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
RevLine 
[e2b9a993]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 */
[08d9c4e6]32
[e2b9a993]33#ifndef DEVMAN_H_
34#define DEVMAN_H_
35
36#include <assert.h>
37#include <bool.h>
38#include <dirent.h>
[c47e1a8]39#include <str.h>
[e2b9a993]40#include <adt/list.h>
[957cfa58]41#include <adt/hash_table.h>
[e2b9a993]42#include <ipc/ipc.h>
[bda60d9]43#include <ipc/devman.h>
[d51ee2b]44#include <ipc/devmap.h>
[e85920d]45#include <fibril_synch.h>
[084ff99]46#include <atomic.h>
[e2b9a993]47
[08d9c4e6]48#include "util.h"
[e2b9a993]49
50#define NAME "devman"
51
52#define MATCH_EXT ".ma"
[957cfa58]53#define DEVICE_BUCKETS 256
[e2b9a993]54
[ce89036b]55#define DEVMAP_CLASS_NAMESPACE "class"
56#define DEVMAP_DEVICE_NAMESPACE "devices"
[a32defa]57#define DEVMAP_SEPARATOR '\\'
[ce89036b]58
[e2b9a993]59struct node;
60typedef struct node node_t;
61
[e85920d]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
[e2b9a993]71/** Representation of device driver.
72 */
73typedef struct driver {
74 /** Pointers to previous and next drivers in a linked list */
75 link_t drivers;
[e85920d]76 /** Specifies whether the driver has been started and wheter is running and prepared to receive requests.*/
77 int state;
[e2b9a993]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;
[e85920d]88 /** Fibril mutex for this driver - driver state, list of devices, phone.*/
89 fibril_mutex_t driver_mutex;
[e2b9a993]90} driver_t;
91
[e85920d]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
[df747b9c]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
[e2b9a993]108/** Representation of a node in the device tree.*/
109struct node {
[084ff99]110 /** The global unique identifier of the device.*/
[bda60d9]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;
[e2b9a993]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.*/
[08d9c4e6]119 link_t sibling;
[e2b9a993]120 /** List of child device nodes. */
121 link_t children;
122 /** List of device ids for device-to-driver matching.*/
[08d9c4e6]123 match_id_list_t match_ids;
[e2b9a993]124 /** Driver of this device.*/
[08d9c4e6]125 driver_t *drv;
[df747b9c]126 /** The state of the device. */
127 device_state_t state;
[e2b9a993]128 /** Pointer to the previous and next device in the list of devices
129 owned by one driver */
[08d9c4e6]130 link_t driver_devices;
[d51ee2b]131 /** The list of device classes to which this device belongs.*/
132 link_t classes;
[957cfa58]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;
[e2b9a993]139};
140
[957cfa58]141
[e2b9a993]142/** Represents device tree.
143 */
144typedef struct dev_tree {
145 /** Root device node. */
146 node_t *root_node;
[bda60d9]147 /** The next available handle - handles are assigned in a sequential manner.*/
[957cfa58]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;
[e2b9a993]155} dev_tree_t;
156
[d51ee2b]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.*/
[692c40cb]163 link_t devices;
164 /** Default base name for the device within the class, might be overrided by the driver.*/
[d51ee2b]165 const char *base_dev_name;
[692c40cb]166 /** Unique numerical identifier of the newly added device.*/
[d51ee2b]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;
[ce89036b]188 /** Link in the hash table of devices registered by the devmapper using their class names.*/
189 link_t devmap_link;
[d51ee2b]190} dev_class_info_t;
[e2b9a993]191
[692c40cb]192/** The list of device classes. */
193typedef struct class_list {
194 /** List of classes */
195 link_t classes;
[ce89036b]196 /** Hash table of devices registered by devmapper using their class name, indexed by devmap handles.*/
197 hash_table_t devmap_devices;
[692c40cb]198 /** Fibril mutex for list of classes. */
[ce89036b]199 fibril_rwlock_t rwlock;
[692c40cb]200} class_list_t;
201
[e2b9a993]202// Match ids and scores
203
204int get_match_score(driver_t *drv, node_t *dev);
205
[c47e1a8]206bool parse_match_ids(char *buf, match_id_list_t *ids);
[e2b9a993]207bool read_match_ids(const char *conf_path, match_id_list_t *ids);
[c47e1a8]208char * read_match_id(char **buf);
209char * read_id(const char **buf);
[729fa2d6]210
211// Drivers
[0c3666d]212
[d347b53]213/**
214 * Initialize the list of device driver's.
215 *
216 * @param drv_list the list of device driver's.
217 *
218 */
[0c3666d]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
[c47e1a8]227driver_t * create_driver(void);
[e2b9a993]228bool get_driver_info(const char *base_path, const char *name, driver_t *drv);
[0c3666d]229int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path);
[e2b9a993]230
[0c3666d]231driver_t * find_best_match_driver(driver_list_t *drivers_list, node_t *node);
[a32defa]232bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree);
[e2b9a993]233
[0c3666d]234void add_driver(driver_list_t *drivers_list, driver_t *drv);
[08d9c4e6]235void attach_driver(node_t *node, driver_t *drv);
[a32defa]236void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree);
[e2b9a993]237bool start_driver(driver_t *drv);
238
[729fa2d6]239driver_t * find_driver(driver_list_t *drv_list, const char *drv_name);
[c16cf62]240void set_driver_phone(driver_t *driver, ipcarg_t phone);
[a32defa]241void initialize_running_driver(driver_t *driver, dev_tree_t *tree);
[729fa2d6]242
[d347b53]243/**
244 * Initialize device driver structure.
245 *
246 * @param drv the device driver structure.
247 *
248 */
[08d9c4e6]249static inline void init_driver(driver_t *drv)
[e2b9a993]250{
[08d9c4e6]251 assert(drv != NULL);
252
253 memset(drv, 0, sizeof(driver_t));
[e2b9a993]254 list_initialize(&drv->match_ids.ids);
255 list_initialize(&drv->devices);
[924c75e1]256 fibril_mutex_initialize(&drv->driver_mutex);
[e2b9a993]257}
258
[d347b53]259/**
260 * Device driver structure clean-up.
261 *
262 * @param drv the device driver structure.
263 */
[08d9c4e6]264static inline void clean_driver(driver_t *drv)
[e2b9a993]265{
266 assert(drv != NULL);
[08d9c4e6]267
268 free_not_null(drv->name);
269 free_not_null(drv->binary_path);
270
[e2b9a993]271 clean_match_ids(&drv->match_ids);
[08d9c4e6]272
273 init_driver(drv);
[e2b9a993]274}
275
[d347b53]276/**
277 * Delete device driver structure.
278 *
279 * @param drv the device driver structure.*
280 */
[08d9c4e6]281static inline void delete_driver(driver_t *drv)
[e2b9a993]282{
[08d9c4e6]283 assert(NULL != drv);
284
[e2b9a993]285 clean_driver(drv);
286 free(drv);
287}
288
289// Device nodes
[d347b53]290/**
291 * Create a new device node.
292 *
293 * @return a device node structure.
294 *
295 */
[e2b9a993]296static inline node_t * create_dev_node()
297{
298 node_t *res = malloc(sizeof(node_t));
[692c40cb]299
[e2b9a993]300 if (res != NULL) {
[08d9c4e6]301 memset(res, 0, sizeof(node_t));
[692c40cb]302 list_initialize(&res->children);
303 list_initialize(&res->match_ids.ids);
304 list_initialize(&res->classes);
[e2b9a993]305 }
[084ff99]306
[e2b9a993]307 return res;
308}
309
[5cd136ab]310/**
311 * Delete a device node.
312 *
313 * @param node a device node structure.
314 *
315 */
[d347b53]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 *
[957cfa58]329 * Device tree's rwlock should be held at least for reading.
330 *
[d347b53]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 */
[957cfa58]335static inline node_t * find_dev_node_no_lock(dev_tree_t *tree, device_handle_t handle)
[e2b9a993]336{
[957cfa58]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;
[e2b9a993]360}
361
[5cd136ab]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
[e2b9a993]365// Device tree
366
[0c3666d]367bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list);
[084ff99]368bool create_root_node(dev_tree_t *tree);
[5cd136ab]369bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name, node_t *parent);
[e2b9a993]370
[d51ee2b]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));
[692c40cb]382 list_initialize(&cl->devices);
[d51ee2b]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
[ce89036b]413void init_class_list(class_list_t *class_list);
[692c40cb]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
[ce89036b]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
[a32defa]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
[e2b9a993]446#endif
[c16cf62]447
448/** @}
449 */
Note: See TracBrowser for help on using the repository browser.