Line data Source code
1 : /* $OpenBSD: pcmcia_cis.c,v 1.21 2017/09/08 05:36:52 deraadt Exp $ */
2 : /* $NetBSD: pcmcia_cis.c,v 1.9 1998/08/22 23:41:48 msaitoh Exp $ */
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/device.h>
36 : #include <sys/malloc.h>
37 :
38 : #include <dev/pcmcia/pcmciareg.h>
39 : #include <dev/pcmcia/pcmciachip.h>
40 : #include <dev/pcmcia/pcmciavar.h>
41 :
42 : #ifdef PCMCIACISDEBUG
43 : #define DPRINTF(arg) printf arg
44 : #else
45 : #define DPRINTF(arg)
46 : #endif
47 :
48 : #define PCMCIA_CIS_SIZE 1024
49 :
50 : struct cis_state {
51 : int count;
52 : int gotmfc;
53 : struct pcmcia_config_entry temp_cfe;
54 : struct pcmcia_config_entry *default_cfe;
55 : struct pcmcia_card *card;
56 : struct pcmcia_function *pf;
57 : };
58 :
59 : int pcmcia_parse_cis_tuple(struct pcmcia_tuple *, void *);
60 :
61 : uint8_t
62 0 : pcmcia_cis_read_1(struct pcmcia_tuple *tuple, bus_size_t idx)
63 : {
64 0 : if (tuple->flags & PTF_INDIRECT) {
65 0 : bus_space_write_1(tuple->memt, tuple->memh,
66 : tuple->indirect_ptr + PCMCIA_INDR_CONTROL, PCMCIA_ICR_ATTR);
67 0 : idx <<= tuple->addrshift;
68 0 : bus_space_write_1(tuple->memt, tuple->memh,
69 : tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 0, idx >> 0);
70 0 : bus_space_write_1(tuple->memt, tuple->memh,
71 : tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 1, idx >> 8);
72 0 : bus_space_write_1(tuple->memt, tuple->memh,
73 : tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 2, idx >> 16);
74 0 : bus_space_write_1(tuple->memt, tuple->memh,
75 : tuple->indirect_ptr + PCMCIA_INDR_ADDRESS + 3, idx >> 24);
76 0 : return bus_space_read_1(tuple->memt, tuple->memh,
77 : tuple->indirect_ptr + PCMCIA_INDR_DATA);
78 : } else
79 0 : return bus_space_read_1(tuple->memt, tuple->memh,
80 : idx << tuple->addrshift);
81 0 : }
82 :
83 : void
84 0 : pcmcia_read_cis(sc)
85 : struct pcmcia_softc *sc;
86 : {
87 0 : struct cis_state state;
88 :
89 0 : memset(&state, 0, sizeof state);
90 :
91 0 : state.card = &sc->card;
92 :
93 0 : state.card->error = 0;
94 0 : state.card->cis1_major = -1;
95 0 : state.card->cis1_minor = -1;
96 0 : state.card->cis1_info[0] = NULL;
97 0 : state.card->cis1_info[1] = NULL;
98 0 : state.card->cis1_info[2] = NULL;
99 0 : state.card->cis1_info[3] = NULL;
100 0 : state.card->manufacturer = PCMCIA_VENDOR_INVALID;
101 0 : state.card->product = PCMCIA_PRODUCT_INVALID;
102 0 : SIMPLEQ_INIT(&state.card->pf_head);
103 :
104 0 : state.pf = NULL;
105 :
106 0 : if (pcmcia_scan_cis((struct device *)sc, pcmcia_parse_cis_tuple,
107 0 : &state) == -1)
108 0 : state.card->error++;
109 0 : }
110 :
111 : int
112 0 : pcmcia_scan_cis(dev, fct, arg)
113 : struct device *dev;
114 : int (*fct)(struct pcmcia_tuple *, void *);
115 : void *arg;
116 : {
117 0 : struct pcmcia_softc *sc = (struct pcmcia_softc *) dev;
118 : pcmcia_chipset_tag_t pct;
119 : pcmcia_chipset_handle_t pch;
120 0 : int window;
121 0 : struct pcmcia_mem_handle pcmh;
122 0 : struct pcmcia_tuple tuple;
123 : int indirect_present;
124 : int longlink_present;
125 : int longlink_common;
126 : u_long longlink_addr;
127 : int mfc_count;
128 : int mfc_index;
129 0 : struct {
130 : int common;
131 : u_long addr;
132 : } mfc[256 / 5];
133 : int ret;
134 :
135 : ret = 0;
136 :
137 0 : pct = sc->pct;
138 0 : pch = sc->pch;
139 :
140 : /* allocate some memory */
141 :
142 0 : if (pcmcia_chip_mem_alloc(pct, pch, PCMCIA_CIS_SIZE, &pcmh)) {
143 : #ifdef DIAGNOSTIC
144 0 : printf("%s: can't alloc memory to read attributes\n",
145 0 : sc->dev.dv_xname);
146 : #endif
147 0 : return -1;
148 : }
149 :
150 : /* initialize state for the primary tuple chain */
151 0 : if (pcmcia_chip_mem_map(pct, pch, PCMCIA_MEM_ATTR, 0,
152 : PCMCIA_CIS_SIZE, &pcmh, &tuple.ptr, &window)) {
153 0 : pcmcia_chip_mem_free(pct, pch, &pcmh);
154 : #ifdef DIAGNOSTIC
155 0 : printf("%s: can't map memory to read attributes\n",
156 0 : sc->dev.dv_xname);
157 : #endif
158 0 : return -1;
159 : }
160 0 : tuple.memt = pcmh.memt;
161 0 : tuple.memh = pcmh.memh;
162 :
163 : DPRINTF(("cis mem map %x\n", (unsigned int) tuple.memh));
164 :
165 0 : tuple.addrshift = 1;
166 0 : tuple.flags = 0;
167 :
168 : indirect_present = 0;
169 : longlink_present = 1;
170 : longlink_common = 1;
171 : longlink_addr = 0;
172 :
173 : mfc_count = 0;
174 : mfc_index = 0;
175 :
176 : DPRINTF(("%s: CIS tuple chain:\n", sc->dev.dv_xname));
177 :
178 0 : while (1) {
179 0 : while (1) {
180 : /*
181 : * Perform boundary check for insane cards.
182 : * If CIS is too long, simulate CIS end.
183 : * (This check may not be sufficient for
184 : * malicious cards.)
185 : */
186 0 : if ((tuple.ptr << tuple.addrshift) >=
187 : PCMCIA_CIS_SIZE - 1 - 32 /* ad hoc value */) {
188 : DPRINTF(("CISTPL_END (too long CIS)\n"));
189 0 : tuple.code = PCMCIA_CISTPL_END;
190 0 : goto cis_end;
191 : }
192 :
193 : /* get the tuple code */
194 :
195 0 : tuple.code = pcmcia_cis_read_1(&tuple, tuple.ptr);
196 :
197 : /* two special-case tuples */
198 :
199 0 : if (tuple.code == PCMCIA_CISTPL_NULL) {
200 : DPRINTF(("CISTPL_NONE\n 00\n"));
201 0 : tuple.ptr++;
202 0 : continue;
203 0 : } else if (tuple.code == PCMCIA_CISTPL_END) {
204 : DPRINTF(("CISTPL_END\n ff\n"));
205 : cis_end:
206 : /* Call the function for the END tuple, since
207 : the CIS semantics depend on it */
208 0 : if ((*fct) (&tuple, arg)) {
209 0 : pcmcia_chip_mem_unmap(pct, pch,
210 : window);
211 : ret = 1;
212 0 : goto done;
213 : }
214 0 : tuple.ptr++;
215 : break;
216 : }
217 : /* now all the normal tuples */
218 :
219 0 : tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
220 0 : switch (tuple.code) {
221 : case PCMCIA_CISTPL_INDIRECT:
222 : indirect_present = 1;
223 : DPRINTF(("CISTPL_INDIRECT\n"));
224 0 : break;
225 : case PCMCIA_CISTPL_LONGLINK_A:
226 : case PCMCIA_CISTPL_LONGLINK_C:
227 0 : if (tuple.length < 4) {
228 : DPRINTF(("CISTPL_LONGLINK_%s too "
229 : "short %d\n",
230 : longlink_common ? "C" : "A",
231 : tuple.length));
232 : break;
233 : }
234 : longlink_present = 1;
235 0 : longlink_common = (tuple.code ==
236 : PCMCIA_CISTPL_LONGLINK_C) ? 1 : 0;
237 0 : longlink_addr = pcmcia_tuple_read_4(&tuple, 0);
238 : DPRINTF(("CISTPL_LONGLINK_%s %lx\n",
239 : longlink_common ? "C" : "A",
240 : longlink_addr));
241 0 : break;
242 : case PCMCIA_CISTPL_NO_LINK:
243 : longlink_present = 0;
244 : DPRINTF(("CISTPL_NO_LINK\n"));
245 0 : break;
246 : case PCMCIA_CISTPL_CHECKSUM:
247 0 : if (tuple.length < 5) {
248 : DPRINTF(("CISTPL_CHECKSUM too "
249 : "short %d\n", tuple.length));
250 : break;
251 : } {
252 : int16_t offset;
253 : u_long addr, length;
254 : u_int cksum, sum;
255 : int i;
256 :
257 : *((u_int16_t *) & offset) =
258 0 : pcmcia_tuple_read_2(&tuple, 0);
259 0 : length = pcmcia_tuple_read_2(&tuple, 2);
260 0 : cksum = pcmcia_tuple_read_1(&tuple, 4);
261 :
262 0 : addr = tuple.ptr + offset;
263 :
264 : DPRINTF(("CISTPL_CHECKSUM addr=%lx "
265 : "len=%lx cksum=%x",
266 : addr, length, cksum));
267 :
268 : /*
269 : * XXX do more work to deal with
270 : * distant regions
271 : */
272 0 : if ((addr >= PCMCIA_CIS_SIZE) ||
273 0 : ((addr + length) >=
274 : PCMCIA_CIS_SIZE)) {
275 : DPRINTF((" skipped, "
276 : "too distant\n"));
277 0 : break;
278 : }
279 : sum = 0;
280 0 : for (i = 0; i < length; i++)
281 0 : sum += pcmcia_cis_read_1(&tuple,
282 0 : addr + i);
283 0 : if (cksum != (sum & 0xff)) {
284 : DPRINTF((" failed sum=%x\n",
285 : sum));
286 0 : printf("%s: CIS checksum "
287 : "failed\n",
288 0 : sc->dev.dv_xname);
289 : #if 0
290 : /*
291 : * XXX Some working cards have
292 : * XXX bad checksums!!
293 : */
294 : ret = -1;
295 : #endif
296 0 : } else {
297 : DPRINTF((" ok\n"));
298 : }
299 0 : }
300 : break;
301 : case PCMCIA_CISTPL_LONGLINK_MFC:
302 0 : if (tuple.length < 6) {
303 : DPRINTF(("CISTPL_LONGLINK_MFC too "
304 : "short %d\n", tuple.length));
305 : break;
306 : }
307 0 : if (((tuple.length - 1) % 5) != 0) {
308 : DPRINTF(("CISTPL_LONGLINK_MFC bogus "
309 : "length %d\n", tuple.length));
310 : break;
311 : }
312 : {
313 : int i, tmp_count;
314 :
315 : /*
316 : * put count into tmp var so that
317 : * if we have to bail (because it's
318 : * a bogus count) it won't be
319 : * remembered for later use.
320 : */
321 : tmp_count =
322 0 : pcmcia_tuple_read_1(&tuple, 0);
323 : DPRINTF(("CISTPL_LONGLINK_MFC %d",
324 : tmp_count));
325 :
326 : /*
327 : * make _sure_ it's the right size;
328 : * if too short, it may be a weird
329 : * (unknown/undefined) format
330 : */
331 0 : if (tuple.length != (tmp_count*5 + 1)) {
332 : DPRINTF((" bogus length %d\n",
333 : tuple.length));
334 0 : break;
335 : }
336 :
337 : #ifdef PCMCIACISDEBUG /* maybe enable all the time? */
338 : /*
339 : * sanity check for a programming
340 : * error which is difficult to find
341 : * when debugging.
342 : */
343 : if (tmp_count >
344 : howmany(sizeof mfc, sizeof mfc[0]))
345 : panic("CISTPL_LONGLINK_MFC mfc "
346 : "count would blow stack");
347 : #endif
348 :
349 : mfc_count = tmp_count;
350 0 : for (i = 0; i < mfc_count; i++) {
351 0 : mfc[i].common =
352 0 : (pcmcia_tuple_read_1(&tuple,
353 0 : 1 + 5 * i) ==
354 : PCMCIA_MFC_MEM_COMMON) ?
355 : 1 : 0;
356 0 : mfc[i].addr =
357 0 : pcmcia_tuple_read_4(&tuple,
358 : 1 + 5 * i + 1);
359 : DPRINTF((" %s:%lx",
360 : mfc[i].common ? "common" :
361 : "attr", mfc[i].addr));
362 : }
363 : DPRINTF(("\n"));
364 0 : }
365 : /*
366 : * for LONGLINK_MFC, fall through to the
367 : * function. This tuple has structural and
368 : * semantic content.
369 : */
370 : default:
371 : {
372 0 : if ((*fct) (&tuple, arg)) {
373 0 : pcmcia_chip_mem_unmap(pct,
374 : pch, window);
375 : ret = 1;
376 0 : goto done;
377 : }
378 : }
379 : break;
380 : } /* switch */
381 : #ifdef PCMCIACISDEBUG
382 : /* print the tuple */
383 : {
384 : int i;
385 :
386 : DPRINTF((" %02x %02x", tuple.code,
387 : tuple.length));
388 :
389 : for (i = 0; i < tuple.length; i++) {
390 : DPRINTF((" %02x",
391 : pcmcia_tuple_read_1(&tuple, i)));
392 : if ((i % 16) == 13)
393 : DPRINTF(("\n"));
394 : }
395 : if ((i % 16) != 14)
396 : DPRINTF(("\n"));
397 : }
398 : #endif
399 : /* skip to the next tuple */
400 0 : tuple.ptr += 2 + tuple.length;
401 : }
402 :
403 : /*
404 : * the chain is done. Clean up and move onto the next one,
405 : * if any. The loop is here in the case that there is an MFC
406 : * card with no longlink (which defaults to existing, == 0).
407 : * In general, this means that if one pointer fails, it will
408 : * try the next one, instead of just bailing.
409 : */
410 :
411 0 : while (1) {
412 0 : pcmcia_chip_mem_unmap(pct, pch, window);
413 :
414 0 : if (indirect_present) {
415 : /*
416 : * Indirect CIS data needs to be obtained
417 : * from specific registers accessible at
418 : * a fixed location in the common window,
419 : * but otherwise is similar to longlink
420 : * in attribute memory.
421 : */
422 :
423 0 : pcmcia_chip_mem_map(pct, pch, PCMCIA_MEM_COMMON,
424 : 0, PCMCIA_INDR_SIZE,
425 : &pcmh, &tuple.indirect_ptr, &window);
426 :
427 : DPRINTF(("cis mem map %x ind %x\n",
428 : (unsigned int) tuple.memh,
429 : (unsigned int) tuple.indirect_ptr));
430 :
431 0 : tuple.addrshift = 1;
432 0 : tuple.flags |= PTF_INDIRECT;
433 0 : tuple.ptr = 0;
434 : longlink_present = 0;
435 : indirect_present = 0;
436 0 : } else if (longlink_present) {
437 : /*
438 : * if the longlink is to attribute memory,
439 : * then it is unindexed. That is, if the
440 : * link value is 0x100, then the actual
441 : * memory address is 0x200. This means that
442 : * we need to multiply by 2 before calling
443 : * mem_map, and then divide the resulting ptr
444 : * by 2 after.
445 : */
446 :
447 0 : if (!longlink_common)
448 0 : longlink_addr *= 2;
449 :
450 0 : pcmcia_chip_mem_map(pct, pch, longlink_common ?
451 : PCMCIA_MEM_COMMON : PCMCIA_MEM_ATTR,
452 : longlink_addr, PCMCIA_CIS_SIZE,
453 : &pcmh, &tuple.ptr, &window);
454 :
455 0 : if (!longlink_common)
456 0 : tuple.ptr /= 2;
457 :
458 : DPRINTF(("cis mem map %x\n",
459 : (unsigned int) tuple.memh));
460 :
461 0 : tuple.addrshift = longlink_common ? 0 : 1;
462 : longlink_present = 0;
463 : longlink_common = 1;
464 : longlink_addr = 0;
465 0 : } else if (mfc_count && (mfc_index < mfc_count)) {
466 0 : if (!mfc[mfc_index].common)
467 0 : mfc[mfc_index].addr *= 2;
468 :
469 0 : pcmcia_chip_mem_map(pct, pch,
470 : mfc[mfc_index].common ?
471 : PCMCIA_MEM_COMMON : PCMCIA_MEM_ATTR,
472 : mfc[mfc_index].addr, PCMCIA_CIS_SIZE,
473 : &pcmh, &tuple.ptr, &window);
474 :
475 0 : if (!mfc[mfc_index].common)
476 0 : tuple.ptr /= 2;
477 :
478 : DPRINTF(("cis mem map %x\n",
479 : (unsigned int) tuple.memh));
480 :
481 : /* set parse state, and point at the next one */
482 :
483 0 : tuple.addrshift = mfc[mfc_index].common ? 0 : 1;
484 :
485 0 : mfc_index++;
486 : } else {
487 : goto done;
488 : }
489 :
490 : /* make sure that the link is valid */
491 0 : tuple.code = pcmcia_cis_read_1(&tuple, tuple.ptr);
492 0 : if (tuple.code != PCMCIA_CISTPL_LINKTARGET) {
493 : DPRINTF(("CISTPL_LINKTARGET expected, "
494 : "code %02x observed\n", tuple.code));
495 0 : continue;
496 : }
497 0 : tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
498 0 : if (tuple.length < 3) {
499 : DPRINTF(("CISTPL_LINKTARGET too short %d\n",
500 : tuple.length));
501 0 : continue;
502 : }
503 0 : if ((pcmcia_tuple_read_1(&tuple, 0) != 'C') ||
504 0 : (pcmcia_tuple_read_1(&tuple, 1) != 'I') ||
505 0 : (pcmcia_tuple_read_1(&tuple, 2) != 'S')) {
506 : DPRINTF(("CISTPL_LINKTARGET magic "
507 : "%02x%02x%02x incorrect\n",
508 : pcmcia_tuple_read_1(&tuple, 0),
509 : pcmcia_tuple_read_1(&tuple, 1),
510 : pcmcia_tuple_read_1(&tuple, 2)));
511 0 : continue;
512 : }
513 0 : tuple.ptr += 2 + tuple.length;
514 :
515 : break;
516 : }
517 : }
518 :
519 : pcmcia_chip_mem_unmap(pct, pch, window);
520 :
521 : done:
522 : /* Last, free the allocated memory block */
523 0 : pcmcia_chip_mem_free(pct, pch, &pcmh);
524 :
525 0 : return (ret);
526 0 : }
527 :
528 : /* XXX this is incredibly verbose. Not sure what trt is */
529 :
530 : void
531 0 : pcmcia_print_cis(sc)
532 : struct pcmcia_softc *sc;
533 : {
534 0 : struct pcmcia_card *card = &sc->card;
535 : struct pcmcia_function *pf;
536 : struct pcmcia_config_entry *cfe;
537 : int i;
538 :
539 0 : printf("%s: CIS version ", sc->dev.dv_xname);
540 0 : if (card->cis1_major == 4) {
541 0 : if (card->cis1_minor == 0)
542 0 : printf("PCMCIA 1.0\n");
543 0 : else if (card->cis1_minor == 1)
544 0 : printf("PCMCIA 2.0 or 2.1\n");
545 0 : } else if (card->cis1_major >= 5)
546 0 : printf("PC Card Standard %d.%d\n", card->cis1_major,
547 : card->cis1_minor);
548 : else
549 0 : printf("unknown (major=%d, minor=%d)\n",
550 : card->cis1_major, card->cis1_minor);
551 :
552 0 : printf("%s: CIS info: ", sc->dev.dv_xname);
553 0 : for (i = 0; i < 4; i++) {
554 0 : if (card->cis1_info[i] == NULL)
555 : break;
556 0 : if (i)
557 0 : printf(", ");
558 0 : printf("%s", card->cis1_info[i]);
559 : }
560 0 : printf("\n");
561 :
562 0 : printf("%s: Manufacturer code 0x%x, product 0x%x\n",
563 0 : sc->dev.dv_xname, card->manufacturer, card->product);
564 :
565 0 : SIMPLEQ_FOREACH(pf, &card->pf_head, pf_list) {
566 0 : printf("%s: function %d: ", sc->dev.dv_xname, pf->number);
567 :
568 0 : switch (pf->function) {
569 : case PCMCIA_FUNCTION_UNSPEC:
570 0 : printf("unspecified");
571 0 : break;
572 : case PCMCIA_FUNCTION_MULTIFUNCTION:
573 0 : printf("multi-function");
574 0 : break;
575 : case PCMCIA_FUNCTION_MEMORY:
576 0 : printf("memory");
577 0 : break;
578 : case PCMCIA_FUNCTION_SERIAL:
579 0 : printf("serial port");
580 0 : break;
581 : case PCMCIA_FUNCTION_PARALLEL:
582 0 : printf("parallel port");
583 0 : break;
584 : case PCMCIA_FUNCTION_DISK:
585 0 : printf("fixed disk");
586 0 : break;
587 : case PCMCIA_FUNCTION_VIDEO:
588 0 : printf("video adapter");
589 0 : break;
590 : case PCMCIA_FUNCTION_NETWORK:
591 0 : printf("network adapter");
592 0 : break;
593 : case PCMCIA_FUNCTION_AIMS:
594 0 : printf("auto incrementing mass storage");
595 0 : break;
596 : case PCMCIA_FUNCTION_SCSI:
597 0 : printf("SCSI bridge");
598 0 : break;
599 : case PCMCIA_FUNCTION_SECURITY:
600 0 : printf("Security services");
601 0 : break;
602 : case PCMCIA_FUNCTION_INSTRUMENT:
603 0 : printf("Instrument");
604 0 : break;
605 : case PCMCIA_FUNCTION_IOBUS:
606 0 : printf("Serial I/O Bus Adapter");
607 0 : break;
608 : default:
609 0 : printf("unknown (%d)", pf->function);
610 0 : break;
611 : }
612 :
613 0 : printf(", ccr addr %lx mask %lx\n", pf->ccr_base, pf->ccr_mask);
614 :
615 0 : SIMPLEQ_FOREACH(cfe, &pf->cfe_head, cfe_list) {
616 0 : printf("%s: function %d, config table entry %d: ",
617 0 : sc->dev.dv_xname, pf->number, cfe->number);
618 :
619 0 : switch (cfe->iftype) {
620 : case PCMCIA_IFTYPE_MEMORY:
621 0 : printf("memory card");
622 0 : break;
623 : case PCMCIA_IFTYPE_IO:
624 0 : printf("I/O card");
625 0 : break;
626 : default:
627 0 : printf("card type unknown");
628 0 : break;
629 : }
630 :
631 0 : printf("; irq mask %x", cfe->irqmask);
632 :
633 0 : if (cfe->num_iospace) {
634 0 : printf("; iomask %lx, iospace", cfe->iomask);
635 :
636 0 : for (i = 0; i < cfe->num_iospace; i++)
637 0 : printf(" %lx%s%lx",
638 0 : cfe->iospace[i].start,
639 0 : cfe->iospace[i].length ? "-" : "",
640 0 : cfe->iospace[i].start +
641 0 : cfe->iospace[i].length - 1);
642 : }
643 0 : if (cfe->num_memspace) {
644 0 : printf("; memspace");
645 :
646 0 : for (i = 0; i < cfe->num_memspace; i++)
647 0 : printf(" %lx%s%lx%s%lx",
648 0 : cfe->memspace[i].cardaddr,
649 0 : cfe->memspace[i].length ? "-" : "",
650 0 : cfe->memspace[i].cardaddr +
651 0 : cfe->memspace[i].length - 1,
652 0 : cfe->memspace[i].hostaddr ?
653 : "@" : "",
654 : cfe->memspace[i].hostaddr);
655 : }
656 0 : if (cfe->maxtwins)
657 0 : printf("; maxtwins %d", cfe->maxtwins);
658 :
659 0 : printf(";");
660 :
661 0 : if (cfe->flags & PCMCIA_CFE_MWAIT_REQUIRED)
662 0 : printf(" mwait_required");
663 0 : if (cfe->flags & PCMCIA_CFE_RDYBSY_ACTIVE)
664 0 : printf(" rdybsy_active");
665 0 : if (cfe->flags & PCMCIA_CFE_WP_ACTIVE)
666 0 : printf(" wp_active");
667 0 : if (cfe->flags & PCMCIA_CFE_BVD_ACTIVE)
668 0 : printf(" bvd_active");
669 0 : if (cfe->flags & PCMCIA_CFE_IO8)
670 0 : printf(" io8");
671 0 : if (cfe->flags & PCMCIA_CFE_IO16)
672 0 : printf(" io16");
673 0 : if (cfe->flags & PCMCIA_CFE_IRQSHARE)
674 0 : printf(" irqshare");
675 0 : if (cfe->flags & PCMCIA_CFE_IRQPULSE)
676 0 : printf(" irqpulse");
677 0 : if (cfe->flags & PCMCIA_CFE_IRQLEVEL)
678 0 : printf(" irqlevel");
679 0 : if (cfe->flags & PCMCIA_CFE_POWERDOWN)
680 0 : printf(" powerdown");
681 0 : if (cfe->flags & PCMCIA_CFE_READONLY)
682 0 : printf(" readonly");
683 0 : if (cfe->flags & PCMCIA_CFE_AUDIO)
684 0 : printf(" audio");
685 :
686 0 : printf("\n");
687 : }
688 : }
689 :
690 0 : if (card->error)
691 0 : printf("%s: %d errors found while parsing CIS\n",
692 0 : sc->dev.dv_xname, card->error);
693 0 : }
694 :
695 : int
696 0 : pcmcia_parse_cis_tuple(tuple, arg)
697 : struct pcmcia_tuple *tuple;
698 : void *arg;
699 : {
700 : /* most of these are educated guesses */
701 : static struct pcmcia_config_entry init_cfe = {
702 : -1, PCMCIA_CFE_RDYBSY_ACTIVE | PCMCIA_CFE_WP_ACTIVE |
703 : PCMCIA_CFE_BVD_ACTIVE, PCMCIA_IFTYPE_MEMORY,
704 : };
705 :
706 0 : struct cis_state *state = arg;
707 :
708 0 : switch (tuple->code) {
709 : case PCMCIA_CISTPL_END:
710 : /*
711 : * If we've seen a LONGLINK_MFC, and this is the first
712 : * END after it, reset the function list.
713 : *
714 : * XXX This might also be the right place to start a
715 : * new function, but that assumes that a function
716 : * definition never crosses any longlink, and I'm not
717 : * sure about that. This is probably safe for MFC
718 : * cards, but what we have now isn't broken, so I'd
719 : * rather not change it.
720 : */
721 0 : if (state->gotmfc == 1) {
722 : struct pcmcia_function *pf, *pfnext;
723 :
724 0 : for (pf = SIMPLEQ_FIRST(&state->card->pf_head);
725 0 : pf != NULL; pf = pfnext) {
726 0 : pfnext = SIMPLEQ_NEXT(pf, pf_list);
727 0 : free(pf, M_DEVBUF, 0);
728 : }
729 :
730 0 : SIMPLEQ_INIT(&state->card->pf_head);
731 :
732 0 : state->count = 0;
733 0 : state->gotmfc = 2;
734 0 : state->pf = NULL;
735 0 : }
736 : break;
737 :
738 : case PCMCIA_CISTPL_LONGLINK_MFC:
739 : /*
740 : * This tuple's structure was dealt with in scan_cis. here,
741 : * record the fact that the MFC tuple was seen, so that
742 : * functions declared before the MFC link can be cleaned
743 : * up.
744 : */
745 0 : state->gotmfc = 1;
746 0 : break;
747 :
748 : #ifdef PCMCIACISDEBUG
749 : case PCMCIA_CISTPL_DEVICE:
750 : case PCMCIA_CISTPL_DEVICE_A:
751 : {
752 : u_int reg, dtype, dspeed;
753 :
754 : reg = pcmcia_tuple_read_1(tuple, 0);
755 : dtype = reg & PCMCIA_DTYPE_MASK;
756 : dspeed = reg & PCMCIA_DSPEED_MASK;
757 :
758 : DPRINTF(("CISTPL_DEVICE%s type=",
759 : (tuple->code == PCMCIA_CISTPL_DEVICE) ? "" : "_A"));
760 : switch (dtype) {
761 : case PCMCIA_DTYPE_NULL:
762 : DPRINTF(("null"));
763 : break;
764 : case PCMCIA_DTYPE_ROM:
765 : DPRINTF(("rom"));
766 : break;
767 : case PCMCIA_DTYPE_OTPROM:
768 : DPRINTF(("otprom"));
769 : break;
770 : case PCMCIA_DTYPE_EPROM:
771 : DPRINTF(("eprom"));
772 : break;
773 : case PCMCIA_DTYPE_EEPROM:
774 : DPRINTF(("eeprom"));
775 : break;
776 : case PCMCIA_DTYPE_FLASH:
777 : DPRINTF(("flash"));
778 : break;
779 : case PCMCIA_DTYPE_SRAM:
780 : DPRINTF(("sram"));
781 : break;
782 : case PCMCIA_DTYPE_DRAM:
783 : DPRINTF(("dram"));
784 : break;
785 : case PCMCIA_DTYPE_FUNCSPEC:
786 : DPRINTF(("funcspec"));
787 : break;
788 : case PCMCIA_DTYPE_EXTEND:
789 : DPRINTF(("extend"));
790 : break;
791 : default:
792 : DPRINTF(("reserved"));
793 : break;
794 : }
795 : DPRINTF((" speed="));
796 : switch (dspeed) {
797 : case PCMCIA_DSPEED_NULL:
798 : DPRINTF(("null"));
799 : break;
800 : case PCMCIA_DSPEED_250NS:
801 : DPRINTF(("250ns"));
802 : break;
803 : case PCMCIA_DSPEED_200NS:
804 : DPRINTF(("200ns"));
805 : break;
806 : case PCMCIA_DSPEED_150NS:
807 : DPRINTF(("150ns"));
808 : break;
809 : case PCMCIA_DSPEED_100NS:
810 : DPRINTF(("100ns"));
811 : break;
812 : case PCMCIA_DSPEED_EXT:
813 : DPRINTF(("ext"));
814 : break;
815 : default:
816 : DPRINTF(("reserved"));
817 : break;
818 : }
819 : }
820 : DPRINTF(("\n"));
821 : break;
822 : #endif
823 :
824 : case PCMCIA_CISTPL_VERS_1:
825 0 : if (tuple->length < 6) {
826 : DPRINTF(("CISTPL_VERS_1 too short %d\n",
827 : tuple->length));
828 : break;
829 : } {
830 : int start, i, ch, count;
831 :
832 0 : state->card->cis1_major = pcmcia_tuple_read_1(tuple, 0);
833 0 : state->card->cis1_minor = pcmcia_tuple_read_1(tuple, 1);
834 :
835 0 : for (count = 0, start = 0, i = 0;
836 0 : (count < 4) && ((i + 4) < 256); i++) {
837 0 : ch = pcmcia_tuple_read_1(tuple, 2 + i);
838 0 : if (ch == 0xff)
839 : break;
840 0 : state->card->cis1_info_buf[i] = ch;
841 0 : if (ch == 0) {
842 0 : state->card->cis1_info[count] =
843 0 : state->card->cis1_info_buf + start;
844 0 : start = i + 1;
845 0 : count++;
846 0 : }
847 : }
848 : DPRINTF(("CISTPL_VERS_1\n"));
849 : }
850 0 : break;
851 :
852 : case PCMCIA_CISTPL_MANFID:
853 0 : if (tuple->length < 4) {
854 : DPRINTF(("CISTPL_MANFID too short %d\n",
855 : tuple->length));
856 : break;
857 : }
858 0 : state->card->manufacturer = pcmcia_tuple_read_2(tuple, 0);
859 0 : state->card->product = pcmcia_tuple_read_2(tuple, 2);
860 : DPRINTF(("CISTPL_MANFID\n"));
861 0 : break;
862 :
863 : case PCMCIA_CISTPL_FUNCID:
864 0 : if (tuple->length < 2) {
865 : DPRINTF(("CISTPL_FUNCID too short %d\n",
866 : tuple->length));
867 : break;
868 : }
869 :
870 : /*
871 : * As far as I understand this, manufacturers do multifunction
872 : * cards in various ways. Sadly enough I do not have the
873 : * PC-Card standard (donate!) so I can only guess what can
874 : * be done.
875 : * The original code implies FUNCID nodes are above CONFIG
876 : * nodes in the CIS tree, however Xircom does it the other
877 : * way round, which of course makes things a bit hard.
878 : * --niklas@openbsd.org
879 : */
880 0 : if (state->pf) {
881 0 : if (state->pf->function == PCMCIA_FUNCTION_UNSPEC) {
882 : /*
883 : * This looks like a opportunistic function
884 : * created by a CONFIG tuple. Just keep it.
885 : */
886 : } else {
887 : /*
888 : * A function is being defined, end it.
889 : */
890 0 : state->pf = NULL;
891 : }
892 : }
893 0 : if (state->pf == NULL) {
894 0 : state->pf = malloc(sizeof(*state->pf), M_DEVBUF,
895 : M_NOWAIT | M_ZERO);
896 0 : if (state->pf == NULL)
897 0 : panic("pcmcia_parse_cis_tuple");
898 0 : state->pf->number = state->count++;
899 0 : state->pf->last_config_index = -1;
900 0 : SIMPLEQ_INIT(&state->pf->cfe_head);
901 :
902 0 : SIMPLEQ_INSERT_TAIL(&state->card->pf_head, state->pf,
903 : pf_list);
904 0 : }
905 0 : state->pf->function = pcmcia_tuple_read_1(tuple, 0);
906 :
907 : DPRINTF(("CISTPL_FUNCID\n"));
908 0 : break;
909 :
910 : case PCMCIA_CISTPL_CONFIG:
911 0 : if (tuple->length < 3) {
912 : DPRINTF(("CISTPL_CONFIG too short %d\n",
913 : tuple->length));
914 : break;
915 : } {
916 : u_int reg, rasz, rmsz, rfsz;
917 : int i;
918 :
919 0 : reg = pcmcia_tuple_read_1(tuple, 0);
920 0 : rasz = 1 + ((reg & PCMCIA_TPCC_RASZ_MASK) >>
921 : PCMCIA_TPCC_RASZ_SHIFT);
922 0 : rmsz = 1 + ((reg & PCMCIA_TPCC_RMSZ_MASK) >>
923 : PCMCIA_TPCC_RMSZ_SHIFT);
924 0 : rfsz = ((reg & PCMCIA_TPCC_RFSZ_MASK) >>
925 : PCMCIA_TPCC_RFSZ_SHIFT);
926 :
927 0 : if (tuple->length < 2 + rasz + rmsz + rfsz) {
928 : DPRINTF(("CISTPL_CONFIG (%d,%d,%d) too "
929 : "short %d\n", rasz, rmsz, rfsz,
930 : tuple->length));
931 0 : break;
932 : }
933 0 : if (state->pf == NULL) {
934 0 : state->pf = malloc(sizeof(*state->pf),
935 : M_DEVBUF, M_NOWAIT | M_ZERO);
936 0 : if (state->pf == NULL)
937 0 : panic("pcmcia_parse_cis_tuple");
938 0 : state->pf->number = state->count++;
939 0 : state->pf->last_config_index = -1;
940 0 : SIMPLEQ_INIT(&state->pf->cfe_head);
941 :
942 0 : SIMPLEQ_INSERT_TAIL(&state->card->pf_head,
943 : state->pf, pf_list);
944 :
945 0 : state->pf->function = PCMCIA_FUNCTION_UNSPEC;
946 0 : }
947 0 : state->pf->last_config_index =
948 0 : pcmcia_tuple_read_1(tuple, 1);
949 :
950 0 : state->pf->ccr_base = 0;
951 0 : for (i = 0; i < rasz; i++)
952 0 : state->pf->ccr_base |=
953 0 : ((pcmcia_tuple_read_1(tuple, 2 + i)) <<
954 0 : (i * 8));
955 :
956 0 : state->pf->ccr_mask = 0;
957 0 : for (i = 0; i < rmsz; i++)
958 0 : state->pf->ccr_mask |=
959 0 : ((pcmcia_tuple_read_1(tuple,
960 0 : 2 + rasz + i)) << (i * 8));
961 :
962 : /* skip the reserved area and subtuples */
963 :
964 : /* reset the default cfe for each cfe list */
965 0 : state->temp_cfe = init_cfe;
966 0 : state->default_cfe = &state->temp_cfe;
967 0 : }
968 : DPRINTF(("CISTPL_CONFIG\n"));
969 : break;
970 :
971 : case PCMCIA_CISTPL_CFTABLE_ENTRY:
972 0 : if (tuple->length < 2) {
973 : DPRINTF(("CISTPL_CFTABLE_ENTRY too short %d\n",
974 : tuple->length));
975 : break;
976 : } {
977 : int idx, i, j;
978 : u_int reg, reg2;
979 : u_int intface, def, num;
980 : u_int power, timing, iospace, irq, memspace, misc;
981 : struct pcmcia_config_entry *cfe;
982 :
983 : idx = 0;
984 :
985 0 : reg = pcmcia_tuple_read_1(tuple, idx);
986 : idx++;
987 0 : intface = reg & PCMCIA_TPCE_INDX_INTFACE;
988 0 : def = reg & PCMCIA_TPCE_INDX_DEFAULT;
989 0 : num = reg & PCMCIA_TPCE_INDX_NUM_MASK;
990 :
991 : /*
992 : * this is a little messy. Some cards have only a
993 : * cfentry with the default bit set. So, as we go
994 : * through the list, we add new indexes to the queue,
995 : * and keep a pointer to the last one with the
996 : * default bit set. if we see a record with the same
997 : * index, as the default, we stash the default and
998 : * replace the queue entry. otherwise, we just add
999 : * new entries to the queue, pointing the default ptr
1000 : * at them if the default bit is set. if we get to
1001 : * the end with the default pointer pointing at a
1002 : * record which hasn't had a matching index, that's
1003 : * ok; it just becomes a cfentry like any other.
1004 : */
1005 :
1006 : /*
1007 : * if the index in the cis differs from the default
1008 : * cis, create new entry in the queue and start it
1009 : * with the current default
1010 : */
1011 0 : if (state->default_cfe == NULL) {
1012 : DPRINTF(("CISTPL_CFTABLE_ENTRY with no "
1013 : "default\n"));
1014 0 : break;
1015 : }
1016 0 : if (num != state->default_cfe->number) {
1017 0 : cfe = (struct pcmcia_config_entry *)
1018 0 : malloc(sizeof(*cfe), M_DEVBUF, M_NOWAIT);
1019 0 : if (cfe == NULL)
1020 0 : panic("pcmcia_parse_cis_tuple");
1021 :
1022 0 : *cfe = *state->default_cfe;
1023 :
1024 0 : SIMPLEQ_INSERT_TAIL(&state->pf->cfe_head,
1025 : cfe, cfe_list);
1026 :
1027 0 : cfe->number = num;
1028 :
1029 : /*
1030 : * if the default bit is set in the cis, then
1031 : * point the new default at whatever is being
1032 : * filled in
1033 : */
1034 0 : if (def)
1035 0 : state->default_cfe = cfe;
1036 : } else {
1037 : /*
1038 : * the cis index matches the default index,
1039 : * fill in the default cfentry. It is
1040 : * assumed that the cfdefault index is in the
1041 : * queue. For it to be otherwise, the cis
1042 : * index would have to be -1 (initial
1043 : * condition) which is not possible, or there
1044 : * would have to be a preceding cis entry
1045 : * which had the same cis index and had the
1046 : * default bit unset. Neither condition
1047 : * should happen. If it does, this cfentry
1048 : * is lost (written into temp space), which
1049 : * is an acceptable failure mode.
1050 : */
1051 :
1052 : cfe = state->default_cfe;
1053 :
1054 : /*
1055 : * if the cis entry does not have the default
1056 : * bit set, copy the default out of the way
1057 : * first.
1058 : */
1059 0 : if (!def) {
1060 0 : state->temp_cfe = *state->default_cfe;
1061 0 : state->default_cfe = &state->temp_cfe;
1062 0 : }
1063 : }
1064 :
1065 0 : if (intface) {
1066 0 : reg = pcmcia_tuple_read_1(tuple, idx);
1067 : idx++;
1068 0 : cfe->flags &= ~(PCMCIA_CFE_MWAIT_REQUIRED
1069 : | PCMCIA_CFE_RDYBSY_ACTIVE
1070 : | PCMCIA_CFE_WP_ACTIVE
1071 : | PCMCIA_CFE_BVD_ACTIVE);
1072 0 : if (reg & PCMCIA_TPCE_IF_MWAIT)
1073 0 : cfe->flags |= PCMCIA_CFE_MWAIT_REQUIRED;
1074 0 : if (reg & PCMCIA_TPCE_IF_RDYBSY)
1075 0 : cfe->flags |= PCMCIA_CFE_RDYBSY_ACTIVE;
1076 0 : if (reg & PCMCIA_TPCE_IF_WP)
1077 0 : cfe->flags |= PCMCIA_CFE_WP_ACTIVE;
1078 0 : if (reg & PCMCIA_TPCE_IF_BVD)
1079 0 : cfe->flags |= PCMCIA_CFE_BVD_ACTIVE;
1080 0 : cfe->iftype = reg & PCMCIA_TPCE_IF_IFTYPE;
1081 0 : }
1082 0 : reg = pcmcia_tuple_read_1(tuple, idx);
1083 0 : idx++;
1084 :
1085 0 : power = reg & PCMCIA_TPCE_FS_POWER_MASK;
1086 0 : timing = reg & PCMCIA_TPCE_FS_TIMING;
1087 0 : iospace = reg & PCMCIA_TPCE_FS_IOSPACE;
1088 0 : irq = reg & PCMCIA_TPCE_FS_IRQ;
1089 0 : memspace = reg & PCMCIA_TPCE_FS_MEMSPACE_MASK;
1090 0 : misc = reg & PCMCIA_TPCE_FS_MISC;
1091 :
1092 0 : if (power) {
1093 : /* skip over power, don't save */
1094 : /* for each parameter selection byte */
1095 0 : for (i = 0; i < power; i++) {
1096 0 : reg = pcmcia_tuple_read_1(tuple, idx);
1097 0 : idx++;
1098 : /* for each bit */
1099 0 : for (j = 0; j < 7; j++) {
1100 : /* if the bit is set */
1101 0 : if ((reg >> j) & 0x01) {
1102 : /* skip over bytes */
1103 0 : do {
1104 0 : reg2 = pcmcia_tuple_read_1(tuple, idx);
1105 0 : idx++;
1106 : /*
1107 : * until
1108 : * non-
1109 : * extension
1110 : * byte
1111 : */
1112 0 : } while (reg2 & 0x80);
1113 : }
1114 : }
1115 : }
1116 : }
1117 0 : if (timing) {
1118 : /* skip over timing, don't save */
1119 0 : reg = pcmcia_tuple_read_1(tuple, idx);
1120 0 : idx++;
1121 :
1122 0 : if ((reg & PCMCIA_TPCE_TD_RESERVED_MASK) !=
1123 : PCMCIA_TPCE_TD_RESERVED_MASK)
1124 0 : idx++;
1125 0 : if ((reg & PCMCIA_TPCE_TD_RDYBSY_MASK) !=
1126 : PCMCIA_TPCE_TD_RDYBSY_MASK)
1127 0 : idx++;
1128 0 : if ((reg & PCMCIA_TPCE_TD_WAIT_MASK) !=
1129 : PCMCIA_TPCE_TD_WAIT_MASK)
1130 0 : idx++;
1131 : }
1132 0 : if (iospace) {
1133 0 : if (tuple->length <= idx) {
1134 : DPRINTF(("ran out of space before TPCE_IO\n"));
1135 :
1136 0 : goto abort_cfe;
1137 : }
1138 :
1139 0 : reg = pcmcia_tuple_read_1(tuple, idx);
1140 0 : idx++;
1141 :
1142 0 : cfe->flags &=
1143 : ~(PCMCIA_CFE_IO8 | PCMCIA_CFE_IO16);
1144 0 : if (reg & PCMCIA_TPCE_IO_BUSWIDTH_8BIT)
1145 0 : cfe->flags |= PCMCIA_CFE_IO8;
1146 0 : if (reg & PCMCIA_TPCE_IO_BUSWIDTH_16BIT)
1147 0 : cfe->flags |= PCMCIA_CFE_IO16;
1148 0 : cfe->iomask =
1149 0 : reg & PCMCIA_TPCE_IO_IOADDRLINES_MASK;
1150 :
1151 0 : if (reg & PCMCIA_TPCE_IO_HASRANGE) {
1152 0 : reg = pcmcia_tuple_read_1(tuple, idx);
1153 0 : idx++;
1154 :
1155 0 : cfe->num_iospace = 1 + (reg &
1156 : PCMCIA_TPCE_IO_RANGE_COUNT);
1157 :
1158 0 : if (cfe->num_iospace >
1159 : (sizeof(cfe->iospace) /
1160 : sizeof(cfe->iospace[0]))) {
1161 : DPRINTF(("too many io "
1162 : "spaces %d",
1163 : cfe->num_iospace));
1164 0 : state->card->error++;
1165 0 : break;
1166 : }
1167 0 : for (i = 0; i < cfe->num_iospace; i++) {
1168 0 : switch (reg & PCMCIA_TPCE_IO_RANGE_ADDRSIZE_MASK) {
1169 : case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_ONE:
1170 0 : cfe->iospace[i].start =
1171 0 : pcmcia_tuple_read_1(tuple, idx);
1172 0 : idx++;
1173 0 : break;
1174 : case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_TWO:
1175 0 : cfe->iospace[i].start =
1176 0 : pcmcia_tuple_read_2(tuple, idx);
1177 : idx += 2;
1178 0 : break;
1179 : case PCMCIA_TPCE_IO_RANGE_ADDRSIZE_FOUR:
1180 0 : cfe->iospace[i].start =
1181 0 : pcmcia_tuple_read_4(tuple, idx);
1182 0 : idx += 4;
1183 0 : break;
1184 : }
1185 0 : switch (reg &
1186 : PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_MASK) {
1187 : case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_ONE:
1188 0 : cfe->iospace[i].length =
1189 0 : pcmcia_tuple_read_1(tuple, idx);
1190 0 : idx++;
1191 0 : break;
1192 : case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_TWO:
1193 0 : cfe->iospace[i].length =
1194 0 : pcmcia_tuple_read_2(tuple, idx);
1195 : idx += 2;
1196 0 : break;
1197 : case PCMCIA_TPCE_IO_RANGE_LENGTHSIZE_FOUR:
1198 0 : cfe->iospace[i].length =
1199 0 : pcmcia_tuple_read_4(tuple, idx);
1200 0 : idx += 4;
1201 0 : break;
1202 : }
1203 0 : cfe->iospace[i].length++;
1204 : }
1205 : } else {
1206 0 : cfe->num_iospace = 1;
1207 0 : cfe->iospace[0].start = 0;
1208 0 : cfe->iospace[0].length =
1209 0 : (1 << cfe->iomask);
1210 : }
1211 : }
1212 :
1213 0 : if (irq) {
1214 0 : if (tuple->length <= idx) {
1215 : DPRINTF(("ran out of space before TPCE_IR\n"));
1216 :
1217 0 : goto abort_cfe;
1218 : }
1219 :
1220 0 : reg = pcmcia_tuple_read_1(tuple, idx);
1221 0 : idx++;
1222 :
1223 0 : cfe->flags &= ~(PCMCIA_CFE_IRQSHARE
1224 : | PCMCIA_CFE_IRQPULSE
1225 : | PCMCIA_CFE_IRQLEVEL);
1226 0 : if (reg & PCMCIA_TPCE_IR_SHARE)
1227 0 : cfe->flags |= PCMCIA_CFE_IRQSHARE;
1228 0 : if (reg & PCMCIA_TPCE_IR_PULSE)
1229 0 : cfe->flags |= PCMCIA_CFE_IRQPULSE;
1230 0 : if (reg & PCMCIA_TPCE_IR_LEVEL)
1231 0 : cfe->flags |= PCMCIA_CFE_IRQLEVEL;
1232 :
1233 0 : if (reg & PCMCIA_TPCE_IR_HASMASK) {
1234 : /*
1235 : * it's legal to ignore the
1236 : * special-interrupt bits, so I will
1237 : */
1238 :
1239 0 : cfe->irqmask =
1240 0 : pcmcia_tuple_read_2(tuple, idx);
1241 : idx += 2;
1242 0 : } else {
1243 0 : cfe->irqmask =
1244 0 : (1 << (reg & PCMCIA_TPCE_IR_IRQ));
1245 : }
1246 : }
1247 0 : if (memspace) {
1248 0 : if (tuple->length <= idx) {
1249 : DPRINTF(("ran out of space before TPCE_MS\n"));
1250 0 : goto abort_cfe;
1251 : }
1252 :
1253 0 : if (memspace == PCMCIA_TPCE_FS_MEMSPACE_NONE) {
1254 0 : cfe->num_memspace = 0;
1255 0 : } else if (memspace == PCMCIA_TPCE_FS_MEMSPACE_LENGTH) {
1256 0 : cfe->num_memspace = 1;
1257 0 : cfe->memspace[0].length = 256 *
1258 0 : pcmcia_tuple_read_2(tuple, idx);
1259 : idx += 2;
1260 0 : cfe->memspace[0].cardaddr = 0;
1261 0 : cfe->memspace[0].hostaddr = 0;
1262 0 : } else if (memspace ==
1263 : PCMCIA_TPCE_FS_MEMSPACE_LENGTHADDR) {
1264 0 : cfe->num_memspace = 1;
1265 0 : cfe->memspace[0].length = 256 *
1266 0 : pcmcia_tuple_read_2(tuple, idx);
1267 : idx += 2;
1268 0 : cfe->memspace[0].cardaddr = 256 *
1269 0 : pcmcia_tuple_read_2(tuple, idx);
1270 : idx += 2;
1271 0 : cfe->memspace[0].hostaddr = cfe->memspace[0].cardaddr;
1272 0 : } else {
1273 : int lengthsize;
1274 : int cardaddrsize;
1275 : int hostaddrsize;
1276 :
1277 0 : reg = pcmcia_tuple_read_1(tuple, idx);
1278 0 : idx++;
1279 :
1280 0 : cfe->num_memspace = (reg &
1281 0 : PCMCIA_TPCE_MS_COUNT) + 1;
1282 :
1283 0 : if (cfe->num_memspace >
1284 : (sizeof(cfe->memspace) /
1285 : sizeof(cfe->memspace[0]))) {
1286 : DPRINTF(("too many mem "
1287 : "spaces %d",
1288 : cfe->num_memspace));
1289 0 : state->card->error++;
1290 0 : break;
1291 : }
1292 : lengthsize =
1293 0 : ((reg & PCMCIA_TPCE_MS_LENGTH_SIZE_MASK) >>
1294 : PCMCIA_TPCE_MS_LENGTH_SIZE_SHIFT);
1295 : cardaddrsize =
1296 0 : ((reg & PCMCIA_TPCE_MS_CARDADDR_SIZE_MASK) >>
1297 : PCMCIA_TPCE_MS_CARDADDR_SIZE_SHIFT);
1298 : hostaddrsize =
1299 0 : (reg & PCMCIA_TPCE_MS_HOSTADDR) ? cardaddrsize : 0;
1300 :
1301 0 : if (lengthsize == 0) {
1302 : DPRINTF(("cfe memspace "
1303 : "lengthsize == 0"));
1304 0 : state->card->error++;
1305 0 : }
1306 0 : for (i = 0; i < cfe->num_memspace; i++) {
1307 0 : if (lengthsize) {
1308 0 : cfe->memspace[i].length =
1309 0 : 256 * pcmcia_tuple_read_n(tuple, lengthsize,
1310 : idx);
1311 0 : idx += lengthsize;
1312 0 : } else {
1313 0 : cfe->memspace[i].length = 0;
1314 : }
1315 0 : if (cfe->memspace[i].length == 0) {
1316 : DPRINTF(("cfe->memspace[%d].length == 0",
1317 : i));
1318 0 : state->card->error++;
1319 0 : }
1320 0 : if (cardaddrsize) {
1321 0 : cfe->memspace[i].cardaddr =
1322 0 : 256 * pcmcia_tuple_read_n(tuple, cardaddrsize,
1323 : idx);
1324 0 : idx += cardaddrsize;
1325 0 : } else {
1326 0 : cfe->memspace[i].cardaddr = 0;
1327 : }
1328 0 : if (hostaddrsize) {
1329 0 : cfe->memspace[i].hostaddr =
1330 0 : 256 * pcmcia_tuple_read_n(tuple, hostaddrsize,
1331 : idx);
1332 0 : idx += hostaddrsize;
1333 0 : } else {
1334 0 : cfe->memspace[i].hostaddr = 0;
1335 : }
1336 : }
1337 0 : }
1338 : }
1339 0 : if (misc) {
1340 0 : if (tuple->length <= idx) {
1341 : DPRINTF(("ran out of space before TPCE_MI\n"));
1342 :
1343 0 : goto abort_cfe;
1344 : }
1345 :
1346 0 : reg = pcmcia_tuple_read_1(tuple, idx);
1347 0 : idx++;
1348 :
1349 0 : cfe->flags &= ~(PCMCIA_CFE_POWERDOWN
1350 : | PCMCIA_CFE_READONLY
1351 : | PCMCIA_CFE_AUDIO);
1352 0 : if (reg & PCMCIA_TPCE_MI_PWRDOWN)
1353 0 : cfe->flags |= PCMCIA_CFE_POWERDOWN;
1354 0 : if (reg & PCMCIA_TPCE_MI_READONLY)
1355 0 : cfe->flags |= PCMCIA_CFE_READONLY;
1356 0 : if (reg & PCMCIA_TPCE_MI_AUDIO)
1357 0 : cfe->flags |= PCMCIA_CFE_AUDIO;
1358 0 : cfe->maxtwins = reg & PCMCIA_TPCE_MI_MAXTWINS;
1359 :
1360 0 : while (reg & PCMCIA_TPCE_MI_EXT) {
1361 0 : reg = pcmcia_tuple_read_1(tuple, idx);
1362 0 : idx++;
1363 : }
1364 : }
1365 : /* skip all the subtuples */
1366 0 : }
1367 :
1368 : abort_cfe:
1369 : DPRINTF(("CISTPL_CFTABLE_ENTRY\n"));
1370 : break;
1371 :
1372 : default:
1373 : DPRINTF(("unhandled CISTPL %x\n", tuple->code));
1374 : break;
1375 : }
1376 :
1377 0 : return (0);
1378 0 : }
|