[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     ! 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