summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2003-12-18 03:51:21 +0000
committerwpaul <wpaul@FreeBSD.org>2003-12-18 03:51:21 +0000
commit74b1363ea90e609ecd017b43c841fa54f54127ff (patch)
tree5ee952471a833e8a8748d227d48d1f385c5adb16
parent3242fb60cccb7ee9ecca553025efbe11e7ae4cbe (diff)
downloadFreeBSD-src-74b1363ea90e609ecd017b43c841fa54f54127ff.zip
FreeBSD-src-74b1363ea90e609ecd017b43c841fa54f54127ff.tar.gz
Deal with the duplicate sysctl leaf problem. A .inf file may contain
definitions for more than one device (usually differentiated by the PCI subvendor/subdevice ID). Each device also has its own tree of registry keys. In some cases, each device has the same keys, but sometimes each device has a unique tree but with overlap. Originally, I just had ndiscvt(8) dump out all the keys it could find, and we would try to apply them to every device we could find. Now, each key has an index number that matches it to a device in the device ID list. This lets us create just the keys that apply to a particular device. I also added an extra field to the device list to hold the subvendor and subdevice ID. Some devices are generic, i.e. there is no subsystem definition. If we have a device that doesn't match a specific subsystem value and we have a generic entry, we use the generic entry.
-rw-r--r--sys/compat/ndis/cfg_var.h1
-rw-r--r--sys/compat/ndis/kern_ndis.c4
-rw-r--r--sys/dev/if_ndis/if_ndis.c33
-rw-r--r--sys/dev/if_ndis/if_ndisvar.h3
-rw-r--r--usr.sbin/ndiscvt/Makefile2
-rw-r--r--usr.sbin/ndiscvt/inf.c58
6 files changed, 65 insertions, 36 deletions
diff --git a/sys/compat/ndis/cfg_var.h b/sys/compat/ndis/cfg_var.h
index 831239c..1199109 100644
--- a/sys/compat/ndis/cfg_var.h
+++ b/sys/compat/ndis/cfg_var.h
@@ -39,6 +39,7 @@ struct ndis_cfg {
char *nc_cfgkey;
char *nc_cfgdesc;
char nc_val[256];
+ int nc_idx;
};
typedef struct ndis_cfg ndis_cfg;
diff --git a/sys/compat/ndis/kern_ndis.c b/sys/compat/ndis/kern_ndis.c
index df4a679..94e340e 100644
--- a/sys/compat/ndis/kern_ndis.c
+++ b/sys/compat/ndis/kern_ndis.c
@@ -214,6 +214,10 @@ ndis_create_sysctls(arg)
while(1) {
if (vals->nc_cfgkey == NULL)
break;
+ if (vals->nc_idx != sc->ndis_devidx) {
+ vals++;
+ continue;
+ }
SYSCTL_ADD_STRING(&sc->ndis_ctx,
SYSCTL_CHILDREN(sc->ndis_tree),
OID_AUTO, vals->nc_cfgkey,
diff --git a/sys/dev/if_ndis/if_ndis.c b/sys/dev/if_ndis/if_ndis.c
index b6beb3d..5e1f9b9 100644
--- a/sys/dev/if_ndis/if_ndis.c
+++ b/sys/dev/if_ndis/if_ndis.c
@@ -85,7 +85,7 @@ static struct ndis_type ndis_devs[] = {
#ifdef NDIS_DEV_TABLE
NDIS_DEV_TABLE
#endif
- { 0, 0, NULL }
+ { 0, 0, 0, NULL }
};
#define __stdcall __attribute__((__stdcall__))
@@ -178,7 +178,9 @@ ndis_probe(dev)
while(t->ndis_name != NULL) {
if ((pci_get_vendor(dev) == t->ndis_vid) &&
- (pci_get_device(dev) == t->ndis_did)) {
+ (pci_get_device(dev) == t->ndis_did) &&
+ (pci_read_config(dev, PCIR_SUBVEND_0, 4) ==
+ t->ndis_subsys)) {
device_set_desc(dev, t->ndis_name);
return(0);
}
@@ -201,6 +203,9 @@ ndis_attach(dev)
struct ifnet *ifp;
int unit, error = 0, rid, len;
void *img;
+ struct ndis_type *t;
+ int devidx = 0, defidx = 0;
+
sc = device_get_softc(dev);
unit = device_get_unit(dev);
@@ -297,6 +302,30 @@ ndis_attach(dev)
sc->ndis_regvals = ndis_regvals;
sc->ndis_iftype = PCIBus;
+ /* Figure out exactly which device we matched. */
+
+ t = ndis_devs;
+
+ while(t->ndis_name != NULL) {
+ if ((pci_get_vendor(dev) == t->ndis_vid) &&
+ (pci_get_device(dev) == t->ndis_did)) {
+ if (t->ndis_subsys == 0)
+ defidx = devidx;
+ else {
+ if (t->ndis_subsys ==
+ pci_read_config(dev, PCIR_SUBVEND_0, 4))
+ break;
+ }
+ }
+ t++;
+ devidx++;
+ }
+
+ if (ndis_devs[devidx].ndis_name == NULL)
+ sc->ndis_devidx = defidx;
+ else
+ sc->ndis_devidx = devidx;
+
sysctl_ctx_init(&sc->ndis_ctx);
/* Create sysctl registry nodes */
diff --git a/sys/dev/if_ndis/if_ndisvar.h b/sys/dev/if_ndis/if_ndisvar.h
index bc3b902..5b9c768 100644
--- a/sys/dev/if_ndis/if_ndisvar.h
+++ b/sys/dev/if_ndis/if_ndisvar.h
@@ -47,6 +47,7 @@ struct ndis_chain {
struct ndis_type {
uint16_t ndis_vid;
uint16_t ndis_did;
+ uint32_t ndis_subsys;
char *ndis_name;
};
@@ -103,6 +104,7 @@ struct ndis_softc {
struct sysctl_ctx_list ndis_ctx;
struct sysctl_oid *ndis_tree;
+ int ndis_devidx;
interface_type ndis_iftype;
bus_dma_tag_t ndis_parent_tag;
@@ -112,7 +114,6 @@ struct ndis_softc {
bus_dmamap_t *ndis_mmaps;
bus_dmamap_t *ndis_tmaps;
int ndis_mmapcnt;
-
};
#define NDIS_LOCK(_sc) mtx_lock(&(_sc)->ndis_mtx)
diff --git a/usr.sbin/ndiscvt/Makefile b/usr.sbin/ndiscvt/Makefile
index f5c7f13..c8aa86f 100644
--- a/usr.sbin/ndiscvt/Makefile
+++ b/usr.sbin/ndiscvt/Makefile
@@ -16,7 +16,7 @@ LDADD= -ll
YFLAGS+=-v
-CFLAGS+=-I. -I${.CURDIR} -I${.CURDIR}/../../sys
+CFLAGS+=-g -I. -I${.CURDIR} -I${.CURDIR}/../../sys
CLEANFILES= y.output
diff --git a/usr.sbin/ndiscvt/inf.c b/usr.sbin/ndiscvt/inf.c
index 46f1146..30bc256 100644
--- a/usr.sbin/ndiscvt/inf.c
+++ b/usr.sbin/ndiscvt/inf.c
@@ -32,7 +32,8 @@ static struct section
static void dump_deviceids (void);
static void dump_pci_id (const char *);
static void dump_regvals (void);
-static void dump_paramreg (const struct section *, const struct reg *);
+static void dump_paramreg (const struct section *,
+ const struct reg *, int);
static FILE *ofp;
@@ -119,7 +120,7 @@ static void
dump_pci_id(const char *s)
{
char *p;
- char vidstr[7], didstr[7];
+ char vidstr[7], didstr[7], subsysstr[14];
p = strcasestr(s, "VEN_");
if (p == NULL)
@@ -135,8 +136,16 @@ dump_pci_id(const char *s)
strncat(didstr, p, 4);
if (p == NULL)
return;
+ p = strcasestr(s, "SUBSYS_");
+ if (p == NULL)
+ strcpy(subsysstr, "0x00000000");
+ else {
+ p += 7;
+ strcpy(subsysstr, "0x");
+ strncat(subsysstr, p, 8);
+ }
- fprintf(ofp, "\t\\\n\t{ %s, %s,", vidstr, didstr);
+ fprintf(ofp, "\t\\\n\t{ %s, %s, %s, ", vidstr, didstr, subsysstr);
return;
}
@@ -193,7 +202,7 @@ dump_deviceids()
}
static void
-dump_addreg(const char *s)
+dump_addreg(const char *s, int devidx)
{
struct section *sec;
struct reg *reg;
@@ -213,13 +222,13 @@ dump_addreg(const char *s)
if (reg->subkey == NULL) {
fprintf(ofp, "\n\t{ \"%s\",", reg->key);
fprintf(ofp,"\n\t\"%s \",", reg->key);
- fprintf(ofp, "\n\t{ \"%s\" } },",
+ fprintf(ofp, "\n\t{ \"%s\" }, %d },",
reg->value == NULL ? "" :
- stringcvt(reg->value));
+ stringcvt(reg->value), devidx);
} else if (strcasestr(reg->subkey,
"Ndi\\params") != NULL &&
strcasecmp(reg->key, "ParamDesc") == 0)
- dump_paramreg(sec, reg);
+ dump_paramreg(sec, reg, devidx);
}
}
@@ -283,7 +292,7 @@ dump_dwordreg(const struct section *s, const struct reg *r)
}
static void
-dump_defaultinfo(const struct section *s, const struct reg *r)
+dump_defaultinfo(const struct section *s, const struct reg *r, int devidx)
{
struct reg *reg;
TAILQ_FOREACH(reg, &rh, link) {
@@ -293,8 +302,8 @@ dump_defaultinfo(const struct section *s, const struct reg *r)
continue;
if (strcasecmp(reg->key, "Default"))
continue;
- fprintf(ofp, "\n\t{ \"%s\" } },", reg->value == NULL ? "" :
- reg->value);
+ fprintf(ofp, "\n\t{ \"%s\" }, %d },", reg->value == NULL ? "" :
+ reg->value, devidx);
break;
}
return;
@@ -340,7 +349,7 @@ dump_typeinfo(const struct section *s, const struct reg *r)
}
static void
-dump_paramreg(const struct section *s, const struct reg *r)
+dump_paramreg(const struct section *s, const struct reg *r, int devidx)
{
const char *keyname;
@@ -349,7 +358,7 @@ dump_paramreg(const struct section *s, const struct reg *r)
dump_paramdesc(s, r);
dump_typeinfo(s, r);
fprintf(ofp, "\",");
- dump_defaultinfo(s, r);
+ dump_defaultinfo(s, r, devidx);
return;
}
@@ -357,14 +366,11 @@ dump_paramreg(const struct section *s, const struct reg *r)
static void
dump_regvals(void)
{
- struct assign *manf, *dev, *dev_dup;
+ struct assign *manf, *dev;
struct section *sec;
struct assign *assign;
- struct assign_head tmp_ah;
char sname[256];
- int i, is_winxp = 0;
-
- TAILQ_INIT(&tmp_ah);
+ int i, is_winxp = 0, devidx = 0;
/* Find manufacturer name */
manf = find_assign("Manufacturer", NULL);
@@ -385,19 +391,6 @@ dump_regvals(void)
fprintf (ofp, "ndis_cfg ndis_regvals[] = {");
TAILQ_FOREACH(assign, &ah, link) {
- /* Avoid repeating the same section. */
- i = 0;
- TAILQ_FOREACH(dev_dup, &tmp_ah, link)
- if (strcmp(dev_dup->vals[0], assign->vals[0]) == 0) {
- i++;
- break;
- }
- if (i)
- continue;
- dev_dup = malloc(sizeof(struct assign));
- bcopy((char *)assign, (char *)dev_dup,
- sizeof(struct assign));
- TAILQ_INSERT_TAIL(&tmp_ah, dev_dup, link);
if (assign->section == sec) {
/*
* Find all the AddReg sections.
@@ -419,12 +412,13 @@ dump_regvals(void)
continue;
for (i = 0; i < W_MAX; i++) {
if (dev->vals[i] != NULL)
- dump_addreg(dev->vals[i]);
+ dump_addreg(dev->vals[i], devidx);
}
+ devidx++;
}
}
- fprintf(ofp, "\n\t{ NULL, NULL, { 0 } }\n};\n\n");
+ fprintf(ofp, "\n\t{ NULL, NULL, { 0 }, 0 }\n};\n\n");
return;
}
OpenPOWER on IntegriCloud