Subject: re: E250 support?
To: None <eeh@netbsd.org>
From: matthew green <mrg@eterna.com.au>
List: port-sparc64
Date: 02/07/2001 12:36:14
   I have a possible fix.  Can you build kernels?


actually, eeh and i discussed this and i have a change that should work.
i've tested it on my U5 and i'll upload a GENERIC kernel shortly.  once
it is verified to work on the 250, i'll commit to -current.


.mrg.


patch for pci_machdep.c for those interested.  it also fixes a bug
where io/mem space weren't (force) enabled for devices without an
"interrupts" property.


Index: pci_machdep.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sparc64/dev/pci_machdep.c,v
retrieving revision 1.18
diff -p -r1.18 pci_machdep.c
*** pci_machdep.c	2001/01/19 21:25:19	1.18
--- pci_machdep.c	2001/02/07 01:33:23
*************** pci_attach_hook(parent, self, pba)
*** 85,91 ****
  	char *name, *devtype;
  	u_int32_t hi, mid, lo, intr;
  	u_int32_t dev, fn, bus;
! 	int node, i, n, *ip, *ap;
  
  	DPRINTF((SPDB_INTFIX|SPDB_INTMAP), ("\npci_attach_hook:"));
  
--- 85,91 ----
  	char *name, *devtype;
  	u_int32_t hi, mid, lo, intr;
  	u_int32_t dev, fn, bus;
! 	int node, i, n, real_intr, *ip, *ap;
  
  	DPRINTF((SPDB_INTFIX|SPDB_INTMAP), ("\npci_attach_hook:"));
  
*************** pci_attach_hook(parent, self, pba)
*** 144,152 ****
  		/* if there isn't any "interrupts" then we don't care to fix it */
  		ip = NULL;
  		if (getprop(node, "interrupts", sizeof(int), &n, (void **)&ip))
! 			continue;
  		DPRINTF(SPDB_INTFIX, (" got interrupts"));
! 		
  		/* and if there isn't an "assigned-addresses" we can't find b/d/f */
  		if (getprop(node, "assigned-addresses", sizeof(int), &n,
  		    (void **)&ap))
--- 144,152 ----
  		/* if there isn't any "interrupts" then we don't care to fix it */
  		ip = NULL;
  		if (getprop(node, "interrupts", sizeof(int), &n, (void **)&ip))
! 			goto enable_iomem;
  		DPRINTF(SPDB_INTFIX, (" got interrupts"));
! 
  		/* and if there isn't an "assigned-addresses" we can't find b/d/f */
  		if (getprop(node, "assigned-addresses", sizeof(int), &n,
  		    (void **)&ap))
*************** pci_attach_hook(parent, self, pba)
*** 167,172 ****
--- 167,179 ----
  
  		tag = pci_make_tag(pc, bus, dev, fn);
  
+ 		/* if "interrupts" <= 4, we must do the fixup, otherwise, it's done */
+ 		if (*ip > 5) {
+ 			real_intr = *ip;
+ 			i = -1;
+ 			goto found_intr;
+ 		}
+ 
  		DPRINTF(SPDB_INTFIX, ("; tag %08x\n\t; reg: hi %x mid %x lo %x intr %x", tag, pr->phys_hi, pr->phys_mid, pr->phys_lo, *ip));
  		DPRINTF(SPDB_INTFIX, ("\n\t; intmapmask: hi %x mid %x lo %x intr %x", pp->pp_intmapmask.phys_hi, pp->pp_intmapmask.phys_mid,
  										      pp->pp_intmapmask.phys_lo, pp->pp_intmapmask.intr));
*************** pci_attach_hook(parent, self, pba)
*** 179,229 ****
  		DPRINTF(SPDB_INTFIX, ("\n\t; after: hi %x mid %x lo %x intr %x", hi, mid, lo, intr));
  
  		for (i = 0; i < pp->pp_nintmap; i++) {
! 			DPRINTF(SPDB_INTFIX, ("\n\t\tmatching for: hi %x mid %x lo %x intr %x", pp->pp_intmap[i].phys_hi, pp->pp_intmap[i].phys_mid,
! 												pp->pp_intmap[i].phys_lo, pp->pp_intmap[i].intr));
  
  			if (pp->pp_intmap[i].phys_hi != hi ||
  			    pp->pp_intmap[i].phys_mid != mid ||
  			    pp->pp_intmap[i].phys_lo != lo ||
! 			    pp->pp_intmap[i].intr != intr)
  				continue;
! 			DPRINTF(SPDB_INTFIX, ("... BINGO! ..."));
! 			
! 		bingo:
  			/*
  			 * OK!  we found match.  pull out the old interrupt
  			 * register, patch in the new value, and put it back.
  			 */
  			intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
! 			DPRINTF(SPDB_INTFIX, ("\n\t    ; read %x from intreg", intr));
! 
! 			intr = (intr & ~PCI_INTERRUPT_LINE_MASK) |
! 			       (pp->pp_intmap[i].child_intr & PCI_INTERRUPT_LINE_MASK);
! 			DPRINTF((SPDB_INTFIX|SPDB_INTMAP), ("\n\t    ; gonna write %x to intreg", intr));
  			pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
! 			DPRINTF((SPDB_INTFIX|SPDB_INTMAP), ("\n\t    ; reread %x from intreg", intr));
  			break;
- 		}
- 		if (i == pp->pp_nintmap) {
- 			/*
- 			 * Not matched by parent interrupt map. If the
- 			 * interrupt property has the INTMAP_OBIO bit
- 			 * set, assume the PROM has (wrongly) supplied it
- 			 * in the parent's bus format, rather than as a
- 			 * PCI interrupt line number.
- 			 *
- 			 * This seems to be an issue only with the
- 			 * psycho host-to-pci bridge.
- 			 */
- 			if (pp->pp_sc->sc_mode == PSYCHO_MODE_PSYCHO &&
- 			    (*ip & INTMAP_OBIO) != 0) {
- 				DPRINTF((SPDB_INTFIX|SPDB_INTMAP),
- 		("\n\t; PSYCHO: no match but obio interrupt in parent format"));
- 
- 				i = -1; goto bingo; /* XXX - hackish.. */
- 			}
  		}
  
  		/* enable mem & dma if not already */
  		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
  			PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE|PCI_COMMAND_IO_ENABLE);
--- 186,223 ----
  		DPRINTF(SPDB_INTFIX, ("\n\t; after: hi %x mid %x lo %x intr %x", hi, mid, lo, intr));
  
  		for (i = 0; i < pp->pp_nintmap; i++) {
! 			DPRINTF(SPDB_INTFIX, ("\n\t\tmatching for: hi %x mid %x lo %x intr %x child_intr %x", pp->pp_intmap[i].phys_hi, pp->pp_intmap[i].phys_mid,
! 												pp->pp_intmap[i].phys_lo, pp->pp_intmap[i].intr, pp->pp_intmap[i].child_intr));
  
  			if (pp->pp_intmap[i].phys_hi != hi ||
  			    pp->pp_intmap[i].phys_mid != mid ||
  			    pp->pp_intmap[i].phys_lo != lo ||
! 			    (pp->pp_intmap[i].intr != intr && pp->pp_intmap[i].child_intr != intr))
  				continue;
! 
! 			if (pp->pp_intmap[i].child_intr == intr)
! 				DPRINTF(SPDB_INTFIX, ("... BINGO! found it in child_intr ..."));
! 			else
! 				DPRINTF(SPDB_INTFIX, ("... BINGO! found it in intr ..."));
! 			real_intr = pp->pp_intmap[i].child_intr;
! 
! 		found_intr:
  			/*
  			 * OK!  we found match.  pull out the old interrupt
  			 * register, patch in the new value, and put it back.
  			 */
  			intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
! 			DPRINTF(SPDB_INTFIX, ("\t    ; read %x from intreg\n", intr));
! 			intr = (intr & ~PCI_INTERRUPT_LINE_MASK) | (real_intr & PCI_INTERRUPT_LINE_MASK);
! 			DPRINTF((SPDB_INTFIX|SPDB_INTMAP), ("\t    ; gonna write %x to intreg\n", intr));
  			pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
! 			DPRINTF((SPDB_INTFIX|SPDB_INTMAP), ("\t    ; reread %x from intreg\n", intr));
  			break;
  		}
+ 		if (i == pp->pp_nintmap)
+ 			printf("%s: could not find interrupts vector!", self->dv_xname);
  
+ enable_iomem:
  		/* enable mem & dma if not already */
  		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
  			PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_MASTER_ENABLE|PCI_COMMAND_IO_ENABLE);