Index: oldkernel/linux/arch/i386/kernel/bios32.c diff -u linux/arch/i386/kernel/bios32.c:1.1.1.1 linux/arch/i386/kernel/bios32.c:1.2 --- linux/arch/i386/kernel/bios32.c:1.1.1.1 Wed May 31 12:33:53 2000 +++ linux/arch/i386/kernel/bios32.c Thu Jun 1 14:11:18 2000 @@ -1,7 +1,7 @@ /* * bios32.c - Low-Level PCI Access * - * $Id: bios32.c,v 1.48 1998/09/26 08:06:55 mj Exp $ + * $Id: bios32.c,v 1.1.1.1 2000/05/31 19:33:53 ccr Exp $ * * Copyright 1993, 1994 Drew Eckhardt * Visionary Computing @@ -1030,6 +1030,56 @@ * Exceptions for specific devices. Usually work-arounds for fatal design flaws. */ +static void __init pci_fixup_peer_bus_scan(unsigned char busno, unsigned char busmax) +{ + struct pci_bus *bus; + if((busno == 0) && (busmax > 0)) + busno++; + while(busno != 0) { + pci_scan_peer_bridge(busno); + for(bus=&pci_root;bus;bus=bus->next) + if(bus->number == busno) + break; + if(bus==NULL) { + return; + } + if(bus->subordinate < busmax) + busno = bus->subordinate + 1; + else + busno = 0; + } +} + +static void __init pci_fixup_rcc(struct pci_dev *d) +{ + /* + * Find and scan busses behind RCC LE north bridge chips + */ + struct pci_bus *bus; + unsigned char busno, busmax; + pci_probe |= PCI_NO_PEER_FIXUP; + pci_read_config_byte(d, 0x44, &busno); + pci_read_config_byte(d, 0x45, &busmax); + printk("PCI: Scanning RCC HE/LE Peer Bus Bridge %02x/%02x\n", + PCI_SLOT(d->devfn), PCI_FUNC(d->devfn)); + pci_fixup_peer_bus_scan(busno, busmax); +} + +static void __init pci_fixup_compaq(struct pci_dev *d) +{ + /* + * Find and scan busses behind RCC LE north bridge chips + */ + struct pci_bus *bus; + unsigned char busno, busmax; + pci_probe |= PCI_NO_PEER_FIXUP; + pci_read_config_byte(d, 0xc8, &busno); + pci_read_config_byte(d, 0xc9, &busmax); + printk("PCI: Scanning Compaq Peer Bus Bridge %02x/%02x\n", + PCI_SLOT(d->devfn), PCI_FUNC(d->devfn)); + pci_fixup_peer_bus_scan(busno, busmax); +} + static void __init pci_fixup_i450nx(struct pci_dev *d) { /* @@ -1043,10 +1093,7 @@ pci_read_config_byte(d, reg++, &suba); pci_read_config_byte(d, reg++, &subb); DBG("i450NX PXB %d: %02x/%02x/%02x\n", pxb, busno, suba, subb); - if (busno) - pci_scan_peer_bridge(busno); /* Bus A */ - if (suba < subb) - pci_scan_peer_bridge(suba+1); /* Bus B */ + pci_fixup_peer_bus_scan(busno,subb); } pci_probe |= PCI_NO_PEER_FIXUP; } @@ -1071,6 +1118,9 @@ static struct dev_ex __initdata dev_ex_table[] = { { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82451NX, pci_fixup_i450nx, "Scanning peer host bridges" }, + { PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_HE, pci_fixup_rcc, "Scanning peer host bridges" }, + { PCI_VENDOR_ID_RCC, PCI_DEVICE_ID_RCC_LE, pci_fixup_rcc, "Scanning peer host bridges" }, + { PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_6010, pci_fixup_compaq, "Scanning peer host bridges" }, { PCI_VENDOR_ID_UMC, PCI_DEVICE_ID_UMC_UM8886BF, pci_fixup_umc_ide, "Working around UM8886BF bugs" } }; Index: oldkernel/linux/drivers/pci/oldproc.c diff -u linux/drivers/pci/oldproc.c:1.2 linux/drivers/pci/oldproc.c:1.3 --- linux/drivers/pci/oldproc.c:1.2 Wed May 31 14:56:52 2000 +++ linux/drivers/pci/oldproc.c Thu Jun 1 14:11:18 2000 @@ -1,5 +1,5 @@ /* - * $Id: oldproc.c,v 1.1.1.1 2000/05/31 19:33:52 ccr Exp $ + * $Id: oldproc.c,v 1.2 2000/05/31 21:56:52 ccr Exp $ * * Backward-compatible procfs interface for PCI. * @@ -36,6 +36,7 @@ */ struct pci_dev_info dev_info[] = { DEVICE( COMPAQ, COMPAQ_1280, "QVision 1280/p"), + DEVICE( COMPAQ, COMPAQ_6010, "Hot Plug PCI Bridge"), DEVICE( COMPAQ, COMPAQ_SMART2P, "Smart-2/P RAID Controller"), DEVICE( COMPAQ, COMPAQ_NETEL100,"Netelligent 10/100"), DEVICE( COMPAQ, COMPAQ_NETEL10, "Netelligent 10"), @@ -411,6 +412,8 @@ DEVICE( MUTECH, MUTECH_MV1000, "MV-1000"), DEVICE( RENDITION, RENDITION_VERITE,"Verite 1000"), DEVICE( RENDITION, RENDITION_VERITE2100,"Verite 2100"), + DEVICE( RCC, RCC_HE, "CNB20HE PCI Bridge"), + DEVICE( RCC, RCC_LE, "CNB30LE PCI Bridge"), DEVICE( TOSHIBA, TOSHIBA_601, "Laptop"), DEVICE( TOSHIBA, TOSHIBA_TOPIC95,"ToPIC95"), DEVICE( TOSHIBA, TOSHIBA_TOPIC97,"ToPIC97"), Index: oldkernel/linux/drivers/pci/pci.c diff -u linux/drivers/pci/pci.c:1.1.1.1 linux/drivers/pci/pci.c:1.2 --- linux/drivers/pci/pci.c:1.1.1.1 Wed May 31 12:33:52 2000 +++ linux/drivers/pci/pci.c Thu Jun 1 14:11:18 2000 @@ -1,5 +1,5 @@ /* - * $Id: pci.c,v 1.91 1999/01/21 13:34:01 davem Exp $ + * $Id: pci.c,v 1.1.1.1 2000/05/31 19:33:52 ccr Exp $ * * PCI Bus Services, see include/linux/pci.h for further explanation. * @@ -282,6 +282,14 @@ * all PCI-to-PCI bridges on this bus. */ pcibios_fixup_bus(bus); + /* + * The fixup code may have just found some peer pci bridges on this + * machine. Update the max variable if that happened so we don't + * get duplicate bus numbers. + */ + for(child=&pci_root; child; child=child->next) + max=((max > child->subordinate) ? max : child->subordinate); + for(dev=bus->devices; dev; dev=dev->sibling) /* * If it's a bridge, scan the bus behind it. @@ -292,6 +300,37 @@ unsigned short cr; /* + * Check for a duplicate bus. If we already scanned + * this bus number as a peer bus, don't also scan it + * as a child bus + */ + if( + ((dev->vendor == PCI_VENDOR_ID_RCC) && + ((dev->device == PCI_DEVICE_ID_RCC_HE) || + (dev->device == PCI_DEVICE_ID_RCC_LE))) || + ((dev->vendor == PCI_VENDOR_ID_COMPAQ) && + (dev->device == PCI_DEVICE_ID_COMPAQ_6010)) || + ((dev->vendor == PCI_VENDOR_ID_INTEL) && + ((dev->device == PCI_DEVICE_ID_INTEL_82454NX) || + (dev->device == PCI_DEVICE_ID_INTEL_82451NX))) + ) + goto skip_it; + /* + * Read the existing primary/secondary/subordinate bus + * number configuration to determine if the PCI bridge + * has already been configured by the system. If so, + * check to see if we've already scanned this bus as + * a result of peer bus scanning, if so, skip this. + */ + pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses); + if ((buses & 0xFFFFFF) != 0) + { + for(child=pci_root.next;child;child=child->next) + if(child->number == ((buses >> 8) & 0xff)) + goto skip_it; + } + + /* * Insert it into the tree of buses. */ child = kmalloc(sizeof(*child), GFP_ATOMIC); @@ -363,6 +402,7 @@ pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses); } pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr); +skip_it: } /* @@ -380,6 +420,12 @@ { struct pci_bus *b; + b = &pci_root; + while((b != NULL) && (bus != 0)) { + if(b->number == bus) + return(b); + b = b->next; + } b = kmalloc(sizeof(*b), GFP_KERNEL); memset(b, 0, sizeof(*b)); b->next = pci_root.next; Index: oldkernel/linux/include/linux/pci.h diff -u linux/include/linux/pci.h:1.2 linux/include/linux/pci.h:1.3 --- linux/include/linux/pci.h:1.2 Wed May 31 14:56:52 2000 +++ linux/include/linux/pci.h Thu Jun 1 14:11:18 2000 @@ -1,5 +1,5 @@ /* - * $Id: pci.h,v 1.1.1.1 2000/05/31 19:33:48 ccr Exp $ + * $Id: pci.h,v 1.2 2000/05/31 21:56:52 ccr Exp $ * * PCI defines and function prototypes * Copyright 1994, Drew Eckhardt @@ -287,6 +287,7 @@ #define PCI_DEVICE_ID_COMPAQ_TOKENRING 0x0508 #define PCI_DEVICE_ID_COMPAQ_1280 0x3033 #define PCI_DEVICE_ID_COMPAQ_TRIFLEX 0x4000 +#define PCI_DEVICE_ID_COMPAQ_6010 0x6010 #define PCI_DEVICE_ID_COMPAQ_SMART2P 0xae10 #define PCI_DEVICE_ID_COMPAQ_NETEL100 0xae32 #define PCI_DEVICE_ID_COMPAQ_NETEL10 0xae34 @@ -856,6 +857,10 @@ #define PCI_VENDOR_ID_RENDITION 0x1163 #define PCI_DEVICE_ID_RENDITION_VERITE 0x0001 #define PCI_DEVICE_ID_RENDITION_VERITE2100 0x2000 + +#define PCI_VENDOR_ID_RCC 0x1166 +#define PCI_DEVICE_ID_RCC_HE 0x0008 +#define PCI_DEVICE_ID_RCC_LE 0x0009 #define PCI_VENDOR_ID_TOSHIBA 0x1179 #define PCI_DEVICE_ID_TOSHIBA_601 0x0601