source: mainline/uspace/srv/devman/devtree.c@ f1380b7

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since f1380b7 was a35b458, checked in by Jiří Zárevúcky <zarevucky.jiri@…>, 7 years ago

style: Remove trailing whitespace on _all_ lines, including empty ones, for particular file types.

Command used: tools/srepl '\s\+$' '' -- *.c *.h *.py *.sh *.s *.S *.ag

Currently, whitespace on empty lines is very inconsistent.
There are two basic choices: Either remove the whitespace, or keep empty lines
indented to the level of surrounding code. The former is AFAICT more common,
and also much easier to do automatically.

Alternatively, we could write script for automatic indentation, and use that
instead. However, if such a script exists, it's possible to use the indented
style locally, by having the editor apply relevant conversions on load/save,
without affecting remote repository. IMO, it makes more sense to adopt
the simpler rule.

  • Property mode set to 100644
File size: 8.4 KB
RevLine 
[59dc181]1/*
2 * Copyright (c) 2010 Lenka Trochtova
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup devman
30 * @{
31 */
32
33#include <errno.h>
34#include <io/log.h>
35
36#include "dev.h"
37#include "devtree.h"
38#include "devman.h"
39#include "driver.h"
40#include "fun.h"
41
42/* hash table operations */
43
44static inline size_t handle_key_hash(void *key)
45{
46 devman_handle_t handle = *(devman_handle_t*)key;
47 return handle;
48}
49
50static size_t devman_devices_hash(const ht_link_t *item)
51{
52 dev_node_t *dev = hash_table_get_inst(item, dev_node_t, devman_dev);
53 return handle_key_hash(&dev->handle);
54}
55
56static size_t devman_functions_hash(const ht_link_t *item)
57{
58 fun_node_t *fun = hash_table_get_inst(item, fun_node_t, devman_fun);
59 return handle_key_hash(&fun->handle);
60}
61
62static bool devman_devices_key_equal(void *key, const ht_link_t *item)
63{
64 devman_handle_t handle = *(devman_handle_t*)key;
65 dev_node_t *dev = hash_table_get_inst(item, dev_node_t, devman_dev);
66 return dev->handle == handle;
67}
68
69static bool devman_functions_key_equal(void *key, const ht_link_t *item)
70{
71 devman_handle_t handle = *(devman_handle_t*)key;
72 fun_node_t *fun = hash_table_get_inst(item, fun_node_t, devman_fun);
73 return fun->handle == handle;
74}
75
76static inline size_t service_id_key_hash(void *key)
77{
78 service_id_t service_id = *(service_id_t*)key;
79 return service_id;
80}
81
82static size_t loc_functions_hash(const ht_link_t *item)
83{
84 fun_node_t *fun = hash_table_get_inst(item, fun_node_t, loc_fun);
85 return service_id_key_hash(&fun->service_id);
86}
87
88static bool loc_functions_key_equal(void *key, const ht_link_t *item)
89{
90 service_id_t service_id = *(service_id_t*)key;
91 fun_node_t *fun = hash_table_get_inst(item, fun_node_t, loc_fun);
92 return fun->service_id == service_id;
93}
94
95
96static hash_table_ops_t devman_devices_ops = {
97 .hash = devman_devices_hash,
98 .key_hash = handle_key_hash,
99 .key_equal = devman_devices_key_equal,
100 .equal = NULL,
101 .remove_callback = NULL
102};
103
104static hash_table_ops_t devman_functions_ops = {
105 .hash = devman_functions_hash,
106 .key_hash = handle_key_hash,
107 .key_equal = devman_functions_key_equal,
108 .equal = NULL,
109 .remove_callback = NULL
110};
111
112static hash_table_ops_t loc_devices_ops = {
113 .hash = loc_functions_hash,
114 .key_hash = service_id_key_hash,
115 .key_equal = loc_functions_key_equal,
116 .equal = NULL,
117 .remove_callback = NULL
118};
119
120/** Create root device and function node in the device tree.
121 *
122 * @param tree The device tree.
123 * @return True on success, false otherwise.
124 */
125bool create_root_nodes(dev_tree_t *tree)
126{
127 fun_node_t *fun;
128 dev_node_t *dev;
[a35b458]129
[59dc181]130 log_msg(LOG_DEFAULT, LVL_DEBUG, "create_root_nodes()");
[a35b458]131
[59dc181]132 fibril_rwlock_write_lock(&tree->rwlock);
[a35b458]133
[59dc181]134 /*
135 * Create root function. This is a pseudo function to which
136 * the root device node is attached. It allows us to match
137 * the root device driver in a standard manner, i.e. against
138 * the parent function.
139 */
[a35b458]140
[59dc181]141 fun = create_fun_node();
142 if (fun == NULL) {
143 fibril_rwlock_write_unlock(&tree->rwlock);
144 return false;
145 }
[a35b458]146
[59dc181]147 fun_add_ref(fun);
148 insert_fun_node(tree, fun, str_dup(""), NULL);
[a35b458]149
[59dc181]150 match_id_t *id = create_match_id();
151 id->id = str_dup("root");
152 id->score = 100;
153 add_match_id(&fun->match_ids, id);
154 tree->root_node = fun;
[a35b458]155
[59dc181]156 /*
157 * Create root device node.
158 */
159 dev = create_dev_node();
160 if (dev == NULL) {
161 fibril_rwlock_write_unlock(&tree->rwlock);
162 return false;
163 }
[a35b458]164
[59dc181]165 dev_add_ref(dev);
166 insert_dev_node(tree, dev, fun);
[a35b458]167
[59dc181]168 fibril_rwlock_write_unlock(&tree->rwlock);
[a35b458]169
[59dc181]170 return dev != NULL;
171}
172
173/** Initialize the device tree.
174 *
175 * Create root device node of the tree and assign driver to it.
176 *
177 * @param tree The device tree.
178 * @param drivers_list the list of available drivers.
179 * @return True on success, false otherwise.
180 */
181bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list)
182{
183 log_msg(LOG_DEFAULT, LVL_DEBUG, "init_device_tree()");
[a35b458]184
[59dc181]185 tree->current_handle = 0;
[a35b458]186
[59dc181]187 hash_table_create(&tree->devman_devices, 0, 0, &devman_devices_ops);
188 hash_table_create(&tree->devman_functions, 0, 0, &devman_functions_ops);
189 hash_table_create(&tree->loc_functions, 0, 0, &loc_devices_ops);
[a35b458]190
[59dc181]191 fibril_rwlock_initialize(&tree->rwlock);
[a35b458]192
[59dc181]193 /* Create root function and root device and add them to the device tree. */
194 if (!create_root_nodes(tree))
195 return false;
[a35b458]196
[59dc181]197 /* Find suitable driver and start it. */
198 dev_node_t *rdev = tree->root_node->child;
199 dev_add_ref(rdev);
[1569a9b]200 bool rc = assign_driver(rdev, drivers_list, tree);
[59dc181]201 dev_del_ref(rdev);
[a35b458]202
[59dc181]203 return rc;
204}
205
206/** Insert new device into device tree.
207 *
208 * @param tree The device tree.
209 * @param dev The newly added device node.
210 * @param pfun The parent function node.
211 *
212 * @return True on success, false otherwise (insufficient resources
213 * etc.).
214 */
215bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun)
216{
217 assert(fibril_rwlock_is_write_locked(&tree->rwlock));
[a35b458]218
[59dc181]219 log_msg(LOG_DEFAULT, LVL_DEBUG, "insert_dev_node(dev=%p, pfun=%p [\"%s\"])",
220 dev, pfun, pfun->pathname);
221
222 /* Add the node to the handle-to-node map. */
223 dev->handle = ++tree->current_handle;
224 hash_table_insert(&tree->devman_devices, &dev->devman_dev);
225
226 /* Add the node to the list of its parent's children. */
227 dev->pfun = pfun;
228 pfun->child = dev;
[a35b458]229
[59dc181]230 return true;
231}
232
233/** Remove device from device tree.
234 *
235 * @param tree Device tree
236 * @param dev Device node
237 */
238void remove_dev_node(dev_tree_t *tree, dev_node_t *dev)
239{
240 assert(fibril_rwlock_is_write_locked(&tree->rwlock));
[a35b458]241
[59dc181]242 log_msg(LOG_DEFAULT, LVL_DEBUG, "remove_dev_node(dev=%p)", dev);
[a35b458]243
[59dc181]244 /* Remove node from the handle-to-node map. */
245 hash_table_remove(&tree->devman_devices, &dev->handle);
[a35b458]246
[59dc181]247 /* Unlink from parent function. */
248 dev->pfun->child = NULL;
249 dev->pfun = NULL;
[a35b458]250
[59dc181]251 dev->state = DEVICE_REMOVED;
252}
253
254
255/** Insert new function into device tree.
256 *
257 * @param tree The device tree.
[1b20da0]258 * @param fun The newly added function node.
[59dc181]259 * @param fun_name The name of the newly added function.
260 * @param dev Owning device node.
261 *
262 * @return True on success, false otherwise (insufficient resources
263 * etc.).
264 */
265bool insert_fun_node(dev_tree_t *tree, fun_node_t *fun, char *fun_name,
266 dev_node_t *dev)
267{
268 fun_node_t *pfun;
[a35b458]269
[59dc181]270 assert(fun_name != NULL);
271 assert(fibril_rwlock_is_write_locked(&tree->rwlock));
[a35b458]272
[59dc181]273 /*
274 * The root function is a special case, it does not belong to any
275 * device so for the root function dev == NULL.
276 */
277 pfun = (dev != NULL) ? dev->pfun : NULL;
[a35b458]278
[59dc181]279 fun->name = fun_name;
280 if (!set_fun_path(tree, fun, pfun)) {
281 return false;
282 }
[a35b458]283
[59dc181]284 /* Add the node to the handle-to-node map. */
285 fun->handle = ++tree->current_handle;
286 hash_table_insert(&tree->devman_functions, &fun->devman_fun);
287
288 /* Add the node to the list of its parent's children. */
289 fun->dev = dev;
290 if (dev != NULL)
291 list_append(&fun->dev_functions, &dev->functions);
[a35b458]292
[59dc181]293 return true;
294}
295
296/** Remove function from device tree.
297 *
298 * @param tree Device tree
299 * @param node Function node to remove
300 */
301void remove_fun_node(dev_tree_t *tree, fun_node_t *fun)
302{
303 assert(fibril_rwlock_is_write_locked(&tree->rwlock));
[a35b458]304
[59dc181]305 /* Remove the node from the handle-to-node map. */
306 hash_table_remove(&tree->devman_functions, &fun->handle);
[a35b458]307
[59dc181]308 /* Remove the node from the list of its parent's children. */
309 if (fun->dev != NULL)
310 list_remove(&fun->dev_functions);
[a35b458]311
[59dc181]312 fun->dev = NULL;
313 fun->state = FUN_REMOVED;
314}
315
316/** @}
317 */
Note: See TracBrowser for help on using the repository browser.