forked from Imagelibrary/rtems
123 lines
3.2 KiB
C
123 lines
3.2 KiB
C
/* SPDX-License-Identifier: BSD-2-Clause */
|
|
|
|
/* Iterate over device tree topology, breadth or depth-first
|
|
*
|
|
* COPYRIGHT (c) 2009 Cobham Gaisler AB.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#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 intptr_t drvmgr_for_each_dev_breadth(
|
|
intptr_t (*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 intptr_t drvmgr_for_each_dev_depth(
|
|
intptr_t (*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 */
|
|
intptr_t drvmgr_for_each_dev(
|
|
intptr_t (*func)(struct drvmgr_dev *dev, void *arg),
|
|
void *arg,
|
|
int options
|
|
)
|
|
{
|
|
intptr_t 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;
|
|
}
|