//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//
//------------------------------------------------------------------------------
//
//  Header: sdpdd.h
//

#ifndef __SDPDD_H
#define __SDPDD_H

#include <windows.h>

#define BLOCK_LEN  512
#define BLOCK_MASK (~(BLOCK_LEN-1))

//----------------------------------------------------------------------------------
//
//							LIST OF COMMAND TYPES
//
//----------------------------------------------------------------------------------

typedef enum {
	CMD_TYPE_BC   = 0,	// Broadcast Command no response (to all cards)
	CMD_TYPE_BCR  = 1,	// Broadcast Command w/ response (to all cards)
	CMD_TYPE_AC   = 2,	// Addressed Command no data 	 (to selected card)
	CMD_TYPE_ADTC = 3	// Addressed Command w/ data	 (to selected card)
} CMD_TYPE;


//----------------------------------------------------------------------------------
//
//		         			LIST OF RESPONSE TYPES
//
//----------------------------------------------------------------------------------

typedef enum {
	RESP_TYPE_NONE = 0,	// No Response
	RESP_TYPE_R1   = 1,	// Normal Response 
	RESP_TYPE_R1B  = 9,	// Normal Response with Busy
	RESP_TYPE_R2   = 2,	// CID/CSD Register Response (the long response)
	RESP_TYPE_R3   = 3,	// OCR (Operating condition) register
	RESP_TYPE_R4   = 4,	// Fast I/O Response			(MMC only)
	RESP_TYPE_R5   = 5,	// Interrupt Request Response		(MMC only)
	RESP_TYPE_R6   = 6,	// Published RCA Response		(SD only)
} RESP_TYPE;


//----------------------------------------------------------------------------------
//
//					      		 CARD REGISTERS
//
//----------------------------------------------------------------------------------

typedef enum {
	CARD_STATUS_REGISTER,
	OCR_REGISTER,	// OCR: Operating Conditions 
 	CID_REGISTER,   // CID: Card IDentification
	CSD_REGISTER,	// CSD: Card-Specific Data
	RCA_REGISTER,   // RCA: Relative Card Address
	SCR_REGISTER,   // SCR: SD-card Configuration (SD only)
} SD_RESPONSE;


// Standard host controller registers
#define SDHC_SYSTEMADDRESS_LO         0x00
#define SDHC_SYSTEMADDRESS_HI         0x02
#define SDHC_BLOCKSIZE                0x04
#define SDHC_BLOCKCOUNT               0x06
#define SDHC_ARGUMENT_0               0x08
#define SDHC_ARGUMENT_1               0x0A
#define SDHC_TRANSFERMODE             0x0C
#define SDHC_COMMAND                  0x0E
#define SDHC_R0                       0x10
#define SDHC_R1                       0x12
#define SDHC_R2                       0x14
#define SDHC_R3                       0x16
#define SDHC_R4                       0x18
#define SDHC_R5                       0x1A
#define SDHC_R6                       0x1C
#define SDHC_R7                       0x1E
#define SDHC_BUFFER_DATA_PORT_0       0x20
#define SDHC_BUFFER_DATA_PORT_1       0x22
#define SDHC_PRESENT_STATE            0x24
#define SDHC_HOST_CONTROL             0x28
#define SDHC_POWER_CONTROL            0x29
#define SDHC_BLOCK_GAP_CONTROL        0x2A
#define SDHC_WAKEUP_CONTROL           0x2B
#define SDHC_CLOCK_CONTROL            0x2C
#define SDHC_TIMEOUT_CONTROL          0x2E
#define SDHC_SOFT_RESET               0x2F
#define SDHC_NORMAL_INT_STATUS        0x30
#define SDHC_ERROR_INT_STATUS         0x32
#define SDHC_NORMAL_INT_STATUS_ENABLE 0x34
#define SDHC_ERROR_INT_STATUS_ENABLE  0x36
#define SDHC_NORMAL_INT_SIGNAL_ENABLE 0x38
#define SDHC_ERROR_INT_SIGNAL_ENABLE  0x3A
#define SDHC_AUTOCMD12_ERROR_STATUS   0x3C
#define SDHC_Reserved1                0x3E
#define SDHC_CAPABILITIES             0x40
#define SDHC_Reserved2                0x44
#define SDHC_MAX_CURRENT_CAPABILITIES 0x48
#define SDHC_Reserved3                0x4C
//#define   SDHC_Reserved4[43]        // 50H
#define SDHC_ADMA_ERROR_STATUS          0x54
#define SDHC_ADMA_SYSTEMADDRESS_LO      0x58
#define SDHC_ADMA_SYSTEMADDRESS_HI      0x5C

#define SDHC_SLOT_INT_STATUS          0xFC
#define SDHC_HOST_CONTROLLER_VER      0xFE


// Transfer Mode Register
#define TXN_MODE_DMA                    0x0001
#define TXN_MODE_BLOCK_COUNT_ENABLE     0x0002
#define TXN_MODE_AUTO_CMD12             0x0004
#define TXN_MODE_DATA_DIRECTION_READ    0x0010
#define TXN_MODE_MULTI_BLOCK            0x0020

// Command Register (3.2.6)
#define CMD_NO_RESPONSE                 0x0000
#define CMD_RESPONSE_LENGTH_136         0x0001
#define CMD_RESPONSE_LENGTH_48          0x0002
#define CMD_RESPONSE_LENGTH_48_BUSY     0x0003
#define CMD_CRC_CHECK                   0x0008
#define CMD_INDEX_CHECK                 0x0010
#define CMD_DATA_PRESENT                0x0020
#define CMD_TYPE_NORMAL                 0x0000
#define CMD_TYPE_RESUME                 0x0040
#define CMD_TYPE_SUSPEND                0x0080
#define CMD_TYPE_ABORT                  0x00c0

#define CMD_INDEX_MASK                  0x3F00
#define CMD_INDEX_SHIFT                 8
#define CMD_RESPONSE_R2                 (CMD_RESPONSE_LENGTH_136 | CMD_CRC_CHECK)
#define CMD_RESPONSE_R3_R4              CMD_RESPONSE_LENGTH_48
#define CMD_RESPONSE_R1_R5_R6_R7        (CMD_RESPONSE_LENGTH_48 | CMD_CRC_CHECK | CMD_INDEX_CHECK)
#define CMD_RESPONSE_R1B_R5B            (CMD_RESPONSE_LENGTH_48_BUSY | CMD_CRC_CHECK | CMD_INDEX_CHECK)

// Present State Register (3.2.9)
#define STATE_CMD_INHIBIT               0x00000001
#define STATE_DAT_INHIBIT               0x00000002
#define STATE_DAT_ACTIVE                0x00000004
#define STATE_WRITE_ACTIVE              0x00000100
#define STATE_READ_ACTIVE               0x00000200
#define STATE_BUF_WRITE_ENABLE          0x00000400
#define STATE_BUF_READ_ENABLE           0x00000800
#define STATE_CARD_INSERTED             0x00010000
#define STATE_CARD_STATE_STABLE         0x00020000
#define STATE_CARD_DETECT_SIGNAL        0x00040000
#define STATE_WRITE_PROTECT             0x00080000
#define STATE_DAT_LINE_SIGNAL           0x00F00000
#define STATE_CMD_LINE_SIGNAL           0x01000000

// Host Control Register (3.2.10)
#define HOSTCTL_LED_CONTROL             0x01
#define HOSTCTL_DAT_WIDTH_4BIT          0x02
#define HOSTCTL_HIGH_SPEED              0x04

// Power Control Register (3.2.11)
#define SDBUS_POWER_ON                  0x01
#define SDBUS_VOLTAGE_SELECT_3_3V       0x0E
#define SDBUS_VOLTAGE_SELECT_3_0V       0x0C
#define SDBUS_VOLTAGE_SELECT_1_8V       0x0A

// Wakeup Control Register (3.2.13)
#define WAKEUP_INTERRUPT                0x01
#define WAKEUP_INSERTION                0x02
#define WAKEUP_REMOVAL                  0x04

#define WAKEUP_ALL_SOURCES              (WAKEUP_INTERRUPT | WAKEUP_INSERTION | WAKEUP_REMOVAL)

// Clock Control Register (3.2.14)
#define CLOCK_INTERNAL_ENABLE           0x0001
#define CLOCK_STABLE                    0x0002
#define CLOCK_ENABLE                    0x0004

// Timeout Control Register (3.2.15)
#define TIME_DATA_TIMEOUT_MASK          0x000F

// Soft Reset Register  (3.2.16)
#define SOFT_RESET_ALL                  0x0001
#define SOFT_RESET_CMD                  0x0002
#define SOFT_RESET_DAT                  0x0004

// Normal Interrupt status register (3.2.17)
#define NORMAL_INT_STATUS_CMD_COMPLETE   0x0001
#define NORMAL_INT_STATUS_TRX_COMPLETE   0x0002
#define NORMAL_INT_STATUS_BLOCK_GAP      0x0004
#define NORMAL_INT_STATUS_DMA            0x0008
#define NORMAL_INT_STATUS_BUF_WRITE_RDY  0x0010
#define NORMAL_INT_STATUS_BUF_READ_RDY   0x0020
#define NORMAL_INT_STATUS_CARD_INSERTION 0x0040
#define NORMAL_INT_STATUS_CARD_REMOVAL   0x0080
#define NORMAL_INT_STATUS_CARD_INT       0x0100
#define NORMAL_INT_STATUS_ERROR_INT      0x8000

// Error Interrupt Status Register (3.2.18)
#define ERR_INT_STATUS_CMD_TIMEOUT       0x0001
#define ERR_INT_STATUS_CMD_CRC           0x0002
#define ERR_INT_STATUS_CMD_CONFLICT      (ERR_INT_STATUS_CMD_TIMEOUT | ERR_INT_STATUS_CMD_CRC_ERR)
#define ERR_INT_STATUS_CMD_ENDBIT        0x0004
#define ERR_INT_STATUS_CMD_INDEX         0x0008
#define ERR_INT_STATUS_DAT_TIMEOUT       0x0010
#define ERR_INT_STATUS_DAT_CRC           0x0020
#define ERR_INT_STATUS_DAT_ENDBIT        0x0040
#define ERR_INT_STATUS_BUS_POWER         0x0080
#define ERR_INT_STATUS_AUTOCMD12         0x0100
#define ERR_INT_STATUS_ADMA              0x0200
#define ERR_INT_STATUS_VENDOR            0xF000

#define IS_CMD_LINE_ERROR(x)    (((x) & 0x0F) != 0)
#define IS_DAT_LINE_ERROR(x)    (((x) & 0x70) != 0)

// Normal interrupt status enable register (3.2.19)
#define NORMAL_INT_ENABLE_CMD_COMPLETE   0x0001
#define NORMAL_INT_ENABLE_TRX_COMPLETE   0x0002
#define NORMAL_INT_ENABLE_BLOCK_GAP      0x0004
#define NORMAL_INT_ENABLE_DMA            0x0008
#define NORMAL_INT_ENABLE_BUF_WRITE_RDY  0x0010
#define NORMAL_INT_ENABLE_BUF_READ_RDY   0x0020
#define NORMAL_INT_ENABLE_CARD_INSERTION 0x0040
#define NORMAL_INT_ENABLE_CARD_REMOVAL   0x0080
#define NORMAL_INT_ENABLE_CARD_INT       0x0100

// Error Interrupt status enable register (3.2.20)
#define ERR_INT_ENABLE_CMD_TIMEOUT       0x0001
#define ERR_INT_ENABLE_CMD_CRC           0x0002
#define ERR_INT_ENABLE_CMD_ENDBIT        0x0004
#define ERR_INT_ENABLE_CMD_INDEX         0x0008
#define ERR_INT_ENABLE_DAT_TIMEOUT       0x0010
#define ERR_INT_ENABLE_DAT_CRC           0x0020
#define ERR_INT_ENABLE_DAT_ENDBIT        0x0040
#define ERR_INT_ENABLE_BUS_POWER         0x0080
#define ERR_INT_ENABLE_AUTOCMD12         0x0100

// Normal interrupt signal enable register (3.2.21)
#define NORMAL_INT_SIGNAL_CMD_COMPLETE   0x0001
#define NORMAL_INT_SIGNAL_TRX_COMPLETE   0x0002
#define NORMAL_INT_SIGNAL_BLOCK_GAP      0x0004
#define NORMAL_INT_SIGNAL_DMA            0x0008
#define NORMAL_INT_SIGNAL_BUF_WRITE_RDY  0x0010
#define NORMAL_INT_SIGNAL_BUF_READ_RDY   0x0020
#define NORMAL_INT_SIGNAL_CARD_INSERTION 0x0040
#define NORMAL_INT_SIGNAL_CARD_REMOVAL   0x0080
#define NORMAL_INT_SIGNAL_CARD_INT       0x0100

// Error Interrupt signal enable register (3.2.22)
#define ERR_INT_SIGNAL_CMD_TIMEOUT       0x0001
#define ERR_INT_SIGNAL_CMD_CRC           0x0002
#define ERR_INT_SIGNAL_CMD_ENDBIT        0x0004
#define ERR_INT_SIGNAL_CMD_INDEX         0x0008
#define ERR_INT_SIGNAL_DAT_TIMEOUT       0x0010
#define ERR_INT_SIGNAL_DAT_CRC           0x0020
#define ERR_INT_SIGNAL_DAT_ENDBIT        0x0040
#define ERR_INT_SIGNAL_BUS_POWER         0x0080
#define ERR_INT_SIGNAL_AUTOCMD12         0x0100

//----------------------------------------------------------------------------------
//
//							CARD STATUS REGISTER BITS
//
//----------------------------------------------------------------------------------

#define CSTAT_OUT_OF_RANGE			0x80000000
#define CSTAT_ADDRESS_ERROR			0x40000000
#define CSTAT_BLOCK_LEN_ERROR		0x20000000
#define CSTAT_ERASE_SEQ_ERROR		0x10000000
#define CSTAT_ERASE_PARAM			0x08000000
#define CSTAT_WP_VIOLATION			0x04000000
#define CSTAT_CARD_IS_LOCKED		0x02000000
#define CSTAT_LOCK_UNLOCK_FAILED	0x01000000
#define CSTAT_COM_CRC_ERROR			0x00800000
#define CSTAT_ILLEGAL_COMMAND		0x00400000
#define CSTAT_CARD_ECC_FAILED		0x00200000
#define CSTAT_CC_ERROR				0x00100000
#define CSTAT_ERROR					0x00080000
#define CSTAT_UNDERRUN				0x00040000
#define CSTAT_OVERRUN				0x00020000
#define CSTAT_CIDCSD_OVERWRITE		0x00010000
#define CSTAT_WP_ERASE_SKIP			0x00008000
#define CSTAT_CARD_ECC_DISABLED		0x00004000
#define CSTAT_CARD_ERASE_RESET		0x00002000
#define CSTAT_CURRENT_STATE			0x00001E00
#define	CSTAT_READY_FOR_DATA		0x00000100
#define	CSTAT_APP_CMD				0x00000020
#define CSTAT_AKE_SEQ_ERROR			0x00000008


//----------------------------------------------------------------------------------
//
//					OPERATING CONDITIONS (OCR) REGISTER BITS
//
//----------------------------------------------------------------------------------

#define OCR_POWER_UP_BUSY			0x80000000
#define	OCR_35_36_V					(1 << 23)
#define OCR_34_35_V					(1 << 22)
#define OCR_33_34_V					(1 << 21)
#define OCR_32_33_V					(1 << 20)
#define OCR_31_32_V					(1 << 19)
#define OCR_30_31_V					(1 << 18)
#define OCR_29_30_V					(1 << 17)
#define OCR_28_29_V					(1 << 16)
#define OCR_27_28_V					(1 << 15)
#define OCR_26_27_V					(1 << 14)
#define OCR_25_26_V					(1 << 13)
#define OCR_24_25_V					(1 << 12)
#define OCR_23_24_V					(1 << 11)
#define OCR_22_23_V					(1 << 10)
#define OCR_21_22_V					(1 << 9)
#define OCR_20_21_V					(1 << 8)
#define OCR_19_20_V					(1 << 7)
#define OCR_18_19_V					(1 << 6)
#define OCR_17_18_V					(1 << 5)
#define OCR_16_17_V					(1 << 4)


//----------------------------------------------------------------------------------
//
//					LIST OF SUPPORTED CAPABLILITIES
//
//----------------------------------------------------------------------------------

typedef enum {
	SET_OPEN_DRAIN			= 1,
	SET_4BIT_MODE			= 2,
	SET_CLOCK_RATE			= 3,
	GET_SUPPORTED_OCR_MMC	= 4,
	GET_SUPPORTED_OCR_SD	= 5,
} PDD_IOCTL;


//----------------------------------------------------------------------------------
//
//					LIST OF MDD<==>PDD INTERFACE
//
//----------------------------------------------------------------------------------

BOOL   PDD_SDInitializeHardware();

BOOL   PDD_SDSendCommand(UINT8 cmd, UINT32 arg, RESP_TYPE resp, CMD_TYPE type, BOOL read);
UINT32 PDD_SDGetResponse(SD_RESPONSE whichResp);

VOID   PDD_SDSetPDDCapabilities(PDD_IOCTL whichAbility, UINT32 Ability);
UINT32 PDD_SDGetPDDCapabilities(PDD_IOCTL whichAbility);

BOOL   PDD_SDReceiveData(UINT8* pBuffer);
VOID   PDD_SDStallExecute(UINT32 waitMs);

VOID SetActiveSlot(unsigned int ActiveSlot);
VOID WriteSDHCReg8(DWORD dwOffset,  BYTE Value);
VOID WriteSDHCReg16(DWORD dwOffset,  WORD Value);
VOID WriteSDHCReg32(DWORD dwOffset,  DWORD Value);
BYTE ReadSDHCReg8(DWORD dwOffset);
WORD ReadSDHCReg16(DWORD dwOffset);
DWORD ReadSDHCReg32(DWORD dwOffset);
VOID SD_SleepMSec(DWORD dwTimeout);
DWORD SD_GetMSecond();
BOOL SoftwareReset(BYTE bResetBits);
BOOL DetectSDCard();
VOID PowerOnSD();
VOID SDClockOn();
VOID SDClockOff();
BOOL PollingForCommandComplete();
BOOL HandleCommandComplete();
VOID SetClockRate(PDWORD pdwRate);
VOID HandleErrors();

#endif
