pcmcia.c revision 1.2 1 /* $NetBSD: pcmcia.c,v 1.2 1997/10/16 23:27:30 thorpej Exp $ */
2
3 #define PCMCIADEBUG
4
5 /*
6 * Copyright (c) 1997 Marc Horowitz. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by Marc Horowitz.
19 * 4. The name of the author may not be used to endorse or promote products
20 * derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 #include "opt_pcmciaverbose.h"
35
36 #include <sys/types.h>
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/device.h>
40
41 /* XXX only needed for intr debugging */
42 #include <vm/vm.h>
43
44 #include <dev/pcmcia/pcmciareg.h>
45 #include <dev/pcmcia/pcmciachip.h>
46 #include <dev/pcmcia/pcmciavar.h>
47
48 #ifdef PCMCIADEBUG
49 int pcmcia_debug = 0;
50 #define DPRINTF(arg) if (pcmcia_debug) printf arg
51 #else
52 #define DPRINTF(arg)
53 #endif
54
55 #ifdef PCMCIAVERBOSE
56 int pcmcia_verbose = 1;
57 #else
58 int pcmcia_verbose = 0;
59 #endif
60
61 #ifdef __BROKEN_INDIRECT_CONFIG
62 int pcmcia_match __P((struct device *, void *, void *));
63 int pcmcia_submatch __P((struct device *, void *, void *));
64 #else
65 int pcmcia_match __P((struct device *, struct cfdata *, void *));
66 int pcmcia_submatch __P((struct device *, struct cfdata *, void *));
67 #endif
68 void pcmcia_attach __P((struct device *, struct device *, void *));
69 int pcmcia_print __P((void *, const char *));
70
71 int pcmcia_card_intr __P((void *));
72
73 struct cfdriver pcmcia_cd = {
74 NULL, "pcmcia", DV_DULL
75 };
76
77 struct cfattach pcmcia_ca = {
78 sizeof(struct pcmcia_softc), pcmcia_match, pcmcia_attach
79 };
80
81 int
82 pcmcia_ccr_read(pf, ccr)
83 struct pcmcia_function *pf;
84 int ccr;
85 {
86
87 return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
88 pf->pf_ccr_offset + ccr));
89 }
90
91 void
92 pcmcia_ccr_write(pf, ccr, val)
93 struct pcmcia_function *pf;
94 int ccr;
95 int val;
96 {
97
98 if ((pf->ccr_mask) & (1 << (ccr / 2))) {
99 bus_space_write_1(pf->pf_ccrt, pf->pf_ccrh,
100 pf->pf_ccr_offset + ccr, val);
101 }
102 }
103
104 int
105 pcmcia_match(parent, match, aux)
106 struct device *parent;
107 #ifdef __BROKEN_INDIRECT_CONFIG
108 void *match;
109 #else
110 struct cfdata *match;
111 #endif
112 void *aux;
113 {
114
115 /* if the autoconfiguration got this far, there's a socket here */
116 return (1);
117 }
118
119 void
120 pcmcia_attach(parent, self, aux)
121 struct device *parent, *self;
122 void *aux;
123 {
124 struct pcmciabus_attach_args *paa = aux;
125 struct pcmcia_softc *sc = (struct pcmcia_softc *) self;
126
127 printf("\n");
128
129 sc->pct = paa->pct;
130 sc->pch = paa->pch;
131 sc->iobase = paa->iobase;
132 sc->iosize = paa->iosize;
133
134 sc->ih = NULL;
135 }
136
137 int
138 pcmcia_card_attach(dev)
139 struct device *dev;
140 {
141 struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
142 struct pcmcia_function *pf;
143 struct pcmcia_attach_args paa;
144 int attached;
145
146 /*
147 * this is here so that when socket_enable calls gettype, trt happens
148 */
149 sc->card.pf_head.sqh_first = NULL;
150
151 pcmcia_chip_socket_enable(sc->pct, sc->pch);
152
153 pcmcia_read_cis(sc);
154
155 pcmcia_chip_socket_disable(sc->pct, sc->pch);
156
157 /*
158 * bail now if the card has no functions, or if there was an error in
159 * the cis.
160 */
161
162 if (sc->card.error)
163 return (1);
164 if (sc->card.pf_head.sqh_first == NULL)
165 return (1);
166
167 if (pcmcia_verbose)
168 pcmcia_print_cis(sc);
169
170 attached = 0;
171
172 for (pf = sc->card.pf_head.sqh_first; pf != NULL;
173 pf = pf->pf_list.sqe_next) {
174 if (pf->cfe_head.sqh_first == NULL)
175 continue;
176
177 pf->sc = sc;
178 pf->cfe = NULL;
179 pf->ih_fct = NULL;
180 pf->ih_arg = NULL;
181 }
182
183 for (pf = sc->card.pf_head.sqh_first; pf != NULL;
184 pf = pf->pf_list.sqe_next) {
185 if (pf->cfe_head.sqh_first == NULL)
186 continue;
187
188 paa.manufacturer = sc->card.manufacturer;
189 paa.product = sc->card.product;
190 paa.card = &sc->card;
191 paa.pf = pf;
192
193 if (config_found_sm(&sc->dev, &paa, pcmcia_print,
194 pcmcia_submatch)) {
195 attached++;
196
197 DPRINTF(("%s: function %d CCR at %d "
198 "offset %lx: %x %x %x %x, %x %x %x %x, %x\n",
199 sc->dev.dv_xname, pf->number,
200 pf->pf_ccr_window, pf->pf_ccr_offset,
201 pcmcia_ccr_read(pf, 0x00),
202 pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
203 pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
204 pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
205 pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
206 }
207 }
208
209 return (attached ? 0 : 1);
210 }
211
212 void
213 pcmcia_card_detach(dev)
214 struct device *dev;
215 {
216 /* struct pcmcia_softc *sc = (struct pcmcia_softc *) dev; */
217 /* don't do anything yet */
218 }
219
220 int
221 #ifdef __BROKEN_INDIRECT_CONFIG
222 pcmcia_submatch(parent, match, aux)
223 struct device *parent;
224 void *match, *aux;
225 {
226 struct cfdata *cf = match;
227 #else
228 pcmcia_submatch(parent, cf, aux)
229 struct device *parent;
230 struct cfdata *cf;
231 void *aux;
232 {
233 #endif
234 struct pcmcia_attach_args *paa = aux;
235
236 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != paa->pf->number)
237 return (0);
238
239 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
240 }
241
242 int
243 pcmcia_print(arg, pnp)
244 void *arg;
245 const char *pnp;
246 {
247 struct pcmcia_attach_args *pa = arg;
248 struct pcmcia_softc *sc = pa->pf->sc;
249 struct pcmcia_card *card = &sc->card;
250 int i;
251
252 if (pnp) {
253 for (i = 0; i < 4; i++) {
254 if (card->cis1_info[i] == NULL)
255 break;
256 if (i)
257 printf(", ");
258 printf("%s", card->cis1_info[i]);
259 }
260 if (i)
261 printf(" ");
262 printf("(manufacturer 0x%x, product 0x%x)", card->manufacturer,
263 card->product);
264 }
265 printf(" function %d", pa->pf->number);
266
267 return (UNCONF);
268 }
269
270 int
271 pcmcia_card_gettype(dev)
272 struct device *dev;
273 {
274 struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
275
276 /*
277 * set the iftype to memory if this card has no functions (not yet
278 * probed), or only one function, and that is memory.
279 */
280 if (sc->card.pf_head.sqh_first == NULL ||
281 (sc->card.pf_head.sqh_first != NULL &&
282 sc->card.pf_head.sqh_first->pf_list.sqe_next == NULL &&
283 (sc->card.pf_head.sqh_first->cfe_head.sqh_first->iftype ==
284 PCMCIA_IFTYPE_MEMORY)))
285 return (PCMCIA_IFTYPE_MEMORY);
286 else
287 return (PCMCIA_IFTYPE_IO);
288 }
289
290 /*
291 * Initialize a PCMCIA function. May be called as long as the function is
292 * disabled.
293 */
294 void
295 pcmcia_function_init(pf, cfe)
296 struct pcmcia_function *pf;
297 struct pcmcia_config_entry *cfe;
298 {
299
300 if (pf->pf_flags & PFF_ENABLED)
301 panic("pcmcia_function_init: function is enabled");
302
303 /* Remember which configuration entry we are using. */
304 pf->cfe = cfe;
305 }
306
307 /* Enable a PCMCIA function */
308 int
309 pcmcia_function_enable(pf)
310 struct pcmcia_function *pf;
311 {
312 struct pcmcia_function *tmp;
313 int reg;
314
315 if (pf->cfe == NULL)
316 panic("pcmcia_function_enable: function not initialized");
317
318 if (pf->pf_flags & PFF_ENABLED) {
319 /*
320 * Don't do anything if we're already enabled.
321 */
322 return (0);
323 }
324
325 /*
326 * Increase the reference count on the socket, enabling power, if
327 * necessary.
328 */
329 if (pf->sc->sc_enabled_count++ == 0)
330 pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
331
332 /*
333 * it's possible for different functions' CCRs to be in the same
334 * underlying page. Check for that.
335 */
336
337 for (tmp = pf->sc->card.pf_head.sqh_first; tmp != NULL;
338 tmp = tmp->pf_list.sqe_next) {
339 if ((tmp->pf_flags & PFF_ENABLED) &&
340 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
341 ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
342 (tmp->ccr_base - tmp->pf_ccr_offset +
343 tmp->pf_ccr_realsize))) {
344 pf->pf_ccrt = tmp->pf_ccrt;
345 pf->pf_ccrh = tmp->pf_ccrh;
346 pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
347
348 /*
349 * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
350 * tmp->ccr_base) + pf->ccr_base;
351 */
352 pf->pf_ccr_offset =
353 (tmp->pf_ccr_offset + pf->ccr_base) -
354 tmp->ccr_base;
355 pf->pf_ccr_window = tmp->pf_ccr_window;
356 break;
357 }
358 }
359
360 if (tmp == NULL) {
361 if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
362 goto bad;
363
364 if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
365 PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
366 &pf->pf_ccr_window)) {
367 pcmcia_mem_free(pf, &pf->pf_pcmh);
368 goto bad;
369 }
370 }
371 DPRINTF(("%s: function %d CCR at %d offset %lx: "
372 "%x %x %x %x, %x %x %x %x, %x\n",
373 pf->sc->dev.dv_xname, pf->number,
374 pf->pf_ccr_window, pf->pf_ccr_offset,
375 pcmcia_ccr_read(pf, 0x00),
376 pcmcia_ccr_read(pf, 0x02), pcmcia_ccr_read(pf, 0x04),
377 pcmcia_ccr_read(pf, 0x06), pcmcia_ccr_read(pf, 0x0A),
378 pcmcia_ccr_read(pf, 0x0C), pcmcia_ccr_read(pf, 0x0E),
379 pcmcia_ccr_read(pf, 0x10), pcmcia_ccr_read(pf, 0x12)));
380
381 reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
382 reg |= PCMCIA_CCR_OPTION_LEVIREQ;
383 if (pcmcia_mfc(pf->sc))
384 reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
385 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
386
387 reg = 0;
388
389 if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
390 reg |= PCMCIA_CCR_STATUS_IOIS8;
391 if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
392 reg |= PCMCIA_CCR_STATUS_AUDIO;
393 /* Not really needed, since we start with 0. */
394 if (pf->cfe->flags & PCMCIA_CFE_POWERDOWN)
395 reg &= ~PCMCIA_CCR_STATUS_PWRDWN;
396 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
397
398 pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
399
400 pf->pf_flags |= PFF_ENABLED;
401 return (0);
402
403 bad:
404 /*
405 * Decrement the reference count, and power down the socket, if
406 * necessary.
407 */
408 if (pf->sc->sc_enabled_count-- == 1)
409 pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
410 return (1);
411 }
412
413 /* Disable PCMCIA function. */
414 void
415 pcmcia_function_disable(pf)
416 struct pcmcia_function *pf;
417 {
418 struct pcmcia_function *tmp;
419 int reg;
420
421 if (pf->cfe == NULL)
422 panic("pcmcia_function_enable: function not initialized");
423
424 if ((pf->pf_flags & PFF_ENABLED) == 0) {
425 /*
426 * Don't do anything if we're already disabled.
427 */
428 return;
429 }
430
431 /* Power down the function if the card supports it. */
432 if (pf->cfe->flags & PCMCIA_CFE_POWERDOWN) {
433 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
434 reg |= PCMCIA_CCR_STATUS_PWRDWN;
435 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
436 }
437
438 /*
439 * it's possible for different functions' CCRs to be in the same
440 * underlying page. Check for that. Note we mark us as disabled
441 * first to avoid matching ourself.
442 */
443
444 pf->pf_flags &= ~PFF_ENABLED;
445 for (tmp = pf->sc->card.pf_head.sqh_first; tmp != NULL;
446 tmp = tmp->pf_list.sqe_next) {
447 if ((tmp->pf_flags & PFF_ENABLED) &&
448 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
449 ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
450 (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
451 break;
452 }
453
454 /* Not used by anyone else; unmap the CCR. */
455 if (tmp == NULL) {
456 pcmcia_mem_unmap(pf, pf->pf_ccr_window);
457 pcmcia_mem_free(pf, &pf->pf_pcmh);
458 }
459
460 /*
461 * Decrement the reference count, and power down the socket, if
462 * necessary.
463 */
464 if (--pf->sc->sc_enabled_count == 0)
465 pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
466 }
467
468 int
469 pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
470 struct pcmcia_function *pf;
471 int width;
472 bus_addr_t offset;
473 bus_size_t size;
474 struct pcmcia_io_handle *pcihp;
475 int *windowp;
476 {
477 bus_addr_t ioaddr;
478 int reg;
479
480 if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
481 width, offset, size, pcihp, windowp))
482 return (1);
483
484 ioaddr = pcihp->addr + offset;
485
486 /*
487 * XXX in the multifunction multi-iospace-per-function case, this
488 * needs to cooperate with io_alloc to make sure that the spaces
489 * don't overlap, and that the ccr's are set correctly
490 */
491
492 if (pcmcia_mfc(pf->sc)) {
493 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0, ioaddr & 0xff);
494 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1, (ioaddr >> 8) & 0xff);
495 pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE, size - 1);
496
497 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
498 reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
499 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
500 }
501 return (0);
502 }
503
504 void *
505 pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg)
506 struct pcmcia_function *pf;
507 int ipl;
508 int (*ih_fct) __P((void *));
509 void *ih_arg;
510 {
511 void *ret;
512
513 /* behave differently if this is a multifunction card */
514
515 if (pcmcia_mfc(pf->sc)) {
516 int s, ihcnt, hiipl, reg;
517 struct pcmcia_function *pf2;
518
519 /* XXX splraise() use needs to go away! */
520
521 /*
522 * mask all the ipl's which are already used by this card,
523 * and find the highest ipl number (lowest priority)
524 */
525
526 ihcnt = 0;
527 s = 0; /* this is only here to keep the compipler
528 happy */
529 hiipl = 0; /* this is only here to keep the compipler
530 happy */
531
532 for (pf2 = pf->sc->card.pf_head.sqh_first; pf2 != NULL;
533 pf2 = pf2->pf_list.sqe_next) {
534 if (pf2->ih_fct) {
535 if (ihcnt == 0) {
536 s = splraise(pf2->ih_ipl);
537 hiipl = pf2->ih_ipl;
538 ihcnt++;
539 } else {
540 splraise(pf2->ih_ipl);
541 if (pf2->ih_ipl > hiipl)
542 hiipl = pf2->ih_ipl;
543 }
544 }
545 }
546
547 /* set up the handler for the new function */
548
549 pf->ih_fct = ih_fct;
550 pf->ih_arg = ih_arg;
551 pf->ih_ipl = ipl;
552
553 /*
554 * establish the real interrupt, changing the ipl if
555 * necessary
556 */
557
558 if (ihcnt == 0) {
559 #ifdef DIAGNOSTIC
560 if (pf->sc->ih != NULL)
561 panic("card has intr handler, but no function does");
562 #endif
563
564 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
565 pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc);
566 } else if (ipl > hiipl) {
567 #ifdef DIAGNOSTIC
568 if (pf->sc->ih == NULL)
569 panic("functions have ih, but the card does not");
570 #endif
571
572 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
573 pf->sc->ih);
574 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
575 pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc);
576 }
577 if (ihcnt)
578 splx(s);
579
580 ret = pf->sc->ih;
581
582 if (ret != NULL) {
583 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
584 reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
585 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
586
587 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
588 reg |= PCMCIA_CCR_STATUS_INTRACK;
589 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
590 }
591 } else {
592 ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
593 pf, ipl, ih_fct, ih_arg);
594 }
595
596 return (ret);
597 }
598
599 void
600 pcmcia_intr_disestablish(pf, ih)
601 struct pcmcia_function *pf;
602 void *ih;
603 {
604
605 /* behave differently if this is a multifunction card */
606
607 if (pcmcia_mfc(pf->sc)) {
608 int s, ihcnt, hiipl;
609 struct pcmcia_function *pf2;
610
611 /*
612 * mask all the ipl's which are already used by this card,
613 * and find the highest ipl number (lowest priority). Skip
614 * the current function.
615 */
616
617 ihcnt = 0;
618 s = 0; /* this is only here to keep the compipler
619 happy */
620 hiipl = 0; /* this is only here to keep the compipler
621 happy */
622
623 for (pf2 = pf->sc->card.pf_head.sqh_first; pf2 != NULL;
624 pf2 = pf2->pf_list.sqe_next) {
625 if (pf2 == pf)
626 continue;
627
628 if (pf2->ih_fct) {
629 if (ihcnt == 0) {
630 s = splraise(pf2->ih_ipl);
631 hiipl = pf2->ih_ipl;
632 ihcnt++;
633 } else {
634 splraise(pf2->ih_ipl);
635 if (pf2->ih_ipl > hiipl)
636 hiipl = pf2->ih_ipl;
637 }
638 }
639 }
640
641 /* null out the handler for this function */
642
643 pf->ih_fct = NULL;
644 pf->ih_arg = NULL;
645
646 /*
647 * if the ih being removed is lower priority than the lowest
648 * priority remaining interrupt, up the priority.
649 */
650
651 #ifdef DIAGNOSTIC
652 if (ihcnt == 0) {
653 panic("can't remove a handler from a card which has none");
654 } else
655 #endif
656 if (ihcnt == 1) {
657 #ifdef DIAGNOSTIC
658 if (pf->sc->ih == NULL)
659 panic("disestablishing last function, but card has no ih");
660 #endif
661 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
662 pf->sc->ih);
663 pf->sc->ih = NULL;
664 } else if (pf->ih_ipl > hiipl) {
665 #ifdef DIAGNOSTIC
666 if (pf->sc->ih == NULL)
667 panic("changing ih ipl, but card has no ih");
668 #endif
669 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
670 pf->sc->ih);
671 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
672 pf->sc->pch, pf, hiipl, pcmcia_card_intr, pf->sc);
673 }
674 if (ihcnt)
675 splx(s);
676 } else {
677 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
678 }
679 }
680
681 int
682 pcmcia_card_intr(arg)
683 void *arg;
684 {
685 struct pcmcia_softc *sc = arg;
686 struct pcmcia_function *pf;
687 int reg, ret, ret2;
688
689 ret = 0;
690
691 for (pf = sc->card.pf_head.sqh_first; pf != NULL;
692 pf = pf->pf_list.sqe_next) {
693 #if 0
694 printf("%s: intr fct=%d physaddr=%lx cor=%02x csr=%02x pin=%02x",
695 sc->dev.dv_xname, pf->number,
696 pmap_extract(pmap_kernel(),
697 (vm_offset_t) pf->ccrh) + pf->ccr_offset,
698 bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
699 pf->pf_ccr_offset + PCMCIA_CCR_OPTION),
700 bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
701 pf->pf_ccr_offset + PCMCIA_CCR_STATUS),
702 bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
703 pf->pf_ccr_offset + PCMCIA_CCR_PIN));
704 #endif
705 if (pf->ih_fct != NULL &&
706 (pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) {
707 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
708 if (reg & PCMCIA_CCR_STATUS_INTR) {
709 ret2 = (*pf->ih_fct)(pf->ih_arg);
710 if (ret2 != 0 && ret == 0)
711 ret = ret2;
712 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
713 #if 0
714 printf("; csr %02x->%02x",
715 reg, reg & ~PCMCIA_CCR_STATUS_INTR);
716 #endif
717 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
718 reg & ~PCMCIA_CCR_STATUS_INTR);
719 }
720 }
721 #if 0
722 printf("\n");
723 #endif
724 }
725
726 return (ret);
727 }
728