Changeset e2b9a993 in mainline
- Timestamp:
- 2010-02-12T15:08:16Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 08d9c4e6
- Parents:
- 85e48a9
- Location:
- uspace
- Files:
-
- 6 added
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/libc/include/ipc/services.h
r85e48a9 re2b9a993 45 45 SERVICE_VFS, 46 46 SERVICE_DEVMAP, 47 SERVICE_DEVMAN, 47 48 SERVICE_FHC, 48 49 SERVICE_OBIO, -
uspace/srv/devman/Makefile
r85e48a9 re2b9a993 34 34 35 35 SOURCES = \ 36 devman.c 36 main.c \ 37 devman.c \ 38 match.c \ 39 util.c 37 40 38 41 include ../Makefile.common -
uspace/srv/devman/devman.c
r85e48a9 re2b9a993 27 27 */ 28 28 29 /** 30 * @defgroup devman Device manager. 31 * @brief HelenOS device manager. 29 /** @addtogroup devman 32 30 * @{ 33 31 */ 34 32 35 /** @file36 */37 38 #include <assert.h>39 #include <ipc/services.h>40 #include <ipc/ns.h>41 #include <async.h>42 #include <stdio.h>43 33 #include <errno.h> 44 #include <bool.h>45 #include <fibril_synch.h>46 #include <stdlib.h>47 #include <string.h>48 #include <dirent.h>49 34 #include <fcntl.h> 50 35 #include <sys/stat.h> 51 #include <ctype.h> 52 //#include <ipc/devman.h> 53 54 #define NAME "devman" 55 56 #define DRIVER_DEFAULT_STORE "/srv/drivers" 57 #define MATCH_EXT ".ma" 58 59 #define MAX_ID_LEN 256 60 61 62 struct driver; 63 struct match_id; 64 struct match_id_list; 65 struct node; 66 struct dev_tree; 67 68 69 typedef struct driver driver_t; 70 typedef struct match_id match_id_t; 71 typedef struct match_id_list match_id_list_t; 72 typedef struct node node_t; 73 typedef struct dev_tree dev_tree_t; 74 75 76 static driver_t * create_driver(); 77 static inline void init_driver(driver_t *drv); 78 static inline void clean_driver(driver_t *drv); 79 static inline void delete_driver(driver_t *drv); 80 static inline void add_driver(driver_t *drv); 81 static char * get_abs_path(const char *base_path, const char *name, const char *ext); 82 static bool parse_match_ids(const char *buf, match_id_list_t *ids); 83 static bool read_match_ids(const char *conf_path, match_id_list_t *ids); 84 static void clean_match_ids(match_id_list_t *ids); 85 static inline match_id_t * create_match_id(); 86 static inline void delete_match_id(match_id_t *id); 87 static void add_match_id(match_id_list_t *ids, match_id_t *id); 88 static bool get_driver_info(const char *base_path, const char *name, driver_t *drv); 89 static int lookup_available_drivers(const char *dir_path); 90 static inline node_t * create_dev_node(); 91 static node_t * create_root_node(); 92 static bool init_device_tree(dev_tree_t *tree); 93 static bool devman_init(); 94 static int get_match_score(driver_t *drv, node_t *dev); 95 96 97 98 LIST_INITIALIZE(drivers_list); 99 100 101 102 /** Represents device tree. 103 */ 104 struct dev_tree { 105 node_t *root_node; 106 }; 107 108 static dev_tree_t device_tree; 109 110 /** Ids of device models used for device-to-driver matching. 111 */ 112 struct match_id { 113 /** Pointers to next and previous ids. 114 */ 115 link_t link; 116 /** Id of device model. 117 */ 118 const char *id; 119 /** Relevancy of device-to-driver match. 120 * The higher is the product of scores specified for the device by the bus driver and by the leaf driver, 121 * the more suitable is the leaf driver for handling the device. 122 */ 123 unsigned int score; 124 }; 125 126 /** List of ids for matching devices to drivers sorted 127 * according to match scores in descending order. 128 */ 129 struct match_id_list { 130 link_t ids; 131 }; 132 133 /** Representation of device driver. 134 */ 135 struct driver { 136 /** Pointers to previous and next drivers in a linked list */ 137 link_t drivers; 138 /** Specifies whether the driver has been started.*/ 139 bool running; 140 /** Phone asociated with this driver */ 141 ipcarg_t phone; 142 /** Name of the device driver */ 143 char *name; 144 /** Path to the driver's binary */ 145 const char *binary_path; 146 /** List of device ids for device-to-driver matching.*/ 147 match_id_list_t match_ids; 148 /** Pointer to the linked list of devices controlled by this driver */ 149 link_t devices; 150 }; 151 152 /** Representation of a node in the device tree.*/ 153 struct node { 154 /** The node of the parent device. */ 155 node_t *parent; 156 /** Pointers to previous and next child devices in the linked list of parent device's node.*/ 157 link_t sibling; 158 /** List of child device nodes. */ 159 link_t children; 160 /** List of device ids for device-to-driver matching.*/ 161 match_id_list_t match_ids; 162 /** Driver of this device.*/ 163 driver_t *drv; 164 /** Pointer to the previous and next device in the list of devices 165 owned by one driver */ 166 link_t driver_devices; 167 }; 168 169 static driver_t * create_driver() 36 37 #include "devman.h" 38 #include "util.h" 39 40 41 driver_t * create_driver() 170 42 { 171 43 driver_t *res = malloc(sizeof(driver_t)); … … 176 48 } 177 49 178 static inline void init_driver(driver_t *drv) 179 { 180 assert(drv != NULL); 181 182 memset(drv, 0, sizeof(driver_t)); 183 list_initialize(&drv->match_ids.ids); 184 list_initialize(&drv->devices); 185 } 186 187 static inline void clean_driver(driver_t *drv) 188 { 189 assert(drv != NULL); 190 191 free(drv->name); 192 free(drv->binary_path); 193 194 clean_match_ids(&drv->match_ids); 195 196 init_driver(drv); 197 } 198 199 static void clean_match_ids(match_id_list_t *ids) 200 { 201 link_t *link = NULL; 202 match_id_t *id; 203 204 while(!list_empty(&ids->ids)) { 205 link = ids->ids.next; 206 list_remove(link); 207 id = list_get_instance(link, match_id_t, link); 208 delete_match_id(id); 209 } 210 } 211 212 static inline match_id_t * create_match_id() 213 { 214 match_id_t *id = malloc(sizeof(match_id_t)); 215 memset(id, 0, sizeof(match_id_t)); 216 return id; 217 } 218 219 static inline void delete_match_id(match_id_t *id) 220 { 221 free(id->id); 222 free(id); 223 } 224 225 static void add_match_id(match_id_list_t *ids, match_id_t *id) 226 { 227 match_id_t *mid = NULL; 228 link_t *link = ids->ids.next; 229 230 while (link != &ids->ids) { 231 mid = list_get_instance(link, match_id_t,link); 232 if (mid->score < id->score) { 233 break; 234 } 235 link = link->next; 236 } 237 238 list_insert_before(&id->link, link); 239 } 240 241 static inline void delete_driver(driver_t *drv) 242 { 243 clean_driver(drv); 244 free(drv); 245 } 246 247 static inline void add_driver(driver_t *drv) 248 { 249 list_prepend(&drv->drivers, &drivers_list); 250 printf(NAME": the '%s' driver was added to the list of available drivers.\n", drv->name); 251 } 252 253 static char * get_abs_path(const char *base_path, const char *name, const char *ext) 254 { 255 char *res; 256 int base_len = str_size(base_path); 257 int size = base_len + str_size(name) + str_size(ext) + 3; 258 259 res = malloc(size); 260 261 if (res) { 262 str_cpy(res, size, base_path); 263 if(base_path[base_len - 1] != '/') { 264 str_append(res, size, "/"); 265 } 266 str_append(res, size, name); 267 if(ext[0] != '.') { 268 str_append(res, size, "."); 269 } 270 str_append(res, size, ext); 271 } 272 273 return res; 274 } 275 276 static inline bool skip_spaces(const char **buf) 277 { 278 while (isspace(**buf)) { 279 (*buf)++; 280 } 281 return *buf != 0; 282 } 283 284 static inline size_t get_id_len(const char *str) 285 { 286 size_t len = 0; 287 while(*str != 0 && !isspace(*str)) { 288 len++; 289 str++; 290 } 291 return len; 292 } 293 294 static char * read_id(const char **buf) 50 char * read_id(const char **buf) 295 51 { 296 52 char *res = NULL; 297 size_t len = get_ id_len(*buf);53 size_t len = get_nonspace_len(*buf); 298 54 if (len > 0) { 299 55 res = malloc(len + 1); … … 306 62 } 307 63 308 staticbool parse_match_ids(const char *buf, match_id_list_t *ids)64 bool parse_match_ids(const char *buf, match_id_list_t *ids) 309 65 { 310 66 int score = 0; … … 344 100 } 345 101 346 staticbool read_match_ids(const char *conf_path, match_id_list_t *ids)102 bool read_match_ids(const char *conf_path, match_id_list_t *ids) 347 103 { 348 104 bool suc = false; … … 392 148 393 149 394 staticbool get_driver_info(const char *base_path, const char *name, driver_t *drv)150 bool get_driver_info(const char *base_path, const char *name, driver_t *drv) 395 151 { 396 152 assert(base_path != NULL && name != NULL && drv != NULL); … … 447 203 /** Lookup drivers in the directory. 448 204 * 449 * @param dir_path the path to the directory where we search for drivers. * 205 * @param drivers_list the list of available drivers. 206 * @param dir_path the path to the directory where we search for drivers. 450 207 */ 451 static int lookup_available_drivers(const char *dir_path)208 int lookup_available_drivers(link_t *drivers_list, const char *dir_path) 452 209 { 453 210 int drv_cnt = 0; … … 460 217 while ((diren = readdir(dir))) { 461 218 if (get_driver_info(dir_path, diren->d_name, drv)) { 462 add_driver(dr v);219 add_driver(drivers_list, drv); 463 220 drv = create_driver(); 464 221 } … … 471 228 } 472 229 473 static inline node_t * create_dev_node() 474 { 475 node_t *res = malloc(sizeof(node_t)); 476 if (res != NULL) { 477 memset(res, 0, sizeof(node_t)); 478 } 479 return res; 480 } 481 482 static inline void init_dev_node(node_t *node, node_t *parent) 483 { 484 assert(NULL != node); 485 486 node->parent = parent; 487 if (NULL != parent) { 488 list_append(&node->sibling, &parent->children); 489 } 490 491 list_initialize(&node->children); 492 493 list_initialize(&node->match_ids.ids); 494 } 495 496 static node_t * create_root_node() 230 node_t * create_root_node() 497 231 { 498 232 node_t *node = create_dev_node(); … … 507 241 } 508 242 509 static int get_match_score(driver_t *drv, node_t *dev) 510 { 511 link_t* drv_head = &drv->match_ids.ids; 512 link_t* dev_head = &dev->match_ids.ids; 513 514 if (list_empty(drv_head) || list_empty(dev_head)) { 515 return 0; 516 } 517 518 link_t* drv_link = drv->match_ids.ids.next; 519 link_t* dev_link = dev->match_ids.ids.next; 520 521 match_id_t *drv_id = list_get_instance(drv_link, match_id_t, link); 522 match_id_t *dev_id = list_get_instance(dev_link, match_id_t, link); 523 524 int score_next_drv = 0; 525 int score_next_dev = 0; 526 527 do { 528 if (0 == str_cmp(drv_id->id, dev_id->id)) { // we found a match 529 // return the score of the match 530 return drv_id->score * dev_id->score; 531 } 532 533 // compute the next score we get, if we advance in the driver's list of match ids 534 if (drv_head != drv_link->next) { 535 score_next_drv = dev_id->score * list_get_instance(drv_link->next, match_id_t, link)->score; 536 } else { 537 score_next_drv = 0; 538 } 539 540 // compute the next score we get, if we advance in the device's list of match ids 541 if (dev_head != dev_link->next) { 542 score_next_dev = drv_id->score * list_get_instance(dev_link->next, match_id_t, link)->score; 543 } else { 544 score_next_dev = 0; 545 } 546 547 // advance in one of the two lists, so we get the next highest score 548 if (score_next_drv > score_next_dev) { 549 drv_link = drv_link->next; 550 drv_id = list_get_instance(drv_link, match_id_t, link); 551 } else { 552 dev_link = dev_link->next; 553 dev_id = list_get_instance(dev_link, match_id_t, link); 554 } 555 556 } while (drv_head != drv_link->next && dev_head != dev_link->next); 557 558 return 0; 559 } 560 561 static driver_t * find_best_match_driver(node_t *node) 243 driver_t * find_best_match_driver(link_t *drivers_list, node_t *node) 562 244 { 563 245 driver_t *best_drv = NULL, *drv = NULL; 564 246 int best_score = 0, score = 0; 565 link_t *link = drivers_list .next;566 567 while (link != &drivers_list) {247 link_t *link = drivers_list->next; 248 249 while (link != drivers_list) { 568 250 drv = list_get_instance(link, driver_t, drivers); 569 251 score = get_match_score(drv, node); … … 577 259 } 578 260 579 staticvoid attach_driver(node_t *node, driver_t *drv)261 void attach_driver(node_t *node, driver_t *drv) 580 262 { 581 263 node->drv = drv; … … 583 265 } 584 266 585 staticbool start_driver(driver_t *drv)267 bool start_driver(driver_t *drv) 586 268 { 587 269 char *argv[2]; … … 600 282 } 601 283 602 staticbool add_device(driver_t *drv, node_t *node)284 bool add_device(driver_t *drv, node_t *node) 603 285 { 604 286 // TODO … … 612 294 } 613 295 614 static bool assign_driver(node_t *node)296 bool assign_driver(node_t *node, link_t *drivers_list) 615 297 { 616 298 // find the driver which is the most suitable for handling this device 617 driver_t *drv = find_best_match_driver( node);299 driver_t *drv = find_best_match_driver(drivers_list, node); 618 300 if (NULL == drv) { 619 301 return false; … … 634 316 } 635 317 636 static bool init_device_tree(dev_tree_t *tree)318 bool init_device_tree(dev_tree_t *tree, link_t *drivers_list) 637 319 { 638 320 // create root node and add it to the device tree … … 642 324 643 325 // find suitable driver and start it 644 return assign_driver(tree->root_node); 645 } 646 647 /** Initialize device manager internal structures. 648 */ 649 static bool devman_init() 650 { 651 // initialize list of available drivers 652 if (0 == lookup_available_drivers(DRIVER_DEFAULT_STORE)) { 653 printf(NAME " no drivers found."); 654 return false; 655 } 656 657 // create root device node 658 if (!init_device_tree(&device_tree)) { 659 printf(NAME " failed to initialize device tree."); 660 return false; 661 } 662 663 return true; 664 } 665 666 667 /** Function for handling connections to device manager. 668 * 669 */ 670 static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall) 671 { 672 /* Select interface */ 673 switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) { 674 /*case DEVMAN_DRIVER: 675 devmap_connection_driver(iid, icall); 676 break;*/ 677 678 default: 679 /* No such interface */ 680 ipc_answer_0(iid, ENOENT); 681 } 682 } 683 684 /** 685 * 686 */ 687 int main(int argc, char *argv[]) 688 { 689 printf(NAME ": HelenOS Device Manager\n"); 690 691 if (!devman_init()) { 692 printf(NAME ": Error while initializing service\n"); 693 return -1; 694 } 695 696 /* 697 // Set a handler of incomming connections 698 async_set_client_connection(devman_connection); 699 700 // Register device manager at naming service 701 ipcarg_t phonead; 702 if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAN, 0, 0, &phonead) != 0) 703 return -1; 704 705 printf(NAME ": Accepting connections\n"); 706 async_manager();*/ 707 708 // Never reached 709 return 0; 710 } 326 return assign_driver(tree->root_node, drivers_list); 327 } 328
Note:
See TracChangeset
for help on using the changeset viewer.