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