source: trunk/kernel/fs/devfs.c @ 421

Last change on this file since 421 was 407, checked in by alain, 7 years ago

First implementation of fork/exec.

File size: 16.6 KB
RevLine 
[23]1/*
2 * devfs.c - DEVFS File system API implementation.
3 *
4 * Author   Mohamed Lamine Karaoui (2014,2015)
5 *          Alain Greiner (2016,2017)
6 *
7 * Copyright (c) Sorbonne Universites
8 *
9 * This file is part of ALMOS-MKH.
10 *
11 * ALMOS-MKH is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; version 2.0 of the License.
14 *
15 * ALMOS-MKH is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with ALMOS-MKH; if not, write to the Free Software Foundation,
22 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24
25#include <hal_types.h>
26#include <hal_special.h>
[407]27#include <hal_uspace.h>
[23]28#include <printk.h>
29#include <chdev.h>
[407]30#include <dev_txt.h>
[188]31#include <cluster.h>
[23]32#include <vfs.h>
[188]33#include <kmem.h>
[23]34#include <devfs.h>
35
[188]36/////////////////////////////////////////////////////////////////////////////////////////
37//     Extern variables
38/////////////////////////////////////////////////////////////////////////////////////////
[23]39
[188]40extern vfs_ctx_t            fs_context[];   // allocated in kernel_init.c
41extern chdev_directory_t    chdev_dir;      // allocated in kernel_init.c
[23]42
[407]43#if CONFIG_READ_DEBUG
44extern uint32_t  enter_devfs_move;
45extern uint32_t  exit_devfs_move;
46#endif
47
[188]48///////////////////////////////
49devfs_ctx_t * devfs_ctx_alloc()
50{
51    kmem_req_t    req;
[23]52
[188]53        req.type    = KMEM_DEVFS_CTX;
54        req.size    = sizeof(devfs_ctx_t);
55    req.flags   = AF_KERNEL | AF_ZERO;
[23]56
[188]57        return (devfs_ctx_t *)kmem_alloc( &req );
58}
[23]59
[188]60/////////////////////////////////////////////
61void devfs_ctx_init( devfs_ctx_t * devfs_ctx,
[204]62                     xptr_t        devfs_dev_inode_xp,
[188]63                     xptr_t        devfs_external_inode_xp )
[23]64{
[204]65    devfs_ctx->dev_inode_xp      = devfs_dev_inode_xp;
[188]66    devfs_ctx->external_inode_xp = devfs_external_inode_xp;
[23]67
[188]68    fs_context[FS_TYPE_DEVFS].extend = devfs_ctx;
69}
[23]70
[188]71/////////////////////////////////////////////////
72void devfs_ctx_destroy( devfs_ctx_t * devfs_ctx )
73{
74    kmem_req_t    req;
[23]75
[188]76    req.type = KMEM_DEVFS_CTX;
77    req.ptr  = devfs_ctx;
78    kmem_free( &req );
79}
[23]80
[188]81///////////////////////////////////////////////////
82void devfs_global_init( xptr_t   parent_inode_xp,
[204]83                        xptr_t * devfs_dev_inode_xp,
[188]84                        xptr_t * devfs_external_inode_xp )
[23]85{
86    error_t  error;
87
[407]88    devfs_dmsg("\n[DBG] %s : enter in cluster %x\n",
[279]89               __FUNCTION__ , local_cxy );
90
[188]91    // creates DEVFS "dev" inode in cluster IO
92    error = vfs_add_child_in_parent( LOCAL_CLUSTER->io_cxy,
93                                     INODE_TYPE_DIR,
94                                     FS_TYPE_DEVFS,
95                                     parent_inode_xp,
96                                     "dev",
97                                     NULL,
[204]98                                     devfs_dev_inode_xp ); 
[23]99
[279]100    assert( (error == 0) , __FUNCTION__ , "cannot create <dev>\n" );
[23]101
[407]102    devfs_dmsg("\n[DBG] %s : <dev> created in cluster %x\n",
[279]103               __FUNCTION__ , local_cxy );
104
[188]105    // create DEVFS "external" inode in cluster IO
106    error = vfs_add_child_in_parent( LOCAL_CLUSTER->io_cxy,
107                                     INODE_TYPE_DIR,
108                                     FS_TYPE_DEVFS,
[204]109                                     *devfs_dev_inode_xp,
110                                     "external",
[188]111                                     NULL,
112                                     devfs_external_inode_xp ); 
[23]113
[279]114    assert( (error == 0) , __FUNCTION__ , "cannot create <external>\n" );
115
[407]116    devfs_dmsg("\n[DBG] %s : <external> created in cluster %x\n",
[279]117               __FUNCTION__ , local_cxy );
[188]118} 
[23]119
[204]120///////////////////////////////////////////////////
121void devfs_local_init( xptr_t   devfs_dev_inode_xp,
122                       xptr_t   devfs_external_inode_xp,
123                       xptr_t * devfs_internal_inode_xp )
[23]124{
125    char          node_name[16];
[188]126    xptr_t        chdev_xp;
127    cxy_t         chdev_cxy;
[407]128    chdev_t     * chdev_ptr;
[188]129    xptr_t        inode_xp;
[23]130    uint32_t      channel;
131
[188]132    // create "internal" directory linked to "dev"
133    snprintf( node_name , 16 , "internal_%x" , local_cxy );
134    vfs_add_child_in_parent( local_cxy,
135                             INODE_TYPE_DIR,
136                             FS_TYPE_DEVFS,
[204]137                             devfs_dev_inode_xp,
[188]138                             node_name,
139                             NULL,
[204]140                             devfs_internal_inode_xp );
[23]141
[407]142devfs_dmsg("\n[DBG] %s : created <%s> inode in cluster %x\n",
143__FUNCTION__ , node_name , local_cxy );
144
[23]145    // create MMC chdev inode
[407]146    chdev_xp  = chdev_dir.mmc[local_cxy];
[188]147    if( chdev_xp != XPTR_NULL)
148    {
[407]149        chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]150        vfs_add_child_in_parent( local_cxy,
151                                 INODE_TYPE_DEV,
152                                 FS_TYPE_DEVFS,
[204]153                                 *devfs_internal_inode_xp,
[407]154                                 chdev_ptr->name,
[188]155                                 GET_PTR( chdev_xp ),
156                                 &inode_xp );
[407]157
158devfs_dmsg("\n[DBG] %s : created <%s> inode in cluster %x\n",
159__FUNCTION__ , chdev_ptr->name , local_cxy );
160
[188]161    }
[23]162
163    // create DMA chdev inodes (one DMA channel per core)
[188]164    for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ )
[23]165    {
[188]166        chdev_xp = chdev_dir.dma[channel];
167        if( chdev_xp != XPTR_NULL)
168        {
[407]169            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]170            vfs_add_child_in_parent( local_cxy,
171                                     INODE_TYPE_DEV,
172                                     FS_TYPE_DEVFS,
[204]173                                     *devfs_internal_inode_xp,
[407]174                                     chdev_ptr->name,
[188]175                                     GET_PTR( chdev_xp ),
176                                     &inode_xp );
[407]177
178devfs_dmsg("\n[DBG] %s : created <%s> inode in cluster %x\n",
179__FUNCTION__ , chdev_ptr->name , local_cxy );
180
[188]181        }
[23]182    }
183
[188]184    // create an IOB inode in cluster containing IOB chdev
185    chdev_xp = chdev_dir.iob;
186    if( chdev_xp != XPTR_NULL )
[23]187    {
[188]188        chdev_cxy = GET_CXY( chdev_xp );
[407]189        chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]190        if( chdev_cxy == local_cxy )
191        {
192            vfs_add_child_in_parent( local_cxy,
193                                     INODE_TYPE_DEV,
194                                     FS_TYPE_DEVFS,
195                                     devfs_external_inode_xp,
[407]196                                     chdev_ptr->name,
[188]197                                     GET_PTR( chdev_xp ),
198                                     &inode_xp );
[407]199
200devfs_dmsg("\n[DBG] %s : created <%s> inode in cluster %x\n",
201__FUNCTION__ , chdev_ptr->name , local_cxy );
202
[188]203        }
204    }
[23]205       
[188]206    // create a PIC inode in cluster containing PIC chdev
207    chdev_xp = chdev_dir.pic;
208    if( chdev_xp != XPTR_NULL )
209    {
210        chdev_cxy = GET_CXY( chdev_xp );
[407]211        chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]212        if( chdev_cxy == local_cxy )
[23]213        {
[188]214            vfs_add_child_in_parent( local_cxy,
215                                     INODE_TYPE_DEV,
216                                     FS_TYPE_DEVFS,
217                                     devfs_external_inode_xp,
[407]218                                     chdev_ptr->name,
[188]219                                     GET_PTR( chdev_xp ),
220                                     &inode_xp );
[407]221
222devfs_dmsg("\n[DBG] %s : created <%s> inode in cluster %x\n",
223__FUNCTION__ , chdev_ptr->name , local_cxy );
224
[23]225        }
[188]226    }
[23]227
[407]228    // create a TXT_RX inode in each cluster containing a TXT_RX chdev
[188]229    for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
230    {
[407]231        chdev_xp = chdev_dir.txt_rx[channel];
[188]232        if( chdev_xp != XPTR_NULL )
[23]233        {
[188]234            chdev_cxy = GET_CXY( chdev_xp );
[407]235            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]236            if( chdev_cxy == local_cxy )
237            {
238                vfs_add_child_in_parent( local_cxy,
239                                         INODE_TYPE_DEV,
240                                         FS_TYPE_DEVFS,
241                                         devfs_external_inode_xp,
[407]242                                         chdev_ptr->name,
[188]243                                         GET_PTR( chdev_xp ),
244                                         &inode_xp );
[407]245
246devfs_dmsg("\n[DBG] %s : created <%s> inode in cluster %x\n",
247__FUNCTION__ , chdev_ptr->name , local_cxy );
248
[188]249            }
[23]250        }
[188]251    }
[23]252
[407]253    // create a TXT_TX inode in each cluster containing a TXT_TX chdev
254    for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
255    {
256        chdev_xp = chdev_dir.txt_tx[channel];
257        if( chdev_xp != XPTR_NULL )
258        {
259            chdev_cxy = GET_CXY( chdev_xp );
260            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
261            if( chdev_cxy == local_cxy )
262            {
263                vfs_add_child_in_parent( local_cxy,
264                                         INODE_TYPE_DEV,
265                                         FS_TYPE_DEVFS,
266                                         devfs_external_inode_xp,
267                                         chdev_ptr->name,
268                                         GET_PTR( chdev_xp ),
269                                         &inode_xp );
270
271devfs_dmsg("\n[DBG] %s : created <%s> inode in cluster %x\n",
272__FUNCTION__ , chdev_ptr->name , local_cxy );
273
274            }
275        }
276    }
277
[188]278    // create an IOC inode in each cluster containing an IOC chdev
279    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
280    {
281        chdev_xp = chdev_dir.ioc[channel];
282        if( chdev_xp != XPTR_NULL )
[23]283        {
[188]284            chdev_cxy = GET_CXY( chdev_xp );
[407]285            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]286            if( chdev_cxy == local_cxy )
287            {
288                vfs_add_child_in_parent( local_cxy,
289                                         INODE_TYPE_DEV,
290                                         FS_TYPE_DEVFS,
291                                         devfs_external_inode_xp,
[407]292                                         chdev_ptr->name,
[188]293                                         GET_PTR( chdev_xp ),
294                                         &inode_xp );
[407]295
296devfs_dmsg("\n[DBG] %s : created <%s> inode in cluster %x\n",
297__FUNCTION__ , chdev_ptr->name , local_cxy );
298
[188]299            }
[23]300        }
[188]301    }
[23]302
[188]303    // create a FBF inode in each cluster containing a FBF chdev
304    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
305    {
306        chdev_xp = chdev_dir.fbf[channel];
307        if( chdev_xp != XPTR_NULL )
[23]308        {
[188]309            chdev_cxy = GET_CXY( chdev_xp );
[407]310            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]311            if( chdev_cxy == local_cxy )
312            {
313                vfs_add_child_in_parent( local_cxy,
314                                         INODE_TYPE_DEV,
315                                         FS_TYPE_DEVFS,
316                                         devfs_external_inode_xp,
[407]317                                         chdev_ptr->name,
[188]318                                         GET_PTR( chdev_xp ),
319                                         &inode_xp );
[407]320
321devfs_dmsg("\n[DBG] %s : created <%s> inode in cluster %x\n",
322__FUNCTION__ , chdev_ptr->name , local_cxy );
323
[188]324            }
[23]325        }
[188]326    }
[23]327
[188]328    // create a NIC_RX inode in each cluster containing a NIC_RX chdev
329    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
330    {
331        chdev_xp = chdev_dir.nic_rx[channel];
332        if( chdev_xp != XPTR_NULL )
[23]333        {
[188]334            chdev_cxy = GET_CXY( chdev_xp );
[407]335            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]336            if( chdev_cxy == local_cxy )
337            {
338                vfs_add_child_in_parent( local_cxy,
339                                         INODE_TYPE_DEV,
340                                         FS_TYPE_DEVFS,
341                                         devfs_external_inode_xp,
[407]342                                         chdev_ptr->name,
[188]343                                         GET_PTR( chdev_xp ),
344                                         &inode_xp );
[407]345
346devfs_dmsg("\n[DBG] %s : created <%s> inode in cluster %x\n",
347__FUNCTION__ , chdev_ptr->name , local_cxy );
348
[188]349            }
[23]350        }
351    }
352
[188]353    // create a NIC_TX inode in each cluster containing a NIC_TX chdev
354    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
[23]355    {
[188]356        chdev_xp = chdev_dir.nic_tx[channel];
357        if( chdev_xp != XPTR_NULL )
358        {
359            chdev_cxy = GET_CXY( chdev_xp );
[407]360            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]361            if( chdev_cxy == local_cxy )
362            {
363                vfs_add_child_in_parent( local_cxy,
364                                         INODE_TYPE_DEV,
365                                         FS_TYPE_DEVFS,
366                                         devfs_external_inode_xp,
[407]367                                         chdev_ptr->name,
[188]368                                         GET_PTR( chdev_xp ),
369                                         &inode_xp );
[407]370
371devfs_dmsg("\n[DBG] %s : created <%s> inode in cluster %x\n",
372__FUNCTION__ , chdev_ptr->name , local_cxy );
373
[188]374            }
375        }
[23]376    }
[188]377}  // end devfs_local_init()
[23]378
[407]379//////////////////////////////////////////
380int devfs_user_move( bool_t     to_buffer,
381                     xptr_t     file_xp,
382                     void     * u_buf,
383                     uint32_t   size )
384{
385    assert( ( file_xp != XPTR_NULL ) , __FUNCTION__ , "file_xp == XPTR_NULL" );
386
387    assert( ( size < CONFIG_TXT_KBUF_SIZE ) , __FUNCTION__ , "string size too large" );
388
389    cxy_t              file_cxy;     // remote file descriptor cluster
390    vfs_file_t       * file_ptr;     // remote file descriptor local pointer
391    vfs_inode_type_t   inode_type;   // associated inode type
392    vfs_inode_t      * inode_ptr;    // associated inode local pointer
393    chdev_t          * chdev_ptr;    // associated chdev type
394    uint32_t           func;         // chdev functionnal type
395    uint32_t           channel;      // chdev channel index
396    error_t            error;
397
398    char               k_buf[CONFIG_TXT_KBUF_SIZE];  // local kernel buffer
399
400devfs_dmsg("\n[DBG] %s enter / cycle %d\n", 
401__FUNCTION__ , hal_time_stamp() );
402
403#if CONFIG_READ_DEBUG
404enter_devfs_move = hal_time_stamp();
405#endif
406
407    // get cluster and local pointer on remote file descriptor
408    // associated inode and chdev are stored in same cluster as the file desc.
409    file_cxy  = GET_CXY( file_xp );
410    file_ptr  = (vfs_file_t *)GET_PTR( file_xp );
411
412    // get inode type from remote file descriptor
413    inode_type = hal_remote_lw( XPTR( file_cxy , &file_ptr->type ) );
414    inode_ptr  = (vfs_inode_t *)hal_remote_lpt( XPTR( file_cxy , &file_ptr->inode ) );
415
416    assert( (inode_type == INODE_TYPE_DEV) , __FUNCTION__ ,
417    "inode type is not INODE_TYPE_DEV" );
418
419    // get chdev local pointer from remote inode extension
420    chdev_ptr = (chdev_t *)hal_remote_lpt( XPTR( file_cxy , &inode_ptr->extend ) );
421 
422    // get chdev functionnal type and channel
423    func    = hal_remote_lw( XPTR( file_cxy , &chdev_ptr->func ) );
424    channel = hal_remote_lw( XPTR( file_cxy , &chdev_ptr->channel ) );
425
426    // action depends on "func" and "to_buffer"
427    if( func == DEV_FUNC_TXT )
428    {
429        if( to_buffer )     // TXT read
430        { 
431            uint32_t i;
432            for( i = 0 ; i < size ; i++ )
433            {
434                error = dev_txt_read( channel , &k_buf[i] );
435
436                if( error ) 
437                {
438
439devfs_dmsg("\n[DBG] %s exit error / cycle %d\n", 
440__FUNCTION__ , hal_time_stamp() );
441
442                    return -1;
443                }
444                else
445                {
446                    hal_strcpy_to_uspace( u_buf , k_buf , size );
447                }
448             }
449
450#if CONFIG_READ_DEBUG
451exit_devfs_move = hal_time_stamp();
452#endif
453
454devfs_dmsg("\n[DBG] %s exit success / size = %d / cycle %d\n", 
455__FUNCTION__ , size , hal_time_stamp() );
456
457            return size;
458        } 
459        else                // TXT write 
460        {
461            hal_strcpy_from_uspace( k_buf , u_buf , size );
462
463            error = dev_txt_write( channel , k_buf , size );
464            if( error ) 
465            {
466
467devfs_dmsg("\n[DBG] %s exit error / cycle %d\n", 
468__FUNCTION__ , hal_time_stamp() );
469
470                return -1;
471            }
472            else
473            {
474
475devfs_dmsg("\n[DBG] %s exit success / size = %d / cycle %d\n", 
476__FUNCTION__ , size , hal_time_stamp() );
477
478                return size;
479            }
480        }
481    }
482    else
483    {
484        panic("device type %s does not support direct user access", chdev_func_str(func) );
485
486        return -1;
487    }
488}  // end devfs_user_move()
489
490
Note: See TracBrowser for help on using the repository browser.