Subject: port-i386/12880: Some BIOSs lie about the interrupt router device
To: None <>
From: None <>
List: netbsd-bugs
Date: 05/09/2001 12:55:41
>Number:         12880
>Category:       port-i386
>Synopsis:       Some BIOSs lie about the interrupt router device
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    port-i386-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Wed May 09 05:53:00 PDT 2001
>Originator:     David Sainty
>Release:        NetBSD-current 8/5/2001
Dynamic Technology Services and Products Ltd (NZ)
System: NetBSD 1.5R NetBSD 1.5R (TEQUILA) #0: Wed Feb 7 01:43:55 NZDT 2001 i386

	I have a system with an AMD751/756 chipset.  As PCIBIOS_INTR_FIXUP
	support was recently added for this chipset I thought I'd play with
	it.  It didn't work.

	The problem was twofold.  Firstly, the PIR table is set up mostly
	acceptably, but the router device location is incorrect (000:00:0).
	This device is the AMD751, not the AMD756.  The '751 is not
	recognised, and so interrupt fixup fails.

	However, even if it is hard-coded to ignore the '751, the '756 will
	not be found in the subsequent search, because it only looks at
	function 0 on each device, but the router on the '756 is at function
	3, on the power management controller (!??).

	Use PCIBIOS_INTR_FIXUP on a system based on the AMD751/756, and using
	the Award Modular BIOS version 6.00PG... in whatever configuration I

	I hacked the first problem, and for the second problem I made it
	search all functions.  I think there probably isn't a lot that can be
	done for the first problem other than maintaining a list of devices
	that are NOT interrupt routers...

	Might be possible to do some heuristic based on the class code of the
	functions on the nominated device, maybe check that one of the
	functions is a PCI-ISA bridge. [ I don't really like this idea :) ]

	Or maybe it is ALWAYS ok to search if the nominated router function
	appears unsupported...  That would solve my problem, and maybe that is
	the right way to go?  This approach would only be a problem if there
	is a possibility that more than one interrupt router is in the system,
	maybe an unused function on a chip used on an expansion card?  Are
	there other reasons another such device might appear multiple times?
	Perhaps that isn't a reasonable concern, hopefully someone with more
	extensive understanding of the rules of PCI systems could say? (hope
	so! :)

	Oh, by the way, this patch is a proof of concept only, in case it
	isn't obvious :)

--- src/sys/arch/i386/pci/pci_intr_fixup.c.orig	Sun Apr 22 02:30:41 2001
+++ src/sys/arch/i386/pci/pci_intr_fixup.c	Wed May  9 23:45:57 2001
@@ -710,6 +710,8 @@
 	pcitag_t icutag;
 	pcireg_t icuid;
+#define ICU_BOGUS
+#ifndef ICU_BOGUS
 	 * Attempt to initialize our PCI interrupt router.  If
 	 * the PIR Table is present in ROM, use the location
@@ -733,6 +735,7 @@
 		if (piit == NULL)
 			piit = pciintr_icu_lookup(icuid);
 	} else {
 		int device, maxdevs = pci_bus_maxdevs(pc, 0);
@@ -740,6 +743,9 @@
 		 * router.
 		for (device = 0; device < maxdevs; device++) {
+			int function, nfuncs;
+			pcireg_t bhlcr;
 			icutag = pci_make_tag(pc, 0, device, 0);
 			icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
@@ -750,11 +756,34 @@
 			if (PCI_VENDOR(icuid) == 0)
-			piit = pciintr_icu_lookup(icuid);
+			bhlcr = pci_conf_read(pc, icutag, PCI_BHLC_REG);
+			if (PCI_HDRTYPE_MULTIFN(bhlcr))
+				nfuncs = 8;
+			else
+				nfuncs = 1;
+			for (function = 0; function < nfuncs; function++) {
+				icutag = pci_make_tag(pc, 0, device, function);
+				icuid = pci_conf_read(pc, icutag, PCI_ID_REG);
+				/* Invalid vendor ID value? */
+					continue;
+				/* Not invalid, but we've done this ~forever */
+				if (PCI_VENDOR(icuid) == 0)
+					continue;
+				piit = pciintr_icu_lookup(icuid);
+				if (piit != NULL)
+					break;
+			}
 			if (piit != NULL)
+#ifndef ICU_BOGUS
 	if (piit == NULL) {
 		printf("pci_intr_fixup: no compatible PCI ICU found");

--- dmesg post-patch ---

NetBSD 1.5V (CHARTREUSE) #2: Wed May  9 23:45:34 NZST 2001
cpu0: AMD Athlon Model 1 (686-class), 548.97 MHz
cpu0: I-cache 64 KB 64b/line 2-way, D-cache 64 KB 64b/line 2-way
cpu0: features 81f9ff<FPU,VME,DE,PSE,TSC,MSR,PAE,MCE,CX8,SEP,MTRR>
cpu0: features 81f9ff<PGE,MCA,CMOV,FGPAT,MMX>
total memory = 65088 KB
avail memory = 57596 KB
using 839 buffers containing 3356 KB of memory
BIOS32 rev. 0 found at 0xfb390
PCI BIOS rev. 2.1 found at 0xfb3c0
pcibios: config mechanism [1][x], special cycles [1][x], last bus 1
PCI IRQ Routing Table rev. 1.0 found at 0xfde60, size 144 bytes (7 entries)
PCI Interrupt Router at 000:00:0
PCI Exclusive IRQs: 10 11 12
PIR Entry 0:
        Bus: 0  Device: 8
                INTA: link 0x01 bitmap 0xdeb8
                INTB: link 0x02 bitmap 0xdeb8
                INTC: link 0x03 bitmap 0xdeb8
                INTD: link 0x04 bitmap 0xdeb8
PIR Entry 1:
        Bus: 0  Device: 9
                INTA: link 0x02 bitmap 0xdeb8
                INTB: link 0x03 bitmap 0xdeb8
                INTC: link 0x04 bitmap 0xdeb8
                INTD: link 0x01 bitmap 0xdeb8
PIR Entry 2:
        Bus: 0  Device: 10
                INTA: link 0x03 bitmap 0xdeb8
                INTB: link 0x04 bitmap 0xdeb8
                INTC: link 0x01 bitmap 0xdeb8
                INTD: link 0x02 bitmap 0xdeb8
PIR Entry 3:
        Bus: 0  Device: 11
                INTA: link 0x04 bitmap 0xdeb8
                INTB: link 0x01 bitmap 0xdeb8
                INTC: link 0x02 bitmap 0xdeb8
                INTD: link 0x03 bitmap 0xdeb8
PIR Entry 4:
        Bus: 0  Device: 12
                INTA: link 0x01 bitmap 0xdeb8
                INTB: link 0x02 bitmap 0xdeb8
                INTC: link 0x03 bitmap 0xdeb8
                INTD: link 0x04 bitmap 0xdeb8
PIR Entry 5:
        Bus: 0  Device: 7
                INTA: link 0x01 bitmap 0xdeb8
                INTB: link 0x02 bitmap 0xdeb8
                INTC: link 0x03 bitmap 0xdeb8
                INTD: link 0x04 bitmap 0xdeb8
PIR Entry 6:
        Bus: 0  Device: 1
                INTA: link 0x01 bitmap 0xdeb8
                INTB: link 0x02 bitmap 0xdeb8
                INTC: link 0x03 bitmap 0xdeb8
                INTD: link 0x04 bitmap 0xdeb8
pciintr_link_fixup: PIRQ 0x00 not connected
pciintr_link_fixup: PIRQ 0x01 already connected to IRQ 12
pciintr_link_fixup: PIRQ 0x02 already connected to IRQ 10
pciintr_link_fixup: PIRQ 0x03 already connected to IRQ 11
pciintr_link_fixup (stage 2): assigning IRQ 10 to PIRQ 0x00
pciintr_link_route: route of PIRQ 0x01 -> IRQ 12 preserved BIOS setting
pciintr_link_route: route of PIRQ 0x02 -> IRQ 10 preserved BIOS setting
pciintr_link_route: route of PIRQ 0x03 -> IRQ 11 preserved BIOS setting
  device vendor product pin PIRQ IRQ stage
000:07:4 0x1022 0x740c   D  0x03  11  0    already assigned
000:09:0 0x1011 0x0019   A  0x01  12  0    already assigned
000:10:0 0x1073 0x0004   A  0x02  10  0    already assigned
000:11:0 0x12d2 0x0018   A  0x03  11  0    already assigned
PCI bridge 0: primary 0, secondary 1, subordinate 1
PCI bus #1 is the last bus
[System BIOS Setting]-----------------------
  device vendor product
  register space address    size
000:00:0 0x1022 0x7006 
        10h mem  0xd8000000 0x04000000
        14h mem  0xe0009000 0x00001000
        18h port 0x0000e000 0x00000004
000:01:0 0x1022 0x7007 
000:07:0 0x1022 0x7408 
000:07:1 0x1022 0x7409 
        20h port 0x0000f000 0x00000010
000:07:3 0x1022 0x740b 
000:07:4 0x1022 0x740c 
        10h mem  0xe000a000 0x00001000
000:09:0 0x1011 0x0019 
        10h port 0x0000e400 0x00000080
        14h mem  0xe0008000 0x00000400
000:10:0 0x1073 0x0004 
        10h mem  0xe0000000 0x00008000
000:11:0 0x12d2 0x0018 
        10h mem  0xdd000000 0x01000000
        14h mem  0xde000000 0x01000000
--------------------------[  0 devices bogus]
 Physical memory end: 0x03fe0000
 PCI memory mapped I/O space start: 0x04000000
mainbus0 (root)
pci0 at mainbus0 bus 0: configuration mode 1
pci0: i/o space, memory space enabled
pchb0 at pci0 dev 0 function 0
pchb0: Advanced Micro Devices AMD751 System Controller (rev. 0x23)
ppb0 at pci0 dev 1 function 0: Advanced Micro Devices AMD751 PCI-to-PCI Bridge (rev. 0x01)
pci1 at ppb0 bus 1
pci1: i/o space, memory space enabled
pcib0 at pci0 dev 7 function 0
pcib0: Advanced Micro Devices AMD756 PCI-to-ISA Bridge (rev. 0x01)
pciide0 at pci0 dev 7 function 1: Advanced Micro Devices AMD756 IDE Controller (rev. 0x03)
pciide0: bus-master DMA support present
pciide0: primary channel configured to compatibility mode
wd0 at pciide0 channel 0 drive 0: <ST5850A>
wd0: drive supports 32-sector PIO transfers, LBA addressing
wd0: 815 MB, 1656 cyl, 16 head, 63 sec, 512 bytes/sect x 1669260 sectors
wd0: 32-bit data port
wd0: drive supports PIO mode 4, DMA mode 2
pciide0: primary channel interrupting at irq 14
pciide0:0:0: multi-word DMA disabled due to chip revision
wd0(pciide0:0:0): using PIO mode 4
pciide0: secondary channel configured to compatibility mode
atapibus0 at pciide0 channel 1: 2 targets
cd0 at atapibus0 drive 0: <HITACHI DVD-ROM GD-2500, , 0101> type 5 cdrom removable
cd0: 32-bit data port
cd0: drive supports PIO mode 4, DMA mode 2
pciide0: secondary channel interrupting at irq 15
pciide0:1:0: multi-word DMA disabled due to chip revision
cd0(pciide0:1:0): using PIO mode 4
Advanced Micro Devices AMD756 Power Management Controller (miscellaneous bridge, revision 0x03) at pci0 dev 7 function 3 not configured
ohci0 at pci0 dev 7 function 4: Advanced Micro Devices AMD756 USB Host Controller (rev. 0x06)
ohci0: interrupting at irq 11
ohci0: OHCI version 1.0, legacy support
usb0 at ohci0: USB revision 1.0
uhub0 at usb0
uhub0: Advanced Micro OHCI root hub, class 9/0, rev 1.00/1.00, addr 1
uhub0: 4 ports with 4 removable, self powered
tlp0 at pci0 dev 9 function 0: DECchip 21143 Ethernet, pass 4.1
tlp0: interrupting at irq 12
tlp0: Ethernet address 00:80:c8:f7:26:92
ukphy0 at tlp0 phy 8: Generic IEEE 802.3u media interface
ukphy0: Am79C873 10/100 media interface (OUI 0x000676, model 0x0000), rev. 0
ukphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
yds0 at pci0 dev 10 function 0: Yamaha 724 Audio (rev. 0x05)
yds0: interrupting at irq 10
yds0: SigmaTel STAC9704 codec; 18 bit DAC, 18 bit ADC, Rockwell 3D
audio0 at yds0: full duplex, mmap, independent
vga0 at pci0 dev 11 function 0: Nvidia Corporation & SGS Thomson Microelectric Riva 128 (rev. 0x10)
wsdisplay0 at vga0: console (80x25, vt100 emulation)
isa0 at pcib0
com0 at isa0 port 0x3f8-0x3ff irq 4: ns16550a, working fifo
com1 at isa0 port 0x2f8-0x2ff irq 3: ns16550a, working fifo
pckbc0 at isa0 port 0x60-0x64
pckbd0 at pckbc0 (kbd slot)
pckbc0: using irq 1 for kbd slot
wskbd0 at pckbd0: console keyboard, using wsdisplay0
pcppi0 at isa0 port 0x61
midi0 at pcppi0: PC speaker
spkr0 at pcppi0
sysbeep0 at pcppi0
isapnp0 at isa0 port 0x279: ISA Plug 'n Play device support
npx0 at isa0 port 0xf0-0xff: using exception 16
fdc0 at isa0 port 0x3f0-0x3f7 irq 6 drq 2
fd0 at fdc0 drive 0: 1.44MB, 80 cyl, 2 head, 18 sec
isapnp0: no ISA Plug 'n Play devices found
opl0 at yds0: model OPL3
midi1 at opl0: DS-1 integrated Yamaha OPL3
mpu0 at yds0
midi2 at mpu0: Yamaha DS-1 MIDI UART
biomask ebe5 netmask fbe5 ttymask fbe7
IPsec: Initialized Security Association Processing.
uhub1 at uhub0 port 1
uhub1: Texas Instruments UT-USB41 hub, class 9/0, rev 1.10/1.10, addr 2
uhub1: 4 ports with 4 removable, self powered
uhid0 at uhub1 port 3 configuration 1 interface 0
uhid0: Microsoft Microsoft IntelliMouse\M-. Explorer, rev 1.10/1.07, addr 3, iclass 3/1
boot device: wd0
root on wd0a dumps on wd0b
root file system type: ffs