source: mainline/uspace/srv/devman/devman.h@ a32defa

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since a32defa was a32defa, checked in by Lenka Trochtova <trochtova.lenka@…>, 15 years ago

Register devices in the device tree by the device mapper so the device hierarchy can be seen from devfs.

  • Property mode set to 100644
File size: 13.0 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#ifndef DEVMAN_H_
34#define DEVMAN_H_
35
36#include <assert.h>
37#include <bool.h>
38#include <dirent.h>
39#include <str.h>
40#include <adt/list.h>
41#include <adt/hash_table.h>
42#include <ipc/ipc.h>
43#include <ipc/devman.h>
44#include <ipc/devmap.h>
45#include <fibril_synch.h>
46#include <atomic.h>
47
48#include "util.h"
49
50#define NAME "devman"
51
52#define MATCH_EXT ".ma"
53#define DEVICE_BUCKETS 256
54
55#define DEVMAP_CLASS_NAMESPACE "class"
56#define DEVMAP_DEVICE_NAMESPACE "devices"
57#define DEVMAP_SEPARATOR '\\'
58
59struct node;
60typedef struct node node_t;
61
62typedef enum {
63 /** driver has not been started */
64 DRIVER_NOT_STARTED = 0,
65 /** driver has been started, but has not registered as running and ready to receive requests */
66 DRIVER_STARTING,
67 /** driver is running and prepared to serve incomming requests */
68 DRIVER_RUNNING
69} driver_state_t;
70
71/** Representation of device driver.
72 */
73typedef struct driver {
74 /** Pointers to previous and next drivers in a linked list */
75 link_t drivers;
76 /** Specifies whether the driver has been started and wheter is running and prepared to receive requests.*/
77 int state;
78 /** Phone asociated with this driver */
79 ipcarg_t phone;
80 /** Name of the device driver */
81 char *name;
82 /** Path to the driver's binary */
83 const char *binary_path;
84 /** List of device ids for device-to-driver matching.*/
85 match_id_list_t match_ids;
86 /** Pointer to the linked list of devices controlled by this driver */
87 link_t devices;
88 /** Fibril mutex for this driver - driver state, list of devices, phone.*/
89 fibril_mutex_t driver_mutex;
90} driver_t;
91
92/** The list of drivers. */
93typedef struct driver_list {
94 /** List of drivers */
95 link_t drivers;
96 /** Fibril mutex for list of drivers. */
97 fibril_mutex_t drivers_mutex;
98} driver_list_t;
99
100/** The state of the device. */
101typedef enum {
102 DEVICE_NOT_INITIALIZED = 0,
103 DEVICE_USABLE,
104 DEVICE_NOT_PRESENT,
105 DEVICE_INVALID
106} device_state_t;
107
108/** Representation of a node in the device tree.*/
109struct node {
110 /** The global unique identifier of the device.*/
111 device_handle_t handle;
112 /** The name of the device specified by its parent. */
113 char *name;
114 /** Full path and name of the device in device hierarchi (i. e. in full path in device tree).*/
115 char *pathname;
116 /** The node of the parent device. */
117 node_t *parent;
118 /** Pointers to previous and next child devices in the linked list of parent device's node.*/
119 link_t sibling;
120 /** List of child device nodes. */
121 link_t children;
122 /** List of device ids for device-to-driver matching.*/
123 match_id_list_t match_ids;
124 /** Driver of this device.*/
125 driver_t *drv;
126 /** The state of the device. */
127 device_state_t state;
128 /** Pointer to the previous and next device in the list of devices
129 owned by one driver */
130 link_t driver_devices;
131 /** The list of device classes to which this device belongs.*/
132 link_t classes;
133 /** Devmap handle if the device is registered by devmapper. */
134 dev_handle_t devmap_handle;
135 /** Used by the hash table of devices indexed by devman device handles.*/
136 link_t devman_link;
137 /** Used by the hash table of devices indexed by devmap device handles.*/
138 link_t devmap_link;
139};
140
141
142/** Represents device tree.
143 */
144typedef struct dev_tree {
145 /** Root device node. */
146 node_t *root_node;
147 /** The next available handle - handles are assigned in a sequential manner.*/
148 device_handle_t current_handle;
149 /** Synchronize access to the device tree.*/
150 fibril_rwlock_t rwlock;
151 /** Hash table of all devices indexed by devman handles.*/
152 hash_table_t devman_devices;
153 /** Hash table of devices registered by devmapper, indexed by devmap handles.*/
154 hash_table_t devmap_devices;
155} dev_tree_t;
156
157typedef struct dev_class {
158 /** The name of the class.*/
159 const char *name;
160 /** Pointer to the previous and next class in the list of registered classes.*/
161 link_t link;
162 /** List of dev_class_info structures - one for each device registered by this class.*/
163 link_t devices;
164 /** Default base name for the device within the class, might be overrided by the driver.*/
165 const char *base_dev_name;
166 /** Unique numerical identifier of the newly added device.*/
167 size_t curr_dev_idx;
168 /** Synchronize access to the list of devices in this class. */
169 fibril_mutex_t mutex;
170} dev_class_t;
171
172/** Provides n-to-m mapping between device nodes and classes
173 * - each device may be register to the arbitrary number of classes
174 * and each class may contain the arbitrary number of devices. */
175typedef struct dev_class_info {
176 /** The class.*/
177 dev_class_t *dev_class;
178 /** The device.*/
179 node_t *dev;
180 /** Pointer to the previous and next class info in the list of devices registered by the class.*/
181 link_t link;
182 /** Pointer to the previous and next class info in the list of classes by which the device is registered.*/
183 link_t dev_classes;
184 /** The name of the device within the class.*/
185 char *dev_name;
186 /** The handle of the device by device mapper in the class namespace.*/
187 dev_handle_t devmap_handle;
188 /** Link in the hash table of devices registered by the devmapper using their class names.*/
189 link_t devmap_link;
190} dev_class_info_t;
191
192/** The list of device classes. */
193typedef struct class_list {
194 /** List of classes */
195 link_t classes;
196 /** Hash table of devices registered by devmapper using their class name, indexed by devmap handles.*/
197 hash_table_t devmap_devices;
198 /** Fibril mutex for list of classes. */
199 fibril_rwlock_t rwlock;
200} class_list_t;
201
202// Match ids and scores
203
204int get_match_score(driver_t *drv, node_t *dev);
205
206bool parse_match_ids(char *buf, match_id_list_t *ids);
207bool read_match_ids(const char *conf_path, match_id_list_t *ids);
208char * read_match_id(char **buf);
209char * read_id(const char **buf);
210
211// Drivers
212
213/**
214 * Initialize the list of device driver's.
215 *
216 * @param drv_list the list of device driver's.
217 *
218 */
219static inline void init_driver_list(driver_list_t *drv_list)
220{
221 assert(NULL != drv_list);
222
223 list_initialize(&drv_list->drivers);
224 fibril_mutex_initialize(&drv_list->drivers_mutex);
225}
226
227driver_t * create_driver(void);
228bool get_driver_info(const char *base_path, const char *name, driver_t *drv);
229int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path);
230
231driver_t * find_best_match_driver(driver_list_t *drivers_list, node_t *node);
232bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree);
233
234void add_driver(driver_list_t *drivers_list, driver_t *drv);
235void attach_driver(node_t *node, driver_t *drv);
236void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree);
237bool start_driver(driver_t *drv);
238
239driver_t * find_driver(driver_list_t *drv_list, const char *drv_name);
240void set_driver_phone(driver_t *driver, ipcarg_t phone);
241void initialize_running_driver(driver_t *driver, dev_tree_t *tree);
242
243/**
244 * Initialize device driver structure.
245 *
246 * @param drv the device driver structure.
247 *
248 */
249static inline void init_driver(driver_t *drv)
250{
251 assert(drv != NULL);
252
253 memset(drv, 0, sizeof(driver_t));
254 list_initialize(&drv->match_ids.ids);
255 list_initialize(&drv->devices);
256 fibril_mutex_initialize(&drv->driver_mutex);
257}
258
259/**
260 * Device driver structure clean-up.
261 *
262 * @param drv the device driver structure.
263 */
264static inline void clean_driver(driver_t *drv)
265{
266 assert(drv != NULL);
267
268 free_not_null(drv->name);
269 free_not_null(drv->binary_path);
270
271 clean_match_ids(&drv->match_ids);
272
273 init_driver(drv);
274}
275
276/**
277 * Delete device driver structure.
278 *
279 * @param drv the device driver structure.*
280 */
281static inline void delete_driver(driver_t *drv)
282{
283 assert(NULL != drv);
284
285 clean_driver(drv);
286 free(drv);
287}
288
289// Device nodes
290/**
291 * Create a new device node.
292 *
293 * @return a device node structure.
294 *
295 */
296static inline node_t * create_dev_node()
297{
298 node_t *res = malloc(sizeof(node_t));
299
300 if (res != NULL) {
301 memset(res, 0, sizeof(node_t));
302 list_initialize(&res->children);
303 list_initialize(&res->match_ids.ids);
304 list_initialize(&res->classes);
305 }
306
307 return res;
308}
309
310/**
311 * Delete a device node.
312 *
313 * @param node a device node structure.
314 *
315 */
316static inline void delete_dev_node(node_t *node)
317{
318 assert(list_empty(&node->children) && NULL == node->parent && NULL == node->drv);
319
320 clean_match_ids(&node->match_ids);
321 free_not_null(node->name);
322 free_not_null(node->pathname);
323 free(node);
324}
325
326/**
327 * Find the device node structure of the device witch has the specified handle.
328 *
329 * Device tree's rwlock should be held at least for reading.
330 *
331 * @param tree the device tree where we look for the device node.
332 * @param handle the handle of the device.
333 * @return the device node.
334 */
335static inline node_t * find_dev_node_no_lock(dev_tree_t *tree, device_handle_t handle)
336{
337 unsigned long key = handle;
338 link_t *link = hash_table_find(&tree->devman_devices, &key);
339 return hash_table_get_instance(link, node_t, devman_link);
340}
341
342/**
343 * Find the device node structure of the device witch has the specified handle.
344 *
345 * @param tree the device tree where we look for the device node.
346 * @param handle the handle of the device.
347 * @return the device node.
348 */
349static inline node_t * find_dev_node(dev_tree_t *tree, device_handle_t handle)
350{
351 node_t *node = NULL;
352
353 fibril_rwlock_read_lock(&tree->rwlock);
354
355 node = find_dev_node_no_lock(tree, handle);
356
357 fibril_rwlock_read_unlock(&tree->rwlock);
358
359 return node;
360}
361
362node_t * find_dev_node_by_path(dev_tree_t *tree, char *path);
363node_t *find_node_child(node_t *parent, const char *name);
364
365// Device tree
366
367bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list);
368bool create_root_node(dev_tree_t *tree);
369bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name, node_t *parent);
370
371// Device classes
372
373/** Create device class.
374 *
375 * @return device class.
376 */
377static inline dev_class_t * create_dev_class()
378{
379 dev_class_t *cl = (dev_class_t *)malloc(sizeof(dev_class_t));
380 if (NULL != cl) {
381 memset(cl, 0, sizeof(dev_class_t));
382 list_initialize(&cl->devices);
383 fibril_mutex_initialize(&cl->mutex);
384 }
385 return cl;
386}
387
388/** Create device class info.
389 *
390 * @return device class info.
391 */
392static inline dev_class_info_t * create_dev_class_info()
393{
394 dev_class_info_t *info = (dev_class_info_t *)malloc(sizeof(dev_class_info_t));
395 if (NULL != info) {
396 memset(info, 0, sizeof(dev_class_info_t));
397 }
398 return info;
399}
400
401static inline size_t get_new_class_dev_idx(dev_class_t *cl)
402{
403 size_t dev_idx;
404 fibril_mutex_lock(&cl->mutex);
405 dev_idx = ++cl->curr_dev_idx;
406 fibril_mutex_unlock(&cl->mutex);
407 return dev_idx;
408}
409
410char * create_dev_name_for_class(dev_class_t *cl, const char *base_dev_name);
411dev_class_info_t * add_device_to_class(node_t *dev, dev_class_t *cl, const char *base_dev_name);
412
413void init_class_list(class_list_t *class_list);
414
415dev_class_t * get_dev_class(class_list_t *class_list, char *class_name);
416dev_class_t * find_dev_class_no_lock(class_list_t *class_list, const char *class_name);
417
418static inline void add_dev_class_no_lock(class_list_t *class_list, dev_class_t *cl)
419{
420 list_append(&cl->link, &class_list->classes);
421}
422
423
424// devmap devices
425
426node_t *find_devmap_tree_device(dev_tree_t *tree, dev_handle_t devmap_handle);
427node_t *find_devmap_class_device(class_list_t *classes, dev_handle_t devmap_handle);
428
429
430static inline void class_add_devmap_device(class_list_t *class_list, dev_class_info_t *cli)
431{
432 unsigned long key = (unsigned long)cli->devmap_handle;
433 fibril_rwlock_write_lock(&class_list->rwlock);
434 hash_table_insert(&class_list->devmap_devices, &key, &cli->devmap_link);
435 fibril_rwlock_write_unlock(&class_list->rwlock);
436}
437
438static inline void tree_add_devmap_device(dev_tree_t *tree, node_t *node)
439{
440 unsigned long key = (unsigned long)node->devmap_handle;
441 fibril_rwlock_write_lock(&tree->rwlock);
442 hash_table_insert(&tree->devmap_devices, &key, &node->devmap_link);
443 fibril_rwlock_write_unlock(&tree->rwlock);
444}
445
446#endif
447
448/** @}
449 */
Note: See TracBrowser for help on using the repository browser.