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