Date: Sat, 7 Jul 2007 19:06:19 GMT From: Maxim Zhuravlev <thioretic@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 123068 for review Message-ID: <200707071906.l67J6Jwa048799@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=123068 Change 123068 by thioretic@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; };
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200707071906.l67J6Jwa048799>