/* * Routines to access hardware * * Copyright (c) 2013 Realtek Semiconductor Corp. * * This module is a confidential and proprietary property of RealTek and * possession or use of this module requires written permission of RealTek. */ #include "rtl8195a.h" #include "hal_gdma.h" #define MAX_GDMA_INDX 1 #define MAX_GDMA_CHNL 6 static u8 HalGdmaReg[MAX_GDMA_INDX+1]; const HAL_GDMA_CHNL GDMA_Chnl_Option[] = { {0,0,GDMA0_CHANNEL0_IRQ,0}, {1,0,GDMA1_CHANNEL0_IRQ,0}, {0,1,GDMA0_CHANNEL1_IRQ,0}, {1,1,GDMA1_CHANNEL1_IRQ,0}, {0,2,GDMA0_CHANNEL2_IRQ,0}, {1,2,GDMA1_CHANNEL2_IRQ,0}, {0,3,GDMA0_CHANNEL3_IRQ,0}, {1,3,GDMA1_CHANNEL3_IRQ,0}, {0,4,GDMA0_CHANNEL4_IRQ,0}, {1,4,GDMA1_CHANNEL4_IRQ,0}, {0,5,GDMA0_CHANNEL5_IRQ,0}, {1,5,GDMA1_CHANNEL5_IRQ,0}, {0xff,0,0,0} // end }; const HAL_GDMA_CHNL GDMA_Multi_Block_Chnl_Option[] = { {0,4,GDMA0_CHANNEL4_IRQ,0}, {1,4,GDMA1_CHANNEL4_IRQ,0}, {0,5,GDMA0_CHANNEL5_IRQ,0}, {1,5,GDMA1_CHANNEL5_IRQ,0}, {0xff,0,0,0} // end }; const u16 HalGdmaChnlEn[6] = { GdmaCh0, GdmaCh1, GdmaCh2, GdmaCh3, GdmaCh4, GdmaCh5 }; VOID HalGdmaOpInit( IN VOID *Data ) { PHAL_GDMA_OP pHalGdmaOp = (PHAL_GDMA_OP) Data; pHalGdmaOp->HalGdmaOnOff = HalGdmaOnOffRtl8195a; pHalGdmaOp->HalGdamChInit = HalGdamChInitRtl8195a; pHalGdmaOp->HalGdmaChDis = HalGdmaChDisRtl8195a; pHalGdmaOp->HalGdmaChEn = HalGdmaChEnRtl8195a; pHalGdmaOp->HalGdmaChSeting = HalGdmaChSetingRtl8195a; #ifndef CONFIG_CHIP_E_CUT pHalGdmaOp->HalGdmaChBlockSeting = HalGdmaChBlockSetingRtl8195a_Patch; #else pHalGdmaOp->HalGdmaChBlockSeting = HalGdmaChBlockSetingRtl8195a_V04; #endif pHalGdmaOp->HalGdmaChIsrEnAndDis = HalGdmaChIsrEnAndDisRtl8195a; pHalGdmaOp->HalGdmaChIsrClean = HalGdmaChIsrCleanRtl8195a; pHalGdmaOp->HalGdmaChCleanAutoSrc = HalGdmaChCleanAutoSrcRtl8195a; pHalGdmaOp->HalGdmaChCleanAutoDst = HalGdmaChCleanAutoDstRtl8195a; } VOID HalGdmaOn(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { pHalGdmaAdapter->GdmaOnOff = ON; HalGdmaOnOffRtl8195a((VOID*)pHalGdmaAdapter); } VOID HalGdmaOff(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { pHalGdmaAdapter->GdmaOnOff = OFF; HalGdmaOnOffRtl8195a((VOID*)pHalGdmaAdapter); } BOOL HalGdmaChInit(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { return (HalGdamChInitRtl8195a((VOID*)pHalGdmaAdapter)); } VOID HalGdmaChDis(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { HalGdmaChDisRtl8195a((VOID*)pHalGdmaAdapter); } VOID HalGdmaChEn(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { HalGdmaChEnRtl8195a((VOID*)pHalGdmaAdapter); } BOOL HalGdmaChSeting(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { return (HalGdmaChSetingRtl8195a((VOID*)pHalGdmaAdapter)); } BOOL HalGdmaChBlockSeting(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { #ifndef CONFIG_CHIP_E_CUT return (HalGdmaChBlockSetingRtl8195a_Patch((VOID*)pHalGdmaAdapter)); #else return (HalGdmaChBlockSetingRtl8195a_V04((VOID*)pHalGdmaAdapter)); #endif } VOID HalGdmaChIsrEn(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { pHalGdmaAdapter->IsrCtrl = ENABLE; HalGdmaChIsrEnAndDisRtl8195a((VOID*)pHalGdmaAdapter); } VOID HalGdmaChIsrDis(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { pHalGdmaAdapter->IsrCtrl = DISABLE; HalGdmaChIsrEnAndDisRtl8195a((VOID*)pHalGdmaAdapter); } u8 HalGdmaChIsrClean(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { return (HalGdmaChIsrCleanRtl8195a((VOID*)pHalGdmaAdapter)); } VOID HalGdmaChCleanAutoSrc(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { HalGdmaChCleanAutoSrcRtl8195a((VOID*)pHalGdmaAdapter); } VOID HalGdmaChCleanAutoDst(PHAL_GDMA_ADAPTER pHalGdmaAdapter) { HalGdmaChCleanAutoDstRtl8195a((VOID*)pHalGdmaAdapter); } HAL_Status HalGdmaChnlRegister (u8 GdmaIdx, u8 ChnlNum) { u32 mask; if ((GdmaIdx > MAX_GDMA_INDX) || (ChnlNum > MAX_GDMA_CHNL)) { // Invalid GDMA Index or Channel Number return HAL_ERR_PARA; } mask = 1 << ChnlNum; if ((HalGdmaReg[GdmaIdx] & mask) != 0) { return HAL_BUSY; } else { #if 1 if (HalGdmaReg[GdmaIdx] == 0) { if (GdmaIdx == 0) { ACTCK_GDMA0_CCTRL(ON); GDMA0_FCTRL(ON); } else { ACTCK_GDMA1_CCTRL(ON); GDMA1_FCTRL(ON); } } #endif HalGdmaReg[GdmaIdx] |= mask; return HAL_OK; } } VOID HalGdmaChnlUnRegister (u8 GdmaIdx, u8 ChnlNum) { u32 mask; if ((GdmaIdx > MAX_GDMA_INDX) || (ChnlNum > MAX_GDMA_CHNL)) { // Invalid GDMA Index or Channel Number return; } mask = 1 << ChnlNum; HalGdmaReg[GdmaIdx] &= ~mask; #if 1 if (HalGdmaReg[GdmaIdx] == 0) { if (GdmaIdx == 0) { ACTCK_GDMA0_CCTRL(OFF); GDMA0_FCTRL(OFF); } else { ACTCK_GDMA1_CCTRL(OFF); GDMA1_FCTRL(OFF); } } #endif } PHAL_GDMA_CHNL HalGdmaChnlAlloc (HAL_GDMA_CHNL *pChnlOption) { HAL_GDMA_CHNL *pgdma_chnl; pgdma_chnl = pChnlOption; if (pChnlOption == NULL) { // Use default GDMA Channel Option table pgdma_chnl = (HAL_GDMA_CHNL*)&GDMA_Chnl_Option[0]; } else{ pgdma_chnl = (HAL_GDMA_CHNL*) pgdma_chnl; } while (pgdma_chnl->GdmaIndx <= MAX_GDMA_INDX) { if (HalGdmaChnlRegister(pgdma_chnl->GdmaIndx, pgdma_chnl->GdmaChnl) == HAL_OK) { // This GDMA Channel is available break; } pgdma_chnl += 1; } if (pgdma_chnl->GdmaIndx > MAX_GDMA_INDX) { pgdma_chnl = NULL; } return pgdma_chnl; } VOID HalGdmaChnlFree (HAL_GDMA_CHNL *pChnl) { IRQ_HANDLE IrqHandle; IrqHandle.IrqNum = pChnl->IrqNum; InterruptDis(&IrqHandle); InterruptUnRegister(&IrqHandle); HalGdmaChnlUnRegister(pChnl->GdmaIndx, pChnl->GdmaChnl); } VOID HalGdmaMemIrqHandler(VOID *pData) { PHAL_GDMA_OBJ pHalGdmaObj=(PHAL_GDMA_OBJ)pData; PHAL_GDMA_ADAPTER pHalGdmaAdapter; PIRQ_HANDLE pGdmaIrqHandle; pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); pGdmaIrqHandle = &(pHalGdmaObj->GdmaIrqHandle); // Clean Auto Reload Bit HalGdmaChCleanAutoDst((VOID*)pHalGdmaAdapter); // Clear Pending ISR HalGdmaChIsrClean((VOID*)pHalGdmaAdapter); HalGdmaChDis((VOID*)(pHalGdmaAdapter)); pHalGdmaObj->Busy = 0; if (pGdmaIrqHandle->IrqFun != NULL) { pGdmaIrqHandle->IrqFun((VOID*)pGdmaIrqHandle->Data); } } BOOL HalGdmaMemCpyAggrInit(PHAL_GDMA_OBJ pHalGdmaObj) { HAL_GDMA_CHNL *pgdma_chnl; PHAL_GDMA_ADAPTER pHalGdmaAdapter; PIRQ_HANDLE pGdmaIrqHandle; IRQ_HANDLE IrqHandle; pgdma_chnl = HalGdmaChnlAlloc((PHAL_GDMA_CHNL) &GDMA_Multi_Block_Chnl_Option[0]); // get a whatever GDMA channel if (NULL == pgdma_chnl) { DBG_GDMA_ERR("%s: Cannot allocate a GDMA Channel\n", __FUNCTION__); return _FALSE; } pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); pGdmaIrqHandle = &(pHalGdmaObj->GdmaIrqHandle); DBG_GDMA_INFO("%s: Use GDMA%d CH%d\n", __FUNCTION__, pgdma_chnl->GdmaIndx, pgdma_chnl->GdmaChnl); _memset((void *)pHalGdmaAdapter, 0, sizeof(HAL_GDMA_ADAPTER)); pHalGdmaAdapter->GdmaCtl.TtFc = TTFCMemToMem; pHalGdmaAdapter->GdmaCtl.Done = 1; pHalGdmaAdapter->MuliBlockCunt = 0; pHalGdmaAdapter->MaxMuliBlock = 1; pHalGdmaAdapter->ChNum = pgdma_chnl->GdmaChnl; pHalGdmaAdapter->GdmaIndex = pgdma_chnl->GdmaIndx; pHalGdmaAdapter->ChEn = 0x0101 << pgdma_chnl->GdmaChnl; pHalGdmaAdapter->GdmaIsrType = (TransferType|ErrType); pHalGdmaAdapter->IsrCtrl = ENABLE; pHalGdmaAdapter->GdmaOnOff = ON; pHalGdmaAdapter->GdmaCtl.IntEn = 1; pHalGdmaAdapter->Rsvd4to7 = 1; pHalGdmaAdapter->Llpctrl = 1; pGdmaIrqHandle->IrqNum = pgdma_chnl->IrqNum; pGdmaIrqHandle->Priority = 10; IrqHandle.IrqFun = (IRQ_FUN) HalGdmaMemIrqHandler; IrqHandle.Data = (u32) pHalGdmaObj; IrqHandle.IrqNum = pGdmaIrqHandle->IrqNum; IrqHandle.Priority = pGdmaIrqHandle->Priority; InterruptRegister(&IrqHandle); InterruptEn(&IrqHandle); pHalGdmaObj->Busy = 0; return _TRUE; } VOID HalGdmaMultiBlockSetting(PHAL_GDMA_OBJ pHalGdmaObj, PHAL_GDMA_BLOCK pHalGdmaBlock) { PHAL_GDMA_ADAPTER pHalGdmaAdapter; u8 BlockNumber; u8 BlockIndex; u8 FourBytesAlign; BlockNumber = pHalGdmaObj->BlockNum; pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); pHalGdmaAdapter->GdmaCtl.LlpSrcEn = 1; pHalGdmaAdapter->GdmaCtl.LlpDstEn = 1; if(((pHalGdmaBlock[0].SrcAddr & 0x03) == 0) &&((pHalGdmaBlock[0].DstAddr & 0x03) == 0) && ((pHalGdmaBlock[0].BlockLength & 0X03) == 0)){ pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeEight; pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthFourBytes; pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeEight; pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthFourBytes; FourBytesAlign = 1; } else{ pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeEight; pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthOneByte; pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeEight; pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthOneByte; FourBytesAlign = 0; } for(BlockIndex = 0; BlockIndex < BlockNumber; BlockIndex++){ pHalGdmaObj->GdmaChLli[BlockIndex].Sarx = pHalGdmaBlock[BlockIndex].SrcAddr; pHalGdmaObj->GdmaChLli[BlockIndex].Darx = pHalGdmaBlock[BlockIndex].DstAddr; pHalGdmaObj->BlockSizeList[BlockIndex].pNextBlockSiz = &pHalGdmaObj->BlockSizeList[BlockIndex + 1]; if(FourBytesAlign){ pHalGdmaObj->BlockSizeList[BlockIndex].BlockSize = pHalGdmaBlock[BlockIndex].BlockLength >> 2; } else{ pHalGdmaObj->BlockSizeList[BlockIndex].BlockSize = pHalGdmaBlock[BlockIndex].BlockLength; } pHalGdmaObj->Lli[BlockIndex].pLliEle = (GDMA_CH_LLI_ELE*) &pHalGdmaObj->GdmaChLli[BlockIndex]; pHalGdmaObj->Lli[BlockIndex].pNextLli = &pHalGdmaObj->Lli[BlockIndex + 1]; if(BlockIndex == BlockNumber - 1){ pHalGdmaObj->BlockSizeList[BlockIndex].pNextBlockSiz = NULL; pHalGdmaObj->Lli[BlockIndex].pNextLli = NULL; } //DBG_GDMA_INFO("Lli[%d].pLiEle = %x\r\n", BlockIndex,Lli[BlockIndex].pLliEle); //DBG_GDMA_INFO("Lli[%d].pNextLli = %x\r\n", BlockIndex,Lli[BlockIndex].pNextLli); } pHalGdmaAdapter->pBlockSizeList = (struct BLOCK_SIZE_LIST*) &pHalGdmaObj->BlockSizeList; pHalGdmaAdapter->pLlix = (struct GDMA_CH_LLI*) &pHalGdmaObj->Lli; //DBG_GDMA_INFO("pHalGdmaAdapter->pBlockSizeList = %x\r\n", pHalGdmaAdapter->pBlockSizeList); //DBG_GDMA_INFO("pHalGdmaAdapter->pLlix = %x\r\n", pHalGdmaAdapter->pLlix ); } VOID HalGdmaLLPMemAlign(PHAL_GDMA_OBJ pHalGdmaObj, PHAL_GDMA_BLOCK pHalGdmaBlock) { PHAL_GDMA_ADAPTER pHalGdmaAdapter; PGDMA_CH_LLI_ELE pLliEle; struct GDMA_CH_LLI *pGdmaChLli; struct BLOCK_SIZE_LIST *pGdmaChBkLi; u32 CtlxLow; u32 CtlxUp; u8 BlockNumber; u8 BlockIndex; pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); BlockNumber = pHalGdmaObj->BlockNum; pLliEle = pHalGdmaAdapter->pLlix->pLliEle; pGdmaChLli = pHalGdmaAdapter->pLlix->pNextLli; pGdmaChBkLi = pHalGdmaAdapter->pBlockSizeList; //4 Move to the second block to configure Memory Alginment setting pLliEle->Llpx = (u32) pGdmaChLli->pLliEle; pGdmaChBkLi = pGdmaChBkLi ->pNextBlockSiz; for(BlockIndex = 1; BlockIndex < BlockNumber; BlockIndex++){ pLliEle = pGdmaChLli->pLliEle; CtlxLow = pLliEle->CtlxLow; CtlxLow &= (BIT_INVC_CTLX_LO_DST_TR_WIDTH & BIT_INVC_CTLX_LO_SRC_TR_WIDTH); CtlxUp = pLliEle->CtlxUp; CtlxUp &= (BIT_INVC_CTLX_UP_BLOCK_BS); if(((pHalGdmaBlock[BlockIndex].SrcAddr & 0x03) == 0) &&((pHalGdmaBlock[BlockIndex].DstAddr & 0x03) == 0) && ((pHalGdmaBlock[BlockIndex].BlockLength & 0X03) == 0)){ pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthFourBytes; pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthFourBytes; pGdmaChBkLi->BlockSize = pHalGdmaBlock[BlockIndex].BlockLength>> 2; } else{ pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthOneByte; pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthOneByte; pGdmaChBkLi->BlockSize = pHalGdmaBlock[BlockIndex].BlockLength; } CtlxLow |= (BIT_CTLX_LO_DST_TR_WIDTH(pHalGdmaAdapter->GdmaCtl.DstTrWidth) | BIT_CTLX_LO_SRC_TR_WIDTH(pHalGdmaAdapter->GdmaCtl.SrcTrWidth)); CtlxUp |= BIT_CTLX_UP_BLOCK_BS(pGdmaChBkLi->BlockSize); pGdmaChLli = pGdmaChLli->pNextLli; pGdmaChBkLi = pGdmaChBkLi->pNextBlockSiz; pLliEle->CtlxLow = CtlxLow; pLliEle->CtlxUp = CtlxUp; pLliEle->Llpx = (u32)(pGdmaChLli->pLliEle); } } VOID HalGdmaMemAggr(PHAL_GDMA_OBJ pHalGdmaObj, PHAL_GDMA_BLOCK pHalGdmaBlock) { PHAL_GDMA_ADAPTER pHalGdmaAdapter; u8 BlockNumber; BlockNumber = pHalGdmaObj->BlockNum; pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); if (pHalGdmaObj->Busy) { DBG_GDMA_ERR("%s: ==> GDMA is Busy\r\n", __FUNCTION__); return; } pHalGdmaObj->Busy = 1; pHalGdmaAdapter->MaxMuliBlock = BlockNumber; pHalGdmaAdapter->ChSar = pHalGdmaBlock[0].SrcAddr; pHalGdmaAdapter->ChDar = pHalGdmaBlock[0].DstAddr; HalGdmaMultiBlockSetting(pHalGdmaObj, pHalGdmaBlock); HalGdmaOn((pHalGdmaAdapter)); HalGdmaChIsrEn((pHalGdmaAdapter)); HalGdmaChBlockSeting((pHalGdmaAdapter)); HalGdmaLLPMemAlign(pHalGdmaObj, pHalGdmaBlock); HalGdmaChEn((pHalGdmaAdapter)); } BOOL HalGdmaMemCpyInit(PHAL_GDMA_OBJ pHalGdmaObj) { HAL_GDMA_CHNL *pgdma_chnl; PHAL_GDMA_ADAPTER pHalGdmaAdapter; PIRQ_HANDLE pGdmaIrqHandle; IRQ_HANDLE IrqHandle; pgdma_chnl = HalGdmaChnlAlloc(NULL); // get a whatever GDMA channel if (NULL == pgdma_chnl) { DBG_GDMA_ERR("%s: Cannot allocate a GDMA Channel\n", __FUNCTION__); return _FALSE; } pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); pGdmaIrqHandle = &(pHalGdmaObj->GdmaIrqHandle); DBG_GDMA_INFO("%s: Use GDMA%d CH%d\n", __FUNCTION__, pgdma_chnl->GdmaIndx, pgdma_chnl->GdmaChnl); #if 0 if (pgdma_chnl->GdmaIndx == 0) { ACTCK_GDMA0_CCTRL(ON); GDMA0_FCTRL(ON); } else if (pgdma_chnl->GdmaIndx == 1) { ACTCK_GDMA1_CCTRL(ON); GDMA1_FCTRL(ON); } #endif _memset((void *)pHalGdmaAdapter, 0, sizeof(HAL_GDMA_ADAPTER)); // pHalGdmaAdapter->GdmaCtl.TtFc = TTFCMemToMem; pHalGdmaAdapter->GdmaCtl.Done = 1; // pHalGdmaAdapter->MuliBlockCunt = 0; // pHalGdmaAdapter->MaxMuliBlock = 1; pHalGdmaAdapter->ChNum = pgdma_chnl->GdmaChnl; pHalGdmaAdapter->GdmaIndex = pgdma_chnl->GdmaIndx; pHalGdmaAdapter->ChEn = 0x0101 << pgdma_chnl->GdmaChnl; pHalGdmaAdapter->GdmaIsrType = (TransferType|ErrType); pHalGdmaAdapter->IsrCtrl = ENABLE; pHalGdmaAdapter->GdmaOnOff = ON; pHalGdmaAdapter->GdmaCtl.IntEn = 1; // pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeEight; // pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeEight; // pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthFourBytes; // pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthFourBytes; // pHalGdmaAdapter->GdmaCtl.Dinc = IncType; // pHalGdmaAdapter->GdmaCtl.Sinc = IncType; pGdmaIrqHandle->IrqNum = pgdma_chnl->IrqNum; pGdmaIrqHandle->Priority = 10; IrqHandle.IrqFun = (IRQ_FUN) HalGdmaMemIrqHandler; IrqHandle.Data = (u32) pHalGdmaObj; IrqHandle.IrqNum = pGdmaIrqHandle->IrqNum; IrqHandle.Priority = pGdmaIrqHandle->Priority; InterruptRegister(&IrqHandle); InterruptEn(&IrqHandle); pHalGdmaObj->Busy = 0; return _TRUE; } VOID HalGdmaMemCpyDeInit(PHAL_GDMA_OBJ pHalGdmaObj) { HAL_GDMA_CHNL GdmaChnl; PHAL_GDMA_ADAPTER pHalGdmaAdapter; PIRQ_HANDLE pGdmaIrqHandle; pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); pGdmaIrqHandle = &(pHalGdmaObj->GdmaIrqHandle); GdmaChnl.GdmaIndx = pHalGdmaAdapter->GdmaIndex; GdmaChnl.GdmaChnl = pHalGdmaAdapter->ChNum; GdmaChnl.IrqNum = pGdmaIrqHandle->IrqNum; HalGdmaChnlFree(&GdmaChnl); } // If multi-task using the same GDMA Object, then it needs a mutex to protect this procedure VOID* HalGdmaMemCpy(PHAL_GDMA_OBJ pHalGdmaObj, void* pDest, void* pSrc, u32 len) { PHAL_GDMA_ADAPTER pHalGdmaAdapter; if (pHalGdmaObj->Busy) { DBG_GDMA_ERR("%s: ==> GDMA is Busy\r\n", __FUNCTION__); return 0; } pHalGdmaObj->Busy = 1; pHalGdmaAdapter = &(pHalGdmaObj->HalGdmaAdapter); DBG_GDMA_INFO("%s: ==> Src=0x%x Dst=0x%x Len=%d\r\n", __FUNCTION__, pSrc, pDest, len); if ((((u32)pSrc & 0x03)==0) && (((u32)pDest & 0x03)==0) && ((len & 0x03)== 0)) { // 4-bytes aligned, move 4 bytes each transfer pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeEight; pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthFourBytes; pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeEight; pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthFourBytes; pHalGdmaAdapter->GdmaCtl.BlockSize = len >> 2; } else { pHalGdmaAdapter->GdmaCtl.SrcMsize = MsizeEight; pHalGdmaAdapter->GdmaCtl.SrcTrWidth = TrWidthOneByte; pHalGdmaAdapter->GdmaCtl.DestMsize = MsizeEight; pHalGdmaAdapter->GdmaCtl.DstTrWidth = TrWidthOneByte; pHalGdmaAdapter->GdmaCtl.BlockSize = len; } pHalGdmaAdapter->ChSar = (u32)pSrc; pHalGdmaAdapter->ChDar = (u32)pDest; pHalGdmaAdapter->PacketLen = len; HalGdmaOn((pHalGdmaAdapter)); HalGdmaChIsrEn((pHalGdmaAdapter)); HalGdmaChSeting((pHalGdmaAdapter)); HalGdmaChEn((pHalGdmaAdapter)); return (pDest); }