void DmaIntModeDemo(void) { UINT8 ch_no; //Dma channel number UINT32 len = 1023; UINT32 tmp_src[1023], tmp_dst[1023]; UINT8 ret; printf("Dma Int Mode Demo.\r\n"); /* enable Dma Clk */ ScuDmaClkEn(); for(ch_no = 0; ch_no < 8; ch_no++) { trans_finish_flag = FALSE; /* initial source data */ GetTrueRand8((UINT8 *)tmp_src, len << 2); /* lock dma channel */ ret = DmaChLock(ch_no); /* setting dma trans interrupt handle */ ret |= DmaSetIntrHandle(ch_no, DmaFinishHdl, NULL, NULL, NULL); /* setting dma trans parameter */ ret |= SetupMode(ch_no, MEM_MEM, DISCRIC, NO_PER, NO_PER, ENINC, ENINC, W_32BIT, len, H_PRI); /* setting dma trans address */ ret |= SetTransAddress(ch_no, (UINT32)tmp_src, (UINT32)tmp_dst); /* start dma trans */ ret |= DmaStart(ch_no); if(ret != DMA_RET_SUCESS) { printf("dma channel %d trans error, error code %d\r\n", ch_no, ret); return; } /* wait trans finish */ while(trans_finish_flag == FALSE); /* disable dma channel trrans finish interrupt */ DisDmaIntr(0x1 << ch_no); if(Memcmp(tmp_src, tmp_dst, len) != 0) { printf("dma channel %d trans error, data error\r\n", ch_no); return; } else { printf("dma channel %d trans sucess\r\n", ch_no); } DmaChUnlock(ch_no); } ScuDmaClkDis(); }
_ATTR_LCDDRIVER_ST7637_CODE_ int32 ST7637_DMATranfer32 (UINT8 x0,UINT8 y0,UINT8 x1,UINT8 y1,UINT32 *pSrc, pFunc CallBack) { UINT32 size; eDMA_CHN channel; DMA_CFGX DmaCfg = {CTLL_M2LCD_WORD,CFGL_M2LCD_SINGLE,CFGH_M2LCD_SINGLE,0}; ST7637_SetWindow(x0,y0, x1,y1); channel = DmaGetChannel(); if (channel != DMA_FALSE) { size = (((x1 + 1) - x0) * ((y1+1) - y0)) >> 1; Lcd_SplitMode(LCD_SPLIT5); DmaStart((uint32)(channel), (UINT32)(pSrc),(uint32)(&(Lcd->data)),size,&DmaCfg, CallBack); return channel; }
/* -------------------------------------------------------------------------------- Function name : int32 UartDmaRead(uint8 *pdata, uint32 size, uint32 uartTimeOut, pFunc Callback) Author : Description : read the uart data by dma. Input : pdata:input data pointer. size: input data size.(byte) uartTimeOut: waiting delay time. Callback:DMA interrupt callback. Return : 0:OK -1:fail History: <author> <time> <version> desc: -------------------------------------------------------------------------------- */ _ATTR_DRIVER_CODE_ int32 UartDmaRead(uint8 *pdata, uint32 size, uint32 uartTimeOut, pFunc Callback) { eDMA_CHN channel; DMA_CFGX DmaCfg = {DMA_CTLL_UART2M,DMA_CFGL_UART2M,DMA_CFGH_UART2M,0}; while ((UartReg->UART_USR & UART_TRANSMIT_FIFO_NOT_FULL) != UART_TRANSMIT_FIFO_NOT_FULL) { if (uartTimeOut == 0) { return (-1); } uartTimeOut--; } channel = DmaGetChannel(); if (channel != DMA_FALSE) { DmaStart((uint32)(channel), (uint32)(&(UartReg->UART_RBR)),(UINT32)(pdata),size, &DmaCfg, Callback); return channel; } return (-1); }
//------------------------------------------------------------------------------ SCODE OMAPDDGPE::DMAFill( GPEBltParms* pParms ) { SCODE result = S_OK; RECTL* prclDst = pParms->prclDst; DWORD dwWidth = prclDst->right - prclDst->left; DWORD dwHeight = prclDst->bottom - prclDst->top; DWORD dwStride = pParms->pDst->Stride(); DWORD dwOffset = 0; OMAPDDGPESurface* pOmapSurf = (OMAPDDGPESurface*) pParms->pDst; DmaConfigInfo_t DmaSettings = { 0, // elemSize 1, // srcElemIndex 1, // srcFrameIndex DMA_CCR_SRC_AMODE_CONST, // srcAddrMode 1, // dstElemIndex 1, // dstFrameIndex DMA_CCR_DST_AMODE_DOUBLE, // dstAddrMode FALSE, // dmaPrio DMA_SYNCH_TRIGGER_NONE, // synchTrigger DMA_SYNCH_NONE, // synchMode 0, // interrupts 0 // syncMap }; // Check that a DMA Blt is worth doing if( dwWidth < MIN_DMA_WIDTH || dwHeight < MIN_DMA_HEIGHT ) { if (g_Globals.m_dwEnableNeonBlts) { pParms->pBlt = (SCODE (GPE::*)(struct GPEBltParms *)) &OMAPDDGPE::DesignateBlt; return OMAPDDGPE::DesignateBlt(pParms); } else { pParms->pBlt = &GPE::EmulatedBlt; return GPE::EmulatedBlt(pParms); } } // Allocate DMA channel if( g_hDmaChannel1 == NULL ) { g_hDmaChannel1 = DmaAllocateChannel(DMA_TYPE_SYSTEM); InitializeCriticalSection( &g_csDmaLock ); } // Lock access to DMA registers EnterCriticalSection( &g_csDmaLock ); // Wait for any pending operations to complete WaitForNotBusy(); // Configure DMA channel for FILL operation switch( pParms->pDst->BytesPerPixel() ) { case 1: DmaSettings.elemSize = DMA_CSDP_DATATYPE_S8; DmaSettings.dstFrameIndex = 1 + dwStride - dwWidth; dwOffset = prclDst->top * dwStride + prclDst->left; break; case 2: DmaSettings.elemSize = DMA_CSDP_DATATYPE_S16; DmaSettings.dstFrameIndex = 1 + dwStride - 2*dwWidth; dwOffset = prclDst->top * dwStride + 2 * prclDst->left; break; case 4: DmaSettings.elemSize = DMA_CSDP_DATATYPE_S32; DmaSettings.dstFrameIndex = 1 + dwStride - 4*dwWidth; dwOffset = prclDst->top * dwStride + 4 * prclDst->left; break; } // Clear any clipping rect for the operation pOmapSurf->OmapSurface()->SetClipping( NULL ); // Enable bursting for improved memory performance DmaSettings.elemSize |= DMA_CSDP_DST_BURST_64BYTES_16x32_8x64 | DMA_CSDP_DST_PACKED; // Configure the DMA channel DmaConfigure( g_hDmaChannel1, &DmaSettings, 0, &g_tDmaDataInfo1 ); DmaSetColor( &g_tDmaDataInfo1, DMA_CCR_CONST_FILL_ENABLE, (DWORD)pParms->solidColor ); DmaSetSrcBuffer( &g_tDmaDataInfo1, NULL, 0 ); DmaSetDstBuffer( &g_tDmaDataInfo1, NULL, pOmapSurf->OmapSurface()->PhysicalAddr() + dwOffset ); DmaSetElementAndFrameCount( &g_tDmaDataInfo1, dwWidth, (UINT16) dwHeight ); // Start the DMA operation DmaStart( &g_tDmaDataInfo1 ); // Unlock access to DMA registers LeaveCriticalSection( &g_csDmaLock ); return result; }
//------------------------------------------------------------------------------ SCODE OMAPDDGPE::DMASrcCopy( GPEBltParms* pParms ) { SCODE result = S_OK; BOOL bDualDMA = FALSE; RECTL* prclSrc = pParms->prclSrc; RECTL* prclDst = pParms->prclDst; DWORD dwPixelSize = pParms->pDst->BytesPerPixel(); DWORD dwWidth = prclDst->right - prclDst->left; DWORD dwHeight = prclDst->bottom - prclDst->top; DWORD dwSrcStride = pParms->pSrc->Stride(); DWORD dwDstStride = pParms->pDst->Stride(); DWORD dwSrcOffset = 0; DWORD dwDstOffset = 0; DWORD dwSrcMidpoint = 0; DWORD dwDstMidpoint = 0; DWORD dwWidth1 = dwWidth, dwWidth2 = dwWidth; DWORD dwHeight1 = dwHeight, dwHeight2 = dwHeight; OMAPDDGPESurface* pOmapSrcSurf = (OMAPDDGPESurface*) pParms->pSrc; OMAPDDGPESurface* pOmapDstSurf = (OMAPDDGPESurface*) pParms->pDst; DmaConfigInfo_t DmaSettings = { 0, // elemSize 1, // srcElemIndex 1, // srcFrameIndex DMA_CCR_SRC_AMODE_DOUBLE, // srcAddrMode 1, // dstElemIndex 1, // dstFrameIndex DMA_CCR_DST_AMODE_DOUBLE, // dstAddrMode FALSE, // dmaPrio DMA_SYNCH_TRIGGER_NONE, // synchTrigger DMA_SYNCH_NONE, // synchMode 0, // interrupts 0 // syncMap }; // Check that a DMA Blt is worth doing if( dwWidth < MIN_DMA_WIDTH || dwHeight < MIN_DMA_HEIGHT ) { if (g_Globals.m_dwEnableNeonBlts) { pParms->pBlt = (SCODE (GPE::*)(struct GPEBltParms *)) &OMAPDDGPE::DesignateBlt; return OMAPDDGPE::DesignateBlt(pParms); } else { pParms->pBlt = &GPE::EmulatedBlt; return GPE::EmulatedBlt(pParms); } } // Allocate DMA channels if( g_hDmaChannel1 == NULL ) { g_hDmaChannel1 = DmaAllocateChannel(DMA_TYPE_SYSTEM); InitializeCriticalSection( &g_csDmaLock ); } if( g_hDmaChannel2 == NULL ) { g_hDmaChannel2 = DmaAllocateChannel(DMA_TYPE_SYSTEM); } // Lock access to DMA registers EnterCriticalSection( &g_csDmaLock ); // Wait for any pending operations to complete WaitForNotBusy(); // Configure DMA channel for SRCCPY operation switch( pParms->pDst->BytesPerPixel() ) { case 1: DmaSettings.elemSize = DMA_CSDP_DATATYPE_S8; break; case 2: DmaSettings.elemSize = DMA_CSDP_DATATYPE_S16; break; case 4: DmaSettings.elemSize = DMA_CSDP_DATATYPE_S32; break; } // Compute element indexing, frame indexing and starting offset for both surfaces // Note that both xPos and yPos will never be both < 0 // Also note that xPos !=1 prevents bursting and actually slows DMA down below memcpy speeds if( pParms->xPositive ) { // Index x axis in positive direction (left to right) DmaSettings.srcElemIndex = 1; DmaSettings.dstElemIndex = 1; // Offset from left side of surface dwSrcOffset = dwPixelSize * prclSrc->left; dwDstOffset = dwPixelSize * prclDst->left; } else { // Index x axis in negative direction (right to left) DmaSettings.srcElemIndex = 1 - 2*dwPixelSize; DmaSettings.dstElemIndex = 1 - 2*dwPixelSize; // Offset from right side of surface dwSrcOffset = dwPixelSize * (prclSrc->right - 1); dwDstOffset = dwPixelSize * (prclDst->right - 1); } if( pParms->yPositive ) { // Index y axis in positive direction (top to bottom) DmaSettings.srcFrameIndex = DmaSettings.srcElemIndex + dwSrcStride; DmaSettings.dstFrameIndex = DmaSettings.dstElemIndex + dwDstStride; if( pParms->xPositive ) { DmaSettings.srcFrameIndex -= dwWidth*dwPixelSize; DmaSettings.dstFrameIndex -= dwWidth*dwPixelSize; } else { DmaSettings.srcFrameIndex += dwWidth*dwPixelSize; DmaSettings.dstFrameIndex += dwWidth*dwPixelSize; } // Offset from top side of surface dwSrcOffset = dwSrcOffset + prclSrc->top * dwSrcStride; dwDstOffset = dwDstOffset + prclDst->top * dwDstStride; } else { // Index y axis in negative direction (bottom to top) DmaSettings.srcFrameIndex = DmaSettings.srcElemIndex - dwSrcStride; DmaSettings.dstFrameIndex = DmaSettings.dstElemIndex - dwDstStride; if( pParms->xPositive ) { DmaSettings.srcFrameIndex -= dwWidth*dwPixelSize; DmaSettings.dstFrameIndex -= dwWidth*dwPixelSize; } else { DmaSettings.srcFrameIndex += dwWidth*dwPixelSize; DmaSettings.dstFrameIndex += dwWidth*dwPixelSize; } // Offset from bottom side of surface dwSrcOffset = dwSrcOffset + (prclSrc->bottom - 1) * dwSrcStride; dwDstOffset = dwDstOffset + (prclDst->bottom - 1) * dwDstStride; } // // Check for fast dual DMA cases // // Different src and dst surfaces can use dual DMA if( pOmapSrcSurf != pOmapDstSurf ) { // Split work in half vertically dwHeight1 = dwHeight/2; dwHeight2 = dwHeight - dwHeight1; dwSrcMidpoint = (pParms->yPositive) ? dwSrcOffset + dwHeight1*dwSrcStride : dwSrcOffset - dwHeight1*dwSrcStride; dwDstMidpoint = (pParms->yPositive) ? dwDstOffset + dwHeight1*dwDstStride : dwDstOffset - dwHeight1*dwDstStride; bDualDMA = TRUE; } // Clear any clipping rect for the operation pOmapSrcSurf->OmapSurface()->SetClipping( NULL ); pOmapDstSurf->OmapSurface()->SetClipping( NULL ); // Enable bursting for improved memory performance DmaSettings.elemSize |= DMA_CSDP_SRC_BURST_64BYTES_16x32_8x64 | DMA_CSDP_SRC_PACKED; DmaSettings.elemSize |= DMA_CSDP_DST_BURST_64BYTES_16x32_8x64 | DMA_CSDP_DST_PACKED; // Configure the DMA channel DmaConfigure( g_hDmaChannel1, &DmaSettings, 0, &g_tDmaDataInfo1 ); DmaSetSrcBuffer( &g_tDmaDataInfo1, NULL, pOmapSrcSurf->OmapSurface()->PhysicalAddr() + dwSrcOffset ); DmaSetDstBuffer( &g_tDmaDataInfo1, NULL, pOmapDstSurf->OmapSurface()->PhysicalAddr() + dwDstOffset ); DmaSetElementAndFrameCount( &g_tDmaDataInfo1, dwWidth1, (UINT16) dwHeight1); if( bDualDMA ) { DmaConfigure( g_hDmaChannel2, &DmaSettings, 0, &g_tDmaDataInfo2 ); DmaSetSrcBuffer( &g_tDmaDataInfo2, NULL, pOmapSrcSurf->OmapSurface()->PhysicalAddr() + dwSrcMidpoint ); DmaSetDstBuffer( &g_tDmaDataInfo2, NULL, pOmapDstSurf->OmapSurface()->PhysicalAddr() + dwDstMidpoint ); DmaSetElementAndFrameCount( &g_tDmaDataInfo2, dwWidth2, (UINT16) dwHeight2 ); } // Configure for transparent copy if requested if( pParms->bltFlags & BLT_TRANSPARENT ) { DmaSetColor( &g_tDmaDataInfo1, DMA_CCR_TRANSPARENT_COPY_ENABLE, (DWORD)pParms->solidColor ); if( bDualDMA ) DmaSetColor( &g_tDmaDataInfo2, DMA_CCR_TRANSPARENT_COPY_ENABLE, (DWORD)pParms->solidColor ); } // Start the DMA operation(s) DmaStart( &g_tDmaDataInfo1 ); if( bDualDMA ) DmaStart( &g_tDmaDataInfo2 ); // Unlock access to DMA registers LeaveCriticalSection( &g_csDmaLock ); return result; }
// // Perform the actual DMA copy // WARNING!! This function assumes the physical memory is contiguous. // No check is performed for performance improvement. // Buffers passed-in come from CMEM and DISPLAY drivers. // DWORD SdmaPx::Copy( LPVOID pSource, LPVOID pDestination, DWORD dwClientIdx ) { DWORD dwRet = 0; DWORD dwCause, dwStatus; DWORD paSrc, paDst; BYTE ffCached = 0; DmaConfigInfo_t dmaSettings = m_SdmaPxClient[dwClientIdx].GetConfig(); DWORD dwDataLength = m_SdmaPxClient[dwClientIdx].GetDataLength(); DWORD dwElementCount = m_SdmaPxClient[dwClientIdx].GetElementCount(); DWORD dwFrameCount = m_SdmaPxClient[dwClientIdx].GetFrameCount(); ASSERTMSG(L"Client must be configured before Copy I/O control is called !!!\n", m_SdmaPxClient[dwClientIdx].IsClientConfigured()); // Configure SDMA for specific client // Need to call this first for length // memset() on DmaConfigInfo_t not needed as done in the SdmaPxClient::Init() method. // m_SdmaPxClient[dwClientIdx].GetConfig(&dmaSettings, &dwDataLength); if(DmaConfigure(m_hDmaChannel, &dmaSettings, 0, &m_dmaInfo) != TRUE) { ERRORMSG(ZONE_ERROR, (TEXT("ERROR! Unable to configure DMA for client\r\n"))); goto cleanUp; } // flush cache if necessary if (ISUNCACHEDADDRESS(pSource) == FALSE) { ffCached |= SOURCE_CACHED; } if (ISUNCACHEDADDRESS(pDestination) == FALSE) { ffCached |= DESTINATION_CACHED; } if (ffCached & (SOURCE_CACHED | DESTINATION_CACHED)) { FlushCache(pSource, pDestination, dwDataLength, ffCached); } // Retrieve base physical address of buffer to be copied and READ lock the pages on the length. if(LockPages( (LPVOID)pSource, (DWORD)dwDataLength, m_rgPFNsrc, LOCKFLAG_READ) == FALSE) { ERRORMSG(ZONE_ERROR, (TEXT("LockPages call \"src\" failed. (error code=%d)\r\n"), GetLastError())); goto cleanUp; } // Not necessary to do the page shift on ARM platform as always 0. (ref. MSDN) // paSrc = (m_rgPFNsrc[0] << m_pageShift) + ((DWORD)pSource & m_pageMask); paSrc = m_rgPFNsrc[0] + ((DWORD)pSource & m_pageMask); // Retrieve base physical address of destination buffer and WRITE lock the pages on the length. if(LockPages( (LPVOID)pDestination, dwDataLength, m_rgPFNdst, LOCKFLAG_WRITE) == FALSE) { ERRORMSG(ZONE_ERROR, (TEXT("LockPages \"dest\" call failed. (error code=%d)\r\n"), GetLastError())); goto cleanUp; } // Not necessary to do the page shift on ARM platform as always 0. (ref. MSDN) // paDst = (m_rgPFNdst[0] << UserKInfo[KINX_PFN_SHIFT]) + ((DWORD)pDestination & m_pageMask); paDst = m_rgPFNdst[0] + ((DWORD)pDestination & m_pageMask); // Configure Dest and Src buffers for DMA. DmaSetSrcBuffer(&m_dmaInfo, (UINT8 *)pSource, paSrc); DmaSetDstBuffer(&m_dmaInfo, (UINT8 *)pDestination, paDst); // Watch out parameters in DmaSetElemenAndFrameCount. For e.g., shift right element count by 2 if you have bytes in input and you use 32bits element size. DmaSetElementAndFrameCount(&m_dmaInfo, dwElementCount, (UINT16)(dwFrameCount)); // start dma DmaStart(&m_dmaInfo); // wait until we hit the end of buffer // Wait for dma interrupt... dwCause = WaitForSingleObject(m_hEvent, DMA_IRQ_TIMEOUT); switch(dwCause) { case WAIT_OBJECT_0: { // Verify cause of interrupt was because we hit the end of block dwStatus = DmaGetStatus(&m_dmaInfo); if ((dwStatus & (dmaSettings.interrupts)) == 0) { ERRORMSG(ZONE_ERROR, (TEXT("Unexpected cause of interrupt\r\n"))); break; } DmaClearStatus(&m_dmaInfo, dwStatus); if (DmaInterruptDone(m_hDmaChannel) == FALSE) { ERRORMSG(ZONE_ERROR, (TEXT("ERROR! Unable to get status for dma interrupt\r\n"))); break; } // Do the "good" client job DmaStop(&m_dmaInfo); break; } default: RETAILMSG(ZONE_ERROR, (TEXT("ERROR! didn't receive DMA interrupt\r\n"))); break; } #if DEBUG_VERIFY_SDMA_COPY // // Beware!! Bring a lot of overhead and can lead to bad display rendering. // NKDbgPrintfW(L"verify memory\r\n"); if (memcmp(pSource, pDestination, dwDataLength) != 0) { NKDbgPrintfW(L"ERROR! memory doesn't match up\r\n"); DebugBreak(); goto cleanUp; } #endif dwRet = dwDataLength; // everything went fine obviously... cleanUp: UnlockPages((LPVOID)pSource, dwDataLength); UnlockPages((LPVOID)pDestination, dwDataLength); return dwRet; }