From f31f435513a72bd9462d2c1602f1a1f023f17497 Mon Sep 17 00:00:00 2001 From: grehan Date: Tue, 13 Jan 2004 11:24:36 +0000 Subject: Make the OpenPic driver bus-independent, with attachments for the MacIO chip and PSIM's IOBus. Bus-specific drivers should use the identify method to attach themselves to nexus so interrupt can be allocated before the h/w is probed. The 'early attach' routine in openpic is used for this stage of boot. When h/w is probed, the openpic can be attached properly. It will enable interrupts allocated prior to this. --- sys/powerpc/include/openpicvar.h | 30 ++++- sys/powerpc/powermac/openpic_macio.c | 231 +++++++++++++++++++++++++++++++++ sys/powerpc/powerpc/openpic.c | 241 ++++++++++++----------------------- sys/powerpc/psim/openpic_iobus.c | 219 +++++++++++++++++++++++++++++++ 4 files changed, 557 insertions(+), 164 deletions(-) create mode 100644 sys/powerpc/powermac/openpic_macio.c create mode 100644 sys/powerpc/psim/openpic_iobus.c (limited to 'sys/powerpc') diff --git a/sys/powerpc/include/openpicvar.h b/sys/powerpc/include/openpicvar.h index 6f7cff6..5001b9b 100644 --- a/sys/powerpc/include/openpicvar.h +++ b/sys/powerpc/include/openpicvar.h @@ -28,13 +28,41 @@ #ifndef _POWERPC_OPENPICVAR_H_ #define _POWERPC_OPENPICVAR_H_ +#define OPENPIC_DEVSTR "OpenPIC Interrupt Controller" + +#define OPENPIC_IRQMAX 256 /* h/w allows more */ + struct openpic_softc { - vm_offset_t sc_base; char *sc_version; u_int sc_ncpu; u_int sc_nirq; int sc_psim; struct rman sc_rman; + bus_space_tag_t sc_bt; + bus_space_handle_t sc_bh; + u_int sc_hwprobed; + u_int sc_early_done; + device_t sc_altdev; + u_char sc_irqrsv[OPENPIC_IRQMAX]; /* pre-h/w reservation */ }; +/* + * Bus-independent attach i/f + */ +int openpic_early_attach(device_t); +int openpic_attach(device_t); + +/* + * PIC interface. + */ +struct resource *openpic_allocate_intr(device_t, device_t, int *, + u_long, u_int); +int openpic_setup_intr(device_t, device_t, + struct resource *, int, driver_intr_t, void *, + void **); +int openpic_teardown_intr(device_t, device_t, + struct resource *, void *); +int openpic_release_intr(device_t dev, device_t, int, + struct resource *res); + #endif /* _POWERPC_OPENPICVAR_H_ */ diff --git a/sys/powerpc/powermac/openpic_macio.c b/sys/powerpc/powermac/openpic_macio.c new file mode 100644 index 0000000..832a043 --- /dev/null +++ b/sys/powerpc/powermac/openpic_macio.c @@ -0,0 +1,231 @@ +/* + * Copyright 2003 by Peter Grehan. 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. + * + */ + +/* + * The macio attachment for the OpenPIC interrupt controller. + * A nexus driver is defined so the number of interrupts can be + * determined early in the boot sequence before the hardware + * is accessed - the interrupt i/f is installed at this time, + * and when h/w is finally accessed, interrupt sources allocated + * prior to this are activated + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include "pic_if.h" + +struct openpic_ofw_softc { + struct openpic_softc osc; + struct resource *sc_memr; /* macio bus resource */ + device_t sc_ndev; /* nexus device */ +}; + +static struct openpic_ofw_softc *ofwpicsoftc; + +/* + * MacIO interface + */ +static void openpic_ofw_identify(driver_t *, device_t); +static int openpic_ofw_probe(device_t); +static int openpic_ofw_attach(device_t); +static int openpic_macio_probe(device_t); +static int openpic_macio_attach(device_t); + +/* + * Nexus attachment + */ +static device_method_t openpic_ofw_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, openpic_ofw_identify), + DEVMETHOD(device_probe, openpic_ofw_probe), + DEVMETHOD(device_attach, openpic_ofw_attach), + + /* PIC interface */ + DEVMETHOD(pic_allocate_intr, openpic_allocate_intr), + DEVMETHOD(pic_setup_intr, openpic_setup_intr), + DEVMETHOD(pic_teardown_intr, openpic_teardown_intr), + DEVMETHOD(pic_release_intr, openpic_release_intr), + + { 0, 0 } +}; + +static driver_t openpic_ofw_driver = { + "openpic", + openpic_ofw_methods, + sizeof(struct openpic_ofw_softc) +}; + +static devclass_t openpic_ofw_devclass; + +DRIVER_MODULE(openpic_ofw, nexus, openpic_ofw_driver, openpic_ofw_devclass, + 0, 0); + +static void +openpic_ofw_identify(driver_t *driver, device_t parent) +{ + device_t child; + phandle_t chosen, pic; + char type[40]; + + chosen = OF_finddevice("/chosen"); + if (chosen == -1) + return; + + if (OF_getprop(chosen, "interrupt-controller", &pic, 4) != 4) + return; + + OF_getprop(pic, "device_type", type, sizeof(type)); + + if (strcmp(type, "open-pic") != 0) + return; + + child = BUS_ADD_CHILD(parent, 0, "openpic", 0); + if (child != NULL) + nexus_set_device_type(child, "macio"); +} + +static int +openpic_ofw_probe(device_t dev) +{ + char *name; + char *type; + + name = nexus_get_name(dev); + type = nexus_get_device_type(dev); + + if (strcmp(name, "openpic") != 0 || + strcmp(type, "macio") != 0) + return (ENXIO); + + device_set_desc(dev, OPENPIC_DEVSTR); + return (0); +} + +static int +openpic_ofw_attach(device_t dev) +{ + KASSERT(ofwpicsoftc == NULL, ("ofw openpic: already probed")); + ofwpicsoftc = device_get_softc(dev); + ofwpicsoftc->sc_ndev = dev; + + nexus_install_intcntlr(dev); + openpic_early_attach(dev); + return (0); +} + +/* + * MacIO attachment + */ +static device_method_t openpic_macio_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, openpic_macio_probe), + DEVMETHOD(device_attach, openpic_macio_attach), + + { 0, 0 }, +}; + +static driver_t openpic_macio_driver = { + "openpicmacio", + openpic_macio_methods, + 0 +}; + +static devclass_t openpic_macio_devclass; + +DRIVER_MODULE(openpicmacio, macio, openpic_macio_driver, + openpic_macio_devclass, 0, 0); + +static int +openpic_macio_probe(device_t dev) +{ + char *type = macio_get_devtype(dev); + + if (strcmp(type, "open-pic") != 0) + return (ENXIO); + + /* + * The description was already printed out in the nexus + * probe, so don't do it again here + */ + device_set_desc(dev, "OpenPIC MacIO interrupt cell"); + if (!bootverbose) + device_quiet(dev); + return (0); +} + +static int +openpic_macio_attach(device_t dev) +{ + struct openpic_ofw_softc *sc; + int rid; + + sc = ofwpicsoftc; + KASSERT(sc != NULL, ("pic not nexus-probed\n")); + + rid = 0; + sc->sc_memr = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, + RF_ACTIVE); + + if (sc->sc_memr == NULL) { + device_printf(dev, "Could not alloc mem resource!\n"); + return (ENXIO); + } + + sc->osc.sc_bt = rman_get_bustag(sc->sc_memr); + sc->osc.sc_bh = rman_get_bushandle(sc->sc_memr); + sc->osc.sc_altdev = dev; + + return (openpic_attach(sc->sc_ndev)); +} + + diff --git a/sys/powerpc/powerpc/openpic.c b/sys/powerpc/powerpc/openpic.c index 864fae4..cd44cff 100644 --- a/sys/powerpc/powerpc/openpic.c +++ b/sys/powerpc/powerpc/openpic.c @@ -31,17 +31,10 @@ #include #include -#include -#include - -#include -#include - #include #include #include #include -#include #include #include @@ -56,25 +49,6 @@ #include "pic_if.h" /* - * Device interface. - */ -static int openpic_probe(device_t); -static int openpic_attach(device_t); - -/* - * PIC interface. - */ -static struct resource *openpic_allocate_intr(device_t, device_t, int *, - u_long, u_int); -static int openpic_setup_intr(device_t, device_t, - struct resource *, int, driver_intr_t, void *, - void **); -static int openpic_teardown_intr(device_t, device_t, - struct resource *, void *); -static int openpic_release_intr(device_t dev, device_t, int, - struct resource *res); - -/* * Local routines */ static u_int openpic_read(struct openpic_softc *, int); @@ -85,89 +59,56 @@ static void openpic_enable_irq(struct openpic_softc *, int, int); static void openpic_disable_irq(struct openpic_softc *, int); static void openpic_set_priority(struct openpic_softc *, int, int); static void openpic_intr(void); -static void irq_enable(uintptr_t); -static void irq_disable(uintptr_t); +static void openpic_ext_enable_irq(uintptr_t); +static void openpic_ext_disable_irq(uintptr_t); + +/* XXX This limits us to one openpic */ +static struct openpic_softc *openpic_softc; /* - * Driver methods. + * Called at nexus-probe time to allow interrupts to be enabled by + * devices that are probed before the OpenPIC h/w is probed. */ -static device_method_t openpic_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, openpic_probe), - DEVMETHOD(device_attach, openpic_attach), - - /* PIC interface */ - DEVMETHOD(pic_allocate_intr, openpic_allocate_intr), - DEVMETHOD(pic_setup_intr, openpic_setup_intr), - DEVMETHOD(pic_teardown_intr, openpic_teardown_intr), - DEVMETHOD(pic_release_intr, openpic_release_intr), +int +openpic_early_attach(device_t dev) +{ + struct openpic_softc *sc; - { 0, 0 } -}; + sc = device_get_softc(dev); + openpic_softc = sc; -static driver_t openpic_driver = { - "openpic", - openpic_methods, - sizeof(struct openpic_softc) -}; + sc->sc_rman.rm_type = RMAN_ARRAY; + sc->sc_rman.rm_descr = device_get_nameunit(dev); -static devclass_t openpic_devclass; + if (rman_init(&sc->sc_rman) != 0 || + rman_manage_region(&sc->sc_rman, 0, OPENPIC_IRQMAX-1) != 0) { + device_printf(dev, "could not set up resource management"); + return (ENXIO); + } -DRIVER_MODULE(openpic, nexus, openpic_driver, openpic_devclass, 0, 0); + intr_init(openpic_intr, OPENPIC_IRQMAX, openpic_ext_enable_irq, + openpic_ext_disable_irq); -static struct openpic_softc *softc; /* XXX This limits us to one openpic */ + sc->sc_early_done = 1; -/* - * Device interface - */ + return (0); +} -static int -openpic_probe(device_t dev) +int +openpic_attach(device_t dev) { - struct openpic_softc *sc; - phandle_t node, parent; - char *type; - char *compat; - u_int32_t reg[5], val; - vm_offset_t macio_base; - vm_offset_t opic_base; - - sc = device_get_softc(dev); - node = nexus_get_node(dev); - type = nexus_get_device_type(dev); - compat = nexus_get_compatible(dev); - - if (type == NULL) - return (ENXIO); - - if (strcmp(type, "open-pic") != 0) - return (ENXIO); + struct openpic_softc *sc; + u_int irq; + u_int32_t x; - if (strcmp(compat, "psim,open-pic") == 0) { - sc->sc_psim = 1; - - if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8) - return (ENXIO); - - opic_base = reg[1]; - } else { - parent = OF_parent(node); - if (OF_getprop(parent, "assigned-addresses", - reg, sizeof(reg)) < 20) - return (ENXIO); - - macio_base = (vm_offset_t)reg[2]; - - if (OF_getprop(node, "reg", reg, sizeof(reg)) < 8) - return (ENXIO); - - opic_base = macio_base + reg[0]; - } + sc = device_get_softc(dev); + sc->sc_hwprobed = 1; - sc->sc_base = (vm_offset_t)pmap_mapdev(opic_base, OPENPIC_SIZE); + if (!sc->sc_early_done) + openpic_early_attach(dev); - val = openpic_read(sc, OPENPIC_FEATURE); - switch (val & OPENPIC_FEATURE_VERSION_MASK) { + x = openpic_read(sc, OPENPIC_FEATURE); + switch (x & OPENPIC_FEATURE_VERSION_MASK) { case 1: sc->sc_version = "1.0"; break; @@ -182,9 +123,9 @@ openpic_probe(device_t dev) break; } - sc->sc_ncpu = ((val & OPENPIC_FEATURE_LAST_CPU_MASK) >> + sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >> OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1; - sc->sc_nirq = ((val & OPENPIC_FEATURE_LAST_IRQ_MASK) >> + sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >> OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1; /* @@ -193,31 +134,10 @@ openpic_probe(device_t dev) if (sc->sc_psim) sc->sc_nirq--; - device_set_desc(dev, "OpenPIC interrupt controller"); - return (0); -} - -static int -openpic_attach(device_t dev) -{ - struct openpic_softc *sc; - u_int32_t irq, x; - - sc = device_get_softc(dev); - softc = sc; - - device_printf(dev, - "Version %s, supports %d CPUs and %d irqs\n", - sc->sc_version, sc->sc_ncpu, sc->sc_nirq); - - sc->sc_rman.rm_type = RMAN_ARRAY; - sc->sc_rman.rm_descr = device_get_nameunit(dev); - - if (rman_init(&sc->sc_rman) != 0 || - rman_manage_region(&sc->sc_rman, 0, sc->sc_nirq - 1) != 0) { - device_printf(dev, "could not set up resource management"); - return (ENXIO); - } + if (bootverbose) + device_printf(dev, + "Version %s, supports %d CPUs and %d irqs\n", + sc->sc_version, sc->sc_ncpu, sc->sc_nirq); /* disable all interrupts */ for (irq = 0; irq < sc->sc_nirq; irq++) @@ -254,10 +174,12 @@ openpic_attach(device_t dev) openpic_eoi(sc, 0); } + /* enable pre-h/w reserved irqs, disable all others */ for (irq = 0; irq < sc->sc_nirq; irq++) - openpic_disable_irq(sc, irq); - - intr_init(openpic_intr, sc->sc_nirq, irq_enable, irq_disable); + if (sc->sc_irqrsv[irq]) + openpic_enable_irq(sc, irq, IST_LEVEL); + else + openpic_disable_irq(sc, irq); return (0); } @@ -266,7 +188,7 @@ openpic_attach(device_t dev) * PIC interface */ -static struct resource * +struct resource * openpic_allocate_intr(device_t dev, device_t child, int *rid, u_long intr, u_int flags) { @@ -278,6 +200,12 @@ openpic_allocate_intr(device_t dev, device_t child, int *rid, u_long intr, needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; + if (sc->sc_hwprobed && (intr > sc->sc_nirq)) { + device_printf(dev, "interrupt reservation %ld out of range\n", + intr); + return (NULL); + } + rv = rman_reserve_resource(&sc->sc_rman, intr, intr, 1, flags, child); if (rv == NULL) { device_printf(dev, "interrupt reservation failed for %s\n", @@ -298,7 +226,7 @@ openpic_allocate_intr(device_t dev, device_t child, int *rid, u_long intr, return (rv); } -static int +int openpic_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_intr_t *intr, void *arg, void **cookiep) { @@ -325,12 +253,16 @@ openpic_setup_intr(device_t dev, device_t child, struct resource *res, error = inthand_add(device_get_nameunit(child), res->r_start, intr, arg, flags, cookiep); - openpic_enable_irq(sc, res->r_start, IST_LEVEL); + + if (sc->sc_hwprobed) + openpic_enable_irq(sc, res->r_start, IST_LEVEL); + else + sc->sc_irqrsv[res->r_start] = 1; return (error); } -static int +int openpic_teardown_intr(device_t dev, device_t child, struct resource *res, void *ih) { @@ -345,7 +277,7 @@ openpic_teardown_intr(device_t dev, device_t child, struct resource *res, return (error); } -static int +int openpic_release_intr(device_t dev, device_t child, int rid, struct resource *res) { @@ -367,29 +299,13 @@ openpic_release_intr(device_t dev, device_t child, int rid, static u_int openpic_read(struct openpic_softc *sc, int reg) { - volatile unsigned char *addr; - - addr = (unsigned char *)sc->sc_base + reg; -#if 0 - printf("openpic: reading from %p (0x%08x + 0x%08x)\n", addr, - sc->sc_base, reg); -#endif - - return in32rb(addr); + return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg)); } static void openpic_write(struct openpic_softc *sc, int reg, u_int val) { - volatile unsigned char *addr; - - addr = (unsigned char *)sc->sc_base + reg; -#if 0 - printf("openpic: writing to %p (0x%08x + 0x%08x)\n", addr, sc->sc_base, - reg); -#endif - - out32rb(addr, val); + bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val); } static int @@ -402,13 +318,6 @@ static void openpic_eoi(struct openpic_softc *sc, int cpu) { openpic_write(sc, OPENPIC_EOI(cpu), 0); - if (!sc->sc_psim) { - /* - * Probably not needed, since appropriate eieio/sync - * is done in out32rb. See Darwin src. - */ - openpic_read(sc, OPENPIC_EOI(cpu)); - } } static void @@ -449,18 +358,20 @@ openpic_set_priority(struct openpic_softc *sc, int cpu, int pri) static void openpic_intr(void) { + struct openpic_softc *sc; int irq; u_int32_t msr; + sc = openpic_softc; msr = mfmsr(); - irq = openpic_read_irq(softc, 0); + irq = openpic_read_irq(sc, 0); if (irq == 255) { return; } start: - openpic_disable_irq(softc, irq); + openpic_disable_irq(sc, irq); /*mtmsr(msr | PSL_EE);*/ /* do the interrupt thang */ @@ -468,23 +379,27 @@ start: mtmsr(msr); - openpic_eoi(softc, 0); + openpic_eoi(sc, 0); - irq = openpic_read_irq(softc, 0); + irq = openpic_read_irq(sc, 0); if (irq != 255) goto start; } static void -irq_enable(uintptr_t irq) +openpic_ext_enable_irq(uintptr_t irq) { + if (!openpic_softc->sc_hwprobed) + return; - openpic_enable_irq(softc, irq, IST_LEVEL); + openpic_enable_irq(openpic_softc, irq, IST_LEVEL); } static void -irq_disable(uintptr_t irq) +openpic_ext_disable_irq(uintptr_t irq) { + if (!openpic_softc->sc_hwprobed) + return; - openpic_disable_irq(softc, irq); + openpic_disable_irq(openpic_softc, irq); } diff --git a/sys/powerpc/psim/openpic_iobus.c b/sys/powerpc/psim/openpic_iobus.c new file mode 100644 index 0000000..5bbeb14 --- /dev/null +++ b/sys/powerpc/psim/openpic_iobus.c @@ -0,0 +1,219 @@ +/* + * Copyright 2003 by Peter Grehan. 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. + * + */ + +/* + * The psim iobus attachment for the OpenPIC interrupt controller. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include + +#include +#include + +#include "pic_if.h" + +struct openpic_iobus_softc { + struct openpic_softc osc; + struct resource *sc_memr; /* iobus mem resource */ + device_t sc_ndev; /* nexus device */ +}; + +static struct openpic_iobus_softc *ppicsoftc; + +/* + * MacIO interface + */ +static void openpic_psim_identify(driver_t *, device_t); +static int openpic_psim_probe(device_t); +static int openpic_psim_attach(device_t); +static int openpic_iobus_probe(device_t); +static int openpic_iobus_attach(device_t); + +/* + * Nexus attachment + */ +static device_method_t openpic_psim_methods[] = { + /* Device interface */ + DEVMETHOD(device_identify, openpic_psim_identify), + DEVMETHOD(device_probe, openpic_psim_probe), + DEVMETHOD(device_attach, openpic_psim_attach), + + /* PIC interface */ + DEVMETHOD(pic_allocate_intr, openpic_allocate_intr), + DEVMETHOD(pic_setup_intr, openpic_setup_intr), + DEVMETHOD(pic_teardown_intr, openpic_teardown_intr), + DEVMETHOD(pic_release_intr, openpic_release_intr), + + { 0, 0 } +}; + +static driver_t openpic_psim_driver = { + "openpic", + openpic_psim_methods, + sizeof(struct openpic_iobus_softc) +}; + +static devclass_t openpic_psim_devclass; + +DRIVER_MODULE(openpic_psim, nexus, openpic_psim_driver, openpic_psim_devclass, + 0, 0); + +static void +openpic_psim_identify(driver_t *driver, device_t parent) +{ + device_t child; + phandle_t pic; + + pic = OF_finddevice("/iobus/opic"); + if (pic == -1) + return; + + child = BUS_ADD_CHILD(parent, 0, "openpic", 0); + if (child != NULL) + nexus_set_device_type(child, "psim"); +} + +static int +openpic_psim_probe(device_t dev) +{ + char *name; + char *type; + + name = nexus_get_name(dev); + type = nexus_get_device_type(dev); + + if (strcmp(name, "openpic") != 0 || + strcmp(type, "psim") != 0) + return (ENXIO); + + device_set_desc(dev, OPENPIC_DEVSTR); + return (0); +} + +static int +openpic_psim_attach(device_t dev) +{ + KASSERT(ppicsoftc == NULL, ("iobus openpic: already probed")); + ppicsoftc = device_get_softc(dev); + ppicsoftc->sc_ndev = dev; + + nexus_install_intcntlr(dev); + openpic_early_attach(dev); + return (0); +} + +/* + * PSIM IOBus attachment + */ +static device_method_t openpic_iobus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, openpic_iobus_probe), + DEVMETHOD(device_attach, openpic_iobus_attach), + + { 0, 0 }, +}; + +static driver_t openpic_iobus_driver = { + "openpiciobus", + openpic_iobus_methods, + 0 +}; + +static devclass_t openpic_iobus_devclass; + +DRIVER_MODULE(openpiciobus, iobus, openpic_iobus_driver, + openpic_iobus_devclass, 0, 0); + +static int +openpic_iobus_probe(device_t dev) +{ + char *name; + + name = iobus_get_name(dev); + if (strcmp(name, "interrupt-controller") != 0) + return (ENXIO); + + /* + * The description was already printed out in the nexus + * probe, so don't do it again here + */ + device_set_desc(dev, "OpenPIC IOBus interrupt cell"); + if (!bootverbose) + device_quiet(dev); + return (0); +} + +static int +openpic_iobus_attach(device_t dev) +{ + struct openpic_iobus_softc *sc; + int rid; + + sc = ppicsoftc; + KASSERT(sc != NULL, ("pic not nexus-probed\n")); + + rid = 0; + sc->sc_memr = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0, 1, + RF_ACTIVE); + + if (sc->sc_memr == NULL) { + device_printf(dev, "Could not alloc mem resource!\n"); + return (ENXIO); + } + + sc->osc.sc_psim = 1; + sc->osc.sc_bt = rman_get_bustag(sc->sc_memr); + sc->osc.sc_bh = rman_get_bushandle(sc->sc_memr); + sc->osc.sc_altdev = dev; + + return (openpic_attach(sc->sc_ndev)); +} + + -- cgit v1.1