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

Last change on this file since 451 was 438, checked in by alain, 7 years ago

Fix a bug in scheduler related to RPC blocking.

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
[438]44#if (DEBUG_SYS_READ & 1)
[435]45extern uint32_t  enter_devfs_read;
46extern uint32_t  exit_devfs_read;
[407]47#endif
48
[438]49#if (DEBUG_SYS_WRITE & 1)
[435]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
[437]87/////////////////////////////////////////////////
[188]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
[438]94#if DEBUG_DEVFS_INIT
[433]95uint32_t cycle = (uint32_t)hal_get_cycles();
[438]96if( DEBUG_DEVFS_INIT < cycle )
[433]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
[438]112#if( DEBUG_DEVFS_INIT & 1 )
113if( DEBUG_DEVFS_INIT < cycle )
[437]114printk("\n[DBG] %s : created <dev> inode at cycle %d\n", __FUNCTION__, cycle );
115#endif
116
[188]117    // create DEVFS "external" inode in cluster IO
118    error = vfs_add_child_in_parent( LOCAL_CLUSTER->io_cxy,
119                                     INODE_TYPE_DIR,
120                                     FS_TYPE_DEVFS,
[204]121                                     *devfs_dev_inode_xp,
122                                     "external",
[188]123                                     NULL,
124                                     devfs_external_inode_xp ); 
[23]125
[279]126    assert( (error == 0) , __FUNCTION__ , "cannot create <external>\n" );
127
[438]128#if DEBUG_DEVFS_INIT
[433]129cycle = (uint32_t)hal_get_cycles();
[438]130if( DEBUG_DEVFS_INIT < cycle )
[433]131printk("\n[DBG] %s : thread %x exit at cycle %d\n",
132__FUNCTION__ , CURRENT_THREAD , cycle );
133#endif
134
[188]135} 
[23]136
[204]137///////////////////////////////////////////////////
138void devfs_local_init( xptr_t   devfs_dev_inode_xp,
139                       xptr_t   devfs_external_inode_xp,
140                       xptr_t * devfs_internal_inode_xp )
[23]141{
142    char          node_name[16];
[188]143    xptr_t        chdev_xp;
144    cxy_t         chdev_cxy;
[407]145    chdev_t     * chdev_ptr;
[188]146    xptr_t        inode_xp;
[23]147    uint32_t      channel;
148
[438]149#if DEBUG_DEVFS_INIT
[433]150uint32_t cycle = (uint32_t)hal_get_cycles();
[438]151if( DEBUG_DEVFS_INIT < cycle )
[433]152printk("\n[DBG] %s : thread %x enter at cycle %d\n",
153__FUNCTION__ , CURRENT_THREAD , cycle );
154#endif
155
[188]156    // create "internal" directory linked to "dev"
157    snprintf( node_name , 16 , "internal_%x" , local_cxy );
158    vfs_add_child_in_parent( local_cxy,
159                             INODE_TYPE_DIR,
160                             FS_TYPE_DEVFS,
[204]161                             devfs_dev_inode_xp,
[188]162                             node_name,
163                             NULL,
[204]164                             devfs_internal_inode_xp );
[23]165
166    // create MMC chdev inode
[407]167    chdev_xp  = chdev_dir.mmc[local_cxy];
[188]168    if( chdev_xp != XPTR_NULL)
169    {
[407]170        chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]171        vfs_add_child_in_parent( local_cxy,
172                                 INODE_TYPE_DEV,
173                                 FS_TYPE_DEVFS,
[204]174                                 *devfs_internal_inode_xp,
[407]175                                 chdev_ptr->name,
[188]176                                 GET_PTR( chdev_xp ),
177                                 &inode_xp );
178    }
[23]179
180    // create DMA chdev inodes (one DMA channel per core)
[188]181    for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ )
[23]182    {
[188]183        chdev_xp = chdev_dir.dma[channel];
184        if( chdev_xp != XPTR_NULL)
185        {
[407]186            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]187            vfs_add_child_in_parent( local_cxy,
188                                     INODE_TYPE_DEV,
189                                     FS_TYPE_DEVFS,
[204]190                                     *devfs_internal_inode_xp,
[407]191                                     chdev_ptr->name,
[188]192                                     GET_PTR( chdev_xp ),
193                                     &inode_xp );
194        }
[23]195    }
196
[188]197    // create an IOB inode in cluster containing IOB chdev
198    chdev_xp = chdev_dir.iob;
199    if( chdev_xp != XPTR_NULL )
[23]200    {
[188]201        chdev_cxy = GET_CXY( chdev_xp );
[407]202        chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]203        if( chdev_cxy == local_cxy )
204        {
205            vfs_add_child_in_parent( local_cxy,
206                                     INODE_TYPE_DEV,
207                                     FS_TYPE_DEVFS,
208                                     devfs_external_inode_xp,
[407]209                                     chdev_ptr->name,
[188]210                                     GET_PTR( chdev_xp ),
211                                     &inode_xp );
212        }
213    }
[23]214       
[188]215    // create a PIC inode in cluster containing PIC chdev
216    chdev_xp = chdev_dir.pic;
217    if( chdev_xp != XPTR_NULL )
218    {
219        chdev_cxy = GET_CXY( chdev_xp );
[407]220        chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]221        if( chdev_cxy == local_cxy )
[23]222        {
[188]223            vfs_add_child_in_parent( local_cxy,
224                                     INODE_TYPE_DEV,
225                                     FS_TYPE_DEVFS,
226                                     devfs_external_inode_xp,
[407]227                                     chdev_ptr->name,
[188]228                                     GET_PTR( chdev_xp ),
229                                     &inode_xp );
[23]230        }
[188]231    }
[23]232
[407]233    // create a TXT_RX inode in each cluster containing a TXT_RX chdev
[188]234    for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
235    {
[407]236        chdev_xp = chdev_dir.txt_rx[channel];
[188]237        if( chdev_xp != XPTR_NULL )
[23]238        {
[188]239            chdev_cxy = GET_CXY( chdev_xp );
[407]240            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]241            if( chdev_cxy == local_cxy )
242            {
243                vfs_add_child_in_parent( local_cxy,
244                                         INODE_TYPE_DEV,
245                                         FS_TYPE_DEVFS,
246                                         devfs_external_inode_xp,
[407]247                                         chdev_ptr->name,
[188]248                                         GET_PTR( chdev_xp ),
249                                         &inode_xp );
250            }
[23]251        }
[188]252    }
[23]253
[407]254    // create a TXT_TX inode in each cluster containing a TXT_TX chdev
255    for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
256    {
257        chdev_xp = chdev_dir.txt_tx[channel];
258        if( chdev_xp != XPTR_NULL )
259        {
260            chdev_cxy = GET_CXY( chdev_xp );
261            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
262            if( chdev_cxy == local_cxy )
263            {
264                vfs_add_child_in_parent( local_cxy,
265                                         INODE_TYPE_DEV,
266                                         FS_TYPE_DEVFS,
267                                         devfs_external_inode_xp,
268                                         chdev_ptr->name,
269                                         GET_PTR( chdev_xp ),
270                                         &inode_xp );
271            }
272        }
273    }
274
[188]275    // create an IOC inode in each cluster containing an IOC chdev
276    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
277    {
278        chdev_xp = chdev_dir.ioc[channel];
279        if( chdev_xp != XPTR_NULL )
[23]280        {
[188]281            chdev_cxy = GET_CXY( chdev_xp );
[407]282            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]283            if( chdev_cxy == local_cxy )
284            {
285                vfs_add_child_in_parent( local_cxy,
286                                         INODE_TYPE_DEV,
287                                         FS_TYPE_DEVFS,
288                                         devfs_external_inode_xp,
[407]289                                         chdev_ptr->name,
[188]290                                         GET_PTR( chdev_xp ),
291                                         &inode_xp );
292            }
[23]293        }
[188]294    }
[23]295
[188]296    // create a FBF inode in each cluster containing a FBF chdev
297    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
298    {
299        chdev_xp = chdev_dir.fbf[channel];
300        if( chdev_xp != XPTR_NULL )
[23]301        {
[188]302            chdev_cxy = GET_CXY( chdev_xp );
[407]303            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]304            if( chdev_cxy == local_cxy )
305            {
306                vfs_add_child_in_parent( local_cxy,
307                                         INODE_TYPE_DEV,
308                                         FS_TYPE_DEVFS,
309                                         devfs_external_inode_xp,
[407]310                                         chdev_ptr->name,
[188]311                                         GET_PTR( chdev_xp ),
312                                         &inode_xp );
313            }
[23]314        }
[188]315    }
[23]316
[188]317    // create a NIC_RX inode in each cluster containing a NIC_RX chdev
318    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
319    {
320        chdev_xp = chdev_dir.nic_rx[channel];
321        if( chdev_xp != XPTR_NULL )
[23]322        {
[188]323            chdev_cxy = GET_CXY( chdev_xp );
[407]324            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]325            if( chdev_cxy == local_cxy )
326            {
327                vfs_add_child_in_parent( local_cxy,
328                                         INODE_TYPE_DEV,
329                                         FS_TYPE_DEVFS,
330                                         devfs_external_inode_xp,
[407]331                                         chdev_ptr->name,
[188]332                                         GET_PTR( chdev_xp ),
333                                         &inode_xp );
334            }
[23]335        }
336    }
337
[188]338    // create a NIC_TX inode in each cluster containing a NIC_TX chdev
339    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
[23]340    {
[188]341        chdev_xp = chdev_dir.nic_tx[channel];
342        if( chdev_xp != XPTR_NULL )
343        {
344            chdev_cxy = GET_CXY( chdev_xp );
[407]345            chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
[188]346            if( chdev_cxy == local_cxy )
347            {
348                vfs_add_child_in_parent( local_cxy,
349                                         INODE_TYPE_DEV,
350                                         FS_TYPE_DEVFS,
351                                         devfs_external_inode_xp,
[407]352                                         chdev_ptr->name,
[188]353                                         GET_PTR( chdev_xp ),
354                                         &inode_xp );
355            }
356        }
[23]357    }
[433]358
[438]359#if DEBUG_DEVFS_INIT
[433]360cycle = (uint32_t)hal_get_cycles();
[438]361if( DEBUG_DEVFS_INIT < cycle )
[433]362printk("\n[DBG] %s : thread %x exit at cycle %d\n",
363__FUNCTION__ , CURRENT_THREAD , cycle );
364#endif
365
[188]366}  // end devfs_local_init()
[23]367
[407]368//////////////////////////////////////////
369int devfs_user_move( bool_t     to_buffer,
370                     xptr_t     file_xp,
371                     void     * u_buf,
372                     uint32_t   size )
373{
374    assert( ( file_xp != XPTR_NULL ) , __FUNCTION__ , "file_xp == XPTR_NULL" );
375
376    assert( ( size < CONFIG_TXT_KBUF_SIZE ) , __FUNCTION__ , "string size too large" );
377
[430]378    xptr_t             chdev_xp;
379    cxy_t              chdev_cxy;
[407]380    chdev_t          * chdev_ptr;    // associated chdev type
381    uint32_t           func;         // chdev functionnal type
382    uint32_t           channel;      // chdev channel index
383    error_t            error;
384
385    char               k_buf[CONFIG_TXT_KBUF_SIZE];  // local kernel buffer
386
[438]387#if (DEBUG_SYS_READ & 1)
[435]388enter_devfs_read = hal_time_stamp();
389#endif
390
[438]391#if (DEBUG_SYS_WRITE & 1)
[435]392enter_devfs_write = hal_time_stamp();
393#endif
394
[438]395#if DEBUG_DEVFS_MOVE
[433]396uint32_t cycle = (uint32_t)hal_get_cycles();
[438]397if( DEBUG_DEVFS_MOVE < cycle )
[433]398printk("\n[DBG] %s : thread %x enter / to_mem %d / cycle %d\n",
399__FUNCTION__ , CURRENT_THREAD , to_buffer , cycle );
400#endif
[407]401
[430]402    // get extended pointer on chdev_xp
403    chdev_xp = chdev_from_file( file_xp );
[407]404
[430]405    // get cluster and local pointer on chdev
406    chdev_cxy  = GET_CXY( chdev_xp );
407    chdev_ptr  = (chdev_t *)GET_PTR( chdev_xp );
[407]408
409    // get chdev functionnal type and channel
[430]410    func    = hal_remote_lw( XPTR( chdev_cxy , &chdev_ptr->func ) );
411    channel = hal_remote_lw( XPTR( chdev_cxy , &chdev_ptr->channel ) );
[407]412
413    // action depends on "func" and "to_buffer"
414    if( func == DEV_FUNC_TXT )
415    {
416        if( to_buffer )     // TXT read
417        { 
418            uint32_t i;
419            for( i = 0 ; i < size ; i++ )
420            {
421                error = dev_txt_read( channel , &k_buf[i] );
422
423                if( error ) 
424                {
425                    return -1;
426                }
427                else
428                {
429                    hal_strcpy_to_uspace( u_buf , k_buf , size );
430                }
431             }
432
[438]433#if DEBUG_DEVFS_MOVE
[433]434cycle = (uint32_t)hal_get_cycles();
[438]435if( DEBUG_DEVFS_MOVE < cycle )
[433]436printk("\n[DBG] %s : thread %x exit / to_mem %d / cycle %d\n",
437__FUNCTION__ , CURRENT_THREAD , to_buffer / cycle );
438#endif
439
[438]440#if (DEBUG_SYS_READ & 1)
[435]441exit_devfs_read = hal_time_stamp();
[407]442#endif
443            return size;
444        } 
445        else                // TXT write 
446        {
447            hal_strcpy_from_uspace( k_buf , u_buf , size );
448
449            error = dev_txt_write( channel , k_buf , size );
450            if( error ) 
451            {
452                return -1;
453            }
454            else
455            {
456
[438]457#if DEBUG_DEVFS_MOVE
[433]458cycle = (uint32_t)hal_get_cycles();
[438]459if( DEBUG_DEVFS_MOVE < cycle )
[433]460printk("\n[DBG] %s : thread %x exit / to_mem %d / cycle %d\n",
461__FUNCTION__ , CURRENT_THREAD , to_buffer / cycle );
462#endif
[407]463
[438]464#if (DEBUG_SYS_WRITE & 1)
[435]465exit_devfs_write = hal_time_stamp();
466#endif
[407]467                return size;
468            }
469        }
470    }
471    else
472    {
[430]473        assert( false , __FUNCTION__ ,
474        "%s does not support direct user access", chdev_func_str(func) );
[407]475
476        return -1;
477    }
[433]478
[407]479}  // end devfs_user_move()
480
481
Note: See TracBrowser for help on using the repository browser.