summaryrefslogtreecommitdiffstats
path: root/sys/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'sys/powerpc')
-rw-r--r--sys/powerpc/conf/MPC85XX1
-rw-r--r--sys/powerpc/include/intr_machdep.h2
-rw-r--r--sys/powerpc/mpc85xx/atpic.c330
-rw-r--r--sys/powerpc/mpc85xx/isa.c100
-rw-r--r--sys/powerpc/mpc85xx/ocpbus.c23
-rw-r--r--sys/powerpc/mpc85xx/pci_ocp.c127
-rw-r--r--sys/powerpc/powerpc/autoconf.c12
-rw-r--r--sys/powerpc/powerpc/intr_machdep.c90
8 files changed, 595 insertions, 90 deletions
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);
}
OpenPOWER on IntegriCloud