Subject: re: E250 support?
To: Mark Blackman <mark.blackman@netscalibur.co.uk>
From: matthew green <mrg@eterna.com.au>
List: port-sparc64
Date: 02/12/2001 13:57:24
try ftp.netbsd.org:/pub/NetBSD/arch/sparc64/kernels/NetBSD-1.5R-2


it was built with this patch:


Index: arch/sparc64/dev/simba.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sparc64/dev/simba.c,v
retrieving revision 1.2
diff -p -p -u -r1.2 simba.c
--- arch/sparc64/dev/simba.c	2000/05/24 20:27:52	1.2
+++ arch/sparc64/dev/simba.c	2001/02/11 18:09:28
@@ -135,6 +135,9 @@ simba_attach(parent, self, aux)
 	pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata);
 	pba.pba_intrswiz = pa->pa_intrswiz;
 	pba.pba_intrtag = pa->pa_intrtag;
+#ifdef __PCI_OFW_BINDING
+        pba.pba_node = pa->pa_node;
+#endif
 
 	config_found(self, &pba, simba_print);
 }
Index: arch/sparc64/dev/psycho.c
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sparc64/dev/psycho.c,v
retrieving revision 1.28
diff -p -p -u -r1.28 psycho.c
--- arch/sparc64/dev/psycho.c	2000/12/04 20:29:34	1.28
+++ arch/sparc64/dev/psycho.c	2001/02/11 18:09:29
@@ -209,6 +209,9 @@ psycho_attach(parent, self, aux)
 	pba.pba_dmat = sc->sc_psycho_this->pp_dmat;
 	pba.pba_iot = sc->sc_psycho_this->pp_iot;
 	pba.pba_memt = sc->sc_psycho_this->pp_memt;
+#ifdef __PCI_OFW_BINDING
+	pba.pba_node = sc->sc_node;
+#endif
 
 	config_found(self, &pba, psycho_print);
 }
Index: arch/sparc64/include/pci_machdep.h
===================================================================
RCS file: /cvsroot/syssrc/sys/arch/sparc64/include/pci_machdep.h,v
retrieving revision 1.5
diff -p -p -u -r1.5 pci_machdep.h
--- arch/sparc64/include/pci_machdep.h	2000/12/28 22:59:10	1.5
+++ arch/sparc64/include/pci_machdep.h	2001/02/11 18:09:29
@@ -65,4 +65,7 @@ void		*pci_intr_establish(pci_chipset_ta
 					 int, int (*)(void *), void *);
 void		pci_intr_disestablish(pci_chipset_tag_t, void *);
 
+/* want pci_attach_args{}->pa_node */
+#define __PCI_OFW_BINDING
+
 #endif /* _MACHINE_PCI_MACHDEP_H_ */
Index: dev/pci/pci.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/pci.c,v
retrieving revision 1.49
diff -p -p -u -r1.49 pci.c
--- dev/pci/pci.c	2000/06/28 16:08:48	1.49
+++ dev/pci/pci.c	2001/02/11 18:09:29
@@ -45,6 +45,11 @@
 #include <dev/pci/pcivar.h>
 #include <dev/pci/pcidevs.h>
 
+#ifdef __PCI_OFW_BINDING
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+#endif
+
 #ifdef PCI_CONFIG_DUMP
 int pci_config_dump = 1;
 #else
@@ -72,11 +77,9 @@ struct cfattach pci_ca = {
 	sizeof(struct pci_softc), pcimatch, pciattach
 };
 
-#ifdef __PCI_OFW_BINDING
-void	pci_ofw_probe_bus __P((struct device *));
-#else
+void	pci_probe_function(struct device *, struct pci_attach_args *,
+			   pci_chipset_tag_t, int, int);
 void	pci_probe_bus __P((struct device *));
-#endif
 int	pciprint __P((void *, const char *));
 int	pcisubmatch __P((struct device *, struct cfdata *, void *));
 
@@ -133,16 +136,124 @@ pcimatch(parent, cf, aux)
 	return 1;
 }
 
-#ifdef __PCI_OFW_BINDING
+/*
+ * Probe a single function.  Call by both the generic and OFW bus probe
+ * routines.
+ */
 void
-pci_ofw_probe_bus(self)
+pci_probe_function(self, pa, pc, device, function)
 	struct device *self;
+	struct pci_attach_args *pa;
+	pci_chipset_tag_t pc;
+	int device, function;
 {
+	pcireg_t tag, intr, csr, id, class;
 	struct pci_softc *sc = (struct pci_softc *)self;
+	int bus = sc->sc_bus;
+	int pin;
+
+	tag = pci_make_tag(pc, bus, device, function);
+	id = pci_conf_read(pc, tag, PCI_ID_REG);
+	csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
+	class = pci_conf_read(pc, tag, PCI_CLASS_REG);
+	intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
+
+	/* Invalid vendor ID value? */
+	if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
+		return;
+	/* XXX Not invalid, but we've done this ~forever. */
+	if (PCI_VENDOR(id) == 0)
+		return;
+
+	pa->pa_iot = sc->sc_iot;
+	pa->pa_memt = sc->sc_memt;
+	pa->pa_dmat = sc->sc_dmat;
+	pa->pa_pc = pc;
+	pa->pa_device = device;
+	pa->pa_function = function;
+	pa->pa_tag = tag;
+	pa->pa_id = id;
+	pa->pa_class = class;
+
+	/* From here on is identical to non-OFW version */
+	/*
+	 * Set up memory, I/O enable, and PCI command flags
+	 * as appropriate.
+	 */
+	pa->pa_flags = sc->sc_flags;
+	if ((csr & PCI_COMMAND_IO_ENABLE) == 0)
+		pa->pa_flags &= ~PCI_FLAGS_IO_ENABLED;
+	if ((csr & PCI_COMMAND_MEM_ENABLE) == 0)
+		pa->pa_flags &= ~PCI_FLAGS_MEM_ENABLED;
+
+	if (bus == 0) {
+		pa->pa_intrswiz = 0;
+		pa->pa_intrtag = pa->pa_tag;
+	} else {
+		pa->pa_intrswiz = sc->sc_intrswiz + device;
+		pa->pa_intrtag = sc->sc_intrtag;
+	}
+	pin = PCI_INTERRUPT_PIN(intr);
+	if (pin == PCI_INTERRUPT_PIN_NONE) {
+		/* no interrupt */
+		pa->pa_intrpin = 0;
+	} else {
+		/*
+		 * swizzle it based on the number of
+		 * busses we're behind and our device
+		 * number.
+		 */
+		pa->pa_intrpin =			/* XXX */
+		    ((pin + pa->pa_intrswiz - 1) % 4) + 1;
+	}
+	pa->pa_intrline = PCI_INTERRUPT_LINE(intr);
+
+	config_found_sm(self, pa, pciprint, pcisubmatch);
+}
+
+#ifdef __PCI_OFW_BINDING
+static __inline pcireg_t pci_OF_getpropint(int node, char *prop);
+
+static __inline pcireg_t
+pci_OF_getpropint(node, prop)
 	int node;
+	char *prop;
+{
+	int it, len;
+
+	if ((len = OF_getproplen(node, prop)) != sizeof(it) ||
+	    OF_getprop(node, prop, &it, sizeof(it)) == 0)
+		return (pcireg_t)~0;
+
+	return (pcireg_t)it;
+
+}
 
+void
+pci_probe_bus(self)
+	struct device *self;
+{
+	struct pci_softc *sc = (struct pci_softc *)self;
+	struct ofw_pci_register reg0;
+	struct pci_attach_args pa;
+	int node, bus, device, function, len;
+	pci_chipset_tag_t pc;
+
+	bus = sc->sc_bus;
+	pc = sc->sc_pc;
 	for (node = OF_child(sc->sc_node); node; node = OF_peer(node)) {
+		len = OF_getproplen(node, "reg");
+		if (len <= 0)
+			continue;
+		if (OF_getprop(node, "reg", (void *)&reg0, sizeof(reg0)) != len)
+			panic("pci_probe_bus: OF_getprop len botch");
+
+		device = OFW_PCI_PHYS_HI_DEVICE(reg0.phys_hi);
+		function = OFW_PCI_PHYS_HI_FUNCTION(reg0.phys_hi);
+
+		pa.pa_node = node;
 
+		pci_probe_function(self, &pa, pc, device, function);
 	}
 }
 #else
@@ -164,9 +275,8 @@ pci_probe_bus(self)
 
 	for (device = 0; device < maxndevs; device++) {
 		pcitag_t tag;
-		pcireg_t id, class, intr, bhlcr, csr;
+		pcireg_t id, bhlcr;
 		struct pci_attach_args pa;
-		int pin;
 
 		tag = pci_make_tag(pc, bus, device, 0);
 		id = pci_conf_read(pc, tag, PCI_ID_REG);
@@ -188,64 +298,8 @@ pci_probe_bus(self)
 		else
 			nfunctions = 1;
 
-		for (function = 0; function < nfunctions; function++) {
-			tag = pci_make_tag(pc, bus, device, function);
-			id = pci_conf_read(pc, tag, PCI_ID_REG);
-			csr = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
-			class = pci_conf_read(pc, tag, PCI_CLASS_REG);
-			intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
-
-			/* Invalid vendor ID value? */
-			if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
-				continue;
-			/* XXX Not invalid, but we've done this ~forever. */
-			if (PCI_VENDOR(id) == 0)
-				continue;
-
-			pa.pa_iot = iot;
-			pa.pa_memt = memt;
-			pa.pa_dmat = sc->sc_dmat;
-			pa.pa_pc = pc;
-			pa.pa_device = device;
-			pa.pa_function = function;
-			pa.pa_tag = tag;
-			pa.pa_id = id;
-			pa.pa_class = class;
-
-			/*
-			 * Set up memory, I/O enable, and PCI command flags
-			 * as appropriate.
-			 */
-			pa.pa_flags = sc->sc_flags;
-			if ((csr & PCI_COMMAND_IO_ENABLE) == 0)
-				pa.pa_flags &= ~PCI_FLAGS_IO_ENABLED;
-			if ((csr & PCI_COMMAND_MEM_ENABLE) == 0)
-				pa.pa_flags &= ~PCI_FLAGS_MEM_ENABLED;
-
-			if (bus == 0) {
-				pa.pa_intrswiz = 0;
-				pa.pa_intrtag = tag;
-			} else {
-				pa.pa_intrswiz = sc->sc_intrswiz + device;
-				pa.pa_intrtag = sc->sc_intrtag;
-			}
-			pin = PCI_INTERRUPT_PIN(intr);
-			if (pin == PCI_INTERRUPT_PIN_NONE) {
-				/* no interrupt */
-				pa.pa_intrpin = 0;
-			} else {
-				/*
-				 * swizzle it based on the number of
-				 * busses we're behind and our device
-				 * number.
-				 */
-				pa.pa_intrpin =			/* XXX */
-				    ((pin + pa.pa_intrswiz - 1) % 4) + 1;
-			}
-			pa.pa_intrline = PCI_INTERRUPT_LINE(intr);
-
-			config_found_sm(self, &pa, pciprint, pcisubmatch);
-		}
+		for (function = 0; function < nfunctions; function++)
+			pci_probe_function(self, &pa, pc, device, function);
 	}
 }
 #endif
@@ -309,11 +363,8 @@ pciattach(parent, self, aux)
 	sc->sc_flags = pba->pba_flags;
 #ifdef __PCI_OFW_BINDING
 	sc->sc_node = pba->pba_node;
-
-	pci_ofw_probe_bus(self);
-#else
-	pci_probe_bus(self);
 #endif
+	pci_probe_bus(self);
 }
 
 int
Index: dev/pci/ppb.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pci/ppb.c,v
retrieving revision 1.19
diff -p -p -u -r1.19 ppb.c
--- dev/pci/ppb.c	1999/11/04 19:04:04	1.19
+++ dev/pci/ppb.c	2001/02/11 18:09:29
@@ -117,6 +117,9 @@ ppbattach(parent, self, aux)
 	pba.pba_bus = PPB_BUSINFO_SECONDARY(busdata);
 	pba.pba_intrswiz = pa->pa_intrswiz;
 	pba.pba_intrtag = pa->pa_intrtag;
+#ifdef __PCI_OFW_BINDING
+        pba.pba_node = pa->pa_node;
+#endif
 
 	config_found(self, &pba, ppbprint);
 }
Index: dev/ofw/ofw_pci.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/ofw/ofw_pci.h,v
retrieving revision 1.2
diff -p -p -u -r1.2 ofw_pci.h
--- dev/ofw/ofw_pci.h	1999/05/05 08:09:34	1.2
+++ dev/ofw/ofw_pci.h	2001/02/11 18:09:30
@@ -87,4 +87,20 @@
 #define	OFW_PCI_PHYS_HI_SPACE_MEM32	0x02000000
 #define	OFW_PCI_PHYS_HI_SPACE_MEM64	0x03000000
 
+#define OFW_PCI_PHYS_HI_DEVICE(hi) \
+	(((hi) & OFW_PCI_PHYS_HI_DEVICEMASK) >> OFW_PCI_PHYS_HI_DEVICESHIFT)
+#define OFW_PCI_PHYS_HI_FUNCTION(hi) \
+	(((hi) & OFW_PCI_PHYS_HI_FUNCTIONMASK) >> OFW_PCI_PHYS_HI_FUNCTIONSHIFT)
+
+/*
+ * This has the 3 32bit cell values, plus 2 more to make up a 64-bit size.
+ */
+struct ofw_pci_register {
+	u_int32_t	phys_hi;
+	u_int32_t	phys_mid;
+	u_int32_t	phys_lo;
+	u_int32_t	size_hi;
+	u_int32_t	size_lo;
+};
+
 #endif /* _DEV_OFW_OFW_PCI_H_ */