Changeset 1a5b252 in mainline
- Timestamp:
- 2011-08-21T11:54:15Z (13 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 8cc4ddb
- Parents:
- e64df9a
- Location:
- uspace
- Files:
-
- 11 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/devctl/devctl.c
re64df9a r1a5b252 37 37 #include <stdio.h> 38 38 #include <stdlib.h> 39 #include <str_error.h> 39 40 #include <sys/typefmt.h> 40 41 … … 43 44 #define MAX_NAME_LENGTH 1024 44 45 45 static int fun_ tree_print(devman_handle_t funh, int lvl)46 static int fun_subtree_print(devman_handle_t funh, int lvl) 46 47 { 47 48 char name[MAX_NAME_LENGTH]; … … 84 85 85 86 for (i = 0; i < count; i++) 86 fun_ tree_print(cfuns[i], lvl + 1);87 fun_subtree_print(cfuns[i], lvl + 1); 87 88 88 89 free(cfuns); … … 90 91 } 91 92 92 int main(int argc, char *argv[])93 static int fun_tree_print(void) 93 94 { 94 95 devman_handle_t root_fun; … … 98 99 if (rc != EOK) { 99 100 printf(NAME ": Error resolving root function.\n"); 101 return EIO; 102 } 103 104 rc = fun_subtree_print(root_fun, 0); 105 if (rc != EOK) 106 return EIO; 107 108 return EOK; 109 } 110 111 static int fun_online(const char *path) 112 { 113 devman_handle_t funh; 114 int rc; 115 116 rc = devman_fun_get_handle(path, &funh, 0); 117 if (rc != EOK) { 118 printf(NAME ": Error resolving device function '%s' (%s)\n", 119 path, str_error(rc)); 120 return rc; 121 } 122 123 rc = devman_fun_online(funh); 124 if (rc != EOK) { 125 printf(NAME ": Failed to online function '%s'.\n", path); 126 return rc; 127 } 128 129 return EOK; 130 } 131 132 static int fun_offline(const char *path) 133 { 134 devman_handle_t funh; 135 int rc; 136 137 rc = devman_fun_get_handle(path, &funh, 0); 138 if (rc != EOK) { 139 printf(NAME ": Error resolving device function '%s' (%s)\n", 140 path, str_error(rc)); 141 return rc; 142 } 143 144 rc = devman_fun_offline(funh); 145 if (rc != EOK) { 146 printf(NAME ": Failed to offline function '%s'.\n", path); 147 return rc; 148 } 149 150 return EOK; 151 } 152 153 static void print_syntax(void) 154 { 155 printf("syntax: devctl [(online|offline) <function>]\n"); 156 } 157 158 int main(int argc, char *argv[]) 159 { 160 int rc; 161 162 if (argc == 1) { 163 rc = fun_tree_print(); 164 if (rc != EOK) 165 return 2; 166 } else if (str_cmp(argv[1], "online") == 0) { 167 if (argc < 3) { 168 printf(NAME ": Argument missing.\n"); 169 print_syntax(); 170 return 1; 171 } 172 173 rc = fun_online(argv[2]); 174 if (rc != EOK) { 175 return 2; 176 } 177 } else if (str_cmp(argv[1], "offline") == 0) { 178 if (argc < 3) { 179 printf(NAME ": Argument missing.\n"); 180 print_syntax(); 181 return 1; 182 } 183 184 rc = fun_offline(argv[2]); 185 if (rc != EOK) { 186 return 2; 187 } 188 } else { 189 printf(NAME ": Invalid argument '%s'.\n", argv[1]); 190 print_syntax(); 100 191 return 1; 101 192 } 102 103 rc = fun_tree_print(root_fun, 0);104 if (rc != EOK)105 return 1;106 193 107 194 return 0; -
uspace/drv/infrastructure/rootvirt/rootvirt.c
re64df9a r1a5b252 63 63 64 64 static int rootvirt_add_device(ddf_dev_t *dev); 65 static int rootvirt_fun_online(ddf_fun_t *fun); 66 static int rootvirt_fun_offline(ddf_fun_t *fun); 65 67 66 68 static driver_ops_t rootvirt_ops = { 67 .add_device = &rootvirt_add_device 69 .add_device = &rootvirt_add_device, 70 .fun_online = &rootvirt_fun_online, 71 .fun_offline = &rootvirt_fun_offline 68 72 }; 69 73 … … 140 144 } 141 145 146 static int rootvirt_fun_online(ddf_fun_t *fun) 147 { 148 ddf_msg(LVL_DEBUG, "rootvirt_fun_online()"); 149 return ddf_fun_online(fun); 150 } 151 152 static int rootvirt_fun_offline(ddf_fun_t *fun) 153 { 154 ddf_msg(LVL_DEBUG, "rootvirt_fun_offline()"); 155 return ddf_fun_offline(fun); 156 } 157 142 158 int main(int argc, char *argv[]) 143 159 { -
uspace/drv/test/test1/test1.c
re64df9a r1a5b252 1 1 /* 2 2 * Copyright (c) 2010 Vojtech Horky 3 * Copyright (c) 2011 Jiri Svoboda 3 4 * All rights reserved. 4 5 * … … 40 41 41 42 static int test1_add_device(ddf_dev_t *dev); 43 static int test1_dev_remove(ddf_dev_t *dev); 44 static int test1_fun_online(ddf_fun_t *fun); 45 static int test1_fun_offline(ddf_fun_t *fun); 42 46 43 47 static driver_ops_t driver_ops = { 44 .add_device = &test1_add_device 48 .add_device = &test1_add_device, 49 .dev_remove = &test1_dev_remove, 50 .fun_online = &test1_fun_online, 51 .fun_offline = &test1_fun_offline 45 52 }; 46 53 … … 49 56 .driver_ops = &driver_ops 50 57 }; 58 59 typedef struct { 60 ddf_fun_t *fun_a; 61 ddf_fun_t *clone; 62 ddf_fun_t *child; 63 } test1_t; 51 64 52 65 /** Register child and inform user about it. … … 60 73 static int register_fun_verbose(ddf_dev_t *parent, const char *message, 61 74 const char *name, const char *match_id, int match_score, 62 int expected_rc )75 int expected_rc, ddf_fun_t **pfun) 63 76 { 64 77 ddf_fun_t *fun = NULL; … … 103 116 } 104 117 118 if (pfun != NULL) 119 *pfun = fun; 120 105 121 return rc; 106 122 } … … 126 142 { 127 143 ddf_fun_t *fun_a; 144 test1_t *test1; 128 145 int rc; 129 146 130 147 ddf_msg(LVL_DEBUG, "add_device(name=\"%s\", handle=%d)", 131 148 dev->name, (int) dev->handle); 149 150 test1 = calloc(1, sizeof(test1_t)); 151 if (test1 == NULL) { 152 ddf_msg(LVL_ERROR, "Failed allocating softstate.\n"); 153 return ENOMEM; 154 } 132 155 133 156 fun_a = ddf_fun_create(dev, fun_exposed, "a"); … … 140 163 if (rc != EOK) { 141 164 ddf_msg(LVL_ERROR, "Failed binding function 'a'."); 165 ddf_fun_destroy(fun_a); 142 166 return rc; 143 167 } … … 151 175 (void) register_fun_verbose(dev, 152 176 "cloning myself ;-)", "clone", 153 "virtual&test1", 10, EOK );177 "virtual&test1", 10, EOK, &test1->clone); 154 178 (void) register_fun_verbose(dev, 155 179 "cloning myself twice ;-)", "clone", 156 "virtual&test1", 10, EEXISTS );180 "virtual&test1", 10, EEXISTS, NULL); 157 181 } else if (str_cmp(dev->name, "clone") == 0) { 158 182 (void) register_fun_verbose(dev, 159 183 "run by the same task", "child", 160 "virtual&test1&child", 10, EOK );184 "virtual&test1&child", 10, EOK, &test1->child); 161 185 } 162 186 163 187 ddf_msg(LVL_DEBUG, "Device `%s' accepted.", dev->name); 164 188 189 test1->fun_a = fun_a; 190 dev->driver_data = test1; 165 191 return EOK; 192 } 193 194 static int fun_remove(ddf_fun_t *fun, const char *name) 195 { 196 int rc; 197 198 ddf_msg(LVL_DEBUG, "fun_remove(%p, '%s')\n", fun, name); 199 rc = ddf_fun_offline(fun); 200 if (rc != EOK) { 201 ddf_msg(LVL_ERROR, "Error offlining function '%s'.", name); 202 return rc; 203 } 204 205 rc = ddf_fun_unbind(fun); 206 if (rc != EOK) { 207 ddf_msg(LVL_ERROR, "Failed offlining function '%s'.", name); 208 return rc; 209 } 210 211 ddf_fun_destroy(fun); 212 return EOK; 213 } 214 215 static int test1_dev_remove(ddf_dev_t *dev) 216 { 217 test1_t *test1 = (test1_t *)dev->driver_data; 218 int rc; 219 220 ddf_msg(LVL_DEBUG, "test1_dev_remove(%p)", dev); 221 222 if (test1->fun_a != NULL) { 223 rc = fun_remove(test1->fun_a, "a"); 224 if (rc != EOK) 225 return rc; 226 } 227 228 if (test1->clone != NULL) { 229 rc = fun_remove(test1->clone, "clone"); 230 if (rc != EOK) 231 return rc; 232 } 233 234 if (test1->child != NULL) { 235 rc = fun_remove(test1->child, "child"); 236 if (rc != EOK) 237 return rc; 238 } 239 240 return EOK; 241 } 242 243 static int test1_fun_online(ddf_fun_t *fun) 244 { 245 ddf_msg(LVL_DEBUG, "test1_fun_online()"); 246 return ddf_fun_online(fun); 247 } 248 249 static int test1_fun_offline(ddf_fun_t *fun) 250 { 251 ddf_msg(LVL_DEBUG, "test1_fun_offline()"); 252 return ddf_fun_offline(fun); 166 253 } 167 254 -
uspace/lib/c/generic/devman.c
re64df9a r1a5b252 327 327 } 328 328 329 int devman_drv_fun_online(devman_handle_t funh) 330 { 331 async_exch_t *exch = devman_exchange_begin(DEVMAN_DRIVER); 332 if (exch == NULL) 333 return ENOMEM; 334 335 sysarg_t retval = async_req_1_0(exch, DEVMAN_DRV_FUN_ONLINE, funh); 336 337 devman_exchange_end(exch); 338 return (int) retval; 339 } 340 341 int devman_drv_fun_offline(devman_handle_t funh) 342 { 343 async_exch_t *exch = devman_exchange_begin(DEVMAN_DRIVER); 344 if (exch == NULL) 345 return ENOMEM; 346 347 sysarg_t retval = async_req_1_0(exch, DEVMAN_DRV_FUN_OFFLINE, funh); 348 349 devman_exchange_end(exch); 350 return (int) retval; 351 } 352 329 353 async_sess_t *devman_parent_device_connect(exch_mgmt_t mgmt, 330 354 devman_handle_t handle, unsigned int flags) … … 430 454 } 431 455 456 int devman_fun_online(devman_handle_t funh) 457 { 458 async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT); 459 if (exch == NULL) 460 return ENOMEM; 461 462 sysarg_t retval = async_req_1_0(exch, DEVMAN_FUN_ONLINE, funh); 463 464 devman_exchange_end(exch); 465 return (int) retval; 466 } 467 468 int devman_fun_offline(devman_handle_t funh) 469 { 470 async_exch_t *exch = devman_exchange_begin(DEVMAN_CLIENT); 471 if (exch == NULL) 472 return ENOMEM; 473 474 sysarg_t retval = async_req_1_0(exch, DEVMAN_FUN_OFFLINE, funh); 475 476 devman_exchange_end(exch); 477 return (int) retval; 478 } 479 432 480 static int devman_get_handles_once(sysarg_t method, sysarg_t arg1, 433 481 devman_handle_t *handle_buf, size_t buf_size, size_t *act_size) -
uspace/lib/c/include/devman.h
re64df9a r1a5b252 50 50 devman_handle_t, devman_handle_t *); 51 51 extern int devman_remove_function(devman_handle_t); 52 extern int devman_drv_fun_online(devman_handle_t); 53 extern int devman_drv_fun_offline(devman_handle_t); 52 54 53 55 extern async_sess_t *devman_device_connect(exch_mgmt_t, devman_handle_t, … … 63 65 extern int devman_fun_get_name(devman_handle_t, char *, size_t); 64 66 extern int devman_fun_get_path(devman_handle_t, char *, size_t); 67 extern int devman_fun_online(devman_handle_t); 68 extern int devman_fun_offline(devman_handle_t); 65 69 66 70 extern int devman_add_device_to_category(devman_handle_t, const char *); -
uspace/lib/c/include/ipc/devman.h
re64df9a r1a5b252 139 139 DEVMAN_ADD_MATCH_ID, 140 140 DEVMAN_ADD_DEVICE_TO_CATEGORY, 141 DEVMAN_DRV_FUN_ONLINE, 142 DEVMAN_DRV_FUN_OFFLINE, 141 143 DEVMAN_REMOVE_FUNCTION 142 144 } driver_to_devman_t; 143 145 144 146 typedef enum { 145 DRIVER_ADD_DEVICE = IPC_FIRST_USER_METHOD 147 DRIVER_DEV_ADD = IPC_FIRST_USER_METHOD, 148 DRIVER_DEV_REMOVE, 149 DRIVER_FUN_ONLINE, 150 DRIVER_FUN_OFFLINE, 146 151 147 152 } devman_to_driver_t; … … 152 157 DEVMAN_FUN_GET_CHILD, 153 158 DEVMAN_FUN_GET_NAME, 159 DEVMAN_FUN_ONLINE, 160 DEVMAN_FUN_OFFLINE, 154 161 DEVMAN_FUN_GET_PATH, 155 162 DEVMAN_FUN_SID_TO_HANDLE -
uspace/lib/drv/generic/driver.c
re64df9a r1a5b252 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); … … 227 231 } 228 232 229 static ddf_fun_t *driver_get_function(list_t *functions, devman_handle_t handle) 233 static ddf_dev_t *driver_get_device(devman_handle_t handle) 234 { 235 ddf_dev_t *dev = NULL; 236 237 assert(fibril_mutex_is_locked(&devices_mutex)); 238 239 list_foreach(devices, link) { 240 dev = list_get_instance(link, ddf_dev_t, link); 241 if (dev->handle == handle) 242 return dev; 243 } 244 245 return NULL; 246 } 247 248 static ddf_fun_t *driver_get_function(devman_handle_t handle) 230 249 { 231 250 ddf_fun_t *fun = NULL; 232 251 233 fibril_mutex_lock(&functions_mutex);234 235 list_foreach( *functions, link) {252 assert(fibril_mutex_is_locked(&functions_mutex)); 253 254 list_foreach(functions, link) { 236 255 fun = list_get_instance(link, ddf_fun_t, link); 237 if (fun->handle == handle) { 238 fibril_mutex_unlock(&functions_mutex); 256 if (fun->handle == handle) 239 257 return fun; 240 } 241 } 242 243 fibril_mutex_unlock(&functions_mutex); 258 } 244 259 245 260 return NULL; … … 270 285 delete_device(dev); 271 286 287 fibril_mutex_lock(&devices_mutex); 288 list_append(&dev->link, &devices); 289 fibril_mutex_unlock(&devices_mutex); 290 272 291 async_answer_0(iid, res); 292 } 293 294 static void driver_dev_remove(ipc_callid_t iid, ipc_call_t *icall) 295 { 296 devman_handle_t devh; 297 ddf_dev_t *dev; 298 int rc; 299 300 printf("libdrv: driver_dev_offline()\n"); 301 devh = IPC_GET_ARG1(*icall); 302 303 fibril_mutex_lock(&devices_mutex); 304 dev = driver_get_device(devh); 305 fibril_mutex_unlock(&devices_mutex); 306 /* XXX need lock on dev */ 307 308 if (dev == NULL) { 309 async_answer_0(iid, ENOENT); 310 return; 311 } 312 313 if (driver->driver_ops->dev_remove != NULL) 314 rc = driver->driver_ops->dev_remove(dev); 315 else 316 rc = ENOTSUP; 317 318 async_answer_0(iid, (sysarg_t) rc); 319 } 320 321 static void driver_fun_online(ipc_callid_t iid, ipc_call_t *icall) 322 { 323 devman_handle_t funh; 324 ddf_fun_t *fun; 325 int rc; 326 327 funh = IPC_GET_ARG1(*icall); 328 fibril_mutex_lock(&functions_mutex); 329 fun = driver_get_function(funh); 330 fibril_mutex_unlock(&functions_mutex); 331 /* XXX Need lock on fun */ 332 333 if (fun == NULL) { 334 async_answer_0(iid, ENOENT); 335 return; 336 } 337 338 if (driver->driver_ops->fun_online != NULL) 339 rc = driver->driver_ops->fun_online(fun); 340 else 341 rc = ENOTSUP; 342 343 async_answer_0(iid, (sysarg_t) rc); 344 } 345 346 static void driver_fun_offline(ipc_callid_t iid, ipc_call_t *icall) 347 { 348 devman_handle_t funh; 349 ddf_fun_t *fun; 350 int rc; 351 352 funh = IPC_GET_ARG1(*icall); 353 fibril_mutex_lock(&functions_mutex); 354 fun = driver_get_function(funh); 355 fibril_mutex_unlock(&functions_mutex); 356 /* XXX Need lock on fun */ 357 358 if (fun == NULL) { 359 async_answer_0(iid, ENOENT); 360 return; 361 } 362 363 if (driver->driver_ops->fun_offline != NULL) 364 rc = driver->driver_ops->fun_offline(fun); 365 else 366 rc = ENOTSUP; 367 368 async_answer_0(iid, (sysarg_t) rc); 273 369 } 274 370 … … 286 382 287 383 switch (IPC_GET_IMETHOD(call)) { 288 case DRIVER_ ADD_DEVICE:384 case DRIVER_DEV_ADD: 289 385 driver_add_device(callid, &call); 290 386 break; 387 case DRIVER_DEV_REMOVE: 388 driver_dev_remove(callid, &call); 389 break; 390 case DRIVER_FUN_ONLINE: 391 driver_fun_online(callid, &call); 392 break; 393 case DRIVER_FUN_OFFLINE: 394 driver_fun_offline(callid, &call); 395 break; 291 396 default: 292 async_answer_0(callid, ENO ENT);397 async_answer_0(callid, ENOTSUP); 293 398 } 294 399 } … … 308 413 */ 309 414 devman_handle_t handle = IPC_GET_ARG2(*icall); 310 ddf_fun_t *fun = driver_get_function(&functions, handle); 415 416 fibril_mutex_lock(&functions_mutex); 417 ddf_fun_t *fun = driver_get_function(handle); 418 fibril_mutex_unlock(&functions_mutex); 419 /* XXX Need a lock on fun */ 311 420 312 421 if (fun == NULL) { … … 614 723 * the function invisible to the system. 615 724 * 616 * @param fun Function to bind725 * @param fun Function to unbind 617 726 * @return EOK on success or negative error code 618 727 */ … … 623 732 assert(fun->bound == true); 624 733 625 add_to_functions_list(fun);626 734 res = devman_remove_function(fun->handle); 627 735 if (res != EOK) … … 631 739 632 740 fun->bound = false; 741 return EOK; 742 } 743 744 /** Online function. 745 * 746 * @param fun Function to online 747 * @return EOK on success or negative error code 748 */ 749 int ddf_fun_online(ddf_fun_t *fun) 750 { 751 int res; 752 753 assert(fun->bound == true); 754 755 res = devman_drv_fun_online(fun->handle); 756 if (res != EOK) 757 return res; 758 759 return EOK; 760 } 761 762 /** Offline function. 763 * 764 * @param fun Function to offline 765 * @return EOK on success or negative error code 766 */ 767 int ddf_fun_offline(ddf_fun_t *fun) 768 { 769 int res; 770 771 assert(fun->bound == true); 772 773 res = devman_drv_fun_offline(fun->handle); 774 if (res != EOK) 775 return res; 776 633 777 return EOK; 634 778 } -
uspace/lib/drv/include/ddf/driver.h
re64df9a r1a5b252 132 132 typedef struct driver_ops { 133 133 /** Callback method for passing a new device to the device driver */ 134 int (*add_device)(ddf_dev_t *dev); 135 /* TODO: add other generic driver operations */ 134 int (*add_device)(ddf_dev_t *); 135 /** Ask driver to remove a device */ 136 int (*dev_remove)(ddf_dev_t *); 137 /** Ask driver to online a specific function */ 138 int (*fun_online)(ddf_fun_t *); 139 /** Ask driver to offline a specific function */ 140 int (*fun_offline)(ddf_fun_t *); 136 141 } driver_ops_t; 137 142 … … 150 155 extern int ddf_fun_bind(ddf_fun_t *); 151 156 extern int ddf_fun_unbind(ddf_fun_t *); 157 extern int ddf_fun_online(ddf_fun_t *); 158 extern int ddf_fun_offline(ddf_fun_t *); 152 159 extern int ddf_fun_add_match_id(ddf_fun_t *, const char *, int); 153 160 -
uspace/srv/devman/devman.c
re64df9a r1a5b252 483 483 } 484 484 485 /** Detach driver from device. 486 * 487 * @param node The device's node in the device tree. 488 * @param drv The driver. 489 */ 490 void detach_driver(dev_node_t *dev) 491 { 492 /* XXX need lock on dev */ 493 driver_t *drv = dev->drv; 494 495 assert(drv != NULL); 496 log_msg(LVL_DEBUG, "detach_driver(dev=\"%s\",drv=\"%s\")", 497 dev->pfun->pathname, drv->name); 498 499 fibril_mutex_lock(&drv->driver_mutex); 500 501 dev->drv = NULL; 502 list_remove(&dev->driver_devices); 503 504 fibril_mutex_unlock(&drv->driver_mutex); 505 } 506 485 507 /** Start a driver 486 508 * … … 726 748 727 749 ipc_call_t answer; 728 aid_t req = async_send_2(exch, DRIVER_ ADD_DEVICE, dev->handle,750 aid_t req = async_send_2(exch, DRIVER_DEV_ADD, dev->handle, 729 751 parent_handle, &answer); 730 752 … … 800 822 } 801 823 824 int driver_dev_remove(dev_node_t *dev) 825 { 826 async_exch_t *exch; 827 sysarg_t retval; 828 driver_t *drv; 829 830 assert(dev != NULL); 831 log_msg(LVL_DEBUG, "driver_dev_remove(%p)", dev); 832 drv = dev->drv; 833 834 exch = async_exchange_begin(drv->sess); 835 retval = async_req_1_0(exch, DRIVER_DEV_REMOVE, dev->handle); 836 async_exchange_end(exch); 837 838 return retval; 839 840 } 841 842 int driver_fun_online(fun_node_t *fun) 843 { 844 async_exch_t *exch; 845 sysarg_t retval; 846 driver_t *drv; 847 848 log_msg(LVL_DEBUG, "driver_fun_online(%p)", fun); 849 if (fun->dev == NULL) { 850 /* XXX root function? */ 851 return EINVAL; 852 } 853 854 drv = fun->dev->drv; 855 856 exch = async_exchange_begin(drv->sess); 857 retval = async_req_1_0(exch, DRIVER_FUN_ONLINE, fun->handle); 858 loc_exchange_end(exch); 859 860 return retval; 861 } 862 863 int driver_fun_offline(fun_node_t *fun) 864 { 865 async_exch_t *exch; 866 sysarg_t retval; 867 driver_t *drv; 868 869 log_msg(LVL_DEBUG, "driver_fun_offline(%p)", fun); 870 if (fun->dev == NULL) { 871 /* XXX root function? */ 872 return EINVAL; 873 } 874 875 drv = fun->dev->drv; 876 877 exch = async_exchange_begin(drv->sess); 878 retval = async_req_1_0(exch, DRIVER_FUN_OFFLINE, fun->handle); 879 loc_exchange_end(exch); 880 881 return retval; 882 883 } 884 802 885 /** Initialize the device tree. 803 886 * … … 1065 1148 } 1066 1149 1150 /** Remove device from device tree. 1151 * 1152 * @param tree Device tree 1153 * @param dev Device node 1154 */ 1155 void remove_dev_node(dev_tree_t *tree, dev_node_t *dev) 1156 { 1157 assert(tree != NULL); 1158 assert(dev != NULL); 1159 assert(fibril_rwlock_is_write_locked(&tree->rwlock)); 1160 1161 log_msg(LVL_DEBUG, "remove_dev_node(dev=%p)", dev); 1162 1163 /* Remove node from the handle-to-node map. */ 1164 unsigned long key = dev->handle; 1165 hash_table_remove(&tree->devman_devices, &key, 1); 1166 1167 /* Unlink from parent function. */ 1168 dev->pfun->child = NULL; 1169 dev->pfun = NULL; 1170 } 1171 1172 1067 1173 /** Insert new function into device tree. 1068 1174 * … … 1127 1233 if (fun->dev != NULL) 1128 1234 list_remove(&fun->dev_functions); 1235 1236 fun->dev = NULL; 1129 1237 } 1130 1238 -
uspace/srv/devman/devman.h
re64df9a r1a5b252 240 240 extern void add_driver(driver_list_t *, driver_t *); 241 241 extern void attach_driver(dev_node_t *, driver_t *); 242 extern void detach_driver(dev_node_t *); 242 243 extern void add_device(driver_t *, dev_node_t *, dev_tree_t *); 243 244 extern bool start_driver(driver_t *); 245 extern int driver_dev_remove(dev_node_t *); 246 extern int driver_fun_online(fun_node_t *); 247 extern int driver_fun_offline(fun_node_t *); 244 248 245 249 extern driver_t *find_driver(driver_list_t *, const char *); … … 274 278 extern bool create_root_nodes(dev_tree_t *); 275 279 extern bool insert_dev_node(dev_tree_t *, dev_node_t *, fun_node_t *); 280 extern void remove_dev_node(dev_tree_t *, dev_node_t *); 276 281 extern bool insert_fun_node(dev_tree_t *, fun_node_t *, char *, dev_node_t *); 277 282 extern void remove_fun_node(dev_tree_t *, fun_node_t *); -
uspace/srv/devman/main.c
re64df9a r1a5b252 237 237 } 238 238 239 /** Handle function registration. 240 * 241 * Child devices are registered by their parent's device driver. 242 */ 243 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call) 244 { 245 fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call); 246 devman_handle_t dev_handle = IPC_GET_ARG2(*call); 247 sysarg_t match_count = IPC_GET_ARG3(*call); 248 dev_tree_t *tree = &device_tree; 249 250 fibril_rwlock_write_lock(&tree->rwlock); 251 252 dev_node_t *dev = NULL; 253 dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle); 254 255 if (pdev == NULL) { 256 fibril_rwlock_write_unlock(&tree->rwlock); 257 async_answer_0(callid, ENOENT); 258 return; 259 } 260 261 if (ftype != fun_inner && ftype != fun_exposed) { 262 /* Unknown function type */ 263 log_msg(LVL_ERROR, 264 "Unknown function type %d provided by driver.", 265 (int) ftype); 266 267 fibril_rwlock_write_unlock(&tree->rwlock); 268 async_answer_0(callid, EINVAL); 269 return; 270 } 271 272 char *fun_name = NULL; 273 int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0); 274 if (rc != EOK) { 275 fibril_rwlock_write_unlock(&tree->rwlock); 276 async_answer_0(callid, rc); 277 return; 278 } 279 280 /* Check that function with same name is not there already. */ 281 if (find_fun_node_in_device(pdev, fun_name) != NULL) { 282 fibril_rwlock_write_unlock(&tree->rwlock); 283 async_answer_0(callid, EEXISTS); 284 printf(NAME ": Warning, driver tried to register `%s' twice.\n", 285 fun_name); 286 free(fun_name); 287 return; 288 } 289 290 fun_node_t *fun = create_fun_node(); 291 fun->ftype = ftype; 292 293 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 294 fibril_rwlock_write_unlock(&tree->rwlock); 295 delete_fun_node(fun); 296 async_answer_0(callid, ENOMEM); 297 return; 298 } 299 300 if (ftype == fun_inner) { 239 static int online_function(fun_node_t *fun) 240 { 241 dev_node_t *dev; 242 243 fibril_rwlock_write_lock(&device_tree.rwlock); 244 245 if (fun->ftype == fun_inner) { 301 246 dev = create_dev_node(); 302 247 if (dev == NULL) { 303 fibril_rwlock_write_unlock(& tree->rwlock);248 fibril_rwlock_write_unlock(&device_tree.rwlock); 304 249 delete_fun_node(fun); 305 async_answer_0(callid, ENOMEM); 306 return; 250 return ENOMEM; 307 251 } 308 252 309 insert_dev_node( tree, dev, fun);310 } 311 312 fibril_rwlock_write_unlock(& tree->rwlock);253 insert_dev_node(&device_tree, dev, fun); 254 } 255 256 fibril_rwlock_write_unlock(&device_tree.rwlock); 313 257 314 258 log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname); 315 259 316 devman_receive_match_ids(match_count, &fun->match_ids); 317 318 if (ftype == fun_inner) { 260 if (fun->ftype == fun_inner) { 261 dev = fun->child; 319 262 assert(dev != NULL); 263 320 264 /* 321 265 * Try to find a suitable driver and assign it to the device. We do … … 336 280 } 337 281 } else { 338 loc_register_tree_function(fun, tree); 282 loc_register_tree_function(fun, &device_tree); 283 } 284 285 return EOK; 286 } 287 288 static int offline_function(fun_node_t *fun) 289 { 290 int rc; 291 292 if (fun->ftype == fun_inner) { 293 printf("devman_drv_fun_offline(): %p is inner fun, removing " 294 "child dev.\n", fun); 295 if (fun->child != NULL) { 296 dev_node_t *dev = fun->child; 297 298 rc = driver_dev_remove(dev); 299 if (rc != EOK) { 300 return ENOTSUP; 301 } 302 detach_driver(dev); 303 fibril_rwlock_write_lock(&device_tree.rwlock); 304 remove_dev_node(&device_tree, dev); 305 fibril_rwlock_write_unlock(&device_tree.rwlock); 306 delete_dev_node(dev); 307 } 308 } else { 309 /* Unregister from location service */ 310 rc = loc_service_unregister(fun->service_id); 311 if (rc != EOK) { 312 log_msg(LVL_ERROR, "Failed unregistering tree service."); 313 return EIO; 314 } 315 316 fun->service_id = 0; 317 } 318 319 return EOK; 320 } 321 322 /** Handle function registration. 323 * 324 * Child devices are registered by their parent's device driver. 325 */ 326 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call) 327 { 328 fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call); 329 devman_handle_t dev_handle = IPC_GET_ARG2(*call); 330 sysarg_t match_count = IPC_GET_ARG3(*call); 331 dev_tree_t *tree = &device_tree; 332 333 fibril_rwlock_write_lock(&tree->rwlock); 334 335 dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle); 336 337 if (pdev == NULL) { 338 fibril_rwlock_write_unlock(&tree->rwlock); 339 async_answer_0(callid, ENOENT); 340 return; 341 } 342 343 if (ftype != fun_inner && ftype != fun_exposed) { 344 /* Unknown function type */ 345 log_msg(LVL_ERROR, 346 "Unknown function type %d provided by driver.", 347 (int) ftype); 348 349 fibril_rwlock_write_unlock(&tree->rwlock); 350 async_answer_0(callid, EINVAL); 351 return; 352 } 353 354 char *fun_name = NULL; 355 int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0); 356 if (rc != EOK) { 357 fibril_rwlock_write_unlock(&tree->rwlock); 358 async_answer_0(callid, rc); 359 return; 360 } 361 362 /* Check that function with same name is not there already. */ 363 if (find_fun_node_in_device(pdev, fun_name) != NULL) { 364 fibril_rwlock_write_unlock(&tree->rwlock); 365 async_answer_0(callid, EEXISTS); 366 printf(NAME ": Warning, driver tried to register `%s' twice.\n", 367 fun_name); 368 free(fun_name); 369 return; 370 } 371 372 fun_node_t *fun = create_fun_node(); 373 fun->ftype = ftype; 374 375 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 376 fibril_rwlock_write_unlock(&tree->rwlock); 377 delete_fun_node(fun); 378 async_answer_0(callid, ENOMEM); 379 return; 380 } 381 382 fibril_rwlock_write_unlock(&tree->rwlock); 383 384 devman_receive_match_ids(match_count, &fun->match_ids); 385 386 rc = online_function(fun); 387 if (rc != EOK) { 388 /* XXX clean up */ 389 async_answer_0(callid, rc); 390 return; 339 391 } 340 392 … … 378 430 } 379 431 432 /** Online function by driver request. 433 * 434 */ 435 static void devman_drv_fun_online(ipc_callid_t iid, ipc_call_t *icall, 436 driver_t *drv) 437 { 438 fun_node_t *fun; 439 int rc; 440 441 printf("devman_drv_fun_online()\n"); 442 fibril_rwlock_write_lock(&device_tree.rwlock); 443 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall)); 444 fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */ 445 446 if (fun == NULL || fun->dev == NULL || fun->dev->drv != drv) { 447 async_answer_0(iid, ENOENT); 448 return; 449 } 450 451 rc = online_function(fun); 452 if (rc != EOK) { 453 printf("devman_drv_fun_online() online_fun->ERROR\n"); 454 async_answer_0(iid, (sysarg_t) rc); 455 return; 456 } 457 printf("devman_drv_fun_online() online_fun->OK\n"); 458 459 async_answer_0(iid, (sysarg_t) EOK); 460 } 461 462 463 /** Offline function by driver request. 464 * 465 */ 466 static void devman_drv_fun_offline(ipc_callid_t iid, ipc_call_t *icall, 467 driver_t *drv) 468 { 469 fun_node_t *fun; 470 int rc; 471 472 fibril_rwlock_write_lock(&device_tree.rwlock); 473 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall)); 474 fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */ 475 476 if (fun == NULL || fun->dev == NULL || fun->dev->drv != drv) { 477 async_answer_0(iid, ENOENT); 478 return; 479 } 480 481 rc = offline_function(fun); 482 if (rc != EOK) { 483 async_answer_0(iid, (sysarg_t) rc); 484 return; 485 } 486 487 async_answer_0(iid, (sysarg_t) EOK); 488 } 489 380 490 /** Remove function. */ 381 491 static void devman_remove_function(ipc_callid_t callid, ipc_call_t *call) … … 399 509 /* Handle possible descendants */ 400 510 /* TODO */ 401 log_msg(LVL_WARN, "devman_remove_function(): not handling " 402 "descendants\n"); 511 if (fun->child != NULL) { 512 log_msg(LVL_WARN, "devman_remove_function(): not handling " 513 "descendants\n"); 514 } 403 515 } else { 404 /* Unregister from location service */ 405 rc = loc_service_unregister(fun->service_id); 406 if (rc != EOK) { 407 log_msg(LVL_ERROR, "Failed unregistering tree service."); 408 fibril_rwlock_write_unlock(&tree->rwlock); 409 async_answer_0(callid, EIO); 410 return; 516 if (fun->service_id != 0) { 517 /* Unregister from location service */ 518 rc = loc_service_unregister(fun->service_id); 519 if (rc != EOK) { 520 log_msg(LVL_ERROR, "Failed unregistering tree " 521 "service."); 522 fibril_rwlock_write_unlock(&tree->rwlock); 523 async_answer_0(callid, EIO); 524 return; 525 } 411 526 } 412 527 } … … 485 600 devman_add_function_to_cat(callid, &call); 486 601 break; 602 case DEVMAN_DRV_FUN_ONLINE: 603 devman_drv_fun_online(callid, &call, driver); 604 break; 605 case DEVMAN_DRV_FUN_OFFLINE: 606 devman_drv_fun_offline(callid, &call, driver); 607 break; 487 608 case DEVMAN_REMOVE_FUNCTION: 488 609 devman_remove_function(callid, &call); 489 610 break; 490 611 default: 491 async_answer_0(callid, EINVAL); 612 async_answer_0(callid, EINVAL); 492 613 break; 493 614 } … … 666 787 } 667 788 789 /** Online function. 790 * 791 * Send a request to online a function to the responsible driver. 792 * The driver may offline other functions if necessary (i.e. if the state 793 * of this function is linked to state of another function somehow). 794 */ 795 static void devman_fun_online(ipc_callid_t iid, ipc_call_t *icall) 796 { 797 fun_node_t *fun; 798 int rc; 799 800 fibril_rwlock_write_lock(&device_tree.rwlock); 801 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall)); 802 fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */ 803 804 if (fun == NULL) { 805 async_answer_0(iid, ENOENT); 806 return; 807 } 808 809 rc = driver_fun_online(fun); 810 811 async_answer_0(iid, (sysarg_t) rc); 812 } 813 814 /** Offline function. 815 * 816 * Send a request to offline a function to the responsible driver. As 817 * a result the subtree rooted at that function should be cleanly 818 * detatched. The driver may offline other functions if necessary 819 * (i.e. if the state of this function is linked to state of another 820 * function somehow). 821 */ 822 static void devman_fun_offline(ipc_callid_t iid, ipc_call_t *icall) 823 { 824 fun_node_t *fun; 825 int rc; 826 827 fibril_rwlock_write_lock(&device_tree.rwlock); 828 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall)); 829 fibril_rwlock_write_unlock(&device_tree.rwlock); /* XXX FIXME */ 830 831 if (fun == NULL) { 832 async_answer_0(iid, ENOENT); 833 return; 834 } 835 836 rc = driver_fun_offline(fun); 837 838 async_answer_0(iid, (sysarg_t) rc); 839 } 840 668 841 /** Find handle for the function instance identified by its service ID. */ 669 842 static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall) … … 709 882 case DEVMAN_FUN_GET_PATH: 710 883 devman_fun_get_path(callid, &call); 884 break; 885 case DEVMAN_FUN_ONLINE: 886 devman_fun_online(callid, &call); 887 break; 888 case DEVMAN_FUN_OFFLINE: 889 devman_fun_offline(callid, &call); 711 890 break; 712 891 case DEVMAN_FUN_SID_TO_HANDLE:
Note:
See TracChangeset
for help on using the changeset viewer.