blob: 23392d3c86e3632bb63ab1be4dd9394cf22e0754 [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>
Yuri Zaporozhets52234d62024-10-30 20:38:20 +010052#include <pci.h>
Jason Jina63ce952007-07-06 08:34:56 +080053#include "biosemui.h"
54
55/*------------------------- Global Variables ------------------------------*/
56
Simon Glass89172162014-11-14 20:56:39 -070057#ifndef CONFIG_X86EMU_RAW_IO
Jason Jina63ce952007-07-06 08:34:56 +080058static char *BE_biosDate = "08/14/99";
59static u8 BE_model = 0xFC;
60static u8 BE_submodel = 0x00;
61#endif
62
Simon Glassd8414fc2014-11-14 20:56:42 -070063#undef DEBUG_IO_ACCESS
64
65#ifdef DEBUG_IO_ACCESS
66#define debug_io(fmt, ...) printf(fmt, ##__VA_ARGS__)
67#else
68#define debug_io(x, b...)
69#endif
70
Jason Jina63ce952007-07-06 08:34:56 +080071/*----------------------------- Implementation ----------------------------*/
72
73/****************************************************************************
74PARAMETERS:
75addr - Emulator memory address to convert
76
77RETURNS:
78Actual memory address to read or write the data
79
80REMARKS:
81This function converts an emulator memory address in a 32-bit range to
82a real memory address that we wish to access. It handles splitting up the
83memory address space appropriately to access the emulator BIOS image, video
84memory and system BIOS etc.
85****************************************************************************/
86static u8 *BE_memaddr(u32 addr)
87{
88 if (addr >= 0xC0000 && addr <= _BE_env.biosmem_limit) {
89 return (u8*)(_BE_env.biosmem_base + addr - 0xC0000);
90 } else if (addr > _BE_env.biosmem_limit && addr < 0xD0000) {
Simon Glass89172162014-11-14 20:56:39 -070091 DB(printf("BE_memaddr: address %#lx may be invalid!\n",
92 (ulong)addr);)
93 return (u8 *)M.mem_base;
Jason Jina63ce952007-07-06 08:34:56 +080094 } else if (addr >= 0xA0000 && addr <= 0xBFFFF) {
95 return (u8*)(_BE_env.busmem_base + addr - 0xA0000);
96 }
Simon Glass89172162014-11-14 20:56:39 -070097#ifdef CONFIG_X86EMU_RAW_IO
Jason Jina63ce952007-07-06 08:34:56 +080098 else if (addr >= 0xD0000 && addr <= 0xFFFFF) {
99 /* We map the real System BIOS directly on real PC's */
Simon Glass89172162014-11-14 20:56:39 -0700100 DB(printf("BE_memaddr: System BIOS address %#lx\n",
101 (ulong)addr);)
102 return (u8 *)_BE_env.busmem_base + addr - 0xA0000;
Jason Jina63ce952007-07-06 08:34:56 +0800103 }
104#else
105 else if (addr >= 0xFFFF5 && addr < 0xFFFFE) {
106 /* Return a faked BIOS date string for non-x86 machines */
Simon Glassd8414fc2014-11-14 20:56:42 -0700107 debug_io("BE_memaddr - Returning BIOS date\n");
Wolfgang Denk92254112007-11-18 16:36:27 +0100108 return (u8 *)(BE_biosDate + addr - 0xFFFF5);
Jason Jina63ce952007-07-06 08:34:56 +0800109 } else if (addr == 0xFFFFE) {
110 /* Return system model identifier for non-x86 machines */
Simon Glassd8414fc2014-11-14 20:56:42 -0700111 debug_io("BE_memaddr - Returning model\n");
Jason Jina63ce952007-07-06 08:34:56 +0800112 return &BE_model;
113 } else if (addr == 0xFFFFF) {
114 /* Return system submodel identifier for non-x86 machines */
Simon Glassd8414fc2014-11-14 20:56:42 -0700115 debug_io("BE_memaddr - Returning submodel\n");
Jason Jina63ce952007-07-06 08:34:56 +0800116 return &BE_submodel;
117 }
118#endif
119 else if (addr > M.mem_size - 1) {
120 HALT_SYS();
Simon Glass89172162014-11-14 20:56:39 -0700121 return (u8 *)M.mem_base;
Jason Jina63ce952007-07-06 08:34:56 +0800122 }
123
Simon Glass89172162014-11-14 20:56:39 -0700124 return (u8 *)(M.mem_base + addr);
Jason Jina63ce952007-07-06 08:34:56 +0800125}
126
127/****************************************************************************
128PARAMETERS:
129addr - Emulator memory address to read
130
131RETURNS:
132Byte value read from emulator memory.
133
134REMARKS:
135Reads a byte value from the emulator memory. We have three distinct memory
136regions that are handled differently, which this function handles.
137****************************************************************************/
138u8 X86API BE_rdb(u32 addr)
139{
140 if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
141 return 0;
142 else {
143 u8 val = readb_le(BE_memaddr(addr));
144 return val;
145 }
146}
147
148/****************************************************************************
149PARAMETERS:
150addr - Emulator memory address to read
151
152RETURNS:
153Word value read from emulator memory.
154
155REMARKS:
156Reads a word value from the emulator memory. We have three distinct memory
157regions that are handled differently, which this function handles.
158****************************************************************************/
159u16 X86API BE_rdw(u32 addr)
160{
161 if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
162 return 0;
163 else {
164 u8 *base = BE_memaddr(addr);
165 u16 val = readw_le(base);
166 return val;
167 }
168}
169
170/****************************************************************************
171PARAMETERS:
172addr - Emulator memory address to read
173
174RETURNS:
175Long value read from emulator memory.
176
177REMARKS:
178Reads a 32-bit value from the emulator memory. We have three distinct memory
179regions that are handled differently, which this function handles.
180****************************************************************************/
181u32 X86API BE_rdl(u32 addr)
182{
183 if (_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)
184 return 0;
185 else {
186 u8 *base = BE_memaddr(addr);
187 u32 val = readl_le(base);
188 return val;
189 }
190}
191
192/****************************************************************************
193PARAMETERS:
194addr - Emulator memory address to read
195val - Value to store
196
197REMARKS:
198Writes a byte value to emulator memory. We have three distinct memory
199regions that are handled differently, which this function handles.
200****************************************************************************/
201void X86API BE_wrb(u32 addr, u8 val)
202{
203 if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
204 writeb_le(BE_memaddr(addr), val);
205 }
206}
207
208/****************************************************************************
209PARAMETERS:
210addr - Emulator memory address to read
211val - Value to store
212
213REMARKS:
214Writes a word value to emulator memory. We have three distinct memory
215regions that are handled differently, which this function handles.
216****************************************************************************/
217void X86API BE_wrw(u32 addr, u16 val)
218{
219 if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
220 u8 *base = BE_memaddr(addr);
221 writew_le(base, val);
222
223 }
224}
225
226/****************************************************************************
227PARAMETERS:
228addr - Emulator memory address to read
229val - Value to store
230
231REMARKS:
232Writes a 32-bit value to emulator memory. We have three distinct memory
233regions that are handled differently, which this function handles.
234****************************************************************************/
235void X86API BE_wrl(u32 addr, u32 val)
236{
237 if (!(_BE_env.emulateVGA && addr >= 0xA0000 && addr <= 0xBFFFF)) {
238 u8 *base = BE_memaddr(addr);
239 writel_le(base, val);
240 }
241}
242
Simon Glass89172162014-11-14 20:56:39 -0700243#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800244
245/* For Non-Intel machines we may need to emulate some I/O port accesses that
246 * the BIOS may try to access, such as the PCI config registers.
247 */
248
249#define IS_TIMER_PORT(port) (0x40 <= port && port <= 0x43)
250#define IS_CMOS_PORT(port) (0x70 <= port && port <= 0x71)
251/*#define IS_VGA_PORT(port) (_BE_env.emulateVGA && 0x3C0 <= port && port <= 0x3DA)*/
252#define IS_VGA_PORT(port) (0x3C0 <= port && port <= 0x3DA)
253#define IS_PCI_PORT(port) (0xCF8 <= port && port <= 0xCFF)
254#define IS_SPKR_PORT(port) (port == 0x61)
255
256/****************************************************************************
257PARAMETERS:
258port - Port to read from
259type - Type of access to perform
260
261REMARKS:
262Performs an emulated read from the Standard VGA I/O ports. If the target
263hardware does not support mapping the VGA I/O and memory (such as some
264PowerPC systems), we emulate the VGA so that the BIOS will still be able to
265set NonVGA display modes such as on ATI hardware.
266****************************************************************************/
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200267static u8 VGA_inpb (const int port)
Jason Jina63ce952007-07-06 08:34:56 +0800268{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200269 u8 val = 0xff;
Jason Jina63ce952007-07-06 08:34:56 +0800270
Simon Glassd8414fc2014-11-14 20:56:42 -0700271 debug_io("vga_inb.%04X -> ", (u16) port);
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200272 switch (port) {
273 case 0x3C0:
274 /* 3C0 has funky characteristics because it can act as either
275 a data register or index register depending on the state
276 of an internal flip flop in the hardware. Hence we have
277 to emulate that functionality in here. */
278 if (_BE_env.flipFlop3C0 == 0) {
279 /* Access 3C0 as index register */
280 val = _BE_env.emu3C0;
281 } else {
282 /* Access 3C0 as data register */
283 if (_BE_env.emu3C0 < ATT_C)
284 val = _BE_env.emu3C1[_BE_env.emu3C0];
285 }
286 _BE_env.flipFlop3C0 ^= 1;
287 break;
288 case 0x3C1:
289 if (_BE_env.emu3C0 < ATT_C)
290 return _BE_env.emu3C1[_BE_env.emu3C0];
291 break;
292 case 0x3CC:
293 return _BE_env.emu3C2;
294 case 0x3C4:
295 return _BE_env.emu3C4;
296 case 0x3C5:
297 if (_BE_env.emu3C4 < ATT_C)
298 return _BE_env.emu3C5[_BE_env.emu3C4];
299 break;
300 case 0x3C6:
301 return _BE_env.emu3C6;
302 case 0x3C7:
303 return _BE_env.emu3C7;
304 case 0x3C8:
305 return _BE_env.emu3C8;
306 case 0x3C9:
307 if (_BE_env.emu3C7 < PAL_C)
308 return _BE_env.emu3C9[_BE_env.emu3C7++];
309 break;
310 case 0x3CE:
311 return _BE_env.emu3CE;
312 case 0x3CF:
313 if (_BE_env.emu3CE < GRA_C)
314 return _BE_env.emu3CF[_BE_env.emu3CE];
315 break;
316 case 0x3D4:
317 if (_BE_env.emu3C2 & 0x1)
318 return _BE_env.emu3D4;
319 break;
320 case 0x3D5:
321 if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
322 return _BE_env.emu3D5[_BE_env.emu3D4];
323 break;
324 case 0x3DA:
325 _BE_env.flipFlop3C0 = 0;
326 val = _BE_env.emu3DA;
327 _BE_env.emu3DA ^= 0x9;
328 break;
329 }
330 return val;
Jason Jina63ce952007-07-06 08:34:56 +0800331}
332
333/****************************************************************************
334PARAMETERS:
335port - Port to write to
336type - Type of access to perform
337
338REMARKS:
339Performs an emulated write to one of the 8253 timer registers. For now
340we only emulate timer 0 which is the only timer that the BIOS code appears
341to use.
342****************************************************************************/
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200343static void VGA_outpb (int port, u8 val)
Jason Jina63ce952007-07-06 08:34:56 +0800344{
Wolfgang Denk96bb2e02007-08-06 02:17:36 +0200345 switch (port) {
346 case 0x3C0:
347 /* 3C0 has funky characteristics because it can act as either
348 a data register or index register depending on the state
349 of an internal flip flop in the hardware. Hence we have
350 to emulate that functionality in here. */
351 if (_BE_env.flipFlop3C0 == 0) {
352 /* Access 3C0 as index register */
353 _BE_env.emu3C0 = val;
354 } else {
355 /* Access 3C0 as data register */
356 if (_BE_env.emu3C0 < ATT_C)
357 _BE_env.emu3C1[_BE_env.emu3C0] = val;
358 }
359 _BE_env.flipFlop3C0 ^= 1;
360 break;
361 case 0x3C2:
362 _BE_env.emu3C2 = val;
363 break;
364 case 0x3C4:
365 _BE_env.emu3C4 = val;
366 break;
367 case 0x3C5:
368 if (_BE_env.emu3C4 < ATT_C)
369 _BE_env.emu3C5[_BE_env.emu3C4] = val;
370 break;
371 case 0x3C6:
372 _BE_env.emu3C6 = val;
373 break;
374 case 0x3C7:
375 _BE_env.emu3C7 = (int) val *3;
376
377 break;
378 case 0x3C8:
379 _BE_env.emu3C8 = (int) val *3;
380
381 break;
382 case 0x3C9:
383 if (_BE_env.emu3C8 < PAL_C)
384 _BE_env.emu3C9[_BE_env.emu3C8++] = val;
385 break;
386 case 0x3CE:
387 _BE_env.emu3CE = val;
388 break;
389 case 0x3CF:
390 if (_BE_env.emu3CE < GRA_C)
391 _BE_env.emu3CF[_BE_env.emu3CE] = val;
392 break;
393 case 0x3D4:
394 if (_BE_env.emu3C2 & 0x1)
395 _BE_env.emu3D4 = val;
396 break;
397 case 0x3D5:
398 if ((_BE_env.emu3C2 & 0x1) && (_BE_env.emu3D4 < CRT_C))
399 _BE_env.emu3D5[_BE_env.emu3D4] = val;
400 break;
401 }
Jason Jina63ce952007-07-06 08:34:56 +0800402}
403
404/****************************************************************************
405PARAMETERS:
406regOffset - Offset into register space for non-DWORD accesses
407value - Value to write to register for PCI_WRITE_* operations
408func - Function to perform (PCIAccessRegFlags)
409
410RETURNS:
411Value read from configuration register for PCI_READ_* operations
412
413REMARKS:
414Accesses a PCI configuration space register by decoding the value currently
415stored in the _BE_env.configAddress variable and passing it through to the
416portable PCI_accessReg function.
417****************************************************************************/
418static u32 BE_accessReg(int regOffset, u32 value, int func)
419{
420#ifdef __KERNEL__
421 int function, device, bus;
422 u8 val8;
423 u16 val16;
424 u32 val32;
425
Jason Jina63ce952007-07-06 08:34:56 +0800426 /* 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)) {
Yuri Zaporozhets52234d62024-10-30 20:38:20 +0100438 pci_dev_t bdf = PCI_BDF(bus, device, function);
Jason Jina63ce952007-07-06 08:34:56 +0800439 switch (func) {
440 case REG_READ_BYTE:
Yuri Zaporozhets52234d62024-10-30 20:38:20 +0100441 pci_read_config_byte(bdf, regOffset, &val8);
Jason Jina63ce952007-07-06 08:34:56 +0800442 return val8;
443 case REG_READ_WORD:
Yuri Zaporozhets52234d62024-10-30 20:38:20 +0100444 pci_read_config_word(bdf, regOffset, &val16);
Jason Jina63ce952007-07-06 08:34:56 +0800445 return val16;
446 case REG_READ_DWORD:
Yuri Zaporozhets52234d62024-10-30 20:38:20 +0100447 pci_read_config_dword(bdf, regOffset, &val32);
Jason Jina63ce952007-07-06 08:34:56 +0800448 return val32;
449 case REG_WRITE_BYTE:
Yuri Zaporozhets52234d62024-10-30 20:38:20 +0100450 pci_write_config_byte(bdf, regOffset, value);
Jason Jina63ce952007-07-06 08:34:56 +0800451
452 return 0;
453 case REG_WRITE_WORD:
Yuri Zaporozhets52234d62024-10-30 20:38:20 +0100454 pci_write_config_word(bdf, regOffset, value);
Jason Jina63ce952007-07-06 08:34:56 +0800455
456 return 0;
457 case REG_WRITE_DWORD:
Yuri Zaporozhets52234d62024-10-30 20:38:20 +0100458 pci_write_config_dword(bdf, regOffset, value);
Jason Jina63ce952007-07-06 08:34:56 +0800459
460 return 0;
461 }
462 }
463 return 0;
464#else
465 PCIDeviceInfo pciInfo;
466
467 pciInfo.mech1 = 1;
468 pciInfo.slot.i = 0;
469 pciInfo.slot.p.Function = (_BE_env.configAddress >> 8) & 0x7;
470 pciInfo.slot.p.Device = (_BE_env.configAddress >> 11) & 0x1F;
471 pciInfo.slot.p.Bus = (_BE_env.configAddress >> 16) & 0xFF;
472 pciInfo.slot.p.Enable = 1;
473
474 /* Ignore accesses to all devices other than the one we're POSTing */
475 if ((pciInfo.slot.p.Function ==
476 _BE_env.vgaInfo.pciInfo->slot.p.Function)
477 && (pciInfo.slot.p.Device == _BE_env.vgaInfo.pciInfo->slot.p.Device)
478 && (pciInfo.slot.p.Bus == _BE_env.vgaInfo.pciInfo->slot.p.Bus))
479 return PCI_accessReg((_BE_env.configAddress & 0xFF) + regOffset,
480 value, func, &pciInfo);
481 return 0;
482#endif
483}
484
485/****************************************************************************
486PARAMETERS:
487port - Port to read from
488type - Type of access to perform
489
490REMARKS:
491Performs an emulated read from one of the PCI configuration space registers.
492We emulate this using our PCI_accessReg function which will access the PCI
493configuration space registers in a portable fashion.
494****************************************************************************/
495static u32 PCI_inp(int port, int type)
496{
497 switch (type) {
498 case REG_READ_BYTE:
499 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
500 && port <= 0xCFF)
501 return BE_accessReg(port - 0xCFC, 0, REG_READ_BYTE);
502 break;
503 case REG_READ_WORD:
504 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
505 && port <= 0xCFF)
506 return BE_accessReg(port - 0xCFC, 0, REG_READ_WORD);
507 break;
508 case REG_READ_DWORD:
509 if (port == 0xCF8)
510 return _BE_env.configAddress;
511 else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
512 return BE_accessReg(0, 0, REG_READ_DWORD);
513 break;
514 }
515 return 0;
516}
517
518/****************************************************************************
519PARAMETERS:
520port - Port to write to
521type - Type of access to perform
522
523REMARKS:
524Performs an emulated write to one of the PCI control registers.
525****************************************************************************/
526static void PCI_outp(int port, u32 val, int type)
527{
528 switch (type) {
529 case REG_WRITE_BYTE:
530 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
531 && port <= 0xCFF)
532 BE_accessReg(port - 0xCFC, val, REG_WRITE_BYTE);
533 break;
534 case REG_WRITE_WORD:
535 if ((_BE_env.configAddress & 0x80000000) && 0xCFC <= port
536 && port <= 0xCFF)
537 BE_accessReg(port - 0xCFC, val, REG_WRITE_WORD);
538 break;
539 case REG_WRITE_DWORD:
540 if (port == 0xCF8)
541 {
542 _BE_env.configAddress = val & 0x80FFFFFC;
543 }
544 else if ((_BE_env.configAddress & 0x80000000) && port == 0xCFC)
545 BE_accessReg(0, val, REG_WRITE_DWORD);
546 break;
547 }
548}
549
550#endif
551
552/****************************************************************************
553PARAMETERS:
554port - Port to write to
555
556RETURNS:
557Value read from the I/O port
558
559REMARKS:
560Performs an emulated 8-bit read from an I/O port. We handle special cases
561that we need to emulate in here, and fall through to reflecting the write
562through to the real hardware if we don't need to special case it.
563****************************************************************************/
564u8 X86API BE_inb(X86EMU_pioAddr port)
565{
566 u8 val = 0;
567
Simon Glass89172162014-11-14 20:56:39 -0700568#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800569 if (IS_VGA_PORT(port)){
570 /*seems reading port 0x3c3 return the high 16 bit of io port*/
571 if(port == 0x3c3)
572 val = LOG_inpb(port);
573 else
574 val = VGA_inpb(port);
575 }
576 else if (IS_TIMER_PORT(port))
577 DB(printf("Can not interept TIMER port now!\n");)
578 else if (IS_SPKR_PORT(port))
579 DB(printf("Can not interept SPEAKER port now!\n");)
580 else if (IS_CMOS_PORT(port))
581 DB(printf("Can not interept CMOS port now!\n");)
582 else if (IS_PCI_PORT(port))
583 val = PCI_inp(port, REG_READ_BYTE);
584 else if (port < 0x100) {
585 DB(printf("WARN: INVALID inb.%04X -> %02X\n", (u16) port, val);)
586 val = LOG_inpb(port);
587 } else
588#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700589 {
590 debug_io("inb.%04X -> ", (u16) port);
Jason Jina63ce952007-07-06 08:34:56 +0800591 val = LOG_inpb(port);
Simon Glassd8414fc2014-11-14 20:56:42 -0700592 debug_io("%02X\n", val);
593 }
594
Jason Jina63ce952007-07-06 08:34:56 +0800595 return val;
596}
597
598/****************************************************************************
599PARAMETERS:
600port - Port to write to
601
602RETURNS:
603Value read from the I/O port
604
605REMARKS:
606Performs an emulated 16-bit read from an I/O port. We handle special cases
607that we need to emulate in here, and fall through to reflecting the write
608through to the real hardware if we don't need to special case it.
609****************************************************************************/
610u16 X86API BE_inw(X86EMU_pioAddr port)
611{
612 u16 val = 0;
613
Simon Glass89172162014-11-14 20:56:39 -0700614#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800615 if (IS_PCI_PORT(port))
616 val = PCI_inp(port, REG_READ_WORD);
617 else if (port < 0x100) {
618 DB(printf("WARN: Maybe INVALID inw.%04X -> %04X\n", (u16) port, val);)
619 val = LOG_inpw(port);
620 } else
621#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700622 {
623 debug_io("inw.%04X -> ", (u16) port);
Jason Jina63ce952007-07-06 08:34:56 +0800624 val = LOG_inpw(port);
Simon Glassd8414fc2014-11-14 20:56:42 -0700625 debug_io("%04X\n", val);
626 }
627
Jason Jina63ce952007-07-06 08:34:56 +0800628 return val;
629}
630
631/****************************************************************************
632PARAMETERS:
633port - Port to write to
634
635RETURNS:
636Value read from the I/O port
637
638REMARKS:
639Performs an emulated 32-bit read from an I/O port. We handle special cases
640that we need to emulate in here, and fall through to reflecting the write
641through to the real hardware if we don't need to special case it.
642****************************************************************************/
643u32 X86API BE_inl(X86EMU_pioAddr port)
644{
645 u32 val = 0;
646
Simon Glass89172162014-11-14 20:56:39 -0700647#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800648 if (IS_PCI_PORT(port))
649 val = PCI_inp(port, REG_READ_DWORD);
650 else if (port < 0x100) {
651 val = LOG_inpd(port);
652 } else
653#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700654 {
655 debug_io("inl.%04X -> ", (u16) port);
Jason Jina63ce952007-07-06 08:34:56 +0800656 val = LOG_inpd(port);
Simon Glassd8414fc2014-11-14 20:56:42 -0700657 debug_io("%08X\n", val);
658 }
659
Jason Jina63ce952007-07-06 08:34:56 +0800660 return val;
661}
662
663/****************************************************************************
664PARAMETERS:
665port - Port to write to
666val - Value to write to port
667
668REMARKS:
669Performs an emulated 8-bit write to an I/O port. We handle special cases
670that we need to emulate in here, and fall through to reflecting the write
671through to the real hardware if we don't need to special case it.
672****************************************************************************/
673void X86API BE_outb(X86EMU_pioAddr port, u8 val)
674{
Simon Glass89172162014-11-14 20:56:39 -0700675#if !defined(CONFIG_X86EMU_RAW_IO)
Jason Jina63ce952007-07-06 08:34:56 +0800676 if (IS_VGA_PORT(port))
677 VGA_outpb(port, val);
678 else if (IS_TIMER_PORT(port))
679 DB(printf("Can not interept TIMER port now!\n");)
680 else if (IS_SPKR_PORT(port))
681 DB(printf("Can not interept SPEAKER port now!\n");)
682 else if (IS_CMOS_PORT(port))
683 DB(printf("Can not interept CMOS port now!\n");)
684 else if (IS_PCI_PORT(port))
685 PCI_outp(port, val, REG_WRITE_BYTE);
686 else if (port < 0x100) {
687 DB(printf("WARN:Maybe INVALID outb.%04X <- %02X\n", (u16) port, val);)
688 LOG_outpb(port, val);
689 } else
690#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700691 {
692 debug_io("outb.%04X <- %02X", (u16) port, val);
Jason Jina63ce952007-07-06 08:34:56 +0800693 LOG_outpb(port, val);
Simon Glassd8414fc2014-11-14 20:56:42 -0700694 debug_io("\n");
695 }
Jason Jina63ce952007-07-06 08:34:56 +0800696}
697
698/****************************************************************************
699PARAMETERS:
700port - Port to write to
701val - Value to write to port
702
703REMARKS:
704Performs an emulated 16-bit write to an I/O port. We handle special cases
705that we need to emulate in here, and fall through to reflecting the write
706through to the real hardware if we don't need to special case it.
707****************************************************************************/
708void X86API BE_outw(X86EMU_pioAddr port, u16 val)
709{
Simon Glass89172162014-11-14 20:56:39 -0700710#if !defined(CONFIG_X86EMU_RAW_IO)
Simon Glassd8414fc2014-11-14 20:56:42 -0700711 if (IS_VGA_PORT(port)) {
712 VGA_outpb(port, val);
713 VGA_outpb(port + 1, val >> 8);
714 } else if (IS_PCI_PORT(port)) {
715 PCI_outp(port, val, REG_WRITE_WORD);
716 } else if (port < 0x100) {
717 DB(printf("WARN: MAybe INVALID outw.%04X <- %04X\n", (u16)port,
718 val);)
719 LOG_outpw(port, val);
720 } else
Jason Jina63ce952007-07-06 08:34:56 +0800721#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700722 {
723 debug_io("outw.%04X <- %04X", (u16) port, val);
724 LOG_outpw(port, val);
725 debug_io("\n");
726 }
Jason Jina63ce952007-07-06 08:34:56 +0800727}
728
729/****************************************************************************
730PARAMETERS:
731port - Port to write to
732val - Value to write to port
733
734REMARKS:
735Performs an emulated 32-bit write to an I/O port. We handle special cases
736that we need to emulate in here, and fall through to reflecting the write
737through to the real hardware if we don't need to special case it.
738****************************************************************************/
739void X86API BE_outl(X86EMU_pioAddr port, u32 val)
740{
Simon Glass89172162014-11-14 20:56:39 -0700741#if !defined(CONFIG_X86EMU_RAW_IO)
Simon Glassacda1cc2014-11-14 20:56:40 -0700742 if (IS_PCI_PORT(port)) {
Jason Jina63ce952007-07-06 08:34:56 +0800743 PCI_outp(port, val, REG_WRITE_DWORD);
Simon Glassacda1cc2014-11-14 20:56:40 -0700744 } else if (port < 0x100) {
Jason Jina63ce952007-07-06 08:34:56 +0800745 DB(printf("WARN: INVALID outl.%04X <- %08X\n", (u16) port,val);)
746 LOG_outpd(port, val);
747 } else
748#endif
Simon Glassd8414fc2014-11-14 20:56:42 -0700749 {
750 debug_io("outl.%04X <- %08X", (u16) port, val);
Jason Jina63ce952007-07-06 08:34:56 +0800751 LOG_outpd(port, val);
Simon Glassd8414fc2014-11-14 20:56:42 -0700752 debug_io("\n");
753 }
Jason Jina63ce952007-07-06 08:34:56 +0800754}