forked from Imagelibrary/rtems
104 lines
2.1 KiB
C
104 lines
2.1 KiB
C
/* 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 <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++] = 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;
|
|
}
|