/*
 * This program was created by AXELL CORPORATION.
 * Copyright (C) 2017 AXELL CORPORATION, all rights reserved.
*/

/*****************************************************************************/
/*     include file                                                          */
/*****************************************************************************/
#include "kernel.h"
#include "kernel_itron4.h"
#include "ffsys.h"
#include "ffsysdrv_cfg.h"

#include "vram/vrammgr.h"
#include "uhs_type.h"
#include "uhs_stdlib.h"
#include "usb_msc_api.h"
#include "usb_msc_param.h"

/*****************************************************************************/
/*     global variable                                                       */
/*****************************************************************************/
/* メモリプールID */
int32_t			g_mplid_fs = 0;

/*****************************************************************************/
/*     define value                                                          */
/*****************************************************************************/
/* Sector Size */
#define SEC_LEN         512         /* Sector size for low driver */

/******************************************************************************
   Function：  usb_ini
   Argument：  dev_id     : デバイスID
   Return  ：  E_OK       正常終了
   Summary ：  USB初期化処理
   Caution ：  
******************************************************************************/
ER usb_ini(ID dev_id)
{
	AG903_VRAMMgrMplPrm		pool_prm;						/* メモリプール生成パラメータ		*/


	if(g_mplid_fs == 0) {
		/*------------------*/
		/* メモリプール生成 */
		/*------------------*/
		/* パラメータ設定 */
		pool_prm.mplatr	= AG903_OSW_ATRFIFO;				/* メモリプール待ち FIFO 順			*/
		pool_prm.mplsz	= MPL_FS_SIZE;						/* メモリプールのバイトサイズ		*/
		pool_prm.mpl	= (void *)MPL_FS_ADDR;				/* メモリプール領域の先頭番地		*/
		pool_prm.memtype = AG903_VRAM_NORMAL_CACHE_OFF;		/* キャッシュ OFF					*/

		g_mplid_fs = AG903_VRAMMgrCreateMpl(&pool_prm);
	}
    return E_OK;
}

/******************************************************************************
   Function：  usb_ext
   Argument：  dev_id     : デバイスID
   Return  ：  E_OK       正常終了
   Summary ：  USB終了処理
   Caution ：  
******************************************************************************/
ER usb_ext(ID dev_id)
{
    /* 処理なし */
    return E_OK;
}

/******************************************************************************
   Function：  usb_mnt
   Argument：  dev_id     : デバイスID
   Return  ：  E_OK       正常終了
   Summary ：  USBマウント処理
   Caution ：  
******************************************************************************/
ER usb_mnt(ID dev_id)
{
    PSTOR_UNIT pNewUnit;
    uhs_sbit32_t retval;


    /* dev_idが0の場合 */
    /* ※mount()からコールされた場合は、dev_idは0となる */
    if(dev_id == 0) {
		/* 接続中デバイス数が複数 */
		if(Usbh_Stor_GetAttachDevNum() > 1) {
			/* エラー */
			return E_PAR;
		}
		/* 接続中デバイスが1個以下 */
		else {
			/* デバイスIDを0以外の固定値と置き換える */
			dev_id = CFG_DRV_LOW_FIXED_DEV_ID;
			/* Storage Driverへ対して、Unmount Diskがあるか確認 */
			pNewUnit = Usbh_Stor_GetUnmountUnit();
			if(pNewUnit == NULL){
				/* 未マウントのデバイスが無い */
				return  E_NRD;
			}
        }
    }
    /* dev_idが0以外 */
    else {
        /* デバイスIDからPSTOR_UNITを取り出す */
        pNewUnit = (PSTOR_UNIT)dev_id;
    }
	
	/* マウント処理 */
	retval = Usbh_Stor_Mount(pNewUnit, (PUSER_DRV)dev_id);
	if(retval != USBSTOR_SUCCESS) {
		return E_DRV;
	}
	return E_OK;
}

/******************************************************************************
   Function：  usb_umt
   Argument：  dev_id     : デバイスID
   Return  ：  E_OK       正常終了
   Summary ：  USBアンマウント処理
   Caution ：  
******************************************************************************/
ER usb_umt(ID dev_id)
{
    uhs_sbit32_t retval;


    /* dev_idが0の場合 */
    /* ※unmount()からコールされた場合は、dev_idは0となる */
    if(dev_id == 0) {
		/* デバイスIDを0以外の固定値と置き換える */
		dev_id = CFG_DRV_LOW_FIXED_DEV_ID;
	}
    retval = Usbh_Stor_Unmount((PUSER_DRV)dev_id);
	if(retval != USBSTOR_SUCCESS) {
		return E_DRV;
	}
	return E_OK;
}

/******************************************************************************
   Function：  usb_read
   Argument：  dev_id     : デバイスID
               buf        : リードデータを格納するバッファ
               cnt        : セクタ個数
               tmo        : (未使用)
   Return  ：  E_OK       正常終了
   Summary ：  USBアンマウント処理
   Caution ：  
******************************************************************************/
ER usb_read(ID dev_id, VP buf, UW pos, UH cnt, TMO tmo)
{
    uhs_ubit8_t *pBuff;
    uhs_sbit32_t retval;


    /* 非キャッシュバッファ取得 */
    pBuff = AG903_VRAMMgrMalloc(g_mplid_fs, cnt * SEC_LEN);
    /* セクタリード */
    retval = Usbh_Stor_ReadSector((PUSER_DRV)(dev_id), 
                                (uhs_ubit32_t)(pos),
                                (uhs_ubit16_t)(cnt),
                                pBuff);
    if (retval != USBSTOR_SUCCESS) {
        /* 非キャッシュバッファ解放 */
		AG903_VRAMMgrFree(g_mplid_fs, pBuff);
        return E_DRV;
    }
    /* バッファコピー */
    memcpy(buf, pBuff, cnt * SEC_LEN);
    /* 非キャッシュバッファ解放 */
	AG903_VRAMMgrFree(g_mplid_fs, pBuff);

	return E_OK;
}

/******************************************************************************
   Function：  usb_write
   Argument：  dev_id     : デバイスID
               buf        : ライトデータが格納されているバッファ
               cnt        : セクタ個数
               tmo        : (未使用)
   Return  ：  E_OK       正常終了
   Summary ：  USBアンマウント処理
   Caution ：  
******************************************************************************/
ER usb_write(ID dev_id, VP buf, UW pos, UH cnt, TMO tmo)
{
    uhs_ubit8_t *pBuff;
    uhs_sbit32_t retval;


    /* 非キャッシュバッファ取得 */
    pBuff = AG903_VRAMMgrMalloc(g_mplid_fs, cnt * SEC_LEN);
    /* バッファコピー */
    memcpy(pBuff, buf, cnt * SEC_LEN);
    /* セクタライト */
    retval = Usbh_Stor_WriteSector((PUSER_DRV)(dev_id), 
                                 (uhs_ubit32_t)(pos),
                                 (uhs_ubit16_t)(cnt),
                                 pBuff);
    /* 非キャッシュバッファ解放 */
 	AG903_VRAMMgrFree(g_mplid_fs, pBuff);
   if (retval != USBSTOR_SUCCESS) {
        return E_DRV;
    }

    return E_OK;
}
