source: mainline/uspace/srv/devman/fun.c@ 181c32f

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 181c32f was 08bc23d, checked in by Jiri Svoboda <jiri@…>, 12 years ago

Merge breaking devman.c apart.

  • Property mode set to 100644
File size: 7.1 KB
Line 
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 "devman.h"
37#include "fun.h"
38
39static fun_node_t *find_node_child(dev_tree_t *, fun_node_t *, const char *);
40
41/* Function nodes */
42
43/** Create a new function node.
44 *
45 * @return A function node structure.
46 */
47fun_node_t *create_fun_node(void)
48{
49 fun_node_t *fun;
50
51 fun = calloc(1, sizeof(fun_node_t));
52 if (fun == NULL)
53 return NULL;
54
55 fun->state = FUN_INIT;
56 atomic_set(&fun->refcnt, 0);
57 fibril_mutex_initialize(&fun->busy_lock);
58 link_initialize(&fun->dev_functions);
59 list_initialize(&fun->match_ids.ids);
60
61 return fun;
62}
63
64/** Delete a function node.
65 *
66 * @param fun The device node structure.
67 */
68void delete_fun_node(fun_node_t *fun)
69{
70 assert(fun->dev == NULL);
71 assert(fun->child == NULL);
72
73 clean_match_ids(&fun->match_ids);
74 free(fun->name);
75 free(fun->pathname);
76 free(fun);
77}
78
79/** Increase function node reference count.
80 *
81 * @param fun Function node
82 */
83void fun_add_ref(fun_node_t *fun)
84{
85 atomic_inc(&fun->refcnt);
86}
87
88/** Decrease function node reference count.
89 *
90 * When the count drops to zero the function node is freed.
91 *
92 * @param fun Function node
93 */
94void fun_del_ref(fun_node_t *fun)
95{
96 if (atomic_predec(&fun->refcnt) == 0)
97 delete_fun_node(fun);
98}
99
100/** Make function busy for reconfiguration operations. */
101void fun_busy_lock(fun_node_t *fun)
102{
103 fibril_mutex_lock(&fun->busy_lock);
104}
105
106/** Mark end of reconfiguration operation. */
107void fun_busy_unlock(fun_node_t *fun)
108{
109 fibril_mutex_unlock(&fun->busy_lock);
110}
111
112/** Find the function node with the specified handle.
113 *
114 * @param tree The device tree where we look for the device node.
115 * @param handle The handle of the function.
116 * @return The function node.
117 */
118fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, devman_handle_t handle)
119{
120 fun_node_t *fun;
121
122 assert(fibril_rwlock_is_locked(&tree->rwlock));
123
124 ht_link_t *link = hash_table_find(&tree->devman_functions, &handle);
125 if (link == NULL)
126 return NULL;
127
128 fun = hash_table_get_inst(link, fun_node_t, devman_fun);
129
130 return fun;
131}
132
133/** Find the function node with the specified handle.
134 *
135 * @param tree The device tree where we look for the device node.
136 * @param handle The handle of the function.
137 * @return The function node.
138 */
139fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle)
140{
141 fun_node_t *fun = NULL;
142
143 fibril_rwlock_read_lock(&tree->rwlock);
144
145 fun = find_fun_node_no_lock(tree, handle);
146 if (fun != NULL)
147 fun_add_ref(fun);
148
149 fibril_rwlock_read_unlock(&tree->rwlock);
150
151 return fun;
152}
153
154/** Create and set device's full path in device tree.
155 *
156 * @param tree Device tree
157 * @param node The device's device node.
158 * @param parent The parent device node.
159 * @return True on success, false otherwise (insufficient
160 * resources etc.).
161 */
162bool set_fun_path(dev_tree_t *tree, fun_node_t *fun, fun_node_t *parent)
163{
164 assert(fibril_rwlock_is_write_locked(&tree->rwlock));
165 assert(fun->name != NULL);
166
167 size_t pathsize = (str_size(fun->name) + 1);
168 if (parent != NULL)
169 pathsize += str_size(parent->pathname) + 1;
170
171 fun->pathname = (char *) malloc(pathsize);
172 if (fun->pathname == NULL) {
173 log_msg(LOG_DEFAULT, LVL_ERROR, "Failed to allocate device path.");
174 return false;
175 }
176
177 if (parent != NULL) {
178 str_cpy(fun->pathname, pathsize, parent->pathname);
179 str_append(fun->pathname, pathsize, "/");
180 str_append(fun->pathname, pathsize, fun->name);
181 } else {
182 str_cpy(fun->pathname, pathsize, fun->name);
183 }
184
185 return true;
186}
187
188/** Find function node with a specified path in the device tree.
189 *
190 * @param path The path of the function node in the device tree.
191 * @param tree The device tree.
192 * @return The function node if it is present in the tree, NULL
193 * otherwise.
194 */
195fun_node_t *find_fun_node_by_path(dev_tree_t *tree, char *path)
196{
197 assert(path != NULL);
198
199 bool is_absolute = path[0] == '/';
200 if (!is_absolute) {
201 return NULL;
202 }
203
204 fibril_rwlock_read_lock(&tree->rwlock);
205
206 fun_node_t *fun = tree->root_node;
207 fun_add_ref(fun);
208 /*
209 * Relative path to the function from its parent (but with '/' at the
210 * beginning)
211 */
212 char *rel_path = path;
213 char *next_path_elem = NULL;
214 bool cont = (rel_path[1] != '\0');
215
216 while (cont && fun != NULL) {
217 next_path_elem = get_path_elem_end(rel_path + 1);
218 if (next_path_elem[0] == '/') {
219 cont = true;
220 next_path_elem[0] = 0;
221 } else {
222 cont = false;
223 }
224
225 fun_node_t *cfun = find_node_child(tree, fun, rel_path + 1);
226 fun_del_ref(fun);
227 fun = cfun;
228
229 if (cont) {
230 /* Restore the original path. */
231 next_path_elem[0] = '/';
232 }
233 rel_path = next_path_elem;
234 }
235
236 fibril_rwlock_read_unlock(&tree->rwlock);
237
238 return fun;
239}
240
241/** Find function with a specified name belonging to given device.
242 *
243 * Device tree rwlock should be held at least for reading.
244 *
245 * @param tree Device tree
246 * @param dev Device the function belongs to.
247 * @param name Function name (not path).
248 * @return Function node.
249 * @retval NULL No function with given name.
250 */
251fun_node_t *find_fun_node_in_device(dev_tree_t *tree, dev_node_t *dev,
252 const char *name)
253{
254 assert(name != NULL);
255 assert(fibril_rwlock_is_locked(&tree->rwlock));
256
257 list_foreach(dev->functions, dev_functions, fun_node_t, fun) {
258 if (str_cmp(name, fun->name) == 0) {
259 fun_add_ref(fun);
260 return fun;
261 }
262 }
263
264 return NULL;
265}
266
267/** Find child function node with a specified name.
268 *
269 * Device tree rwlock should be held at least for reading.
270 *
271 * @param tree Device tree
272 * @param parent The parent function node.
273 * @param name The name of the child function.
274 * @return The child function node.
275 */
276static fun_node_t *find_node_child(dev_tree_t *tree, fun_node_t *pfun,
277 const char *name)
278{
279 return find_fun_node_in_device(tree, pfun->child, name);
280}
281
282/** @}
283 */
Note: See TracBrowser for help on using the repository browser.