summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorAdam Jackson <ajax@nwnk.net>2006-04-28 22:28:56 +0000
committerAdam Jackson <ajax@nwnk.net>2006-04-28 22:28:56 +0000
commit267133e37732631c74d0f41b9217474188b2bcd4 (patch)
treed8d6f727378c2fcccfd42acf8c4aa61efc51cd57 /hw
parentc28a0c78502757bad606dee692b8dce3d3a747f0 (diff)
Bug #6751: Use sysfs to read card ROMs if available. (Dave Airlie)
Diffstat (limited to 'hw')
-rw-r--r--hw/xfree86/os-support/bus/Pci.c14
-rw-r--r--hw/xfree86/os-support/bus/Pci.h1
-rw-r--r--hw/xfree86/os-support/bus/linuxPci.c43
3 files changed, 58 insertions, 0 deletions
diff --git a/hw/xfree86/os-support/bus/Pci.c b/hw/xfree86/os-support/bus/Pci.c
index 15cd8f461..007c07a34 100644
--- a/hw/xfree86/os-support/bus/Pci.c
+++ b/hw/xfree86/os-support/bus/Pci.c
@@ -236,6 +236,8 @@ static pciConfigPtr pci_devp[MAX_PCI_DEVICES + 1] = {NULL, };
static int readPciBios( PCITAG Tag, CARD8* tmp, ADDRESS hostbase,
unsigned char * buf, int len, PciBiosType BiosType );
+static int (*pciOSHandleBIOS)(PCITAG Tag, int basereg, unsigned char *buf, int len);
+
/*
* Platform specific PCI function pointers.
*
@@ -269,6 +271,11 @@ pciInit()
#endif
}
+void pciSetOSBIOSPtr(int (*bios_fn)(PCITAG Tag, int basereg, unsigned char * buf, int len))
+{
+ pciOSHandleBIOS = bios_fn;
+}
+
_X_EXPORT PCITAG
pciFindFirst(CARD32 id, CARD32 mask)
{
@@ -1279,6 +1286,13 @@ HandlePciBios(PCITAG Tag, int basereg, unsigned char * buf, int len)
PCITAG *pTag;
int i;
+ /* fall back to the old code if the OS code fails */
+ if (pciOSHandleBIOS) {
+ n = pciOSHandleBIOS(Tag, basereg, buf, len);
+ if (n)
+ return n;
+ }
+
n = handlePciBIOS( Tag, basereg, buf, len );
if (n)
return n;
diff --git a/hw/xfree86/os-support/bus/Pci.h b/hw/xfree86/os-support/bus/Pci.h
index 833c07af0..32088fe4f 100644
--- a/hw/xfree86/os-support/bus/Pci.h
+++ b/hw/xfree86/os-support/bus/Pci.h
@@ -425,6 +425,7 @@ CARD32 pciByteSwap(CARD32);
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);
diff --git a/hw/xfree86/os-support/bus/linuxPci.c b/hw/xfree86/os-support/bus/linuxPci.c
index 3dce431a6..092f28f03 100644
--- a/hw/xfree86/os-support/bus/linuxPci.c
+++ b/hw/xfree86/os-support/bus/linuxPci.c
@@ -73,6 +73,7 @@ static CARD8 linuxPciCfgReadByte(PCITAG tag, int off);
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,
@@ -121,6 +122,7 @@ linuxPciInit()
pciBusInfo[0] = &linuxPci0;
pciFindFirstFP = pciGenFindFirst;
pciFindNextFP = pciGenFindNext;
+ pciSetOSBIOSPtr(linuxPciHandleBIOS);
}
static int
@@ -888,3 +890,44 @@ xf86AccResFromOS(resPtr pRes)
}
#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;
+}