diff options
author | Daniel Hellstrom <daniel@gaisler.com> | 2011-11-28 09:52:03 +0100 |
---|---|---|
committer | Daniel Hellstrom <daniel@gaisler.com> | 2015-04-17 01:10:16 +0200 |
commit | e7fade3ac4559214ab0508dc54a71a3d1f522afb (patch) | |
tree | 13e32728a3b6adccd3f435db73091a8233d5dadf /cpukit/libdrvmgr/drvmgr_for_each_dev.c | |
parent | LIBPCI: added PCI shell command (diff) | |
download | rtems-e7fade3ac4559214ab0508dc54a71a3d1f522afb.tar.bz2 |
DRVMGR: added driver manager to cpukit/libdrvmgr
Diffstat (limited to 'cpukit/libdrvmgr/drvmgr_for_each_dev.c')
-rw-r--r-- | cpukit/libdrvmgr/drvmgr_for_each_dev.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/cpukit/libdrvmgr/drvmgr_for_each_dev.c b/cpukit/libdrvmgr/drvmgr_for_each_dev.c new file mode 100644 index 0000000000..a3e63ecef9 --- /dev/null +++ b/cpukit/libdrvmgr/drvmgr_for_each_dev.c @@ -0,0 +1,104 @@ +/* Iterate over device tree topology, breadth or depth-first + * + * COPYRIGHT (c) 2009. + * Cobham Gaisler AB. + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include <string.h> +#include <drvmgr/drvmgr.h> +#include <drvmgr/drvmgr_list.h> +#include "drvmgr_internal.h" + +/* Traverse device tree breadth-first. Supports up to 31 buses */ +static int drvmgr_for_each_dev_breadth( + int (*func)(struct drvmgr_dev *dev, void *arg), + void *arg + ) +{ + int ret = 0, i, pos; + struct drvmgr_bus *bus, *buses[32]; + struct drvmgr_dev *dev; + + pos = 0; + memset(&buses[0], 0, sizeof(buses)); + buses[pos++] = drv_mgr.root_dev.bus; /* Get root bus */ + + for (i = 0, bus = buses[0]; buses[i]; i++, bus = buses[i]) { + dev = bus->children; + while (dev) { + ret = func(dev, arg); + if (ret != 0) + break; + if (dev->bus && pos < 31) + buses[pos++] = dev->bus; + + dev = dev->next_in_bus; + } + } + + return ret; +} + +/* Traverse device tree depth-first. */ +static int drvmgr_for_each_dev_depth( + int (*func)(struct drvmgr_dev *dev, void *arg), + void *arg + ) +{ + int ret = 0; + struct drvmgr_dev *dev; + + /* Get first device */ + dev = drv_mgr.root_dev.bus->children; + + while (dev) { + ret = func(dev, arg); + if (ret != 0) + break; + if (dev->bus && dev->bus->children) { + dev = dev->bus->children; + } else { +next_dev: + if (dev->next_in_bus == NULL) { + /* Step up one level... back to parent bus */ + dev = dev->parent->dev; + if (dev == &drv_mgr.root_dev) + break; + goto next_dev; + } else { + dev = dev->next_in_bus; + } + } + } + + return ret; +} + +/* Traverse device tree depth-first or breadth-first */ +int drvmgr_for_each_dev( + int (*func)(struct drvmgr_dev *dev, void *arg), + void *arg, + int options + ) +{ + int ret; + + DRVMGR_LOCK_READ(); + + /* Get Root Device */ + if (drv_mgr.root_dev.bus->children != NULL) { + if (options & DRVMGR_FED_BF) + ret = drvmgr_for_each_dev_breadth(func, arg); + else + ret = drvmgr_for_each_dev_depth(func, arg); + } else + ret = 0; + + DRVMGR_UNLOCK(); + + return ret; +} |