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

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

Fix several bugs in vfs.c, fatfs.c, and devfs.c to support
the <.> and <..> directory entries.

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