Changeset 07b39338 in mainline for uspace/srv/devman/devman.c
- Timestamp:
- 2011-08-20T18:21:49Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 6ab014d
- Parents:
- 0cf27ee (diff), f00af83 (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
r0cf27ee r07b39338 73 73 } 74 74 75 static int loc_devices_class_compare(unsigned long key[], hash_count_t keys,76 link_t *item)77 {78 dev_class_info_t *class_info79 = hash_table_get_instance(item, dev_class_info_t, loc_link);80 assert(class_info != NULL);81 82 return (class_info->service_id == (service_id_t) key[0]);83 }84 85 75 static void devices_remove_callback(link_t *item) 86 76 { … … 102 92 .hash = devices_hash, 103 93 .compare = loc_functions_compare, 104 .remove_callback = devices_remove_callback105 };106 107 static hash_table_operations_t loc_devices_class_ops = {108 .hash = devices_hash,109 .compare = loc_devices_class_compare,110 94 .remove_callback = devices_remove_callback 111 95 }; … … 564 548 565 549 fibril_mutex_lock(&driver->driver_mutex); 566 567 async_exch_t *exch = async_exchange_begin(driver->sess);568 async_sess_t *sess = async_connect_me_to(EXCHANGE_SERIALIZE, exch,569 DRIVER_DEVMAN, 0, 0);570 async_exchange_end(exch);571 572 if (!sess) {573 fibril_mutex_unlock(&driver->driver_mutex);574 return;575 }576 550 577 551 /* … … 599 573 fibril_mutex_unlock(&driver->driver_mutex); 600 574 601 add_device( sess,driver, dev, tree);575 add_device(driver, dev, tree); 602 576 603 577 /* … … 619 593 link = driver->devices.head.next; 620 594 } 621 622 async_hangup(sess);623 595 624 596 /* … … 734 706 * @param node The device's node in the device tree. 735 707 */ 736 void add_device(async_sess_t *sess, driver_t *drv, dev_node_t *dev, 737 dev_tree_t *tree) 708 void add_device(driver_t *drv, dev_node_t *dev, dev_tree_t *tree) 738 709 { 739 710 /* … … 752 723 } 753 724 754 async_exch_t *exch = async_exchange_begin( sess);725 async_exch_t *exch = async_exchange_begin(drv->sess); 755 726 756 727 ipc_call_t answer; … … 822 793 fibril_mutex_unlock(&drv->driver_mutex); 823 794 824 if (is_running) { 825 /* Notify the driver about the new device. */ 826 async_exch_t *exch = async_exchange_begin(drv->sess); 827 async_sess_t *sess = async_connect_me_to(EXCHANGE_SERIALIZE, exch, 828 DRIVER_DEVMAN, 0, 0); 829 async_exchange_end(exch); 830 831 if (sess) { 832 add_device(sess, drv, dev, tree); 833 async_hangup(sess); 834 } 835 } 795 /* Notify the driver about the new device. */ 796 if (is_running) 797 add_device(drv, dev, tree); 836 798 837 799 return true; … … 936 898 } 937 899 900 /** Get list of device functions. */ 901 int dev_get_functions(dev_tree_t *tree, dev_node_t *dev, 902 devman_handle_t *hdl_buf, size_t buf_size, size_t *act_size) 903 { 904 size_t act_cnt; 905 size_t buf_cnt; 906 907 assert(fibril_rwlock_is_locked(&tree->rwlock)); 908 909 buf_cnt = buf_size / sizeof(devman_handle_t); 910 911 act_cnt = list_count(&dev->functions); 912 *act_size = act_cnt * sizeof(devman_handle_t); 913 914 if (buf_size % sizeof(devman_handle_t) != 0) 915 return EINVAL; 916 917 size_t pos = 0; 918 list_foreach(dev->functions, item) { 919 fun_node_t *fun = 920 list_get_instance(item, fun_node_t, dev_functions); 921 922 if (pos < buf_cnt) 923 hdl_buf[pos] = fun->handle; 924 pos++; 925 } 926 927 return EOK; 928 } 929 930 938 931 /* Function nodes */ 939 932 … … 950 943 link_initialize(&res->dev_functions); 951 944 list_initialize(&res->match_ids.ids); 952 list_initialize(&res->classes);953 945 link_initialize(&res->devman_fun); 954 946 link_initialize(&res->loc_fun); … … 1115 1107 1116 1108 return true; 1109 } 1110 1111 /** Remove function from device tree. 1112 * 1113 * @param tree Device tree 1114 * @param node Function node to remove 1115 */ 1116 void remove_fun_node(dev_tree_t *tree, fun_node_t *fun) 1117 { 1118 assert(tree != NULL); 1119 assert(fun != NULL); 1120 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1121 1122 /* Remove the node from the handle-to-node map. */ 1123 unsigned long key = fun->handle; 1124 hash_table_remove(&tree->devman_functions, &key, 1); 1125 1126 /* Remove the node from the list of its parent's children. */ 1127 if (fun->dev != NULL) 1128 list_remove(&fun->dev_functions); 1117 1129 } 1118 1130 … … 1142 1154 char *rel_path = path; 1143 1155 char *next_path_elem = NULL; 1144 bool cont = true;1156 bool cont = (rel_path[1] != '\0'); 1145 1157 1146 1158 while (cont && fun != NULL) { … … 1193 1205 } 1194 1206 1195 /** Find function node by its class name and index. */1196 fun_node_t *find_fun_node_by_class(class_list_t *class_list,1197 const char *class_name, const char *dev_name)1198 {1199 assert(class_list != NULL);1200 assert(class_name != NULL);1201 assert(dev_name != NULL);1202 1203 fibril_rwlock_read_lock(&class_list->rwlock);1204 1205 dev_class_t *cl = find_dev_class_no_lock(class_list, class_name);1206 if (cl == NULL) {1207 fibril_rwlock_read_unlock(&class_list->rwlock);1208 return NULL;1209 }1210 1211 dev_class_info_t *dev = find_dev_in_class(cl, dev_name);1212 if (dev == NULL) {1213 fibril_rwlock_read_unlock(&class_list->rwlock);1214 return NULL;1215 }1216 1217 fun_node_t *fun = dev->fun;1218 1219 fibril_rwlock_read_unlock(&class_list->rwlock);1220 1221 return fun;1222 }1223 1224 1225 1207 /** Find child function node with a specified name. 1226 1208 * … … 1235 1217 return find_fun_node_in_device(pfun->child, name); 1236 1218 } 1237 1238 /* Device classes */1239 1240 /** Create device class.1241 *1242 * @return Device class.1243 */1244 dev_class_t *create_dev_class(void)1245 {1246 dev_class_t *cl;1247 1248 cl = (dev_class_t *) malloc(sizeof(dev_class_t));1249 if (cl != NULL) {1250 memset(cl, 0, sizeof(dev_class_t));1251 list_initialize(&cl->devices);1252 fibril_mutex_initialize(&cl->mutex);1253 }1254 1255 return cl;1256 }1257 1258 /** Create device class info.1259 *1260 * @return Device class info.1261 */1262 dev_class_info_t *create_dev_class_info(void)1263 {1264 dev_class_info_t *info;1265 1266 info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t));1267 if (info != NULL) {1268 memset(info, 0, sizeof(dev_class_info_t));1269 link_initialize(&info->dev_classes);1270 link_initialize(&info->loc_link);1271 link_initialize(&info->link);1272 }1273 1274 return info;1275 }1276 1277 size_t get_new_class_dev_idx(dev_class_t *cl)1278 {1279 size_t dev_idx;1280 1281 fibril_mutex_lock(&cl->mutex);1282 dev_idx = ++cl->curr_dev_idx;1283 fibril_mutex_unlock(&cl->mutex);1284 1285 return dev_idx;1286 }1287 1288 1289 /** Create unique device name within the class.1290 *1291 * @param cl The class.1292 * @param base_dev_name Contains the base name for the device if it was1293 * specified by the driver when it registered the device by1294 * the class; NULL if driver specified no base name.1295 * @return The unique name for the device within the class.1296 */1297 char *create_dev_name_for_class(dev_class_t *cl, const char *base_dev_name)1298 {1299 char *dev_name;1300 const char *base_name;1301 1302 if (base_dev_name != NULL)1303 base_name = base_dev_name;1304 else1305 base_name = cl->base_dev_name;1306 1307 size_t idx = get_new_class_dev_idx(cl);1308 asprintf(&dev_name, "%s%zu", base_name, idx);1309 1310 return dev_name;1311 }1312 1313 /** Add the device function to the class.1314 *1315 * The device may be added to multiple classes and a class may contain multiple1316 * devices. The class and the device are associated with each other by the1317 * dev_class_info_t structure.1318 *1319 * @param dev The device.1320 * @param class The class.1321 * @param base_dev_name The base name of the device within the class if1322 * specified by the driver, NULL otherwise.1323 * @return dev_class_info_t structure which associates the device1324 * with the class.1325 */1326 dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl,1327 const char *base_dev_name)1328 {1329 dev_class_info_t *info;1330 1331 assert(fun != NULL);1332 assert(cl != NULL);1333 1334 info = create_dev_class_info();1335 1336 1337 if (info != NULL) {1338 info->dev_class = cl;1339 info->fun = fun;1340 1341 /* Add the device to the class. */1342 fibril_mutex_lock(&cl->mutex);1343 list_append(&info->link, &cl->devices);1344 fibril_mutex_unlock(&cl->mutex);1345 1346 /* Add the class to the device. */1347 list_append(&info->dev_classes, &fun->classes);1348 1349 /* Create unique name for the device within the class. */1350 info->dev_name = create_dev_name_for_class(cl, base_dev_name);1351 }1352 1353 return info;1354 }1355 1356 dev_class_t *get_dev_class(class_list_t *class_list, char *class_name)1357 {1358 dev_class_t *cl;1359 1360 fibril_rwlock_write_lock(&class_list->rwlock);1361 cl = find_dev_class_no_lock(class_list, class_name);1362 if (cl == NULL) {1363 cl = create_dev_class();1364 if (cl != NULL) {1365 cl->name = class_name;1366 cl->base_dev_name = "";1367 add_dev_class_no_lock(class_list, cl);1368 }1369 }1370 1371 fibril_rwlock_write_unlock(&class_list->rwlock);1372 return cl;1373 }1374 1375 dev_class_t *find_dev_class_no_lock(class_list_t *class_list,1376 const char *class_name)1377 {1378 dev_class_t *cl;1379 1380 list_foreach(class_list->classes, link) {1381 cl = list_get_instance(link, dev_class_t, link);1382 if (str_cmp(cl->name, class_name) == 0) {1383 return cl;1384 }1385 }1386 1387 return NULL;1388 }1389 1390 void add_dev_class_no_lock(class_list_t *class_list, dev_class_t *cl)1391 {1392 list_append(&cl->link, &class_list->classes);1393 }1394 1395 dev_class_info_t *find_dev_in_class(dev_class_t *dev_class, const char *dev_name)1396 {1397 assert(dev_class != NULL);1398 assert(dev_name != NULL);1399 1400 list_foreach(dev_class->devices, link) {1401 dev_class_info_t *dev = list_get_instance(link,1402 dev_class_info_t, link);1403 1404 if (str_cmp(dev->dev_name, dev_name) == 0) {1405 return dev;1406 }1407 }1408 1409 return NULL;1410 }1411 1412 void init_class_list(class_list_t *class_list)1413 {1414 list_initialize(&class_list->classes);1415 fibril_rwlock_initialize(&class_list->rwlock);1416 hash_table_create(&class_list->loc_functions, DEVICE_BUCKETS, 1,1417 &loc_devices_class_ops);1418 }1419 1420 1219 1421 1220 /* loc devices */ … … 1436 1235 } 1437 1236 1438 fun_node_t *find_loc_class_function(class_list_t *classes,1439 service_id_t service_id)1440 {1441 fun_node_t *fun = NULL;1442 dev_class_info_t *cli;1443 link_t *link;1444 unsigned long key = (unsigned long)service_id;1445 1446 fibril_rwlock_read_lock(&classes->rwlock);1447 link = hash_table_find(&classes->loc_functions, &key);1448 if (link != NULL) {1449 cli = hash_table_get_instance(link, dev_class_info_t,1450 loc_link);1451 fun = cli->fun;1452 }1453 fibril_rwlock_read_unlock(&classes->rwlock);1454 1455 return fun;1456 }1457 1458 void class_add_loc_function(class_list_t *class_list, dev_class_info_t *cli)1459 {1460 unsigned long key = (unsigned long) cli->service_id;1461 1462 fibril_rwlock_write_lock(&class_list->rwlock);1463 hash_table_insert(&class_list->loc_functions, &key, &cli->loc_link);1464 fibril_rwlock_write_unlock(&class_list->rwlock);1465 1466 assert(find_loc_class_function(class_list, cli->service_id) != NULL);1467 }1468 1469 1237 void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun) 1470 1238 {
Note:
See TracChangeset
for help on using the changeset viewer.