source: soft/giet_vm/giet_drivers/fbf_driver.c @ 295

Last change on this file since 295 was 295, checked in by alain, 11 years ago

Introducing a major release, to suppoort the tsar_generic_leti platform
and the various (external or internal) peripherals configurations.
The map.xml format has been modified, in order to support the new
vci_iopic componentand a new policy for peripherals initialisation.
The IRQs are nom described in the XICU and IOPIC components
(and not anymore in the processors).
To enforce this major change, the map.xml file signature changed:
The signature value must be: 0xDACE2014

This new release has been tested on the tsar_generic_leti platform
for the following mappings:

  • 4c_4p_sort_leti
  • 4c_4p_sort_leti_ext
  • 4c_4p_transpose_leti
  • 4c_4p_transpose_leti_ext
  • 4c_1p_four_leti_ext
File size: 14.8 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : fbf_driver.c
3// Date     : 23/05/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The fbf_driver.c and fbf_driver.h files are part ot the GIET-VM kernel.
8// This driver supports the SoCLib vci_framebuffer component.
9//
10// There exist two methods to access the VciFrameBuffer device:
11// 
12// 1) The _fb_sync_write() and _fb_sync_read() functions use a memcpy strategy
13// to implement the transfer between a data buffer (user space) and the frame
14// buffer (kernel space). They are blocking until completion of the transfer.
15//
16// 2) The _fb_cma_init(), _fb_cma_write() and _fb_cma_stop() functions use
17// the VciChbufDma component (non replicated) to transfer a flow of images from
18// an user space chained buffer (two buffers) to the frame buffer.
19// A CMA channel must be allocated to the task requesting it in the mapping_info,
20// and stored in the task context.
21///////////////////////////////////////////////////////////////////////////////////
22// The seg_fbf_base virtual address must be defined in giet_vsegs.ld file.
23///////////////////////////////////////////////////////////////////////////////////
24
25#include <giet_config.h>
26#include <fbf_driver.h>
27#include <utils.h>
28#include <dma_driver.h>
29#include <cma_driver.h>
30#include <tty_driver.h>
31#include <ctx_handler.h>
32#include <mmc_driver.h>
33#include <vmem.h>
34
35#if !defined(GIET_USE_IOMMU)
36# error: You must define GIET_USE_IOMMU in the giet_config.h file
37#endif
38
39#if !defined( USE_IOB )
40# error: You must define USE_IOB in the hard_config.h file
41#endif
42
43#define in_unckdata __attribute__((section (".unckdata")))
44
45////////////// memcpy approach //////////////////////////////////////////////////
46
47//////////////////////////////////////////////////////////////////////////////////
48// _fb_sync_write()
49// Transfer data from an memory buffer to the frame_buffer device using a memcpy.
50// - offset : offset (in bytes) in the frame buffer.
51// - buffer : base address of the memory buffer.
52// - length : number of bytes to be transfered.
53//////////////////////////////////////////////////////////////////////////////////
54
55unsigned int _fb_sync_write(unsigned int offset, 
56                            const void * buffer, 
57                            unsigned int length) 
58{
59    char* fbf_address = (char *)&seg_fbf_base + offset;
60
61    _memcpy( fbf_address, buffer, length);
62
63    return 0;
64}
65//////////////////////////////////////////////////////////////////////////////////
66// _fb_sync_read()
67// Transfer data from the frame_buffer device to a memory buffer using a memcpy.
68// - offset : offset (in bytes) in the frame buffer.
69// - buffer : base address of the memory buffer.
70// - length : number of bytes to be transfered.
71//////////////////////////////////////////////////////////////////////////////////
72unsigned int _fb_sync_read( unsigned int   offset, 
73                            void*          buffer, 
74                            unsigned int   length) 
75{
76    char* fbf_address = (char *)&seg_fbf_base + offset;
77
78    _memcpy( buffer, fbf_address, length);
79
80    return 0;
81}
82
83
84///////////////// CDMA approach //////////////////////////////////////////////////
85
86// This structure contains two chbuf descriptors that can be used by
87// the VciChbufDma component to tranfer a flow of images:
88// - The SRC chbuf descriptor contain two slots (two user buffers)
89// - The DST chbuf descriptor contains only one slot (frame buffer)
90
91typedef struct fb_cma_channel_s
92{
93    paddr_t       buf0;     // physical address + status for user buffer 0
94    paddr_t       buf1;     // physical address + status for user buffer 1
95    paddr_t       fbf;      // physical address + status for frame buffer
96    unsigned int  length;   // buffer length (number of bytes)
97    unsigned int  padding;  // unused (just to have channel size = 32 bytes)
98} fb_cma_channel_t;
99
100// array of FB_CMA channels descriptors (32 bytes per entry)
101// each entry contains one SRC and one DST chbuf descriptors.
102in_unckdata volatile fb_cma_channel_t
103_fb_cma_channel[NB_CMA_CHANNELS] __attribute__((aligned(64)));
104
105// array of physical addresses for the FB_CMA channels descriptors
106in_unckdata volatile paddr_t         
107_fb_cma_desc_paddr[NB_CMA_CHANNELS];
108
109//////////////////////////////////////////////////////////////////////////////////////
110// _fb_cma_init()
111// This function uses the _fb_cma_channel[] and _fb_cma_desc_paddr[] arrays,
112// (that are both indexed by the channel index), and does four things:
113//
114// 1) computes the physical addresses for the two source user buffers, for
115//    the destination frame buffer. It initialises the channel descriptor
116//    _fb_cma_channel[i], containing the SRC chbuf descriptor (two buffers),
117//    the DST chbuf descriptor (one single buffer), and the buffer length.
118//
119// 2) computes the physical address for the channel descriptor and register it
120//    in the _fb_cma_desc_paddr[i].
121//   
122// 3) makes a SYNC request to L2 cache for channel descriptor, because the
123//    channel descriptor is directly accessed in XRAM by the CMA component.
124//
125// 4) Starts the CMA hardware channel, that will poll the channel descriptor
126//    to fransfer an user buffer to the frame buffer as soon as the source
127//    user buffer is marked valid.
128//
129// Returns 0 if success, > 0 if error
130//////////////////////////////////////////////////////////////////////////////////////
131unsigned int _fb_cma_init( const void*  vbase0,  // first user buffer vbase address
132                           const void*  vbase1,  // second user buffer vbase address
133                           unsigned int length ) // buffer length (number of bytes)
134{
135#if NB_CMA_CHANNELS > 0
136
137    unsigned int  channel_id;          // CMA channel index
138    unsigned int  user_ptab;           // page table virtual address
139    unsigned int  ko;                  // unsuccessfull V2P translation
140    unsigned int  vaddr;               // virtual address
141    unsigned int  flags;               // protection flags
142    unsigned int  ppn;                 // physical page number
143    paddr_t       desc_paddr;          // physical address of channel descriptor
144
145    // get CMA channel index
146    channel_id = _get_context_slot(CTX_CMA_ID);
147    if ( channel_id >= NB_CMA_CHANNELS )
148    {
149        _printf("\n[GIET ERROR] in _fb_cma_init() : CMA channel index too large\n");
150        return 1;
151    }
152
153    // checking size for channel descriptor
154    if ( sizeof(fb_cma_channel_t) != 32 )
155    {
156        _printf("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel size\n");
157        return 1;
158    }
159
160    // checking channel descriptor alignment (32 bytes)
161    if ( (unsigned int)(&_fb_cma_channel[channel_id]) & 0x1F ) 
162    {
163        _printf("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel alignment\n");
164        return 1;
165    }
166
167    // checking user buffer virtual addresses and length alignment
168    if ( ((unsigned int)vbase0 & 0x3) || ((unsigned int)vbase1 & 0x3) || (length & 0x3) ) 
169    {
170        _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer not word aligned\n");
171        return 1;
172    }
173
174    // get page table virtual address
175    user_ptab = _get_context_slot(CTX_PTAB_ID);
176
177    // compute and register frame buffer physical address
178    vaddr = ((unsigned int)&seg_fbf_base);
179    ko    = _v2p_translate( (page_table_t*) user_ptab, 
180                         (vaddr >> 12),
181                         &ppn, 
182                         &flags );
183    if (ko) 
184    {
185        _printf("\n[GIET ERROR] in _fb_cma_init() : frame buffer unmapped\n");
186        return 1;
187    }
188    _fb_cma_channel[channel_id].fbf = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
189
190    // Compute and register first user buffer physical address
191    vaddr = (unsigned int)vbase0; 
192    ko = _v2p_translate( (page_table_t*) user_ptab, 
193                         (vaddr >> 12),
194                         &ppn, 
195                         &flags );
196    if (ko) 
197    {
198        _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer 0 unmapped\n");
199        return 1;
200    } 
201    if ((flags & PTE_U) == 0) 
202    {
203        _printf("[GIET ERROR] in _fb_cma_init() : user buffer 0 not in user space\n");
204        return 1; 
205    }
206    _fb_cma_channel[channel_id].buf0 = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
207
208    // Compute and register second user buffer physical address
209    vaddr = (unsigned int)vbase1; 
210    ko = _v2p_translate( (page_table_t*) user_ptab, 
211                         (vaddr >> 12),
212                         &ppn, 
213                         &flags );
214    if (ko) 
215    {
216        _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer 1 unmapped\n");
217        return 1;
218    } 
219    if ((flags & PTE_U) == 0) 
220    {
221        _printf("[GIET ERROR] in _fb_cma_init() : user buffer 1 not in user space\n");
222        return 1; 
223    }
224    _fb_cma_channel[channel_id].buf1 = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
225
226    // register buffer length in channel descriptor
227    _fb_cma_channel[channel_id].length = length;
228
229    // Compute and register physical adress of the channel descriptor
230    vaddr = (unsigned int)(&_fb_cma_channel[channel_id]);
231    ko = _v2p_translate( (page_table_t*) user_ptab, 
232                         (vaddr >> 12),
233                         &ppn, 
234                         &flags );
235    if (ko) 
236    {
237        _printf("\n[GIET ERROR] in _fb_cma_init() : channel descriptor unmapped\n");
238        return 1;
239    } 
240    _fb_cma_desc_paddr[channel_id] = (((paddr_t)ppn) << 12) | (vaddr & 0x00000FFF);
241
242    desc_paddr                     = (((paddr_t)ppn) << 12) | (vaddr & 0x00000FFF);
243   
244
245#if GIET_DEBUG_FBF_DRIVER
246_printf("\n[CMA DEBUG] enters _fb_cma_init()\n"
247        " - fbf       pbase = %l\n"
248        " - buf0      pbase = %l\n"
249        " - buf1      pbase = %l\n"
250        " - channel   pbase = %l\n"
251        _fb_cma_channel[channel_id].fbf,
252        _fb_cma_channel[channel_id].buf0,
253        _fb_cma_channel[channel_id].buf1,
254        _fb_cma_desc_paddr[channel_id] );
255#endif
256
257    if ( USE_IOB )
258    {
259        // SYNC request for channel descriptor
260        _memc_sync( desc_paddr, 32 );
261    }
262
263    // CMA channel activation
264    _cma_set_register( channel_id, CHBUF_SRC_DESC , (unsigned int)(desc_paddr & 0xFFFFFFFF) );
265    _cma_set_register( channel_id, CHBUF_SRC_EXT  , (unsigned int)(desc_paddr >> 32) );
266    _cma_set_register( channel_id, CHBUF_SRC_NBUFS, 2 );
267    _cma_set_register( channel_id, CHBUF_DST_DESC , (unsigned int)(desc_paddr & 0xFFFFFFFF) + 16 );
268    _cma_set_register( channel_id, CHBUF_DST_EXT  , (unsigned int)(desc_paddr >> 32) );
269    _cma_set_register( channel_id, CHBUF_DST_NBUFS, 1 );
270    _cma_set_register( channel_id, CHBUF_BUF_SIZE , length );
271    _cma_set_register( channel_id, CHBUF_PERIOD   , 300 );
272    _cma_set_register( channel_id, CHBUF_RUN      , 1 );
273    return 0;
274
275#else
276    _printf("\n[GIET ERROR] in _fb_cma_init() : no CMA channel allocated\n");
277    return 1;
278#endif
279}
280
281////////////////////////////////////////////////////////////////////////////////////
282// _fb_cma_write()
283//
284// It updates the status of the SRC and DST chbuf descriptors, to allow the CMA
285// component to transfer the source user buffer to the frame buffer.
286//
287// If the IO Bridge component is used:
288// 1) it makes an INVAL request for the channel descriptor, before testing the
289//    source buffer status, because it is modified in XRAM by the CMA component.
290// 2) it makes a SYNC request for the source user buffer before activating the CMA
291//    transfer, because the data will be read from XRAM by the CMA component.
292// 3) it makes a SYNC request for the channel descriptor after modification
293//    of the SRC and DST status, because these descriptors will be read from XRAM
294//    by the CMA component.
295//
296// The buffer_id argument is the user buffer index (0 => buf0 / not 0 => buf1)
297// Returns 0 if success, > 0 if error
298////////////////////////////////////////////////////////////////////////////////////
299unsigned int _fb_cma_write( unsigned int buffer_id )
300{
301#if NB_CMA_CHANNELS > 0
302
303    volatile paddr_t buf_paddr;
304    unsigned int     full = 1;
305
306    unsigned int     count = 0;
307
308    // get CMA channel index
309    unsigned int channel_id = _get_context_slot(CTX_CMA_ID);
310
311#if GIET_DEBUG_FBF_DRIVER
312_printf("\n[CMA DEBUG] _fb_cma_write() for CMA channel %d / bufid = %d at cycle %d\n",
313        channel_id, buffer_id, _get_proctime() );
314#endif
315
316    // waiting buffer empty
317    while ( full )
318    { 
319        if ( USE_IOB )
320        {
321            // INVAL L2 cache for the channel descriptor,
322            _memc_inval( _fb_cma_desc_paddr[channel_id], 32 );
323
324            // INVAL L1 cache for the channel descriptor,
325            _dcache_buf_invalidate( (void*)&_fb_cma_channel[channel_id], 32 );
326        }
327
328        // read SRC buffer descriptor
329        if ( buffer_id == 0 ) buf_paddr = _fb_cma_channel[channel_id].buf0;
330        else                  buf_paddr = _fb_cma_channel[channel_id].buf1;
331        full = ( (unsigned int)(buf_paddr>>63) );
332
333        count++;
334        if ( count == 10 ) _exit();
335    }
336
337    if ( USE_IOB )
338    {
339        // SYNC request for the user buffer because
340        // this buffer will be read from XRAM by the CMA component
341        _memc_sync( buf_paddr, _fb_cma_channel[channel_id].length );
342    }
343
344    // set SRC full
345    if ( buffer_id == 0 )
346    _fb_cma_channel[channel_id].buf0 = buf_paddr | 0x8000000000000000ULL;
347    else
348    _fb_cma_channel[channel_id].buf1 = buf_paddr | 0x8000000000000000ULL;
349
350    // set DST empty
351    _fb_cma_channel[channel_id].fbf  = _fb_cma_channel[channel_id].fbf
352                                       & 0x7FFFFFFFFFFFFFFFULL;
353
354    if ( USE_IOB )
355    {
356        // SYNC request for the channel descriptor, because
357        // it will be read in XRAM by the CMA component
358        _memc_sync( _fb_cma_desc_paddr[channel_id], 32 );
359    }
360
361    return 0;
362
363#else
364
365    _printf("\n[GIET ERROR] in _fb_cma_channel() : no CMA channel allocated\n");
366    return 1;
367
368#endif
369}
370//////////////////////////////////////////////////////////////////////////////////
371// _fb_cma_stop()
372// This function desactivates the CMA channel allocated to the calling task.
373// Returns 0 if success, > 0 if error
374//////////////////////////////////////////////////////////////////////////////////
375unsigned int _fb_cma_stop( unsigned int buffer_id )
376{
377#if NB_CMA_CHANNELS > 0
378
379    // get CMA channel allocated
380    unsigned int channel_id = _get_context_slot(CTX_CMA_ID);
381
382#if GIET_DEBUG_FBF_DRIVER
383_printf("\n[CMA DEBUG] _fb_cma_stop() for CMA channel %d at cycle %d\n",
384        channel_id, _get_proctime() );
385#endif
386
387    // CMA channel desactivation
388    _cma_set_register( channel_id, CHBUF_RUN, 0 );
389
390    return 0;
391
392#else
393
394    _printf("\n[GIET ERROR] in _fb_cma_stop() : no CMA channel allocated\n");
395    return 1;
396
397#endif
398}
399   
400
401// Local Variables:
402// tab-width: 4
403// c-basic-offset: 4
404// c-file-offsets:((innamespace . 0)(inline-open . 0))
405// indent-tabs-mode: nil
406// End:
407// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
408
Note: See TracBrowser for help on using the repository browser.