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

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

Bug fix in both _tty_rx_isr() and _bdv_isr():
The ISR must do nothing it the status indicates that
there is no pending ISR.

File size: 14.7 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// 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{
[295]59    char* fbf_address = (char *)&seg_fbf_base + offset;
60
61    _memcpy( fbf_address, buffer, length);
62
[258]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{
[295]76    char* fbf_address = (char *)&seg_fbf_base + offset;
77
78    _memcpy( buffer, fbf_address, length);
79
[258]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
[263]100// array of FB_CMA channels descriptors (32 bytes per entry)
101// each entry contains one SRC and one DST chbuf descriptors.
[258]102in_unckdata volatile fb_cma_channel_t
103_fb_cma_channel[NB_CMA_CHANNELS] __attribute__((aligned(64)));
104
[263]105// array of physical addresses for the FB_CMA channels descriptors
[258]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,
[263]112// (that are both indexed by the channel index), and does four things:
[258]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),
[263]117//    the DST chbuf descriptor (one single buffer), and the buffer length.
[258]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
[263]143    paddr_t       desc_paddr;          // physical address of channel descriptor
[258]144
145    // get CMA channel index
146    channel_id = _get_context_slot(CTX_CMA_ID);
147    if ( channel_id >= NB_CMA_CHANNELS )
148    {
[295]149        _printf("\n[GIET ERROR] in _fb_cma_init() : CMA channel index too large\n");
[258]150        return 1;
151    }
152
153    // checking size for channel descriptor
154    if ( sizeof(fb_cma_channel_t) != 32 )
155    {
[295]156        _printf("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel size\n");
[258]157        return 1;
158    }
159
160    // checking channel descriptor alignment (32 bytes)
161    if ( (unsigned int)(&_fb_cma_channel[channel_id]) & 0x1F ) 
162    {
[295]163        _printf("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel alignment\n");
[258]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    {
[295]170        _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer not word aligned\n");
[258]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    {
[295]185        _printf("\n[GIET ERROR] in _fb_cma_init() : frame buffer unmapped\n");
[258]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    {
[295]198        _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer 0 unmapped\n");
[258]199        return 1;
200    } 
201    if ((flags & PTE_U) == 0) 
202    {
[295]203        _printf("[GIET ERROR] in _fb_cma_init() : user buffer 0 not in user space\n");
[258]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    {
[295]216        _printf("\n[GIET ERROR] in _fb_cma_init() : user buffer 1 unmapped\n");
[258]217        return 1;
218    } 
219    if ((flags & PTE_U) == 0) 
220    {
[295]221        _printf("[GIET ERROR] in _fb_cma_init() : user buffer 1 not in user space\n");
[258]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    {
[295]237        _printf("\n[GIET ERROR] in _fb_cma_init() : channel descriptor unmapped\n");
[258]238        return 1;
239    } 
[263]240    _fb_cma_desc_paddr[channel_id] = (((paddr_t)ppn) << 12) | (vaddr & 0x00000FFF);
[258]241
[263]242    desc_paddr                     = (((paddr_t)ppn) << 12) | (vaddr & 0x00000FFF);
243   
244
245#if GIET_DEBUG_FBF_DRIVER
[295]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] );
[258]255#endif
256
[275]257    if ( USE_IOB )
258    {
259        // SYNC request for channel descriptor
[297]260        _mmc_sync( desc_paddr, 32 );
[275]261    }
[258]262
263    // CMA channel activation
[295]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 );
[258]273    return 0;
274
275#else
[295]276    _printf("\n[GIET ERROR] in _fb_cma_init() : no CMA channel allocated\n");
[258]277    return 1;
278#endif
279}
[295]280
[263]281////////////////////////////////////////////////////////////////////////////////////
[258]282// _fb_cma_write()
283//
[263]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)
[258]297// Returns 0 if success, > 0 if error
[263]298////////////////////////////////////////////////////////////////////////////////////
[258]299unsigned int _fb_cma_write( unsigned int buffer_id )
300{
301#if NB_CMA_CHANNELS > 0
302
[263]303    volatile paddr_t buf_paddr;
304    unsigned int     full = 1;
[258]305
[263]306    unsigned int     count = 0;
307
[258]308    // get CMA channel index
309    unsigned int channel_id = _get_context_slot(CTX_CMA_ID);
310
[263]311#if GIET_DEBUG_FBF_DRIVER
[295]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() );
[263]314#endif
[258]315
[263]316    // waiting buffer empty
317    while ( full )
318    { 
319        if ( USE_IOB )
320        {
321            // INVAL L2 cache for the channel descriptor,
[297]322            _mmc_inval( _fb_cma_desc_paddr[channel_id], 32 );
[263]323
324            // INVAL L1 cache for the channel descriptor,
[295]325            _dcache_buf_invalidate( (void*)&_fb_cma_channel[channel_id], 32 );
[263]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
[297]341        _mmc_sync( buf_paddr, _fb_cma_channel[channel_id].length );
[263]342    }
343
[258]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
[263]354    if ( USE_IOB )
355    {
356        // SYNC request for the channel descriptor, because
357        // it will be read in XRAM by the CMA component
[297]358        _mmc_sync( _fb_cma_desc_paddr[channel_id], 32 );
[263]359    }
[258]360
361    return 0;
362
363#else
364
[295]365    _printf("\n[GIET ERROR] in _fb_cma_channel() : no CMA channel allocated\n");
[258]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
[295]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
[258]387    // CMA channel desactivation
[295]388    _cma_set_register( channel_id, CHBUF_RUN, 0 );
389
[258]390    return 0;
391
392#else
393
[295]394    _printf("\n[GIET ERROR] in _fb_cma_stop() : no CMA channel allocated\n");
[258]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.