From owner-p4-projects@FreeBSD.ORG Tue Aug 8 15:07:39 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3EE9116A4DE; Tue, 8 Aug 2006 15:07:39 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id DC13516A4E0 for ; Tue, 8 Aug 2006 15:07:38 +0000 (UTC) (envelope-from gonzo@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id C55DC43D5A for ; Tue, 8 Aug 2006 15:07:37 +0000 (GMT) (envelope-from gonzo@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k78F7bsI005480 for ; Tue, 8 Aug 2006 15:07:37 GMT (envelope-from gonzo@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k78F7bUh005471 for perforce@freebsd.org; Tue, 8 Aug 2006 15:07:37 GMT (envelope-from gonzo@FreeBSD.org) Date: Tue, 8 Aug 2006 15:07:37 GMT Message-Id: <200608081507.k78F7bUh005471@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to gonzo@FreeBSD.org using -f From: Oleksandr Tymoshenko To: Perforce Change Reviews Cc: Subject: PERFORCE change 103448 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 Aug 2006 15:07:39 -0000 http://perforce.freebsd.org/chv.cgi?CH=103448 Change 103448 by gonzo@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 #include #include +#include #include #include @@ -39,20 +40,17 @@ #include #include +#include + #include #include -#include #include -#include -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 #include + +#include #include -#include #include #include #include @@ -63,31 +64,140 @@ #include #include +#include +#include + #include #include #include #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 . Respective file + * from FreeBSD src tree 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 + */ + 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_ */