[e7fade3] | 1 | /* Iterate over device tree topology, breadth or depth-first |
---|
| 2 | * |
---|
[65d1f35] | 3 | * COPYRIGHT (c) 2009 Cobham Gaisler AB. |
---|
[e7fade3] | 4 | * |
---|
| 5 | * The license and distribution terms for this file may be |
---|
| 6 | * found in the file LICENSE in this distribution or at |
---|
[0decc806] | 7 | * http://www.rtems.org/license/LICENSE. |
---|
[e7fade3] | 8 | */ |
---|
| 9 | |
---|
| 10 | #include <string.h> |
---|
| 11 | #include <drvmgr/drvmgr.h> |
---|
| 12 | #include <drvmgr/drvmgr_list.h> |
---|
| 13 | #include "drvmgr_internal.h" |
---|
| 14 | |
---|
| 15 | /* Traverse device tree breadth-first. Supports up to 31 buses */ |
---|
[a7e8996] | 16 | static intptr_t drvmgr_for_each_dev_breadth( |
---|
| 17 | intptr_t (*func)(struct drvmgr_dev *dev, void *arg), |
---|
[e7fade3] | 18 | void *arg |
---|
| 19 | ) |
---|
| 20 | { |
---|
| 21 | int ret = 0, i, pos; |
---|
| 22 | struct drvmgr_bus *bus, *buses[32]; |
---|
| 23 | struct drvmgr_dev *dev; |
---|
| 24 | |
---|
| 25 | pos = 0; |
---|
| 26 | memset(&buses[0], 0, sizeof(buses)); |
---|
[bb2f220] | 27 | buses[pos++] = drvmgr.root_dev.bus; /* Get root bus */ |
---|
[e7fade3] | 28 | |
---|
| 29 | for (i = 0, bus = buses[0]; buses[i]; i++, bus = buses[i]) { |
---|
| 30 | dev = bus->children; |
---|
| 31 | while (dev) { |
---|
| 32 | ret = func(dev, arg); |
---|
| 33 | if (ret != 0) |
---|
| 34 | break; |
---|
| 35 | if (dev->bus && pos < 31) |
---|
| 36 | buses[pos++] = dev->bus; |
---|
| 37 | |
---|
| 38 | dev = dev->next_in_bus; |
---|
| 39 | } |
---|
| 40 | } |
---|
| 41 | |
---|
| 42 | return ret; |
---|
| 43 | } |
---|
| 44 | |
---|
| 45 | /* Traverse device tree depth-first. */ |
---|
[a7e8996] | 46 | static intptr_t drvmgr_for_each_dev_depth( |
---|
| 47 | intptr_t (*func)(struct drvmgr_dev *dev, void *arg), |
---|
[e7fade3] | 48 | void *arg |
---|
| 49 | ) |
---|
| 50 | { |
---|
| 51 | int ret = 0; |
---|
| 52 | struct drvmgr_dev *dev; |
---|
| 53 | |
---|
| 54 | /* Get first device */ |
---|
[bb2f220] | 55 | dev = drvmgr.root_dev.bus->children; |
---|
[e7fade3] | 56 | |
---|
| 57 | while (dev) { |
---|
| 58 | ret = func(dev, arg); |
---|
| 59 | if (ret != 0) |
---|
| 60 | break; |
---|
| 61 | if (dev->bus && dev->bus->children) { |
---|
| 62 | dev = dev->bus->children; |
---|
| 63 | } else { |
---|
| 64 | next_dev: |
---|
| 65 | if (dev->next_in_bus == NULL) { |
---|
| 66 | /* Step up one level... back to parent bus */ |
---|
| 67 | dev = dev->parent->dev; |
---|
[bb2f220] | 68 | if (dev == &drvmgr.root_dev) |
---|
[e7fade3] | 69 | break; |
---|
| 70 | goto next_dev; |
---|
| 71 | } else { |
---|
| 72 | dev = dev->next_in_bus; |
---|
| 73 | } |
---|
| 74 | } |
---|
| 75 | } |
---|
| 76 | |
---|
| 77 | return ret; |
---|
| 78 | } |
---|
| 79 | |
---|
| 80 | /* Traverse device tree depth-first or breadth-first */ |
---|
[a7e8996] | 81 | intptr_t drvmgr_for_each_dev( |
---|
| 82 | intptr_t (*func)(struct drvmgr_dev *dev, void *arg), |
---|
[e7fade3] | 83 | void *arg, |
---|
| 84 | int options |
---|
| 85 | ) |
---|
| 86 | { |
---|
[a7e8996] | 87 | intptr_t ret; |
---|
[e7fade3] | 88 | |
---|
| 89 | DRVMGR_LOCK_READ(); |
---|
| 90 | |
---|
| 91 | /* Get Root Device */ |
---|
[bb2f220] | 92 | if (drvmgr.root_dev.bus->children != NULL) { |
---|
[e7fade3] | 93 | if (options & DRVMGR_FED_BF) |
---|
| 94 | ret = drvmgr_for_each_dev_breadth(func, arg); |
---|
| 95 | else |
---|
| 96 | ret = drvmgr_for_each_dev_depth(func, arg); |
---|
| 97 | } else |
---|
| 98 | ret = 0; |
---|
| 99 | |
---|
| 100 | DRVMGR_UNLOCK(); |
---|
| 101 | |
---|
| 102 | return ret; |
---|
| 103 | } |
---|