Changes in uspace/lib/drv/generic/driver.c [45059d6b:a996ae31] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/driver.c
r45059d6b ra996ae31 63 63 64 64 /** Devices */ 65 LIST_INITIALIZE(devices); 66 FIBRIL_MUTEX_INITIALIZE(devices_mutex); 67 68 /** Functions */ 65 69 LIST_INITIALIZE(functions); 66 70 FIBRIL_MUTEX_INITIALIZE(functions_mutex); … … 76 80 77 81 static irq_code_t default_pseudocode = { 82 0, 83 NULL, 78 84 sizeof(default_cmds) / sizeof(irq_cmd_t), 79 85 default_cmds … … 82 88 static ddf_dev_t *create_device(void); 83 89 static void delete_device(ddf_dev_t *); 90 static void dev_add_ref(ddf_dev_t *); 91 static void dev_del_ref(ddf_dev_t *); 92 static void fun_add_ref(ddf_fun_t *); 93 static void fun_del_ref(ddf_fun_t *); 84 94 static remote_handler_t *function_get_default_handler(ddf_fun_t *); 85 95 static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t); … … 190 200 pseudocode = &default_pseudocode; 191 201 192 int res = register_irq(irq, dev->handle, ctx->id, pseudocode);202 int res = irq_register(irq, dev->handle, ctx->id, pseudocode); 193 203 if (res != EOK) { 194 204 remove_interrupt_context(&interrupt_contexts, ctx); … … 203 213 interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts, 204 214 dev, irq); 205 int res = unregister_irq(irq, dev->handle);215 int res = irq_unregister(irq, dev->handle); 206 216 207 217 if (ctx != NULL) { … … 227 237 } 228 238 229 static ddf_fun_t *driver_get_function(list_t *functions, devman_handle_t handle) 239 static ddf_dev_t *driver_get_device(devman_handle_t handle) 240 { 241 ddf_dev_t *dev = NULL; 242 243 assert(fibril_mutex_is_locked(&devices_mutex)); 244 245 list_foreach(devices, link) { 246 dev = list_get_instance(link, ddf_dev_t, link); 247 if (dev->handle == handle) 248 return dev; 249 } 250 251 return NULL; 252 } 253 254 static ddf_fun_t *driver_get_function(devman_handle_t handle) 230 255 { 231 256 ddf_fun_t *fun = NULL; 232 257 233 fibril_mutex_lock(&functions_mutex);234 235 list_foreach( *functions, link) {258 assert(fibril_mutex_is_locked(&functions_mutex)); 259 260 list_foreach(functions, link) { 236 261 fun = list_get_instance(link, ddf_fun_t, link); 237 if (fun->handle == handle) { 238 fibril_mutex_unlock(&functions_mutex); 262 if (fun->handle == handle) 239 263 return fun; 240 } 241 } 242 243 fibril_mutex_unlock(&functions_mutex); 264 } 244 265 245 266 return NULL; 246 267 } 247 268 248 static void driver_ add_device(ipc_callid_t iid, ipc_call_t *icall)269 static void driver_dev_add(ipc_callid_t iid, ipc_call_t *icall) 249 270 { 250 271 char *dev_name = NULL; … … 252 273 253 274 devman_handle_t dev_handle = IPC_GET_ARG1(*icall); 254 275 devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall); 255 276 256 277 ddf_dev_t *dev = create_device(); 278 279 /* Add one reference that will be dropped by driver_dev_remove() */ 280 dev_add_ref(dev); 257 281 dev->handle = dev_handle; 258 282 … … 266 290 (void) parent_fun_handle; 267 291 268 res = driver->driver_ops->add_device(dev); 269 if (res != EOK) 270 delete_device(dev); 292 res = driver->driver_ops->dev_add(dev); 293 294 if (res != EOK) { 295 dev_del_ref(dev); 296 async_answer_0(iid, res); 297 return; 298 } 299 300 fibril_mutex_lock(&devices_mutex); 301 list_append(&dev->link, &devices); 302 fibril_mutex_unlock(&devices_mutex); 271 303 272 304 async_answer_0(iid, res); 305 } 306 307 static void driver_dev_added(ipc_callid_t iid, ipc_call_t *icall) 308 { 309 fibril_mutex_lock(&devices_mutex); 310 ddf_dev_t *dev = driver_get_device(IPC_GET_ARG1(*icall)); 311 fibril_mutex_unlock(&devices_mutex); 312 313 if (dev != NULL && driver->driver_ops->device_added != NULL) 314 driver->driver_ops->device_added(dev); 315 } 316 317 static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall) 318 { 319 devman_handle_t devh; 320 ddf_dev_t *dev; 321 int rc; 322 323 devh = IPC_GET_ARG1(*icall); 324 325 fibril_mutex_lock(&devices_mutex); 326 dev = driver_get_device(devh); 327 if (dev != NULL) 328 dev_add_ref(dev); 329 fibril_mutex_unlock(&devices_mutex); 330 331 if (dev == NULL) { 332 async_answer_0(iid, ENOENT); 333 return; 334 } 335 336 if (driver->driver_ops->dev_remove != NULL) 337 rc = driver->driver_ops->dev_remove(dev); 338 else 339 rc = ENOTSUP; 340 341 if (rc == EOK) 342 dev_del_ref(dev); 343 344 async_answer_0(iid, (sysarg_t) rc); 345 } 346 347 static void driver_dev_gone(ipc_callid_t iid, ipc_call_t *icall) 348 { 349 devman_handle_t devh; 350 ddf_dev_t *dev; 351 int rc; 352 353 devh = IPC_GET_ARG1(*icall); 354 355 fibril_mutex_lock(&devices_mutex); 356 dev = driver_get_device(devh); 357 if (dev != NULL) 358 dev_add_ref(dev); 359 fibril_mutex_unlock(&devices_mutex); 360 361 if (dev == NULL) { 362 async_answer_0(iid, ENOENT); 363 return; 364 } 365 366 if (driver->driver_ops->dev_gone != NULL) 367 rc = driver->driver_ops->dev_gone(dev); 368 else 369 rc = ENOTSUP; 370 371 if (rc == EOK) 372 dev_del_ref(dev); 373 374 async_answer_0(iid, (sysarg_t) rc); 375 } 376 377 static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall) 378 { 379 devman_handle_t funh; 380 ddf_fun_t *fun; 381 int rc; 382 383 funh = IPC_GET_ARG1(*icall); 384 385 /* 386 * Look the function up. Bump reference count so that 387 * the function continues to exist until we return 388 * from the driver. 389 */ 390 fibril_mutex_lock(&functions_mutex); 391 392 fun = driver_get_function(funh); 393 if (fun != NULL) 394 fun_add_ref(fun); 395 396 fibril_mutex_unlock(&functions_mutex); 397 398 if (fun == NULL) { 399 async_answer_0(iid, ENOENT); 400 return; 401 } 402 403 /* Call driver entry point */ 404 if (driver->driver_ops->fun_online != NULL) 405 rc = driver->driver_ops->fun_online(fun); 406 else 407 rc = ENOTSUP; 408 409 fun_del_ref(fun); 410 411 async_answer_0(iid, (sysarg_t) rc); 412 } 413 414 static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall) 415 { 416 devman_handle_t funh; 417 ddf_fun_t *fun; 418 int rc; 419 420 funh = IPC_GET_ARG1(*icall); 421 422 /* 423 * Look the function up. Bump reference count so that 424 * the function continues to exist until we return 425 * from the driver. 426 */ 427 fibril_mutex_lock(&functions_mutex); 428 429 fun = driver_get_function(funh); 430 if (fun != NULL) 431 fun_add_ref(fun); 432 433 fibril_mutex_unlock(&functions_mutex); 434 435 if (fun == NULL) { 436 async_answer_0(iid, ENOENT); 437 return; 438 } 439 440 /* Call driver entry point */ 441 if (driver->driver_ops->fun_offline != NULL) 442 rc = driver->driver_ops->fun_offline(fun); 443 else 444 rc = ENOTSUP; 445 446 async_answer_0(iid, (sysarg_t) rc); 273 447 } 274 448 … … 286 460 287 461 switch (IPC_GET_IMETHOD(call)) { 288 case DRIVER_ADD_DEVICE: 289 driver_add_device(callid, &call); 462 case DRIVER_DEV_ADD: 463 driver_dev_add(callid, &call); 464 break; 465 case DRIVER_DEV_ADDED: 466 async_answer_0(callid, EOK); 467 driver_dev_added(callid, &call); 468 break; 469 case DRIVER_DEV_REMOVE: 470 driver_dev_remove(callid, &call); 471 break; 472 case DRIVER_DEV_GONE: 473 driver_dev_gone(callid, &call); 474 break; 475 case DRIVER_FUN_ONLINE: 476 driver_fun_online(callid, &call); 477 break; 478 case DRIVER_FUN_OFFLINE: 479 driver_fun_offline(callid, &call); 290 480 break; 291 481 default: 292 async_answer_0(callid, ENO ENT);482 async_answer_0(callid, ENOTSUP); 293 483 } 294 484 } … … 308 498 */ 309 499 devman_handle_t handle = IPC_GET_ARG2(*icall); 310 ddf_fun_t *fun = driver_get_function(&functions, handle); 500 501 fibril_mutex_lock(&functions_mutex); 502 ddf_fun_t *fun = driver_get_function(handle); 503 fibril_mutex_unlock(&functions_mutex); 504 /* XXX Need a lock on fun */ 311 505 312 506 if (fun == NULL) { … … 466 660 ddf_dev_t *dev; 467 661 468 dev = malloc(sizeof(ddf_dev_t));662 dev = calloc(1, sizeof(ddf_dev_t)); 469 663 if (dev == NULL) 470 664 return NULL; 471 665 472 memset(dev, 0, sizeof(ddf_dev_t));473 666 return dev; 474 667 } … … 498 691 static void delete_device(ddf_dev_t *dev) 499 692 { 693 if (dev->driver_data != NULL) 694 free(dev->driver_data); 500 695 free(dev); 501 696 } 502 697 503 /** Delete devicestructure.698 /** Delete function structure. 504 699 * 505 700 * @param dev The device structure. … … 508 703 { 509 704 clean_match_ids(&fun->match_ids); 705 if (fun->driver_data != NULL) 706 free(fun->driver_data); 510 707 if (fun->name != NULL) 511 708 free(fun->name); … … 513 710 } 514 711 712 /** Increase device reference count. */ 713 static void dev_add_ref(ddf_dev_t *dev) 714 { 715 atomic_inc(&dev->refcnt); 716 } 717 718 /** Decrease device reference count. 719 * 720 * Free the device structure if the reference count drops to zero. 721 */ 722 static void dev_del_ref(ddf_dev_t *dev) 723 { 724 if (atomic_predec(&dev->refcnt) == 0) 725 delete_device(dev); 726 } 727 728 /** Increase function reference count. 729 * 730 * This also increases reference count on the device. The device structure 731 * will thus not be deallocated while there are some associated function 732 * structures. 733 */ 734 static void fun_add_ref(ddf_fun_t *fun) 735 { 736 dev_add_ref(fun->dev); 737 atomic_inc(&fun->refcnt); 738 } 739 740 /** Decrease function reference count. 741 * 742 * Free the function structure if the reference count drops to zero. 743 */ 744 static void fun_del_ref(ddf_fun_t *fun) 745 { 746 ddf_dev_t *dev = fun->dev; 747 748 if (atomic_predec(&fun->refcnt) == 0) 749 delete_function(fun); 750 751 dev_del_ref(dev); 752 } 753 754 /** Allocate driver-specific device data. */ 755 extern void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size) 756 { 757 void *data; 758 759 assert(dev->driver_data == NULL); 760 761 data = calloc(1, size); 762 if (data == NULL) 763 return NULL; 764 765 dev->driver_data = data; 766 return data; 767 } 768 515 769 /** Create a DDF function node. 516 770 * … … 544 798 return NULL; 545 799 800 /* Add one reference that will be dropped by ddf_fun_destroy() */ 801 fun->dev = dev; 802 fun_add_ref(fun); 803 546 804 fun->bound = false; 547 fun->dev = dev;548 805 fun->ftype = ftype; 549 806 … … 557 814 } 558 815 816 /** Allocate driver-specific function data. */ 817 extern void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size) 818 { 819 void *data; 820 821 assert(fun->bound == false); 822 assert(fun->driver_data == NULL); 823 824 data = calloc(1, size); 825 if (data == NULL) 826 return NULL; 827 828 fun->driver_data = data; 829 return data; 830 } 831 559 832 /** Destroy DDF function node. 560 833 * … … 567 840 { 568 841 assert(fun->bound == false); 569 delete_function(fun); 842 843 /* 844 * Drop the reference added by ddf_fun_create(). This will deallocate 845 * the function as soon as all other references are dropped (i.e. 846 * as soon control leaves all driver entry points called in context 847 * of this function. 848 */ 849 fun_del_ref(fun); 570 850 } 571 851 … … 614 894 * the function invisible to the system. 615 895 * 616 * @param fun Function to bind896 * @param fun Function to unbind 617 897 * @return EOK on success or negative error code 618 898 */ … … 623 903 assert(fun->bound == true); 624 904 625 add_to_functions_list(fun);626 905 res = devman_remove_function(fun->handle); 627 906 if (res != EOK) … … 631 910 632 911 fun->bound = false; 912 return EOK; 913 } 914 915 /** Online function. 916 * 917 * @param fun Function to online 918 * @return EOK on success or negative error code 919 */ 920 int ddf_fun_online(ddf_fun_t *fun) 921 { 922 int res; 923 924 assert(fun->bound == true); 925 926 res = devman_drv_fun_online(fun->handle); 927 if (res != EOK) 928 return res; 929 930 return EOK; 931 } 932 933 /** Offline function. 934 * 935 * @param fun Function to offline 936 * @return EOK on success or negative error code 937 */ 938 int ddf_fun_offline(ddf_fun_t *fun) 939 { 940 int res; 941 942 assert(fun->bound == true); 943 944 res = devman_drv_fun_offline(fun->handle); 945 if (res != EOK) 946 return res; 947 633 948 return EOK; 634 949 } … … 657 972 658 973 match_id->id = str_dup(match_id_str); 659 match_id->score = 90;974 match_id->score = match_score; 660 975 661 976 add_match_id(&fun->match_ids, match_id); … … 703 1018 * incoming connections. 704 1019 */ 705 rc = devman_driver_register(driver->name, driver_connection); 1020 async_set_client_connection(driver_connection); 1021 rc = devman_driver_register(driver->name); 706 1022 if (rc != EOK) { 707 1023 printf("Error: Failed to register driver with device manager "
Note:
See TracChangeset
for help on using the changeset viewer.