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

Last change on this file since 457 was 457, checked in by alain, 8 years ago

This version modifies the exec syscall and fixes a large number of small bugs.
The version number has been updated (0.1)

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_kernel_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 (DEBUG_SYS_READ & 1)
45extern uint32_t enter_devfs_read;
46extern uint32_t exit_devfs_read;
47#endif
48
49#if (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 DEBUG_DEVFS_INIT
95uint32_t cycle = (uint32_t)hal_get_cycles();
96if( 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 0
102 error = vfs_add_child_in_parent( 0, // 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#if( DEBUG_DEVFS_INIT & 1 )
113if( DEBUG_DEVFS_INIT < cycle )
114printk("\n[DBG] %s : created <dev> inode at cycle %d\n", __FUNCTION__, cycle );
115#endif
116
117 // create DEVFS "external" inode in cluster 0
118 error = vfs_add_child_in_parent( 0, // cxy
119 INODE_TYPE_DIR,
120 FS_TYPE_DEVFS,
121 *devfs_dev_inode_xp,
122 "external",
123 NULL,
124 devfs_external_inode_xp );
125
126 assert( (error == 0) , __FUNCTION__ , "cannot create <external>\n" );
127
128#if DEBUG_DEVFS_INIT
129cycle = (uint32_t)hal_get_cycles();
130if( DEBUG_DEVFS_INIT < cycle )
131printk("\n[DBG] %s : thread %x exit at cycle %d\n",
132__FUNCTION__ , CURRENT_THREAD , cycle );
133#endif
134
135}
136
137///////////////////////////////////////////////////
138void devfs_local_init( xptr_t devfs_dev_inode_xp,
139 xptr_t devfs_external_inode_xp,
140 xptr_t * devfs_internal_inode_xp )
141{
142 char node_name[16];
143 xptr_t chdev_xp;
144 cxy_t chdev_cxy;
145 chdev_t * chdev_ptr;
146 xptr_t inode_xp;
147 uint32_t channel;
148
149#if DEBUG_DEVFS_INIT
150uint32_t cycle = (uint32_t)hal_get_cycles();
151if( DEBUG_DEVFS_INIT < cycle )
152printk("\n[DBG] %s : thread %x enter at cycle %d\n",
153__FUNCTION__ , CURRENT_THREAD , cycle );
154#endif
155
156 // create "internal" directory linked to "dev"
157 snprintf( node_name , 16 , "internal_%x" , local_cxy );
158 vfs_add_child_in_parent( local_cxy,
159 INODE_TYPE_DIR,
160 FS_TYPE_DEVFS,
161 devfs_dev_inode_xp,
162 node_name,
163 NULL,
164 devfs_internal_inode_xp );
165
166 // create MMC chdev inode
167 chdev_xp = chdev_dir.mmc[local_cxy];
168 if( chdev_xp != XPTR_NULL)
169 {
170 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
171 vfs_add_child_in_parent( local_cxy,
172 INODE_TYPE_DEV,
173 FS_TYPE_DEVFS,
174 *devfs_internal_inode_xp,
175 chdev_ptr->name,
176 GET_PTR( chdev_xp ),
177 &inode_xp );
178 }
179
180 // create DMA chdev inodes (one DMA channel per core)
181 for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ )
182 {
183 chdev_xp = chdev_dir.dma[channel];
184 if( chdev_xp != XPTR_NULL)
185 {
186 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
187 vfs_add_child_in_parent( local_cxy,
188 INODE_TYPE_DEV,
189 FS_TYPE_DEVFS,
190 *devfs_internal_inode_xp,
191 chdev_ptr->name,
192 GET_PTR( chdev_xp ),
193 &inode_xp );
194 }
195 }
196
197 // create an IOB inode in cluster containing IOB chdev
198 chdev_xp = chdev_dir.iob;
199 if( chdev_xp != XPTR_NULL )
200 {
201 chdev_cxy = GET_CXY( chdev_xp );
202 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
203 if( chdev_cxy == local_cxy )
204 {
205 vfs_add_child_in_parent( local_cxy,
206 INODE_TYPE_DEV,
207 FS_TYPE_DEVFS,
208 devfs_external_inode_xp,
209 chdev_ptr->name,
210 GET_PTR( chdev_xp ),
211 &inode_xp );
212 }
213 }
214
215 // create a PIC inode in cluster containing PIC chdev
216 chdev_xp = chdev_dir.pic;
217 if( chdev_xp != XPTR_NULL )
218 {
219 chdev_cxy = GET_CXY( chdev_xp );
220 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
221 if( chdev_cxy == local_cxy )
222 {
223 vfs_add_child_in_parent( local_cxy,
224 INODE_TYPE_DEV,
225 FS_TYPE_DEVFS,
226 devfs_external_inode_xp,
227 chdev_ptr->name,
228 GET_PTR( chdev_xp ),
229 &inode_xp );
230 }
231 }
232
233 // create a TXT_RX inode in each cluster containing a TXT_RX chdev
234 for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
235 {
236 chdev_xp = chdev_dir.txt_rx[channel];
237 if( chdev_xp != XPTR_NULL )
238 {
239 chdev_cxy = GET_CXY( chdev_xp );
240 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
241 if( chdev_cxy == local_cxy )
242 {
243 vfs_add_child_in_parent( local_cxy,
244 INODE_TYPE_DEV,
245 FS_TYPE_DEVFS,
246 devfs_external_inode_xp,
247 chdev_ptr->name,
248 GET_PTR( chdev_xp ),
249 &inode_xp );
250 }
251 }
252 }
253
254 // create a TXT_TX inode in each cluster containing a TXT_TX chdev
255 for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
256 {
257 chdev_xp = chdev_dir.txt_tx[channel];
258 if( chdev_xp != XPTR_NULL )
259 {
260 chdev_cxy = GET_CXY( chdev_xp );
261 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
262 if( chdev_cxy == local_cxy )
263 {
264 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 GET_PTR( chdev_xp ),
270 &inode_xp );
271 }
272 }
273 }
274
275 // create an IOC inode in each cluster containing an IOC chdev
276 for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
277 {
278 chdev_xp = chdev_dir.ioc[channel];
279 if( chdev_xp != XPTR_NULL )
280 {
281 chdev_cxy = GET_CXY( chdev_xp );
282 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
283 if( chdev_cxy == local_cxy )
284 {
285 vfs_add_child_in_parent( local_cxy,
286 INODE_TYPE_DEV,
287 FS_TYPE_DEVFS,
288 devfs_external_inode_xp,
289 chdev_ptr->name,
290 GET_PTR( chdev_xp ),
291 &inode_xp );
292 }
293 }
294 }
295
296 // create a FBF inode in each cluster containing a FBF chdev
297 for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
298 {
299 chdev_xp = chdev_dir.fbf[channel];
300 if( chdev_xp != XPTR_NULL )
301 {
302 chdev_cxy = GET_CXY( chdev_xp );
303 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
304 if( chdev_cxy == local_cxy )
305 {
306 vfs_add_child_in_parent( local_cxy,
307 INODE_TYPE_DEV,
308 FS_TYPE_DEVFS,
309 devfs_external_inode_xp,
310 chdev_ptr->name,
311 GET_PTR( chdev_xp ),
312 &inode_xp );
313 }
314 }
315 }
316
317 // create a NIC_RX inode in each cluster containing a NIC_RX chdev
318 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
319 {
320 chdev_xp = chdev_dir.nic_rx[channel];
321 if( chdev_xp != XPTR_NULL )
322 {
323 chdev_cxy = GET_CXY( chdev_xp );
324 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
325 if( chdev_cxy == local_cxy )
326 {
327 vfs_add_child_in_parent( local_cxy,
328 INODE_TYPE_DEV,
329 FS_TYPE_DEVFS,
330 devfs_external_inode_xp,
331 chdev_ptr->name,
332 GET_PTR( chdev_xp ),
333 &inode_xp );
334 }
335 }
336 }
337
338 // create a NIC_TX inode in each cluster containing a NIC_TX chdev
339 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
340 {
341 chdev_xp = chdev_dir.nic_tx[channel];
342 if( chdev_xp != XPTR_NULL )
343 {
344 chdev_cxy = GET_CXY( chdev_xp );
345 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
346 if( chdev_cxy == local_cxy )
347 {
348 vfs_add_child_in_parent( local_cxy,
349 INODE_TYPE_DEV,
350 FS_TYPE_DEVFS,
351 devfs_external_inode_xp,
352 chdev_ptr->name,
353 GET_PTR( chdev_xp ),
354 &inode_xp );
355 }
356 }
357 }
358
359#if DEBUG_DEVFS_INIT
360cycle = (uint32_t)hal_get_cycles();
361if( DEBUG_DEVFS_INIT < cycle )
362printk("\n[DBG] %s : thread %x exit at cycle %d\n",
363__FUNCTION__ , CURRENT_THREAD , cycle );
364#endif
365
366} // end devfs_local_init()
367
368//////////////////////////////////////////
369int devfs_user_move( bool_t to_buffer,
370 xptr_t file_xp,
371 void * u_buf,
372 uint32_t size )
373{
374 assert( ( file_xp != XPTR_NULL ) , __FUNCTION__ , "file_xp == XPTR_NULL" );
375
376 assert( ( size < CONFIG_TXT_KBUF_SIZE ) , __FUNCTION__ , "string size too large" );
377
378 xptr_t chdev_xp;
379 cxy_t chdev_cxy;
380 chdev_t * chdev_ptr; // associated chdev type
381 uint32_t func; // chdev functionnal type
382 uint32_t channel; // chdev channel index
383 error_t error;
384
385 char k_buf[CONFIG_TXT_KBUF_SIZE]; // local kernel buffer
386
387#if (DEBUG_SYS_READ & 1)
388enter_devfs_read = hal_time_stamp();
389#endif
390
391#if (DEBUG_SYS_WRITE & 1)
392enter_devfs_write = hal_time_stamp();
393#endif
394
395#if DEBUG_DEVFS_MOVE
396uint32_t cycle = (uint32_t)hal_get_cycles();
397if( DEBUG_DEVFS_MOVE < cycle )
398printk("\n[DBG] %s : thread %x enter / to_mem %d / cycle %d\n",
399__FUNCTION__ , CURRENT_THREAD , to_buffer , cycle );
400#endif
401
402 // get extended pointer on chdev_xp
403 chdev_xp = chdev_from_file( file_xp );
404
405 // get cluster and local pointer on chdev
406 chdev_cxy = GET_CXY( chdev_xp );
407 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
408
409 // get chdev functionnal type and channel
410 func = hal_remote_lw( XPTR( chdev_cxy , &chdev_ptr->func ) );
411 channel = hal_remote_lw( XPTR( chdev_cxy , &chdev_ptr->channel ) );
412
413 // action depends on "func" and "to_buffer"
414 if( func == DEV_FUNC_TXT )
415 {
416 if( to_buffer ) // TXT read
417 {
418 uint32_t i;
419 for( i = 0 ; i < size ; i++ )
420 {
421 error = dev_txt_read( channel , &k_buf[i] );
422
423 if( error )
424 {
425 return -1;
426 }
427 else
428 {
429 hal_strcpy_to_uspace( u_buf , k_buf , size );
430 }
431 }
432
433#if DEBUG_DEVFS_MOVE
434cycle = (uint32_t)hal_get_cycles();
435if( DEBUG_DEVFS_MOVE < cycle )
436printk("\n[DBG] %s : thread %x exit / to_mem %d / cycle %d\n",
437__FUNCTION__ , CURRENT_THREAD , to_buffer / cycle );
438#endif
439
440#if (DEBUG_SYS_READ & 1)
441exit_devfs_read = hal_time_stamp();
442#endif
443 return size;
444 }
445 else // TXT write
446 {
447 hal_strcpy_from_uspace( k_buf , u_buf , size );
448
449 error = dev_txt_write( channel , k_buf , size );
450 if( error )
451 {
452 return -1;
453 }
454 else
455 {
456
457#if DEBUG_DEVFS_MOVE
458cycle = (uint32_t)hal_get_cycles();
459if( DEBUG_DEVFS_MOVE < cycle )
460printk("\n[DBG] %s : thread %x exit / to_mem %d / cycle %d\n",
461__FUNCTION__ , CURRENT_THREAD , to_buffer / cycle );
462#endif
463
464#if (DEBUG_SYS_WRITE & 1)
465exit_devfs_write = hal_time_stamp();
466#endif
467 return size;
468 }
469 }
470 }
471 else
472 {
473 assert( false , __FUNCTION__ ,
474 "%s does not support direct user access", chdev_func_str(func) );
475
476 return -1;
477 }
478
479} // end devfs_user_move()
480
481
Note: See TracBrowser for help on using the repository browser.