Ignore:
File:
1 edited

Legend:

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

    r45059d6b rb72efe8  
    3737#include <ipc/driver.h>
    3838#include <ipc/devman.h>
    39 #include <loc.h>
     39#include <devmap.h>
    4040#include <str_error.h>
    4141#include <stdio.h>
     
    6666}
    6767
    68 static int loc_functions_compare(unsigned long key[], hash_count_t keys,
     68static int devmap_functions_compare(unsigned long key[], hash_count_t keys,
    6969    link_t *item)
    7070{
    71         fun_node_t *fun = hash_table_get_instance(item, fun_node_t, loc_fun);
    72         return (fun->service_id == (service_id_t) key[0]);
     71        fun_node_t *fun = hash_table_get_instance(item, fun_node_t, devmap_fun);
     72        return (fun->devmap_handle == (devmap_handle_t) key[0]);
     73}
     74
     75static int devmap_devices_class_compare(unsigned long key[], hash_count_t keys,
     76    link_t *item)
     77{
     78        dev_class_info_t *class_info
     79            = hash_table_get_instance(item, dev_class_info_t, devmap_link);
     80        assert(class_info != NULL);
     81
     82        return (class_info->devmap_handle == (devmap_handle_t) key[0]);
    7383}
    7484
     
    8999};
    90100
    91 static hash_table_operations_t loc_devices_ops = {
     101static hash_table_operations_t devmap_devices_ops = {
    92102        .hash = devices_hash,
    93         .compare = loc_functions_compare,
     103        .compare = devmap_functions_compare,
     104        .remove_callback = devices_remove_callback
     105};
     106
     107static hash_table_operations_t devmap_devices_class_ops = {
     108        .hash = devices_hash,
     109        .compare = devmap_devices_class_compare,
    94110        .remove_callback = devices_remove_callback
    95111};
     
    254270        }
    255271       
    256         ssize_t read_bytes = read_all(fd, buf, len);
     272        ssize_t read_bytes = safe_read(fd, buf, len);
    257273        if (read_bytes <= 0) {
    258                 log_msg(LVL_ERROR, "Unable to read file '%s' (%zd).", conf_path,
    259                     read_bytes);
     274                log_msg(LVL_ERROR, "Unable to read file '%s'.", conf_path);
    260275                goto cleanup;
    261276        }
     
    406421        }
    407422       
    408         insert_fun_node(tree, fun, str_dup(""), NULL);
     423        insert_fun_node(tree, fun, clone_string(""), NULL);
    409424        match_id_t *id = create_match_id();
    410         id->id = str_dup("root");
     425        id->id = clone_string("root");
    411426        id->score = 100;
    412427        add_match_id(&fun->match_ids, id);
     
    548563
    549564        fibril_mutex_lock(&driver->driver_mutex);
     565       
     566        async_exch_t *exch = async_exchange_begin(driver->sess);
     567        async_sess_t *sess = async_connect_me_to(EXCHANGE_SERIALIZE, exch,
     568            DRIVER_DEVMAN, 0, 0);
     569        async_exchange_end(exch);
     570
     571        if (!sess) {
     572                fibril_mutex_unlock(&driver->driver_mutex);
     573                return;
     574        }
    550575
    551576        /*
     
    573598                fibril_mutex_unlock(&driver->driver_mutex);
    574599
    575                 add_device(driver, dev, tree);
     600                add_device(sess, driver, dev, tree);
    576601
    577602                /*
     
    593618                link = driver->devices.head.next;
    594619        }
     620
     621        async_hangup(sess);
    595622
    596623        /*
     
    673700}
    674701
    675 /** Create loc path and name for the function. */
    676 void loc_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
    677 {
    678         char *loc_pathname = NULL;
    679         char *loc_name = NULL;
    680        
    681         asprintf(&loc_name, "%s", fun->pathname);
    682         if (loc_name == NULL)
     702/** Create devmap path and name for the function. */
     703void devmap_register_tree_function(fun_node_t *fun, dev_tree_t *tree)
     704{
     705        char *devmap_pathname = NULL;
     706        char *devmap_name = NULL;
     707       
     708        asprintf(&devmap_name, "%s", fun->pathname);
     709        if (devmap_name == NULL)
    683710                return;
    684711       
    685         replace_char(loc_name, '/', LOC_SEPARATOR);
    686        
    687         asprintf(&loc_pathname, "%s/%s", LOC_DEVICE_NAMESPACE,
    688             loc_name);
    689         if (loc_pathname == NULL) {
    690                 free(loc_name);
     712        replace_char(devmap_name, '/', DEVMAP_SEPARATOR);
     713       
     714        asprintf(&devmap_pathname, "%s/%s", DEVMAP_DEVICE_NAMESPACE,
     715            devmap_name);
     716        if (devmap_pathname == NULL) {
     717                free(devmap_name);
    691718                return;
    692719        }
    693720       
    694         loc_service_register_with_iface(loc_pathname,
    695             &fun->service_id, DEVMAN_CONNECT_FROM_LOC);
    696        
    697         tree_add_loc_function(tree, fun);
    698        
    699         free(loc_name);
    700         free(loc_pathname);
     721        devmap_device_register_with_iface(devmap_pathname,
     722            &fun->devmap_handle, DEVMAN_CONNECT_FROM_DEVMAP);
     723       
     724        tree_add_devmap_function(tree, fun);
     725       
     726        free(devmap_name);
     727        free(devmap_pathname);
    701728}
    702729
     
    706733 * @param node          The device's node in the device tree.
    707734 */
    708 void add_device(driver_t *drv, dev_node_t *dev, dev_tree_t *tree)
     735void add_device(async_sess_t *sess, driver_t *drv, dev_node_t *dev,
     736    dev_tree_t *tree)
    709737{
    710738        /*
     
    723751        }
    724752       
    725         async_exch_t *exch = async_exchange_begin(drv->sess);
     753        async_exch_t *exch = async_exchange_begin(sess);
    726754       
    727755        ipc_call_t answer;
     
    793821        fibril_mutex_unlock(&drv->driver_mutex);
    794822
    795         /* Notify the driver about the new device. */
    796         if (is_running)
    797                 add_device(drv, dev, tree);
     823        if (is_running) {
     824                /* Notify the driver about the new device. */
     825                async_exch_t *exch = async_exchange_begin(drv->sess);
     826                async_sess_t *sess = async_connect_me_to(EXCHANGE_SERIALIZE, exch,
     827                    DRIVER_DEVMAN, 0, 0);
     828                async_exchange_end(exch);
     829               
     830                if (sess) {
     831                        add_device(sess, drv, dev, tree);
     832                        async_hangup(sess);
     833                }
     834        }
    798835       
    799836        return true;
     
    818855        hash_table_create(&tree->devman_functions, DEVICE_BUCKETS, 1,
    819856            &devman_functions_ops);
    820         hash_table_create(&tree->loc_functions, DEVICE_BUCKETS, 1,
    821             &loc_devices_ops);
     857        hash_table_create(&tree->devmap_functions, DEVICE_BUCKETS, 1,
     858            &devmap_devices_ops);
    822859       
    823860        fibril_rwlock_initialize(&tree->rwlock);
     
    898935}
    899936
    900 /** Get list of device functions. */
    901 int dev_get_functions(dev_tree_t *tree, dev_node_t *dev,
    902     devman_handle_t *hdl_buf, size_t buf_size, size_t *act_size)
    903 {
    904         size_t act_cnt;
    905         size_t buf_cnt;
    906 
    907         assert(fibril_rwlock_is_locked(&tree->rwlock));
    908 
    909         buf_cnt = buf_size / sizeof(devman_handle_t);
    910 
    911         act_cnt = list_count(&dev->functions);
    912         *act_size = act_cnt * sizeof(devman_handle_t);
    913 
    914         if (buf_size % sizeof(devman_handle_t) != 0)
    915                 return EINVAL;
    916 
    917         size_t pos = 0;
    918         list_foreach(dev->functions, item) {
    919                 fun_node_t *fun =
    920                     list_get_instance(item, fun_node_t, dev_functions);
    921 
    922                 if (pos < buf_cnt)
    923                         hdl_buf[pos] = fun->handle;
    924                 pos++;
    925         }
    926 
    927         return EOK;
    928 }
    929 
    930 
    931937/* Function nodes */
    932938
     
    943949                link_initialize(&res->dev_functions);
    944950                list_initialize(&res->match_ids.ids);
     951                list_initialize(&res->classes);
    945952                link_initialize(&res->devman_fun);
    946                 link_initialize(&res->loc_fun);
     953                link_initialize(&res->devmap_fun);
    947954        }
    948955       
     
    11071114       
    11081115        return true;
    1109 }
    1110 
    1111 /** Remove function from device tree.
    1112  *
    1113  * @param tree          Device tree
    1114  * @param node          Function node to remove
    1115  */
    1116 void remove_fun_node(dev_tree_t *tree, fun_node_t *fun)
    1117 {
    1118         assert(tree != NULL);
    1119         assert(fun != NULL);
    1120         assert(fibril_rwlock_is_write_locked(&tree->rwlock));
    1121        
    1122         /* Remove the node from the handle-to-node map. */
    1123         unsigned long key = fun->handle;
    1124         hash_table_remove(&tree->devman_functions, &key, 1);
    1125        
    1126         /* Remove the node from the list of its parent's children. */
    1127         if (fun->dev != NULL)
    1128                 list_remove(&fun->dev_functions);
    11291116}
    11301117
     
    11541141        char *rel_path = path;
    11551142        char *next_path_elem = NULL;
    1156         bool cont = (rel_path[1] != '\0');
     1143        bool cont = true;
    11571144       
    11581145        while (cont && fun != NULL) {
     
    12051192}
    12061193
     1194/** Find function node by its class name and index. */
     1195fun_node_t *find_fun_node_by_class(class_list_t *class_list,
     1196    const char *class_name, const char *dev_name)
     1197{
     1198        assert(class_list != NULL);
     1199        assert(class_name != NULL);
     1200        assert(dev_name != NULL);
     1201
     1202        fibril_rwlock_read_lock(&class_list->rwlock);
     1203
     1204        dev_class_t *cl = find_dev_class_no_lock(class_list, class_name);
     1205        if (cl == NULL) {
     1206                fibril_rwlock_read_unlock(&class_list->rwlock);
     1207                return NULL;
     1208        }
     1209
     1210        dev_class_info_t *dev = find_dev_in_class(cl, dev_name);
     1211        if (dev == NULL) {
     1212                fibril_rwlock_read_unlock(&class_list->rwlock);
     1213                return NULL;
     1214        }
     1215
     1216        fun_node_t *fun = dev->fun;
     1217
     1218        fibril_rwlock_read_unlock(&class_list->rwlock);
     1219
     1220        return fun;
     1221}
     1222
     1223
    12071224/** Find child function node with a specified name.
    12081225 *
     
    12181235}
    12191236
    1220 /* loc devices */
    1221 
    1222 fun_node_t *find_loc_tree_function(dev_tree_t *tree, service_id_t service_id)
     1237/* Device classes */
     1238
     1239/** Create device class.
     1240 *
     1241 * @return      Device class.
     1242 */
     1243dev_class_t *create_dev_class(void)
     1244{
     1245        dev_class_t *cl;
     1246       
     1247        cl = (dev_class_t *) malloc(sizeof(dev_class_t));
     1248        if (cl != NULL) {
     1249                memset(cl, 0, sizeof(dev_class_t));
     1250                list_initialize(&cl->devices);
     1251                fibril_mutex_initialize(&cl->mutex);
     1252        }
     1253       
     1254        return cl;
     1255}
     1256
     1257/** Create device class info.
     1258 *
     1259 * @return              Device class info.
     1260 */
     1261dev_class_info_t *create_dev_class_info(void)
     1262{
     1263        dev_class_info_t *info;
     1264       
     1265        info = (dev_class_info_t *) malloc(sizeof(dev_class_info_t));
     1266        if (info != NULL) {
     1267                memset(info, 0, sizeof(dev_class_info_t));
     1268                link_initialize(&info->dev_classes);
     1269                link_initialize(&info->devmap_link);
     1270                link_initialize(&info->link);
     1271        }
     1272       
     1273        return info;
     1274}
     1275
     1276size_t get_new_class_dev_idx(dev_class_t *cl)
     1277{
     1278        size_t dev_idx;
     1279       
     1280        fibril_mutex_lock(&cl->mutex);
     1281        dev_idx = ++cl->curr_dev_idx;
     1282        fibril_mutex_unlock(&cl->mutex);
     1283       
     1284        return dev_idx;
     1285}
     1286
     1287
     1288/** Create unique device name within the class.
     1289 *
     1290 * @param cl            The class.
     1291 * @param base_dev_name Contains the base name for the device if it was
     1292 *                      specified by the driver when it registered the device by
     1293 *                      the class; NULL if driver specified no base name.
     1294 * @return              The unique name for the device within the class.
     1295 */
     1296char *create_dev_name_for_class(dev_class_t *cl, const char *base_dev_name)
     1297{
     1298        char *dev_name;
     1299        const char *base_name;
     1300       
     1301        if (base_dev_name != NULL)
     1302                base_name = base_dev_name;
     1303        else
     1304                base_name = cl->base_dev_name;
     1305       
     1306        size_t idx = get_new_class_dev_idx(cl);
     1307        asprintf(&dev_name, "%s%zu", base_name, idx);
     1308       
     1309        return dev_name;
     1310}
     1311
     1312/** Add the device function to the class.
     1313 *
     1314 * The device may be added to multiple classes and a class may contain multiple
     1315 * devices. The class and the device are associated with each other by the
     1316 * dev_class_info_t structure.
     1317 *
     1318 * @param dev           The device.
     1319 * @param class         The class.
     1320 * @param base_dev_name The base name of the device within the class if
     1321 *                      specified by the driver, NULL otherwise.
     1322 * @return              dev_class_info_t structure which associates the device
     1323 *                      with the class.
     1324 */
     1325dev_class_info_t *add_function_to_class(fun_node_t *fun, dev_class_t *cl,
     1326    const char *base_dev_name)
     1327{
     1328        dev_class_info_t *info;
     1329
     1330        assert(fun != NULL);
     1331        assert(cl != NULL);
     1332
     1333        info = create_dev_class_info();
     1334
     1335       
     1336        if (info != NULL) {
     1337                info->dev_class = cl;
     1338                info->fun = fun;
     1339               
     1340                /* Add the device to the class. */
     1341                fibril_mutex_lock(&cl->mutex);
     1342                list_append(&info->link, &cl->devices);
     1343                fibril_mutex_unlock(&cl->mutex);
     1344               
     1345                /* Add the class to the device. */
     1346                list_append(&info->dev_classes, &fun->classes);
     1347               
     1348                /* Create unique name for the device within the class. */
     1349                info->dev_name = create_dev_name_for_class(cl, base_dev_name);
     1350        }
     1351       
     1352        return info;
     1353}
     1354
     1355dev_class_t *get_dev_class(class_list_t *class_list, char *class_name)
     1356{
     1357        dev_class_t *cl;
     1358       
     1359        fibril_rwlock_write_lock(&class_list->rwlock);
     1360        cl = find_dev_class_no_lock(class_list, class_name);
     1361        if (cl == NULL) {
     1362                cl = create_dev_class();
     1363                if (cl != NULL) {
     1364                        cl->name = class_name;
     1365                        cl->base_dev_name = "";
     1366                        add_dev_class_no_lock(class_list, cl);
     1367                }
     1368        }
     1369
     1370        fibril_rwlock_write_unlock(&class_list->rwlock);
     1371        return cl;
     1372}
     1373
     1374dev_class_t *find_dev_class_no_lock(class_list_t *class_list,
     1375    const char *class_name)
     1376{
     1377        dev_class_t *cl;
     1378       
     1379        list_foreach(class_list->classes, link) {
     1380                cl = list_get_instance(link, dev_class_t, link);
     1381                if (str_cmp(cl->name, class_name) == 0) {
     1382                        return cl;
     1383                }
     1384        }
     1385       
     1386        return NULL;
     1387}
     1388
     1389void add_dev_class_no_lock(class_list_t *class_list, dev_class_t *cl)
     1390{
     1391        list_append(&cl->link, &class_list->classes);
     1392}
     1393
     1394dev_class_info_t *find_dev_in_class(dev_class_t *dev_class, const char *dev_name)
     1395{
     1396        assert(dev_class != NULL);
     1397        assert(dev_name != NULL);
     1398
     1399        list_foreach(dev_class->devices, link) {
     1400                dev_class_info_t *dev = list_get_instance(link,
     1401                    dev_class_info_t, link);
     1402
     1403                if (str_cmp(dev->dev_name, dev_name) == 0) {
     1404                        return dev;
     1405                }
     1406        }
     1407
     1408        return NULL;
     1409}
     1410
     1411void init_class_list(class_list_t *class_list)
     1412{
     1413        list_initialize(&class_list->classes);
     1414        fibril_rwlock_initialize(&class_list->rwlock);
     1415        hash_table_create(&class_list->devmap_functions, DEVICE_BUCKETS, 1,
     1416            &devmap_devices_class_ops);
     1417}
     1418
     1419
     1420/* Devmap devices */
     1421
     1422fun_node_t *find_devmap_tree_function(dev_tree_t *tree, devmap_handle_t devmap_handle)
    12231423{
    12241424        fun_node_t *fun = NULL;
    12251425        link_t *link;
    1226         unsigned long key = (unsigned long) service_id;
     1426        unsigned long key = (unsigned long) devmap_handle;
    12271427       
    12281428        fibril_rwlock_read_lock(&tree->rwlock);
    1229         link = hash_table_find(&tree->loc_functions, &key);
     1429        link = hash_table_find(&tree->devmap_functions, &key);
    12301430        if (link != NULL)
    1231                 fun = hash_table_get_instance(link, fun_node_t, loc_fun);
     1431                fun = hash_table_get_instance(link, fun_node_t, devmap_fun);
    12321432        fibril_rwlock_read_unlock(&tree->rwlock);
    12331433       
     
    12351435}
    12361436
    1237 void tree_add_loc_function(dev_tree_t *tree, fun_node_t *fun)
    1238 {
    1239         unsigned long key = (unsigned long) fun->service_id;
     1437fun_node_t *find_devmap_class_function(class_list_t *classes,
     1438    devmap_handle_t devmap_handle)
     1439{
     1440        fun_node_t *fun = NULL;
     1441        dev_class_info_t *cli;
     1442        link_t *link;
     1443        unsigned long key = (unsigned long)devmap_handle;
     1444       
     1445        fibril_rwlock_read_lock(&classes->rwlock);
     1446        link = hash_table_find(&classes->devmap_functions, &key);
     1447        if (link != NULL) {
     1448                cli = hash_table_get_instance(link, dev_class_info_t,
     1449                    devmap_link);
     1450                fun = cli->fun;
     1451        }
     1452        fibril_rwlock_read_unlock(&classes->rwlock);
     1453       
     1454        return fun;
     1455}
     1456
     1457void class_add_devmap_function(class_list_t *class_list, dev_class_info_t *cli)
     1458{
     1459        unsigned long key = (unsigned long) cli->devmap_handle;
     1460       
     1461        fibril_rwlock_write_lock(&class_list->rwlock);
     1462        hash_table_insert(&class_list->devmap_functions, &key, &cli->devmap_link);
     1463        fibril_rwlock_write_unlock(&class_list->rwlock);
     1464
     1465        assert(find_devmap_class_function(class_list, cli->devmap_handle) != NULL);
     1466}
     1467
     1468void tree_add_devmap_function(dev_tree_t *tree, fun_node_t *fun)
     1469{
     1470        unsigned long key = (unsigned long) fun->devmap_handle;
    12401471        fibril_rwlock_write_lock(&tree->rwlock);
    1241         hash_table_insert(&tree->loc_functions, &key, &fun->loc_fun);
     1472        hash_table_insert(&tree->devmap_functions, &key, &fun->devmap_fun);
    12421473        fibril_rwlock_write_unlock(&tree->rwlock);
    12431474}
Note: See TracChangeset for help on using the changeset viewer.