LCOV - code coverage report
Current view: top level - dev/pcmcia - pcmcia.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 370 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 19 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13