Changes in uspace/lib/drv/generic/driver.c [a996ae31:77ad86c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/driver.c
ra996ae31 r77ad86c 70 70 FIBRIL_MUTEX_INITIALIZE(functions_mutex); 71 71 72 /** Interrupts */73 static interrupt_context_list_t interrupt_contexts;74 75 static irq_cmd_t default_cmds[] = {76 {77 .cmd = CMD_ACCEPT78 }79 };80 81 static irq_code_t default_pseudocode = {82 0,83 NULL,84 sizeof(default_cmds) / sizeof(irq_cmd_t),85 default_cmds86 };87 88 72 static ddf_dev_t *create_device(void); 89 73 static void delete_device(ddf_dev_t *); … … 95 79 static void *function_get_ops(ddf_fun_t *, dev_inferface_idx_t); 96 80 97 static void driver_irq_handler(ipc_callid_t iid, ipc_call_t *icall)98 {99 int id = (int)IPC_GET_IMETHOD(*icall);100 interrupt_context_t *ctx;101 102 ctx = find_interrupt_context_by_id(&interrupt_contexts, id);103 if (ctx != NULL && ctx->handler != NULL)104 (*ctx->handler)(ctx->dev, iid, icall);105 }106 107 interrupt_context_t *create_interrupt_context(void)108 {109 interrupt_context_t *ctx;110 111 ctx = (interrupt_context_t *) malloc(sizeof(interrupt_context_t));112 if (ctx != NULL)113 memset(ctx, 0, sizeof(interrupt_context_t));114 115 return ctx;116 }117 118 void delete_interrupt_context(interrupt_context_t *ctx)119 {120 if (ctx != NULL)121 free(ctx);122 }123 124 void init_interrupt_context_list(interrupt_context_list_t *list)125 {126 memset(list, 0, sizeof(interrupt_context_list_t));127 fibril_mutex_initialize(&list->mutex);128 list_initialize(&list->contexts);129 }130 131 void132 add_interrupt_context(interrupt_context_list_t *list, interrupt_context_t *ctx)133 {134 fibril_mutex_lock(&list->mutex);135 ctx->id = list->curr_id++;136 list_append(&ctx->link, &list->contexts);137 fibril_mutex_unlock(&list->mutex);138 }139 140 void remove_interrupt_context(interrupt_context_list_t *list,141 interrupt_context_t *ctx)142 {143 fibril_mutex_lock(&list->mutex);144 list_remove(&ctx->link);145 fibril_mutex_unlock(&list->mutex);146 }147 148 interrupt_context_t *149 find_interrupt_context_by_id(interrupt_context_list_t *list, int id)150 {151 interrupt_context_t *ctx;152 153 fibril_mutex_lock(&list->mutex);154 155 list_foreach(list->contexts, link) {156 ctx = list_get_instance(link, interrupt_context_t, link);157 if (ctx->id == id) {158 fibril_mutex_unlock(&list->mutex);159 return ctx;160 }161 }162 163 fibril_mutex_unlock(&list->mutex);164 return NULL;165 }166 167 interrupt_context_t *168 find_interrupt_context(interrupt_context_list_t *list, ddf_dev_t *dev, int irq)169 {170 interrupt_context_t *ctx;171 172 fibril_mutex_lock(&list->mutex);173 174 list_foreach(list->contexts, link) {175 ctx = list_get_instance(link, interrupt_context_t, link);176 if (ctx->irq == irq && ctx->dev == dev) {177 fibril_mutex_unlock(&list->mutex);178 return ctx;179 }180 }181 182 fibril_mutex_unlock(&list->mutex);183 return NULL;184 }185 186 187 int188 register_interrupt_handler(ddf_dev_t *dev, int irq, interrupt_handler_t *handler,189 irq_code_t *pseudocode)190 {191 interrupt_context_t *ctx = create_interrupt_context();192 193 ctx->dev = dev;194 ctx->irq = irq;195 ctx->handler = handler;196 197 add_interrupt_context(&interrupt_contexts, ctx);198 199 if (pseudocode == NULL)200 pseudocode = &default_pseudocode;201 202 int res = irq_register(irq, dev->handle, ctx->id, pseudocode);203 if (res != EOK) {204 remove_interrupt_context(&interrupt_contexts, ctx);205 delete_interrupt_context(ctx);206 }207 208 return res;209 }210 211 int unregister_interrupt_handler(ddf_dev_t *dev, int irq)212 {213 interrupt_context_t *ctx = find_interrupt_context(&interrupt_contexts,214 dev, irq);215 int res = irq_unregister(irq, dev->handle);216 217 if (ctx != NULL) {218 remove_interrupt_context(&interrupt_contexts, ctx);219 delete_interrupt_context(ctx);220 }221 222 return res;223 }224 225 81 static void add_to_functions_list(ddf_fun_t *fun) 226 82 { … … 269 125 static void driver_dev_add(ipc_callid_t iid, ipc_call_t *icall) 270 126 { 271 char *dev_name = NULL;272 int res;273 274 127 devman_handle_t dev_handle = IPC_GET_ARG1(*icall); 275 128 devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall); 276 129 277 130 ddf_dev_t *dev = create_device(); 278 131 279 132 /* Add one reference that will be dropped by driver_dev_remove() */ 280 133 dev_add_ref(dev); 281 134 dev->handle = dev_handle; 282 135 136 char *dev_name = NULL; 283 137 async_data_write_accept((void **) &dev_name, true, 0, 0, 0, 0); 284 138 dev->name = dev_name; 285 139 286 140 /* 287 141 * Currently not used, parent fun handle is stored in context … … 290 144 (void) parent_fun_handle; 291 145 292 res = driver->driver_ops->dev_add(dev);146 int res = driver->driver_ops->dev_add(dev); 293 147 294 148 if (res != EOK) { … … 305 159 } 306 160 307 static void driver_dev_added(ipc_callid_t iid, ipc_call_t *icall) 308 { 161 static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall) 162 { 163 devman_handle_t devh = IPC_GET_ARG1(*icall); 164 309 165 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); 166 ddf_dev_t *dev = driver_get_device(devh); 327 167 if (dev != NULL) 328 168 dev_add_ref(dev); … … 333 173 return; 334 174 } 175 176 int rc; 335 177 336 178 if (driver->driver_ops->dev_remove != NULL) … … 347 189 static void driver_dev_gone(ipc_callid_t iid, ipc_call_t *icall) 348 190 { 349 devman_handle_t devh; 350 ddf_dev_t *dev; 351 int rc; 352 353 devh = IPC_GET_ARG1(*icall); 191 devman_handle_t devh = IPC_GET_ARG1(*icall); 354 192 355 193 fibril_mutex_lock(&devices_mutex); 356 d ev = driver_get_device(devh);194 ddf_dev_t *dev = driver_get_device(devh); 357 195 if (dev != NULL) 358 196 dev_add_ref(dev); … … 363 201 return; 364 202 } 203 204 int rc; 365 205 366 206 if (driver->driver_ops->dev_gone != NULL) … … 377 217 static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall) 378 218 { 379 devman_handle_t funh; 380 ddf_fun_t *fun; 381 int rc; 382 383 funh = IPC_GET_ARG1(*icall); 219 devman_handle_t funh = IPC_GET_ARG1(*icall); 384 220 385 221 /* … … 390 226 fibril_mutex_lock(&functions_mutex); 391 227 392 fun = driver_get_function(funh);228 ddf_fun_t *fun = driver_get_function(funh); 393 229 if (fun != NULL) 394 230 fun_add_ref(fun); … … 402 238 403 239 /* Call driver entry point */ 240 int rc; 241 404 242 if (driver->driver_ops->fun_online != NULL) 405 243 rc = driver->driver_ops->fun_online(fun); … … 414 252 static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall) 415 253 { 416 devman_handle_t funh; 417 ddf_fun_t *fun; 418 int rc; 419 420 funh = IPC_GET_ARG1(*icall); 254 devman_handle_t funh = IPC_GET_ARG1(*icall); 421 255 422 256 /* … … 427 261 fibril_mutex_lock(&functions_mutex); 428 262 429 fun = driver_get_function(funh);263 ddf_fun_t *fun = driver_get_function(funh); 430 264 if (fun != NULL) 431 265 fun_add_ref(fun); … … 439 273 440 274 /* Call driver entry point */ 275 int rc; 276 441 277 if (driver->driver_ops->fun_offline != NULL) 442 278 rc = driver->driver_ops->fun_offline(fun); … … 462 298 case DRIVER_DEV_ADD: 463 299 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 300 break; 469 301 case DRIVER_DEV_REMOVE: … … 753 585 754 586 /** Allocate driver-specific device data. */ 755 extern void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size) 756 { 757 void *data; 758 587 void *ddf_dev_data_alloc(ddf_dev_t *dev, size_t size) 588 { 759 589 assert(dev->driver_data == NULL); 760 761 data = calloc(1, size);590 591 void *data = calloc(1, size); 762 592 if (data == NULL) 763 593 return NULL; 764 594 765 595 dev->driver_data = data; 766 596 return data; … … 792 622 ddf_fun_t *ddf_fun_create(ddf_dev_t *dev, fun_type_t ftype, const char *name) 793 623 { 794 ddf_fun_t *fun; 795 796 fun = create_function(); 624 ddf_fun_t *fun = create_function(); 797 625 if (fun == NULL) 798 626 return NULL; 799 627 800 628 /* Add one reference that will be dropped by ddf_fun_destroy() */ 801 629 fun->dev = dev; 802 630 fun_add_ref(fun); 803 631 804 632 fun->bound = false; 805 633 fun->ftype = ftype; 806 634 807 635 fun->name = str_dup(name); 808 636 if (fun->name == NULL) { … … 810 638 return NULL; 811 639 } 812 640 813 641 return fun; 814 642 } 815 643 816 644 /** Allocate driver-specific function data. */ 817 extern void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size) 818 { 819 void *data; 820 645 void *ddf_fun_data_alloc(ddf_fun_t *fun, size_t size) 646 { 821 647 assert(fun->bound == false); 822 648 assert(fun->driver_data == NULL); 823 824 data = calloc(1, size);649 650 void *data = calloc(1, size); 825 651 if (data == NULL) 826 652 return NULL; 827 653 828 654 fun->driver_data = data; 829 655 return data; … … 835 661 * must not be bound. 836 662 * 837 * @param fun Function to destroy 663 * @param fun Function to destroy 664 * 838 665 */ 839 666 void ddf_fun_destroy(ddf_fun_t *fun) 840 667 { 841 668 assert(fun->bound == false); 842 669 843 670 /* 844 671 * Drop the reference added by ddf_fun_create(). This will deallocate … … 855 682 if (fun->ops == NULL) 856 683 return NULL; 684 857 685 return fun->ops->interfaces[idx]; 858 686 } … … 867 695 * the same name. 868 696 * 869 * @param fun Function to bind 870 * @return EOK on success or negative error code 697 * @param fun Function to bind 698 * 699 * @return EOK on success or negative error code 700 * 871 701 */ 872 702 int ddf_fun_bind(ddf_fun_t *fun) … … 875 705 assert(fun->name != NULL); 876 706 877 int res;878 879 707 add_to_functions_list(fun); 880 res = devman_add_function(fun->name, fun->ftype, &fun->match_ids,708 int res = devman_add_function(fun->name, fun->ftype, &fun->match_ids, 881 709 fun->dev->handle, &fun->handle); 882 710 if (res != EOK) { … … 894 722 * the function invisible to the system. 895 723 * 896 * @param fun Function to unbind 897 * @return EOK on success or negative error code 724 * @param fun Function to unbind 725 * 726 * @return EOK on success or negative error code 727 * 898 728 */ 899 729 int ddf_fun_unbind(ddf_fun_t *fun) 900 730 { 901 int res;902 903 731 assert(fun->bound == true); 904 732 905 res = devman_remove_function(fun->handle);733 int res = devman_remove_function(fun->handle); 906 734 if (res != EOK) 907 735 return res; 908 736 909 737 remove_from_functions_list(fun); 910 738 … … 915 743 /** Online function. 916 744 * 917 * @param fun Function to online 918 * @return EOK on success or negative error code 745 * @param fun Function to online 746 * 747 * @return EOK on success or negative error code 748 * 919 749 */ 920 750 int ddf_fun_online(ddf_fun_t *fun) 921 751 { 922 int res;923 924 752 assert(fun->bound == true); 925 753 926 res = devman_drv_fun_online(fun->handle);754 int res = devman_drv_fun_online(fun->handle); 927 755 if (res != EOK) 928 756 return res; … … 933 761 /** Offline function. 934 762 * 935 * @param fun Function to offline 936 * @return EOK on success or negative error code 763 * @param fun Function to offline 764 * 765 * @return EOK on success or negative error code 766 * 937 767 */ 938 768 int ddf_fun_offline(ddf_fun_t *fun) 939 769 { 940 int res;941 942 770 assert(fun->bound == true); 943 771 944 res = devman_drv_fun_offline(fun->handle);772 int res = devman_drv_fun_offline(fun->handle); 945 773 if (res != EOK) 946 774 return res; … … 954 782 * Cannot be called when the function node is bound. 955 783 * 956 * @param fun Function 957 * @param match_id_str Match string 958 * @param match_score Match score 959 * @return EOK on success, ENOMEM if out of memory. 784 * @param fun Function 785 * @param match_id_str Match string 786 * @param match_score Match score 787 * 788 * @return EOK on success. 789 * @return ENOMEM if out of memory. 790 * 960 791 */ 961 792 int ddf_fun_add_match_id(ddf_fun_t *fun, const char *match_id_str, 962 793 int match_score) 963 794 { 964 match_id_t *match_id;965 966 795 assert(fun->bound == false); 967 796 assert(fun->ftype == fun_inner); 968 797 969 match_id = create_match_id();798 match_id_t *match_id = create_match_id(); 970 799 if (match_id == NULL) 971 800 return ENOMEM; … … 989 818 * 990 819 * Must only be called when the function is bound. 820 * 991 821 */ 992 822 int ddf_fun_add_to_category(ddf_fun_t *fun, const char *cat_name) … … 1000 830 int ddf_driver_main(driver_t *drv) 1001 831 { 1002 int rc;1003 1004 832 /* 1005 833 * Remember the driver structure - driver_ops will be called by generic … … 1008 836 driver = drv; 1009 837 1010 /* Initialize the list of interrupt contexts. */ 1011 init_interrupt_context_list(&interrupt_contexts); 1012 1013 /* Set generic interrupt handler. */ 1014 async_set_interrupt_received(driver_irq_handler); 838 /* Initialize interrupt module */ 839 interrupt_init(); 1015 840 1016 841 /* … … 1019 844 */ 1020 845 async_set_client_connection(driver_connection); 1021 rc = devman_driver_register(driver->name);846 int rc = devman_driver_register(driver->name); 1022 847 if (rc != EOK) { 1023 848 printf("Error: Failed to register driver with device manager " … … 1025 850 str_error(rc)); 1026 851 1027 return 1;852 return rc; 1028 853 } 1029 854 … … 1031 856 rc = task_retval(0); 1032 857 if (rc != EOK) 1033 return 1;1034 858 return rc; 859 1035 860 async_manager(); 1036 861 1037 862 /* Never reached. */ 1038 return 0;863 return EOK; 1039 864 } 1040 865
Note:
See TracChangeset
for help on using the changeset viewer.