source: soft/giet_vm/giet_kernel/sys_handler.c @ 554

Last change on this file since 554 was 547, checked in by alain, 9 years ago

Move the peripheral initialisation from the boot.c to the kernel_init.c

  • Property svn:executable set to *
File size: 56.7 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : sys_handler.c
3// Date     : 01/04/2012
4// Author   : alain greiner and joel porquet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7
8#include <sys_handler.h>
9#include <tty_driver.h>
10#include <tim_driver.h>
11#include <nic_driver.h>
12#include <mmc_driver.h>
13#include <mwr_driver.h>
14#include <cma_driver.h>
15#include <ctx_handler.h>
16#include <fat32.h>
17#include <utils.h>
18#include <kernel_malloc.h>
19#include <tty0.h>
20#include <vmem.h>
21#include <hard_config.h>
22#include <giet_config.h>
23#include <mapping_info.h>
24#include <irq_handler.h>
25#include <io.h>
26
27#if !defined(SEG_BOOT_MAPPING_BASE)
28# error: You must define SEG_BOOT_MAPPING_BASE in the hard_config.h file
29#endif
30
31#if !defined(NB_TTY_CHANNELS)
32# error: You must define NB_TTY_CHANNELS in the hard_config.h file
33#endif
34
35#if (NB_TTY_CHANNELS < 1)
36# error: NB_TTY_CHANNELS cannot be smaller than 1!
37#endif
38
39#if !defined(NB_TIM_CHANNELS)
40# error: You must define NB_TIM_CHANNELS in the hard_config.h file
41#endif
42
43#if !defined(NB_NIC_CHANNELS)
44# error: You must define NB_NIC_CHANNELS in the hard_config.h file
45#endif
46
47#if !defined(NB_CMA_CHANNELS)
48# error: You must define NB_CMA_CHANNELS in the hard_config.h file
49#endif
50
51#if !defined(GIET_NO_HARD_CC)
52# error: You must define GIET_NO_HARD_CC in the giet_config.h file
53#endif
54
55#if !defined ( GIET_NIC_MAC4 )
56# error: You must define GIET_NIC_MAC4 in the giet_config.h file
57#endif
58
59#if !defined ( GIET_NIC_MAC2 )
60# error: You must define GIET_NIC_MAC2 in the giet_config.h file
61#endif
62
63////////////////////////////////////////////////////////////////////////////
64//        Extern variables
65////////////////////////////////////////////////////////////////////////////
66
67// allocated in tty0.c file.
68extern sqt_lock_t _tty0_sqt_lock;
69
70// allocated in mwr_driver.c file.
71extern simple_lock_t  _coproc_lock[X_SIZE*Y_SIZE];
72extern unsigned int   _coproc_done[X_SIZE*Y_SIZE];
73
74// allocated in tty_driver.c file.
75extern unsigned int _tty_rx_full[NB_TTY_CHANNELS];
76extern unsigned int _tty_rx_buf[NB_TTY_CHANNELS];
77
78////////////////////////////////////////////////////////////////////////////
79//     Channel allocators for peripherals
80//     (TTY[0] is reserved for kernel)
81////////////////////////////////////////////////////////////////////////////
82
83__attribute__((section(".kdata")))
84unsigned int _tty_channel_allocator    = 1;
85
86__attribute__((section(".kdata")))
87unsigned int _tim_channel_allocator    = 0;
88
89__attribute__((section(".kdata")))
90unsigned int _cma_channel_allocator    = 0;
91
92__attribute__((section(".kdata")))
93unsigned int _nic_rx_channel_allocator = 0;
94
95__attribute__((section(".kdata")))
96unsigned int _nic_tx_channel_allocator = 0;
97
98////////////////////////////////////////////////////////////////////////////
99//     NIC_RX and NIC_TX chbuf arrays
100////////////////////////////////////////////////////////////////////////////
101
102__attribute__((section(".kdata")))
103nic_chbuf_t  _nic_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
104
105__attribute__((section(".kdata")))
106nic_chbuf_t  _nic_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(64)));
107
108////////////////////////////////////////////////////////////////////////////
109// FBF related chbuf descriptors array, indexed by the CMA channel index.
110// Physical addresses of these chbuf descriptors required for L2 cache sync.
111////////////////////////////////////////////////////////////////////////////
112
113__attribute__((section(".kdata")))
114fbf_chbuf_t _fbf_chbuf[NB_CMA_CHANNELS] __attribute__((aligned(64)));
115
116__attribute__((section(".kdata")))
117unsigned long long _fbf_chbuf_paddr[NB_CMA_CHANNELS];
118
119////////////////////////////////////////////////////////////////////////////
120//    Initialize the syscall vector with syscall handlers
121// Note: This array must be synchronised with the define in file stdio.h
122////////////////////////////////////////////////////////////////////////////
123
124__attribute__((section(".kdata")))
125const void * _syscall_vector[64] = 
126{
127    &_sys_proc_xyp,             /* 0x00 */
128    &_get_proctime,             /* 0x01 */
129    &_sys_tty_write,            /* 0x02 */
130    &_sys_tty_read,             /* 0x03 */
131    &_sys_tty_alloc,            /* 0x04 */
132    &_sys_tty_get_lock,         /* 0x05 */
133    &_sys_tty_release_lock,     /* 0x06 */
134    &_sys_heap_info,            /* 0x07 */
135    &_sys_local_task_id,        /* 0x08 */
136    &_sys_global_task_id,       /* 0x09 */ 
137    &_sys_fbf_cma_alloc,        /* 0x0A */
138    &_sys_fbf_cma_start,        /* 0x0B */
139    &_sys_fbf_cma_display,      /* 0x0C */
140    &_sys_fbf_cma_stop,         /* 0x0D */
141    &_sys_task_exit,            /* 0x0E */
142    &_sys_procs_number,         /* 0x0F */
143
144    &_sys_fbf_sync_write,       /* 0x10 */
145    &_sys_fbf_sync_read,        /* 0x11 */
146    &_sys_thread_id,            /* 0x12 */
147    &_sys_ukn,                  /* 0x13 */
148    &_sys_tim_alloc,            /* 0x14 */
149    &_sys_tim_start,            /* 0x15 */ 
150    &_sys_tim_stop,             /* 0x16 */
151    &_sys_ukn,                  /* 0x17 */
152    &_sys_ukn,                  /* 0x18 */   
153    &_sys_context_switch,       /* 0x19 */
154    &_sys_vseg_get_vbase,       /* 0x1A */
155    &_sys_vseg_get_length,      /* 0x1B */
156    &_sys_xy_from_ptr,          /* 0x1C */
157    &_sys_ukn,                  /* 0x1D */
158    &_sys_ukn,                  /* 0x1E */
159    &_sys_ukn,                  /* 0x1F */
160
161    &_fat_user_open,            /* 0x20 */
162    &_fat_user_read,            /* 0x21 */
163    &_fat_user_write,           /* 0x22 */
164    &_fat_user_lseek,           /* 0x23 */
165    &_fat_fstat,                /* 0x24 */
166    &_fat_close,                /* 0x25 */
167    &_sys_ukn,                  /* 0x26 */
168    &_sys_ukn,                  /* 0x27 */
169    &_sys_ukn,                  /* 0x28 */
170    &_sys_ukn,                  /* 0x29 */
171    &_sys_ukn,                  /* 0x2A */
172    &_sys_ukn,                  /* 0x2B */
173    &_sys_ukn,                  /* 0x2C */
174    &_sys_ukn,                  /* 0x2D */
175    &_sys_ukn,                  /* 0x2E */
176    &_sys_ukn,                  /* 0x2F */
177
178    &_sys_nic_alloc,            /* 0x30 */
179    &_sys_nic_start,            /* 0x31 */
180    &_sys_nic_move,             /* 0x32 */
181    &_sys_nic_stop,             /* 0x33 */
182    &_sys_nic_stats,            /* 0x34 */
183    &_sys_nic_clear,            /* 0x35 */ 
184    &_sys_ukn,                  /* 0x36 */
185    &_sys_ukn,                  /* 0x37 */
186    &_sys_coproc_register_get,  /* 0x38 */   
187    &_sys_coproc_register_set,  /* 0x39 */
188    &_sys_coproc_release,       /* 0x3A */
189    &_sys_coproc_completed,     /* 0x3B */
190    &_sys_coproc_alloc,         /* 0x3C */
191    &_sys_coproc_channel_init,  /* 0x3D */
192    &_sys_coproc_channel_start, /* 0x3E */
193    &_sys_coproc_channel_stop,  /* 0x3F */
194};
195
196
197//////////////////////////////////////////////////////////////////////////////
198//           Coprocessors related syscall handlers
199//////////////////////////////////////////////////////////////////////////////
200
201///////////////////////////////////////////////////////
202int _sys_coproc_register_set( unsigned int  cluster_xy,
203                              unsigned int  reg_index,
204                              unsigned int  value )
205{
206    // TODO checking coprocessor ownership...
207
208    _mwr_set_coproc_register( cluster_xy , reg_index , value );
209    return 0;
210} 
211
212///////////////////////////////////////////////////////
213int _sys_coproc_register_get( unsigned int   cluster_xy,
214                              unsigned int   reg_index,
215                              unsigned int*  buffer )
216{
217    // TODO checking coprocessor ownership...
218
219    *buffer = _mwr_get_coproc_register( cluster_xy , reg_index );
220    return 0;
221} 
222
223//////////////////////////////////////////////////
224int _sys_coproc_alloc( unsigned int   coproc_type,
225                       unsigned int*  coproc_info,
226                       unsigned int*  cluster_xy )
227{
228    // In this implementation, the allocation policy is constrained:
229    // the coprocessor must be in the same cluster as the calling task,
230    // and ther is at most one coprocessor per cluster
231
232    mapping_header_t  * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
233    mapping_cluster_t * cluster = _get_cluster_base(header);
234    mapping_periph_t  * periph  = _get_periph_base(header);
235
236    // get cluster coordinates and cluster global index
237    unsigned int procid     = _get_procid();
238    unsigned int x          = procid >> (Y_WIDTH + P_WIDTH);
239    unsigned int y          = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
240    unsigned int cluster_id = x*Y_SIZE + y;
241 
242    // search coprocessor in cluster
243    mapping_periph_t*  found = NULL;
244    unsigned int min   = cluster[cluster_id].periph_offset;
245    unsigned int max   = min + cluster[cluster_id].periphs;
246    unsigned int periph_id;
247    for ( periph_id = min ; periph_id < max ; periph_id++ )
248    {
249        if ( (periph[periph_id].type == PERIPH_TYPE_MWR) &&
250             (periph[periph_id].subtype == coproc_type) )
251        {
252            found = &periph[periph_id];
253            break;
254        }
255    } 
256
257    if ( found != NULL )
258    {
259        // get the lock (at most one coproc per cluster)
260        _simple_lock_acquire( &_coproc_lock[cluster_id] );
261 
262        // returns coprocessor info
263        *coproc_info = (found->arg0 & 0xFF)     |
264                       (found->arg1 & 0xFF)<<8  |
265                       (found->arg2 & 0xFF)<<16 |
266                       (found->arg3 & 0xFF)<<24 ;
267        *cluster_xy = (x<<Y_WIDTH) + y;
268
269#if GIET_DEBUG_COPROC
270_printf("\n[GIET DEBUG COPROC] _sys_coproc_alloc() in cluster[%d,%d]\n"
271        "  coproc_info = %x / cluster_xy = %x\n",
272        x , y , *coproc_info , *cluster_xy );
273#endif
274        return 0;
275    }
276    else
277    {
278         _printf("\n[GIET_ERROR] in _sys_coproc_alloc(): no coprocessor "
279                 " with type %d available in cluster[%d,%d]\n",
280                 coproc_type , x , y );
281        return -1;
282    }
283}  // end _sys_coproc_alloc()
284
285//////////////////////////////////////////////////
286int _sys_coproc_release( unsigned int cluster_xy )
287{
288    // TODO checking coprocessor ownership...
289
290    // check cluster coordinates
291    unsigned int cx     = cluster_xy >> Y_WIDTH;
292    unsigned int cy     = cluster_xy & ((1<<Y_WIDTH)-1);
293    unsigned int procid = _get_procid();
294    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
295    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
296    if ( (x != cx) || (y != cy) )
297    {
298         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
299                 "wrong cluster coordinates\n");
300         return -1;
301    }
302
303    // compute coprocessor global index
304    unsigned int coproc_id = x * Y_SIZE + y;
305
306    // release coprocessor
307    _simple_lock_release( &_coproc_lock[coproc_id] );
308
309#if GIET_DEBUG_COPROC
310_printf("\n[GIET DEBUG COPROC] _sys_coproc_release() in cluster[%d,%d]\n",
311        x, y );
312#endif
313
314    return 0;
315}  // end _sys_coproc_release()
316
317/////////////////////////////////////////////////////////////////
318int _sys_coproc_channel_init( unsigned int            cluster_xy,
319                              unsigned int            channel,
320                              giet_coproc_channel_t*  desc )
321{
322    // TODO checking coprocessor ownership...
323
324    // check cluster coordinates
325    unsigned int cx     = cluster_xy >> Y_WIDTH;
326    unsigned int cy     = cluster_xy & ((1<<Y_WIDTH)-1);
327    unsigned int procid = _get_procid();
328    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
329    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
330    if ( (x != cx) || (y != cy) )
331    {
332         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init(): "
333                 "wrong cluster coordinates\n");
334         return -1;
335    }
336
337    // check channel mode
338    unsigned mode = desc->channel_mode;
339    if ( (mode != MODE_MWMR) && 
340         (mode != MODE_DMA_IRQ) && 
341         (mode != MODE_DMA_NO_IRQ) )
342    {
343         _printf("\n[GIET_ERROR] in _sys_coproc_channel_init():"
344                 " illegal mode\n");
345         return -1;
346    }
347
348    // get memory buffer size
349    unsigned int size = desc->buffer_size;
350 
351    // physical addresses
352    unsigned long long buffer_paddr;
353    unsigned int       buffer_lsb;
354    unsigned int       buffer_msb;
355    unsigned long long mwmr_paddr;
356    unsigned int       mwmr_lsb;
357    unsigned int       mwmr_msb;
358    unsigned long long lock_paddr;
359    unsigned int       lock_lsb;
360    unsigned int       lock_msb;
361
362    unsigned int       flags;     // unused
363
364    // compute memory buffer physical address
365    buffer_paddr = _v2p_translate( desc->buffer_vaddr , &flags );
366    buffer_lsb   = (unsigned int)buffer_paddr;
367    buffer_msb   = (unsigned int)(buffer_paddr>>32); 
368
369    // call MWMR_DMA driver
370    _mwr_set_channel_register( cluster_xy, channel, CHANNEL_MODE, mode ); 
371    _mwr_set_channel_register( cluster_xy, channel, CHANNEL_SIZE, size ); 
372    _mwr_set_channel_register( cluster_xy, channel, CHANNEL_BUFFER_LSB, buffer_lsb ); 
373    _mwr_set_channel_register( cluster_xy, channel, CHANNEL_BUFFER_MSB, buffer_msb ); 
374                       
375    if ( mode == MODE_MWMR )
376    {
377        // compute MWMR descriptor physical address
378        mwmr_paddr = _v2p_translate( desc->mwmr_vaddr , &flags );
379        mwmr_lsb = (unsigned int)mwmr_paddr;
380        mwmr_msb = (unsigned int)(mwmr_paddr>>32); 
381
382        // call MWMR_DMA driver
383        _mwr_set_channel_register( cluster_xy, channel, CHANNEL_MWMR_LSB, mwmr_lsb ); 
384        _mwr_set_channel_register( cluster_xy, channel, CHANNEL_MWMR_MSB, mwmr_msb ); 
385
386        // compute lock physical address
387        lock_paddr = _v2p_translate( desc->lock_vaddr , &flags );
388        lock_lsb = (unsigned int)lock_paddr;
389        lock_msb = (unsigned int)(lock_paddr>>32); 
390
391        // call MWMR_DMA driver
392        _mwr_set_channel_register( cluster_xy, channel, CHANNEL_LOCK_LSB, lock_lsb ); 
393        _mwr_set_channel_register( cluster_xy, channel, CHANNEL_LOCK_MSB, lock_msb ); 
394    }
395
396#if GIET_DEBUG_COPROC
397_printf("\n[GIET DEBUG COPROC] _sys_coproc_channel_init() in cluster[%d,%d]\n"
398        " channel =  %d / mode = %d / buffer_size = %d\n"
399        " buffer_paddr = %l / mwmr_paddr = %l / lock_paddr = %l\n",
400        x , y , channel , mode , size ,
401        buffer_paddr, mwmr_paddr, lock_paddr );
402#endif
403       
404    return 0;
405} // end _sys_coproc_channel_init()
406
407////////////////////////////////////////////////////////
408int _sys_coproc_channel_start( unsigned int  cluster_xy,
409                               unsigned int  channel )
410{
411    // TODO checking coprocessor ownership...
412
413    // check cluster coordinates
414    unsigned int cx     = cluster_xy >> Y_WIDTH;
415    unsigned int cy     = cluster_xy & ((1<<Y_WIDTH)-1);
416    unsigned int procid = _get_procid();
417    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
418    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
419    if ( (x != cx) || (y != cy) )
420    {
421         _printf("\n[GIET_ERROR] in _sys_coproc_channel_start():"
422                 " wrong coordinates\n");
423         return -1;
424    }
425 
426    // reset synchronisation variable
427    unsigned int coproc_id = (x * Y_SIZE) + y;
428    _coproc_done[coproc_id] = 0;
429
430    // call MWMR_DMA driver
431    _mwr_set_channel_register( cluster_xy, channel, CHANNEL_RUNNING, 1 ); 
432
433#if GIET_DEBUG_COPROC
434_printf("\n[GIET DEBUG COPROC] _sys_coproc_channel_start() in cluster[%d,%d]"
435        " / channel = %d\n", x , y , channel );
436#endif
437
438    return 0;
439} // end _sys_coproc_channel_start()
440
441///////////////////////////////////////////////////////
442int _sys_coproc_channel_stop( unsigned int  cluster_xy,
443                              unsigned int  channel )
444{
445    // TODO checking coprocessor ownership...
446
447    // check cluster coordinates
448    unsigned int cx     = cluster_xy >> Y_WIDTH;
449    unsigned int cy     = cluster_xy & ((1<<Y_WIDTH)-1);
450    unsigned int procid = _get_procid();
451    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
452    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
453    if ( (x != cx) || (y != cy) )
454    {
455         _printf("\n[GIET_ERROR] in _sys_coproc_channel_stop(): wrong coordinates\n");
456         return -1;
457    }
458 
459    // call MWMR_DMA driver
460    _mwr_set_channel_register( cluster_xy, channel, CHANNEL_RUNNING, 0 );
461
462#if GIET_DEBUG_COPROC
463_printf("\n[GIET DEBUG COPROC] _sys_coproc_channel_stop() in cluster[%d,%d]"
464        " / channel = %d\n", x , y , channel );
465#endif
466
467    return 0;
468} // end _sys_coproc_channel_stop()
469
470/////////////////////////////////////////////////////
471int _sys_coproc_completed( unsigned int  cluster_xy )
472{
473    // TODO checking coprocessor ownership...
474
475    // check cluster coordinates
476    unsigned int cx     = cluster_xy >> Y_WIDTH;
477    unsigned int cy     = cluster_xy & ((1<<Y_WIDTH)-1);
478    unsigned int procid = _get_procid();
479    unsigned int x      = procid >> (Y_WIDTH + P_WIDTH);
480    unsigned int y      = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
481    if ( (x != cx) || (y != cy) )
482    {
483         _printf("\n[GIET_ERROR] in _sys_coproc_completed(): "
484                 "wrong cluster coordinates\n");
485         return -1;
486    }
487 
488    // polling the synchronisation variable
489    unsigned int coproc_id = (x * Y_SIZE) + y;
490    while ( ioread32( &_coproc_done[coproc_id]) == 0 ) asm volatile("nop");
491
492    _coproc_done[coproc_id] = 0;
493
494#if GIET_DEBUG_COPROC
495_printf("\n[GIET DEBUG COPROC] _sys_coproc_completed() in cluster[%d,%d]\n", 
496        x, y );
497#endif
498
499    return 0;
500} // end _sys_coproc_completed()
501
502
503//////////////////////////////////////////////////////////////////////////////
504//             TTY related syscall handlers
505//////////////////////////////////////////////////////////////////////////////
506
507////////////////////
508int _sys_tty_alloc()
509{
510    // get a new TTY terminal index
511    unsigned int channel = _atomic_increment( &_tty_channel_allocator, 1 );
512
513    if ( channel >= NB_TTY_CHANNELS )
514    {
515        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : not enough TTY channels\n");
516        return -1;
517    }
518    else
519    {
520    }
521
522    // allocate a WTI mailbox to the calling proc if external IRQ
523    unsigned int unused;
524    if ( USE_PIC ) _ext_irq_alloc( ISR_TTY_RX , channel , &unused ); 
525   
526    // update calling task index
527    _set_context_slot( CTX_TTY_ID, channel );
528
529    return 0;
530}
531
532/////////////////////////////////////////////////
533int _sys_tty_write( const char*  buffer,   
534                    unsigned int length,    // number of characters
535                    unsigned int channel)   // channel index
536{
537    unsigned int  nwritten;
538
539    // compute and check tty channel
540    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
541    if( channel >= NB_TTY_CHANNELS ) return -1;
542
543    // write string to TTY channel
544    for (nwritten = 0; nwritten < length; nwritten++) 
545    {
546        // check tty's status
547        if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 )  break;
548
549        // write one byte
550        if (buffer[nwritten] == '\n') 
551        {
552            _tty_set_register( channel, TTY_WRITE, (unsigned int)'\r' );
553        }
554        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] );
555    }
556   
557    return nwritten;
558}
559
560////////////////////////////////////////////////
561int _sys_tty_read( char*        buffer, 
562                   unsigned int length,    // unused
563                   unsigned int channel)   // channel index
564{
565    // compute and check tty channel
566    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
567    if( channel >= NB_TTY_CHANNELS ) return -1;
568
569    // read one character from TTY channel
570    if (_tty_rx_full[channel] == 0) 
571    {
572        return 0;
573    }
574    else 
575    {
576        *buffer = _tty_rx_buf[channel];
577        _tty_rx_full[channel] = 0;
578        return 1;
579    }
580}
581
582///////////////////////////////////////////
583int _sys_tty_get_lock( unsigned int   channel,       // unused
584                       unsigned int * save_sr_ptr )
585{
586    // check tty channel
587    if( channel != 0 )  return 1;
588
589    _it_disable( save_sr_ptr );
590    _sqt_lock_acquire( &_tty0_sqt_lock );
591    return 0;
592}
593
594///////////////////////////////////////////////
595int _sys_tty_release_lock( unsigned int   channel,
596                           unsigned int * save_sr_ptr )
597{
598    // check tty channel
599    if( channel != 0 )  return 1;
600
601    _sqt_lock_release( &_tty0_sqt_lock );
602    _it_restore( save_sr_ptr );
603    return 0;
604}
605
606//////////////////////////////////////////////////////////////////////////////
607//             TIM related syscall handlers
608//////////////////////////////////////////////////////////////////////////////
609
610////////////////////
611int _sys_tim_alloc()
612{
613    // get a new timer index
614    unsigned int channel = _atomic_increment( &_tim_channel_allocator, 1 );
615
616    if ( channel >= NB_TIM_CHANNELS )
617    {
618        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : not enough TIM channels\n");
619        return -1;
620    }
621    else
622    {
623        _set_context_slot( CTX_TIM_ID, channel );
624        return 0;
625    }
626}
627
628/////////////////////////////////////////
629int _sys_tim_start( unsigned int period )
630{
631    // get timer index
632    unsigned int channel = _get_context_slot( CTX_TIM_ID );
633    if ( channel >= NB_TIM_CHANNELS )
634    {
635        _printf("\n[GIET_ERROR] in _sys_tim_start() : not enough TIM channels\n");
636        return -1;
637    }
638
639    // start timer
640    _timer_start( channel, period );
641
642    return 0;
643}
644
645///////////////////
646int _sys_tim_stop()
647{
648    // get timer index
649    unsigned int channel = _get_context_slot( CTX_TIM_ID );
650    if ( channel >= NB_TIM_CHANNELS )
651    {
652        _printf("\n[GIET_ERROR] in _sys_tim_stop() : illegal timer index\n");
653        return -1;
654    }
655
656    // stop timer
657    _timer_stop( channel );
658
659    return 0;
660}
661
662//////////////////////////////////////////////////////////////////////////////
663//             NIC related syscall handlers
664//////////////////////////////////////////////////////////////////////////////
665
666#define NIC_CONTAINER_SIZE 4096
667
668////////////////////////////////////////
669int _sys_nic_alloc( unsigned int is_rx,
670                    unsigned int xmax,
671                    unsigned int ymax )
672{
673    // check xmax / ymax parameters
674    if ( xmax > X_SIZE )
675    {
676        _printf("\n[GIET_ERROR] in _sys_nic_alloc() xmax argument too large\n");
677        return -1;
678    }
679    if ( ymax > Y_SIZE )
680    {
681        _printf("\n[GIET_ERROR] in _sys_nic_alloc() ymax argument too large\n");
682        return -1;
683    }
684
685    // get a NIC_RX or NIC_TX channel index
686    unsigned int nic_channel;
687    unsigned int cma_channel;
688
689    if ( is_rx ) nic_channel = _atomic_increment( &_nic_rx_channel_allocator, 1 );
690    else         nic_channel = _atomic_increment( &_nic_tx_channel_allocator, 1 );
691
692    if ( (nic_channel >= NB_NIC_CHANNELS) )
693    {
694        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
695        return -1;
696    }
697
698    // get a CMA channel index
699    cma_channel = _atomic_increment( &_cma_channel_allocator, 1 );
700
701    if ( cma_channel >= NB_CMA_CHANNELS )
702    {
703        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
704        return -1;
705    }
706
707#if GIET_DEBUG_NIC
708unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
709_printf("\n[GIET DEBUG NIC] Task %d enters sys_nic_alloc() at cycle %d\n"
710        "  nic_channel = %d / cma_channel = %d\n",
711        thread , _get_proctime() , nic_channel , cma_channel );
712#endif
713
714    // register nic_index and cma_index in task context
715    if ( is_rx )
716    {
717        _set_context_slot( CTX_NIC_RX_ID, nic_channel );
718        _set_context_slot( CTX_CMA_RX_ID, cma_channel );
719    }
720    else
721    {
722        _set_context_slot( CTX_NIC_TX_ID, nic_channel );
723        _set_context_slot( CTX_CMA_TX_ID, cma_channel );
724    }
725
726    // physical addresses to be registered in the CMA registers
727    unsigned long long nic_chbuf_pbase;     // NIC chbuf physical address
728    unsigned long long ker_chbuf_pbase;     // kernel chbuf physical address
729
730    // allocate one kernel container per cluster in the (xmax / ymax) mesh
731    unsigned int        cx;                 // cluster X coordinate
732    unsigned int        cy;                 // cluster Y coordinate
733    unsigned int        index;              // container index in chbuf
734    unsigned int        vaddr;              // virtual address
735    unsigned long long  cont_paddr;         // container physical address
736
737    unsigned int        flags;              // for _v2p_translate()
738
739    for ( cx = 0 ; cx < xmax ; cx++ )
740    {
741        for ( cy = 0 ; cy < ymax ; cy++ )
742        {
743            // compute index in chbuf
744            index = (cx * ymax) + cy; 
745
746            // allocate the kernel container
747            vaddr = (unsigned int)_remote_malloc( NIC_CONTAINER_SIZE, cx, cy );
748
749            if ( vaddr == 0 )  // not enough kernel heap memory in cluster[cx,cy]
750            {
751                _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough kenel heap"
752                        " in cluster[%d,%d]\n", cx, cy );
753                return -1;
754            }
755
756            // compute container physical address
757            cont_paddr = _v2p_translate( vaddr , &flags );
758
759            // initialize chbuf entry
760            if ( is_rx ) _nic_rx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
761            else         _nic_tx_chbuf[nic_channel].buffer[index].desc = cont_paddr;
762
763#if GIET_DEBUG_NIC
764_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc()"
765        " allocates container in cluster[%d,%d]\n"
766        "  vaddr = %x / paddr = %l\n",
767        thread , cx , cy , vaddr , cont_paddr );
768#endif
769        }
770    }
771
772    // complete kernel chbuf initialisation
773    if ( is_rx )
774    {
775        _nic_rx_chbuf[nic_channel].xmax = xmax;
776        _nic_rx_chbuf[nic_channel].ymax = ymax;
777    }
778    else
779    {
780        _nic_tx_chbuf[nic_channel].xmax = xmax;
781        _nic_tx_chbuf[nic_channel].ymax = ymax;
782    }
783
784    // compute the NIC chbuf descriptor physical address
785    unsigned int offset;
786    if ( is_rx ) offset = 0x4000;
787    else         offset = 0x4080;
788    nic_chbuf_pbase = (((unsigned long long)((X_IO << Y_WIDTH) + Y_IO))<<32) |
789                      (SEG_NIC_BASE + (nic_channel<<15) + offset);
790
791#if GIET_DEBUG_NIC
792_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get NIC chbuf : paddr = %l\n",
793        thread , nic_chbuf_pbase );
794#endif
795
796    // compute the kernel chbuf descriptor physical address
797    if ( is_rx ) vaddr = (unsigned int)( &_nic_rx_chbuf[nic_channel] );
798    else         vaddr = (unsigned int)( &_nic_tx_chbuf[nic_channel] );
799
800    ker_chbuf_pbase = _v2p_translate( vaddr , &flags );
801
802#if GIET_DEBUG_NIC
803_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_alloc() get kernel chbuf\n"
804        "  vaddr = %x / paddr = %l\n",
805        thread , vaddr , ker_chbuf_pbase );
806#endif
807
808    // sync the kernel chbuf in L2 after write in L2
809    _mmc_sync( ker_chbuf_pbase, sizeof( nic_chbuf_t ) );
810
811    // initializes CMA registers defining the source & destination chbufs
812    if ( is_rx )               // NIC to kernel
813    {
814        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(nic_chbuf_pbase) );
815        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
816        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 );
817        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(ker_chbuf_pbase) );
818        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
819        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, xmax * ymax );
820    }
821    else                      // kernel to NIC
822    {
823        _cma_set_register( cma_channel, CHBUF_SRC_DESC , (unsigned int)(ker_chbuf_pbase) );
824        _cma_set_register( cma_channel, CHBUF_SRC_EXT  , (unsigned int)(ker_chbuf_pbase>>32) );
825        _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, xmax * ymax );
826        _cma_set_register( cma_channel, CHBUF_DST_DESC , (unsigned int)(nic_chbuf_pbase) );
827        _cma_set_register( cma_channel, CHBUF_DST_EXT  , (unsigned int)(nic_chbuf_pbase>>32) );
828        _cma_set_register( cma_channel, CHBUF_DST_NBUFS, 2 );
829    }
830
831#if GIET_DEBUG_NIC
832_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_alloc() at cycle %d\n",
833        thread, _get_proctime() );
834#endif
835
836    return nic_channel;
837} // end _sys_nic_alloc()
838
839
840////////////////////////////////////////
841int _sys_nic_start( unsigned int is_rx,
842                    unsigned int channel )
843{
844    unsigned int nic_channel;
845    unsigned int cma_channel;
846
847    // get NIC channel index and CMA channel index from task context
848    if ( is_rx )
849    {
850        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
851        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
852    }
853    else
854    {
855        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
856        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
857    }
858
859#if GIET_DEBUG_NIC
860unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
861_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_start() at cycle %d\n"
862        "  get NIC channel = %d / CMA channel = %d\n",
863        thread, _get_proctime(), nic_channel, cma_channel );
864#endif
865
866    // check NIC and CMA channels index
867    if ( nic_channel != channel )
868    {
869        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal NIC channel\n");
870        return -1;
871    }
872    if ( cma_channel >= NB_CMA_CHANNELS )
873    {
874        _printf("\n[GIET_ERROR] in _sys_nic_start(): illegal CMA channel\n");
875        return -1;
876    }
877
878    // start CMA transfer
879    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , NIC_CONTAINER_SIZE );
880    _cma_set_register( cma_channel, CHBUF_PERIOD   , 0 );     // OUT_OF_ORDER
881    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
882
883    // activates NIC channel
884    _nic_channel_start( nic_channel, is_rx, GIET_NIC_MAC4, GIET_NIC_MAC2 ); 
885
886#if GIET_DEBUG_NIC
887_printf("\n[GIET DEBUG NIC] Task %d exit _sys_nic_start() at cycle %d\n",
888        thread , _get_proctime() );
889#endif
890
891    return 0;
892}  // end _sys_nic_start()
893
894
895//////////////////////////////////////
896int _sys_nic_move( unsigned int is_rx,
897                   unsigned int channel,
898                   void*        buffer )
899{
900
901#if GIET_DEBUG_NIC
902unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
903_printf("\n[GIET DEBUG NIC] Task %d enters _sys_nic_move() at cycle %d\n",
904        thread , _get_proctime() );
905#endif
906
907    // check NIC channel index
908    if ( channel >= NB_NIC_CHANNELS )
909    {
910        _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
911        return -1;
912    }
913
914    // get kernel chbuf virtual address
915    nic_chbuf_t* chbuf;
916    if ( is_rx )  chbuf = &_nic_rx_chbuf[channel];
917    else          chbuf = &_nic_tx_chbuf[channel];
918
919    // get xmax / ymax parameters
920    unsigned int xmax = chbuf->xmax;
921    unsigned int ymax = chbuf->ymax;
922
923    // get cluster coordinates for the processor running the calling task
924    unsigned int  procid = _get_procid();
925    unsigned int  cx     = procid >> (Y_WIDTH + P_WIDTH);
926    unsigned int  cy     = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
927   
928    // check processor coordinates / (xmax,ymax)
929    if ( cx >= xmax )
930    {
931        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor X coordinate = %d"
932                " / xmax = %d\n", cx , xmax );
933        return -1;
934    }
935    if ( cy >= ymax )
936    {
937        _printf("\n[GIET_ERROR] in _sys_nic_move() : processor Y coordinate = %d"
938                " / ymax = %d\n", cy , ymax );
939        return -1;
940    }
941   
942    unsigned long long user_buffer_paddr;    // user buffer physical address
943    unsigned long long kernel_buffer_paddr;  // kernel buffer physical address
944    unsigned long long kernel_chbuf_paddr;   // kernel chbuf physical address
945    unsigned long long buffer_descriptor;    // kernel buffer descriptor
946    unsigned long long buffer_desc_paddr;    // kernel buffer descriptor paddr
947    unsigned int       index;                // kernel buffer index in chbuf
948    unsigned int       flags;                // for _v2P_translate
949
950    // Compute user buffer physical address and check access rights
951    user_buffer_paddr = _v2p_translate( (unsigned int)buffer , &flags );
952
953    if ( (flags & PTE_U) == 0 )
954    {
955        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal buffer address\n");
956        return -1;
957    }
958
959#if GIET_DEBUG_NIC
960_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() get user buffer : paddr = %l\n",
961        thread, user_buffer_paddr );
962#endif
963
964    // compute kernel chbuf physical address (required for sync)
965    kernel_chbuf_paddr = _v2p_translate( (unsigned int)chbuf , &flags );
966
967    // poll local kernel container status until success
968    while ( 1 )
969    {
970        // compute buffer index and buffer descriptor paddr
971        index = (ymax * cx) + cy;
972        buffer_desc_paddr = kernel_chbuf_paddr + (index<<6);
973
974        // inval buffer descriptor in L2 before read in L2
975        _mmc_inval( buffer_desc_paddr , 8 );
976        buffer_descriptor = chbuf->buffer[index].desc;
977
978#if GIET_DEBUG_NIC
979_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() read buf_desc %d at cycle %d\n"
980        "  paddr = %l / buffer descriptor = %l\n",
981        thread, index, _get_proctime(), buffer_desc_paddr, buffer_descriptor );
982#endif
983
984        // test buffer status and break if found
985        if ( ( is_rx != 0 ) && (buffer_descriptor >> 63) == 1 )  break;
986        if ( ( is_rx == 0 ) && (buffer_descriptor >> 63) == 0 )  break;
987    }
988
989    // compute kernel buffer physical address
990    kernel_buffer_paddr = buffer_descriptor & 0x0000FFFFFFFFFFFFULL;
991   
992    // move one container
993    if ( is_rx )              // RX transfer
994    {
995        // inval kernel buffer in L2 before read in L2
996        _mmc_inval( kernel_buffer_paddr, NIC_CONTAINER_SIZE );
997
998        // transfer data from kernel buffer to user buffer
999        _physical_memcpy( user_buffer_paddr, 
1000                          kernel_buffer_paddr, 
1001                          NIC_CONTAINER_SIZE );
1002#if GIET_DEBUG_NIC
1003_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer kernel buffer %l\n"
1004        " to user buffer %l at cycle %d\n",
1005        thread , kernel_buffer_paddr , user_buffer_paddr , _get_proctime() );
1006#endif
1007
1008    }
1009    else                      // TX transfer
1010    {
1011        // transfer data from user buffer to kernel buffer
1012        _physical_memcpy( kernel_buffer_paddr, 
1013                          user_buffer_paddr, 
1014                          NIC_CONTAINER_SIZE );
1015
1016        // sync kernel buffer in L2 after write in L2
1017        _mmc_sync( kernel_buffer_paddr, NIC_CONTAINER_SIZE );
1018
1019#if GIET_DEBUG_NIC
1020_printf("\n[GIET DEBUG NIC] Task %d in _sys_nic_move() transfer "
1021        "user buffer %l to kernel buffer %l at cycle %d\n",
1022        thread , user_buffer_paddr , kernel_buffer_paddr , _get_proctime() );
1023#endif
1024
1025    }
1026
1027    // update kernel chbuf status
1028    if ( is_rx ) chbuf->buffer[index].desc = kernel_buffer_paddr & 0x0000FFFFFFFFFFFFULL;
1029    else         chbuf->buffer[index].desc = kernel_buffer_paddr | 0x8000000000000000ULL;
1030
1031    // sync kernel chbuf in L2 after write in L2
1032    _mmc_sync( kernel_chbuf_paddr + (index<<6) , 8 );
1033
1034#if GIET_DEBUG_NIC
1035_printf("\n[GIET DEBUG NIC] Task %d get buffer %d  and exit _sys_nic_move() at cycle %d\n",
1036        thread , index , _get_proctime() );
1037#endif
1038
1039    return 0;
1040} // end _sys_nic_move()
1041
1042
1043////////////////////////////////////////
1044int _sys_nic_stop( unsigned int is_rx,
1045                   unsigned int channel )
1046{
1047    unsigned int nic_channel;
1048    unsigned int cma_channel;
1049
1050    // get NIC channel index and CMA channel index
1051    if ( is_rx )
1052    {
1053        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1054        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
1055    }
1056    else
1057    {
1058        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1059        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
1060    }
1061
1062    // check NIC and CMA channels index
1063    if ( nic_channel != channel )
1064    {
1065        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal NIC channel\n");
1066        return -1;
1067    }
1068    if ( cma_channel >= NB_CMA_CHANNELS )
1069    {
1070        _printf("\n[GIET_ERROR] in _sys_nic_stop(): illegal CMA channel\n");
1071        return -1;
1072    }
1073
1074    // desactivates the NIC channel
1075    _nic_channel_stop( nic_channel, is_rx );
1076
1077    // desactivates the CMA channel
1078    _cma_set_register( cma_channel, CHBUF_RUN , 0 );
1079
1080    return 0;
1081}  // end _sys_nic_stop()
1082
1083////////////////////////////////////////
1084int _sys_nic_clear( unsigned int is_rx,
1085                    unsigned int channel )
1086{
1087    unsigned int nic_channel;
1088
1089    // get NIC channel
1090    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1091    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1092
1093    if ( nic_channel != channel )
1094    {
1095        _printf("\n[GIET_ERROR] in _sys_nic_clear(): illegal NIC channel\n");
1096        return -1;
1097    }
1098
1099    if ( is_rx )
1100    {
1101        _nic_set_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       , 0 );
1102        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      , 0 );
1103        _nic_set_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        , 0 );
1104        _nic_set_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     , 0 );
1105        _nic_set_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       , 0 );
1106        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_RECEIVED  , 0 );
1107        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST , 0 );
1108        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  , 0 );
1109        _nic_set_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   , 0 );
1110    } 
1111    else
1112    {
1113        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  , 0 );
1114        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TRANSMIT  , 0 );
1115        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   , 0 );
1116        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL , 0 );
1117        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  , 0 );
1118        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    , 0 );
1119        _nic_set_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST , 0 );
1120    }
1121    return 0;
1122}  // en _sys_nic_clear()
1123
1124////////////////////////////////////////
1125int _sys_nic_stats( unsigned int is_rx,
1126                    unsigned int channel )
1127{
1128    unsigned int nic_channel;
1129
1130    // get NIC channel
1131    if ( is_rx )  nic_channel = _get_context_slot( CTX_NIC_RX_ID );
1132    else          nic_channel = _get_context_slot( CTX_NIC_TX_ID );
1133
1134    if ( nic_channel != channel )
1135    {
1136        _printf("\n[GIET_ERROR] in _sys_nic_stats(): illegal NIC channel\n");
1137        return -1;
1138    }
1139
1140    if ( is_rx )
1141    {
1142        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_RX_G2S_RECEIVED       );
1143        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_SMALL      );
1144        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_RX_DES_TOO_BIG        );
1145        unsigned int fifo_full  = _nic_get_global_register( NIC_G_NPKT_RX_DES_MFIFO_FULL     );
1146        unsigned int crc_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DES_CRC_FAIL       );
1147        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_BROADCAST );
1148        unsigned int dst_fail   = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_DST_FAIL  );
1149        unsigned int ch_full    = _nic_get_global_register( NIC_G_NPKT_RX_DISPATCH_CH_FULL   );
1150
1151        _printf("\n### Network Controller RX Statistics ###\n"
1152                "- packets received : %d\n"
1153                "- too small        : %d\n"
1154                "- too big          : %d\n"
1155                "- fifo full        : %d\n" 
1156                "- crc fail         : %d\n" 
1157                "- dst mac fail     : %d\n" 
1158                "- channel full     : %d\n" 
1159                "- broadcast        : %d\n",
1160                received,
1161                too_small,
1162                too_big,
1163                fifo_full,
1164                crc_fail,
1165                dst_fail,
1166                ch_full,
1167                broadcast );
1168    } 
1169    else
1170    {
1171        unsigned int received   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_RECEIVED  );
1172        unsigned int too_big    = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_BIG   );
1173        unsigned int too_small  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_TOO_SMALL );
1174        unsigned int src_fail   = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_SRC_FAIL  );
1175        unsigned int bypass     = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BYPASS    );
1176        unsigned int broadcast  = _nic_get_global_register( NIC_G_NPKT_TX_DISPATCH_BROADCAST );
1177
1178        _printf("\n### Network Controller TX Statistics ###\n"
1179                "- packets received : %d\n"
1180                "- too small        : %d\n"
1181                "- too big          : %d\n"
1182                "- src mac fail     : %d\n" 
1183                "- bypass           : %d\n" 
1184                "- broadcast        : %d\n",
1185                received,
1186                too_big,
1187                too_small,
1188                src_fail,
1189                bypass,
1190                broadcast );
1191    }
1192    return 0;
1193}  // end _sys_nic_stats()
1194
1195/////////////////////////////////////////////////////////////////////////////////////////
1196//    FBF related syscall handlers
1197/////////////////////////////////////////////////////////////////////////////////////////
1198
1199/////////////////////////////////////////////
1200int _sys_fbf_sync_write( unsigned int offset,
1201                         void*        buffer,
1202                         unsigned int length )
1203{
1204    char* fbf_address = (char *)SEG_FBF_BASE + offset;
1205    memcpy( fbf_address, buffer, length);
1206
1207    return 0;
1208}
1209
1210/////////////////////////////////////////////
1211int _sys_fbf_sync_read(  unsigned int offset,
1212                         void*        buffer,
1213                         unsigned int length )
1214{
1215    char* fbf_address = (char *)SEG_FBF_BASE + offset;
1216    memcpy( buffer, fbf_address, length);
1217
1218    return 0;
1219}
1220
1221////////////////////////
1222int _sys_fbf_cma_alloc()
1223{
1224   // get a new CMA channel index
1225    unsigned int channel = _atomic_increment( &_cma_channel_allocator, 1 );
1226
1227    if ( channel >= NB_CMA_CHANNELS )
1228    {
1229        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : not enough CMA channels\n");
1230        return -1;
1231    }
1232    else
1233    {
1234        _set_context_slot( CTX_CMA_FB_ID, channel );
1235        return 0;
1236    }
1237} // end sys_fbf_cma_alloc()
1238
1239////////////////////////////////////////////
1240int _sys_fbf_cma_start( void*        vbase0, 
1241                        void*        vbase1, 
1242                        unsigned int length ) 
1243{
1244#if NB_CMA_CHANNELS > 0
1245
1246    unsigned int       vaddr;           // virtual address
1247    unsigned int       flags;           // for _v2p_translate()
1248
1249    // get channel index
1250    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1251
1252    if ( channel >= NB_CMA_CHANNELS )
1253    {
1254        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
1255        return -1;
1256    }
1257
1258#if GIET_DEBUG_FBF_CMA
1259_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_start()\n"
1260        " - channel      = %d\n"
1261        " - buf0   vbase = %x\n"
1262        " - buf1   vbase = %x\n"
1263        " - buffer size  = %x\n",
1264        channel,
1265        (unsigned int)vbase0,
1266        (unsigned int)vbase1,
1267        length );
1268#endif
1269
1270    // checking user buffers virtual addresses and length alignment
1271    if ( ((unsigned int)vbase0 & 0x3) || 
1272         ((unsigned int)vbase1 & 0x3) || 
1273         (length & 0x3) ) 
1274    {
1275        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer not aligned\n");
1276        return -1;
1277    }
1278
1279    // compute frame buffer physical address and initialize _fbf_chbuf[channel]
1280    vaddr = (unsigned int)SEG_FBF_BASE;
1281    _fbf_chbuf[channel].fbf.desc = _v2p_translate( vaddr , &flags );
1282
1283    // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
1284    vaddr = (unsigned int)vbase0;
1285    _fbf_chbuf[channel].buf0.desc = _v2p_translate( vaddr , &flags );
1286
1287    if ((flags & PTE_U) == 0) 
1288    {
1289        _printf("\n[GIET ERROR] in _fbf_cma_start() : buf0 not in user space\n");
1290        return -1;
1291    }
1292
1293    // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
1294    vaddr = (unsigned int)vbase1;
1295    _fbf_chbuf[channel].buf1.desc = _v2p_translate( vaddr , &flags );
1296
1297    if ((flags & PTE_U) == 0) 
1298    {
1299        _printf("\n[GIET ERROR] in _fbf_cma_start() : buf1 not in user space\n");
1300        return -1;
1301    }
1302
1303    // initializes buffer length
1304    _fbf_chbuf[channel].length = length;
1305
1306    // Compute and register physical adress of the fbf_chbuf descriptor
1307    vaddr = (unsigned int)&_fbf_chbuf[channel];
1308    _fbf_chbuf_paddr[channel] = _v2p_translate( vaddr , &flags );
1309 
1310    if ( USE_IOB )
1311    {
1312        // SYNC request for fbf_chbuf descriptor
1313        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof( fbf_chbuf_t ) );
1314    }
1315
1316#if GIET_DEBUG_FBF_CMA
1317_printf(" - fbf    pbase = %l\n"
1318        " - buf0   pbase = %l\n"
1319        " - buf1   pbase = %l\n"
1320        " - chbuf  pbase = %l\n",
1321        _fbf_chbuf[channel].fbf.desc,
1322        _fbf_chbuf[channel].buf0.desc,
1323        _fbf_chbuf[channel].buf1.desc,
1324        _fbf_chbuf_paddr[channel] );
1325#endif
1326
1327    // start CMA transfer
1328    unsigned long long paddr = _fbf_chbuf_paddr[channel];
1329    unsigned int src_chbuf_paddr_lsb = (unsigned int)(paddr & 0xFFFFFFFF);
1330    unsigned int src_chbuf_paddr_ext = (unsigned int)(paddr >> 32);
1331    unsigned int dst_chbuf_paddr_lsb = src_chbuf_paddr_lsb + 128;
1332    unsigned int dst_chbuf_paddr_ext = src_chbuf_paddr_ext;
1333
1334    _cma_set_register( channel, CHBUF_SRC_DESC , src_chbuf_paddr_lsb );
1335    _cma_set_register( channel, CHBUF_SRC_EXT  , src_chbuf_paddr_ext );
1336    _cma_set_register( channel, CHBUF_SRC_NBUFS, 2 );
1337    _cma_set_register( channel, CHBUF_DST_DESC , dst_chbuf_paddr_lsb );
1338    _cma_set_register( channel, CHBUF_DST_EXT  , dst_chbuf_paddr_ext );
1339    _cma_set_register( channel, CHBUF_DST_NBUFS, 1 );
1340    _cma_set_register( channel, CHBUF_BUF_SIZE , length );
1341    _cma_set_register( channel, CHBUF_PERIOD   , 300 );
1342    _cma_set_register( channel, CHBUF_RUN      , 1 );
1343
1344    return 0;
1345
1346#else
1347
1348    _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
1349    return -1;
1350
1351#endif
1352} // end _sys_fbf_cma_start()
1353
1354/////////////////////////////////////////////////////
1355int _sys_fbf_cma_display( unsigned int buffer_index )
1356{
1357#if NB_CMA_CHANNELS > 0
1358
1359    volatile unsigned int full = 1;
1360
1361    // get channel index
1362    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1363
1364    if ( channel >= NB_CMA_CHANNELS )
1365    {
1366        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : "
1367                "CMA channel index too large\n");
1368        return -1;
1369    }
1370
1371    // get fbf_chbuf descriptor pointer
1372    fbf_chbuf_t* pdesc = &_fbf_chbuf[channel];     
1373
1374#if GIET_DEBUG_FBF_CMA
1375_printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
1376        " - cma channel     = %d\n"
1377        " - buffer index    = %d\n"
1378        " - buf0_desc value = %l\n"
1379        " - buf1_desc value = %l\n"
1380        " - fbf_desc  value = %l\n",
1381        channel , buffer_index,
1382        _fbf_chbuf[channel].buf0.desc,
1383        _fbf_chbuf[channel].buf1.desc,
1384        _fbf_chbuf[channel].fbf.desc );
1385#endif
1386
1387    if ( buffer_index == 0 )    // user buffer 0
1388    {
1389        // INVAL L1 and L2 cache copies of user buffer descriptor,
1390        // because it has been modified in RAM by the CMA component
1391        _dcache_buf_invalidate( (unsigned int)pdesc , sizeof(buffer_descriptor_t) );
1392        _mmc_inval( _fbf_chbuf_paddr[channel] , sizeof(buffer_descriptor_t) );
1393
1394        // waiting user buffer released by the CMA component)
1395        while ( full )
1396        { 
1397            full = (unsigned int)(pdesc->buf0.desc >> 63);
1398        }
1399
1400        // SYNC request for the user buffer, because
1401        // it will be read from XRAM by the CMA component
1402        _mmc_sync( pdesc->buf0.desc , pdesc->length );
1403
1404        // set user buffer status
1405        pdesc->buf0.desc = pdesc->buf0.desc | 0x8000000000000000ULL;
1406
1407        // reset fbf buffer status
1408        pdesc->fbf.desc  = pdesc->fbf.desc  & 0x7FFFFFFFFFFFFFFFULL;
1409
1410        // SYNC request, because these buffer descriptors
1411        // will be read from XRAM by the CMA component
1412        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof(fbf_chbuf_t) );
1413    }
1414    else                        // user buffer 1
1415    {
1416        // INVAL L1 and L2 cache copies of user buffer descriptor,
1417        // because it has been modified in RAM by the CMA component
1418        _dcache_buf_invalidate( (unsigned int)pdesc + 64, sizeof(buffer_descriptor_t) );
1419        _mmc_inval( _fbf_chbuf_paddr[channel] + 64, sizeof(buffer_descriptor_t) );
1420
1421        // waiting user buffer released by the CMA component)
1422        while ( full )
1423        { 
1424            full = (unsigned int)(pdesc->buf1.desc >> 63);
1425        }
1426
1427        // SYNC request for the user buffer, because
1428        // it will be read from XRAM by the CMA component
1429        _mmc_sync( pdesc->buf1.desc , pdesc->length );
1430
1431        // set user buffer status
1432        pdesc->buf1.desc = pdesc->buf1.desc | 0x8000000000000000ULL;
1433
1434        // reset fbf buffer status
1435        pdesc->fbf.desc  = pdesc->fbf.desc  & 0x7FFFFFFFFFFFFFFFULL;
1436
1437        // SYNC request, because these buffer descriptors
1438        // will be read from XRAM by the CMA component
1439        _mmc_sync( _fbf_chbuf_paddr[channel] , sizeof(fbf_chbuf_t) );
1440    }
1441
1442#if GIET_DEBUG_FBF_CMA
1443_printf("\n[FBF_CMA DEBUG] exit _sys_fb_cma_display()\n"
1444        " - buf0_desc value = %l\n"
1445        " - buf1_desc value = %l\n"
1446        " - fbf_desc  value = %l\n",
1447        _fbf_chbuf[channel].buf0.desc,
1448        _fbf_chbuf[channel].buf1.desc,
1449        _fbf_chbuf[channel].fbf.desc );
1450#endif
1451
1452    return 0;
1453
1454#else
1455
1456    _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
1457    return -1;
1458
1459#endif
1460} // end _sys_fbf_cma_display()
1461
1462
1463///////////////////////
1464int _sys_fbf_cma_stop()
1465{
1466#if NB_CMA_CHANNELS > 0
1467
1468    // get channel index
1469    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
1470
1471    if ( channel >= NB_CMA_CHANNELS )
1472    {
1473        _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
1474        return -1;
1475    }
1476
1477    // Desactivate CMA channel
1478    _cma_set_register( channel, CHBUF_RUN, 0 );
1479
1480    return 0;
1481
1482#else
1483
1484    _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
1485    return -1;
1486
1487#endif
1488} // end _sys_fbf_cma_stop()
1489
1490
1491//////////////////////////////////////////////////////////////////////////////
1492//           Miscelaneous syscall handlers
1493//////////////////////////////////////////////////////////////////////////////
1494
1495///////////////
1496int _sys_ukn() 
1497{
1498    _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
1499    return -1;
1500}
1501
1502////////////////////////////////////
1503int _sys_proc_xyp( unsigned int* x,
1504                   unsigned int* y,
1505                   unsigned int* p )
1506{
1507    unsigned int gpid = _get_procid();  // global processor index from CPO register
1508
1509    *x = (gpid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
1510    *y = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
1511    *p = gpid & ((1<<P_WIDTH)-1);
1512
1513    return 0;
1514}
1515
1516//////////////////////////////////
1517int _sys_task_exit( char* string ) 
1518{
1519    unsigned int date       = _get_proctime();
1520
1521    unsigned int gpid       = _get_procid();
1522    unsigned int cluster_xy = gpid >> P_WIDTH;
1523    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
1524    unsigned int x          = cluster_xy >> Y_WIDTH;
1525    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
1526
1527    unsigned int task_id    = _get_context_slot(CTX_LTID_ID);
1528
1529    // print exit message
1530    _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
1531            "\n       Cause : %s\n\n",
1532            task_id, x, y, lpid, date, string );
1533
1534    // goes to sleeping state
1535    _set_context_slot(CTX_RUN_ID, 0);
1536
1537    // deschedule
1538    _sys_context_switch();
1539
1540    return 0;
1541} 
1542
1543/////////////////////////
1544int _sys_context_switch() 
1545{
1546    unsigned int save_sr;
1547
1548    _it_disable( &save_sr );
1549    _ctx_switch();
1550    _it_restore( &save_sr );
1551
1552    return 0;
1553}
1554
1555////////////////////////
1556int _sys_local_task_id()
1557{
1558    return _get_context_slot(CTX_LTID_ID);
1559}
1560
1561/////////////////////////
1562int _sys_global_task_id()
1563{
1564    return _get_context_slot(CTX_GTID_ID);
1565}
1566
1567////////////////////
1568int _sys_thread_id()
1569{
1570    return _get_context_slot(CTX_TRDID_ID);
1571}
1572
1573////////////////////////////////////////////
1574int _sys_procs_number( unsigned int* x_size,
1575                       unsigned int* y_size,
1576                       unsigned int* nprocs )
1577{
1578    mapping_header_t * header   = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1579    mapping_cluster_t * cluster = _get_cluster_base(header);
1580
1581    unsigned int x;
1582    unsigned int y;
1583    unsigned int okmin = 1;
1584    unsigned int okmax = 1;
1585
1586    // compute max values
1587    unsigned int xmax  = header->x_size;
1588    unsigned int ymax  = header->y_size;
1589    unsigned int procs = cluster[0].procs;
1590
1591    // check the (ymax-1) lower rows
1592    for ( y = 0 ; y < ymax-1 ; y++ )
1593    {
1594        for ( x = 0 ; x < xmax ; x++ )
1595        {
1596            if (cluster[x*ymax+y].procs != procs ) okmin = 0;
1597        }
1598    }
1599
1600    // check the upper row
1601    for ( x = 0 ; x < xmax ; x++ )
1602    {
1603        if (cluster[x*ymax+ymax-1].procs != procs ) okmax = 0;
1604    }
1605
1606    // return values
1607    if ( okmin && okmax )
1608    {
1609        *x_size = xmax;
1610        *y_size = ymax;
1611        *nprocs = procs;
1612    }
1613    else if ( okmin )
1614    {
1615        *x_size = xmax;
1616        *y_size = ymax-1;
1617        *nprocs = procs;
1618    }
1619    else
1620    {
1621        *x_size = 0;
1622        *y_size = 0;
1623        *nprocs = 0;
1624    }
1625    return 0;
1626}
1627
1628///////////////////////////////////////////////////////
1629int _sys_vseg_get_vbase( char*             vspace_name, 
1630                         char*             vseg_name, 
1631                         unsigned int*     vbase ) 
1632{
1633    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1634    mapping_vspace_t * vspace = _get_vspace_base(header);
1635    mapping_vseg_t * vseg     = _get_vseg_base(header);
1636
1637    unsigned int vspace_id;
1638    unsigned int vseg_id;
1639
1640    // scan vspaces
1641    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1642    {
1643        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
1644        {
1645            // scan vsegs
1646            for (vseg_id = vspace[vspace_id].vseg_offset; 
1647                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
1648                 vseg_id++) 
1649            {
1650                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
1651                {
1652                    *vbase = vseg[vseg_id].vbase;
1653                    return 0;
1654                }
1655            } 
1656        }
1657    } 
1658    return -1;    // not found
1659}
1660
1661/////////////////////////////////////////////////////////
1662int _sys_vseg_get_length( char*         vspace_name, 
1663                          char*         vseg_name,
1664                          unsigned int* length ) 
1665{
1666    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1667    mapping_vspace_t * vspace = _get_vspace_base(header);
1668    mapping_vseg_t * vseg     = _get_vseg_base(header);
1669
1670    unsigned int vspace_id;
1671    unsigned int vseg_id;
1672
1673    // scan vspaces
1674    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1675    {
1676        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
1677        {
1678            // scan vsegs
1679            for (vseg_id = vspace[vspace_id].vseg_offset; 
1680                 vseg_id < (vspace[vspace_id].vseg_offset + vspace[vspace_id].vsegs); 
1681                 vseg_id++) 
1682            {
1683                if (_strncmp(vseg[vseg_id].name, vseg_name, 31) == 0) 
1684                {
1685                    *length = vseg[vseg_id].length;
1686                    return 0;
1687                }
1688            } 
1689        }
1690    } 
1691    return -1;    // not found
1692}
1693
1694////////////////////////////////////////
1695int _sys_xy_from_ptr( void*         ptr,
1696                      unsigned int* x,
1697                      unsigned int* y )
1698{
1699    unsigned int flags;
1700    unsigned long long paddr = _v2p_translate( (unsigned int)ptr , &flags );
1701   
1702    *x = (paddr>>36) & 0xF;
1703    *y = (paddr>>32) & 0xF;
1704
1705    return 0;
1706}
1707
1708/////////////////////////////////////////
1709int _sys_heap_info( unsigned int* vaddr, 
1710                    unsigned int* length,
1711                    unsigned int  x,
1712                    unsigned int  y ) 
1713{
1714    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1715    mapping_task_t *   task    = _get_task_base(header);
1716    mapping_vseg_t *   vseg    = _get_vseg_base(header);
1717    mapping_vspace_t * vspace  = _get_vspace_base(header);
1718
1719    unsigned int task_id;
1720    unsigned int vspace_id;
1721    unsigned int vseg_id = 0xFFFFFFFF;
1722
1723    // searching the heap vseg
1724    if ( (x < X_SIZE) && (y < Y_SIZE) )  // searching a task in cluster(x,y)
1725    {
1726        // get vspace global index
1727        vspace_id = _get_context_slot(CTX_VSID_ID);
1728
1729        // scan all tasks in vspace
1730        unsigned int min = vspace[vspace_id].task_offset ;
1731        unsigned int max = min + vspace[vspace_id].tasks ;
1732        for ( task_id = min ; task_id < max ; task_id++ )
1733        {
1734            if ( task[task_id].clusterid == (x * Y_SIZE + y) )
1735            {
1736                vseg_id = task[task_id].heap_vseg_id;
1737                if ( vseg_id != 0xFFFFFFFF ) break;
1738            }
1739        }
1740    }
1741    else                                // searching in the calling task
1742    {
1743        task_id = _get_context_slot(CTX_GTID_ID);
1744        vseg_id = task[task_id].heap_vseg_id;
1745    }
1746
1747    // analysing the vseg_id
1748    if ( vseg_id != 0xFFFFFFFF ) 
1749    {
1750        *vaddr  = vseg[vseg_id].vbase;
1751        *length = vseg[vseg_id].length;
1752        return 0;
1753    }
1754    else 
1755    {
1756        *vaddr  = 0;
1757        *length = 0;
1758        return -1;
1759    }
1760}  // end _sys_heap_info()
1761
1762
1763// Local Variables:
1764// tab-width: 4
1765// c-basic-offset: 4
1766// c-file-offsets:((innamespace . 0)(inline-open . 0))
1767// indent-tabs-mode: nil
1768// End:
1769// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1770
Note: See TracBrowser for help on using the repository browser.