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 *)®, 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 *)®, 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 *)®, 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 *)®, 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 *)®, 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);