PERFORCE change 103448 for review
Oleksandr Tymoshenko
gonzo at FreeBSD.org
Tue Aug 8 15:07:39 UTC 2006
http://perforce.freebsd.org/chv.cgi?CH=103448
Change 103448 by gonzo at gonzo_hq on 2006/08/08 15:07:25
o Heavily refactored GT code. "gt" device reduced to abstraction,
bus methods proxy between nexus device and GT south bridge.
gt_pci.c is a simplified version of GT pci bridge implementation
from NetBSD.
Affected files ...
.. //depot/projects/mips2/src/sys/mips/mips4k/malta/gt.c#2 edit
.. //depot/projects/mips2/src/sys/mips/mips4k/malta/gt_pci.c#2 edit
.. //depot/projects/mips2/src/sys/mips/mips4k/malta/gtvar.h#2 edit
Differences ...
==== //depot/projects/mips2/src/sys/mips/mips4k/malta/gt.c#2 (text+ko) ====
@@ -31,6 +31,7 @@
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
+#include <sys/rman.h>
#include <sys/types.h>
#include <vm/vm.h>
@@ -39,20 +40,17 @@
#include <vm/vm_page.h>
#include <vm/vm_extern.h>
+#include <dev/ic/i8259.h>
+
#include <machine/bus.h>
#include <machine/intr_machdep.h>
-#include <mips/mips4k/malta/gtreg.h>
#include <mips/mips4k/malta/gtvar.h>
-#include <mips/mips4k/malta/maltareg.h>
-extern void irq_entry(void);
-struct gt_softc *gt_softc;
-
static int
gt_probe(device_t dev)
{
- device_set_desc(dev, "GT64120 device bus");
+ device_set_desc(dev, "GT64120 chip");
return (0);
}
@@ -66,34 +64,13 @@
gt_attach(device_t dev)
{
struct gt_softc *sc = device_get_softc(dev);
- /* int i; */
-
- gt_softc = sc;
- sc->sc_st = MIPS_BUS_SPACE_MEM;
- sc->sc_sh = MALTA_PCIMEM1_BASE;
sc->dev = dev;
- if (bus_space_subregion(sc->sc_st, sc->sc_sh,
- MIPS_PHYS_TO_KSEG1(MALTA_PCIMEM1_BASE),
- MALTA_PCIMEM1_SIZE, &sc->sc_sys_sh) != 0)
- panic("Enable to map IRQ registers");
- sc->sc_irq_rman.rm_type = RMAN_ARRAY;
- sc->sc_irq_rman.rm_descr = "GT64120 IRQs";
- sc->sc_mem_rman.rm_type = RMAN_ARRAY;
- sc->sc_mem_rman.rm_descr = "GT64120 Memory";
- if (rman_init(&sc->sc_irq_rman) != 0 ||
- rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0)
- panic("gt_attach: failed to set up IRQ rman");
- if (rman_init(&sc->sc_mem_rman) != 0 ||
- rman_manage_region(&sc->sc_mem_rman,
- MIPS_PHYS_TO_KSEG1(MALTA_PCIMEM1_BASE),
- MIPS_PHYS_TO_KSEG1(MALTA_PCIMEM1_BASE +
- MALTA_PCIMEM1_SIZE)) != 0)
- panic("gt_attach: failed to set up memory rman");
- /* XXXMIPS: Disable and clear all interrupts. */
device_add_child(dev, "pcib", 0);
bus_generic_probe(dev);
bus_generic_attach(dev);
+
+
return (0);
}
@@ -101,140 +78,44 @@
gt_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 gt_softc *sc = device_get_softc(dev);
- struct resource_list_entry *rle;
- struct gt_ivar *ivar = device_get_ivars(child);
- struct resource_list *rl = &ivar->resources;
-
- if (device_get_parent(child) != dev)
- return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
+ return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child,
type, rid, start, end, count, flags));
- rle = resource_list_find(rl, type, *rid);
- if (rle == NULL)
- return (NULL);
- if (rle->res)
- panic("Resource rid %d type %d already in use", *rid, type);
- if (start == 0UL && end == ~0UL) {
- start = rle->start;
- count = ulmax(count, rle->count);
- end = ulmax(rle->end, start + count - 1);
- }
- switch (type)
- {
- case SYS_RES_IRQ:
- rle->res = rman_reserve_resource(&sc->sc_irq_rman,
- start, end, count, flags, child);
- break;
- case SYS_RES_MEMORY:
- rle->res = rman_reserve_resource(&sc->sc_mem_rman,
- start, end, count, flags, child);
- rman_set_bustag(rle->res, MIPS_BUS_SPACE_MEM);
- rman_set_bushandle(rle->res, start);
- break;
- }
- if (rle->res) {
- rle->start = rman_get_start(rle->res);
- rle->end = rman_get_end(rle->res);
- rle->count = count;
- rman_set_rid(rle->res, *rid);
- }
- return (rle->res);
}
-static struct resource_list *
-gt_get_resource_list(device_t dev, device_t child)
-{
- struct gt_ivar *ivar;
-
- ivar = device_get_ivars(child);
- return (&(ivar->resources));
-}
-
static int
-gt_release_resource(device_t dev, device_t child, int type,
- int rid, struct resource *r)
-{
- struct resource_list *rl;
- struct resource_list_entry *rle;
-
- rl = gt_get_resource_list(dev, child);
- if (rl == NULL)
- return (EINVAL);
- rle = resource_list_find(rl, type, rid);
- if (rle == NULL)
- return (EINVAL);
- rman_release_resource(r);
- rle->res = NULL;
- return (0);
-}
-
-static int
gt_setup_intr(device_t dev, device_t child,
struct resource *ires, int flags, driver_intr_t *intr, void *arg,
void **cookiep)
{
-#if 0
- int x = rman_get_start(ires);
- printf("IRQ request: %d\n", x);
- struct gt_softc *sc = device_get_softc(dev);
-
- if (rman_get_start(ires) == AT91RM92_IRQ_SYSTEM && !(flags & INTR_FAST))
- panic("All system interrupt ISRs must be type INTR_FAST");
- BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags, intr, arg,
- cookiep);
- bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_IECR,
- 1 << rman_get_start(ires));
-#endif
- printf("Unimplemented %s at %s:%d\n", __func__, __FILE__, __LINE__);
- return (0);
+ return BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
+ intr, arg, cookiep);
}
static int
gt_teardown_intr(device_t dev, device_t child, struct resource *res,
void *cookie)
{
-#if 0
- struct gt_softc *sc = device_get_softc(dev);
- bus_space_write_4(sc->sc_st, sc->sc_sys_sh, IC_IDCR,
- 1 << rman_get_start(res));
return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
-#endif
- printf("Unimplemented %s at %s:%d\n", __func__, __FILE__, __LINE__);
- return (0);
}
static int
-gt_activate_resource(device_t bus, device_t child, int type, int rid,
+gt_activate_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
- bus_space_handle_t p;
- int error;
-
- if (type == SYS_RES_MEMORY) {
- error = bus_space_map(rman_get_bustag(r),
- rman_get_bushandle(r), rman_get_size(r), 0, &p);
- if (error)
- return (error);
- rman_set_bushandle(r, p);
- }
- return (rman_activate_resource(r));
+ return (BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child,
+ type, rid, r));
}
static device_method_t gt_methods[] = {
DEVMETHOD(device_probe, gt_probe),
+ DEVMETHOD(device_identify, gt_identify),
DEVMETHOD(device_attach, gt_attach),
- DEVMETHOD(device_identify, gt_identify),
- DEVMETHOD(bus_alloc_resource, gt_alloc_resource),
DEVMETHOD(bus_setup_intr, gt_setup_intr),
DEVMETHOD(bus_teardown_intr, gt_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, gt_alloc_resource),
DEVMETHOD(bus_activate_resource, gt_activate_resource),
- DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
- DEVMETHOD(bus_get_resource_list,gt_get_resource_list),
- DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
- DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
- DEVMETHOD(bus_release_resource, gt_release_resource),
DEVMETHOD(bus_print_child, bus_generic_print_child),
{0, 0},
==== //depot/projects/mips2/src/sys/mips/mips4k/malta/gt_pci.c#2 (text+ko) ====
@@ -44,8 +44,9 @@
#include <sys/param.h>
#include <sys/systm.h>
+
+#include <sys/bus.h>
#include <sys/malloc.h>
-#include <sys/bus.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/rman.h>
@@ -63,31 +64,140 @@
#include <mips/mips4k/malta/gtreg.h>
#include <mips/mips4k/malta/gtvar.h>
+#include <isa/isareg.h>
+#include <dev/ic/i8259.h>
+
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcib_private.h>
#include "pcib_if.h"
-extern struct gt_softc *gt_softc;
+
+#define ICU_LEN 16 /* number of ISA IRQs */
+
+/*
+ * XXX: These defines are from NetBSD's <dev/ic/i8259reg.h>. Respective file
+ * from FreeBSD src tree <dev/ic/i8259.h> lacks some definitions.
+ */
+#define PIC_OCW1 1
+#define PIC_OCW2 0
+#define PIC_OCW3 0
+
+#define OCW2_SELECT 0
+#define OCW2_ILS(x) ((x) << 0) /* interrupt level select */
+
+#define OCW3_POLL_IRQ(x) ((x) & 0x7f)
+#define OCW3_POLL_PENDING (1U << 7)
+
+struct intrhand {
+ LIST_ENTRY(intrhand) ih_list;
+ driver_intr_t *ih_func;
+ void *ih_arg;
+ int ih_irq;
+};
+
+struct pci_intrhead {
+ LIST_HEAD(, intrhand) intr_list;
+};
struct gt_pci_softc {
device_t sc_dev;
bus_space_tag_t sc_st;
bus_space_tag_t sc_pciio;
bus_space_tag_t sc_pcimem;
+ bus_space_handle_t sc_ioh_icu1;
+ bus_space_handle_t sc_ioh_icu2;
+ bus_space_handle_t sc_ioh_elcr;
+
int sc_busno;
struct rman sc_mem_rman;
struct rman sc_io_rman;
struct rman sc_irq_rman;
uint32_t sc_mem;
uint32_t sc_io;
+
+ struct resource *sc_irq;
+ struct pci_intrhead sc_intrtab[ICU_LEN];
+ uint16_t sc_imask;
+ uint16_t sc_elcr;
+
+ uint16_t sc_reserved;
+
+ void *sc_ih;
};
+static void
+gt_pci_set_icus(struct gt_pci_softc *sc)
+{
+ /* Enable the cascade IRQ (2) if 8-15 is enabled. */
+ if ((sc->sc_imask & 0xff00) != 0xff00)
+ sc->sc_imask &= ~(1U << 2);
+ else
+ sc->sc_imask |= (1U << 2);
+
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu1, PIC_OCW1,
+ sc->sc_imask & 0xff);
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu2, PIC_OCW1,
+ (sc->sc_imask >> 8) & 0xff);
+
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_elcr, 0,
+ sc->sc_elcr & 0xff);
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_elcr, 1,
+ (sc->sc_elcr >> 8) & 0xff);
+}
+
+static void
+gt_pci_intr(void *v)
+{
+ struct gt_pci_softc *sc = v;
+ struct intrhand *ih;
+ int irq;
+
+ for (;;) {
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu1, PIC_OCW3,
+ OCW3_SEL | OCW3_P);
+ irq = bus_space_read_1(sc->sc_pciio, sc->sc_ioh_icu1, PIC_OCW3);
+ if ((irq & OCW3_POLL_PENDING) == 0)
+ {
+ return;
+ }
+
+ irq = OCW3_POLL_IRQ(irq);
+
+ if (irq == 2) {
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu2,
+ PIC_OCW3, OCW3_SEL | OCW3_P);
+ irq = bus_space_read_1(sc->sc_pciio, sc->sc_ioh_icu2,
+ PIC_OCW3);
+ if (irq & OCW3_POLL_PENDING)
+ irq = OCW3_POLL_IRQ(irq) + 8;
+ else
+ irq = 2;
+ }
+
+ LIST_FOREACH(ih, &sc->sc_intrtab[irq].intr_list, ih_list)
+ (*ih->ih_func)(ih->ih_arg);
+
+ /* Send a specific EOI to the 8259. */
+ if (irq > 7) {
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu2,
+ PIC_OCW2, OCW2_SELECT | OCW2_EOI | OCW2_SL |
+ OCW2_ILS(irq & 7));
+ irq = 2;
+ }
+
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu1, PIC_OCW2,
+ OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(irq));
+ }
+}
+
+
+
static int
gt_pci_probe(device_t dev)
{
- device_set_desc(dev, "GT64120 PCI bus");
+ device_set_desc(dev, "GT64120 PCI bridge");
return (0);
}
@@ -97,8 +207,8 @@
uint32_t busno;
struct gt_pci_softc *sc = device_get_softc(dev);
+ int rid, i;
- sc->sc_st = gt_softc->sc_st;
busno = 0;
sc->sc_dev = dev;
sc->sc_busno = busno;
@@ -129,6 +239,130 @@
rman_manage_region(&sc->sc_irq_rman, 1, 31) != 0)
panic("gt_pci_attach: failed to set up IRQ rman");
+ /*
+ * Map the PIC/ELCR registers.
+ */
+#if 0
+ if (bus_space_map(sc->sc_pciio, 0x4d0, 2, 0, &sc->sc_ioh_elcr) != 0)
+ device_printf(dev, "unable to map ELCR registers\n");
+ if (bus_space_map(sc->sc_pciio, IO_ICU1, 2, 0, &sc->sc_ioh_icu1) != 0)
+ device_printf(dev, "unable to map ICU1 registers\n");
+ if (bus_space_map(sc->sc_pciio, IO_ICU2, 2, 0, &sc->sc_ioh_icu2) != 0)
+ device_printf(dev, "unable to map ICU2 registers\n");
+#else
+ sc->sc_ioh_elcr = sc->sc_io + 0x4d0;
+ sc->sc_ioh_icu1 = sc->sc_io + IO_ICU1;
+ sc->sc_ioh_icu2 = sc->sc_io + IO_ICU2;
+#endif
+
+
+ /* All interrupts default to "masked off". */
+ sc->sc_imask = 0xffff;
+
+ /* All interrupts default to edge-triggered. */
+ sc->sc_elcr = 0;
+
+ /*
+ * Initialize the 8259s.
+ */
+ /* reset, program device, 4 bytes */
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu1, 0,
+ ICW1_RESET | ICW1_IC4);
+ /*
+ * XXX: values from NetBSD's <dev/ic/i8259reg.h>
+ */
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu1, 1,
+ 0/*XXX*/);
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu1, 1,
+ 1 << 2);
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu1, 1,
+ ICW4_8086);
+
+ /* mask all interrupts */
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu1, 0,
+ sc->sc_imask & 0xff);
+
+ /* enable special mask mode */
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu1, 1,
+ OCW3_SEL | OCW3_ESMM | OCW3_SMM);
+
+ /* read IRR by default */
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu1, 1,
+ OCW3_SEL | OCW3_RR);
+
+ /* reset, program device, 4 bytes */
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu2, 0,
+ ICW1_RESET | ICW1_IC4);
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu2, 1,
+ 0/*XXX*/);
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu2, 1,
+ 1 << 2);
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu2, 1,
+ ICW4_8086);
+
+ /* mask all interrupts */
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu2, 0,
+ sc->sc_imask & 0xff);
+
+ /* enable special mask mode */
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu2, 1,
+ OCW3_SEL | OCW3_ESMM | OCW3_SMM);
+
+ /* read IRR by default */
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_icu2, 1,
+ OCW3_SEL | OCW3_RR);
+
+ /*
+ * Default all interrupts to edge-triggered.
+ */
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_elcr, 0,
+ sc->sc_elcr & 0xff);
+ bus_space_write_1(sc->sc_pciio, sc->sc_ioh_elcr, 1,
+ (sc->sc_elcr >> 8) & 0xff);
+
+ /*
+ * Some ISA interrupts are reserved for devices that
+ * we know are hard-wired to certain IRQs.
+ */
+ sc->sc_reserved =
+ (1U << 0) | /* timer */
+ (1U << 1) | /* keyboard controller (keyboard) */
+ (1U << 2) | /* PIC cascade */
+ (1U << 3) | /* COM 2 */
+ (1U << 4) | /* COM 1 */
+ (1U << 6) | /* floppy */
+ (1U << 7) | /* centronics */
+ (1U << 8) | /* RTC */
+ (1U << 9) | /* I2C */
+ (1U << 12) | /* keyboard controller (mouse) */
+ (1U << 14) | /* IDE primary */
+ (1U << 15); /* IDE secondary */
+
+ /* Initialize our interrupt table. */
+ for (i = 0; i < ICU_LEN; i++) {
+ LIST_INIT(&sc->sc_intrtab[i].intr_list);
+ }
+
+ /* Hook up our interrupt handler. */
+ if ((sc->sc_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid,
+ MALTA_SOUTHBRIDGE_INTR, MALTA_SOUTHBRIDGE_INTR, 1,
+ RF_SHAREABLE | RF_ACTIVE)) == NULL) {
+ device_printf(dev, "unable to allocate IRQ resource\n");
+ return ENXIO;
+ }
+
+ if ((bus_setup_intr(dev, sc->sc_irq, INTR_FAST | INTR_MPSAFE,
+ gt_pci_intr, sc, &sc->sc_ih))) {
+ device_printf(dev,
+ "WARNING: unable to register interrupt handler\n");
+ return ENXIO;
+ }
+
+ if (sc->sc_ih == NULL)
+
+
+
+
/* Initialize memory and i/o rmans. */
device_add_child(dev, "pci", busno);
return (bus_generic_attach(dev));
@@ -263,9 +497,9 @@
*/
switch (device) {
case 9: /*
- * PIIX4 IDE adapter
+ * PIIX4 IDE adapter. HW IRQ0
*/
- return 2;
+ return 0;
default:
printf("No mapping for %d/%d/%d/%d\n", bus, device, func, pin);
@@ -369,23 +603,53 @@
struct resource *ires, int flags, driver_intr_t *intr, void *arg,
void **cookiep)
{
-#if 0
- return (BUS_SETUP_INTR(device_get_parent(dev), child, ires, flags,
- intr, arg, cookiep));
-#endif
- printf("Unimplemented %s at %s:%d\n", __func__, __FILE__, __LINE__);
- return (0);
+ struct gt_pci_softc *sc = device_get_softc(dev);
+ struct intrhand *ih;
+ int irq;
+
+ irq = rman_get_start(ires);
+ if (irq >= ICU_LEN || irq == 2)
+ panic("%s: bad irq or type", __func__);
+
+ ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
+ if (ih == NULL)
+ return ENOMEM;
+
+ ih->ih_func = intr;
+ ih->ih_arg = arg;
+ ih->ih_irq = irq;
+
+ /* Insert the handler into the table. */
+ LIST_INSERT_HEAD(&sc->sc_intrtab[irq].intr_list, ih, ih_list);
+
+ /* Enable it, set trigger mode. */
+ sc->sc_imask &= ~(1 << irq);
+ sc->sc_elcr &= ~(1 << irq);
+
+ gt_pci_set_icus(sc);
+
+ *cookiep = (void *)ih;
+
+ return 0;
}
static int
gt_pci_teardown_intr(device_t dev, device_t child, struct resource *res,
void *cookie)
{
-#if 0
- return (BUS_TEARDOWN_INTR(device_get_parent(dev), child, res, cookie));
-#endif
- printf("Unimplemented %s at %s:%d\n", __func__, __FILE__, __LINE__);
- return (0);
+ struct gt_pci_softc *sc = device_get_softc(dev);
+ struct intrhand *ih = cookie;
+ LIST_REMOVE(ih, ih_list);
+
+ /* If there are no more handlers on this IRQ, disable it. */
+ if (LIST_FIRST(&sc->sc_intrtab[ih->ih_irq].intr_list) == NULL) {
+ sc->sc_imask |= (1 << ih->ih_irq);
+ gt_pci_set_icus(sc);
+ }
+
+ free(ih, M_DEVBUF);
+
+ return 0;
}
static device_method_t gt_pci_methods[] = {
==== //depot/projects/mips2/src/sys/mips/mips4k/malta/gtvar.h#2 (text+ko) ====
@@ -31,16 +31,6 @@
struct gt_softc {
device_t dev;
- bus_space_tag_t sc_st;
- bus_space_handle_t sc_sh;
- bus_space_handle_t sc_sys_sh;
- struct rman sc_irq_rman;
- struct rman sc_mem_rman;
};
-struct gt_ivar {
- struct resource_list resources;
-};
-
-
#endif /* _GTVAR_H_ */
More information about the p4-projects
mailing list