Subject: Re: 3c905 (ex) in beige g3 problem
To: None <port-macppc@netbsd.org>
From: Tim Kelly <hockey@dialectronics.com>
List: port-macppc
Date: 10/12/2004 15:45:17
On Tue, 12 Oct 2004 15:09:22 -0400
Michael <macallan18@earthlink.net> wrote:

> > The previously posted OF printout indicates that AAPL,interrupt is
> > 0x19(irq 25), which means that at OF did at least assign an
> > interrupt to the card.
> Yep, so a fix should be trivial.

Indeed, the fix turns out to be two lines.

> I don't think the ex driver needs any change - I'd suggest looking at
> pci_machdep.c first to see what goes wrong and why.

Good call. In fixpci (pci_machdep.c), on a grackle equipped PowerMac,
the first line:

len = OF_getprop(parent, "#interrupt-cells", &ilen, sizeof(ilen));

will return a value greater than zero. Later, 

if (ilen == 0) {
			/*
			 * Early Apple OFW implementation don't handle
			 * interrupts as defined by the OFW PCI bindings.
			 */
			len = OF_getprop(node, "AAPL,interrupts", irqs, 4);
		} else {
			iaddr.phys_hi = addr[0].phys_hi;
			iaddr.phys_mid = addr[0].phys_mid;
			iaddr.phys_lo = addr[0].phys_lo;
			/*
			 * Thankfully, PCI can only have one entry in its
			 * "interrupts" property.
			 */
			len = OF_getprop(node, "interrupts", &iaddr.icells[0],
			    4*ilen);
			if (len != 4*ilen)
				continue;
			len = find_node_intr(node, &iaddr.phys_hi, irqs);
		}

will go to the else statement and then into find_node_intr. In
find_node_intr, 

	len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
	mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask));

	if (mlen != -1)
		memcpy(maskedaddr, addr, mlen);
again:
	if (len == -1 || mlen == -1)
		goto nomap;

will go to nomap, because grackle has the following .properties:

ff83c410: /pci@80000000                [grackle]
[...]
0 > dev /pci@80000000  ok
0 > .properties 
name                    pci
device_type             pci
model                   MOT,PPC106
8259-interrupt-acknowledge 
                        fef00000 
reg                     80000000  7f000000 
#address-cells          00000003 
#size-cells             00000002 
#interrupt-cells        00000001 
clock-frequency         01fca055 
slot-names              0000e000 41310042 31004331 00
ranges                  01000000 00000000 00000000  fe000000  00000000
00800000                         02000000 00000000 00000000  fd000000 
00000000 01000000                         02000000 00000000 80000000 
80000000  00000000 7d000000 compatible              grackle
bus-range               00000000 00000000 

Grackle does not have interrupt-map nor interrupt-map-mask. Nomap has 

	memset(name, 0, sizeof(name));
	OF_getprop(parent, "name", name, sizeof(name));
	if (strcmp(name, "pci-bridge") == 0) {
		len = OF_getprop(parent, "AAPL,interrupts", intr, 4) ;
		if (len == 4)
			return len;
	}

<snip #if 0>

	return -1;

Grackle is "pci", not "pci-bridge" so find_node_intr returns -1. Back in
fixpci, if -1 is the value, no interrupt is set in the interrupt
register:

		if (len > 0) {
			intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
			intr &= ~PCI_INTERRUPT_LINE_MASK;
			intr |= irqs[0] & PCI_INTERRUPT_LINE_MASK;
			pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
		}


So the fix appears to be quite trivial:

		if (len != 4*ilen)
			continue;
		len = find_node_intr(node, &iaddr.phys_hi, irqs);
		if (len == -1)
			len = OF_getprop(node, "AAPL,interrupts", irqs, 4);

The code just defaults to extracting the interrupt manually. A snippet
of the dmesg with this applied:

NetBSD 2.0_RC4 (MACWORK1) #9: Wed Oct 13 00:58:19 MEST 2004
  	  root@basis:/usr/src/sys/arch/macppc/compile/MACWORK1
  [...]
  pchb0: Motorola MPC106 "Grackle" Host Bridge (rev. 0x40)
  ex0 at pci0 dev 15 function 0: 3Com 3c905B-TX 10/100 Ethernet (rev.
0x30)  
  ex0: interrupting at irq 25  
  ex0: MAC address 00:50:da:df:12:e6
  exphy0 at ex0 phy 24: 3Com internal media interface
  exphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto

and a patch courtesy of Markus Kilbinger (who also provided the above
dmesg):

[Wed Oct 13 01:31:17 basis pci]$ cvs diff -bu pci_machdep.c
Index: pci_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/arch/macppc/pci/pci_machdep.c,v
retrieving revision 1.24.2.1
diff -b -u -r1.24.2.1 pci_machdep.c
--- pci_machdep.c       9 Apr 2004 02:31:12 -0000       1.24.2.1
+++ pci_machdep.c       12 Oct 2004 23:31:30 -0000
@@ -363,6 +363,8 @@
                     if (len != 4*ilen)
                              continue;
                     len = find_node_intr(node, &iaddr.phys_hi,irqs);
+                   if (len == -1)
+                       len=OF_getprop(node,"AAPL,interrupts",irqs,4);
                     }
                     if (len > 0) {
                        intr = pci_conf_read(pc, tag,PCI_INTERRUPT_REG);

(I had a lot of problems getting sylpheed to not wrap the lines
improperly, so hopefully the patch will apply properly)


This is very likely to affect all grackle equipped PowerMacs which will
lead to not properly mapping interrupts any PCI cards present. The two
lines are a quick fix so that no big changes have to be made and can
(ideally) get into the next RC.

tim