Changes in uspace/srv/devmap/devmap.c [a405563:63e0bdd] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devmap/devmap.c
ra405563 r63e0bdd 42 42 #include <errno.h> 43 43 #include <bool.h> 44 #include <fibril_sync .h>44 #include <fibril_synch.h> 45 45 #include <stdlib.h> 46 #include <str ing.h>46 #include <str.h> 47 47 #include <ipc/devmap.h> 48 #include <assert.h> 48 49 49 50 #define NAME "devmap" … … 61 62 link_t devices; 62 63 /** Phone asociated with this driver */ 63 ipcarg_t phone;64 sysarg_t phone; 64 65 /** Device driver name */ 65 66 char *name; … … 67 68 fibril_mutex_t devices_mutex; 68 69 } devmap_driver_t; 70 71 /** Info about registered namespaces 72 * 73 */ 74 typedef struct { 75 /** Pointer to the previous and next device in the list of all namespaces */ 76 link_t namespaces; 77 /** Unique namespace identifier */ 78 devmap_handle_t handle; 79 /** Namespace name */ 80 char *name; 81 /** Reference count */ 82 size_t refcnt; 83 } devmap_namespace_t; 69 84 70 85 /** Info about registered device … … 77 92 owned by one driver */ 78 93 link_t driver_devices; 79 /** Unique device identifier */ 80 dev_handle_t handle; 94 /** Unique device identifier */ 95 devmap_handle_t handle; 96 /** Device namespace */ 97 devmap_namespace_t *namespace; 81 98 /** Device name */ 82 99 char *name; 83 100 /** Device driver handling this device */ 84 101 devmap_driver_t *driver; 102 /** Use this interface when forwarding to driver. */ 103 sysarg_t forward_interface; 85 104 } devmap_device_t; 86 105 87 106 LIST_INITIALIZE(devices_list); 107 LIST_INITIALIZE(namespaces_list); 88 108 LIST_INITIALIZE(drivers_list); 89 109 … … 101 121 static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex); 102 122 103 static dev _handle_t last_handle = 0;123 static devmap_handle_t last_handle = 0; 104 124 static devmap_device_t *null_devices[NULL_DEVICES]; 105 125 106 static dev_handle_t devmap_create_handle(void) 126 /* 127 * Dummy list for null devices. This is necessary so that null devices can 128 * be used just as any other devices, e.g. in devmap_device_unregister_core(). 129 */ 130 static LIST_INITIALIZE(dummy_null_driver_devices); 131 132 static devmap_handle_t devmap_create_handle(void) 107 133 { 108 134 /* TODO: allow reusing old handles after their unregistration … … 117 143 } 118 144 119 /** Find device with given name. 120 * 121 */ 122 static devmap_device_t *devmap_device_find_name(const char *name) 123 { 124 link_t *item = devices_list.next; 125 devmap_device_t *device = NULL; 126 127 while (item != &devices_list) { 128 device = list_get_instance(item, devmap_device_t, devices); 129 if (str_cmp(device->name, name) == 0) 130 break; 131 item = item->next; 132 } 133 134 if (item == &devices_list) 145 /** Convert fully qualified device name to namespace and device name. 146 * 147 * A fully qualified device name can be either a plain device name 148 * (then the namespace is considered to be an empty string) or consist 149 * of two components separated by a slash. No more than one slash 150 * is allowed. 151 * 152 */ 153 static bool devmap_fqdn_split(const char *fqdn, char **ns_name, char **name) 154 { 155 size_t cnt = 0; 156 size_t slash_offset = 0; 157 size_t slash_after = 0; 158 159 size_t offset = 0; 160 size_t offset_prev = 0; 161 wchar_t c; 162 163 while ((c = str_decode(fqdn, &offset, STR_NO_LIMIT)) != 0) { 164 if (c == '/') { 165 cnt++; 166 slash_offset = offset_prev; 167 slash_after = offset; 168 } 169 offset_prev = offset; 170 } 171 172 /* More than one slash */ 173 if (cnt > 1) 174 return false; 175 176 /* No slash -> namespace is empty */ 177 if (cnt == 0) { 178 *ns_name = str_dup(""); 179 if (*ns_name == NULL) 180 return false; 181 182 *name = str_dup(fqdn); 183 if (*name == NULL) { 184 free(*ns_name); 185 return false; 186 } 187 188 if (str_cmp(*name, "") == 0) { 189 free(*name); 190 free(*ns_name); 191 return false; 192 } 193 194 return true; 195 } 196 197 /* Exactly one slash */ 198 *ns_name = str_ndup(fqdn, slash_offset); 199 if (*ns_name == NULL) 200 return false; 201 202 *name = str_dup(fqdn + slash_after); 203 if (*name == NULL) { 204 free(*ns_name); 205 return false; 206 } 207 208 if (str_cmp(*name, "") == 0) { 209 free(*name); 210 free(*ns_name); 211 return false; 212 } 213 214 return true; 215 } 216 217 /** Find namespace with given name. */ 218 static devmap_namespace_t *devmap_namespace_find_name(const char *name) 219 { 220 link_t *item; 221 222 assert(fibril_mutex_is_locked(&devices_list_mutex)); 223 224 for (item = namespaces_list.next; item != &namespaces_list; item = item->next) { 225 devmap_namespace_t *namespace = 226 list_get_instance(item, devmap_namespace_t, namespaces); 227 if (str_cmp(namespace->name, name) == 0) 228 return namespace; 229 } 230 231 return NULL; 232 } 233 234 /** Find namespace with given handle. 235 * 236 * @todo: use hash table 237 * 238 */ 239 static devmap_namespace_t *devmap_namespace_find_handle(devmap_handle_t handle) 240 { 241 link_t *item; 242 243 assert(fibril_mutex_is_locked(&devices_list_mutex)); 244 245 for (item = namespaces_list.next; item != &namespaces_list; item = item->next) { 246 devmap_namespace_t *namespace = 247 list_get_instance(item, devmap_namespace_t, namespaces); 248 if (namespace->handle == handle) 249 return namespace; 250 } 251 252 return NULL; 253 } 254 255 /** Find device with given name. */ 256 static devmap_device_t *devmap_device_find_name(const char *ns_name, 257 const char *name) 258 { 259 link_t *item; 260 261 assert(fibril_mutex_is_locked(&devices_list_mutex)); 262 263 for (item = devices_list.next; item != &devices_list; item = item->next) { 264 devmap_device_t *device = 265 list_get_instance(item, devmap_device_t, devices); 266 if ((str_cmp(device->namespace->name, ns_name) == 0) 267 && (str_cmp(device->name, name) == 0)) 268 return device; 269 } 270 271 return NULL; 272 } 273 274 /** Find device with given handle. 275 * 276 * @todo: use hash table 277 * 278 */ 279 static devmap_device_t *devmap_device_find_handle(devmap_handle_t handle) 280 { 281 link_t *item; 282 283 assert(fibril_mutex_is_locked(&devices_list_mutex)); 284 285 for (item = devices_list.next; item != &devices_list; item = item->next) { 286 devmap_device_t *device = 287 list_get_instance(item, devmap_device_t, devices); 288 if (device->handle == handle) 289 return device; 290 } 291 292 return NULL; 293 } 294 295 /** Create a namespace (if not already present). */ 296 static devmap_namespace_t *devmap_namespace_create(const char *ns_name) 297 { 298 devmap_namespace_t *namespace; 299 300 assert(fibril_mutex_is_locked(&devices_list_mutex)); 301 302 namespace = devmap_namespace_find_name(ns_name); 303 if (namespace != NULL) 304 return namespace; 305 306 namespace = (devmap_namespace_t *) malloc(sizeof(devmap_namespace_t)); 307 if (namespace == NULL) 135 308 return NULL; 136 309 137 device = list_get_instance(item, devmap_device_t, devices); 138 return device; 139 } 140 141 /** Find device with given handle. 142 * 143 * @todo: use hash table 144 * 145 */ 146 static devmap_device_t *devmap_device_find_handle(dev_handle_t handle) 147 { 148 fibril_mutex_lock(&devices_list_mutex); 149 150 link_t *item = (&devices_list)->next; 151 devmap_device_t *device = NULL; 152 153 while (item != &devices_list) { 154 device = list_get_instance(item, devmap_device_t, devices); 155 if (device->handle == handle) 156 break; 157 item = item->next; 158 } 159 160 if (item == &devices_list) { 161 fibril_mutex_unlock(&devices_list_mutex); 310 namespace->name = str_dup(ns_name); 311 if (namespace->name == NULL) { 312 free(namespace); 162 313 return NULL; 163 314 } 164 315 165 device = list_get_instance(item, devmap_device_t, devices); 166 167 fibril_mutex_unlock(&devices_list_mutex); 168 169 return device; 170 } 171 172 /** 173 * Unregister device and free it. It's assumed that driver's device list is 174 * already locked. 175 */ 176 static int devmap_device_unregister_core(devmap_device_t *device) 177 { 316 namespace->handle = devmap_create_handle(); 317 namespace->refcnt = 0; 318 319 /* 320 * Insert new namespace into list of registered namespaces 321 */ 322 list_append(&(namespace->namespaces), &namespaces_list); 323 324 return namespace; 325 } 326 327 /** Destroy a namespace (if it is no longer needed). */ 328 static void devmap_namespace_destroy(devmap_namespace_t *namespace) 329 { 330 assert(fibril_mutex_is_locked(&devices_list_mutex)); 331 332 if (namespace->refcnt == 0) { 333 list_remove(&(namespace->namespaces)); 334 335 free(namespace->name); 336 free(namespace); 337 } 338 } 339 340 /** Increase namespace reference count by including device. */ 341 static void devmap_namespace_addref(devmap_namespace_t *namespace, 342 devmap_device_t *device) 343 { 344 assert(fibril_mutex_is_locked(&devices_list_mutex)); 345 346 device->namespace = namespace; 347 namespace->refcnt++; 348 } 349 350 /** Decrease namespace reference count. */ 351 static void devmap_namespace_delref(devmap_namespace_t *namespace) 352 { 353 assert(fibril_mutex_is_locked(&devices_list_mutex)); 354 355 namespace->refcnt--; 356 devmap_namespace_destroy(namespace); 357 } 358 359 /** Unregister device and free it. */ 360 static void devmap_device_unregister_core(devmap_device_t *device) 361 { 362 assert(fibril_mutex_is_locked(&devices_list_mutex)); 363 364 devmap_namespace_delref(device->namespace); 178 365 list_remove(&(device->devices)); 179 366 list_remove(&(device->driver_devices)); … … 181 368 free(device->name); 182 369 free(device); 183 184 return EOK;185 370 } 186 371 … … 189 374 * drivers. 190 375 */ 191 static void devmap_driver_register(devmap_driver_t **odriver) 192 { 193 *odriver = NULL; 194 376 static devmap_driver_t *devmap_driver_register(void) 377 { 195 378 ipc_call_t icall; 196 379 ipc_callid_t iid = async_get_call(&icall); 197 380 198 if (IPC_GET_ METHOD(icall) != DEVMAP_DRIVER_REGISTER) {199 ipc_answer_0(iid, EREFUSED);200 return ;201 } 202 203 devmap_driver_t *driver = (devmap_driver_t *) malloc(sizeof(devmap_driver_t));204 381 if (IPC_GET_IMETHOD(icall) != DEVMAP_DRIVER_REGISTER) { 382 async_answer_0(iid, EREFUSED); 383 return NULL; 384 } 385 386 devmap_driver_t *driver = 387 (devmap_driver_t *) malloc(sizeof(devmap_driver_t)); 205 388 if (driver == NULL) { 206 ipc_answer_0(iid, ENOMEM);207 return ;389 async_answer_0(iid, ENOMEM); 390 return NULL; 208 391 } 209 392 … … 211 394 * Get driver name 212 395 */ 213 i pc_callid_t callid;214 size_t name_size;215 if ( !ipc_data_write_receive(&callid, &name_size)) {396 int rc = async_data_write_accept((void **) &driver->name, true, 0, 397 DEVMAP_NAME_MAXLEN, 0, NULL); 398 if (rc != EOK) { 216 399 free(driver); 217 ipc_answer_0(callid, EREFUSED); 218 ipc_answer_0(iid, EREFUSED); 219 return; 220 } 221 222 if (name_size > DEVMAP_NAME_MAXLEN) { 223 free(driver); 224 ipc_answer_0(callid, EINVAL); 225 ipc_answer_0(iid, EREFUSED); 226 return; 400 async_answer_0(iid, rc); 401 return NULL; 227 402 } 228 403 229 404 /* 230 * Allocate buffer for device name. 231 */ 232 driver->name = (char *) malloc(name_size + 1); 233 if (driver->name == NULL) { 234 free(driver); 235 ipc_answer_0(callid, ENOMEM); 236 ipc_answer_0(iid, EREFUSED); 237 return; 238 } 239 240 /* 241 * Send confirmation to sender and get data into buffer. 242 */ 243 if (ipc_data_write_finalize(callid, driver->name, name_size) != EOK) { 405 * Create connection to the driver 406 */ 407 ipc_call_t call; 408 ipc_callid_t callid = async_get_call(&call); 409 410 if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) { 244 411 free(driver->name); 245 412 free(driver); 246 ipc_answer_0(iid, EREFUSED); 247 return; 248 } 249 250 driver->name[name_size] = 0; 251 252 /* Initialize mutex for list of devices owned by this driver */ 413 async_answer_0(callid, ENOTSUP); 414 async_answer_0(iid, ENOTSUP); 415 return NULL; 416 } 417 418 driver->phone = IPC_GET_ARG5(call); 419 async_answer_0(callid, EOK); 420 421 /* 422 * Initialize mutex for list of devices 423 * owned by this driver 424 */ 253 425 fibril_mutex_initialize(&driver->devices_mutex); 254 426 … … 257 429 */ 258 430 list_initialize(&driver->devices); 259 260 /* 261 * Create connection to the driver 262 */ 263 ipc_call_t call; 264 callid = async_get_call(&call); 265 266 if (IPC_GET_METHOD(call) != IPC_M_CONNECT_TO_ME) { 267 ipc_answer_0(callid, ENOTSUP); 268 269 free(driver->name); 270 free(driver); 271 ipc_answer_0(iid, ENOTSUP); 272 return; 273 } 274 275 driver->phone = IPC_GET_ARG5(call); 276 277 ipc_answer_0(callid, EOK); 278 279 list_initialize(&(driver->drivers)); 431 432 link_initialize(&driver->drivers); 280 433 281 434 fibril_mutex_lock(&drivers_list_mutex); 282 435 283 436 /* TODO: 284 * check that no driver with name equal to driver->name is registered 437 * Check that no driver with name equal to 438 * driver->name is registered 285 439 */ 286 440 … … 291 445 fibril_mutex_unlock(&drivers_list_mutex); 292 446 293 ipc_answer_0(iid, EOK);294 295 *odriver =driver;447 async_answer_0(iid, EOK); 448 449 return driver; 296 450 } 297 451 … … 309 463 310 464 if (driver->phone != 0) 311 ipc_hangup(driver->phone);465 async_hangup(driver->phone); 312 466 313 467 /* Remove it from list of drivers */ … … 328 482 fibril_mutex_unlock(&drivers_list_mutex); 329 483 330 /* free name and driver */484 /* Free name and driver */ 331 485 if (driver->name != NULL) 332 486 free(driver->name); … … 344 498 { 345 499 if (driver == NULL) { 346 ipc_answer_0(iid, EREFUSED);500 async_answer_0(iid, EREFUSED); 347 501 return; 348 502 } 349 503 350 504 /* Create new device entry */ 351 devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t)); 505 devmap_device_t *device = 506 (devmap_device_t *) malloc(sizeof(devmap_device_t)); 352 507 if (device == NULL) { 353 ipc_answer_0(iid, ENOMEM); 354 return; 355 } 356 357 /* Get device name */ 358 ipc_callid_t callid; 359 size_t size; 360 if (!ipc_data_write_receive(&callid, &size)) { 508 async_answer_0(iid, ENOMEM); 509 return; 510 } 511 512 /* Set the interface, if any. */ 513 device->forward_interface = IPC_GET_ARG1(*icall); 514 515 /* Get fqdn */ 516 char *fqdn; 517 int rc = async_data_write_accept((void **) &fqdn, true, 0, 518 DEVMAP_NAME_MAXLEN, 0, NULL); 519 if (rc != EOK) { 361 520 free(device); 362 ipc_answer_0(iid, EREFUSED); 363 return; 364 } 365 366 if (size > DEVMAP_NAME_MAXLEN) { 521 async_answer_0(iid, rc); 522 return; 523 } 524 525 char *ns_name; 526 if (!devmap_fqdn_split(fqdn, &ns_name, &device->name)) { 527 free(fqdn); 367 528 free(device); 368 ipc_answer_0(callid, EINVAL); 369 ipc_answer_0(iid, EREFUSED); 370 return; 371 } 372 373 /* +1 for terminating \0 */ 374 device->name = (char *) malloc(size + 1); 375 376 if (device->name == NULL) { 377 free(device); 378 ipc_answer_0(callid, ENOMEM); 379 ipc_answer_0(iid, EREFUSED); 380 return; 381 } 382 383 ipc_data_write_finalize(callid, device->name, size); 384 device->name[size] = 0; 385 386 list_initialize(&(device->devices)); 387 list_initialize(&(device->driver_devices)); 529 async_answer_0(iid, EINVAL); 530 return; 531 } 532 533 free(fqdn); 388 534 389 535 fibril_mutex_lock(&devices_list_mutex); 390 536 391 /* Check that device with such name is not already registered */392 if (NULL != devmap_device_find_name(device->name)) {393 printf(NAME ": Device '%s' already registered\n", device->name);537 devmap_namespace_t *namespace = devmap_namespace_create(ns_name); 538 free(ns_name); 539 if (namespace == NULL) { 394 540 fibril_mutex_unlock(&devices_list_mutex); 395 541 free(device->name); 396 542 free(device); 397 ipc_answer_0(iid, EEXISTS); 543 async_answer_0(iid, ENOMEM); 544 return; 545 } 546 547 link_initialize(&device->devices); 548 link_initialize(&device->driver_devices); 549 550 /* Check that device is not already registered */ 551 if (devmap_device_find_name(namespace->name, device->name) != NULL) { 552 printf("%s: Device '%s/%s' already registered\n", NAME, 553 device->namespace->name, device->name); 554 devmap_namespace_destroy(namespace); 555 fibril_mutex_unlock(&devices_list_mutex); 556 free(device->name); 557 free(device); 558 async_answer_0(iid, EEXISTS); 398 559 return; 399 560 } … … 401 562 /* Get unique device handle */ 402 563 device->handle = devmap_create_handle(); 403 564 565 devmap_namespace_addref(namespace, device); 404 566 device->driver = driver; 405 567 … … 416 578 fibril_mutex_unlock(&devices_list_mutex); 417 579 418 ipc_answer_1(iid, EOK, device->handle);580 async_answer_1(iid, EOK, device->handle); 419 581 } 420 582 … … 437 599 static void devmap_forward(ipc_callid_t callid, ipc_call_t *call) 438 600 { 601 fibril_mutex_lock(&devices_list_mutex); 602 439 603 /* 440 604 * Get handle from request 441 605 */ 442 dev _handle_t handle = IPC_GET_ARG2(*call);606 devmap_handle_t handle = IPC_GET_ARG2(*call); 443 607 devmap_device_t *dev = devmap_device_find_handle(handle); 444 608 445 609 if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) { 446 ipc_answer_0(callid, ENOENT); 447 return; 448 } 449 450 ipc_forward_fast(callid, dev->driver->phone, dev->handle, 451 IPC_GET_ARG3(*call), 0, IPC_FF_NONE); 610 fibril_mutex_unlock(&devices_list_mutex); 611 async_answer_0(callid, ENOENT); 612 return; 613 } 614 615 if (dev->forward_interface == 0) { 616 async_forward_fast(callid, dev->driver->phone, 617 dev->handle, 0, 0, 618 IPC_FF_NONE); 619 } else { 620 async_forward_fast(callid, dev->driver->phone, 621 dev->forward_interface, dev->handle, 0, 622 IPC_FF_NONE); 623 } 624 625 fibril_mutex_unlock(&devices_list_mutex); 452 626 } 453 627 … … 458 632 * 459 633 */ 460 static void devmap_get_handle(ipc_callid_t iid, ipc_call_t *icall) 461 { 462 /* 463 * Wait for incoming message with device name (but do not 464 * read the name itself until the buffer is allocated). 465 */ 466 ipc_callid_t callid; 467 size_t size; 468 if (!ipc_data_write_receive(&callid, &size)) { 469 ipc_answer_0(callid, EREFUSED); 470 ipc_answer_0(iid, EREFUSED); 471 return; 472 } 473 474 if ((size < 1) || (size > DEVMAP_NAME_MAXLEN)) { 475 ipc_answer_0(callid, EINVAL); 476 ipc_answer_0(iid, EREFUSED); 477 return; 478 } 479 480 /* 481 * Allocate buffer for device name. 482 */ 483 char *name = (char *) malloc(size + 1); 484 if (name == NULL) { 485 ipc_answer_0(callid, ENOMEM); 486 ipc_answer_0(iid, EREFUSED); 487 return; 488 } 489 490 /* 491 * Send confirmation to sender and get data into buffer. 492 */ 493 ipcarg_t retval = ipc_data_write_finalize(callid, name, size); 494 if (retval != EOK) { 495 ipc_answer_0(iid, EREFUSED); 496 free(name); 497 return; 498 } 499 name[size] = '\0'; 634 static void devmap_device_get_handle(ipc_callid_t iid, ipc_call_t *icall) 635 { 636 char *fqdn; 637 638 /* Get fqdn */ 639 int rc = async_data_write_accept((void **) &fqdn, true, 0, 640 DEVMAP_NAME_MAXLEN, 0, NULL); 641 if (rc != EOK) { 642 async_answer_0(iid, rc); 643 return; 644 } 645 646 char *ns_name; 647 char *name; 648 if (!devmap_fqdn_split(fqdn, &ns_name, &name)) { 649 free(fqdn); 650 async_answer_0(iid, EINVAL); 651 return; 652 } 653 654 free(fqdn); 500 655 501 656 fibril_mutex_lock(&devices_list_mutex); 502 657 const devmap_device_t *dev; 658 503 659 recheck: 504 660 505 661 /* 506 662 * Find device name in the list of known devices. 507 663 */ 508 dev = devmap_device_find_name(n ame);664 dev = devmap_device_find_name(ns_name, name); 509 665 510 666 /* … … 519 675 } 520 676 521 ipc_answer_0(iid, ENOENT); 677 async_answer_0(iid, ENOENT); 678 free(ns_name); 522 679 free(name); 523 680 fibril_mutex_unlock(&devices_list_mutex); 524 681 return; 525 682 } 683 684 async_answer_1(iid, EOK, dev->handle); 685 526 686 fibril_mutex_unlock(&devices_list_mutex); 527 528 ipc_answer_1(iid, EOK, dev->handle); 687 free(ns_name); 529 688 free(name); 530 689 } 531 690 532 /** Find name of device identified by id and send it to caller. 533 * 534 */ 535 static void devmap_get_name(ipc_callid_t iid, ipc_call_t *icall) 536 { 537 const devmap_device_t *device = devmap_device_find_handle(IPC_GET_ARG1(*icall)); 691 /** Find handle for namespace identified by name. 692 * 693 * In answer will be send EOK and device handle in arg1 or a error 694 * code from errno.h. 695 * 696 */ 697 static void devmap_namespace_get_handle(ipc_callid_t iid, ipc_call_t *icall) 698 { 699 char *name; 700 701 /* Get device name */ 702 int rc = async_data_write_accept((void **) &name, true, 0, 703 DEVMAP_NAME_MAXLEN, 0, NULL); 704 if (rc != EOK) { 705 async_answer_0(iid, rc); 706 return; 707 } 708 709 fibril_mutex_lock(&devices_list_mutex); 710 const devmap_namespace_t *namespace; 711 712 recheck: 538 713 539 714 /* 540 * Device not found. 541 */ 542 if (device == NULL) { 543 ipc_answer_0(iid, ENOENT); 544 return; 545 } 546 547 ipc_answer_0(iid, EOK); 548 549 /* FIXME: 550 * We have no channel from DEVMAP to client, therefore 551 * sending must be initiated by client. 552 * 553 * size_t name_size = str_size(device->name); 554 * 555 * int rc = ipc_data_write_send(phone, device->name, name_size); 556 * if (rc != EOK) { 557 * async_wait_for(req, NULL); 558 * return rc; 559 * } 560 */ 561 562 /* TODO: send name in response */ 563 } 564 565 static void devmap_get_count(ipc_callid_t iid, ipc_call_t *icall) 715 * Find namespace name in the list of known namespaces. 716 */ 717 namespace = devmap_namespace_find_name(name); 718 719 /* 720 * Namespace was not found. 721 */ 722 if (namespace == NULL) { 723 if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) { 724 /* Blocking lookup */ 725 fibril_condvar_wait(&devices_list_cv, 726 &devices_list_mutex); 727 goto recheck; 728 } 729 730 async_answer_0(iid, ENOENT); 731 free(name); 732 fibril_mutex_unlock(&devices_list_mutex); 733 return; 734 } 735 736 async_answer_1(iid, EOK, namespace->handle); 737 738 fibril_mutex_unlock(&devices_list_mutex); 739 free(name); 740 } 741 742 static void devmap_handle_probe(ipc_callid_t iid, ipc_call_t *icall) 566 743 { 567 744 fibril_mutex_lock(&devices_list_mutex); 568 ipc_answer_1(iid, EOK, list_count(&devices_list)); 745 746 devmap_namespace_t *namespace = 747 devmap_namespace_find_handle(IPC_GET_ARG1(*icall)); 748 if (namespace == NULL) { 749 devmap_device_t *dev = 750 devmap_device_find_handle(IPC_GET_ARG1(*icall)); 751 if (dev == NULL) 752 async_answer_1(iid, EOK, DEV_HANDLE_NONE); 753 else 754 async_answer_1(iid, EOK, DEV_HANDLE_DEVICE); 755 } else 756 async_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE); 757 569 758 fibril_mutex_unlock(&devices_list_mutex); 570 759 } 571 760 572 static void devmap_get_ devices(ipc_callid_t iid, ipc_call_t *icall)761 static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall) 573 762 { 574 763 fibril_mutex_lock(&devices_list_mutex); 575 764 async_answer_1(iid, EOK, list_count(&namespaces_list)); 765 fibril_mutex_unlock(&devices_list_mutex); 766 } 767 768 static void devmap_get_device_count(ipc_callid_t iid, ipc_call_t *icall) 769 { 770 fibril_mutex_lock(&devices_list_mutex); 771 772 devmap_namespace_t *namespace = 773 devmap_namespace_find_handle(IPC_GET_ARG1(*icall)); 774 if (namespace == NULL) 775 async_answer_0(iid, EEXISTS); 776 else 777 async_answer_1(iid, EOK, namespace->refcnt); 778 779 fibril_mutex_unlock(&devices_list_mutex); 780 } 781 782 static void devmap_get_namespaces(ipc_callid_t iid, ipc_call_t *icall) 783 { 576 784 ipc_callid_t callid; 577 785 size_t size; 578 if (! ipc_data_read_receive(&callid, &size)) {579 ipc_answer_0(callid, EREFUSED);580 ipc_answer_0(iid, EREFUSED);786 if (!async_data_read_receive(&callid, &size)) { 787 async_answer_0(callid, EREFUSED); 788 async_answer_0(iid, EREFUSED); 581 789 return; 582 790 } 583 791 584 792 if ((size % sizeof(dev_desc_t)) != 0) { 585 ipc_answer_0(callid, EINVAL); 586 ipc_answer_0(iid, EREFUSED); 587 return; 588 } 793 async_answer_0(callid, EINVAL); 794 async_answer_0(iid, EINVAL); 795 return; 796 } 797 798 fibril_mutex_lock(&devices_list_mutex); 589 799 590 800 size_t count = size / sizeof(dev_desc_t); 801 if (count != list_count(&namespaces_list)) { 802 fibril_mutex_unlock(&devices_list_mutex); 803 async_answer_0(callid, EOVERFLOW); 804 async_answer_0(iid, EOVERFLOW); 805 return; 806 } 807 591 808 dev_desc_t *desc = (dev_desc_t *) malloc(size); 592 809 if (desc == NULL) { 593 ipc_answer_0(callid, ENOMEM); 594 ipc_answer_0(iid, EREFUSED); 595 return; 596 } 597 810 fibril_mutex_unlock(&devices_list_mutex); 811 async_answer_0(callid, ENOMEM); 812 async_answer_0(iid, ENOMEM); 813 return; 814 } 815 816 link_t *item; 598 817 size_t pos = 0; 599 link_t *item = devices_list.next;600 601 while ((item != &devices_list) && (pos < count)) {602 devmap_device_t *device = list_get_instance(item, devmap_device_t, devices);818 for (item = namespaces_list.next; item != &namespaces_list; 819 item = item->next) { 820 devmap_namespace_t *namespace = 821 list_get_instance(item, devmap_namespace_t, namespaces); 603 822 604 desc[pos].handle = device->handle;605 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);823 desc[pos].handle = namespace->handle; 824 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name); 606 825 pos++; 607 item = item->next; 608 } 609 610 ipcarg_t retval = ipc_data_read_finalize(callid, desc, pos * sizeof(dev_desc_t)); 611 if (retval != EOK) { 612 ipc_answer_0(iid, EREFUSED); 613 free(desc); 614 return; 615 } 826 } 827 828 sysarg_t retval = async_data_read_finalize(callid, desc, size); 616 829 617 830 free(desc); 618 619 831 fibril_mutex_unlock(&devices_list_mutex); 620 832 621 ipc_answer_1(iid, EOK, pos); 833 async_answer_0(iid, retval); 834 } 835 836 static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall) 837 { 838 /* FIXME: Use faster algorithm which can make better use 839 of namespaces */ 840 841 ipc_callid_t callid; 842 size_t size; 843 if (!async_data_read_receive(&callid, &size)) { 844 async_answer_0(callid, EREFUSED); 845 async_answer_0(iid, EREFUSED); 846 return; 847 } 848 849 if ((size % sizeof(dev_desc_t)) != 0) { 850 async_answer_0(callid, EINVAL); 851 async_answer_0(iid, EINVAL); 852 return; 853 } 854 855 fibril_mutex_lock(&devices_list_mutex); 856 857 devmap_namespace_t *namespace = 858 devmap_namespace_find_handle(IPC_GET_ARG1(*icall)); 859 if (namespace == NULL) { 860 fibril_mutex_unlock(&devices_list_mutex); 861 async_answer_0(callid, ENOENT); 862 async_answer_0(iid, ENOENT); 863 return; 864 } 865 866 size_t count = size / sizeof(dev_desc_t); 867 if (count != namespace->refcnt) { 868 fibril_mutex_unlock(&devices_list_mutex); 869 async_answer_0(callid, EOVERFLOW); 870 async_answer_0(iid, EOVERFLOW); 871 return; 872 } 873 874 dev_desc_t *desc = (dev_desc_t *) malloc(size); 875 if (desc == NULL) { 876 fibril_mutex_unlock(&devices_list_mutex); 877 async_answer_0(callid, ENOMEM); 878 async_answer_0(iid, EREFUSED); 879 return; 880 } 881 882 link_t *item; 883 size_t pos = 0; 884 for (item = devices_list.next; item != &devices_list; item = item->next) { 885 devmap_device_t *device = 886 list_get_instance(item, devmap_device_t, devices); 887 888 if (device->namespace == namespace) { 889 desc[pos].handle = device->handle; 890 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name); 891 pos++; 892 } 893 } 894 895 sysarg_t retval = async_data_read_finalize(callid, desc, size); 896 897 free(desc); 898 fibril_mutex_unlock(&devices_list_mutex); 899 900 async_answer_0(iid, retval); 622 901 } 623 902 … … 638 917 if (!fnd) { 639 918 fibril_mutex_unlock(&null_devices_mutex); 640 ipc_answer_0(iid, ENOMEM); 641 return; 642 } 643 644 /* Create NULL device entry */ 645 devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t)); 919 async_answer_0(iid, ENOMEM); 920 return; 921 } 922 923 char null[DEVMAP_NAME_MAXLEN]; 924 snprintf(null, DEVMAP_NAME_MAXLEN, "%u", i); 925 926 char *dev_name = str_dup(null); 927 if (dev_name == NULL) { 928 fibril_mutex_unlock(&null_devices_mutex); 929 async_answer_0(iid, ENOMEM); 930 return; 931 } 932 933 devmap_device_t *device = 934 (devmap_device_t *) malloc(sizeof(devmap_device_t)); 646 935 if (device == NULL) { 647 936 fibril_mutex_unlock(&null_devices_mutex); 648 ipc_answer_0(iid, ENOMEM);649 return; 650 } 651 652 char null[DEVMAP_NAME_MAXLEN];653 snprintf(null, DEVMAP_NAME_MAXLEN, "null%u", i);654 655 device->name = str_dup(null);656 if (device->name == NULL) {937 async_answer_0(iid, ENOMEM); 938 return; 939 } 940 941 fibril_mutex_lock(&devices_list_mutex); 942 943 devmap_namespace_t *namespace = devmap_namespace_create("null"); 944 if (namespace == NULL) { 945 fibril_mutex_lock(&devices_list_mutex); 657 946 fibril_mutex_unlock(&null_devices_mutex); 658 free(device); 659 ipc_answer_0(iid, ENOMEM); 660 return; 661 } 662 663 list_initialize(&(device->devices)); 664 list_initialize(&(device->driver_devices)); 665 666 fibril_mutex_lock(&devices_list_mutex); 947 async_answer_0(iid, ENOMEM); 948 return; 949 } 950 951 link_initialize(&device->devices); 952 link_initialize(&device->driver_devices); 667 953 668 954 /* Get unique device handle */ … … 670 956 device->driver = NULL; 671 957 672 /* Insert device into list of all devices 673 and into null devices array */ 958 devmap_namespace_addref(namespace, device); 959 device->name = dev_name; 960 961 /* 962 * Insert device into list of all devices and into null devices array. 963 * Insert device into a dummy list of null driver's devices so that it 964 * can be safely removed later. 965 */ 674 966 list_append(&device->devices, &devices_list); 967 list_append(&device->driver_devices, &dummy_null_driver_devices); 675 968 null_devices[i] = device; 676 969 … … 678 971 fibril_mutex_unlock(&null_devices_mutex); 679 972 680 ipc_answer_1(iid, EOK, (ipcarg_t) i);973 async_answer_1(iid, EOK, (sysarg_t) i); 681 974 } 682 975 683 976 static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall) 684 977 { 978 sysarg_t i = IPC_GET_ARG1(*icall); 979 if (i >= NULL_DEVICES) { 980 async_answer_0(iid, ELIMIT); 981 return; 982 } 983 685 984 fibril_mutex_lock(&null_devices_mutex); 686 985 687 ipcarg_t i = IPC_GET_ARG1(*icall);688 689 986 if (null_devices[i] == NULL) { 690 ipc_answer_0(iid, ENOENT); 691 return; 692 } 693 987 fibril_mutex_unlock(&null_devices_mutex); 988 async_answer_0(iid, ENOENT); 989 return; 990 } 991 992 fibril_mutex_lock(&devices_list_mutex); 694 993 devmap_device_unregister_core(null_devices[i]); 994 fibril_mutex_unlock(&devices_list_mutex); 995 695 996 null_devices[i] = NULL; 696 997 697 998 fibril_mutex_unlock(&null_devices_mutex); 698 699 ipc_answer_0(iid, EOK); 999 async_answer_0(iid, EOK); 700 1000 } 701 1001 … … 723 1023 { 724 1024 /* Accept connection */ 725 ipc_answer_0(iid, EOK); 726 727 devmap_driver_t *driver = NULL; 728 devmap_driver_register(&driver); 729 730 if (NULL == driver) 1025 async_answer_0(iid, EOK); 1026 1027 devmap_driver_t *driver = devmap_driver_register(); 1028 if (driver == NULL) 731 1029 return; 732 1030 … … 736 1034 ipc_callid_t callid = async_get_call(&call); 737 1035 738 switch (IPC_GET_ METHOD(call)) {1036 switch (IPC_GET_IMETHOD(call)) { 739 1037 case IPC_M_PHONE_HUNGUP: 740 1038 cont = false; … … 742 1040 case DEVMAP_DRIVER_UNREGISTER: 743 1041 if (NULL == driver) 744 ipc_answer_0(callid, ENOENT);1042 async_answer_0(callid, ENOENT); 745 1043 else 746 ipc_answer_0(callid, EOK);1044 async_answer_0(callid, EOK); 747 1045 break; 748 1046 case DEVMAP_DEVICE_REGISTER: … … 755 1053 break; 756 1054 case DEVMAP_DEVICE_GET_HANDLE: 757 devmap_ get_handle(callid, &call);758 break; 759 case DEVMAP_ DEVICE_GET_NAME:760 devmap_ get_name(callid, &call);1055 devmap_device_get_handle(callid, &call); 1056 break; 1057 case DEVMAP_NAMESPACE_GET_HANDLE: 1058 devmap_namespace_get_handle(callid, &call); 761 1059 break; 762 1060 default: 763 if (!(callid & IPC_CALLID_NOTIFICATION)) 764 ipc_answer_0(callid, ENOENT); 1061 async_answer_0(callid, ENOENT); 765 1062 } 766 1063 } … … 781 1078 { 782 1079 /* Accept connection */ 783 ipc_answer_0(iid, EOK);1080 async_answer_0(iid, EOK); 784 1081 785 1082 bool cont = true; … … 788 1085 ipc_callid_t callid = async_get_call(&call); 789 1086 790 switch (IPC_GET_ METHOD(call)) {1087 switch (IPC_GET_IMETHOD(call)) { 791 1088 case IPC_M_PHONE_HUNGUP: 792 1089 cont = false; 793 1090 continue; 794 1091 case DEVMAP_DEVICE_GET_HANDLE: 795 devmap_get_handle(callid, &call); 796 break; 797 case DEVMAP_DEVICE_GET_NAME: 798 devmap_get_name(callid, &call); 799 break; 800 case DEVMAP_DEVICE_NULL_CREATE: 1092 devmap_device_get_handle(callid, &call); 1093 break; 1094 case DEVMAP_NAMESPACE_GET_HANDLE: 1095 devmap_namespace_get_handle(callid, &call); 1096 break; 1097 case DEVMAP_HANDLE_PROBE: 1098 devmap_handle_probe(callid, &call); 1099 break; 1100 case DEVMAP_NULL_CREATE: 801 1101 devmap_null_create(callid, &call); 802 1102 break; 803 case DEVMAP_ DEVICE_NULL_DESTROY:1103 case DEVMAP_NULL_DESTROY: 804 1104 devmap_null_destroy(callid, &call); 805 1105 break; 806 case DEVMAP_DEVICE_GET_COUNT: 807 devmap_get_count(callid, &call); 808 break; 809 case DEVMAP_DEVICE_GET_DEVICES: 1106 case DEVMAP_GET_NAMESPACE_COUNT: 1107 devmap_get_namespace_count(callid, &call); 1108 break; 1109 case DEVMAP_GET_DEVICE_COUNT: 1110 devmap_get_device_count(callid, &call); 1111 break; 1112 case DEVMAP_GET_NAMESPACES: 1113 devmap_get_namespaces(callid, &call); 1114 break; 1115 case DEVMAP_GET_DEVICES: 810 1116 devmap_get_devices(callid, &call); 811 1117 break; 812 1118 default: 813 if (!(callid & IPC_CALLID_NOTIFICATION)) 814 ipc_answer_0(callid, ENOENT); 1119 async_answer_0(callid, ENOENT); 815 1120 } 816 1121 } … … 823 1128 { 824 1129 /* Select interface */ 825 switch (( ipcarg_t) (IPC_GET_ARG1(*icall))) {1130 switch ((sysarg_t) (IPC_GET_ARG1(*icall))) { 826 1131 case DEVMAP_DRIVER: 827 1132 devmap_connection_driver(iid, icall); … … 836 1141 default: 837 1142 /* No such interface */ 838 ipc_answer_0(iid, ENOENT);1143 async_answer_0(iid, ENOENT); 839 1144 } 840 1145 } … … 845 1150 int main(int argc, char *argv[]) 846 1151 { 847 printf( NAME ": HelenOS Device Mapper\n");1152 printf("%s: HelenOS Device Mapper\n", NAME); 848 1153 849 1154 if (!devmap_init()) { 850 printf( NAME ": Error while initializing service\n");1155 printf("%s: Error while initializing service\n", NAME); 851 1156 return -1; 852 1157 } … … 856 1161 857 1162 /* Register device mapper at naming service */ 858 ipcarg_t phonead; 859 if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0) 1163 if (service_register(SERVICE_DEVMAP) != EOK) 860 1164 return -1; 861 1165 862 printf( NAME ": Accepting connections\n");1166 printf("%s: Accepting connections\n", NAME); 863 1167 async_manager(); 864 1168 … … 867 1171 } 868 1172 869 /** 1173 /** 870 1174 * @} 871 1175 */
Note:
See TracChangeset
for help on using the changeset viewer.