Changeset a35b458 in mainline for uspace/lib/drv/generic/driver.c
- Timestamp:
- 2018-03-02T20:10:49Z (7 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- f1380b7
- Parents:
- 3061bc1
- git-author:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-02-28 17:38:31)
- git-committer:
- Jiří Zárevúcky <zarevucky.jiri@…> (2018-03-02 20:10:49)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/lib/drv/generic/driver.c
r3061bc1 ra35b458 97 97 { 98 98 assert(fibril_mutex_is_locked(&devices_mutex)); 99 99 100 100 list_foreach(devices, link, ddf_dev_t, dev) { 101 101 if (dev->handle == handle) 102 102 return dev; 103 103 } 104 104 105 105 return NULL; 106 106 } … … 109 109 { 110 110 assert(fibril_mutex_is_locked(&functions_mutex)); 111 111 112 112 list_foreach(functions, link, ddf_fun_t, fun) { 113 113 if (fun->handle == handle) 114 114 return fun; 115 115 } 116 116 117 117 return NULL; 118 118 } … … 122 122 devman_handle_t dev_handle = IPC_GET_ARG1(*icall); 123 123 devman_handle_t parent_fun_handle = IPC_GET_ARG2(*icall); 124 124 125 125 char *dev_name = NULL; 126 126 errno_t rc = async_data_write_accept((void **) &dev_name, true, 0, 0, 0, 0); … … 129 129 return; 130 130 } 131 131 132 132 fibril_rwlock_read_lock(&stopping_lock); 133 133 … … 137 137 return; 138 138 } 139 139 140 140 ddf_dev_t *dev = create_device(); 141 141 if (!dev) { … … 145 145 return; 146 146 } 147 147 148 148 /* Add one reference that will be dropped by driver_dev_remove() */ 149 149 dev_add_ref(dev); 150 150 dev->handle = dev_handle; 151 151 dev->name = dev_name; 152 152 153 153 /* 154 154 * Currently not used, parent fun handle is stored in context … … 156 156 */ 157 157 (void) parent_fun_handle; 158 158 159 159 errno_t res = driver->driver_ops->dev_add(dev); 160 160 161 161 if (res != EOK) { 162 162 fibril_rwlock_read_unlock(&stopping_lock); … … 165 165 return; 166 166 } 167 167 168 168 fibril_mutex_lock(&devices_mutex); 169 169 list_append(&dev->link, &devices); 170 170 fibril_mutex_unlock(&devices_mutex); 171 171 fibril_rwlock_read_unlock(&stopping_lock); 172 172 173 173 async_answer_0(iid, res); 174 174 } … … 177 177 { 178 178 devman_handle_t devh = IPC_GET_ARG1(*icall); 179 179 180 180 fibril_mutex_lock(&devices_mutex); 181 181 ddf_dev_t *dev = driver_get_device(devh); … … 183 183 dev_add_ref(dev); 184 184 fibril_mutex_unlock(&devices_mutex); 185 185 186 186 if (dev == NULL) { 187 187 async_answer_0(iid, ENOENT); 188 188 return; 189 189 } 190 190 191 191 errno_t rc; 192 192 193 193 if (driver->driver_ops->dev_remove != NULL) 194 194 rc = driver->driver_ops->dev_remove(dev); 195 195 else 196 196 rc = ENOTSUP; 197 197 198 198 if (rc == EOK) { 199 199 fibril_mutex_lock(&devices_mutex); … … 202 202 dev_del_ref(dev); 203 203 } 204 204 205 205 dev_del_ref(dev); 206 206 async_answer_0(iid, rc); … … 210 210 { 211 211 devman_handle_t devh = IPC_GET_ARG1(*icall); 212 212 213 213 fibril_mutex_lock(&devices_mutex); 214 214 ddf_dev_t *dev = driver_get_device(devh); … … 216 216 dev_add_ref(dev); 217 217 fibril_mutex_unlock(&devices_mutex); 218 218 219 219 if (dev == NULL) { 220 220 async_answer_0(iid, ENOENT); 221 221 return; 222 222 } 223 223 224 224 errno_t rc; 225 225 226 226 if (driver->driver_ops->dev_gone != NULL) 227 227 rc = driver->driver_ops->dev_gone(dev); 228 228 else 229 229 rc = ENOTSUP; 230 230 231 231 if (rc == EOK) { 232 232 fibril_mutex_lock(&devices_mutex); … … 235 235 dev_del_ref(dev); 236 236 } 237 237 238 238 dev_del_ref(dev); 239 239 async_answer_0(iid, rc); … … 243 243 { 244 244 devman_handle_t funh = IPC_GET_ARG1(*icall); 245 245 246 246 /* 247 247 * Look the function up. Bump reference count so that … … 250 250 */ 251 251 fibril_mutex_lock(&functions_mutex); 252 252 253 253 ddf_fun_t *fun = driver_get_function(funh); 254 254 if (fun != NULL) 255 255 fun_add_ref(fun); 256 256 257 257 fibril_mutex_unlock(&functions_mutex); 258 258 259 259 if (fun == NULL) { 260 260 async_answer_0(iid, ENOENT); 261 261 return; 262 262 } 263 263 264 264 /* Call driver entry point */ 265 265 errno_t rc; 266 266 267 267 if (driver->driver_ops->fun_online != NULL) 268 268 rc = driver->driver_ops->fun_online(fun); 269 269 else 270 270 rc = ENOTSUP; 271 271 272 272 fun_del_ref(fun); 273 273 274 274 async_answer_0(iid, rc); 275 275 } … … 278 278 { 279 279 devman_handle_t funh = IPC_GET_ARG1(*icall); 280 280 281 281 /* 282 282 * Look the function up. Bump reference count so that … … 285 285 */ 286 286 fibril_mutex_lock(&functions_mutex); 287 287 288 288 ddf_fun_t *fun = driver_get_function(funh); 289 289 if (fun != NULL) 290 290 fun_add_ref(fun); 291 291 292 292 fibril_mutex_unlock(&functions_mutex); 293 293 294 294 if (fun == NULL) { 295 295 async_answer_0(iid, ENOENT); 296 296 return; 297 297 } 298 298 299 299 /* Call driver entry point */ 300 300 errno_t rc; 301 301 302 302 if (driver->driver_ops->fun_offline != NULL) 303 303 rc = driver->driver_ops->fun_offline(fun); 304 304 else 305 305 rc = ENOTSUP; 306 306 307 307 async_answer_0(iid, rc); 308 308 } … … 342 342 /* Accept connection */ 343 343 async_answer_0(iid, EOK); 344 344 345 345 while (true) { 346 346 ipc_call_t call; 347 347 ipc_callid_t callid = async_get_call(&call); 348 348 349 349 if (!IPC_GET_IMETHOD(call)) 350 350 break; 351 351 352 352 switch (IPC_GET_IMETHOD(call)) { 353 353 case DRIVER_DEV_ADD: … … 394 394 fun_add_ref(fun); 395 395 fibril_mutex_unlock(&functions_mutex); 396 396 397 397 if (fun == NULL) { 398 398 printf("%s: driver_connection_gen error - no function with handle" … … 401 401 return; 402 402 } 403 403 404 404 if (fun->conn_handler != NULL) { 405 405 /* Driver has a custom connection handler. */ … … 408 408 return; 409 409 } 410 410 411 411 /* 412 412 * TODO - if the client is not a driver, check whether it is allowed to 413 413 * use the device. 414 414 */ 415 415 416 416 errno_t ret = EOK; 417 417 /* Open device function */ 418 418 if (fun->ops != NULL && fun->ops->open != NULL) 419 419 ret = (*fun->ops->open)(fun); 420 420 421 421 async_answer_0(iid, ret); 422 422 if (ret != EOK) { … … 424 424 return; 425 425 } 426 426 427 427 while (true) { 428 428 ipc_callid_t callid; … … 430 430 callid = async_get_call(&call); 431 431 sysarg_t method = IPC_GET_IMETHOD(call); 432 432 433 433 if (!method) { 434 434 /* Close device function */ … … 439 439 return; 440 440 } 441 441 442 442 /* Convert ipc interface id to interface index */ 443 443 444 444 int iface_idx = DEV_IFACE_IDX(method); 445 445 446 446 if (!is_valid_iface_idx(iface_idx)) { 447 447 remote_handler_t *default_handler = … … 451 451 continue; 452 452 } 453 453 454 454 /* 455 455 * Function has no such interface and … … 462 462 continue; 463 463 } 464 464 465 465 /* Calling one of the function's interfaces */ 466 466 467 467 /* Get the interface ops structure. */ 468 468 void *ops = function_get_ops(fun, iface_idx); … … 474 474 continue; 475 475 } 476 476 477 477 /* 478 478 * Get the corresponding interface for remote request … … 481 481 const remote_iface_t *rem_iface = get_remote_iface(iface_idx); 482 482 assert(rem_iface != NULL); 483 483 484 484 /* get the method of the remote interface */ 485 485 sysarg_t iface_method_idx = IPC_GET_ARG1(call); … … 493 493 continue; 494 494 } 495 495 496 496 /* 497 497 * Call the remote interface's method, which will … … 624 624 { 625 625 assert(dev->driver_data == NULL); 626 626 627 627 void *data = calloc(1, size); 628 628 if (data == NULL) 629 629 return NULL; 630 630 631 631 dev->driver_data = data; 632 632 return data; … … 732 732 if (fun == NULL) 733 733 return NULL; 734 734 735 735 /* Add one reference that will be dropped by ddf_fun_destroy() */ 736 736 fun->dev = dev; 737 737 fun_add_ref(fun); 738 738 739 739 fun->bound = false; 740 740 fun->ftype = ftype; 741 741 742 742 if (name != NULL) { 743 743 fun->name = str_dup(name); … … 747 747 } 748 748 } 749 749 750 750 return fun; 751 751 } … … 756 756 assert(fun->bound == false); 757 757 assert(fun->driver_data == NULL); 758 758 759 759 void *data = calloc(1, size); 760 760 if (data == NULL) 761 761 return NULL; 762 762 763 763 fun->driver_data = data; 764 764 return data; … … 792 792 { 793 793 assert(fun->bound == false); 794 794 795 795 /* 796 796 * Drop the reference added by ddf_fun_create(). This will deallocate … … 807 807 if (fun->ops == NULL) 808 808 return NULL; 809 809 810 810 return fun->ops->interfaces[idx]; 811 811 } … … 830 830 assert(fun->name != NULL); 831 831 assert(fun->dev != NULL); 832 832 833 833 add_to_functions_list(fun); 834 834 errno_t res = devman_add_function(fun->name, fun->ftype, &fun->match_ids, … … 838 838 return res; 839 839 } 840 840 841 841 fun->bound = true; 842 842 return res; … … 856 856 { 857 857 assert(fun->bound == true); 858 858 859 859 errno_t res = devman_remove_function(fun->handle); 860 860 if (res != EOK) 861 861 return res; 862 862 863 863 remove_from_functions_list(fun); 864 864 865 865 fun->bound = false; 866 866 return EOK; … … 877 877 { 878 878 assert(fun->bound == true); 879 879 880 880 errno_t res = devman_drv_fun_online(fun->handle); 881 881 if (res != EOK) 882 882 return res; 883 883 884 884 return EOK; 885 885 } … … 895 895 { 896 896 assert(fun->bound == true); 897 897 898 898 errno_t res = devman_drv_fun_offline(fun->handle); 899 899 if (res != EOK) 900 900 return res; 901 901 902 902 return EOK; 903 903 } … … 921 921 assert(fun->bound == false); 922 922 assert(fun->ftype == fun_inner); 923 923 924 924 match_id_t *match_id = create_match_id(); 925 925 if (match_id == NULL) 926 926 return ENOMEM; 927 927 928 928 match_id->id = str_dup(match_id_str); 929 929 match_id->score = match_score; 930 930 931 931 add_match_id(&fun->match_ids, match_id); 932 932 return EOK; … … 967 967 assert(fun->bound == true); 968 968 assert(fun->ftype == fun_exposed); 969 969 970 970 return devman_add_device_to_category(fun->handle, cat_name); 971 971 } … … 978 978 */ 979 979 driver = drv; 980 980 981 981 /* 982 982 * Register driver with device manager using generic handler for … … 990 990 return rc; 991 991 } 992 992 993 993 rc = async_create_port(INTERFACE_DDF_DEVMAN, driver_connection_devman, 994 994 NULL, &port); … … 997 997 return rc; 998 998 } 999 999 1000 1000 async_set_fallback_port_handler(driver_connection_client, NULL); 1001 1001 1002 1002 rc = devman_driver_register(driver->name); 1003 1003 if (rc != EOK) { … … 1005 1005 "(%s).\n", (rc == EEXIST) ? "driver already started" : 1006 1006 str_error(rc)); 1007 1007 1008 1008 return rc; 1009 1009 } 1010 1010 1011 1011 /* Return success from the task since server has started. */ 1012 1012 rc = task_retval(0); … … 1015 1015 return rc; 1016 1016 } 1017 1017 1018 1018 async_manager(); 1019 1019 1020 1020 /* Never reached. */ 1021 1021 return EOK;
Note:
See TracChangeset
for help on using the changeset viewer.