- Remove the old sparc64 OFW PCI code (as opposed to the former
"options OFW_NEWPCI"). This is a bit overdue, the new sparc64 OFW PCI code which is meant to replace the old one is in place for 10 months and enabled by default in GENERIC for 8 months. FreeBSD 5.2 and 5.2.1 also shipped with the new code enabled by default. - Some minor clean-up, e.g. remove functions that encapsulated the #ifdefs for OFW_NEWPCI, remove unused resp. no longer required includes, etc. Approved by: tmm, no objections on freebsd-sparc64
This commit is contained in:
parent
60f798c1c8
commit
66a79ac95d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=129051
@ -54,9 +54,9 @@ sparc64/isa/ofw_isa.c optional ebus
|
||||
sparc64/isa/ofw_isa.c optional isa
|
||||
sparc64/pci/apb.c optional pci
|
||||
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_pcib.c optional pci
|
||||
sparc64/pci/ofw_pcib_subr.c optional pci
|
||||
sparc64/pci/ofw_pcibus.c optional pci
|
||||
sparc64/pci/ofw_pci_if.m optional pci
|
||||
sparc64/pci/psycho.c optional pci
|
||||
sparc64/sbus/sbus.c optional sbus
|
||||
|
@ -9,7 +9,6 @@ GFB_NO_MODE_CHANGE opt_gfb.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
|
||||
# Debug IOMMU inserts/removes using diagnostic accesses. Very loud.
|
||||
IOMMU_DIAG opt_iommu.h
|
||||
PMAP_STATS opt_pmap.h
|
||||
|
@ -76,14 +76,6 @@ device sbus
|
||||
device central
|
||||
device fhc
|
||||
|
||||
# New OpenFirmware PCI framework. This fixes a number of interrupt-
|
||||
# routing problems and changes the device enumeration to be hopefully
|
||||
# closer to Solaris. Be aware that, because of the latter, enabling or
|
||||
# disabling this option may require reconfiguration, and can even
|
||||
# cause the machine to not boot without manual intervention before the
|
||||
# fstab is adjusted.
|
||||
options OFW_NEWPCI
|
||||
|
||||
# Floppy drives
|
||||
#device fdc
|
||||
|
||||
|
@ -31,14 +31,6 @@ device sbus
|
||||
device central
|
||||
device fhc
|
||||
|
||||
# New OpenFirmware PCI framework. This fixes a number of interrupt-
|
||||
# routing problems and changes the device enumeration to be hopefully
|
||||
# closer to Solaris. Be aware that, because of the latter, enabling or
|
||||
# disabling this option may require reconfiguration, and can even
|
||||
# cause the machine to not boot without manual intervention before the
|
||||
# fstab is adjusted.
|
||||
#options OFW_NEWPCI
|
||||
|
||||
|
||||
#####################################################################
|
||||
# HARDWARE DEVICE CONFIGURATION
|
||||
|
@ -46,8 +46,6 @@
|
||||
* 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>
|
||||
@ -59,7 +57,6 @@
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_pci.h>
|
||||
|
||||
#include <machine/ofw_bus.h>
|
||||
#include <machine/resource.h>
|
||||
@ -99,9 +96,7 @@ struct ebus_softc {
|
||||
int sc_nrange;
|
||||
int sc_nimap;
|
||||
|
||||
#ifdef OFW_NEWPCI
|
||||
struct ofw_bus_iinfo sc_iinfo;
|
||||
#endif
|
||||
};
|
||||
|
||||
static device_probe_t ebus_probe;
|
||||
@ -151,25 +146,13 @@ static devclass_t ebus_devclass;
|
||||
|
||||
DRIVER_MODULE(ebus, pci, ebus_driver, ebus_devclass, 0, 0);
|
||||
|
||||
static phandle_t
|
||||
ebus_get_busnode(device_t dev)
|
||||
{
|
||||
|
||||
#ifdef OFW_NEWPCI
|
||||
return (ofw_pci_get_node(dev));
|
||||
#else
|
||||
return (ofw_pci_find_node(pci_get_bus(dev), pci_get_slot(dev),
|
||||
pci_get_function(dev)));
|
||||
#endif
|
||||
}
|
||||
|
||||
static int
|
||||
ebus_probe(device_t dev)
|
||||
{
|
||||
char name[10];
|
||||
phandle_t node;
|
||||
|
||||
if ((node = ebus_get_busnode(dev)) == 0)
|
||||
if ((node = ofw_pci_get_node(dev)) == 0)
|
||||
return (ENXIO);
|
||||
|
||||
OF_getprop(node, "name", &name, sizeof(name));
|
||||
@ -200,7 +183,7 @@ ebus_attach(device_t dev)
|
||||
int i, rnum, rid;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->sc_node = node = ebus_get_busnode(dev);
|
||||
sc->sc_node = node = ofw_pci_get_node(dev);
|
||||
|
||||
sc->sc_nrange = OF_getprop_alloc(node, "ranges",
|
||||
sizeof(*sc->sc_range), (void **)&sc->sc_range);
|
||||
@ -239,9 +222,7 @@ ebus_attach(device_t dev)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OFW_NEWPCI
|
||||
ofw_bus_setup_iinfo(node, &sc->sc_iinfo, sizeof(ofw_isa_intr_t));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Now attach our children.
|
||||
@ -490,17 +471,10 @@ ebus_setup_dinfo(device_t dev, struct ebus_softc *sc, phandle_t node,
|
||||
nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intrs),
|
||||
(void **)&intrs);
|
||||
for (i = 0; i < nintr; i++) {
|
||||
#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 (rintr == ORIR_NOTFOUND) {
|
||||
#endif
|
||||
if (rintr == PCI_INVALID_IRQ)
|
||||
panic("ebus_setup_dinfo: could not map ebus "
|
||||
"interrupt %d", intrs[i]);
|
||||
}
|
||||
resource_list_add(&edi->edi_rl, SYS_RES_IRQ, i,
|
||||
rintr, rintr, 1);
|
||||
}
|
||||
|
@ -37,8 +37,6 @@
|
||||
*/
|
||||
typedef u_int32_t pcell_t;
|
||||
|
||||
#ifdef OFW_NEWPCI
|
||||
|
||||
struct ofw_bus_iinfo {
|
||||
u_int8_t *opi_imap;
|
||||
u_int8_t *opi_imapmsk;
|
||||
@ -52,13 +50,4 @@ int ofw_bus_lookup_imap(phandle_t, struct ofw_bus_iinfo *, void *, int,
|
||||
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_ */
|
||||
|
@ -29,33 +29,25 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "opt_ofw_pci.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <sys/rman.h>
|
||||
#include <sys/interrupt.h>
|
||||
|
||||
#include <isa/isareg.h>
|
||||
#include <isa/isavar.h>
|
||||
#include <isa/isa_common.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
#include <dev/ofw/ofw_pci.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/ofw_bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
#include <sparc64/pci/ofw_pci.h>
|
||||
#include <sparc64/isa/ofw_isa.h>
|
||||
|
||||
@ -65,19 +57,16 @@ bus_space_handle_t isa_io_hdl;
|
||||
bus_space_tag_t isa_mem_bt = NULL;
|
||||
bus_space_handle_t isa_mem_hdl;
|
||||
|
||||
u_int64_t isa_io_base;
|
||||
u_int64_t isa_io_limit;
|
||||
u_int64_t isa_mem_base;
|
||||
u_int64_t isa_mem_limit;
|
||||
static u_int64_t isa_io_base;
|
||||
static u_int64_t isa_io_limit;
|
||||
static u_int64_t isa_mem_base;
|
||||
static u_int64_t isa_mem_limit;
|
||||
|
||||
device_t isa_bus_device;
|
||||
|
||||
static phandle_t isab_node;
|
||||
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
|
||||
@ -117,26 +106,17 @@ isa_init(device_t dev)
|
||||
device_t bridge;
|
||||
phandle_t node;
|
||||
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 kludge; however, it is needed to provide
|
||||
@ -150,13 +130,8 @@ isa_init(device_t dev)
|
||||
continue;
|
||||
if (ino > 7)
|
||||
panic("isa_init: XXX: ino too large");
|
||||
#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--) {
|
||||
|
@ -35,14 +35,11 @@
|
||||
* 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>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_pci.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
@ -100,7 +97,6 @@ ofw_isa_range_map(struct isa_ranges *range, int nrange, u_long *start,
|
||||
*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)
|
||||
@ -122,4 +118,3 @@ ofw_isa_route_intr(device_t bridge, phandle_t node, struct ofw_bus_iinfo *ii,
|
||||
}
|
||||
return (mintr);
|
||||
}
|
||||
#endif /* OFW_NEWPCI */
|
||||
|
@ -64,27 +64,11 @@ struct isa_ranges {
|
||||
|
||||
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 */
|
||||
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 */
|
||||
ofw_isa_intr_t intr; /* interrupt */
|
||||
};
|
||||
|
||||
int ofw_isa_range_restype(struct isa_ranges *);
|
||||
/* Map an IO range. Returns the resource type of the range. */
|
||||
int ofw_isa_range_map(struct isa_ranges *, int, u_long *, u_long *, int *);
|
||||
|
||||
#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_ */
|
||||
|
@ -37,7 +37,7 @@
|
||||
* Support for the Sun APB (Advanced PCI Bridge) PCI-PCI bridge.
|
||||
* This bridge does not fully comply to the PCI bridge specification, and is
|
||||
* therefore not supported by the generic driver.
|
||||
* We can use some pf the pcib methods anyway.
|
||||
* We can use some of the pcib methods anyway.
|
||||
*/
|
||||
|
||||
#include "opt_ofw_pci.h"
|
||||
@ -45,11 +45,9 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.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>
|
||||
@ -76,9 +74,6 @@ struct apb_softc {
|
||||
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 */
|
||||
@ -103,17 +98,11 @@ static device_method_t apb_methods[] = {
|
||||
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 }
|
||||
};
|
||||
@ -190,13 +179,7 @@ apb_attach(device_t dev)
|
||||
*/
|
||||
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",
|
||||
@ -211,11 +194,6 @@ apb_attach(device_t dev)
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
#ifndef OFW_NEWPCI
|
||||
if (sc->sc_bsc.ops_pcib_sc.secbus == 0)
|
||||
panic("apb_attach: APB with uninitialized secbus");
|
||||
#endif
|
||||
|
||||
device_add_child(dev, "pci", sc->sc_bsc.ops_pcib_sc.secbus);
|
||||
return (bus_generic_attach(dev));
|
||||
}
|
||||
@ -233,8 +211,8 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
sc = device_get_softc(dev);
|
||||
/*
|
||||
* If this is a "default" allocation against this rid, we can't work
|
||||
* out where it's coming from (we should actually never see these) so we
|
||||
* just have to punt.
|
||||
* out where it's coming from (we should actually never see these) so
|
||||
* we just have to punt.
|
||||
*/
|
||||
if ((start == 0) && (end == ~0)) {
|
||||
device_printf(dev, "can't decode default resource id %d for "
|
||||
@ -291,31 +269,3 @@ apb_alloc_resource(device_t dev, device_t child, int type, int *rid,
|
||||
return (bus_generic_alloc_resource(dev, child, type, rid, start, end,
|
||||
count, flags));
|
||||
}
|
||||
|
||||
#ifndef OFW_NEWPCI
|
||||
/*
|
||||
* Route an interrupt across a PCI bridge - we need to rely on the firmware
|
||||
* here.
|
||||
*/
|
||||
static int
|
||||
apb_route_interrupt(device_t pcib, device_t dev, int pin)
|
||||
{
|
||||
|
||||
/*
|
||||
* XXX: ugly loathsome hack:
|
||||
* We can't use ofw_pci_route_intr() here; the device passed may be
|
||||
* the one of a bridge, so the original device can't be recovered.
|
||||
*
|
||||
* We need to use the firmware to route interrupts, however it has
|
||||
* no interface which could be used to interpret intpins; instead,
|
||||
* all assignments are done by device.
|
||||
*
|
||||
* The MI pci code will try to reroute interrupts of 0, although they
|
||||
* are correct; all other interrupts are preinitialized, so if we
|
||||
* get here, the intline is either 0 (so return 0), or we hit a
|
||||
* device which was not preinitialized (e.g. hotplugged stuff), in
|
||||
* which case we are lost.
|
||||
*/
|
||||
return (0);
|
||||
}
|
||||
#endif /* !OFW_NEWPCI */
|
||||
|
@ -38,138 +38,18 @@
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
#include <dev/ofw/ofw_pci.h>
|
||||
#include <dev/ofw/openfirm.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"
|
||||
|
||||
u_int8_t pci_bus_cnt;
|
||||
phandle_t *pci_bus_map;
|
||||
int pci_bus_map_sz;
|
||||
static u_int8_t pci_bus_cnt;
|
||||
static phandle_t *pci_bus_map;
|
||||
static 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
|
||||
/*
|
||||
* INOs < 255 are really intpin numbers; use a driver method to figure out
|
||||
* the real INO.
|
||||
*/
|
||||
#define OPQ_INO_CALLBACK 2
|
||||
/*
|
||||
* Do not map EBus interrupts at PCI buses, but assume that they are fully
|
||||
* specified already.
|
||||
*/
|
||||
#define OPQ_EBUS_NOMAP 4
|
||||
|
||||
static struct ofw_pci_quirk {
|
||||
char *opq_model;
|
||||
int opq_quirks;
|
||||
} ofw_pci_quirks[] = {
|
||||
{ "SUNW,Ultra-4", OPQ_INO_CALLBACK | OPQ_EBUS_NOMAP },
|
||||
{ "SUNW,Ultra-1-Engine", OPQ_NO_SWIZZLE },
|
||||
};
|
||||
#define OPQ_NENT (sizeof(ofw_pci_quirks) / sizeof(ofw_pci_quirks[0]))
|
||||
|
||||
static int pci_quirks;
|
||||
|
||||
#define OFW_PCI_PCIBUS "pci"
|
||||
#define OFW_PCI_EBUS "ebus"
|
||||
|
||||
int
|
||||
ofw_pci_orb_callback(phandle_t node, u_int8_t *pintptr, int pintsz,
|
||||
u_int8_t *pregptr, int pregsz, u_int8_t **rintr, int *terminate,
|
||||
void *cookie)
|
||||
{
|
||||
device_t dev = cookie;
|
||||
struct ofw_pci_register preg;
|
||||
ofw_pci_intr_t pintr, intr;
|
||||
u_int slot;
|
||||
char type[32];
|
||||
int found = 0;
|
||||
|
||||
if ((pci_quirks & OPQ_EBUS_NOMAP) != 0 &&
|
||||
OF_getprop(node, "name", type, sizeof(type)) != -1 &&
|
||||
strcmp(type, OFW_PCI_EBUS) == 0) {
|
||||
*terminate = 1;
|
||||
return (-1);
|
||||
}
|
||||
if (pintsz != sizeof(pintr) || pregsz < sizeof(preg))
|
||||
return (-1);
|
||||
bcopy(pintptr, &pintr, sizeof(pintr));
|
||||
bcopy(pregptr, &preg, sizeof(preg));
|
||||
slot = OFW_PCI_PHYS_HI_DEVICE(preg.phys_hi);
|
||||
|
||||
if ((pci_quirks & OPQ_INO_CALLBACK) != 0 && pintr <= 255) {
|
||||
/*
|
||||
* The e450 has no interrupt maps at all, and it usually has
|
||||
* full interrupt numbers, including IGN, in the interrupt
|
||||
* properties. There is one exception, however: the property
|
||||
* 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 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 = OFW_PCI_GUESS_INO(dev, node, slot, pintr);
|
||||
found = intr != 255;
|
||||
*terminate = found;
|
||||
}
|
||||
if (!found && (pci_quirks & OPQ_NO_SWIZZLE) == 0 &&
|
||||
OF_getprop(node, "device_type", type, sizeof(type)) != -1 &&
|
||||
strcmp(type, OFW_PCI_PCIBUS) == 0 && pintr >= 1 && pintr <= 4) {
|
||||
/*
|
||||
* Handle a quirk found on some Netra t1 models: there exist
|
||||
* PCI bridges without interrupt maps, where we apparently must
|
||||
* do the PCI swizzle and continue to map on at the parent.
|
||||
*/
|
||||
intr = (slot + pintr + 3) % 4 + 1;
|
||||
*terminate = 0;
|
||||
found = 1;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
*rintr = malloc(sizeof(intr), M_OFWPROP, M_WAITOK);
|
||||
bcopy(&intr, *rintr, sizeof(intr));
|
||||
return (sizeof(intr));
|
||||
} else
|
||||
return (-1);
|
||||
}
|
||||
|
||||
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 (PCI_INVALID_IRQ);
|
||||
/*
|
||||
* Some machines (notably the SPARCengine Ultra AX and the e450) have
|
||||
* no mappings at all, but use complete interrupt vector number
|
||||
* including the IGN. Catch this case and remove the IGN.
|
||||
*/
|
||||
if (rv > ign)
|
||||
rv -= ign;
|
||||
return (rv);
|
||||
}
|
||||
#endif /* !OFW_NEWCPI */
|
||||
|
||||
u_int8_t
|
||||
ofw_pci_alloc_busno(phandle_t node)
|
||||
{
|
||||
@ -193,199 +73,3 @@ ofw_pci_alloc_busno(phandle_t node)
|
||||
pci_bus_map[n] = node;
|
||||
return (n);
|
||||
}
|
||||
|
||||
#ifndef OFW_NEWPCI
|
||||
/*
|
||||
* Initialize bridge bus numbers for bridges that implement the primary,
|
||||
* secondary and subordinate bus number registers.
|
||||
*/
|
||||
void
|
||||
ofw_pci_binit(device_t busdev, struct ofw_pci_bdesc *obd)
|
||||
{
|
||||
|
||||
#ifdef OFW_PCI_DEBUG
|
||||
printf("PCI-PCI bridge at %u/%u/%u: setting bus #s to %u/%u/%u\n",
|
||||
obd->obd_bus, obd->obd_slot, obd->obd_func, obd->obd_bus,
|
||||
obd->obd_secbus, obd->obd_subbus);
|
||||
#endif /* OFW_PCI_DEBUG */
|
||||
PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
|
||||
PCIR_PRIBUS_1, obd->obd_bus, 1);
|
||||
PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
|
||||
PCIR_SECBUS_1, obd->obd_secbus, 1);
|
||||
PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
|
||||
PCIR_SUBBUS_1, obd->obd_subbus, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the PCI bus hierarchy, starting with the root PCI bus and descending
|
||||
* through bridges, and initialize the interrupt line and latency timer
|
||||
* configuration registers of attached devices using firmware information,
|
||||
* as well as the the bus numbers and ranges of the bridges.
|
||||
*/
|
||||
void
|
||||
ofw_pci_init(device_t dev, phandle_t bushdl, ofw_pci_intr_t ign,
|
||||
struct ofw_pci_bdesc *obd)
|
||||
{
|
||||
struct ofw_pci_register pcir;
|
||||
struct ofw_pci_bdesc subobd, *tobd;
|
||||
phandle_t node;
|
||||
char type[32];
|
||||
int i, intr, freemap;
|
||||
u_int slot, busno, func, sub, lat;
|
||||
u_int8_t clnsz;
|
||||
|
||||
/* Initialize the quirk list. */
|
||||
for (i = 0; i < OPQ_NENT; i++) {
|
||||
if (strcmp(sparc64_model, ofw_pci_quirks[i].opq_model) == 0) {
|
||||
pci_quirks = ofw_pci_quirks[i].opq_quirks;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((node = OF_child(bushdl)) == 0)
|
||||
return;
|
||||
freemap = 0;
|
||||
busno = obd->obd_secbus;
|
||||
/*
|
||||
* Compute the 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));
|
||||
|
||||
do {
|
||||
if (node == -1)
|
||||
panic("ofw_pci_init_intr: OF_child failed");
|
||||
if (OF_getprop(node, "device_type", type, sizeof(type)) == -1)
|
||||
type[0] = '\0';
|
||||
else
|
||||
type[sizeof(type) - 1] = '\0';
|
||||
if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1)
|
||||
panic("ofw_pci_init: OF_getprop failed");
|
||||
slot = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi);
|
||||
func = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi);
|
||||
PCIB_WRITE_CONFIG(dev, busno, slot, func, PCIR_CACHELNSZ,
|
||||
clnsz / 4, 1);
|
||||
if (strcmp(type, OFW_PCI_PCIBUS) == 0) {
|
||||
/*
|
||||
* This is a pci-pci bridge, initalize the bus number and
|
||||
* recurse to initialize the child bus. The hierarchy is
|
||||
* usually at most 2 levels deep, so recursion is
|
||||
* feasible.
|
||||
*/
|
||||
subobd.obd_bus = busno;
|
||||
subobd.obd_slot = slot;
|
||||
subobd.obd_func = func;
|
||||
sub = ofw_pci_alloc_busno(node);
|
||||
subobd.obd_secbus = subobd.obd_subbus = sub;
|
||||
/* Assume this bridge is mostly standard conforming. */
|
||||
subobd.obd_init = ofw_pci_binit;
|
||||
subobd.obd_super = obd;
|
||||
/*
|
||||
* Need to change all subordinate bus registers of the
|
||||
* bridges above this one now so that configuration
|
||||
* transactions will get through.
|
||||
*/
|
||||
for (tobd = obd; tobd != NULL; tobd = tobd->obd_super) {
|
||||
tobd->obd_subbus = sub;
|
||||
tobd->obd_init(dev, tobd);
|
||||
}
|
||||
subobd.obd_init(dev, &subobd);
|
||||
#ifdef OFW_PCI_DEBUG
|
||||
device_printf(dev, "%s: descending to "
|
||||
"subordinate PCI bus\n", __func__);
|
||||
#endif /* OFW_PCI_DEBUG */
|
||||
ofw_pci_init(dev, node, ign, &subobd);
|
||||
} else {
|
||||
/*
|
||||
* 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 33 and no wait states
|
||||
* should be assumed.
|
||||
*/
|
||||
lat = PCIB_READ_CONFIG(dev, busno, slot, func,
|
||||
PCIR_MINGNT, 1) * 33 / 4;
|
||||
if (lat != 0) {
|
||||
#ifdef OFW_PCI_DEBUG
|
||||
printf("device %d/%d/%d: latency timer %d -> "
|
||||
"%d\n", busno, slot, func,
|
||||
PCIB_READ_CONFIG(dev, busno, slot, func,
|
||||
PCIR_LATTIMER, 1), lat);
|
||||
#endif /* OFW_PCI_DEBUG */
|
||||
PCIB_WRITE_CONFIG(dev, busno, slot, func,
|
||||
PCIR_LATTIMER, imin(lat, 255), 1);
|
||||
}
|
||||
|
||||
/* Initialize the intline registers. */
|
||||
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",
|
||||
__func__, busno, slot, func, intr,
|
||||
(int)PCIB_READ_CONFIG(dev, busno, slot,
|
||||
func, PCIR_INTLINE, 1));
|
||||
#endif /* OFW_PCI_DEBUG */
|
||||
PCIB_WRITE_CONFIG(dev, busno, slot, func,
|
||||
PCIR_INTLINE, intr, 1);
|
||||
} else {
|
||||
#ifdef OFW_PCI_DEBUG
|
||||
device_printf(dev, "%s: no interrupt "
|
||||
"mapping found for %d/%d/%d (preset %d)\n",
|
||||
__func__, busno, slot, func,
|
||||
(int)PCIB_READ_CONFIG(dev, busno, slot,
|
||||
func, PCIR_INTLINE, 1));
|
||||
#endif /* OFW_PCI_DEBUG */
|
||||
/*
|
||||
* The firmware initializes to 0 instead of
|
||||
* 255.
|
||||
*/
|
||||
PCIB_WRITE_CONFIG(dev, busno, slot, func,
|
||||
PCIR_INTLINE, PCI_INVALID_IRQ, 1);
|
||||
}
|
||||
}
|
||||
} while ((node = OF_peer(node)) != 0);
|
||||
}
|
||||
|
||||
phandle_t
|
||||
ofw_pci_find_node(int bus, int slot, int func)
|
||||
{
|
||||
phandle_t node, bnode;
|
||||
struct ofw_pci_register pcir;
|
||||
|
||||
/*
|
||||
* Retrieve the bus node from the mapping that was created on
|
||||
* initialization. The bus numbers the firmware uses cannot be trusted,
|
||||
* so they might have needed to be changed and this is necessary.
|
||||
*/
|
||||
if (bus >= pci_bus_map_sz)
|
||||
return (0);
|
||||
bnode = pci_bus_map[bus];
|
||||
if (bnode == 0)
|
||||
return (0);
|
||||
for (node = OF_child(bnode); node != 0 && node != -1;
|
||||
node = OF_peer(node)) {
|
||||
if (OF_getprop(node, "reg", &pcir, sizeof(pcir)) == -1)
|
||||
continue;
|
||||
if (OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi) == slot &&
|
||||
OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi) == func)
|
||||
return (node);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
phandle_t
|
||||
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 */
|
||||
|
@ -46,26 +46,8 @@ typedef u_int32_t ofw_pci_intr_t;
|
||||
#define PCI_CS_MEM32 0x02
|
||||
#define PCI_CS_MEM64 0x03
|
||||
|
||||
struct ofw_pci_imap {
|
||||
u_int32_t phys_hi;
|
||||
u_int32_t phys_mid;
|
||||
u_int32_t phys_lo;
|
||||
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;
|
||||
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)
|
||||
{
|
||||
@ -73,26 +55,4 @@ 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 *);
|
||||
|
||||
struct ofw_pci_bdesc {
|
||||
u_int obd_bus;
|
||||
u_int obd_slot;
|
||||
u_int obd_func;
|
||||
u_int obd_secbus;
|
||||
u_int obd_subbus;
|
||||
ofw_pci_binit_t *obd_init;
|
||||
struct ofw_pci_bdesc *obd_super;
|
||||
};
|
||||
|
||||
obr_callback_t ofw_pci_orb_callback;
|
||||
ofw_pci_binit_t ofw_pci_binit;
|
||||
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_ */
|
||||
|
@ -34,7 +34,6 @@ 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;
|
||||
@ -46,15 +45,6 @@ CODE {
|
||||
return (OFW_PCI_INTR_PENDING(device_get_parent(dev), intr));
|
||||
}
|
||||
|
||||
static ofw_pci_intr_t
|
||||
ofw_pci_default_guess_ino(device_t dev, phandle_t node, u_int slot,
|
||||
u_int pin)
|
||||
{
|
||||
|
||||
return (OFW_PCI_GUESS_INO(device_get_parent(dev), node, slot,
|
||||
pin));
|
||||
}
|
||||
|
||||
static bus_space_handle_t
|
||||
ofw_pci_default_get_bus_handle(device_t dev, int type,
|
||||
bus_space_handle_t childhdl, bus_space_tag_t *tag)
|
||||
@ -85,18 +75,6 @@ METHOD int 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.
|
||||
# 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 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.
|
||||
@ -107,8 +85,8 @@ METHOD bus_space_handle_t get_bus_handle {
|
||||
bus_space_tag_t *tag;
|
||||
} 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.
|
||||
# Get the firmware node for the device dev on the bus. The default method 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 {
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/pciio.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
*/
|
||||
|
||||
#include "opt_ofw_pci.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
@ -131,4 +132,3 @@ ofw_pcib_gen_adjust_busrange(device_t bridge, u_int subbus)
|
||||
OFW_PCI_ADJUST_BUSRANGE(device_get_parent(bridge), subbus);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,10 +35,8 @@ struct ofw_pcib_gen_softc {
|
||||
* 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);
|
||||
|
@ -59,7 +59,6 @@
|
||||
#include <machine/ofw_bus.h>
|
||||
#include <machine/ofw_upa.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <sys/rman.h>
|
||||
|
||||
@ -80,9 +79,6 @@ 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 *);
|
||||
@ -114,14 +110,9 @@ 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 */
|
||||
@ -146,14 +137,9 @@ static device_method_t psycho_methods[] = {
|
||||
|
||||
/* 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 }
|
||||
};
|
||||
@ -297,9 +283,6 @@ 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;
|
||||
@ -583,27 +566,7 @@ psycho_attach(device_t dev)
|
||||
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;
|
||||
|
||||
/*
|
||||
* Initialize the interrupt registers of all devices hanging from
|
||||
* the host bridge directly or indirectly via PCI-PCI bridges.
|
||||
* The MI code (and the PCI spec) assume that this is done during
|
||||
* system initialization, however the firmware does not do this
|
||||
* at least on some models, and we probably shouldn't trust that
|
||||
* the firmware uses the same model as this driver if it does.
|
||||
* 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", sc->sc_secbus);
|
||||
return (bus_generic_attach(dev));
|
||||
@ -792,21 +755,6 @@ 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)
|
||||
{
|
||||
|
||||
#ifdef PSYCHO_DEBUG
|
||||
printf("psycho at %u/%u/%u: setting bus #s to %u/%u/%u\n",
|
||||
obd->obd_bus, obd->obd_slot, obd->obd_func, obd->obd_bus,
|
||||
obd->obd_secbus, obd->obd_subbus);
|
||||
#endif /* PSYCHO_DEBUG */
|
||||
PCIB_WRITE_CONFIG(busdev, obd->obd_bus, obd->obd_slot, obd->obd_func,
|
||||
PCSR_SUBBUS, obd->obd_subbus, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
psycho_maxslots(device_t dev)
|
||||
{
|
||||
@ -815,32 +763,6 @@ psycho_maxslots(device_t dev)
|
||||
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
|
||||
* drivers are added. Moving it to the MI code should maybe be reconsidered
|
||||
* if one of these devices appear in non-sparc64 boxen. It's likely that not
|
||||
* all BIOSes/firmwares can deal with them.
|
||||
*/
|
||||
struct psycho_dquirk {
|
||||
u_int32_t dq_devid;
|
||||
int dq_quirk;
|
||||
};
|
||||
|
||||
/* Quirk types. May be or'ed together. */
|
||||
#define DQT_BAD_INTPIN 1 /* Intpin reg 0, but intpin used */
|
||||
|
||||
static struct psycho_dquirk dquirks[] = {
|
||||
{ 0x1001108e, DQT_BAD_INTPIN }, /* Sun HME (PCIO func. 1) */
|
||||
{ 0x1101108e, DQT_BAD_INTPIN }, /* Sun GEM (PCIO2 func. 1) */
|
||||
{ 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]))
|
||||
|
||||
static u_int32_t
|
||||
psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
|
||||
int width)
|
||||
@ -848,9 +770,6 @@ 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;
|
||||
#ifndef OFW_NEWPCI
|
||||
u_int32_t devid;
|
||||
#endif
|
||||
u_int8_t byte;
|
||||
u_int16_t shrt;
|
||||
u_int32_t wrd;
|
||||
@ -884,30 +803,6 @@ psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
|
||||
#endif
|
||||
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,
|
||||
PCIR_DEVVENDOR, 4);
|
||||
for (i = 0; i < NDQUIRKS; i++) {
|
||||
if (dquirks[i].dq_devid == devid) {
|
||||
/*
|
||||
* Need to set the intpin to a value != 0 so
|
||||
* that the MI code will think that this device
|
||||
* has an interrupt.
|
||||
* Just use 1 (intpin a) for now. This is, of
|
||||
* course, bogus, but since interrupts are
|
||||
* routed in advance, this does not really
|
||||
* matter.
|
||||
*/
|
||||
if ((dquirks[i].dq_quirk & DQT_BAD_INTPIN) != 0)
|
||||
r = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* !OFW_NEWPCI */
|
||||
return (r);
|
||||
}
|
||||
|
||||
@ -940,7 +835,6 @@ psycho_write_config(device_t dev, u_int bus, u_int slot, u_int func,
|
||||
static int
|
||||
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;
|
||||
@ -975,24 +869,6 @@ psycho_route_interrupt(device_t bridge, device_t dev, int pin)
|
||||
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
|
||||
* the one of a bridge, so the original device can't be recovered.
|
||||
*
|
||||
* We need to use the firmware to route interrupts, however it has
|
||||
* no interface which could be used to interpret intpins; instead,
|
||||
* all assignments are done by device.
|
||||
*
|
||||
* The MI pci code will try to reroute interrupts of 0, although they
|
||||
* are correct; all other interrupts are preinitialized, so if we
|
||||
* get here, the intline is either 0 (so return 0), or we hit a
|
||||
* device which was not preinitialized (e.g. hotplugged stuff), in
|
||||
* which case we are lost.
|
||||
*/
|
||||
return (0);
|
||||
#endif /* OFW_NEWPCI */
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1238,33 +1114,6 @@ psycho_intr_pending(device_t dev, ofw_pci_intr_t intr)
|
||||
return (diag != 0);
|
||||
}
|
||||
|
||||
#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);
|
||||
bus_addr_t intrmap;
|
||||
|
||||
/*
|
||||
* If this is not for one of our direct children (i.e. we are mapping
|
||||
* at our node), tell the interrupt mapper to go on - we need the
|
||||
* slot number of the device or it's topmost parent bridge to guess
|
||||
* the INO.
|
||||
*/
|
||||
if (node != sc->sc_node)
|
||||
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.
|
||||
* 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 * (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, int type, bus_space_handle_t childhdl,
|
||||
bus_space_tag_t *tag)
|
||||
@ -1284,7 +1133,6 @@ psycho_get_bus_handle(device_t dev, int type, bus_space_handle_t childhdl,
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef OFW_NEWPCI
|
||||
static phandle_t
|
||||
psycho_get_node(device_t bus, device_t dev)
|
||||
{
|
||||
@ -1311,7 +1159,6 @@ psycho_adjust_busrange(device_t dev, u_int subbus)
|
||||
PCSR_SUBBUS, subbus, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static bus_space_tag_t
|
||||
psycho_alloc_bus_tag(struct psycho_softc *sc, int type)
|
||||
|
@ -67,9 +67,7 @@ struct psycho_softc {
|
||||
struct resource *sc_irq_res[6];
|
||||
void *sc_ihand[6];
|
||||
|
||||
#ifdef OFW_NEWPCI
|
||||
struct ofw_bus_iinfo sc_iinfo;
|
||||
#endif
|
||||
|
||||
struct upa_ranges *sc_range;
|
||||
int sc_nrange;
|
||||
|
@ -64,8 +64,6 @@
|
||||
* bits left.
|
||||
*/
|
||||
|
||||
#include "opt_ofw_pci.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/systm.h>
|
||||
@ -86,8 +84,6 @@ 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)
|
||||
{
|
||||
@ -181,7 +177,7 @@ ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz,
|
||||
i = imapsz;
|
||||
tsz = physsz + intrsz + sizeof(phandle_t) + rintrsz;
|
||||
while (i > 0) {
|
||||
KASSERT(i >= tsz, ("ofw_bus_find_intr: truncated map"));
|
||||
KASSERT(i >= tsz, ("ofw_bus_search_intrmap: truncated map"));
|
||||
bcopy(mptr + physsz + intrsz, &parent, sizeof(parent));
|
||||
if (ofw_bus_searchprop(parent, "#interrupt-cells",
|
||||
&pintrsz, sizeof(pintrsz)) == -1)
|
||||
@ -200,168 +196,3 @@ ofw_bus_search_intrmap(void *intr, int intrsz, void *regs, int physsz,
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
#else
|
||||
/*
|
||||
* Map an interrupt using the firmware reg, interrupt-map and
|
||||
* interrupt-map-mask properties.
|
||||
* The interrupt is returned in *result, which is malloc()'ed. The size of
|
||||
* the interrupt specifiaction is returned.
|
||||
*/
|
||||
static int
|
||||
ofw_bus_find_intr(u_int8_t *intr, int intrsz, u_int8_t *regs, int physsz,
|
||||
u_int8_t *imap, int imapsz, u_int8_t *imapmsk, u_int8_t **result)
|
||||
{
|
||||
phandle_t parent;
|
||||
char *ref;
|
||||
u_int8_t *mptr;
|
||||
pcell_t pintrsz;
|
||||
int i, rsz, tsz;
|
||||
|
||||
rsz = -1;
|
||||
ref = malloc(physsz + intrsz, M_TEMP, M_WAITOK);
|
||||
if (imapmsk != NULL) {
|
||||
for (i = 0; i < physsz; i++)
|
||||
ref[i] = regs[i] & imapmsk[i];
|
||||
for (i = 0; i < intrsz; i++)
|
||||
ref[physsz + i] = intr[i] & imapmsk[physsz + i];
|
||||
} else {
|
||||
bcopy(regs, ref, physsz);
|
||||
bcopy(intr, ref + physsz, intrsz);
|
||||
}
|
||||
mptr = imap;
|
||||
i = imapsz;
|
||||
while (i > 0) {
|
||||
KASSERT(i >= physsz + sizeof(parent),
|
||||
("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);
|
||||
KASSERT(i >= physsz + intrsz + sizeof(parent) +
|
||||
pintrsz, ("ofw_bus_find_intr: truncated map"));
|
||||
if (bcmp(ref, mptr, physsz + intrsz) == 0) {
|
||||
*result = malloc(pintrsz, M_OFWPROP, M_WAITOK);
|
||||
bcopy(mptr + physsz + intrsz + sizeof(parent),
|
||||
*result, pintrsz);
|
||||
rsz = pintrsz;
|
||||
break;
|
||||
}
|
||||
tsz = physsz + intrsz + sizeof(phandle_t) + pintrsz;
|
||||
mptr += tsz;
|
||||
i -= tsz;
|
||||
}
|
||||
free(ref, M_TEMP);
|
||||
return (rsz);
|
||||
}
|
||||
|
||||
/*
|
||||
* Apply the OpenFirmware algorithm for mapping an interrupt. First, the
|
||||
* 'interrupts' and 'reg' properties are retrieved; those are matched against
|
||||
* the interrupt map of the next higher node. If there is no match or no such
|
||||
* propery, we go to the next higher node, using the 'reg' property of the node
|
||||
* that was just processed unusccessfully.
|
||||
* When a match occurs, we should continue to search, using the new interrupt
|
||||
* specification that was just found; this is currently not performed
|
||||
* (see below).
|
||||
* When the root node is reached with at least one successful mapping performed,
|
||||
* and the format is right, the interrupt number is returned.
|
||||
*
|
||||
* This should work for all bus systems.
|
||||
*/
|
||||
u_int32_t
|
||||
ofw_bus_route_intr(phandle_t node, int intrp, obr_callback_t *cb, void *cookie)
|
||||
{
|
||||
u_int8_t *reg, *intr, *tintr, *imap, *imapmsk;
|
||||
phandle_t parent;
|
||||
pcell_t addrc, ic;
|
||||
u_int32_t rv;
|
||||
int regsz, tisz, isz, imapsz, found;
|
||||
|
||||
found = 0;
|
||||
reg = imap = imapmsk = NULL;
|
||||
if (intrp == ORIP_NOINT) {
|
||||
isz = OF_getprop_alloc(node, "interrupts", 1, (void **)&intr);
|
||||
if (isz < 0)
|
||||
return (ORIR_NOTFOUND);
|
||||
} else {
|
||||
ic = intrp;
|
||||
isz = sizeof(ic);
|
||||
intr = malloc(isz, M_OFWPROP, M_WAITOK);
|
||||
bcopy(&ic, intr, isz);
|
||||
}
|
||||
/*
|
||||
* Note that apparently, remapping at multiple levels is allowed;
|
||||
* however, this causes problems with EBus at least, and seems to never
|
||||
* be needed, so we disable it for now (*sigh*).
|
||||
*/
|
||||
for (parent = OF_parent(node); parent != 0 && !found;
|
||||
parent = OF_parent(node = parent)) {
|
||||
if (reg != NULL)
|
||||
free(reg, M_OFWPROP);
|
||||
regsz = OF_getprop_alloc(node, "reg", 1, (void **)®);
|
||||
if (regsz < 0)
|
||||
panic("ofw_bus_route_intr: could not get reg property");
|
||||
imapsz = OF_getprop_alloc(parent, "interrupt-map", 1,
|
||||
(void **)&imap);
|
||||
if (imapsz == -1) {
|
||||
/*
|
||||
* Use the callback to allow caller-specific workarounds
|
||||
* for firmware bugs (missing properties).
|
||||
*/
|
||||
if (cb != NULL) {
|
||||
tisz = cb(parent, intr, isz, reg, regsz, &tintr,
|
||||
&found, cookie);
|
||||
if (tisz != -1) {
|
||||
isz = tisz;
|
||||
free(intr, M_OFWPROP);
|
||||
intr = tintr;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (OF_getprop(parent, "#address-cells", &addrc,
|
||||
sizeof(addrc)) == -1)
|
||||
addrc = 2;
|
||||
addrc *= sizeof(pcell_t);
|
||||
/*
|
||||
* Failures to get the mask are ignored; a full mask is assumed
|
||||
* in this case.
|
||||
*/
|
||||
OF_getprop_alloc(parent, "interrupt-map-mask", 1,
|
||||
(void **)&imapmsk);
|
||||
tisz = ofw_bus_find_intr(intr, isz, reg, addrc, imap, imapsz,
|
||||
imapmsk, &tintr);
|
||||
if (tisz != -1) {
|
||||
found = 1;
|
||||
isz = tisz;
|
||||
free(intr, M_OFWPROP);
|
||||
intr = tintr;
|
||||
}
|
||||
free(imap, M_OFWPROP);
|
||||
if (imapmsk != NULL)
|
||||
free(imapmsk, M_OFWPROP);
|
||||
}
|
||||
if (reg != NULL)
|
||||
free(reg, M_OFWPROP);
|
||||
#if 0
|
||||
/*
|
||||
* Obviously there are some boxes that don't require mapping at all,
|
||||
* for example the U30, which has no interrupt maps for children of
|
||||
* the root PCI bus.
|
||||
*/
|
||||
if (!found) {
|
||||
if (intrp != ORIP_NOINT)
|
||||
return (ORIR_NOTFOUND);
|
||||
panic("ofw_bus_route_intr: 'interrupts' property, but no "
|
||||
"mapping found");
|
||||
}
|
||||
#endif
|
||||
KASSERT(isz == sizeof(u_int32_t),
|
||||
("ofw_bus_route_intr: bad interrupt spec size %d", isz));
|
||||
bcopy(intr, &rv, sizeof(rv));
|
||||
free(intr, M_OFWPROP);
|
||||
return (rv);
|
||||
}
|
||||
#endif /* OFW_NEWPCI */
|
||||
|
@ -29,8 +29,6 @@
|
||||
* Some OpenFirmware helper functions that are likely machine dependent.
|
||||
*/
|
||||
|
||||
#include "opt_ofw_pci.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
||||
@ -65,11 +63,7 @@ OF_getetheraddr2(device_t dev, u_char *addr)
|
||||
{
|
||||
phandle_t node;
|
||||
|
||||
#ifdef OFW_NEWPCI
|
||||
node = ofw_pci_get_node(dev);
|
||||
#else
|
||||
node = ofw_pci_node(dev);
|
||||
#endif
|
||||
if (node <= 0)
|
||||
return (-1);
|
||||
return (OF_getprop(node, "local-mac-address", addr, ETHER_ADDR_LEN));
|
||||
|
Loading…
Reference in New Issue
Block a user