This source file includes following definitions.
- pcmcia_ccr_read
- pcmcia_ccr_write
- pcmcia_match
- pcmcia_attach
- pcmcia_power
- pcmcia_card_attach
- pcmcia_card_detach
- pcmcia_card_deactivate
- pcmcia_submatch
- pcmcia_print
- pcmcia_card_gettype
- pcmcia_function_init
- pcmcia_socket_enable
- pcmcia_socket_disable
- pcmcia_function_enable
- pcmcia_function_disable
- pcmcia_io_map
- pcmcia_intr_establish
- pcmcia_intr_disestablish
- pcmcia_intr_string
- pcmcia_card_intr
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
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
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
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
112 return (1);
113 }
114
115 void
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
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
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
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
184
185
186
187 if (sc->card.error)
188 return (1);
189
190 #if 0
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
200
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
257 pcmcia_card_detach(dev, flags)
258 struct device *dev;
259 int flags;
260 {
261 struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
262 struct pcmcia_function *pf;
263 int error;
264
265
266
267
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
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
295
296
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
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 ] !=
319 -1 &&
320 cf->cf_loc[0 ] != paa->pf->number)
321 return (0);
322
323 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
324 }
325
326 int
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 if (i != 0)
340 printf("\"");
341
342 if (card->manufacturer != PCMCIA_VENDOR_INVALID &&
343 card->product != PCMCIA_PRODUCT_INVALID) {
344 if (i != 0)
345 printf(" ");
346 printf("(");
347 if (card->manufacturer != PCMCIA_VENDOR_INVALID)
348 printf("manufacturer 0x%x%s",
349 card->manufacturer,
350 card->product == PCMCIA_PRODUCT_INVALID ?
351 "" : ", ");
352 if (card->product != PCMCIA_PRODUCT_INVALID)
353 printf("product 0x%x",
354 card->product);
355 printf(")");
356 }
357 if (i != 0)
358 printf(" ");
359 printf("at %s", pnp);
360 }
361 printf(" function %d", pa->pf->number);
362
363 if (!pnp) {
364 for (i = 0; i < 3 && card->cis1_info[i]; i++)
365 printf("%s%s", i ? ", " : " \"", card->cis1_info[i]);
366 if (i != 0)
367 printf("\"");
368 }
369
370 return (UNCONF);
371 }
372
373 int
374 pcmcia_card_gettype(dev)
375 struct device *dev;
376 {
377 struct pcmcia_softc *sc = (struct pcmcia_softc *)dev;
378 struct pcmcia_function *pf;
379
380
381
382
383
384
385 pf = SIMPLEQ_FIRST(&sc->card.pf_head);
386 if (pf == NULL || (SIMPLEQ_NEXT(pf, pf_list) == NULL &&
387 ((pf->pf_flags & PFF_FAKE) ||
388 pf->cfe == NULL || pf->cfe->iftype == PCMCIA_IFTYPE_MEMORY)))
389 return (PCMCIA_IFTYPE_MEMORY);
390 else
391 return (PCMCIA_IFTYPE_IO);
392 }
393
394
395
396
397
398 void
399 pcmcia_function_init(pf, cfe)
400 struct pcmcia_function *pf;
401 struct pcmcia_config_entry *cfe;
402 {
403 if (pf->pf_flags & PFF_ENABLED)
404 panic("pcmcia_function_init: function is enabled");
405
406
407 pf->cfe = cfe;
408 }
409
410 static inline void pcmcia_socket_enable(pct, pch)
411 pcmcia_chipset_tag_t pct;
412 pcmcia_chipset_handle_t *pch;
413 {
414 pcmcia_chip_socket_enable(pct, pch);
415 }
416
417 static inline void pcmcia_socket_disable(pct, pch)
418 pcmcia_chipset_tag_t pct;
419 pcmcia_chipset_handle_t *pch;
420 {
421 pcmcia_chip_socket_disable(pct, pch);
422 }
423
424
425 int
426 pcmcia_function_enable(pf)
427 struct pcmcia_function *pf;
428 {
429 struct pcmcia_function *tmp;
430 int reg;
431
432 if (pf->cfe == NULL)
433 panic("pcmcia_function_enable: function not initialized");
434
435
436
437
438
439 if (pf->sc->sc_enabled_count++ == 0)
440 pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
441 DPRINTF(("%s: ++enabled_count = %d\n", pf->sc->dev.dv_xname,
442 pf->sc->sc_enabled_count));
443
444 if (pf->pf_flags & PFF_ENABLED) {
445
446
447
448 DPRINTF(("%s: pcmcia_function_enable on enabled func\n"));
449 return (0);
450 }
451
452
453 if (pf->pf_flags & PFF_FAKE)
454 goto done;
455
456
457
458
459
460 SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
461 if ((tmp->pf_flags & PFF_ENABLED) &&
462 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
463 ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
464 (tmp->ccr_base - tmp->pf_ccr_offset +
465 tmp->pf_ccr_realsize))) {
466 pf->pf_ccrt = tmp->pf_ccrt;
467 pf->pf_ccrh = tmp->pf_ccrh;
468 pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
469
470
471
472
473
474 pf->pf_ccr_offset =
475 (tmp->pf_ccr_offset + pf->ccr_base) -
476 tmp->ccr_base;
477 pf->pf_ccr_window = tmp->pf_ccr_window;
478 break;
479 }
480 }
481
482 if (tmp == NULL) {
483 if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
484 goto bad;
485
486 if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
487 PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
488 &pf->pf_ccr_window)) {
489 pcmcia_mem_free(pf, &pf->pf_pcmh);
490 goto bad;
491 }
492 }
493
494 reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
495 reg |= PCMCIA_CCR_OPTION_LEVIREQ;
496 if (pcmcia_mfc(pf->sc)) {
497 reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
498 if (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))
499 reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
500 if (pf->ih_fct)
501 reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
502
503 }
504
505 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
506
507 reg = 0;
508
509 if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
510 reg |= PCMCIA_CCR_STATUS_IOIS8;
511 if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
512 reg |= PCMCIA_CCR_STATUS_AUDIO;
513 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
514
515 pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
516
517 if (pcmcia_mfc(pf->sc)) {
518 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
519 (pf->pf_mfc_iobase >> 0) & 0xff);
520 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
521 (pf->pf_mfc_iobase >> 8) & 0xff);
522 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
523 (pf->pf_mfc_iobase >> 16) & 0xff);
524 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
525 (pf->pf_mfc_iobase >> 24) & 0xff);
526 pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
527 pf->pf_mfc_iomax - pf->pf_mfc_iobase);
528 }
529
530 #ifdef PCMCIADEBUG
531 SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
532 printf("%s: function %d CCR at %d offset %lx: "
533 "%x %x %x %x, %x %x %x %x, %x\n",
534 tmp->sc->dev.dv_xname, tmp->number,
535 tmp->pf_ccr_window, tmp->pf_ccr_offset,
536 pcmcia_ccr_read(tmp, 0x00),
537 pcmcia_ccr_read(tmp, 0x02),
538 pcmcia_ccr_read(tmp, 0x04),
539 pcmcia_ccr_read(tmp, 0x06),
540
541 pcmcia_ccr_read(tmp, 0x0A),
542 pcmcia_ccr_read(tmp, 0x0C),
543 pcmcia_ccr_read(tmp, 0x0E),
544 pcmcia_ccr_read(tmp, 0x10),
545
546 pcmcia_ccr_read(tmp, 0x12));
547 }
548 #endif
549
550 done:
551 pf->pf_flags |= PFF_ENABLED;
552 delay(1000);
553 return (0);
554
555 bad:
556
557
558
559
560 if (--pf->sc->sc_enabled_count == 0)
561 pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
562 DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
563 pf->sc->sc_enabled_count));
564
565 return (1);
566 }
567
568
569 void
570 pcmcia_function_disable(pf)
571 struct pcmcia_function *pf;
572 {
573 struct pcmcia_function *tmp;
574
575 if (pf->cfe == NULL)
576 panic("pcmcia_function_enable: function not initialized");
577
578 if ((pf->pf_flags & PFF_ENABLED) == 0) {
579
580
581
582 return;
583 }
584
585
586 if (pf->pf_flags & PFF_FAKE) {
587 pf->pf_flags &= ~PFF_ENABLED;
588 goto done;
589 }
590
591
592
593
594
595
596 pf->pf_flags &= ~PFF_ENABLED;
597 SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
598 if ((tmp->pf_flags & PFF_ENABLED) &&
599 (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
600 ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
601 (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
602 break;
603 }
604
605
606 if (tmp == NULL) {
607 pcmcia_mem_unmap(pf, pf->pf_ccr_window);
608 pcmcia_mem_free(pf, &pf->pf_pcmh);
609 }
610
611 done:
612
613
614
615
616 if (--pf->sc->sc_enabled_count == 0)
617 pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
618 DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
619 pf->sc->sc_enabled_count));
620 }
621
622 int
623 pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
624 struct pcmcia_function *pf;
625 int width;
626 bus_addr_t offset;
627 bus_size_t size;
628 struct pcmcia_io_handle *pcihp;
629 int *windowp;
630 {
631 int reg;
632
633 if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
634 width, offset, size, pcihp, windowp))
635 return (1);
636
637
638
639
640
641
642
643 if (pcmcia_mfc(pf->sc) &&
644 (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))) {
645 bus_addr_t iobase = pcihp->addr;
646 bus_addr_t iomax = pcihp->addr + pcihp->size - 1;
647
648 if (pf->pf_mfc_iomax == 0) {
649 pf->pf_mfc_iobase = iobase;
650 pf->pf_mfc_iomax = iomax;
651 } else {
652 if (iobase < pf->pf_mfc_iobase)
653 pf->pf_mfc_iobase = iobase;
654 if (iomax > pf->pf_mfc_iomax)
655 pf->pf_mfc_iomax = iomax;
656 }
657
658 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
659 (pf->pf_mfc_iobase >> 0) & 0xff);
660 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
661 (pf->pf_mfc_iobase >> 8) & 0xff);
662 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
663 (pf->pf_mfc_iobase >> 16) & 0xff);
664 pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
665 (pf->pf_mfc_iobase >> 24) & 0xff);
666 pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
667 pf->pf_mfc_iomax - pf->pf_mfc_iobase);
668
669 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
670 reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
671 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
672 }
673 return (0);
674 }
675
676 void *
677 pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg, xname)
678 struct pcmcia_function *pf;
679 int ipl;
680 int (*ih_fct)(void *);
681 void *ih_arg;
682 char *xname;
683 {
684 void *ret;
685 int s, ihcnt, hiipl, reg;
686 struct pcmcia_function *pf2;
687
688
689 if (pcmcia_mfc(pf->sc)) {
690
691
692
693
694 ihcnt = 0;
695 SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
696 if (pf2->ih_fct) {
697 DPRINTF(("%s: function %d has ih_fct %p\n",
698 pf->sc->dev.dv_xname, pf2->number,
699 pf2->ih_fct));
700
701 if (ihcnt == 0)
702 hiipl = pf2->ih_ipl;
703 else if (pf2->ih_ipl > hiipl)
704 hiipl = pf2->ih_ipl;
705
706 ihcnt++;
707 }
708 }
709
710
711
712
713
714 if (ihcnt == 0) {
715 #ifdef DIAGNOSTIC
716 if (pf->sc->ih != NULL)
717 panic("card has intr handler, "
718 "but no function does");
719 #endif
720 s = spltty();
721
722
723 pf->ih_fct = ih_fct;
724 pf->ih_arg = ih_arg;
725 pf->ih_ipl = ipl;
726
727 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
728 pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
729 xname);
730 splx(s);
731 } else if (ipl > hiipl) {
732 #ifdef DIAGNOSTIC
733 if (pf->sc->ih == NULL)
734 panic("functions have ih, "
735 "but the card does not");
736 #endif
737
738 s = spltty();
739
740 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
741 pf->sc->ih);
742
743
744 pf->ih_fct = ih_fct;
745 pf->ih_arg = ih_arg;
746 pf->ih_ipl = ipl;
747
748 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
749 pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
750 xname);
751
752 splx(s);
753 } else {
754 s = spltty();
755
756
757 pf->ih_fct = ih_fct;
758 pf->ih_arg = ih_arg;
759 pf->ih_ipl = ipl;
760
761 splx(s);
762 }
763
764 ret = pf->sc->ih;
765
766 if (ret != NULL) {
767 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
768 reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
769 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
770
771 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
772 reg |= PCMCIA_CCR_STATUS_INTRACK;
773 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
774 }
775 } else
776 ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
777 pf, ipl, ih_fct, ih_arg, xname);
778
779 return (ret);
780 }
781
782 void
783 pcmcia_intr_disestablish(pf, ih)
784 struct pcmcia_function *pf;
785 void *ih;
786 {
787 int s, reg, ihcnt, hiipl;
788 struct pcmcia_function *pf2;
789
790
791 if (pcmcia_mfc(pf->sc)) {
792
793
794
795
796
797 ihcnt = 0;
798 SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
799 if (pf2 == pf)
800 continue;
801
802 if (pf2->ih_fct) {
803 if (ihcnt == 0)
804 hiipl = pf2->ih_ipl;
805 else if (pf2->ih_ipl > hiipl)
806 hiipl = pf2->ih_ipl;
807 ihcnt++;
808 }
809 }
810
811
812
813
814
815
816
817
818
819
820 if (ihcnt == 0) {
821 #ifdef DIAGNOSTIC
822 if (pf->sc->ih == NULL)
823 panic("disestablishing last function, but card has no ih");
824 #endif
825 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
826 pf->sc->ih);
827
828 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
829 reg &= ~PCMCIA_CCR_OPTION_IREQ_ENABLE;
830 pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
831
832 pf->ih_fct = NULL;
833 pf->ih_arg = NULL;
834
835 pf->sc->ih = NULL;
836 } else if (pf->ih_ipl > hiipl) {
837 #ifdef DIAGNOSTIC
838 if (pf->sc->ih == NULL)
839 panic("changing ih ipl, but card has no ih");
840 #endif
841 s = spltty();
842
843 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
844 pf->sc->ih);
845 pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
846 pf->sc->pch, pf, hiipl, pcmcia_card_intr, pf->sc,
847 NULL);
848
849
850 pf->ih_fct = NULL;
851 pf->ih_arg = NULL;
852
853 splx(s);
854 } else {
855 s = spltty();
856
857 pf->ih_fct = NULL;
858 pf->ih_arg = NULL;
859
860 splx(s);
861 }
862 } else
863 pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
864 }
865
866 const char *
867 pcmcia_intr_string(pf, ih)
868 struct pcmcia_function *pf;
869 void *ih;
870 {
871 return pcmcia_chip_intr_string(pf->sc->pct, pf->sc->pch, ih);
872 }
873
874 int
875 pcmcia_card_intr(arg)
876 void *arg;
877 {
878 struct pcmcia_softc *sc = arg;
879 struct pcmcia_function *pf;
880 int reg, ret, ret2;
881
882 ret = 0;
883
884 for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
885 pf = SIMPLEQ_NEXT(pf, pf_list)) {
886 #ifdef PCMCIADEBUG
887 printf("%s: intr flags=%x fct=%d cor=%02x csr=%02x pin=%02x",
888 sc->dev.dv_xname, pf->pf_flags, pf->number,
889 pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION),
890 pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS),
891 pcmcia_ccr_read(pf, PCMCIA_CCR_PIN));
892 #endif
893 if (pf->ih_fct != NULL &&
894 (pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) {
895 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
896 if (reg & PCMCIA_CCR_STATUS_INTR) {
897 ret2 = (*pf->ih_fct)(pf->ih_arg);
898 if (ret2 != 0 && ret == 0)
899 ret = ret2;
900 reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
901 #ifdef PCMCIADEBUG
902 printf("; csr %02x->%02x",
903 reg, reg & ~PCMCIA_CCR_STATUS_INTR);
904 #endif
905 pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
906 reg & ~PCMCIA_CCR_STATUS_INTR);
907 }
908 }
909 #ifdef PCMCIADEBUG
910 printf("\n");
911 #endif
912 }
913
914 return (ret);
915 }