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