PERFORCE change 123068 for review
Maxim Zhuravlev
thioretic at FreeBSD.org
Sat Jul 7 19:06:19 UTC 2007
http://perforce.freebsd.org/chv.cgi?CH=123068
Change 123068 by thioretic at thioretic on 2007/07/07 19:05:27
Start to introduce advanced topology stuff.
Now device has multiple parents, so some dummy
find & replace. Those for bus_generic_* stuff next time.)
Affected files ...
.. //depot/projects/soc2007/thioretic_gidl/TODO#9 edit
.. //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#7 edit
.. //depot/projects/soc2007/thioretic_gidl/sys/bus.h#5 edit
Differences ...
==== //depot/projects/soc2007/thioretic_gidl/TODO#9 (text+ko) ====
@@ -71,6 +71,7 @@
# represent drivers of interest.
a.1.2 Devclasses
SOLUTION: add filters field to devclass
+ FILE(S) AFFECTED: kern/subr_bus.c
# 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
@@ -81,9 +82,27 @@
#
# BUS<-+-+....
# |
- # DR_LOWEST driver_n<-+----+...
- # | |
- # filter0 filter1
+ # DR_LOWEST driver_n<-+-----+...
+ # | |
+ # filter_0 filter_1
#
# NB: here BUS is also a DR_LOWEST driver in turn with all
- # those consequences.+ # those consequences.
+ a.1.3 Topology
+ SOLUTION: add a kinda *REQDEV* flag for driver
+ FILE(S) AFFECTED: kern/subr_bus.c, sys/bus.h
+ # Currently device layout is hardware-driven (i.e. depends on
+ # device - bus relations). But all the fun (the project) is all
+ # about adding functionality-driven layout to newbus. I.e.
+ # mux / demux depends not so much on hardware topology as on
+ # functionality , provided by a device (i.e whether it is a mouse
+ # or a keyboard or ...). At this point it's obvious, that currently
+ # there are no means, provided by newbus, to build a *device*, not
+ # backed up by a *real* device, into the newbus tree. At same time
+ # it's a good idea to use the built tree for such functional (eg. mux)
+ # devices. At this point it's obvious, that there should be means to
+ # create a corresponding device on driver add, and init it to the
+ # driver without any probing. Also a device may have multiple parents
+ # and children. At this point it becomes obvious, that we should let
+ # a driver not just process, but also produce and destroy an io request.
+
==== //depot/projects/soc2007/thioretic_gidl/kern/subr_bus.c#7 (text+ko) ====
@@ -82,7 +82,7 @@
typedef struct drv_compat *drv_compat_t;
struct pdrv_compat {
- drv_compat *pdriver;
+ drv_compat_t pdriver;
TAILQ_ENTRY(pdrv_compat) link;
};
@@ -132,7 +132,8 @@
*/
TAILQ_ENTRY(device) link; /**< list of devices in parent */
TAILQ_ENTRY(device) devlink; /**< global device list membership */
- device_t parent; /**< parent of this device */
+ //device_t parent; /**< parent of this device */
+ device_list_t parents;
device_list_t children; /**< list of child devices */
/*
@@ -915,6 +916,17 @@
return (1);
}
+static int
+drv_compat_flags2idx (uint32_t flags){
+ switch (flags & DR_ALLEVELS){
+ case DR_LOWEST: return (DRV_LOWEST);
+ case DR_LOWER: return (DRV_LOWER);
+ case DR_MIDDLE: return (DRV_MIDDLE);
+ case DR_UPPER: return (DRV_UPPER);
+ case DR_TOPMOST: return (DRV_TOPMOST);
+ }
+}
+
/**
* device control multiplexing entries
*/
@@ -1076,7 +1088,7 @@
DEVMETHOD(bus_hinted_child, drv_compat_ctrl_hinted_child)
};
-static driver_t drv_compat_ctrl_driver = {
+static driver_t drv_compat_ctrl_driver = { /*TODO*/
"drv_compat_ctrl",
drv_compat_ctrl_methods,
0
@@ -1093,7 +1105,7 @@
//driverlink_t dl;
pdrv_compat* pdrvl;
if (!drv_compat_get_flags(driver, &flags))
- /*todo what?*/
+ /*todo what?*/;
switch ((flags)&(DR_LOWEST|DR_LOWER|DR_MIDDLE|DR_UPPER|DR_TOPMOST)) {
case DR_LOWEST: level=DRV_LOWEST; break;
@@ -1176,7 +1188,7 @@
}
if (filter) {
- TAILQ_INSERT_TAIL(&(dc->parent->filters), dc, link);
+ TAILQ_INSERT_TAIL(&(dc->parent->filters), &dc, link);
}
return (dc);
@@ -1246,7 +1258,7 @@
* Make sure the devclass which the driver is implementing exists.
*/
if (!drv_compat_get_flags (driver, &flags)){
- /*todo what???*/
+ /*todo what???*/;
}
devclass_find_internal(driver->name, 0, TRUE, FALSE);
@@ -1322,8 +1334,8 @@
if (dc->devices[i]) {
dev = dc->devices[i];
if (/*dev->driver == driver*/
- is_device_driver(dev, driver) && dev->parent &&
- dev->parent->devclass == busclass) {
+ is_device_driver(dev, driver) && !TAILQ_EMPTY(&(dev->parents)) &&
+ (TAILQ_FIRST(&(dev->parent->devclass))) == busclass) {
if ((error = device_detach(dev)) != 0)
return (error);
device_set_driver(dev, NULL);
@@ -1398,8 +1410,8 @@
if (dc->devices[i]) {
dev = dc->devices[i];
if (/*dev->driver == driver*/
- is_device_driver(dev, driver) && dev->parent &&
- dev->parent->devclass == busclass) {
+ is_device_driver(dev, driver) && !TAILQ_EMPTY(&(dev->parents) &&
+ (TAILQ_FIRST(&(dev->parent)))->devclass == busclass) {
if ((error = device_quiesce(dev)) != 0)
return (error);
}
@@ -1820,11 +1832,12 @@
* @returns the new device
*/
static device_t
-make_device(device_t parent, const char *name, int unit) /*TODO*/
+make_device(device_t parent, const char *name, int unit, driver_t *initto) /*TODO*/
{
device_t dev;
devclass_t dc;
int level;
+ drv_compat_t drvc;
PDEBUG(("%s at %s as unit %d", name, DEVICENAME(parent), unit));
@@ -1842,14 +1855,27 @@
dev = malloc(sizeof(struct device), M_BUS, M_NOWAIT|M_ZERO);
if (!dev)
return (NULL);
-
- dev->parent = parent;
- TAILQ_INIT(&dev->children);
- kobj_init((kobj_t) dev, &null_class);
+ TAILQ_INIT(&(dev->parents));
+ TAILQ_INSERT_TAIL(&(dev->parents), *parent, link)
+ TAILQ_INIT(&(dev->children));
+ //kobj_init((kobj_t) dev, &null_class);
+ kobj_init((kobj_t) dev, &drv_compat_ctrl_driver)
//dev->driver = NULL;
for (level=DRV_LOWEST; level<=DRV_TOPMOST; level++)
TAILQ_INIT(&((dev->drivers)[level]));
- dev->devclass = NULL;
+ if (initto){
+ drvc = drv_compat_find_driver (initto);
+ if (!(drvc->topology_ops = kobj_create (initto, M_BUS, M_NOWAIT|M_ZERO)))
+ /*todo what??*/;
+ dev->devclass = devclass_find (DRIVERNAME(driver));
+ level = drv_compat_flags2idx(drvc->flags);
+ TAILQ_INSERT_TAIL (&((dev->drivers)[level]), &drvc, link);
+ dev->state = DS_ALIVE;
+ }
+ else{
+ dev->devclass = NULL;
+ dev->state = DS_NOTPRESENT;
+ }
dev->unit = unit;
dev->nameunit = NULL;
dev->desc = NULL;
@@ -1863,13 +1889,13 @@
dev->flags |= DF_FIXEDCLASS;
if (devclass_add_device(dc, dev)) {
kobj_delete((kobj_t) dev, M_BUS);
+ dev->state = 0;
return (NULL);
}
}
dev->ivars = NULL;
dev->softc = NULL;
- dev->state = DS_NOTPRESENT;
TAILQ_INSERT_TAIL(&bus_data_devices, dev, devlink);
bus_data_generation_update();
@@ -1945,7 +1971,7 @@
PDEBUG(("%s at %s with order %d as unit %d",
name, DEVICENAME(dev), order, unit));
- child = make_device(dev, name, unit);
+ child = make_device(dev, name, unit, NULL);
if (child == NULL)
return (child);
child->order = order;
@@ -2013,6 +2039,15 @@
return (0);
}
+static int
+is_device_parent (device_t dev, device_t child){
+ device_t dc;
+ TAILQ_FOREACH (dc, &(child->parents), link){
+ if (dc == dev) return (1);
+ }
+ return (0);
+}
+
/**
* @brief Find a device given a unit number
*
@@ -2039,12 +2074,14 @@
if (unit != -1) {
child = devclass_get_device(dc, unit);
- if (child && child->parent == dev)
+ if (child && /*child->parent == dev*/
+ is_device_parent(dev, child))
return (child);
} else {
for (unit = 0; unit < devclass_get_maxunit(dc); unit++) {
child = devclass_get_device(dc, unit);
- if (child && child->parent == dev)
+ if (child && /*child->parent == dev*/
+ is_device_parent(dev, child))
return (child);
}
}
@@ -2224,9 +2261,11 @@
* @brief Return the parent of a device
*/
device_t
-device_get_parent(device_t dev)
+device_get_parent(device_t dev) /*TODO*/
{
- return (dev->parent);
+ if (!TAILQ_EMPTY(&(dev->parents)))
+ return (TAILQ_FIRST(&(dev->parents)));
+ return (NULL);
}
/**
@@ -2545,10 +2584,14 @@
void
device_busy(device_t dev)
{
+ device_t parent;
if (dev->state < DS_ATTACHED)
panic("device_busy: called for unattached device");
- if (dev->busy == 0 && dev->parent)
- device_busy(dev->parent);
+ if (dev->busy == 0 && !TAILQ_EMPTY(&(dev->parents))){
+ TAILQ_FOREACH (parent, &(dev->parents), link){
+ device_busy(parent);
+ }
+ }
dev->busy++;
dev->state = DS_BUSY;
}
@@ -2564,8 +2607,12 @@
device_get_nameunit(dev));
dev->busy--;
if (dev->busy == 0) {
- if (dev->parent)
- device_unbusy(dev->parent);
+ if (/*dev->parent*/!TAILQ_EMPTY(&(dev->parents))){
+ TAILQ_FOREACH (parent, &(dev->parents), link){
+ device_unbusy(parent);
+ }
+ }
+ //device_unbusy(dev->parent);
dev->state = DS_ATTACHED;
}
}
@@ -2725,7 +2772,7 @@
* @retval non-zero some other unix error code
*/
int
-device_probe_and_attach(device_t dev)
+device_probe_and_attach(device_t dev) /*TODO*/
{
int error;
@@ -2777,10 +2824,14 @@
device_attach(device_t dev)
{
int error;
+ device_t parent;
device_sysctl_init(dev);
- if (!device_is_quiet(dev))
- device_print_child(dev->parent, dev);
+ if (!device_is_quiet(dev)){
+ TAILQ_FOREACH (parent, &(dev->parents), link){
+ device_print_child(parent, dev);
+ }
+ }
if ((error = DEVICE_ATTACH(dev)) != 0) {
printf("device_attach: %s%d attach returned %d\n",
dev->driver->name, dev->unit, error);
@@ -2817,6 +2868,7 @@
device_detach(device_t dev)
{
int error;
+ device_t parent;
GIANT_REQUIRED;
@@ -2830,8 +2882,11 @@
return (error);
devremoved(dev);
device_printf(dev, "detached\n");
- if (dev->parent)
- BUS_CHILD_DETACHED(dev->parent, dev);
+ if (!TAILQ_EMPTY(&(dev->parent))){
+ TAILQ_FOREACH (parent, &(dev->parents), link){
+ BUS_CHILD_DETACHED(parent, dev);
+ }
+ }
if (!(dev->flags & DF_FIXEDCLASS))
devclass_delete_device(dev->devclass, dev);
@@ -4057,7 +4112,7 @@
case MOD_LOAD:
TAILQ_INIT(&bus_data_devices);
kobj_class_compile((kobj_class_t) &root_driver);
- root_bus = make_device(NULL, "root", 0);
+ root_bus = make_device(NULL, "root", 0, NULL);
root_bus->desc = "System root bus";
kobj_init((kobj_t) root_bus, (kobj_class_t) &root_driver);
root_bus->driver = &root_driver;
@@ -4159,13 +4214,13 @@
int
driver_module_handler(module_t mod, int what, void *arg)
{
- int error;
+ int error=0;
struct driver_module_data *dmd;
devclass_t bus_devclass, parent_devclass, filter_devclass;
drv_internal_t drv_intnl;
kobj_class_t driver;
char* parents[];
- int count=0;
+ int count=0, isfilter;
dmd = (struct driver_module_data *)arg;
drv_intnl = dmd->dmd_driver;
@@ -4183,23 +4238,24 @@
driver = drv_intnl->devops;
PDEBUG(("Loading module: driver %s on bus %s",
DRIVERNAME(driver), dmd->dmd_busname));
- if (drv_intnl->flags & ~(DR_LOWEST | DR_STACKAWARE | DR_TOPMOST)){
+ if (!parse_parent_name(dmd->dmd_busname, &parents))
+ break;
+ isfilter = drv_intnl->flags & ~(DR_LOWEST | DR_STACKAWARE | DR_TOPMOST);
+ while (parents[count]){
+ if (isfilter){
/* 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);
+ error &= devclass_add_driver (filter_devclass, driver);
count++;
}
- free(parents);
+ else{
+ error &= devclass_add_driver(parents[count], driver);
+ }
}
- else{
- error = devclass_add_driver(bus_devclass, driver);
- }
+ free(parents);
if (error)
break;
@@ -4220,6 +4276,15 @@
*dmd->dmd_devclass =
devclass_find_internal(driver->name, 0, TRUE);
}
+
+ if(drv_intnl->flags & DR_REQDEV){ /*restrict to DR_LOWEST? */
+ make_device (root_bus, DRIVERNAME(driver), -1, driver);
+ /* todo: set all parents for device
+ * parents are all devices (alive) in parent
+ * devclasses
+ */
+ }
+
break;
case MOD_UNLOAD:
==== //depot/projects/soc2007/thioretic_gidl/sys/bus.h#5 (text+ko) ====
@@ -495,6 +495,7 @@
#define DR_MIDDLE 8
#define DR_UPPER 16
#define DR_TOPMOST 32
+#define DR_REQDEV 64
uint32_t flags;
};
More information about the p4-projects
mailing list