Home | History | Annotate | Line # | Download | only in pcmcia
pcmcia.c revision 1.82.22.1
      1 /*	$NetBSD: pcmcia.c,v 1.82.22.1 2007/09/04 15:05:21 joerg 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.82.22.1 2007/09/04 15:05:21 joerg 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 <net/if.h>
     60 
     61 #include <dev/pcmcia/pcmciareg.h>
     62 #include <dev/pcmcia/pcmciachip.h>
     63 #include <dev/pcmcia/pcmciavar.h>
     64 #ifdef IT8368E_LEGACY_MODE /* XXX -uch */
     65 #include <arch/hpcmips/dev/it8368var.h>
     66 #endif
     67 
     68 #include "locators.h"
     69 
     70 #ifdef PCMCIADEBUG
     71 int	pcmcia_debug = 0;
     72 #define	DPRINTF(arg) if (pcmcia_debug) printf arg
     73 #else
     74 #define	DPRINTF(arg)
     75 #endif
     76 
     77 #ifdef PCMCIAVERBOSE
     78 int	pcmcia_verbose = 1;
     79 #else
     80 int	pcmcia_verbose = 0;
     81 #endif
     82 
     83 int	pcmcia_match(struct device *, struct cfdata *, void *);
     84 void	pcmcia_attach(struct device *, struct device *, void *);
     85 int	pcmcia_rescan(struct device *, const char *, const int *);
     86 void	pcmcia_childdetached(struct device *, struct device *);
     87 int	pcmcia_print(void *, const char *);
     88 
     89 CFATTACH_DECL2(pcmcia, sizeof(struct pcmcia_softc),
     90     pcmcia_match, pcmcia_attach, NULL, NULL,
     91     pcmcia_rescan, pcmcia_childdetached);
     92 
     93 int
     94 pcmcia_ccr_read(pf, ccr)
     95 	struct pcmcia_function *pf;
     96 	int ccr;
     97 {
     98 
     99 	return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
    100 	    pf->pf_ccr_offset + ccr * 2));
    101 }
    102 
    103 void
    104 pcmcia_ccr_write(pf, ccr, val)
    105 	struct pcmcia_function *pf;
    106 	int ccr;
    107 	int val;
    108 {
    109 
    110 	if (pf->ccr_mask & (1 << ccr)) {
    111 		bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
    112 		    pf->pf_ccr_offset + ccr * 2, val);
    113 	}
    114 }
    115 
    116 int
    117 pcmcia_match(struct device *parent, struct cfdata *match, void *aux)
    118 {
    119 	struct pcmciabus_attach_args *paa = aux;
    120 
    121 	if (strcmp(paa->paa_busname, match->cf_name)) {
    122 	    return 0;
    123 	}
    124 	/* if the autoconfiguration got this far, there's a socket here */
    125 	return (1);
    126 }
    127 
    128 void
    129 pcmcia_attach(struct device *parent, struct device *self, void *aux)
    130 {
    131 	struct pcmciabus_attach_args *paa = aux;
    132 	struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
    133 
    134 	printf("\n");
    135 
    136 	sc->pct = paa->pct;
    137 	sc->pch = paa->pch;
    138 	sc->iobase = paa->iobase;
    139 	sc->iosize = paa->iosize;
    140 
    141 	sc->ih = NULL;
    142 }
    143 
    144 int
    145 pcmcia_card_attach(dev)
    146 	struct device *dev;
    147 {
    148 	struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
    149 	struct pcmcia_function *pf;
    150 	int error;
    151 	static const int wildcard[PCMCIACF_NLOCS] = {
    152 		PCMCIACF_FUNCTION_DEFAULT
    153 	};
    154 
    155 	/*
    156 	 * this is here so that when socket_enable calls gettype, trt happens
    157 	 */
    158 	SIMPLEQ_FIRST(&sc->card.pf_head) = NULL;
    159 
    160 	pcmcia_socket_enable(dev);
    161 
    162 	pcmcia_read_cis(sc);
    163 	pcmcia_check_cis_quirks(sc);
    164 
    165 #if 1 /* XXX remove this, done below ??? */
    166 	/*
    167 	 * bail now if the card has no functions, or if there was an error in
    168 	 * the cis.
    169 	 */
    170 	if (sc->card.error ||
    171 	    SIMPLEQ_EMPTY(&sc->card.pf_head)) {
    172 		printf("%s: card appears to have bogus CIS\n",
    173 		    sc->dev.dv_xname);
    174 		error = EIO;
    175 		goto done;
    176 	}
    177 #endif
    178 
    179 	if (pcmcia_verbose)
    180 		pcmcia_print_cis(sc);
    181 
    182 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    183 		if (SIMPLEQ_EMPTY(&pf->cfe_head))
    184 			continue;
    185 
    186 #ifdef DIAGNOSTIC
    187 		if (pf->child != NULL) {
    188 			printf("%s: %s still attached to function %d!\n",
    189 			    sc->dev.dv_xname, pf->child->dv_xname,
    190 			    pf->number);
    191 			panic("pcmcia_card_attach");
    192 		}
    193 #endif
    194 		pf->sc = sc;
    195 		pf->child = NULL;
    196 		pf->cfe = NULL;
    197 		pf->pf_ih = NULL;
    198 	}
    199 
    200 	error = pcmcia_rescan(dev, "pcmcia", wildcard);
    201 done:
    202 	pcmcia_socket_disable(dev);
    203 	return (error);
    204 }
    205 
    206 int
    207 pcmcia_rescan(struct device *self, const char *ifattr,
    208     const int *locators)
    209 {
    210 	struct pcmcia_softc *sc = (struct pcmcia_softc *)self;
    211 	struct pcmcia_function *pf;
    212 	struct pcmcia_attach_args paa;
    213 	int locs[PCMCIACF_NLOCS];
    214 
    215 	if (sc->card.error ||
    216 	    SIMPLEQ_EMPTY(&sc->card.pf_head)) {
    217 		/* XXX silently ignore if no card present? */
    218 		return (EIO);
    219 	}
    220 
    221 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    222 		if (SIMPLEQ_EMPTY(&pf->cfe_head))
    223 			continue;
    224 
    225 		if ((locators[PCMCIACF_FUNCTION] != PCMCIACF_FUNCTION_DEFAULT)
    226 		    && (locators[PCMCIACF_FUNCTION] != pf->number))
    227 			continue;
    228 
    229 		if (pf->child)
    230 			continue;
    231 
    232 		locs[PCMCIACF_FUNCTION] = pf->number;
    233 
    234 		paa.manufacturer = sc->card.manufacturer;
    235 		paa.product = sc->card.product;
    236 		paa.card = &sc->card;
    237 		paa.pf = pf;
    238 
    239 		pf->child = config_found_sm_loc(self, "pcmcia", locs, &paa,
    240 						pcmcia_print,
    241 						config_stdsubmatch);
    242 	}
    243 
    244 	return (0);
    245 }
    246 
    247 void
    248 pcmcia_card_detach(dev, flags)
    249 	struct device *dev;
    250 	int flags;		/* DETACH_* flags */
    251 {
    252 	struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
    253 	struct pcmcia_function *pf;
    254 	int error;
    255 
    256 	/*
    257 	 * We are running on either the PCMCIA socket's event thread
    258 	 * or in user context detaching a device by user request.
    259 	 */
    260 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    261 		pf->pf_flags |= PFF_DETACHED;
    262 		if (SIMPLEQ_EMPTY(&pf->cfe_head))
    263 			continue;
    264 		if (pf->child == NULL)
    265 			continue;
    266 		DPRINTF(("%s: detaching %s (function %d)\n",
    267 		    sc->dev.dv_xname, pf->child->dv_xname, pf->number));
    268 		if ((error = config_detach(pf->child, flags)) != 0) {
    269 			printf("%s: error %d detaching %s (function %d)\n",
    270 			    sc->dev.dv_xname, error, pf->child->dv_xname,
    271 			    pf->number);
    272 		}
    273 	}
    274 
    275 	if (sc->sc_enabled_count != 0) {
    276 #ifdef DIAGNOSTIC
    277 		printf("pcmcia_card_detach: enabled_count should be 0 here??\n");
    278 #endif
    279 		pcmcia_chip_socket_disable(sc->pct, sc->pch);
    280 		sc->sc_enabled_count = 0;
    281 	}
    282 }
    283 
    284 void
    285 pcmcia_childdetached(struct device *self, struct device *child)
    286 {
    287 	struct pcmcia_softc *sc = (struct pcmcia_softc *)self;
    288 	struct pcmcia_function *pf;
    289 
    290 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    291 		if (SIMPLEQ_EMPTY(&pf->cfe_head))
    292 			continue;
    293 		if (pf->child == child) {
    294 			KASSERT(device_locator(child, PCMCIACF_FUNCTION)
    295 				== pf->number);
    296 			pf->child = NULL;
    297 			return;
    298 		}
    299 	}
    300 
    301 	printf("%s: pcmcia_childdetached: %s not found\n",
    302 	       self->dv_xname, child->dv_xname);
    303 }
    304 
    305 void
    306 pcmcia_card_deactivate(dev)
    307 	struct device *dev;
    308 {
    309 	struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
    310 	struct pcmcia_function *pf;
    311 
    312 	/*
    313 	 * We're in the chip's card removal interrupt handler.
    314 	 * Deactivate the child driver.  The PCMCIA socket's
    315 	 * event thread will run later to finish the detach.
    316 	 */
    317 	SIMPLEQ_FOREACH(pf, &sc->card.pf_head, pf_list) {
    318 		if (SIMPLEQ_EMPTY(&pf->cfe_head))
    319 			continue;
    320 		if (pf->child == NULL)
    321 			continue;
    322 		DPRINTF(("%s: deactivating %s (function %d)\n",
    323 		    sc->dev.dv_xname, pf->child->dv_xname, pf->number));
    324 		config_deactivate(pf->child);
    325 	}
    326 }
    327 
    328 int
    329 pcmcia_print(arg, pnp)
    330 	void *arg;
    331 	const char *pnp;
    332 {
    333 	struct pcmcia_attach_args *pa = arg;
    334 	struct pcmcia_softc *sc = pa->pf->sc;
    335 	struct pcmcia_card *card = &sc->card;
    336 	char devinfo[256];
    337 
    338 	if (pnp)
    339 		aprint_normal("%s", pnp);
    340 
    341 	pcmcia_devinfo(card, !!pnp, devinfo, sizeof(devinfo));
    342 
    343 	aprint_normal(" function %d: %s\n", pa->pf->number, devinfo);
    344 
    345 	return (UNCONF);
    346 }
    347 
    348 void
    349 pcmcia_devinfo(card, showhex, cp, cplen)
    350 	struct pcmcia_card *card;
    351 	int showhex;
    352 	char *cp;
    353 	size_t cplen;
    354 {
    355 	int i, n;
    356 
    357 	if (cplen > 1) {
    358 		*cp++ = '<';
    359 		*cp = '\0';
    360 		cplen--;
    361 	}
    362 
    363 	for (i = 0; i < 4 && card->cis1_info[i] != NULL && cplen > 1; i++) {
    364 		n = snprintf(cp, cplen, "%s%s", i ? ", " : "",
    365 		        card->cis1_info[i]);
    366 		cp += n;
    367 		if (cplen < n)
    368 			return;
    369 		cplen -= n;
    370 	}
    371 
    372 	if (cplen > 1) {
    373 		*cp++ = '>';
    374 		*cp = '\0';
    375 		cplen--;
    376 	}
    377 
    378 	if (showhex && cplen > 1)
    379 		snprintf(cp, cplen, " (manufacturer 0x%04x, product 0x%04x)",
    380 		    card->manufacturer, card->product);
    381 }
    382 
    383 const void *
    384 pcmcia_product_lookup(pa, tab, nent, ent_size, matchfn)
    385 	struct pcmcia_attach_args *pa;
    386 	const void *tab;
    387 	size_t nent;
    388 	size_t ent_size;
    389 	pcmcia_product_match_fn matchfn;
    390 {
    391         const struct pcmcia_product *pp;
    392 	int n;
    393 	int matches;
    394 
    395 #ifdef DIAGNOSTIC
    396 	if (sizeof *pp > ent_size)
    397 		panic("pcmcia_product_lookup: bogus ent_size %ld",
    398 		      (long) ent_size);
    399 #endif
    400 
    401         for (pp = tab, n = nent; n; pp = (const struct pcmcia_product *)
    402 	      ((const char *)pp + ent_size), n--) {
    403 		/* see if it matches vendor/product */
    404 		matches = 0;
    405 		if ((pp->pp_vendor != PCMCIA_VENDOR_INVALID &&
    406 		     pp->pp_vendor == pa->manufacturer) &&
    407 		    (pp->pp_product != PCMCIA_PRODUCT_INVALID &&
    408 		     pp->pp_product == pa->product))
    409 			matches = 1;
    410 		if ((pp->pp_cisinfo[0] && pa->card->cis1_info[0] &&
    411 		          !strcmp(pp->pp_cisinfo[0], pa->card->cis1_info[0])) &&
    412 		         (pp->pp_cisinfo[1] && pa->card->cis1_info[1] &&
    413 		          !strcmp(pp->pp_cisinfo[1], pa->card->cis1_info[1])) &&
    414 		         (!pp->pp_cisinfo[2] || (pa->card->cis1_info[2] &&
    415 		           !strcmp(pp->pp_cisinfo[2], pa->card->cis1_info[2]))) &&
    416 		         (!pp->pp_cisinfo[3] || (pa->card->cis1_info[3] &&
    417 		           !strcmp(pp->pp_cisinfo[3], pa->card->cis1_info[3]))))
    418 			matches = 1;
    419 
    420 		/* if a separate match function is given, let it override */
    421 		if (matchfn)
    422 			matches = (*matchfn)(pa, pp, matches);
    423 
    424 		if (matches)
    425                         return (pp);
    426         }
    427         return (0);
    428 }
    429 
    430 void
    431 pcmcia_socket_settype(dev, type)
    432 	struct device *dev;
    433 	int type;
    434 {
    435 	struct pcmcia_softc *sc = (void *)dev;
    436 
    437 	pcmcia_chip_socket_settype(sc->pct, sc->pch, type);
    438 }
    439 
    440 /*
    441  * Initialize a PCMCIA function.  May be called as long as the function is
    442  * disabled.
    443  */
    444 void
    445 pcmcia_function_init(pf, cfe)
    446 	struct pcmcia_function *pf;
    447 	struct pcmcia_config_entry *cfe;
    448 {
    449 	if (pf->pf_flags & PFF_ENABLED)
    450 		panic("pcmcia_function_init: function is enabled");
    451 
    452 	/* Remember which configuration entry we are using. */
    453 	pf->cfe = cfe;
    454 }
    455 
    456 void
    457 pcmcia_socket_enable(dev)
    458 	struct device *dev;
    459 {
    460 	struct pcmcia_softc *sc = (void *)dev;
    461 
    462 	if (sc->sc_enabled_count++ == 0)
    463 		pcmcia_chip_socket_enable(sc->pct, sc->pch);
    464 	DPRINTF(("%s: ++enabled_count = %d\n", sc->dev.dv_xname,
    465 		 sc->sc_enabled_count));
    466 }
    467 
    468 void
    469 pcmcia_socket_disable(dev)
    470 	struct device *dev;
    471 {
    472 	struct pcmcia_softc *sc = (void *)dev;
    473 
    474 	if (--sc->sc_enabled_count == 0)
    475 		pcmcia_chip_socket_disable(sc->pct, sc->pch);
    476 	DPRINTF(("%s: --enabled_count = %d\n", sc->dev.dv_xname,
    477 		 sc->sc_enabled_count));
    478 }
    479 
    480 /* Enable a PCMCIA function */
    481 int
    482 pcmcia_function_enable(pf)
    483 	struct pcmcia_function *pf;
    484 {
    485 	struct pcmcia_softc *sc = pf->sc;
    486 	struct pcmcia_function *tmp;
    487 	int reg;
    488 	int error;
    489 
    490 	if (pf->cfe == NULL)
    491 		panic("pcmcia_function_enable: function not initialized");
    492 
    493 	/*
    494 	 * Increase the reference count on the socket, enabling power, if
    495 	 * necessary.
    496 	 */
    497 	pcmcia_socket_enable(&sc->dev);
    498 	pcmcia_socket_settype(&sc->dev, pf->cfe->iftype);
    499 
    500 	if (pf->pf_flags & PFF_ENABLED) {
    501 		/*
    502 		 * Don't do anything if we're already enabled.
    503 		 */
    504 		return (0);
    505 	}
    506 
    507 	/*
    508 	 * it's possible for different functions' CCRs to be in the same
    509 	 * underlying page.  Check for that.
    510 	 */
    511 
    512 	SIMPLEQ_FOREACH(tmp, &sc->card.pf_head, pf_list) {
    513 		if ((tmp->pf_flags & PFF_ENABLED) &&
    514 		    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
    515 		    ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
    516 		     (tmp->ccr_base - tmp->pf_ccr_offset +
    517 		      tmp->pf_ccr_realsize))) {
    518 			pf->pf_ccrt = tmp->pf_ccrt;
    519 			pf->pf_ccrh = tmp->pf_ccrh;
    520 			pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
    521 
    522 			/*
    523 			 * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
    524 			 * tmp->ccr_base) + pf->ccr_base;
    525 			 */
    526 			pf->pf_ccr_offset =
    527 			    (tmp->pf_ccr_offset + pf->ccr_base) -
    528 			    tmp->ccr_base;
    529 			pf->pf_ccr_window = tmp->pf_ccr_window;
    530 			break;
    531 		}
    532 	}
    533 
    534 	if (tmp == NULL) {
    535 		error = pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh);
    536 		if (error)
    537 			goto bad;
    538 
    539 		error = pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
    540 		    PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
    541 		    &pf->pf_ccr_window);
    542 		if (error) {
    543 			pcmcia_mem_free(pf, &pf->pf_pcmh);
    544 			goto bad;
    545 		}
    546 	}
    547 
    548 	if (pcmcia_mfc(sc) || 1) {
    549 		pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
    550 				 (pf->pf_mfc_iobase >>  0) & 0xff);
    551 		pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
    552 				 (pf->pf_mfc_iobase >>  8) & 0xff);
    553 		pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
    554 				 (pf->pf_mfc_iobase >> 16) & 0xff);
    555 		pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
    556 				 (pf->pf_mfc_iobase >> 24) & 0xff);
    557 		pcmcia_ccr_write(pf, PCMCIA_CCR_IOLIMIT,
    558 				 pf->pf_mfc_iomax - pf->pf_mfc_iobase);
    559 	}
    560 
    561 	reg = 0;
    562 	if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
    563 		reg |= PCMCIA_CCR_STATUS_AUDIO;
    564 	pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
    565 
    566 	pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
    567 
    568 	reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
    569 	reg |= PCMCIA_CCR_OPTION_LEVIREQ;
    570 	if (pcmcia_mfc(sc)) {
    571 		reg |= (PCMCIA_CCR_OPTION_FUNC_ENABLE |
    572 			PCMCIA_CCR_OPTION_ADDR_DECODE);
    573 		if (pf->pf_ih)
    574 			reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
    575 
    576 	}
    577 	pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    578 
    579 #ifdef PCMCIADEBUG
    580 	if (pcmcia_debug) {
    581 		SIMPLEQ_FOREACH(tmp, &sc->card.pf_head, pf_list) {
    582 			printf("%s: function %d CCR at %d offset %lx: "
    583 			       "%x %x %x %x, %x %x %x %x, %x\n",
    584 			       tmp->sc->dev.dv_xname, tmp->number,
    585 			       tmp->pf_ccr_window,
    586 			       (unsigned long) tmp->pf_ccr_offset,
    587 			       pcmcia_ccr_read(tmp, 0),
    588 			       pcmcia_ccr_read(tmp, 1),
    589 			       pcmcia_ccr_read(tmp, 2),
    590 			       pcmcia_ccr_read(tmp, 3),
    591 
    592 			       pcmcia_ccr_read(tmp, 5),
    593 			       pcmcia_ccr_read(tmp, 6),
    594 			       pcmcia_ccr_read(tmp, 7),
    595 			       pcmcia_ccr_read(tmp, 8),
    596 
    597 			       pcmcia_ccr_read(tmp, 9));
    598 		}
    599 	}
    600 #endif
    601 
    602 #ifdef IT8368E_LEGACY_MODE
    603 	/* return to I/O mode */
    604 	it8368_mode(pf, IT8368_IO_MODE, IT8368_WIDTH_16);
    605 #endif
    606 
    607 	pf->pf_flags |= PFF_ENABLED;
    608 	return (0);
    609 
    610 bad:
    611 	/*
    612 	 * Decrement the reference count, and power down the socket, if
    613 	 * necessary.
    614 	 */
    615 	printf("%s: couldn't map the CCR\n", pf->child->dv_xname);
    616 	pcmcia_socket_disable(&sc->dev);
    617 
    618 	return (error);
    619 }
    620 
    621 /* Disable PCMCIA function. */
    622 void
    623 pcmcia_function_disable(pf)
    624 	struct pcmcia_function *pf;
    625 {
    626 	struct pcmcia_softc *sc = pf->sc;
    627 	struct pcmcia_function *tmp;
    628 	int reg;
    629 
    630 	if (pf->cfe == NULL)
    631 		panic("pcmcia_function_enable: function not initialized");
    632 
    633 	if ((pf->pf_flags & PFF_ENABLED) == 0) {
    634 		/*
    635 		 * Don't do anything but decrement if we're already disabled.
    636 		 */
    637 		goto out;
    638 	}
    639 
    640 	if (pcmcia_mfc(sc) &&
    641 	    (pf->pf_flags & PFF_DETACHED) == 0) {
    642 		reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
    643 		reg &= ~(PCMCIA_CCR_OPTION_FUNC_ENABLE|
    644 			 PCMCIA_CCR_OPTION_ADDR_DECODE|
    645 		         PCMCIA_CCR_OPTION_IREQ_ENABLE);
    646 		pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
    647 	}
    648 
    649 	/*
    650 	 * it's possible for different functions' CCRs to be in the same
    651 	 * underlying page.  Check for that.  Note we mark us as disabled
    652 	 * first to avoid matching ourself.
    653 	 */
    654 
    655 	pf->pf_flags &= ~PFF_ENABLED;
    656 	SIMPLEQ_FOREACH(tmp, &sc->card.pf_head, pf_list) {
    657 		if ((tmp->pf_flags & PFF_ENABLED) &&
    658 		    (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
    659 		    ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
    660 		(tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
    661 			break;
    662 	}
    663 
    664 	/* Not used by anyone else; unmap the CCR. */
    665 	if (tmp == NULL) {
    666 		pcmcia_mem_unmap(pf, pf->pf_ccr_window);
    667 		pcmcia_mem_free(pf, &pf->pf_pcmh);
    668 	}
    669 
    670 out:
    671 	/*
    672 	 * Decrement the reference count, and power down the socket, if
    673 	 * necessary.
    674 	 */
    675 	pcmcia_socket_disable(&sc->dev);
    676 }
    677 
    678 int
    679 pcmcia_io_map(pf, width, pcihp, windowp)
    680 	struct pcmcia_function *pf;
    681 	int width;
    682 	struct pcmcia_io_handle *pcihp;
    683 	int *windowp;
    684 {
    685 	struct pcmcia_softc *sc = pf->sc;
    686 	int error;
    687 
    688 	if (pf->pf_flags & PFF_ENABLED)
    689 		printf("pcmcia_io_map: function is enabled!\n");
    690 
    691 	error = pcmcia_chip_io_map(sc->pct, sc->pch,
    692 	    width, 0, pcihp->size, pcihp, windowp);
    693 	if (error)
    694 		return (error);
    695 
    696 	/*
    697 	 * XXX in the multifunction multi-iospace-per-function case, this
    698 	 * needs to cooperate with io_alloc to make sure that the spaces
    699 	 * don't overlap, and that the ccr's are set correctly
    700 	 */
    701 
    702 	if (pcmcia_mfc(sc) || 1) {
    703 		bus_addr_t iobase = pcihp->addr;
    704 		bus_addr_t iomax = pcihp->addr + pcihp->size - 1;
    705 
    706 		DPRINTF(("window iobase %lx iomax %lx\n", (long)iobase,
    707 		    (long)iomax));
    708 		if (pf->pf_mfc_iobase == 0) {
    709 			pf->pf_mfc_iobase = iobase;
    710 			pf->pf_mfc_iomax = iomax;
    711 		} else {
    712 			if (iobase < pf->pf_mfc_iobase)
    713 				pf->pf_mfc_iobase = iobase;
    714 			if (iomax > pf->pf_mfc_iomax)
    715 				pf->pf_mfc_iomax = iomax;
    716 		}
    717 		DPRINTF(("function iobase %lx iomax %lx\n",
    718 		    (long)pf->pf_mfc_iobase, (long)pf->pf_mfc_iomax));
    719 	}
    720 
    721 	return (0);
    722 }
    723 
    724 void
    725 pcmcia_io_unmap(pf, window)
    726 	struct pcmcia_function *pf;
    727 	int window;
    728 {
    729 	struct pcmcia_softc *sc = pf->sc;
    730 
    731 	if (pf->pf_flags & PFF_ENABLED)
    732 		printf("pcmcia_io_unmap: function is enabled!\n");
    733 
    734 	pcmcia_chip_io_unmap(sc->pct, sc->pch, window);
    735 }
    736 
    737 void *
    738 pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
    739 	struct pcmcia_function *pf;
    740 	int ipl;
    741 	int (*ih_fct)(void *);
    742 	void *ih_arg;
    743 {
    744 
    745 	if (pf->pf_flags & PFF_ENABLED)
    746 		printf("pcmcia_intr_establish: function is enabled!\n");
    747 	if (pf->pf_ih)
    748 		panic("pcmcia_intr_establish: already done\n");
    749 
    750 	pf->pf_ih = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
    751 	    pf, ipl, ih_fct, ih_arg);
    752 	if (!pf->pf_ih)
    753 		printf("%s: interrupt establish failed\n", pf->child->dv_xname);
    754 	return (pf->pf_ih);
    755 }
    756 
    757 void
    758 pcmcia_intr_disestablish(pf, ih)
    759 	struct pcmcia_function *pf;
    760 	void *ih;
    761 {
    762 
    763 	if (pf->pf_flags & PFF_ENABLED)
    764 		printf("pcmcia_intr_disestablish: function is enabled!\n");
    765 	if (!pf->pf_ih)
    766 		panic("pcmcia_intr_distestablish: already done\n");
    767 
    768 	pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
    769 	pf->pf_ih = 0;
    770 }
    771 
    772 int
    773 pcmcia_config_alloc(pf, cfe)
    774 	struct pcmcia_function *pf;
    775 	struct pcmcia_config_entry *cfe;
    776 {
    777 	int error = 0;
    778 	int n, m;
    779 
    780 	for (n = 0; n < cfe->num_iospace; n++) {
    781 		bus_addr_t start = cfe->iospace[n].start;
    782 		bus_size_t length = cfe->iospace[n].length;
    783 		bus_size_t align = cfe->iomask ? (1 << cfe->iomask) :
    784 		    length;
    785 		bus_size_t skew = start & (align - 1);
    786 
    787 		if ((start - skew) == 0 && align < 0x400) {
    788 			if (skew)
    789 				printf("Drats!  I need a skew!\n");
    790 			start = 0;
    791 		}
    792 
    793 		DPRINTF(("pcmcia_config_alloc: io %d start=%lx length=%lx align=%lx skew=%lx\n",
    794 		    n, (long)start, (long)length, (long)align, (long)skew));
    795 
    796 		error = pcmcia_io_alloc(pf, start, length, align,
    797 		    &cfe->iospace[n].handle);
    798 		if (error)
    799 			break;
    800 	}
    801 	if (n < cfe->num_iospace) {
    802 		for (m = 0; m < n; m++)
    803 			pcmcia_io_free(pf, &cfe->iospace[m].handle);
    804 		return (error);
    805 	}
    806 
    807 	for (n = 0; n < cfe->num_memspace; n++) {
    808 		bus_size_t length = cfe->memspace[n].length;
    809 
    810 		DPRINTF(("pcmcia_config_alloc: mem %d length %lx\n", n,
    811 		    (long)length));
    812 
    813 		error = pcmcia_mem_alloc(pf, length, &cfe->memspace[n].handle);
    814 		if (error)
    815 			break;
    816 	}
    817 	if (n < cfe->num_memspace) {
    818 		for (m = 0; m < cfe->num_iospace; m++)
    819 			pcmcia_io_free(pf, &cfe->iospace[m].handle);
    820 		for (m = 0; m < n; m++)
    821 			pcmcia_mem_free(pf, &cfe->memspace[m].handle);
    822 		return (error);
    823 	}
    824 
    825 	/* This one's good! */
    826 	return (error);
    827 }
    828 
    829 void
    830 pcmcia_config_free(pf)
    831 	struct pcmcia_function *pf;
    832 {
    833 	struct pcmcia_config_entry *cfe = pf->cfe;
    834 	int m;
    835 
    836 	for (m = 0; m < cfe->num_iospace; m++)
    837 		pcmcia_io_free(pf, &cfe->iospace[m].handle);
    838 	for (m = 0; m < cfe->num_memspace; m++)
    839 		pcmcia_mem_free(pf, &cfe->memspace[m].handle);
    840 }
    841 
    842 int
    843 pcmcia_config_map(pf)
    844 	struct pcmcia_function *pf;
    845 {
    846 	struct pcmcia_config_entry *cfe = pf->cfe;
    847 	int error = 0;
    848 	int n, m;
    849 
    850 	for (n = 0; n < cfe->num_iospace; n++) {
    851 		int width;
    852 
    853 		if (cfe->flags & PCMCIA_CFE_IO16)
    854 			width = PCMCIA_WIDTH_AUTO;
    855 		else
    856 			width = PCMCIA_WIDTH_IO8;
    857 		error = pcmcia_io_map(pf, width, &cfe->iospace[n].handle,
    858 		    &cfe->iospace[n].window);
    859 		if (error)
    860 			break;
    861 	}
    862 	if (n < cfe->num_iospace) {
    863 		for (m = 0; m < n; m++)
    864 			pcmcia_io_unmap(pf, cfe->iospace[m].window);
    865 		return (error);
    866 	}
    867 
    868 	for (n = 0; n < cfe->num_memspace; n++) {
    869 		bus_size_t length = cfe->memspace[n].length;
    870 		int width;
    871 
    872 		DPRINTF(("pcmcia_config_alloc: mem %d length %lx\n", n,
    873 		    (long)length));
    874 
    875 		/*XXX*/
    876 		width = PCMCIA_WIDTH_MEM8|PCMCIA_MEM_COMMON;
    877 		error = pcmcia_mem_map(pf, width, 0, length,
    878 		    &cfe->memspace[n].handle, &cfe->memspace[n].offset,
    879 		    &cfe->memspace[n].window);
    880 		if (error)
    881 			break;
    882 	}
    883 	if (n < cfe->num_memspace) {
    884 		for (m = 0; m < cfe->num_iospace; m++)
    885 			pcmcia_io_unmap(pf, cfe->iospace[m].window);
    886 		for (m = 0; m < n; m++)
    887 			pcmcia_mem_unmap(pf, cfe->memspace[m].window);
    888 		return (error);
    889 	}
    890 
    891 	/* This one's good! */
    892 	return (error);
    893 }
    894 
    895 void
    896 pcmcia_config_unmap(pf)
    897 	struct pcmcia_function *pf;
    898 {
    899 	struct pcmcia_config_entry *cfe = pf->cfe;
    900 	int m;
    901 
    902 	for (m = 0; m < cfe->num_iospace; m++)
    903 		pcmcia_io_unmap(pf, cfe->iospace[m].window);
    904 	for (m = 0; m < cfe->num_memspace; m++)
    905 		pcmcia_mem_unmap(pf, cfe->memspace[m].window);
    906 }
    907 
    908 int
    909 pcmcia_function_configure(pf, validator)
    910 	struct pcmcia_function *pf;
    911 	int (*validator)(struct pcmcia_config_entry *);
    912 {
    913 	struct pcmcia_config_entry *cfe;
    914 	int error = ENOENT;
    915 
    916 	SIMPLEQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
    917 		error = validator(cfe);
    918 		if (error)
    919 			continue;
    920 		error = pcmcia_config_alloc(pf, cfe);
    921 		if (!error)
    922 			break;
    923 	}
    924 	if (!cfe) {
    925 		DPRINTF(("pcmcia_function_configure: no config entry found, error=%d\n",
    926 		    error));
    927 		return (error);
    928 	}
    929 
    930 	/* Remember which configuration entry we are using. */
    931 	pf->cfe = cfe;
    932 
    933 	error = pcmcia_config_map(pf);
    934 	if (error) {
    935 		DPRINTF(("pcmcia_function_configure: map failed, error=%d\n",
    936 		    error));
    937 		return (error);
    938 	}
    939 
    940 	return (0);
    941 }
    942 
    943 void
    944 pcmcia_function_unconfigure(pf)
    945 	struct pcmcia_function *pf;
    946 {
    947 
    948 	pcmcia_config_unmap(pf);
    949 	pcmcia_config_free(pf);
    950 }
    951 
    952 pnp_status_t
    953 pcmcia_net_generic_power(device_t dv, pnp_request_t req, void *opaque,
    954     pnp_state_t *device_state, struct ifnet *ifp)
    955 {
    956 	pnp_status_t status;
    957 	pnp_state_t *cur_state;
    958 	pnp_capabilities_t *caps;
    959 	int s;
    960 
    961 	status = PNP_STATUS_UNSUPPORTED;
    962 
    963 	switch (req) {
    964 	case PNP_REQUEST_GET_CAPABILITIES:
    965 		caps = opaque;
    966 		caps->state = PNP_STATE_D0 | PNP_STATE_D3;
    967 		status = PNP_STATUS_SUCCESS;
    968 		break;
    969 	case PNP_REQUEST_SET_STATE:
    970 		cur_state = opaque;
    971 		switch (*cur_state) {
    972 		case PNP_STATE_D0:
    973 			s = splnet();
    974 
    975 			if (ifp->if_flags & IFF_UP) {
    976 				ifp->if_flags &= ~IFF_RUNNING;
    977 				(*ifp->if_init)(ifp);
    978 				(*ifp->if_start)(ifp);
    979 			}
    980 
    981 			splx(s);
    982 			break;
    983 		case PNP_STATE_D3:
    984 			s = splnet();
    985 			(*ifp->if_stop)(ifp, 1);
    986 			splx(s);
    987 			break;
    988 		default:
    989 			return PNP_STATUS_UNSUPPORTED;
    990 		}
    991 		*device_state = *cur_state;
    992 		status = PNP_STATUS_SUCCESS;
    993 
    994 		break;
    995 	case PNP_REQUEST_GET_STATE:
    996 		cur_state = opaque;
    997 
    998 		*cur_state = *device_state;
    999 		status = PNP_STATUS_SUCCESS;
   1000 		break;
   1001 	default:
   1002 		status = PNP_STATUS_UNSUPPORTED;
   1003 	}
   1004 
   1005 	return status;
   1006 }
   1007