Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/devman/main.c

    rf302586 r422722e  
    234234        dev_node_t *dev_node = (dev_node_t *) arg;
    235235        assign_driver(dev_node, &drivers_list, &device_tree);
    236 
    237         /* Delete one reference we got from the caller. */
    238         dev_del_ref(dev_node);
    239236        return EOK;
    240237}
    241238
    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) {
     239/** Handle function registration.
     240 *
     241 * Child devices are registered by their parent's device driver.
     242 */
     243static 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) {
    256301                dev = create_dev_node();
    257302                if (dev == NULL) {
    258                         fibril_rwlock_write_unlock(&device_tree.rwlock);
    259                         return ENOMEM;
     303                        fibril_rwlock_write_unlock(&tree->rwlock);
     304                        delete_fun_node(fun);
     305                        async_answer_0(callid, ENOMEM);
     306                        return;
    260307                }
    261308
    262                 insert_dev_node(&device_tree, dev, fun);
    263                 dev_add_ref(dev);
    264         }
     309                insert_dev_node(tree, dev, fun);
     310        }
     311
     312        fibril_rwlock_write_unlock(&tree->rwlock);
    265313       
    266314        log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
    267315       
    268         if (fun->ftype == fun_inner) {
    269                 dev = fun->child;
     316        devman_receive_match_ids(match_count, &fun->match_ids);
     317
     318        if (ftype == fun_inner) {
    270319                assert(dev != NULL);
    271                
    272                 /* Give one reference over to assign_driver_fibril(). */
    273                 dev_add_ref(dev);
    274320                /*
    275321                 * Try to find a suitable driver and assign it to the device.  We do
     
    281327                fid_t assign_fibril = fibril_create(assign_driver_fibril, dev);
    282328                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);
     329                        /*
     330                         * Fallback in case we are out of memory.
     331                         * Probably not needed as we will die soon anyway ;-).
     332                         */
     333                        (void) assign_driver_fibril(fun);
     334                } else {
     335                        fibril_add_ready(assign_fibril);
    355336                }
    356337        } 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;
     338                loc_register_tree_function(fun, tree);
    453339        }
    454340       
     
    470356                async_answer_0(callid, rc);
    471357                return;
    472         }
     358        }       
    473359       
    474360        fun_node_t *fun = find_fun_node(&device_tree, handle);
     
    478364        }
    479365       
    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        
    489366        rc = loc_category_get_id(cat_name, &cat_id, IPC_FLAG_BLOCKING);
    490367        if (rc == EOK) {
    491368                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);
    494369        } else {
    495370                log_msg(LVL_ERROR, "Failed adding function `%s' to category "
     
    497372        }
    498373       
    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));
    517         if (fun == NULL) {
    518                 async_answer_0(iid, ENOENT);
    519                 return;
    520         }
    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);
    532         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));
    554         if (fun == NULL) {
    555                 async_answer_0(iid, ENOENT);
    556                 return;
    557         }
    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);
     374        log_msg(LVL_NOTE, "Function `%s' added to category `%s'.",
     375            fun->pathname, cat_name);
     376
     377        async_answer_0(callid, EOK);
    576378}
    577379
     
    583385        int rc;
    584386       
    585         fun_node_t *fun = find_fun_node(&device_tree, fun_handle);
     387        fibril_rwlock_write_lock(&tree->rwlock);
     388       
     389        fun_node_t *fun = find_fun_node_no_lock(&device_tree, fun_handle);
    586390        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) {
    597391                fibril_rwlock_write_unlock(&tree->rwlock);
    598392                async_answer_0(callid, ENOENT);
     
    600394        }
    601395       
     396        log_msg(LVL_DEBUG, "devman_remove_function(fun='%s')", fun->pathname);
     397       
    602398        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                 }
     399                /* Handle possible descendants */
     400                /* TODO */
     401                log_msg(LVL_WARN, "devman_remove_function(): not handling "
     402                    "descendants\n");
    656403        } 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                         }
     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;
    668411                }
    669412        }
     
    671414        remove_fun_node(&device_tree, fun);
    672415        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);
     416        delete_fun_node(fun);
    678417       
    679418        log_msg(LVL_DEBUG, "devman_remove_function() succeeded.");
     
    746485                        devman_add_function_to_cat(callid, &call);
    747486                        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;
    754487                case DEVMAN_REMOVE_FUNCTION:
    755488                        devman_remove_function(callid, &call);
    756489                        break;
    757490                default:
    758                         async_answer_0(callid, EINVAL);
     491                        async_answer_0(callid, EINVAL); 
    759492                        break;
    760493                }
     
    767500{
    768501        char *pathname;
    769         devman_handle_t handle;
    770502       
    771503        int rc = async_data_write_accept((void **) &pathname, true, 0, 0, 0, 0);
     
    784516        }
    785517
    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);
     518        async_answer_1(iid, EOK, fun->handle);
    802519}
    803520
     
    817534        if (!async_data_read_receive(&data_callid, &data_len)) {
    818535                async_answer_0(iid, EINVAL);
    819                 fun_del_ref(fun);
    820536                return;
    821537        }
     
    825541                async_answer_0(data_callid, ENOMEM);
    826542                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);
    841543                return;
    842544        }
     
    850552        async_answer_0(iid, EOK);
    851553
    852         fibril_rwlock_read_unlock(&device_tree.rwlock);
    853         fun_del_ref(fun);
    854554        free(buffer);
    855555}
     
    871571        if (!async_data_read_receive(&data_callid, &data_len)) {
    872572                async_answer_0(iid, EINVAL);
    873                 fun_del_ref(fun);
    874573                return;
    875574        }
     
    879578                async_answer_0(data_callid, ENOMEM);
    880579                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        
     580                return;
     581        }
     582
    898583        size_t sent_length = str_size(fun->pathname);
    899584        if (sent_length > data_len) {
     
    904589        async_answer_0(iid, EOK);
    905590
    906         fibril_rwlock_read_unlock(&device_tree.rwlock);
    907         fun_del_ref(fun);
    908591        free(buffer);
    909592}
     
    926609        dev_node_t *dev = find_dev_node_no_lock(&device_tree,
    927610            IPC_GET_ARG1(*icall));
    928         if (dev == NULL || dev->state == DEVICE_REMOVED) {
     611        if (dev == NULL) {
    929612                fibril_rwlock_read_unlock(&device_tree.rwlock);
    930613                async_answer_0(callid, ENOENT);
     
    965648        fibril_rwlock_read_lock(&device_tree.rwlock);
    966649       
    967         fun = find_fun_node_no_lock(&device_tree, IPC_GET_ARG1(*icall));
    968         if (fun == NULL || fun->state == FUN_REMOVED) {
     650        fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
     651        if (fun == NULL) {
    969652                fibril_rwlock_read_unlock(&device_tree.rwlock);
    970653                async_answer_0(iid, ENOENT);
     
    983666}
    984667
    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)
     668/** Find handle for the function instance identified by its service ID. */
     669static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall)
    992670{
    993671        fun_node_t *fun;
    994         int rc;
    995 
    996         fun = find_fun_node(&device_tree, IPC_GET_ARG1(*icall));
     672
     673        fun = find_loc_tree_function(&device_tree, IPC_GET_ARG1(*icall));
     674       
    997675        if (fun == NULL) {
    998676                async_answer_0(iid, ENOENT);
    999677                return;
    1000678        }
    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         }
    1053679
    1054680        async_answer_1(iid, EOK, fun->handle);
    1055         fibril_rwlock_read_unlock(&device_tree.rwlock);
    1056         fun_del_ref(fun);
    1057681}
    1058682
     
    1086710                        devman_fun_get_path(callid, &call);
    1087711                        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;
    1094712                case DEVMAN_FUN_SID_TO_HANDLE:
    1095713                        devman_fun_sid_to_handle(callid, &call);
     
    1112730        if (fun == NULL)
    1113731                dev = find_dev_node(&device_tree, handle);
    1114         else {
    1115                 fibril_rwlock_read_lock(&device_tree.rwlock);
     732        else
    1116733                dev = fun->dev;
    1117                 if (dev != NULL)
    1118                         dev_add_ref(dev);
    1119                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    1120         }
    1121734
    1122735        /*
     
    1130743                    "function with handle %" PRIun " was found.", handle);
    1131744                async_answer_0(iid, ENOENT);
    1132                 goto cleanup;
     745                return;
    1133746        }
    1134747
     
    1138751                    handle);
    1139752                async_answer_0(iid, ENOENT);
    1140                 goto cleanup;
     753                return;
    1141754        }
    1142755       
    1143756        driver_t *driver = NULL;
    1144        
    1145         fibril_rwlock_read_lock(&device_tree.rwlock);
    1146757       
    1147758        if (drv_to_parent) {
     
    1158769        }
    1159770       
    1160         fibril_rwlock_read_unlock(&device_tree.rwlock);
    1161        
    1162771        if (driver == NULL) {
    1163772                log_msg(LVL_ERROR, "IPC forwarding refused - " \
    1164773                    "the device %" PRIun " is not in usable state.", handle);
    1165774                async_answer_0(iid, ENOENT);
    1166                 goto cleanup;
     775                return;
    1167776        }
    1168777       
     
    1177786                    "Could not forward to driver `%s'.", driver->name);
    1178787                async_answer_0(iid, EINVAL);
    1179                 goto cleanup;
     788                return;
    1180789        }
    1181790
     
    1193802        async_forward_fast(iid, exch, method, fwd_h, 0, IPC_FF_NONE);
    1194803        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);
    1201804}
    1202805
     
    1208811        fun_node_t *fun;
    1209812        dev_node_t *dev;
    1210         devman_handle_t handle;
    1211         driver_t *driver;
    1212813
    1213814        fun = find_loc_tree_function(&device_tree, service_id);
    1214815       
    1215         fibril_rwlock_read_lock(&device_tree.rwlock);
    1216        
    1217         if (fun == NULL || fun->dev == NULL || fun->dev->drv == NULL) {
     816        if (fun == NULL || fun->dev->drv == NULL) {
    1218817                log_msg(LVL_WARN, "devman_connection_loc(): function "
    1219818                    "not found.\n");
    1220                 fibril_rwlock_read_unlock(&device_tree.rwlock);
    1221819                async_answer_0(iid, ENOENT);
    1222820                return;
     
    1224822       
    1225823        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,
     824       
     825        async_exch_t *exch = async_exchange_begin(dev->drv->sess);
     826        async_forward_fast(iid, exch, DRIVER_CLIENT, fun->handle, 0,
    1233827            IPC_FF_NONE);
    1234828        async_exchange_end(exch);
     
    1236830        log_msg(LVL_DEBUG,
    1237831            "Forwarding loc service request for `%s' function to driver `%s'.",
    1238             fun->pathname, driver->name);
    1239 
    1240         fun_del_ref(fun);
     832            fun->pathname, dev->drv->name);
    1241833}
    1242834
     
    1309901
    1310902        /*
    1311          * Caution: As the device manager is not a real loc
    1312          * driver (it uses a completely different IPC protocol
    1313          * than an ordinary loc driver), forwarding a connection
    1314          * from client to the devman by location service will
    1315          * not work.
     903         * !!! devman_connection ... as the device manager is not a real loc
     904         * driver (it uses a completely different ipc protocol than an ordinary
     905         * loc driver) forwarding a connection from client to the devman by
     906         * location service would not work.
    1316907         */
    1317         loc_server_register(NAME);
     908        loc_server_register(NAME, devman_connection);
    1318909       
    1319910        return true;
     
    1326917        if (log_init(NAME, LVL_WARN) != EOK) {
    1327918                printf(NAME ": Error initializing logging subsystem.\n");
     919                return -1;
     920        }
     921
     922        if (!devman_init()) {
     923                log_msg(LVL_ERROR, "Error while initializing service.");
    1328924                return -1;
    1329925        }
     
    1334930        async_set_client_connection(devman_connection);
    1335931
    1336         if (!devman_init()) {
    1337                 log_msg(LVL_ERROR, "Error while initializing service.");
    1338                 return -1;
    1339         }
    1340 
    1341932        /* Register device manager at naming service. */
    1342933        if (service_register(SERVICE_DEVMAN) != EOK) {
Note: See TracChangeset for help on using the changeset viewer.