mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-28 15:32:45 +00:00
The original programs that this code was lifted from (pccardd and
pccardc) parsed data to make decisions about stuff related to card configuration. The purely CIS dumping aspect of this program obviates the need for such parsing. Save some space and don't parse the data anymore for configuration purposes. Just parse it to print an interpreatation of it.
This commit is contained in:
parent
199493b917
commit
2d134dead2
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=185121
@ -62,7 +62,7 @@ static void dump_info_v2(u_char *p, int len);
|
||||
static void dump_org(u_char *p, int len);
|
||||
|
||||
void
|
||||
dumpcis(struct cis *cp)
|
||||
dumpcis(struct tuple_list *tlist)
|
||||
{
|
||||
struct tuple *tp;
|
||||
struct tuple_list *tl;
|
||||
@ -70,7 +70,7 @@ dumpcis(struct cis *cp)
|
||||
u_char *p;
|
||||
int func = 0;
|
||||
|
||||
for (tl = cp->tlist; tl; tl = tl->next)
|
||||
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);
|
||||
|
@ -39,7 +39,6 @@ static const char rcsid[] =
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <pccard/cardinfo.h>
|
||||
#include <pccard/cis.h>
|
||||
@ -47,13 +46,6 @@ static const char rcsid[] =
|
||||
#include "readcis.h"
|
||||
|
||||
static int ck_linktarget(int, off_t, int);
|
||||
static void cis_info(struct cis *, unsigned char *, int);
|
||||
static void device_desc(unsigned char *, int, struct dev_mem *);
|
||||
static void config_map(struct cis *, unsigned char *, int);
|
||||
static void cis_config(struct cis *, unsigned char *, int);
|
||||
static void cis_manuf_id(struct cis *, unsigned char *, int);
|
||||
static void cis_func_id(struct cis *, unsigned char *, int);
|
||||
static void cis_network_ext(struct cis *, unsigned char *, 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);
|
||||
@ -116,215 +108,31 @@ xmalloc(int sz)
|
||||
/*
|
||||
* After reading the tuples, decode the relevant ones.
|
||||
*/
|
||||
struct cis *
|
||||
struct tuple_list *
|
||||
readcis(int fd)
|
||||
{
|
||||
struct tuple_list *tl;
|
||||
struct tuple *tp;
|
||||
struct cis *cp;
|
||||
|
||||
cp = xmalloc(sizeof(*cp));
|
||||
cp->tlist = read_tuples(fd);
|
||||
if (cp->tlist == 0)
|
||||
return (NULL);
|
||||
|
||||
for (tl = cp->tlist; tl; tl = tl->next)
|
||||
for (tp = tl->tuples; tp; tp = tp->next) {
|
||||
switch (tp->code) {
|
||||
case CIS_MEM_COMMON: /* 0x01 */
|
||||
device_desc(tp->data, tp->length, &cp->common_mem);
|
||||
break;
|
||||
case CIS_INFO_V1: /* 0x15 */
|
||||
cis_info(cp, tp->data, tp->length);
|
||||
break;
|
||||
case CIS_MEM_ATTR: /* 0x17 */
|
||||
device_desc(tp->data, tp->length, &cp->attr_mem);
|
||||
break;
|
||||
case CIS_CONF_MAP: /* 0x1A */
|
||||
config_map(cp, tp->data, tp->length);
|
||||
break;
|
||||
case CIS_CONFIG: /* 0x1B */
|
||||
cis_config(cp, tp->data, tp->length);
|
||||
break;
|
||||
case CIS_MANUF_ID: /* 0x20 */
|
||||
cis_manuf_id(cp, tp->data, tp->length);
|
||||
break;
|
||||
case CIS_FUNC_ID: /* 0x21 */
|
||||
cis_func_id(cp, tp->data, tp->length);
|
||||
break;
|
||||
case CIS_FUNC_EXT: /* 0x22 */
|
||||
if (cp->func_id1 == 6) /* LAN adaptor */
|
||||
cis_network_ext(cp, tp->data, tp->length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (cp);
|
||||
return (read_tuples(fd));
|
||||
}
|
||||
|
||||
/*
|
||||
* free_cis - delete cis entry.
|
||||
*/
|
||||
void
|
||||
freecis(struct cis *cp)
|
||||
freecis(struct tuple_list *tlist)
|
||||
{
|
||||
struct cis_ioblk *io;
|
||||
struct cis_memblk *mem;
|
||||
struct cis_config *conf;
|
||||
struct tuple *tp;
|
||||
struct tuple_list *tl;
|
||||
struct tuple *tp;
|
||||
|
||||
while ((tl = cp->tlist) != 0) {
|
||||
cp->tlist = tl->next;
|
||||
while ((tl = tlist) != 0) {
|
||||
tlist = tl->next;
|
||||
while ((tp = tl->tuples) != 0) {
|
||||
tl->tuples = tp->next;
|
||||
if (tp->data)
|
||||
free(tp->data);
|
||||
free(tp->data);
|
||||
free(tp);
|
||||
}
|
||||
free(tl);
|
||||
}
|
||||
|
||||
while ((conf = cp->conf) != 0) {
|
||||
cp->conf = conf->next;
|
||||
while ((io = conf->io) != 0) {
|
||||
conf->io = io->next;
|
||||
free(io);
|
||||
}
|
||||
while ((mem = conf->mem) != 0) {
|
||||
conf->mem = mem->next;
|
||||
free(mem);
|
||||
}
|
||||
free(conf);
|
||||
}
|
||||
free(cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fills in CIS version data.
|
||||
*/
|
||||
static void
|
||||
cis_info(struct cis *cp, unsigned char *p, int len)
|
||||
{
|
||||
cp->maj_v = *p++;
|
||||
cp->min_v = *p++;
|
||||
len -= 2;
|
||||
if (cp->manuf) {
|
||||
free(cp->manuf);
|
||||
cp->manuf = NULL;
|
||||
}
|
||||
if (len > 1 && *p != 0xff) {
|
||||
cp->manuf = strdup(p);
|
||||
len -= strlen(p) + 1;
|
||||
p += strlen(p) + 1;
|
||||
}
|
||||
if (cp->vers) {
|
||||
free(cp->vers);
|
||||
cp->vers = NULL;
|
||||
}
|
||||
if (len > 1 && *p != 0xff) {
|
||||
cp->vers = strdup(p);
|
||||
len -= strlen(p) + 1;
|
||||
p += strlen(p) + 1;
|
||||
} else {
|
||||
cp->vers = strdup("[none]");
|
||||
}
|
||||
if (cp->add_info1) {
|
||||
free(cp->add_info1);
|
||||
cp->add_info1 = NULL;
|
||||
}
|
||||
if (len > 1 && *p != 0xff) {
|
||||
cp->add_info1 = strdup(p);
|
||||
len -= strlen(p) + 1;
|
||||
p += strlen(p) + 1;
|
||||
} else {
|
||||
cp->add_info1 = strdup("[none]");
|
||||
}
|
||||
if (cp->add_info2) {
|
||||
free(cp->add_info2);
|
||||
cp->add_info2 = NULL;
|
||||
}
|
||||
if (len > 1 && *p != 0xff)
|
||||
cp->add_info2 = strdup(p);
|
||||
else
|
||||
cp->add_info2 = strdup("[none]");
|
||||
}
|
||||
|
||||
static void
|
||||
cis_manuf_id(struct cis *cp, unsigned char *p, int len)
|
||||
{
|
||||
if (len >= 4) {
|
||||
cp->manufacturer = tpl16(p);
|
||||
cp->product = tpl16(p+2);
|
||||
if (len == 5)
|
||||
cp->prodext = *(p+4); /* For xe driver */
|
||||
} else {
|
||||
cp->manufacturer=0;
|
||||
cp->product=0;
|
||||
cp->prodext=0;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Fills in CIS function ID.
|
||||
*/
|
||||
static void
|
||||
cis_func_id(struct cis *cp, unsigned char *p, int len __unused)
|
||||
{
|
||||
cp->func_id1 = *p++;
|
||||
cp->func_id2 = *p++;
|
||||
}
|
||||
|
||||
static void
|
||||
cis_network_ext(struct cis *cp, unsigned char *p, int len __unused)
|
||||
{
|
||||
int i;
|
||||
|
||||
switch (p[0]) {
|
||||
case 4: /* Node ID */
|
||||
if (len <= 2 || len < p[1] + 2)
|
||||
return;
|
||||
|
||||
if (cp->lan_nid)
|
||||
free(cp->lan_nid);
|
||||
cp->lan_nid = xmalloc(p[1]);
|
||||
|
||||
for (i = 0; i <= p[1]; i++)
|
||||
cp->lan_nid[i] = p[i + 1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* device_desc - decode device descriptor.
|
||||
*/
|
||||
static void
|
||||
device_desc(unsigned char *p, int len, struct dev_mem *dp)
|
||||
{
|
||||
while (len > 0 && *p != 0xFF) {
|
||||
dp->valid = 1;
|
||||
dp->type = (*p & 0xF0) >> 4;
|
||||
dp->wps = !!(*p & 0x8);
|
||||
dp->speed = *p & 7;
|
||||
p++;
|
||||
if (*p != 0xFF) {
|
||||
dp->addr = (*p >> 3) & 0xF;
|
||||
dp->units = *p & 7;
|
||||
}
|
||||
p++;
|
||||
len -= 2;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* configuration map of card control register.
|
||||
*/
|
||||
static void
|
||||
config_map(struct cis *cp, unsigned char *p, int len __unused)
|
||||
{
|
||||
unsigned char *p1;
|
||||
int rlen = (*p & 3) + 1;
|
||||
|
||||
p1 = p + 1;
|
||||
cp->last_config = *p1++ & 0x3F;
|
||||
cp->reg_addr = parse_num(rlen | 0x10, p1, &p1, 0);
|
||||
cp->ccrs = *p1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -363,125 +171,6 @@ parse_num(int sz, u_char *p, u_char **q, int ofs)
|
||||
return num;
|
||||
}
|
||||
|
||||
/*
|
||||
* CIS config entry - Decode and build configuration entry.
|
||||
*/
|
||||
static void
|
||||
cis_config(struct cis *cp, unsigned char *p, int len __unused)
|
||||
{
|
||||
int x;
|
||||
int i, j;
|
||||
struct cis_config *conf, *last;
|
||||
unsigned char feat;
|
||||
|
||||
conf = xmalloc(sizeof(*conf));
|
||||
if ((last = cp->conf) != 0) {
|
||||
while (last->next)
|
||||
last = last->next;
|
||||
last->next = conf;
|
||||
} else
|
||||
cp->conf = conf;
|
||||
conf->id = *p & 0x3F; /* Config index */
|
||||
if (*p & 0x40) /* Default flag */
|
||||
cp->def_config = conf;
|
||||
if (*p++ & 0x80)
|
||||
p++; /* Interface byte skip */
|
||||
feat = *p++; /* Features byte */
|
||||
for (i = 0; i < CIS_FEAT_POWER(feat); i++) {
|
||||
unsigned char parms = *p++;
|
||||
|
||||
conf->pwr = 1;
|
||||
for (j = 0; j < 8; j++)
|
||||
if (parms & (1 << j))
|
||||
while (*p++ & 0x80);
|
||||
}
|
||||
if (feat & CIS_FEAT_TIMING) {
|
||||
conf->timing = 1;
|
||||
i = *p++;
|
||||
if (CIS_WAIT_SCALE(i) != 3)
|
||||
p++;
|
||||
if (CIS_READY_SCALE(i) != 7)
|
||||
p++;
|
||||
if (CIS_RESERVED_SCALE(i) != 7)
|
||||
p++;
|
||||
}
|
||||
if (feat & CIS_FEAT_I_O) {
|
||||
conf->iospace = 1;
|
||||
if (CIS_IO_RANGE & *p)
|
||||
conf->io_blks = CIS_IO_BLKS(p[1]) + 1;
|
||||
conf->io_addr = CIS_IO_ADDR(*p);
|
||||
conf->io_bus = (*p >> 5) & 3; /* CIS_IO_8BIT | CIS_IO_16BIT */
|
||||
if (*p++ & CIS_IO_RANGE) {
|
||||
struct cis_ioblk *io;
|
||||
struct cis_ioblk *last_io = NULL;
|
||||
|
||||
i = CIS_IO_ADSZ(*p);
|
||||
j = CIS_IO_BLKSZ(*p++);
|
||||
for (x = 0; x < conf->io_blks; x++) {
|
||||
io = xmalloc(sizeof(*io));
|
||||
if (last_io)
|
||||
last_io->next = io;
|
||||
else
|
||||
conf->io = io;
|
||||
last_io = io;
|
||||
io->addr = parse_num(i, p, &p, 0);
|
||||
io->size = parse_num(j, p, &p, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (feat & CIS_FEAT_IRQ) {
|
||||
conf->irq = 1;
|
||||
conf->irqlevel = *p & 0xF;
|
||||
conf->irq_flags = *p & 0xF0;
|
||||
if (*p++ & CIS_IRQ_MASK) {
|
||||
conf->irq_mask = tpl16(p);
|
||||
p += 2;
|
||||
}
|
||||
}
|
||||
switch (CIS_FEAT_MEMORY(feat)) {
|
||||
case CIS_FEAT_MEM_NONE:
|
||||
break;
|
||||
case CIS_FEAT_MEM_LEN:
|
||||
conf->memspace = 1;
|
||||
conf->mem = xmalloc(sizeof(*conf->mem));
|
||||
conf->mem->length = tpl16(p) << 8;
|
||||
break;
|
||||
case CIS_FEAT_MEM_ADDR:
|
||||
conf->memspace = 1;
|
||||
conf->mem = xmalloc(sizeof(*conf->mem));
|
||||
conf->mem->length = tpl16(p) << 8;
|
||||
conf->mem->address = tpl16(p + 2) << 8;
|
||||
break;
|
||||
case CIS_FEAT_MEM_WIN: {
|
||||
struct cis_memblk *mem;
|
||||
struct cis_memblk *last_mem = NULL;
|
||||
|
||||
conf->memspace = 1;
|
||||
x = *p++;
|
||||
conf->memwins = CIS_MEM_WINS(x);
|
||||
for (i = 0; i < conf->memwins; i++) {
|
||||
mem = xmalloc(sizeof(*mem));
|
||||
if (last_mem)
|
||||
last_mem->next = mem;
|
||||
else
|
||||
conf->mem = mem;
|
||||
last_mem = mem;
|
||||
mem->length = parse_num(CIS_MEM_LENSZ(x) | 0x10, p, &p, 0) << 8;
|
||||
mem->address = parse_num(CIS_MEM_ADDRSZ(x) | 0x10, p, &p, 0) << 8;
|
||||
if (x & CIS_MEM_HOST) {
|
||||
mem->host_address = parse_num(CIS_MEM_ADDRSZ(x) | 0x10,
|
||||
p, &p, 0) << 8;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (feat & CIS_FEAT_MISC) {
|
||||
conf->misc_valid = 1;
|
||||
conf->misc = *p++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read the tuples from the card.
|
||||
* The processing of tuples is as follows:
|
||||
@ -522,7 +211,7 @@ read_tuples(int fd)
|
||||
if (tp && tp->length == 4) {
|
||||
offs = tpl32(tp->data);
|
||||
#ifdef DEBUG
|
||||
printf("Checking long link at %qd (%s memory)\n",
|
||||
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. */
|
||||
@ -541,11 +230,12 @@ read_tuples(int fd)
|
||||
*/
|
||||
if (find_tuple_in_list(tlist, CIS_NOLINK) == 0 && tlist->next == 0 &&
|
||||
ck_linktarget(fd, (off_t) 0, 0)) {
|
||||
offs = 0;
|
||||
#ifdef DEBUG
|
||||
printf("Reading long link at %qd (%s memory)\n",
|
||||
printf("Reading long link at %zd (%s memory)\n",
|
||||
offs, flag ? "Attribute" : "Common");
|
||||
#endif
|
||||
tlist->next = read_one_tuplelist(fd, 0, (off_t) 0);
|
||||
tlist->next = read_one_tuplelist(fd, 0, offs);
|
||||
}
|
||||
return (tlist);
|
||||
}
|
||||
@ -573,7 +263,6 @@ read_one_tuplelist(int fd, int flags, off_t offs)
|
||||
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) {
|
||||
@ -619,7 +308,7 @@ read_one_tuplelist(int fd, int flags, off_t offs)
|
||||
*/
|
||||
tinfo = get_tuple_info(code);
|
||||
if (tinfo != NULL && (tinfo->length != 255 && tinfo->length > length)) {
|
||||
printf("code %s ignored\n", tuple_name(code));
|
||||
printf("code %s (%d) ignored\n", tuple_name(code), code);
|
||||
tp->code = CIS_NULL;
|
||||
}
|
||||
if (tl->tuples == NULL)
|
||||
|
@ -46,89 +46,6 @@ struct tuple_info {
|
||||
unsigned char length; /* 255 means variable length */
|
||||
};
|
||||
|
||||
/*
|
||||
* Memory device descriptor.
|
||||
*/
|
||||
struct dev_mem {
|
||||
unsigned char valid;
|
||||
unsigned char type;
|
||||
unsigned char speed;
|
||||
unsigned char wps;
|
||||
unsigned char addr;
|
||||
unsigned char units;
|
||||
};
|
||||
|
||||
/*
|
||||
* One I/O structure describing a possible I/O map
|
||||
* of the card.
|
||||
*/
|
||||
struct cis_ioblk {
|
||||
struct cis_ioblk *next;
|
||||
unsigned int addr;
|
||||
unsigned int size;
|
||||
};
|
||||
|
||||
/*
|
||||
* A structure storing a memory map for the card.
|
||||
*/
|
||||
struct cis_memblk {
|
||||
struct cis_memblk *next;
|
||||
unsigned int address;
|
||||
unsigned int length;
|
||||
unsigned int host_address;
|
||||
};
|
||||
|
||||
/*
|
||||
* One configuration entry for the card.
|
||||
*/
|
||||
struct cis_config {
|
||||
struct cis_config *next;
|
||||
unsigned int pwr:1; /* Which values are defined. */
|
||||
unsigned int timing:1;
|
||||
unsigned int iospace:1;
|
||||
unsigned int irq:1;
|
||||
unsigned int memspace:1;
|
||||
unsigned int misc_valid:1;
|
||||
unsigned char id;
|
||||
unsigned char io_blks;
|
||||
unsigned char io_addr;
|
||||
unsigned char io_bus;
|
||||
struct cis_ioblk *io;
|
||||
unsigned char irqlevel;
|
||||
unsigned char irq_flags;
|
||||
unsigned irq_mask;
|
||||
unsigned char memwins;
|
||||
struct cis_memblk *mem;
|
||||
unsigned char misc;
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure holding all data retrieved from the
|
||||
* CIS block on the card.
|
||||
* The default configuration contains interface defaults
|
||||
* not listed in each separate configuration.
|
||||
*/
|
||||
struct cis {
|
||||
struct tuple_list *tlist;
|
||||
char *manuf;
|
||||
char *vers;
|
||||
char *add_info1;
|
||||
char *add_info2;
|
||||
unsigned char maj_v, min_v;
|
||||
unsigned char last_config;
|
||||
unsigned char ccrs;
|
||||
unsigned long reg_addr;
|
||||
u_int manufacturer;
|
||||
u_int product;
|
||||
u_int prodext;
|
||||
unsigned char func_id1, func_id2;
|
||||
struct dev_mem attr_mem;
|
||||
struct dev_mem common_mem;
|
||||
struct cis_config *def_config;
|
||||
struct cis_config *conf;
|
||||
unsigned char *lan_nid;
|
||||
};
|
||||
|
||||
#define tpl32(tp) ((*((tp) + 3) << 24) | \
|
||||
(*((tp) + 2) << 16) | \
|
||||
(*((tp) + 1) << 8) | *(tp))
|
||||
@ -136,9 +53,9 @@ struct cis {
|
||||
(*((tp) + 1) << 8) | *(tp))
|
||||
#define tpl16(tp) ((*((tp) + 1) << 8) | *(tp))
|
||||
|
||||
void dumpcis(struct cis *);
|
||||
void freecis(struct cis *);
|
||||
struct cis *readcis(int);
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user