Home | History | Annotate | Line # | Download | only in pcmcia
pcmcia.c revision 1.1.2.9
      1  1.1.2.1     marc #define PCMCIADEBUG
      2  1.1.2.1     marc 
      3  1.1.2.1     marc #include <sys/types.h>
      4  1.1.2.1     marc #include <sys/param.h>
      5  1.1.2.1     marc #include <sys/systm.h>
      6  1.1.2.1     marc #include <sys/device.h>
      7  1.1.2.1     marc 
      8  1.1.2.1     marc /* XXX only needed for intr debugging */
      9  1.1.2.1     marc #include <vm/vm.h>
     10  1.1.2.1     marc 
     11  1.1.2.1     marc #include <dev/pcmcia/pcmciareg.h>
     12  1.1.2.1     marc #include <dev/pcmcia/pcmciachip.h>
     13  1.1.2.1     marc #include <dev/pcmcia/pcmciavar.h>
     14  1.1.2.1     marc 
     15  1.1.2.1     marc #ifdef PCMCIADEBUG
     16  1.1.2.3  thorpej int	pcmcia_debug = 0;
     17  1.1.2.3  thorpej #define DPRINTF(arg) if (pcmcia_debug) printf arg
     18  1.1.2.1     marc #else
     19  1.1.2.1     marc #define DPRINTF(arg)
     20  1.1.2.1     marc #endif
     21  1.1.2.1     marc 
     22  1.1.2.5  thorpej #ifdef PCMCIAVERBOSE
     23  1.1.2.5  thorpej int	pcmcia_verbose = 1;
     24  1.1.2.5  thorpej #else
     25  1.1.2.5  thorpej int	pcmcia_verbose = 0;
     26  1.1.2.5  thorpej #endif
     27  1.1.2.5  thorpej 
     28  1.1.2.1     marc #ifdef	__BROKEN_INDIRECT_CONFIG
     29  1.1.2.1     marc int pcmcia_match __P((struct device *, void *, void *));
     30  1.1.2.1     marc int pcmcia_submatch __P((struct device *, void *, void *));
     31  1.1.2.1     marc #else
     32  1.1.2.1     marc int pcmcia_match __P((struct device *, struct cfdata *, void *));
     33  1.1.2.1     marc int pcmcia_submatch __P((struct device *, struct cfdata *, void *));
     34  1.1.2.1     marc #endif
     35  1.1.2.1     marc void pcmcia_attach __P((struct device *, struct device *, void *));
     36  1.1.2.1     marc int pcmcia_print __P((void *, const char *));
     37  1.1.2.1     marc 
     38  1.1.2.1     marc int pcmcia_card_intr __P((void *));
     39  1.1.2.1     marc 
     40  1.1.2.1     marc struct cfdriver pcmcia_cd = {
     41  1.1.2.1     marc 	NULL, "pcmcia", DV_DULL
     42  1.1.2.1     marc };
     43  1.1.2.1     marc 
     44  1.1.2.1     marc struct cfattach pcmcia_ca = {
     45  1.1.2.1     marc 	sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach
     46  1.1.2.1     marc };
     47  1.1.2.1     marc 
     48  1.1.2.1     marc int
     49  1.1.2.1     marc pcmcia_ccr_read(pf, ccr)
     50  1.1.2.1     marc      struct pcmcia_function *pf;
     51  1.1.2.1     marc      int ccr;
     52  1.1.2.1     marc {
     53  1.1.2.5  thorpej     return(bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
     54  1.1.2.5  thorpej     			    pf->pf_ccr_offset + ccr));
     55  1.1.2.1     marc }
     56  1.1.2.1     marc 
     57  1.1.2.1     marc void
     58  1.1.2.1     marc pcmcia_ccr_write(pf, ccr, val)
     59  1.1.2.1     marc      struct pcmcia_function *pf;
     60  1.1.2.1     marc      int ccr;
     61  1.1.2.1     marc      int val;
     62  1.1.2.1     marc {
     63  1.1.2.5  thorpej     if ((pf->ccr_mask) & (1 << (ccr / 2))) {
     64  1.1.2.5  thorpej 	bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
     65  1.1.2.5  thorpej 			  pf->pf_ccr_offset + ccr, val);
     66  1.1.2.1     marc     }
     67  1.1.2.1     marc }
     68  1.1.2.1     marc 
     69  1.1.2.1     marc int
     70  1.1.2.1     marc pcmcia_match(parent, match, aux)
     71  1.1.2.1     marc      struct device *parent;
     72  1.1.2.1     marc #ifdef	__BROKEN_INDIRECT_CONFIG
     73  1.1.2.1     marc      void *match;
     74  1.1.2.1     marc #else
     75  1.1.2.1     marc      struct cfdata *match;
     76  1.1.2.1     marc #endif
     77  1.1.2.1     marc      void *aux;
     78  1.1.2.1     marc {
     79  1.1.2.1     marc     /* if the autoconfiguration got this far, there's a socket here */
     80  1.1.2.1     marc 
     81  1.1.2.1     marc     return(1);
     82  1.1.2.1     marc }
     83  1.1.2.1     marc 
     84  1.1.2.1     marc void
     85  1.1.2.1     marc pcmcia_attach(parent, self, aux)
     86  1.1.2.1     marc 	struct device *parent, *self;
     87  1.1.2.1     marc 	void *aux;
     88  1.1.2.1     marc {
     89  1.1.2.1     marc     struct pcmciabus_attach_args *paa = (struct pcmciabus_attach_args *) aux;
     90  1.1.2.1     marc     struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
     91  1.1.2.1     marc 
     92  1.1.2.1     marc     printf("\n");
     93  1.1.2.1     marc 
     94  1.1.2.1     marc     sc->pct = paa->pct;
     95  1.1.2.1     marc     sc->pch = paa->pch;
     96  1.1.2.1     marc 
     97  1.1.2.1     marc     sc->ih = NULL;
     98  1.1.2.1     marc }
     99  1.1.2.1     marc 
    100  1.1.2.1     marc int
    101  1.1.2.8     marc pcmcia_card_attach(dev)
    102  1.1.2.1     marc      struct device *dev;
    103  1.1.2.1     marc {
    104  1.1.2.1     marc     struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
    105  1.1.2.1     marc     struct pcmcia_function *pf;
    106  1.1.2.1     marc     struct pcmcia_attach_args paa;
    107  1.1.2.1     marc     int attached;
    108  1.1.2.1     marc 
    109  1.1.2.8     marc     /* this is here so that when socket_enable calls gettype, trt happens */
    110  1.1.2.8     marc     sc->card.pf_head.sqh_first = NULL;
    111  1.1.2.8     marc 
    112  1.1.2.8     marc     pcmcia_chip_socket_enable(sc->pct, sc->pch);
    113  1.1.2.8     marc 
    114  1.1.2.1     marc     pcmcia_read_cis(sc);
    115  1.1.2.1     marc 
    116  1.1.2.8     marc     pcmcia_chip_socket_disable(sc->pct, sc->pch);
    117  1.1.2.8     marc 
    118  1.1.2.1     marc     /* bail now if the card has no functions, or if there was an error
    119  1.1.2.1     marc        in the cis. */
    120  1.1.2.1     marc 
    121  1.1.2.1     marc     if (sc->card.error)
    122  1.1.2.1     marc 	return(1);
    123  1.1.2.1     marc     if (!sc->card.pf_head.sqh_first)
    124  1.1.2.1     marc 	return(1);
    125  1.1.2.1     marc 
    126  1.1.2.5  thorpej     if (pcmcia_verbose)
    127  1.1.2.5  thorpej 	pcmcia_print_cis(sc);
    128  1.1.2.1     marc 
    129  1.1.2.1     marc     attached = 0;
    130  1.1.2.1     marc 
    131  1.1.2.1     marc     for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
    132  1.1.2.1     marc 	if (pf->cfe_head.sqh_first == NULL)
    133  1.1.2.1     marc 	    continue;
    134  1.1.2.1     marc 
    135  1.1.2.1     marc 	pf->sc = sc;
    136  1.1.2.1     marc 	pf->cfe = NULL;
    137  1.1.2.1     marc 	pf->ih_fct = NULL;
    138  1.1.2.1     marc 	pf->ih_arg = NULL;
    139  1.1.2.1     marc     }
    140  1.1.2.1     marc 
    141  1.1.2.1     marc     for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
    142  1.1.2.1     marc 	if (pf->cfe_head.sqh_first == NULL)
    143  1.1.2.1     marc 	    continue;
    144  1.1.2.1     marc 
    145  1.1.2.1     marc 	paa.manufacturer = sc->card.manufacturer;
    146  1.1.2.1     marc 	paa.product = sc->card.product;
    147  1.1.2.1     marc 	paa.card = &sc->card;
    148  1.1.2.1     marc 	paa.pf = pf;
    149  1.1.2.1     marc 
    150  1.1.2.1     marc 	if (config_found_sm(&sc->dev, &paa, pcmcia_print, pcmcia_submatch)) {
    151  1.1.2.1     marc 	    attached++;
    152  1.1.2.1     marc 
    153  1.1.2.1     marc 	    DPRINTF(("%s: function %d CCR at %d offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
    154  1.1.2.1     marc 		     sc->dev.dv_xname, pf->number,
    155  1.1.2.5  thorpej 		     pf->pf_ccr_window, pf->pf_ccr_offset,
    156  1.1.2.1     marc 		     pcmcia_ccr_read(pf, 0x00),
    157  1.1.2.1     marc 		     pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
    158  1.1.2.1     marc 		     pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
    159  1.1.2.1     marc 		     pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
    160  1.1.2.1     marc 		     pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
    161  1.1.2.1     marc 	}
    162  1.1.2.1     marc     }
    163  1.1.2.1     marc 
    164  1.1.2.1     marc     return(attached?0:1);
    165  1.1.2.1     marc }
    166  1.1.2.1     marc 
    167  1.1.2.1     marc void
    168  1.1.2.8     marc pcmcia_card_detach(dev)
    169  1.1.2.1     marc      struct device *dev;
    170  1.1.2.1     marc {
    171  1.1.2.1     marc /*    struct pcmcia_softc *sc = (struct pcmcia_softc *) dev; */
    172  1.1.2.1     marc     /* don't do anything yet */
    173  1.1.2.1     marc }
    174  1.1.2.1     marc 
    175  1.1.2.1     marc int
    176  1.1.2.1     marc #ifdef __BROKEN_INDIRECT_CONFIG
    177  1.1.2.1     marc pcmcia_submatch(parent, match, aux)
    178  1.1.2.1     marc #else
    179  1.1.2.1     marc pcmcia_submatch(parent, cf, aux)
    180  1.1.2.1     marc #endif
    181  1.1.2.1     marc      struct device *parent;
    182  1.1.2.1     marc #ifdef __BROKEN_INDIRECT_CONFIG
    183  1.1.2.1     marc      void *match;
    184  1.1.2.1     marc #else
    185  1.1.2.1     marc      struct cfdata *cf;
    186  1.1.2.1     marc #endif
    187  1.1.2.1     marc      void *aux;
    188  1.1.2.1     marc {
    189  1.1.2.1     marc #ifdef __BROKEN_INDIRECT_CONFIG
    190  1.1.2.1     marc     struct cfdata *cf = match;
    191  1.1.2.1     marc #endif
    192  1.1.2.1     marc 
    193  1.1.2.1     marc     struct pcmcia_attach_args *paa = (struct pcmcia_attach_args *) aux;
    194  1.1.2.1     marc 
    195  1.1.2.1     marc     if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != paa->pf->number)
    196  1.1.2.1     marc 	return(0);
    197  1.1.2.1     marc 
    198  1.1.2.1     marc     return ((*cf->cf_attach->ca_match)(parent, cf, aux));
    199  1.1.2.1     marc }
    200  1.1.2.1     marc 
    201  1.1.2.1     marc int
    202  1.1.2.1     marc pcmcia_print(arg, pnp)
    203  1.1.2.1     marc      void *arg;
    204  1.1.2.1     marc      const char *pnp;
    205  1.1.2.1     marc {
    206  1.1.2.5  thorpej     struct pcmcia_attach_args *pa = (struct pcmcia_attach_args *) arg;
    207  1.1.2.5  thorpej     struct pcmcia_softc *sc = pa->pf->sc;
    208  1.1.2.5  thorpej     struct pcmcia_card *card = &sc->card;
    209  1.1.2.5  thorpej     int i;
    210  1.1.2.5  thorpej 
    211  1.1.2.5  thorpej     if (pnp) {
    212  1.1.2.5  thorpej 	for (i = 0; i < 4; i++) {
    213  1.1.2.5  thorpej 	    if (!card->cis1_info[i])
    214  1.1.2.5  thorpej 		break;
    215  1.1.2.5  thorpej 	    if (i)
    216  1.1.2.5  thorpej 		printf(", ");
    217  1.1.2.5  thorpej 	    printf("%s", card->cis1_info[i]);
    218  1.1.2.5  thorpej 	}
    219  1.1.2.5  thorpej 	if (i)
    220  1.1.2.5  thorpej 		printf(" ");
    221  1.1.2.5  thorpej 	printf("(manufacturer 0x%x, product 0x%x)", card->manufacturer,
    222  1.1.2.5  thorpej 	       card->product);
    223  1.1.2.5  thorpej     }
    224  1.1.2.1     marc 
    225  1.1.2.5  thorpej     printf(" function %d", pa->pf->number);
    226  1.1.2.1     marc 
    227  1.1.2.1     marc     return(UNCONF);
    228  1.1.2.1     marc }
    229  1.1.2.1     marc 
    230  1.1.2.8     marc int pcmcia_card_gettype(dev)
    231  1.1.2.8     marc      struct device *dev;
    232  1.1.2.8     marc {
    233  1.1.2.8     marc     struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
    234  1.1.2.8     marc 
    235  1.1.2.8     marc     /* set the iftype to memory if this card has no functions (not yet
    236  1.1.2.8     marc        probed), or only one function, and that is memory. */
    237  1.1.2.8     marc     if (!sc->card.pf_head.sqh_first ||
    238  1.1.2.8     marc 	(sc->card.pf_head.sqh_first &&
    239  1.1.2.8     marc 	 !sc->card.pf_head.sqh_first->pf_list.sqe_next &&
    240  1.1.2.8     marc 	 (sc->card.pf_head.sqh_first->cfe_head.sqh_first->iftype ==
    241  1.1.2.8     marc 	  PCMCIA_IFTYPE_MEMORY)))
    242  1.1.2.8     marc 	return(PCMCIA_IFTYPE_MEMORY);
    243  1.1.2.8     marc     else
    244  1.1.2.8     marc 	return(PCMCIA_IFTYPE_IO);
    245  1.1.2.8     marc }
    246  1.1.2.8     marc 
    247  1.1.2.7  thorpej /* Initialize a PCMCIA function.  May be called as long as the function
    248  1.1.2.7  thorpej    is disabled. */
    249  1.1.2.7  thorpej void
    250  1.1.2.7  thorpej pcmcia_function_init(pf, cfe)
    251  1.1.2.1     marc      struct pcmcia_function *pf;
    252  1.1.2.1     marc      struct pcmcia_config_entry *cfe;
    253  1.1.2.1     marc {
    254  1.1.2.7  thorpej 
    255  1.1.2.7  thorpej      if (pf->pf_flags & PFF_ENABLED)
    256  1.1.2.7  thorpej 	panic("pcmcia_function_init: function is enabled");
    257  1.1.2.7  thorpej 
    258  1.1.2.7  thorpej      /* Remember which configuration entry we are using. */
    259  1.1.2.7  thorpej      pf->cfe = cfe;
    260  1.1.2.7  thorpej }
    261  1.1.2.7  thorpej 
    262  1.1.2.7  thorpej /* Enable a PCMCIA function */
    263  1.1.2.7  thorpej int
    264  1.1.2.7  thorpej pcmcia_function_enable(pf)
    265  1.1.2.7  thorpej      struct pcmcia_function *pf;
    266  1.1.2.7  thorpej {
    267  1.1.2.1     marc     struct pcmcia_function *tmp;
    268  1.1.2.1     marc     int reg;
    269  1.1.2.1     marc 
    270  1.1.2.7  thorpej     if (pf->cfe == NULL)
    271  1.1.2.7  thorpej 	panic("pcmcia_function_enable: function not initialized");
    272  1.1.2.9  thorpej     if (pf->pf_flags & PFF_ENABLED) {
    273  1.1.2.9  thorpej 	/*
    274  1.1.2.9  thorpej 	 * Don't do anything if we're already enabled.
    275  1.1.2.9  thorpej 	 */
    276  1.1.2.9  thorpej 	return (0);
    277  1.1.2.9  thorpej     }
    278  1.1.2.7  thorpej 
    279  1.1.2.7  thorpej     /* Increase the reference count on the socket, enabling power,
    280  1.1.2.7  thorpej        if necessary. */
    281  1.1.2.7  thorpej     if (pf->sc->sc_enabled_count++ == 0)
    282  1.1.2.7  thorpej 	pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
    283  1.1.2.1     marc 
    284  1.1.2.1     marc     /* it's possible for different functions' CCRs to be in the same
    285  1.1.2.1     marc        underlying page.  Check for that. */
    286  1.1.2.1     marc 
    287  1.1.2.1     marc     for (tmp = pf->sc->card.pf_head.sqh_first;
    288  1.1.2.1     marc 	 tmp;
    289  1.1.2.1     marc 	 tmp = tmp->pf_list.sqe_next) {
    290  1.1.2.7  thorpej 	if ((tmp->pf_flags & PFF_ENABLED) &&
    291  1.1.2.5  thorpej 	    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
    292  1.1.2.1     marc 	    ((pf->ccr_base+PCMCIA_CCR_SIZE) <=
    293  1.1.2.5  thorpej 	     (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize))) {
    294  1.1.2.5  thorpej 	    pf->pf_ccrt = tmp->pf_ccrt;
    295  1.1.2.5  thorpej 	    pf->pf_ccrh = tmp->pf_ccrh;
    296  1.1.2.5  thorpej 	    pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
    297  1.1.2.5  thorpej 
    298  1.1.2.5  thorpej 	    /* pf->pf_ccr_offset =
    299  1.1.2.5  thorpej 	       (tmp->pf_ccr_offset - tmp->ccr_base) + pf->ccr_base; */
    300  1.1.2.5  thorpej 	    pf->pf_ccr_offset =
    301  1.1.2.5  thorpej 	        (tmp->pf_ccr_offset + pf->ccr_base) - tmp->ccr_base;
    302  1.1.2.5  thorpej 	    pf->pf_ccr_window = tmp->pf_ccr_window;
    303  1.1.2.1     marc 	    break;
    304  1.1.2.1     marc 	}
    305  1.1.2.1     marc     }
    306  1.1.2.1     marc 
    307  1.1.2.1     marc     if (tmp == NULL) {
    308  1.1.2.5  thorpej 	if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
    309  1.1.2.7  thorpej 	    goto bad;
    310  1.1.2.1     marc 
    311  1.1.2.5  thorpej 	if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
    312  1.1.2.5  thorpej 			   PCMCIA_CCR_SIZE, &pf->pf_pcmh,
    313  1.1.2.7  thorpej 			   &pf->pf_ccr_offset, &pf->pf_ccr_window)) {
    314  1.1.2.7  thorpej 	    pcmcia_mem_free(pf, &pf->pf_pcmh);
    315  1.1.2.7  thorpej 	    goto bad;
    316  1.1.2.7  thorpej 	}
    317  1.1.2.1     marc     }
    318  1.1.2.1     marc 
    319  1.1.2.1     marc     DPRINTF(("%s: function %d CCR at %d offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
    320  1.1.2.1     marc 	     pf->sc->dev.dv_xname, pf->number,
    321  1.1.2.5  thorpej 	     pf->pf_ccr_window, pf->pf_ccr_offset,
    322  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x00),
    323  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
    324  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
    325  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
    326  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
    327  1.1.2.1     marc 
    328  1.1.2.1     marc     reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
    329  1.1.2.1     marc     reg |= PCMCIA_CCR_OPTION_LEVIREQ;
    330  1.1.2.1     marc     if (pcmcia_mfc(pf->sc))
    331  1.1.2.1     marc 	reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
    332  1.1.2.1     marc     pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    333  1.1.2.1     marc 
    334  1.1.2.1     marc     reg = 0;
    335  1.1.2.8     marc 
    336  1.1.2.1     marc     if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
    337  1.1.2.1     marc 	reg |= PCMCIA_CCR_STATUS_IOIS8;
    338  1.1.2.1     marc     if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
    339  1.1.2.1     marc 	reg |= PCMCIA_CCR_STATUS_AUDIO;
    340  1.1.2.7  thorpej     /* Not really needed, since we start with 0. */
    341  1.1.2.7  thorpej     if (pf->cfe->flags & PCMCIA_CFE_POWERDOWN)
    342  1.1.2.7  thorpej 	reg &= ~PCMCIA_CCR_STATUS_PWRDWN;
    343  1.1.2.1     marc     pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
    344  1.1.2.1     marc 
    345  1.1.2.1     marc     pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
    346  1.1.2.1     marc 
    347  1.1.2.7  thorpej     pf->pf_flags |= PFF_ENABLED;
    348  1.1.2.1     marc     return(0);
    349  1.1.2.7  thorpej 
    350  1.1.2.7  thorpej  bad:
    351  1.1.2.8     marc     /* Decrement the reference count, and power down the socket,
    352  1.1.2.7  thorpej        if necessary. */
    353  1.1.2.7  thorpej     if (pf->sc->sc_enabled_count-- == 1)
    354  1.1.2.7  thorpej 	pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
    355  1.1.2.7  thorpej     return (1);
    356  1.1.2.7  thorpej }
    357  1.1.2.7  thorpej 
    358  1.1.2.7  thorpej /* Disable PCMCIA function. */
    359  1.1.2.7  thorpej void
    360  1.1.2.7  thorpej pcmcia_function_disable(pf)
    361  1.1.2.7  thorpej      struct pcmcia_function *pf;
    362  1.1.2.7  thorpej {
    363  1.1.2.7  thorpej     struct pcmcia_function *tmp;
    364  1.1.2.7  thorpej     int reg;
    365  1.1.2.7  thorpej 
    366  1.1.2.7  thorpej     if (pf->cfe == NULL)
    367  1.1.2.7  thorpej 	panic("pcmcia_function_enable: function not initialized");
    368  1.1.2.9  thorpej     if ((pf->pf_flags & PFF_ENABLED) == 0) {
    369  1.1.2.9  thorpej 	/*
    370  1.1.2.9  thorpej 	 * Don't do anything if we're already disabled.
    371  1.1.2.9  thorpej 	 */
    372  1.1.2.9  thorpej 	return;
    373  1.1.2.9  thorpej     }
    374  1.1.2.7  thorpej 
    375  1.1.2.7  thorpej     /* Power down the function if the card supports it. */
    376  1.1.2.7  thorpej     if (pf->cfe->flags & PCMCIA_CFE_POWERDOWN) {
    377  1.1.2.7  thorpej     	reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    378  1.1.2.7  thorpej 	reg |= PCMCIA_CCR_STATUS_PWRDWN;
    379  1.1.2.7  thorpej 	pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
    380  1.1.2.7  thorpej     }
    381  1.1.2.7  thorpej 
    382  1.1.2.7  thorpej     /* it's possible for different functions' CCRs to be in the same
    383  1.1.2.7  thorpej        underlying page.  Check for that.  Note we mark us as disabled
    384  1.1.2.7  thorpej        first to avoid matching ourself. */
    385  1.1.2.7  thorpej 
    386  1.1.2.7  thorpej     pf->pf_flags &= ~PFF_ENABLED;
    387  1.1.2.7  thorpej     for (tmp = pf->sc->card.pf_head.sqh_first;
    388  1.1.2.7  thorpej 	 tmp;
    389  1.1.2.7  thorpej 	 tmp = tmp->pf_list.sqe_next) {
    390  1.1.2.7  thorpej 	if ((tmp->pf_flags & PFF_ENABLED) &&
    391  1.1.2.7  thorpej 	    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
    392  1.1.2.7  thorpej 	    ((pf->ccr_base+PCMCIA_CCR_SIZE) <=
    393  1.1.2.7  thorpej 	     (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
    394  1.1.2.7  thorpej 	    break;
    395  1.1.2.7  thorpej     }
    396  1.1.2.7  thorpej 
    397  1.1.2.7  thorpej     /* Not used by anyone else; unmap the CCR. */
    398  1.1.2.7  thorpej     if (tmp == NULL) {
    399  1.1.2.7  thorpej 	pcmcia_mem_unmap(pf, pf->pf_ccr_window);
    400  1.1.2.7  thorpej 	pcmcia_mem_free(pf, &pf->pf_pcmh);
    401  1.1.2.7  thorpej     }
    402  1.1.2.7  thorpej 
    403  1.1.2.8     marc     /* Decrement the reference count, and power down the socket,
    404  1.1.2.7  thorpej        if necessary. */
    405  1.1.2.8     marc     if (--pf->sc->sc_enabled_count == 0)
    406  1.1.2.7  thorpej 	pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
    407  1.1.2.1     marc }
    408  1.1.2.1     marc 
    409  1.1.2.1     marc int
    410  1.1.2.5  thorpej pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
    411  1.1.2.1     marc      struct pcmcia_function *pf;
    412  1.1.2.1     marc      int width;
    413  1.1.2.5  thorpej      bus_addr_t offset;
    414  1.1.2.1     marc      bus_size_t size;
    415  1.1.2.5  thorpej      struct pcmcia_io_handle *pcihp;
    416  1.1.2.1     marc      int *windowp;
    417  1.1.2.1     marc {
    418  1.1.2.5  thorpej     bus_addr_t ioaddr;
    419  1.1.2.1     marc     int reg;
    420  1.1.2.1     marc 
    421  1.1.2.1     marc     if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
    422  1.1.2.5  thorpej 			   width, offset, size, pcihp, windowp))
    423  1.1.2.1     marc 	return(1);
    424  1.1.2.1     marc 
    425  1.1.2.5  thorpej     ioaddr = pcihp->addr + offset;
    426  1.1.2.5  thorpej 
    427  1.1.2.1     marc     /* XXX in the multifunction multi-iospace-per-function case, this
    428  1.1.2.1     marc        needs to cooperate with io_alloc to make sure that the spaces
    429  1.1.2.1     marc        don't overlap, and that the ccr's are set correctly */
    430  1.1.2.1     marc 
    431  1.1.2.1     marc     if (pcmcia_mfc(pf->sc)) {
    432  1.1.2.5  thorpej 	pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0, ioaddr & 0xff);
    433  1.1.2.5  thorpej 	pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1, (ioaddr >> 8) & 0xff);
    434  1.1.2.1     marc 	pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, size - 1);
    435  1.1.2.1     marc 
    436  1.1.2.1     marc 	reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
    437  1.1.2.1     marc 	reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
    438  1.1.2.1     marc 	pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    439  1.1.2.1     marc     }
    440  1.1.2.1     marc 
    441  1.1.2.1     marc     return(0);
    442  1.1.2.1     marc }
    443  1.1.2.1     marc 
    444  1.1.2.1     marc void *
    445  1.1.2.1     marc pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
    446  1.1.2.1     marc      struct pcmcia_function *pf;
    447  1.1.2.1     marc      int ipl;
    448  1.1.2.1     marc      int (*ih_fct) __P((void *));
    449  1.1.2.1     marc      void *ih_arg;
    450  1.1.2.1     marc {
    451  1.1.2.1     marc     void *ret;
    452  1.1.2.1     marc 
    453  1.1.2.1     marc     /* behave differently if this is a multifunction card */
    454  1.1.2.1     marc 
    455  1.1.2.1     marc     if (pcmcia_mfc(pf->sc)) {
    456  1.1.2.1     marc 	int s, ihcnt, hiipl, reg;
    457  1.1.2.1     marc 	struct pcmcia_function *pf2;
    458  1.1.2.1     marc 
    459  1.1.2.1     marc 	/* mask all the ipl's which are already used by this card,
    460  1.1.2.1     marc 	   and find the highest ipl number (lowest priority) */
    461  1.1.2.1     marc 
    462  1.1.2.1     marc 	ihcnt = 0;
    463  1.1.2.1     marc 	s = 0; /* this is only here to keep the compipler happy */
    464  1.1.2.1     marc 	hiipl = 0; /* this is only here to keep the compipler happy */
    465  1.1.2.1     marc 
    466  1.1.2.1     marc 	for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
    467  1.1.2.1     marc 	     pf2 = pf2->pf_list.sqe_next) {
    468  1.1.2.1     marc 	    if (pf2->ih_fct) {
    469  1.1.2.1     marc 		if (!ihcnt) {
    470  1.1.2.1     marc 		    s = splraise(pf2->ih_ipl);
    471  1.1.2.1     marc 		    hiipl = pf2->ih_ipl;
    472  1.1.2.1     marc 		    ihcnt++;
    473  1.1.2.1     marc 		} else {
    474  1.1.2.1     marc 		    splraise(pf2->ih_ipl);
    475  1.1.2.1     marc 		    if (pf2->ih_ipl > hiipl)
    476  1.1.2.1     marc 			hiipl = pf2->ih_ipl;
    477  1.1.2.1     marc 		}
    478  1.1.2.1     marc 	    }
    479  1.1.2.1     marc 	}
    480  1.1.2.1     marc 
    481  1.1.2.1     marc 	/* set up the handler for the new function */
    482  1.1.2.1     marc 
    483  1.1.2.1     marc 	pf->ih_fct = ih_fct;
    484  1.1.2.1     marc 	pf->ih_arg = ih_arg;
    485  1.1.2.1     marc 	pf->ih_ipl = ipl;
    486  1.1.2.1     marc 
    487  1.1.2.1     marc 	/* establish the real interrupt, changing the ipl if necessary */
    488  1.1.2.1     marc 
    489  1.1.2.1     marc 	if (ihcnt == 0) {
    490  1.1.2.1     marc #ifdef DIAGNOSTIC
    491  1.1.2.1     marc 	    if (pf->sc->ih)
    492  1.1.2.1     marc 		panic("card has intr handler, but no function does");
    493  1.1.2.1     marc #endif
    494  1.1.2.1     marc 
    495  1.1.2.1     marc 	    pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    496  1.1.2.6  thorpej 						    pf, ipl,
    497  1.1.2.4  thorpej 						    pcmcia_card_intr, pf->sc);
    498  1.1.2.1     marc 	} else if (ipl > hiipl) {
    499  1.1.2.1     marc #ifdef DIAGNOSTIC
    500  1.1.2.1     marc 	    if (! pf->sc->ih)
    501  1.1.2.1     marc 		panic("functions have ih, but the card does not");
    502  1.1.2.1     marc #endif
    503  1.1.2.1     marc 
    504  1.1.2.1     marc 	    pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    505  1.1.2.1     marc 					  pf->sc->ih);
    506  1.1.2.1     marc 	    pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    507  1.1.2.6  thorpej 						    pf, ipl,
    508  1.1.2.4  thorpej 						    pcmcia_card_intr, pf->sc);
    509  1.1.2.1     marc 	}
    510  1.1.2.1     marc 
    511  1.1.2.1     marc 	if (ihcnt)
    512  1.1.2.1     marc 	    splx(s);
    513  1.1.2.1     marc 
    514  1.1.2.1     marc 	ret = pf->sc->ih;
    515  1.1.2.1     marc 
    516  1.1.2.1     marc 	if (ret) {
    517  1.1.2.1     marc 	    reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
    518  1.1.2.1     marc 	    reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
    519  1.1.2.1     marc 	    pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    520  1.1.2.1     marc 
    521  1.1.2.1     marc 	    reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    522  1.1.2.1     marc 	    reg |= PCMCIA_CCR_STATUS_INTRACK;
    523  1.1.2.1     marc 	    pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
    524  1.1.2.1     marc 	}
    525  1.1.2.1     marc     } else {
    526  1.1.2.1     marc 	ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    527  1.1.2.6  thorpej 					 pf, ipl, ih_fct, ih_arg);
    528  1.1.2.1     marc     }
    529  1.1.2.1     marc 
    530  1.1.2.1     marc     return(ret);
    531  1.1.2.1     marc }
    532  1.1.2.1     marc 
    533  1.1.2.1     marc void
    534  1.1.2.1     marc pcmcia_intr_disestablish(pf, ih)
    535  1.1.2.1     marc      struct pcmcia_function *pf;
    536  1.1.2.1     marc      void *ih;
    537  1.1.2.1     marc {
    538  1.1.2.4  thorpej 
    539  1.1.2.1     marc     /* behave differently if this is a multifunction card */
    540  1.1.2.1     marc 
    541  1.1.2.1     marc     if (pcmcia_mfc(pf->sc)) {
    542  1.1.2.1     marc 	int s, ihcnt, hiipl;
    543  1.1.2.1     marc 	struct pcmcia_function *pf2;
    544  1.1.2.1     marc 
    545  1.1.2.1     marc 	/* mask all the ipl's which are already used by this card,
    546  1.1.2.1     marc 	   and find the highest ipl number (lowest priority).  Skip
    547  1.1.2.1     marc 	   the current function. */
    548  1.1.2.1     marc 
    549  1.1.2.1     marc 	ihcnt = 0;
    550  1.1.2.1     marc 	s = 0; /* this is only here to keep the compipler happy */
    551  1.1.2.1     marc 	hiipl = 0; /* this is only here to keep the compipler happy */
    552  1.1.2.1     marc 
    553  1.1.2.1     marc 	for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
    554  1.1.2.1     marc 	     pf2 = pf2->pf_list.sqe_next) {
    555  1.1.2.1     marc 	    if (pf2 == pf)
    556  1.1.2.1     marc 		continue;
    557  1.1.2.1     marc 
    558  1.1.2.1     marc 	    if (pf2->ih_fct) {
    559  1.1.2.1     marc 		if (!ihcnt) {
    560  1.1.2.1     marc 		    s = splraise(pf2->ih_ipl);
    561  1.1.2.1     marc 		    hiipl = pf2->ih_ipl;
    562  1.1.2.1     marc 		    ihcnt++;
    563  1.1.2.1     marc 		} else {
    564  1.1.2.1     marc 		    splraise(pf2->ih_ipl);
    565  1.1.2.1     marc 		    if (pf2->ih_ipl > hiipl)
    566  1.1.2.1     marc 			hiipl = pf2->ih_ipl;
    567  1.1.2.1     marc 		}
    568  1.1.2.1     marc 	    }
    569  1.1.2.1     marc 	}
    570  1.1.2.1     marc 
    571  1.1.2.1     marc 	/* null out the handler for this function */
    572  1.1.2.1     marc 
    573  1.1.2.1     marc 	pf->ih_fct = NULL;
    574  1.1.2.1     marc 	pf->ih_arg = NULL;
    575  1.1.2.1     marc 
    576  1.1.2.1     marc 	/* if the ih being removed is lower priority than the lowest
    577  1.1.2.1     marc 	   priority remaining interrupt, up the priority. */
    578  1.1.2.1     marc 
    579  1.1.2.1     marc #ifdef DIAGNOSTIC
    580  1.1.2.1     marc 	if (ihcnt == 0) {
    581  1.1.2.1     marc 	    panic("can't remove a handler from a card which has none");
    582  1.1.2.1     marc 	} else
    583  1.1.2.1     marc #endif
    584  1.1.2.1     marc 	if (ihcnt == 1) {
    585  1.1.2.1     marc #ifdef DIAGNOSTIC
    586  1.1.2.1     marc 	    if (!pf->sc->ih)
    587  1.1.2.1     marc 		panic("disestablishing last function, but card has no ih");
    588  1.1.2.1     marc #endif
    589  1.1.2.1     marc 	    pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    590  1.1.2.1     marc 					  pf->sc->ih);
    591  1.1.2.1     marc 	    pf->sc->ih = NULL;
    592  1.1.2.1     marc 	} else if (pf->ih_ipl > hiipl) {
    593  1.1.2.1     marc #ifdef DIAGNOSTIC
    594  1.1.2.1     marc 	    if (!pf->sc->ih)
    595  1.1.2.1     marc 		panic("changing ih ipl, but card has no ih");
    596  1.1.2.1     marc #endif
    597  1.1.2.1     marc 	    pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    598  1.1.2.1     marc 					  pf->sc->ih);
    599  1.1.2.1     marc 	    pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    600  1.1.2.6  thorpej 						    pf, hiipl,
    601  1.1.2.4  thorpej 						    pcmcia_card_intr, pf->sc);
    602  1.1.2.1     marc 	}
    603  1.1.2.1     marc 
    604  1.1.2.1     marc 	if (ihcnt)
    605  1.1.2.1     marc 	    splx(s);
    606  1.1.2.1     marc     } else {
    607  1.1.2.1     marc 	pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
    608  1.1.2.1     marc     }
    609  1.1.2.1     marc }
    610  1.1.2.1     marc 
    611  1.1.2.1     marc int pcmcia_card_intr(arg)
    612  1.1.2.1     marc     void *arg;
    613  1.1.2.1     marc {
    614  1.1.2.1     marc     struct pcmcia_softc *sc = (struct pcmcia_softc *) arg;
    615  1.1.2.1     marc     struct pcmcia_function *pf;
    616  1.1.2.1     marc     int reg, ret, ret2;
    617  1.1.2.1     marc 
    618  1.1.2.1     marc     ret = 0;
    619  1.1.2.1     marc 
    620  1.1.2.1     marc     for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
    621  1.1.2.1     marc #if 0
    622  1.1.2.1     marc 	printf("%s: intr fct=%d physaddr=%lx cor=%02x csr=%02x pin=%02x",
    623  1.1.2.1     marc 	       sc->dev.dv_xname, pf->number,
    624  1.1.2.1     marc 	       pmap_extract(pmap_kernel(), (vm_offset_t) pf->ccrh) + pf->ccr_offset,
    625  1.1.2.5  thorpej 	       bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
    626  1.1.2.5  thorpej 				pf->pf_ccr_offset+PCMCIA_CCR_OPTION),
    627  1.1.2.5  thorpej 	       bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
    628  1.1.2.5  thorpej 				pf->pf_ccr_offset+PCMCIA_CCR_STATUS),
    629  1.1.2.5  thorpej 	       bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
    630  1.1.2.5  thorpej 				pf->pf_ccr_offset+PCMCIA_CCR_PIN));
    631  1.1.2.1     marc #endif
    632  1.1.2.1     marc 	if (pf->ih_fct &&
    633  1.1.2.1     marc 	    (pf->ccr_mask & (1<<(PCMCIA_CCR_STATUS/2)))) {
    634  1.1.2.1     marc 	    reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    635  1.1.2.1     marc 	    if (reg & PCMCIA_CCR_STATUS_INTR) {
    636  1.1.2.1     marc 		ret2 = (*pf->ih_fct)(pf->ih_arg);
    637  1.1.2.1     marc 		if (ret2 && !ret)
    638  1.1.2.1     marc 		    ret = ret2;
    639  1.1.2.1     marc 		reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    640  1.1.2.1     marc #if 0
    641  1.1.2.1     marc 		printf("; csr %02x->%02x", reg, reg & ~PCMCIA_CCR_STATUS_INTR);
    642  1.1.2.1     marc #endif
    643  1.1.2.1     marc 		pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
    644  1.1.2.1     marc 				 reg & ~PCMCIA_CCR_STATUS_INTR);
    645  1.1.2.1     marc 	    }
    646  1.1.2.1     marc 	}
    647  1.1.2.1     marc #if 0
    648  1.1.2.1     marc 	printf("\n");
    649  1.1.2.1     marc #endif
    650  1.1.2.1     marc     }
    651  1.1.2.1     marc 
    652  1.1.2.1     marc     return(ret);
    653  1.1.2.1     marc }
    654