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