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

Annotation of sys/dev/cardbus/cardslot.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: cardslot.c,v 1.7 2005/09/19 19:05:39 fgsch Exp $      */
                      2: /*     $NetBSD: cardslot.c,v 1.9 2000/03/22 09:35:06 haya Exp $        */
                      3:
                      4: /*
                      5:  * Copyright (c) 1999 and 2000
                      6:  *       HAYAKAWA Koichi.  All rights reserved.
                      7:  *
                      8:  * Redistribution and use in source and binary forms, with or without
                      9:  * modification, are permitted provided that the following conditions
                     10:  * are met:
                     11:  * 1. Redistributions of source code must retain the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer.
                     13:  * 2. Redistributions in binary form must reproduce the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer in the
                     15:  *    documentation and/or other materials provided with the distribution.
                     16:  * 3. All advertising materials mentioning features or use of this software
                     17:  *    must display the following acknowledgement:
                     18:  *     This product includes software developed by HAYAKAWA Koichi.
                     19:  * 4. The name of the author may not be used to endorse or promote products
                     20:  *    derived from this software without specific prior written permission.
                     21:  *
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
                     27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
                     28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
                     31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
                     32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     33:  * POSSIBILITY OF SUCH DAMAGE.
                     34:  */
                     35:
                     36: #include <sys/param.h>
                     37: #include <sys/systm.h>
                     38: #include <sys/device.h>
                     39: #include <sys/malloc.h>
                     40: #include <sys/kernel.h>
                     41: #include <sys/syslog.h>
                     42: #include <sys/kthread.h>
                     43:
                     44: #include <machine/bus.h>
                     45:
                     46: #include <dev/cardbus/cardslotvar.h>
                     47: #include <dev/cardbus/cardbusvar.h>
                     48: #include <dev/pcmcia/pcmciavar.h>
                     49: #include <dev/pcmcia/pcmciachip.h>
                     50: #include <dev/ic/i82365var.h>
                     51:
                     52: #if defined CARDSLOT_DEBUG
                     53: #define STATIC
                     54: #define DPRINTF(a) printf a
                     55: #else
                     56: #define STATIC static
                     57: #define DPRINTF(a)
                     58: #endif
                     59:
                     60: STATIC void cardslotattach(struct device *, struct device *, void *);
                     61:
                     62: STATIC int cardslotmatch(struct device *, void *, void *);
                     63: static void create_slot_manager(void *);
                     64: static void cardslot_event_thread(void *arg);
                     65:
                     66: STATIC int cardslot_cb_print(void *aux, const char *pcic);
                     67: static int cardslot_16_print(void *, const char *);
                     68: static int cardslot_16_submatch(struct device *, void *,void *);
                     69:
                     70: struct cfattach cardslot_ca = {
                     71:        sizeof(struct cardslot_softc), cardslotmatch, cardslotattach
                     72: };
                     73:
                     74: struct cfdriver cardslot_cd = {
                     75:        NULL, "cardslot", DV_DULL
                     76: };
                     77:
                     78: STATIC int
                     79: cardslotmatch(struct device *parent, void *match, void *aux)
                     80: {
                     81:        struct cardslot_attach_args *caa = aux;
                     82:
                     83:        if (caa->caa_cb_attach == NULL && caa->caa_16_attach == NULL) {
                     84:                /* Neither CardBus nor 16-bit PCMCIA are defined. */
                     85:                return (0);
                     86:        }
                     87:
                     88:        return (1);
                     89: }
                     90:
                     91: STATIC void
                     92: cardslotattach(struct device *parent, struct device *self, void *aux)
                     93: {
                     94:        struct cardslot_softc *sc = (struct cardslot_softc *)self;
                     95:        struct cardslot_attach_args *caa = aux;
                     96:
                     97:        struct cbslot_attach_args *cba = caa->caa_cb_attach;
                     98:        struct pcmciabus_attach_args *pa = caa->caa_16_attach;
                     99:
                    100:        struct cardbus_softc *csc;
                    101:        struct pcmcia_softc *psc;
                    102:
                    103:        sc->sc_slot = sc->sc_dev.dv_unit;
                    104:        sc->sc_cb_softc = NULL;
                    105:        sc->sc_16_softc = NULL;
                    106:        SIMPLEQ_INIT(&sc->sc_events);
                    107:        sc->sc_th_enable = 0;
                    108:
                    109:        printf(" slot %d flags %x\n", sc->sc_slot,
                    110:            sc->sc_dev.dv_cfdata->cf_flags);
                    111:
                    112:        DPRINTF(("%s attaching CardBus bus...\n", sc->sc_dev.dv_xname));
                    113:        if (cba != NULL) {
                    114:                if ((csc = (void *)config_found(self, cba,
                    115:                    cardslot_cb_print)) != NULL) {
                    116:                        /* cardbus found */
                    117:                        DPRINTF(("cardslotattach: found cardbus on %s\n",
                    118:                            sc->sc_dev.dv_xname));
                    119:                        sc->sc_cb_softc = csc;
                    120:                }
                    121:        }
                    122:
                    123:        if (pa != NULL) {
                    124:                if ((psc = (void *)config_found_sm(self, pa, cardslot_16_print,
                    125:                    cardslot_16_submatch)) != NULL) {
                    126:                        /* pcmcia 16-bit bus found */
                    127:                        DPRINTF(("cardslotattach: found 16-bit pcmcia bus\n"));
                    128:                        sc->sc_16_softc = psc;
                    129:                        /* XXX: dirty.  This code should be removed
                    130:                         * to achieve MI
                    131:                         */
                    132:                        caa->caa_ph->pcmcia = (struct device *)psc;
                    133:                }
                    134:        }
                    135:
                    136:        if (csc != NULL || psc != NULL)
                    137:                kthread_create_deferred(create_slot_manager, (void *)sc);
                    138:
                    139:        if (csc && (csc->sc_cf->cardbus_ctrl)(csc->sc_cc, CARDBUS_CD)) {
                    140:                DPRINTF(("cardslotattach: CardBus card found\n"));
                    141:                /* attach deferred */
                    142:                cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_CB);
                    143:        }
                    144:
                    145:        if (psc && (psc->pct->card_detect)(psc->pch)) {
                    146:                DPRINTF(("cardbusattach: 16-bit card found\n"));
                    147:                /* attach deferred */
                    148:                cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_16);
                    149:        }
                    150: }
                    151:
                    152: STATIC int
                    153: cardslot_cb_print(void *aux, const char *pnp)
                    154: {
                    155:        struct cbslot_attach_args *cba = aux;
                    156:
                    157:        if (pnp)
                    158:                printf("cardbus at %s subordinate bus %d", pnp, cba->cba_bus);
                    159:
                    160:        return (UNCONF);
                    161: }
                    162:
                    163: static int
                    164: cardslot_16_submatch(struct device *parent, void *match, void *aux)
                    165: {
                    166:        struct cfdata *cf = match;
                    167:
                    168:        if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 0)
                    169:                return (0);
                    170:
                    171:        if (cf->cf_loc[0] == -1)
                    172:                return ((*cf->cf_attach->ca_match)(parent, cf, aux));
                    173:
                    174:        return (0);
                    175: }
                    176:
                    177: static int
                    178: cardslot_16_print(void *arg, const char *pnp)
                    179: {
                    180:        if (pnp)
                    181:                printf("pcmciabus at %s", pnp);
                    182:
                    183:        return (UNCONF);
                    184: }
                    185:
                    186: static void
                    187: create_slot_manager(void *arg)
                    188: {
                    189:        struct cardslot_softc *sc = (struct cardslot_softc *)arg;
                    190:
                    191:        sc->sc_th_enable = 1;
                    192:
                    193:        if (kthread_create(cardslot_event_thread, sc, &sc->sc_event_thread,
                    194:            "%s", sc->sc_dev.dv_xname)) {
                    195:                printf("%s: unable to create event thread for slot %d\n",
                    196:                    sc->sc_dev.dv_xname, sc->sc_slot);
                    197:                panic("create_slot_manager");
                    198:        }
                    199: }
                    200:
                    201: /*
                    202:  * void cardslot_event_throw(struct cardslot_softc *sc, int ev)
                    203:  *
                    204:  *   This function throws an event to the event handler.  If the state
                    205:  *   of a slot is changed, it should be noticed using this function.
                    206:  */
                    207: void
                    208: cardslot_event_throw(struct cardslot_softc *sc, int ev)
                    209: {
                    210:        struct cardslot_event *ce;
                    211:
                    212:        DPRINTF(("cardslot_event_throw: an event %s comes\n",
                    213:            ev == CARDSLOT_EVENT_INSERTION_CB ? "CardBus Card inserted" :
                    214:            ev == CARDSLOT_EVENT_INSERTION_16 ? "16-bit Card inserted" :
                    215:            ev == CARDSLOT_EVENT_REMOVAL_CB ? "CardBus Card removed" :
                    216:            ev == CARDSLOT_EVENT_REMOVAL_16 ? "16-bit Card removed" : "???"));
                    217:
                    218:        if ((ce = (struct cardslot_event *)malloc(sizeof(struct cardslot_event),
                    219:            M_TEMP, M_NOWAIT)) == NULL) {
                    220:                panic("cardslot_event");
                    221:        }
                    222:
                    223:        ce->ce_type = ev;
                    224:
                    225:        {
                    226:                int s = spltty();
                    227:                SIMPLEQ_INSERT_TAIL(&sc->sc_events, ce, ce_q);
                    228:                splx(s);
                    229:        }
                    230:
                    231:        wakeup(&sc->sc_events);
                    232: }
                    233:
                    234: /*
                    235:  * static void cardslot_event_thread(void *arg)
                    236:  *
                    237:  *   This function is the main routine handing cardslot events such as
                    238:  *   insertions and removals.
                    239:  *
                    240:  */
                    241: static void
                    242: cardslot_event_thread(void *arg)
                    243: {
                    244:        struct cardslot_softc *sc = arg;
                    245:        struct cardslot_event *ce;
                    246:        int s;
                    247:        static int antonym_ev[4] = {
                    248:                CARDSLOT_EVENT_REMOVAL_16, CARDSLOT_EVENT_INSERTION_16,
                    249:                CARDSLOT_EVENT_REMOVAL_CB, CARDSLOT_EVENT_INSERTION_CB
                    250:        };
                    251:
                    252:        while (sc->sc_th_enable) {
                    253:                s = spltty();
                    254:                if ((ce = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) {
                    255:                        splx(s);
                    256:                        (void) tsleep(&sc->sc_events, PWAIT, "cardslotev", 0);
                    257:                        continue;
                    258:                }
                    259:                SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q);
                    260:                splx(s);
                    261:
                    262:                if (IS_CARDSLOT_INSERT_REMOVE_EV(ce->ce_type)) {
                    263:                        /* Chattering suppression */
                    264:                        s = spltty();
                    265:                        while (1) {
                    266:                                struct cardslot_event *ce1, *ce2;
                    267:
                    268:                                if ((ce1 = SIMPLEQ_FIRST(&sc->sc_events)) ==
                    269:                                    NULL)
                    270:                                        break;
                    271:                                if (ce1->ce_type != antonym_ev[ce->ce_type])
                    272:                                        break;
                    273:                                if ((ce2 = SIMPLEQ_NEXT(ce1, ce_q)) == NULL)
                    274:                                        break;
                    275:                                if (ce2->ce_type == ce->ce_type) {
                    276:                                        SIMPLEQ_REMOVE_HEAD(&sc->sc_events,
                    277:                                            ce_q);
                    278:                                        free(ce1, M_TEMP);
                    279:                                        SIMPLEQ_REMOVE_HEAD(&sc->sc_events,
                    280:                                            ce_q);
                    281:                                        free(ce2, M_TEMP);
                    282:                                }
                    283:                        }
                    284:                        splx(s);
                    285:                }
                    286:
                    287:                switch (ce->ce_type) {
                    288:                case CARDSLOT_EVENT_INSERTION_CB:
                    289:                        if ((CARDSLOT_CARDTYPE(sc->sc_status) ==
                    290:                             CARDSLOT_STATUS_CARD_CB) ||
                    291:                            (CARDSLOT_CARDTYPE(sc->sc_status) ==
                    292:                             CARDSLOT_STATUS_CARD_16)) {
                    293:                                if (CARDSLOT_WORK(sc->sc_status) ==
                    294:                                    CARDSLOT_STATUS_WORKING) {
                    295:                                        /* A card has already been inserted
                    296:                                         * and works.
                    297:                                         */
                    298:                                        break;
                    299:                                }
                    300:                        }
                    301:
                    302:                        if (sc->sc_cb_softc) {
                    303:                                CARDSLOT_SET_CARDTYPE(sc->sc_status,
                    304:                                    CARDSLOT_STATUS_CARD_CB);
                    305:                                if (cardbus_attach_card(sc->sc_cb_softc) > 0) {
                    306:                                        /* At least one function works */
                    307:                                        CARDSLOT_SET_WORK(sc->sc_status,
                    308:                                            CARDSLOT_STATUS_WORKING);
                    309:                                } else {
                    310:                                        /* No functions work or this card is
                    311:                                         * not known
                    312:                                         */
                    313:                                        CARDSLOT_SET_WORK(sc->sc_status,
                    314:                                            CARDSLOT_STATUS_NOTWORK);
                    315:                                }
                    316:                        } else {
                    317:                                panic("no cardbus on %s", sc->sc_dev.dv_xname);
                    318:                        }
                    319:
                    320:                        break;
                    321:
                    322:                case CARDSLOT_EVENT_INSERTION_16:
                    323:                        if ((CARDSLOT_CARDTYPE(sc->sc_status) ==
                    324:                             CARDSLOT_STATUS_CARD_CB) ||
                    325:                            (CARDSLOT_CARDTYPE(sc->sc_status) ==
                    326:                             CARDSLOT_STATUS_CARD_16)) {
                    327:                                if (CARDSLOT_WORK(sc->sc_status) ==
                    328:                                    CARDSLOT_STATUS_WORKING) {
                    329:                                        /* A card has already been inserted
                    330:                                         * and works.
                    331:                                         */
                    332:                                        break;
                    333:                                }
                    334:                        }
                    335:                        if (sc->sc_16_softc) {
                    336:                                CARDSLOT_SET_CARDTYPE(sc->sc_status,
                    337:                                    CARDSLOT_STATUS_CARD_16);
                    338:                                if (pcmcia_card_attach(
                    339:                                    (struct device *)sc->sc_16_softc)) {
                    340:                                        /* Do not attach */
                    341:                                        CARDSLOT_SET_WORK(sc->sc_status,
                    342:                                            CARDSLOT_STATUS_NOTWORK);
                    343:                                } else {
                    344:                                        /* working */
                    345:                                        CARDSLOT_SET_WORK(sc->sc_status,
                    346:                                            CARDSLOT_STATUS_WORKING);
                    347:                                }
                    348:                        } else {
                    349:                                panic("no 16-bit pcmcia on %s",
                    350:                                    sc->sc_dev.dv_xname);
                    351:                        }
                    352:
                    353:                        break;
                    354:
                    355:                case CARDSLOT_EVENT_REMOVAL_CB:
                    356:                        if (CARDSLOT_CARDTYPE(sc->sc_status) ==
                    357:                            CARDSLOT_STATUS_CARD_CB) {
                    358:                                /* CardBus card has not been inserted. */
                    359:                                if (CARDSLOT_WORK(sc->sc_status) ==
                    360:                                    CARDSLOT_STATUS_WORKING) {
                    361:                                        cardbus_detach_card(sc->sc_cb_softc);
                    362:                                        CARDSLOT_SET_WORK(sc->sc_status,
                    363:                                            CARDSLOT_STATUS_NOTWORK);
                    364:                                        CARDSLOT_SET_WORK(sc->sc_status,
                    365:                                            CARDSLOT_STATUS_CARD_NONE);
                    366:                                }
                    367:                                CARDSLOT_SET_CARDTYPE(sc->sc_status,
                    368:                                    CARDSLOT_STATUS_CARD_NONE);
                    369:                        } else if (CARDSLOT_CARDTYPE(sc->sc_status) !=
                    370:                            CARDSLOT_STATUS_CARD_16) {
                    371:                                /* Unknown card... */
                    372:                                CARDSLOT_SET_CARDTYPE(sc->sc_status,
                    373:                                    CARDSLOT_STATUS_CARD_NONE);
                    374:                        }
                    375:                        CARDSLOT_SET_WORK(sc->sc_status,
                    376:                            CARDSLOT_STATUS_NOTWORK);
                    377:                        break;
                    378:
                    379:                case CARDSLOT_EVENT_REMOVAL_16:
                    380:                        DPRINTF(("%s: removal event\n", sc->sc_dev.dv_xname));
                    381:                        if (CARDSLOT_CARDTYPE(sc->sc_status) !=
                    382:                            CARDSLOT_STATUS_CARD_16) {
                    383:                                /* 16-bit card has not been inserted. */
                    384:                                break;
                    385:                        }
                    386:                        if ((sc->sc_16_softc != NULL) &&
                    387:                            (CARDSLOT_WORK(sc->sc_status) ==
                    388:                             CARDSLOT_STATUS_WORKING)) {
                    389:                                struct pcmcia_softc *psc = sc->sc_16_softc;
                    390:
                    391:                                pcmcia_card_deactivate((struct device *)psc);
                    392:                                pcmcia_chip_socket_disable(psc->pct, psc->pch);
                    393:                                pcmcia_card_detach((struct device *)psc,
                    394:                                    DETACH_FORCE);
                    395:                        }
                    396:                        CARDSLOT_SET_CARDTYPE(sc->sc_status,
                    397:                            CARDSLOT_STATUS_CARD_NONE);
                    398:                        CARDSLOT_SET_WORK(sc->sc_status,
                    399:                            CARDSLOT_STATUS_NOTWORK);
                    400:                        break;
                    401:
                    402:                default:
                    403:                        panic("cardslot_event_thread: unknown event %d",
                    404:                            ce->ce_type);
                    405:                }
                    406:                free(ce, M_TEMP);
                    407:        }
                    408:
                    409:        sc->sc_event_thread = NULL;
                    410:
                    411:        /* In case the parent device is waiting for us to exit. */
                    412:        wakeup(sc);
                    413:
                    414:        kthread_exit(0);
                    415: }

CVSweb