1330449Seadler/*- 2330449Seadler * SPDX-License-Identifier: BSD-3-Clause 3330449Seadler * 415284Snate * Copyright (c) 1995 Andrew McRae. All rights reserved. 515284Snate * 615284Snate * Redistribution and use in source and binary forms, with or without 715284Snate * modification, are permitted provided that the following conditions 815284Snate * are met: 915284Snate * 1. Redistributions of source code must retain the above copyright 1015284Snate * notice, this list of conditions and the following disclaimer. 1115284Snate * 2. Redistributions in binary form must reproduce the above copyright 1215284Snate * notice, this list of conditions and the following disclaimer in the 1315284Snate * documentation and/or other materials provided with the distribution. 1415284Snate * 3. The name of the author may not be used to endorse or promote products 1515284Snate * derived from this software without specific prior written permission. 1615284Snate * 1715284Snate * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1815284Snate * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1915284Snate * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2015284Snate * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2115284Snate * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2215284Snate * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2315284Snate * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2415284Snate * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2515284Snate * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2615284Snate * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2710217Sphk */ 2830171Scharnier 2930171Scharnier#ifndef lint 3030171Scharnierstatic const char rcsid[] = 3150479Speter "$FreeBSD: stable/11/usr.sbin/dumpcis/printcis.c 330449 2018-03-05 07:26:05Z eadler $"; 3230171Scharnier#endif /* not lint */ 3330171Scharnier 3459656Siwasaki/* 3559656Siwasaki * Code cleanup, bug-fix and extension 3659656Siwasaki * by Tatsumi Hosokawa <hosokawa@mt.cs.keio.ac.jp> 3759656Siwasaki */ 3859656Siwasaki 3959656Siwasaki#include <err.h> 4010217Sphk#include <stdio.h> 4110217Sphk#include <stdlib.h> 4210217Sphk#include <string.h> 4330171Scharnier#include <unistd.h> 4410217Sphk#include <sys/ioctl.h> 4510217Sphk 46188633Simp#include "cis.h" 4710217Sphk#include "readcis.h" 4810217Sphk 4959656Siwasakistatic void dump_config_map(struct tuple *tp); 5059656Siwasakistatic void dump_cis_config(struct tuple *tp); 5159656Siwasakistatic void dump_other_cond(u_char *p, int len); 52185033Simpstatic void dump_device_desc(u_char *p, int len, const char *type); 5359656Siwasakistatic void dump_info_v1(u_char *p, int len); 5459656Siwasakistatic void dump_longlink_mfc(u_char *p, int len); 5559656Siwasakistatic void dump_bar(u_char *p, int len); 5659656Siwasakistatic void dump_device_geo(u_char *p, int len); 5759656Siwasakistatic void dump_func_id(u_char *p); 5859656Siwasakistatic void dump_serial_ext(u_char *p, int len); 5959656Siwasakistatic void dump_disk_ext(u_char *p, int len); 6059656Siwasakistatic void dump_network_ext(u_char *p, int len); 6159656Siwasakistatic void dump_info_v2(u_char *p, int len); 6259656Siwasakistatic void dump_org(u_char *p, int len); 6310217Sphk 6410217Sphkvoid 65185121Simpdumpcis(struct tuple_list *tlist) 6610217Sphk{ 6715175Snate struct tuple *tp; 6815175Snate struct tuple_list *tl; 6915175Snate int count = 0, sz, ad, i; 7059656Siwasaki u_char *p; 7159656Siwasaki int func = 0; 7210217Sphk 73185121Simp for (tl = tlist; tl; tl = tl->next) 7415175Snate for (tp = tl->tuples; tp; tp = tp->next) { 7510217Sphk printf("Tuple #%d, code = 0x%x (%s), length = %d\n", 7615175Snate ++count, tp->code, tuple_name(tp->code), tp->length); 7710217Sphk p = tp->data; 7810217Sphk sz = tp->length; 7910217Sphk ad = 0; 8015175Snate while (sz > 0) { 8110217Sphk printf(" %03x: ", ad); 8210217Sphk for (i = 0; i < ((sz < 16) ? sz : 16); i++) 8310217Sphk printf(" %02x", p[i]); 8410217Sphk printf("\n"); 8510217Sphk sz -= 16; 8610217Sphk p += 16; 8710217Sphk ad += 16; 8815175Snate } 8915175Snate switch (tp->code) { 9010217Sphk default: 9110217Sphk break; 9210217Sphk case CIS_MEM_COMMON: /* 0x01 */ 9310217Sphk dump_device_desc(tp->data, tp->length, "Common"); 9410217Sphk break; 9559656Siwasaki case CIS_CONF_MAP_CB: /* 0x04 */ 9659656Siwasaki dump_config_map(tp); 9759656Siwasaki break; 9859656Siwasaki case CIS_CONFIG_CB: /* 0x05 */ 9959656Siwasaki dump_cis_config(tp); 10059656Siwasaki break; 10159656Siwasaki case CIS_LONGLINK_MFC: /* 0x06 */ 10259656Siwasaki dump_longlink_mfc(tp->data, tp->length); 10359656Siwasaki break; 10459656Siwasaki case CIS_BAR: /* 0x07 */ 10559656Siwasaki dump_bar(tp->data, tp->length); 10659656Siwasaki break; 10710217Sphk case CIS_CHECKSUM: /* 0x10 */ 10859656Siwasaki printf("\tChecksum from offset %d, length %d, value is 0x%x\n", 10959656Siwasaki tpl16(tp->data), 11059656Siwasaki tpl16(tp->data + 2), 11159656Siwasaki tp->data[4]); 11210217Sphk break; 11310217Sphk case CIS_LONGLINK_A: /* 0x11 */ 11410217Sphk printf("\tLong link to attribute memory, address 0x%x\n", 11559656Siwasaki tpl32(tp->data)); 11610217Sphk break; 11710217Sphk case CIS_LONGLINK_C: /* 0x12 */ 11810217Sphk printf("\tLong link to common memory, address 0x%x\n", 11959656Siwasaki tpl32(tp->data)); 12059656Siwasaki break; 12110217Sphk case CIS_INFO_V1: /* 0x15 */ 12210217Sphk dump_info_v1(tp->data, tp->length); 12310217Sphk break; 12410217Sphk case CIS_ALTSTR: /* 0x16 */ 12510217Sphk break; 12610217Sphk case CIS_MEM_ATTR: /* 0x17 */ 12710217Sphk dump_device_desc(tp->data, tp->length, "Attribute"); 12810217Sphk break; 12910217Sphk case CIS_JEDEC_C: /* 0x18 */ 13010217Sphk case CIS_JEDEC_A: /* 0x19 */ 13110217Sphk break; 13210217Sphk case CIS_CONF_MAP: /* 0x1A */ 13310217Sphk dump_config_map(tp); 13410217Sphk break; 13510217Sphk case CIS_CONFIG: /* 0x1B */ 13610217Sphk dump_cis_config(tp); 13710217Sphk break; 13810217Sphk case CIS_DEVICE_OC: /* 0x1C */ 13910217Sphk case CIS_DEVICE_OA: /* 0x1D */ 14059656Siwasaki dump_other_cond(tp->data, tp->length); 14110217Sphk break; 14210217Sphk case CIS_DEVICEGEO: /* 0x1E */ 14310217Sphk case CIS_DEVICEGEO_A: /* 0x1F */ 14459656Siwasaki dump_device_geo(tp->data, tp->length); 14510217Sphk break; 14610217Sphk case CIS_MANUF_ID: /* 0x20 */ 14710217Sphk printf("\tPCMCIA ID = 0x%x, OEM ID = 0x%x\n", 14859656Siwasaki tpl16(tp->data), 14959656Siwasaki tpl16(tp->data + 2)); 15010217Sphk break; 15110217Sphk case CIS_FUNC_ID: /* 0x21 */ 15259656Siwasaki func = tp->data[0]; 15359656Siwasaki dump_func_id(tp->data); 15459656Siwasaki break; 15559656Siwasaki case CIS_FUNC_EXT: /* 0x22 */ 15659656Siwasaki switch (func) { 15710217Sphk case 2: 15859656Siwasaki dump_serial_ext(tp->data, tp->length); 15910217Sphk break; 16010217Sphk case 4: 16159656Siwasaki dump_disk_ext(tp->data, tp->length); 16210217Sphk break; 16310217Sphk case 6: 16459656Siwasaki dump_network_ext(tp->data, tp->length); 16510217Sphk break; 16615175Snate } 16710217Sphk break; 16810217Sphk case CIS_VERS_2: /* 0x40 */ 16959656Siwasaki dump_info_v2(tp->data, tp->length); 17010217Sphk break; 17159656Siwasaki case CIS_ORG: /* 0x46 */ 17259656Siwasaki dump_org(tp->data, tp->length); 17359656Siwasaki break; 17410217Sphk } 17515175Snate } 17610217Sphk} 17715175Snate 17810217Sphk/* 17959656Siwasaki * CIS_CONF_MAP : Dump configuration map tuple. 18059656Siwasaki * CIS_CONF_MAP_CB: Dump configuration map for CardBus 18110217Sphk */ 18259656Siwasakistatic void 18310217Sphkdump_config_map(struct tuple *tp) 18410217Sphk{ 18559656Siwasaki u_char *p = tp->data, x; 18659656Siwasaki int rlen, mlen = 0; 18715175Snate int i; 18810217Sphk 18959656Siwasaki rlen = (p[0] & 3) + 1; 19059656Siwasaki if (tp->code == CIS_CONF_MAP) 19159656Siwasaki mlen = ((p[0] >> 2) & 3) + 1; 19259656Siwasaki if (tp->length < rlen + mlen + 2) { 19359656Siwasaki printf("\tWrong length for configuration map tuple\n"); 19459656Siwasaki return; 19559656Siwasaki } 19659656Siwasaki printf("\tReg len = %d, config register addr = 0x%x, last config = 0x%x\n", 19759656Siwasaki rlen, parse_num(rlen | 0x10, p + 2, &p, 0), p[1]); 19859656Siwasaki if (mlen) { 19910217Sphk printf("\tRegisters: "); 20059656Siwasaki for (i = 0; i < mlen; i++, p++) { 20159656Siwasaki for (x = 0x1; x; x <<= 1) 20259656Siwasaki printf("%c", x & *p ? 'X' : '-'); 20359656Siwasaki putchar(' '); 20459656Siwasaki } 20515175Snate } 20659656Siwasaki i = tp->length - (rlen + mlen + 2); 20759656Siwasaki if (i) { 20859656Siwasaki if (!mlen) 20959656Siwasaki putchar('\t'); 21059656Siwasaki printf("%d bytes in subtuples", i); 21159656Siwasaki } 21259656Siwasaki if (mlen || i) 21359656Siwasaki putchar('\n'); 21410217Sphk} 21515175Snate 21610217Sphk/* 21759656Siwasaki * Dump power descriptor. 21859656Siwasaki * call from dump_cis_config() 21910217Sphk */ 22059656Siwasakistatic int 22159656Siwasakiprint_pwr_desc(u_char *p) 22259656Siwasaki{ 22359656Siwasaki int len = 1, i; 22459656Siwasaki u_char mask; 225185033Simp const char **expp; 226185033Simp static const char *pname[] = 22759656Siwasaki {"Nominal operating supply voltage", 22859656Siwasaki "Minimum operating supply voltage", 22959656Siwasaki "Maximum operating supply voltage", 23059656Siwasaki "Continuous supply current", 23159656Siwasaki "Max current average over 1 second", 23259656Siwasaki "Max current average over 10 ms", 23359656Siwasaki "Power down supply current", 23459656Siwasaki "Reserved" 23559656Siwasaki }; 236185033Simp static const char *vexp[] = 23759656Siwasaki {"10uV", "100uV", "1mV", "10mV", "100mV", "1V", "10V", "100V"}; 238185033Simp static const char *cexp[] = 23959656Siwasaki {"10nA", "1uA", "10uA", "100uA", "1mA", "10mA", "100mA", "1A"}; 240185033Simp static const char *mant[] = 24159656Siwasaki {"1", "1.2", "1.3", "1.5", "2", "2.5", "3", "3.5", "4", "4.5", 24259656Siwasaki "5", "5.5", "6", "7", "8", "9"}; 24359656Siwasaki 24459656Siwasaki mask = *p++; 24559656Siwasaki expp = vexp; 24659656Siwasaki for (i = 0; i < 8; i++) 24759656Siwasaki if (mask & (1 << i)) { 24859656Siwasaki len++; 24959656Siwasaki if (i >= 3) 25059656Siwasaki expp = cexp; 25159656Siwasaki printf("\t\t%s: ", pname[i]); 25259656Siwasaki printf("%s x %s", 25359656Siwasaki mant[(*p >> 3) & 0xF], 25459656Siwasaki expp[*p & 7]); 25559656Siwasaki while (*p & 0x80) { 25659656Siwasaki len++; 25759656Siwasaki p++; 25859656Siwasaki printf(", ext = 0x%x", *p); 25959656Siwasaki } 26059656Siwasaki printf("\n"); 26159656Siwasaki p++; 26259656Siwasaki } 26359656Siwasaki return (len); 26459656Siwasaki} 26559656Siwasaki 26659656Siwasaki/* 26759656Siwasaki * print_ext_speed - Print extended speed. 26859656Siwasaki * call from dump_cis_config(), dump_device_desc() 26959656Siwasaki */ 27059656Siwasakistatic void 27159656Siwasakiprint_ext_speed(u_char x, int scale) 27259656Siwasaki{ 273185033Simp static const char *mant[] = 27459656Siwasaki {"Reserved", "1.0", "1.2", "1.3", "1.5", "2.0", "2.5", "3.0", 27559656Siwasaki "3.5", "4.0", "4.5", "5.0", "5.5", "6.0", "7.0", "8.0"}; 276185033Simp static const char *exp[] = 27759656Siwasaki {"1 ns", "10 ns", "100 ns", "1 us", "10 us", "100 us", 27859656Siwasaki "1 ms", "10 ms"}; 279185033Simp static const char *scale_name[] = 28059656Siwasaki {"None", "10", "100", "1,000", "10,000", "100,000", 28159656Siwasaki "1,000,000", "10,000,000"}; 28259656Siwasaki 28359656Siwasaki printf("Speed = %s x %s", mant[(x >> 3) & 0xF], exp[x & 7]); 28459656Siwasaki if (scale) 28559656Siwasaki printf(", scaled by %s", scale_name[scale & 7]); 28659656Siwasaki} 28759656Siwasaki 28859656Siwasaki/* 28959656Siwasaki * Print variable length value. 29059656Siwasaki * call from print_io_map(), print_mem_map() 29159656Siwasaki */ 29259656Siwasakistatic int 293185033Simpprint_num(int sz, const char *fmt, u_char *p, int ofs) 29459656Siwasaki{ 29559656Siwasaki switch (sz) { 29659656Siwasaki case 0: 29759656Siwasaki case 0x10: 29859656Siwasaki return 0; 29959656Siwasaki case 1: 30059656Siwasaki case 0x11: 30159656Siwasaki printf(fmt, *p + ofs); 30259656Siwasaki return 1; 30359656Siwasaki case 2: 30459656Siwasaki case 0x12: 30559656Siwasaki printf(fmt, tpl16(p) + ofs); 30659656Siwasaki return 2; 30759656Siwasaki case 0x13: 30859656Siwasaki printf(fmt, tpl24(p) + ofs); 30959656Siwasaki return 3; 31059656Siwasaki case 3: 31159656Siwasaki case 0x14: 31259656Siwasaki printf(fmt, tpl32(p) + ofs); 31359656Siwasaki return 4; 31459656Siwasaki } 31559656Siwasaki errx(1, "print_num(0x%x): Illegal arguments", sz); 31659656Siwasaki/*NOTREACHED*/ 31759656Siwasaki} 31859656Siwasaki 31959656Siwasaki/* 32059656Siwasaki * Print I/O mapping sub-tuple. 32159656Siwasaki * call from dump_cis_config() 32259656Siwasaki */ 32359656Siwasakistatic u_char * 32459656Siwasakiprint_io_map(u_char *p, u_char *q) 32559656Siwasaki{ 32659656Siwasaki int i, j; 32759656Siwasaki u_char c; 32859656Siwasaki 32959656Siwasaki if (q <= p) 33059656Siwasaki goto err; 33159656Siwasaki if (CIS_IO_ADDR(*p)) /* I/O address line */ 33259656Siwasaki printf("\tCard decodes %d address lines", 33359656Siwasaki CIS_IO_ADDR(*p)); 33459656Siwasaki else 33559656Siwasaki printf("\tCard provides address decode"); 33659656Siwasaki 33759656Siwasaki /* 8/16 bit I/O */ 33859656Siwasaki switch (*p & (CIS_IO_8BIT | CIS_IO_16BIT)) { 33959656Siwasaki case CIS_IO_8BIT: 34059656Siwasaki printf(", 8 Bit I/O only"); 34159656Siwasaki break; 34259656Siwasaki case CIS_IO_16BIT: 34359656Siwasaki printf(", limited 8/16 Bit I/O"); 34459656Siwasaki break; 34559656Siwasaki case (CIS_IO_8BIT | CIS_IO_16BIT): 34659656Siwasaki printf(", full 8/16 Bit I/O"); 34759656Siwasaki break; 34859656Siwasaki } 34959656Siwasaki putchar('\n'); 35059656Siwasaki 35159656Siwasaki /* I/O block sub-tuple exist */ 35259656Siwasaki if (*p++ & CIS_IO_RANGE) { 35359656Siwasaki if (q <= p) 35459656Siwasaki goto err; 35559656Siwasaki c = *p++; 35659656Siwasaki /* calculate byte length */ 35759656Siwasaki j = CIS_IO_ADSZ(c) + CIS_IO_BLKSZ(c); 35859656Siwasaki if (CIS_IO_ADSZ(c) == 3) 35959656Siwasaki j++; 36059656Siwasaki if (CIS_IO_BLKSZ(c) == 3) 36159656Siwasaki j++; 36259656Siwasaki /* number of I/O block sub-tuples */ 36359656Siwasaki for (i = 0; i <= CIS_IO_BLKS(c); i++) { 36459656Siwasaki if (q - p < j) 36559656Siwasaki goto err; 36659656Siwasaki printf("\t\tI/O address # %d: ", i + 1); 36759656Siwasaki /* start block address */ 36859656Siwasaki p += print_num(CIS_IO_ADSZ(c), 36959656Siwasaki "block start = 0x%x", p, 0); 37059656Siwasaki /* block size */ 37159656Siwasaki p += print_num(CIS_IO_BLKSZ(c), 37259656Siwasaki " block length = 0x%x", p, 1); 37359656Siwasaki putchar('\n'); 37459656Siwasaki } 37559656Siwasaki } 37659656Siwasaki return p; 37759656Siwasaki 37859656Siwasaki err: /* warning */ 37959656Siwasaki printf("\tWrong length for I/O mapping sub-tuple\n"); 38059656Siwasaki return p; 38159656Siwasaki} 38259656Siwasaki 38359656Siwasaki/* 38459656Siwasaki * Print IRQ sub-tuple. 38559656Siwasaki * call from dump_cis_config() 38659656Siwasaki */ 38759656Siwasakistatic u_char * 38859656Siwasakiprint_irq_map(u_char *p, u_char *q) 38959656Siwasaki{ 39059656Siwasaki int i, j; 39159656Siwasaki u_char c; 39259656Siwasaki 39359656Siwasaki if (q <= p) 39459656Siwasaki goto err; 39559656Siwasaki printf("\t\tIRQ modes:"); 39659656Siwasaki c = ' '; 39759656Siwasaki if (*p & CIS_IRQ_LEVEL) { /* Level triggered interrupts */ 39859656Siwasaki printf(" Level"); 39959656Siwasaki c = ','; 40059656Siwasaki } 40159656Siwasaki if (*p & CIS_IRQ_PULSE) { /* Pulse triggered requests */ 40259656Siwasaki printf("%c Pulse", c); 40359656Siwasaki c = ','; 40459656Siwasaki } 40559656Siwasaki if (*p & CIS_IRQ_SHARING) /* Interrupt sharing */ 40659656Siwasaki printf("%c Shared", c); 40759656Siwasaki putchar('\n'); 40859656Siwasaki 40959656Siwasaki /* IRQ mask values exist */ 41059656Siwasaki if (*p & CIS_IRQ_MASK) { 41159656Siwasaki if (q - p < 3) 41259656Siwasaki goto err; 41359656Siwasaki i = tpl16(p + 1); /* IRQ mask */ 41459656Siwasaki printf("\t\tIRQs: "); 41559656Siwasaki if (*p & 1) 41659656Siwasaki printf(" NMI"); 41759656Siwasaki if (*p & 0x2) 41859656Siwasaki printf(" IOCK"); 41959656Siwasaki if (*p & 0x4) 42059656Siwasaki printf(" BERR"); 42159656Siwasaki if (*p & 0x8) 42259656Siwasaki printf(" VEND"); 42359656Siwasaki for (j = 0; j < 16; j++) 42459656Siwasaki if (i & (1 << j)) 42559656Siwasaki printf(" %d", j); 42659656Siwasaki putchar('\n'); 42759656Siwasaki p += 3; 42859656Siwasaki } else { 42959656Siwasaki printf("\t\tIRQ level = %d\n", CIS_IRQ_IRQN(*p)); 43059656Siwasaki p++; 43159656Siwasaki } 43259656Siwasaki return p; 43359656Siwasaki 43459656Siwasaki err: /* warning */ 43559656Siwasaki printf("\tWrong length for IRQ sub-tuple\n"); 43659656Siwasaki return p; 43759656Siwasaki} 43859656Siwasaki 43959656Siwasaki/* 44059656Siwasaki * Print memory map sub-tuple. 44159656Siwasaki * call from dump_cis_config() 44259656Siwasaki */ 44359656Siwasakistatic u_char * 44459656Siwasakiprint_mem_map(u_char feat, u_char *p, u_char *q) 44559656Siwasaki{ 44659656Siwasaki int i, j; 44759656Siwasaki u_char c; 44859656Siwasaki 44959656Siwasaki switch (CIS_FEAT_MEMORY(feat)) { 45059656Siwasaki 45159656Siwasaki case CIS_FEAT_MEM_NONE: /* No memory block */ 45259656Siwasaki break; 45359656Siwasaki case CIS_FEAT_MEM_LEN: /* Specify memory length */ 45459656Siwasaki if (q - p < 2) 45559656Siwasaki goto err; 45659656Siwasaki printf("\tMemory space length = 0x%x\n", tpl16(p)); 45759656Siwasaki p += 2; 45859656Siwasaki break; 45959656Siwasaki case CIS_FEAT_MEM_ADDR: /* Memory address and length */ 46059656Siwasaki if (q - p < 4) 46159656Siwasaki goto err; 46259656Siwasaki printf("\tMemory space address = 0x%x, length = 0x%x\n", 46359656Siwasaki tpl16(p + 2), tpl16(p)); 46459656Siwasaki p += 4; 46559656Siwasaki break; 46659656Siwasaki case CIS_FEAT_MEM_WIN: /* Memory descriptors. */ 46759656Siwasaki if (q <= p) 46859656Siwasaki goto err; 46959656Siwasaki c = *p++; 47059656Siwasaki /* calculate byte length */ 47159656Siwasaki j = CIS_MEM_LENSZ(c) + CIS_MEM_ADDRSZ(c); 47259656Siwasaki if (c & CIS_MEM_HOST) 47359656Siwasaki j += CIS_MEM_ADDRSZ(c); 47459656Siwasaki /* number of memory block */ 47559656Siwasaki for (i = 0; i < CIS_MEM_WINS(c); i++) { 47659656Siwasaki if (q - p < j) 47759656Siwasaki goto err; 47859656Siwasaki printf("\tMemory descriptor %d\n\t\t", i + 1); 47959656Siwasaki /* memory length */ 48059656Siwasaki p += print_num(CIS_MEM_LENSZ(c) | 0x10, 48159656Siwasaki " blk length = 0x%x00", p, 0); 48259656Siwasaki /* card address */ 48359656Siwasaki p += print_num(CIS_MEM_ADDRSZ(c) | 0x10, 48459656Siwasaki " card addr = 0x%x00", p, 0); 48559656Siwasaki if (c & CIS_MEM_HOST) /* Host address value exist */ 48659656Siwasaki p += print_num(CIS_MEM_ADDRSZ(c) | 0x10, 48759656Siwasaki " host addr = 0x%x00", p, 0); 48859656Siwasaki putchar('\n'); 48959656Siwasaki } 49059656Siwasaki break; 49159656Siwasaki } 49259656Siwasaki return p; 49359656Siwasaki 49459656Siwasaki err: /* warning */ 49559656Siwasaki printf("\tWrong length for memory mapping sub-tuple\n"); 49659656Siwasaki return p; 49759656Siwasaki} 49859656Siwasaki 49959656Siwasaki/* 50059656Siwasaki * CIS_CONFIG : Dump a config entry. 50159656Siwasaki * CIS_CONFIG_CB: Dump a configuration entry for CardBus 50259656Siwasaki */ 50359656Siwasakistatic void 50410217Sphkdump_cis_config(struct tuple *tp) 50510217Sphk{ 50659656Siwasaki u_char *p, *q, feat; 50715175Snate int i, j; 50815175Snate char c; 50910217Sphk 51010217Sphk p = tp->data; 51159656Siwasaki q = p + tp->length; 51210217Sphk printf("\tConfig index = 0x%x%s\n", *p & 0x3F, 51359656Siwasaki *p & 0x40 ? "(default)" : ""); 51459656Siwasaki 51559656Siwasaki /* Interface byte exists */ 51659656Siwasaki if (tp->code == CIS_CONFIG && (*p & 0x80)) { 51710217Sphk p++; 51810217Sphk printf("\tInterface byte = 0x%x ", *p); 51959656Siwasaki switch (*p & 0xF) { /* Interface type */ 52010217Sphk default: 52110217Sphk printf("(reserved)"); 52210217Sphk break; 52310217Sphk case 0: 52410217Sphk printf("(memory)"); 52510217Sphk break; 52610217Sphk case 1: 52710217Sphk printf("(I/O)"); 52810217Sphk break; 52910217Sphk case 4: 53010217Sphk case 5: 53110217Sphk case 6: 53210217Sphk case 7: 53310217Sphk case 8: 53410217Sphk printf("(custom)"); 53510217Sphk break; 53615175Snate } 53710217Sphk c = ' '; 53859656Siwasaki if (*p & 0x10) { /* Battery voltage detect */ 53910217Sphk printf(" BVD1/2 active"); 54010217Sphk c = ','; 54115175Snate } 54259656Siwasaki if (*p & 0x20) { /* Write protect active */ 54310217Sphk printf("%c card WP active", c); /* Write protect */ 54410217Sphk c = ','; 54515175Snate } 54659656Siwasaki if (*p & 0x40) { /* RdyBsy active bit */ 54710217Sphk printf("%c +RDY/-BSY active", c); 54810217Sphk c = ','; 54915175Snate } 55059656Siwasaki if (*p & 0x80) /* Wait signal required */ 55110217Sphk printf("%c wait signal supported", c); 55210217Sphk printf("\n"); 55315175Snate } 55459656Siwasaki 55559656Siwasaki /* features byte */ 55610217Sphk p++; 55710217Sphk feat = *p++; 55859656Siwasaki 55959656Siwasaki /* Power structure sub-tuple */ 56059656Siwasaki switch (CIS_FEAT_POWER(feat)) { /* Power sub-tuple(s) exists */ 56110217Sphk case 0: 56210217Sphk break; 56310217Sphk case 1: 56410217Sphk printf("\tVcc pwr:\n"); 56559656Siwasaki p += print_pwr_desc(p); 56610217Sphk break; 56710217Sphk case 2: 56810217Sphk printf("\tVcc pwr:\n"); 56959656Siwasaki p += print_pwr_desc(p); 57010217Sphk printf("\tVpp pwr:\n"); 57159656Siwasaki p += print_pwr_desc(p); 57210217Sphk break; 57310217Sphk case 3: 57410217Sphk printf("\tVcc pwr:\n"); 57559656Siwasaki p += print_pwr_desc(p); 57610217Sphk printf("\tVpp1 pwr:\n"); 57759656Siwasaki p += print_pwr_desc(p); 57810217Sphk printf("\tVpp2 pwr:\n"); 57959656Siwasaki p += print_pwr_desc(p); 58010217Sphk break; 58115175Snate } 58259656Siwasaki 58359656Siwasaki /* Timing sub-tuple */ 58459656Siwasaki if (tp->code == CIS_CONFIG && 58559656Siwasaki (feat & CIS_FEAT_TIMING)) { /* Timing sub-tuple exists */ 58659656Siwasaki i = *p++; 58759656Siwasaki j = CIS_WAIT_SCALE(i); 58859656Siwasaki if (j != 3) { 58910217Sphk printf("\tWait scale "); 59059656Siwasaki print_ext_speed(*p++, j); 59110217Sphk printf("\n"); 59215175Snate } 59359656Siwasaki j = CIS_READY_SCALE(i); 59415175Snate if (j != 7) { 59510217Sphk printf("\tRDY/BSY scale "); 59659656Siwasaki print_ext_speed(*p++, j); 59710217Sphk printf("\n"); 59810217Sphk } 59959656Siwasaki j = CIS_RESERVED_SCALE(i); 60059656Siwasaki if (j != 7) { 60159656Siwasaki printf("\tExternal scale "); 60259656Siwasaki print_ext_speed(*p++, j); 60359656Siwasaki printf("\n"); 60459656Siwasaki } 60515175Snate } 60659656Siwasaki 60759656Siwasaki /* I/O mapping sub-tuple */ 60859656Siwasaki if (feat & CIS_FEAT_I_O) { /* I/O space sub-tuple exists */ 60959656Siwasaki if (tp->code == CIS_CONFIG) 61059656Siwasaki p = print_io_map(p, q); 61159656Siwasaki else { /* CIS_CONFIG_CB */ 61259656Siwasaki printf("\tI/O base:"); 61359656Siwasaki for (i = 0; i < 8; i++) 61459656Siwasaki if (*p & (1 << i)) 61559656Siwasaki printf(" %d", i); 61659656Siwasaki putchar('\n'); 61710217Sphk p++; 61810217Sphk } 61915175Snate } 62015175Snate 62159656Siwasaki /* IRQ descriptor sub-tuple */ 62259656Siwasaki if (feat & CIS_FEAT_IRQ) /* IRQ sub-tuple exists */ 62359656Siwasaki p = print_irq_map(p, q); 62459656Siwasaki 62559656Siwasaki /* Memory map sub-tuple */ 62659656Siwasaki if (CIS_FEAT_MEMORY(feat)) { /* Memory space sub-tuple(s) exists */ 62759656Siwasaki if (tp->code == CIS_CONFIG) 62859656Siwasaki p = print_mem_map(feat, p, q); 62959656Siwasaki else { /* CIS_CONFIG_CB */ 63059656Siwasaki printf("\tMemory base:"); 63159656Siwasaki for (i = 0; i < 8; i++) 63259656Siwasaki if (*p & (1 << i)) 63359656Siwasaki printf(" %d", i); 63459656Siwasaki putchar('\n'); 63510217Sphk p++; 63610217Sphk } 63715175Snate } 63815175Snate 63959656Siwasaki /* Misc sub-tuple */ 64059656Siwasaki if (feat & CIS_FEAT_MISC) { /* Miscellaneous sub-tuple exists */ 64159656Siwasaki if (tp->code == CIS_CONFIG) { 64259656Siwasaki printf("\tMax twin cards = %d\n", *p & 7); 64359656Siwasaki printf("\tMisc attr:%s%s%s", 64459656Siwasaki (*p & 8) ? " (Audio-BVD2)" : "", 64559656Siwasaki (*p & 0x10) ? " (Read-only)" : "", 64659656Siwasaki (*p & 0x20) ? " (Power down supported)" : ""); 64759656Siwasaki if (*p++ & 0x80) { 64859656Siwasaki printf(" (Ext byte = 0x%x)", *p); 64959656Siwasaki p++; 65015175Snate } 65159656Siwasaki putchar('\n'); 65259656Siwasaki } 65359656Siwasaki else { /* CIS_CONFIG_CB */ 65459656Siwasaki printf("\tMisc attr:"); 65559656Siwasaki printf("%s%s%s%s%s%s%s", 65659656Siwasaki (*p & 1) ? " (Master)" : "", 65759656Siwasaki (*p & 2) ? " (Invalidate)" : "", 65859656Siwasaki (*p & 4) ? " (VGA palette)" : "", 65959656Siwasaki (*p & 8) ? " (Parity)" : "", 66059656Siwasaki (*p & 0x10) ? " (Wait)" : "", 66159656Siwasaki (*p & 0x20) ? " (Serr)" : "", 66259656Siwasaki (*p & 0x40) ? " (Fast back)" : ""); 66359656Siwasaki if (*p++ & 0x80) { 66459656Siwasaki printf("%s%s", 66559656Siwasaki (*p & 1) ? " (Binary audio)" : "", 66659656Siwasaki (*p & 2) ? " (pwm audio)" : ""); 66759656Siwasaki p++; 66815175Snate } 66959656Siwasaki putchar('\n'); 67015175Snate } 67115175Snate } 67210217Sphk} 67315175Snate 67410217Sphk/* 67559656Siwasaki * CIS_DEVICE_OC, CIS_DEVICE_OA: 67659656Siwasaki * Dump other conditions for common/attribute memory 67710217Sphk */ 67859656Siwasakistatic void 67959656Siwasakidump_other_cond(u_char *p, int len) 68010217Sphk{ 68159656Siwasaki if (p[0] && len > 0) { 68210217Sphk printf("\t"); 68310217Sphk if (p[0] & 1) 68410217Sphk printf("(MWAIT)"); 68510217Sphk if (p[0] & 2) 68610217Sphk printf(" (3V card)"); 68710217Sphk if (p[0] & 0x80) 68810217Sphk printf(" (Extension bytes follow)"); 68910217Sphk printf("\n"); 69015175Snate } 69110217Sphk} 69215175Snate 69310217Sphk/* 69459656Siwasaki * CIS_MEM_COMMON, CIS_MEM_ATTR: 69559656Siwasaki * Common / Attribute memory descripter 69610217Sphk */ 69759656Siwasakistatic void 698185033Simpdump_device_desc(u_char *p, int len, const char *type) 69910217Sphk{ 700185033Simp static const char *un_name[] = 70115175Snate {"512b", "2Kb", "8Kb", "32Kb", "128Kb", "512Kb", "2Mb", "reserved"}; 702185033Simp static const char *speed[] = 70315175Snate {"No speed", "250nS", "200nS", "150nS", 70415175Snate "100nS", "Reserved", "Reserved"}; 705185033Simp static const char *dev[] = 70615175Snate {"No device", "Mask ROM", "OTPROM", "UV EPROM", 70715175Snate "EEPROM", "FLASH EEPROM", "SRAM", "DRAM", 70815175Snate "Reserved", "Reserved", "Reserved", "Reserved", 70915175Snate "Reserved", "Function specific", "Extended", 71015175Snate "Reserved"}; 71115175Snate int count = 0; 71210217Sphk 71315175Snate while (*p != 0xFF && len > 0) { 71459656Siwasaki u_char x; 71510217Sphk 71610217Sphk x = *p++; 71710217Sphk len -= 2; 71810217Sphk if (count++ == 0) 71910217Sphk printf("\t%s memory device information:\n", type); 72010217Sphk printf("\t\tDevice number %d, type %s, WPS = %s\n", 72115175Snate count, dev[x >> 4], (x & 0x8) ? "ON" : "OFF"); 72215175Snate if ((x & 7) == 7) { 72310217Sphk len--; 72415175Snate if (*p) { 72510217Sphk printf("\t\t"); 72676341Sdmlb print_ext_speed(*p, 0); 72715175Snate while (*p & 0x80) { 72810217Sphk p++; 72910217Sphk len--; 73010217Sphk } 73115175Snate } 73210217Sphk p++; 73315175Snate } else 73410217Sphk printf("\t\tSpeed = %s", speed[x & 7]); 73510217Sphk printf(", Memory block size = %s, %d units\n", 73615175Snate un_name[*p & 7], (*p >> 3) + 1); 73710217Sphk p++; 73815175Snate } 73910217Sphk} 74015175Snate 74110217Sphk/* 74259656Siwasaki * CIS_INFO_V1: Print version-1 info 74310217Sphk */ 74459656Siwasakistatic void 74559656Siwasakidump_info_v1(u_char *p, int len) 74610217Sphk{ 74759656Siwasaki if (len < 2) { 74859656Siwasaki printf("\tWrong length for version-1 info tuple\n"); 74959656Siwasaki return; 75059656Siwasaki } 75110217Sphk printf("\tVersion = %d.%d", p[0], p[1]); 75210217Sphk p += 2; 75359656Siwasaki len -= 2; 75459656Siwasaki if (len > 1 && *p != 0xff) { 75559656Siwasaki printf(", Manuf = [%s]", p); 75659656Siwasaki while (*p++ && --len > 0); 75759656Siwasaki } 75859656Siwasaki if (len > 1 && *p != 0xff) { 75959656Siwasaki printf(", card vers = [%s]", p); 76059656Siwasaki while (*p++ && --len > 0); 76159656Siwasaki } else { 76259656Siwasaki printf("\n\tWrong length for version-1 info tuple\n"); 76344701Simp return; 76444701Simp } 76559656Siwasaki putchar('\n'); 76659656Siwasaki if (len > 1 && *p != 0xff) { 76759656Siwasaki printf("\tAddit. info = [%.*s]", len, p); 76859656Siwasaki while (*p++ && --len > 0); 76959656Siwasaki if (len > 1 && *p != 0xff) 77059656Siwasaki printf(",[%.*s]", len, p); 77159656Siwasaki putchar('\n'); 77259656Siwasaki } 77310217Sphk} 77415175Snate 77510217Sphk/* 77659656Siwasaki * CIS_FUNC_ID: Functional ID 77710217Sphk */ 77859656Siwasakistatic void 77959656Siwasakidump_func_id(u_char *p) 78010217Sphk{ 781185033Simp static const char *id[] = { 78259656Siwasaki "Multifunction card", 78359656Siwasaki "Memory card", 78459656Siwasaki "Serial port/modem", 78559656Siwasaki "Parallel port", 78659656Siwasaki "Fixed disk card", 78759656Siwasaki "Video adapter", 78859656Siwasaki "Network/LAN adapter", 78959656Siwasaki "AIMS", 79059656Siwasaki "SCSI card", 79159656Siwasaki "Security" 79259656Siwasaki }; 79359656Siwasaki 79459656Siwasaki printf("\t%s%s%s\n", 79559656Siwasaki (*p <= 9) ? id[*p] : "Unknown function", 79659656Siwasaki (p[1] & 1) ? " - POST initialize" : "", 79759656Siwasaki (p[1] & 2) ? " - Card has ROM" : ""); 79859656Siwasaki} 79959656Siwasaki 80059656Siwasaki/* 80159656Siwasaki * CIS_FUNC_EXT: Dump functional extension tuple. 80259656Siwasaki * (Serial port/modem) 80359656Siwasaki */ 80459656Siwasakistatic void 80559656Siwasakidump_serial_ext(u_char *p, int len) 80659656Siwasaki{ 807185033Simp static const char *type[] = { 80859656Siwasaki "", "Modem", "Data", "Fax", "Voice", "Data modem", 80959656Siwasaki "Fax/modem", "Voice", " (Data)", " (Fax)", " (Voice)" 81059656Siwasaki }; 81159656Siwasaki 81259656Siwasaki if (len < 1) 81310217Sphk return; 81415175Snate switch (p[0]) { 81559656Siwasaki case 0: /* Serial */ 81659656Siwasaki case 8: /* Data */ 81759656Siwasaki case 9: /* Fax */ 81859656Siwasaki case 10: /* Voice */ 81959656Siwasaki printf("\tSerial interface extension:%s\n", type[*p]); 82059656Siwasaki if (len < 4) 82159656Siwasaki goto err; 82215175Snate switch (p[1] & 0x1F) { 82310217Sphk default: 824185033Simp printf("\t\tUnknown device"); 82510217Sphk break; 82610217Sphk case 0: 82710217Sphk printf("\t\t8250 UART"); 82810217Sphk break; 82910217Sphk case 1: 83010217Sphk printf("\t\t16450 UART"); 83110217Sphk break; 83210217Sphk case 2: 83310217Sphk printf("\t\t16550 UART"); 83410217Sphk break; 83515175Snate } 83659656Siwasaki printf(", Parity - %s%s%s%s\n", 83759656Siwasaki (p[2] & 1) ? "Space," : "", 83859656Siwasaki (p[2] & 2) ? "Mark," : "", 83959656Siwasaki (p[2] & 4) ? "Odd," : "", 84059656Siwasaki (p[2] & 8) ? "Even" : ""); 84159656Siwasaki printf("\t\tData bit - %s%s%s%s Stop bit - %s%s%s\n", 84259656Siwasaki (p[3] & 1) ? "5bit," : "", 84359656Siwasaki (p[3] & 2) ? "6bit," : "", 84459656Siwasaki (p[3] & 4) ? "7bit," : "", 84559656Siwasaki (p[3] & 8) ? "8bit," : "", 84659656Siwasaki (p[3] & 0x10) ? "1bit," : "", 84759656Siwasaki (p[3] & 0x20) ? "1.5bit," : "", 84859656Siwasaki (p[3] & 0x40) ? "2bit" : ""); 84910217Sphk break; 85059656Siwasaki case 1: /* Serial */ 85159656Siwasaki case 5: /* Data */ 85259656Siwasaki case 6: /* Fax */ 85359656Siwasaki case 7: /* Voice */ 85459656Siwasaki printf("\t%s interface capabilities:\n", type[*p]); 85559656Siwasaki if (len < 9) 85659656Siwasaki goto err; 85710217Sphk break; 85859656Siwasaki case 2: /* Data */ 85910217Sphk printf("\tData modem services available:\n"); 86010217Sphk break; 86159656Siwasaki case 0x13: /* Fax1 */ 86259656Siwasaki case 0x23: /* Fax2 */ 86359656Siwasaki case 0x33: /* Fax3 */ 86459656Siwasaki printf("\tFax%d/modem services available:\n", *p >> 4); 86510217Sphk break; 86659656Siwasaki case 0x84: /* Voice */ 86710217Sphk printf("\tVoice services available:\n"); 86810217Sphk break; 86959656Siwasaki err: /* warning */ 87059656Siwasaki printf("\tWrong length for serial extension tuple\n"); 87159656Siwasaki return; 87215175Snate } 87310217Sphk} 87415175Snate 87510217Sphk/* 87659656Siwasaki * CIS_FUNC_EXT: Dump functional extension tuple. 87759656Siwasaki * (Fixed disk card) 87810217Sphk */ 87959656Siwasakistatic void 88059656Siwasakidump_disk_ext(u_char *p, int len) 88110217Sphk{ 88259656Siwasaki if (len < 1) 88359656Siwasaki return; 88459656Siwasaki switch (p[0]) { 88559656Siwasaki case 1: /* IDE interface */ 88659656Siwasaki if (len < 2) 88759656Siwasaki goto err; 88859656Siwasaki printf("\tDisk interface: %s\n", 88959656Siwasaki (p[1] & 1) ? "IDE" : "Undefined"); 89059656Siwasaki break; 89159656Siwasaki case 2: /* Master */ 89259656Siwasaki case 3: /* Slave */ 89359656Siwasaki if (len < 3) 89459656Siwasaki goto err; 89559656Siwasaki printf("\tDisk features: %s, %s%s\n", 89659656Siwasaki (p[1] & 0x04) ? "Silicon" : "Rotating", 89759656Siwasaki (p[1] & 0x08) ? "Unique, " : "", 89859656Siwasaki (p[1] & 0x10) ? "Dual" : "Single"); 89959656Siwasaki if (p[2] & 0x7f) 90059656Siwasaki printf("\t\t%s%s%s%s%s%s%s\n", 90159656Siwasaki (p[2] & 0x01) ? "Sleep, " : "", 90259656Siwasaki (p[2] & 0x02) ? "Standby, " : "", 90359656Siwasaki (p[2] & 0x04) ? "Idle, " : "", 90459656Siwasaki (p[2] & 0x08) ? "Low power, " : "", 90559656Siwasaki (p[2] & 0x10) ? "Reg inhibit, " : "", 90659656Siwasaki (p[2] & 0x20) ? "Index, " : "", 90759656Siwasaki (p[2] & 0x40) ? "Iois16" : ""); 90859656Siwasaki break; 90959656Siwasaki err: /* warning */ 91059656Siwasaki printf("\tWrong length for fixed disk extension tuple\n"); 91159656Siwasaki return; 91259656Siwasaki } 91359656Siwasaki} 91410217Sphk 91559656Siwasakistatic void 91659656Siwasakiprint_speed(u_int i) 91759656Siwasaki{ 91859656Siwasaki if (i < 1000) 91959656Siwasaki printf("%u bits/sec", i); 92059656Siwasaki else if (i < 1000000) 92159656Siwasaki printf("%u kb/sec", i / 1000); 92259656Siwasaki else 92359656Siwasaki printf("%u Mb/sec", i / 1000000); 92410217Sphk} 92559656Siwasaki 92659656Siwasaki/* 92759656Siwasaki * CIS_FUNC_EXT: Dump functional extension tuple. 92859656Siwasaki * (Network/LAN adapter) 92959656Siwasaki */ 93059656Siwasakistatic void 93159656Siwasakidump_network_ext(u_char *p, int len) 93259656Siwasaki{ 93359656Siwasaki static const char *tech[] = { 93459656Siwasaki "Undefined", "ARCnet", "Ethernet", "Token ring", 93559656Siwasaki "Localtalk", "FDDI/CDDI", "ATM", "Wireless" 93659656Siwasaki }; 93759656Siwasaki static const char *media[] = { 93859656Siwasaki "Undefined", "UTP", "STP", "Thin coax", 93959656Siwasaki "THICK coax", "Fiber", "900 MHz", "2.4 GHz", 94059656Siwasaki "5.4 GHz", "Diffuse Infrared", "Point to point Infrared" 94159656Siwasaki }; 94259656Siwasaki u_int i = 0; 94359656Siwasaki 94459656Siwasaki if (len < 1) 94559656Siwasaki return; 94659656Siwasaki switch (p[0]) { 94759656Siwasaki case 1: /* Network technology */ 94859656Siwasaki if (len < 2) 94959656Siwasaki goto err; 95059656Siwasaki printf("\tNetwork technology: %s\n", tech[p[1] & 7]); 95159656Siwasaki break; 95259656Siwasaki case 2: /* Network speed */ 95359656Siwasaki if (len < 5) 95459656Siwasaki goto err; 95559656Siwasaki printf("\tNetwork speed: "); 95659656Siwasaki print_speed(tpl32(p + 1)); 95759656Siwasaki putchar('\n'); 95859656Siwasaki break; 95959656Siwasaki case 3: /* Network media */ 96059656Siwasaki if (len < 2) 96159656Siwasaki goto err; 96259656Siwasaki if (p[1] <= 10) 96359656Siwasaki i = p[1]; 96459656Siwasaki printf("\tNetwork media: %s\n", media[i]); 96559656Siwasaki break; 96659656Siwasaki case 4: /* Node ID */ 96759656Siwasaki if (len <= 2 || len < p[1] + 2) 96859656Siwasaki goto err; 96959656Siwasaki printf("\tNetwork node ID:"); 97059656Siwasaki for (i = 0; i < p[1]; i++) 97159656Siwasaki printf(" %02x", p[i + 2]); 97259656Siwasaki putchar('\n'); 97359656Siwasaki break; 974250460Seadler case 5: /* Connector type */ 97559656Siwasaki if (len < 2) 97659656Siwasaki goto err; 97759656Siwasaki printf("\tNetwork connector: %s connector standard\n", 97859656Siwasaki (p[1] == 0) ? "open" : "closed"); 97959656Siwasaki break; 98059656Siwasaki err: /* warning */ 98159656Siwasaki printf("\tWrong length for network extension tuple\n"); 98259656Siwasaki return; 98359656Siwasaki } 98459656Siwasaki} 98559656Siwasaki 98659656Siwasaki/* 98759656Siwasaki * CIS_LONGLINK_MFC: Long link to next chain for Multi function card 98859656Siwasaki */ 98959656Siwasakistatic void 99059656Siwasakidump_longlink_mfc(u_char *p, int len) 99159656Siwasaki{ 99259656Siwasaki u_int i, n = *p++; 99359656Siwasaki 99459656Siwasaki --len; 99559656Siwasaki for (i = 0; i < n; i++) { 99659656Siwasaki if (len < 5) { 99759656Siwasaki printf("\tWrong length for long link MFC tuple\n"); 99859656Siwasaki return; 99959656Siwasaki } 100059656Siwasaki printf("\tFunction %d: %s memory, address 0x%x\n", 100159656Siwasaki i, (*p ? "common" : "attribute"), tpl32(p + 1)); 100259656Siwasaki p += 5; 100359656Siwasaki len -= 5; 100459656Siwasaki } 100559656Siwasaki} 100659656Siwasaki 100759656Siwasaki/* 100859656Siwasaki * CIS_DEVICEGEO, CIS_DEVICEGEO_A: 100959656Siwasaki * Geometry info for common/attribute memory 101059656Siwasaki */ 101159656Siwasakistatic void 101259656Siwasakidump_device_geo(u_char *p, int len) 101359656Siwasaki{ 101459656Siwasaki while (len >= 6) { 101559656Siwasaki printf("\twidth = %d, erase = 0x%x, read = 0x%x, write = 0x%x\n" 101659656Siwasaki "\t\tpartition = 0x%x, interleave = 0x%x\n", 101759656Siwasaki p[0], 1 << (p[1] - 1), 101859656Siwasaki 1 << (p[2] - 1), 1 << (p[3] - 1), 101959656Siwasaki 1 << (p[4] - 1), 1 << (p[5] - 1)); 102059656Siwasaki len -= 6; 102159656Siwasaki } 102259656Siwasaki} 102359656Siwasaki 102459656Siwasaki/* 102559656Siwasaki * CIS_INFO_V2: Print version-2 info 102659656Siwasaki */ 102759656Siwasakistatic void 102859656Siwasakidump_info_v2(u_char *p, int len) 102959656Siwasaki{ 103059656Siwasaki if (len < 9) { 103159656Siwasaki printf("\tWrong length for version-2 info tuple\n"); 103259656Siwasaki return; 103359656Siwasaki } 103459656Siwasaki printf("\tVersion = 0x%x, compliance = 0x%x, dindex = 0x%x\n", 103559656Siwasaki p[0], p[1], tpl16(p + 2)); 103659656Siwasaki printf("\tVspec8 = 0x%x, vspec9 = 0x%x, nhdr = %d\n", 103759656Siwasaki p[6], p[7], p[8]); 103859656Siwasaki p += 9; 103959656Siwasaki len -= 9; 104059656Siwasaki if (len <= 1 || *p == 0xff) 104159656Siwasaki return; 104259656Siwasaki printf("\tVendor = [%.*s]", len, p); 104359656Siwasaki while (*p++ && --len > 0); 104459656Siwasaki if (len > 1 && *p != 0xff) 104559656Siwasaki printf(", info = [%.*s]", len, p); 104659656Siwasaki putchar('\n'); 104759656Siwasaki} 104859656Siwasaki 104959656Siwasaki/* 105059656Siwasaki * CIS_ORG: Organization 105159656Siwasaki */ 105259656Siwasakistatic void 105359656Siwasakidump_org(u_char *p, int len) 105459656Siwasaki{ 105559656Siwasaki if (len < 1) { 105659656Siwasaki printf("\tWrong length for organization tuple\n"); 105759656Siwasaki return; 105859656Siwasaki } 105959656Siwasaki switch (*p) { 106059656Siwasaki case 0: 106159656Siwasaki printf("\tFilesystem"); 106259656Siwasaki break; 106359656Siwasaki case 1: 106459656Siwasaki printf("\tApp specific"); 106559656Siwasaki break; 106659656Siwasaki case 2: 106759656Siwasaki printf("\tCode"); 106859656Siwasaki break; 106959656Siwasaki default: 107059656Siwasaki if (*p < 0x80) 107159656Siwasaki printf("\tReserved"); 107259656Siwasaki else 107359656Siwasaki printf("\tVendor specific"); 107459656Siwasaki break; 107559656Siwasaki } 107659656Siwasaki printf(" [%.*s]\n", len - 1, p + 1); 107759656Siwasaki} 107859656Siwasaki 107959656Siwasakistatic void 108059656Siwasakiprint_size(u_int i) 108159656Siwasaki{ 108259656Siwasaki if (i < 1024) 108359656Siwasaki printf("%ubits", i); 108459656Siwasaki else if (i < 1024*1024) 108559656Siwasaki printf("%ukb", i / 1024); 108659656Siwasaki else 108759656Siwasaki printf("%uMb", i / (1024*1024)); 108859656Siwasaki} 108959656Siwasaki 109059656Siwasaki/* 109159656Siwasaki * CIS_BAR: Base address register for CardBus 109259656Siwasaki */ 109359656Siwasakistatic void 109459656Siwasakidump_bar(u_char *p, int len) 109559656Siwasaki{ 109659656Siwasaki if (len < 6) { 109759656Siwasaki printf("\tWrong length for BAR tuple\n"); 109859656Siwasaki return; 109959656Siwasaki } 110059656Siwasaki printf("\tBAR %d: size = ", *p & 7); 110159656Siwasaki print_size(tpl32(p + 2)); 110259656Siwasaki printf(", %s%s%s%s\n", 110359656Siwasaki (*p & 0x10) ? "I/O" : "Memory", 110459656Siwasaki (*p & 0x20) ? ", Prefetch" : "", 110559656Siwasaki (*p & 0x40) ? ", Cacheable" : "", 110659656Siwasaki (*p & 0x80) ? ", <1Mb" : ""); 110759656Siwasaki} 1108