Subject: Overhaul device parent matching in config(8)/kernel
To: None <tech-kern@netbsd.org>
From: Jason R Thorpe <thorpej@wasabisystems.com>
List: tech-kern
Date: 09/25/2002 09:49:42
--ZGiS0Q5IWpPtfppv
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Folks...
I have overhauled how device parent matching is done in the kernel in
order to better support:
1. Drivers are loadable modules (no, this is no where near
complete yet).
2. Some forthcoming changes to support attaching real devices
to pseudo-devices.
For those of you fortunate enough to not know how this currently works
in the kernel, here is a lesson:
* For each entry in the cfdata[] table, config(8) emits a
"parent vector", which is an array of indices back into
the cfdata[] table. These reference cfdata[] entries for
potential parents of the device.
* When the kernel attaches a device, it scans the cfdata[]
table looking for un-attached entries who's parent vector
array references the device's cfdata[] entry, and when it
finds one, applies the match info in the child's cfdata[]
entry, attempting to attach the device.
This is sub-optimal for several reasons:
* In the presence of multiple cfdata[] tables (i.e. which
would be the case with loadable driver modules), the parent
vector can't reference a parent from another cfdata[] table.
* For devices which are spec'd to attach to an interface attribute
(e.g. "scsibus* at scsi?"), config(8) represents this internally
by expanding the vector to all device's which carry that interface
attribute. I.e. if you say "acphy* at mii?", conifig(8) actually
generates a parent vector that looks like this:
acphy* at url*|aue*|xi*|ste*|bge*|wm*|stge*|gsip*| \
sip*|vr*|tl*|pcn*|sf*|tlp*|tlp*|rtk*|ne0|\
ne1|ne*|ne*|ne*|ne*|epic*|sm0|sm*|sm*|fxp*|\
ex*|ep*|ep*|ep*|ep*|ep*|ep*
This obviously doesn't work if you later load a "foo" device
which carries the "mii" interface attribute, and want to attach
an acphy to it ... you'd need to create another cfdata[] entry
for acphy with the correct parent vector.
What I have done to address this is:
* Add a "const char **cd_attrs" member to the cfdriver structure.
If non-NULL, it is an array of interface attributes carried by
a device, e.g.:
static const char *ex_attrs[] = { "mii", NULL };
struct cfdriver ex_cd = {
NULL, "ex", DV_IFNET, 0, ex_attrs
};
For devices which do not have interface attributes, you
have this instead:
struct cfdriver lc_cd = {
NULL, "lc", DV_IFNET, 0, NULL
};
By recording the fact that something has an interface attribute,
this allows you to attach to that attribute at run-time, rather
than relying on a pre-expanded list of things that have the
attribute.
* Remove the parent vector array, in favor of a new "parent spec",
which looks like this:
struct cfparent {
const char *cfp_iattr; /* interface attribute */
const char *cfp_parent; /* optional specific parent */
int cfp_unit; /* optional specific unit
(-1 to wildcard) */
};
Since all devices attach to an interface attribute, the
parent spec records which one. Additionally, if a device
instance wants to attach to a specific parent, that is also
recorded. So, the new parent spec can preceisely describe
the following three cases:
scsibus* at scsi?
-> iattr = "scsi", parent = NULL, unit = -1
scsibus* at ahc?
-> iattr = "scsi", parent = "ahc", unit = -1
scsibus* at ahc5
-> iattr = "scsi", parent = "ahc", unit = 5
* The kernel now uses the cd_attrs array and the parent specs
to identify potential children of a device (i.e. the device
matches the child's parent spec). This works in the presence
of multiple cfdata tables, because no references back into
any cfdata table are made; everything is done with string
comparisons.
This exercise has also allowed me to garbage-collect vast amounts of
confusing code from config(8) :-)
Diffs for this are at:
ftp://ftp.netbsd.org/pub/incoming/thorpej/config-diffs
They're actually not that large, and some of the changes were merely
to make the __BROKEN_CONFIG_UNIT_USAGE stuff a little more readable.
--
-- Jason R. Thorpe <thorpej@wasabisystems.com>
--ZGiS0Q5IWpPtfppv
Content-Type: message/external-body; access-type=x-mutt-deleted;
expiration="Wed, 25 Sep 2002 10:27:17 -0700"; length=38356
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=config-diffs
--ZGiS0Q5IWpPtfppv--