Changes in uspace/srv/devman/main.c [655cc56:3ad7b1c] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/main.c
r655cc56 r3ad7b1c 39 39 #include <assert.h> 40 40 #include <ipc/services.h> 41 #include < ns.h>41 #include <ipc/ns.h> 42 42 #include <async.h> 43 43 #include <stdio.h> … … 56 56 #include <ipc/driver.h> 57 57 #include <thread.h> 58 #include < loc.h>58 #include <devmap.h> 59 59 60 60 #include "devman.h" … … 64 64 static driver_list_t drivers_list; 65 65 static dev_tree_t device_tree; 66 67 static int init_running_drv(void *drv); 66 static class_list_t class_list; 68 67 69 68 /** Register running driver. */ 70 static driver_t *devman_driver_register(ipc_callid_t callid, ipc_call_t *call) 71 { 69 static driver_t *devman_driver_register(void) 70 { 71 ipc_call_t icall; 72 ipc_callid_t iid; 72 73 driver_t *driver = NULL; 74 75 log_msg(LVL_DEBUG, "devman_driver_register"); 76 77 iid = async_get_call(&icall); 78 if (IPC_GET_IMETHOD(icall) != DEVMAN_DRIVER_REGISTER) { 79 async_answer_0(iid, EREFUSED); 80 return NULL; 81 } 82 73 83 char *drv_name = NULL; 74 75 log_msg(LVL_DEBUG, "devman_driver_register");76 84 77 85 /* Get driver name. */ 78 86 int rc = async_data_write_accept((void **) &drv_name, true, 0, 0, 0, 0); 79 87 if (rc != EOK) { 80 async_answer_0( callid, rc);88 async_answer_0(iid, rc); 81 89 return NULL; 82 90 } … … 91 99 free(drv_name); 92 100 drv_name = NULL; 93 async_answer_0( callid, ENOENT);101 async_answer_0(iid, ENOENT); 94 102 return NULL; 95 103 } … … 100 108 fibril_mutex_lock(&driver->driver_mutex); 101 109 102 if (driver-> sess) {110 if (driver->phone >= 0) { 103 111 /* We already have a connection to the driver. */ 104 112 log_msg(LVL_ERROR, "Driver '%s' already started.\n", 105 113 driver->name); 106 114 fibril_mutex_unlock(&driver->driver_mutex); 107 async_answer_0( callid, EEXISTS);115 async_answer_0(iid, EEXISTS); 108 116 return NULL; 109 117 } … … 120 128 break; 121 129 case DRIVER_RUNNING: 122 /* Should not happen since we do not have a connected session*/130 /* Should not happen since we do not have a connected phone */ 123 131 assert(false); 124 132 } … … 127 135 log_msg(LVL_DEBUG, "Creating connection to the `%s' driver.", 128 136 driver->name); 129 driver->sess = async_callback_receive(EXCHANGE_PARALLEL); 130 if (!driver->sess) { 137 ipc_call_t call; 138 ipc_callid_t callid = async_get_call(&call); 139 if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) { 131 140 fibril_mutex_unlock(&driver->driver_mutex); 132 141 async_answer_0(callid, ENOTSUP); 142 async_answer_0(iid, ENOTSUP); 133 143 return NULL; 134 144 } 135 /* FIXME: Work around problem with callback sessions */ 136 async_sess_args_set(driver->sess, DRIVER_DEVMAN, 0, 0); 137 138 log_msg(LVL_NOTE, 145 146 /* Remember driver's phone. */ 147 driver->phone = IPC_GET_ARG5(call); 148 149 fibril_mutex_unlock(&driver->driver_mutex); 150 151 log_msg(LVL_NOTE, 139 152 "The `%s' driver was successfully registered as running.", 140 153 driver->name); 154 155 async_answer_0(callid, EOK); 156 async_answer_0(iid, EOK); 157 158 return driver; 159 } 160 161 /** Receive device match ID from the device's parent driver and add it to the 162 * list of devices match ids. 163 * 164 * @param match_ids The list of the device's match ids. 165 * @return Zero on success, negative error code otherwise. 166 */ 167 static int devman_receive_match_id(match_id_list_t *match_ids) 168 { 169 match_id_t *match_id = create_match_id(); 170 ipc_callid_t callid; 171 ipc_call_t call; 172 int rc = 0; 173 174 callid = async_get_call(&call); 175 if (DEVMAN_ADD_MATCH_ID != IPC_GET_IMETHOD(call)) { 176 log_msg(LVL_ERROR, 177 "Invalid protocol when trying to receive match id."); 178 async_answer_0(callid, EINVAL); 179 delete_match_id(match_id); 180 return EINVAL; 181 } 182 183 if (match_id == NULL) { 184 log_msg(LVL_ERROR, "Failed to allocate match id."); 185 async_answer_0(callid, ENOMEM); 186 return ENOMEM; 187 } 188 189 async_answer_0(callid, EOK); 190 191 match_id->score = IPC_GET_ARG1(call); 192 193 char *match_id_str; 194 rc = async_data_write_accept((void **) &match_id_str, true, 0, 0, 0, 0); 195 match_id->id = match_id_str; 196 if (rc != EOK) { 197 delete_match_id(match_id); 198 log_msg(LVL_ERROR, "Failed to receive match id string: %s.", 199 str_error(rc)); 200 return rc; 201 } 202 203 list_append(&match_id->link, &match_ids->ids); 204 205 log_msg(LVL_DEBUG, "Received match id `%s', score %d.", 206 match_id->id, match_id->score); 207 return rc; 208 } 209 210 /** Receive device match IDs from the device's parent driver and add them to the 211 * list of devices match ids. 212 * 213 * @param match_count The number of device's match ids to be received. 214 * @param match_ids The list of the device's match ids. 215 * @return Zero on success, negative error code otherwise. 216 */ 217 static int devman_receive_match_ids(sysarg_t match_count, 218 match_id_list_t *match_ids) 219 { 220 int ret = EOK; 221 size_t i; 222 223 for (i = 0; i < match_count; i++) { 224 if (EOK != (ret = devman_receive_match_id(match_ids))) 225 return ret; 226 } 227 return ret; 228 } 229 230 static int assign_driver_fibril(void *arg) 231 { 232 dev_node_t *dev_node = (dev_node_t *) arg; 233 assign_driver(dev_node, &drivers_list, &device_tree); 234 return EOK; 235 } 236 237 /** Handle function registration. 238 * 239 * Child devices are registered by their parent's device driver. 240 */ 241 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call) 242 { 243 fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call); 244 devman_handle_t dev_handle = IPC_GET_ARG2(*call); 245 sysarg_t match_count = IPC_GET_ARG3(*call); 246 dev_tree_t *tree = &device_tree; 247 248 fibril_rwlock_write_lock(&tree->rwlock); 249 250 dev_node_t *dev = NULL; 251 dev_node_t *pdev = find_dev_node_no_lock(&device_tree, dev_handle); 252 253 if (pdev == NULL) { 254 fibril_rwlock_write_unlock(&tree->rwlock); 255 async_answer_0(callid, ENOENT); 256 return; 257 } 258 259 if (ftype != fun_inner && ftype != fun_exposed) { 260 /* Unknown function type */ 261 log_msg(LVL_ERROR, 262 "Unknown function type %d provided by driver.", 263 (int) ftype); 264 265 fibril_rwlock_write_unlock(&tree->rwlock); 266 async_answer_0(callid, EINVAL); 267 return; 268 } 269 270 char *fun_name = NULL; 271 int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0); 272 if (rc != EOK) { 273 fibril_rwlock_write_unlock(&tree->rwlock); 274 async_answer_0(callid, rc); 275 return; 276 } 277 278 /* Check that function with same name is not there already. */ 279 if (find_fun_node_in_device(pdev, fun_name) != NULL) { 280 fibril_rwlock_write_unlock(&tree->rwlock); 281 async_answer_0(callid, EEXISTS); 282 printf(NAME ": Warning, driver tried to register `%s' twice.\n", 283 fun_name); 284 free(fun_name); 285 return; 286 } 287 288 fun_node_t *fun = create_fun_node(); 289 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 290 fibril_rwlock_write_unlock(&tree->rwlock); 291 delete_fun_node(fun); 292 async_answer_0(callid, ENOMEM); 293 return; 294 } 295 296 if (ftype == fun_inner) { 297 dev = create_dev_node(); 298 if (dev == NULL) { 299 fibril_rwlock_write_unlock(&tree->rwlock); 300 delete_fun_node(fun); 301 async_answer_0(callid, ENOMEM); 302 return; 303 } 304 305 insert_dev_node(tree, dev, fun); 306 } 307 308 fibril_rwlock_write_unlock(&tree->rwlock); 309 310 log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname); 311 312 devman_receive_match_ids(match_count, &fun->match_ids); 313 314 if (ftype == fun_inner) { 315 assert(dev != NULL); 316 /* 317 * Try to find a suitable driver and assign it to the device. We do 318 * not want to block the current fibril that is used for processing 319 * incoming calls: we will launch a separate fibril to handle the 320 * driver assigning. That is because assign_driver can actually include 321 * task spawning which could take some time. 322 */ 323 fid_t assign_fibril = fibril_create(assign_driver_fibril, dev); 324 if (assign_fibril == 0) { 325 /* 326 * Fallback in case we are out of memory. 327 * Probably not needed as we will die soon anyway ;-). 328 */ 329 (void) assign_driver_fibril(fun); 330 } else { 331 fibril_add_ready(assign_fibril); 332 } 333 } else { 334 devmap_register_tree_function(fun, tree); 335 } 336 337 /* Return device handle to parent's driver. */ 338 async_answer_1(callid, EOK, fun->handle); 339 } 340 341 static void devmap_register_class_dev(dev_class_info_t *cli) 342 { 343 /* Create devmap path and name for the device. */ 344 char *devmap_pathname = NULL; 345 346 asprintf(&devmap_pathname, "%s/%s%c%s", DEVMAP_CLASS_NAMESPACE, 347 cli->dev_class->name, DEVMAP_SEPARATOR, cli->dev_name); 348 if (devmap_pathname == NULL) 349 return; 350 351 /* 352 * Register the device by the device mapper and remember its devmap 353 * handle. 354 */ 355 devmap_device_register_with_iface(devmap_pathname, 356 &cli->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP); 357 358 /* 359 * Add device to the hash map of class devices registered by device 360 * mapper. 361 */ 362 class_add_devmap_function(&class_list, cli); 363 364 free(devmap_pathname); 365 } 366 367 static void devman_add_function_to_class(ipc_callid_t callid, ipc_call_t *call) 368 { 369 devman_handle_t handle = IPC_GET_ARG1(*call); 370 371 /* Get class name. */ 372 char *class_name; 373 int rc = async_data_write_accept((void **) &class_name, true, 374 0, 0, 0, 0); 375 if (rc != EOK) { 376 async_answer_0(callid, rc); 377 return; 378 } 379 380 fun_node_t *fun = find_fun_node(&device_tree, handle); 381 if (fun == NULL) { 382 async_answer_0(callid, ENOENT); 383 return; 384 } 385 386 dev_class_t *cl = get_dev_class(&class_list, class_name); 387 dev_class_info_t *class_info = add_function_to_class(fun, cl, NULL); 388 389 /* Register the device's class alias by devmapper. */ 390 devmap_register_class_dev(class_info); 391 392 log_msg(LVL_NOTE, "Function `%s' added to class `%s' as `%s'.", 393 fun->pathname, class_name, class_info->dev_name); 394 395 async_answer_0(callid, EOK); 396 } 397 398 /** Initialize driver which has registered itself as running and ready. 399 * 400 * The initialization is done in a separate fibril to avoid deadlocks (if the 401 * driver needed to be served by devman during the driver's initialization). 402 */ 403 static int init_running_drv(void *drv) 404 { 405 driver_t *driver = (driver_t *) drv; 406 407 initialize_running_driver(driver, &device_tree); 408 log_msg(LVL_DEBUG, "The `%s` driver was successfully initialized.", 409 driver->name); 410 return 0; 411 } 412 413 /** Function for handling connections from a driver to the device manager. */ 414 static void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall) 415 { 416 /* Accept the connection. */ 417 async_answer_0(iid, EOK); 418 419 driver_t *driver = devman_driver_register(); 420 if (driver == NULL) 421 return; 141 422 142 423 /* … … 149 430 log_msg(LVL_ERROR, "Failed to create initialization fibril " \ 150 431 "for driver `%s'.", driver->name); 151 fibril_mutex_unlock(&driver->driver_mutex); 152 async_answer_0(callid, ENOMEM); 153 return NULL; 154 } 155 432 return; 433 } 156 434 fibril_add_ready(fid); 157 fibril_mutex_unlock(&driver->driver_mutex); 158 159 async_answer_0(callid, EOK); 160 return driver; 161 } 162 163 /** Receive device match ID from the device's parent driver and add it to the 164 * list of devices match ids. 165 * 166 * @param match_ids The list of the device's match ids. 167 * @return Zero on success, negative error code otherwise. 168 */ 169 static int devman_receive_match_id(match_id_list_t *match_ids) 170 { 171 match_id_t *match_id = create_match_id(); 435 172 436 ipc_callid_t callid; 173 437 ipc_call_t call; 174 int rc = 0; 175 176 callid = async_get_call(&call); 177 if (DEVMAN_ADD_MATCH_ID != IPC_GET_IMETHOD(call)) { 178 log_msg(LVL_ERROR, 179 "Invalid protocol when trying to receive match id."); 180 async_answer_0(callid, EINVAL); 181 delete_match_id(match_id); 182 return EINVAL; 183 } 184 185 if (match_id == NULL) { 186 log_msg(LVL_ERROR, "Failed to allocate match id."); 187 async_answer_0(callid, ENOMEM); 188 return ENOMEM; 189 } 190 191 async_answer_0(callid, EOK); 192 193 match_id->score = IPC_GET_ARG1(call); 194 195 char *match_id_str; 196 rc = async_data_write_accept((void **) &match_id_str, true, 0, 0, 0, 0); 197 match_id->id = match_id_str; 438 bool cont = true; 439 while (cont) { 440 callid = async_get_call(&call); 441 442 switch (IPC_GET_IMETHOD(call)) { 443 case IPC_M_PHONE_HUNGUP: 444 cont = false; 445 continue; 446 case DEVMAN_ADD_FUNCTION: 447 devman_add_function(callid, &call); 448 break; 449 case DEVMAN_ADD_DEVICE_TO_CLASS: 450 devman_add_function_to_class(callid, &call); 451 break; 452 default: 453 async_answer_0(callid, EINVAL); 454 break; 455 } 456 } 457 } 458 459 /** Find handle for the device instance identified by the device's path in the 460 * device tree. */ 461 static void devman_function_get_handle(ipc_callid_t iid, ipc_call_t *icall) 462 { 463 char *pathname; 464 465 int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0); 198 466 if (rc != EOK) { 199 delete_match_id(match_id); 200 log_msg(LVL_ERROR, "Failed to receive match id string: %s.", 201 str_error(rc)); 202 return rc; 203 } 204 205 list_append(&match_id->link, &match_ids->ids); 206 207 log_msg(LVL_DEBUG, "Received match id `%s', score %d.", 208 match_id->id, match_id->score); 209 return rc; 210 } 211 212 /** Receive device match IDs from the device's parent driver and add them to the 213 * list of devices match ids. 214 * 215 * @param match_count The number of device's match ids to be received. 216 * @param match_ids The list of the device's match ids. 217 * @return Zero on success, negative error code otherwise. 218 */ 219 static int devman_receive_match_ids(sysarg_t match_count, 220 match_id_list_t *match_ids) 221 { 222 int ret = EOK; 223 size_t i; 224 225 for (i = 0; i < match_count; i++) { 226 if (EOK != (ret = devman_receive_match_id(match_ids))) 227 return ret; 228 } 229 return ret; 230 } 231 232 static int assign_driver_fibril(void *arg) 233 { 234 dev_node_t *dev_node = (dev_node_t *) arg; 235 assign_driver(dev_node, &drivers_list, &device_tree); 236 237 /* Delete one reference we got from the caller. */ 238 dev_del_ref(dev_node); 239 return EOK; 240 } 241 242 static int online_function(fun_node_t *fun) 243 { 244 dev_node_t *dev; 245 246 fibril_rwlock_write_lock(&device_tree.rwlock); 247 248 if (fun->state == FUN_ON_LINE) { 249 fibril_rwlock_write_unlock(&device_tree.rwlock); 250 log_msg(LVL_WARN, "Function %s is already on line.", 251 fun->pathname); 252 return EOK; 253 } 254 255 if (fun->ftype == fun_inner) { 256 dev = create_dev_node(); 257 if (dev == NULL) { 258 fibril_rwlock_write_unlock(&device_tree.rwlock); 259 return ENOMEM; 260 } 261 262 insert_dev_node(&device_tree, dev, fun); 263 dev_add_ref(dev); 264 } 265 266 log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname); 267 268 if (fun->ftype == fun_inner) { 269 dev = fun->child; 270 assert(dev != NULL); 271 272 /* Give one reference over to assign_driver_fibril(). */ 273 dev_add_ref(dev); 274 /* 275 * Try to find a suitable driver and assign it to the device. We do 276 * not want to block the current fibril that is used for processing 277 * incoming calls: we will launch a separate fibril to handle the 278 * driver assigning. That is because assign_driver can actually include 279 * task spawning which could take some time. 280 */ 281 fid_t assign_fibril = fibril_create(assign_driver_fibril, dev); 282 if (assign_fibril == 0) { 283 log_msg(LVL_ERROR, "Failed to create fibril for " 284 "assigning driver."); 285 /* XXX Cleanup */ 286 fibril_rwlock_write_unlock(&device_tree.rwlock); 287 return ENOMEM; 288 } 289 fibril_add_ready(assign_fibril); 290 } else { 291 loc_register_tree_function(fun, &device_tree); 292 } 293 294 fibril_rwlock_write_unlock(&device_tree.rwlock); 295 296 return EOK; 297 } 298 299 static int offline_function(fun_node_t *fun) 300 { 301 int rc; 302 303 fibril_rwlock_write_lock(&device_tree.rwlock); 304 305 if (fun->state == FUN_OFF_LINE) { 306 fibril_rwlock_write_unlock(&device_tree.rwlock); 307 log_msg(LVL_WARN, "Function %s is already off line.", 308 fun->pathname); 309 return EOK; 310 } 311 312 if (fun->ftype == fun_inner) { 313 log_msg(LVL_DEBUG, "Offlining inner function %s.", 314 fun->pathname); 315 316 if (fun->child != NULL) { 317 dev_node_t *dev = fun->child; 318 device_state_t dev_state; 319 320 dev_add_ref(dev); 321 dev_state = dev->state; 322 323 fibril_rwlock_write_unlock(&device_tree.rwlock); 324 325 /* If device is owned by driver, ask driver to give it up. */ 326 if (dev_state == DEVICE_USABLE) { 327 rc = driver_dev_remove(&device_tree, dev); 328 if (rc != EOK) { 329 dev_del_ref(dev); 330 return ENOTSUP; 331 } 332 } 333 334 /* Verify that driver removed all functions */ 335 fibril_rwlock_read_lock(&device_tree.rwlock); 336 if (!list_empty(&dev->functions)) { 337 fibril_rwlock_read_unlock(&device_tree.rwlock); 338 dev_del_ref(dev); 339 return EIO; 340 } 341 342 driver_t *driver = dev->drv; 343 fibril_rwlock_read_unlock(&device_tree.rwlock); 344 345 if (driver) 346 detach_driver(&device_tree, dev); 347 348 fibril_rwlock_write_lock(&device_tree.rwlock); 349 remove_dev_node(&device_tree, dev); 350 351 /* Delete ref created when node was inserted */ 352 dev_del_ref(dev); 353 /* Delete ref created by dev_add_ref(dev) above */ 354 dev_del_ref(dev); 355 } 356 } else { 357 /* Unregister from location service */ 358 rc = loc_service_unregister(fun->service_id); 359 if (rc != EOK) { 360 fibril_rwlock_write_unlock(&device_tree.rwlock); 361 log_msg(LVL_ERROR, "Failed unregistering tree service."); 362 return EIO; 363 } 364 365 fun->service_id = 0; 366 } 367 368 fun->state = FUN_OFF_LINE; 369 fibril_rwlock_write_unlock(&device_tree.rwlock); 370 371 return EOK; 372 } 373 374 /** Handle function registration. 375 * 376 * Child devices are registered by their parent's device driver. 377 */ 378 static void devman_add_function(ipc_callid_t callid, ipc_call_t *call) 379 { 380 fun_type_t ftype = (fun_type_t) IPC_GET_ARG1(*call); 381 devman_handle_t dev_handle = IPC_GET_ARG2(*call); 382 sysarg_t match_count = IPC_GET_ARG3(*call); 383 dev_tree_t *tree = &device_tree; 384 385 dev_node_t *pdev = find_dev_node(&device_tree, dev_handle); 386 if (pdev == NULL) { 387 async_answer_0(callid, ENOENT); 388 return; 389 } 390 391 if (ftype != fun_inner && ftype != fun_exposed) { 392 /* Unknown function type */ 393 log_msg(LVL_ERROR, 394 "Unknown function type %d provided by driver.", 395 (int) ftype); 396 397 dev_del_ref(pdev); 398 async_answer_0(callid, EINVAL); 399 return; 400 } 401 402 char *fun_name = NULL; 403 int rc = async_data_write_accept((void **)&fun_name, true, 0, 0, 0, 0); 404 if (rc != EOK) { 405 dev_del_ref(pdev); 406 async_answer_0(callid, rc); 407 return; 408 } 409 410 fibril_rwlock_write_lock(&tree->rwlock); 411 412 /* Check device state */ 413 if (pdev->state == DEVICE_REMOVED) { 414 fibril_rwlock_write_unlock(&tree->rwlock); 415 dev_del_ref(pdev); 416 async_answer_0(callid, ENOENT); 417 return; 418 } 419 420 /* Check that function with same name is not there already. */ 421 if (find_fun_node_in_device(tree, pdev, fun_name) != NULL) { 422 fibril_rwlock_write_unlock(&tree->rwlock); 423 dev_del_ref(pdev); 424 async_answer_0(callid, EEXISTS); 425 printf(NAME ": Warning, driver tried to register `%s' twice.\n", 426 fun_name); 427 free(fun_name); 428 return; 429 } 430 431 fun_node_t *fun = create_fun_node(); 432 fun_add_ref(fun); 433 fun->ftype = ftype; 434 435 if (!insert_fun_node(&device_tree, fun, fun_name, pdev)) { 436 fibril_rwlock_write_unlock(&tree->rwlock); 437 dev_del_ref(pdev); 438 delete_fun_node(fun); 439 async_answer_0(callid, ENOMEM); 440 return; 441 } 442 443 fibril_rwlock_write_unlock(&tree->rwlock); 444 dev_del_ref(pdev); 445 446 devman_receive_match_ids(match_count, &fun->match_ids); 447 448 rc = online_function(fun); 449 if (rc != EOK) { 450 /* XXX clean up */ 451 async_answer_0(callid, rc); 452 return; 453 } 454 455 /* Return device handle to parent's driver. */ 456 async_answer_1(callid, EOK, fun->handle); 457 } 458 459 static void devman_add_function_to_cat(ipc_callid_t callid, ipc_call_t *call) 460 { 461 devman_handle_t handle = IPC_GET_ARG1(*call); 462 category_id_t cat_id; 463 int rc; 464 465 /* Get category name. */ 466 char *cat_name; 467 rc = async_data_write_accept((void **) &cat_name, true, 468 0, 0, 0, 0); 469 if (rc != EOK) { 470 async_answer_0(callid, rc); 471 return; 472 } 473 474 fun_node_t *fun = find_fun_node(&device_tree, handle); 475 if (fun == NULL) { 476 async_answer_0(callid, ENOENT); 477 return; 478 } 479 480 fibril_rwlock_read_lock(&device_tree.rwlock); 481 482 /* Check function state */ 483 if (fun->state == FUN_REMOVED) { 484 fibril_rwlock_read_unlock(&device_tree.rwlock); 485 async_answer_0(callid, ENOENT); 486 return; 487 } 488 489 rc = loc_category_get_id(cat_name, &cat_id, IPC_FLAG_BLOCKING); 490 if (rc == EOK) { 491 loc_service_add_to_cat(fun->service_id, cat_id); 492 log_msg(LVL_NOTE, "Function `%s' added to category `%s'.", 493 fun->pathname, cat_name); 494 } else { 495 log_msg(LVL_ERROR, "Failed adding function `%s' to category " 496 "`%s'.", fun->pathname, cat_name); 497 } 498 499 fibril_rwlock_read_unlock(&device_tree.rwlock); 500 fun_del_ref(fun); 501 502 async_answer_0(callid, rc); 503 } 504 505 /** Online function by driver request. 506 * 507 */ 508 static void devman_drv_fun_online(ipc_callid_t iid, ipc_call_t *icall, 509 driver_t *drv) 510 { 511 fun_node_t *fun; 512 int rc; 513 514 log_msg(LVL_DEBUG, "devman_drv_fun_online()"); 515 516 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 467 async_answer_0(iid, rc); 468 return; 469 } 470 471 fun_node_t *fun = find_fun_node_by_path(&device_tree, pathname); 472 473 free(pathname); 474 517 475 if (fun == NULL) { 518 476 async_answer_0(iid, ENOENT); 519 477 return; 520 478 } 521 522 fibril_rwlock_read_lock(&device_tree.rwlock); 523 if (fun->dev == NULL || fun->dev->drv != drv) { 524 fibril_rwlock_read_unlock(&device_tree.rwlock); 525 fun_del_ref(fun); 526 async_answer_0(iid, ENOENT); 527 return; 528 } 529 fibril_rwlock_read_unlock(&device_tree.rwlock); 530 531 rc = online_function(fun); 479 480 async_answer_1(iid, EOK, fun->handle); 481 } 482 483 /** Find handle for the device instance identified by device class name. */ 484 static void devman_function_get_handle_by_class(ipc_callid_t iid, 485 ipc_call_t *icall) 486 { 487 char *classname; 488 char *devname; 489 490 int rc = async_data_write_accept((void **) &classname, true, 0, 0, 0, 0); 532 491 if (rc != EOK) { 533 fun_del_ref(fun); 534 async_answer_0(iid, (sysarg_t) rc); 535 return; 536 } 537 538 fun_del_ref(fun); 539 540 async_answer_0(iid, (sysarg_t) EOK); 541 } 542 543 544 /** Offline function by driver request. 545 * 546 */ 547 static void devman_drv_fun_offline(ipc_callid_t iid, ipc_call_t *icall, 548 driver_t *drv) 549 { 550 fun_node_t *fun; 551 int rc; 552 553 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 492 async_answer_0(iid, rc); 493 return; 494 } 495 rc = async_data_write_accept((void **) &devname, true, 0, 0, 0, 0); 496 if (rc != EOK) { 497 free(classname); 498 async_answer_0(iid, rc); 499 return; 500 } 501 502 503 fun_node_t *fun = find_fun_node_by_class(&class_list, 504 classname, devname); 505 506 free(classname); 507 free(devname); 508 554 509 if (fun == NULL) { 555 510 async_answer_0(iid, ENOENT); 556 511 return; 557 512 } 558 559 fibril_rwlock_write_lock(&device_tree.rwlock); 560 if (fun->dev == NULL || fun->dev->drv != drv) { 561 fun_del_ref(fun); 562 async_answer_0(iid, ENOENT); 563 return; 564 } 565 fibril_rwlock_write_unlock(&device_tree.rwlock); 566 567 rc = offline_function(fun); 568 if (rc != EOK) { 569 fun_del_ref(fun); 570 async_answer_0(iid, (sysarg_t) rc); 571 return; 572 } 573 574 fun_del_ref(fun); 575 async_answer_0(iid, (sysarg_t) EOK); 576 } 577 578 /** Remove function. */ 579 static void devman_remove_function(ipc_callid_t callid, ipc_call_t *call) 580 { 581 devman_handle_t fun_handle = IPC_GET_ARG1(*call); 582 dev_tree_t *tree = &device_tree; 583 int rc; 584 585 fun_node_t *fun = find_fun_node(&device_tree, fun_handle); 586 if (fun == NULL) { 587 async_answer_0(callid, ENOENT); 588 return; 589 } 590 591 fibril_rwlock_write_lock(&tree->rwlock); 592 593 log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname); 594 595 /* Check function state */ 596 if (fun->state == FUN_REMOVED) { 597 fibril_rwlock_write_unlock(&tree->rwlock); 598 async_answer_0(callid, ENOENT); 599 return; 600 } 601 602 if (fun->ftype == fun_inner) { 603 /* This is a surprise removal. Handle possible descendants */ 604 if (fun->child != NULL) { 605 dev_node_t *dev = fun->child; 606 device_state_t dev_state; 607 int gone_rc; 608 609 dev_add_ref(dev); 610 dev_state = dev->state; 611 612 fibril_rwlock_write_unlock(&device_tree.rwlock); 613 614 /* If device is owned by driver, inform driver it is gone. */ 615 if (dev_state == DEVICE_USABLE) 616 gone_rc = driver_dev_gone(&device_tree, dev); 617 else 618 gone_rc = EOK; 619 620 fibril_rwlock_read_lock(&device_tree.rwlock); 621 622 /* Verify that driver succeeded and removed all functions */ 623 if (gone_rc != EOK || !list_empty(&dev->functions)) { 624 log_msg(LVL_ERROR, "Driver did not remove " 625 "functions for device that is gone. " 626 "Device node is now defunct."); 627 628 /* 629 * Not much we can do but mark the device 630 * node as having invalid state. This 631 * is a driver bug. 632 */ 633 dev->state = DEVICE_INVALID; 634 fibril_rwlock_read_unlock(&device_tree.rwlock); 635 dev_del_ref(dev); 636 if (gone_rc == EOK) 637 gone_rc = ENOTSUP; 638 async_answer_0(callid, gone_rc); 639 return; 640 } 641 642 driver_t *driver = dev->drv; 643 fibril_rwlock_read_unlock(&device_tree.rwlock); 644 645 if (driver) 646 detach_driver(&device_tree, dev); 647 648 fibril_rwlock_write_lock(&device_tree.rwlock); 649 remove_dev_node(&device_tree, dev); 650 651 /* Delete ref created when node was inserted */ 652 dev_del_ref(dev); 653 /* Delete ref created by dev_add_ref(dev) above */ 654 dev_del_ref(dev); 655 } 656 } else { 657 if (fun->service_id != 0) { 658 /* Unregister from location service */ 659 rc = loc_service_unregister(fun->service_id); 660 if (rc != EOK) { 661 log_msg(LVL_ERROR, "Failed unregistering tree " 662 "service."); 663 fibril_rwlock_write_unlock(&tree->rwlock); 664 fun_del_ref(fun); 665 async_answer_0(callid, EIO); 666 return; 667 } 668 } 669 } 670 671 remove_fun_node(&device_tree, fun); 672 fibril_rwlock_write_unlock(&tree->rwlock); 673 674 /* Delete ref added when inserting function into tree */ 675 fun_del_ref(fun); 676 /* Delete ref added above when looking up function */ 677 fun_del_ref(fun); 678 679 log_msg(LVL_DEBUG, "devman_remove_function() succeeded."); 680 async_answer_0(callid, EOK); 681 } 682 683 /** Initialize driver which has registered itself as running and ready. 684 * 685 * The initialization is done in a separate fibril to avoid deadlocks (if the 686 * driver needed to be served by devman during the driver's initialization). 687 */ 688 static int init_running_drv(void *drv) 689 { 690 driver_t *driver = (driver_t *) drv; 691 692 initialize_running_driver(driver, &device_tree); 693 log_msg(LVL_DEBUG, "The `%s` driver was successfully initialized.", 694 driver->name); 695 return 0; 696 } 697 698 /** Function for handling connections from a driver to the device manager. */ 699 static void devman_connection_driver(ipc_callid_t iid, ipc_call_t *icall) 700 { 701 client_t *client; 702 driver_t *driver; 703 704 /* Accept the connection. */ 513 514 async_answer_1(iid, EOK, fun->handle); 515 } 516 517 518 /** Function for handling connections from a client to the device manager. */ 519 static void devman_connection_client(ipc_callid_t iid, ipc_call_t *icall) 520 { 521 /* Accept connection. */ 705 522 async_answer_0(iid, EOK); 706 523 707 client = async_get_client_data(); 708 if (client == NULL) { 709 log_msg(LVL_ERROR, "Failed to allocate client data."); 710 return; 711 } 712 713 while (true) { 524 bool cont = true; 525 while (cont) { 714 526 ipc_call_t call; 715 527 ipc_callid_t callid = async_get_call(&call); 716 528 717 if (!IPC_GET_IMETHOD(call))718 break;719 720 if (IPC_GET_IMETHOD(call) != DEVMAN_DRIVER_REGISTER) {721 fibril_mutex_lock(&client->mutex);722 driver = client->driver;723 fibril_mutex_unlock(&client->mutex);724 if (driver == NULL) {725 /* First call must be to DEVMAN_DRIVER_REGISTER */726 async_answer_0(callid, ENOTSUP);727 continue;728 }729 }730 731 529 switch (IPC_GET_IMETHOD(call)) { 732 case DEVMAN_DRIVER_REGISTER: 733 fibril_mutex_lock(&client->mutex); 734 if (client->driver != NULL) { 735 fibril_mutex_unlock(&client->mutex); 736 async_answer_0(callid, EINVAL); 737 continue; 738 } 739 client->driver = devman_driver_register(callid, &call); 740 fibril_mutex_unlock(&client->mutex); 741 break; 742 case DEVMAN_ADD_FUNCTION: 743 devman_add_function(callid, &call); 744 break; 745 case DEVMAN_ADD_DEVICE_TO_CATEGORY: 746 devman_add_function_to_cat(callid, &call); 747 break; 748 case DEVMAN_DRV_FUN_ONLINE: 749 devman_drv_fun_online(callid, &call, driver); 750 break; 751 case DEVMAN_DRV_FUN_OFFLINE: 752 devman_drv_fun_offline(callid, &call, driver); 753 break; 754 case DEVMAN_REMOVE_FUNCTION: 755 devman_remove_function(callid, &call); 756 break; 757 default: 758 async_answer_0(callid, EINVAL); 759 break; 760 } 761 } 762 } 763 764 /** Find handle for the device instance identified by the device's path in the 765 * device tree. */ 766 static void devman_function_get_handle(ipc_callid_t iid, ipc_call_t *icall) 767 { 768 char *pathname; 769 devman_handle_t handle; 770 771 int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0); 772 if (rc != EOK) { 773 async_answer_0(iid, rc); 774 return; 775 } 776 777 fun_node_t *fun = find_fun_node_by_path(&device_tree, pathname); 778 779 free(pathname); 780 781 if (fun == NULL) { 782 async_answer_0(iid, ENOENT); 783 return; 784 } 785 786 fibril_rwlock_read_lock(&device_tree.rwlock); 787 788 /* Check function state */ 789 if (fun->state == FUN_REMOVED) { 790 fibril_rwlock_read_unlock(&device_tree.rwlock); 791 async_answer_0(iid, ENOENT); 792 return; 793 } 794 handle = fun->handle; 795 796 fibril_rwlock_read_unlock(&device_tree.rwlock); 797 798 /* Delete reference created above by find_fun_node_by_path() */ 799 fun_del_ref(fun); 800 801 async_answer_1(iid, EOK, handle); 802 } 803 804 /** Get device name. */ 805 static void devman_fun_get_name(ipc_callid_t iid, ipc_call_t *icall) 806 { 807 devman_handle_t handle = IPC_GET_ARG1(*icall); 808 809 fun_node_t *fun = find_fun_node(&device_tree, handle); 810 if (fun == NULL) { 811 async_answer_0(iid, ENOMEM); 812 return; 813 } 814 815 ipc_callid_t data_callid; 816 size_t data_len; 817 if (!async_data_read_receive(&data_callid, &data_len)) { 818 async_answer_0(iid, EINVAL); 819 fun_del_ref(fun); 820 return; 821 } 822 823 void *buffer = malloc(data_len); 824 if (buffer == NULL) { 825 async_answer_0(data_callid, ENOMEM); 826 async_answer_0(iid, ENOMEM); 827 fun_del_ref(fun); 828 return; 829 } 830 831 fibril_rwlock_read_lock(&device_tree.rwlock); 832 833 /* Check function state */ 834 if (fun->state == FUN_REMOVED) { 835 fibril_rwlock_read_unlock(&device_tree.rwlock); 836 free(buffer); 837 838 async_answer_0(data_callid, ENOENT); 839 async_answer_0(iid, ENOENT); 840 fun_del_ref(fun); 841 return; 842 } 843 844 size_t sent_length = str_size(fun->name); 845 if (sent_length > data_len) { 846 sent_length = data_len; 847 } 848 849 async_data_read_finalize(data_callid, fun->name, sent_length); 850 async_answer_0(iid, EOK); 851 852 fibril_rwlock_read_unlock(&device_tree.rwlock); 853 fun_del_ref(fun); 854 free(buffer); 855 } 856 857 858 /** Get device path. */ 859 static void devman_fun_get_path(ipc_callid_t iid, ipc_call_t *icall) 860 { 861 devman_handle_t handle = IPC_GET_ARG1(*icall); 862 863 fun_node_t *fun = find_fun_node(&device_tree, handle); 864 if (fun == NULL) { 865 async_answer_0(iid, ENOMEM); 866 return; 867 } 868 869 ipc_callid_t data_callid; 870 size_t data_len; 871 if (!async_data_read_receive(&data_callid, &data_len)) { 872 async_answer_0(iid, EINVAL); 873 fun_del_ref(fun); 874 return; 875 } 876 877 void *buffer = malloc(data_len); 878 if (buffer == NULL) { 879 async_answer_0(data_callid, ENOMEM); 880 async_answer_0(iid, ENOMEM); 881 fun_del_ref(fun); 882 return; 883 } 884 885 fibril_rwlock_read_lock(&device_tree.rwlock); 886 887 /* Check function state */ 888 if (fun->state == FUN_REMOVED) { 889 fibril_rwlock_read_unlock(&device_tree.rwlock); 890 free(buffer); 891 892 async_answer_0(data_callid, ENOENT); 893 async_answer_0(iid, ENOENT); 894 fun_del_ref(fun); 895 return; 896 } 897 898 size_t sent_length = str_size(fun->pathname); 899 if (sent_length > data_len) { 900 sent_length = data_len; 901 } 902 903 async_data_read_finalize(data_callid, fun->pathname, sent_length); 904 async_answer_0(iid, EOK); 905 906 fibril_rwlock_read_unlock(&device_tree.rwlock); 907 fun_del_ref(fun); 908 free(buffer); 909 } 910 911 static void devman_dev_get_functions(ipc_callid_t iid, ipc_call_t *icall) 912 { 913 ipc_callid_t callid; 914 size_t size; 915 size_t act_size; 916 int rc; 917 918 if (!async_data_read_receive(&callid, &size)) { 919 async_answer_0(callid, EREFUSED); 920 async_answer_0(iid, EREFUSED); 921 return; 922 } 923 924 fibril_rwlock_read_lock(&device_tree.rwlock); 925 926 dev_node_t *dev = find_dev_node_no_lock(&device_tree, 927 IPC_GET_ARG1(*icall)); 928 if (dev == NULL || dev->state == DEVICE_REMOVED) { 929 fibril_rwlock_read_unlock(&device_tree.rwlock); 930 async_answer_0(callid, ENOENT); 931 async_answer_0(iid, ENOENT); 932 return; 933 } 934 935 devman_handle_t *hdl_buf = (devman_handle_t *) malloc(size); 936 if (hdl_buf == NULL) { 937 fibril_rwlock_read_unlock(&device_tree.rwlock); 938 async_answer_0(callid, ENOMEM); 939 async_answer_0(iid, ENOMEM); 940 return; 941 } 942 943 rc = dev_get_functions(&device_tree, dev, hdl_buf, size, &act_size); 944 if (rc != EOK) { 945 fibril_rwlock_read_unlock(&device_tree.rwlock); 946 async_answer_0(callid, rc); 947 async_answer_0(iid, rc); 948 return; 949 } 950 951 fibril_rwlock_read_unlock(&device_tree.rwlock); 952 953 sysarg_t retval = async_data_read_finalize(callid, hdl_buf, size); 954 free(hdl_buf); 955 956 async_answer_1(iid, retval, act_size); 957 } 958 959 960 /** Get handle for child device of a function. */ 961 static void devman_fun_get_child(ipc_callid_t iid, ipc_call_t *icall) 962 { 963 fun_node_t *fun; 964 965 fibril_rwlock_read_lock(&device_tree.rwlock); 966 967 fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall)); 968 if (fun == NULL || fun->state == FUN_REMOVED) { 969 fibril_rwlock_read_unlock(&device_tree.rwlock); 970 async_answer_0(iid, ENOENT); 971 return; 972 } 973 974 if (fun->child == NULL) { 975 fibril_rwlock_read_unlock(&device_tree.rwlock); 976 async_answer_0(iid, ENOENT); 977 return; 978 } 979 980 async_answer_1(iid, EOK, fun->child->handle); 981 982 fibril_rwlock_read_unlock(&device_tree.rwlock); 983 } 984 985 /** Online function. 986 * 987 * Send a request to online a function to the responsible driver. 988 * The driver may offline other functions if necessary (i.e. if the state 989 * of this function is linked to state of another function somehow). 990 */ 991 static void devman_fun_online(ipc_callid_t iid, ipc_call_t *icall) 992 { 993 fun_node_t *fun; 994 int rc; 995 996 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 997 if (fun == NULL) { 998 async_answer_0(iid, ENOENT); 999 return; 1000 } 1001 1002 rc = driver_fun_online(&device_tree, fun); 1003 fun_del_ref(fun); 1004 1005 async_answer_0(iid, (sysarg_t) rc); 1006 } 1007 1008 /** Offline function. 1009 * 1010 * Send a request to offline a function to the responsible driver. As 1011 * a result the subtree rooted at that function should be cleanly 1012 * detatched. The driver may offline other functions if necessary 1013 * (i.e. if the state of this function is linked to state of another 1014 * function somehow). 1015 */ 1016 static void devman_fun_offline(ipc_callid_t iid, ipc_call_t *icall) 1017 { 1018 fun_node_t *fun; 1019 int rc; 1020 1021 fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall)); 1022 if (fun == NULL) { 1023 async_answer_0(iid, ENOENT); 1024 return; 1025 } 1026 1027 rc = driver_fun_offline(&device_tree, fun); 1028 fun_del_ref(fun); 1029 1030 async_answer_0(iid, (sysarg_t) rc); 1031 } 1032 1033 /** Find handle for the function instance identified by its service ID. */ 1034 static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall) 1035 { 1036 fun_node_t *fun; 1037 1038 fun = find_loc_tree_function(&device_tree, IPC_GET_ARG1(*icall)); 1039 1040 if (fun == NULL) { 1041 async_answer_0(iid, ENOENT); 1042 return; 1043 } 1044 1045 fibril_rwlock_read_lock(&device_tree.rwlock); 1046 1047 /* Check function state */ 1048 if (fun->state == FUN_REMOVED) { 1049 fibril_rwlock_read_unlock(&device_tree.rwlock); 1050 async_answer_0(iid, ENOENT); 1051 return; 1052 } 1053 1054 async_answer_1(iid, EOK, fun->handle); 1055 fibril_rwlock_read_unlock(&device_tree.rwlock); 1056 fun_del_ref(fun); 1057 } 1058 1059 /** Function for handling connections from a client to the device manager. */ 1060 static void devman_connection_client(ipc_callid_t iid, ipc_call_t *icall) 1061 { 1062 /* Accept connection. */ 1063 async_answer_0(iid, EOK); 1064 1065 while (true) { 1066 ipc_call_t call; 1067 ipc_callid_t callid = async_get_call(&call); 1068 1069 if (!IPC_GET_IMETHOD(call)) 1070 break; 1071 1072 switch (IPC_GET_IMETHOD(call)) { 530 case IPC_M_PHONE_HUNGUP: 531 cont = false; 532 continue; 1073 533 case DEVMAN_DEVICE_GET_HANDLE: 1074 534 devman_function_get_handle(callid, &call); 1075 535 break; 1076 case DEVMAN_DEV_GET_FUNCTIONS: 1077 devman_dev_get_functions(callid, &call); 1078 break; 1079 case DEVMAN_FUN_GET_CHILD: 1080 devman_fun_get_child(callid, &call); 1081 break; 1082 case DEVMAN_FUN_GET_NAME: 1083 devman_fun_get_name(callid, &call); 1084 break; 1085 case DEVMAN_FUN_GET_PATH: 1086 devman_fun_get_path(callid, &call); 1087 break; 1088 case DEVMAN_FUN_ONLINE: 1089 devman_fun_online(callid, &call); 1090 break; 1091 case DEVMAN_FUN_OFFLINE: 1092 devman_fun_offline(callid, &call); 1093 break; 1094 case DEVMAN_FUN_SID_TO_HANDLE: 1095 devman_fun_sid_to_handle(callid, &call); 536 case DEVMAN_DEVICE_GET_HANDLE_BY_CLASS: 537 devman_function_get_handle_by_class(callid, &call); 1096 538 break; 1097 539 default: … … 1112 554 if (fun == NULL) 1113 555 dev = find_dev_node(&device_tree, handle); 1114 else { 1115 fibril_rwlock_read_lock(&device_tree.rwlock); 556 else 1116 557 dev = fun->dev; 1117 if (dev != NULL)1118 dev_add_ref(dev);1119 fibril_rwlock_read_unlock(&device_tree.rwlock);1120 }1121 558 1122 559 /* … … 1130 567 "function with handle %" PRIun " was found.", handle); 1131 568 async_answer_0(iid, ENOENT); 1132 goto cleanup;569 return; 1133 570 } 1134 571 … … 1138 575 handle); 1139 576 async_answer_0(iid, ENOENT); 1140 goto cleanup;577 return; 1141 578 } 1142 579 1143 580 driver_t *driver = NULL; 1144 1145 fibril_rwlock_read_lock(&device_tree.rwlock);1146 581 1147 582 if (drv_to_parent) { … … 1158 593 } 1159 594 1160 fibril_rwlock_read_unlock(&device_tree.rwlock);1161 1162 595 if (driver == NULL) { 1163 596 log_msg(LVL_ERROR, "IPC forwarding refused - " \ 1164 597 "the device %" PRIun " is not in usable state.", handle); 1165 598 async_answer_0(iid, ENOENT); 1166 goto cleanup;599 return; 1167 600 } 1168 601 … … 1173 606 method = DRIVER_CLIENT; 1174 607 1175 if (!driver->sess) { 1176 log_msg(LVL_ERROR, 1177 "Could not forward to driver `%s'.", driver->name); 608 if (driver->phone < 0) { 609 log_msg(LVL_ERROR, 610 "Could not forward to driver `%s' (phone is %d).", 611 driver->name, (int) driver->phone); 1178 612 async_answer_0(iid, EINVAL); 1179 goto cleanup;613 return; 1180 614 } 1181 615 … … 1189 623 dev->pfun->pathname, driver->name); 1190 624 } 1191 1192 async_exch_t *exch = async_exchange_begin(driver->sess); 1193 async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE); 1194 async_exchange_end(exch); 1195 1196 cleanup: 1197 if (dev != NULL) 1198 dev_del_ref(dev); 1199 if (fun != NULL) 1200 fun_del_ref(fun); 1201 } 1202 1203 /** Function for handling connections from a client forwarded by the location 1204 * service to the device manager. */ 1205 static void devman_connection_loc(ipc_callid_t iid, ipc_call_t *icall) 1206 { 1207 service_id_t service_id = IPC_GET_ARG2(*icall); 625 626 async_forward_fast(iid, driver->phone, method, fwd_h, 0, IPC_FF_NONE); 627 } 628 629 /** Function for handling connections from a client forwarded by the device 630 * mapper to the device manager. */ 631 static void devman_connection_devmapper(ipc_callid_t iid, ipc_call_t *icall) 632 { 633 devmap_handle_t devmap_handle = IPC_GET_ARG2(*icall); 1208 634 fun_node_t *fun; 1209 635 dev_node_t *dev; 1210 devman_handle_t handle; 1211 driver_t *driver; 1212 1213 fun = find_loc_tree_function(&device_tree, service_id); 1214 1215 fibril_rwlock_read_lock(&device_tree.rwlock); 1216 1217 if (fun == NULL || fun->dev == NULL || fun->dev->drv == NULL) { 1218 log_msg(LVL_WARN, "devman_connection_loc(): function " 1219 "not found.\n"); 1220 fibril_rwlock_read_unlock(&device_tree.rwlock); 636 637 fun = find_devmap_tree_function(&device_tree, devmap_handle); 638 if (fun == NULL) 639 fun = find_devmap_class_function(&class_list, devmap_handle); 640 641 if (fun == NULL || fun->dev->drv == NULL) { 1221 642 async_answer_0(iid, ENOENT); 1222 643 return; … … 1224 645 1225 646 dev = fun->dev; 1226 driver = dev->drv;1227 handle = fun->handle;1228 1229 fibril_rwlock_read_unlock(&device_tree.rwlock);1230 1231 async_exch_t *exch = async_exchange_begin(driver->sess);1232 async_forward_fast(iid, exch, DRIVER_CLIENT,handle, 0,647 648 if (dev->state != DEVICE_USABLE || dev->drv->phone < 0) { 649 async_answer_0(iid, EINVAL); 650 return; 651 } 652 653 async_forward_fast(iid, dev->drv->phone, DRIVER_CLIENT, fun->handle, 0, 1233 654 IPC_FF_NONE); 1234 async_exchange_end(exch); 1235 1236 log_msg(LVL_DEBUG, 1237 "Forwarding loc service request for `%s' function to driver `%s'.", 1238 fun->pathname, driver->name); 1239 1240 fun_del_ref(fun); 655 log_msg(LVL_DEBUG, 656 "Forwarding devmapper request for `%s' function to driver `%s'.", 657 fun->pathname, dev->drv->name); 1241 658 } 1242 659 1243 660 /** Function for handling connections to device manager. */ 1244 static void devman_connection(ipc_callid_t iid, ipc_call_t *icall , void *arg)1245 { 1246 /* Select port. */661 static void devman_connection(ipc_callid_t iid, ipc_call_t *icall) 662 { 663 /* Select interface. */ 1247 664 switch ((sysarg_t) (IPC_GET_ARG1(*icall))) { 1248 665 case DEVMAN_DRIVER: … … 1256 673 devman_forward(iid, icall, false); 1257 674 break; 1258 case DEVMAN_CONNECT_FROM_ LOC:1259 /* Someone connected through locnode. */1260 devman_connection_ loc(iid, icall);675 case DEVMAN_CONNECT_FROM_DEVMAP: 676 /* Someone connected through devmap node. */ 677 devman_connection_devmapper(iid, icall); 1261 678 break; 1262 679 case DEVMAN_CONNECT_TO_PARENTS_DEVICE: … … 1270 687 } 1271 688 1272 static void *devman_client_data_create(void)1273 {1274 client_t *client;1275 1276 client = calloc(1, sizeof(client_t));1277 if (client == NULL)1278 return NULL;1279 1280 fibril_mutex_initialize(&client->mutex);1281 return client;1282 }1283 1284 static void devman_client_data_destroy(void *data)1285 {1286 free(data);1287 }1288 1289 689 /** Initialize device manager internal structures. */ 1290 690 static bool devman_init(void) … … 1308 708 } 1309 709 710 init_class_list(&class_list); 711 1310 712 /* 1311 * !!! devman_connection ... as the device manager is not a real loc713 * !!! devman_connection ... as the device manager is not a real devmap 1312 714 * driver (it uses a completely different ipc protocol than an ordinary 1313 * locdriver) forwarding a connection from client to the devman by1314 * location servicewould not work.715 * devmap driver) forwarding a connection from client to the devman by 716 * devmapper would not work. 1315 717 */ 1316 loc_server_register(NAME, devman_connection);718 devmap_driver_register(NAME, devman_connection); 1317 719 1318 720 return true; … … 1323 725 printf(NAME ": HelenOS Device Manager\n"); 1324 726 1325 if (log_init(NAME, LVL_ WARN) != EOK) {727 if (log_init(NAME, LVL_ERROR) != EOK) { 1326 728 printf(NAME ": Error initializing logging subsystem.\n"); 1327 729 return -1; … … 1333 735 } 1334 736 1335 /* Set handlers for incoming connections. */ 1336 async_set_client_data_constructor(devman_client_data_create); 1337 async_set_client_data_destructor(devman_client_data_destroy); 737 /* Set a handler of incomming connections. */ 1338 738 async_set_client_connection(devman_connection); 1339 739 … … 1345 745 1346 746 printf(NAME ": Accepting connections.\n"); 1347 task_retval(0);1348 747 async_manager(); 1349 748
Note:
See TracChangeset
for help on using the changeset viewer.