Home | History | Annotate | Line # | Download | only in pcmcia
pcmcia.c revision 1.48
      1 /*	$NetBSD: pcmcia.c,v 1.48 2004/08/09 18:30:51 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.48 2004/08/09 18:30:51 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 reg;
    647 
    648 	if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
    649 	    width, 0, pcihp->size, pcihp, windowp))
    650 		return (1);
    651 
    652 	/*
    653 	 * XXX in the multifunction multi-iospace-per-function case, this
    654 	 * needs to cooperate with io_alloc to make sure that the spaces
    655 	 * don't overlap, and that the ccr's are set correctly
    656 	 */
    657 
    658 	if (pcmcia_mfc(pf->sc)) {
    659 		int win;
    660 		long iomask;
    661 
    662 		/* round up to nearest (2^n)-1 */
    663 		for (iomask = 1; iomask < pcihp->size; iomask <<= 1)
    664 			;
    665 		iomask--;
    666 
    667 		win = pf->pf_mfc_windows;
    668 		KASSERT(win < 2);
    669 printf("win %d = addr %lx size %lx iomask %lx\n", win, (long)pcihp->addr, (long)pcihp->size, (long)iomask);
    670 		pf->pf_mfc_iobase[win] = pcihp->addr;
    671 		pf->pf_mfc_iomask = iomask;
    672 
    673 		if (pf->pf_flags & PFF_ENABLED) {
    674 			pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0 + 2 * win,
    675 					 (pcihp->addr >> 0) & 0xff);
    676 			pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1 + 2 * win,
    677 					 (pcihp->addr >> 8) & 0xff);
    678 			pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, iomask);
    679 
    680 			reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
    681 			reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
    682 			pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    683 		}
    684 	}
    685 
    686 	return (0);
    687 }
    688 
    689 void
    690 pcmcia_io_unmap(pf, window)
    691 	struct pcmcia_function *pf;
    692 	int window;
    693 {
    694 
    695 	if (pcmcia_mfc(pf->sc)) {
    696 		/*
    697 		 * Don't bother trying to unmap windows in the CCR here,
    698 		 * because we generally get called when a card has been
    699 		 * ejected, and the CCR isn't there any more.
    700 		 */
    701 		--pf->pf_mfc_windows;
    702 	}
    703 
    704 	pcmcia_chip_io_unmap(pf->sc->pct, pf->sc->pch, window);
    705 }
    706 
    707 void *
    708 pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
    709 	struct pcmcia_function *pf;
    710 	int ipl;
    711 	int (*ih_fct) __P((void *));
    712 	void *ih_arg;
    713 {
    714 	void *ret;
    715 
    716 	/* behave differently if this is a multifunction card */
    717 
    718 	if (pcmcia_mfc(pf->sc)) {
    719 		int s, ihcnt, hiipl, reg;
    720 		struct pcmcia_function *pf2;
    721 
    722 		/*
    723 		 * mask all the ipl's which are already used by this card,
    724 		 * and find the highest ipl number (lowest priority)
    725 		 */
    726 
    727 		ihcnt = 0;
    728 		s = 0;		/* this is only here to keep the compiler
    729 				   happy */
    730 		hiipl = 0;	/* this is only here to keep the compiler
    731 				   happy */
    732 
    733 		SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
    734 			if (pf2->ih_fct) {
    735 				DPRINTF(("%s: function %d has ih_fct %p\n",
    736 					 pf->sc->dev.dv_xname, pf2->number,
    737 					 pf2->ih_fct));
    738 
    739 				if (ihcnt == 0) {
    740 					hiipl = pf2->ih_ipl;
    741 				} else {
    742 					if (pf2->ih_ipl > hiipl)
    743 						hiipl = pf2->ih_ipl;
    744 				}
    745 
    746 				ihcnt++;
    747 			}
    748 		}
    749 
    750 		/*
    751 		 * establish the real interrupt, changing the ipl if
    752 		 * necessary
    753 		 */
    754 
    755 		if (ihcnt == 0) {
    756 #ifdef DIAGNOSTIC
    757 			if (pf->sc->ih != NULL)
    758 				panic("card has intr handler, but no function does");
    759 #endif
    760 			s = splhigh();
    761 
    762 			/* set up the handler for the new function */
    763 
    764 			pf->ih_fct = ih_fct;
    765 			pf->ih_arg = ih_arg;
    766 			pf->ih_ipl = ipl;
    767 
    768 			pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
    769 			    pf->sc->pch, pf, ipl, PCMCIA_CARD_INTR, pf->sc);
    770 			splx(s);
    771 		} else if (ipl > hiipl) {
    772 #ifdef DIAGNOSTIC
    773 			if (pf->sc->ih == NULL)
    774 				panic("functions have ih, but the card does not");
    775 #endif
    776 
    777 			/* XXX need #ifdef for splserial on x86 */
    778 			s = splhigh();
    779 
    780 			pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    781 						      pf->sc->ih);
    782 
    783 			/* set up the handler for the new function */
    784 			pf->ih_fct = ih_fct;
    785 			pf->ih_arg = ih_arg;
    786 			pf->ih_ipl = ipl;
    787 
    788 			pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
    789 			    pf->sc->pch, pf, ipl, PCMCIA_CARD_INTR, pf->sc);
    790 
    791 			splx(s);
    792 		} else {
    793 			s = splhigh();
    794 
    795 			/* set up the handler for the new function */
    796 
    797 			pf->ih_fct = ih_fct;
    798 			pf->ih_arg = ih_arg;
    799 			pf->ih_ipl = ipl;
    800 
    801 			splx(s);
    802 		}
    803 
    804 		ret = pf->sc->ih;
    805 
    806 		if (ret != NULL &&
    807 		    (pf->pf_flags & PFF_ENABLED) != 0) {
    808 			reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
    809 			reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
    810 			pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    811 		}
    812 	} else {
    813 		ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    814 		    pf, ipl, ih_fct, ih_arg);
    815 	}
    816 
    817 	return (ret);
    818 }
    819 
    820 void
    821 pcmcia_intr_disestablish(pf, ih)
    822 	struct pcmcia_function *pf;
    823 	void *ih;
    824 {
    825 	/* behave differently if this is a multifunction card */
    826 
    827 	if (pcmcia_mfc(pf->sc)) {
    828 		int s, ihcnt, hiipl;
    829 		struct pcmcia_function *pf2;
    830 
    831 		/*
    832 		 * mask all the ipl's which are already used by this card,
    833 		 * and find the highest ipl number (lowest priority).  Skip
    834 		 * the current function.
    835 		 */
    836 
    837 		ihcnt = 0;
    838 		s = 0;		/* avoid compiler warning */
    839 		hiipl = 0;	/* avoid compiler warning */
    840 
    841 		SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
    842 			if (pf2 == pf)
    843 				continue;
    844 
    845 			if (pf2->ih_fct) {
    846 				if (ihcnt == 0) {
    847 					hiipl = pf2->ih_ipl;
    848 				} else {
    849 					if (pf2->ih_ipl > hiipl)
    850 						hiipl = pf2->ih_ipl;
    851 				}
    852 				ihcnt++;
    853 			}
    854 		}
    855 
    856 		/*
    857 		 * If the ih being removed is lower priority than the lowest
    858 		 * priority remaining interrupt, up the priority.
    859 		 */
    860 
    861 		/*
    862 		 * ihcnt is the number of interrupt handlers *not* including
    863 		 * the one about to be removed.
    864 		 */
    865 
    866 		if (ihcnt == 0) {
    867 			int reg;
    868 
    869 #ifdef DIAGNOSTIC
    870 			if (pf->sc->ih == NULL)
    871 				panic("disestablishing last function, but card has no ih");
    872 #endif
    873 			pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    874 			    pf->sc->ih);
    875 
    876 			if (pf->pf_flags & PFF_ENABLED) {
    877 				reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
    878 				reg &= ~PCMCIA_CCR_OPTION_IREQ_ENABLE;
    879 				pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    880 			}
    881 
    882 			pf->ih_fct = NULL;
    883 			pf->ih_arg = NULL;
    884 
    885 			pf->sc->ih = NULL;
    886 		} else if (pf->ih_ipl > hiipl) {
    887 #ifdef DIAGNOSTIC
    888 			if (pf->sc->ih == NULL)
    889 				panic("changing ih ipl, but card has no ih");
    890 #endif
    891 			/* XXX need #ifdef for splserial on x86 */
    892 			s = splhigh();
    893 
    894 			pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
    895 			    pf->sc->ih);
    896 			pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
    897 			    pf->sc->pch, pf, hiipl, PCMCIA_CARD_INTR, pf->sc);
    898 
    899 			/* null out the handler for this function */
    900 
    901 			pf->ih_fct = NULL;
    902 			pf->ih_arg = NULL;
    903 
    904 			splx(s);
    905 		} else {
    906 			s = splhigh();
    907 
    908 			pf->ih_fct = NULL;
    909 			pf->ih_arg = NULL;
    910 
    911 			splx(s);
    912 		}
    913 	} else {
    914 		pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
    915 	}
    916 }
    917 
    918 int
    919 pcmcia_card_intr(arg)
    920 	void *arg;
    921 {
    922 	struct pcmcia_softc *sc = arg;
    923 	struct pcmcia_function *pf;
    924 	int reg, ret;
    925 
    926 	ret = 0;
    927 
    928 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    929 		if ((pf->pf_flags & PFF_ENABLED) == 0 ||
    930 		    pf->ih_fct == NULL)
    931 			continue;
    932 		if (pf->ccr_mask & (1 << PCMCIA_CCR_STATUS)) {
    933 			reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    934 			if (reg & PCMCIA_CCR_STATUS_INTR) {
    935 				ret |= (*pf->ih_fct)(pf->ih_arg);
    936 				if (reg & PCMCIA_CCR_STATUS_INTRACK)
    937 					pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
    938 					    reg & ~PCMCIA_CCR_STATUS_INTR);
    939 			}
    940 		} else
    941 			ret |= (*pf->ih_fct)(pf->ih_arg);
    942 	}
    943 
    944 	return (ret);
    945 }
    946 
    947 #ifdef PCMCIADEBUG
    948 int
    949 pcmcia_card_intrdebug(arg)
    950 	void *arg;
    951 {
    952 	struct pcmcia_softc *sc = arg;
    953 	struct pcmcia_function *pf;
    954 	int reg, ret;
    955 
    956 	ret = 0;
    957 
    958 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    959 		printf("%s: intr flags=%x fct=%d cor=%02x csr=%02x pin=%02x",
    960 		       sc->dev.dv_xname, pf->pf_flags, pf->number,
    961 		       pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION),
    962 		       pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS),
    963 		       pcmcia_ccr_read(pf, PCMCIA_CCR_PIN));
    964 		if ((pf->pf_flags & PFF_ENABLED) == 0 ||
    965 		    pf->ih_fct == NULL) {
    966 			printf("\n");
    967 			continue;
    968 		}
    969 		if (pf->ccr_mask & (1 << PCMCIA_CCR_STATUS)) {
    970 			reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
    971 			if (reg & PCMCIA_CCR_STATUS_INTR) {
    972 				ret |= (*pf->ih_fct)(pf->ih_arg);
    973 				if (reg & PCMCIA_CCR_STATUS_INTRACK) {
    974 					printf("; csr %02x->%02x",
    975 					    reg, reg & ~PCMCIA_CCR_STATUS_INTR);
    976 					pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
    977 					    reg & ~PCMCIA_CCR_STATUS_INTR);
    978 				}
    979 			}
    980 		} else
    981 			ret |= (*pf->ih_fct)(pf->ih_arg);
    982 		printf("\n");
    983 	}
    984 
    985 	return (ret);
    986 }
    987 #endif
    988