#include <windows.h>
#include <CEDDK.h>
#include <bsp_cfg.h>
#include <oal_intr.h>
#include <register_map.h>
#include "pmplatform.h"
#include "dma_controller.h"

#include "image_cfg.h"

#include <drvmsg.h>
#include <drvlib_mem.h>





HANDLE      m_hPowerCon;


#define DMAC_CODE_BASE    IMAGE_DMA_CODE_UA_START
#define DMAC_CODE_PHY_BASE    IMAGE_DMA_CODE_PA_START
#define DMAC_PDMA_CODE_SIZE_PER_CHANNEL    0xa0 //160Byte
#define DMAC_MDMA_CODE_SIZE_PER_CHANNEL    0x400 //1024Byte

#define DMA_UNIT_NUM 3
#define DMA_CH_NUM 8


volatile static UINT32 *v_pDMACode;

static volatile DMAC_REG *g_pPDMAC0Reg = NULL;
static volatile DMAC_REG *g_pPDMAC1Reg = NULL;
static volatile DMAC_REG *g_pMDMACReg = NULL;
static volatile CMU_CLK_REG    *g_pCMUCLKReg = NULL;

static BOOL DMA_lock(void);
static BOOL DMA_unlock(void);

static HANDLE g_hMutex = NULL;

#define DMA_MUTEX    TEXT("DMA_Mutex")

#define DMA_SRC_NUM    45

static const UINT32 g_DreqSrctoPeri[DMA_SRC_NUM] =
{
//                        DreqSrc Num  Peri Num
//.....................................................
// Peri DMA 0,1
    PERI_UART_0_RX,        //0x0            // 0x0
    PERI_UART_0_TX,        //0x1            // 0x1
    PERI_UART_1_RX,        //0x2            // 0x2
    PERI_UART_1_TX,        //0x3            // 0x3
    PERI_UART_2_RX,        //0x4            // 0x4
    PERI_UART_2_TX,        //0x5            // 0x5
    PERI_UART_3_RX,        //0x6            // 0x6
    PERI_UART_3_TX,        //0x7            // 0x7
    PERI_I2S_0_RX,         //0x8            // 0x9
    PERI_I2S_0_TX,         //0x9            // 0xa
    PERI_I2S_0S_TX,        //0xa            // 0xb
    PERI_I2S_1_RX,         //0xb            // 0xc
    PERI_I2S_1_TX,         //0xc            // 0xd
    PERI_SPI_0_RX,         //0xd            // 0x10
    PERI_SPI_0_TX,         //0xe            // 0x11
    PERI_SPI_1_RX,         //0xf            // 0x12
    PERI_SPI_1_TX,         //0x10           // 0x13
    PERI_SPI_2_RX,         //0x11           // 0x14
    PERI_SPI_2_TX,         //0x12           // 0x15
// Peri DMA 0
    PERI_AC_MICin,         //0x13           // 0x16
    PERI_AC_PCMin,         //0x14           // 0x17
    PERI_AC_PCMout,        //0x15           // 0x18
    PERI_PWM,              //0x16           // 0x1a
    PERI_PWM,              //0x17           // 0x1a
    PERI_SPDIFO,           //0x18           // 0x1b
    PERI_SPDIFO,           //0x19           // 0x1b
// Peri DMA 1
    PERI_I2S_2_RX,         //0x1a           // 0xe
    PERI_I2S_2_TX,         //0x1b           // 0xf
    PERI_PCM_0_RX,         //0x1c           // 0x16
    PERI_PCM_0_TX,         //0x1d           // 0x17
    PERI_PCM_1_RX,         //0x1e           // 0x18
    PERI_PCM_1_TX,         //0x1f           // 0x19
    PERI_MSM_REQ0,         //0x20           // 0x1a
    PERI_MSM_REQ0,         //0x21           // 0x1b
    PERI_MSM_REQ1,         //0x22           // 0x1c
    PERI_MSM_REQ1,         //0x23           // 0x1d
    PERI_MSM_REQ2,         //0x24           // 0x1a
    PERI_MSM_REQ2,         //0x25           // 0x1b
    PERI_MSM_REQ3,         //0x26           // 0x1c
    PERI_MSM_REQ3,         //0x27           // 0x1d
    PERI_PCM_2_RX,         //0x28           // 0x1e
    PERI_PCM_2_TX,         //0x29           // 0x1f
// Mem DMA
    PERI_SEC_RX,           //0x2a           // 0x0
    PERI_SEC_TX,           //0x2b           // 0x1
    PERI_SOFTWARE          //0x2c           // 0xff
};



DMA_ERROR DMA_initialize_register_address(void *pDMAC0Reg, void *pDMAC1Reg, void *pMDMACReg, void *pCMUCLKReg)
{
    DMA_ERROR error = DMA_SUCCESS;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_initialize_register_address(0x%08x, 0x%08x,0x%08x, 0x%08x)\n\r"), pDMAC0Reg, pDMAC1Reg,pMDMACReg, pCMUCLKReg));

    if (pDMAC0Reg == NULL || pDMAC1Reg == NULL || pCMUCLKReg == NULL)
    {
        ERRMSG((_T("[DMA:ERR] DMA_initialize_register_address() : NULL pointer parameter\n\r")));
        error = DMA_ERROR_NULL_PARAMETER;
    }
    else
    {

        g_pPDMAC0Reg = (DMAC_REG *)pDMAC0Reg;
        g_pPDMAC1Reg = (DMAC_REG *)pDMAC1Reg;
        g_pMDMACReg = (DMAC_REG *)pMDMACReg;
        g_pCMUCLKReg = (CMU_CLK_REG *)pCMUCLKReg;
        DBGMSG(DMA_INFO,(_T("[DMA:INF] g_pDMAC0Reg = 0x%08x\n\r"), g_pPDMAC0Reg));
        DBGMSG(DMA_INFO,(_T("[DMA:INF] g_pDMAC1Reg = 0x%08x\n\r"), g_pPDMAC1Reg));
      DBGMSG(DMA_INFO,(_T("[DMA:INF] g_pMDMACReg = 0x%08x\n\r"), g_pMDMACReg));
        DBGMSG(DMA_INFO,(_T("[DMA:INF] g_pCMUCLKReg = 0x%08x\n\r"), g_pCMUCLKReg));



        //isaac where is this register???
//        g_pSysConReg->SDMA_SEL = 0xcfffffff;    // All DMA is set to Normal DMA except Security TX, RX

    }


    if (g_hMutex == NULL)
    {
        g_hMutex = CreateMutex(NULL, FALSE, DMA_MUTEX);
        if (g_hMutex == NULL)
        {
            ERRMSG((_T("[DMA:ERR] DMA_initialize_register_address() : CreateMutex() Failed\n\r")));
            error = DMA_ERROR_NOT_INITIALIZED;
        }
    }


    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_initialize_register_address() : %d\n\r"), error));



    return error;
}



DMA_UNIT DMAdrv_GetDmaUnit(DREQ_SRC eSrc)
{
    DMA_UNIT dma_unit;
    switch(eSrc)
    {
        case DMAsrc_PCM_2_TX:
        case DMAsrc_PCM_2_RX:
        case DMAsrc_MSM_REQ3_TX:
        case DMAsrc_MSM_REQ3_RX:
        case DMAsrc_MSM_REQ2_TX:
        case DMAsrc_MSM_REQ2_RX:
        case DMAsrc_MSM_REQ1_TX:
        case DMAsrc_MSM_REQ1_RX:
        case DMAsrc_MSM_REQ0_TX:
        case DMAsrc_MSM_REQ0_RX:
        case DMAsrc_PCM_1_TX:
        case DMAsrc_PCM_1_RX:
        case DMAsrc_PCM_0_TX:
        case DMAsrc_PCM_0_RX:
        case DMAsrc_I2S_2_TX:
        case DMAsrc_I2S_2_RX:    
            dma_unit=DMA_PDMA1;
            break;
        case DMAsrc_SPDIFO_TX:
        case DMAsrc_SPDIFO_RX:
        case DMAsrc_PWM_TX:
        case DMAsrc_PWM_RX:
        case DMAsrc_AC_PCMout:
        case DMAsrc_AC_PCMin:
        case DMAsrc_AC_MICin:
            dma_unit=DMA_PDMA0;
            break;
        case DMAsrc_SEC_RX:
        case DMAsrc_SEC_TX:
        case DMAsrc_SOFTWARE_1:
        case DMAsrc_SOFTWARE_2:
        case DMAsrc_SOFTWARE_3:
        case DMAsrc_SOFTWARE_4:
        case DMAsrc_SOFTWARE_5:
        case DMAsrc_SOFTWARE_6:
            dma_unit=DMA_MDMA;
            break;
        case DMAsrc_UART_0_TX:
        case DMAsrc_UART_0_RX:
        case DMAsrc_UART_1_TX:
        case DMAsrc_UART_1_RX:
        case DMAsrc_UART_2_TX:
        case DMAsrc_UART_2_RX:
        case DMAsrc_UART_3_TX:
        case DMAsrc_UART_3_RX:
        case DMAsrc_I2S_0_RX:
        case DMAsrc_I2S_0_TX:
        case DMAsrc_I2S_0S_TX:
        case DMAsrc_I2S_1_RX:
        case DMAsrc_I2S_1_TX:
        case DMAsrc_SPI_0_RX:
        case DMAsrc_SPI_0_TX:
        case DMAsrc_SPI_1_RX:
        case DMAsrc_SPI_1_TX:
        case DMAsrc_SPI_2_RX:
        case DMAsrc_SPI_2_TX:
            dma_unit=DMA_PDMA;
            break;
        default:
            dma_unit=DMA_INVALIDUNIT;
            break;
    }
    return dma_unit;
}


BOOL DMA_request_channel(DMA_CH_CONTEXT *pCtxt, DREQ_SRC DMASrc)
{
    BOOL bRet = TRUE;
    DMA_CH eCh=0;
    DMA_UNIT dmaunit;
    BOOL isFind=FALSE;
    int i;


   DWORD dwIPIndex ;
  DWORD dwBytes;



    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_request_channel(%d)\n\r"), DMASrc));

    if (g_pPDMAC0Reg == NULL || g_pPDMAC1Reg == NULL ||g_pMDMACReg == NULL)
    {
        ERRMSG((_T("[DMA:ERR] DMA Register Address is Not initialized\n\r")));
        bRet = FALSE;
        goto CleanUp;
    }



    m_hPowerCon = CreateFile( L"PWC0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
    if (m_hPowerCon == INVALID_HANDLE_VALUE)
    {

        ERRMSG((_T("[DISPDRV:ERR] DMA_request_channel() : LDI Open Device Failed\n\r")));
        return FALSE;
    }

    dwIPIndex = CLK_IP0_PDMA0;
    if (!DeviceIoControl(m_hPowerCon, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
    {
        ERRMSG((_T("[DMA] CLK_IP_PDMA0  IOCTL_PWRCON_SET_CLOCK_ON Failed on line\r\n")));
    }

    dwIPIndex = CLK_IP0_PDMA1;
    if (!DeviceIoControl(m_hPowerCon, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
    {
        ERRMSG((_T("[DMA] CLK_IP_PDMA1 IOCTL_PWRCON_SET_CLOCK_ON Failed on line\r\n")));
    }

    dwIPIndex = CLK_IP0_MDMA;
    if (!DeviceIoControl(m_hPowerCon, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
    {
        ERRMSG((_T("[DMA] CLK_IP_MDMA IOCTL_PWRCON_SET_CLOCK_ON Failed on line\r\n")));
    }	


    dmaunit = DMAdrv_GetDmaUnit(DMASrc);
    // Lock DMA Access
    DMA_lock();
    // Valid channel selection 0~24
    if(dmaunit == DMA_MDMA)
    {
        for(i=0;i<DMA_CH_NUM;i++)
                if (!(g_pMDMACReg->IntEnable & (1<< i)))    // Check channel in use with Int Enable Bit !!!
                {
                    eCh = DMA_00 + i;
                    isFind=TRUE;
                    break;
                }
    }
    else if(dmaunit ==  DMA_PDMA0)
    {
        for(i=0;i<DMA_CH_NUM;i++)
            if (!(g_pPDMAC0Reg->IntEnable & (1<< i)))    // Check channel in use with Int Enable Bit !!!
            {
                eCh = DMA_10 + i;
                isFind=TRUE;
                break;
            }
    }
    else if(dmaunit == DMA_PDMA1)
    {
        for(i=0;i<DMA_CH_NUM;i++)
            if (!(g_pPDMAC1Reg->IntEnable & (1<< i)))    // Check channel in use with Int Enable Bit !!!
            {
                eCh = DMA_20 + i;
                isFind=TRUE;
                break;
            }
    }
    else if(dmaunit==DMA_PDMA)
    {

        for(i=0;i<DMA_CH_NUM;i++)
            if (!(g_pPDMAC0Reg->IntEnable & (1<< i)))    // Check channel in use with Int Enable Bit !!!
            {
                eCh = DMA_10 + i;
                isFind=TRUE;
                break;
            }
        if(isFind==FALSE)
        {
            for(i=0;i<DMA_CH_NUM;i++)
                if (!(g_pPDMAC1Reg->IntEnable & (1<< i)))    // Check channel in use with Int Enable Bit !!!
                {
                    eCh = DMA_20 + i;
                    isFind=TRUE;
                    break;
                }
        }
    }
    else
    {
        ERRMSG((_T("[DMA:ERR] DMA_request_channel() : Unknown DMA Source [%d]\n\r"), pCtxt->DMASrc));
        goto CleanUp;

    }

   	if(isFind == FALSE){
        ERRMSG((_T("[DMA:ERR] DMA_request_channel() : There is no valid channel\n\r")));
        goto CleanUp;
        }


// Controller selection and controller base address according to channel number
    switch(eCh )
    {
        case DMA_00: case DMA_01: case DMA_02: case DMA_03:
        case DMA_04: case DMA_05: case DMA_06: case DMA_07:
            pCtxt->Controller = DMA_MDMA;
            pCtxt->BaseAddr=(unsigned int)g_pMDMACReg;
            break;
        case DMA_10: case DMA_11: case DMA_12: case DMA_13:
        case DMA_14: case DMA_15: case DMA_16: case DMA_17:
            pCtxt->Controller = DMA_PDMA0;
            pCtxt->BaseAddr=(unsigned int)g_pPDMAC0Reg;
            break;
        case DMA_20: case DMA_21: case DMA_22: case DMA_23:
        case DMA_24: case DMA_25: case DMA_26: case DMA_27:
            pCtxt->Controller = DMA_PDMA1;
            pCtxt->BaseAddr=(unsigned int)g_pPDMAC1Reg;
            break;
        default:
            ERRMSG((_T("[DMA:ERR] DMA_request_channel() : Unknown Channel [%d]\n\r"), eCh));
        goto CleanUp;
        break;

    }



     if (eCh < 24)        // there is available channel
        {
            DBGMSG(DMA_DBG,(_T("[DMA:INF] DMA_request_channel() : Ch[%d] in DMAC%d is Available for DMASrc[%d]\n\r"), eCh,pCtxt->Controller, DMASrc));


            pCtxt->DMASrc = DMASrc;
            pCtxt->PeriNum = g_DreqSrctoPeri[DMASrc];
            pCtxt->CH0_24= (DMA_CH)eCh;
            pCtxt->CH0_7=(DMAC_CH)i;
            pCtxt->dwIRQ = IRQ_MDMA_CH0 + (DWORD) eCh  ;
            pCtxt->bValid = TRUE;
            DMA_clear_interrupt_mask(pCtxt);

        }
    else            // there is no available channel
        {
            ERRMSG((_T("[DMA:ERR] DMA_request_channel() : No Available Channel in DMAC0 for DMASrc[%d]\n\r"), DMASrc));
            bRet = FALSE;
            goto CleanUp;
        }




CleanUp:






 // Disable CLK when No channel is allocated
    if (!g_pMDMACReg->IntEnable)
    {
	dwIPIndex = CLK_IP0_MDMA;
	if (!DeviceIoControl(m_hPowerCon, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
	{
	    ERRMSG((_T("[DMA] CLK_IP_MDMA  IOCTL_PWRCON_SET_CLOCK_OFF Failed on line\r\n")));
	}
    }
	
    if (!g_pPDMAC0Reg->IntEnable)
    {
        
	dwIPIndex = CLK_IP0_PDMA0;
	if (!DeviceIoControl(m_hPowerCon, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
	{
	    ERRMSG((_T("[DMA] CLK_IP_PDMA0  IOCTL_PWRCON_SET_CLOCK_OFF Failed on line\r\n")));
	}
    }

    if (!g_pPDMAC1Reg->IntEnable)
    {
	dwIPIndex = CLK_IP0_PDMA1;
	if (!DeviceIoControl(m_hPowerCon, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
	{
	    ERRMSG((_T("[DMA] CLK_IP_PDMA1  IOCTL_PWRCON_SET_CLOCK_OFF Failed on line\r\n")));
	}
    }



    if (bRet == FALSE)        // Request is denied
    {
        // Clear DMA Channel Context
        memset((void *)pCtxt, 0x0, sizeof(DMA_CH_CONTEXT));
    }

    DMA_unlock();

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_request_channel() : pCtxt->CH0_24 : %d,pCtxt->CH0_7 : %d, ret : %d, pCtxt->dwIRQ : %d,pCtxt->PeriNum : %d\n\r"),
        pCtxt->CH0_24,pCtxt->CH0_7,bRet,pCtxt->dwIRQ,pCtxt->PeriNum));

    return bRet;
}

BOOL DMA_release_channel(DMA_CH_CONTEXT *pCtxt)
{

    BOOL bRet = TRUE;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_release_channel() : Ch%d in DMAC%d, \n\r"), pCtxt->CH0_7, pCtxt->Controller));

    if (pCtxt->bValid == FALSE)
    {
        ERRMSG((_T("[DMA:ERR] DMA_release_channel() : Invalid DMA_CH_CONTEXT\n\r")));
        bRet = FALSE;
        goto CleanUp;
    }

    bRet = DMA_channel_stop(pCtxt);

    DMA_set_interrupt_mask(pCtxt);

    if(v_pDMACode != NULL)
    {
        if(pCtxt->Dir == MEM_TO_MEM)
            DrvLib_UnmapIoSpace((PVOID)pCtxt->CodeStAddr);
		
        else
            DrvLib_UnmapIoSpace((PVOID)pCtxt->CodeStAddr);
        v_pDMACode = NULL;
    }


    if(m_hPowerCon != NULL)
    {
        CloseHandle(m_hPowerCon);
        m_hPowerCon = NULL;
    }

CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_release_channel() : %d\n\r"), bRet));

    return bRet;
}



DMA_ERROR DMA_initialize_channel(DMA_CH_CONTEXT *pCtxt, BOOL bSync)
{
    DMA_ERROR error = DMA_SUCCESS;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_initialize_channel() : Ch%d in DMAC%d (bSync:%d)\n\r"), pCtxt->CH0_7, pCtxt->Controller, bSync));


    //direction selection
     switch(pCtxt->DMASrc)
        {
        case DMAsrc_UART_0_TX:
        case DMAsrc_UART_1_TX:
        case DMAsrc_UART_2_TX:
        case DMAsrc_UART_3_TX:
        case DMAsrc_I2S_0_TX:
        case DMAsrc_I2S_0S_TX:
        case DMAsrc_I2S_1_TX:
        case DMAsrc_I2S_2_TX:
        case DMAsrc_SPI_0_TX:
        case DMAsrc_SPI_1_TX:
        case DMAsrc_SPI_2_TX:
        case DMAsrc_AC_PCMout:
        case DMAsrc_PCM_0_TX:
        case DMAsrc_PCM_1_TX:
        case DMAsrc_PCM_2_TX:            
        case DMAsrc_SPDIFO_TX:
        case DMAsrc_PWM_TX:
        case DMAsrc_MSM_REQ3_TX:
        case DMAsrc_MSM_REQ2_TX:
        case DMAsrc_MSM_REQ1_TX:
        case DMAsrc_MSM_REQ0_TX:
            pCtxt->Dir = MEM_TO_PERI;        // Memory -> Peripheral
            break;
        case DMAsrc_UART_0_RX:
        case DMAsrc_UART_1_RX:
        case DMAsrc_UART_2_RX:
        case DMAsrc_UART_3_RX:
        case DMAsrc_I2S_0_RX:
        case DMAsrc_I2S_1_RX:
        case DMAsrc_I2S_2_RX:
        case DMAsrc_SPI_0_RX:
        case DMAsrc_SPI_1_RX:
        case DMAsrc_SPI_2_RX:
        case DMAsrc_AC_PCMin:
        case DMAsrc_PCM_0_RX:
        case DMAsrc_PCM_1_RX:
        case DMAsrc_PCM_2_RX:            
        case DMAsrc_SPDIFO_RX:
        case DMAsrc_PWM_RX:
        case DMAsrc_AC_MICin:
        case DMAsrc_MSM_REQ3_RX:
        case DMAsrc_MSM_REQ2_RX:
        case DMAsrc_MSM_REQ1_RX:
        case DMAsrc_MSM_REQ0_RX:
            pCtxt->Dir = PERI_TO_MEM;        // Peripheral  -> Memory
            break;
        case DMAsrc_SEC_RX:
        case DMAsrc_SEC_TX:
        case DMAsrc_SOFTWARE_1:
        case DMAsrc_SOFTWARE_2:
        case DMAsrc_SOFTWARE_3:
        case DMAsrc_SOFTWARE_4:
        case DMAsrc_SOFTWARE_5:
        case DMAsrc_SOFTWARE_6:
            pCtxt->Dir = MEM_TO_MEM;        // Memory  -> Memory
            break;
         default :
             goto CleanUp;
             break;
         }
        pCtxt->ProtectionBit = NON_SECURE;


    if( pCtxt->Dir == MEM_TO_MEM){
        pCtxt->CodePhysicalStAddr.LowPart = DMAC_CODE_PHY_BASE + pCtxt->CH0_24*DMAC_MDMA_CODE_SIZE_PER_CHANNEL;
        v_pDMACode = DrvLib_MapIoSpace(pCtxt->CodePhysicalStAddr.LowPart, DMAC_MDMA_CODE_SIZE_PER_CHANNEL, FALSE);
        }
    else {
        pCtxt->CodePhysicalStAddr.LowPart = DMAC_CODE_PHY_BASE + pCtxt->CH0_24*DMAC_PDMA_CODE_SIZE_PER_CHANNEL;
        v_pDMACode = DrvLib_MapIoSpace(pCtxt->CodePhysicalStAddr.LowPart, DMAC_PDMA_CODE_SIZE_PER_CHANNEL, FALSE);
        }



    if (v_pDMACode == NULL)
    {
        DBGMSG(DMA_DBG,(_T("[DMA] v_pDMACode : MmMapIoSpace failed!\n\r")));
        goto CleanUp;
    }

    pCtxt->CodeStAddr= (unsigned int)v_pDMACode;


CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_initialize_channel() : %d\n\r"), error));

    return error;
}


DMA_ERROR DMA_memoryclear(DMA_CH_CONTEXT *pCtxt, unsigned int uiDstAddr, unsigned int uiByteCount)
{

    unsigned int ret = 0;
    BOOL bRet = TRUE;
    pl330_DMA_parameters DMA_Para;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_MemsetZero() : Ch%d in DMAC%d, \n\r"), pCtxt->CH0_7, pCtxt->Controller));

    if (pCtxt->bValid == FALSE)
    {
        ERRMSG((_T("[DMA:ERR] DMA_MemsetZero() : Invalid DMA_CH_CONTEXT\n\r")));
        bRet = FALSE;
        goto CleanUp;
    }

    pCtxt->DstAddr = uiDstAddr;
    pCtxt->TransferCnt = uiByteCount;

    pCtxt->CtrlReg_4Byte.uSI = INCREASE;
    pCtxt->CtrlReg_4Byte.uSBSize = DWORD_UNIT ;
    pCtxt->CtrlReg_4Byte.uSBLength= 0xf;
    pCtxt->CtrlReg_4Byte.uSCache = 0;

    if(pCtxt->ProtectionBit == NON_SECURE)
        pCtxt->CtrlReg_4Byte.uSProt = 2;
    else if(pCtxt->ProtectionBit == SECURE)
        pCtxt->CtrlReg_4Byte.uSProt = 0;

    pCtxt->CtrlReg_4Byte.uDI = INCREASE;
    pCtxt->CtrlReg_4Byte.uDBSize = DWORD_UNIT ;
    pCtxt->CtrlReg_4Byte.uDBLength= 0xf;
    pCtxt->CtrlReg_4Byte.uDCache = 0;
    pCtxt->CtrlReg_4Byte.uESSize = 0;

    if(pCtxt->ProtectionBit == NON_SECURE)
        pCtxt->CtrlReg_4Byte.uDProt = 2;
    else if(pCtxt->ProtectionBit == SECURE)
        pCtxt->CtrlReg_4Byte.uDProt = 0;

    DMA_Para.mBaseController = (unsigned long)pCtxt->Controller;
    DMA_Para.mDirection =(unsigned long) MEM_TO_MEM;
    DMA_Para.mSrcAddr = (unsigned long)pCtxt->SrcAddr;
    DMA_Para.mDstAddr =(unsigned long) pCtxt->DstAddr;
    DMA_Para.mTrSize =(unsigned long) pCtxt->TransferCnt;
    DMA_Para.mControl = pCtxt->CtrlReg_4Byte;
    DMA_Para.mPeriNum =(unsigned long) pCtxt->PeriNum;
    DMA_Para.mBwJump = pCtxt->CodeOffset;
    DMA_Para.mIrqEnable = 1;
    DMA_Para.mLastReq = TRUE;
    DMA_Para.mLoop = 0;
    DMA_Para.mMemoryClear = TRUE;


    pCtxt->CodeOffset = 0;

    ret = setup_DMA_channel((u8 *)(pCtxt->CodeStAddr + pCtxt->CodeOffset), DMA_Para, pCtxt->CH0_7);

    pCtxt->CodeOffset += ret;


CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_MemsetZero() : %d\n\r"), bRet));

    return bRet;
}

DMA_ERROR DMA_get_current_channel_sourceaddress(DMA_CH_CONTEXT *pCtxt,unsigned int p_uiBaseSrcAddr,
unsigned int* p_uiSrcAddr, unsigned int* p_curBufCount)
{

    DMA_ERROR error = DMA_SUCCESS;
    volatile DMAC_REG *pDMACReg ;
    int result;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_get_current_channel_sourceaddress() : Ch%d in DMAC%d\n\r"), pCtxt->CH0_7, pCtxt->Controller));

    if (pCtxt->bValid == FALSE)
    {
        ERRMSG((_T("[DMA:ERR] DMA_get_current_channel_sourceaddress() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }


     pDMACReg = (DMAC_REG *)pCtxt->BaseAddr;

    *p_uiSrcAddr = pDMACReg->CHStatus[pCtxt->CH0_7].SrcAddr;//SrcAddr

    result = ((*p_uiSrcAddr)&(~(pCtxt->TransferCnt-1))) - p_uiBaseSrcAddr;

    if (0 > result)
    {
        ERRMSG((_T("[DMA:ERR] DMA_get_current_channel_sourceaddress() : Invalid size of buffer\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }
    else
    {
        *p_curBufCount = result/pCtxt->TransferCnt;
    }

CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_get_current_channel_sourceaddress() : %d\n\r"), error));

    return error;
}


DMA_ERROR DMA_get_current_channel_destaddress(DMA_CH_CONTEXT *pCtxt,unsigned int p_uiBaseDestAddr,
unsigned int* p_uiDestAddr, unsigned int* p_curBufCount)
{

    DMA_ERROR error = DMA_SUCCESS;
    volatile DMAC_REG *pDMACReg ;
    //int result;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_get_current_channel_destaddress() : Ch%d in DMAC%d\n\r"), pCtxt->CH0_7, pCtxt->Controller));

    if (pCtxt->bValid == FALSE)
    {
        ERRMSG((_T("[DMA:ERR] DMA_get_current_channel_sourceaddress() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }


     pDMACReg = (DMAC_REG *)pCtxt->BaseAddr;

    *p_uiDestAddr = pDMACReg->CHStatus[pCtxt->CH0_7].DstAddr;//SrcAddr

#if 0
    result = ((*p_uiDestAddr)&(~(pCtxt->TransferCnt-1))) - p_uiBaseDestAddr;

    if (0 > result)
    {
        ERRMSG((_T("[DMA:ERR] DMA_get_current_channel_sourceaddress() : Invalid size of buffer\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }
    else
    {
        *p_curBufCount = result/pCtxt->TransferCnt;
    }
#else
	*p_curBufCount = (*p_uiDestAddr) - p_uiBaseDestAddr;

    if (0 > p_curBufCount)
    {
        ERRMSG((_T("[DMA:ERR] DMA_get_current_channel_sourceaddress() : Invalid size of buffer\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }
#endif     

CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_get_current_channel_sourceaddress() : %d\n\r"), error));

    return error;
}

DMA_ERROR DMA_set_channel_source(DMA_CH_CONTEXT *pCtxt, unsigned int uiSrcAddr, TRANSFER_UNIT Unit, BURST_SIZE Burst, ADDRESS_UPDATE Update)
{
    DMA_ERROR error = DMA_SUCCESS;
    UINT32 uBWidth;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_set_channel_source() : Ch%d in DMAC%d (0x%08x, %d, %d, %d)\n\r"), pCtxt->CH0_7, pCtxt->Controller, uiSrcAddr, Unit, Burst, Update));

    if (pCtxt->bValid == FALSE)
    {
        ERRMSG((_T("[DMA:ERR] DMA_set_channel_source() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }

    pCtxt->SrcAddr = uiSrcAddr ;

    switch(Unit)
    {
    case BYTE_UNIT: case HWORD_UNIT: case WORD_UNIT: case DWORD_UNIT:
        pCtxt->SrcUnit = Unit;
        break;
    default:
        ERRMSG((_T("[DMA:ERR] DMA_set_channel_source() : Unknown Transfer Unit [%d]\n\r"), Unit));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
        break;
    }

    switch(Burst)
    {
    case BURST_1:    case BURST_4:    case BURST_8:    case BURST_16:
    case BURST_32:    case BURST_64:    case BURST_128:    case BURST_256:
        pCtxt->SrcBurst = Burst;
        break;
    default:
        ERRMSG((_T("[DMA:ERR] DMA_set_channel_source() : Unknown Burst Size [%d]\n\r"), Burst));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
        break;
    }

    switch(Update)
    {
    case INCREASE: case FIXED:
        pCtxt->SrcUpdate = Update;
        break;
    default:
        ERRMSG((_T("[DMA:ERR] DMA_set_channel_source() : Unknown Address Update [%d]\n\r"), Update));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
        break;
    }


    switch(pCtxt->SrcBurst) // Source burst length 1~16
    {
        case BURST_1   : uBWidth=0x0;break;
        case BURST_4   : uBWidth=0x3;break;
        case BURST_8   : uBWidth=0x7;break;
        case BURST_16  : uBWidth=0xf;break;
        case BURST_16X2 : uBWidth=0xf;break;
        default :
        ERRMSG((_T("[DMA:ERR] DMA_set_channel_source() : Unknown Src Burst Size [%d]\n\r"), pCtxt->SrcBurst));
        goto CleanUp;
            break;
    }


    pCtxt->CtrlReg_4Byte.uSI = pCtxt->SrcUpdate;
    pCtxt->CtrlReg_4Byte.uSBSize = pCtxt->SrcUnit ;
    pCtxt->CtrlReg_4Byte.uSBLength= uBWidth;
    pCtxt->CtrlReg_4Byte.uSCache = 0;

    if(pCtxt->ProtectionBit == NON_SECURE)
        pCtxt->CtrlReg_4Byte.uSProt = 2;
    else if(pCtxt->ProtectionBit == SECURE)
        pCtxt->CtrlReg_4Byte.uSProt = 0;

CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_set_channel_source() : %d\n\r"), error));

    return error;
}

DMA_ERROR DMA_set_channel_destination(DMA_CH_CONTEXT *pCtxt, unsigned int uiDstAddr, TRANSFER_UNIT Unit, BURST_SIZE Burst, ADDRESS_UPDATE Update)
{

    DMA_ERROR error = DMA_SUCCESS;
        UINT32 uBWidth;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_set_channel_destnation() : Ch%d in DMAC%d (0x%08x, %d, %d, %d)\n\r"), pCtxt->CH0_7, pCtxt->Controller, uiDstAddr, Unit, Burst, Update));

    if (pCtxt->bValid == FALSE)
    {
        ERRMSG((_T("[DMA:ERR] DMA_set_channel_destnation() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }

   pCtxt->DstAddr = uiDstAddr;

    switch(Unit)
    {
    case BYTE_UNIT: case HWORD_UNIT: case WORD_UNIT: case DWORD_UNIT:
        pCtxt->DstUnit = Unit;
        break;
    default:
        ERRMSG((_T("[DMA:ERR] DMA_set_channel_destnation() : Unknown Transfer Unit [%d]\n\r"), Unit));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
        break;
    }

    switch(Burst)
    {
    case BURST_1:    case BURST_4:    case BURST_8:    case BURST_16: case BURST_16X2:
    case BURST_32:    case BURST_64:    case BURST_128:    case BURST_256:
        pCtxt->DstBurst = Burst;
        break;
    default:
        ERRMSG((_T("[DMA:ERR] DMA_set_channel_destnation() : Unknown Burst Size [%d]\n\r"), Burst));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
        break;
    }

    switch(Update)
    {
    case INCREASE: case FIXED:
        pCtxt->DstUpdate = Update;
        break;
    default:
        ERRMSG((_T("[DMA:ERR] DMA_set_channel_destnation() : Unknown Address Update [%d]\n\r"), Update));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
        break;
    }


    switch(pCtxt->DstBurst) // Destination burst length 1~16
    {
        case BURST_1   : uBWidth=0x0;break;
        case BURST_4   : uBWidth=0x3;break;
        case BURST_8   : uBWidth=0x7;break;
        case BURST_16  : uBWidth=0xf;break;
        case BURST_16X2 : uBWidth=0xf;break;
        default :
        ERRMSG((_T("[DMA:ERR] DMA_set_channel_Destination() : Unknown Dst Burst Size [%d]\n\r"), pCtxt->DstBurst));
        goto CleanUp;
            break;
    }

    pCtxt->CtrlReg_4Byte.uDI = pCtxt->DstUpdate;
    pCtxt->CtrlReg_4Byte.uDBSize = pCtxt->DstUnit ;
    pCtxt->CtrlReg_4Byte.uDBLength= uBWidth;
    pCtxt->CtrlReg_4Byte.uDCache = 0;
    pCtxt->CtrlReg_4Byte.uESSize = 0;

    if(pCtxt->ProtectionBit == NON_SECURE)
        pCtxt->CtrlReg_4Byte.uDProt = 2;
    else if(pCtxt->ProtectionBit == SECURE)
        pCtxt->CtrlReg_4Byte.uDProt = 0;


CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_set_channel_destnation() : %d\n\r"), error));

    return error;
}

DMA_ERROR DMA_set_channel_transfer_size(DMA_CH_CONTEXT *pCtxt, unsigned int uiByteCount)
{

    DMA_ERROR error = DMA_SUCCESS;


    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_set_channel_transfer_size() : Ch%d in DMAC%d (ByteCount : %d)\n\r"), pCtxt->CH0_7, pCtxt->Controller, uiByteCount));

    if (pCtxt->bValid == FALSE)
    {
        ERRMSG((_T("[DMA:ERR] DMA_set_channel_transfer_size() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }

    // Check size according to controller, sepecially M2M
    pCtxt->TransferCnt = uiByteCount; //Total Tx Count


CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_set_channel_transfer_size() : %d\n\r"), error));

    return error;
}



DMA_ERROR DMA_initialize_LLI(DMA_CH_CONTEXT *pCtxt, int iLLICount)
{
    DMA_ERROR error = DMA_SUCCESS;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_initialize_LLI() : Ch%d in DMAC%d (%d)\n\r"), pCtxt->CH0_7, pCtxt->Controller, iLLICount));

    if (pCtxt->bValid == FALSE)
    {
        ERRMSG((_T("[DMA:ERR] DMA_initialize_LLI() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }

    if (iLLICount == 0 || iLLICount > MAX_LLI_ENTRY)
    {
        ERRMSG((_T("[DMA] DMA_initialize_LLI() : LLICount [%d] Out of Range \n\r"), pCtxt->LLICount));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }

    pCtxt->LLICount = iLLICount;

CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_initialize_LLI() : %d\n\r"), error));

    return error;
}

DMA_ERROR DMA_set_LLI_entry(DMA_CH_CONTEXT *pCtxt, int iEntryNumber, LLI_NEXT_ITEM NextItem, unsigned int uiSrcAddr, unsigned int uiDstAddr, unsigned int uiByteCount)

{
    DMA_ERROR error = DMA_SUCCESS;
    unsigned int ret = 0;
    pl330_DMA_parameters DMA_Para;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_set_LLI_entry() : Ch%d in DMAC%d (%d, %d, 0x%08x, 0x%08x, %d)\n\r"), pCtxt->CH0_7, pCtxt->Controller, iEntryNumber, NextItem, uiSrcAddr, uiDstAddr, uiByteCount));

    if (pCtxt->bValid == FALSE)
    {
        ERRMSG((_T("[DMA:ERR] DMA_set_LLI_entry() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }

    if (iEntryNumber > pCtxt->LLICount-1)
    {
        ERRMSG((_T("[DMA:ERR] DMA_set_LLI_entry() : LLI Entry exceed Maximum Entry Number (%d > %d)\n\r"), iEntryNumber, pCtxt->LLICount-1));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }

    pCtxt->SrcAddr = uiSrcAddr ;
    pCtxt->DstAddr = uiDstAddr;
    pCtxt->TransferCnt = uiByteCount;

    DMA_Para.mBaseController = (unsigned long)pCtxt->Controller;
    DMA_Para.mDirection =(unsigned long) pCtxt->Dir;
    DMA_Para.mSrcAddr = (unsigned long)pCtxt->SrcAddr;
    DMA_Para.mDstAddr =(unsigned long) pCtxt->DstAddr;
    DMA_Para.mTrSize =(unsigned long) pCtxt->TransferCnt;
    DMA_Para.mControl = pCtxt->CtrlReg_4Byte;
    DMA_Para.mPeriNum =(unsigned long) pCtxt->PeriNum;
    DMA_Para.mBwJump = pCtxt->CodeOffset;
    DMA_Para.mIrqEnable = 1;
    DMA_Para.mMemoryClear = FALSE;

    if(NextItem == LLI_FIRST_ENTRY){ //Last LLI

        if(pCtxt->LLICount == 1) //one LLI
        {
            DMA_Para.mLastReq = TRUE;
            DMA_Para.mLoop = 0;
        }
        else
        {
            DMA_Para.mLastReq = TRUE;
            DMA_Para.mLoop = 1;
        }
    }
    else{
        DMA_Para.mLastReq = FALSE;
        DMA_Para.mLoop = 0;
    }

    if(!iEntryNumber) //first LLI Entry
        pCtxt->CodeOffset = 0;


    ret = setup_DMA_channel((u8 *)(pCtxt->CodeStAddr + pCtxt->CodeOffset), DMA_Para, pCtxt->CH0_7);


    pCtxt->CodeOffset += ret;

CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_set_LLI_entry() : %d\n\r"), error));

    return error;
}


DMA_ERROR DMA_channel_start(DMA_CH_CONTEXT *pCtxt)
{
    DMA_ERROR error = DMA_SUCCESS;
   unsigned int ret =0;
    volatile DMAC_REG *pDMACReg ;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_channel_start() : Ch%d in DMAC%d : ControlRegAddr : 0x%08x\n\r"), pCtxt->CH0_7, pCtxt->Controller,pCtxt->BaseAddr));

    if (pCtxt->bValid == FALSE)
    {
        ERRMSG((_T("[DMA:ERR] DMA_channel_start() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }


    DMA_lock();

    pDMACReg = (DMAC_REG *)pCtxt->BaseAddr;

    start_DMA_channel((u32 *)(&pDMACReg->DbgStatus), pCtxt->CH0_7,(u8 *)pCtxt->CodePhysicalStAddr.LowPart,pCtxt->ProtectionBit);


    DMA_unlock();

CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_channel_start() : %d\n\r"), error));

    return error;
}


DMA_ERROR DMA_channel_stop(DMA_CH_CONTEXT *pCtxt)
{
    DMA_ERROR error = DMA_SUCCESS;
    volatile DMAC_REG *pDMACReg ;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_channel_stop() : Ch%d in DMAC%d\n\r"), pCtxt->CH0_7, pCtxt->Controller));

    if (pCtxt->bValid == FALSE)
    {
        ERRMSG((_T("[DMA:ERR] DMA_channel_stop() : Invalid DMA_CH_CONTEXT\n\r")));
        error = DMA_ERROR_ILLEGAL_PARAMETER;
        goto CleanUp;
    }



    DMA_lock();


    pDMACReg = (DMAC_REG *)pCtxt->BaseAddr;

    stop_DMA_channel((u32 *)(&pDMACReg->DbgStatus) ,(int) pCtxt->CH0_7);


    DMA_unlock();



CleanUp:

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_channel_stop() : %d\n\r"), error));

    return error;
}



void DMA_set_interrupt_mask(DMA_CH_CONTEXT *pCtxt) //Interrupt Disable
{
    volatile DMAC_REG *pDMACReg ;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_set_interrupt_mask() : %d\n\r"), pCtxt->CH0_7));

    pDMACReg = (DMAC_REG *)pCtxt->BaseAddr;

    pDMACReg->IntEnable &= ~(1<<pCtxt->CH0_7);
	
    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_set_interrupt_mask() \n\r")));
	

}

void DMA_clear_interrupt_mask(DMA_CH_CONTEXT *pCtxt) //Interrupt Enable
{

    volatile DMAC_REG *pDMACReg ;

    DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_clear_interrupt_mask() : %d\n\r"), pCtxt->CH0_7));

     pDMACReg = (DMAC_REG *)pCtxt->BaseAddr;

      pDMACReg->IntEnable |= (1<<pCtxt->CH0_7);

    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_clear_interrupt_mask() \n\r")));	  
}

void DMA_clear_interrupt_pending(DMA_CH_CONTEXT *pCtxt)
{
    volatile DMAC_REG *pDMACReg ;

     DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_clear_interrupt_pending() : %d\n\r"), pCtxt->CH0_7));

     pDMACReg = (DMAC_REG *)pCtxt->BaseAddr;

     pDMACReg->IntClear = 1<<pCtxt->CH0_7;

     DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_clear_interrupt_pending() \n\r")));	 

}
void DMA_check_interrupt_pending(DMA_CH_CONTEXT *pCtxt)
{
    volatile DMAC_REG *pDMACReg ;
    volatile UINT32 TimeOutCount;


     DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_Check_interrupt_pending() : %d\n\r"), pCtxt->CH0_7));

     pDMACReg = (DMAC_REG *)pCtxt->BaseAddr;

     TimeOutCount = 10000000L;
 
	do{
		 if(pDMACReg->IntStatus & (1 << pCtxt->CH0_7)){
	            DMA_clear_interrupt_pending(pCtxt);
       	     break;
		}
		 if(TimeOutCount-- == 0){
		        ERRMSG((_T("[DMA] DMA_check_interrupt_pending() : TimeOut Error\n\r")));
		 	break;
		 	}
        }while(1);
		


    DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_Check_interrupt_pending() : %d\n\r"), pCtxt->CH0_7));
}


static BOOL DMA_lock(void)
{
    DWORD dwRet;

     DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_lock\n\r")));
    dwRet = WaitForSingleObject(g_hMutex, INFINITE);
    if (dwRet != WAIT_OBJECT_0)
    {
        ERRMSG((_T("[DMA] DMA_lock() : WaitForSingleObject() Failed\n\r")));
        return FALSE;
    }

     DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_lock\n\r")));
    return TRUE;
}

static BOOL DMA_unlock(void)
{
    BOOL bRet;

	     DBGMSG(DMA_FUNC,(_T("[DMA]++DMA_unlock\n\r")));

    bRet = ReleaseMutex(g_hMutex);
    if (bRet == FALSE)
    {
        ERRMSG((_T("[DMA] DMA_unlock() : ReleaseMutex() Failed\n\r")));
        return FALSE;
    }

	     DBGMSG(DMA_FUNC,(_T("[DMA]--DMA_unlock\n\r")));
    return TRUE;
}

