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