--- xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.c 2005-11-08 11:04:56.000000000 -0800 +++ xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.c 2006-06-29 15:48:37.000000000 -0700 @@ -233,6 +233,8 @@ static pciConfigPtr pci_devp[MAX_PCI_DEVICES + 1] = {NULL, }; +static int (*pciOSHandleBIOS)(PCITAG Tag, int basereg, unsigned char *buf, int len); + /* * Platform specific PCI function pointers. * @@ -266,6 +268,11 @@ #endif } +void pciSetOSBIOSPtr(int (*bios_fn)(PCITAG Tag, int basereg, unsigned char * buf, int len)) +{ + pciOSHandleBIOS = bios_fn; +} + PCITAG pciFindFirst(CARD32 id, CARD32 mask) { @@ -1347,6 +1354,13 @@ PCITAG *pTag; int i; + /* fall back to the old code if the OS code fails */ + if (pciOSHandleBIOS) { + n = pciOSHandleBIOS(Tag, basereg, func, ptr); + if (n) + return n; + } + n = handlePciBIOS(Tag,basereg,func,ptr); if (n) return n; --- xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.h 2005-11-08 11:04:56.000000000 -0800 +++ xc/programs/Xserver/hw/xfree86/os-support/bus/Pci.h 2006-06-29 15:43:50.000000000 -0700 @@ -431,6 +431,7 @@ Bool pciMfDev(int, int); ADDRESS pciAddrNOOP(PCITAG tag, PciAddrType type, ADDRESS); +extern void pciSetOSBIOSPtr(int (*bios_fn)(PCITAG Tag, int basereg, unsigned char * buf, int len)); extern PCITAG (*pciFindFirstFP)(void); extern PCITAG (*pciFindNextFP)(void); --- xc/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c 2005-11-08 11:04:56.000000000 -0800 +++ xc/programs/Xserver/hw/xfree86/os-support/bus/linuxPci.c 2006-06-29 15:43:50.000000000 -0700 @@ -73,6 +73,7 @@ static void linuxPciCfgWriteByte(PCITAG tag, int off, CARD8 val); static CARD16 linuxPciCfgReadWord(PCITAG tag, int off); static void linuxPciCfgWriteWord(PCITAG tag, int off, CARD16 val); +static int linuxPciHandleBIOS(PCITAG Tag, int basereg, unsigned char *buf, int len); static pciBusFuncs_t linuxFuncs0 = { /* pciReadLong */ linuxPciCfgRead, @@ -125,6 +126,7 @@ pciBusInfo[0] = &linuxPci0; pciFindFirstFP = pciGenFindFirst; pciFindNextFP = pciGenFindNext; + pciSetOSBIOSPtr(linuxPciHandleBIOS); } static int @@ -892,3 +894,44 @@ } #endif /* !INCLUDE_XF86_NO_DOMAIN */ + +int linuxPciHandleBIOS(PCITAG Tag, int basereg, unsigned char *buf, int len) +{ + unsigned int dom, bus, dev, func; + unsigned int fd; + char file[256]; + struct stat st; + int ret; + int sofar = 0; + + dom = PCI_DOM_FROM_TAG(Tag); + bus = PCI_BUS_FROM_TAG(Tag); + dev = PCI_DEV_FROM_TAG(Tag); + func = PCI_FUNC_FROM_TAG(Tag); + sprintf(file, "/sys/bus/pci/devices/%04x:%02x:%02x.%1x/rom", + dom, bus, dev, func); + + if (stat(file, &st) == 0) + { + if ((fd = open(file, O_RDWR))) + basereg = 0x0; + + /* enable the ROM first */ + write(fd, "1", 2); + lseek(fd, 0, SEEK_SET); + do { + /* copy the ROM until we hit Len, EOF or read error */ + ret = read(fd, buf+sofar, len-sofar); + if (ret <= 0) + break; + sofar += ret; + } while (sofar < len); + + write(fd, "0", 2); + close(fd); + if (sofar < len) + xf86MsgVerb(X_INFO, 3, "Attempted to read BIOS %dKB from %s: got %dKB\n", len/1024, file, sofar/1024); + return sofar; + } + return 0; +}