Home | History | Annotate | Line # | Download | only in pcmcia
pcmcia.c revision 1.1.2.8
      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.7  thorpej     if (pf->pf_flags & PFF_ENABLED)
    273  1.1.2.7  thorpej 	panic("pcmcia_function_enable: function already enabled");
    274  1.1.2.7  thorpej 
    275  1.1.2.7  thorpej     /* Increase the reference count on the socket, enabling power,
    276  1.1.2.7  thorpej        if necessary. */
    277  1.1.2.7  thorpej     if (pf->sc->sc_enabled_count++ == 0)
    278  1.1.2.7  thorpej 	pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
    279  1.1.2.1     marc 
    280  1.1.2.1     marc     /* it's possible for different functions' CCRs to be in the same
    281  1.1.2.1     marc        underlying page.  Check for that. */
    282  1.1.2.1     marc 
    283  1.1.2.1     marc     for (tmp = pf->sc->card.pf_head.sqh_first;
    284  1.1.2.1     marc 	 tmp;
    285  1.1.2.1     marc 	 tmp = tmp->pf_list.sqe_next) {
    286  1.1.2.7  thorpej 	if ((tmp->pf_flags & PFF_ENABLED) &&
    287  1.1.2.5  thorpej 	    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
    288  1.1.2.1     marc 	    ((pf->ccr_base+PCMCIA_CCR_SIZE) <=
    289  1.1.2.5  thorpej 	     (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize))) {
    290  1.1.2.5  thorpej 	    pf->pf_ccrt = tmp->pf_ccrt;
    291  1.1.2.5  thorpej 	    pf->pf_ccrh = tmp->pf_ccrh;
    292  1.1.2.5  thorpej 	    pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
    293  1.1.2.5  thorpej 
    294  1.1.2.5  thorpej 	    /* pf->pf_ccr_offset =
    295  1.1.2.5  thorpej 	       (tmp->pf_ccr_offset - tmp->ccr_base) + pf->ccr_base; */
    296  1.1.2.5  thorpej 	    pf->pf_ccr_offset =
    297  1.1.2.5  thorpej 	        (tmp->pf_ccr_offset + pf->ccr_base) - tmp->ccr_base;
    298  1.1.2.5  thorpej 	    pf->pf_ccr_window = tmp->pf_ccr_window;
    299  1.1.2.1     marc 	    break;
    300  1.1.2.1     marc 	}
    301  1.1.2.1     marc     }
    302  1.1.2.1     marc 
    303  1.1.2.1     marc     if (tmp == NULL) {
    304  1.1.2.5  thorpej 	if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
    305  1.1.2.7  thorpej 	    goto bad;
    306  1.1.2.1     marc 
    307  1.1.2.5  thorpej 	if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
    308  1.1.2.5  thorpej 			   PCMCIA_CCR_SIZE, &pf->pf_pcmh,
    309  1.1.2.7  thorpej 			   &pf->pf_ccr_offset, &pf->pf_ccr_window)) {
    310  1.1.2.7  thorpej 	    pcmcia_mem_free(pf, &pf->pf_pcmh);
    311  1.1.2.7  thorpej 	    goto bad;
    312  1.1.2.7  thorpej 	}
    313  1.1.2.1     marc     }
    314  1.1.2.1     marc 
    315  1.1.2.1     marc     DPRINTF(("%s: function %d CCR at %d offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
    316  1.1.2.1     marc 	     pf->sc->dev.dv_xname, pf->number,
    317  1.1.2.5  thorpej 	     pf->pf_ccr_window, pf->pf_ccr_offset,
    318  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x00),
    319  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
    320  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
    321  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
    322  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
    323  1.1.2.1     marc 
    324  1.1.2.1     marc     reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
    325  1.1.2.1     marc     reg |= PCMCIA_CCR_OPTION_LEVIREQ;
    326  1.1.2.1     marc     if (pcmcia_mfc(pf->sc))
    327  1.1.2.1     marc 	reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
    328  1.1.2.1     marc     pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    329  1.1.2.1     marc 
    330  1.1.2.1     marc     reg = 0;
    331  1.1.2.8     marc 
    332  1.1.2.1     marc     if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
    333  1.1.2.1     marc 	reg |= PCMCIA_CCR_STATUS_IOIS8;
    334  1.1.2.1     marc     if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
    335  1.1.2.1     marc 	reg |= PCMCIA_CCR_STATUS_AUDIO;
    336  1.1.2.7  thorpej     /* Not really needed, since we start with 0. */
    337  1.1.2.7  thorpej     if (pf->cfe->flags & PCMCIA_CFE_POWERDOWN)
    338  1.1.2.7  thorpej 	reg &= ~PCMCIA_CCR_STATUS_PWRDWN;
    339  1.1.2.1     marc     pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
    340  1.1.2.1     marc 
    341  1.1.2.1     marc     pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
    342  1.1.2.1     marc 
    343  1.1.2.7  thorpej     pf->pf_flags |= PFF_ENABLED;
    344  1.1.2.1     marc     return(0);
    345  1.1.2.7  thorpej 
    346  1.1.2.7  thorpej  bad:
    347  1.1.2.8     marc     /* Decrement the reference count, and power down the socket,
    348  1.1.2.7  thorpej        if necessary. */
    349  1.1.2.7  thorpej     if (pf->sc->sc_enabled_count-- == 1)
    350  1.1.2.7  thorpej 	pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
    351  1.1.2.7  thorpej     return (1);
    352  1.1.2.7  thorpej }
    353  1.1.2.7  thorpej 
    354  1.1.2.7  thorpej /* Disable PCMCIA function. */
    355  1.1.2.7  thorpej void
    356  1.1.2.7  thorpej pcmcia_function_disable(pf)
    357  1.1.2.7  thorpej      struct pcmcia_function *pf;
    358  1.1.2.7  thorpej {
    359  1.1.2.7  thorpej     struct pcmcia_function *tmp;
    360  1.1.2.7  thorpej     int reg;
    361  1.1.2.7  thorpej 
    362  1.1.2.7  thorpej     if (pf->cfe == NULL)
    363  1.1.2.7  thorpej 	panic("pcmcia_function_enable: function not initialized");
    364  1.1.2.7  thorpej 
    365  1.1.2.7  thorpej     /* Power down the function if the card supports it. */
    366  1.1.2.7  thorpej     if (pf->cfe->flags & PCMCIA_CFE_POWERDOWN) {
    367  1.1.2.7  thorpej     	reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    368  1.1.2.7  thorpej 	reg |= PCMCIA_CCR_STATUS_PWRDWN;
    369  1.1.2.7  thorpej 	pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
    370  1.1.2.7  thorpej     }
    371  1.1.2.7  thorpej 
    372  1.1.2.7  thorpej     /* it's possible for different functions' CCRs to be in the same
    373  1.1.2.7  thorpej        underlying page.  Check for that.  Note we mark us as disabled
    374  1.1.2.7  thorpej        first to avoid matching ourself. */
    375  1.1.2.7  thorpej 
    376  1.1.2.7  thorpej     pf->pf_flags &= ~PFF_ENABLED;
    377  1.1.2.7  thorpej     for (tmp = pf->sc->card.pf_head.sqh_first;
    378  1.1.2.7  thorpej 	 tmp;
    379  1.1.2.7  thorpej 	 tmp = tmp->pf_list.sqe_next) {
    380  1.1.2.7  thorpej 	if ((tmp->pf_flags & PFF_ENABLED) &&
    381  1.1.2.7  thorpej 	    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
    382  1.1.2.7  thorpej 	    ((pf->ccr_base+PCMCIA_CCR_SIZE) <=
    383  1.1.2.7  thorpej 	     (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
    384  1.1.2.7  thorpej 	    break;
    385  1.1.2.7  thorpej     }
    386  1.1.2.7  thorpej 
    387  1.1.2.7  thorpej     /* Not used by anyone else; unmap the CCR. */
    388  1.1.2.7  thorpej     if (tmp == NULL) {
    389  1.1.2.7  thorpej 	pcmcia_mem_unmap(pf, pf->pf_ccr_window);
    390  1.1.2.7  thorpej 	pcmcia_mem_free(pf, &pf->pf_pcmh);
    391  1.1.2.7  thorpej     }
    392  1.1.2.7  thorpej 
    393  1.1.2.8     marc     /* Decrement the reference count, and power down the socket,
    394  1.1.2.7  thorpej        if necessary. */
    395  1.1.2.8     marc     if (--pf->sc->sc_enabled_count == 0)
    396  1.1.2.7  thorpej 	pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
    397  1.1.2.1     marc }
    398  1.1.2.1     marc 
    399  1.1.2.1     marc int
    400  1.1.2.5  thorpej pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
    401  1.1.2.1     marc      struct pcmcia_function *pf;
    402  1.1.2.1     marc      int width;
    403  1.1.2.5  thorpej      bus_addr_t offset;
    404  1.1.2.1     marc      bus_size_t size;
    405  1.1.2.5  thorpej      struct pcmcia_io_handle *pcihp;
    406  1.1.2.1     marc      int *windowp;
    407  1.1.2.1     marc {
    408  1.1.2.5  thorpej     bus_addr_t ioaddr;
    409  1.1.2.1     marc     int reg;
    410  1.1.2.1     marc 
    411  1.1.2.1     marc     if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
    412  1.1.2.5  thorpej 			   width, offset, size, pcihp, windowp))
    413  1.1.2.1     marc 	return(1);
    414  1.1.2.1     marc 
    415  1.1.2.5  thorpej     ioaddr = pcihp->addr + offset;
    416  1.1.2.5  thorpej 
    417  1.1.2.1     marc     /* XXX in the multifunction multi-iospace-per-function case, this
    418  1.1.2.1     marc        needs to cooperate with io_alloc to make sure that the spaces
    419  1.1.2.1     marc        don't overlap, and that the ccr's are set correctly */
    420  1.1.2.1     marc 
    421  1.1.2.1     marc     if (pcmcia_mfc(pf->sc)) {
    422  1.1.2.5  thorpej 	pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0, ioaddr & 0xff);
    423  1.1.2.5  thorpej 	pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1, (ioaddr >> 8) & 0xff);
    424  1.1.2.1     marc 	pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, size - 1);
    425  1.1.2.1     marc 
    426  1.1.2.1     marc 	reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
    427  1.1.2.1     marc 	reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
    428  1.1.2.1     marc 	pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    429  1.1.2.1     marc     }
    430  1.1.2.1     marc 
    431  1.1.2.1     marc     return(0);
    432  1.1.2.1     marc }
    433  1.1.2.1     marc 
    434  1.1.2.1     marc void *
    435  1.1.2.1     marc pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
    436  1.1.2.1     marc      struct pcmcia_function *pf;
    437  1.1.2.1     marc      int ipl;
    438  1.1.2.1     marc      int (*ih_fct) __P((void *));
    439  1.1.2.1     marc      void *ih_arg;
    440  1.1.2.1     marc {
    441  1.1.2.1     marc     void *ret;
    442  1.1.2.1     marc 
    443  1.1.2.1     marc     /* behave differently if this is a multifunction card */
    444  1.1.2.1     marc 
    445  1.1.2.1     marc     if (pcmcia_mfc(pf->sc)) {
    446  1.1.2.1     marc 	int s, ihcnt, hiipl, reg;
    447  1.1.2.1     marc 	struct pcmcia_function *pf2;
    448  1.1.2.1     marc 
    449  1.1.2.1     marc 	/* mask all the ipl's which are already used by this card,
    450  1.1.2.1     marc 	   and find the highest ipl number (lowest priority) */
    451  1.1.2.1     marc 
    452  1.1.2.1     marc 	ihcnt = 0;
    453  1.1.2.1     marc 	s = 0; /* this is only here to keep the compipler happy */
    454  1.1.2.1     marc 	hiipl = 0; /* this is only here to keep the compipler happy */
    455  1.1.2.1     marc 
    456  1.1.2.1     marc 	for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
    457  1.1.2.1     marc 	     pf2 = pf2->pf_list.sqe_next) {
    458  1.1.2.1     marc 	    if (pf2->ih_fct) {
    459  1.1.2.1     marc 		if (!ihcnt) {
    460  1.1.2.1     marc 		    s = splraise(pf2->ih_ipl);
    461  1.1.2.1     marc 		    hiipl = pf2->ih_ipl;
    462  1.1.2.1     marc 		    ihcnt++;
    463  1.1.2.1     marc 		} else {
    464  1.1.2.1     marc 		    splraise(pf2->ih_ipl);
    465  1.1.2.1     marc 		    if (pf2->ih_ipl > hiipl)
    466  1.1.2.1     marc 			hiipl = pf2->ih_ipl;
    467  1.1.2.1     marc 		}
    468  1.1.2.1     marc 	    }
    469  1.1.2.1     marc 	}
    470  1.1.2.1     marc 
    471  1.1.2.1     marc 	/* set up the handler for the new function */
    472  1.1.2.1     marc 
    473  1.1.2.1     marc 	pf->ih_fct = ih_fct;
    474  1.1.2.1     marc 	pf->ih_arg = ih_arg;
    475  1.1.2.1     marc 	pf->ih_ipl = ipl;
    476  1.1.2.1     marc 
    477  1.1.2.1     marc 	/* establish the real interrupt, changing the ipl if necessary */
    478  1.1.2.1     marc 
    479  1.1.2.1     marc 	if (ihcnt == 0) {
    480  1.1.2.1     marc #ifdef DIAGNOSTIC
    481  1.1.2.1     marc 	    if (pf->sc->ih)
    482  1.1.2.1     marc 		panic("card has intr handler, but no function does");
    483  1.1.2.1     marc #endif
    484  1.1.2.1     marc 
    485  1.1.2.1     marc 	    pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    486  1.1.2.6  thorpej 						    pf, ipl,
    487  1.1.2.4  thorpej 						    pcmcia_card_intr, pf->sc);
    488  1.1.2.1     marc 	} else if (ipl > hiipl) {
    489  1.1.2.1     marc #ifdef DIAGNOSTIC
    490  1.1.2.1     marc 	    if (! pf->sc->ih)
    491  1.1.2.1     marc 		panic("functions have ih, but the card does not");
    492  1.1.2.1     marc #endif
    493  1.1.2.1     marc 
    494  1.1.2.1     marc 	    pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    495  1.1.2.1     marc 					  pf->sc->ih);
    496  1.1.2.1     marc 	    pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    497  1.1.2.6  thorpej 						    pf, ipl,
    498  1.1.2.4  thorpej 						    pcmcia_card_intr, pf->sc);
    499  1.1.2.1     marc 	}
    500  1.1.2.1     marc 
    501  1.1.2.1     marc 	if (ihcnt)
    502  1.1.2.1     marc 	    splx(s);
    503  1.1.2.1     marc 
    504  1.1.2.1     marc 	ret = pf->sc->ih;
    505  1.1.2.1     marc 
    506  1.1.2.1     marc 	if (ret) {
    507  1.1.2.1     marc 	    reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
    508  1.1.2.1     marc 	    reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
    509  1.1.2.1     marc 	    pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    510  1.1.2.1     marc 
    511  1.1.2.1     marc 	    reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    512  1.1.2.1     marc 	    reg |= PCMCIA_CCR_STATUS_INTRACK;
    513  1.1.2.1     marc 	    pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
    514  1.1.2.1     marc 	}
    515  1.1.2.1     marc     } else {
    516  1.1.2.1     marc 	ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    517  1.1.2.6  thorpej 					 pf, ipl, ih_fct, ih_arg);
    518  1.1.2.1     marc     }
    519  1.1.2.1     marc 
    520  1.1.2.1     marc     return(ret);
    521  1.1.2.1     marc }
    522  1.1.2.1     marc 
    523  1.1.2.1     marc void
    524  1.1.2.1     marc pcmcia_intr_disestablish(pf, ih)
    525  1.1.2.1     marc      struct pcmcia_function *pf;
    526  1.1.2.1     marc      void *ih;
    527  1.1.2.1     marc {
    528  1.1.2.4  thorpej 
    529  1.1.2.1     marc     /* behave differently if this is a multifunction card */
    530  1.1.2.1     marc 
    531  1.1.2.1     marc     if (pcmcia_mfc(pf->sc)) {
    532  1.1.2.1     marc 	int s, ihcnt, hiipl;
    533  1.1.2.1     marc 	struct pcmcia_function *pf2;
    534  1.1.2.1     marc 
    535  1.1.2.1     marc 	/* mask all the ipl's which are already used by this card,
    536  1.1.2.1     marc 	   and find the highest ipl number (lowest priority).  Skip
    537  1.1.2.1     marc 	   the current function. */
    538  1.1.2.1     marc 
    539  1.1.2.1     marc 	ihcnt = 0;
    540  1.1.2.1     marc 	s = 0; /* this is only here to keep the compipler happy */
    541  1.1.2.1     marc 	hiipl = 0; /* this is only here to keep the compipler happy */
    542  1.1.2.1     marc 
    543  1.1.2.1     marc 	for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
    544  1.1.2.1     marc 	     pf2 = pf2->pf_list.sqe_next) {
    545  1.1.2.1     marc 	    if (pf2 == pf)
    546  1.1.2.1     marc 		continue;
    547  1.1.2.1     marc 
    548  1.1.2.1     marc 	    if (pf2->ih_fct) {
    549  1.1.2.1     marc 		if (!ihcnt) {
    550  1.1.2.1     marc 		    s = splraise(pf2->ih_ipl);
    551  1.1.2.1     marc 		    hiipl = pf2->ih_ipl;
    552  1.1.2.1     marc 		    ihcnt++;
    553  1.1.2.1     marc 		} else {
    554  1.1.2.1     marc 		    splraise(pf2->ih_ipl);
    555  1.1.2.1     marc 		    if (pf2->ih_ipl > hiipl)
    556  1.1.2.1     marc 			hiipl = pf2->ih_ipl;
    557  1.1.2.1     marc 		}
    558  1.1.2.1     marc 	    }
    559  1.1.2.1     marc 	}
    560  1.1.2.1     marc 
    561  1.1.2.1     marc 	/* null out the handler for this function */
    562  1.1.2.1     marc 
    563  1.1.2.1     marc 	pf->ih_fct = NULL;
    564  1.1.2.1     marc 	pf->ih_arg = NULL;
    565  1.1.2.1     marc 
    566  1.1.2.1     marc 	/* if the ih being removed is lower priority than the lowest
    567  1.1.2.1     marc 	   priority remaining interrupt, up the priority. */
    568  1.1.2.1     marc 
    569  1.1.2.1     marc #ifdef DIAGNOSTIC
    570  1.1.2.1     marc 	if (ihcnt == 0) {
    571  1.1.2.1     marc 	    panic("can't remove a handler from a card which has none");
    572  1.1.2.1     marc 	} else
    573  1.1.2.1     marc #endif
    574  1.1.2.1     marc 	if (ihcnt == 1) {
    575  1.1.2.1     marc #ifdef DIAGNOSTIC
    576  1.1.2.1     marc 	    if (!pf->sc->ih)
    577  1.1.2.1     marc 		panic("disestablishing last function, but card has no ih");
    578  1.1.2.1     marc #endif
    579  1.1.2.1     marc 	    pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    580  1.1.2.1     marc 					  pf->sc->ih);
    581  1.1.2.1     marc 	    pf->sc->ih = NULL;
    582  1.1.2.1     marc 	} else if (pf->ih_ipl > hiipl) {
    583  1.1.2.1     marc #ifdef DIAGNOSTIC
    584  1.1.2.1     marc 	    if (!pf->sc->ih)
    585  1.1.2.1     marc 		panic("changing ih ipl, but card has no ih");
    586  1.1.2.1     marc #endif
    587  1.1.2.1     marc 	    pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    588  1.1.2.1     marc 					  pf->sc->ih);
    589  1.1.2.1     marc 	    pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    590  1.1.2.6  thorpej 						    pf, hiipl,
    591  1.1.2.4  thorpej 						    pcmcia_card_intr, pf->sc);
    592  1.1.2.1     marc 	}
    593  1.1.2.1     marc 
    594  1.1.2.1     marc 	if (ihcnt)
    595  1.1.2.1     marc 	    splx(s);
    596  1.1.2.1     marc     } else {
    597  1.1.2.1     marc 	pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
    598  1.1.2.1     marc     }
    599  1.1.2.1     marc }
    600  1.1.2.1     marc 
    601  1.1.2.1     marc int pcmcia_card_intr(arg)
    602  1.1.2.1     marc     void *arg;
    603  1.1.2.1     marc {
    604  1.1.2.1     marc     struct pcmcia_softc *sc = (struct pcmcia_softc *) arg;
    605  1.1.2.1     marc     struct pcmcia_function *pf;
    606  1.1.2.1     marc     int reg, ret, ret2;
    607  1.1.2.1     marc 
    608  1.1.2.1     marc     ret = 0;
    609  1.1.2.1     marc 
    610  1.1.2.1     marc     for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
    611  1.1.2.1     marc #if 0
    612  1.1.2.1     marc 	printf("%s: intr fct=%d physaddr=%lx cor=%02x csr=%02x pin=%02x",
    613  1.1.2.1     marc 	       sc->dev.dv_xname, pf->number,
    614  1.1.2.1     marc 	       pmap_extract(pmap_kernel(), (vm_offset_t) pf->ccrh) + pf->ccr_offset,
    615  1.1.2.5  thorpej 	       bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
    616  1.1.2.5  thorpej 				pf->pf_ccr_offset+PCMCIA_CCR_OPTION),
    617  1.1.2.5  thorpej 	       bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
    618  1.1.2.5  thorpej 				pf->pf_ccr_offset+PCMCIA_CCR_STATUS),
    619  1.1.2.5  thorpej 	       bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
    620  1.1.2.5  thorpej 				pf->pf_ccr_offset+PCMCIA_CCR_PIN));
    621  1.1.2.1     marc #endif
    622  1.1.2.1     marc 	if (pf->ih_fct &&
    623  1.1.2.1     marc 	    (pf->ccr_mask & (1<<(PCMCIA_CCR_STATUS/2)))) {
    624  1.1.2.1     marc 	    reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    625  1.1.2.1     marc 	    if (reg & PCMCIA_CCR_STATUS_INTR) {
    626  1.1.2.1     marc 		ret2 = (*pf->ih_fct)(pf->ih_arg);
    627  1.1.2.1     marc 		if (ret2 && !ret)
    628  1.1.2.1     marc 		    ret = ret2;
    629  1.1.2.1     marc 		reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    630  1.1.2.1     marc #if 0
    631  1.1.2.1     marc 		printf("; csr %02x->%02x", reg, reg & ~PCMCIA_CCR_STATUS_INTR);
    632  1.1.2.1     marc #endif
    633  1.1.2.1     marc 		pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
    634  1.1.2.1     marc 				 reg & ~PCMCIA_CCR_STATUS_INTR);
    635  1.1.2.1     marc 	    }
    636  1.1.2.1     marc 	}
    637  1.1.2.1     marc #if 0
    638  1.1.2.1     marc 	printf("\n");
    639  1.1.2.1     marc #endif
    640  1.1.2.1     marc     }
    641  1.1.2.1     marc 
    642  1.1.2.1     marc     return(ret);
    643  1.1.2.1     marc }
    644