summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjhb <jhb@FreeBSD.org>2002-11-22 17:50:47 +0000
committerjhb <jhb@FreeBSD.org>2002-11-22 17:50:47 +0000
commitc532e9c1042c4729b06bc8853da88a03a269625e (patch)
treef1416576e12ca74626ba634e2a66d84d801872db /sys
parent16a0962105073549c567209736af81ded4ef56f8 (diff)
downloadFreeBSD-src-c532e9c1042c4729b06bc8853da88a03a269625e.zip
FreeBSD-src-c532e9c1042c4729b06bc8853da88a03a269625e.tar.gz
Add a function host_pcib_get_bnsno() that attempts to determine the bus
number of the child bus of a host to PCI bridge by reading from proprietary configuration registers in the host to PCI bridge devices. Approved by: re
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/pci_pci.c81
-rw-r--r--sys/dev/pci/pcib_private.h4
2 files changed, 85 insertions, 0 deletions
diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c
index 99424ba..31d97f8 100644
--- a/sys/dev/pci/pci_pci.c
+++ b/sys/dev/pci/pci_pci.c
@@ -445,3 +445,84 @@ pcib_route_interrupt(device_t pcib, device_t dev, int pin)
}
return(intnum);
}
+
+/*
+ * Try to read the bus number of a host-PCI bridge using appropriate config
+ * registers.
+ */
+int
+host_pcib_get_busno(pci_read_config_fn read_config, int bus, int slot, int func,
+ u_int8_t *busnum)
+{
+ u_int32_t id;
+
+ id = read_config(bus, slot, func, PCIR_DEVVENDOR, 4);
+ if (id == 0xffff)
+ return (0);
+
+ switch (id) {
+ case 0x12258086:
+ /* Intel 824?? */
+ /* XXX This is a guess */
+ /* *busnum = read_config(bus, slot, func, 0x41, 1); */
+ *busnum = bus;
+ break;
+ case 0x84c48086:
+ /* Intel 82454KX/GX (Orion) */
+ *busnum = read_config(bus, slot, func, 0x4a, 1);
+ break;
+ case 0x84ca8086:
+ /*
+ * For the 450nx chipset, there is a whole bundle of
+ * things pretending to be host bridges. The MIOC will
+ * be seen first and isn't really a pci bridge (the
+ * actual busses are attached to the PXB's). We need to
+ * read the registers of the MIOC to figure out the
+ * bus numbers for the PXB channels.
+ *
+ * Since the MIOC doesn't have a pci bus attached, we
+ * pretend it wasn't there.
+ */
+ return (0);
+ case 0x84cb8086:
+ switch (slot) {
+ case 0x12:
+ /* Intel 82454NX PXB#0, Bus#A */
+ *busnum = read_config(bus, 0, func, 0xd0, 1);
+ break;
+ case 0x13:
+ /* Intel 82454NX PXB#0, Bus#B */
+ *busnum = read_config(bus, 0, func, 0xd1, 1) + 1;
+ break;
+ case 0x14:
+ /* Intel 82454NX PXB#1, Bus#A */
+ *busnum = read_config(bus, 0, func, 0xd3, 1);
+ break;
+ case 0x15:
+ /* Intel 82454NX PXB#1, Bus#B */
+ *busnum = read_config(bus, 0, func, 0xd4, 1) + 1;
+ break;
+ }
+ break;
+
+ /* ServerWorks -- vendor 0x1166 */
+ case 0x00051166:
+ case 0x00061166:
+ case 0x00081166:
+ case 0x00091166:
+ case 0x00101166:
+ case 0x00111166:
+ case 0x00171166:
+ case 0x01011166:
+ case 0x010f1014:
+ case 0x02011166:
+ case 0x03021014:
+ *busnum = read_config(bus, slot, func, 0x44, 1);
+ break;
+ default:
+ /* Don't know how to read bus number. */
+ return 0;
+ }
+
+ return 1;
+}
diff --git a/sys/dev/pci/pcib_private.h b/sys/dev/pci/pcib_private.h
index ec25172..b6ef8b8 100644
--- a/sys/dev/pci/pcib_private.h
+++ b/sys/dev/pci/pcib_private.h
@@ -58,6 +58,10 @@ struct pcib_softc
u_int8_t seclat; /* secondary bus latency timer */
};
+typedef u_int32_t pci_read_config_fn(int b, int s, int f, int reg, int width);
+
+int host_pcib_get_busno(pci_read_config_fn read_config, int bus,
+ int slot, int func, u_int8_t *busnum);
int pcib_attach(device_t dev);
void pcib_attach_common(device_t dev);
int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result);
OpenPOWER on IntegriCloud