/* * pcibios code from linuxbios */ #include #undef __KERNEL__ #include void printk(const char *fmt, ...); #define printk_debug printk #define printk_err printk enum { 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 }; int pcibios( unsigned long *pedi, unsigned long *pesi, unsigned long *pebp, unsigned long *pesp, unsigned long *pebx, unsigned long *pedx, unsigned long *pecx, 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 = -1; 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 << 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 int 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: retval = pci_read_config_byte(dev, reg, &byte); *pecx = byte; break; case READCONFWORD: retval = pci_read_config_word(dev, reg, &word); *pecx = word; break; case READCONFDWORD: retval = pci_read_config_dword(dev, reg, &dword); *pecx = dword; break; case WRITECONFBYTE: byte = *pecx; retval = pci_write_config_byte(dev, reg, byte); break; case WRITECONFWORD: word = *pecx; retval = pci_write_config_word(dev, reg, word); break; case WRITECONFDWORD: word = *pecx; retval = pci_write_config_dword(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; default: printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func); break; } return retval; }