Changes in uspace/srv/devmap/devmap.c [63e0bdd:a405563] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/devmap/devmap.c
r63e0bdd ra405563 42 42 #include <errno.h> 43 43 #include <bool.h> 44 #include <fibril_sync h.h>44 #include <fibril_sync.h> 45 45 #include <stdlib.h> 46 #include <str .h>46 #include <string.h> 47 47 #include <ipc/devmap.h> 48 #include <assert.h>49 48 50 49 #define NAME "devmap" … … 62 61 link_t devices; 63 62 /** Phone asociated with this driver */ 64 sysarg_t phone;63 ipcarg_t phone; 65 64 /** Device driver name */ 66 65 char *name; … … 68 67 fibril_mutex_t devices_mutex; 69 68 } devmap_driver_t; 70 71 /** Info about registered namespaces72 *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;84 69 85 70 /** Info about registered device … … 92 77 owned by one driver */ 93 78 link_t driver_devices; 94 /** Unique device identifier */ 95 devmap_handle_t handle; 96 /** Device namespace */ 97 devmap_namespace_t *namespace; 79 /** Unique device identifier */ 80 dev_handle_t handle; 98 81 /** Device name */ 99 82 char *name; 100 83 /** Device driver handling this device */ 101 84 devmap_driver_t *driver; 102 /** Use this interface when forwarding to driver. */103 sysarg_t forward_interface;104 85 } devmap_device_t; 105 86 106 87 LIST_INITIALIZE(devices_list); 107 LIST_INITIALIZE(namespaces_list);108 88 LIST_INITIALIZE(drivers_list); 109 89 … … 121 101 static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex); 122 102 123 static dev map_handle_t last_handle = 0;103 static dev_handle_t last_handle = 0; 124 104 static devmap_device_t *null_devices[NULL_DEVICES]; 125 105 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) 106 static dev_handle_t devmap_create_handle(void) 133 107 { 134 108 /* TODO: allow reusing old handles after their unregistration … … 143 117 } 144 118 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. 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) 135 return NULL; 136 137 device = list_get_instance(item, devmap_device_t, devices); 138 return device; 139 } 140 141 /** Find device with given handle. 235 142 * 236 143 * @todo: use hash table 237 144 * 238 145 */ 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); 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); 288 155 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) 156 break; 157 item = item->next; 158 } 159 160 if (item == &devices_list) { 161 fibril_mutex_unlock(&devices_list_mutex); 308 162 return NULL; 309 310 namespace->name = str_dup(ns_name); 311 if (namespace->name == NULL) { 312 free(namespace); 313 return NULL; 314 } 315 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); 163 } 164 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 { 365 178 list_remove(&(device->devices)); 366 179 list_remove(&(device->driver_devices)); … … 368 181 free(device->name); 369 182 free(device); 183 184 return EOK; 370 185 } 371 186 … … 374 189 * drivers. 375 190 */ 376 static devmap_driver_t *devmap_driver_register(void) 377 { 191 static void devmap_driver_register(devmap_driver_t **odriver) 192 { 193 *odriver = NULL; 194 378 195 ipc_call_t icall; 379 196 ipc_callid_t iid = async_get_call(&icall); 380 197 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));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 388 205 if (driver == NULL) { 389 async_answer_0(iid, ENOMEM);390 return NULL;206 ipc_answer_0(iid, ENOMEM); 207 return; 391 208 } 392 209 … … 394 211 * Get driver name 395 212 */ 396 i nt rc = async_data_write_accept((void **) &driver->name, true, 0,397 DEVMAP_NAME_MAXLEN, 0, NULL);398 if ( rc != EOK) {213 ipc_callid_t callid; 214 size_t name_size; 215 if (!ipc_data_write_receive(&callid, &name_size)) { 399 216 free(driver); 400 async_answer_0(iid, rc); 401 return NULL; 402 } 403 404 /* 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) { 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; 227 } 228 229 /* 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) { 411 244 free(driver->name); 412 245 free(driver); 413 async_answer_0(callid, ENOTSUP); 414 async_answer_0(iid, ENOTSUP); 415 return NULL; 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 */ 253 fibril_mutex_initialize(&driver->devices_mutex); 254 255 /* 256 * Initialize list of asociated devices 257 */ 258 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; 416 273 } 417 274 418 275 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 */ 425 fibril_mutex_initialize(&driver->devices_mutex); 426 427 /* 428 * Initialize list of asociated devices 429 */ 430 list_initialize(&driver->devices); 431 432 link_initialize(&driver->drivers); 276 277 ipc_answer_0(callid, EOK); 278 279 list_initialize(&(driver->drivers)); 433 280 434 281 fibril_mutex_lock(&drivers_list_mutex); 435 282 436 283 /* TODO: 437 * Check that no driver with name equal to 438 * driver->name is registered 284 * check that no driver with name equal to driver->name is registered 439 285 */ 440 286 … … 445 291 fibril_mutex_unlock(&drivers_list_mutex); 446 292 447 async_answer_0(iid, EOK);448 449 returndriver;293 ipc_answer_0(iid, EOK); 294 295 *odriver = driver; 450 296 } 451 297 … … 463 309 464 310 if (driver->phone != 0) 465 async_hangup(driver->phone);311 ipc_hangup(driver->phone); 466 312 467 313 /* Remove it from list of drivers */ … … 482 328 fibril_mutex_unlock(&drivers_list_mutex); 483 329 484 /* Free name and driver */330 /* free name and driver */ 485 331 if (driver->name != NULL) 486 332 free(driver->name); … … 498 344 { 499 345 if (driver == NULL) { 500 async_answer_0(iid, EREFUSED);346 ipc_answer_0(iid, EREFUSED); 501 347 return; 502 348 } 503 349 504 350 /* Create new device entry */ 505 devmap_device_t *device = 506 (devmap_device_t *) malloc(sizeof(devmap_device_t)); 351 devmap_device_t *device = (devmap_device_t *) malloc(sizeof(devmap_device_t)); 507 352 if (device == NULL) { 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) { 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)) { 520 361 free(device); 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); 362 ipc_answer_0(iid, EREFUSED); 363 return; 364 } 365 366 if (size > DEVMAP_NAME_MAXLEN) { 528 367 free(device); 529 async_answer_0(iid, EINVAL); 530 return; 531 } 532 533 free(fqdn); 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)); 534 388 535 389 fibril_mutex_lock(&devices_list_mutex); 536 390 537 devmap_namespace_t *namespace = devmap_namespace_create(ns_name);538 free(ns_name);539 if (namespace == NULL) {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); 540 394 fibril_mutex_unlock(&devices_list_mutex); 541 395 free(device->name); 542 396 free(device); 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); 397 ipc_answer_0(iid, EEXISTS); 559 398 return; 560 399 } … … 562 401 /* Get unique device handle */ 563 402 device->handle = devmap_create_handle(); 564 565 devmap_namespace_addref(namespace, device); 403 566 404 device->driver = driver; 567 405 … … 578 416 fibril_mutex_unlock(&devices_list_mutex); 579 417 580 async_answer_1(iid, EOK, device->handle);418 ipc_answer_1(iid, EOK, device->handle); 581 419 } 582 420 … … 599 437 static void devmap_forward(ipc_callid_t callid, ipc_call_t *call) 600 438 { 601 fibril_mutex_lock(&devices_list_mutex);602 603 439 /* 604 440 * Get handle from request 605 441 */ 606 dev map_handle_t handle = IPC_GET_ARG2(*call);442 dev_handle_t handle = IPC_GET_ARG2(*call); 607 443 devmap_device_t *dev = devmap_device_find_handle(handle); 608 444 609 445 if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) { 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); 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); 626 452 } 627 453 … … 632 458 * 633 459 */ 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); 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'; 655 500 656 501 fibril_mutex_lock(&devices_list_mutex); 657 502 const devmap_device_t *dev; 658 659 503 recheck: 660 504 661 505 /* 662 506 * Find device name in the list of known devices. 663 507 */ 664 dev = devmap_device_find_name(n s_name, name);508 dev = devmap_device_find_name(name); 665 509 666 510 /* … … 675 519 } 676 520 677 async_answer_0(iid, ENOENT); 678 free(ns_name); 521 ipc_answer_0(iid, ENOENT); 679 522 free(name); 680 523 fibril_mutex_unlock(&devices_list_mutex); 681 524 return; 682 525 } 683 684 async_answer_1(iid, EOK, dev->handle);685 686 526 fibril_mutex_unlock(&devices_list_mutex); 687 free(ns_name); 527 528 ipc_answer_1(iid, EOK, dev->handle); 688 529 free(name); 689 530 } 690 531 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 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)); 538 539 /* 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) 566 { 709 567 fibril_mutex_lock(&devices_list_mutex); 710 const devmap_namespace_t *namespace; 711 712 recheck: 713 714 /* 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 568 ipc_answer_1(iid, EOK, list_count(&devices_list)); 738 569 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) 570 } 571 572 static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall) 743 573 { 744 574 fibril_mutex_lock(&devices_list_mutex); 745 575 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 else754 async_answer_1(iid, EOK, DEV_HANDLE_DEVICE);755 } else756 async_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);757 758 fibril_mutex_unlock(&devices_list_mutex);759 }760 761 static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)762 {763 fibril_mutex_lock(&devices_list_mutex);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 else777 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 {784 576 ipc_callid_t callid; 785 577 size_t size; 786 if (! async_data_read_receive(&callid, &size)) {787 async_answer_0(callid, EREFUSED);788 async_answer_0(iid, EREFUSED);578 if (!ipc_data_read_receive(&callid, &size)) { 579 ipc_answer_0(callid, EREFUSED); 580 ipc_answer_0(iid, EREFUSED); 789 581 return; 790 582 } 791 583 792 584 if ((size % sizeof(dev_desc_t)) != 0) { 793 async_answer_0(callid, EINVAL); 794 async_answer_0(iid, EINVAL); 795 return; 796 } 797 798 fibril_mutex_lock(&devices_list_mutex); 585 ipc_answer_0(callid, EINVAL); 586 ipc_answer_0(iid, EREFUSED); 587 return; 588 } 799 589 800 590 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 808 591 dev_desc_t *desc = (dev_desc_t *) malloc(size); 809 592 if (desc == NULL) { 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; 593 ipc_answer_0(callid, ENOMEM); 594 ipc_answer_0(iid, EREFUSED); 595 return; 596 } 597 817 598 size_t pos = 0; 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);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); 822 603 823 desc[pos].handle = namespace->handle;824 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name);604 desc[pos].handle = device->handle; 605 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name); 825 606 pos++; 826 } 827 828 sysarg_t retval = async_data_read_finalize(callid, desc, size); 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 } 829 616 830 617 free(desc); 618 831 619 fibril_mutex_unlock(&devices_list_mutex); 832 620 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); 621 ipc_answer_1(iid, EOK, pos); 901 622 } 902 623 … … 917 638 if (!fnd) { 918 639 fibril_mutex_unlock(&null_devices_mutex); 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)); 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)); 935 646 if (device == NULL) { 936 647 fibril_mutex_unlock(&null_devices_mutex); 937 async_answer_0(iid, ENOMEM); 938 return; 939 } 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) { 657 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)); 940 665 941 666 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);946 fibril_mutex_unlock(&null_devices_mutex);947 async_answer_0(iid, ENOMEM);948 return;949 }950 951 link_initialize(&device->devices);952 link_initialize(&device->driver_devices);953 667 954 668 /* Get unique device handle */ … … 956 670 device->driver = NULL; 957 671 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 */ 672 /* Insert device into list of all devices 673 and into null devices array */ 966 674 list_append(&device->devices, &devices_list); 967 list_append(&device->driver_devices, &dummy_null_driver_devices);968 675 null_devices[i] = device; 969 676 … … 971 678 fibril_mutex_unlock(&null_devices_mutex); 972 679 973 async_answer_1(iid, EOK, (sysarg_t) i);680 ipc_answer_1(iid, EOK, (ipcarg_t) i); 974 681 } 975 682 976 683 static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall) 977 684 { 978 sysarg_t i = IPC_GET_ARG1(*icall);979 if (i >= NULL_DEVICES) {980 async_answer_0(iid, ELIMIT);981 return;982 }983 984 685 fibril_mutex_lock(&null_devices_mutex); 985 686 687 ipcarg_t i = IPC_GET_ARG1(*icall); 688 986 689 if (null_devices[i] == NULL) { 987 fibril_mutex_unlock(&null_devices_mutex); 988 async_answer_0(iid, ENOENT); 989 return; 990 } 991 992 fibril_mutex_lock(&devices_list_mutex); 690 ipc_answer_0(iid, ENOENT); 691 return; 692 } 693 993 694 devmap_device_unregister_core(null_devices[i]); 994 fibril_mutex_unlock(&devices_list_mutex);995 996 695 null_devices[i] = NULL; 997 696 998 697 fibril_mutex_unlock(&null_devices_mutex); 999 async_answer_0(iid, EOK); 698 699 ipc_answer_0(iid, EOK); 1000 700 } 1001 701 … … 1023 723 { 1024 724 /* Accept connection */ 1025 async_answer_0(iid, EOK); 1026 1027 devmap_driver_t *driver = devmap_driver_register(); 1028 if (driver == NULL) 725 ipc_answer_0(iid, EOK); 726 727 devmap_driver_t *driver = NULL; 728 devmap_driver_register(&driver); 729 730 if (NULL == driver) 1029 731 return; 1030 732 … … 1034 736 ipc_callid_t callid = async_get_call(&call); 1035 737 1036 switch (IPC_GET_ IMETHOD(call)) {738 switch (IPC_GET_METHOD(call)) { 1037 739 case IPC_M_PHONE_HUNGUP: 1038 740 cont = false; … … 1040 742 case DEVMAP_DRIVER_UNREGISTER: 1041 743 if (NULL == driver) 1042 async_answer_0(callid, ENOENT);744 ipc_answer_0(callid, ENOENT); 1043 745 else 1044 async_answer_0(callid, EOK);746 ipc_answer_0(callid, EOK); 1045 747 break; 1046 748 case DEVMAP_DEVICE_REGISTER: … … 1053 755 break; 1054 756 case DEVMAP_DEVICE_GET_HANDLE: 1055 devmap_ device_get_handle(callid, &call);1056 break; 1057 case DEVMAP_ NAMESPACE_GET_HANDLE:1058 devmap_ namespace_get_handle(callid, &call);757 devmap_get_handle(callid, &call); 758 break; 759 case DEVMAP_DEVICE_GET_NAME: 760 devmap_get_name(callid, &call); 1059 761 break; 1060 762 default: 1061 async_answer_0(callid, ENOENT); 763 if (!(callid & IPC_CALLID_NOTIFICATION)) 764 ipc_answer_0(callid, ENOENT); 1062 765 } 1063 766 } … … 1078 781 { 1079 782 /* Accept connection */ 1080 async_answer_0(iid, EOK);783 ipc_answer_0(iid, EOK); 1081 784 1082 785 bool cont = true; … … 1085 788 ipc_callid_t callid = async_get_call(&call); 1086 789 1087 switch (IPC_GET_ IMETHOD(call)) {790 switch (IPC_GET_METHOD(call)) { 1088 791 case IPC_M_PHONE_HUNGUP: 1089 792 cont = false; 1090 793 continue; 1091 794 case DEVMAP_DEVICE_GET_HANDLE: 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: 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: 1101 801 devmap_null_create(callid, &call); 1102 802 break; 1103 case DEVMAP_ NULL_DESTROY:803 case DEVMAP_DEVICE_NULL_DESTROY: 1104 804 devmap_null_destroy(callid, &call); 1105 805 break; 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: 806 case DEVMAP_DEVICE_GET_COUNT: 807 devmap_get_count(callid, &call); 808 break; 809 case DEVMAP_DEVICE_GET_DEVICES: 1116 810 devmap_get_devices(callid, &call); 1117 811 break; 1118 812 default: 1119 async_answer_0(callid, ENOENT); 813 if (!(callid & IPC_CALLID_NOTIFICATION)) 814 ipc_answer_0(callid, ENOENT); 1120 815 } 1121 816 } … … 1128 823 { 1129 824 /* Select interface */ 1130 switch (( sysarg_t) (IPC_GET_ARG1(*icall))) {825 switch ((ipcarg_t) (IPC_GET_ARG1(*icall))) { 1131 826 case DEVMAP_DRIVER: 1132 827 devmap_connection_driver(iid, icall); … … 1141 836 default: 1142 837 /* No such interface */ 1143 async_answer_0(iid, ENOENT);838 ipc_answer_0(iid, ENOENT); 1144 839 } 1145 840 } … … 1150 845 int main(int argc, char *argv[]) 1151 846 { 1152 printf( "%s: HelenOS Device Mapper\n", NAME);847 printf(NAME ": HelenOS Device Mapper\n"); 1153 848 1154 849 if (!devmap_init()) { 1155 printf( "%s: Error while initializing service\n", NAME);850 printf(NAME ": Error while initializing service\n"); 1156 851 return -1; 1157 852 } … … 1161 856 1162 857 /* Register device mapper at naming service */ 1163 if (service_register(SERVICE_DEVMAP) != EOK) 858 ipcarg_t phonead; 859 if (ipc_connect_to_me(PHONE_NS, SERVICE_DEVMAP, 0, 0, &phonead) != 0) 1164 860 return -1; 1165 861 1166 printf( "%s: Accepting connections\n", NAME);862 printf(NAME ": Accepting connections\n"); 1167 863 async_manager(); 1168 864 … … 1171 867 } 1172 868 1173 /** 869 /** 1174 870 * @} 1175 871 */
Note:
See TracChangeset
for help on using the changeset viewer.