summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorsascha <sascha@nomad.localdomain>2007-10-19 08:45:57 +0200
committersascha <sascha@nomad.localdomain>2007-10-19 08:45:57 +0200
commit3b6d6a45e705efb64fe522158ed33f640073da12 (patch)
treea7f25b80f133f7046ad88b6a19ee320281922ffa /lib
parent98839f801049609613a964e0526083b66d236e5a (diff)
downloadbarebox-3b6d6a45e705efb64fe522158ed33f640073da12.tar.gz
barebox-3b6d6a45e705efb64fe522158ed33f640073da12.tar.xz
- Implement tree structure for devices
- Use device tree structure to implement partitions - Let devinfo print a nice tree - Introduce 'fixed' partitions which are not removable - Fix mount: It was not possible to mount on a relative path.
Diffstat (limited to 'lib')
-rw-r--r--lib/driver.c106
1 files changed, 60 insertions, 46 deletions
diff --git a/lib/driver.c b/lib/driver.c
index 1d1e59b2ad..27b607511e 100644
--- a/lib/driver.c
+++ b/lib/driver.c
@@ -86,6 +86,7 @@ int register_device(struct device_d *new_device)
debug ("register_device: %s\n",new_device->name);
list_add_tail(&new_device->list, &device_list);
+ INIT_LIST_HEAD(&new_device->children);
for_each_driver(drv) {
if (!match(drv, new_device))
@@ -96,17 +97,37 @@ int register_device(struct device_d *new_device)
}
EXPORT_SYMBOL(register_device);
-void unregister_device(struct device_d *old_dev)
+int unregister_device(struct device_d *old_dev)
{
debug("unregister_device: %s:%s\n",old_dev->name, old_dev->id);
+ if (!list_empty(&old_dev->children)) {
+ errno = -EBUSY;
+ return errno;
+ }
+
if (old_dev->driver)
old_dev->driver->remove(old_dev);
list_del(&old_dev->list);
+
+ /* remove device from parents child list */
+ if (old_dev->parent)
+ list_del(&old_dev->sibling);
+
+ return 0;
}
EXPORT_SYMBOL(unregister_device);
+int dev_add_child(struct device_d *dev, struct device_d *child)
+{
+ child->parent = dev;
+
+ list_add_tail(&child->sibling, &dev->children);
+
+ return 0;
+}
+
struct driver_d *get_driver_by_name(const char *name)
{
struct driver_d *drv;
@@ -132,7 +153,7 @@ int register_driver(struct driver_d *drv)
{
struct device_d *dev = NULL;
- debug("register_driver: %s\n",new_driver->name);
+ debug("register_driver: %s\n", drv->name);
list_add_tail(&drv->list, &driver_list);
@@ -148,51 +169,17 @@ int register_driver(struct driver_d *drv)
}
EXPORT_SYMBOL(register_driver);
-static char devicename_from_spec_str_buf[PATH_MAX];
-
-char *deviceid_from_spec_str(const char *str, char **endp)
-{
- char *buf = devicename_from_spec_str_buf;
- const char *end;
- int i = 0;
-
- if (isdigit(*str)) {
- /* No device name given, use default driver mem */
- sprintf(buf, "mem");
- end = str;
- } else {
- /* OK, we have a device name, parse it */
- while (*str) {
- if (*str == ':') {
- str++;
- buf[i] = 0;
- break;
- }
-
- buf[i++] = *str++;
- buf[i] = 0;
- if (i == MAX_DRIVER_NAME)
- return NULL;
- }
- end = str;
- }
-
- if (endp)
- *endp = (char *)end;
-
- return buf;
-}
-
/* Get a device struct from the beginning of the string. Default to mem if no
* device is given, return NULL if a unknown device is given.
* If endp is not NULL, this function stores a pointer to the first character
* after the device name in *endp.
*/
-struct device_d *device_from_spec_str(const char *str, char **endp)
+struct device_d *get_device_by_path(const char *path)
{
- char *name;
- name = deviceid_from_spec_str(str, endp);
- return get_device_by_id(name);
+ if (strncmp(path, "/dev/", 5))
+ return NULL;
+
+ return get_device_by_id(path + 5);
}
ssize_t dev_read(struct device_d *dev, void *buf, size_t count, unsigned long offset, ulong flags)
@@ -254,6 +241,30 @@ int dummy_probe(struct device_d *dev)
return 0;
}
+static int do_devinfo_subtree(struct device_d *dev, int depth, char edge)
+{
+ struct device_d *child;
+ int i;
+
+ for (i = 0; i < depth; i++)
+ printf("| ");
+
+ if (*dev->id)
+ printf("%c----%s\n", edge, dev->id);
+ else if (dev->type == DEVICE_TYPE_FS)
+ printf("%c----filesystem: %s\n", edge, fsdev_get_mountpoint((struct fs_device_d *)dev->type_data));
+
+ if (!list_empty(&dev->children)) {
+ device_for_each_child(dev, child) {
+ do_dev_subtree(child, depth + 1,
+ list_is_last(&child->sibling,
+ &dev->children) ? '`' : '|');
+ }
+ }
+
+ return 0;
+}
+
static int do_devinfo ( cmd_tbl_t *cmdtp, int argc, char *argv[])
{
struct device_d *dev;
@@ -264,23 +275,26 @@ static int do_devinfo ( cmd_tbl_t *cmdtp, int argc, char *argv[])
printf("devices:\n");
for_each_device(dev) {
- printf("%10s: base=0x%08x size=0x%08x (driver %s)\n",
- dev->id, dev->map_base, dev->size,
- dev->driver ?
- dev->driver->name : "none");
+ if (!dev->parent)
+ do_devinfo_subtree(dev, 0, '|');
}
printf("\ndrivers:\n");
for_each_driver(drv)
printf("%10s\n",drv->name);
} else {
- struct device_d *dev = get_device_by_id(argv[1]);
+ struct device_d *dev = get_device_by_path(argv[1]);
if (!dev) {
printf("no such device: %s\n",argv[1]);
return -1;
}
+ printf("base : 0x%08x\nsize : 0x%08x\ndriver: %s\n\n",
+ dev->map_base, dev->size,
+ dev->driver ?
+ dev->driver->name : "none");
+
if (dev->driver)
dev->driver->info(dev);