Changes in uspace/srv/devman/main.c [422722e:9934f7d] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/main.c
r422722e r9934f7d 56 56 #include <ipc/driver.h> 57 57 #include <thread.h> 58 #include < loc.h>58 #include <devmap.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 67 static int init_running_drv(void *drv); 66 static class_list_t class_list; 68 67 69 68 /** Register running driver. */ 70 static driver_t *devman_driver_register(ipc_callid_t callid, ipc_call_t *call) 71 { 69 static driver_t *devman_driver_register(void) 70 { 71 ipc_call_t icall; 72 ipc_callid_t iid; 72 73 driver_t *driver = NULL; 74 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 73 83 char *drv_name = NULL; 74 75 log_msg(LVL_DEBUG, "devman_driver_register");76 84 77 85 /* Get driver name. */ 78 86 int rc = async_data_write_accept((void **) &drv_name, true, 0, 0, 0, 0); 79 87 if (rc != EOK) { 80 async_answer_0( callid, rc);88 async_answer_0(iid, rc); 81 89 return NULL; 82 90 } … … 91 99 free(drv_name); 92 100 drv_name = NULL; 93 async_answer_0( callid, ENOENT);101 async_answer_0(iid, ENOENT); 94 102 return NULL; 95 103 } … … 105 113 driver->name); 106 114 fibril_mutex_unlock(&driver->driver_mutex); 107 async_answer_0( callid, EEXISTS);115 async_answer_0(iid, EEXISTS); 108 116 return NULL; 109 117 } … … 127 135 log_msg(LVL_DEBUG, "Creating connection to the `%s' driver.", 128 136 driver->name); 129 driver->sess = async_callback_receive(EXCHANGE_ PARALLEL);137 driver->sess = async_callback_receive(EXCHANGE_SERIALIZE); 130 138 if (!driver->sess) { 131 139 fibril_mutex_unlock(&driver->driver_mutex); 132 async_answer_0( callid, ENOTSUP);140 async_answer_0(iid, ENOTSUP); 133 141 return NULL; 134 142 } 135 /* FIXME: Work around problem with callback sessions */136 async_sess_args_set(driver->sess, DRIVER_DEVMAN, 0, 0);143 144 fibril_mutex_unlock(&driver->driver_mutex); 137 145 138 146 log_msg(LVL_NOTE, … … 140 148 driver->name); 141 149 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); 150 async_answer_0(iid, EOK); 151 160 152 return driver; 161 153 } … … 287 279 return; 288 280 } 289 281 290 282 fun_node_t *fun = create_fun_node(); 291 fun->ftype = ftype;292 293 283 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 294 284 fibril_rwlock_write_unlock(&tree->rwlock); … … 336 326 } 337 327 } else { 338 loc_register_tree_function(fun, tree);328 devmap_register_tree_function(fun, tree); 339 329 } 340 330 … … 343 333 } 344 334 345 static void devman_add_function_to_cat(ipc_callid_t callid, ipc_call_t *call) 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) 346 362 { 347 363 devman_handle_t handle = IPC_GET_ARG1(*call); 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, 364 365 /* Get class name. */ 366 char *class_name; 367 int rc = async_data_write_accept((void **) &class_name, true, 354 368 0, 0, 0, 0); 355 369 if (rc != EOK) { … … 364 378 } 365 379 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."); 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 419 389 async_answer_0(callid, EOK); 420 390 } … … 438 408 static void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall) 439 409 { 440 client_t *client;441 driver_t *driver;442 443 410 /* Accept the connection. */ 444 411 async_answer_0(iid, EOK); 445 412 446 client = async_get_client_data(); 447 if (client == NULL) { 448 log_msg(LVL_ERROR, "Failed to allocate client data."); 449 return; 450 } 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); 451 429 452 430 while (true) { … … 457 435 break; 458 436 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 470 437 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;481 438 case DEVMAN_ADD_FUNCTION: 482 439 devman_add_function(callid, &call); 483 440 break; 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); 441 case DEVMAN_ADD_DEVICE_TO_CLASS: 442 devman_add_function_to_class(callid, &call); 489 443 break; 490 444 default: … … 519 473 } 520 474 521 /** Get device name. */ 522 static void devman_fun_get_name(ipc_callid_t iid, ipc_call_t *icall) 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) 523 512 { 524 513 devman_handle_t handle = IPC_GET_ARG1(*icall); … … 544 533 } 545 534 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 583 535 size_t sent_length = str_size(fun->pathname); 584 536 if (sent_length > data_len) { … … 592 544 } 593 545 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 }682 546 683 547 /** Function for handling connections from a client to the device manager. */ … … 698 562 devman_function_get_handle(callid, &call); 699 563 break; 700 case DEVMAN_DEV _GET_FUNCTIONS:701 devman_ dev_get_functions(callid, &call);564 case DEVMAN_DEVICE_GET_HANDLE_BY_CLASS: 565 devman_function_get_handle_by_class(callid, &call); 702 566 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); 567 case DEVMAN_DEVICE_GET_DEVICE_PATH: 568 devman_get_device_path_by_handle(callid, &call); 714 569 break; 715 570 default: … … 804 659 } 805 660 806 /** Function for handling connections from a client forwarded by the location807 * serviceto 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);661 /** Function for handling connections from a client forwarded by the device 662 * mapper to 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); 811 666 fun_node_t *fun; 812 667 dev_node_t *dev; 813 668 814 fun = find_loc_tree_function(&device_tree, service_id); 669 fun = find_devmap_tree_function(&device_tree, devmap_handle); 670 if (fun == NULL) 671 fun = find_devmap_class_function(&class_list, devmap_handle); 815 672 816 673 if (fun == NULL || fun->dev->drv == NULL) { 817 log_msg(LVL_WARN, "devman_connection_loc(): function "818 "not found.\n");819 674 async_answer_0(iid, ENOENT); 820 675 return; … … 822 677 823 678 dev = fun->dev; 679 680 if ((dev->state != DEVICE_USABLE) || (!dev->drv->sess)) { 681 async_answer_0(iid, EINVAL); 682 return; 683 } 824 684 825 685 async_exch_t *exch = async_exchange_begin(dev->drv->sess); … … 829 689 830 690 log_msg(LVL_DEBUG, 831 "Forwarding loc servicerequest for `%s' function to driver `%s'.",691 "Forwarding devmapper request for `%s' function to driver `%s'.", 832 692 fun->pathname, dev->drv->name); 833 693 } … … 836 696 static void devman_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 837 697 { 838 /* Select port. */698 /* Select interface. */ 839 699 switch ((sysarg_t) (IPC_GET_ARG1(*icall))) { 840 700 case DEVMAN_DRIVER: … … 848 708 devman_forward(iid, icall, false); 849 709 break; 850 case DEVMAN_CONNECT_FROM_ LOC:851 /* Someone connected through locnode. */852 devman_connection_ loc(iid, icall);710 case DEVMAN_CONNECT_FROM_DEVMAP: 711 /* Someone connected through devmap node. */ 712 devman_connection_devmapper(iid, icall); 853 713 break; 854 714 case DEVMAN_CONNECT_TO_PARENTS_DEVICE: … … 862 722 } 863 723 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 881 724 /** Initialize device manager internal structures. */ 882 725 static bool devman_init(void) … … 900 743 } 901 744 745 init_class_list(&class_list); 746 902 747 /* 903 * !!! devman_connection ... as the device manager is not a real loc748 * !!! devman_connection ... as the device manager is not a real devmap 904 749 * driver (it uses a completely different ipc protocol than an ordinary 905 * locdriver) forwarding a connection from client to the devman by906 * location servicewould not work.750 * devmap driver) forwarding a connection from client to the devman by 751 * devmapper would not work. 907 752 */ 908 loc_server_register(NAME, devman_connection);753 devmap_driver_register(NAME, devman_connection); 909 754 910 755 return true; … … 915 760 printf(NAME ": HelenOS Device Manager\n"); 916 761 917 if (log_init(NAME, LVL_ WARN) != EOK) {762 if (log_init(NAME, LVL_ERROR) != EOK) { 918 763 printf(NAME ": Error initializing logging subsystem.\n"); 919 764 return -1; … … 925 770 } 926 771 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); 772 /* Set a handler of incomming connections. */ 930 773 async_set_client_connection(devman_connection); 931 774
Note:
See TracChangeset
for help on using the changeset viewer.