Changes in uspace/lib/drv/generic/driver.c [f278930:79a141a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/driver.c
rf278930 r79a141a 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); … … 147 139 find_interrupt_context_by_id(interrupt_context_list_t *list, int id) 148 140 { 141 fibril_mutex_lock(&list->mutex); 142 143 link_t *link = list->contexts.next; 149 144 interrupt_context_t *ctx; 150 145 151 fibril_mutex_lock(&list->mutex); 152 153 list_foreach(list->contexts, link) { 146 while (link != &list->contexts) { 154 147 ctx = list_get_instance(link, interrupt_context_t, link); 155 148 if (ctx->id == id) { … … 157 150 return ctx; 158 151 } 152 link = link->next; 159 153 } 160 154 … … 166 160 find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq) 167 161 { 162 fibril_mutex_lock(&list->mutex); 163 164 link_t *link = list->contexts.next; 168 165 interrupt_context_t *ctx; 169 166 170 fibril_mutex_lock(&list->mutex); 171 172 list_foreach(list->contexts, link) { 167 while (link != &list->contexts) { 173 168 ctx = list_get_instance(link, interrupt_context_t, link); 174 169 if (ctx->irq == irq && ctx->dev == dev) { … … 176 171 return ctx; 177 172 } 173 link = link->next; 178 174 } 179 175 … … 235 231 } 236 232 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 } 233 static ddf_fun_t *driver_get_function(link_t *functions, devman_handle_t handle) 234 { 235 ddf_fun_t *fun = NULL; 236 237 fibril_mutex_lock(&functions_mutex); 238 link_t *link = functions->next; 239 240 while (link != functions) { 241 fun = list_get_instance(link, ddf_fun_t, link); 242 if (fun->handle == handle) { 243 fibril_mutex_unlock(&functions_mutex); 244 return fun; 245 } 246 247 link = link->next; 248 } 249 250 fibril_mutex_unlock(&functions_mutex); 248 251 249 252 return NULL; 250 253 } 251 254 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) 255 static void driver_add_device(ipc_callid_t iid, ipc_call_t *icall) 268 256 { 269 257 char *dev_name = NULL; … … 274 262 275 263 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 264 dev->handle = dev_handle; 280 265 … … 289 274 290 275 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); 276 if (res != EOK) 277 delete_device(dev); 301 278 302 279 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_fun_online(ipc_callid_t iid, ipc_call_t *icall)336 {337 devman_handle_t funh;338 ddf_fun_t *fun;339 int rc;340 341 funh = IPC_GET_ARG1(*icall);342 343 /*344 * Look the function up. Bump reference count so that345 * the function continues to exist until we return346 * from the driver.347 */348 fibril_mutex_lock(&functions_mutex);349 350 fun = driver_get_function(funh);351 if (fun != NULL)352 fun_add_ref(fun);353 354 fibril_mutex_unlock(&functions_mutex);355 356 if (fun == NULL) {357 async_answer_0(iid, ENOENT);358 return;359 }360 361 /* Call driver entry point */362 if (driver->driver_ops->fun_online != NULL)363 rc = driver->driver_ops->fun_online(fun);364 else365 rc = ENOTSUP;366 367 fun_del_ref(fun);368 369 async_answer_0(iid, (sysarg_t) rc);370 }371 372 static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall)373 {374 devman_handle_t funh;375 ddf_fun_t *fun;376 int rc;377 378 funh = IPC_GET_ARG1(*icall);379 380 /*381 * Look the function up. Bump reference count so that382 * the function continues to exist until we return383 * from the driver.384 */385 fibril_mutex_lock(&functions_mutex);386 387 fun = driver_get_function(funh);388 if (fun != NULL)389 fun_add_ref(fun);390 391 fibril_mutex_unlock(&functions_mutex);392 393 if (fun == NULL) {394 async_answer_0(iid, ENOENT);395 return;396 }397 398 /* Call driver entry point */399 if (driver->driver_ops->fun_offline != NULL)400 rc = driver->driver_ops->fun_offline(fun);401 else402 rc = ENOTSUP;403 404 async_answer_0(iid, (sysarg_t) rc);405 280 } 406 281 … … 418 293 419 294 switch (IPC_GET_IMETHOD(call)) { 420 case DRIVER_DEV_ADD: 421 driver_dev_add(callid, &call); 422 break; 423 case DRIVER_DEV_REMOVE: 424 driver_dev_remove(callid, &call); 425 break; 426 case DRIVER_FUN_ONLINE: 427 driver_fun_online(callid, &call); 428 break; 429 case DRIVER_FUN_OFFLINE: 430 driver_fun_offline(callid, &call); 295 case DRIVER_ADD_DEVICE: 296 driver_add_device(callid, &call); 431 297 break; 432 298 default: 433 async_answer_0(callid, ENO TSUP);299 async_answer_0(callid, ENOENT); 434 300 } 435 301 } … … 449 315 */ 450 316 devman_handle_t handle = IPC_GET_ARG2(*icall); 451 452 fibril_mutex_lock(&functions_mutex); 453 ddf_fun_t *fun = driver_get_function(handle); 454 fibril_mutex_unlock(&functions_mutex); 455 /* XXX Need a lock on fun */ 317 ddf_fun_t *fun = driver_get_function(&functions, handle); 456 318 457 319 if (fun == NULL) { … … 459 321 " %" PRIun " was found.\n", driver->name, handle); 460 322 async_answer_0(iid, ENOENT); 461 return;462 }463 464 if (fun->conn_handler != NULL) {465 /* Driver has a custom connection handler. */466 (*fun->conn_handler)(iid, icall, (void *)fun);467 323 return; 468 324 } … … 571 427 572 428 /** Function for handling connections to device driver. */ 573 static void driver_connection(ipc_callid_t iid, ipc_call_t *icall, void *arg) 574 { 575 sysarg_t conn_type; 576 577 if (iid == 0) { 578 /* Callback connection from devman */ 579 /* XXX Use separate handler for this type of connection */ 580 conn_type = DRIVER_DEVMAN; 581 } else { 582 conn_type = IPC_GET_ARG1(*icall); 583 } 584 429 static void driver_connection(ipc_callid_t iid, ipc_call_t *icall) 430 { 585 431 /* Select interface */ 586 switch ( conn_type) {432 switch ((sysarg_t) (IPC_GET_ARG1(*icall))) { 587 433 case DRIVER_DEVMAN: 588 434 /* Handle request from device manager */ … … 611 457 ddf_dev_t *dev; 612 458 613 dev = calloc(1,sizeof(ddf_dev_t));459 dev = malloc(sizeof(ddf_dev_t)); 614 460 if (dev == NULL) 615 461 return NULL; 616 462 463 memset(dev, 0, sizeof(ddf_dev_t)); 617 464 return dev; 618 465 } … … 642 489 static void delete_device(ddf_dev_t *dev) 643 490 { 644 if (dev->driver_data != NULL)645 free(dev->driver_data);646 491 free(dev); 647 492 } 648 493 649 /** Delete functionstructure.494 /** Delete device structure. 650 495 * 651 496 * @param dev The device structure. … … 654 499 { 655 500 clean_match_ids(&fun->match_ids); 656 if (fun->driver_data != NULL)657 free(fun->driver_data);658 501 if (fun->name != NULL) 659 502 free(fun->name); … … 661 504 } 662 505 663 /** Increase device reference count. */664 static void dev_add_ref(ddf_dev_t *dev)665 {666 atomic_inc(&dev->refcnt);667 }668 669 /** Decrease device reference count.670 *671 * Free the device structure if the reference count drops to zero.672 */673 static void dev_del_ref(ddf_dev_t *dev)674 {675 if (atomic_predec(&dev->refcnt) == 0)676 delete_device(dev);677 }678 679 /** Increase function reference count.680 *681 * This also increases reference count on the device. The device structure682 * will thus not be deallocated while there are some associated function683 * structures.684 */685 static void fun_add_ref(ddf_fun_t *fun)686 {687 dev_add_ref(fun->dev);688 atomic_inc(&fun->refcnt);689 }690 691 /** Decrease function reference count.692 *693 * Free the function structure if the reference count drops to zero.694 */695 static void fun_del_ref(ddf_fun_t *fun)696 {697 ddf_dev_t *dev = fun->dev;698 699 if (atomic_predec(&fun->refcnt) == 0)700 delete_function(fun);701 702 dev_del_ref(dev);703 }704 705 /** Allocate driver-specific device data. */706 extern void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size)707 {708 void *data;709 710 assert(dev->driver_data == NULL);711 712 data = calloc(1, size);713 if (data == NULL)714 return NULL;715 716 dev->driver_data = data;717 return data;718 }719 720 506 /** Create a DDF function node. 721 507 * … … 749 535 return NULL; 750 536 751 /* Add one reference that will be dropped by ddf_fun_destroy() */537 fun->bound = false; 752 538 fun->dev = dev; 753 fun_add_ref(fun);754 755 fun->bound = false;756 539 fun->ftype = ftype; 757 540 … … 765 548 } 766 549 767 /** Allocate driver-specific function data. */768 extern void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size)769 {770 void *data;771 772 assert(fun->bound == false);773 assert(fun->driver_data == NULL);774 775 data = calloc(1, size);776 if (data == NULL)777 return NULL;778 779 fun->driver_data = data;780 return data;781 }782 783 550 /** Destroy DDF function node. 784 551 * … … 791 558 { 792 559 assert(fun->bound == false); 793 794 /* 795 * Drop the reference added by ddf_fun_create(). This will deallocate 796 * the function as soon as all other references are dropped (i.e. 797 * as soon control leaves all driver entry points called in context 798 * of this function. 799 */ 800 fun_del_ref(fun); 560 delete_function(fun); 801 561 } 802 562 … … 823 583 int ddf_fun_bind(ddf_fun_t *fun) 824 584 { 825 assert(fun->bound == false);826 585 assert(fun->name != NULL); 827 586 … … 840 599 } 841 600 842 /** Unbind a function node.843 *844 * Unbind the specified function from the system. This effectively makes845 * the function invisible to the system.846 *847 * @param fun Function to unbind848 * @return EOK on success or negative error code849 */850 int ddf_fun_unbind(ddf_fun_t *fun)851 {852 int res;853 854 assert(fun->bound == true);855 856 res = devman_remove_function(fun->handle);857 if (res != EOK)858 return res;859 860 remove_from_functions_list(fun);861 862 fun->bound = false;863 return EOK;864 }865 866 /** Online function.867 *868 * @param fun Function to online869 * @return EOK on success or negative error code870 */871 int ddf_fun_online(ddf_fun_t *fun)872 {873 int res;874 875 assert(fun->bound == true);876 877 res = devman_drv_fun_online(fun->handle);878 if (res != EOK)879 return res;880 881 return EOK;882 }883 884 /** Offline function.885 *886 * @param fun Function to offline887 * @return EOK on success or negative error code888 */889 int ddf_fun_offline(ddf_fun_t *fun)890 {891 int res;892 893 assert(fun->bound == true);894 895 res = devman_drv_fun_offline(fun->handle);896 if (res != EOK)897 return res;898 899 return EOK;900 }901 902 601 /** Add single match ID to inner function. 903 602 * … … 922 621 return ENOMEM; 923 622 924 match_id->id = str_dup(match_id_str);623 match_id->id = match_id_str; 925 624 match_id->score = 90; 926 625 … … 937 636 } 938 637 939 /** Add exposed function to c ategory.638 /** Add exposed function to class. 940 639 * 941 640 * Must only be called when the function is bound. 942 641 */ 943 int ddf_fun_add_to_c ategory(ddf_fun_t *fun, const char *cat_name)642 int ddf_fun_add_to_class(ddf_fun_t *fun, const char *class_name) 944 643 { 945 644 assert(fun->bound == true); 946 645 assert(fun->ftype == fun_exposed); 947 646 948 return devman_add_device_to_c ategory(fun->handle, cat_name);647 return devman_add_device_to_class(fun->handle, class_name); 949 648 } 950 649
Note:
See TracChangeset
for help on using the changeset viewer.