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