root/dev/cardbus/cardslot.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cardslotmatch
  2. cardslotattach
  3. cardslot_cb_print
  4. cardslot_16_submatch
  5. cardslot_16_print
  6. create_slot_manager
  7. cardslot_event_throw
  8. cardslot_event_thread

    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 }

/* [<][>][^][v][top][bottom][index][help] */