Annotation of sys/dev/pcmcia/pcmcia.c, Revision 1.1.1.1
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: */
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: * Bail now if there was an error in the CIS.
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: * 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
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
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
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
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: * Set the iftype to memory if this card has no functions (not yet
382: * probed), or only one function, and that is not initialized yet or
383: * that is memory.
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: * Initialize a PCMCIA function. May be called as long as the function is
396: * disabled.
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: /* Remember which configuration entry we are using. */
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: /* Enable a PCMCIA function */
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: * Increase the reference count on the socket, enabling power, if
437: * necessary.
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: * Don't do anything if we're already enabled.
447: */
448: DPRINTF(("%s: pcmcia_function_enable on enabled func\n"));
449: return (0);
450: }
451:
452: /* If there was no CIS don't mess with CCR */
453: if (pf->pf_flags & PFF_FAKE)
454: goto done;
455:
456: /*
457: * It's possible for different functions' CCRs to be in the same
458: * underlying page. Check for that.
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: * pf->pf_ccr_offset = (tmp->pf_ccr_offset -
472: * tmp->ccr_base) + pf->ccr_base;
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: * Decrement the reference count, and power down the socket, if
558: * necessary.
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: /* Disable PCMCIA function. */
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: * Don't do anything if we're already disabled.
581: */
582: return;
583: }
584:
585: /* If there was no CIS don't mess with CCR */
586: if (pf->pf_flags & PFF_FAKE) {
587: pf->pf_flags &= ~PFF_ENABLED;
588: goto done;
589: }
590:
591: /*
592: * it's possible for different functions' CCRs to be in the same
593: * underlying page. Check for that. Note we mark us as disabled
594: * first to avoid matching ourself.
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: /* Not used by anyone else; unmap the CCR. */
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: * Decrement the reference count, and power down the socket, if
614: * necessary.
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: * XXX In the multifunction multi-iospace-per-function case, this
639: * needs to cooperate with io_alloc to make sure that the spaces
640: * don't overlap, and that the ccr's are set correctly.
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: /* Behave differently if this is a multifunction card. */
689: if (pcmcia_mfc(pf->sc)) {
690: /*
691: * Mask all the ipl's which are already used by this card,
692: * and find the highest ipl number (lowest priority).
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: * Establish the real interrupt, changing the ipl if
712: * necessary.
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: /* Set up the handler for the new function. */
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: /* set up the handler for the new function */
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: /* Set up the handler for the new function. */
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: /* Behave differently if this is a multifunction card. */
791: if (pcmcia_mfc(pf->sc)) {
792: /*
793: * Mask all the ipl's which are already used by this card,
794: * and find the highest ipl number (lowest priority). Skip
795: * the current function.
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: * If the ih being removed is lower priority than the lowest
813: * priority remaining interrupt, up the priority.
814: */
815:
816: /*
817: * ihcnt is the number of interrupt handlers *not* including
818: * the one about to be removed.
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: /* Null out the handler for this function. */
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: }
CVSweb