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