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

Last change on this file since 428 was 407, checked in by alain, 9 years ago

First implementation of fork/exec.

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