Home | History | Annotate | Line # | Download | only in pcmcia
pcmcia.c revision 1.1.2.4
      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.1     marc #ifdef	__BROKEN_INDIRECT_CONFIG
     23  1.1.2.1     marc int pcmcia_match __P((struct device *, void *, void *));
     24  1.1.2.1     marc int pcmcia_submatch __P((struct device *, void *, void *));
     25  1.1.2.1     marc #else
     26  1.1.2.1     marc int pcmcia_match __P((struct device *, struct cfdata *, void *));
     27  1.1.2.1     marc int pcmcia_submatch __P((struct device *, struct cfdata *, void *));
     28  1.1.2.1     marc #endif
     29  1.1.2.1     marc void pcmcia_attach __P((struct device *, struct device *, void *));
     30  1.1.2.1     marc int pcmcia_print __P((void *, const char *));
     31  1.1.2.1     marc 
     32  1.1.2.1     marc int pcmcia_card_intr __P((void *));
     33  1.1.2.1     marc 
     34  1.1.2.1     marc struct cfdriver pcmcia_cd = {
     35  1.1.2.1     marc 	NULL, "pcmcia", DV_DULL
     36  1.1.2.1     marc };
     37  1.1.2.1     marc 
     38  1.1.2.1     marc struct cfattach pcmcia_ca = {
     39  1.1.2.1     marc 	sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach
     40  1.1.2.1     marc };
     41  1.1.2.1     marc 
     42  1.1.2.1     marc int
     43  1.1.2.1     marc pcmcia_ccr_read(pf, ccr)
     44  1.1.2.1     marc      struct pcmcia_function *pf;
     45  1.1.2.1     marc      int ccr;
     46  1.1.2.1     marc {
     47  1.1.2.1     marc     return(bus_space_read_1((pf)->ccrt, (pf)->ccrh, (pf)->ccr_offset+(ccr)));
     48  1.1.2.1     marc }
     49  1.1.2.1     marc 
     50  1.1.2.1     marc void
     51  1.1.2.1     marc pcmcia_ccr_write(pf, ccr, val)
     52  1.1.2.1     marc      struct pcmcia_function *pf;
     53  1.1.2.1     marc      int ccr;
     54  1.1.2.1     marc      int val;
     55  1.1.2.1     marc {
     56  1.1.2.1     marc     if (((pf)->ccr_mask) & (1<<(ccr/2))) {
     57  1.1.2.1     marc 	bus_space_write_1((pf)->ccrt, (pf)->ccrh,
     58  1.1.2.1     marc 			  (pf)->ccr_offset+(ccr), (val));
     59  1.1.2.1     marc     }
     60  1.1.2.1     marc }
     61  1.1.2.1     marc 
     62  1.1.2.1     marc int
     63  1.1.2.1     marc pcmcia_match(parent, match, aux)
     64  1.1.2.1     marc      struct device *parent;
     65  1.1.2.1     marc #ifdef	__BROKEN_INDIRECT_CONFIG
     66  1.1.2.1     marc      void *match;
     67  1.1.2.1     marc #else
     68  1.1.2.1     marc      struct cfdata *match;
     69  1.1.2.1     marc #endif
     70  1.1.2.1     marc      void *aux;
     71  1.1.2.1     marc {
     72  1.1.2.1     marc     /* if the autoconfiguration got this far, there's a socket here */
     73  1.1.2.1     marc 
     74  1.1.2.1     marc     return(1);
     75  1.1.2.1     marc }
     76  1.1.2.1     marc 
     77  1.1.2.1     marc void
     78  1.1.2.1     marc pcmcia_attach(parent, self, aux)
     79  1.1.2.1     marc 	struct device *parent, *self;
     80  1.1.2.1     marc 	void *aux;
     81  1.1.2.1     marc {
     82  1.1.2.1     marc     struct pcmciabus_attach_args *paa = (struct pcmciabus_attach_args *) aux;
     83  1.1.2.1     marc     struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
     84  1.1.2.1     marc 
     85  1.1.2.1     marc     printf("\n");
     86  1.1.2.1     marc 
     87  1.1.2.1     marc     sc->pct = paa->pct;
     88  1.1.2.1     marc     sc->pch = paa->pch;
     89  1.1.2.1     marc 
     90  1.1.2.1     marc     sc->ih = NULL;
     91  1.1.2.1     marc }
     92  1.1.2.1     marc 
     93  1.1.2.1     marc int
     94  1.1.2.1     marc pcmcia_attach_card(dev, iftype)
     95  1.1.2.1     marc      struct device *dev;
     96  1.1.2.1     marc      int *iftype;
     97  1.1.2.1     marc {
     98  1.1.2.1     marc     struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
     99  1.1.2.1     marc     struct pcmcia_function *pf;
    100  1.1.2.1     marc     struct pcmcia_attach_args paa;
    101  1.1.2.1     marc     int attached;
    102  1.1.2.1     marc 
    103  1.1.2.1     marc     pcmcia_read_cis(sc);
    104  1.1.2.1     marc 
    105  1.1.2.1     marc     /* bail now if the card has no functions, or if there was an error
    106  1.1.2.1     marc        in the cis. */
    107  1.1.2.1     marc 
    108  1.1.2.1     marc     if (sc->card.error)
    109  1.1.2.1     marc 	return(1);
    110  1.1.2.1     marc     if (!sc->card.pf_head.sqh_first)
    111  1.1.2.1     marc 	return(1);
    112  1.1.2.1     marc 
    113  1.1.2.1     marc     pcmcia_print_cis(sc);
    114  1.1.2.1     marc 
    115  1.1.2.1     marc     /* set the iftype to memory if this card has only one function,
    116  1.1.2.1     marc        and that is memory. */
    117  1.1.2.1     marc     if (sc->card.pf_head.sqh_first &&
    118  1.1.2.1     marc 	!sc->card.pf_head.sqh_first->pf_list.sqe_next &&
    119  1.1.2.1     marc 	(sc->card.pf_head.sqh_first->cfe_head.sqh_first->iftype ==
    120  1.1.2.1     marc 	 PCMCIA_IFTYPE_MEMORY))
    121  1.1.2.1     marc 	*iftype = PCMCIA_IFTYPE_MEMORY;
    122  1.1.2.1     marc     else
    123  1.1.2.1     marc 	*iftype = PCMCIA_IFTYPE_IO;
    124  1.1.2.1     marc 
    125  1.1.2.1     marc     attached = 0;
    126  1.1.2.1     marc 
    127  1.1.2.1     marc     for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
    128  1.1.2.1     marc 	if (pf->cfe_head.sqh_first == NULL)
    129  1.1.2.1     marc 	    continue;
    130  1.1.2.1     marc 
    131  1.1.2.1     marc 	pf->sc = sc;
    132  1.1.2.1     marc 	pf->cfe = NULL;
    133  1.1.2.1     marc 	pf->ih_fct = NULL;
    134  1.1.2.1     marc 	pf->ih_arg = NULL;
    135  1.1.2.1     marc     }
    136  1.1.2.1     marc 
    137  1.1.2.1     marc     for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
    138  1.1.2.1     marc 	if (pf->cfe_head.sqh_first == NULL)
    139  1.1.2.1     marc 	    continue;
    140  1.1.2.1     marc 
    141  1.1.2.1     marc 	paa.manufacturer = sc->card.manufacturer;
    142  1.1.2.1     marc 	paa.product = sc->card.product;
    143  1.1.2.1     marc 	paa.card = &sc->card;
    144  1.1.2.1     marc 	paa.pf = pf;
    145  1.1.2.1     marc 
    146  1.1.2.1     marc 	if (config_found_sm(&sc->dev, &paa, pcmcia_print, pcmcia_submatch)) {
    147  1.1.2.1     marc 	    attached++;
    148  1.1.2.1     marc 
    149  1.1.2.1     marc 	    DPRINTF(("%s: function %d CCR at %d offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
    150  1.1.2.1     marc 		     sc->dev.dv_xname, pf->number,
    151  1.1.2.1     marc 		     pf->ccr_window, pf->ccr_offset,
    152  1.1.2.1     marc 		     pcmcia_ccr_read(pf, 0x00),
    153  1.1.2.1     marc 		     pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
    154  1.1.2.1     marc 		     pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
    155  1.1.2.1     marc 		     pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
    156  1.1.2.1     marc 		     pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
    157  1.1.2.1     marc 	}
    158  1.1.2.1     marc     }
    159  1.1.2.1     marc 
    160  1.1.2.1     marc     return(attached?0:1);
    161  1.1.2.1     marc }
    162  1.1.2.1     marc 
    163  1.1.2.1     marc void
    164  1.1.2.1     marc pcmcia_detach_card(dev)
    165  1.1.2.1     marc      struct device *dev;
    166  1.1.2.1     marc {
    167  1.1.2.1     marc /*    struct pcmcia_softc *sc = (struct pcmcia_softc *) dev; */
    168  1.1.2.1     marc     /* don't do anything yet */
    169  1.1.2.1     marc }
    170  1.1.2.1     marc 
    171  1.1.2.1     marc int
    172  1.1.2.1     marc #ifdef __BROKEN_INDIRECT_CONFIG
    173  1.1.2.1     marc pcmcia_submatch(parent, match, aux)
    174  1.1.2.1     marc #else
    175  1.1.2.1     marc pcmcia_submatch(parent, cf, aux)
    176  1.1.2.1     marc #endif
    177  1.1.2.1     marc      struct device *parent;
    178  1.1.2.1     marc #ifdef __BROKEN_INDIRECT_CONFIG
    179  1.1.2.1     marc      void *match;
    180  1.1.2.1     marc #else
    181  1.1.2.1     marc      struct cfdata *cf;
    182  1.1.2.1     marc #endif
    183  1.1.2.1     marc      void *aux;
    184  1.1.2.1     marc {
    185  1.1.2.1     marc #ifdef __BROKEN_INDIRECT_CONFIG
    186  1.1.2.1     marc     struct cfdata *cf = match;
    187  1.1.2.1     marc #endif
    188  1.1.2.1     marc 
    189  1.1.2.1     marc     struct pcmcia_attach_args *paa = (struct pcmcia_attach_args *) aux;
    190  1.1.2.1     marc 
    191  1.1.2.1     marc     if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != paa->pf->number)
    192  1.1.2.1     marc 	return(0);
    193  1.1.2.1     marc 
    194  1.1.2.1     marc     return ((*cf->cf_attach->ca_match)(parent, cf, aux));
    195  1.1.2.1     marc }
    196  1.1.2.1     marc 
    197  1.1.2.1     marc int
    198  1.1.2.1     marc pcmcia_print(arg, pnp)
    199  1.1.2.1     marc      void *arg;
    200  1.1.2.1     marc      const char *pnp;
    201  1.1.2.1     marc {
    202  1.1.2.1     marc     struct pcmcia_attach_args *paa = (struct pcmcia_attach_args *) arg;
    203  1.1.2.1     marc 
    204  1.1.2.1     marc     if (pnp)
    205  1.1.2.1     marc 	printf("manufacturer code %x, product %x at %s",
    206  1.1.2.1     marc 	       paa->manufacturer, paa->product, pnp);
    207  1.1.2.1     marc 
    208  1.1.2.1     marc     printf(" function %d", paa->pf->number);
    209  1.1.2.1     marc 
    210  1.1.2.1     marc     return(UNCONF);
    211  1.1.2.1     marc }
    212  1.1.2.1     marc 
    213  1.1.2.1     marc int
    214  1.1.2.1     marc pcmcia_enable_function(pf, pcmcia, cfe)
    215  1.1.2.1     marc      struct pcmcia_function *pf;
    216  1.1.2.1     marc      struct device *pcmcia;
    217  1.1.2.1     marc      struct pcmcia_config_entry *cfe;
    218  1.1.2.1     marc {
    219  1.1.2.1     marc     struct pcmcia_function *tmp;
    220  1.1.2.1     marc     int reg;
    221  1.1.2.1     marc 
    222  1.1.2.1     marc     pf->cfe = cfe;
    223  1.1.2.1     marc 
    224  1.1.2.1     marc     /* it's possible for different functions' CCRs to be in the same
    225  1.1.2.1     marc        underlying page.  Check for that. */
    226  1.1.2.1     marc 
    227  1.1.2.1     marc     for (tmp = pf->sc->card.pf_head.sqh_first;
    228  1.1.2.1     marc 	 tmp;
    229  1.1.2.1     marc 	 tmp = tmp->pf_list.sqe_next) {
    230  1.1.2.1     marc 	if (tmp->cfe &&
    231  1.1.2.1     marc 	    (pf->ccr_base >= (tmp->ccr_base - tmp->ccr_offset)) &&
    232  1.1.2.1     marc 	    ((pf->ccr_base+PCMCIA_CCR_SIZE) <=
    233  1.1.2.1     marc 	     (tmp->ccr_base - tmp->ccr_offset + tmp->ccr_realsize))) {
    234  1.1.2.1     marc 	    pf->ccrt = tmp->ccrt;
    235  1.1.2.1     marc 	    pf->ccrh = tmp->ccrh;
    236  1.1.2.1     marc 	    pf->ccr_realsize = tmp->ccr_realsize;
    237  1.1.2.1     marc 
    238  1.1.2.1     marc 	    /* pf->ccr_offset =
    239  1.1.2.1     marc 	       (tmp->ccr_offset - tmp->ccr_base) + pf->ccr_base; */
    240  1.1.2.1     marc 	    pf->ccr_offset = (tmp->ccr_offset + pf->ccr_base) - tmp->ccr_base;
    241  1.1.2.1     marc 	    pf->ccr_window = tmp->ccr_window;
    242  1.1.2.1     marc 	    /* XXX when shutting down one function, it will be necessary
    243  1.1.2.1     marc 	       to make sure this window is no longer in use before
    244  1.1.2.1     marc 	       actually unmapping and freeing it */
    245  1.1.2.1     marc 	    break;
    246  1.1.2.1     marc 	}
    247  1.1.2.1     marc     }
    248  1.1.2.1     marc 
    249  1.1.2.1     marc     if (tmp == NULL) {
    250  1.1.2.1     marc 	if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->ccrt, &pf->ccrh,
    251  1.1.2.1     marc 			     &pf->ccr_mhandle, &pf->ccr_realsize))
    252  1.1.2.1     marc 	    return(1);
    253  1.1.2.1     marc 
    254  1.1.2.1     marc 	if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, PCMCIA_CCR_SIZE,
    255  1.1.2.1     marc 			   pf->ccrt, pf->ccrh, pf->ccr_base,
    256  1.1.2.1     marc 			   &pf->ccr_offset, &pf->ccr_window))
    257  1.1.2.1     marc 	    return(1);
    258  1.1.2.1     marc     }
    259  1.1.2.1     marc 
    260  1.1.2.1     marc     DPRINTF(("%s: function %d CCR at %d offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
    261  1.1.2.1     marc 	     pf->sc->dev.dv_xname, pf->number,
    262  1.1.2.1     marc 	     pf->ccr_window, pf->ccr_offset,
    263  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x00),
    264  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
    265  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
    266  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
    267  1.1.2.1     marc 	     pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
    268  1.1.2.1     marc 
    269  1.1.2.1     marc     reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
    270  1.1.2.1     marc     reg |= PCMCIA_CCR_OPTION_LEVIREQ;
    271  1.1.2.1     marc     if (pcmcia_mfc(pf->sc))
    272  1.1.2.1     marc 	reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
    273  1.1.2.1     marc     pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    274  1.1.2.1     marc 
    275  1.1.2.1     marc #if 0
    276  1.1.2.1     marc     reg = PCMCIA_CCR_STATUS_SIGCHG;
    277  1.1.2.1     marc #else
    278  1.1.2.1     marc     reg = 0;
    279  1.1.2.1     marc #endif
    280  1.1.2.1     marc     if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
    281  1.1.2.1     marc 	reg |= PCMCIA_CCR_STATUS_IOIS8;
    282  1.1.2.1     marc     if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
    283  1.1.2.1     marc 	reg |= PCMCIA_CCR_STATUS_AUDIO;
    284  1.1.2.1     marc     pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
    285  1.1.2.1     marc 
    286  1.1.2.1     marc     pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
    287  1.1.2.1     marc 
    288  1.1.2.1     marc     return(0);
    289  1.1.2.1     marc }
    290  1.1.2.1     marc 
    291  1.1.2.1     marc int
    292  1.1.2.1     marc pcmcia_io_map(pf, width, size, iot, ioh, windowp)
    293  1.1.2.1     marc      struct pcmcia_function *pf;
    294  1.1.2.1     marc      int width;
    295  1.1.2.1     marc      bus_size_t size;
    296  1.1.2.1     marc      bus_space_tag_t iot;
    297  1.1.2.1     marc      bus_space_handle_t ioh;
    298  1.1.2.1     marc      int *windowp;
    299  1.1.2.1     marc {
    300  1.1.2.1     marc     int reg;
    301  1.1.2.1     marc 
    302  1.1.2.1     marc     if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
    303  1.1.2.1     marc 			   width, size, iot, ioh, windowp))
    304  1.1.2.1     marc 	return(1);
    305  1.1.2.1     marc 
    306  1.1.2.1     marc     /* XXX in the multifunction multi-iospace-per-function case, this
    307  1.1.2.1     marc        needs to cooperate with io_alloc to make sure that the spaces
    308  1.1.2.1     marc        don't overlap, and that the ccr's are set correctly */
    309  1.1.2.1     marc 
    310  1.1.2.1     marc     if (pcmcia_mfc(pf->sc)) {
    311  1.1.2.1     marc 	pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0, ioh & 0xff);
    312  1.1.2.1     marc 	pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1, (ioh >> 8) & 0xff);
    313  1.1.2.1     marc 	pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, size - 1);
    314  1.1.2.1     marc 
    315  1.1.2.1     marc 	reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
    316  1.1.2.1     marc 	reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
    317  1.1.2.1     marc 	pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    318  1.1.2.1     marc     }
    319  1.1.2.1     marc 
    320  1.1.2.1     marc     return(0);
    321  1.1.2.1     marc }
    322  1.1.2.1     marc 
    323  1.1.2.1     marc void *
    324  1.1.2.1     marc pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
    325  1.1.2.1     marc      struct pcmcia_function *pf;
    326  1.1.2.1     marc      int ipl;
    327  1.1.2.1     marc      int (*ih_fct) __P((void *));
    328  1.1.2.1     marc      void *ih_arg;
    329  1.1.2.1     marc {
    330  1.1.2.4  thorpej     u_int16_t irqmask = pf->cfe_head.sqh_first->irqmask;
    331  1.1.2.1     marc     void *ret;
    332  1.1.2.1     marc 
    333  1.1.2.1     marc     /* behave differently if this is a multifunction card */
    334  1.1.2.1     marc 
    335  1.1.2.1     marc     if (pcmcia_mfc(pf->sc)) {
    336  1.1.2.1     marc 	int s, ihcnt, hiipl, reg;
    337  1.1.2.1     marc 	struct pcmcia_function *pf2;
    338  1.1.2.1     marc 
    339  1.1.2.1     marc 	/* mask all the ipl's which are already used by this card,
    340  1.1.2.1     marc 	   and find the highest ipl number (lowest priority) */
    341  1.1.2.1     marc 
    342  1.1.2.1     marc 	ihcnt = 0;
    343  1.1.2.1     marc 	s = 0; /* this is only here to keep the compipler happy */
    344  1.1.2.1     marc 	hiipl = 0; /* this is only here to keep the compipler happy */
    345  1.1.2.1     marc 
    346  1.1.2.1     marc 	for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
    347  1.1.2.1     marc 	     pf2 = pf2->pf_list.sqe_next) {
    348  1.1.2.1     marc 	    if (pf2->ih_fct) {
    349  1.1.2.1     marc 		if (!ihcnt) {
    350  1.1.2.1     marc 		    s = splraise(pf2->ih_ipl);
    351  1.1.2.1     marc 		    hiipl = pf2->ih_ipl;
    352  1.1.2.1     marc 		    ihcnt++;
    353  1.1.2.1     marc 		} else {
    354  1.1.2.1     marc 		    splraise(pf2->ih_ipl);
    355  1.1.2.1     marc 		    if (pf2->ih_ipl > hiipl)
    356  1.1.2.1     marc 			hiipl = pf2->ih_ipl;
    357  1.1.2.1     marc 		}
    358  1.1.2.1     marc 	    }
    359  1.1.2.1     marc 	}
    360  1.1.2.1     marc 
    361  1.1.2.1     marc 	/* set up the handler for the new function */
    362  1.1.2.1     marc 
    363  1.1.2.1     marc 	pf->ih_fct = ih_fct;
    364  1.1.2.1     marc 	pf->ih_arg = ih_arg;
    365  1.1.2.1     marc 	pf->ih_ipl = ipl;
    366  1.1.2.1     marc 
    367  1.1.2.1     marc 	/* establish the real interrupt, changing the ipl if necessary */
    368  1.1.2.1     marc 
    369  1.1.2.1     marc 	if (ihcnt == 0) {
    370  1.1.2.1     marc #ifdef DIAGNOSTIC
    371  1.1.2.1     marc 	    if (pf->sc->ih)
    372  1.1.2.1     marc 		panic("card has intr handler, but no function does");
    373  1.1.2.1     marc #endif
    374  1.1.2.1     marc 
    375  1.1.2.1     marc 	    pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    376  1.1.2.4  thorpej 						    irqmask, ipl,
    377  1.1.2.4  thorpej 						    pcmcia_card_intr, pf->sc);
    378  1.1.2.1     marc 	} else if (ipl > hiipl) {
    379  1.1.2.1     marc #ifdef DIAGNOSTIC
    380  1.1.2.1     marc 	    if (! pf->sc->ih)
    381  1.1.2.1     marc 		panic("functions have ih, but the card does not");
    382  1.1.2.1     marc #endif
    383  1.1.2.1     marc 
    384  1.1.2.1     marc 	    pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    385  1.1.2.1     marc 					  pf->sc->ih);
    386  1.1.2.1     marc 	    pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    387  1.1.2.4  thorpej 						    irqmask, ipl,
    388  1.1.2.4  thorpej 						    pcmcia_card_intr, pf->sc);
    389  1.1.2.1     marc 	}
    390  1.1.2.1     marc 
    391  1.1.2.1     marc 	if (ihcnt)
    392  1.1.2.1     marc 	    splx(s);
    393  1.1.2.1     marc 
    394  1.1.2.1     marc 	ret = pf->sc->ih;
    395  1.1.2.1     marc 
    396  1.1.2.1     marc 	if (ret) {
    397  1.1.2.1     marc 	    reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
    398  1.1.2.1     marc 	    reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
    399  1.1.2.1     marc 	    pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    400  1.1.2.1     marc 
    401  1.1.2.1     marc 	    reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    402  1.1.2.1     marc 	    reg |= PCMCIA_CCR_STATUS_INTRACK;
    403  1.1.2.1     marc 	    pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
    404  1.1.2.1     marc 	}
    405  1.1.2.1     marc     } else {
    406  1.1.2.1     marc 	ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    407  1.1.2.4  thorpej 					 irqmask, ipl, ih_fct, ih_arg);
    408  1.1.2.1     marc     }
    409  1.1.2.1     marc 
    410  1.1.2.1     marc     return(ret);
    411  1.1.2.1     marc }
    412  1.1.2.1     marc 
    413  1.1.2.1     marc void
    414  1.1.2.1     marc pcmcia_intr_disestablish(pf, ih)
    415  1.1.2.1     marc      struct pcmcia_function *pf;
    416  1.1.2.1     marc      void *ih;
    417  1.1.2.1     marc {
    418  1.1.2.4  thorpej     u_int16_t irqmask = pf->cfe_head.sqh_first->irqmask;
    419  1.1.2.4  thorpej 
    420  1.1.2.1     marc     /* behave differently if this is a multifunction card */
    421  1.1.2.1     marc 
    422  1.1.2.1     marc     if (pcmcia_mfc(pf->sc)) {
    423  1.1.2.1     marc 	int s, ihcnt, hiipl;
    424  1.1.2.1     marc 	struct pcmcia_function *pf2;
    425  1.1.2.1     marc 
    426  1.1.2.1     marc 	/* mask all the ipl's which are already used by this card,
    427  1.1.2.1     marc 	   and find the highest ipl number (lowest priority).  Skip
    428  1.1.2.1     marc 	   the current function. */
    429  1.1.2.1     marc 
    430  1.1.2.1     marc 	ihcnt = 0;
    431  1.1.2.1     marc 	s = 0; /* this is only here to keep the compipler happy */
    432  1.1.2.1     marc 	hiipl = 0; /* this is only here to keep the compipler happy */
    433  1.1.2.1     marc 
    434  1.1.2.1     marc 	for (pf2 = pf->sc->card.pf_head.sqh_first; pf2;
    435  1.1.2.1     marc 	     pf2 = pf2->pf_list.sqe_next) {
    436  1.1.2.1     marc 	    if (pf2 == pf)
    437  1.1.2.1     marc 		continue;
    438  1.1.2.1     marc 
    439  1.1.2.1     marc 	    if (pf2->ih_fct) {
    440  1.1.2.1     marc 		if (!ihcnt) {
    441  1.1.2.1     marc 		    s = splraise(pf2->ih_ipl);
    442  1.1.2.1     marc 		    hiipl = pf2->ih_ipl;
    443  1.1.2.1     marc 		    ihcnt++;
    444  1.1.2.1     marc 		} else {
    445  1.1.2.1     marc 		    splraise(pf2->ih_ipl);
    446  1.1.2.1     marc 		    if (pf2->ih_ipl > hiipl)
    447  1.1.2.1     marc 			hiipl = pf2->ih_ipl;
    448  1.1.2.1     marc 		}
    449  1.1.2.1     marc 	    }
    450  1.1.2.1     marc 	}
    451  1.1.2.1     marc 
    452  1.1.2.1     marc 	/* null out the handler for this function */
    453  1.1.2.1     marc 
    454  1.1.2.1     marc 	pf->ih_fct = NULL;
    455  1.1.2.1     marc 	pf->ih_arg = NULL;
    456  1.1.2.1     marc 
    457  1.1.2.1     marc 	/* if the ih being removed is lower priority than the lowest
    458  1.1.2.1     marc 	   priority remaining interrupt, up the priority. */
    459  1.1.2.1     marc 
    460  1.1.2.1     marc #ifdef DIAGNOSTIC
    461  1.1.2.1     marc 	if (ihcnt == 0) {
    462  1.1.2.1     marc 	    panic("can't remove a handler from a card which has none");
    463  1.1.2.1     marc 	} else
    464  1.1.2.1     marc #endif
    465  1.1.2.1     marc 	if (ihcnt == 1) {
    466  1.1.2.1     marc #ifdef DIAGNOSTIC
    467  1.1.2.1     marc 	    if (!pf->sc->ih)
    468  1.1.2.1     marc 		panic("disestablishing last function, but card has no ih");
    469  1.1.2.1     marc #endif
    470  1.1.2.1     marc 	    pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    471  1.1.2.1     marc 					  pf->sc->ih);
    472  1.1.2.1     marc 	    pf->sc->ih = NULL;
    473  1.1.2.1     marc 	} else if (pf->ih_ipl > hiipl) {
    474  1.1.2.1     marc #ifdef DIAGNOSTIC
    475  1.1.2.1     marc 	    if (!pf->sc->ih)
    476  1.1.2.1     marc 		panic("changing ih ipl, but card has no ih");
    477  1.1.2.1     marc #endif
    478  1.1.2.1     marc 	    pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    479  1.1.2.1     marc 					  pf->sc->ih);
    480  1.1.2.1     marc 	    pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    481  1.1.2.4  thorpej 						    irqmask, hiipl,
    482  1.1.2.4  thorpej 						    pcmcia_card_intr, pf->sc);
    483  1.1.2.1     marc 	}
    484  1.1.2.1     marc 
    485  1.1.2.1     marc 	if (ihcnt)
    486  1.1.2.1     marc 	    splx(s);
    487  1.1.2.1     marc     } else {
    488  1.1.2.1     marc 	pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
    489  1.1.2.1     marc     }
    490  1.1.2.1     marc }
    491  1.1.2.1     marc 
    492  1.1.2.1     marc int pcmcia_card_intr(arg)
    493  1.1.2.1     marc     void *arg;
    494  1.1.2.1     marc {
    495  1.1.2.1     marc     struct pcmcia_softc *sc = (struct pcmcia_softc *) arg;
    496  1.1.2.1     marc     struct pcmcia_function *pf;
    497  1.1.2.1     marc     int reg, ret, ret2;
    498  1.1.2.1     marc 
    499  1.1.2.1     marc     ret = 0;
    500  1.1.2.1     marc 
    501  1.1.2.1     marc     for (pf = sc->card.pf_head.sqh_first; pf; pf = pf->pf_list.sqe_next) {
    502  1.1.2.1     marc #if 0
    503  1.1.2.1     marc 	printf("%s: intr fct=%d physaddr=%lx cor=%02x csr=%02x pin=%02x",
    504  1.1.2.1     marc 	       sc->dev.dv_xname, pf->number,
    505  1.1.2.1     marc 	       pmap_extract(pmap_kernel(), (vm_offset_t) pf->ccrh) + pf->ccr_offset,
    506  1.1.2.1     marc 	       bus_space_read_1(pf->ccrt, pf->ccrh,
    507  1.1.2.1     marc 				pf->ccr_offset+PCMCIA_CCR_OPTION),
    508  1.1.2.1     marc 	       bus_space_read_1(pf->ccrt, pf->ccrh,
    509  1.1.2.1     marc 				pf->ccr_offset+PCMCIA_CCR_STATUS),
    510  1.1.2.1     marc 	       bus_space_read_1(pf->ccrt, pf->ccrh,
    511  1.1.2.1     marc 				pf->ccr_offset+PCMCIA_CCR_PIN));
    512  1.1.2.1     marc #endif
    513  1.1.2.1     marc 	if (pf->ih_fct &&
    514  1.1.2.1     marc 	    (pf->ccr_mask & (1<<(PCMCIA_CCR_STATUS/2)))) {
    515  1.1.2.1     marc 	    reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    516  1.1.2.1     marc 	    if (reg & PCMCIA_CCR_STATUS_INTR) {
    517  1.1.2.1     marc 		ret2 = (*pf->ih_fct)(pf->ih_arg);
    518  1.1.2.1     marc 		if (ret2 && !ret)
    519  1.1.2.1     marc 		    ret = ret2;
    520  1.1.2.1     marc 		reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    521  1.1.2.1     marc #if 0
    522  1.1.2.1     marc 		printf("; csr %02x->%02x", reg, reg & ~PCMCIA_CCR_STATUS_INTR);
    523  1.1.2.1     marc #endif
    524  1.1.2.1     marc 		pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
    525  1.1.2.1     marc 				 reg & ~PCMCIA_CCR_STATUS_INTR);
    526  1.1.2.1     marc 	    }
    527  1.1.2.1     marc 	}
    528  1.1.2.1     marc #if 0
    529  1.1.2.1     marc 	printf("\n");
    530  1.1.2.1     marc #endif
    531  1.1.2.1     marc     }
    532  1.1.2.1     marc 
    533  1.1.2.1     marc     return(ret);
    534  1.1.2.1     marc }
    535  1.1.2.1     marc 
    536