diff options
Diffstat (limited to 'usr.sbin/dumpcis')
-rw-r--r-- | usr.sbin/dumpcis/Makefile | 9 | ||||
-rw-r--r-- | usr.sbin/dumpcis/Makefile.depend | 18 | ||||
-rw-r--r-- | usr.sbin/dumpcis/cardinfo.h | 205 | ||||
-rw-r--r-- | usr.sbin/dumpcis/cis.h | 279 | ||||
-rw-r--r-- | usr.sbin/dumpcis/dumpcis.8 | 48 | ||||
-rw-r--r-- | usr.sbin/dumpcis/main.c | 58 | ||||
-rw-r--r-- | usr.sbin/dumpcis/printcis.c | 1105 | ||||
-rw-r--r-- | usr.sbin/dumpcis/readcis.c | 377 | ||||
-rw-r--r-- | usr.sbin/dumpcis/readcis.h | 61 |
9 files changed, 2160 insertions, 0 deletions
diff --git a/usr.sbin/dumpcis/Makefile b/usr.sbin/dumpcis/Makefile new file mode 100644 index 0000000..7a5a590 --- /dev/null +++ b/usr.sbin/dumpcis/Makefile @@ -0,0 +1,9 @@ +# pccardc Makefile +# +# $FreeBSD$ + +PROG= dumpcis +MAN= dumpcis.8 +SRCS= main.c readcis.c printcis.c + +.include <bsd.prog.mk> diff --git a/usr.sbin/dumpcis/Makefile.depend b/usr.sbin/dumpcis/Makefile.depend new file mode 100644 index 0000000..3646e2e --- /dev/null +++ b/usr.sbin/dumpcis/Makefile.depend @@ -0,0 +1,18 @@ +# $FreeBSD$ +# Autogenerated - do NOT edit! + +DIRDEPS = \ + gnu/lib/csu \ + gnu/lib/libgcc \ + include \ + include/xlocale \ + lib/${CSU_DIR} \ + lib/libc \ + lib/libcompiler_rt \ + + +.include <dirdeps.mk> + +.if ${DEP_RELDIR} == ${_DEP_RELDIR} +# local dependencies - needed for -jN in clean tree +.endif diff --git a/usr.sbin/dumpcis/cardinfo.h b/usr.sbin/dumpcis/cardinfo.h new file mode 100644 index 0000000..9489067 --- /dev/null +++ b/usr.sbin/dumpcis/cardinfo.h @@ -0,0 +1,205 @@ +/* + * Include file for PCMCIA user process interface + * + *------------------------------------------------------------------------- + */ +/*- + * Copyright (c) 1995 Andrew McRae. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* $FreeBSD$ */ + +#ifndef _PCCARD_CARDINFO_H_ +#define _PCCARD_CARDINFO_H_ + +#ifndef _KERNEL +#include <sys/types.h> +#endif +#include <sys/ioccom.h> + +#define PIOCGSTATE _IOR('P', 1, struct slotstate) /* Get slot state */ +#define PIOCGMEM _IOWR('P', 2, struct mem_desc) /* Get memory map */ +#define PIOCSMEM _IOW('P', 3, struct mem_desc) /* Set memory map */ +#define PIOCGIO _IOWR('P', 4, struct io_desc) /* Get I/O map */ +#define PIOCSIO _IOW('P', 5, struct io_desc) /* Set I/O map */ +#define PIOCSDRV _IOWR('P', 6, struct dev_desc) /* Set driver */ +#define PIOCRWFLAG _IOW('P', 7, int) /* Set flags for drv use */ +#define PIOCRWMEM _IOWR('P', 8, unsigned long) /* Set mem for drv use */ +#define PIOCSPOW _IOW('P', 9, struct power) /* Set power structure */ +#define PIOCSVIR _IOW('P', 10, int) /* Virtual insert/remove */ +#define PIOCSBEEP _IOW('P', 11, int) /* Select Beep */ +#define PIOCSRESOURCE _IOWR('P', 12, struct pccard_resource) /* get resource info */ +/* + * Debug codes. + */ +#define PIOCGREG _IOWR('P',100, struct pcic_reg) /* get reg */ +#define PIOCSREG _IOW('P', 101, struct pcic_reg) /* Set reg */ + +/* + * Slot states for PIOCGSTATE + * + * Here's a state diagram of all the possible states: + * + * power x 1 + * ------------------- + * / \ + * / v + * resume +----------+ power x 0 +----------+ + * ------->| inactive |<--------------| filled | + * / +----------+ +----------+ + * / / \ ^ | + * nil <--------- \ insert or | | suspend or + * suspend \ power x 1 | | eject + * \ | v + * \ +----------+ + * ----------->| empty | + * eject +----------+ + * + * Note, the above diagram is for the state. On suspend, the laststate + * gets set to suspend to tell pccardd what happened. Also the nil state + * means that when the no state change has happened. Note: if you eject + * while suspended in the inactive state, you will return to the + * empty state if you do not insert a new card and to the inactive state + * if you do insert a new card. + * + * Some might argue that inactive should be sticky forever and + * eject/insert shouldn't take it out of that state. They might be + * right. On the other hand, some would argue that eject resets all + * state. They might be right. They both can't be right. The above + * represents a reasonable compromise between the two. + * + * Some bridges allow one to query to see if the card was changed while + * we were suspended. Others do not. We make no use of this functionality + * at this time. + */ +enum cardstate { noslot, empty, suspend, filled, inactive }; + +/* + * Descriptor structure for memory map. + */ +struct mem_desc { + int window; /* Memory map window number (0-4) */ + int flags; /* Flags - see below */ + caddr_t start; /* System memory start */ + int size; /* Size of memory area */ + unsigned long card; /* Card memory address */ +}; + +#define MDF_16BITS 0x01 /* Memory is 16 bits wide */ +#define MDF_ZEROWS 0x02 /* Set no wait states for memory */ +#define MDF_WS0 0x04 /* Wait state flags */ +#define MDF_WS1 0x08 +#define MDF_ATTR 0x10 /* Memory is attribute memory */ +#define MDF_WP 0x20 /* Write protect memory */ +#define MDF_ACTIVE 0x40 /* Context active (read-only) */ + +/* + * Descriptor structure for I/O map + */ +struct io_desc { + int window; /* I/O map number (0-1) */ + int flags; /* Flags - see below */ + int start; /* I/O port start */ + int size; /* Number of port addresses */ +}; + +#define IODF_WS 0x01 /* Set wait states for 16 bit I/O access */ +#define IODF_16BIT 0x02 /* I/O access are 16 bit */ +#define IODF_CS16 0x04 /* Allow card selection of 16 bit access */ +#define IODF_ZEROWS 0x08 /* No wait states for 8 bit I/O */ +#define IODF_ACTIVE 0x10 /* Context active (read-only) */ + +/* + * Device descriptor for allocation of driver. + */ +#define DEV_MISC_LEN 36 +#define DEV_MAX_CIS_LEN 40 +struct dev_desc { + char name[16]; /* Driver name */ + int unit; /* Driver unit number */ + unsigned long mem; /* Memory address of driver */ + int memsize; /* Memory size (if used) */ + int iobase; /* base of I/O ports */ + int iosize; /* Length of I/O ports */ + int irqmask; /* Interrupt number(s) to allocate */ + int flags; /* Device flags */ + uint8_t misc[DEV_MISC_LEN]; /* For any random info */ + uint8_t manufstr[DEV_MAX_CIS_LEN]; + uint8_t versstr[DEV_MAX_CIS_LEN]; + uint8_t cis3str[DEV_MAX_CIS_LEN]; + uint8_t cis4str[DEV_MAX_CIS_LEN]; + uint32_t manufacturer; /* Manufacturer ID */ + uint32_t product; /* Product ID */ + uint32_t prodext; /* Product ID (extended) */ +}; +#define DEV_DESC_HAS_SIZE 1 + +struct pcic_reg { + unsigned char reg; + unsigned char value; +}; + +/* + * Slot information. Used to read current status of slot. + */ +struct slotstate { + enum cardstate state; /* Current state of slot */ + enum cardstate laststate; /* Previous state of slot */ + int maxmem; /* Max allowed memory windows */ + int maxio; /* Max allowed I/O windows */ + int irqs; /* Bitmap of IRQs allowed */ + int flags; /* Capability flags */ +}; + +/* + * The power values are in volts * 10, e.g. 5V is 50, 3.3V is 33. + */ +struct power { + int vcc; + int vpp; +}; + +/* + * The PC-Card resource IOC_GET_RESOURCE_RANGE + */ +struct pccard_resource { + int type; + u_long size; + u_long min; + u_long max; + u_long resource_addr; +}; + + +/* + * Other system limits + */ +#define MAXSLOT 16 +#define NUM_MEM_WINDOWS 10 +#define NUM_IO_WINDOWS 6 +#define CARD_DEVICE "/dev/card%d" /* String for snprintf */ +#define PCCARD_MEMSIZE (4*1024) + +#endif /* !_PCCARD_CARDINFO_H_ */ diff --git a/usr.sbin/dumpcis/cis.h b/usr.sbin/dumpcis/cis.h new file mode 100644 index 0000000..6cc935b --- /dev/null +++ b/usr.sbin/dumpcis/cis.h @@ -0,0 +1,279 @@ +/* + * PCMCIA card structures and defines. + * These defines relate to the user level + * structures and card information, not + * driver/process communication. + *------------------------------------------------------------------------- + */ +/*- + * Copyright (c) 1995 Andrew McRae. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +/* + * Card Information Structure tuples definitions + * The structure of a tuple is basically: + * + * Tuple_code + * Tuple_data_length + * Tuple_data ... + * + * Tuples are contiguous in attribute memory, and + * are terminated with a 0xFF for the tuple code or + * the tuple length. + */ +#ifndef _PCCARD_CIS_H +#define _PCCARD_CIS_H + +#define CIS_NULL 0 /* Empty tuple */ +#define CIS_MEM_COMMON 0x01 /* Device descriptor, common memory */ +#define CIS_LONGLINK_CB 0x02 /* Long link to next chain for CardBus */ +#define CIS_INDIRECT 0x03 /* Indirect access */ +#define CIS_CONF_MAP_CB 0x04 /* Card Configuration map for CardBus */ +#define CIS_CONFIG_CB 0x05 /* Card Configuration entry for CardBus */ +#define CIS_LONGLINK_MFC 0x06 /* Long link to next chain for Multi function card */ +#define CIS_BAR 0x07 /* Base address register for CardBus */ +#define CIS_CHECKSUM 0x10 /* Checksum */ +#define CIS_LONGLINK_A 0x11 /* Link to Attribute memory */ +#define CIS_LONGLINK_C 0x12 /* Link to Common memory */ +#define CIS_LINKTARGET 0x13 /* Linked tuple must start with this. */ +#define CIS_NOLINK 0x14 /* Assume no common memory link tuple. */ +#define CIS_INFO_V1 0x15 /* Card info data, version 1 */ +#define CIS_ALTSTR 0x16 /* Alternate language string tuple. */ +#define CIS_MEM_ATTR 0x17 /* Device descriptor, Attribute memory */ +#define CIS_JEDEC_C 0x18 /* JEDEC descr for common memory */ +#define CIS_JEDEC_A 0x19 /* JEDEC descr for Attribute memory */ +#define CIS_CONF_MAP 0x1A /* Card Configuration map */ +#define CIS_CONFIG 0x1B /* Card Configuration entry */ +#define CIS_DEVICE_OC 0x1C /* Other conditions info - common memory */ +#define CIS_DEVICE_OA 0x1D /* Other conditions info - attribute memory */ +#define CIS_DEVICEGEO 0x1E /* Geometry info for common memory */ +#define CIS_DEVICEGEO_A 0x1F /* Geometry info for attribute memory */ +#define CIS_MANUF_ID 0x20 /* Card manufacturer's ID */ +#define CIS_FUNC_ID 0x21 /* Function of card */ +#define CIS_FUNC_EXT 0x22 /* Functional extension */ +/* + * Data recording format tuples. + */ +#define CIS_SW_INTERLV 0x23 /* Software interleave */ +#define CIS_VERS_2 0x40 /* Card info data, version 2 */ +#define CIS_FORMAT 0x41 /* Memory card format */ +#define CIS_GEOMETRY 0x42 /* Disk sector layout */ +#define CIS_BYTEORDER 0x43 /* Byte order of memory data */ +#define CIS_DATE 0x44 /* Format data/time */ +#define CIS_BATTERY 0x45 /* Battery replacement date */ +#define CIS_ORG 0x46 /* Organization of data on card */ +#define CIS_END 0xFF /* Termination code */ + +/* + * Internal tuple definitions. + * + * Device descriptor for memory (CIS_MEM_ATTR, CIS_MEM_COMMON) + * + * Byte 1: + * 0xF0 - Device type + * 0x08 - Write protect switch + * 0x07 - Speed index (7 = extended speed) + * Byte 2: Extended speed (bit 7 = another follows) + * Byte 3: (ignored if 0xFF) + * 0xF8 - Addressable units (0's numbered) + * 0x07 - Unit size + * The three byte sequence is repeated until byte 1 == 0xFF + */ + +/* + * CIS_INFO_V1 - Version one card information. + * + * Byte 1: Major version number (should be 4) + * Byte 2: Minor version number (should be 1) + * Byte 3-x: Null terminated Manufacturer name + * Byte x-x: Null terminated product name + * Byte x-x: Null terminated additional info 1 + * Byte x-x: Null terminated additional info 2 + * Byte x: final byte must be 0xFF + */ +#define CIS_MAJOR_VERSION 4 +#define CIS_MINOR_VERSION 1 + +/* + * CIS_CONF_MAP - Provides an address map for the card + * configuration register(s), and a max value + * identifying the last configuration tuple. + * + * Byte 1: + * 0x3C - Register mask size (0's numbered) + * 0x03 - Register address size (0's numbered) + * Byte 2: + * 0x3F - ID of last configuration. + * Byte 3-n: Card register address (size is determined by + * the value in byte 1). + * Byte x-x: Card register masks (size determined by the + * value in byte 1) + */ + +/* + * CIS_CONFIG - Card configuration entry. Multiple tuples may + * exist of this type, each one describing a different + * memory/I-O map that can be used to address this card. + * The first one usually has extra config data about the + * card features. The final configuration tuple number + * is stored in the CIS_CONF_MAP tuple so that the complete + * list can be scanned. + * + * Byte 1: + * 0x3F - Configuration ID number. + * 0x40 - Indicates this is the default configuration + * 0x80 - Interface byte exists + * Byte 2: (exists only if bit 0x80 set in byte 1) + * 0x0F - Interface type value + * 0x10 - Battery voltage detect + * 0x20 - Write protect active + * 0x40 - RdyBsy active bit + * 0x80 - Wait signal required + * Byte 3: (features byte) + * 0x03 - Power sub-tuple(s) exists + * 0x04 - Timing sub-tuple exists + * 0x08 - I/O space sub-tuple exists + * 0x10 - IRQ sub-tuple exists + * 0x60 - Memory space sub-tuple(s) exists + * 0x80 - Miscellaneous sub-tuple exists + */ +#define CIS_FEAT_POWER(x) ((x) & 0x3) +#define CIS_FEAT_TIMING 0x4 +#define CIS_FEAT_I_O 0x8 +#define CIS_FEAT_IRQ 0x10 +#define CIS_FEAT_MEMORY(x) (((x) >> 5) & 0x3) +#define CIS_FEAT_MISC 0x80 +/* + * Depending on whether the "features" byte has the corresponding + * bit set, a number of sub-tuples follow. Some features have + * more than one sub-tuple, depending on the count within the + * features byte (e.g power feature bits allows up to 3 sub-tuples). + * + * Power structure sub-tuple: + * Byte 1: parameter exists - Each bit (starting from 0x01) indicates + * that a parameter block exists - up to 8 parameter blocks + * are therefore allowed). + * Byte 2: + * 0x7F - Parameter data + * 0x80 - More bytes follow (0 = last byte) + * + * Timing sub-tuple + * Byte 1: + * 0x03 - Wait scale + * 0x1C - Ready scale + * 0xE0 - Reserved scale + * Byte 2: extended wait scale if wait scale != 3 + * Byte 3: extended ready scale if ready scale != 7 + * Byte 4: extended reserved scale if reserved scale != 7 + */ +#define CIS_WAIT_SCALE(x) ((x) & 0x3) +#define CIS_READY_SCALE(x) (((x)>>2) & 0x7) +#define CIS_RESERVED_SCALE(x) (((x)>>5) & 0x7) +/* + * I/O mapping sub-tuple: + * Byte 1: + * 0x1F - I/O address lines + * 0x20 - 8 bit I/O + * 0x40 - 16 bit I/O + * 0x80 - I/O range?? + * Byte 2: + * 0x0F - 0's numbered count of I/O block subtuples following. + * 0x30 - Size of I/O address value within subtuple. Values + * can be 1 (8 bits), 2 (16 bits) or 3 (32 bits). + * 0xC0 - Size of I/O port block size value within subtuple. + * I/O block sub-tuples, count from previous block: + * Byte 1-n: I/O start address + * Byte x-x: Size of I/O port block. + */ +#define CIS_IO_ADDR(x) ((x) & 0x1F) +#define CIS_IO_8BIT 0x20 +#define CIS_IO_16BIT 0x40 +#define CIS_IO_RANGE 0x80 +#define CIS_IO_BLKS(x) ((x) & 0xF) +#define CIS_IO_ADSZ(x) (((x)>>4) & 3) +#define CIS_IO_BLKSZ(x) (((x)>>6) & 3) +/* + * IRQ sub-tuple. + * Byte 1: + * 0x0F - Irq number or mask bits + * 0x10 - IRQ mask values exist + * 0x20 - Level triggered interrupts + * 0x40 - Pulse triggered requests + * 0x80 - Interrupt sharing. + * Byte 2-3: Interrupt req mask (if 0x10 of byte 1 set). + */ +#define CIS_IRQ_IRQN(x) ((x) & 0xF) +#define CIS_IRQ_MASK 0x10 +#define CIS_IRQ_LEVEL 0x20 +#define CIS_IRQ_PULSE 0x40 +#define CIS_IRQ_SHARING 0x80 +/* + * Memory block subtuple. Depending on the features bits, the + * following subtuples are used: + * mem features == 1 + * Byte 1-2: upper 16 bits of 24 bit memory length. + * mem features == 2 + * Byte 1-2: upper 16 bits of 24 bit memory length. + * Byte 3-4: upper 16 bits of 24 bit memory address. + * mem_features == 3 + * Byte 1: + * 0x07 - 0's numbered count of memory sub-tuples + * 0x18 - Memory length size (1's numbered) + * 0x60 - Memory address size (1's numbered) + * 0x80 - Host address value exists + * Memory sub-tuples follow: + * Byte 1-n: Memory length value (<< 8) + * Byte n-n: Memory card address value (<< 8) + * Byte n-n: Memory host address value (<< 8) + */ +#define CIS_FEAT_MEM_NONE 0 /* No memory config */ +#define CIS_FEAT_MEM_LEN 1 /* Just length */ +#define CIS_FEAT_MEM_ADDR 2 /* Card address & length */ +#define CIS_FEAT_MEM_WIN 3 /* Multiple windows */ + +#define CIS_MEM_WINS(x) (((x) & 0x7)+1) +#define CIS_MEM_LENSZ(x) (((x) >> 3) & 0x3) +#define CIS_MEM_ADDRSZ(x) (((x) >> 5) & 0x3) +#define CIS_MEM_HOST 0x80 +/* + * Misc sub-tuple. + * Byte 1: + * Byte 2: + * 0x0c - DMA Request Signal + * 00 - not support DMA + * 01 - use SPKR# line + * 10 - use IOIS16# line + * 11 - use INPACK# line + * 0x10 - DMA Width + * 0 - 8 bit DMA + * 1 - 16 bit DMA + */ +#define CIS_MISC_DMA_WIDTH(x) (((x) & 0x10) >> 4) +#define CIS_MISC_DMA_REQ(x) (((x) >> 2) & 0x3) + +#endif /* _PCCARD_CIS_H */ diff --git a/usr.sbin/dumpcis/dumpcis.8 b/usr.sbin/dumpcis/dumpcis.8 new file mode 100644 index 0000000..86949df --- /dev/null +++ b/usr.sbin/dumpcis/dumpcis.8 @@ -0,0 +1,48 @@ +.\" +.\" Copyright (c) 2006 M. Warner Losh <imp@FreeBSD.org> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $FreeBSD$ +.\" +.Dd October 18, 2006 +.Dt DUMPCIS 8 +.Os +.Sh NAME +.Nm dumpcis +.Nd PC Card and Cardbus (PCMCIA) CIS display tool +.Sh SYNOPSIS +.Nm +.Ar +.Sh DESCRIPTION +The +.Nm +utility translates a raw CIS stream into human readable form. +.Sh SEE ALSO +.Xr cardbus 4 , +.Xr cbb 4 , +.Xr pccard 4 +.Sh AUTHORS +The original version was written by +.An Warner Losh Aq Mt imp@FreeBSD.org . diff --git a/usr.sbin/dumpcis/main.c b/usr.sbin/dumpcis/main.c new file mode 100644 index 0000000..2e66506 --- /dev/null +++ b/usr.sbin/dumpcis/main.c @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2006 M. Warner Losh. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> +#include "readcis.h" + +static void +scanfile(char *name) +{ + int fd; + struct tuple_list *tl; + + fd = open(name, O_RDONLY); + if (fd < 0) + return; + tl = readcis(fd); + if (tl) { + printf("Configuration data for file %s\n", + name); + dumpcis(tl); + freecis(tl); + } + close(fd); +} + +int +main(int argc, char **argv) +{ + for (argc--, argv++; argc; argc--, argv++) + scanfile(*argv); + return 0; +} diff --git a/usr.sbin/dumpcis/printcis.c b/usr.sbin/dumpcis/printcis.c new file mode 100644 index 0000000..ff2ac90 --- /dev/null +++ b/usr.sbin/dumpcis/printcis.c @@ -0,0 +1,1105 @@ +/* + * Copyright (c) 1995 Andrew McRae. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef lint +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> +#include <unistd.h> +#include <sys/ioctl.h> + +#include "cis.h" +#include "readcis.h" + +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, const 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 tuple_list *tlist) +{ + struct tuple *tp; + struct tuple_list *tl; + int count = 0, sz, ad, i; + u_char *p; + int func = 0; + + for (tl = tlist; tl; tl = tl->next) + for (tp = tl->tuples; tp; tp = tp->next) { + printf("Tuple #%d, code = 0x%x (%s), length = %d\n", + ++count, tp->code, tuple_name(tp->code), tp->length); + p = tp->data; + sz = tp->length; + ad = 0; + while (sz > 0) { + printf(" %03x: ", ad); + for (i = 0; i < ((sz < 16) ? sz : 16); i++) + printf(" %02x", p[i]); + printf("\n"); + sz -= 16; + p += 16; + ad += 16; + } + switch (tp->code) { + default: + break; + 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 */ + 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", + tpl32(tp->data)); + break; + case CIS_LONGLINK_C: /* 0x12 */ + printf("\tLong link to common memory, address 0x%x\n", + tpl32(tp->data)); + break; + case CIS_INFO_V1: /* 0x15 */ + dump_info_v1(tp->data, tp->length); + break; + case CIS_ALTSTR: /* 0x16 */ + break; + case CIS_MEM_ATTR: /* 0x17 */ + dump_device_desc(tp->data, tp->length, "Attribute"); + break; + case CIS_JEDEC_C: /* 0x18 */ + case CIS_JEDEC_A: /* 0x19 */ + break; + case CIS_CONF_MAP: /* 0x1A */ + dump_config_map(tp); + break; + case CIS_CONFIG: /* 0x1B */ + dump_cis_config(tp); + break; + case CIS_DEVICE_OC: /* 0x1C */ + case CIS_DEVICE_OA: /* 0x1D */ + dump_other_cond(tp->data, tp->length); + break; + case CIS_DEVICEGEO: /* 0x1E */ + 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", + tpl16(tp->data), + tpl16(tp->data + 2)); + break; + case CIS_FUNC_ID: /* 0x21 */ + func = tp->data[0]; + dump_func_id(tp->data); + break; + case CIS_FUNC_EXT: /* 0x22 */ + switch (func) { + case 2: + dump_serial_ext(tp->data, tp->length); + break; + case 4: + dump_disk_ext(tp->data, tp->length); + break; + case 6: + dump_network_ext(tp->data, tp->length); + break; + } + 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; + } + } +} + +/* + * CIS_CONF_MAP : Dump configuration map tuple. + * CIS_CONF_MAP_CB: Dump configuration map for CardBus + */ +static void +dump_config_map(struct tuple *tp) +{ + u_char *p = tp->data, x; + int rlen, mlen = 0; + int i; + + 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' : '-'); + putchar(' '); + } + } + i = tp->length - (rlen + mlen + 2); + if (i) { + if (!mlen) + putchar('\t'); + printf("%d bytes in subtuples", i); + } + if (mlen || i) + putchar('\n'); +} + +/* + * Dump power descriptor. + * call from dump_cis_config() + */ +static int +print_pwr_desc(u_char *p) +{ + int len = 1, i; + u_char mask; + const char **expp; + static const 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 const char *vexp[] = + {"10uV", "100uV", "1mV", "10mV", "100mV", "1V", "10V", "100V"}; + static const char *cexp[] = + {"10nA", "1uA", "10uA", "100uA", "1mA", "10mA", "100mA", "1A"}; + static const 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 const 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 const char *exp[] = + {"1 ns", "10 ns", "100 ns", "1 us", "10 us", "100 us", + "1 ms", "10 ms"}; + static const 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, const 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) +{ + 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)" : ""); + + /* Interface byte exists */ + if (tp->code == CIS_CONFIG && (*p & 0x80)) { + p++; + printf("\tInterface byte = 0x%x ", *p); + switch (*p & 0xF) { /* Interface type */ + default: + printf("(reserved)"); + break; + case 0: + printf("(memory)"); + break; + case 1: + printf("(I/O)"); + break; + case 4: + case 5: + case 6: + case 7: + case 8: + printf("(custom)"); + break; + } + c = ' '; + if (*p & 0x10) { /* Battery voltage detect */ + printf(" BVD1/2 active"); + c = ','; + } + if (*p & 0x20) { /* Write protect active */ + printf("%c card WP active", c); /* Write protect */ + c = ','; + } + if (*p & 0x40) { /* RdyBsy active bit */ + printf("%c +RDY/-BSY active", c); + c = ','; + } + if (*p & 0x80) /* Wait signal required */ + printf("%c wait signal supported", c); + printf("\n"); + } + + /* features byte */ + p++; + feat = *p++; + + /* Power structure sub-tuple */ + switch (CIS_FEAT_POWER(feat)) { /* Power sub-tuple(s) exists */ + case 0: + break; + case 1: + printf("\tVcc pwr:\n"); + p += print_pwr_desc(p); + break; + case 2: + printf("\tVcc pwr:\n"); + p += print_pwr_desc(p); + printf("\tVpp pwr:\n"); + p += print_pwr_desc(p); + break; + case 3: + printf("\tVcc pwr:\n"); + p += print_pwr_desc(p); + printf("\tVpp1 pwr:\n"); + p += print_pwr_desc(p); + printf("\tVpp2 pwr:\n"); + p += print_pwr_desc(p); + break; + } + + /* 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++, j); + printf("\n"); + } + j = CIS_READY_SCALE(i); + if (j != 7) { + printf("\tRDY/BSY scale "); + print_ext_speed(*p++, j); + printf("\n"); + } + j = CIS_RESERVED_SCALE(i); + if (j != 7) { + printf("\tExternal scale "); + print_ext_speed(*p++, j); + printf("\n"); + } + } + + /* 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++; + } + } + + /* 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++; + } + } + + /* 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++; + } + putchar('\n'); + } + 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'); + } + } +} + +/* + * CIS_DEVICE_OC, CIS_DEVICE_OA: + * Dump other conditions for common/attribute memory + */ +static void +dump_other_cond(u_char *p, int len) +{ + if (p[0] && len > 0) { + printf("\t"); + if (p[0] & 1) + printf("(MWAIT)"); + if (p[0] & 2) + printf(" (3V card)"); + if (p[0] & 0x80) + printf(" (Extension bytes follow)"); + printf("\n"); + } +} + +/* + * CIS_MEM_COMMON, CIS_MEM_ATTR: + * Common / Attribute memory descripter + */ +static void +dump_device_desc(u_char *p, int len, const char *type) +{ + static const char *un_name[] = + {"512b", "2Kb", "8Kb", "32Kb", "128Kb", "512Kb", "2Mb", "reserved"}; + static const char *speed[] = + {"No speed", "250nS", "200nS", "150nS", + "100nS", "Reserved", "Reserved"}; + static const char *dev[] = + {"No device", "Mask ROM", "OTPROM", "UV EPROM", + "EEPROM", "FLASH EEPROM", "SRAM", "DRAM", + "Reserved", "Reserved", "Reserved", "Reserved", + "Reserved", "Function specific", "Extended", + "Reserved"}; + int count = 0; + + while (*p != 0xFF && len > 0) { + u_char x; + + x = *p++; + len -= 2; + if (count++ == 0) + printf("\t%s memory device information:\n", type); + printf("\t\tDevice number %d, type %s, WPS = %s\n", + count, dev[x >> 4], (x & 0x8) ? "ON" : "OFF"); + if ((x & 7) == 7) { + len--; + if (*p) { + printf("\t\t"); + print_ext_speed(*p, 0); + while (*p & 0x80) { + p++; + len--; + } + } + p++; + } else + printf("\t\tSpeed = %s", speed[x & 7]); + printf(", Memory block size = %s, %d units\n", + un_name[*p & 7], (*p >> 3) + 1); + p++; + } +} + +/* + * CIS_INFO_V1: Print version-1 info + */ +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; + 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; + } + 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'); + } +} + +/* + * CIS_FUNC_ID: Functional ID + */ +static void +dump_func_id(u_char *p) +{ + static const 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) +{ + static const char *type[] = { + "", "Modem", "Data", "Fax", "Voice", "Data modem", + "Fax/modem", "Voice", " (Data)", " (Fax)", " (Voice)" + }; + + if (len < 1) + return; + switch (p[0]) { + 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\tUnknown device"); + break; + case 0: + printf("\t\t8250 UART"); + break; + case 1: + printf("\t\t16450 UART"); + break; + case 2: + printf("\t\t16550 UART"); + break; + } + 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: /* 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: /* Data */ + printf("\tData modem services available:\n"); + break; + case 0x13: /* Fax1 */ + case 0x23: /* Fax2 */ + case 0x33: /* Fax3 */ + printf("\tFax%d/modem services available:\n", *p >> 4); + break; + case 0x84: /* Voice */ + printf("\tVoice services available:\n"); + break; + err: /* warning */ + printf("\tWrong length for serial extension tuple\n"); + return; + } +} + +/* + * CIS_FUNC_EXT: Dump functional extension tuple. + * (Fixed disk card) + */ +static void +dump_disk_ext(u_char *p, int len) +{ + 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; + } +} + +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: /* Connector 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" : ""); +} diff --git a/usr.sbin/dumpcis/readcis.c b/usr.sbin/dumpcis/readcis.c new file mode 100644 index 0000000..25bd396 --- /dev/null +++ b/usr.sbin/dumpcis/readcis.c @@ -0,0 +1,377 @@ +/* + * Copyright (c) 1995 Andrew McRae. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef lint +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> +#include <unistd.h> + +#include "cardinfo.h" +#include "cis.h" +#include "readcis.h" + +static int ck_linktarget(int, off_t, int); +static struct tuple_list *read_one_tuplelist(int, int, off_t); +static struct tuple_list *read_tuples(int); +static struct tuple *find_tuple_in_list(struct tuple_list *, unsigned char); +static struct tuple_info *get_tuple_info(unsigned char); + +static struct tuple_info tuple_info[] = { + {"Null tuple", CIS_NULL, 0}, + {"Common memory descriptor", CIS_MEM_COMMON, 255}, + {"Long link to next chain for CardBus", CIS_LONGLINK_CB, 255}, + {"Indirect access", CIS_INDIRECT, 255}, + {"Configuration map for CardBus", CIS_CONF_MAP_CB, 255}, + {"Configuration entry for CardBus", CIS_CONFIG_CB, 255}, + {"Long link to next chain for MFC", CIS_LONGLINK_MFC, 255}, + {"Base address register for CardBus", CIS_BAR, 6}, + {"Checksum", CIS_CHECKSUM, 5}, + {"Long link to attribute memory", CIS_LONGLINK_A, 4}, + {"Long link to common memory", CIS_LONGLINK_C, 4}, + {"Link target", CIS_LINKTARGET, 3}, + {"No link", CIS_NOLINK, 0}, + {"Version 1 info", CIS_INFO_V1, 255}, + {"Alternate language string", CIS_ALTSTR, 255}, + {"Attribute memory descriptor", CIS_MEM_ATTR, 255}, + {"JEDEC descr for common memory", CIS_JEDEC_C, 255}, + {"JEDEC descr for attribute memory", CIS_JEDEC_A, 255}, + {"Configuration map", CIS_CONF_MAP, 255}, + {"Configuration entry", CIS_CONFIG, 255}, + {"Other conditions for common memory", CIS_DEVICE_OC, 255}, + {"Other conditions for attribute memory", CIS_DEVICE_OA, 255}, + {"Geometry info for common memory", CIS_DEVICEGEO, 255}, + {"Geometry info for attribute memory", CIS_DEVICEGEO_A, 255}, + {"Manufacturer ID", CIS_MANUF_ID, 4}, + {"Functional ID", CIS_FUNC_ID, 2}, + {"Functional EXT", CIS_FUNC_EXT, 255}, + {"Software interleave", CIS_SW_INTERLV, 2}, + {"Version 2 Info", CIS_VERS_2, 255}, + {"Data format", CIS_FORMAT, 255}, + {"Geometry", CIS_GEOMETRY, 4}, + {"Byte order", CIS_BYTEORDER, 2}, + {"Card init date", CIS_DATE, 4}, + {"Battery replacement", CIS_BATTERY, 4}, + {"Organization", CIS_ORG, 255}, + {"Terminator", CIS_END, 0}, + {0, 0, 0} +}; + +static void * +xmalloc(int sz) +{ + void *p; + + sz = (sz + 7) & ~7; + p = malloc(sz); + if (p) + bzero(p, sz); + else + errx(1, "malloc"); + return (p); +} + +/* + * After reading the tuples, decode the relevant ones. + */ +struct tuple_list * +readcis(int fd) +{ + + return (read_tuples(fd)); +} + +/* + * free_cis - delete cis entry. + */ +void +freecis(struct tuple_list *tlist) +{ + struct tuple_list *tl; + struct tuple *tp; + + while ((tl = tlist) != 0) { + tlist = tl->next; + while ((tp = tl->tuples) != 0) { + tl->tuples = tp->next; + free(tp->data); + free(tp); + } + free(tl); + } +} + +/* + * Parse variable length value. + */ +u_int +parse_num(int sz, u_char *p, u_char **q, int ofs) +{ + u_int num = 0; + + switch (sz) { + case 0: + case 0x10: + break; + case 1: + case 0x11: + num = (*p++) + ofs; + break; + case 2: + case 0x12: + num = tpl16(p) + ofs; + p += 2; + break; + case 0x13: + num = tpl24(p) + ofs; + p += 3; + break; + case 3: + case 0x14: + num = tpl32(p) + ofs; + p += 4; + break; + } + if (q) + *q = p; + return num; +} + +/* + * Read the tuples from the card. + * The processing of tuples is as follows: + * - Read tuples at attribute memory, offset 0. + * - If a CIS_END is the first tuple, look for + * a tuple list at common memory offset 0; this list + * must start with a LINKTARGET. + * - If a long link tuple was encountered, execute the long + * link. + * - If a no-link tuple was seen, terminate processing. + * - If no no-link tuple exists, and no long link tuple + * exists while processing the primary tuple list, + * then look for a LINKTARGET tuple in common memory. + * - If a long link tuple is found in any list, then process + * it. Only one link is allowed per list. + */ +static struct tuple_list *tlist; + +static struct tuple_list * +read_tuples(int fd) +{ + struct tuple_list *tl = 0, *last_tl; + struct tuple *tp; + int flag; + off_t offs; + + tlist = 0; + last_tl = tlist = read_one_tuplelist(fd, MDF_ATTR, (off_t) 0); + + /* Now start processing the links (if any). */ + do { + flag = MDF_ATTR; + tp = find_tuple_in_list(last_tl, CIS_LONGLINK_A); + if (tp == 0) { + flag = 0; + tp = find_tuple_in_list(last_tl, CIS_LONGLINK_C); + } + if (tp && tp->length == 4) { + offs = tpl32(tp->data); +#ifdef DEBUG + printf("Checking long link at %zd (%s memory)\n", + offs, flag ? "Attribute" : "Common"); +#endif + /* If a link was found, read the tuple list from it. */ + if (ck_linktarget(fd, offs, flag)) { + tl = read_one_tuplelist(fd, flag, offs); + last_tl->next = tl; + last_tl = tl; + } + } else + tl = 0; + } while (tl); + + /* + * If the primary list had no NOLINK tuple, and no LINKTARGET, + * then try to read a tuple list at common memory (offset 0). + */ + if (find_tuple_in_list(tlist, CIS_NOLINK) == 0 && + find_tuple_in_list(tlist, CIS_LINKTARGET) == 0 && + ck_linktarget(fd, (off_t) 0, 0)) { + offs = 0; +#ifdef DEBUG + printf("Reading long link at %zd (%s memory)\n", + offs, flag ? "Attribute" : "Common"); +#endif + tlist->next = read_one_tuplelist(fd, 0, offs); + } + return (tlist); +} + +/* + * Read one tuple list from the card. + */ +static struct tuple_list * +read_one_tuplelist(int fd, int flags, off_t offs) +{ + struct tuple *tp, *last_tp = 0; + struct tuple_list *tl; + struct tuple_info *tinfo; + int total = 0; + unsigned char code, length; + + /* Check to see if this memory has already been scanned. */ + for (tl = tlist; tl; tl = tl->next) + if (tl->offs == offs && tl->flags == (flags & MDF_ATTR)) + return (0); + tl = xmalloc(sizeof(*tl)); + tl->offs = offs; + tl->flags = flags & MDF_ATTR; + ioctl(fd, PIOCRWFLAG, &flags); + lseek(fd, offs, SEEK_SET); + do { + if (read(fd, &code, 1) != 1) { + warn("CIS code read"); + break; + } + total++; + if (code == CIS_NULL) + continue; + tp = xmalloc(sizeof(*tp)); + tp->code = code; + if (code == CIS_END) + length = 0; + else { + if (read(fd, &length, 1) != 1) { + warn("CIS len read"); + break; + } + total++; + } + tp->length = length; +#ifdef DEBUG + printf("Tuple code = 0x%x, len = %d\n", code, length); +#endif + if (length == 0xFF) { + length = tp->length = 0; + code = CIS_END; + } + if (length != 0) { + total += length; + tp->data = xmalloc(length); + if (read(fd, tp->data, length) != length) { + warn("CIS read"); + break; + } + } + + /* + * Check the tuple, and ignore it if it isn't in the table + * or the length is illegal. + */ + tinfo = get_tuple_info(code); + if (tinfo != NULL && (tinfo->length != 255 && tinfo->length > length)) { + printf("code %s (%d) ignored\n", tuple_name(code), code); + tp->code = CIS_NULL; + } + if (tl->tuples == NULL) + tl->tuples = tp; + else + last_tp->next = tp; + last_tp = tp; + } while (code != CIS_END && total < 1024); + return (tl); +} + +/* + * return true if the offset points to a LINKTARGET tuple. + */ +static int +ck_linktarget(int fd, off_t offs, int flag) +{ + char blk[5]; + + ioctl(fd, PIOCRWFLAG, &flag); + lseek(fd, offs, SEEK_SET); + if (read(fd, blk, 5) != 5) + return (0); + if (blk[0] == CIS_LINKTARGET && + blk[1] == 0x3 && + blk[2] == 'C' && + blk[3] == 'I' && + blk[4] == 'S') + return (1); + return (0); +} + +/* + * find_tuple_in_list - find a tuple within a + * single tuple list. + */ +static struct tuple * +find_tuple_in_list(struct tuple_list *tl, unsigned char code) +{ + struct tuple *tp; + + for (tp = tl->tuples; tp; tp = tp->next) + if (tp->code == code) + break; + return (tp); +} + +/* + * return table entry for code. + */ +static struct tuple_info * +get_tuple_info(unsigned char code) +{ + struct tuple_info *tp; + + for (tp = tuple_info; tp->name; tp++) + if (tp->code == code) + return (tp); + return (0); +} + +const char * +tuple_name(unsigned char code) +{ + struct tuple_info *tp; + + tp = get_tuple_info(code); + if (tp) + return (tp->name); + return ("Unknown"); +} diff --git a/usr.sbin/dumpcis/readcis.h b/usr.sbin/dumpcis/readcis.h new file mode 100644 index 0000000..8fc2e2d --- /dev/null +++ b/usr.sbin/dumpcis/readcis.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1995 Andrew McRae. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +struct tuple { + struct tuple *next; + unsigned char code; + int length; + unsigned char *data; +}; + +struct tuple_list { + struct tuple_list *next; + struct tuple *tuples; + off_t offs; + int flags; +}; + +struct tuple_info { + const char *name; + unsigned char code; + unsigned char length; /* 255 means variable length */ +}; + +#define tpl32(tp) ((*((tp) + 3) << 24) | \ + (*((tp) + 2) << 16) | \ + (*((tp) + 1) << 8) | *(tp)) +#define tpl24(tp) ((*((tp) + 2) << 16) | \ + (*((tp) + 1) << 8) | *(tp)) +#define tpl16(tp) ((*((tp) + 1) << 8) | *(tp)) + +void dumpcis(struct tuple_list *); +void freecis(struct tuple_list *); +struct tuple_list *readcis(int); + +const char *tuple_name(unsigned char); +u_int parse_num(int, u_char *, u_char **, int); |