diff --git a/sys/dev/pci/pci_pci.c b/sys/dev/pci/pci_pci.c index 99424bac26e3..31d97f814239 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 ec25172a144f..b6ef8b85fed1 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);