Module Name:    src
Committed By:   jdc
Date:           Tue Apr 16 06:57:06 UTC 2013

Modified Files:
        src/sys/arch/sparc/conf: files.sparc
        src/sys/arch/sparc/include: pci_machdep.h
        src/sys/arch/sparc/sparc: autoconf.c msiiep.c msiiepvar.h pci_machdep.c
Added Files:
        src/sys/arch/sparc/sparc: pci_fixup.c pci_fixup.h

Log Message:
Add PCI fixup for MicroSPARC-IIep.
Unconfigured PCI-PCI bridges and devices behind them are configured.


To generate a diff of this commit:
cvs rdiff -u -r1.153 -r1.154 src/sys/arch/sparc/conf/files.sparc
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/sparc/include/pci_machdep.h
cvs rdiff -u -r1.250 -r1.251 src/sys/arch/sparc/sparc/autoconf.c
cvs rdiff -u -r1.43 -r1.44 src/sys/arch/sparc/sparc/msiiep.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/sparc/sparc/msiiepvar.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/sparc/sparc/pci_fixup.c \
    src/sys/arch/sparc/sparc/pci_fixup.h
cvs rdiff -u -r1.17 -r1.18 src/sys/arch/sparc/sparc/pci_machdep.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/sparc/conf/files.sparc
diff -u src/sys/arch/sparc/conf/files.sparc:1.153 src/sys/arch/sparc/conf/files.sparc:1.154
--- src/sys/arch/sparc/conf/files.sparc:1.153	Tue Feb  5 21:52:48 2013
+++ src/sys/arch/sparc/conf/files.sparc	Tue Apr 16 06:57:05 2013
@@ -1,4 +1,4 @@
-#	$NetBSD: files.sparc,v 1.153 2013/02/05 21:52:48 macallan Exp $
+#	$NetBSD: files.sparc,v 1.154 2013/04/16 06:57:05 jdc Exp $
 
 # @(#)files.sparc	8.1 (Berkeley) 7/19/93
 # sparc-specific configuration info
@@ -28,6 +28,7 @@ device mspcic {}: pcibus
 attach mspcic at msiiep
 file	arch/sparc/sparc/msiiep.c		msiiep | mspcic
 file	arch/sparc/sparc/pci_machdep.c		msiiep | mspcic
+file	arch/sparc/sparc/pci_fixup.c		msiiep | mspcic
 
 device ebus {[addr = -1]}
 attach ebus at pci

Index: src/sys/arch/sparc/include/pci_machdep.h
diff -u src/sys/arch/sparc/include/pci_machdep.h:1.9 src/sys/arch/sparc/include/pci_machdep.h:1.10
--- src/sys/arch/sparc/include/pci_machdep.h:1.9	Sat Oct 27 17:18:11 2012
+++ src/sys/arch/sparc/include/pci_machdep.h	Tue Apr 16 06:57:06 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: pci_machdep.h,v 1.9 2012/10/27 17:18:11 chs Exp $ */
+/*	$NetBSD: pci_machdep.h,v 1.10 2013/04/16 06:57:06 jdc Exp $ */
 
 /*
  * Copyright (c) 1999 Matthew R. Green
@@ -55,6 +55,10 @@ struct sparc_pci_chipset {
 	void		*cookie;	/* msiiep_softc, but sssh! */
 };
 
+#define IS_PCI_BRIDGE(class) \
+	(((class >> 16) & 0xff) == PCI_CLASS_BRIDGE && \
+	    ((class >> 8) & 0xff) == PCI_SUBCLASS_BRIDGE_PCI)
+
 /* 
  * The MI PCI code expects pcitag_t to be a scalar type.  But besides
  * the bus/device/function we need to store the OFW node as well.  We
@@ -63,7 +67,7 @@ struct sparc_pci_chipset {
  * form directly suitable for pci mode1 configuration address port.
  */
 #define	PCITAG_CREATE(n,b,d,f)	\
-	(((uint64_t)(n)<<32)|0x80000000U|((b)<<16)|((d)<<11)|((f)<<8))
+	(((uint64_t)(n)<<32)|0x80000000U|((b)<<16)|((d)<<11)|((f)<<8)|(b?1:0))
 
 #define	PCITAG_NODE(t)		((uint32_t)(((t)>>32)&0xffffffff))
 #define	PCITAG_OFFSET(t)	((uint32_t)((t)&0xffffffff))

Index: src/sys/arch/sparc/sparc/autoconf.c
diff -u src/sys/arch/sparc/sparc/autoconf.c:1.250 src/sys/arch/sparc/sparc/autoconf.c:1.251
--- src/sys/arch/sparc/sparc/autoconf.c:1.250	Thu Feb 14 12:44:16 2013
+++ src/sys/arch/sparc/sparc/autoconf.c	Tue Apr 16 06:57:06 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: autoconf.c,v 1.250 2013/02/14 12:44:16 martin Exp $ */
+/*	$NetBSD: autoconf.c,v 1.251 2013/04/16 06:57:06 jdc Exp $ */
 
 /*
  * Copyright (c) 1996
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.250 2013/02/14 12:44:16 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.251 2013/04/16 06:57:06 jdc Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -101,6 +101,9 @@ __KERNEL_RCSID(0, "$NetBSD: autoconf.c,v
 #include <dev/pci/pcidevs.h>
 #include <dev/pci/pcivar.h>
 #include <sparc/sparc/msiiepreg.h>
+#ifdef MSIIEP
+#include <sparc/sparc/pci_fixup.h>
+#endif
 
 #ifdef DDB
 #include <machine/db_machdep.h>
@@ -360,7 +363,6 @@ bootstrap(void)
 
 	if ((bi_howto = lookup_bootinfo(BTINFO_BOOTHOWTO)) != NULL) {
 		boothowto = bi_howto->boothowto;
-printf("initialized boothowt from bootloader: %x\n", boothowto);
 	}
 }
 
@@ -1757,12 +1759,23 @@ nail_bootdev(device_t dev, struct bootpa
 	bootpath_store(1, NULL);
 }
 
+/*
+ * We use device_register() to:
+ *   set device properties on PCI devices
+ *   find the bootpath
+ */
 void
 device_register(device_t dev, void *aux)
 {
 	struct bootpath *bp = bootpath_store(0, NULL);
 	const char *bpname;
 
+#ifdef MSIIEP
+	/* Check for PCI devices */
+	if (bus_class(device_parent(dev)) == BUSCLASS_PCI)
+		set_pci_props(dev);
+#endif
+		
 	/*
 	 * If device name does not match current bootpath component
 	 * then there's nothing interesting to consider.

Index: src/sys/arch/sparc/sparc/msiiep.c
diff -u src/sys/arch/sparc/sparc/msiiep.c:1.43 src/sys/arch/sparc/sparc/msiiep.c:1.44
--- src/sys/arch/sparc/sparc/msiiep.c:1.43	Sun Jul 17 23:34:17 2011
+++ src/sys/arch/sparc/sparc/msiiep.c	Tue Apr 16 06:57:06 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: msiiep.c,v 1.43 2011/07/17 23:34:17 mrg Exp $ */
+/*	$NetBSD: msiiep.c,v 1.44 2013/04/16 06:57:06 jdc Exp $ */
 
 /*
  * Copyright (c) 2001 Valeriy E. Ushakov
@@ -27,7 +27,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msiiep.c,v 1.43 2011/07/17 23:34:17 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msiiep.c,v 1.44 2013/04/16 06:57:06 jdc Exp $");
 
 #include <sys/param.h>
 #include <sys/malloc.h>
@@ -48,7 +48,7 @@ __KERNEL_RCSID(0, "$NetBSD: msiiep.c,v 1
 
 #include <sparc/sparc/msiiepreg.h>
 #include <sparc/sparc/msiiepvar.h>
-
+#include <sparc/sparc/pci_fixup.h>
 
 /*
  * Autoconfiguration.
@@ -98,23 +98,13 @@ CFATTACH_DECL_NEW(mspcic, sizeof(struct 
 static struct sparc_pci_chipset mspcic_pc_tag = { NULL };
 
 
-/*
- * Bus space tags for memory and i/o.
- */
-
-struct mspcic_pci_map {
-	uint32_t sysbase;
-	uint32_t pcibase;
-	uint32_t size;
-};
-
 /* fixed i/o and one set of i/o cycle translation registers */
-static struct mspcic_pci_map mspcic_pci_iomap[2] = {
+struct mspcic_pci_map mspcic_pci_iomap[IOMAP_SIZE] = {
 	{ 0x30000000, 0x0, 0x00010000 }		/* fixed i/o (decoded bits) */
 };
 
 /* fixed mem and two sets of mem cycle translation registers */
-static struct mspcic_pci_map mspcic_pci_memmap[3] = {
+struct mspcic_pci_map mspcic_pci_memmap[MEMMAP_SIZE] = {
 	{ 0x30100000, 0x00100000, 0x00f00000 }	/* fixed mem (pass through) */
 };
 
@@ -282,7 +272,7 @@ mspcic_attach(device_t parent, device_t 
 	struct msiiep_attach_args *msa = aux;
 	struct mainbus_attach_args *ma = msa->msa_ma;
 	int node = ma->ma_node;
-	char devinfo[256];
+	char devinfo[256], buf[32], *model;
 
 	struct pcibus_attach_args pba;
 
@@ -300,6 +290,22 @@ mspcic_attach(device_t parent, device_t 
 
 	mspcic_init_maps();
 
+	/*
+	 * On Espresso, we need to adjust the interrupt mapping on
+	 * lines 4-7, as onboard devices and cards in the PCI slots use
+	 * those lines.  Note, that enabling line 5 (onboard ide) causes
+	 * a continuous interrupt stream, so leave that unmapped (0).
+	 * Any other device using line 5 can't be used.
+	 * Interrupt line wiring for slots is set in pci_machdep.c.
+	 * Set the PCI Trdy and Retry Counters to non-zero values, otherwise
+	 * we'll lock up when using devices behind a PCI-PCI bridge.
+	 */
+	model = prom_getpropstringA(prom_findroot(), "model", buf, sizeof(buf));
+	if (model != NULL && !strcmp(model, "SUNW,375-0059")) {
+		mspcic_write_2(pcic_intr_asgn_sel_hi, (uint16_t) 0x7502);
+		mspcic_write_4(pcic_cntrs, (uint32_t) 0x00808000);
+	}
+
 	/* init cookies/parents in our statically allocated tags */
 	mspcic_io_tag = *sc->sc_bustag;
 	mspcic_io_tag.cookie = &mspcic_io_cookie;
@@ -353,6 +359,8 @@ mspcic_attach(device_t parent, device_t 
 	pba.pba_pc = &mspcic_pc_tag;
 	pba.pba_flags = PCI_FLAGS_IO_OKAY | PCI_FLAGS_MEM_OKAY;
 
+	mspcic_pci_scan(sc->sc_node);
+
 	config_found_ia(self, "pcibus", &pba, mspcic_print);
 }
 

Index: src/sys/arch/sparc/sparc/msiiepvar.h
diff -u src/sys/arch/sparc/sparc/msiiepvar.h:1.8 src/sys/arch/sparc/sparc/msiiepvar.h:1.9
--- src/sys/arch/sparc/sparc/msiiepvar.h:1.8	Sun Jul 17 23:32:37 2011
+++ src/sys/arch/sparc/sparc/msiiepvar.h	Tue Apr 16 06:57:06 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: msiiepvar.h,v 1.8 2011/07/17 23:32:37 mrg Exp $ */
+/*	$NetBSD: msiiepvar.h,v 1.9 2013/04/16 06:57:06 jdc Exp $ */
 
 /*
  * Copyright (c) 2001 Valeriy E. Ushakov
@@ -51,4 +51,17 @@ struct mspcic_softc {
 
 extern int	mspcic_assigned_interrupt(int);
 
+/*
+ * Bus space tags for memory and i/o.
+ */
+
+struct mspcic_pci_map {
+	uint32_t sysbase;
+	uint32_t pcibase;
+	uint32_t size;
+};
+
+#define IOMAP_SIZE 2
+#define MEMMAP_SIZE 3
+
 #endif /* _SPARC_MSIIEP_VAR_H_ */

Index: src/sys/arch/sparc/sparc/pci_machdep.c
diff -u src/sys/arch/sparc/sparc/pci_machdep.c:1.17 src/sys/arch/sparc/sparc/pci_machdep.c:1.18
--- src/sys/arch/sparc/sparc/pci_machdep.c:1.17	Sat Oct 27 17:18:12 2012
+++ src/sys/arch/sparc/sparc/pci_machdep.c	Tue Apr 16 06:57:06 2013
@@ -1,4 +1,4 @@
-/*	$NetBSD: pci_machdep.c,v 1.17 2012/10/27 17:18:12 chs Exp $ */
+/*	$NetBSD: pci_machdep.c,v 1.18 2013/04/16 06:57:06 jdc Exp $ */
 
 /*
  * Copyright (c) 1999, 2000 Matthew R. Green
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.17 2012/10/27 17:18:12 chs Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.18 2013/04/16 06:57:06 jdc Exp $");
 
 #if defined(DEBUG) && !defined(SPARC_PCI_DEBUG)
 #define SPARC_PCI_DEBUG
@@ -100,29 +100,43 @@ int sparc_pci_debug = 0;
  * Probably we can do some forth hacking in boot loader's prompatch
  * (that's what it was introduced for), but for now it's way more
  * simple to just hardcode it here.
+ * XXX: Unknown mappings for PCI slots set to line 8.
  */
 
 struct mspcic_pci_intr_wiring {
 	u_int		mpiw_bus;
 	u_int		mpiw_device;
 	u_int		mpiw_function;
-	pci_intr_line_t	mpiw_line;
+	pci_intr_line_t	mpiw_line[4];	/* Int A (0) - Int D (3) */
 };
 
 static struct mspcic_pci_intr_wiring krups_pci_intr_wiring[] = {
-	{ 0, 0, 1,    1 },	/* ethernet */
-	{ 0, 1, 0,    2 },	/* vga */
+	{ 0, 0, 1,    { 1, 0, 0, 0 } },	/* ethernet */
+	{ 0, 1, 0,    { 2, 0, 0, 0 } },	/* vga */
 };
 
 static struct mspcic_pci_intr_wiring espresso_pci_intr_wiring[] = {
-	{ 0,  0, 1,    1 },	/* ethernet */
-	{ 0,  1, 0,    2 },	/* vga */
-	{ 0,  2, 0,    6 },	/* pci slot1 */
-	{ 0,  3, 0,    7 },	/* pci slot2 */
-	{ 0,  7, 0,    4 },	/* isa */
-	{ 0, 16, 0,    5 },	/* eide */
-/*	{ 0, 17, 0,    ? },	   power management */
-	{ 0, 20, 0,    4 },	/* usb */
+	{ 0,  0, 1,    { 1, 0, 0, 0 } },	/* ethernet */
+	{ 0,  1, 0,    { 2, 0, 0, 0 } },	/* vga */
+	{ 0,  2, 0,    { 6, 7, 8, 8 } },	/* pci slot1 */
+	{ 0,  2, 1,    { 6, 7, 8, 8 } },	/* pci slot1 */
+	{ 0,  2, 2,    { 6, 7, 8, 8 } },	/* pci slot1 */
+	{ 0,  2, 3,    { 6, 7, 8, 8 } },	/* pci slot1 */
+	{ 0,  2, 4,    { 6, 7, 8, 8 } },	/* pci slot1 */
+	{ 0,  2, 5,    { 6, 7, 8, 8 } },	/* pci slot1 */
+	{ 0,  2, 6,    { 6, 7, 8, 8 } },	/* pci slot1 */
+	{ 0,  2, 7,    { 6, 7, 8, 8 } },	/* pci slot1 */
+	{ 0,  3, 0,    { 7, 8, 8, 8 } },	/* pci slot2 */
+	{ 0,  3, 1,    { 7, 8, 8, 8 } },	/* pci slot2 */
+	{ 0,  3, 2,    { 7, 8, 8, 8 } },	/* pci slot2 */
+	{ 0,  3, 3,    { 7, 8, 8, 8 } },	/* pci slot2 */
+	{ 0,  3, 4,    { 7, 8, 8, 8 } },	/* pci slot2 */
+	{ 0,  3, 5,    { 7, 8, 8, 8 } },	/* pci slot2 */
+	{ 0,  3, 6,    { 7, 8, 8, 8 } },	/* pci slot2 */
+	{ 0,  3, 7,    { 7, 8, 8, 8 } },	/* pci slot2 */
+	{ 0,  7, 0,    { 4, 0, 0, 0 } },	/* isa */
+	{ 0, 16, 0,    { 5, 0, 0, 0 } },	/* eide */
+	{ 0, 20, 0,    { 5, 0, 0, 0 } },	/* usb */
 };
 
 struct mspcic_known_model {
@@ -153,6 +167,10 @@ pci_attach_hook(device_t parent, device_
 	char buf[32];
 	char *model;
 
+	/* We only need to run once (root PCI bus is 0) */
+	if (pba->pba_bus != 0)
+		return;
+
 	model = prom_getpropstringA(prom_findroot(), "model",
 				    buf, sizeof(buf));
 	if (model == NULL)
@@ -193,7 +211,6 @@ pci_make_tag(pci_chipset_tag_t pc, int b
 
 	memset(name, 0, sizeof(name));
 #endif
-
 	tag = PCITAG_CREATE(-1, b, d, f);
 	if (b >= 256 || d >= 32 || f >= 8) {
 		printf("pci_make_tag: bad request %d/%d/%d\n", b, d, f);
@@ -211,6 +228,9 @@ pci_make_tag(pci_chipset_tag_t pc, int b
 	for (node = OF_child(sc->sc_node); node != 0; node = OF_peer(node)) {
 		struct ofw_pci_register reg;
 		uint32_t busrange[2];
+		int class;
+		pcireg_t busdata;
+		pcitag_t bustag;
 
 #ifdef SPARC_PCI_DEBUG
 		if (sparc_pci_debug & SPDB_PROBE) {
@@ -245,25 +265,49 @@ pci_make_tag(pci_chipset_tag_t pc, int b
 		 * that gets more complicated.
 		 */
 		len = OF_getproplen(node, "reg");
-		if (len < sizeof(reg))
-			continue;
-		if (OF_getprop(node, "reg", (void *)&reg, sizeof(reg)) != len)
-			panic("pci_probe_bus: OF_getprop len botch");
-
-		if (b != OFW_PCI_PHYS_HI_BUS(reg.phys_hi))
-			continue;
-		if (d != OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi))
-			continue;
-		if (f != OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi))
-			continue;
+		OF_getprop(node, "reg", (void *)&reg, sizeof(reg));
+
+		/*
+		 * Check for (OFW unconfigured) bridges that we fixed up.
+		 * We'll set this top-level bridge's node in the tag,
+		 * so that we can use it later for interrupt wiring.
+		 */
+		if (b > 0) {
+			len = OF_getproplen(node, "class-code");
+			if (!len)
+				continue;
+			OF_getprop(node, "class-code", &class, len);
+			if (IS_PCI_BRIDGE(class)) {
+				bustag = PCITAG_CREATE(node,
+				    OFW_PCI_PHYS_HI_BUS(reg.phys_hi),
+				    OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi),
+				    OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi));
+				busdata = pci_conf_read(NULL, bustag,
+				    PCI_BRIDGE_BUS_REG);
+				if (b != ((busdata >> 8) & 0xff))
+					continue;
+
+#ifdef SPARC_PCI_DEBUG
+				if (sparc_pci_debug & SPDB_PROBE) {
+					OF_getprop(node, "name", &name,
+					    sizeof(name));
+					printf("> matched device behind node "
+					    "%x %s (bus %d)\n", node, name, b);
+				}
+#endif
+			} else
+				continue;
+		} else {
+			if (b != OFW_PCI_PHYS_HI_BUS(reg.phys_hi))
+				continue;
+			if (d != OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi))
+				continue;
+			if (f != OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi))
+				continue;
+		}
 
 		/* Got a match */
 		tag = PCITAG_CREATE(node, b, d, f);
-
-		/* Enable all the different spaces for this device */
-		pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
-			PCI_COMMAND_MASTER_ENABLE
-			| PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_IO_ENABLE);
 		DPRINTF(SPDB_PROBE, ("> found node %x %s\n", node, name));
 		return tag;
 	}
@@ -368,22 +412,75 @@ pci_conf_write(pci_chipset_tag_t pc, pci
 int
 pci_intr_map(const struct pci_attach_args *pa, pci_intr_handle_t *ihp)
 {
-	int i;
+	int i, node;
+	pcitag_t tag;
+	pcireg_t val;
+	pci_intr_pin_t pin;
 
 	DPRINTF(SPDB_INTMAP,
 		("pci_intr_map(%d/%d/%d) -> ",
 		 pa->pa_bus, pa->pa_device, pa->pa_function));
 
+	tag = pci_make_tag(pa->pa_pc, pa->pa_bus, pa->pa_device,
+	    pa->pa_function);
+	node = PCITAG_NODE(tag);
+	val = pci_conf_read(NULL, tag, PCI_INTERRUPT_REG);
+	pin = PCI_INTERRUPT_PIN(val);
+
+	/*
+	 * Pin should be A(1) to D(4) - use values 0 to 3 respectively to
+	 * represent them.  Built-in devices might show pin 0, so assume
+	 * pin A for those - the static wiring map has the correct line.
+	 */
+	if (pin)
+		pin -= 1;
+
 	for (i = 0; i < wiring_map_size; ++i) {
 		struct mspcic_pci_intr_wiring *w = &wiring_map[i];
 
+		/* Device on PCI bus 0 */
 		if (pa->pa_bus == w->mpiw_bus
 		    && pa->pa_device == w->mpiw_device
 		    && pa->pa_function == w->mpiw_function)
 		{
-			DPRINTF(SPDB_INTMAP, ("line %d\n", w->mpiw_line));
-			*ihp = w->mpiw_line;
+			if (w->mpiw_line[pin] > 7) {
+				DPRINTF(SPDB_INTMAP, ("not mapped\n"));
+				return -1;
+			}
+			DPRINTF(SPDB_INTMAP, ("pin %c line %d\n", 'A' + pin,
+			    w->mpiw_line[pin]));
+			*ihp = w->mpiw_line[pin];
 			return 0;
+		/* Device on other PCI bus - find top-level bridge device */
+		} else if (pa->pa_bus) {
+			struct ofw_pci_register reg;
+
+			OF_getprop(node, "reg", (void *)&reg, sizeof(reg));
+			if (OFW_PCI_PHYS_HI_BUS(reg.phys_hi) == w->mpiw_bus
+			    && OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi)
+			    == w->mpiw_device
+			    && OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi)
+			    == w->mpiw_function) {
+				int j;
+
+				/* PCI bridge interrupt swizzle */
+				for (j = 0; j < PCI_INTERRUPT_LINE(val); j++)
+					pin = (pin + (pa->pa_device % 4)) % 4;
+
+				if (w->mpiw_line[pin] > 7) {
+					DPRINTF(SPDB_INTMAP, ("pin %c "
+					    "not mapped\n", pin));
+					return -1;
+				}
+				DPRINTF(SPDB_INTMAP, ("pin %c line %d "
+				    "via bridge (%d/%d/%d) depth %d\n",
+				    'A' + pin, w->mpiw_line[pin],
+				    w->mpiw_bus, w->mpiw_device,
+				    w->mpiw_function,
+				    PCI_INTERRUPT_LINE(val)));
+				*ihp = w->mpiw_line[pin];
+				return 0;
+			}
 		}
 	}
 

Added files:

Index: src/sys/arch/sparc/sparc/pci_fixup.c
diff -u /dev/null src/sys/arch/sparc/sparc/pci_fixup.c:1.1
--- /dev/null	Tue Apr 16 06:57:06 2013
+++ src/sys/arch/sparc/sparc/pci_fixup.c	Tue Apr 16 06:57:06 2013
@@ -0,0 +1,527 @@
+/*	$NetBSD: pci_fixup.c,v 1.1 2013/04/16 06:57:06 jdc Exp $	*/
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Julian Coleman.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_ether.h>
+
+#define _SPARC_BUS_DMA_PRIVATE
+#include <sys/bus.h>
+#include <machine/autoconf.h>
+#include <machine/promlib.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcidevs.h>
+
+#include <dev/ofw/ofw_pci.h>
+
+#include <sparc/sparc/msiiepreg.h>
+#include <sparc/sparc/msiiepvar.h>
+#include <sparc/sparc/pci_fixup.h>
+
+static void mspcic_pci_fixup(int, pcitag_t, int *, uint32_t *, uint32_t *,
+	uint32_t, uint32_t memtop);
+
+extern struct mspcic_pci_map mspcic_pci_iomap[];
+extern struct mspcic_pci_map mspcic_pci_memmap[];
+
+/* ======================================================================
+ *
+ *			General PCI bus fixup
+ */
+
+#define MAX_DEVFUN	256	/* 32 device * 8 function */
+#define DF_NEXTDEV(i)	(i + 7 - (i % 8))
+#define MAP_TOP(map)	(map.pcibase + map.size)
+#define RND_IO_START(t, m)	(((t & m) == t) ? t : \
+    ((t + PCI_MAPREG_IO_SIZE(m)) & m))
+#define RND_MEM_START(t, m)	(((t & m) == t) ? t : \
+    ((t + PCI_MAPREG_MEM_SIZE(m)) & m))
+
+void
+mspcic_pci_scan(int root)
+{
+	int i, j, node, bus, dev, fun, maxbus, len, class;
+	struct ofw_pci_register reg;
+	pcitag_t tag;
+	pcireg_t val, saved;
+	uint32_t io[IOMAP_SIZE], mem[MEMMAP_SIZE];
+#ifdef SPARC_PCI_FIXUP_DEBUG
+	char name[80];
+
+	memset(name, 0, sizeof(name));
+#endif
+	maxbus = 1;
+	for (i = 0; i < IOMAP_SIZE; i++)
+		io[i] = mspcic_pci_iomap[i].pcibase;
+	for (i = 0; i < MEMMAP_SIZE; i++)
+		mem[i] = mspcic_pci_memmap[i].pcibase;
+	node = OF_child(root);
+
+#ifdef SPARC_PCI_FIXUP_DEBUG
+	printf("mspcic_pci_scan start:\n");
+	printf("  max bus %d\n", maxbus);
+	for (i = 0; i < IOMAP_SIZE; i++)
+		printf("  PCI I/O %d %08x to %08x\n",
+		    i, io[i], MAP_TOP(mspcic_pci_iomap[i]) - 1);
+	for (i = 0; i < MEMMAP_SIZE; i++)
+		printf("  PCI Mem %d %08x to %08x\n",
+		    i, mem[i], MAP_TOP(mspcic_pci_memmap[i]) - 1);
+#endif
+
+	/*
+	 * Scan our known PCI devices and collect:
+	 *   maximum bus number
+	 *   maxium used address in each I/O and memory range
+	 */
+	while(node) {
+		uint32_t busrange[2];
+
+#ifdef SPARC_PCI_FIXUP_DEBUG
+		OF_getprop(node, "name", &name, sizeof(name));
+		printf("> checking node %x: %s\n", node, name);
+#endif
+		len = OF_getproplen(node, "reg");
+		if (len < sizeof(reg))
+			continue;
+		if (OF_getprop(node, "reg", (void *)&reg, sizeof(reg)) != len)
+			panic("pci_probe_bus: OF_getprop len botch");
+		bus = OFW_PCI_PHYS_HI_BUS(reg.phys_hi);
+		dev = OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi);
+		fun = OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi);
+		tag = PCITAG_CREATE(node, bus, dev, fun);
+#ifdef SPARC_PCI_FIXUP_DEBUG
+		printf("> bus %2d, dev %2d, fun %2d\n",
+		    PCITAG_BUS(tag), PCITAG_DEV(tag), PCITAG_FUN(tag));
+#endif
+		/* Enable all the different spaces/errors for this device */
+		pci_conf_write(NULL, tag, PCI_COMMAND_STATUS_REG,
+		    PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
+		    PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_PARITY_ENABLE);
+
+		/* Configured PCI-PCI bridges - increment max bus number */
+		if ((OF_getprop(node, "bus-range", (void *)&busrange,
+		   sizeof(busrange)) == sizeof(busrange)))
+		{
+			if (busrange[1] > maxbus)
+				maxbus = busrange[1] + 1;
+			if (maxbus > 255)
+				panic("mspcic_pci_scan: maxbus > 255");
+
+			/* go down one level */
+			node = OF_child(node);
+			continue;
+		}
+
+		/* Next node, or parent's next node (if we descended) */
+		if (OF_peer(node))
+			node = OF_peer(node);
+		else if (OF_parent(node) != root) {
+			node = OF_parent(node);
+			node = OF_peer(node);
+		} else
+			node = 0;
+
+		/* Check the Mem and I/O allocations for this node */
+		val = pci_conf_read(NULL, tag, PCI_BHLC_REG);
+		if (PCI_HDRTYPE_TYPE(val))	/* Type 0x00 has BAR's */
+			continue;		/* Skip to next node */
+
+		/*
+		 * Read BAR's:
+		 *   save the current (address) value
+		 *   write 0xffffffff and read back the size mask
+		 *   restore the saved value
+		 */
+		for (i = 0; i < 6; i++) {
+			saved = pci_conf_read(NULL, tag, PCI_BAR(i));
+			pci_conf_write(NULL, tag, PCI_BAR(i), (pcireg_t) ~0x0);
+			val = pci_conf_read(NULL, tag, PCI_BAR(i));
+			pci_conf_write(NULL, tag, PCI_BAR(i), saved);
+			if (!val)
+				continue;	/* Skip to next BAR */
+			saved &= 0xfffffffe;	/* Remove I/O bit */
+#ifdef SPARC_PCI_FIXUP_DEBUG
+			printf("> BAR %02x: value %08x mask %08x\n",
+			    PCI_BAR(i), saved, val);
+#endif
+
+			/* Compare the address + size against our mappings */
+			if (PCI_MAPREG_TYPE(val) == PCI_MAPREG_TYPE_IO) {
+				saved = saved + PCI_MAPREG_IO_SIZE(val);
+				for (j = 0; j < IOMAP_SIZE; j++)
+					if (saved > io[j] && saved <=
+					    MAP_TOP(mspcic_pci_iomap[j]))
+					io[j] = saved;
+			} else {	/* PCI_MAPREG_TYPE_MEM */
+				saved = saved + PCI_MAPREG_MEM_SIZE(val);
+				for (j = 0; j < MEMMAP_SIZE; j++)
+				if (saved > mem[j] && saved <=
+				    MAP_TOP(mspcic_pci_memmap[j]))
+					mem[j] = saved;
+			}
+		}
+
+		/* Read ROM */
+		saved = pci_conf_read(NULL, tag, PCI_MAPREG_ROM);
+		pci_conf_write(NULL, tag, PCI_MAPREG_ROM, (pcireg_t) ~0x0);
+		val = pci_conf_read(NULL, tag, PCI_MAPREG_ROM);
+		pci_conf_write(NULL, tag, PCI_MAPREG_ROM, saved);
+		if (val) {
+#ifdef SPARC_PCI_FIXUP_DEBUG
+			printf("> ROM: start %08x mask %08x\n", saved, val);
+#endif
+			saved = saved + PCI_MAPREG_MEM_SIZE(val);
+			for (j = 0; j < MEMMAP_SIZE; j++)
+			if (saved > mem[j] && saved <=
+			    MAP_TOP(mspcic_pci_memmap[j]))
+				mem[j] = saved;
+		}
+	}
+
+#ifdef SPARC_PCI_FIXUP_DEBUG
+	printf("mspcic_pci_scan finish:\n");
+	printf("  max bus %d\n", maxbus);
+	for (i = 0; i < IOMAP_SIZE; i++)
+		if (io[i] < MAP_TOP(mspcic_pci_iomap[i]) - 1)
+			printf("  PCI I/O free %d %08x to %08x\n",
+			    i, io[i], MAP_TOP(mspcic_pci_iomap[i]) - 1);
+		else
+			printf("  PCI I/O %d full %08x to %08x\n",
+			    i, mspcic_pci_iomap[i].sysbase,
+			    MAP_TOP(mspcic_pci_iomap[i]) - 1);
+	for (i = 0; i < MEMMAP_SIZE; i++)
+		if (mem[i] < MAP_TOP(mspcic_pci_memmap[i]) - 1)
+			printf("  PCI Mem free %d %08x to %08x\n",
+			    i, mem[i], MAP_TOP(mspcic_pci_memmap[i]) - 1);
+		else
+			printf("  PCI %d Mem full %08x to %08x\n",
+			    i, mspcic_pci_memmap[i].sysbase,
+			    MAP_TOP(mspcic_pci_memmap[i]) - 1);
+#endif
+
+	node = OF_child(root);
+	/*
+	 * Scan our known PCI devices and fix up any buses that
+	 * the firmware didn't configure.
+	 */
+	while(node) {
+		int next, k;
+
+		/* Next node, or parent's next node (if we descended) */
+		if (OF_peer(node))
+			next = OF_peer(node);
+		else if (OF_parent(node) != root) {
+			next = OF_parent(node);
+			next = OF_peer(node);
+		} else
+			next = 0;
+
+		len = OF_getproplen(node, "class-code");
+		if (!len) {
+			node = next;
+			continue;
+		}
+		OF_getprop(node, "class-code", &class, len);
+		if (!IS_PCI_BRIDGE(class)) {
+			node = next;
+			continue;
+		}
+		len = OF_getproplen(node, "reg");
+		if (len < sizeof(reg))
+			continue;
+		if (OF_getprop(node, "reg", (void *)&reg, sizeof(reg)) != len)
+			panic("pci_probe_bus: OF_getprop len botch");
+		bus = OFW_PCI_PHYS_HI_BUS(reg.phys_hi);
+		dev = OFW_PCI_PHYS_HI_DEVICE(reg.phys_hi);
+		fun = OFW_PCI_PHYS_HI_FUNCTION(reg.phys_hi);
+		tag = PCITAG_CREATE(node, bus, dev, fun);
+
+		/*
+		 * Find ranges with largest free space
+		 * Round up start to 12 bit (io) and 20 bit (mem) multiples
+		 * because bridge base/limit registers have that granularity.
+		 */
+		i = 0;
+		j = 0;
+		for (k = 1; k < IOMAP_SIZE; k++) {
+			io[k] = RND_IO_START(io[k], 0xf000);
+			if (MAP_TOP(mspcic_pci_iomap[k]) - io[k] >
+			    MAP_TOP(mspcic_pci_iomap[i]) - io[i])
+				i = k;
+		}
+		for (k = 1; k < MEMMAP_SIZE; k++) {
+			mem[k] = RND_MEM_START(mem[k], 0xfff00000);
+			if (MAP_TOP(mspcic_pci_memmap[k]) - mem[k] >
+			    MAP_TOP(mspcic_pci_memmap[j]) - mem[j])
+				j = k;
+		}
+		mspcic_pci_fixup(1, tag, &maxbus, &io[i], &mem[j],
+		    MAP_TOP(mspcic_pci_iomap[i]),
+		    MAP_TOP(mspcic_pci_memmap[j]));
+		node = next;
+	}
+}
+
+static void
+mspcic_pci_fixup(int depth, pcitag_t starttag, int *maxbus, uint32_t *io,
+	uint32_t *mem, uint32_t iotop, uint32_t memtop)
+{
+	int i, j, startbus;
+	uint32_t startio, startmem;
+	pcitag_t tag;
+	pcireg_t val, size, start;
+
+	startbus = *maxbus;
+	startio = *io;
+	startmem = *mem;
+
+#ifdef SPARC_PCI_FIXUP_DEBUG
+	printf("mspcic_pci_fixup start:\n");
+	printf("  bridge at (%d %d %d), depth %d\n", PCITAG_BUS(starttag),
+	    PCITAG_DEV(starttag), PCITAG_FUN(starttag), depth);
+	printf("  start bus %d\n", startbus);
+	printf("  io free %08x to %08x\n", startio, iotop - 1);
+	printf("  mem free %08x to %08x\n", startmem, memtop - 1);
+#endif
+
+	pci_conf_write(NULL, starttag, PCI_COMMAND_STATUS_REG,
+	    PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE
+	    | PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_PARITY_ENABLE);
+	pci_conf_write(NULL, starttag, PCI_BRIDGE_CONTROL_REG, 0);
+
+	/* Secondary bus = startbus, subordinate bus = 0xff */
+	pci_conf_write(NULL, starttag, PCI_BRIDGE_BUS_REG,
+	    ((startbus & 0xff) << PCI_BRIDGE_BUS_SECONDARY_SHIFT) |
+	    (0xff << PCI_BRIDGE_BUS_SUBORDINATE_SHIFT));
+
+	/*
+	 * Fix up bus numbering, bus addresses, device addresses,
+	 * interrupts and fast back-to-back capabilities.
+	 */
+	for (i = 0; i < MAX_DEVFUN; i++) {
+		tag = PCITAG_CREATE(0, startbus, i / 8, i % 8);
+		/* Enable all the different spaces for this device */
+		pci_conf_write(NULL, tag, PCI_COMMAND_STATUS_REG,
+		    PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE
+		    | PCI_COMMAND_IO_ENABLE | PCI_COMMAND_PARITY_ENABLE);
+		val = pci_conf_read(NULL, tag, PCI_ID_REG);
+		if (PCI_VENDOR(val) == PCI_VENDOR_INVALID) {
+			i = DF_NEXTDEV(i);
+			continue;
+		}
+#ifdef SPARC_PCI_FIXUP_DEBUG
+		printf("> Found %04x:%04x at (%d %d %d)\n", PCI_VENDOR(val),
+		    PCI_PRODUCT(val), startbus, i / 8, i % 8);
+#endif
+
+		/* Check interrupt pin(s), and write depth to line */
+		val = pci_conf_read(NULL, tag, PCI_INTERRUPT_REG);
+		if (PCI_INTERRUPT_PIN(val)) {
+			val = (val & ~(PCI_INTERRUPT_LINE_MASK <<
+			    PCI_INTERRUPT_LINE_SHIFT)) | depth;
+			pci_conf_write(NULL, tag, PCI_INTERRUPT_REG, val);
+		}
+
+		/* Check device type */
+		val = pci_conf_read(NULL, tag, PCI_CLASS_REG);
+		if (IS_PCI_BRIDGE(val)) {
+			(*maxbus)++;
+			if (*maxbus > 255)
+				panic("mspcic_pci_fixup: maxbus > 255");
+			mspcic_pci_fixup(depth + 1, tag, maxbus, io, mem,
+			    iotop, memtop);
+		}
+
+		pci_conf_write(NULL, tag, PCI_MAPREG_ROM, (pcireg_t) ~0x0);
+		val = pci_conf_read(NULL, tag, PCI_MAPREG_ROM);
+		if (val) {
+			size = PCI_MAPREG_MEM_SIZE(val);
+			start = RND_MEM_START(*mem, val);
+			if (start + size <= memtop) {
+				*mem = start + size;
+				pci_conf_write(NULL, tag, PCI_MAPREG_ROM,
+				    start);
+#ifdef SPARC_PCI_FIXUP_DEBUG
+				printf("> ROM: %08x to %08x mask %08x\n",
+				    start, (*mem) - 1, val);
+#endif
+			}
+		}
+
+		val = pci_conf_read(NULL, tag, PCI_BHLC_REG);
+		/* Check for multifunction devices and for BAR's  */
+		if (!PCI_HDRTYPE_MULTIFN(val))
+			i = DF_NEXTDEV(i);
+		if (PCI_HDRTYPE_TYPE(val))
+			continue;
+
+		/*
+		 * Read BAR's:
+		 *   write 0xffffffff and read back the size mask
+		 *   set the base address
+		 */
+		for (j = 0; j < 6; j++) {
+			pci_conf_write(NULL, tag, PCI_BAR(j),
+			    (pcireg_t) ~0x0);
+			val = pci_conf_read(NULL, tag, PCI_BAR(j));
+			if (!val)
+				continue;
+			if (PCI_MAPREG_TYPE(val) ==
+			    PCI_MAPREG_TYPE_IO) {
+				size = PCI_MAPREG_IO_SIZE(val);
+				start = RND_IO_START(*io, val);
+				if (start + size <= iotop) {
+					*io = start + size;
+					pci_conf_write(NULL, tag, PCI_BAR(j),
+					    start);
+#ifdef SPARC_PCI_FIXUP_DEBUG
+					printf("> BAR %02x set: %08x to %08x "
+					    "mask %08x (io)\n", PCI_BAR(j),
+					    start, (*io) - 1, val);
+#endif
+				} else {
+					pci_conf_write(NULL, tag,
+					    PCI_COMMAND_STATUS_REG, 0);
+					printf("Fixup failed for (%d %d %d)\n",
+					    startbus, i / 8, i % 8);
+				}
+			} else {	/* PCI_MAPREG_TYPE_MEM */
+				size = PCI_MAPREG_MEM_SIZE(val);
+				start = RND_MEM_START(*mem, val);
+				if (start + size <= memtop) {
+					*mem = start + size;
+					pci_conf_write(NULL, tag, PCI_BAR(j),
+					    start);
+#ifdef SPARC_PCI_FIXUP_DEBUG
+					printf("> BAR %02x set: %08x to %08x "
+					    "mask %08x (mem)\n", PCI_BAR(j),
+					    start, (*mem) - 1, val);
+#endif
+				} else {
+					pci_conf_write(NULL, tag,
+					    PCI_COMMAND_STATUS_REG, 0);
+					printf("Fixup failed for (%d %d %d)\n",
+					    startbus, i / 8, i % 8);
+				}
+			}
+		}
+	}
+
+	/* Secondary bus = startbus, subordinate bus = maxbus */
+	pci_conf_write(NULL, starttag, PCI_BRIDGE_BUS_REG,
+	    ((startbus & 0xff) << PCI_BRIDGE_BUS_SECONDARY_SHIFT) |
+	    ((*maxbus & 0xff) << PCI_BRIDGE_BUS_SUBORDINATE_SHIFT));
+
+	/* 16-bit I/O range */
+	val = ((startio & 0xf000) >> 8) | ((*(io) - 1) & 0xf000);
+	pci_conf_write(NULL, starttag, PCI_BRIDGE_STATIO_REG, val);
+#ifdef SPARC_PCI_FIXUP_DEBUG
+	printf("16-bit I/O range = %04x\n",
+	    pci_conf_read(NULL, starttag, PCI_BRIDGE_STATIO_REG) & 0xffff);
+#endif
+
+	/* Mem range and (disabled) prefetch mem range */
+	val = ((startmem & 0xfff00000) >> 16) |
+	    ((*(mem) - 1) & 0xfff00000);
+	pci_conf_write(NULL, starttag, PCI_BRIDGE_MEMORY_REG, val);
+	pci_conf_write(NULL, starttag, PCI_BRIDGE_PREFETCHMEM_REG, 0x0000ffff);
+#ifdef SPARC_PCI_FIXUP_DEBUG
+	printf("Mem range = %08x\n",
+	    pci_conf_read(NULL, starttag, PCI_BRIDGE_MEMORY_REG));
+	printf("Pref mem range = %08x\n",
+	    pci_conf_read(NULL, starttag, PCI_BRIDGE_PREFETCHMEM_REG));
+#endif
+
+	/* 32-bit I/O range (if supported) */
+	val = pci_conf_read(NULL, starttag, PCI_BRIDGE_STATIO_REG);
+	if ((val & 0x0101) == 0x0101) {
+		val = ((startio & 0xffff0000) >> 16) |
+		    ((*(io) - 1) & 0xffff0000);
+		pci_conf_write(NULL, starttag, PCI_BRIDGE_IOHIGH_REG, val);
+	}
+#ifdef SPARC_PCI_FIXUP_DEBUG
+	printf("32-bit I/O range = %08x\n",
+	    pci_conf_read(NULL, starttag, PCI_BRIDGE_IOHIGH_REG));
+#endif
+
+	/* 64-bit prefetchable range (if supported) - set it to 0 */
+	val = pci_conf_read(NULL, starttag, PCI_BRIDGE_PREFETCHMEM_REG);
+	if (val & 0x01) {
+		pci_conf_write(NULL, starttag, PCI_BRIDGE_PREFETCHBASE32_REG,
+		    (pcireg_t) ~0);
+		pci_conf_write(NULL, starttag, PCI_BRIDGE_PREFETCHLIMIT32_REG,
+		    (pcireg_t) 0);
+	}
+
+#ifdef SPARC_PCI_FIXUP_DEBUG
+	printf("mspcic_pci_fixup finish:\n");
+	printf("  bridge at (%d %d %d), depth %d\n", PCITAG_BUS(starttag),
+	    PCITAG_DEV(starttag), PCITAG_FUN(starttag), depth);
+	printf("  bus range %d to %d\n", startbus, *maxbus);
+	printf("  io used %08x to %08x\n", startio, *(io) - 1);
+	printf("  mem used %08x to %08x\n", startmem, *(mem) - 1);
+#endif
+}
+
+/* ======================================================================
+ *
+ *			PCI device fixup for autoconf
+ */
+
+void
+set_pci_props(device_t dev)
+{
+	struct idprom *idp;
+	uint8_t eaddr[ETHER_ADDR_LEN];
+	prop_dictionary_t dict;
+	prop_data_t blob;
+
+	/*
+	 * We only handle network devices.
+	 * XXX: We have to set the ethernet address for HME cards here.  If
+	 * we leave this to the driver attachment, we will crash when trying
+	 * to map the 16MB Ebus device in if_hme_pci.c.
+	 */
+	if (!(device_is_a(dev, "le") || device_is_a(dev, "hme") ||
+	   device_is_a(dev, "be") || device_is_a(dev, "ie")))
+		return;
+
+	idp = prom_getidprom();
+	memcpy(eaddr, idp->idp_etheraddr, 6);
+	dict = device_properties(dev);
+	blob = prop_data_create_data(eaddr, ETHER_ADDR_LEN);
+	prop_dictionary_set(dict, "mac-address", blob);
+	prop_object_release(blob);
+}
Index: src/sys/arch/sparc/sparc/pci_fixup.h
diff -u /dev/null src/sys/arch/sparc/sparc/pci_fixup.h:1.1
--- /dev/null	Tue Apr 16 06:57:06 2013
+++ src/sys/arch/sparc/sparc/pci_fixup.h	Tue Apr 16 06:57:06 2013
@@ -0,0 +1,33 @@
+/*	$NetBSD: pci_fixup.h,v 1.1 2013/04/16 06:57:06 jdc Exp $	*/
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Julian Coleman.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+void mspcic_pci_scan(int);
+void set_pci_props(device_t);

Reply via email to