File:
[DragonFly] /
src /
sys /
bus /
pccard /
pccard_cis.c
Revision
1.1:
download - view:
text,
annotated -
select for diffs
Tue Feb 10 07:55:45 2004 UTC (9 years, 3 months ago) by
joerg
Branches:
MAIN
CVS tags:
HEAD
Initial backport of NEWCARD from FreeBSD 5.
The included version is from end of November 2002 with the exception of
bus/pccard/pccarddevs which is from November 2003.
Thanks to Warner Losh and the other folks for NEWCARD.
1: /* $NetBSD: pcmcia_cis.c,v 1.17 2000/02/10 09:01:52 chopps Exp $ */
2: /* $FreeBSD: src/sys/dev/pccard/pccard_cis.c,v 1.23 2002/11/14 14:02:32 mux Exp $ */
3: /* $DragonFly: src/sys/bus/pccard/pccard_cis.c,v 1.1 2004/02/10 07:55:45 joerg Exp $ */
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 <sys/param.h>
35: #include <sys/systm.h>
36: #include <sys/malloc.h>
37: #include <sys/module.h>
38: #include <sys/kernel.h>
39: #include <sys/queue.h>
40: #include <sys/types.h>
41:
42: #include <sys/bus.h>
43: #include <machine/bus.h>
44: #include <sys/rman.h>
45: #include <machine/resource.h>
46:
47: #include <bus/pccard/pccardreg.h>
48: #include <bus/pccard/pccardvar.h>
49:
50: #include "card_if.h"
51:
52: extern int pccard_cis_debug;
53:
54: #define PCCARDCISDEBUG
55: #ifdef PCCARDCISDEBUG
56: #define DPRINTF(arg) if (pccard_cis_debug) printf arg
57: #define DEVPRINTF(arg) if (pccard_cis_debug) device_printf arg
58: #else
59: #define DPRINTF(arg)
60: #define DEVPRINTF(arg)
61: #endif
62:
63: #define PCCARD_CIS_SIZE 1024
64:
65: struct cis_state {
66: int count;
67: int gotmfc;
68: struct pccard_config_entry temp_cfe;
69: struct pccard_config_entry *default_cfe;
70: struct pccard_card *card;
71: struct pccard_function *pf;
72: };
73:
74: int pccard_parse_cis_tuple(struct pccard_tuple *, void *);
75: static int decode_funce(struct pccard_tuple *, struct pccard_function *);
76:
77: void
78: pccard_read_cis(struct pccard_softc *sc)
79: {
80: struct cis_state state;
81:
82: bzero(&state, sizeof state);
83:
84: state.card = &sc->card;
85:
86: state.card->error = 0;
87: state.card->cis1_major = -1;
88: state.card->cis1_minor = -1;
89: state.card->cis1_info[0] = NULL;
90: state.card->cis1_info[1] = NULL;
91: state.card->cis1_info[2] = NULL;
92: state.card->cis1_info[3] = NULL;
93: state.card->manufacturer = PCMCIA_VENDOR_INVALID;
94: state.card->product = PCMCIA_PRODUCT_INVALID;
95: STAILQ_INIT(&state.card->pf_head);
96:
97: state.pf = NULL;
98:
99: if (pccard_scan_cis(sc->dev, pccard_parse_cis_tuple,
100: &state) == -1)
101: state.card->error++;
102: }
103:
104: int
105: pccard_scan_cis(device_t dev, int (*fct)(struct pccard_tuple *, void *),
106: void *arg)
107: {
108: struct resource *res;
109: int rid;
110: struct pccard_tuple tuple;
111: int longlink_present;
112: int longlink_common;
113: u_long longlink_addr;
114: int mfc_count;
115: int mfc_index;
116: struct {
117: int common;
118: u_long addr;
119: } mfc[256 / 5];
120: int ret;
121:
122: ret = 0;
123:
124: /* allocate some memory */
125:
126: rid = 0;
127: res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, ~0,
128: PCCARD_CIS_SIZE, RF_ACTIVE);
129: if (res == NULL) {
130: device_printf(dev, "can't alloc memory to read attributes\n");
131: return -1;
132: }
133: CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY,
134: rid, PCCARD_A_MEM_ATTR);
135: tuple.memt = rman_get_bustag(res);
136: tuple.memh = rman_get_bushandle(res);
137: tuple.ptr = 0;
138:
139: DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh));
140:
141: tuple.mult = 2;
142:
143: longlink_present = 1;
144: longlink_common = 1;
145: longlink_addr = 0;
146:
147: mfc_count = 0;
148: mfc_index = 0;
149:
150: DEVPRINTF((dev, "CIS tuple chain:\n"));
151:
152: while (1) {
153: while (1) {
154: /* get the tuple code */
155:
156: tuple.code = pccard_cis_read_1(&tuple, tuple.ptr);
157:
158: /* two special-case tuples */
159:
160: if (tuple.code == PCCARD_CISTPL_NULL) {
161: DPRINTF(("CISTPL_NONE\n 00\n"));
162: tuple.ptr++;
163: continue;
164: } else if (tuple.code == PCCARD_CISTPL_END) {
165: DPRINTF(("CISTPL_END\n ff\n"));
166: /* Call the function for the END tuple, since
167: the CIS semantics depend on it */
168: if ((*fct) (&tuple, arg)) {
169: ret = 1;
170: goto done;
171: }
172: tuple.ptr++;
173: break;
174: }
175: /* now all the normal tuples */
176:
177: tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1);
178: switch (tuple.code) {
179: case PCCARD_CISTPL_LONGLINK_A:
180: case PCCARD_CISTPL_LONGLINK_C:
181: if (tuple.length < 4) {
182: DPRINTF(("CISTPL_LONGLINK_%s too "
183: "short %d\n",
184: longlink_common ? "C" : "A",
185: tuple.length));
186: break;
187: }
188: longlink_present = 1;
189: longlink_common = (tuple.code ==
190: PCCARD_CISTPL_LONGLINK_C) ? 1 : 0;
191: longlink_addr = pccard_tuple_read_4(&tuple, 0);
192: DPRINTF(("CISTPL_LONGLINK_%s %lx\n",
193: longlink_common ? "C" : "A",
194: longlink_addr));
195: break;
196: case PCCARD_CISTPL_NO_LINK:
197: longlink_present = 0;
198: DPRINTF(("CISTPL_NO_LINK\n"));
199: break;
200: case PCCARD_CISTPL_CHECKSUM:
201: if (tuple.length < 5) {
202: DPRINTF(("CISTPL_CHECKSUM too "
203: "short %d\n", tuple.length));
204: break;
205: } {
206: int16_t offset;
207: u_long addr, length;
208: u_int cksum, sum;
209: int i;
210:
211: offset = (uint16_t)
212: pccard_tuple_read_2(&tuple, 0);
213: length = pccard_tuple_read_2(&tuple, 2);
214: cksum = pccard_tuple_read_1(&tuple, 4);
215:
216: addr = tuple.ptr + offset;
217:
218: DPRINTF(("CISTPL_CHECKSUM addr=%lx "
219: "len=%lx cksum=%x",
220: addr, length, cksum));
221:
222: /*
223: * XXX do more work to deal with
224: * distant regions
225: */
226: if ((addr >= PCCARD_CIS_SIZE) ||
227: ((addr + length) >=
228: PCCARD_CIS_SIZE)) {
229: DPRINTF((" skipped, "
230: "too distant\n"));
231: break;
232: }
233: sum = 0;
234: for (i = 0; i < length; i++)
235: sum +=
236: bus_space_read_1(tuple.memt,
237: tuple.memh,
238: addr + tuple.mult * i);
239: if (cksum != (sum & 0xff)) {
240: DPRINTF((" failed sum=%x\n",
241: sum));
242: device_printf(dev,
243: "CIS checksum failed\n");
244: #if 0
245: /*
246: * XXX Some working cards have
247: * XXX bad checksums!!
248: */
249: ret = -1;
250: #endif
251: } else {
252: DPRINTF((" ok\n"));
253: }
254: }
255: break;
256: case PCCARD_CISTPL_LONGLINK_MFC:
257: if (tuple.length < 1) {
258: DPRINTF(("CISTPL_LONGLINK_MFC too "
259: "short %d\n", tuple.length));
260: break;
261: }
262: if (((tuple.length - 1) % 5) != 0) {
263: DPRINTF(("CISTPL_LONGLINK_MFC bogus "
264: "length %d\n", tuple.length));
265: break;
266: }
267: /*
268: * this is kind of ad hoc, as I don't have
269: * any real documentation
270: */
271: {
272: int i, tmp_count;
273:
274: /*
275: * put count into tmp var so that
276: * if we have to bail (because it's
277: * a bogus count) it won't be
278: * remembered for later use.
279: */
280: tmp_count =
281: pccard_tuple_read_1(&tuple, 0);
282:
283: DPRINTF(("CISTPL_LONGLINK_MFC %d",
284: tmp_count));
285:
286: /*
287: * make _sure_ it's the right size;
288: * if too short, it may be a weird
289: * (unknown/undefined) format
290: */
291: if (tuple.length != (tmp_count*5 + 1)) {
292: DPRINTF((" bogus length %d\n",
293: tuple.length));
294: break;
295: }
296: /*
297: * sanity check for a programming
298: * error which is difficult to find
299: * when debugging.
300: */
301: if (tmp_count >
302: howmany(sizeof mfc, sizeof mfc[0]))
303: panic("CISTPL_LONGLINK_MFC mfc "
304: "count would blow stack");
305: mfc_count = tmp_count;
306: for (i = 0; i < mfc_count; i++) {
307: mfc[i].common =
308: (pccard_tuple_read_1(&tuple,
309: 1 + 5 * i) ==
310: PCCARD_MFC_MEM_COMMON) ?
311: 1 : 0;
312: mfc[i].addr =
313: pccard_tuple_read_4(&tuple,
314: 1 + 5 * i + 1);
315: DPRINTF((" %s:%lx",
316: mfc[i].common ? "common" :
317: "attr", mfc[i].addr));
318: }
319: DPRINTF(("\n"));
320: }
321: /*
322: * for LONGLINK_MFC, fall through to the
323: * function. This tuple has structural and
324: * semantic content.
325: */
326: default:
327: {
328: if ((*fct) (&tuple, arg)) {
329: ret = 1;
330: goto done;
331: }
332: }
333: break;
334: } /* switch */
335: #ifdef PCCARDCISDEBUG
336: /* print the tuple */
337: {
338: int i;
339:
340: DPRINTF((" %02x %02x", tuple.code,
341: tuple.length));
342:
343: for (i = 0; i < tuple.length; i++) {
344: DPRINTF((" %02x",
345: pccard_tuple_read_1(&tuple, i)));
346: if ((i % 16) == 13)
347: DPRINTF(("\n"));
348: }
349:
350: if ((i % 16) != 14)
351: DPRINTF(("\n"));
352: }
353: #endif
354: /* skip to the next tuple */
355: tuple.ptr += 2 + tuple.length;
356: }
357:
358: /*
359: * the chain is done. Clean up and move onto the next one,
360: * if any. The loop is here in the case that there is an MFC
361: * card with no longlink (which defaults to existing, == 0).
362: * In general, this means that if one pointer fails, it will
363: * try the next one, instead of just bailing.
364: */
365:
366: while (1) {
367: if (longlink_present) {
368: CARD_SET_RES_FLAGS(device_get_parent(dev), dev,
369: SYS_RES_MEMORY, rid, longlink_common ?
370: PCCARD_A_MEM_COM : PCCARD_A_MEM_ATTR);
371: DPRINTF(("cis mem map %x\n",
372: (unsigned int) tuple.memh));
373: tuple.mult = longlink_common ? 1 : 2;
374: tuple.ptr = longlink_addr;
375: longlink_present = 0;
376: longlink_common = 1;
377: longlink_addr = 0;
378: } else if (mfc_count && (mfc_index < mfc_count)) {
379: CARD_SET_RES_FLAGS(device_get_parent(dev), dev,
380: SYS_RES_MEMORY, rid, mfc[mfc_index].common
381: ? PCCARD_A_MEM_COM : PCCARD_A_MEM_ATTR);
382: DPRINTF(("cis mem map %x\n",
383: (unsigned int) tuple.memh));
384: /* set parse state, and point at the next one */
385: tuple.mult = mfc[mfc_index].common ? 1 : 2;
386: tuple.ptr = mfc[mfc_index].addr;
387: mfc_index++;
388: } else {
389: goto done;
390: }
391:
392: /* make sure that the link is valid */
393: tuple.code = pccard_cis_read_1(&tuple, tuple.ptr);
394: if (tuple.code != PCCARD_CISTPL_LINKTARGET) {
395: DPRINTF(("CISTPL_LINKTARGET expected, "
396: "code %02x observed\n", tuple.code));
397: continue;
398: }
399: tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1);
400: if (tuple.length < 3) {
401: DPRINTF(("CISTPL_LINKTARGET too short %d\n",
402: tuple.length));
403: continue;
404: }
405: if ((pccard_tuple_read_1(&tuple, 0) != 'C') ||
406: (pccard_tuple_read_1(&tuple, 1) != 'I') ||
407: (pccard_tuple_read_1(&tuple, 2) != 'S')) {
408: DPRINTF(("CISTPL_LINKTARGET magic "
409: "%02x%02x%02x incorrect\n",
410: pccard_tuple_read_1(&tuple, 0),
411: pccard_tuple_read_1(&tuple, 1),
412: pccard_tuple_read_1(&tuple, 2)));
413: continue;
414: }
415: tuple.ptr += 2 + tuple.length;
416: break;
417: }
418: }
419:
420: done:
421: bus_release_resource(dev, SYS_RES_MEMORY, rid, res);
422:
423: return (ret);
424: }
425:
426: /* XXX this is incredibly verbose. Not sure what trt is */
427:
428: void
429: pccard_print_cis(device_t dev)
430: {
431: struct pccard_softc *sc = PCCARD_SOFTC(dev);
432: struct pccard_card *card = &sc->card;
433: struct pccard_function *pf;
434: struct pccard_config_entry *cfe;
435: int i;
436:
437: device_printf(dev, "CIS version ");
438: if (card->cis1_major == 4) {
439: if (card->cis1_minor == 0)
440: printf("PCCARD 1.0\n");
441: else if (card->cis1_minor == 1)
442: printf("PCCARD 2.0 or 2.1\n");
443: } else if (card->cis1_major >= 5)
444: printf("PC Card Standard %d.%d\n", card->cis1_major, card->cis1_minor);
445: else
446: printf("unknown (major=%d, minor=%d)\n",
447: card->cis1_major, card->cis1_minor);
448:
449: device_printf(dev, "CIS info: ");
450: for (i = 0; i < 4; i++) {
451: if (card->cis1_info[i] == NULL)
452: break;
453: if (i)
454: printf(", ");
455: printf("%s", card->cis1_info[i]);
456: }
457: printf("\n");
458:
459: device_printf(dev, "Manufacturer code 0x%x, product 0x%x\n",
460: card->manufacturer, card->product);
461:
462: STAILQ_FOREACH(pf, &card->pf_head, pf_list) {
463: device_printf(dev, "function %d: ", pf->number);
464:
465: switch (pf->function) {
466: case PCCARD_FUNCTION_UNSPEC:
467: printf("unspecified");
468: break;
469: case PCCARD_FUNCTION_MULTIFUNCTION:
470: printf("multi-function");
471: break;
472: case PCCARD_FUNCTION_MEMORY:
473: printf("memory");
474: break;
475: case PCCARD_FUNCTION_SERIAL:
476: printf("serial port");
477: break;
478: case PCCARD_FUNCTION_PARALLEL:
479: printf("parallel port");
480: break;
481: case PCCARD_FUNCTION_DISK:
482: printf("fixed disk");
483: break;
484: case PCCARD_FUNCTION_VIDEO:
485: printf("video adapter");
486: break;
487: case PCCARD_FUNCTION_NETWORK:
488: printf("network adapter");
489: break;
490: case PCCARD_FUNCTION_AIMS:
491: printf("auto incrementing mass storage");
492: break;
493: case PCCARD_FUNCTION_SCSI:
494: printf("SCSI bridge");
495: break;
496: case PCCARD_FUNCTION_SECURITY:
497: printf("Security services");
498: break;
499: case PCCARD_FUNCTION_INSTRUMENT:
500: printf("Instrument");
501: break;
502: default:
503: printf("unknown (%d)", pf->function);
504: break;
505: }
506:
507: printf(", ccr addr %x mask %x\n", pf->ccr_base, pf->ccr_mask);
508:
509: STAILQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
510: device_printf(dev, "function %d, config table entry "
511: "%d: ", pf->number, cfe->number);
512:
513: switch (cfe->iftype) {
514: case PCCARD_IFTYPE_MEMORY:
515: printf("memory card");
516: break;
517: case PCCARD_IFTYPE_IO:
518: printf("I/O card");
519: break;
520: default:
521: printf("card type unknown");
522: break;
523: }
524:
525: printf("; irq mask %x", cfe->irqmask);
526:
527: if (cfe->num_iospace) {
528: printf("; iomask %lx, iospace", cfe->iomask);
529:
530: for (i = 0; i < cfe->num_iospace; i++) {
531: printf(" %lx", cfe->iospace[i].start);
532: if (cfe->iospace[i].length)
533: printf("-%lx",
534: cfe->iospace[i].start +
535: cfe->iospace[i].length - 1);
536: }
537: }
538: if (cfe->num_memspace) {
539: printf("; memspace");
540:
541: for (i = 0; i < cfe->num_memspace; i++) {
542: printf(" %lx",
543: cfe->memspace[i].cardaddr);
544: if (cfe->memspace[i].length)
545: printf("-%lx",
546: cfe->memspace[i].cardaddr +
547: cfe->memspace[i].length - 1);
548: if (cfe->memspace[i].hostaddr)
549: printf("@%lx",
550: cfe->memspace[i].hostaddr);
551: }
552: }
553: if (cfe->maxtwins)
554: printf("; maxtwins %d", cfe->maxtwins);
555:
556: printf(";");
557:
558: if (cfe->flags & PCCARD_CFE_MWAIT_REQUIRED)
559: printf(" mwait_required");
560: if (cfe->flags & PCCARD_CFE_RDYBSY_ACTIVE)
561: printf(" rdybsy_active");
562: if (cfe->flags & PCCARD_CFE_WP_ACTIVE)
563: printf(" wp_active");
564: if (cfe->flags & PCCARD_CFE_BVD_ACTIVE)
565: printf(" bvd_active");
566: if (cfe->flags & PCCARD_CFE_IO8)
567: printf(" io8");
568: if (cfe->flags & PCCARD_CFE_IO16)
569: printf(" io16");
570: if (cfe->flags & PCCARD_CFE_IRQSHARE)
571: printf(" irqshare");
572: if (cfe->flags & PCCARD_CFE_IRQPULSE)
573: printf(" irqpulse");
574: if (cfe->flags & PCCARD_CFE_IRQLEVEL)
575: printf(" irqlevel");
576: if (cfe->flags & PCCARD_CFE_POWERDOWN)
577: printf(" powerdown");
578: if (cfe->flags & PCCARD_CFE_READONLY)
579: printf(" readonly");
580: if (cfe->flags & PCCARD_CFE_AUDIO)
581: printf(" audio");
582:
583: printf("\n");
584: }
585: }
586:
587: if (card->error)
588: device_printf(dev, "%d errors found while parsing CIS\n",
589: card->error);
590: }
591:
592: int
593: pccard_parse_cis_tuple(struct pccard_tuple *tuple, void *arg)
594: {
595: /* most of these are educated guesses */
596: static struct pccard_config_entry init_cfe = {
597: -1, PCCARD_CFE_RDYBSY_ACTIVE | PCCARD_CFE_WP_ACTIVE |
598: PCCARD_CFE_BVD_ACTIVE, PCCARD_IFTYPE_MEMORY,
599: };
600:
601: struct cis_state *state = arg;
602:
603: switch (tuple->code) {
604: case PCCARD_CISTPL_END:
605: /* if we've seen a LONGLINK_MFC, and this is the first
606: * END after it, reset the function list.
607: *
608: * XXX This might also be the right place to start a
609: * new function, but that assumes that a function
610: * definition never crosses any longlink, and I'm not
611: * sure about that. This is probably safe for MFC
612: * cards, but what we have now isn't broken, so I'd
613: * rather not change it.
614: */
615: if (state->gotmfc == 1) {
616: struct pccard_function *pf, *pfnext;
617:
618: for (pf = STAILQ_FIRST(&state->card->pf_head);
619: pf != NULL; pf = pfnext) {
620: pfnext = STAILQ_NEXT(pf, pf_list);
621: free(pf, M_DEVBUF);
622: }
623:
624: STAILQ_INIT(&state->card->pf_head);
625:
626: state->count = 0;
627: state->gotmfc = 2;
628: state->pf = NULL;
629: }
630: break;
631: case PCCARD_CISTPL_LONGLINK_MFC:
632: /*
633: * this tuple's structure was dealt with in scan_cis. here,
634: * record the fact that the MFC tuple was seen, so that
635: * functions declared before the MFC link can be cleaned
636: * up.
637: */
638: state->gotmfc = 1;
639: break;
640: #ifdef PCCARDCISDEBUG
641: case PCCARD_CISTPL_DEVICE:
642: case PCCARD_CISTPL_DEVICE_A:
643: {
644: u_int reg, dtype, dspeed;
645:
646: reg = pccard_tuple_read_1(tuple, 0);
647: dtype = reg & PCCARD_DTYPE_MASK;
648: dspeed = reg & PCCARD_DSPEED_MASK;
649:
650: DPRINTF(("CISTPL_DEVICE%s type=",
651: (tuple->code == PCCARD_CISTPL_DEVICE) ? "" : "_A"));
652: switch (dtype) {
653: case PCCARD_DTYPE_NULL:
654: DPRINTF(("null"));
655: break;
656: case PCCARD_DTYPE_ROM:
657: DPRINTF(("rom"));
658: break;
659: case PCCARD_DTYPE_OTPROM:
660: DPRINTF(("otprom"));
661: break;
662: case PCCARD_DTYPE_EPROM:
663: DPRINTF(("eprom"));
664: break;
665: case PCCARD_DTYPE_EEPROM:
666: DPRINTF(("eeprom"));
667: break;
668: case PCCARD_DTYPE_FLASH:
669: DPRINTF(("flash"));
670: break;
671: case PCCARD_DTYPE_SRAM:
672: DPRINTF(("sram"));
673: break;
674: case PCCARD_DTYPE_DRAM:
675: DPRINTF(("dram"));
676: break;
677: case PCCARD_DTYPE_FUNCSPEC:
678: DPRINTF(("funcspec"));
679: break;
680: case PCCARD_DTYPE_EXTEND:
681: DPRINTF(("extend"));
682: break;
683: default:
684: DPRINTF(("reserved"));
685: break;
686: }
687: DPRINTF((" speed="));
688: switch (dspeed) {
689: case PCCARD_DSPEED_NULL:
690: DPRINTF(("null"));
691: break;
692: case PCCARD_DSPEED_250NS:
693: DPRINTF(("250ns"));
694: break;
695: case PCCARD_DSPEED_200NS:
696: DPRINTF(("200ns"));
697: break;
698: case PCCARD_DSPEED_150NS:
699: DPRINTF(("150ns"));
700: break;
701: case PCCARD_DSPEED_100NS:
702: DPRINTF(("100ns"));
703: break;
704: case PCCARD_DSPEED_EXT:
705: DPRINTF(("ext"));
706: break;
707: default:
708: DPRINTF(("reserved"));
709: break;
710: }
711: }
712: DPRINTF(("\n"));
713: break;
714: #endif
715: case PCCARD_CISTPL_VERS_1:
716: if (tuple->length < 6) {
717: DPRINTF(("CISTPL_VERS_1 too short %d\n",
718: tuple->length));
719: break;
720: } {
721: int start, i, ch, count;
722:
723: state->card->cis1_major = pccard_tuple_read_1(tuple, 0);
724: state->card->cis1_minor = pccard_tuple_read_1(tuple, 1);
725:
726: for (count = 0, start = 0, i = 0;
727: (count < 4) && ((i + 4) < 256); i++) {
728: ch = pccard_tuple_read_1(tuple, 2 + i);
729: if (ch == 0xff)
730: break;
731: state->card->cis1_info_buf[i] = ch;
732: if (ch == 0) {
733: state->card->cis1_info[count] =
734: state->card->cis1_info_buf + start;
735: start = i + 1;
736: count++;
737: }
738: }
739: DPRINTF(("CISTPL_VERS_1\n"));
740: }
741: break;
742: case PCCARD_CISTPL_MANFID:
743: if (tuple->length < 4) {
744: DPRINTF(("CISTPL_MANFID too short %d\n",
745: tuple->length));
746: break;
747: }
748: state->card->manufacturer = pccard_tuple_read_2(tuple, 0);
749: state->card->product = pccard_tuple_read_2(tuple, 2);
750: /*
751: * This is for xe driver. But not limited to that driver.
752: * In PC Card Standard,
753: * Manufacturer ID: 2byte.
754: * Product ID: typically 2bytes, but there's no limit on its
755: * size. prodext is a two byte field, so maybe we should
756: * also handle the '6' case. So far no cards have surfaced
757: * with a length of '6'.
758: */
759: if (tuple->length == 5 ) {
760: state->card->prodext = pccard_tuple_read_1(tuple, 4);
761: }
762: DPRINTF(("CISTPL_MANFID\n"));
763: break;
764: case PCCARD_CISTPL_FUNCID:
765: if (tuple->length < 1) {
766: DPRINTF(("CISTPL_FUNCID too short %d\n",
767: tuple->length));
768: break;
769: }
770: if ((state->pf == NULL) || (state->gotmfc == 2)) {
771: state->pf = malloc(sizeof(*state->pf), M_DEVBUF,
772: M_NOWAIT | M_ZERO);
773: state->pf->number = state->count++;
774: state->pf->last_config_index = -1;
775: STAILQ_INIT(&state->pf->cfe_head);
776:
777: STAILQ_INSERT_TAIL(&state->card->pf_head, state->pf,
778: pf_list);
779: }
780: state->pf->function = pccard_tuple_read_1(tuple, 0);
781:
782: DPRINTF(("CISTPL_FUNCID\n"));
783: break;
784: case PCCARD_CISTPL_FUNCE:
785: if (state->pf == NULL || state->pf->function <= 0) {
786: DPRINTF(("CISTPL_FUNCE is not followed by "
787: "valid CISTPL_FUNCID\n"));
788: break;
789: }
790: if (tuple->length >= 2) {
791: decode_funce(tuple, state->pf);
792: }
793: DPRINTF(("CISTPL_FUNCE\n"));
794: break;
795: case PCCARD_CISTPL_CONFIG:
796: if (tuple->length < 3) {
797: DPRINTF(("CISTPL_CONFIG too short %d\n",
798: tuple->length));
799: break;
800: } {
801: u_int reg, rasz, rmsz, rfsz;
802: int i;
803:
804: reg = pccard_tuple_read_1(tuple, 0);
805: rasz = 1 + ((reg & PCCARD_TPCC_RASZ_MASK) >>
806: PCCARD_TPCC_RASZ_SHIFT);
807: rmsz = 1 + ((reg & PCCARD_TPCC_RMSZ_MASK) >>
808: PCCARD_TPCC_RMSZ_SHIFT);
809: rfsz = ((reg & PCCARD_TPCC_RFSZ_MASK) >>
810: PCCARD_TPCC_RFSZ_SHIFT);
811:
812: if (tuple->length < (rasz + rmsz + rfsz)) {
813: DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too "
814: "short %d\n", rasz, rmsz, rfsz,
815: tuple->length));
816: break;
817: }
818: if (state->pf == NULL) {
819: state->pf = malloc(sizeof(*state->pf),
820: M_DEVBUF, M_NOWAIT | M_ZERO);
821: state->pf->number = state->count++;
822: state->pf->last_config_index = -1;
823: STAILQ_INIT(&state->pf->cfe_head);
824:
825: STAILQ_INSERT_TAIL(&state->card->pf_head,
826: state->pf, pf_list);
827:
828: state->pf->function = PCCARD_FUNCTION_UNSPEC;
829: }
830: state->pf->last_config_index =
831: pccard_tuple_read_1(tuple, 1);
832:
833: state->pf->ccr_base = 0;
834: for (i = 0; i < rasz; i++)
835: state->pf->ccr_base |=
836: ((pccard_tuple_read_1(tuple, 2 + i)) <<
837: (i * 8));
838:
839: state->pf->ccr_mask = 0;
840: for (i = 0; i < rmsz; i++)
841: state->pf->ccr_mask |=
842: ((pccard_tuple_read_1(tuple,
843: 2 + rasz + i)) << (i * 8));
844:
845: /* skip the reserved area and subtuples */
846:
847: /* reset the default cfe for each cfe list */
848: state->temp_cfe = init_cfe;
849: state->default_cfe = &state->temp_cfe;
850: }
851: DPRINTF(("CISTPL_CONFIG\n"));
852: break;
853: case PCCARD_CISTPL_CFTABLE_ENTRY:
854: {
855: int idx, i, j;
856: u_int reg, reg2;
857: u_int intface, def, num;
858: u_int power, timing, iospace, irq, memspace, misc;
859: struct pccard_config_entry *cfe;
860:
861: idx = 0;
862:
863: reg = pccard_tuple_read_1(tuple, idx);
864: idx++;
865: intface = reg & PCCARD_TPCE_INDX_INTFACE;
866: def = reg & PCCARD_TPCE_INDX_DEFAULT;
867: num = reg & PCCARD_TPCE_INDX_NUM_MASK;
868:
869: /*
870: * this is a little messy. Some cards have only a
871: * cfentry with the default bit set. So, as we go
872: * through the list, we add new indexes to the queue,
873: * and keep a pointer to the last one with the
874: * default bit set. if we see a record with the same
875: * index, as the default, we stash the default and
876: * replace the queue entry. otherwise, we just add
877: * new entries to the queue, pointing the default ptr
878: * at them if the default bit is set. if we get to
879: * the end with the default pointer pointing at a
880: * record which hasn't had a matching index, that's
881: * ok; it just becomes a cfentry like any other.
882: */
883:
884: /*
885: * if the index in the cis differs from the default
886: * cis, create new entry in the queue and start it
887: * with the current default
888: */
889: if (num != state->default_cfe->number) {
890: cfe = (struct pccard_config_entry *)
891: malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
892:
893: *cfe = *state->default_cfe;
894:
895: STAILQ_INSERT_TAIL(&state->pf->cfe_head,
896: cfe, cfe_list);
897:
898: cfe->number = num;
899:
900: /*
901: * if the default bit is set in the cis, then
902: * point the new default at whatever is being
903: * filled in
904: */
905: if (def)
906: state->default_cfe = cfe;
907: } else {
908: /*
909: * the cis index matches the default index,
910: * fill in the default cfentry. It is
911: * assumed that the cfdefault index is in the
912: * queue. For it to be otherwise, the cis
913: * index would have to be -1 (initial
914: * condition) which is not possible, or there
915: * would have to be a preceding cis entry
916: * which had the same cis index and had the
917: * default bit unset. Neither condition
918: * should happen. If it does, this cfentry
919: * is lost (written into temp space), which
920: * is an acceptable failure mode.
921: */
922:
923: cfe = state->default_cfe;
924:
925: /*
926: * if the cis entry does not have the default
927: * bit set, copy the default out of the way
928: * first.
929: */
930: if (!def) {
931: state->temp_cfe = *state->default_cfe;
932: state->default_cfe = &state->temp_cfe;
933: }
934: }
935:
936: if (intface) {
937: reg = pccard_tuple_read_1(tuple, idx);
938: idx++;
939: cfe->flags &= ~(PCCARD_CFE_MWAIT_REQUIRED
940: | PCCARD_CFE_RDYBSY_ACTIVE
941: | PCCARD_CFE_WP_ACTIVE
942: | PCCARD_CFE_BVD_ACTIVE);
943: if (reg & PCCARD_TPCE_IF_MWAIT)
944: cfe->flags |= PCCARD_CFE_MWAIT_REQUIRED;
945: if (reg & PCCARD_TPCE_IF_RDYBSY)
946: cfe->flags |= PCCARD_CFE_RDYBSY_ACTIVE;
947: if (reg & PCCARD_TPCE_IF_WP)
948: cfe->flags |= PCCARD_CFE_WP_ACTIVE;
949: if (reg & PCCARD_TPCE_IF_BVD)
950: cfe->flags |= PCCARD_CFE_BVD_ACTIVE;
951: cfe->iftype = reg & PCCARD_TPCE_IF_IFTYPE;
952: }
953: reg = pccard_tuple_read_1(tuple, idx);
954: idx++;
955:
956: power = reg & PCCARD_TPCE_FS_POWER_MASK;
957: timing = reg & PCCARD_TPCE_FS_TIMING;
958: iospace = reg & PCCARD_TPCE_FS_IOSPACE;
959: irq = reg & PCCARD_TPCE_FS_IRQ;
960: memspace = reg & PCCARD_TPCE_FS_MEMSPACE_MASK;
961: misc = reg & PCCARD_TPCE_FS_MISC;
962:
963: if (power) {
964: /* skip over power, don't save */
965: /* for each parameter selection byte */
966: for (i = 0; i < power; i++) {
967: reg = pccard_tuple_read_1(tuple, idx);
968: idx++;
969: /* for each bit */
970: for (j = 0; j < 7; j++) {
971: /* if the bit is set */
972: if ((reg >> j) & 0x01) {
973: /* skip over bytes */
974: do {
975: reg2 = pccard_tuple_read_1(tuple, idx);
976: idx++;
977: /*
978: * until
979: * non-extensi
980: * on byte
981: */
982: } while (reg2 & 0x80);
983: }
984: }
985: }
986: }
987: if (timing) {
988: /* skip over timing, don't save */
989: reg = pccard_tuple_read_1(tuple, idx);
990: idx++;
991:
992: if ((reg & PCCARD_TPCE_TD_RESERVED_MASK) !=
993: PCCARD_TPCE_TD_RESERVED_MASK)
994: idx++;
995: if ((reg & PCCARD_TPCE_TD_RDYBSY_MASK) !=
996: PCCARD_TPCE_TD_RDYBSY_MASK)
997: idx++;
998: if ((reg & PCCARD_TPCE_TD_WAIT_MASK) !=
999: PCCARD_TPCE_TD_WAIT_MASK)
1000: idx++;
1001: }
1002: if (iospace) {
1003: if (tuple->length <= idx) {
1004: DPRINTF(("ran out of space before TCPE_IO\n"));
1005: goto abort_cfe;
1006: }
1007:
1008: reg = pccard_tuple_read_1(tuple, idx);
1009: idx++;
1010: cfe->flags &=
1011: ~(PCCARD_CFE_IO8 | PCCARD_CFE_IO16);
1012: if (reg & PCCARD_TPCE_IO_BUSWIDTH_8BIT)
1013: cfe->flags |= PCCARD_CFE_IO8;
1014: if (reg & PCCARD_TPCE_IO_BUSWIDTH_16BIT)
1015: cfe->flags |= PCCARD_CFE_IO16;
1016: cfe->iomask =
1017: reg & PCCARD_TPCE_IO_IOADDRLINES_MASK;
1018:
1019: if (reg & PCCARD_TPCE_IO_HASRANGE) {
1020: reg = pccard_tuple_read_1(tuple, idx);
1021: idx++;
1022:
1023: cfe->num_iospace = 1 + (reg &
1024: PCCARD_TPCE_IO_RANGE_COUNT);
1025:
1026: if (cfe->num_iospace >
1027: (sizeof(cfe->iospace) /
1028: sizeof(cfe->iospace[0]))) {
1029: DPRINTF(("too many io "
1030: "spaces %d",
1031: cfe->num_iospace));
1032: state->card->error++;
1033: break;
1034: }
1035: for (i = 0; i < cfe->num_iospace; i++) {
1036: switch (reg & PCCARD_TPCE_IO_RANGE_ADDRSIZE_MASK) {
1037: case PCCARD_TPCE_IO_RANGE_ADDRSIZE_ONE:
1038: cfe->iospace[i].start =
1039: pccard_tuple_read_1(tuple, idx);
1040: idx++;
1041: break;
1042: case PCCARD_TPCE_IO_RANGE_ADDRSIZE_TWO:
1043: cfe->iospace[i].start =
1044: pccard_tuple_read_2(tuple, idx);
1045: idx += 2;
1046: break;
1047: case PCCARD_TPCE_IO_RANGE_ADDRSIZE_FOUR:
1048: cfe->iospace[i].start =
1049: pccard_tuple_read_4(tuple, idx);
1050: idx += 4;
1051: break;
1052: }
1053: switch (reg &
1054: PCCARD_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
1055: case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_ONE:
1056: cfe->iospace[i].length =
1057: pccard_tuple_read_1(tuple, idx);
1058: idx++;
1059: break;
1060: case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_TWO:
1061: cfe->iospace[i].length =
1062: pccard_tuple_read_2(tuple, idx);
1063: idx += 2;
1064: break;
1065: case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
1066: cfe->iospace[i].length =
1067: pccard_tuple_read_4(tuple, idx);
1068: idx += 4;
1069: break;
1070: }
1071: cfe->iospace[i].length++;
1072: }
1073: } else {
1074: cfe->num_iospace = 1;
1075: cfe->iospace[0].start = 0;
1076: cfe->iospace[0].length =
1077: (1 << cfe->iomask);
1078: }
1079: }
1080: if (irq) {
1081: if (tuple->length <= idx) {
1082: DPRINTF(("ran out of space before TCPE_IR\n"));
1083: goto abort_cfe;
1084: }
1085:
1086: reg = pccard_tuple_read_1(tuple, idx);
1087: idx++;
1088: cfe->flags &= ~(PCCARD_CFE_IRQSHARE
1089: | PCCARD_CFE_IRQPULSE
1090: | PCCARD_CFE_IRQLEVEL);
1091: if (reg & PCCARD_TPCE_IR_SHARE)
1092: cfe->flags |= PCCARD_CFE_IRQSHARE;
1093: if (reg & PCCARD_TPCE_IR_PULSE)
1094: cfe->flags |= PCCARD_CFE_IRQPULSE;
1095: if (reg & PCCARD_TPCE_IR_LEVEL)
1096: cfe->flags |= PCCARD_CFE_IRQLEVEL;
1097:
1098: if (reg & PCCARD_TPCE_IR_HASMASK) {
1099: /*
1100: * it's legal to ignore the
1101: * special-interrupt bits, so I will
1102: */
1103:
1104: cfe->irqmask =
1105: pccard_tuple_read_2(tuple, idx);
1106: idx += 2;
1107: } else {
1108: cfe->irqmask =
1109: (1 << (reg & PCCARD_TPCE_IR_IRQ));
1110: }
1111: }
1112: if (memspace) {
1113: if (tuple->length <= idx) {
1114: DPRINTF(("ran out of space before TCPE_MS\n"));
1115: goto abort_cfe;
1116: }
1117:
1118: if (memspace == PCCARD_TPCE_FS_MEMSPACE_NONE) {
1119: cfe->num_memspace = 0;
1120: } else if (memspace == PCCARD_TPCE_FS_MEMSPACE_LENGTH) {
1121: cfe->num_memspace = 1;
1122: cfe->memspace[0].length = 256 *
1123: pccard_tuple_read_2(tuple, idx);
1124: idx += 2;
1125: cfe->memspace[0].cardaddr = 0;
1126: cfe->memspace[0].hostaddr = 0;
1127: } else if (memspace ==
1128: PCCARD_TPCE_FS_MEMSPACE_LENGTHADDR) {
1129: cfe->num_memspace = 1;
1130: cfe->memspace[0].length = 256 *
1131: pccard_tuple_read_2(tuple, idx);
1132: idx += 2;
1133: cfe->memspace[0].cardaddr = 256 *
1134: pccard_tuple_read_2(tuple, idx);
1135: idx += 2;
1136: cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr;
1137: } else {
1138: int lengthsize;
1139: int cardaddrsize;
1140: int hostaddrsize;
1141:
1142: reg = pccard_tuple_read_1(tuple, idx);
1143: idx++;
1144:
1145: cfe->num_memspace = (reg &
1146: PCCARD_TPCE_MS_COUNT) + 1;
1147:
1148: if (cfe->num_memspace >
1149: (sizeof(cfe->memspace) /
1150: sizeof(cfe->memspace[0]))) {
1151: DPRINTF(("too many mem "
1152: "spaces %d",
1153: cfe->num_memspace));
1154: state->card->error++;
1155: break;
1156: }
1157: lengthsize =
1158: ((reg & PCCARD_TPCE_MS_LENGTH_SIZE_MASK) >>
1159: PCCARD_TPCE_MS_LENGTH_SIZE_SHIFT);
1160: cardaddrsize =
1161: ((reg & PCCARD_TPCE_MS_CARDADDR_SIZE_MASK) >>
1162: PCCARD_TPCE_MS_CARDADDR_SIZE_SHIFT);
1163: hostaddrsize =
1164: (reg & PCCARD_TPCE_MS_HOSTADDR) ? cardaddrsize : 0;
1165:
1166: if (lengthsize == 0) {
1167: DPRINTF(("cfe memspace "
1168: "lengthsize == 0"));
1169: state->card->error++;
1170: }
1171: for (i = 0; i < cfe->num_memspace; i++) {
1172: if (lengthsize) {
1173: cfe->memspace[i].length =
1174: 256 * pccard_tuple_read_n(tuple, lengthsize,
1175: idx);
1176: idx += lengthsize;
1177: } else {
1178: cfe->memspace[i].length = 0;
1179: }
1180: if (cfe->memspace[i].length == 0) {
1181: DPRINTF(("cfe->memspace[%d].length == 0",
1182: i));
1183: state->card->error++;
1184: }
1185: if (cardaddrsize) {
1186: cfe->memspace[i].cardaddr =
1187: 256 * pccard_tuple_read_n(tuple, cardaddrsize,
1188: idx);
1189: idx += cardaddrsize;
1190: } else {
1191: cfe->memspace[i].cardaddr = 0;
1192: }
1193: if (hostaddrsize) {
1194: cfe->memspace[i].hostaddr =
1195: 256 * pccard_tuple_read_n(tuple, hostaddrsize,
1196: idx);
1197: idx += hostaddrsize;
1198: } else {
1199: cfe->memspace[i].hostaddr = 0;
1200: }
1201: }
1202: }
1203: }
1204: if (misc) {
1205: if (tuple->length <= idx) {
1206: DPRINTF(("ran out of space before TCPE_MI\n"));
1207: goto abort_cfe;
1208: }
1209:
1210: reg = pccard_tuple_read_1(tuple, idx);
1211: idx++;
1212: cfe->flags &= ~(PCCARD_CFE_POWERDOWN
1213: | PCCARD_CFE_READONLY
1214: | PCCARD_CFE_AUDIO);
1215: if (reg & PCCARD_TPCE_MI_PWRDOWN)
1216: cfe->flags |= PCCARD_CFE_POWERDOWN;
1217: if (reg & PCCARD_TPCE_MI_READONLY)
1218: cfe->flags |= PCCARD_CFE_READONLY;
1219: if (reg & PCCARD_TPCE_MI_AUDIO)
1220: cfe->flags |= PCCARD_CFE_AUDIO;
1221: cfe->maxtwins = reg & PCCARD_TPCE_MI_MAXTWINS;
1222:
1223: while (reg & PCCARD_TPCE_MI_EXT) {
1224: reg = pccard_tuple_read_1(tuple, idx);
1225: idx++;
1226: }
1227: }
1228: /* skip all the subtuples */
1229: }
1230:
1231: abort_cfe:
1232: DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
1233: break;
1234: default:
1235: DPRINTF(("unhandled CISTPL %x\n", tuple->code));
1236: break;
1237: }
1238:
1239: return (0);
1240: }
1241:
1242: static int
1243: decode_funce(struct pccard_tuple *tuple, struct pccard_function *pf)
1244: {
1245: int type = pccard_tuple_read_1(tuple, 0);
1246:
1247: switch (pf->function) {
1248: case PCCARD_FUNCTION_DISK:
1249: if (type == PCCARD_TPLFE_TYPE_DISK_DEVICE_INTERFACE) {
1250: pf->pf_funce_disk_interface
1251: = pccard_tuple_read_1(tuple, 1);
1252: }
1253: break;
1254: case PCCARD_FUNCTION_NETWORK:
1255: if (type == PCCARD_TPLFE_TYPE_LAN_NID) {
1256: int i;
1257: int len = pccard_tuple_read_1(tuple, 1);
1258: if (tuple->length < 2 + len || len > 8) {
1259: /* tuple length not enough or nid too long */
1260: break;
1261: }
1262: for (i = 0; i < len; i++) {
1263: pf->pf_funce_lan_nid[i]
1264: = pccard_tuple_read_1(tuple, i + 2);
1265: }
1266: pf->pf_funce_lan_nidlen = len;
1267: }
1268: break;
1269: default:
1270: break;
1271: }
1272: return 0;
1273: }