Changeset b5e68c8 in mainline for uspace/srv/devman/devman.c
- Timestamp:
- 2011-05-12T16:49:44Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f36787d7
- Parents:
- e80329d6 (diff), 750636a (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
re80329d6 rb5e68c8 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> 40 #include <str_error.h> 41 #include <stdio.h> 39 42 40 43 #include "devman.h" 44 45 fun_node_t *find_node_child(fun_node_t *parent, const char *name); 41 46 42 47 /* hash table operations */ … … 50 55 link_t *item) 51 56 { 52 node_t *dev = hash_table_get_instance(item, node_t, devman_link);53 return (dev->handle == (dev ice_handle_t) key[0]);54 } 55 56 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, 57 62 link_t *item) 58 63 { 59 node_t *dev = hash_table_get_instance(item, node_t, devmap_link); 60 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]); 61 83 } 62 84 … … 71 93 }; 72 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 73 101 static hash_table_operations_t devmap_devices_ops = { 74 102 .hash = devices_hash, 75 .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, 76 110 .remove_callback = devices_remove_callback 77 111 }; … … 114 148 fibril_mutex_unlock(&drivers_list->drivers_mutex); 115 149 116 printf(NAME": the '%s' driverwas added to the list of available "117 "drivers. \n", drv->name);150 log_msg(LVL_NOTE, "Driver `%s' was added to the list of available " 151 "drivers.", drv->name); 118 152 } 119 153 … … 205 239 bool read_match_ids(const char *conf_path, match_id_list_t *ids) 206 240 { 207 printf(NAME ": read_match_ids conf_path = %s.\n", conf_path);241 log_msg(LVL_DEBUG, "read_match_ids(conf_path=\"%s\")", conf_path); 208 242 209 243 bool suc = false; … … 215 249 fd = open(conf_path, O_RDONLY); 216 250 if (fd < 0) { 217 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)); 218 253 goto cleanup; 219 254 } … … 223 258 lseek(fd, 0, SEEK_SET); 224 259 if (len == 0) { 225 printf(NAME ": configuration file '%s' is empty.\n", conf_path); 260 log_msg(LVL_ERROR, "Configuration file '%s' is empty.", 261 conf_path); 226 262 goto cleanup; 227 263 } … … 229 265 buf = malloc(len + 1); 230 266 if (buf == NULL) { 231 printf(NAME ": memory allocation failed when parsing file "232 "'%s'. \n", conf_path);267 log_msg(LVL_ERROR, "Memory allocation failed when parsing file " 268 "'%s'.", conf_path); 233 269 goto cleanup; 234 270 } 235 271 236 if (read(fd, buf, len) <= 0) { 237 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); 238 275 goto cleanup; 239 276 } 240 buf[ len] = 0;277 buf[read_bytes] = 0; 241 278 242 279 suc = parse_match_ids(buf, ids); … … 273 310 bool get_driver_info(const char *base_path, const char *name, driver_t *drv) 274 311 { 275 printf(NAME ": get_driver_info base_path = %s, name = %s.\n",312 log_msg(LVL_DEBUG, "get_driver_info(base_path=\"%s\", name=\"%s\")", 276 313 base_path, name); 277 314 … … 305 342 struct stat s; 306 343 if (stat(drv->binary_path, &s) == ENOENT) { /* FIXME!! */ 307 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); 308 346 goto cleanup; 309 347 } … … 332 370 int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path) 333 371 { 334 printf(NAME ": lookup_available_drivers, dir = %s \n", dir_path);372 log_msg(LVL_DEBUG, "lookup_available_drivers(dir=\"%s\")", dir_path); 335 373 336 374 int drv_cnt = 0; … … 356 394 } 357 395 358 /** Create root device node in the device tree.396 /** Create root device and function node in the device tree. 359 397 * 360 398 * @param tree The device tree. 361 399 * @return True on success, false otherwise. 362 400 */ 363 bool create_root_node(dev_tree_t *tree) 364 { 365 node_t *node; 366 367 printf(NAME ": create_root_node\n"); 368 369 node = create_dev_node(); 370 if (node != NULL) { 371 insert_dev_node(tree, node, clone_string(""), NULL); 372 match_id_t *id = create_match_id(); 373 id->id = clone_string("root"); 374 id->score = 100; 375 add_match_id(&node->match_ids, id); 376 tree->root_node = node; 377 } 378 379 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; 380 444 } 381 445 … … 395 459 * is found. 396 460 */ 397 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) 398 462 { 399 463 driver_t *best_drv = NULL, *drv = NULL; … … 423 487 * @param drv The driver. 424 488 */ 425 void attach_driver( node_t *node, driver_t *drv)426 { 427 printf(NAME ": attach_driver %s to device %s\n",428 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); 429 493 430 494 fibril_mutex_lock(&drv->driver_mutex); 431 495 432 node->drv = drv;433 list_append(& node->driver_devices, &drv->devices);496 dev->drv = drv; 497 list_append(&dev->driver_devices, &drv->devices); 434 498 435 499 fibril_mutex_unlock(&drv->driver_mutex); … … 437 501 438 502 /** Start a driver 439 *440 * The driver's mutex is assumed to be locked.441 503 * 442 504 * @param drv The driver's structure. … … 446 508 bool start_driver(driver_t *drv) 447 509 { 448 printf(NAME ": start_driver '%s'\n", drv->name); 449 450 const char *argv[2]; 451 452 argv[0] = drv->name; 453 argv[1] = NULL; 454 455 int err; 456 if (task_spawn(drv->binary_path, argv, &err) == 0) { 457 printf(NAME ": error spawning %s, errno = %d\n", 458 drv->name, err); 510 int rc; 511 512 assert(fibril_mutex_is_locked(&drv->driver_mutex)); 513 514 log_msg(LVL_DEBUG, "start_driver(drv=\"%s\")", drv->name); 515 516 rc = task_spawnl(NULL, drv->binary_path, drv->binary_path, NULL); 517 if (rc != EOK) { 518 log_msg(LVL_ERROR, "Spawning driver `%s' (%s) failed: %s.", 519 drv->name, drv->binary_path, str_error(rc)); 459 520 return false; 460 521 } … … 495 556 } 496 557 497 /** Remember the driver's phone.498 *499 * @param driver The driver.500 * @param phone The phone to the driver.501 */502 void set_driver_phone(driver_t *driver, ipcarg_t phone)503 {504 fibril_mutex_lock(&driver->driver_mutex);505 assert(driver->state == DRIVER_STARTING);506 driver->phone = phone;507 fibril_mutex_unlock(&driver->driver_mutex);508 }509 510 558 /** Notify driver about the devices to which it was assigned. 511 559 * 512 * The driver's mutex must be locked.513 *514 560 * @param driver The driver to which the devices are passed. 515 561 */ 516 562 static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree) 517 563 { 518 node_t *dev;564 dev_node_t *dev; 519 565 link_t *link; 520 566 int phone; 521 567 522 printf(NAME ": pass_devices_to_driver\n"); 523 524 phone = ipc_connect_me_to(driver->phone, DRIVER_DEVMAN, 0, 0); 525 if (phone > 0) { 526 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 */ 527 622 link = driver->devices.next; 528 while (link != &driver->devices) { 529 dev = list_get_instance(link, node_t, driver_devices); 530 add_device(phone, driver, dev, tree); 531 link = link->next; 532 } 533 534 ipc_hangup(phone); 535 } 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); 536 640 } 537 641 … … 547 651 void initialize_running_driver(driver_t *driver, dev_tree_t *tree) 548 652 { 549 printf(NAME ": initialize_running_driver\n");550 fibril_mutex_lock(&driver->driver_mutex);653 log_msg(LVL_DEBUG, "initialize_running_driver(driver=\"%s\")", 654 driver->name); 551 655 552 656 /* … … 555 659 */ 556 660 pass_devices_to_driver(driver, tree); 557 558 /* Change driver's state to running. */559 driver->state = DRIVER_RUNNING;560 561 fibril_mutex_unlock(&driver->driver_mutex);562 661 } 563 662 … … 574 673 list_initialize(&drv->devices); 575 674 fibril_mutex_initialize(&drv->driver_mutex); 675 drv->phone = -1; 576 676 } 577 677 … … 604 704 } 605 705 606 /** Create devmap path and name for the device. */607 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) 608 708 { 609 709 char *devmap_pathname = NULL; 610 710 char *devmap_name = NULL; 611 711 612 asprintf(&devmap_name, "%s", node->pathname);712 asprintf(&devmap_name, "%s", fun->pathname); 613 713 if (devmap_name == NULL) 614 714 return; … … 623 723 } 624 724 625 devmap_device_register(devmap_pathname, &node->devmap_handle); 626 627 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); 628 729 629 730 free(devmap_name); … … 631 732 } 632 733 633 634 734 /** Pass a device to running driver. 635 735 * … … 637 737 * @param node The device's node in the device tree. 638 738 */ 639 void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree) 640 { 641 printf(NAME ": add_device\n"); 642 643 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; 644 749 ipc_call_t answer; 645 750 646 751 /* Send the device to the driver. */ 647 aid_t req = async_send_1(phone, DRIVER_ADD_DEVICE, node->handle, 648 &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); 649 761 650 762 /* Send the device's name to the driver. */ 651 rc = async_data_write_start(phone, node->name,652 str_size( node->name) + 1);763 rc = async_data_write_start(phone, dev->pfun->name, 764 str_size(dev->pfun->name) + 1); 653 765 if (rc != EOK) { 654 766 /* TODO handle error */ 655 767 } 656 768 657 769 /* Wait for answer from the driver. */ 658 770 async_wait_for(req, &rc); 771 659 772 switch(rc) { 660 773 case EOK: 661 node->state = DEVICE_USABLE; 662 devmap_register_tree_device(node, tree); 774 dev->state = DEVICE_USABLE; 663 775 break; 664 776 case ENOENT: 665 node->state = DEVICE_NOT_PRESENT;777 dev->state = DEVICE_NOT_PRESENT; 666 778 break; 667 779 default: 668 node->state = DEVICE_INVALID; 669 } 670 780 dev->state = DEVICE_INVALID; 781 } 782 783 dev->passed_to_driver = true; 784 671 785 return; 672 786 } … … 679 793 * successfully assigned to the device, false otherwise. 680 794 */ 681 bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree) 682 { 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 683 802 /* 684 803 * Find the driver which is the most suitable for handling this device. 685 804 */ 686 driver_t *drv = find_best_match_driver(drivers_list, node);805 driver_t *drv = find_best_match_driver(drivers_list, dev); 687 806 if (drv == NULL) { 688 printf(NAME ": no driver found for device '%s'.\n",689 node->pathname);807 log_msg(LVL_ERROR, "No driver found for device `%s'.", 808 dev->pfun->pathname); 690 809 return false; 691 810 } 692 811 693 812 /* Attach the driver to the device. */ 694 attach_driver(node, drv); 695 813 attach_driver(dev, drv); 814 815 fibril_mutex_lock(&drv->driver_mutex); 696 816 if (drv->state == DRIVER_NOT_STARTED) { 697 817 /* Start the driver. */ 698 818 start_driver(drv); 699 819 } 700 701 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) { 702 824 /* Notify the driver about the new device. */ 703 int phone = ipc_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0);704 if (phone > 0) {705 add_device(phone, drv, node, tree);706 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); 707 829 } 708 830 } … … 721 843 bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list) 722 844 { 723 printf(NAME ": init_device_tree.\n");845 log_msg(LVL_DEBUG, "init_device_tree()"); 724 846 725 847 tree->current_handle = 0; … … 727 849 hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1, 728 850 &devman_devices_ops); 729 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, 730 854 &devmap_devices_ops); 731 855 732 856 fibril_rwlock_initialize(&tree->rwlock); 733 857 734 /* Create root node and add itto the device tree. */735 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)) 736 860 return false; 737 861 738 862 /* Find suitable driver and start it. */ 739 return assign_driver(tree->root_node , drivers_list, tree);863 return assign_driver(tree->root_node->child, drivers_list, tree); 740 864 } 741 865 … … 746 870 * @return A device node structure. 747 871 */ 748 node_t *create_dev_node(void)749 { 750 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)); 751 875 752 876 if (res != NULL) { 753 memset(res, 0, sizeof( node_t));754 list_initialize(&res-> children);755 li st_initialize(&res->match_ids.ids);756 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); 757 881 } 758 882 … … 764 888 * @param node The device node structure. 765 889 */ 766 void delete_dev_node(node_t *node) 767 { 768 assert(list_empty(&node->children)); 769 assert(node->parent == NULL); 770 assert(node->drv == NULL); 771 772 clean_match_ids(&node->match_ids); 773 free_not_null(node->name); 774 free_not_null(node->pathname); 775 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); 776 897 } 777 898 778 899 /** Find the device node structure of the device witch has the specified handle. 779 *780 * Device tree's rwlock should be held at least for reading.781 900 * 782 901 * @param tree The device tree where we look for the device node. … … 784 903 * @return The device node. 785 904 */ 786 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) 787 906 { 788 907 unsigned long key = handle; 789 link_t *link = hash_table_find(&tree->devman_devices, &key); 790 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); 791 914 } 792 915 … … 797 920 * @return The device node. 798 921 */ 799 node_t *find_dev_node(dev_tree_t *tree, device_handle_t handle)800 { 801 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; 802 925 803 926 fibril_rwlock_read_lock(&tree->rwlock); 804 node= find_dev_node_no_lock(tree, handle);927 dev = find_dev_node_no_lock(tree, handle); 805 928 fibril_rwlock_read_unlock(&tree->rwlock); 806 929 807 return node; 808 } 809 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 } 810 1006 811 1007 /** Create and set device's full path in device tree. … … 816 1012 * resources etc.). 817 1013 */ 818 static bool set_ dev_path(node_t *node,node_t *parent)819 { 820 assert( node->name != NULL);821 822 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); 823 1019 if (parent != NULL) 824 1020 pathsize += str_size(parent->pathname) + 1; 825 1021 826 node->pathname = (char *) malloc(pathsize);827 if ( node->pathname == NULL) {828 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."); 829 1025 return false; 830 1026 } 831 1027 832 1028 if (parent != NULL) { 833 str_cpy( node->pathname, pathsize, parent->pathname);834 str_append( node->pathname, pathsize, "/");835 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); 836 1032 } else { 837 str_cpy( node->pathname, pathsize, node->name);1033 str_cpy(fun->pathname, pathsize, fun->name); 838 1034 } 839 1035 … … 842 1038 843 1039 /** Insert new device into device tree. 844 *845 * The device tree's rwlock should be already held exclusively when calling this846 * function.847 1040 * 848 1041 * @param tree The device tree. … … 854 1047 * etc.). 855 1048 */ 856 bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name, 857 node_t *parent) 858 { 859 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); 860 1052 assert(tree != NULL); 861 assert(dev_name != NULL); 862 863 node->name = dev_name; 864 if (!set_dev_path(node, parent)) { 865 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)) { 866 1098 return false; 867 1099 } 868 1100 869 1101 /* Add the node to the handle-to-node map. */ 870 node->handle = ++tree->current_handle;871 unsigned long key = node->handle;872 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); 873 1105 874 1106 /* Add the node to the list of its parent's children. */ 875 node->parent = parent;876 if ( parent!= NULL)877 list_append(& node->sibling, &parent->children);1107 fun->dev = dev; 1108 if (dev != NULL) 1109 list_append(&fun->dev_functions, &dev->functions); 878 1110 879 1111 return true; 880 1112 } 881 1113 882 /** Find devicenode with a specified path in the device tree.1114 /** Find function node with a specified path in the device tree. 883 1115 * 884 * @param path The path of the devicenode in the device tree.1116 * @param path The path of the function node in the device tree. 885 1117 * @param tree The device tree. 886 * @return The devicenode if it is present in the tree, NULL1118 * @return The function node if it is present in the tree, NULL 887 1119 * otherwise. 888 1120 */ 889 node_t *find_dev_node_by_path(dev_tree_t *tree, char *path) 890 { 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 891 1130 fibril_rwlock_read_lock(&tree->rwlock); 892 1131 893 node_t *dev= tree->root_node;1132 fun_node_t *fun = tree->root_node; 894 1133 /* 895 * Relative path to the devicefrom its parent (but with '/' at the1134 * Relative path to the function from its parent (but with '/' at the 896 1135 * beginning) 897 1136 */ 898 1137 char *rel_path = path; 899 1138 char *next_path_elem = NULL; 900 bool cont = (rel_path[0] == '/');901 902 while (cont && dev!= NULL) {1139 bool cont = true; 1140 1141 while (cont && fun != NULL) { 903 1142 next_path_elem = get_path_elem_end(rel_path + 1); 904 1143 if (next_path_elem[0] == '/') { … … 909 1148 } 910 1149 911 dev = find_node_child(dev, rel_path + 1);1150 fun = find_node_child(fun, rel_path + 1); 912 1151 913 1152 if (cont) { … … 920 1159 fibril_rwlock_read_unlock(&tree->rwlock); 921 1160 922 return dev;923 } 924 925 /** Find child device node with a specified name.1161 return fun; 1162 } 1163 1164 /** Find function with a specified name belonging to given device. 926 1165 * 927 1166 * Device tree rwlock should be held at least for reading. 928 1167 * 929 * @param parent The parent device node. 930 * @param name The name of the child device node. 931 * @return The child device node. 932 */ 933 node_t *find_node_child(node_t *parent, const char *name) 934 { 935 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; 936 1179 link_t *link; 937 938 link = parent->children.next; 939 940 while (link != &parent->children) { 941 dev = list_get_instance(link, node_t, sibling); 942 943 if (str_cmp(name, dev->name) == 0) 944 return dev; 945 946 link = link->next; 947 } 948 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 949 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); 950 1234 } 951 1235 … … 979 1263 980 1264 info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t)); 981 if (info != NULL) 1265 if (info != NULL) { 982 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 } 983 1271 984 1272 return info; … … 1016 1304 1017 1305 size_t idx = get_new_class_dev_idx(cl); 1018 asprintf(&dev_name, "%s% d", base_name, idx);1306 asprintf(&dev_name, "%s%zu", base_name, idx); 1019 1307 1020 1308 return dev_name; 1021 1309 } 1022 1310 1023 /** Add the device to the class.1311 /** Add the device function to the class. 1024 1312 * 1025 1313 * The device may be added to multiple classes and a class may contain multiple … … 1034 1322 * with the class. 1035 1323 */ 1036 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, 1037 1325 const char *base_dev_name) 1038 1326 { 1039 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 1040 1334 1041 1335 if (info != NULL) { 1042 1336 info->dev_class = cl; 1043 info-> dev = dev;1337 info->fun = fun; 1044 1338 1045 1339 /* Add the device to the class. */ … … 1049 1343 1050 1344 /* Add the class to the device. */ 1051 list_append(&info->dev_classes, & dev->classes);1345 list_append(&info->dev_classes, &fun->classes); 1052 1346 1053 1347 /* Create unique name for the device within the class. */ … … 1085 1379 while (link != &class_list->classes) { 1086 1380 cl = list_get_instance(link, dev_class_t, link); 1087 if (str_cmp(cl->name, class_name) == 0) 1381 if (str_cmp(cl->name, class_name) == 0) { 1088 1382 return cl; 1383 } 1384 link = link->next; 1089 1385 } 1090 1386 … … 1095 1391 { 1096 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; 1097 1413 } 1098 1414 … … 1101 1417 list_initialize(&class_list->classes); 1102 1418 fibril_rwlock_initialize(&class_list->rwlock); 1103 hash_table_create(&class_list->devmap_ devices, DEVICE_BUCKETS, 1,1104 &devmap_devices_ ops);1419 hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1, 1420 &devmap_devices_class_ops); 1105 1421 } 1106 1422 … … 1108 1424 /* Devmap devices */ 1109 1425 1110 node_t *find_devmap_tree_device(dev_tree_t *tree, dev_handle_t devmap_handle)1111 { 1112 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; 1113 1429 link_t *link; 1114 1430 unsigned long key = (unsigned long) devmap_handle; 1115 1431 1116 1432 fibril_rwlock_read_lock(&tree->rwlock); 1117 link = hash_table_find(&tree->devmap_ devices, &key);1433 link = hash_table_find(&tree->devmap_functions, &key); 1118 1434 if (link != NULL) 1119 dev = hash_table_get_instance(link, node_t, devmap_link);1435 fun = hash_table_get_instance(link, fun_node_t, devmap_fun); 1120 1436 fibril_rwlock_read_unlock(&tree->rwlock); 1121 1437 1122 return dev;1123 } 1124 1125 node_t *find_devmap_class_device(class_list_t *classes,1126 dev _handle_t devmap_handle)1127 { 1128 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; 1129 1445 dev_class_info_t *cli; 1130 1446 link_t *link; … … 1132 1448 1133 1449 fibril_rwlock_read_lock(&classes->rwlock); 1134 link = hash_table_find(&classes->devmap_ devices, &key);1450 link = hash_table_find(&classes->devmap_functions, &key); 1135 1451 if (link != NULL) { 1136 1452 cli = hash_table_get_instance(link, dev_class_info_t, 1137 1453 devmap_link); 1138 dev = cli->dev;1454 fun = cli->fun; 1139 1455 } 1140 1456 fibril_rwlock_read_unlock(&classes->rwlock); 1141 1457 1142 return dev;1143 } 1144 1145 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) 1146 1462 { 1147 1463 unsigned long key = (unsigned long) cli->devmap_handle; 1148 1464 1149 1465 fibril_rwlock_write_lock(&class_list->rwlock); 1150 hash_table_insert(&class_list->devmap_ devices, &key, &cli->devmap_link);1466 hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link); 1151 1467 fibril_rwlock_write_unlock(&class_list->rwlock); 1152 } 1153 1154 void tree_add_devmap_device(dev_tree_t *tree, node_t *node) 1155 { 1156 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; 1157 1475 fibril_rwlock_write_lock(&tree->rwlock); 1158 hash_table_insert(&tree->devmap_ devices, &key, &node->devmap_link);1476 hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun); 1159 1477 fibril_rwlock_write_unlock(&tree->rwlock); 1160 1478 }
Note:
See TracChangeset
for help on using the changeset viewer.