/* 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.org/license/LICENSE. */ #include #include #include #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++] = drvmgr.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 = drvmgr.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 == &drvmgr.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 (drvmgr.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; }