#ifndef _SSD1928_SDHC_H
#define _SSD1928_SDHC_H

#include "GenericTypeDefs.h"
#include "SSD1928.h"
#include "endian.h"

//these typedefs are specific for Solomon sdhc example only
typedef signed long long	INT64;
typedef unsigned long long	UINT64;
typedef signed long			INT32;
typedef unsigned long		UINT32;
typedef short int			INT16;
typedef unsigned short int	UINT16;
typedef signed char			INT8;
typedef unsigned char		UINT8;

#define BIT(x)					(1UL << (x))
#define BIT16(x)				SWAP16(BIT(x))
#define BIT32(x)				SWAP32(BIT(x))

/*
***********************************************************************
* There are dependencies between operation modes and card states.
* Each state in the SD memory card state is associated with one
* operation mode. More details on page 12,
* Physical Layer Simplified Specification Version 2.00
***********************************************************************
*/
typedef struct tagState 
{
	UINT16 	code;
	UINT8 	name[32];
} CARD_STATE;

/*
***********************************************************************
* Each card has a set of information registers (see Chapter 5,
* Physical Layer Simplified Specification Version 2.00).
* CSD is the Card Specific Data register. These registers provide
* information regarding access to the card contents, e.g. the card
* capacity can be obtained from these registers
***********************************************************************
*/
typedef struct tagCSD2
{
	//CSD occupies 128 Bit
	UINT8 	rsvd;		// due to CRC-7 and embedded 'End' bit in the structure
	UINT8 	version;	// b[7:6] = csd_version, b[5:0] = rsvd
	UINT8 	taac;		// defines the async part of the data access time
	UINT8 	nsac;		// defines the worst case for the clock-dependent factor of the data access time
	UINT8 	tran_speed;	// defines the max. data transfer rate per one data line
	UINT8 	ccc;		// command classes (class 0 - class 11)
	UINT8 	rd_blk_len;	// max. read data block length b[7:4]=ccc, b[3:0] = read block len
	UINT8 	blk_align;	// ???
	UINT8 	c_size;		// card capacity
	UINT8 	max_rd_curr;// max read current @VDD min-max
	UINT8 	max_wr_curr;// max write current @VDD min-max
	UINT8 	erase_sz;	// c_size_mult | erase single block enable | erase sector size
	UINT8 	wp_grp;		// write protect group size
	UINT8 	r2w_factor;	// write speed factor
	UINT8 	wr_blk_len;	// write data block length
	UINT8 	file_wp;	// file format gp | write protect etc
} CSD_T;

/*
***********************************************************************
* Each card has a set of information registers (see Chapter 5,
* Physical Layer Simplified Specification Version 2.00).
* The Card Identification (CID) register is 128bits wide.
* It contains the card id information during the card id phrase.
* Every individual card shall have a unique id number.
* For example, the manufacturer ID can be obtained from this register
***********************************************************************
*/
typedef struct tagCID2 
{
	UINT8 	rsvd;
	UINT8 	manuf_id;		// manufacturer ID
	UINT8 	oem_app_id[2];	// OEM or application ID
	UINT8 	pdt_name[5];	// product name
	UINT8 	pdt_rev;		// product version
	UINT8 	pdt_sn[4];		// serial number
	UINT8 	manuf_date[2];	// manufacturing date
} CID_T;

typedef struct tagMMC_CID2 
{
	UINT8 	rsvd;
	UINT8 	manuf_id;
	UINT8 	oem_app_id[2];
	UINT8 	pdt_name[6];
	UINT8 	pdt_rev;
	UINT8 	pdt_sn[4];
	UINT8 	manuf_date;
} MMC_CID_T;

/*
***********************************************************************
* In addition to the CSD register, there is another configuration
* register names SD CARD Configuration Register (SCR) which provides
* information on the SD Memory Card's special features that were configured
* into the given card
***********************************************************************
*/
typedef struct tagSCR2 
{
	// size if 64 bits. This register shall be set in the factory by the
	// manufacturer
	UINT8 	version;
	UINT8 	config;
	UINT16 	rsvd1;
	UINT32 	rsvd2;
} SCR_T;

#define CARDTYPE_SDMEM		1
#define CARDTYPE_SDIO		2		//SDIO is not supported in this version
#define CARDTYPE_MMC		4
#define CARDTYPE_SDHC		9

//these typedefs are specific for FATfs
typedef BYTE	DSTATUS;

/* Results of Disk Functions */
typedef enum {
	RES_OK = 0,		/* 0: Successful */
	RES_ERROR,		/* 1: R/W Error */
	RES_WRPRT,		/* 2: Write Protected */
	RES_NOTRDY,		/* 3: Not Ready */
	RES_PARERR		/* 4: Invalid Parameter */
} DRESULT;


#define MAX_WAIT				30000		//max wait loop for debounce, e.g. at ssd1928_SDCardDetect(void)
											//this value obtained from trail, varies with cpu speed

#define REG_u32DMAAddr 			0x1100
#define REG_u16BlkSize 			0x1104
#define REG_u16BlkCount 		0x1106
#define REG_u32Arg 				0x1108
#define REG_u16TrnsfrMode 		0x110c
#define REG_u16Cmd 				0x110e
#define REG_a32Rsp				0x1110
#define REG_u8DataPort			0x1120
#define REG_a8Rsvd1				0x1121
#define REG_u32PrsntState		0x1124
#define REG_u8HstCntl			0x1128
#define REG_u8PwrCntl			0x1129
#define REG_u8BlkGapCntl		0x112a
#define REG_u8WkupCntl			0x112b
#define REG_u8ClkCntl			0x112c
#define REG_u8ClkDiv			0x112d
#define REG_u8ToutCntl			0x112e
#define REG_u8SwReset			0x112f
#define REG_u16NrmIntrStatus	0x1130
#define REG_u16ErrIntrStatus	0x1132
#define REG_u16NrmIntrStatusEn	0x1134
#define REG_u16ErrIntrStatusEn	0x1136
#define REG_u16NrmIntrSignalEn	0x1138
#define REG_u16ErrIntrSignalEn	0x113a
#define REG_u16ACMD12ErrStatus	0x113c
#define REG_u16Rsvd2			0x113e
#define REG_u32Capabilities		0x1140
#define REG_u32CapRsvd			0x1144
#define REG_u32MaxCurrCap		0x1148
#define REG_u32MaxCurrCapRsvd	0x114c
#define REG_u32Rsvd3			0x1150/*REG_u32Rsvd[(0xFC - 0x50) >> 2]*/
#define REG_u16SlotIntrStatus	0x11fc
#define REG_u16HCVer			0x11fe	

// Bit mask for REG_u16Cmd; 16-bit register at Offset (0x0E) 
#define CMDR_IDX_MASK				SWAP16(0x3F00)				//Command index at D13-D08
#define CMDR_TYPE_MASK				SWAP16(BIT(7) | BIT(6))		//Command type incl. Suspend, Resume, and Abort
#define CMDR_DATA_PRESENT			BIT16(5)					//Data Present Select to indicate that data is present 
#define CMDR_IDX_CHECK_EN			BIT16(4)					//Command index check enable to indicate the Host Controller shall check the index field
#define CMDR_CRC_CHECK_EN			BIT16(3)					//CRC check enable
#define CMDR_RSPTYPE_MASK			SWAP16(BIT(1) | BIT(0))		//Response type select, 00(R0, no response), 01(R136, response length 136), 02(R48, length 48), 03(R48b, length 48+check busy)
#define CMD_IDX(x)					SWAP16((x) << 8)
#define CMD_TYPE(x)					SWAP16((x) << 6)		
#define ABORT						3
#define RESUME						2
#define SUSPEND						1
#define NORMAL						0
#define CMD_RSP(x)					SWAP16((x) << 0)
#define R0							0
#define R136						1
#define R48							2
#define R48b						3

// Present State Register Bits, 32-bits (0x24)
#define PSR_CMDLINE_SIGNAL			BIT32(24)
#define PSR_DATLINE_SIGNAL			SWAP32(BIT(23)|BIT(22)|BIT(21)|BIT(20))
#define PSR_WPSW_PIN				BIT32(19)
#define PSR_CARD_DET_PIN			BIT32(18)
#define PSR_CARD_STABLE				BIT32(17)
#define PSR_CARD_INSERTED			BIT32(16)
#define PSR_BUF_RDEN				BIT32(11)
#define PSR_BUF_WREN				BIT32(10)
#define PSR_RD_ACTIVE				BIT32(9)
#define PSR_WR_ACTIVE				BIT32(8)
#define PSR_DATLINE_ACTIVE			BIT32(2)
#define PSR_INHIBIT_DAT				BIT32(1)
#define PSR_INHIBIT_CMD				BIT32(0)

// Wakeup Control Register, 8-bit (0x2E)
#define WKR_CARD_REMOVAL			BIT(2)
#define WKR_CARD_INSERT				BIT(1)
#define WKR_CARD_IRQ				BIT(0)

// Software Reset Register bits, 8-bit (0x2F)
#define SW_RESET_DATA				BIT(2)
#define SW_RESET_CMD				BIT(1)
#define SW_RESET_ALL				BIT(0)


// Normal Interrupt Status Register at Offset (0x30)
// Bits are common between Status, Enable, and Signal Enable registers
#define INTR_ERR					BIT16(15)
#define INTR_CARD					BIT16(8)
#define INTR_CARD_REMOVAL			BIT16(7)
#define INTR_CARD_INSERTION			BIT16(6)
#define INTR_BUF_RD_RDY				BIT16(5)
#define INTR_BUF_WR_RDY				BIT16(4)
#define INTR_DMA					BIT16(3)
#define INTR_BLK_GAP				BIT16(2)
#define INTR_DAT_COMPLETE			BIT16(1)
#define INTR_CMD_COMPLETE			BIT16(0)

// Error Interrupt Status Register (0x32)
// Bits are common between Status, Enable, and Signal Enable registers
#define EINTR_VS_BLKSZ_ERR			BIT16(14)
#define EINTR_VS_DAT_CONFLICT		BIT16(13)
#define EINTR_VS_RSP_DIR			BIT16(12)
#define EINTR_AUTOCMD12				BIT16(8)
#define EINTR_CURR_LIMIT			BIT16(7)
#define EINTR_DAT_END				BIT16(6)
#define EINTR_DAT_CRC				BIT16(5)
#define EINTR_DAT_TOUT				BIT16(4)
#define EINTR_CMD_IDX				BIT16(3)
#define EINTR_CMD_END				BIT16(2)
#define EINTR_CMD_CRC				BIT16(1)
#define EINTR_CMD_TOUT				BIT16(0)

// List of Commands
#define CMD_RESET				0	// it is the reset command, of course
#define CMD_SEND_OCR			1	// used exclusively in MMC
#define CMD_SEND_ALL_CID		2	// R2: R136
#define CMD_SEND_RCA			3	// R1 (MMC) or R6(SDMEM)
#define CMD_SET_DSR				4
#define CMD_IO_SEND_OCR			5	// R4, unique to IO cards
#define CMD_SELECT_CARD			7	// R1, arg=rca[31..16] or 0
#define CMD_SEND_IF_COND		8   // SDHC card: Send Interface Condition Command 
#define CMD_SEND_CSD			9	// R2: R136
#define CMD_SEND_CID			10	// R2: R136
#define CMD_STOP_TRANSMISSION	12	// R1b: arg=stuff bits
#define CMD_SEND_STATUS			13	// R1
#define CMD_GO_INACTIVE			15	// None, arg=rca[31..16], stuff[15..0]
#define CMD_SET_BLKLEN			16	// R1, arg=block len[31..0]
#define CMD_RD_SINGLE			17	// R1, arg=block address[31..0]
#define CMD_RD_MULTIPLE			18	// R1, arg=block address[31..0]
#define CMD_WR_SINGLE			24	// R1, arg=block address[31..0]
#define CMD_WR_MULTIPLE			25 	// R1, arg=block address[31..0]
#define CMD_SET_WP				28	// R1b, arg=wp address[31..0]
#define CMD_CLR_WP				29	// R1b, arg=wp address[31..0]
#define CMD_SEND_WP				30	// R1, DATA, arg=wp address[31..0]
#define CMD_ERASE_SADDR			32	// R1, arg=block address[31..0]
#define CMD_ERASE_EADDR			33	// R1, arg=block address[31..0]
#define CMD_ERASE_GRP_SADDR		35	// R1, arg=block address[31..0]
#define CMD_ERASE_GRP_EADDR		36	// R1, arg=block address[31..0]
#define CMD_ERASE				38	// R1b, arg=stuff bits[31..0]
#define CMD_IO_RW_DIRECT		52	// R5
#define CMD_IO_RW_EXTENDED		53	// R1, data transfer
#define CMD_APP_CMD				55	// R1, arg=rca[31..16], stuff[15..0]
#define CMD_GEN_CMD				56	// R1, data, arg=stuff[31..1], RD/WR[0]
#define CMD_READ_OCR			58

#define ACMD_SET_BUS_WIDTH			6	// R1, arg=[1..0] = bus width, [31:2] stuff bits
#define ACMD_SEND_STATUS			13	// R1, DATA, arg=stuff bits [31..0]
#define ACMD_SEND_NUM_WR_BLK		22	// R1, DATA, arg=stuff bits [31..0]
#define ACMD_SEND_OCR				41
#define ACMD_SEND_SCR				51	// R1, arg=stuff bits[31..0]


SHORT	ssd1928_SDReset (BYTE reset_type);
SHORT 	ssd1928_SDCardDetect(void);
SHORT	ssd1928_SDPwrCntl(BOOL pwr);
SHORT   ssd1928_SDSetClk(BYTE div);


DSTATUS ssd1928_SDInit(BYTE disk);

#endif
