printcis.c revision 15175
1/*
2 *	dump CIS tuples.
3 */
4#include <stdio.h>
5#include <unistd.h>
6#include <stdlib.h>
7#include <string.h>
8#include <sys/ioctl.h>
9
10#include <pccard/card.h>
11#include <pccard/cis.h>
12
13#include "readcis.h"
14
15int     dump_pwr_desc(unsigned char *);
16void    print_ext_speed(unsigned char, int);
17void    dump_device_desc(unsigned char *p, int len, char *type);
18void    dump_info_v1(unsigned char *p, int len);
19void    dump_config_map(struct tuple *tp);
20void    dump_cis_config(struct tuple *tp);
21void    dump_other_cond(unsigned char *p);
22void    dump_func_ext(unsigned char *p, int len);
23
24void
25dumpcis(struct cis *cp)
26{
27	struct tuple *tp;
28	struct tuple_list *tl;
29	int     count = 0, sz, ad, i;
30	unsigned char *p;
31
32	for (tl = cp->tlist; tl; tl = tl->next)
33		for (tp = tl->tuples; tp; tp = tp->next) {
34			printf("Tuple #%d, code = 0x%x (%s), length = %d\n",
35			    ++count, tp->code, tuple_name(tp->code), tp->length);
36			p = tp->data;
37			sz = tp->length;
38			ad = 0;
39			while (sz > 0) {
40				printf("    %03x: ", ad);
41				for (i = 0; i < ((sz < 16) ? sz : 16); i++)
42					printf(" %02x", p[i]);
43				printf("\n");
44				sz -= 16;
45				p += 16;
46				ad += 16;
47			}
48			switch (tp->code) {
49			default:
50				break;
51			case CIS_MEM_COMMON:	/* 0x01 */
52				dump_device_desc(tp->data, tp->length, "Common");
53				break;
54			case CIS_CHECKSUM:	/* 0x10 */
55				if (tp->length == 5) {
56					printf("\tChecksum from offset %d, length %d, value is 0x%x\n",
57					    (short)((tp->data[1] << 8) | tp->data[0]),
58					    (tp->data[3] << 8) | tp->data[2],
59					    tp->data[4]);
60				} else
61					printf("\tIllegal length for checksum!\n");
62				break;
63			case CIS_LONGLINK_A:	/* 0x11 */
64				printf("\tLong link to attribute memory, address 0x%x\n",
65				    (tp->data[3] << 24) |
66				    (tp->data[2] << 16) |
67				    (tp->data[1] << 8)  |
68				    tp->data[0]);
69				break;
70			case CIS_LONGLINK_C:	/* 0x12 */
71				printf("\tLong link to common memory, address 0x%x\n",
72				    (tp->data[3] << 24) |
73				    (tp->data[2] << 16) |
74				    (tp->data[1] << 8)  |
75				    tp->data[0]);
76				break;
77				break;
78			case CIS_INFO_V1:	/* 0x15 */
79				dump_info_v1(tp->data, tp->length);
80				break;
81			case CIS_ALTSTR:	/* 0x16 */
82				break;
83			case CIS_MEM_ATTR:	/* 0x17 */
84				dump_device_desc(tp->data, tp->length, "Attribute");
85				break;
86			case CIS_JEDEC_C:	/* 0x18 */
87				break;
88			case CIS_JEDEC_A:	/* 0x19 */
89				break;
90			case CIS_CONF_MAP:	/* 0x1A */
91				dump_config_map(tp);
92				break;
93			case CIS_CONFIG:	/* 0x1B */
94				dump_cis_config(tp);
95				break;
96			case CIS_DEVICE_OC:	/* 0x1C */
97				dump_other_cond(tp->data);
98				break;
99			case CIS_DEVICE_OA:	/* 0x1D */
100				dump_other_cond(tp->data);
101				break;
102			case CIS_DEVICEGEO:	/* 0x1E */
103				break;
104			case CIS_DEVICEGEO_A:	/* 0x1F */
105				break;
106			case CIS_MANUF_ID:	/* 0x20 */
107				printf("\tPCMCIA ID = 0x%x, OEM ID = 0x%x\n",
108				    (tp->data[1] << 8) | tp->data[0],
109				    (tp->data[3] << 8) | tp->data[2]);
110				break;
111			case CIS_FUNC_ID:	/* 0x21 */
112				switch (tp->data[0]) {
113				default:
114					printf("\tUnknown function");
115					break;
116				case 0:
117					printf("\tMultifunction card");
118					break;
119				case 1:
120					printf("\tMemory card");
121					break;
122				case 2:
123					printf("\tSerial port/modem");
124					break;
125				case 3:
126					printf("\tParallel port");
127					break;
128				case 4:
129					printf("\tFixed disk card");
130					break;
131				case 5:
132					printf("\tVideo adapter");
133					break;
134				case 6:
135					printf("\tNetwork/LAN adapter");
136					break;
137				case 7:
138					printf("\tAIMS");
139					break;
140				}
141				printf("%s%s\n", (tp->data[1] & 1) ? " - POST initialize" : "",
142				    (tp->data[1] & 2) ? " - Card has ROM" : "");
143				break;
144			case CIS_FUNC_EXT:	/* 0x22 */
145				dump_func_ext(tp->data, tp->length);
146				break;
147			case CIS_VERS_2:	/* 0x40 */
148				break;
149			}
150		}
151}
152
153/*
154 *	Dump configuration map tuple.
155 */
156void
157dump_config_map(struct tuple *tp)
158{
159	unsigned char *p, x;
160	int     rlen, mlen;
161	int     i;
162	union {
163		unsigned long l;
164		unsigned char b[4];
165	} u;
166
167	rlen = (tp->data[0] & 3) + 1;
168	mlen = ((tp->data[0] >> 2) & 3) + 1;
169	u.l = 0;
170	p = tp->data + 2;
171	for (i = 0; i < rlen; i++)
172		u.b[i] = *p++;
173	printf("\tReg len = %d, config register addr = 0x%lx, last config = 0x%x\n",
174	    rlen, u.l, tp->data[1]);
175	if (mlen)
176		printf("\tRegisters: ");
177	for (i = 0; i < mlen; i++, p++) {
178		for (x = 0x1; x; x <<= 1)
179			printf("%c", x & *p ? 'X' : '-');
180		printf(" ");
181	}
182	printf("\n");
183}
184
185/*
186 *	Dump a config entry.
187 */
188void
189dump_cis_config(struct tuple *tp)
190{
191	unsigned char *p, feat;
192	int     i, j;
193	char    c;
194
195	p = tp->data;
196	printf("\tConfig index = 0x%x%s\n", *p & 0x3F,
197	    *p & 0x40 ? "(default)" : "");
198	if (*p & 0x80) {
199		p++;
200		printf("\tInterface byte = 0x%x ", *p);
201		switch (*p & 0xF) {
202		default:
203			printf("(reserved)");
204			break;
205		case 0:
206			printf("(memory)");
207			break;
208		case 1:
209			printf("(I/O)");
210			break;
211		case 4:
212		case 5:
213		case 6:
214		case 7:
215		case 8:
216			printf("(custom)");
217			break;
218		}
219		c = ' ';
220		if (*p & 0x10) {
221			printf(" BVD1/2 active");
222			c = ',';
223		}
224		if (*p & 0x20) {
225			printf("%c card WP active", c);	/* Write protect */
226			c = ',';
227		}
228		if (*p & 0x40) {
229			printf("%c +RDY/-BSY active", c);
230			c = ',';
231		}
232		if (*p & 0x80)
233			printf("%c wait signal supported", c);
234		printf("\n");
235	}
236	p++;
237	feat = *p++;
238	switch (feat & 3) {
239	case 0:
240		break;
241	case 1:
242		printf("\tVcc pwr:\n");
243		p += dump_pwr_desc(p);
244		break;
245	case 2:
246		printf("\tVcc pwr:\n");
247		p += dump_pwr_desc(p);
248		printf("\tVpp pwr:\n");
249		p += dump_pwr_desc(p);
250		break;
251	case 3:
252		printf("\tVcc pwr:\n");
253		p += dump_pwr_desc(p);
254		printf("\tVpp1 pwr:\n");
255		p += dump_pwr_desc(p);
256		printf("\tVpp2 pwr:\n");
257		p += dump_pwr_desc(p);
258		break;
259	}
260	if (feat & 0x4) {
261		i = *p & 3;
262		j = (*p >> 2) & 7;
263		p++;
264		if (i != 3) {
265			printf("\tWait scale ");
266			print_ext_speed(*p, i);
267			while (*p & 0x80)
268				p++;
269			printf("\n");
270		}
271		if (j != 7) {
272			printf("\tRDY/BSY scale ");
273			print_ext_speed(*p, j);
274			while (*p & 0x80)
275				p++;
276			printf("\n");
277		}
278	}
279	if (feat & 0x8) {
280		if (*p & 0x1F)
281			printf("\tCard decodes %d address lines", *p & 0x1F);
282		else
283			printf("\tCard provides address decode");
284		switch ((*p >> 5) & 3) {
285		case 0:
286			break;
287		case 1:
288			printf(", 8 Bit I/O only");
289			break;
290		case 2:
291			printf(", limited 8/16 Bit I/O");
292			break;
293		case 3:
294			printf(", full 8/16 Bit I/O");
295			break;
296		}
297		printf("\n");
298		if (*p & 0x80) {
299			p++;
300			c = *p++;
301			for (i = 0; i <= (c & 0xF); i++) {
302				printf("\t\tI/O address # %d: ", i + 1);
303				switch ((c >> 4) & 3) {
304				case 0:
305					break;
306				case 1:
307					printf("block start = 0x%x", *p++);
308					break;
309				case 2:
310					printf("block start = 0x%x", (p[1] << 8) | *p);
311					p += 2;
312					break;
313				case 3:
314					printf("block start = 0x%x",
315					    (p[3] << 24) | (p[2] << 16) |
316					    (p[1] << 8) | *p);
317					p += 4;
318					break;
319				}
320				switch ((c >> 6) & 3) {
321				case 0:
322					break;
323				case 1:
324					printf(" block length = 0x%x", *p++ + 1);
325					break;
326				case 2:
327					printf(" block length = 0x%x", ((p[1] << 8) | *p) + 1);
328					p += 2;
329					break;
330				case 3:
331					printf(" block length = 0x%x",
332					    ((p[3] << 24) | (p[2] << 16) |
333						(p[1] << 8) | *p) + 1);
334					p += 4;
335					break;
336				}
337				printf("\n");
338			}
339		}
340	}
341
342	/* IRQ descriptor */
343	if (feat & 0x10) {
344		printf("\t\tIRQ modes:");
345		c = ' ';
346		if (*p & 0x20) {
347			printf(" Level");
348			c = ',';
349		}
350		if (*p & 0x40) {
351			printf("%c Pulse", c);
352			c = ',';
353		}
354		if (*p & 0x80)
355			printf("%c Shared", c);
356		printf("\n");
357		if (*p & 0x10) {
358			i = p[0] | (p[1] << 8);
359			printf("\t\tIRQs: ");
360			if (*p & 1)
361				printf(" NMI");
362			if (*p & 0x2)
363				printf(" IOCK");
364			if (*p & 0x4)
365				printf(" BERR");
366			if (*p & 0x8)
367				printf(" VEND");
368			for (j = 0; j < 16; j++)
369				if (i & (1 << j))
370					printf(" %d", j);
371			printf("\n");
372			p += 3;
373		} else {
374			printf("\t\tIRQ level = %d\n", *p & 0xF);
375			p++;
376		}
377	}
378	switch ((feat >> 5) & 3) {
379	case 0:
380		break;
381	case 1:
382		printf("\tMemory space length = 0x%x\n", (p[1] << 8) | p[0]);
383		p += 2;
384		break;
385	case 2:
386		printf("\tMemory space address = 0x%x, length = 0x%x\n",
387		    (p[3] << 8) | p[2],
388		    (p[1] << 8) | p[0]);
389		p += 4;
390		break;
391
392	/* Memory descriptors. */
393	case 3:
394		c = *p++;
395		for (i = 0; i <= (c & 7); i++) {
396			printf("\tMemory descriptor %d\n\t\t", i + 1);
397			switch ((c >> 3) & 3) {
398			case 0:
399				break;
400			case 1:
401				printf(" blk length = 0x%x00", *p++);
402				break;
403			case 2:
404				printf(" blk length = 0x%x00", (p[1] << 8) | *p);
405				p += 2;
406				break;
407			case 3:
408				printf(" blk length = 0x%x00",
409				    (p[3] << 24) | (p[2] << 16) |
410				    (p[1] << 8) | *p);
411				p += 4;
412				break;
413			}
414			switch ((c >> 5) & 3) {
415			case 0:
416				break;
417			case 1:
418				printf(" card addr = 0x%x00", *p++);
419				break;
420			case 2:
421				printf(" card addr = 0x%x00", (p[1] << 8) | *p);
422				p += 2;
423				break;
424			case 3:
425				printf(" card addr = 0x%x00",
426				    (p[3] << 24) | (p[2] << 16) |
427				    (p[1] << 8) | *p);
428				p += 4;
429				break;
430			}
431			if (c & 0x80)
432				switch ((c >> 5) & 3) {
433				case 0:
434					break;
435				case 1:
436					printf(" host addr = 0x%x00", *p++);
437					break;
438				case 2:
439					printf(" host addr = 0x%x00", (p[1] << 8) | *p);
440					p += 2;
441					break;
442				case 3:
443					printf(" host addr = 0x%x00",
444					    (p[3] << 24) | (p[2] << 16) |
445					    (p[1] << 8) | *p);
446					p += 4;
447					break;
448				}
449			printf("\n");
450		}
451		break;
452	}
453	if (feat & 0x80) {
454		printf("\tMax twin cards = %d\n", *p & 7);
455		printf("\tMisc attr:");
456		if (*p & 0x8)
457			printf(" (Audio-BVD2)");
458		if (*p & 0x10)
459			printf(" (Read-only)");
460		if (*p & 0x20)
461			printf(" (Power down supported)");
462		if (*p & 0x80) {
463			printf(" (Ext byte = 0x%x)", p[1]);
464			p++;
465		}
466		printf("\n");
467		p++;
468	}
469}
470
471/*
472 *	dump_other_cond - Dump other conditions.
473 */
474void
475dump_other_cond(unsigned char *p)
476{
477	if (p[0]) {
478		printf("\t");
479		if (p[0] & 1)
480			printf("(MWAIT)");
481		if (p[0] & 2)
482			printf(" (3V card)");
483		if (p[0] & 0x80)
484			printf(" (Extension bytes follow)");
485		printf("\n");
486	}
487}
488
489/*
490 *	Dump power descriptor.
491 */
492int
493dump_pwr_desc(unsigned char *p)
494{
495	int     len = 1, i;
496	unsigned char mask;
497	char  **expp;
498	static char *pname[] =
499	{"Nominal operating supply voltage",
500	 "Minimum operating supply voltage",
501	 "Maximum operating supply voltage",
502	 "Continuous supply current",
503	 "Max current average over 1 second",
504	 "Max current average over 10 ms",
505	 "Power down supply current",
506	 "Reserved"
507	};
508	static char *vexp[] =
509	{"10uV", "100uV", "1mV", "10mV", "100mV", "1V", "10V", "100V"};
510	static char *cexp[] =
511	{"10nA", "1uA", "10uA", "100uA", "1mA", "10mA", "100mA", "1A"};
512	static char *mant[] =
513	{"1", "1.2", "1.3", "1.5", "2", "2.5", "3", "3.5", "4", "4.5",
514	"5", "5.5", "6", "7", "8", "9"};
515
516	mask = *p++;
517	expp = vexp;
518	for (i = 0; i < 8; i++)
519		if (mask & (1 << i)) {
520			len++;
521			if (i >= 3)
522				expp = cexp;
523			printf("\t\t%s: ", pname[i]);
524			printf("%s x %s",
525			    mant[(*p >> 3) & 0xF],
526			    expp[*p & 7]);
527			while (*p & 0x80) {
528				len++;
529				p++;
530				printf(", ext = 0x%x", *p);
531			}
532			printf("\n");
533			p++;
534		}
535	return (len);
536}
537
538void
539dump_device_desc(unsigned char *p, int len, char *type)
540{
541	static char *un_name[] =
542	{"512b", "2Kb", "8Kb", "32Kb", "128Kb", "512Kb", "2Mb", "reserved"};
543	static char *speed[] =
544	{"No speed", "250nS", "200nS", "150nS",
545	"100nS", "Reserved", "Reserved"};
546	static char *dev[] =
547	{"No device", "Mask ROM", "OTPROM", "UV EPROM",
548	 "EEPROM", "FLASH EEPROM", "SRAM", "DRAM",
549	 "Reserved", "Reserved", "Reserved", "Reserved",
550	 "Reserved", "Function specific", "Extended",
551	"Reserved"};
552	int     count = 0;
553
554	while (*p != 0xFF && len > 0) {
555		unsigned char x;
556
557		x = *p++;
558		len -= 2;
559		if (count++ == 0)
560			printf("\t%s memory device information:\n", type);
561		printf("\t\tDevice number %d, type %s, WPS = %s\n",
562		    count, dev[x >> 4], (x & 0x8) ? "ON" : "OFF");
563		if ((x & 7) == 7) {
564			len--;
565			if (*p) {
566				printf("\t\t");
567				print_ext_speed(*p, 0);
568				while (*p & 0x80) {
569					p++;
570					len--;
571				}
572			}
573			p++;
574		} else
575			printf("\t\tSpeed = %s", speed[x & 7]);
576		printf(", Memory block size = %s, %d units\n",
577		    un_name[*p & 7], (*p >> 3) + 1);
578		p++;
579	}
580}
581
582/*
583 *	Print version info
584 */
585void
586dump_info_v1(unsigned char *p, int len)
587{
588	printf("\tVersion = %d.%d", p[0], p[1]);
589	p += 2;
590	printf(", Manuf = [%s],", p);
591	while (*p++);
592	printf("card vers = [%s]\n", p);
593	while (*p++);
594	printf("\tAddit. info = [%s]", p);
595	while (*p++);
596	printf(",[%s]\n", p);
597}
598
599/*
600 *	dump functional extension tuple.
601 */
602void
603dump_func_ext(unsigned char *p, int len)
604{
605	if (len == 0)
606		return;
607	switch (p[0]) {
608	case 0:
609	case 8:
610	case 10:
611		if (len != 4) {
612			printf("\tWrong length for serial extension\n");
613			return;
614		}
615		printf("\tSerial interface extension:\n");
616		switch (p[1] & 0x1F) {
617		default:
618			printf("\t\tUnkn device");
619			break;
620		case 0:
621			printf("\t\t8250 UART");
622			break;
623		case 1:
624			printf("\t\t16450 UART");
625			break;
626		case 2:
627			printf("\t\t16550 UART");
628			break;
629		}
630		printf(", Parity - %s%s%s%s",
631		    (p[2] & 1) ? "Space," : "",
632		    (p[2] & 2) ? "Mark," : "",
633		    (p[2] & 4) ? "Odd," : "",
634		    (p[2] & 8) ? "Even," : "");
635		printf("\n");
636		break;
637	case 1:
638	case 5:
639	case 6:
640	case 7:
641		printf("\tModem interface capabilities:\n");
642		break;
643	case 2:
644		printf("\tData modem services available:\n");
645		break;
646	case 9:
647		printf("\tFax/modem services available:\n");
648		break;
649	case 4:
650		printf("\tVoice services available:\n");
651		break;
652	}
653}
654
655/*
656 *	print_ext_speed - Print extended speed.
657 */
658void
659print_ext_speed(unsigned char x, int scale)
660{
661	static char *mant[] =
662	{"Reserved", "1.0", "1.2", "1.3", "1.5", "2.0", "2.5", "3.0",
663	"3.5", "4.0", "4.5", "5.0", "5.5", "6.0", "7.0", "8.0"};
664	static char *exp[] =
665	{"1 ns", "10 ns", "100 ns", "1 us", "10 us", "100 us",
666	"1 ms", "10 ms"};
667	static char *scale_name[] =
668	{"None", "10", "100", "1,000", "10,000", "100,000",
669	"1,000,000", "10,000,000"};
670
671	printf("Speed = %s x %s", mant[(x >> 3) & 0xF], exp[x & 7]);
672	if (scale)
673		printf(", scaled by %s", scale_name[scale & 7]);
674}
675