/***********************************************************************************************************************
 * DISCLAIMER
 * This software is supplied by Renesas Electronics Corporation and is only intended for use with Renesas products. No
 * other uses are authorized. This software is owned by Renesas Electronics Corporation and is protected under all
 * applicable laws, including copyright laws.
 * THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
 * THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED. TO THE MAXIMUM
 * EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES
 * SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR ANY REASON RELATED TO THIS
 * SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 * Renesas reserves the right, without notice, to make changes to this software and to discontinue the availability of
 * this software. By using this software, you agree to the additional terms and conditions found by accessing the
 * following link:
 * http://www.renesas.com/disclaimer
 *
 * Copyright (C) 2014(2017) Renesas Electronics Corporation. All rights reserved.
 ***********************************************************************************************************************/
/***********************************************************************************************************************
 * File Name    : r_ram_disk.h
 * Description  : Header file for RAM-disk media driver.
 ***********************************************************************************************************************/
/**********************************************************************************************************************
 * History : DD.MM.YYYY Version Description
 *         : 08.01.2014 1.00 First Release
 *         : 26.12.2014 1.10 RX71M is added
 *         : 30.09.2015 1.11 RX63N/RX631 is added.
 *         : 30.09.2016 1.20 RX65N/RX651 is added.
 *         : 30.09.2017 1.22 Move RAM DISK macro & global variables.
 ***********************************************************************************************************************/

#ifndef RAM_DISK_H 
#define RAM_DISK_H

/***********************************************************************************************************************
 Includes   <System Includes> , "Project Includes"
 ***********************************************************************************************************************/
/* Fixed width integers. */
#include <stdint.h>

/* RAM disk configuration */
#include "r_usb_basic_config.h"
#include "r_usb_media_driver_if.h"

/***********************************************************************************************************************
 Macro definitions
 ***********************************************************************************************************************/
#ifdef GRROSE
#define	USBC_PMSC_USER_APPLICATION_ADDR		(0xFFE00000)
#define	USBC_PMSC_USER_APPLICATION_END		(0xFFEFFFFF)
#define	USBC_PMSC_STORAGE_FLASH_ADDR		(0xFFF00000)
#define	USBC_PMSC_STORAGE_FLASH_BLOCKSIZE	(32 * 1024ul)
#define USB_MEDIA_ADDRESS               	(USBC_PMSC_STORAGE_FLASH_ADDR) /* Media Head Address */
#define STRG_MEDIASIZE                  	(960 * 1024ul)     /* Media size */
#include "r_flash_rx_if.h"
#include "rx65n/r_flash_rx65n.h"
#if (FLASH_CF_MIN_PGM_SIZE == 128)
#define	FLASH_BLANKCHECK_MASK	(0xFFFFFF80)
#else
#error "no definition of FLASH_CF_MIN_PGM_SIZE"
#endif
#endif //GRROSE

#define STRG_TOTALSECT                  (STRG_MEDIASIZE / STRG_SECTSIZE)
#define RAMDISK_SIGNATURE               (0xAA55u)

/* Logical Block Unit Size */
#define USBC_ATAPI_BLOCK_UNIT			512
/* Transfer Unit Size */
#define USBC_ATAPI_TRANSFER_UNIT		(256 * USBC_ATAPI_BLOCK_UNIT)

#define	USBC_ATAPI_STORAGE_SECTOR_COUNT	(STRG_MEDIASIZE/512)

#define	MBR_SECTOR_COUNT				1		// 1セクタ
#define	FATFS_RESERVED_SECTOR_COUNT		1		// 1セクタ
#define	FATFS_ROOT_DIR_SECTOR_COUNT		2		// 2セクタ
#define	FATFS_FAT_SECTOR_COUNT			1		// 1セクタ

#if 	ENABLE_FAT16
#define	FATFS_FILE_SYSTEM_NAME			'F','A','T','1','6',' ',' ',' '
#else
#define	FATFS_FILE_SYSTEM_NAME			'F','A','T','1','2',' ',' ',' '
#endif

#define	FATFS_MEDIATYPE					0xF0		// リムーバブルメディア
#define	FATFS_OEM_NAME					'M','S','D','O','S','5','.','0'
#define	FATFS_CLUSTER_SIZE				(FATFS_SECTOR_PER_CLUSTER * USBC_ATAPI_BLOCK_UNIT)
#define	FATFS_SECTOR_PER_CLUSTER		64		// 32KBクラスタ

// Inquiry data
#define	STR_PRODUCT_VERSION				"1.00"				// 4����
#define	STR_VENDOR_ID					"Renesas "			// 8����
#define	STR_PRODUCT_ID					"Mass Storage    "	// 16����
										//1234567890123456

// Directory entry data for Volume label
#define	INIT_ROOT_DIR_ENTRY_VOLUME_LABEL											\
	'G' ,'R' ,'-' ,'R' ,'O' ,'S' ,'E' ,' ' ,' ' , ' ', ' ',0x08,0x00,0x00,0x00,0x00,\
	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,\

// Directory entry data for "Gadget Renesas Project Home.html"
#define	INIT_ROOT_DIR_ENTRY_HTML_FILE												\
	0x43,0x65,0x00,0x2E,0x00,0x68,0x00,0x74,0x00,0x6D,0x00,0x0F,0x00,0x43,0x6C,0x00,\
	0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00,0xFF,0xFF,0xFF,0xFF,\
	0x02,0x73,0x00,0x20,0x00,0x50,0x00,0x72,0x00,0x6F,0x00,0x0F,0x00,0x43,0x6A,0x00,\
	0x65,0x00,0x63,0x00,0x74,0x00,0x20,0x00,0x48,0x00,0x00,0x00,0x6F,0x00,0x6D,0x00,\
	0x01,0x47,0x00,0x61,0x00,0x64,0x00,0x67,0x00,0x65,0x00,0x0F,0x00,0x43,0x74,0x00,\
	0x20,0x00,0x52,0x00,0x65,0x00,0x6E,0x00,0x65,0x00,0x00,0x00,0x73,0x00,0x61,0x00,\
	0x47,0x41,0x44,0x47,0x45,0x54,0x7E,0x31,0x48,0x54,0x4D,0x21,0x00,0x2D,0x8D,0x6C,\
	0xAB,0x40,0xAB,0x40,0x00,0x00,0xC0,0x68,0xAB,0x40,0x02,0x00,0x6A,0x00,0x00,0x00,\

// Directory entry data
#define	INIT_ROOT_DIR_ENTRY				INIT_ROOT_DIR_ENTRY_VOLUME_LABEL			\
										INIT_ROOT_DIR_ENTRY_HTML_FILE				\

// HTML file contents
#define	HTML_FILE_DATA																\
	"<a href=\"http://gadget.renesas.com/\">"	"\r\n"\
	"Gadget Renesas Project Home"												"\r\n"\
	"</a>"																		"\r\n"

#define	HTML_FILE_DATA_CLUSTER_COUNT	1	// round_up(sizeof(HTML_FILE_DATA),FATFS_CLUSTER_SIZE)
#define	HTML_FILE_DATA_SECTOR_COUNT		(HTML_FILE_DATA_CLUSTER_COUNT*FATFS_SECTOR_PER_CLUSTER)


#if 	ENABLE_FAT16

#define	PARTITION_ID					0x04					// DOS(FAT16<=32MB)
#define	INIT_FAT_DATA_RESERVED			0xF8,0xFF,0xFF,0xFF		// for FAT16

 #if 	(HTML_FILE_DATA_CLUSTER_COUNT==1)
#define	INIT_FAT_DATA					INIT_FAT_DATA_RESERVED,				\
										0xFF,0xFF			// used 1 cluster
 #elif	(HTML_FILE_DATA_CLUSTER_COUNT==2)
#define	INIT_FAT_DATA					INIT_FAT_DATA_RESERVED,				\
										0x03,0x00,0xFF,0xFF	// used 2 clusters
 #else
	#error Update INIT_FAT_DATA by HTML_FILE_DATA_CLUSTER_COUNT.
 #endif

#else	//FAT12

#define	PARTITION_ID					0x01					// DOS(FAT12)
#define	INIT_FAT_DATA_RESERVED			0xF8,0xFF,0xFF			// for FAT12

 #if 	(HTML_FILE_DATA_CLUSTER_COUNT==1)
#define	INIT_FAT_DATA					INIT_FAT_DATA_RESERVED,				\
										0xFF,0x0F,0x00		// used 1 cluster
 #elif	(HTML_FILE_DATA_CLUSTER_COUNT==2)
#define	INIT_FAT_DATA					INIT_FAT_DATA_RESERVED,				\
										0x03,0xF0,0xFF		// used 2 clusters
 #else
	#error Update INIT_FAT_DATA by HTML_FILE_DATA_CLUSTER_COUNT.
 #endif

#endif	//ENABLE_FAT16


#define	LBA_BASE_VOLUME					(MBR_SECTOR_COUNT)
#define	LBA_BASE_FAT1					(LBA_BASE_VOLUME+FATFS_RESERVED_SECTOR_COUNT)
#define	LBA_BASE_FAT2					(LBA_BASE_FAT1+FATFS_FAT_SECTOR_COUNT)
#define	LBA_BASE_ROOT_DIR				(LBA_BASE_FAT2+FATFS_FAT_SECTOR_COUNT)
#define	LBA_BASE_CLUSTERS				(LBA_BASE_ROOT_DIR+FATFS_ROOT_DIR_SECTOR_COUNT)
#define	LBA_BASE_HTML_FILE_CLUSTER		(LBA_BASE_CLUSTERS)
//#define	LBA_BASE_STORAGE_CLUSTERS		(LBA_BASE_HTML_FILE_CLUSTER + HTML_FILE_DATA_SECTOR_COUNT + \
//                                        (128 - LBA_BASE_HTML_FILE_CLUSTER + HTML_FILE_DATA_SECTOR_COUNT) )
#define	LBA_BASE_STORAGE_CLUSTERS		(LBA_BASE_HTML_FILE_CLUSTER + HTML_FILE_DATA_SECTOR_COUNT )

#define	USBC_ATAPI_TOTAL_SECTOR_COUNT	(LBA_BASE_STORAGE_CLUSTERS +	\
										 USBC_ATAPI_STORAGE_SECTOR_COUNT)

#define	MBR_PARTITION_ID				PARTITION_ID
#define	MBR_END_HEAD_NO					63
#define	MBR_END_SECTOR_NO				32
#define	MBR_END_CYLINDER_NO				((USBC_ATAPI_TOTAL_SECTOR_COUNT/((MBR_END_HEAD_NO+1)*MBR_END_SECTOR_NO))-1)

#define	FATFS_VOLUME_TOTAL_SECTOR_COUNT	(USBC_ATAPI_TOTAL_SECTOR_COUNT - \
										 MBR_SECTOR_COUNT)

#define	FATFS_SECTOR_SIZE_LO			((USBC_ATAPI_BLOCK_UNIT>>0)&0xFF)
#define	FATFS_SECTOR_SIZE_HI			((USBC_ATAPI_BLOCK_UNIT>>8)&0xFF)

#define	FATFS_HIDDEN_SECTOR_COUNT_LO	((MBR_SECTOR_COUNT>>0)&0xFF)
#define	FATFS_HIDDEN_SECTOR_COUNT_HI	((MBR_SECTOR_COUNT>>8)&0xFF)

#define	FATFS_RESERVED_SECTOR_COUNT_LO	((FATFS_RESERVED_SECTOR_COUNT>>0)&0xFF)
#define	FATFS_RESERVED_SECTOR_COUNT_HI	((FATFS_RESERVED_SECTOR_COUNT>>8)&0xFF)

#define	FATFS_ROOT_DIR_COUNT			(FATFS_ROOT_DIR_SECTOR_COUNT*USBC_ATAPI_BLOCK_UNIT/32)
#define	FATFS_ROOT_DIR_COUNT_LO			((FATFS_ROOT_DIR_COUNT>>0)&0xFF)
#define	FATFS_ROOT_DIR_COUNT_HI			((FATFS_ROOT_DIR_COUNT>>8)&0xFF)

#if	(USBC_ATAPI_TOTAL_SECTOR_COUNT < 0x10000ul)
#define	FATFS_TOTAL_SECTOR_COUNT_LO		((FATFS_VOLUME_TOTAL_SECTOR_COUNT>>0)&0xFF)
#define	FATFS_TOTAL_SECTOR_COUNT_HI		((FATFS_VOLUME_TOTAL_SECTOR_COUNT>>8)&0xFF)
#define	FATFS_TOTAL_SECTOR_COUNT_EX_0	0
#define	FATFS_TOTAL_SECTOR_COUNT_EX_1	0
#define	FATFS_TOTAL_SECTOR_COUNT_EX_2	0
#define	FATFS_TOTAL_SECTOR_COUNT_EX_3	0
#else
#define	FATFS_TOTAL_SECTOR_COUNT_LO		0
#define	FATFS_TOTAL_SECTOR_COUNT_HI		0
#define	FATFS_TOTAL_SECTOR_COUNT_EX_0	((FATFS_VOLUME_TOTAL_SECTOR_COUNT>> 0)&0xFF)
#define	FATFS_TOTAL_SECTOR_COUNT_EX_1	((FATFS_VOLUME_TOTAL_SECTOR_COUNT>> 8)&0xFF)
#define	FATFS_TOTAL_SECTOR_COUNT_EX_2	((FATFS_VOLUME_TOTAL_SECTOR_COUNT>>16)&0xFF)
#define	FATFS_TOTAL_SECTOR_COUNT_EX_3	((FATFS_VOLUME_TOTAL_SECTOR_COUNT>>24)&0xFF)
#endif

#define	FATFS_FAT_SECTOR_COUNT_LO		((FATFS_FAT_SECTOR_COUNT>>0)&0xFF)
#define	FATFS_FAT_SECTOR_COUNT_HI		((FATFS_FAT_SECTOR_COUNT>>8)&0xFF)


/******************************************************************************
Local variables and functions
******************************************************************************/
static	uint32_t	usb_gpmsc_Atapi_lbaCurrent;		// Current LBA for READ/WRITE
static	uint32_t	usb_gpmsc_Atapi_nCurXferCount;	// Current Transfer sector count for READ/WRITE
static	uint32_t	usb_gpmsc_Atapi_lbaLast;		// Last LBA for READ/WRITE
static	uint32_t	usb_gpmsc_Atapi_nLastXferCount;	// Last Transfer sector count for READ/WRITE


/***********************************************************************************************************************
 Typedef definitions
 ***********************************************************************************************************************/
/******************************************************************************
	Structure of Directory Entry
******************************************************************************/
struct tagDirectoryEntry
{
	uint8_t		bFilename[8];		// 00: Filename
	uint8_t		bExtension[3];		// 08: Extension
	uint8_t		bAttributes;		// 0B: Attributes flags
	uint8_t		bFilenameFlags;		// 0C: Filename flags
	uint8_t		nCreationTime_ms;	// 0D: Creation time in 10ms
	uint16_t	wCreationTime;		// 0E: Creation time
	uint16_t	wCreationDate;		// 10: Creation date
	uint16_t	wLastAccessDate;	// 12: Last access date
	uint16_t	wClusNoEx;			// 14: (High word of cluster number for FAT32)
	uint16_t	wLastWriteTime;		// 16: Last modified time
	uint16_t	wLastWriteDate;		// 18: Last modified date
	uint16_t	nClusNo;			// 1A: Cluster number
	uint32_t	nFileSize;			// 1C: File size
};
typedef	struct tagDirectoryEntry	DIRENT, *PDIRENT;

/***********************************************************************************************************************
 * Exported global variables (to be accessed by other files)
 ************************************************************************************************************************/
extern usb_media_driver_t g_ram_mediadriver;
extern uint8_t g_ram_disk_boot_sector[];
extern uint8_t g_usb_pmsc_tablefat[];
extern uint8_t g_usb_pmsc_rootdir[];
extern uint8_t g_usb_pmsc_htmlfile[];

/***********************************************************************************************************************
Functions
 ***********************************************************************************************************************/
PDIRENT fatfs_FindUserApplicationFileInfo( void );
uint16_t fatfs_GetNextClusterNo( const uint16_t );
void* fatfs_GetClusterData( const uint16_t );
#endif /* RAM_DISK_H */
