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

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

Introducing support for TSAR fixed format cluster index (cluster_xy)
We have now 4 parameters defined in map.xml:

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