Annotation of sys/dev/pcmcia/pcmcia.c, Revision 1.2
1.1 nbrk 1: /* $OpenBSD: pcmcia.c,v 1.37 2006/04/16 20:43:12 miod 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
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: /* If the autoconfiguration got this far, there's a socket here. */
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: * this is here so that when socket_enable calls gettype, trt happens
172: */
1.2 ! nbrk 173: printf("pcmcia_card_attach\n");
1.1 nbrk 174: SIMPLEQ_FIRST(&sc->card.pf_head) = NULL;
175:
176: pcmcia_chip_socket_enable(sc->pct, sc->pch);
1.2 ! nbrk 177: printf("pcmcia_chip_socket_enable\n");
1.1 nbrk 178:
179: pcmcia_read_cis(sc);
1.2 ! nbrk 180: printf("pcmcia_read_cis\n");
1.1 nbrk 181:
182: pcmcia_chip_socket_disable(sc->pct, sc->pch);
1.2 ! nbrk 183: printf("pcmcia_chip_socket_disable\n");
1.1 nbrk 184:
185: pcmcia_check_cis_quirks(sc);
1.2 ! nbrk 186: printf("pcmcia_check_cis_quirks\n");
1.1 nbrk 187:
188: /*
189: * Bail now if there was an error in the CIS.
190: */
191:
192: if (sc->card.error)
193: return (1);
194:
195: #if 0
196: if (SIMPLEQ_EMPTY(&sc->card.pf_head))
197: return (1);
198: #endif
199:
200: if (pcmcia_verbose)
201: pcmcia_print_cis(sc);
202:
203: /*
204: * If there was no function, this might be CIS-less card we still
205: * want to probe. Fixup a function element for it.
206: */
207: if (SIMPLEQ_FIRST(&sc->card.pf_head) == NULL) {
208: pf = malloc(sizeof *pf, M_DEVBUF, M_NOWAIT);
209: if (pf == NULL)
210: panic("pcmcia_card_attach");
211: bzero(pf, sizeof *pf);
212: pf->number = 0;
213: pf->pf_flags = PFF_FAKE;
214: pf->last_config_index = -1;
215: SIMPLEQ_INIT(&pf->cfe_head);
216: SIMPLEQ_INSERT_TAIL(&sc->card.pf_head, pf, pf_list);
217: }
218:
219: attached = 0;
220:
221: for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
222: pf = SIMPLEQ_NEXT(pf, pf_list)) {
223: pf->sc = sc;
224: pf->child = NULL;
225: pf->cfe = NULL;
226: pf->ih_fct = NULL;
227: pf->ih_arg = NULL;
228: }
229:
230: for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
231: pf = SIMPLEQ_NEXT(pf, pf_list)) {
232: paa.manufacturer = sc->card.manufacturer;
233: paa.product = sc->card.product;
234: paa.card = &sc->card;
235: paa.pf = pf;
236:
237: pf->child = config_found_sm(&sc->dev, &paa, pcmcia_print,
238: pcmcia_submatch);
239: if (pf->child) {
240: attached++;
241:
242: if ((pf->pf_flags & PFF_FAKE) == 0)
243: DPRINTF(("%s: function %d CCR at %d offset %lx"
244: ": %x %x %x %x, %x %x %x %x, %x\n",
245: sc->dev.dv_xname, pf->number,
246: pf->pf_ccr_window, pf->pf_ccr_offset,
247: pcmcia_ccr_read(pf, 0x00),
248: pcmcia_ccr_read(pf, 0x02),
249: pcmcia_ccr_read(pf, 0x04),
250: pcmcia_ccr_read(pf, 0x06),
251: pcmcia_ccr_read(pf, 0x0A),
252: pcmcia_ccr_read(pf, 0x0C),
253: pcmcia_ccr_read(pf, 0x0E),
254: pcmcia_ccr_read(pf, 0x10),
255: pcmcia_ccr_read(pf, 0x12)));
256: }
257: }
258: return (attached ? 0 : 1);
259: }
260:
261: void
262: pcmcia_card_detach(dev, flags)
263: struct device *dev;
264: int flags; /* DETACH_* flags */
265: {
266: struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
267: struct pcmcia_function *pf;
268: int error;
269:
270: /*
271: * We are running on either the PCMCIA socket's event thread
272: * or in user context detaching a device by user request.
273: */
274: for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
275: pf = SIMPLEQ_NEXT(pf, pf_list)) {
276: if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
277: continue;
278: if (pf->child == NULL)
279: continue;
280: DPRINTF(("%s: detaching %s (function %d)\n",
281: sc->dev.dv_xname, pf->child->dv_xname, pf->number));
282: if ((error = config_detach(pf->child, flags)) != 0) {
283: printf("%s: error %d detaching %s (function %d)\n",
284: sc->dev.dv_xname, error, pf->child->dv_xname,
285: pf->number);
286: } else
287: pf->child = NULL;
288: }
289: }
290:
291: void
292: pcmcia_card_deactivate(dev)
293: struct device *dev;
294: {
295: struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
296: struct pcmcia_function *pf;
297:
298: /*
299: * We're in the chip's card removal interrupt handler.
300: * Deactivate the child driver. The PCMCIA socket's
301: * event thread will run later to finish the detach.
302: */
303: for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
304: pf = SIMPLEQ_NEXT(pf, pf_list)) {
305: if (SIMPLEQ_FIRST(&pf->cfe_head) == NULL)
306: continue;
307: if (pf->child == NULL)
308: continue;
309: DPRINTF(("%s: deactivating %s (function %d)\n",
310: sc->dev.dv_xname, pf->child->dv_xname, pf->number));
311: config_deactivate(pf->child);
312: }
313: }
314:
315: int
316: pcmcia_submatch(parent, match, aux)
317: struct device *parent;
318: void *match, *aux;
319: {
320: struct cfdata *cf = match;
321: struct pcmcia_attach_args *paa = aux;
322:
323: if (cf->cf_loc[0 /* PCMCIACF_FUNCTION */] !=
324: -1 /* PCMCIACF_FUNCTION_DEFAULT */ &&
325: cf->cf_loc[0 /* PCMCIACF_FUNCTION */] != paa->pf->number)
326: return (0);
327:
328: return ((*cf->cf_attach->ca_match)(parent, cf, aux));
329: }
330:
331: int
332: pcmcia_print(arg, pnp)
333: void *arg;
334: const char *pnp;
335: {
336: struct pcmcia_attach_args *pa = arg;
337: struct pcmcia_softc *sc = pa->pf->sc;
338: struct pcmcia_card *card = &sc->card;
339: int i;
340:
341: if (pnp) {
342: for (i = 0; i < 4 && card->cis1_info[i]; i++)
343: printf("%s%s", i ? ", " : "\"", card->cis1_info[i]);
344: if (i != 0)
345: printf("\"");
346:
347: if (card->manufacturer != PCMCIA_VENDOR_INVALID &&
348: card->product != PCMCIA_PRODUCT_INVALID) {
349: if (i != 0)
350: printf(" ");
351: printf("(");
352: if (card->manufacturer != PCMCIA_VENDOR_INVALID)
353: printf("manufacturer 0x%x%s",
354: card->manufacturer,
355: card->product == PCMCIA_PRODUCT_INVALID ?
356: "" : ", ");
357: if (card->product != PCMCIA_PRODUCT_INVALID)
358: printf("product 0x%x",
359: card->product);
360: printf(")");
361: }
362: if (i != 0)
363: printf(" ");
364: printf("at %s", pnp);
365: }
366: printf(" function %d", pa->pf->number);
367:
368: if (!pnp) {
369: for (i = 0; i < 3 && card->cis1_info[i]; i++)
370: printf("%s%s", i ? ", " : " \"", card->cis1_info[i]);
371: if (i != 0)
372: printf("\"");
373: }
374:
375: return (UNCONF);
376: }
377:
378: int
379: pcmcia_card_gettype(dev)
380: struct device *dev;
381: {
382: struct pcmcia_softc *sc = (struct pcmcia_softc *)dev;
383: struct pcmcia_function *pf;
384:
385: /*
386: * Set the iftype to memory if this card has no functions (not yet
387: * probed), or only one function, and that is not initialized yet or
388: * that is memory.
389: */
390: pf = SIMPLEQ_FIRST(&sc->card.pf_head);
391: if (pf == NULL || (SIMPLEQ_NEXT(pf, pf_list) == NULL &&
392: ((pf->pf_flags & PFF_FAKE) ||
393: pf->cfe == NULL || pf->cfe->iftype == PCMCIA_IFTYPE_MEMORY)))
394: return (PCMCIA_IFTYPE_MEMORY);
395: else
396: return (PCMCIA_IFTYPE_IO);
397: }
398:
399: /*
400: * Initialize a PCMCIA function. May be called as long as the function is
401: * disabled.
402: */
403: void
404: pcmcia_function_init(pf, cfe)
405: struct pcmcia_function *pf;
406: struct pcmcia_config_entry *cfe;
407: {
408: if (pf->pf_flags & PFF_ENABLED)
409: panic("pcmcia_function_init: function is enabled");
410:
411: /* Remember which configuration entry we are using. */
412: pf->cfe = cfe;
413: }
414:
415: static inline void pcmcia_socket_enable(pct, pch)
416: pcmcia_chipset_tag_t pct;
417: pcmcia_chipset_handle_t *pch;
418: {
419: pcmcia_chip_socket_enable(pct, pch);
420: }
421:
422: static inline void pcmcia_socket_disable(pct, pch)
423: pcmcia_chipset_tag_t pct;
424: pcmcia_chipset_handle_t *pch;
425: {
426: pcmcia_chip_socket_disable(pct, pch);
427: }
428:
429: /* Enable a PCMCIA function */
430: int
431: pcmcia_function_enable(pf)
432: struct pcmcia_function *pf;
433: {
434: struct pcmcia_function *tmp;
435: int reg;
436:
437: if (pf->cfe == NULL)
438: panic("pcmcia_function_enable: function not initialized");
439:
440: /*
441: * Increase the reference count on the socket, enabling power, if
442: * necessary.
443: */
444: if (pf->sc->sc_enabled_count++ == 0)
445: pcmcia_chip_socket_enable(pf->sc->pct, pf->sc->pch);
446: DPRINTF(("%s: ++enabled_count = %d\n", pf->sc->dev.dv_xname,
447: pf->sc->sc_enabled_count));
448:
449: if (pf->pf_flags & PFF_ENABLED) {
450: /*
451: * Don't do anything if we're already enabled.
452: */
453: DPRINTF(("%s: pcmcia_function_enable on enabled func\n"));
454: return (0);
455: }
456:
457: /* If there was no CIS don't mess with CCR */
458: if (pf->pf_flags & PFF_FAKE)
459: goto done;
460:
461: /*
462: * It's possible for different functions' CCRs to be in the same
463: * underlying page. Check for that.
464: */
465: SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
466: if ((tmp->pf_flags & PFF_ENABLED) &&
467: (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
468: ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
469: (tmp->ccr_base - tmp->pf_ccr_offset +
470: tmp->pf_ccr_realsize))) {
471: pf->pf_ccrt = tmp->pf_ccrt;
472: pf->pf_ccrh = tmp->pf_ccrh;
473: pf->pf_ccr_realsize = tmp->pf_ccr_realsize;
474:
475: /*
476: * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
477: * tmp->ccr_base) + pf->ccr_base;
478: */
479: pf->pf_ccr_offset =
480: (tmp->pf_ccr_offset + pf->ccr_base) -
481: tmp->ccr_base;
482: pf->pf_ccr_window = tmp->pf_ccr_window;
483: break;
484: }
485: }
486:
487: if (tmp == NULL) {
488: if (pcmcia_mem_alloc(pf, PCMCIA_CCR_SIZE, &pf->pf_pcmh))
489: goto bad;
490:
491: if (pcmcia_mem_map(pf, PCMCIA_MEM_ATTR, pf->ccr_base,
492: PCMCIA_CCR_SIZE, &pf->pf_pcmh, &pf->pf_ccr_offset,
493: &pf->pf_ccr_window)) {
494: pcmcia_mem_free(pf, &pf->pf_pcmh);
495: goto bad;
496: }
497: }
498:
499: reg = (pf->cfe->number & PCMCIA_CCR_OPTION_CFINDEX);
500: reg |= PCMCIA_CCR_OPTION_LEVIREQ;
501: if (pcmcia_mfc(pf->sc)) {
502: reg |= PCMCIA_CCR_OPTION_FUNC_ENABLE;
503: if (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))
504: reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
505: if (pf->ih_fct)
506: reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
507:
508: }
509:
510: pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
511:
512: reg = 0;
513:
514: if ((pf->cfe->flags & PCMCIA_CFE_IO16) == 0)
515: reg |= PCMCIA_CCR_STATUS_IOIS8;
516: if (pf->cfe->flags & PCMCIA_CFE_AUDIO)
517: reg |= PCMCIA_CCR_STATUS_AUDIO;
518: pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
519:
520: pcmcia_ccr_write(pf, PCMCIA_CCR_SOCKETCOPY, 0);
521:
522: if (pcmcia_mfc(pf->sc)) {
523: pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
524: (pf->pf_mfc_iobase >> 0) & 0xff);
525: pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
526: (pf->pf_mfc_iobase >> 8) & 0xff);
527: pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
528: (pf->pf_mfc_iobase >> 16) & 0xff);
529: pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
530: (pf->pf_mfc_iobase >> 24) & 0xff);
531: pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
532: pf->pf_mfc_iomax - pf->pf_mfc_iobase);
533: }
534:
535: #ifdef PCMCIADEBUG
536: SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
537: printf("%s: function %d CCR at %d offset %lx: "
538: "%x %x %x %x, %x %x %x %x, %x\n",
539: tmp->sc->dev.dv_xname, tmp->number,
540: tmp->pf_ccr_window, tmp->pf_ccr_offset,
541: pcmcia_ccr_read(tmp, 0x00),
542: pcmcia_ccr_read(tmp, 0x02),
543: pcmcia_ccr_read(tmp, 0x04),
544: pcmcia_ccr_read(tmp, 0x06),
545:
546: pcmcia_ccr_read(tmp, 0x0A),
547: pcmcia_ccr_read(tmp, 0x0C),
548: pcmcia_ccr_read(tmp, 0x0E),
549: pcmcia_ccr_read(tmp, 0x10),
550:
551: pcmcia_ccr_read(tmp, 0x12));
552: }
553: #endif
554:
555: done:
556: pf->pf_flags |= PFF_ENABLED;
557: delay(1000);
558: return (0);
559:
560: bad:
561: /*
562: * Decrement the reference count, and power down the socket, if
563: * necessary.
564: */
565: if (--pf->sc->sc_enabled_count == 0)
566: pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
567: DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
568: pf->sc->sc_enabled_count));
569:
570: return (1);
571: }
572:
573: /* Disable PCMCIA function. */
574: void
575: pcmcia_function_disable(pf)
576: struct pcmcia_function *pf;
577: {
578: struct pcmcia_function *tmp;
579:
580: if (pf->cfe == NULL)
581: panic("pcmcia_function_enable: function not initialized");
582:
583: if ((pf->pf_flags & PFF_ENABLED) == 0) {
584: /*
585: * Don't do anything if we're already disabled.
586: */
587: return;
588: }
589:
590: /* If there was no CIS don't mess with CCR */
591: if (pf->pf_flags & PFF_FAKE) {
592: pf->pf_flags &= ~PFF_ENABLED;
593: goto done;
594: }
595:
596: /*
597: * it's possible for different functions' CCRs to be in the same
598: * underlying page. Check for that. Note we mark us as disabled
599: * first to avoid matching ourself.
600: */
601: pf->pf_flags &= ~PFF_ENABLED;
602: SIMPLEQ_FOREACH(tmp, &pf->sc->card.pf_head, pf_list) {
603: if ((tmp->pf_flags & PFF_ENABLED) &&
604: (pf->ccr_base >= (tmp->ccr_base - tmp->pf_ccr_offset)) &&
605: ((pf->ccr_base + PCMCIA_CCR_SIZE) <=
606: (tmp->ccr_base - tmp->pf_ccr_offset + tmp->pf_ccr_realsize)))
607: break;
608: }
609:
610: /* Not used by anyone else; unmap the CCR. */
611: if (tmp == NULL) {
612: pcmcia_mem_unmap(pf, pf->pf_ccr_window);
613: pcmcia_mem_free(pf, &pf->pf_pcmh);
614: }
615:
616: done:
617: /*
618: * Decrement the reference count, and power down the socket, if
619: * necessary.
620: */
621: if (--pf->sc->sc_enabled_count == 0)
622: pcmcia_chip_socket_disable(pf->sc->pct, pf->sc->pch);
623: DPRINTF(("%s: --enabled_count = %d\n", pf->sc->dev.dv_xname,
624: pf->sc->sc_enabled_count));
625: }
626:
627: int
628: pcmcia_io_map(pf, width, offset, size, pcihp, windowp)
629: struct pcmcia_function *pf;
630: int width;
631: bus_addr_t offset;
632: bus_size_t size;
633: struct pcmcia_io_handle *pcihp;
634: int *windowp;
635: {
636: int reg;
637:
638: if (pcmcia_chip_io_map(pf->sc->pct, pf->sc->pch,
639: width, offset, size, pcihp, windowp))
640: return (1);
641:
642: /*
643: * XXX In the multifunction multi-iospace-per-function case, this
644: * needs to cooperate with io_alloc to make sure that the spaces
645: * don't overlap, and that the ccr's are set correctly.
646: */
647:
648: if (pcmcia_mfc(pf->sc) &&
649: (pf->ccr_mask & (1 << (PCMCIA_CCR_IOBASE0 / 2)))) {
650: bus_addr_t iobase = pcihp->addr;
651: bus_addr_t iomax = pcihp->addr + pcihp->size - 1;
652:
653: if (pf->pf_mfc_iomax == 0) {
654: pf->pf_mfc_iobase = iobase;
655: pf->pf_mfc_iomax = iomax;
656: } else {
657: if (iobase < pf->pf_mfc_iobase)
658: pf->pf_mfc_iobase = iobase;
659: if (iomax > pf->pf_mfc_iomax)
660: pf->pf_mfc_iomax = iomax;
661: }
662:
663: pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE0,
664: (pf->pf_mfc_iobase >> 0) & 0xff);
665: pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE1,
666: (pf->pf_mfc_iobase >> 8) & 0xff);
667: pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE2,
668: (pf->pf_mfc_iobase >> 16) & 0xff);
669: pcmcia_ccr_write(pf, PCMCIA_CCR_IOBASE3,
670: (pf->pf_mfc_iobase >> 24) & 0xff);
671: pcmcia_ccr_write(pf, PCMCIA_CCR_IOSIZE,
672: pf->pf_mfc_iomax - pf->pf_mfc_iobase);
673:
674: reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
675: reg |= PCMCIA_CCR_OPTION_ADDR_DECODE;
676: pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
677: }
678: return (0);
679: }
680:
681: void *
682: pcmcia_intr_establish(pf, ipl, ih_fct, ih_arg, xname)
683: struct pcmcia_function *pf;
684: int ipl;
685: int (*ih_fct)(void *);
686: void *ih_arg;
687: char *xname;
688: {
689: void *ret;
690: int s, ihcnt, hiipl, reg;
691: struct pcmcia_function *pf2;
692:
693: /* Behave differently if this is a multifunction card. */
694: if (pcmcia_mfc(pf->sc)) {
695: /*
696: * Mask all the ipl's which are already used by this card,
697: * and find the highest ipl number (lowest priority).
698: */
699: ihcnt = 0;
700: SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
701: if (pf2->ih_fct) {
702: DPRINTF(("%s: function %d has ih_fct %p\n",
703: pf->sc->dev.dv_xname, pf2->number,
704: pf2->ih_fct));
705:
706: if (ihcnt == 0)
707: hiipl = pf2->ih_ipl;
708: else if (pf2->ih_ipl > hiipl)
709: hiipl = pf2->ih_ipl;
710:
711: ihcnt++;
712: }
713: }
714:
715: /*
716: * Establish the real interrupt, changing the ipl if
717: * necessary.
718: */
719: if (ihcnt == 0) {
720: #ifdef DIAGNOSTIC
721: if (pf->sc->ih != NULL)
722: panic("card has intr handler, "
723: "but no function does");
724: #endif
725: s = spltty();
726:
727: /* Set up the handler for the new function. */
728: pf->ih_fct = ih_fct;
729: pf->ih_arg = ih_arg;
730: pf->ih_ipl = ipl;
731:
732: pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
733: pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
734: xname);
735: splx(s);
736: } else if (ipl > hiipl) {
737: #ifdef DIAGNOSTIC
738: if (pf->sc->ih == NULL)
739: panic("functions have ih, "
740: "but the card does not");
741: #endif
742:
743: s = spltty();
744:
745: pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
746: pf->sc->ih);
747:
748: /* set up the handler for the new function */
749: pf->ih_fct = ih_fct;
750: pf->ih_arg = ih_arg;
751: pf->ih_ipl = ipl;
752:
753: pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
754: pf->sc->pch, pf, ipl, pcmcia_card_intr, pf->sc,
755: xname);
756:
757: splx(s);
758: } else {
759: s = spltty();
760:
761: /* Set up the handler for the new function. */
762: pf->ih_fct = ih_fct;
763: pf->ih_arg = ih_arg;
764: pf->ih_ipl = ipl;
765:
766: splx(s);
767: }
768:
769: ret = pf->sc->ih;
770:
771: if (ret != NULL) {
772: reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
773: reg |= PCMCIA_CCR_OPTION_IREQ_ENABLE;
774: pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
775:
776: reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
777: reg |= PCMCIA_CCR_STATUS_INTRACK;
778: pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS, reg);
779: }
780: } else
781: ret = pcmcia_chip_intr_establish(pf->sc->pct, pf->sc->pch,
782: pf, ipl, ih_fct, ih_arg, xname);
783:
784: return (ret);
785: }
786:
787: void
788: pcmcia_intr_disestablish(pf, ih)
789: struct pcmcia_function *pf;
790: void *ih;
791: {
792: int s, reg, ihcnt, hiipl;
793: struct pcmcia_function *pf2;
794:
795: /* Behave differently if this is a multifunction card. */
796: if (pcmcia_mfc(pf->sc)) {
797: /*
798: * Mask all the ipl's which are already used by this card,
799: * and find the highest ipl number (lowest priority). Skip
800: * the current function.
801: */
802: ihcnt = 0;
803: SIMPLEQ_FOREACH(pf2, &pf->sc->card.pf_head, pf_list) {
804: if (pf2 == pf)
805: continue;
806:
807: if (pf2->ih_fct) {
808: if (ihcnt == 0)
809: hiipl = pf2->ih_ipl;
810: else if (pf2->ih_ipl > hiipl)
811: hiipl = pf2->ih_ipl;
812: ihcnt++;
813: }
814: }
815:
816: /*
817: * If the ih being removed is lower priority than the lowest
818: * priority remaining interrupt, up the priority.
819: */
820:
821: /*
822: * ihcnt is the number of interrupt handlers *not* including
823: * the one about to be removed.
824: */
825: if (ihcnt == 0) {
826: #ifdef DIAGNOSTIC
827: if (pf->sc->ih == NULL)
828: panic("disestablishing last function, but card has no ih");
829: #endif
830: pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
831: pf->sc->ih);
832:
833: reg = pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION);
834: reg &= ~PCMCIA_CCR_OPTION_IREQ_ENABLE;
835: pcmcia_ccr_write(pf, PCMCIA_CCR_OPTION, reg);
836:
837: pf->ih_fct = NULL;
838: pf->ih_arg = NULL;
839:
840: pf->sc->ih = NULL;
841: } else if (pf->ih_ipl > hiipl) {
842: #ifdef DIAGNOSTIC
843: if (pf->sc->ih == NULL)
844: panic("changing ih ipl, but card has no ih");
845: #endif
846: s = spltty();
847:
848: pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch,
849: pf->sc->ih);
850: pf->sc->ih = pcmcia_chip_intr_establish(pf->sc->pct,
851: pf->sc->pch, pf, hiipl, pcmcia_card_intr, pf->sc,
852: NULL);
853:
854: /* Null out the handler for this function. */
855: pf->ih_fct = NULL;
856: pf->ih_arg = NULL;
857:
858: splx(s);
859: } else {
860: s = spltty();
861:
862: pf->ih_fct = NULL;
863: pf->ih_arg = NULL;
864:
865: splx(s);
866: }
867: } else
868: pcmcia_chip_intr_disestablish(pf->sc->pct, pf->sc->pch, ih);
869: }
870:
871: const char *
872: pcmcia_intr_string(pf, ih)
873: struct pcmcia_function *pf;
874: void *ih;
875: {
876: return pcmcia_chip_intr_string(pf->sc->pct, pf->sc->pch, ih);
877: }
878:
879: int
880: pcmcia_card_intr(arg)
881: void *arg;
882: {
883: struct pcmcia_softc *sc = arg;
884: struct pcmcia_function *pf;
885: int reg, ret, ret2;
886:
887: ret = 0;
888:
889: for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL;
890: pf = SIMPLEQ_NEXT(pf, pf_list)) {
891: #ifdef PCMCIADEBUG
892: printf("%s: intr flags=%x fct=%d cor=%02x csr=%02x pin=%02x",
893: sc->dev.dv_xname, pf->pf_flags, pf->number,
894: pcmcia_ccr_read(pf, PCMCIA_CCR_OPTION),
895: pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS),
896: pcmcia_ccr_read(pf, PCMCIA_CCR_PIN));
897: #endif
898: if (pf->ih_fct != NULL &&
899: (pf->ccr_mask & (1 << (PCMCIA_CCR_STATUS / 2)))) {
900: reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
901: if (reg & PCMCIA_CCR_STATUS_INTR) {
902: ret2 = (*pf->ih_fct)(pf->ih_arg);
903: if (ret2 != 0 && ret == 0)
904: ret = ret2;
905: reg = pcmcia_ccr_read(pf, PCMCIA_CCR_STATUS);
906: #ifdef PCMCIADEBUG
907: printf("; csr %02x->%02x",
908: reg, reg & ~PCMCIA_CCR_STATUS_INTR);
909: #endif
910: pcmcia_ccr_write(pf, PCMCIA_CCR_STATUS,
911: reg & ~PCMCIA_CCR_STATUS_INTR);
912: }
913: }
914: #ifdef PCMCIADEBUG
915: printf("\n");
916: #endif
917: }
918:
919: return (ret);
920: }
CVSweb