Index: head/sys/powerpc/include/intr_machdep.h =================================================================== --- head/sys/powerpc/include/intr_machdep.h (revision 218074) +++ head/sys/powerpc/include/intr_machdep.h (revision 218075) @@ -1,64 +1,60 @@ /*- * Copyright (C) 2002 Benno Rice. * 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 Benno Rice ``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 TOOLS GMBH 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_INTR_MACHDEP_H_ #define _MACHINE_INTR_MACHDEP_H_ #define INTR_VECTORS 256 -#define MAX_PICS 5 -#define IGN_SHIFT 8 -#define INTR_INTLINE(irq) (irq & ((1 << IGN_SHIFT) - 1)) -#define INTR_IGN(irq) (irq >> IGN_SHIFT) +#define MAX_PICS 5 +#define INTR_VEC(node, pin) powerpc_get_irq(node, pin) -#define INTR_VEC(pic_id, irq) ((powerpc_ign_lookup(pic_id) << IGN_SHIFT) | (irq)) - /* * Default base address for MSI messages on PowerPC */ #define MSI_INTEL_ADDR_BASE 0xfee00000 extern device_t root_pic; struct trapframe; driver_filter_t powerpc_ipi_handler; void intrcnt_add(const char *name, u_long **countp); -void powerpc_register_pic(device_t, u_int); -int powerpc_ign_lookup(uint32_t pic_id); +void powerpc_register_pic(device_t, uint32_t, u_int, u_int, u_int); +u_int powerpc_get_irq(uint32_t, u_int); void powerpc_dispatch_intr(u_int, struct trapframe *); int powerpc_enable_intr(void); int powerpc_setup_intr(const char *, u_int, driver_filter_t, driver_intr_t, void *, enum intr_type, void **); int powerpc_teardown_intr(void *); int powerpc_bind_intr(u_int irq, u_char cpu); int powerpc_config_intr(int, enum intr_trigger, enum intr_polarity); #endif /* _MACHINE_INTR_MACHDEP_H_ */ Index: head/sys/powerpc/include/openpicvar.h =================================================================== --- head/sys/powerpc/include/openpicvar.h (revision 218074) +++ head/sys/powerpc/include/openpicvar.h (revision 218075) @@ -1,69 +1,69 @@ /*- * Copyright (C) 2002 Benno Rice. * 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 Benno Rice ``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 TOOLS GMBH 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 _POWERPC_OPENPICVAR_H_ #define _POWERPC_OPENPICVAR_H_ #define OPENPIC_DEVSTR "OpenPIC Interrupt Controller" #define OPENPIC_IRQMAX 256 /* h/w allows more */ struct openpic_softc { device_t sc_dev; struct resource *sc_memr; struct resource *sc_intr; bus_space_tag_t sc_bt; bus_space_handle_t sc_bh; char *sc_version; int sc_rid; int sc_irq; void *sc_icookie; u_int sc_ncpu; u_int sc_nirq; int sc_psim; }; extern devclass_t openpic_devclass; /* * Bus-independent attach i/f */ -int openpic_attach(device_t); +int openpic_common_attach(device_t, uint32_t); /* * PIC interface. */ void openpic_bind(device_t dev, u_int irq, cpumask_t cpumask); void openpic_config(device_t, u_int, enum intr_trigger, enum intr_polarity); void openpic_dispatch(device_t, struct trapframe *); void openpic_enable(device_t, u_int, u_int); void openpic_eoi(device_t, u_int); void openpic_ipi(device_t, u_int); void openpic_mask(device_t, u_int); void openpic_unmask(device_t, u_int); #endif /* _POWERPC_OPENPICVAR_H_ */ Index: head/sys/powerpc/mambo/mambo_openpic.c =================================================================== --- head/sys/powerpc/mambo/mambo_openpic.c (revision 218074) +++ head/sys/powerpc/mambo/mambo_openpic.c (revision 218075) @@ -1,180 +1,179 @@ /*- * Copyright 2008 by Nathan Whitehorn. 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 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pic_if.h" /* * Mambo interface */ static int openpic_mambo_probe(device_t); -static uint32_t openpic_mambo_id(device_t dev); +static int openpic_mambo_attach(device_t); static int openpicbus_mambo_probe(device_t dev); static int openpicbus_mambo_attach(device_t dev); -static struct resource *openpicbus_alloc_resource(device_t bus, device_t dev, - int type, int *rid, u_long start, u_long end, u_long count, - u_int flags); +static struct resource *openpicbus_alloc_resource(device_t bus, device_t dev, + int type, int *rid, u_long start, u_long end, u_long count, u_int flags); static device_method_t openpicbus_mambo_methods[] = { /* Device interface */ DEVMETHOD(device_probe, openpicbus_mambo_probe), DEVMETHOD(device_attach, openpicbus_mambo_attach), /* Bus interface */ DEVMETHOD(bus_alloc_resource, openpicbus_alloc_resource), {0,0} }; struct openpicbus_softc { vm_offset_t picaddr; }; static driver_t openpicbus_mambo_driver = { "openpicbus", openpicbus_mambo_methods, sizeof(struct openpicbus_softc), }; static device_method_t openpic_mambo_methods[] = { /* Device interface */ DEVMETHOD(device_probe, openpic_mambo_probe), - DEVMETHOD(device_attach, openpic_attach), + DEVMETHOD(device_attach, openpic_mambo_attach), /* PIC interface */ DEVMETHOD(pic_config, openpic_config), DEVMETHOD(pic_dispatch, openpic_dispatch), DEVMETHOD(pic_enable, openpic_enable), DEVMETHOD(pic_eoi, openpic_eoi), DEVMETHOD(pic_ipi, openpic_ipi), DEVMETHOD(pic_mask, openpic_mask), DEVMETHOD(pic_unmask, openpic_unmask), - DEVMETHOD(pic_id, openpic_mambo_id), { 0, 0 }, }; static driver_t openpic_mambo_driver = { "openpic", openpic_mambo_methods, sizeof(struct openpic_softc), }; static devclass_t openpicbus_devclass; DRIVER_MODULE(openpicbus, nexus, openpicbus_mambo_driver, openpicbus_devclass, 0, 0); DRIVER_MODULE(openpic, openpicbus, openpic_mambo_driver, openpic_devclass, 0, 0); static int openpicbus_mambo_probe(device_t dev) { const char *type = ofw_bus_get_type(dev); if (type == NULL || strcmp(type, "open-pic") != 0) return (ENXIO); device_set_desc(dev, "Mambo OpenPIC Container"); return (0); } static int openpicbus_mambo_attach(device_t dev) { uint64_t picaddr; phandle_t nexus; struct openpicbus_softc *sc; sc = device_get_softc(dev); nexus = OF_parent(ofw_bus_get_node(dev)); OF_getprop(nexus,"platform-open-pic", &picaddr,sizeof(picaddr)); sc->picaddr = picaddr; device_add_child(dev,"openpic",-1); return (bus_generic_attach(dev)); } static struct resource * openpicbus_alloc_resource(device_t bus, device_t dev, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct openpicbus_softc *sc; sc = device_get_softc(bus); count = 0x40000; start = sc->picaddr; end = start + count; return (bus_alloc_resource(bus, type, rid, start, end, count, flags)); } static int openpic_mambo_probe(device_t dev) { + device_set_desc(dev, OPENPIC_DEVSTR); - return (0); } -static uint32_t -openpic_mambo_id(device_t dev) +static int +openpic_mambo_attach(device_t dev) { - return (ofw_bus_get_node(device_get_parent(dev))); + + return (openpic_common_attach(dev, + ofw_bus_get_node(device_get_parent(dev)))); } - Index: head/sys/powerpc/mpc85xx/atpic.c =================================================================== --- head/sys/powerpc/mpc85xx/atpic.c (revision 218074) +++ head/sys/powerpc/mpc85xx/atpic.c (revision 218075) @@ -1,338 +1,327 @@ /*- * Copyright (c) 2009 Marcel Moolenaar * * 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 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include -#include #include #include #include #include #include #include "pic_if.h" #define ATPIC_MASTER 0 #define ATPIC_SLAVE 1 struct atpic_softc { device_t sc_dev; /* I/O port resources for master & slave. */ struct resource *sc_res[2]; int sc_rid[2]; /* Our "routing" interrupt */ struct resource *sc_ires; void *sc_icookie; int sc_irid; int sc_vector[16]; uint8_t sc_mask[2]; }; static int atpic_isa_attach(device_t); static void atpic_isa_identify(driver_t *, device_t); static int atpic_isa_probe(device_t); static void atpic_config(device_t, u_int, enum intr_trigger, enum intr_polarity); static void atpic_dispatch(device_t, struct trapframe *); static void atpic_enable(device_t, u_int, u_int); static void atpic_eoi(device_t, u_int); static void atpic_ipi(device_t, u_int); static void atpic_mask(device_t, u_int); static void atpic_unmask(device_t, u_int); -static uint32_t atpic_id (device_t dev); static device_method_t atpic_isa_methods[] = { /* Device interface */ DEVMETHOD(device_identify, atpic_isa_identify), DEVMETHOD(device_probe, atpic_isa_probe), DEVMETHOD(device_attach, atpic_isa_attach), /* PIC interface */ DEVMETHOD(pic_config, atpic_config), DEVMETHOD(pic_dispatch, atpic_dispatch), DEVMETHOD(pic_enable, atpic_enable), DEVMETHOD(pic_eoi, atpic_eoi), DEVMETHOD(pic_ipi, atpic_ipi), DEVMETHOD(pic_mask, atpic_mask), DEVMETHOD(pic_unmask, atpic_unmask), - DEVMETHOD(pic_id, atpic_id), { 0, 0 }, }; static driver_t atpic_isa_driver = { "atpic", atpic_isa_methods, sizeof(struct atpic_softc) }; static devclass_t atpic_devclass; DRIVER_MODULE(atpic, isa, atpic_isa_driver, atpic_devclass, 0, 0); static struct isa_pnp_id atpic_ids[] = { { 0x0000d041 /* PNP0000 */, "AT interrupt controller" }, { 0 } }; static __inline uint8_t atpic_read(struct atpic_softc *sc, int icu, int ofs) { uint8_t val; val = bus_read_1(sc->sc_res[icu], ofs); return (val); } static __inline void atpic_write(struct atpic_softc *sc, int icu, int ofs, uint8_t val) { bus_write_1(sc->sc_res[icu], ofs, val); bus_barrier(sc->sc_res[icu], ofs, 2 - ofs, BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE); } static void atpic_intr(void *arg) { atpic_dispatch(arg, NULL); } static void atpic_isa_identify(driver_t *drv, device_t parent) { device_t child; child = BUS_ADD_CHILD(parent, ISA_ORDER_SENSITIVE, drv->name, -1); device_set_driver(child, drv); isa_set_logicalid(child, atpic_ids[0].ip_id); isa_set_vendorid(child, atpic_ids[0].ip_id); bus_set_resource(child, SYS_RES_IOPORT, ATPIC_MASTER, IO_ICU1, 2); bus_set_resource(child, SYS_RES_IOPORT, ATPIC_SLAVE, IO_ICU2, 2); /* ISA interrupts are routed through external interrupt 0. */ - bus_set_resource(child, SYS_RES_IRQ, 0, PIC_IRQ_EXT(0), 1); + bus_set_resource(child, SYS_RES_IRQ, 0, 16, 1); } static int atpic_isa_probe(device_t dev) { int res; res = ISA_PNP_PROBE(device_get_parent(dev), dev, atpic_ids); if (res > 0) return (res); device_set_desc(dev, "PC/AT compatible PIC"); return (res); } static void atpic_init(struct atpic_softc *sc, int icu) { sc->sc_mask[icu] = 0xff - ((icu == ATPIC_MASTER) ? 4 : 0); atpic_write(sc, icu, 0, ICW1_RESET | ICW1_IC4); atpic_write(sc, icu, 1, (icu == ATPIC_SLAVE) ? 8 : 0); atpic_write(sc, icu, 1, (icu == ATPIC_SLAVE) ? 2 : 4); atpic_write(sc, icu, 1, ICW4_8086); atpic_write(sc, icu, 1, sc->sc_mask[icu]); atpic_write(sc, icu, 0, OCW3_SEL | OCW3_RR); } static int atpic_isa_attach(device_t dev) { struct atpic_softc *sc; int error; sc = device_get_softc(dev); sc->sc_dev = dev; error = ENXIO; sc->sc_rid[ATPIC_MASTER] = 0; sc->sc_res[ATPIC_MASTER] = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->sc_rid[ATPIC_MASTER], RF_ACTIVE); if (sc->sc_res[ATPIC_MASTER] == NULL) goto fail; sc->sc_rid[ATPIC_SLAVE] = 1; sc->sc_res[ATPIC_SLAVE] = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &sc->sc_rid[ATPIC_SLAVE], RF_ACTIVE); if (sc->sc_res[ATPIC_SLAVE] == NULL) goto fail; sc->sc_irid = 0; sc->sc_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irid, RF_ACTIVE); if (sc->sc_ires == NULL) goto fail; error = bus_setup_intr(dev, sc->sc_ires, INTR_TYPE_MISC | INTR_MPSAFE, NULL, atpic_intr, dev, &sc->sc_icookie); if (error) goto fail; atpic_init(sc, ATPIC_SLAVE); atpic_init(sc, ATPIC_MASTER); - powerpc_register_pic(dev, 0x10); + powerpc_register_pic(dev, 0, 16, 0, TRUE); return (0); fail: if (sc->sc_ires != NULL) bus_release_resource(dev, SYS_RES_IRQ, sc->sc_irid, sc->sc_ires); if (sc->sc_res[ATPIC_SLAVE] != NULL) bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid[ATPIC_SLAVE], sc->sc_res[ATPIC_SLAVE]); if (sc->sc_res[ATPIC_MASTER] != NULL) bus_release_resource(dev, SYS_RES_IOPORT, sc->sc_rid[ATPIC_MASTER], sc->sc_res[ATPIC_MASTER]); return (error); } /* * PIC interface. */ static void atpic_config(device_t dev, u_int irq, enum intr_trigger trig, enum intr_polarity pol) { } static void atpic_dispatch(device_t dev, struct trapframe *tf) { struct atpic_softc *sc; uint8_t irq; sc = device_get_softc(dev); atpic_write(sc, ATPIC_MASTER, 0, OCW3_SEL | OCW3_P); irq = atpic_read(sc, ATPIC_MASTER, 0); atpic_write(sc, ATPIC_MASTER, 0, OCW3_SEL | OCW3_RR); if ((irq & 0x80) == 0) return; if (irq == 0x82) { atpic_write(sc, ATPIC_SLAVE, 0, OCW3_SEL | OCW3_P); irq = atpic_read(sc, ATPIC_SLAVE, 0) + 8; atpic_write(sc, ATPIC_SLAVE, 0, OCW3_SEL | OCW3_RR); if ((irq & 0x80) == 0) return; } powerpc_dispatch_intr(sc->sc_vector[irq & 0x0f], tf); } static void atpic_enable(device_t dev, u_int irq, u_int vector) { struct atpic_softc *sc; sc = device_get_softc(dev); sc->sc_vector[irq] = vector; atpic_unmask(dev, irq); } static void atpic_eoi(device_t dev, u_int irq) { struct atpic_softc *sc; sc = device_get_softc(dev); if (irq > 7) atpic_write(sc, ATPIC_SLAVE, 0, OCW2_EOI); atpic_write(sc, ATPIC_MASTER, 0, OCW2_EOI); } static void atpic_ipi(device_t dev, u_int cpu) { /* No SMP support. */ } static void atpic_mask(device_t dev, u_int irq) { struct atpic_softc *sc; sc = device_get_softc(dev); if (irq > 7) { sc->sc_mask[ATPIC_SLAVE] |= 1 << (irq - 8); atpic_write(sc, ATPIC_SLAVE, 1, sc->sc_mask[ATPIC_SLAVE]); } else { sc->sc_mask[ATPIC_MASTER] |= 1 << irq; atpic_write(sc, ATPIC_MASTER, 1, sc->sc_mask[ATPIC_MASTER]); } } static void atpic_unmask(device_t dev, u_int irq) { struct atpic_softc *sc; sc = device_get_softc(dev); if (irq > 7) { sc->sc_mask[ATPIC_SLAVE] &= ~(1 << (irq - 8)); atpic_write(sc, ATPIC_SLAVE, 1, sc->sc_mask[ATPIC_SLAVE]); } else { sc->sc_mask[ATPIC_MASTER] &= ~(1 << irq); atpic_write(sc, ATPIC_MASTER, 1, sc->sc_mask[ATPIC_MASTER]); } } - -static uint32_t -atpic_id (device_t dev) -{ - - return (ATPIC_ID); -} - Index: head/sys/powerpc/mpc85xx/isa.c =================================================================== --- head/sys/powerpc/mpc85xx/isa.c (revision 218074) +++ head/sys/powerpc/mpc85xx/isa.c (revision 218075) @@ -1,107 +1,101 @@ /*- * Copyright (c) 2009 Marcel Moolenaar * * 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 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include -#include #include #include #include #include -#include "ocpbus.h" - void isa_init(device_t dev) { } struct resource * isa_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 isa_device* idev = DEVTOISA(child); struct resource_list *rl = &idev->id_resources; int isdefault, passthrough, rids; isdefault = (start == 0UL && end == ~0UL) ? 1 : 0; passthrough = (device_get_parent(child) != bus) ? 1 : 0; if (!passthrough && !isdefault && resource_list_find(rl, type, *rid) == NULL) { switch (type) { case SYS_RES_IOPORT: rids = ISA_PNP_NPORT; break; - case SYS_RES_IRQ: - rids = ISA_PNP_NIRQ; - start = ISA_IRQ(start); - break; + case SYS_RES_IRQ: rids = ISA_PNP_NIRQ; break; case SYS_RES_MEMORY: rids = ISA_PNP_NMEM; break; default: rids = 0; break; } if (*rid < 0 || *rid >= rids) return (NULL); resource_list_add(rl, type, *rid, start, end, count); } return (resource_list_alloc(rl, bus, child, type, rid, start, end, count, flags)); } int isa_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { struct isa_device* idev = DEVTOISA(child); struct resource_list *rl = &idev->id_resources; return (resource_list_release(rl, bus, child, type, rid, r)); } int isa_setup_intr(device_t bus, device_t child, struct resource *r, int flags, driver_filter_t filter, void (*ihand)(void *), void *arg, void **cookiep) { return (BUS_SETUP_INTR(device_get_parent(bus), child, r, flags, filter, ihand, arg, cookiep)); } int isa_teardown_intr(device_t bus, device_t child, struct resource *r, void *cookie) { return (BUS_TEARDOWN_INTR(device_get_parent(bus), child, r, cookie)); } Index: head/sys/powerpc/mpc85xx/openpic_fdt.c =================================================================== --- head/sys/powerpc/mpc85xx/openpic_fdt.c (revision 218074) +++ head/sys/powerpc/mpc85xx/openpic_fdt.c (revision 218075) @@ -1,93 +1,92 @@ /*- * Copyright (c) 2009-2010 The FreeBSD Foundation * All rights reserved. * * This software was developed by Semihalf under sponsorship from * the FreeBSD Foundation. * * 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 __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include "pic_if.h" static int openpic_fdt_probe(device_t); -static uint32_t openpic_fdt_id(device_t); +static int openpic_fdt_attach(device_t); static device_method_t openpic_fdt_methods[] = { /* Device interface */ DEVMETHOD(device_probe, openpic_fdt_probe), - DEVMETHOD(device_attach, openpic_attach), + DEVMETHOD(device_attach, openpic_fdt_attach), /* PIC interface */ DEVMETHOD(pic_bind, openpic_bind), DEVMETHOD(pic_config, openpic_config), DEVMETHOD(pic_dispatch, openpic_dispatch), DEVMETHOD(pic_enable, openpic_enable), DEVMETHOD(pic_eoi, openpic_eoi), DEVMETHOD(pic_ipi, openpic_ipi), DEVMETHOD(pic_mask, openpic_mask), DEVMETHOD(pic_unmask, openpic_unmask), - DEVMETHOD(pic_id, openpic_fdt_id), { 0, 0 }, }; static driver_t openpic_fdt_driver = { "openpic", openpic_fdt_methods, sizeof(struct openpic_softc) }; DRIVER_MODULE(openpic, simplebus, openpic_fdt_driver, openpic_devclass, 0, 0); static int openpic_fdt_probe(device_t dev) { if (!ofw_bus_is_compatible(dev, "chrp,open-pic")) return (ENXIO); device_set_desc(dev, OPENPIC_DEVSTR); return (BUS_PROBE_DEFAULT); } -static uint32_t -openpic_fdt_id(device_t dev) +static int +openpic_fdt_attach(device_t dev) { - return (ofw_bus_get_node(dev)); + return (openpic_common_attach(dev, ofw_bus_get_node(dev))); } Index: head/sys/powerpc/mpc85xx/pci_fdt.c =================================================================== --- head/sys/powerpc/mpc85xx/pci_fdt.c (revision 218074) +++ head/sys/powerpc/mpc85xx/pci_fdt.c (revision 218075) @@ -1,1067 +1,1022 @@ /*- * Copyright 2006-2007 by Juniper Networks. * Copyright 2008 Semihalf. * Copyright 2010 The FreeBSD Foundation * All rights reserved. * * Portions of this software were developed by Semihalf * under sponsorship from the FreeBSD Foundation. * * 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: FreeBSD: src/sys/powerpc/mpc85xx/pci_ocp.c,v 1.9 2010/03/23 23:46:28 marcel */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ofw_bus_if.h" #include "pcib_if.h" #include #include #include #include #define REG_CFG_ADDR 0x0000 #define CONFIG_ACCESS_ENABLE 0x80000000 #define REG_CFG_DATA 0x0004 #define REG_INT_ACK 0x0008 #define REG_POTAR(n) (0x0c00 + 0x20 * (n)) #define REG_POTEAR(n) (0x0c04 + 0x20 * (n)) #define REG_POWBAR(n) (0x0c08 + 0x20 * (n)) #define REG_POWAR(n) (0x0c10 + 0x20 * (n)) #define REG_PITAR(n) (0x0e00 - 0x20 * (n)) #define REG_PIWBAR(n) (0x0e08 - 0x20 * (n)) #define REG_PIWBEAR(n) (0x0e0c - 0x20 * (n)) #define REG_PIWAR(n) (0x0e10 - 0x20 * (n)) #define REG_PEX_MES_DR 0x0020 #define REG_PEX_MES_IER 0x0028 #define REG_PEX_ERR_DR 0x0e00 #define REG_PEX_ERR_EN 0x0e08 #define PCIR_LTSSM 0x404 #define LTSSM_STAT_L0 0x16 #define DEVFN(b, s, f) ((b << 16) | (s << 8) | f) struct fsl_pcib_softc { device_t sc_dev; struct rman sc_iomem; bus_addr_t sc_iomem_va; /* Virtual mapping. */ bus_addr_t sc_iomem_size; bus_addr_t sc_iomem_alloc; /* Next allocation. */ int sc_iomem_target; struct rman sc_ioport; bus_addr_t sc_ioport_va; /* Virtual mapping. */ bus_addr_t sc_ioport_size; bus_addr_t sc_ioport_alloc; /* Next allocation. */ int sc_ioport_target; struct resource *sc_res; bus_space_handle_t sc_bsh; bus_space_tag_t sc_bst; int sc_rid; int sc_busnr; int sc_pcie; uint8_t sc_pcie_capreg; /* PCI-E Capability Reg Set */ /* Devices that need special attention. */ int sc_devfn_tundra; int sc_devfn_via_ide; struct fdt_pci_intr sc_intr_info; }; /* Local forward declerations. */ static uint32_t fsl_pcib_cfgread(struct fsl_pcib_softc *, u_int, u_int, u_int, u_int, int); static void fsl_pcib_cfgwrite(struct fsl_pcib_softc *, u_int, u_int, u_int, u_int, uint32_t, int); static int fsl_pcib_decode_win(phandle_t, struct fsl_pcib_softc *); static void fsl_pcib_err_init(device_t); static void fsl_pcib_inbound(struct fsl_pcib_softc *, int, int, u_long, u_long, u_long); -static int fsl_pcib_init(struct fsl_pcib_softc *, int, int, int); +static int fsl_pcib_init(struct fsl_pcib_softc *, int, int); static int fsl_pcib_intr_info(phandle_t, struct fsl_pcib_softc *); static int fsl_pcib_set_range(struct fsl_pcib_softc *, int, int, u_long, u_long); static void fsl_pcib_outbound(struct fsl_pcib_softc *, int, int, u_long, u_long, u_long); /* Forward declerations. */ static int fsl_pcib_attach(device_t); static int fsl_pcib_detach(device_t); static int fsl_pcib_probe(device_t); static struct resource *fsl_pcib_alloc_resource(device_t, device_t, int, int *, u_long, u_long, u_long, u_int); static int fsl_pcib_read_ivar(device_t, device_t, int, uintptr_t *); static int fsl_pcib_release_resource(device_t, device_t, int, int, struct resource *); static int fsl_pcib_write_ivar(device_t, device_t, int, uintptr_t); static int fsl_pcib_maxslots(device_t); static uint32_t fsl_pcib_read_config(device_t, u_int, u_int, u_int, u_int, int); static void fsl_pcib_write_config(device_t, u_int, u_int, u_int, u_int, uint32_t, int); -static int next_busnr = 0; - /* Configuration r/w mutex. */ struct mtx pcicfg_mtx; static int mtx_initialized = 0; /* * Bus interface definitions. */ static device_method_t fsl_pcib_methods[] = { /* Device interface */ DEVMETHOD(device_probe, fsl_pcib_probe), DEVMETHOD(device_attach, fsl_pcib_attach), DEVMETHOD(device_detach, fsl_pcib_detach), /* Bus interface */ DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_read_ivar, fsl_pcib_read_ivar), DEVMETHOD(bus_write_ivar, fsl_pcib_write_ivar), DEVMETHOD(bus_alloc_resource, fsl_pcib_alloc_resource), DEVMETHOD(bus_release_resource, fsl_pcib_release_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), /* pcib interface */ DEVMETHOD(pcib_maxslots, fsl_pcib_maxslots), DEVMETHOD(pcib_read_config, fsl_pcib_read_config), DEVMETHOD(pcib_write_config, fsl_pcib_write_config), DEVMETHOD(pcib_route_interrupt, pcib_route_interrupt), /* OFW bus interface */ 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 fsl_pcib_driver = { "pcib", fsl_pcib_methods, sizeof(struct fsl_pcib_softc), }; devclass_t pcib_devclass; DRIVER_MODULE(pcib, fdtbus, fsl_pcib_driver, pcib_devclass, 0, 0); static int fsl_pcib_probe(device_t dev) { - phandle_t parnode; + phandle_t node; - /* - * The PCI subnode does not have the 'compatible' property, so we need - * to check in the parent PCI node. However the parent is not - * represented by a separate ofw_bus child, and therefore - * ofw_bus_is_compatible() cannot be used, but direct fdt equivalent. - */ - parnode = OF_parent(ofw_bus_get_node(dev)); - if (parnode == 0) + node = ofw_bus_get_node(dev); + if (!fdt_is_type(node, "pci")) return (ENXIO); - if (!(fdt_is_compatible(parnode, "fsl,mpc8548-pcie") || - fdt_is_compatible(parnode, "fsl,mpc8548-pcie"))) + + if (!(fdt_is_compatible(node, "fsl,mpc8540-pci") || + fdt_is_compatible(node, "fsl,mpc8548-pcie"))) return (ENXIO); device_set_desc(dev, "Freescale Integrated PCI/PCI-E Controller"); - return (BUS_PROBE_DEFAULT); } static int fsl_pcib_attach(device_t dev) { struct fsl_pcib_softc *sc; phandle_t node; uint32_t cfgreg; - int maxslot, subbus; + int maxslot; uint8_t ltssm, capptr; sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_rid = 0; sc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, RF_ACTIVE); if (sc->sc_res == NULL) { device_printf(dev, "could not map I/O memory\n"); return (ENXIO); } sc->sc_bst = rman_get_bustag(sc->sc_res); sc->sc_bsh = rman_get_bushandle(sc->sc_res); sc->sc_busnr = 0; if (!mtx_initialized) { mtx_init(&pcicfg_mtx, "pcicfg", NULL, MTX_SPIN); mtx_initialized = 1; } cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_VENDOR, 2); if (cfgreg != 0x1057 && cfgreg != 0x1957) goto err; capptr = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_CAP_PTR, 1); while (capptr != 0) { cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, capptr, 2); switch (cfgreg & 0xff) { case PCIY_PCIX: break; case PCIY_EXPRESS: sc->sc_pcie = 1; sc->sc_pcie_capreg = capptr; break; } capptr = (cfgreg >> 8) & 0xff; } node = ofw_bus_get_node(dev); /* * Get PCI interrupt info. */ if (fsl_pcib_intr_info(node, sc) != 0) { device_printf(dev, "could not retrieve interrupt info\n"); goto err; } /* * Configure decode windows for PCI(E) access. */ if (fsl_pcib_decode_win(node, sc) != 0) goto err; cfgreg = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_COMMAND, 2); cfgreg |= PCIM_CMD_SERRESPEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | PCIM_CMD_PORTEN; fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_COMMAND, cfgreg, 2); sc->sc_devfn_tundra = -1; sc->sc_devfn_via_ide = -1; - maxslot = (sc->sc_pcie) ? 1 : 31; /* - * Scan bus using firmware configured, 0 based bus numbering, - * let fsl_pcib_init() shift bus number by next_busnr offset. + * Scan bus using firmware configured, 0 based bus numbering. */ - sc->sc_busnr = 1; - subbus = fsl_pcib_init(sc, 0, next_busnr, maxslot); + sc->sc_busnr = 0; + maxslot = (sc->sc_pcie) ? 0 : PCI_SLOTMAX; + fsl_pcib_init(sc, sc->sc_busnr, maxslot); - if (bootverbose) - printf("PCI: domain %d, busnr = %d, next_busnr = %d\n", - device_get_unit(dev), next_busnr + 1, - next_busnr + subbus + 1); - - /* Set final busnr */ - sc->sc_busnr = next_busnr + 1; - next_busnr += subbus + 1; - if (sc->sc_pcie) { ltssm = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_LTSSM, 1); if (ltssm < LTSSM_STAT_L0) { if (bootverbose) printf("PCI %d: no PCIE link, skipping\n", device_get_unit(dev)); return (0); } } fsl_pcib_err_init(dev); device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); err: bus_release_resource(dev, SYS_RES_MEMORY, sc->sc_rid, sc->sc_res); return (ENXIO); } static uint32_t fsl_pcib_cfgread(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func, u_int reg, int bytes) { uint32_t addr, data; if (bus == sc->sc_busnr - 1) bus = 0; addr = CONFIG_ACCESS_ENABLE; addr |= (bus & 0xff) << 16; addr |= (slot & 0x1f) << 11; addr |= (func & 0x7) << 8; addr |= reg & 0xfc; if (sc->sc_pcie) addr |= (reg & 0xf00) << 16; mtx_lock_spin(&pcicfg_mtx); bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr); switch (bytes) { case 1: data = bus_space_read_1(sc->sc_bst, sc->sc_bsh, REG_CFG_DATA + (reg & 3)); break; case 2: data = le16toh(bus_space_read_2(sc->sc_bst, sc->sc_bsh, REG_CFG_DATA + (reg & 2))); break; case 4: data = le32toh(bus_space_read_4(sc->sc_bst, sc->sc_bsh, REG_CFG_DATA)); break; default: data = ~0; break; } mtx_unlock_spin(&pcicfg_mtx); return (data); } static void fsl_pcib_cfgwrite(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func, u_int reg, uint32_t data, int bytes) { uint32_t addr; if (bus == sc->sc_busnr - 1) bus = 0; addr = CONFIG_ACCESS_ENABLE; addr |= (bus & 0xff) << 16; addr |= (slot & 0x1f) << 11; addr |= (func & 0x7) << 8; addr |= reg & 0xfc; if (sc->sc_pcie) addr |= (reg & 0xf00) << 16; mtx_lock_spin(&pcicfg_mtx); bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_ADDR, addr); switch (bytes) { case 1: bus_space_write_1(sc->sc_bst, sc->sc_bsh, REG_CFG_DATA + (reg & 3), data); break; case 2: bus_space_write_2(sc->sc_bst, sc->sc_bsh, REG_CFG_DATA + (reg & 2), htole16(data)); break; case 4: bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_CFG_DATA, htole32(data)); break; } mtx_unlock_spin(&pcicfg_mtx); } #if 0 static void dump(struct fsl_pcib_softc *sc) { unsigned int i; #define RD(o) bus_space_read_4(sc->sc_bst, sc->sc_bsh, o) for (i = 0; i < 5; i++) { printf("POTAR%u =0x%08x\n", i, RD(REG_POTAR(i))); printf("POTEAR%u =0x%08x\n", i, RD(REG_POTEAR(i))); printf("POWBAR%u =0x%08x\n", i, RD(REG_POWBAR(i))); printf("POWAR%u =0x%08x\n", i, RD(REG_POWAR(i))); } printf("\n"); for (i = 1; i < 4; i++) { printf("PITAR%u =0x%08x\n", i, RD(REG_PITAR(i))); printf("PIWBAR%u =0x%08x\n", i, RD(REG_PIWBAR(i))); printf("PIWBEAR%u=0x%08x\n", i, RD(REG_PIWBEAR(i))); printf("PIWAR%u =0x%08x\n", i, RD(REG_PIWAR(i))); } printf("\n"); #undef RD for (i = 0; i < 0x48; i += 4) { printf("cfg%02x=0x%08x\n", i, fsl_pcib_cfgread(sc, 0, 0, 0, i, 4)); } } #endif static int fsl_pcib_maxslots(device_t dev) { struct fsl_pcib_softc *sc = device_get_softc(dev); - return ((sc->sc_pcie) ? 1 : 31); + return ((sc->sc_pcie) ? 0 : PCI_SLOTMAX); } static uint32_t fsl_pcib_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int bytes) { struct fsl_pcib_softc *sc = device_get_softc(dev); u_int devfn; if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10) return (~0); devfn = DEVFN(bus, slot, func); if (devfn == sc->sc_devfn_tundra) return (~0); if (devfn == sc->sc_devfn_via_ide && reg == PCIR_INTPIN) return (1); return (fsl_pcib_cfgread(sc, bus, slot, func, reg, bytes)); } static void fsl_pcib_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, uint32_t val, int bytes) { struct fsl_pcib_softc *sc = device_get_softc(dev); if (bus == sc->sc_busnr && !sc->sc_pcie && slot < 10) return; fsl_pcib_cfgwrite(sc, bus, slot, func, reg, val, bytes); } static void fsl_pcib_init_via(struct fsl_pcib_softc *sc, uint16_t device, int bus, int slot, int fn) { if (device == 0x0686) { fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x52, 0x34, 1); fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x77, 0x00, 1); fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x83, 0x98, 1); fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x85, 0x03, 1); } else if (device == 0x0571) { sc->sc_devfn_via_ide = DEVFN(bus, slot, fn); fsl_pcib_write_config(sc->sc_dev, bus, slot, fn, 0x40, 0x0b, 1); } } static int fsl_pcib_init_bar(struct fsl_pcib_softc *sc, int bus, int slot, int func, int barno) { bus_addr_t *allocp; uint32_t addr, mask, size; int reg, width; reg = PCIR_BAR(barno); if (DEVFN(bus, slot, func) == sc->sc_devfn_via_ide) { switch (barno) { case 0: addr = 0x1f0; break; case 1: addr = 0x3f4; break; case 2: addr = 0x170; break; case 3: addr = 0x374; break; case 4: addr = 0xcc0; break; default: return (1); } fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4); return (1); } fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4); size = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, reg, 4); if (size == 0) return (1); width = ((size & 7) == 4) ? 2 : 1; if (size & 1) { /* I/O port */ allocp = &sc->sc_ioport_alloc; size &= ~3; if ((size & 0xffff0000) == 0) size |= 0xffff0000; } else { /* memory */ allocp = &sc->sc_iomem_alloc; size &= ~15; } mask = ~size; size = mask + 1; /* Sanity check (must be a power of 2). */ if (size & mask) return (width); addr = (*allocp + mask) & ~mask; *allocp = addr + size; if (bootverbose) printf("PCI %u:%u:%u:%u: reg %x: size=%08x: addr=%08x\n", device_get_unit(sc->sc_dev), bus, slot, func, reg, size, addr); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4); if (width == 2) fsl_pcib_write_config(sc->sc_dev, bus, slot, func, reg + 4, 0, 4); return (width); } static u_int fsl_pcib_route_int(struct fsl_pcib_softc *sc, u_int bus, u_int slot, u_int func, u_int intpin) { int err, unit; u_int devfn, intline; unit = device_get_unit(sc->sc_dev); devfn = DEVFN(bus, slot, func); if (devfn == sc->sc_devfn_via_ide) -#if 0 - intline = INTR_VEC(ATPIC_ID, 14); + intline = INTR_VEC(0, 14); else if (devfn == sc->sc_devfn_via_ide + 1) - intline = INTR_VEC(ATPIC_ID, 10); + intline = INTR_VEC(0, 10); else if (devfn == sc->sc_devfn_via_ide + 2) - intline = INTR_VEC(ATPIC_ID, 10); -#endif - ; + intline = INTR_VEC(0, 10); else { if (intpin != 0) err = fdt_pci_route_intr(bus, slot, func, intpin, &sc->sc_intr_info, &intline); else intline = 0xff; } if (bootverbose) printf("PCI %u:%u:%u:%u: intpin %u: intline=%u\n", unit, bus, slot, func, intpin, intline); return (intline); } static int -fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int busnr_offset, - int maxslot) +fsl_pcib_init(struct fsl_pcib_softc *sc, int bus, int maxslot) { - int secbus, subbus; + int secbus; int old_pribus, old_secbus, old_subbus; int new_pribus, new_secbus, new_subbus; int slot, func, maxfunc; int bar, maxbar; uint16_t vendor, device; uint8_t command, hdrtype, class, subclass; uint8_t intline, intpin; - subbus = bus; + secbus = bus; for (slot = 0; slot <= maxslot; slot++) { maxfunc = 0; for (func = 0; func <= maxfunc; func++) { - hdrtype = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, PCIR_HDRTYPE, 1); if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE) continue; if (func == 0 && (hdrtype & PCIM_MFDEV)) maxfunc = PCI_FUNCMAX; vendor = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, PCIR_VENDOR, 2); device = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, PCIR_DEVICE, 2); if (vendor == 0x1957 && device == 0x3fff) { sc->sc_devfn_tundra = DEVFN(bus, slot, func); continue; } command = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, PCIR_COMMAND, 1); command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_COMMAND, command, 1); if (vendor == 0x1106) fsl_pcib_init_via(sc, device, bus, slot, func); /* Program the base address registers. */ maxbar = (hdrtype & PCIM_HDRTYPE) ? 1 : 6; bar = 0; while (bar < maxbar) bar += fsl_pcib_init_bar(sc, bus, slot, func, bar); /* Perform interrupt routing. */ intpin = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, PCIR_INTPIN, 1); intline = fsl_pcib_route_int(sc, bus, slot, func, intpin); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_INTLINE, intline, 1); command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN; fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_COMMAND, command, 1); /* * Handle PCI-PCI bridges */ class = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, PCIR_CLASS, 1); subclass = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, PCIR_SUBCLASS, 1); -#if 0 + /* Allow only proper PCI-PCI briges */ if (class != PCIC_BRIDGE) continue; if (subclass != PCIS_BRIDGE_PCI) continue; -#endif - /* Allow all DEVTYPE 1 devices */ - if (hdrtype != PCIM_HDRTYPE_BRIDGE) - continue; - subbus++; - secbus = subbus; + secbus++; /* Program I/O decoder. */ fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEL_1, sc->sc_ioport.rm_start >> 8, 1); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITL_1, sc->sc_ioport.rm_end >> 8, 1); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOBASEH_1, sc->sc_ioport.rm_start >> 16, 2); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_IOLIMITH_1, sc->sc_ioport.rm_end >> 16, 2); /* Program (non-prefetchable) memory decoder. */ fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMBASE_1, sc->sc_iomem.rm_start >> 16, 2); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_MEMLIMIT_1, sc->sc_iomem.rm_end >> 16, 2); /* Program prefetchable memory decoder. */ fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEL_1, 0x0010, 2); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITL_1, 0x000f, 2); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMBASEH_1, 0x00000000, 4); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PMLIMITH_1, 0x00000000, 4); /* Read currect bus register configuration */ old_pribus = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, PCIR_PRIBUS_1, 1); old_secbus = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, PCIR_SECBUS_1, 1); old_subbus = fsl_pcib_read_config(sc->sc_dev, bus, slot, func, PCIR_SUBBUS_1, 1); if (bootverbose) printf("PCI: reading firmware bus numbers for " "secbus = %d (bus/sec/sub) = (%d/%d/%d)\n", - secbus + busnr_offset, old_pribus, - old_secbus, old_subbus); + secbus, old_pribus, old_secbus, old_subbus); - /* Skip unconfigured devices */ - if ((old_pribus == 0) && - (old_secbus == 0) && (old_subbus == 0)) - continue; + new_pribus = bus; + new_secbus = secbus; - subbus += fsl_pcib_init(sc, secbus, busnr_offset, - (subclass == PCIS_BRIDGE_PCI) ? 31 : 1); + secbus = fsl_pcib_init(sc, secbus, + (subclass == PCIS_BRIDGE_PCI) ? PCI_SLOTMAX : 0); - new_pribus = bus + busnr_offset; - new_secbus = secbus + busnr_offset; - new_subbus = subbus + busnr_offset; + new_subbus = secbus; - /* Fixup pribus for MPC8572 PCIE controller */ - if ((vendor == 0x1957) && ((device = 0x0040) || - (device == 0x0041))) - new_pribus = 0; - if (bootverbose) - printf("PCI: translate firmware bus numbers for " - "secbus %d (%d/%d/%d) -> (%d/%d/%d)\n", - secbus + busnr_offset, - old_pribus, old_secbus, old_subbus, + printf("PCI: translate firmware bus numbers " + "for secbus %d (%d/%d/%d) -> (%d/%d/%d)\n", + secbus, old_pribus, old_secbus, old_subbus, new_pribus, new_secbus, new_subbus); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_PRIBUS_1, new_pribus, 1); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_SECBUS_1, new_secbus, 1); fsl_pcib_write_config(sc->sc_dev, bus, slot, func, PCIR_SUBBUS_1, new_subbus, 1); } } - if (bootverbose) - printf("PCI: bus %d, #subbus = %d\n", - bus + busnr_offset, subbus - bus); - - return (subbus - bus); + return (secbus); } static void fsl_pcib_inbound(struct fsl_pcib_softc *sc, int wnd, int tgt, u_long start, u_long size, u_long pci_start) { uint32_t attr, bar, tar; KASSERT(wnd > 0, ("%s: inbound window 0 is invalid", __func__)); switch (tgt) { /* XXX OCP85XX_TGTIF_RAM2, OCP85XX_TGTIF_RAM_INTL should be handled */ case OCP85XX_TGTIF_RAM1: attr = 0xa0f55000 | (ffsl(size) - 2); break; default: attr = 0; break; } tar = start >> 12; bar = pci_start >> 12; bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PITAR(wnd), tar); bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBEAR(wnd), 0); bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWBAR(wnd), bar); bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PIWAR(wnd), attr); } static void fsl_pcib_outbound(struct fsl_pcib_softc *sc, int wnd, int res, u_long start, u_long size, u_long pci_start) { uint32_t attr, bar, tar; switch (res) { case SYS_RES_MEMORY: attr = 0x80044000 | (ffsl(size) - 2); break; case SYS_RES_IOPORT: attr = 0x80088000 | (ffsl(size) - 2); break; default: attr = 0x0004401f; break; } bar = start >> 12; tar = pci_start >> 12; bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTAR(wnd), tar); bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POTEAR(wnd), 0); bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWBAR(wnd), bar); bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_POWAR(wnd), attr); } static int fsl_pcib_set_range(struct fsl_pcib_softc *sc, int type, int wnd, u_long start, u_long size) { struct rman *rm; u_long end, alloc; bus_addr_t pci_start, pci_end; bus_addr_t *vap, *allocp; int error; end = start + size - 1; switch (type) { case SYS_RES_IOPORT: rm = &sc->sc_ioport; pci_start = 0x0000; pci_end = 0xffff; alloc = 0x1000; vap = &sc->sc_ioport_va; allocp = &sc->sc_ioport_alloc; break; case SYS_RES_MEMORY: rm = &sc->sc_iomem; pci_start = start; pci_end = end; alloc = 0; vap = &sc->sc_iomem_va; allocp = &sc->sc_iomem_alloc; break; default: return (EINVAL); } rm->rm_type = RMAN_ARRAY; rm->rm_start = pci_start; rm->rm_end = pci_end; error = rman_init(rm); if (error) return (error); error = rman_manage_region(rm, pci_start, pci_end); if (error) { rman_fini(rm); return (error); } *allocp = pci_start + alloc; *vap = (uintptr_t)pmap_mapdev(start, size); fsl_pcib_outbound(sc, wnd, type, start, size, pci_start); return (0); } static void fsl_pcib_err_init(device_t dev) { struct fsl_pcib_softc *sc; uint16_t sec_stat, dsr; uint32_t dcr, err_en; sc = device_get_softc(dev); sec_stat = fsl_pcib_cfgread(sc, 0, 0, 0, PCIR_SECSTAT_1, 2); if (sec_stat) fsl_pcib_cfgwrite(sc, 0, 0, 0, PCIR_SECSTAT_1, 0xffff, 2); if (sc->sc_pcie) { /* Clear error bits */ bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_IER, 0xffffffff); bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_MES_DR, 0xffffffff); bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_DR, 0xffffffff); dsr = fsl_pcib_cfgread(sc, 0, 0, 0, sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_STA, 2); if (dsr) fsl_pcib_cfgwrite(sc, 0, 0, 0, sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_STA, 0xffff, 2); /* Enable all errors reporting */ err_en = 0x00bfff00; bus_space_write_4(sc->sc_bst, sc->sc_bsh, REG_PEX_ERR_EN, err_en); /* Enable error reporting: URR, FER, NFER */ dcr = fsl_pcib_cfgread(sc, 0, 0, 0, sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_CTL, 4); dcr |= PCIM_EXP_CTL_URR_ENABLE | PCIM_EXP_CTL_FER_ENABLE | PCIM_EXP_CTL_NFER_ENABLE; fsl_pcib_cfgwrite(sc, 0, 0, 0, sc->sc_pcie_capreg + PCIR_EXPRESS_DEVICE_CTL, dcr, 4); } } static int fsl_pcib_detach(device_t dev) { if (mtx_initialized) { mtx_destroy(&pcicfg_mtx); mtx_initialized = 0; } return (bus_generic_detach(dev)); } static struct resource * fsl_pcib_alloc_resource(device_t dev, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct fsl_pcib_softc *sc = device_get_softc(dev); struct rman *rm; struct resource *res; bus_addr_t va; switch (type) { case SYS_RES_IOPORT: rm = &sc->sc_ioport; va = sc->sc_ioport_va; break; case SYS_RES_MEMORY: rm = &sc->sc_iomem; va = sc->sc_iomem_va; break; case SYS_RES_IRQ: -#if 0 - if (INTR_IGN(start) == powerpc_ign_lookup(ATPIC_ID)) { + if (start < 16) { device_printf(dev, "%s requested ISA interrupt %lu\n", device_get_nameunit(child), start); } -#endif flags |= RF_SHAREABLE; return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid, start, end, count, flags)); default: return (NULL); } res = rman_reserve_resource(rm, start, end, count, flags, child); if (res == NULL) return (NULL); rman_set_bustag(res, &bs_le_tag); rman_set_bushandle(res, va + rman_get_start(res) - rm->rm_start); return (res); } static int fsl_pcib_release_resource(device_t dev, device_t child, int type, int rid, struct resource *res) { return (rman_release_resource(res)); } static int fsl_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { struct fsl_pcib_softc *sc = device_get_softc(dev); switch (which) { case PCIB_IVAR_BUS: *result = sc->sc_busnr; return (0); case PCIB_IVAR_DOMAIN: *result = device_get_unit(dev); return (0); } return (ENOENT); } static int fsl_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) { struct fsl_pcib_softc *sc = device_get_softc(dev); switch (which) { case PCIB_IVAR_BUS: sc->sc_busnr = value; return (0); } return (ENOENT); } static int fsl_pcib_intr_info(phandle_t node, struct fsl_pcib_softc *sc) { int error; if ((error = fdt_pci_intr_info(node, &sc->sc_intr_info)) != 0) return (error); return (0); } static int fsl_pcib_decode_win(phandle_t node, struct fsl_pcib_softc *sc) { struct fdt_pci_range io_space, mem_space; device_t dev; int error; dev = sc->sc_dev; if ((error = fdt_pci_ranges(node, &io_space, &mem_space)) != 0) { device_printf(dev, "could not retrieve 'ranges' data\n"); return (error); } /* * Configure LAW decode windows. */ error = law_pci_target(sc->sc_res, &sc->sc_iomem_target, &sc->sc_ioport_target); if (error != 0) { device_printf(dev, "could not retrieve PCI LAW target info\n"); return (error); } error = law_enable(sc->sc_iomem_target, mem_space.base_parent, mem_space.len); if (error != 0) { device_printf(dev, "could not program LAW for PCI MEM range\n"); return (error); } error = law_enable(sc->sc_ioport_target, io_space.base_parent, io_space.len); if (error != 0) { device_printf(dev, "could not program LAW for PCI IO range\n"); return (error); } /* * Set outbout and inbound windows. */ fsl_pcib_outbound(sc, 0, -1, 0, 0, 0); if ((error = fsl_pcib_set_range(sc, SYS_RES_MEMORY, 1, mem_space.base_parent, mem_space.len)) != 0) return (error); if ((error = fsl_pcib_set_range(sc, SYS_RES_IOPORT, 2, io_space.base_parent, io_space.len)) != 0) return (error); fsl_pcib_outbound(sc, 3, -1, 0, 0, 0); fsl_pcib_outbound(sc, 4, -1, 0, 0, 0); fsl_pcib_inbound(sc, 1, -1, 0, 0, 0); fsl_pcib_inbound(sc, 2, -1, 0, 0, 0); fsl_pcib_inbound(sc, 3, OCP85XX_TGTIF_RAM1, 0, 2U * 1024U * 1024U * 1024U, 0); return (0); } Index: head/sys/powerpc/powermac/cpcht.c =================================================================== --- head/sys/powerpc/powermac/cpcht.c (revision 218074) +++ head/sys/powerpc/powermac/cpcht.c (revision 218075) @@ -1,990 +1,982 @@ /*- * Copyright (C) 2008-2010 Nathan Whitehorn * 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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pcib_if.h" #include "pic_if.h" /* * IBM CPC9X5 Hypertransport Device interface. */ static int cpcht_probe(device_t); static int cpcht_attach(device_t); static void cpcht_configure_htbridge(device_t, phandle_t); /* * Bus interface. */ static int cpcht_read_ivar(device_t, device_t, int, uintptr_t *); static struct resource *cpcht_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags); static int cpcht_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *res); static int cpcht_release_resource(device_t bus, device_t child, int type, int rid, struct resource *res); static int cpcht_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *res); /* * pcib interface. */ static int cpcht_maxslots(device_t); static u_int32_t cpcht_read_config(device_t, u_int, u_int, u_int, u_int, int); static void cpcht_write_config(device_t, u_int, u_int, u_int, u_int, u_int32_t, int); static int cpcht_route_interrupt(device_t bus, device_t dev, int pin); static int cpcht_alloc_msi(device_t dev, device_t child, int count, int maxcount, int *irqs); static int cpcht_release_msi(device_t dev, device_t child, int count, int *irqs); static int cpcht_alloc_msix(device_t dev, device_t child, int *irq); static int cpcht_release_msix(device_t dev, device_t child, int irq); static int cpcht_map_msi(device_t dev, device_t child, int irq, uint64_t *addr, uint32_t *data); /* * ofw_bus interface */ static phandle_t cpcht_get_node(device_t bus, device_t child); /* * Driver methods. */ static device_method_t cpcht_methods[] = { /* Device interface */ DEVMETHOD(device_probe, cpcht_probe), DEVMETHOD(device_attach, cpcht_attach), /* Bus interface */ DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_read_ivar, cpcht_read_ivar), DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), DEVMETHOD(bus_alloc_resource, cpcht_alloc_resource), DEVMETHOD(bus_release_resource, cpcht_release_resource), DEVMETHOD(bus_activate_resource, cpcht_activate_resource), DEVMETHOD(bus_deactivate_resource, cpcht_deactivate_resource), /* pcib interface */ DEVMETHOD(pcib_maxslots, cpcht_maxslots), DEVMETHOD(pcib_read_config, cpcht_read_config), DEVMETHOD(pcib_write_config, cpcht_write_config), DEVMETHOD(pcib_route_interrupt, cpcht_route_interrupt), DEVMETHOD(pcib_alloc_msi, cpcht_alloc_msi), DEVMETHOD(pcib_release_msi, cpcht_release_msi), DEVMETHOD(pcib_alloc_msix, cpcht_alloc_msix), DEVMETHOD(pcib_release_msix, cpcht_release_msix), DEVMETHOD(pcib_map_msi, cpcht_map_msi), /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, cpcht_get_node), { 0, 0 } }; struct cpcht_irq { enum { IRQ_NONE, IRQ_HT, IRQ_MSI, IRQ_INTERNAL } irq_type; int ht_source; vm_offset_t ht_base; vm_offset_t apple_eoi; uint32_t eoi_data; int edge; }; static struct cpcht_irq *cpcht_irqmap = NULL; uint32_t cpcht_msipic = 0; struct cpcht_softc { device_t sc_dev; phandle_t sc_node; vm_offset_t sc_data; uint64_t sc_populated_slots; struct rman sc_mem_rman; struct rman sc_io_rman; struct cpcht_irq htirq_map[128]; struct mtx htirq_mtx; }; static driver_t cpcht_driver = { "pcib", cpcht_methods, sizeof(struct cpcht_softc) }; static devclass_t cpcht_devclass; DRIVER_MODULE(cpcht, nexus, cpcht_driver, cpcht_devclass, 0, 0); #define CPCHT_IOPORT_BASE 0xf4000000UL /* Hardwired */ #define CPCHT_IOPORT_SIZE 0x00400000UL #define HTAPIC_REQUEST_EOI 0x20 #define HTAPIC_TRIGGER_LEVEL 0x02 #define HTAPIC_MASK 0x01 struct cpcht_range { u_int32_t pci_hi; u_int32_t pci_mid; u_int32_t pci_lo; u_int32_t junk; u_int32_t host_hi; u_int32_t host_lo; u_int32_t size_hi; u_int32_t size_lo; }; static int cpcht_probe(device_t dev) { const char *type, *compatible; type = ofw_bus_get_type(dev); compatible = ofw_bus_get_compat(dev); if (type == NULL || compatible == NULL) return (ENXIO); if (strcmp(type, "ht") != 0) return (ENXIO); if (strcmp(compatible, "u3-ht") != 0) return (ENXIO); device_set_desc(dev, "IBM CPC9X5 HyperTransport Tunnel"); return (0); } static int cpcht_attach(device_t dev) { struct cpcht_softc *sc; phandle_t node, child; u_int32_t reg[3]; int i, error; node = ofw_bus_get_node(dev); sc = device_get_softc(dev); if (OF_getprop(node, "reg", reg, sizeof(reg)) < 12) return (ENXIO); sc->sc_dev = dev; sc->sc_node = node; sc->sc_populated_slots = 0; sc->sc_data = (vm_offset_t)pmap_mapdev(reg[1], reg[2]); sc->sc_mem_rman.rm_type = RMAN_ARRAY; sc->sc_mem_rman.rm_descr = "CPCHT Device Memory"; error = rman_init(&sc->sc_mem_rman); if (error) { device_printf(dev, "rman_init() failed. error = %d\n", error); return (error); } sc->sc_io_rman.rm_type = RMAN_ARRAY; sc->sc_io_rman.rm_descr = "CPCHT I/O Memory"; error = rman_init(&sc->sc_io_rman); if (error) { device_printf(dev, "rman_init() failed. error = %d\n", error); return (error); } /* * Set up the resource manager and the HT->MPIC mapping. For cpcht, * the ranges are properties of the child bridges, and this is also * where we get the HT interrupts properties. */ /* I/O port mappings are usually not in the device tree */ rman_manage_region(&sc->sc_io_rman, 0, CPCHT_IOPORT_SIZE - 1); bzero(sc->htirq_map, sizeof(sc->htirq_map)); mtx_init(&sc->htirq_mtx, "cpcht irq", NULL, MTX_DEF); for (i = 0; i < 8; i++) sc->htirq_map[i].irq_type = IRQ_INTERNAL; for (child = OF_child(node); child != 0; child = OF_peer(child)) cpcht_configure_htbridge(dev, child); /* Now make the mapping table available to the MPIC */ cpcht_irqmap = sc->htirq_map; device_add_child(dev, "pci", device_get_unit(dev)); return (bus_generic_attach(dev)); } static void cpcht_configure_htbridge(device_t dev, phandle_t child) { struct cpcht_softc *sc; struct ofw_pci_register pcir; struct cpcht_range ranges[7], *rp; int nranges, ptr, nextptr; uint32_t vend, val; int i, nirq, irq; u_int f, s; sc = device_get_softc(dev); if (OF_getprop(child, "reg", &pcir, sizeof(pcir)) == -1) return; s = OFW_PCI_PHYS_HI_DEVICE(pcir.phys_hi); f = OFW_PCI_PHYS_HI_FUNCTION(pcir.phys_hi); /* * Mark this slot is populated. The remote south bridge does * not like us talking to unpopulated slots on the root bus. */ sc->sc_populated_slots |= (1 << s); /* * Next grab this child bus's bus ranges. */ bzero(ranges, sizeof(ranges)); nranges = OF_getprop(child, "ranges", ranges, sizeof(ranges)); nranges /= sizeof(ranges[0]); ranges[6].pci_hi = 0; for (rp = ranges; rp < ranges + nranges && rp->pci_hi != 0; rp++) { switch (rp->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { case OFW_PCI_PHYS_HI_SPACE_CONFIG: break; case OFW_PCI_PHYS_HI_SPACE_IO: rman_manage_region(&sc->sc_io_rman, rp->pci_lo, rp->pci_lo + rp->size_lo - 1); break; case OFW_PCI_PHYS_HI_SPACE_MEM32: rman_manage_region(&sc->sc_mem_rman, rp->pci_lo, rp->pci_lo + rp->size_lo - 1); break; case OFW_PCI_PHYS_HI_SPACE_MEM64: panic("64-bit CPCHT reserved memory!"); break; } } /* * Next build up any HT->MPIC mappings for this sub-bus. One would * naively hope that enabling, disabling, and EOIing interrupts would * cause the appropriate HT bus transactions to that effect. This is * not the case. * * Instead, we have to muck about on the HT peer's root PCI bridges, * figure out what interrupts they send, enable them, and cache * the location of their WaitForEOI registers so that we can * send EOIs later. */ /* All the devices we are interested in have caps */ if (!(PCIB_READ_CONFIG(dev, 0, s, f, PCIR_STATUS, 2) & PCIM_STATUS_CAPPRESENT)) return; nextptr = PCIB_READ_CONFIG(dev, 0, s, f, PCIR_CAP_PTR, 1); while (nextptr != 0) { ptr = nextptr; nextptr = PCIB_READ_CONFIG(dev, 0, s, f, ptr + PCICAP_NEXTPTR, 1); /* Find the HT IRQ capabilities */ if (PCIB_READ_CONFIG(dev, 0, s, f, ptr + PCICAP_ID, 1) != PCIY_HT) continue; val = PCIB_READ_CONFIG(dev, 0, s, f, ptr + PCIR_HT_COMMAND, 2); if ((val & PCIM_HTCMD_CAP_MASK) != PCIM_HTCAP_INTERRUPT) continue; /* Ask for the IRQ count */ PCIB_WRITE_CONFIG(dev, 0, s, f, ptr + PCIR_HT_COMMAND, 0x1, 1); nirq = PCIB_READ_CONFIG(dev, 0, s, f, ptr + 4, 4); nirq = ((nirq >> 16) & 0xff) + 1; device_printf(dev, "%d HT IRQs on device %d.%d\n", nirq, s, f); for (i = 0; i < nirq; i++) { PCIB_WRITE_CONFIG(dev, 0, s, f, ptr + PCIR_HT_COMMAND, 0x10 + (i << 1), 1); irq = PCIB_READ_CONFIG(dev, 0, s, f, ptr + 4, 4); /* * Mask this interrupt for now. */ PCIB_WRITE_CONFIG(dev, 0, s, f, ptr + 4, irq | HTAPIC_MASK, 4); irq = (irq >> 16) & 0xff; sc->htirq_map[irq].irq_type = IRQ_HT; sc->htirq_map[irq].ht_source = i; sc->htirq_map[irq].ht_base = sc->sc_data + (((((s & 0x1f) << 3) | (f & 0x07)) << 8) | (ptr)); PCIB_WRITE_CONFIG(dev, 0, s, f, ptr + PCIR_HT_COMMAND, 0x11 + (i << 1), 1); sc->htirq_map[irq].eoi_data = PCIB_READ_CONFIG(dev, 0, s, f, ptr + 4, 4) | 0x80000000; /* * Apple uses a non-compliant IO/APIC that differs * in how we signal EOIs. Check if this device was * made by Apple, and act accordingly. */ vend = PCIB_READ_CONFIG(dev, 0, s, f, PCIR_DEVVENDOR, 4); if ((vend & 0xffff) == 0x106b) sc->htirq_map[irq].apple_eoi = (sc->htirq_map[irq].ht_base - ptr) + 0x60; } } } static int cpcht_maxslots(device_t dev) { return (PCI_SLOTMAX); } static u_int32_t cpcht_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int width) { struct cpcht_softc *sc; vm_offset_t caoff; sc = device_get_softc(dev); caoff = sc->sc_data + (((((slot & 0x1f) << 3) | (func & 0x07)) << 8) | reg); if (bus == 0 && (!(sc->sc_populated_slots & (1 << slot)) || func > 0)) return (0xffffffff); if (bus > 0) caoff += 0x01000000UL + (bus << 16); switch (width) { case 1: return (in8rb(caoff)); break; case 2: return (in16rb(caoff)); break; case 4: return (in32rb(caoff)); break; } return (0xffffffff); } static void cpcht_write_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, u_int32_t val, int width) { struct cpcht_softc *sc; vm_offset_t caoff; sc = device_get_softc(dev); caoff = sc->sc_data + (((((slot & 0x1f) << 3) | (func & 0x07)) << 8) | reg); if (bus == 0 && (!(sc->sc_populated_slots & (1 << slot)) || func > 0)) return; if (bus > 0) caoff += 0x01000000UL + (bus << 16); switch (width) { case 1: out8rb(caoff, val); break; case 2: out16rb(caoff, val); break; case 4: out32rb(caoff, val); break; } } static int cpcht_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { switch (which) { case PCIB_IVAR_DOMAIN: *result = device_get_unit(dev); return (0); case PCIB_IVAR_BUS: *result = 0; /* Root bus */ return (0); } return (ENOENT); } static phandle_t cpcht_get_node(device_t bus, device_t dev) { struct cpcht_softc *sc; sc = device_get_softc(bus); /* We only have one child, the PCI bus, which needs our own node. */ return (sc->sc_node); } static int cpcht_route_interrupt(device_t bus, device_t dev, int pin) { return (pin); } static struct resource * cpcht_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 cpcht_softc *sc; struct resource *rv; struct rman *rm; int needactivate; needactivate = flags & RF_ACTIVE; flags &= ~RF_ACTIVE; sc = device_get_softc(bus); switch (type) { case SYS_RES_IOPORT: end = min(end, start + count); rm = &sc->sc_io_rman; break; case SYS_RES_MEMORY: rm = &sc->sc_mem_rman; break; case SYS_RES_IRQ: return (bus_alloc_resource(bus, type, rid, start, end, count, flags)); default: device_printf(bus, "unknown resource request from %s\n", device_get_nameunit(child)); return (NULL); } rv = rman_reserve_resource(rm, start, end, count, flags, child); if (rv == NULL) { device_printf(bus, "failed to reserve resource for %s\n", device_get_nameunit(child)); return (NULL); } rman_set_rid(rv, *rid); if (needactivate) { if (bus_activate_resource(child, type, *rid, rv) != 0) { device_printf(bus, "failed to activate resource for %s\n", device_get_nameunit(child)); rman_release_resource(rv); return (NULL); } } return (rv); } static int cpcht_activate_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { void *p; if (type == SYS_RES_IRQ) return (bus_activate_resource(bus, type, rid, res)); if (type == SYS_RES_MEMORY || type == SYS_RES_IOPORT) { vm_offset_t start; start = (vm_offset_t)rman_get_start(res); if (type == SYS_RES_IOPORT) start += CPCHT_IOPORT_BASE; if (bootverbose) printf("cpcht mapdev: start %zx, len %ld\n", start, rman_get_size(res)); p = pmap_mapdev(start, (vm_size_t)rman_get_size(res)); if (p == NULL) return (ENOMEM); rman_set_virtual(res, p); rman_set_bustag(res, &bs_le_tag); rman_set_bushandle(res, (u_long)p); } return (rman_activate_resource(res)); } static int cpcht_release_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { if (rman_get_flags(res) & RF_ACTIVE) { int error = bus_deactivate_resource(child, type, rid, res); if (error) return error; } return (rman_release_resource(res)); } static int cpcht_deactivate_resource(device_t bus, device_t child, int type, int rid, struct resource *res) { /* * If this is a memory resource, unmap it. */ if ((type == SYS_RES_MEMORY) || (type == SYS_RES_IOPORT)) { u_int32_t psize; psize = rman_get_size(res); pmap_unmapdev((vm_offset_t)rman_get_virtual(res), psize); } return (rman_deactivate_resource(res)); } static int cpcht_alloc_msi(device_t dev, device_t child, int count, int maxcount, int *irqs) { struct cpcht_softc *sc; int i, j; sc = device_get_softc(dev); j = 0; /* Bail if no MSI PIC yet */ if (cpcht_msipic == 0) return (ENXIO); mtx_lock(&sc->htirq_mtx); for (i = 8; i < 124 - count; i++) { for (j = 0; j < count; j++) { if (sc->htirq_map[i+j].irq_type != IRQ_NONE) break; } if (j == count) break; i += j; /* We know there isn't a large enough run */ } if (j != count) { mtx_unlock(&sc->htirq_mtx); return (ENXIO); } for (j = 0; j < count; j++) { irqs[j] = INTR_VEC(cpcht_msipic, i+j); sc->htirq_map[i+j].irq_type = IRQ_MSI; } mtx_unlock(&sc->htirq_mtx); return (0); } static int cpcht_release_msi(device_t dev, device_t child, int count, int *irqs) { struct cpcht_softc *sc; int i; sc = device_get_softc(dev); mtx_lock(&sc->htirq_mtx); for (i = 0; i < count; i++) sc->htirq_map[irqs[i] & 0xff].irq_type = IRQ_NONE; mtx_unlock(&sc->htirq_mtx); return (0); } static int cpcht_alloc_msix(device_t dev, device_t child, int *irq) { struct cpcht_softc *sc; int i; sc = device_get_softc(dev); /* Bail if no MSI PIC yet */ if (cpcht_msipic == 0) return (ENXIO); mtx_lock(&sc->htirq_mtx); for (i = 8; i < 124; i++) { if (sc->htirq_map[i].irq_type == IRQ_NONE) { sc->htirq_map[i].irq_type = IRQ_MSI; *irq = INTR_VEC(cpcht_msipic, i); mtx_unlock(&sc->htirq_mtx); return (0); } } mtx_unlock(&sc->htirq_mtx); return (ENXIO); } static int cpcht_release_msix(device_t dev, device_t child, int irq) { struct cpcht_softc *sc; sc = device_get_softc(dev); mtx_lock(&sc->htirq_mtx); sc->htirq_map[irq & 0xff].irq_type = IRQ_NONE; mtx_unlock(&sc->htirq_mtx); return (0); } static int cpcht_map_msi(device_t dev, device_t child, int irq, uint64_t *addr, uint32_t *data) { device_t pcib; struct pci_devinfo *dinfo; struct pcicfg_ht *ht = NULL; for (pcib = child; pcib != dev; pcib = device_get_parent(device_get_parent(pcib))) { dinfo = device_get_ivars(pcib); ht = &dinfo->cfg.ht; if (ht == NULL) continue; } if (ht == NULL) return (ENXIO); *addr = ht->ht_msiaddr; *data = irq & 0xff; return (0); } /* * Driver for the integrated MPIC on U3/U4 (CPC925/CPC945) */ static int openpic_cpcht_probe(device_t); static int openpic_cpcht_attach(device_t); static void openpic_cpcht_config(device_t, u_int irq, enum intr_trigger trig, enum intr_polarity pol); static void openpic_cpcht_enable(device_t, u_int irq, u_int vector); static void openpic_cpcht_unmask(device_t, u_int irq); static void openpic_cpcht_eoi(device_t, u_int irq); -static uint32_t openpic_cpcht_id(device_t); static device_method_t openpic_cpcht_methods[] = { /* Device interface */ DEVMETHOD(device_probe, openpic_cpcht_probe), DEVMETHOD(device_attach, openpic_cpcht_attach), /* PIC interface */ DEVMETHOD(pic_bind, openpic_bind), DEVMETHOD(pic_config, openpic_cpcht_config), DEVMETHOD(pic_dispatch, openpic_dispatch), DEVMETHOD(pic_enable, openpic_cpcht_enable), DEVMETHOD(pic_eoi, openpic_cpcht_eoi), DEVMETHOD(pic_ipi, openpic_ipi), DEVMETHOD(pic_mask, openpic_mask), DEVMETHOD(pic_unmask, openpic_cpcht_unmask), - DEVMETHOD(pic_id, openpic_cpcht_id), { 0, 0 }, }; struct openpic_cpcht_softc { struct openpic_softc sc_openpic; struct mtx sc_ht_mtx; }; static driver_t openpic_cpcht_driver = { "htpic", openpic_cpcht_methods, sizeof(struct openpic_cpcht_softc), }; DRIVER_MODULE(openpic, unin, openpic_cpcht_driver, openpic_devclass, 0, 0); static int openpic_cpcht_probe(device_t dev) { const char *type = ofw_bus_get_type(dev); if (strcmp(type, "open-pic") != 0) return (ENXIO); device_set_desc(dev, OPENPIC_DEVSTR); return (0); } static int openpic_cpcht_attach(device_t dev) { struct openpic_cpcht_softc *sc; + phandle_t node; int err, irq; - err = openpic_attach(dev); + node = ofw_bus_get_node(dev); + err = openpic_common_attach(dev, node); if (err != 0) return (err); /* * The HT APIC stuff is not thread-safe, so we need a mutex to * protect it. */ sc = device_get_softc(dev); mtx_init(&sc->sc_ht_mtx, "htpic", NULL, MTX_SPIN); /* * Interrupts 0-3 are internally sourced and are level triggered * active low. Interrupts 4-123 are connected to a pulse generator * and should be programmed as edge triggered low-to-high. * * IBM CPC945 Manual, Section 9.3. */ for (irq = 0; irq < 4; irq++) openpic_config(dev, irq, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); for (irq = 4; irq < 124; irq++) openpic_config(dev, irq, INTR_TRIGGER_EDGE, INTR_POLARITY_LOW); /* * Use this PIC for MSI only if it is the root PIC. This may not * be necessary, but Linux does it, and I cannot find any U3 machines * with MSI devices to test. */ - if (dev == root_pic) - cpcht_msipic = PIC_ID(dev); + cpcht_msipic = node; return (0); } static void openpic_cpcht_config(device_t dev, u_int irq, enum intr_trigger trig, enum intr_polarity pol) { struct openpic_cpcht_softc *sc; uint32_t ht_irq; /* * The interrupt settings for the MPIC are completely determined * by the internal wiring in the northbridge. Real changes to these * settings need to be negotiated with the remote IO-APIC on the HT * link. */ sc = device_get_softc(dev); if (cpcht_irqmap != NULL && irq < 128 && cpcht_irqmap[irq].ht_base > 0 && !cpcht_irqmap[irq].edge) { mtx_lock_spin(&sc->sc_ht_mtx); /* Program the data port */ out8rb(cpcht_irqmap[irq].ht_base + PCIR_HT_COMMAND, 0x10 + (cpcht_irqmap[irq].ht_source << 1)); /* Grab the IRQ config register */ ht_irq = in32rb(cpcht_irqmap[irq].ht_base + 4); /* Mask the IRQ while we fiddle settings */ out32rb(cpcht_irqmap[irq].ht_base + 4, ht_irq | HTAPIC_MASK); /* Program the interrupt sense */ ht_irq &= ~(HTAPIC_TRIGGER_LEVEL | HTAPIC_REQUEST_EOI); if (trig == INTR_TRIGGER_EDGE) { cpcht_irqmap[irq].edge = 1; } else { cpcht_irqmap[irq].edge = 0; ht_irq |= HTAPIC_TRIGGER_LEVEL | HTAPIC_REQUEST_EOI; } out32rb(cpcht_irqmap[irq].ht_base + 4, ht_irq); mtx_unlock_spin(&sc->sc_ht_mtx); } } static void openpic_cpcht_enable(device_t dev, u_int irq, u_int vec) { struct openpic_cpcht_softc *sc; uint32_t ht_irq; openpic_enable(dev, irq, vec); sc = device_get_softc(dev); if (cpcht_irqmap != NULL && irq < 128 && cpcht_irqmap[irq].ht_base > 0) { mtx_lock_spin(&sc->sc_ht_mtx); /* Program the data port */ out8rb(cpcht_irqmap[irq].ht_base + PCIR_HT_COMMAND, 0x10 + (cpcht_irqmap[irq].ht_source << 1)); /* Unmask the interrupt */ ht_irq = in32rb(cpcht_irqmap[irq].ht_base + 4); ht_irq &= ~HTAPIC_MASK; out32rb(cpcht_irqmap[irq].ht_base + 4, ht_irq); mtx_unlock_spin(&sc->sc_ht_mtx); } openpic_cpcht_eoi(dev, irq); } static void openpic_cpcht_unmask(device_t dev, u_int irq) { struct openpic_cpcht_softc *sc; uint32_t ht_irq; openpic_unmask(dev, irq); sc = device_get_softc(dev); if (cpcht_irqmap != NULL && irq < 128 && cpcht_irqmap[irq].ht_base > 0) { mtx_lock_spin(&sc->sc_ht_mtx); /* Program the data port */ out8rb(cpcht_irqmap[irq].ht_base + PCIR_HT_COMMAND, 0x10 + (cpcht_irqmap[irq].ht_source << 1)); /* Unmask the interrupt */ ht_irq = in32rb(cpcht_irqmap[irq].ht_base + 4); ht_irq &= ~HTAPIC_MASK; out32rb(cpcht_irqmap[irq].ht_base + 4, ht_irq); mtx_unlock_spin(&sc->sc_ht_mtx); } openpic_cpcht_eoi(dev, irq); } static void openpic_cpcht_eoi(device_t dev, u_int irq) { struct openpic_cpcht_softc *sc; uint32_t off, mask; if (irq == 255) return; sc = device_get_softc(dev); if (cpcht_irqmap != NULL && irq < 128 && cpcht_irqmap[irq].ht_base > 0 && !cpcht_irqmap[irq].edge) { /* If this is an HT IRQ, acknowledge it at the remote APIC */ if (cpcht_irqmap[irq].apple_eoi) { off = (cpcht_irqmap[irq].ht_source >> 3) & ~3; mask = 1 << (cpcht_irqmap[irq].ht_source & 0x1f); out32rb(cpcht_irqmap[irq].apple_eoi + off, mask); } else { mtx_lock_spin(&sc->sc_ht_mtx); out8rb(cpcht_irqmap[irq].ht_base + PCIR_HT_COMMAND, 0x11 + (cpcht_irqmap[irq].ht_source << 1)); out32rb(cpcht_irqmap[irq].ht_base + 4, cpcht_irqmap[irq].eoi_data); mtx_unlock_spin(&sc->sc_ht_mtx); } } openpic_eoi(dev, irq); } - -static uint32_t -openpic_cpcht_id(device_t dev) -{ - return (ofw_bus_get_node(dev)); -} - Index: head/sys/powerpc/powermac/hrowpic.c =================================================================== --- head/sys/powerpc/powermac/hrowpic.c (revision 218074) +++ head/sys/powerpc/powermac/hrowpic.c (revision 218075) @@ -1,291 +1,280 @@ /*- * 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. * * $FreeBSD$ */ /* * A driver for the PIC found in the Heathrow/Paddington MacIO chips. * This was superseded by an OpenPIC in the Keylargo and beyond * MacIO versions. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pic_if.h" /* * MacIO interface */ static int hrowpic_probe(device_t); static int hrowpic_attach(device_t); static void hrowpic_dispatch(device_t, struct trapframe *); static void hrowpic_enable(device_t, u_int, u_int); static void hrowpic_eoi(device_t, u_int); static void hrowpic_ipi(device_t, u_int); static void hrowpic_mask(device_t, u_int); static void hrowpic_unmask(device_t, u_int); -static uint32_t hrowpic_id(device_t dev); static device_method_t hrowpic_methods[] = { /* Device interface */ DEVMETHOD(device_probe, hrowpic_probe), DEVMETHOD(device_attach, hrowpic_attach), /* PIC interface */ DEVMETHOD(pic_dispatch, hrowpic_dispatch), DEVMETHOD(pic_enable, hrowpic_enable), DEVMETHOD(pic_eoi, hrowpic_eoi), - DEVMETHOD(pic_id, hrowpic_id), DEVMETHOD(pic_ipi, hrowpic_ipi), DEVMETHOD(pic_mask, hrowpic_mask), DEVMETHOD(pic_unmask, hrowpic_unmask), { 0, 0 }, }; static driver_t hrowpic_driver = { "hrowpic", hrowpic_methods, sizeof(struct hrowpic_softc) }; static devclass_t hrowpic_devclass; DRIVER_MODULE(hrowpic, macio, hrowpic_driver, hrowpic_devclass, 0, 0); static uint32_t hrowpic_read_reg(struct hrowpic_softc *sc, u_int reg, u_int bank) { if (bank == HPIC_PRIMARY) reg += HPIC_1ST_OFFSET; return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg)); } static void hrowpic_write_reg(struct hrowpic_softc *sc, u_int reg, u_int bank, uint32_t val) { if (bank == HPIC_PRIMARY) reg += HPIC_1ST_OFFSET; bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val); /* XXX Issue a read to force the write to complete. */ bus_space_read_4(sc->sc_bt, sc->sc_bh, reg); } static int hrowpic_probe(device_t dev) { const char *type = ofw_bus_get_type(dev); /* * OpenPIC cells have a type of "open-pic", so this * is sufficient to identify a Heathrow cell */ if (strcmp(type, "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, "Heathrow MacIO interrupt controller"); return (0); } static int hrowpic_attach(device_t dev) { struct hrowpic_softc *sc; sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_rrid = 0; sc->sc_rres = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rrid, RF_ACTIVE); if (sc->sc_rres == NULL) { device_printf(dev, "Could not alloc mem resource!\n"); return (ENXIO); } sc->sc_bt = rman_get_bustag(sc->sc_rres); sc->sc_bh = rman_get_bushandle(sc->sc_rres); /* * Disable all interrupt sources and clear outstanding interrupts */ hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_PRIMARY, 0); hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_PRIMARY, 0xffffffff); hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_SECONDARY, 0); hrowpic_write_reg(sc, HPIC_CLEAR, HPIC_SECONDARY, 0xffffffff); - powerpc_register_pic(dev, 64); - root_pic = dev; /* Heathrow systems have only one PIC */ - + powerpc_register_pic(dev, ofw_bus_get_node(dev), 64, 0, FALSE); return (0); } /* * Local routines */ static void hrowpic_toggle_irq(struct hrowpic_softc *sc, int irq, int enable) { u_int roffset; u_int rbit; KASSERT((irq > 0) && (irq <= HROWPIC_IRQMAX), ("en irq out of range")); /* * Humor the SMP layer if it wants to set up an IPI handler. */ if (irq == HROWPIC_IRQMAX) return; /* * Calculate prim/sec register bank for the IRQ, update soft copy, * and enable the IRQ as an interrupt source */ roffset = HPIC_INT_TO_BANK(irq); rbit = HPIC_INT_TO_REGBIT(irq); if (enable) sc->sc_softreg[roffset] |= (1 << rbit); else sc->sc_softreg[roffset] &= ~(1 << rbit); hrowpic_write_reg(sc, HPIC_ENABLE, roffset, sc->sc_softreg[roffset]); } /* * PIC I/F methods. */ static void hrowpic_dispatch(device_t dev, struct trapframe *tf) { struct hrowpic_softc *sc; uint64_t mask; uint32_t reg; u_int irq; sc = device_get_softc(dev); while (1) { mask = hrowpic_read_reg(sc, HPIC_STATUS, HPIC_SECONDARY); reg = hrowpic_read_reg(sc, HPIC_STATUS, HPIC_PRIMARY); mask = (mask << 32) | reg; if (mask == 0) break; irq = 0; while (irq < HROWPIC_IRQMAX) { if (mask & 1) powerpc_dispatch_intr(sc->sc_vector[irq], tf); mask >>= 1; irq++; } } } static void hrowpic_enable(device_t dev, u_int irq, u_int vector) { struct hrowpic_softc *sc; sc = device_get_softc(dev); sc->sc_vector[irq] = vector; hrowpic_toggle_irq(sc, irq, 1); } static void hrowpic_eoi(device_t dev __unused, u_int irq __unused) { struct hrowpic_softc *sc; int bank; sc = device_get_softc(dev); bank = (irq >= 32) ? HPIC_SECONDARY : HPIC_PRIMARY ; hrowpic_write_reg(sc, HPIC_CLEAR, bank, 1U << (irq & 0x1f)); } static void hrowpic_ipi(device_t dev, u_int irq) { /* No SMP support. */ } static void hrowpic_mask(device_t dev, u_int irq) { struct hrowpic_softc *sc; sc = device_get_softc(dev); hrowpic_toggle_irq(sc, irq, 0); } static void hrowpic_unmask(device_t dev, u_int irq) { struct hrowpic_softc *sc; sc = device_get_softc(dev); hrowpic_toggle_irq(sc, irq, 1); } - -static uint32_t -hrowpic_id(device_t dev) -{ - return (ofw_bus_get_node(dev)); -} - Index: head/sys/powerpc/powermac/openpic_macio.c =================================================================== --- head/sys/powerpc/powermac/openpic_macio.c (revision 218074) +++ head/sys/powerpc/powermac/openpic_macio.c (revision 218075) @@ -1,107 +1,106 @@ /*- * 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. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pic_if.h" /* * MacIO interface */ static int openpic_macio_probe(device_t); -static uint32_t openpic_macio_id(device_t); +static int openpic_macio_attach(device_t); static device_method_t openpic_macio_methods[] = { /* Device interface */ DEVMETHOD(device_probe, openpic_macio_probe), - DEVMETHOD(device_attach, openpic_attach), + DEVMETHOD(device_attach, openpic_macio_attach), /* PIC interface */ DEVMETHOD(pic_bind, openpic_bind), DEVMETHOD(pic_config, openpic_config), DEVMETHOD(pic_dispatch, openpic_dispatch), DEVMETHOD(pic_enable, openpic_enable), DEVMETHOD(pic_eoi, openpic_eoi), DEVMETHOD(pic_ipi, openpic_ipi), DEVMETHOD(pic_mask, openpic_mask), DEVMETHOD(pic_unmask, openpic_unmask), - DEVMETHOD(pic_id, openpic_macio_id), { 0, 0 }, }; static driver_t openpic_macio_driver = { "openpic", openpic_macio_methods, sizeof(struct openpic_softc), }; DRIVER_MODULE(openpic, macio, openpic_macio_driver, openpic_devclass, 0, 0); static int openpic_macio_probe(device_t dev) { const char *type = ofw_bus_get_type(dev); if (strcmp(type, "open-pic") != 0) return (ENXIO); device_set_desc(dev, OPENPIC_DEVSTR); return (0); } -static uint32_t -openpic_macio_id(device_t dev) +static int +openpic_macio_attach(device_t dev) { - return (ofw_bus_get_node(dev)); + + return (openpic_common_attach(dev, ofw_bus_get_node(dev))); } - Index: head/sys/powerpc/powerpc/intr_machdep.c =================================================================== --- head/sys/powerpc/powerpc/intr_machdep.c (revision 218074) +++ head/sys/powerpc/powerpc/intr_machdep.c (revision 218075) @@ -1,497 +1,553 @@ /*- * Copyright (c) 1991 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * William Jolitz. * * 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. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. */ /*- * Copyright (c) 2002 Benno Rice. * 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. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 * form: src/sys/i386/isa/intr_machdep.c,v 1.57 2001/07/20 * * $FreeBSD$ */ +#include "opt_isa.h" + #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pic_if.h" #define MAX_STRAY_LOG 5 MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data"); struct powerpc_intr { struct intr_event *event; long *cntp; u_int irq; device_t pic; u_int intline; u_int vector; u_int cntindex; cpumask_t cpu; enum intr_trigger trig; enum intr_polarity pol; }; struct pic { - device_t pic; - uint32_t pic_id; - int ipi_irq; + device_t dev; + uint32_t node; + u_int irqs; + u_int ipis; + int base; }; static u_int intrcnt_index = 0; static struct mtx intr_table_lock; static struct powerpc_intr *powerpc_intrs[INTR_VECTORS]; static struct pic piclist[MAX_PICS]; static u_int nvectors; /* Allocated vectors */ static u_int npics; /* PICs registered */ +#ifdef DEV_ISA +static u_int nirqs = 16; /* Allocated IRQS (ISA pre-allocated). */ +#else +static u_int nirqs = 0; /* Allocated IRQs. */ +#endif static u_int stray_count; device_t root_pic; #ifdef SMP static void *ipi_cookie; #endif static void intr_init(void *dummy __unused) { mtx_init(&intr_table_lock, "intr sources lock", NULL, MTX_DEF); } SYSINIT(intr_init, SI_SUB_INTR, SI_ORDER_FIRST, intr_init, NULL); #ifdef SMP static void smp_intr_init(void *dummy __unused) { struct powerpc_intr *i; int vector; for (vector = 0; vector < nvectors; vector++) { i = powerpc_intrs[vector]; if (i != NULL && i->pic == root_pic) PIC_BIND(i->pic, i->intline, i->cpu); } } - SYSINIT(smp_intr_init, SI_SUB_SMP, SI_ORDER_ANY, smp_intr_init, NULL); #endif static void intrcnt_setname(const char *name, int index) { snprintf(intrnames + (MAXCOMLEN + 1) * index, MAXCOMLEN + 1, "%-*s", MAXCOMLEN, name); } void intrcnt_add(const char *name, u_long **countp) { int idx; idx = atomic_fetchadd_int(&intrcnt_index, 1); *countp = &intrcnt[idx]; intrcnt_setname(name, idx); } static struct powerpc_intr * intr_lookup(u_int irq) { char intrname[8]; struct powerpc_intr *i, *iscan; int vector; mtx_lock(&intr_table_lock); for (vector = 0; vector < nvectors; vector++) { i = powerpc_intrs[vector]; if (i != NULL && i->irq == irq) { mtx_unlock(&intr_table_lock); return (i); } } i = malloc(sizeof(*i), M_INTR, M_NOWAIT); if (i == NULL) { mtx_unlock(&intr_table_lock); return (NULL); } i->event = NULL; i->cntp = NULL; i->trig = INTR_TRIGGER_CONFORM; i->pol = INTR_POLARITY_CONFORM; i->irq = irq; i->pic = NULL; i->vector = -1; #ifdef SMP i->cpu = all_cpus; #else i->cpu = 1; #endif for (vector = 0; vector < INTR_VECTORS && vector <= nvectors; vector++) { iscan = powerpc_intrs[vector]; if (iscan != NULL && iscan->irq == irq) break; if (iscan == NULL && i->vector == -1) i->vector = vector; iscan = NULL; } if (iscan == NULL && i->vector != -1) { powerpc_intrs[i->vector] = i; i->cntindex = atomic_fetchadd_int(&intrcnt_index, 1); i->cntp = &intrcnt[i->cntindex]; sprintf(intrname, "irq%u:", i->irq); intrcnt_setname(intrname, i->cntindex); nvectors++; } mtx_unlock(&intr_table_lock); if (iscan != NULL || i->vector == -1) { free(i, M_INTR); i = iscan; } return (i); } static int powerpc_map_irq(struct powerpc_intr *i) { + struct pic *p; + u_int cnt; + int idx; - i->intline = INTR_INTLINE(i->irq); - i->pic = piclist[INTR_IGN(i->irq)].pic; + for (idx = 0; idx < npics; idx++) { + p = &piclist[idx]; + cnt = p->irqs + p->ipis; + if (i->irq >= p->base && i->irq < p->base + cnt) + break; + } + if (idx == npics) + return (EINVAL); + i->intline = i->irq - p->base; + i->pic = p->dev; + /* Try a best guess if that failed */ if (i->pic == NULL) i->pic = root_pic; return (0); } static void powerpc_intr_eoi(void *arg) { struct powerpc_intr *i = arg; PIC_EOI(i->pic, i->intline); } static void powerpc_intr_pre_ithread(void *arg) { struct powerpc_intr *i = arg; PIC_MASK(i->pic, i->intline); PIC_EOI(i->pic, i->intline); } static void powerpc_intr_post_ithread(void *arg) { struct powerpc_intr *i = arg; PIC_UNMASK(i->pic, i->intline); } static int powerpc_assign_intr_cpu(void *arg, u_char cpu) { #ifdef SMP struct powerpc_intr *i = arg; if (cpu == NOCPU) i->cpu = all_cpus; else i->cpu = 1 << cpu; if (!cold && i->pic != NULL && i->pic == root_pic) PIC_BIND(i->pic, i->intline, i->cpu); return (0); #else return (EOPNOTSUPP); #endif } void -powerpc_register_pic(device_t dev, u_int ipi) +powerpc_register_pic(device_t dev, uint32_t node, u_int irqs, u_int ipis, + u_int atpic) { - int i; + struct pic *p; + u_int irq; + int idx; mtx_lock(&intr_table_lock); - for (i = 0; i < npics; i++) { - if (piclist[i].pic_id == PIC_ID(dev)) + /* XXX see powerpc_get_irq(). */ + for (idx = 0; idx < npics; idx++) { + p = &piclist[idx]; + if (p->node != node) + continue; + if (node != 0 || p->dev == dev) break; } - piclist[i].pic = dev; - piclist[i].pic_id = PIC_ID(dev); - piclist[i].ipi_irq = ipi; - if (i == npics) + p = &piclist[idx]; + + p->dev = dev; + p->node = node; + p->irqs = irqs; + p->ipis = ipis; + if (idx == npics) { +#ifdef DEV_ISA + p->base = (atpic) ? 0 : nirqs; +#else + p->base = nirqs; +#endif + irq = p->base + irqs + ipis; + nirqs = MAX(nirqs, irq); npics++; + } mtx_unlock(&intr_table_lock); } -int -powerpc_ign_lookup(uint32_t pic_id) +u_int +powerpc_get_irq(uint32_t node, u_int pin) { - int i; + int idx; - mtx_lock(&intr_table_lock); + if (node == 0) + return (pin); - for (i = 0; i < npics; i++) { - if (piclist[i].pic_id == pic_id) { + mtx_lock(&intr_table_lock); + for (idx = 0; idx < npics; idx++) { + if (piclist[idx].node == node) { mtx_unlock(&intr_table_lock); - return (i); + return (piclist[idx].base + pin); } } - piclist[i].pic = NULL; - piclist[i].pic_id = pic_id; - piclist[i].ipi_irq = 0; + + /* + * XXX we should never encounter an unregistered PIC, but that + * can only be done when we properly support bus enumeration + * using multiple passes. Until then, fake an entry and give it + * some adhoc maximum number of IRQs and IPIs. + */ + piclist[idx].dev = NULL; + piclist[idx].node = node; + piclist[idx].irqs = 124; + piclist[idx].ipis = 4; + piclist[idx].base = nirqs; + nirqs += 128; npics++; mtx_unlock(&intr_table_lock); - return (i); + return (piclist[idx].base + pin); } int powerpc_enable_intr(void) { struct powerpc_intr *i; int error, vector; #ifdef SMP int n; #endif if (npics == 0) panic("no PIC detected\n"); + if (root_pic == NULL) + root_pic = piclist[0].dev; + #ifdef SMP /* Install an IPI handler. */ - for (n = 0; n < npics; n++) { - if (piclist[n].pic != root_pic) + if (piclist[n].dev != root_pic) continue; + KASSERT(piclist[n].ipis != 0, ("%s", __func__)); error = powerpc_setup_intr("IPI", - INTR_VEC(piclist[n].pic_id, piclist[n].ipi_irq), + INTR_VEC(piclist[n].node, piclist[n].irqs), powerpc_ipi_handler, NULL, NULL, INTR_TYPE_MISC | INTR_EXCL, &ipi_cookie); if (error) { printf("unable to setup IPI handler\n"); return (error); } } #endif for (vector = 0; vector < nvectors; vector++) { i = powerpc_intrs[vector]; if (i == NULL) continue; error = powerpc_map_irq(i); if (error) continue; if (i->trig != INTR_TRIGGER_CONFORM || i->pol != INTR_POLARITY_CONFORM) PIC_CONFIG(i->pic, i->intline, i->trig, i->pol); + + if (i != NULL && i->pic == root_pic) + PIC_BIND(i->pic, i->intline, i->cpu); if (i->event != NULL) PIC_ENABLE(i->pic, i->intline, vector); } return (0); } int powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter, driver_intr_t handler, void *arg, enum intr_type flags, void **cookiep) { struct powerpc_intr *i; int error, enable = 0; i = intr_lookup(irq); if (i == NULL) return (ENOMEM); if (i->event == NULL) { error = intr_event_create(&i->event, (void *)i, 0, irq, powerpc_intr_pre_ithread, powerpc_intr_post_ithread, powerpc_intr_eoi, powerpc_assign_intr_cpu, "irq%u:", irq); if (error) return (error); enable = 1; } error = intr_event_add_handler(i->event, name, filter, handler, arg, intr_priority(flags), flags, cookiep); mtx_lock(&intr_table_lock); intrcnt_setname(i->event->ie_fullname, i->cntindex); mtx_unlock(&intr_table_lock); if (!cold) { error = powerpc_map_irq(i); if (!error && (i->trig != INTR_TRIGGER_CONFORM || i->pol != INTR_POLARITY_CONFORM)) PIC_CONFIG(i->pic, i->intline, i->trig, i->pol); if (!error && i->pic == root_pic) PIC_BIND(i->pic, i->intline, i->cpu); if (!error && enable) PIC_ENABLE(i->pic, i->intline, i->vector); } return (error); } int powerpc_teardown_intr(void *cookie) { return (intr_event_remove_handler(cookie)); } #ifdef SMP int powerpc_bind_intr(u_int irq, u_char cpu) { struct powerpc_intr *i; i = intr_lookup(irq); if (i == NULL) return (ENOMEM); return (intr_event_bind(i->event, cpu)); } #endif int powerpc_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol) { struct powerpc_intr *i; i = intr_lookup(irq); if (i == NULL) return (ENOMEM); i->trig = trig; i->pol = pol; if (!cold && i->pic != NULL) PIC_CONFIG(i->pic, i->intline, trig, pol); return (0); } void powerpc_dispatch_intr(u_int vector, struct trapframe *tf) { struct powerpc_intr *i; struct intr_event *ie; i = powerpc_intrs[vector]; if (i == NULL) goto stray; (*i->cntp)++; ie = i->event; KASSERT(ie != NULL, ("%s: interrupt without an event", __func__)); if (intr_event_handle(ie, tf) != 0) { goto stray; } return; stray: stray_count++; if (stray_count <= MAX_STRAY_LOG) { printf("stray irq %d\n", i ? i->irq : -1); if (stray_count >= MAX_STRAY_LOG) { printf("got %d stray interrupts, not logging anymore\n", MAX_STRAY_LOG); } } if (i != NULL) PIC_MASK(i->pic, i->intline); } Index: head/sys/powerpc/powerpc/openpic.c =================================================================== --- head/sys/powerpc/powerpc/openpic.c (revision 218074) +++ head/sys/powerpc/powerpc/openpic.c (revision 218075) @@ -1,378 +1,377 @@ /*- * Copyright (C) 2002 Benno Rice. * 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 Benno Rice ``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 TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pic_if.h" devclass_t openpic_devclass; /* * Local routines */ static int openpic_intr(void *arg); static __inline uint32_t openpic_read(struct openpic_softc *sc, u_int reg) { return (bus_space_read_4(sc->sc_bt, sc->sc_bh, reg)); } static __inline void openpic_write(struct openpic_softc *sc, u_int reg, uint32_t val) { bus_space_write_4(sc->sc_bt, sc->sc_bh, reg, val); } static __inline void openpic_set_priority(struct openpic_softc *sc, int pri) { u_int tpr; uint32_t x; sched_pin(); tpr = OPENPIC_PCPU_TPR((sc->sc_dev == root_pic) ? PCPU_GET(cpuid) : 0); x = openpic_read(sc, tpr); x &= ~OPENPIC_TPR_MASK; x |= pri; openpic_write(sc, tpr, x); sched_unpin(); } int -openpic_attach(device_t dev) +openpic_common_attach(device_t dev, uint32_t node) { struct openpic_softc *sc; u_int cpu, ipi, irq; u_int32_t x; sc = device_get_softc(dev); sc->sc_dev = dev; sc->sc_rid = 0; sc->sc_memr = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->sc_rid, RF_ACTIVE); if (sc->sc_memr == NULL) { device_printf(dev, "Could not alloc mem resource!\n"); return (ENXIO); } sc->sc_bt = rman_get_bustag(sc->sc_memr); sc->sc_bh = rman_get_bushandle(sc->sc_memr); /* Reset the PIC */ x = openpic_read(sc, OPENPIC_CONFIG); x |= OPENPIC_CONFIG_RESET; openpic_write(sc, OPENPIC_CONFIG, x); while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) { powerpc_sync(); DELAY(100); } /* Check if this is a cascaded PIC */ sc->sc_irq = 0; sc->sc_intr = NULL; do { struct resource_list *rl; rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev); if (rl == NULL) break; if (resource_list_find(rl, SYS_RES_IRQ, 0) == NULL) break; sc->sc_intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->sc_irq, RF_ACTIVE); /* XXX Cascaded PICs pass NULL trapframes! */ bus_setup_intr(dev, sc->sc_intr, INTR_TYPE_MISC | INTR_MPSAFE, openpic_intr, NULL, dev, &sc->sc_icookie); } while (0); /* Reset the PIC */ x = openpic_read(sc, OPENPIC_CONFIG); x |= OPENPIC_CONFIG_RESET; openpic_write(sc, OPENPIC_CONFIG, x); while (openpic_read(sc, OPENPIC_CONFIG) & OPENPIC_CONFIG_RESET) { powerpc_sync(); DELAY(100); } x = openpic_read(sc, OPENPIC_FEATURE); switch (x & OPENPIC_FEATURE_VERSION_MASK) { case 1: sc->sc_version = "1.0"; break; case 2: sc->sc_version = "1.2"; break; case 3: sc->sc_version = "1.3"; break; default: sc->sc_version = "unknown"; break; } sc->sc_ncpu = ((x & OPENPIC_FEATURE_LAST_CPU_MASK) >> OPENPIC_FEATURE_LAST_CPU_SHIFT) + 1; sc->sc_nirq = ((x & OPENPIC_FEATURE_LAST_IRQ_MASK) >> OPENPIC_FEATURE_LAST_IRQ_SHIFT) + 1; /* * PSIM seems to report 1 too many IRQs and CPUs */ if (sc->sc_psim) { sc->sc_nirq--; sc->sc_ncpu--; } if (bootverbose) device_printf(dev, "Version %s, supports %d CPUs and %d irqs\n", sc->sc_version, sc->sc_ncpu, sc->sc_nirq); for (cpu = 0; cpu < sc->sc_ncpu; cpu++) openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 15); /* Reset and disable all interrupts. */ for (irq = 0; irq < sc->sc_nirq; irq++) { x = irq; /* irq == vector. */ x |= OPENPIC_IMASK; x |= OPENPIC_POLARITY_NEGATIVE; x |= OPENPIC_SENSE_LEVEL; x |= 8 << OPENPIC_PRIORITY_SHIFT; openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); } /* Reset and disable all IPIs. */ for (ipi = 0; ipi < 4; ipi++) { x = sc->sc_nirq + ipi; x |= OPENPIC_IMASK; x |= 15 << OPENPIC_PRIORITY_SHIFT; openpic_write(sc, OPENPIC_IPI_VECTOR(ipi), x); } /* we don't need 8259 passthrough mode */ x = openpic_read(sc, OPENPIC_CONFIG); x |= OPENPIC_CONFIG_8259_PASSTHRU_DISABLE; openpic_write(sc, OPENPIC_CONFIG, x); /* send all interrupts to cpu 0 */ for (irq = 0; irq < sc->sc_nirq; irq++) openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0); /* clear all pending interrupts from cpu 0 */ for (irq = 0; irq < sc->sc_nirq; irq++) { (void)openpic_read(sc, OPENPIC_PCPU_IACK(0)); openpic_write(sc, OPENPIC_PCPU_EOI(0), 0); } for (cpu = 0; cpu < sc->sc_ncpu; cpu++) openpic_write(sc, OPENPIC_PCPU_TPR(cpu), 0); - powerpc_register_pic(dev, sc->sc_nirq); + powerpc_register_pic(dev, node, sc->sc_nirq, 4, FALSE); /* If this is not a cascaded PIC, it must be the root PIC */ if (sc->sc_intr == NULL) root_pic = dev; return (0); } /* * PIC I/F methods */ void openpic_bind(device_t dev, u_int irq, cpumask_t cpumask) { struct openpic_softc *sc; /* If we aren't directly connected to the CPU, this won't work */ if (dev != root_pic) return; sc = device_get_softc(dev); openpic_write(sc, OPENPIC_IDEST(irq), cpumask); } void openpic_config(device_t dev, u_int irq, enum intr_trigger trig, enum intr_polarity pol) { struct openpic_softc *sc; uint32_t x; sc = device_get_softc(dev); x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); if (pol == INTR_POLARITY_LOW) x &= ~OPENPIC_POLARITY_POSITIVE; else x |= OPENPIC_POLARITY_POSITIVE; if (trig == INTR_TRIGGER_EDGE) x &= ~OPENPIC_SENSE_LEVEL; else x |= OPENPIC_SENSE_LEVEL; openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); } static int openpic_intr(void *arg) { device_t dev = (device_t)(arg); /* XXX Cascaded PICs do not pass non-NULL trapframes! */ openpic_dispatch(dev, NULL); return (FILTER_HANDLED); } void openpic_dispatch(device_t dev, struct trapframe *tf) { struct openpic_softc *sc; u_int cpuid, vector; CTR1(KTR_INTR, "%s: got interrupt", __func__); cpuid = (dev == root_pic) ? PCPU_GET(cpuid) : 0; sc = device_get_softc(dev); - while (1) { vector = openpic_read(sc, OPENPIC_PCPU_IACK(cpuid)); vector &= OPENPIC_VECTOR_MASK; if (vector == 255) break; powerpc_dispatch_intr(vector, tf); } } void openpic_enable(device_t dev, u_int irq, u_int vector) { struct openpic_softc *sc; uint32_t x; sc = device_get_softc(dev); if (irq < sc->sc_nirq) { x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK); x |= vector; openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); } else { x = openpic_read(sc, OPENPIC_IPI_VECTOR(0)); x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK); x |= vector; openpic_write(sc, OPENPIC_IPI_VECTOR(0), x); } } void openpic_eoi(device_t dev, u_int irq __unused) { struct openpic_softc *sc; u_int cpuid; cpuid = (dev == root_pic) ? PCPU_GET(cpuid) : 0; sc = device_get_softc(dev); openpic_write(sc, OPENPIC_PCPU_EOI(cpuid), 0); } void openpic_ipi(device_t dev, u_int cpu) { struct openpic_softc *sc; KASSERT(dev == root_pic, ("Cannot send IPIs from non-root OpenPIC")); sc = device_get_softc(dev); sched_pin(); openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(cpuid), 0), 1u << cpu); sched_unpin(); } void openpic_mask(device_t dev, u_int irq) { struct openpic_softc *sc; uint32_t x; sc = device_get_softc(dev); if (irq < sc->sc_nirq) { x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); x |= OPENPIC_IMASK; openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); } else { x = openpic_read(sc, OPENPIC_IPI_VECTOR(0)); x |= OPENPIC_IMASK; openpic_write(sc, OPENPIC_IPI_VECTOR(0), x); } } void openpic_unmask(device_t dev, u_int irq) { struct openpic_softc *sc; uint32_t x; sc = device_get_softc(dev); if (irq < sc->sc_nirq) { x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq)); x &= ~OPENPIC_IMASK; openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x); } else { x = openpic_read(sc, OPENPIC_IPI_VECTOR(0)); x &= ~OPENPIC_IMASK; openpic_write(sc, OPENPIC_IPI_VECTOR(0), x); } } Index: head/sys/powerpc/powerpc/pic_if.m =================================================================== --- head/sys/powerpc/powerpc/pic_if.m (revision 218074) +++ head/sys/powerpc/powerpc/pic_if.m (revision 218075) @@ -1,82 +1,78 @@ #- # Copyright (c) 1998 Doug Rabson # 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. # # from: src/sys/kern/bus_if.m,v 1.21 2002/04/21 11:16:10 markm Exp # $FreeBSD$ # #include #include INTERFACE pic; METHOD void bind { device_t dev; u_int irq; cpumask_t cpumask; }; METHOD void config { device_t dev; u_int irq; enum intr_trigger trig; enum intr_polarity pol; }; METHOD void dispatch { device_t dev; struct trapframe *tf; }; METHOD void enable { device_t dev; u_int irq; u_int vector; }; METHOD void eoi { device_t dev; u_int irq; }; METHOD void ipi { device_t dev; u_int cpu; }; -METHOD uint32_t id { - device_t dev; -}; - METHOD void mask { device_t dev; u_int irq; }; METHOD void unmask { device_t dev; u_int irq; }; Index: head/sys/powerpc/ps3/ps3pic.c =================================================================== --- head/sys/powerpc/ps3/ps3pic.c (revision 218074) +++ head/sys/powerpc/ps3/ps3pic.c (revision 218075) @@ -1,254 +1,243 @@ /*- * Copyright 2010 Nathan Whitehorn * * 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 BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include "ps3-hvcall.h" #include "pic_if.h" static void ps3pic_identify(driver_t *driver, device_t parent); static int ps3pic_probe(device_t); static int ps3pic_attach(device_t); static void ps3pic_dispatch(device_t, struct trapframe *); static void ps3pic_enable(device_t, u_int, u_int); static void ps3pic_eoi(device_t, u_int); static void ps3pic_ipi(device_t, u_int); static void ps3pic_mask(device_t, u_int); static void ps3pic_unmask(device_t, u_int); -static uint32_t ps3pic_id(device_t dev); struct ps3pic_softc { uint64_t *bitmap_thread0; uint64_t *mask_thread0; uint64_t *bitmap_thread1; uint64_t *mask_thread1; uint64_t sc_ipi_outlet[2]; int sc_vector[64]; }; static device_method_t ps3pic_methods[] = { /* Device interface */ DEVMETHOD(device_identify, ps3pic_identify), DEVMETHOD(device_probe, ps3pic_probe), DEVMETHOD(device_attach, ps3pic_attach), /* PIC interface */ DEVMETHOD(pic_dispatch, ps3pic_dispatch), DEVMETHOD(pic_enable, ps3pic_enable), DEVMETHOD(pic_eoi, ps3pic_eoi), - DEVMETHOD(pic_id, ps3pic_id), DEVMETHOD(pic_ipi, ps3pic_ipi), DEVMETHOD(pic_mask, ps3pic_mask), DEVMETHOD(pic_unmask, ps3pic_unmask), { 0, 0 }, }; static driver_t ps3pic_driver = { "ps3pic", ps3pic_methods, sizeof(struct ps3pic_softc) }; static devclass_t ps3pic_devclass; DRIVER_MODULE(ps3pic, nexus, ps3pic_driver, ps3pic_devclass, 0, 0); static MALLOC_DEFINE(M_PS3PIC, "ps3pic", "PS3 PIC"); static void ps3pic_identify(driver_t *driver, device_t parent) { if (strcmp(installed_platform(), "ps3") != 0) return; if (device_find_child(parent, "ps3pic", -1) == NULL) BUS_ADD_CHILD(parent, 0, "ps3pic", 0); } static int ps3pic_probe(device_t dev) { device_set_desc(dev, "Playstation 3 interrupt controller"); return (BUS_PROBE_NOWILDCARD); } static int ps3pic_attach(device_t dev) { struct ps3pic_softc *sc; uint64_t ppe; int thread; sc = device_get_softc(dev); sc->bitmap_thread0 = contigmalloc(128 /* 512 bits * 2 */, M_PS3PIC, M_NOWAIT | M_ZERO, 0, BUS_SPACE_MAXADDR, 64 /* alignment */, PAGE_SIZE /* boundary */); sc->mask_thread0 = sc->bitmap_thread0 + 4; sc->bitmap_thread1 = sc->bitmap_thread0 + 8; sc->mask_thread1 = sc->bitmap_thread0 + 12; lv1_get_logical_ppe_id(&ppe); thread = 32 - fls(mfctrl()); lv1_configure_irq_state_bitmap(ppe, thread, vtophys(sc->bitmap_thread0)); #ifdef SMP lv1_configure_irq_state_bitmap(ppe, !thread, vtophys(sc->bitmap_thread1)); /* Map both IPIs to the same VIRQ to avoid changes in intr_machdep */ lv1_construct_event_receive_port(&sc->sc_ipi_outlet[0]); lv1_connect_irq_plug_ext(ppe, thread, sc->sc_ipi_outlet[0], sc->sc_ipi_outlet[0], 0); lv1_construct_event_receive_port(&sc->sc_ipi_outlet[1]); lv1_connect_irq_plug_ext(ppe, !thread, sc->sc_ipi_outlet[0], sc->sc_ipi_outlet[1], 0); #endif - powerpc_register_pic(dev, sc->sc_ipi_outlet[0]); - root_pic = dev; /* PS3s have only one PIC */ - + powerpc_register_pic(dev, 0, sc->sc_ipi_outlet[0], 1, FALSE); return (0); } /* * PIC I/F methods. */ static void ps3pic_dispatch(device_t dev, struct trapframe *tf) { uint64_t bitmap, mask; int irq; struct ps3pic_softc *sc; sc = device_get_softc(dev); if (PCPU_GET(cpuid) == 0) { bitmap = sc->bitmap_thread0[0]; mask = sc->mask_thread0[0]; } else { bitmap = sc->bitmap_thread1[0]; mask = sc->mask_thread1[0]; } while ((irq = ffsl(bitmap & mask) - 1) != -1) { bitmap &= ~(1UL << irq); powerpc_dispatch_intr(sc->sc_vector[63 - irq], tf); } } static void ps3pic_enable(device_t dev, u_int irq, u_int vector) { struct ps3pic_softc *sc; sc = device_get_softc(dev); sc->sc_vector[irq] = vector; ps3pic_unmask(dev, irq); } static void ps3pic_eoi(device_t dev, u_int irq) { uint64_t ppe; int thread; lv1_get_logical_ppe_id(&ppe); thread = 32 - fls(mfctrl()); lv1_end_of_interrupt_ext(ppe, thread, irq); } static void ps3pic_ipi(device_t dev, u_int cpu) { struct ps3pic_softc *sc; sc = device_get_softc(dev); lv1_send_event_locally(sc->sc_ipi_outlet[cpu]); } static void ps3pic_mask(device_t dev, u_int irq) { struct ps3pic_softc *sc; uint64_t ppe; sc = device_get_softc(dev); /* Do not mask IPIs! */ if (irq == sc->sc_ipi_outlet[0]) return; sc->mask_thread0[0] &= ~(1UL << (63 - irq)); sc->mask_thread1[0] &= ~(1UL << (63 - irq)); lv1_get_logical_ppe_id(&ppe); lv1_did_update_interrupt_mask(ppe, 0); lv1_did_update_interrupt_mask(ppe, 1); } static void ps3pic_unmask(device_t dev, u_int irq) { struct ps3pic_softc *sc; uint64_t ppe; sc = device_get_softc(dev); sc->mask_thread0[0] |= (1UL << (63 - irq)); sc->mask_thread1[0] |= (1UL << (63 - irq)); lv1_get_logical_ppe_id(&ppe); lv1_did_update_interrupt_mask(ppe, 0); lv1_did_update_interrupt_mask(ppe, 1); } - -static uint32_t -ps3pic_id(device_t dev) -{ - return (0); -} - Index: head/sys/powerpc/psim/openpic_iobus.c =================================================================== --- head/sys/powerpc/psim/openpic_iobus.c (revision 218074) +++ head/sys/powerpc/psim/openpic_iobus.c (revision 218075) @@ -1,111 +1,119 @@ /*- * 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 "pic_if.h" /* * PSIM IOBus interface */ static int openpic_iobus_probe(device_t); +static int openpic_iobus_attach(device_t); static device_method_t openpic_iobus_methods[] = { /* Device interface */ DEVMETHOD(device_probe, openpic_iobus_probe), - DEVMETHOD(device_attach, openpic_attach), + DEVMETHOD(device_attach, openpic_iobus_attach), /* PIC interface */ DEVMETHOD(pic_config, openpic_config), DEVMETHOD(pic_dispatch, openpic_dispatch), DEVMETHOD(pic_enable, openpic_enable), DEVMETHOD(pic_eoi, openpic_eoi), DEVMETHOD(pic_ipi, openpic_ipi), DEVMETHOD(pic_mask, openpic_mask), DEVMETHOD(pic_unmask, openpic_unmask), { 0, 0 } }; static driver_t openpic_iobus_driver = { "openpic", openpic_iobus_methods, sizeof(struct openpic_softc) }; DRIVER_MODULE(openpic, iobus, openpic_iobus_driver, openpic_devclass, 0, 0); static int openpic_iobus_probe(device_t dev) { struct openpic_softc *sc; 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_DEVSTR); sc = device_get_softc(dev); sc->sc_psim = 1; return (0); +} + +static int +openpic_iobus_attach(device_t dev) +{ + + return (openpic_common_attach(dev, 0)); }