root/dev/pcmcia/pcmcia.c

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

DEFINITIONS

This source file includes following definitions.
  1. pcmcia_ccr_read
  2. pcmcia_ccr_write
  3. pcmcia_match
  4. pcmcia_attach
  5. pcmcia_power
  6. pcmcia_card_attach
  7. pcmcia_card_detach
  8. pcmcia_card_deactivate
  9. pcmcia_submatch
  10. pcmcia_print
  11. pcmcia_card_gettype
  12. pcmcia_function_init
  13. pcmcia_socket_enable
  14. pcmcia_socket_disable
  15. pcmcia_function_enable
  16. pcmcia_function_disable
  17. pcmcia_io_map
  18. pcmcia_intr_establish
  19. pcmcia_intr_disestablish
  20. pcmcia_intr_string
  21. pcmcia_card_intr

    1 /*      $OpenBSD: pcmcia.c,v 1.37 2006/04/16 20:43:12 miod Exp $        */
    2 /*      $NetBSD: pcmcia.c,v 1.9 1998/08/13 02:10:55 eeh Exp $   */
    3 
    4 /*
    5  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  * 3. All advertising materials mentioning features or use of this software
   16  *    must display the following acknowledgement:
   17  *      This product includes software developed by Marc Horowitz.
   18  * 4. The name of the author may not be used to endorse or promote products
   19  *    derived from this software without specific prior written permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   31  */
   32 
   33 #include <sys/types.h>
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/device.h>
   37 #include <sys/malloc.h>
   38 
   39 #include <dev/pcmcia/pcmciareg.h>
   40 #include <dev/pcmcia/pcmciachip.h>
   41 #include <dev/pcmcia/pcmciavar.h>
   42 
   43 #ifdef PCMCIADEBUG
   44 #define DPRINTF(arg) printf arg
   45 #else
   46 #define DPRINTF(arg)
   47 #endif
   48 
   49 #ifdef PCMCIAVERBOSE
   50 int     pcmcia_verbose = 1;
   51 #else
   52 int     pcmcia_verbose = 0;
   53 #endif
   54 
   55 int     pcmcia_match(struct device *, void *, void *);
   56 int     pcmcia_submatch(struct device *, void *, void *);
   57 void    pcmcia_attach(struct device *, struct device *, void *);
   58 int     pcmcia_print(void *, const char *);
   59 void    pcmcia_card_detach_notify(struct device *, void *);
   60 void    pcmcia_power(int why, void *arg);
   61 
   62 static inline void pcmcia_socket_enable(pcmcia_chipset_tag_t,
   63                                              pcmcia_chipset_handle_t *);
   64 static inline void pcmcia_socket_disable(pcmcia_chipset_tag_t,
   65                                               pcmcia_chipset_handle_t *);
   66 
   67 int pcmcia_card_intr(void *);
   68 
   69 struct cfdriver pcmcia_cd = {
   70         NULL, "pcmcia", DV_DULL
   71 };
   72 
   73 struct cfattach pcmcia_ca = {
   74         sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach
   75 };
   76 
   77 int
   78 pcmcia_ccr_read(pf, ccr)
   79         struct pcmcia_function *pf;
   80         int ccr;
   81 {
   82 
   83         return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
   84             pf->pf_ccr_offset + ccr));
   85 }
   86 
   87 void
   88 pcmcia_ccr_write(pf, ccr, val)
   89         struct pcmcia_function *pf;
   90         int ccr;
   91         int val;
   92 {
   93 
   94         if ((pf->ccr_mask) & (1 << (ccr / 2))) {
   95                 bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
   96                     pf->pf_ccr_offset + ccr, val);
   97         }
   98 }
   99 
  100 int
  101 pcmcia_match(parent, match, aux)
  102         struct device *parent;
  103         void *match, *aux;
  104 {
  105         struct cfdata *cf = match;
  106         struct pcmciabus_attach_args *paa = aux;
  107 
  108         if (strcmp(paa->paa_busname, cf->cf_driver->cd_name))
  109                 return 0;
  110 
  111         /* If the autoconfiguration got this far, there's a socket here. */
  112         return (1);
  113 }
  114 
  115 void
  116 pcmcia_attach(parent, self, aux)
  117         struct device *parent, *self;
  118         void *aux;
  119 {
  120         struct pcmciabus_attach_args *paa = aux;
  121         struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
  122 
  123         printf("\n");
  124 
  125         sc->pct = paa->pct;
  126         sc->pch = paa->pch;
  127         sc->iobase = paa->iobase;
  128         sc->iosize = paa->iosize;
  129 
  130         sc->ih = NULL;
  131         powerhook_establish(pcmcia_power, sc);
  132 }
  133 
  134 void
  135 pcmcia_power(why, arg)
  136         int why;
  137         void *arg;
  138 {
  139         struct pcmcia_softc *sc = (struct pcmcia_softc *) arg;
  140         struct pcmcia_function *pf;
  141         struct device *d;
  142         int act = DVACT_ACTIVATE;
  143 
  144         if (why != PWR_RESUME)
  145                 act = DVACT_DEACTIVATE;
  146 
  147         for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  148              pf = SIMPLEQ_NEXT(pf, pf_list)) {
  149                 if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
  150                         continue;
  151                 d = pf->child;
  152                 if (d == NULL)
  153                         continue;
  154                 if (act == DVACT_ACTIVATE)
  155                         config_activate(pf->child);
  156                 else
  157                         config_deactivate(pf->child);
  158         }
  159 }
  160 
  161 int
  162 pcmcia_card_attach(dev)
  163         struct device *dev;
  164 {
  165         struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
  166         struct pcmcia_function *pf;
  167         struct pcmcia_attach_args paa;
  168         int attached;
  169 
  170         /*
  171          * this is here so that when socket_enable calls gettype, trt happens
  172          */
  173         SIMPLEQ_FIRST(&sc->card.pf_head) = NULL;
  174 
  175         pcmcia_chip_socket_enable(sc->pct, sc->pch);
  176 
  177         pcmcia_read_cis(sc);
  178 
  179         pcmcia_chip_socket_disable(sc->pct, sc->pch);
  180 
  181         pcmcia_check_cis_quirks(sc);
  182 
  183         /*
  184          * Bail now if there was an error in the CIS.
  185          */
  186 
  187         if (sc->card.error)
  188                 return (1);
  189 
  190 #if 0
  191         if (SIMPLEQ_EMPTY(&sc->card.pf_head))
  192                 return (1);
  193 #endif
  194 
  195         if (pcmcia_verbose)
  196                 pcmcia_print_cis(sc);
  197 
  198         /*
  199          * If there was no function, this might be CIS-less card we still
  200          * want to probe.  Fixup a function element for it.
  201          */
  202         if (SIMPLEQ_FIRST(&sc->card.pf_head) == NULL) {
  203                 pf = malloc(sizeof *pf, M_DEVBUF, M_NOWAIT);
  204                 if (pf == NULL)
  205                         panic("pcmcia_card_attach");
  206                 bzero(pf, sizeof *pf);
  207                 pf->number = 0;
  208                 pf->pf_flags = PFF_FAKE;
  209                 pf->last_config_index = -1;
  210                 SIMPLEQ_INIT(&pf->cfe_head);
  211                 SIMPLEQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list);
  212         }
  213 
  214         attached = 0;
  215 
  216         for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  217             pf = SIMPLEQ_NEXT(pf, pf_list)) {
  218                 pf->sc = sc;
  219                 pf->child = NULL;
  220                 pf->cfe = NULL;
  221                 pf->ih_fct = NULL;
  222                 pf->ih_arg = NULL;
  223         }
  224 
  225         for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  226             pf = SIMPLEQ_NEXT(pf, pf_list)) {
  227                 paa.manufacturer = sc->card.manufacturer;
  228                 paa.product = sc->card.product;
  229                 paa.card = &sc->card;
  230                 paa.pf = pf;
  231 
  232                 pf->child = config_found_sm(&sc->dev, &paa, pcmcia_print,
  233                     pcmcia_submatch);
  234                 if (pf->child) {
  235                         attached++;
  236 
  237                         if ((pf->pf_flags & PFF_FAKE) == 0)
  238                                 DPRINTF(("%s: function %d CCR at %d offset %lx"
  239                                         ": %x %x %x %x, %x %x %x %x, %x\n",
  240                                         sc->dev.dv_xname, pf->number,
  241                                         pf->pf_ccr_window, pf->pf_ccr_offset,
  242                                         pcmcia_ccr_read(pf, 0x00),
  243                                         pcmcia_ccr_read(pf, 0x02),
  244                                         pcmcia_ccr_read(pf, 0x04),
  245                                         pcmcia_ccr_read(pf, 0x06),
  246                                         pcmcia_ccr_read(pf, 0x0A),
  247                                         pcmcia_ccr_read(pf, 0x0C),
  248                                         pcmcia_ccr_read(pf, 0x0E),
  249                                         pcmcia_ccr_read(pf, 0x10),
  250                                         pcmcia_ccr_read(pf, 0x12)));
  251                 }
  252         }
  253         return (attached ? 0 : 1);
  254 }
  255 
  256 void
  257 pcmcia_card_detach(dev, flags)
  258         struct device *dev;
  259         int flags;              /* DETACH_* flags */
  260 {
  261         struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
  262         struct pcmcia_function *pf;
  263         int error;
  264 
  265         /*
  266          * We are running on either the PCMCIA socket's event thread
  267          * or in user context detaching a device by user request.
  268          */
  269         for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  270              pf = SIMPLEQ_NEXT(pf, pf_list)) {
  271                 if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
  272                         continue;
  273                 if (pf->child == NULL)
  274                         continue;
  275                 DPRINTF(("%s: detaching %s (function %d)\n",
  276                     sc->dev.dv_xname, pf->child->dv_xname, pf->number));
  277                 if ((error = config_detach(pf->child, flags)) != 0) {
  278                         printf("%s: error %d detaching %s (function %d)\n",
  279                             sc->dev.dv_xname, error, pf->child->dv_xname,
  280                             pf->number);
  281                 } else
  282                         pf->child = NULL;
  283         }
  284 }
  285 
  286 void
  287 pcmcia_card_deactivate(dev)
  288         struct device *dev;
  289 {
  290         struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
  291         struct pcmcia_function *pf;
  292 
  293         /*
  294          * We're in the chip's card removal interrupt handler.
  295          * Deactivate the child driver.  The PCMCIA socket's
  296          * event thread will run later to finish the detach.
  297          */
  298         for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  299              pf = SIMPLEQ_NEXT(pf, pf_list)) {
  300                 if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
  301                         continue;
  302                 if (pf->child == NULL)
  303                         continue;
  304                 DPRINTF(("%s: deactivating %s (function %d)\n",
  305                     sc->dev.dv_xname, pf->child->dv_xname, pf->number));
  306                 config_deactivate(pf->child);
  307         }
  308 }
  309 
  310 int
  311 pcmcia_submatch(parent, match, aux)
  312         struct device *parent;
  313         void *match, *aux;
  314 {
  315         struct cfdata *cf = match;
  316         struct pcmcia_attach_args *paa = aux;
  317 
  318         if (cf->cf_loc[0 /* PCMCIACF_FUNCTION */] !=
  319             -1 /* PCMCIACF_FUNCTION_DEFAULT */ &&
  320             cf->cf_loc[0 /* PCMCIACF_FUNCTION */] != paa->pf->number)
  321                 return (0);
  322 
  323         return ((*cf->cf_attach->ca_match)(parent, cf, aux));
  324 }
  325 
  326 int
  327 pcmcia_print(arg, pnp)
  328         void *arg;
  329         const char *pnp;
  330 {
  331         struct pcmcia_attach_args *pa = arg;
  332         struct pcmcia_softc *sc = pa->pf->sc;
  333         struct pcmcia_card *card = &sc->card;
  334         int i;
  335 
  336         if (pnp) {
  337                 for (i = 0; i < 4 && card->cis1_info[i]; i++)
  338                         printf("%s%s", i ? ", " : "\"", card->cis1_info[i]);
  339                 if (i != 0)
  340                         printf("\"");
  341 
  342                 if (card->manufacturer != PCMCIA_VENDOR_INVALID &&
  343                     card->product != PCMCIA_PRODUCT_INVALID) {
  344                         if (i != 0)
  345                                 printf(" ");
  346                         printf("(");
  347                         if (card->manufacturer != PCMCIA_VENDOR_INVALID)
  348                                 printf("manufacturer 0x%x%s",
  349                                     card->manufacturer,
  350                                     card->product == PCMCIA_PRODUCT_INVALID ?
  351                                     "" : ", ");
  352                         if (card->product != PCMCIA_PRODUCT_INVALID)
  353                                 printf("product 0x%x",
  354                                     card->product);
  355                         printf(")");
  356                 }
  357                 if (i != 0)
  358                         printf(" ");
  359                 printf("at %s", pnp);
  360         }
  361         printf(" function %d", pa->pf->number);
  362 
  363         if (!pnp) {
  364                 for (i = 0; i < 3 && card->cis1_info[i]; i++)
  365                         printf("%s%s", i ? ", " : " \"", card->cis1_info[i]);
  366                 if (i != 0)
  367                         printf("\"");
  368         }
  369 
  370         return (UNCONF);
  371 }
  372 
  373 int
  374 pcmcia_card_gettype(dev)
  375         struct device  *dev;
  376 {
  377         struct pcmcia_softc *sc = (struct pcmcia_softc *)dev;
  378         struct pcmcia_function *pf;
  379 
  380         /*
  381          * Set the iftype to memory if this card has no functions (not yet
  382          * probed), or only one function, and that is not initialized yet or
  383          * that is memory.
  384          */
  385         pf = SIMPLEQ_FIRST(&sc->card.pf_head);
  386         if (pf == NULL || (SIMPLEQ_NEXT(pf, pf_list) == NULL &&
  387             ((pf->pf_flags & PFF_FAKE) ||
  388             pf->cfe == NULL || pf->cfe->iftype == PCMCIA_IFTYPE_MEMORY)))
  389                 return (PCMCIA_IFTYPE_MEMORY);
  390         else
  391                 return (PCMCIA_IFTYPE_IO);
  392 }
  393 
  394 /*
  395  * Initialize a PCMCIA function.  May be called as long as the function is
  396  * disabled.
  397  */
  398 void
  399 pcmcia_function_init(pf, cfe)
  400         struct pcmcia_function *pf;
  401         struct pcmcia_config_entry *cfe;
  402 {
  403         if (pf->pf_flags & PFF_ENABLED)
  404                 panic("pcmcia_function_init: function is enabled");
  405 
  406         /* Remember which configuration entry we are using. */
  407         pf->cfe = cfe;
  408 }
  409 
  410 static inline void pcmcia_socket_enable(pct, pch)
  411      pcmcia_chipset_tag_t pct;
  412      pcmcia_chipset_handle_t *pch;
  413 {
  414         pcmcia_chip_socket_enable(pct, pch);
  415 }
  416 
  417 static inline void pcmcia_socket_disable(pct, pch)
  418      pcmcia_chipset_tag_t pct;
  419      pcmcia_chipset_handle_t *pch;
  420 {
  421         pcmcia_chip_socket_disable(pct, pch);
  422 }
  423 
  424 /* Enable a PCMCIA function */
  425 int
  426 pcmcia_function_enable(pf)
  427         struct pcmcia_function *pf;
  428 {
  429         struct pcmcia_function *tmp;
  430         int reg;
  431 
  432         if (pf->cfe == NULL)
  433                 panic("pcmcia_function_enable: function not initialized");
  434 
  435         /*
  436          * Increase the reference count on the socket, enabling power, if
  437          * necessary.
  438          */
  439         if (pf->sc->sc_enabled_count++ == 0)
  440                 pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
  441         DPRINTF(("%s: ++enabled_count = %d\n", pf->sc->dev.dv_xname,
  442                  pf->sc->sc_enabled_count));
  443 
  444         if (pf->pf_flags & PFF_ENABLED) {
  445                 /*
  446                  * Don't do anything if we're already enabled.
  447                  */
  448                 DPRINTF(("%s: pcmcia_function_enable on enabled func\n"));
  449                 return (0);
  450         }
  451 
  452         /* If there was no CIS don't mess with CCR */
  453         if (pf->pf_flags & PFF_FAKE)
  454                 goto done;
  455 
  456         /*
  457          * It's possible for different functions' CCRs to be in the same
  458          * underlying page.  Check for that.
  459          */
  460         SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
  461                 if ((tmp->pf_flags & PFF_ENABLED) &&
  462                     (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
  463                     ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
  464                      (tmp->ccr_base - tmp->pf_ccr_offset +
  465                       tmp->pf_ccr_realsize))) {
  466                         pf->pf_ccrt = tmp->pf_ccrt;
  467                         pf->pf_ccrh = tmp->pf_ccrh;
  468                         pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
  469 
  470                         /*
  471                          * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
  472                          * tmp->ccr_base) + pf->ccr_base;
  473                          */
  474                         pf->pf_ccr_offset =
  475                             (tmp->pf_ccr_offset + pf->ccr_base) -
  476                             tmp->ccr_base;
  477                         pf->pf_ccr_window = tmp->pf_ccr_window;
  478                         break;
  479                 }
  480         }
  481 
  482         if (tmp == NULL) {
  483                 if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
  484                         goto bad;
  485 
  486                 if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
  487                     PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
  488                     &pf->pf_ccr_window)) {
  489                         pcmcia_mem_free(pf, &pf->pf_pcmh);
  490                         goto bad;
  491                 }
  492         }
  493 
  494         reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
  495         reg |= PCMCIA_CCR_OPTION_LEVIREQ;
  496         if (pcmcia_mfc(pf->sc)) {
  497                 reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
  498                 if (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))
  499                         reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
  500                 if (pf->ih_fct)
  501                         reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
  502 
  503         }
  504 
  505         pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
  506 
  507         reg = 0;
  508 
  509         if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
  510                 reg |= PCMCIA_CCR_STATUS_IOIS8;
  511         if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
  512                 reg |= PCMCIA_CCR_STATUS_AUDIO;
  513         pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
  514 
  515         pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
  516 
  517         if (pcmcia_mfc(pf->sc)) {
  518                 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
  519                                  (pf->pf_mfc_iobase >>  0) & 0xff);
  520                 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
  521                                  (pf->pf_mfc_iobase >>  8) & 0xff);
  522                 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
  523                                  (pf->pf_mfc_iobase >> 16) & 0xff);
  524                 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
  525                                  (pf->pf_mfc_iobase >> 24) & 0xff);
  526                 pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
  527                                  pf->pf_mfc_iomax - pf->pf_mfc_iobase);
  528         }
  529 
  530 #ifdef PCMCIADEBUG
  531         SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
  532                 printf("%s: function %d CCR at %d offset %lx: "
  533                        "%x %x %x %x, %x %x %x %x, %x\n",
  534                        tmp->sc->dev.dv_xname, tmp->number,
  535                        tmp->pf_ccr_window, tmp->pf_ccr_offset,
  536                        pcmcia_ccr_read(tmp, 0x00),
  537                        pcmcia_ccr_read(tmp, 0x02),
  538                        pcmcia_ccr_read(tmp, 0x04),
  539                        pcmcia_ccr_read(tmp, 0x06),
  540 
  541                        pcmcia_ccr_read(tmp, 0x0A),
  542                        pcmcia_ccr_read(tmp, 0x0C),
  543                        pcmcia_ccr_read(tmp, 0x0E),
  544                        pcmcia_ccr_read(tmp, 0x10),
  545 
  546                        pcmcia_ccr_read(tmp, 0x12));
  547         }
  548 #endif
  549 
  550  done:
  551         pf->pf_flags |= PFF_ENABLED;
  552         delay(1000);
  553         return (0);
  554 
  555  bad:
  556         /*
  557          * Decrement the reference count, and power down the socket, if
  558          * necessary.
  559          */
  560         if (--pf->sc->sc_enabled_count == 0)
  561                 pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
  562         DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
  563                  pf->sc->sc_enabled_count));
  564 
  565         return (1);
  566 }
  567 
  568 /* Disable PCMCIA function. */
  569 void
  570 pcmcia_function_disable(pf)
  571         struct pcmcia_function *pf;
  572 {
  573         struct pcmcia_function *tmp;
  574 
  575         if (pf->cfe == NULL)
  576                 panic("pcmcia_function_enable: function not initialized");
  577 
  578         if ((pf->pf_flags & PFF_ENABLED) == 0) {
  579                 /*
  580                  * Don't do anything if we're already disabled.
  581                  */
  582                 return;
  583         }
  584 
  585         /* If there was no CIS don't mess with CCR */
  586         if (pf->pf_flags & PFF_FAKE) {
  587                 pf->pf_flags &= ~PFF_ENABLED;
  588                 goto done;
  589         }
  590 
  591         /*
  592          * it's possible for different functions' CCRs to be in the same
  593          * underlying page.  Check for that.  Note we mark us as disabled
  594          * first to avoid matching ourself.
  595          */
  596         pf->pf_flags &= ~PFF_ENABLED;
  597         SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
  598                 if ((tmp->pf_flags & PFF_ENABLED) &&
  599                     (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
  600                     ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
  601                 (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
  602                         break;
  603         }
  604 
  605         /* Not used by anyone else; unmap the CCR. */
  606         if (tmp == NULL) {
  607                 pcmcia_mem_unmap(pf, pf->pf_ccr_window);
  608                 pcmcia_mem_free(pf, &pf->pf_pcmh);
  609         }
  610 
  611  done:
  612         /*
  613          * Decrement the reference count, and power down the socket, if
  614          * necessary.
  615          */
  616         if (--pf->sc->sc_enabled_count == 0)
  617                 pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
  618         DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
  619                  pf->sc->sc_enabled_count));
  620 }
  621 
  622 int
  623 pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
  624         struct pcmcia_function *pf;
  625         int width;
  626         bus_addr_t offset;
  627         bus_size_t size;
  628         struct pcmcia_io_handle *pcihp;
  629         int *windowp;
  630 {
  631         int reg;
  632 
  633         if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
  634             width, offset, size, pcihp, windowp))
  635                 return (1);
  636 
  637         /*
  638          * XXX In the multifunction multi-iospace-per-function case, this
  639          * needs to cooperate with io_alloc to make sure that the spaces
  640          * don't overlap, and that the ccr's are set correctly.
  641          */
  642 
  643         if (pcmcia_mfc(pf->sc) &&
  644             (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))) {
  645                 bus_addr_t iobase = pcihp->addr;
  646                 bus_addr_t iomax = pcihp->addr + pcihp->size - 1;
  647 
  648                 if (pf->pf_mfc_iomax == 0) {
  649                         pf->pf_mfc_iobase = iobase;
  650                         pf->pf_mfc_iomax = iomax;
  651                 } else {
  652                         if (iobase < pf->pf_mfc_iobase)
  653                                 pf->pf_mfc_iobase = iobase;
  654                         if (iomax > pf->pf_mfc_iomax)
  655                                 pf->pf_mfc_iomax = iomax;
  656                 }
  657 
  658                 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
  659                                  (pf->pf_mfc_iobase >>  0) & 0xff);
  660                 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
  661                                  (pf->pf_mfc_iobase >>  8) & 0xff);
  662                 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
  663                                  (pf->pf_mfc_iobase >> 16) & 0xff);
  664                 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
  665                                  (pf->pf_mfc_iobase >> 24) & 0xff);
  666                 pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
  667                                  pf->pf_mfc_iomax - pf->pf_mfc_iobase);
  668 
  669                 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
  670                 reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
  671                 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
  672         }
  673         return (0);
  674 }
  675 
  676 void *
  677 pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg, xname)
  678         struct pcmcia_function *pf;
  679         int ipl;
  680         int (*ih_fct)(void *);
  681         void *ih_arg;
  682         char *xname;
  683 {
  684         void *ret;
  685         int s, ihcnt, hiipl, reg;
  686         struct pcmcia_function *pf2;
  687 
  688         /* Behave differently if this is a multifunction card. */
  689         if (pcmcia_mfc(pf->sc)) {
  690                 /*
  691                  * Mask all the ipl's which are already used by this card,
  692                  * and find the highest ipl number (lowest priority).
  693                  */
  694                 ihcnt = 0;
  695                 SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
  696                         if (pf2->ih_fct) {
  697                                 DPRINTF(("%s: function %d has ih_fct %p\n",
  698                                     pf->sc->dev.dv_xname, pf2->number,
  699                                     pf2->ih_fct));
  700 
  701                                 if (ihcnt == 0)
  702                                         hiipl = pf2->ih_ipl;
  703                                 else if (pf2->ih_ipl > hiipl)
  704                                         hiipl = pf2->ih_ipl;
  705 
  706                                 ihcnt++;
  707                         }
  708                 }
  709 
  710                 /*
  711                  * Establish the real interrupt, changing the ipl if
  712                  * necessary.
  713                  */
  714                 if (ihcnt == 0) {
  715 #ifdef DIAGNOSTIC
  716                         if (pf->sc->ih != NULL)
  717                                 panic("card has intr handler, "
  718                                     "but no function does");
  719 #endif
  720                         s = spltty();
  721 
  722                         /* Set up the handler for the new function. */
  723                         pf->ih_fct = ih_fct;
  724                         pf->ih_arg = ih_arg;
  725                         pf->ih_ipl = ipl;
  726 
  727                         pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
  728                             pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
  729                             xname);
  730                         splx(s);
  731                 } else if (ipl > hiipl) {
  732 #ifdef DIAGNOSTIC
  733                         if (pf->sc->ih == NULL)
  734                                 panic("functions have ih, "
  735                                     "but the card does not");
  736 #endif
  737 
  738                         s = spltty();
  739 
  740                         pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
  741                             pf->sc->ih);
  742 
  743                         /* set up the handler for the new function */
  744                         pf->ih_fct = ih_fct;
  745                         pf->ih_arg = ih_arg;
  746                         pf->ih_ipl = ipl;
  747 
  748                         pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
  749                             pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
  750                             xname);
  751 
  752                         splx(s);
  753                 } else {
  754                         s = spltty();
  755 
  756                         /* Set up the handler for the new function. */
  757                         pf->ih_fct = ih_fct;
  758                         pf->ih_arg = ih_arg;
  759                         pf->ih_ipl = ipl;
  760 
  761                         splx(s);
  762                 }
  763 
  764                 ret = pf->sc->ih;
  765 
  766                 if (ret != NULL) {
  767                         reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
  768                         reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
  769                         pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
  770 
  771                         reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
  772                         reg |= PCMCIA_CCR_STATUS_INTRACK;
  773                         pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
  774                 }
  775         } else
  776                 ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
  777                     pf, ipl, ih_fct, ih_arg, xname);
  778 
  779         return (ret);
  780 }
  781 
  782 void
  783 pcmcia_intr_disestablish(pf, ih)
  784         struct pcmcia_function *pf;
  785         void *ih;
  786 {
  787         int s, reg, ihcnt, hiipl;
  788         struct pcmcia_function *pf2;
  789 
  790         /* Behave differently if this is a multifunction card.  */
  791         if (pcmcia_mfc(pf->sc)) {
  792                 /*
  793                  * Mask all the ipl's which are already used by this card,
  794                  * and find the highest ipl number (lowest priority).  Skip
  795                  * the current function.
  796                  */
  797                 ihcnt = 0;
  798                 SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
  799                         if (pf2 == pf)
  800                                 continue;
  801 
  802                         if (pf2->ih_fct) {
  803                                 if (ihcnt == 0)
  804                                         hiipl = pf2->ih_ipl;
  805                                 else if (pf2->ih_ipl > hiipl)
  806                                         hiipl = pf2->ih_ipl;
  807                                 ihcnt++;
  808                         }
  809                 }
  810 
  811                 /*
  812                  * If the ih being removed is lower priority than the lowest
  813                  * priority remaining interrupt, up the priority.
  814                  */
  815 
  816                 /*
  817                  * ihcnt is the number of interrupt handlers *not* including
  818                  * the one about to be removed.
  819                  */
  820                 if (ihcnt == 0) {
  821 #ifdef DIAGNOSTIC
  822                         if (pf->sc->ih == NULL)
  823                                 panic("disestablishing last function, but card has no ih");
  824 #endif
  825                         pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
  826                             pf->sc->ih);
  827 
  828                         reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
  829                         reg &= ~PCMCIA_CCR_OPTION_IREQ_ENABLE;
  830                         pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
  831 
  832                         pf->ih_fct = NULL;
  833                         pf->ih_arg = NULL;
  834 
  835                         pf->sc->ih = NULL;
  836                 } else if (pf->ih_ipl > hiipl) {
  837 #ifdef DIAGNOSTIC
  838                         if (pf->sc->ih == NULL)
  839                                 panic("changing ih ipl, but card has no ih");
  840 #endif
  841                         s = spltty();
  842 
  843                         pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
  844                             pf->sc->ih);
  845                         pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
  846                             pf->sc->pch, pf, hiipl, pcmcia_card_intr, pf->sc,
  847                             NULL);
  848 
  849                         /* Null out the handler for this function. */
  850                         pf->ih_fct = NULL;
  851                         pf->ih_arg = NULL;
  852 
  853                         splx(s);
  854                 } else {
  855                         s = spltty();
  856 
  857                         pf->ih_fct = NULL;
  858                         pf->ih_arg = NULL;
  859 
  860                         splx(s);
  861                 }
  862         } else
  863                 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
  864 }
  865 
  866 const char *
  867 pcmcia_intr_string(pf, ih)
  868         struct pcmcia_function *pf;
  869         void *ih;
  870 {
  871         return pcmcia_chip_intr_string(pf->sc->pct, pf->sc->pch, ih);
  872 }
  873 
  874 int
  875 pcmcia_card_intr(arg)
  876         void *arg;
  877 {
  878         struct pcmcia_softc *sc = arg;
  879         struct pcmcia_function *pf;
  880         int reg, ret, ret2;
  881 
  882         ret = 0;
  883 
  884         for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
  885             pf = SIMPLEQ_NEXT(pf, pf_list)) {
  886 #ifdef PCMCIADEBUG
  887                 printf("%s: intr flags=%x fct=%d cor=%02x csr=%02x pin=%02x",
  888                        sc->dev.dv_xname, pf->pf_flags, pf->number,
  889                        pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION),
  890                        pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS),
  891                        pcmcia_ccr_read(pf, PCMCIA_CCR_PIN));
  892 #endif
  893                 if (pf->ih_fct != NULL &&
  894                     (pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) {
  895                         reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
  896                         if (reg & PCMCIA_CCR_STATUS_INTR) {
  897                                 ret2 = (*pf->ih_fct)(pf->ih_arg);
  898                                 if (ret2 != 0 && ret == 0)
  899                                         ret = ret2;
  900                                 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
  901 #ifdef PCMCIADEBUG
  902                                 printf("; csr %02x->%02x",
  903                                     reg, reg & ~PCMCIA_CCR_STATUS_INTR);
  904 #endif
  905                                 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
  906                                     reg & ~PCMCIA_CCR_STATUS_INTR);
  907                         }
  908                 }
  909 #ifdef PCMCIADEBUG
  910                 printf("\n");
  911 #endif
  912         }
  913 
  914         return (ret);
  915 }

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