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

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

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:         */
                    173:        SIMPLEQ_FIRST(&sc->card.pf_head) = NULL;
                    174:
                    175:        pcmcia_chip_socket_enable(sc->pct, sc->pch);
                    176:
                    177:        pcmcia_read_cis(sc);
                    178:
                    179:        pcmcia_chip_socket_disable(sc->pct, sc->pch);
                    180:
                    181:        pcmcia_check_cis_quirks(sc);
                    182:
                    183:        /*
                    184:         * Bail now if there was an error in the CIS.
                    185:         */
                    186:
                    187:        if (sc->card.error)
                    188:                return (1);
                    189:
                    190: #if 0
                    191:        if (SIMPLEQ_EMPTY(&sc->card.pf_head))
                    192:                return (1);
                    193: #endif
                    194:
                    195:        if (pcmcia_verbose)
                    196:                pcmcia_print_cis(sc);
                    197:
                    198:        /*
                    199:         * If there was no function, this might be CIS-less card we still
                    200:         * want to probe.  Fixup a function element for it.
                    201:         */
                    202:        if (SIMPLEQ_FIRST(&sc->card.pf_head) == NULL) {
                    203:                pf = malloc(sizeof *pf, M_DEVBUF, M_NOWAIT);
                    204:                if (pf == NULL)
                    205:                        panic("pcmcia_card_attach");
                    206:                bzero(pf, sizeof *pf);
                    207:                pf->number = 0;
                    208:                pf->pf_flags = PFF_FAKE;
                    209:                pf->last_config_index = -1;
                    210:                SIMPLEQ_INIT(&pf->cfe_head);
                    211:                SIMPLEQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list);
                    212:        }
                    213:
                    214:        attached = 0;
                    215:
                    216:        for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
                    217:            pf = SIMPLEQ_NEXT(pf, pf_list)) {
                    218:                pf->sc = sc;
                    219:                pf->child = NULL;
                    220:                pf->cfe = NULL;
                    221:                pf->ih_fct = NULL;
                    222:                pf->ih_arg = NULL;
                    223:        }
                    224:
                    225:        for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
                    226:            pf = SIMPLEQ_NEXT(pf, pf_list)) {
                    227:                paa.manufacturer = sc->card.manufacturer;
                    228:                paa.product = sc->card.product;
                    229:                paa.card = &sc->card;
                    230:                paa.pf = pf;
                    231:
                    232:                pf->child = config_found_sm(&sc->dev, &paa, pcmcia_print,
                    233:                    pcmcia_submatch);
                    234:                if (pf->child) {
                    235:                        attached++;
                    236:
                    237:                        if ((pf->pf_flags & PFF_FAKE) == 0)
                    238:                                DPRINTF(("%s: function %d CCR at %d offset %lx"
                    239:                                        ": %x %x %x %x, %x %x %x %x, %x\n",
                    240:                                        sc->dev.dv_xname, pf->number,
                    241:                                        pf->pf_ccr_window, pf->pf_ccr_offset,
                    242:                                        pcmcia_ccr_read(pf, 0x00),
                    243:                                        pcmcia_ccr_read(pf, 0x02),
                    244:                                        pcmcia_ccr_read(pf, 0x04),
                    245:                                        pcmcia_ccr_read(pf, 0x06),
                    246:                                        pcmcia_ccr_read(pf, 0x0A),
                    247:                                        pcmcia_ccr_read(pf, 0x0C),
                    248:                                        pcmcia_ccr_read(pf, 0x0E),
                    249:                                        pcmcia_ccr_read(pf, 0x10),
                    250:                                        pcmcia_ccr_read(pf, 0x12)));
                    251:                }
                    252:        }
                    253:        return (attached ? 0 : 1);
                    254: }
                    255:
                    256: void
                    257: pcmcia_card_detach(dev, flags)
                    258:        struct device *dev;
                    259:        int flags;              /* DETACH_* flags */
                    260: {
                    261:        struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
                    262:        struct pcmcia_function *pf;
                    263:        int error;
                    264:
                    265:        /*
                    266:         * We are running on either the PCMCIA socket's event thread
                    267:         * or in user context detaching a device by user request.
                    268:         */
                    269:        for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
                    270:             pf = SIMPLEQ_NEXT(pf, pf_list)) {
                    271:                if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
                    272:                        continue;
                    273:                if (pf->child == NULL)
                    274:                        continue;
                    275:                DPRINTF(("%s: detaching %s (function %d)\n",
                    276:                    sc->dev.dv_xname, pf->child->dv_xname, pf->number));
                    277:                if ((error = config_detach(pf->child, flags)) != 0) {
                    278:                        printf("%s: error %d detaching %s (function %d)\n",
                    279:                            sc->dev.dv_xname, error, pf->child->dv_xname,
                    280:                            pf->number);
                    281:                } else
                    282:                        pf->child = NULL;
                    283:        }
                    284: }
                    285:
                    286: void
                    287: pcmcia_card_deactivate(dev)
                    288:        struct device *dev;
                    289: {
                    290:        struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
                    291:        struct pcmcia_function *pf;
                    292:
                    293:        /*
                    294:         * We're in the chip's card removal interrupt handler.
                    295:         * Deactivate the child driver.  The PCMCIA socket's
                    296:         * event thread will run later to finish the detach.
                    297:         */
                    298:        for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
                    299:             pf = SIMPLEQ_NEXT(pf, pf_list)) {
                    300:                if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
                    301:                        continue;
                    302:                if (pf->child == NULL)
                    303:                        continue;
                    304:                DPRINTF(("%s: deactivating %s (function %d)\n",
                    305:                    sc->dev.dv_xname, pf->child->dv_xname, pf->number));
                    306:                config_deactivate(pf->child);
                    307:        }
                    308: }
                    309:
                    310: int
                    311: pcmcia_submatch(parent, match, aux)
                    312:        struct device *parent;
                    313:        void *match, *aux;
                    314: {
                    315:        struct cfdata *cf = match;
                    316:        struct pcmcia_attach_args *paa = aux;
                    317:
                    318:        if (cf->cf_loc[0 /* PCMCIACF_FUNCTION */] !=
                    319:            -1 /* PCMCIACF_FUNCTION_DEFAULT */ &&
                    320:            cf->cf_loc[0 /* PCMCIACF_FUNCTION */] != paa->pf->number)
                    321:                return (0);
                    322:
                    323:        return ((*cf->cf_attach->ca_match)(parent, cf, aux));
                    324: }
                    325:
                    326: int
                    327: pcmcia_print(arg, pnp)
                    328:        void *arg;
                    329:        const char *pnp;
                    330: {
                    331:        struct pcmcia_attach_args *pa = arg;
                    332:        struct pcmcia_softc *sc = pa->pf->sc;
                    333:        struct pcmcia_card *card = &sc->card;
                    334:        int i;
                    335:
                    336:        if (pnp) {
                    337:                for (i = 0; i < 4 && card->cis1_info[i]; i++)
                    338:                        printf("%s%s", i ? ", " : "\"", card->cis1_info[i]);
                    339:                if (i != 0)
                    340:                        printf("\"");
                    341:
                    342:                if (card->manufacturer != PCMCIA_VENDOR_INVALID &&
                    343:                    card->product != PCMCIA_PRODUCT_INVALID) {
                    344:                        if (i != 0)
                    345:                                printf(" ");
                    346:                        printf("(");
                    347:                        if (card->manufacturer != PCMCIA_VENDOR_INVALID)
                    348:                                printf("manufacturer 0x%x%s",
                    349:                                    card->manufacturer,
                    350:                                    card->product == PCMCIA_PRODUCT_INVALID ?
                    351:                                    "" : ", ");
                    352:                        if (card->product != PCMCIA_PRODUCT_INVALID)
                    353:                                printf("product 0x%x",
                    354:                                    card->product);
                    355:                        printf(")");
                    356:                }
                    357:                if (i != 0)
                    358:                        printf(" ");
                    359:                printf("at %s", pnp);
                    360:        }
                    361:        printf(" function %d", pa->pf->number);
                    362:
                    363:        if (!pnp) {
                    364:                for (i = 0; i < 3 && card->cis1_info[i]; i++)
                    365:                        printf("%s%s", i ? ", " : " \"", card->cis1_info[i]);
                    366:                if (i != 0)
                    367:                        printf("\"");
                    368:        }
                    369:
                    370:        return (UNCONF);
                    371: }
                    372:
                    373: int
                    374: pcmcia_card_gettype(dev)
                    375:        struct device  *dev;
                    376: {
                    377:        struct pcmcia_softc *sc = (struct pcmcia_softc *)dev;
                    378:        struct pcmcia_function *pf;
                    379:
                    380:        /*
                    381:         * Set the iftype to memory if this card has no functions (not yet
                    382:         * probed), or only one function, and that is not initialized yet or
                    383:         * that is memory.
                    384:         */
                    385:        pf = SIMPLEQ_FIRST(&sc->card.pf_head);
                    386:        if (pf == NULL || (SIMPLEQ_NEXT(pf, pf_list) == NULL &&
                    387:            ((pf->pf_flags & PFF_FAKE) ||
                    388:            pf->cfe == NULL || pf->cfe->iftype == PCMCIA_IFTYPE_MEMORY)))
                    389:                return (PCMCIA_IFTYPE_MEMORY);
                    390:        else
                    391:                return (PCMCIA_IFTYPE_IO);
                    392: }
                    393:
                    394: /*
                    395:  * Initialize a PCMCIA function.  May be called as long as the function is
                    396:  * disabled.
                    397:  */
                    398: void
                    399: pcmcia_function_init(pf, cfe)
                    400:        struct pcmcia_function *pf;
                    401:        struct pcmcia_config_entry *cfe;
                    402: {
                    403:        if (pf->pf_flags & PFF_ENABLED)
                    404:                panic("pcmcia_function_init: function is enabled");
                    405:
                    406:        /* Remember which configuration entry we are using. */
                    407:        pf->cfe = cfe;
                    408: }
                    409:
                    410: static inline void pcmcia_socket_enable(pct, pch)
                    411:      pcmcia_chipset_tag_t pct;
                    412:      pcmcia_chipset_handle_t *pch;
                    413: {
                    414:        pcmcia_chip_socket_enable(pct, pch);
                    415: }
                    416:
                    417: static inline void pcmcia_socket_disable(pct, pch)
                    418:      pcmcia_chipset_tag_t pct;
                    419:      pcmcia_chipset_handle_t *pch;
                    420: {
                    421:        pcmcia_chip_socket_disable(pct, pch);
                    422: }
                    423:
                    424: /* Enable a PCMCIA function */
                    425: int
                    426: pcmcia_function_enable(pf)
                    427:        struct pcmcia_function *pf;
                    428: {
                    429:        struct pcmcia_function *tmp;
                    430:        int reg;
                    431:
                    432:        if (pf->cfe == NULL)
                    433:                panic("pcmcia_function_enable: function not initialized");
                    434:
                    435:        /*
                    436:         * Increase the reference count on the socket, enabling power, if
                    437:         * necessary.
                    438:         */
                    439:        if (pf->sc->sc_enabled_count++ == 0)
                    440:                pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
                    441:        DPRINTF(("%s: ++enabled_count = %d\n", pf->sc->dev.dv_xname,
                    442:                 pf->sc->sc_enabled_count));
                    443:
                    444:        if (pf->pf_flags & PFF_ENABLED) {
                    445:                /*
                    446:                 * Don't do anything if we're already enabled.
                    447:                 */
                    448:                DPRINTF(("%s: pcmcia_function_enable on enabled func\n"));
                    449:                return (0);
                    450:        }
                    451:
                    452:        /* If there was no CIS don't mess with CCR */
                    453:        if (pf->pf_flags & PFF_FAKE)
                    454:                goto done;
                    455:
                    456:        /*
                    457:         * It's possible for different functions' CCRs to be in the same
                    458:         * underlying page.  Check for that.
                    459:         */
                    460:        SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
                    461:                if ((tmp->pf_flags & PFF_ENABLED) &&
                    462:                    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
                    463:                    ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
                    464:                     (tmp->ccr_base - tmp->pf_ccr_offset +
                    465:                      tmp->pf_ccr_realsize))) {
                    466:                        pf->pf_ccrt = tmp->pf_ccrt;
                    467:                        pf->pf_ccrh = tmp->pf_ccrh;
                    468:                        pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
                    469:
                    470:                        /*
                    471:                         * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
                    472:                         * tmp->ccr_base) + pf->ccr_base;
                    473:                         */
                    474:                        pf->pf_ccr_offset =
                    475:                            (tmp->pf_ccr_offset + pf->ccr_base) -
                    476:                            tmp->ccr_base;
                    477:                        pf->pf_ccr_window = tmp->pf_ccr_window;
                    478:                        break;
                    479:                }
                    480:        }
                    481:
                    482:        if (tmp == NULL) {
                    483:                if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
                    484:                        goto bad;
                    485:
                    486:                if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
                    487:                    PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
                    488:                    &pf->pf_ccr_window)) {
                    489:                        pcmcia_mem_free(pf, &pf->pf_pcmh);
                    490:                        goto bad;
                    491:                }
                    492:        }
                    493:
                    494:        reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
                    495:        reg |= PCMCIA_CCR_OPTION_LEVIREQ;
                    496:        if (pcmcia_mfc(pf->sc)) {
                    497:                reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
                    498:                if (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))
                    499:                        reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
                    500:                if (pf->ih_fct)
                    501:                        reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
                    502:
                    503:        }
                    504:
                    505:        pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
                    506:
                    507:        reg = 0;
                    508:
                    509:        if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
                    510:                reg |= PCMCIA_CCR_STATUS_IOIS8;
                    511:        if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
                    512:                reg |= PCMCIA_CCR_STATUS_AUDIO;
                    513:        pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
                    514:
                    515:        pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
                    516:
                    517:        if (pcmcia_mfc(pf->sc)) {
                    518:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
                    519:                                 (pf->pf_mfc_iobase >>  0) & 0xff);
                    520:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
                    521:                                 (pf->pf_mfc_iobase >>  8) & 0xff);
                    522:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
                    523:                                 (pf->pf_mfc_iobase >> 16) & 0xff);
                    524:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
                    525:                                 (pf->pf_mfc_iobase >> 24) & 0xff);
                    526:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
                    527:                                 pf->pf_mfc_iomax - pf->pf_mfc_iobase);
                    528:        }
                    529:
                    530: #ifdef PCMCIADEBUG
                    531:        SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
                    532:                printf("%s: function %d CCR at %d offset %lx: "
                    533:                       "%x %x %x %x, %x %x %x %x, %x\n",
                    534:                       tmp->sc->dev.dv_xname, tmp->number,
                    535:                       tmp->pf_ccr_window, tmp->pf_ccr_offset,
                    536:                       pcmcia_ccr_read(tmp, 0x00),
                    537:                       pcmcia_ccr_read(tmp, 0x02),
                    538:                       pcmcia_ccr_read(tmp, 0x04),
                    539:                       pcmcia_ccr_read(tmp, 0x06),
                    540:
                    541:                       pcmcia_ccr_read(tmp, 0x0A),
                    542:                       pcmcia_ccr_read(tmp, 0x0C),
                    543:                       pcmcia_ccr_read(tmp, 0x0E),
                    544:                       pcmcia_ccr_read(tmp, 0x10),
                    545:
                    546:                       pcmcia_ccr_read(tmp, 0x12));
                    547:        }
                    548: #endif
                    549:
                    550:  done:
                    551:        pf->pf_flags |= PFF_ENABLED;
                    552:        delay(1000);
                    553:        return (0);
                    554:
                    555:  bad:
                    556:        /*
                    557:         * Decrement the reference count, and power down the socket, if
                    558:         * necessary.
                    559:         */
                    560:        if (--pf->sc->sc_enabled_count == 0)
                    561:                pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
                    562:        DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
                    563:                 pf->sc->sc_enabled_count));
                    564:
                    565:        return (1);
                    566: }
                    567:
                    568: /* Disable PCMCIA function. */
                    569: void
                    570: pcmcia_function_disable(pf)
                    571:        struct pcmcia_function *pf;
                    572: {
                    573:        struct pcmcia_function *tmp;
                    574:
                    575:        if (pf->cfe == NULL)
                    576:                panic("pcmcia_function_enable: function not initialized");
                    577:
                    578:        if ((pf->pf_flags & PFF_ENABLED) == 0) {
                    579:                /*
                    580:                 * Don't do anything if we're already disabled.
                    581:                 */
                    582:                return;
                    583:        }
                    584:
                    585:        /* If there was no CIS don't mess with CCR */
                    586:        if (pf->pf_flags & PFF_FAKE) {
                    587:                pf->pf_flags &= ~PFF_ENABLED;
                    588:                goto done;
                    589:        }
                    590:
                    591:        /*
                    592:         * it's possible for different functions' CCRs to be in the same
                    593:         * underlying page.  Check for that.  Note we mark us as disabled
                    594:         * first to avoid matching ourself.
                    595:         */
                    596:        pf->pf_flags &= ~PFF_ENABLED;
                    597:        SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
                    598:                if ((tmp->pf_flags & PFF_ENABLED) &&
                    599:                    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
                    600:                    ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
                    601:                (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
                    602:                        break;
                    603:        }
                    604:
                    605:        /* Not used by anyone else; unmap the CCR. */
                    606:        if (tmp == NULL) {
                    607:                pcmcia_mem_unmap(pf, pf->pf_ccr_window);
                    608:                pcmcia_mem_free(pf, &pf->pf_pcmh);
                    609:        }
                    610:
                    611:  done:
                    612:        /*
                    613:         * Decrement the reference count, and power down the socket, if
                    614:         * necessary.
                    615:         */
                    616:        if (--pf->sc->sc_enabled_count == 0)
                    617:                pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
                    618:        DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
                    619:                 pf->sc->sc_enabled_count));
                    620: }
                    621:
                    622: int
                    623: pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
                    624:        struct pcmcia_function *pf;
                    625:        int width;
                    626:        bus_addr_t offset;
                    627:        bus_size_t size;
                    628:        struct pcmcia_io_handle *pcihp;
                    629:        int *windowp;
                    630: {
                    631:        int reg;
                    632:
                    633:        if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
                    634:            width, offset, size, pcihp, windowp))
                    635:                return (1);
                    636:
                    637:        /*
                    638:         * XXX In the multifunction multi-iospace-per-function case, this
                    639:         * needs to cooperate with io_alloc to make sure that the spaces
                    640:         * don't overlap, and that the ccr's are set correctly.
                    641:         */
                    642:
                    643:        if (pcmcia_mfc(pf->sc) &&
                    644:            (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))) {
                    645:                bus_addr_t iobase = pcihp->addr;
                    646:                bus_addr_t iomax = pcihp->addr + pcihp->size - 1;
                    647:
                    648:                if (pf->pf_mfc_iomax == 0) {
                    649:                        pf->pf_mfc_iobase = iobase;
                    650:                        pf->pf_mfc_iomax = iomax;
                    651:                } else {
                    652:                        if (iobase < pf->pf_mfc_iobase)
                    653:                                pf->pf_mfc_iobase = iobase;
                    654:                        if (iomax > pf->pf_mfc_iomax)
                    655:                                pf->pf_mfc_iomax = iomax;
                    656:                }
                    657:
                    658:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
                    659:                                 (pf->pf_mfc_iobase >>  0) & 0xff);
                    660:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
                    661:                                 (pf->pf_mfc_iobase >>  8) & 0xff);
                    662:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
                    663:                                 (pf->pf_mfc_iobase >> 16) & 0xff);
                    664:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
                    665:                                 (pf->pf_mfc_iobase >> 24) & 0xff);
                    666:                pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
                    667:                                 pf->pf_mfc_iomax - pf->pf_mfc_iobase);
                    668:
                    669:                reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
                    670:                reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
                    671:                pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
                    672:        }
                    673:        return (0);
                    674: }
                    675:
                    676: void *
                    677: pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg, xname)
                    678:        struct pcmcia_function *pf;
                    679:        int ipl;
                    680:        int (*ih_fct)(void *);
                    681:        void *ih_arg;
                    682:        char *xname;
                    683: {
                    684:        void *ret;
                    685:        int s, ihcnt, hiipl, reg;
                    686:        struct pcmcia_function *pf2;
                    687:
                    688:        /* Behave differently if this is a multifunction card. */
                    689:        if (pcmcia_mfc(pf->sc)) {
                    690:                /*
                    691:                 * Mask all the ipl's which are already used by this card,
                    692:                 * and find the highest ipl number (lowest priority).
                    693:                 */
                    694:                ihcnt = 0;
                    695:                SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
                    696:                        if (pf2->ih_fct) {
                    697:                                DPRINTF(("%s: function %d has ih_fct %p\n",
                    698:                                    pf->sc->dev.dv_xname, pf2->number,
                    699:                                    pf2->ih_fct));
                    700:
                    701:                                if (ihcnt == 0)
                    702:                                        hiipl = pf2->ih_ipl;
                    703:                                else if (pf2->ih_ipl > hiipl)
                    704:                                        hiipl = pf2->ih_ipl;
                    705:
                    706:                                ihcnt++;
                    707:                        }
                    708:                }
                    709:
                    710:                /*
                    711:                 * Establish the real interrupt, changing the ipl if
                    712:                 * necessary.
                    713:                 */
                    714:                if (ihcnt == 0) {
                    715: #ifdef DIAGNOSTIC
                    716:                        if (pf->sc->ih != NULL)
                    717:                                panic("card has intr handler, "
                    718:                                    "but no function does");
                    719: #endif
                    720:                        s = spltty();
                    721:
                    722:                        /* Set up the handler for the new function. */
                    723:                        pf->ih_fct = ih_fct;
                    724:                        pf->ih_arg = ih_arg;
                    725:                        pf->ih_ipl = ipl;
                    726:
                    727:                        pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
                    728:                            pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
                    729:                            xname);
                    730:                        splx(s);
                    731:                } else if (ipl > hiipl) {
                    732: #ifdef DIAGNOSTIC
                    733:                        if (pf->sc->ih == NULL)
                    734:                                panic("functions have ih, "
                    735:                                    "but the card does not");
                    736: #endif
                    737:
                    738:                        s = spltty();
                    739:
                    740:                        pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
                    741:                            pf->sc->ih);
                    742:
                    743:                        /* set up the handler for the new function */
                    744:                        pf->ih_fct = ih_fct;
                    745:                        pf->ih_arg = ih_arg;
                    746:                        pf->ih_ipl = ipl;
                    747:
                    748:                        pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
                    749:                            pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
                    750:                            xname);
                    751:
                    752:                        splx(s);
                    753:                } else {
                    754:                        s = spltty();
                    755:
                    756:                        /* Set up the handler for the new function. */
                    757:                        pf->ih_fct = ih_fct;
                    758:                        pf->ih_arg = ih_arg;
                    759:                        pf->ih_ipl = ipl;
                    760:
                    761:                        splx(s);
                    762:                }
                    763:
                    764:                ret = pf->sc->ih;
                    765:
                    766:                if (ret != NULL) {
                    767:                        reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
                    768:                        reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
                    769:                        pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
                    770:
                    771:                        reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
                    772:                        reg |= PCMCIA_CCR_STATUS_INTRACK;
                    773:                        pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
                    774:                }
                    775:        } else
                    776:                ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
                    777:                    pf, ipl, ih_fct, ih_arg, xname);
                    778:
                    779:        return (ret);
                    780: }
                    781:
                    782: void
                    783: pcmcia_intr_disestablish(pf, ih)
                    784:        struct pcmcia_function *pf;
                    785:        void *ih;
                    786: {
                    787:        int s, reg, ihcnt, hiipl;
                    788:        struct pcmcia_function *pf2;
                    789:
                    790:        /* Behave differently if this is a multifunction card.  */
                    791:        if (pcmcia_mfc(pf->sc)) {
                    792:                /*
                    793:                 * Mask all the ipl's which are already used by this card,
                    794:                 * and find the highest ipl number (lowest priority).  Skip
                    795:                 * the current function.
                    796:                 */
                    797:                ihcnt = 0;
                    798:                SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
                    799:                        if (pf2 == pf)
                    800:                                continue;
                    801:
                    802:                        if (pf2->ih_fct) {
                    803:                                if (ihcnt == 0)
                    804:                                        hiipl = pf2->ih_ipl;
                    805:                                else if (pf2->ih_ipl > hiipl)
                    806:                                        hiipl = pf2->ih_ipl;
                    807:                                ihcnt++;
                    808:                        }
                    809:                }
                    810:
                    811:                /*
                    812:                 * If the ih being removed is lower priority than the lowest
                    813:                 * priority remaining interrupt, up the priority.
                    814:                 */
                    815:
                    816:                /*
                    817:                 * ihcnt is the number of interrupt handlers *not* including
                    818:                 * the one about to be removed.
                    819:                 */
                    820:                if (ihcnt == 0) {
                    821: #ifdef DIAGNOSTIC
                    822:                        if (pf->sc->ih == NULL)
                    823:                                panic("disestablishing last function, but card has no ih");
                    824: #endif
                    825:                        pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
                    826:                            pf->sc->ih);
                    827:
                    828:                        reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
                    829:                        reg &= ~PCMCIA_CCR_OPTION_IREQ_ENABLE;
                    830:                        pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
                    831:
                    832:                        pf->ih_fct = NULL;
                    833:                        pf->ih_arg = NULL;
                    834:
                    835:                        pf->sc->ih = NULL;
                    836:                } else if (pf->ih_ipl > hiipl) {
                    837: #ifdef DIAGNOSTIC
                    838:                        if (pf->sc->ih == NULL)
                    839:                                panic("changing ih ipl, but card has no ih");
                    840: #endif
                    841:                        s = spltty();
                    842:
                    843:                        pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
                    844:                            pf->sc->ih);
                    845:                        pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
                    846:                            pf->sc->pch, pf, hiipl, pcmcia_card_intr, pf->sc,
                    847:                            NULL);
                    848:
                    849:                        /* Null out the handler for this function. */
                    850:                        pf->ih_fct = NULL;
                    851:                        pf->ih_arg = NULL;
                    852:
                    853:                        splx(s);
                    854:                } else {
                    855:                        s = spltty();
                    856:
                    857:                        pf->ih_fct = NULL;
                    858:                        pf->ih_arg = NULL;
                    859:
                    860:                        splx(s);
                    861:                }
                    862:        } else
                    863:                pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
                    864: }
                    865:
                    866: const char *
                    867: pcmcia_intr_string(pf, ih)
                    868:        struct pcmcia_function *pf;
                    869:        void *ih;
                    870: {
                    871:        return pcmcia_chip_intr_string(pf->sc->pct, pf->sc->pch, ih);
                    872: }
                    873:
                    874: int
                    875: pcmcia_card_intr(arg)
                    876:        void *arg;
                    877: {
                    878:        struct pcmcia_softc *sc = arg;
                    879:        struct pcmcia_function *pf;
                    880:        int reg, ret, ret2;
                    881:
                    882:        ret = 0;
                    883:
                    884:        for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
                    885:            pf = SIMPLEQ_NEXT(pf, pf_list)) {
                    886: #ifdef PCMCIADEBUG
                    887:                printf("%s: intr flags=%x fct=%d cor=%02x csr=%02x pin=%02x",
                    888:                       sc->dev.dv_xname, pf->pf_flags, pf->number,
                    889:                       pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION),
                    890:                       pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS),
                    891:                       pcmcia_ccr_read(pf, PCMCIA_CCR_PIN));
                    892: #endif
                    893:                if (pf->ih_fct != NULL &&
                    894:                    (pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) {
                    895:                        reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
                    896:                        if (reg & PCMCIA_CCR_STATUS_INTR) {
                    897:                                ret2 = (*pf->ih_fct)(pf->ih_arg);
                    898:                                if (ret2 != 0 && ret == 0)
                    899:                                        ret = ret2;
                    900:                                reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
                    901: #ifdef PCMCIADEBUG
                    902:                                printf("; csr %02x->%02x",
                    903:                                    reg, reg & ~PCMCIA_CCR_STATUS_INTR);
                    904: #endif
                    905:                                pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
                    906:                                    reg & ~PCMCIA_CCR_STATUS_INTR);
                    907:                        }
                    908:                }
                    909: #ifdef PCMCIADEBUG
                    910:                printf("\n");
                    911: #endif
                    912:        }
                    913:
                    914:        return (ret);
                    915: }

CVSweb