115175Snate/* 215284Snate * Copyright (c) 1995 Andrew McRae. All rights reserved. 315284Snate * 415284Snate * Redistribution and use in source and binary forms, with or without 515284Snate * modification, are permitted provided that the following conditions 615284Snate * are met: 715284Snate * 1. Redistributions of source code must retain the above copyright 815284Snate * notice, this list of conditions and the following disclaimer. 915284Snate * 2. Redistributions in binary form must reproduce the above copyright 1015284Snate * notice, this list of conditions and the following disclaimer in the 1115284Snate * documentation and/or other materials provided with the distribution. 1215284Snate * 3. The name of the author may not be used to endorse or promote products 1315284Snate * derived from this software without specific prior written permission. 1415284Snate * 1515284Snate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1615284Snate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1715284Snate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1815284Snate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1915284Snate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2015284Snate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2115284Snate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2215284Snate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2315284Snate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2415284Snate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2510217Sphk */ 2630171Scharnier 2730171Scharnier#ifndef lint 2830171Scharnierstatic const char rcsid[] = 2950479Speter "$FreeBSD: releng/10.3/usr.sbin/dumpcis/printcis.c 250460 2013-05-10 16:41:26Z eadler $"; 3030171Scharnier#endif /* not lint */ 3130171Scharnier 3259656Siwasaki/* 3359656Siwasaki * Code cleanup, bug-fix and extension 3459656Siwasaki * by Tatsumi Hosokawa <hosokawa@mt.cs.keio.ac.jp> 3559656Siwasaki */ 3659656Siwasaki 3759656Siwasaki#include <err.h> 3810217Sphk#include <stdio.h> 3910217Sphk#include <stdlib.h> 4010217Sphk#include <string.h> 4130171Scharnier#include <unistd.h> 4210217Sphk#include <sys/ioctl.h> 4310217Sphk 44188633Simp#include "cis.h" 4510217Sphk#include "readcis.h" 4610217Sphk 4759656Siwasakistatic void dump_config_map(struct tuple *tp); 4859656Siwasakistatic void dump_cis_config(struct tuple *tp); 4959656Siwasakistatic void dump_other_cond(u_char *p, int len); 50185033Simpstatic void dump_device_desc(u_char *p, int len, const char *type); 5159656Siwasakistatic void dump_info_v1(u_char *p, int len); 5259656Siwasakistatic void dump_longlink_mfc(u_char *p, int len); 5359656Siwasakistatic void dump_bar(u_char *p, int len); 5459656Siwasakistatic void dump_device_geo(u_char *p, int len); 5559656Siwasakistatic void dump_func_id(u_char *p); 5659656Siwasakistatic void dump_serial_ext(u_char *p, int len); 5759656Siwasakistatic void dump_disk_ext(u_char *p, int len); 5859656Siwasakistatic void dump_network_ext(u_char *p, int len); 5959656Siwasakistatic void dump_info_v2(u_char *p, int len); 6059656Siwasakistatic void dump_org(u_char *p, int len); 6110217Sphk 6210217Sphkvoid 63185121Simpdumpcis(struct tuple_list *tlist) 6410217Sphk{ 6515175Snate struct tuple *tp; 6615175Snate struct tuple_list *tl; 6715175Snate int count = 0, sz, ad, i; 6859656Siwasaki u_char *p; 6959656Siwasaki int func = 0; 7010217Sphk 71185121Simp for (tl = tlist; tl; tl = tl->next) 7215175Snate for (tp = tl->tuples; tp; tp = tp->next) { 7310217Sphk printf("Tuple #%d, code = 0x%x (%s), length = %d\n", 7415175Snate ++count, tp->code, tuple_name(tp->code), tp->length); 7510217Sphk p = tp->data; 7610217Sphk sz = tp->length; 7710217Sphk ad = 0; 7815175Snate while (sz > 0) { 7910217Sphk printf(" %03x: ", ad); 8010217Sphk for (i = 0; i < ((sz < 16) ? sz : 16); i++) 8110217Sphk printf(" %02x", p[i]); 8210217Sphk printf("\n"); 8310217Sphk sz -= 16; 8410217Sphk p += 16; 8510217Sphk ad += 16; 8615175Snate } 8715175Snate switch (tp->code) { 8810217Sphk default: 8910217Sphk break; 9010217Sphk case CIS_MEM_COMMON: /* 0x01 */ 9110217Sphk dump_device_desc(tp->data, tp->length, "Common"); 9210217Sphk break; 9359656Siwasaki case CIS_CONF_MAP_CB: /* 0x04 */ 9459656Siwasaki dump_config_map(tp); 9559656Siwasaki break; 9659656Siwasaki case CIS_CONFIG_CB: /* 0x05 */ 9759656Siwasaki dump_cis_config(tp); 9859656Siwasaki break; 9959656Siwasaki case CIS_LONGLINK_MFC: /* 0x06 */ 10059656Siwasaki dump_longlink_mfc(tp->data, tp->length); 10159656Siwasaki break; 10259656Siwasaki case CIS_BAR: /* 0x07 */ 10359656Siwasaki dump_bar(tp->data, tp->length); 10459656Siwasaki break; 10510217Sphk case CIS_CHECKSUM: /* 0x10 */ 10659656Siwasaki printf("\tChecksum from offset %d, length %d, value is 0x%x\n", 10759656Siwasaki tpl16(tp->data), 10859656Siwasaki tpl16(tp->data + 2), 10959656Siwasaki tp->data[4]); 11010217Sphk break; 11110217Sphk case CIS_LONGLINK_A: /* 0x11 */ 11210217Sphk printf("\tLong link to attribute memory, address 0x%x\n", 11359656Siwasaki tpl32(tp->data)); 11410217Sphk break; 11510217Sphk case CIS_LONGLINK_C: /* 0x12 */ 11610217Sphk printf("\tLong link to common memory, address 0x%x\n", 11759656Siwasaki tpl32(tp->data)); 11859656Siwasaki break; 11910217Sphk case CIS_INFO_V1: /* 0x15 */ 12010217Sphk dump_info_v1(tp->data, tp->length); 12110217Sphk break; 12210217Sphk case CIS_ALTSTR: /* 0x16 */ 12310217Sphk break; 12410217Sphk case CIS_MEM_ATTR: /* 0x17 */ 12510217Sphk dump_device_desc(tp->data, tp->length, "Attribute"); 12610217Sphk break; 12710217Sphk case CIS_JEDEC_C: /* 0x18 */ 12810217Sphk case CIS_JEDEC_A: /* 0x19 */ 12910217Sphk break; 13010217Sphk case CIS_CONF_MAP: /* 0x1A */ 13110217Sphk dump_config_map(tp); 13210217Sphk break; 13310217Sphk case CIS_CONFIG: /* 0x1B */ 13410217Sphk dump_cis_config(tp); 13510217Sphk break; 13610217Sphk case CIS_DEVICE_OC: /* 0x1C */ 13710217Sphk case CIS_DEVICE_OA: /* 0x1D */ 13859656Siwasaki dump_other_cond(tp->data, tp->length); 13910217Sphk break; 14010217Sphk case CIS_DEVICEGEO: /* 0x1E */ 14110217Sphk case CIS_DEVICEGEO_A: /* 0x1F */ 14259656Siwasaki dump_device_geo(tp->data, tp->length); 14310217Sphk break; 14410217Sphk case CIS_MANUF_ID: /* 0x20 */ 14510217Sphk printf("\tPCMCIA ID = 0x%x, OEM ID = 0x%x\n", 14659656Siwasaki tpl16(tp->data), 14759656Siwasaki tpl16(tp->data + 2)); 14810217Sphk break; 14910217Sphk case CIS_FUNC_ID: /* 0x21 */ 15059656Siwasaki func = tp->data[0]; 15159656Siwasaki dump_func_id(tp->data); 15259656Siwasaki break; 15359656Siwasaki case CIS_FUNC_EXT: /* 0x22 */ 15459656Siwasaki switch (func) { 15510217Sphk case 2: 15659656Siwasaki dump_serial_ext(tp->data, tp->length); 15710217Sphk break; 15810217Sphk case 4: 15959656Siwasaki dump_disk_ext(tp->data, tp->length); 16010217Sphk break; 16110217Sphk case 6: 16259656Siwasaki dump_network_ext(tp->data, tp->length); 16310217Sphk break; 16415175Snate } 16510217Sphk break; 16610217Sphk case CIS_VERS_2: /* 0x40 */ 16759656Siwasaki dump_info_v2(tp->data, tp->length); 16810217Sphk break; 16959656Siwasaki case CIS_ORG: /* 0x46 */ 17059656Siwasaki dump_org(tp->data, tp->length); 17159656Siwasaki break; 17210217Sphk } 17315175Snate } 17410217Sphk} 17515175Snate 17610217Sphk/* 17759656Siwasaki * CIS_CONF_MAP : Dump configuration map tuple. 17859656Siwasaki * CIS_CONF_MAP_CB: Dump configuration map for CardBus 17910217Sphk */ 18059656Siwasakistatic void 18110217Sphkdump_config_map(struct tuple *tp) 18210217Sphk{ 18359656Siwasaki u_char *p = tp->data, x; 18459656Siwasaki int rlen, mlen = 0; 18515175Snate int i; 18610217Sphk 18759656Siwasaki rlen = (p[0] & 3) + 1; 18859656Siwasaki if (tp->code == CIS_CONF_MAP) 18959656Siwasaki mlen = ((p[0] >> 2) & 3) + 1; 19059656Siwasaki if (tp->length < rlen + mlen + 2) { 19159656Siwasaki printf("\tWrong length for configuration map tuple\n"); 19259656Siwasaki return; 19359656Siwasaki } 19459656Siwasaki printf("\tReg len = %d, config register addr = 0x%x, last config = 0x%x\n", 19559656Siwasaki rlen, parse_num(rlen | 0x10, p + 2, &p, 0), p[1]); 19659656Siwasaki if (mlen) { 19710217Sphk printf("\tRegisters: "); 19859656Siwasaki for (i = 0; i < mlen; i++, p++) { 19959656Siwasaki for (x = 0x1; x; x <<= 1) 20059656Siwasaki printf("%c", x & *p ? 'X' : '-'); 20159656Siwasaki putchar(' '); 20259656Siwasaki } 20315175Snate } 20459656Siwasaki i = tp->length - (rlen + mlen + 2); 20559656Siwasaki if (i) { 20659656Siwasaki if (!mlen) 20759656Siwasaki putchar('\t'); 20859656Siwasaki printf("%d bytes in subtuples", i); 20959656Siwasaki } 21059656Siwasaki if (mlen || i) 21159656Siwasaki putchar('\n'); 21210217Sphk} 21315175Snate 21410217Sphk/* 21559656Siwasaki * Dump power descriptor. 21659656Siwasaki * call from dump_cis_config() 21710217Sphk */ 21859656Siwasakistatic int 21959656Siwasakiprint_pwr_desc(u_char *p) 22059656Siwasaki{ 22159656Siwasaki int len = 1, i; 22259656Siwasaki u_char mask; 223185033Simp const char **expp; 224185033Simp static const char *pname[] = 22559656Siwasaki {"Nominal operating supply voltage", 22659656Siwasaki "Minimum operating supply voltage", 22759656Siwasaki "Maximum operating supply voltage", 22859656Siwasaki "Continuous supply current", 22959656Siwasaki "Max current average over 1 second", 23059656Siwasaki "Max current average over 10 ms", 23159656Siwasaki "Power down supply current", 23259656Siwasaki "Reserved" 23359656Siwasaki }; 234185033Simp static const char *vexp[] = 23559656Siwasaki {"10uV", "100uV", "1mV", "10mV", "100mV", "1V", "10V", "100V"}; 236185033Simp static const char *cexp[] = 23759656Siwasaki {"10nA", "1uA", "10uA", "100uA", "1mA", "10mA", "100mA", "1A"}; 238185033Simp static const char *mant[] = 23959656Siwasaki {"1", "1.2", "1.3", "1.5", "2", "2.5", "3", "3.5", "4", "4.5", 24059656Siwasaki "5", "5.5", "6", "7", "8", "9"}; 24159656Siwasaki 24259656Siwasaki mask = *p++; 24359656Siwasaki expp = vexp; 24459656Siwasaki for (i = 0; i < 8; i++) 24559656Siwasaki if (mask & (1 << i)) { 24659656Siwasaki len++; 24759656Siwasaki if (i >= 3) 24859656Siwasaki expp = cexp; 24959656Siwasaki printf("\t\t%s: ", pname[i]); 25059656Siwasaki printf("%s x %s", 25159656Siwasaki mant[(*p >> 3) & 0xF], 25259656Siwasaki expp[*p & 7]); 25359656Siwasaki while (*p & 0x80) { 25459656Siwasaki len++; 25559656Siwasaki p++; 25659656Siwasaki printf(", ext = 0x%x", *p); 25759656Siwasaki } 25859656Siwasaki printf("\n"); 25959656Siwasaki p++; 26059656Siwasaki } 26159656Siwasaki return (len); 26259656Siwasaki} 26359656Siwasaki 26459656Siwasaki/* 26559656Siwasaki * print_ext_speed - Print extended speed. 26659656Siwasaki * call from dump_cis_config(), dump_device_desc() 26759656Siwasaki */ 26859656Siwasakistatic void 26959656Siwasakiprint_ext_speed(u_char x, int scale) 27059656Siwasaki{ 271185033Simp static const char *mant[] = 27259656Siwasaki {"Reserved", "1.0", "1.2", "1.3", "1.5", "2.0", "2.5", "3.0", 27359656Siwasaki "3.5", "4.0", "4.5", "5.0", "5.5", "6.0", "7.0", "8.0"}; 274185033Simp static const char *exp[] = 27559656Siwasaki {"1 ns", "10 ns", "100 ns", "1 us", "10 us", "100 us", 27659656Siwasaki "1 ms", "10 ms"}; 277185033Simp static const char *scale_name[] = 27859656Siwasaki {"None", "10", "100", "1,000", "10,000", "100,000", 27959656Siwasaki "1,000,000", "10,000,000"}; 28059656Siwasaki 28159656Siwasaki printf("Speed = %s x %s", mant[(x >> 3) & 0xF], exp[x & 7]); 28259656Siwasaki if (scale) 28359656Siwasaki printf(", scaled by %s", scale_name[scale & 7]); 28459656Siwasaki} 28559656Siwasaki 28659656Siwasaki/* 28759656Siwasaki * Print variable length value. 28859656Siwasaki * call from print_io_map(), print_mem_map() 28959656Siwasaki */ 29059656Siwasakistatic int 291185033Simpprint_num(int sz, const char *fmt, u_char *p, int ofs) 29259656Siwasaki{ 29359656Siwasaki switch (sz) { 29459656Siwasaki case 0: 29559656Siwasaki case 0x10: 29659656Siwasaki return 0; 29759656Siwasaki case 1: 29859656Siwasaki case 0x11: 29959656Siwasaki printf(fmt, *p + ofs); 30059656Siwasaki return 1; 30159656Siwasaki case 2: 30259656Siwasaki case 0x12: 30359656Siwasaki printf(fmt, tpl16(p) + ofs); 30459656Siwasaki return 2; 30559656Siwasaki case 0x13: 30659656Siwasaki printf(fmt, tpl24(p) + ofs); 30759656Siwasaki return 3; 30859656Siwasaki case 3: 30959656Siwasaki case 0x14: 31059656Siwasaki printf(fmt, tpl32(p) + ofs); 31159656Siwasaki return 4; 31259656Siwasaki } 31359656Siwasaki errx(1, "print_num(0x%x): Illegal arguments", sz); 31459656Siwasaki/*NOTREACHED*/ 31559656Siwasaki} 31659656Siwasaki 31759656Siwasaki/* 31859656Siwasaki * Print I/O mapping sub-tuple. 31959656Siwasaki * call from dump_cis_config() 32059656Siwasaki */ 32159656Siwasakistatic u_char * 32259656Siwasakiprint_io_map(u_char *p, u_char *q) 32359656Siwasaki{ 32459656Siwasaki int i, j; 32559656Siwasaki u_char c; 32659656Siwasaki 32759656Siwasaki if (q <= p) 32859656Siwasaki goto err; 32959656Siwasaki if (CIS_IO_ADDR(*p)) /* I/O address line */ 33059656Siwasaki printf("\tCard decodes %d address lines", 33159656Siwasaki CIS_IO_ADDR(*p)); 33259656Siwasaki else 33359656Siwasaki printf("\tCard provides address decode"); 33459656Siwasaki 33559656Siwasaki /* 8/16 bit I/O */ 33659656Siwasaki switch (*p & (CIS_IO_8BIT | CIS_IO_16BIT)) { 33759656Siwasaki case CIS_IO_8BIT: 33859656Siwasaki printf(", 8 Bit I/O only"); 33959656Siwasaki break; 34059656Siwasaki case CIS_IO_16BIT: 34159656Siwasaki printf(", limited 8/16 Bit I/O"); 34259656Siwasaki break; 34359656Siwasaki case (CIS_IO_8BIT | CIS_IO_16BIT): 34459656Siwasaki printf(", full 8/16 Bit I/O"); 34559656Siwasaki break; 34659656Siwasaki } 34759656Siwasaki putchar('\n'); 34859656Siwasaki 34959656Siwasaki /* I/O block sub-tuple exist */ 35059656Siwasaki if (*p++ & CIS_IO_RANGE) { 35159656Siwasaki if (q <= p) 35259656Siwasaki goto err; 35359656Siwasaki c = *p++; 35459656Siwasaki /* calculate byte length */ 35559656Siwasaki j = CIS_IO_ADSZ(c) + CIS_IO_BLKSZ(c); 35659656Siwasaki if (CIS_IO_ADSZ(c) == 3) 35759656Siwasaki j++; 35859656Siwasaki if (CIS_IO_BLKSZ(c) == 3) 35959656Siwasaki j++; 36059656Siwasaki /* number of I/O block sub-tuples */ 36159656Siwasaki for (i = 0; i <= CIS_IO_BLKS(c); i++) { 36259656Siwasaki if (q - p < j) 36359656Siwasaki goto err; 36459656Siwasaki printf("\t\tI/O address # %d: ", i + 1); 36559656Siwasaki /* start block address */ 36659656Siwasaki p += print_num(CIS_IO_ADSZ(c), 36759656Siwasaki "block start = 0x%x", p, 0); 36859656Siwasaki /* block size */ 36959656Siwasaki p += print_num(CIS_IO_BLKSZ(c), 37059656Siwasaki " block length = 0x%x", p, 1); 37159656Siwasaki putchar('\n'); 37259656Siwasaki } 37359656Siwasaki } 37459656Siwasaki return p; 37559656Siwasaki 37659656Siwasaki err: /* warning */ 37759656Siwasaki printf("\tWrong length for I/O mapping sub-tuple\n"); 37859656Siwasaki return p; 37959656Siwasaki} 38059656Siwasaki 38159656Siwasaki/* 38259656Siwasaki * Print IRQ sub-tuple. 38359656Siwasaki * call from dump_cis_config() 38459656Siwasaki */ 38559656Siwasakistatic u_char * 38659656Siwasakiprint_irq_map(u_char *p, u_char *q) 38759656Siwasaki{ 38859656Siwasaki int i, j; 38959656Siwasaki u_char c; 39059656Siwasaki 39159656Siwasaki if (q <= p) 39259656Siwasaki goto err; 39359656Siwasaki printf("\t\tIRQ modes:"); 39459656Siwasaki c = ' '; 39559656Siwasaki if (*p & CIS_IRQ_LEVEL) { /* Level triggered interrupts */ 39659656Siwasaki printf(" Level"); 39759656Siwasaki c = ','; 39859656Siwasaki } 39959656Siwasaki if (*p & CIS_IRQ_PULSE) { /* Pulse triggered requests */ 40059656Siwasaki printf("%c Pulse", c); 40159656Siwasaki c = ','; 40259656Siwasaki } 40359656Siwasaki if (*p & CIS_IRQ_SHARING) /* Interrupt sharing */ 40459656Siwasaki printf("%c Shared", c); 40559656Siwasaki putchar('\n'); 40659656Siwasaki 40759656Siwasaki /* IRQ mask values exist */ 40859656Siwasaki if (*p & CIS_IRQ_MASK) { 40959656Siwasaki if (q - p < 3) 41059656Siwasaki goto err; 41159656Siwasaki i = tpl16(p + 1); /* IRQ mask */ 41259656Siwasaki printf("\t\tIRQs: "); 41359656Siwasaki if (*p & 1) 41459656Siwasaki printf(" NMI"); 41559656Siwasaki if (*p & 0x2) 41659656Siwasaki printf(" IOCK"); 41759656Siwasaki if (*p & 0x4) 41859656Siwasaki printf(" BERR"); 41959656Siwasaki if (*p & 0x8) 42059656Siwasaki printf(" VEND"); 42159656Siwasaki for (j = 0; j < 16; j++) 42259656Siwasaki if (i & (1 << j)) 42359656Siwasaki printf(" %d", j); 42459656Siwasaki putchar('\n'); 42559656Siwasaki p += 3; 42659656Siwasaki } else { 42759656Siwasaki printf("\t\tIRQ level = %d\n", CIS_IRQ_IRQN(*p)); 42859656Siwasaki p++; 42959656Siwasaki } 43059656Siwasaki return p; 43159656Siwasaki 43259656Siwasaki err: /* warning */ 43359656Siwasaki printf("\tWrong length for IRQ sub-tuple\n"); 43459656Siwasaki return p; 43559656Siwasaki} 43659656Siwasaki 43759656Siwasaki/* 43859656Siwasaki * Print memory map sub-tuple. 43959656Siwasaki * call from dump_cis_config() 44059656Siwasaki */ 44159656Siwasakistatic u_char * 44259656Siwasakiprint_mem_map(u_char feat, u_char *p, u_char *q) 44359656Siwasaki{ 44459656Siwasaki int i, j; 44559656Siwasaki u_char c; 44659656Siwasaki 44759656Siwasaki switch (CIS_FEAT_MEMORY(feat)) { 44859656Siwasaki 44959656Siwasaki case CIS_FEAT_MEM_NONE: /* No memory block */ 45059656Siwasaki break; 45159656Siwasaki case CIS_FEAT_MEM_LEN: /* Specify memory length */ 45259656Siwasaki if (q - p < 2) 45359656Siwasaki goto err; 45459656Siwasaki printf("\tMemory space length = 0x%x\n", tpl16(p)); 45559656Siwasaki p += 2; 45659656Siwasaki break; 45759656Siwasaki case CIS_FEAT_MEM_ADDR: /* Memory address and length */ 45859656Siwasaki if (q - p < 4) 45959656Siwasaki goto err; 46059656Siwasaki printf("\tMemory space address = 0x%x, length = 0x%x\n", 46159656Siwasaki tpl16(p + 2), tpl16(p)); 46259656Siwasaki p += 4; 46359656Siwasaki break; 46459656Siwasaki case CIS_FEAT_MEM_WIN: /* Memory descriptors. */ 46559656Siwasaki if (q <= p) 46659656Siwasaki goto err; 46759656Siwasaki c = *p++; 46859656Siwasaki /* calculate byte length */ 46959656Siwasaki j = CIS_MEM_LENSZ(c) + CIS_MEM_ADDRSZ(c); 47059656Siwasaki if (c & CIS_MEM_HOST) 47159656Siwasaki j += CIS_MEM_ADDRSZ(c); 47259656Siwasaki /* number of memory block */ 47359656Siwasaki for (i = 0; i < CIS_MEM_WINS(c); i++) { 47459656Siwasaki if (q - p < j) 47559656Siwasaki goto err; 47659656Siwasaki printf("\tMemory descriptor %d\n\t\t", i + 1); 47759656Siwasaki /* memory length */ 47859656Siwasaki p += print_num(CIS_MEM_LENSZ(c) | 0x10, 47959656Siwasaki " blk length = 0x%x00", p, 0); 48059656Siwasaki /* card address */ 48159656Siwasaki p += print_num(CIS_MEM_ADDRSZ(c) | 0x10, 48259656Siwasaki " card addr = 0x%x00", p, 0); 48359656Siwasaki if (c & CIS_MEM_HOST) /* Host address value exist */ 48459656Siwasaki p += print_num(CIS_MEM_ADDRSZ(c) | 0x10, 48559656Siwasaki " host addr = 0x%x00", p, 0); 48659656Siwasaki putchar('\n'); 48759656Siwasaki } 48859656Siwasaki break; 48959656Siwasaki } 49059656Siwasaki return p; 49159656Siwasaki 49259656Siwasaki err: /* warning */ 49359656Siwasaki printf("\tWrong length for memory mapping sub-tuple\n"); 49459656Siwasaki return p; 49559656Siwasaki} 49659656Siwasaki 49759656Siwasaki/* 49859656Siwasaki * CIS_CONFIG : Dump a config entry. 49959656Siwasaki * CIS_CONFIG_CB: Dump a configuration entry for CardBus 50059656Siwasaki */ 50159656Siwasakistatic void 50210217Sphkdump_cis_config(struct tuple *tp) 50310217Sphk{ 50459656Siwasaki u_char *p, *q, feat; 50515175Snate int i, j; 50615175Snate char c; 50710217Sphk 50810217Sphk p = tp->data; 50959656Siwasaki q = p + tp->length; 51010217Sphk printf("\tConfig index = 0x%x%s\n", *p & 0x3F, 51159656Siwasaki *p & 0x40 ? "(default)" : ""); 51259656Siwasaki 51359656Siwasaki /* Interface byte exists */ 51459656Siwasaki if (tp->code == CIS_CONFIG && (*p & 0x80)) { 51510217Sphk p++; 51610217Sphk printf("\tInterface byte = 0x%x ", *p); 51759656Siwasaki switch (*p & 0xF) { /* Interface type */ 51810217Sphk default: 51910217Sphk printf("(reserved)"); 52010217Sphk break; 52110217Sphk case 0: 52210217Sphk printf("(memory)"); 52310217Sphk break; 52410217Sphk case 1: 52510217Sphk printf("(I/O)"); 52610217Sphk break; 52710217Sphk case 4: 52810217Sphk case 5: 52910217Sphk case 6: 53010217Sphk case 7: 53110217Sphk case 8: 53210217Sphk printf("(custom)"); 53310217Sphk break; 53415175Snate } 53510217Sphk c = ' '; 53659656Siwasaki if (*p & 0x10) { /* Battery voltage detect */ 53710217Sphk printf(" BVD1/2 active"); 53810217Sphk c = ','; 53915175Snate } 54059656Siwasaki if (*p & 0x20) { /* Write protect active */ 54110217Sphk printf("%c card WP active", c); /* Write protect */ 54210217Sphk c = ','; 54315175Snate } 54459656Siwasaki if (*p & 0x40) { /* RdyBsy active bit */ 54510217Sphk printf("%c +RDY/-BSY active", c); 54610217Sphk c = ','; 54715175Snate } 54859656Siwasaki if (*p & 0x80) /* Wait signal required */ 54910217Sphk printf("%c wait signal supported", c); 55010217Sphk printf("\n"); 55115175Snate } 55259656Siwasaki 55359656Siwasaki /* features byte */ 55410217Sphk p++; 55510217Sphk feat = *p++; 55659656Siwasaki 55759656Siwasaki /* Power structure sub-tuple */ 55859656Siwasaki switch (CIS_FEAT_POWER(feat)) { /* Power sub-tuple(s) exists */ 55910217Sphk case 0: 56010217Sphk break; 56110217Sphk case 1: 56210217Sphk printf("\tVcc pwr:\n"); 56359656Siwasaki p += print_pwr_desc(p); 56410217Sphk break; 56510217Sphk case 2: 56610217Sphk printf("\tVcc pwr:\n"); 56759656Siwasaki p += print_pwr_desc(p); 56810217Sphk printf("\tVpp pwr:\n"); 56959656Siwasaki p += print_pwr_desc(p); 57010217Sphk break; 57110217Sphk case 3: 57210217Sphk printf("\tVcc pwr:\n"); 57359656Siwasaki p += print_pwr_desc(p); 57410217Sphk printf("\tVpp1 pwr:\n"); 57559656Siwasaki p += print_pwr_desc(p); 57610217Sphk printf("\tVpp2 pwr:\n"); 57759656Siwasaki p += print_pwr_desc(p); 57810217Sphk break; 57915175Snate } 58059656Siwasaki 58159656Siwasaki /* Timing sub-tuple */ 58259656Siwasaki if (tp->code == CIS_CONFIG && 58359656Siwasaki (feat & CIS_FEAT_TIMING)) { /* Timing sub-tuple exists */ 58459656Siwasaki i = *p++; 58559656Siwasaki j = CIS_WAIT_SCALE(i); 58659656Siwasaki if (j != 3) { 58710217Sphk printf("\tWait scale "); 58859656Siwasaki print_ext_speed(*p++, j); 58910217Sphk printf("\n"); 59015175Snate } 59159656Siwasaki j = CIS_READY_SCALE(i); 59215175Snate if (j != 7) { 59310217Sphk printf("\tRDY/BSY scale "); 59459656Siwasaki print_ext_speed(*p++, j); 59510217Sphk printf("\n"); 59610217Sphk } 59759656Siwasaki j = CIS_RESERVED_SCALE(i); 59859656Siwasaki if (j != 7) { 59959656Siwasaki printf("\tExternal scale "); 60059656Siwasaki print_ext_speed(*p++, j); 60159656Siwasaki printf("\n"); 60259656Siwasaki } 60315175Snate } 60459656Siwasaki 60559656Siwasaki /* I/O mapping sub-tuple */ 60659656Siwasaki if (feat & CIS_FEAT_I_O) { /* I/O space sub-tuple exists */ 60759656Siwasaki if (tp->code == CIS_CONFIG) 60859656Siwasaki p = print_io_map(p, q); 60959656Siwasaki else { /* CIS_CONFIG_CB */ 61059656Siwasaki printf("\tI/O base:"); 61159656Siwasaki for (i = 0; i < 8; i++) 61259656Siwasaki if (*p & (1 << i)) 61359656Siwasaki printf(" %d", i); 61459656Siwasaki putchar('\n'); 61510217Sphk p++; 61610217Sphk } 61715175Snate } 61815175Snate 61959656Siwasaki /* IRQ descriptor sub-tuple */ 62059656Siwasaki if (feat & CIS_FEAT_IRQ) /* IRQ sub-tuple exists */ 62159656Siwasaki p = print_irq_map(p, q); 62259656Siwasaki 62359656Siwasaki /* Memory map sub-tuple */ 62459656Siwasaki if (CIS_FEAT_MEMORY(feat)) { /* Memory space sub-tuple(s) exists */ 62559656Siwasaki if (tp->code == CIS_CONFIG) 62659656Siwasaki p = print_mem_map(feat, p, q); 62759656Siwasaki else { /* CIS_CONFIG_CB */ 62859656Siwasaki printf("\tMemory base:"); 62959656Siwasaki for (i = 0; i < 8; i++) 63059656Siwasaki if (*p & (1 << i)) 63159656Siwasaki printf(" %d", i); 63259656Siwasaki putchar('\n'); 63310217Sphk p++; 63410217Sphk } 63515175Snate } 63615175Snate 63759656Siwasaki /* Misc sub-tuple */ 63859656Siwasaki if (feat & CIS_FEAT_MISC) { /* Miscellaneous sub-tuple exists */ 63959656Siwasaki if (tp->code == CIS_CONFIG) { 64059656Siwasaki printf("\tMax twin cards = %d\n", *p & 7); 64159656Siwasaki printf("\tMisc attr:%s%s%s", 64259656Siwasaki (*p & 8) ? " (Audio-BVD2)" : "", 64359656Siwasaki (*p & 0x10) ? " (Read-only)" : "", 64459656Siwasaki (*p & 0x20) ? " (Power down supported)" : ""); 64559656Siwasaki if (*p++ & 0x80) { 64659656Siwasaki printf(" (Ext byte = 0x%x)", *p); 64759656Siwasaki p++; 64815175Snate } 64959656Siwasaki putchar('\n'); 65059656Siwasaki } 65159656Siwasaki else { /* CIS_CONFIG_CB */ 65259656Siwasaki printf("\tMisc attr:"); 65359656Siwasaki printf("%s%s%s%s%s%s%s", 65459656Siwasaki (*p & 1) ? " (Master)" : "", 65559656Siwasaki (*p & 2) ? " (Invalidate)" : "", 65659656Siwasaki (*p & 4) ? " (VGA palette)" : "", 65759656Siwasaki (*p & 8) ? " (Parity)" : "", 65859656Siwasaki (*p & 0x10) ? " (Wait)" : "", 65959656Siwasaki (*p & 0x20) ? " (Serr)" : "", 66059656Siwasaki (*p & 0x40) ? " (Fast back)" : ""); 66159656Siwasaki if (*p++ & 0x80) { 66259656Siwasaki printf("%s%s", 66359656Siwasaki (*p & 1) ? " (Binary audio)" : "", 66459656Siwasaki (*p & 2) ? " (pwm audio)" : ""); 66559656Siwasaki p++; 66615175Snate } 66759656Siwasaki putchar('\n'); 66815175Snate } 66915175Snate } 67010217Sphk} 67115175Snate 67210217Sphk/* 67359656Siwasaki * CIS_DEVICE_OC, CIS_DEVICE_OA: 67459656Siwasaki * Dump other conditions for common/attribute memory 67510217Sphk */ 67659656Siwasakistatic void 67759656Siwasakidump_other_cond(u_char *p, int len) 67810217Sphk{ 67959656Siwasaki if (p[0] && len > 0) { 68010217Sphk printf("\t"); 68110217Sphk if (p[0] & 1) 68210217Sphk printf("(MWAIT)"); 68310217Sphk if (p[0] & 2) 68410217Sphk printf(" (3V card)"); 68510217Sphk if (p[0] & 0x80) 68610217Sphk printf(" (Extension bytes follow)"); 68710217Sphk printf("\n"); 68815175Snate } 68910217Sphk} 69015175Snate 69110217Sphk/* 69259656Siwasaki * CIS_MEM_COMMON, CIS_MEM_ATTR: 69359656Siwasaki * Common / Attribute memory descripter 69410217Sphk */ 69559656Siwasakistatic void 696185033Simpdump_device_desc(u_char *p, int len, const char *type) 69710217Sphk{ 698185033Simp static const char *un_name[] = 69915175Snate {"512b", "2Kb", "8Kb", "32Kb", "128Kb", "512Kb", "2Mb", "reserved"}; 700185033Simp static const char *speed[] = 70115175Snate {"No speed", "250nS", "200nS", "150nS", 70215175Snate "100nS", "Reserved", "Reserved"}; 703185033Simp static const char *dev[] = 70415175Snate {"No device", "Mask ROM", "OTPROM", "UV EPROM", 70515175Snate "EEPROM", "FLASH EEPROM", "SRAM", "DRAM", 70615175Snate "Reserved", "Reserved", "Reserved", "Reserved", 70715175Snate "Reserved", "Function specific", "Extended", 70815175Snate "Reserved"}; 70915175Snate int count = 0; 71010217Sphk 71115175Snate while (*p != 0xFF && len > 0) { 71259656Siwasaki u_char x; 71310217Sphk 71410217Sphk x = *p++; 71510217Sphk len -= 2; 71610217Sphk if (count++ == 0) 71710217Sphk printf("\t%s memory device information:\n", type); 71810217Sphk printf("\t\tDevice number %d, type %s, WPS = %s\n", 71915175Snate count, dev[x >> 4], (x & 0x8) ? "ON" : "OFF"); 72015175Snate if ((x & 7) == 7) { 72110217Sphk len--; 72215175Snate if (*p) { 72310217Sphk printf("\t\t"); 72476341Sdmlb print_ext_speed(*p, 0); 72515175Snate while (*p & 0x80) { 72610217Sphk p++; 72710217Sphk len--; 72810217Sphk } 72915175Snate } 73010217Sphk p++; 73115175Snate } else 73210217Sphk printf("\t\tSpeed = %s", speed[x & 7]); 73310217Sphk printf(", Memory block size = %s, %d units\n", 73415175Snate un_name[*p & 7], (*p >> 3) + 1); 73510217Sphk p++; 73615175Snate } 73710217Sphk} 73815175Snate 73910217Sphk/* 74059656Siwasaki * CIS_INFO_V1: Print version-1 info 74110217Sphk */ 74259656Siwasakistatic void 74359656Siwasakidump_info_v1(u_char *p, int len) 74410217Sphk{ 74559656Siwasaki if (len < 2) { 74659656Siwasaki printf("\tWrong length for version-1 info tuple\n"); 74759656Siwasaki return; 74859656Siwasaki } 74910217Sphk printf("\tVersion = %d.%d", p[0], p[1]); 75010217Sphk p += 2; 75159656Siwasaki len -= 2; 75259656Siwasaki if (len > 1 && *p != 0xff) { 75359656Siwasaki printf(", Manuf = [%s]", p); 75459656Siwasaki while (*p++ && --len > 0); 75559656Siwasaki } 75659656Siwasaki if (len > 1 && *p != 0xff) { 75759656Siwasaki printf(", card vers = [%s]", p); 75859656Siwasaki while (*p++ && --len > 0); 75959656Siwasaki } else { 76059656Siwasaki printf("\n\tWrong length for version-1 info tuple\n"); 76144701Simp return; 76244701Simp } 76359656Siwasaki putchar('\n'); 76459656Siwasaki if (len > 1 && *p != 0xff) { 76559656Siwasaki printf("\tAddit. info = [%.*s]", len, p); 76659656Siwasaki while (*p++ && --len > 0); 76759656Siwasaki if (len > 1 && *p != 0xff) 76859656Siwasaki printf(",[%.*s]", len, p); 76959656Siwasaki putchar('\n'); 77059656Siwasaki } 77110217Sphk} 77215175Snate 77310217Sphk/* 77459656Siwasaki * CIS_FUNC_ID: Functional ID 77510217Sphk */ 77659656Siwasakistatic void 77759656Siwasakidump_func_id(u_char *p) 77810217Sphk{ 779185033Simp static const char *id[] = { 78059656Siwasaki "Multifunction card", 78159656Siwasaki "Memory card", 78259656Siwasaki "Serial port/modem", 78359656Siwasaki "Parallel port", 78459656Siwasaki "Fixed disk card", 78559656Siwasaki "Video adapter", 78659656Siwasaki "Network/LAN adapter", 78759656Siwasaki "AIMS", 78859656Siwasaki "SCSI card", 78959656Siwasaki "Security" 79059656Siwasaki }; 79159656Siwasaki 79259656Siwasaki printf("\t%s%s%s\n", 79359656Siwasaki (*p <= 9) ? id[*p] : "Unknown function", 79459656Siwasaki (p[1] & 1) ? " - POST initialize" : "", 79559656Siwasaki (p[1] & 2) ? " - Card has ROM" : ""); 79659656Siwasaki} 79759656Siwasaki 79859656Siwasaki/* 79959656Siwasaki * CIS_FUNC_EXT: Dump functional extension tuple. 80059656Siwasaki * (Serial port/modem) 80159656Siwasaki */ 80259656Siwasakistatic void 80359656Siwasakidump_serial_ext(u_char *p, int len) 80459656Siwasaki{ 805185033Simp static const char *type[] = { 80659656Siwasaki "", "Modem", "Data", "Fax", "Voice", "Data modem", 80759656Siwasaki "Fax/modem", "Voice", " (Data)", " (Fax)", " (Voice)" 80859656Siwasaki }; 80959656Siwasaki 81059656Siwasaki if (len < 1) 81110217Sphk return; 81215175Snate switch (p[0]) { 81359656Siwasaki case 0: /* Serial */ 81459656Siwasaki case 8: /* Data */ 81559656Siwasaki case 9: /* Fax */ 81659656Siwasaki case 10: /* Voice */ 81759656Siwasaki printf("\tSerial interface extension:%s\n", type[*p]); 81859656Siwasaki if (len < 4) 81959656Siwasaki goto err; 82015175Snate switch (p[1] & 0x1F) { 82110217Sphk default: 822185033Simp printf("\t\tUnknown device"); 82310217Sphk break; 82410217Sphk case 0: 82510217Sphk printf("\t\t8250 UART"); 82610217Sphk break; 82710217Sphk case 1: 82810217Sphk printf("\t\t16450 UART"); 82910217Sphk break; 83010217Sphk case 2: 83110217Sphk printf("\t\t16550 UART"); 83210217Sphk break; 83315175Snate } 83459656Siwasaki printf(", Parity - %s%s%s%s\n", 83559656Siwasaki (p[2] & 1) ? "Space," : "", 83659656Siwasaki (p[2] & 2) ? "Mark," : "", 83759656Siwasaki (p[2] & 4) ? "Odd," : "", 83859656Siwasaki (p[2] & 8) ? "Even" : ""); 83959656Siwasaki printf("\t\tData bit - %s%s%s%s Stop bit - %s%s%s\n", 84059656Siwasaki (p[3] & 1) ? "5bit," : "", 84159656Siwasaki (p[3] & 2) ? "6bit," : "", 84259656Siwasaki (p[3] & 4) ? "7bit," : "", 84359656Siwasaki (p[3] & 8) ? "8bit," : "", 84459656Siwasaki (p[3] & 0x10) ? "1bit," : "", 84559656Siwasaki (p[3] & 0x20) ? "1.5bit," : "", 84659656Siwasaki (p[3] & 0x40) ? "2bit" : ""); 84710217Sphk break; 84859656Siwasaki case 1: /* Serial */ 84959656Siwasaki case 5: /* Data */ 85059656Siwasaki case 6: /* Fax */ 85159656Siwasaki case 7: /* Voice */ 85259656Siwasaki printf("\t%s interface capabilities:\n", type[*p]); 85359656Siwasaki if (len < 9) 85459656Siwasaki goto err; 85510217Sphk break; 85659656Siwasaki case 2: /* Data */ 85710217Sphk printf("\tData modem services available:\n"); 85810217Sphk break; 85959656Siwasaki case 0x13: /* Fax1 */ 86059656Siwasaki case 0x23: /* Fax2 */ 86159656Siwasaki case 0x33: /* Fax3 */ 86259656Siwasaki printf("\tFax%d/modem services available:\n", *p >> 4); 86310217Sphk break; 86459656Siwasaki case 0x84: /* Voice */ 86510217Sphk printf("\tVoice services available:\n"); 86610217Sphk break; 86759656Siwasaki err: /* warning */ 86859656Siwasaki printf("\tWrong length for serial extension tuple\n"); 86959656Siwasaki return; 87015175Snate } 87110217Sphk} 87215175Snate 87310217Sphk/* 87459656Siwasaki * CIS_FUNC_EXT: Dump functional extension tuple. 87559656Siwasaki * (Fixed disk card) 87610217Sphk */ 87759656Siwasakistatic void 87859656Siwasakidump_disk_ext(u_char *p, int len) 87910217Sphk{ 88059656Siwasaki if (len < 1) 88159656Siwasaki return; 88259656Siwasaki switch (p[0]) { 88359656Siwasaki case 1: /* IDE interface */ 88459656Siwasaki if (len < 2) 88559656Siwasaki goto err; 88659656Siwasaki printf("\tDisk interface: %s\n", 88759656Siwasaki (p[1] & 1) ? "IDE" : "Undefined"); 88859656Siwasaki break; 88959656Siwasaki case 2: /* Master */ 89059656Siwasaki case 3: /* Slave */ 89159656Siwasaki if (len < 3) 89259656Siwasaki goto err; 89359656Siwasaki printf("\tDisk features: %s, %s%s\n", 89459656Siwasaki (p[1] & 0x04) ? "Silicon" : "Rotating", 89559656Siwasaki (p[1] & 0x08) ? "Unique, " : "", 89659656Siwasaki (p[1] & 0x10) ? "Dual" : "Single"); 89759656Siwasaki if (p[2] & 0x7f) 89859656Siwasaki printf("\t\t%s%s%s%s%s%s%s\n", 89959656Siwasaki (p[2] & 0x01) ? "Sleep, " : "", 90059656Siwasaki (p[2] & 0x02) ? "Standby, " : "", 90159656Siwasaki (p[2] & 0x04) ? "Idle, " : "", 90259656Siwasaki (p[2] & 0x08) ? "Low power, " : "", 90359656Siwasaki (p[2] & 0x10) ? "Reg inhibit, " : "", 90459656Siwasaki (p[2] & 0x20) ? "Index, " : "", 90559656Siwasaki (p[2] & 0x40) ? "Iois16" : ""); 90659656Siwasaki break; 90759656Siwasaki err: /* warning */ 90859656Siwasaki printf("\tWrong length for fixed disk extension tuple\n"); 90959656Siwasaki return; 91059656Siwasaki } 91159656Siwasaki} 91210217Sphk 91359656Siwasakistatic void 91459656Siwasakiprint_speed(u_int i) 91559656Siwasaki{ 91659656Siwasaki if (i < 1000) 91759656Siwasaki printf("%u bits/sec", i); 91859656Siwasaki else if (i < 1000000) 91959656Siwasaki printf("%u kb/sec", i / 1000); 92059656Siwasaki else 92159656Siwasaki printf("%u Mb/sec", i / 1000000); 92210217Sphk} 92359656Siwasaki 92459656Siwasaki/* 92559656Siwasaki * CIS_FUNC_EXT: Dump functional extension tuple. 92659656Siwasaki * (Network/LAN adapter) 92759656Siwasaki */ 92859656Siwasakistatic void 92959656Siwasakidump_network_ext(u_char *p, int len) 93059656Siwasaki{ 93159656Siwasaki static const char *tech[] = { 93259656Siwasaki "Undefined", "ARCnet", "Ethernet", "Token ring", 93359656Siwasaki "Localtalk", "FDDI/CDDI", "ATM", "Wireless" 93459656Siwasaki }; 93559656Siwasaki static const char *media[] = { 93659656Siwasaki "Undefined", "UTP", "STP", "Thin coax", 93759656Siwasaki "THICK coax", "Fiber", "900 MHz", "2.4 GHz", 93859656Siwasaki "5.4 GHz", "Diffuse Infrared", "Point to point Infrared" 93959656Siwasaki }; 94059656Siwasaki u_int i = 0; 94159656Siwasaki 94259656Siwasaki if (len < 1) 94359656Siwasaki return; 94459656Siwasaki switch (p[0]) { 94559656Siwasaki case 1: /* Network technology */ 94659656Siwasaki if (len < 2) 94759656Siwasaki goto err; 94859656Siwasaki printf("\tNetwork technology: %s\n", tech[p[1] & 7]); 94959656Siwasaki break; 95059656Siwasaki case 2: /* Network speed */ 95159656Siwasaki if (len < 5) 95259656Siwasaki goto err; 95359656Siwasaki printf("\tNetwork speed: "); 95459656Siwasaki print_speed(tpl32(p + 1)); 95559656Siwasaki putchar('\n'); 95659656Siwasaki break; 95759656Siwasaki case 3: /* Network media */ 95859656Siwasaki if (len < 2) 95959656Siwasaki goto err; 96059656Siwasaki if (p[1] <= 10) 96159656Siwasaki i = p[1]; 96259656Siwasaki printf("\tNetwork media: %s\n", media[i]); 96359656Siwasaki break; 96459656Siwasaki case 4: /* Node ID */ 96559656Siwasaki if (len <= 2 || len < p[1] + 2) 96659656Siwasaki goto err; 96759656Siwasaki printf("\tNetwork node ID:"); 96859656Siwasaki for (i = 0; i < p[1]; i++) 96959656Siwasaki printf(" %02x", p[i + 2]); 97059656Siwasaki putchar('\n'); 97159656Siwasaki break; 972250460Seadler case 5: /* Connector type */ 97359656Siwasaki if (len < 2) 97459656Siwasaki goto err; 97559656Siwasaki printf("\tNetwork connector: %s connector standard\n", 97659656Siwasaki (p[1] == 0) ? "open" : "closed"); 97759656Siwasaki break; 97859656Siwasaki err: /* warning */ 97959656Siwasaki printf("\tWrong length for network extension tuple\n"); 98059656Siwasaki return; 98159656Siwasaki } 98259656Siwasaki} 98359656Siwasaki 98459656Siwasaki/* 98559656Siwasaki * CIS_LONGLINK_MFC: Long link to next chain for Multi function card 98659656Siwasaki */ 98759656Siwasakistatic void 98859656Siwasakidump_longlink_mfc(u_char *p, int len) 98959656Siwasaki{ 99059656Siwasaki u_int i, n = *p++; 99159656Siwasaki 99259656Siwasaki --len; 99359656Siwasaki for (i = 0; i < n; i++) { 99459656Siwasaki if (len < 5) { 99559656Siwasaki printf("\tWrong length for long link MFC tuple\n"); 99659656Siwasaki return; 99759656Siwasaki } 99859656Siwasaki printf("\tFunction %d: %s memory, address 0x%x\n", 99959656Siwasaki i, (*p ? "common" : "attribute"), tpl32(p + 1)); 100059656Siwasaki p += 5; 100159656Siwasaki len -= 5; 100259656Siwasaki } 100359656Siwasaki} 100459656Siwasaki 100559656Siwasaki/* 100659656Siwasaki * CIS_DEVICEGEO, CIS_DEVICEGEO_A: 100759656Siwasaki * Geometry info for common/attribute memory 100859656Siwasaki */ 100959656Siwasakistatic void 101059656Siwasakidump_device_geo(u_char *p, int len) 101159656Siwasaki{ 101259656Siwasaki while (len >= 6) { 101359656Siwasaki printf("\twidth = %d, erase = 0x%x, read = 0x%x, write = 0x%x\n" 101459656Siwasaki "\t\tpartition = 0x%x, interleave = 0x%x\n", 101559656Siwasaki p[0], 1 << (p[1] - 1), 101659656Siwasaki 1 << (p[2] - 1), 1 << (p[3] - 1), 101759656Siwasaki 1 << (p[4] - 1), 1 << (p[5] - 1)); 101859656Siwasaki len -= 6; 101959656Siwasaki } 102059656Siwasaki} 102159656Siwasaki 102259656Siwasaki/* 102359656Siwasaki * CIS_INFO_V2: Print version-2 info 102459656Siwasaki */ 102559656Siwasakistatic void 102659656Siwasakidump_info_v2(u_char *p, int len) 102759656Siwasaki{ 102859656Siwasaki if (len < 9) { 102959656Siwasaki printf("\tWrong length for version-2 info tuple\n"); 103059656Siwasaki return; 103159656Siwasaki } 103259656Siwasaki printf("\tVersion = 0x%x, compliance = 0x%x, dindex = 0x%x\n", 103359656Siwasaki p[0], p[1], tpl16(p + 2)); 103459656Siwasaki printf("\tVspec8 = 0x%x, vspec9 = 0x%x, nhdr = %d\n", 103559656Siwasaki p[6], p[7], p[8]); 103659656Siwasaki p += 9; 103759656Siwasaki len -= 9; 103859656Siwasaki if (len <= 1 || *p == 0xff) 103959656Siwasaki return; 104059656Siwasaki printf("\tVendor = [%.*s]", len, p); 104159656Siwasaki while (*p++ && --len > 0); 104259656Siwasaki if (len > 1 && *p != 0xff) 104359656Siwasaki printf(", info = [%.*s]", len, p); 104459656Siwasaki putchar('\n'); 104559656Siwasaki} 104659656Siwasaki 104759656Siwasaki/* 104859656Siwasaki * CIS_ORG: Organization 104959656Siwasaki */ 105059656Siwasakistatic void 105159656Siwasakidump_org(u_char *p, int len) 105259656Siwasaki{ 105359656Siwasaki if (len < 1) { 105459656Siwasaki printf("\tWrong length for organization tuple\n"); 105559656Siwasaki return; 105659656Siwasaki } 105759656Siwasaki switch (*p) { 105859656Siwasaki case 0: 105959656Siwasaki printf("\tFilesystem"); 106059656Siwasaki break; 106159656Siwasaki case 1: 106259656Siwasaki printf("\tApp specific"); 106359656Siwasaki break; 106459656Siwasaki case 2: 106559656Siwasaki printf("\tCode"); 106659656Siwasaki break; 106759656Siwasaki default: 106859656Siwasaki if (*p < 0x80) 106959656Siwasaki printf("\tReserved"); 107059656Siwasaki else 107159656Siwasaki printf("\tVendor specific"); 107259656Siwasaki break; 107359656Siwasaki } 107459656Siwasaki printf(" [%.*s]\n", len - 1, p + 1); 107559656Siwasaki} 107659656Siwasaki 107759656Siwasakistatic void 107859656Siwasakiprint_size(u_int i) 107959656Siwasaki{ 108059656Siwasaki if (i < 1024) 108159656Siwasaki printf("%ubits", i); 108259656Siwasaki else if (i < 1024*1024) 108359656Siwasaki printf("%ukb", i / 1024); 108459656Siwasaki else 108559656Siwasaki printf("%uMb", i / (1024*1024)); 108659656Siwasaki} 108759656Siwasaki 108859656Siwasaki/* 108959656Siwasaki * CIS_BAR: Base address register for CardBus 109059656Siwasaki */ 109159656Siwasakistatic void 109259656Siwasakidump_bar(u_char *p, int len) 109359656Siwasaki{ 109459656Siwasaki if (len < 6) { 109559656Siwasaki printf("\tWrong length for BAR tuple\n"); 109659656Siwasaki return; 109759656Siwasaki } 109859656Siwasaki printf("\tBAR %d: size = ", *p & 7); 109959656Siwasaki print_size(tpl32(p + 2)); 110059656Siwasaki printf(", %s%s%s%s\n", 110159656Siwasaki (*p & 0x10) ? "I/O" : "Memory", 110259656Siwasaki (*p & 0x20) ? ", Prefetch" : "", 110359656Siwasaki (*p & 0x40) ? ", Cacheable" : "", 110459656Siwasaki (*p & 0x80) ? ", <1Mb" : ""); 110559656Siwasaki} 1106