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