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

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

This is a major release, including a deep restructuration of code.
The main evolutions are

  • use of the Tsar preloader to load the GIET boot-loader from disk
  • introduction of a FAT32 file system library,
  • use of this fat32 library by the boot-loader to load the map.bin data structure, and the various .elf files
  • reorganisation of drivers (one file per peripheral).
  • introduction of drivers for new peripherals: vci_chbuf_dma and vci_multi_ahci.
  • introduction of a new physical memory allocator in the boot code.

This release has been tested on the tsar_generic_iob architecture,
for the two following mappings: 4c_1p_iob_four.xml and 4c_1p_iob_sort.xml

File size: 14.1 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// 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
98in_unckdata volatile fb_cma_channel_t
99_fb_cma_channel[NB_CMA_CHANNELS] __attribute__((aligned(64)));
100
101in_unckdata volatile paddr_t         
102_fb_cma_desc_paddr[NB_CMA_CHANNELS];
103
104//////////////////////////////////////////////////////////////////////////////////////
105// _fb_cma_init()
106// This function uses the _fb_cma_channel[] and _fb_cma_desc_paddr[] arrays,
107// that are both indexed by the channel index.
108// where each entry contains one fb_cma_channel structure (defining two
109// SRC and DST chbuf descriptors), and does four things:
110//
111// 1) computes the physical addresses for the two source user buffers, for
112//    the destination frame buffer. It initialises the channel descriptor
113//    _fb_cma_channel[i], containing the SRC chbuf descriptor (two buffers),
114//    the DST chbuf descriptor (one single frame buffer), and the buffer length.
115//
116// 2) computes the physical address for the channel descriptor and register it
117//    in the _fb_cma_desc_paddr[i].
118//   
119// 3) makes a SYNC request to L2 cache for channel descriptor, because the
120//    channel descriptor is directly accessed in XRAM by the CMA component.
121//
122// 4) Starts the CMA hardware channel, that will poll the channel descriptor
123//    to fransfer an user buffer to the frame buffer as soon as the source
124//    user buffer is marked valid.
125//
126// Returns 0 if success, > 0 if error
127//////////////////////////////////////////////////////////////////////////////////////
128unsigned int _fb_cma_init( const void*  vbase0,  // first user buffer vbase address
129                           const void*  vbase1,  // second user buffer vbase address
130                           unsigned int length ) // buffer length (number of bytes)
131{
132#if NB_CMA_CHANNELS > 0
133
134    unsigned int  channel_id;          // CMA channel index
135    unsigned int  user_ptab;           // page table virtual address
136    unsigned int  ko;                  // unsuccessfull V2P translation
137    unsigned int  vaddr;               // virtual address
138    unsigned int  flags;               // protection flags
139    unsigned int  ppn;                 // physical page number
140    paddr_t       channel_pbase;       // physical address of channel descriptor
141
142    // get CMA channel index
143    channel_id = _get_context_slot(CTX_CMA_ID);
144    if ( channel_id >= NB_CMA_CHANNELS )
145    {
146        _tty_get_lock( 0 );
147        _puts("\n[GIET ERROR] in _fb_cma_init() : CMA channel index too large\n");
148        _tty_release_lock( 0 );
149        return 1;
150    }
151
152    // checking size for channel descriptor
153    if ( sizeof(fb_cma_channel_t) != 32 )
154    {
155        _tty_get_lock( 0 );
156        _puts("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel size\n");
157        _tty_release_lock( 0 );
158        return 1;
159    }
160
161    // checking channel descriptor alignment (32 bytes)
162    if ( (unsigned int)(&_fb_cma_channel[channel_id]) & 0x1F ) 
163    {
164        _tty_get_lock( 0 );
165        _puts("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel alignment\n");
166        _tty_release_lock( 0 );
167        return 1;
168    }
169
170    // checking user buffer virtual addresses and length alignment
171    if ( ((unsigned int)vbase0 & 0x3) || ((unsigned int)vbase1 & 0x3) || (length & 0x3) ) 
172    {
173        _tty_get_lock( 0 );
174        _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer not word aligned\n");
175        _tty_release_lock( 0 );
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
183    vaddr = ((unsigned int)&seg_fbf_base);
184    ko    = _v2p_translate( (page_table_t*) user_ptab, 
185                         (vaddr >> 12),
186                         &ppn, 
187                         &flags );
188    if (ko) 
189    {
190        _tty_get_lock( 0 );
191        _puts("\n[GIET ERROR] in _fb_cma_init() : frame buffer unmapped\n");
192        _tty_release_lock( 0 );
193        return 1;
194    }
195    _fb_cma_channel[channel_id].fbf = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
196
197    // Compute and register first user buffer physical address
198    vaddr = (unsigned int)vbase0; 
199    ko = _v2p_translate( (page_table_t*) user_ptab, 
200                         (vaddr >> 12),
201                         &ppn, 
202                         &flags );
203    if (ko) 
204    {
205        _tty_get_lock( 0 );
206        _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer 0 unmapped\n");
207        _tty_release_lock( 0 );
208        return 1;
209    } 
210    if ((flags & PTE_U) == 0) 
211    {
212        _tty_get_lock( 0 );
213        _puts("[GIET ERROR] in _fb_cma_init() : user buffer 0 not in user space\n");
214        _tty_release_lock( 0 );
215        return 1; 
216    }
217    _fb_cma_channel[channel_id].buf0 = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
218
219    // Compute and register second user buffer physical address
220    vaddr = (unsigned int)vbase1; 
221    ko = _v2p_translate( (page_table_t*) user_ptab, 
222                         (vaddr >> 12),
223                         &ppn, 
224                         &flags );
225    if (ko) 
226    {
227        _tty_get_lock( 0 );
228        _puts("\n[GIET ERROR] in _fb_cma_init() : user buffer 1 unmapped\n");
229        _tty_release_lock( 0 );
230        return 1;
231    } 
232    if ((flags & PTE_U) == 0) 
233    {
234        _tty_get_lock( 0 );
235        _puts("[GIET ERROR] in _fb_cma_init() : user buffer 1 not in user space\n");
236        _tty_release_lock( 0 );
237        return 1; 
238    }
239    _fb_cma_channel[channel_id].buf1 = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
240
241    // register buffer length in channel descriptor
242    _fb_cma_channel[channel_id].length = length;
243
244    // Compute and register physical adress of the channel descriptor
245    vaddr = (unsigned int)(&_fb_cma_channel[channel_id]);
246    ko = _v2p_translate( (page_table_t*) user_ptab, 
247                         (vaddr >> 12),
248                         &ppn, 
249                         &flags );
250    if (ko) 
251    {
252        _tty_get_lock( 0 );
253        _puts("\n[GIET ERROR] in _fb_cma_init() : channel descriptor unmapped\n");
254        _tty_release_lock( 0 );
255        return 1;
256    } 
257    channel_pbase = (((paddr_t)ppn) << 12) | (vaddr & 0x00000FFF);
258    _fb_cma_desc_paddr[channel_id] = channel_pbase;
259
260#if GIET_DEBUG_CMA_DRIVER
261_puts("\n");
262_puts("- fbf       pbase = ");
263_putl( _fb_cma_channel[channel_id].fbf );
264_puts("\n");
265_puts("- buf0      pbase = ");
266_putl( _fb_cma_channel[channel_id].buf0 );
267_puts("\n");
268_puts("- buf1      pbase = ");
269_putl( _fb_cma_channel[channel_id].buf1 );
270_puts("\n");
271_puts("- channel   pbase = ");
272_putl( channel_pbase );
273_puts("\n");
274#endif
275
276    // SYNC request for channel descriptor
277    _memc_sync( channel_pbase, 32 );
278
279    // CMA channel activation
280    unsigned int* cma_vbase = (unsigned int *)&seg_cma_base;
281    unsigned int  offset     = channel_id * CHBUF_CHANNEL_SPAN;
282
283    cma_vbase[offset + CHBUF_SRC_DESC]  = (unsigned int)(channel_pbase & 0xFFFFFFFF);
284    cma_vbase[offset + CHBUF_SRC_EXT]   = (unsigned int)(channel_pbase >> 32);
285    cma_vbase[offset + CHBUF_SRC_NBUFS] = 2;
286    cma_vbase[offset + CHBUF_DST_DESC]  = (unsigned int)(channel_pbase & 0xFFFFFFFF) + 16;
287    cma_vbase[offset + CHBUF_DST_EXT]   = (unsigned int)(channel_pbase >> 32);
288    cma_vbase[offset + CHBUF_DST_NBUFS] = 1;
289    cma_vbase[offset + CHBUF_BUF_SIZE]  = length;
290    cma_vbase[offset + CHBUF_PERIOD]    = 300;
291    cma_vbase[offset + CHBUF_RUN]       = 1;
292
293    return 0;
294
295#else
296
297    _tty_get_lock( 0 );
298    _puts("\n[GIET ERROR] in _fb_cma_init() : no CMA channel allocated\n");
299    _tty_release_lock( 0 );
300
301    return 1;
302#endif
303}
304//////////////////////////////////////////////////////////////////////////////////
305// _fb_cma_write()
306// This function makes a SYNC request for the source user buffer.
307// Then it updates the status of the SRC and DST chbuf descriptors, to allow
308// the CMA component to transfer the source user buffer buffer to the destination
309// frame buffer, and makes a SYNC request for the channel descriptor.
310//
311// - buffer_id : user buffer index (0 => buf0 / not 0 => buf1)
312// Returns 0 if success, > 0 if error
313//////////////////////////////////////////////////////////////////////////////////
314unsigned int _fb_cma_write( unsigned int buffer_id )
315{
316#if NB_CMA_CHANNELS > 0
317
318    paddr_t         buf_paddr;
319    unsigned int    buf_length;
320
321    // get CMA channel index
322    unsigned int channel_id = _get_context_slot(CTX_CMA_ID);
323
324    // SYNC request for the source user buffer
325    if ( buffer_id == 0 )  buf_paddr = _fb_cma_channel[channel_id].buf0;
326    else                   buf_paddr = _fb_cma_channel[channel_id].buf1;
327    buf_length = _fb_cma_channel[channel_id].length;
328    _memc_sync( buf_paddr, buf_length );
329
330    // set SRC full
331    if ( buffer_id == 0 )
332    _fb_cma_channel[channel_id].buf0 = buf_paddr | 0x8000000000000000ULL;
333    else
334    _fb_cma_channel[channel_id].buf1 = buf_paddr | 0x8000000000000000ULL;
335
336    // set DST empty
337    _fb_cma_channel[channel_id].fbf  = _fb_cma_channel[channel_id].fbf
338                                       & 0x7FFFFFFFFFFFFFFFULL;
339
340    // SYNC request for the channel descriptor
341    buf_paddr  = _fb_cma_desc_paddr[channel_id];
342    buf_length = 32;
343    _memc_sync( buf_paddr, buf_length );
344
345    return 0;
346
347#else
348
349    _tty_get_lock( 0 );
350    _puts("\n[GIET ERROR] in _fb_cma_channel() : no CMA channel allocated\n");
351    _tty_release_lock( 0 );
352    return 1;
353
354#endif
355}
356//////////////////////////////////////////////////////////////////////////////////
357// _fb_cma_stop()
358// This function desactivates the CMA channel allocated to the calling task.
359// Returns 0 if success, > 0 if error
360//////////////////////////////////////////////////////////////////////////////////
361unsigned int _fb_cma_stop( unsigned int buffer_id )
362{
363#if NB_CMA_CHANNELS > 0
364
365    // get CMA channel allocated
366    unsigned int channel_id = _get_context_slot(CTX_CMA_ID);
367
368    // CMA channel desactivation
369    unsigned int* cma_vbase = (unsigned int *)&seg_cma_base;
370    unsigned int  offset     = channel_id * CHBUF_CHANNEL_SPAN;
371    cma_vbase[offset + CHBUF_RUN] = 0;
372    return 0;
373
374#else
375
376    _tty_get_lock( 0 );
377    _puts("\n[GIET ERROR] in _fb_cma_stop() : no CMA channel allocated\n");
378    _tty_release_lock( 0 );
379    return 1;
380
381#endif
382}
383   
384
385// Local Variables:
386// tab-width: 4
387// c-basic-offset: 4
388// c-file-offsets:((innamespace . 0)(inline-open . 0))
389// indent-tabs-mode: nil
390// End:
391// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
392
Note: See TracBrowser for help on using the repository browser.