Ignore:
File:
1 edited

Legend:

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

    r1a5b252 r422722e  
    237237}
    238238
    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) {
     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) {
    246301                dev = create_dev_node();
    247302                if (dev == NULL) {
    248                         fibril_rwlock_write_unlock(&device_tree.rwlock);
     303                        fibril_rwlock_write_unlock(&tree->rwlock);
    249304                        delete_fun_node(fun);
    250                         return ENOMEM;
     305                        async_answer_0(callid, ENOMEM);
     306                        return;
    251307                }
    252308
    253                 insert_dev_node(&device_tree, dev, fun);
    254         }
    255        
    256         fibril_rwlock_write_unlock(&device_tree.rwlock);
     309                insert_dev_node(tree, dev, fun);
     310        }
     311
     312        fibril_rwlock_write_unlock(&tree->rwlock);
    257313       
    258314        log_msg(LVL_DEBUG, "devman_add_function(fun=\"%s\")", fun->pathname);
    259315       
    260         if (fun->ftype == fun_inner) {
    261                 dev = fun->child;
     316        devman_receive_match_ids(match_count, &fun->match_ids);
     317
     318        if (ftype == fun_inner) {
    262319                assert(dev != NULL);
    263                
    264320                /*
    265321                 * Try to find a suitable driver and assign it to the device.  We do
     
    280336                }
    281337        } else {
    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;
     338                loc_register_tree_function(fun, tree);
    391339        }
    392340       
     
    430378}
    431379
    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 
    490380/** Remove function. */
    491381static void devman_remove_function(ipc_callid_t callid, ipc_call_t *call)
     
    509399                /* Handle possible descendants */
    510400                /* TODO */
    511                 if (fun->child != NULL) {
    512                         log_msg(LVL_WARN, "devman_remove_function(): not handling "
    513                             "descendants\n");
    514                 }
     401                log_msg(LVL_WARN, "devman_remove_function(): not handling "
     402                    "descendants\n");
    515403        } else {
    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                         }
     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;
    526411                }
    527412        }
     
    600485                        devman_add_function_to_cat(callid, &call);
    601486                        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;
    608487                case DEVMAN_REMOVE_FUNCTION:
    609488                        devman_remove_function(callid, &call);
    610489                        break;
    611490                default:
    612                         async_answer_0(callid, EINVAL);
     491                        async_answer_0(callid, EINVAL); 
    613492                        break;
    614493                }
     
    787666}
    788667
    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 
    841668/** Find handle for the function instance identified by its service ID. */
    842669static void devman_fun_sid_to_handle(ipc_callid_t iid, ipc_call_t *icall)
     
    882709                case DEVMAN_FUN_GET_PATH:
    883710                        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);
    890711                        break;
    891712                case DEVMAN_FUN_SID_TO_HANDLE:
Note: See TracChangeset for help on using the changeset viewer.