Changeset 1a5b252 in mainline for uspace/srv/devman/main.c
- Timestamp:
- 2011-08-21T11:54:15Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8cc4ddb
- Parents:
- e64df9a
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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.