Changeset 38b3baf in mainline for uspace/srv/devman/devman.c
- Timestamp:
- 2010-10-23T07:16:14Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 7e66a5ec
- Parents:
- 032e0bb
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devman/devman.c
r032e0bb r38b3baf 40 40 #include "devman.h" 41 41 42 / / hash table operations42 /* hash table operations */ 43 43 44 44 static hash_index_t devices_hash(unsigned long key[]) … … 47 47 } 48 48 49 static int devman_devices_compare(unsigned long key[], hash_count_t keys, link_t *item) 49 static int 50 devman_devices_compare(unsigned long key[], hash_count_t keys, link_t *item) 50 51 { 51 52 node_t *dev = hash_table_get_instance(item, node_t, devman_link); … … 53 54 } 54 55 55 static int devmap_devices_compare(unsigned long key[], hash_count_t keys, link_t *item) 56 static int 57 devmap_devices_compare(unsigned long key[], hash_count_t keys, link_t *item) 56 58 { 57 59 node_t *dev = hash_table_get_instance(item, node_t, devmap_link); … … 76 78 77 79 /** Allocate and initialize a new driver structure. 78 * 79 * @return driver structure.80 */ 81 driver_t * create_driver()80 * 81 * @return Driver structure. 82 */ 83 driver_t *create_driver(void) 82 84 { 83 85 driver_t *res = malloc(sizeof(driver_t)); 84 if (res != NULL) {86 if (res != NULL) 85 87 init_driver(res); 86 }87 88 return res; 88 89 } 89 90 90 91 /** Add a driver to the list of drivers. 91 * 92 * 92 93 * @param drivers_list the list of drivers. 93 94 * @param drv the driver's structure. … … 99 100 fibril_mutex_unlock(&drivers_list->drivers_mutex); 100 101 101 printf(NAME": the '%s' driver was added to the list of available drivers.\n", drv->name);102 } 103 104 /** Read match id at the specified position of a string and set 105 * the position in the string to the first character following the id. 106 * 107 * @param buf the position in the input string.108 * 109 * @return the match id.110 */ 111 char * read_match_id(char **buf)102 printf(NAME": the '%s' driver was added to the list of available " 103 "drivers.\n", drv->name); 104 } 105 106 /** Read match id at the specified position of a string and set the position in 107 * the string to the first character following the id. 108 * 109 * @param buf The position in the input string. 110 * @return The match id. 111 */ 112 char *read_match_id(char **buf) 112 113 { 113 114 char *res = NULL; 114 115 size_t len = get_nonspace_len(*buf); 116 115 117 if (len > 0) { 116 118 res = malloc(len + 1); 117 119 if (res != NULL) { 118 str_ncpy(res, len + 1, *buf, len); 120 str_ncpy(res, len + 1, *buf, len); 119 121 *buf += len; 120 122 } 121 123 } 124 122 125 return res; 123 126 } … … 125 128 /** 126 129 * Read match ids and associated match scores from a string. 127 * 128 * Each match score in the string is followed by its match id. 129 * The match ids and match scores are separated by whitespaces. 130 * Neither match ids nor match scores can contain whitespaces. 131 * 132 * @param buf the string from which the match ids are read. 133 * @param ids the list of match ids into which the match ids and scores are added. 134 * 135 * @return true if at least one match id and associated match score was successfully read, false otherwise. 130 * 131 * Each match score in the string is followed by its match id. 132 * The match ids and match scores are separated by whitespaces. 133 * Neither match ids nor match scores can contain whitespaces. 134 * 135 * @param buf The string from which the match ids are read. 136 * @param ids The list of match ids into which the match ids and 137 * scores are added. 138 * @return True if at least one match id and associated match score 139 * was successfully read, false otherwise. 136 140 */ 137 141 bool parse_match_ids(char *buf, match_id_list_t *ids) … … 142 146 143 147 while (true) { 144 / / skip spaces145 if (!skip_spaces(&buf)) {148 /* skip spaces */ 149 if (!skip_spaces(&buf)) 146 150 break; 147 }148 / / read score151 152 /* read score */ 149 153 score = strtoul(buf, &buf, 10); 150 154 151 / / skip spaces152 if (!skip_spaces(&buf)) {155 /* skip spaces */ 156 if (!skip_spaces(&buf)) 153 157 break; 154 } 155 156 // read id 157 if (NULL == (id = read_match_id(&buf))) { 158 break; 159 } 160 161 // create new match_id structure 158 159 /* read id */ 160 id = read_match_id(&buf); 161 if (NULL == id) 162 break; 163 164 /* create new match_id structure */ 162 165 match_id_t *mid = create_match_id(); 163 166 mid->id = id; 164 167 mid->score = score; 165 168 166 / // add it to the list169 /* add it to the list */ 167 170 add_match_id(ids, mid); 168 171 169 ids_read++; 170 } 172 ids_read++; 173 } 171 174 172 175 return ids_read > 0; … … 175 178 /** 176 179 * Read match ids and associated match scores from a file. 177 * 178 * Each match score in the file is followed by its match id. 179 * The match ids and match scores are separated by whitespaces. 180 * Neither match ids nor match scores can contain whitespaces. 181 * 182 * @param buf the path to the file from which the match ids are read. 183 * @param ids the list of match ids into which the match ids and scores are added. 184 * 185 * @return true if at least one match id and associated match score was successfully read, false otherwise. 186 */ 187 bool read_match_ids(const char *conf_path, match_id_list_t *ids) 188 { 180 * 181 * Each match score in the file is followed by its match id. 182 * The match ids and match scores are separated by whitespaces. 183 * Neither match ids nor match scores can contain whitespaces. 184 * 185 * @param buf The path to the file from which the match ids are read. 186 * @param ids The list of match ids into which the match ids and 187 * scores are added. 188 * @return True if at least one match id and associated match score 189 * was successfully read, false otherwise. 190 */ 191 bool read_match_ids(const char *conf_path, match_id_list_t *ids) 192 { 189 193 printf(NAME ": read_match_ids conf_path = %s.\n", conf_path); 190 194 191 bool suc = false; 195 bool suc = false; 192 196 char *buf = NULL; 193 197 bool opened = false; 194 int fd; 198 int fd; 195 199 size_t len = 0; 196 200 … … 199 203 printf(NAME ": unable to open %s\n", conf_path); 200 204 goto cleanup; 201 } 202 opened = true; 205 } 206 opened = true; 203 207 204 208 len = lseek(fd, 0, SEEK_END); 205 lseek(fd, 0, SEEK_SET); 209 lseek(fd, 0, SEEK_SET); 206 210 if (len == 0) { 207 211 printf(NAME ": configuration file '%s' is empty.\n", conf_path); 208 goto cleanup; 212 goto cleanup; 209 213 } 210 214 211 215 buf = malloc(len + 1); 212 216 if (buf == NULL) { 213 printf(NAME ": memory allocation failed when parsing file '%s'.\n", conf_path); 217 printf(NAME ": memory allocation failed when parsing file " 218 "'%s'.\n", conf_path); 214 219 goto cleanup; 215 220 } … … 224 229 225 230 cleanup: 226 227 231 free(buf); 228 232 229 if(opened) { 230 close(fd); 231 } 233 if(opened) 234 close(fd); 232 235 233 236 return suc; … … 236 239 /** 237 240 * Get information about a driver. 238 * 239 * Each driver has its own directory in the base directory. 241 * 242 * Each driver has its own directory in the base directory. 240 243 * The name of the driver's directory is the same as the name of the driver. 241 * The driver's directory contains driver's binary (named as the driver without extension) 242 * and the configuration file with match ids for device-to-driver matching 243 * (named as the driver with a special extension). 244 * 245 * This function searches for the driver's directory and containing configuration files. 246 * If all the files needed are found, they are parsed and 247 * the information about the driver is stored to the driver's structure. 248 * 249 * @param base_path the base directory, in which we look for driver's subdirectory. 250 * @param name the name of the driver. 251 * @param drv the driver structure to fill information in. 252 * 253 * @return true on success, false otherwise. 244 * The driver's directory contains driver's binary (named as the driver without 245 * extension) and the configuration file with match ids for device-to-driver 246 * matching (named as the driver with a special extension). 247 * 248 * This function searches for the driver's directory and containing 249 * configuration files. If all the files needed are found, they are parsed and 250 * the information about the driver is stored in the driver's structure. 251 * 252 * @param base_path The base directory, in which we look for driver's 253 * subdirectory. 254 * @param name The name of the driver. 255 * @param drv The driver structure to fill information in. 256 * 257 * @return True on success, false otherwise. 254 258 */ 255 259 bool get_driver_info(const char *base_path, const char *name, driver_t *drv) 256 260 { 257 printf(NAME ": get_driver_info base_path = %s, name = %s.\n", base_path, name); 261 printf(NAME ": get_driver_info base_path = %s, name = %s.\n", 262 base_path, name); 258 263 259 264 assert(base_path != NULL && name != NULL && drv != NULL); 260 265 261 266 bool suc = false; 262 char *match_path = NULL; 267 char *match_path = NULL; 263 268 size_t name_size = 0; 264 269 265 // read the list of match ids from the driver's configuration file 266 if (NULL == (match_path = get_abs_path(base_path, name, MATCH_EXT))) { 270 /* Read the list of match ids from the driver's configuration file. */ 271 match_path = get_abs_path(base_path, name, MATCH_EXT); 272 if (NULL == match_path) 267 273 goto cleanup; 268 } 269 270 if (!read_match_ids(match_path, &drv->match_ids)) { 274 275 if (!read_match_ids(match_path, &drv->match_ids)) 271 276 goto cleanup; 272 } 273 274 // allocate and fill driver's name 275 name_size = str_size(name)+1; 277 278 /* Allocate and fill driver's name. */ 279 name_size = str_size(name) + 1; 276 280 drv->name = malloc(name_size); 277 if (!drv->name) {281 if (!drv->name) 278 282 goto cleanup; 279 }280 283 str_cpy(drv->name, name_size, name); 281 284 282 // initialize path with driver's binary 283 if (NULL == (drv->binary_path = get_abs_path(base_path, name, ""))) { 285 /* Initialize path with driver's binary. */ 286 drv->binary_path = get_abs_path(base_path, name, ""); 287 if (NULL == drv->binary_path) 284 288 goto cleanup; 285 } 286 287 // check whether the driver's binary exists 289 290 /* Check whether the driver's binary exists. */ 288 291 struct stat s; 289 292 if (stat(drv->binary_path, &s) == ENOENT) { … … 295 298 296 299 cleanup: 297 298 300 if (!suc) { 299 301 free(drv->binary_path); 300 302 free(drv->name); 301 / / set the driver structure to the default state302 init_driver(drv); 303 /* Set the driver structure to the default state. */ 304 init_driver(drv); 303 305 } 304 306 … … 309 311 310 312 /** Lookup drivers in the directory. 311 * 312 * @param drivers_list the list of available drivers. 313 * @param dir_path the path to the directory where we search for drivers. 314 * 315 * @return number of drivers which were found. 316 */ 313 * 314 * @param drivers_list The list of available drivers. 315 * @param dir_path The path to the directory where we search for drivers. 316 * @return Number of drivers which were found. 317 */ 317 318 int lookup_available_drivers(driver_list_t *drivers_list, const char *dir_path) 318 319 { … … 327 328 if (dir != NULL) { 328 329 driver_t *drv = create_driver(); 329 while ((diren = readdir(dir))) { 330 while ((diren = readdir(dir))) { 330 331 if (get_driver_info(dir_path, diren->d_name, drv)) { 331 332 add_driver(drivers_list, drv); 332 333 drv_cnt++; 333 334 drv = create_driver(); 334 } 335 } 335 336 } 336 337 delete_driver(drv); … … 342 343 343 344 /** Create root device node in the device tree. 344 * 345 * @param tree the device tree.346 * @return true on success, false otherwise.345 * 346 * @param tree The device tree. 347 * @return True on success, false otherwise. 347 348 */ 348 349 bool create_root_node(dev_tree_t *tree) … … 350 351 printf(NAME ": create_root_node\n"); 351 352 node_t *node = create_dev_node(); 352 if (node) { 353 if (node) { 353 354 insert_dev_node(tree, node, clone_string(""), NULL); 354 355 match_id_t *id = create_match_id(); … … 358 359 tree->root_node = node; 359 360 } 360 return node != NULL; 361 } 362 363 /** Lookup the best matching driver for the specified device in the list of drivers. 364 * 365 * A match between a device and a driver is found 366 * if one of the driver's match ids match one of the device's match ids. 367 * The score of the match is the product of the driver's and device's score associated with the matching id. 368 * The best matching driver for a device is the driver 369 * with the highest score of the match between the device and the driver. 370 * 371 * @param drivers_list the list of drivers, where we look for the driver suitable for handling the device. 372 * @param node the device node structure of the device. 373 * 374 * @return the best matching driver or NULL if no matching driver is found. 375 */ 376 driver_t * find_best_match_driver(driver_list_t *drivers_list, node_t *node) 377 { 378 //printf(NAME ": find_best_match_driver for device '%s' \n", node->pathname); 361 return node != NULL; 362 } 363 364 /** Lookup the best matching driver for the specified device in the list of 365 * drivers. 366 * 367 * A match between a device and a driver is found if one of the driver's match 368 * ids match one of the device's match ids. The score of the match is the 369 * product of the driver's and device's score associated with the matching id. 370 * The best matching driver for a device is the driver with the highest score 371 * of the match between the device and the driver. 372 * 373 * @param drivers_list The list of drivers, where we look for the driver 374 * suitable for handling the device. 375 * @param node The device node structure of the device. 376 * @return The best matching driver or NULL if no matching driver 377 * is found. 378 */ 379 driver_t *find_best_match_driver(driver_list_t *drivers_list, node_t *node) 380 { 379 381 driver_t *best_drv = NULL, *drv = NULL; 380 382 int best_score = 0, score = 0; … … 382 384 fibril_mutex_lock(&drivers_list->drivers_mutex); 383 385 384 link_t *link = drivers_list->drivers.next; 386 link_t *link = drivers_list->drivers.next; 385 387 while (link != &drivers_list->drivers) { 386 388 drv = list_get_instance(link, driver_t, drivers); … … 395 397 fibril_mutex_unlock(&drivers_list->drivers_mutex); 396 398 397 return best_drv; 398 } 399 400 /** 401 * Assign a driver to a device.402 * 403 * @param node the device's node in the device tree.404 * @param drv the driver.405 */ 406 void attach_driver(node_t *node, driver_t *drv) 407 { 408 printf(NAME ": attach_driver %s to device %s\n",drv->name, node->pathname);399 return best_drv; 400 } 401 402 /** Assign a driver to a device. 403 * 404 * @param node The device's node in the device tree. 405 * @param drv The driver. 406 */ 407 void attach_driver(node_t *node, driver_t *drv) 408 { 409 printf(NAME ": attach_driver %s to device %s\n", 410 drv->name, node->pathname); 409 411 410 412 fibril_mutex_lock(&drv->driver_mutex); … … 416 418 } 417 419 418 /** Start a driver .419 * 420 /** Start a driver 421 * 420 422 * The driver's mutex is assumed to be locked. 421 * 422 * @param drv the driver's structure. 423 * @return true if the driver's task is successfully spawned, false otherwise. 423 * 424 * @param drv The driver's structure. 425 * @return True if the driver's task is successfully spawned, false 426 * otherwise. 424 427 */ 425 428 bool start_driver(driver_t *drv) … … 434 437 int err; 435 438 if (!task_spawn(drv->binary_path, argv, &err)) { 436 printf(NAME ": error spawning %s, errno = %d\n", drv->name, err); 439 printf(NAME ": error spawning %s, errno = %d\n", 440 drv->name, err); 437 441 return false; 438 442 } … … 443 447 444 448 /** Find device driver in the list of device drivers. 445 * 446 * @param drv_list the list of device drivers. 447 * @param drv_name the name of the device driver which is searched. 448 * @return the device driver of the specified name, if it is in the list, NULL otherwise. 449 */ 450 driver_t * find_driver(driver_list_t *drv_list, const char *drv_name) 451 { 449 * 450 * @param drv_list The list of device drivers. 451 * @param drv_name The name of the device driver which is searched. 452 * @return The device driver of the specified name, if it is in the 453 * list, NULL otherwise. 454 */ 455 driver_t *find_driver(driver_list_t *drv_list, const char *drv_name) 456 { 452 457 driver_t *res = NULL; 453 458 454 fibril_mutex_lock(&drv_list->drivers_mutex); 459 fibril_mutex_lock(&drv_list->drivers_mutex); 455 460 456 461 driver_t *drv = NULL; 457 link_t *link = drv_list->drivers.next; 462 link_t *link = drv_list->drivers.next; 458 463 while (link != &drv_list->drivers) { 459 464 drv = list_get_instance(link, driver_t, drivers); … … 471 476 472 477 /** Remember the driver's phone. 473 * @param driver the driver. 474 * @param phone the phone to the driver. 478 * 479 * @param driver The driver. 480 * @param phone The phone to the driver. 475 481 */ 476 482 void set_driver_phone(driver_t *driver, ipcarg_t phone) 477 { 478 fibril_mutex_lock(&driver->driver_mutex); 483 { 484 fibril_mutex_lock(&driver->driver_mutex); 479 485 assert(DRIVER_STARTING == driver->state); 480 driver->phone = phone; 481 fibril_mutex_unlock(&driver->driver_mutex); 482 } 483 484 /** 485 * Notify driver about the devices to which it was assigned. 486 * 486 driver->phone = phone; 487 fibril_mutex_unlock(&driver->driver_mutex); 488 } 489 490 /** Notify driver about the devices to which it was assigned. 491 * 487 492 * The driver's mutex must be locked. 488 * 489 * @param driver the driver to which the devices are passed.493 * 494 * @param driver The driver to which the devices are passed. 490 495 */ 491 496 static void pass_devices_to_driver(driver_t *driver, dev_tree_t *tree) 492 { 497 { 493 498 printf(NAME ": pass_devices_to_driver\n"); 494 499 node_t *dev; … … 510 515 } 511 516 512 /** Finish the initialization of a driver after it has succesfully started 517 /** Finish the initialization of a driver after it has succesfully started 513 518 * and after it has registered itself by the device manager. 514 * 515 * Pass devices formerly matched to the driver to the driver and remember the driver is running and fully functional now. 516 * 517 * @param driver the driver which registered itself as running by the device manager. 518 */ 519 void initialize_running_driver(driver_t *driver, dev_tree_t *tree) 520 { 519 * 520 * Pass devices formerly matched to the driver to the driver and remember the 521 * driver is running and fully functional now. 522 * 523 * @param driver The driver which registered itself as running by the 524 * device manager. 525 */ 526 void initialize_running_driver(driver_t *driver, dev_tree_t *tree) 527 { 521 528 printf(NAME ": initialize_running_driver\n"); 522 529 fibril_mutex_lock(&driver->driver_mutex); 523 530 524 // pass devices which have been already assigned to the driver to the driver 525 pass_devices_to_driver(driver, tree); 526 527 // change driver's state to running 528 driver->state = DRIVER_RUNNING; 531 /* 532 * Pass devices which have been already assigned to the driver to the 533 * driver. 534 */ 535 pass_devices_to_driver(driver, tree); 536 537 /* Change driver's state to running. */ 538 driver->state = DRIVER_RUNNING; 529 539 530 540 fibril_mutex_unlock(&driver->driver_mutex); … … 532 542 533 543 544 /** Create devmap path and name for the device. */ 534 545 static void devmap_register_tree_device(node_t *node, dev_tree_t *tree) 535 546 { 536 // create devmap path and name for the device537 547 char *devmap_pathname = NULL; 538 548 char *devmap_name = NULL; 539 549 540 550 asprintf(&devmap_name, "%s", node->pathname); 541 if (NULL == devmap_name) {551 if (NULL == devmap_name) 542 552 return; 543 }544 553 545 554 replace_char(devmap_name, '/', DEVMAP_SEPARATOR); 546 555 547 asprintf(&devmap_pathname, "%s/%s", DEVMAP_DEVICE_NAMESPACE, devmap_name); 556 asprintf(&devmap_pathname, "%s/%s", DEVMAP_DEVICE_NAMESPACE, 557 devmap_name); 548 558 if (NULL == devmap_pathname) { 549 559 free(devmap_name); 550 560 return; 551 } 561 } 552 562 553 563 devmap_device_register(devmap_pathname, &node->devmap_handle); … … 556 566 557 567 free(devmap_name); 558 free(devmap_pathname); 568 free(devmap_pathname); 559 569 } 560 570 561 571 562 572 /** Pass a device to running driver. 563 * 564 * @param drv the driver's structure.565 * @param node the device's node in the device tree.573 * 574 * @param drv The driver's structure. 575 * @param node The device's node in the device tree. 566 576 */ 567 577 void add_device(int phone, driver_t *drv, node_t *node, dev_tree_t *tree) … … 572 582 ipc_call_t answer; 573 583 574 // send the device to the driver 575 aid_t req = async_send_1(phone, DRIVER_ADD_DEVICE, node->handle, &answer); 576 577 // send the device's name to the driver 578 rc = async_data_write_start(phone, node->name, str_size(node->name) + 1); 579 if (rc != EOK) { 580 // TODO handle error 581 } 582 583 // wait for answer from the driver 584 /* Send the device to the driver. */ 585 aid_t req = async_send_1(phone, DRIVER_ADD_DEVICE, node->handle, 586 &answer); 587 588 /* Send the device's name to the driver. */ 589 rc = async_data_write_start(phone, node->name, 590 str_size(node->name) + 1); 591 if (rc != EOK) { 592 /* TODO handle error */ 593 } 594 595 /* Wait for answer from the driver. */ 584 596 async_wait_for(req, &rc); 585 597 switch(rc) { … … 592 604 break; 593 605 default: 594 node->state = DEVICE_INVALID; 606 node->state = DEVICE_INVALID; 595 607 } 596 608 … … 598 610 } 599 611 600 /** 601 * Find suitable driver for a device and assign the driver to it. 602 * 603 * @param node the device node of the device in the device tree. 604 * @param drivers_list the list of available drivers. 605 * 606 * @return true if the suitable driver is found and successfully assigned to the device, false otherwise. 607 */ 608 bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree) 609 { 610 //printf(NAME ": assign_driver\n"); 611 612 // find the driver which is the most suitable for handling this device 612 /** Find suitable driver for a device and assign the driver to it. 613 * 614 * @param node The device node of the device in the device tree. 615 * @param drivers_list The list of available drivers. 616 * @return True if the suitable driver is found and 617 * successfully assigned to the device, false otherwise. 618 */ 619 bool assign_driver(node_t *node, driver_list_t *drivers_list, dev_tree_t *tree) 620 { 621 /* 622 * Find the driver which is the most suitable for handling this device. 623 */ 613 624 driver_t *drv = find_best_match_driver(drivers_list, node); 614 625 if (NULL == drv) { 615 printf(NAME ": no driver found for device '%s'.\n", node->pathname); 616 return false; 617 } 618 619 // attach the driver to the device 626 printf(NAME ": no driver found for device '%s'.\n", 627 node->pathname); 628 return false; 629 } 630 631 /* Attach the driver to the device. */ 620 632 attach_driver(node, drv); 621 633 622 634 if (DRIVER_NOT_STARTED == drv->state) { 623 / / start driver635 /* Start the driver. */ 624 636 start_driver(drv); 625 } 637 } 626 638 627 639 if (DRIVER_RUNNING == drv->state) { 628 / / notify driver about new device640 /* Notify the driver about the new device. */ 629 641 int phone = ipc_connect_me_to(drv->phone, DRIVER_DEVMAN, 0, 0); 630 642 if (phone > 0) { 631 add_device(phone, drv, node, tree); 643 add_device(phone, drv, node, tree); 632 644 ipc_hangup(phone); 633 645 } … … 637 649 } 638 650 639 /** 640 * Initialize the device tree. 641 * 651 /** Initialize the device tree. 652 * 642 653 * Create root device node of the tree and assign driver to it. 643 * 644 * @param tree the device tree.645 * @param the list of available drivers.646 * @return true on success, false otherwise.654 * 655 * @param tree The device tree. 656 * @param drivers_list the list of available drivers. 657 * @return True on success, false otherwise. 647 658 */ 648 659 bool init_device_tree(dev_tree_t *tree, driver_list_t *drivers_list) … … 652 663 tree->current_handle = 0; 653 664 654 hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1, &devman_devices_ops); 655 hash_table_create(&tree->devmap_devices, DEVICE_BUCKETS, 1, &devmap_devices_ops); 665 hash_table_create(&tree->devman_devices, DEVICE_BUCKETS, 1, 666 &devman_devices_ops); 667 hash_table_create(&tree->devmap_devices, DEVICE_BUCKETS, 1, 668 &devmap_devices_ops); 656 669 657 670 fibril_rwlock_initialize(&tree->rwlock); 658 671 659 / / create root node and add it to the device tree660 if (!create_root_node(tree)) {672 /* Create root node and add it to the device tree. */ 673 if (!create_root_node(tree)) 661 674 return false; 662 } 663 664 // find suitable driver and start it 675 676 /* Find suitable driver and start it. */ 665 677 return assign_driver(tree->root_node, drivers_list, tree); 666 678 } 667 679 668 680 /** Create and set device's full path in device tree. 669 * 670 * @param node the device's device node. 671 * @param parent the parent device node. 672 * @return true on success, false otherwise (insufficient resources etc.). 681 * 682 * @param node The device's device node. 683 * @param parent The parent device node. 684 * @return True on success, false otherwise (insufficient 685 * resources etc.). 673 686 */ 674 687 static bool set_dev_path(node_t *node, node_t *parent) 675 { 688 { 676 689 assert(NULL != node->name); 677 690 678 size_t pathsize = (str_size(node->name) + 1); 679 if (NULL != parent) {680 pathsize += str_size(parent->pathname) + 1; 681 }682 683 if (NULL == (node->pathname = (char *)malloc(pathsize))) {691 size_t pathsize = (str_size(node->name) + 1); 692 if (NULL != parent) 693 pathsize += str_size(parent->pathname) + 1; 694 695 node->pathname = (char *) malloc(pathsize); 696 if (NULL == node->pathname) { 684 697 printf(NAME ": failed to allocate device path.\n"); 685 698 return false; … … 698 711 699 712 /** Insert new device into device tree. 700 * 701 * The device tree's rwlock should be already held exclusively when calling this function. 702 * 703 * @param tree the device tree. 704 * @param node the newly added device node. 705 * @param dev_name the name of the newly added device. 706 * @param parent the parent device node. 707 * @return true on success, false otherwise (insufficient resources etc.). 708 */ 709 bool insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name, node_t *parent) 710 { 711 // printf(NAME ": insert_dev_node\n"); 712 713 * 714 * The device tree's rwlock should be already held exclusively when calling this 715 * function. 716 * 717 * @param tree The device tree. 718 * @param node The newly added device node. 719 * @param dev_name The name of the newly added device. 720 * @param parent The parent device node. 721 * @return True on success, false otherwise (insufficient resources 722 * etc.). 723 */ 724 bool 725 insert_dev_node(dev_tree_t *tree, node_t *node, char *dev_name, node_t *parent) 726 { 713 727 assert(NULL != node && NULL != tree && NULL != dev_name); 714 728 … … 716 730 if (!set_dev_path(node, parent)) { 717 731 fibril_rwlock_write_unlock(&tree->rwlock); 718 return false; 719 } 720 721 / / add the node to the handle-to-node map732 return false; 733 } 734 735 /* Add the node to the handle-to-node map. */ 722 736 node->handle = ++tree->current_handle; 723 737 unsigned long key = node->handle; 724 738 hash_table_insert(&tree->devman_devices, &key, &node->devman_link); 725 739 726 / / add the node to the list of its parent's children740 /* Add the node to the list of its parent's children. */ 727 741 node->parent = parent; 728 if (NULL != parent) {729 list_append(&node->sibling, &parent->children); 730 }742 if (NULL != parent) 743 list_append(&node->sibling, &parent->children); 744 731 745 return true; 732 746 } 733 747 734 /** 735 * Find device node with a specified path in the device tree. 748 /** Find device node with a specified path in the device tree. 736 749 * 737 * @param path the path of the device node in the device tree.738 * @param tree the device tree.739 * 740 * @return the device node if it is present in the tree, NULLotherwise.741 */ 742 node_t * 750 * @param path The path of the device node in the device tree. 751 * @param tree The device tree. 752 * @return The device node if it is present in the tree, NULL 753 * otherwise. 754 */ 755 node_t *find_dev_node_by_path(dev_tree_t *tree, char *path) 743 756 { 744 757 fibril_rwlock_read_lock(&tree->rwlock); 745 758 746 759 node_t *dev = tree->root_node; 747 // relative path to the device from its parent (but with '/' at the beginning) 760 /* 761 * Relative path to the device from its parent (but with '/' at the 762 * beginning) 763 */ 748 764 char *rel_path = path; 749 765 char *next_path_elem = NULL; 750 766 bool cont = '/' == rel_path[0]; 751 767 752 while (cont && NULL != dev) { 753 next_path_elem = get_path_elem_end(rel_path + 1); 768 while (cont && NULL != dev) { 769 next_path_elem = get_path_elem_end(rel_path + 1); 754 770 if ('/' == next_path_elem[0]) { 755 771 cont = true; … … 759 775 } 760 776 761 dev = find_node_child(dev, rel_path + 1); 777 dev = find_node_child(dev, rel_path + 1); 762 778 763 779 if (cont) { 764 / / restore the original path780 /* Restore the original path. */ 765 781 next_path_elem[0] = '/'; 766 782 } 767 rel_path = next_path_elem; 783 rel_path = next_path_elem; 768 784 } 769 785 … … 773 789 } 774 790 775 /** 776 * Find child device node with a specified name. 777 * 778 * Device tree rwlock should be held at least for reading. 779 * 780 * @param parent the parent device node. 781 * @param name the name of the child device node. 782 * 783 * @return the child device node. 791 /** Find child device node with a specified name. 792 * 793 * Device tree rwlock should be held at least for reading. 794 * 795 * @param parent The parent device node. 796 * @param name The name of the child device node. 797 * @return The child device node. 784 798 */ 785 799 node_t *find_node_child(node_t *parent, const char *name) … … 787 801 node_t *dev; 788 802 link_t *link; 789 803 790 804 link = parent->children.next; 791 805 … … 793 807 dev = list_get_instance(link, node_t, sibling); 794 808 795 if (0 == str_cmp(name, dev->name)) { 796 return dev; 797 } 809 if (0 == str_cmp(name, dev->name)) 810 return dev; 798 811 799 812 link = link->next; 800 } 801 813 } 814 802 815 return NULL; 803 816 } 804 817 805 /** Create unique device name within the class. 806 * 807 * @param cl the class.808 * @param base_dev_name contains base name for the device809 * if it was specified by the driver when it registered the device by the class;810 * NULL if driver specified no base name.811 * @return the unique name for the device within the class.812 */ 813 char * 818 /** Create unique device name within the class. 819 * 820 * @param cl The class. 821 * @param base_dev_name Contains the base name for the device if it was 822 * specified by the driver when it registered the device by 823 * the class; NULL if driver specified no base name. 824 * @return The unique name for the device within the class. 825 */ 826 char *create_dev_name_for_class(dev_class_t *cl, const char *base_dev_name) 814 827 { 815 828 char *dev_name; 816 829 const char *base_name; 817 if (NULL != base_dev_name) { 830 831 if (NULL != base_dev_name) 818 832 base_name = base_dev_name; 819 } else {833 else 820 834 base_name = cl->base_dev_name; 821 }822 835 823 836 size_t idx = get_new_class_dev_idx(cl); 824 837 asprintf(&dev_name, "%s%d", base_name, idx); 825 return dev_name; 838 839 return dev_name; 826 840 } 827 841 828 842 /** Add the device to the class. 829 * 830 * The device may be added to multiple classes and a class may contain multiple devices. 831 * The class and the device are associated with each other by the dev_class_info_t structure. 832 * 833 * @param dev the device. 834 * @param class the class. 835 * @param base_dev_name the base name of the device within the class if specified by the driver, 836 * NULL otherwise. 837 * @return dev_class_info_t structure which associates the device with the class. 838 */ 839 dev_class_info_t * add_device_to_class(node_t *dev, dev_class_t *cl, const char *base_dev_name) 840 { 843 * 844 * The device may be added to multiple classes and a class may contain multiple 845 * devices. The class and the device are associated with each other by the 846 * dev_class_info_t structure. 847 * 848 * @param dev The device. 849 * @param class The class. 850 * @param base_dev_name The base name of the device within the class if 851 * specified by the driver, NULL otherwise. 852 * @return dev_class_info_t structure which associates the device 853 * with the class. 854 */ 855 dev_class_info_t * 856 add_device_to_class(node_t *dev, dev_class_t *cl, const char *base_dev_name) 857 { 841 858 dev_class_info_t *info = create_dev_class_info(); 859 842 860 if (NULL != info) { 843 861 info->dev_class = cl; 844 862 info->dev = dev; 845 863 846 / / add the device to the class864 /* Add the device to the class. */ 847 865 fibril_mutex_lock(&cl->mutex); 848 866 list_append(&info->link, &cl->devices); 849 867 fibril_mutex_unlock(&cl->mutex); 850 868 851 / / add the class to the device869 /* Add the class to the device. */ 852 870 list_append(&info->dev_classes, &dev->classes); 853 871 854 / / create unique name for the device within the class855 info->dev_name = create_dev_name_for_class(cl, base_dev_name); 872 /* Create unique name for the device within the class. */ 873 info->dev_name = create_dev_name_for_class(cl, base_dev_name); 856 874 } 857 875 … … 859 877 } 860 878 861 dev_class_t * 879 dev_class_t *get_dev_class(class_list_t *class_list, char *class_name) 862 880 { 863 881 dev_class_t *cl; 864 fibril_rwlock_write_lock(&class_list->rwlock); 882 883 fibril_rwlock_write_lock(&class_list->rwlock); 865 884 cl = find_dev_class_no_lock(class_list, class_name); 866 885 if (NULL == cl) { 867 886 cl = create_dev_class(); 868 887 if (NULL != cl) { 869 cl->name = class_name; 888 cl->name = class_name; 870 889 cl->base_dev_name = ""; 871 890 add_dev_class_no_lock(class_list, cl); 872 } 873 } 891 } 892 } 874 893 fibril_rwlock_write_unlock(&class_list->rwlock); 875 894 return cl; 876 895 } 877 896 878 dev_class_t * find_dev_class_no_lock(class_list_t *class_list, const char *class_name) 897 dev_class_t * 898 find_dev_class_no_lock(class_list_t *class_list, const char *class_name) 879 899 { 880 900 dev_class_t *cl; 881 901 link_t *link = class_list->classes.next; 902 882 903 while (link != &class_list->classes) { 883 904 cl = list_get_instance(link, dev_class_t, link); 884 if (0 == str_cmp(cl->name, class_name)) {905 if (0 == str_cmp(cl->name, class_name)) 885 906 return cl; 886 } 887 } 888 889 return NULL; 907 } 908 909 return NULL; 890 910 } 891 911 … … 894 914 list_initialize(&class_list->classes); 895 915 fibril_rwlock_initialize(&class_list->rwlock); 896 hash_table_create(&class_list->devmap_devices, DEVICE_BUCKETS, 1, &devmap_devices_ops); 897 } 898 899 900 // devmap devices 916 hash_table_create(&class_list->devmap_devices, DEVICE_BUCKETS, 1, 917 &devmap_devices_ops); 918 } 919 920 921 /* devmap devices */ 901 922 902 923 node_t *find_devmap_tree_device(dev_tree_t *tree, dev_handle_t devmap_handle) … … 904 925 node_t *dev = NULL; 905 926 link_t *link; 906 unsigned long key = (unsigned long) devmap_handle;927 unsigned long key = (unsigned long) devmap_handle; 907 928 908 929 fibril_rwlock_read_lock(&tree->rwlock); 909 link = hash_table_find(&tree->devmap_devices, &key); 910 if (NULL != link) {930 link = hash_table_find(&tree->devmap_devices, &key); 931 if (NULL != link) 911 932 dev = hash_table_get_instance(link, node_t, devmap_link); 912 }913 933 fibril_rwlock_read_unlock(&tree->rwlock); 914 934 … … 916 936 } 917 937 918 node_t *find_devmap_class_device(class_list_t *classes, dev_handle_t devmap_handle) 938 node_t * 939 find_devmap_class_device(class_list_t *classes, dev_handle_t devmap_handle) 919 940 { 920 941 node_t *dev = NULL; … … 924 945 925 946 fibril_rwlock_read_lock(&classes->rwlock); 926 link = hash_table_find(&classes->devmap_devices, &key); 947 link = hash_table_find(&classes->devmap_devices, &key); 927 948 if (NULL != link) { 928 cli = hash_table_get_instance(link, dev_class_info_t, devmap_link); 949 cli = hash_table_get_instance(link, dev_class_info_t, 950 devmap_link); 929 951 dev = cli->dev; 930 952 } 931 953 fibril_rwlock_read_unlock(&classes->rwlock); 932 954 933 return dev; 934 } 935 955 return dev; 956 } 936 957 937 958 /** @}
Note:
See TracChangeset
for help on using the changeset viewer.