blob: 2fd794f76c63899d547ff8738661f9d008d20070 [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
Jason Jina63ce952007-07-06 08:34:56 +0800425 /* Decode the configuration register values for the register we wish to
426 * access
427 */
428 regOffset += (_BE_env.configAddress & 0xFF);
429 function = (_BE_env.configAddress >> 8) & 0x7;
430 device = (_BE_env.configAddress >> 11) & 0x1F;
431 bus = (_BE_env.configAddress >> 16) & 0xFF;
432
433 /* Ignore accesses to all devices other than the one we're POSTing */
434 if ((function == _BE_env.vgaInfo.function) &&
435 (device == _BE_env.vgaInfo.device) &&
436 (bus == _BE_env.vgaInfo.bus)) {
437 switch (func) {
438 case REG_READ_BYTE:
439 pci_read_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
440 &val8);
441 return val8;
442 case REG_READ_WORD:
443 pci_read_config_word(_BE_env.vgaInfo.pcidev, regOffset,
444 &val16);
445 return val16;
446 case REG_READ_DWORD:
447 pci_read_config_dword(_BE_env.vgaInfo.pcidev, regOffset,
448 &val32);
449 return val32;
450 case REG_WRITE_BYTE:
451 pci_write_config_byte(_BE_env.vgaInfo.pcidev, regOffset,
452 value);
453
454 return 0;
455 case REG_WRITE_WORD:
456 pci_write_config_word(_BE_env.vgaInfo.pcidev, regOffset,
457 value);
458
459 return 0;
460 case REG_WRITE_DWORD:
461 pci_write_config_dword(_BE_env.vgaInfo.pcidev,
462 regOffset, value);
463
464 return 0;
465 }
466 }
467 return 0;
468#else
469 PCIDeviceInfo pciInfo;
470
471 pciInfo.mech1 = 1;
472 pciInfo.slot.i = 0;
473 pciInfo.slot.p.Function = (_BE_env.configAddress >> 8) & 0x7;
474 pciInfo.slot.p.Device = (_BE_env.configAddress >> 11) & 0x1F;
475 pciInfo.slot.p.Bus = (_BE_env.configAddress >> 16) & 0xFF;
476 pciInfo.slot.p.Enable = 1;
477
478 /* Ignore accesses to all devices other than the one we're POSTing */
479 if ((pciInfo.slot.p.Function ==
480 _BE_env.vgaInfo.pciInfo->slot.p.Function)
481 && (pciInfo.slot.p.Device == _BE_env.vgaInfo.pciInfo->slot.p.Device)
482 && (pciInfo.slot.p.Bus == _BE_env.vgaInfo.pciInfo->slot.p.Bus))
483 return PCI_accessReg((_BE_env.configAddress & 0xFF) + regOffset,
484 value, func, &pciInfo);
485 return 0;
486#endif
487}
488
489/****************************************************************************
490PARAMETERS:
491port - Port to read from
492type - Type of access to perform
493
494REMARKS:
495Performs an emulated read from one of the PCI configuration space registers.
496We emulate this using our PCI_accessReg function which will access the PCI
497configuration space registers in a portable fashion.
498****************************************************************************/
499static u32 PCI_inp(int port, int type)
500{
501 switch (type) {
502 case REG_READ_BYTE:
503 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
504 && port <= 0xCFF)
505 return BE_accessReg(port - 0xCFC, 0, REG_READ_BYTE);
506 break;
507 case REG_READ_WORD:
508 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
509 && port <= 0xCFF)
510 return BE_accessReg(port - 0xCFC, 0, REG_READ_WORD);
511 break;
512 case REG_READ_DWORD:
513 if (port == 0xCF8)
514 return _BE_env.configAddress;
515 else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
516 return BE_accessReg(0, 0, REG_READ_DWORD);
517 break;
518 }
519 return 0;
520}
521
522/****************************************************************************
523PARAMETERS:
524port - Port to write to
525type - Type of access to perform
526
527REMARKS:
528Performs an emulated write to one of the PCI control registers.
529****************************************************************************/
530static void PCI_outp(int port, u32 val, int type)
531{
532 switch (type) {
533 case REG_WRITE_BYTE:
534 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
535 && port <= 0xCFF)
536 BE_accessReg(port - 0xCFC, val, REG_WRITE_BYTE);
537 break;
538 case REG_WRITE_WORD:
539 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
540 && port <= 0xCFF)
541 BE_accessReg(port - 0xCFC, val, REG_WRITE_WORD);
542 break;
543 case REG_WRITE_DWORD:
544 if (port == 0xCF8)
545 {
546 _BE_env.configAddress = val & 0x80FFFFFC;
547 }
548 else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
549 BE_accessReg(0, val, REG_WRITE_DWORD);
550 break;
551 }
552}
553
554#endif
555
556/****************************************************************************
557PARAMETERS:
558port - Port to write to
559
560RETURNS:
561Value read from the I/O port
562
563REMARKS:
564Performs an emulated 8-bit read from an I/O port. We handle special cases
565that we need to emulate in here, and fall through to reflecting the write
566through to the real hardware if we don't need to special case it.
567****************************************************************************/
568u8 X86API BE_inb(X86EMU_pioAddr port)
569{
570 u8 val = 0;
571
Simon Glass89172162014-11-14 20:56:39 -0700572#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800573 if (IS_VGA_PORT(port)){
574 /*seems reading port 0x3c3 return the high 16 bit of io port*/
575 if(port == 0x3c3)
576 val = LOG_inpb(port);
577 else
578 val = VGA_inpb(port);
579 }
580 else if (IS_TIMER_PORT(port))
581 DB(printf("Can not interept TIMER port now!\n");)
582 else if (IS_SPKR_PORT(port))
583 DB(printf("Can not interept SPEAKER port now!\n");)
584 else if (IS_CMOS_PORT(port))
585 DB(printf("Can not interept CMOS port now!\n");)
586 else if (IS_PCI_PORT(port))
587 val = PCI_inp(port, REG_READ_BYTE);
588 else if (port < 0x100) {
589 DB(printf("WARN: INVALID inb.%04X -> %02X\n", (u16) port, val);)
590 val = LOG_inpb(port);
591 } else
592#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700593 {
594 debug_io("inb.%04X -> ", (u16) port);
Jason Jina63ce952007-07-06 08:34:56 +0800595 val = LOG_inpb(port);
Simon Glassd8414fc2014-11-14 20:56:42 -0700596 debug_io("%02X\n", val);
597 }
598
Jason Jina63ce952007-07-06 08:34:56 +0800599 return val;
600}
601
602/****************************************************************************
603PARAMETERS:
604port - Port to write to
605
606RETURNS:
607Value read from the I/O port
608
609REMARKS:
610Performs an emulated 16-bit read from an I/O port. We handle special cases
611that we need to emulate in here, and fall through to reflecting the write
612through to the real hardware if we don't need to special case it.
613****************************************************************************/
614u16 X86API BE_inw(X86EMU_pioAddr port)
615{
616 u16 val = 0;
617
Simon Glass89172162014-11-14 20:56:39 -0700618#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800619 if (IS_PCI_PORT(port))
620 val = PCI_inp(port, REG_READ_WORD);
621 else if (port < 0x100) {
622 DB(printf("WARN: Maybe INVALID inw.%04X -> %04X\n", (u16) port, val);)
623 val = LOG_inpw(port);
624 } else
625#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700626 {
627 debug_io("inw.%04X -> ", (u16) port);
Jason Jina63ce952007-07-06 08:34:56 +0800628 val = LOG_inpw(port);
Simon Glassd8414fc2014-11-14 20:56:42 -0700629 debug_io("%04X\n", val);
630 }
631
Jason Jina63ce952007-07-06 08:34:56 +0800632 return val;
633}
634
635/****************************************************************************
636PARAMETERS:
637port - Port to write to
638
639RETURNS:
640Value read from the I/O port
641
642REMARKS:
643Performs an emulated 32-bit read from an I/O port. We handle special cases
644that we need to emulate in here, and fall through to reflecting the write
645through to the real hardware if we don't need to special case it.
646****************************************************************************/
647u32 X86API BE_inl(X86EMU_pioAddr port)
648{
649 u32 val = 0;
650
Simon Glass89172162014-11-14 20:56:39 -0700651#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800652 if (IS_PCI_PORT(port))
653 val = PCI_inp(port, REG_READ_DWORD);
654 else if (port < 0x100) {
655 val = LOG_inpd(port);
656 } else
657#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700658 {
659 debug_io("inl.%04X -> ", (u16) port);
Jason Jina63ce952007-07-06 08:34:56 +0800660 val = LOG_inpd(port);
Simon Glassd8414fc2014-11-14 20:56:42 -0700661 debug_io("%08X\n", val);
662 }
663
Jason Jina63ce952007-07-06 08:34:56 +0800664 return val;
665}
666
667/****************************************************************************
668PARAMETERS:
669port - Port to write to
670val - Value to write to port
671
672REMARKS:
673Performs an emulated 8-bit write to an I/O port. We handle special cases
674that we need to emulate in here, and fall through to reflecting the write
675through to the real hardware if we don't need to special case it.
676****************************************************************************/
677void X86API BE_outb(X86EMU_pioAddr port, u8 val)
678{
Simon Glass89172162014-11-14 20:56:39 -0700679#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800680 if (IS_VGA_PORT(port))
681 VGA_outpb(port, val);
682 else if (IS_TIMER_PORT(port))
683 DB(printf("Can not interept TIMER port now!\n");)
684 else if (IS_SPKR_PORT(port))
685 DB(printf("Can not interept SPEAKER port now!\n");)
686 else if (IS_CMOS_PORT(port))
687 DB(printf("Can not interept CMOS port now!\n");)
688 else if (IS_PCI_PORT(port))
689 PCI_outp(port, val, REG_WRITE_BYTE);
690 else if (port < 0x100) {
691 DB(printf("WARN:Maybe INVALID outb.%04X <- %02X\n", (u16) port, val);)
692 LOG_outpb(port, val);
693 } else
694#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700695 {
696 debug_io("outb.%04X <- %02X", (u16) port, val);
Jason Jina63ce952007-07-06 08:34:56 +0800697 LOG_outpb(port, val);
Simon Glassd8414fc2014-11-14 20:56:42 -0700698 debug_io("\n");
699 }
Jason Jina63ce952007-07-06 08:34:56 +0800700}
701
702/****************************************************************************
703PARAMETERS:
704port - Port to write to
705val - Value to write to port
706
707REMARKS:
708Performs an emulated 16-bit write to an I/O port. We handle special cases
709that we need to emulate in here, and fall through to reflecting the write
710through to the real hardware if we don't need to special case it.
711****************************************************************************/
712void X86API BE_outw(X86EMU_pioAddr port, u16 val)
713{
Simon Glass89172162014-11-14 20:56:39 -0700714#if !defined(CONFIG_X86EMU_RAW_IO)
Simon Glassd8414fc2014-11-14 20:56:42 -0700715 if (IS_VGA_PORT(port)) {
716 VGA_outpb(port, val);
717 VGA_outpb(port + 1, val >> 8);
718 } else if (IS_PCI_PORT(port)) {
719 PCI_outp(port, val, REG_WRITE_WORD);
720 } else if (port < 0x100) {
721 DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16)port,
722 val);)
723 LOG_outpw(port, val);
724 } else
Jason Jina63ce952007-07-06 08:34:56 +0800725#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700726 {
727 debug_io("outw.%04X <- %04X", (u16) port, val);
728 LOG_outpw(port, val);
729 debug_io("\n");
730 }
Jason Jina63ce952007-07-06 08:34:56 +0800731}
732
733/****************************************************************************
734PARAMETERS:
735port - Port to write to
736val - Value to write to port
737
738REMARKS:
739Performs an emulated 32-bit write to an I/O port. We handle special cases
740that we need to emulate in here, and fall through to reflecting the write
741through to the real hardware if we don't need to special case it.
742****************************************************************************/
743void X86API BE_outl(X86EMU_pioAddr port, u32 val)
744{
Simon Glass89172162014-11-14 20:56:39 -0700745#if !defined(CONFIG_X86EMU_RAW_IO)
Simon Glassacda1cc2014-11-14 20:56:40 -0700746 if (IS_PCI_PORT(port)) {
Jason Jina63ce952007-07-06 08:34:56 +0800747 PCI_outp(port, val, REG_WRITE_DWORD);
Simon Glassacda1cc2014-11-14 20:56:40 -0700748 } else if (port < 0x100) {
Jason Jina63ce952007-07-06 08:34:56 +0800749 DB(printf("WARN: INVALID outl.%04X <- %08X\n", (u16) port,val);)
750 LOG_outpd(port, val);
751 } else
752#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700753 {
754 debug_io("outl.%04X <- %08X", (u16) port, val);
Jason Jina63ce952007-07-06 08:34:56 +0800755 LOG_outpd(port, val);
Simon Glassd8414fc2014-11-14 20:56:42 -0700756 debug_io("\n");
757 }
Jason Jina63ce952007-07-06 08:34:56 +0800758}