

#define WINCE 1

#ifdef WINCE
#include <windows.h>
#include <CEDDK.h>
#include <bsp_cfg.h>
#include <drvmsg.h> 
#include "dma_controller.h"
#endif
#define    PL330_DMA_DEBUG
#undef    PL330_DMA_DEBUG

#ifdef LINUX
#ifdef PL330_DMA_DEBUG
#define dma_debug(fmt...) printk( fmt)
#else
#define dma_debug(fmt...)
#endif
#define print_warning(fmt...) printk( fmt)
#else

#endif

typedef unsigned long    u32;
typedef    unsigned char    u8;
typedef unsigned char bool;


#define PL330_P2M_DMA            0
#define PL330_M2P_DMA            1
#define PL330_M2M_DMA            2
#define PL330_P2P_DMA            3

#define    PL330_MAX_ITERATION_NUM        256
#define    PL330_MAX_JUMPBACK_NUM        256
#define    PL330_MAX_EVENT_NUM        32
#define    PL330_MAX_PERIPHERAL_NUM    32
#define    PL330_MAX_CHANNEL_NUM        8


#define DMA_DBGSTATUS            0x0
#define DMA_DBGCMD            0x1
#define DMA_DBGINST0            0x2
#define DMA_DBGINST1            0x3


#define memOutp8(addr, data) (*(volatile u8 *)(addr) = (data))
#define Outp32(addr, data)    (*(volatile u32 *)(addr) = (data))
#define Inp32(addr, data) (data = (*(volatile u32 *)(addr)))






static int config_DMA_control(u8 * mcode_ptr, pl330_dma_control dmacon);
static int register_irq_to_DMA_channel(u8 * mcode_ptr, int uEventNum);
static int config_DMA_set_infinite_loop(u32 * mcode_ptr, int uBwJump);
static int config_DMA_mark_end(u8 * mcode_ptr) ;


/*---------------------- Primitive functions -------------*/
/* DMAMOV CCR, ...  */
static int encodeDmaMoveChCtrl(u8 * mcode_ptr, u32 dmacon)
{
    u8 uInsBytes[6];
    u32 i;

    uInsBytes[0] = (u8)(0xbc);
    uInsBytes[1] = (u8)(0x1);
    uInsBytes[2] = (u8)((dmacon>>0)&0xff);
    uInsBytes[3] = (u8)((dmacon>>8)&0xff);
    uInsBytes[4] = (u8)((dmacon>>16)&0xff);
    uInsBytes[5] = (u8)((dmacon>>24)&0xff);

    for(i=0; i<6; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }
    //mcode_ptr += 6;
    return 6;
}
/* DMAMOV SAR, uStAddr
 * DMAMOV DAR, uStAddr   */
static int encodeDmaMove(u8 * mcode_ptr, u8 uDir, u32 uStAddr)
{
    u8 uInsBytes[6];
        u32 i;

    uInsBytes[0] = (u8)(0xbc);
    uInsBytes[1] = (u8)(0x0|uDir);
    uInsBytes[2] = (u8)((uStAddr>>0)&0xff);
    uInsBytes[3] = (u8)((uStAddr>>8)&0xff);
    uInsBytes[4] = (u8)((uStAddr>>16)&0xff);
    uInsBytes[5] = (u8)((uStAddr>>24)&0xff);

    for(i=0; i<6; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 6;
}


/* DMALD, DMALDS, DMALDB  */
static int encodeDmaLoad(u8 * mcode_ptr)
{
    u8 bs=0;
    u8 x=0;
    u8 uInsBytes[1];
    u32 i;

    uInsBytes[0] = (u8)(0x04|(bs<<1)|(x<<0));

    for(i=0; i<1; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 1;
}

/* DMALDPS, DMALDPB (Load Peripheral)  */
static int encodeDmaLoadPeri(u8 * mcode_ptr, u8 mPeriNum)
{
    u8 bs;
    u8 uInsBytes[2];
    u32 i;

    bs = 0; // single -> 0, burst -> 1

    if(mPeriNum > PL330_MAX_PERIPHERAL_NUM) {
#ifdef WINCE
        ERRMSG((_T("The peripheral number is too big ! : %d\n\r"),mPeriNum));
#else
        print_warning("[%s] The peripheral number is too big ! : %d\n", __FUNCTION__, mPeriNum);
#endif
        return 0;
    }

    uInsBytes[0] = (u8)(0x25|(bs<<1));
    uInsBytes[1] = (u8)(0x00|((mPeriNum&0x1f)<<3));

    for(i=0; i<2; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 2;
}

/* DMAST, DMASTS, DMASTB  */
static int encodeDmaStore(u8 * mcode_ptr)
{
    u8 bs=0;
    u8 x=0;
    u8 uInsBytes[1];
    u32 i;
  /*
    if (m_eDir == DMA_M2M)
    {
        bs=0; x=0;
    }
    else if ((m_eDir == DMA_P2M) && (m_uBurstSz == 1)) // single transfer only
    {
        bs=0; x=1;
    }
    else if ((m_eDir == DMA_P2M) && (m_uBurstSz != 1)) // burst transfer only
    {
        bs=1; x=1;
    }
    else
    {
        Assert(0);
    }
*/
    uInsBytes[0] = (u8)(0x08|(bs<<1)|(x<<0));

    for(i=0; i<1; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 1;
}

/* DMASTPS, DMASTPB (Store and notify Peripheral)  */
static int encodeDmaStorePeri(u8 * mcode_ptr, u8 mPeriNum)
{
    u8 bs;
    u8 uInsBytes[2];
    u32 i;

    bs = 0; // single -> 0, burst -> 1

    if(mPeriNum > PL330_MAX_PERIPHERAL_NUM) {
#ifdef WINCE
        ERRMSG((_T("The peripheral number is too big ! : %d\n\r"),mPeriNum));
#else
        print_warning("[%s] The peripheral number is too big ! : %d\n", __FUNCTION__, mPeriNum);
#endif
        return 0;
    }

    uInsBytes[0] = (u8)(0x29|(bs<<1));
    uInsBytes[1] = (u8)(0x00|((mPeriNum&0x1f)<<3));

    for(i=0; i<2; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 2;
}

/* DMASTZ  */
static int encodeDmaStoreZero(u8 * mcode_ptr)
{
    u8 uInsBytes[1];
    u32 i;

    uInsBytes[0] = (u8)(0x0c);

    for(i=0; i<1; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 1;
}

/* DMALP  */
static int encodeDmaLoop(u8 * mcode_ptr, u8 uLoopCnt, u8 uIteration)
{
    u8 uInsBytes[2];
    u32 i;
    if(uIteration > PL330_MAX_ITERATION_NUM) {
#ifdef WINCE
        ERRMSG((_T("The iteration number is too big ! : %d\n\r"),uIteration));
#else
        print_warning("[%s] The iteration number is too big ! : %d\n", __FUNCTION__, uIteration);
#endif
        return 0;
    }

    uInsBytes[0] = (u8)(0x20|(uLoopCnt<<1));
    uInsBytes[1] = (u8)(uIteration);

    for(i=0; i<2; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 2;

}

/* DMALPFE  */
static int encodeDmaLoopForever(u8 * mcode_ptr, u8 uBwJump)
{
    u8 bs=0;
    u8 x=0;
    u8 uInsBytes[2];
    u32 i;

    if(uBwJump > PL330_MAX_JUMPBACK_NUM) {
#ifdef WINCE
        ERRMSG((_T("The address to jump to is too far \n\r")));
#else
        print_warning("[%s] The address to jump to is too far ! : %d\n", __FUNCTION__, uBwJump);
#endif
        return 0;
    }


/*
    if (m_eDir == DMA_M2M)
    {
        bs=0; x=0;
    }
    else if (m_uBurstSz == 1) // single transfer only
    {
        /// temp bs=0; x=1;
        bs=0; x=0;
    }
    else if (m_uBurstSz != 1) // burst transfer only
    {
        bs=1; x=1;
    }
    else
    {
        dma_debug(0);
    }
*/
    uInsBytes[0] = (u8)(0x28|(0<<4)|(0<<2)|(bs<<1)|x);
    uInsBytes[1] = (u8)(uBwJump);

    for(i=0; i<2; i++)
    {
        memOutp8(mcode_ptr + i, uInsBytes[i]);
    }

    return 2;
}

/* DMALPEND, DMALPENDS, DMALPENDB  */
static int encodeDmaLoopEnd(u8 * mcode_ptr, u8 uLoopCnt, u8 uBwJump)
{
    u8 bs=0;
    u8 x=0;
    u8 uInsBytes[2];
    u32 i;
    if(uBwJump > PL330_MAX_JUMPBACK_NUM) {
#ifdef WINCE
        ERRMSG((_T("The address to jump to is too far \n\r")));
#else
        print_warning("[%s] The address to jump to is too far !\n", __FUNCTION__);
#endif
        return 0;
    }
    //dma_debug(uLoopCnt < 2); // Lc0 or Lc1

/*
    if (m_eDir == DMA_M2M)
    {
        bs=0; x=0;
    }
    else if (m_uBurstSz == 1) // single transfer only
    {
        /// temp bs=0; x=1;
        bs=0; x=0;
    }
    else if (m_uBurstSz != 1) // burst transfer only
    {
        bs=1; x=1;
    }
    else
    {
        dma_debug(0);
    }
*/
    uInsBytes[0] = (u8)(0x38|(1<<4)|(uLoopCnt<<2)|(bs<<1)|x);
    uInsBytes[1] = (u8)(uBwJump);

    for(i=0; i<2; i++)
    {
        memOutp8(mcode_ptr + i, uInsBytes[i]);
    }

    return 2;
}

/*  DMAWFP, DMAWFPS, DMAWFPB (Wait For Peripheral) */
static int encodeDmaWaitForPeri(u8 * mcode_ptr, u8 mPeriNum)
{
    u8 bs=0;
    u8 p=0;
    u8 uInsBytes[2];
        u32 i;

    if(mPeriNum > PL330_MAX_PERIPHERAL_NUM) {
#ifdef WINCE
        ERRMSG((_T("The peripheral number is too big ! : %d\n\r"),mPeriNum));
#else
        print_warning("[%s] The peripheral number is too big ! : %d\n", __FUNCTION__, mPeriNum);
#endif
        return 0;
    }
/*
    if (m_uBurstSz == 1) // single transfer only
    {
        bs=0; p=0;
    }
    else if (m_uBurstSz != 1) // burst transfer only
    {
        bs=1; p=0;
    }
    else // both single transfer and burst one
    {
        bs=0; p=1;
    }
*/
    uInsBytes[0] = (u8)(0x30|(bs<<1)|p);
    uInsBytes[1] = (u8)(0x00|((mPeriNum&0x1f)<<3));

    for(i=0; i<2; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 2;
}

/* DMAWFE (Wait For Event) */
static int encodeDmaWaitForEvent(u8 * mcode_ptr, u8 uEventNum) // 0~31
{
    u8 uInsBytes[2];
    u32 i;

    if(uEventNum > PL330_MAX_EVENT_NUM) {
#ifdef WINCE
        ERRMSG((_T("The uEventNum number is too big ! : %d\n\r"),uEventNum));
#else
        print_warning("[%s] The uEventNum number is too big ! : %d\n", __FUNCTION__, uEventNum);
#endif
        return 0;
    }

    uInsBytes[0] = (u8)(0x36);
    uInsBytes[1] = (u8)((uEventNum<<3)|0x2); // for cache coherency, invalid is issued.

    for(i=0; i<2; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 2;
}

/*  DMAFLUSHP (Flush and notify Peripheral) */
static int encodeDmaFlushPeri(u8 * mcode_ptr, u8 mPeriNum)
{
    u8 uInsBytes[2];
    u32 i;

    if(mPeriNum > PL330_MAX_PERIPHERAL_NUM) {
#ifdef WINCE
        ERRMSG((_T("The peripheral number is too big ! : %d\n\r"),mPeriNum));
#else
        print_warning("[%s] The peripheral number is too big ! : %d\n", __FUNCTION__, mPeriNum);
#endif
        return 0;
        }
    uInsBytes[0] = (u8)(0x35);
    uInsBytes[1] = (u8)(0x00|((mPeriNum&0x1f)<<3));


    for(i=0; i<2; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 2;
}

/* DMAEND */
static int encodeDmaEnd(u8 * mcode_ptr)
{
    memOutp8(mcode_ptr, 0x00);

    return 1;
}

/* DMAADDH (Add Halfword) */
static int encodeDmaAddHalfword(u8 * mcode_ptr, bool bSrcDir, u32 uStAddr)
{
    u8 uDir = (bSrcDir) ? 0 : 1; /* src addr=0, dst addr=1 */
    u8 uInsBytes[3];
    u32 i;

    uInsBytes[0] = (u8)(0x54|(uDir<<1));
    uInsBytes[1] = (u8)((uStAddr>>0)&0xff);
    uInsBytes[2] = (u8)((uStAddr>>8)&0xff);

    for(i=0; i<3; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 3;
}

/* DMAKILL (Kill) */
static int encodeDmaKill(u8 * mcode_ptr)
{
    u8 uInsBytes[1];
    u32 i;
    uInsBytes[0] = (u8)(0x01);

    for(i=0; i<1; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 1;
}

/* DMANOP (No operation) */
static int encodeDmaNop(u8 * mcode_ptr)
{
    u8 uInsBytes[1];
    u32 i;
    uInsBytes[0] = (u8)(0x18);

    for(i=0; i<1; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 1;
}


/* DMARMB (Read Memory Barrier) */
static int encodeDmaReadMemBarrier(u8 * mcode_ptr)
{
    u8 uInsBytes[1];
    u32 i;
    uInsBytes[0] = (u8)(0x12);

    for(i=0; i<1; i++)
    {
        memOutp8(mcode_ptr+i, uInsBytes[i]);
    }

    return 1;
}

/* DMASEV (Send Event) */
static int encodeDmaSendEvent(u8 * mcode_ptr, u8 uEventNum) // 0~31
{
    u8 uInsBytes[2];
    u32 i;
    uInsBytes[0] = (u8)(0x34);
    uInsBytes[1] = (u8)((uEventNum<<3)|0x0);

    if(uEventNum > PL330_MAX_EVENT_NUM) {
#ifdef WINCE
        ERRMSG((_T("The uEventNum number is too big ! : %d\n\r"),uEventNum));
#else
        print_warning("[%s] The uEventNum number is too big ! : %d\n", __FUNCTION__, uEventNum);
#endif
        return 0;
    }

    for(i=0; i<2; i++)
    {
        memOutp8(mcode_ptr + i, uInsBytes[i]);
    }

    return 2;
}



/* DMAWMB (Write Memory Barrier) */
static int encodeDmaWriteMemBarrier(u8 * mcode_ptr)
{
    u8 uInsBytes[1];
    u32 i;
    uInsBytes[0] = (u8)(0x13);

    for(i=0; i<1; i++)
    {
        memOutp8(mcode_ptr + i, uInsBytes[i]);
    }

    return 1;
}


/* DMAGO over DBGINST0,1 registers */
static void encodeDmaGoOverDBGINST(u32 * mcode_ptr, u8 chanNum, u8 * mbufAddr, u8 m_secureBit)
{
    u32 x;
    u8 uDmaGo;        /* DMAGO instruction */
    u32 	TimeOutCount;

	
    if(chanNum > PL330_MAX_CHANNEL_NUM) {
#ifdef WINCE
        ERRMSG((_T("The Channel number is too big ! : %d\n\r"),chanNum));
#else
        print_warning("[%s] Channel number is too big ! : %d\n", __FUNCTION__, chanNum);
#endif

    }

  TimeOutCount = 10000000L;
  
    do
    {
	if(TimeOutCount-- == 0){
		ERRMSG((_T("[DMA] encodeDmaGoOverDBGINST() : TimeOut Error\n\r")));
		break;
	}
        Inp32(mcode_ptr+DMA_DBGSTATUS, x);
    } while ((x&0x1)==0x1);



     uDmaGo = (m_secureBit!=0) ?
        (0xa0|(0<<1)) : // secure mode
        (0xa0|(1<<1));  // non secure mode

    Outp32(mcode_ptr+DMA_DBGINST0, (chanNum<<24)|(uDmaGo<<16)|(chanNum<<8)|(0<<0));
    Outp32(mcode_ptr+DMA_DBGINST1, (u32)mbufAddr);
    Outp32(mcode_ptr+DMA_DBGCMD, 0); // execute the instruction that the DBGINST0,1 registers contain


}


/* DMAKILL over DBGINST0,1 registers - Stop a DMA channel */
static void encodeDmaKillChannelOverDBGINST(u32 * mcode_ptr, u8 chanNum)
{
    u32 x, TimeOutCount;


    if(chanNum > PL330_MAX_CHANNEL_NUM) {
#ifdef WINCE
        ERRMSG((_T("The Channel number is too big ! : %d\n\r"),chanNum));
#else
        print_warning("[%s] The Channel number is too big ! : %d\n", __FUNCTION__, chanNum);
#endif
    }

  TimeOutCount = 10000000L;
    do
    {

	if(TimeOutCount-- == 0){
		ERRMSG((_T("[DMA] encodeDmaKillChannelOverDBGINST_BEFORE() : TimeOut Error\n\r")));
		break;
	}
        Inp32(mcode_ptr+DMA_DBGSTATUS, x);

    } while ((x&0x1)==0x1);


    Outp32(mcode_ptr+DMA_DBGINST0, (0<<24)|(1<<16)|(chanNum<<8)|(1<<0));    // issue instruction by manager thread
    Outp32(mcode_ptr+DMA_DBGINST1, 0);
    Outp32(mcode_ptr+DMA_DBGCMD, 0); // execute the instruction that the DBGINST0,1 registers contain

   TimeOutCount = 10000000L;
    do
    {
	if(TimeOutCount-- == 0){
		ERRMSG((_T("[DMA] encodeDmaKillChannelOverDBGINST_AFTER() : TimeOut Error\n\r")));
		break;
	}    
        Inp32(mcode_ptr+DMA_DBGSTATUS, x);
    } while ((x&0x1)==0x1);

}

/* DMAKILL over DBGINST0,1 registers - Stop a DMA controller (stop all of the channels) */
static void encodeDmaKillDMACOverDBGINST(u32 * mcode_ptr)
{
    u32 x, TimeOutCount;

    TimeOutCount = 10000000L;
	
    do
    {

	if(TimeOutCount-- == 0){
		ERRMSG((_T("[DMA] encodeDmaKillChannelOverDBGINST_BEFORE() : TimeOut Error\n\r")));
		break;
	}
        Inp32(mcode_ptr+DMA_DBGSTATUS, x);

    } while ((x&0x1)==0x1);


    Outp32(mcode_ptr+DMA_DBGINST0, (0<<24)|(1<<16)|(0<<8)|(0<<0));    // issue instruction by manager thread
    Outp32(mcode_ptr+DMA_DBGINST1, 0);
    Outp32(mcode_ptr+DMA_DBGCMD, 0); // execute the instruction that the DBGINST0,1 registers contain

    TimeOutCount = 10000000L;
    do
    {
	if(TimeOutCount-- == 0){
		ERRMSG((_T("[DMA] encodeDmaKillChannelOverDBGINST_AFTER() : TimeOut Error\n\r")));
		break;
	}    
        Inp32(mcode_ptr+DMA_DBGSTATUS, x);
    } while ((x&0x1)==0x1);

}


/*---------------------- Wrapper functions -------------*/

/* config_DMA_Go_command
 * - make DMA GO command into the Debug Instruction register
 *
 *    mcode_ptr    the pointer to the buffer for PL330 DMA micro code
 *    chanNum        the DMA channel number to be started
 *    mbufAddr    the start address of the buffer for PL330 DMA micro codes
 */
static void config_DMA_GO_command(u32 * mcode_ptr, int chanNum, u8 * mbufAddr, int secureMode)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("config_DMA_GO_command\n\r")));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    encodeDmaGoOverDBGINST(mcode_ptr, (u8)chanNum, mbufAddr, (u8)secureMode);
}


/* config_DMA_stop_channel
 * - stop the DMA channel working on
 *    mcode_ptr    the buffer for PL330 DMAKILL micro code to be stored into
 *    chanNum        the DMA channel number to be stopped
 */
static void config_DMA_stop_channel(u32 * mcode_ptr, int chanNum)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("config_DMA_stop_channel\n\r")));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    encodeDmaKillChannelOverDBGINST(mcode_ptr, (u8)chanNum);
}

/* config_DMA_stop_controller
 * - stop the DMA controller
 *    mcode_ptr    the buffer for PL330 DMAKILL micro code to be stored into
 */
static void config_DMA_stop_controller(u32 * mcode_ptr)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("config_DMA_stop_controller\n\r")));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    encodeDmaKillDMACOverDBGINST(mcode_ptr);
}

/* config_DMA_start_address
 * - set the DMA start address
 *
 *    mcode_ptr    the pointer to the buffer for PL330 DMA micro code
 *    uStAddr        the DMA start address
 */
static int config_DMA_start_address(u8 * mcode_ptr, int uStAddr)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("config_DMA_start_address : 0x%08x\n\r"),uStAddr));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    return encodeDmaMove(mcode_ptr, 0, (u32)uStAddr);
}


/* config_DMA_destination_address
 * - set the DMA destination address
 *
 *    mcode_ptr    the pointer to the buffer for PL330 DMA micro code
 *    uStAddr        the DMA destination address
 */
static int config_DMA_destination_address(u8 * mcode_ptr, int uStAddr)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("config_DMA_destination_address: 0x%08x\n\r"),uStAddr));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    return encodeDmaMove(mcode_ptr, 2, (u32)uStAddr);
}


/* config_DMA_transfer_remainder
 * - set the transfer size of the remainder
 *
 *    mcode_ptr    the pointer to the buffer for PL330 DMA micro code to be stored into
 *    lcRemainder    the remainder except for the LC-aligned transfers
 *    dma_param    the parameter set for a DMA operation
 */

static int config_DMA_transfer_remainder(u8 * mcode_ptr, int lcRemainder,  pl330_DMA_parameters dma_param)
{

    int mcode_size = 0, msize = 0;
    int lc0 = 0, lcSize = 0, mLoopStart0 = 0, dmaSent = 0;


#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("config_DMA_transfer_remainder: 0x%08x\n\r"),mcode_ptr));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif

    dmaSent = dma_param.mTrSize - lcRemainder;

    if(!dma_param.mMemoryClear){
        msize = config_DMA_start_address(mcode_ptr+mcode_size, dma_param.mSrcAddr+dmaSent);
        mcode_size+= msize;
      }

    msize = config_DMA_destination_address(mcode_ptr+mcode_size, dma_param.mDstAddr+dmaSent);
    mcode_size+= msize;

    dma_param.mControl.uSBSize = 0x2;    /* 4 bytes    */
    dma_param.mControl.uSBLength = 0x0;    /* 1 transfer */
    dma_param.mControl.uDBSize = 0x2;    /* 4 bytes    */
    dma_param.mControl.uDBLength = 0x0;    /* 1 transfer */

    msize = config_DMA_control(mcode_ptr+mcode_size, dma_param.mControl);

    mcode_size+= msize;

    lcSize = (dma_param.mControl.uSBLength+1)*(1<<dma_param.mControl.uSBSize);
    lc0 = lcRemainder/lcSize;

    msize = encodeDmaLoop(mcode_ptr+mcode_size, 0, lc0-1);
    mcode_size+= msize;
    mLoopStart0 = mcode_size;

    switch(dma_param.mDirection) {
        case PL330_M2M_DMA:
            if(!dma_param.mMemoryClear){
                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
                    mcode_size+= msize;
                    msize = encodeDmaReadMemBarrier(mcode_ptr+mcode_size);
                    mcode_size+= msize;
                    msize = encodeDmaStore(mcode_ptr+mcode_size);
                    mcode_size+= msize;
                    msize = encodeDmaWriteMemBarrier(mcode_ptr+mcode_size);
                    mcode_size+= msize;					

            }
            else {
                msize = encodeDmaStoreZero(mcode_ptr+mcode_size);
                mcode_size+= msize;
             }
            break;

        case PL330_M2P_DMA:
			if(dma_param.mBaseController == 	DMA_PDMA1)
				{
				if(dma_param.mPeriNum == PERI_MSM_REQ0 || dma_param.mPeriNum == PERI_MSM_REQ1) //MODEM I/F TX
					{
				      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
		                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
		                    mcode_size+= msize;
		                    msize = encodeDmaStorePeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
					}
				else
					{
				      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
		                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
		                    mcode_size+= msize;
		                    msize = encodeDmaStore(mcode_ptr+mcode_size);
		                    mcode_size+= msize;
		                    msize = encodeDmaFlushPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
					}
				}
			else		
				{
			      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
	                    msize = encodeDmaStore(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
	                    msize = encodeDmaFlushPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
				}
            break;

        case PL330_P2M_DMA:
			if(dma_param.mPeriNum == PERI_MSM_REQ2 ||	dma_param.mPeriNum == 	 PERI_MSM_REQ3) // MODEM I/F RX
				{
			      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size,(u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaLoadPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaStore(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
				}
			else
				{
	                    msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size,(u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaLoadPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaStore(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
	                    msize = encodeDmaFlushPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
				}
            break;
        case PL330_P2P_DMA:
#ifdef WINCE
                ERRMSG((_T("P2P DMA selected\n\r")));
#else
                print_warning("[%s] P2P DMA selected !\n", __FUNCTION__);
#endif

            break;

        default:
#ifdef WINCE
                ERRMSG((_T("Invaild DMA direction selected\n\r")));
#else
                print_warning("[%s] Invaild DMA direction selected !\n", __FUNCTION__);
#endif
            break;
    }

    msize = encodeDmaLoopEnd(mcode_ptr+mcode_size, 0, (u8)(mcode_size-mLoopStart0));
    mcode_size+= msize;

    return mcode_size;

}


#ifdef USE_UART_RX_DMA
#define    UART_RX_TRANSFERUNIT       28
static int config_DMA_transfer_size_forUART(u8 * mcode_ptr, pl330_DMA_parameters dma_param)
{
    int mcode_size = 0, msize = 0;
    int lc0 = 0, lc1 = 0, lcRemainder = 0, lcSize = 0;
    int mLoopStart0 = 0, mLoopStart1 = 0;

#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("config_DMA_transfer_size\n\r")));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    switch(dma_param.mDirection) {
        case PL330_M2M_DMA:
            if(dma_param.mTrSize > (8*1024*1024)) {
#ifdef WINCE
                ERRMSG((_T("The chunk size is too big !: %d\n\r"),dma_param.mTrSize));
#else
                print_warning("[%s] The chunk size is too big !: %d\n", __FUNCTION__, dma_param.mTrSize);
#endif
                return 0;
            }
            break;

        case PL330_M2P_DMA:
        case PL330_P2M_DMA:
            if(dma_param.mTrSize > (2*1024*1024)) {
#ifdef WINCE
                ERRMSG((_T("The chunk size is too big !: %d\n\r"),dma_param.mTrSize));
#else
                print_warning("[%s] The chunk size is too big !: %d\n", __FUNCTION__, dma_param.mTrSize);
#endif
                return 0;
            }
            break;

        case PL330_P2P_DMA:
#ifdef WINCE
                ERRMSG((_T("P2P DMA selected\n\r")));
#else
                print_warning("[%s] P2P DMA selected !\n", __FUNCTION__);
#endif

            break;

        default:
#ifdef WINCE
                ERRMSG((_T("Invaild DMA direction selected\n\r")));
#else
                print_warning("[%s] Invaild DMA direction selected !\n", __FUNCTION__);
#endif

            break;
    }


         lcSize = (dma_param.mControl.uSBLength+1)*(1<<dma_param.mControl.uSBSize);	
          lc0= UART_RX_TRANSFERUNIT/lcSize;// UART DMA REQ Tigger level = 32Byte, But  DMA Transfer size = 28Byte
   	   lc1 = dma_param.mTrSize/(UART_RX_TRANSFERUNIT);
      
	        if(lc1 <= PL330_MAX_ITERATION_NUM) {  
                  //ERRMSG((_T("[DMA] Total: %d, lc1: %d, lc0: %d\n\r"),dma_param.mTrSize,lc1,lc0));		
	            msize = encodeDmaLoop(mcode_ptr+mcode_size, 1, lc1-1);
	            mcode_size+= msize;
	            mLoopStart1 = mcode_size;

	            msize = encodeDmaLoop(mcode_ptr+mcode_size, 0, lc0 - 1);
	            mcode_size+= msize;	
	            mLoopStart0 = mcode_size;	                

	            switch(dma_param.mDirection) {
	                case PL330_P2M_DMA:
		                    msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size,(u8)dma_param.mPeriNum);
		                    mcode_size+= msize;		
		                    msize = encodeDmaLoadPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
		                    msize = encodeDmaStore(mcode_ptr+mcode_size);
		                    mcode_size+= msize;
		                    msize = encodeDmaFlushPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
	                    break;

	                default:
				ERRMSG((_T("[DMA] Invaild DMA direction selected\n\r")));
		             break;
	            }

	            msize = encodeDmaLoopEnd(mcode_ptr+mcode_size, 0, (u8)(mcode_size-mLoopStart0));
	            mcode_size+= msize;
                        
	            msize = encodeDmaLoopEnd(mcode_ptr+mcode_size, 1, (u8)(mcode_size-mLoopStart1));
	            mcode_size+= msize;

	        }
	        else {
#ifdef WINCE
	                ERRMSG((_T("The transfer size is over the limit\n\r")));
#else
	                print_warning("The transfer size is over the limit \n");
#endif

	        }

    return mcode_size;
}
#endif //USE_UART_RX_DMA

/* config_DMA_transfer_size
 * - set the transfer size
 *
 *    mcode_ptr    the pointer to the buffer for PL330 DMA micro code
 *    dma_param    the parameter set for a DMA operation
 */
static int config_DMA_transfer_size(u8 * mcode_ptr, pl330_DMA_parameters dma_param)
{
    int mcode_size = 0, msize = 0;
    int lc0 = 0, lc1 = 0, lcRemainder = 0, lcSize = 0;
    int mLoopStart0 = 0, mLoopStart1 = 0;

#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("config_DMA_transfer_size\n\r")));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    switch(dma_param.mDirection) {
        case PL330_M2M_DMA:
            if(dma_param.mTrSize > (32*1024*1024)) {
#ifdef WINCE
                ERRMSG((_T("The chunk size is too big !: %d\n\r"),dma_param.mTrSize));
#else
                print_warning("[%s] The chunk size is too big !: %d\n", __FUNCTION__, dma_param.mTrSize);
#endif
                return 0;
            }
            break;

        case PL330_M2P_DMA:
        case PL330_P2M_DMA:
            if(dma_param.mTrSize > (2*1024*1024)) {
#ifdef WINCE
                ERRMSG((_T("The chunk size is too big !: %d\n\r"),dma_param.mTrSize));
#else
                print_warning("[%s] The chunk size is too big !: %d\n", __FUNCTION__, dma_param.mTrSize);
#endif
                return 0;
            }
            break;

        case PL330_P2P_DMA:
#ifdef WINCE
                ERRMSG((_T("P2P DMA selected\n\r")));
#else
                print_warning("[%s] P2P DMA selected !\n", __FUNCTION__);
#endif

            break;

        default:
#ifdef WINCE
                ERRMSG((_T("Invaild DMA direction selected\n\r")));
#else
                print_warning("[%s] Invaild DMA direction selected !\n", __FUNCTION__);
#endif

            break;
    }


    lcSize = (dma_param.mControl.uSBLength+1)*(1<<dma_param.mControl.uSBSize);

    lc0 = dma_param.mTrSize/lcSize;

    lcRemainder = dma_param.mTrSize - (lc0*lcSize);

    if(lc0 > PL330_MAX_ITERATION_NUM) {
        lc1 = lc0/PL330_MAX_ITERATION_NUM;

        if(lc1 <= PL330_MAX_ITERATION_NUM) {
            msize = encodeDmaLoop(mcode_ptr+mcode_size, 1, lc1-1);
            mcode_size+= msize;
            mLoopStart1 = mcode_size;

            msize = encodeDmaLoop(mcode_ptr+mcode_size, 0, PL330_MAX_ITERATION_NUM-1);
            mcode_size+= msize;
            mLoopStart0 = mcode_size;

            switch(dma_param.mDirection) {
                case PL330_M2M_DMA:
                    if(!dma_param.mMemoryClear){
                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
                    mcode_size+= msize;
                    msize = encodeDmaReadMemBarrier(mcode_ptr+mcode_size);
                    mcode_size+= msize;
                    msize = encodeDmaStore(mcode_ptr+mcode_size);
                    mcode_size+= msize;
                    msize = encodeDmaWriteMemBarrier(mcode_ptr+mcode_size);
                    mcode_size+= msize;										
                    }
                    else
                        {
                        msize = encodeDmaStoreZero(mcode_ptr+mcode_size);
                        mcode_size+= msize;
                        }
                    break;

                case PL330_M2P_DMA:
			if(dma_param.mBaseController == 	DMA_PDMA1)
				{
				if(dma_param.mPeriNum == PERI_MSM_REQ0 || dma_param.mPeriNum == PERI_MSM_REQ1) //MODEM I/F TX
					{
				      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
		                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
		                    mcode_size+= msize;
		                    msize = encodeDmaStorePeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
					}
				else
					{
				      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
		                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
		                    mcode_size+= msize;
		                    msize = encodeDmaStore(mcode_ptr+mcode_size);
		                    mcode_size+= msize;
		                    msize = encodeDmaFlushPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
					}
				}
			else		
				{
			      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
	                    msize = encodeDmaStore(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
	                    msize = encodeDmaFlushPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
				}
                    break;

                case PL330_P2M_DMA:
			if(dma_param.mPeriNum == PERI_MSM_REQ2 ||	dma_param.mPeriNum == 	 PERI_MSM_REQ3) // MODEM I/F RX
				{
			      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size,(u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaLoadPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaStore(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
				}
			else
				{
	                    msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size,(u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaLoadPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaStore(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
	                    msize = encodeDmaFlushPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
				}
                    break;

                case PL330_P2P_DMA:
#ifdef WINCE
                    ERRMSG((_T("P2P DMA selected\n\r")));
#else
                    print_warning("[%s] P2P DMA selected !\n", __FUNCTION__);
#endif
                    break;

                default:
#ifdef WINCE
                    ERRMSG((_T("Invaild DMA direction selected\n\r")));
#else
                    print_warning("[%s] Invaild DMA direction selected !\n", __FUNCTION__);
#endif
                    break;
            }

            msize = encodeDmaLoopEnd(mcode_ptr+mcode_size, 0, (u8)(mcode_size-mLoopStart0));
            mcode_size+= msize;

            msize = encodeDmaLoopEnd(mcode_ptr+mcode_size, 1, (u8)(mcode_size-mLoopStart1));
            mcode_size+= msize;

            lc0 = lc0 - (lc1*PL330_MAX_ITERATION_NUM);
        }
        else {
#ifdef WINCE
                ERRMSG((_T("The transfer size is over the limit\n\r")));
#else
                print_warning("The transfer size is over the limit \n");
#endif

        }
    }

    if(lc0 > 0 ) {
        msize = encodeDmaLoop(mcode_ptr+mcode_size, 0, lc0-1);
        mcode_size+= msize;
        mLoopStart0 = mcode_size;

        switch(dma_param.mDirection) {
            case PL330_M2M_DMA:
                if(!dma_param.mMemoryClear){
                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
                    mcode_size+= msize;
                    msize = encodeDmaReadMemBarrier(mcode_ptr+mcode_size);
                    mcode_size+= msize;
                    msize = encodeDmaStore(mcode_ptr+mcode_size);
                    mcode_size+= msize;
                    msize = encodeDmaWriteMemBarrier(mcode_ptr+mcode_size);
                    mcode_size+= msize;					
                }
                else {
                    msize = encodeDmaStoreZero(mcode_ptr+mcode_size);
                    mcode_size+= msize;
                 }
                break;

            case PL330_M2P_DMA:
			if(dma_param.mBaseController == 	DMA_PDMA1)
				{
				if(dma_param.mPeriNum == PERI_MSM_REQ0 || dma_param.mPeriNum == PERI_MSM_REQ1) //MODEM I/F TX
					{
				      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
		                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
		                    mcode_size+= msize;
		                    msize = encodeDmaStorePeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
					}
				else
					{
				      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
		                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
		                    mcode_size+= msize;
		                    msize = encodeDmaStore(mcode_ptr+mcode_size);
		                    mcode_size+= msize;
		                    msize = encodeDmaFlushPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
		                    mcode_size+= msize;
					}
				}
			else		
				{
			      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaLoad(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
	                    msize = encodeDmaStore(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
	                    msize = encodeDmaFlushPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
				}
                break;

            case PL330_P2M_DMA:
			if(dma_param.mPeriNum == PERI_MSM_REQ2 ||	dma_param.mPeriNum == 	 PERI_MSM_REQ3) // MODEM I/F RX
				{
			      msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size,(u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaLoadPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaStore(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
				}
			else
				{
	                    msize = encodeDmaWaitForPeri(mcode_ptr+mcode_size,(u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaLoadPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
	                    msize = encodeDmaStore(mcode_ptr+mcode_size);
	                    mcode_size+= msize;
	                    msize = encodeDmaFlushPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
	                    mcode_size+= msize;
				}
                break;

            case PL330_P2P_DMA:
#ifdef WINCE
                ERRMSG((_T("P2P DMA selected \n\r")));
#else
                print_warning("[%s] P2P DMA selected !\n", __FUNCTION__);
#endif

                break;

            default:
                break;
        }

        msize = encodeDmaLoopEnd(mcode_ptr+mcode_size, 0, (u8)(mcode_size-mLoopStart0));
        mcode_size+= msize;


    if(lcRemainder !=0) {
        msize = config_DMA_transfer_remainder(mcode_ptr+mcode_size, lcRemainder, dma_param);
        mcode_size += msize;
    }


    if(dma_param.mBaseController == DMA_PDMA1){
		if( dma_param.mPeriNum == PERI_MSM_REQ2 || dma_param.mPeriNum == PERI_MSM_REQ3) //MODEM I/F TX and RX	
   		{
			msize = encodeDmaFlushPeri(mcode_ptr+mcode_size, (u8)dma_param.mPeriNum);
			mcode_size+= msize;
   		}
  	}
    }
	
    return mcode_size;
}


/* config_DMA_control
 * - set the burst length, burst size, source and destination increment/fixed field
 *
 *    mcode_ptr    the pointer to the buffer for PL330 DMA micro code
 *    dmacon        the value for the DMA channel control register
 */

static int config_DMA_control(u8 * mcode_ptr, pl330_dma_control dmacon)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("config_DMA_control\n\r")));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif

    return encodeDmaMoveChCtrl(mcode_ptr, *(u32 *)&dmacon);
}


/* register_irq_to_DMA_channel
 * - register an event with the DMA channel
 *
 *    mcode_ptr    the pointer to the buffer for PL330 DMA micro code
 *    uEventNum    the event number to be assigned to this DMA channel
 */
static int register_irq_to_DMA_channel(u8 * mcode_ptr, int uEventNum)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("register_irq_to_DMA_channel : evnetnum :%d\n\r"),uEventNum));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    return encodeDmaSendEvent(mcode_ptr, (u8)uEventNum);
}

/* config_DMA_set_infinite_loop
 * - set an infinite loop
 *
 *    mcode_ptr    the pointer to the buffer for PL330 DMAPLPEND micro code to be stored into
 *    bBwJump        the relative location of the first instruction in the program loop
 */
static int config_DMA_set_infinite_loop(u32 * mcode_ptr, int uBwJump)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("config_DMA_set_infinite_loop : %d\n\r"),uBwJump));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    return encodeDmaLoopForever((u8 *)mcode_ptr, (u8)uBwJump);
}

/* config_DMA_mark_end
 * - mark the end of the DMA request
 *
 *    mcode_ptr    the pointer to the buffer for PL330 DMA micro code
 */
static int config_DMA_mark_end(u8 * mcode_ptr)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("config_DMA_mark_end\n\r")));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    return encodeDmaEnd(mcode_ptr);
}



/*---------------------- DMA Feature Functions -------------*/

/* start_DMA_controller
 * - start the DMA controller
 *
 */
void start_DMA_controller()
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("start_DMA_controller\n\r")));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
}


/* stop_DMA_controller
 * - stop the DMA controller
 *
 */
void stop_DMA_controller(u32 * mbuf)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("stop_DMA_controller\n\r")));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    config_DMA_stop_controller(mbuf);
}


/* setup_DMA_channel
 * - set up a DMA channel for the DMA operation
 *
 *    mbuf        the buffer address for PL330 DMA micro codes
 *    dma_param    the parameter set for a DMA operation
 *    chanNum        the DMA channel number to be started
 */



int setup_DMA_channel(u8 * mbuf, pl330_DMA_parameters dma_param, int chanNum)
{
    int mcode_size = 0, msize = 0;


#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("setup_DMA_channel : SRC : 0x%08x, DST : 0x%08x : channelnu : %d\n\r"),dma_param.mSrcAddr,dma_param.mDstAddr,chanNum));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif

    if(!dma_param.mMemoryClear){
        msize = config_DMA_start_address(mbuf+mcode_size, dma_param.mSrcAddr);
        mcode_size+= msize;
    }


    msize = config_DMA_destination_address(mbuf+mcode_size, dma_param.mDstAddr);
    mcode_size+= msize;


    msize = config_DMA_control(mbuf+mcode_size, dma_param.mControl);
    mcode_size+= msize;

  if((dma_param.mDirection == PL330_M2P_DMA) ||(dma_param.mDirection == PL330_P2M_DMA))
  	{
	    msize = encodeDmaFlushPeri(mbuf+mcode_size, (u8)dma_param.mPeriNum);
	    mcode_size+= msize;
  	}

#ifdef USE_UART_RX_DMA  
	 if(dma_param.mPeriNum == PERI_UART_0_RX ||dma_param.mPeriNum == PERI_UART_1_RX 
	 	||dma_param.mPeriNum == PERI_UART_2_RX||dma_param.mPeriNum == PERI_UART_3_RX){
	    msize = config_DMA_transfer_size_forUART(mbuf+mcode_size, dma_param);
	    mcode_size+= msize;
	 	}
	 else{
	    msize = config_DMA_transfer_size(mbuf+mcode_size, dma_param);
	    mcode_size+= msize; 	
	 	}
#else
    msize = config_DMA_transfer_size(mbuf+mcode_size, dma_param);
    mcode_size+= msize;
#endif 

    if(dma_param.mIrqEnable) {
        msize = register_irq_to_DMA_channel(mbuf+mcode_size, chanNum);
        mcode_size+= msize;
    }


    if(dma_param.mLoop) {
        msize = config_DMA_set_infinite_loop((u32 *)(mbuf+mcode_size), dma_param.mBwJump+mcode_size);
        mcode_size+= msize;
    }


    if(dma_param.mLastReq) {
        msize = config_DMA_mark_end(mbuf+mcode_size);
        mcode_size+= msize;
    }



    return mcode_size;
}


/* start_DMA_channel
 * - get the DMA channel started
 *
 *    mbuf        the buffer address for PL330 DMA micro code
 *    chanNum        the DMA channel number to be started
 *    mbufAddr    the start address of the buffer for PL330 DMA micro codes
 */
void start_DMA_channel(u32 * mbuf, int chanNum, u8 * mbufAddr, int secureMode)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("start_DMA_channel :  contorlregaddr : 0x%08x, Codestartaddr : 0x%08x\n\r"),mbuf,mbufAddr));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    config_DMA_GO_command(mbuf, chanNum, mbufAddr, secureMode);

}


/* stop_DMA_channel
 * - get the DMA channel stopped
 *
 *    chanNum        the DMA channel number to be stopped
 */
void stop_DMA_channel(u32 * mbuf, int chanNum)
{
#ifdef WINCE
    DBGMSG(DMA_FUNC,(_T("stop_DMA_channel\n\r")));
#else
    dma_debug("%s entered :\n", __FUNCTION__);
#endif
    config_DMA_stop_channel(mbuf, chanNum);
}


