summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2005-11-08 19:04:56 +0000
committerKristian Høgsberg <krh@redhat.com>2005-11-08 19:04:56 +0000
commitf8430a1b8651f4b52d9d3b54694a60d929b48925 (patch)
treed907a72e2da7758e87fdb8ad6a890872e59b63ca
parent5390c7ab05d23f64e6d9afaa558be246a6d6e1b4 (diff)
Bug #2880, add functions for byte and word level access to pci config
space. Fix broken utf8 again.
-rw-r--r--hw/xfree86/os-support/bus/Pci.c61
-rw-r--r--hw/xfree86/os-support/bus/Pci.h11
-rw-r--r--hw/xfree86/os-support/bus/linuxPci.c70
3 files changed, 128 insertions, 14 deletions
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();
+
+ 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));
+ 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);
+
+ pciInit();
+
+ if ((bus >= 0) && ((bus < pciNumBuses) || inProbe) && pciBusInfo[bus] &&
+ pciBusInfo[bus]->funcs->pciReadByte) {
+ CARD8 rv = (*pciBusInfo[bus]->funcs->pciReadByte)(tag, offset);
- tmp = pciReadLong(tag, aligned_offset);
+ return(rv);
+ } else {
+ tmp = pciReadLong(tag, aligned_offset);
- return((CARD8)((tmp >> shift) & 0xff));
+ 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
/*