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