Home | History | Annotate | Line # | Download | only in pcmcia
pcmcia.c revision 1.51
      1 /*	$NetBSD: pcmcia.c,v 1.51 2004/08/09 19:33:07 mycroft Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2004 Charles M. Hannum.  All rights reserved.
      5  *
      6  * Redistribution and use in source and binary forms, with or without
      7  * modification, are permitted provided that the following conditions
      8  * are met:
      9  * 1. Redistributions of source code must retain the above copyright
     10  *    notice, this list of conditions and the following disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above copyright
     12  *    notice, this list of conditions and the following disclaimer in the
     13  *    documentation and/or other materials provided with the distribution.
     14  * 3. All advertising materials mentioning features or use of this software
     15  *    must display the following acknowledgement:
     16  *      This product includes software developed by Charles M. Hannum.
     17  * 4. The name of the author may not be used to endorse or promote products
     18  *    derived from this software without specific prior written permission.
     19  */
     20 
     21 /*
     22  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
     23  *
     24  * Redistribution and use in source and binary forms, with or without
     25  * modification, are permitted provided that the following conditions
     26  * are met:
     27  * 1. Redistributions of source code must retain the above copyright
     28  *    notice, this list of conditions and the following disclaimer.
     29  * 2. Redistributions in binary form must reproduce the above copyright
     30  *    notice, this list of conditions and the following disclaimer in the
     31  *    documentation and/or other materials provided with the distribution.
     32  * 3. All advertising materials mentioning features or use of this software
     33  *    must display the following acknowledgement:
     34  *	This product includes software developed by Marc Horowitz.
     35  * 4. The name of the author may not be used to endorse or promote products
     36  *    derived from this software without specific prior written permission.
     37  *
     38  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     39  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     40  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     41  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     42  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     43  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     44  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     45  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     47  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     48  */
     49 
     50 #include <sys/cdefs.h>
     51 __KERNEL_RCSID(0, "$NetBSD: pcmcia.c,v 1.51 2004/08/09 19:33:07 mycroft Exp $");
     52 
     53 #include "opt_pcmciaverbose.h"
     54 
     55 #include <sys/param.h>
     56 #include <sys/systm.h>
     57 #include <sys/device.h>
     58 
     59 #include <dev/pcmcia/pcmciareg.h>
     60 #include <dev/pcmcia/pcmciachip.h>
     61 #include <dev/pcmcia/pcmciavar.h>
     62 #ifdef IT8368E_LEGACY_MODE /* XXX -uch */
     63 #include <arch/hpcmips/dev/it8368var.h>
     64 #endif
     65 
     66 #include "locators.h"
     67 
     68 #ifdef PCMCIADEBUG
     69 int	pcmcia_debug = 0;
     70 #define	DPRINTF(arg) if (pcmcia_debug) printf arg
     71 int	pcmciaintr_debug = 0;
     72 /* this is done this way to avoid doing lots of conditionals
     73    at interrupt level.  */
     74 #define PCMCIA_CARD_INTR (pcmciaintr_debug?pcmcia_card_intrdebug:pcmcia_card_intr)
     75 #else
     76 #define	DPRINTF(arg)
     77 #define PCMCIA_CARD_INTR (pcmcia_card_intr)
     78 #endif
     79 
     80 #ifdef PCMCIAVERBOSE
     81 int	pcmcia_verbose = 1;
     82 #else
     83 int	pcmcia_verbose = 0;
     84 #endif
     85 
     86 int	pcmcia_match __P((struct device *, struct cfdata *, void *));
     87 int	pcmcia_submatch __P((struct device *, struct cfdata *, void *));
     88 void	pcmcia_attach __P((struct device *, struct device *, void *));
     89 int	pcmcia_print __P((void *, const char *));
     90 
     91 int pcmcia_card_intr __P((void *));
     92 #ifdef PCMCIADEBUG
     93 int pcmcia_card_intrdebug __P((void *));
     94 #endif
     95 
     96 CFATTACH_DECL(pcmcia, sizeof(struct pcmcia_softc),
     97     pcmcia_match, pcmcia_attach, NULL, NULL);
     98 
     99 int
    100 pcmcia_ccr_read(pf, ccr)
    101 	struct pcmcia_function *pf;
    102 	int ccr;
    103 {
    104 
    105 	return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
    106 	    pf->pf_ccr_offset + ccr * 2));
    107 }
    108 
    109 void
    110 pcmcia_ccr_write(pf, ccr, val)
    111 	struct pcmcia_function *pf;
    112 	int ccr;
    113 	int val;
    114 {
    115 
    116 	if (pf->ccr_mask & (1 << ccr)) {
    117 		bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
    118 		    pf->pf_ccr_offset + ccr * 2, val);
    119 	}
    120 }
    121 
    122 int
    123 pcmcia_match(parent, match, aux)
    124 	struct device *parent;
    125 	struct cfdata *match;
    126 	void *aux;
    127 {
    128 	struct pcmciabus_attach_args *paa = aux;
    129 
    130 	if (strcmp(paa->paa_busname, match->cf_name)) {
    131 	    return 0;
    132 	}
    133 	/* if the autoconfiguration got this far, there's a socket here */
    134 	return (1);
    135 }
    136 
    137 void
    138 pcmcia_attach(parent, self, aux)
    139 	struct device *parent, *self;
    140 	void *aux;
    141 {
    142 	struct pcmciabus_attach_args *paa = aux;
    143 	struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
    144 
    145 	printf("\n");
    146 
    147 	sc->pct = paa->pct;
    148 	sc->pch = paa->pch;
    149 	sc->iobase = paa->iobase;
    150 	sc->iosize = paa->iosize;
    151 
    152 	sc->ih = NULL;
    153 }
    154 
    155 int
    156 pcmcia_card_attach(dev)
    157 	struct device *dev;
    158 {
    159 	struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
    160 	struct pcmcia_function *pf;
    161 	struct pcmcia_attach_args paa;
    162 	int attached;
    163 
    164 	/*
    165 	 * this is here so that when socket_enable calls gettype, trt happens
    166 	 */
    167 	SIMPLEQ_FIRST(&sc->card.pf_head) = NULL;
    168 
    169 	pcmcia_chip_socket_enable(sc->pct, sc->pch);
    170 
    171 	pcmcia_read_cis(sc);
    172 
    173 	pcmcia_chip_socket_disable(sc->pct, sc->pch);
    174 
    175 	pcmcia_check_cis_quirks(sc);
    176 
    177 	/*
    178 	 * bail now if the card has no functions, or if there was an error in
    179 	 * the cis.
    180 	 */
    181 
    182 	if (sc->card.error)
    183 		return (1);
    184 	if (SIMPLEQ_EMPTY(&sc->card.pf_head))
    185 		return (1);
    186 
    187 	if (pcmcia_verbose)
    188 		pcmcia_print_cis(sc);
    189 
    190 	attached = 0;
    191 
    192 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    193 		if (SIMPLEQ_EMPTY(&pf->cfe_head))
    194 			continue;
    195 
    196 #ifdef DIAGNOSTIC
    197 		if (pf->child != NULL) {
    198 			printf("%s: %s still attached to function %d!\n",
    199 			    sc->dev.dv_xname, pf->child->dv_xname,
    200 			    pf->number);
    201 			panic("pcmcia_card_attach");
    202 		}
    203 #endif
    204 		pf->sc = sc;
    205 		pf->child = NULL;
    206 		pf->cfe = NULL;
    207 		pf->ih_fct = NULL;
    208 		pf->ih_arg = NULL;
    209 	}
    210 
    211 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    212 		if (SIMPLEQ_EMPTY(&pf->cfe_head))
    213 			continue;
    214 
    215 		paa.manufacturer = sc->card.manufacturer;
    216 		paa.product = sc->card.product;
    217 		paa.card = &sc->card;
    218 		paa.pf = pf;
    219 
    220 		if ((pf->child = config_found_sm(&sc->dev, &paa, pcmcia_print,
    221 		    pcmcia_submatch)) != NULL)
    222 			attached++;
    223 	}
    224 
    225 	return (attached ? 0 : 1);
    226 }
    227 
    228 void
    229 pcmcia_card_detach(dev, flags)
    230 	struct device *dev;
    231 	int flags;		/* DETACH_* flags */
    232 {
    233 	struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
    234 	struct pcmcia_function *pf;
    235 	int error;
    236 
    237 	/*
    238 	 * We are running on either the PCMCIA socket's event thread
    239 	 * or in user context detaching a device by user request.
    240 	 */
    241 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    242 		if (SIMPLEQ_EMPTY(&pf->cfe_head))
    243 			continue;
    244 		if (pf->child == NULL)
    245 			continue;
    246 		DPRINTF(("%s: detaching %s (function %d)\n",
    247 		    sc->dev.dv_xname, pf->child->dv_xname, pf->number));
    248 		if ((error = config_detach(pf->child, flags)) != 0) {
    249 			printf("%s: error %d detaching %s (function %d)\n",
    250 			    sc->dev.dv_xname, error, pf->child->dv_xname,
    251 			    pf->number);
    252 		} else
    253 			pf->child = NULL;
    254 	}
    255 }
    256 
    257 void
    258 pcmcia_card_deactivate(dev)
    259 	struct device *dev;
    260 {
    261 	struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
    262 	struct pcmcia_function *pf;
    263 
    264 	/*
    265 	 * We're in the chip's card removal interrupt handler.
    266 	 * Deactivate the child driver.  The PCMCIA socket's
    267 	 * event thread will run later to finish the detach.
    268 	 */
    269 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    270 		if (SIMPLEQ_EMPTY(&pf->cfe_head))
    271 			continue;
    272 		if (pf->child == NULL)
    273 			continue;
    274 		DPRINTF(("%s: deactivating %s (function %d)\n",
    275 		    sc->dev.dv_xname, pf->child->dv_xname, pf->number));
    276 		config_deactivate(pf->child);
    277 	}
    278 }
    279 
    280 int
    281 pcmcia_submatch(parent, cf, aux)
    282 	struct device *parent;
    283 	struct cfdata *cf;
    284 	void *aux;
    285 {
    286 	struct pcmcia_attach_args *paa = aux;
    287 
    288 	if (cf->cf_loc[PCMCIACF_FUNCTION] != PCMCIACF_FUNCTION_DEFAULT &&
    289 	    cf->cf_loc[PCMCIACF_FUNCTION] != paa->pf->number)
    290 		return (0);
    291 
    292 	return (config_match(parent, cf, aux));
    293 }
    294 
    295 int
    296 pcmcia_print(arg, pnp)
    297 	void *arg;
    298 	const char *pnp;
    299 {
    300 	struct pcmcia_attach_args *pa = arg;
    301 	struct pcmcia_softc *sc = pa->pf->sc;
    302 	struct pcmcia_card *card = &sc->card;
    303 	char devinfo[256];
    304 
    305 	if (pnp)
    306 		aprint_normal("%s", pnp);
    307 
    308 	pcmcia_devinfo(card, !!pnp, devinfo, sizeof(devinfo));
    309 
    310 	aprint_normal(" function %d: %s", pa->pf->number, devinfo);
    311 
    312 	return (UNCONF);
    313 }
    314 
    315 void
    316 pcmcia_devinfo(card, showhex, cp, cplen)
    317 	struct pcmcia_card *card;
    318 	int showhex;
    319 	char *cp;
    320 	size_t cplen;
    321 {
    322 	int i, n;
    323 
    324 	if (cplen > 1) {
    325 		*cp++ = '<';
    326 		*cp = '\0';
    327 		cplen--;
    328 	}
    329 
    330 	for (i = 0; i < 4 && card->cis1_info[i] != NULL && cplen > 1; i++) {
    331 		n = snprintf(cp, cplen, "%s%s", i ? ", " : "",
    332 		        card->cis1_info[i]);
    333 		cp += n;
    334 		if (cplen < n)
    335 			return;
    336 		cplen -= n;
    337 	}
    338 
    339 	if (cplen > 1) {
    340 		*cp++ = '>';
    341 		*cp = '\0';
    342 		cplen--;
    343 	}
    344 
    345 	if (showhex && cplen > 1)
    346 		snprintf(cp, cplen, " (manufacturer 0x%04x, product 0x%04x)",
    347 		    card->manufacturer, card->product);
    348 }
    349 
    350 const struct pcmcia_product *
    351 pcmcia_product_lookup(pa, tab, ent_size, matchfn)
    352 	struct pcmcia_attach_args *pa;
    353 	const struct pcmcia_product *tab;
    354 	size_t ent_size;
    355 	pcmcia_product_match_fn matchfn;
    356 {
    357         const struct pcmcia_product *ent;
    358 	int matches;
    359 
    360 #ifdef DIAGNOSTIC
    361 	if (sizeof *ent > ent_size)
    362 		panic("pcmcia_product_lookup: bogus ent_size %ld",
    363 		      (long) ent_size);
    364 #endif
    365 
    366         for (ent = tab;
    367 	    ent->pp_name != NULL;
    368 	    ent = (const struct pcmcia_product *)
    369 	      ((const char *)ent + ent_size)) {
    370 
    371 		/* see if it matches vendor/product/function */
    372 		matches = (pa->manufacturer == ent->pp_vendor) &&
    373 		    (pa->product == ent->pp_product) &&
    374 		    (pa->pf->number == ent->pp_expfunc);
    375 
    376 		/* if a separate match function is given, let it override */
    377 		if (matchfn != NULL)
    378 			matches = (*matchfn)(pa, ent, matches);
    379 
    380 		if (matches)
    381                         return (ent);
    382         }
    383         return (NULL);
    384 }
    385 
    386 int
    387 pcmcia_card_gettype(dev)
    388 	struct device  *dev;
    389 {
    390 	struct pcmcia_softc *sc = (struct pcmcia_softc *)dev;
    391 	struct pcmcia_function *pf;
    392 
    393 	/*
    394 	 * set the iftype to memory if this card has no functions (not yet
    395 	 * probed), or only one function, and that is not initialized yet or
    396 	 * that is memory.
    397 	 */
    398 	pf = SIMPLEQ_FIRST(&sc->card.pf_head);
    399 	if (pf == NULL ||
    400 	    (SIMPLEQ_NEXT(pf, pf_list) == NULL &&
    401 	    (pf->cfe == NULL || pf->cfe->iftype == PCMCIA_IFTYPE_MEMORY)))
    402 		return (PCMCIA_IFTYPE_MEMORY);
    403 	else
    404 		return (PCMCIA_IFTYPE_IO);
    405 }
    406 
    407 /*
    408  * Initialize a PCMCIA function.  May be called as long as the function is
    409  * disabled.
    410  */
    411 void
    412 pcmcia_function_init(pf, cfe)
    413 	struct pcmcia_function *pf;
    414 	struct pcmcia_config_entry *cfe;
    415 {
    416 	if (pf->pf_flags & PFF_ENABLED)
    417 		panic("pcmcia_function_init: function is enabled");
    418 
    419 	/* Remember which configuration entry we are using. */
    420 	pf->cfe = cfe;
    421 }
    422 
    423 void pcmcia_socket_enable(dev)
    424 	struct device *dev;
    425 {
    426 	struct pcmcia_softc *sc = (void *)dev;
    427 
    428 	pcmcia_chip_socket_enable(sc->pct, sc->pch);
    429 }
    430 
    431 void pcmcia_socket_disable(dev)
    432 	struct device *dev;
    433 {
    434 	struct pcmcia_softc *sc = (void *)dev;
    435 
    436 	pcmcia_chip_socket_disable(sc->pct, sc->pch);
    437 }
    438 
    439 /* Enable a PCMCIA function */
    440 int
    441 pcmcia_function_enable(pf)
    442 	struct pcmcia_function *pf;
    443 {
    444 	struct pcmcia_function *tmp;
    445 	int reg;
    446 
    447 	if (pf->cfe == NULL)
    448 		panic("pcmcia_function_enable: function not initialized");
    449 
    450 	/*
    451 	 * Increase the reference count on the socket, enabling power, if
    452 	 * necessary.
    453 	 */
    454 	if (pf->sc->sc_enabled_count++ == 0)
    455 		pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
    456 	DPRINTF(("%s: ++enabled_count = %d\n", pf->sc->dev.dv_xname,
    457 		 pf->sc->sc_enabled_count));
    458 
    459 	if (pf->pf_flags & PFF_ENABLED) {
    460 		/*
    461 		 * Don't do anything if we're already enabled.
    462 		 */
    463 		return (0);
    464 	}
    465 
    466 	/*
    467 	 * it's possible for different functions' CCRs to be in the same
    468 	 * underlying page.  Check for that.
    469 	 */
    470 
    471 	SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
    472 		if ((tmp->pf_flags & PFF_ENABLED) &&
    473 		    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
    474 		    ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
    475 		     (tmp->ccr_base - tmp->pf_ccr_offset +
    476 		      tmp->pf_ccr_realsize))) {
    477 			pf->pf_ccrt = tmp->pf_ccrt;
    478 			pf->pf_ccrh = tmp->pf_ccrh;
    479 			pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
    480 
    481 			/*
    482 			 * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
    483 			 * tmp->ccr_base) + pf->ccr_base;
    484 			 */
    485 			pf->pf_ccr_offset =
    486 			    (tmp->pf_ccr_offset + pf->ccr_base) -
    487 			    tmp->ccr_base;
    488 			pf->pf_ccr_window = tmp->pf_ccr_window;
    489 			break;
    490 		}
    491 	}
    492 
    493 	if (tmp == NULL) {
    494 		if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
    495 			goto bad;
    496 
    497 		if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
    498 		    PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
    499 		    &pf->pf_ccr_window)) {
    500 			pcmcia_mem_free(pf, &pf->pf_pcmh);
    501 			goto bad;
    502 		}
    503 	}
    504 
    505 	if (pcmcia_mfc(pf->sc)) {
    506 		pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
    507 				 (pf->pf_mfc_iobase[0] >> 0) & 0xff);
    508 		pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
    509 				 (pf->pf_mfc_iobase[0] >> 8) & 0xff);
    510 		pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
    511 				 (pf->pf_mfc_iobase[1] >> 0) & 0xff);
    512 		pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
    513 				 (pf->pf_mfc_iobase[1] >> 8) & 0xff);
    514 		pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, pf->pf_mfc_iomask);
    515 	}
    516 
    517 	reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
    518 	reg |= PCMCIA_CCR_OPTION_LEVIREQ;
    519 	if (pcmcia_mfc(pf->sc)) {
    520 		reg |= (PCMCIA_CCR_OPTION_FUNC_ENABLE |
    521 			PCMCIA_CCR_OPTION_ADDR_DECODE);
    522 		if (pf->ih_fct)
    523 			reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
    524 
    525 	}
    526 	pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    527 
    528 	reg = 0;
    529 	if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
    530 		reg |= PCMCIA_CCR_STATUS_IOIS8;
    531 	if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
    532 		reg |= PCMCIA_CCR_STATUS_AUDIO;
    533 	pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
    534 
    535 	pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
    536 
    537 #ifdef PCMCIADEBUG
    538 	if (pcmcia_debug) {
    539 		SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
    540 			printf("%s: function %d CCR at %d offset %lx: "
    541 			       "%x %x %x %x, %x %x %x %x, %x\n",
    542 			       tmp->sc->dev.dv_xname, tmp->number,
    543 			       tmp->pf_ccr_window,
    544 			       (unsigned long) tmp->pf_ccr_offset,
    545 			       pcmcia_ccr_read(tmp, 0),
    546 			       pcmcia_ccr_read(tmp, 1),
    547 			       pcmcia_ccr_read(tmp, 2),
    548 			       pcmcia_ccr_read(tmp, 3),
    549 
    550 			       pcmcia_ccr_read(tmp, 5),
    551 			       pcmcia_ccr_read(tmp, 6),
    552 			       pcmcia_ccr_read(tmp, 7),
    553 			       pcmcia_ccr_read(tmp, 8),
    554 
    555 			       pcmcia_ccr_read(tmp, 9));
    556 		}
    557 	}
    558 #endif
    559 
    560 	pf->pf_flags |= PFF_ENABLED;
    561 
    562 #ifdef IT8368E_LEGACY_MODE
    563 	/* return to I/O mode */
    564 	it8368_mode(pf, IT8368_IO_MODE, IT8368_WIDTH_16);
    565 #endif
    566 	return (0);
    567 
    568  bad:
    569 	/*
    570 	 * Decrement the reference count, and power down the socket, if
    571 	 * necessary.
    572 	 */
    573 	if (--pf->sc->sc_enabled_count == 0)
    574 		pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
    575 	DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
    576 		 pf->sc->sc_enabled_count));
    577 
    578 	return (1);
    579 }
    580 
    581 /* Disable PCMCIA function. */
    582 void
    583 pcmcia_function_disable(pf)
    584 	struct pcmcia_function *pf;
    585 {
    586 	struct pcmcia_function *tmp;
    587 	int reg;
    588 
    589 	if (pf->cfe == NULL)
    590 		panic("pcmcia_function_enable: function not initialized");
    591 
    592 	if ((pf->pf_flags & PFF_ENABLED) == 0) {
    593 		/*
    594 		 * Don't do anything but decrement if we're already disabled.
    595 		 */
    596 		goto out;
    597 	}
    598 
    599 	if (pcmcia_mfc(pf->sc)) {
    600 		reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
    601 		reg &= ~(PCMCIA_CCR_OPTION_FUNC_ENABLE|
    602 			 PCMCIA_CCR_OPTION_ADDR_DECODE|
    603 		         PCMCIA_CCR_OPTION_IREQ_ENABLE);
    604 		pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    605 	}
    606 
    607 	/*
    608 	 * it's possible for different functions' CCRs to be in the same
    609 	 * underlying page.  Check for that.  Note we mark us as disabled
    610 	 * first to avoid matching ourself.
    611 	 */
    612 
    613 	pf->pf_flags &= ~PFF_ENABLED;
    614 	SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
    615 		if ((tmp->pf_flags & PFF_ENABLED) &&
    616 		    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
    617 		    ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
    618 		(tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
    619 			break;
    620 	}
    621 
    622 	/* Not used by anyone else; unmap the CCR. */
    623 	if (tmp == NULL) {
    624 		pcmcia_mem_unmap(pf, pf->pf_ccr_window);
    625 		pcmcia_mem_free(pf, &pf->pf_pcmh);
    626 	}
    627 
    628 out:
    629 	/*
    630 	 * Decrement the reference count, and power down the socket, if
    631 	 * necessary.
    632 	 */
    633 	if (--pf->sc->sc_enabled_count == 0)
    634 		pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
    635 	DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
    636 		 pf->sc->sc_enabled_count));
    637 }
    638 
    639 int
    640 pcmcia_io_map(pf, width, pcihp, windowp)
    641 	struct pcmcia_function *pf;
    642 	int width;
    643 	struct pcmcia_io_handle *pcihp;
    644 	int *windowp;
    645 {
    646 	int error;
    647 
    648 	if (pf->pf_flags & PFF_ENABLED)
    649 		printf("pcmcia_io_map: function is enabled!\n");
    650 
    651 	error = pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
    652 	    width, 0, pcihp->size, pcihp, windowp);
    653 	if (error)
    654 		return (error);
    655 
    656 	/*
    657 	 * XXX in the multifunction multi-iospace-per-function case, this
    658 	 * needs to cooperate with io_alloc to make sure that the spaces
    659 	 * don't overlap, and that the ccr's are set correctly
    660 	 */
    661 
    662 	if (pcmcia_mfc(pf->sc)) {
    663 		int win;
    664 		long iomask;
    665 
    666 		/* round up to nearest (2^n)-1 */
    667 		for (iomask = 1; iomask < pcihp->size; iomask <<= 1)
    668 			;
    669 		iomask--;
    670 
    671 		win = pf->pf_mfc_windows;
    672 		KASSERT(win < 2);
    673 printf("win %d = addr %lx size %lx iomask %lx\n", win, (long)pcihp->addr, (long)pcihp->size, (long)iomask);
    674 		pf->pf_mfc_iobase[win] = pcihp->addr;
    675 		pf->pf_mfc_iomask = iomask;
    676 	}
    677 
    678 	return (0);
    679 }
    680 
    681 void
    682 pcmcia_io_unmap(pf, window)
    683 	struct pcmcia_function *pf;
    684 	int window;
    685 {
    686 
    687 	if (pf->pf_flags & PFF_ENABLED)
    688 		printf("pcmcia_io_unmap: function is enabled!\n");
    689 
    690 	if (pcmcia_mfc(pf->sc)) {
    691 		/*
    692 		 * Don't bother trying to unmap windows in the CCR here,
    693 		 * because we generally get called when a card has been
    694 		 * ejected, and the CCR isn't there any more.
    695 		 */
    696 		--pf->pf_mfc_windows;
    697 	}
    698 
    699 	pcmcia_chip_io_unmap(pf->sc->pct, pf->sc->pch, window);
    700 }
    701 
    702 void *
    703 pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
    704 	struct pcmcia_function *pf;
    705 	int ipl;
    706 	int (*ih_fct) __P((void *));
    707 	void *ih_arg;
    708 {
    709 	void *ret;
    710 
    711 	if (pf->pf_flags & PFF_ENABLED)
    712 		printf("pcmcia_intr_establish: function is enabled!\n");
    713 
    714 	/* behave differently if this is a multifunction card */
    715 	if (pcmcia_mfc(pf->sc)) {
    716 		int s, ihcnt, hiipl;
    717 		struct pcmcia_function *pf2;
    718 
    719 		/*
    720 		 * mask all the ipl's which are already used by this card,
    721 		 * and find the highest ipl number (lowest priority)
    722 		 */
    723 
    724 		ihcnt = 0;
    725 		s = 0;		/* this is only here to keep the compiler
    726 				   happy */
    727 		hiipl = 0;	/* this is only here to keep the compiler
    728 				   happy */
    729 
    730 		SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
    731 			if (pf2->ih_fct) {
    732 				DPRINTF(("%s: function %d has ih_fct %p\n",
    733 					 pf->sc->dev.dv_xname, pf2->number,
    734 					 pf2->ih_fct));
    735 
    736 				if (ihcnt == 0) {
    737 					hiipl = pf2->ih_ipl;
    738 				} else {
    739 					if (pf2->ih_ipl > hiipl)
    740 						hiipl = pf2->ih_ipl;
    741 				}
    742 
    743 				ihcnt++;
    744 			}
    745 		}
    746 
    747 		/*
    748 		 * establish the real interrupt, changing the ipl if
    749 		 * necessary
    750 		 */
    751 
    752 		if (ihcnt == 0) {
    753 #ifdef DIAGNOSTIC
    754 			if (pf->sc->ih != NULL)
    755 				panic("card has intr handler, but no function does");
    756 #endif
    757 			s = splhigh();
    758 
    759 			/* set up the handler for the new function */
    760 
    761 			pf->ih_fct = ih_fct;
    762 			pf->ih_arg = ih_arg;
    763 			pf->ih_ipl = ipl;
    764 
    765 			pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
    766 			    pf->sc->pch, pf, ipl, PCMCIA_CARD_INTR, pf->sc);
    767 			splx(s);
    768 		} else if (ipl > hiipl) {
    769 #ifdef DIAGNOSTIC
    770 			if (pf->sc->ih == NULL)
    771 				panic("functions have ih, but the card does not");
    772 #endif
    773 
    774 			/* XXX need #ifdef for splserial on x86 */
    775 			s = splhigh();
    776 
    777 			pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    778 						      pf->sc->ih);
    779 
    780 			/* set up the handler for the new function */
    781 			pf->ih_fct = ih_fct;
    782 			pf->ih_arg = ih_arg;
    783 			pf->ih_ipl = ipl;
    784 
    785 			pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
    786 			    pf->sc->pch, pf, ipl, PCMCIA_CARD_INTR, pf->sc);
    787 
    788 			splx(s);
    789 		} else {
    790 			s = splhigh();
    791 
    792 			/* set up the handler for the new function */
    793 
    794 			pf->ih_fct = ih_fct;
    795 			pf->ih_arg = ih_arg;
    796 			pf->ih_ipl = ipl;
    797 
    798 			splx(s);
    799 		}
    800 
    801 		ret = pf->sc->ih;
    802 	} else {
    803 		ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    804 		    pf, ipl, ih_fct, ih_arg);
    805 	}
    806 
    807 	return (ret);
    808 }
    809 
    810 void
    811 pcmcia_intr_disestablish(pf, ih)
    812 	struct pcmcia_function *pf;
    813 	void *ih;
    814 {
    815 	if (pf->pf_flags & PFF_ENABLED)
    816 		printf("pcmcia_intr_disestablish: function is enabled!\n");
    817 
    818 	/* behave differently if this is a multifunction card */
    819 	if (pcmcia_mfc(pf->sc)) {
    820 		int s, ihcnt, hiipl;
    821 		struct pcmcia_function *pf2;
    822 
    823 		/*
    824 		 * mask all the ipl's which are already used by this card,
    825 		 * and find the highest ipl number (lowest priority).  Skip
    826 		 * the current function.
    827 		 */
    828 
    829 		ihcnt = 0;
    830 		s = 0;		/* avoid compiler warning */
    831 		hiipl = 0;	/* avoid compiler warning */
    832 
    833 		SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
    834 			if (pf2 == pf)
    835 				continue;
    836 
    837 			if (pf2->ih_fct) {
    838 				if (ihcnt == 0) {
    839 					hiipl = pf2->ih_ipl;
    840 				} else {
    841 					if (pf2->ih_ipl > hiipl)
    842 						hiipl = pf2->ih_ipl;
    843 				}
    844 				ihcnt++;
    845 			}
    846 		}
    847 
    848 		/*
    849 		 * If the ih being removed is lower priority than the lowest
    850 		 * priority remaining interrupt, up the priority.
    851 		 */
    852 
    853 		/*
    854 		 * ihcnt is the number of interrupt handlers *not* including
    855 		 * the one about to be removed.
    856 		 */
    857 
    858 		if (ihcnt == 0) {
    859 #ifdef DIAGNOSTIC
    860 			if (pf->sc->ih == NULL)
    861 				panic("disestablishing last function, but card has no ih");
    862 #endif
    863 			pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    864 			    pf->sc->ih);
    865 
    866 			pf->ih_fct = NULL;
    867 			pf->ih_arg = NULL;
    868 
    869 			pf->sc->ih = NULL;
    870 		} else if (pf->ih_ipl > hiipl) {
    871 #ifdef DIAGNOSTIC
    872 			if (pf->sc->ih == NULL)
    873 				panic("changing ih ipl, but card has no ih");
    874 #endif
    875 			/* XXX need #ifdef for splserial on x86 */
    876 			s = splhigh();
    877 
    878 			pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    879 			    pf->sc->ih);
    880 			pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
    881 			    pf->sc->pch, pf, hiipl, PCMCIA_CARD_INTR, pf->sc);
    882 
    883 			/* null out the handler for this function */
    884 
    885 			pf->ih_fct = NULL;
    886 			pf->ih_arg = NULL;
    887 
    888 			splx(s);
    889 		} else {
    890 			s = splhigh();
    891 
    892 			pf->ih_fct = NULL;
    893 			pf->ih_arg = NULL;
    894 
    895 			splx(s);
    896 		}
    897 	} else {
    898 		pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
    899 	}
    900 }
    901 
    902 int
    903 pcmcia_card_intr(arg)
    904 	void *arg;
    905 {
    906 	struct pcmcia_softc *sc = arg;
    907 	struct pcmcia_function *pf;
    908 	int reg, ret;
    909 
    910 	ret = 0;
    911 
    912 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    913 		if ((pf->pf_flags & PFF_ENABLED) == 0 ||
    914 		    pf->ih_fct == NULL)
    915 			continue;
    916 		if (pf->ccr_mask & (1 << PCMCIA_CCR_STATUS)) {
    917 			reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    918 			if (reg & PCMCIA_CCR_STATUS_INTR) {
    919 				ret |= (*pf->ih_fct)(pf->ih_arg);
    920 				if (reg & PCMCIA_CCR_STATUS_INTRACK)
    921 					pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
    922 					    reg & ~PCMCIA_CCR_STATUS_INTR);
    923 			}
    924 		} else
    925 			ret |= (*pf->ih_fct)(pf->ih_arg);
    926 	}
    927 
    928 	return (ret);
    929 }
    930 
    931 #ifdef PCMCIADEBUG
    932 int
    933 pcmcia_card_intrdebug(arg)
    934 	void *arg;
    935 {
    936 	struct pcmcia_softc *sc = arg;
    937 	struct pcmcia_function *pf;
    938 	int reg, ret;
    939 
    940 	ret = 0;
    941 
    942 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    943 		printf("%s: intr flags=%x fct=%d cor=%02x csr=%02x pin=%02x",
    944 		       sc->dev.dv_xname, pf->pf_flags, pf->number,
    945 		       pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION),
    946 		       pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS),
    947 		       pcmcia_ccr_read(pf, PCMCIA_CCR_PIN));
    948 		if ((pf->pf_flags & PFF_ENABLED) == 0 ||
    949 		    pf->ih_fct == NULL) {
    950 			printf("\n");
    951 			continue;
    952 		}
    953 		if (pf->ccr_mask & (1 << PCMCIA_CCR_STATUS)) {
    954 			reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    955 			if (reg & PCMCIA_CCR_STATUS_INTR) {
    956 				ret |= (*pf->ih_fct)(pf->ih_arg);
    957 				if (reg & PCMCIA_CCR_STATUS_INTRACK) {
    958 					printf("; csr %02x->%02x",
    959 					    reg, reg & ~PCMCIA_CCR_STATUS_INTR);
    960 					pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
    961 					    reg & ~PCMCIA_CCR_STATUS_INTR);
    962 				}
    963 			}
    964 		} else
    965 			ret |= (*pf->ih_fct)(pf->ih_arg);
    966 		printf("\n");
    967 	}
    968 
    969 	return (ret);
    970 }
    971 #endif
    972