Changeset eb522e8 in mainline for uspace/srv/devman/devman.c
- Timestamp:
- 2011-06-01T08:43:42Z (15 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8d6c1f1
- Parents:
- 9e2e715 (diff), e51a514 (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
-
uspace/srv/devman/devman.c (modified) (45 diffs)
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/devman.c
r9e2e715 reb522e8 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> 38 39 #include <devmap.h> 39 40 #include <str_error.h> 41 #include <stdio.h> 40 42 41 43 #include "devman.h" 44 45 fun_node_t *find_node_child(fun_node_t *parent, const char *name); 42 46 43 47 /* hash table operations */ … … 51 55 link_t *item) 52 56 { 53 node_t *dev = hash_table_get_instance(item, node_t, devman_link);54 return (dev->handle == (dev ice_handle_t) key[0]);55 } 56 57 static int devma p_devices_compare(unsigned long key[], hash_count_t keys,57 dev_node_t *dev = hash_table_get_instance(item, dev_node_t, devman_dev); 58 return (dev->handle == (devman_handle_t) key[0]); 59 } 60 61 static int devman_functions_compare(unsigned long key[], hash_count_t keys, 58 62 link_t *item) 59 63 { 60 node_t *dev = hash_table_get_instance(item, node_t, devmap_link); 61 return (dev->devmap_handle == (dev_handle_t) key[0]); 64 fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devman_fun); 65 return (fun->handle == (devman_handle_t) key[0]); 66 } 67 68 static int devmap_functions_compare(unsigned long key[], hash_count_t keys, 69 link_t *item) 70 { 71 fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devmap_fun); 72 return (fun->devmap_handle == (devmap_handle_t) key[0]); 73 } 74 75 static int devmap_devices_class_compare(unsigned long key[], hash_count_t keys, 76 link_t *item) 77 { 78 dev_class_info_t *class_info 79 = hash_table_get_instance(item, dev_class_info_t, devmap_link); 80 assert(class_info != NULL); 81 82 return (class_info->devmap_handle == (devmap_handle_t) key[0]); 62 83 } 63 84 … … 72 93 }; 73 94 95 static hash_table_operations_t devman_functions_ops = { 96 .hash = devices_hash, 97 .compare = devman_functions_compare, 98 .remove_callback = devices_remove_callback 99 }; 100 74 101 static hash_table_operations_t devmap_devices_ops = { 75 102 .hash = devices_hash, 76 .compare = devmap_devices_compare, 103 .compare = devmap_functions_compare, 104 .remove_callback = devices_remove_callback 105 }; 106 107 static hash_table_operations_t devmap_devices_class_ops = { 108 .hash = devices_hash, 109 .compare = devmap_devices_class_compare, 77 110 .remove_callback = devices_remove_callback 78 111 }; … … 115 148 fibril_mutex_unlock(&drivers_list->drivers_mutex); 116 149 117 printf(NAME": the '%s' driverwas added to the list of available "118 "drivers. \n", drv->name);150 log_msg(LVL_NOTE, "Driver `%s' was added to the list of available " 151 "drivers.", drv->name); 119 152 } 120 153 … … 206 239 bool read_match_ids(const char *conf_path, match_id_list_t *ids) 207 240 { 208 printf(NAME ": read_match_ids conf_path = %s.\n", conf_path);241 log_msg(LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path); 209 242 210 243 bool suc = false; … … 216 249 fd = open(conf_path, O_RDONLY); 217 250 if (fd < 0) { 218 printf(NAME ": unable to open %s\n", conf_path); 251 log_msg(LVL_ERROR, "Unable to open `%s' for reading: %s.", 252 conf_path, str_error(fd)); 219 253 goto cleanup; 220 254 } … … 224 258 lseek(fd, 0, SEEK_SET); 225 259 if (len == 0) { 226 printf(NAME ": configuration file '%s' is empty.\n", conf_path); 260 log_msg(LVL_ERROR, "Configuration file '%s' is empty.", 261 conf_path); 227 262 goto cleanup; 228 263 } … … 230 265 buf = malloc(len + 1); 231 266 if (buf == NULL) { 232 printf(NAME ": memory allocation failed when parsing file "233 "'%s'. \n", conf_path);267 log_msg(LVL_ERROR, "Memory allocation failed when parsing file " 268 "'%s'.", conf_path); 234 269 goto cleanup; 235 270 } 236 271 237 if (read(fd, buf, len) <= 0) { 238 printf(NAME ": unable to read file '%s'.\n", conf_path); 272 ssize_t read_bytes = safe_read(fd, buf, len); 273 if (read_bytes <= 0) { 274 log_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path); 239 275 goto cleanup; 240 276 } 241 buf[ len] = 0;277 buf[read_bytes] = 0; 242 278 243 279 suc = parse_match_ids(buf, ids); … … 274 310 bool get_driver_info(const char *base_path, const char *name, driver_t *drv) 275 311 { 276 printf(NAME ": get_driver_info base_path = %s, name = %s.\n",312 log_msg(LVL_DEBUG, "get_driver_info(base_path=\"%s\", name=\"%s\")", 277 313 base_path, name); 278 314 … … 306 342 struct stat s; 307 343 if (stat(drv->binary_path, &s) == ENOENT) { /* FIXME!! */ 308 printf(NAME ": driver not found at path %s.", drv->binary_path); 344 log_msg(LVL_ERROR, "Driver not found at path `%s'.", 345 drv->binary_path); 309 346 goto cleanup; 310 347 } … … 333 370 int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path) 334 371 { 335 printf(NAME ": lookup_available_drivers, dir = %s \n", dir_path);372 log_msg(LVL_DEBUG, "lookup_available_drivers(dir=\"%s\")", dir_path); 336 373 337 374 int drv_cnt = 0; … … 357 394 } 358 395 359 /** Create root device node in the device tree.396 /** Create root device and function node in the device tree. 360 397 * 361 398 * @param tree The device tree. 362 399 * @return True on success, false otherwise. 363 400 */ 364 bool create_root_node(dev_tree_t *tree) 365 { 366 node_t *node; 367 368 printf(NAME ": create_root_node\n"); 369 370 node = create_dev_node(); 371 if (node != NULL) { 372 insert_dev_node(tree, node, clone_string(""), NULL); 373 match_id_t *id = create_match_id(); 374 id->id = clone_string("root"); 375 id->score = 100; 376 add_match_id(&node->match_ids, id); 377 tree->root_node = node; 378 } 379 380 return node != NULL; 401 bool create_root_nodes(dev_tree_t *tree) 402 { 403 fun_node_t *fun; 404 dev_node_t *dev; 405 406 log_msg(LVL_DEBUG, "create_root_nodes()"); 407 408 fibril_rwlock_write_lock(&tree->rwlock); 409 410 /* 411 * Create root function. This is a pseudo function to which 412 * the root device node is attached. It allows us to match 413 * the root device driver in a standard manner, i.e. against 414 * the parent function. 415 */ 416 417 fun = create_fun_node(); 418 if (fun == NULL) { 419 fibril_rwlock_write_unlock(&tree->rwlock); 420 return false; 421 } 422 423 insert_fun_node(tree, fun, clone_string(""), NULL); 424 match_id_t *id = create_match_id(); 425 id->id = clone_string("root"); 426 id->score = 100; 427 add_match_id(&fun->match_ids, id); 428 tree->root_node = fun; 429 430 /* 431 * Create root device node. 432 */ 433 dev = create_dev_node(); 434 if (dev == NULL) { 435 fibril_rwlock_write_unlock(&tree->rwlock); 436 return false; 437 } 438 439 insert_dev_node(tree, dev, fun); 440 441 fibril_rwlock_write_unlock(&tree->rwlock); 442 443 return dev != NULL; 381 444 } 382 445 … … 396 459 * is found. 397 460 */ 398 driver_t *find_best_match_driver(driver_list_t *drivers_list, node_t *node)461 driver_t *find_best_match_driver(driver_list_t *drivers_list, dev_node_t *node) 399 462 { 400 463 driver_t *best_drv = NULL, *drv = NULL; … … 424 487 * @param drv The driver. 425 488 */ 426 void attach_driver( node_t *node, driver_t *drv)427 { 428 printf(NAME ": attach_driver %s to device %s\n",429 d rv->name, node->pathname);489 void attach_driver(dev_node_t *dev, driver_t *drv) 490 { 491 log_msg(LVL_DEBUG, "attach_driver(dev=\"%s\",drv=\"%s\")", 492 dev->pfun->pathname, drv->name); 430 493 431 494 fibril_mutex_lock(&drv->driver_mutex); 432 495 433 node->drv = drv;434 list_append(& node->driver_devices, &drv->devices);496 dev->drv = drv; 497 list_append(&dev->driver_devices, &drv->devices); 435 498 436 499 fibril_mutex_unlock(&drv->driver_mutex); … … 438 501 439 502 /** Start a driver 440 *441 * The driver's mutex is assumed to be locked.442 503 * 443 504 * @param drv The driver's structure. … … 449 510 int rc; 450 511 451 printf(NAME ": start_driver '%s'\n", drv->name); 512 assert(fibril_mutex_is_locked(&drv->driver_mutex)); 513 514 log_msg(LVL_DEBUG, "start_driver(drv=\"%s\")", drv->name); 452 515 453 516 rc = task_spawnl(NULL, drv->binary_path, drv->binary_path, NULL); 454 517 if (rc != EOK) { 455 printf(NAME ": error spawning %s (%s)\n",456 drv->name, str_error(rc));518 log_msg(LVL_ERROR, "Spawning driver `%s' (%s) failed: %s.", 519 drv->name, drv->binary_path, str_error(rc)); 457 520 return false; 458 521 } … … 493 556 } 494 557 495 /** Remember the driver's phone.496 *497 * @param driver The driver.498 * @param phone The phone to the driver.499 */500 void set_driver_phone(driver_t *driver, ipcarg_t phone)501 {502 fibril_mutex_lock(&driver->driver_mutex);503 assert(driver->state == DRIVER_STARTING);504 driver->phone = phone;505 fibril_mutex_unlock(&driver->driver_mutex);506 }507 508 558 /** Notify driver about the devices to which it was assigned. 509 559 * 510 * The driver's mutex must be locked.511 *512 560 * @param driver The driver to which the devices are passed. 513 561 */ 514 562 static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree) 515 563 { 516 node_t *dev;564 dev_node_t *dev; 517 565 link_t *link; 518 566 int phone; 519 567 520 printf(NAME ": pass_devices_to_driver\n"); 521 522 phone = ipc_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0); 523 if (phone > 0) { 524 568 log_msg(LVL_DEBUG, "pass_devices_to_driver(driver=\"%s\")", 569 driver->name); 570 571 fibril_mutex_lock(&driver->driver_mutex); 572 573 phone = async_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0); 574 575 if (phone < 0) { 576 fibril_mutex_unlock(&driver->driver_mutex); 577 return; 578 } 579 580 /* 581 * Go through devices list as long as there is some device 582 * that has not been passed to the driver. 583 */ 584 link = driver->devices.next; 585 while (link != &driver->devices) { 586 dev = list_get_instance(link, dev_node_t, driver_devices); 587 if (dev->passed_to_driver) { 588 link = link->next; 589 continue; 590 } 591 592 /* 593 * We remove the device from the list to allow safe adding 594 * of new devices (no one will touch our item this way). 595 */ 596 list_remove(link); 597 598 /* 599 * Unlock to avoid deadlock when adding device 600 * handled by itself. 601 */ 602 fibril_mutex_unlock(&driver->driver_mutex); 603 604 add_device(phone, driver, dev, tree); 605 606 /* 607 * Lock again as we will work with driver's 608 * structure. 609 */ 610 fibril_mutex_lock(&driver->driver_mutex); 611 612 /* 613 * Insert the device back. 614 * The order is not relevant here so no harm is done 615 * (actually, the order would be preserved in most cases). 616 */ 617 list_append(link, &driver->devices); 618 619 /* 620 * Restart the cycle to go through all devices again. 621 */ 525 622 link = driver->devices.next; 526 while (link != &driver->devices) { 527 dev = list_get_instance(link, node_t, driver_devices); 528 add_device(phone, driver, dev, tree); 529 link = link->next; 530 } 531 532 ipc_hangup(phone); 533 } 623 } 624 625 async_hangup(phone); 626 627 /* 628 * Once we passed all devices to the driver, we need to mark the 629 * driver as running. 630 * It is vital to do it here and inside critical section. 631 * 632 * If we would change the state earlier, other devices added to 633 * the driver would be added to the device list and started 634 * immediately and possibly started here as well. 635 */ 636 log_msg(LVL_DEBUG, "Driver `%s' enters running state.", driver->name); 637 driver->state = DRIVER_RUNNING; 638 639 fibril_mutex_unlock(&driver->driver_mutex); 534 640 } 535 641 … … 545 651 void initialize_running_driver(driver_t *driver, dev_tree_t *tree) 546 652 { 547 printf(NAME ": initialize_running_driver\n");548 fibril_mutex_lock(&driver->driver_mutex);653 log_msg(LVL_DEBUG, "initialize_running_driver(driver=\"%s\")", 654 driver->name); 549 655 550 656 /* … … 553 659 */ 554 660 pass_devices_to_driver(driver, tree); 555 556 /* Change driver's state to running. */557 driver->state = DRIVER_RUNNING;558 559 fibril_mutex_unlock(&driver->driver_mutex);560 661 } 561 662 … … 572 673 list_initialize(&drv->devices); 573 674 fibril_mutex_initialize(&drv->driver_mutex); 675 drv->phone = -1; 574 676 } 575 677 … … 602 704 } 603 705 604 /** Create devmap path and name for the device. */605 static void devmap_register_tree_device(node_t *node, dev_tree_t *tree)706 /** Create devmap path and name for the function. */ 707 void devmap_register_tree_function(fun_node_t *fun, dev_tree_t *tree) 606 708 { 607 709 char *devmap_pathname = NULL; 608 710 char *devmap_name = NULL; 609 711 610 asprintf(&devmap_name, "%s", node->pathname);712 asprintf(&devmap_name, "%s", fun->pathname); 611 713 if (devmap_name == NULL) 612 714 return; … … 621 723 } 622 724 623 devmap_device_register(devmap_pathname, &node->devmap_handle); 624 625 tree_add_devmap_device(tree, node); 725 devmap_device_register_with_iface(devmap_pathname, 726 &fun->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP); 727 728 tree_add_devmap_function(tree, fun); 626 729 627 730 free(devmap_name); … … 629 732 } 630 733 631 632 734 /** Pass a device to running driver. 633 735 * … … 635 737 * @param node The device's node in the device tree. 636 738 */ 637 void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree) 638 { 639 printf(NAME ": add_device\n"); 640 641 ipcarg_t rc; 739 void add_device(int phone, driver_t *drv, dev_node_t *dev, dev_tree_t *tree) 740 { 741 /* 742 * We do not expect to have driver's mutex locked as we do not 743 * access any structures that would affect driver_t. 744 */ 745 log_msg(LVL_DEBUG, "add_device(drv=\"%s\", dev=\"%s\")", 746 drv->name, dev->pfun->name); 747 748 sysarg_t rc; 642 749 ipc_call_t answer; 643 750 644 751 /* Send the device to the driver. */ 645 aid_t req = async_send_1(phone, DRIVER_ADD_DEVICE, node->handle, 646 &answer); 752 devman_handle_t parent_handle; 753 if (dev->pfun) { 754 parent_handle = dev->pfun->handle; 755 } else { 756 parent_handle = 0; 757 } 758 759 aid_t req = async_send_2(phone, DRIVER_ADD_DEVICE, dev->handle, 760 parent_handle, &answer); 647 761 648 762 /* Send the device's name to the driver. */ 649 rc = async_data_write_start(phone, node->name,650 str_size( node->name) + 1);763 rc = async_data_write_start(phone, dev->pfun->name, 764 str_size(dev->pfun->name) + 1); 651 765 if (rc != EOK) { 652 766 /* TODO handle error */ 653 767 } 654 768 655 769 /* Wait for answer from the driver. */ 656 770 async_wait_for(req, &rc); 771 657 772 switch(rc) { 658 773 case EOK: 659 node->state = DEVICE_USABLE; 660 devmap_register_tree_device(node, tree); 774 dev->state = DEVICE_USABLE; 661 775 break; 662 776 case ENOENT: 663 node->state = DEVICE_NOT_PRESENT;777 dev->state = DEVICE_NOT_PRESENT; 664 778 break; 665 779 default: 666 node->state = DEVICE_INVALID; 667 } 668 780 dev->state = DEVICE_INVALID; 781 } 782 783 dev->passed_to_driver = true; 784 669 785 return; 670 786 } … … 677 793 * successfully assigned to the device, false otherwise. 678 794 */ 679 bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree) 680 { 795 bool assign_driver(dev_node_t *dev, driver_list_t *drivers_list, 796 dev_tree_t *tree) 797 { 798 assert(dev != NULL); 799 assert(drivers_list != NULL); 800 assert(tree != NULL); 801 681 802 /* 682 803 * Find the driver which is the most suitable for handling this device. 683 804 */ 684 driver_t *drv = find_best_match_driver(drivers_list, node);805 driver_t *drv = find_best_match_driver(drivers_list, dev); 685 806 if (drv == NULL) { 686 printf(NAME ": no driver found for device '%s'.\n",687 node->pathname);807 log_msg(LVL_ERROR, "No driver found for device `%s'.", 808 dev->pfun->pathname); 688 809 return false; 689 810 } 690 811 691 812 /* Attach the driver to the device. */ 692 attach_driver(node, drv); 693 813 attach_driver(dev, drv); 814 815 fibril_mutex_lock(&drv->driver_mutex); 694 816 if (drv->state == DRIVER_NOT_STARTED) { 695 817 /* Start the driver. */ 696 818 start_driver(drv); 697 819 } 698 699 if (drv->state == DRIVER_RUNNING) { 820 bool is_running = drv->state == DRIVER_RUNNING; 821 fibril_mutex_unlock(&drv->driver_mutex); 822 823 if (is_running) { 700 824 /* Notify the driver about the new device. */ 701 int phone = ipc_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);702 if (phone > 0) {703 add_device(phone, drv, node, tree);704 ipc_hangup(phone);825 int phone = async_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0); 826 if (phone >= 0) { 827 add_device(phone, drv, dev, tree); 828 async_hangup(phone); 705 829 } 706 830 } … … 719 843 bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list) 720 844 { 721 printf(NAME ": init_device_tree.\n");845 log_msg(LVL_DEBUG, "init_device_tree()"); 722 846 723 847 tree->current_handle = 0; … … 725 849 hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1, 726 850 &devman_devices_ops); 727 hash_table_create(&tree->devmap_devices, DEVICE_BUCKETS, 1, 851 hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1, 852 &devman_functions_ops); 853 hash_table_create(&tree->devmap_functions, DEVICE_BUCKETS, 1, 728 854 &devmap_devices_ops); 729 855 730 856 fibril_rwlock_initialize(&tree->rwlock); 731 857 732 /* Create root node and add itto the device tree. */733 if (!create_root_node (tree))858 /* Create root function and root device and add them to the device tree. */ 859 if (!create_root_nodes(tree)) 734 860 return false; 735 861 736 862 /* Find suitable driver and start it. */ 737 return assign_driver(tree->root_node , drivers_list, tree);863 return assign_driver(tree->root_node->child, drivers_list, tree); 738 864 } 739 865 … … 744 870 * @return A device node structure. 745 871 */ 746 node_t *create_dev_node(void)747 { 748 node_t *res = malloc(sizeof(node_t));872 dev_node_t *create_dev_node(void) 873 { 874 dev_node_t *res = malloc(sizeof(dev_node_t)); 749 875 750 876 if (res != NULL) { 751 memset(res, 0, sizeof( node_t));752 list_initialize(&res-> children);753 li st_initialize(&res->match_ids.ids);754 li st_initialize(&res->classes);877 memset(res, 0, sizeof(dev_node_t)); 878 list_initialize(&res->functions); 879 link_initialize(&res->driver_devices); 880 link_initialize(&res->devman_dev); 755 881 } 756 882 … … 762 888 * @param node The device node structure. 763 889 */ 764 void delete_dev_node(node_t *node) 765 { 766 assert(list_empty(&node->children)); 767 assert(node->parent == NULL); 768 assert(node->drv == NULL); 769 770 clean_match_ids(&node->match_ids); 771 free_not_null(node->name); 772 free_not_null(node->pathname); 773 free(node); 890 void delete_dev_node(dev_node_t *dev) 891 { 892 assert(list_empty(&dev->functions)); 893 assert(dev->pfun == NULL); 894 assert(dev->drv == NULL); 895 896 free(dev); 774 897 } 775 898 776 899 /** Find the device node structure of the device witch has the specified handle. 777 *778 * Device tree's rwlock should be held at least for reading.779 900 * 780 901 * @param tree The device tree where we look for the device node. … … 782 903 * @return The device node. 783 904 */ 784 node_t *find_dev_node_no_lock(dev_tree_t *tree, device_handle_t handle)905 dev_node_t *find_dev_node_no_lock(dev_tree_t *tree, devman_handle_t handle) 785 906 { 786 907 unsigned long key = handle; 787 link_t *link = hash_table_find(&tree->devman_devices, &key); 788 return hash_table_get_instance(link, node_t, devman_link); 908 link_t *link; 909 910 assert(fibril_rwlock_is_locked(&tree->rwlock)); 911 912 link = hash_table_find(&tree->devman_devices, &key); 913 return hash_table_get_instance(link, dev_node_t, devman_dev); 789 914 } 790 915 … … 795 920 * @return The device node. 796 921 */ 797 node_t *find_dev_node(dev_tree_t *tree, device_handle_t handle)798 { 799 node_t *node= NULL;922 dev_node_t *find_dev_node(dev_tree_t *tree, devman_handle_t handle) 923 { 924 dev_node_t *dev = NULL; 800 925 801 926 fibril_rwlock_read_lock(&tree->rwlock); 802 node= find_dev_node_no_lock(tree, handle);927 dev = find_dev_node_no_lock(tree, handle); 803 928 fibril_rwlock_read_unlock(&tree->rwlock); 804 929 805 return node; 806 } 807 930 return dev; 931 } 932 933 /* Function nodes */ 934 935 /** Create a new function node. 936 * 937 * @return A function node structure. 938 */ 939 fun_node_t *create_fun_node(void) 940 { 941 fun_node_t *res = malloc(sizeof(fun_node_t)); 942 943 if (res != NULL) { 944 memset(res, 0, sizeof(fun_node_t)); 945 link_initialize(&res->dev_functions); 946 list_initialize(&res->match_ids.ids); 947 list_initialize(&res->classes); 948 link_initialize(&res->devman_fun); 949 link_initialize(&res->devmap_fun); 950 } 951 952 return res; 953 } 954 955 /** Delete a function node. 956 * 957 * @param fun The device node structure. 958 */ 959 void delete_fun_node(fun_node_t *fun) 960 { 961 assert(fun->dev == NULL); 962 assert(fun->child == NULL); 963 964 clean_match_ids(&fun->match_ids); 965 free_not_null(fun->name); 966 free_not_null(fun->pathname); 967 free(fun); 968 } 969 970 /** Find the function node with the specified handle. 971 * 972 * @param tree The device tree where we look for the device node. 973 * @param handle The handle of the function. 974 * @return The function node. 975 */ 976 fun_node_t *find_fun_node_no_lock(dev_tree_t *tree, devman_handle_t handle) 977 { 978 unsigned long key = handle; 979 link_t *link; 980 981 assert(fibril_rwlock_is_locked(&tree->rwlock)); 982 983 link = hash_table_find(&tree->devman_functions, &key); 984 if (link == NULL) 985 return NULL; 986 987 return hash_table_get_instance(link, fun_node_t, devman_fun); 988 } 989 990 /** Find the function node with the specified handle. 991 * 992 * @param tree The device tree where we look for the device node. 993 * @param handle The handle of the function. 994 * @return The function node. 995 */ 996 fun_node_t *find_fun_node(dev_tree_t *tree, devman_handle_t handle) 997 { 998 fun_node_t *fun = NULL; 999 1000 fibril_rwlock_read_lock(&tree->rwlock); 1001 fun = find_fun_node_no_lock(tree, handle); 1002 fibril_rwlock_read_unlock(&tree->rwlock); 1003 1004 return fun; 1005 } 808 1006 809 1007 /** Create and set device's full path in device tree. … … 814 1012 * resources etc.). 815 1013 */ 816 static bool set_ dev_path(node_t *node,node_t *parent)817 { 818 assert( node->name != NULL);819 820 size_t pathsize = (str_size( node->name) + 1);1014 static bool set_fun_path(fun_node_t *fun, fun_node_t *parent) 1015 { 1016 assert(fun->name != NULL); 1017 1018 size_t pathsize = (str_size(fun->name) + 1); 821 1019 if (parent != NULL) 822 1020 pathsize += str_size(parent->pathname) + 1; 823 1021 824 node->pathname = (char *) malloc(pathsize);825 if ( node->pathname == NULL) {826 printf(NAME ": failed to allocate device path.\n");1022 fun->pathname = (char *) malloc(pathsize); 1023 if (fun->pathname == NULL) { 1024 log_msg(LVL_ERROR, "Failed to allocate device path."); 827 1025 return false; 828 1026 } 829 1027 830 1028 if (parent != NULL) { 831 str_cpy( node->pathname, pathsize, parent->pathname);832 str_append( node->pathname, pathsize, "/");833 str_append( node->pathname, pathsize, node->name);1029 str_cpy(fun->pathname, pathsize, parent->pathname); 1030 str_append(fun->pathname, pathsize, "/"); 1031 str_append(fun->pathname, pathsize, fun->name); 834 1032 } else { 835 str_cpy( node->pathname, pathsize, node->name);1033 str_cpy(fun->pathname, pathsize, fun->name); 836 1034 } 837 1035 … … 840 1038 841 1039 /** Insert new device into device tree. 842 *843 * The device tree's rwlock should be already held exclusively when calling this844 * function.845 1040 * 846 1041 * @param tree The device tree. … … 852 1047 * etc.). 853 1048 */ 854 bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name, 855 node_t *parent) 856 { 857 assert(node != NULL); 1049 bool insert_dev_node(dev_tree_t *tree, dev_node_t *dev, fun_node_t *pfun) 1050 { 1051 assert(dev != NULL); 858 1052 assert(tree != NULL); 859 assert(dev_name != NULL); 860 861 node->name = dev_name; 862 if (!set_dev_path(node, parent)) { 863 fibril_rwlock_write_unlock(&tree->rwlock); 1053 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1054 1055 log_msg(LVL_DEBUG, "insert_dev_node(dev=%p, pfun=%p [\"%s\"])", 1056 dev, pfun, pfun->pathname); 1057 1058 /* Add the node to the handle-to-node map. */ 1059 dev->handle = ++tree->current_handle; 1060 unsigned long key = dev->handle; 1061 hash_table_insert(&tree->devman_devices, &key, &dev->devman_dev); 1062 1063 /* Add the node to the list of its parent's children. */ 1064 dev->pfun = pfun; 1065 pfun->child = dev; 1066 1067 return true; 1068 } 1069 1070 /** Insert new function into device tree. 1071 * 1072 * @param tree The device tree. 1073 * @param node The newly added function node. 1074 * @param dev_name The name of the newly added function. 1075 * @param parent Owning device node. 1076 * 1077 * @return True on success, false otherwise (insufficient resources 1078 * etc.). 1079 */ 1080 bool insert_fun_node(dev_tree_t *tree, fun_node_t *fun, char *fun_name, 1081 dev_node_t *dev) 1082 { 1083 fun_node_t *pfun; 1084 1085 assert(fun != NULL); 1086 assert(tree != NULL); 1087 assert(fun_name != NULL); 1088 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1089 1090 /* 1091 * The root function is a special case, it does not belong to any 1092 * device so for the root function dev == NULL. 1093 */ 1094 pfun = (dev != NULL) ? dev->pfun : NULL; 1095 1096 fun->name = fun_name; 1097 if (!set_fun_path(fun, pfun)) { 864 1098 return false; 865 1099 } 866 1100 867 1101 /* Add the node to the handle-to-node map. */ 868 node->handle = ++tree->current_handle;869 unsigned long key = node->handle;870 hash_table_insert(&tree->devman_ devices, &key, &node->devman_link);1102 fun->handle = ++tree->current_handle; 1103 unsigned long key = fun->handle; 1104 hash_table_insert(&tree->devman_functions, &key, &fun->devman_fun); 871 1105 872 1106 /* Add the node to the list of its parent's children. */ 873 node->parent = parent;874 if ( parent!= NULL)875 list_append(& node->sibling, &parent->children);1107 fun->dev = dev; 1108 if (dev != NULL) 1109 list_append(&fun->dev_functions, &dev->functions); 876 1110 877 1111 return true; 878 1112 } 879 1113 880 /** Find devicenode with a specified path in the device tree.1114 /** Find function node with a specified path in the device tree. 881 1115 * 882 * @param path The path of the devicenode in the device tree.1116 * @param path The path of the function node in the device tree. 883 1117 * @param tree The device tree. 884 * @return The devicenode if it is present in the tree, NULL1118 * @return The function node if it is present in the tree, NULL 885 1119 * otherwise. 886 1120 */ 887 node_t *find_dev_node_by_path(dev_tree_t *tree, char *path) 888 { 1121 fun_node_t *find_fun_node_by_path(dev_tree_t *tree, char *path) 1122 { 1123 assert(path != NULL); 1124 1125 bool is_absolute = path[0] == '/'; 1126 if (!is_absolute) { 1127 return NULL; 1128 } 1129 889 1130 fibril_rwlock_read_lock(&tree->rwlock); 890 1131 891 node_t *dev= tree->root_node;1132 fun_node_t *fun = tree->root_node; 892 1133 /* 893 * Relative path to the devicefrom its parent (but with '/' at the1134 * Relative path to the function from its parent (but with '/' at the 894 1135 * beginning) 895 1136 */ 896 1137 char *rel_path = path; 897 1138 char *next_path_elem = NULL; 898 bool cont = (rel_path[0] == '/');899 900 while (cont && dev!= NULL) {1139 bool cont = true; 1140 1141 while (cont && fun != NULL) { 901 1142 next_path_elem = get_path_elem_end(rel_path + 1); 902 1143 if (next_path_elem[0] == '/') { … … 907 1148 } 908 1149 909 dev = find_node_child(dev, rel_path + 1);1150 fun = find_node_child(fun, rel_path + 1); 910 1151 911 1152 if (cont) { … … 918 1159 fibril_rwlock_read_unlock(&tree->rwlock); 919 1160 920 return dev;921 } 922 923 /** Find child device node with a specified name.1161 return fun; 1162 } 1163 1164 /** Find function with a specified name belonging to given device. 924 1165 * 925 1166 * Device tree rwlock should be held at least for reading. 926 1167 * 927 * @param parent The parent device node. 928 * @param name The name of the child device node. 929 * @return The child device node. 930 */ 931 node_t *find_node_child(node_t *parent, const char *name) 932 { 933 node_t *dev; 1168 * @param dev Device the function belongs to. 1169 * @param name Function name (not path). 1170 * @return Function node. 1171 * @retval NULL No function with given name. 1172 */ 1173 fun_node_t *find_fun_node_in_device(dev_node_t *dev, const char *name) 1174 { 1175 assert(dev != NULL); 1176 assert(name != NULL); 1177 1178 fun_node_t *fun; 934 1179 link_t *link; 935 936 link = parent->children.next; 937 938 while (link != &parent->children) { 939 dev = list_get_instance(link, node_t, sibling); 940 941 if (str_cmp(name, dev->name) == 0) 942 return dev; 943 944 link = link->next; 945 } 946 1180 1181 for (link = dev->functions.next; 1182 link != &dev->functions; 1183 link = link->next) { 1184 fun = list_get_instance(link, fun_node_t, dev_functions); 1185 1186 if (str_cmp(name, fun->name) == 0) 1187 return fun; 1188 } 1189 947 1190 return NULL; 1191 } 1192 1193 /** Find function node by its class name and index. */ 1194 fun_node_t *find_fun_node_by_class(class_list_t *class_list, 1195 const char *class_name, const char *dev_name) 1196 { 1197 assert(class_list != NULL); 1198 assert(class_name != NULL); 1199 assert(dev_name != NULL); 1200 1201 fibril_rwlock_read_lock(&class_list->rwlock); 1202 1203 dev_class_t *cl = find_dev_class_no_lock(class_list, class_name); 1204 if (cl == NULL) { 1205 fibril_rwlock_read_unlock(&class_list->rwlock); 1206 return NULL; 1207 } 1208 1209 dev_class_info_t *dev = find_dev_in_class(cl, dev_name); 1210 if (dev == NULL) { 1211 fibril_rwlock_read_unlock(&class_list->rwlock); 1212 return NULL; 1213 } 1214 1215 fun_node_t *fun = dev->fun; 1216 1217 fibril_rwlock_read_unlock(&class_list->rwlock); 1218 1219 return fun; 1220 } 1221 1222 1223 /** Find child function node with a specified name. 1224 * 1225 * Device tree rwlock should be held at least for reading. 1226 * 1227 * @param parent The parent function node. 1228 * @param name The name of the child function. 1229 * @return The child function node. 1230 */ 1231 fun_node_t *find_node_child(fun_node_t *pfun, const char *name) 1232 { 1233 return find_fun_node_in_device(pfun->child, name); 948 1234 } 949 1235 … … 977 1263 978 1264 info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t)); 979 if (info != NULL) 1265 if (info != NULL) { 980 1266 memset(info, 0, sizeof(dev_class_info_t)); 1267 link_initialize(&info->dev_classes); 1268 link_initialize(&info->devmap_link); 1269 link_initialize(&info->link); 1270 } 981 1271 982 1272 return info; … … 1014 1304 1015 1305 size_t idx = get_new_class_dev_idx(cl); 1016 asprintf(&dev_name, "%s% d", base_name, idx);1306 asprintf(&dev_name, "%s%zu", base_name, idx); 1017 1307 1018 1308 return dev_name; 1019 1309 } 1020 1310 1021 /** Add the device to the class.1311 /** Add the device function to the class. 1022 1312 * 1023 1313 * The device may be added to multiple classes and a class may contain multiple … … 1032 1322 * with the class. 1033 1323 */ 1034 dev_class_info_t *add_ device_to_class(node_t *dev, dev_class_t *cl,1324 dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl, 1035 1325 const char *base_dev_name) 1036 1326 { 1037 dev_class_info_t *info = create_dev_class_info(); 1327 dev_class_info_t *info; 1328 1329 assert(fun != NULL); 1330 assert(cl != NULL); 1331 1332 info = create_dev_class_info(); 1333 1038 1334 1039 1335 if (info != NULL) { 1040 1336 info->dev_class = cl; 1041 info-> dev = dev;1337 info->fun = fun; 1042 1338 1043 1339 /* Add the device to the class. */ … … 1047 1343 1048 1344 /* Add the class to the device. */ 1049 list_append(&info->dev_classes, & dev->classes);1345 list_append(&info->dev_classes, &fun->classes); 1050 1346 1051 1347 /* Create unique name for the device within the class. */ … … 1083 1379 while (link != &class_list->classes) { 1084 1380 cl = list_get_instance(link, dev_class_t, link); 1085 if (str_cmp(cl->name, class_name) == 0) 1381 if (str_cmp(cl->name, class_name) == 0) { 1086 1382 return cl; 1383 } 1384 link = link->next; 1087 1385 } 1088 1386 … … 1093 1391 { 1094 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 link_t *link; 1401 for (link = dev_class->devices.next; 1402 link != &dev_class->devices; 1403 link = link->next) { 1404 dev_class_info_t *dev = list_get_instance(link, 1405 dev_class_info_t, link); 1406 1407 if (str_cmp(dev->dev_name, dev_name) == 0) { 1408 return dev; 1409 } 1410 } 1411 1412 return NULL; 1095 1413 } 1096 1414 … … 1099 1417 list_initialize(&class_list->classes); 1100 1418 fibril_rwlock_initialize(&class_list->rwlock); 1101 hash_table_create(&class_list->devmap_ devices, DEVICE_BUCKETS, 1,1102 &devmap_devices_ ops);1419 hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1, 1420 &devmap_devices_class_ops); 1103 1421 } 1104 1422 … … 1106 1424 /* Devmap devices */ 1107 1425 1108 node_t *find_devmap_tree_device(dev_tree_t *tree, dev_handle_t devmap_handle)1109 { 1110 node_t *dev= NULL;1426 fun_node_t *find_devmap_tree_function(dev_tree_t *tree, devmap_handle_t devmap_handle) 1427 { 1428 fun_node_t *fun = NULL; 1111 1429 link_t *link; 1112 1430 unsigned long key = (unsigned long) devmap_handle; 1113 1431 1114 1432 fibril_rwlock_read_lock(&tree->rwlock); 1115 link = hash_table_find(&tree->devmap_ devices, &key);1433 link = hash_table_find(&tree->devmap_functions, &key); 1116 1434 if (link != NULL) 1117 dev = hash_table_get_instance(link, node_t, devmap_link);1435 fun = hash_table_get_instance(link, fun_node_t, devmap_fun); 1118 1436 fibril_rwlock_read_unlock(&tree->rwlock); 1119 1437 1120 return dev;1121 } 1122 1123 node_t *find_devmap_class_device(class_list_t *classes,1124 dev _handle_t devmap_handle)1125 { 1126 node_t *dev= NULL;1438 return fun; 1439 } 1440 1441 fun_node_t *find_devmap_class_function(class_list_t *classes, 1442 devmap_handle_t devmap_handle) 1443 { 1444 fun_node_t *fun = NULL; 1127 1445 dev_class_info_t *cli; 1128 1446 link_t *link; … … 1130 1448 1131 1449 fibril_rwlock_read_lock(&classes->rwlock); 1132 link = hash_table_find(&classes->devmap_ devices, &key);1450 link = hash_table_find(&classes->devmap_functions, &key); 1133 1451 if (link != NULL) { 1134 1452 cli = hash_table_get_instance(link, dev_class_info_t, 1135 1453 devmap_link); 1136 dev = cli->dev;1454 fun = cli->fun; 1137 1455 } 1138 1456 fibril_rwlock_read_unlock(&classes->rwlock); 1139 1457 1140 return dev;1141 } 1142 1143 void class_add_devmap_ device(class_list_t *class_list, dev_class_info_t *cli)1458 return fun; 1459 } 1460 1461 void class_add_devmap_function(class_list_t *class_list, dev_class_info_t *cli) 1144 1462 { 1145 1463 unsigned long key = (unsigned long) cli->devmap_handle; 1146 1464 1147 1465 fibril_rwlock_write_lock(&class_list->rwlock); 1148 hash_table_insert(&class_list->devmap_ devices, &key, &cli->devmap_link);1466 hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link); 1149 1467 fibril_rwlock_write_unlock(&class_list->rwlock); 1150 } 1151 1152 void tree_add_devmap_device(dev_tree_t *tree, node_t *node) 1153 { 1154 unsigned long key = (unsigned long) node->devmap_handle; 1468 1469 assert(find_devmap_class_function(class_list, cli->devmap_handle) != NULL); 1470 } 1471 1472 void tree_add_devmap_function(dev_tree_t *tree, fun_node_t *fun) 1473 { 1474 unsigned long key = (unsigned long) fun->devmap_handle; 1155 1475 fibril_rwlock_write_lock(&tree->rwlock); 1156 hash_table_insert(&tree->devmap_ devices, &key, &node->devmap_link);1476 hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun); 1157 1477 fibril_rwlock_write_unlock(&tree->rwlock); 1158 1478 }
Note:
See TracChangeset
for help on using the changeset viewer.
