Rototill the sparc64 nexus(4) (actually this brings in the code the
sun4v nexus(4) in turn is based on): o Change nexus(4) to manage the resources of its children so the respective device drivers don't need to figure them out of OFW themselves. o Change nexus(4) to provide the ofw_bus KOBJ interface instead of using IVARs for supplying the OFW node and the subset of standard properties of its children. Together with the previous change this also allows to fully take advantage of newbus in that drivers like fhc(4), which attach on multiple parent busses, no longer require different bus front-ends as obtaining the OFW node and properties as well as resource allocation works the same for all supported busses. As such this change also is part 4/4 of allowing creator(4) to work in USIII-based machines as it allows this driver to attach on both nexus(4) and upa(4). On the other hand removing these IVARs breaks API compatibility with the powerpc nexus(4) but which isn't that bad as a) sparc64 currently doesn't share any device driver hanging off of nexus(4) with powerpc and b) they were no longer compatible regarding OFW-related extensions at the pci(4) level since quite some time. o Provide bus_get_dma_tag methods in nexus(4) and its children in order to handle DMA tags in a hierarchical way and get rid of the sparc64_root_dma_tag kludge. Together with the previous two items this changes also allows to completely get rid of the nexus(4) IVAR interface. It also includes: - pushing the constraints previously specified by the nexus_dmatag down into the DMA tags of psycho(4) and sbus(4) as it's their IOMMUs which induce these restrictions (and nothing at the nexus(4) or anything that would warrant specifying them there), - fixing some obviously wrong constraints of the psycho(4) and sbus(4) DMA tags, which happened to not actually be used with the sparc64_root_dma_tag kludge in place and therefore didn't cause problems so far, - replacing magic constants for constraints with macros as far as it is obvious as to where they come from. This doesn't include taking advantage of the newbus way to get the parent DMA tags implemented by this change in order to divorce the IOTSBs of the PCI and SBus IOMMUs or for implementing the workaround for the DMA sync bug in Sabre (and Tomatillo) bridges, yet, though. o Get rid of the notion that nexus(4) (mostly) reflects an UPA bus by replacing ofw_upa.h and with ofw_nexus.h (which was repo-copied from ofw_upa.h) and renaming its content, which actually applies to all of Fireplane/Safari, JBus and UPA (in the host bus case), as appropriate. o Just use M_DEVBUF instead of a separate M_NEXUS malloc type for allocating the device info for the children of nexus(4). This is done in order to not need to export M_NEXUS when deriving drivers for subordinate busses from the nexus(4) class. o Use the DEFINE_CLASS_0() macro to declare the nexus(4) driver so we can derive subclasses from it. o Const'ify the nexus_excl_name and nexus_excl_type arrays as well as add 'associations' and 'rsc', which are pseudo-devices without resources and therefore of no real interest for nexus(4), to the former. o Let the nexus(4) device memory rman manage the entire 64-bit address space instead of just the UPA_MEMSTART to UPA_MEMEND subregion as Fireplane/Safari- and JBus-based machines use multiple ranges, which can't be as easily divided as in the case of UPA (limiting the address space only served for sanity checking anyway). o Use M_WAITOK instead of M_NOWAIT when allocating the device info for children of nexus(4) in order to give one less opportunity for adding devices to nexus(4) to fail. o While adapting the drivers affected by the above nexus(4) changes, change them to take advantage of rman_get_rid() instead of caching the RIDs assigned to allocated resources, now that the RIDs of resources are correctly set. o In iommu(4) and nexus(4) replace hard-coded functions names, which actually became outdated in several places, in panic strings and status massages with __func__. [1] o Use driver_filter_t in prototypes where appropriate. o Add my copyright to creator(4), fhc(4), nexus(4), psycho(4) and sbus(4) as I changed considerable amounts of these drivers as well as added a bunch of new features, workarounds for silicon bugs etc. o Fix some white space nits. Due to lack of access to Exx00 hardware, these changes, i.e. central(4) and fhc(4), couldn't be runtime tested on such a machine. Exx00 are currently reported to panic before trying to attach nexus(4) anyway though. PR: 76052 [1] Approved by: re (kensmith)
This commit is contained in:
parent
ddb38a1f3d
commit
33368e9fe8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=167308
@ -80,8 +80,6 @@ sparc64/central/central.c optional central
|
||||
sparc64/ebus/ebus.c optional ebus
|
||||
sparc64/fhc/clkbrd.c optional clkbrd fhc
|
||||
sparc64/fhc/fhc.c optional fhc
|
||||
sparc64/fhc/fhc_central.c optional fhc central
|
||||
sparc64/fhc/fhc_nexus.c optional fhc
|
||||
sparc64/isa/isa.c optional isa
|
||||
sparc64/isa/isa_dma.c optional isa
|
||||
sparc64/isa/ofw_isa.c optional ebus | isa
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Jake Burkholder.
|
||||
* Copyright (c) 2005 - 2006 Marius Strobl <marius@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -37,13 +38,12 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/module.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/bus_private.h>
|
||||
#include <machine/nexusvar.h>
|
||||
#include <machine/ofw_machdep.h>
|
||||
#include <machine/ofw_upa.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/sc_machdep.h>
|
||||
|
||||
@ -63,7 +63,6 @@ struct creator_softc {
|
||||
|
||||
struct cdev *sc_si;
|
||||
|
||||
int sc_rid[FFB_NREG];
|
||||
struct resource *sc_reg[FFB_NREG];
|
||||
bus_space_tag_t sc_bt[FFB_NREG];
|
||||
bus_space_handle_t sc_bh[FFB_NREG];
|
||||
@ -172,9 +171,7 @@ static devclass_t creator_devclass;
|
||||
DEFINE_CLASS_0(creator, creator_bus_driver, creator_bus_methods,
|
||||
sizeof(struct creator_softc));
|
||||
DRIVER_MODULE(creator, nexus, creator_bus_driver, creator_devclass, 0, 0);
|
||||
#if 0
|
||||
DRIVER_MODULE(creator, upa, creator_bus_driver, creator_devclass, 0, 0);
|
||||
#endif
|
||||
|
||||
static d_open_t creator_fb_open;
|
||||
static d_close_t creator_fb_close;
|
||||
@ -880,8 +877,8 @@ creator_bus_probe(device_t dev)
|
||||
phandle_t node;
|
||||
int type;
|
||||
|
||||
name = nexus_get_name(dev);
|
||||
node = nexus_get_node(dev);
|
||||
name = ofw_bus_get_name(dev);
|
||||
node = ofw_bus_get_node(dev);
|
||||
if (strcmp(name, "SUNW,ffb") == 0) {
|
||||
if (OF_getprop(node, "board_type", &type, sizeof(type)) == -1)
|
||||
return (ENXIO);
|
||||
@ -906,18 +903,15 @@ static int
|
||||
creator_bus_attach(device_t dev)
|
||||
{
|
||||
struct creator_softc *sc;
|
||||
struct upa_regs *reg;
|
||||
video_adapter_t *adp;
|
||||
video_switch_t *sw;
|
||||
phandle_t node;
|
||||
bus_addr_t phys;
|
||||
bus_size_t size;
|
||||
int error;
|
||||
int nreg;
|
||||
int rid;
|
||||
int unit;
|
||||
int i;
|
||||
|
||||
node = nexus_get_node(dev);
|
||||
node = ofw_bus_get_node(dev);
|
||||
if ((sc = (struct creator_softc *)vid_get_adapter(vid_find_adapter(
|
||||
CREATOR_DRIVER_NAME, 0))) != NULL && sc->sc_node == node) {
|
||||
device_printf(dev, "console\n");
|
||||
@ -940,20 +934,10 @@ creator_bus_attach(device_t dev)
|
||||
* allocate more than these two resources and just limit the
|
||||
* range accessible via creator_fb_mmap() accordingly.
|
||||
*/
|
||||
reg = nexus_get_reg(dev);
|
||||
nreg = nexus_get_nreg(dev);
|
||||
if (nreg <= FFB_FBC) {
|
||||
device_printf(dev, "not enough resources\n");
|
||||
error = ENXIO;
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < nreg; i++) {
|
||||
phys = UPA_REG_PHYS(reg + i);
|
||||
size = UPA_REG_SIZE(reg + i);
|
||||
sc->sc_rid[i] = i;
|
||||
sc->sc_reg[i] = bus_alloc_resource(dev, SYS_RES_MEMORY,
|
||||
&sc->sc_rid[i], phys, phys + size - 1, size,
|
||||
RF_ACTIVE);
|
||||
for (i = 0; i < FFB_NREG; i++) {
|
||||
rid = i;
|
||||
sc->sc_reg[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&rid, RF_ACTIVE);
|
||||
if (sc->sc_reg[i] == NULL) {
|
||||
if (i <= FFB_FBC) {
|
||||
device_printf(dev,
|
||||
@ -1000,7 +984,7 @@ creator_bus_attach(device_t dev)
|
||||
for (i = 0; i < devclass_get_maxunit(creator_devclass); i++)
|
||||
if (vid_find_adapter(CREATOR_DRIVER_NAME, i) < 0)
|
||||
break;
|
||||
if (strcmp(nexus_get_name(dev), "SUNW,afb") == 0)
|
||||
if (strcmp(ofw_bus_get_name(dev), "SUNW,afb") == 0)
|
||||
sc->sc_flags |= CREATOR_AFB;
|
||||
if ((error = sw->init(i, adp, 0)) != 0) {
|
||||
device_printf(dev, "cannot initialize adapter\n");
|
||||
@ -1031,8 +1015,8 @@ creator_bus_attach(device_t dev)
|
||||
|
||||
fail:
|
||||
for (i = 0; i < FFB_NREG && sc->sc_reg[i] != NULL; i++)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid[i],
|
||||
sc->sc_reg[i]);
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
rman_get_rid(sc->sc_reg[i]), sc->sc_reg[i]);
|
||||
return (error);
|
||||
}
|
||||
|
||||
|
@ -39,8 +39,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/nexusvar.h>
|
||||
#include <machine/ofw_upa.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <sys/rman.h>
|
||||
@ -68,14 +66,14 @@ static ofw_bus_get_devinfo_t central_get_devinfo;
|
||||
static int central_print_res(struct central_devinfo *);
|
||||
|
||||
static device_method_t central_methods[] = {
|
||||
/* Device interface. */
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, central_probe),
|
||||
DEVMETHOD(device_attach, central_attach),
|
||||
DEVMETHOD(device_shutdown, bus_generic_shutdown),
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
|
||||
/* Bus interface. */
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, central_print_child),
|
||||
DEVMETHOD(bus_probe_nomatch, central_probe_nomatch),
|
||||
DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
|
||||
@ -112,7 +110,7 @@ static int
|
||||
central_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (strcmp(nexus_get_name(dev), "central") == 0) {
|
||||
if (strcmp(ofw_bus_get_name(dev), "central") == 0) {
|
||||
device_set_desc(dev, "central");
|
||||
return (0);
|
||||
}
|
||||
@ -132,7 +130,7 @@ central_attach(device_t dev)
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
node = nexus_get_node(dev);
|
||||
node = ofw_bus_get_node(dev);
|
||||
|
||||
sc->sc_nrange = OF_getprop_alloc(node, "ranges",
|
||||
sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Jake Burkholder.
|
||||
* Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -32,6 +33,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/pcpu.h>
|
||||
|
||||
#include <dev/led/led.h>
|
||||
@ -46,7 +48,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <sparc64/fhc/fhcreg.h>
|
||||
#include <sparc64/fhc/fhcvar.h>
|
||||
#include <sparc64/sbus/ofw_sbus.h>
|
||||
|
||||
struct fhc_clr {
|
||||
@ -62,18 +63,87 @@ struct fhc_devinfo {
|
||||
struct resource_list fdi_rl;
|
||||
};
|
||||
|
||||
static int fhc_intr_stub(void *);
|
||||
struct fhc_softc {
|
||||
struct resource * sc_memres[FHC_NREG];
|
||||
bus_space_handle_t sc_bh[FHC_NREG];
|
||||
bus_space_tag_t sc_bt[FHC_NREG];
|
||||
int sc_nrange;
|
||||
struct sbus_ranges *sc_ranges;
|
||||
uint32_t sc_board;
|
||||
int sc_ign;
|
||||
struct cdev *sc_led_dev;
|
||||
int sc_flags;
|
||||
#define FHC_CENTRAL (1 << 0)
|
||||
};
|
||||
|
||||
static device_probe_t fhc_probe;
|
||||
static device_attach_t fhc_attach;
|
||||
static bus_print_child_t fhc_print_child;
|
||||
static bus_probe_nomatch_t fhc_probe_nomatch;
|
||||
static bus_setup_intr_t fhc_setup_intr;
|
||||
static bus_teardown_intr_t fhc_teardown_intr;
|
||||
static bus_alloc_resource_t fhc_alloc_resource;
|
||||
static bus_get_resource_list_t fhc_get_resource_list;
|
||||
static ofw_bus_get_devinfo_t fhc_get_devinfo;
|
||||
|
||||
static driver_filter_t fhc_intr_stub;
|
||||
static void fhc_led_func(void *, int);
|
||||
static int fhc_print_res(struct fhc_devinfo *);
|
||||
|
||||
int
|
||||
static device_method_t fhc_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, fhc_probe),
|
||||
DEVMETHOD(device_attach, fhc_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, fhc_print_child),
|
||||
DEVMETHOD(bus_probe_nomatch, fhc_probe_nomatch),
|
||||
DEVMETHOD(bus_setup_intr, fhc_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, fhc_teardown_intr),
|
||||
DEVMETHOD(bus_alloc_resource, fhc_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_get_resource_list, fhc_get_resource_list),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_devinfo, fhc_get_devinfo),
|
||||
DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
|
||||
DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
|
||||
DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
|
||||
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
|
||||
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static driver_t fhc_driver = {
|
||||
"fhc",
|
||||
fhc_methods,
|
||||
sizeof(struct fhc_softc),
|
||||
};
|
||||
|
||||
static devclass_t fhc_devclass;
|
||||
|
||||
DRIVER_MODULE(fhc, central, fhc_driver, fhc_devclass, 0, 0);
|
||||
DRIVER_MODULE(fhc, nexus, fhc_driver, fhc_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
fhc_probe(device_t dev)
|
||||
{
|
||||
|
||||
return (0);
|
||||
if (strcmp(ofw_bus_get_name(dev), "fhc") == 0) {
|
||||
device_set_desc(dev, "fhc");
|
||||
return (0);
|
||||
}
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
fhc_attach(device_t dev)
|
||||
{
|
||||
char ledname[sizeof("boardXX")];
|
||||
@ -83,16 +153,48 @@ fhc_attach(device_t dev)
|
||||
phandle_t child;
|
||||
phandle_t node;
|
||||
device_t cdev;
|
||||
uint32_t board;
|
||||
uint32_t ctrl;
|
||||
uint32_t *intr;
|
||||
uint32_t iv;
|
||||
char *name;
|
||||
int error;
|
||||
int i;
|
||||
int nintr;
|
||||
int nreg;
|
||||
int i;
|
||||
int rid;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
node = sc->sc_node;
|
||||
node = ofw_bus_get_node(dev);
|
||||
|
||||
if (strcmp(device_get_name(device_get_parent(dev)), "central") == 0)
|
||||
sc->sc_flags |= FHC_CENTRAL;
|
||||
|
||||
for (i = 0; i < FHC_NREG; i++) {
|
||||
rid = i;
|
||||
sc->sc_memres[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&rid, RF_ACTIVE);
|
||||
if (sc->sc_memres[i] == NULL) {
|
||||
device_printf(dev, "cannot allocate resource %d\n", i);
|
||||
error = ENXIO;
|
||||
goto fail_memres;
|
||||
}
|
||||
sc->sc_bt[i] = rman_get_bustag(sc->sc_memres[i]);
|
||||
sc->sc_bh[i] = rman_get_bushandle(sc->sc_memres[i]);
|
||||
}
|
||||
|
||||
if ((sc->sc_flags & FHC_CENTRAL) != 0) {
|
||||
board = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
|
||||
sc->sc_bh[FHC_INTERNAL], FHC_BSR);
|
||||
sc->sc_board = ((board >> 16) & 0x1) | ((board >> 12) & 0xe);
|
||||
} else {
|
||||
if (OF_getprop(node, "board#", &sc->sc_board,
|
||||
sizeof(sc->sc_board)) == -1) {
|
||||
device_printf(dev, "cannot get board number\n");
|
||||
error = ENXIO;
|
||||
goto fail_memres;
|
||||
}
|
||||
}
|
||||
|
||||
device_printf(dev, "board %d, ", sc->sc_board);
|
||||
if (OF_getprop_alloc(node, "board-model", 1, (void **)&name) != -1) {
|
||||
@ -125,8 +227,9 @@ fhc_attach(device_t dev)
|
||||
sc->sc_nrange = OF_getprop_alloc(node, "ranges",
|
||||
sizeof(*sc->sc_ranges), (void **)&sc->sc_ranges);
|
||||
if (sc->sc_nrange == -1) {
|
||||
device_printf(dev, "can't get ranges\n");
|
||||
return (ENXIO);
|
||||
device_printf(dev, "cannot get ranges\n");
|
||||
error = ENXIO;
|
||||
goto fail_memres;
|
||||
}
|
||||
|
||||
if ((sc->sc_flags & FHC_CENTRAL) == 0) {
|
||||
@ -179,9 +282,16 @@ fhc_attach(device_t dev)
|
||||
}
|
||||
|
||||
return (bus_generic_attach(dev));
|
||||
|
||||
fail_memres:
|
||||
for (i = 0; i < FHC_NREG; i++)
|
||||
if (sc->sc_memres[i] != NULL)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY,
|
||||
rman_get_rid(sc->sc_memres[i]), sc->sc_memres[i]);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
fhc_print_child(device_t dev, device_t child)
|
||||
{
|
||||
int rv;
|
||||
@ -192,7 +302,7 @@ fhc_print_child(device_t dev, device_t child)
|
||||
return (rv);
|
||||
}
|
||||
|
||||
void
|
||||
static void
|
||||
fhc_probe_nomatch(device_t dev, device_t child)
|
||||
{
|
||||
const char *type;
|
||||
@ -204,7 +314,7 @@ fhc_probe_nomatch(device_t dev, device_t child)
|
||||
type != NULL ? type : "unknown");
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
fhc_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
|
||||
driver_filter_t *filt, driver_intr_t *func, void *arg, void **cookiep)
|
||||
{
|
||||
@ -269,7 +379,7 @@ fhc_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
static int
|
||||
fhc_teardown_intr(device_t bus, device_t child, struct resource *r,
|
||||
void *cookie)
|
||||
{
|
||||
@ -295,7 +405,7 @@ fhc_intr_stub(void *arg)
|
||||
return (FILTER_HANDLED);
|
||||
}
|
||||
|
||||
struct resource *
|
||||
static struct resource *
|
||||
fhc_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
@ -354,7 +464,7 @@ fhc_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
return (res);
|
||||
}
|
||||
|
||||
struct resource_list *
|
||||
static struct resource_list *
|
||||
fhc_get_resource_list(device_t bus, device_t child)
|
||||
{
|
||||
struct fhc_devinfo *fdi;
|
||||
@ -363,7 +473,7 @@ fhc_get_resource_list(device_t bus, device_t child)
|
||||
return (&fdi->fdi_rl);
|
||||
}
|
||||
|
||||
const struct ofw_bus_devinfo *
|
||||
static const struct ofw_bus_devinfo *
|
||||
fhc_get_devinfo(device_t bus, device_t child)
|
||||
{
|
||||
struct fhc_devinfo *fdi;
|
||||
|
@ -1,132 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Jake Burkholder.
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <sparc64/fhc/fhcreg.h>
|
||||
#include <sparc64/fhc/fhcvar.h>
|
||||
|
||||
static device_probe_t fhc_central_probe;
|
||||
static device_attach_t fhc_central_attach;
|
||||
|
||||
static device_method_t fhc_central_methods[] = {
|
||||
/* Device interface. */
|
||||
DEVMETHOD(device_probe, fhc_central_probe),
|
||||
DEVMETHOD(device_attach, fhc_central_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, fhc_print_child),
|
||||
DEVMETHOD(bus_probe_nomatch, fhc_probe_nomatch),
|
||||
DEVMETHOD(bus_setup_intr, fhc_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, fhc_teardown_intr),
|
||||
DEVMETHOD(bus_alloc_resource, fhc_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_get_resource_list, fhc_get_resource_list),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_devinfo, fhc_get_devinfo),
|
||||
DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
|
||||
DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
|
||||
DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
|
||||
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
|
||||
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static driver_t fhc_central_driver = {
|
||||
"fhc",
|
||||
fhc_central_methods,
|
||||
sizeof(struct fhc_softc),
|
||||
};
|
||||
|
||||
static devclass_t fhc_central_devclass;
|
||||
|
||||
DRIVER_MODULE(fhc, central, fhc_central_driver, fhc_central_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
fhc_central_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (strcmp(ofw_bus_get_name(dev), "fhc") == 0) {
|
||||
device_set_desc(dev, "fhc");
|
||||
return (fhc_probe(dev));
|
||||
}
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
fhc_central_attach(device_t dev)
|
||||
{
|
||||
struct fhc_softc *sc;
|
||||
phandle_t node;
|
||||
int board;
|
||||
int rid;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
node = ofw_bus_get_node(dev);
|
||||
sc->sc_node = node;
|
||||
sc->sc_flags |= FHC_CENTRAL;
|
||||
|
||||
for (i = 0; i < FHC_NREG; i++) {
|
||||
rid = i;
|
||||
sc->sc_memres[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
|
||||
&rid, RF_ACTIVE);
|
||||
if (sc->sc_memres[i] == NULL)
|
||||
panic("%s: can't allocate registers", __func__);
|
||||
sc->sc_bt[i] = rman_get_bustag(sc->sc_memres[i]);
|
||||
sc->sc_bh[i] = rman_get_bushandle(sc->sc_memres[i]);
|
||||
}
|
||||
|
||||
board = bus_space_read_4(sc->sc_bt[FHC_INTERNAL],
|
||||
sc->sc_bh[FHC_INTERNAL], FHC_BSR);
|
||||
sc->sc_board = ((board >> 16) & 0x1) | ((board >> 12) & 0xe);
|
||||
|
||||
return (fhc_attach(dev));
|
||||
}
|
@ -1,147 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Jake Burkholder.
|
||||
* 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 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.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/ofw_upa.h>
|
||||
#include <machine/nexusvar.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <sparc64/fhc/fhcreg.h>
|
||||
#include <sparc64/fhc/fhcvar.h>
|
||||
|
||||
static device_probe_t fhc_nexus_probe;
|
||||
static device_attach_t fhc_nexus_attach;
|
||||
|
||||
static device_method_t fhc_nexus_methods[] = {
|
||||
/* Device interface. */
|
||||
DEVMETHOD(device_probe, fhc_nexus_probe),
|
||||
DEVMETHOD(device_attach, fhc_nexus_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, fhc_print_child),
|
||||
DEVMETHOD(bus_probe_nomatch, fhc_probe_nomatch),
|
||||
DEVMETHOD(bus_setup_intr, fhc_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, fhc_teardown_intr),
|
||||
DEVMETHOD(bus_alloc_resource, fhc_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_get_resource_list, fhc_get_resource_list),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_devinfo, fhc_get_devinfo),
|
||||
DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
|
||||
DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
|
||||
DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
|
||||
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
|
||||
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
|
||||
|
||||
{ NULL, NULL }
|
||||
};
|
||||
|
||||
static driver_t fhc_nexus_driver = {
|
||||
"fhc",
|
||||
fhc_nexus_methods,
|
||||
sizeof(struct fhc_softc),
|
||||
};
|
||||
|
||||
static devclass_t fhc_nexus_devclass;
|
||||
|
||||
DRIVER_MODULE(fhc, nexus, fhc_nexus_driver, fhc_nexus_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
fhc_nexus_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (strcmp(nexus_get_name(dev), "fhc") == 0) {
|
||||
device_set_desc(dev, "fhc");
|
||||
return (fhc_probe(dev));
|
||||
}
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
static int
|
||||
fhc_nexus_attach(device_t dev)
|
||||
{
|
||||
struct fhc_softc *sc;
|
||||
struct upa_regs *reg;
|
||||
bus_addr_t phys;
|
||||
bus_addr_t size;
|
||||
phandle_t node;
|
||||
int nreg;
|
||||
int rid;
|
||||
int i;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
node = nexus_get_node(dev);
|
||||
sc->sc_node = node;
|
||||
|
||||
reg = nexus_get_reg(dev);
|
||||
nreg = nexus_get_nreg(dev);
|
||||
if (nreg != FHC_NREG) {
|
||||
device_printf(dev, "wrong number of regs\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
for (i = 0; i < nreg; i++) {
|
||||
phys = UPA_REG_PHYS(reg + i);
|
||||
size = UPA_REG_SIZE(reg + i);
|
||||
rid = 0;
|
||||
sc->sc_memres[i] = bus_alloc_resource(dev, SYS_RES_MEMORY,
|
||||
&rid, phys, phys + size - 1, size, RF_ACTIVE);
|
||||
if (sc->sc_memres[i] == NULL)
|
||||
panic("%s: can't allocate registers", __func__);
|
||||
sc->sc_bt[i] = rman_get_bustag(sc->sc_memres[i]);
|
||||
sc->sc_bh[i] = rman_get_bushandle(sc->sc_memres[i]);
|
||||
}
|
||||
|
||||
if (OF_getprop(node, "board#", &sc->sc_board,
|
||||
sizeof(sc->sc_board)) == -1) {
|
||||
device_printf(dev, "could not get board number\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
return (fhc_attach(dev));
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 Jake Burkholder.
|
||||
* 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 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _SPARC64_FHC_FHCVAR_H_
|
||||
#define _SPARC64_FHC_FHCVAR_H_
|
||||
|
||||
#define FHC_CENTRAL (1<<0)
|
||||
|
||||
struct fhc_softc {
|
||||
phandle_t sc_node;
|
||||
struct resource * sc_memres[FHC_NREG];
|
||||
bus_space_handle_t sc_bh[FHC_NREG];
|
||||
bus_space_tag_t sc_bt[FHC_NREG];
|
||||
int sc_nrange;
|
||||
struct sbus_ranges *sc_ranges;
|
||||
int sc_board;
|
||||
int sc_ign;
|
||||
int sc_flags;
|
||||
struct cdev *sc_led_dev;
|
||||
};
|
||||
|
||||
device_probe_t fhc_probe;
|
||||
device_attach_t fhc_attach;
|
||||
|
||||
bus_print_child_t fhc_print_child;
|
||||
bus_probe_nomatch_t fhc_probe_nomatch;
|
||||
bus_setup_intr_t fhc_setup_intr;
|
||||
bus_teardown_intr_t fhc_teardown_intr;
|
||||
bus_alloc_resource_t fhc_alloc_resource;
|
||||
bus_get_resource_list_t fhc_get_resource_list;
|
||||
|
||||
ofw_bus_get_devinfo_t fhc_get_devinfo;
|
||||
|
||||
#endif /* !_SPARC64_FHC_FHCVAR_H_ */
|
@ -73,11 +73,4 @@ struct bus_dmamap {
|
||||
int sparc64_dma_alloc_map(bus_dma_tag_t dmat, bus_dmamap_t *mapp);
|
||||
void sparc64_dma_free_map(bus_dma_tag_t dmat, bus_dmamap_t map);
|
||||
|
||||
/*
|
||||
* XXX: This is a kluge. It would be better to handle dma tags in a hierarchical
|
||||
* way, and have a BUS_GET_DMA_TAG(); however, since this is not currently the
|
||||
* case, save a root tag in the relevant bus attach function and use that.
|
||||
*/
|
||||
extern bus_dma_tag_t sparc64_root_dma_tag;
|
||||
|
||||
#endif /* !_MACHINE_BUS_PRIVATE_H_ */
|
||||
|
@ -40,7 +40,7 @@
|
||||
#define _MACHINE_IOMMUREG_H_
|
||||
|
||||
/*
|
||||
* UltraSPARC IOMMU registers, common to both the sbus and PCI
|
||||
* UltraSPARC IOMMU registers, common to both the PCI and SBus
|
||||
* controllers.
|
||||
*/
|
||||
|
||||
@ -65,7 +65,7 @@
|
||||
#define STRBUF_D 0x0000000000000002UL
|
||||
|
||||
#define IOMMU_BITS 34
|
||||
#define IOMMU_MAXADDR (1UL << IOMMU_BITS)
|
||||
#define IOMMU_MAXADDR ((1UL << IOMMU_BITS) - 1)
|
||||
|
||||
/*
|
||||
* control register bits
|
||||
@ -140,7 +140,7 @@
|
||||
#define STRBUF_FLUSHSYNC_NBYTES STRBUF_LINESZ
|
||||
|
||||
/*
|
||||
* On sun4u each bus controller has a separate IOMMU. The IOMMU has
|
||||
* On sun4u each bus controller has a separate IOMMU. The IOMMU has
|
||||
* a TSB which must be page aligned and physically contiguous. Mappings
|
||||
* can be of 8K IOMMU pages or 64K IOMMU pages. We use 8K for compatibility
|
||||
* with the CPU's MMU.
|
||||
@ -168,7 +168,7 @@
|
||||
|
||||
#define IOTSB_BASESZ (1024 << IOTTE_SHIFT)
|
||||
#define IOTSB_VEND (~IO_PAGE_MASK)
|
||||
#define IOTSB_VSTART(sz) (u_int)(IOTSB_VEND << ((sz) + 10))
|
||||
#define IOTSB_VSTART(sz) (u_int)(IOTSB_VEND << ((sz) + 10))
|
||||
|
||||
#define MAKEIOTTE(pa,w,c,s) \
|
||||
(((pa) & IOTTE_PAMASK) | ((w) ? IOTTE_W : 0) | \
|
||||
|
@ -1,58 +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$
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_NEXUSVAR_H_
|
||||
#define _MACHINE_NEXUSVAR_H_
|
||||
|
||||
enum nexus_ivars {
|
||||
NEXUS_IVAR_NODE,
|
||||
NEXUS_IVAR_NAME,
|
||||
NEXUS_IVAR_DEVICE_TYPE,
|
||||
NEXUS_IVAR_MODEL,
|
||||
NEXUS_IVAR_REG,
|
||||
NEXUS_IVAR_NREG,
|
||||
NEXUS_IVAR_INTERRUPTS,
|
||||
NEXUS_IVAR_NINTERRUPTS,
|
||||
NEXUS_IVAR_DMATAG,
|
||||
};
|
||||
|
||||
#define NEXUS_ACCESSOR(var, ivar, type) \
|
||||
__BUS_ACCESSOR(nexus, var, NEXUS, ivar, type)
|
||||
|
||||
NEXUS_ACCESSOR(node, NODE, phandle_t)
|
||||
NEXUS_ACCESSOR(name, NAME, char *)
|
||||
NEXUS_ACCESSOR(device_type, DEVICE_TYPE, char *)
|
||||
NEXUS_ACCESSOR(model, MODEL, char *)
|
||||
NEXUS_ACCESSOR(reg, REG, struct upa_regs *)
|
||||
NEXUS_ACCESSOR(nreg, NREG, int)
|
||||
NEXUS_ACCESSOR(interrupts, INTERRUPTS, u_int *)
|
||||
NEXUS_ACCESSOR(ninterrupts, NINTERRUPTS, int)
|
||||
NEXUS_ACCESSOR(dmatag, DMATAG, bus_dma_tag_t)
|
||||
|
||||
#undef NEXUS_ACCESSOR
|
||||
|
||||
#endif /* _MACHINE_NEXUSVAR_H_ */
|
@ -31,24 +31,24 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_OFW_UPA_H_
|
||||
#define _MACHINE_OFW_UPA_H_
|
||||
#ifndef _MACHINE_OFW_NEXUS_H_
|
||||
#define _MACHINE_OFW_NEXUS_H_
|
||||
|
||||
/*
|
||||
* These are the regs and ranges property the psycho uses. They should be
|
||||
* applicable to all UPA devices. XXX: verify this.
|
||||
* These are the regs used for devices on the nexus. They apply to all of
|
||||
* Fireplane/Safari, JBus and UPA.
|
||||
*/
|
||||
|
||||
struct upa_regs {
|
||||
u_int32_t phys_hi;
|
||||
u_int32_t phys_lo;
|
||||
u_int32_t size_hi;
|
||||
u_int32_t size_lo;
|
||||
struct nexus_regs {
|
||||
uint32_t phys_hi;
|
||||
uint32_t phys_lo;
|
||||
uint32_t size_hi;
|
||||
uint32_t size_lo;
|
||||
};
|
||||
|
||||
#define UPA_REG_PHYS(r) \
|
||||
(((u_int64_t)(r)->phys_hi << 32) | (u_int64_t)(r)->phys_lo)
|
||||
#define UPA_REG_SIZE(r) \
|
||||
(((u_int64_t)(r)->size_hi << 32) | (u_int64_t)(r)->size_lo)
|
||||
#define NEXUS_REG_PHYS(r) \
|
||||
(((uint64_t)(r)->phys_hi << 32) | (uint64_t)(r)->phys_lo)
|
||||
#define NEXUS_REG_SIZE(r) \
|
||||
(((uint64_t)(r)->size_hi << 32) | (uint64_t)(r)->size_lo)
|
||||
|
||||
#endif /* !_MACHINE_OFW_UPA_H_ */
|
||||
#endif /* !_MACHINE_OFW_NEXUS_H_ */
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*-
|
||||
* Copyright (c) 1998, 1999 Eduardo E. Horvath
|
||||
* Copyright (c) 1999 Matthew R. Green
|
||||
* 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 ``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.
|
||||
*
|
||||
* from: NetBSD: psychoreg.h,v 1.8 2001/09/10 16:17:06 eeh Exp
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _MACHINE_OFW_UPA_H_
|
||||
#define _MACHINE_OFW_UPA_H_
|
||||
|
||||
/*
|
||||
* These are the regs and ranges property the psycho uses. They should be
|
||||
* applicable to all UPA devices. XXX: verify this.
|
||||
*/
|
||||
|
||||
struct upa_regs {
|
||||
u_int32_t phys_hi;
|
||||
u_int32_t phys_lo;
|
||||
u_int32_t size_hi;
|
||||
u_int32_t size_lo;
|
||||
};
|
||||
|
||||
#define UPA_REG_PHYS(r) \
|
||||
(((u_int64_t)(r)->phys_hi << 32) | (u_int64_t)(r)->phys_lo)
|
||||
#define UPA_REG_SIZE(r) \
|
||||
(((u_int64_t)(r)->size_hi << 32) | (u_int64_t)(r)->size_lo)
|
||||
|
||||
#endif /* !_MACHINE_OFW_UPA_H_ */
|
@ -1,6 +1,7 @@
|
||||
/*-
|
||||
* Copyright (c) 1999, 2000 Matthew R. Green
|
||||
* Copyright (c) 2001 - 2003 by Thomas Moestl <tmm@FreeBSD.org>
|
||||
* Copyright (c) 2005 - 2006 Marius Strobl <marius@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -45,8 +46,8 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kdb.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/pcpu.h>
|
||||
#include <sys/reboot.h>
|
||||
|
||||
@ -55,19 +56,16 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/bus_private.h>
|
||||
#include <machine/bus_common.h>
|
||||
#include <machine/bus_private.h>
|
||||
#include <machine/iommureg.h>
|
||||
#include <machine/nexusvar.h>
|
||||
#include <machine/iommuvar.h>
|
||||
#include <machine/ofw_bus.h>
|
||||
#include <machine/ofw_upa.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/ver.h>
|
||||
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <machine/iommuvar.h>
|
||||
|
||||
#include <dev/pci/pcireg.h>
|
||||
#include <dev/pci/pcivar.h>
|
||||
|
||||
@ -79,22 +77,22 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
static const struct psycho_desc *psycho_find_desc(const struct psycho_desc *,
|
||||
const char *);
|
||||
static const struct psycho_desc *psycho_get_desc(phandle_t, const char *);
|
||||
static const struct psycho_desc *psycho_get_desc(device_t);
|
||||
static void psycho_set_intr(struct psycho_softc *, int, bus_addr_t, int,
|
||||
driver_filter_t);
|
||||
static int psycho_find_intrmap(struct psycho_softc *, int, bus_addr_t *,
|
||||
bus_addr_t *, u_long *);
|
||||
static int psycho_intr_stub(void *);
|
||||
static driver_filter_t psycho_intr_stub;
|
||||
static bus_space_tag_t psycho_alloc_bus_tag(struct psycho_softc *, int);
|
||||
|
||||
/* Interrupt handlers */
|
||||
static int psycho_ue(void *);
|
||||
static int psycho_ce(void *);
|
||||
static int psycho_pci_bus(void *);
|
||||
static int psycho_powerfail(void *);
|
||||
static int psycho_overtemp(void *);
|
||||
static driver_filter_t psycho_ue;
|
||||
static driver_filter_t psycho_ce;
|
||||
static driver_filter_t psycho_pci_bus;
|
||||
static driver_filter_t psycho_powerfail;
|
||||
static driver_filter_t psycho_overtemp;
|
||||
#ifdef PSYCHO_MAP_WAKEUP
|
||||
static int psycho_wakeup(void *);
|
||||
static driver_filter_t psycho_wakeup;
|
||||
#endif
|
||||
|
||||
/* IOMMU support */
|
||||
@ -112,6 +110,7 @@ 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 bus_get_dma_tag_t psycho_get_dma_tag;
|
||||
static pcib_maxslots_t psycho_maxslots;
|
||||
static pcib_read_config_t psycho_read_config;
|
||||
static pcib_write_config_t psycho_write_config;
|
||||
@ -137,6 +136,7 @@ static device_method_t psycho_methods[] = {
|
||||
DEVMETHOD(bus_activate_resource, psycho_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, psycho_deactivate_resource),
|
||||
DEVMETHOD(bus_release_resource, psycho_release_resource),
|
||||
DEVMETHOD(bus_get_dma_tag, psycho_get_dma_tag),
|
||||
|
||||
/* pcib interface */
|
||||
DEVMETHOD(pcib_maxslots, psycho_maxslots),
|
||||
@ -251,25 +251,22 @@ psycho_find_desc(const struct psycho_desc *table, const char *string)
|
||||
{
|
||||
const struct psycho_desc *desc;
|
||||
|
||||
for (desc = table; desc->pd_string != NULL; desc++) {
|
||||
if (string == NULL)
|
||||
return (NULL);
|
||||
for (desc = table; desc->pd_string != NULL; desc++)
|
||||
if (strcmp(desc->pd_string, string) == 0)
|
||||
return (desc);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static const struct psycho_desc *
|
||||
psycho_get_desc(phandle_t node, const char *model)
|
||||
psycho_get_desc(device_t dev)
|
||||
{
|
||||
const struct psycho_desc *rv;
|
||||
char compat[32];
|
||||
|
||||
rv = NULL;
|
||||
if (model != NULL)
|
||||
rv = psycho_find_desc(psycho_models, model);
|
||||
if (rv == NULL &&
|
||||
OF_getprop(node, "compatible", compat, sizeof(compat)) != -1)
|
||||
rv = psycho_find_desc(psycho_compats, compat);
|
||||
rv = psycho_find_desc(psycho_models, ofw_bus_get_model(dev));
|
||||
if (rv == NULL)
|
||||
rv = psycho_find_desc(psycho_compats, ofw_bus_get_compat(dev));
|
||||
return (rv);
|
||||
}
|
||||
|
||||
@ -278,11 +275,9 @@ psycho_probe(device_t dev)
|
||||
{
|
||||
const char *dtype;
|
||||
|
||||
dtype = nexus_get_device_type(dev);
|
||||
if (nexus_get_reg(dev) != NULL && dtype != NULL &&
|
||||
strcmp(dtype, OFW_PCI_TYPE) == 0 &&
|
||||
psycho_get_desc(nexus_get_node(dev),
|
||||
nexus_get_model(dev)) != NULL) {
|
||||
dtype = ofw_bus_get_type(dev);
|
||||
if (dtype != NULL && strcmp(dtype, OFW_PCI_TYPE) == 0 &&
|
||||
psycho_get_desc(dev) != NULL) {
|
||||
device_set_desc(dev, "U2P UPA-PCI bridge");
|
||||
return (0);
|
||||
}
|
||||
@ -296,23 +291,21 @@ psycho_attach(device_t dev)
|
||||
char name[sizeof("pci108e,1000")];
|
||||
struct psycho_softc *asc, *sc, *osc;
|
||||
struct ofw_pci_ranges *range;
|
||||
struct upa_regs *reg;
|
||||
const struct psycho_desc *desc;
|
||||
phandle_t child, node;
|
||||
uint64_t csr, dr;
|
||||
uint32_t dvmabase, psycho_br[2];
|
||||
int32_t rev;
|
||||
u_long mlen;
|
||||
u_int ver;
|
||||
int n, i, nrange, nreg, rid;
|
||||
int i, n, nrange, rid;
|
||||
#ifdef PSYCHO_DEBUG
|
||||
bus_addr_t map, clr;
|
||||
uint64_t mr;
|
||||
#endif
|
||||
|
||||
node = nexus_get_node(dev);
|
||||
node = ofw_bus_get_node(dev);
|
||||
sc = device_get_softc(dev);
|
||||
desc = psycho_get_desc(node, nexus_get_model(dev));
|
||||
desc = psycho_get_desc(dev);
|
||||
|
||||
sc->sc_node = node;
|
||||
sc->sc_dev = dev;
|
||||
@ -325,14 +318,11 @@ psycho_attach(device_t dev)
|
||||
* PBM 256-byte PCI header
|
||||
* (2) the shared Psycho configuration registers
|
||||
*/
|
||||
reg = nexus_get_reg(dev);
|
||||
nreg = nexus_get_nreg(dev);
|
||||
if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
|
||||
if (nreg <= 2)
|
||||
panic("%s: %d not enough registers", __func__, nreg);
|
||||
sc->sc_basepaddr = (vm_paddr_t)UPA_REG_PHYS(®[2]);
|
||||
mlen = UPA_REG_SIZE(®[2]);
|
||||
sc->sc_pcictl = UPA_REG_PHYS(®[0]) - sc->sc_basepaddr;
|
||||
rid = 2;
|
||||
sc->sc_pcictl =
|
||||
bus_get_resource_start(dev, SYS_RES_MEMORY, 0) -
|
||||
bus_get_resource_start(dev, SYS_RES_MEMORY, 2);
|
||||
switch (sc->sc_pcictl) {
|
||||
case PSR_PCICTL0:
|
||||
sc->sc_half = 0;
|
||||
@ -345,13 +335,17 @@ psycho_attach(device_t dev)
|
||||
__func__);
|
||||
}
|
||||
} else {
|
||||
if (nreg <= 0)
|
||||
panic("%s: %d not enough registers", __func__, nreg);
|
||||
sc->sc_basepaddr = (vm_paddr_t)UPA_REG_PHYS(®[0]);
|
||||
mlen = UPA_REG_SIZE(reg);
|
||||
rid = 0;
|
||||
sc->sc_pcictl = PSR_PCICTL0;
|
||||
sc->sc_half = 0;
|
||||
}
|
||||
sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
|
||||
(sc->sc_mode == PSYCHO_MODE_PSYCHO ? RF_SHAREABLE : 0) |
|
||||
RF_ACTIVE);
|
||||
if (sc->sc_mem_res == NULL)
|
||||
panic("%s: could not allocate registers", __func__);
|
||||
sc->sc_bustag = rman_get_bustag(sc->sc_mem_res);
|
||||
sc->sc_bushandle = rman_get_bushandle(sc->sc_mem_res);
|
||||
|
||||
/*
|
||||
* Match other Psycho's that are already configured against
|
||||
@ -360,33 +354,14 @@ psycho_attach(device_t dev)
|
||||
*/
|
||||
osc = NULL;
|
||||
SLIST_FOREACH(asc, &psycho_softcs, sc_link) {
|
||||
if (asc->sc_basepaddr == sc->sc_basepaddr) {
|
||||
if (rman_get_start(asc->sc_mem_res) ==
|
||||
rman_get_start(sc->sc_mem_res)) {
|
||||
/* Found partner. */
|
||||
osc = asc;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (osc == NULL) {
|
||||
rid = 0;
|
||||
sc->sc_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid,
|
||||
sc->sc_basepaddr, sc->sc_basepaddr + mlen - 1, mlen,
|
||||
RF_ACTIVE);
|
||||
if (sc->sc_mem_res == NULL ||
|
||||
rman_get_start(sc->sc_mem_res) != sc->sc_basepaddr)
|
||||
panic("%s: could not allocate device memory", __func__);
|
||||
sc->sc_bustag = rman_get_bustag(sc->sc_mem_res);
|
||||
sc->sc_bushandle = rman_get_bushandle(sc->sc_mem_res);
|
||||
} else {
|
||||
/*
|
||||
* There's another Psycho using the same register space.
|
||||
* Copy the relevant stuff.
|
||||
*/
|
||||
sc->sc_mem_res = NULL;
|
||||
sc->sc_bustag = osc->sc_bustag;
|
||||
sc->sc_bushandle = osc->sc_bushandle;
|
||||
}
|
||||
|
||||
/* Clear PCI AFSR. */
|
||||
PCICTL_WRITE8(sc, PCR_AFS, PCIAFSR_ERRMASK);
|
||||
|
||||
@ -588,15 +563,13 @@ psycho_attach(device_t dev)
|
||||
sc->sc_pci_memt = psycho_alloc_bus_tag(sc, PCI_MEMORY_BUS_SPACE);
|
||||
sc->sc_pci_iot = psycho_alloc_bus_tag(sc, PCI_IO_BUS_SPACE);
|
||||
sc->sc_pci_cfgt = psycho_alloc_bus_tag(sc, PCI_CONFIG_BUS_SPACE);
|
||||
if (bus_dma_tag_create(nexus_get_dmatag(dev), 8, 1, 0, 0x3ffffffff,
|
||||
NULL, NULL, 0x3ffffffff, 0xff, 0xffffffff, 0, NULL, NULL,
|
||||
if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, IOMMU_MAXADDR, ~0,
|
||||
NULL, NULL, IOMMU_MAXADDR, 0xff, 0xffffffff, 0, NULL, NULL,
|
||||
&sc->sc_pci_dmat) != 0)
|
||||
panic("%s: bus_dma_tag_create failed", __func__);
|
||||
/* Customize the tag. */
|
||||
sc->sc_pci_dmat->dt_cookie = sc->sc_is;
|
||||
sc->sc_pci_dmat->dt_mt = &iommu_dma_methods;
|
||||
/* XXX: register as root DMA tag (kludge). */
|
||||
sparc64_root_dma_tag = sc->sc_pci_dmat;
|
||||
|
||||
#ifdef PSYCHO_DEBUG
|
||||
/*
|
||||
@ -604,7 +577,7 @@ psycho_attach(device_t dev)
|
||||
* This aids the debugging of interrupt routing problems.
|
||||
*/
|
||||
for (map = PSR_PCIA0_INT_MAP, clr = PSR_PCIA0_INT_CLR, n = 0;
|
||||
map <= PSR_PCIB3_INT_MAP; map += 8, clr += 32, n++) {
|
||||
map <= PSR_PCIB3_INT_MAP; map += 8, clr += 32, n++) {
|
||||
mr = PSYCHO_READ8(sc, map);
|
||||
device_printf(dev, "intr map (pci) %d: %#lx\n", n, (u_long)mr);
|
||||
PSYCHO_WRITE8(sc, map, mr & ~INTMAP_V);
|
||||
@ -613,7 +586,7 @@ psycho_attach(device_t dev)
|
||||
PSYCHO_WRITE8(sc, map, INTMAP_ENABLE(mr, PCPU_GET(mid)));
|
||||
}
|
||||
for (map = PSR_SCSI_INT_MAP, clr = PSR_SCSI_INT_CLR, n = 0;
|
||||
map <= PSR_SERIAL_INT_MAP; map += 8, clr += 8, n++) {
|
||||
map <= PSR_SERIAL_INT_MAP; map += 8, clr += 8, n++) {
|
||||
mr = PSYCHO_READ8(sc, map);
|
||||
device_printf(dev, "intr map (obio) %d: %#lx, clr: %#lx\n", n,
|
||||
(u_long)mr, (u_long)clr);
|
||||
@ -683,16 +656,16 @@ static void
|
||||
psycho_set_intr(struct psycho_softc *sc, int index, bus_addr_t map, int iflags,
|
||||
driver_filter_t handler)
|
||||
{
|
||||
int rid, vec, res;
|
||||
uint64_t mr;
|
||||
int res, rid;
|
||||
|
||||
res = EINVAL;
|
||||
rid = index;
|
||||
mr = PSYCHO_READ8(sc, map);
|
||||
vec = INTVEC(mr);
|
||||
sc->sc_irq_res[index] = bus_alloc_resource(sc->sc_dev, SYS_RES_IRQ,
|
||||
&rid, vec, vec, 1, RF_ACTIVE);
|
||||
if (sc->sc_irq_res[index] != NULL) {
|
||||
sc->sc_irq_res[index] = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ,
|
||||
&rid, RF_ACTIVE);
|
||||
if (sc->sc_irq_res[index] != NULL &&
|
||||
rman_get_start(sc->sc_irq_res[index]) == INTVEC(mr)) {
|
||||
if (iflags & FAST) {
|
||||
iflags &= ~FAST;
|
||||
res = bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index],
|
||||
@ -722,8 +695,8 @@ psycho_find_intrmap(struct psycho_softc *sc, int ino, bus_addr_t *intrmapptr,
|
||||
/* Hunt thru OBIO first. */
|
||||
diag = PSYCHO_READ8(sc, PSR_OBIO_INT_DIAG);
|
||||
for (intrmap = PSR_SCSI_INT_MAP, intrclr = PSR_SCSI_INT_CLR;
|
||||
intrmap <= PSR_SERIAL_INT_MAP; intrmap += 8, intrclr += 8,
|
||||
diag >>= 2) {
|
||||
intrmap <= PSR_SERIAL_INT_MAP; intrmap += 8, intrclr += 8,
|
||||
diag >>= 2) {
|
||||
im = PSYCHO_READ8(sc, intrmap);
|
||||
if (INTINO(im) == ino) {
|
||||
diag &= 2;
|
||||
@ -736,11 +709,11 @@ psycho_find_intrmap(struct psycho_softc *sc, int ino, bus_addr_t *intrmapptr,
|
||||
diag = PSYCHO_READ8(sc, PSR_PCI_INT_DIAG);
|
||||
/* Now do PCI interrupts. */
|
||||
for (intrmap = PSR_PCIA0_INT_MAP, intrclr = PSR_PCIA0_INT_CLR;
|
||||
intrmap <= PSR_PCIB3_INT_MAP; intrmap += 8, intrclr += 32,
|
||||
diag >>= 8) {
|
||||
intrmap <= PSR_PCIB3_INT_MAP; intrmap += 8, intrclr += 32,
|
||||
diag >>= 8) {
|
||||
if (sc->sc_mode == PSYCHO_MODE_PSYCHO &&
|
||||
(intrmap == PSR_PCIA2_INT_MAP ||
|
||||
intrmap == PSR_PCIA3_INT_MAP))
|
||||
intrmap == PSR_PCIA3_INT_MAP))
|
||||
continue;
|
||||
im = PSYCHO_READ8(sc, intrmap);
|
||||
if (((im ^ ino) & 0x3c) == 0) {
|
||||
@ -930,7 +903,7 @@ psycho_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
|
||||
|
||||
static void
|
||||
psycho_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg,
|
||||
uint32_t val, int width)
|
||||
uint32_t val, int width)
|
||||
{
|
||||
struct psycho_softc *sc;
|
||||
bus_space_handle_t bh;
|
||||
@ -1025,7 +998,7 @@ psycho_intr_stub(void *arg)
|
||||
|
||||
static int
|
||||
psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
|
||||
int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
|
||||
int flags, driver_filter_t *filt, driver_intr_t *intr, void *arg,
|
||||
void **cookiep)
|
||||
{
|
||||
struct {
|
||||
@ -1157,7 +1130,7 @@ psycho_setup_intr(device_t dev, device_t child, struct resource *ires,
|
||||
|
||||
static int
|
||||
psycho_teardown_intr(device_t dev, device_t child, struct resource *vec,
|
||||
void *cookie)
|
||||
void *cookie)
|
||||
{
|
||||
struct psycho_clr *pc = cookie;
|
||||
int error;
|
||||
@ -1290,6 +1263,15 @@ psycho_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
return (rman_release_resource(r));
|
||||
}
|
||||
|
||||
static bus_dma_tag_t
|
||||
psycho_get_dma_tag(device_t bus, device_t child)
|
||||
{
|
||||
struct psycho_softc *sc;
|
||||
|
||||
sc = device_get_softc(bus);
|
||||
return (sc->sc_pci_dmat);
|
||||
}
|
||||
|
||||
static int
|
||||
psycho_intr_pending(device_t dev, ofw_pci_intr_t intr)
|
||||
{
|
||||
|
@ -39,7 +39,6 @@
|
||||
*/
|
||||
struct psycho_softc {
|
||||
device_t sc_dev;
|
||||
vm_paddr_t sc_basepaddr;
|
||||
|
||||
/* Interrupt Group Number for this device */
|
||||
int sc_ign;
|
||||
|
@ -73,6 +73,7 @@
|
||||
/*-
|
||||
* Copyright (c) 1999 Eduardo Horvath
|
||||
* Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>.
|
||||
* Copyright (c) 2005 Marius Strobl <marius@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -121,9 +122,6 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/bus_private.h>
|
||||
#include <machine/iommureg.h>
|
||||
#include <machine/bus_common.h>
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/nexusvar.h>
|
||||
#include <machine/ofw_upa.h>
|
||||
#include <machine/resource.h>
|
||||
|
||||
#include <sys/rman.h>
|
||||
@ -158,12 +156,9 @@ struct sbus_rd {
|
||||
struct sbus_softc {
|
||||
bus_space_tag_t sc_bustag;
|
||||
bus_space_handle_t sc_bushandle;
|
||||
bus_dma_tag_t sc_dmatag;
|
||||
bus_dma_tag_t sc_cdmatag;
|
||||
bus_space_tag_t sc_cbustag;
|
||||
int sc_clockfreq; /* clock frequency (in Hz) */
|
||||
struct upa_regs *sc_reg;
|
||||
int sc_nreg;
|
||||
int sc_nrange;
|
||||
struct sbus_rd *sc_rd;
|
||||
int sc_burst; /* burst transfer sizes supp. */
|
||||
@ -203,16 +198,17 @@ static bus_alloc_resource_t sbus_alloc_resource;
|
||||
static bus_release_resource_t sbus_release_resource;
|
||||
static bus_activate_resource_t sbus_activate_resource;
|
||||
static bus_deactivate_resource_t sbus_deactivate_resource;
|
||||
static bus_get_dma_tag_t sbus_get_dma_tag;
|
||||
static ofw_bus_get_devinfo_t sbus_get_devinfo;
|
||||
|
||||
static int sbus_inlist(const char *, const char **);
|
||||
static struct sbus_devinfo * sbus_setup_dinfo(device_t, struct sbus_softc *,
|
||||
phandle_t);
|
||||
static void sbus_destroy_dinfo(struct sbus_devinfo *);
|
||||
static int sbus_intr_stub(void *);
|
||||
static driver_filter_t sbus_intr_stub;
|
||||
static bus_space_tag_t sbus_alloc_bustag(struct sbus_softc *);
|
||||
static int sbus_overtemp(void *);
|
||||
static int sbus_pwrfail(void *);
|
||||
static driver_filter_t sbus_overtemp;
|
||||
static driver_filter_t sbus_pwrfail;
|
||||
static int sbus_print_res(struct sbus_devinfo *);
|
||||
|
||||
static device_method_t sbus_methods[] = {
|
||||
@ -235,6 +231,7 @@ static device_method_t sbus_methods[] = {
|
||||
DEVMETHOD(bus_release_resource, sbus_release_resource),
|
||||
DEVMETHOD(bus_get_resource_list, sbus_get_resource_list),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
DEVMETHOD(bus_get_dma_tag, sbus_get_dma_tag),
|
||||
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_devinfo, sbus_get_devinfo),
|
||||
@ -283,11 +280,11 @@ sbus_inlist(const char *name, const char **list)
|
||||
static int
|
||||
sbus_probe(device_t dev)
|
||||
{
|
||||
char *t;
|
||||
const char *t;
|
||||
|
||||
t = nexus_get_device_type(dev);
|
||||
t = ofw_bus_get_type(dev);
|
||||
if (((t == NULL || strcmp(t, OFW_SBUS_TYPE) != 0)) &&
|
||||
strcmp(nexus_get_name(dev), OFW_SBUS_NAME) != 0)
|
||||
strcmp(ofw_bus_get_name(dev), OFW_SBUS_NAME) != 0)
|
||||
return (ENXIO);
|
||||
device_set_desc(dev, "U2S UPA-SBus bridge");
|
||||
return (0);
|
||||
@ -300,30 +297,22 @@ sbus_attach(device_t dev)
|
||||
struct sbus_devinfo *sdi;
|
||||
struct sbus_ranges *range;
|
||||
struct resource *res;
|
||||
struct resource_list *rl;
|
||||
device_t cdev;
|
||||
bus_addr_t phys;
|
||||
bus_size_t size;
|
||||
char *name;
|
||||
phandle_t child, node;
|
||||
u_int64_t mr;
|
||||
int intr, clock, rid, vec, i;
|
||||
int clock, i, intr, rid;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
node = nexus_get_node(dev);
|
||||
node = ofw_bus_get_node(dev);
|
||||
|
||||
if ((sc->sc_nreg = OF_getprop_alloc(node, "reg", sizeof(*sc->sc_reg),
|
||||
(void **)&sc->sc_reg)) == -1) {
|
||||
panic("%s: error getting reg property", __func__);
|
||||
}
|
||||
if (sc->sc_nreg < 1)
|
||||
panic("%s: bogus properties", __func__);
|
||||
phys = UPA_REG_PHYS(&sc->sc_reg[0]);
|
||||
size = UPA_REG_SIZE(&sc->sc_reg[0]);
|
||||
rid = 0;
|
||||
sc->sc_sysio_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, phys,
|
||||
phys + size - 1, size, RF_ACTIVE);
|
||||
if (sc->sc_sysio_res == NULL ||
|
||||
rman_get_start(sc->sc_sysio_res) != phys)
|
||||
sc->sc_sysio_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->sc_sysio_res == NULL)
|
||||
panic("%s: cannot allocate device memory", __func__);
|
||||
sc->sc_bustag = rman_get_bustag(sc->sc_sysio_res);
|
||||
sc->sc_bushandle = rman_get_bushandle(sc->sc_sysio_res);
|
||||
@ -358,15 +347,17 @@ sbus_attach(device_t dev)
|
||||
* Preallocate all space that the SBus bridge decodes, so that nothing
|
||||
* else gets in the way; set up rmans etc.
|
||||
*/
|
||||
rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
|
||||
for (i = 0; i < sc->sc_nrange; i++) {
|
||||
phys = range[i].poffset | ((bus_addr_t)range[i].pspace << 32);
|
||||
size = range[i].size;
|
||||
sc->sc_rd[i].rd_slot = range[i].cspace;
|
||||
sc->sc_rd[i].rd_coffset = range[i].coffset;
|
||||
sc->sc_rd[i].rd_cend = sc->sc_rd[i].rd_coffset + size;
|
||||
rid = 0;
|
||||
if ((res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, phys,
|
||||
phys + size - 1, size, RF_ACTIVE)) == NULL)
|
||||
rid = resource_list_add_next(rl, SYS_RES_MEMORY, phys,
|
||||
phys + size - 1, size);
|
||||
if ((res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
|
||||
RF_ACTIVE)) == NULL)
|
||||
panic("%s: cannot allocate decoded range", __func__);
|
||||
sc->sc_rd[i].rd_bushandle = rman_get_bushandle(res);
|
||||
sc->sc_rd[i].rd_rman.rm_type = RMAN_ARRAY;
|
||||
@ -416,33 +407,31 @@ sbus_attach(device_t dev)
|
||||
iommu_init(name, &sc->sc_is, 3, -1, 1);
|
||||
|
||||
/* Create the DMA tag. */
|
||||
sc->sc_dmatag = nexus_get_dmatag(dev);
|
||||
if (bus_dma_tag_create(sc->sc_dmatag, 8, 1, 0, 0x3ffffffff, NULL, NULL,
|
||||
0x3ffffffff, 0xff, 0xffffffff, 0, NULL, NULL, &sc->sc_cdmatag) != 0)
|
||||
if (bus_dma_tag_create(bus_get_dma_tag(dev), 8, 0, IOMMU_MAXADDR, ~0,
|
||||
NULL, NULL, IOMMU_MAXADDR, 0xff, 0xffffffff, 0, NULL, NULL,
|
||||
&sc->sc_cdmatag) != 0)
|
||||
panic("%s: bus_dma_tag_create failed", __func__);
|
||||
/* Customize the tag. */
|
||||
sc->sc_cdmatag->dt_cookie = &sc->sc_is;
|
||||
sc->sc_cdmatag->dt_mt = &iommu_dma_methods;
|
||||
/* XXX: register as root dma tag (kludge). */
|
||||
sparc64_root_dma_tag = sc->sc_cdmatag;
|
||||
|
||||
/* Enable the over-temperature and power-fail interrupts. */
|
||||
rid = 0;
|
||||
rid = 4;
|
||||
mr = SYSIO_READ8(sc, SBR_THERM_INT_MAP);
|
||||
vec = INTVEC(mr);
|
||||
sc->sc_ot_ires = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, vec,
|
||||
vec, 1, RF_ACTIVE);
|
||||
sc->sc_ot_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->sc_ot_ires == NULL ||
|
||||
rman_get_start(sc->sc_ot_ires) != INTVEC(mr) ||
|
||||
bus_setup_intr(dev, sc->sc_ot_ires, INTR_TYPE_MISC,
|
||||
sbus_overtemp, NULL, sc, &sc->sc_ot_ihand) != 0)
|
||||
panic("%s: failed to set up temperature interrupt", __func__);
|
||||
SYSIO_WRITE8(sc, SBR_THERM_INT_MAP, INTMAP_ENABLE(mr, PCPU_GET(mid)));
|
||||
rid = 0;
|
||||
rid = 3;
|
||||
mr = SYSIO_READ8(sc, SBR_POWER_INT_MAP);
|
||||
vec = INTVEC(mr);
|
||||
sc->sc_pf_ires = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, vec,
|
||||
vec, 1, RF_ACTIVE);
|
||||
sc->sc_pf_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
|
||||
RF_ACTIVE);
|
||||
if (sc->sc_pf_ires == NULL ||
|
||||
rman_get_start(sc->sc_pf_ires) != INTVEC(mr) ||
|
||||
bus_setup_intr(dev, sc->sc_pf_ires, INTR_TYPE_MISC,
|
||||
sbus_pwrfail, NULL, sc, &sc->sc_pf_ihand) != 0)
|
||||
panic("%s: failed to set up power fail interrupt", __func__);
|
||||
@ -904,6 +893,15 @@ sbus_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
return (0);
|
||||
}
|
||||
|
||||
static bus_dma_tag_t
|
||||
sbus_get_dma_tag(device_t bus, device_t child)
|
||||
{
|
||||
struct sbus_softc *sc;
|
||||
|
||||
sc = device_get_softc(bus);
|
||||
return (sc->sc_cdmatag);
|
||||
}
|
||||
|
||||
static const struct ofw_bus_devinfo *
|
||||
sbus_get_devinfo(device_t bus, device_t child)
|
||||
{
|
||||
|
@ -189,14 +189,6 @@ dflt_lock(void *arg, bus_dma_lock_op_t op)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Since there is no way for a device to obtain a dma tag from its parent
|
||||
* we use this kluge to handle different the different supported bus systems.
|
||||
* The sparc64_root_dma_tag is used as parent for tags that have none, so that
|
||||
* the correct methods will be used.
|
||||
*/
|
||||
bus_dma_tag_t sparc64_root_dma_tag;
|
||||
|
||||
/*
|
||||
* Allocate a device specific dma_tag.
|
||||
*/
|
||||
@ -207,23 +199,25 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
|
||||
int nsegments, bus_size_t maxsegsz, int flags, bus_dma_lock_t *lockfunc,
|
||||
void *lockfuncarg, bus_dma_tag_t *dmat)
|
||||
{
|
||||
bus_dma_tag_t impptag;
|
||||
bus_dma_tag_t newtag;
|
||||
|
||||
/* Return a NULL tag on failure */
|
||||
*dmat = NULL;
|
||||
|
||||
/* Enforce the usage of BUS_GET_DMA_TAG(). */
|
||||
if (parent == NULL)
|
||||
panic("%s: parent DMA tag NULL", __func__);
|
||||
|
||||
newtag = (bus_dma_tag_t)malloc(sizeof(*newtag), M_DEVBUF, M_NOWAIT);
|
||||
if (newtag == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
impptag = parent != NULL ? parent : sparc64_root_dma_tag;
|
||||
/*
|
||||
* The method table pointer and the cookie need to be taken over from
|
||||
* the parent or the root tag.
|
||||
* the parent.
|
||||
*/
|
||||
newtag->dt_cookie = impptag->dt_cookie;
|
||||
newtag->dt_mt = impptag->dt_mt;
|
||||
newtag->dt_cookie = parent->dt_cookie;
|
||||
newtag->dt_mt = parent->dt_mt;
|
||||
|
||||
newtag->dt_parent = parent;
|
||||
newtag->dt_alignment = alignment;
|
||||
@ -251,18 +245,14 @@ bus_dma_tag_create(bus_dma_tag_t parent, bus_size_t alignment,
|
||||
newtag->dt_segments = NULL;
|
||||
|
||||
/* Take into account any restrictions imposed by our parent tag */
|
||||
if (parent != NULL) {
|
||||
newtag->dt_lowaddr = ulmin(parent->dt_lowaddr,
|
||||
newtag->dt_lowaddr);
|
||||
newtag->dt_highaddr = ulmax(parent->dt_highaddr,
|
||||
newtag->dt_highaddr);
|
||||
if (newtag->dt_boundary == 0)
|
||||
newtag->dt_boundary = parent->dt_boundary;
|
||||
else if (parent->dt_boundary != 0)
|
||||
newtag->dt_boundary = ulmin(parent->dt_boundary,
|
||||
newtag->dt_boundary);
|
||||
atomic_add_int(&parent->dt_ref_count, 1);
|
||||
}
|
||||
newtag->dt_lowaddr = ulmin(parent->dt_lowaddr, newtag->dt_lowaddr);
|
||||
newtag->dt_highaddr = ulmax(parent->dt_highaddr, newtag->dt_highaddr);
|
||||
if (newtag->dt_boundary == 0)
|
||||
newtag->dt_boundary = parent->dt_boundary;
|
||||
else if (parent->dt_boundary != 0)
|
||||
newtag->dt_boundary = ulmin(parent->dt_boundary,
|
||||
newtag->dt_boundary);
|
||||
atomic_add_int(&parent->dt_ref_count, 1);
|
||||
|
||||
if (newtag->dt_boundary > 0)
|
||||
newtag->dt_maxsegsz = ulmin(newtag->dt_maxsegsz,
|
||||
@ -696,15 +686,15 @@ struct bus_dma_methods nexus_dma_methods = {
|
||||
struct bus_dma_tag nexus_dmatag = {
|
||||
NULL,
|
||||
NULL,
|
||||
8,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0x3ffffffff,
|
||||
~0,
|
||||
~0,
|
||||
NULL, /* XXX */
|
||||
NULL,
|
||||
0x3ffffffff, /* XXX */
|
||||
0xff, /* XXX */
|
||||
0xffffffff, /* XXX */
|
||||
~0,
|
||||
~0,
|
||||
~0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
@ -96,12 +96,13 @@
|
||||
* from: NetBSD: sbus.c,v 1.13 1999/05/23 07:24:02 mrg Exp
|
||||
* from: @(#)sbus.c 8.1 (Berkeley) 6/11/93
|
||||
* from: NetBSD: iommu.c,v 1.42 2001/08/06 22:02:58 eeh Exp
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* UltraSPARC IOMMU support; used by both the sbus and pci code.
|
||||
* UltraSPARC IOMMU support; used by both the PCI and SBus code.
|
||||
* Currently, the IOTSBs are synchronized, because determining the bus the map
|
||||
* is to be loaded for is not possible with the current busdma code.
|
||||
* The code is structured so that the IOMMUs can be easily divorced when that
|
||||
@ -328,7 +329,7 @@ iommu_map_remq(struct iommu_state *is, bus_dmamap_t map)
|
||||
}
|
||||
|
||||
/*
|
||||
* initialise the UltraSPARC IOMMU (SBus or PCI):
|
||||
* initialise the UltraSPARC IOMMU (PCI or SBus):
|
||||
* - allocate and setup the iotsb.
|
||||
* - enable the IOMMU
|
||||
* - initialise the streaming buffers (if they exist)
|
||||
@ -347,7 +348,7 @@ iommu_init(char *name, struct iommu_state *is, int tsbsize, u_int32_t iovabase,
|
||||
/*
|
||||
* Setup the iommu.
|
||||
*
|
||||
* The sun4u iommu is part of the SBUS or PCI controller so we
|
||||
* The sun4u iommu is part of the PCI or SBus controller so we
|
||||
* will deal with it here..
|
||||
*
|
||||
* The IOMMU address space always ends at 0xffffe000, but the starting
|
||||
@ -379,7 +380,7 @@ iommu_init(char *name, struct iommu_state *is, int tsbsize, u_int32_t iovabase,
|
||||
rman_manage_region(&iommu_dvma_rman,
|
||||
(is->is_dvmabase >> IO_PAGE_SHIFT) + resvpg,
|
||||
(end >> IO_PAGE_SHIFT) - 1) != 0)
|
||||
panic("iommu_init: can't initialize dvma rman");
|
||||
panic("%s: could not initialize DVMA rman", __func__);
|
||||
/*
|
||||
* Allocate memory for I/O page tables. They need to be
|
||||
* physically contiguous.
|
||||
@ -387,7 +388,7 @@ iommu_init(char *name, struct iommu_state *is, int tsbsize, u_int32_t iovabase,
|
||||
iommu_tsb = contigmalloc(size, M_DEVBUF, M_NOWAIT, 0, ~0UL,
|
||||
PAGE_SIZE, 0);
|
||||
if (iommu_tsb == 0)
|
||||
panic("iommu_init: contigmalloc failed");
|
||||
panic("%s: contigmalloc failed", __func__);
|
||||
iommu_ptsb = pmap_kextract((vm_offset_t)iommu_tsb);
|
||||
bzero(iommu_tsb, size);
|
||||
} else {
|
||||
@ -398,8 +399,8 @@ iommu_init(char *name, struct iommu_state *is, int tsbsize, u_int32_t iovabase,
|
||||
first = STAILQ_FIRST(&iommu_insts);
|
||||
if (is->is_tsbsize != first->is_tsbsize ||
|
||||
is->is_dvmabase != first->is_dvmabase) {
|
||||
panic("iommu_init: secondary IOMMU state does not "
|
||||
"match primary");
|
||||
panic("%s: secondary IOMMU state does not "
|
||||
"match primary", __func__);
|
||||
}
|
||||
}
|
||||
STAILQ_INSERT_TAIL(&iommu_insts, is, is_link);
|
||||
@ -464,7 +465,7 @@ iommu_enter(struct iommu_state *is, vm_offset_t va, vm_paddr_t pa,
|
||||
|
||||
KASSERT(va >= is->is_dvmabase,
|
||||
("iommu_enter: va %#lx not in DVMA space", va));
|
||||
KASSERT(pa < IOMMU_MAXADDR,
|
||||
KASSERT(pa <= IOMMU_MAXADDR,
|
||||
("iommu_enter: XXX: physical address too large (%#lx)", pa));
|
||||
|
||||
tte = MAKEIOTTE(pa, !(flags & BUS_DMA_NOWRITE),
|
||||
@ -579,7 +580,7 @@ iommu_strbuf_flush_sync(struct iommu_state *is)
|
||||
microuptime(&cur);
|
||||
|
||||
if (!*is->is_flushva[0] || !*is->is_flushva[1]) {
|
||||
panic("iommu_strbuf_flush_done: flush timeout %ld, %ld at %#lx",
|
||||
panic("%s: flush timeout %ld, %ld at %#lx", __func__,
|
||||
*is->is_flushva[0], *is->is_flushva[1], is->is_flushpa[0]);
|
||||
}
|
||||
|
||||
@ -628,7 +629,7 @@ iommu_dvma_valloc(bus_dma_tag_t t, struct iommu_state *is, bus_dmamap_t map,
|
||||
align = (t->dt_alignment + IO_PAGE_MASK) >> IO_PAGE_SHIFT;
|
||||
sgsize = round_io_page(size) >> IO_PAGE_SHIFT;
|
||||
if (t->dt_boundary > 0 && t->dt_boundary < IO_PAGE_SIZE)
|
||||
panic("iommu_dvmamap_load: illegal boundary specified");
|
||||
panic("%s: illegal boundary specified", __func__);
|
||||
res = rman_reserve_resource_bound(&iommu_dvma_rman, 0L,
|
||||
t->dt_lowaddr >> IO_PAGE_SHIFT, sgsize,
|
||||
t->dt_boundary >> IO_PAGE_SHIFT,
|
||||
@ -849,7 +850,7 @@ iommu_dvmamap_create(bus_dma_tag_t dt, int flags, bus_dmamap_t *mapp)
|
||||
* Clamp preallocation to IOMMU_MAX_PRE. In some situations we can
|
||||
* handle more; that case is handled by reallocating at map load time.
|
||||
*/
|
||||
totsz = ulmin(IOMMU_SIZE_ROUNDUP(dt->dt_maxsize), IOMMU_MAX_PRE);
|
||||
totsz = ulmin(IOMMU_SIZE_ROUNDUP(dt->dt_maxsize), IOMMU_MAX_PRE);
|
||||
error = iommu_dvma_valloc(dt, is, *mapp, totsz);
|
||||
if (error != 0)
|
||||
return (0);
|
||||
@ -886,7 +887,7 @@ iommu_dvmamap_destroy(bus_dma_tag_t dt, bus_dmamap_t map)
|
||||
}
|
||||
|
||||
/*
|
||||
* IOMMU DVMA operations, common to SBUS and PCI.
|
||||
* IOMMU DVMA operations, common to PCI and SBus.
|
||||
*/
|
||||
static int
|
||||
iommu_dvmamap_load_buffer(bus_dma_tag_t dt, struct iommu_state *is,
|
||||
@ -987,7 +988,7 @@ iommu_dvmamap_load(bus_dma_tag_t dt, bus_dmamap_t map, void *buf,
|
||||
|
||||
if ((map->dm_flags & DMF_LOADED) != 0) {
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("iommu_dvmamap_load: map still in use\n");
|
||||
printf("%s: map still in use\n", __func__);
|
||||
#endif
|
||||
bus_dmamap_unload(dt, map);
|
||||
}
|
||||
@ -1031,7 +1032,7 @@ iommu_dvmamap_load_mbuf(bus_dma_tag_t dt, bus_dmamap_t map, struct mbuf *m0,
|
||||
|
||||
if ((map->dm_flags & DMF_LOADED) != 0) {
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("iommu_dvmamap_load_mbuf: map still in use\n");
|
||||
printf("%s: map still in use\n", __func__);
|
||||
#endif
|
||||
bus_dmamap_unload(dt, map);
|
||||
}
|
||||
@ -1080,7 +1081,7 @@ iommu_dvmamap_load_mbuf_sg(bus_dma_tag_t dt, bus_dmamap_t map, struct mbuf *m0,
|
||||
*nsegs = -1;
|
||||
if ((map->dm_flags & DMF_LOADED) != 0) {
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("iommu_dvmamap_load_mbuf: map still in use\n");
|
||||
printf("%s: map still in use\n", __func__);
|
||||
#endif
|
||||
bus_dmamap_unload(dt, map);
|
||||
}
|
||||
@ -1125,7 +1126,7 @@ iommu_dvmamap_load_uio(bus_dma_tag_t dt, bus_dmamap_t map, struct uio *uio,
|
||||
|
||||
if ((map->dm_flags & DMF_LOADED) != 0) {
|
||||
#ifdef DIAGNOSTIC
|
||||
printf("iommu_dvmamap_load_uio: map still in use\n");
|
||||
printf("%s: map still in use\n", __func__);
|
||||
#endif
|
||||
bus_dmamap_unload(dt, map);
|
||||
}
|
||||
@ -1153,7 +1154,7 @@ iommu_dvmamap_load_uio(bus_dma_tag_t dt, bus_dmamap_t map, struct uio *uio,
|
||||
continue;
|
||||
|
||||
error = iommu_dvmamap_load_buffer(dt, is, map,
|
||||
iov[i].iov_base, minlen, td, flags, dt->dt_segments,
|
||||
iov[i].iov_base, minlen, td, flags, dt->dt_segments,
|
||||
&nsegs, first);
|
||||
first = 0;
|
||||
|
||||
@ -1205,7 +1206,7 @@ iommu_dvmamap_sync(bus_dma_tag_t dt, bus_dmamap_t map, bus_dmasync_op_t op)
|
||||
membar(Sync);
|
||||
if (IOMMU_HAS_SB(is) &&
|
||||
((op & BUS_DMASYNC_POSTREAD) != 0 ||
|
||||
(op & BUS_DMASYNC_PREWRITE) != 0)) {
|
||||
(op & BUS_DMASYNC_PREWRITE) != 0)) {
|
||||
IS_LOCK(is);
|
||||
SLIST_FOREACH(r, &map->dm_reslist, dr_link) {
|
||||
va = (vm_offset_t)BDR_START(r);
|
||||
@ -1242,7 +1243,7 @@ iommu_diag(struct iommu_state *is, vm_offset_t va)
|
||||
IS_LOCK_ASSERT(is);
|
||||
IOMMU_WRITE8(is, is_dva, 0, trunc_io_page(va));
|
||||
membar(StoreStore | StoreLoad);
|
||||
printf("iommu_diag: tte entry %#lx", IOMMU_GET_TTE(is, va));
|
||||
printf("%s: tte entry %#lx", __func__, IOMMU_GET_TTE(is, va));
|
||||
if (is->is_dtcmp != 0) {
|
||||
printf(", tag compare register is %#lx\n",
|
||||
IOMMU_READ8(is, is_dtcmp, 0));
|
||||
@ -1251,8 +1252,8 @@ iommu_diag(struct iommu_state *is, vm_offset_t va)
|
||||
for (i = 0; i < 16; i++) {
|
||||
tag = IOMMU_READ8(is, is_dtag, i * 8);
|
||||
data = IOMMU_READ8(is, is_ddram, i * 8);
|
||||
printf("iommu_diag: tag %d: %#lx, vpn %#lx, err %lx; "
|
||||
"data %#lx, pa %#lx, v %d, c %d\n", i,
|
||||
printf("%s: tag %d: %#lx, vpn %#lx, err %lx; "
|
||||
"data %#lx, pa %#lx, v %d, c %d\n", __func__, i,
|
||||
tag, (tag & IOMMU_DTAG_VPNMASK) << IOMMU_DTAG_VPNSHIFT,
|
||||
(tag & IOMMU_DTAG_ERRMASK) >> IOMMU_DTAG_ERRSHIFT, data,
|
||||
(data & IOMMU_DDATA_PGMASK) << IOMMU_DDATA_PGSHIFT,
|
||||
|
@ -1,6 +1,7 @@
|
||||
/*-
|
||||
* Copyright 1998 Massachusetts Institute of Technology
|
||||
* Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>.
|
||||
* Copyright 2006 by Marius Strobl <marius@FreeBSD.org>.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
@ -37,20 +38,20 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/cons.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/frame.h>
|
||||
#include <machine/bus_common.h>
|
||||
#include <machine/intr_machdep.h>
|
||||
#include <machine/nexusvar.h>
|
||||
#include <machine/ofw_upa.h>
|
||||
#include <machine/ofw_nexus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <machine/upa.h>
|
||||
#include <machine/ver.h>
|
||||
|
||||
#include <sys/rman.h>
|
||||
|
||||
@ -67,18 +68,9 @@ __FBSDID("$FreeBSD$");
|
||||
* work for all Open Firmware based machines...
|
||||
*/
|
||||
|
||||
static MALLOC_DEFINE(M_NEXUS, "nexus", "nexus device information");
|
||||
|
||||
struct nexus_devinfo {
|
||||
phandle_t ndi_node;
|
||||
/* Some common properties. */
|
||||
char *ndi_name;
|
||||
char *ndi_device_type;
|
||||
char *ndi_model;
|
||||
struct upa_regs *ndi_reg;
|
||||
int ndi_nreg;
|
||||
u_int *ndi_interrupts;
|
||||
int ndi_ninterrupts;
|
||||
struct ofw_bus_devinfo ndi_obdinfo;
|
||||
struct resource_list ndi_rl;
|
||||
};
|
||||
|
||||
struct nexus_softc {
|
||||
@ -88,15 +80,23 @@ struct nexus_softc {
|
||||
|
||||
static device_probe_t nexus_probe;
|
||||
static device_attach_t nexus_attach;
|
||||
static bus_print_child_t nexus_print_child;
|
||||
static bus_add_child_t nexus_add_child;
|
||||
static bus_probe_nomatch_t nexus_probe_nomatch;
|
||||
static bus_read_ivar_t nexus_read_ivar;
|
||||
static bus_setup_intr_t nexus_setup_intr;
|
||||
static bus_teardown_intr_t nexus_teardown_intr;
|
||||
static bus_alloc_resource_t nexus_alloc_resource;
|
||||
static bus_activate_resource_t nexus_activate_resource;
|
||||
static bus_deactivate_resource_t nexus_deactivate_resource;
|
||||
static bus_release_resource_t nexus_release_resource;
|
||||
static bus_get_resource_list_t nexus_get_resource_list;
|
||||
static bus_get_dma_tag_t nexus_get_dma_tag;
|
||||
static ofw_bus_get_devinfo_t nexus_get_devinfo;
|
||||
|
||||
static int nexus_inlist(const char *, const char **);
|
||||
static struct nexus_devinfo * nexus_setup_dinfo(device_t, phandle_t);
|
||||
static void nexus_destroy_dinfo(struct nexus_devinfo *);
|
||||
static int nexus_print_res(struct nexus_devinfo *);
|
||||
|
||||
static device_method_t nexus_methods[] = {
|
||||
/* Device interface */
|
||||
@ -107,44 +107,53 @@ static device_method_t nexus_methods[] = {
|
||||
DEVMETHOD(device_suspend, bus_generic_suspend),
|
||||
DEVMETHOD(device_resume, bus_generic_resume),
|
||||
|
||||
/* Bus interface. */
|
||||
DEVMETHOD(bus_add_child, nexus_add_child),
|
||||
DEVMETHOD(bus_print_child, bus_generic_print_child),
|
||||
/* Bus interface */
|
||||
DEVMETHOD(bus_print_child, nexus_print_child),
|
||||
DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch),
|
||||
DEVMETHOD(bus_read_ivar, nexus_read_ivar),
|
||||
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
|
||||
DEVMETHOD(bus_read_ivar, bus_generic_read_ivar),
|
||||
DEVMETHOD(bus_write_ivar, bus_generic_write_ivar),
|
||||
DEVMETHOD(bus_add_child, nexus_add_child),
|
||||
DEVMETHOD(bus_alloc_resource, nexus_alloc_resource),
|
||||
DEVMETHOD(bus_activate_resource, nexus_activate_resource),
|
||||
DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource),
|
||||
DEVMETHOD(bus_release_resource, nexus_release_resource),
|
||||
DEVMETHOD(bus_setup_intr, nexus_setup_intr),
|
||||
DEVMETHOD(bus_teardown_intr, nexus_teardown_intr),
|
||||
DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
|
||||
DEVMETHOD(bus_get_resource_list, nexus_get_resource_list),
|
||||
DEVMETHOD(bus_get_dma_tag, nexus_get_dma_tag),
|
||||
|
||||
/* ofw_bus interface */
|
||||
DEVMETHOD(ofw_bus_get_devinfo, nexus_get_devinfo),
|
||||
DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
|
||||
DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
|
||||
DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
|
||||
DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
|
||||
DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
|
||||
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t nexus_driver = {
|
||||
"nexus",
|
||||
nexus_methods,
|
||||
sizeof(struct nexus_softc),
|
||||
};
|
||||
|
||||
static devclass_t nexus_devclass;
|
||||
|
||||
DEFINE_CLASS_0(nexus, nexus_driver, nexus_methods, sizeof(struct nexus_softc));
|
||||
DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0);
|
||||
|
||||
static char *nexus_excl_name[] = {
|
||||
static const char *nexus_excl_name[] = {
|
||||
"aliases",
|
||||
"associations",
|
||||
"chosen",
|
||||
"counter-timer", /* No separate device; handled by psycho/sbus */
|
||||
"memory",
|
||||
"openprom",
|
||||
"options",
|
||||
"packages",
|
||||
"rsc",
|
||||
"virtual-memory",
|
||||
NULL
|
||||
};
|
||||
|
||||
static char *nexus_excl_type[] = {
|
||||
static const char *nexus_excl_type[] = {
|
||||
"cpu",
|
||||
NULL
|
||||
};
|
||||
@ -153,10 +162,12 @@ extern struct bus_space_tag nexus_bustag;
|
||||
extern struct bus_dma_tag nexus_dmatag;
|
||||
|
||||
static int
|
||||
nexus_inlist(char *name, char *list[])
|
||||
nexus_inlist(const char *name, const char **list)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (name == NULL)
|
||||
return (0);
|
||||
for (i = 0; list[i] != NULL; i++)
|
||||
if (strcmp(name, list[i]) == 0)
|
||||
return (1);
|
||||
@ -179,26 +190,25 @@ nexus_probe(device_t dev)
|
||||
static int
|
||||
nexus_attach(device_t dev)
|
||||
{
|
||||
phandle_t root;
|
||||
phandle_t child;
|
||||
device_t cdev;
|
||||
struct nexus_devinfo *dinfo;
|
||||
struct nexus_devinfo *ndi;
|
||||
struct nexus_softc *sc;
|
||||
char *name, *type;
|
||||
device_t cdev;
|
||||
phandle_t node;
|
||||
|
||||
if ((root = OF_peer(0)) == -1)
|
||||
panic("nexus_probe: OF_peer failed.");
|
||||
node = OF_peer(0);
|
||||
if (node == -1)
|
||||
panic("%s: OF_peer failed.", __func__);
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->sc_intr_rman.rm_type = RMAN_ARRAY;
|
||||
sc->sc_intr_rman.rm_descr = "Interrupts";
|
||||
sc->sc_mem_rman.rm_type = RMAN_ARRAY;
|
||||
sc->sc_mem_rman.rm_descr = "UPA Device Memory";
|
||||
sc->sc_mem_rman.rm_descr = "Device Memory";
|
||||
if (rman_init(&sc->sc_intr_rman) != 0 ||
|
||||
rman_init(&sc->sc_mem_rman) != 0 ||
|
||||
rman_manage_region(&sc->sc_intr_rman, 0, IV_MAX - 1) != 0 ||
|
||||
rman_manage_region(&sc->sc_mem_rman, UPA_MEMSTART, UPA_MEMEND) != 0)
|
||||
panic("nexus_attach(): failed to set up rmans");
|
||||
rman_manage_region(&sc->sc_mem_rman, 0ULL, ~0ULL) != 0)
|
||||
panic("%s: failed to set up rmans.", __func__);
|
||||
|
||||
/*
|
||||
* Allow devices to identify.
|
||||
@ -208,32 +218,17 @@ nexus_attach(device_t dev)
|
||||
/*
|
||||
* Now walk the OFW tree and attach top-level devices.
|
||||
*/
|
||||
for (child = OF_child(root); child != 0; child = OF_peer(child)) {
|
||||
if (child == -1)
|
||||
panic("nexus_attach(): OF_child() failed.");
|
||||
if (OF_getprop_alloc(child, "name", 1, (void **)&name) == -1)
|
||||
for (node = OF_child(node); node > 0; node = OF_peer(node)) {
|
||||
if ((ndi = nexus_setup_dinfo(dev, node)) == NULL)
|
||||
continue;
|
||||
OF_getprop_alloc(child, "device_type", 1, (void **)&type);
|
||||
if (NEXUS_EXCLUDED(name, type)) {
|
||||
free(name, M_OFWPROP);
|
||||
free(type, M_OFWPROP);
|
||||
cdev = device_add_child(dev, NULL, -1);
|
||||
if (cdev == NULL) {
|
||||
device_printf(dev, "<%s>: device_add_child failed\n",
|
||||
ndi->ndi_obdinfo.obd_name);
|
||||
nexus_destroy_dinfo(ndi);
|
||||
continue;
|
||||
}
|
||||
cdev = device_add_child(dev, NULL, -1);
|
||||
if (cdev == NULL)
|
||||
panic("nexus_attach(): device_add_child() failed.");
|
||||
dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_WAITOK);
|
||||
dinfo->ndi_node = child;
|
||||
dinfo->ndi_name = name;
|
||||
dinfo->ndi_device_type = type;
|
||||
OF_getprop_alloc(child, "model", 1,
|
||||
(void **)&dinfo->ndi_model);
|
||||
dinfo->ndi_nreg = OF_getprop_alloc(child, "reg",
|
||||
sizeof(*dinfo->ndi_reg), (void **)&dinfo->ndi_reg);
|
||||
dinfo->ndi_ninterrupts = OF_getprop_alloc(child,
|
||||
"interrupts", sizeof(*dinfo->ndi_interrupts),
|
||||
(void **)&dinfo->ndi_interrupts);
|
||||
device_set_ivars(cdev, dinfo);
|
||||
device_set_ivars(cdev, ndi);
|
||||
}
|
||||
return (bus_generic_attach(dev));
|
||||
}
|
||||
@ -242,73 +237,42 @@ static device_t
|
||||
nexus_add_child(device_t dev, int order, const char *name, int unit)
|
||||
{
|
||||
device_t cdev;
|
||||
struct nexus_devinfo *dinfo;
|
||||
struct nexus_devinfo *ndi;
|
||||
|
||||
cdev = device_add_child_ordered(dev, order, name, unit);
|
||||
if (cdev == NULL)
|
||||
return (NULL);
|
||||
|
||||
dinfo = malloc(sizeof(*dinfo), M_NEXUS, M_NOWAIT | M_ZERO);
|
||||
if (dinfo == NULL)
|
||||
return (NULL);
|
||||
|
||||
dinfo->ndi_node = -1;
|
||||
dinfo->ndi_name = strdup(name, M_OFWPROP);
|
||||
device_set_ivars(cdev, dinfo);
|
||||
ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
ndi->ndi_obdinfo.obd_node = -1;
|
||||
ndi->ndi_obdinfo.obd_name = strdup(name, M_OFWPROP);
|
||||
resource_list_init(&ndi->ndi_rl);
|
||||
device_set_ivars(cdev, ndi);
|
||||
|
||||
return (cdev);
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_print_child(device_t dev, device_t child)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = bus_print_child_header(dev, child);
|
||||
rv += nexus_print_res(device_get_ivars(child));
|
||||
rv += bus_print_child_footer(dev, child);
|
||||
return (rv);
|
||||
}
|
||||
|
||||
static void
|
||||
nexus_probe_nomatch(device_t dev, device_t child)
|
||||
{
|
||||
char *type;
|
||||
const char *type;
|
||||
|
||||
if ((type = nexus_get_device_type(child)) == NULL)
|
||||
type = "(unknown)";
|
||||
device_printf(dev, "<%s>, type %s (no driver attached)\n",
|
||||
nexus_get_name(child), type);
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
|
||||
{
|
||||
struct nexus_devinfo *dinfo;
|
||||
|
||||
if ((dinfo = device_get_ivars(child)) == 0)
|
||||
return (ENOENT);
|
||||
switch (which) {
|
||||
case NEXUS_IVAR_NODE:
|
||||
*result = dinfo->ndi_node;
|
||||
break;
|
||||
case NEXUS_IVAR_NAME:
|
||||
*result = (uintptr_t)dinfo->ndi_name;
|
||||
break;
|
||||
case NEXUS_IVAR_DEVICE_TYPE:
|
||||
*result = (uintptr_t)dinfo->ndi_device_type;
|
||||
break;
|
||||
case NEXUS_IVAR_MODEL:
|
||||
*result = (uintptr_t)dinfo->ndi_model;
|
||||
break;
|
||||
case NEXUS_IVAR_REG:
|
||||
*result = (uintptr_t)dinfo->ndi_reg;
|
||||
break;
|
||||
case NEXUS_IVAR_NREG:
|
||||
*result = dinfo->ndi_nreg;
|
||||
break;
|
||||
case NEXUS_IVAR_INTERRUPTS:
|
||||
*result = (uintptr_t)dinfo->ndi_interrupts;
|
||||
break;
|
||||
case NEXUS_IVAR_NINTERRUPTS:
|
||||
*result = dinfo->ndi_ninterrupts;
|
||||
break;
|
||||
case NEXUS_IVAR_DMATAG:
|
||||
*result = (uintptr_t)&nexus_dmatag;
|
||||
break;
|
||||
default:
|
||||
return (ENOENT);
|
||||
}
|
||||
return 0;
|
||||
device_printf(dev, "<%s>", ofw_bus_get_name(child));
|
||||
nexus_print_res(device_get_ivars(child));
|
||||
type = ofw_bus_get_type(child);
|
||||
printf(" type %s (no driver attached)\n",
|
||||
type != NULL ? type : "unknown");
|
||||
}
|
||||
|
||||
static int
|
||||
@ -318,7 +282,7 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
|
||||
int error;
|
||||
|
||||
if (res == NULL)
|
||||
panic("nexus_setup_intr: NULL interrupt resource!");
|
||||
panic("%s: NULL interrupt resource!", __func__);
|
||||
|
||||
if ((rman_get_flags(res) & RF_SHAREABLE) == 0)
|
||||
flags |= INTR_EXCL;
|
||||
@ -331,6 +295,11 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags,
|
||||
error = inthand_add(device_get_nameunit(child), rman_get_start(res),
|
||||
filt, intr, arg, flags, cookiep);
|
||||
|
||||
/*
|
||||
* XXX in case of the AFB/FFB interrupt and a Psycho, Sabre or U2S
|
||||
* bridge enable the interrupt in the respective bridge.
|
||||
*/
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
@ -346,12 +315,31 @@ static struct resource *
|
||||
nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
u_long start, u_long end, u_long count, u_int flags)
|
||||
{
|
||||
struct nexus_softc *sc = device_get_softc(bus);
|
||||
struct resource *rv;
|
||||
struct rman *rm;
|
||||
int needactivate = flags & RF_ACTIVE;
|
||||
struct nexus_softc *sc;
|
||||
struct rman *rm;
|
||||
struct resource *rv;
|
||||
struct resource_list_entry *rle;
|
||||
int isdefault, needactivate, passthrough;
|
||||
|
||||
flags &= ~RF_ACTIVE;
|
||||
isdefault = (start == 0UL && end == ~0UL);
|
||||
needactivate = flags & RF_ACTIVE;
|
||||
passthrough = (device_get_parent(child) != bus);
|
||||
sc = device_get_softc(bus);
|
||||
rle = NULL;
|
||||
|
||||
if (!passthrough) {
|
||||
rle = resource_list_find(BUS_GET_RESOURCE_LIST(bus, child),
|
||||
type, *rid);
|
||||
if (rle == NULL)
|
||||
return (NULL);
|
||||
if (rle->res != NULL)
|
||||
panic("%s: resource entry is busy", __func__);
|
||||
if (isdefault) {
|
||||
start = rle->start;
|
||||
count = ulmax(count, rle->count);
|
||||
end = ulmax(rle->end, start + count - 1);
|
||||
}
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SYS_RES_IRQ:
|
||||
@ -364,6 +352,7 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
flags &= ~RF_ACTIVE;
|
||||
rv = rman_reserve_resource(rm, start, end, count, flags, child);
|
||||
if (rv == NULL)
|
||||
return (NULL);
|
||||
@ -380,6 +369,13 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
|
||||
}
|
||||
}
|
||||
|
||||
if (!passthrough) {
|
||||
rle->res = rv;
|
||||
rle->start = rman_get_start(rv);
|
||||
rle->end = rman_get_end(rv);
|
||||
rle->count = rle->end - rle->start + 1;
|
||||
}
|
||||
|
||||
return (rv);
|
||||
}
|
||||
|
||||
@ -403,7 +399,7 @@ nexus_deactivate_resource(device_t bus, device_t child, int type, int rid,
|
||||
|
||||
static int
|
||||
nexus_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
struct resource *r)
|
||||
struct resource *r)
|
||||
{
|
||||
int error;
|
||||
|
||||
@ -414,3 +410,117 @@ nexus_release_resource(device_t bus, device_t child, int type, int rid,
|
||||
}
|
||||
return (rman_release_resource(r));
|
||||
}
|
||||
|
||||
static struct resource_list *
|
||||
nexus_get_resource_list(device_t dev, device_t child)
|
||||
{
|
||||
struct nexus_devinfo *ndi;
|
||||
|
||||
ndi = device_get_ivars(child);
|
||||
return (&ndi->ndi_rl);
|
||||
}
|
||||
|
||||
static bus_dma_tag_t
|
||||
nexus_get_dma_tag(device_t bus, device_t child)
|
||||
{
|
||||
|
||||
return (&nexus_dmatag);
|
||||
}
|
||||
|
||||
static const struct ofw_bus_devinfo *
|
||||
nexus_get_devinfo(device_t dev, device_t child)
|
||||
{
|
||||
struct nexus_devinfo *ndi;
|
||||
|
||||
ndi = device_get_ivars(child);
|
||||
return (&ndi->ndi_obdinfo);
|
||||
}
|
||||
|
||||
static struct nexus_devinfo *
|
||||
nexus_setup_dinfo(device_t dev, phandle_t node)
|
||||
{
|
||||
struct nexus_devinfo *ndi;
|
||||
struct nexus_regs *reg;
|
||||
bus_addr_t phys;
|
||||
bus_size_t size;
|
||||
uint32_t ign;
|
||||
uint32_t *intr;
|
||||
int i;
|
||||
int nintr;
|
||||
int nreg;
|
||||
|
||||
ndi = malloc(sizeof(*ndi), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
if (ofw_bus_gen_setup_devinfo(&ndi->ndi_obdinfo, node) != 0) {
|
||||
free(ndi, M_DEVBUF);
|
||||
return (NULL);
|
||||
}
|
||||
if (NEXUS_EXCLUDED(ndi->ndi_obdinfo.obd_name,
|
||||
ndi->ndi_obdinfo.obd_type)) {
|
||||
ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
|
||||
free(ndi, M_DEVBUF);
|
||||
return (NULL);
|
||||
}
|
||||
resource_list_init(&ndi->ndi_rl);
|
||||
nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)®);
|
||||
if (nreg == -1) {
|
||||
device_printf(dev, "<%s>: incomplete\n",
|
||||
ndi->ndi_obdinfo.obd_name);
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < nreg; i++) {
|
||||
phys = NEXUS_REG_PHYS(®[i]);
|
||||
size = NEXUS_REG_SIZE(®[i]);
|
||||
resource_list_add(&ndi->ndi_rl, SYS_RES_MEMORY, i, phys,
|
||||
phys + size - 1, size);
|
||||
}
|
||||
free(reg, M_OFWPROP);
|
||||
|
||||
nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intr),
|
||||
(void **)&intr);
|
||||
if (nintr > 0) {
|
||||
if (OF_getprop(node, cpu_impl < CPU_IMPL_ULTRASPARCIII ?
|
||||
"upa-portid" : "portid", &ign, sizeof(ign)) <= 0) {
|
||||
device_printf(dev, "<%s>: could not determine portid\n",
|
||||
ndi->ndi_obdinfo.obd_name);
|
||||
free(intr, M_OFWPROP);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* XXX 7-bit MID on Starfire */
|
||||
ign = (ign << INTMAP_IGN_SHIFT) & INTMAP_IGN_MASK;
|
||||
for (i = 0; i < nintr; i++) {
|
||||
intr[i] |= ign;
|
||||
resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i],
|
||||
intr[i], 1);
|
||||
}
|
||||
free(intr, M_OFWPROP);
|
||||
}
|
||||
|
||||
return (ndi);
|
||||
|
||||
fail:
|
||||
nexus_destroy_dinfo(ndi);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
nexus_destroy_dinfo(struct nexus_devinfo *ndi)
|
||||
{
|
||||
|
||||
resource_list_free(&ndi->ndi_rl);
|
||||
ofw_bus_gen_destroy_devinfo(&ndi->ndi_obdinfo);
|
||||
free(ndi, M_DEVBUF);
|
||||
}
|
||||
|
||||
static int
|
||||
nexus_print_res(struct nexus_devinfo *ndi)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = 0;
|
||||
rv += resource_list_print_type(&ndi->ndi_rl, "mem", SYS_RES_MEMORY,
|
||||
"%#lx");
|
||||
rv += resource_list_print_type(&ndi->ndi_rl, "irq", SYS_RES_IRQ,
|
||||
"%ld");
|
||||
return (rv);
|
||||
}
|
||||
|
@ -36,10 +36,9 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/limits.h>
|
||||
#include <sys/module.h>
|
||||
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/nexusvar.h>
|
||||
|
||||
#include <dev/syscons/syscons.h>
|
||||
|
||||
@ -88,7 +87,7 @@ sc_probe(device_t dev)
|
||||
int unit;
|
||||
|
||||
unit = device_get_unit(dev);
|
||||
if (strcmp(nexus_get_name(dev), SC_DRIVER_NAME) != 0 ||
|
||||
if (strcmp(ofw_bus_get_name(dev), SC_DRIVER_NAME) != 0 ||
|
||||
unit >= SC_MD_MAX)
|
||||
return (ENXIO);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user