/*
* This program was created by AXELL CORPORATION.
* Copyright (C) 2017 AXELL CORPORATION, all rights reserved.
*/
#include "sample_common.h"
#include "com.h"
#include "dmac/dmacmgr.h"

/* プロトタイプ */
static int32_t Dmac_init_module(void);
static int32_t Dmac_term_module(void);
static void Dmac_SampleHelp(void);
static void Dmac_SimpleTrns(void);
static void Dmac_DescListTrns(void);
static void Dmac_ChEventTrns(void);
static void Dmac_RemoteDescTrns(void);
static void Dmac_WriteOnlyTrns(void);
static void Dmac_SetLdmFull(AG903_DMACMgrHandle *handle);
static int32_t Dmac_GetMem(uint8_t** srcaddr, uint8_t** dstaddr0, uint8_t** dstaddr1);
static int32_t Dmac_RelMem(uint8_t* srcaddr, uint8_t* dstaddr0, uint8_t* dstaddr1);
static int32_t Dmac_CheckVerify(uint8_t* src, uint8_t* dst, uint32_t size);
static int32_t Dmac_WatiTerm(uint32_t timout);
static void Dmac_TermHdlr(AG903_DMACMgrHandle* handle, AG903_DMACMgrDesc** desc, uint8_t* end);
static void Dmac_AbortHdlr(AG903_DMACMgrHandle* handle);
static void Dmac_ErrHdlr(AG903_DMACMgrHandle* handle);

/* Param */
#define DMAC_SMP_TRNS_SIZE		(1024)					/* データ転送数[byte] */
#define DMAC_SMP_ALIGN_SIZE		(32)					/* バッファアラインサイズ[byte] */
#define DMAC_SMP_MPL_SIZE		(DMAC_SMP_TRNS_SIZE*4)	/* メモリプールサイズ */
#define DMAC_SMP_MPL_ADDR		(AG903_SAMPLE_VRAM_ADDR)	/* メモリプールアドレス */
#define DMAC_SMP_CH_MAIN		(0)						/* DMAC CH (Mani) */
#define DMAC_SMP_CH_SUB			(1)						/* DMAC CH (Sub) */
#define DMAC_SMP_EVENT			(1)						/* Event番号 */
#define DMAC_SMP_CONSTVAL		(0xFF00AA55)			/* Const Data */
#define DMAC_SMP_LD_ALIGN		(8)						/* ディスクリプタアライン[byte] */

/* Macro */
#define	EPRINT(FMT, ...)		sys_print(0, FMT,##__VA_ARGS__)
#define	PRINT(FMT, ...)			sys_print(0, FMT"\r\n",##__VA_ARGS__)
#define DMAC_ERROR(str)			sys_print(1, " ERROR:%s[%d] *%s*\r\n",__FUNCTION__, __LINE__, str)

static void (*func[])() = {
	Dmac_SampleHelp,
	Dmac_SimpleTrns,
	Dmac_DescListTrns,
	Dmac_ChEventTrns,
	Dmac_RemoteDescTrns,
	Dmac_WriteOnlyTrns,
};

static _Bool	Dmacterm;

/**
 * @brief		メイン処理
 * @param[in]	param	制御パラメータ
 * @return		なし
 * @note		なし
 */
void DMAC_main(uint8_t param)
{
	((void)param);
	uint8_t		mode = 0;
	char		input[2+2];

	Dmac_SampleHelp();	/* Help表示 */

	Dmac_init_module();

	while (mode != 0xFF) {
		EPRINT(" -- Choose sample number (00h<HELP> to FFh): ");
		COM_GetNum_Wait(input, sizeof(input));
		mode = (ASCtoBIN(input[0]) << 4)
			 | (ASCtoBIN(input[1]) << 0);
		if(0xFF == mode) {
			break;
		}
		if(mode >= (sizeof(func)/sizeof(void*))) {
			func[0](); /* Help */
		}
		else {
			func[mode]();	/* Sample func実行 */
		}
	}

	Dmac_term_module();

	return;
}

/**
 * @brief		サブ処理
 * @param[in]	param	制御パラメータ
 * @return		なし
 * @note		なし
 */
void DMAC_sub(uint32_t param)
{
	((void)param);
	return;
}

/**
 * @brief		モジュール初期化
 * @param[in]	なし
 * @retval		AG903_ENONE		正常終了
 * @note		なし
 */
static int32_t Dmac_init_module(void)
{
	int32_t	ret;
	
	ret = sys_meminit(AG903_SAMPLE_VRAM_ALLOC_SIZE,
				 (void *)AG903_SAMPLE_VRAM_ADDR,
				 SYSMEM_NORMAL_CACHE_OFF);
	if(AG903_ENONE != ret) {
		DMAC_ERROR("CreateMpl");
	}

	return AG903_ENONE;
}

/**
 * @brief		モジュール終了
 * @param[in]	なし
 * @retval		AG903_ENONE		正常終了
 * @note		なし
 */
static int32_t Dmac_term_module(void)
{
	sys_memfinal();
	return AG903_ENONE;
}

/**
 * @brief		ヘルプ表示
 * @param		なし
 * @return		なし
 * @note		なし
 */
static void Dmac_SampleHelp(void)
{
	PRINT("\t# 00 ... Help");
	PRINT("\t# 01 ... Simple Transfer");
	PRINT("\t# 02 ... Descriptor List Transfer");
	PRINT("\t# 03 ... Channel Event Transfer");
	PRINT("\t# 04 ... Remote Descriptor Transfer");
	PRINT("\t# 05 ... Write Only Mode Transfer");
	PRINT("\t# FF ... Exit Sample");

	return;
}

/**
 * @brief		簡易ディスクリプタ転送
 * @param		なし
 * @return		なし
 * @note		なし
 */
static void Dmac_SimpleTrns(void)
{
	AG903_DMACMgrHandle *handle;
	uint8_t* 	srcaddr = NULL;
	uint8_t* 	dstaddr = NULL;
	int32_t 	result;

	PRINT(" Simple Transfer");

	Dmacterm = false;

	result = Dmac_GetMem(&srcaddr, &dstaddr, NULL);	/* 転送領域確保 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetMem");
	}

	/* DMAC設定 */
	result = AG903_DMACMgrGetHandle(DMAC_SMP_CH_MAIN, &handle); 					/* ハンドル取得 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("GetHandle");
	}
	result = AG903_DMACMgrSetIntCallback(handle, Dmac_TermHdlr, Dmac_AbortHdlr, Dmac_ErrHdlr); 	/* コールバック登録 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetIntCallback");
	}
	result = AG903_DMACMgrSetSimpleTrnsDesc(handle, (void*)srcaddr,
											DMAC_SMP_TRNS_SIZE, (void*)dstaddr); 	/* 簡易転送用ディスクリプタ設定 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetSimpleTrnsDesc");
	}

	/* 転送開始〜完了待ち */
	PRINT(" * Transfer Start");
	result = AG903_DMACMgrEnable(handle); 											/* 実行 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Enable");
	}
	result = Dmac_WatiTerm(1000);
	if(AG903_ENONE != result) {
		DMAC_ERROR("WaitTerm");
	}
	else {
		PRINT(" * Transfer End");
	}
	result = Dmac_CheckVerify(srcaddr, dstaddr, DMAC_SMP_TRNS_SIZE); 				/* ベリファイ */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Verify");
	}
	else {
		PRINT(" * Verify OK");
	}

	/* DMAC解放 */
	result = AG903_DMACMgrReleaseHandle(handle); 									/* ハンドル解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("ReleaseHandle");
	}

	result = Dmac_RelMem(srcaddr, dstaddr, NULL);	/* 転送領域解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("RelMem");
	}

	return;
}

/**
 * @brief		ディスクリプタリスト転送
 * @param		なし
 * @return		なし
 * @note		2個のディスクリプタを用意して2箇所へ転送します
 */
static void Dmac_DescListTrns(void)
{
	AG903_DMACMgrHandle *handle;
    AG903_DMACMgrConfig config;
	AG903_DMACMgrDesc	desc[2];
	uint8_t* 	srcaddr  = NULL;
	uint8_t* 	dstaddr0 = NULL;
	uint8_t* 	dstaddr1 = NULL;
	int32_t 	result;

	PRINT(" Descriptor List Transfer");

	Dmacterm = false;

	result = Dmac_GetMem(&srcaddr, &dstaddr0, &dstaddr1);	/* 転送領域確保 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetMem");
	}

	/* DMAC設定 */
	result = AG903_DMACMgrGetHandle(DMAC_SMP_CH_MAIN, &handle); 					/* ハンドル取得 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("GetHandle");
	}
	result = AG903_DMACMgrSetIntCallback(handle, Dmac_TermHdlr, Dmac_AbortHdlr, Dmac_ErrHdlr); 	/* コールバック登録 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetIntCallback");
	}
	config.val = 0;
	desc[0].Ctrl.val = 0;
	desc[0].SrcAddr  = (uint32_t)srcaddr;
	desc[0].DstAddr  = (uint32_t)dstaddr0;
	desc[0].Trns.val = DMAC_SMP_TRNS_SIZE;
	desc[0].Stride.val = 0;
	desc[0].next = (void*)&desc[1]; /* desc[1]へ */
	desc[1].Ctrl.val = 0;
	desc[1].SrcAddr  = (uint32_t)srcaddr;
	desc[1].DstAddr  = (uint32_t)dstaddr1;
	desc[1].Trns.val = DMAC_SMP_TRNS_SIZE;
	desc[1].Stride.val = 0;
	desc[1].next = 0;
	AG903_DMACMgrSetDescList(handle, &config, desc, 2); 							/* ディスクリプタ設定 */

	/* 転送開始〜完了待ち */
	PRINT(" * Transfer Start");
	result = AG903_DMACMgrEnable(handle); 											/* 実行 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Enable");
	}
	result = Dmac_WatiTerm(1000);
	if(AG903_ENONE != result) {
		DMAC_ERROR("WaitTerm");
	}
	else {
		PRINT(" * Transfer End");
	}
	result = Dmac_CheckVerify(srcaddr, dstaddr0, DMAC_SMP_TRNS_SIZE); 				/* ベリファイ */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Verify");
	}
	else {
		PRINT(" * 1st Verify OK");
	}
	result = Dmac_CheckVerify(srcaddr, dstaddr1, DMAC_SMP_TRNS_SIZE); 				/* ベリファイ */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Verify");
	}
	else {
		PRINT(" * 2nd Verify OK");
	}

	/* DMAC解放 */
	result = AG903_DMACMgrReleaseHandle(handle); 									/* ハンドル解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("ReleaseHandle");
	}

	result = Dmac_RelMem(srcaddr, dstaddr0, dstaddr1);	/* 転送領域解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("RelMem");
	}

	return;
}

/**
 * @brief		チャンネルイベント転送
 * @param		なし
 * @return		なし
 * @note		2個のDMACを使用して2箇所へ転送します
 */
static void Dmac_ChEventTrns(void)
{
	AG903_DMACMgrHandle *handle0;
	AG903_DMACMgrHandle *handle1;
    AG903_DMACMgrConfig config;
	AG903_DMACMgrDesc	desc;
	uint8_t* 	srcaddr  = NULL;
	uint8_t* 	dstaddr0 = NULL;
	uint8_t* 	dstaddr1 = NULL;
	int32_t 	result;

	PRINT(" Channel Event Transfer");

	Dmacterm = false;

	result = Dmac_GetMem(&srcaddr, &dstaddr0, &dstaddr1);	/* 転送領域確保 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetMem");
	}

	/* DMAC0設定 */
	result = AG903_DMACMgrGetHandle(DMAC_SMP_CH_MAIN, &handle0); 				/* ハンドル取得 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("GetHandle");
	}
	config.val = 0;
	desc.Ctrl.val = 0;
	desc.Ctrl.st.ExpEn = 1;
	desc.Ctrl.st.SEventEn = 1; /* Set Event */
	desc.Ctrl.st.ChSEvent = DMAC_SMP_EVENT;
	desc.SrcAddr  = (uint32_t)srcaddr;
	desc.DstAddr  = (uint32_t)dstaddr0;
	desc.Trns.val = DMAC_SMP_TRNS_SIZE;
	desc.Stride.val = 0;
	desc.next = 0;
	AG903_DMACMgrSetDescList(handle0, &config, &desc, 1); 							/* ディスクリプタ設定 */

	/* DMAC1設定 */
	result = AG903_DMACMgrGetHandle(DMAC_SMP_CH_SUB, &handle1); 					/* ハンドル取得 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("GetHandle");
	}
	result = AG903_DMACMgrSetIntCallback(handle1, Dmac_TermHdlr, Dmac_AbortHdlr, Dmac_ErrHdlr); 	/* コールバック登録 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetIntCallback");
	}
	config.val = 0;
	desc.Ctrl.val = 0;
	desc.Ctrl.st.ExpEn = 1;
	desc.Ctrl.st.WEventEn = 1; /* Wait Event */
	desc.Ctrl.st.ChWEvent = (1<<DMAC_SMP_EVENT);
	desc.SrcAddr  = (uint32_t)dstaddr0;
	desc.DstAddr  = (uint32_t)dstaddr1;
	desc.Trns.val = DMAC_SMP_TRNS_SIZE;
	desc.Stride.val = 0;
	desc.next = 0;
	AG903_DMACMgrSetDescList(handle1, &config, &desc, 1); 							/* ディスクリプタ設定 */

	/* 転送開始〜完了待ち */
	PRINT(" * Transfer Start");
	result = AG903_DMACMgrEnable(handle1); 											/* DMAC1実行 (DMAC0完了待ち) */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Enable");
	}
	result = AG903_DMACMgrEnable(handle0); 											/* DMAC0実行 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Enable");
	}
	result = Dmac_WatiTerm(1000);
	if(AG903_ENONE != result) {
		DMAC_ERROR("WaitTerm");
	}
	else {
		PRINT(" * Transfer End");
	}
	result = Dmac_CheckVerify(srcaddr, dstaddr0, DMAC_SMP_TRNS_SIZE); 				/* ベリファイ */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Verify");
	}
	else {
		PRINT(" * 1st Verify OK");
	}
	result = Dmac_CheckVerify(srcaddr, dstaddr1, DMAC_SMP_TRNS_SIZE); 				/* ベリファイ */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Verify");
	}
	else {
		PRINT(" * 2nd Verify OK");
	}

	/* DMAC解放 */
	result = AG903_DMACMgrReleaseHandle(handle0); 									/* DMAC0ハンドル解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("ReleaseHandle");
	}
	result = AG903_DMACMgrReleaseHandle(handle1); 									/* DMAC1ハンドル解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("ReleaseHandle");
	}

	result = Dmac_RelMem(srcaddr, dstaddr0, dstaddr1);	/* 転送領域解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("RelMem");
	}

	return;
}

/**
 * @brief		リモードディスクリプタ転送
 * @param		なし
 * @return		なし
 * @note		なし
 */
static void Dmac_RemoteDescTrns(void)
{
	AG903_DMACMgrHandle *handle;
	AG903_DMACMgrHandle *dummy;
    AG903_DMACMgrConfig config;
	AG903_DMACMgrDesc	desc;
	uint8_t* 	srcaddr = NULL;
	uint8_t*	dstaddr = NULL;
	uint8_t*	rddbuf;
	int32_t 	result;

	PRINT(" Remote Descriptor Transfer");

	Dmacterm = false;

	result = Dmac_GetMem(&srcaddr, &dstaddr, NULL);	/* 転送領域確保 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetMem");
	}

	/* LDMをダミーで埋める (LDMがFULLの条件を意図的に作る) */
	result = AG903_DMACMgrGetHandle(DMAC_SMP_CH_SUB, &dummy);
	if(AG903_ENONE != result) {
		DMAC_ERROR("GetHandle");
	}
	Dmac_SetLdmFull(dummy);

	/* リモードディスクリプタ領域設定 */
	rddbuf = (uint8_t*)sys_memalign(AG903_DMAC_RDD_ENTRY_NUM*AG903_DMAC_DESC_SIZE, DMAC_SMP_LD_ALIGN);
	result = AG903_DMACMgrSetRemoteDescAddr((void*)rddbuf);
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetRemoteDescAddr");
	}

	/* DMAC設定 */
	result = AG903_DMACMgrGetHandle(DMAC_SMP_CH_MAIN, &handle); 		/* ハンドル取得 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("GetHandle");
	}
	result = AG903_DMACMgrSetIntCallback(handle, Dmac_TermHdlr, Dmac_AbortHdlr, Dmac_ErrHdlr); 	/* コールバック登録 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetIntCallback");
	}
	config.val = 0;
	desc.Ctrl.val = 0;
	desc.SrcAddr  = (uint32_t)srcaddr;
	desc.DstAddr  = (uint32_t)dstaddr;
	desc.Trns.val = DMAC_SMP_TRNS_SIZE;
	desc.Stride.val = 0;
	desc.next = 0;
	AG903_DMACMgrSetDescList(handle, &config, &desc, 1); 				/* ディスクリプタ設定 */

	/* 転送開始〜完了待ち */
	PRINT(" * Transfer Start");
	result = AG903_DMACMgrEnable(handle); 								/* 実行 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Enable");
	}
	result = Dmac_WatiTerm(1000);
	if(AG903_ENONE != result) {
		DMAC_ERROR("WaitTerm");
	}
	else {
		PRINT(" * Transfer End");
	}
	result = Dmac_CheckVerify(srcaddr, dstaddr, DMAC_SMP_TRNS_SIZE); 	/* ベリファイ */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Verify");
	}
	else {
		PRINT(" * Verify OK");
	}

	/* DMAC解放 */
	result = AG903_DMACMgrReleaseHandle(handle); 						/* ハンドル解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("ReleaseHandle");
	}
	result = AG903_DMACMgrReleaseHandle(dummy); 						/* ダミーハンドル解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("ReleaseHandle");
	}

	/* リモードディスクリプタ領域クリア */
	result = AG903_DMACMgrClearRemoteDescAddr();
	if(AG903_ENONE != result) {
		DMAC_ERROR("ClearRemoteDescAddr");
	}
	sys_free(rddbuf);

	result = Dmac_RelMem(srcaddr, dstaddr, NULL);	/* 転送領域解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("RelMem");
	}

	return;
}

/**
 * @brief		Write Only Mode転送
 * @param		なし
 * @return		なし
 * @note		なし
 */
static void Dmac_WriteOnlyTrns(void)
{
	AG903_DMACMgrHandle *handle;
    AG903_DMACMgrConfig config;
	AG903_DMACMgrDesc	desc;
	uint8_t* 	dstaddr = NULL;
	int32_t 	result;

	PRINT(" Write Only Mode Transfer");

	Dmacterm = false;

	result = Dmac_GetMem(NULL, &dstaddr, NULL);	/* 転送領域確保 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetMem");
	}

	/* DMAC設定 */
	result = AG903_DMACMgrGetHandle(DMAC_SMP_CH_MAIN, &handle); 					/* ハンドル取得 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("GetHandle");
	}
	result = AG903_DMACMgrSetIntCallback(handle, Dmac_TermHdlr, Dmac_AbortHdlr, Dmac_ErrHdlr); 	/* コールバック登録 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetIntCallback");
	}
	result = AG903_DMACMgrSetConstantValue(DMAC_SMP_CONSTVAL);						/* Write Val設定 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("SetConstantVal");
	}
	config.val        = 0;
	config.st.WOMode = 1; /* WriteOnlyMode */
	desc.Ctrl.val     = 0;
	desc.DstAddr      = (uint32_t)dstaddr;
	desc.Trns.val     = DMAC_SMP_TRNS_SIZE;
	desc.Stride.val   = 0;
	desc.next = 0;
	AG903_DMACMgrSetDescList(handle, &config, &desc, 1); 							/* ディスクリプタ設定 */

	/* 転送開始〜完了待ち */
	PRINT(" * Transfer Start");
	result = AG903_DMACMgrEnable(handle); 											/* 実行 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Enable");
	}
	result = Dmac_WatiTerm(1000);
	if(AG903_ENONE != result) {
		DMAC_ERROR("WaitTerm");
	}
	else {
		PRINT(" * Transfer End");
	}
	result = Dmac_CheckVerify(NULL, dstaddr, DMAC_SMP_TRNS_SIZE); 					/* ベリファイ */
	if(AG903_ENONE != result) {
		DMAC_ERROR("Verify");
	}
	else {
		PRINT(" * Verify OK");
	}

	/* DMAC解放 */
	result = AG903_DMACMgrReleaseHandle(handle); 									/* ハンドル解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("ReleaseHandle");
	}

	result = Dmac_RelMem(NULL, dstaddr, NULL);	/* 転送領域解放 */
	if(AG903_ENONE != result) {
		DMAC_ERROR("RelMem");
	}

	return;
}

/**
 * @brief		LDM Full埋め (テスト用)
 * @param[in]	DMACハンドル
 * @return		なし
 * @note		なし
 */
static void Dmac_SetLdmFull(AG903_DMACMgrHandle *handle)
{
    AG903_DMACMgrConfig config;
	AG903_DMACMgrDesc	desc;
	uint32_t 	src;
	uint32_t 	dst;
	int32_t 	result;
	uint32_t	loop;

	config.val = 0;
	desc.Ctrl.val = 0;
	desc.Ctrl.st.SrcCtrl = 2; /* Fixed */
	desc.Ctrl.st.DstCtrl = 2; /* Fixed */
	desc.SrcAddr  = (uint32_t)&src;
	desc.DstAddr  = (uint32_t)&dst;
	desc.Trns.val = DMAC_SMP_TRNS_SIZE;
	desc.Stride.val = 0;
	desc.next = 0;

	for(loop=0; loop<AG903_DMAC_LDD_ENTRY_NUM; loop++) {
		result = AG903_DMACMgrSetDescList(handle, &config, &desc, 1);
		if(-AG903_ENOBUFS == result) {
			break;
		}
	}

	return;
}

/**
 * @brief		転送用メモリ確保
 * @param[out]	送信バッファ
 * @param[out]	受信バッファ
 * @return		なし
 * @note		確保後に内容を初期化します
 */
static int32_t Dmac_GetMem(uint8_t** srcaddr, uint8_t** dstaddr0, uint8_t** dstaddr1)
{
	uint8_t* 	getbuf;
	uint32_t 	loop;

	if(NULL != srcaddr) {
		getbuf = (uint8_t*)sys_memalign(DMAC_SMP_TRNS_SIZE, DMAC_SMP_ALIGN_SIZE);
		if(NULL == getbuf) {
			return -AG903_EFAULT;
		}
		for(loop=0; loop<DMAC_SMP_TRNS_SIZE; loop++) {
			*(getbuf+loop) = loop;	/* 転送元データセット */
		}
		(*srcaddr) = getbuf;
	}

	if(NULL != dstaddr0) {
		getbuf = (uint8_t*)sys_memalign(DMAC_SMP_TRNS_SIZE, DMAC_SMP_ALIGN_SIZE);
		if(NULL == getbuf) {
			return -AG903_EFAULT;
		}
		for(loop=0; loop<DMAC_SMP_TRNS_SIZE; loop++) {
			*(getbuf+loop) = 0;		/* 転送先データクリア */
		}
		(*dstaddr0) = getbuf;
	}

	if(NULL != dstaddr1) {
		getbuf = (uint8_t*)sys_memalign(DMAC_SMP_TRNS_SIZE, DMAC_SMP_ALIGN_SIZE);
		if(NULL == getbuf) {
			return -AG903_EFAULT;
		}
		for(loop=0; loop<DMAC_SMP_TRNS_SIZE; loop++) {
			*(getbuf+loop) = 0;		/* 転送先データクリア */
		}
		(*dstaddr1) = getbuf;
	}

	return AG903_ENONE;
}

/**
 * @brief		転送用メモリ解放
 * @param[in]	送信バッファ
 * @param[in]	受信バッファ
 * @return		なし
 * @note		なし
 */
static int32_t Dmac_RelMem(uint8_t* srcaddr, uint8_t* dstaddr0, uint8_t* dstaddr1)
{
	int32_t 	result;

	if(NULL != srcaddr) {
		result = sys_free(srcaddr);
		if(AG903_ENONE != result) {
			return result;
		}
	}

	if(NULL != dstaddr0) {
		result = sys_free(dstaddr0);
		if(AG903_ENONE != result) {
			return result;
		}
	}

	if(NULL != dstaddr1) {
		result = sys_free(dstaddr1);
		if(AG903_ENONE != result) {
			return result;
		}
	}

	return AG903_ENONE;
}

/**
 * @brief		ベリファイチェック
 * @param[in]	src		比較元
 * @param[in]	dst		比較先
 * @param[in]	size	比較サイズ
 * @return		なし
 * @note		なし
 */
static int32_t Dmac_CheckVerify(uint8_t* src, uint8_t* dst, uint32_t size)
{
	int32_t		retval = AG903_ENONE;
	uint32_t	loop;
	uint32_t*	dst32 = (uint32_t*)dst;

	if(NULL != src) {
		for(loop=0; loop<size; loop++) {
			if( *(src+loop) != *(dst+loop) ) {
				retval = -AG903_EFAULT;
				break;
			}
		}
	}
	else {
		/* srcがNULLの場合はconstデータと比較する */
		for(loop=0; loop<(size/4); loop++) {
			if( DMAC_SMP_CONSTVAL != (*dst32) ) {
				retval = -AG903_EFAULT;
				break;
			}
			dst32 ++;
		}
	}

	return retval;
}

/**
 * @brief		転送完了待ち
 * @param[in]	timout	タイムアウト[ms]
 * @return		なし
 * @note		なし
 */
static int32_t Dmac_WatiTerm(uint32_t timout)
{
	int32_t		retval = AG903_ENONE;
	uint32_t	cnt;
	uint32_t	loop;

	cnt = timout/10;
	if(timout%10) {
		cnt++;
	}
	for(loop=0; loop<cnt; loop++) {
		if(true == Dmacterm) {
			Dmacterm = false;
			break;
		}
		sys_dlytsk(10);
	}
	if(cnt<=loop) {
		retval = -AG903_ETIMEDOUT;
	}

	return retval;
}




/**
 * @brief		転送終了割込み
 * @param[in]	handle	ハンドル
 * @param[out]	desc	ディスクリプタ格納先
 * @param[out]	end		循環終了フラグ
 * @return		なし
 * @note		なし
 */
static void Dmac_TermHdlr(AG903_DMACMgrHandle* handle, AG903_DMACMgrDesc** desc, uint8_t* end)
{
	((void)handle);
	((void)desc);
	((void)end);
	Dmacterm = true;
	return;
}

/**
 * @brief		アボート割込み
 * @param[in]	handle	ハンドル
 * @return		なし
 * @note		なし
 */
static void Dmac_AbortHdlr(AG903_DMACMgrHandle* handle)
{
	((void)handle);
	return;
}

/**
 * @brief		エラー割込み
 * @param[in]	handle	ハンドル
 * @return		なし
 * @note		なし
 */
static void Dmac_ErrHdlr(AG903_DMACMgrHandle* handle)
{
	((void)handle);
	return;
}
