source: soft/giet_vm/sys/drivers.c @ 189

Last change on this file since 189 was 189, checked in by alain, 12 years ago

Introducing a new release where all initialisation
is done in the boot code.

File size: 38.6 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : drivers.c
3// Date     : 01/04/2012
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The drivers.c and drivers.h files are part ot the GIET-VM nano kernel.
8// They contains the drivers for the peripherals available in the SoCLib library:
9// - vci_multi_tty
10// - vci_multi_timer
11// - vci_multi_dma
12// - vci_multi_icu
13// - vci_xicu
14// - vci_gcd
15// - vci_frame_buffer
16// - vci_block_device
17//
18// The following global parameters must be defined in the giet_config.h file:
19// - NB_CLUSTERS   
20// - NB_PROCS_MAX 
21// - NB_TIMERS_MAX   
22// - NB_DMAS_MAX     
23// - NB_TTYS   
24//
25// The following base addresses must be defined in the sys.ld file:
26// - seg_icu_base
27// - seg_timer_base
28// - seg_tty_base
29// - seg_gcd_base
30// - seg_dma_base
31// - seg_fb_base
32// - seg_ioc_base
33///////////////////////////////////////////////////////////////////////////////////
34
35#include <vm_handler.h>
36#include <sys_handler.h>
37#include <giet_config.h>
38#include <drivers.h>
39#include <common.h>
40#include <hwr_mapping.h>
41#include <mips32_registers.h>
42#include <ctx_handler.h>
43
44#if !defined(NB_CLUSTERS)
45# error: You must define NB_CLUSTERS in 'giet_config.h' file
46#endif
47
48#if !defined(NB_PROCS_MAX)
49# error: You must define NB_PROCS_MAX in 'giet_config.h' file
50#endif
51
52#if (NB_PROCS_MAX > 8)
53# error: NB_PROCS_MAX cannot be larger than 8!
54#endif
55
56#if !defined(CLUSTER_SPAN)
57# error: You must define CLUSTER_SPAN in 'giet_config.h' file
58#endif
59
60#if !defined(NB_TTYS)
61# error: You must define NB_TTYS in 'giet_config.h' file
62#endif
63
64#if (NB_TTYS < 1)
65# error: NB_TTYS cannot be smaller than 1!
66#endif
67
68#if !defined(NB_DMAS_MAX)
69# error: You must define NB_DMAS_MAX in 'giet_config.h' file
70#endif
71
72#if (NB_DMAS_MAX < 1)
73# error: NB_DMAS_MAX cannot be 0!
74#endif
75
76#if !defined(NB_TIMERS_MAX)
77# error: You must define NB_TIMERS_MAX in 'giet_config.h' file
78#endif
79
80#if ( (NB_TIMERS_MAX + NB_PROCS_MAX) > 32 )
81# error: NB_TIMERS_MAX + NB_PROCS_MAX cannot be larger than 32
82#endif
83
84#if !defined(NB_IOCS)
85# error: You must define NB_IOCS in 'giet_config.h' file
86#endif
87
88#if ( NB_IOCS > 1 )
89# error: NB_IOCS cannot be larger than 1
90#endif
91
92
93#define in_unckdata __attribute__((section (".unckdata")))
94
95
96//////////////////////////////////////////////////////////////////////////////
97//      VciMultiTimer driver
98//////////////////////////////////////////////////////////////////////////////
99// There is one multi_timer (or xicu) component per cluster.
100// The global index is cluster_id*(NB_PROCS_MAX+NB_TIMERS_MAX) + local_id
101// There is two types of timers:
102// - "system" timers : one per processor, used for context switch.
103//   local_id in [0, NB_PROCS_MAX-1],
104// - "user" timers : requested by the task in the mapping_info data structure.
105//   local_id in [NB_PROC_MAX, NB_PROCS_MAX+NB_TIMERS_MAX-1],
106//   For each user timer, the tty_id is stored in the context of the task
107//   and must be explicitely defined in the boot code.
108// These timers can be implemented in a vci_multi_timer component
109// or in a vci_xicu component (depending on the GIET_USE_XICU parameter).
110//////////////////////////////////////////////////////////////////////////////
111
112// User Timer signaling variables
113
114#if (NB_TIMERS_MAX > 0)
115in_unckdata volatile unsigned char _user_timer_event[NB_CLUSTERS*NB_TIMERS_MAX] 
116         = { [0 ... ((NB_CLUSTERS*NB_TIMERS_MAX)-1)] = 0 };
117#endif
118
119//////////////////////////////////////////////////////////////////////////////
120//     _timer_access()
121// This function is the only way to access a timer device.
122// It can be a multi-timer component or an xicu component.
123// It can be used by the kernel to initialise a "system" timer,
124// or by a task (through a system call) to configure an "user" timer.
125// Returns 0 if success, > 0 if error.
126//////////////////////////////////////////////////////////////////////////////
127unsigned int _timer_access( unsigned int        read,
128                            unsigned int        cluster_id,
129                            unsigned int        local_id,
130                            unsigned int        register_id, 
131                            unsigned int*       buffer )
132{
133    // parameters checking
134    if ( register_id >= TIMER_SPAN)                                     return 1;
135    if ( cluster_id >= NB_CLUSTERS)                                     return 1;
136    if ( local_id >= NB_TIMERS_MAX + NB_PROCS_MAX ) return 1;
137
138#if GIET_USE_XICU
139
140    unsigned int* timer_address = //TODO
141
142#else
143
144    unsigned int* timer_address = (unsigned int*)&seg_timer_base + 
145                                  (cluster_id * CLUSTER_SPAN)  +
146                                  (local_id * TIMER_SPAN);
147#endif
148
149    if (read)   *buffer = timer_address[register_id]; // read word
150    else                timer_address[register_id] = *buffer; // write word
151    return 0;
152}
153//////////////////////////////////////////////////////////////////////////////
154//     _timer_write()
155// This function implements a write access to a "user" timer register.
156// It gets the cluster_id and local_id from the global index stored in
157// the task context and use the timer_access() function to make the write.
158// Returns 0 if success, > 0 if error.
159//////////////////////////////////////////////////////////////////////////////
160unsigned int _timer_write( unsigned int register_id, 
161                           unsigned int value )
162{
163    unsigned int buffer     = value;
164    unsigned int timer_id   = _get_current_context_slot(CTX_TIMER_ID);
165    unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX);
166    unsigned int local_id   = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX);
167
168    // checking user timer
169    if ( local_id < NB_PROCS_MAX ) 
170    {
171        return 2;
172    }
173    else
174    {
175        return _timer_access ( 0,                               // write access
176                               cluster_id,
177                               local_id,
178                               register_id,
179                               &buffer );
180    }
181}
182//////////////////////////////////////////////////////////////////////////////
183//     _timer_read()
184// This function implements a read access to a "user" timer register.
185// It gets the cluster_id and local_id from the global index stored in
186// the task context and use the timer_access() function to make the read.
187// Returns 0 if success, > 0 if error.
188//////////////////////////////////////////////////////////////////////////////
189unsigned int _timer_read( unsigned int  register_id, 
190                          unsigned int* buffer )
191{
192    unsigned int timer_id   = _get_current_context_slot(CTX_TIMER_ID);
193    unsigned int cluster_id = timer_id / (NB_PROCS_MAX + NB_TIMERS_MAX);
194    unsigned int local_id   = timer_id % (NB_PROCS_MAX + NB_TIMERS_MAX);
195
196    // checking user timer
197    if ( local_id < NB_PROCS_MAX ) 
198    {
199        return 2;
200    }
201    else
202    {
203        return _timer_access ( 1,                               // read access
204                               cluster_id,
205                               local_id,
206                               register_id,
207                               buffer );
208    }
209}
210/////////////////////////////////////////////////////////////////////////////////
211//     _timer_check()
212/////////////////////////////////////////////////////////////////////////////////
213
214/////////////////////////////////////////////////////////////////////////////////
215//      VciMultiTty driver
216/////////////////////////////////////////////////////////////////////////////////
217// There is only one multi_tty controler in the architecture.
218// The total number of TTYs is defined by the configuration parameter NB_TTYS.
219// The "system" terminal is TTY[0].
220// The "user" TTYs are allocated to applications by the GIET in the boot phase,
221// as defined in the mapping_info data structure. The corresponding tty_id must
222// be stored in the context of the task by the boot code.
223// The TTY address is : seg_tty_base + tty_id*TTY_SPAN
224/////////////////////////////////////////////////////////////////////////////////
225
226// TTY variables
227in_unckdata volatile unsigned char _tty_get_buf[NB_TTYS];
228in_unckdata volatile unsigned char _tty_get_full[NB_TTYS] = { [0 ... NB_TTYS-1] = 0 };
229in_unckdata unsigned int           _tty_put_lock = 0;  // protect kernel TTY[0]
230
231////////////////////////////////////////////////////////////////////////////////
232//      _tty_error()
233////////////////////////////////////////////////////////////////////////////////
234void _tty_error()
235{
236    unsigned int task_id = _get_current_task_id();
237    unsigned int proc_id = _procid();
238
239    _get_lock(&_tty_put_lock);
240    _puts("\n[GIET ERROR] TTY index too large for task ");
241    _putw( task_id );
242    _puts(" on processor ");
243    _putw( proc_id );
244    _puts("\n");
245    _release_lock(&_tty_put_lock);
246}
247/////////////////////////////////////////////////////////////////////////////////
248//      _tty_write()
249// Write one or several characters directly from a fixed-length user buffer to
250// the TTY_WRITE register of the TTY controler.
251// It doesn't use the TTY_PUT_IRQ interrupt and the associated kernel buffer.
252// This is a non blocking call: it tests the TTY_STATUS register, and stops
253// the transfer as soon as the TTY_STATUS[WRITE] bit is set.
254// The function returns  the number of characters that have been written.
255/////////////////////////////////////////////////////////////////////////////////
256unsigned int _tty_write( const char             *buffer, 
257                         unsigned int   length)
258{
259    unsigned int        nwritten;
260
261    unsigned int        tty_id = _get_current_context_slot(CTX_TTY_ID);
262    if ( tty_id >= NB_TTYS )
263    {
264        _tty_error();
265        return 0;
266    }
267
268    unsigned int*       tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN;
269
270    for (nwritten = 0; nwritten < length; nwritten++)
271    {
272        // check tty's status
273        if ((tty_address[TTY_STATUS] & 0x2) == 0x2)
274            break;
275        else
276            // write character
277            tty_address[TTY_WRITE] = (unsigned int)buffer[nwritten];
278    }
279    return nwritten;
280}
281//////////////////////////////////////////////////////////////////////////////
282//      _tty_read_irq()
283// This non-blocking function uses the TTY_GET_IRQ[tty_id] interrupt and
284// the associated kernel buffer, that has been written by the ISR.
285// It fetches one single character from the _tty_get_buf[tty_id] kernel
286// buffer, writes this character to the user buffer, and resets the
287// _tty_get_full[tty_id] buffer.
288// Returns 0 if the kernel buffer is empty, 1 if the buffer is full.
289//////////////////////////////////////////////////////////////////////////////
290unsigned int _tty_read_irq( char                        *buffer, 
291                            unsigned int        length)
292{
293    unsigned int        tty_id = _get_current_context_slot(CTX_TTY_ID);
294
295    if ( tty_id >= NB_TTYS )
296    {
297        _tty_error();
298        return 0;
299    }
300
301    if (_tty_get_full[tty_id] == 0) 
302    {
303        return 0;
304    }
305    else
306    {
307        *buffer = _tty_get_buf[tty_id];
308        _tty_get_full[tty_id] = 0;
309        return 1;
310    }
311} 
312////////////////////////////////////////////////////////////////////////////////
313//     _tty_read()
314// This non-blocking function fetches one character directly from the TTY_READ
315// register of the TTY controler, and writes this character to the user buffer.
316// It doesn't use the TTY_GET_IRQ interrupt and the associated kernel buffer.
317// Returns 0 if the register is empty, 1 if the register is full.
318////////////////////////////////////////////////////////////////////////////////
319unsigned int _tty_read( char                    *buffer, 
320                        unsigned int    length)
321{
322    unsigned int        tty_id = _get_current_context_slot(CTX_TTY_ID);
323    if ( tty_id >= NB_TTYS )
324    {
325        _tty_error();
326        return 0;
327    }
328
329    unsigned int*       tty_address = (unsigned int*)&seg_tty_base + tty_id*TTY_SPAN;
330
331    if ((tty_address[TTY_STATUS] & 0x1) != 0x1) 
332    {
333        return 0;
334    }
335    else
336    {
337        *buffer = (char)tty_address[TTY_READ];
338        return 1;
339    }
340}
341
342////////////////////////////////////////////////////////////////////////////////
343//      VciMultiIcu and VciXicu drivers
344////////////////////////////////////////////////////////////////////////////////
345// There is in principle one vci_multi_icu (or vci_xicu) component per cluster,
346// and the number of independant ICUs is equal to NB_PROCS_MAX, because there is
347// one private interrupr controler per processor.
348////////////////////////////////////////////////////////////////////////////////
349
350////////////////////////////////////////////////////////////////////////////////
351//     _icu_write()
352// Write a 32-bit word in a memory mapped register of the MULTI_ICU device,
353// identified by the cluster index, and a processor local index.
354// Returns 0 if success, > 0 if error.
355////////////////////////////////////////////////////////////////////////////////
356unsigned int _icu_write( unsigned int cluster_index,
357                         unsigned int proc_index,
358                         unsigned int register_index, 
359                         unsigned int value )
360{
361#if GIET_USE_XICU
362
363#else
364
365    // parameters checking
366    if ( register_index >= ICU_SPAN)            return 1;
367    if ( cluster_index >= NB_CLUSTERS)          return 1;
368    if ( proc_index >= NB_PROCS_MAX )       return 1;
369
370    unsigned int *icu_address = (unsigned int*)&seg_icu_base + 
371                                (cluster_index * CLUSTER_SPAN)  +
372                                (proc_index * ICU_SPAN);
373
374    icu_address[register_index] = value;   // write word
375    return 0;
376
377#endif
378}
379////////////////////////////////////////////////////////////////////////////////
380//     _icu_read()
381// Read a 32-bit word in a memory mapped register of the MULTI_ICU device,
382// identified by the cluster index and a processor local index.
383// Returns 0 if success, > 0 if error.
384////////////////////////////////////////////////////////////////////////////////
385unsigned int _icu_read(  unsigned int cluster_index,
386                         unsigned int proc_index,
387                         unsigned int register_index, 
388                         unsigned int* buffer )
389{
390#if GIET_USE_XICU
391
392#else
393
394    // parameters checking
395    if ( register_index >= ICU_SPAN)            return 1;
396    if ( cluster_index >= NB_CLUSTERS)          return 1;
397    if ( proc_index >= NB_PROCS_MAX )       return 1;
398
399    unsigned int *icu_address = (unsigned int*)&seg_icu_base + 
400                                (cluster_index * CLUSTER_SPAN)  +
401                                (proc_index * ICU_SPAN);
402
403    *buffer = icu_address[register_index]; // read word
404    return 0;
405
406#endif
407}
408
409////////////////////////////////////////////////////////////////////////////////
410//      VciGcd driver
411////////////////////////////////////////////////////////////////////////////////
412// The Greater Dommon Divider is a -very- simple hardware coprocessor
413// performing the computation of the GCD of two 32 bits integers.
414// It has no DMA capability.
415////////////////////////////////////////////////////////////////////////////////
416
417////////////////////////////////////////////////////////////////////////////////
418//     _gcd_write()
419// Write a 32-bit word in a memory mapped register of the GCD coprocessor.
420// Returns 0 if success, > 0 if error.
421////////////////////////////////////////////////////////////////////////////////
422unsigned int _gcd_write( unsigned int register_index, 
423                         unsigned int value)
424{
425    volatile unsigned int *gcd_address;
426
427    // parameters checking
428    if (register_index >= GCD_END)
429        return 1;
430
431    gcd_address = (unsigned int*)&seg_gcd_base;
432
433    gcd_address[register_index] = value; // write word
434    return 0;
435}
436////////////////////////////////////////////////////////////////////////////////
437//     _gcd_read()
438// Read a 32-bit word in a memory mapped register of the GCD coprocessor.
439// Returns 0 if success, > 0 if error.
440////////////////////////////////////////////////////////////////////////////////
441unsigned int _gcd_read( unsigned int register_index, 
442                        unsigned int *buffer)
443{
444    volatile unsigned int *gcd_address;
445
446    // parameters checking
447    if (register_index >= GCD_END)
448        return 1;
449
450    gcd_address = (unsigned int*)&seg_gcd_base;
451
452    *buffer = gcd_address[register_index]; // read word
453    return 0;
454}
455
456////////////////////////////////////////////////////////////////////////////////
457// VciBlockDevice driver
458////////////////////////////////////////////////////////////////////////////////
459// The VciBlockDevice is a single channel external storage contrÃŽler.
460//
461// The IOMMU can be activated or not:
462//
463// 1) When the IOMMU is used, a fixed size 2Mbytes vseg is allocated to
464// the IOC peripheral, in the I/O virtual space, and the user buffer is
465// dynamically remapped in the IOMMU page table. The corresponding entry
466// in the IOMMU PT1 is defined by the kernel _ioc_iommu_ix1 variable.
467// The number of pages to be unmapped is stored in the _ioc_npages variable.
468// The number of PT2 entries is dynamically computed and stored in the
469// kernel _ioc_iommu_npages variable. It cannot be larger than 512.
470// The user buffer is unmapped by the _ioc_completed() function when
471// the transfer is completed.
472//
473// 2/ If the IOMMU is not used, we check that  the user buffer is mapped to a
474// contiguous physical buffer (this is generally true because the user space
475// page tables are statically constructed to use contiguous physical memory).
476//
477// Finally, the memory buffer must fulfill the following conditions:
478// - The user buffer must be word aligned,
479// - The user buffer must be mapped in user address space,
480// - The user buffer must be writable in case of (to_mem) access,
481// - The total number of physical pages occupied by the user buffer cannot
482//   be larger than 512 pages if the IOMMU is activated,
483// - All physical pages occupied by the user buffer must be contiguous
484//   if the IOMMU is not activated.
485// An error code is returned if these conditions are not verified.
486//
487// As the IOC component can be used by several programs running in parallel,
488// the _ioc_lock variable guaranties exclusive access to the device.  The
489// _ioc_read() and _ioc_write() functions use atomic LL/SC to get the lock.
490// and set _ioc_lock to a non zero value.  The _ioc_write() and _ioc_read()
491// functions are blocking, polling the _ioc_lock variable until the device is
492// available.
493// When the tranfer is completed, the ISR routine activated by the IOC IRQ
494// set the _ioc_done variable to a non-zero value. Possible address errors
495// detected by the IOC peripheral are reported by the ISR in the _ioc_status
496// variable.
497// The _ioc_completed() function is polling the _ioc_done variable, waiting for
498// transfer completion. When the completion is signaled, the _ioc_completed()
499// function reset the _ioc_done variable to zero, and releases the _ioc_lock
500// variable.
501//
502// In a multi-processing environment, this polling policy should be replaced by
503// a descheduling policy for the requesting process.
504///////////////////////////////////////////////////////////////////////////////
505
506// IOC global variables
507in_unckdata volatile unsigned int       _ioc_status       = 0;
508in_unckdata volatile unsigned int       _ioc_done         = 0;
509in_unckdata unsigned int                        _ioc_lock         = 0;
510in_unckdata unsigned int                        _ioc_iommu_ix1    = 0;
511in_unckdata unsigned int                        _ioc_iommu_npages; 
512
513///////////////////////////////////////////////////////////////////////////////
514//      _ioc_access()
515// This function transfer data between a memory buffer and the block device.
516// The buffer lentgth is (count*block_size) bytes.
517// Arguments are:
518// - to_mem     : from external storage to memory when non 0
519// - lba        : first block index on the external storage.
520// - user_vaddr : virtual base address of the memory buffer.
521// - count      : number of blocks to be transfered.
522// Returns 0 if success, > 0 if error.
523///////////////////////////////////////////////////////////////////////////////
524unsigned int _ioc_access( unsigned int  to_mem,
525                          unsigned int  lba,
526                          unsigned int  user_vaddr,
527                          unsigned int  count )
528{
529    unsigned int                user_vpn_min;   // first virtuel page index in user space
530    unsigned int                user_vpn_max;   // last virtual page index in user space
531    unsigned int                vpn;                    // current virtual page index in user space
532    unsigned int                ppn;                    // physical page number
533    unsigned int                flags;                  // page protection flags
534    unsigned int                ix2;                    // page index in IOMMU PT1 page table
535    unsigned int                addr;                   // buffer address for IOC peripheral
536    unsigned int                ppn_first;              // first physical page number for user buffer
537       
538    // check buffer alignment
539    if ( (unsigned int)user_vaddr & 0x3 ) return 1;
540
541    unsigned int*       ioc_address = (unsigned int*)&seg_ioc_base;
542    unsigned int        block_size   = ioc_address[BLOCK_DEVICE_BLOCK_SIZE];
543    unsigned int        length       = count*block_size;
544
545    // get user space page table virtual address
546    unsigned int user_pt_vbase = _get_current_context_slot(CTX_PTAB_ID);
547   
548    user_vpn_min = user_vaddr >> 12;
549    user_vpn_max = (user_vaddr + length - 1) >> 12;
550    ix2          = 0;
551
552    // loop on all virtual pages covering the user buffer
553    for ( vpn = user_vpn_min ; vpn <= user_vpn_max ; vpn++ )
554    {
555        // get ppn and flags for each vpn
556        unsigned int ko = _v2p_translate( (page_table_t*)user_pt_vbase,
557                                           vpn,
558                                           &ppn,
559                                           &flags );
560
561        // check access rights
562        if ( ko )                                                                 return 2;             // unmapped
563        if ( (flags & PTE_U) == 0 )                               return 3;             // not in user space
564        if ( ( (flags & PTE_W) == 0 ) && to_mem ) return 4;             // not writable
565
566        // save first ppn value
567        if ( ix2 == 0 ) ppn_first = ppn;
568
569        if ( GIET_IOMMU_ACTIVE )    // the user buffer must be remapped in the I/0 space
570        {
571            // check buffer length < 2 Mbytes
572            if ( ix2 > 511 ) return 2;
573
574            // map the physical page in IOMMU page table
575            _iommu_add_pte2( _ioc_iommu_ix1,    // PT1 index
576                             ix2,                               // PT2 index
577                                                 ppn,                           // Physical page number
578                             flags );                   // Protection flags
579        }
580        else                    // no IOMMU : check that physical pages are contiguous
581        {
582            if ( (ppn - ppn_first) != ix2 )           return 5;         // split physical buffer 
583        }
584       
585        // increment page index
586        ix2++;
587    } // end for vpn
588
589    // register the number of pages to be unmapped
590    _ioc_iommu_npages = (user_vpn_max - user_vpn_min) + 1;
591
592    // invalidate data cache in case of memory write
593    if ( to_mem ) _dcache_buf_invalidate( (void*)user_vaddr, length );
594
595    // compute buffer base address for IOC depending on IOMMU activation
596    if ( GIET_IOMMU_ACTIVE ) addr = (_ioc_iommu_ix1) << 21 | (user_vaddr & 0xFFF);
597    else                     addr = (ppn_first << 12) | (user_vaddr & 0xFFF);
598
599    // get the lock on ioc device
600    _get_lock( &_ioc_lock );
601
602    // peripheral configuration 
603    ioc_address[BLOCK_DEVICE_BUFFER]     = addr;
604    ioc_address[BLOCK_DEVICE_COUNT]      = count;
605    ioc_address[BLOCK_DEVICE_LBA]        = lba;
606    if ( to_mem == 0 ) ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_WRITE;
607    else               ioc_address[BLOCK_DEVICE_OP] = BLOCK_DEVICE_READ;
608
609    return 0;
610}
611/////////////////////////////////////////////////////////////////////////////////
612// _ioc_completed()
613//
614// This function checks completion of an I/O transfer and reports errors.
615// As it is a blocking call, the processor is stalled.
616// If the virtual memory is activated, the pages mapped in the I/O virtual
617// space are unmapped, and the IOB TLB is cleared.
618// Returns 0 if success, > 0 if error.
619/////////////////////////////////////////////////////////////////////////////////
620unsigned int _ioc_completed()
621{
622    unsigned int        ret;
623    unsigned int        ix2;
624
625    // busy waiting
626    while (_ioc_done == 0)
627        asm volatile("nop");
628
629    // unmap the buffer from IOMMU page table if IOMMU is activated
630    if ( GIET_IOMMU_ACTIVE )
631    {
632        unsigned int* iob_address = (unsigned int*)&seg_iob_base;
633
634        for ( ix2 = 0 ; ix2 < _ioc_iommu_npages ; ix2++ )
635        {
636            // unmap the page in IOMMU page table
637            _iommu_inval_pte2( _ioc_iommu_ix1,  // PT1 index
638                              ix2 );                    // PT2 index
639
640            // clear IOMMU TLB
641            iob_address[IOB_INVAL_PTE] = (_ioc_iommu_ix1 << 21) | (ix2 << 12); 
642        }
643    }
644
645    // test IOC status
646    if ((_ioc_status != BLOCK_DEVICE_READ_SUCCESS)
647            && (_ioc_status != BLOCK_DEVICE_WRITE_SUCCESS)) ret = 1;    // error
648    else                                                    ret = 0;    // success
649
650    // reset synchronization variables
651    _ioc_lock =0;
652    _ioc_done =0;
653
654    return ret;
655}
656///////////////////////////////////////////////////////////////////////////////
657//     _ioc_read()
658// Transfer data from the block device to a memory buffer in user space.
659// - lba    : first block index on the block device
660// - buffer : base address of the memory buffer (must be word aligned)
661// - count  : number of blocks to be transfered.
662// Returns 0 if success, > 0 if error.
663///////////////////////////////////////////////////////////////////////////////
664unsigned int _ioc_read( unsigned int    lba, 
665                        void*               buffer, 
666                        unsigned int    count )
667{
668    return _ioc_access( 1,              // read access
669                        lba,
670                        (unsigned int)buffer,
671                        count );
672}
673///////////////////////////////////////////////////////////////////////////////
674//     _ioc_write()
675// Transfer data from a memory buffer in user space to the block device.
676// - lba    : first block index on the block device
677// - buffer : base address of the memory buffer (must be word aligned)
678// - count  : number of blocks to be transfered.
679// Returns 0 if success, > 0 if error.
680///////////////////////////////////////////////////////////////////////////////
681unsigned int _ioc_write( unsigned int   lba, 
682                         const void*    buffer, 
683                         unsigned int   count )
684{
685    return _ioc_access( 0,              // write access
686                        lba,
687                        (unsigned int)buffer,
688                        count );
689}
690
691//////////////////////////////////////////////////////////////////////////////////
692// VciMultiDma driver
693//////////////////////////////////////////////////////////////////////////////////
694// The DMA controllers are physically distributed in the clusters.
695// There is  (NB_CLUSTERS * NB_DMAS_MAX) channels, indexed by a global index:
696//        dma_id = cluster_id * NB_DMA_MAX + loc_id
697//
698// As a DMA channel can be used by several tasks, each DMA channel is protected
699// by a specific lock: _dma_lock[dma_id]
700// The signalisation between the OS and the DMA uses the _dma_done[dma_id]
701// synchronisation variables  (set by the ISR, and reset by the OS).
702// The transfer status is copied by the ISR in the _dma_status[dma_id] variables.
703//
704// These DMA channels can be used by the FB driver, or by the NIC driver.
705//////////////////////////////////////////////////////////////////////////////////
706
707#if  (NB_DMAS_MAX > 0)
708in_unckdata unsigned int                        _dma_lock[NB_DMAS_MAX * NB_CLUSTERS]
709                                       = { [0 ... (NB_DMAS_MAX * NB_CLUSTERS)-1] = 0 };
710
711in_unckdata volatile unsigned int       _dma_done[NB_DMAS_MAX * NB_CLUSTERS]
712                                       = { [0 ... (NB_DMAS_MAX * NB_CLUSTERS)-1] = 0 };
713
714in_unckdata volatile unsigned int       _dma_status[NB_DMAS_MAX * NB_CLUSTERS];
715
716in_unckdata unsigned int                        _dma_iommu_ix1 = 1;
717
718in_unckdata unsigned int            _dma_iommu_npages[NB_DMAS_MAX * NB_CLUSTERS];
719#endif
720
721//////////////////////////////////////////////////////////////////////////////////
722//      VciFrameBuffer driver
723//////////////////////////////////////////////////////////////////////////////////
724// The vci_frame_buffer device can be accessed directly by software with memcpy(),
725// or it can be accessed through a multi-channels DMA component:
726// 
727// The '_fb_sync_write' and '_fb_sync_read' functions use a memcpy strategy to
728// implement the transfer between a data buffer (user space) and the frame
729// buffer (kernel space). They are blocking until completion of the transfer.
730//
731// The '_fb_write()', '_fb_read()' and '_fb_completed()' functions use the DMA
732// controlers (distributed in the clusters) to transfer data
733// between the user buffer and the frame buffer. A  DMA channel is
734// allocated to each task requesting it in the mapping_info data structure.
735//////////////////////////////////////////////////////////////////////////////////
736
737//////////////////////////////////////////////////////////////////////////////////
738// _fb_sync_write()
739// Transfer data from an memory buffer to the frame_buffer device using
740// a memcpy. The source memory buffer must be in user address space.
741// - offset : offset (in bytes) in the frame buffer.
742// - buffer : base address of the memory buffer.
743// - length : number of bytes to be transfered.
744// Returns 0 if success, > 0 if error.
745//////////////////////////////////////////////////////////////////////////////////
746unsigned int _fb_sync_write( unsigned int       offset, 
747                             const void*        buffer, 
748                             unsigned int       length )
749{
750
751    // buffer must be mapped in user space
752    if ( ((unsigned int)buffer + length ) >= 0x80000000 )
753    {
754        return 1;
755    }
756    else
757    {
758        unsigned char *fb_address = (unsigned char*)&seg_fb_base + offset;
759        memcpy((void*)fb_address, (void*)buffer, length);
760        return 0;
761    }
762}
763
764//////////////////////////////////////////////////////////////////////////////////
765// _fb_sync_read()
766// Transfer data from the frame_buffer device to a memory buffer using
767// a memcpy. The destination memory buffer must be in user address space.
768// - offset : offset (in bytes) in the frame buffer.
769// - buffer : base address of the memory buffer.
770// - length : number of bytes to be transfered.
771// Returns 0 if success, > 0 if error.
772//////////////////////////////////////////////////////////////////////////////////
773unsigned int _fb_sync_read( unsigned int        offset, 
774                            const void*         buffer, 
775                            unsigned int        length )
776{
777    // buffer must be mapped in user space
778    if ( ((unsigned int)buffer + length ) >= 0x80000000 )
779    {
780        return 1;
781    }
782    else
783    {
784        unsigned char *fb_address = (unsigned char*)&seg_fb_base + offset;
785        memcpy((void*)buffer, (void*)fb_address, length);
786        return 0;
787    }
788}
789
790//////////////////////////////////////////////////////////////////////////////////
791// _fb_dma_access()
792// Transfer data between a user buffer and the frame_buffer using DMA.
793// - to_user    : from frame buffer to user buffer when true.
794// - offset     : offset (in bytes) in the frame buffer.
795// - user_vaddr : virtual base address of the memory buffer.
796// - length     : number of bytes to be transfered.
797// The memory buffer must be mapped in user address space and word-aligned.
798// The user buffer length must be multiple of 4 bytes.
799// Me must compute the physical base addresses for both the frame buffer
800// and the user buffer before programming the DMA transfer.
801// The GIET being fully static, we don't need to split the transfer in 4Kbytes
802// pages, because the user buffer is contiguous in physical space.
803// Returns 0 if success, > 0 if error.
804//////////////////////////////////////////////////////////////////////////////////
805unsigned int _fb_dma_access( unsigned int       to_user,
806                             unsigned int   offset,
807                             unsigned int   user_vaddr,
808                             unsigned int   length )
809{
810    unsigned int        ko;                             // unsuccessfull V2P translation
811    unsigned int        flags;                  // protection flags
812    unsigned int        ppn;                    // physical page number
813    unsigned int    user_pbase;         // user buffer pbase address
814    unsigned int    fb_pbase;           // frame buffer pbase address
815
816    // get DMA channel and compute DMA vbase address
817    unsigned int        dma_id     = _get_current_context_slot(CTX_FBDMA_ID);
818    unsigned int    cluster_id = dma_id / NB_DMAS_MAX;
819    unsigned int    loc_id     = dma_id % NB_DMAS_MAX;
820    unsigned int*       dma_base   = (unsigned int*)&seg_dma_base +
821                                 (cluster_id * CLUSTER_SPAN) + 
822                                 (loc_id * DMA_SPAN);
823
824    // check user buffer address and length alignment
825    if ( (user_vaddr & 0x3) || (length & 0x3) )
826    {
827        _puts("[GIET ERROR] in _fbdma_access() : user buffer not word aligned\n");
828        return 1;
829    }
830
831    // get user space page table virtual address
832    unsigned int        user_ptab = _get_current_context_slot(CTX_PTAB_ID);
833
834    // compute frame buffer pbase address
835    unsigned int fb_vaddr = (unsigned int)&seg_fb_base + offset;
836
837    ko = _v2p_translate( (page_table_t*)user_ptab,
838                         (fb_vaddr >> 12),
839                         &ppn,
840                         &flags );
841    fb_pbase = (ppn << 12) | (fb_vaddr & 0x00000FFF);
842
843    if ( ko )
844    {
845        _puts("[GIET ERROR] in _fbdma_access() : frame buffer unmapped\n");
846        return 2;
847    }
848
849    // Compute user buffer pbase address
850    ko = _v2p_translate( (page_table_t*)user_ptab,
851                         (user_vaddr >> 12),
852                         &ppn,
853                         &flags );
854    user_pbase = (ppn << 12) | (user_vaddr & 0x00000FFF);
855
856    if ( ko )
857    {
858        _puts("[GIET ERROR] in _fbdma_access() : user buffer unmapped\n");
859        return 3;
860    } 
861    if ( (flags & PTE_U) == 0 )
862    {
863        _puts("[GIET ERROR] in _fbdma_access() : user buffer not in user space\n");
864        return 4; 
865    }
866    if ( ( (flags & PTE_W) == 0 ) && to_user ) 
867    {
868        _puts("[GIET ERROR] in _fbdma_access() : user buffer not writable\n");
869        return 5;
870    }
871
872
873
874/*
875    // loop on all virtual pages covering the user buffer
876    unsigned int user_vpn_min = user_vaddr >> 12;
877    unsigned int user_vpn_max = (user_vaddr + length - 1) >> 12;
878    unsigned int ix2          = 0;
879    unsigned int ix1          = _dma_iommu_ix1 + dma_id;
880
881    for ( vpn = user_vpn_min ; vpn <= user_vpn_max ; vpn++ )
882    {
883        // get ppn and flags for each vpn
884        unsigned int ko = _v2p_translate( (page_table_t*)user_pt_vbase,
885                                          vpn,
886                                          &ppn,
887                                          &flags );
888
889        // check access rights
890        if ( ko )                                 return 3;     // unmapped
891        if ( (flags & PTE_U) == 0 )               return 4;     // not in user space
892        if ( ( (flags & PTE_W) == 0 ) && to_user ) return 5;     // not writable
893
894        // save first ppn value
895        if ( ix2 == 0 ) ppn_first = ppn;
896
897        if ( GIET_IOMMU_ACTIVE )    // the user buffer must be remapped in the I/0 space
898        {
899            // check buffer length < 2 Mbytes
900            if ( ix2 > 511 ) return 2;
901
902            // map the physical page in IOMMU page table
903            _iommu_add_pte2( ix1,               // PT1 index
904                             ix2,               // PT2 index
905                             ppn,               // physical page number
906                             flags );   // protection flags
907        }
908        else            // no IOMMU : check that physical pages are contiguous
909        {
910            if ( (ppn - ppn_first) != ix2 )       return 6;     // split physical buffer 
911        }
912
913        // increment page index
914        ix2++;
915    } // end for vpn
916
917    // register the number of pages to be unmapped if iommu activated
918    _dma_iommu_npages[dma_id] = (user_vpn_max - user_vpn_min) + 1;
919
920*/
921    // invalidate data cache in case of memory write
922    if ( to_user ) _dcache_buf_invalidate( (void*)user_vaddr, length );
923
924    // get the lock
925    _get_lock( &_dma_lock[dma_id] );
926
927    // DMA configuration
928    if ( to_user )
929    {
930        dma_base[DMA_SRC] = (unsigned int)fb_pbase;
931        dma_base[DMA_DST] = (unsigned int)user_pbase;
932    }
933    else
934    {
935        dma_base[DMA_SRC] = (unsigned int)user_pbase;
936        dma_base[DMA_DST] = (unsigned int)fb_pbase;
937    }
938    dma_base[DMA_LEN] = (unsigned int)length;
939   
940    return 0;
941} 
942//////////////////////////////////////////////////////////////////////////////////
943// _fb_write()
944// Transfer data from a memory buffer to the frame_buffer device using  DMA.
945// - offset : offset (in bytes) in the frame buffer.
946// - buffer : base address of the memory buffer.
947// - length : number of bytes to be transfered.
948// Returns 0 if success, > 0 if error.
949//////////////////////////////////////////////////////////////////////////////////
950unsigned int _fb_write( unsigned int    offset, 
951                        const void*             buffer, 
952                        unsigned int    length )
953{
954    return _fb_dma_access( 0,                                           // write to frame buffer
955                           offset,
956                           (unsigned int)buffer,
957                           length );   
958}
959
960//////////////////////////////////////////////////////////////////////////////////
961// _fb_read()
962// Transfer data from the frame_buffer device to a memory buffer using  DMA.
963// - offset : offset (in bytes) in the frame buffer.
964// - buffer : base address of the memory buffer.
965// - length : number of bytes to be transfered.
966// Returns 0 if success, > 0 if error.
967//////////////////////////////////////////////////////////////////////////////////
968unsigned int _fb_read( unsigned int     offset, 
969                       const void*              buffer, 
970                       unsigned int     length )
971{
972    return _fb_dma_access( 1,                                           // read from frame buffer
973                           offset,
974                           (unsigned int)buffer,
975                           length );   
976}
977
978//////////////////////////////////////////////////////////////////////////////////
979// _fb_completed()
980// This function checks completion of a DMA transfer to or fom the frame buffer.
981// As it is a blocking call, the processor is busy waiting.
982// Returns 0 if success, > 0 if error
983// (1 == read error / 2 == DMA idle error / 3 == write error)
984//////////////////////////////////////////////////////////////////////////////////
985unsigned int _fb_completed()
986{
987    unsigned int dma_id = _get_current_context_slot(CTX_FBDMA_ID);
988
989    // busy waiting with a pseudo random delay between bus access
990    while (_dma_done[dma_id] == 0)
991    {
992            unsigned int i;
993        unsigned int delay = ( _proctime() ^ _procid()<<4 ) & 0xFF;
994        for (i = 0; i < delay; i++)
995            asm volatile("nop");
996    }
997   
998    // unmap the buffer from IOMMU page table if IOMMU is activated
999    if ( GIET_IOMMU_ACTIVE )
1000    {
1001        unsigned int* iob_address = (unsigned int*)&seg_iob_base;
1002        unsigned int  ix1         = _dma_iommu_ix1 + dma_id;
1003        unsigned int  ix2;
1004
1005        for ( ix2 = 0 ; ix2 < _dma_iommu_npages[dma_id] ; ix2++ )
1006        {
1007            // unmap the page in IOMMU page table
1008            _iommu_inval_pte2( ix1,             // PT1 index
1009                               ix2 );   // PT2 index
1010
1011            // clear IOMMU TLB
1012            iob_address[IOB_INVAL_PTE] = (ix1 << 21) | (ix2 << 12);
1013        }
1014    }
1015
1016    // reset synchronization variables
1017    _dma_lock[dma_id] = 0;
1018    _dma_done[dma_id] = 0;
1019
1020    return _dma_status[dma_id];
1021}
1022
Note: See TracBrowser for help on using the repository browser.