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
Line 
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_kernel_types.h>
26#include <hal_special.h>
27#include <hal_uspace.h>
28#include <printk.h>
29#include <string.h>
30#include <chdev.h>
31#include <thread.h>
32#include <dev_txt.h>
33#include <cluster.h>
34#include <vfs.h>
35#include <kmem.h>
36#include <devfs.h>
37
38/////////////////////////////////////////////////////////////////////////////////////////
39//     Extern variables
40/////////////////////////////////////////////////////////////////////////////////////////
41
42extern vfs_ctx_t            fs_context[];   // allocated in kernel_init.c
43extern chdev_directory_t    chdev_dir;      // allocated in kernel_init.c
44
45#if (DEBUG_SYS_READ & 1)
46extern uint32_t  enter_devfs_read;
47extern uint32_t  exit_devfs_read;
48#endif
49
50#if (DEBUG_SYS_WRITE & 1)
51extern uint32_t  enter_devfs_write;
52extern uint32_t  exit_devfs_write;
53#endif
54
55/////////////////////////////////////
56devfs_ctx_t * devfs_ctx_alloc( void )
57{
58    kmem_req_t    req;
59
60        req.type    = KMEM_DEVFS_CTX;
61        req.size    = sizeof(devfs_ctx_t);
62    req.flags   = AF_KERNEL | AF_ZERO;
63
64        return (devfs_ctx_t *)kmem_alloc( &req );
65}
66
67/////////////////////////////////////////////
68void devfs_ctx_init( devfs_ctx_t * devfs_ctx,
69                     xptr_t        devfs_dev_inode_xp,
70                     xptr_t        devfs_external_inode_xp )
71{
72    devfs_ctx->dev_inode_xp      = devfs_dev_inode_xp;
73    devfs_ctx->external_inode_xp = devfs_external_inode_xp;
74
75    fs_context[FS_TYPE_DEVFS].extend = devfs_ctx;
76}
77
78/////////////////////////////////////////////////
79void devfs_ctx_destroy( devfs_ctx_t * devfs_ctx )
80{
81    kmem_req_t    req;
82
83    req.type = KMEM_DEVFS_CTX;
84    req.ptr  = devfs_ctx;
85    kmem_free( &req );
86}
87
88/////////////////////////////////////////////////
89void devfs_global_init( xptr_t   root_inode_xp,
90                        xptr_t * devfs_dev_inode_xp,
91                        xptr_t * devfs_external_inode_xp )
92{
93    error_t  error;
94    xptr_t   unused_xp;   // required by vfs_add_child_in_parent()
95
96    // create DEVFS "dev" inode in cluster 0
97    error = vfs_add_child_in_parent( 0,                // cxy
98                                     INODE_TYPE_DIR,
99                                     FS_TYPE_DEVFS,
100                                     root_inode_xp,
101                                     "dev",
102                                     &unused_xp,
103                                     devfs_dev_inode_xp );
104
105    // create dentries <.> and <..> in <dev>
106    error |= vfs_add_special_dentries( *devfs_dev_inode_xp,
107                                       root_inode_xp );
108
109// check success
110assert( (error == 0) , "cannot create <dev>\n" );
111
112#if DEBUG_DEVFS_INIT
113uint32_t   cycle = (uint32_t)hal_get_cycles();
114thread_t * this  = CURRENT_THREAD;
115if( DEBUG_DEVFS_INIT < cycle )
116printk("\n[%s] thread[%x,%x] created <dev> inode / cycle %d\n",
117__FUNCTION__, this->process->pid, this->trdid, cycle );
118#endif
119
120    // create DEVFS "external" inode in cluster 0
121    error = vfs_add_child_in_parent( 0,               // cxy
122                                     INODE_TYPE_DIR,
123                                     FS_TYPE_DEVFS,
124                                     *devfs_dev_inode_xp,
125                                     "external",
126                                     &unused_xp,
127                                     devfs_external_inode_xp );
128
129    // create dentries <.> and <..> in <external>
130    error |= vfs_add_special_dentries( *devfs_external_inode_xp,
131                                       *devfs_dev_inode_xp );
132
133// check success
134assert( (error == 0) , "cannot create <external>\n" );
135
136#if DEBUG_DEVFS_INIT
137cycle = (uint32_t)hal_get_cycles();
138if( DEBUG_DEVFS_INIT < cycle )
139printk("\n[%s] thread[%x,%x] created <external> inode / cycle %d\n",
140__FUNCTION__, this->process->pid, this->trdid, cycle );
141#endif
142
143}  // end devfs_global_init()
144
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 )
149{
150    char          node_name[16];
151    xptr_t        chdev_xp;
152    cxy_t         chdev_cxy;
153    chdev_t     * chdev_ptr;
154    xptr_t        inode_xp;
155    cxy_t         inode_cxy;
156    vfs_inode_t * inode_ptr;
157    uint32_t      channel;
158    xptr_t        unused_xp;    // required by add_child_in_parent()
159    error_t       error;
160
161    // create "internal" directory
162    snprintf( node_name , 16 , "internal_%x" , local_cxy );
163
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
179#if DEBUG_DEVFS_INIT
180uint32_t   cycle = (uint32_t)hal_get_cycles();
181thread_t * this  = CURRENT_THREAD;
182if( DEBUG_DEVFS_INIT < cycle )
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 );
185#endif
186
187    // create MMC chdev inode
188    chdev_xp  = chdev_dir.mmc[local_cxy];
189    if( chdev_xp != XPTR_NULL)
190    {
191        chdev_ptr = GET_PTR( chdev_xp );
192        chdev_cxy = GET_CXY( chdev_xp );
193
194assert( (chdev_cxy == local_cxy ), "illegal MMC chdev in cluster %x\n", local_cxy );
195
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 );
203
204assert( (error == 0) , "cannot create MMC inode\n" );
205
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       
211#if DEBUG_DEVFS_INIT
212cycle = (uint32_t)hal_get_cycles();
213if( DEBUG_DEVFS_INIT < cycle )
214printk("\n[%s] thread[%x,%x] created <mmc> inode in cluster %x\n",
215__FUNCTION__, this->process->pid, this->trdid, local_cxy, cycle );
216#endif
217
218    }
219
220    // create DMA chdev inodes (one DMA channel per core)
221    for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ )
222    {
223        chdev_xp  = chdev_dir.dma[channel];
224        if( chdev_xp != XPTR_NULL)
225        {
226            chdev_ptr = GET_PTR( chdev_xp );
227            chdev_cxy = GET_CXY( chdev_xp );
228
229assert( (chdev_cxy == local_cxy ), "illegal DMA chdev in cluster %x\n", local_cxy );
230
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 );
238
239assert( (error == 0) , "cannot create DMA inode\n" );
240
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       
246#if DEBUG_DEVFS_INIT
247cycle = (uint32_t)hal_get_cycles();
248if( DEBUG_DEVFS_INIT < cycle )
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 );
251#endif
252        }
253    }
254
255    // create an IOB inode in cluster containing IOB chdev
256    chdev_xp = chdev_dir.iob;
257    if( chdev_xp != XPTR_NULL )
258    {
259        chdev_cxy = GET_CXY( chdev_xp );
260        chdev_ptr = GET_PTR( chdev_xp );
261
262        if( chdev_cxy == local_cxy )
263        {
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 );
271
272assert( (error == 0) , "cannot create IOB inode\n" );
273
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       
279#if DEBUG_DEVFS_INIT
280cycle = (uint32_t)hal_get_cycles();
281if( DEBUG_DEVFS_INIT < cycle )
282printk("\n[%s] thread[%x,%x] created <iob> inode in cluster %x\n",
283__FUNCTION__, this->process->pid, this->trdid, local_cxy, cycle );
284#endif
285        }
286    }
287       
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 );
293        chdev_ptr = GET_PTR( chdev_xp );
294
295        if( chdev_cxy == local_cxy )
296        {
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 );
304
305assert( (error == 0) , "cannot create PIC inode\n" );
306
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       
312#if DEBUG_DEVFS_INIT
313cycle = (uint32_t)hal_get_cycles();
314if( DEBUG_DEVFS_INIT < cycle )
315printk("\n[%s] thread[%x,%x] created <pic> inode in cluster %x\n",
316__FUNCTION__, this->process->pid, this->trdid, local_cxy, cycle );
317#endif
318        }
319    }
320
321    // create a TXT_RX inode in each cluster containing a TXT_RX chdev
322    for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
323    {
324        chdev_xp = chdev_dir.txt_rx[channel];
325        if( chdev_xp != XPTR_NULL )
326        {
327            chdev_cxy = GET_CXY( chdev_xp );
328            chdev_ptr = GET_PTR( chdev_xp );
329
330            if( chdev_cxy == local_cxy )
331            {
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 );
339
340assert( (error == 0) , "cannot create TXT_RX inode\n" );
341
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       
347#if DEBUG_DEVFS_INIT
348cycle = (uint32_t)hal_get_cycles();
349if( DEBUG_DEVFS_INIT < cycle )
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 );
352#endif
353            }
354        }
355    }
356
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 );
364            chdev_ptr = GET_PTR( chdev_xp );
365
366            if( chdev_cxy == local_cxy )
367            {
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 );
375
376assert( (error == 0) , "cannot create TXT_TX inode\n" );
377
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       
383#if DEBUG_DEVFS_INIT
384cycle = (uint32_t)hal_get_cycles();
385if( DEBUG_DEVFS_INIT < cycle )
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 );
388#endif
389            }
390        }
391    }
392
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 )
398        {
399            chdev_cxy = GET_CXY( chdev_xp );
400            chdev_ptr = GET_PTR( chdev_xp );
401
402            if( chdev_cxy == local_cxy )
403            {
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 );
411
412assert( (error == 0) , "cannot create IOC inode\n" );
413
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       
419#if DEBUG_DEVFS_INIT
420cycle = (uint32_t)hal_get_cycles();
421if( DEBUG_DEVFS_INIT < cycle )
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 );
424#endif
425            }
426        }
427    }
428
429    // create a FBF inode in each cluster containing a FBF chdev
430    for( channel = 0 ; channel < CONFIG_MAX_FBF_CHANNELS ; channel++ )
431    {
432        chdev_xp = chdev_dir.fbf[channel];
433        if( chdev_xp != XPTR_NULL )
434        {
435            chdev_cxy = GET_CXY( chdev_xp );
436            chdev_ptr = GET_PTR( chdev_xp );
437
438            if( chdev_cxy == local_cxy )
439            {
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 );
447
448assert( (error == 0) , "cannot create FBF inode\n" );
449
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       
455#if DEBUG_DEVFS_INIT
456cycle = (uint32_t)hal_get_cycles();
457if( DEBUG_DEVFS_INIT < cycle )
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 );
460#endif
461            }
462        }
463    }
464
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 )
470        {
471            chdev_cxy = GET_CXY( chdev_xp );
472            chdev_ptr = GET_PTR( chdev_xp );
473
474            if( chdev_cxy == local_cxy )
475            {
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 
491#if DEBUG_DEVFS_INIT
492cycle = (uint32_t)hal_get_cycles();
493if( DEBUG_DEVFS_INIT < cycle )
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 );
496#endif
497            }
498        }
499    }
500
501    // create a NIC_TX inode in each cluster containing a NIC_TX chdev
502    for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
503    {
504        chdev_xp = chdev_dir.nic_tx[channel];
505        if( chdev_xp != XPTR_NULL )
506        {
507            chdev_cxy = GET_CXY( chdev_xp );
508            chdev_ptr = GET_PTR( chdev_xp );
509
510            if( chdev_cxy == local_cxy )
511            {
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 );
519
520assert( (error == 0) , "cannot create NIC_TX inode\n" );
521
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       
527#if DEBUG_DEVFS_INIT
528cycle = (uint32_t)hal_get_cycles();
529if( DEBUG_DEVFS_INIT < cycle )
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 );
532#endif
533            }
534        }
535    }
536}  // end devfs_local_init()
537
538//////////////////////////////////////////
539int devfs_user_move( bool_t     to_buffer,
540                     xptr_t     file_xp,
541                     char     * u_buf,
542                     uint32_t   size )
543{
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;
553
554    char             k_buf[CONFIG_TXT_KBUF_SIZE];  // local kernel buffer
555
556assert( ( file_xp != XPTR_NULL ) , "file_xp == XPTR_NULL" );
557
558#if (DEBUG_SYS_READ & 1)
559enter_devfs_read = hal_time_stamp();
560#endif
561
562#if (DEBUG_SYS_WRITE & 1)
563enter_devfs_write = hal_time_stamp();
564#endif
565
566#if DEBUG_DEVFS_MOVE
567uint32_t   cycle = (uint32_t)hal_get_cycles();
568thread_t * this  = CURRENT_THREAD;
569if( DEBUG_DEVFS_MOVE < cycle )
570printk("\n[%s] thread[%x,%x] enter / to_mem %d / cycle %d\n",
571__FUNCTION__, this->process->pid, this->trdid, to_buffer, cycle );
572#endif
573
574    // get extended pointer on chdev_xp
575    chdev_xp = chdev_from_file( file_xp );
576
577    // get cluster and local pointer on chdev
578    chdev_cxy  = GET_CXY( chdev_xp );
579    chdev_ptr  = (chdev_t *)GET_PTR( chdev_xp );
580
581    // get chdev functionnal type and channel
582    func    = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->func ) );
583    channel = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->channel ) );
584
585// Only TXT devices are associated to a pseudo-file
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++ )
602            {
603                error = dev_txt_read( channel , &k_buf[i] );
604
605                if( error )  return -1;
606            }
607
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
616#if DEBUG_DEVFS_MOVE
617cycle = (uint32_t)hal_get_cycles();
618if( DEBUG_DEVFS_MOVE < cycle )
619printk("\n[%s] thread[%x,%x] exit / to_mem %d / cycle %d\n",
620__FUNCTION__, this->process->pid, this->trdid, to_buffer, cycle );
621#endif
622
623#if (DEBUG_SYS_READ & 1)
624exit_devfs_read = hal_time_stamp();
625#endif
626            return size;
627    } 
628    ///////////// TXT write 
629    else               
630    {
631        while( todo )
632        {
633            // set burst size
634            if( todo > CONFIG_TXT_KBUF_SIZE ) burst = CONFIG_TXT_KBUF_SIZE;
635            else                              burst = todo;
636
637            // move burst bytes from u_buf to k_buf
638            hal_strcpy_from_uspace( k_buf , u_buf , burst );
639
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
650#if DEBUG_DEVFS_MOVE
651cycle = (uint32_t)hal_get_cycles();
652if( DEBUG_DEVFS_MOVE < cycle )
653printk("\n[%s] thread[%x,%x] exit / to_mem %d / cycle %d\n",
654__FUNCTION__, this->process->pid, this->trdid, to_buffer, cycle );
655#endif
656
657#if (DEBUG_SYS_WRITE & 1)
658exit_devfs_write = hal_time_stamp();
659#endif
660            return size;
661    }
662
663}  // end devfs_user_move()
664
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
679
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.