PERFORCE change 122974 for review
Maxim Zhuravlev
thioretic at FreeBSD.org
Thu Jul 5 21:15:10 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=122974
Change 122974 by thioretic at thioretic on 2007/07/05 21:14:17
Devclasses for filter drivers stuff.
Affected files ...
.. //depot/projects/soc2007/thioretic_gidl/TODO#7 edit
.. //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#6 edit
.. //depot/projects/soc2007/thioretic_gidl/sys/bus.h#4 edit
Differences ...
==== //depot/projects/soc2007/thioretic_gidl/TODO#7 (text+ko) ====
@@ -68,4 +68,22 @@
# attached, but to drv_compat_ctrl_driver, which will demux
# to stacked drivers.
# dev->drivers are pointers to drv_compat structures that
- # represent drivers of interest.+ # represent drivers of interest.
+ a.1.2 Devclasses
+ SOLUTION: add filters field to devclass
+ # the filter drivers (with DR_LOWEST<level<DR_TOPMOST) use
+ # devclasses quite differently. Actually, they just extend
+ # the functionality of DR_LOWEST driver. So only DR_LOWEST
+ # driver should have an in-tree built devclass, with
+ # pointers to devclasses of filter drivers. I.e.:
+ #
+ # Devclasses tree:
+ #
+ # BUS<-+-+....
+ # |
+ # DR_LOWEST driver_n<-+----+...
+ # | |
+ # filter0 filter1
+ #
+ # NB: here BUS is also a DR_LOWEST driver in turn with all
+ # those consequences.
==== //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#6 (text+ko) ====
@@ -84,20 +84,29 @@
struct pdrv_compat {
drv_compat *pdriver;
TAILQ_ENTRY(pdrv_compat) link;
-}
+};
+
/*
* Forward declarations
*/
typedef TAILQ_HEAD(devclass_list, devclass) devclass_list_t;
+typedef TAILQ_HEAD(pdevclass_list, pdevclass) pdevclass_list_t;
typedef TAILQ_HEAD(driver_list, driverlink) driver_list_t;
typedef TAILQ_HEAD(device_list, device) device_list_t;
typedef TAILQ_HEAD(drv_compat_list, drv_compat) drv_compat_list_t;
typedef TAILQ_HEAD(pdrv_compat_list, pdrv_compat) pdrv_compat_list_t;
+struct pdevclass{
+ devclass_t devclass_ptr;
+ TAILQ_ENTRY(pdevclass) link;
+};
+
struct devclass {
TAILQ_ENTRY(devclass) link;
devclass_t parent; /* parent in devclass hierarchy */
+ pdevclass_list_t filters; /* these are used to hold information,
+ used for non-DRV_LOWEST drivers' classes */
driver_list_t drivers; /* bus devclasses store drivers for bus */
char *name;
device_t *devices; /* array of devices indexed by unit */
@@ -1124,7 +1133,7 @@
*/
static devclass_t
devclass_find_internal(const char *classname, const char *parentname,
- int create)
+ int create, int filter)
{
devclass_t dc;
@@ -1147,6 +1156,7 @@
dc->name = (char*) (dc + 1);
strcpy(dc->name, classname);
TAILQ_INIT(&dc->drivers);
+ TAILQ_INIT(&dc->filters);
TAILQ_INSERT_TAIL(&devclasses, dc, link);
bus_data_generation_update();
@@ -1162,7 +1172,11 @@
*/
if (parentname && dc && !dc->parent &&
strcmp(classname, parentname) != 0) {
- dc->parent = devclass_find_internal(parentname, 0, FALSE);
+ dc->parent = devclass_find_internal(parentname, 0, FALSE, FALSE);
+ }
+
+ if (filter) {
+ TAILQ_INSERT_TAIL(&(dc->parent->filters), dc, link);
}
return (dc);
@@ -1179,7 +1193,7 @@
devclass_t
devclass_create(const char *classname)
{
- return (devclass_find_internal(classname, 0, TRUE));
+ return (devclass_find_internal(classname, 0, TRUE, FALSE));
}
/**
@@ -1193,7 +1207,7 @@
devclass_t
devclass_find(const char *classname)
{
- return (devclass_find_internal(classname, 0, FALSE));
+ return (devclass_find_internal(classname, 0, FALSE, FALSE));
}
/**
@@ -1212,6 +1226,7 @@
{
driverlink_t dl;
int i;
+ uint32_t flags;
PDEBUG(("%s", DRIVERNAME(driver)));
@@ -1230,7 +1245,11 @@
/*
* Make sure the devclass which the driver is implementing exists.
*/
- devclass_find_internal(driver->name, 0, TRUE);
+ if (!drv_compat_get_flags (driver, &flags)){
+ /*todo what???*/
+ }
+
+ devclass_find_internal(driver->name, 0, TRUE, FALSE);
dl->driver = driver;
TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
@@ -1810,7 +1829,7 @@
PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));
if (name) {
- dc = devclass_find_internal(name, 0, TRUE);
+ dc = devclass_find_internal(name, 0, TRUE, FALSE);
if (!dc) {
printf("make_device: can't find device class %s\n",
name);
@@ -2627,7 +2646,7 @@
return (EINVAL);
}
- dc = devclass_find_internal(classname, 0, TRUE);
+ dc = devclass_find_internal(classname, 0, TRUE, FALSE);
if (!dc)
return (ENOMEM);
@@ -4043,7 +4062,7 @@
kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
root_bus->driver = &root_driver;
root_bus->state = DS_ATTACHED;
- root_devclass = devclass_find_internal("root", 0, FALSE);
+ root_devclass = devclass_find_internal("root", 0, FALSE, FALSE);
devinit();
return (0);
@@ -4083,6 +4102,53 @@
}
/**
+ * @internal
+ * @brief Parses the dmd_busname for filter drivers
+ *
+ * The dmd_busname for filter drivers if represented
+ * by a string of busnames (actually they are names
+ * of DR_LOWEST drivers) delimited by '|' symbol.
+ *
+ * @param in a pointer to dmd_busname string
+ * @param out a pointer to store the address
+ * of an array of strings, representing
+ * the devclass names of DR_LOWEST
+ * drivers.
+ */
+
+static int
+parse_parent_name (char* in, char ***out){ /*TODO*/
+ char* cptr = in, *ptr = in, *newpar;
+ int count = 1, num = 0;
+
+ if (!in || *in == '\0')
+ return (0);
+
+ if (!strcmp(in, "*")){
+ /* do we need this?
+ * if we do, then there must be a way
+ * to add filter driver to devclasses
+ * of drivers, not yet added
+ */
+ }
+ else{
+ while (strchr(ptr, '|')) count++;
+ *out = malloc (sizeof(char*)*(count+1), M_BUS, M_NOWAIT|M_ZERO);
+ count=0;
+ do {
+ while (*ptr!='|' && *ptr!='\0') num++, ptr++;
+ newpar = malloc ((num+1)*sizeof(char), M_BUS, M_NOWAIT|M_ZERO);
+ if (!newpar) return(0);
+ strlcpy(newpar, cptr, num+1);
+ (*out)[count++] = newpar;
+ num = 0; cptr = ++ptr;
+ } while (cptr<(in+strlen(in)));
+ (*out)[count]=NULL;
+ return (1);
+ }
+}
+
+/**
* @brief Module handler for registering device drivers
*
* This module handler is used to automatically register device
@@ -4095,12 +4161,16 @@
{
int error;
struct driver_module_data *dmd;
- devclass_t bus_devclass;
+ devclass_t bus_devclass, parent_devclass, filter_devclass;
drv_internal_t drv_intnl;
kobj_class_t driver;
+ char* parents[];
+ int count=0;
dmd = (struct driver_module_data *)arg;
- bus_devclass = devclass_find_internal(dmd->dmd_busname, 0, TRUE);
+ drv_intnl = dmd->dmd_driver;
+ if (!(drv_intnl->flags & ~(DR_LOWEST | DR_STACKAWARE | DR_TOPMOST)))
+ bus_devclass = devclass_find_internal(dmd->dmd_busname, 0, TRUE, FALSE);
error = 0;
switch (what) {
@@ -4109,12 +4179,27 @@
error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
//driver = dmd->dmd_driver;
- drv_intnl = dmd->dmd_driver;
drv_compat_add_driver(drv_intnl);
driver = drv_intnl->devops;
PDEBUG(("Loading module: driver %s on bus %s",
DRIVERNAME(driver), dmd->dmd_busname));
- error = devclass_add_driver(bus_devclass, driver);
+ if (drv_intnl->flags & ~(DR_LOWEST | DR_STACKAWARE | DR_TOPMOST)){
+ /* if is a filter driver */
+ if (!parse_parent_name(dmd->dmd_busname, &parents))
+ break;
+ while (parents[count]){
+ parent_devclass = devclass_find_internal (parents[count],
+ 0, TRUE, FALSE);
+ filter_devclass = devclass_find_internal (driver->name,
+ parent[count], TRUE, TRUE);
+ error = devclass_add_driver (filter_devclass, driver);
+ count++;
+ }
+ free(parents);
+ }
+ else{
+ error = devclass_add_driver(bus_devclass, driver);
+ }
if (error)
break;
==== //depot/projects/soc2007/thioretic_gidl/sys/bus.h#4 (text+ko) ====
@@ -498,6 +498,8 @@
uint32_t flags;
};
+#define DR_ALLLEVELS (DR_LOWEST|DR_LOWER|DR_MIDDLE|DR_UPPER|DR_TOPMOST)
+
typedef struct drv_internal *drv_internal_t;
struct driver_module_data {
@@ -513,7 +515,7 @@
\
static struct drv_internal name##_##busname##_intnl { \
(kobj_class_t) &driver, \
- LOWEST \
+ DR_LOWEST \
}; \
\
static struct driver_module_data name##_##busname##_driver_mod = { \
More information about the p4-projects
mailing list