blob: 690fb5a4d7b304f85e7410ad0428e70352dd3ddb [file] [log] [blame]
Jason Jina63ce952007-07-06 08:34:56 +08001/****************************************************************************
2*
3* BIOS emulator and interface
4* to Realmode X86 Emulator Library
5*
6* ========================================================================
7*
Kumar Gala6a6d9482009-07-28 21:49:52 -05008* Copyright (C) 2007 Freescale Semiconductor, Inc.
Jason Jina63ce952007-07-06 08:34:56 +08009* Jason Jin<Jason.jin@freescale.com>
10*
11* Copyright (C) 1991-2004 SciTech Software, Inc. All rights reserved.
12*
13* This file may be distributed and/or modified under the terms of the
14* GNU General Public License version 2.0 as published by the Free
15* Software Foundation and appearing in the file LICENSE.GPL included
16* in the packaging of this file.
17*
18* Licensees holding a valid Commercial License for this product from
19* SciTech Software, Inc. may use this file in accordance with the
20* Commercial License Agreement provided with the Software.
21*
22* This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
23* THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24* PURPOSE.
25*
26* See http://www.scitechsoft.com/license/ for information about
27* the licensing options available and how to purchase a Commercial
28* License Agreement.
29*
30* Contact license@scitechsoft.com if any conditions of this licensing
31* are not clear to you, or you have questions about licensing options.
32*
33* ========================================================================
34*
35* Language: ANSI C
36* Environment: Any
37* Developer: Kendall Bennett
38*
39* Description: This file includes BIOS emulator I/O and memory access
40* functions.
41*
42* Jason ported this file to u-boot to run the ATI video card
43* BIOS in u-boot. Removed some emulate functions such as the
44* timer port access. Made all the VGA port except reading 0x3c3
45* be emulated. Seems like reading 0x3c3 should return the high
46* 16 bit of the io port.
47*
48****************************************************************************/
49
Linus Walleij9b6a5af2013-04-01 22:14:14 +000050#define __io
Simon Glassa9b9ef42014-12-10 20:12:01 -070051#include <asm/io.h>
Jason Jina63ce952007-07-06 08:34:56 +080052#include "biosemui.h"
53
54/*------------------------- Global Variables ------------------------------*/
55
Simon Glass89172162014-11-14 20:56:39 -070056#ifndef CONFIG_X86EMU_RAW_IO
Jason Jina63ce952007-07-06 08:34:56 +080057static char *BE_biosDate = "08/14/99";
58static u8 BE_model = 0xFC;
59static u8 BE_submodel = 0x00;
60#endif
61
Simon Glassd8414fc2014-11-14 20:56:42 -070062#undef DEBUG_IO_ACCESS
63
64#ifdef DEBUG_IO_ACCESS
65#define debug_io(fmt, ...) printf(fmt, ##__VA_ARGS__)
66#else
67#define debug_io(x, b...)
68#endif
69
Jason Jina63ce952007-07-06 08:34:56 +080070/*----------------------------- Implementation ----------------------------*/
71
72/****************************************************************************
73PARAMETERS:
74addr - Emulator memory address to convert
75
76RETURNS:
77Actual memory address to read or write the data
78
79REMARKS:
80This function converts an emulator memory address in a 32-bit range to
81a real memory address that we wish to access. It handles splitting up the
82memory address space appropriately to access the emulator BIOS image, video
83memory and system BIOS etc.
84****************************************************************************/
85static u8 *BE_memaddr(u32 addr)
86{
87 if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
88 return (u8*)(_BE_env.biosmem_base + addr - 0xC0000);
89 } else if (addr > _BE_env.biosmem_limit && addr < 0xD0000) {
Simon Glass89172162014-11-14 20:56:39 -070090 DB(printf("BE_memaddr: address %#lx may be invalid!\n",
91 (ulong)addr);)
92 return (u8 *)M.mem_base;
Jason Jina63ce952007-07-06 08:34:56 +080093 } else if (addr >= 0xA0000 && addr <= 0xBFFFF) {
94 return (u8*)(_BE_env.busmem_base + addr - 0xA0000);
95 }
Simon Glass89172162014-11-14 20:56:39 -070096#ifdef CONFIG_X86EMU_RAW_IO
Jason Jina63ce952007-07-06 08:34:56 +080097 else if (addr >= 0xD0000 && addr <= 0xFFFFF) {
98 /* We map the real System BIOS directly on real PC's */
Simon Glass89172162014-11-14 20:56:39 -070099 DB(printf("BE_memaddr: System BIOS address %#lx\n",
100 (ulong)addr);)
101 return (u8 *)_BE_env.busmem_base + addr - 0xA0000;
Jason Jina63ce952007-07-06 08:34:56 +0800102 }
103#else
104 else if (addr >= 0xFFFF5 && addr < 0xFFFFE) {
105 /* Return a faked BIOS date string for non-x86 machines */
Simon Glassd8414fc2014-11-14 20:56:42 -0700106 debug_io("BE_memaddr - Returning BIOS date\n");
Wolfgang Denk92254112007-11-18 16:36:27 +0100107 return (u8 *)(BE_biosDate + addr - 0xFFFF5);
Jason Jina63ce952007-07-06 08:34:56 +0800108 } else if (addr == 0xFFFFE) {
109 /* Return system model identifier for non-x86 machines */
Simon Glassd8414fc2014-11-14 20:56:42 -0700110 debug_io("BE_memaddr - Returning model\n");
Jason Jina63ce952007-07-06 08:34:56 +0800111 return &BE_model;
112 } else if (addr == 0xFFFFF) {
113 /* Return system submodel identifier for non-x86 machines */
Simon Glassd8414fc2014-11-14 20:56:42 -0700114 debug_io("BE_memaddr - Returning submodel\n");
Jason Jina63ce952007-07-06 08:34:56 +0800115 return &BE_submodel;
116 }
117#endif
118 else if (addr > M.mem_size - 1) {
119 HALT_SYS();
Simon Glass89172162014-11-14 20:56:39 -0700120 return (u8 *)M.mem_base;
Jason Jina63ce952007-07-06 08:34:56 +0800121 }
122
Simon Glass89172162014-11-14 20:56:39 -0700123 return (u8 *)(M.mem_base + addr);
Jason Jina63ce952007-07-06 08:34:56 +0800124}
125
126/****************************************************************************
127PARAMETERS:
128addr - Emulator memory address to read
129
130RETURNS:
131Byte value read from emulator memory.
132
133REMARKS:
134Reads a byte value from the emulator memory. We have three distinct memory
135regions that are handled differently, which this function handles.
136****************************************************************************/
137u8 X86API BE_rdb(u32 addr)
138{
139 if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
140 return 0;
141 else {
142 u8 val = readb_le(BE_memaddr(addr));
143 return val;
144 }
145}
146
147/****************************************************************************
148PARAMETERS:
149addr - Emulator memory address to read
150
151RETURNS:
152Word value read from emulator memory.
153
154REMARKS:
155Reads a word value from the emulator memory. We have three distinct memory
156regions that are handled differently, which this function handles.
157****************************************************************************/
158u16 X86API BE_rdw(u32 addr)
159{
160 if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
161 return 0;
162 else {
163 u8 *base = BE_memaddr(addr);
164 u16 val = readw_le(base);
165 return val;
166 }
167}
168
169/****************************************************************************
170PARAMETERS:
171addr - Emulator memory address to read
172
173RETURNS:
174Long value read from emulator memory.
175
176REMARKS:
177Reads a 32-bit value from the emulator memory. We have three distinct memory
178regions that are handled differently, which this function handles.
179****************************************************************************/
180u32 X86API BE_rdl(u32 addr)
181{
182 if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
183 return 0;
184 else {
185 u8 *base = BE_memaddr(addr);
186 u32 val = readl_le(base);
187 return val;
188 }
189}
190
191/****************************************************************************
192PARAMETERS:
193addr - Emulator memory address to read
194val - Value to store
195
196REMARKS:
197Writes a byte value to emulator memory. We have three distinct memory
198regions that are handled differently, which this function handles.
199****************************************************************************/
200void X86API BE_wrb(u32 addr, u8 val)
201{
202 if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
203 writeb_le(BE_memaddr(addr), val);
204 }
205}
206
207/****************************************************************************
208PARAMETERS:
209addr - Emulator memory address to read
210val - Value to store
211
212REMARKS:
213Writes a word value to emulator memory. We have three distinct memory
214regions that are handled differently, which this function handles.
215****************************************************************************/
216void X86API BE_wrw(u32 addr, u16 val)
217{
218 if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
219 u8 *base = BE_memaddr(addr);
220 writew_le(base, val);
221
222 }
223}
224
225/****************************************************************************
226PARAMETERS:
227addr - Emulator memory address to read
228val - Value to store
229
230REMARKS:
231Writes a 32-bit value to emulator memory. We have three distinct memory
232regions that are handled differently, which this function handles.
233****************************************************************************/
234void X86API BE_wrl(u32 addr, u32 val)
235{
236 if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
237 u8 *base = BE_memaddr(addr);
238 writel_le(base, val);
239 }
240}
241
Simon Glass89172162014-11-14 20:56:39 -0700242#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800243
244/* For Non-Intel machines we may need to emulate some I/O port accesses that
245 * the BIOS may try to access, such as the PCI config registers.
246 */
247
248#define IS_TIMER_PORT(port) (0x40 <= port && port <= 0x43)
249#define IS_CMOS_PORT(port) (0x70 <= port && port <= 0x71)
250/*#define IS_VGA_PORT(port) (_BE_env.emulateVGA && 0x3C0 <= port && port <= 0x3DA)*/
251#define IS_VGA_PORT(port) (0x3C0 <= port && port <= 0x3DA)
252#define IS_PCI_PORT(port) (0xCF8 <= port && port <= 0xCFF)
253#define IS_SPKR_PORT(port) (port == 0x61)
254
255/****************************************************************************
256PARAMETERS:
257port - Port to read from
258type - Type of access to perform
259
260REMARKS:
261Performs an emulated read from the Standard VGA I/O ports. If the target
262hardware does not support mapping the VGA I/O and memory (such as some
263PowerPC systems), we emulate the VGA so that the BIOS will still be able to
264set NonVGA display modes such as on ATI hardware.
265****************************************************************************/
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200266static u8 VGA_inpb (const int port)
Jason Jina63ce952007-07-06 08:34:56 +0800267{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200268 u8 val = 0xff;
Jason Jina63ce952007-07-06 08:34:56 +0800269
Simon Glassd8414fc2014-11-14 20:56:42 -0700270 debug_io("vga_inb.%04X -> ", (u16) port);
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200271 switch (port) {
272 case 0x3C0:
273 /* 3C0 has funky characteristics because it can act as either
274 a data register or index register depending on the state
275 of an internal flip flop in the hardware. Hence we have
276 to emulate that functionality in here. */
277 if (_BE_env.flipFlop3C0 == 0) {
278 /* Access 3C0 as index register */
279 val = _BE_env.emu3C0;
280 } else {
281 /* Access 3C0 as data register */
282 if (_BE_env.emu3C0 < ATT_C)
283 val = _BE_env.emu3C1[_BE_env.emu3C0];
284 }
285 _BE_env.flipFlop3C0 ^= 1;
286 break;
287 case 0x3C1:
288 if (_BE_env.emu3C0 < ATT_C)
289 return _BE_env.emu3C1[_BE_env.emu3C0];
290 break;
291 case 0x3CC:
292 return _BE_env.emu3C2;
293 case 0x3C4:
294 return _BE_env.emu3C4;
295 case 0x3C5:
296 if (_BE_env.emu3C4 < ATT_C)
297 return _BE_env.emu3C5[_BE_env.emu3C4];
298 break;
299 case 0x3C6:
300 return _BE_env.emu3C6;
301 case 0x3C7:
302 return _BE_env.emu3C7;
303 case 0x3C8:
304 return _BE_env.emu3C8;
305 case 0x3C9:
306 if (_BE_env.emu3C7 < PAL_C)
307 return _BE_env.emu3C9[_BE_env.emu3C7++];
308 break;
309 case 0x3CE:
310 return _BE_env.emu3CE;
311 case 0x3CF:
312 if (_BE_env.emu3CE < GRA_C)
313 return _BE_env.emu3CF[_BE_env.emu3CE];
314 break;
315 case 0x3D4:
316 if (_BE_env.emu3C2 & 0x1)
317 return _BE_env.emu3D4;
318 break;
319 case 0x3D5:
320 if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
321 return _BE_env.emu3D5[_BE_env.emu3D4];
322 break;
323 case 0x3DA:
324 _BE_env.flipFlop3C0 = 0;
325 val = _BE_env.emu3DA;
326 _BE_env.emu3DA ^= 0x9;
327 break;
328 }
329 return val;
Jason Jina63ce952007-07-06 08:34:56 +0800330}
331
332/****************************************************************************
333PARAMETERS:
334port - Port to write to
335type - Type of access to perform
336
337REMARKS:
338Performs an emulated write to one of the 8253 timer registers. For now
339we only emulate timer 0 which is the only timer that the BIOS code appears
340to use.
341****************************************************************************/
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200342static void VGA_outpb (int port, u8 val)
Jason Jina63ce952007-07-06 08:34:56 +0800343{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200344 switch (port) {
345 case 0x3C0:
346 /* 3C0 has funky characteristics because it can act as either
347 a data register or index register depending on the state
348 of an internal flip flop in the hardware. Hence we have
349 to emulate that functionality in here. */
350 if (_BE_env.flipFlop3C0 == 0) {
351 /* Access 3C0 as index register */
352 _BE_env.emu3C0 = val;
353 } else {
354 /* Access 3C0 as data register */
355 if (_BE_env.emu3C0 < ATT_C)
356 _BE_env.emu3C1[_BE_env.emu3C0] = val;
357 }
358 _BE_env.flipFlop3C0 ^= 1;
359 break;
360 case 0x3C2:
361 _BE_env.emu3C2 = val;
362 break;
363 case 0x3C4:
364 _BE_env.emu3C4 = val;
365 break;
366 case 0x3C5:
367 if (_BE_env.emu3C4 < ATT_C)
368 _BE_env.emu3C5[_BE_env.emu3C4] = val;
369 break;
370 case 0x3C6:
371 _BE_env.emu3C6 = val;
372 break;
373 case 0x3C7:
374 _BE_env.emu3C7 = (int) val *3;
375
376 break;
377 case 0x3C8:
378 _BE_env.emu3C8 = (int) val *3;
379
380 break;
381 case 0x3C9:
382 if (_BE_env.emu3C8 < PAL_C)
383 _BE_env.emu3C9[_BE_env.emu3C8++] = val;
384 break;
385 case 0x3CE:
386 _BE_env.emu3CE = val;
387 break;
388 case 0x3CF:
389 if (_BE_env.emu3CE < GRA_C)
390 _BE_env.emu3CF[_BE_env.emu3CE] = val;
391 break;
392 case 0x3D4:
393 if (_BE_env.emu3C2 & 0x1)
394 _BE_env.emu3D4 = val;
395 break;
396 case 0x3D5:
397 if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
398 _BE_env.emu3D5[_BE_env.emu3D4] = val;
399 break;
400 }
Jason Jina63ce952007-07-06 08:34:56 +0800401}
402
403/****************************************************************************
404PARAMETERS:
405regOffset - Offset into register space for non-DWORD accesses
406value - Value to write to register for PCI_WRITE_* operations
407func - Function to perform (PCIAccessRegFlags)
408
409RETURNS:
410Value read from configuration register for PCI_READ_* operations
411
412REMARKS:
413Accesses a PCI configuration space register by decoding the value currently
414stored in the _BE_env.configAddress variable and passing it through to the
415portable PCI_accessReg function.
416****************************************************************************/
417static u32 BE_accessReg(int regOffset, u32 value, int func)
418{
419#ifdef __KERNEL__
420 int function, device, bus;
421 u8 val8;
422 u16 val16;
423 u32 val32;
424
425
426 /* Decode the configuration register values for the register we wish to
427 * access
428 */
429 regOffset += (_BE_env.configAddress & 0xFF);
430 function = (_BE_env.configAddress >> 8) & 0x7;
431 device = (_BE_env.configAddress >> 11) & 0x1F;
432 bus = (_BE_env.configAddress >> 16) & 0xFF;
433
434 /* Ignore accesses to all devices other than the one we're POSTing */
435 if ((function == _BE_env.vgaInfo.function) &&
436 (device == _BE_env.vgaInfo.device) &&
437 (bus == _BE_env.vgaInfo.bus)) {
438 switch (func) {
439 case REG_READ_BYTE:
440 pci_read_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
441 &val8);
442 return val8;
443 case REG_READ_WORD:
444 pci_read_config_word(_BE_env.vgaInfo.pcidev, regOffset,
445 &val16);
446 return val16;
447 case REG_READ_DWORD:
448 pci_read_config_dword(_BE_env.vgaInfo.pcidev, regOffset,
449 &val32);
450 return val32;
451 case REG_WRITE_BYTE:
452 pci_write_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
453 value);
454
455 return 0;
456 case REG_WRITE_WORD:
457 pci_write_config_word(_BE_env.vgaInfo.pcidev, regOffset,
458 value);
459
460 return 0;
461 case REG_WRITE_DWORD:
462 pci_write_config_dword(_BE_env.vgaInfo.pcidev,
463 regOffset, value);
464
465 return 0;
466 }
467 }
468 return 0;
469#else
470 PCIDeviceInfo pciInfo;
471
472 pciInfo.mech1 = 1;
473 pciInfo.slot.i = 0;
474 pciInfo.slot.p.Function = (_BE_env.configAddress >> 8) & 0x7;
475 pciInfo.slot.p.Device = (_BE_env.configAddress >> 11) & 0x1F;
476 pciInfo.slot.p.Bus = (_BE_env.configAddress >> 16) & 0xFF;
477 pciInfo.slot.p.Enable = 1;
478
479 /* Ignore accesses to all devices other than the one we're POSTing */
480 if ((pciInfo.slot.p.Function ==
481 _BE_env.vgaInfo.pciInfo->slot.p.Function)
482 && (pciInfo.slot.p.Device == _BE_env.vgaInfo.pciInfo->slot.p.Device)
483 && (pciInfo.slot.p.Bus == _BE_env.vgaInfo.pciInfo->slot.p.Bus))
484 return PCI_accessReg((_BE_env.configAddress & 0xFF) + regOffset,
485 value, func, &pciInfo);
486 return 0;
487#endif
488}
489
490/****************************************************************************
491PARAMETERS:
492port - Port to read from
493type - Type of access to perform
494
495REMARKS:
496Performs an emulated read from one of the PCI configuration space registers.
497We emulate this using our PCI_accessReg function which will access the PCI
498configuration space registers in a portable fashion.
499****************************************************************************/
500static u32 PCI_inp(int port, int type)
501{
502 switch (type) {
503 case REG_READ_BYTE:
504 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
505 && port <= 0xCFF)
506 return BE_accessReg(port - 0xCFC, 0, REG_READ_BYTE);
507 break;
508 case REG_READ_WORD:
509 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
510 && port <= 0xCFF)
511 return BE_accessReg(port - 0xCFC, 0, REG_READ_WORD);
512 break;
513 case REG_READ_DWORD:
514 if (port == 0xCF8)
515 return _BE_env.configAddress;
516 else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
517 return BE_accessReg(0, 0, REG_READ_DWORD);
518 break;
519 }
520 return 0;
521}
522
523/****************************************************************************
524PARAMETERS:
525port - Port to write to
526type - Type of access to perform
527
528REMARKS:
529Performs an emulated write to one of the PCI control registers.
530****************************************************************************/
531static void PCI_outp(int port, u32 val, int type)
532{
533 switch (type) {
534 case REG_WRITE_BYTE:
535 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
536 && port <= 0xCFF)
537 BE_accessReg(port - 0xCFC, val, REG_WRITE_BYTE);
538 break;
539 case REG_WRITE_WORD:
540 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
541 && port <= 0xCFF)
542 BE_accessReg(port - 0xCFC, val, REG_WRITE_WORD);
543 break;
544 case REG_WRITE_DWORD:
545 if (port == 0xCF8)
546 {
547 _BE_env.configAddress = val & 0x80FFFFFC;
548 }
549 else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
550 BE_accessReg(0, val, REG_WRITE_DWORD);
551 break;
552 }
553}
554
555#endif
556
557/****************************************************************************
558PARAMETERS:
559port - Port to write to
560
561RETURNS:
562Value read from the I/O port
563
564REMARKS:
565Performs an emulated 8-bit read from an I/O port. We handle special cases
566that we need to emulate in here, and fall through to reflecting the write
567through to the real hardware if we don't need to special case it.
568****************************************************************************/
569u8 X86API BE_inb(X86EMU_pioAddr port)
570{
571 u8 val = 0;
572
Simon Glass89172162014-11-14 20:56:39 -0700573#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800574 if (IS_VGA_PORT(port)){
575 /*seems reading port 0x3c3 return the high 16 bit of io port*/
576 if(port == 0x3c3)
577 val = LOG_inpb(port);
578 else
579 val = VGA_inpb(port);
580 }
581 else if (IS_TIMER_PORT(port))
582 DB(printf("Can not interept TIMER port now!\n");)
583 else if (IS_SPKR_PORT(port))
584 DB(printf("Can not interept SPEAKER port now!\n");)
585 else if (IS_CMOS_PORT(port))
586 DB(printf("Can not interept CMOS port now!\n");)
587 else if (IS_PCI_PORT(port))
588 val = PCI_inp(port, REG_READ_BYTE);
589 else if (port < 0x100) {
590 DB(printf("WARN: INVALID inb.%04X -> %02X\n", (u16) port, val);)
591 val = LOG_inpb(port);
592 } else
593#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700594 {
595 debug_io("inb.%04X -> ", (u16) port);
Jason Jina63ce952007-07-06 08:34:56 +0800596 val = LOG_inpb(port);
Simon Glassd8414fc2014-11-14 20:56:42 -0700597 debug_io("%02X\n", val);
598 }
599
Jason Jina63ce952007-07-06 08:34:56 +0800600 return val;
601}
602
603/****************************************************************************
604PARAMETERS:
605port - Port to write to
606
607RETURNS:
608Value read from the I/O port
609
610REMARKS:
611Performs an emulated 16-bit read from an I/O port. We handle special cases
612that we need to emulate in here, and fall through to reflecting the write
613through to the real hardware if we don't need to special case it.
614****************************************************************************/
615u16 X86API BE_inw(X86EMU_pioAddr port)
616{
617 u16 val = 0;
618
Simon Glass89172162014-11-14 20:56:39 -0700619#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800620 if (IS_PCI_PORT(port))
621 val = PCI_inp(port, REG_READ_WORD);
622 else if (port < 0x100) {
623 DB(printf("WARN: Maybe INVALID inw.%04X -> %04X\n", (u16) port, val);)
624 val = LOG_inpw(port);
625 } else
626#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700627 {
628 debug_io("inw.%04X -> ", (u16) port);
Jason Jina63ce952007-07-06 08:34:56 +0800629 val = LOG_inpw(port);
Simon Glassd8414fc2014-11-14 20:56:42 -0700630 debug_io("%04X\n", val);
631 }
632
Jason Jina63ce952007-07-06 08:34:56 +0800633 return val;
634}
635
636/****************************************************************************
637PARAMETERS:
638port - Port to write to
639
640RETURNS:
641Value read from the I/O port
642
643REMARKS:
644Performs an emulated 32-bit read from an I/O port. We handle special cases
645that we need to emulate in here, and fall through to reflecting the write
646through to the real hardware if we don't need to special case it.
647****************************************************************************/
648u32 X86API BE_inl(X86EMU_pioAddr port)
649{
650 u32 val = 0;
651
Simon Glass89172162014-11-14 20:56:39 -0700652#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800653 if (IS_PCI_PORT(port))
654 val = PCI_inp(port, REG_READ_DWORD);
655 else if (port < 0x100) {
656 val = LOG_inpd(port);
657 } else
658#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700659 {
660 debug_io("inl.%04X -> ", (u16) port);
Jason Jina63ce952007-07-06 08:34:56 +0800661 val = LOG_inpd(port);
Simon Glassd8414fc2014-11-14 20:56:42 -0700662 debug_io("%08X\n", val);
663 }
664
Jason Jina63ce952007-07-06 08:34:56 +0800665 return val;
666}
667
668/****************************************************************************
669PARAMETERS:
670port - Port to write to
671val - Value to write to port
672
673REMARKS:
674Performs an emulated 8-bit write to an I/O port. We handle special cases
675that we need to emulate in here, and fall through to reflecting the write
676through to the real hardware if we don't need to special case it.
677****************************************************************************/
678void X86API BE_outb(X86EMU_pioAddr port, u8 val)
679{
Simon Glass89172162014-11-14 20:56:39 -0700680#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800681 if (IS_VGA_PORT(port))
682 VGA_outpb(port, val);
683 else if (IS_TIMER_PORT(port))
684 DB(printf("Can not interept TIMER port now!\n");)
685 else if (IS_SPKR_PORT(port))
686 DB(printf("Can not interept SPEAKER port now!\n");)
687 else if (IS_CMOS_PORT(port))
688 DB(printf("Can not interept CMOS port now!\n");)
689 else if (IS_PCI_PORT(port))
690 PCI_outp(port, val, REG_WRITE_BYTE);
691 else if (port < 0x100) {
692 DB(printf("WARN:Maybe INVALID outb.%04X <- %02X\n", (u16) port, val);)
693 LOG_outpb(port, val);
694 } else
695#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700696 {
697 debug_io("outb.%04X <- %02X", (u16) port, val);
Jason Jina63ce952007-07-06 08:34:56 +0800698 LOG_outpb(port, val);
Simon Glassd8414fc2014-11-14 20:56:42 -0700699 debug_io("\n");
700 }
Jason Jina63ce952007-07-06 08:34:56 +0800701}
702
703/****************************************************************************
704PARAMETERS:
705port - Port to write to
706val - Value to write to port
707
708REMARKS:
709Performs an emulated 16-bit write to an I/O port. We handle special cases
710that we need to emulate in here, and fall through to reflecting the write
711through to the real hardware if we don't need to special case it.
712****************************************************************************/
713void X86API BE_outw(X86EMU_pioAddr port, u16 val)
714{
Simon Glass89172162014-11-14 20:56:39 -0700715#if !defined(CONFIG_X86EMU_RAW_IO)
Simon Glassd8414fc2014-11-14 20:56:42 -0700716 if (IS_VGA_PORT(port)) {
717 VGA_outpb(port, val);
718 VGA_outpb(port + 1, val >> 8);
719 } else if (IS_PCI_PORT(port)) {
720 PCI_outp(port, val, REG_WRITE_WORD);
721 } else if (port < 0x100) {
722 DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16)port,
723 val);)
724 LOG_outpw(port, val);
725 } else
Jason Jina63ce952007-07-06 08:34:56 +0800726#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700727 {
728 debug_io("outw.%04X <- %04X", (u16) port, val);
729 LOG_outpw(port, val);
730 debug_io("\n");
731 }
Jason Jina63ce952007-07-06 08:34:56 +0800732}
733
734/****************************************************************************
735PARAMETERS:
736port - Port to write to
737val - Value to write to port
738
739REMARKS:
740Performs an emulated 32-bit write to an I/O port. We handle special cases
741that we need to emulate in here, and fall through to reflecting the write
742through to the real hardware if we don't need to special case it.
743****************************************************************************/
744void X86API BE_outl(X86EMU_pioAddr port, u32 val)
745{
Simon Glass89172162014-11-14 20:56:39 -0700746#if !defined(CONFIG_X86EMU_RAW_IO)
Simon Glassacda1cc2014-11-14 20:56:40 -0700747 if (IS_PCI_PORT(port)) {
Jason Jina63ce952007-07-06 08:34:56 +0800748 PCI_outp(port, val, REG_WRITE_DWORD);
Simon Glassacda1cc2014-11-14 20:56:40 -0700749 } else if (port < 0x100) {
Jason Jina63ce952007-07-06 08:34:56 +0800750 DB(printf("WARN: INVALID outl.%04X <- %08X\n", (u16) port,val);)
751 LOG_outpd(port, val);
752 } else
753#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700754 {
755 debug_io("outl.%04X <- %08X", (u16) port, val);
Jason Jina63ce952007-07-06 08:34:56 +0800756 LOG_outpd(port, val);
Simon Glassd8414fc2014-11-14 20:56:42 -0700757 debug_io("\n");
758 }
Jason Jina63ce952007-07-06 08:34:56 +0800759}