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

Last change on this file since 657 was 657, checked in by alain, 7 years ago

Introduce remote_buf.c/.h & socket.c/.h files.
Update dev_nic.c/.h files.

File size: 28.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,2018,2019,2020)
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///////////////////////////////////
56xptr_t devfs_ctx_alloc( cxy_t cxy )
57{
58 kmem_req_t req;
59
60 req.type = KMEM_KCM;
61 req.order = bits_log2( sizeof(devfs_ctx_t) );
62 req.flags = AF_KERNEL | AF_ZERO;
63
64 // allocates devfs context from target cluster
65 return XPTR( cxy , kmem_remote_alloc( cxy , &req ) );
66}
67
68/////////////////////////////////////////////
69void devfs_ctx_init( xptr_t devfs_ctx_xp,
70 xptr_t devfs_dev_inode_xp,
71 xptr_t devfs_external_inode_xp )
72{
73 // get cluster and local pointer on remote devfs context
74 devfs_ctx_t * devfs_ctx_ptr = GET_PTR( devfs_ctx_xp );
75 cxy_t devfs_ctx_cxy = GET_CXY( devfs_ctx_xp );
76
77 // set values in remote devfs context
78 hal_remote_s64( XPTR( devfs_ctx_cxy , &devfs_ctx_ptr->dev_inode_xp ),
79 devfs_dev_inode_xp );
80
81 hal_remote_s64( XPTR( devfs_ctx_cxy , &devfs_ctx_ptr->external_inode_xp ),
82 devfs_external_inode_xp );
83
84 // register devfs context in the remote fs_context array[]
85 hal_remote_spt( XPTR( devfs_ctx_cxy , &fs_context[FS_TYPE_DEVFS].extend ),
86 devfs_ctx_ptr );
87}
88
89//////////////////////////////////////////////
90void devfs_ctx_destroy( xptr_t devfs_ctx_xp )
91{
92 kmem_req_t req;
93
94 // get cluster and local pointer on devfs context
95 devfs_ctx_t * devfs_ctx_ptr = GET_PTR( devfs_ctx_xp );
96 cxy_t devfs_ctx_cxy = GET_CXY( devfs_ctx_xp );
97
98 req.type = KMEM_KCM;
99 req.ptr = devfs_ctx_ptr;
100
101 // release devfs context descriptor to remote cluster
102 kmem_remote_free( devfs_ctx_cxy , &req );
103}
104
105/////////////////////////////////////////////////
106void devfs_global_init( xptr_t root_inode_xp,
107 xptr_t * devfs_dev_inode_xp,
108 xptr_t * devfs_external_inode_xp )
109{
110 error_t error;
111 xptr_t unused_xp; // required by vfs_add_child_in_parent()
112 vfs_inode_t * inode;
113
114 // get
115
116 // create DEVFS "dev" inode in cluster 0
117 error = vfs_add_child_in_parent( 0, // cxy
118 FS_TYPE_DEVFS,
119 root_inode_xp,
120 "dev",
121 &unused_xp,
122 devfs_dev_inode_xp );
123
124 // update inode "type" field
125 inode = GET_PTR( *devfs_dev_inode_xp );
126 inode->type = INODE_TYPE_DIR;
127
128 // create dentries <.> and <..> in <dev>
129 error |= vfs_add_special_dentries( *devfs_dev_inode_xp,
130 root_inode_xp );
131
132 if( error )
133 {
134 printk("\n[PANIC] in %s : cannot create <dev> directory\n", __FUNCTION__ );
135 hal_core_sleep();
136 }
137
138#if DEBUG_DEVFS_GLOBAL_INIT
139uint32_t cycle = (uint32_t)hal_get_cycles();
140thread_t * this = CURRENT_THREAD;
141if( DEBUG_DEVFS_GLOBAL_INIT < cycle )
142printk("\n[%s] thread[%x,%x] created <dev> inode / cycle %d\n",
143__FUNCTION__, this->process->pid, this->trdid, cycle );
144#endif
145
146 // create DEVFS "external" inode in cluster 0
147 error = vfs_add_child_in_parent( 0, // cxy
148 FS_TYPE_DEVFS,
149 *devfs_dev_inode_xp,
150 "external",
151 &unused_xp,
152 devfs_external_inode_xp );
153
154 // update inode "type" field
155 inode = GET_PTR( *devfs_external_inode_xp );
156 inode->type = INODE_TYPE_DIR;
157
158 // create dentries <.> and <..> in <external>
159 error |= vfs_add_special_dentries( *devfs_external_inode_xp,
160 *devfs_dev_inode_xp );
161
162 if( error )
163 {
164 printk("\n[PANIC] in %s : cannot create <external> directory\n", __FUNCTION__ );
165 hal_core_sleep();
166 }
167
168#if DEBUG_DEVFS_GLOBAL_INIT
169cycle = (uint32_t)hal_get_cycles();
170if( DEBUG_DEVFS_GLOBAL_INIT < cycle )
171printk("\n[%s] thread[%x,%x] created <external> inode / cycle %d\n",
172__FUNCTION__, this->process->pid, this->trdid, cycle );
173#endif
174
175} // end devfs_global_init()
176
177///////////////////////////////////////////////////
178void devfs_local_init( xptr_t devfs_dev_inode_xp,
179 xptr_t devfs_external_inode_xp )
180{
181 xptr_t internal_inode_xp; // extended pointer on <internal> inode
182 vfs_inode_t * internal_inode_ptr; // local pointer on <internal> inode
183 char node_name[16];
184 xptr_t chdev_xp;
185 cxy_t chdev_cxy;
186 chdev_t * chdev_ptr;
187 xptr_t inode_xp;
188 vfs_inode_t * inode_ptr;
189 uint32_t channel;
190 xptr_t unused_xp; // required by add_child_in_parent()
191 error_t error;
192
193
194#if DEBUG_DEVFS_LOCAL_INIT
195uint32_t cycle = (uint32_t)hal_get_cycles();
196thread_t * this = CURRENT_THREAD;
197if( DEBUG_DEVFS_LOCAL_INIT < cycle )
198printk("\n[%s] thread[%x,%x] enter / cycle %d\n",
199__FUNCTION__, this->process->pid, this->trdid, cycle );
200#endif
201
202 // create <internal> directory
203 snprintf( node_name , 16 , "internal_%x" , local_cxy );
204
205 error = vfs_add_child_in_parent( local_cxy, // target cluster
206 FS_TYPE_DEVFS, // FS type
207 devfs_dev_inode_xp, // parent inode
208 node_name, // child name
209 &unused_xp,
210 &internal_inode_xp ); // child inode
211
212 // set <internal> inode "type" field
213 internal_inode_ptr = GET_PTR( internal_inode_xp );
214 internal_inode_ptr->type = INODE_TYPE_DEV;
215
216 // create dentries <.> and <..> in <internal>
217 error |= vfs_add_special_dentries( internal_inode_xp,
218 devfs_dev_inode_xp );
219
220 if( error )
221 {
222 printk("\n[PANIC] in %s : cannot create <internal> directory\n", __FUNCTION__ );
223 hal_core_sleep();
224 }
225
226#if DEBUG_DEVFS_LOCAL_INIT
227cycle = (uint32_t)hal_get_cycles();
228if( DEBUG_DEVFS_LOCAL_INIT < cycle )
229printk("\n[%s] thread[%x,%x] created <%s> inode in cluster %x / cycle %d\n",
230__FUNCTION__, this->process->pid, this->trdid, node_name, local_cxy, cycle );
231#endif
232
233 // create MMC chdev inode
234 chdev_xp = chdev_dir.mmc[local_cxy];
235 if( chdev_xp != XPTR_NULL)
236 {
237 chdev_ptr = GET_PTR( chdev_xp );
238 chdev_cxy = GET_CXY( chdev_xp );
239
240 if( chdev_cxy != local_cxy )
241 {
242 printk("\n[PANIC] in %s : illegal MMC chdev in cluster %x\n",
243 __FUNCTION__, local_cxy );
244 hal_core_sleep();
245 }
246
247 error = vfs_add_child_in_parent( local_cxy,
248 FS_TYPE_DEVFS,
249 internal_inode_xp,
250 chdev_ptr->name,
251 &unused_xp,
252 &inode_xp );
253
254 if( error )
255 {
256 printk("\n[PANIC] in %s : cannot create MMC inode in cluster %x\n",
257 __FUNCTION__, local_cxy );
258 hal_core_sleep();
259 }
260
261 // update child inode "extend" and "type" fields
262 inode_ptr = GET_PTR( inode_xp );
263 inode_ptr->extend = chdev_ptr;
264 inode_ptr->type = INODE_TYPE_DEV;
265
266#if DEBUG_DEVFS_LOCAL_INIT
267cycle = (uint32_t)hal_get_cycles();
268if( DEBUG_DEVFS_LOCAL_INIT < cycle )
269printk("\n[%s] thread[%x,%x] created <mmc> inode in cluster %x\n",
270__FUNCTION__, this->process->pid, this->trdid, local_cxy, cycle );
271#endif
272
273 }
274
275 // create DMA chdev inodes (one DMA channel per core)
276 for( channel = 0 ; channel < LOCAL_CLUSTER->cores_nr ; channel++ )
277 {
278 chdev_xp = chdev_dir.dma[channel];
279 if( chdev_xp != XPTR_NULL)
280 {
281 chdev_ptr = GET_PTR( chdev_xp );
282 chdev_cxy = GET_CXY( chdev_xp );
283
284 if( chdev_cxy != local_cxy )
285 {
286 printk("\n[PANIC] in %s : illegal DMA chdev in cluster %x\n",
287 __FUNCTION__, local_cxy );
288 hal_core_sleep();
289 }
290
291 error = vfs_add_child_in_parent( local_cxy,
292 FS_TYPE_DEVFS,
293 internal_inode_xp,
294 chdev_ptr->name,
295 &unused_xp,
296 &inode_xp );
297 if( error )
298 {
299 printk("\n[PANIC] in %s : cannot create DMA inode in cluster %x\n",
300 __FUNCTION__, local_cxy );
301 hal_core_sleep();
302 }
303
304 // update child inode "extend" and "type" fields
305 inode_ptr = GET_PTR( inode_xp );
306 inode_ptr->extend = chdev_ptr;
307 inode_ptr->type = INODE_TYPE_DEV;
308
309#if DEBUG_DEVFS_LOCAL_INIT
310cycle = (uint32_t)hal_get_cycles();
311if( DEBUG_DEVFS_LOCAL_INIT < cycle )
312printk("\n[%s] thread [%x,%x] created <dma[%d]> inode in cluster %x\n",
313__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
314#endif
315 }
316 }
317
318 // create an IOB inode in cluster containing IOB chdev
319 chdev_xp = chdev_dir.iob;
320 if( chdev_xp != XPTR_NULL )
321 {
322 chdev_cxy = GET_CXY( chdev_xp );
323 chdev_ptr = GET_PTR( chdev_xp );
324
325 if( chdev_cxy == local_cxy )
326 {
327 error = vfs_add_child_in_parent( local_cxy,
328 FS_TYPE_DEVFS,
329 devfs_external_inode_xp,
330 chdev_ptr->name,
331 &unused_xp,
332 &inode_xp );
333 if( error )
334 {
335 printk("\n[PANIC] in %s : cannot create IOB inode in cluster %x\n",
336 __FUNCTION__, local_cxy );
337 hal_core_sleep();
338 }
339
340 // update child inode "extend" and "type" fields
341 inode_ptr = GET_PTR( inode_xp );
342 inode_ptr->extend = chdev_ptr;
343 inode_ptr->type = INODE_TYPE_DEV;
344
345#if DEBUG_DEVFS_LOCAL_INIT
346cycle = (uint32_t)hal_get_cycles();
347if( DEBUG_DEVFS_LOCAL_INIT < cycle )
348printk("\n[%s] thread[%x,%x] created <iob> inode in cluster %x\n",
349__FUNCTION__, this->process->pid, this->trdid, local_cxy, cycle );
350#endif
351 }
352 }
353
354 // create a PIC inode in cluster containing PIC chdev
355 chdev_xp = chdev_dir.pic;
356 if( chdev_xp != XPTR_NULL )
357 {
358 chdev_cxy = GET_CXY( chdev_xp );
359 chdev_ptr = GET_PTR( chdev_xp );
360
361 if( chdev_cxy == local_cxy )
362 {
363 error = vfs_add_child_in_parent( local_cxy,
364 FS_TYPE_DEVFS,
365 devfs_external_inode_xp,
366 chdev_ptr->name,
367 &unused_xp,
368 &inode_xp );
369
370 if( error )
371 {
372 printk("\n[PANIC] in %s : cannot create PIC inode in cluster %x\n",
373 __FUNCTION__, local_cxy );
374 hal_core_sleep();
375 }
376
377 // update child inode "extend" field
378 inode_ptr = GET_PTR( inode_xp );
379 inode_ptr->extend = chdev_ptr;
380 inode_ptr->type = INODE_TYPE_DEV;
381
382#if DEBUG_DEVFS_LOCAL_INIT
383cycle = (uint32_t)hal_get_cycles();
384if( DEBUG_DEVFS_LOCAL_INIT < cycle )
385printk("\n[%s] thread[%x,%x] created <pic> inode in cluster %x\n",
386__FUNCTION__, this->process->pid, this->trdid, local_cxy, cycle );
387#endif
388 }
389 }
390
391 // create a TXT_RX inode in each cluster containing a TXT_RX chdev
392 for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
393 {
394 chdev_xp = chdev_dir.txt_rx[channel];
395 if( chdev_xp != XPTR_NULL )
396 {
397 chdev_cxy = GET_CXY( chdev_xp );
398 chdev_ptr = GET_PTR( chdev_xp );
399
400 if( chdev_cxy == local_cxy )
401 {
402 error = vfs_add_child_in_parent( local_cxy,
403 FS_TYPE_DEVFS,
404 devfs_external_inode_xp,
405 chdev_ptr->name,
406 &unused_xp,
407 &inode_xp );
408
409 if( error )
410 {
411 printk("\n[PANIC] in %s : cannot create TXT_RX inode in cluster %x\n",
412 __FUNCTION__, local_cxy );
413 hal_core_sleep();
414 }
415
416 // update child inode "extend" and "type" fields
417 inode_ptr = GET_PTR( inode_xp );
418 inode_ptr->extend = chdev_ptr;
419 inode_ptr->type = INODE_TYPE_DEV;
420
421#if DEBUG_DEVFS_LOCAL_INIT
422cycle = (uint32_t)hal_get_cycles();
423if( DEBUG_DEVFS_LOCAL_INIT < cycle )
424printk("\n[%s] thread[%x,%x] created <txt_rx[%d]> inode in cluster %x\n",
425__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
426#endif
427 }
428 }
429 }
430
431 // create a TXT_TX inode in each cluster containing a TXT_TX chdev
432 for( channel = 0 ; channel < CONFIG_MAX_TXT_CHANNELS ; channel++ )
433 {
434 chdev_xp = chdev_dir.txt_tx[channel];
435 if( chdev_xp != XPTR_NULL )
436 {
437 chdev_cxy = GET_CXY( chdev_xp );
438 chdev_ptr = GET_PTR( chdev_xp );
439
440 if( chdev_cxy == local_cxy )
441 {
442 error = vfs_add_child_in_parent( local_cxy,
443 FS_TYPE_DEVFS,
444 devfs_external_inode_xp,
445 chdev_ptr->name,
446 &unused_xp,
447 &inode_xp );
448 if( error )
449 {
450 printk("\n[PANIC] in %s : cannot create TXT_TX inode in cluster %x\n",
451 __FUNCTION__, local_cxy );
452 hal_core_sleep();
453 }
454
455 // update child inode "extend" and "type" fields
456 inode_ptr = GET_PTR( inode_xp );
457 inode_ptr->extend = chdev_ptr;
458 inode_ptr->type = INODE_TYPE_DEV;
459
460#if DEBUG_DEVFS_LOCAL_INIT
461cycle = (uint32_t)hal_get_cycles();
462if( DEBUG_DEVFS_LOCAL_INIT < cycle )
463printk("\n[%s] thread[%x,%x] created <txt_tx[%d]> inode in cluster %x\n",
464__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
465#endif
466 }
467 }
468 }
469
470 // create an IOC inode in each cluster containing an IOC chdev
471 for( channel = 0 ; channel < CONFIG_MAX_IOC_CHANNELS ; channel++ )
472 {
473 chdev_xp = chdev_dir.ioc[channel];
474 if( chdev_xp != XPTR_NULL )
475 {
476 chdev_cxy = GET_CXY( chdev_xp );
477 chdev_ptr = GET_PTR( chdev_xp );
478
479 if( chdev_cxy == local_cxy )
480 {
481 error = vfs_add_child_in_parent( local_cxy,
482 FS_TYPE_DEVFS,
483 devfs_external_inode_xp,
484 chdev_ptr->name,
485 &unused_xp,
486 &inode_xp );
487 if( error )
488 {
489 printk("\n[PANIC] in %s : cannot create IOC inode in cluster %x\n",
490 __FUNCTION__, local_cxy );
491 hal_core_sleep();
492 }
493
494 // update child inode "extend" and "type" fields
495 inode_ptr = GET_PTR( inode_xp );
496 inode_ptr->extend = chdev_ptr;
497 inode_ptr->type = INODE_TYPE_DEV;
498
499#if DEBUG_DEVFS_LOCAL_INIT
500cycle = (uint32_t)hal_get_cycles();
501if( DEBUG_DEVFS_LOCAL_INIT < cycle )
502printk("\n[%s] thread[%x,%x] created <ioc[%d]> inode in cluster %x\n",
503__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
504#endif
505 }
506 }
507 }
508
509 // create a FBF inode in each cluster containing a FBF chdev
510 for( channel = 0 ; channel < CONFIG_MAX_FBF_CHANNELS ; channel++ )
511 {
512 chdev_xp = chdev_dir.fbf[channel];
513 if( chdev_xp != XPTR_NULL )
514 {
515 chdev_cxy = GET_CXY( chdev_xp );
516 chdev_ptr = GET_PTR( chdev_xp );
517
518 if( chdev_cxy == local_cxy )
519 {
520 error = vfs_add_child_in_parent( local_cxy,
521 FS_TYPE_DEVFS,
522 devfs_external_inode_xp,
523 chdev_ptr->name,
524 &unused_xp,
525 &inode_xp );
526 if( error )
527 {
528 printk("\n[PANIC] in %s : cannot create FBF inode in cluster %x\n",
529 __FUNCTION__, local_cxy );
530 hal_core_sleep();
531 }
532
533 // update child inode "extend" and "type" fields
534 inode_ptr = GET_PTR( inode_xp );
535 inode_ptr->extend = chdev_ptr;
536 inode_ptr->type = INODE_TYPE_DEV;
537
538#if DEBUG_DEVFS_LOCAL_INIT
539cycle = (uint32_t)hal_get_cycles();
540if( DEBUG_DEVFS_LOCAL_INIT < cycle )
541printk("\n[%s] thread[%x,%x] created <fbf[%d]> inode in cluster %x\n",
542__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
543#endif
544 }
545 }
546 }
547
548 // create a NIC_RX inode in each cluster containing a NIC_RX chdev
549 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
550 {
551 chdev_xp = chdev_dir.nic_rx[channel];
552 if( chdev_xp != XPTR_NULL )
553 {
554 chdev_cxy = GET_CXY( chdev_xp );
555 chdev_ptr = GET_PTR( chdev_xp );
556
557 if( chdev_cxy == local_cxy )
558 {
559 error = vfs_add_child_in_parent( local_cxy,
560 FS_TYPE_DEVFS,
561 devfs_external_inode_xp,
562 chdev_ptr->name,
563 &unused_xp,
564 &inode_xp );
565 if( error )
566 {
567 printk("\n[PANIC] in %s : cannot create NIC_RX inode in cluster %x\n",
568 __FUNCTION__, local_cxy );
569 hal_core_sleep();
570 }
571
572 // update child inode "extend" and "type" fields
573 inode_ptr = GET_PTR( inode_xp );
574 inode_ptr->extend = chdev_ptr;
575 inode_ptr->type = INODE_TYPE_DEV;
576
577#if DEBUG_DEVFS_LOCAL_INIT
578cycle = (uint32_t)hal_get_cycles();
579if( DEBUG_DEVFS_LOCAL_INIT < cycle )
580printk("\n[%s] thread[%x,%x] created <nic_rx[%d]> inode in cluster %x\n",
581__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
582#endif
583 }
584 }
585 }
586
587 // create a NIC_TX inode in each cluster containing a NIC_TX chdev
588 for( channel = 0 ; channel < CONFIG_MAX_NIC_CHANNELS ; channel++ )
589 {
590 chdev_xp = chdev_dir.nic_tx[channel];
591 if( chdev_xp != XPTR_NULL )
592 {
593 chdev_cxy = GET_CXY( chdev_xp );
594 chdev_ptr = GET_PTR( chdev_xp );
595
596 if( chdev_cxy == local_cxy )
597 {
598 error = vfs_add_child_in_parent( local_cxy,
599 FS_TYPE_DEVFS,
600 devfs_external_inode_xp,
601 chdev_ptr->name,
602 &unused_xp,
603 &inode_xp );
604 if( error )
605 {
606 printk("\n[PANIC] in %s : cannot create NIC_TX inode in cluster %x\n",
607 __FUNCTION__, local_cxy );
608 hal_core_sleep();
609 }
610
611 // update child inode "extend" and "type" fields
612 inode_ptr = GET_PTR( inode_xp );
613 inode_ptr->extend = chdev_ptr;
614 inode_ptr->type = INODE_TYPE_DEV;
615
616#if DEBUG_DEVFS_LOCAL_INIT
617cycle = (uint32_t)hal_get_cycles();
618if( DEBUG_DEVFS_LOCAL_INIT < cycle )
619printk("\n[%s] thread[%x,%x] created <nic_tx[%d]> inode in cluster %x\n",
620__FUNCTION__, this->process->pid, this->trdid, channel, local_cxy, cycle );
621#endif
622 }
623 }
624 }
625} // end devfs_local_init()
626
627//////////////////////////////////////////
628int devfs_user_move( bool_t to_buffer,
629 xptr_t file_xp,
630 char * u_buf,
631 uint32_t size )
632{
633 xptr_t chdev_xp;
634 cxy_t chdev_cxy;
635 chdev_t * chdev_ptr; // associated chdev type
636 uint32_t func; // chdev functionnal type
637 uint32_t channel; // chdev channel index
638 uint32_t burst; // number of bytes in a burst
639 uint32_t todo; // number of bytes not yet moved
640 error_t error;
641 uint32_t i;
642
643 char k_buf[CONFIG_TXT_KBUF_SIZE]; // local kernel buffer
644
645assert( ( file_xp != XPTR_NULL ) , "file_xp == XPTR_NULL" );
646
647#if (DEBUG_SYS_READ & 1)
648enter_devfs_read = hal_time_stamp();
649#endif
650
651#if (DEBUG_SYS_WRITE & 1)
652enter_devfs_write = hal_time_stamp();
653#endif
654
655#if DEBUG_DEVFS_MOVE
656uint32_t cycle = (uint32_t)hal_get_cycles();
657thread_t * this = CURRENT_THREAD;
658if( DEBUG_DEVFS_MOVE < cycle )
659printk("\n[%s] thread[%x,%x] enter / to_mem %d / cycle %d\n",
660__FUNCTION__, this->process->pid, this->trdid, to_buffer, cycle );
661#endif
662
663 // get extended pointer on chdev_xp
664 chdev_xp = chdev_from_file( file_xp );
665
666 // get cluster and local pointer on chdev
667 chdev_cxy = GET_CXY( chdev_xp );
668 chdev_ptr = (chdev_t *)GET_PTR( chdev_xp );
669
670 // get chdev functionnal type and channel
671 func = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->func ) );
672 channel = hal_remote_l32( XPTR( chdev_cxy , &chdev_ptr->channel ) );
673
674// Only TXT devices are associated to a pseudo-file
675assert( ( func == DEV_FUNC_TXT ) , __FUNCTION__, "illegal device func_type");
676
677 // initialise number of bytes to move
678 todo = size;
679
680 /////////////// TXT read
681 if( to_buffer )
682 {
683 while( todo )
684 {
685 // set burst size
686 if( todo > CONFIG_TXT_KBUF_SIZE ) burst = CONFIG_TXT_KBUF_SIZE;
687 else burst = todo;
688
689 // read burst bytes from TXT device to kernel buffer
690 for( i = 0 ; i < burst ; i++ )
691 {
692 error = dev_txt_read( channel , &k_buf[i] );
693
694 if( error ) return -1;
695 }
696
697 // move burst bytes from k_buf to u_buf
698 hal_strcpy_to_uspace( u_buf,
699 XPTR( local_cxy , k_buf ),
700 burst );
701
702 // update loop variables
703 todo -= burst;
704 u_buf += burst;
705 }
706
707#if DEBUG_DEVFS_MOVE
708cycle = (uint32_t)hal_get_cycles();
709if( DEBUG_DEVFS_MOVE < cycle )
710printk("\n[%s] thread[%x,%x] exit / to_mem %d / cycle %d\n",
711__FUNCTION__, this->process->pid, this->trdid, to_buffer, cycle );
712#endif
713
714#if (DEBUG_SYS_READ & 1)
715exit_devfs_read = hal_time_stamp();
716#endif
717 return size;
718 }
719 ///////////// TXT write
720 else
721 {
722 while( todo )
723 {
724 // set burst size
725 if( todo > CONFIG_TXT_KBUF_SIZE ) burst = CONFIG_TXT_KBUF_SIZE;
726 else burst = todo;
727
728 // move burst bytes from u_buf to k_buf
729 hal_strcpy_from_uspace( XPTR( local_cxy , k_buf ) , u_buf , burst );
730
731 // write burst bytes from kernel buffer to TXT device
732 error = dev_txt_write( channel , k_buf , burst );
733
734 if( error ) return -1;
735
736 // update loop variables
737 todo -= burst;
738 u_buf += burst;
739 }
740
741#if DEBUG_DEVFS_MOVE
742cycle = (uint32_t)hal_get_cycles();
743if( DEBUG_DEVFS_MOVE < cycle )
744printk("\n[%s] thread[%x,%x] exit / to_mem %d / cycle %d\n",
745__FUNCTION__, this->process->pid, this->trdid, to_buffer, cycle );
746#endif
747
748#if (DEBUG_SYS_WRITE & 1)
749exit_devfs_write = hal_time_stamp();
750#endif
751 return size;
752 }
753
754} // end devfs_user_move()
755
756///////////////////////////////////////////////////////
757error_t devfs_get_user_dir( struct vfs_inode_s * inode,
758 struct dirent * array,
759 uint32_t max_dirent,
760 uint32_t min_dentry,
761 bool_t detailed,
762 uint32_t * entries,
763 bool_t * done )
764{
765 xptr_t xhtab_xp; // extended pointer on inode xhtab (children dentries)
766 xptr_t dentry_xp; // extended pointer on current dentry
767 vfs_dentry_t * dentry_ptr; // local pointer on current dentry
768 uint32_t dentry_id; // dentry index in set of children dentry
769 uint32_t dirent_id; // dirent index in array of dirent
770
771// detailed argument unused
772assert( (detailed == false) , "detailed argument not supported\n");
773
774 // One loop to scan the target inode xhtab containing the set of dentries
775 // exit loop if no more dentries, or dirent array full
776
777#if DEBUG_DEVFS_GET_USER_DIR
778char inode_name[CONFIG_VFS_MAX_NAME_LENGTH];
779uint32_t cycle = (uint32_t)hal_get_cycles();
780thread_t * this = CURRENT_THREAD;
781vfs_inode_get_name( XPTR( local_cxy , inode ) , inode_name );
782if( DEBUG_DEVFS_GET_USER_DIR < cycle )
783printk("\n[%s] thread[%x,%x] enter for inode <%s> / cycle %d\n",
784__FUNCTION__, this->process->pid, this->trdid, inode_name , cycle );
785#endif
786
787 // get extended pointer on inode xhtab
788 xhtab_xp = XPTR( local_cxy , &inode->children );
789
790 // initialize loop variables
791 dentry_xp = xhtab_get_first( xhtab_xp );
792 dentry_id = 0;
793 dirent_id = 0;
794
795 while( (dentry_xp != XPTR_NULL ) && (dirent_id < max_dirent) )
796 {
797 if( dentry_id >= min_dentry )
798 {
799 // copy name into dirent array
800 dentry_ptr = GET_PTR( dentry_xp );
801 strcpy( array[dirent_id].d_name , dentry_ptr->name );
802
803 // increment dirent_id
804 dirent_id++;
805 }
806
807 // update loop variables
808 dentry_xp = xhtab_get_next( xhtab_xp );
809 dentry_id++;
810 }
811
812 // return results of scan
813 *done = (dentry_xp == XPTR_NULL);
814 *entries = dirent_id;
815
816#if DEBUG_DEVFS_GET_USER_DIR
817cycle = (uint32_t)hal_get_cycles();
818if( DEBUG_DEVFS_GET_USER_DIR < cycle )
819printk("\n[%s] thread[%x,%x] exit for inode <%s> / %d entries / cycle %d\n",
820__FUNCTION__, this->process->pid, this->trdid, inode_name, entries, cycle );
821#endif
822
823 return 0;
824
825} // en devfs_get_user_dir()
826
Note: See TracBrowser for help on using the repository browser.