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

Last change on this file since 436 was 435, checked in by alain, 4 years ago

Fix a bad bug in scheduler...

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