diff --git a/sys/dev/pccard/pccard.c b/sys/dev/pccard/pccard.c index 4194275d8d19..622c198e453b 100644 --- a/sys/dev/pccard/pccard.c +++ b/sys/dev/pccard/pccard.c @@ -263,9 +263,10 @@ pccard_attach_card(device_t dev) pccard_set_default_descr(child) == 0 && device_probe_and_attach(child) == 0) { DEVPRINTF((sc->dev, "function %d CCR at %d " - "offset %x: %x %x %x %x, %x %x %x %x, %x\n", + "offset %x mask %x: " + "%x %x %x %x, %x %x %x %x, %x\n", pf->number, pf->pf_ccr_window, pf->pf_ccr_offset, - pccard_ccr_read(pf, 0x00), + pf->ccr_mask, pccard_ccr_read(pf, 0x00), pccard_ccr_read(pf, 0x02), pccard_ccr_read(pf, 0x04), pccard_ccr_read(pf, 0x06), pccard_ccr_read(pf, 0x0A), pccard_ccr_read(pf, 0x0C), pccard_ccr_read(pf, 0x0E), @@ -528,6 +529,43 @@ pccard_function_free(struct pccard_function *pf) resource_list_free(&devi->resources); } +static void +pccard_mfc_adjust_iobase(struct pccard_function *pf, bus_addr_t addr, + bus_addr_t offset, bus_size_t size) +{ + bus_addr_t iosize; + bus_size_t tmp; + + if (addr != 0) { + if (pf->pf_mfc_iomax == 0) { + pf->pf_mfc_iobase = addr + offset; + pf->pf_mfc_iomax = pf->pf_mfc_iobase + size; + } else { + /* this makes the assumption that nothing overlaps */ + if (pf->pf_mfc_iobase > addr + offset) + pf->pf_mfc_iobase = addr + offset; + if (pf->pf_mfc_iomax < addr + offset + size) + pf->pf_mfc_iomax = addr + offset + size; + } + } + + tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase; + /* round up to nearest (2^n)-1 */ + for (iosize = 1; iosize < tmp; iosize <<= 1) + ; + iosize--; + + DEVPRINTF((pf->dev, "MFC: I/O base 0x%x IOSIZE %lld\n", + pf->pf_mfc_iobase, (uint64_t) iosize)); + pccard_ccr_write(pf, PCCARD_CCR_IOBASE0, + pf->pf_mfc_iobase & 0xff); + pccard_ccr_write(pf, PCCARD_CCR_IOBASE1, + (pf->pf_mfc_iobase >> 8) & 0xff); + pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0); + pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0); + pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize); +} + /* Enable a PCCARD function */ static int pccard_function_enable(struct pccard_function *pf) @@ -615,24 +653,8 @@ pccard_function_enable(struct pccard_function *pf) pccard_ccr_write(pf, PCCARD_CCR_SOCKETCOPY, 0); - if (pccard_mfc(pf->sc)) { - long tmp, iosize; - - tmp = pf->pf_mfc_iomax - pf->pf_mfc_iobase; - /* round up to nearest (2^n)-1 */ - for (iosize = 1; iosize < tmp; iosize <<= 1) - ; - iosize--; - - pccard_ccr_write(pf, PCCARD_CCR_IOBASE0, - pf->pf_mfc_iobase & 0xff); - pccard_ccr_write(pf, PCCARD_CCR_IOBASE1, - (pf->pf_mfc_iobase >> 8) & 0xff); - pccard_ccr_write(pf, PCCARD_CCR_IOBASE2, 0); - pccard_ccr_write(pf, PCCARD_CCR_IOBASE3, 0); - - pccard_ccr_write(pf, PCCARD_CCR_IOSIZE, iosize); - } + if (pccard_mfc(pf->sc)) + pccard_mfc_adjust_iobase(pf, 0, 0, 0); #ifdef PCCARDDEBUG if (pccard_debug) { @@ -1052,8 +1074,10 @@ pccard_alloc_resource(device_t dev, device_t child, int type, int *rid, struct pccard_ivar *dinfo; struct resource_list_entry *rle = 0; int passthrough = (device_get_parent(child) != dev); + int isdefault = (start == 0 && end == ~0UL && count == 1); struct resource *r = NULL; + /* XXX I'm no longer sure this is right */ if (passthrough) { return (BUS_ALLOC_RESOURCE(device_get_parent(dev), child, type, rid, start, end, count, flags)); @@ -1062,30 +1086,27 @@ pccard_alloc_resource(device_t dev, device_t child, int type, int *rid, dinfo = device_get_ivars(child); rle = resource_list_find(&dinfo->resources, type, *rid); - if (rle == NULL) - return (NULL); /* no resource of that type/rid */ - - if (rle->res == NULL) { - switch(type) { - case SYS_RES_IOPORT: - r = bus_alloc_resource(dev, type, rid, start, end, - count, rman_make_alignment_flags(count)); - if (r == NULL) - goto bad; - resource_list_add(&dinfo->resources, type, *rid, - rman_get_start(r), rman_get_end(r), count); - rle = resource_list_find(&dinfo->resources, type, *rid); - if (!rle) - goto bad; - rle->res = r; - break; - case SYS_RES_MEMORY: - break; - case SYS_RES_IRQ: - break; - } - return (rle->res); + if (rle == NULL && isdefault) + return (NULL); /* no resource of that type/rid */ + if (rle == NULL || rle->res == NULL) { + /* Do we want this device to own it? */ + /* XXX I think so, but that might be lame XXX */ + r = bus_alloc_resource(dev, type, rid, start, end, + count, flags /* XXX aligment? */); + if (r == NULL) + goto bad; + resource_list_add(&dinfo->resources, type, *rid, + rman_get_start(r), rman_get_end(r), count); + rle = resource_list_find(&dinfo->resources, type, *rid); + if (!rle) + goto bad; + rle->res = r; } + /* + * XXX the following looks wrong, in theory, but likely it is + * XXX needed because of how the CIS code allocates resources + * XXX for this device. + */ if (rman_get_device(rle->res) != dev) return (NULL); bus_release_resource(dev, type, *rid, rle->res); @@ -1252,6 +1273,37 @@ pccard_teardown_intr(device_t dev, device_t child, struct resource *r, return (ret); } +static int +pccard_activate_resource(device_t brdev, device_t child, int type, int rid, + struct resource *r) +{ + struct pccard_ivar *ivar = PCCARD_IVAR(child); + struct pccard_function *pf = ivar->fcn; + + switch(type) { + case SYS_RES_IOPORT: + /* + * We need to adjust IOBASE[01] and IOSIZE if we're an MFC + * card. + */ + if (pccard_mfc(pf->sc)) + pccard_mfc_adjust_iobase(pf, rman_get_start(r), 0, + rman_get_size(r)); + break; + default: + break; + } + return (bus_generic_activate_resource(brdev, child, type, rid, r)); +} + +static int +pccard_deactivate_resource(device_t brdev, device_t child, int type, + int rid, struct resource *r) +{ + /* XXX undo pccard_activate_resource? XXX */ + return (bus_generic_deactivate_resource(brdev, child, type, rid, r)); +} + static device_method_t pccard_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pccard_probe), @@ -1267,8 +1319,8 @@ static device_method_t pccard_methods[] = { DEVMETHOD(bus_child_detached, pccard_child_detached), DEVMETHOD(bus_alloc_resource, pccard_alloc_resource), DEVMETHOD(bus_release_resource, pccard_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_activate_resource, pccard_activate_resource), + DEVMETHOD(bus_deactivate_resource, pccard_deactivate_resource), DEVMETHOD(bus_setup_intr, pccard_setup_intr), DEVMETHOD(bus_teardown_intr, pccard_teardown_intr), DEVMETHOD(bus_set_resource, pccard_set_resource), diff --git a/sys/dev/pccard/pccardvar.h b/sys/dev/pccard/pccardvar.h index 7a20f48b4dcb..1868a370d3a4 100644 --- a/sys/dev/pccard/pccardvar.h +++ b/sys/dev/pccard/pccardvar.h @@ -147,8 +147,8 @@ struct pccard_function { #define pf_ccr_realsize pf_pcmh.realsize uint32_t pf_ccr_offset; /* Offset from ccr_base of CIS */ int pf_ccr_window; - long pf_mfc_iobase; /* Right type? */ - long pf_mfc_iomax; + bus_addr_t pf_mfc_iobase; + bus_addr_t pf_mfc_iomax; int pf_flags; driver_intr_t *intr_handler; void *intr_handler_arg; @@ -373,10 +373,8 @@ enum { #define PCMCIA_CARD2_D(v1, p1, p2, f) \ { PCMCIA_STR_ ## p2, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \ f, PCMCIA_CIS_ ## p2} -#if 1 #define PCMCIA_CARD(v, p, f) { NULL, PCMCIA_VENDOR_ ## v, \ PCCARD_P(v, p), f, PCCARD_C(v, p) } #define PCMCIA_CARD2(v1, p1, p2, f) \ { NULL, PCMCIA_VENDOR_ ## v1, PCCARD_P(v1, p1), \ f, PCMCIA_CIS_ ## p2} -#endif