From fe98624bbbe09125f4467ea5b13884429395c4c3 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Mon, 3 Jan 2000 06:45:16 +0000 Subject: [PATCH] Connect interrupts and start processing them. We panic on card removal now, but we're getting interrupts! o Add pcic_suspend/pcic_resume so we can detach our children on suspention and fix the state of the pcic on resume. o Remove some unused parts of softc. o Centralize resource activation/deactivation for pcic bridge chip in the stylistic pcic_activate/pcic_deactivate. o Add bus_print_child method so we can see the pccard attachment. o Add pcic_identify in an attempt to make it possible to automatically id the pcic devices. This works great, but we cannot divine the irq to use from this method, nor the memory hole. For the moment, KLUDGE irq to be 10 and memory hold to be 0xd0000. o Loose the pnp probe stuff. This may be a big mistake, but it is easy enough to add back later. I did this so the identify routines can do their thing unmolested by pnp information. The whole identify thing may be a bad idea to be ripped out later. o change return type of pcic_intr to void, make it static and ripple this through the code. o Add explicit call to bus_generic_attach at the end of pcic_attach to get any children probed/attached. o add some comments about future directions/questionable things being done at different layers, etc. --- sys/dev/pccard/pccard.c | 4 +- sys/dev/pcic/i82365.c | 145 ++++++++++++++++++++++++++++++++++---- sys/dev/pcic/i82365_isa.c | 116 +++++++++++++++--------------- sys/dev/pcic/i82365var.h | 20 +++--- 4 files changed, 197 insertions(+), 88 deletions(-) diff --git a/sys/dev/pccard/pccard.c b/sys/dev/pccard/pccard.c index 67a4ae16c3f1..927941d5a54f 100644 --- a/sys/dev/pccard/pccard.c +++ b/sys/dev/pccard/pccard.c @@ -77,12 +77,13 @@ int pccard_card_intr(void *); int pccard_card_intrdebug(void *); #endif +/* XXX Shouldn't be touching hardware, that's a layering violation */ +/* XXX imp */ int pccard_ccr_read(pf, ccr) struct pccard_function *pf; int ccr; { - return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh, pf->pf_ccr_offset + ccr)); } @@ -839,7 +840,6 @@ pccard_card_intrdebug(arg) static int pccard_add_children(device_t dev, int busno) { - device_add_child(dev, NULL, -1); return 0; } diff --git a/sys/dev/pcic/i82365.c b/sys/dev/pcic/i82365.c index 4bb534a9fae2..74c774267ff5 100644 --- a/sys/dev/pcic/i82365.c +++ b/sys/dev/pcic/i82365.c @@ -62,6 +62,8 @@ int pcic_debug = 0; #else #define DPRINTF(arg) #endif +/* To later turn into debug */ +#define DEVPRINTF(arg) device_printf arg; #define DETACH_FORCE 0x1 @@ -80,11 +82,15 @@ int pcic_debug = 0; static void pcic_init_socket(struct pcic_handle *); -int pcic_intr_socket(struct pcic_handle *); +static void pcic_intr_socket(struct pcic_handle *); -void pcic_attach_card(struct pcic_handle *); -void pcic_detach_card(struct pcic_handle *, int); -void pcic_deactivate_card(struct pcic_handle *); +static void pcic_deactivate(device_t dev); +static int pcic_activate(device_t dev); +static void pcic_intr(void *arg); + +void pcic_attach_card(struct pcic_handle *); +void pcic_detach_card(struct pcic_handle *, int); +void pcic_deactivate_card(struct pcic_handle *); static void pcic_chip_do_mem_map(struct pcic_handle *, int); static void pcic_chip_do_io_map(struct pcic_handle *, int); @@ -172,21 +178,104 @@ pcic_vendor_to_string(int vendor) return ("Unknown controller"); } -void +static int +pcic_activate(device_t dev) +{ + struct pcic_softc *sc = (struct pcic_softc *) + device_get_softc(dev); + int err; + + sc->port_rid = 0; + sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, + 0, ~0, PCIC_IOSIZE, RF_ACTIVE); + if (!sc->port_res) { +#ifdef PCIC_DEBUG + device_printf(dev, "Cannot allocate ioport\n"); +#endif + return ENOMEM; + } + + sc->irq_rid = 0; + sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, + 0, ~0, 1, RF_ACTIVE); + if (!sc->irq_res) { +#ifdef PCIC_DEBUG + device_printf(dev, "Cannot allocate irq\n"); +#endif + pcic_deactivate(dev); + return ENOMEM; + } + sc->irq = rman_get_start(sc->irq_res); + if ((err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, pcic_intr, + sc, &sc->intrhand)) != 0) { + pcic_deactivate(dev); + return err; + } + + sc->mem_rid = 0; + sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid, + 0, ~0, 1 << 13, RF_ACTIVE); + if (!sc->mem_res) { +#ifdef PCIC_DEBUG + device_printf(dev, "Cannot allocate mem\n"); +#endif + pcic_deactivate(dev); + return ENOMEM; + } + sc->subregionmask = (1 << + ((rman_get_end(sc->mem_res) - rman_get_start(sc->mem_res) + 1) / + PCIC_MEM_PAGESIZE)) - 1; + + sc->iot = rman_get_bustag(sc->port_res); + sc->ioh = rman_get_bushandle(sc->port_res);; + sc->memt = rman_get_bustag(sc->mem_res); + sc->memh = rman_get_bushandle(sc->mem_res);; + + return (0); +} + +static void +pcic_deactivate(device_t dev) +{ + struct pcic_softc *sc = device_get_softc(dev); + + if (sc->intrhand) + bus_teardown_intr(dev, sc->irq_res, sc->intrhand); + sc->intrhand = 0; + if (sc->port_res) + bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid, + sc->port_res); + sc->port_res = 0; + if (sc->irq_res) + bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, + sc->irq_res); + sc->irq_res = 0; + if (sc->mem_res) + bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, + sc->mem_res); + sc->mem_res = 0; + return; +} + +int pcic_attach(device_t dev) { struct pcic_softc *sc = (struct pcic_softc *) device_get_softc(dev); struct pcic_handle *h; - int vendor, count, i, reg; + int vendor, count, i, reg, error; sc->dev = dev; + /* Activate our resources */ + if ((error = pcic_activate(dev)) != 0) + return error; + /* now check for each controller/socket */ /* * this could be done with a loop, but it would violate the - * abstraction + * abstraction... so? --imp */ count = 0; @@ -349,6 +438,14 @@ pcic_attach(device_t dev) device_set_ivars(h->dev, h); pcic_init_socket(h); } + + /* + * Probe and attach any children as were configured above. + */ + error = bus_generic_attach(dev); + if (error) + pcic_deactivate(dev); + return error; } void @@ -512,22 +609,20 @@ pcic_init_socket(struct pcic_handle *h) } } -int +static void pcic_intr(void *arg) { struct pcic_softc *sc = arg; - int i, ret = 0; + int i; - DPRINTF(("%s: intr\n", sc->dev.dv_xname)); + DEVPRINTF((sc->dev, "intr\n")); for (i = 0; i < PCIC_NSLOTS; i++) if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) - ret += pcic_intr_socket(&sc->handle[i]); - - return (ret ? 1 : 0); + pcic_intr_socket(&sc->handle[i]); } -int +static void pcic_intr_socket(struct pcic_handle *h) { int cscreg; @@ -581,7 +676,6 @@ pcic_intr_socket(struct pcic_handle *h) if (cscreg & PCIC_CSC_BATTDEAD) { DPRINTF(("%s: %02x BATTDEAD\n", h->ph_parent->dv_xname, h->sock)); } - return (cscreg ? 1 : 0); } void @@ -1377,6 +1471,27 @@ pcic_release_resource(device_t dev, device_t child, int type, int rid, return bus_generic_release_resource(dev, child, type, rid, r); } +int +pcic_suspend(device_t dev) +{ + /* + * Do nothing for now, maybe in time do what FreeBSD's current + * pccard code does and detach my children. That's the safest thing + * to do since we don't want to wake up and have different hardware + * in the slots. + */ + + return 0; +} + +int +pcic_resume(device_t dev) +{ + /* Need to port pcic_power from newer netbsd versions of this file */ + + return 0; +} + static void pcic_start_threads(void *arg) { diff --git a/sys/dev/pcic/i82365_isa.c b/sys/dev/pcic/i82365_isa.c index 1360c93b9f13..c390be1e708e 100644 --- a/sys/dev/pcic/i82365_isa.c +++ b/sys/dev/pcic/i82365_isa.c @@ -225,7 +225,7 @@ pcic_isa_bus_width_probe (device_t dev) } static int -pcic_isa_probe(device_t dev) +pcic_isa_check(device_t dev, u_int16_t addr) { bus_space_tag_t iot; bus_space_handle_t ioh; @@ -233,13 +233,9 @@ pcic_isa_probe(device_t dev) int rid; struct resource *res; - /* Check isapnp ids */ - if (ISA_PNP_PROBE(device_get_parent(dev), dev, pcic_ids) == ENXIO) - return (ENXIO); - rid = 0; - res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, PCIC_IOSIZE, - RF_ACTIVE); + res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, addr, addr, + PCIC_IOSIZE, RF_ACTIVE); if (!res) return(ENXIO); iot = rman_get_bustag(res); @@ -272,67 +268,65 @@ pcic_isa_probe(device_t dev) bus_release_resource(dev, SYS_RES_IOPORT, rid, res); - /* XXX DO I NEED TO WORRY ABOUT the IRQ? XXX */ + return (found); +} - if (!found) +static void +pcic_isa_identify(driver_t *driver, device_t parent) +{ + device_t child; + u_int16_t ioaddrs[] = { 0x3e0, 0x3e2, 0x3e4, 0x3e6, 0 }; + u_int16_t ioaddr; + int i; + + for (i = 0; ioaddrs[i]; i++) { + ioaddr = ioaddrs[i]; + if (pcic_isa_check(parent, ioaddr)) { + child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, + "pcic", -1); + device_set_driver(child, driver); +/* XXX */ + bus_set_resource(child, SYS_RES_IRQ, 0, 10, 1); + bus_set_resource(child, SYS_RES_MEMORY, 0, 0xd0000, 1 << 12); + bus_set_resource(child, SYS_RES_IOPORT, 0, ioaddr, + PCIC_IOSIZE); + } + } +} + +static int +pcic_isa_probe(device_t dev) +{ + int error; + + /* Check isapnp ids */ + error = ISA_PNP_PROBE(device_get_parent(dev), dev, pcic_ids); + if (error == ENXIO) return (ENXIO); - return (0); + /* If we had some other problem. */ + if (!(error == 0 || error == ENOENT)) { + return (error); + } + + /* If we have the resources we need then we're good to go. */ + if ((bus_get_resource_start(dev, SYS_RES_IOPORT, 0) != 0) && + (bus_get_resource_start(dev, SYS_RES_IRQ, 0) != 0)) { + return (0); + } + + return (ENXIO); } static int pcic_isa_attach(device_t dev) { - struct pcic_softc *sc = (struct pcic_softc *) device_get_softc(dev); + int err = 0; - sc->port_rid = 0; - sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid, - 0, ~0, PCIC_IOSIZE, RF_ACTIVE); - if (!sc->port_res) { - device_printf(dev, "Unable to allocate I/O ports\n"); - goto error; - } - - sc->mem_rid = 0; - sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid, - 0, ~0, 1 << 13, RF_ACTIVE); - if (!sc->mem_res) { - device_printf(dev, "Unable to allocate memory range\n"); - goto error; - } - - sc->subregionmask = (1 << - ((rman_get_end(sc->mem_res) - rman_get_start(sc->mem_res) + 1) / - PCIC_MEM_PAGESIZE)) - 1; + if ((err = pcic_attach(dev)) == 0) + pcic_isa_bus_width_probe (dev); - sc->irq_rid = 0; - sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid, - 0, ~0, 1, RF_ACTIVE); - if (!sc->irq_res) { - device_printf(dev, "Unable to allocate irq\n"); - goto error; - } - - sc->iot = rman_get_bustag(sc->port_res); - sc->ioh = rman_get_bushandle(sc->port_res);; - sc->memt = rman_get_bustag(sc->mem_res); - sc->memh = rman_get_bushandle(sc->mem_res);; - - pcic_attach(dev); - pcic_isa_bus_width_probe (dev); - - return 0; - error: - if (sc->port_res) - bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid, - sc->port_res); - if (sc->mem_res) - bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, - sc->mem_res); - if (sc->irq_res) - bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid, - sc->irq_res); - return ENOMEM; + return err; } static int @@ -343,15 +337,17 @@ pcic_isa_detach(device_t dev) static device_method_t pcic_isa_methods[] = { /* Device interface */ + DEVMETHOD(device_identify, pcic_isa_identify), DEVMETHOD(device_probe, pcic_isa_probe), DEVMETHOD(device_attach, pcic_isa_attach), DEVMETHOD(device_detach, pcic_isa_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_suspend, pcic_suspend), + DEVMETHOD(device_resume, pcic_resume), /* Bus Interface */ DEVMETHOD(bus_driver_added, bus_generic_driver_added), + DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_alloc_resource, pcic_alloc_resource), DEVMETHOD(bus_release_resource, pcic_release_resource), DEVMETHOD(bus_activate_resource, pcic_activate_resource), diff --git a/sys/dev/pcic/i82365var.h b/sys/dev/pcic/i82365var.h index 01b501026011..e6d0f7eebb01 100644 --- a/sys/dev/pcic/i82365var.h +++ b/sys/dev/pcic/i82365var.h @@ -101,16 +101,13 @@ struct pcic_softc { bus_space_tag_t iot; bus_space_handle_t ioh; - struct resource *port_res; - int port_rid; - struct resource *mem_res; - int mem_rid; + void *intrhand; struct resource *irq_res; - int irq_rid; - - - /* XXX isa_chipset_tag_t, pci_chipset_tag_t, etc. */ - void *intr_est; + int irq_rid; + struct resource *mem_res; + int mem_rid; + struct resource *port_res; + int port_rid; /* this needs to be large enough to hold PCIC_MEM_PAGES bits */ int subregionmask; @@ -140,8 +137,7 @@ int pcic_ident_ok(int); int pcic_vendor(struct pcic_handle *); char *pcic_vendor_to_string(int); -void pcic_attach(device_t dev); -int pcic_intr(void *arg); +int pcic_attach(device_t dev); #if 0 @@ -193,3 +189,5 @@ int pcic_setup_intr(device_t dev, device_t child, struct resource *irq, int flags, driver_intr_t intr, void *arg, void **cookiep); int pcic_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookiep); +int pcic_suspend(device_t dev); +int pcic_resume(device_t dev);