PERFORCE change 123211 for review
Maxim Zhuravlev
thioretic at FreeBSD.org
Mon Jul 9 16:44:30 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=123211
Change 123211 by thioretic at thioretic on 2007/07/09 16:43:44
TODO: softc, device_set_driver semantics, some functional
drivers related (i.e. parents' manipulation (add/remove))
stuff and some cleanups.
Affected files ...
.. //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#10 edit
Differences ...
==== //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#10 (text+ko) ====
@@ -140,7 +140,8 @@
/*
* Details of this device.
*/
- /*driver_t*/ drv_compat_t driver; /**< current driver to be probed/attached/...*/
+ /*driver_t*/ pdrv_compat *driver; /**< current driver to be probed/attached/...*/
+ int driver_level;
//driver_list_t drivers[DRV_LEVELS];
pdrv_compat_list_t drivers[DRV_LEVELS];
int drv_compat_flags;
@@ -355,7 +356,7 @@
SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
OID_AUTO, "%driver", CTLFLAG_RD,
dev, DEVICE_SYSCTL_DRIVER, device_sysctl_handler, "A",
- "device driver name"); /*TODO*/
+ "device drivers names"); /**TODO*/
SYSCTL_ADD_PROC(&dev->sysctl_ctx, SYSCTL_CHILDREN(dev->sysctl_tree),
OID_AUTO, "%location", CTLFLAG_RD,
dev, DEVICE_SYSCTL_LOCATION, device_sysctl_handler, "A",
@@ -923,7 +924,12 @@
drvc->flags = flags;
return (1);
}
-
+/**
+ * @internal
+ * @brief Checks driver and returns corresponding driver
+ *
+ * @param flags drv_compat flags
+ */
static int
drv_compat_flags2idx (uint32_t flags){
switch (flags & DR_ALLEVELS){
@@ -935,6 +941,15 @@
}
}
+drv_compat_isfilter (driver_t *driver){
+ uint32_t flags;
+ int level;
+
+ drv_compat_get_flags (driver, &flags);
+ level = drv_compat_flags2idx (flags);
+ return((level>DR_LOWEST & level<DR_TOPMOST) ? TRUE : FALSE);
+}
+
/**
* device control multiplexing entries
*/
@@ -1106,24 +1121,26 @@
* End of compatibility layer implementaion
*/
-int
-is_device_driver (device_t dev, driver_t *driver){ /*TODO*/
+/**
+ * @internal
+ * @brief Checks, whether the driver is in device's stack
+ *
+ * @param dev device, to check
+ * @param driver driver, to be checked
+ */
+static int
+is_device_driver (device_t dev, driver_t *driver){
int level;
uint32_t flags;
- //driverlink_t dl;
pdrv_compat* pdrvl;
+
if (!drv_compat_get_flags(driver, &flags))
/*todo what?*/;
-
- switch ((flags)&(DR_LOWEST|DR_LOWER|DR_MIDDLE|DR_UPPER|DR_TOPMOST)) {
- case DR_LOWEST: level=DRV_LOWEST; break;
- case DR_LOWER: level=DRV_LOWER; break;
- case DR_MIDDLE: level=DRV_MIDDLE; break;
- case DR_UPPER: level=DRV_UPPER; break;
- case DR_TOPMOST: level=DRV_TOPMOST; break;
- }
+ level = drv_compat_flags2idx (flags);
+
TAILQ_FOREACH(pdrvl,&((dev->drivers)[level]),link){
- if (pdrvl->pdriver->driver==driver) return(TRUE);
+ if (pdrvl->pdriver->driver == driver)
+ return(TRUE);
}
return(FALSE);
}
@@ -1153,9 +1170,9 @@
*/
static devclass_t
devclass_find_internal(const char *classname, const char *parentname,
- int create, int filter)
+ int create, int filter) /**TODO*/
{
- devclass_t dc;
+ devclass_t dc, dcp;
PDEBUG(("looking for %s", classname));
if (!classname)
@@ -1190,13 +1207,19 @@
* device_probe_child() if a device exists for which there is no
* suitable driver.
*/
- if (parentname && dc && !dc->parent &&
- strcmp(classname, parentname) != 0) {
- dc->parent = devclass_find_internal(parentname, 0, FALSE, FALSE);
+ if (!parentname)
+ return (dc);
+
+ dcp = devclass_find_internal(parentname, 0, FALSE, FALSE)
+
+ if (dc && !dc->parent &&
+ strcmp(classname, parentname) != 0 &&
+ !filter) {
+ dc->parent = dcp;
}
if (filter) {
- TAILQ_INSERT_TAIL(&(dc->parent->filters), &dc, link);
+ TAILQ_INSERT_TAIL(&(dcp->filters), &dc, link);
}
return (dc);
@@ -1242,11 +1265,13 @@
* @param driver the driver to register
*/
int
-devclass_add_driver(devclass_t dc, driver_t *driver)
+devclass_add_driver(devclass_t dc, driver_t *driver) /*TODO*/
{
driverlink_t dl;
int i;
uint32_t flags;
+ int isfilter;
+ drv_compat_t drvc;
PDEBUG(("%s", DRIVERNAME(driver)));
@@ -1254,22 +1279,26 @@
if (!dl)
return (ENOMEM);
+ isfilter = drv_compat_isfilter (driver);
/*
* Compile the driver's methods. Also increase the reference count
* so that the class doesn't get freed when the last instance
* goes. This means we can safely use static methods and avoids a
* double-free in devclass_delete_driver.
*/
- kobj_class_compile((kobj_class_t) driver);
+ //kobj_class_compile((kobj_class_t) driver);
+
+ drvc = drv_compat_find_driver (driver);
+ drvc->topology_ops = kobj_create (drvc->driver, M_BUS, M_NOWAIT|M_ZERO);
/*
* Make sure the devclass which the driver is implementing exists.
*/
- if (!drv_compat_get_flags (driver, &flags)){
- /*todo what???*/;
- }
- devclass_find_internal(driver->name, 0, TRUE, FALSE);
+ if (isfilter)
+ devclass_find_internal(driver->name, dc->name, TRUE, TRUE);
+ else
+ devclass_find_internal(driver->name, 0, TRUE, FALSE);
dl->driver = driver;
TAILQ_INSERT_TAIL(&dc->drivers, dl, link);
@@ -1278,9 +1307,14 @@
/*
* Call BUS_DRIVER_ADDED for any existing busses in this class.
*/
- for (i = 0; i < dc->maxunit; i++)
- if (dc->devices[i])
- BUS_DRIVER_ADDED(dc->devices[i], driver);
+ if (!isfilter){
+ for (i = 0; i < dc->maxunit; i++)
+ if (dc->devices[i])
+ BUS_DRIVER_ADDED(dc->devices[i], driver);
+ }
+ else {
+ devclass_filter2devices(dc, driver);
+ }
bus_data_generation_update();
return (0);
@@ -1308,6 +1342,7 @@
device_t dev;
int i;
int error;
+ drv_compat_t drvc;
PDEBUG(("%s from devclass %s", driver->name, DEVCLANAME(busclass)));
@@ -1342,8 +1377,10 @@
if (dc->devices[i]) {
dev = dc->devices[i];
if (/*dev->driver == driver*/
- is_device_driver(dev, driver) && !TAILQ_EMPTY(&(dev->parents)) &&
+ is_device_driver(dev, driver) &&
+ !TAILQ_EMPTY(&(dev->parents)) &&
(TAILQ_FIRST(&(dev->parents)))->device_ptr->devclass == busclass) {
+ device_set_driver(dev, driver);
if ((error = device_detach(dev)) != 0)
return (error);
device_set_driver(dev, NULL);
@@ -1356,8 +1393,11 @@
/* XXX: kobj_mtx */
driver->refs--;
- if (driver->refs == 0)
- kobj_class_free((kobj_class_t) driver);
+ if (driver->refs == 0){
+ drvc = drv_compat_find_driver (driver);
+ //kobj_class_free((kobj_class_t) driver);
+ kobj_delete (drvc->topology_ops, M_BUS);
+ }
bus_data_generation_update();
return (0);
@@ -1770,9 +1810,10 @@
* @retval ENOMEM memory allocation failure
*/
static int
-devclass_add_device(devclass_t dc, device_t dev)
+devclass_add_device(devclass_t dc, device_t dev) /*TODO*/
{
int buflen, error;
+ drv_compat_t drvc;
PDEBUG(("%s in devclass %s", DEVICENAME(dev), DEVCLANAME(dc)));
@@ -1792,6 +1833,8 @@
dev->devclass = dc;
snprintf(dev->nameunit, buflen, "%s%d", dc->name, dev->unit);
+ devclass_device2filters (dc, dev);
+
return (0);
}
@@ -1808,7 +1851,7 @@
* @retval 0 success
*/
static int
-devclass_delete_device(devclass_t dc, device_t dev)
+devclass_delete_device(devclass_t dc, device_t dev) /*TODO*/
{
if (!dc || !dev)
return (0);
@@ -1827,6 +1870,46 @@
return (0);
}
+static int
+filter_probe_and_attach (device_t dev, driver_t *driver){
+ drv_compat_t drvc;
+ int level;
+
+ device_set_driver (dev, dl->driver);
+ if (DEVICE_PROBE(dev)<=0){
+ drvc = dev->driver;
+ level = drv_compat_flags2idx(drvc->flags);
+ TAILQ_INSERT_TAIL (&((dev->drivers)[level]), &drvc, link);
+ }
+ device_set_driver (dev, NULL);
+}
+
+static void
+devclass_device2filters (devclass_t dc, device_t dev){
+ pdevclass *pdc;
+ driver_t *drv;
+ driverlink_t dl;
+
+ if (TAILQ_EMPTY(&(dc->filters))) return ();
+ TAILQ_FOREACH (pdc, &(dc->filters), link){
+ if (TAILQ_EMPTY(&(pdc->driver_ptr->drivers)))
+ continue;
+ TAILQ_FOREACH(dl, &(pdc->driver_ptr->drivers), link){
+ filter_probe_and_attach (dev, dl->driver);
+ }
+ }
+}
+
+static void
+devclass_filter2devices (devclass_t dc, driver_t *filter){
+ int i;
+
+ for (i=0, i<=dc->maxunit; i++){
+ if ((dc->devices[i]) &&
+ ((dc->devices[i])->state == DS_ALIVE))
+ filter_probe_and_attach (dv->devices[i], filter);
+ }
+}
/**
* @internal
* @brief Make a new device and add it as a child of @p parent
@@ -2747,13 +2830,31 @@
* @retval ENOMEM a memory allocation failure occurred
*/
int
-device_set_driver(device_t dev, driver_t *driver)
+device_set_driver(device_t dev, driver_t *driver) /*TODO*/
{
- drv_compat_t drvc;
+ drv_compat_t drvc;
+ pdrv_compat *drvctmp;
+ uint32_t flags;
+ int level;
if (dev->state >= DS_ATTACHED)
return (EBUSY);
+
+ drvc = drv_compat_find_driver (driver);
+
+ TAILQ_FOREACH(drvctmp, &(dev->drivers[level]), link){
+ if (drvctmp->pdriver == drvc)
+ break;
+ }
+
+ if (!drvctmp){
+
+ }
+ dev->driver = drvctmp;
+ dev->driver_level = level;
+
+ /*
if (dev->driver == driver)
return (0);
@@ -2761,13 +2862,7 @@
free(dev->softc, M_BUS_SC);
dev->softc = NULL;
}
- //kobj_delete((kobj_t) dev, 0);
- dev->driver = drvc = drv_compat_find_driver (driver);
if (driver) {
- if (!(drvc->topology_ops = kobj_create (initto, M_BUS, M_NOWAIT|M_ZERO)))
- /*todo what??*/;
- dev->driver = drvc;
- //kobj_init((kobj_t) dev, (kobj_class_t) driver);
if (!(dev->flags & DF_EXTERNALSOFTC) && driver->size > 0) {
dev->softc = malloc(driver->size, M_BUS_SC,
M_NOWAIT | M_ZERO);
@@ -2778,8 +2873,6 @@
return (ENOMEM);
}
}
- } /*else {
- kobj_init((kobj_t) dev, &null_class);
}*/
bus_data_generation_update();
@@ -2889,7 +2982,7 @@
dev->devclass = devclass_find (DRIVERNAME(drvc->driver));
level = drv_compat_flags2idx(drvc->flags);
TAILQ_INSERT_TAIL (&((dev->drivers)[level]), &drvc, link);
- driver = NULL;
+ dev->driver = NULL;
}
dev->state = DS_ATTACHED;
devadded(dev);
@@ -4273,8 +4366,6 @@
dmd = (struct driver_module_data *)arg;
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) {
@@ -4282,27 +4373,17 @@
if (dmd->dmd_chainevh)
error = dmd->dmd_chainevh(mod,what,dmd->dmd_chainarg);
- //driver = 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));
if (!parse_parent_name(dmd->dmd_busname, &parents))
break;
- isfilter = drv_intnl->flags & ~(DR_LOWEST | DR_STACKAWARE | DR_TOPMOST);
+ isfilter = drv_compat_isfilter (driver);
while (parents[count]){
- if (isfilter){
- /* if is a filter driver */
- 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++;
- }
- else{
- error &= devclass_add_driver(parents[count], driver);
- }
+ parent_devclass = devclass_find_internal(parents[count], 0, TRUE, FALSE);
+ error &= devclass_add_driver (parent_devclass, driver);
+ count++;
}
free(parents);
if (error)
@@ -4330,7 +4411,7 @@
dev = make_device (root_bus, DRIVERNAME(driver), -1/*, driver*/);
device_set_driver(dev, driver);
/*if (!hasclass)*/
- device_set_devclass(child, dl->driver->name);
+ device_set_devclass(dev, driver->name);
/* Fetch any flags for the device before probing.
resource_int_value(dl->driver->name, child->unit,
More information about the p4-projects
mailing list