00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00038 #include <ipc/services.h>
00039 #include <ipc/ns.h>
00040 #include <async.h>
00041 #include <stdio.h>
00042 #include <errno.h>
00043 #include <bool.h>
00044 #include <fibril_synch.h>
00045 #include <stdlib.h>
00046 #include <str.h>
00047 #include <ipc/devmap.h>
00048 #include <assert.h>
00049
00050 #define NAME "devmap"
00051 #define NULL_DEVICES 256
00052
00058 typedef struct {
00060 link_t drivers;
00062 link_t devices;
00064 sysarg_t phone;
00066 char *name;
00068 fibril_mutex_t devices_mutex;
00069 } devmap_driver_t;
00070
00074 typedef struct {
00076 link_t namespaces;
00078 devmap_handle_t handle;
00080 char *name;
00082 size_t refcnt;
00083 } devmap_namespace_t;
00084
00088 typedef struct {
00090 link_t devices;
00093 link_t driver_devices;
00095 devmap_handle_t handle;
00097 devmap_namespace_t *namespace;
00099 char *name;
00101 devmap_driver_t *driver;
00103 sysarg_t forward_interface;
00104 } devmap_device_t;
00105
00106 LIST_INITIALIZE(devices_list);
00107 LIST_INITIALIZE(namespaces_list);
00108 LIST_INITIALIZE(drivers_list);
00109
00110
00111
00112
00113
00114
00115
00116
00117 static FIBRIL_MUTEX_INITIALIZE(devices_list_mutex);
00118 static FIBRIL_CONDVAR_INITIALIZE(devices_list_cv);
00119 static FIBRIL_MUTEX_INITIALIZE(drivers_list_mutex);
00120 static FIBRIL_MUTEX_INITIALIZE(create_handle_mutex);
00121 static FIBRIL_MUTEX_INITIALIZE(null_devices_mutex);
00122
00123 static devmap_handle_t last_handle = 0;
00124 static devmap_device_t *null_devices[NULL_DEVICES];
00125
00126
00127
00128
00129
00130 static LIST_INITIALIZE(dummy_null_driver_devices);
00131
00132 static devmap_handle_t devmap_create_handle(void)
00133 {
00134
00135
00136
00137
00138 fibril_mutex_lock(&create_handle_mutex);
00139 last_handle++;
00140 fibril_mutex_unlock(&create_handle_mutex);
00141
00142 return last_handle;
00143 }
00144
00153 static bool devmap_fqdn_split(const char *fqdn, char **ns_name, char **name)
00154 {
00155 size_t cnt = 0;
00156 size_t slash_offset = 0;
00157 size_t slash_after = 0;
00158
00159 size_t offset = 0;
00160 size_t offset_prev = 0;
00161 wchar_t c;
00162
00163 while ((c = str_decode(fqdn, &offset, STR_NO_LIMIT)) != 0) {
00164 if (c == '/') {
00165 cnt++;
00166 slash_offset = offset_prev;
00167 slash_after = offset;
00168 }
00169 offset_prev = offset;
00170 }
00171
00172
00173 if (cnt > 1)
00174 return false;
00175
00176
00177 if (cnt == 0) {
00178 *ns_name = str_dup("");
00179 if (*ns_name == NULL)
00180 return false;
00181
00182 *name = str_dup(fqdn);
00183 if (*name == NULL) {
00184 free(*ns_name);
00185 return false;
00186 }
00187
00188 if (str_cmp(*name, "") == 0) {
00189 free(*name);
00190 free(*ns_name);
00191 return false;
00192 }
00193
00194 return true;
00195 }
00196
00197
00198 *ns_name = str_ndup(fqdn, slash_offset);
00199 if (*ns_name == NULL)
00200 return false;
00201
00202 *name = str_dup(fqdn + slash_after);
00203 if (*name == NULL) {
00204 free(*ns_name);
00205 return false;
00206 }
00207
00208 if (str_cmp(*name, "") == 0) {
00209 free(*name);
00210 free(*ns_name);
00211 return false;
00212 }
00213
00214 return true;
00215 }
00216
00218 static devmap_namespace_t *devmap_namespace_find_name(const char *name)
00219 {
00220 link_t *item;
00221
00222 assert(fibril_mutex_is_locked(&devices_list_mutex));
00223
00224 for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
00225 devmap_namespace_t *namespace =
00226 list_get_instance(item, devmap_namespace_t, namespaces);
00227 if (str_cmp(namespace->name, name) == 0)
00228 return namespace;
00229 }
00230
00231 return NULL;
00232 }
00233
00239 static devmap_namespace_t *devmap_namespace_find_handle(devmap_handle_t handle)
00240 {
00241 link_t *item;
00242
00243 assert(fibril_mutex_is_locked(&devices_list_mutex));
00244
00245 for (item = namespaces_list.next; item != &namespaces_list; item = item->next) {
00246 devmap_namespace_t *namespace =
00247 list_get_instance(item, devmap_namespace_t, namespaces);
00248 if (namespace->handle == handle)
00249 return namespace;
00250 }
00251
00252 return NULL;
00253 }
00254
00256 static devmap_device_t *devmap_device_find_name(const char *ns_name,
00257 const char *name)
00258 {
00259 link_t *item;
00260
00261 assert(fibril_mutex_is_locked(&devices_list_mutex));
00262
00263 for (item = devices_list.next; item != &devices_list; item = item->next) {
00264 devmap_device_t *device =
00265 list_get_instance(item, devmap_device_t, devices);
00266 if ((str_cmp(device->namespace->name, ns_name) == 0)
00267 && (str_cmp(device->name, name) == 0))
00268 return device;
00269 }
00270
00271 return NULL;
00272 }
00273
00279 static devmap_device_t *devmap_device_find_handle(devmap_handle_t handle)
00280 {
00281 link_t *item;
00282
00283 assert(fibril_mutex_is_locked(&devices_list_mutex));
00284
00285 for (item = devices_list.next; item != &devices_list; item = item->next) {
00286 devmap_device_t *device =
00287 list_get_instance(item, devmap_device_t, devices);
00288 if (device->handle == handle)
00289 return device;
00290 }
00291
00292 return NULL;
00293 }
00294
00296 static devmap_namespace_t *devmap_namespace_create(const char *ns_name)
00297 {
00298 devmap_namespace_t *namespace;
00299
00300 assert(fibril_mutex_is_locked(&devices_list_mutex));
00301
00302 namespace = devmap_namespace_find_name(ns_name);
00303 if (namespace != NULL)
00304 return namespace;
00305
00306 namespace = (devmap_namespace_t *) malloc(sizeof(devmap_namespace_t));
00307 if (namespace == NULL)
00308 return NULL;
00309
00310 namespace->name = str_dup(ns_name);
00311 if (namespace->name == NULL) {
00312 free(namespace);
00313 return NULL;
00314 }
00315
00316 namespace->handle = devmap_create_handle();
00317 namespace->refcnt = 0;
00318
00319
00320
00321
00322 list_append(&(namespace->namespaces), &namespaces_list);
00323
00324 return namespace;
00325 }
00326
00328 static void devmap_namespace_destroy(devmap_namespace_t *namespace)
00329 {
00330 assert(fibril_mutex_is_locked(&devices_list_mutex));
00331
00332 if (namespace->refcnt == 0) {
00333 list_remove(&(namespace->namespaces));
00334
00335 free(namespace->name);
00336 free(namespace);
00337 }
00338 }
00339
00341 static void devmap_namespace_addref(devmap_namespace_t *namespace,
00342 devmap_device_t *device)
00343 {
00344 assert(fibril_mutex_is_locked(&devices_list_mutex));
00345
00346 device->namespace = namespace;
00347 namespace->refcnt++;
00348 }
00349
00351 static void devmap_namespace_delref(devmap_namespace_t *namespace)
00352 {
00353 assert(fibril_mutex_is_locked(&devices_list_mutex));
00354
00355 namespace->refcnt--;
00356 devmap_namespace_destroy(namespace);
00357 }
00358
00360 static void devmap_device_unregister_core(devmap_device_t *device)
00361 {
00362 assert(fibril_mutex_is_locked(&devices_list_mutex));
00363
00364 devmap_namespace_delref(device->namespace);
00365 list_remove(&(device->devices));
00366 list_remove(&(device->driver_devices));
00367
00368 free(device->name);
00369 free(device);
00370 }
00371
00376 static devmap_driver_t *devmap_driver_register(void)
00377 {
00378 ipc_call_t icall;
00379 ipc_callid_t iid = async_get_call(&icall);
00380
00381 if (IPC_GET_IMETHOD(icall) != DEVMAP_DRIVER_REGISTER) {
00382 async_answer_0(iid, EREFUSED);
00383 return NULL;
00384 }
00385
00386 devmap_driver_t *driver =
00387 (devmap_driver_t *) malloc(sizeof(devmap_driver_t));
00388 if (driver == NULL) {
00389 async_answer_0(iid, ENOMEM);
00390 return NULL;
00391 }
00392
00393
00394
00395
00396 int rc = async_data_write_accept((void **) &driver->name, true, 0,
00397 DEVMAP_NAME_MAXLEN, 0, NULL);
00398 if (rc != EOK) {
00399 free(driver);
00400 async_answer_0(iid, rc);
00401 return NULL;
00402 }
00403
00404
00405
00406
00407 ipc_call_t call;
00408 ipc_callid_t callid = async_get_call(&call);
00409
00410 if (IPC_GET_IMETHOD(call) != IPC_M_CONNECT_TO_ME) {
00411 free(driver->name);
00412 free(driver);
00413 async_answer_0(callid, ENOTSUP);
00414 async_answer_0(iid, ENOTSUP);
00415 return NULL;
00416 }
00417
00418 driver->phone = IPC_GET_ARG5(call);
00419 async_answer_0(callid, EOK);
00420
00421
00422
00423
00424
00425 fibril_mutex_initialize(&driver->devices_mutex);
00426
00427
00428
00429
00430 list_initialize(&driver->devices);
00431
00432 link_initialize(&driver->drivers);
00433
00434 fibril_mutex_lock(&drivers_list_mutex);
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444 list_append(&(driver->drivers), &drivers_list);
00445 fibril_mutex_unlock(&drivers_list_mutex);
00446
00447 async_answer_0(iid, EOK);
00448
00449 return driver;
00450 }
00451
00457 static int devmap_driver_unregister(devmap_driver_t *driver)
00458 {
00459 if (driver == NULL)
00460 return EEXISTS;
00461
00462 fibril_mutex_lock(&drivers_list_mutex);
00463
00464 if (driver->phone != 0)
00465 async_hangup(driver->phone);
00466
00467
00468 list_remove(&(driver->drivers));
00469
00470
00471 fibril_mutex_lock(&devices_list_mutex);
00472 fibril_mutex_lock(&driver->devices_mutex);
00473
00474 while (!list_empty(&(driver->devices))) {
00475 devmap_device_t *device = list_get_instance(driver->devices.next,
00476 devmap_device_t, driver_devices);
00477 devmap_device_unregister_core(device);
00478 }
00479
00480 fibril_mutex_unlock(&driver->devices_mutex);
00481 fibril_mutex_unlock(&devices_list_mutex);
00482 fibril_mutex_unlock(&drivers_list_mutex);
00483
00484
00485 if (driver->name != NULL)
00486 free(driver->name);
00487
00488 free(driver);
00489
00490 return EOK;
00491 }
00492
00496 static void devmap_device_register(ipc_callid_t iid, ipc_call_t *icall,
00497 devmap_driver_t *driver)
00498 {
00499 if (driver == NULL) {
00500 async_answer_0(iid, EREFUSED);
00501 return;
00502 }
00503
00504
00505 devmap_device_t *device =
00506 (devmap_device_t *) malloc(sizeof(devmap_device_t));
00507 if (device == NULL) {
00508 async_answer_0(iid, ENOMEM);
00509 return;
00510 }
00511
00512
00513 device->forward_interface = IPC_GET_ARG1(*icall);
00514
00515
00516 char *fqdn;
00517 int rc = async_data_write_accept((void **) &fqdn, true, 0,
00518 DEVMAP_NAME_MAXLEN, 0, NULL);
00519 if (rc != EOK) {
00520 free(device);
00521 async_answer_0(iid, rc);
00522 return;
00523 }
00524
00525 char *ns_name;
00526 if (!devmap_fqdn_split(fqdn, &ns_name, &device->name)) {
00527 free(fqdn);
00528 free(device);
00529 async_answer_0(iid, EINVAL);
00530 return;
00531 }
00532
00533 free(fqdn);
00534
00535 fibril_mutex_lock(&devices_list_mutex);
00536
00537 devmap_namespace_t *namespace = devmap_namespace_create(ns_name);
00538 free(ns_name);
00539 if (namespace == NULL) {
00540 fibril_mutex_unlock(&devices_list_mutex);
00541 free(device->name);
00542 free(device);
00543 async_answer_0(iid, ENOMEM);
00544 return;
00545 }
00546
00547 link_initialize(&device->devices);
00548 link_initialize(&device->driver_devices);
00549
00550
00551 if (devmap_device_find_name(namespace->name, device->name) != NULL) {
00552 printf("%s: Device '%s/%s' already registered\n", NAME,
00553 namespace->name, device->name);
00554 devmap_namespace_destroy(namespace);
00555 fibril_mutex_unlock(&devices_list_mutex);
00556 free(device->name);
00557 free(device);
00558 async_answer_0(iid, EEXISTS);
00559 return;
00560 }
00561
00562
00563 device->handle = devmap_create_handle();
00564
00565 devmap_namespace_addref(namespace, device);
00566 device->driver = driver;
00567
00568
00569 list_append(&device->devices, &devices_list);
00570
00571
00572 fibril_mutex_lock(&device->driver->devices_mutex);
00573
00574 list_append(&device->driver_devices, &device->driver->devices);
00575
00576 fibril_mutex_unlock(&device->driver->devices_mutex);
00577 fibril_condvar_broadcast(&devices_list_cv);
00578 fibril_mutex_unlock(&devices_list_mutex);
00579
00580 async_answer_1(iid, EOK, device->handle);
00581 }
00582
00586 static int devmap_device_unregister(ipc_callid_t iid, ipc_call_t *icall,
00587 devmap_driver_t *driver)
00588 {
00589
00590 return EOK;
00591 }
00592
00599 static void devmap_forward(ipc_callid_t callid, ipc_call_t *call)
00600 {
00601 fibril_mutex_lock(&devices_list_mutex);
00602
00603
00604
00605
00606 devmap_handle_t handle = IPC_GET_ARG2(*call);
00607 devmap_device_t *dev = devmap_device_find_handle(handle);
00608
00609 if ((dev == NULL) || (dev->driver == NULL) || (dev->driver->phone == 0)) {
00610 fibril_mutex_unlock(&devices_list_mutex);
00611 async_answer_0(callid, ENOENT);
00612 return;
00613 }
00614
00615 if (dev->forward_interface == 0) {
00616 async_forward_fast(callid, dev->driver->phone,
00617 dev->handle, 0, 0,
00618 IPC_FF_NONE);
00619 } else {
00620 async_forward_fast(callid, dev->driver->phone,
00621 dev->forward_interface, dev->handle, 0,
00622 IPC_FF_NONE);
00623 }
00624
00625 fibril_mutex_unlock(&devices_list_mutex);
00626 }
00627
00634 static void devmap_device_get_handle(ipc_callid_t iid, ipc_call_t *icall)
00635 {
00636 char *fqdn;
00637
00638
00639 int rc = async_data_write_accept((void **) &fqdn, true, 0,
00640 DEVMAP_NAME_MAXLEN, 0, NULL);
00641 if (rc != EOK) {
00642 async_answer_0(iid, rc);
00643 return;
00644 }
00645
00646 char *ns_name;
00647 char *name;
00648 if (!devmap_fqdn_split(fqdn, &ns_name, &name)) {
00649 free(fqdn);
00650 async_answer_0(iid, EINVAL);
00651 return;
00652 }
00653
00654 free(fqdn);
00655
00656 fibril_mutex_lock(&devices_list_mutex);
00657 const devmap_device_t *dev;
00658
00659 recheck:
00660
00661
00662
00663
00664 dev = devmap_device_find_name(ns_name, name);
00665
00666
00667
00668
00669 if (dev == NULL) {
00670 if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
00671
00672 fibril_condvar_wait(&devices_list_cv,
00673 &devices_list_mutex);
00674 goto recheck;
00675 }
00676
00677 async_answer_0(iid, ENOENT);
00678 free(ns_name);
00679 free(name);
00680 fibril_mutex_unlock(&devices_list_mutex);
00681 return;
00682 }
00683
00684 async_answer_1(iid, EOK, dev->handle);
00685
00686 fibril_mutex_unlock(&devices_list_mutex);
00687 free(ns_name);
00688 free(name);
00689 }
00690
00697 static void devmap_namespace_get_handle(ipc_callid_t iid, ipc_call_t *icall)
00698 {
00699 char *name;
00700
00701
00702 int rc = async_data_write_accept((void **) &name, true, 0,
00703 DEVMAP_NAME_MAXLEN, 0, NULL);
00704 if (rc != EOK) {
00705 async_answer_0(iid, rc);
00706 return;
00707 }
00708
00709 fibril_mutex_lock(&devices_list_mutex);
00710 const devmap_namespace_t *namespace;
00711
00712 recheck:
00713
00714
00715
00716
00717 namespace = devmap_namespace_find_name(name);
00718
00719
00720
00721
00722 if (namespace == NULL) {
00723 if (IPC_GET_ARG1(*icall) & IPC_FLAG_BLOCKING) {
00724
00725 fibril_condvar_wait(&devices_list_cv,
00726 &devices_list_mutex);
00727 goto recheck;
00728 }
00729
00730 async_answer_0(iid, ENOENT);
00731 free(name);
00732 fibril_mutex_unlock(&devices_list_mutex);
00733 return;
00734 }
00735
00736 async_answer_1(iid, EOK, namespace->handle);
00737
00738 fibril_mutex_unlock(&devices_list_mutex);
00739 free(name);
00740 }
00741
00742 static void devmap_handle_probe(ipc_callid_t iid, ipc_call_t *icall)
00743 {
00744 fibril_mutex_lock(&devices_list_mutex);
00745
00746 devmap_namespace_t *namespace =
00747 devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
00748 if (namespace == NULL) {
00749 devmap_device_t *dev =
00750 devmap_device_find_handle(IPC_GET_ARG1(*icall));
00751 if (dev == NULL)
00752 async_answer_1(iid, EOK, DEV_HANDLE_NONE);
00753 else
00754 async_answer_1(iid, EOK, DEV_HANDLE_DEVICE);
00755 } else
00756 async_answer_1(iid, EOK, DEV_HANDLE_NAMESPACE);
00757
00758 fibril_mutex_unlock(&devices_list_mutex);
00759 }
00760
00761 static void devmap_get_namespace_count(ipc_callid_t iid, ipc_call_t *icall)
00762 {
00763 fibril_mutex_lock(&devices_list_mutex);
00764 async_answer_1(iid, EOK, list_count(&namespaces_list));
00765 fibril_mutex_unlock(&devices_list_mutex);
00766 }
00767
00768 static void devmap_get_device_count(ipc_callid_t iid, ipc_call_t *icall)
00769 {
00770 fibril_mutex_lock(&devices_list_mutex);
00771
00772 devmap_namespace_t *namespace =
00773 devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
00774 if (namespace == NULL)
00775 async_answer_0(iid, EEXISTS);
00776 else
00777 async_answer_1(iid, EOK, namespace->refcnt);
00778
00779 fibril_mutex_unlock(&devices_list_mutex);
00780 }
00781
00782 static void devmap_get_namespaces(ipc_callid_t iid, ipc_call_t *icall)
00783 {
00784 ipc_callid_t callid;
00785 size_t size;
00786 if (!async_data_read_receive(&callid, &size)) {
00787 async_answer_0(callid, EREFUSED);
00788 async_answer_0(iid, EREFUSED);
00789 return;
00790 }
00791
00792 if ((size % sizeof(dev_desc_t)) != 0) {
00793 async_answer_0(callid, EINVAL);
00794 async_answer_0(iid, EINVAL);
00795 return;
00796 }
00797
00798 fibril_mutex_lock(&devices_list_mutex);
00799
00800 size_t count = size / sizeof(dev_desc_t);
00801 if (count != list_count(&namespaces_list)) {
00802 fibril_mutex_unlock(&devices_list_mutex);
00803 async_answer_0(callid, EOVERFLOW);
00804 async_answer_0(iid, EOVERFLOW);
00805 return;
00806 }
00807
00808 dev_desc_t *desc = (dev_desc_t *) malloc(size);
00809 if (desc == NULL) {
00810 fibril_mutex_unlock(&devices_list_mutex);
00811 async_answer_0(callid, ENOMEM);
00812 async_answer_0(iid, ENOMEM);
00813 return;
00814 }
00815
00816 link_t *item;
00817 size_t pos = 0;
00818 for (item = namespaces_list.next; item != &namespaces_list;
00819 item = item->next) {
00820 devmap_namespace_t *namespace =
00821 list_get_instance(item, devmap_namespace_t, namespaces);
00822
00823 desc[pos].handle = namespace->handle;
00824 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, namespace->name);
00825 pos++;
00826 }
00827
00828 sysarg_t retval = async_data_read_finalize(callid, desc, size);
00829
00830 free(desc);
00831 fibril_mutex_unlock(&devices_list_mutex);
00832
00833 async_answer_0(iid, retval);
00834 }
00835
00836 static void devmap_get_devices(ipc_callid_t iid, ipc_call_t *icall)
00837 {
00838
00839
00840
00841 ipc_callid_t callid;
00842 size_t size;
00843 if (!async_data_read_receive(&callid, &size)) {
00844 async_answer_0(callid, EREFUSED);
00845 async_answer_0(iid, EREFUSED);
00846 return;
00847 }
00848
00849 if ((size % sizeof(dev_desc_t)) != 0) {
00850 async_answer_0(callid, EINVAL);
00851 async_answer_0(iid, EINVAL);
00852 return;
00853 }
00854
00855 fibril_mutex_lock(&devices_list_mutex);
00856
00857 devmap_namespace_t *namespace =
00858 devmap_namespace_find_handle(IPC_GET_ARG1(*icall));
00859 if (namespace == NULL) {
00860 fibril_mutex_unlock(&devices_list_mutex);
00861 async_answer_0(callid, ENOENT);
00862 async_answer_0(iid, ENOENT);
00863 return;
00864 }
00865
00866 size_t count = size / sizeof(dev_desc_t);
00867 if (count != namespace->refcnt) {
00868 fibril_mutex_unlock(&devices_list_mutex);
00869 async_answer_0(callid, EOVERFLOW);
00870 async_answer_0(iid, EOVERFLOW);
00871 return;
00872 }
00873
00874 dev_desc_t *desc = (dev_desc_t *) malloc(size);
00875 if (desc == NULL) {
00876 fibril_mutex_unlock(&devices_list_mutex);
00877 async_answer_0(callid, ENOMEM);
00878 async_answer_0(iid, EREFUSED);
00879 return;
00880 }
00881
00882 link_t *item;
00883 size_t pos = 0;
00884 for (item = devices_list.next; item != &devices_list; item = item->next) {
00885 devmap_device_t *device =
00886 list_get_instance(item, devmap_device_t, devices);
00887
00888 if (device->namespace == namespace) {
00889 desc[pos].handle = device->handle;
00890 str_cpy(desc[pos].name, DEVMAP_NAME_MAXLEN, device->name);
00891 pos++;
00892 }
00893 }
00894
00895 sysarg_t retval = async_data_read_finalize(callid, desc, size);
00896
00897 free(desc);
00898 fibril_mutex_unlock(&devices_list_mutex);
00899
00900 async_answer_0(iid, retval);
00901 }
00902
00903 static void devmap_null_create(ipc_callid_t iid, ipc_call_t *icall)
00904 {
00905 fibril_mutex_lock(&null_devices_mutex);
00906
00907 unsigned int i;
00908 bool fnd = false;
00909
00910 for (i = 0; i < NULL_DEVICES; i++) {
00911 if (null_devices[i] == NULL) {
00912 fnd = true;
00913 break;
00914 }
00915 }
00916
00917 if (!fnd) {
00918 fibril_mutex_unlock(&null_devices_mutex);
00919 async_answer_0(iid, ENOMEM);
00920 return;
00921 }
00922
00923 char null[DEVMAP_NAME_MAXLEN];
00924 snprintf(null, DEVMAP_NAME_MAXLEN, "%u", i);
00925
00926 char *dev_name = str_dup(null);
00927 if (dev_name == NULL) {
00928 fibril_mutex_unlock(&null_devices_mutex);
00929 async_answer_0(iid, ENOMEM);
00930 return;
00931 }
00932
00933 devmap_device_t *device =
00934 (devmap_device_t *) malloc(sizeof(devmap_device_t));
00935 if (device == NULL) {
00936 fibril_mutex_unlock(&null_devices_mutex);
00937 async_answer_0(iid, ENOMEM);
00938 return;
00939 }
00940
00941 fibril_mutex_lock(&devices_list_mutex);
00942
00943 devmap_namespace_t *namespace = devmap_namespace_create("null");
00944 if (namespace == NULL) {
00945 fibril_mutex_lock(&devices_list_mutex);
00946 fibril_mutex_unlock(&null_devices_mutex);
00947 async_answer_0(iid, ENOMEM);
00948 return;
00949 }
00950
00951 link_initialize(&device->devices);
00952 link_initialize(&device->driver_devices);
00953
00954
00955 device->handle = devmap_create_handle();
00956 device->driver = NULL;
00957
00958 devmap_namespace_addref(namespace, device);
00959 device->name = dev_name;
00960
00961
00962
00963
00964
00965
00966 list_append(&device->devices, &devices_list);
00967 list_append(&device->driver_devices, &dummy_null_driver_devices);
00968 null_devices[i] = device;
00969
00970 fibril_mutex_unlock(&devices_list_mutex);
00971 fibril_mutex_unlock(&null_devices_mutex);
00972
00973 async_answer_1(iid, EOK, (sysarg_t) i);
00974 }
00975
00976 static void devmap_null_destroy(ipc_callid_t iid, ipc_call_t *icall)
00977 {
00978 sysarg_t i = IPC_GET_ARG1(*icall);
00979 if (i >= NULL_DEVICES) {
00980 async_answer_0(iid, ELIMIT);
00981 return;
00982 }
00983
00984 fibril_mutex_lock(&null_devices_mutex);
00985
00986 if (null_devices[i] == NULL) {
00987 fibril_mutex_unlock(&null_devices_mutex);
00988 async_answer_0(iid, ENOENT);
00989 return;
00990 }
00991
00992 fibril_mutex_lock(&devices_list_mutex);
00993 devmap_device_unregister_core(null_devices[i]);
00994 fibril_mutex_unlock(&devices_list_mutex);
00995
00996 null_devices[i] = NULL;
00997
00998 fibril_mutex_unlock(&null_devices_mutex);
00999 async_answer_0(iid, EOK);
01000 }
01001
01006 static bool devmap_init(void)
01007 {
01008 fibril_mutex_lock(&null_devices_mutex);
01009
01010 unsigned int i;
01011 for (i = 0; i < NULL_DEVICES; i++)
01012 null_devices[i] = NULL;
01013
01014 fibril_mutex_unlock(&null_devices_mutex);
01015
01016 return true;
01017 }
01018
01022 static void devmap_connection_driver(ipc_callid_t iid, ipc_call_t *icall)
01023 {
01024
01025 async_answer_0(iid, EOK);
01026
01027 devmap_driver_t *driver = devmap_driver_register();
01028 if (driver == NULL)
01029 return;
01030
01031 bool cont = true;
01032 while (cont) {
01033 ipc_call_t call;
01034 ipc_callid_t callid = async_get_call(&call);
01035
01036 switch (IPC_GET_IMETHOD(call)) {
01037 case IPC_M_PHONE_HUNGUP:
01038 cont = false;
01039 continue;
01040 case DEVMAP_DRIVER_UNREGISTER:
01041 if (NULL == driver)
01042 async_answer_0(callid, ENOENT);
01043 else
01044 async_answer_0(callid, EOK);
01045 break;
01046 case DEVMAP_DEVICE_REGISTER:
01047
01048 devmap_device_register(callid, &call, driver);
01049 break;
01050 case DEVMAP_DEVICE_UNREGISTER:
01051
01052 devmap_device_unregister(callid, &call, driver);
01053 break;
01054 case DEVMAP_DEVICE_GET_HANDLE:
01055 devmap_device_get_handle(callid, &call);
01056 break;
01057 case DEVMAP_NAMESPACE_GET_HANDLE:
01058 devmap_namespace_get_handle(callid, &call);
01059 break;
01060 default:
01061 async_answer_0(callid, ENOENT);
01062 }
01063 }
01064
01065 if (driver != NULL) {
01066
01067
01068
01069 devmap_driver_unregister(driver);
01070 driver = NULL;
01071 }
01072 }
01073
01077 static void devmap_connection_client(ipc_callid_t iid, ipc_call_t *icall)
01078 {
01079
01080 async_answer_0(iid, EOK);
01081
01082 bool cont = true;
01083 while (cont) {
01084 ipc_call_t call;
01085 ipc_callid_t callid = async_get_call(&call);
01086
01087 switch (IPC_GET_IMETHOD(call)) {
01088 case IPC_M_PHONE_HUNGUP:
01089 cont = false;
01090 continue;
01091 case DEVMAP_DEVICE_GET_HANDLE:
01092 devmap_device_get_handle(callid, &call);
01093 break;
01094 case DEVMAP_NAMESPACE_GET_HANDLE:
01095 devmap_namespace_get_handle(callid, &call);
01096 break;
01097 case DEVMAP_HANDLE_PROBE:
01098 devmap_handle_probe(callid, &call);
01099 break;
01100 case DEVMAP_NULL_CREATE:
01101 devmap_null_create(callid, &call);
01102 break;
01103 case DEVMAP_NULL_DESTROY:
01104 devmap_null_destroy(callid, &call);
01105 break;
01106 case DEVMAP_GET_NAMESPACE_COUNT:
01107 devmap_get_namespace_count(callid, &call);
01108 break;
01109 case DEVMAP_GET_DEVICE_COUNT:
01110 devmap_get_device_count(callid, &call);
01111 break;
01112 case DEVMAP_GET_NAMESPACES:
01113 devmap_get_namespaces(callid, &call);
01114 break;
01115 case DEVMAP_GET_DEVICES:
01116 devmap_get_devices(callid, &call);
01117 break;
01118 default:
01119 async_answer_0(callid, ENOENT);
01120 }
01121 }
01122 }
01123
01127 static void devmap_connection(ipc_callid_t iid, ipc_call_t *icall)
01128 {
01129
01130 switch ((sysarg_t) (IPC_GET_ARG1(*icall))) {
01131 case DEVMAP_DRIVER:
01132 devmap_connection_driver(iid, icall);
01133 break;
01134 case DEVMAP_CLIENT:
01135 devmap_connection_client(iid, icall);
01136 break;
01137 case DEVMAP_CONNECT_TO_DEVICE:
01138
01139 devmap_forward(iid, icall);
01140 break;
01141 default:
01142
01143 async_answer_0(iid, ENOENT);
01144 }
01145 }
01146
01150 int main(int argc, char *argv[])
01151 {
01152 printf("%s: HelenOS Device Mapper\n", NAME);
01153
01154 if (!devmap_init()) {
01155 printf("%s: Error while initializing service\n", NAME);
01156 return -1;
01157 }
01158
01159
01160 async_set_client_connection(devmap_connection);
01161
01162
01163 if (service_register(SERVICE_DEVMAP) != EOK)
01164 return -1;
01165
01166 printf("%s: Accepting connections\n", NAME);
01167 async_manager();
01168
01169
01170 return 0;
01171 }
01172