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