Ignore:
Timestamp:
Aug 27, 2013, 5:41:51 PM (11 years ago)
Author:
alain
Message:

Improving support for Chained Buffer DMA in drivers.c file.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/sys/drivers.c

    r253 r254  
    715715    _ioc_iommu_npages = (user_vpn_max - user_vpn_min) + 1;
    716716
    717     // invalidate local data cache in case of memory write
    718     if (to_mem) _dcache_buf_invalidate((void *) user_vaddr, length);
     717    // If no IOB, invalidate L1 cache in case of memory write
     718    if ( to_mem && (USE_IOB == 0) ) _dcache_buf_invalidate((void *) user_vaddr, length);
    719719
    720720#if GIET_DEBUG_IOC_DRIVER
     
    742742#endif
    743743
    744     // Invalidate L2 cache if IO Bridge is used
     744    // If IOB, invalidate L2 cache in case of memory write
    745745    if ( to_mem && USE_IOB ) _memc_inval( buf_paddr, length );
    746746   
     
    12671267// the VciChbufDma component (non replicated) to transfer a flow of images from
    12681268// an user space chained buffer (two buffers) to the frame buffer.
    1269 // A CMA channel is allocated to the task requesting it in the mapping_info,
     1269// A CMA channel must be allocated to the task requesting it in the mapping_info,
    12701270// and stored in the task context.
    12711271//////////////////////////////////////////////////////////////////////////////////
     
    13581358// - The SRC chbuf descriptor contain two slots (two user buffers)
    13591359// - The DST chbuf descriptor contains only one slot (frame buffer)
     1360
    13601361typedef struct fb_cma_channel_s
    13611362{
    1362     paddr_t buf0;   // physical address + status for user buffer 0
    1363     paddr_t buf1;   // physical address + status for user buffer 1
    1364     paddr_t fbf;    // physical address + status for frame buffer
     1363    paddr_t       buf0;     // physical address + status for user buffer 0
     1364    paddr_t       buf1;     // physical address + status for user buffer 1
     1365    paddr_t       fbf;      // physical address + status for frame buffer
     1366    unsigned int  length;   // buffer length (number of bytes)
     1367    unsigned int  padding;  // unused (just to hahe channel size = 32 bytes)
    13651368} fb_cma_channel_t;
    13661369
    1367 in_unckdata volatile fb_cma_channel_t _fb_cma_channel[NB_CMA_CHANNELS];
     1370in_unckdata volatile fb_cma_channel_t _fb_cma_channel[NB_CMA_CHANNELS] __attribute__((aligned(64)));
     1371in_unckdata volatile paddr_t          _fb_cma_desc_paddr[NB_CMA_CHANNELS];
    13681372
    13691373//////////////////////////////////////////////////////////////////////////////////
    13701374// _fb_cma_init()
    1371 // This function does two things:
    1372 // 1) Initialises the SRC chbuf descriptor (two buffers), and the DST
    1373 //    chbuf descriptor (one single frame buffer), after translating 
    1374 //    virtual addresses to physical addresses, and checking access rights.
    1375 // 2) Starts the CMA hardware channel, that will permanently try to display
    1376 //    images as soon as the SRC buffers are filled.
     1375// This function uses the _fb_cma_channel[] and _fb_cma_desc_paddr[] arrays,
     1376// that are both indexed by the channel index.
     1377// where each entry contains one fb_cma_channel structure (defining two
     1378// SRC and DST chbuf descriptors), and does four things:
     1379//
     1380// 1) computes the physical addresses for the two source user buffers, for
     1381//    the destination frame buffer. It initialises the channel descriptor
     1382//    _fb_cma_channel[i], containing the SRC chbuf descriptor (two buffers),
     1383//    the DST chbuf descriptor (one single frame buffer), and the buffer length.
     1384//
     1385// 2) computes the physical address for the channel descriptor and register it
     1386//    in the _fb_cma_desc_paddr[i].
     1387//   
     1388// 3) makes a SYNC request to L2 cache for channel descriptor, because the
     1389//    channel descriptor is directly accessed in XRAM by the CMA component.
     1390//
     1391// 4) Starts the CMA hardware channel, that will poll the channel descriptor
     1392//    to fransfer an user buffer to the frame buffer as soon as the source
     1393//    user buffer is marked valid.
     1394//
    13771395// Arguments are:
    13781396// - vbase0 : virtual base address of the first user buffer.
     
    13871405#if NB_CMA_CHANNELS > 0
    13881406
    1389     unsigned int  channel_id;       // CMA channel index
    1390     unsigned int  user_ptab;        // page table virtual address
    1391     unsigned int  ko;               // unsuccessfull V2P translation
    1392     unsigned int  vpn;              // virtual page number
    1393     unsigned int  flags;            // protection flags
    1394     unsigned int  ppn;              // physical page number
    1395     paddr_t       src_chbuf_pbase;  // physical address for SRC chbuf descriptor
    1396     paddr_t       dst_chbuf_pbase;  // physical address for SRC chbuf descriptor
     1407    unsigned int  channel_id;          // CMA channel index
     1408    unsigned int  user_ptab;           // page table virtual address
     1409    unsigned int  ko;                  // unsuccessfull V2P translation
     1410    unsigned int  vaddr;               // virtual address
     1411    unsigned int  flags;               // protection flags
     1412    unsigned int  ppn;                 // physical page number
     1413    paddr_t       channel_pbase;       // physical address of channel descriptor
    13971414
    13981415    // get CMA channel index
     
    14061423    }
    14071424
    1408     // check user buffer virtual addresses and length alignment
     1425    // checking size for channel descriptor
     1426    if ( sizeof(fb_cma_channel_t) != 32 )
     1427    {
     1428        _get_lock(&_tty_put_lock);
     1429        _puts("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel size\n");
     1430        _release_lock(&_tty_put_lock);
     1431        return 1;
     1432    }
     1433
     1434    // checking channel descriptor alignment (32 bytes)
     1435    if ( (unsigned int)(&_fb_cma_channel[channel_id]) & 0x1F )
     1436    {
     1437        _get_lock(&_tty_put_lock);
     1438        _puts("\n[GIET ERROR] in _fb_cma_init() : bad fb_cma_channel alignment\n");
     1439        _release_lock(&_tty_put_lock);
     1440        return 1;
     1441    }
     1442
     1443    // checking user buffer virtual addresses and length alignment
    14091444    if ( ((unsigned int)vbase0 & 0x3) || ((unsigned int)vbase1 & 0x3) || (length & 0x3) )
    14101445    {
     
    14181453    user_ptab = _get_context_slot(CTX_PTAB_ID);
    14191454
    1420     // get frame buffer virtual address
    1421 
    14221455    // compute and register frame buffer physical address
    1423     vpn = ((unsigned int)&seg_fbf_base) >> 12;
    1424     ko = _v2p_translate( (page_table_t*) user_ptab,
    1425                          vpn,
     1456    vaddr = ((unsigned int)&seg_fbf_base);
     1457    ko    = _v2p_translate( (page_table_t*) user_ptab,
     1458                         (vaddr >> 12),
    14261459                         &ppn,
    14271460                         &flags );
     
    14331466        return 1;
    14341467    }
    1435     _fb_cma_channel[channel_id].fbf = ((paddr_t)ppn << 12) | (vpn & 0x00000FFF);
     1468    _fb_cma_channel[channel_id].fbf = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
    14361469
    14371470    // Compute and register first user buffer physical address
    1438     vpn = (unsigned int)vbase0 >> 12;
     1471    vaddr = (unsigned int)vbase0;
    14391472    ko = _v2p_translate( (page_table_t*) user_ptab,
    1440                          vpn,
     1473                         (vaddr >> 12),
    14411474                         &ppn,
    14421475                         &flags );
     
    14551488        return 1;
    14561489    }
    1457     _fb_cma_channel[channel_id].buf0 = ((paddr_t)ppn << 12) | (vpn & 0x00000FFF);
     1490    _fb_cma_channel[channel_id].buf0 = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
    14581491
    14591492    // Compute and register second user buffer physical address
    1460     vpn = (unsigned int)vbase1 >> 12;
     1493    vaddr = (unsigned int)vbase1;
    14611494    ko = _v2p_translate( (page_table_t*) user_ptab,
    1462                          vpn,
     1495                         (vaddr >> 12),
    14631496                         &ppn,
    14641497                         &flags );
     
    14771510        return 1;
    14781511    }
    1479     _fb_cma_channel[channel_id].buf1 = ((paddr_t)ppn << 12) | (vpn & 0x00000FFF);
    1480 
    1481     // Compute physical adress of the SRC chbuf descriptor
    1482     vpn = ((unsigned int)(&_fb_cma_channel[channel_id].buf0)) >> 12;
     1512    _fb_cma_channel[channel_id].buf1 = ((paddr_t)ppn << 12) | (vaddr & 0x00000FFF);
     1513
     1514    // register buffer length in channel descriptor
     1515    _fb_cma_channel[channel_id].length = length;
     1516
     1517    // Compute and register physical adress of the channel descriptor
     1518    vaddr = (unsigned int)(&_fb_cma_channel[channel_id]);
    14831519    ko = _v2p_translate( (page_table_t*) user_ptab,
    1484                          vpn,
     1520                         (vaddr >> 12),
    14851521                         &ppn,
    14861522                         &flags );
     
    14881524    {
    14891525        _get_lock(&_tty_put_lock);
    1490         _puts("\n[GIET ERROR] in _fb_cma_init() : SRC chbuf descriptor unmapped\n");
     1526        _puts("\n[GIET ERROR] in _fb_cma_init() : channel descriptor unmapped\n");
    14911527        _release_lock(&_tty_put_lock);
    14921528        return 1;
    14931529    }
    1494     src_chbuf_pbase = (((paddr_t)ppn) << 12) | (vpn & 0x00000FFF);
    1495 
    1496     // Compute physical adress of the DST chbuf descriptor
    1497     vpn = ((unsigned int)(&_fb_cma_channel[channel_id].fbf)) >> 12;
    1498     ko = _v2p_translate( (page_table_t*) user_ptab,
    1499                          vpn,
    1500                          &ppn,
    1501                          &flags );
    1502     if (ko)
    1503     {
    1504         _get_lock(&_tty_put_lock);
    1505         _puts("\n[GIET ERROR] in _fb_cma_init() : DST chbuf descriptor unmapped\n");
    1506         _release_lock(&_tty_put_lock);
    1507         return 1;
    1508     }
    1509     dst_chbuf_pbase = (((paddr_t)ppn) << 12) | (vpn & 0x00000FFF);
     1530    channel_pbase = (((paddr_t)ppn) << 12) | (vaddr & 0x00000FFF);
     1531    _fb_cma_desc_paddr[channel_id] = channel_pbase;
     1532
     1533#if GIET_DEBUG_CMA_DRIVER
     1534_puts("\n");
     1535_puts("- fbf       pbase = ");
     1536_putl( _fb_cma_channel[channel_id].fbf );
     1537_puts("\n");
     1538_puts("- buf0      pbase = ");
     1539_putl( _fb_cma_channel[channel_id].buf0 );
     1540_puts("\n");
     1541_puts("- buf1      pbase = ");
     1542_putl( _fb_cma_channel[channel_id].buf1 );
     1543_puts("\n");
     1544_puts("- channel   pbase = ");
     1545_putl( channel_pbase );
     1546_puts("\n");
     1547#endif
     1548
     1549    // SYNC request for channel descriptor
     1550    _memc_sync( channel_pbase, 32 );
    15101551
    15111552    // CMA channel activation
     
    15131554    unsigned int  offset     = channel_id * CHBUF_CHANNEL_SPAN;
    15141555
    1515     cma_vbase[offset + CHBUF_SRC_DESC]  = (unsigned int)(src_chbuf_pbase & 0xFFFFFFFF);
    1516     cma_vbase[offset + CHBUF_SRC_EXT]   = (unsigned int)(src_chbuf_pbase >> 32);
     1556    cma_vbase[offset + CHBUF_SRC_DESC]  = (unsigned int)(channel_pbase & 0xFFFFFFFF);
     1557    cma_vbase[offset + CHBUF_SRC_EXT]   = (unsigned int)(channel_pbase >> 32);
    15171558    cma_vbase[offset + CHBUF_SRC_NBUFS] = 2;
    1518     cma_vbase[offset + CHBUF_DST_DESC]  = (unsigned int)(dst_chbuf_pbase & 0xFFFFFFFF);
    1519     cma_vbase[offset + CHBUF_DST_EXT]   = (unsigned int)(dst_chbuf_pbase >> 32);
     1559    cma_vbase[offset + CHBUF_DST_DESC]  = (unsigned int)(channel_pbase & 0xFFFFFFFF) + 16;
     1560    cma_vbase[offset + CHBUF_DST_EXT]   = (unsigned int)(channel_pbase >> 32);
    15201561    cma_vbase[offset + CHBUF_DST_NBUFS] = 1;
    15211562    cma_vbase[offset + CHBUF_BUF_SIZE]  = length;
     
    15361577//////////////////////////////////////////////////////////////////////////////////
    15371578// _fb_cma_write()
    1538 // This function updates the status of the SRC and DST chbuf descriptors
    1539 // to allows the CMA component to transfer another buffer.
     1579// This function makes a SYNC request for the source user buffer.
     1580// Then it updates the status of the SRC and DST chbuf descriptors, to allow
     1581// the CMA component to transfer the source user buffer buffer to the destination
     1582// frame buffer, and makes a SYNC request for the channel descriptor.
     1583//
    15401584// - buffer_id : user buffer index (0 => buf0 / not 0 => buf1)
    15411585// Returns 0 if success, > 0 if error
     
    15451589#if NB_CMA_CHANNELS > 0
    15461590
     1591    paddr_t         buf_paddr;
     1592    unsigned int    buf_length;
     1593
    15471594    // get CMA channel index
    15481595    unsigned int channel_id = _get_context_slot(CTX_CMA_ID);
    1549     if ( channel_id >= NB_CMA_CHANNELS )
    1550     {
    1551         _get_lock(&_tty_put_lock);
    1552         _puts("\n[GIET ERROR] in _fb_cma_write() : CMA channel index too large\n");
    1553         _release_lock(&_tty_put_lock);
    1554         return 1;
    1555     }
     1596
     1597    // SYNC request for the source user buffer
     1598    if ( buffer_id == 0 )  buf_paddr = _fb_cma_channel[channel_id].buf0;
     1599    else                   buf_paddr = _fb_cma_channel[channel_id].buf1;
     1600    buf_length = _fb_cma_channel[channel_id].length;
     1601    _memc_sync( buf_paddr, buf_length );
     1602
    15561603    // set SRC full
    15571604    if ( buffer_id == 0 )
    1558     _fb_cma_channel[channel_id].buf0 = _fb_cma_channel[channel_id].buf0
    1559                                        | 0x8000000000000000ULL;
     1605    _fb_cma_channel[channel_id].buf0 = buf_paddr | 0x8000000000000000ULL;
    15601606    else
    1561     _fb_cma_channel[channel_id].buf1 = _fb_cma_channel[channel_id].buf1
    1562                                        | 0x8000000000000000ULL;
     1607    _fb_cma_channel[channel_id].buf1 = buf_paddr | 0x8000000000000000ULL;
     1608
    15631609    // set DST empty
    15641610    _fb_cma_channel[channel_id].fbf  = _fb_cma_channel[channel_id].fbf
    15651611                                       & 0x7FFFFFFFFFFFFFFFULL;
     1612
     1613    // SYNC request for the channel descriptor
     1614    buf_paddr  = _fb_cma_desc_paddr[channel_id];
     1615    buf_length = 32;
     1616    _memc_sync( buf_paddr, buf_length );
     1617
    15661618    return 0;
    15671619
     
    15861638    // get CMA channel allocated
    15871639    unsigned int channel_id = _get_context_slot(CTX_CMA_ID);
    1588     if ( channel_id >= NB_CMA_CHANNELS )
    1589     {
    1590         _get_lock(&_tty_put_lock);
    1591         _puts("\n[GIET ERROR] in _fb_cma_stop() : CMA channel index too large\n");
    1592         _release_lock(&_tty_put_lock);
    1593         return 1;
    1594     }
     1640
    15951641    // CMA channel desactivation
    15961642    unsigned int* cma_vbase = (unsigned int *)&seg_cma_base;
     
    17041750///////////////////////////////////////////////////////////////////////////////////
    17051751// _memc_inval()
    1706 // This function invalidate all cache lines covering a memory buffer defined
     1752// This function invalidates all cache lines covering a memory buffer defined
    17071753// by the physical base address, and the length.
    17081754// The buffer address MSB are used to compute the cluster index.
     
    17241770    mmc_address[MEMC_BUF_LENGTH] = buf_length;
    17251771    mmc_address[MEMC_CMD_TYPE]   = MEMC_CMD_INVAL;
     1772
     1773    // release the lock protecting MEMC
     1774    mmc_address[MEMC_LOCK] = 0;
     1775}
     1776///////////////////////////////////////////////////////////////////////////////////
     1777// _memc_sync()
     1778// This function copies to external RAM all cache lines covering a memory buffer
     1779// defined by the physical base address, and the length, if they are dirty.
     1780// The buffer address MSB are used to compute the cluster index.
     1781///////////////////////////////////////////////////////////////////////////////////
     1782void _memc_sync( paddr_t      buf_paddr,
     1783                 unsigned int buf_length )
     1784{
     1785    unsigned int cluster_id    = (unsigned int)((buf_paddr>>32)/(256/NB_CLUSTERS));
     1786
     1787    unsigned int * mmc_address = (unsigned int *) ((unsigned int)&seg_mmc_base +
     1788                                 (cluster_id * (unsigned int)&vseg_cluster_increment));
     1789
     1790    // get the lock protecting exclusive access to MEMC
     1791    while ( mmc_address[MEMC_LOCK] ) { asm volatile("nop"); }
     1792
     1793    // write inval arguments
     1794    mmc_address[MEMC_ADDR_LO]    = (unsigned int)buf_paddr;
     1795    mmc_address[MEMC_ADDR_HI]    = (unsigned int)(buf_paddr>>32);
     1796    mmc_address[MEMC_BUF_LENGTH] = buf_length;
     1797    mmc_address[MEMC_CMD_TYPE]   = MEMC_CMD_SYNC;
    17261798
    17271799    // release the lock protecting MEMC
Note: See TracChangeset for help on using the changeset viewer.