Changeset 8b655705 in mainline for uspace/srv/devman/devman.c
- Timestamp:
- 2011-04-15T19:38:07Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 9dd730d1
- Parents:
- 6b9e85b (diff), b2fb47f (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the(diff)
links above to see all the changes relative to each parent. - File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/devman.c
r6b9e85b r8b655705 34 34 #include <fcntl.h> 35 35 #include <sys/stat.h> 36 #include <io/log.h> 36 37 #include <ipc/driver.h> 37 38 #include <ipc/devman.h> … … 41 42 #include "devman.h" 42 43 44 fun_node_t *find_node_child(fun_node_t *parent, const char *name); 45 43 46 /* hash table operations */ 44 47 … … 51 54 link_t *item) 52 55 { 53 node_t *dev = hash_table_get_instance(item, node_t, devman_link);56 dev_node_t *dev = hash_table_get_instance(item, dev_node_t, devman_dev); 54 57 return (dev->handle == (devman_handle_t) key[0]); 55 58 } 56 59 57 static int devma p_devices_compare(unsigned long key[], hash_count_t keys,60 static int devman_functions_compare(unsigned long key[], hash_count_t keys, 58 61 link_t *item) 59 62 { 60 node_t *dev = hash_table_get_instance(item, node_t, devmap_link); 61 return (dev->devmap_handle == (devmap_handle_t) key[0]); 63 fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devman_fun); 64 return (fun->handle == (devman_handle_t) key[0]); 65 } 66 67 static int devmap_functions_compare(unsigned long key[], hash_count_t keys, 68 link_t *item) 69 { 70 fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devmap_fun); 71 return (fun->devmap_handle == (devmap_handle_t) key[0]); 62 72 } 63 73 … … 82 92 }; 83 93 94 static hash_table_operations_t devman_functions_ops = { 95 .hash = devices_hash, 96 .compare = devman_functions_compare, 97 .remove_callback = devices_remove_callback 98 }; 99 84 100 static hash_table_operations_t devmap_devices_ops = { 85 101 .hash = devices_hash, 86 .compare = devmap_ devices_compare,102 .compare = devmap_functions_compare, 87 103 .remove_callback = devices_remove_callback 88 104 }; … … 131 147 fibril_mutex_unlock(&drivers_list->drivers_mutex); 132 148 133 printf(NAME": the '%s' driverwas added to the list of available "134 "drivers. \n", drv->name);149 log_msg(LVL_NOTE, "Driver `%s' was added to the list of available " 150 "drivers.", drv->name); 135 151 } 136 152 … … 222 238 bool read_match_ids(const char *conf_path, match_id_list_t *ids) 223 239 { 224 printf(NAME ": read_match_ids conf_path = %s.\n", conf_path);240 log_msg(LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path); 225 241 226 242 bool suc = false; … … 232 248 fd = open(conf_path, O_RDONLY); 233 249 if (fd < 0) { 234 printf(NAME ": unable to open %s\n", conf_path); 250 log_msg(LVL_ERROR, "Unable to open `%s' for reading: %s.", 251 conf_path, str_error(fd)); 235 252 goto cleanup; 236 253 } … … 240 257 lseek(fd, 0, SEEK_SET); 241 258 if (len == 0) { 242 printf(NAME ": configuration file '%s' is empty.\n", conf_path); 259 log_msg(LVL_ERROR, "Configuration file '%s' is empty.", 260 conf_path); 243 261 goto cleanup; 244 262 } … … 246 264 buf = malloc(len + 1); 247 265 if (buf == NULL) { 248 printf(NAME ": memory allocation failed when parsing file "249 "'%s'. \n", conf_path);266 log_msg(LVL_ERROR, "Memory allocation failed when parsing file " 267 "'%s'.", conf_path); 250 268 goto cleanup; 251 269 } 252 270 253 if (read(fd, buf, len) <= 0) { 254 printf(NAME ": unable to read file '%s'.\n", conf_path); 271 ssize_t read_bytes = safe_read(fd, buf, len); 272 if (read_bytes <= 0) { 273 log_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path); 255 274 goto cleanup; 256 275 } 257 buf[ len] = 0;276 buf[read_bytes] = 0; 258 277 259 278 suc = parse_match_ids(buf, ids); … … 290 309 bool get_driver_info(const char *base_path, const char *name, driver_t *drv) 291 310 { 292 printf(NAME ": get_driver_info base_path = %s, name = %s.\n",311 log_msg(LVL_DEBUG, "get_driver_info(base_path=\"%s\", name=\"%s\")", 293 312 base_path, name); 294 313 … … 322 341 struct stat s; 323 342 if (stat(drv->binary_path, &s) == ENOENT) { /* FIXME!! */ 324 printf(NAME ": driver not found at path %s.", drv->binary_path); 343 log_msg(LVL_ERROR, "Driver not found at path `%s'.", 344 drv->binary_path); 325 345 goto cleanup; 326 346 } … … 349 369 int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path) 350 370 { 351 printf(NAME ": lookup_available_drivers, dir = %s \n", dir_path);371 log_msg(LVL_DEBUG, "lookup_available_drivers(dir=\"%s\")", dir_path); 352 372 353 373 int drv_cnt = 0; … … 373 393 } 374 394 375 /** Create root device node in the device tree.395 /** Create root device and function node in the device tree. 376 396 * 377 397 * @param tree The device tree. 378 398 * @return True on success, false otherwise. 379 399 */ 380 bool create_root_node(dev_tree_t *tree) 381 { 382 node_t *node; 383 384 printf(NAME ": create_root_node\n"); 385 400 bool create_root_nodes(dev_tree_t *tree) 401 { 402 fun_node_t *fun; 403 dev_node_t *dev; 404 405 log_msg(LVL_DEBUG, "create_root_nodes()"); 406 386 407 fibril_rwlock_write_lock(&tree->rwlock); 387 node = create_dev_node(); 388 if (node != NULL) { 389 insert_dev_node(tree, node, clone_string(""), NULL); 390 match_id_t *id = create_match_id(); 391 id->id = clone_string("root"); 392 id->score = 100; 393 add_match_id(&node->match_ids, id); 394 tree->root_node = node; 395 } 408 409 /* 410 * Create root function. This is a pseudo function to which 411 * the root device node is attached. It allows us to match 412 * the root device driver in a standard manner, i.e. against 413 * the parent function. 414 */ 415 416 fun = create_fun_node(); 417 if (fun == NULL) { 418 fibril_rwlock_write_unlock(&tree->rwlock); 419 return false; 420 } 421 422 insert_fun_node(tree, fun, clone_string(""), NULL); 423 match_id_t *id = create_match_id(); 424 id->id = clone_string("root"); 425 id->score = 100; 426 add_match_id(&fun->match_ids, id); 427 tree->root_node = fun; 428 429 /* 430 * Create root device node. 431 */ 432 dev = create_dev_node(); 433 if (dev == NULL) { 434 fibril_rwlock_write_unlock(&tree->rwlock); 435 return false; 436 } 437 438 insert_dev_node(tree, dev, fun); 439 396 440 fibril_rwlock_write_unlock(&tree->rwlock); 397 398 return node!= NULL;441 442 return dev != NULL; 399 443 } 400 444 … … 414 458 * is found. 415 459 */ 416 driver_t *find_best_match_driver(driver_list_t *drivers_list, node_t *node)460 driver_t *find_best_match_driver(driver_list_t *drivers_list, dev_node_t *node) 417 461 { 418 462 driver_t *best_drv = NULL, *drv = NULL; … … 442 486 * @param drv The driver. 443 487 */ 444 void attach_driver( node_t *node, driver_t *drv)445 { 446 printf(NAME ": attach_driver %s to device %s\n",447 d rv->name, node->pathname);488 void attach_driver(dev_node_t *dev, driver_t *drv) 489 { 490 log_msg(LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")", 491 dev->pfun->pathname, drv->name); 448 492 449 493 fibril_mutex_lock(&drv->driver_mutex); 450 494 451 node->drv = drv;452 list_append(& node->driver_devices, &drv->devices);495 dev->drv = drv; 496 list_append(&dev->driver_devices, &drv->devices); 453 497 454 498 fibril_mutex_unlock(&drv->driver_mutex); … … 467 511 assert(fibril_mutex_is_locked(&drv->driver_mutex)); 468 512 469 printf(NAME ": start_driver '%s'\n", drv->name);513 log_msg(LVL_DEBUG, "start_driver(drv=\"%s\")", drv->name); 470 514 471 515 rc = task_spawnl(NULL, drv->binary_path, drv->binary_path, NULL); 472 516 if (rc != EOK) { 473 printf(NAME ": error spawning %s (%s)\n",474 drv->name, str_error(rc));517 log_msg(LVL_ERROR, "Spawning driver `%s' (%s) failed: %s.", 518 drv->name, drv->binary_path, str_error(rc)); 475 519 return false; 476 520 } … … 511 555 } 512 556 513 /** Remember the driver's phone.514 *515 * @param driver The driver.516 * @param phone The phone to the driver.517 */518 void set_driver_phone(driver_t *driver, sysarg_t phone)519 {520 fibril_mutex_lock(&driver->driver_mutex);521 assert(driver->state == DRIVER_STARTING);522 driver->phone = phone;523 fibril_mutex_unlock(&driver->driver_mutex);524 }525 526 557 /** Notify driver about the devices to which it was assigned. 527 558 * … … 530 561 static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree) 531 562 { 532 node_t *dev;563 dev_node_t *dev; 533 564 link_t *link; 534 565 int phone; 535 566 536 printf(NAME ": pass_devices_to_driver(`%s')\n", driver->name); 567 log_msg(LVL_DEBUG, "pass_devices_to_driver(driver=\"%s\")", 568 driver->name); 537 569 538 570 fibril_mutex_lock(&driver->driver_mutex); … … 551 583 link = driver->devices.next; 552 584 while (link != &driver->devices) { 553 dev = list_get_instance(link, node_t, driver_devices);585 dev = list_get_instance(link, dev_node_t, driver_devices); 554 586 if (dev->passed_to_driver) { 555 587 link = link->next; … … 590 622 } 591 623 592 ipc_hangup(phone);624 async_hangup(phone); 593 625 594 626 /* … … 601 633 * immediately and possibly started here as well. 602 634 */ 603 printf(NAME ": driver %s goes into running state.\n", driver->name);635 log_msg(LVL_DEBUG, "Driver `%s' enters running state.", driver->name); 604 636 driver->state = DRIVER_RUNNING; 605 637 … … 618 650 void initialize_running_driver(driver_t *driver, dev_tree_t *tree) 619 651 { 620 printf(NAME ": initialize_running_driver (`%s')\n", driver->name); 652 log_msg(LVL_DEBUG, "initialize_running_driver(driver=\"%s\")", 653 driver->name); 621 654 622 655 /* … … 639 672 list_initialize(&drv->devices); 640 673 fibril_mutex_initialize(&drv->driver_mutex); 674 drv->phone = -1; 641 675 } 642 676 … … 669 703 } 670 704 671 /** Create devmap path and name for the device. */672 static void devmap_register_tree_device(node_t *node, dev_tree_t *tree)705 /** Create devmap path and name for the function. */ 706 void devmap_register_tree_function(fun_node_t *fun, dev_tree_t *tree) 673 707 { 674 708 char *devmap_pathname = NULL; 675 709 char *devmap_name = NULL; 676 710 677 asprintf(&devmap_name, "%s", node->pathname);711 asprintf(&devmap_name, "%s", fun->pathname); 678 712 if (devmap_name == NULL) 679 713 return; … … 689 723 690 724 devmap_device_register_with_iface(devmap_pathname, 691 & node->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);692 693 tree_add_devmap_ device(tree, node);725 &fun->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP); 726 727 tree_add_devmap_function(tree, fun); 694 728 695 729 free(devmap_name); … … 702 736 * @param node The device's node in the device tree. 703 737 */ 704 void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)738 void add_device(int phone, driver_t *drv, dev_node_t *dev, dev_tree_t *tree) 705 739 { 706 740 /* … … 708 742 * access any structures that would affect driver_t. 709 743 */ 710 printf(NAME ": add_device (driver `%s', device `%s')\n", drv->name,711 node->name);744 log_msg(LVL_DEBUG, "add_device(drv=\"%s\", dev=\"%s\")", 745 drv->name, dev->pfun->name); 712 746 713 747 sysarg_t rc; … … 716 750 /* Send the device to the driver. */ 717 751 devman_handle_t parent_handle; 718 if ( node->parent) {719 parent_handle = node->parent->handle;752 if (dev->pfun) { 753 parent_handle = dev->pfun->handle; 720 754 } else { 721 755 parent_handle = 0; 722 756 } 723 757 724 aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, node->handle,758 aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, dev->handle, 725 759 parent_handle, &answer); 726 760 727 761 /* Send the device's name to the driver. */ 728 rc = async_data_write_start(phone, node->name,729 str_size( node->name) + 1);762 rc = async_data_write_start(phone, dev->pfun->name, 763 str_size(dev->pfun->name) + 1); 730 764 if (rc != EOK) { 731 765 /* TODO handle error */ … … 737 771 switch(rc) { 738 772 case EOK: 739 node->state = DEVICE_USABLE; 740 devmap_register_tree_device(node, tree); 773 dev->state = DEVICE_USABLE; 741 774 break; 742 775 case ENOENT: 743 node->state = DEVICE_NOT_PRESENT;776 dev->state = DEVICE_NOT_PRESENT; 744 777 break; 745 778 default: 746 node->state = DEVICE_INVALID;747 } 748 749 node->passed_to_driver = true;779 dev->state = DEVICE_INVALID; 780 } 781 782 dev->passed_to_driver = true; 750 783 751 784 return; … … 759 792 * successfully assigned to the device, false otherwise. 760 793 */ 761 bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree) 762 { 794 bool assign_driver(dev_node_t *dev, driver_list_t *drivers_list, 795 dev_tree_t *tree) 796 { 797 assert(dev != NULL); 798 assert(drivers_list != NULL); 799 assert(tree != NULL); 800 763 801 /* 764 802 * Find the driver which is the most suitable for handling this device. 765 803 */ 766 driver_t *drv = find_best_match_driver(drivers_list, node);804 driver_t *drv = find_best_match_driver(drivers_list, dev); 767 805 if (drv == NULL) { 768 printf(NAME ": no driver found for device '%s'.\n",769 node->pathname);806 log_msg(LVL_ERROR, "No driver found for device `%s'.", 807 dev->pfun->pathname); 770 808 return false; 771 809 } 772 810 773 811 /* Attach the driver to the device. */ 774 attach_driver( node, drv);812 attach_driver(dev, drv); 775 813 776 814 fibril_mutex_lock(&drv->driver_mutex); … … 786 824 int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0); 787 825 if (phone >= 0) { 788 add_device(phone, drv, node, tree);789 ipc_hangup(phone);826 add_device(phone, drv, dev, tree); 827 async_hangup(phone); 790 828 } 791 829 } … … 804 842 bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list) 805 843 { 806 printf(NAME ": init_device_tree.\n");844 log_msg(LVL_DEBUG, "init_device_tree()"); 807 845 808 846 tree->current_handle = 0; … … 810 848 hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1, 811 849 &devman_devices_ops); 812 hash_table_create(&tree->devmap_devices, DEVICE_BUCKETS, 1, 850 hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1, 851 &devman_functions_ops); 852 hash_table_create(&tree->devmap_functions, DEVICE_BUCKETS, 1, 813 853 &devmap_devices_ops); 814 854 815 855 fibril_rwlock_initialize(&tree->rwlock); 816 856 817 /* Create root node and add itto the device tree. */818 if (!create_root_node (tree))857 /* Create root function and root device and add them to the device tree. */ 858 if (!create_root_nodes(tree)) 819 859 return false; 820 860 821 861 /* Find suitable driver and start it. */ 822 return assign_driver(tree->root_node , drivers_list, tree);862 return assign_driver(tree->root_node->child, drivers_list, tree); 823 863 } 824 864 … … 829 869 * @return A device node structure. 830 870 */ 831 node_t *create_dev_node(void)832 { 833 node_t *res = malloc(sizeof(node_t));871 dev_node_t *create_dev_node(void) 872 { 873 dev_node_t *res = malloc(sizeof(dev_node_t)); 834 874 835 875 if (res != NULL) { 836 memset(res, 0, sizeof( node_t));837 list_initialize(&res-> children);838 li st_initialize(&res->match_ids.ids);839 li st_initialize(&res->classes);876 memset(res, 0, sizeof(dev_node_t)); 877 list_initialize(&res->functions); 878 link_initialize(&res->driver_devices); 879 link_initialize(&res->devman_dev); 840 880 } 841 881 … … 847 887 * @param node The device node structure. 848 888 */ 849 void delete_dev_node(node_t *node) 850 { 851 assert(list_empty(&node->children)); 852 assert(node->parent == NULL); 853 assert(node->drv == NULL); 854 855 clean_match_ids(&node->match_ids); 856 free_not_null(node->name); 857 free_not_null(node->pathname); 858 free(node); 889 void delete_dev_node(dev_node_t *dev) 890 { 891 assert(list_empty(&dev->functions)); 892 assert(dev->pfun == NULL); 893 assert(dev->drv == NULL); 894 895 free(dev); 859 896 } 860 897 … … 865 902 * @return The device node. 866 903 */ 867 node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)904 dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle) 868 905 { 869 906 unsigned long key = handle; … … 873 910 874 911 link = hash_table_find(&tree->devman_devices, &key); 875 return hash_table_get_instance(link, node_t, devman_link);912 return hash_table_get_instance(link, dev_node_t, devman_dev); 876 913 } 877 914 … … 882 919 * @return The device node. 883 920 */ 884 node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle)885 { 886 node_t *node= NULL;921 dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle) 922 { 923 dev_node_t *dev = NULL; 887 924 888 925 fibril_rwlock_read_lock(&tree->rwlock); 889 node= find_dev_node_no_lock(tree, handle);926 dev = find_dev_node_no_lock(tree, handle); 890 927 fibril_rwlock_read_unlock(&tree->rwlock); 891 928 892 return node; 893 } 894 929 return dev; 930 } 931 932 /* Function nodes */ 933 934 /** Create a new function node. 935 * 936 * @return A function node structure. 937 */ 938 fun_node_t *create_fun_node(void) 939 { 940 fun_node_t *res = malloc(sizeof(fun_node_t)); 941 942 if (res != NULL) { 943 memset(res, 0, sizeof(fun_node_t)); 944 link_initialize(&res->dev_functions); 945 list_initialize(&res->match_ids.ids); 946 list_initialize(&res->classes); 947 link_initialize(&res->devman_fun); 948 link_initialize(&res->devmap_fun); 949 } 950 951 return res; 952 } 953 954 /** Delete a function node. 955 * 956 * @param fun The device node structure. 957 */ 958 void delete_fun_node(fun_node_t *fun) 959 { 960 assert(fun->dev == NULL); 961 assert(fun->child == NULL); 962 963 clean_match_ids(&fun->match_ids); 964 free_not_null(fun->name); 965 free_not_null(fun->pathname); 966 free(fun); 967 } 968 969 /** Find the function node with the specified handle. 970 * 971 * @param tree The device tree where we look for the device node. 972 * @param handle The handle of the function. 973 * @return The function node. 974 */ 975 fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, devman_handle_t handle) 976 { 977 unsigned long key = handle; 978 link_t *link; 979 980 assert(fibril_rwlock_is_locked(&tree->rwlock)); 981 982 link = hash_table_find(&tree->devman_functions, &key); 983 if (link == NULL) 984 return NULL; 985 986 return hash_table_get_instance(link, fun_node_t, devman_fun); 987 } 988 989 /** Find the function node with the specified handle. 990 * 991 * @param tree The device tree where we look for the device node. 992 * @param handle The handle of the function. 993 * @return The function node. 994 */ 995 fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle) 996 { 997 fun_node_t *fun = NULL; 998 999 fibril_rwlock_read_lock(&tree->rwlock); 1000 fun = find_fun_node_no_lock(tree, handle); 1001 fibril_rwlock_read_unlock(&tree->rwlock); 1002 1003 return fun; 1004 } 895 1005 896 1006 /** Create and set device's full path in device tree. … … 901 1011 * resources etc.). 902 1012 */ 903 static bool set_ dev_path(node_t *node,node_t *parent)904 { 905 assert( node->name != NULL);906 907 size_t pathsize = (str_size( node->name) + 1);1013 static bool set_fun_path(fun_node_t *fun, fun_node_t *parent) 1014 { 1015 assert(fun->name != NULL); 1016 1017 size_t pathsize = (str_size(fun->name) + 1); 908 1018 if (parent != NULL) 909 1019 pathsize += str_size(parent->pathname) + 1; 910 1020 911 node->pathname = (char *) malloc(pathsize);912 if ( node->pathname == NULL) {913 printf(NAME ": failed to allocate device path.\n");1021 fun->pathname = (char *) malloc(pathsize); 1022 if (fun->pathname == NULL) { 1023 log_msg(LVL_ERROR, "Failed to allocate device path."); 914 1024 return false; 915 1025 } 916 1026 917 1027 if (parent != NULL) { 918 str_cpy( node->pathname, pathsize, parent->pathname);919 str_append( node->pathname, pathsize, "/");920 str_append( node->pathname, pathsize, node->name);1028 str_cpy(fun->pathname, pathsize, parent->pathname); 1029 str_append(fun->pathname, pathsize, "/"); 1030 str_append(fun->pathname, pathsize, fun->name); 921 1031 } else { 922 str_cpy( node->pathname, pathsize, node->name);1032 str_cpy(fun->pathname, pathsize, fun->name); 923 1033 } 924 1034 … … 936 1046 * etc.). 937 1047 */ 938 bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name, 939 node_t *parent) 940 { 941 assert(node != NULL); 1048 bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun) 1049 { 1050 assert(dev != NULL); 942 1051 assert(tree != NULL); 943 assert(dev_name != NULL);944 1052 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 945 1053 946 node->name = dev_name; 947 if (!set_dev_path(node, parent)) { 1054 log_msg(LVL_DEBUG, "insert_dev_node(dev=%p, pfun=%p [\"%s\"])", 1055 dev, pfun, pfun->pathname); 1056 1057 /* Add the node to the handle-to-node map. */ 1058 dev->handle = ++tree->current_handle; 1059 unsigned long key = dev->handle; 1060 hash_table_insert(&tree->devman_devices, &key, &dev->devman_dev); 1061 1062 /* Add the node to the list of its parent's children. */ 1063 dev->pfun = pfun; 1064 pfun->child = dev; 1065 1066 return true; 1067 } 1068 1069 /** Insert new function into device tree. 1070 * 1071 * @param tree The device tree. 1072 * @param node The newly added function node. 1073 * @param dev_name The name of the newly added function. 1074 * @param parent Owning device node. 1075 * 1076 * @return True on success, false otherwise (insufficient resources 1077 * etc.). 1078 */ 1079 bool insert_fun_node(dev_tree_t *tree, fun_node_t *fun, char *fun_name, 1080 dev_node_t *dev) 1081 { 1082 fun_node_t *pfun; 1083 1084 assert(fun != NULL); 1085 assert(tree != NULL); 1086 assert(fun_name != NULL); 1087 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1088 1089 /* 1090 * The root function is a special case, it does not belong to any 1091 * device so for the root function dev == NULL. 1092 */ 1093 pfun = (dev != NULL) ? dev->pfun : NULL; 1094 1095 fun->name = fun_name; 1096 if (!set_fun_path(fun, pfun)) { 948 1097 return false; 949 1098 } 950 1099 951 1100 /* Add the node to the handle-to-node map. */ 952 node->handle = ++tree->current_handle;953 unsigned long key = node->handle;954 hash_table_insert(&tree->devman_ devices, &key, &node->devman_link);1101 fun->handle = ++tree->current_handle; 1102 unsigned long key = fun->handle; 1103 hash_table_insert(&tree->devman_functions, &key, &fun->devman_fun); 955 1104 956 1105 /* Add the node to the list of its parent's children. */ 957 node->parent = parent;958 if ( parent!= NULL)959 list_append(& node->sibling, &parent->children);1106 fun->dev = dev; 1107 if (dev != NULL) 1108 list_append(&fun->dev_functions, &dev->functions); 960 1109 961 1110 return true; 962 1111 } 963 1112 964 /** Find devicenode with a specified path in the device tree.1113 /** Find function node with a specified path in the device tree. 965 1114 * 966 * @param path The path of the devicenode in the device tree.1115 * @param path The path of the function node in the device tree. 967 1116 * @param tree The device tree. 968 * @return The devicenode if it is present in the tree, NULL1117 * @return The function node if it is present in the tree, NULL 969 1118 * otherwise. 970 1119 */ 971 node_t *find_dev_node_by_path(dev_tree_t *tree, char *path) 972 { 1120 fun_node_t *find_fun_node_by_path(dev_tree_t *tree, char *path) 1121 { 1122 assert(path != NULL); 1123 1124 bool is_absolute = path[0] == '/'; 1125 if (!is_absolute) { 1126 return NULL; 1127 } 1128 973 1129 fibril_rwlock_read_lock(&tree->rwlock); 974 1130 975 node_t *dev= tree->root_node;1131 fun_node_t *fun = tree->root_node; 976 1132 /* 977 * Relative path to the devicefrom its parent (but with '/' at the1133 * Relative path to the function from its parent (but with '/' at the 978 1134 * beginning) 979 1135 */ 980 1136 char *rel_path = path; 981 1137 char *next_path_elem = NULL; 982 bool cont = (rel_path[0] == '/');983 984 while (cont && dev!= NULL) {1138 bool cont = true; 1139 1140 while (cont && fun != NULL) { 985 1141 next_path_elem = get_path_elem_end(rel_path + 1); 986 1142 if (next_path_elem[0] == '/') { … … 991 1147 } 992 1148 993 dev = find_node_child(dev, rel_path + 1);1149 fun = find_node_child(fun, rel_path + 1); 994 1150 995 1151 if (cont) { … … 1002 1158 fibril_rwlock_read_unlock(&tree->rwlock); 1003 1159 1004 return dev;1005 } 1006 1007 /** Find child device node with a specified name.1160 return fun; 1161 } 1162 1163 /** Find function with a specified name belonging to given device. 1008 1164 * 1009 1165 * Device tree rwlock should be held at least for reading. 1010 1166 * 1011 * @param parent The parent device node. 1012 * @param name The name of the child device node. 1013 * @return The child device node. 1014 */ 1015 node_t *find_node_child(node_t *parent, const char *name) 1016 { 1017 node_t *dev; 1167 * @param dev Device the function belongs to. 1168 * @param name Function name (not path). 1169 * @return Function node. 1170 * @retval NULL No function with given name. 1171 */ 1172 fun_node_t *find_fun_node_in_device(dev_node_t *dev, const char *name) 1173 { 1174 assert(dev != NULL); 1175 assert(name != NULL); 1176 1177 fun_node_t *fun; 1018 1178 link_t *link; 1019 1020 link = parent->children.next; 1021 1022 while (link != &parent->children) { 1023 dev = list_get_instance(link, node_t, sibling); 1024 1025 if (str_cmp(name, dev->name) == 0) 1026 return dev; 1027 1028 link = link->next; 1029 } 1030 1179 1180 for (link = dev->functions.next; 1181 link != &dev->functions; 1182 link = link->next) { 1183 fun = list_get_instance(link, fun_node_t, dev_functions); 1184 1185 if (str_cmp(name, fun->name) == 0) 1186 return fun; 1187 } 1188 1031 1189 return NULL; 1190 } 1191 1192 /** Find function node by its class name and index. */ 1193 fun_node_t *find_fun_node_by_class(class_list_t *class_list, 1194 const char *class_name, const char *dev_name) 1195 { 1196 assert(class_list != NULL); 1197 assert(class_name != NULL); 1198 assert(dev_name != NULL); 1199 1200 fibril_rwlock_read_lock(&class_list->rwlock); 1201 1202 dev_class_t *cl = find_dev_class_no_lock(class_list, class_name); 1203 if (cl == NULL) { 1204 fibril_rwlock_read_unlock(&class_list->rwlock); 1205 return NULL; 1206 } 1207 1208 dev_class_info_t *dev = find_dev_in_class(cl, dev_name); 1209 if (dev == NULL) { 1210 fibril_rwlock_read_unlock(&class_list->rwlock); 1211 return NULL; 1212 } 1213 1214 fun_node_t *fun = dev->fun; 1215 1216 fibril_rwlock_read_unlock(&class_list->rwlock); 1217 1218 return fun; 1219 } 1220 1221 1222 /** Find child function node with a specified name. 1223 * 1224 * Device tree rwlock should be held at least for reading. 1225 * 1226 * @param parent The parent function node. 1227 * @param name The name of the child function. 1228 * @return The child function node. 1229 */ 1230 fun_node_t *find_node_child(fun_node_t *pfun, const char *name) 1231 { 1232 return find_fun_node_in_device(pfun->child, name); 1032 1233 } 1033 1234 … … 1063 1264 if (info != NULL) { 1064 1265 memset(info, 0, sizeof(dev_class_info_t)); 1065 li st_initialize(&info->dev_classes);1066 li st_initialize(&info->devmap_link);1067 li st_initialize(&info->link);1266 link_initialize(&info->dev_classes); 1267 link_initialize(&info->devmap_link); 1268 link_initialize(&info->link); 1068 1269 } 1069 1270 … … 1107 1308 } 1108 1309 1109 /** Add the device to the class.1310 /** Add the device function to the class. 1110 1311 * 1111 1312 * The device may be added to multiple classes and a class may contain multiple … … 1120 1321 * with the class. 1121 1322 */ 1122 dev_class_info_t *add_ device_to_class(node_t *dev, dev_class_t *cl,1323 dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl, 1123 1324 const char *base_dev_name) 1124 1325 { 1125 dev_class_info_t *info = create_dev_class_info(); 1326 dev_class_info_t *info; 1327 1328 assert(fun != NULL); 1329 assert(cl != NULL); 1330 1331 info = create_dev_class_info(); 1332 1126 1333 1127 1334 if (info != NULL) { 1128 1335 info->dev_class = cl; 1129 info-> dev = dev;1336 info->fun = fun; 1130 1337 1131 1338 /* Add the device to the class. */ … … 1135 1342 1136 1343 /* Add the class to the device. */ 1137 list_append(&info->dev_classes, & dev->classes);1344 list_append(&info->dev_classes, &fun->classes); 1138 1345 1139 1346 /* Create unique name for the device within the class. */ … … 1185 1392 } 1186 1393 1394 dev_class_info_t *find_dev_in_class(dev_class_t *dev_class, const char *dev_name) 1395 { 1396 assert(dev_class != NULL); 1397 assert(dev_name != NULL); 1398 1399 link_t *link; 1400 for (link = dev_class->devices.next; 1401 link != &dev_class->devices; 1402 link = link->next) { 1403 dev_class_info_t *dev = list_get_instance(link, 1404 dev_class_info_t, link); 1405 1406 if (str_cmp(dev->dev_name, dev_name) == 0) { 1407 return dev; 1408 } 1409 } 1410 1411 return NULL; 1412 } 1413 1187 1414 void init_class_list(class_list_t *class_list) 1188 1415 { 1189 1416 list_initialize(&class_list->classes); 1190 1417 fibril_rwlock_initialize(&class_list->rwlock); 1191 hash_table_create(&class_list->devmap_ devices, DEVICE_BUCKETS, 1,1418 hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1, 1192 1419 &devmap_devices_class_ops); 1193 1420 } … … 1196 1423 /* Devmap devices */ 1197 1424 1198 node_t *find_devmap_tree_device(dev_tree_t *tree, devmap_handle_t devmap_handle)1199 { 1200 node_t *dev= NULL;1425 fun_node_t *find_devmap_tree_function(dev_tree_t *tree, devmap_handle_t devmap_handle) 1426 { 1427 fun_node_t *fun = NULL; 1201 1428 link_t *link; 1202 1429 unsigned long key = (unsigned long) devmap_handle; 1203 1430 1204 1431 fibril_rwlock_read_lock(&tree->rwlock); 1205 link = hash_table_find(&tree->devmap_ devices, &key);1432 link = hash_table_find(&tree->devmap_functions, &key); 1206 1433 if (link != NULL) 1207 dev = hash_table_get_instance(link, node_t, devmap_link);1434 fun = hash_table_get_instance(link, fun_node_t, devmap_fun); 1208 1435 fibril_rwlock_read_unlock(&tree->rwlock); 1209 1436 1210 return dev;1211 } 1212 1213 node_t *find_devmap_class_device(class_list_t *classes,1437 return fun; 1438 } 1439 1440 fun_node_t *find_devmap_class_function(class_list_t *classes, 1214 1441 devmap_handle_t devmap_handle) 1215 1442 { 1216 node_t *dev= NULL;1443 fun_node_t *fun = NULL; 1217 1444 dev_class_info_t *cli; 1218 1445 link_t *link; … … 1220 1447 1221 1448 fibril_rwlock_read_lock(&classes->rwlock); 1222 link = hash_table_find(&classes->devmap_ devices, &key);1449 link = hash_table_find(&classes->devmap_functions, &key); 1223 1450 if (link != NULL) { 1224 1451 cli = hash_table_get_instance(link, dev_class_info_t, 1225 1452 devmap_link); 1226 dev = cli->dev;1453 fun = cli->fun; 1227 1454 } 1228 1455 fibril_rwlock_read_unlock(&classes->rwlock); 1229 1456 1230 return dev;1231 } 1232 1233 void class_add_devmap_ device(class_list_t *class_list, dev_class_info_t *cli)1457 return fun; 1458 } 1459 1460 void class_add_devmap_function(class_list_t *class_list, dev_class_info_t *cli) 1234 1461 { 1235 1462 unsigned long key = (unsigned long) cli->devmap_handle; 1236 1463 1237 1464 fibril_rwlock_write_lock(&class_list->rwlock); 1238 hash_table_insert(&class_list->devmap_ devices, &key, &cli->devmap_link);1465 hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link); 1239 1466 fibril_rwlock_write_unlock(&class_list->rwlock); 1240 1467 1241 assert(find_devmap_class_ device(class_list, cli->devmap_handle) != NULL);1242 } 1243 1244 void tree_add_devmap_ device(dev_tree_t *tree, node_t *node)1245 { 1246 unsigned long key = (unsigned long) node->devmap_handle;1468 assert(find_devmap_class_function(class_list, cli->devmap_handle) != NULL); 1469 } 1470 1471 void tree_add_devmap_function(dev_tree_t *tree, fun_node_t *fun) 1472 { 1473 unsigned long key = (unsigned long) fun->devmap_handle; 1247 1474 fibril_rwlock_write_lock(&tree->rwlock); 1248 hash_table_insert(&tree->devmap_ devices, &key, &node->devmap_link);1475 hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun); 1249 1476 fibril_rwlock_write_unlock(&tree->rwlock); 1250 1477 }
Note:
See TracChangeset
for help on using the changeset viewer.