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

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

1) introduce a dev_ioc_sync_write() function in IOC API,

to improve the DEVFS synchronous update.

2) fix a big bug in both the user_dir_create() and user_dir_destroy()

functions: add an extended pointer on the reference client process
in the function's arguments.

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