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