The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/cardbus/cardslot.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $OpenBSD: cardslot.c,v 1.23 2022/04/06 18:59:27 naddy 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  *
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   21  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   22  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   24  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   26  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   28  * POSSIBILITY OF SUCH DAMAGE.
   29  */
   30 
   31 #include <sys/param.h>
   32 #include <sys/systm.h>
   33 #include <sys/device.h>
   34 #include <sys/malloc.h>
   35 #include <sys/kernel.h>
   36 #include <sys/syslog.h>
   37 #include <sys/pool.h>
   38 #include <sys/task.h>
   39 
   40 #include <dev/cardbus/cardslotvar.h>
   41 #include <dev/cardbus/cardbusvar.h>
   42 #include <dev/pcmcia/pcmciavar.h>
   43 #include <dev/pcmcia/pcmciachip.h>
   44 #include <dev/ic/i82365var.h>
   45 
   46 #if defined CARDSLOT_DEBUG
   47 #define STATIC
   48 #define DPRINTF(a) printf a
   49 #else
   50 #ifdef DDB
   51 #define STATIC
   52 #else
   53 #define STATIC static
   54 #endif
   55 #define DPRINTF(a)
   56 #endif
   57 
   58 STATIC void cardslotattach(struct device *, struct device *, void *);
   59 
   60 STATIC int cardslotmatch(struct device *, void *, void *);
   61 STATIC void cardslot_event(void *arg);
   62 STATIC void cardslot_process_event(struct cardslot_softc *);
   63 
   64 STATIC int cardslot_cb_print(void *aux, const char *pcic);
   65 STATIC int cardslot_16_print(void *, const char *);
   66 STATIC int cardslot_16_submatch(struct device *, void *,void *);
   67 
   68 const struct cfattach cardslot_ca = {
   69         sizeof(struct cardslot_softc), cardslotmatch, cardslotattach
   70 };
   71 
   72 struct cfdriver cardslot_cd = {
   73         NULL, "cardslot", DV_DULL
   74 };
   75 
   76 struct pool cardsloteventpool;
   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 = NULL;
  101         struct pcmcia_softc *psc = NULL;
  102 
  103         if (cardsloteventpool.pr_size == 0) {
  104                 pool_init(&cardsloteventpool, sizeof(struct cardslot_event),
  105                     0, IPL_BIO, 0, "cardslot", NULL);
  106         }
  107 
  108         sc->sc_slot = sc->sc_dev.dv_unit;
  109         sc->sc_cb_softc = NULL;
  110         sc->sc_16_softc = NULL;
  111         SIMPLEQ_INIT(&sc->sc_events);
  112         task_set(&sc->sc_event_task, cardslot_event, sc);
  113 
  114         printf(" slot %d flags %x\n", sc->sc_slot,
  115             sc->sc_dev.dv_cfdata->cf_flags);
  116 
  117         DPRINTF(("%s attaching CardBus bus...\n", sc->sc_dev.dv_xname));
  118         if (cba != NULL) {
  119                 if ((csc = (void *)config_found(self, cba,
  120                     cardslot_cb_print)) != NULL) {
  121                         /* cardbus found */
  122                         DPRINTF(("cardslotattach: found cardbus on %s\n",
  123                             sc->sc_dev.dv_xname));
  124                         sc->sc_cb_softc = csc;
  125                 }
  126         }
  127 
  128         if (pa != NULL) {
  129                 if ((psc = (void *)config_found_sm(self, pa, cardslot_16_print,
  130                     cardslot_16_submatch)) != NULL) {
  131                         /* pcmcia 16-bit bus found */
  132                         DPRINTF(("cardslotattach: found 16-bit pcmcia bus\n"));
  133                         sc->sc_16_softc = psc;
  134                         /* XXX: dirty.  This code should be removed
  135                          * to achieve MI
  136                          */
  137                         caa->caa_ph->pcmcia = (struct device *)psc;
  138                 }
  139         }
  140 
  141         if (csc && (csc->sc_cf->cardbus_ctrl)(csc->sc_cc, CARDBUS_CD)) {
  142                 DPRINTF(("cardslotattach: CardBus card found\n"));
  143                 /* attach deferred */
  144                 cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_CB);
  145         }
  146 
  147         if (psc && (psc->pct->card_detect)(psc->pch)) {
  148                 DPRINTF(("cardbusattach: 16-bit card found\n"));
  149                 /* attach deferred */
  150                 cardslot_event_throw(sc, CARDSLOT_EVENT_INSERTION_16);
  151         }
  152 }
  153 
  154 STATIC int
  155 cardslot_cb_print(void *aux, const char *pnp)
  156 {
  157         struct cbslot_attach_args *cba = aux;
  158 
  159         if (pnp)
  160                 printf("cardbus at %s subordinate bus %d", pnp, cba->cba_bus);
  161 
  162         return (UNCONF);
  163 }
  164 
  165 STATIC int
  166 cardslot_16_submatch(struct device *parent, void *match, void *aux)
  167 {
  168         struct cfdata *cf = match;
  169 
  170         if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != 0)
  171                 return (0);
  172 
  173         if (cf->cf_loc[0] == -1)
  174                 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
  175 
  176         return (0);
  177 }
  178 
  179 STATIC int
  180 cardslot_16_print(void *arg, const char *pnp)
  181 {
  182         if (pnp)
  183                 printf("pcmciabus at %s", pnp);
  184 
  185         return (UNCONF);
  186 }
  187 
  188 /*
  189  * void cardslot_event_throw(struct cardslot_softc *sc, int ev)
  190  *
  191  *   This function throws an event to the event handler.  If the state
  192  *   of a slot is changed, it should be noticed using this function.
  193  */
  194 void
  195 cardslot_event_throw(struct cardslot_softc *sc, int ev)
  196 {
  197         struct cardslot_event *ce;
  198         int s;
  199 
  200         DPRINTF(("cardslot_event_throw: an event %s comes\n",
  201             ev == CARDSLOT_EVENT_INSERTION_CB ? "CardBus Card inserted" :
  202             ev == CARDSLOT_EVENT_INSERTION_16 ? "16-bit Card inserted" :
  203             ev == CARDSLOT_EVENT_REMOVAL_CB ? "CardBus Card removed" :
  204             ev == CARDSLOT_EVENT_REMOVAL_16 ? "16-bit Card removed" : "???"));
  205 
  206         ce = pool_get(&cardsloteventpool, PR_NOWAIT);
  207         if (ce == NULL)
  208                 return;
  209         ce->ce_type = ev;
  210 
  211         s = spltty();
  212         SIMPLEQ_INSERT_TAIL(&sc->sc_events, ce, ce_q);
  213         splx(s);
  214 
  215         task_add(systq, &sc->sc_event_task);
  216 }
  217 
  218 /*
  219  * STATIC void cardslot_event(void *arg)
  220  *
  221  *   This function is the main routine handing cardslot events such as
  222  *   insertions and removals.
  223  *
  224  */
  225 STATIC void
  226 cardslot_event(void *arg1)
  227 {
  228         struct cardslot_softc *sc = arg1;
  229 
  230         while (!SIMPLEQ_EMPTY(&sc->sc_events))
  231                 cardslot_process_event(sc);
  232 }
  233 
  234 
  235 STATIC void
  236 cardslot_process_event(struct cardslot_softc *sc)
  237 {
  238         struct cardslot_event *ce;
  239         int s, ev;
  240 
  241         s = spltty();
  242         if ((ce = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) {
  243                 splx(s);
  244                 return;
  245         }
  246         SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q);
  247 
  248         if (IS_CARDSLOT_INSERT_REMOVE_EV(ce->ce_type)) {
  249                 /* Chattering suppression */
  250                 static int antonym_ev[4] = {
  251                         CARDSLOT_EVENT_REMOVAL_16,
  252                         CARDSLOT_EVENT_INSERTION_16,
  253                         CARDSLOT_EVENT_REMOVAL_CB,
  254                         CARDSLOT_EVENT_INSERTION_CB
  255                 };
  256 
  257                 while (1) {
  258                         struct cardslot_event *ce1, *ce2;
  259 
  260                         if ((ce1 = SIMPLEQ_FIRST(&sc->sc_events)) ==
  261                             NULL)
  262                                 break;
  263                         if (ce1->ce_type != antonym_ev[ce->ce_type])
  264                                 break;
  265                         if ((ce2 = SIMPLEQ_NEXT(ce1, ce_q)) == NULL)
  266                                 break;
  267                         if (ce2->ce_type == ce->ce_type) {
  268                                 SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q);
  269                                 pool_put(&cardsloteventpool, ce1);
  270                                 SIMPLEQ_REMOVE_HEAD(&sc->sc_events, ce_q);
  271                                 pool_put(&cardsloteventpool, ce2);
  272                         }
  273                 }
  274         }
  275         splx(s);
  276 
  277         ev = ce->ce_type;
  278         pool_put(&cardsloteventpool, ce);
  279 
  280         switch (ev) {
  281         case CARDSLOT_EVENT_INSERTION_CB:
  282                 if ((CARDSLOT_CARDTYPE(sc->sc_status) ==
  283                      CARDSLOT_STATUS_CARD_CB) ||
  284                     (CARDSLOT_CARDTYPE(sc->sc_status) ==
  285                      CARDSLOT_STATUS_CARD_16)) {
  286                         if (CARDSLOT_WORK(sc->sc_status) ==
  287                             CARDSLOT_STATUS_WORKING) {
  288                                 /* A card has already been inserted
  289                                  * and works.
  290                                  */
  291                                 break;
  292                         }
  293                 }
  294 
  295                 if (sc->sc_cb_softc) {
  296                         CARDSLOT_SET_CARDTYPE(sc->sc_status,
  297                             CARDSLOT_STATUS_CARD_CB);
  298                         if (cardbus_attach_card(sc->sc_cb_softc) > 0) {
  299                                 /* At least one function works */
  300                                 CARDSLOT_SET_WORK(sc->sc_status,
  301                                     CARDSLOT_STATUS_WORKING);
  302                         } else {
  303                                 /* No functions work or this card is
  304                                  * not known
  305                                  */
  306                                 CARDSLOT_SET_WORK(sc->sc_status,
  307                                     CARDSLOT_STATUS_NOTWORK);
  308                         }
  309                 } else {
  310                         printf("%s: CardBus support disabled\n",
  311                             sc->sc_dev.dv_xname);
  312                 }
  313                 break;
  314 
  315         case CARDSLOT_EVENT_INSERTION_16:
  316                 if ((CARDSLOT_CARDTYPE(sc->sc_status) ==
  317                      CARDSLOT_STATUS_CARD_CB) ||
  318                     (CARDSLOT_CARDTYPE(sc->sc_status) ==
  319                      CARDSLOT_STATUS_CARD_16)) {
  320                         if (CARDSLOT_WORK(sc->sc_status) ==
  321                             CARDSLOT_STATUS_WORKING) {
  322                                 /* A card has already been inserted
  323                                  * and works.
  324                                  */
  325                                 break;
  326                         }
  327                 }
  328                 if (sc->sc_16_softc) {
  329                         CARDSLOT_SET_CARDTYPE(sc->sc_status,
  330                             CARDSLOT_STATUS_CARD_16);
  331                         if (pcmcia_card_attach(
  332                             (struct device *)sc->sc_16_softc)) {
  333                                 /* Do not attach */
  334                                 CARDSLOT_SET_WORK(sc->sc_status,
  335                                     CARDSLOT_STATUS_NOTWORK);
  336                         } else {
  337                                 /* working */
  338                                 CARDSLOT_SET_WORK(sc->sc_status,
  339                                     CARDSLOT_STATUS_WORKING);
  340                         }
  341                 } else {
  342                         panic("no 16-bit pcmcia on %s",
  343                             sc->sc_dev.dv_xname);
  344                 }
  345                 break;
  346 
  347         case CARDSLOT_EVENT_REMOVAL_CB:
  348                 if (CARDSLOT_CARDTYPE(sc->sc_status) ==
  349                     CARDSLOT_STATUS_CARD_CB) {
  350                         /* CardBus card has not been inserted. */
  351                         if (CARDSLOT_WORK(sc->sc_status) ==
  352                             CARDSLOT_STATUS_WORKING) {
  353                                 cardbus_detach_card(sc->sc_cb_softc);
  354                                 CARDSLOT_SET_WORK(sc->sc_status,
  355                                     CARDSLOT_STATUS_NOTWORK);
  356                                 CARDSLOT_SET_WORK(sc->sc_status,
  357                                     CARDSLOT_STATUS_CARD_NONE);
  358                         }
  359                         CARDSLOT_SET_CARDTYPE(sc->sc_status,
  360                             CARDSLOT_STATUS_CARD_NONE);
  361                 } else if (CARDSLOT_CARDTYPE(sc->sc_status) !=
  362                     CARDSLOT_STATUS_CARD_16) {
  363                         /* Unknown card... */
  364                         CARDSLOT_SET_CARDTYPE(sc->sc_status,
  365                             CARDSLOT_STATUS_CARD_NONE);
  366                 }
  367                 CARDSLOT_SET_WORK(sc->sc_status,
  368                     CARDSLOT_STATUS_NOTWORK);
  369                 break;
  370 
  371         case CARDSLOT_EVENT_REMOVAL_16:
  372                 DPRINTF(("%s: removal event\n", sc->sc_dev.dv_xname));
  373                 if (CARDSLOT_CARDTYPE(sc->sc_status) !=
  374                     CARDSLOT_STATUS_CARD_16) {
  375                         /* 16-bit card has not been inserted. */
  376                         break;
  377                 }
  378                 if ((sc->sc_16_softc != NULL) &&
  379                     (CARDSLOT_WORK(sc->sc_status) ==
  380                      CARDSLOT_STATUS_WORKING)) {
  381                         struct pcmcia_softc *psc = sc->sc_16_softc;
  382 
  383                         pcmcia_card_deactivate((struct device *)psc);
  384                         pcmcia_chip_socket_disable(psc->pct, psc->pch);
  385                         pcmcia_card_detach((struct device *)psc,
  386                             DETACH_FORCE);
  387                 }
  388                 CARDSLOT_SET_CARDTYPE(sc->sc_status,
  389                     CARDSLOT_STATUS_CARD_NONE);
  390                 CARDSLOT_SET_WORK(sc->sc_status,
  391                     CARDSLOT_STATUS_NOTWORK);
  392                 break;
  393 
  394         default:
  395                 panic("cardslot_event_thread: unknown event %d", ev);
  396         }
  397 }

Cache object: b0c0a99a94b15f5c0fa72ca7d8e187c8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.