Changeset eb1a2f4 in mainline for uspace/srv
- Timestamp:
- 2011-02-22T23:30:56Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 3b5d1535, a9c674e0
- Parents:
- dbe25f1 (diff), 664af708 (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. - Location:
- uspace/srv
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/devman.c
rdbe25f1 reb1a2f4 41 41 #include "devman.h" 42 42 43 fun_node_t *find_node_child(fun_node_t *parent, const char *name); 44 43 45 /* hash table operations */ 44 46 … … 51 53 link_t *item) 52 54 { 53 node_t *dev = hash_table_get_instance(item, node_t, devman_link);55 dev_node_t *dev = hash_table_get_instance(item, dev_node_t, devman_dev); 54 56 return (dev->handle == (devman_handle_t) key[0]); 55 57 } 56 58 57 static int devma p_devices_compare(unsigned long key[], hash_count_t keys,59 static int devman_functions_compare(unsigned long key[], hash_count_t keys, 58 60 link_t *item) 59 61 { 60 node_t *dev = hash_table_get_instance(item, node_t, devmap_link); 61 return (dev->devmap_handle == (devmap_handle_t) key[0]); 62 fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devman_fun); 63 return (fun->handle == (devman_handle_t) key[0]); 64 } 65 66 static int devmap_functions_compare(unsigned long key[], hash_count_t keys, 67 link_t *item) 68 { 69 fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devmap_fun); 70 return (fun->devmap_handle == (devmap_handle_t) key[0]); 62 71 } 63 72 … … 82 91 }; 83 92 93 static hash_table_operations_t devman_functions_ops = { 94 .hash = devices_hash, 95 .compare = devman_functions_compare, 96 .remove_callback = devices_remove_callback 97 }; 98 84 99 static hash_table_operations_t devmap_devices_ops = { 85 100 .hash = devices_hash, 86 .compare = devmap_ devices_compare,101 .compare = devmap_functions_compare, 87 102 .remove_callback = devices_remove_callback 88 103 }; … … 381 396 } 382 397 383 /** Create root device node in the device tree.398 /** Create root device and function node in the device tree. 384 399 * 385 400 * @param tree The device tree. 386 401 * @return True on success, false otherwise. 387 402 */ 388 bool create_root_node(dev_tree_t *tree) 389 { 390 node_t *node; 391 392 printf(NAME ": create_root_node\n"); 393 403 bool create_root_nodes(dev_tree_t *tree) 404 { 405 fun_node_t *fun; 406 dev_node_t *dev; 407 408 printf(NAME ": create_root_nodes\n"); 409 394 410 fibril_rwlock_write_lock(&tree->rwlock); 395 node = create_dev_node(); 396 if (node != NULL) { 397 insert_dev_node(tree, node, clone_string(""), NULL); 398 match_id_t *id = create_match_id(); 399 id->id = clone_string("root"); 400 id->score = 100; 401 add_match_id(&node->match_ids, id); 402 tree->root_node = node; 403 } 411 412 /* 413 * Create root function. This is a pseudo function to which 414 * the root device node is attached. It allows us to match 415 * the root device driver in a standard manner, i.e. against 416 * the parent function. 417 */ 418 419 fun = create_fun_node(); 420 if (fun == NULL) { 421 fibril_rwlock_write_unlock(&tree->rwlock); 422 return false; 423 } 424 425 insert_fun_node(tree, fun, clone_string(""), NULL); 426 match_id_t *id = create_match_id(); 427 id->id = clone_string("root"); 428 id->score = 100; 429 add_match_id(&fun->match_ids, id); 430 tree->root_node = fun; 431 432 /* 433 * Create root device node. 434 */ 435 dev = create_dev_node(); 436 if (dev == NULL) { 437 fibril_rwlock_write_unlock(&tree->rwlock); 438 return false; 439 } 440 441 insert_dev_node(tree, dev, fun); 442 404 443 fibril_rwlock_write_unlock(&tree->rwlock); 405 406 return node!= NULL;444 445 return dev != NULL; 407 446 } 408 447 … … 422 461 * is found. 423 462 */ 424 driver_t *find_best_match_driver(driver_list_t *drivers_list, node_t *node)463 driver_t *find_best_match_driver(driver_list_t *drivers_list, dev_node_t *node) 425 464 { 426 465 driver_t *best_drv = NULL, *drv = NULL; … … 450 489 * @param drv The driver. 451 490 */ 452 void attach_driver( node_t *node, driver_t *drv)491 void attach_driver(dev_node_t *dev, driver_t *drv) 453 492 { 454 493 printf(NAME ": attach_driver %s to device %s\n", 455 drv->name, node->pathname);494 drv->name, dev->pfun->pathname); 456 495 457 496 fibril_mutex_lock(&drv->driver_mutex); 458 497 459 node->drv = drv;460 list_append(& node->driver_devices, &drv->devices);498 dev->drv = drv; 499 list_append(&dev->driver_devices, &drv->devices); 461 500 462 501 fibril_mutex_unlock(&drv->driver_mutex); … … 538 577 static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree) 539 578 { 540 node_t *dev;579 dev_node_t *dev; 541 580 link_t *link; 542 581 int phone; … … 559 598 link = driver->devices.next; 560 599 while (link != &driver->devices) { 561 dev = list_get_instance(link, node_t, driver_devices);600 dev = list_get_instance(link, dev_node_t, driver_devices); 562 601 if (dev->passed_to_driver) { 563 602 link = link->next; … … 677 716 } 678 717 679 /** Create devmap path and name for the device. */680 static void devmap_register_tree_device(node_t *node, dev_tree_t *tree)718 /** Create devmap path and name for the function. */ 719 void devmap_register_tree_function(fun_node_t *fun, dev_tree_t *tree) 681 720 { 682 721 char *devmap_pathname = NULL; 683 722 char *devmap_name = NULL; 684 723 685 asprintf(&devmap_name, "%s", node->pathname);724 asprintf(&devmap_name, "%s", fun->pathname); 686 725 if (devmap_name == NULL) 687 726 return; … … 697 736 698 737 devmap_device_register_with_iface(devmap_pathname, 699 & node->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);700 701 tree_add_devmap_ device(tree, node);738 &fun->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP); 739 740 tree_add_devmap_function(tree, fun); 702 741 703 742 free(devmap_name); … … 710 749 * @param node The device's node in the device tree. 711 750 */ 712 void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree)751 void add_device(int phone, driver_t *drv, dev_node_t *dev, dev_tree_t *tree) 713 752 { 714 753 /* … … 717 756 */ 718 757 printf(NAME ": add_device (driver `%s', device `%s')\n", drv->name, 719 node->name);758 dev->pfun->name); 720 759 721 760 sysarg_t rc; … … 724 763 /* Send the device to the driver. */ 725 764 devman_handle_t parent_handle; 726 if ( node->parent) {727 parent_handle = node->parent->handle;765 if (dev->pfun) { 766 parent_handle = dev->pfun->handle; 728 767 } else { 729 768 parent_handle = 0; 730 769 } 731 770 732 aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, node->handle,771 aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, dev->handle, 733 772 parent_handle, &answer); 734 773 735 774 /* Send the device's name to the driver. */ 736 rc = async_data_write_start(phone, node->name,737 str_size( node->name) + 1);775 rc = async_data_write_start(phone, dev->pfun->name, 776 str_size(dev->pfun->name) + 1); 738 777 if (rc != EOK) { 739 778 /* TODO handle error */ … … 745 784 switch(rc) { 746 785 case EOK: 747 node->state = DEVICE_USABLE; 748 devmap_register_tree_device(node, tree); 786 dev->state = DEVICE_USABLE; 749 787 break; 750 788 case ENOENT: 751 node->state = DEVICE_NOT_PRESENT;789 dev->state = DEVICE_NOT_PRESENT; 752 790 break; 753 791 default: 754 node->state = DEVICE_INVALID;755 } 756 757 node->passed_to_driver = true;792 dev->state = DEVICE_INVALID; 793 } 794 795 dev->passed_to_driver = true; 758 796 759 797 return; … … 767 805 * successfully assigned to the device, false otherwise. 768 806 */ 769 bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree) 770 { 807 bool assign_driver(dev_node_t *dev, driver_list_t *drivers_list, 808 dev_tree_t *tree) 809 { 810 assert(dev != NULL); 811 assert(drivers_list != NULL); 812 assert(tree != NULL); 813 771 814 /* 772 815 * Find the driver which is the most suitable for handling this device. 773 816 */ 774 driver_t *drv = find_best_match_driver(drivers_list, node);817 driver_t *drv = find_best_match_driver(drivers_list, dev); 775 818 if (drv == NULL) { 776 819 printf(NAME ": no driver found for device '%s'.\n", 777 node->pathname);820 dev->pfun->pathname); 778 821 return false; 779 822 } 780 823 781 824 /* Attach the driver to the device. */ 782 attach_driver( node, drv);825 attach_driver(dev, drv); 783 826 784 827 fibril_mutex_lock(&drv->driver_mutex); … … 794 837 int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0); 795 838 if (phone >= 0) { 796 add_device(phone, drv, node, tree);839 add_device(phone, drv, dev, tree); 797 840 async_hangup(phone); 798 841 } … … 818 861 hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1, 819 862 &devman_devices_ops); 820 hash_table_create(&tree->devmap_devices, DEVICE_BUCKETS, 1, 863 hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1, 864 &devman_functions_ops); 865 hash_table_create(&tree->devmap_functions, DEVICE_BUCKETS, 1, 821 866 &devmap_devices_ops); 822 867 823 868 fibril_rwlock_initialize(&tree->rwlock); 824 869 825 /* Create root node and add itto the device tree. */826 if (!create_root_node (tree))870 /* Create root function and root device and add them to the device tree. */ 871 if (!create_root_nodes(tree)) 827 872 return false; 828 873 829 874 /* Find suitable driver and start it. */ 830 return assign_driver(tree->root_node , drivers_list, tree);875 return assign_driver(tree->root_node->child, drivers_list, tree); 831 876 } 832 877 … … 837 882 * @return A device node structure. 838 883 */ 839 node_t *create_dev_node(void)840 { 841 node_t *res = malloc(sizeof(node_t));884 dev_node_t *create_dev_node(void) 885 { 886 dev_node_t *res = malloc(sizeof(dev_node_t)); 842 887 843 888 if (res != NULL) { 844 memset(res, 0, sizeof( node_t));845 list_initialize(&res-> children);846 li st_initialize(&res->match_ids.ids);847 li st_initialize(&res->classes);889 memset(res, 0, sizeof(dev_node_t)); 890 list_initialize(&res->functions); 891 link_initialize(&res->driver_devices); 892 link_initialize(&res->devman_dev); 848 893 } 849 894 … … 855 900 * @param node The device node structure. 856 901 */ 857 void delete_dev_node(node_t *node) 858 { 859 assert(list_empty(&node->children)); 860 assert(node->parent == NULL); 861 assert(node->drv == NULL); 862 863 clean_match_ids(&node->match_ids); 864 free_not_null(node->name); 865 free_not_null(node->pathname); 866 free(node); 902 void delete_dev_node(dev_node_t *dev) 903 { 904 assert(list_empty(&dev->functions)); 905 assert(dev->pfun == NULL); 906 assert(dev->drv == NULL); 907 908 free(dev); 867 909 } 868 910 … … 873 915 * @return The device node. 874 916 */ 875 node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle)917 dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle) 876 918 { 877 919 unsigned long key = handle; … … 881 923 882 924 link = hash_table_find(&tree->devman_devices, &key); 883 return hash_table_get_instance(link, node_t, devman_link);925 return hash_table_get_instance(link, dev_node_t, devman_dev); 884 926 } 885 927 … … 890 932 * @return The device node. 891 933 */ 892 node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle)893 { 894 node_t *node= NULL;934 dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle) 935 { 936 dev_node_t *dev = NULL; 895 937 896 938 fibril_rwlock_read_lock(&tree->rwlock); 897 node= find_dev_node_no_lock(tree, handle);939 dev = find_dev_node_no_lock(tree, handle); 898 940 fibril_rwlock_read_unlock(&tree->rwlock); 899 941 900 return node; 901 } 902 942 return dev; 943 } 944 945 /* Function nodes */ 946 947 /** Create a new function node. 948 * 949 * @return A function node structure. 950 */ 951 fun_node_t *create_fun_node(void) 952 { 953 fun_node_t *res = malloc(sizeof(fun_node_t)); 954 955 if (res != NULL) { 956 memset(res, 0, sizeof(fun_node_t)); 957 link_initialize(&res->dev_functions); 958 list_initialize(&res->match_ids.ids); 959 list_initialize(&res->classes); 960 link_initialize(&res->devman_fun); 961 link_initialize(&res->devmap_fun); 962 } 963 964 return res; 965 } 966 967 /** Delete a function node. 968 * 969 * @param fun The device node structure. 970 */ 971 void delete_fun_node(fun_node_t *fun) 972 { 973 assert(fun->dev == NULL); 974 assert(fun->child == NULL); 975 976 clean_match_ids(&fun->match_ids); 977 free_not_null(fun->name); 978 free_not_null(fun->pathname); 979 free(fun); 980 } 981 982 /** Find the function node with the specified handle. 983 * 984 * @param tree The device tree where we look for the device node. 985 * @param handle The handle of the function. 986 * @return The function node. 987 */ 988 fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, devman_handle_t handle) 989 { 990 unsigned long key = handle; 991 link_t *link; 992 993 assert(fibril_rwlock_is_locked(&tree->rwlock)); 994 995 link = hash_table_find(&tree->devman_functions, &key); 996 if (link == NULL) 997 return NULL; 998 999 return hash_table_get_instance(link, fun_node_t, devman_fun); 1000 } 1001 1002 /** Find the function node with the specified handle. 1003 * 1004 * @param tree The device tree where we look for the device node. 1005 * @param handle The handle of the function. 1006 * @return The function node. 1007 */ 1008 fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle) 1009 { 1010 fun_node_t *fun = NULL; 1011 1012 fibril_rwlock_read_lock(&tree->rwlock); 1013 fun = find_fun_node_no_lock(tree, handle); 1014 fibril_rwlock_read_unlock(&tree->rwlock); 1015 1016 return fun; 1017 } 903 1018 904 1019 /** Create and set device's full path in device tree. … … 909 1024 * resources etc.). 910 1025 */ 911 static bool set_ dev_path(node_t *node,node_t *parent)912 { 913 assert( node->name != NULL);914 915 size_t pathsize = (str_size( node->name) + 1);1026 static bool set_fun_path(fun_node_t *fun, fun_node_t *parent) 1027 { 1028 assert(fun->name != NULL); 1029 1030 size_t pathsize = (str_size(fun->name) + 1); 916 1031 if (parent != NULL) 917 1032 pathsize += str_size(parent->pathname) + 1; 918 1033 919 node->pathname = (char *) malloc(pathsize);920 if ( node->pathname == NULL) {1034 fun->pathname = (char *) malloc(pathsize); 1035 if (fun->pathname == NULL) { 921 1036 printf(NAME ": failed to allocate device path.\n"); 922 1037 return false; … … 924 1039 925 1040 if (parent != NULL) { 926 str_cpy( node->pathname, pathsize, parent->pathname);927 str_append( node->pathname, pathsize, "/");928 str_append( node->pathname, pathsize, node->name);1041 str_cpy(fun->pathname, pathsize, parent->pathname); 1042 str_append(fun->pathname, pathsize, "/"); 1043 str_append(fun->pathname, pathsize, fun->name); 929 1044 } else { 930 str_cpy( node->pathname, pathsize, node->name);1045 str_cpy(fun->pathname, pathsize, fun->name); 931 1046 } 932 1047 … … 944 1059 * etc.). 945 1060 */ 946 bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name, 947 node_t *parent) 948 { 949 assert(node != NULL); 1061 bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun) 1062 { 1063 assert(dev != NULL); 950 1064 assert(tree != NULL); 951 assert(dev_name != NULL);952 1065 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 953 1066 954 node->name = dev_name; 955 if (!set_dev_path(node, parent)) { 1067 /* Add the node to the handle-to-node map. */ 1068 dev->handle = ++tree->current_handle; 1069 unsigned long key = dev->handle; 1070 hash_table_insert(&tree->devman_devices, &key, &dev->devman_dev); 1071 1072 /* Add the node to the list of its parent's children. */ 1073 printf("insert_dev_node: dev=%p, dev->pfun := %p\n", dev, pfun); 1074 dev->pfun = pfun; 1075 pfun->child = dev; 1076 1077 return true; 1078 } 1079 1080 /** Insert new function into device tree. 1081 * 1082 * @param tree The device tree. 1083 * @param node The newly added function node. 1084 * @param dev_name The name of the newly added function. 1085 * @param parent Owning device node. 1086 * 1087 * @return True on success, false otherwise (insufficient resources 1088 * etc.). 1089 */ 1090 bool insert_fun_node(dev_tree_t *tree, fun_node_t *fun, char *fun_name, 1091 dev_node_t *dev) 1092 { 1093 fun_node_t *pfun; 1094 1095 assert(fun != NULL); 1096 assert(tree != NULL); 1097 assert(fun_name != NULL); 1098 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1099 1100 /* 1101 * The root function is a special case, it does not belong to any 1102 * device so for the root function dev == NULL. 1103 */ 1104 pfun = (dev != NULL) ? dev->pfun : NULL; 1105 1106 fun->name = fun_name; 1107 if (!set_fun_path(fun, pfun)) { 956 1108 return false; 957 1109 } 958 1110 959 1111 /* Add the node to the handle-to-node map. */ 960 node->handle = ++tree->current_handle;961 unsigned long key = node->handle;962 hash_table_insert(&tree->devman_ devices, &key, &node->devman_link);1112 fun->handle = ++tree->current_handle; 1113 unsigned long key = fun->handle; 1114 hash_table_insert(&tree->devman_functions, &key, &fun->devman_fun); 963 1115 964 1116 /* Add the node to the list of its parent's children. */ 965 node->parent = parent;966 if ( parent!= NULL)967 list_append(& node->sibling, &parent->children);1117 fun->dev = dev; 1118 if (dev != NULL) 1119 list_append(&fun->dev_functions, &dev->functions); 968 1120 969 1121 return true; 970 1122 } 971 1123 972 /** Find devicenode with a specified path in the device tree.1124 /** Find function node with a specified path in the device tree. 973 1125 * 974 * @param path The path of the devicenode in the device tree.1126 * @param path The path of the function node in the device tree. 975 1127 * @param tree The device tree. 976 * @return The devicenode if it is present in the tree, NULL1128 * @return The function node if it is present in the tree, NULL 977 1129 * otherwise. 978 1130 */ 979 node_t *find_dev_node_by_path(dev_tree_t *tree, char *path)1131 fun_node_t *find_fun_node_by_path(dev_tree_t *tree, char *path) 980 1132 { 981 1133 fibril_rwlock_read_lock(&tree->rwlock); 982 1134 983 node_t *dev= tree->root_node;1135 fun_node_t *fun = tree->root_node; 984 1136 /* 985 * Relative path to the devicefrom its parent (but with '/' at the1137 * Relative path to the function from its parent (but with '/' at the 986 1138 * beginning) 987 1139 */ … … 990 1142 bool cont = (rel_path[0] == '/'); 991 1143 992 while (cont && dev!= NULL) {1144 while (cont && fun != NULL) { 993 1145 next_path_elem = get_path_elem_end(rel_path + 1); 994 1146 if (next_path_elem[0] == '/') { … … 999 1151 } 1000 1152 1001 dev = find_node_child(dev, rel_path + 1);1153 fun = find_node_child(fun, rel_path + 1); 1002 1154 1003 1155 if (cont) { … … 1010 1162 fibril_rwlock_read_unlock(&tree->rwlock); 1011 1163 1012 return dev;1013 } 1014 1015 /** Find child devicenode with a specified name.1164 return fun; 1165 } 1166 1167 /** Find child function node with a specified name. 1016 1168 * 1017 1169 * Device tree rwlock should be held at least for reading. 1018 1170 * 1019 * @param parent The parent devicenode.1020 * @param name The name of the child device node.1021 * @return The child devicenode.1022 */ 1023 node_t *find_node_child(node_t *parent, const char *name)1024 { 1025 node_t *dev;1171 * @param parent The parent function node. 1172 * @param name The name of the child function. 1173 * @return The child function node. 1174 */ 1175 fun_node_t *find_node_child(fun_node_t *pfun, const char *name) 1176 { 1177 fun_node_t *fun; 1026 1178 link_t *link; 1027 1179 1028 link = p arent->children.next;1029 1030 while (link != &p arent->children) {1031 dev = list_get_instance(link, node_t, sibling);1180 link = pfun->child->functions.next; 1181 1182 while (link != &pfun->child->functions) { 1183 fun = list_get_instance(link, fun_node_t, dev_functions); 1032 1184 1033 if (str_cmp(name, dev->name) == 0)1034 return dev;1185 if (str_cmp(name, fun->name) == 0) 1186 return fun; 1035 1187 1036 1188 link = link->next; … … 1115 1267 } 1116 1268 1117 /** Add the device to the class.1269 /** Add the device function to the class. 1118 1270 * 1119 1271 * The device may be added to multiple classes and a class may contain multiple … … 1128 1280 * with the class. 1129 1281 */ 1130 dev_class_info_t *add_ device_to_class(node_t *dev, dev_class_t *cl,1282 dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl, 1131 1283 const char *base_dev_name) 1132 1284 { 1133 dev_class_info_t *info = create_dev_class_info(); 1285 dev_class_info_t *info; 1286 1287 assert(fun != NULL); 1288 assert(cl != NULL); 1289 1290 info = create_dev_class_info(); 1291 1134 1292 1135 1293 if (info != NULL) { 1136 1294 info->dev_class = cl; 1137 info-> dev = dev;1295 info->fun = fun; 1138 1296 1139 1297 /* Add the device to the class. */ … … 1143 1301 1144 1302 /* Add the class to the device. */ 1145 list_append(&info->dev_classes, & dev->classes);1303 list_append(&info->dev_classes, &fun->classes); 1146 1304 1147 1305 /* Create unique name for the device within the class. */ … … 1197 1355 list_initialize(&class_list->classes); 1198 1356 fibril_rwlock_initialize(&class_list->rwlock); 1199 hash_table_create(&class_list->devmap_ devices, DEVICE_BUCKETS, 1,1357 hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1, 1200 1358 &devmap_devices_class_ops); 1201 1359 } … … 1204 1362 /* Devmap devices */ 1205 1363 1206 node_t *find_devmap_tree_device(dev_tree_t *tree, devmap_handle_t devmap_handle)1207 { 1208 node_t *dev= NULL;1364 fun_node_t *find_devmap_tree_function(dev_tree_t *tree, devmap_handle_t devmap_handle) 1365 { 1366 fun_node_t *fun = NULL; 1209 1367 link_t *link; 1210 1368 unsigned long key = (unsigned long) devmap_handle; 1211 1369 1212 1370 fibril_rwlock_read_lock(&tree->rwlock); 1213 link = hash_table_find(&tree->devmap_ devices, &key);1371 link = hash_table_find(&tree->devmap_functions, &key); 1214 1372 if (link != NULL) 1215 dev = hash_table_get_instance(link, node_t, devmap_link);1373 fun = hash_table_get_instance(link, fun_node_t, devmap_fun); 1216 1374 fibril_rwlock_read_unlock(&tree->rwlock); 1217 1375 1218 return dev;1219 } 1220 1221 node_t *find_devmap_class_device(class_list_t *classes,1376 return fun; 1377 } 1378 1379 fun_node_t *find_devmap_class_function(class_list_t *classes, 1222 1380 devmap_handle_t devmap_handle) 1223 1381 { 1224 node_t *dev= NULL;1382 fun_node_t *fun = NULL; 1225 1383 dev_class_info_t *cli; 1226 1384 link_t *link; … … 1228 1386 1229 1387 fibril_rwlock_read_lock(&classes->rwlock); 1230 link = hash_table_find(&classes->devmap_ devices, &key);1388 link = hash_table_find(&classes->devmap_functions, &key); 1231 1389 if (link != NULL) { 1232 1390 cli = hash_table_get_instance(link, dev_class_info_t, 1233 1391 devmap_link); 1234 dev = cli->dev;1392 fun = cli->fun; 1235 1393 } 1236 1394 fibril_rwlock_read_unlock(&classes->rwlock); 1237 1395 1238 return dev;1239 } 1240 1241 void class_add_devmap_ device(class_list_t *class_list, dev_class_info_t *cli)1396 return fun; 1397 } 1398 1399 void class_add_devmap_function(class_list_t *class_list, dev_class_info_t *cli) 1242 1400 { 1243 1401 unsigned long key = (unsigned long) cli->devmap_handle; 1244 1402 1245 1403 fibril_rwlock_write_lock(&class_list->rwlock); 1246 hash_table_insert(&class_list->devmap_ devices, &key, &cli->devmap_link);1404 hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link); 1247 1405 fibril_rwlock_write_unlock(&class_list->rwlock); 1248 1406 1249 assert(find_devmap_class_ device(class_list, cli->devmap_handle) != NULL);1250 } 1251 1252 void tree_add_devmap_ device(dev_tree_t *tree, node_t *node)1253 { 1254 unsigned long key = (unsigned long) node->devmap_handle;1407 assert(find_devmap_class_function(class_list, cli->devmap_handle) != NULL); 1408 } 1409 1410 void tree_add_devmap_function(dev_tree_t *tree, fun_node_t *fun) 1411 { 1412 unsigned long key = (unsigned long) fun->devmap_handle; 1255 1413 fibril_rwlock_write_lock(&tree->rwlock); 1256 hash_table_insert(&tree->devmap_ devices, &key, &node->devmap_link);1414 hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun); 1257 1415 fibril_rwlock_write_unlock(&tree->rwlock); 1258 1416 } -
uspace/srv/devman/devman.h
rdbe25f1 reb1a2f4 56 56 #define DEVMAP_SEPARATOR '\\' 57 57 58 struct node; 59 typedef struct node node_t; 58 struct dev_node; 59 typedef struct dev_node dev_node_t; 60 61 struct fun_node; 62 typedef struct fun_node fun_node_t; 60 63 61 64 typedef enum { … … 117 120 } device_state_t; 118 121 119 /** Representation of anode in the device tree. */120 struct node {122 /** Device node in the device tree. */ 123 struct dev_node { 121 124 /** The global unique identifier of the device. */ 122 125 devman_handle_t handle; 123 /** The name of the device specified by its parent. */ 124 char *name; 125 126 /** 127 * Full path and name of the device in device hierarchi (i. e. in full 128 * path in device tree). 129 */ 130 char *pathname; 131 132 /** The node of the parent device. */ 133 node_t *parent; 134 135 /** 136 * Pointers to previous and next child devices in the linked list of 137 * parent device's node. 138 */ 139 link_t sibling; 140 141 /** List of child device nodes. */ 142 link_t children; 143 /** List of device ids for device-to-driver matching. */ 144 match_id_list_t match_ids; 126 127 /** (Parent) function the device is attached to. */ 128 fun_node_t *pfun; 129 130 /** List of device functions. */ 131 link_t functions; 145 132 /** Driver of this device. */ 146 133 driver_t *drv; 147 134 /** The state of the device. */ 148 135 device_state_t state; 149 /** 150 * Pointer to the previous and next device in the list of devices 151 * owned by one driver. 152 */ 136 /** Link to list of devices owned by driver (driver_t.devices) */ 153 137 link_t driver_devices; 154 138 155 /** The list of device classes to which this device belongs. */156 link_t classes;157 /** Devmap handle if the device is registered by devmapper. */158 devmap_handle_t devmap_handle;159 160 139 /** 161 140 * Used by the hash table of devices indexed by devman device handles. 162 141 */ 163 link_t devman_link; 164 165 /** 166 * Used by the hash table of devices indexed by devmap device handles. 167 */ 168 link_t devmap_link; 169 142 link_t devman_dev; 143 170 144 /** 171 145 * Whether this device was already passed to the driver. … … 173 147 bool passed_to_driver; 174 148 }; 149 150 /** Function node in the device tree. */ 151 struct fun_node { 152 /** The global unique identifier of the function */ 153 devman_handle_t handle; 154 /** Name of the function, assigned by the device driver */ 155 char *name; 156 157 /** Full path and name of the device in device hierarchy */ 158 char *pathname; 159 160 /** Device which this function belongs to */ 161 dev_node_t *dev; 162 163 /** Link to list of functions in the device (ddf_dev_t.functions) */ 164 link_t dev_functions; 165 166 /** Child device node (if any attached). */ 167 dev_node_t *child; 168 /** List of device ids for device-to-driver matching. */ 169 match_id_list_t match_ids; 170 171 /** The list of device classes to which this device function belongs. */ 172 link_t classes; 173 /** Devmap handle if the device function is registered by devmap. */ 174 devmap_handle_t devmap_handle; 175 176 /** 177 * Used by the hash table of functions indexed by devman device handles. 178 */ 179 link_t devman_fun; 180 181 /** 182 * Used by the hash table of functions indexed by devmap device handles. 183 */ 184 link_t devmap_fun; 185 }; 186 175 187 176 188 /** Represents device tree. */ 177 189 typedef struct dev_tree { 178 190 /** Root device node. */ 179 node_t *root_node;191 fun_node_t *root_node; 180 192 181 193 /** … … 191 203 hash_table_t devman_devices; 192 204 205 /** Hash table of all devices indexed by devman handles. */ 206 hash_table_t devman_functions; 207 193 208 /** 194 209 * Hash table of devices registered by devmapper, indexed by devmap 195 210 * handles. 196 211 */ 197 hash_table_t devmap_ devices;212 hash_table_t devmap_functions; 198 213 } dev_tree_t; 199 214 … … 227 242 228 243 /** 229 * Provides n-to-m mapping between device nodes and classes - each device may230 * be register to the arbitrary number of classes and each class maycontain231 * the arbitrary number of devices.244 * Provides n-to-m mapping between function nodes and classes - each function 245 * can register in an arbitrary number of classes and each class can contain 246 * an arbitrary number of device functions. 232 247 */ 233 248 typedef struct dev_class_info { … … 235 250 dev_class_t *dev_class; 236 251 /** The device. */ 237 node_t *dev;252 fun_node_t *fun; 238 253 239 254 /** … … 249 264 link_t dev_classes; 250 265 251 /** The name of the device within the class. */266 /** The name of the device function within the class. */ 252 267 char *dev_name; 253 268 /** The handle of the device by device mapper in the class namespace. */ … … 270 285 * indexed by devmap handles. 271 286 */ 272 hash_table_t devmap_ devices;287 hash_table_t devmap_functions; 273 288 274 289 /** Fibril mutex for list of classes. */ … … 278 293 /* Match ids and scores */ 279 294 280 extern int get_match_score(driver_t *, node_t *);295 extern int get_match_score(driver_t *, dev_node_t *); 281 296 282 297 extern bool parse_match_ids(char *, match_id_list_t *); … … 292 307 extern int lookup_available_drivers(driver_list_t *, const char *); 293 308 294 extern driver_t *find_best_match_driver(driver_list_t *, node_t *);295 extern bool assign_driver( node_t *, driver_list_t *, dev_tree_t *);309 extern driver_t *find_best_match_driver(driver_list_t *, dev_node_t *); 310 extern bool assign_driver(dev_node_t *, driver_list_t *, dev_tree_t *); 296 311 297 312 extern void add_driver(driver_list_t *, driver_t *); 298 extern void attach_driver( node_t *, driver_t *);299 extern void add_device(int, driver_t *, node_t *, dev_tree_t *);313 extern void attach_driver(dev_node_t *, driver_t *); 314 extern void add_device(int, driver_t *, dev_node_t *, dev_tree_t *); 300 315 extern bool start_driver(driver_t *); 301 316 … … 310 325 /* Device nodes */ 311 326 312 extern node_t *create_dev_node(void);313 extern void delete_dev_node( node_t *node);314 extern node_t *find_dev_node_no_lock(dev_tree_t *tree,327 extern dev_node_t *create_dev_node(void); 328 extern void delete_dev_node(dev_node_t *node); 329 extern dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, 315 330 devman_handle_t handle); 316 extern node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle); 317 extern node_t *find_dev_node_by_path(dev_tree_t *, char *); 318 extern node_t *find_node_child(node_t *, const char *); 331 extern dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle); 332 extern dev_node_t *find_dev_function(dev_node_t *, const char *); 333 334 extern fun_node_t *create_fun_node(void); 335 extern void delete_fun_node(fun_node_t *); 336 extern fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, 337 devman_handle_t handle); 338 extern fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle); 339 extern fun_node_t *find_fun_node_by_path(dev_tree_t *, char *); 319 340 320 341 /* Device tree */ 321 342 322 343 extern bool init_device_tree(dev_tree_t *, driver_list_t *); 323 extern bool create_root_node(dev_tree_t *); 324 extern bool insert_dev_node(dev_tree_t *, node_t *, char *, node_t *); 344 extern bool create_root_nodes(dev_tree_t *); 345 extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *); 346 extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *); 325 347 326 348 /* Device classes */ … … 330 352 extern size_t get_new_class_dev_idx(dev_class_t *); 331 353 extern char *create_dev_name_for_class(dev_class_t *, const char *); 332 extern dev_class_info_t *add_ device_to_class(node_t *, dev_class_t *,354 extern dev_class_info_t *add_function_to_class(fun_node_t *, dev_class_t *, 333 355 const char *); 334 356 … … 341 363 /* Devmap devices */ 342 364 343 extern node_t *find_devmap_tree_device(dev_tree_t *, devmap_handle_t); 344 extern node_t *find_devmap_class_device(class_list_t *, devmap_handle_t); 345 346 extern void class_add_devmap_device(class_list_t *, dev_class_info_t *); 347 extern void tree_add_devmap_device(dev_tree_t *, node_t *); 365 extern void devmap_register_tree_function(fun_node_t *, dev_tree_t *); 366 367 extern fun_node_t *find_devmap_tree_function(dev_tree_t *, devmap_handle_t); 368 extern fun_node_t *find_devmap_class_function(class_list_t *, devmap_handle_t); 369 370 extern void class_add_devmap_function(class_list_t *, dev_class_info_t *); 371 extern void tree_add_devmap_function(dev_tree_t *, fun_node_t *); 348 372 349 373 #endif -
uspace/srv/devman/main.c
rdbe25f1 reb1a2f4 199 199 static int assign_driver_fibril(void *arg) 200 200 { 201 node_t *node = (node_t *) arg;202 assign_driver( node, &drivers_list, &device_tree);201 dev_node_t *dev_node = (dev_node_t *) arg; 202 assign_driver(dev_node, &drivers_list, &device_tree); 203 203 return EOK; 204 204 } 205 205 206 /** Handle child deviceregistration.206 /** Handle function registration. 207 207 * 208 208 * Child devices are registered by their parent's device driver. 209 209 */ 210 static void devman_add_child(ipc_callid_t callid, ipc_call_t *call) 211 { 212 devman_handle_t parent_handle = IPC_GET_ARG1(*call); 213 sysarg_t match_count = IPC_GET_ARG2(*call); 210 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call) 211 { 212 fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call); 213 devman_handle_t dev_handle = IPC_GET_ARG2(*call); 214 sysarg_t match_count = IPC_GET_ARG3(*call); 214 215 dev_tree_t *tree = &device_tree; 215 216 216 217 fibril_rwlock_write_lock(&tree->rwlock); 217 node_t *parent = find_dev_node_no_lock(&device_tree, parent_handle); 218 219 if (parent == NULL) { 218 219 dev_node_t *dev = NULL; 220 dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle); 221 222 if (pdev == NULL) { 220 223 fibril_rwlock_write_unlock(&tree->rwlock); 221 224 async_answer_0(callid, ENOENT); … … 223 226 } 224 227 225 char *dev_name = NULL; 226 int rc = async_data_write_accept((void **)&dev_name, true, 0, 0, 0, 0); 228 if (ftype != fun_inner && ftype != fun_exposed) { 229 /* Unknown function type */ 230 printf(NAME ": Error, unknown function type provided by driver!\n"); 231 232 fibril_rwlock_write_unlock(&tree->rwlock); 233 async_answer_0(callid, EINVAL); 234 return; 235 } 236 237 char *fun_name = NULL; 238 int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0); 227 239 if (rc != EOK) { 228 240 fibril_rwlock_write_unlock(&tree->rwlock); … … 231 243 } 232 244 233 node_t *node = create_dev_node();234 if (!insert_ dev_node(&device_tree, node, dev_name, parent)) {245 fun_node_t *fun = create_fun_node(); 246 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 235 247 fibril_rwlock_write_unlock(&tree->rwlock); 236 delete_ dev_node(node);248 delete_fun_node(fun); 237 249 async_answer_0(callid, ENOMEM); 238 250 return; 239 251 } 240 252 253 if (ftype == fun_inner) { 254 dev = create_dev_node(); 255 if (dev == NULL) { 256 fibril_rwlock_write_unlock(&tree->rwlock); 257 delete_fun_node(fun); 258 async_answer_0(callid, ENOMEM); 259 return; 260 } 261 262 insert_dev_node(tree, dev, fun); 263 } 264 241 265 fibril_rwlock_write_unlock(&tree->rwlock); 242 266 243 printf(NAME ": devman_add_child %s\n", node->pathname); 244 245 devman_receive_match_ids(match_count, &node->match_ids); 246 247 /* 248 * Try to find a suitable driver and assign it to the device. We do 249 * not want to block the current fibril that is used for processing 250 * incoming calls: we will launch a separate fibril to handle the 251 * driver assigning. That is because assign_driver can actually include 252 * task spawning which could take some time. 253 */ 254 fid_t assign_fibril = fibril_create(assign_driver_fibril, node); 255 if (assign_fibril == 0) { 267 printf(NAME ": devman_add_function %s\n", fun->pathname); 268 269 devman_receive_match_ids(match_count, &fun->match_ids); 270 271 if (ftype == fun_inner) { 272 assert(dev != NULL); 256 273 /* 257 * Fallback in case we are out of memory. 258 * Probably not needed as we will die soon anyway ;-). 274 * Try to find a suitable driver and assign it to the device. We do 275 * not want to block the current fibril that is used for processing 276 * incoming calls: we will launch a separate fibril to handle the 277 * driver assigning. That is because assign_driver can actually include 278 * task spawning which could take some time. 259 279 */ 260 (void) assign_driver_fibril(node); 280 fid_t assign_fibril = fibril_create(assign_driver_fibril, dev); 281 if (assign_fibril == 0) { 282 /* 283 * Fallback in case we are out of memory. 284 * Probably not needed as we will die soon anyway ;-). 285 */ 286 (void) assign_driver_fibril(fun); 287 } else { 288 fibril_add_ready(assign_fibril); 289 } 261 290 } else { 262 fibril_add_ready(assign_fibril);263 } 264 291 devmap_register_tree_function(fun, tree); 292 } 293 265 294 /* Return device handle to parent's driver. */ 266 async_answer_1(callid, EOK, node->handle);295 async_answer_1(callid, EOK, fun->handle); 267 296 } 268 297 … … 288 317 * mapper. 289 318 */ 290 class_add_devmap_ device(&class_list, cli);319 class_add_devmap_function(&class_list, cli); 291 320 292 321 free(devmap_pathname); 293 322 } 294 323 295 static void devman_add_ device_to_class(ipc_callid_t callid, ipc_call_t *call)324 static void devman_add_function_to_class(ipc_callid_t callid, ipc_call_t *call) 296 325 { 297 326 devman_handle_t handle = IPC_GET_ARG1(*call); … … 306 335 } 307 336 308 node_t *dev = find_dev_node(&device_tree, handle);309 if ( dev== NULL) {337 fun_node_t *fun = find_fun_node(&device_tree, handle); 338 if (fun == NULL) { 310 339 async_answer_0(callid, ENOENT); 311 340 return; … … 313 342 314 343 dev_class_t *cl = get_dev_class(&class_list, class_name); 315 dev_class_info_t *class_info = add_ device_to_class(dev, cl, NULL);344 dev_class_info_t *class_info = add_function_to_class(fun, cl, NULL); 316 345 317 346 /* Register the device's class alias by devmapper. */ 318 347 devmap_register_class_dev(class_info); 319 348 320 printf(NAME ": device'%s' added to class '%s', class name '%s' was "321 "asigned to it\n", dev->pathname, class_name, class_info->dev_name);349 printf(NAME ": function'%s' added to class '%s', class name '%s' was " 350 "asigned to it\n", fun->pathname, class_name, class_info->dev_name); 322 351 323 352 async_answer_0(callid, EOK); … … 372 401 cont = false; 373 402 continue; 374 case DEVMAN_ADD_ CHILD_DEVICE:375 devman_add_ child(callid, &call);403 case DEVMAN_ADD_FUNCTION: 404 devman_add_function(callid, &call); 376 405 break; 377 406 case DEVMAN_ADD_DEVICE_TO_CLASS: 378 devman_add_ device_to_class(callid, &call);407 devman_add_function_to_class(callid, &call); 379 408 break; 380 409 default: … … 387 416 /** Find handle for the device instance identified by the device's path in the 388 417 * device tree. */ 389 static void devman_ device_get_handle(ipc_callid_t iid, ipc_call_t *icall)418 static void devman_function_get_handle(ipc_callid_t iid, ipc_call_t *icall) 390 419 { 391 420 char *pathname; … … 397 426 } 398 427 399 node_t * dev = find_dev_node_by_path(&device_tree, pathname);428 fun_node_t *fun = find_fun_node_by_path(&device_tree, pathname); 400 429 401 430 free(pathname); 402 431 403 if ( dev== NULL) {432 if (fun == NULL) { 404 433 async_answer_0(iid, ENOENT); 405 434 return; 406 435 } 407 408 async_answer_1(iid, EOK, dev->handle);436 437 async_answer_1(iid, EOK, fun->handle); 409 438 } 410 439 … … 426 455 continue; 427 456 case DEVMAN_DEVICE_GET_HANDLE: 428 devman_ device_get_handle(callid, &call);457 devman_function_get_handle(callid, &call); 429 458 break; 430 459 default: … … 438 467 { 439 468 devman_handle_t handle = IPC_GET_ARG2(*icall); 440 441 node_t *dev = find_dev_node(&device_tree, handle); 442 if (dev == NULL) { 443 printf(NAME ": devman_forward error - no device with handle %" PRIun 444 " was found.\n", handle); 469 devman_handle_t fwd_h; 470 fun_node_t *fun = NULL; 471 dev_node_t *dev = NULL; 472 473 fun = find_fun_node(&device_tree, handle); 474 if (fun == NULL) 475 dev = find_dev_node(&device_tree, handle); 476 else 477 dev = fun->dev; 478 479 if (fun == NULL && dev == NULL) { 480 printf(NAME ": devman_forward error - no device or function with " 481 "handle %" PRIun " was found.\n", handle); 445 482 async_answer_0(iid, ENOENT); 446 483 return; 447 484 } 485 486 if (fun == NULL && !drv_to_parent) { 487 printf(NAME ": devman_forward error - cannot connect to " 488 "handle %" PRIun ", refers to a device.\n", handle); 489 async_answer_0(iid, ENOENT); 490 return; 491 } 448 492 449 493 driver_t *driver = NULL; 450 494 451 495 if (drv_to_parent) { 452 if (dev->parent != NULL) 453 driver = dev->parent->drv; 496 /* Connect to parent function of a device (or device function). */ 497 if (dev->pfun->dev != NULL) 498 driver = dev->pfun->dev->drv; 499 fwd_h = dev->pfun->handle; 454 500 } else if (dev->state == DEVICE_USABLE) { 501 /* Connect to the specified function */ 455 502 driver = dev->drv; 456 503 assert(driver != NULL); 504 505 fwd_h = handle; 457 506 } 458 507 … … 460 509 printf(NAME ": devman_forward error - the device %" PRIun \ 461 510 " (%s) is not in usable state.\n", 462 handle, dev->p athname);511 handle, dev->pfun->pathname); 463 512 async_answer_0(iid, ENOENT); 464 513 return; … … 479 528 } 480 529 481 printf(NAME ": devman_forward: forward connection to device %s to " 482 "driver %s.\n", dev->pathname, driver->name); 483 async_forward_fast(iid, driver->phone, method, dev->handle, 0, IPC_FF_NONE); 530 if (fun != NULL) { 531 printf(NAME ": devman_forward: forward connection to function %s to " 532 "driver %s.\n", fun->pathname, driver->name); 533 } else { 534 printf(NAME ": devman_forward: forward connection to device %s to " 535 "driver %s.\n", dev->pfun->pathname, driver->name); 536 } 537 538 async_forward_fast(iid, driver->phone, method, fwd_h, 0, IPC_FF_NONE); 484 539 } 485 540 … … 489 544 { 490 545 devmap_handle_t devmap_handle = IPC_GET_ARG2(*icall); 491 node_t *dev; 492 493 dev = find_devmap_tree_device(&device_tree, devmap_handle); 494 if (dev == NULL) 495 dev = find_devmap_class_device(&class_list, devmap_handle); 496 497 if (dev == NULL || dev->drv == NULL) { 546 fun_node_t *fun; 547 dev_node_t *dev; 548 549 fun = find_devmap_tree_function(&device_tree, devmap_handle); 550 if (fun == NULL) 551 fun = find_devmap_class_function(&class_list, devmap_handle); 552 553 if (fun == NULL || fun->dev->drv == NULL) { 498 554 async_answer_0(iid, ENOENT); 499 555 return; 500 556 } 557 558 dev = fun->dev; 501 559 502 560 if (dev->state != DEVICE_USABLE || dev->drv->phone <= 0) { … … 505 563 } 506 564 507 async_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, dev->handle, 0,565 async_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, fun->handle, 0, 508 566 IPC_FF_NONE); 509 567 printf(NAME ": devman_connection_devmapper: forwarded connection to " 510 "device %s to driver %s.\n", dev->pathname, dev->drv->name);568 "device %s to driver %s.\n", fun->pathname, dev->drv->name); 511 569 } 512 570 -
uspace/srv/devman/match.c
rdbe25f1 reb1a2f4 57 57 } 58 58 59 int get_match_score(driver_t *drv, node_t *dev)59 int get_match_score(driver_t *drv, dev_node_t *dev) 60 60 { 61 61 link_t *drv_head = &drv->match_ids.ids; 62 link_t *dev_head = &dev-> match_ids.ids;62 link_t *dev_head = &dev->pfun->match_ids.ids; 63 63 64 64 if (list_empty(drv_head) || list_empty(dev_head)) -
uspace/srv/fs/devfs/devfs_ops.c
rdbe25f1 reb1a2f4 278 278 fibril_mutex_unlock(&devices_mutex); 279 279 280 free(dev);281 280 return ENOENT; 282 281 }
Note:
See TracChangeset
for help on using the changeset viewer.