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

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

All drivers have been modified to use only the information
contained in the hard_config.h file

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