xref: /haiku/src/bin/pcmcia-cs/dump_cis.c (revision bc3955fea5b07e2e94a27fc05e4bb58fe6f0319b)
1 /*======================================================================
2 
3     PC Card CIS dump utility
4 
5     dump_cis.c 1.63 2001/11/30 23:10:17
6 
7     The contents of this file are subject to the Mozilla Public
8     License Version 1.1 (the "License"); you may not use this file
9     except in compliance with the License. You may obtain a copy of
10     the License at http://www.mozilla.org/MPL/
11 
12     Software distributed under the License is distributed on an "AS
13     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14     implied. See the License for the specific language governing
15     rights and limitations under the License.
16 
17     The initial developer of the original code is David A. Hinds
18     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
19     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
20 
21     Alternatively, the contents of this file may be used under the
22     terms of the GNU General Public License version 2 (the "GPL"), in
23     which case the provisions of the GPL are applicable instead of the
24     above.  If you wish to allow the use of your version of this file
25     only under the terms of the GPL and not to allow others to use
26     your version of this file under the MPL, indicate your decision
27     by deleting the provisions above and replace them with the notice
28     and other provisions required by the GPL.  If you do not delete
29     the provisions above, a recipient may use your version of this
30     file under either the MPL or the GPL.
31 
32 ======================================================================*/
33 #if (defined(__BEOS__) || defined(__HAIKU__))
34 #include <OS.h>
35 #endif
36 #include <sys/types.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
41 #include <fcntl.h>
42 #include <errno.h>
43 #include <sys/time.h>
44 #include <sys/ioctl.h>
45 #include <sys/stat.h>
46 
47 #include <pcmcia/cs_types.h>
48 #include <pcmcia/cs.h>
49 #include <pcmcia/cistpl.h>
50 #include <pcmcia/ds.h>
51 
52 static int verbose = 0;
53 static char indent[10] = "  ";
54 
55 /*====================================================================*/
56 #if (!defined(__BEOS__) && !defined(__HAIKU__))
57 static int major = 0;
58 
lookup_dev(char * name)59 static int lookup_dev(char *name)
60 {
61     FILE *f;
62     int n;
63     char s[32], t[32];
64 
65     f = fopen("/proc/devices", "r");
66     if (f == NULL)
67 	return -1;
68     while (fgets(s, 32, f) != NULL) {
69 	if (sscanf(s, "%d %s", &n, t) == 2)
70 	    if (strcmp(name, t) == 0)
71 		break;
72     }
73     fclose(f);
74     if (strcmp(name, t) == 0)
75 	return n;
76     else
77 	return -1;
78 }
79 #endif
80 /*====================================================================*/
81 
open_sock(int sock)82 static int open_sock(int sock)
83 {
84 #if (defined(__BEOS__) || defined(__HAIKU__))
85     char fn[B_OS_NAME_LENGTH];
86     sprintf(fn, "/dev/bus/pcmcia/sock/%d", sock);
87     return open(fn, O_RDONLY);
88 #else
89     static char *paths[] = {
90 	"/var/lib/pcmcia", "/var/run", "/dev", "/tmp", NULL
91     };
92     int fd;
93     char **p, fn[64];
94     dev_t dev = (major<<8) + sock;
95 
96     for (p = paths; *p; p++) {
97 	sprintf(fn, "%s/dc%d", *p, getpid());
98 	if (mknod(fn, (S_IFCHR|S_IREAD|S_IWRITE), dev) == 0) {
99 	    fd = open(fn, O_RDONLY);
100 	    unlink(fn);
101 	    if (fd >= 0)
102 		return fd;
103 	    if (errno == ENODEV) break;
104 	}
105     }
106     return -1;
107 #endif
108 } /* open_sock */
109 
110 /*====================================================================*/
111 
print_tuple(tuple_parse_t * tup)112 static void print_tuple(tuple_parse_t *tup)
113 {
114     int i;
115     printf("%soffset 0x%2.2x, tuple 0x%2.2x, link 0x%2.2x\n",
116 	   indent, tup->tuple.CISOffset, tup->tuple.TupleCode,
117 	   tup->tuple.TupleLink);
118     for (i = 0; i < tup->tuple.TupleDataLen; i++) {
119 	if ((i % 16) == 0) printf("%s  ", indent);
120 	printf("%2.2x ", (u_char)tup->data[i]);
121 	if ((i % 16) == 15) putchar('\n');
122     }
123     if ((i % 16) != 0) putchar('\n');
124 }
125 
126 /*====================================================================*/
127 
print_funcid(cistpl_funcid_t * fn)128 static void print_funcid(cistpl_funcid_t *fn)
129 {
130     printf("%sfuncid ", indent);
131     switch (fn->func) {
132     case CISTPL_FUNCID_MULTI:
133 	printf("multi_function"); break;
134     case CISTPL_FUNCID_MEMORY:
135 	printf("memory_card"); break;
136     case CISTPL_FUNCID_SERIAL:
137 	printf("serial_port"); break;
138     case CISTPL_FUNCID_PARALLEL:
139 	printf("parallel_port"); break;
140     case CISTPL_FUNCID_FIXED:
141 	printf("fixed_disk"); break;
142     case CISTPL_FUNCID_VIDEO:
143 	printf("video_adapter"); break;
144     case CISTPL_FUNCID_NETWORK:
145 	printf("network_adapter"); break;
146     case CISTPL_FUNCID_AIMS:
147 	printf("aims_card"); break;
148     case CISTPL_FUNCID_SCSI:
149 	printf("scsi_adapter"); break;
150     default:
151 	printf("unknown"); break;
152     }
153     if (fn->sysinit & CISTPL_SYSINIT_POST)
154 	printf(" [post]");
155     if (fn->sysinit & CISTPL_SYSINIT_ROM)
156 	printf(" [rom]");
157     putchar('\n');
158 }
159 
160 /*====================================================================*/
161 
print_size(u_int size)162 static void print_size(u_int size)
163 {
164     if (size < 1024)
165 	printf("%ub", size);
166     else if (size < 1024*1024)
167 	printf("%ukb", size/1024);
168     else
169 	printf("%umb", size/(1024*1024));
170 }
171 
print_unit(u_int v,char * unit,char tag)172 static void print_unit(u_int v, char *unit, char tag)
173 {
174     int n;
175     for (n = 0; (v % 1000) == 0; n++) v /= 1000;
176     printf("%u", v);
177     if (n < strlen(unit)) putchar(unit[n]);
178     putchar(tag);
179 }
180 
print_time(u_int tm,u_long scale)181 static void print_time(u_int tm, u_long scale)
182 {
183     print_unit(tm * scale, "num", 's');
184 }
185 
print_volt(u_int vi)186 static void print_volt(u_int vi)
187 {
188     print_unit(vi * 10, "um", 'V');
189 }
190 
print_current(u_int ii)191 static void print_current(u_int ii)
192 {
193     print_unit(ii / 10, "um", 'A');
194 }
195 
print_speed(u_int b)196 static void print_speed(u_int b)
197 {
198     if (b < 1000)
199 	printf("%u bits/sec", b);
200     else if (b < 1000000)
201 	printf("%u kb/sec", b/1000);
202     else
203 	printf("%u mb/sec", b/1000000);
204 }
205 
206 /*====================================================================*/
207 
208 static const char *dtype[] = {
209     "NULL", "ROM", "OTPROM", "EPROM", "EEPROM", "FLASH", "SRAM",
210     "DRAM", "rsvd", "rsvd", "rsvd", "rsvd", "rsvd", "fn_specific",
211     "extended", "rsvd"
212 };
213 
print_device(cistpl_device_t * dev)214 static void print_device(cistpl_device_t *dev)
215 {
216     int i;
217     for (i = 0; i < dev->ndev; i++) {
218 	printf("%s  %s ", indent, dtype[dev->dev[i].type]);
219 	printf("%uns, ", dev->dev[i].speed);
220 	print_size(dev->dev[i].size);
221 	putchar('\n');
222     }
223     if (dev->ndev == 0)
224 	printf("%s  no_info\n", indent);
225 }
226 
227 /*====================================================================*/
228 
print_power(char * tag,cistpl_power_t * power)229 static void print_power(char *tag, cistpl_power_t *power)
230 {
231     int i, n;
232     for (i = n = 0; i < 8; i++)
233 	if (power->present & (1<<i)) n++;
234     i = 0;
235     printf("%s  %s", indent, tag);
236     if (power->present & (1<<CISTPL_POWER_VNOM)) {
237 	printf(" Vnom "); i++;
238 	print_volt(power->param[CISTPL_POWER_VNOM]);
239     }
240     if (power->present & (1<<CISTPL_POWER_VMIN)) {
241 	printf(" Vmin "); i++;
242 	print_volt(power->param[CISTPL_POWER_VMIN]);
243     }
244     if (power->present & (1<<CISTPL_POWER_VMAX)) {
245  	printf(" Vmax "); i++;
246 	print_volt(power->param[CISTPL_POWER_VMAX]);
247     }
248     if (power->present & (1<<CISTPL_POWER_ISTATIC)) {
249 	printf(" Istatic "); i++;
250 	print_current(power->param[CISTPL_POWER_ISTATIC]);
251     }
252     if (power->present & (1<<CISTPL_POWER_IAVG)) {
253 	if (++i == 5) printf("\n%s   ", indent);
254 	printf(" Iavg ");
255 	print_current(power->param[CISTPL_POWER_IAVG]);
256     }
257     if (power->present & (1<<CISTPL_POWER_IPEAK)) {
258 	if (++i == 5) printf("\n%s ", indent);
259 	printf(" Ipeak ");
260 	print_current(power->param[CISTPL_POWER_IPEAK]);
261     }
262     if (power->present & (1<<CISTPL_POWER_IDOWN)) {
263 	if (++i == 5) printf("\n%s ", indent);
264 	printf(" Idown ");
265 	print_current(power->param[CISTPL_POWER_IDOWN]);
266     }
267     if (power->flags & CISTPL_POWER_HIGHZ_OK) {
268 	if (++i == 5) printf("\n%s ", indent);
269 	printf(" [highz OK]");
270     }
271     if (power->flags & CISTPL_POWER_HIGHZ_REQ) {
272 	printf(" [highz]");
273     }
274     putchar('\n');
275 }
276 
277 /*====================================================================*/
278 
print_cftable_entry(cistpl_cftable_entry_t * entry)279 static void print_cftable_entry(cistpl_cftable_entry_t *entry)
280 {
281     int i;
282 
283     printf("%scftable_entry 0x%2.2x%s\n", indent, entry->index,
284 	   (entry->flags & CISTPL_CFTABLE_DEFAULT) ? " [default]" : "");
285 
286     if (entry->flags & ~CISTPL_CFTABLE_DEFAULT) {
287 	printf("%s ", indent);
288 	if (entry->flags & CISTPL_CFTABLE_BVDS)
289 	    printf(" [bvd]");
290 	if (entry->flags & CISTPL_CFTABLE_WP)
291 	    printf(" [wp]");
292 	if (entry->flags & CISTPL_CFTABLE_RDYBSY)
293 	    printf(" [rdybsy]");
294 	if (entry->flags & CISTPL_CFTABLE_MWAIT)
295 	    printf(" [mwait]");
296 	if (entry->flags & CISTPL_CFTABLE_AUDIO)
297 	    printf(" [audio]");
298 	if (entry->flags & CISTPL_CFTABLE_READONLY)
299 	    printf(" [readonly]");
300 	if (entry->flags & CISTPL_CFTABLE_PWRDOWN)
301 	    printf(" [pwrdown]");
302 	putchar('\n');
303     }
304 
305     if (entry->vcc.present)
306 	print_power("Vcc", &entry->vcc);
307     if (entry->vpp1.present)
308 	print_power("Vpp1", &entry->vpp1);
309     if (entry->vpp2.present)
310 	print_power("Vpp2", &entry->vpp2);
311 
312     if ((entry->timing.wait != 0) || (entry->timing.ready != 0) ||
313 	(entry->timing.reserved != 0)) {
314 	printf("%s  timing", indent);
315 	if (entry->timing.wait != 0) {
316 	    printf(" wait ");
317 	    print_time(entry->timing.wait, entry->timing.waitscale);
318 	}
319 	if (entry->timing.ready != 0) {
320 	    printf(" ready ");
321 	    print_time(entry->timing.ready, entry->timing.rdyscale);
322 	}
323 	if (entry->timing.reserved != 0) {
324 	    printf(" reserved ");
325 	    print_time(entry->timing.reserved, entry->timing.rsvscale);
326 	}
327 	putchar('\n');
328     }
329 
330     if (entry->io.nwin) {
331 	cistpl_io_t *io = &entry->io;
332 	printf("%s  io", indent);
333 	for (i = 0; i < io->nwin; i++) {
334 	    if (i) putchar(',');
335 	    printf(" 0x%4.4x-0x%4.4x", io->win[i].base,
336 		   io->win[i].base+io->win[i].len-1);
337 	}
338 	printf(" [lines=%d]", io->flags & CISTPL_IO_LINES_MASK);
339 	if (io->flags & CISTPL_IO_8BIT) printf(" [8bit]");
340 	if (io->flags & CISTPL_IO_16BIT) printf(" [16bit]");
341 	if (io->flags & CISTPL_IO_RANGE) printf(" [range]");
342 	putchar('\n');
343     }
344 
345     if (entry->irq.IRQInfo1) {
346 	printf("%s  irq ", indent);
347 	if (entry->irq.IRQInfo1 & IRQ_INFO2_VALID)
348 	    printf("mask 0x%04x", entry->irq.IRQInfo2);
349 	else
350 	    printf("%u", entry->irq.IRQInfo1 & IRQ_MASK);
351 	if (entry->irq.IRQInfo1 & IRQ_LEVEL_ID) printf(" [level]");
352 	if (entry->irq.IRQInfo1 & IRQ_PULSE_ID) printf(" [pulse]");
353 	if (entry->irq.IRQInfo1 & IRQ_SHARE_ID) printf(" [shared]");
354 	putchar('\n');
355     }
356 
357     if (entry->mem.nwin) {
358 	cistpl_mem_t *mem = &entry->mem;
359 	printf("%s  memory", indent);
360 	for (i = 0; i < mem->nwin; i++) {
361 	    if (i) putchar(',');
362 	    printf(" 0x%4.4x-0x%4.4x @ 0x%4.4x", mem->win[i].card_addr,
363 		   mem->win[i].card_addr + mem->win[i].len-1,
364 		   mem->win[i].host_addr);
365 	}
366 	putchar('\n');
367     }
368 
369     if (verbose && entry->subtuples)
370 	printf("%s  %d bytes in subtuples\n", indent, entry->subtuples);
371 
372 }
373 
374 /*====================================================================*/
375 
print_cftable_entry_cb(cistpl_cftable_entry_cb_t * entry)376 static void print_cftable_entry_cb(cistpl_cftable_entry_cb_t *entry)
377 {
378     int i;
379 
380     printf("%scftable_entry_cb 0x%2.2x%s\n", indent, entry->index,
381 	   (entry->flags & CISTPL_CFTABLE_DEFAULT) ? " [default]" : "");
382 
383     if (entry->flags & ~CISTPL_CFTABLE_DEFAULT) {
384 	printf("%s ", indent);
385 	if (entry->flags & CISTPL_CFTABLE_MASTER)
386 	    printf(" [master]");
387 	if (entry->flags & CISTPL_CFTABLE_INVALIDATE)
388 	    printf(" [invalidate]");
389 	if (entry->flags & CISTPL_CFTABLE_VGA_PALETTE)
390 	    printf(" [vga palette]");
391 	if (entry->flags & CISTPL_CFTABLE_PARITY)
392 	    printf(" [parity]");
393 	if (entry->flags & CISTPL_CFTABLE_WAIT)
394 	    printf(" [wait]");
395 	if (entry->flags & CISTPL_CFTABLE_SERR)
396 	    printf(" [serr]");
397 	if (entry->flags & CISTPL_CFTABLE_FAST_BACK)
398 	    printf(" [fast back]");
399 	if (entry->flags & CISTPL_CFTABLE_BINARY_AUDIO)
400 	    printf(" [binary audio]");
401 	if (entry->flags & CISTPL_CFTABLE_PWM_AUDIO)
402 	    printf(" [pwm audio]");
403 	putchar('\n');
404     }
405 
406     if (entry->vcc.present)
407 	print_power("Vcc", &entry->vcc);
408     if (entry->vpp1.present)
409 	print_power("Vpp1", &entry->vpp1);
410     if (entry->vpp2.present)
411 	print_power("Vpp2", &entry->vpp2);
412 
413     if (entry->io) {
414 	printf("%s  io_base", indent);
415 	for (i = 0; i < 8; i++)
416 	    if (entry->io & (1<<i)) printf(" %d", i);
417 	putchar('\n');
418     }
419 
420     if (entry->irq.IRQInfo1) {
421 	printf("%s  irq ", indent);
422 	if (entry->irq.IRQInfo1 & IRQ_INFO2_VALID)
423 	    printf("mask 0x%4.4x", entry->irq.IRQInfo2);
424 	else
425 	    printf("%u", entry->irq.IRQInfo1 & IRQ_MASK);
426 	if (entry->irq.IRQInfo1 & IRQ_LEVEL_ID) printf(" [level]");
427 	if (entry->irq.IRQInfo1 & IRQ_PULSE_ID) printf(" [pulse]");
428 	if (entry->irq.IRQInfo1 & IRQ_SHARE_ID) printf(" [shared]");
429 	putchar('\n');
430     }
431 
432     if (entry->mem) {
433 	printf("%s  mem_base", indent);
434 	for (i = 0; i < 8; i++)
435 	    if (entry->mem & (1<<i)) printf(" %d", i);
436 	putchar('\n');
437     }
438 
439     if (verbose && entry->subtuples)
440 	printf("%s  %d bytes in subtuples\n", indent,  entry->subtuples);
441 
442 }
443 
444 /*====================================================================*/
445 
print_jedec(cistpl_jedec_t * j)446 static void print_jedec(cistpl_jedec_t *j)
447 {
448     int i;
449     for (i = 0; i < j->nid; i++) {
450 	if (i != 0) putchar(',');
451 	printf(" 0x%02x 0x%02x", j->id[i].mfr, j->id[i].info);
452     }
453     putchar('\n');
454 }
455 
456 /*====================================================================*/
457 
print_device_geo(cistpl_device_geo_t * geo)458 static void print_device_geo(cistpl_device_geo_t *geo)
459 {
460     int i;
461     for (i = 0; i < geo->ngeo; i++) {
462 	printf("%s  width %d erase 0x%x read 0x%x write 0x%x "
463 	       "partition 0x%x interleave 0x%x\n", indent,
464 	       geo->geo[i].buswidth, geo->geo[i].erase_block,
465 	       geo->geo[i].read_block, geo->geo[i].write_block,
466 	       geo->geo[i].partition, geo->geo[i].interleave);
467     }
468 }
469 
470 /*====================================================================*/
471 
print_org(cistpl_org_t * org)472 static void print_org(cistpl_org_t *org)
473 {
474     printf("%sdata_org ", indent);
475     switch (org->data_org) {
476     case CISTPL_ORG_FS:
477 	printf("[filesystem]"); break;
478     case CISTPL_ORG_APPSPEC:
479 	printf("[app_specific]"); break;
480     case CISTPL_ORG_XIP:
481 	printf("[code]"); break;
482     default:
483 	if (org->data_org < 0x80)
484 	    printf("[reserved]");
485 	else
486 	    printf("[vendor_specific]");
487     }
488     printf(", \"%s\"\n", org->desc);
489 }
490 
491 /*====================================================================*/
492 
493 static char *data_mod[] = {
494     "Bell103", "V.21", "V.23", "V.22", "Bell212A", "V.22bis",
495     "V.26", "V.26bis", "V.27bis", "V.29", "V.32", "V.32bis",
496     "V.34", "rfu", "rfu", "rfu"
497 };
498 static char *fax_mod[] = {
499     "V.21-C2", "V.27ter", "V.29", "V.17", "V.33", "rfu", "rfu", "rfu"
500 };
501 static char *fax_features[] = {
502     "T.3", "T.4", "T.6", "error", "voice", "poll", "file", "passwd"
503 };
504 static char *cmd_protocol[] = {
505     "AT1", "AT2", "AT3", "MNP_AT", "V.25bis", "V.25A", "DMCL"
506 };
507 static char *uart[] = {
508     "8250", "16450", "16550", "8251", "8530", "85230"
509 };
510 static char *parity[] = { "space", "mark", "odd", "even" };
511 static char *stop[] = { "1", "1.5", "2" };
512 static char *flow[] = {
513     "XON/XOFF xmit", "XON/XOFF rcv", "hw xmit", "hw rcv", "transparent"
514 };
print_serial(cistpl_funce_t * funce)515 static void print_serial(cistpl_funce_t *funce)
516 {
517     cistpl_serial_t *s;
518     cistpl_data_serv_t *ds;
519     cistpl_fax_serv_t *fs;
520     cistpl_modem_cap_t *cp;
521     int i, j;
522 
523     switch (funce->type & 0x0f) {
524     case CISTPL_FUNCE_SERIAL_IF:
525     case CISTPL_FUNCE_SERIAL_IF_DATA:
526     case CISTPL_FUNCE_SERIAL_IF_FAX:
527     case CISTPL_FUNCE_SERIAL_IF_VOICE:
528 	s = (cistpl_serial_t *)(funce->data);
529 	printf("%sserial_interface", indent);
530 	if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_IF_DATA)
531 	    printf("_data");
532 	else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_IF_FAX)
533 	    printf("_fax");
534 	else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_IF_VOICE)
535 	    printf("_voice");
536 	printf("\n%s  uart %s", indent,
537 	       (s->uart_type < 6) ? uart[s->uart_type] : "reserved");
538 	if (s->uart_cap_0) {
539 	    printf(" [");
540 	    for (i = 0; i < 4; i++)
541 	        if (s->uart_cap_0 & (1<<i))
542 		    printf("%s%s", parity[i],
543 			   (s->uart_cap_0 >= (2<<i)) ? "/" : "]");
544 	}
545 	if (s->uart_cap_1) {
546 	    int m = s->uart_cap_1 & 0x0f;
547 	    int n = s->uart_cap_1 >> 4;
548 	    printf(" [");
549 	    for (i = 0; i < 4; i++)
550 		if (m & (1<<i))
551 		    printf("%d%s", i+5, (m >= (2<<i)) ? "/" : "");
552 	    printf("] [");
553 	    for (i = 0; i < 3; i++)
554 	        if (n & (1<<i))
555 		    printf("%s%s", stop[i], (n >= (2<<i)) ? "/" : "]");
556 	}
557 	printf("\n");
558 	break;
559     case CISTPL_FUNCE_SERIAL_CAP:
560     case CISTPL_FUNCE_SERIAL_CAP_DATA:
561     case CISTPL_FUNCE_SERIAL_CAP_FAX:
562     case CISTPL_FUNCE_SERIAL_CAP_VOICE:
563 	cp = (cistpl_modem_cap_t *)(funce->data);
564 	printf("%sserial_modem_cap", indent);
565 	if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_CAP_DATA)
566 	    printf("_data");
567 	else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_CAP_FAX)
568 	    printf("_fax");
569 	else if ((funce->type & 0x0f) == CISTPL_FUNCE_SERIAL_CAP_VOICE)
570 	    printf("_voice");
571 	if (cp->flow) {
572 	    printf("\n%s  flow", indent);
573 	    for (i = 0; i < 5; i++)
574 		if (cp->flow & (1<<i))
575 		    printf(" [%s]", flow[i]);
576 	}
577 	printf("\n%s  cmd_buf %d rcv_buf %d xmit_buf %d\n",
578 	       indent, 4*(cp->cmd_buf+1),
579 	       cp->rcv_buf_0+(cp->rcv_buf_1<<8)+(cp->rcv_buf_2<<16),
580 	       cp->xmit_buf_0+(cp->xmit_buf_1<<8)+(cp->xmit_buf_2<<16));
581 	break;
582     case CISTPL_FUNCE_SERIAL_SERV_DATA:
583 	ds = (cistpl_data_serv_t *)(funce->data);
584 	printf("%sserial_data_services\n", indent);
585 	printf("%s  data_rate %d\n", indent,
586 	       75*((ds->max_data_0<<8) + ds->max_data_1));
587 	printf("%s  modulation", indent);
588 	for (i = j = 0; i < 16; i++)
589 	    if (((ds->modulation_1<<8) + ds->modulation_0) & (1<<i)) {
590 		if (++j % 6 == 0)
591 		    printf("\n%s   ", indent);
592 		printf(" [%s]", data_mod[i]);
593 	    }
594 	printf("\n");
595 	if (ds->error_control) {
596 	    printf("%s  error_control", indent);
597 	    if (ds->error_control & CISTPL_SERIAL_ERR_MNP2_4)
598 		printf(" [MNP2-4]");
599 	    if (ds->error_control & CISTPL_SERIAL_ERR_V42_LAPM)
600 		printf(" [V.42/LAPM]");
601 	    printf("\n");
602 	}
603 	if (ds->compression) {
604 	    printf("%s  compression", indent);
605 	    if (ds->compression & CISTPL_SERIAL_CMPR_V42BIS)
606 		printf(" [V.42bis]");
607 	    if (ds->compression & CISTPL_SERIAL_CMPR_MNP5)
608 		printf(" [MNP5]");
609 	    printf("\n");
610 	}
611 	if (ds->cmd_protocol) {
612 	    printf("%s  cmd_protocol", indent);
613 	    for (i = 0; i < 7; i++)
614 		if (ds->cmd_protocol & (1<<i))
615 		    printf(" [%s]", cmd_protocol[i]);
616 	    printf("\n");
617 	}
618 	break;
619 
620     case CISTPL_FUNCE_SERIAL_SERV_FAX:
621 	fs = (cistpl_fax_serv_t *)(funce->data);
622 	printf("%sserial_fax_services [class=%d]\n",
623 	       indent, funce->type>>4);
624 	printf("%s  data_rate %d\n", indent,
625 	       75*((fs->max_data_0<<8) + fs->max_data_1));
626 	printf("%s  modulation", indent);
627 	for (i = 0; i < 8; i++)
628 	    if (fs->modulation & (1<<i))
629 		printf(" [%s]", fax_mod[i]);
630 	printf("\n");
631 	if (fs->features_0) {
632 	    printf("%s  features", indent);
633 	    for (i = 0; i < 8; i++)
634 		if (fs->features_0 & (1<<i))
635 		    printf(" [%s]", fax_features[i]);
636 	    printf("\n");
637 	}
638 	break;
639     }
640 }
641 
642 /*====================================================================*/
643 
print_fixed(cistpl_funce_t * funce)644 static void print_fixed(cistpl_funce_t *funce)
645 {
646     cistpl_ide_interface_t *i;
647     cistpl_ide_feature_t *f;
648 
649     switch (funce->type) {
650     case CISTPL_FUNCE_IDE_IFACE:
651 	i = (cistpl_ide_interface_t *)(funce->data);
652 	printf("%sdisk_interface ", indent);
653 	if (i->interface == CISTPL_IDE_INTERFACE)
654 	    printf("[ide]\n");
655 	else
656 	    printf("[undefined]\n");
657 	break;
658     case CISTPL_FUNCE_IDE_MASTER:
659     case CISTPL_FUNCE_IDE_SLAVE:
660 	f = (cistpl_ide_feature_t *)(funce->data);
661 	printf("%sdisk_features", indent);
662 	if (f->feature1 & CISTPL_IDE_SILICON)
663 	    printf(" [silicon]");
664 	else
665 	    printf(" [rotating]");
666 	if (f->feature1 & CISTPL_IDE_UNIQUE)
667 	    printf(" [unique]");
668 	if (f->feature1 & CISTPL_IDE_DUAL)
669 	    printf(" [dual]");
670 	else
671 	    printf(" [single]");
672 	if (f->feature1 && f->feature2)
673 	    printf("\n%s ", indent);
674 	if (f->feature2 & CISTPL_IDE_HAS_SLEEP)
675 	    printf(" [sleep]");
676 	if (f->feature2 & CISTPL_IDE_HAS_STANDBY)
677 	    printf(" [standby]");
678 	if (f->feature2 & CISTPL_IDE_HAS_IDLE)
679 	    printf(" [idle]");
680 	if (f->feature2 & CISTPL_IDE_LOW_POWER)
681 	    printf(" [low power]");
682 	if (f->feature2 & CISTPL_IDE_REG_INHIBIT)
683 	    printf(" [reg inhibit]");
684 	if (f->feature2 & CISTPL_IDE_HAS_INDEX)
685 	    printf(" [index]");
686 	if (f->feature2 & CISTPL_IDE_IOIS16)
687 	    printf(" [iois16]");
688 	putchar('\n');
689 	break;
690     }
691 }
692 
693 /*====================================================================*/
694 
695 static const char *tech[] = {
696     "undefined", "ARCnet", "ethernet", "token_ring", "localtalk",
697     "FDDI/CDDI", "ATM", "wireless"
698 };
699 
700 static const char *media[] = {
701     "undefined", "unshielded_twisted_pair", "shielded_twisted_pair",
702     "thin_coax", "thick_coax", "fiber", "900_MHz", "2.4_GHz",
703     "5.4_GHz", "diffuse_infrared", "point_to_point_infrared"
704 };
705 
print_network(cistpl_funce_t * funce)706 static void print_network(cistpl_funce_t *funce)
707 {
708     cistpl_lan_tech_t *t;
709     cistpl_lan_speed_t *s;
710     cistpl_lan_media_t *m;
711     cistpl_lan_node_id_t *n;
712     cistpl_lan_connector_t *c;
713     int i;
714 
715     switch (funce->type) {
716     case CISTPL_FUNCE_LAN_TECH:
717 	t = (cistpl_lan_tech_t *)(funce->data);
718 	printf("%slan_technology %s\n", indent, tech[t->tech]);
719 	break;
720     case CISTPL_FUNCE_LAN_SPEED:
721 	s = (cistpl_lan_speed_t *)(funce->data);
722 	printf("%slan_speed ", indent);
723 	print_speed(s->speed);
724 	putchar('\n');
725 	break;
726     case CISTPL_FUNCE_LAN_MEDIA:
727 	m = (cistpl_lan_media_t *)(funce->data);
728 	printf("%slan_media %s\n", indent, media[m->media]);
729 	break;
730     case CISTPL_FUNCE_LAN_NODE_ID:
731 	n = (cistpl_lan_node_id_t *)(funce->data);
732 	printf("%slan_node_id", indent);
733 	for (i = 0; i < n->nb; i++)
734 	    printf(" %02x", n->id[i]);
735 	putchar('\n');
736 	break;
737     case CISTPL_FUNCE_LAN_CONNECTOR:
738 	c = (cistpl_lan_connector_t *)(funce->data);
739 	printf("%slan_connector ", indent);
740 	if (c->code == 0)
741 	    printf("Open connector standard\n");
742 	else
743 	    printf("Closed connector standard\n");
744 	break;
745     }
746 }
747 
748 /*====================================================================*/
749 
print_vers_1(cistpl_vers_1_t * v1)750 static void print_vers_1(cistpl_vers_1_t *v1)
751 {
752     int i, n;
753     char s[32];
754     sprintf(s, "%svers_1 %d.%d", indent, v1->major, v1->minor);
755     printf("%s", s);
756     n = strlen(s);
757     for (i = 0; i < v1->ns; i++) {
758 	if (n + strlen(v1->str + v1->ofs[i]) + 4 > 72) {
759 	    n = strlen(indent) + 2;
760 	    printf(",\n%s  ", indent);
761 	} else {
762 	    printf(", ");
763 	    n += 2;
764 	}
765 	printf("\"%s\"", v1->str + v1->ofs[i]);
766 	n += strlen(v1->str + v1->ofs[i]) + 2;
767     }
768     putchar('\n');
769 }
770 
771 /*====================================================================*/
772 
print_vers_2(cistpl_vers_2_t * v2)773 static void print_vers_2(cistpl_vers_2_t *v2)
774 {
775     printf("%sversion 0x%2.2x, compliance 0x%2.2x, dindex 0x%4.4x\n",
776 	   indent, v2->vers, v2->comply, v2->dindex);
777     printf("%s  vspec8 0x%2.2x, vspec9 0x%2.2x, nhdr %d\n",
778 	   indent, v2->vspec8, v2->vspec9, v2->nhdr);
779     printf("%s  vendor \"%s\"\n", indent, v2->str+v2->vendor);
780     printf("%s  info \"%s\"\n", indent, v2->str+v2->info);
781 }
782 
783 /*====================================================================*/
784 
785 #ifdef CISTPL_FORMAT_DISK
print_format(cistpl_format_t * fmt)786 static void print_format(cistpl_format_t *fmt)
787 {
788     if (fmt->type == CISTPL_FORMAT_DISK)
789 	printf("%s  [disk]", indent);
790     else if (fmt->type == CISTPL_FORMAT_MEM)
791 	printf("%s  [memory]", indent);
792     else
793 	printf("%s  [type 0x%02x]\n", indent, fmt->type);
794     if (fmt->edc == CISTPL_EDC_NONE)
795 	printf(" [no edc]");
796     else if (fmt->edc == CISTPL_EDC_CKSUM)
797 	printf(" [cksum]");
798     else if (fmt->edc == CISTPL_EDC_CRC)
799 	printf(" [crc]");
800     else if (fmt->edc == CISTPL_EDC_PCC)
801 	printf(" [pcc]");
802     else
803 	printf(" [edc 0x%02x]", fmt->edc);
804     printf(" offset 0x%04x length ", fmt->offset);
805     print_size(fmt->length);
806     putchar('\n');
807 }
808 #endif
809 
810 /*====================================================================*/
811 
print_config(int code,cistpl_config_t * cfg)812 static void print_config(int code, cistpl_config_t *cfg)
813 {
814     printf("%sconfig%s base 0x%4.4x", indent,
815 	   (code == CISTPL_CONFIG_CB) ? "_cb" : "",
816 	   cfg->base);
817     if (code == CISTPL_CONFIG)
818 	printf(" mask 0x%4.4x", cfg->rmask[0]);
819     printf(" last_index 0x%2.2x\n", cfg->last_idx);
820     if (verbose && cfg->subtuples)
821 	printf("%s  %d bytes in subtuples\n", indent, cfg->subtuples);
822 }
823 
824 /*====================================================================*/
825 
826 static int nfn = 0, cur = 0;
827 
print_parse(tuple_parse_t * tup)828 static void print_parse(tuple_parse_t *tup)
829 {
830     static int func = 0;
831     int i;
832 
833     switch (tup->tuple.TupleCode) {
834     case CISTPL_DEVICE:
835     case CISTPL_DEVICE_A:
836 	if (tup->tuple.TupleCode == CISTPL_DEVICE)
837 	    printf("%sdev_info\n", indent);
838 	else
839 	    printf("%sattr_dev_info\n", indent);
840 	print_device(&tup->parse.device);
841 	break;
842     case CISTPL_CHECKSUM:
843 	printf("%schecksum 0x%04x-0x%04x = 0x%02x\n",
844 	       indent, tup->parse.checksum.addr,
845 	       tup->parse.checksum.addr+tup->parse.checksum.len-1,
846 	       tup->parse.checksum.sum);
847 	break;
848     case CISTPL_LONGLINK_A:
849 	if (verbose)
850 	    printf("%slong_link_attr 0x%04x\n", indent,
851 		   tup->parse.longlink.addr);
852 	break;
853     case CISTPL_LONGLINK_C:
854 	if (verbose)
855 	    printf("%slong_link 0x%04x\n", indent,
856 		   tup->parse.longlink.addr);
857 	break;
858     case CISTPL_LONGLINK_MFC:
859 	if (verbose) {
860 	    printf("%smfc_long_link\n", indent);
861 	    for (i = 0; i < tup->parse.longlink_mfc.nfn; i++)
862 		printf("%s function %d: %s 0x%04x\n", indent, i,
863 		       tup->parse.longlink_mfc.fn[i].space ? "common" : "attr",
864 		       tup->parse.longlink_mfc.fn[i].addr);
865 	} else {
866 	    printf("%smfc {\n", indent);
867 	    nfn = tup->parse.longlink_mfc.nfn;
868 	    cur = 0;
869 	    strcat(indent, "  ");
870 	}
871 	break;
872     case CISTPL_NO_LINK:
873 	if (verbose)
874 	    printf("%sno_long_link\n", indent);
875 	break;
876 #ifdef CISTPL_INDIRECT
877     case CISTPL_INDIRECT:
878 	if (verbose)
879 	    printf("%sindirect_access\n", indent);
880 	break;
881 #endif
882     case CISTPL_LINKTARGET:
883 	if (verbose)
884 	    printf("%slink_target\n", indent);
885 	else {
886 	    if (cur++) printf("%s}, {\n", indent+2);
887 	}
888 	break;
889     case CISTPL_VERS_1:
890 	print_vers_1(&tup->parse.version_1);
891 	break;
892     case CISTPL_ALTSTR:
893 	break;
894     case CISTPL_JEDEC_A:
895     case CISTPL_JEDEC_C:
896 	if (tup->tuple.TupleCode == CISTPL_JEDEC_C)
897 	    printf("%scommon_jedec", indent);
898 	else
899 	    printf("%sattr_jedec", indent);
900 	print_jedec(&tup->parse.jedec);
901 	break;
902     case CISTPL_DEVICE_GEO:
903     case CISTPL_DEVICE_GEO_A:
904 	if (tup->tuple.TupleCode == CISTPL_DEVICE_GEO)
905 	    printf("%scommon_geometry\n", indent);
906 	else
907 	    printf("%sattr_geometry\n", indent);
908 	print_device_geo(&tup->parse.device_geo);
909 	break;
910     case CISTPL_MANFID:
911 	printf("%smanfid 0x%4.4x, 0x%4.4x\n", indent,
912 	       tup->parse.manfid.manf, tup->parse.manfid.card);
913 	break;
914     case CISTPL_FUNCID:
915 	print_funcid(&tup->parse.funcid);
916 	func = tup->parse.funcid.func;
917 	break;
918     case CISTPL_FUNCE:
919 	switch (func) {
920 	case CISTPL_FUNCID_SERIAL:
921 	    print_serial(&tup->parse.funce);
922 	    break;
923 	case CISTPL_FUNCID_FIXED:
924 	    print_fixed(&tup->parse.funce);
925 	    break;
926 	case CISTPL_FUNCID_NETWORK:
927 	    print_network(&tup->parse.funce);
928 	    break;
929 	}
930 	break;
931     case CISTPL_BAR:
932 	printf("%sBAR %d size ", indent,
933 	       tup->parse.bar.attr & CISTPL_BAR_SPACE);
934 	print_size(tup->parse.bar.size);
935 	if (tup->parse.bar.attr & CISTPL_BAR_SPACE_IO)
936 	    printf(" [io]");
937 	else
938 	    printf(" [mem]");
939 	if (tup->parse.bar.attr & CISTPL_BAR_PREFETCH)
940 	    printf(" [prefetch]");
941 	if (tup->parse.bar.attr & CISTPL_BAR_CACHEABLE)
942 	    printf(" [cacheable]");
943 	if (tup->parse.bar.attr & CISTPL_BAR_1MEG_MAP)
944 	    printf(" [<1mb]");
945 	putchar('\n');
946 	break;
947     case CISTPL_CONFIG:
948     case CISTPL_CONFIG_CB:
949 	print_config(tup->tuple.TupleCode, &tup->parse.config);
950 	break;
951     case CISTPL_CFTABLE_ENTRY:
952 	print_cftable_entry(&tup->parse.cftable_entry);
953 	break;
954     case CISTPL_CFTABLE_ENTRY_CB:
955 	print_cftable_entry_cb(&tup->parse.cftable_entry_cb);
956 	break;
957     case CISTPL_VERS_2:
958 	print_vers_2(&tup->parse.vers_2);
959 	break;
960     case CISTPL_ORG:
961 	print_org(&tup->parse.org);
962 	break;
963 #ifdef CISTPL_FORMAT_DISK
964     case CISTPL_FORMAT:
965     case CISTPL_FORMAT_A:
966 	if (tup->tuple.TupleCode == CISTPL_FORMAT)
967 	    printf("%scommon_format\n", indent);
968 	else
969 	    printf("%sattr_format\n", indent);
970 	print_format(&tup->parse.format);
971 #endif
972     }
973 }
974 
975 /*====================================================================*/
976 
get_tuple_buf(int fd,ds_ioctl_arg_t * arg,int first)977 static int get_tuple_buf(int fd, ds_ioctl_arg_t *arg, int first)
978 {
979     u_int ofs;
980     static int nb = 0;
981     static u_char buf[1024];
982 
983     if (first) {
984 	nb = read(fd, buf, sizeof(buf));
985 	arg->tuple.TupleLink = arg->tuple.CISOffset = 0;
986     }
987     ofs = arg->tuple.CISOffset + arg->tuple.TupleLink;
988     if (ofs >= nb) return -1;
989     arg->tuple.TupleCode = buf[ofs++];
990     arg->tuple.TupleDataLen = arg->tuple.TupleLink = buf[ofs++];
991     arg->tuple.CISOffset = ofs;
992     memcpy(arg->tuple_parse.data, buf+ofs, arg->tuple.TupleLink);
993     return 0;
994 }
995 
get_tuple(int fd,ds_ioctl_arg_t * arg,int first)996 static int get_tuple(int fd, ds_ioctl_arg_t *arg, int first)
997 {
998     int cmd = (first) ? DS_GET_FIRST_TUPLE : DS_GET_NEXT_TUPLE;
999     if (ioctl(fd, cmd, arg) != 0) {
1000 	if (errno == ENODEV)
1001 	    printf("%sno card\n", indent);
1002 	else if (errno != ENODATA)
1003 	    printf("%sget tuple: %s\n", indent, strerror(errno));
1004 	return -1;
1005     }
1006     if (ioctl(fd, DS_GET_TUPLE_DATA, arg) != 0) {
1007 	printf("%sget tuple data: %s\n", indent, strerror(errno));
1008 	return -1;
1009     }
1010     return 0;
1011 }
1012 
1013 /*====================================================================*/
1014 
1015 #define MAX_SOCKS 8
1016 
main(int argc,char * argv[])1017 int main(int argc, char *argv[])
1018 {
1019     int i, fd, pfd = -1;
1020     ds_ioctl_arg_t arg;
1021     int optch, errflg, first;
1022     int force = 0;
1023     char *infile = NULL;
1024 
1025     errflg = 0;
1026     while ((optch = getopt(argc, argv, "fvi:")) != -1) {
1027 	switch (optch) {
1028 	case 'f':
1029 	    force = 1; break;
1030 	case 'v':
1031 	    verbose = 1; break;
1032 	case 'i':
1033 	    infile = strdup(optarg); break;
1034 	default:
1035 	    errflg = 1; break;
1036 	}
1037     }
1038     if (errflg || (optind < argc)) {
1039 	fprintf(stderr, "usage: %s [-v] [-f] [-i infile]\n", argv[0]);
1040 	exit(EXIT_FAILURE);
1041     }
1042 
1043 #if (!defined(__BEOS__) && !defined(__HAIKU__))
1044     major = lookup_dev("pcmcia");
1045     if (major < 0) {
1046 	fprintf(stderr, "no pcmcia driver in /proc/devices\n");
1047 	exit(EXIT_FAILURE);
1048     }
1049 #endif
1050 
1051     for (i = 0; (i < MAX_SOCKS) && !(i && infile); i++) {
1052 	nfn = cur = 0;
1053 	if (infile) {
1054 	    indent[0] = '\0';
1055 	    fd = open(infile, O_RDONLY);
1056 	    if (fd < 0) {
1057 		perror("open()");
1058 		return -1;
1059 	    }
1060 	    pfd = open_sock(0);
1061 	} else {
1062 	    strcpy(indent, "  ");
1063 	    fd = pfd = open_sock(i);
1064 	}
1065 	if (pfd < 0)
1066 	    break;
1067 	if (!verbose && (i > 0)) putchar('\n');
1068 	if (!infile) printf("Socket %d:\n", i);
1069 
1070 	if (!force && !infile) {
1071 	    if (ioctl(fd, DS_VALIDATE_CIS, &arg) != 0) {
1072 		printf("%svalidate CIS: %s\n", indent, strerror(errno));
1073 		continue;
1074 	    }
1075 	    if (arg.cisinfo.Chains == 0) {
1076 		printf("%sno CIS present\n", indent);
1077 		continue;
1078 	    }
1079 	}
1080 
1081 	arg.tuple.TupleDataMax = sizeof(arg.tuple_parse.data);
1082 	arg.tuple.Attributes = TUPLE_RETURN_LINK | TUPLE_RETURN_COMMON;
1083 	arg.tuple.DesiredTuple = RETURN_FIRST_TUPLE;
1084 	arg.tuple.TupleOffset = 0;
1085 
1086 	for (first = 1; ; first = 0) {
1087 	    if (infile) {
1088 		if (get_tuple_buf(fd, &arg, first) != 0) break;
1089 	    } else {
1090 		if (get_tuple(fd, &arg, first) != 0) break;
1091 	    }
1092 	    if (verbose) print_tuple(&arg.tuple_parse);
1093 	    if (ioctl(pfd, DS_PARSE_TUPLE, &arg) == 0)
1094 		print_parse(&arg.tuple_parse);
1095 	    else if (errno != ENOSYS)
1096 		printf("%sparse error: %s\n", indent,
1097 		       strerror(errno));
1098 	    if (verbose) putchar('\n');
1099 	    if (arg.tuple.TupleCode == CISTPL_END)
1100 		break;
1101 	}
1102 
1103 	if (!verbose && (nfn > 0))
1104 	    printf("%s}\n", indent+2);
1105     }
1106     if ((i == 0) && (pfd < 0)) {
1107 	perror("open()");
1108 	return -1;
1109     }
1110 
1111     return 0;
1112 }
1113