summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/files.sparc645
-rw-r--r--sys/conf/options.sparc641
-rw-r--r--sys/sparc64/ebus/ebus.c37
-rw-r--r--sys/sparc64/include/ofw_bus.h27
-rw-r--r--sys/sparc64/isa/isa.c62
-rw-r--r--sys/sparc64/isa/ofw_isa.c33
-rw-r--r--sys/sparc64/isa/ofw_isa.h18
-rw-r--r--sys/sparc64/pci/apb.c182
-rw-r--r--sys/sparc64/pci/ofw_pci.c37
-rw-r--r--sys/sparc64/pci/ofw_pci.h31
-rw-r--r--sys/sparc64/pci/ofw_pci_if.m76
-rw-r--r--sys/sparc64/pci/ofw_pcib.c122
-rw-r--r--sys/sparc64/pci/ofw_pcib_subr.c134
-rw-r--r--sys/sparc64/pci/ofw_pcib_subr.h49
-rw-r--r--sys/sparc64/pci/ofw_pcibus.c264
-rw-r--r--sys/sparc64/pci/psycho.c228
-rw-r--r--sys/sparc64/pci/psychovar.h7
-rw-r--r--sys/sparc64/sparc64/ofw_bus.c126
-rw-r--r--sys/sparc64/sparc64/sparcbus_if.m93
19 files changed, 1160 insertions, 372 deletions
diff --git a/sys/conf/files.sparc64 b/sys/conf/files.sparc64
index 107312f..1f76310 100644
--- a/sys/conf/files.sparc64
+++ b/sys/conf/files.sparc64
@@ -34,6 +34,10 @@ sparc64/isa/ofw_isa.c optional ebus
sparc64/isa/ofw_isa.c optional isa
sparc64/pci/apb.c optional apb
sparc64/pci/ofw_pci.c optional pci
+sparc64/pci/ofw_pcib.c optional pci ofw_newpci
+sparc64/pci/ofw_pcib_subr.c optional pci ofw_newpci
+sparc64/pci/ofw_pcibus.c optional pci ofw_newpci
+sparc64/pci/ofw_pci_if.m optional pci
sparc64/pci/psycho.c optional pci
sparc64/sbus/sbus.c optional sbus
sparc64/sparc64/autoconf.c standard
@@ -71,7 +75,6 @@ sparc64/sparc64/ofw_machdep.c standard
sparc64/sparc64/pmap.c standard
sparc64/sparc64/prof_machdep.c optional profiling-routine
sparc64/sparc64/rwindow.c standard
-sparc64/sparc64/sparcbus_if.m standard
sparc64/sparc64/spitfire.c standard
sparc64/sparc64/support.S standard
sparc64/sparc64/sys_machdep.c standard
diff --git a/sys/conf/options.sparc64 b/sys/conf/options.sparc64
index d0893b7..5bd885a 100644
--- a/sys/conf/options.sparc64
+++ b/sys/conf/options.sparc64
@@ -6,6 +6,7 @@ EBUS_DEBUG opt_ebus.h
PSYCHO_DEBUG opt_psycho.h
DEBUGGER_ON_POWERFAIL opt_psycho.h
OFW_PCI_DEBUG opt_ofw_pci.h
+OFW_NEWPCI opt_ofw_pci.h
# Normal IOMMU debugging
IOMMU_DEBUG opt_iommu.h
# Debug IOMMU inserts/removes using diagnostic accesses. Very loud.
diff --git a/sys/sparc64/ebus/ebus.c b/sys/sparc64/ebus/ebus.c
index 6c71e02..575ba0a 100644
--- a/sys/sparc64/ebus/ebus.c
+++ b/sys/sparc64/ebus/ebus.c
@@ -48,6 +48,8 @@
* there are machines with both ISA and EBus.
*/
+#include "opt_ofw_pci.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -101,6 +103,10 @@ struct ebus_softc {
int sc_nrange;
int sc_nimap;
+
+#ifdef OFW_NEWPCI
+ struct ofw_bus_iinfo sc_iinfo;
+#endif
};
static int ebus_probe(device_t);
@@ -159,12 +165,12 @@ ebus_probe(device_t dev)
phandle_t node;
char *cname;
- /*
- * XXX: PCI specific! There should be a common cookie IVAR value for all
- * buses! Does not really matter much here though...
- */
+#ifdef OFW_NEWPCI
+ node = ofw_pci_get_node(dev);
+#else
node = ofw_pci_find_node(pci_get_bus(dev), pci_get_slot(dev),
pci_get_function(dev));
+#endif
if (node == 0)
return (ENXIO);
@@ -192,8 +198,12 @@ ebus_probe(device_t dev)
if (sc->sc_nrange == -1)
panic("ebus_attach: could not get ranges property");
+#ifdef OFW_NEWPCI
+ ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_isa_intr_t));
+#endif
+
/*
- * now attach all our children
+ * Now attach our children.
*/
DPRINTF(EDB_CHILD, ("ebus node %08x, searching children...\n", node));
for (node = OF_child(node); node > 0; node = OF_peer(node)) {
@@ -368,7 +378,8 @@ ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node,
{
struct ebus_devinfo *edi;
struct isa_regs *reg;
- u_int32_t *intrs, intr;
+ ofw_isa_intr_t *intrs;
+ ofw_pci_intr_t rintr;
u_int64_t start;
int nreg, nintr, i;
@@ -395,20 +406,26 @@ ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node,
resource_list_add(&edi->edi_rl, SYS_RES_IOPORT, i,
start, start + reg[i].size - 1, reg[i].size);
}
+ free(reg, M_OFWPROP);
nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs),
(void **)&intrs);
for (i = 0; i < nintr; i++) {
- intr = ofw_bus_route_intr(node, intrs[i], ofw_pci_orb_callback,
+#ifdef OFW_NEWPCI
+ rintr = ofw_isa_route_intr(dev, node, &sc->sc_iinfo, intrs[i]);
+ if (rintr == PCI_INVALID_IRQ) {
+#else
+ rintr = ofw_bus_route_intr(node, intrs[i], ofw_pci_orb_callback,
dev);
- if (intr == ORIR_NOTFOUND) {
+ if (rintr == ORIR_NOTFOUND) {
+#endif
panic("ebus_setup_dinfo: could not map ebus "
"interrupt %d", intrs[i]);
}
resource_list_add(&edi->edi_rl, SYS_RES_IRQ, i,
- intr, intr, 1);
+ rintr, rintr, 1);
}
- free(reg, M_OFWPROP);
+ free(intrs, M_OFWPROP);
return (edi);
}
diff --git a/sys/sparc64/include/ofw_bus.h b/sys/sparc64/include/ofw_bus.h
index 9f07183..f720180 100644
--- a/sys/sparc64/include/ofw_bus.h
+++ b/sys/sparc64/include/ofw_bus.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>.
+ * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,9 +31,34 @@
#define ORIP_NOINT -1
#define ORIR_NOTFOUND 0xffffffff
+/*
+ * Other than in OpenFirmware calls, the size of a bus cell seems to be always
+ * the same.
+ */
+typedef u_int32_t pcell_t;
+
+#ifdef OFW_NEWPCI
+
+struct ofw_bus_iinfo {
+ u_int8_t *opi_imap;
+ u_int8_t *opi_imapmsk;
+ int opi_imapsz;
+ pcell_t opi_addrc;
+};
+
+void ofw_bus_setup_iinfo(phandle_t, struct ofw_bus_iinfo *, int);
+int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
+ void *, int, void *, int, void *);
+int ofw_bus_search_intrmap(void *, int, void *, int, void *, int, void *,
+ void *, void *, int);
+
+#else
+
typedef int obr_callback_t(phandle_t, u_int8_t *, int, u_int8_t *, int,
u_int8_t **, int *, void *);
u_int32_t ofw_bus_route_intr(phandle_t, int, obr_callback_t *, void *);
+#endif
+
#endif /* !_MACHINE_OFW_BUS_H_ */
diff --git a/sys/sparc64/isa/isa.c b/sys/sparc64/isa/isa.c
index 2df0257d..4916b1e 100644
--- a/sys/sparc64/isa/isa.c
+++ b/sys/sparc64/isa/isa.c
@@ -29,6 +29,8 @@
* $FreeBSD$
*/
+#include "opt_ofw_pci.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -57,8 +59,6 @@
#include <sparc64/pci/ofw_pci.h>
#include <sparc64/isa/ofw_isa.h>
-#include "sparcbus_if.h"
-
/* There can be only one ISA bus, so it is safe to use globals. */
bus_space_tag_t isa_io_bt = NULL;
bus_space_handle_t isa_io_hdl;
@@ -73,7 +73,11 @@ u_int64_t isa_mem_limit;
device_t isa_bus_device;
static phandle_t isab_node;
-static u_int32_t isa_ino[8];
+static ofw_pci_intr_t isa_ino[8];
+
+#ifdef OFW_NEWPCI
+struct ofw_bus_iinfo isa_iinfo;
+#endif
/*
* XXX: This is really partly partly PCI-specific, but unfortunately is
@@ -98,9 +102,9 @@ isa_irq_pending(void)
/* XXX: Is this correct? */
for (i = 7, pending = 0; i >= 0; i--) {
- pending <<= 1;
- if (isa_ino[i] != ORIR_NOTFOUND) {
- pending |= (SPARCBUS_INTR_PENDING(isa_bus_device,
+ pending <<= 1;
+ if (isa_ino[i] != PCI_INVALID_IRQ) {
+ pending |= (OFW_PCI_INTR_PENDING(isa_bus_device,
isa_ino[i]) == 0) ? 0 : 1;
}
}
@@ -112,29 +116,47 @@ isa_init(device_t dev)
{
device_t bridge;
phandle_t node;
- u_int32_t ino;
+ ofw_isa_intr_t ino;
+#ifndef OFW_NEWPCI
+ ofw_pci_intr_t rino;
+#endif
struct isa_ranges *br;
int nbr, i;
/* The parent of the bus must be a PCI-ISA bridge. */
bridge = device_get_parent(dev);
+#ifdef OFW_NEWPCI
+ isab_node = ofw_pci_get_node(bridge);
+#else
isab_node = ofw_pci_node(bridge);
+#endif
nbr = OF_getprop_alloc(isab_node, "ranges", sizeof(*br), (void **)&br);
if (nbr <= 0)
panic("isa_init: cannot get bridge range property");
+
+#ifdef OFW_NEWPCI
+ ofw_bus_setup_iinfo(isab_node, &isa_iinfo, sizeof(ofw_isa_intr_t));
+#endif
+
/*
- * This is really a bad kluge; however, it is needed to provide
- * isa_irq_pending().
+ * This is really a bad kludge; however, it is needed to provide
+ * isa_irq_pending(), which is unfortunately still used by some
+ * drivers.
*/
for (i = 0; i < 8; i++)
- isa_ino[i] = ORIR_NOTFOUND;
+ isa_ino[i] = PCI_INVALID_IRQ;
for (node = OF_child(isab_node); node != 0; node = OF_peer(node)) {
if (OF_getprop(node, "interrupts", &ino, sizeof(ino)) == -1)
continue;
if (ino > 7)
panic("isa_init: XXX: ino too large");
- isa_ino[ino] = ofw_bus_route_intr(node, ino,
- ofw_pci_orb_callback, dev);
+#ifdef OFW_NEWPCI
+ isa_ino[ino] = ofw_isa_route_intr(bridge, node, &isa_iinfo,
+ ino);
+#else
+ rino = ofw_bus_route_intr(node, ino, ofw_pci_orb_callback, dev);
+ isa_ino[ino] = rino == ORIR_NOTFOUND ? PCI_INVALID_IRQ : rino;
+#endif
}
for (nbr -= 1; nbr >= 0; nbr--) {
@@ -143,15 +165,15 @@ isa_init(device_t dev)
/* This is probably always 0. */
isa_io_base = ISAB_RANGE_PHYS(&br[nbr]);
isa_io_limit = br[nbr].size;
- isa_io_hdl = SPARCBUS_GET_BUS_HANDLE(bridge, SBBT_IO,
- isa_io_base, &isa_io_bt);
+ isa_io_hdl = OFW_PCI_GET_BUS_HANDLE(bridge,
+ SYS_RES_IOPORT, isa_io_base, &isa_io_bt);
break;
case ISAR_SPACE_MEM:
/* This is probably always 0. */
isa_mem_base = ISAB_RANGE_PHYS(&br[nbr]);
isa_mem_limit = br[nbr].size;
- isa_mem_hdl = SPARCBUS_GET_BUS_HANDLE(bridge, SBBT_MEM,
- isa_mem_base, &isa_mem_bt);
+ isa_mem_hdl = OFW_PCI_GET_BUS_HANDLE(bridge,
+ SYS_RES_MEMORY, isa_mem_base, &isa_mem_bt);
break;
}
}
@@ -170,7 +192,7 @@ isa_route_intr_res(device_t bus, u_long start, u_long end)
if (start > 7)
panic("isa_route_intr_res: start out of isa range");
res = isa_ino[start];
- if (res == ORIR_NOTFOUND)
+ if (res == PCI_INVALID_IRQ)
device_printf(bus, "could not map interrupt %d\n", res);
return (res);
}
@@ -244,7 +266,7 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
"irq allocation");
if (!isdefault) {
start = end = isa_route_intr_res(bus, start, end);
- if (start == 255)
+ if (start == PCI_INVALID_IRQ)
return (NULL);
}
break;
@@ -255,7 +277,7 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
start = ulmin(start + base, limit);
end = ulmin(end + base, limit);
}
-
+
/*
* This inlines a modified resource_list_alloc(); this is needed
* because the resources need to have offsets added to them, which
@@ -289,7 +311,7 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
break;
case SYS_RES_IRQ:
start = end = isa_route_intr_res(bus, start, end);
- if (start == 255)
+ if (start == PCI_INVALID_IRQ)
return (NULL);
break;
}
diff --git a/sys/sparc64/isa/ofw_isa.c b/sys/sparc64/isa/ofw_isa.c
index a87665e..986220d 100644
--- a/sys/sparc64/isa/ofw_isa.c
+++ b/sys/sparc64/isa/ofw_isa.c
@@ -1,6 +1,6 @@
/*
* Copyright (c) 1999, 2000 Matthew R. Green
- * Copyright (c) 2001 Thomas Moestl <tmm@FreeBSD.org>
+ * Copyright (c) 2001, 2003 Thomas Moestl <tmm@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,6 +35,8 @@
* Helper functions which can be used in both ISA and EBus code.
*/
+#include "opt_ofw_pci.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
@@ -42,11 +44,14 @@
#include <ofw/openfirm.h>
#include <ofw/ofw_pci.h>
+#include <machine/bus.h>
#include <machine/resource.h>
#include <machine/ofw_bus.h>
-#include <sparc64/isa/ofw_isa.h>
#include <sparc64/pci/ofw_pci.h>
+#include <sparc64/isa/ofw_isa.h>
+
+#include "pcib_if.h"
/* XXX: this only supports PCI as parent bus right now. */
int
@@ -86,3 +91,27 @@ ofw_isa_map_iorange(struct isa_ranges *range, int nrange, u_long *start,
panic("ofw_isa_map_iorange: could not map range %#lx - %#lx",
*start, *end);
}
+
+#ifdef OFW_NEWPCI
+ofw_pci_intr_t
+ofw_isa_route_intr(device_t bridge, phandle_t node, struct ofw_bus_iinfo *ii,
+ ofw_isa_intr_t intr)
+{
+ struct isa_regs reg;
+ u_int8_t maskbuf[sizeof(reg) + sizeof(intr)];
+ device_t pbridge;
+ ofw_isa_intr_t mintr;
+
+ pbridge = device_get_parent(device_get_parent(bridge));
+ /*
+ * If we get a match from using the map, the resulting INO is
+ * fully specified, so we may not continue to map.
+ */
+ if (!ofw_bus_lookup_imap(node, ii, &reg, sizeof(reg),
+ &intr, sizeof(intr), &mintr, sizeof(mintr), maskbuf)) {
+ /* Try routing at the parent bridge. */
+ mintr = PCIB_ROUTE_INTERRUPT(pbridge, bridge, intr);
+ }
+ return (mintr);
+}
+#endif /* OFW_NEWPCI */
diff --git a/sys/sparc64/isa/ofw_isa.h b/sys/sparc64/isa/ofw_isa.h
index 9402657..dd534ad 100644
--- a/sys/sparc64/isa/ofw_isa.h
+++ b/sys/sparc64/isa/ofw_isa.h
@@ -60,24 +60,28 @@ struct isa_ranges {
((((u_int64_t)((r)->child_hi)) << 32) | ((u_int64_t)(r)->child_lo))
#define ISA_RANGE_PS(r) (((r)->phys_hi >> 24) & 0x03)
+typedef u_int32_t ofw_isa_intr_t;
+
struct isa_imap {
u_int32_t phys_hi; /* high phys addr mask */
u_int32_t phys_lo; /* low phys addr mask */
- u_int32_t intr; /* interrupt mask */
- int32_t cnode; /* child node */
- u_int32_t cintr; /* child interrupt */
+ ofw_isa_intr_t intr; /* interrupt mask */
+ phandle_t cnode; /* child node */
+ ofw_pci_intr_t cintr; /* child interrupt */
};
struct isa_imap_msk {
u_int32_t phys_hi; /* high phys addr */
u_int32_t phys_lo; /* low phys addr */
- u_int32_t intr; /* interrupt */
+ ofw_isa_intr_t intr; /* interrupt */
};
-/* Map an interrupt property to an INO */
-int ofw_isa_map_intr(struct isa_imap *, int, struct isa_imap_msk *, int,
- struct isa_regs *, int);
/* Map an IO range. Returns the resource type of the range. */
int ofw_isa_map_iorange(struct isa_ranges *, int, u_long *, u_long *);
+#ifdef OFW_NEWPCI
+ofw_pci_intr_t ofw_isa_route_intr(device_t, phandle_t, struct ofw_bus_iinfo *,
+ ofw_isa_intr_t);
+#endif
+
#endif /* !_SPARC64_ISA_OFW_ISA_H_ */
diff --git a/sys/sparc64/pci/apb.c b/sys/sparc64/pci/apb.c
index 4e8b746..49324b2 100644
--- a/sys/sparc64/pci/apb.c
+++ b/sys/sparc64/pci/apb.c
@@ -2,7 +2,7 @@
* Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier
* Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
* Copyright (c) 2000 BSDi
- * Copyright (c) 2001 Thomas Moestl <tmm@FreeBSD.org>
+ * Copyright (c) 2001, 2003 Thomas Moestl <tmm@FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -40,6 +40,8 @@
* We can use some pf the pcib methods anyway.
*/
+#include "opt_ofw_pci.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -49,40 +51,34 @@
#include <dev/ofw/openfirm.h>
#include <dev/ofw/ofw_pci.h>
+#include <machine/bus.h>
+#include <machine/ofw_bus.h>
#include <machine/resource.h>
-#include <sparc64/pci/ofw_pci.h>
-
-#include <pci/pcivar.h>
#include <pci/pcireg.h>
+#include <pci/pcivar.h>
+#include <pci/pcib_private.h>
#include "pcib_if.h"
+#include <sparc64/pci/ofw_pci.h>
+#include <sparc64/pci/ofw_pcib_subr.h>
+
/*
* Bridge-specific data.
*/
struct apb_softc {
- device_t dev;
- u_int8_t secbus; /* secondary bus number */
- u_int8_t subbus; /* subordinate bus number */
- u_int8_t iomap;
- u_int8_t memmap;
+ struct ofw_pcib_gen_softc sc_bsc;
+ u_int8_t sc_iomap;
+ u_int8_t sc_memmap;
};
-static int apb_probe(device_t dev);
-static int apb_attach(device_t dev);
-static struct resource *apb_alloc_resource(device_t dev, device_t child,
- int type, int *rid, u_long start, u_long end, u_long count, u_int flags);
-static int apb_read_ivar(device_t dev, device_t child, int which,
- uintptr_t *result);
-static int apb_write_ivar(device_t dev, device_t child, int which,
- uintptr_t value);
-static int apb_maxslots(device_t dev);
-static u_int32_t apb_read_config(device_t dev, int b, int s, int f, int reg,
- int width);
-static void apb_write_config(device_t dev, int b, int s, int f, int reg,
- u_int32_t val, int width);
-static int apb_route_interrupt(device_t pcib, device_t dev, int pin);
+static device_probe_t apb_probe;
+static device_attach_t apb_attach;
+static bus_alloc_resource_t apb_alloc_resource;
+#ifndef OFW_NEWPCI
+static pcib_route_interrupt_t apb_route_interrupt;
+#endif
static device_method_t apb_methods[] = {
/* Device interface */
@@ -94,8 +90,8 @@ static device_method_t apb_methods[] = {
/* Bus interface */
DEVMETHOD(bus_print_child, bus_generic_print_child),
- DEVMETHOD(bus_read_ivar, apb_read_ivar),
- DEVMETHOD(bus_write_ivar, apb_write_ivar),
+ DEVMETHOD(bus_read_ivar, pcib_read_ivar),
+ DEVMETHOD(bus_write_ivar, pcib_write_ivar),
DEVMETHOD(bus_alloc_resource, apb_alloc_resource),
DEVMETHOD(bus_release_resource, bus_generic_release_resource),
DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
@@ -104,10 +100,20 @@ static device_method_t apb_methods[] = {
DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
/* pcib interface */
- DEVMETHOD(pcib_maxslots, apb_maxslots),
- DEVMETHOD(pcib_read_config, apb_read_config),
- DEVMETHOD(pcib_write_config, apb_write_config),
+ DEVMETHOD(pcib_maxslots, pcib_maxslots),
+ DEVMETHOD(pcib_read_config, pcib_read_config),
+ DEVMETHOD(pcib_write_config, pcib_write_config),
+#ifdef OFW_NEWPCI
+ DEVMETHOD(pcib_route_interrupt, ofw_pcib_gen_route_interrupt),
+#else
DEVMETHOD(pcib_route_interrupt, apb_route_interrupt),
+#endif
+
+ /* ofw_pci interface */
+#ifdef OFW_NEWPCI
+ DEVMETHOD(ofw_pci_get_node, ofw_pcib_gen_get_node),
+ DEVMETHOD(ofw_pci_adjust_busrange, ofw_pcib_gen_adjust_busrange),
+#endif
{ 0, 0 }
};
@@ -118,9 +124,7 @@ static driver_t apb_driver = {
sizeof(struct apb_softc),
};
-static devclass_t apb_devclass;
-
-DRIVER_MODULE(apb, pci, apb_driver, apb_devclass, 0, 0);
+DRIVER_MODULE(apb, pci, apb_driver, pcib_devclass, 0, 0);
/* APB specific registers */
#define APBR_IOMAP 0xde
@@ -178,42 +182,42 @@ static int
apb_attach(device_t dev)
{
struct apb_softc *sc;
- device_t child;
sc = device_get_softc(dev);
- sc->dev = dev;
/*
* Get current bridge configuration.
*/
- sc->secbus = pci_read_config(dev, PCIR_SECBUS_1, 1);
- sc->subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1);
- sc->iomap = pci_read_config(dev, APBR_IOMAP, 1);
- sc->memmap = pci_read_config(dev, APBR_MEMMAP, 1);
+ sc->sc_iomap = pci_read_config(dev, APBR_IOMAP, 1);
+ sc->sc_memmap = pci_read_config(dev, APBR_MEMMAP, 1);
+#ifdef OFW_NEWPCI
+ ofw_pcib_gen_setup(dev);
+#else
+ sc->sc_bsc.ops_pcib_sc.dev = dev;
+ sc->sc_bsc.ops_pcib_sc.secbus = pci_read_config(dev, PCIR_SECBUS_1, 1);
+ sc->sc_bsc.ops_pcib_sc.subbus = pci_read_config(dev, PCIR_SUBBUS_1, 1);
+#endif
if (bootverbose) {
- device_printf(dev, " secondary bus %d\n", sc->secbus);
- device_printf(dev, " subordinate bus %d\n", sc->subbus);
+ device_printf(dev, " secondary bus %d\n",
+ sc->sc_bsc.ops_pcib_sc.secbus);
+ device_printf(dev, " subordinate bus %d\n",
+ sc->sc_bsc.ops_pcib_sc.subbus);
device_printf(dev, " I/O decode ");
- apb_map_print(sc->iomap, APB_IO_SCALE);
+ apb_map_print(sc->sc_iomap, APB_IO_SCALE);
printf("\n");
device_printf(dev, " memory decode ");
- apb_map_print(sc->memmap, APB_MEM_SCALE);
+ apb_map_print(sc->sc_memmap, APB_MEM_SCALE);
printf("\n");
}
- /*
- * If we don't hardwire the bus down, pciconf gets confused.
- */
- if (sc->secbus != 0) {
- child = device_add_child(dev, "pci", sc->secbus);
- if (child != NULL)
- return (bus_generic_attach(dev));
- } else
+#ifndef OFW_NEWPCI
+ if (sc->sc_bsc.ops_pcib_sc.secbus == 0)
panic("apb_attach: APB with uninitialized secbus");
+#endif
- /* no secondary bus; we should have fixed this */
- return (0);
+ device_add_child(dev, "pci", sc->sc_bsc.ops_pcib_sc.secbus);
+ return (bus_generic_attach(dev));
}
/*
@@ -244,8 +248,8 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid,
*/
switch (type) {
case SYS_RES_IOPORT:
- if (!apb_map_checkrange(sc->iomap, APB_IO_SCALE, start,
- end)) {
+ if (!apb_map_checkrange(sc->sc_iomap, APB_IO_SCALE,
+ start, end)) {
device_printf(dev, "device %s%d requested "
"unsupported I/O range 0x%lx-0x%lx\n",
device_get_name(child),
@@ -253,14 +257,14 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid,
return (NULL);
}
if (bootverbose)
- device_printf(sc->dev, "device %s%d requested "
- "decoded I/O range 0x%lx-0x%lx\n",
- device_get_name(child),
+ device_printf(sc->sc_bsc.ops_pcib_sc.dev,
+ "device %s%d requested decoded I/O range "
+ "0x%lx-0x%lx\n", device_get_name(child),
device_get_unit(child), start, end);
break;
case SYS_RES_MEMORY:
- if (!apb_map_checkrange(sc->memmap, APB_MEM_SCALE,
+ if (!apb_map_checkrange(sc->sc_memmap, APB_MEM_SCALE,
start, end)) {
device_printf(dev, "device %s%d requested "
"unsupported memory range 0x%lx-0x%lx\n",
@@ -269,8 +273,9 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid,
return (NULL);
}
if (bootverbose)
- device_printf(sc->dev, "device %s%d requested "
- "decoded memory range 0x%lx-0x%lx\n",
+ device_printf(sc->sc_bsc.ops_pcib_sc.dev,
+ "device %s%d requested decoded memory "
+ "range 0x%lx-0x%lx\n",
device_get_name(child),
device_get_unit(child), start, end);
break;
@@ -287,63 +292,7 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid,
count, flags));
}
-static int
-apb_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
-{
- struct apb_softc *sc = device_get_softc(dev);
-
- switch (which) {
- case PCIB_IVAR_BUS:
- *result = sc->secbus;
- return (0);
- }
- return (ENOENT);
-}
-
-static int
-apb_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
-{
- struct apb_softc *sc = device_get_softc(dev);
-
- switch (which) {
- case PCIB_IVAR_BUS:
- sc->secbus = value;
- break;
- }
- return (ENOENT);
-}
-
-/*
- * PCIB interface.
- */
-static int
-apb_maxslots(device_t dev)
-{
-
- return (PCI_SLOTMAX);
-}
-
-/*
- * Since we are a child of a PCI bus, its parent must support the pcib
- * interface.
- */
-static u_int32_t
-apb_read_config(device_t dev, int b, int s, int f, int reg, int width)
-{
-
- return (PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), b,
- s, f, reg, width));
-}
-
-static void
-apb_write_config(device_t dev, int b, int s, int f, int reg, u_int32_t val,
- int width)
-{
-
- PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), b, s, f, reg,
- val, width);
-}
-
+#ifndef OFW_NEWPCI
/*
* Route an interrupt across a PCI bridge - we need to rely on the firmware
* here.
@@ -369,3 +318,4 @@ apb_route_interrupt(device_t pcib, device_t dev, int pin)
*/
return (0);
}
+#endif /* !OFW_NEWPCI */
diff --git a/sys/sparc64/pci/ofw_pci.c b/sys/sparc64/pci/ofw_pci.c
index ca54bf1..7da9cbb 100644
--- a/sys/sparc64/pci/ofw_pci.c
+++ b/sys/sparc64/pci/ofw_pci.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 1999, 2000 Matthew R. Green
+ * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>
* All rights reserved.
- * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -38,27 +38,29 @@
#include <sys/systm.h>
#include <sys/bus.h>
-#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
#include <dev/ofw/ofw_pci.h>
#include <dev/ofw/openfirm.h>
-#include <sparc64/pci/ofw_pci.h>
-
#include <machine/bus.h>
#include <machine/cache.h>
#include <machine/iommureg.h>
#include <machine/ofw_bus.h>
#include <machine/ver.h>
+#include <sparc64/pci/ofw_pci.h>
+
#include "pcib_if.h"
-#include "sparcbus_if.h"
u_int8_t pci_bus_cnt;
phandle_t *pci_bus_map;
int pci_bus_map_sz;
+#define PCI_BUS_MAP_INC 10
+
+#ifndef OFW_NEWPCI
/* Do not swizzle on a PCI bus node with no interrupt-map propery. */
#define OPQ_NO_SWIZZLE 1
/*
@@ -85,7 +87,6 @@ static int pci_quirks;
#define OFW_PCI_PCIBUS "pci"
#define OFW_PCI_EBUS "ebus"
-#define PCI_BUS_MAP_INC 10
int
ofw_pci_orb_callback(phandle_t node, u_int8_t *pintptr, int pintsz,
@@ -94,7 +95,7 @@ ofw_pci_orb_callback(phandle_t node, u_int8_t *pintptr, int pintsz,
{
device_t dev = cookie;
struct ofw_pci_register preg;
- u_int32_t pintr, intr;
+ ofw_pci_intr_t pintr, intr;
u_int slot;
char type[32];
int found = 0;
@@ -105,7 +106,7 @@ ofw_pci_orb_callback(phandle_t node, u_int8_t *pintptr, int pintsz,
*terminate = 1;
return (-1);
}
- if (pintsz != sizeof(u_int32_t) || pregsz < sizeof(preg))
+ if (pintsz != sizeof(pintr) || pregsz < sizeof(preg))
return (-1);
bcopy(pintptr, &pintr, sizeof(pintr));
bcopy(pregptr, &preg, sizeof(preg));
@@ -119,13 +120,13 @@ ofw_pci_orb_callback(phandle_t node, u_int8_t *pintptr, int pintsz,
* values for external PCI devices seem to always be below 255
* and describe the interrupt pin to be used on the slot, while
* we have to figure out the base INO by looking at the slot
- * number (which we do using a sparcbus method).
+ * number (which we do using an ofw_pci method).
*
* Of course, there is an exception to that nice rule:
* in the ebus case, the interrupt property has the correct
* INO (but without IGN). This is dealt with above.
*/
- intr = SPARCBUS_GUESS_INO(dev, node, slot, pintr);
+ intr = OFW_PCI_GUESS_INO(dev, node, slot, pintr);
found = intr != 255;
*terminate = found;
}
@@ -150,14 +151,14 @@ ofw_pci_orb_callback(phandle_t node, u_int8_t *pintptr, int pintsz,
return (-1);
}
-static u_int32_t
-ofw_pci_route_intr(device_t dev, phandle_t node, u_int32_t ign)
+static ofw_pci_intr_t
+ofw_pci_route_intr(device_t dev, phandle_t node, ofw_pci_intr_t ign)
{
u_int32_t rv;
rv = ofw_bus_route_intr(node, ORIP_NOINT, ofw_pci_orb_callback, dev);
if (rv == ORIR_NOTFOUND)
- return (255);
+ return (PCI_INVALID_IRQ);
/*
* Some machines (notably the SPARCengine Ultra AX and the e450) have
* no mappings at all, but use complete interrupt vector number
@@ -167,6 +168,7 @@ ofw_pci_route_intr(device_t dev, phandle_t node, u_int32_t ign)
rv -= ign;
return (rv);
}
+#endif /* !OFW_NEWCPI */
u_int8_t
ofw_pci_alloc_busno(phandle_t node)
@@ -192,6 +194,7 @@ ofw_pci_alloc_busno(phandle_t node)
return (n);
}
+#ifndef OFW_NEWPCI
/*
* Initialize bridge bus numbers for bridges that implement the primary,
* secondary and subordinate bus number registers.
@@ -220,7 +223,7 @@ ofw_pci_binit(device_t busdev, struct ofw_pci_bdesc *obd)
* as well as the the bus numbers and ranges of the bridges.
*/
void
-ofw_pci_init(device_t dev, phandle_t bushdl, u_int32_t ign,
+ofw_pci_init(device_t dev, phandle_t bushdl, ofw_pci_intr_t ign,
struct ofw_pci_bdesc *obd)
{
struct ofw_pci_register pcir;
@@ -321,7 +324,8 @@ ofw_pci_init(device_t dev, phandle_t bushdl, u_int32_t ign,
}
/* Initialize the intline registers. */
- if ((intr = ofw_pci_route_intr(dev, node, ign)) != 255) {
+ if ((intr = ofw_pci_route_intr(dev, node, ign)) !=
+ PCI_INVALID_IRQ) {
#ifdef OFW_PCI_DEBUG
device_printf(dev, "%s: mapping intr for "
"%d/%d/%d to %d (preset was %d)\n",
@@ -344,7 +348,7 @@ ofw_pci_init(device_t dev, phandle_t bushdl, u_int32_t ign,
* 255.
*/
PCIB_WRITE_CONFIG(dev, busno, slot, func,
- PCIR_INTLINE, 255, 1);
+ PCIR_INTLINE, PCI_INVALID_IRQ, 1);
}
}
} while ((node = OF_peer(node)) != 0);
@@ -384,3 +388,4 @@ ofw_pci_node(device_t dev)
return (ofw_pci_find_node(pci_get_bus(dev), pci_get_slot(dev),
pci_get_function(dev)));
}
+#endif /* OFW_NEWPCI */
diff --git a/sys/sparc64/pci/ofw_pci.h b/sys/sparc64/pci/ofw_pci.h
index 1c2122b..af26526 100644
--- a/sys/sparc64/pci/ofw_pci.h
+++ b/sys/sparc64/pci/ofw_pci.h
@@ -1,7 +1,7 @@
/*
* Copyright (c) 1999, 2000 Matthew R. Green
+ * Copyright (c) 2001, 2003 by Thomas Moestl <tmm@FreeBSD.org>
* All rights reserved.
- * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -36,6 +36,10 @@
#include <machine/ofw_bus.h>
+typedef u_int32_t ofw_pci_intr_t;
+
+#include "ofw_pci_if.h"
+
/* PCI range child spaces. XXX: are these MI? */
#define PCI_CS_CONFIG 0x00
#define PCI_CS_IO 0x01
@@ -46,18 +50,31 @@ struct ofw_pci_imap {
u_int32_t phys_hi;
u_int32_t phys_mid;
u_int32_t phys_lo;
- u_int32_t intr;
- int32_t child_node;
- u_int32_t child_intr;
+ ofw_pci_intr_t intr;
+ phandle_t child_node;
+ phandle_t child_intr;
};
struct ofw_pci_imap_msk {
u_int32_t phys_hi;
u_int32_t phys_mid;
u_int32_t phys_lo;
- u_int32_t intr;
+ ofw_pci_intr_t intr;
};
+u_int8_t ofw_pci_alloc_busno(phandle_t);
+
+#ifdef OFW_NEWPCI
+
+static __inline phandle_t
+ofw_pci_get_node(device_t dev)
+{
+
+ return (OFW_PCI_GET_NODE(device_get_parent(dev), dev));
+}
+
+#else
+
struct ofw_pci_bdesc;
typedef void ofw_pci_binit_t(device_t, struct ofw_pci_bdesc *);
@@ -72,10 +89,10 @@ struct ofw_pci_bdesc {
};
obr_callback_t ofw_pci_orb_callback;
-u_int8_t ofw_pci_alloc_busno(phandle_t);
ofw_pci_binit_t ofw_pci_binit;
-void ofw_pci_init(device_t, phandle_t, u_int32_t, struct ofw_pci_bdesc *);
+void ofw_pci_init(device_t, phandle_t, ofw_pci_intr_t, struct ofw_pci_bdesc *);
phandle_t ofw_pci_find_node(int, int, int);
phandle_t ofw_pci_node(device_t);
+#endif
#endif /* ! _SPARC64_PCI_OFW_PCI_H_ */
diff --git a/sys/sparc64/pci/ofw_pci_if.m b/sys/sparc64/pci/ofw_pci_if.m
index fe7826e..508e842 100644
--- a/sys/sparc64/pci/ofw_pci_if.m
+++ b/sys/sparc64/pci/ofw_pci_if.m
@@ -1,4 +1,4 @@
-# Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>.
+# Copyright (c) 2001, 2003 by Thomas Moestl <tmm@FreeBSD.org>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@@ -28,66 +28,98 @@
#include <dev/ofw/openfirm.h>
-INTERFACE sparcbus;
+#include <sparc64/pci/ofw_pci.h>
-HEADER {
- /* Bus tag types for the get_bustag method */
- enum sbbt_id {
- SBBT_IO,
- SBBT_MEM,
- };
-};
+INTERFACE ofw_pci;
CODE {
+ static ofw_pci_intr_pending_t ofw_pci_default_intr_pending;
+ static ofw_pci_guess_ino_t ofw_pci_default_guess_ino;
+ static ofw_pci_get_bus_handle_t ofw_pci_default_get_bus_handle;
+ static ofw_pci_get_node_t ofw_pci_default_get_node;
+ static ofw_pci_adjust_busrange_t ofw_pci_default_adjust_busrange;
+
static int
- sparcbus_default_intr_pending(device_t dev, int intr)
+ ofw_pci_default_intr_pending(device_t dev, ofw_pci_intr_t intr)
{
- return (SPARCBUS_INTR_PENDING(device_get_parent(dev), intr));
+ return (OFW_PCI_INTR_PENDING(device_get_parent(dev), intr));
}
- static u_int32_t
- sparcbus_default_guess_ino(device_t dev, phandle_t node, u_int slot,
+ static ofw_pci_intr_t
+ ofw_pci_default_guess_ino(device_t dev, phandle_t node, u_int slot,
u_int pin)
{
- return (SPARCBUS_GUESS_INO(device_get_parent(dev), node, slot,
+ return (OFW_PCI_GUESS_INO(device_get_parent(dev), node, slot,
pin));
}
static bus_space_handle_t
- sparcbus_default_get_bus_handle(device_t dev, enum sbbt_id id,
+ ofw_pci_default_get_bus_handle(device_t dev, int type,
bus_space_handle_t childhdl, bus_space_tag_t *tag)
{
- return (SPARCBUS_GET_BUS_HANDLE(device_get_parent(dev), id,
+ return (OFW_PCI_GET_BUS_HANDLE(device_get_parent(dev), type,
childhdl, tag));
}
+
+ static phandle_t
+ ofw_pci_default_get_node(device_t bus, device_t dev)
+ {
+
+ return (0);
+ }
+
+ static void
+ ofw_pci_default_adjust_busrange(device_t dev, u_int busno)
+ {
+
+ return (OFW_PCI_ADJUST_BUSRANGE(device_get_parent(dev), busno));
+ }
};
# Return whether an interrupt request is pending for the INO intr.
METHOD int intr_pending {
device_t dev;
- int intr;
-} DEFAULT sparcbus_default_intr_pending;
+ ofw_pci_intr_t intr;
+} DEFAULT ofw_pci_default_intr_pending;
# Let the bus driver guess the INO of the device at the given slot and intpin
# on the bus described by the node if it could not be determined from the
# firmware properties. Returns 255 if no INO could be found (mapping will
# continue at the parent), or the desired INO.
-METHOD u_int32_t guess_ino {
+# This method is only used in the !OFW_NEWPCI case, and will go away soon.
+METHOD ofw_pci_intr_t guess_ino {
device_t dev;
phandle_t node;
u_int slot;
u_int pin;
-} DEFAULT sparcbus_default_guess_ino;
+} DEFAULT ofw_pci_default_guess_ino;
# Get the bustag for the root bus. This is needed for ISA old-stlye
# in[bwl]()/out[bwl]() support, where no tag retrieved from a resource is
# passed. The returned tag is used to construct a tag for the whole ISA bus.
METHOD bus_space_handle_t get_bus_handle {
device_t dev;
- enum sbbt_id id;
+ int type;
bus_space_handle_t childhdl;
bus_space_tag_t *tag;
-} DEFAULT sparcbus_default_get_bus_handle;
+} DEFAULT ofw_pci_default_get_bus_handle;
+
+# Get the firmware node for the device dev on the bus bus. The default mthod
+# will return 0, which signals that there is no such node.
+# This could be an ivar, but isn't to avoid numbering conflicts with standard
+# pci/pcib ones.
+METHOD phandle_t get_node {
+ device_t bus;
+ device_t dev;
+} DEFAULT ofw_pci_default_get_node;
+
+# Make sure that all PCI bridges up in the hierarchy contain this bus in their
+# subordinate bus range. This is required because we reenumerate all PCI
+# buses.
+METHOD void adjust_busrange {
+ device_t dev;
+ u_int subbus;
+} DEFAULT ofw_pci_default_adjust_busrange;
diff --git a/sys/sparc64/pci/ofw_pcib.c b/sys/sparc64/pci/ofw_pcib.c
new file mode 100644
index 0000000..c70286a
--- /dev/null
+++ b/sys/sparc64/pci/ofw_pcib.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 1994,1995 Stefan Esser, Wolfgang StanglMeier
+ * Copyright (c) 2000 Michael Smith <msmith@freebsd.org>
+ * Copyright (c) 2000 BSDi
+ * Copyright (c) 2001 - 2003 Thomas Moestl <tmm@FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * from: FreeBSD: src/sys/dev/pci/pci_pci.c,v 1.3 2000/12/13
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_ofw_pci.h"
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/pciio.h>
+
+#include <dev/ofw/openfirm.h>
+
+#include <machine/bus.h>
+#include <machine/ofw_bus.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcib_private.h>
+
+#include "pcib_if.h"
+
+#include <sparc64/pci/ofw_pci.h>
+#include <sparc64/pci/ofw_pcib_subr.h>
+
+static device_probe_t ofw_pcib_probe;
+static device_attach_t ofw_pcib_attach;
+
+static device_method_t ofw_pcib_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ofw_pcib_probe),
+ DEVMETHOD(device_attach, ofw_pcib_attach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_read_ivar, pcib_read_ivar),
+ DEVMETHOD(bus_write_ivar, pcib_write_ivar),
+ DEVMETHOD(bus_alloc_resource, pcib_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ /* pcib interface */
+ DEVMETHOD(pcib_maxslots, pcib_maxslots),
+ DEVMETHOD(pcib_read_config, pcib_read_config),
+ DEVMETHOD(pcib_write_config, pcib_write_config),
+ DEVMETHOD(pcib_route_interrupt, ofw_pcib_gen_route_interrupt),
+
+ /* ofw_pci interface */
+ DEVMETHOD(ofw_pci_get_node, ofw_pcib_gen_get_node),
+ DEVMETHOD(ofw_pci_adjust_busrange, ofw_pcib_gen_adjust_busrange),
+
+ { 0, 0 }
+};
+
+static driver_t ofw_pcib_driver = {
+ "pcib",
+ ofw_pcib_methods,
+ sizeof(struct ofw_pcib_gen_softc),
+};
+
+DRIVER_MODULE(ofw_pcib, pci, ofw_pcib_driver, pcib_devclass, 0, 0);
+
+static int
+ofw_pcib_probe(device_t dev)
+{
+ if ((pci_get_class(dev) == PCIC_BRIDGE) &&
+ (pci_get_subclass(dev) == PCIS_BRIDGE_PCI) &&
+ ofw_pci_get_node(dev) != 0) {
+ device_set_desc(dev, "OFW PCI-PCI bridge");
+ return (0);
+ }
+ return (ENXIO);
+}
+
+static int
+ofw_pcib_attach(device_t dev)
+{
+ struct ofw_pcib_gen_softc *sc = device_get_softc(dev);
+
+ ofw_pcib_gen_setup(dev);
+ pcib_attach_common(dev);
+ device_add_child(dev, "pci", sc->ops_pcib_sc.secbus);
+ return (bus_generic_attach(dev));
+}
diff --git a/sys/sparc64/pci/ofw_pcib_subr.c b/sys/sparc64/pci/ofw_pcib_subr.c
new file mode 100644
index 0000000..0c72c48
--- /dev/null
+++ b/sys/sparc64/pci/ofw_pcib_subr.c
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 2003 by Thomas Moestl <tmm@FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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 AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_ofw_pci.h"
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+
+#include <machine/bus.h>
+#include <machine/ofw_bus.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcib_private.h>
+
+#include "pcib_if.h"
+
+#include <sparc64/pci/ofw_pci.h>
+#include <sparc64/pci/ofw_pcib_subr.h>
+
+void
+ofw_pcib_gen_setup(device_t bridge)
+{
+ struct ofw_pcib_gen_softc *sc = device_get_softc(bridge);
+ u_int secbus;
+
+ sc->ops_pcib_sc.dev = bridge;
+ sc->ops_node = ofw_pci_get_node(bridge);
+ KASSERT(sc->ops_node != 0,
+ ("ofw_pcib_gen_setup: no ofw pci parent bus!"));
+
+ /*
+ * Setup the secondary bus number register, by allocating a new unique
+ * bus number for it; the firmware preset does not always seem to be
+ * correct.
+ */
+ secbus = ofw_pci_alloc_busno(sc->ops_node);
+ pci_write_config(bridge, PCIR_PRIBUS_1, pci_get_bus(bridge), 1);
+ pci_write_config(bridge, PCIR_SECBUS_1, secbus, 1);
+ pci_write_config(bridge, PCIR_SUBBUS_1, secbus, 1);
+ sc->ops_pcib_sc.subbus = sc->ops_pcib_sc.secbus = secbus;
+ /* Notify parent bridges. */
+ OFW_PCI_ADJUST_BUSRANGE(device_get_parent(bridge), secbus);
+
+ ofw_bus_setup_iinfo(sc->ops_node, &sc->ops_iinfo,
+ sizeof(ofw_pci_intr_t));
+}
+
+int
+ofw_pcib_gen_route_interrupt(device_t bridge, device_t dev, int intpin)
+{
+ struct ofw_pcib_gen_softc *sc = device_get_softc(bridge);
+ struct ofw_bus_iinfo *ii = &sc->ops_iinfo;
+ struct ofw_pci_register reg;
+ device_t pbridge = device_get_parent(device_get_parent(bridge));
+ phandle_t node = ofw_pci_get_node(dev);
+ ofw_pci_intr_t pintr, mintr;
+ u_int8_t maskbuf[sizeof(reg) + sizeof(pintr)];
+
+ if (ii->opi_imapsz > 0) {
+ pintr = intpin;
+ if (ofw_bus_lookup_imap(node, ii, &reg, sizeof(reg), &pintr,
+ sizeof(pintr), &mintr, sizeof(mintr), maskbuf)) {
+ /*
+ * If we've found a mapping, return it and don't map
+ * it again on higher levels - that causes problems
+ * in some cases, and never seems to be required.
+ */
+ return (mintr);
+ }
+ } else if (intpin >= 1 && intpin <= 4) {
+ /*
+ * When an interrupt map is missing, we need to do the
+ * standard PCI swizzle and continue mapping at the parent.
+ */
+ return (pcib_route_interrupt(bridge, dev, intpin));
+ }
+ /* Try at the parent. */
+ return (PCIB_ROUTE_INTERRUPT(pbridge, bridge, intpin));
+}
+
+phandle_t
+ofw_pcib_gen_get_node(device_t bridge, device_t dev)
+{
+ struct ofw_pcib_gen_softc *sc = device_get_softc(bridge);
+
+ return (sc->ops_node);
+}
+
+void
+ofw_pcib_gen_adjust_busrange(device_t bridge, u_int subbus)
+{
+ struct ofw_pcib_gen_softc *sc = device_get_softc(bridge);
+
+ if (subbus > sc->ops_pcib_sc.subbus) {
+#ifdef OFW_PCI_DEBUG
+ device_printf(bridge,
+ "adjusting secondary bus number from %d to %d\n",
+ sc->ops_pcib_sc.subbus, subbus);
+#endif
+ pci_write_config(bridge, PCIR_SUBBUS_1, subbus, 1);
+ sc->ops_pcib_sc.subbus = subbus;
+ /* Notify parent bridges. */
+ OFW_PCI_ADJUST_BUSRANGE(device_get_parent(bridge), subbus);
+ }
+}
+
diff --git a/sys/sparc64/pci/ofw_pcib_subr.h b/sys/sparc64/pci/ofw_pcib_subr.h
new file mode 100644
index 0000000..8e03532
--- /dev/null
+++ b/sys/sparc64/pci/ofw_pcib_subr.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2003 by Thomas Moestl <tmm@FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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 AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SPARC64_PCI_OFW_PCI_SUBR_H
+#define _SPARC64_PCI_OFW_PCI_SUBR_H
+
+struct ofw_pcib_gen_softc {
+ /*
+ * This is here so that we can use pci bridge methods, too - the
+ * generic routines only need the dev, secbus and subbus members
+ * filled.
+ */
+ struct pcib_softc ops_pcib_sc;
+#ifdef OFW_NEWPCI
+ phandle_t ops_node;
+ struct ofw_bus_iinfo ops_iinfo;
+#endif
+};
+
+void ofw_pcib_gen_setup(device_t);
+pcib_route_interrupt_t ofw_pcib_gen_route_interrupt;
+ofw_pci_get_node_t ofw_pcib_gen_get_node;
+ofw_pci_adjust_busrange_t ofw_pcib_gen_adjust_busrange;
+
+#endif /* !_SPARC64_PCI_OFW_PCI_SUBR_H */
diff --git a/sys/sparc64/pci/ofw_pcibus.c b/sys/sparc64/pci/ofw_pcibus.c
new file mode 100644
index 0000000..597b656
--- /dev/null
+++ b/sys/sparc64/pci/ofw_pcibus.c
@@ -0,0 +1,264 @@
+/*-
+ * Copyright (c) 1997, Stefan Esser <se@freebsd.org>
+ * Copyright (c) 2000, Michael Smith <msmith@freebsd.org>
+ * Copyright (c) 2000, BSDi
+ * Copyright (c) 2003, Thomas Moestl <tmm@FreeBSD.org>
+ * All rights reserved.
+ *
+ * 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 unmodified, 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 AUTHOR ``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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#include "opt_ofw_pci.h"
+#include <sys/param.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/libkern.h>
+#include <sys/module.h>
+#include <sys/pciio.h>
+
+#include <dev/ofw/openfirm.h>
+#include <dev/ofw/ofw_pci.h>
+
+#include <machine/bus.h>
+#include <machine/bus_common.h>
+#include <machine/cache.h>
+#include <machine/iommureg.h>
+#include <machine/resource.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pci_private.h>
+
+#include <sparc64/pci/ofw_pci.h>
+
+#include "pcib_if.h"
+#include "pci_if.h"
+
+/* Helper functions. */
+static void ofw_pcibus_setup_device(device_t, u_int, u_int, u_int);
+
+/* Methods. */
+static device_probe_t ofw_pcibus_probe;
+static device_attach_t ofw_pcibus_attach;
+static pci_assign_interrupt_t ofw_pcibus_assign_interrupt;
+static ofw_pci_get_node_t ofw_pcibus_get_node;
+
+static device_method_t ofw_pcibus_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ofw_pcibus_probe),
+ DEVMETHOD(device_attach, ofw_pcibus_attach),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_print_child, pci_print_child),
+ DEVMETHOD(bus_probe_nomatch, pci_probe_nomatch),
+ DEVMETHOD(bus_read_ivar, pci_read_ivar),
+ DEVMETHOD(bus_write_ivar, pci_write_ivar),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+ DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
+ DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
+
+ DEVMETHOD(bus_get_resource_list, pci_get_resource_list),
+ DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
+ DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_delete_resource, pci_delete_resource),
+ DEVMETHOD(bus_alloc_resource, pci_alloc_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_child_pnpinfo_str, pci_child_pnpinfo_str_method),
+ DEVMETHOD(bus_child_location_str, pci_child_location_str_method),
+
+ /* PCI interface */
+ DEVMETHOD(pci_read_config, pci_read_config_method),
+ DEVMETHOD(pci_write_config, pci_write_config_method),
+ DEVMETHOD(pci_enable_busmaster, pci_enable_busmaster_method),
+ DEVMETHOD(pci_disable_busmaster, pci_disable_busmaster_method),
+ DEVMETHOD(pci_enable_io, pci_enable_io_method),
+ DEVMETHOD(pci_disable_io, pci_disable_io_method),
+ DEVMETHOD(pci_get_powerstate, pci_get_powerstate_method),
+ DEVMETHOD(pci_set_powerstate, pci_set_powerstate_method),
+ DEVMETHOD(pci_assign_interrupt, ofw_pcibus_assign_interrupt),
+
+ /* OFW PCI interface */
+ DEVMETHOD(ofw_pci_get_node, ofw_pcibus_get_node),
+
+ { 0, 0 }
+};
+
+struct ofw_pcibus_devinfo {
+ struct pci_devinfo opd_dinfo;
+ phandle_t opd_node;
+};
+
+struct ofw_pcibus_softc {
+ phandle_t ops_node;
+};
+
+static driver_t ofw_pcibus_driver = {
+ "pci",
+ ofw_pcibus_methods,
+ sizeof(struct ofw_pcibus_softc),
+};
+
+DRIVER_MODULE(ofw_pcibus, pcib, ofw_pcibus_driver, pci_devclass, 0, 0);
+MODULE_VERSION(ofw_pcibus, 1);
+MODULE_DEPEND(ofw_pcibus, pci, 1, 1, 1);
+
+static int
+ofw_pcibus_probe(device_t dev)
+{
+
+ if (ofw_pci_get_node(dev) == 0)
+ return (ENXIO);
+ device_set_desc(dev, "OFW PCI bus");
+
+ return (0);
+}
+
+/*
+ * Perform miscellaneous setups the firmware usually does not do for us.
+ */
+static void
+ofw_pcibus_setup_device(device_t bridge, u_int busno, u_int slot, u_int func)
+{
+ u_int lat, clnsz;
+
+ /*
+ * Initialize the latency timer register for busmaster devices to work
+ * properly. This is another task which the firmware does not always
+ * perform. The Min_Gnt register can be used to compute it's recommended
+ * value: it contains the desired latency in units of 1/4 us. To
+ * calculate the correct latency timer value, a bus clock of 33MHz and
+ * no wait states should be assumed.
+ */
+ lat = PCIB_READ_CONFIG(bridge, busno, slot, func, PCIR_MINGNT, 1) *
+ 33 / 4;
+ if (lat != 0) {
+#ifdef OFW_PCI_DEBUG
+ device_printf(bridge, "device %d/%d/%d: latency timer %d -> "
+ "%d\n", busno, slot, func,
+ PCIB_READ_CONFIG(bridge, busno, slot, func,
+ PCIR_LATTIMER, 1), lat);
+#endif /* OFW_PCI_DEBUG */
+ PCIB_WRITE_CONFIG(bridge, busno, slot, func,
+ PCIR_LATTIMER, imin(lat, 255), 1);
+ }
+
+ /*
+ * Compute a value to write into the cache line size register.
+ * The role of the streaming cache is unclear in write invalidate
+ * transfers, so it is made sure that it's line size is always reached.
+ */
+ clnsz = imax(cache.ec_linesize, STRBUF_LINESZ);
+ KASSERT((clnsz / STRBUF_LINESZ) * STRBUF_LINESZ == clnsz &&
+ (clnsz / cache.ec_linesize) * cache.ec_linesize == clnsz &&
+ (clnsz / 4) * 4 == clnsz, ("bogus cache line size %d", clnsz));
+ PCIB_WRITE_CONFIG(bridge, busno, slot, func, PCIR_CACHELNSZ,
+ clnsz / 4, 1);
+
+ /*
+ * The preset in the intline register is usually wrong. Reset it to 255,
+ * so that the PCI code will reroute the interrupt if needed.
+ */
+ PCIB_WRITE_CONFIG(bridge, busno, slot, func, PCIR_INTLINE,
+ PCI_INVALID_IRQ, 1);
+}
+
+static int
+ofw_pcibus_attach(device_t dev)
+{
+ device_t pcib = device_get_parent(dev);
+ struct ofw_pci_register pcir;
+ struct ofw_pcibus_devinfo *dinfo;
+ phandle_t node, child;
+ u_int slot, busno, func;
+
+ /*
+ * Ask the bridge for the bus number - in some cases, we need to
+ * renumber buses, so the firmware information cannot be trusted.
+ */
+ busno = pcib_get_bus(dev);
+ if (bootverbose)
+ device_printf(dev, "physical bus=%d\n", busno);
+
+ node = ofw_pci_get_node(dev);
+ for (child = OF_child(node); child != 0; child = OF_peer(child)) {
+ if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1)
+ panic("ofw_pci_attach: OF_getprop failed");
+ slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi);
+ func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi);
+ ofw_pcibus_setup_device(pcib, busno, slot, func);
+ dinfo = (struct ofw_pcibus_devinfo *)pci_read_device(pcib,
+ busno, slot, func, sizeof(*dinfo));
+ if (dinfo != NULL) {
+ dinfo->opd_node = child;
+ pci_add_child(dev, (struct pci_devinfo *)dinfo);
+ }
+ }
+
+ return (bus_generic_attach(dev));
+}
+
+static int
+ofw_pcibus_assign_interrupt(device_t dev, device_t child)
+{
+ struct ofw_pcibus_devinfo *dinfo = device_get_ivars(child);
+ pcicfgregs *cfg = &dinfo->opd_dinfo.cfg;
+ phandle_t node = ofw_pci_get_node(child);
+ ofw_pci_intr_t intr;
+ int isz;
+
+ isz = OF_getprop(node, "interrupts", &intr, sizeof(intr));
+ if (isz != sizeof(intr)) {
+ /* No property; our best guess is the intpin. */
+ intr = cfg->intpin;
+ } else if (intr >= 255) {
+ /*
+ * A fully specified interrupt (including IGN), as present on
+ * SPARCengine Ultra AX and e450. Extract the INO and return it.
+ */
+ return (INTINO(intr));
+ }
+ /*
+ * If we got intr from a property, it may or may not be an intpin.
+ * For on-board devices, it frequently is not, and is completely out
+ * of the valid intpin range. For PCI slots, it hopefully is, otherwise
+ * we will have trouble interfacing with non-OFW buses such as cardbus.
+ * Since we cannot tell which it is without violating layering, we
+ * will always use the route_interrupt method, and treat exceptions on
+ * the level they become apparent.
+ */
+ return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr));
+}
+
+static phandle_t
+ofw_pcibus_get_node(device_t bus, device_t dev)
+{
+ struct ofw_pcibus_devinfo *dinfo = device_get_ivars(dev);
+
+ return (dinfo->opd_node);
+}
diff --git a/sys/sparc64/pci/psycho.c b/sys/sparc64/pci/psycho.c
index 4d5a3a3..a1d7fee 100644
--- a/sys/sparc64/pci/psycho.c
+++ b/sys/sparc64/pci/psycho.c
@@ -1,7 +1,7 @@
/*
* Copyright (c) 1999, 2000 Matthew R. Green
+ * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>
* All rights reserved.
- * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -36,6 +36,7 @@
* UltraSPARC IIi and IIe `sabre' PCI controllers.
*/
+#include "opt_ofw_pci.h"
#include "opt_psycho.h"
#include <sys/param.h>
@@ -55,6 +56,7 @@
#include <machine/frame.h>
#include <machine/intr_machdep.h>
#include <machine/nexusvar.h>
+#include <machine/ofw_bus.h>
#include <machine/ofw_upa.h>
#include <machine/resource.h>
#include <machine/cpu.h>
@@ -71,7 +73,6 @@
#include <sparc64/pci/psychovar.h>
#include "pcib_if.h"
-#include "sparcbus_if.h"
static void psycho_get_ranges(phandle_t, struct upa_ranges **, int *);
static void psycho_set_intr(struct psycho_softc *, int, device_t, bus_addr_t,
@@ -80,7 +81,9 @@ static int psycho_find_intrmap(struct psycho_softc *, int, bus_addr_t *,
bus_addr_t *, u_long *);
static void psycho_intr_stub(void *);
static bus_space_tag_t psycho_alloc_bus_tag(struct psycho_softc *, int);
-
+#ifndef OFW_NEWPCI
+static ofw_pci_binit_t psycho_binit;
+#endif
/* Interrupt handlers */
static void psycho_ue(void *);
@@ -94,34 +97,32 @@ static void psycho_wakeup(void *);
/* IOMMU support */
static void psycho_iommu_init(struct psycho_softc *, int);
-static ofw_pci_binit_t psycho_binit;
/*
- * autoconfiguration
+ * Methods.
*/
-static int psycho_probe(device_t);
-static int psycho_attach(device_t);
-static int psycho_read_ivar(device_t, device_t, int, u_long *);
-static int psycho_setup_intr(device_t, device_t, struct resource *, int,
- driver_intr_t *, void *, void **);
-static int psycho_teardown_intr(device_t, device_t, struct resource *, void *);
-static struct resource *psycho_alloc_resource(device_t, device_t, int, int *,
- u_long, u_long, u_long, u_int);
-static int psycho_activate_resource(device_t, device_t, int, int,
- struct resource *);
-static int psycho_deactivate_resource(device_t, device_t, int, int,
- struct resource *);
-static int psycho_release_resource(device_t, device_t, int, int,
- struct resource *);
-static int psycho_maxslots(device_t);
-static u_int32_t psycho_read_config(device_t, u_int, u_int, u_int, u_int, int);
-static void psycho_write_config(device_t, u_int, u_int, u_int, u_int, u_int32_t,
- int);
-static int psycho_route_interrupt(device_t, device_t, int);
-static int psycho_intr_pending(device_t, int);
-static u_int32_t psycho_guess_ino(device_t, phandle_t, u_int, u_int);
-static bus_space_handle_t psycho_get_bus_handle(device_t dev, enum sbbt_id id,
- bus_space_handle_t childhdl, bus_space_tag_t *tag);
+static device_probe_t psycho_probe;
+static device_attach_t psycho_attach;
+static bus_read_ivar_t psycho_read_ivar;
+static bus_setup_intr_t psycho_setup_intr;
+static bus_teardown_intr_t psycho_teardown_intr;
+static bus_alloc_resource_t psycho_alloc_resource;
+static bus_activate_resource_t psycho_activate_resource;
+static bus_deactivate_resource_t psycho_deactivate_resource;
+static bus_release_resource_t psycho_release_resource;
+static pcib_maxslots_t psycho_maxslots;
+static pcib_read_config_t psycho_read_config;
+static pcib_write_config_t psycho_write_config;
+static pcib_route_interrupt_t psycho_route_interrupt;
+static ofw_pci_intr_pending_t psycho_intr_pending;
+#ifndef OFW_NEWPCI
+static ofw_pci_guess_ino_t psycho_guess_ino;
+#endif
+static ofw_pci_get_bus_handle_t psycho_get_bus_handle;
+#ifdef OFW_NEWPCI
+static ofw_pci_get_node_t psycho_get_node;
+static ofw_pci_adjust_busrange_t psycho_adjust_busrange;
+#endif
static device_method_t psycho_methods[] = {
/* Device interface */
@@ -144,10 +145,16 @@ static device_method_t psycho_methods[] = {
DEVMETHOD(pcib_write_config, psycho_write_config),
DEVMETHOD(pcib_route_interrupt, psycho_route_interrupt),
- /* sparcbus interface */
- DEVMETHOD(sparcbus_intr_pending, psycho_intr_pending),
- DEVMETHOD(sparcbus_guess_ino, psycho_guess_ino),
- DEVMETHOD(sparcbus_get_bus_handle, psycho_get_bus_handle),
+ /* ofw_pci interface */
+ DEVMETHOD(ofw_pci_intr_pending, psycho_intr_pending),
+#ifndef OFW_NEWPCI
+ DEVMETHOD(ofw_pci_guess_ino, psycho_guess_ino),
+#endif
+ DEVMETHOD(ofw_pci_get_bus_handle, psycho_get_bus_handle),
+#ifdef OFW_NEWPCI
+ DEVMETHOD(ofw_pci_get_node, psycho_get_node),
+ DEVMETHOD(ofw_pci_adjust_busrange, psycho_adjust_busrange),
+#endif
{ 0, 0 }
};
@@ -314,7 +321,9 @@ psycho_attach(device_t dev)
struct psycho_softc *osc = NULL;
struct psycho_softc *asc;
struct upa_regs *reg;
+#ifndef OFW_NEWPCI
struct ofw_pci_bdesc obd;
+#endif
struct psycho_desc *desc;
phandle_t node;
u_int64_t csr;
@@ -587,17 +596,30 @@ psycho_attach(device_t dev)
if (n != sizeof(psycho_br))
panic("broken psycho bus-range (%d)", n);
- sc->sc_busno = ofw_pci_alloc_busno(sc->sc_node);
- obd.obd_bus = psycho_br[0];
- obd.obd_secbus = obd.obd_subbus = sc->sc_busno;
+ sc->sc_secbus = sc->sc_subbus = ofw_pci_alloc_busno(sc->sc_node);
+ /*
+ * Program the bus range registers.
+ * NOTE: the psycho, the second write changes the bus number the
+ * psycho itself uses for it's configuration space, so these
+ * writes must be kept in this order!
+ * The sabre always uses bus 0, but there only can be one sabre per
+ * machine.
+ */
+ PCIB_WRITE_CONFIG(dev, psycho_br[0], PCS_DEVICE, PCS_FUNC, PCSR_SUBBUS,
+ sc->sc_subbus, 1);
+ PCIB_WRITE_CONFIG(dev, psycho_br[0], PCS_DEVICE, PCS_FUNC, PCSR_SECBUS,
+ sc->sc_secbus, 1);
+
+#ifdef OFW_NEWPCI
+ ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_pci_intr_t));
+#else
+ obd.obd_bus = obd.obd_secbus = sc->sc_secbus;
+ obd.obd_subbus = sc->sc_subbus;
obd.obd_slot = PCS_DEVICE;
obd.obd_func = PCS_FUNC;
obd.obd_init = psycho_binit;
obd.obd_super = NULL;
- /* Initial setup. */
- psycho_binit(dev, &obd);
- /* Update the bus number to what was just programmed. */
- obd.obd_bus = obd.obd_secbus;
+
/*
* Initialize the interrupt registers of all devices hanging from
* the host bridge directly or indirectly via PCI-PCI bridges.
@@ -608,8 +630,9 @@ psycho_attach(device_t dev)
* Additionally, set up the bus numbers and ranges.
*/
ofw_pci_init(dev, sc->sc_node, sc->sc_ign, &obd);
+#endif /* OFW_NEWPCI */
- device_add_child(dev, "pci", device_get_unit(dev));
+ device_add_child(dev, "pci", sc->sc_secbus);
return (bus_generic_attach(dev));
}
@@ -726,8 +749,8 @@ psycho_ce(void *arg)
afar = PSYCHO_READ8(sc, PSR_CE_AFA);
afsr = PSYCHO_READ8(sc, PSR_CE_AFS);
/* It's correctable. Dump the regs and continue. */
- printf("%s: correctable DMA error AFAR %#lx AFSR %#lx\n",
- device_get_name(sc->sc_dev), (u_long)afar, (u_long)afsr);
+ device_printf(sc->sc_dev, "correctable DMA error AFAR %#lx "
+ "AFSR %#lx\n", (u_long)afar, (u_long)afsr);
}
static void
@@ -780,7 +803,7 @@ psycho_wakeup(void *arg)
PSYCHO_WRITE8(sc, PSR_PWRMGT_INT_CLR, 0);
/* Gee, we don't really have a framework to deal with this properly. */
- printf("%s: power management wakeup\n", device_get_name(sc->sc_dev));
+ device_printf(sc->sc_dev, "power management wakeup\n");
}
#endif /* PSYCHO_MAP_WAKEUP */
@@ -810,6 +833,7 @@ psycho_iommu_init(struct psycho_softc *sc, int tsbsize)
iommu_init(name, is, tsbsize, sc->sc_dvmabase, 0);
}
+#ifndef OFW_NEWPCI
static void
psycho_binit(device_t busdev, struct ofw_pci_bdesc *obd)
{
@@ -819,28 +843,20 @@ psycho_binit(device_t busdev, struct ofw_pci_bdesc *obd)
obd->obd_bus, obd->obd_slot, obd->obd_func, obd->obd_bus,
obd->obd_secbus, obd->obd_subbus);
#endif /* PSYCHO_DEBUG */
- /*
- * NOTE: this must be kept in this order, since the last write will
- * change the config space address of the psycho.
- */
PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
PCSR_SUBBUS, obd->obd_subbus, 1);
- PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
- PCSR_SECBUS, obd->obd_secbus, 1);
}
+#endif
static int
psycho_maxslots(device_t dev)
{
- /*
- * XXX: is this correct? At any rate, a number that is too high
- * shouldn't do any harm, if only because of the way things are
- * handled in psycho_read_config.
- */
- return (31);
+ /* XXX: is this correct? */
+ return (PCI_SLOTMAX);
}
+#ifndef OFW_NEWPCI
/*
* Keep a table of quirky PCI devices that need fixups before the MI PCI code
* creates the resource lists. This needs to be moved around once other bus
@@ -862,6 +878,7 @@ static struct psycho_dquirk dquirks[] = {
{ 0x1102108e, DQT_BAD_INTPIN }, /* Sun FireWire ctl. (PCIO2 func. 2) */
{ 0x1103108e, DQT_BAD_INTPIN }, /* Sun USB ctl. (PCIO2 func. 3) */
};
+#endif /* !OFW_NEWPCI */
#define NDQUIRKS (sizeof(dquirks) / sizeof(dquirks[0]))
@@ -872,10 +889,13 @@ psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
struct psycho_softc *sc;
bus_space_handle_t bh;
u_long offset = 0;
- u_int32_t r, devid;
+#ifndef OFW_NEWPCI
+ u_int32_t devid;
+#endif
u_int8_t byte;
u_int16_t shrt;
u_int32_t wrd;
+ u_int32_t r;
int i;
sc = (struct psycho_softc *)device_get_softc(dev);
@@ -906,6 +926,7 @@ psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
r = -1;
}
+#ifndef OFW_NEWPCI
if (reg == PCIR_INTPIN && r == 0) {
/* Check for DQT_BAD_INTPIN quirk. */
devid = psycho_read_config(dev, bus, slot, func,
@@ -927,6 +948,7 @@ psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
}
}
}
+#endif /* !OFW_NEWPCI */
return (r);
}
@@ -957,9 +979,44 @@ psycho_write_config(device_t dev, u_int bus, u_int slot, u_int func,
}
static int
-psycho_route_interrupt(device_t bus, device_t dev, int pin)
+psycho_route_interrupt(device_t bridge, device_t dev, int pin)
{
-
+#ifdef OFW_NEWPCI
+ struct psycho_softc *sc = device_get_softc(bridge);
+ struct ofw_pci_register reg;
+ bus_addr_t intrmap;
+ phandle_t node = ofw_pci_get_node(dev);
+ ofw_pci_intr_t pintr, mintr;
+ u_int8_t maskbuf[sizeof(reg) + sizeof(pintr)];
+
+ pintr = pin;
+ if (ofw_bus_lookup_imap(node, &sc->sc_iinfo, &reg, sizeof(reg),
+ &pintr, sizeof(pintr), &mintr, sizeof(mintr), maskbuf))
+ return (mintr);
+ /*
+ * If this is outside of the range for an intpin, it's likely a full
+ * INO, and no mapping is required at all; this happens on the u30,
+ * where there's no interrupt map at the psycho node. Fortunately,
+ * there seem to be no INOs in the intpin range on this boxen, so
+ * this easy heuristics will do.
+ */
+ if (pin > 4)
+ return (pin);
+ /*
+ * Guess the INO; we always assume that this is a non-OBIO
+ * device, and that pin is a "real" intpin number. Determine
+ * the mapping register to be used by the slot number.
+ * We only need to do this on e450s, it seems; here, the slot numbers
+ * for bus A are one-based, while those for bus B seemingly have an
+ * offset of 2 (hence the factor of 3 below).
+ */
+ intrmap = PSR_PCIA0_INT_MAP +
+ 8 * (pci_get_slot(dev) - 1 + 3 * sc->sc_half);
+ mintr = INTINO(PSYCHO_READ8(sc, intrmap)) + pin - 1;
+ device_printf(bridge, "guessing interrupt %d for device %d/%d pin %d\n",
+ (int)mintr, pci_get_slot(dev), pci_get_function(dev), pin);
+ return (mintr);
+#else
/*
* XXX: ugly loathsome hack:
* We can't use ofw_pci_route_intr() here; the device passed may be
@@ -976,6 +1033,7 @@ psycho_route_interrupt(device_t bus, device_t dev, int pin)
* which case we are lost.
*/
return (0);
+#endif /* OFW_NEWPCI */
}
static int
@@ -986,7 +1044,7 @@ psycho_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
sc = (struct psycho_softc *)device_get_softc(dev);
switch (which) {
case PCIB_IVAR_BUS:
- *result = sc->sc_busno;
+ *result = sc->sc_secbus;
return (0);
}
return (ENOENT);
@@ -1032,7 +1090,7 @@ psycho_setup_intr(device_t dev, device_t child,
ino = INTINO(vec);
if (!psycho_find_intrmap(sc, ino, &intrmapptr, &intrclrptr, NULL)) {
- printf("Cannot find interrupt vector %lx\n", vec);
+ device_printf(dev, "Cannot find interrupt vector %lx\n", vec);
free(pc, M_DEVBUF);
return (NULL);
}
@@ -1204,20 +1262,22 @@ psycho_release_resource(device_t bus, device_t child, int type, int rid,
}
static int
-psycho_intr_pending(device_t dev, int intr)
+psycho_intr_pending(device_t dev, ofw_pci_intr_t intr)
{
struct psycho_softc *sc;
u_long diag;
sc = (struct psycho_softc *)device_get_softc(dev);
if (!psycho_find_intrmap(sc, intr, NULL, NULL, &diag)) {
- printf("psycho_intr_pending: mapping not found for %d\n", intr);
+ device_printf(dev, "psycho_intr_pending: mapping not found for"
+ " %d\n", intr);
return (0);
}
return (diag != 0);
}
-static u_int32_t
+#ifndef OFW_NEWPCI
+static ofw_pci_intr_t
psycho_guess_ino(device_t dev, phandle_t node, u_int slot, u_int pin)
{
struct psycho_softc *sc = (struct psycho_softc *)device_get_softc(dev);
@@ -1230,7 +1290,7 @@ psycho_guess_ino(device_t dev, phandle_t node, u_int slot, u_int pin)
* the INO.
*/
if (node != sc->sc_node)
- return (255);
+ return (PCI_INVALID_IRQ);
/*
* Actually guess the INO. We always assume that this is a non-OBIO
* device, and use from the slot number to determine it.
@@ -1241,19 +1301,20 @@ psycho_guess_ino(device_t dev, phandle_t node, u_int slot, u_int pin)
intrmap = PSR_PCIA0_INT_MAP + 8 * (slot - 1 + 3 * sc->sc_half);
return (INTINO(PSYCHO_READ8(sc, intrmap)) + pin - 1);
}
+#endif /* !OFW_NEWPCI */
static bus_space_handle_t
-psycho_get_bus_handle(device_t dev, enum sbbt_id id,
- bus_space_handle_t childhdl, bus_space_tag_t *tag)
+psycho_get_bus_handle(device_t dev, int type, bus_space_handle_t childhdl,
+ bus_space_tag_t *tag)
{
struct psycho_softc *sc;
sc = (struct psycho_softc *)device_get_softc(dev);
- switch(id) {
- case SBBT_IO:
+ switch (type) {
+ case SYS_RES_IOPORT:
*tag = sc->sc_iot;
return (sc->sc_bh[PCI_CS_IO] + childhdl);
- case SBBT_MEM:
+ case SYS_RES_MEMORY:
*tag = sc->sc_memt;
return (sc->sc_bh[PCI_CS_MEM32] + childhdl);
default:
@@ -1261,6 +1322,35 @@ psycho_get_bus_handle(device_t dev, enum sbbt_id id,
}
}
+#ifdef OFW_NEWPCI
+static phandle_t
+psycho_get_node(device_t bus, device_t dev)
+{
+ struct psycho_softc *sc = device_get_softc(bus);
+
+ /* We only have one child, the PCI bus, which needs our own node. */
+ return (sc->sc_node);
+}
+
+static void
+psycho_adjust_busrange(device_t dev, u_int subbus)
+{
+ struct psycho_softc *sc = device_get_softc(dev);
+
+ /* If necessary, adjust the subordinate bus number register. */
+ if (subbus > sc->sc_subbus) {
+#ifdef PSYCHO_DEBUG
+ device_printf(dev,
+ "adjusting secondary bus number from %d to %d\n",
+ sc->sc_subbus, subbus);
+#endif
+ sc->sc_subbus = subbus;
+ PCIB_WRITE_CONFIG(dev, sc->sc_secbus, PCS_DEVICE, PCS_FUNC,
+ PCSR_SUBBUS, subbus, 1);
+ }
+}
+#endif
+
/*
* below here is bus space and bus dma support
*/
diff --git a/sys/sparc64/pci/psychovar.h b/sys/sparc64/pci/psychovar.h
index 2a77b15..584d8a4 100644
--- a/sys/sparc64/pci/psychovar.h
+++ b/sys/sparc64/pci/psychovar.h
@@ -71,6 +71,10 @@ struct psycho_softc {
struct resource *sc_irq_res[6];
void *sc_ihand[6];
+#ifdef OFW_NEWPCI
+ struct ofw_bus_iinfo sc_iinfo;
+#endif
+
/*
* note that the sabre really only has one ranges property,
* used for both simba a and simba b (but the ranges for
@@ -87,7 +91,8 @@ struct psycho_softc {
bus_space_handle_t sc_bh[4];
- int sc_busno;
+ u_int sc_secbus;
+ u_int sc_subbus;
struct rman sc_mem_rman;
struct rman sc_io_rman;
diff --git a/sys/sparc64/sparc64/ofw_bus.c b/sys/sparc64/sparc64/ofw_bus.c
index 6d8e242..359da41 100644
--- a/sys/sparc64/sparc64/ofw_bus.c
+++ b/sys/sparc64/sparc64/ofw_bus.c
@@ -29,7 +29,7 @@
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*-
- * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>.
+ * Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -64,6 +64,8 @@
* bits left.
*/
+#include "opt_ofw_pci.h"
+
#include <sys/param.h>
#include <sys/malloc.h>
#include <sys/systm.h>
@@ -72,12 +74,6 @@
#include <machine/ofw_bus.h>
-/*
- * Other than in OpenFirmware calls, the size of a bus cell seems to be always
- * the same.
- */
-typedef u_int32_t pcell_t;
-
static int
ofw_bus_searchprop(phandle_t node, char *propname, void *buf, int buflen)
{
@@ -90,7 +86,122 @@ ofw_bus_searchprop(phandle_t node, char *propname, void *buf, int buflen)
return (-1);
}
+#ifdef OFW_NEWPCI
+
+void
+ofw_bus_setup_iinfo(phandle_t node, struct ofw_bus_iinfo *ii, int intrsz)
+{
+ pcell_t addrc;
+ int msksz;
+
+ if (OF_getprop(node, "#address-cells", &addrc, sizeof(addrc)) == -1)
+ addrc = 2;
+ ii->opi_addrc = addrc * sizeof(pcell_t);
+
+ ii->opi_imapsz = OF_getprop_alloc(node, "interrupt-map", 1,
+ (void **)&ii->opi_imap);
+ if (ii->opi_imapsz > 0) {
+ msksz = OF_getprop_alloc(node, "interrupt-map-mask", 1,
+ (void **)&ii->opi_imapmsk);
+ /*
+ * Failure to get the mask is ignored; a full mask is used then.
+ * Barf on bad mask sizes, however.
+ */
+ if (msksz != -1 && msksz != ii->opi_addrc + intrsz) {
+ panic("ofw_bus_setup_iinfo: bad interrupt-map-mask "
+ "property!");
+ }
+ }
+
+}
+
+int
+ofw_bus_lookup_imap(phandle_t node, struct ofw_bus_iinfo *ii, void *reg,
+ int regsz, void *pintr, int pintrsz, void *mintr, int mintrsz,
+ void *maskbuf)
+{
+ int rv;
+
+ if (ii->opi_imapsz <= 0)
+ return (0);
+ KASSERT(regsz >= ii->opi_addrc,
+ ("ofw_bus_lookup_imap: register size too small: %d < %d",
+ regsz, ii->opi_addrc));
+ rv = OF_getprop(node, "reg", reg, regsz);
+ if (rv < regsz)
+ panic("ofw_bus_lookup_imap: could not get reg property");
+ return (ofw_bus_search_intrmap(pintr, pintrsz, reg, ii->opi_addrc,
+ ii->opi_imap, ii->opi_imapsz, ii->opi_imapmsk, maskbuf, mintr,
+ mintrsz));
+}
+
+/*
+ * Map an interrupt using the firmware reg, interrupt-map and
+ * interrupt-map-mask properties.
+ * The interrupt property to be mapped must be of size intrsz, and pointed to
+ * by intr. The regs property of the node for which the mapping is done must
+ * be passed as regs. This property is an array of register specifications;
+ * the size of the address part of such a specification must be passed as
+ * physsz. Only the first element of the property is used.
+ * imap and imapsz hold the interrupt mask and it's size.
+ * imapmsk is a pointer to the interrupt-map-mask property, which must have
+ * a size of physsz + intrsz; it may be NULL, in which case a full mask is
+ * assumed.
+ * maskbuf must point to a buffer of length physsz + intrsz.
+ * The interrupt is returned in result, which must point to a buffer of length
+ * rintrsz (which gives the expected size of the mapped interrupt).
+ * Returns 1 if a mapping was found, 0 otherwise.
+ */
+int
+ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz,
+ void *imap, int imapsz, void *imapmsk, void *maskbuf, void *result,
+ int rintrsz)
+{
+ phandle_t parent;
+ u_int8_t *ref = maskbuf;
+ u_int8_t *uiintr = intr;
+ u_int8_t *uiregs = regs;
+ u_int8_t *uiimapmsk = imapmsk;
+ u_int8_t *mptr;
+ pcell_t pintrsz;
+ int i, rsz, tsz;
+
+ rsz = -1;
+ if (imapmsk != NULL) {
+ for (i = 0; i < physsz; i++)
+ ref[i] = uiregs[i] & uiimapmsk[i];
+ for (i = 0; i < intrsz; i++)
+ ref[physsz + i] = uiintr[i] & uiimapmsk[physsz + i];
+ } else {
+ bcopy(regs, ref, physsz);
+ bcopy(intr, ref + physsz, intrsz);
+ }
+
+ mptr = imap;
+ i = imapsz;
+ tsz = physsz + intrsz + sizeof(phandle_t) + rintrsz;
+ while (i > 0) {
+ KASSERT(i >= tsz, ("ofw_bus_find_intr: truncated map"));
+ bcopy(mptr + physsz + intrsz, &parent, sizeof(parent));
+ if (ofw_bus_searchprop(parent, "#interrupt-cells",
+ &pintrsz, sizeof(pintrsz)) == -1)
+ pintrsz = 1; /* default */
+ pintrsz *= sizeof(pcell_t);
+ if (pintrsz != rintrsz)
+ panic("ofw_bus_search_intrmap: expected interrupt cell "
+ "size incorrect: %d != %d", rintrsz, pintrsz);
+ if (bcmp(ref, mptr, physsz + intrsz) == 0) {
+ bcopy(mptr + physsz + intrsz + sizeof(parent),
+ result, rintrsz);
+ return (1);
+ }
+ mptr += tsz;
+ i -= tsz;
+ }
+ return (0);
+}
+#else
/*
* Map an interrupt using the firmware reg, interrupt-map and
* interrupt-map-mask properties.
@@ -253,3 +364,4 @@ ofw_bus_route_intr(phandle_t node, int intrp, obr_callback_t *cb, void *cookie)
free(intr, M_OFWPROP);
return (rv);
}
+#endif /* OFW_NEWPCI */
diff --git a/sys/sparc64/sparc64/sparcbus_if.m b/sys/sparc64/sparc64/sparcbus_if.m
deleted file mode 100644
index fe7826e..0000000
--- a/sys/sparc64/sparc64/sparcbus_if.m
+++ /dev/null
@@ -1,93 +0,0 @@
-# Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>.
-# All rights reserved.
-#
-# 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 AUTHOR ``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 AUTHOR 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.
-#
-# $FreeBSD$
-
-#include <sys/bus.h>
-#include <machine/bus.h>
-
-#include <dev/ofw/openfirm.h>
-
-INTERFACE sparcbus;
-
-HEADER {
- /* Bus tag types for the get_bustag method */
- enum sbbt_id {
- SBBT_IO,
- SBBT_MEM,
- };
-};
-
-CODE {
- static int
- sparcbus_default_intr_pending(device_t dev, int intr)
- {
-
- return (SPARCBUS_INTR_PENDING(device_get_parent(dev), intr));
- }
-
- static u_int32_t
- sparcbus_default_guess_ino(device_t dev, phandle_t node, u_int slot,
- u_int pin)
- {
-
- return (SPARCBUS_GUESS_INO(device_get_parent(dev), node, slot,
- pin));
- }
-
- static bus_space_handle_t
- sparcbus_default_get_bus_handle(device_t dev, enum sbbt_id id,
- bus_space_handle_t childhdl, bus_space_tag_t *tag)
- {
-
- return (SPARCBUS_GET_BUS_HANDLE(device_get_parent(dev), id,
- childhdl, tag));
- }
-};
-
-# Return whether an interrupt request is pending for the INO intr.
-METHOD int intr_pending {
- device_t dev;
- int intr;
-} DEFAULT sparcbus_default_intr_pending;
-
-# Let the bus driver guess the INO of the device at the given slot and intpin
-# on the bus described by the node if it could not be determined from the
-# firmware properties. Returns 255 if no INO could be found (mapping will
-# continue at the parent), or the desired INO.
-METHOD u_int32_t guess_ino {
- device_t dev;
- phandle_t node;
- u_int slot;
- u_int pin;
-} DEFAULT sparcbus_default_guess_ino;
-
-# Get the bustag for the root bus. This is needed for ISA old-stlye
-# in[bwl]()/out[bwl]() support, where no tag retrieved from a resource is
-# passed. The returned tag is used to construct a tag for the whole ISA bus.
-METHOD bus_space_handle_t get_bus_handle {
- device_t dev;
- enum sbbt_id id;
- bus_space_handle_t childhdl;
- bus_space_tag_t *tag;
-} DEFAULT sparcbus_default_get_bus_handle;
OpenPOWER on IntegriCloud