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