diff --git a/hw/xfree86/os-support/bus/Pci.c b/hw/xfree86/os-support/bus/Pci.c index 71c5b2b3b..4e71eb614 100644 --- a/hw/xfree86/os-support/bus/Pci.c +++ b/hw/xfree86/os-support/bus/Pci.c @@ -319,14 +319,24 @@ pciReadWord(PCITAG tag, int offset) CARD32 tmp; int shift = (offset & 3) * 8; int aligned_offset = offset & ~3; + int bus = PCI_BUS_FROM_TAG(tag); if (shift != 0 && shift != 16) FatalError("pciReadWord: Alignment error: Cannot read 16 bits " "at offset %d\n", offset); - tmp = pciReadLong(tag, aligned_offset); + pciInit(); - return((CARD16)((tmp >> shift) & 0xffff)); + if ((bus >= 0) && ((bus < pciNumBuses) || inProbe) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciReadWord) { + CARD32 rv = (*pciBusInfo[bus]->funcs->pciReadWord)(tag, offset); + + return(rv); + } else { + tmp = pciReadLong(tag, aligned_offset); + + return((CARD16)((tmp >> shift) & 0xffff)); + } } CARD8 @@ -335,10 +345,20 @@ pciReadByte(PCITAG tag, int offset) CARD32 tmp; int shift = (offset & 3) * 8; int aligned_offset = offset & ~3; + int bus = PCI_BUS_FROM_TAG(tag); - tmp = pciReadLong(tag, aligned_offset); + pciInit(); - return((CARD8)((tmp >> shift) & 0xff)); + if ((bus >= 0) && ((bus < pciNumBuses) || inProbe) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciReadByte) { + CARD8 rv = (*pciBusInfo[bus]->funcs->pciReadByte)(tag, offset); + + return(rv); + } else { + tmp = pciReadLong(tag, aligned_offset); + + return((CARD8)((tmp >> shift) & 0xff)); + } } void @@ -359,17 +379,25 @@ pciWriteWord(PCITAG tag, int offset, CARD16 val) CARD32 tmp; int aligned_offset = offset & ~3; int shift = (offset & 3) * 8; + int bus = PCI_BUS_FROM_TAG(tag); if (shift != 0 && shift != 16) FatalError("pciWriteWord: Alignment Error: Cannot read 16 bits " "from offset %d\n", offset); - tmp = pciReadLong(tag, aligned_offset); + pciInit(); - tmp &= ~(0xffffL << shift); - tmp |= (((CARD32)val) << shift); + if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciWriteWord) { + (*pciBusInfo[bus]->funcs->pciWriteWord)(tag, offset, val); + } else { + tmp = pciReadLong(tag, aligned_offset); - pciWriteLong(tag, aligned_offset, tmp); + tmp &= ~(0xffffL << shift); + tmp |= (((CARD32)val) << shift); + + pciWriteLong(tag, aligned_offset, tmp); + } } void @@ -378,13 +406,22 @@ pciWriteByte(PCITAG tag, int offset, CARD8 val) CARD32 tmp; int aligned_offset = offset & ~3; int shift = (offset & 3) *8 ; + int bus = PCI_BUS_FROM_TAG(tag); - tmp = pciReadLong(tag, aligned_offset); + pciInit(); - tmp &= ~(0xffL << shift); - tmp |= (((CARD32)val) << shift); + if ((bus >= 0) && (bus < pciNumBuses) && pciBusInfo[bus] && + pciBusInfo[bus]->funcs->pciWriteByte) { + (*pciBusInfo[bus]->funcs->pciWriteByte)(tag, offset, val); + } else { - pciWriteLong(tag, aligned_offset, tmp); + tmp = pciReadLong(tag, aligned_offset); + + tmp &= ~(0xffL << shift); + tmp |= (((CARD32)val) << shift); + + pciWriteLong(tag, aligned_offset, tmp); + } } void diff --git a/hw/xfree86/os-support/bus/Pci.h b/hw/xfree86/os-support/bus/Pci.h index ee6e9d723..70293d3f4 100644 --- a/hw/xfree86/os-support/bus/Pci.h +++ b/hw/xfree86/os-support/bus/Pci.h @@ -194,8 +194,11 @@ ((val >> 8) & 0x0000ff00) | \ ((val << 8) & 0x00ff0000) | \ ((val << 24) & 0xff000000)) +#define PCI_CPU16(val) (((val >> 8) & 0x000000ff) | \ + ((val << 8) & 0x0000ff00)) #else #define PCI_CPU(val) (val) +#define PCI_CPU16(val) (val) #endif /* @@ -382,6 +385,14 @@ typedef struct pci_bus_funcs { void (*pciGetBridgeBuses)(int, int *, int *, int *); /* Use pointer's to avoid #include recursion */ void (*pciGetBridgeResources)(int, pointer *, pointer *, pointer *); + + /* These are optional and will be implemented using read long + * if not present. */ + CARD8 (*pciReadByte)(PCITAG, int); + void (*pciWriteByte)(PCITAG, int, CARD8); + CARD16 (*pciReadWord)(PCITAG, int); + void (*pciWriteWord)(PCITAG, int, CARD16); + } pciBusFuncs_t, *pciBusFuncs_p; /* diff --git a/hw/xfree86/os-support/bus/linuxPci.c b/hw/xfree86/os-support/bus/linuxPci.c index 1ae8e87b6..40fb4604b 100644 --- a/hw/xfree86/os-support/bus/linuxPci.c +++ b/hw/xfree86/os-support/bus/linuxPci.c @@ -69,17 +69,32 @@ static ADDRESS linuxPpcBusAddrToHostAddr(PCITAG, PciAddrType, ADDRESS); static ADDRESS linuxPpcHostAddrToBusAddr(PCITAG, PciAddrType, ADDRESS); #endif +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 pciBusFuncs_t linuxFuncs0 = { /* pciReadLong */ linuxPciCfgRead, /* pciWriteLong */ linuxPciCfgWrite, /* pciSetBitsLong */ linuxPciCfgSetBits, #if defined(__powerpc__) /* pciAddrHostToBus */ linuxPpcHostAddrToBusAddr, -/* pciAddrBusToHost */ linuxPpcBusAddrToHostAddr +/* pciAddrBusToHost */ linuxPpcBusAddrToHostAddr, #else /* pciAddrHostToBus */ pciAddrNOOP, -/* pciAddrBusToHost */ linuxTransAddrBusToHost +/* pciAddrBusToHost */ linuxTransAddrBusToHost, #endif + +/* pciControlBridge */ NULL, +/* pciGetBridgeBuses */ NULL, +/* pciGetBridgeResources */ NULL, + +/* pciReadByte */ linuxPciCfgReadByte, +/* pciWriteByte */ linuxPciCfgWriteByte, + +/* pciReadWord */ linuxPciCfgReadWord, +/* pciWriteWord */ linuxPciCfgWriteWord, }; static pciBusInfo_t linuxPci0 = { @@ -270,6 +285,57 @@ linuxPpcHostAddrToBusAddr(PCITAG tag, PciAddrType type, ADDRESS addr) #endif /* __powerpc__ */ +static CARD8 +linuxPciCfgReadByte(PCITAG tag, int off) +{ + int fd; + CARD8 val = 0xff; + + if (-1 != (fd = linuxPciOpenFile(tag,FALSE))) { + lseek(fd,off,SEEK_SET); + read(fd,&val,1); + } + + return val; +} + +static void +linuxPciCfgWriteByte(PCITAG tag, int off, CARD8 val) +{ + int fd; + + if (-1 != (fd = linuxPciOpenFile(tag,TRUE))) { + lseek(fd,off,SEEK_SET); + write(fd, &val, 1); + } +} + +static CARD16 +linuxPciCfgReadWord(PCITAG tag, int off) +{ + int fd; + CARD16 val = 0xff; + + if (-1 != (fd = linuxPciOpenFile(tag,FALSE))) { + lseek(fd, off, SEEK_SET); + read(fd, &val, 2); + } + + return PCI_CPU16(val); +} + +static void +linuxPciCfgWriteWord(PCITAG tag, int off, CARD16 val) +{ + int fd; + + if (-1 != (fd = linuxPciOpenFile(tag,TRUE))) { + lseek(fd, off, SEEK_SET); + val = PCI_CPU16(val); + write(fd, &val, 2); + } +} + #ifndef INCLUDE_XF86_NO_DOMAIN /*