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.2 2004/03/15 17:15:18 dillon 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_INTWAIT | 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_INTWAIT | 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 = malloc(sizeof(*cfe), M_DEVBUF, M_INTWAIT);
891:
892: *cfe = *state->default_cfe;
893:
894: STAILQ_INSERT_TAIL(&state->pf->cfe_head,
895: cfe, cfe_list);
896:
897: cfe->number = num;
898:
899: /*
900: * if the default bit is set in the cis, then
901: * point the new default at whatever is being
902: * filled in
903: */
904: if (def)
905: state->default_cfe = cfe;
906: } else {
907: /*
908: * the cis index matches the default index,
909: * fill in the default cfentry. It is
910: * assumed that the cfdefault index is in the
911: * queue. For it to be otherwise, the cis
912: * index would have to be -1 (initial
913: * condition) which is not possible, or there
914: * would have to be a preceding cis entry
915: * which had the same cis index and had the
916: * default bit unset. Neither condition
917: * should happen. If it does, this cfentry
918: * is lost (written into temp space), which
919: * is an acceptable failure mode.
920: */
921:
922: cfe = state->default_cfe;
923:
924: /*
925: * if the cis entry does not have the default
926: * bit set, copy the default out of the way
927: * first.
928: */
929: if (!def) {
930: state->temp_cfe = *state->default_cfe;
931: state->default_cfe = &state->temp_cfe;
932: }
933: }
934:
935: if (intface) {
936: reg = pccard_tuple_read_1(tuple, idx);
937: idx++;
938: cfe->flags &= ~(PCCARD_CFE_MWAIT_REQUIRED
939: | PCCARD_CFE_RDYBSY_ACTIVE
940: | PCCARD_CFE_WP_ACTIVE
941: | PCCARD_CFE_BVD_ACTIVE);
942: if (reg & PCCARD_TPCE_IF_MWAIT)
943: cfe->flags |= PCCARD_CFE_MWAIT_REQUIRED;
944: if (reg & PCCARD_TPCE_IF_RDYBSY)
945: cfe->flags |= PCCARD_CFE_RDYBSY_ACTIVE;
946: if (reg & PCCARD_TPCE_IF_WP)
947: cfe->flags |= PCCARD_CFE_WP_ACTIVE;
948: if (reg & PCCARD_TPCE_IF_BVD)
949: cfe->flags |= PCCARD_CFE_BVD_ACTIVE;
950: cfe->iftype = reg & PCCARD_TPCE_IF_IFTYPE;
951: }
952: reg = pccard_tuple_read_1(tuple, idx);
953: idx++;
954:
955: power = reg & PCCARD_TPCE_FS_POWER_MASK;
956: timing = reg & PCCARD_TPCE_FS_TIMING;
957: iospace = reg & PCCARD_TPCE_FS_IOSPACE;
958: irq = reg & PCCARD_TPCE_FS_IRQ;
959: memspace = reg & PCCARD_TPCE_FS_MEMSPACE_MASK;
960: misc = reg & PCCARD_TPCE_FS_MISC;
961:
962: if (power) {
963: /* skip over power, don't save */
964: /* for each parameter selection byte */
965: for (i = 0; i < power; i++) {
966: reg = pccard_tuple_read_1(tuple, idx);
967: idx++;
968: /* for each bit */
969: for (j = 0; j < 7; j++) {
970: /* if the bit is set */
971: if ((reg >> j) & 0x01) {
972: /* skip over bytes */
973: do {
974: reg2 = pccard_tuple_read_1(tuple, idx);
975: idx++;
976: /*
977: * until
978: * non-extensi
979: * on byte
980: */
981: } while (reg2 & 0x80);
982: }
983: }
984: }
985: }
986: if (timing) {
987: /* skip over timing, don't save */
988: reg = pccard_tuple_read_1(tuple, idx);
989: idx++;
990:
991: if ((reg & PCCARD_TPCE_TD_RESERVED_MASK) !=
992: PCCARD_TPCE_TD_RESERVED_MASK)
993: idx++;
994: if ((reg & PCCARD_TPCE_TD_RDYBSY_MASK) !=
995: PCCARD_TPCE_TD_RDYBSY_MASK)
996: idx++;
997: if ((reg & PCCARD_TPCE_TD_WAIT_MASK) !=
998: PCCARD_TPCE_TD_WAIT_MASK)
999: idx++;
1000: }
1001: if (iospace) {
1002: if (tuple->length <= idx) {
1003: DPRINTF(("ran out of space before TCPE_IO\n"));
1004: goto abort_cfe;
1005: }
1006:
1007: reg = pccard_tuple_read_1(tuple, idx);
1008: idx++;
1009: cfe->flags &=
1010: ~(PCCARD_CFE_IO8 | PCCARD_CFE_IO16);
1011: if (reg & PCCARD_TPCE_IO_BUSWIDTH_8BIT)
1012: cfe->flags |= PCCARD_CFE_IO8;
1013: if (reg & PCCARD_TPCE_IO_BUSWIDTH_16BIT)
1014: cfe->flags |= PCCARD_CFE_IO16;
1015: cfe->iomask =
1016: reg & PCCARD_TPCE_IO_IOADDRLINES_MASK;
1017:
1018: if (reg & PCCARD_TPCE_IO_HASRANGE) {
1019: reg = pccard_tuple_read_1(tuple, idx);
1020: idx++;
1021:
1022: cfe->num_iospace = 1 + (reg &
1023: PCCARD_TPCE_IO_RANGE_COUNT);
1024:
1025: if (cfe->num_iospace >
1026: (sizeof(cfe->iospace) /
1027: sizeof(cfe->iospace[0]))) {
1028: DPRINTF(("too many io "
1029: "spaces %d",
1030: cfe->num_iospace));
1031: state->card->error++;
1032: break;
1033: }
1034: for (i = 0; i < cfe->num_iospace; i++) {
1035: switch (reg & PCCARD_TPCE_IO_RANGE_ADDRSIZE_MASK) {
1036: case PCCARD_TPCE_IO_RANGE_ADDRSIZE_ONE:
1037: cfe->iospace[i].start =
1038: pccard_tuple_read_1(tuple, idx);
1039: idx++;
1040: break;
1041: case PCCARD_TPCE_IO_RANGE_ADDRSIZE_TWO:
1042: cfe->iospace[i].start =
1043: pccard_tuple_read_2(tuple, idx);
1044: idx += 2;
1045: break;
1046: case PCCARD_TPCE_IO_RANGE_ADDRSIZE_FOUR:
1047: cfe->iospace[i].start =
1048: pccard_tuple_read_4(tuple, idx);
1049: idx += 4;
1050: break;
1051: }
1052: switch (reg &
1053: PCCARD_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
1054: case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_ONE:
1055: cfe->iospace[i].length =
1056: pccard_tuple_read_1(tuple, idx);
1057: idx++;
1058: break;
1059: case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_TWO:
1060: cfe->iospace[i].length =
1061: pccard_tuple_read_2(tuple, idx);
1062: idx += 2;
1063: break;
1064: case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
1065: cfe->iospace[i].length =
1066: pccard_tuple_read_4(tuple, idx);
1067: idx += 4;
1068: break;
1069: }
1070: cfe->iospace[i].length++;
1071: }
1072: } else {
1073: cfe->num_iospace = 1;
1074: cfe->iospace[0].start = 0;
1075: cfe->iospace[0].length =
1076: (1 << cfe->iomask);
1077: }
1078: }
1079: if (irq) {
1080: if (tuple->length <= idx) {
1081: DPRINTF(("ran out of space before TCPE_IR\n"));
1082: goto abort_cfe;
1083: }
1084:
1085: reg = pccard_tuple_read_1(tuple, idx);
1086: idx++;
1087: cfe->flags &= ~(PCCARD_CFE_IRQSHARE
1088: | PCCARD_CFE_IRQPULSE
1089: | PCCARD_CFE_IRQLEVEL);
1090: if (reg & PCCARD_TPCE_IR_SHARE)
1091: cfe->flags |= PCCARD_CFE_IRQSHARE;
1092: if (reg & PCCARD_TPCE_IR_PULSE)
1093: cfe->flags |= PCCARD_CFE_IRQPULSE;
1094: if (reg & PCCARD_TPCE_IR_LEVEL)
1095: cfe->flags |= PCCARD_CFE_IRQLEVEL;
1096:
1097: if (reg & PCCARD_TPCE_IR_HASMASK) {
1098: /*
1099: * it's legal to ignore the
1100: * special-interrupt bits, so I will
1101: */
1102:
1103: cfe->irqmask =
1104: pccard_tuple_read_2(tuple, idx);
1105: idx += 2;
1106: } else {
1107: cfe->irqmask =
1108: (1 << (reg & PCCARD_TPCE_IR_IRQ));
1109: }
1110: }
1111: if (memspace) {
1112: if (tuple->length <= idx) {
1113: DPRINTF(("ran out of space before TCPE_MS\n"));
1114: goto abort_cfe;
1115: }
1116:
1117: if (memspace == PCCARD_TPCE_FS_MEMSPACE_NONE) {
1118: cfe->num_memspace = 0;
1119: } else if (memspace == PCCARD_TPCE_FS_MEMSPACE_LENGTH) {
1120: cfe->num_memspace = 1;
1121: cfe->memspace[0].length = 256 *
1122: pccard_tuple_read_2(tuple, idx);
1123: idx += 2;
1124: cfe->memspace[0].cardaddr = 0;
1125: cfe->memspace[0].hostaddr = 0;
1126: } else if (memspace ==
1127: PCCARD_TPCE_FS_MEMSPACE_LENGTHADDR) {
1128: cfe->num_memspace = 1;
1129: cfe->memspace[0].length = 256 *
1130: pccard_tuple_read_2(tuple, idx);
1131: idx += 2;
1132: cfe->memspace[0].cardaddr = 256 *
1133: pccard_tuple_read_2(tuple, idx);
1134: idx += 2;
1135: cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr;
1136: } else {
1137: int lengthsize;
1138: int cardaddrsize;
1139: int hostaddrsize;
1140:
1141: reg = pccard_tuple_read_1(tuple, idx);
1142: idx++;
1143:
1144: cfe->num_memspace = (reg &
1145: PCCARD_TPCE_MS_COUNT) + 1;
1146:
1147: if (cfe->num_memspace >
1148: (sizeof(cfe->memspace) /
1149: sizeof(cfe->memspace[0]))) {
1150: DPRINTF(("too many mem "
1151: "spaces %d",
1152: cfe->num_memspace));
1153: state->card->error++;
1154: break;
1155: }
1156: lengthsize =
1157: ((reg & PCCARD_TPCE_MS_LENGTH_SIZE_MASK) >>
1158: PCCARD_TPCE_MS_LENGTH_SIZE_SHIFT);
1159: cardaddrsize =
1160: ((reg & PCCARD_TPCE_MS_CARDADDR_SIZE_MASK) >>
1161: PCCARD_TPCE_MS_CARDADDR_SIZE_SHIFT);
1162: hostaddrsize =
1163: (reg & PCCARD_TPCE_MS_HOSTADDR) ? cardaddrsize : 0;
1164:
1165: if (lengthsize == 0) {
1166: DPRINTF(("cfe memspace "
1167: "lengthsize == 0"));
1168: state->card->error++;
1169: }
1170: for (i = 0; i < cfe->num_memspace; i++) {
1171: if (lengthsize) {
1172: cfe->memspace[i].length =
1173: 256 * pccard_tuple_read_n(tuple, lengthsize,
1174: idx);
1175: idx += lengthsize;
1176: } else {
1177: cfe->memspace[i].length = 0;
1178: }
1179: if (cfe->memspace[i].length == 0) {
1180: DPRINTF(("cfe->memspace[%d].length == 0",
1181: i));
1182: state->card->error++;
1183: }
1184: if (cardaddrsize) {
1185: cfe->memspace[i].cardaddr =
1186: 256 * pccard_tuple_read_n(tuple, cardaddrsize,
1187: idx);
1188: idx += cardaddrsize;
1189: } else {
1190: cfe->memspace[i].cardaddr = 0;
1191: }
1192: if (hostaddrsize) {
1193: cfe->memspace[i].hostaddr =
1194: 256 * pccard_tuple_read_n(tuple, hostaddrsize,
1195: idx);
1196: idx += hostaddrsize;
1197: } else {
1198: cfe->memspace[i].hostaddr = 0;
1199: }
1200: }
1201: }
1202: }
1203: if (misc) {
1204: if (tuple->length <= idx) {
1205: DPRINTF(("ran out of space before TCPE_MI\n"));
1206: goto abort_cfe;
1207: }
1208:
1209: reg = pccard_tuple_read_1(tuple, idx);
1210: idx++;
1211: cfe->flags &= ~(PCCARD_CFE_POWERDOWN
1212: | PCCARD_CFE_READONLY
1213: | PCCARD_CFE_AUDIO);
1214: if (reg & PCCARD_TPCE_MI_PWRDOWN)
1215: cfe->flags |= PCCARD_CFE_POWERDOWN;
1216: if (reg & PCCARD_TPCE_MI_READONLY)
1217: cfe->flags |= PCCARD_CFE_READONLY;
1218: if (reg & PCCARD_TPCE_MI_AUDIO)
1219: cfe->flags |= PCCARD_CFE_AUDIO;
1220: cfe->maxtwins = reg & PCCARD_TPCE_MI_MAXTWINS;
1221:
1222: while (reg & PCCARD_TPCE_MI_EXT) {
1223: reg = pccard_tuple_read_1(tuple, idx);
1224: idx++;
1225: }
1226: }
1227: /* skip all the subtuples */
1228: }
1229:
1230: abort_cfe:
1231: DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
1232: break;
1233: default:
1234: DPRINTF(("unhandled CISTPL %x\n", tuple->code));
1235: break;
1236: }
1237:
1238: return (0);
1239: }
1240:
1241: static int
1242: decode_funce(struct pccard_tuple *tuple, struct pccard_function *pf)
1243: {
1244: int type = pccard_tuple_read_1(tuple, 0);
1245:
1246: switch (pf->function) {
1247: case PCCARD_FUNCTION_DISK:
1248: if (type == PCCARD_TPLFE_TYPE_DISK_DEVICE_INTERFACE) {
1249: pf->pf_funce_disk_interface
1250: = pccard_tuple_read_1(tuple, 1);
1251: }
1252: break;
1253: case PCCARD_FUNCTION_NETWORK:
1254: if (type == PCCARD_TPLFE_TYPE_LAN_NID) {
1255: int i;
1256: int len = pccard_tuple_read_1(tuple, 1);
1257: if (tuple->length < 2 + len || len > 8) {
1258: /* tuple length not enough or nid too long */
1259: break;
1260: }
1261: for (i = 0; i < len; i++) {
1262: pf->pf_funce_lan_nid[i]
1263: = pccard_tuple_read_1(tuple, i + 2);
1264: }
1265: pf->pf_funce_lan_nidlen = len;
1266: }
1267: break;
1268: default:
1269: break;
1270: }
1271: return 0;
1272: }