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