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

Last change on this file since 454 was 449, checked in by alain, 10 years ago

Introducing the CMA_RX, CMA_TX, NIC_RX, NIC_TX slots in the task context.
This allows an user task to have a private NIC channel and a private CMA channel.

  • Property svn:executable set to *
File size: 34.5 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 <ioc_driver.h>
12#include <nic_driver.h>
13#include <mmc_driver.h>
14#include <cma_driver.h>
15#include <ctx_handler.h>
16#include <fat32.h>
17#include <utils.h>
18#include <kernel_utils.h>
19#include <vmem.h>
20#include <hard_config.h>
21#include <giet_config.h>
22#include <mapping_info.h>
23
24#if !defined(SEG_BOOT_MAPPING_BASE)
25# error: You must define SEG_BOOT_MAPPING_BASE in the hard_config.h file
26#endif
27
28#if !defined(NB_TTY_CHANNELS)
29# error: You must define NB_TTY_CHANNELS in the hard_config.h file
30#endif
31
32#if !defined(NB_TIM_CHANNELS)
33# error: You must define NB_TIM_CHANNELS in the hard_config.h file
34#endif
35
36#if !defined(NB_NIC_CHANNELS)
37# error: You must define NB_NIC_CHANNELS in the hard_config.h file
38#endif
39
40#if !defined(NB_CMA_CHANNELS)
41# error: You must define NB_CMA_CHANNELS in the hard_config.h file
42#endif
43
44#if !defined(GIET_NIC_CHBUF_NBUFS)
45# error: You must define GIET_NIC_CHBUF_NBUFS in the giet_config.h file
46#endif
47
48#if !defined(GIET_NIC_CHBUF_SIZE)
49# error: You must define GIET_NIC_CHBUF_SIZE in the giet_config.h file
50#endif
51
52#if !defined(GIET_NIC_CHBUF_TIMEOUT)
53# error: You must define GIET_NIC_CHBUF_TIMEOUT in the giet_config.h file
54#endif
55
56
57////////////////////////////////////////////////////////////////////////////
58//     Channel allocators for peripherals
59//     (TTY[0] is reserved for kernel)
60////////////////////////////////////////////////////////////////////////////
61
62unsigned int _tty_channel_allocator = 1;
63unsigned int _tim_channel_allocator = 0;
64unsigned int _cma_channel_allocator = 0;
65unsigned int _nic_rx_channel_allocator = 0;
66unsigned int _nic_tx_channel_allocator = 0;
67
68
69////////////////////////////////////////////////////////////////////////////
70//     NIC_RX and NIC_TX chbuf arrays
71////////////////////////////////////////////////////////////////////////////
72
73nic_chbuf_t  _nic_rx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(8)));
74nic_chbuf_t  _nic_tx_chbuf[NB_NIC_CHANNELS] __attribute__((aligned(8)));
75
76
77////////////////////////////////////////////////////////////////////////////
78//    Initialize the syscall vector with syscall handlers
79// Note: This array must be synchronised with the define in file stdio.h
80////////////////////////////////////////////////////////////////////////////
81const void * _syscall_vector[64] = 
82{
83    &_sys_proc_xyp,         /* 0x00 */
84    &_get_proctime,         /* 0x01 */
85    &_sys_tty_write,        /* 0x02 */
86    &_sys_tty_read,         /* 0x03 */
87    &_sys_tty_alloc,        /* 0x04 */
88    &_sys_tty_get_lock,     /* 0x05 */
89    &_sys_tty_release_lock, /* 0x06 */
90    &_sys_heap_info,        /* 0x07 */
91    &_sys_local_task_id,    /* 0x08 */
92    &_sys_global_task_id,   /* 0x09 */ 
93    &_sys_fbf_cma_alloc,    /* 0x0A */
94    &_sys_fbf_cma_start,    /* 0x0B */
95    &_sys_fbf_cma_display,  /* 0x0C */
96    &_sys_fbf_cma_stop,     /* 0x0D */
97    &_sys_task_exit,        /* 0x0E */
98    &_sys_procs_number,     /* 0x0F */
99
100    &_sys_fbf_sync_write,   /* 0x10 */
101    &_sys_fbf_sync_read,    /* 0x11 */
102    &_sys_thread_id,        /* 0x12 */
103    &_sys_ukn,              /* 0x13 */
104    &_sys_tim_alloc,        /* 0x14 */
105    &_sys_tim_start,        /* 0x15 */ 
106    &_sys_tim_stop,         /* 0x16 */
107    &_sys_ukn,              /* 0x17 */
108    &_sys_ukn,              /* 0x18 */   
109    &_context_switch,       /* 0x19 */
110    &_sys_vobj_get_vbase,   /* 0x1A */
111    &_sys_vobj_get_length,  /* 0x1B */
112    &_sys_xy_from_ptr,      /* 0x1C */
113    &_sys_ukn,              /* 0x1D */
114    &_sys_ukn,              /* 0x1E */
115    &_sys_ukn,              /* 0x1F */
116
117    &_fat_user_open,        /* 0x20 */
118    &_fat_user_read,        /* 0x21 */
119    &_fat_user_write,       /* 0x22 */
120    &_fat_user_lseek,       /* 0x23 */
121    &_fat_fstat,            /* 0x24 */
122    &_fat_close,            /* 0x25 */
123    &_sys_ukn,              /* 0x26 */
124    &_sys_ukn,              /* 0x27 */
125    &_sys_ukn,              /* 0x28 */
126    &_sys_ukn,              /* 0x29 */
127    &_sys_ukn,              /* 0x2A */
128    &_sys_ukn,              /* 0x2B */
129    &_sys_ukn,              /* 0x2C */
130    &_sys_ukn,              /* 0x2D */
131    &_sys_ukn,              /* 0x2E */
132    &_sys_ukn,              /* 0x2F */
133
134    &_sys_nic_alloc,        /* 0x30 */
135    &_sys_nic_alloc,        /* 0x31 */
136    &_sys_nic_start,        /* 0x32 */
137    &_sys_nic_start,        /* 0x33 */
138    &_sys_nic_move,         /* 0x34 */
139    &_sys_nic_move,         /* 0x35 */ 
140    &_sys_nic_stop,         /* 0x36 */
141    &_sys_nic_stop,         /* 0x37 */
142    &_sys_ukn,              /* 0x38 */   
143    &_sys_ukn,              /* 0x39 */
144    &_sys_ukn,              /* 0x3A */
145    &_sys_ukn,              /* 0x3B */
146    &_sys_ukn,              /* 0x3C */
147    &_sys_ukn,              /* 0x3D */
148    &_sys_ukn,              /* 0x3E */
149    &_sys_ukn,              /* 0x3F */
150};
151
152//////////////////////////////////////////////////////////////////////////////
153//             TTY related syscall handlers
154//////////////////////////////////////////////////////////////////////////////
155
156////////////////////
157int _sys_tty_alloc()
158{
159    // get a new TTY terminal index
160    unsigned int channel = _atomic_increment( &_tty_channel_allocator );
161    unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
162    unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
163
164    if ( channel >= NB_TTY_CHANNELS )
165    {
166        _printf("\n[GIET_ERROR] in _sys_tty_alloc() : not enough TTY channels\n");
167        return -1;
168    }
169    else
170    {
171        _printf("\n[GIET WARNING] TTY channel %d allocated "
172                " to thread %d in vspace %d\n", channel, thread, vspace );
173        _set_context_slot( CTX_TTY_ID, channel );
174        return 0;
175    }
176}
177
178/////////////////////////////////////////////////
179int _sys_tty_write( const char*  buffer,   
180                    unsigned int length,    // number of characters
181                    unsigned int channel)   // channel index
182{
183    unsigned int  nwritten;
184
185    // compute and check tty channel
186    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
187    if( channel >= NB_TTY_CHANNELS ) return -1;
188
189    // write string to TTY channel
190    for (nwritten = 0; nwritten < length; nwritten++) 
191    {
192        // check tty's status
193        if ( _tty_get_register( channel, TTY_STATUS ) & 0x2 )  break;
194
195        // write one byte
196        if (buffer[nwritten] == '\n') 
197        {
198            _tty_set_register( channel, TTY_WRITE, (unsigned int)'\r' );
199        }
200        _tty_set_register( channel, TTY_WRITE, (unsigned int)buffer[nwritten] );
201    }
202   
203    return nwritten;
204}
205
206////////////////////////////////////////////////
207int _sys_tty_read( char*        buffer, 
208                   unsigned int length,    // unused
209                   unsigned int channel)   // channel index
210{
211    // compute and check tty channel
212    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
213    if( channel >= NB_TTY_CHANNELS ) return -1;
214
215    // read one character from TTY channel
216    if (_tty_rx_full[channel] == 0) 
217    {
218        return 0;
219    }
220    else 
221    {
222        *buffer = _tty_rx_buf[channel];
223        _tty_rx_full[channel] = 0;
224        return 1;
225    }
226}
227
228///////////////////////////////////////////
229int _sys_tty_get_lock( unsigned int   channel,
230                       unsigned int * save_sr_ptr )
231{
232    // compute and check tty channel
233    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
234    if( channel >= NB_TTY_CHANNELS ) return -1;
235
236    _it_disable( save_sr_ptr );
237    _get_lock( &_tty_lock[channel] );
238    return 0;
239}
240
241///////////////////////////////////////////////
242int _sys_tty_release_lock( unsigned int   channel,
243                           unsigned int * save_sr_ptr )
244{
245    // compute and check tty channel
246    if( channel == 0xFFFFFFFF )  channel = _get_context_slot(CTX_TTY_ID);
247    if( channel >= NB_TTY_CHANNELS ) return -1;
248
249    _release_lock( &_tty_lock[channel] );
250    _it_restore( save_sr_ptr );
251    return 0;
252}
253
254//////////////////////////////////////////////////////////////////////////////
255//             TIM related syscall handlers
256//////////////////////////////////////////////////////////////////////////////
257
258////////////////////
259int _sys_tim_alloc()
260{
261    // get a new timer index
262    unsigned int channel = _atomic_increment(&_tim_channel_allocator);
263    unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
264    unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
265
266    if ( channel >= NB_TIM_CHANNELS )
267    {
268        _printf("\n[GIET_ERROR] in _sys_tim_alloc() : not enough TIM channels\n");
269        return -1;
270    }
271    else
272    {
273        _printf("\n[GIET WARNING] TIM channel %d allocated "
274                " to thread %d in vspace %d\n", channel, thread, vspace );
275        _set_context_slot( CTX_TIM_ID, channel );
276        return 0;
277    }
278}
279
280/////////////////////////////////////////
281int _sys_tim_start( unsigned int period )
282{
283    // get timer index
284    unsigned int channel = _get_context_slot( CTX_TIM_ID );
285    if ( channel >= NB_TIM_CHANNELS )
286    {
287        _printf("\n[GIET_ERROR] in _sys_tim_start() : not enough TIM channels\n");
288        return -1;
289    }
290
291    // start timer
292    _timer_start( channel, period );
293
294    return 0;
295}
296
297///////////////////
298int _sys_tim_stop()
299{
300    // get timer index
301    unsigned int channel = _get_context_slot( CTX_TIM_ID );
302    if ( channel >= NB_TIM_CHANNELS )
303    {
304        _printf("\n[GIET_ERROR] in _sys_tim_stop() : illegal timer index\n");
305        return -1;
306    }
307
308    // stop timer
309    _timer_stop( channel );
310
311    return 0;
312}
313
314//////////////////////////////////////////////////////////////////////////////
315//             NIC related syscall handlers
316//////////////////////////////////////////////////////////////////////////////
317
318///////////////////////////////////////////
319int _sys_nic_alloc( unsigned int is_rx )
320{
321    unsigned int nic_channel;
322    unsigned int cma_channel;
323
324    // get a NIC_RX or NIC_TX channel index
325    if ( is_rx ) nic_channel = _atomic_increment(&_nic_rx_channel_allocator);
326    else         nic_channel = _atomic_increment(&_nic_tx_channel_allocator);
327
328    if ( (nic_channel >= NB_NIC_CHANNELS) )
329    {
330        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough NIC channels\n");
331        return -1;
332    }
333
334    // get a CMA channel index
335    cma_channel = _atomic_increment(&_cma_channel_allocator);
336
337    if ( cma_channel >= NB_CMA_CHANNELS )
338    {
339        _printf("\n[GIET_ERROR] in _sys_nic_alloc() not enough CMA channels\n");
340        return -1;
341    }
342   
343    // register nic_index and cma_index in task context
344    if ( is_rx )
345    {
346        _set_context_slot( CTX_NIC_RX_ID, nic_channel );
347        _set_context_slot( CTX_CMA_RX_ID, cma_channel );
348    }
349    else
350    {
351        _set_context_slot( CTX_NIC_TX_ID, nic_channel );
352        _set_context_slot( CTX_CMA_TX_ID, cma_channel );
353    }
354
355#if GIET_DEBUG_NIC
356unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
357unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
358_printf("\n[GIET DEBUG_NIC] NIC channel %d and CMA channel %d"
359        " allocated to task %d in vspace %d\n", 
360        nic_channel, cma_channel, thread, vspace );
361#endif
362
363    return 0;
364}
365
366////////////////////////////////////////
367int _sys_nic_start( unsigned int is_rx,
368                    unsigned int mac4,
369                    unsigned int mac2 )
370{
371    unsigned int nic_channel;
372    unsigned int cma_channel;
373
374    // get NIC channel index and CMA channel index
375    if ( is_rx )
376    {
377        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
378        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
379    }
380    else
381    {
382        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
383        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
384    }
385
386    if ( nic_channel >= NB_NIC_CHANNELS )
387    {
388        _printf("\n[GIET_ERROR] in _sys_nic_start(): NIC channel not allocated\n");
389        return -1;
390    }
391    if ( cma_channel >= NB_CMA_CHANNELS )
392    {
393        _printf("\n[GIET_ERROR] in _sys_nic_start(): CMA channel not allocated\n");
394        return -1;
395    }
396
397    unsigned int nic_chbuf_lsb;     // 32 LSB bits of the NIC chbuf physical address
398    unsigned int nic_chbuf_msb;     // 16 MSB bits of the NIC chbuf physical address
399    unsigned int ker_chbuf_lsb;     // 32 LSB bits of the kernel chbuf physical address
400    unsigned int ker_chbuf_msb;     // 16 MSB bits of the kernel chbuf physical address
401
402    // get the NIC chbuf descriptor physical address
403    unsigned int offset;
404    if ( is_rx ) offset = 0x1000;
405    else         offset = 0x1010;
406    nic_chbuf_lsb = SEG_NIC_BASE + (nic_channel * NIC_CHANNEL_SPAN) + offset;
407    nic_chbuf_msb = (X_IO << Y_WIDTH) + Y_IO;
408
409    // get the kernel chbuf descriptor physical address
410    unsigned int ker_chbuf_vaddr;
411    if ( is_rx ) ker_chbuf_vaddr = (unsigned int)( &_nic_rx_chbuf[nic_channel] );
412    else         ker_chbuf_vaddr = (unsigned int)( &_nic_tx_chbuf[nic_channel] );
413
414    // compute the kernel chbuf descriptor physical address
415    unsigned int ppn;
416    unsigned int flags;
417    unsigned int ptab  = _get_context_slot(CTX_PTAB_ID);
418    unsigned int ko    = _v2p_translate( (page_table_t*)ptab,
419                                          ker_chbuf_vaddr,
420                                          &ppn,
421                                          &flags );
422    if ( ko )
423    {
424        _puts("\n[GIET ERROR] in _nic_cma_start_receive() : kernel buffer unmapped\n");
425        return -1;
426    }
427
428    ker_chbuf_lsb = (ppn << 12) | (ker_chbuf_vaddr & 0x00000FFF);
429    ker_chbuf_msb = ppn >> 20;
430
431    // initializes CMA registers defining the source chbuf (NIc)
432    _cma_set_register( cma_channel, CHBUF_SRC_DESC , nic_chbuf_lsb );
433    _cma_set_register( cma_channel, CHBUF_DST_EXT  , nic_chbuf_msb );
434    _cma_set_register( cma_channel, CHBUF_SRC_NBUFS, 2 );
435
436    // initializes CMA registers defining the destination chbuf (kernel)
437    _cma_set_register( cma_channel, CHBUF_DST_DESC , ker_chbuf_lsb );
438    _cma_set_register( cma_channel, CHBUF_DST_EXT  , ker_chbuf_msb );
439    _cma_set_register( cma_channel, CHBUF_DST_NBUFS, GIET_NIC_CHBUF_NBUFS );
440
441    // start CMA transfer
442    _cma_set_register( cma_channel, CHBUF_BUF_SIZE , 4096 );
443    _cma_set_register( cma_channel, CHBUF_PERIOD   , 300 );
444    _cma_set_register( cma_channel, CHBUF_RUN      , 1 );
445
446    // activates NIC channel
447    _nic_channel_start( nic_channel, is_rx, mac4, mac2 ); 
448    return 0;
449}
450
451//////////////////////////////////////
452int _sys_nic_move( unsigned int is_rx,
453                   void*        buffer )
454{
455    unsigned long long user_paddr;    // user buffer physical address
456    unsigned long long kernel_paddr;  // kernel buffer physical address
457
458    // Compute user buffer physical address and check access rights
459    unsigned int ppn;
460    unsigned int flags;
461    unsigned int vaddr = (unsigned int)buffer;
462    unsigned int user_ptab = _get_context_slot( CTX_PTAB_ID );
463    unsigned int ko = _v2p_translate( (page_table_t*)user_ptab,
464                                       vaddr,
465                                       &ppn,
466                                       &flags );
467    if ( ko )
468    {
469        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : user buffer unmapped\n");
470        return -1;
471    }
472    if ( (flags & PTE_U) == 0 )
473    {
474        _printf("\n[GIET ERROR] in _sys_nic_tx_move() : illegal buffer address\n");
475        return -1;
476    }
477    user_paddr = ((unsigned long long)ppn << 12) | (vaddr & 0x00000FFF);
478
479    // get NIC channel index, to get pointer on NIC_TX chbuf pointer
480    unsigned int channel;
481    if ( is_rx ) channel = _get_context_slot( CTX_NIC_RX_ID );
482    else         channel = _get_context_slot( CTX_NIC_TX_ID );
483
484    if ( channel >= NB_NIC_CHANNELS )
485    {
486        _printf("\n[GIET_ERROR] in _sys_nic_move() : illegal NIC channel index\n");
487        return -1;
488    }
489
490    nic_chbuf_t* chbuf;
491    if ( is_rx ) chbuf = &_nic_rx_chbuf[channel];
492    else         chbuf = &_nic_tx_chbuf[channel];
493
494    // polling on the chbuf status
495    volatile unsigned long long desc;
496    unsigned int full;
497    unsigned int ok      = 0;
498    unsigned int index   = chbuf->index;
499    unsigned int timeout = GIET_NIC_CHBUF_TIMEOUT;
500    while( ok == 0 )
501    {
502        desc  = chbuf->buffer[index];
503        full  =  desc >> 63;
504        if ( (is_rx && full) || ((is_rx == 0) && (full == 0)) )  // success
505        {
506            ok = 1;
507        }
508        else                                                   // retry
509        {
510            timeout--;
511        }
512        if ( timeout == 0 )
513        {
514            _printf("\n[GIET_ERROR] in _sys_ni_move() : timeout\n");
515            return -1;
516        }
517    }
518    kernel_paddr = desc & 0x0000FFFFFFFFFFFFULL;
519   
520    // move one container using, a physical_memcpy
521    if ( is_rx ) _physical_memcpy( user_paddr, 
522                                   kernel_paddr, 
523                                   GIET_NIC_CHBUF_SIZE );
524
525    else         _physical_memcpy( kernel_paddr, 
526                                   user_paddr, 
527                                   GIET_NIC_CHBUF_SIZE );
528
529    // update chbuf status and index
530    if ( is_rx ) chbuf->buffer[index] = desc & 0x0000FFFFFFFFFFFFULL;
531    else         chbuf->buffer[index] = desc | 0x8000000000000000ULL;
532    if ( index == (GIET_NIC_CHBUF_NBUFS - 1) ) chbuf->index = 0;
533    else                                       chbuf->index = index + 1;
534
535    return 0;
536} // end _sys_nic_move()
537
538////////////////////////////////////////
539int _sys_nic_stop( unsigned int is_rx )
540{
541    unsigned int nic_channel;
542    unsigned int cma_channel;
543
544    // get NIC channel index and CMA channel index
545    if ( is_rx )
546    {
547        nic_channel = _get_context_slot( CTX_NIC_RX_ID );
548        cma_channel = _get_context_slot( CTX_CMA_RX_ID );
549    }
550    else
551    {
552        nic_channel = _get_context_slot( CTX_NIC_TX_ID );
553        cma_channel = _get_context_slot( CTX_CMA_TX_ID );
554    }
555
556    if ( nic_channel >= NB_NIC_CHANNELS )
557    {
558        _printf("\n[GIET_ERROR] in _sys_nic_start(): NIC channel not allocated\n");
559        return -1;
560    }
561    if ( cma_channel >= NB_CMA_CHANNELS )
562    {
563        _printf("\n[GIET_ERROR] in _sys_nic_start(): CMA channel not allocated\n");
564        return -1;
565    }
566
567    // desactivates the NIC channel
568    _nic_channel_stop( nic_channel, is_rx );
569
570    // desactivates the CMA channel
571    _cma_channel_stop( cma_channel );
572
573    return 0;
574}
575
576/////////////////////////////////////////////////////////////////////////////////////////
577//    FBF related syscall handlers
578/////////////////////////////////////////////////////////////////////////////////////////
579
580// Array of fbf_chbuf descriptors, indexed by the CMA channel index.
581__attribute__((section (".unckdata")))
582volatile fbf_chbuf_t _fbf_chbuf[NB_CMA_CHANNELS] __attribute__((aligned(32)));
583
584// Physical addresses of these fbf_chbuf descriptors (required for L2 cache sync)
585__attribute__((section (".unckdata")))
586unsigned long long _fbf_chbuf_paddr[NB_CMA_CHANNELS];
587
588/////////////////////////////////////////////
589int _sys_fbf_sync_write( unsigned int offset,
590                         void*        buffer,
591                         unsigned int length )
592{
593    char* fbf_address = (char *)SEG_FBF_BASE + offset;
594    memcpy( fbf_address, buffer, length);
595
596    return 0;
597}
598
599/////////////////////////////////////////////
600int _sys_fbf_sync_read(  unsigned int offset,
601                         void*        buffer,
602                         unsigned int length )
603{
604    char* fbf_address = (char *)SEG_FBF_BASE + offset;
605    memcpy( buffer, fbf_address, length);
606
607    return 0;
608}
609
610////////////////////////
611int _sys_fbf_cma_alloc()
612{
613   // get a new CMA channel index
614    unsigned int channel = _atomic_increment( &_cma_channel_allocator );
615    unsigned int thread  = _get_context_slot( CTX_TRDID_ID );
616    unsigned int vspace  = _get_context_slot( CTX_VSID_ID );
617
618    if ( channel >= NB_CMA_CHANNELS )
619    {
620        _printf("\n[GIET ERROR] in _sys_fbf_cma_alloc() : not enough CMA channels\n");
621        return -1;
622    }
623    else
624    {
625        _printf("\n[GIET WARNING] FBF_CMA channel %d allocated "
626                " to thread %d in vspace %d\n", channel, thread, vspace );
627        _set_context_slot( CTX_CMA_FB_ID, channel );
628        return 0;
629    }
630} // end sys_fbf_cma_alloc()
631
632////////////////////////////////////////////
633int _sys_fbf_cma_start( void*        vbase0, 
634                        void*        vbase1, 
635                        unsigned int length ) 
636{
637#if NB_CMA_CHANNELS > 0
638
639    unsigned int       ptab;            // page table virtual address
640    unsigned int       ko;              // unsuccessfull V2P translation
641    unsigned int       vaddr;           // virtual address
642    unsigned int       flags;           // protection flags
643    unsigned int       ppn;             // physical page number
644    unsigned long long chbuf_paddr;     // physical address of source chbuf descriptor
645
646    // get channel index
647    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
648
649    if ( channel >= NB_CMA_CHANNELS )
650    {
651        _printf("\n[GIET ERROR] in _fbf_cma_start() : CMA channel index too large\n");
652        return -1;
653    }
654
655#if GIET_DEBUG_FBF_CMA
656_printf("\n[FBF_CMA DEBUG] enters _sys_fbf_cma_start()\n"
657        " - channel      = %d\n"
658        " - buf0   vbase = %x\n"
659        " - buf1   vbase = %x\n"
660        " - buffer size  = %x\n",
661        channel,
662        (unsigned int)vbase0,
663        (unsigned int)vbase1,
664        length );
665#endif
666
667    // checking user buffers virtual addresses and length alignment
668    if ( ((unsigned int)vbase0 & 0x3) || ((unsigned int)vbase1 & 0x3) || (length & 0x3) ) 
669    {
670        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer not word aligned\n");
671        return -1;
672    }
673
674    // get page table virtual address
675    ptab = _get_context_slot(CTX_PTAB_ID);
676
677    // compute frame buffer physical address and initialize _fbf_chbuf[channel]
678    vaddr = ((unsigned int)SEG_FBF_BASE);
679    ko    = _v2p_translate( (page_table_t*) ptab, 
680                            (vaddr >> 12),
681                            &ppn, 
682                            &flags );
683    if (ko) 
684    {
685        _printf("\n[GIET ERROR] in _fb_cma_start() : frame buffer unmapped\n");
686        return -1;
687    }
688
689    _fbf_chbuf[channel].fbf    = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
690
691    // Compute user buffer 0 physical addresses and intialize _fbf_chbuf[channel]
692    vaddr = (unsigned int)vbase0; 
693    ko = _v2p_translate( (page_table_t*) ptab, 
694                         (vaddr >> 12),
695                         &ppn, 
696                         &flags );
697    if (ko) 
698    {
699        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer 0 unmapped\n");
700        return -1;
701    } 
702    if ((flags & PTE_U) == 0) 
703    {
704        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer 0 not in user space\n");
705        return -1;
706    }
707
708    _fbf_chbuf[channel].buf0 = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
709
710    // Compute user buffer 1 physical addresses and intialize _fbf_chbuf[channel]
711    vaddr = (unsigned int)vbase1; 
712    ko = _v2p_translate( (page_table_t*) ptab, 
713                         (vaddr >> 12),
714                         &ppn, 
715                         &flags );
716    if (ko) 
717    {
718        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer 1 unmapped\n");
719        return -1;
720    } 
721    if ((flags & PTE_U) == 0) 
722    {
723        _printf("\n[GIET ERROR] in _fbf_cma_start() : user buffer 1 not in user space\n");
724        return -1;
725    }
726
727    _fbf_chbuf[channel].buf1 = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
728
729    // initializes buffer length
730    _fbf_chbuf[channel].length = length;
731
732    // Compute and register physical adress of the chbuf descriptor
733    vaddr = (unsigned int)(&_fbf_chbuf[channel]);
734    ko = _v2p_translate( (page_table_t*) ptab, 
735                         (vaddr >> 12),
736                         &ppn, 
737                         &flags );
738    if (ko) 
739    {
740        _printf("\n[GIET ERROR] in _fbf_cma_start() : chbuf descriptor unmapped\n");
741        return -1;
742    }
743 
744    chbuf_paddr = (((paddr_t)ppn) << 12) | (vaddr & 0x00000FFF);
745
746    _fbf_chbuf_paddr[channel] = chbuf_paddr;
747
748
749    if ( USE_IOB )
750    {
751        // SYNC request for channel descriptor
752        _mmc_sync( chbuf_paddr, 32 );
753    }
754
755#if GIET_DEBUG_FBF_CMA
756_printf(" - fbf    pbase = %l\n"
757        " - buf0   pbase = %l\n"
758        " - buf1   pbase = %l\n"
759        " - chbuf  pbase = %l\n",
760        _fbf_chbuf[channel].fbf,
761        _fbf_chbuf[channel].buf0,
762        _fbf_chbuf[channel].buf1,
763        chbuf_paddr );
764#endif
765
766    // call CMA driver to start transfer
767    _cma_channel_start( channel, 
768                        chbuf_paddr,
769                        2,
770                        chbuf_paddr + 16,
771                        1,
772                        length );
773    return 0;
774
775#else
776
777    _printf("\n[GIET ERROR] in _sys_fbf_cma_start() : NB_CMA_CHANNELS = 0\n");
778    return -1;
779
780#endif
781} // end _sys_fbf_cma_start()
782
783/////////////////////////////////////////////////////
784int _sys_fbf_cma_display( unsigned int buffer_index )
785{
786#if NB_CMA_CHANNELS > 0
787
788    volatile paddr_t buf_paddr;
789    unsigned int     full = 1;
790
791    // get channel index
792    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
793
794    if ( channel >= NB_CMA_CHANNELS )
795    {
796        _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : CMA channel index too large\n");
797        return -1;
798    }
799
800#if GIET_DEBUG_FBF_CMA
801_printf("\n[FBF_CMA DEBUG] enters _sys_fb_cma_display()\n"
802        " - channel      = %d\n"
803        " - buffer       = %d\n",
804        channel, buffer_index );
805#endif
806
807    // waiting user buffer empty
808    while ( full )
809    { 
810        if ( USE_IOB )
811        {
812            // INVAL L1 cache for the chbuf descriptor,
813            _dcache_buf_invalidate( (unsigned int)&_fbf_chbuf[channel], 32 );
814
815            // INVAL L2 cache for the chbuf descriptor,
816            _mmc_inval( _fbf_chbuf_paddr[channel], 32 );
817        }
818
819        // read user buffer descriptor
820        if ( buffer_index == 0 ) buf_paddr = _fbf_chbuf[channel].buf0;
821        else                     buf_paddr = _fbf_chbuf[channel].buf1;
822
823        full = ( (unsigned int)(buf_paddr>>63) );
824    }
825
826    if ( USE_IOB )
827    {
828        // SYNC request for the user buffer, because
829        // it will be read from XRAM by the CMA component
830        _mmc_sync( buf_paddr, _fbf_chbuf[channel].length );
831    }
832
833    // set user buffer status
834    if ( buffer_index == 0 ) _fbf_chbuf[channel].buf0 = buf_paddr | 0x8000000000000000ULL;
835    else                     _fbf_chbuf[channel].buf1 = buf_paddr | 0x8000000000000000ULL;
836
837    // reset fbf buffer status
838    _fbf_chbuf[channel].fbf  = _fbf_chbuf[channel].fbf & 0x7FFFFFFFFFFFFFFFULL;
839
840    if ( USE_IOB )
841    {
842        // SYNC request for the channel descriptor, because
843        // it will be read from XRAM by the CMA component
844        _mmc_sync( _fbf_chbuf_paddr[channel], 32 );
845    }
846
847#if GIET_DEBUG_FBF_CMA
848_printf(" - fbf    pbase = %l\n"
849        " - buf0   pbase = %l\n"
850        " - buf1   pbase = %l\n",
851        _fbf_chbuf[channel].fbf,
852        _fbf_chbuf[channel].buf0,
853        _fbf_chbuf[channel].buf1 );
854#endif
855
856
857    return 0;
858
859#else
860
861    _printf("\n[GIET ERROR] in _sys_fbf_cma_display() : no CMA channel allocated\n");
862    return -1;
863
864#endif
865} // end _sys_fbf_cma_display()
866
867///////////////////////
868int _sys_fbf_cma_stop()
869{
870#if NB_CMA_CHANNELS > 0
871
872    // get channel index
873    unsigned int channel = _get_context_slot( CTX_CMA_FB_ID );
874
875    if ( channel >= NB_CMA_CHANNELS )
876    {
877        _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : CMA channel index too large\n");
878        return -1;
879    }
880
881    // Desactivate CMA channel
882    _cma_channel_stop( channel );
883
884    return 0;
885
886#else
887
888    _printf("\n[GIET ERROR] in _sys_fbf_cma_stop() : no CMA channel allocated\n");
889    return -1;
890
891#endif
892} // end _sys_fbf_cma_stop()
893
894
895//////////////////////////////////////////////////////////////////////////////
896//           Miscelaneous syscall handlers
897//////////////////////////////////////////////////////////////////////////////
898
899///////////////
900int _sys_ukn() 
901{
902    _printf("\n[GIET ERROR] Undefined System Call / EPC = %x\n", _get_epc() );
903    return -1;
904}
905
906////////////////////////////////////
907int _sys_proc_xyp( unsigned int* x,
908                   unsigned int* y,
909                   unsigned int* p )
910{
911    unsigned int gpid = _get_procid();  // global processor index from CPO register
912
913    *x = (gpid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
914    *y = (gpid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
915    *p = gpid & ((1<<P_WIDTH)-1);
916
917    return 0;
918}
919
920//////////////////////////////////
921int _sys_task_exit( char* string ) 
922{
923    unsigned int date       = _get_proctime();
924
925    unsigned int gpid       = _get_procid();
926    unsigned int cluster_xy = gpid >> P_WIDTH;
927    unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
928    unsigned int x          = cluster_xy >> Y_WIDTH;
929    unsigned int lpid       = gpid & ((1<<P_WIDTH)-1);
930
931    unsigned int task_id    = _get_context_slot(CTX_LTID_ID);
932
933    // print exit message
934    _printf("\n[GIET] Exit task %d on processor[%d,%d,%d] at cycle %d"
935            "\n       Cause : %s\n\n",
936            task_id, x, y, lpid, date, string );
937
938    // goes to sleeping state
939    _set_context_slot(CTX_RUN_ID, 0);
940
941    // deschedule
942    _context_switch();
943
944    return 0;
945} 
946
947//////////////////////
948int _context_switch() 
949{
950    unsigned int save_sr;
951
952    _it_disable( &save_sr );
953    _ctx_switch();
954    _it_restore( &save_sr );
955
956    return 0;
957}
958
959////////////////////////
960int _sys_local_task_id()
961{
962    return _get_context_slot(CTX_LTID_ID);
963}
964
965/////////////////////////
966int _sys_global_task_id()
967{
968    return _get_context_slot(CTX_GTID_ID);
969}
970
971////////////////////
972int _sys_thread_id()
973{
974    return _get_context_slot(CTX_TRDID_ID);
975}
976
977//////////////////////////////////////
978int _sys_procs_number( unsigned int  x, 
979                       unsigned int  y, 
980                       unsigned int* number )
981{
982    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
983    mapping_cluster_t * cluster = _get_cluster_base(header);
984
985    if ( (x < X_SIZE) && (y < Y_SIZE) )
986    {
987        *number = cluster[(x*Y_SIZE)+y].procs;
988        return 0;
989    }
990    else 
991    {
992        _printf("\n[GIET ERROR] in _sys_procs_number() : illegal (x,y) coordinates\n" );
993        return -1;
994    }
995}
996
997///////////////////////////////////////////////////////
998int _sys_vobj_get_vbase( char*             vspace_name, 
999                         char*             vobj_name, 
1000                         unsigned int*     vbase ) 
1001{
1002    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1003    mapping_vspace_t * vspace = _get_vspace_base(header);
1004    mapping_vobj_t * vobj     = _get_vobj_base(header);
1005
1006    unsigned int vspace_id;
1007    unsigned int vobj_id;
1008
1009    // scan vspaces
1010    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1011    {
1012        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
1013        {
1014            // scan vobjs
1015            for (vobj_id = vspace[vspace_id].vobj_offset; 
1016                 vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs); 
1017                 vobj_id++) 
1018            {
1019                if (_strncmp(vobj[vobj_id].name, vobj_name, 31) == 0) 
1020                {
1021                    *vbase = vobj[vobj_id].vbase;
1022                    return 0;
1023                }
1024            } 
1025        }
1026    } 
1027    return -1;    // not found
1028}
1029
1030/////////////////////////////////////////////////////////
1031int _sys_vobj_get_length( char*         vspace_name, 
1032                          char*         vobj_name,
1033                          unsigned int* length ) 
1034{
1035    mapping_header_t * header = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1036    mapping_vspace_t * vspace = _get_vspace_base(header);
1037    mapping_vobj_t * vobj     = _get_vobj_base(header);
1038
1039    unsigned int vspace_id;
1040    unsigned int vobj_id;
1041
1042    // scan vspaces
1043    for (vspace_id = 0; vspace_id < header->vspaces; vspace_id++) 
1044    {
1045        if (_strncmp( vspace[vspace_id].name, vspace_name, 31) == 0) 
1046        {
1047            // scan vobjs
1048            for (vobj_id = vspace[vspace_id].vobj_offset; 
1049                 vobj_id < (vspace[vspace_id].vobj_offset + vspace[vspace_id].vobjs); 
1050                 vobj_id++) 
1051            {
1052                if (_strncmp(vobj[vobj_id].name, vobj_name, 31) == 0) 
1053                {
1054                    *length = vobj[vobj_id].length;
1055                    return 0;
1056                }
1057            } 
1058        }
1059    } 
1060    return -1;    // not found
1061}
1062
1063////////////////////////////////////////
1064int _sys_xy_from_ptr( void*         ptr,
1065                      unsigned int* x,
1066                      unsigned int* y )
1067{
1068    unsigned int ret;
1069    unsigned int ppn;
1070    unsigned int flags;
1071    unsigned int vpn  = (((unsigned int)ptr)>>12);
1072   
1073    // get the page table pointer
1074    page_table_t* pt = (page_table_t*)_get_context_slot( CTX_PTAB_ID ); 
1075
1076    // compute the physical address
1077    if ( (ret = _v2p_translate( pt, vpn, &ppn, &flags )) ) return -1;
1078
1079    *x = (ppn>>24) & 0xF;
1080    *y = (ppn>>20) & 0xF;
1081    return 0;
1082}
1083
1084/////////////////////////////////////////
1085int _sys_heap_info( unsigned int* vaddr, 
1086                    unsigned int* length,
1087                    unsigned int  x,
1088                    unsigned int  y ) 
1089{
1090    mapping_header_t * header  = (mapping_header_t *)SEG_BOOT_MAPPING_BASE;
1091    mapping_task_t *   tasks   = _get_task_base(header);
1092    mapping_vobj_t *   vobjs   = _get_vobj_base(header);
1093    mapping_vspace_t * vspaces = _get_vspace_base(header);
1094
1095    unsigned int task_id;
1096    unsigned int vspace_id;
1097    unsigned int vobj_id = 0xFFFFFFFF;
1098
1099    // searching the heap vobj_id
1100    if ( (x < X_SIZE) && (y < Y_SIZE) )  // searching a task in cluster(x,y)
1101    {
1102        // get vspace global index
1103        vspace_id = _get_context_slot(CTX_VSID_ID);
1104
1105        // scan all tasks in vspace
1106        unsigned int min = vspaces[vspace_id].task_offset ;
1107        unsigned int max = min + vspaces[vspace_id].tasks ;
1108        for ( task_id = min ; task_id < max ; task_id++ )
1109        {
1110            if ( tasks[task_id].clusterid == (x * Y_SIZE + y) )
1111            {
1112                vobj_id = tasks[task_id].heap_vobj_id;
1113                if ( vobj_id != 0xFFFFFFFF ) break;
1114            }
1115        }
1116    }
1117    else                                // searching in the calling task
1118    {
1119        task_id = _get_context_slot(CTX_GTID_ID);
1120        vobj_id = tasks[task_id].heap_vobj_id;
1121    }
1122
1123    // analysing the vobj_id
1124    if ( vobj_id != 0xFFFFFFFF ) 
1125    {
1126        *vaddr  = vobjs[vobj_id].vbase;
1127        *length = vobjs[vobj_id].length;
1128        return 0;
1129    }
1130    else 
1131    {
1132        *vaddr  = 0;
1133        *length = 0;
1134        return -1;
1135    }
1136}  // end _sys_heap_info()
1137
1138
1139// Local Variables:
1140// tab-width: 4
1141// c-basic-offset: 4
1142// c-file-offsets:((innamespace . 0)(inline-open . 0))
1143// indent-tabs-mode: nil
1144// End:
1145// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
1146
Note: See TracBrowser for help on using the repository browser.