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

Last change on this file since 690 was 683, checked in by alain, 3 years ago

All modifications required to support the <tcp_chat> application
including error recovery in case of packet loss.A

File size: 28.7 KB
RevLine 
[23]1/*
2 * devfs.c - DEVFS File system API implementation.
3 *
4 * Author   Mohamed Lamine Karaoui (2014,2015)
[673]5 *          Alain Greiner          (2016,2017,2018,2019,2020)
[23]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
[457]25#include <hal_kernel_types.h>
[23]26#include <hal_special.h>
[407]27#include <hal_uspace.h>
[23]28#include <printk.h>
[612]29#include <string.h>
[23]30#include <chdev.h>
[433]31#include <thread.h>
[407]32#include <dev_txt.h>
[188]33#include <cluster.h>
[23]34#include <vfs.h>
[188]35#include <kmem.h>
[23]36#include <devfs.h>
37
[188]38/////////////////////////////////////////////////////////////////////////////////////////
39//     Extern variables
40/////////////////////////////////////////////////////////////////////////////////////////
[23]41
[188]42extern vfs_ctx_t            fs_context[];   // allocated in kernel_init.c
43extern chdev_directory_t    chdev_dir;      // allocated in kernel_init.c
[23]44
[438]45#if (DEBUG_SYS_READ & 1)
[435]46extern uint32_t  enter_devfs_read;
47extern uint32_t  exit_devfs_read;
[407]48#endif
49
[438]50#if (DEBUG_SYS_WRITE & 1)
[435]51extern uint32_t  enter_devfs_write;
52extern uint32_t  exit_devfs_write;
53#endif
54
[657]55///////////////////////////////////
56xptr_t devfs_ctx_alloc( cxy_t cxy )
[188]57{
[683]58    // allocates devfs context from target cluster
59        void * ptr = kmem_remote_alloc( cxy,
60                                    bits_log2(sizeof(devfs_ctx_t)),
61                                    AF_ZERO );
[23]62
[683]63    if( ptr == NULL ) return XPTR_NULL;
64        else              return XPTR( cxy , ptr );
[188]65}
[23]66
[188]67/////////////////////////////////////////////
[657]68void devfs_ctx_init( xptr_t     devfs_ctx_xp,
69                     xptr_t     devfs_dev_inode_xp,
70                     xptr_t     devfs_external_inode_xp )
[23]71{
[657]72    // get cluster and local pointer on remote devfs context
73    devfs_ctx_t * devfs_ctx_ptr = GET_PTR( devfs_ctx_xp );
74    cxy_t         devfs_ctx_cxy = GET_CXY( devfs_ctx_xp );
[23]75
[657]76    // set values in remote devfs context
77    hal_remote_s64( XPTR( devfs_ctx_cxy  , &devfs_ctx_ptr->dev_inode_xp ),
78                    devfs_dev_inode_xp );
79
80    hal_remote_s64( XPTR( devfs_ctx_cxy  , &devfs_ctx_ptr->external_inode_xp ),
81                    devfs_external_inode_xp );
82
83    // register devfs context in the remote fs_context array[]
84    hal_remote_spt( XPTR( devfs_ctx_cxy , &fs_context[FS_TYPE_DEVFS].extend ),
85                          devfs_ctx_ptr ); 
[188]86}
[23]87
[657]88//////////////////////////////////////////////
89void devfs_ctx_destroy( xptr_t  devfs_ctx_xp )
[188]90{
[657]91    // get cluster and local pointer on devfs context
92    devfs_ctx_t * devfs_ctx_ptr = GET_PTR( devfs_ctx_xp );
93    cxy_t         devfs_ctx_cxy = GET_CXY( devfs_ctx_xp );
94
95    // release devfs context descriptor to remote cluster
[683]96    kmem_remote_free( devfs_ctx_cxy,
97                      devfs_ctx_ptr,
98                      bits_log2(sizeof(devfs_ctx_t)) );
[188]99}
[23]100
[437]101/////////////////////////////////////////////////
[602]102void devfs_global_init( xptr_t   root_inode_xp,
[204]103                        xptr_t * devfs_dev_inode_xp,
[188]104                        xptr_t * devfs_external_inode_xp )
[23]105{
[623]106    error_t       error;
107    xptr_t        unused_xp;   // required by vfs_add_child_in_parent()
108    vfs_inode_t * inode;
[23]109
[657]110    // get
111
[610]112    // create DEVFS "dev" inode in cluster 0
[457]113    error = vfs_add_child_in_parent( 0,                // cxy
[188]114                                     FS_TYPE_DEVFS,
[602]115                                     root_inode_xp,
[188]116                                     "dev",
[602]117                                     &unused_xp,
118                                     devfs_dev_inode_xp );
[23]119
[623]120    // update inode "type" field
121    inode = GET_PTR( *devfs_dev_inode_xp );
[673]122    inode->type = FILE_TYPE_DIR;
[623]123 
[612]124    // create dentries <.> and <..> in <dev>
125    error |= vfs_add_special_dentries( *devfs_dev_inode_xp,
126                                       root_inode_xp );
127
[623]128    if( error )
129    {
130        printk("\n[PANIC] in %s : cannot create <dev> directory\n", __FUNCTION__ );
131        hal_core_sleep();
132    }
[23]133
[614]134#if DEBUG_DEVFS_GLOBAL_INIT
[598]135uint32_t   cycle = (uint32_t)hal_get_cycles();
136thread_t * this  = CURRENT_THREAD;
[614]137if( DEBUG_DEVFS_GLOBAL_INIT < cycle )
[598]138printk("\n[%s] thread[%x,%x] created <dev> inode / cycle %d\n",
139__FUNCTION__, this->process->pid, this->trdid, cycle );
[437]140#endif
141
[457]142    // create DEVFS "external" inode in cluster 0
143    error = vfs_add_child_in_parent( 0,               // cxy
[188]144                                     FS_TYPE_DEVFS,
[204]145                                     *devfs_dev_inode_xp,
146                                     "external",
[602]147                                     &unused_xp,
148                                     devfs_external_inode_xp );
[23]149
[623]150    // update inode "type" field
151    inode = GET_PTR( *devfs_external_inode_xp );
[673]152    inode->type = FILE_TYPE_DIR;
[623]153 
[612]154    // create dentries <.> and <..> in <external>
155    error |= vfs_add_special_dentries( *devfs_external_inode_xp,
156                                       *devfs_dev_inode_xp );
[279]157
[623]158    if( error )
159    {
160        printk("\n[PANIC] in %s : cannot create <external> directory\n", __FUNCTION__ );
161        hal_core_sleep();
162    }
[612]163
[614]164#if DEBUG_DEVFS_GLOBAL_INIT
[433]165cycle = (uint32_t)hal_get_cycles();
[614]166if( DEBUG_DEVFS_GLOBAL_INIT < cycle )
[598]167printk("\n[%s] thread[%x,%x] created <external> inode / cycle %d\n",
168__FUNCTION__, this->process->pid, this->trdid, cycle );
[433]169#endif
170
[602]171}  // end devfs_global_init()
[23]172
[204]173///////////////////////////////////////////////////
174void devfs_local_init( xptr_t   devfs_dev_inode_xp,
[657]175                       xptr_t   devfs_external_inode_xp )
[23]176{
[657]177    xptr_t        internal_inode_xp;   // extended pointer on <internal> inode
178    vfs_inode_t * internal_inode_ptr;  // local pointer on <internal> inode
[23]179    char          node_name[16];
[188]180    xptr_t        chdev_xp;
181    cxy_t         chdev_cxy;
[407]182    chdev_t     * chdev_ptr;
[188]183    xptr_t        inode_xp;
[602]184    vfs_inode_t * inode_ptr;
[23]185    uint32_t      channel;
[657]186    xptr_t        unused_xp;           // required by add_child_in_parent()
[612]187    error_t       error;
[657]188   
[23]189
[614]190#if DEBUG_DEVFS_LOCAL_INIT
191uint32_t   cycle = (uint32_t)hal_get_cycles();
192thread_t * this  = CURRENT_THREAD;
193if( DEBUG_DEVFS_LOCAL_INIT < cycle )
194printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
195__FUNCTION__, this->process->pid, this->trdid, cycle );
196#endif
197
[657]198    // create <internal> directory
[673]199    snprintk( node_name , 16 , "internal_%x" , local_cxy );
[610]200
[657]201    error = vfs_add_child_in_parent( local_cxy,              // target cluster
202                                     FS_TYPE_DEVFS,          // FS type
203                                     devfs_dev_inode_xp,     // parent inode
204                                     node_name,              // child name
[612]205                                     &unused_xp,
[657]206                                     &internal_inode_xp );   // child inode
[612]207
[657]208    // set <internal> inode "type" field
209    internal_inode_ptr       = GET_PTR( internal_inode_xp );
[673]210    internal_inode_ptr->type = FILE_TYPE_DEV;
[623]211 
[612]212    // create dentries <.> and <..> in <internal>
[657]213    error |= vfs_add_special_dentries( internal_inode_xp,
[612]214                                       devfs_dev_inode_xp );
215
[623]216    if( error )
217    {
218        printk("\n[PANIC] in %s : cannot create <internal> directory\n", __FUNCTION__ );
219        hal_core_sleep();
220    }
[612]221
[614]222#if DEBUG_DEVFS_LOCAL_INIT
223cycle = (uint32_t)hal_get_cycles();
224if( DEBUG_DEVFS_LOCAL_INIT < cycle )
[598]225printk("\n[%s] thread[%x,%x] created <%s> inode in cluster %x / cycle %d\n",
226__FUNCTION__, this->process->pid, this->trdid, node_name, local_cxy, cycle );
[568]227#endif
[23]228
229    // create MMC chdev inode
[407]230    chdev_xp  = chdev_dir.mmc[local_cxy];
[188]231    if( chdev_xp != XPTR_NULL)
232    {
[602]233        chdev_ptr = GET_PTR( chdev_xp );
[610]234        chdev_cxy = GET_CXY( chdev_xp );
235
[623]236        if( chdev_cxy != local_cxy )
237        {
238            printk("\n[PANIC] in %s : illegal MMC chdev in cluster %x\n",
239            __FUNCTION__, local_cxy );
240            hal_core_sleep();
241        }
[610]242
[612]243        error = vfs_add_child_in_parent( local_cxy,
244                                         FS_TYPE_DEVFS,
[657]245                                         internal_inode_xp,
[612]246                                         chdev_ptr->name,
247                                         &unused_xp,
248                                         &inode_xp );
[602]249
[623]250        if( error )
251        {
252            printk("\n[PANIC] in %s : cannot create MMC inode in cluster %x\n",
253            __FUNCTION__, local_cxy );
254            hal_core_sleep();
255        }
[612]256
[623]257        // update child inode "extend" and "type" fields
[602]258        inode_ptr = GET_PTR( inode_xp );
[623]259        inode_ptr->extend = chdev_ptr;
[673]260        inode_ptr->type   = FILE_TYPE_DEV;
[602]261       
[614]262#if DEBUG_DEVFS_LOCAL_INIT
[568]263cycle = (uint32_t)hal_get_cycles();
[614]264if( DEBUG_DEVFS_LOCAL_INIT < cycle )
[598]265printk("\n[%s] thread[%x,%x] created <mmc> inode in cluster %x\n",
266__FUNCTION__, this->process->pid, this->trdid, local_cxy, cycle );
[568]267#endif
268
[188]269    }
[23]270
271    // create DMA chdev inodes (one DMA channel per core)
[188]272    for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ )
[23]273    {
[602]274        chdev_xp  = chdev_dir.dma[channel];
[188]275        if( chdev_xp != XPTR_NULL)
276        {
[602]277            chdev_ptr = GET_PTR( chdev_xp );
[610]278            chdev_cxy = GET_CXY( chdev_xp );
279
[623]280            if( chdev_cxy != local_cxy )
281            {
[624]282                printk("\n[PANIC] in %s : illegal DMA chdev in cluster %x\n",
[623]283                __FUNCTION__, local_cxy );
284                hal_core_sleep();
285            }
[610]286
[612]287            error = vfs_add_child_in_parent( local_cxy,
288                                             FS_TYPE_DEVFS,
[657]289                                             internal_inode_xp,
[612]290                                             chdev_ptr->name,
291                                             &unused_xp,
292                                             &inode_xp );
[623]293            if( error )
294            {
295                printk("\n[PANIC] in %s : cannot create DMA inode in cluster %x\n",
296                __FUNCTION__, local_cxy );
297                hal_core_sleep();
298            }
[602]299
[623]300            // update child inode "extend" and "type" fields
[602]301            inode_ptr = GET_PTR( inode_xp );
[623]302            inode_ptr->extend = chdev_ptr;
[673]303            inode_ptr->type   = FILE_TYPE_DEV;
[602]304       
[614]305#if DEBUG_DEVFS_LOCAL_INIT
[568]306cycle = (uint32_t)hal_get_cycles();
[614]307if( DEBUG_DEVFS_LOCAL_INIT < cycle )
[598]308printk("\n[%s] thread [%x,%x] created <dma[%d]> inode in cluster %x\n",
309__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
[568]310#endif
[188]311        }
[23]312    }
313
[188]314    // create an IOB inode in cluster containing IOB chdev
315    chdev_xp = chdev_dir.iob;
316    if( chdev_xp != XPTR_NULL )
[23]317    {
[188]318        chdev_cxy = GET_CXY( chdev_xp );
[602]319        chdev_ptr = GET_PTR( chdev_xp );
[610]320
[188]321        if( chdev_cxy == local_cxy )
322        {
[612]323            error = vfs_add_child_in_parent( local_cxy,
324                                             FS_TYPE_DEVFS,
325                                             devfs_external_inode_xp,
326                                             chdev_ptr->name,
327                                             &unused_xp,
328                                             &inode_xp );
[623]329            if( error )
330            {
331                printk("\n[PANIC] in %s : cannot create IOB inode in cluster %x\n",
332                __FUNCTION__, local_cxy );
333                hal_core_sleep();
334            }
[602]335
[623]336            // update child inode "extend" and "type" fields
[602]337            inode_ptr = GET_PTR( inode_xp );
[623]338            inode_ptr->extend = chdev_ptr;
[673]339            inode_ptr->type   = FILE_TYPE_DEV;
[602]340       
[614]341#if DEBUG_DEVFS_LOCAL_INIT
[568]342cycle = (uint32_t)hal_get_cycles();
[614]343if( DEBUG_DEVFS_LOCAL_INIT < cycle )
[598]344printk("\n[%s] thread[%x,%x] created <iob> inode in cluster %x\n",
345__FUNCTION__, this->process->pid, this->trdid, local_cxy, cycle );
[568]346#endif
[188]347        }
348    }
[23]349       
[188]350    // create a PIC inode in cluster containing PIC chdev
351    chdev_xp = chdev_dir.pic;
352    if( chdev_xp != XPTR_NULL )
353    {
354        chdev_cxy = GET_CXY( chdev_xp );
[602]355        chdev_ptr = GET_PTR( chdev_xp );
[610]356
[188]357        if( chdev_cxy == local_cxy )
[23]358        {
[612]359            error = vfs_add_child_in_parent( local_cxy,
360                                             FS_TYPE_DEVFS,
361                                             devfs_external_inode_xp,
362                                             chdev_ptr->name,
363                                             &unused_xp,
364                                             &inode_xp );
[602]365
[623]366            if( error )
367            {
368                printk("\n[PANIC] in %s : cannot create PIC inode in cluster %x\n",
369                __FUNCTION__, local_cxy );
370                hal_core_sleep();
371            }
[612]372
[602]373            // update child inode "extend" field
374            inode_ptr = GET_PTR( inode_xp );
[623]375            inode_ptr->extend = chdev_ptr;
[673]376            inode_ptr->type   = FILE_TYPE_DEV;
[602]377       
[614]378#if DEBUG_DEVFS_LOCAL_INIT
[568]379cycle = (uint32_t)hal_get_cycles();
[614]380if( DEBUG_DEVFS_LOCAL_INIT < cycle )
[598]381printk("\n[%s] thread[%x,%x] created <pic> inode in cluster %x\n",
382__FUNCTION__, this->process->pid, this->trdid, local_cxy, cycle );
[568]383#endif
[23]384        }
[188]385    }
[23]386
[407]387    // create a TXT_RX inode in each cluster containing a TXT_RX chdev
[188]388    for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
389    {
[407]390        chdev_xp = chdev_dir.txt_rx[channel];
[188]391        if( chdev_xp != XPTR_NULL )
[23]392        {
[188]393            chdev_cxy = GET_CXY( chdev_xp );
[602]394            chdev_ptr = GET_PTR( chdev_xp );
[610]395
[188]396            if( chdev_cxy == local_cxy )
397            {
[612]398                error = vfs_add_child_in_parent( local_cxy,
399                                                 FS_TYPE_DEVFS,
400                                                 devfs_external_inode_xp,
401                                                 chdev_ptr->name,
402                                                 &unused_xp,
403                                                 &inode_xp );
[602]404
[623]405                if( error )
406                {
407                    printk("\n[PANIC] in %s : cannot create TXT_RX inode in cluster %x\n",
408                    __FUNCTION__, local_cxy );
409                    hal_core_sleep();
410                }
[612]411
[623]412                // update child inode "extend" and "type" fields
[602]413                inode_ptr = GET_PTR( inode_xp );
[623]414                inode_ptr->extend = chdev_ptr;
[673]415                inode_ptr->type   = FILE_TYPE_DEV;
[602]416       
[614]417#if DEBUG_DEVFS_LOCAL_INIT
[568]418cycle = (uint32_t)hal_get_cycles();
[614]419if( DEBUG_DEVFS_LOCAL_INIT < cycle )
[598]420printk("\n[%s] thread[%x,%x] created <txt_rx[%d]> inode in cluster %x\n",
421__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
[568]422#endif
[188]423            }
[23]424        }
[188]425    }
[23]426
[407]427    // create a TXT_TX inode in each cluster containing a TXT_TX chdev
428    for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
429    {
430        chdev_xp = chdev_dir.txt_tx[channel];
431        if( chdev_xp != XPTR_NULL )
432        {
433            chdev_cxy = GET_CXY( chdev_xp );
[602]434            chdev_ptr = GET_PTR( chdev_xp );
[610]435
[407]436            if( chdev_cxy == local_cxy )
437            {
[612]438                error = vfs_add_child_in_parent( local_cxy,
439                                                 FS_TYPE_DEVFS,
440                                                 devfs_external_inode_xp,
441                                                 chdev_ptr->name,
442                                                 &unused_xp,
443                                                 &inode_xp );
[623]444                if( error )
445                {
446                    printk("\n[PANIC] in %s : cannot create TXT_TX inode in cluster %x\n",
447                    __FUNCTION__, local_cxy );
448                    hal_core_sleep();
449                }
[602]450
[623]451                // update child inode "extend" and "type" fields
[602]452                inode_ptr = GET_PTR( inode_xp );
[623]453                inode_ptr->extend = chdev_ptr;
[673]454                inode_ptr->type   = FILE_TYPE_DEV;
[602]455       
[614]456#if DEBUG_DEVFS_LOCAL_INIT
[568]457cycle = (uint32_t)hal_get_cycles();
[614]458if( DEBUG_DEVFS_LOCAL_INIT < cycle )
[598]459printk("\n[%s] thread[%x,%x] created <txt_tx[%d]> inode in cluster %x\n",
460__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
[568]461#endif
[407]462            }
463        }
464    }
465
[188]466    // create an IOC inode in each cluster containing an IOC chdev
467    for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
468    {
469        chdev_xp = chdev_dir.ioc[channel];
470        if( chdev_xp != XPTR_NULL )
[23]471        {
[188]472            chdev_cxy = GET_CXY( chdev_xp );
[602]473            chdev_ptr = GET_PTR( chdev_xp );
[610]474
[188]475            if( chdev_cxy == local_cxy )
476            {
[612]477                error = vfs_add_child_in_parent( local_cxy,
478                                                 FS_TYPE_DEVFS,
479                                                 devfs_external_inode_xp,
480                                                 chdev_ptr->name,
481                                                 &unused_xp,
482                                                 &inode_xp );
[623]483                if( error )
484                {
485                    printk("\n[PANIC] in %s : cannot create IOC inode in cluster %x\n",
486                    __FUNCTION__, local_cxy );
487                    hal_core_sleep();
488                }
[602]489
[623]490                // update child inode "extend" and "type" fields
[602]491                inode_ptr = GET_PTR( inode_xp );
[623]492                inode_ptr->extend = chdev_ptr;
[673]493                inode_ptr->type   = FILE_TYPE_DEV;
[602]494       
[614]495#if DEBUG_DEVFS_LOCAL_INIT
[568]496cycle = (uint32_t)hal_get_cycles();
[614]497if( DEBUG_DEVFS_LOCAL_INIT < cycle )
[598]498printk("\n[%s] thread[%x,%x] created <ioc[%d]> inode in cluster %x\n",
499__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
[568]500#endif
[188]501            }
[23]502        }
[188]503    }
[23]504
[188]505    // create a FBF inode in each cluster containing a FBF chdev
[568]506    for( channel = 0 ; channel < CONFIG_MAX_FBF_CHANNELS ; channel++ )
[188]507    {
508        chdev_xp = chdev_dir.fbf[channel];
509        if( chdev_xp != XPTR_NULL )
[23]510        {
[188]511            chdev_cxy = GET_CXY( chdev_xp );
[602]512            chdev_ptr = GET_PTR( chdev_xp );
[610]513
[188]514            if( chdev_cxy == local_cxy )
515            {
[612]516                error = vfs_add_child_in_parent( local_cxy,
517                                                 FS_TYPE_DEVFS,
518                                                 devfs_external_inode_xp,
519                                                 chdev_ptr->name,
520                                                 &unused_xp,
521                                                 &inode_xp );
[623]522                if( error )
523                {
524                    printk("\n[PANIC] in %s : cannot create FBF inode in cluster %x\n",
525                    __FUNCTION__, local_cxy );
526                    hal_core_sleep();
527                }
[602]528
[623]529                // update child inode "extend" and "type" fields
[602]530                inode_ptr = GET_PTR( inode_xp );
[623]531                inode_ptr->extend = chdev_ptr;
[673]532                inode_ptr->type   = FILE_TYPE_DEV;
[602]533       
[614]534#if DEBUG_DEVFS_LOCAL_INIT
[568]535cycle = (uint32_t)hal_get_cycles();
[614]536if( DEBUG_DEVFS_LOCAL_INIT < cycle )
[598]537printk("\n[%s] thread[%x,%x] created <fbf[%d]> inode in cluster %x\n",
538__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
[568]539#endif
[188]540            }
[23]541        }
[188]542    }
[23]543
[188]544    // create a NIC_RX inode in each cluster containing a NIC_RX chdev
545    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
546    {
547        chdev_xp = chdev_dir.nic_rx[channel];
548        if( chdev_xp != XPTR_NULL )
[23]549        {
[188]550            chdev_cxy = GET_CXY( chdev_xp );
[610]551            chdev_ptr = GET_PTR( chdev_xp );
552
[188]553            if( chdev_cxy == local_cxy )
554            {
[612]555                error = vfs_add_child_in_parent( local_cxy,
556                                                 FS_TYPE_DEVFS,
557                                                 devfs_external_inode_xp,
558                                                 chdev_ptr->name,
559                                                 &unused_xp,
560                                                 &inode_xp );
[623]561                if( error )
562                {
563                    printk("\n[PANIC] in %s : cannot create NIC_RX inode in cluster %x\n",
564                    __FUNCTION__, local_cxy );
565                    hal_core_sleep();
566                }
[612]567
[623]568                // update child inode "extend" and "type" fields
[612]569                inode_ptr = GET_PTR( inode_xp );
[623]570                inode_ptr->extend = chdev_ptr;
[673]571                inode_ptr->type   = FILE_TYPE_DEV;
[612]572 
[614]573#if DEBUG_DEVFS_LOCAL_INIT
[568]574cycle = (uint32_t)hal_get_cycles();
[614]575if( DEBUG_DEVFS_LOCAL_INIT < cycle )
[598]576printk("\n[%s] thread[%x,%x] created <nic_rx[%d]> inode in cluster %x\n",
577__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
[568]578#endif
[188]579            }
[23]580        }
581    }
582
[188]583    // create a NIC_TX inode in each cluster containing a NIC_TX chdev
584    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
[23]585    {
[188]586        chdev_xp = chdev_dir.nic_tx[channel];
587        if( chdev_xp != XPTR_NULL )
588        {
589            chdev_cxy = GET_CXY( chdev_xp );
[602]590            chdev_ptr = GET_PTR( chdev_xp );
[610]591
[188]592            if( chdev_cxy == local_cxy )
593            {
[612]594                error = vfs_add_child_in_parent( local_cxy,
595                                                 FS_TYPE_DEVFS,
596                                                 devfs_external_inode_xp,
597                                                 chdev_ptr->name,
598                                                 &unused_xp,
599                                                 &inode_xp );
[623]600                if( error )
601                {
602                    printk("\n[PANIC] in %s : cannot create NIC_TX inode in cluster %x\n",
603                    __FUNCTION__, local_cxy );
604                    hal_core_sleep();
605                }
[602]606
[623]607                // update child inode "extend" and "type" fields
[602]608                inode_ptr = GET_PTR( inode_xp );
[623]609                inode_ptr->extend = chdev_ptr;
[673]610                inode_ptr->type   = FILE_TYPE_DEV;
[602]611       
[614]612#if DEBUG_DEVFS_LOCAL_INIT
[433]613cycle = (uint32_t)hal_get_cycles();
[614]614if( DEBUG_DEVFS_LOCAL_INIT < cycle )
[598]615printk("\n[%s] thread[%x,%x] created <nic_tx[%d]> inode in cluster %x\n",
616__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
[433]617#endif
[568]618            }
619        }
620    }
[188]621}  // end devfs_local_init()
[23]622
[407]623//////////////////////////////////////////
624int devfs_user_move( bool_t     to_buffer,
625                     xptr_t     file_xp,
[598]626                     char     * u_buf,
[407]627                     uint32_t   size )
628{
[598]629    xptr_t           chdev_xp;
630    cxy_t            chdev_cxy;
631    chdev_t        * chdev_ptr;                    // associated chdev type
632    uint32_t         func;                         // chdev functionnal type
633    uint32_t         channel;                      // chdev channel index
634    uint32_t         burst;                        // number of bytes in a burst
635    uint32_t         todo;                         // number of bytes not yet moved
636    error_t          error;
637    uint32_t         i;
[407]638
[598]639    char             k_buf[CONFIG_TXT_KBUF_SIZE];  // local kernel buffer
[407]640
[673]641assert( __FUNCTION__, ( file_xp != XPTR_NULL ) , "file_xp == XPTR_NULL" );
[407]642
[438]643#if (DEBUG_SYS_READ & 1)
[435]644enter_devfs_read = hal_time_stamp();
645#endif
646
[438]647#if (DEBUG_SYS_WRITE & 1)
[435]648enter_devfs_write = hal_time_stamp();
649#endif
650
[438]651#if DEBUG_DEVFS_MOVE
[598]652uint32_t   cycle = (uint32_t)hal_get_cycles();
653thread_t * this  = CURRENT_THREAD;
[438]654if( DEBUG_DEVFS_MOVE < cycle )
[598]655printk("\n[%s] thread[%x,%x] enter / to_mem %d / cycle %d\n",
656__FUNCTION__, this->process->pid, this->trdid, to_buffer, cycle );
[433]657#endif
[407]658
[430]659    // get extended pointer on chdev_xp
660    chdev_xp = chdev_from_file( file_xp );
[407]661
[430]662    // get cluster and local pointer on chdev
663    chdev_cxy  = GET_CXY( chdev_xp );
664    chdev_ptr  = (chdev_t *)GET_PTR( chdev_xp );
[407]665
666    // get chdev functionnal type and channel
[568]667    func    = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->func ) );
668    channel = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->channel ) );
[407]669
[602]670// Only TXT devices are associated to a pseudo-file
[673]671assert( __FUNCTION__, ( func == DEV_FUNC_TXT ) , "illegal device func_type");
[598]672
673    // initialise number of bytes to move
674    todo = size;
675
676    /////////////// TXT read
677    if( to_buffer )
678    { 
679        while( todo )
680        {
681            // set burst size
682            if( todo > CONFIG_TXT_KBUF_SIZE ) burst = CONFIG_TXT_KBUF_SIZE;
683            else                              burst = todo;
684
685            // read burst bytes from TXT device to kernel buffer
686            for( i = 0 ; i < burst ; i++ )
[407]687            {
688                error = dev_txt_read( channel , &k_buf[i] );
689
[598]690                if( error )  return -1;
691            }
[407]692
[598]693            // move burst bytes from k_buf to u_buf                   
[637]694            hal_strcpy_to_uspace( u_buf,
695                                  XPTR( local_cxy , k_buf ),
696                                  burst );
[598]697
698            // update loop variables
699            todo  -= burst;
700            u_buf += burst;
701        }
702
[438]703#if DEBUG_DEVFS_MOVE
[433]704cycle = (uint32_t)hal_get_cycles();
[438]705if( DEBUG_DEVFS_MOVE < cycle )
[598]706printk("\n[%s] thread[%x,%x] exit / to_mem %d / cycle %d\n",
707__FUNCTION__, this->process->pid, this->trdid, to_buffer, cycle );
[433]708#endif
709
[438]710#if (DEBUG_SYS_READ & 1)
[435]711exit_devfs_read = hal_time_stamp();
[407]712#endif
713            return size;
[598]714    } 
715    ///////////// TXT write 
716    else               
717    {
718        while( todo )
[407]719        {
[598]720            // set burst size
721            if( todo > CONFIG_TXT_KBUF_SIZE ) burst = CONFIG_TXT_KBUF_SIZE;
722            else                              burst = todo;
[407]723
[598]724            // move burst bytes from u_buf to k_buf
[637]725            hal_strcpy_from_uspace( XPTR( local_cxy , k_buf ) , u_buf , burst );
[407]726
[598]727            // write burst bytes from kernel buffer to TXT device
728            error = dev_txt_write( channel , k_buf , burst );
729
730            if( error ) return -1;
731
732            // update loop variables
733            todo  -= burst;
734            u_buf += burst;
735        } 
736
[438]737#if DEBUG_DEVFS_MOVE
[433]738cycle = (uint32_t)hal_get_cycles();
[438]739if( DEBUG_DEVFS_MOVE < cycle )
[598]740printk("\n[%s] thread[%x,%x] exit / to_mem %d / cycle %d\n",
741__FUNCTION__, this->process->pid, this->trdid, to_buffer, cycle );
[433]742#endif
[407]743
[438]744#if (DEBUG_SYS_WRITE & 1)
[435]745exit_devfs_write = hal_time_stamp();
746#endif
[598]747            return size;
[407]748    }
749
750}  // end devfs_user_move()
751
[612]752///////////////////////////////////////////////////////
753error_t devfs_get_user_dir( struct vfs_inode_s * inode,
754                            struct dirent      * array,
755                            uint32_t             max_dirent,
756                            uint32_t             min_dentry,
757                            bool_t               detailed,
758                            uint32_t           * entries,
759                            bool_t             * done )
760{
761    xptr_t         xhtab_xp;    // extended pointer on inode xhtab (children dentries)
762    xptr_t         dentry_xp;   // extended pointer on current dentry
763    vfs_dentry_t * dentry_ptr;  // local pointer on current dentry
764    uint32_t       dentry_id;   // dentry index in set of children dentry   
765    uint32_t       dirent_id;   // dirent index in array of dirent
[407]766
[612]767// detailed argument unused
[673]768assert( __FUNCTION__, (detailed == false) , "detailed argument not supported\n");
[612]769 
770    // One loop to scan the target inode xhtab containing the set of dentries
771    // exit loop if no more dentries, or dirent array full
772
773#if DEBUG_DEVFS_GET_USER_DIR
774char       inode_name[CONFIG_VFS_MAX_NAME_LENGTH];
775uint32_t   cycle = (uint32_t)hal_get_cycles();
776thread_t * this  = CURRENT_THREAD;
777vfs_inode_get_name( XPTR( local_cxy , inode ) , inode_name );
778if( DEBUG_DEVFS_GET_USER_DIR < cycle )
779printk("\n[%s]  thread[%x,%x] enter for inode <%s> / cycle %d\n",
780__FUNCTION__, this->process->pid, this->trdid, inode_name , cycle );
781#endif
782
783    // get extended pointer on inode xhtab
784    xhtab_xp  = XPTR( local_cxy , &inode->children );
785
786    // initialize loop variables
787    dentry_xp = xhtab_get_first( xhtab_xp );
788    dentry_id = 0;
789    dirent_id = 0;
790
791    while( (dentry_xp != XPTR_NULL ) && (dirent_id < max_dirent) )
792    {
793        if( dentry_id >= min_dentry )
794        {
795            // copy name into dirent array
796            dentry_ptr = GET_PTR( dentry_xp );
797            strcpy( array[dirent_id].d_name , dentry_ptr->name ); 
798
799            // increment dirent_id
800            dirent_id++;
801        }
802         
803        // update loop variables
804        dentry_xp = xhtab_get_next( xhtab_xp );
805        dentry_id++;
806    }
807
808    // return results of scan
809    *done    = (dentry_xp == XPTR_NULL);
810    *entries = dirent_id;
811
812#if DEBUG_DEVFS_GET_USER_DIR
813cycle = (uint32_t)hal_get_cycles();
814if( DEBUG_DEVFS_GET_USER_DIR < cycle )
815printk("\n[%s]  thread[%x,%x] exit for inode <%s> / %d entries / cycle %d\n",
816__FUNCTION__, this->process->pid, this->trdid, inode_name, entries, cycle );
817#endif
818
819    return 0;
820   
821}  // en devfs_get_user_dir()
822
Note: See TracBrowser for help on using the repository browser.