[BACK]Return to pcmcia.c CVS log [TXT][DIR] Up to [local] / sys / dev / pcmcia

Annotation of sys/dev/pcmcia/pcmcia.c, Revision 1.2

1.1       nbrk        1: /*     $OpenBSD: pcmcia.c,v 1.37 2006/04/16 20:43:12 miod Exp $        */
                      2: /*     $NetBSD: pcmcia.c,v 1.9 1998/08/13 02:10:55 eeh Exp $   */
                      3:
                      4: /*
                      5:  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by Marc Horowitz.
                     18:  * 4. The name of the author may not be used to endorse or promote products
                     19:  *    derived from this software without specific prior written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
                     30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     31:  */
                     32:
                     33: #include <sys/types.h>
                     34: #include <sys/param.h>
                     35: #include <sys/systm.h>
                     36: #include <sys/device.h>
                     37: #include <sys/malloc.h>
                     38:
                     39: #include <dev/pcmcia/pcmciareg.h>
                     40: #include <dev/pcmcia/pcmciachip.h>
                     41: #include <dev/pcmcia/pcmciavar.h>
                     42:
                     43: #ifdef PCMCIADEBUG
                     44: #define        DPRINTF(arg) printf arg
                     45: #else
                     46: #define        DPRINTF(arg)
                     47: #endif
                     48:
                     49: #ifdef PCMCIAVERBOSE
                     50: int    pcmcia_verbose = 1;
                     51: #else
                     52: int    pcmcia_verbose = 0;
                     53: #endif
                     54:
                     55: int    pcmcia_match(struct device *, void *, void *);
                     56: int    pcmcia_submatch(struct device *, void *, void *);
                     57: void   pcmcia_attach(struct device *, struct device *, void *);
                     58: int    pcmcia_print(void *, const char *);
                     59: void   pcmcia_card_detach_notify(struct device *, void *);
                     60: void   pcmcia_power(int why, void *arg);
                     61:
                     62: static inline void pcmcia_socket_enable(pcmcia_chipset_tag_t,
                     63:                                             pcmcia_chipset_handle_t *);
                     64: static inline void pcmcia_socket_disable(pcmcia_chipset_tag_t,
                     65:                                              pcmcia_chipset_handle_t *);
                     66:
                     67: int pcmcia_card_intr(void *);
                     68:
                     69: struct cfdriver pcmcia_cd = {
                     70:        NULL, "pcmcia", DV_DULL
                     71: };
                     72:
                     73: struct cfattach pcmcia_ca = {
                     74:        sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach
                     75: };
                     76:
                     77: int
                     78: pcmcia_ccr_read(pf, ccr)
                     79:        struct pcmcia_function *pf;
                     80:        int ccr;
                     81: {
                     82:
                     83:        return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
                     84:            pf->pf_ccr_offset + ccr));
                     85: }
                     86:
                     87: void
                     88: pcmcia_ccr_write(pf, ccr, val)
                     89:        struct pcmcia_function *pf;
                     90:        int ccr;
                     91:        int val;
                     92: {
                     93:
                     94:        if ((pf->ccr_mask) & (1 << (ccr / 2))) {
                     95:                bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
                     96:                    pf->pf_ccr_offset + ccr, val);
                     97:        }
                     98: }
                     99:
                    100: int
                    101: pcmcia_match(parent, match, aux)
                    102:        struct device *parent;
                    103:        void *match, *aux;
                    104: {
                    105:        struct cfdata *cf = match;
                    106:        struct pcmciabus_attach_args *paa = aux;
                    107:
                    108:        if (strcmp(paa->paa_busname, cf->cf_driver->cd_name))
                    109:                return 0;
                    110:
                    111:        /* If the autoconfiguration got this far, there's a socket here. */
                    112:        return (1);
                    113: }
                    114:
                    115: void
                    116: pcmcia_attach(parent, self, aux)
                    117:        struct device *parent, *self;
                    118:        void *aux;
                    119: {
                    120:        struct pcmciabus_attach_args *paa = aux;
                    121:        struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
                    122:
                    123:        printf("\n");
                    124:
                    125:        sc->pct = paa->pct;
                    126:        sc->pch = paa->pch;
                    127:        sc->iobase = paa->iobase;
                    128:        sc->iosize = paa->iosize;
                    129:
                    130:        sc->ih = NULL;
                    131:        powerhook_establish(pcmcia_power, sc);
                    132: }
                    133:
                    134: void
                    135: pcmcia_power(why, arg)
                    136:        int why;
                    137:        void *arg;
                    138: {
                    139:        struct pcmcia_softc *sc = (struct pcmcia_softc *) arg;
                    140:        struct pcmcia_function *pf;
                    141:        struct device *d;
                    142:        int act = DVACT_ACTIVATE;
                    143:
                    144:        if (why != PWR_RESUME)
                    145:                act = DVACT_DEACTIVATE;
                    146:
                    147:        for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
                    148:             pf = SIMPLEQ_NEXT(pf, pf_list)) {
                    149:                if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
                    150:                        continue;
                    151:                d = pf->child;
                    152:                if (d == NULL)
                    153:                        continue;
                    154:                if (act == DVACT_ACTIVATE)
                    155:                        config_activate(pf->child);
                    156:                else
                    157:                        config_deactivate(pf->child);
                    158:        }
                    159: }
                    160:
                    161: int
                    162: pcmcia_card_attach(dev)
                    163:        struct device *dev;
                    164: {
                    165:        struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
                    166:        struct pcmcia_function *pf;
                    167:        struct pcmcia_attach_args paa;
                    168:        int attached;
                    169:
                    170:        /*
                    171:         * this is here so that when socket_enable calls gettype, trt happens
                    172:         */
1.2     ! nbrk      173:        printf("pcmcia_card_attach\n");
1.1       nbrk      174:        SIMPLEQ_FIRST(&sc->card.pf_head) = NULL;
                    175:
                    176:        pcmcia_chip_socket_enable(sc->pct, sc->pch);
1.2     ! nbrk      177:        printf("pcmcia_chip_socket_enable\n");
1.1       nbrk      178:
                    179:        pcmcia_read_cis(sc);
1.2     ! nbrk      180:        printf("pcmcia_read_cis\n");
1.1       nbrk      181:
                    182:        pcmcia_chip_socket_disable(sc->pct, sc->pch);
1.2     ! nbrk      183:        printf("pcmcia_chip_socket_disable\n");
1.1       nbrk      184:
                    185:        pcmcia_check_cis_quirks(sc);
1.2     ! nbrk      186:        printf("pcmcia_check_cis_quirks\n");
1.1       nbrk      187:
                    188:        /*
                    189:         * Bail now if there was an error in the CIS.
                    190:         */
                    191:
                    192:        if (sc->card.error)
                    193:                return (1);
                    194:
                    195: #if 0
                    196:        if (SIMPLEQ_EMPTY(&sc->card.pf_head))
                    197:                return (1);
                    198: #endif
                    199:
                    200:        if (pcmcia_verbose)
                    201:                pcmcia_print_cis(sc);
                    202:
                    203:        /*
                    204:         * If there was no function, this might be CIS-less card we still
                    205:         * want to probe.  Fixup a function element for it.
                    206:         */
                    207:        if (SIMPLEQ_FIRST(&sc->card.pf_head) == NULL) {
                    208:                pf = malloc(sizeof *pf, M_DEVBUF, M_NOWAIT);
                    209:                if (pf == NULL)
                    210:                        panic("pcmcia_card_attach");
                    211:                bzero(pf, sizeof *pf);
                    212:                pf->number = 0;
                    213:                pf->pf_flags = PFF_FAKE;
                    214:                pf->last_config_index = -1;
                    215:                SIMPLEQ_INIT(&pf->cfe_head);
                    216:                SIMPLEQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list);
                    217:        }
                    218:
                    219:        attached = 0;
                    220:
                    221:        for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
                    222:            pf = SIMPLEQ_NEXT(pf, pf_list)) {
                    223:                pf->sc = sc;
                    224:                pf->child = NULL;
                    225:                pf->cfe = NULL;
                    226:                pf->ih_fct = NULL;
                    227:                pf->ih_arg = NULL;
                    228:        }
                    229:
                    230:        for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
                    231:            pf = SIMPLEQ_NEXT(pf, pf_list)) {
                    232:                paa.manufacturer = sc->card.manufacturer;
                    233:                paa.product = sc->card.product;
                    234:                paa.card = &sc->card;
                    235:                paa.pf = pf;
                    236:
                    237:                pf->child = config_found_sm(&sc->dev, &paa, pcmcia_print,
                    238:                    pcmcia_submatch);
                    239:                if (pf->child) {
                    240:                        attached++;
                    241:
                    242:                        if ((pf->pf_flags & PFF_FAKE) == 0)
                    243:                                DPRINTF(("%s: function %d CCR at %d offset %lx"
                    244:                                        ": %x %x %x %x, %x %x %x %x, %x\n",
                    245:                                        sc->dev.dv_xname, pf->number,
                    246:                                        pf->pf_ccr_window, pf->pf_ccr_offset,
                    247:                                        pcmcia_ccr_read(pf, 0x00),
                    248:                                        pcmcia_ccr_read(pf, 0x02),
                    249:                                        pcmcia_ccr_read(pf, 0x04),
                    250:                                        pcmcia_ccr_read(pf, 0x06),
                    251:                                        pcmcia_ccr_read(pf, 0x0A),
                    252:                                        pcmcia_ccr_read(pf, 0x0C),
                    253:                                        pcmcia_ccr_read(pf, 0x0E),
                    254:                                        pcmcia_ccr_read(pf, 0x10),
                    255:                                        pcmcia_ccr_read(pf, 0x12)));
                    256:                }
                    257:        }
                    258:        return (attached ? 0 : 1);
                    259: }
                    260:
                    261: void
                    262: pcmcia_card_detach(dev, flags)
                    263:        struct device *dev;
                    264:        int flags;              /* DETACH_* flags */
                    265: {
                    266:        struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
                    267:        struct pcmcia_function *pf;
                    268:        int error;
                    269:
                    270:        /*
                    271:         * We are running on either the PCMCIA socket's event thread
                    272:         * or in user context detaching a device by user request.
                    273:         */
                    274:        for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
                    275:             pf = SIMPLEQ_NEXT(pf, pf_list)) {
                    276:                if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
                    277:                        continue;
                    278:                if (pf->child == NULL)
                    279:                        continue;
                    280:                DPRINTF(("%s: detaching %s (function %d)\n",
                    281:                    sc->dev.dv_xname, pf->child->dv_xname, pf->number));
                    282:                if ((error = config_detach(pf->child, flags)) != 0) {
                    283:                        printf("%s: error %d detaching %s (function %d)\n",
                    284:                            sc->dev.dv_xname, error, pf->child->dv_xname,
                    285:                            pf->number);
                    286:                } else
                    287:                        pf->child = NULL;
                    288:        }
                    289: }
                    290:
                    291: void
                    292: pcmcia_card_deactivate(dev)
                    293:        struct device *dev;
                    294: {
                    295:        struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
                    296:        struct pcmcia_function *pf;
                    297:
                    298:        /*
                    299:         * We're in the chip's card removal interrupt handler.
                    300:         * Deactivate the child driver.  The PCMCIA socket's
                    301:         * event thread will run later to finish the detach.
                    302:         */
                    303:        for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
                    304:             pf = SIMPLEQ_NEXT(pf, pf_list)) {
                    305:                if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
                    306:                        continue;
                    307:                if (pf->child == NULL)
                    308:                        continue;
                    309:                DPRINTF(("%s: deactivating %s (function %d)\n",
                    310:                    sc->dev.dv_xname, pf->child->dv_xname, pf->number));
                    311:                config_deactivate(pf->child);
                    312:        }
                    313: }
                    314:
                    315: int
                    316: pcmcia_submatch(parent, match, aux)
                    317:        struct device *parent;
                    318:        void *match, *aux;
                    319: {
                    320:        struct cfdata *cf = match;
                    321:        struct pcmcia_attach_args *paa = aux;
                    322:
                    323:        if (cf->cf_loc[0 /* PCMCIACF_FUNCTION */] !=
                    324:            -1 /* PCMCIACF_FUNCTION_DEFAULT */ &&
                    325:            cf->cf_loc[0 /* PCMCIACF_FUNCTION */] != paa->pf->number)
                    326:                return (0);
                    327:
                    328:        return ((*cf->cf_attach->ca_match)(parent, cf, aux));
                    329: }
                    330:
                    331: int
                    332: pcmcia_print(arg, pnp)
                    333:        void *arg;
                    334:        const char *pnp;
                    335: {
                    336:        struct pcmcia_attach_args *pa = arg;
                    337:        struct pcmcia_softc *sc = pa->pf->sc;
                    338:        struct pcmcia_card *card = &sc->card;
                    339:        int i;
                    340:
                    341:        if (pnp) {
                    342:                for (i = 0; i < 4 && card->cis1_info[i]; i++)
                    343:                        printf("%s%s", i ? ", " : "\"", card->cis1_info[i]);
                    344:                if (i != 0)
                    345:                        printf("\"");
                    346:
                    347:                if (card->manufacturer != PCMCIA_VENDOR_INVALID &&
                    348:                    card->product != PCMCIA_PRODUCT_INVALID) {
                    349:                        if (i != 0)
                    350:                                printf(" ");
                    351:                        printf("(");
                    352:                        if (card->manufacturer != PCMCIA_VENDOR_INVALID)
                    353:                                printf("manufacturer 0x%x%s",
                    354:                                    card->manufacturer,
                    355:                                    card->product == PCMCIA_PRODUCT_INVALID ?
                    356:                                    "" : ", ");
                    357:                        if (card->product != PCMCIA_PRODUCT_INVALID)
                    358:                                printf("product 0x%x",
                    359:                                    card->product);
                    360:                        printf(")");
                    361:                }
                    362:                if (i != 0)
                    363:                        printf(" ");
                    364:                printf("at %s", pnp);
                    365:        }
                    366:        printf(" function %d", pa->pf->number);
                    367:
                    368:        if (!pnp) {
                    369:                for (i = 0; i < 3 && card->cis1_info[i]; i++)
                    370:                        printf("%s%s", i ? ", " : " \"", card->cis1_info[i]);
                    371:                if (i != 0)
                    372:                        printf("\"");
                    373:        }
                    374:
                    375:        return (UNCONF);
                    376: }
                    377:
                    378: int
                    379: pcmcia_card_gettype(dev)
                    380:        struct device  *dev;
                    381: {
                    382:        struct pcmcia_softc *sc = (struct pcmcia_softc *)dev;
                    383:        struct pcmcia_function *pf;
                    384:
                    385:        /*
                    386:         * Set the iftype to memory if this card has no functions (not yet
                    387:         * probed), or only one function, and that is not initialized yet or
                    388:         * that is memory.
                    389:         */
                    390:        pf = SIMPLEQ_FIRST(&sc->card.pf_head);
                    391:        if (pf == NULL || (SIMPLEQ_NEXT(pf, pf_list) == NULL &&
                    392:            ((pf->pf_flags & PFF_FAKE) ||
                    393:            pf->cfe == NULL || pf->cfe->iftype == PCMCIA_IFTYPE_MEMORY)))
                    394:                return (PCMCIA_IFTYPE_MEMORY);
                    395:        else
                    396:                return (PCMCIA_IFTYPE_IO);
                    397: }
                    398:
                    399: /*
                    400:  * Initialize a PCMCIA function.  May be called as long as the function is
                    401:  * disabled.
                    402:  */
                    403: void
                    404: pcmcia_function_init(pf, cfe)
                    405:        struct pcmcia_function *pf;
                    406:        struct pcmcia_config_entry *cfe;
                    407: {
                    408:        if (pf->pf_flags & PFF_ENABLED)
                    409:                panic("pcmcia_function_init: function is enabled");
                    410:
                    411:        /* Remember which configuration entry we are using. */
                    412:        pf->cfe = cfe;
                    413: }
                    414:
                    415: static inline void pcmcia_socket_enable(pct, pch)
                    416:      pcmcia_chipset_tag_t pct;
                    417:      pcmcia_chipset_handle_t *pch;
                    418: {
                    419:        pcmcia_chip_socket_enable(pct, pch);
                    420: }
                    421:
                    422: static inline void pcmcia_socket_disable(pct, pch)
                    423:      pcmcia_chipset_tag_t pct;
                    424:      pcmcia_chipset_handle_t *pch;
                    425: {
                    426:        pcmcia_chip_socket_disable(pct, pch);
                    427: }
                    428:
                    429: /* Enable a PCMCIA function */
                    430: int
                    431: pcmcia_function_enable(pf)
                    432:        struct pcmcia_function *pf;
                    433: {
                    434:        struct pcmcia_function *tmp;
                    435:        int reg;
                    436:
                    437:        if (pf->cfe == NULL)
                    438:                panic("pcmcia_function_enable: function not initialized");
                    439:
                    440:        /*
                    441:         * Increase the reference count on the socket, enabling power, if
                    442:         * necessary.
                    443:         */
                    444:        if (pf->sc->sc_enabled_count++ == 0)
                    445:                pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
                    446:        DPRINTF(("%s: ++enabled_count = %d\n", pf->sc->dev.dv_xname,
                    447:                 pf->sc->sc_enabled_count));
                    448:
                    449:        if (pf->pf_flags & PFF_ENABLED) {
                    450:                /*
                    451:                 * Don't do anything if we're already enabled.
                    452:                 */
                    453:                DPRINTF(("%s: pcmcia_function_enable on enabled func\n"));
                    454:                return (0);
                    455:        }
                    456:
                    457:        /* If there was no CIS don't mess with CCR */
                    458:        if (pf->pf_flags & PFF_FAKE)
                    459:                goto done;
                    460:
                    461:        /*
                    462:         * It's possible for different functions' CCRs to be in the same
                    463:         * underlying page.  Check for that.
                    464:         */
                    465:        SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
                    466:                if ((tmp->pf_flags & PFF_ENABLED) &&
                    467:                    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
                    468:                    ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
                    469:                     (tmp->ccr_base - tmp->pf_ccr_offset +
                    470:                      tmp->pf_ccr_realsize))) {
                    471:                        pf->pf_ccrt = tmp->pf_ccrt;
                    472:                        pf->pf_ccrh = tmp->pf_ccrh;
                    473:                        pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
                    474:
                    475:                        /*
                    476:                         * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
                    477:                         * tmp->ccr_base) + pf->ccr_base;
                    478:                         */
                    479:                        pf->pf_ccr_offset =
                    480:                            (tmp->pf_ccr_offset + pf->ccr_base) -
                    481:                            tmp->ccr_base;
                    482:                        pf->pf_ccr_window = tmp->pf_ccr_window;
                    483:                        break;
                    484:                }
                    485:        }
                    486:
                    487:        if (tmp == NULL) {
                    488:                if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
                    489:                        goto bad;
                    490:
                    491:                if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
                    492:                    PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
                    493:                    &pf->pf_ccr_window)) {
                    494:                        pcmcia_mem_free(pf, &pf->pf_pcmh);
                    495:                        goto bad;
                    496:                }
                    497:        }
                    498:
                    499:        reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
                    500:        reg |= PCMCIA_CCR_OPTION_LEVIREQ;
                    501:        if (pcmcia_mfc(pf->sc)) {
                    502:                reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
                    503:                if (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))
                    504:                        reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
                    505:                if (pf->ih_fct)
                    506:                        reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
                    507:
                    508:        }
                    509:
                    510:        pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
                    511:
                    512:        reg = 0;
                    513:
                    514:        if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
                    515:                reg |= PCMCIA_CCR_STATUS_IOIS8;
                    516:        if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
                    517:                reg |= PCMCIA_CCR_STATUS_AUDIO;
                    518:        pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
                    519:
                    520:        pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
                    521:
                    522:        if (pcmcia_mfc(pf->sc)) {
                    523:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
                    524:                                 (pf->pf_mfc_iobase >>  0) & 0xff);
                    525:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
                    526:                                 (pf->pf_mfc_iobase >>  8) & 0xff);
                    527:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
                    528:                                 (pf->pf_mfc_iobase >> 16) & 0xff);
                    529:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
                    530:                                 (pf->pf_mfc_iobase >> 24) & 0xff);
                    531:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
                    532:                                 pf->pf_mfc_iomax - pf->pf_mfc_iobase);
                    533:        }
                    534:
                    535: #ifdef PCMCIADEBUG
                    536:        SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
                    537:                printf("%s: function %d CCR at %d offset %lx: "
                    538:                       "%x %x %x %x, %x %x %x %x, %x\n",
                    539:                       tmp->sc->dev.dv_xname, tmp->number,
                    540:                       tmp->pf_ccr_window, tmp->pf_ccr_offset,
                    541:                       pcmcia_ccr_read(tmp, 0x00),
                    542:                       pcmcia_ccr_read(tmp, 0x02),
                    543:                       pcmcia_ccr_read(tmp, 0x04),
                    544:                       pcmcia_ccr_read(tmp, 0x06),
                    545:
                    546:                       pcmcia_ccr_read(tmp, 0x0A),
                    547:                       pcmcia_ccr_read(tmp, 0x0C),
                    548:                       pcmcia_ccr_read(tmp, 0x0E),
                    549:                       pcmcia_ccr_read(tmp, 0x10),
                    550:
                    551:                       pcmcia_ccr_read(tmp, 0x12));
                    552:        }
                    553: #endif
                    554:
                    555:  done:
                    556:        pf->pf_flags |= PFF_ENABLED;
                    557:        delay(1000);
                    558:        return (0);
                    559:
                    560:  bad:
                    561:        /*
                    562:         * Decrement the reference count, and power down the socket, if
                    563:         * necessary.
                    564:         */
                    565:        if (--pf->sc->sc_enabled_count == 0)
                    566:                pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
                    567:        DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
                    568:                 pf->sc->sc_enabled_count));
                    569:
                    570:        return (1);
                    571: }
                    572:
                    573: /* Disable PCMCIA function. */
                    574: void
                    575: pcmcia_function_disable(pf)
                    576:        struct pcmcia_function *pf;
                    577: {
                    578:        struct pcmcia_function *tmp;
                    579:
                    580:        if (pf->cfe == NULL)
                    581:                panic("pcmcia_function_enable: function not initialized");
                    582:
                    583:        if ((pf->pf_flags & PFF_ENABLED) == 0) {
                    584:                /*
                    585:                 * Don't do anything if we're already disabled.
                    586:                 */
                    587:                return;
                    588:        }
                    589:
                    590:        /* If there was no CIS don't mess with CCR */
                    591:        if (pf->pf_flags & PFF_FAKE) {
                    592:                pf->pf_flags &= ~PFF_ENABLED;
                    593:                goto done;
                    594:        }
                    595:
                    596:        /*
                    597:         * it's possible for different functions' CCRs to be in the same
                    598:         * underlying page.  Check for that.  Note we mark us as disabled
                    599:         * first to avoid matching ourself.
                    600:         */
                    601:        pf->pf_flags &= ~PFF_ENABLED;
                    602:        SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
                    603:                if ((tmp->pf_flags & PFF_ENABLED) &&
                    604:                    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
                    605:                    ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
                    606:                (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
                    607:                        break;
                    608:        }
                    609:
                    610:        /* Not used by anyone else; unmap the CCR. */
                    611:        if (tmp == NULL) {
                    612:                pcmcia_mem_unmap(pf, pf->pf_ccr_window);
                    613:                pcmcia_mem_free(pf, &pf->pf_pcmh);
                    614:        }
                    615:
                    616:  done:
                    617:        /*
                    618:         * Decrement the reference count, and power down the socket, if
                    619:         * necessary.
                    620:         */
                    621:        if (--pf->sc->sc_enabled_count == 0)
                    622:                pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
                    623:        DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
                    624:                 pf->sc->sc_enabled_count));
                    625: }
                    626:
                    627: int
                    628: pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
                    629:        struct pcmcia_function *pf;
                    630:        int width;
                    631:        bus_addr_t offset;
                    632:        bus_size_t size;
                    633:        struct pcmcia_io_handle *pcihp;
                    634:        int *windowp;
                    635: {
                    636:        int reg;
                    637:
                    638:        if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
                    639:            width, offset, size, pcihp, windowp))
                    640:                return (1);
                    641:
                    642:        /*
                    643:         * XXX In the multifunction multi-iospace-per-function case, this
                    644:         * needs to cooperate with io_alloc to make sure that the spaces
                    645:         * don't overlap, and that the ccr's are set correctly.
                    646:         */
                    647:
                    648:        if (pcmcia_mfc(pf->sc) &&
                    649:            (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))) {
                    650:                bus_addr_t iobase = pcihp->addr;
                    651:                bus_addr_t iomax = pcihp->addr + pcihp->size - 1;
                    652:
                    653:                if (pf->pf_mfc_iomax == 0) {
                    654:                        pf->pf_mfc_iobase = iobase;
                    655:                        pf->pf_mfc_iomax = iomax;
                    656:                } else {
                    657:                        if (iobase < pf->pf_mfc_iobase)
                    658:                                pf->pf_mfc_iobase = iobase;
                    659:                        if (iomax > pf->pf_mfc_iomax)
                    660:                                pf->pf_mfc_iomax = iomax;
                    661:                }
                    662:
                    663:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
                    664:                                 (pf->pf_mfc_iobase >>  0) & 0xff);
                    665:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
                    666:                                 (pf->pf_mfc_iobase >>  8) & 0xff);
                    667:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
                    668:                                 (pf->pf_mfc_iobase >> 16) & 0xff);
                    669:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
                    670:                                 (pf->pf_mfc_iobase >> 24) & 0xff);
                    671:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
                    672:                                 pf->pf_mfc_iomax - pf->pf_mfc_iobase);
                    673:
                    674:                reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
                    675:                reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
                    676:                pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
                    677:        }
                    678:        return (0);
                    679: }
                    680:
                    681: void *
                    682: pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg, xname)
                    683:        struct pcmcia_function *pf;
                    684:        int ipl;
                    685:        int (*ih_fct)(void *);
                    686:        void *ih_arg;
                    687:        char *xname;
                    688: {
                    689:        void *ret;
                    690:        int s, ihcnt, hiipl, reg;
                    691:        struct pcmcia_function *pf2;
                    692:
                    693:        /* Behave differently if this is a multifunction card. */
                    694:        if (pcmcia_mfc(pf->sc)) {
                    695:                /*
                    696:                 * Mask all the ipl's which are already used by this card,
                    697:                 * and find the highest ipl number (lowest priority).
                    698:                 */
                    699:                ihcnt = 0;
                    700:                SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
                    701:                        if (pf2->ih_fct) {
                    702:                                DPRINTF(("%s: function %d has ih_fct %p\n",
                    703:                                    pf->sc->dev.dv_xname, pf2->number,
                    704:                                    pf2->ih_fct));
                    705:
                    706:                                if (ihcnt == 0)
                    707:                                        hiipl = pf2->ih_ipl;
                    708:                                else if (pf2->ih_ipl > hiipl)
                    709:                                        hiipl = pf2->ih_ipl;
                    710:
                    711:                                ihcnt++;
                    712:                        }
                    713:                }
                    714:
                    715:                /*
                    716:                 * Establish the real interrupt, changing the ipl if
                    717:                 * necessary.
                    718:                 */
                    719:                if (ihcnt == 0) {
                    720: #ifdef DIAGNOSTIC
                    721:                        if (pf->sc->ih != NULL)
                    722:                                panic("card has intr handler, "
                    723:                                    "but no function does");
                    724: #endif
                    725:                        s = spltty();
                    726:
                    727:                        /* Set up the handler for the new function. */
                    728:                        pf->ih_fct = ih_fct;
                    729:                        pf->ih_arg = ih_arg;
                    730:                        pf->ih_ipl = ipl;
                    731:
                    732:                        pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
                    733:                            pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
                    734:                            xname);
                    735:                        splx(s);
                    736:                } else if (ipl > hiipl) {
                    737: #ifdef DIAGNOSTIC
                    738:                        if (pf->sc->ih == NULL)
                    739:                                panic("functions have ih, "
                    740:                                    "but the card does not");
                    741: #endif
                    742:
                    743:                        s = spltty();
                    744:
                    745:                        pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
                    746:                            pf->sc->ih);
                    747:
                    748:                        /* set up the handler for the new function */
                    749:                        pf->ih_fct = ih_fct;
                    750:                        pf->ih_arg = ih_arg;
                    751:                        pf->ih_ipl = ipl;
                    752:
                    753:                        pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
                    754:                            pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
                    755:                            xname);
                    756:
                    757:                        splx(s);
                    758:                } else {
                    759:                        s = spltty();
                    760:
                    761:                        /* Set up the handler for the new function. */
                    762:                        pf->ih_fct = ih_fct;
                    763:                        pf->ih_arg = ih_arg;
                    764:                        pf->ih_ipl = ipl;
                    765:
                    766:                        splx(s);
                    767:                }
                    768:
                    769:                ret = pf->sc->ih;
                    770:
                    771:                if (ret != NULL) {
                    772:                        reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
                    773:                        reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
                    774:                        pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
                    775:
                    776:                        reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
                    777:                        reg |= PCMCIA_CCR_STATUS_INTRACK;
                    778:                        pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
                    779:                }
                    780:        } else
                    781:                ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
                    782:                    pf, ipl, ih_fct, ih_arg, xname);
                    783:
                    784:        return (ret);
                    785: }
                    786:
                    787: void
                    788: pcmcia_intr_disestablish(pf, ih)
                    789:        struct pcmcia_function *pf;
                    790:        void *ih;
                    791: {
                    792:        int s, reg, ihcnt, hiipl;
                    793:        struct pcmcia_function *pf2;
                    794:
                    795:        /* Behave differently if this is a multifunction card.  */
                    796:        if (pcmcia_mfc(pf->sc)) {
                    797:                /*
                    798:                 * Mask all the ipl's which are already used by this card,
                    799:                 * and find the highest ipl number (lowest priority).  Skip
                    800:                 * the current function.
                    801:                 */
                    802:                ihcnt = 0;
                    803:                SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
                    804:                        if (pf2 == pf)
                    805:                                continue;
                    806:
                    807:                        if (pf2->ih_fct) {
                    808:                                if (ihcnt == 0)
                    809:                                        hiipl = pf2->ih_ipl;
                    810:                                else if (pf2->ih_ipl > hiipl)
                    811:                                        hiipl = pf2->ih_ipl;
                    812:                                ihcnt++;
                    813:                        }
                    814:                }
                    815:
                    816:                /*
                    817:                 * If the ih being removed is lower priority than the lowest
                    818:                 * priority remaining interrupt, up the priority.
                    819:                 */
                    820:
                    821:                /*
                    822:                 * ihcnt is the number of interrupt handlers *not* including
                    823:                 * the one about to be removed.
                    824:                 */
                    825:                if (ihcnt == 0) {
                    826: #ifdef DIAGNOSTIC
                    827:                        if (pf->sc->ih == NULL)
                    828:                                panic("disestablishing last function, but card has no ih");
                    829: #endif
                    830:                        pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
                    831:                            pf->sc->ih);
                    832:
                    833:                        reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
                    834:                        reg &= ~PCMCIA_CCR_OPTION_IREQ_ENABLE;
                    835:                        pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
                    836:
                    837:                        pf->ih_fct = NULL;
                    838:                        pf->ih_arg = NULL;
                    839:
                    840:                        pf->sc->ih = NULL;
                    841:                } else if (pf->ih_ipl > hiipl) {
                    842: #ifdef DIAGNOSTIC
                    843:                        if (pf->sc->ih == NULL)
                    844:                                panic("changing ih ipl, but card has no ih");
                    845: #endif
                    846:                        s = spltty();
                    847:
                    848:                        pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
                    849:                            pf->sc->ih);
                    850:                        pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
                    851:                            pf->sc->pch, pf, hiipl, pcmcia_card_intr, pf->sc,
                    852:                            NULL);
                    853:
                    854:                        /* Null out the handler for this function. */
                    855:                        pf->ih_fct = NULL;
                    856:                        pf->ih_arg = NULL;
                    857:
                    858:                        splx(s);
                    859:                } else {
                    860:                        s = spltty();
                    861:
                    862:                        pf->ih_fct = NULL;
                    863:                        pf->ih_arg = NULL;
                    864:
                    865:                        splx(s);
                    866:                }
                    867:        } else
                    868:                pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
                    869: }
                    870:
                    871: const char *
                    872: pcmcia_intr_string(pf, ih)
                    873:        struct pcmcia_function *pf;
                    874:        void *ih;
                    875: {
                    876:        return pcmcia_chip_intr_string(pf->sc->pct, pf->sc->pch, ih);
                    877: }
                    878:
                    879: int
                    880: pcmcia_card_intr(arg)
                    881:        void *arg;
                    882: {
                    883:        struct pcmcia_softc *sc = arg;
                    884:        struct pcmcia_function *pf;
                    885:        int reg, ret, ret2;
                    886:
                    887:        ret = 0;
                    888:
                    889:        for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
                    890:            pf = SIMPLEQ_NEXT(pf, pf_list)) {
                    891: #ifdef PCMCIADEBUG
                    892:                printf("%s: intr flags=%x fct=%d cor=%02x csr=%02x pin=%02x",
                    893:                       sc->dev.dv_xname, pf->pf_flags, pf->number,
                    894:                       pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION),
                    895:                       pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS),
                    896:                       pcmcia_ccr_read(pf, PCMCIA_CCR_PIN));
                    897: #endif
                    898:                if (pf->ih_fct != NULL &&
                    899:                    (pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) {
                    900:                        reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
                    901:                        if (reg & PCMCIA_CCR_STATUS_INTR) {
                    902:                                ret2 = (*pf->ih_fct)(pf->ih_arg);
                    903:                                if (ret2 != 0 && ret == 0)
                    904:                                        ret = ret2;
                    905:                                reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
                    906: #ifdef PCMCIADEBUG
                    907:                                printf("; csr %02x->%02x",
                    908:                                    reg, reg & ~PCMCIA_CCR_STATUS_INTR);
                    909: #endif
                    910:                                pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
                    911:                                    reg & ~PCMCIA_CCR_STATUS_INTR);
                    912:                        }
                    913:                }
                    914: #ifdef PCMCIADEBUG
                    915:                printf("\n");
                    916: #endif
                    917:        }
                    918:
                    919:        return (ret);
                    920: }

CVSweb