Ignore:
Timestamp:
Jun 24, 2014, 4:41:44 PM (10 years ago)
Author:
alain
Message:

Introducing a _dma_physical_memcpy() in the DMA driver.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • soft/giet_vm/giet_drivers/dma_driver.c

    r333 r343  
    152152// and sets the transfer size to lauch the transfer.
    153153//////////////////////////////////////////////////////////////////////////////////
    154 unsigned int _dma_start_transfer( unsigned int       cluster_xy,
    155                                   unsigned int       channel_id,
    156                                   unsigned long long dst_paddr,   // physical address
    157                                   unsigned long long src_paddr,   // physical address
    158                                   unsigned int       size )       // bytes
    159 {
    160 #if NB_DMA_CHANNELS > 0
    161 
    162     // parameters checking
    163     unsigned int x = cluster_xy >> Y_WIDTH;
    164     unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
    165     if (x >= X_SIZE)                    return 1;
    166     if (y >= Y_SIZE)                    return 1;
    167     if (channel_id >= NB_DMA_CHANNELS)  return 1;
     154void _dma_start_transfer( unsigned int       cluster_xy,  // DMA cluster
     155                          unsigned int       channel_id,  // DMA channel
     156                          unsigned long long dst_paddr,   // physical address
     157                          unsigned long long src_paddr,   // physical address
     158                          unsigned int       size )       // bytes
     159{
     160#if NB_DMA_CHANNELS > 0
    168161
    169162    // compute DMA base address
     
    177170    dma_address[channel_id * DMA_SPAN + DMA_DST_EXT] = (unsigned int)(dst_paddr>>32);
    178171    dma_address[channel_id * DMA_SPAN + DMA_LEN]     = (unsigned int)size;
    179     return 0;
    180 #else
    181     return 1;
    182 #endif
    183 }
    184 ///////////////////////////////////////////////////////////////////////////////////
    185 // This function copies a source memory buffer to a destination memory buffer,
    186 // using the distributed DMA. As it makes virtual to physical address translation,
    187 // the MMU should be activated.
    188 // This driver makes the assumption that each processor has a private DMA channel:
    189 // the DMA cluster and channel indexes are obtained from the processor index.
     172
     173#endif
     174}
     175
     176///////////////////////////////////////////////////////////////////////////////////
     177// This function copies a source memory buffer to a destination memory buffer,
     178// using directly physical addresses.
     179// This blocking function is supposed to be used by the kernel only,
     180// and uses a polling policy on DMA_STATUS register to detect completion.
     181// Therefore, the DMA_IRQ is NOT used.
    190182// The source and destination buffers base addresses must be word aligned,
    191183// and the buffer's size must be multiple of 4.
     
    193185// message is displayed on TTY0, and the system crash.
    194186///////////////////////////////////////////////////////////////////////////////////
    195 // Note: this blocking function is supposed to be used by the kernel only,
    196 // and uses a polling policy on DMA_STATUS register to detect completion.
    197 // Therefore, the DMA_IRQ is NOT used.
    198 ///////////////////////////////////////////////////////////////////////////////////
    199 inline void  _dma_copy( unsigned int vspace_id, // vspace index for V2P
    200                         void*        dest,      // dest buffer vbase
    201                         const void*  source,    // source buffer vbase
    202                         unsigned int size )     // bytes
    203 {
    204 #if NB_DMA_CHANNELS > 0
    205 
    206     unsigned int procid     = _get_procid();
    207     unsigned int cluster_xy = procid/NB_PROCS_MAX;
    208     unsigned int channel_id = procid%NB_PROCS_MAX;
    209 
    210     unsigned int ko;
    211     unsigned int ppn;
    212     unsigned int flags;
    213 
    214 #if GIET_DEBUG_DMA_DRIVER
    215 unsigned int x          = cluster_xy >> Y_WIDTH;
    216 unsigned int y          = cluster_xy & ((1<<Y_WIDTH)-1);
    217 
    218 _printf("\n[DMA DEBUG] Processor[%d,%d,%d] enters _dma_copy() at cycle %d\n"
    219         " - vspace_id   = %d\n"
    220         " - src_vaddr   = %x\n"
    221         " - dst_vaddr   = %x\n"
     187void _dma_physical_copy( unsigned int       cluster_xy,  // DMA cluster
     188                         unsigned int       channel_id,  // DMA channel
     189                         unsigned long long dst_paddr,   // destination physical address
     190                         unsigned long long src_paddr,   // source physical address
     191                         unsigned int       size )       // bytes
     192{
     193#if NB_DMA_CHANNELS > 0
     194
     195    // check DMA channel parameters
     196    unsigned int x = cluster_xy >> Y_WIDTH;
     197    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     198    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
     199    {
     200        _printf("\n[GIET ERROR] in _dma_physical_copy() : illegal DMA channel ");
     201        _exit();
     202    }
     203
     204    // check buffers alignment constraints
     205    if ( (dst_paddr & 0x3)   || (src_paddr & 0x3) || (size & 0x3) )
     206    {
     207        _printf("\n[GIET ERROR] in _dma_physical_copy() : buffer unaligned\n");
     208        _exit();
     209    }
     210
     211#if GIET_DEBUG_DMA_DRIVER
     212_printf("\n[DMA DEBUG] Start a dma_physical_copy on channel[%d,%d,%d] at cycle %d\n"
     213        " - src_paddr   = %l\n"
     214        " - dst_paddr   = %l\n"
    222215        " - bytes       = %x\n",
    223         x, y, channel_id, _get_proctime(), vspace_id,
    224         (unsigned int)source, (unsigned int)dest, size );
    225 #endif
    226 
    227     // checking alignment constraints
    228     if ( (((unsigned int)dest) & 0x3)   ||
    229          (((unsigned int)source) & 0x3) ||
    230          (size & 0x3) )
    231     {
    232         _printf("\n[GIET ERROR] in _dma_copy() : buffer unaligned\n");
    233         _exit();
    234     }
    235 
    236     // get vspace 0 page table pointer
    237     unsigned int pt =  _ptabs_vaddr[vspace_id];
    238 
    239     // get source buffer physical addresse
    240     ko = _v2p_translate( (page_table_t*)pt,              // page table pointer
    241                          ((unsigned int)source)>>12,     // vpn
    242                          &ppn,                           // ppn
    243                          &flags );                       // flags
    244     if ( ko )
    245     {
    246         _printf("\n[GIET ERROR] in _dma_copy() : source buffer unmapped\n");
    247         _exit();
    248     }
    249     unsigned long long src_paddr = (((unsigned long long)ppn) << 12) |
    250                                    ((unsigned int)source & 0x00000FFF);
    251 
    252     // get dest buffer physical addresse
    253     ko = _v2p_translate( (page_table_t*)pt,              // page table pointer
    254                          ((unsigned int)dest)>>12,       // vpn
    255                          &ppn,                           // ppn
    256                          &flags );                       // flags
    257     if ( ko )
    258     {
    259         _printf("\n[GIET ERROR] in _dma_copy() : dest buffer unmapped\n");
    260         _exit();
    261     }
    262     unsigned long long dst_paddr = (((unsigned long long)ppn) << 12) |
    263                                    ((unsigned int)dest & 0x00000FFF);
    264 
    265 #if GIET_DEBUG_DMA_DRIVER
    266 _printf(" - src_paddr   = %l\n"
    267         " - dst_paddr   = %l\n",
    268         src_paddr, dst_paddr );
    269 #endif
    270 
    271     // invalidate L1 cache if no hardware cache coherence
    272     if ( GIET_NO_HARD_CC ) _dcache_buf_invalidate( dest, size );
     216        x, y, channel_id, _get_proctime(), src_paddr, dst_paddr, size );
     217#endif
    273218
    274219    // dma channel configuration & lauching
    275     ko = _dma_start_transfer(  cluster_xy, channel_id, dst_paddr, src_paddr, size );
    276     if ( ko )
    277     {
    278         _printf("\n[GIET ERROR] in _dma_copy() : cannot start transfer\n");
    279         _exit();
    280     }
     220    _dma_start_transfer( cluster_xy, channel_id, dst_paddr, src_paddr, size );
    281221
    282222    // scan dma channel status
     
    289229
    290230#if GIET_DEBUG_DMA_DRIVER
    291 _printf("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register ...\n");
     231_printf("\n[DMA DEBUG] _dma_physical_copy() : ... waiting on DMA_STATUS register\n");
     232#endif
     233
     234    }
     235   
     236    // analyse status
     237    if( status != DMA_SUCCESS )
     238    {
     239        _printf("\n[GIET ERROR] in _dma_physical_copy() : DMA_STATUS = %x\n", status );
     240        _exit();
     241    }
     242    // reset dma channel
     243    _dma_reset( cluster_xy, channel_id );
     244
     245#if GIET_DEBUG_DMA_DRIVER
     246_printf("\n[DMA DEBUG] _dma_physical_copy() completed at cycle %d\n", _get_proctime() );
     247#endif
     248
     249#else // NB_DMA_CHANNELS == 0
     250    _printf("\n[GIET ERROR] in _dma_physical_copy() : NB_DMA_CHANNELS == 0 / cycle %d\n",
     251            _get_proctime );
     252    _exit();
     253#endif
     254}
     255
     256///////////////////////////////////////////////////////////////////////////////////
     257// This function copies a source memory buffer to a destination memory buffer,
     258// making virtual to physical address translation: the MMU should be activated.
     259// This blocking function is supposed to be used by the kernel only,
     260// and uses a polling policy on DMA_STATUS register to detect completion.
     261// Therefore, the DMA_IRQ is NOT used.
     262// The source and destination buffers base addresses must be word aligned,
     263// and the buffer's size must be multiple of 4.
     264// In case of error (buffer unmapped, unaligned, or DMA_STATUS error), an error
     265// message is displayed on TTY0, and the system crash.
     266///////////////////////////////////////////////////////////////////////////////////
     267void  _dma_copy( unsigned int cluster_xy,    // DMA cluster
     268                 unsigned int channel_id,    // DMA channel
     269                 unsigned int vspace_id,     // vspace index for v2p translation
     270                 unsigned int dst_vaddr,     // dst_vaddr buffer vbase
     271                 unsigned int src_vaddr,     // src_vaddr buffer vbase
     272                 unsigned int size )         // bytes
     273{
     274#if NB_DMA_CHANNELS > 0
     275
     276    // check DMA channel parameters
     277    unsigned int x = cluster_xy >> Y_WIDTH;
     278    unsigned int y = cluster_xy & ((1<<Y_WIDTH)-1);
     279    if ( (x >= X_SIZE) || (y >= Y_SIZE) || (channel_id >= NB_DMA_CHANNELS) )
     280    {
     281        _printf("\n[GIET ERROR] in _dma_copy() : illegal DMA channel ");
     282        _exit();
     283    }
     284
     285    // check buffers alignment constraints
     286    if ( (dst_vaddr & 0x3)   || (src_vaddr & 0x3) || (size & 0x3) )
     287    {
     288        _printf("\n[GIET ERROR] in _dma_copy() : buffer unaligned\n");
     289        _exit();
     290    }
     291
     292    unsigned int ko;
     293    unsigned int ppn;
     294    unsigned int flags;
     295
     296#if GIET_DEBUG_DMA_DRIVER
     297_printf("\n[DMA DEBUG] Start a dma_copy on channel[%d,%d,%d] at cycle %d\n"
     298        " - src_vaddr   = %x\n"
     299        " - dst_vaddr   = %x\n"
     300        " - bytes       = %x\n",
     301        x, y, channel_id, _get_proctime(), src_vaddr, dst_vaddr, size );
     302#endif
     303
     304    // checking alignment constraints
     305    if ( (((unsigned int)dst_vaddr) & 0x3) ||
     306         (((unsigned int)src_vaddr) & 0x3) ||
     307         (size & 0x3) )
     308    {
     309        _printf("\n[GIET ERROR] in _dma_copy() : buffer unaligned\n");
     310        _exit();
     311    }
     312
     313    // get vspace page table pointer
     314    unsigned int pt =  _ptabs_vaddr[vspace_id];
     315
     316    // get src_paddr buffer physical addresse
     317    ko = _v2p_translate( (page_table_t*)pt,              // page table pointer
     318                         src_vaddr>>12,                  // vpn
     319                         &ppn,                           // ppn
     320                         &flags );                       // flags
     321    if ( ko )
     322    {
     323        _printf("\n[GIET ERROR] in _dma_copy() : source buffer unmapped\n");
     324        _exit();
     325    }
     326    unsigned long long src_paddr = (((unsigned long long)ppn) << 12) |
     327                                   (unsigned long long)(src_vaddr & 0x00000FFF);
     328
     329    // get dst_paddr buffer physical addresse
     330    ko = _v2p_translate( (page_table_t*)pt,              // page table pointer
     331                         dst_vaddr>>12,                  // vpn
     332                         &ppn,                           // ppn
     333                         &flags );                       // flags
     334    if ( ko )
     335    {
     336        _printf("\n[GIET ERROR] in _dma_copy() : dest buffer unmapped\n");
     337        _exit();
     338    }
     339    unsigned long long dst_paddr = (((unsigned long long)ppn) << 12) |
     340                                   (unsigned long long)(dst_vaddr & 0x00000FFF);
     341
     342#if GIET_DEBUG_DMA_DRIVER
     343_printf(" - src_paddr   = %l\n"
     344        " - dst_paddr   = %l\n",
     345        src_paddr, dst_paddr );
     346#endif
     347
     348    // dma channel configuration & lauching
     349    _dma_start_transfer(  cluster_xy, channel_id, dst_paddr, src_paddr, size );
     350
     351    // scan dma channel status
     352    unsigned int status = _dma_get_status( cluster_xy, channel_id );
     353    while( (status != DMA_SUCCESS) &&
     354           (status != DMA_READ_ERROR) &&
     355           (status != DMA_WRITE_ERROR) )
     356    {
     357        status = _dma_get_status( cluster_xy, channel_id );
     358
     359#if GIET_DEBUG_DMA_DRIVER
     360_printf("\n[DMA DEBUG] _dma_copy() : ... waiting on DMA_STATUS register\n");
    292361#endif
    293362
Note: See TracChangeset for help on using the changeset viewer.