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