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

Last change on this file since 435 was 435, checked in by alain, 6 years ago

Fix a bad bug in scheduler...

File size: 15.8 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>
[433]30#include <thread.h>
[407]31#include <dev_txt.h>
[188]32#include <cluster.h>
[23]33#include <vfs.h>
[188]34#include <kmem.h>
[23]35#include <devfs.h>
36
[188]37/////////////////////////////////////////////////////////////////////////////////////////
38//     Extern variables
39/////////////////////////////////////////////////////////////////////////////////////////
[23]40
[188]41extern vfs_ctx_t            fs_context[];   // allocated in kernel_init.c
42extern chdev_directory_t    chdev_dir;      // allocated in kernel_init.c
[23]43
[435]44#if (CONFIG_DEBUG_SYS_READ & 1)
45extern uint32_t  enter_devfs_read;
46extern uint32_t  exit_devfs_read;
[407]47#endif
48
[435]49#if (CONFIG_DEBUG_SYS_WRITE & 1)
50extern uint32_t  enter_devfs_write;
51extern uint32_t  exit_devfs_write;
52#endif
53
[188]54///////////////////////////////
55devfs_ctx_t * devfs_ctx_alloc()
56{
57    kmem_req_t    req;
[23]58
[188]59        req.type    = KMEM_DEVFS_CTX;
60        req.size    = sizeof(devfs_ctx_t);
61    req.flags   = AF_KERNEL | AF_ZERO;
[23]62
[188]63        return (devfs_ctx_t *)kmem_alloc( &req );
64}
[23]65
[188]66/////////////////////////////////////////////
67void devfs_ctx_init( devfs_ctx_t * devfs_ctx,
[204]68                     xptr_t        devfs_dev_inode_xp,
[188]69                     xptr_t        devfs_external_inode_xp )
[23]70{
[204]71    devfs_ctx->dev_inode_xp      = devfs_dev_inode_xp;
[188]72    devfs_ctx->external_inode_xp = devfs_external_inode_xp;
[23]73
[188]74    fs_context[FS_TYPE_DEVFS].extend = devfs_ctx;
75}
[23]76
[188]77/////////////////////////////////////////////////
78void devfs_ctx_destroy( devfs_ctx_t * devfs_ctx )
79{
80    kmem_req_t    req;
[23]81
[188]82    req.type = KMEM_DEVFS_CTX;
83    req.ptr  = devfs_ctx;
84    kmem_free( &req );
85}
[23]86
[188]87///////////////////////////////////////////////////
88void devfs_global_init( xptr_t   parent_inode_xp,
[204]89                        xptr_t * devfs_dev_inode_xp,
[188]90                        xptr_t * devfs_external_inode_xp )
[23]91{
92    error_t  error;
93
[433]94#if CONFIG_DEBUG_DEVFS_INIT
95uint32_t cycle = (uint32_t)hal_get_cycles();
96if( CONFIG_DEBUG_DEVFS_INIT < cycle )
97printk("\n[DBG] %s : thread %x enter at cycle %d\n",
98__FUNCTION__ , CURRENT_THREAD , cycle );
99#endif
[279]100
[188]101    // creates DEVFS "dev" inode in cluster IO
102    error = vfs_add_child_in_parent( LOCAL_CLUSTER->io_cxy,
103                                     INODE_TYPE_DIR,
104                                     FS_TYPE_DEVFS,
105                                     parent_inode_xp,
106                                     "dev",
107                                     NULL,
[204]108                                     devfs_dev_inode_xp ); 
[23]109
[279]110    assert( (error == 0) , __FUNCTION__ , "cannot create <dev>\n" );
[23]111
[188]112    // create DEVFS "external" inode in cluster IO
113    error = vfs_add_child_in_parent( LOCAL_CLUSTER->io_cxy,
114                                     INODE_TYPE_DIR,
115                                     FS_TYPE_DEVFS,
[204]116                                     *devfs_dev_inode_xp,
117                                     "external",
[188]118                                     NULL,
119                                     devfs_external_inode_xp ); 
[23]120
[279]121    assert( (error == 0) , __FUNCTION__ , "cannot create <external>\n" );
122
[433]123#if CONFIG_DEBUG_DEVFS_INIT
124cycle = (uint32_t)hal_get_cycles();
125if( CONFIG_DEBUG_DEVFS_INIT < cycle )
126printk("\n[DBG] %s : thread %x exit at cycle %d\n",
127__FUNCTION__ , CURRENT_THREAD , cycle );
128#endif
129
[188]130} 
[23]131
[204]132///////////////////////////////////////////////////
133void devfs_local_init( xptr_t   devfs_dev_inode_xp,
134                       xptr_t   devfs_external_inode_xp,
135                       xptr_t * devfs_internal_inode_xp )
[23]136{
137    char          node_name[16];
[188]138    xptr_t        chdev_xp;
139    cxy_t         chdev_cxy;
[407]140    chdev_t     * chdev_ptr;
[188]141    xptr_t        inode_xp;
[23]142    uint32_t      channel;
143
[433]144#if CONFIG_DEBUG_DEVFS_INIT
145uint32_t cycle = (uint32_t)hal_get_cycles();
146if( CONFIG_DEBUG_DEVFS_INIT < cycle )
147printk("\n[DBG] %s : thread %x enter at cycle %d\n",
148__FUNCTION__ , CURRENT_THREAD , cycle );
149#endif
150
[188]151    // create "internal" directory linked to "dev"
152    snprintf( node_name , 16 , "internal_%x" , local_cxy );
153    vfs_add_child_in_parent( local_cxy,
154                             INODE_TYPE_DIR,
155                             FS_TYPE_DEVFS,
[204]156                             devfs_dev_inode_xp,
[188]157                             node_name,
158                             NULL,
[204]159                             devfs_internal_inode_xp );
[23]160
161    // create MMC chdev inode
[407]162    chdev_xp  = chdev_dir.mmc[local_cxy];
[188]163    if( chdev_xp != XPTR_NULL)
164    {
[407]165        chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]166        vfs_add_child_in_parent( local_cxy,
167                                 INODE_TYPE_DEV,
168                                 FS_TYPE_DEVFS,
[204]169                                 *devfs_internal_inode_xp,
[407]170                                 chdev_ptr->name,
[188]171                                 GET_PTR( chdev_xp ),
172                                 &inode_xp );
173    }
[23]174
175    // create DMA chdev inodes (one DMA channel per core)
[188]176    for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ )
[23]177    {
[188]178        chdev_xp = chdev_dir.dma[channel];
179        if( chdev_xp != XPTR_NULL)
180        {
[407]181            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]182            vfs_add_child_in_parent( local_cxy,
183                                     INODE_TYPE_DEV,
184                                     FS_TYPE_DEVFS,
[204]185                                     *devfs_internal_inode_xp,
[407]186                                     chdev_ptr->name,
[188]187                                     GET_PTR( chdev_xp ),
188                                     &inode_xp );
189        }
[23]190    }
191
[188]192    // create an IOB inode in cluster containing IOB chdev
193    chdev_xp = chdev_dir.iob;
194    if( chdev_xp != XPTR_NULL )
[23]195    {
[188]196        chdev_cxy = GET_CXY( chdev_xp );
[407]197        chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]198        if( chdev_cxy == local_cxy )
199        {
200            vfs_add_child_in_parent( local_cxy,
201                                     INODE_TYPE_DEV,
202                                     FS_TYPE_DEVFS,
203                                     devfs_external_inode_xp,
[407]204                                     chdev_ptr->name,
[188]205                                     GET_PTR( chdev_xp ),
206                                     &inode_xp );
207        }
208    }
[23]209       
[188]210    // create a PIC inode in cluster containing PIC chdev
211    chdev_xp = chdev_dir.pic;
212    if( chdev_xp != XPTR_NULL )
213    {
214        chdev_cxy = GET_CXY( chdev_xp );
[407]215        chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]216        if( chdev_cxy == local_cxy )
[23]217        {
[188]218            vfs_add_child_in_parent( local_cxy,
219                                     INODE_TYPE_DEV,
220                                     FS_TYPE_DEVFS,
221                                     devfs_external_inode_xp,
[407]222                                     chdev_ptr->name,
[188]223                                     GET_PTR( chdev_xp ),
224                                     &inode_xp );
[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 );
245            }
[23]246        }
[188]247    }
[23]248
[407]249    // create a TXT_TX inode in each cluster containing a TXT_TX chdev
250    for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
251    {
252        chdev_xp = chdev_dir.txt_tx[channel];
253        if( chdev_xp != XPTR_NULL )
254        {
255            chdev_cxy = GET_CXY( chdev_xp );
256            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
257            if( chdev_cxy == local_cxy )
258            {
259                vfs_add_child_in_parent( local_cxy,
260                                         INODE_TYPE_DEV,
261                                         FS_TYPE_DEVFS,
262                                         devfs_external_inode_xp,
263                                         chdev_ptr->name,
264                                         GET_PTR( chdev_xp ),
265                                         &inode_xp );
266            }
267        }
268    }
269
[188]270    // create an IOC inode in each cluster containing an IOC chdev
271    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
272    {
273        chdev_xp = chdev_dir.ioc[channel];
274        if( chdev_xp != XPTR_NULL )
[23]275        {
[188]276            chdev_cxy = GET_CXY( chdev_xp );
[407]277            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]278            if( chdev_cxy == local_cxy )
279            {
280                vfs_add_child_in_parent( local_cxy,
281                                         INODE_TYPE_DEV,
282                                         FS_TYPE_DEVFS,
283                                         devfs_external_inode_xp,
[407]284                                         chdev_ptr->name,
[188]285                                         GET_PTR( chdev_xp ),
286                                         &inode_xp );
287            }
[23]288        }
[188]289    }
[23]290
[188]291    // create a FBF inode in each cluster containing a FBF chdev
292    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
293    {
294        chdev_xp = chdev_dir.fbf[channel];
295        if( chdev_xp != XPTR_NULL )
[23]296        {
[188]297            chdev_cxy = GET_CXY( chdev_xp );
[407]298            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]299            if( chdev_cxy == local_cxy )
300            {
301                vfs_add_child_in_parent( local_cxy,
302                                         INODE_TYPE_DEV,
303                                         FS_TYPE_DEVFS,
304                                         devfs_external_inode_xp,
[407]305                                         chdev_ptr->name,
[188]306                                         GET_PTR( chdev_xp ),
307                                         &inode_xp );
308            }
[23]309        }
[188]310    }
[23]311
[188]312    // create a NIC_RX inode in each cluster containing a NIC_RX chdev
313    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
314    {
315        chdev_xp = chdev_dir.nic_rx[channel];
316        if( chdev_xp != XPTR_NULL )
[23]317        {
[188]318            chdev_cxy = GET_CXY( chdev_xp );
[407]319            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]320            if( chdev_cxy == local_cxy )
321            {
322                vfs_add_child_in_parent( local_cxy,
323                                         INODE_TYPE_DEV,
324                                         FS_TYPE_DEVFS,
325                                         devfs_external_inode_xp,
[407]326                                         chdev_ptr->name,
[188]327                                         GET_PTR( chdev_xp ),
328                                         &inode_xp );
329            }
[23]330        }
331    }
332
[188]333    // create a NIC_TX inode in each cluster containing a NIC_TX chdev
334    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
[23]335    {
[188]336        chdev_xp = chdev_dir.nic_tx[channel];
337        if( chdev_xp != XPTR_NULL )
338        {
339            chdev_cxy = GET_CXY( chdev_xp );
[407]340            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]341            if( chdev_cxy == local_cxy )
342            {
343                vfs_add_child_in_parent( local_cxy,
344                                         INODE_TYPE_DEV,
345                                         FS_TYPE_DEVFS,
346                                         devfs_external_inode_xp,
[407]347                                         chdev_ptr->name,
[188]348                                         GET_PTR( chdev_xp ),
349                                         &inode_xp );
350            }
351        }
[23]352    }
[433]353
354#if CONFIG_DEBUG_DEVFS_INIT
355cycle = (uint32_t)hal_get_cycles();
356if( CONFIG_DEBUG_DEVFS_INIT < cycle )
357printk("\n[DBG] %s : thread %x exit at cycle %d\n",
358__FUNCTION__ , CURRENT_THREAD , cycle );
359#endif
360
[188]361}  // end devfs_local_init()
[23]362
[407]363//////////////////////////////////////////
364int devfs_user_move( bool_t     to_buffer,
365                     xptr_t     file_xp,
366                     void     * u_buf,
367                     uint32_t   size )
368{
369    assert( ( file_xp != XPTR_NULL ) , __FUNCTION__ , "file_xp == XPTR_NULL" );
370
371    assert( ( size < CONFIG_TXT_KBUF_SIZE ) , __FUNCTION__ , "string size too large" );
372
[430]373    xptr_t             chdev_xp;
374    cxy_t              chdev_cxy;
[407]375    chdev_t          * chdev_ptr;    // associated chdev type
376    uint32_t           func;         // chdev functionnal type
377    uint32_t           channel;      // chdev channel index
378    error_t            error;
379
380    char               k_buf[CONFIG_TXT_KBUF_SIZE];  // local kernel buffer
381
[435]382#if (CONFIG_DEBUG_SYS_READ & 1)
383enter_devfs_read = hal_time_stamp();
384#endif
385
386#if (CONFIG_DEBUG_SYS_WRITE & 1)
387enter_devfs_write = hal_time_stamp();
388#endif
389
[433]390#if CONFIG_DEBUG_DEVFS_MOVE
391uint32_t cycle = (uint32_t)hal_get_cycles();
392if( CONFIG_DEBUG_DEVFS_MOVE < cycle )
393printk("\n[DBG] %s : thread %x enter / to_mem %d / cycle %d\n",
394__FUNCTION__ , CURRENT_THREAD , to_buffer , cycle );
395#endif
[407]396
[430]397    // get extended pointer on chdev_xp
398    chdev_xp = chdev_from_file( file_xp );
[407]399
[430]400    // get cluster and local pointer on chdev
401    chdev_cxy  = GET_CXY( chdev_xp );
402    chdev_ptr  = (chdev_t *)GET_PTR( chdev_xp );
[407]403
404    // get chdev functionnal type and channel
[430]405    func    = hal_remote_lw( XPTR( chdev_cxy , &chdev_ptr->func ) );
406    channel = hal_remote_lw( XPTR( chdev_cxy , &chdev_ptr->channel ) );
[407]407
408    // action depends on "func" and "to_buffer"
409    if( func == DEV_FUNC_TXT )
410    {
411        if( to_buffer )     // TXT read
412        { 
413            uint32_t i;
414            for( i = 0 ; i < size ; i++ )
415            {
416                error = dev_txt_read( channel , &k_buf[i] );
417
418                if( error ) 
419                {
420                    return -1;
421                }
422                else
423                {
424                    hal_strcpy_to_uspace( u_buf , k_buf , size );
425                }
426             }
427
[433]428#if CONFIG_DEBUG_DEVFS_MOVE
429cycle = (uint32_t)hal_get_cycles();
430if( CONFIG_DEBUG_DEVFS_MOVE < cycle )
431printk("\n[DBG] %s : thread %x exit / to_mem %d / cycle %d\n",
432__FUNCTION__ , CURRENT_THREAD , to_buffer / cycle );
433#endif
434
[435]435#if (CONFIG_DEBUG_SYS_READ & 1)
436exit_devfs_read = hal_time_stamp();
[407]437#endif
438            return size;
439        } 
440        else                // TXT write 
441        {
442            hal_strcpy_from_uspace( k_buf , u_buf , size );
443
444            error = dev_txt_write( channel , k_buf , size );
445            if( error ) 
446            {
447                return -1;
448            }
449            else
450            {
451
[433]452#if CONFIG_DEBUG_DEVFS_MOVE
453cycle = (uint32_t)hal_get_cycles();
454if( CONFIG_DEBUG_DEVFS_MOVE < cycle )
455printk("\n[DBG] %s : thread %x exit / to_mem %d / cycle %d\n",
456__FUNCTION__ , CURRENT_THREAD , to_buffer / cycle );
457#endif
[407]458
[435]459#if (CONFIG_DEBUG_SYS_WRITE & 1)
460exit_devfs_write = hal_time_stamp();
461#endif
[407]462                return size;
463            }
464        }
465    }
466    else
467    {
[430]468        assert( false , __FUNCTION__ ,
469        "%s does not support direct user access", chdev_func_str(func) );
[407]470
471        return -1;
472    }
[433]473
[407]474}  // end devfs_user_move()
475
476
Note: See TracBrowser for help on using the repository browser.