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

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

blip

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