Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/srv/fs/devfs/devfs_ops.c

    r1313ee9 r0da4e41  
    4242#include <string.h>
    4343#include <libfs.h>
    44 #include <fibril_synch.h>
     44#include <fibril_sync.h>
    4545#include <adt/hash_table.h>
    46 #include <ipc/devmap.h>
    4746#include <sys/stat.h>
    48 #include <libfs.h>
    49 #include <assert.h>
    5047#include "devfs.h"
    5148#include "devfs_ops.h"
    5249
    53 typedef struct {
    54         devmap_handle_type_t type;
    55         dev_handle_t handle;
    56 } devfs_node_t;
     50#define PLB_GET_CHAR(pos)  (devfs_reg.plb_ro[pos % PLB_SIZE])
    5751
    5852/** Opened devices structure */
     
    9791};
    9892
    99 static int devfs_node_get_internal(fs_node_t **rfn, devmap_handle_type_t type,
    100     dev_handle_t handle)
    101 {
    102         devfs_node_t *node = (devfs_node_t *) malloc(sizeof(devfs_node_t));
    103         if (node == NULL) {
    104                 *rfn = NULL;
    105                 return ENOMEM;
    106         }
    107        
    108         *rfn = (fs_node_t *) malloc(sizeof(fs_node_t));
    109         if (*rfn == NULL) {
    110                 free(node);
    111                 *rfn = NULL;
    112                 return ENOMEM;
    113         }
    114        
    115         fs_node_initialize(*rfn);
    116         node->type = type;
    117         node->handle = handle;
    118        
    119         (*rfn)->data = node;
    120         return EOK;
    121 }
    122 
    123 static int devfs_root_get(fs_node_t **rfn, dev_handle_t dev_handle)
    124 {
    125         return devfs_node_get_internal(rfn, DEV_HANDLE_NONE, 0);
    126 }
    127 
    128 static int devfs_match(fs_node_t **rfn, fs_node_t *pfn, const char *component)
    129 {
    130         devfs_node_t *node = (devfs_node_t *) pfn->data;
    131        
    132         if (node->handle == 0) {
    133                 /* Root directory */
    134                
    135                 dev_desc_t *devs;
    136                 size_t count = devmap_get_namespaces(&devs);
    137                
    138                 if (count > 0) {
    139                         size_t pos;
    140                         for (pos = 0; pos < count; pos++) {
    141                                 /* Ignore root namespace */
    142                                 if (str_cmp(devs[pos].name, "") == 0)
    143                                         continue;
     93bool devfs_init(void)
     94{
     95        if (!hash_table_create(&devices, DEVICES_BUCKETS,
     96            DEVICES_KEYS, &devices_ops))
     97                return false;
     98       
     99        if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0)
     100                return false;
     101       
     102        return true;
     103}
     104
     105void devfs_mounted(ipc_callid_t rid, ipc_call_t *request)
     106{
     107        /* Accept the mount options */
     108        ipc_callid_t callid;
     109        size_t size;
     110        if (!async_data_write_receive(&callid, &size)) {
     111                ipc_answer_0(callid, EINVAL);
     112                ipc_answer_0(rid, EINVAL);
     113                return;
     114        }
     115       
     116        char *opts = malloc(size + 1);
     117        if (!opts) {
     118                ipc_answer_0(callid, ENOMEM);
     119                ipc_answer_0(rid, ENOMEM);
     120                return;
     121        }
     122       
     123        ipcarg_t retval = async_data_write_finalize(callid, opts, size);
     124        if (retval != EOK) {
     125                ipc_answer_0(rid, retval);
     126                free(opts);
     127                return;
     128        }
     129       
     130        free(opts);
     131       
     132        ipc_answer_3(rid, EOK, 0, 0, 0);
     133}
     134
     135void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
     136{
     137        ipc_answer_0(rid, ENOTSUP);
     138}
     139
     140void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
     141{
     142        ipcarg_t first = IPC_GET_ARG1(*request);
     143        ipcarg_t last = IPC_GET_ARG2(*request);
     144        dev_handle_t dev_handle = IPC_GET_ARG3(*request);
     145        ipcarg_t lflag = IPC_GET_ARG4(*request);
     146        fs_index_t index = IPC_GET_ARG5(*request);
     147       
     148        /* Hierarchy is flat, no altroot is supported */
     149        if (index != 0) {
     150                ipc_answer_0(rid, ENOENT);
     151                return;
     152        }
     153       
     154        if ((lflag & L_LINK) || (lflag & L_UNLINK)) {
     155                ipc_answer_0(rid, ENOTSUP);
     156                return;
     157        }
     158       
     159        /* Eat slash */
     160        if (PLB_GET_CHAR(first) == '/') {
     161                first++;
     162                first %= PLB_SIZE;
     163        }
     164       
     165        if (first >= last) {
     166                /* Root entry */
     167                if (!(lflag & L_FILE))
     168                        ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, 0, 0, 0);
     169                else
     170                        ipc_answer_0(rid, ENOENT);
     171        } else {
     172                if (!(lflag & L_DIRECTORY)) {
     173                        size_t len;
     174                        if (last >= first)
     175                                len = last - first + 1;
     176                        else
     177                                len = first + PLB_SIZE - last + 1;
     178                       
     179                        char *name = (char *) malloc(len + 1);
     180                        if (name == NULL) {
     181                                ipc_answer_0(rid, ENOMEM);
     182                                return;
     183                        }
     184                       
     185                        size_t i;
     186                        for (i = 0; i < len; i++)
     187                                name[i] = PLB_GET_CHAR(first + i);
     188                       
     189                        name[len] = 0;
     190                       
     191                        dev_handle_t handle;
     192                        if (devmap_device_get_handle(name, &handle, 0) != EOK) {
     193                                free(name);
     194                                ipc_answer_0(rid, ENOENT);
     195                                return;
     196                        }
     197                       
     198                        if (lflag & L_OPEN) {
     199                                unsigned long key[] = {
     200                                        [DEVICES_KEY_HANDLE] = (unsigned long) handle
     201                                };
    144202                               
    145                                 if (str_cmp(devs[pos].name, component) == 0) {
    146                                         free(devs);
    147                                         return devfs_node_get_internal(rfn, DEV_HANDLE_NAMESPACE, devs[pos].handle);
     203                                fibril_mutex_lock(&devices_mutex);
     204                                link_t *lnk = hash_table_find(&devices, key);
     205                                if (lnk == NULL) {
     206                                        int phone = devmap_device_connect(handle, 0);
     207                                        if (phone < 0) {
     208                                                fibril_mutex_unlock(&devices_mutex);
     209                                                free(name);
     210                                                ipc_answer_0(rid, ENOENT);
     211                                                return;
     212                                        }
     213                                       
     214                                        device_t *dev = (device_t *) malloc(sizeof(device_t));
     215                                        if (dev == NULL) {
     216                                                fibril_mutex_unlock(&devices_mutex);
     217                                                free(name);
     218                                                ipc_answer_0(rid, ENOMEM);
     219                                                return;
     220                                        }
     221                                       
     222                                        dev->handle = handle;
     223                                        dev->phone = phone;
     224                                        dev->refcount = 1;
     225                                       
     226                                        hash_table_insert(&devices, key, &dev->link);
     227                                } else {
     228                                        device_t *dev = hash_table_get_instance(lnk, device_t, link);
     229                                        dev->refcount++;
    148230                                }
     231                                fibril_mutex_unlock(&devices_mutex);
    149232                        }
    150233                       
    151                         free(devs);
    152                 }
    153                
    154                 /* Search root namespace */
    155                 dev_handle_t namespace;
    156                 if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
    157                         count = devmap_get_devices(namespace, &devs);
    158                        
    159                         if (count > 0) {
    160                                 size_t pos;
    161                                 for (pos = 0; pos < count; pos++) {
    162                                         if (str_cmp(devs[pos].name, component) == 0) {
    163                                                 free(devs);
    164                                                 return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
    165                                         }
    166                                 }
    167                                
    168                                 free(devs);
    169                         }
    170                 }
    171                
    172                 *rfn = NULL;
    173                 return EOK;
    174         }
    175        
    176         if (node->type == DEV_HANDLE_NAMESPACE) {
    177                 /* Namespace directory */
    178                
    179                 dev_desc_t *devs;
    180                 size_t count = devmap_get_devices(node->handle, &devs);
    181                 if (count > 0) {
    182                         size_t pos;
    183                         for (pos = 0; pos < count; pos++) {
    184                                 if (str_cmp(devs[pos].name, component) == 0) {
    185                                         free(devs);
    186                                         return devfs_node_get_internal(rfn, DEV_HANDLE_DEVICE, devs[pos].handle);
    187                                 }
    188                         }
    189                        
    190                         free(devs);
    191                 }
    192                
    193                 *rfn = NULL;
    194                 return EOK;
    195         }
    196        
    197         *rfn = NULL;
    198         return EOK;
    199 }
    200 
    201 static int devfs_node_get(fs_node_t **rfn, dev_handle_t dev_handle, fs_index_t index)
    202 {
    203         return devfs_node_get_internal(rfn, devmap_handle_probe(index), index);
    204 }
    205 
    206 static int devfs_node_open(fs_node_t *fn)
    207 {
    208         devfs_node_t *node = (devfs_node_t *) fn->data;
    209        
    210         if (node->handle == 0) {
    211                 /* Root directory */
    212                 return EOK;
    213         }
    214        
    215         devmap_handle_type_t type = devmap_handle_probe(node->handle);
    216        
    217         if (type == DEV_HANDLE_NAMESPACE) {
    218                 /* Namespace directory */
    219                 return EOK;
    220         }
    221        
    222         if (type == DEV_HANDLE_DEVICE) {
    223                 /* Device node */
    224                
     234                        free(name);
     235                       
     236                        ipc_answer_5(rid, EOK, devfs_reg.fs_handle, dev_handle, handle, 0, 1);
     237                } else
     238                        ipc_answer_0(rid, ENOENT);
     239        }
     240}
     241
     242void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
     243{
     244        dev_handle_t handle = IPC_GET_ARG2(*request);
     245       
     246        unsigned long key[] = {
     247                [DEVICES_KEY_HANDLE] = (unsigned long) handle
     248        };
     249       
     250        fibril_mutex_lock(&devices_mutex);
     251        link_t *lnk = hash_table_find(&devices, key);
     252        if (lnk == NULL) {
     253                int phone = devmap_device_connect(handle, 0);
     254                if (phone < 0) {
     255                        fibril_mutex_unlock(&devices_mutex);
     256                        ipc_answer_0(rid, ENOENT);
     257                        return;
     258                }
     259               
     260                device_t *dev = (device_t *) malloc(sizeof(device_t));
     261                if (dev == NULL) {
     262                        fibril_mutex_unlock(&devices_mutex);
     263                        ipc_answer_0(rid, ENOMEM);
     264                        return;
     265                }
     266               
     267                dev->handle = handle;
     268                dev->phone = phone;
     269                dev->refcount = 1;
     270               
     271                hash_table_insert(&devices, key, &dev->link);
     272        } else {
     273                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     274                dev->refcount++;
     275        }
     276        fibril_mutex_unlock(&devices_mutex);
     277       
     278        ipc_answer_3(rid, EOK, 0, 1, L_FILE);
     279}
     280
     281void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
     282{
     283        dev_handle_t dev_handle = (dev_handle_t) IPC_GET_ARG1(*request);
     284        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     285       
     286        ipc_callid_t callid;
     287        size_t size;
     288        if (!async_data_read_receive(&callid, &size) ||
     289            size != sizeof(struct stat)) {
     290                ipc_answer_0(callid, EINVAL);
     291                ipc_answer_0(rid, EINVAL);
     292                return;
     293        }
     294
     295        struct stat stat;
     296        memset(&stat, 0, sizeof(struct stat));
     297
     298        stat.fs_handle = devfs_reg.fs_handle;
     299        stat.dev_handle = dev_handle;
     300        stat.index = index;
     301        stat.lnkcnt = 1;
     302        stat.is_file = (index != 0);
     303        stat.size = 0;
     304       
     305        if (index != 0) {
    225306                unsigned long key[] = {
    226                         [DEVICES_KEY_HANDLE] = (unsigned long) node->handle
     307                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     308                };
     309               
     310                fibril_mutex_lock(&devices_mutex);
     311                link_t *lnk = hash_table_find(&devices, key);
     312                if (lnk != NULL)
     313                        stat.devfs_stat.device = (dev_handle_t)index;
     314                fibril_mutex_unlock(&devices_mutex);
     315        }
     316
     317        async_data_read_finalize(callid, &stat, sizeof(struct stat));
     318        ipc_answer_0(rid, EOK);
     319}
     320
     321void devfs_read(ipc_callid_t rid, ipc_call_t *request)
     322{
     323        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     324        off_t pos = (off_t) IPC_GET_ARG3(*request);
     325       
     326        if (index != 0) {
     327                unsigned long key[] = {
     328                        [DEVICES_KEY_HANDLE] = (unsigned long) index
    227329                };
    228330               
     
    230332                link_t *lnk = hash_table_find(&devices, key);
    231333                if (lnk == NULL) {
    232                         device_t *dev = (device_t *) malloc(sizeof(device_t));
    233                         if (dev == NULL) {
    234                                 fibril_mutex_unlock(&devices_mutex);
    235                                 return ENOMEM;
    236                         }
    237                        
    238                         int phone = devmap_device_connect(node->handle, 0);
    239                         if (phone < 0) {
    240                                 fibril_mutex_unlock(&devices_mutex);
    241                                 free(dev);
    242                                 return ENOENT;
    243                         }
    244                        
    245                         dev->handle = node->handle;
    246                         dev->phone = phone;
    247                         dev->refcount = 1;
    248                        
    249                         hash_table_insert(&devices, key, &dev->link);
    250                 } else {
    251                         device_t *dev = hash_table_get_instance(lnk, device_t, link);
    252                         dev->refcount++;
    253                 }
    254                
     334                        fibril_mutex_unlock(&devices_mutex);
     335                        ipc_answer_0(rid, ENOENT);
     336                        return;
     337                }
     338               
     339                device_t *dev = hash_table_get_instance(lnk, device_t, link);
     340               
     341                ipc_callid_t callid;
     342                if (!async_data_read_receive(&callid, NULL)) {
     343                        fibril_mutex_unlock(&devices_mutex);
     344                        ipc_answer_0(callid, EINVAL);
     345                        ipc_answer_0(rid, EINVAL);
     346                        return;
     347                }
     348               
     349                /* Make a request at the driver */
     350                ipc_call_t answer;
     351                aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request),
     352                    IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
     353                    IPC_GET_ARG3(*request), &answer);
     354               
     355                /* Forward the IPC_M_DATA_READ request to the driver */
     356                ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    255357                fibril_mutex_unlock(&devices_mutex);
    256358               
    257                 return EOK;
    258         }
    259        
    260         return ENOENT;
    261 }
    262 
    263 static int devfs_node_put(fs_node_t *fn)
    264 {
    265         free(fn->data);
    266         free(fn);
    267         return EOK;
    268 }
    269 
    270 static int devfs_create_node(fs_node_t **rfn, dev_handle_t dev_handle, int lflag)
    271 {
    272         assert((lflag & L_FILE) ^ (lflag & L_DIRECTORY));
    273        
    274         *rfn = NULL;
    275         return ENOTSUP;
    276 }
    277 
    278 static int devfs_destroy_node(fs_node_t *fn)
    279 {
    280         return ENOTSUP;
    281 }
    282 
    283 static int devfs_link_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
    284 {
    285         return ENOTSUP;
    286 }
    287 
    288 static int devfs_unlink_node(fs_node_t *pfn, fs_node_t *cfn, const char *nm)
    289 {
    290         return ENOTSUP;
    291 }
    292 
    293 static int devfs_has_children(bool *has_children, fs_node_t *fn)
    294 {
    295         devfs_node_t *node = (devfs_node_t *) fn->data;
    296        
    297         if (node->handle == 0) {
    298                 size_t count = devmap_count_namespaces();
    299                 if (count > 0) {
    300                         *has_children = true;
    301                         return EOK;
    302                 }
    303                
    304                 /* Root namespace */
    305                 dev_handle_t namespace;
    306                 if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
    307                         count = devmap_count_devices(namespace);
    308                         if (count > 0) {
    309                                 *has_children = true;
    310                                 return EOK;
    311                         }
    312                 }
    313                
    314                 *has_children = false;
    315                 return EOK;
    316         }
    317        
    318         if (node->type == DEV_HANDLE_NAMESPACE) {
    319                 size_t count = devmap_count_devices(node->handle);
    320                 if (count > 0) {
    321                         *has_children = true;
    322                         return EOK;
    323                 }
    324                
    325                 *has_children = false;
    326                 return EOK;
    327         }
    328        
    329         *has_children = false;
    330         return EOK;
    331 }
    332 
    333 static fs_index_t devfs_index_get(fs_node_t *fn)
    334 {
    335         devfs_node_t *node = (devfs_node_t *) fn->data;
    336         return node->handle;
    337 }
    338 
    339 static size_t devfs_size_get(fs_node_t *fn)
    340 {
    341         return 0;
    342 }
    343 
    344 static unsigned int devfs_lnkcnt_get(fs_node_t *fn)
    345 {
    346         devfs_node_t *node = (devfs_node_t *) fn->data;
    347        
    348         if (node->handle == 0)
    349                 return 0;
    350        
    351         return 1;
    352 }
    353 
    354 static char devfs_plb_get_char(unsigned pos)
    355 {
    356         return devfs_reg.plb_ro[pos % PLB_SIZE];
    357 }
    358 
    359 static bool devfs_is_directory(fs_node_t *fn)
    360 {
    361         devfs_node_t *node = (devfs_node_t *) fn->data;
    362        
    363         return ((node->type == DEV_HANDLE_NONE) || (node->type == DEV_HANDLE_NAMESPACE));
    364 }
    365 
    366 static bool devfs_is_file(fs_node_t *fn)
    367 {
    368         devfs_node_t *node = (devfs_node_t *) fn->data;
    369        
    370         return (node->type == DEV_HANDLE_DEVICE);
    371 }
    372 
    373 static dev_handle_t devfs_device_get(fs_node_t *fn)
    374 {
    375         devfs_node_t *node = (devfs_node_t *) fn->data;
    376        
    377         if (node->type == DEV_HANDLE_DEVICE)
    378                 return node->handle;
    379        
    380         return 0;
    381 }
    382 
    383 /** libfs operations */
    384 libfs_ops_t devfs_libfs_ops = {
    385         .root_get = devfs_root_get,
    386         .match = devfs_match,
    387         .node_get = devfs_node_get,
    388         .node_open = devfs_node_open,
    389         .node_put = devfs_node_put,
    390         .create = devfs_create_node,
    391         .destroy = devfs_destroy_node,
    392         .link = devfs_link_node,
    393         .unlink = devfs_unlink_node,
    394         .has_children = devfs_has_children,
    395         .index_get = devfs_index_get,
    396         .size_get = devfs_size_get,
    397         .lnkcnt_get = devfs_lnkcnt_get,
    398         .plb_get_char = devfs_plb_get_char,
    399         .is_directory = devfs_is_directory,
    400         .is_file = devfs_is_file,
    401         .device_get = devfs_device_get
    402 };
    403 
    404 bool devfs_init(void)
    405 {
    406         if (!hash_table_create(&devices, DEVICES_BUCKETS,
    407             DEVICES_KEYS, &devices_ops))
    408                 return false;
    409        
    410         if (devmap_get_phone(DEVMAP_CLIENT, IPC_FLAG_BLOCKING) < 0)
    411                 return false;
    412        
    413         return true;
    414 }
    415 
    416 void devfs_mounted(ipc_callid_t rid, ipc_call_t *request)
    417 {
    418         char *opts;
    419        
    420         /* Accept the mount options */
    421         ipcarg_t retval = async_data_string_receive(&opts, 0);
    422         if (retval != EOK) {
    423                 ipc_answer_0(rid, retval);
    424                 return;
    425         }
    426        
    427         free(opts);
    428         ipc_answer_3(rid, EOK, 0, 0, 0);
    429 }
    430 
    431 void devfs_mount(ipc_callid_t rid, ipc_call_t *request)
    432 {
    433         libfs_mount(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
    434 }
    435 
    436 void devfs_lookup(ipc_callid_t rid, ipc_call_t *request)
    437 {
    438         libfs_lookup(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
    439 }
    440 
    441 void devfs_open_node(ipc_callid_t rid, ipc_call_t *request)
    442 {
    443         libfs_open_node(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
    444 }
    445 
    446 void devfs_stat(ipc_callid_t rid, ipc_call_t *request)
    447 {
    448         libfs_stat(&devfs_libfs_ops, devfs_reg.fs_handle, rid, request);
    449 }
    450 
    451 void devfs_read(ipc_callid_t rid, ipc_call_t *request)
    452 {
    453         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    454         off_t pos = (off_t) IPC_GET_ARG3(*request);
    455        
    456         if (index == 0) {
     359                /* Wait for reply from the driver. */
     360                ipcarg_t rc;
     361                async_wait_for(msg, &rc);
     362                size_t bytes = IPC_GET_ARG1(answer);
     363               
     364                /* Driver reply is the final result of the whole operation */
     365                ipc_answer_1(rid, rc, bytes);
     366        } else {
    457367                ipc_callid_t callid;
    458368                size_t size;
     
    463373                }
    464374               
    465                 dev_desc_t *desc;
    466                 size_t count = devmap_get_namespaces(&desc);
    467                
    468                 /* Get rid of root namespace */
    469                 size_t i;
    470                 for (i = 0; i < count; i++) {
    471                         if (str_cmp(desc[i].name, "") == 0) {
    472                                 if (pos >= i)
    473                                         pos++;
    474                                
    475                                 break;
    476                         }
    477                 }
    478                
    479                 if (pos < count) {
     375                size_t count = devmap_device_get_count();
     376                dev_desc_t *desc = malloc(count * sizeof(dev_desc_t));
     377                if (desc == NULL) {
     378                        ipc_answer_0(callid, ENOMEM);
     379                        ipc_answer_1(rid, ENOMEM, 0);
     380                        return;
     381                }
     382               
     383                size_t max = devmap_device_get_devices(count, desc);
     384               
     385                if (pos < max) {
    480386                        async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
    481                         free(desc);
    482                         ipc_answer_1(rid, EOK, 1);
     387                } else {
     388                        ipc_answer_0(callid, ENOENT);
     389                        ipc_answer_1(rid, ENOENT, 0);
    483390                        return;
    484391                }
    485392               
    486393                free(desc);
    487                 pos -= count;
    488                
    489                 /* Search root namespace */
    490                 dev_handle_t namespace;
    491                 if (devmap_namespace_get_handle("", &namespace, 0) == EOK) {
    492                         count = devmap_get_devices(namespace, &desc);
    493                        
    494                         if (pos < count) {
    495                                 async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
    496                                 free(desc);
    497                                 ipc_answer_1(rid, EOK, 1);
    498                                 return;
    499                         }
    500                        
    501                         free(desc);
    502                 }
    503                
    504                 ipc_answer_0(callid, ENOENT);
    505                 ipc_answer_1(rid, ENOENT, 0);
    506                 return;
    507         }
    508        
    509         devmap_handle_type_t type = devmap_handle_probe(index);
    510        
    511         if (type == DEV_HANDLE_NAMESPACE) {
    512                 /* Namespace directory */
    513                 ipc_callid_t callid;
    514                 size_t size;
    515                 if (!async_data_read_receive(&callid, &size)) {
    516                         ipc_answer_0(callid, EINVAL);
    517                         ipc_answer_0(rid, EINVAL);
    518                         return;
    519                 }
    520                
    521                 dev_desc_t *desc;
    522                 size_t count = devmap_get_devices(index, &desc);
    523                
    524                 if (pos < count) {
    525                         async_data_read_finalize(callid, desc[pos].name, str_size(desc[pos].name) + 1);
    526                         free(desc);
    527                         ipc_answer_1(rid, EOK, 1);
    528                         return;
    529                 }
    530                
    531                 free(desc);
    532                 ipc_answer_0(callid, ENOENT);
    533                 ipc_answer_1(rid, ENOENT, 0);
    534                 return;
    535         }
    536        
    537         if (type == DEV_HANDLE_DEVICE) {
    538                 /* Device node */
    539                
     394               
     395                ipc_answer_1(rid, EOK, 1);
     396        }
     397}
     398
     399void devfs_write(ipc_callid_t rid, ipc_call_t *request)
     400{
     401        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
     402        off_t pos = (off_t) IPC_GET_ARG3(*request);
     403       
     404        if (index != 0) {
    540405                unsigned long key[] = {
    541406                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     
    553418               
    554419                ipc_callid_t callid;
    555                 if (!async_data_read_receive(&callid, NULL)) {
     420                if (!async_data_write_receive(&callid, NULL)) {
    556421                        fibril_mutex_unlock(&devices_mutex);
    557422                        ipc_answer_0(callid, EINVAL);
     
    566431                    IPC_GET_ARG3(*request), &answer);
    567432               
    568                 /* Forward the IPC_M_DATA_READ request to the driver */
     433                /* Forward the IPC_M_DATA_WRITE request to the driver */
    569434                ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
     435               
    570436                fibril_mutex_unlock(&devices_mutex);
    571437               
     
    577443                /* Driver reply is the final result of the whole operation */
    578444                ipc_answer_1(rid, rc, bytes);
    579                 return;
    580         }
    581        
    582         ipc_answer_0(rid, ENOENT);
    583 }
    584 
    585 void devfs_write(ipc_callid_t rid, ipc_call_t *request)
     445        } else {
     446                /* Read-only filesystem */
     447                ipc_answer_0(rid, ENOTSUP);
     448        }
     449}
     450
     451void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
     452{
     453        ipc_answer_0(rid, ENOTSUP);
     454}
     455
     456void devfs_close(ipc_callid_t rid, ipc_call_t *request)
    586457{
    587458        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    588         off_t pos = (off_t) IPC_GET_ARG3(*request);
    589        
    590         if (index == 0) {
    591                 ipc_answer_0(rid, ENOTSUP);
    592                 return;
    593         }
    594        
    595         devmap_handle_type_t type = devmap_handle_probe(index);
    596        
    597         if (type == DEV_HANDLE_NAMESPACE) {
    598                 /* Namespace directory */
    599                 ipc_answer_0(rid, ENOTSUP);
    600                 return;
    601         }
    602        
    603         if (type == DEV_HANDLE_DEVICE) {
    604                 /* Device node */
     459       
     460        if (index != 0) {
    605461                unsigned long key[] = {
    606462                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     
    616472               
    617473                device_t *dev = hash_table_get_instance(lnk, device_t, link);
    618                
    619                 ipc_callid_t callid;
    620                 if (!async_data_write_receive(&callid, NULL)) {
    621                         fibril_mutex_unlock(&devices_mutex);
    622                         ipc_answer_0(callid, EINVAL);
    623                         ipc_answer_0(rid, EINVAL);
    624                         return;
    625                 }
    626                
    627                 /* Make a request at the driver */
    628                 ipc_call_t answer;
    629                 aid_t msg = async_send_3(dev->phone, IPC_GET_METHOD(*request),
    630                     IPC_GET_ARG1(*request), IPC_GET_ARG2(*request),
    631                     IPC_GET_ARG3(*request), &answer);
    632                
    633                 /* Forward the IPC_M_DATA_WRITE request to the driver */
    634                 ipc_forward_fast(callid, dev->phone, 0, 0, 0, IPC_FF_ROUTE_FROM_ME);
    635                
    636                 fibril_mutex_unlock(&devices_mutex);
    637                
    638                 /* Wait for reply from the driver. */
    639                 ipcarg_t rc;
    640                 async_wait_for(msg, &rc);
    641                 size_t bytes = IPC_GET_ARG1(answer);
    642                
    643                 /* Driver reply is the final result of the whole operation */
    644                 ipc_answer_1(rid, rc, bytes);
    645                 return;
    646         }
    647        
    648         ipc_answer_0(rid, ENOENT);
    649 }
    650 
    651 void devfs_truncate(ipc_callid_t rid, ipc_call_t *request)
    652 {
    653         ipc_answer_0(rid, ENOTSUP);
    654 }
    655 
    656 void devfs_close(ipc_callid_t rid, ipc_call_t *request)
    657 {
    658         fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    659        
    660         if (index == 0) {
    661                 ipc_answer_0(rid, EOK);
    662                 return;
    663         }
    664        
    665         devmap_handle_type_t type = devmap_handle_probe(index);
    666        
    667         if (type == DEV_HANDLE_NAMESPACE) {
    668                 /* Namespace directory */
    669                 ipc_answer_0(rid, EOK);
    670                 return;
    671         }
    672        
    673         if (type == DEV_HANDLE_DEVICE) {
    674                 unsigned long key[] = {
    675                         [DEVICES_KEY_HANDLE] = (unsigned long) index
    676                 };
    677                
    678                 fibril_mutex_lock(&devices_mutex);
    679                 link_t *lnk = hash_table_find(&devices, key);
    680                 if (lnk == NULL) {
    681                         fibril_mutex_unlock(&devices_mutex);
    682                         ipc_answer_0(rid, ENOENT);
    683                         return;
    684                 }
    685                
    686                 device_t *dev = hash_table_get_instance(lnk, device_t, link);
    687474                dev->refcount--;
    688475               
     
    695482               
    696483                ipc_answer_0(rid, EOK);
    697                 return;
    698         }
    699        
    700         ipc_answer_0(rid, ENOENT);
     484        } else
     485                ipc_answer_0(rid, ENOTSUP);
    701486}
    702487
     
    705490        fs_index_t index = (fs_index_t) IPC_GET_ARG2(*request);
    706491       
    707         if (index == 0) {
    708                 ipc_answer_0(rid, EOK);
    709                 return;
    710         }
    711        
    712         devmap_handle_type_t type = devmap_handle_probe(index);
    713        
    714         if (type == DEV_HANDLE_NAMESPACE) {
    715                 /* Namespace directory */
    716                 ipc_answer_0(rid, EOK);
    717                 return;
    718         }
    719        
    720         if (type == DEV_HANDLE_DEVICE) {
     492        if (index != 0) {
    721493                unsigned long key[] = {
    722494                        [DEVICES_KEY_HANDLE] = (unsigned long) index
     
    746518                /* Driver reply is the final result of the whole operation */
    747519                ipc_answer_0(rid, rc);
    748                 return;
    749         }
    750        
    751         ipc_answer_0(rid, ENOENT);
     520        } else
     521                ipc_answer_0(rid, ENOTSUP);
    752522}
    753523
Note: See TracChangeset for help on using the changeset viewer.