GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / pccons / vgainit.c
blobcc05439841b616a0719ea57e13f10937b09e6f6a
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * VGA BIOS initialization File: VGAINIT.C
5 *
6 * This module interfaces with the X86 emulator borrowed from
7 * XFree86 to do VGA initialization.
9 * WARNING: This code is SB1250-specific for now. It's not
10 * hard to change, but then again, aren't we interested in the 1250?
12 * Author: Mitch Lichtenberg (mpl@broadcom.com)
14 *********************************************************************
16 * Copyright 2000,2001,2002,2003
17 * Broadcom Corporation. All rights reserved.
19 * This software is furnished under license and may be used and
20 * copied only in accordance with the following terms and
21 * conditions. Subject to these conditions, you may download,
22 * copy, install, use, modify and distribute modified or unmodified
23 * copies of this software in source and/or binary form. No title
24 * or ownership is transferred hereby.
26 * 1) Any source code used, modified or distributed must reproduce
27 * and retain this copyright notice and list of conditions
28 * as they appear in the source file.
30 * 2) No right is granted to use any trade name, trademark, or
31 * logo of Broadcom Corporation. The "Broadcom Corporation"
32 * name may not be used to endorse or promote products derived
33 * from this software without the prior written permission of
34 * Broadcom Corporation.
36 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
37 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
38 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
39 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
40 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
41 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
42 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
44 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
45 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
46 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
47 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
48 * THE POSSIBILITY OF SUCH DAMAGE.
49 ********************************************************************* */
51 #include "sbmips.h"
52 #include "lib_types.h"
53 #include "lib_string.h"
54 #include "lib_printf.h"
55 #include "lib_malloc.h"
56 #include "pcireg.h"
57 #include "pcivar.h"
58 #include "cfe_console.h"
59 #include "vga.h"
60 #include "pcibios.h"
61 #include "lib_physio.h"
62 #include "vga_subr.h"
63 #include "x86mem.h"
64 #include "x86emu.h"
65 #include "env_subr.h"
68 /* *********************************************************************
69 * Configuration
70 ********************************************************************* */
72 #define BYTESONLY 0 /* Always write registers as bytes */
73 #define VGAINIT_NOISY 0 /* lots of debug output */
75 #define SB1250_PASS2_WORKAROUNDS
77 /* *********************************************************************
78 * ISA port macros - currently SB1250-specific
79 ********************************************************************* */
81 #define INB(x) inb(x)
82 #define INW(x) inw(x)
83 #define INL(x) inl(x)
84 #define OUTB(x,y) outb(x,y)
85 #define OUTW(x,y) outw(x,y)
86 #define OUTL(x,y) outl(x,y)
88 /* *********************************************************************
89 * ISA memory macros - currently SB1250-specific
90 ********************************************************************* */
92 typedef uintptr_t vm_offset_t;
94 #if defined(_P5064_) || defined(_P6064_)
95 #define PCI_MEM_SPACE 0x10000000 /* 128MB: s/w configurable */
96 #define __ISAaddr(addr) ((physaddr_t)(PCI_MEM_SPACE+(addr)))
97 #else
98 #define __ISAaddr(addr) ((physaddr_t)0x40000000+(addr))
99 #endif
101 #define __ISAreadbyte(addr) phys_read8(__ISAaddr(addr))
102 #define __ISAreadword(addr) phys_read16(__ISAaddr(addr))
103 #define __ISAreaddword(addr) phys_read32(__ISAaddr(addr))
104 #define __ISAwritebyte(addr,data) phys_write8(__ISAaddr(addr),(data))
105 #define __ISAwriteword(addr,data) phys_write16(__ISAaddr(addr),(data))
106 #define __ISAwritedword(addr,data) phys_write32(__ISAaddr(addr),(data))
108 /* *********************************************************************
109 * Other macros
110 ********************************************************************* */
112 #define OFFSET(addr) (((addr) >> 0) & 0xffff)
113 #define SEGMENT(addr) (((addr) >> 4) & 0xf000)
115 #define BSWAP_SHORT(s) ((((s) >> 8) & 0xFF) | (((s)&0xFF) << 8))
116 #define BSWAP_LONG(s) ((((s) & 0xFF000000) >> 24) | \
117 (((s) & 0x00FF0000) >> 8) | \
118 (((s) & 0x0000FF00) << 8) | \
119 (((s) & 0x000000FF) << 24))
122 #ifdef __MIPSEB
123 #define CPU_TO_LE16(s) BSWAP_SHORT(s)
124 #define CPU_TO_LE32(s) BSWAP_LONG(s)
125 #define LE16_TO_CPU(s) BSWAP_SHORT(s)
126 #define LE32_TO_CPU(s) BSWAP_LONG(s)
127 #else
128 #define CPU_TO_LE16(s) (s)
129 #define CPU_TO_LE32(s) (s)
130 #define LE16_TO_CPU(s) (s)
131 #define LE32_TO_CPU(s) (s)
132 #endif
135 /* *********************************************************************
136 * Prototypes
137 ********************************************************************* */
139 int vga_biosinit(void);
140 int vga_probe(void);
141 extern void ui_restart(int);
142 void vgaraw_dump(char *tail);
143 int x86emutest(void);
145 /* *********************************************************************
146 * Globals
147 ********************************************************************* */
149 static vga_term_t vga;
150 static x86mem_t x86mem;
152 #define BIOSRAMLOC (0xC0000)
153 #define STACKSIZE 4096
154 #define IRETOFFSET 12
155 static uint8_t x86initcode[] = {
156 #if (VGA_TEXTMODE_ROWS == 60)
157 0xB8,0x02,0x4F, /* mov ax,042F */
158 0xBB,0x08,0x01, /* mov bx,0108 */ /* VESA 80x60 */
159 #else
160 0xB8,0x03,0x00, /* mov AX,0003 */ /* 80x25 mode */
161 #endif
163 0xCD,0x10, /* int 10 */
164 0xB8,0x34,0x12, /* mov ax,1234 */
165 0xBB,0x78,0x56, /* mov bx,5678 */
166 0xCC, /* int 3 */
167 0xCF}; /* IRET */
169 static uint8_t x86testcode[] = {
170 0x90,0x90,0x90,0x90,0x90, /* nop, nop, nop, nop, nop */
171 0xeb,0x09, /* jmp 10 */
172 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90, /* 9 nops */
173 0xb8,0x34,0x12, /* mov ax,1234 */
174 0xbb,0x78,0x56, /* mov bx,5678 */
175 0xcc, /* int 3 */
176 0xcf}; /* iret */
178 static uint32_t __ISAreadmem(x86mem_t *mem,uint32_t addr,int size)
180 unsigned long val;
182 switch (size) {
183 case M_BYTE:
184 val = __ISAreadbyte(addr);
185 break;
186 case M_WORD:
187 if (BYTESONLY || (addr & 0x1)) {
188 val = (__ISAreadbyte(addr) | (__ISAreadbyte(addr + 1) << 8));
190 else {
191 val = __ISAreadword(addr);
192 val = LE16_TO_CPU(val);
194 break;
195 case M_DWORD:
196 if (BYTESONLY || (addr & 0x3)) {
197 val = (__ISAreadbyte(addr) |
198 (__ISAreadbyte(addr + 1) << 8) |
199 (__ISAreadbyte(addr + 2) << 16) |
200 (__ISAreadbyte(addr + 3) << 24));
202 else {
203 val = __ISAreaddword(addr);
204 val = LE32_TO_CPU(val);
206 break;
207 default:
208 val = 0;
211 return val;
216 static void __ISAwritemem(x86mem_t *mem,uint32_t addr,uint32_t data,int size)
218 switch (size) {
219 case M_BYTE:
220 __ISAwritebyte(addr, data);
221 break;
223 case M_WORD:
224 if (BYTESONLY || (addr & 0x1)) {
225 __ISAwritebyte(addr, data >> 0);
226 __ISAwritebyte(addr + 1, data >> 8);
228 else {
229 data = CPU_TO_LE16(data);
230 __ISAwriteword(addr, data);
232 break;
234 case M_DWORD:
235 if (BYTESONLY || (addr & 0x3)) {
236 __ISAwritebyte(addr, data >> 0);
237 __ISAwritebyte(addr + 1, data >> 8);
238 __ISAwritebyte(addr + 2, data >> 16);
239 __ISAwritebyte(addr + 3, data >> 24);
241 else {
242 data = CPU_TO_LE32(data);
243 __ISAwritedword(addr, data);
245 break;
250 static u8 __x86emu_rdb(u32 addr)
252 #if VGAINIT_NOISY
253 if ((addr < 0x400) || (addr > 0x100000)) {
254 xprintf("Read %08X (int %02X) ",addr,addr/4);
255 printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
257 #endif
258 return x86mem_readb(&x86mem,addr);
262 static u16 __x86emu_rdw(u32 addr)
264 #if VGAINIT_NOISY
265 if ((addr < 0x400) || (addr > 0x100000)) {
266 xprintf("Read %08X (int %02X) ",addr,addr/4);
267 printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
269 #endif
270 return x86mem_readw(&x86mem,addr);
274 static u32 __x86emu_rdl(u32 addr)
276 #if VGAINIT_NOISY
277 if ((addr < 0x400) || (addr > 0x100000)) {
278 xprintf("Read %08X (int %02X) ",addr,addr/4);
279 printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
281 #endif
282 return x86mem_readl(&x86mem,addr);
286 static void __x86emu_wrb(u32 addr, u8 val)
288 #if VGAINIT_NOISY
289 if ((addr < 0x400) || (addr > 0x100000)) {
290 xprintf("Write %08X (int %02X) ",addr,addr/4);
291 printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
293 #endif
294 x86mem_writeb(&x86mem,addr,val);
298 static void __x86emu_wrw(u32 addr, u16 val)
300 #if VGAINIT_NOISY
301 if ((addr < 0x400) || (addr > 0x100000)) {
302 xprintf("Write %08X %04X (int %02X) ",addr,val,addr/4);
303 printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
305 #endif
306 x86mem_writew(&x86mem,addr,val);
310 static void __x86emu_wrl(u32 addr, u32 val)
312 #if VGAINIT_NOISY
313 if ((addr < 0x400) || (addr > 0x100000)) {
314 xprintf("Write %08X (int %02X) ",addr,addr/4);
315 printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
317 #endif
318 x86mem_writel(&x86mem,addr,val);
322 #define TS_COMMAND 0
323 #define TS_DATA1 1
324 #define TS_DATA2 2
325 static uint16_t timerCount = 0;
326 static int timerState = TS_COMMAND;
327 static u8 __x86emu_inb(X86EMU_pioAddr port)
329 u8 val;
332 * Emulate just enough functionality of the
333 * timer chip to fool the Trident BIOS
335 if (port == 0x40) {
336 timerCount++;
337 switch (timerState) {
338 case TS_COMMAND:
339 return 0;
340 case TS_DATA1:
341 timerState = TS_DATA1;
342 return timerCount & 0xFF;
343 case TS_DATA2:
344 timerState = TS_COMMAND;
345 return (timerCount >> 8) & 0xFF;
349 #ifdef SB1250_PASS2_WORKAROUNDS
350 if ((port < 0x3BC) || (port > 0x3DF)) {
351 return 0;
353 #endif
355 val = INB(port);
357 #if VGAINIT_NOISY
358 /*if (port < 0x100)*/ xprintf("INB %08X %02X\n",port,val);
359 if (console_status()) ui_restart(0);
360 #endif
363 return val;
367 static u16 __x86emu_inw(X86EMU_pioAddr port)
369 u16 val;
371 #ifdef SB1250_PASS2_WORKAROUNDS
372 if ((port < 0x3BC) || (port > 0x3DF)) {
373 return 0;
375 #endif
377 val = INW(port);
379 val = LE16_TO_CPU(val);
381 #if VGAINIT_NOISY
382 /*if (port < 0x100)*/ xprintf("INW %08X %04X\n",port,val);
383 #endif
385 return val;
389 static u32 __x86emu_inl(X86EMU_pioAddr port)
391 u32 val;
393 #ifdef SB1250_PASS2_WORKAROUNDS
394 if ((port < 0x3BC) || (port > 0x3DF)) {
395 return 0;
397 #endif
399 val = INL(port);
401 val = LE32_TO_CPU(val);
403 #if VGAINIT_NOISY
404 /*if (port < 0x100)*/ xprintf("INL %08X %08X\n",port,val);
405 #endif
408 return val;
412 static void __x86emu_outb(X86EMU_pioAddr port, u8 val)
415 * Emulate just enough functionality of the timer
416 * chip to fool the Trident BIOS
418 if (port == 0x43) {
419 timerCount++;
420 timerState = TS_DATA1;
421 return;
424 #if VGAINIT_NOISY
425 /*if (port < 0x100)*/ xprintf("OUTB %08X %08X\n",port,val);
426 #endif
428 #ifdef SB1250_PASS2_WORKAROUNDS
429 if ((port < 0x3BC) || (port > 0x3DF)) {
430 return;
432 #endif
434 OUTB(port,val);
438 static void __x86emu_outw(X86EMU_pioAddr port, u16 val)
440 val = CPU_TO_LE16(val);
442 #if VGAINIT_NOISY
443 /*if (port < 0x100)*/ xprintf("OUTW %08X %04X ",port,val);
444 printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
445 #endif
447 #ifdef SB1250_PASS2_WORKAROUNDS
448 if ((port < 0x3BC) || (port > 0x3DF)) {
449 return;
451 #endif
453 OUTW(port,val);
457 static void __x86emu_outl(X86EMU_pioAddr port, u32 val)
459 if (port == 0x2D) return;
461 val = CPU_TO_LE32(val);
463 #if VGAINIT_NOISY
464 /*if (port < 0x100)*/ xprintf("OUTL %08X %08X ",port,val);
465 printf("CS:IP = %04X:%04X\n",M.x86.R_CS,M.x86.R_IP);
466 #endif
468 #ifdef SB1250_PASS2_WORKAROUNDS
469 if ((port < 0x3BC) || (port > 0x3DF)) {
470 return;
472 #endif
475 OUTL(port,val);
479 static void regs2tag(pcitag_t *tag)
481 pcitag_t mytag;
482 int bus,device,function;
484 bus = M.x86.R_BH;
485 device = M.x86.R_BL >> 3;
486 function = M.x86.R_BL & 0x07;
488 mytag = pci_make_tag(0,bus,device,function);
490 *tag = mytag;
493 static void __SIMint10(int intno)
495 #if VGAINIT_NOISY
496 xprintf("Int10: BIOS function AX=%04X\n",M.x86.R_AX);
497 #endif
500 * The only BIOS function that VGAs appear to
501 * depend on in the real BIOS is the one
502 * that enables/disables video memory.
505 if ((M.x86.R_AH == 0x12) && (M.x86.R_BL == 0x32)) {
506 if (M.x86.R_AL == 0) {
507 /* enable video memory */
508 __x86emu_outb(VGA_MISCOUTPUT_W, __x86emu_inb(VGA_MISCOUTPUT_R) | 0x02);
509 return;
511 else if (M.x86.R_AL == 1) {
512 /* disable video memory */
513 __x86emu_outb(VGA_MISCOUTPUT_W, __x86emu_inb(VGA_MISCOUTPUT_R) & ~0x02);
514 return;
516 else {
517 xprintf("Int10 unknown function AX=%04X\n",
518 M.x86.R_AX);
521 else {
523 /* Otherwise, pass the int10 on to the ROM */
525 X86EMU_prepareForInt(0x10);
530 static void __SIMint3(int intno)
532 #if VGAINIT_NOISY
533 xprintf("Int3: Breakpoint reached.\n");
534 #endif
535 HALT_SYS();
539 static void __SIMintunk(int intno)
541 #if VGAINIT_NOISY
542 xprintf("Int%02X: Unhandled interrupt!\n",intno);
543 #endif
544 HALT_SYS();
547 static void __SIMint42(int intno)
549 #if VGAINIT_NOISY
550 xprintf("Int42: Function AX=%04X\n",M.x86.R_AX);
551 #endif
552 switch (M.x86.R_AH) {
553 case 0:
554 vga_reset(&vga);
555 break;
556 default:
557 #if VGAINIT_NOISY
558 xprintf("Int42: Unknown INT42 command: %x\n",M.x86.R_AH);
559 #endif
560 break;
565 static void __SIMint6D(int intno)
567 int reflect = 1;
569 #if VGAINIT_NOISY
570 xprintf("Int6D: Function AX=%04X\n",M.x86.R_AX);
571 #endif
573 switch (M.x86.R_AH) {
574 case 0:
575 break;
576 case 0x13:
577 if (M.x86.R_AL == 1) {
578 unsigned long addr;
579 unsigned long count;
580 uint8_t ch;
582 addr = (M.x86.R_ES << 4) + M.x86.R_BP;
583 count = M.x86.R_CX;
585 while (count) {
586 ch = __x86emu_rdb(addr);
587 vga_writechar(&vga,ch,M.x86.R_BL);
588 addr++;
589 count--;
591 reflect = 0;
593 break;
594 default:
595 #if VGAINIT_NOISY
596 xprintf("Unknown INT6D command: %x\n",M.x86.R_AH);
597 #endif
598 break;
601 if (reflect) X86EMU_prepareForInt(0x6D);
606 static void __SIMint1A(int intno)
608 pcitag_t tag;
609 int bus,device,function;
610 int ret;
612 if (M.x86.R_AH != PCIBIOS_FN_MAJOR) return;
614 switch (M.x86.R_AL) {
615 case PCIBIOS_FN_INSTCHK:
616 M.x86.R_EAX = 0x00;
617 M.x86.R_AL = 0x01;
618 M.x86.R_EDX = PCIBIOS_SIGNATURE;
619 M.x86.R_EBX = PCIBIOS_VERSION;
620 M.x86.R_ECX &= 0xFF00;
621 M.x86.R_CL = 0; /* Highest bus number */
622 #ifdef VGAINIT_NOISY
623 xprintf("Int1A: Installation check\n");
624 #endif
625 CLEAR_FLAG(F_CF);
626 break;
628 case PCIBIOS_FN_FINDDEV:
629 ret = pci_find_device(M.x86.R_DX,M.x86.R_CX,M.x86.R_SI,&tag);
630 #if VGAINIT_NOISY
631 xprintf("Int1A: Find device VID=%04X,DID=%04X,Idx=%d: ",
632 M.x86.R_DX,M.x86.R_CX,M.x86.R_SI);
633 if (ret == 0) {
634 pci_break_tag(tag,NULL,&bus,&device,&function);
635 xprintf("Found Bus%d, Dev%d, Func%d\n",bus,device,function);
637 else {
638 xprintf("not found.\n");
640 #endif
641 if (ret == 0) {
642 pci_break_tag(tag,NULL,&bus,&device,&function);
643 M.x86.R_BH = bus;
644 M.x86.R_BL = (device << 3) | function;
645 M.x86.R_AH = PCIBIOS_SUCCESSFUL;
647 else {
648 M.x86.R_AH = PCIBIOS_DEVICE_NOT_FOUND;
651 CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL),F_CF);
652 break;
654 case PCIBIOS_FN_FINDCLASS:
655 ret = pci_find_class(M.x86.R_ECX,M.x86.R_SI,&tag);
656 #if VGAINIT_NOISY
657 xprintf("Int1A: Find Class %08X,Idx=%d: ",
658 M.x86.R_ECX,M.x86.R_SI);
659 if (ret == 0) {
660 pci_break_tag(tag,NULL,&bus,&device,&function);
661 xprintf("Found Bus%d, Dev%d, Func%d\n",bus,device,function);
663 else {
664 xprintf("not found.\n");
666 #endif
668 if (ret == 0) {
669 pci_break_tag(tag,NULL,&bus,&device,&function);
670 M.x86.R_BH = bus;
671 M.x86.R_BL = (device << 3) | function;
672 M.x86.R_AH = PCIBIOS_SUCCESSFUL;
674 else {
675 M.x86.R_AH =PCIBIOS_DEVICE_NOT_FOUND;
678 CONDITIONAL_SET_FLAG((M.x86.R_AH != PCIBIOS_SUCCESSFUL),F_CF);
679 break;
681 case PCIBIOS_FN_RDCFGBYTE:
682 regs2tag(&tag);
683 M.x86.R_CL = pci_conf_read8(tag,M.x86.R_DI);
684 M.x86.R_AH = PCIBIOS_SUCCESSFUL;
685 #if VGAINIT_NOISY
686 xprintf("Int1A: Read Cfg Byte %04X from ",M.x86.R_DI);
687 pci_break_tag(tag,NULL,&bus,&device,&function);
688 xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
689 xprintf(": %02X\n",M.x86.R_CX);
690 #endif
692 CLEAR_FLAG(F_CF);
693 break;
695 case PCIBIOS_FN_RDCFGWORD:
696 regs2tag(&tag);
697 M.x86.R_CX = pci_conf_read16(tag,M.x86.R_DI);
698 M.x86.R_AH = PCIBIOS_SUCCESSFUL;
699 #if VGAINIT_NOISY
700 xprintf("Int1A: Read Cfg Word %04X from ",M.x86.R_DI);
701 pci_break_tag(tag,NULL,&bus,&device,&function);
702 xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
703 xprintf(": %04X\n",M.x86.R_CX);
704 #endif
705 CLEAR_FLAG(F_CF);
706 break;
708 case PCIBIOS_FN_RDCFGDWORD:
709 regs2tag(&tag);
710 M.x86.R_ECX = pci_conf_read(tag,M.x86.R_DI);
711 #if VGAINIT_NOISY
712 xprintf("Int1A: Read Cfg Dword %04X from ",M.x86.R_DI);
713 pci_break_tag(tag,NULL,&bus,&device,&function);
714 xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
715 xprintf(": %08X\n",M.x86.R_ECX);
716 #endif
717 M.x86.R_AH = PCIBIOS_SUCCESSFUL;
718 CLEAR_FLAG(F_CF);
719 break;
721 case PCIBIOS_FN_WRCFGBYTE:
722 regs2tag(&tag);
723 pci_conf_write8(tag,M.x86.R_DI,M.x86.R_CL);
724 #if VGAINIT_NOISY
725 xprintf("Int1A: Write Cfg byte %04X to ",M.x86.R_DI);
726 pci_break_tag(tag,NULL,&bus,&device,&function);
727 xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
728 xprintf(": %02X\n",M.x86.R_CL);
729 #endif
731 M.x86.R_AH = PCIBIOS_SUCCESSFUL;
732 CLEAR_FLAG(F_CF);
733 break;
735 case PCIBIOS_FN_WRCFGWORD:
736 regs2tag(&tag);
737 pci_conf_write16(tag,M.x86.R_DI,M.x86.R_CX);
738 #if VGAINIT_NOISY
739 xprintf("Int1A: Write Cfg Word %04X to ",M.x86.R_DI);
740 pci_break_tag(tag,NULL,&bus,&device,&function);
741 xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
742 xprintf(": %04X\n",M.x86.R_CX);
743 #endif
744 M.x86.R_AH = PCIBIOS_SUCCESSFUL;
745 CLEAR_FLAG(F_CF);
746 break;
748 case PCIBIOS_FN_WRCFGDWORD:
749 regs2tag(&tag);
750 pci_conf_write(tag,M.x86.R_DI,M.x86.R_ECX);
751 #if VGAINIT_NOISY
752 xprintf("Int1A: Write Cfg Dword %04X to ",M.x86.R_DI);
753 pci_break_tag(tag,NULL,&bus,&device,&function);
754 xprintf("Bus%d, Dev%d, Func%d",bus,device,function);
755 xprintf(": %08X\n",M.x86.R_ECX);
756 #endif
757 M.x86.R_AH = PCIBIOS_SUCCESSFUL;
758 CLEAR_FLAG(F_CF);
759 break;
761 default:
762 #if VGAINIT_NOISY
763 xprintf("Int1A: Unimplemented PCI BIOS function AX=%04x\n", M.x86.R_AX);
764 #endif
765 break;
771 static int x86init(void)
774 * Access functions for I/O ports
776 static X86EMU_pioFuncs piofuncs = {
777 __x86emu_inb,
778 __x86emu_inw,
779 __x86emu_inl,
780 __x86emu_outb,
781 __x86emu_outw,
782 __x86emu_outl
786 * Access functions for memory
788 static X86EMU_memFuncs memfuncs = {
789 __x86emu_rdb,
790 __x86emu_rdw,
791 __x86emu_rdl,
792 __x86emu_wrb,
793 __x86emu_wrw,
794 __x86emu_wrl
798 * Interrupt table
800 void (*funcs[256])(int num);
801 int idx;
804 * Establish hooks in the simulator
806 X86EMU_setupMemFuncs(&memfuncs);
807 X86EMU_setupPioFuncs(&piofuncs);
810 * Decode what X86 software interrupts we need to hook
813 for (idx = 0; idx < 256; idx++) {
814 funcs[idx] = __SIMintunk; /* assume all are bad */
816 funcs[0x42] = __SIMint42; /* int42: video BIOS */
817 funcs[0x1F] = NULL; /* reflect INT1F */
818 funcs[0x43] = NULL; /* reflect INT43 */
819 funcs[0x6D] = __SIMint6D; /* int6D: video BIOS */
821 funcs[0x03] = __SIMint3; /* int3: firmware exit */
822 funcs[0x10] = __SIMint10; /* int10: video BIOS */
823 funcs[0x1A] = __SIMint1A; /* int1A: PCI BIOS */
825 X86EMU_setupIntrFuncs(funcs);
827 x86mem_init(&x86mem);
828 x86mem_hook(&x86mem,0xA0000,__ISAreadmem,__ISAwritemem);
829 x86mem_hook(&x86mem,0xA8000,__ISAreadmem,__ISAwritemem);
830 x86mem_hook(&x86mem,0xB0000,__ISAreadmem,__ISAwritemem);
831 x86mem_hook(&x86mem,0xB8000,__ISAreadmem,__ISAwritemem);
833 return 0;
838 static void x86uninit(void)
840 x86mem_uninit(&x86mem);
844 int vga_probe(void)
846 pcitag_t tag;
848 if (pci_find_class(PCI_CLASS_DISPLAY,0,&tag) == 0) {
849 return 0;
852 return -1;
855 int vga_biosinit(void)
857 physaddr_t biosaddr;
858 pcitag_t tag;
859 uint32_t addr;
860 uint32_t romaddr;
861 uint32_t destaddr;
862 uint32_t stackaddr;
863 uint32_t iretaddr;
864 unsigned int biossize;
865 int bus,device,function;
866 int idx;
867 int res;
869 if (pci_find_class(PCI_CLASS_DISPLAY,0,&tag) == 0) {
870 romaddr = pci_conf_read(tag,PCI_MAPREG_ROM);
871 pci_conf_write(tag,PCI_MAPREG_ROM,romaddr | PCI_MAPREG_ROM_ENABLE);
873 else {
874 xprintf("No suitable VGA device found in the system.\n");
875 return -1;
878 addr = romaddr;
879 addr &= PCI_MAPREG_ROM_ADDR_MASK;
880 #if defined(_P5064_) || defined(_P6064_)
881 biosaddr = cpu_isamap((vm_offset_t) romaddr,0);
882 #else
883 biosaddr = (physaddr_t) romaddr;
884 #endif
887 * Check for the presence of a VGA BIOS on this adapter.
890 if (!((phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+0) == PCIBIOS_ROMSIG1) &&
891 (phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+1) == PCIBIOS_ROMSIG2))) {
892 xprintf("No VGA BIOS on this adapter.\n");
893 pci_conf_write(tag,PCI_MAPREG_ROM,romaddr);
894 return -1;
896 biossize = PCIBIOS_ROMSIZE(phys_read8(biosaddr+PCIBIOS_ROMSIZE_OFFSET));
898 #if VGAINIT_NOISY
899 xprintf("VGA BIOS size is %d bytes\n",biossize);
900 #endif
903 * Initialize the X86 emulator
906 if (x86init() != 0) {
907 xprintf("X86 emulator did not initialize.\n");
908 pci_conf_write(tag,PCI_MAPREG_ROM,romaddr);
909 return -1;
914 destaddr = BIOSRAMLOC;
915 stackaddr = destaddr + biossize + STACKSIZE;
918 * Copy the BIOS from the PCI rom into RAM
921 #if VGAINIT_NOISY
922 xprintf("Copying VGA BIOS to RAM.\n");
923 #endif
925 for (idx = 0; idx < biossize; idx+=4) {
926 uint32_t b;
928 b = phys_read32(biosaddr+idx);
929 x86mem_memcpy(&x86mem,destaddr+idx,(uint8_t *) &b,sizeof(uint32_t));
933 * Gross! The NVidia TNT2 BIOS expects to
934 * find a PC ROM BIOS date (just the slashes)
935 * at the right place in the ROMs.
938 x86mem_memcpy(&x86mem,0xFFFF5,"08/13/99",8);
941 * Turn off the BIOS ROM, we have our copy now.
944 pci_conf_write(tag,PCI_MAPREG_ROM,romaddr);
947 * Point certain vectors at a dummy IRET in our code space.
948 * Some ROMs don't take too kindly to null vectors, like
949 * the 3dfx Voodoo3 BIOS, which makes sure int1a is
950 * filled in before it attempts to call it. The
951 * code here is never really executed, since the emulator
952 * hooks it.
955 iretaddr = stackaddr + IRETOFFSET;
956 __x86emu_wrw(0x1A*4+0,OFFSET(iretaddr));
957 __x86emu_wrw(0x1A*4+2,SEGMENT(iretaddr));
961 * The actual code begins 3 bytes after the beginning of the ROM. Set
962 * the start address to the first byte of executable code.
965 M.x86.R_CS = SEGMENT(destaddr + PCIBIOS_ROMENTRY_OFFSET);
966 M.x86.R_IP = OFFSET(destaddr + PCIBIOS_ROMENTRY_OFFSET);
969 * Set the stack to point after our copy of the ROM
972 M.x86.R_SS = SEGMENT(stackaddr - 8);
973 M.x86.R_SP = OFFSET(stackaddr - 8);
976 * GROSS! The Voodoo3 card expects BP to have
977 * the following value:
980 M.x86.R_BP = 0x197;
983 * The PCI BIOS spec says you pass the bus, device, and function
984 * numbers in the AX register when starting the ROM code.
987 pci_break_tag(tag,NULL,&bus,&device,&function);
988 M.x86.R_AH = bus;
989 M.x86.R_AL = (device << 3) | (function & 7);
992 * Arrange for the return address to point to a little piece
993 * of code that will do an int10 to set text mode, followed
994 * by storing a couple of simple signatures in the registers,
995 * and an int3 to stop the simulator.
997 * The location of this piece of code is just after our
998 * stack, and since the stack grows down, this is in 'stackaddr'
1001 __x86emu_wrw(stackaddr-8,OFFSET(stackaddr));
1002 __x86emu_wrw(stackaddr-6,SEGMENT(stackaddr));
1004 /* copy in the code. */
1006 for (idx = 0; idx < sizeof(x86initcode); idx++) {
1007 __x86emu_wrb(stackaddr+idx,x86initcode[idx]);
1011 * Set up the VGA console descriptor. We need this to process the
1012 * int10's that write firmware copyright notices and such.
1015 vga_init(&vga,(__ISAaddr(VGA_TEXTBUF_COLOR)),outb);
1018 * Launch the simulator.
1021 xprintf("Initializing VGA.\n");
1022 #ifdef DEBUG
1023 X86EMU_trace_on();
1024 #endif
1025 X86EMU_exec();
1028 * Check for the magic exit values in the registers. These get set
1029 * by the code in the array 'x86initcode' that was loaded above
1032 if ((M.x86.R_AX == 0x1234) && (M.x86.R_BX == 0x5678)) res = 0;
1033 else res = -1;
1036 * Done!
1039 x86uninit();
1041 if (res < 0) {
1042 xprintf("VGA initialization failed.\n");
1044 else {
1045 char temp[32];
1046 char *str = "If you can see this message, the VGA has been successfully initialized!\r\n\r\n";
1048 xprintf("VGA initialization successful.\n");
1049 vga_writestr(&vga,str,0x07,strlen(str));
1051 sprintf(temp,"%d",VGA_TEXTMODE_ROWS);
1052 env_setenv("VGA_ROWS",temp,ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN);
1053 sprintf(temp,"%d",VGA_TEXTMODE_COLS);
1054 env_setenv("VGA_COLS",temp,ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN);
1058 return res;
1061 int x86emutest(void)
1063 uint32_t destaddr;
1064 uint32_t stackaddr;
1065 int res;
1068 * Initialize the X86 emulator
1071 if (x86init() != 0) {
1072 xprintf("X86 emulator did not initialize.\n");
1073 return -1;
1076 destaddr = BIOSRAMLOC;
1077 stackaddr = destaddr + 1024;
1080 * Copy the BIOS from the PCI rom into RAM
1083 xprintf("Copying test program to RAM.\n");
1084 x86mem_memcpy(&x86mem,destaddr,x86testcode,sizeof(x86testcode));
1087 * The actual code begins 3 bytes after the beginning of the ROM. Set
1088 * the start address to the first byte of executable code.
1091 M.x86.R_CS = SEGMENT(destaddr + PCIBIOS_ROMENTRY_OFFSET);
1092 M.x86.R_IP = OFFSET(destaddr + PCIBIOS_ROMENTRY_OFFSET);
1095 * Set the stack to point after our copy of the ROM
1098 M.x86.R_SS = SEGMENT(stackaddr - 8);
1099 M.x86.R_SP = OFFSET(stackaddr - 8);
1102 * Launch the simulator.
1105 xprintf("Running X86emu test.\n");
1106 #ifdef DEBUG
1107 X86EMU_trace_on();
1108 #endif
1109 X86EMU_exec();
1112 * Check for the magic exit values in the registers. These get set
1113 * by the code in the array 'x86initcode' that was loaded above
1116 if ((M.x86.R_AX == 0x1234) && (M.x86.R_BX == 0x5678)) res = 0;
1117 else res = -1;
1120 * Done!
1123 x86uninit();
1125 if (res < 0) xprintf("X86emu test failed.\n");
1126 else xprintf("X86emu test successful.\n");
1128 return res;
1133 void vgaraw_dump(char *tail)
1135 physaddr_t biosaddr;
1136 pcitag_t tag;
1137 uint32_t addr;
1138 uint32_t romaddr;
1139 unsigned int biossize;
1140 int idx;
1141 int res;
1143 if (pci_find_class(PCI_CLASS_DISPLAY,0,&tag) == 0) {
1144 romaddr = pci_conf_read(tag,PCI_MAPREG_ROM);
1145 pci_conf_write(tag,PCI_MAPREG_ROM,romaddr | PCI_MAPREG_ROM_ENABLE);
1147 else {
1148 xprintf("No suitable VGA device found in the system.\n");
1149 return ;
1152 addr = romaddr;
1153 addr &= PCI_MAPREG_ROM_ADDR_MASK;
1155 #if defined(_P5064_) || defined(_P6064_)
1156 biosaddr = cpu_isamap((vm_offset_t) romaddr,0);
1157 #else
1158 biosaddr = romaddr;
1159 #endif
1162 * Check for the presence of a VGA BIOS on this adapter.
1165 xprintf("VGA BIOS is mapped to %08X\n",(uint32_t) biosaddr);
1167 if (!((phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+0) == PCIBIOS_ROMSIG1) &&
1168 (phys_read8(biosaddr+PCIBIOS_ROMSIG_OFFSET+1) == PCIBIOS_ROMSIG2))) {
1169 xprintf("No VGA BIOS on this adapter, assuming 32K ROM\n");
1170 biossize = 32768;
1171 return;
1173 else {
1174 biossize = PCIBIOS_ROMSIZE(phys_read8(biosaddr+PCIBIOS_ROMSIZE_OFFSET));
1175 xprintf("VGA BIOS size is %d bytes\n",biossize);
1178 for (idx = 0; idx < biossize; idx+=16) {
1179 xprintf("%04X: ",idx);
1180 for (res = 0; res < 16; res++) {
1181 xprintf("%02X ",phys_read8(biosaddr+idx+res));
1183 xprintf("\n");
1184 if (console_status()) break;
1187 // pci_conf_write(tag,PCI_MAPREG_ROM,romaddr);