Changeset 1a5b252 in mainline for uspace/srv
- Timestamp:
- 2011-08-21T11:54:15Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8cc4ddb
- Parents:
- e64df9a
- Location:
- uspace/srv/devman
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/devman.c
re64df9a r1a5b252 483 483 } 484 484 485 /** Detach driver from device. 486 * 487 * @param node The device's node in the device tree. 488 * @param drv The driver. 489 */ 490 void detach_driver(dev_node_t *dev) 491 { 492 /* XXX need lock on dev */ 493 driver_t *drv = dev->drv; 494 495 assert(drv != NULL); 496 log_msg(LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")", 497 dev->pfun->pathname, drv->name); 498 499 fibril_mutex_lock(&drv->driver_mutex); 500 501 dev->drv = NULL; 502 list_remove(&dev->driver_devices); 503 504 fibril_mutex_unlock(&drv->driver_mutex); 505 } 506 485 507 /** Start a driver 486 508 * … … 726 748 727 749 ipc_call_t answer; 728 aid_t req = async_send_2(exch, DRIVER_ ADD_DEVICE, dev->handle,750 aid_t req = async_send_2(exch, DRIVER_DEV_ADD, dev->handle, 729 751 parent_handle, &answer); 730 752 … … 800 822 } 801 823 824 int driver_dev_remove(dev_node_t *dev) 825 { 826 async_exch_t *exch; 827 sysarg_t retval; 828 driver_t *drv; 829 830 assert(dev != NULL); 831 log_msg(LVL_DEBUG, "driver_dev_remove(%p)", dev); 832 drv = dev->drv; 833 834 exch = async_exchange_begin(drv->sess); 835 retval = async_req_1_0(exch, DRIVER_DEV_REMOVE, dev->handle); 836 async_exchange_end(exch); 837 838 return retval; 839 840 } 841 842 int driver_fun_online(fun_node_t *fun) 843 { 844 async_exch_t *exch; 845 sysarg_t retval; 846 driver_t *drv; 847 848 log_msg(LVL_DEBUG, "driver_fun_online(%p)", fun); 849 if (fun->dev == NULL) { 850 /* XXX root function? */ 851 return EINVAL; 852 } 853 854 drv = fun->dev->drv; 855 856 exch = async_exchange_begin(drv->sess); 857 retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, fun->handle); 858 loc_exchange_end(exch); 859 860 return retval; 861 } 862 863 int driver_fun_offline(fun_node_t *fun) 864 { 865 async_exch_t *exch; 866 sysarg_t retval; 867 driver_t *drv; 868 869 log_msg(LVL_DEBUG, "driver_fun_offline(%p)", fun); 870 if (fun->dev == NULL) { 871 /* XXX root function? */ 872 return EINVAL; 873 } 874 875 drv = fun->dev->drv; 876 877 exch = async_exchange_begin(drv->sess); 878 retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, fun->handle); 879 loc_exchange_end(exch); 880 881 return retval; 882 883 } 884 802 885 /** Initialize the device tree. 803 886 * … … 1065 1148 } 1066 1149 1150 /** Remove device from device tree. 1151 * 1152 * @param tree Device tree 1153 * @param dev Device node 1154 */ 1155 void remove_dev_node(dev_tree_t *tree, dev_node_t *dev) 1156 { 1157 assert(tree != NULL); 1158 assert(dev != NULL); 1159 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1160 1161 log_msg(LVL_DEBUG, "remove_dev_node(dev=%p)", dev); 1162 1163 /* Remove node from the handle-to-node map. */ 1164 unsigned long key = dev->handle; 1165 hash_table_remove(&tree->devman_devices, &key, 1); 1166 1167 /* Unlink from parent function. */ 1168 dev->pfun->child = NULL; 1169 dev->pfun = NULL; 1170 } 1171 1172 1067 1173 /** Insert new function into device tree. 1068 1174 * … … 1127 1233 if (fun->dev != NULL) 1128 1234 list_remove(&fun->dev_functions); 1235 1236 fun->dev = NULL; 1129 1237 } 1130 1238 -
uspace/srv/devman/devman.h
re64df9a r1a5b252 240 240 extern void add_driver(driver_list_t *, driver_t *); 241 241 extern void attach_driver(dev_node_t *, driver_t *); 242 extern void detach_driver(dev_node_t *); 242 243 extern void add_device(driver_t *, dev_node_t *, dev_tree_t *); 243 244 extern bool start_driver(driver_t *); 245 extern int driver_dev_remove(dev_node_t *); 246 extern int driver_fun_online(fun_node_t *); 247 extern int driver_fun_offline(fun_node_t *); 244 248 245 249 extern driver_t *find_driver(driver_list_t *, const char *); … … 274 278 extern bool create_root_nodes(dev_tree_t *); 275 279 extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *); 280 extern void remove_dev_node(dev_tree_t *, dev_node_t *); 276 281 extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *); 277 282 extern void remove_fun_node(dev_tree_t *, fun_node_t *); -
uspace/srv/devman/main.c
re64df9a r1a5b252 237 237 } 238 238 239 /** Handle function registration. 240 * 241 * Child devices are registered by their parent's device driver. 242 */ 243 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call) 244 { 245 fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call); 246 devman_handle_t dev_handle = IPC_GET_ARG2(*call); 247 sysarg_t match_count = IPC_GET_ARG3(*call); 248 dev_tree_t *tree = &device_tree; 249 250 fibril_rwlock_write_lock(&tree->rwlock); 251 252 dev_node_t *dev = NULL; 253 dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle); 254 255 if (pdev == NULL) { 256 fibril_rwlock_write_unlock(&tree->rwlock); 257 async_answer_0(callid, ENOENT); 258 return; 259 } 260 261 if (ftype != fun_inner && ftype != fun_exposed) { 262 /* Unknown function type */ 263 log_msg(LVL_ERROR, 264 "Unknown function type %d provided by driver.", 265 (int) ftype); 266 267 fibril_rwlock_write_unlock(&tree->rwlock); 268 async_answer_0(callid, EINVAL); 269 return; 270 } 271 272 char *fun_name = NULL; 273 int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0); 274 if (rc != EOK) { 275 fibril_rwlock_write_unlock(&tree->rwlock); 276 async_answer_0(callid, rc); 277 return; 278 } 279 280 /* Check that function with same name is not there already. */ 281 if (find_fun_node_in_device(pdev, fun_name) != NULL) { 282 fibril_rwlock_write_unlock(&tree->rwlock); 283 async_answer_0(callid, EEXISTS); 284 printf(NAME ": Warning, driver tried to register `%s' twice.\n", 285 fun_name); 286 free(fun_name); 287 return; 288 } 289 290 fun_node_t *fun = create_fun_node(); 291 fun->ftype = ftype; 292 293 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 294 fibril_rwlock_write_unlock(&tree->rwlock); 295 delete_fun_node(fun); 296 async_answer_0(callid, ENOMEM); 297 return; 298 } 299 300 if (ftype == fun_inner) { 239 static int online_function(fun_node_t *fun) 240 { 241 dev_node_t *dev; 242 243 fibril_rwlock_write_lock(&device_tree.rwlock); 244 245 if (fun->ftype == fun_inner) { 301 246 dev = create_dev_node(); 302 247 if (dev == NULL) { 303 fibril_rwlock_write_unlock(& tree->rwlock);248 fibril_rwlock_write_unlock(&device_tree.rwlock); 304 249 delete_fun_node(fun); 305 async_answer_0(callid, ENOMEM); 306 return; 250 return ENOMEM; 307 251 } 308 252 309 insert_dev_node( tree, dev, fun);310 } 311 312 fibril_rwlock_write_unlock(& tree->rwlock);253 insert_dev_node(&device_tree, dev, fun); 254 } 255 256 fibril_rwlock_write_unlock(&device_tree.rwlock); 313 257 314 258 log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname); 315 259 316 devman_receive_match_ids(match_count, &fun->match_ids); 317 318 if (ftype == fun_inner) { 260 if (fun->ftype == fun_inner) { 261 dev = fun->child; 319 262 assert(dev != NULL); 263 320 264 /* 321 265 * Try to find a suitable driver and assign it to the device. We do … … 336 280 } 337 281 } else { 338 loc_register_tree_function(fun, tree); 282 loc_register_tree_function(fun, &device_tree); 283 } 284 285 return EOK; 286 } 287 288 static int offline_function(fun_node_t *fun) 289 { 290 int rc; 291 292 if (fun->ftype == fun_inner) { 293 printf("devman_drv_fun_offline(): %p is inner fun, removing " 294 "child dev.\n", fun); 295 if (fun->child != NULL) { 296 dev_node_t *dev = fun->child; 297 298 rc = driver_dev_remove(dev); 299 if (rc != EOK) { 300 return ENOTSUP; 301 } 302 detach_driver(dev); 303 fibril_rwlock_write_lock(&device_tree.rwlock); 304 remove_dev_node(&device_tree, dev); 305 fibril_rwlock_write_unlock(&device_tree.rwlock); 306 delete_dev_node(dev); 307 } 308 } else { 309 /* Unregister from location service */ 310 rc = loc_service_unregister(fun->service_id); 311 if (rc != EOK) { 312 log_msg(LVL_ERROR, "Failed unregistering tree service."); 313 return EIO; 314 } 315 316 fun->service_id = 0; 317 } 318 319 return EOK; 320 } 321 322 /** Handle function registration. 323 * 324 * Child devices are registered by their parent's device driver. 325 */ 326 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call) 327 { 328 fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call); 329 devman_handle_t dev_handle = IPC_GET_ARG2(*call); 330 sysarg_t match_count = IPC_GET_ARG3(*call); 331 dev_tree_t *tree = &device_tree; 332 333 fibril_rwlock_write_lock(&tree->rwlock); 334 335 dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle); 336 337 if (pdev == NULL) { 338 fibril_rwlock_write_unlock(&tree->rwlock); 339 async_answer_0(callid, ENOENT); 340 return; 341 } 342 343 if (ftype != fun_inner && ftype != fun_exposed) { 344 /* Unknown function type */ 345 log_msg(LVL_ERROR, 346 "Unknown function type %d provided by driver.", 347 (int) ftype); 348 349 fibril_rwlock_write_unlock(&tree->rwlock); 350 async_answer_0(callid, EINVAL); 351 return; 352 } 353 354 char *fun_name = NULL; 355 int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0); 356 if (rc != EOK) { 357 fibril_rwlock_write_unlock(&tree->rwlock); 358 async_answer_0(callid, rc); 359 return; 360 } 361 362 /* Check that function with same name is not there already. */ 363 if (find_fun_node_in_device(pdev, fun_name) != NULL) { 364 fibril_rwlock_write_unlock(&tree->rwlock); 365 async_answer_0(callid, EEXISTS); 366 printf(NAME ": Warning, driver tried to register `%s' twice.\n", 367 fun_name); 368 free(fun_name); 369 return; 370 } 371 372 fun_node_t *fun = create_fun_node(); 373 fun->ftype = ftype; 374 375 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 376 fibril_rwlock_write_unlock(&tree->rwlock); 377 delete_fun_node(fun); 378 async_answer_0(callid, ENOMEM); 379 return; 380 } 381 382 fibril_rwlock_write_unlock(&tree->rwlock); 383 384 devman_receive_match_ids(match_count, &fun->match_ids); 385 386 rc = online_function(fun); 387 if (rc != EOK) { 388 /* XXX clean up */ 389 async_answer_0(callid, rc); 390 return; 339 391 } 340 392 … … 378 430 } 379 431 432 /** Online function by driver request. 433 * 434 */ 435 static void devman_drv_fun_online(ipc_callid_t iid, ipc_call_t *icall, 436 driver_t *drv) 437 { 438 fun_node_t *fun; 439 int rc; 440 441 printf("devman_drv_fun_online()\n"); 442 fibril_rwlock_write_lock(&device_tree.rwlock); 443 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall)); 444 fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */ 445 446 if (fun == NULL || fun->dev == NULL || fun->dev->drv != drv) { 447 async_answer_0(iid, ENOENT); 448 return; 449 } 450 451 rc = online_function(fun); 452 if (rc != EOK) { 453 printf("devman_drv_fun_online() online_fun->ERROR\n"); 454 async_answer_0(iid, (sysarg_t) rc); 455 return; 456 } 457 printf("devman_drv_fun_online() online_fun->OK\n"); 458 459 async_answer_0(iid, (sysarg_t) EOK); 460 } 461 462 463 /** Offline function by driver request. 464 * 465 */ 466 static void devman_drv_fun_offline(ipc_callid_t iid, ipc_call_t *icall, 467 driver_t *drv) 468 { 469 fun_node_t *fun; 470 int rc; 471 472 fibril_rwlock_write_lock(&device_tree.rwlock); 473 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall)); 474 fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */ 475 476 if (fun == NULL || fun->dev == NULL || fun->dev->drv != drv) { 477 async_answer_0(iid, ENOENT); 478 return; 479 } 480 481 rc = offline_function(fun); 482 if (rc != EOK) { 483 async_answer_0(iid, (sysarg_t) rc); 484 return; 485 } 486 487 async_answer_0(iid, (sysarg_t) EOK); 488 } 489 380 490 /** Remove function. */ 381 491 static void devman_remove_function(ipc_callid_t callid, ipc_call_t *call) … … 399 509 /* Handle possible descendants */ 400 510 /* TODO */ 401 log_msg(LVL_WARN, "devman_remove_function(): not handling " 402 "descendants\n"); 511 if (fun->child != NULL) { 512 log_msg(LVL_WARN, "devman_remove_function(): not handling " 513 "descendants\n"); 514 } 403 515 } 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; 516 if (fun->service_id != 0) { 517 /* Unregister from location service */ 518 rc = loc_service_unregister(fun->service_id); 519 if (rc != EOK) { 520 log_msg(LVL_ERROR, "Failed unregistering tree " 521 "service."); 522 fibril_rwlock_write_unlock(&tree->rwlock); 523 async_answer_0(callid, EIO); 524 return; 525 } 411 526 } 412 527 } … … 485 600 devman_add_function_to_cat(callid, &call); 486 601 break; 602 case DEVMAN_DRV_FUN_ONLINE: 603 devman_drv_fun_online(callid, &call, driver); 604 break; 605 case DEVMAN_DRV_FUN_OFFLINE: 606 devman_drv_fun_offline(callid, &call, driver); 607 break; 487 608 case DEVMAN_REMOVE_FUNCTION: 488 609 devman_remove_function(callid, &call); 489 610 break; 490 611 default: 491 async_answer_0(callid, EINVAL); 612 async_answer_0(callid, EINVAL); 492 613 break; 493 614 } … … 666 787 } 667 788 789 /** Online function. 790 * 791 * Send a request to online a function to the responsible driver. 792 * The driver may offline other functions if necessary (i.e. if the state 793 * of this function is linked to state of another function somehow). 794 */ 795 static void devman_fun_online(ipc_callid_t iid, ipc_call_t *icall) 796 { 797 fun_node_t *fun; 798 int rc; 799 800 fibril_rwlock_write_lock(&device_tree.rwlock); 801 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall)); 802 fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */ 803 804 if (fun == NULL) { 805 async_answer_0(iid, ENOENT); 806 return; 807 } 808 809 rc = driver_fun_online(fun); 810 811 async_answer_0(iid, (sysarg_t) rc); 812 } 813 814 /** Offline function. 815 * 816 * Send a request to offline a function to the responsible driver. As 817 * a result the subtree rooted at that function should be cleanly 818 * detatched. The driver may offline other functions if necessary 819 * (i.e. if the state of this function is linked to state of another 820 * function somehow). 821 */ 822 static void devman_fun_offline(ipc_callid_t iid, ipc_call_t *icall) 823 { 824 fun_node_t *fun; 825 int rc; 826 827 fibril_rwlock_write_lock(&device_tree.rwlock); 828 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall)); 829 fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */ 830 831 if (fun == NULL) { 832 async_answer_0(iid, ENOENT); 833 return; 834 } 835 836 rc = driver_fun_offline(fun); 837 838 async_answer_0(iid, (sysarg_t) rc); 839 } 840 668 841 /** Find handle for the function instance identified by its service ID. */ 669 842 static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall) … … 709 882 case DEVMAN_FUN_GET_PATH: 710 883 devman_fun_get_path(callid, &call); 884 break; 885 case DEVMAN_FUN_ONLINE: 886 devman_fun_online(callid, &call); 887 break; 888 case DEVMAN_FUN_OFFLINE: 889 devman_fun_offline(callid, &call); 711 890 break; 712 891 case DEVMAN_FUN_SID_TO_HANDLE:
Note:
See TracChangeset
for help on using the changeset viewer.