diff options
-rw-r--r-- | sys/conf/files.powerpc | 2 | ||||
-rw-r--r-- | sys/powerpc/conf/MPC85XX | 1 | ||||
-rw-r--r-- | sys/powerpc/include/intr_machdep.h | 2 | ||||
-rw-r--r-- | sys/powerpc/mpc85xx/atpic.c | 330 | ||||
-rw-r--r-- | sys/powerpc/mpc85xx/isa.c | 100 | ||||
-rw-r--r-- | sys/powerpc/mpc85xx/ocpbus.c | 23 | ||||
-rw-r--r-- | sys/powerpc/mpc85xx/pci_ocp.c | 127 | ||||
-rw-r--r-- | sys/powerpc/powerpc/autoconf.c | 12 | ||||
-rw-r--r-- | sys/powerpc/powerpc/intr_machdep.c | 90 |
9 files changed, 597 insertions, 90 deletions
diff --git a/sys/conf/files.powerpc b/sys/conf/files.powerpc index 00ac74a..389d62e 100644 --- a/sys/conf/files.powerpc +++ b/sys/conf/files.powerpc @@ -103,6 +103,8 @@ powerpc/fpu/fpu_implode.c optional fpu_emu powerpc/fpu/fpu_mul.c optional fpu_emu powerpc/fpu/fpu_sqrt.c optional fpu_emu powerpc/fpu/fpu_subr.c optional fpu_emu +powerpc/mpc85xx/atpic.c optional mpc85xx isa +powerpc/mpc85xx/isa.c optional mpc85xx isa powerpc/mpc85xx/lbc.c optional mpc85xx powerpc/mpc85xx/mpc85xx.c optional mpc85xx powerpc/mpc85xx/nexus.c optional mpc85xx diff --git a/sys/powerpc/conf/MPC85XX b/sys/powerpc/conf/MPC85XX index 122e483..901d18c 100644 --- a/sys/powerpc/conf/MPC85XX +++ b/sys/powerpc/conf/MPC85XX @@ -57,6 +57,7 @@ device da device em device ether device fxp +device isa device loop device md device miibus diff --git a/sys/powerpc/include/intr_machdep.h b/sys/powerpc/include/intr_machdep.h index 0cadf0c..f25d937 100644 --- a/sys/powerpc/include/intr_machdep.h +++ b/sys/powerpc/include/intr_machdep.h @@ -31,12 +31,14 @@ #define INTR_VECTORS 256 extern device_t pic; +extern device_t pic8259; struct trapframe; driver_filter_t powerpc_ipi_handler; void powerpc_register_pic(device_t, u_int); +void powerpc_register_8259(device_t); void powerpc_dispatch_intr(u_int, struct trapframe *); int powerpc_enable_intr(void); diff --git a/sys/powerpc/mpc85xx/atpic.c b/sys/powerpc/mpc85xx/atpic.c new file mode 100644 index 0000000..d5ee265 --- /dev/null +++ b/sys/powerpc/mpc85xx/atpic.c @@ -0,0 +1,330 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <sys/rman.h> +#include <sys/bus.h> + +#include <machine/bus.h> +#include <machine/intr.h> +#include <machine/intr_machdep.h> +#include <machine/pio.h> + +#include <powerpc/mpc85xx/ocpbus.h> + +#include <dev/ic/i8259.h> + +#include <isa/isareg.h> +#include <isa/isavar.h> + +#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 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), + + { 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(pic8259, arg); +} + +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); +} + +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_FAST, + NULL, atpic_intr, NULL, &sc->sc_icookie); + if (error) + goto fail; + + atpic_init(sc, ATPIC_SLAVE); + atpic_init(sc, ATPIC_MASTER); + + powerpc_register_8259(dev); + 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]); + atpic_write(sc, ATPIC_SLAVE, 0, OCW2_EOI); + } else { + sc->sc_mask[ATPIC_MASTER] |= 1 << irq; + atpic_write(sc, ATPIC_MASTER, 1, sc->sc_mask[ATPIC_MASTER]); + } + atpic_write(sc, ATPIC_MASTER, 0, OCW2_EOI); +} + +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]); + } +} diff --git a/sys/powerpc/mpc85xx/isa.c b/sys/powerpc/mpc85xx/isa.c new file mode 100644 index 0000000..5b996ca --- /dev/null +++ b/sys/powerpc/mpc85xx/isa.c @@ -0,0 +1,100 @@ +/*- + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/param.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/resource.h> + +#include <isa/isareg.h> +#include <isa/isavar.h> +#include <isa/isa_common.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; 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)); +} diff --git a/sys/powerpc/mpc85xx/ocpbus.c b/sys/powerpc/mpc85xx/ocpbus.c index ddc2e74..216ca41 100644 --- a/sys/powerpc/mpc85xx/ocpbus.c +++ b/sys/powerpc/mpc85xx/ocpbus.c @@ -159,15 +159,15 @@ ocpbus_write_law(int trgt, int type, u_long *startp, u_long *countp) case SYS_RES_IOPORT: switch (trgt) { case OCP85XX_TGTIF_PCI0: - addr = 0xff000000; + addr = 0xfee00000; size = 0x00010000; break; case OCP85XX_TGTIF_PCI1: - addr = 0xff010000; + addr = 0xfee10000; size = 0x00010000; break; case OCP85XX_TGTIF_PCI2: - addr = 0xff020000; + addr = 0xfee20000; size = 0x00010000; break; default: @@ -266,7 +266,7 @@ ocpbus_attach(device_t dev) ccsr_read4(OCP85XX_PORDEVSR), ccsr_read4(OCP85XX_PORDEVSR2)); - for (i = 0; i < 4; i++) + for (i = PIC_IRQ_START; i < PIC_IRQ_START + 4; i++) powerpc_config_intr(i, INTR_TRIGGER_LEVEL, INTR_POLARITY_LOW); return (bus_generic_attach(dev)); @@ -424,15 +424,8 @@ ocpbus_alloc_resource(device_t dev, device_t child, int type, int *rid, return (NULL); } - /* - * ISA interrupts (IRQ 0-15) are remapped by the - * PCI driver. Make sure this happened. - */ - if (start < PIC_IRQ_START) - return (NULL); - - rv = rman_reserve_resource(&sc->sc_irq, start - PIC_IRQ_START, - start - PIC_IRQ_START + count - 1, count, flags, child); + rv = rman_reserve_resource(&sc->sc_irq, start, + start + count - 1, count, flags, child); if (rv == NULL) return (NULL); break; @@ -598,7 +591,5 @@ ocpbus_config_intr(device_t dev, int irq, enum intr_trigger trig, enum intr_polarity pol) { - if (irq < PIC_IRQ_START) - return (EINVAL); - return (powerpc_config_intr(irq - PIC_IRQ_START, trig, pol)); + return (powerpc_config_intr(irq, trig, pol)); } diff --git a/sys/powerpc/mpc85xx/pci_ocp.c b/sys/powerpc/mpc85xx/pci_ocp.c index babfc6a..b98f62c 100644 --- a/sys/powerpc/mpc85xx/pci_ocp.c +++ b/sys/powerpc/mpc85xx/pci_ocp.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #include <machine/resource.h> #include <machine/bus.h> +#include <machine/intr_machdep.h> #include <machine/ocpbus.h> #include <machine/spr.h> @@ -75,6 +76,8 @@ __FBSDID("$FreeBSD$"); #define REG_PIWBEAR(n) (0x0e0c - 0x20 * (n)) #define REG_PIWAR(n) (0x0e10 - 0x20 * (n)) +#define DEVFN(b, s, f) ((b << 16) | (s << 8) | f) + struct pci_ocp_softc { device_t sc_dev; @@ -92,6 +95,10 @@ struct pci_ocp_softc { int sc_busnr; int sc_pcie:1; + + /* Devices that need special attention. */ + int sc_devfn_tundra; + int sc_devfn_via_ide; }; static int pci_ocp_attach(device_t); @@ -262,9 +269,15 @@ pci_ocp_read_config(device_t dev, u_int bus, u_int slot, u_int func, u_int reg, int bytes) { struct pci_ocp_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 (pci_ocp_cfgread(sc, bus, slot, func, reg, bytes)); } @@ -372,6 +385,22 @@ out: return (error); } +static void +pci_ocp_init_via(struct pci_ocp_softc *sc, uint16_t device, int bus, + int slot, int fn) +{ + + if (device == 0x0686) { + pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x52, 0x34, 1); + pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x77, 0x00, 1); + pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x83, 0x98, 1); + pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x85, 0x03, 1); + } else if (device == 0x0571) { + sc->sc_devfn_via_ide = DEVFN(bus, slot, fn); + pci_ocp_write_config(sc->sc_dev, bus, slot, fn, 0x40, 0x0b, 1); + } +} + static int pci_ocp_init_bar(struct pci_ocp_softc *sc, int bus, int slot, int func, int barno) @@ -381,6 +410,20 @@ pci_ocp_init_bar(struct pci_ocp_softc *sc, int bus, int slot, int func, 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); + } + pci_ocp_write_config(sc->sc_dev, bus, slot, func, reg, addr, 4); + return (1); + } + pci_ocp_write_config(sc->sc_dev, bus, slot, func, reg, ~0, 4); size = pci_ocp_read_config(sc->sc_dev, bus, slot, func, reg, 4); if (size == 0) @@ -421,17 +464,23 @@ static u_int pci_ocp_route_int(struct pci_ocp_softc *sc, u_int bus, u_int slot, u_int func, u_int intpin) { - u_int intline; - - /* - * Default interrupt routing. - */ - if (intpin != 0) { - intline = intpin - 1; - intline += (bus != sc->sc_busnr) ? slot : 0; - intline = PIC_IRQ_EXT(intline & 3); - } else - intline = 0xff; + u_int devfn, intline; + + devfn = DEVFN(bus, slot, func); + if (devfn == sc->sc_devfn_via_ide) + intline = 14; + else if (devfn == sc->sc_devfn_via_ide + 1) + intline = 10; + else if (devfn == sc->sc_devfn_via_ide + 2) + intline = 10; + else { + if (intpin != 0) { + intline = intpin - 1; + intline += (bus != sc->sc_busnr) ? slot : 0; + intline = PIC_IRQ_EXT(intline & 3); + } else + intline = 0xff; + } if (bootverbose) printf("PCI %u:%u:%u:%u: intpin %u: intline=%u\n", @@ -448,7 +497,7 @@ pci_ocp_init(struct pci_ocp_softc *sc, int bus, int maxslot) int func, maxfunc; int bar, maxbar; uint16_t vendor, device; - uint8_t cr8, command, hdrtype, class, subclass; + uint8_t command, hdrtype, class, subclass; uint8_t intline, intpin; secbus = bus; @@ -463,46 +512,25 @@ pci_ocp_init(struct pci_ocp_softc *sc, int bus, int maxslot) if (func == 0 && (hdrtype & PCIM_MFDEV)) maxfunc = PCI_FUNCMAX; - command = pci_ocp_read_config(sc->sc_dev, bus, slot, - func, PCIR_COMMAND, 1); - command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN); - pci_ocp_write_config(sc->sc_dev, bus, slot, func, - PCIR_COMMAND, command, 1); - vendor = pci_ocp_read_config(sc->sc_dev, bus, slot, func, PCIR_VENDOR, 2); device = pci_ocp_read_config(sc->sc_dev, bus, slot, func, PCIR_DEVICE, 2); - /* - * Make sure the ATA controller on the VIA82C686 - * South bridge is enabled. - */ - if (vendor == 0x1106 && device == 0x0686) { - /* Enable the ATA controller. */ - cr8 = pci_ocp_read_config(sc->sc_dev, bus, - slot, func, 0x48, 1); - if (cr8 & 2) { - device_printf(sc->sc_dev, - "enabling ATA controller\n"); - pci_ocp_write_config(sc->sc_dev, bus, - slot, func, 0x48, cr8 & ~2, 1); - } - } - if (vendor == 0x1106 && device == 0x0571) { - pci_ocp_write_config(sc->sc_dev, bus, slot, - func, 0xc4, 0x00, 1); - /* Set legacy mode. */ - pci_ocp_write_config(sc->sc_dev, bus, slot, - func, 0x40, 0x08, 1); - pci_ocp_write_config(sc->sc_dev, bus, slot, - func, PCIR_PROGIF, 0x00, 1); - pci_ocp_write_config(sc->sc_dev, bus, slot, - func, 0x42, 0x09, 1); - pci_ocp_write_config(sc->sc_dev, bus, slot, - func, 0x40, 0x0b, 1); + if (vendor == 0x1957 && device == 0x3fff) { + sc->sc_devfn_tundra = DEVFN(bus, slot, func); + continue; } + command = pci_ocp_read_config(sc->sc_dev, bus, slot, + func, PCIR_COMMAND, 1); + command &= ~(PCIM_CMD_MEMEN | PCIM_CMD_PORTEN); + pci_ocp_write_config(sc->sc_dev, bus, slot, func, + PCIR_COMMAND, command, 1); + + if (vendor == 0x1106) + pci_ocp_init_via(sc, device, bus, slot, func); + /* Program the base address registers. */ maxbar = (hdrtype & PCIM_HDRTYPE) ? 1 : 6; bar = 0; @@ -518,8 +546,7 @@ pci_ocp_init(struct pci_ocp_softc *sc, int bus, int maxslot) pci_ocp_write_config(sc->sc_dev, bus, slot, func, PCIR_INTLINE, intline, 1); - command |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MEMEN | - PCIM_CMD_PORTEN; + command |= PCIM_CMD_MEMEN | PCIM_CMD_PORTEN; pci_ocp_write_config(sc->sc_dev, bus, slot, func, PCIR_COMMAND, command, 1); @@ -723,6 +750,9 @@ pci_ocp_attach(device_t dev) pci_ocp_inbound(sc, 2, -1, 0, 0, 0); pci_ocp_inbound(sc, 3, OCP85XX_TGTIF_RAM1, 0, 2U*1024U*1024U*1024U, 0); + sc->sc_devfn_tundra = -1; + sc->sc_devfn_via_ide = -1; + maxslot = (sc->sc_pcie) ? 1 : 31; pci_ocp_init(sc, sc->sc_busnr, maxslot); @@ -749,12 +779,9 @@ pci_ocp_alloc_resource(device_t dev, device_t child, int type, int *rid, va = sc->sc_iomem_va; break; case SYS_RES_IRQ: - /* ISA interrupts are routed to IRQ 0 on the PIC. */ if (start < PIC_IRQ_START) { device_printf(dev, "%s requested ISA interrupt %lu\n", device_get_nameunit(child), start); - /* XXX */ - start = PIC_IRQ_EXT(0); } return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid, start, end, count, flags)); diff --git a/sys/powerpc/powerpc/autoconf.c b/sys/powerpc/powerpc/autoconf.c index 3749321..18c8bdc 100644 --- a/sys/powerpc/powerpc/autoconf.c +++ b/sys/powerpc/powerpc/autoconf.c @@ -24,6 +24,8 @@ * SUCH DAMAGE. */ +#include "opt_isa.h" + #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); @@ -35,6 +37,12 @@ __FBSDID("$FreeBSD$"); #include <machine/intr_machdep.h> +#ifdef DEV_ISA +extern void isa_probe_children(device_t dev); + +device_t isa_bus_device; +#endif + static device_t nexusdev; static void configure_first(void *); @@ -62,6 +70,10 @@ configure(void *dummy) { root_bus_configure(); +#ifdef DEV_ISA + if (isa_bus_device) + isa_probe_children(isa_bus_device); +#endif } static void diff --git a/sys/powerpc/powerpc/intr_machdep.c b/sys/powerpc/powerpc/intr_machdep.c index 3786f63..026cc02 100644 --- a/sys/powerpc/powerpc/intr_machdep.c +++ b/sys/powerpc/powerpc/intr_machdep.c @@ -60,6 +60,8 @@ * $FreeBSD$ */ +#include "opt_platform.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -83,6 +85,14 @@ #include "pic_if.h" +#ifdef MPC85XX +#define ISA_IRQ_COUNT 16 +#endif + +#ifndef ISA_IRQ_COUNT +#define ISA_IRQ_COUNT 0 +#endif + #define MAX_STRAY_LOG 5 MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data"); @@ -90,10 +100,12 @@ MALLOC_DEFINE(M_INTR, "intr", "interrupt handler data"); struct powerpc_intr { struct intr_event *event; long *cntp; - enum intr_trigger trig; - enum intr_polarity pol; u_int irq; + device_t pic; + u_int intline; u_int vector; + enum intr_trigger trig; + enum intr_polarity pol; }; static struct mtx intr_table_lock; @@ -108,6 +120,7 @@ static void *ipi_cookie; static u_int ipi_irq; device_t pic; +device_t pic8259; static void intr_init(void *dummy __unused) @@ -180,28 +193,50 @@ intr_lookup(u_int irq) return (i); } +static int +powerpc_map_irq(struct powerpc_intr *i) +{ + +#if ISA_IRQ_COUNT > 0 + if (i->irq < ISA_IRQ_COUNT) { + if (pic8259 == NULL) { + i->pic = pic; + i->intline = 0; + return (ENXIO); + } + i->pic = pic8259; + i->intline = i->irq; + return (0); + } +#endif + + i->pic = pic; + i->intline = i->irq - ISA_IRQ_COUNT; + return (0); +} + static void powerpc_intr_eoi(void *arg) { - u_int irq = (uintptr_t)arg; + struct powerpc_intr *i = arg; - PIC_EOI(pic, irq); + PIC_EOI(i->pic, i->intline); } static void powerpc_intr_mask(void *arg) { - u_int irq = (uintptr_t)arg; + struct powerpc_intr *i = arg; - PIC_MASK(pic, irq); + PIC_MASK(i->pic, i->intline); } static void powerpc_intr_unmask(void *arg) { - u_int irq = (uintptr_t)arg; + struct powerpc_intr *i = arg; - PIC_UNMASK(pic, irq); + PIC_UNMASK(i->pic, i->intline); } void @@ -209,17 +244,21 @@ powerpc_register_pic(device_t dev, u_int ipi) { pic = dev; - ipi_irq = ipi; + ipi_irq = ipi + ISA_IRQ_COUNT; +} + +void +powerpc_register_8259(device_t dev) +{ + + pic8259 = dev; } int powerpc_enable_intr(void) { struct powerpc_intr *i; -#ifdef SMP - int error; -#endif - int vector; + int error, vector; if (pic == NULL) panic("no PIC detected\n"); @@ -239,12 +278,16 @@ powerpc_enable_intr(void) 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(pic, i->irq, i->trig, i->pol); + PIC_CONFIG(i->pic, i->intline, i->trig, i->pol); if (i->event != NULL) - PIC_ENABLE(pic, i->irq, vector); + PIC_ENABLE(i->pic, i->intline, vector); } return (0); @@ -262,7 +305,7 @@ powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter, return (ENOMEM); if (i->event == NULL) { - error = intr_event_create(&i->event, (void *)irq, 0, irq, + error = intr_event_create(&i->event, (void *)i, 0, irq, powerpc_intr_mask, powerpc_intr_unmask, powerpc_intr_eoi, NULL, "irq%u:", irq); if (error) @@ -280,9 +323,11 @@ powerpc_setup_intr(const char *name, u_int irq, driver_filter_t filter, intrcnt_setname(i->event->ie_fullname, i->vector); mtx_unlock(&intr_table_lock); - if (!cold && enable) - PIC_ENABLE(pic, i->irq, i->vector); - + if (!cold) { + error = powerpc_map_irq(i); + if (!error && enable) + PIC_ENABLE(i->pic, i->intline, i->vector); + } return (error); } @@ -298,9 +343,6 @@ powerpc_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol) { struct powerpc_intr *i; - if (trig == INTR_TRIGGER_CONFORM && pol == INTR_POLARITY_CONFORM) - return (0); - i = intr_lookup(irq); if (i == NULL) return (ENOMEM); @@ -309,7 +351,7 @@ powerpc_config_intr(int irq, enum intr_trigger trig, enum intr_polarity pol) i->pol = pol; if (!cold) - PIC_CONFIG(pic, irq, trig, pol); + PIC_CONFIG(i->pic, i->intline, trig, pol); return (0); } @@ -344,5 +386,5 @@ stray: } } if (i != NULL) - PIC_MASK(pic, i->irq); + PIC_MASK(i->pic, i->intline); } |