Changes in uspace/lib/drv/generic/driver.c [80a96d2:b72efe8] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/driver.c
r80a96d2 rb72efe8 63 63 64 64 /** Devices */ 65 LIST_INITIALIZE(devices);66 FIBRIL_MUTEX_INITIALIZE(devices_mutex);67 68 /** Functions */69 65 LIST_INITIALIZE(functions); 70 66 FIBRIL_MUTEX_INITIALIZE(functions_mutex); … … 86 82 static ddf_dev_t *create_device(void); 87 83 static void delete_device(ddf_dev_t *); 88 static void dev_add_ref(ddf_dev_t *);89 static void dev_del_ref(ddf_dev_t *);90 static void fun_add_ref(ddf_fun_t *);91 static void fun_del_ref(ddf_fun_t *);92 84 static remote_handler_t *function_get_default_handler(ddf_fun_t *); 93 85 static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t); … … 235 227 } 236 228 237 static ddf_dev_t *driver_get_device(devman_handle_t handle) 238 { 239 ddf_dev_t *dev = NULL; 240 241 assert(fibril_mutex_is_locked(&devices_mutex)); 242 243 list_foreach(devices, link) { 244 dev = list_get_instance(link, ddf_dev_t, link); 245 if (dev->handle == handle) 246 return dev; 247 } 229 static ddf_fun_t *driver_get_function(list_t *functions, devman_handle_t handle) 230 { 231 ddf_fun_t *fun = NULL; 232 233 fibril_mutex_lock(&functions_mutex); 234 235 list_foreach(*functions, link) { 236 fun = list_get_instance(link, ddf_fun_t, link); 237 if (fun->handle == handle) { 238 fibril_mutex_unlock(&functions_mutex); 239 return fun; 240 } 241 } 242 243 fibril_mutex_unlock(&functions_mutex); 248 244 249 245 return NULL; 250 246 } 251 247 252 static ddf_fun_t *driver_get_function(devman_handle_t handle) 253 { 254 ddf_fun_t *fun = NULL; 255 256 assert(fibril_mutex_is_locked(&functions_mutex)); 257 258 list_foreach(functions, link) { 259 fun = list_get_instance(link, ddf_fun_t, link); 260 if (fun->handle == handle) 261 return fun; 262 } 263 264 return NULL; 265 } 266 267 static void driver_dev_add(ipc_callid_t iid, ipc_call_t *icall) 248 static void driver_add_device(ipc_callid_t iid, ipc_call_t *icall) 268 249 { 269 250 char *dev_name = NULL; … … 274 255 275 256 ddf_dev_t *dev = create_device(); 276 277 /* Add one reference that will be dropped by driver_dev_remove() */278 dev_add_ref(dev);279 257 dev->handle = dev_handle; 280 258 … … 289 267 290 268 res = driver->driver_ops->add_device(dev); 291 292 if (res != EOK) { 293 dev_del_ref(dev); 294 async_answer_0(iid, res); 295 return; 296 } 297 298 fibril_mutex_lock(&devices_mutex); 299 list_append(&dev->link, &devices); 300 fibril_mutex_unlock(&devices_mutex); 269 if (res != EOK) 270 delete_device(dev); 301 271 302 272 async_answer_0(iid, res); 303 }304 305 static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall)306 {307 devman_handle_t devh;308 ddf_dev_t *dev;309 int rc;310 311 devh = IPC_GET_ARG1(*icall);312 313 fibril_mutex_lock(&devices_mutex);314 dev = driver_get_device(devh);315 if (dev != NULL)316 dev_add_ref(dev);317 fibril_mutex_unlock(&devices_mutex);318 319 if (dev == NULL) {320 async_answer_0(iid, ENOENT);321 return;322 }323 324 if (driver->driver_ops->dev_remove != NULL)325 rc = driver->driver_ops->dev_remove(dev);326 else327 rc = ENOTSUP;328 329 if (rc == EOK)330 dev_del_ref(dev);331 332 async_answer_0(iid, (sysarg_t) rc);333 }334 335 static void driver_dev_gone(ipc_callid_t iid, ipc_call_t *icall)336 {337 devman_handle_t devh;338 ddf_dev_t *dev;339 int rc;340 341 devh = IPC_GET_ARG1(*icall);342 343 fibril_mutex_lock(&devices_mutex);344 dev = driver_get_device(devh);345 if (dev != NULL)346 dev_add_ref(dev);347 fibril_mutex_unlock(&devices_mutex);348 349 if (dev == NULL) {350 async_answer_0(iid, ENOENT);351 return;352 }353 354 if (driver->driver_ops->dev_gone != NULL)355 rc = driver->driver_ops->dev_gone(dev);356 else357 rc = ENOTSUP;358 359 if (rc == EOK)360 dev_del_ref(dev);361 362 async_answer_0(iid, (sysarg_t) rc);363 }364 365 static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall)366 {367 devman_handle_t funh;368 ddf_fun_t *fun;369 int rc;370 371 funh = IPC_GET_ARG1(*icall);372 373 /*374 * Look the function up. Bump reference count so that375 * the function continues to exist until we return376 * from the driver.377 */378 fibril_mutex_lock(&functions_mutex);379 380 fun = driver_get_function(funh);381 if (fun != NULL)382 fun_add_ref(fun);383 384 fibril_mutex_unlock(&functions_mutex);385 386 if (fun == NULL) {387 async_answer_0(iid, ENOENT);388 return;389 }390 391 /* Call driver entry point */392 if (driver->driver_ops->fun_online != NULL)393 rc = driver->driver_ops->fun_online(fun);394 else395 rc = ENOTSUP;396 397 fun_del_ref(fun);398 399 async_answer_0(iid, (sysarg_t) rc);400 }401 402 static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall)403 {404 devman_handle_t funh;405 ddf_fun_t *fun;406 int rc;407 408 funh = IPC_GET_ARG1(*icall);409 410 /*411 * Look the function up. Bump reference count so that412 * the function continues to exist until we return413 * from the driver.414 */415 fibril_mutex_lock(&functions_mutex);416 417 fun = driver_get_function(funh);418 if (fun != NULL)419 fun_add_ref(fun);420 421 fibril_mutex_unlock(&functions_mutex);422 423 if (fun == NULL) {424 async_answer_0(iid, ENOENT);425 return;426 }427 428 /* Call driver entry point */429 if (driver->driver_ops->fun_offline != NULL)430 rc = driver->driver_ops->fun_offline(fun);431 else432 rc = ENOTSUP;433 434 async_answer_0(iid, (sysarg_t) rc);435 273 } 436 274 … … 448 286 449 287 switch (IPC_GET_IMETHOD(call)) { 450 case DRIVER_DEV_ADD: 451 driver_dev_add(callid, &call); 452 break; 453 case DRIVER_DEV_REMOVE: 454 driver_dev_remove(callid, &call); 455 break; 456 case DRIVER_DEV_GONE: 457 driver_dev_gone(callid, &call); 458 break; 459 case DRIVER_FUN_ONLINE: 460 driver_fun_online(callid, &call); 461 break; 462 case DRIVER_FUN_OFFLINE: 463 driver_fun_offline(callid, &call); 288 case DRIVER_ADD_DEVICE: 289 driver_add_device(callid, &call); 464 290 break; 465 291 default: 466 async_answer_0(callid, ENO TSUP);292 async_answer_0(callid, ENOENT); 467 293 } 468 294 } … … 482 308 */ 483 309 devman_handle_t handle = IPC_GET_ARG2(*icall); 484 485 fibril_mutex_lock(&functions_mutex); 486 ddf_fun_t *fun = driver_get_function(handle); 487 fibril_mutex_unlock(&functions_mutex); 488 /* XXX Need a lock on fun */ 310 ddf_fun_t *fun = driver_get_function(&functions, handle); 489 311 490 312 if (fun == NULL) { … … 492 314 " %" PRIun " was found.\n", driver->name, handle); 493 315 async_answer_0(iid, ENOENT); 494 return;495 }496 497 if (fun->conn_handler != NULL) {498 /* Driver has a custom connection handler. */499 (*fun->conn_handler)(iid, icall, (void *)fun);500 316 return; 501 317 } … … 606 422 static void driver_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 607 423 { 608 sysarg_t conn_type;609 610 if (iid == 0) {611 /* Callback connection from devman */612 /* XXX Use separate handler for this type of connection */613 conn_type = DRIVER_DEVMAN;614 } else {615 conn_type = IPC_GET_ARG1(*icall);616 }617 618 424 /* Select interface */ 619 switch ( conn_type) {425 switch ((sysarg_t) (IPC_GET_ARG1(*icall))) { 620 426 case DRIVER_DEVMAN: 621 427 /* Handle request from device manager */ … … 644 450 ddf_dev_t *dev; 645 451 646 dev = calloc(1,sizeof(ddf_dev_t));452 dev = malloc(sizeof(ddf_dev_t)); 647 453 if (dev == NULL) 648 454 return NULL; 649 455 456 memset(dev, 0, sizeof(ddf_dev_t)); 650 457 return dev; 651 458 } … … 675 482 static void delete_device(ddf_dev_t *dev) 676 483 { 677 if (dev->driver_data != NULL)678 free(dev->driver_data);679 484 free(dev); 680 485 } 681 486 682 /** Delete functionstructure.487 /** Delete device structure. 683 488 * 684 489 * @param dev The device structure. … … 687 492 { 688 493 clean_match_ids(&fun->match_ids); 689 if (fun->driver_data != NULL)690 free(fun->driver_data);691 494 if (fun->name != NULL) 692 495 free(fun->name); … … 694 497 } 695 498 696 /** Increase device reference count. */697 static void dev_add_ref(ddf_dev_t *dev)698 {699 atomic_inc(&dev->refcnt);700 }701 702 /** Decrease device reference count.703 *704 * Free the device structure if the reference count drops to zero.705 */706 static void dev_del_ref(ddf_dev_t *dev)707 {708 if (atomic_predec(&dev->refcnt) == 0)709 delete_device(dev);710 }711 712 /** Increase function reference count.713 *714 * This also increases reference count on the device. The device structure715 * will thus not be deallocated while there are some associated function716 * structures.717 */718 static void fun_add_ref(ddf_fun_t *fun)719 {720 dev_add_ref(fun->dev);721 atomic_inc(&fun->refcnt);722 }723 724 /** Decrease function reference count.725 *726 * Free the function structure if the reference count drops to zero.727 */728 static void fun_del_ref(ddf_fun_t *fun)729 {730 ddf_dev_t *dev = fun->dev;731 732 if (atomic_predec(&fun->refcnt) == 0)733 delete_function(fun);734 735 dev_del_ref(dev);736 }737 738 /** Allocate driver-specific device data. */739 extern void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size)740 {741 void *data;742 743 assert(dev->driver_data == NULL);744 745 data = calloc(1, size);746 if (data == NULL)747 return NULL;748 749 dev->driver_data = data;750 return data;751 }752 753 499 /** Create a DDF function node. 754 500 * … … 782 528 return NULL; 783 529 784 /* Add one reference that will be dropped by ddf_fun_destroy() */530 fun->bound = false; 785 531 fun->dev = dev; 786 fun_add_ref(fun);787 788 fun->bound = false;789 532 fun->ftype = ftype; 790 533 … … 798 541 } 799 542 800 /** Allocate driver-specific function data. */801 extern void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size)802 {803 void *data;804 805 assert(fun->bound == false);806 assert(fun->driver_data == NULL);807 808 data = calloc(1, size);809 if (data == NULL)810 return NULL;811 812 fun->driver_data = data;813 return data;814 }815 816 543 /** Destroy DDF function node. 817 544 * … … 824 551 { 825 552 assert(fun->bound == false); 826 827 /* 828 * Drop the reference added by ddf_fun_create(). This will deallocate 829 * the function as soon as all other references are dropped (i.e. 830 * as soon control leaves all driver entry points called in context 831 * of this function. 832 */ 833 fun_del_ref(fun); 553 delete_function(fun); 834 554 } 835 555 … … 856 576 int ddf_fun_bind(ddf_fun_t *fun) 857 577 { 858 assert(fun->bound == false);859 578 assert(fun->name != NULL); 860 579 … … 873 592 } 874 593 875 /** Unbind a function node.876 *877 * Unbind the specified function from the system. This effectively makes878 * the function invisible to the system.879 *880 * @param fun Function to unbind881 * @return EOK on success or negative error code882 */883 int ddf_fun_unbind(ddf_fun_t *fun)884 {885 int res;886 887 assert(fun->bound == true);888 889 res = devman_remove_function(fun->handle);890 if (res != EOK)891 return res;892 893 remove_from_functions_list(fun);894 895 fun->bound = false;896 return EOK;897 }898 899 /** Online function.900 *901 * @param fun Function to online902 * @return EOK on success or negative error code903 */904 int ddf_fun_online(ddf_fun_t *fun)905 {906 int res;907 908 assert(fun->bound == true);909 910 res = devman_drv_fun_online(fun->handle);911 if (res != EOK)912 return res;913 914 return EOK;915 }916 917 /** Offline function.918 *919 * @param fun Function to offline920 * @return EOK on success or negative error code921 */922 int ddf_fun_offline(ddf_fun_t *fun)923 {924 int res;925 926 assert(fun->bound == true);927 928 res = devman_drv_fun_offline(fun->handle);929 if (res != EOK)930 return res;931 932 return EOK;933 }934 935 594 /** Add single match ID to inner function. 936 595 * … … 955 614 return ENOMEM; 956 615 957 match_id->id = str_dup(match_id_str);616 match_id->id = match_id_str; 958 617 match_id->score = 90; 959 618 … … 970 629 } 971 630 972 /** Add exposed function to c ategory.631 /** Add exposed function to class. 973 632 * 974 633 * Must only be called when the function is bound. 975 634 */ 976 int ddf_fun_add_to_c ategory(ddf_fun_t *fun, const char *cat_name)635 int ddf_fun_add_to_class(ddf_fun_t *fun, const char *class_name) 977 636 { 978 637 assert(fun->bound == true); 979 638 assert(fun->ftype == fun_exposed); 980 639 981 return devman_add_device_to_c ategory(fun->handle, cat_name);640 return devman_add_device_to_class(fun->handle, class_name); 982 641 } 983 642
Note:
See TracChangeset
for help on using the changeset viewer.