From 83b991afff40e12a8b6756af06a472842edb1a66 Mon Sep 17 00:00:00 2001 From: Eric Biederman Date: Sat, 11 Oct 2003 06:20:25 +0000 Subject: - O2, enums, and switch statements work in romcc - Support for compiling romcc on non x86 platforms - new romc options -msse and -mmmx for specifying extra registers to use - Bug fixes to device the device disable/enable framework and an amd8111 implementation - Move the link specification to the chip specification instead of the path - Allow specifying devices with internal bridges. - Initial via epia support - Opteron errata fixes git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1200 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/pc80/vgabios.c | 851 ++++++++++++++++++++++++++--------------------------- 1 file changed, 425 insertions(+), 426 deletions(-) (limited to 'src/pc80/vgabios.c') diff --git a/src/pc80/vgabios.c b/src/pc80/vgabios.c index 05e3ce33ed..9aebf1d35c 100644 --- a/src/pc80/vgabios.c +++ b/src/pc80/vgabios.c @@ -66,86 +66,86 @@ /* The address arguments to this function are PHYSICAL ADDRESSES */ static void real_mode_switch_call_vga(unsigned long devfn) { - __asm__ __volatile__ - ( - // paranoia -- does ecx get saved? not sure. This is - // the easiest safe thing to do. - "pushal\n" - /* save the stack */ - "mov %esp, __stack\n" - "jmp 1f\n" - "__stack: .long 0\n" - "1:\n" - /* get devfn into %ecx */ - "movl %esp, %ebp\n" - "movl 8(%ebp), %ecx\n" - /* This configures CS properly for real mode. */ - " ljmp $0x28, $__rms_16bit\n" - "__rms_16bit: \n" - ".code16 \n" /* 16 bit code from here on... */ - - /* Load the segment registers w/ properly configured segment - * descriptors. They will retain these configurations (limits, - * writability, etc.) once protected mode is turned off. */ - " mov $0x30, %ax \n" - " mov %ax, %ds \n" - " mov %ax, %es \n" - " mov %ax, %fs \n" - " mov %ax, %gs \n" - " mov %ax, %ss \n" - - /* Turn off protection (bit 0 in CR0) */ - " movl %cr0, %eax \n" - " andl $0xFFFFFFFE, %eax \n" - " movl %eax, %cr0 \n" - - /* Now really going into real mode */ - " ljmp $0, $__rms_real \n" - "__rms_real: \n" - - // put the stack at the end of page zero. - // that way we can easily share it between real and protected, - // since the 16-bit ESP at segment 0 will work for any case. - /* Setup a stack */ - " mov $0x0, %ax \n" - " mov %ax, %ss \n" - " movl $0x1000, %eax \n" - " movl %eax, %esp \n" - /* debugging for RGM */ - " mov $0x11, %al \n" - " outb %al, $0x80\n" - - /* Dump zeros in the other segregs */ - " xor %ax, %ax \n" - " mov %ax, %ds \n" - " mov %ax, %es \n" - " mov %ax, %fs \n" - " mov %ax, %gs \n" - " mov %cx, %ax \n" - " .byte 0x9a, 0x03, 0, 0, 0xc0 \n" - " movb $0x55, %al\noutb %al, $0x80\n" - /* if we got here, just about done. - * Need to get back to protected mode */ - "movl %cr0, %eax\n" - // "andl $0x7FFAFFD1, %eax\n" /* PG,AM,WP,NE,TS,EM,MP = 0 */ - // "orl $0x60000001, %eax\n" /* CD, NW, PE = 1 */ - "orl $0x0000001, %eax\n" /* PE = 1 */ - "movl %eax, %cr0\n" - /* Now that we are in protected mode jump to a 32 bit code segment. */ - "data32 ljmp $0x10, $vgarestart\n" - "vgarestart:\n" - ".code32\n" - " movw $0x18, %ax \n" - " mov %ax, %ds \n" - " mov %ax, %es \n" - " mov %ax, %fs \n" - " mov %ax, %gs \n" - " mov %ax, %ss \n" - ".globl vga_exit\n" - "vga_exit:\n" - " mov __stack, %esp\n" - " popal\n" - ); + __asm__ __volatile__ + ( + // paranoia -- does ecx get saved? not sure. This is + // the easiest safe thing to do. + "pushal\n" + /* save the stack */ + "mov %esp, __stack\n" + "jmp 1f\n" + "__stack: .long 0\n" + "1:\n" + /* get devfn into %ecx */ + "movl %esp, %ebp\n" + "movl 8(%ebp), %ecx\n" + /* This configures CS properly for real mode. */ + " ljmp $0x28, $__rms_16bit\n" + "__rms_16bit: \n" + ".code16 \n" /* 16 bit code from here on... */ + + /* Load the segment registers w/ properly configured segment + * descriptors. They will retain these configurations (limits, + * writability, etc.) once protected mode is turned off. */ + " mov $0x30, %ax \n" + " mov %ax, %ds \n" + " mov %ax, %es \n" + " mov %ax, %fs \n" + " mov %ax, %gs \n" + " mov %ax, %ss \n" + + /* Turn off protection (bit 0 in CR0) */ + " movl %cr0, %eax \n" + " andl $0xFFFFFFFE, %eax \n" + " movl %eax, %cr0 \n" + + /* Now really going into real mode */ + " ljmp $0, $__rms_real \n" + "__rms_real: \n" + + // put the stack at the end of page zero. + // that way we can easily share it between real and protected, + // since the 16-bit ESP at segment 0 will work for any case. + /* Setup a stack */ + " mov $0x0, %ax \n" + " mov %ax, %ss \n" + " movl $0x1000, %eax \n" + " movl %eax, %esp \n" + /* debugging for RGM */ + " mov $0x11, %al \n" + " outb %al, $0x80\n" + + /* Dump zeros in the other segregs */ + " xor %ax, %ax \n" + " mov %ax, %ds \n" + " mov %ax, %es \n" + " mov %ax, %fs \n" + " mov %ax, %gs \n" + " mov %cx, %ax \n" + " .byte 0x9a, 0x03, 0, 0, 0xc0 \n" + " movb $0x55, %al\noutb %al, $0x80\n" + /* if we got here, just about done. + * Need to get back to protected mode */ + "movl %cr0, %eax\n" + // "andl $0x7FFAFFD1, %eax\n" /* PG,AM,WP,NE,TS,EM,MP = 0 */ + // "orl $0x60000001, %eax\n" /* CD, NW, PE = 1 */ + "orl $0x0000001, %eax\n" /* PE = 1 */ + "movl %eax, %cr0\n" + /* Now that we are in protected mode jump to a 32 bit code segment. */ + "data32 ljmp $0x10, $vgarestart\n" + "vgarestart:\n" + ".code32\n" + " movw $0x18, %ax \n" + " mov %ax, %ds \n" + " mov %ax, %es \n" + " mov %ax, %fs \n" + " mov %ax, %gs \n" + " mov %ax, %ss \n" + ".globl vga_exit\n" + "vga_exit:\n" + " mov __stack, %esp\n" + " popal\n" + ); } __asm__ (".text\n""real_mode_switch_end:\n"); extern char real_mode_switch_end[]; @@ -153,53 +153,53 @@ extern char real_mode_switch_end[]; void do_vgabios(void) { - struct pci_dev *dev; - unsigned long busdevfn; - unsigned int rom = 0; - unsigned char *buf; - unsigned int size = 64*1024; - int i; - - for (i=0x400; i<0x500; i++) { - printk_debug("%02x%c", *(unsigned char *)i, i%16==15 ? '\n' : ' '); - *(unsigned char *) i = 0; - } - - for (i=0x400; i<0x500; i++) { - printk_debug("%02x%c", *(unsigned char *)i, i%16==15 ? '\n' : ' '); - } - - dev = pci_find_class(PCI_CLASS_DISPLAY_VGA <<8, NULL); - - if (! dev) { - printk_debug("NO VGA FOUND\n"); - return; - } - printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor, dev->device); - + struct pci_dev *dev; + unsigned long busdevfn; + unsigned int rom = 0; + unsigned char *buf; + unsigned int size = 64*1024; + int i; + + for (i=0x400; i<0x500; i++) { + printk_debug("%02x%c", *(unsigned char *)i, i%16==15 ? '\n' : ' '); + *(unsigned char *) i = 0; + } + + for (i=0x400; i<0x500; i++) { + printk_debug("%02x%c", *(unsigned char *)i, i%16==15 ? '\n' : ' '); + } + + dev = pci_find_class(PCI_CLASS_DISPLAY_VGA <<8, NULL); + + if (! dev) { + printk_debug("NO VGA FOUND\n"); + return; + } + printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor, dev->device); + #ifdef VGABIOS_START - // Use VGA BIOS blob at specified address - rom = VGABIOS_START; + // Use VGA BIOS blob at specified address + rom = VGABIOS_START; #else - pci_read_config32(dev, PCI_ROM_ADDRESS, &rom); - // paranoia - rom = 0xf0000000; - pci_write_config32(dev, PCI_ROM_ADDRESS, rom|1); - printk_debug("rom base, size: %x\n", rom); + pci_read_config32(dev, PCI_ROM_ADDRESS, &rom); + // paranoia + rom = 0xf0000000; + pci_write_config32(dev, PCI_ROM_ADDRESS, rom|1); + printk_debug("rom base, size: %x\n", rom); #endif - buf = (unsigned char *) rom; - if ((buf[0] == 0x55) && (buf[1] = 0xaa)) { - memcpy((void *) 0xc0000, buf, size); - - for(i = 0; i < 16; i++) - printk_debug("0x%x ", buf[i]); - // check signature here later! - busdevfn = (dev->bus->secondary << 8) | dev->devfn; - real_mode_switch_call_vga(busdevfn); - } else - printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]); + buf = (unsigned char *) rom; + if ((buf[0] == 0x55) && (buf[1] = 0xaa)) { + memcpy((void *) 0xc0000, buf, size); + + for(i = 0; i < 16; i++) + printk_debug("0x%x ", buf[i]); + // check signature here later! + busdevfn = (dev->bus->secondary << 8) | dev->devfn; + real_mode_switch_call_vga(busdevfn); + } else + printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]); #ifndef VGABIOS_START - pci_write_config32(dev, PCI_ROM_ADDRESS, 0); + pci_write_config32(dev, PCI_ROM_ADDRESS, 0); #endif } @@ -209,7 +209,7 @@ do_vgabios(void) // to the BIOS. // no longer. Dammit. We have to respond to these. struct realidt { - unsigned short offset, cs; + unsigned short offset, cs; }; // from a handy writeup that andrey found. @@ -228,15 +228,15 @@ struct realidt { // have to do address fixup in this little stub, and calls are absolute // so the handler is relocatable. void handler(void) { - __asm__ __volatile__ ( - ".code16\n" - "idthandle:\n" - " pushal\n" - " movb $0, %al\n" - " ljmp $0, $callbiosint16\n" - "end_idthandle:\n" - ".code32\n" - ); + __asm__ __volatile__ ( + ".code16\n" + "idthandle:\n" + " pushal\n" + " movb $0, %al\n" + " ljmp $0, $callbiosint16\n" + "end_idthandle:\n" + ".code32\n" + ); } @@ -247,79 +247,79 @@ void handler(void) { // REFERENCE parameters. In this way, we can easily get // returns back to the INTx caller (i.e. vgabios) void callbiosint(void) { - __asm__ __volatile__ ( - ".code16\n" - "callbiosint16:\n" - // clean up the int #. To save space we put it in the lower - // byte. But the top 24 bits are junk. - "andl $0xff, %eax\n" - // this push does two things: - // - put the INT # on the stack as a parameter - // - provides us with a temp for the %cr0 mods. - "pushl %eax\n" - "movl %cr0, %eax\n" - //"andl $0x7FFAFFD1, %eax\n" /* PG,AM,WP,NE,TS,EM,MP = 0 */ - //"orl $0x60000001, %eax\n" /* CD, NW, PE = 1 */ - "orl $0x00000001, %eax\n" /* PE = 1 */ - "movl %eax, %cr0\n" - /* Now that we are in protected mode jump to a 32 bit code segment. */ - "data32 ljmp $0x10, $biosprotect\n" - "biosprotect:\n" - ".code32\n" - " movw $0x18, %ax \n" - " mov %ax, %ds \n" - " mov %ax, %es \n" - " mov %ax, %fs \n" - " mov %ax, %gs \n" - " mov %ax, %ss \n" - " call biosint \n" - // back to real mode ... - " ljmp $0x28, $__rms_16bit\n" - "__rms_16bit: \n" - ".code16 \n" /* 16 bit code from here on... */ - - /* Load the segment registers w/ properly configured segment - * descriptors. They will retain these configurations (limits, - * writability, etc.) once protected mode is turned off. */ - " mov $0x30, %ax \n" - " mov %ax, %ds \n" - " mov %ax, %es \n" - " mov %ax, %fs \n" - " mov %ax, %gs \n" - " mov %ax, %ss \n" - - /* Turn off protection (bit 0 in CR0) */ - " movl %cr0, %eax \n" - " andl $0xFFFFFFFE, %eax \n" - " movl %eax, %cr0 \n" - - /* Now really going into real mode */ - " ljmp $0, $__rms_real \n" - "__rms_real: \n" - - /* Setup a stack */ - " mov $0x0, %ax \n" - " mov %ax, %ss \n" - /* ebugging for RGM */ - " mov $0x11, %al \n" - " outb %al, $0x80\n" - " xor %ax, %ax \n" - " mov %ax, %ds \n" - " mov %ax, %es \n" - " mov %ax, %fs \n" - " mov %ax, %gs \n" - // pop the INT # that you pushed earlier - " popl %eax\n" - " popal\n" - " iret\n" - ".code32\n" - ); + __asm__ __volatile__ ( + ".code16\n" + "callbiosint16:\n" + // clean up the int #. To save space we put it in the lower + // byte. But the top 24 bits are junk. + "andl $0xff, %eax\n" + // this push does two things: + // - put the INT # on the stack as a parameter + // - provides us with a temp for the %cr0 mods. + "pushl %eax\n" + "movl %cr0, %eax\n" + //"andl $0x7FFAFFD1, %eax\n" /* PG,AM,WP,NE,TS,EM,MP = 0 */ + //"orl $0x60000001, %eax\n" /* CD, NW, PE = 1 */ + "orl $0x00000001, %eax\n" /* PE = 1 */ + "movl %eax, %cr0\n" + /* Now that we are in protected mode jump to a 32 bit code segment. */ + "data32 ljmp $0x10, $biosprotect\n" + "biosprotect:\n" + ".code32\n" + " movw $0x18, %ax \n" + " mov %ax, %ds \n" + " mov %ax, %es \n" + " mov %ax, %fs \n" + " mov %ax, %gs \n" + " mov %ax, %ss \n" + " call biosint \n" + // back to real mode ... + " ljmp $0x28, $__rms_16bit\n" + "__rms_16bit: \n" + ".code16 \n" /* 16 bit code from here on... */ + + /* Load the segment registers w/ properly configured segment + * descriptors. They will retain these configurations (limits, + * writability, etc.) once protected mode is turned off. */ + " mov $0x30, %ax \n" + " mov %ax, %ds \n" + " mov %ax, %es \n" + " mov %ax, %fs \n" + " mov %ax, %gs \n" + " mov %ax, %ss \n" + + /* Turn off protection (bit 0 in CR0) */ + " movl %cr0, %eax \n" + " andl $0xFFFFFFFE, %eax \n" + " movl %eax, %cr0 \n" + + /* Now really going into real mode */ + " ljmp $0, $__rms_real \n" + "__rms_real: \n" + + /* Setup a stack */ + " mov $0x0, %ax \n" + " mov %ax, %ss \n" + /* ebugging for RGM */ + " mov $0x11, %al \n" + " outb %al, $0x80\n" + " xor %ax, %ax \n" + " mov %ax, %ds \n" + " mov %ax, %es \n" + " mov %ax, %fs \n" + " mov %ax, %gs \n" + // pop the INT # that you pushed earlier + " popl %eax\n" + " popal\n" + " iret\n" + ".code32\n" + ); } enum { - PCIBIOS = 0x1a, - MEMSIZE = 0x12 + PCIBIOS = 0x1a, + MEMSIZE = 0x12 }; int pcibios( @@ -350,116 +350,116 @@ biosint( unsigned long cs_ip, unsigned short stackflags ) { - unsigned long ip; - unsigned long cs; - unsigned long flags; - int ret = -1; - - ip = cs_ip & 0xffff; - cs = cs_ip >> 16; - flags = stackflags; - - printk_debug("biosint: # 0x%lx, eax 0x%lx ebx 0x%lx ecx 0x%lx edx 0x%lx\n", - intnumber, eax, ebx, ecx, edx); - printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi 0x%lx\n", ebp, esp, edi, esi); - printk_debug("biosint: ip 0x%x cs 0x%x flags 0x%x\n", ip, cs, flags); - // cases in a good compiler are just as good as your own tables. - switch (intnumber) { - case 0 ... 15: - // These are not BIOS service, but the CPU-generated exceptions - printk_info("biosint: Oops, exception %u\n", intnumber); - if (esp < 0x1000) { - printk_debug("Stack contents: "); - while (esp < 0x1000) { - printk_debug("0x%04x ", *(unsigned short *) esp); - esp += 2; - } - printk_debug("\n"); - } - printk_debug("biosint: Bailing out\n"); - // "longjmp" - vga_exit(); - break; - - case PCIBIOS: - ret = pcibios( &edi, &esi, &ebp, &esp, - &ebx, &edx, &ecx, &eax, &flags); - break; - case MEMSIZE: - // who cares. - eax = 64 * 1024; - ret = 0; - break; - default: - printk_info(__FUNCTION__ ": Unsupport int #0x%x\n", - intnumber); - break; - } - if (ret) - flags |= 1; // carry flags - else - flags &= ~1; - stackflags = flags; - return ret; + unsigned long ip; + unsigned long cs; + unsigned long flags; + int ret = -1; + + ip = cs_ip & 0xffff; + cs = cs_ip >> 16; + flags = stackflags; + + printk_debug("biosint: # 0x%lx, eax 0x%lx ebx 0x%lx ecx 0x%lx edx 0x%lx\n", + intnumber, eax, ebx, ecx, edx); + printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi 0x%lx\n", ebp, esp, edi, esi); + printk_debug("biosint: ip 0x%x cs 0x%x flags 0x%x\n", ip, cs, flags); + // cases in a good compiler are just as good as your own tables. + switch (intnumber) { + case 0 ... 15: + // These are not BIOS service, but the CPU-generated exceptions + printk_info("biosint: Oops, exception %u\n", intnumber); + if (esp < 0x1000) { + printk_debug("Stack contents: "); + while (esp < 0x1000) { + printk_debug("0x%04x ", *(unsigned short *) esp); + esp += 2; + } + printk_debug("\n"); + } + printk_debug("biosint: Bailing out\n"); + // "longjmp" + vga_exit(); + break; + + case PCIBIOS: + ret = pcibios( &edi, &esi, &ebp, &esp, + &ebx, &edx, &ecx, &eax, &flags); + break; + case MEMSIZE: + // who cares. + eax = 64 * 1024; + ret = 0; + break; + default: + printk_info(__FUNCTION__ ": Unsupport int #0x%x\n", + intnumber); + break; + } + if (ret) + flags |= 1; // carry flags + else + flags &= ~1; + stackflags = flags; + return ret; } -void -setup_realmode_idt(void) { - extern unsigned char idthandle, end_idthandle; - int i; - struct realidt *idts = (struct realidt *) 0; - int codesize = &end_idthandle - &idthandle; - unsigned char *intbyte, *codeptr; - - // for each int, we create a customized little handler - // that just pushes %ax, puts the int # in %al, - // then calls the common interrupt handler. - // this necessitated because intel didn't know much about - // architecture when they did the 8086 (it shows) - // (hmm do they know anymore even now :-) - // obviously you can see I don't really care about memory - // efficiency. If I did I would probe back through the stack - // and get it that way. But that's really disgusting. - for (i = 0; i < 256; i++) { - idts[i].cs = 0; - codeptr = (char*) 4096 + i * codesize; - idts[i].offset = (unsigned) codeptr; - memcpy(codeptr, &idthandle, codesize); - intbyte = codeptr + 3; - *intbyte = i; - } - - // fixed entry points - - // VGA BIOSes tend to hardcode f000:f065 as the previous handler of - // int10. - // calling convention here is the same as INTs, we can reuse - // the int entry code. - codeptr = (char*) 0xff065; - memcpy(codeptr, &idthandle, codesize); - intbyte = codeptr + 3; - *intbyte = 0x42; /* int42 is the relocated int10 */ +void setup_realmode_idt(void) +{ + extern unsigned char idthandle, end_idthandle; + int i; + struct realidt *idts = (struct realidt *) 0; + int codesize = &end_idthandle - &idthandle; + unsigned char *intbyte, *codeptr; + + // for each int, we create a customized little handler + // that just pushes %ax, puts the int # in %al, + // then calls the common interrupt handler. + // this necessitated because intel didn't know much about + // architecture when they did the 8086 (it shows) + // (hmm do they know anymore even now :-) + // obviously you can see I don't really care about memory + // efficiency. If I did I would probe back through the stack + // and get it that way. But that's really disgusting. + for (i = 0; i < 256; i++) { + idts[i].cs = 0; + codeptr = (char*) 4096 + i * codesize; + idts[i].offset = (unsigned) codeptr; + memcpy(codeptr, &idthandle, codesize); + intbyte = codeptr + 3; + *intbyte = i; + } + + // fixed entry points + + // VGA BIOSes tend to hardcode f000:f065 as the previous handler of + // int10. + // calling convention here is the same as INTs, we can reuse + // the int entry code. + codeptr = (char*) 0xff065; + memcpy(codeptr, &idthandle, codesize); + intbyte = codeptr + 3; + *intbyte = 0x42; /* int42 is the relocated int10 */ } enum { - CHECK = 0xb001, - FINDDEV = 0xb102, - READCONFBYTE = 0xb108, - READCONFWORD = 0xb109, - READCONFDWORD = 0xb10a, - WRITECONFBYTE = 0xb10b, - WRITECONFWORD = 0xb10c, - WRITECONFDWORD = 0xb10d + CHECK = 0xb001, + FINDDEV = 0xb102, + READCONFBYTE = 0xb108, + READCONFWORD = 0xb109, + READCONFDWORD = 0xb10a, + WRITECONFBYTE = 0xb10b, + WRITECONFWORD = 0xb10c, + WRITECONFDWORD = 0xb10d }; // errors go in AH. Just set these up so that word assigns // will work. KISS. enum { - PCIBIOS_NODEV = 0x8600, - PCIBIOS_BADREG = 0x8700 + PCIBIOS_NODEV = 0x8600, + PCIBIOS_BADREG = 0x8700 }; int @@ -474,145 +474,144 @@ pcibios( unsigned long *peax, unsigned long *pflags ) { - unsigned long edi = *pedi; - unsigned long esi = *pesi; - unsigned long ebp = *pebp; - unsigned long esp = *pesp; - unsigned long ebx = *pebx; - unsigned long edx = *pedx; - unsigned long ecx = *pecx; - unsigned long eax = *peax; - unsigned long flags = *pflags; - unsigned short func = (unsigned short) eax; - int retval = 0; - unsigned short devid, vendorid, devfn; - short devindex; /* Use short to get rid of gabage in upper half of 32-bit register */ - unsigned char bus; - struct pci_dev *dev; - - switch(func) { - case CHECK: - *pedx = 0x4350; - *pecx = 0x2049; - retval = 0; - break; - case FINDDEV: - { - devid = *pecx; - vendorid = *pedx; - devindex = *pesi; - dev = 0; - while ((dev = pci_find_device(vendorid, devid, dev))) { - if (devindex <= 0) - break; - devindex--; - } - if (dev) { - unsigned short busdevfn; - *peax = 0; - // busnum is an unsigned char; - // devfn is an int, so we mask it off. - busdevfn = (dev->bus->secondary << 8) - | (dev->devfn & 0xff); - printk_debug("0x%x: return 0x%x\n", func, busdevfn); - *pebx = busdevfn; - retval = 0; - } else { - *peax = PCIBIOS_NODEV; - retval = -1; - } - } - break; - case READCONFDWORD: - case READCONFWORD: - case READCONFBYTE: - case WRITECONFDWORD: - case WRITECONFWORD: - case WRITECONFBYTE: - { - unsigned long dword; - unsigned short word; - unsigned char byte; - unsigned char reg; - - devfn = *pebx & 0xff; - bus = *pebx >> 8; - reg = *pedi; - dev = pci_find_slot(bus, devfn); - if (! dev) { - printk_debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn); - // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn! - *peax = PCIBIOS_BADREG; - retval = -1; - } - switch(func) { - case READCONFBYTE: - byte = pci_read_config8(dev, reg); - *pecx = byte; - break; - case READCONFWORD: - word = pci_read_config16(dev, reg); - *pecx = word; - break; - case READCONFDWORD: - dword = pci_read_config32(dev, reg); - *pecx = dword; + unsigned long edi = *pedi; + unsigned long esi = *pesi; + unsigned long ebp = *pebp; + unsigned long esp = *pesp; + unsigned long ebx = *pebx; + unsigned long edx = *pedx; + unsigned long ecx = *pecx; + unsigned long eax = *peax; + unsigned long flags = *pflags; + unsigned short func = (unsigned short) eax; + int retval = 0; + unsigned short devid, vendorid, devfn; + short devindex; /* Use short to get rid of gabage in upper half of 32-bit register */ + unsigned char bus; + struct pci_dev *dev; + + switch(func) { + case CHECK: + *pedx = 0x4350; + *pecx = 0x2049; + retval = 0; + break; + case FINDDEV: + { + devid = *pecx; + vendorid = *pedx; + devindex = *pesi; + dev = 0; + while ((dev = pci_find_device(vendorid, devid, dev))) { + if (devindex <= 0) + break; + devindex--; + } + if (dev) { + unsigned short busdevfn; + *peax = 0; + // busnum is an unsigned char; + // devfn is an int, so we mask it off. + busdevfn = (dev->bus->secondary << 8) + | (dev->devfn & 0xff); + printk_debug("0x%x: return 0x%x\n", func, busdevfn); + *pebx = busdevfn; + retval = 0; + } else { + *peax = PCIBIOS_NODEV; + retval = -1; + } + } break; - case WRITECONFBYTE: - byte = *pecx; - write_config8(dev, reg, byte); - break; - case WRITECONFWORD: - word = *pecx; - write_config16(dev, reg, word); - break; - case WRITECONFDWORD: - word = *pecx; - write_config32(dev, reg, dword); + case READCONFDWORD: + case READCONFWORD: + case READCONFBYTE: + case WRITECONFDWORD: + case WRITECONFWORD: + case WRITECONFBYTE: + { + unsigned long dword; + unsigned short word; + unsigned char byte; + unsigned char reg; + + devfn = *pebx & 0xff; + bus = *pebx >> 8; + reg = *pedi; + dev = pci_find_slot(bus, devfn); + if (! dev) { + printk_debug("0x%x: BAD DEVICE bus %d devfn 0x%x\n", func, bus, devfn); + // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn! + *peax = PCIBIOS_BADREG; + retval = -1; + } + switch(func) { + case READCONFBYTE: + byte = pci_read_config8(dev, reg); + *pecx = byte; + break; + case READCONFWORD: + word = pci_read_config16(dev, reg); + *pecx = word; + break; + case READCONFDWORD: + dword = pci_read_config32(dev, reg); + *pecx = dword; + break; + case WRITECONFBYTE: + byte = *pecx; + write_config8(dev, reg, byte); + break; + case WRITECONFWORD: + word = *pecx; + write_config16(dev, reg, word); + break; + case WRITECONFDWORD: + word = *pecx; + write_config32(dev, reg, dword); + break; + } + + if (retval) + retval = PCIBIOS_BADREG; + printk_debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%lx\n", func, bus, devfn, reg, *pecx); + *peax = 0; + retval = 0; + } break; - } - - if (retval) - retval = PCIBIOS_BADREG; - printk_debug("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%lx\n", func, bus, devfn, reg, *pecx); - *peax = 0; - retval = 0; - } - break; - default: - printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func); - break; - } - - return retval; + default: + printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func); + break; + } + + return retval; } -static void -vga_init(struct chip *chip, enum chip_pass pass) +static void vga_init(struct chip *chip, enum chip_pass pass) { - struct pc80_vgabios_config *conf = - (struct pc80_vgabios_config *)chip->chip_info; - - switch (pass) { - case CONF_PASS_PRE_BOOT: - - break; - - default: - /* nothing yet */ - break; - } + struct pc80_vgabios_config *conf = + (struct pc80_vgabios_config *)chip->chip_info; + + switch (pass) { + case CONF_PASS_PRE_BOOT: + + break; + + default: + /* nothing yet */ + break; + } } static void enumerate(struct chip *chip) { - /* don't really need to do anything */ + /* don't really need to do anything */ } struct chip_control southbridge_via_vt8231_control = { - .enumerate = enumerate, - enable: vga_init, - name: "Legacy VGA bios" + .enumerate = enumerate, + .enable = vga_init, + .name = "Legacy VGA bios" }; -- cgit v1.2.3