summaryrefslogtreecommitdiffstats
path: root/usr.sbin/pccard/pccardc
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>2000-04-26 15:36:43 +0000
committeriwasaki <iwasaki@FreeBSD.org>2000-04-26 15:36:43 +0000
commit2fda64208132fbaa6e6e99477931b9e81b5bd862 (patch)
tree24eabdae3a41424014523960238b6927a18c8f22 /usr.sbin/pccard/pccardc
parent669bd2a6bbbb76c7c6f90d331a5b21ebb1fcf03e (diff)
downloadFreeBSD-src-2fda64208132fbaa6e6e99477931b9e81b5bd862.zip
FreeBSD-src-2fda64208132fbaa6e6e99477931b9e81b5bd862.tar.gz
MFPAO3. Improvement of of pccard cis tuple parsing capability.
- Fixed bogus CIS tuple dumping (Network node ID, IRQ modes and etc.) - Include telling drivers ethernet address if Network node ID tuple is available. This is usefull for some bogus ehter cards which can't get correct ethernet address from CIS tupple. Obtained from: PAO3
Diffstat (limited to 'usr.sbin/pccard/pccardc')
-rw-r--r--usr.sbin/pccard/pccardc/printcis.c1200
1 files changed, 799 insertions, 401 deletions
diff --git a/usr.sbin/pccard/pccardc/printcis.c b/usr.sbin/pccard/pccardc/printcis.c
index 4fea696..70626d4 100644
--- a/usr.sbin/pccard/pccardc/printcis.c
+++ b/usr.sbin/pccard/pccardc/printcis.c
@@ -29,6 +29,12 @@ static const char rcsid[] =
"$FreeBSD$";
#endif /* not lint */
+/*
+ * Code cleanup, bug-fix and extension
+ * by Tatsumi Hosokawa <hosokawa@mt.cs.keio.ac.jp>
+ */
+
+#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -40,14 +46,20 @@ static const char rcsid[] =
#include "readcis.h"
-int dump_pwr_desc(unsigned char *);
-void print_ext_speed(unsigned char, int);
-void dump_device_desc(unsigned char *p, int len, char *type);
-void dump_info_v1(unsigned char *p, int len);
-void dump_config_map(struct tuple *tp);
-void dump_cis_config(struct tuple *tp);
-void dump_other_cond(unsigned char *p);
-void dump_func_ext(unsigned char *p, int len);
+static void dump_config_map(struct tuple *tp);
+static void dump_cis_config(struct tuple *tp);
+static void dump_other_cond(u_char *p, int len);
+static void dump_device_desc(u_char *p, int len, char *type);
+static void dump_info_v1(u_char *p, int len);
+static void dump_longlink_mfc(u_char *p, int len);
+static void dump_bar(u_char *p, int len);
+static void dump_device_geo(u_char *p, int len);
+static void dump_func_id(u_char *p);
+static void dump_serial_ext(u_char *p, int len);
+static void dump_disk_ext(u_char *p, int len);
+static void dump_network_ext(u_char *p, int len);
+static void dump_info_v2(u_char *p, int len);
+static void dump_org(u_char *p, int len);
void
dumpcis(struct cis *cp)
@@ -55,7 +67,8 @@ dumpcis(struct cis *cp)
struct tuple *tp;
struct tuple_list *tl;
int count = 0, sz, ad, i;
- unsigned char *p;
+ u_char *p;
+ int func = 0;
for (tl = cp->tlist; tl; tl = tl->next)
for (tp = tl->tuples; tp; tp = tp->next) {
@@ -79,30 +92,32 @@ dumpcis(struct cis *cp)
case CIS_MEM_COMMON: /* 0x01 */
dump_device_desc(tp->data, tp->length, "Common");
break;
+ case CIS_CONF_MAP_CB: /* 0x04 */
+ dump_config_map(tp);
+ break;
+ case CIS_CONFIG_CB: /* 0x05 */
+ dump_cis_config(tp);
+ break;
+ case CIS_LONGLINK_MFC: /* 0x06 */
+ dump_longlink_mfc(tp->data, tp->length);
+ break;
+ case CIS_BAR: /* 0x07 */
+ dump_bar(tp->data, tp->length);
+ break;
case CIS_CHECKSUM: /* 0x10 */
- if (tp->length == 5) {
- printf("\tChecksum from offset %d, length %d, value is 0x%x\n",
- (short)((tp->data[1] << 8) | tp->data[0]),
- (tp->data[3] << 8) | tp->data[2],
- tp->data[4]);
- } else
- printf("\tIllegal length for checksum!\n");
+ printf("\tChecksum from offset %d, length %d, value is 0x%x\n",
+ tpl16(tp->data),
+ tpl16(tp->data + 2),
+ tp->data[4]);
break;
case CIS_LONGLINK_A: /* 0x11 */
printf("\tLong link to attribute memory, address 0x%x\n",
- (tp->data[3] << 24) |
- (tp->data[2] << 16) |
- (tp->data[1] << 8) |
- tp->data[0]);
+ tpl32(tp->data));
break;
case CIS_LONGLINK_C: /* 0x12 */
printf("\tLong link to common memory, address 0x%x\n",
- (tp->data[3] << 24) |
- (tp->data[2] << 16) |
- (tp->data[1] << 8) |
- tp->data[0]);
- break;
- break;
+ tpl32(tp->data));
+ break;
case CIS_INFO_V1: /* 0x15 */
dump_info_v1(tp->data, tp->length);
break;
@@ -112,7 +127,6 @@ dumpcis(struct cis *cp)
dump_device_desc(tp->data, tp->length, "Attribute");
break;
case CIS_JEDEC_C: /* 0x18 */
- break;
case CIS_JEDEC_A: /* 0x19 */
break;
case CIS_CONF_MAP: /* 0x1A */
@@ -122,111 +136,387 @@ dumpcis(struct cis *cp)
dump_cis_config(tp);
break;
case CIS_DEVICE_OC: /* 0x1C */
- dump_other_cond(tp->data);
- break;
case CIS_DEVICE_OA: /* 0x1D */
- dump_other_cond(tp->data);
+ dump_other_cond(tp->data, tp->length);
break;
case CIS_DEVICEGEO: /* 0x1E */
- break;
case CIS_DEVICEGEO_A: /* 0x1F */
+ dump_device_geo(tp->data, tp->length);
break;
case CIS_MANUF_ID: /* 0x20 */
printf("\tPCMCIA ID = 0x%x, OEM ID = 0x%x\n",
- (tp->data[1] << 8) | tp->data[0],
- (tp->data[3] << 8) | tp->data[2]);
+ tpl16(tp->data),
+ tpl16(tp->data + 2));
break;
case CIS_FUNC_ID: /* 0x21 */
- switch (tp->data[0]) {
- default:
- printf("\tUnknown function");
- break;
- case 0:
- printf("\tMultifunction card");
- break;
- case 1:
- printf("\tMemory card");
- break;
+ func = tp->data[0];
+ dump_func_id(tp->data);
+ break;
+ case CIS_FUNC_EXT: /* 0x22 */
+ switch (func) {
case 2:
- printf("\tSerial port/modem");
- break;
- case 3:
- printf("\tParallel port");
+ dump_serial_ext(tp->data, tp->length);
break;
case 4:
- printf("\tFixed disk card");
- break;
- case 5:
- printf("\tVideo adapter");
+ dump_disk_ext(tp->data, tp->length);
break;
case 6:
- printf("\tNetwork/LAN adapter");
- break;
- case 7:
- printf("\tAIMS");
+ dump_network_ext(tp->data, tp->length);
break;
}
- printf("%s%s\n", (tp->data[1] & 1) ? " - POST initialize" : "",
- (tp->data[1] & 2) ? " - Card has ROM" : "");
- break;
- case CIS_FUNC_EXT: /* 0x22 */
- dump_func_ext(tp->data, tp->length);
break;
case CIS_VERS_2: /* 0x40 */
+ dump_info_v2(tp->data, tp->length);
+ break;
+ case CIS_ORG: /* 0x46 */
+ dump_org(tp->data, tp->length);
break;
}
}
}
/*
- * Dump configuration map tuple.
+ * CIS_CONF_MAP : Dump configuration map tuple.
+ * CIS_CONF_MAP_CB: Dump configuration map for CardBus
*/
-void
+static void
dump_config_map(struct tuple *tp)
{
- unsigned char *p, x;
- int rlen, mlen;
+ u_char *p = tp->data, x;
+ int rlen, mlen = 0;
int i;
- union {
- unsigned long l;
- unsigned char b[4];
- } u;
-
- rlen = (tp->data[0] & 3) + 1;
- mlen = ((tp->data[0] >> 2) & 3) + 1;
- u.l = 0;
- p = tp->data + 2;
- for (i = 0; i < rlen; i++)
- u.b[i] = *p++;
- printf("\tReg len = %d, config register addr = 0x%lx, last config = 0x%x\n",
- rlen, u.l, tp->data[1]);
- if (mlen)
+
+ rlen = (p[0] & 3) + 1;
+ if (tp->code == CIS_CONF_MAP)
+ mlen = ((p[0] >> 2) & 3) + 1;
+ if (tp->length < rlen + mlen + 2) {
+ printf("\tWrong length for configuration map tuple\n");
+ return;
+ }
+ printf("\tReg len = %d, config register addr = 0x%x, last config = 0x%x\n",
+ rlen, parse_num(rlen | 0x10, p + 2, &p, 0), p[1]);
+ if (mlen) {
printf("\tRegisters: ");
- for (i = 0; i < mlen; i++, p++) {
- for (x = 0x1; x; x <<= 1)
- printf("%c", x & *p ? 'X' : '-');
- printf(" ");
+ for (i = 0; i < mlen; i++, p++) {
+ for (x = 0x1; x; x <<= 1)
+ printf("%c", x & *p ? 'X' : '-');
+ putchar(' ');
+ }
+ }
+ i = tp->length - (rlen + mlen + 2);
+ if (i) {
+ if (!mlen)
+ putchar('\t');
+ printf("%d bytes in subtuples", i);
}
- printf("\n");
+ if (mlen || i)
+ putchar('\n');
}
/*
- * Dump a config entry.
+ * Dump power descriptor.
+ * call from dump_cis_config()
*/
-void
+static int
+print_pwr_desc(u_char *p)
+{
+ int len = 1, i;
+ u_char mask;
+ char **expp;
+ static char *pname[] =
+ {"Nominal operating supply voltage",
+ "Minimum operating supply voltage",
+ "Maximum operating supply voltage",
+ "Continuous supply current",
+ "Max current average over 1 second",
+ "Max current average over 10 ms",
+ "Power down supply current",
+ "Reserved"
+ };
+ static char *vexp[] =
+ {"10uV", "100uV", "1mV", "10mV", "100mV", "1V", "10V", "100V"};
+ static char *cexp[] =
+ {"10nA", "1uA", "10uA", "100uA", "1mA", "10mA", "100mA", "1A"};
+ static char *mant[] =
+ {"1", "1.2", "1.3", "1.5", "2", "2.5", "3", "3.5", "4", "4.5",
+ "5", "5.5", "6", "7", "8", "9"};
+
+ mask = *p++;
+ expp = vexp;
+ for (i = 0; i < 8; i++)
+ if (mask & (1 << i)) {
+ len++;
+ if (i >= 3)
+ expp = cexp;
+ printf("\t\t%s: ", pname[i]);
+ printf("%s x %s",
+ mant[(*p >> 3) & 0xF],
+ expp[*p & 7]);
+ while (*p & 0x80) {
+ len++;
+ p++;
+ printf(", ext = 0x%x", *p);
+ }
+ printf("\n");
+ p++;
+ }
+ return (len);
+}
+
+/*
+ * print_ext_speed - Print extended speed.
+ * call from dump_cis_config(), dump_device_desc()
+ */
+static void
+print_ext_speed(u_char x, int scale)
+{
+ static char *mant[] =
+ {"Reserved", "1.0", "1.2", "1.3", "1.5", "2.0", "2.5", "3.0",
+ "3.5", "4.0", "4.5", "5.0", "5.5", "6.0", "7.0", "8.0"};
+ static char *exp[] =
+ {"1 ns", "10 ns", "100 ns", "1 us", "10 us", "100 us",
+ "1 ms", "10 ms"};
+ static char *scale_name[] =
+ {"None", "10", "100", "1,000", "10,000", "100,000",
+ "1,000,000", "10,000,000"};
+
+ printf("Speed = %s x %s", mant[(x >> 3) & 0xF], exp[x & 7]);
+ if (scale)
+ printf(", scaled by %s", scale_name[scale & 7]);
+}
+
+/*
+ * Print variable length value.
+ * call from print_io_map(), print_mem_map()
+ */
+static int
+print_num(int sz, char *fmt, u_char *p, int ofs)
+{
+ switch (sz) {
+ case 0:
+ case 0x10:
+ return 0;
+ case 1:
+ case 0x11:
+ printf(fmt, *p + ofs);
+ return 1;
+ case 2:
+ case 0x12:
+ printf(fmt, tpl16(p) + ofs);
+ return 2;
+ case 0x13:
+ printf(fmt, tpl24(p) + ofs);
+ return 3;
+ case 3:
+ case 0x14:
+ printf(fmt, tpl32(p) + ofs);
+ return 4;
+ }
+ errx(1, "print_num(0x%x): Illegal arguments", sz);
+/*NOTREACHED*/
+}
+
+/*
+ * Print I/O mapping sub-tuple.
+ * call from dump_cis_config()
+ */
+static u_char *
+print_io_map(u_char *p, u_char *q)
+{
+ int i, j;
+ u_char c;
+
+ if (q <= p)
+ goto err;
+ if (CIS_IO_ADDR(*p)) /* I/O address line */
+ printf("\tCard decodes %d address lines",
+ CIS_IO_ADDR(*p));
+ else
+ printf("\tCard provides address decode");
+
+ /* 8/16 bit I/O */
+ switch (*p & (CIS_IO_8BIT | CIS_IO_16BIT)) {
+ case CIS_IO_8BIT:
+ printf(", 8 Bit I/O only");
+ break;
+ case CIS_IO_16BIT:
+ printf(", limited 8/16 Bit I/O");
+ break;
+ case (CIS_IO_8BIT | CIS_IO_16BIT):
+ printf(", full 8/16 Bit I/O");
+ break;
+ }
+ putchar('\n');
+
+ /* I/O block sub-tuple exist */
+ if (*p++ & CIS_IO_RANGE) {
+ if (q <= p)
+ goto err;
+ c = *p++;
+ /* calculate byte length */
+ j = CIS_IO_ADSZ(c) + CIS_IO_BLKSZ(c);
+ if (CIS_IO_ADSZ(c) == 3)
+ j++;
+ if (CIS_IO_BLKSZ(c) == 3)
+ j++;
+ /* number of I/O block sub-tuples */
+ for (i = 0; i <= CIS_IO_BLKS(c); i++) {
+ if (q - p < j)
+ goto err;
+ printf("\t\tI/O address # %d: ", i + 1);
+ /* start block address */
+ p += print_num(CIS_IO_ADSZ(c),
+ "block start = 0x%x", p, 0);
+ /* block size */
+ p += print_num(CIS_IO_BLKSZ(c),
+ " block length = 0x%x", p, 1);
+ putchar('\n');
+ }
+ }
+ return p;
+
+ err: /* warning */
+ printf("\tWrong length for I/O mapping sub-tuple\n");
+ return p;
+}
+
+/*
+ * Print IRQ sub-tuple.
+ * call from dump_cis_config()
+ */
+static u_char *
+print_irq_map(u_char *p, u_char *q)
+{
+ int i, j;
+ u_char c;
+
+ if (q <= p)
+ goto err;
+ printf("\t\tIRQ modes:");
+ c = ' ';
+ if (*p & CIS_IRQ_LEVEL) { /* Level triggered interrupts */
+ printf(" Level");
+ c = ',';
+ }
+ if (*p & CIS_IRQ_PULSE) { /* Pulse triggered requests */
+ printf("%c Pulse", c);
+ c = ',';
+ }
+ if (*p & CIS_IRQ_SHARING) /* Interrupt sharing */
+ printf("%c Shared", c);
+ putchar('\n');
+
+ /* IRQ mask values exist */
+ if (*p & CIS_IRQ_MASK) {
+ if (q - p < 3)
+ goto err;
+ i = tpl16(p + 1); /* IRQ mask */
+ printf("\t\tIRQs: ");
+ if (*p & 1)
+ printf(" NMI");
+ if (*p & 0x2)
+ printf(" IOCK");
+ if (*p & 0x4)
+ printf(" BERR");
+ if (*p & 0x8)
+ printf(" VEND");
+ for (j = 0; j < 16; j++)
+ if (i & (1 << j))
+ printf(" %d", j);
+ putchar('\n');
+ p += 3;
+ } else {
+ printf("\t\tIRQ level = %d\n", CIS_IRQ_IRQN(*p));
+ p++;
+ }
+ return p;
+
+ err: /* warning */
+ printf("\tWrong length for IRQ sub-tuple\n");
+ return p;
+}
+
+/*
+ * Print memory map sub-tuple.
+ * call from dump_cis_config()
+ */
+static u_char *
+print_mem_map(u_char feat, u_char *p, u_char *q)
+{
+ int i, j;
+ u_char c;
+
+ switch (CIS_FEAT_MEMORY(feat)) {
+
+ case CIS_FEAT_MEM_NONE: /* No memory block */
+ break;
+ case CIS_FEAT_MEM_LEN: /* Specify memory length */
+ if (q - p < 2)
+ goto err;
+ printf("\tMemory space length = 0x%x\n", tpl16(p));
+ p += 2;
+ break;
+ case CIS_FEAT_MEM_ADDR: /* Memory address and length */
+ if (q - p < 4)
+ goto err;
+ printf("\tMemory space address = 0x%x, length = 0x%x\n",
+ tpl16(p + 2), tpl16(p));
+ p += 4;
+ break;
+ case CIS_FEAT_MEM_WIN: /* Memory descriptors. */
+ if (q <= p)
+ goto err;
+ c = *p++;
+ /* calculate byte length */
+ j = CIS_MEM_LENSZ(c) + CIS_MEM_ADDRSZ(c);
+ if (c & CIS_MEM_HOST)
+ j += CIS_MEM_ADDRSZ(c);
+ /* number of memory block */
+ for (i = 0; i < CIS_MEM_WINS(c); i++) {
+ if (q - p < j)
+ goto err;
+ printf("\tMemory descriptor %d\n\t\t", i + 1);
+ /* memory length */
+ p += print_num(CIS_MEM_LENSZ(c) | 0x10,
+ " blk length = 0x%x00", p, 0);
+ /* card address */
+ p += print_num(CIS_MEM_ADDRSZ(c) | 0x10,
+ " card addr = 0x%x00", p, 0);
+ if (c & CIS_MEM_HOST) /* Host address value exist */
+ p += print_num(CIS_MEM_ADDRSZ(c) | 0x10,
+ " host addr = 0x%x00", p, 0);
+ putchar('\n');
+ }
+ break;
+ }
+ return p;
+
+ err: /* warning */
+ printf("\tWrong length for memory mapping sub-tuple\n");
+ return p;
+}
+
+/*
+ * CIS_CONFIG : Dump a config entry.
+ * CIS_CONFIG_CB: Dump a configuration entry for CardBus
+ */
+static void
dump_cis_config(struct tuple *tp)
{
- unsigned char *p, feat;
+ u_char *p, *q, feat;
int i, j;
char c;
p = tp->data;
+ q = p + tp->length;
printf("\tConfig index = 0x%x%s\n", *p & 0x3F,
- *p & 0x40 ? "(default)" : "");
- if (*p & 0x80) {
+ *p & 0x40 ? "(default)" : "");
+
+ /* Interface byte exists */
+ if (tp->code == CIS_CONFIG && (*p & 0x80)) {
p++;
printf("\tInterface byte = 0x%x ", *p);
- switch (*p & 0xF) {
+ switch (*p & 0xF) { /* Interface type */
default:
printf("(reserved)");
break;
@@ -245,265 +535,150 @@ dump_cis_config(struct tuple *tp)
break;
}
c = ' ';
- if (*p & 0x10) {
+ if (*p & 0x10) { /* Battery voltage detect */
printf(" BVD1/2 active");
c = ',';
}
- if (*p & 0x20) {
+ if (*p & 0x20) { /* Write protect active */
printf("%c card WP active", c); /* Write protect */
c = ',';
}
- if (*p & 0x40) {
+ if (*p & 0x40) { /* RdyBsy active bit */
printf("%c +RDY/-BSY active", c);
c = ',';
}
- if (*p & 0x80)
+ if (*p & 0x80) /* Wait signal required */
printf("%c wait signal supported", c);
printf("\n");
}
+
+ /* features byte */
p++;
feat = *p++;
- switch (CIS_FEAT_POWER(feat)) {
+
+ /* Power structure sub-tuple */
+ switch (CIS_FEAT_POWER(feat)) { /* Power sub-tuple(s) exists */
case 0:
break;
case 1:
printf("\tVcc pwr:\n");
- p += dump_pwr_desc(p);
+ p += print_pwr_desc(p);
break;
case 2:
printf("\tVcc pwr:\n");
- p += dump_pwr_desc(p);
+ p += print_pwr_desc(p);
printf("\tVpp pwr:\n");
- p += dump_pwr_desc(p);
+ p += print_pwr_desc(p);
break;
case 3:
printf("\tVcc pwr:\n");
- p += dump_pwr_desc(p);
+ p += print_pwr_desc(p);
printf("\tVpp1 pwr:\n");
- p += dump_pwr_desc(p);
+ p += print_pwr_desc(p);
printf("\tVpp2 pwr:\n");
- p += dump_pwr_desc(p);
+ p += print_pwr_desc(p);
break;
}
- if (feat & CIS_FEAT_TIMING) {
- i = CIS_WAIT_SCALE(*p);
- j = CIS_READY_SCALE(*p);
- p++;
- if (i != 3) {
+
+ /* Timing sub-tuple */
+ if (tp->code == CIS_CONFIG &&
+ (feat & CIS_FEAT_TIMING)) { /* Timing sub-tuple exists */
+ i = *p++;
+ j = CIS_WAIT_SCALE(i);
+ if (j != 3) {
printf("\tWait scale ");
- print_ext_speed(*p, i);
- while (*p & 0x80)
- p++;
+ print_ext_speed(*p++, j);
printf("\n");
}
+ j = CIS_READY_SCALE(i);
if (j != 7) {
printf("\tRDY/BSY scale ");
- print_ext_speed(*p, j);
- while (*p & 0x80)
- p++;
+ print_ext_speed(*p++, j);
printf("\n");
}
- }
- if (feat & CIS_FEAT_I_O) {
- if (CIS_IO_ADDR(*p))
- printf("\tCard decodes %d address lines",
- CIS_IO_ADDR(*p));
- else
- printf("\tCard provides address decode");
- switch (CIS_MEM_ADDRSZ(*p)) {
- case 0:
- break;
- case 1:
- printf(", 8 Bit I/O only");
- break;
- case 2:
- printf(", limited 8/16 Bit I/O");
- break;
- case 3:
- printf(", full 8/16 Bit I/O");
- break;
+ j = CIS_RESERVED_SCALE(i);
+ if (j != 7) {
+ printf("\tExternal scale ");
+ print_ext_speed(*p++, j);
+ printf("\n");
}
- printf("\n");
- if (*p & CIS_IO_RANGE) {
+ }
+
+ /* I/O mapping sub-tuple */
+ if (feat & CIS_FEAT_I_O) { /* I/O space sub-tuple exists */
+ if (tp->code == CIS_CONFIG)
+ p = print_io_map(p, q);
+ else { /* CIS_CONFIG_CB */
+ printf("\tI/O base:");
+ for (i = 0; i < 8; i++)
+ if (*p & (1 << i))
+ printf(" %d", i);
+ putchar('\n');
p++;
- c = *p++;
- for (i = 0; i <= CIS_IO_BLKS(c); i++) {
- printf("\t\tI/O address # %d: ", i + 1);
- switch (CIS_IO_ADSZ(c)) {
- case 0:
- break;
- case 1:
- printf("block start = 0x%x", *p++);
- break;
- case 2:
- printf("block start = 0x%x", (p[1] << 8) | *p);
- p += 2;
- break;
- case 3:
- printf("block start = 0x%x",
- (p[3] << 24) | (p[2] << 16) |
- (p[1] << 8) | *p);
- p += 4;
- break;
- }
- switch (CIS_IO_BLKSZ(c)) {
- case 0:
- break;
- case 1:
- printf(" block length = 0x%x", *p++ + 1);
- break;
- case 2:
- printf(" block length = 0x%x", ((p[1] << 8) | *p) + 1);
- p += 2;
- break;
- case 3:
- printf(" block length = 0x%x",
- ((p[3] << 24) | (p[2] << 16) |
- (p[1] << 8) | *p) + 1);
- p += 4;
- break;
- }
- printf("\n");
- }
}
}
- /* IRQ descriptor */
- if (feat & CIS_FEAT_IRQ) {
- printf("\t\tIRQ modes:");
- c = ' ';
- if (*p & CIS_IRQ_LEVEL) {
- printf(" Level");
- c = ',';
- }
- if (*p & CIS_IRQ_PULSE) {
- printf("%c Pulse", c);
- c = ',';
- }
- if (*p & CIS_IRQ_SHARING)
- printf("%c Shared", c);
- printf("\n");
- if (*p & CIS_IRQ_MASK) {
- i = p[0] | (p[1] << 8);
- printf("\t\tIRQs: ");
- if (*p & 1)
- printf(" NMI");
- if (*p & 0x2)
- printf(" IOCK");
- if (*p & 0x4)
- printf(" BERR");
- if (*p & 0x8)
- printf(" VEND");
- for (j = 0; j < 16; j++)
- if (i & (1 << j))
- printf(" %d", j);
- printf("\n");
- p += 3;
- } else {
- printf("\t\tIRQ level = %d\n", CIS_IRQ_IRQN(*p));
+ /* IRQ descriptor sub-tuple */
+ if (feat & CIS_FEAT_IRQ) /* IRQ sub-tuple exists */
+ p = print_irq_map(p, q);
+
+ /* Memory map sub-tuple */
+ if (CIS_FEAT_MEMORY(feat)) { /* Memory space sub-tuple(s) exists */
+ if (tp->code == CIS_CONFIG)
+ p = print_mem_map(feat, p, q);
+ else { /* CIS_CONFIG_CB */
+ printf("\tMemory base:");
+ for (i = 0; i < 8; i++)
+ if (*p & (1 << i))
+ printf(" %d", i);
+ putchar('\n');
p++;
}
}
- switch (CIS_FEAT_MEMORY(feat)) {
- case 0:
- break;
- case 1:
- printf("\tMemory space length = 0x%x\n", (p[1] << 8) | p[0]);
- p += 2;
- break;
- case 2:
- printf("\tMemory space address = 0x%x, length = 0x%x\n",
- (p[3] << 8) | p[2],
- (p[1] << 8) | p[0]);
- p += 4;
- break;
- /* Memory descriptors. */
- case 3:
- c = *p++;
- for (i = 0; i <= (c & 7); i++) {
- printf("\tMemory descriptor %d\n\t\t", i + 1);
- switch (CIS_MEM_LENSZ(c)) {
- case 0:
- break;
- case 1:
- printf(" blk length = 0x%x00", *p++);
- break;
- case 2:
- printf(" blk length = 0x%x00", (p[1] << 8) | *p);
- p += 2;
- break;
- case 3:
- printf(" blk length = 0x%x00",
- (p[3] << 24) | (p[2] << 16) |
- (p[1] << 8) | *p);
- p += 4;
- break;
- }
- switch (CIS_MEM_ADDRSZ(c)) {
- case 0:
- break;
- case 1:
- printf(" card addr = 0x%x00", *p++);
- break;
- case 2:
- printf(" card addr = 0x%x00", (p[1] << 8) | *p);
- p += 2;
- break;
- case 3:
- printf(" card addr = 0x%x00",
- (p[3] << 24) | (p[2] << 16) |
- (p[1] << 8) | *p);
- p += 4;
- break;
+ /* Misc sub-tuple */
+ if (feat & CIS_FEAT_MISC) { /* Miscellaneous sub-tuple exists */
+ if (tp->code == CIS_CONFIG) {
+ printf("\tMax twin cards = %d\n", *p & 7);
+ printf("\tMisc attr:%s%s%s",
+ (*p & 8) ? " (Audio-BVD2)" : "",
+ (*p & 0x10) ? " (Read-only)" : "",
+ (*p & 0x20) ? " (Power down supported)" : "");
+ if (*p++ & 0x80) {
+ printf(" (Ext byte = 0x%x)", *p);
+ p++;
}
- if (c & CIS_MEM_HOST)
- switch ((c >> 5) & 3) {
- case 0:
- break;
- case 1:
- printf(" host addr = 0x%x00", *p++);
- break;
- case 2:
- printf(" host addr = 0x%x00", (p[1] << 8) | *p);
- p += 2;
- break;
- case 3:
- printf(" host addr = 0x%x00",
- (p[3] << 24) | (p[2] << 16) |
- (p[1] << 8) | *p);
- p += 4;
- break;
- }
- printf("\n");
+ putchar('\n');
}
- break;
- }
- if (feat & CIS_FEAT_MISC) {
- printf("\tMax twin cards = %d\n", *p & 7);
- printf("\tMisc attr:");
- if (*p & 0x8)
- printf(" (Audio-BVD2)");
- if (*p & 0x10)
- printf(" (Read-only)");
- if (*p & 0x20)
- printf(" (Power down supported)");
- if (*p & 0x80) {
- printf(" (Ext byte = 0x%x)", p[1]);
- p++;
+ else { /* CIS_CONFIG_CB */
+ printf("\tMisc attr:");
+ printf("%s%s%s%s%s%s%s",
+ (*p & 1) ? " (Master)" : "",
+ (*p & 2) ? " (Invalidate)" : "",
+ (*p & 4) ? " (VGA palette)" : "",
+ (*p & 8) ? " (Parity)" : "",
+ (*p & 0x10) ? " (Wait)" : "",
+ (*p & 0x20) ? " (Serr)" : "",
+ (*p & 0x40) ? " (Fast back)" : "");
+ if (*p++ & 0x80) {
+ printf("%s%s",
+ (*p & 1) ? " (Binary audio)" : "",
+ (*p & 2) ? " (pwm audio)" : "");
+ p++;
+ }
+ putchar('\n');
}
- printf("\n");
- p++;
}
}
/*
- * dump_other_cond - Dump other conditions.
+ * CIS_DEVICE_OC, CIS_DEVICE_OA:
+ * Dump other conditions for common/attribute memory
*/
-void
-dump_other_cond(unsigned char *p)
+static void
+dump_other_cond(u_char *p, int len)
{
- if (p[0]) {
+ if (p[0] && len > 0) {
printf("\t");
if (p[0] & 1)
printf("(MWAIT)");
@@ -516,56 +691,11 @@ dump_other_cond(unsigned char *p)
}
/*
- * Dump power descriptor.
+ * CIS_MEM_COMMON, CIS_MEM_ATTR:
+ * Common / Attribute memory descripter
*/
-int
-dump_pwr_desc(unsigned char *p)
-{
- int len = 1, i;
- unsigned char mask;
- char **expp;
- static char *pname[] =
- {"Nominal operating supply voltage",
- "Minimum operating supply voltage",
- "Maximum operating supply voltage",
- "Continuous supply current",
- "Max current average over 1 second",
- "Max current average over 10 ms",
- "Power down supply current",
- "Reserved"
- };
- static char *vexp[] =
- {"10uV", "100uV", "1mV", "10mV", "100mV", "1V", "10V", "100V"};
- static char *cexp[] =
- {"10nA", "1uA", "10uA", "100uA", "1mA", "10mA", "100mA", "1A"};
- static char *mant[] =
- {"1", "1.2", "1.3", "1.5", "2", "2.5", "3", "3.5", "4", "4.5",
- "5", "5.5", "6", "7", "8", "9"};
-
- mask = *p++;
- expp = vexp;
- for (i = 0; i < 8; i++)
- if (mask & (1 << i)) {
- len++;
- if (i >= 3)
- expp = cexp;
- printf("\t\t%s: ", pname[i]);
- printf("%s x %s",
- mant[(*p >> 3) & 0xF],
- expp[*p & 7]);
- while (*p & 0x80) {
- len++;
- p++;
- printf(", ext = 0x%x", *p);
- }
- printf("\n");
- p++;
- }
- return (len);
-}
-
-void
-dump_device_desc(unsigned char *p, int len, char *type)
+static void
+dump_device_desc(u_char *p, int len, char *type)
{
static char *un_name[] =
{"512b", "2Kb", "8Kb", "32Kb", "128Kb", "512Kb", "2Mb", "reserved"};
@@ -581,7 +711,7 @@ dump_device_desc(unsigned char *p, int len, char *type)
int count = 0;
while (*p != 0xFF && len > 0) {
- unsigned char x;
+ u_char x;
x = *p++;
len -= 2;
@@ -593,7 +723,7 @@ dump_device_desc(unsigned char *p, int len, char *type)
len--;
if (*p) {
printf("\t\t");
- print_ext_speed(*p, 0);
+ print_ext_speed(*p++, 0);
while (*p & 0x80) {
p++;
len--;
@@ -609,45 +739,86 @@ dump_device_desc(unsigned char *p, int len, char *type)
}
/*
- * Print version info
+ * CIS_INFO_V1: Print version-1 info
*/
-void
-dump_info_v1(unsigned char *p, int len)
+static void
+dump_info_v1(u_char *p, int len)
{
+ if (len < 2) {
+ printf("\tWrong length for version-1 info tuple\n");
+ return;
+ }
printf("\tVersion = %d.%d", p[0], p[1]);
p += 2;
- printf(", Manuf = [%s],", p);
- while (*p++);
- printf("card vers = [%s]\n", p);
- while (*p++);
- if (*p == 0xff)
+ len -= 2;
+ if (len > 1 && *p != 0xff) {
+ printf(", Manuf = [%s]", p);
+ while (*p++ && --len > 0);
+ }
+ if (len > 1 && *p != 0xff) {
+ printf(", card vers = [%s]", p);
+ while (*p++ && --len > 0);
+ } else {
+ printf("\n\tWrong length for version-1 info tuple\n");
return;
- printf("\tAddit. info = [%s]", p);
- while (*p++);
- while (*p != 0xff) {
- printf(",[%s]", p);
- while (*p++);
}
- printf("\n");
+ putchar('\n');
+ if (len > 1 && *p != 0xff) {
+ printf("\tAddit. info = [%.*s]", len, p);
+ while (*p++ && --len > 0);
+ if (len > 1 && *p != 0xff)
+ printf(",[%.*s]", len, p);
+ putchar('\n');
+ }
}
/*
- * dump functional extension tuple.
+ * CIS_FUNC_ID: Functional ID
*/
-void
-dump_func_ext(unsigned char *p, int len)
+static void
+dump_func_id(u_char *p)
+{
+ static char *id[] = {
+ "Multifunction card",
+ "Memory card",
+ "Serial port/modem",
+ "Parallel port",
+ "Fixed disk card",
+ "Video adapter",
+ "Network/LAN adapter",
+ "AIMS",
+ "SCSI card",
+ "Security"
+ };
+
+ printf("\t%s%s%s\n",
+ (*p <= 9) ? id[*p] : "Unknown function",
+ (p[1] & 1) ? " - POST initialize" : "",
+ (p[1] & 2) ? " - Card has ROM" : "");
+}
+
+/*
+ * CIS_FUNC_EXT: Dump functional extension tuple.
+ * (Serial port/modem)
+ */
+static void
+dump_serial_ext(u_char *p, int len)
{
- if (len == 0)
+ static char *type[] = {
+ "", "Modem", "Data", "Fax", "Voice", "Data modem",
+ "Fax/modem", "Voice", " (Data)", " (Fax)", " (Voice)"
+ };
+
+ if (len < 1)
return;
switch (p[0]) {
- case 0:
- case 8:
- case 10:
- if (len != 4) {
- printf("\tWrong length for serial extension\n");
- return;
- }
- printf("\tSerial interface extension:\n");
+ case 0: /* Serial */
+ case 8: /* Data */
+ case 9: /* Fax */
+ case 10: /* Voice */
+ printf("\tSerial interface extension:%s\n", type[*p]);
+ if (len < 4)
+ goto err;
switch (p[1] & 0x1F) {
default:
printf("\t\tUnkn device");
@@ -662,48 +833,275 @@ dump_func_ext(unsigned char *p, int len)
printf("\t\t16550 UART");
break;
}
- printf(", Parity - %s%s%s%s",
- (p[2] & 1) ? "Space," : "",
- (p[2] & 2) ? "Mark," : "",
- (p[2] & 4) ? "Odd," : "",
- (p[2] & 8) ? "Even," : "");
- printf("\n");
+ printf(", Parity - %s%s%s%s\n",
+ (p[2] & 1) ? "Space," : "",
+ (p[2] & 2) ? "Mark," : "",
+ (p[2] & 4) ? "Odd," : "",
+ (p[2] & 8) ? "Even" : "");
+ printf("\t\tData bit - %s%s%s%s Stop bit - %s%s%s\n",
+ (p[3] & 1) ? "5bit," : "",
+ (p[3] & 2) ? "6bit," : "",
+ (p[3] & 4) ? "7bit," : "",
+ (p[3] & 8) ? "8bit," : "",
+ (p[3] & 0x10) ? "1bit," : "",
+ (p[3] & 0x20) ? "1.5bit," : "",
+ (p[3] & 0x40) ? "2bit" : "");
break;
- case 1:
- case 5:
- case 6:
- case 7:
- printf("\tModem interface capabilities:\n");
+ case 1: /* Serial */
+ case 5: /* Data */
+ case 6: /* Fax */
+ case 7: /* Voice */
+ printf("\t%s interface capabilities:\n", type[*p]);
+ if (len < 9)
+ goto err;
break;
- case 2:
+ case 2: /* Data */
printf("\tData modem services available:\n");
break;
- case 9:
- printf("\tFax/modem services available:\n");
+ case 0x13: /* Fax1 */
+ case 0x23: /* Fax2 */
+ case 0x33: /* Fax3 */
+ printf("\tFax%d/modem services available:\n", *p >> 4);
break;
- case 4:
+ case 0x84: /* Voice */
printf("\tVoice services available:\n");
break;
+ err: /* warning */
+ printf("\tWrong length for serial extension tuple\n");
+ return;
}
}
/*
- * print_ext_speed - Print extended speed.
+ * CIS_FUNC_EXT: Dump functional extension tuple.
+ * (Fixed disk card)
*/
-void
-print_ext_speed(unsigned char x, int scale)
+static void
+dump_disk_ext(u_char *p, int len)
{
- static char *mant[] =
- {"Reserved", "1.0", "1.2", "1.3", "1.5", "2.0", "2.5", "3.0",
- "3.5", "4.0", "4.5", "5.0", "5.5", "6.0", "7.0", "8.0"};
- static char *exp[] =
- {"1 ns", "10 ns", "100 ns", "1 us", "10 us", "100 us",
- "1 ms", "10 ms"};
- static char *scale_name[] =
- {"None", "10", "100", "1,000", "10,000", "100,000",
- "1,000,000", "10,000,000"};
+ if (len < 1)
+ return;
+ switch (p[0]) {
+ case 1: /* IDE interface */
+ if (len < 2)
+ goto err;
+ printf("\tDisk interface: %s\n",
+ (p[1] & 1) ? "IDE" : "Undefined");
+ break;
+ case 2: /* Master */
+ case 3: /* Slave */
+ if (len < 3)
+ goto err;
+ printf("\tDisk features: %s, %s%s\n",
+ (p[1] & 0x04) ? "Silicon" : "Rotating",
+ (p[1] & 0x08) ? "Unique, " : "",
+ (p[1] & 0x10) ? "Dual" : "Single");
+ if (p[2] & 0x7f)
+ printf("\t\t%s%s%s%s%s%s%s\n",
+ (p[2] & 0x01) ? "Sleep, " : "",
+ (p[2] & 0x02) ? "Standby, " : "",
+ (p[2] & 0x04) ? "Idle, " : "",
+ (p[2] & 0x08) ? "Low power, " : "",
+ (p[2] & 0x10) ? "Reg inhibit, " : "",
+ (p[2] & 0x20) ? "Index, " : "",
+ (p[2] & 0x40) ? "Iois16" : "");
+ break;
+ err: /* warning */
+ printf("\tWrong length for fixed disk extension tuple\n");
+ return;
+ }
+}
- printf("Speed = %s x %s", mant[(x >> 3) & 0xF], exp[x & 7]);
- if (scale)
- printf(", scaled by %s", scale_name[scale & 7]);
+static void
+print_speed(u_int i)
+{
+ if (i < 1000)
+ printf("%u bits/sec", i);
+ else if (i < 1000000)
+ printf("%u kb/sec", i / 1000);
+ else
+ printf("%u Mb/sec", i / 1000000);
+}
+
+/*
+ * CIS_FUNC_EXT: Dump functional extension tuple.
+ * (Network/LAN adapter)
+ */
+static void
+dump_network_ext(u_char *p, int len)
+{
+ static const char *tech[] = {
+ "Undefined", "ARCnet", "Ethernet", "Token ring",
+ "Localtalk", "FDDI/CDDI", "ATM", "Wireless"
+ };
+ static const char *media[] = {
+ "Undefined", "UTP", "STP", "Thin coax",
+ "THICK coax", "Fiber", "900 MHz", "2.4 GHz",
+ "5.4 GHz", "Diffuse Infrared", "Point to point Infrared"
+ };
+ u_int i = 0;
+
+ if (len < 1)
+ return;
+ switch (p[0]) {
+ case 1: /* Network technology */
+ if (len < 2)
+ goto err;
+ printf("\tNetwork technology: %s\n", tech[p[1] & 7]);
+ break;
+ case 2: /* Network speed */
+ if (len < 5)
+ goto err;
+ printf("\tNetwork speed: ");
+ print_speed(tpl32(p + 1));
+ putchar('\n');
+ break;
+ case 3: /* Network media */
+ if (len < 2)
+ goto err;
+ if (p[1] <= 10)
+ i = p[1];
+ printf("\tNetwork media: %s\n", media[i]);
+ break;
+ case 4: /* Node ID */
+ if (len <= 2 || len < p[1] + 2)
+ goto err;
+ printf("\tNetwork node ID:");
+ for (i = 0; i < p[1]; i++)
+ printf(" %02x", p[i + 2]);
+ putchar('\n');
+ break;
+ case 5: /* Connecter type */
+ if (len < 2)
+ goto err;
+ printf("\tNetwork connector: %s connector standard\n",
+ (p[1] == 0) ? "open" : "closed");
+ break;
+ err: /* warning */
+ printf("\tWrong length for network extension tuple\n");
+ return;
+ }
+}
+
+/*
+ * CIS_LONGLINK_MFC: Long link to next chain for Multi function card
+ */
+static void
+dump_longlink_mfc(u_char *p, int len)
+{
+ u_int i, n = *p++;
+
+ --len;
+ for (i = 0; i < n; i++) {
+ if (len < 5) {
+ printf("\tWrong length for long link MFC tuple\n");
+ return;
+ }
+ printf("\tFunction %d: %s memory, address 0x%x\n",
+ i, (*p ? "common" : "attribute"), tpl32(p + 1));
+ p += 5;
+ len -= 5;
+ }
+}
+
+/*
+ * CIS_DEVICEGEO, CIS_DEVICEGEO_A:
+ * Geometry info for common/attribute memory
+ */
+static void
+dump_device_geo(u_char *p, int len)
+{
+ while (len >= 6) {
+ printf("\twidth = %d, erase = 0x%x, read = 0x%x, write = 0x%x\n"
+ "\t\tpartition = 0x%x, interleave = 0x%x\n",
+ p[0], 1 << (p[1] - 1),
+ 1 << (p[2] - 1), 1 << (p[3] - 1),
+ 1 << (p[4] - 1), 1 << (p[5] - 1));
+ len -= 6;
+ }
+}
+
+/*
+ * CIS_INFO_V2: Print version-2 info
+ */
+static void
+dump_info_v2(u_char *p, int len)
+{
+ if (len < 9) {
+ printf("\tWrong length for version-2 info tuple\n");
+ return;
+ }
+ printf("\tVersion = 0x%x, compliance = 0x%x, dindex = 0x%x\n",
+ p[0], p[1], tpl16(p + 2));
+ printf("\tVspec8 = 0x%x, vspec9 = 0x%x, nhdr = %d\n",
+ p[6], p[7], p[8]);
+ p += 9;
+ len -= 9;
+ if (len <= 1 || *p == 0xff)
+ return;
+ printf("\tVendor = [%.*s]", len, p);
+ while (*p++ && --len > 0);
+ if (len > 1 && *p != 0xff)
+ printf(", info = [%.*s]", len, p);
+ putchar('\n');
+}
+
+/*
+ * CIS_ORG: Organization
+ */
+static void
+dump_org(u_char *p, int len)
+{
+ if (len < 1) {
+ printf("\tWrong length for organization tuple\n");
+ return;
+ }
+ switch (*p) {
+ case 0:
+ printf("\tFilesystem");
+ break;
+ case 1:
+ printf("\tApp specific");
+ break;
+ case 2:
+ printf("\tCode");
+ break;
+ default:
+ if (*p < 0x80)
+ printf("\tReserved");
+ else
+ printf("\tVendor specific");
+ break;
+ }
+ printf(" [%.*s]\n", len - 1, p + 1);
+}
+
+static void
+print_size(u_int i)
+{
+ if (i < 1024)
+ printf("%ubits", i);
+ else if (i < 1024*1024)
+ printf("%ukb", i / 1024);
+ else
+ printf("%uMb", i / (1024*1024));
+}
+
+/*
+ * CIS_BAR: Base address register for CardBus
+ */
+static void
+dump_bar(u_char *p, int len)
+{
+ if (len < 6) {
+ printf("\tWrong length for BAR tuple\n");
+ return;
+ }
+ printf("\tBAR %d: size = ", *p & 7);
+ print_size(tpl32(p + 2));
+ printf(", %s%s%s%s\n",
+ (*p & 0x10) ? "I/O" : "Memory",
+ (*p & 0x20) ? ", Prefetch" : "",
+ (*p & 0x40) ? ", Cacheable" : "",
+ (*p & 0x80) ? ", <1Mb" : "");
}
OpenPOWER on IntegriCloud