1 /*======================================================================
3 PCMCIA Card Information Structure parser
5 The contents of this file are subject to the Mozilla Public
6 License Version 2.0 (the "License"); you may not use this file
7 except in compliance with the License. You may obtain a copy of
8 the License at http://www.mozilla.org/MPL/
10 Software distributed under the License is distributed on an "AS
11 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
12 implied. See the License for the specific language governing
13 rights and limitations under the License.
15 The initial developer of the original code is David A. Hinds
16 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
17 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
19 Alternatively, the contents of this file may be used under the
20 terms of the GNU General Public License version 2 (the "GPL"), in
21 which case the provisions of the GPL are applicable instead of the
22 above. If you wish to allow the use of your version of this file
23 only under the terms of the GPL and not to allow others to use
24 your version of this file under the MPL, indicate your decision
25 by deleting the provisions above and replace them with the notice
26 and other provisions required by the GPL. If you do not delete
27 the provisions above, a recipient may use your version of this
28 file under either the MPL or the GPL.
30 ======================================================================*/
34 #include <asm/byteorder.h>
35 #define le16_to_cpu __le16_to_cpu
36 #define le32_to_cpu __le32_to_cpu
38 #include <pcmcia/cs_types.h>
39 #include <pcmcia/cs.h>
40 #include <pcmcia/bulkmem.h>
41 #include <pcmcia/cistpl.h>
43 static const u_char mantissa[] = {
44 10, 12, 13, 15, 20, 25, 30, 35,
45 40, 45, 50, 55, 60, 70, 80, 90
48 static const u_int exponent[] = {
49 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000
52 /* Convert an extended speed byte to a time in nanoseconds */
53 #define SPEED_CVT(v) \
54 (mantissa[(((v)>>3)&15)-1] * exponent[(v)&7] / 10)
55 /* Convert a power byte to a current in 0.1 microamps */
56 #define POWER_CVT(v) \
57 (mantissa[((v)>>3)&15] * exponent[(v)&7] / 10)
58 #define POWER_SCALE(v) (exponent[(v)&7])
60 /*======================================================================
62 Parsing routines for individual tuples
64 ======================================================================*/
66 static int parse_device(tuple_t *tuple, cistpl_device_t *device)
72 p = (u_char *)tuple->TupleData;
73 q = p + tuple->TupleDataLen;
76 for (i = 0; i < CISTPL_MAX_DEVICES; i++) {
78 if (*p == 0xff) break;
79 device->dev[i].type = (*p >> 4);
80 device->dev[i].wp = (*p & 0x08) ? 1 : 0;
82 case 0: device->dev[i].speed = 0; break;
83 case 1: device->dev[i].speed = 250; break;
84 case 2: device->dev[i].speed = 200; break;
85 case 3: device->dev[i].speed = 150; break;
86 case 4: device->dev[i].speed = 100; break;
88 if (++p == q) return CS_BAD_TUPLE;
89 device->dev[i].speed = SPEED_CVT(*p);
91 if (++p == q) return CS_BAD_TUPLE;
97 if (++p == q) return CS_BAD_TUPLE;
98 if (*p == 0xff) break;
100 if (scale == 7) return CS_BAD_TUPLE;
101 device->dev[i].size = ((*p >> 3) + 1) * (512 << (scale*2));
109 /*====================================================================*/
111 static int parse_checksum(tuple_t *tuple, cistpl_checksum_t *csum)
114 if (tuple->TupleDataLen < 5)
116 p = (u_char *)tuple->TupleData;
117 csum->addr = tuple->CISOffset+(short)le16_to_cpu(*(u_short *)p)-2;
118 csum->len = le16_to_cpu(*(u_short *)(p + 2));
123 /*====================================================================*/
125 static int parse_longlink(tuple_t *tuple, cistpl_longlink_t *link)
127 if (tuple->TupleDataLen < 4)
129 link->addr = le32_to_cpu(*(u_int *)tuple->TupleData);
133 /*====================================================================*/
135 static int parse_longlink_mfc(tuple_t *tuple,
136 cistpl_longlink_mfc_t *link)
141 p = (u_char *)tuple->TupleData;
144 if (tuple->TupleDataLen <= link->nfn*5)
146 for (i = 0; i < link->nfn; i++) {
147 link->fn[i].space = *p; p++;
148 link->fn[i].addr = le32_to_cpu(*(u_int *)p); p += 4;
153 /*====================================================================*/
155 static int parse_strings(u_char *p, u_char *q, int max,
156 char *s, u_char *ofs, u_char *found)
160 if (p == q) return CS_BAD_TUPLE;
162 for (i = 0; i < max; i++) {
163 if (*p == 0xff) break;
167 s[j++] = (*p == 0xff) ? '\0' : *p;
168 if ((*p == '\0') || (*p == 0xff)) break;
169 if (++p == q) return CS_BAD_TUPLE;
171 if ((*p == 0xff) || (++p == q)) break;
177 return (ns == max) ? CS_SUCCESS : CS_BAD_TUPLE;
181 /*====================================================================*/
183 static int parse_vers_1(tuple_t *tuple, cistpl_vers_1_t *vers_1)
187 p = (u_char *)tuple->TupleData;
188 q = p + tuple->TupleDataLen;
190 vers_1->major = *p; p++;
191 vers_1->minor = *p; p++;
192 if (p >= q) return CS_BAD_TUPLE;
194 return parse_strings(p, q, CISTPL_VERS_1_MAX_PROD_STRINGS,
195 vers_1->str, vers_1->ofs, &vers_1->ns);
198 /*====================================================================*/
200 static int parse_altstr(tuple_t *tuple, cistpl_altstr_t *altstr)
204 p = (u_char *)tuple->TupleData;
205 q = p + tuple->TupleDataLen;
207 return parse_strings(p, q, CISTPL_MAX_ALTSTR_STRINGS,
208 altstr->str, altstr->ofs, &altstr->ns);
211 /*====================================================================*/
213 static int parse_jedec(tuple_t *tuple, cistpl_jedec_t *jedec)
218 p = (u_char *)tuple->TupleData;
219 q = p + tuple->TupleDataLen;
221 for (nid = 0; nid < CISTPL_MAX_DEVICES; nid++) {
223 jedec->id[nid].mfr = p[0];
224 jedec->id[nid].info = p[1];
231 /*====================================================================*/
233 static int parse_manfid(tuple_t *tuple, cistpl_manfid_t *m)
236 if (tuple->TupleDataLen < 4)
238 p = (u_short *)tuple->TupleData;
239 m->manf = le16_to_cpu(p[0]);
240 m->card = le16_to_cpu(p[1]);
244 /*====================================================================*/
246 static int parse_funcid(tuple_t *tuple, cistpl_funcid_t *f)
249 if (tuple->TupleDataLen < 2)
251 p = (u_char *)tuple->TupleData;
257 /*====================================================================*/
259 static int parse_funce(tuple_t *tuple, cistpl_funce_t *f)
263 if (tuple->TupleDataLen < 1)
265 p = (u_char *)tuple->TupleData;
267 for (i = 1; i < tuple->TupleDataLen; i++)
272 /*====================================================================*/
274 static int parse_config(tuple_t *tuple, cistpl_config_t *config)
279 p = (u_char *)tuple->TupleData;
281 rmsz = (*p & 0x3c) >> 2;
282 if (tuple->TupleDataLen < rasz+rmsz+4)
284 config->last_idx = *(++p);
287 for (i = 0; i <= rasz; i++)
288 config->base += p[i] << (8*i);
290 for (i = 0; i < 4; i++)
291 config->rmask[i] = 0;
292 for (i = 0; i <= rmsz; i++)
293 config->rmask[i>>2] += p[i] << (8*(i%4));
294 config->subtuples = tuple->TupleDataLen - (rasz+rmsz+4);
298 /*======================================================================
300 The following routines are all used to parse the nightmarish
301 config table entries.
303 ======================================================================*/
305 static u_char *parse_power(u_char *p, u_char *q,
311 if (p == q) return NULL;
315 for (i = 0; i < 7; i++)
316 if (pwr->present & (1<<i)) {
317 if (p == q) return NULL;
318 pwr->param[i] = POWER_CVT(*p);
319 scale = POWER_SCALE(*p);
321 if (++p == q) return NULL;
322 if ((*p & 0x7f) < 100)
323 pwr->param[i] += (*p & 0x7f) * scale / 100;
325 pwr->flags |= CISTPL_POWER_HIGHZ_OK;
329 pwr->flags |= CISTPL_POWER_HIGHZ_REQ;
338 /*====================================================================*/
340 static u_char *parse_timing(u_char *p, u_char *q,
341 cistpl_timing_t *timing)
345 if (p == q) return NULL;
347 if ((scale & 3) != 3) {
348 if (++p == q) return NULL;
349 timing->wait = SPEED_CVT(*p);
350 timing->waitscale = exponent[scale & 3];
354 if ((scale & 7) != 7) {
355 if (++p == q) return NULL;
356 timing->ready = SPEED_CVT(*p);
357 timing->rdyscale = exponent[scale & 7];
362 if (++p == q) return NULL;
363 timing->reserved = SPEED_CVT(*p);
364 timing->rsvscale = exponent[scale];
366 timing->reserved = 0;
371 /*====================================================================*/
373 static u_char *parse_io(u_char *p, u_char *q, cistpl_io_t *io)
377 if (p == q) return NULL;
383 io->win[0].len = (1 << (io->flags & CISTPL_IO_LINES_MASK));
387 if (++p == q) return NULL;
388 io->nwin = (*p & 0x0f) + 1;
389 bsz = (*p & 0x30) >> 4;
391 lsz = (*p & 0xc0) >> 6;
395 for (i = 0; i < io->nwin; i++) {
398 for (j = 0; j < bsz; j++, p++) {
399 if (p == q) return NULL;
400 io->win[i].base += *p << (j*8);
402 for (j = 0; j < lsz; j++, p++) {
403 if (p == q) return NULL;
404 io->win[i].len += *p << (j*8);
410 /*====================================================================*/
412 static u_char *parse_mem(u_char *p, u_char *q, cistpl_mem_t *mem)
414 int i, j, asz, lsz, has_ha;
417 if (p == q) return NULL;
419 mem->nwin = (*p & 0x07) + 1;
420 lsz = (*p & 0x18) >> 3;
421 asz = (*p & 0x60) >> 5;
422 has_ha = (*p & 0x80);
423 if (++p == q) return NULL;
425 for (i = 0; i < mem->nwin; i++) {
427 for (j = 0; j < lsz; j++, p++) {
428 if (p == q) return NULL;
431 for (j = 0; j < asz; j++, p++) {
432 if (p == q) return NULL;
436 for (j = 0; j < asz; j++, p++) {
437 if (p == q) return NULL;
440 mem->win[i].len = len << 8;
441 mem->win[i].card_addr = ca << 8;
442 mem->win[i].host_addr = ha << 8;
447 /*====================================================================*/
449 static u_char *parse_irq(u_char *p, u_char *q, cistpl_irq_t *irq)
451 if (p == q) return NULL;
452 irq->IRQInfo1 = *p; p++;
453 if (irq->IRQInfo1 & IRQ_INFO2_VALID) {
454 if (p+2 > q) return NULL;
455 irq->IRQInfo2 = (p[1]<<8) + p[0];
461 /*====================================================================*/
463 static int parse_cftable_entry(tuple_t *tuple,
464 cistpl_cftable_entry_t *entry)
466 u_char *p, *q, features;
468 p = tuple->TupleData;
469 q = p + tuple->TupleDataLen;
470 entry->index = *p & 0x3f;
473 entry->flags |= CISTPL_CFTABLE_DEFAULT;
475 if (++p == q) return CS_BAD_TUPLE;
477 entry->flags |= CISTPL_CFTABLE_BVDS;
479 entry->flags |= CISTPL_CFTABLE_WP;
481 entry->flags |= CISTPL_CFTABLE_RDYBSY;
483 entry->flags |= CISTPL_CFTABLE_MWAIT;
484 entry->interface = *p & 0x0f;
486 entry->interface = 0;
488 /* Process optional features */
489 if (++p == q) return CS_BAD_TUPLE;
493 if ((features & 3) > 0) {
494 p = parse_power(p, q, &entry->vcc);
495 if (p == NULL) return CS_BAD_TUPLE;
497 entry->vcc.present = 0;
498 if ((features & 3) > 1) {
499 p = parse_power(p, q, &entry->vpp1);
500 if (p == NULL) return CS_BAD_TUPLE;
502 entry->vpp1.present = 0;
503 if ((features & 3) > 2) {
504 p = parse_power(p, q, &entry->vpp2);
505 if (p == NULL) return CS_BAD_TUPLE;
507 entry->vpp2.present = 0;
510 if (features & 0x04) {
511 p = parse_timing(p, q, &entry->timing);
512 if (p == NULL) return CS_BAD_TUPLE;
514 entry->timing.wait = 0;
515 entry->timing.ready = 0;
516 entry->timing.reserved = 0;
519 /* I/O window options */
520 if (features & 0x08) {
521 p = parse_io(p, q, &entry->io);
522 if (p == NULL) return CS_BAD_TUPLE;
526 /* Interrupt options */
527 if (features & 0x10) {
528 p = parse_irq(p, q, &entry->irq);
529 if (p == NULL) return CS_BAD_TUPLE;
531 entry->irq.IRQInfo1 = 0;
533 switch (features & 0x60) {
539 entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
540 entry->mem.win[0].card_addr = 0;
541 entry->mem.win[0].host_addr = 0;
543 if (p > q) return CS_BAD_TUPLE;
547 entry->mem.win[0].len = le16_to_cpu(*(u_short *)p) << 8;
548 entry->mem.win[0].card_addr =
549 le16_to_cpu(*(u_short *)(p+2)) << 8;
550 entry->mem.win[0].host_addr = 0;
552 if (p > q) return CS_BAD_TUPLE;
555 p = parse_mem(p, q, &entry->mem);
556 if (p == NULL) return CS_BAD_TUPLE;
561 if (features & 0x80) {
562 if (p == q) return CS_BAD_TUPLE;
563 entry->flags |= (*p << 8);
565 if (++p == q) return CS_BAD_TUPLE;
569 entry->subtuples = q-p;
574 /*====================================================================*/
576 static int parse_bar(tuple_t *tuple, cistpl_bar_t *bar)
579 if (tuple->TupleDataLen < 6)
581 p = (u_char *)tuple->TupleData;
584 bar->size = le32_to_cpu(*(u_int *)p);
588 static int parse_config_cb(tuple_t *tuple, cistpl_config_t *config)
592 p = (u_char *)tuple->TupleData;
593 if ((*p != 3) || (tuple->TupleDataLen < 6))
595 config->last_idx = *(++p);
597 config->base = le32_to_cpu(*(u_int *)p);
598 config->subtuples = tuple->TupleDataLen - 6;
602 static int parse_cftable_entry_cb(tuple_t *tuple,
603 cistpl_cftable_entry_cb_t *entry)
605 u_char *p, *q, features;
607 p = tuple->TupleData;
608 q = p + tuple->TupleDataLen;
609 entry->index = *p & 0x3f;
612 entry->flags |= CISTPL_CFTABLE_DEFAULT;
614 /* Process optional features */
615 if (++p == q) return CS_BAD_TUPLE;
619 if ((features & 3) > 0) {
620 p = parse_power(p, q, &entry->vcc);
621 if (p == NULL) return CS_BAD_TUPLE;
623 entry->vcc.present = 0;
624 if ((features & 3) > 1) {
625 p = parse_power(p, q, &entry->vpp1);
626 if (p == NULL) return CS_BAD_TUPLE;
628 entry->vpp1.present = 0;
629 if ((features & 3) > 2) {
630 p = parse_power(p, q, &entry->vpp2);
631 if (p == NULL) return CS_BAD_TUPLE;
633 entry->vpp2.present = 0;
635 /* I/O window options */
636 if (features & 0x08) {
637 if (p == q) return CS_BAD_TUPLE;
642 /* Interrupt options */
643 if (features & 0x10) {
644 p = parse_irq(p, q, &entry->irq);
645 if (p == NULL) return CS_BAD_TUPLE;
647 entry->irq.IRQInfo1 = 0;
649 if (features & 0x20) {
650 if (p == q) return CS_BAD_TUPLE;
651 entry->mem = *p; p++;
656 if (features & 0x80) {
657 if (p == q) return CS_BAD_TUPLE;
658 entry->flags |= (*p << 8);
660 if (++p == q) return CS_BAD_TUPLE;
661 entry->flags |= (*p << 16);
664 if (++p == q) return CS_BAD_TUPLE;
668 entry->subtuples = q-p;
673 /*====================================================================*/
675 static int parse_device_geo(tuple_t *tuple, cistpl_device_geo_t *geo)
680 p = (u_char *)tuple->TupleData;
681 q = p + tuple->TupleDataLen;
683 for (n = 0; n < CISTPL_MAX_DEVICES; n++) {
685 geo->geo[n].buswidth = p[0];
686 geo->geo[n].erase_block = 1 << (p[1]-1);
687 geo->geo[n].read_block = 1 << (p[2]-1);
688 geo->geo[n].write_block = 1 << (p[3]-1);
689 geo->geo[n].partition = 1 << (p[4]-1);
690 geo->geo[n].interleave = 1 << (p[5]-1);
697 /*====================================================================*/
699 static int parse_vers_2(tuple_t *tuple, cistpl_vers_2_t *v2)
703 if (tuple->TupleDataLen < 10)
706 p = tuple->TupleData;
707 q = p + tuple->TupleDataLen;
711 v2->dindex = le16_to_cpu(*(u_short *)(p+2));
716 return parse_strings(p, q, 2, v2->str, &v2->vendor, NULL);
719 /*====================================================================*/
721 static int parse_org(tuple_t *tuple, cistpl_org_t *org)
726 p = tuple->TupleData;
727 q = p + tuple->TupleDataLen;
728 if (p == q) return CS_BAD_TUPLE;
730 if (++p == q) return CS_BAD_TUPLE;
731 for (i = 0; i < 30; i++) {
733 if (*p == '\0') break;
734 if (++p == q) return CS_BAD_TUPLE;
739 /*====================================================================*/
741 static int parse_format(tuple_t *tuple, cistpl_format_t *fmt)
745 if (tuple->TupleDataLen < 10)
748 p = tuple->TupleData;
752 fmt->offset = le32_to_cpu(*(u_int *)(p+2));
753 fmt->length = le32_to_cpu(*(u_int *)(p+6));
758 /*====================================================================*/
760 int parse_tuple(tuple_t *tuple, cisparse_t *parse)
762 int ret = CS_SUCCESS;
764 if (tuple->TupleDataLen > tuple->TupleDataMax)
766 switch (tuple->TupleCode) {
768 case CISTPL_DEVICE_A:
769 ret = parse_device(tuple, &parse->device);
772 ret = parse_bar(tuple, &parse->bar);
774 case CISTPL_CONFIG_CB:
775 ret = parse_config_cb(tuple, &parse->config);
777 case CISTPL_CFTABLE_ENTRY_CB:
778 ret = parse_cftable_entry_cb(tuple, &parse->cftable_entry_cb);
780 case CISTPL_CHECKSUM:
781 ret = parse_checksum(tuple, &parse->checksum);
783 case CISTPL_LONGLINK_A:
784 case CISTPL_LONGLINK_C:
785 ret = parse_longlink(tuple, &parse->longlink);
787 case CISTPL_LONGLINK_MFC:
788 ret = parse_longlink_mfc(tuple, &parse->longlink_mfc);
791 ret = parse_vers_1(tuple, &parse->version_1);
794 ret = parse_altstr(tuple, &parse->altstr);
798 ret = parse_jedec(tuple, &parse->jedec);
801 ret = parse_manfid(tuple, &parse->manfid);
804 ret = parse_funcid(tuple, &parse->funcid);
807 ret = parse_funce(tuple, &parse->funce);
810 ret = parse_config(tuple, &parse->config);
812 case CISTPL_CFTABLE_ENTRY:
813 ret = parse_cftable_entry(tuple, &parse->cftable_entry);
815 case CISTPL_DEVICE_GEO:
816 case CISTPL_DEVICE_GEO_A:
817 ret = parse_device_geo(tuple, &parse->device_geo);
820 ret = parse_vers_2(tuple, &parse->vers_2);
823 ret = parse_org(tuple, &parse->org);
826 case CISTPL_FORMAT_A:
827 ret = parse_format(tuple, &parse->format);
830 case CISTPL_LINKTARGET:
834 ret = CS_UNSUPPORTED_FUNCTION;