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