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