Date: Tue, 1 Dec 1998 21:01:22 -0700 (MST) From: vanmaren@cs.utah.edu To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: kern/8928: 450NX-based computers only probe the first PCI bus Message-ID: <199812020401.VAA01553@vanmaren.aros.net>
next in thread | raw e-mail | index | archive | help
>Number: 8928 >Category: kern >Synopsis: 450NX-based computers only probe the first PCI bus >Confidential: no >Severity: critical >Priority: high >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Dec 1 20:10:01 PST 1998 >Last-Modified: >Originator: Kevin Van Maren >Organization: University of Utah >Release: FreeBSD 3.0-CURRENT i386 >Environment: This occurs in both 3.0-CURRENT and 2.2-STABLE with the 450NX chipset. >Description: MIOC: Memory and I/O controller. It connects the CPU bus to the memory subsystem and the PCI controller. PXB: PCI Expander bridge, connects the MIOC to either two 32-bit PCI busses or a 64-bit bus. The MIOC can control one or two PXBs. Any devices not plugged into the first PCI bus simply won't be found. Most current 450NX-based computers are quad-capable with either two 32-bit PCI busses (using one PXB), or with two 32-bit busses and a 64-bit PCI bus (using two PXB chips). In either case, only devices on the first 32-bit PCI bus will be probed, as FreeBSD doesn't know about the other PCI busses. The problem stems from how the PCI busses are provided by the chipset. The processor bus interface attaches to the MIOC, which in turn can connect to either one or two PXB PCI bus controller chips (with either one or two PCI bus interfaces each). Instead of there being one PCI bus with the other busses "bridged" from that one, they are connected in parallel to the MIOC. Fancy circuitry makes it all "work". However, since the PXB chips are probed as regular devices, and not as PCI-PCI bridges, the PCI bus count isn't incremented. Additionally, it is actually possible for the BIOS to skip PCI busses when programming the bus IDs for the PXBs in the MIOC (to allow for hot-plug devices with a PCI-PCI bridge). Also, since the configuration for the PXB is actually controlled by configuration registers in the MIOC, the MIOC must be asked how many PCI busses there are. It would be much cleaner to set up the subordinatebus for each PXB as it is probed, but the info is in the MIOC, not the PXB. >How-To-Repeat: Buy a quad Xeon. Install FreeBSD. Try to use a device not on the first bus. [PCI busses bridged from the first bus will, of course, work, but not the other ones.] >Fix: The hardware knows how to route requests to higher bus numbers properly; the kernel just doesn't know to look for something there. The fix is to read the BIOS-programmed configuration from the MIOC configuration registers. The highest bus number must belong to the last bus on the last PXB, and there are 4 choices. The code just searches backwards until it finds one that has been configured. Here are the patches. Note that I haven't actually tested the ones for 2.2-STABLE, but I think they will work...they do compile. [Unfortunalty, I don't have good access to a 450NX box now.] Patches for 2.2-STABLE: (in src/sys/pci) Index: pcisupport.c =================================================================== RCS file: /usr/lsrc/FreeBSD/CVS/src/sys/pci/pcisupport.c,v retrieving revision 1.40.2.8 diff -u -r1.40.2.8 pcisupport.c --- pcisupport.c 1998-06-17 09:29:09-06 1.40.2.8 +++ pcisupport.c 1998-12-01 20:58:41-07 @@ -172,6 +172,10 @@ return ("Intel 82450KX (Orion) PCI memory controller"); case 0x84c58086: return ("Intel 82454GX (Orion) host to PCI bridge"); + case 0x84ca8086: + return ("Intel 82451NX Memory and I/O Controller"); + case 0x84cb8086: + return ("Intel 82454NX PCI Expander Bridge"); case 0x00051166: return ("Ross (?) host to PCI bridge"); case 0x00221014: @@ -726,6 +730,56 @@ } static void +config_450nx(pcici_t tag) +{ + unsigned long devmap; + int i; + + /* Read the MIOC devmap to determine which PCI expanders are present */ + devmap = (pci_conf_read(tag, 0xd4) >> 16) & 0x3c; + + if (!devmap) { + printf("Error: 450NX MIOC: No PCI Expander Bridge present.\n"); + return; + } + +#if 0 + /* + * This hack is in the spirit of the config_orion() routine. + * It *would* work, except that some 450NX-based servers are + * set up to SKIP PCI busses, presumably to support hot-plug + * PCI cards that contain a single PCI-PCI bridge chip. + */ + + /* Now pciroots just needs to get set to the number of bits set... */ + + pciroots = 0; + for (i = 2; i < 6; i++) + if (devmap & (1 << i)) + pciroots++; +#else + /* + * Since the buses are configured in order, we just have to + * find the highest bus, and use those numbers. + * This is `wrong', but there is nothing else I can really do... + */ + if (devmap & 0x20) { /* B1, 0xd5 */ + pciroots = (pci_conf_read(tag, 0xd4) >> 8) & 0xff; + } else if (devmap & 0x10) { /* A1, 0xd4 */ + pciroots = pci_conf_read(tag, 0xd4) & 0xff; + } else if (devmap & 0x8) { /* B0, 0xd2 */ + pciroots = (pci_conf_read(tag, 0xd0) >> 16) & 0xff; + } else /* if (devmap & 0x4) */ { /* A0, 0xd1 */ + pciroots = (pci_conf_read(tag, 0xd0) >> 8) & 0xff; + } +#endif + + if (bootverbose) + printf("config_450nx: %d PCI busses found\n", pciroots); +} + + +static void chipset_attach (pcici_t config_id, int unit) { switch (pci_conf_read (config_id, PCI_ID_REG)) { @@ -738,6 +792,9 @@ break; case 0x00051166: /* Ross ??? */ config_Ross (config_id); + break; + case 0x84ca8086: /* Intel 450NX */ + config_450nx (config_id); break; } #ifndef PCI_QUIET Patches for 3.0-CURRENT: in src/sys/pci Index: pcisupport.c =================================================================== RCS file: /usr/lsrc/FreeBSD/CVS/src/sys/pci/pcisupport.c,v retrieving revision 1.74 diff -u -r1.74 pcisupport.c --- pcisupport.c 1998-11-26 14:57:52-07 1.74 +++ pcisupport.c 1998-12-01 20:28:31-07 @@ -118,6 +122,7 @@ * XXX Both fixbushigh_orion() and fixbushigh_i1225() are bogus in that way, * that they store the highest bus number to scan in this device's config * data, though it is about PCI buses attached to the CPU independently! + * The same goes for fixbushigh_450nx. */ static void @@ -137,6 +142,57 @@ tag->secondarybus = tag->subordinatebus = sublementarybus +1; } + +/* + * This reads the PCI config space for the 82451NX MIOC in the 450NX + * chipset to determine the PCI bus configuration. + * + * Assuming the BIOS has set up the MIOC properly, this will correctly + * report the number of PCI busses in the system. + * + * A small problem is that the Host to PCI bridge control is in the MIOC, + * while the host-pci bridges are separate PCI devices. So it really + * isn't easily possible to set up the subordinatebus mappings as the + * 82454NX PCI expander bridges are probed, although that makes the + * most sense. + */ +static void +fixbushigh_450nx(pcici_t tag) +{ + int subordinatebus; + unsigned long devmap; + + /* + * Read the DEVMAP field, so we know which fields to check. + * If the Host-PCI bridge isn't marked as present by the BIOS, + * we have to assume it doesn't exist. + * If this doesn't find all the PCI busses, complain to the + * BIOS vendor. There is nothing more we can do. + */ + devmap = pci_cfgread(tag, 0xd6, 2) & 0x3c; + if (!devmap) + panic("450NX MIOC: No host to PCI bridges marked present.\n"); + /* + * Since the buses are configured in order, we just have to + * find the highest bus, and use those numbers. + */ + if (devmap & 0x20) { /* B1 */ + subordinatebus = pci_cfgread(tag, 0xd5, 1); + } else if (devmap & 0x10) { /* A1 */ + subordinatebus = pci_cfgread(tag, 0xd4, 1); + } else if (devmap & 0x8) { /* B0 */ + subordinatebus = pci_cfgread(tag, 0xd2, 1); + } else /* if (devmap & 0x4) */ { /* A0 */ + subordinatebus = pci_cfgread(tag, 0xd1, 1); + } + if (bootverbose) + printf("fixbushigh_450nx: subordinatebus is %d\n", + subordinatebus); + + tag->secondarybus = tag->subordinatebus = subordinatebus; +} + + static void fixwsc_natoma(pcici_t tag) { @@ -231,6 +287,7 @@ case 0x84c58086: return ("Intel 82453KX/GX (Orion) PCI memory controller"); case 0x84ca8086: + fixbushigh_450nx(tag); return ("Intel 82451NX Memory and I/O Controller"); case 0x84cb8086: return ("Intel 82454NX PCI Expander Bridge"); >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199812020401.VAA01553>