Changeset bd5f3b7 in mainline for uspace/srv/devman/main.c
- Timestamp:
- 2011-08-21T13:07:35Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 00aece0, f1a9e87
- Parents:
- 86a34d3e (diff), a6480d5 (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/main.c
r86a34d3e rbd5f3b7 56 56 #include <ipc/driver.h> 57 57 #include <thread.h> 58 #include < devmap.h>58 #include <loc.h> 59 59 60 60 #include "devman.h" … … 64 64 static driver_list_t drivers_list; 65 65 static dev_tree_t device_tree; 66 static class_list_t class_list; 66 67 static int init_running_drv(void *drv); 67 68 68 69 /** Register running driver. */ 69 static driver_t *devman_driver_register(void) 70 { 71 ipc_call_t icall; 72 ipc_callid_t iid; 70 static driver_t *devman_driver_register(ipc_callid_t callid, ipc_call_t *call) 71 { 73 72 driver_t *driver = NULL; 73 char *drv_name = NULL; 74 74 75 75 log_msg(LVL_DEBUG, "devman_driver_register"); 76 77 iid = async_get_call(&icall);78 if (IPC_GET_IMETHOD(icall) != DEVMAN_DRIVER_REGISTER) {79 async_answer_0(iid, EREFUSED);80 return NULL;81 }82 83 char *drv_name = NULL;84 76 85 77 /* Get driver name. */ 86 78 int rc = async_data_write_accept((void **) &drv_name, true, 0, 0, 0, 0); 87 79 if (rc != EOK) { 88 async_answer_0( iid, rc);80 async_answer_0(callid, rc); 89 81 return NULL; 90 82 } … … 99 91 free(drv_name); 100 92 drv_name = NULL; 101 async_answer_0( iid, ENOENT);93 async_answer_0(callid, ENOENT); 102 94 return NULL; 103 95 } … … 113 105 driver->name); 114 106 fibril_mutex_unlock(&driver->driver_mutex); 115 async_answer_0( iid, EEXISTS);107 async_answer_0(callid, EEXISTS); 116 108 return NULL; 117 109 } … … 135 127 log_msg(LVL_DEBUG, "Creating connection to the `%s' driver.", 136 128 driver->name); 137 driver->sess = async_callback_receive(EXCHANGE_ SERIALIZE);129 driver->sess = async_callback_receive(EXCHANGE_PARALLEL); 138 130 if (!driver->sess) { 139 131 fibril_mutex_unlock(&driver->driver_mutex); 140 async_answer_0( iid, ENOTSUP);132 async_answer_0(callid, ENOTSUP); 141 133 return NULL; 142 134 } 143 144 fibril_mutex_unlock(&driver->driver_mutex);135 /* FIXME: Work around problem with callback sessions */ 136 async_sess_args_set(driver->sess, DRIVER_DEVMAN, 0, 0); 145 137 146 138 log_msg(LVL_NOTE, … … 148 140 driver->name); 149 141 150 async_answer_0(iid, EOK); 151 142 /* 143 * Initialize the driver as running (e.g. pass assigned devices to it) 144 * in a separate fibril; the separate fibril is used to enable the 145 * driver to use devman service during the driver's initialization. 146 */ 147 fid_t fid = fibril_create(init_running_drv, driver); 148 if (fid == 0) { 149 log_msg(LVL_ERROR, "Failed to create initialization fibril " \ 150 "for driver `%s'.", driver->name); 151 fibril_mutex_unlock(&driver->driver_mutex); 152 async_answer_0(callid, ENOMEM); 153 return NULL; 154 } 155 156 fibril_add_ready(fid); 157 fibril_mutex_unlock(&driver->driver_mutex); 158 159 async_answer_0(callid, EOK); 152 160 return driver; 153 161 } … … 279 287 return; 280 288 } 281 289 282 290 fun_node_t *fun = create_fun_node(); 291 fun->ftype = ftype; 292 283 293 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 284 294 fibril_rwlock_write_unlock(&tree->rwlock); … … 326 336 } 327 337 } else { 328 devmap_register_tree_function(fun, tree);338 loc_register_tree_function(fun, tree); 329 339 } 330 340 … … 333 343 } 334 344 335 static void devmap_register_class_dev(dev_class_info_t *cli) 336 { 337 /* Create devmap path and name for the device. */ 338 char *devmap_pathname = NULL; 339 340 asprintf(&devmap_pathname, "%s/%s%c%s", DEVMAP_CLASS_NAMESPACE, 341 cli->dev_class->name, DEVMAP_SEPARATOR, cli->dev_name); 342 if (devmap_pathname == NULL) 343 return; 344 345 /* 346 * Register the device by the device mapper and remember its devmap 347 * handle. 348 */ 349 devmap_device_register_with_iface(devmap_pathname, 350 &cli->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP); 351 352 /* 353 * Add device to the hash map of class devices registered by device 354 * mapper. 355 */ 356 class_add_devmap_function(&class_list, cli); 357 358 free(devmap_pathname); 359 } 360 361 static void devman_add_function_to_class(ipc_callid_t callid, ipc_call_t *call) 345 static void devman_add_function_to_cat(ipc_callid_t callid, ipc_call_t *call) 362 346 { 363 347 devman_handle_t handle = IPC_GET_ARG1(*call); 364 365 /* Get class name. */ 366 char *class_name; 367 int rc = async_data_write_accept((void **) &class_name, true, 348 category_id_t cat_id; 349 int rc; 350 351 /* Get category name. */ 352 char *cat_name; 353 rc = async_data_write_accept((void **) &cat_name, true, 368 354 0, 0, 0, 0); 369 355 if (rc != EOK) { … … 378 364 } 379 365 380 dev_class_t *cl = get_dev_class(&class_list, class_name); 381 dev_class_info_t *class_info = add_function_to_class(fun, cl, NULL); 382 383 /* Register the device's class alias by devmapper. */ 384 devmap_register_class_dev(class_info); 385 386 log_msg(LVL_NOTE, "Function `%s' added to class `%s' as `%s'.", 387 fun->pathname, class_name, class_info->dev_name); 388 366 rc = loc_category_get_id(cat_name, &cat_id, IPC_FLAG_BLOCKING); 367 if (rc == EOK) { 368 loc_service_add_to_cat(fun->service_id, cat_id); 369 } else { 370 log_msg(LVL_ERROR, "Failed adding function `%s' to category " 371 "`%s'.", fun->pathname, cat_name); 372 } 373 374 log_msg(LVL_NOTE, "Function `%s' added to category `%s'.", 375 fun->pathname, cat_name); 376 377 async_answer_0(callid, EOK); 378 } 379 380 /** Remove function. */ 381 static void devman_remove_function(ipc_callid_t callid, ipc_call_t *call) 382 { 383 devman_handle_t fun_handle = IPC_GET_ARG1(*call); 384 dev_tree_t *tree = &device_tree; 385 int rc; 386 387 fibril_rwlock_write_lock(&tree->rwlock); 388 389 fun_node_t *fun = find_fun_node_no_lock(&device_tree, fun_handle); 390 if (fun == NULL) { 391 fibril_rwlock_write_unlock(&tree->rwlock); 392 async_answer_0(callid, ENOENT); 393 return; 394 } 395 396 log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname); 397 398 if (fun->ftype == fun_inner) { 399 /* Handle possible descendants */ 400 /* TODO */ 401 log_msg(LVL_WARN, "devman_remove_function(): not handling " 402 "descendants\n"); 403 } else { 404 /* Unregister from location service */ 405 rc = loc_service_unregister(fun->service_id); 406 if (rc != EOK) { 407 log_msg(LVL_ERROR, "Failed unregistering tree service."); 408 fibril_rwlock_write_unlock(&tree->rwlock); 409 async_answer_0(callid, EIO); 410 return; 411 } 412 } 413 414 remove_fun_node(&device_tree, fun); 415 fibril_rwlock_write_unlock(&tree->rwlock); 416 delete_fun_node(fun); 417 418 log_msg(LVL_DEBUG, "devman_remove_function() succeeded."); 389 419 async_answer_0(callid, EOK); 390 420 } … … 408 438 static void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall) 409 439 { 440 client_t *client; 441 driver_t *driver; 442 410 443 /* Accept the connection. */ 411 444 async_answer_0(iid, EOK); 412 445 413 driver_t *driver = devman_driver_register(); 414 if (driver == NULL) 415 return; 416 417 /* 418 * Initialize the driver as running (e.g. pass assigned devices to it) 419 * in a separate fibril; the separate fibril is used to enable the 420 * driver to use devman service during the driver's initialization. 421 */ 422 fid_t fid = fibril_create(init_running_drv, driver); 423 if (fid == 0) { 424 log_msg(LVL_ERROR, "Failed to create initialization fibril " \ 425 "for driver `%s'.", driver->name); 426 return; 427 } 428 fibril_add_ready(fid); 446 client = async_get_client_data(); 447 if (client == NULL) { 448 log_msg(LVL_ERROR, "Failed to allocate client data."); 449 return; 450 } 429 451 430 452 while (true) { … … 435 457 break; 436 458 459 if (IPC_GET_IMETHOD(call) != DEVMAN_DRIVER_REGISTER) { 460 fibril_mutex_lock(&client->mutex); 461 driver = client->driver; 462 fibril_mutex_unlock(&client->mutex); 463 if (driver == NULL) { 464 /* First call must be to DEVMAN_DRIVER_REGISTER */ 465 async_answer_0(callid, ENOTSUP); 466 continue; 467 } 468 } 469 437 470 switch (IPC_GET_IMETHOD(call)) { 471 case DEVMAN_DRIVER_REGISTER: 472 fibril_mutex_lock(&client->mutex); 473 if (client->driver != NULL) { 474 fibril_mutex_unlock(&client->mutex); 475 async_answer_0(callid, EINVAL); 476 continue; 477 } 478 client->driver = devman_driver_register(callid, &call); 479 fibril_mutex_unlock(&client->mutex); 480 break; 438 481 case DEVMAN_ADD_FUNCTION: 439 482 devman_add_function(callid, &call); 440 483 break; 441 case DEVMAN_ADD_DEVICE_TO_CLASS: 442 devman_add_function_to_class(callid, &call); 484 case DEVMAN_ADD_DEVICE_TO_CATEGORY: 485 devman_add_function_to_cat(callid, &call); 486 break; 487 case DEVMAN_REMOVE_FUNCTION: 488 devman_remove_function(callid, &call); 443 489 break; 444 490 default: … … 473 519 } 474 520 475 /** Find handle for the device instance identified by device class name. */ 476 static void devman_function_get_handle_by_class(ipc_callid_t iid, 477 ipc_call_t *icall) 478 { 479 char *classname; 480 char *devname; 481 482 int rc = async_data_write_accept((void **) &classname, true, 0, 0, 0, 0); 483 if (rc != EOK) { 484 async_answer_0(iid, rc); 485 return; 486 } 487 rc = async_data_write_accept((void **) &devname, true, 0, 0, 0, 0); 488 if (rc != EOK) { 489 free(classname); 490 async_answer_0(iid, rc); 491 return; 492 } 493 494 495 fun_node_t *fun = find_fun_node_by_class(&class_list, 496 classname, devname); 497 498 free(classname); 499 free(devname); 500 501 if (fun == NULL) { 502 async_answer_0(iid, ENOENT); 503 return; 504 } 505 506 async_answer_1(iid, EOK, fun->handle); 507 } 508 509 /** Find device path by its handle. */ 510 static void devman_get_device_path_by_handle(ipc_callid_t iid, 511 ipc_call_t *icall) 521 /** Get device name. */ 522 static void devman_fun_get_name(ipc_callid_t iid, ipc_call_t *icall) 512 523 { 513 524 devman_handle_t handle = IPC_GET_ARG1(*icall); … … 533 544 } 534 545 546 size_t sent_length = str_size(fun->name); 547 if (sent_length > data_len) { 548 sent_length = data_len; 549 } 550 551 async_data_read_finalize(data_callid, fun->name, sent_length); 552 async_answer_0(iid, EOK); 553 554 free(buffer); 555 } 556 557 558 /** Get device path. */ 559 static void devman_fun_get_path(ipc_callid_t iid, ipc_call_t *icall) 560 { 561 devman_handle_t handle = IPC_GET_ARG1(*icall); 562 563 fun_node_t *fun = find_fun_node(&device_tree, handle); 564 if (fun == NULL) { 565 async_answer_0(iid, ENOMEM); 566 return; 567 } 568 569 ipc_callid_t data_callid; 570 size_t data_len; 571 if (!async_data_read_receive(&data_callid, &data_len)) { 572 async_answer_0(iid, EINVAL); 573 return; 574 } 575 576 void *buffer = malloc(data_len); 577 if (buffer == NULL) { 578 async_answer_0(data_callid, ENOMEM); 579 async_answer_0(iid, ENOMEM); 580 return; 581 } 582 535 583 size_t sent_length = str_size(fun->pathname); 536 584 if (sent_length > data_len) { … … 544 592 } 545 593 594 static void devman_dev_get_functions(ipc_callid_t iid, ipc_call_t *icall) 595 { 596 ipc_callid_t callid; 597 size_t size; 598 size_t act_size; 599 int rc; 600 601 if (!async_data_read_receive(&callid, &size)) { 602 async_answer_0(callid, EREFUSED); 603 async_answer_0(iid, EREFUSED); 604 return; 605 } 606 607 fibril_rwlock_read_lock(&device_tree.rwlock); 608 609 dev_node_t *dev = find_dev_node_no_lock(&device_tree, 610 IPC_GET_ARG1(*icall)); 611 if (dev == NULL) { 612 fibril_rwlock_read_unlock(&device_tree.rwlock); 613 async_answer_0(callid, ENOENT); 614 async_answer_0(iid, ENOENT); 615 return; 616 } 617 618 devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size); 619 if (hdl_buf == NULL) { 620 fibril_rwlock_read_unlock(&device_tree.rwlock); 621 async_answer_0(callid, ENOMEM); 622 async_answer_0(iid, ENOMEM); 623 return; 624 } 625 626 rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size); 627 if (rc != EOK) { 628 fibril_rwlock_read_unlock(&device_tree.rwlock); 629 async_answer_0(callid, rc); 630 async_answer_0(iid, rc); 631 return; 632 } 633 634 fibril_rwlock_read_unlock(&device_tree.rwlock); 635 636 sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size); 637 free(hdl_buf); 638 639 async_answer_1(iid, retval, act_size); 640 } 641 642 643 /** Get handle for child device of a function. */ 644 static void devman_fun_get_child(ipc_callid_t iid, ipc_call_t *icall) 645 { 646 fun_node_t *fun; 647 648 fibril_rwlock_read_lock(&device_tree.rwlock); 649 650 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 651 if (fun == NULL) { 652 fibril_rwlock_read_unlock(&device_tree.rwlock); 653 async_answer_0(iid, ENOENT); 654 return; 655 } 656 657 if (fun->child == NULL) { 658 fibril_rwlock_read_unlock(&device_tree.rwlock); 659 async_answer_0(iid, ENOENT); 660 return; 661 } 662 663 async_answer_1(iid, EOK, fun->child->handle); 664 665 fibril_rwlock_read_unlock(&device_tree.rwlock); 666 } 667 668 /** Find handle for the function instance identified by its service ID. */ 669 static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall) 670 { 671 fun_node_t *fun; 672 673 fun = find_loc_tree_function(&device_tree, IPC_GET_ARG1(*icall)); 674 675 if (fun == NULL) { 676 async_answer_0(iid, ENOENT); 677 return; 678 } 679 680 async_answer_1(iid, EOK, fun->handle); 681 } 546 682 547 683 /** Function for handling connections from a client to the device manager. */ … … 562 698 devman_function_get_handle(callid, &call); 563 699 break; 564 case DEVMAN_DEVICE_GET_HANDLE_BY_CLASS: 565 devman_function_get_handle_by_class(callid, &call); 566 break; 567 case DEVMAN_DEVICE_GET_DEVICE_PATH: 568 devman_get_device_path_by_handle(callid, &call); 700 case DEVMAN_DEV_GET_FUNCTIONS: 701 devman_dev_get_functions(callid, &call); 702 break; 703 case DEVMAN_FUN_GET_CHILD: 704 devman_fun_get_child(callid, &call); 705 break; 706 case DEVMAN_FUN_GET_NAME: 707 devman_fun_get_name(callid, &call); 708 break; 709 case DEVMAN_FUN_GET_PATH: 710 devman_fun_get_path(callid, &call); 711 break; 712 case DEVMAN_FUN_SID_TO_HANDLE: 713 devman_fun_sid_to_handle(callid, &call); 569 714 break; 570 715 default: … … 659 804 } 660 805 661 /** Function for handling connections from a client forwarded by the device662 * mapperto the device manager. */663 static void devman_connection_ devmapper(ipc_callid_t iid, ipc_call_t *icall)664 { 665 devmap_handle_t devmap_handle= IPC_GET_ARG2(*icall);806 /** Function for handling connections from a client forwarded by the location 807 * service to the device manager. */ 808 static void devman_connection_loc(ipc_callid_t iid, ipc_call_t *icall) 809 { 810 service_id_t service_id = IPC_GET_ARG2(*icall); 666 811 fun_node_t *fun; 667 812 dev_node_t *dev; 668 813 669 fun = find_devmap_tree_function(&device_tree, devmap_handle); 670 if (fun == NULL) 671 fun = find_devmap_class_function(&class_list, devmap_handle); 814 fun = find_loc_tree_function(&device_tree, service_id); 672 815 673 816 if (fun == NULL || fun->dev->drv == NULL) { 817 log_msg(LVL_WARN, "devman_connection_loc(): function " 818 "not found.\n"); 674 819 async_answer_0(iid, ENOENT); 675 820 return; … … 677 822 678 823 dev = fun->dev; 679 680 if ((dev->state != DEVICE_USABLE) || (!dev->drv->sess)) {681 async_answer_0(iid, EINVAL);682 return;683 }684 824 685 825 async_exch_t *exch = async_exchange_begin(dev->drv->sess); … … 689 829 690 830 log_msg(LVL_DEBUG, 691 "Forwarding devmapperrequest for `%s' function to driver `%s'.",831 "Forwarding loc service request for `%s' function to driver `%s'.", 692 832 fun->pathname, dev->drv->name); 693 833 } … … 696 836 static void devman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 697 837 { 698 /* Select interface. */838 /* Select port. */ 699 839 switch ((sysarg_t) (IPC_GET_ARG1(*icall))) { 700 840 case DEVMAN_DRIVER: … … 708 848 devman_forward(iid, icall, false); 709 849 break; 710 case DEVMAN_CONNECT_FROM_ DEVMAP:711 /* Someone connected through devmapnode. */712 devman_connection_ devmapper(iid, icall);850 case DEVMAN_CONNECT_FROM_LOC: 851 /* Someone connected through loc node. */ 852 devman_connection_loc(iid, icall); 713 853 break; 714 854 case DEVMAN_CONNECT_TO_PARENTS_DEVICE: … … 722 862 } 723 863 864 static void *devman_client_data_create(void) 865 { 866 client_t *client; 867 868 client = calloc(1, sizeof(client_t)); 869 if (client == NULL) 870 return NULL; 871 872 fibril_mutex_initialize(&client->mutex); 873 return client; 874 } 875 876 static void devman_client_data_destroy(void *data) 877 { 878 free(data); 879 } 880 724 881 /** Initialize device manager internal structures. */ 725 882 static bool devman_init(void) … … 743 900 } 744 901 745 init_class_list(&class_list);746 747 902 /* 748 * !!! devman_connection ... as the device manager is not a real devmap903 * !!! devman_connection ... as the device manager is not a real loc 749 904 * driver (it uses a completely different ipc protocol than an ordinary 750 * devmapdriver) forwarding a connection from client to the devman by751 * devmapperwould not work.905 * loc driver) forwarding a connection from client to the devman by 906 * location service would not work. 752 907 */ 753 devmap_driver_register(NAME, devman_connection);908 loc_server_register(NAME, devman_connection); 754 909 755 910 return true; … … 760 915 printf(NAME ": HelenOS Device Manager\n"); 761 916 762 if (log_init(NAME, LVL_ ERROR) != EOK) {917 if (log_init(NAME, LVL_WARN) != EOK) { 763 918 printf(NAME ": Error initializing logging subsystem.\n"); 764 919 return -1; … … 770 925 } 771 926 772 /* Set a handler of incomming connections. */ 927 /* Set handlers for incoming connections. */ 928 async_set_client_data_constructor(devman_client_data_create); 929 async_set_client_data_destructor(devman_client_data_destroy); 773 930 async_set_client_connection(devman_connection); 774 931
Note:
See TracChangeset
for help on using the changeset viewer.