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