devfs_ops.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2009 Martin Decky
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * - Redistributions of source code must retain the above copyright
00010  *   notice, this list of conditions and the following disclaimer.
00011  * - Redistributions in binary form must reproduce the above copyright
00012  *   notice, this list of conditions and the following disclaimer in the
00013  *   documentation and/or other materials provided with the distribution.
00014  * - The name of the author may not be used to endorse or promote products
00015  *   derived from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00018  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
00019  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
00020  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
00021  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
00022  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00023  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00024  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00026  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00027  */
00028 
00038 #include <macros.h>
00039 #include <bool.h>
00040 #include <errno.h>
00041 #include <malloc.h>
00042 #include <str.h>
00043 #include <libfs.h>
00044 #include <fibril_synch.h>
00045 #include <adt/hash_table.h>
00046 #include <ipc/devmap.h>
00047 #include <sys/stat.h>
00048 #include <libfs.h>
00049 #include <assert.h>
00050 #include "devfs.h"
00051 #include "devfs_ops.h"
00052 
00053 typedef struct {
00054         devmap_handle_type_t type;
00055         devmap_handle_t handle;
00056 } devfs_node_t;
00057 
00059 typedef struct {
00060         devmap_handle_t handle;
00061         int phone;              
00062         size_t refcount;
00063         link_t link;
00064         fibril_condvar_t cv;    
00065 } device_t;
00066 
00068 static hash_table_t devices;
00069 
00071 static FIBRIL_MUTEX_INITIALIZE(devices_mutex);
00072 
00073 #define DEVICES_KEYS        1
00074 #define DEVICES_KEY_HANDLE  0
00075 #define DEVICES_BUCKETS     256
00076 
00077 /* Implementation of hash table interface for the nodes hash table. */
00078 static hash_index_t devices_hash(unsigned long key[])
00079 {
00080         return key[DEVICES_KEY_HANDLE] % DEVICES_BUCKETS;
00081 }
00082 
00083 static int devices_compare(unsigned long key[], hash_count_t keys, link_t *item)
00084 {
00085         device_t *dev = hash_table_get_instance(item, device_t, link);
00086         return (dev->handle == (devmap_handle_t) key[DEVICES_KEY_HANDLE]);
00087 }
00088 
00089 static void devices_remove_callback(link_t *item)
00090 {
00091         free(hash_table_get_instance(item, device_t, link));
00092 }
00093 
00094 static hash_table_operations_t devices_ops = {
00095         .hash = devices_hash,
00096         .compare = devices_compare,
00097         .remove_callback = devices_remove_callback
00098 };
00099 
00100 static int devfs_node_get_internal(fs_node_t **rfn, devmap_handle_type_t type,
00101     devmap_handle_t handle)
00102 {
00103         devfs_node_t *node = (devfs_node_t *) malloc(sizeof(devfs_node_t));
00104         if (node == NULL) {
00105                 *rfn = NULL;
00106                 return ENOMEM;
00107         }
00108         
00109         *rfn = (fs_node_t *) malloc(sizeof(fs_node_t));
00110         if (*rfn == NULL) {
00111                 free(node);
00112                 *rfn = NULL;
00113                 return ENOMEM;
00114         }
00115         
00116         fs_node_initialize(*rfn);
00117         node->type = type;
00118         node->handle = handle;
00119         
00120         (*rfn)->data = node;
00121         return EOK;
00122 }
00123 
00124 static int devfs_root_get(fs_node_t **rfn, devmap_handle_t devmap_handle)
00125 {
00126         return devfs_node_get_internal(rfn, DEV_HANDLE_NONE, 0);
00127 }
00128 
00129 static int devfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
00130 {
00131         devfs_node_t *node = (devfs_node_t *) pfn->data;
00132         int ret;
00133         
00134         if (node->handle == 0) {
00135                 /* Root directory */
00136                 
00137                 dev_desc_t *devs;
00138                 size_t count = devmap_get_namespaces(&devs);
00139                 
00140                 if (count > 0) {
00141                         size_t pos;
00142                         for (pos = 0; pos < count; pos++) {
00143                                 /* Ignore root namespace */
00144                                 if (str_cmp(devs[pos].name, "") == 0)
00145                                         continue;
00146                                 
00147                                 if (str_cmp(devs[pos].name, component) == 0) {
00148                                         ret = devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
00149                                         free(devs);
00150                                         return ret;
00151                                 }
00152                         }
00153                         
00154                         free(devs);
00155                 }
00156                 
00157                 /* Search root namespace */
00158                 devmap_handle_t namespace;
00159                 if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
00160                         count = devmap_get_devices(namespace, &devs);
00161                         
00162                         if (count > 0) {
00163                                 size_t pos;
00164                                 for (pos = 0; pos < count; pos++) {
00165                                         if (str_cmp(devs[pos].name, component) == 0) {
00166                                                 ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
00167                                                 free(devs);
00168                                                 return ret;
00169                                         }
00170                                 }
00171                                 
00172                                 free(devs);
00173                         }
00174                 }
00175                 
00176                 *rfn = NULL;
00177                 return EOK;
00178         }
00179         
00180         if (node->type == DEV_HANDLE_NAMESPACE) {
00181                 /* Namespace directory */
00182                 
00183                 dev_desc_t *devs;
00184                 size_t count = devmap_get_devices(node->handle, &devs);
00185                 if (count > 0) {
00186                         size_t pos;
00187                         for (pos = 0; pos < count; pos++) {
00188                                 if (str_cmp(devs[pos].name, component) == 0) {
00189                                         ret = devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
00190                                         free(devs);
00191                                         return ret;
00192                                 }
00193                         }
00194                         
00195                         free(devs);
00196                 }
00197                 
00198                 *rfn = NULL;
00199                 return EOK;
00200         }
00201         
00202         *rfn = NULL;
00203         return EOK;
00204 }
00205 
00206 static int devfs_node_get(fs_node_t **rfn, devmap_handle_t devmap_handle, fs_index_t index)
00207 {
00208         return devfs_node_get_internal(rfn, devmap_handle_probe(index), index);
00209 }
00210 
00211 static int devfs_node_open(fs_node_t *fn)
00212 {
00213         devfs_node_t *node = (devfs_node_t *) fn->data;
00214         
00215         if (node->handle == 0) {
00216                 /* Root directory */
00217                 return EOK;
00218         }
00219         
00220         devmap_handle_type_t type = devmap_handle_probe(node->handle);
00221         
00222         if (type == DEV_HANDLE_NAMESPACE) {
00223                 /* Namespace directory */
00224                 return EOK;
00225         }
00226         
00227         if (type == DEV_HANDLE_DEVICE) {
00228                 /* Device node */
00229                 
00230                 unsigned long key[] = {
00231                         [DEVICES_KEY_HANDLE] = (unsigned long) node->handle
00232                 };
00233                 link_t *lnk;
00234 
00235                 fibril_mutex_lock(&devices_mutex);
00236 restart:
00237                 lnk = hash_table_find(&devices, key);
00238                 if (lnk == NULL) {
00239                         device_t *dev = (device_t *) malloc(sizeof(device_t));
00240                         if (dev == NULL) {
00241                                 fibril_mutex_unlock(&devices_mutex);
00242                                 return ENOMEM;
00243                         }
00244                         
00245                         dev->handle = node->handle;
00246                         dev->phone = -1;        /* mark as incomplete */
00247                         dev->refcount = 1;
00248                         fibril_condvar_initialize(&dev->cv);
00249 
00250                         /*
00251                          * Insert the incomplete device structure so that other
00252                          * fibrils will not race with us when we drop the mutex
00253                          * below.
00254                          */
00255                         hash_table_insert(&devices, key, &dev->link);
00256 
00257                         /*
00258                          * Drop the mutex to allow recursive devfs requests.
00259                          */
00260                         fibril_mutex_unlock(&devices_mutex);
00261 
00262                         int phone = devmap_device_connect(node->handle, 0);
00263 
00264                         fibril_mutex_lock(&devices_mutex);
00265 
00266                         /*
00267                          * Notify possible waiters about this device structure
00268                          * being completed (or destroyed).
00269                          */
00270                         fibril_condvar_broadcast(&dev->cv);
00271 
00272                         if (phone < 0) {
00273                                 /*
00274                                  * Connecting failed, need to remove the
00275                                  * entry and free the device structure.
00276                                  */
00277                                 hash_table_remove(&devices, key, DEVICES_KEYS);
00278                                 fibril_mutex_unlock(&devices_mutex);
00279 
00280                                 return ENOENT;
00281                         }
00282                         
00283                         /* Set the correct phone. */
00284                         dev->phone = phone;
00285                 } else {
00286                         device_t *dev = hash_table_get_instance(lnk, device_t, link);
00287 
00288                         if (dev->phone < 0) {
00289                                 /*
00290                                  * Wait until the device structure is completed
00291                                  * and start from the beginning as the device
00292                                  * structure might have entirely disappeared
00293                                  * while we were not holding the mutex in
00294                                  * fibril_condvar_wait().
00295                                  */
00296                                 fibril_condvar_wait(&dev->cv, &devices_mutex);
00297                                 goto restart;
00298                         }
00299 
00300                         dev->refcount++;
00301                 }
00302                 
00303                 fibril_mutex_unlock(&devices_mutex);
00304                 
00305                 return EOK;
00306         }
00307         
00308         return ENOENT;
00309 }
00310 
00311 static int devfs_node_put(fs_node_t *fn)
00312 {
00313         free(fn->data);
00314         free(fn);
00315         return EOK;
00316 }
00317 
00318 static int devfs_create_node(fs_node_t **rfn, devmap_handle_t devmap_handle, int lflag)
00319 {
00320         assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
00321         
00322         *rfn = NULL;
00323         return ENOTSUP;
00324 }
00325 
00326 static int devfs_destroy_node(fs_node_t *fn)
00327 {
00328         return ENOTSUP;
00329 }
00330 
00331 static int devfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
00332 {
00333         return ENOTSUP;
00334 }
00335 
00336 static int devfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
00337 {
00338         return ENOTSUP;
00339 }
00340 
00341 static int devfs_has_children(bool *has_children, fs_node_t *fn)
00342 {
00343         devfs_node_t *node = (devfs_node_t *) fn->data;
00344         
00345         if (node->handle == 0) {
00346                 size_t count = devmap_count_namespaces();
00347                 if (count > 0) {
00348                         *has_children = true;
00349                         return EOK;
00350                 }
00351                 
00352                 /* Root namespace */
00353                 devmap_handle_t namespace;
00354                 if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
00355                         count = devmap_count_devices(namespace);
00356                         if (count > 0) {
00357                                 *has_children = true;
00358                                 return EOK;
00359                         }
00360                 }
00361                 
00362                 *has_children = false;
00363                 return EOK;
00364         }
00365         
00366         if (node->type == DEV_HANDLE_NAMESPACE) {
00367                 size_t count = devmap_count_devices(node->handle);
00368                 if (count > 0) {
00369                         *has_children = true;
00370                         return EOK;
00371                 }
00372                 
00373                 *has_children = false;
00374                 return EOK;
00375         }
00376         
00377         *has_children = false;
00378         return EOK;
00379 }
00380 
00381 static fs_index_t devfs_index_get(fs_node_t *fn)
00382 {
00383         devfs_node_t *node = (devfs_node_t *) fn->data;
00384         return node->handle;
00385 }
00386 
00387 static aoff64_t devfs_size_get(fs_node_t *fn)
00388 {
00389         return 0;
00390 }
00391 
00392 static unsigned int devfs_lnkcnt_get(fs_node_t *fn)
00393 {
00394         devfs_node_t *node = (devfs_node_t *) fn->data;
00395         
00396         if (node->handle == 0)
00397                 return 0;
00398         
00399         return 1;
00400 }
00401 
00402 static char devfs_plb_get_char(unsigned pos)
00403 {
00404         return devfs_reg.plb_ro[pos % PLB_SIZE];
00405 }
00406 
00407 static bool devfs_is_directory(fs_node_t *fn)
00408 {
00409         devfs_node_t *node = (devfs_node_t *) fn->data;
00410         
00411         return ((node->type == DEV_HANDLE_NONE) || (node->type == DEV_HANDLE_NAMESPACE));
00412 }
00413 
00414 static bool devfs_is_file(fs_node_t *fn)
00415 {
00416         devfs_node_t *node = (devfs_node_t *) fn->data;
00417         
00418         return (node->type == DEV_HANDLE_DEVICE);
00419 }
00420 
00421 static devmap_handle_t devfs_device_get(fs_node_t *fn)
00422 {
00423         devfs_node_t *node = (devfs_node_t *) fn->data;
00424         
00425         if (node->type == DEV_HANDLE_DEVICE)
00426                 return node->handle;
00427         
00428         return 0;
00429 }
00430 
00432 libfs_ops_t devfs_libfs_ops = {
00433         .root_get = devfs_root_get,
00434         .match = devfs_match,
00435         .node_get = devfs_node_get,
00436         .node_open = devfs_node_open,
00437         .node_put = devfs_node_put,
00438         .create = devfs_create_node,
00439         .destroy = devfs_destroy_node,
00440         .link = devfs_link_node,
00441         .unlink = devfs_unlink_node,
00442         .has_children = devfs_has_children,
00443         .index_get = devfs_index_get,
00444         .size_get = devfs_size_get,
00445         .lnkcnt_get = devfs_lnkcnt_get,
00446         .plb_get_char = devfs_plb_get_char,
00447         .is_directory = devfs_is_directory,
00448         .is_file = devfs_is_file,
00449         .device_get = devfs_device_get
00450 };
00451 
00452 bool devfs_init(void)
00453 {
00454         if (!hash_table_create(&devices, DEVICES_BUCKETS,
00455             DEVICES_KEYS, &devices_ops))
00456                 return false;
00457         
00458         return true;
00459 }
00460 
00461 void devfs_mounted(ipc_callid_t rid, ipc_call_t *request)
00462 {
00463         char *opts;
00464         
00465         /* Accept the mount options */
00466         sysarg_t retval = async_data_write_accept((void **) &opts, true, 0, 0,
00467             0, NULL);
00468         if (retval != EOK) {
00469                 async_answer_0(rid, retval);
00470                 return;
00471         }
00472         
00473         free(opts);
00474         async_answer_3(rid, EOK, 0, 0, 0);
00475 }
00476 
00477 void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
00478 {
00479         libfs_mount(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
00480 }
00481 
00482 void devfs_unmounted(ipc_callid_t rid, ipc_call_t *request)
00483 {
00484         async_answer_0(rid, ENOTSUP);
00485 }
00486 
00487 void devfs_unmount(ipc_callid_t rid, ipc_call_t *request)
00488 {
00489         libfs_unmount(&devfs_libfs_ops, rid, request);
00490 }
00491 
00492 void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
00493 {
00494         libfs_lookup(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
00495 }
00496 
00497 void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
00498 {
00499         libfs_open_node(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
00500 }
00501 
00502 void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
00503 {
00504         libfs_stat(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
00505 }
00506 
00507 void devfs_read(ipc_callid_t rid, ipc_call_t *request)
00508 {
00509         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
00510         aoff64_t pos =
00511             (aoff64_t) MERGE_LOUP32(IPC_GET_ARG3(*request), IPC_GET_ARG4(*request));
00512         
00513         if (index == 0) {
00514                 ipc_callid_t callid;
00515                 size_t size;
00516                 if (!async_data_read_receive(&callid, &size)) {
00517                         async_answer_0(callid, EINVAL);
00518                         async_answer_0(rid, EINVAL);
00519                         return;
00520                 }
00521                 
00522                 dev_desc_t *desc;
00523                 size_t count = devmap_get_namespaces(&desc);
00524                 
00525                 /* Get rid of root namespace */
00526                 size_t i;
00527                 for (i = 0; i < count; i++) {
00528                         if (str_cmp(desc[i].name, "") == 0) {
00529                                 if (pos >= i)
00530                                         pos++;
00531                                 
00532                                 break;
00533                         }
00534                 }
00535                 
00536                 if (pos < count) {
00537                         async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
00538                         free(desc);
00539                         async_answer_1(rid, EOK, 1);
00540                         return;
00541                 }
00542                 
00543                 free(desc);
00544                 pos -= count;
00545                 
00546                 /* Search root namespace */
00547                 devmap_handle_t namespace;
00548                 if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
00549                         count = devmap_get_devices(namespace, &desc);
00550                         
00551                         if (pos < count) {
00552                                 async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
00553                                 free(desc);
00554                                 async_answer_1(rid, EOK, 1);
00555                                 return;
00556                         }
00557                         
00558                         free(desc);
00559                 }
00560                 
00561                 async_answer_0(callid, ENOENT);
00562                 async_answer_1(rid, ENOENT, 0);
00563                 return;
00564         }
00565         
00566         devmap_handle_type_t type = devmap_handle_probe(index);
00567         
00568         if (type == DEV_HANDLE_NAMESPACE) {
00569                 /* Namespace directory */
00570                 ipc_callid_t callid;
00571                 size_t size;
00572                 if (!async_data_read_receive(&callid, &size)) {
00573                         async_answer_0(callid, EINVAL);
00574                         async_answer_0(rid, EINVAL);
00575                         return;
00576                 }
00577                 
00578                 dev_desc_t *desc;
00579                 size_t count = devmap_get_devices(index, &desc);
00580                 
00581                 if (pos < count) {
00582                         async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
00583                         free(desc);
00584                         async_answer_1(rid, EOK, 1);
00585                         return;
00586                 }
00587                 
00588                 free(desc);
00589                 async_answer_0(callid, ENOENT);
00590                 async_answer_1(rid, ENOENT, 0);
00591                 return;
00592         }
00593         
00594         if (type == DEV_HANDLE_DEVICE) {
00595                 /* Device node */
00596                 
00597                 unsigned long key[] = {
00598                         [DEVICES_KEY_HANDLE] = (unsigned long) index
00599                 };
00600                 
00601                 fibril_mutex_lock(&devices_mutex);
00602                 link_t *lnk = hash_table_find(&devices, key);
00603                 if (lnk == NULL) {
00604                         fibril_mutex_unlock(&devices_mutex);
00605                         async_answer_0(rid, ENOENT);
00606                         return;
00607                 }
00608                 
00609                 device_t *dev = hash_table_get_instance(lnk, device_t, link);
00610                 assert(dev->phone >= 0);
00611                 
00612                 ipc_callid_t callid;
00613                 if (!async_data_read_receive(&callid, NULL)) {
00614                         fibril_mutex_unlock(&devices_mutex);
00615                         async_answer_0(callid, EINVAL);
00616                         async_answer_0(rid, EINVAL);
00617                         return;
00618                 }
00619                 
00620                 /* Make a request at the driver */
00621                 ipc_call_t answer;
00622                 aid_t msg = async_send_3(dev->phone, IPC_GET_IMETHOD(*request),
00623                     IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
00624                     IPC_GET_ARG3(*request), &answer);
00625                 
00626                 /* Forward the IPC_M_DATA_READ request to the driver */
00627                 async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
00628                 fibril_mutex_unlock(&devices_mutex);
00629                 
00630                 /* Wait for reply from the driver. */
00631                 sysarg_t rc;
00632                 async_wait_for(msg, &rc);
00633                 size_t bytes = IPC_GET_ARG1(answer);
00634                 
00635                 /* Driver reply is the final result of the whole operation */
00636                 async_answer_1(rid, rc, bytes);
00637                 return;
00638         }
00639         
00640         async_answer_0(rid, ENOENT);
00641 }
00642 
00643 void devfs_write(ipc_callid_t rid, ipc_call_t *request)
00644 {
00645         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
00646         if (index == 0) {
00647                 async_answer_0(rid, ENOTSUP);
00648                 return;
00649         }
00650         
00651         devmap_handle_type_t type = devmap_handle_probe(index);
00652         
00653         if (type == DEV_HANDLE_NAMESPACE) {
00654                 /* Namespace directory */
00655                 async_answer_0(rid, ENOTSUP);
00656                 return;
00657         }
00658         
00659         if (type == DEV_HANDLE_DEVICE) {
00660                 /* Device node */
00661                 unsigned long key[] = {
00662                         [DEVICES_KEY_HANDLE] = (unsigned long) index
00663                 };
00664                 
00665                 fibril_mutex_lock(&devices_mutex);
00666                 link_t *lnk = hash_table_find(&devices, key);
00667                 if (lnk == NULL) {
00668                         fibril_mutex_unlock(&devices_mutex);
00669                         async_answer_0(rid, ENOENT);
00670                         return;
00671                 }
00672                 
00673                 device_t *dev = hash_table_get_instance(lnk, device_t, link);
00674                 assert(dev->phone >= 0);
00675                 
00676                 ipc_callid_t callid;
00677                 if (!async_data_write_receive(&callid, NULL)) {
00678                         fibril_mutex_unlock(&devices_mutex);
00679                         async_answer_0(callid, EINVAL);
00680                         async_answer_0(rid, EINVAL);
00681                         return;
00682                 }
00683                 
00684                 /* Make a request at the driver */
00685                 ipc_call_t answer;
00686                 aid_t msg = async_send_3(dev->phone, IPC_GET_IMETHOD(*request),
00687                     IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
00688                     IPC_GET_ARG3(*request), &answer);
00689                 
00690                 /* Forward the IPC_M_DATA_WRITE request to the driver */
00691                 async_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
00692                 
00693                 fibril_mutex_unlock(&devices_mutex);
00694                 
00695                 /* Wait for reply from the driver. */
00696                 sysarg_t rc;
00697                 async_wait_for(msg, &rc);
00698                 size_t bytes = IPC_GET_ARG1(answer);
00699                 
00700                 /* Driver reply is the final result of the whole operation */
00701                 async_answer_1(rid, rc, bytes);
00702                 return;
00703         }
00704         
00705         async_answer_0(rid, ENOENT);
00706 }
00707 
00708 void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
00709 {
00710         async_answer_0(rid, ENOTSUP);
00711 }
00712 
00713 void devfs_close(ipc_callid_t rid, ipc_call_t *request)
00714 {
00715         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
00716         
00717         if (index == 0) {
00718                 async_answer_0(rid, EOK);
00719                 return;
00720         }
00721         
00722         devmap_handle_type_t type = devmap_handle_probe(index);
00723         
00724         if (type == DEV_HANDLE_NAMESPACE) {
00725                 /* Namespace directory */
00726                 async_answer_0(rid, EOK);
00727                 return;
00728         }
00729         
00730         if (type == DEV_HANDLE_DEVICE) {
00731                 unsigned long key[] = {
00732                         [DEVICES_KEY_HANDLE] = (unsigned long) index
00733                 };
00734                 
00735                 fibril_mutex_lock(&devices_mutex);
00736                 link_t *lnk = hash_table_find(&devices, key);
00737                 if (lnk == NULL) {
00738                         fibril_mutex_unlock(&devices_mutex);
00739                         async_answer_0(rid, ENOENT);
00740                         return;
00741                 }
00742                 
00743                 device_t *dev = hash_table_get_instance(lnk, device_t, link);
00744                 assert(dev->phone >= 0);
00745                 dev->refcount--;
00746                 
00747                 if (dev->refcount == 0) {
00748                         async_hangup(dev->phone);
00749                         hash_table_remove(&devices, key, DEVICES_KEYS);
00750                 }
00751                 
00752                 fibril_mutex_unlock(&devices_mutex);
00753                 
00754                 async_answer_0(rid, EOK);
00755                 return;
00756         }
00757         
00758         async_answer_0(rid, ENOENT);
00759 }
00760 
00761 void devfs_sync(ipc_callid_t rid, ipc_call_t *request)
00762 {
00763         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
00764         
00765         if (index == 0) {
00766                 async_answer_0(rid, EOK);
00767                 return;
00768         }
00769         
00770         devmap_handle_type_t type = devmap_handle_probe(index);
00771         
00772         if (type == DEV_HANDLE_NAMESPACE) {
00773                 /* Namespace directory */
00774                 async_answer_0(rid, EOK);
00775                 return;
00776         }
00777         
00778         if (type == DEV_HANDLE_DEVICE) {
00779                 unsigned long key[] = {
00780                         [DEVICES_KEY_HANDLE] = (unsigned long) index
00781                 };
00782                 
00783                 fibril_mutex_lock(&devices_mutex);
00784                 link_t *lnk = hash_table_find(&devices, key);
00785                 if (lnk == NULL) {
00786                         fibril_mutex_unlock(&devices_mutex);
00787                         async_answer_0(rid, ENOENT);
00788                         return;
00789                 }
00790                 
00791                 device_t *dev = hash_table_get_instance(lnk, device_t, link);
00792                 assert(dev->phone >= 0);
00793                 
00794                 /* Make a request at the driver */
00795                 ipc_call_t answer;
00796                 aid_t msg = async_send_2(dev->phone, IPC_GET_IMETHOD(*request),
00797                     IPC_GET_ARG1(*request), IPC_GET_ARG2(*request), &answer);
00798                 
00799                 fibril_mutex_unlock(&devices_mutex);
00800                 
00801                 /* Wait for reply from the driver */
00802                 sysarg_t rc;
00803                 async_wait_for(msg, &rc);
00804                 
00805                 /* Driver reply is the final result of the whole operation */
00806                 async_answer_0(rid, rc);
00807                 return;
00808         }
00809         
00810         async_answer_0(rid, ENOENT);
00811 }
00812 
00813 void devfs_destroy(ipc_callid_t rid, ipc_call_t *request)
00814 {
00815         async_answer_0(rid, ENOTSUP);
00816 }
00817 

Generated on Thu Jun 2 07:45:49 2011 for HelenOS/USB by  doxygen 1.4.7