Deleted Added
sdiff udiff text old ( 86272 ) new ( 87352 )
full compact
1/* $NetBSD: pcmcia_cis.c,v 1.10 1998/12/29 09:03:15 marc Exp $ */
2/* $FreeBSD: head/sys/dev/pccard/pccard_cis.c 86272 2001-11-11 20:15:47Z 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
51#define PCCARDCISDEBUG
52#ifdef PCCARDCISDEBUG
53int pccardcis_debug = 1;
54#define DPRINTF(arg) if (pccardcis_debug) printf arg
55#define DEVPRINTF(arg) if (pccardcis_debug) device_printf arg
56#else
57#define DPRINTF(arg)
58#define DEVPRINTF(arg)
59#endif
60
61#define PCCARD_CIS_SIZE 1024
62
63struct cis_state {
64 int count;
65 int gotmfc;
66 struct pccard_config_entry temp_cfe;
67 struct pccard_config_entry *default_cfe;
68 struct pccard_card *card;
69 struct pccard_function *pf;
70};
71
72int pccard_parse_cis_tuple(struct pccard_tuple *, void *);
73static int decode_funce(struct pccard_tuple *, struct pccard_function *);
74
75void
76pccard_read_cis(struct pccard_softc *sc)
77{
78 struct cis_state state;
79
80 state.count = 0;
81 state.gotmfc = 0;
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;
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 %x\n", (unsigned int) tuple.memh));
139
140 tuple.mult = 2;
141
142 longlink_present = 1;
143 longlink_common = 1;
144 longlink_addr = 0;
145
146 mfc_count = 0;
147 mfc_index = 0;
148
149 DEVPRINTF((dev, "CIS tuple chain:\n"));
150
151 while (1) {
152 while (1) {
153 /* get the tuple code */
154
155 tuple.code = pccard_cis_read_1(&tuple, tuple.ptr);
156
157 /* two special-case tuples */
158
159 if (tuple.code == PCCARD_CISTPL_NULL) {
160 DPRINTF(("CISTPL_NONE\n 00\n"));
161 tuple.ptr++;
162 continue;
163 } else if (tuple.code == PCCARD_CISTPL_END) {
164 DPRINTF(("CISTPL_END\n ff\n"));
165 /* Call the function for the END tuple, since
166 the CIS semantics depend on it */
167 if ((*fct) (&tuple, arg)) {
168 ret = 1;
169 goto done;
170 }
171 ret = 1; goto done; /* XXX IMP XXX */
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 *((u_int16_t *) & offset) =
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) < 0) ||
228 ((addr + length) >=
229 PCCARD_CIS_SIZE)) {
230 DPRINTF((" skipped, "
231 "too distant\n"));
232 break;
233 }
234 sum = 0;
235 for (i = 0; i < length; i++)
236 sum +=
237 bus_space_read_1(tuple.memt,
238 tuple.memh,
239 addr + tuple.mult * i);
240 if (cksum != (sum & 0xff)) {
241 DPRINTF((" failed sum=%x\n",
242 sum));
243 device_printf(dev,
244 "CIS checksum failed\n");
245#if 0
246 /*
247 * XXX Some working cards have
248 * XXX bad checksums!!
249 */
250 ret = -1;
251#endif
252 } else {
253 DPRINTF((" ok\n"));
254 }
255 }
256 break;
257 case PCCARD_CISTPL_LONGLINK_MFC:
258 if (tuple.length < 1) {
259 DPRINTF(("CISTPL_LONGLINK_MFC too "
260 "short %d\n", tuple.length));
261 break;
262 }
263 /*
264 * this is kind of ad hoc, as I don't have
265 * any real documentation
266 */
267 {
268 int i;
269
270 mfc_count =
271 pccard_tuple_read_1(&tuple, 0);
272 DPRINTF(("CISTPL_LONGLINK_MFC %d",
273 mfc_count));
274 for (i = 0; i < mfc_count; i++) {
275 mfc[i].common =
276 (pccard_tuple_read_1(&tuple,
277 1 + 5 * i) ==
278 PCCARD_MFC_MEM_COMMON) ?
279 1 : 0;
280 mfc[i].addr =
281 pccard_tuple_read_4(&tuple,
282 1 + 5 * i + 1);
283 DPRINTF((" %s:%lx",
284 mfc[i].common ? "common" :
285 "attr", mfc[i].addr));
286 }
287 DPRINTF(("\n"));
288 }
289 /*
290 * for LONGLINK_MFC, fall through to the
291 * function. This tuple has structural and
292 * semantic content.
293 */
294 default:
295 {
296 if ((*fct) (&tuple, arg)) {
297 ret = 1;
298 goto done;
299 }
300 }
301 break;
302 } /* switch */
303#ifdef PCCARDCISDEBUG
304 /* print the tuple */
305 {
306 int i;
307
308 DPRINTF((" %02x %02x", tuple.code,
309 tuple.length));
310
311 for (i = 0; i < tuple.length; i++) {
312 DPRINTF((" %02x",
313 pccard_tuple_read_1(&tuple, i)));
314 if ((i % 16) == 13)
315 DPRINTF(("\n"));
316 }
317 if ((i % 16) != 14)
318 DPRINTF(("\n"));
319 }
320#endif
321 /* skip to the next tuple */
322 tuple.ptr += 2 + tuple.length;
323 }
324
325#ifdef XXX /* I'm not up to this tonight, need to implement new API */
326 /* to deal with moving windows and such. At least that's */
327 /* what it appears at this instant */
328
329 /*
330 * the chain is done. Clean up and move onto the next one,
331 * if any. The loop is here in the case that there is an MFC
332 * card with no longlink (which defaults to existing, == 0).
333 * In general, this means that if one pointer fails, it will
334 * try the next one, instead of just bailing.
335 */
336
337 while (1) {
338 pccard_chip_mem_unmap(pct, pch, window);
339
340 if (longlink_present) {
341 /*
342 * if the longlink is to attribute memory,
343 * then it is unindexed. That is, if the
344 * link value is 0x100, then the actual
345 * memory address is 0x200. This means that
346 * we need to multiply by 2 before calling
347 * mem_map, and then divide the resulting ptr
348 * by 2 after.
349 */
350
351 if (!longlink_common)
352 longlink_addr *= 2;
353
354 pccard_chip_mem_map(pct, pch, longlink_common ?
355 PCCARD_MEM_COMMON : PCCARD_MEM_ATTR,
356 longlink_addr, PCCARD_CIS_SIZE,
357 &pcmh, &tuple.ptr, &window);
358
359 if (!longlink_common)
360 tuple.ptr /= 2;
361 DPRINTF(("cis mem map %x\n",
362 (unsigned int) tuple.memh));
363 tuple.mult = longlink_common ? 1 : 2;
364 longlink_present = 0;
365 longlink_common = 1;
366 longlink_addr = 0;
367 } else if (mfc_count && (mfc_index < mfc_count)) {
368 if (!mfc[mfc_index].common)
369 mfc[mfc_index].addr *= 2;
370
371 pccard_chip_mem_map(pct, pch,
372 mfc[mfc_index].common ?
373 PCCARD_MEM_COMMON : PCCARD_MEM_ATTR,
374 mfc[mfc_index].addr, PCCARD_CIS_SIZE,
375 &pcmh, &tuple.ptr, &window);
376
377 if (!mfc[mfc_index].common)
378 tuple.ptr /= 2;
379 DPRINTF(("cis mem map %x\n",
380 (unsigned int) tuple.memh));
381 /* set parse state, and point at the next one */
382
383 tuple.mult = mfc[mfc_index].common ? 1 : 2;
384
385 mfc_index++;
386 } else {
387 goto done;
388 }
389
390 /* make sure that the link is valid */
391 tuple.code = pccard_cis_read_1(&tuple, tuple.ptr);
392 if (tuple.code != PCCARD_CISTPL_LINKTARGET) {
393 DPRINTF(("CISTPL_LINKTARGET expected, "
394 "code %02x observed\n", tuple.code));
395 continue;
396 }
397 tuple.length = pccard_cis_read_1(&tuple, tuple.ptr + 1);
398 if (tuple.length < 3) {
399 DPRINTF(("CISTPL_LINKTARGET too short %d\n",
400 tuple.length));
401 continue;
402 }
403 if ((pccard_tuple_read_1(&tuple, 0) != 'C') ||
404 (pccard_tuple_read_1(&tuple, 1) != 'I') ||
405 (pccard_tuple_read_1(&tuple, 2) != 'S')) {
406 DPRINTF(("CISTPL_LINKTARGET magic "
407 "%02x%02x%02x incorrect\n",
408 pccard_tuple_read_1(&tuple, 0),
409 pccard_tuple_read_1(&tuple, 1),
410 pccard_tuple_read_1(&tuple, 2)));
411 continue;
412 }
413 tuple.ptr += 2 + tuple.length;
414
415 break;
416 }
417#endif /* XXX */
418 }
419
420done:
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
428void
429pccard_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 %lx mask %lx\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
592int
593pccard_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 DPRINTF(("CISTPL_MANFID\n"));
751 break;
752 case PCCARD_CISTPL_FUNCID:
753 if (tuple->length < 1) {
754 DPRINTF(("CISTPL_FUNCID too short %d\n",
755 tuple->length));
756 break;
757 }
758 if ((state->pf == NULL) || (state->gotmfc == 2)) {
759 state->pf = malloc(sizeof(*state->pf), M_DEVBUF,
760 M_NOWAIT | M_ZERO);
761 state->pf->number = state->count++;
762 state->pf->last_config_index = -1;
763 STAILQ_INIT(&state->pf->cfe_head);
764
765 STAILQ_INSERT_TAIL(&state->card->pf_head, state->pf,
766 pf_list);
767 }
768 state->pf->function = pccard_tuple_read_1(tuple, 0);
769
770 DPRINTF(("CISTPL_FUNCID\n"));
771 break;
772 case PCCARD_CISTPL_FUNCE:
773 if (state->pf == NULL || state->pf->function <= 0) {
774 DPRINTF(("CISTPL_FUNCE is not followed by "
775 "valid CISTPL_FUNCID\n"));
776 break;
777 }
778 if (tuple->length >= 2) {
779 decode_funce(tuple, state->pf);
780 }
781 DPRINTF(("CISTPL_FUNCE\n"));
782 break;
783 case PCCARD_CISTPL_CONFIG:
784 if (tuple->length < 3) {
785 DPRINTF(("CISTPL_CONFIG too short %d\n",
786 tuple->length));
787 break;
788 } {
789 u_int reg, rasz, rmsz, rfsz;
790 int i;
791
792 reg = pccard_tuple_read_1(tuple, 0);
793 rasz = 1 + ((reg & PCCARD_TPCC_RASZ_MASK) >>
794 PCCARD_TPCC_RASZ_SHIFT);
795 rmsz = 1 + ((reg & PCCARD_TPCC_RMSZ_MASK) >>
796 PCCARD_TPCC_RMSZ_SHIFT);
797 rfsz = ((reg & PCCARD_TPCC_RFSZ_MASK) >>
798 PCCARD_TPCC_RFSZ_SHIFT);
799
800 if (tuple->length < (rasz + rmsz + rfsz)) {
801 DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too "
802 "short %d\n", rasz, rmsz, rfsz,
803 tuple->length));
804 break;
805 }
806 if (state->pf == NULL) {
807 state->pf = malloc(sizeof(*state->pf),
808 M_DEVBUF, M_NOWAIT | M_ZERO);
809 state->pf->number = state->count++;
810 state->pf->last_config_index = -1;
811 STAILQ_INIT(&state->pf->cfe_head);
812
813 STAILQ_INSERT_TAIL(&state->card->pf_head,
814 state->pf, pf_list);
815
816 state->pf->function = PCCARD_FUNCTION_UNSPEC;
817 }
818 state->pf->last_config_index =
819 pccard_tuple_read_1(tuple, 1);
820
821 state->pf->ccr_base = 0;
822 for (i = 0; i < rasz; i++)
823 state->pf->ccr_base |=
824 ((pccard_tuple_read_1(tuple, 2 + i)) <<
825 (i * 8));
826
827 state->pf->ccr_mask = 0;
828 for (i = 0; i < rmsz; i++)
829 state->pf->ccr_mask |=
830 ((pccard_tuple_read_1(tuple,
831 2 + rasz + i)) << (i * 8));
832
833 /* skip the reserved area and subtuples */
834
835 /* reset the default cfe for each cfe list */
836 state->temp_cfe = init_cfe;
837 state->default_cfe = &state->temp_cfe;
838 }
839 DPRINTF(("CISTPL_CONFIG\n"));
840 break;
841 case PCCARD_CISTPL_CFTABLE_ENTRY:
842 {
843 int idx, i, j;
844 u_int reg, reg2;
845 u_int intface, def, num;
846 u_int power, timing, iospace, irq, memspace, misc;
847 struct pccard_config_entry *cfe;
848
849 idx = 0;
850
851 reg = pccard_tuple_read_1(tuple, idx);
852 idx++;
853 intface = reg & PCCARD_TPCE_INDX_INTFACE;
854 def = reg & PCCARD_TPCE_INDX_DEFAULT;
855 num = reg & PCCARD_TPCE_INDX_NUM_MASK;
856
857 /*
858 * this is a little messy. Some cards have only a
859 * cfentry with the default bit set. So, as we go
860 * through the list, we add new indexes to the queue,
861 * and keep a pointer to the last one with the
862 * default bit set. if we see a record with the same
863 * index, as the default, we stash the default and
864 * replace the queue entry. otherwise, we just add
865 * new entries to the queue, pointing the default ptr
866 * at them if the default bit is set. if we get to
867 * the end with the default pointer pointing at a
868 * record which hasn't had a matching index, that's
869 * ok; it just becomes a cfentry like any other.
870 */
871
872 /*
873 * if the index in the cis differs from the default
874 * cis, create new entry in the queue and start it
875 * with the current default
876 */
877 if (num != state->default_cfe->number) {
878 cfe = (struct pccard_config_entry *)
879 malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
880
881 *cfe = *state->default_cfe;
882
883 STAILQ_INSERT_TAIL(&state->pf->cfe_head,
884 cfe, cfe_list);
885
886 cfe->number = num;
887
888 /*
889 * if the default bit is set in the cis, then
890 * point the new default at whatever is being
891 * filled in
892 */
893 if (def)
894 state->default_cfe = cfe;
895 } else {
896 /*
897 * the cis index matches the default index,
898 * fill in the default cfentry. It is
899 * assumed that the cfdefault index is in the
900 * queue. For it to be otherwise, the cis
901 * index would have to be -1 (initial
902 * condition) which is not possible, or there
903 * would have to be a preceding cis entry
904 * which had the same cis index and had the
905 * default bit unset. Neither condition
906 * should happen. If it does, this cfentry
907 * is lost (written into temp space), which
908 * is an acceptable failure mode.
909 */
910
911 cfe = state->default_cfe;
912
913 /*
914 * if the cis entry does not have the default
915 * bit set, copy the default out of the way
916 * first.
917 */
918 if (!def) {
919 state->temp_cfe = *state->default_cfe;
920 state->default_cfe = &state->temp_cfe;
921 }
922 }
923
924 if (intface) {
925 reg = pccard_tuple_read_1(tuple, idx);
926 idx++;
927 if (reg & PCCARD_TPCE_IF_MWAIT)
928 cfe->flags |= PCCARD_CFE_MWAIT_REQUIRED;
929 if (reg & PCCARD_TPCE_IF_RDYBSY)
930 cfe->flags |= PCCARD_CFE_RDYBSY_ACTIVE;
931 if (reg & PCCARD_TPCE_IF_WP)
932 cfe->flags |= PCCARD_CFE_WP_ACTIVE;
933 if (reg & PCCARD_TPCE_IF_BVD)
934 cfe->flags |= PCCARD_CFE_BVD_ACTIVE;
935 cfe->iftype = reg & PCCARD_TPCE_IF_IFTYPE;
936 }
937 reg = pccard_tuple_read_1(tuple, idx);
938 idx++;
939
940 power = reg & PCCARD_TPCE_FS_POWER_MASK;
941 timing = reg & PCCARD_TPCE_FS_TIMING;
942 iospace = reg & PCCARD_TPCE_FS_IOSPACE;
943 irq = reg & PCCARD_TPCE_FS_IRQ;
944 memspace = reg & PCCARD_TPCE_FS_MEMSPACE_MASK;
945 misc = reg & PCCARD_TPCE_FS_MISC;
946
947 if (power) {
948 /* skip over power, don't save */
949 /* for each parameter selection byte */
950 for (i = 0; i < power; i++) {
951 reg = pccard_tuple_read_1(tuple, idx);
952 idx++;
953 /* for each bit */
954 for (j = 0; j < 7; j++) {
955 /* if the bit is set */
956 if ((reg >> j) & 0x01) {
957 /* skip over bytes */
958 do {
959 reg2 = pccard_tuple_read_1(tuple, idx);
960 idx++;
961 /*
962 * until
963 * non-extensi
964 * on byte
965 */
966 } while (reg2 & 0x80);
967 }
968 }
969 }
970 }
971 if (timing) {
972 /* skip over timing, don't save */
973 reg = pccard_tuple_read_1(tuple, idx);
974 idx++;
975
976 if ((reg & PCCARD_TPCE_TD_RESERVED_MASK) !=
977 PCCARD_TPCE_TD_RESERVED_MASK)
978 idx++;
979 if ((reg & PCCARD_TPCE_TD_RDYBSY_MASK) !=
980 PCCARD_TPCE_TD_RDYBSY_MASK)
981 idx++;
982 if ((reg & PCCARD_TPCE_TD_WAIT_MASK) !=
983 PCCARD_TPCE_TD_WAIT_MASK)
984 idx++;
985 }
986 if (iospace) {
987 if (tuple->length <= idx) {
988 DPRINTF(("ran out of space before TCPE_IO\n"));
989 goto abort_cfe;
990 }
991
992 reg = pccard_tuple_read_1(tuple, idx);
993 idx++;
994
995 if (reg & PCCARD_TPCE_IO_BUSWIDTH_8BIT)
996 cfe->flags |= PCCARD_CFE_IO8;
997 if (reg & PCCARD_TPCE_IO_BUSWIDTH_16BIT)
998 cfe->flags |= PCCARD_CFE_IO16;
999 cfe->iomask =
1000 reg & PCCARD_TPCE_IO_IOADDRLINES_MASK;
1001
1002 if (reg & PCCARD_TPCE_IO_HASRANGE) {
1003 reg = pccard_tuple_read_1(tuple, idx);
1004 idx++;
1005
1006 cfe->num_iospace = 1 + (reg &
1007 PCCARD_TPCE_IO_RANGE_COUNT);
1008
1009 if (cfe->num_iospace >
1010 (sizeof(cfe->iospace) /
1011 sizeof(cfe->iospace[0]))) {
1012 DPRINTF(("too many io "
1013 "spaces %d",
1014 cfe->num_iospace));
1015 state->card->error++;
1016 break;
1017 }
1018 for (i = 0; i < cfe->num_iospace; i++) {
1019 switch (reg & PCCARD_TPCE_IO_RANGE_ADDRSIZE_MASK) {
1020 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_ONE:
1021 cfe->iospace[i].start =
1022 pccard_tuple_read_1(tuple, idx);
1023 idx++;
1024 break;
1025 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_TWO:
1026 cfe->iospace[i].start =
1027 pccard_tuple_read_2(tuple, idx);
1028 idx += 2;
1029 break;
1030 case PCCARD_TPCE_IO_RANGE_ADDRSIZE_FOUR:
1031 cfe->iospace[i].start =
1032 pccard_tuple_read_4(tuple, idx);
1033 idx += 4;
1034 break;
1035 }
1036 switch (reg &
1037 PCCARD_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
1038 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_ONE:
1039 cfe->iospace[i].length =
1040 pccard_tuple_read_1(tuple, idx);
1041 idx++;
1042 break;
1043 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_TWO:
1044 cfe->iospace[i].length =
1045 pccard_tuple_read_2(tuple, idx);
1046 idx += 2;
1047 break;
1048 case PCCARD_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
1049 cfe->iospace[i].length =
1050 pccard_tuple_read_4(tuple, idx);
1051 idx += 4;
1052 break;
1053 }
1054 cfe->iospace[i].length++;
1055 }
1056 } else {
1057 cfe->num_iospace = 1;
1058 cfe->iospace[0].start = 0;
1059 cfe->iospace[0].length =
1060 (1 << cfe->iomask);
1061 }
1062 }
1063 if (irq) {
1064 if (tuple->length <= idx) {
1065 DPRINTF(("ran out of space before TCPE_IR\n"));
1066 goto abort_cfe;
1067 }
1068
1069 reg = pccard_tuple_read_1(tuple, idx);
1070 idx++;
1071
1072 if (reg & PCCARD_TPCE_IR_SHARE)
1073 cfe->flags |= PCCARD_CFE_IRQSHARE;
1074 if (reg & PCCARD_TPCE_IR_PULSE)
1075 cfe->flags |= PCCARD_CFE_IRQPULSE;
1076 if (reg & PCCARD_TPCE_IR_LEVEL)
1077 cfe->flags |= PCCARD_CFE_IRQLEVEL;
1078
1079 if (reg & PCCARD_TPCE_IR_HASMASK) {
1080 /*
1081 * it's legal to ignore the
1082 * special-interrupt bits, so I will
1083 */
1084
1085 cfe->irqmask =
1086 pccard_tuple_read_2(tuple, idx);
1087 idx += 2;
1088 } else {
1089 cfe->irqmask =
1090 (1 << (reg & PCCARD_TPCE_IR_IRQ));
1091 }
1092 }
1093 if (memspace) {
1094 if (tuple->length <= idx) {
1095 DPRINTF(("ran out of space before TCPE_MS\n"));
1096 goto abort_cfe;
1097 }
1098
1099 if (memspace == PCCARD_TPCE_FS_MEMSPACE_NONE) {
1100 cfe->num_memspace = 0;
1101 } else if (memspace == PCCARD_TPCE_FS_MEMSPACE_LENGTH) {
1102 cfe->num_memspace = 1;
1103 cfe->memspace[0].length = 256 *
1104 pccard_tuple_read_2(tuple, idx);
1105 idx += 2;
1106 cfe->memspace[0].cardaddr = 0;
1107 cfe->memspace[0].hostaddr = 0;
1108 } else if (memspace ==
1109 PCCARD_TPCE_FS_MEMSPACE_LENGTHADDR) {
1110 cfe->num_memspace = 1;
1111 cfe->memspace[0].length = 256 *
1112 pccard_tuple_read_2(tuple, idx);
1113 idx += 2;
1114 cfe->memspace[0].cardaddr = 256 *
1115 pccard_tuple_read_2(tuple, idx);
1116 idx += 2;
1117 cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr;
1118 } else {
1119 int lengthsize;
1120 int cardaddrsize;
1121 int hostaddrsize;
1122
1123 reg = pccard_tuple_read_1(tuple, idx);
1124 idx++;
1125
1126 cfe->num_memspace = (reg &
1127 PCCARD_TPCE_MS_COUNT) + 1;
1128
1129 if (cfe->num_memspace >
1130 (sizeof(cfe->memspace) /
1131 sizeof(cfe->memspace[0]))) {
1132 DPRINTF(("too many mem "
1133 "spaces %d",
1134 cfe->num_memspace));
1135 state->card->error++;
1136 break;
1137 }
1138 lengthsize =
1139 ((reg & PCCARD_TPCE_MS_LENGTH_SIZE_MASK) >>
1140 PCCARD_TPCE_MS_LENGTH_SIZE_SHIFT);
1141 cardaddrsize =
1142 ((reg & PCCARD_TPCE_MS_CARDADDR_SIZE_MASK) >>
1143 PCCARD_TPCE_MS_CARDADDR_SIZE_SHIFT);
1144 hostaddrsize =
1145 (reg & PCCARD_TPCE_MS_HOSTADDR) ? cardaddrsize : 0;
1146
1147 if (lengthsize == 0) {
1148 DPRINTF(("cfe memspace "
1149 "lengthsize == 0"));
1150 state->card->error++;
1151 }
1152 for (i = 0; i < cfe->num_memspace; i++) {
1153 if (lengthsize) {
1154 cfe->memspace[i].length =
1155 256 * pccard_tuple_read_n(tuple, lengthsize,
1156 idx);
1157 idx += lengthsize;
1158 } else {
1159 cfe->memspace[i].length = 0;
1160 }
1161 if (cfe->memspace[i].length == 0) {
1162 DPRINTF(("cfe->memspace[%d].length == 0",
1163 i));
1164 state->card->error++;
1165 }
1166 if (cardaddrsize) {
1167 cfe->memspace[i].cardaddr =
1168 256 * pccard_tuple_read_n(tuple, cardaddrsize,
1169 idx);
1170 idx += cardaddrsize;
1171 } else {
1172 cfe->memspace[i].cardaddr = 0;
1173 }
1174 if (hostaddrsize) {
1175 cfe->memspace[i].hostaddr =
1176 256 * pccard_tuple_read_n(tuple, hostaddrsize,
1177 idx);
1178 idx += hostaddrsize;
1179 } else {
1180 cfe->memspace[i].hostaddr = 0;
1181 }
1182 }
1183 }
1184 }
1185 if (misc) {
1186 if (tuple->length <= idx) {
1187 DPRINTF(("ran out of space before TCPE_MI\n"));
1188 goto abort_cfe;
1189 }
1190
1191 reg = pccard_tuple_read_1(tuple, idx);
1192 idx++;
1193
1194 if (reg & PCCARD_TPCE_MI_PWRDOWN)
1195 cfe->flags = PCCARD_CFE_POWERDOWN;
1196 if (reg & PCCARD_TPCE_MI_READONLY)
1197 cfe->flags = PCCARD_CFE_READONLY;
1198 if (reg & PCCARD_TPCE_MI_AUDIO)
1199 cfe->flags = PCCARD_CFE_AUDIO;
1200 cfe->maxtwins = reg & PCCARD_TPCE_MI_MAXTWINS;
1201
1202 while (reg & PCCARD_TPCE_MI_EXT) {
1203 reg = pccard_tuple_read_1(tuple, idx);
1204 idx++;
1205 }
1206 }
1207 /* skip all the subtuples */
1208 }
1209
1210 abort_cfe:
1211 DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
1212 break;
1213 default:
1214 DPRINTF(("unhandled CISTPL %x\n", tuple->code));
1215 break;
1216 }
1217
1218 return (0);
1219}
1220
1221static int
1222decode_funce(struct pccard_tuple *tuple, struct pccard_function *pf)
1223{
1224 int type = pccard_tuple_read_1(tuple, 0);
1225
1226 switch (pf->function) {
1227 case PCCARD_FUNCTION_DISK:
1228 if (type == PCCARD_TPLFE_TYPE_DISK_DEVICE_INTERFACE) {
1229 pf->pf_funce_disk_interface
1230 = pccard_tuple_read_1(tuple, 1);
1231 }
1232 break;
1233 case PCCARD_FUNCTION_NETWORK:
1234 if (type == PCCARD_TPLFE_TYPE_LAN_NID) {
1235 int i;
1236 int len = pccard_tuple_read_1(tuple, 1);
1237 if (tuple->length < 2 + len || len > 8) {
1238 /* tuple length not enough or nid too long */
1239 break;
1240 }
1241 for (i = 0; i < len; i++) {
1242 pf->pf_funce_lan_nid[i]
1243 = pccard_tuple_read_1(tuple, i + 2);
1244 }
1245 pf->pf_funce_lan_nidlen = len;
1246 }
1247 break;
1248 default:
1249 break;
1250 }
1251 return 0;
1252}