#include <rtthread.h>
#include <dfs_fs.h>

#include "sd.h"

#include <AT91SAM7X.h>

// *****************************************************************************
//               PIO DEFINITIONS FOR AT91SAM7X256
// *****************************************************************************
#define AT91C_PIO_PA0        ((unsigned int) 1 <<  0) // Pin Controlled by PA0
#define AT91C_PA0_RXD0     ((unsigned int) AT91C_PIO_PA0) //  USART 0 Receive Data
#define AT91C_PIO_PA1        ((unsigned int) 1 <<  1) // Pin Controlled by PA1
#define AT91C_PA1_TXD0     ((unsigned int) AT91C_PIO_PA1) //  USART 0 Transmit Data
#define AT91C_PIO_PA10       ((unsigned int) 1 << 10) // Pin Controlled by PA10
#define AT91C_PA10_TWD      ((unsigned int) AT91C_PIO_PA10) //  TWI Two-wire Serial Data
#define AT91C_PIO_PA11       ((unsigned int) 1 << 11) // Pin Controlled by PA11
#define AT91C_PA11_TWCK     ((unsigned int) AT91C_PIO_PA11) //  TWI Two-wire Serial Clock
#define AT91C_PIO_PA12       ((unsigned int) 1 << 12) // Pin Controlled by PA12
#define AT91C_PA12_SPI0_NPCS0 ((unsigned int) AT91C_PIO_PA12) //  SPI 0 Peripheral Chip Select 0
#define AT91C_PIO_PA13       ((unsigned int) 1 << 13) // Pin Controlled by PA13
#define AT91C_PA13_SPI0_NPCS1 ((unsigned int) AT91C_PIO_PA13) //  SPI 0 Peripheral Chip Select 1
#define AT91C_PA13_PCK1     ((unsigned int) AT91C_PIO_PA13) //  PMC Programmable Clock Output 1
#define AT91C_PIO_PA14       ((unsigned int) 1 << 14) // Pin Controlled by PA14
#define AT91C_PA14_SPI0_NPCS2 ((unsigned int) AT91C_PIO_PA14) //  SPI 0 Peripheral Chip Select 2
#define AT91C_PA14_IRQ1     ((unsigned int) AT91C_PIO_PA14) //  External Interrupt 1
#define AT91C_PIO_PA15       ((unsigned int) 1 << 15) // Pin Controlled by PA15
#define AT91C_PA15_SPI0_NPCS3 ((unsigned int) AT91C_PIO_PA15) //  SPI 0 Peripheral Chip Select 3
#define AT91C_PA15_TCLK2    ((unsigned int) AT91C_PIO_PA15) //  Timer Counter 2 external clock input
#define AT91C_PIO_PA16       ((unsigned int) 1 << 16) // Pin Controlled by PA16
#define AT91C_PA16_SPI0_MISO ((unsigned int) AT91C_PIO_PA16) //  SPI 0 Master In Slave
#define AT91C_PIO_PA17       ((unsigned int) 1 << 17) // Pin Controlled by PA17
#define AT91C_PA17_SPI0_MOSI ((unsigned int) AT91C_PIO_PA17) //  SPI 0 Master Out Slave
#define AT91C_PIO_PA18       ((unsigned int) 1 << 18) // Pin Controlled by PA18
#define AT91C_PA18_SPI0_SPCK ((unsigned int) AT91C_PIO_PA18) //  SPI 0 Serial Clock
#define AT91C_PIO_PA19       ((unsigned int) 1 << 19) // Pin Controlled by PA19
#define AT91C_PA19_CANRX    ((unsigned int) AT91C_PIO_PA19) //  CAN Receive
#define AT91C_PIO_PA2        ((unsigned int) 1 <<  2) // Pin Controlled by PA2
#define AT91C_PA2_SCK0     ((unsigned int) AT91C_PIO_PA2) //  USART 0 Serial Clock
#define AT91C_PA2_SPI1_NPCS1 ((unsigned int) AT91C_PIO_PA2) //  SPI 1 Peripheral Chip Select 1
#define AT91C_PIO_PA20       ((unsigned int) 1 << 20) // Pin Controlled by PA20
#define AT91C_PA20_CANTX    ((unsigned int) AT91C_PIO_PA20) //  CAN Transmit
#define AT91C_PIO_PA21       ((unsigned int) 1 << 21) // Pin Controlled by PA21
#define AT91C_PA21_TF       ((unsigned int) AT91C_PIO_PA21) //  SSC Transmit Frame Sync
#define AT91C_PA21_SPI1_NPCS0 ((unsigned int) AT91C_PIO_PA21) //  SPI 1 Peripheral Chip Select 0
#define AT91C_PIO_PA22       ((unsigned int) 1 << 22) // Pin Controlled by PA22
#define AT91C_PA22_TK       ((unsigned int) AT91C_PIO_PA22) //  SSC Transmit Clock
#define AT91C_PA22_SPI1_SPCK ((unsigned int) AT91C_PIO_PA22) //  SPI 1 Serial Clock
#define AT91C_PIO_PA23       ((unsigned int) 1 << 23) // Pin Controlled by PA23
#define AT91C_PA23_TD       ((unsigned int) AT91C_PIO_PA23) //  SSC Transmit data
#define AT91C_PA23_SPI1_MOSI ((unsigned int) AT91C_PIO_PA23) //  SPI 1 Master Out Slave
#define AT91C_PIO_PA24       ((unsigned int) 1 << 24) // Pin Controlled by PA24
#define AT91C_PA24_RD       ((unsigned int) AT91C_PIO_PA24) //  SSC Receive Data
#define AT91C_PA24_SPI1_MISO ((unsigned int) AT91C_PIO_PA24) //  SPI 1 Master In Slave
#define AT91C_PIO_PA25       ((unsigned int) 1 << 25) // Pin Controlled by PA25
#define AT91C_PA25_RK       ((unsigned int) AT91C_PIO_PA25) //  SSC Receive Clock
#define AT91C_PA25_SPI1_NPCS1 ((unsigned int) AT91C_PIO_PA25) //  SPI 1 Peripheral Chip Select 1
#define AT91C_PIO_PA26       ((unsigned int) 1 << 26) // Pin Controlled by PA26
#define AT91C_PA26_RF       ((unsigned int) AT91C_PIO_PA26) //  SSC Receive Frame Sync
#define AT91C_PA26_SPI1_NPCS2 ((unsigned int) AT91C_PIO_PA26) //  SPI 1 Peripheral Chip Select 2
#define AT91C_PIO_PA27       ((unsigned int) 1 << 27) // Pin Controlled by PA27
#define AT91C_PA27_DRXD     ((unsigned int) AT91C_PIO_PA27) //  DBGU Debug Receive Data
#define AT91C_PA27_PCK3     ((unsigned int) AT91C_PIO_PA27) //  PMC Programmable Clock Output 3
#define AT91C_PIO_PA28       ((unsigned int) 1 << 28) // Pin Controlled by PA28
#define AT91C_PA28_DTXD     ((unsigned int) AT91C_PIO_PA28) //  DBGU Debug Transmit Data
#define AT91C_PIO_PA29       ((unsigned int) 1 << 29) // Pin Controlled by PA29
#define AT91C_PA29_FIQ      ((unsigned int) AT91C_PIO_PA29) //  AIC Fast Interrupt Input
#define AT91C_PA29_SPI1_NPCS3 ((unsigned int) AT91C_PIO_PA29) //  SPI 1 Peripheral Chip Select 3
#define AT91C_PIO_PA3        ((unsigned int) 1 <<  3) // Pin Controlled by PA3
#define AT91C_PA3_RTS0     ((unsigned int) AT91C_PIO_PA3) //  USART 0 Ready To Send
#define AT91C_PA3_SPI1_NPCS2 ((unsigned int) AT91C_PIO_PA3) //  SPI 1 Peripheral Chip Select 2
#define AT91C_PIO_PA30       ((unsigned int) 1 << 30) // Pin Controlled by PA30
#define AT91C_PA30_IRQ0     ((unsigned int) AT91C_PIO_PA30) //  External Interrupt 0
#define AT91C_PA30_PCK2     ((unsigned int) AT91C_PIO_PA30) //  PMC Programmable Clock Output 2
#define AT91C_PIO_PA4        ((unsigned int) 1 <<  4) // Pin Controlled by PA4
#define AT91C_PA4_CTS0     ((unsigned int) AT91C_PIO_PA4) //  USART 0 Clear To Send
#define AT91C_PA4_SPI1_NPCS3 ((unsigned int) AT91C_PIO_PA4) //  SPI 1 Peripheral Chip Select 3
#define AT91C_PIO_PA5        ((unsigned int) 1 <<  5) // Pin Controlled by PA5
#define AT91C_PA5_RXD1     ((unsigned int) AT91C_PIO_PA5) //  USART 1 Receive Data
#define AT91C_PIO_PA6        ((unsigned int) 1 <<  6) // Pin Controlled by PA6
#define AT91C_PA6_TXD1     ((unsigned int) AT91C_PIO_PA6) //  USART 1 Transmit Data
#define AT91C_PIO_PA7        ((unsigned int) 1 <<  7) // Pin Controlled by PA7
#define AT91C_PA7_SCK1     ((unsigned int) AT91C_PIO_PA7) //  USART 1 Serial Clock
#define AT91C_PA7_SPI0_NPCS1 ((unsigned int) AT91C_PIO_PA7) //  SPI 0 Peripheral Chip Select 1
#define AT91C_PIO_PA8        ((unsigned int) 1 <<  8) // Pin Controlled by PA8
#define AT91C_PA8_RTS1     ((unsigned int) AT91C_PIO_PA8) //  USART 1 Ready To Send
#define AT91C_PA8_SPI0_NPCS2 ((unsigned int) AT91C_PIO_PA8) //  SPI 0 Peripheral Chip Select 2
#define AT91C_PIO_PA9        ((unsigned int) 1 <<  9) // Pin Controlled by PA9
#define AT91C_PA9_CTS1     ((unsigned int) AT91C_PIO_PA9) //  USART 1 Clear To Send
#define AT91C_PA9_SPI0_NPCS3 ((unsigned int) AT91C_PIO_PA9) //  SPI 0 Peripheral Chip Select 3
#define AT91C_PIO_PB0        ((unsigned int) 1 <<  0) // Pin Controlled by PB0
#define AT91C_PB0_ETXCK_EREFCK ((unsigned int) AT91C_PIO_PB0) //  Ethernet MAC Transmit Clock/Reference Clock
#define AT91C_PB0_PCK0     ((unsigned int) AT91C_PIO_PB0) //  PMC Programmable Clock Output 0
#define AT91C_PIO_PB1        ((unsigned int) 1 <<  1) // Pin Controlled by PB1
#define AT91C_PB1_ETXEN    ((unsigned int) AT91C_PIO_PB1) //  Ethernet MAC Transmit Enable
#define AT91C_PIO_PB10       ((unsigned int) 1 << 10) // Pin Controlled by PB10
#define AT91C_PB10_ETX2     ((unsigned int) AT91C_PIO_PB10) //  Ethernet MAC Transmit Data 2
#define AT91C_PB10_SPI1_NPCS1 ((unsigned int) AT91C_PIO_PB10) //  SPI 1 Peripheral Chip Select 1
#define AT91C_PIO_PB11       ((unsigned int) 1 << 11) // Pin Controlled by PB11
#define AT91C_PB11_ETX3     ((unsigned int) AT91C_PIO_PB11) //  Ethernet MAC Transmit Data 3
#define AT91C_PB11_SPI1_NPCS2 ((unsigned int) AT91C_PIO_PB11) //  SPI 1 Peripheral Chip Select 2
#define AT91C_PIO_PB12       ((unsigned int) 1 << 12) // Pin Controlled by PB12
#define AT91C_PB12_ETXER    ((unsigned int) AT91C_PIO_PB12) //  Ethernet MAC Transmikt Coding Error
#define AT91C_PB12_TCLK0    ((unsigned int) AT91C_PIO_PB12) //  Timer Counter 0 external clock input
#define AT91C_PIO_PB13       ((unsigned int) 1 << 13) // Pin Controlled by PB13
#define AT91C_PB13_ERX2     ((unsigned int) AT91C_PIO_PB13) //  Ethernet MAC Receive Data 2
#define AT91C_PB13_SPI0_NPCS1 ((unsigned int) AT91C_PIO_PB13) //  SPI 0 Peripheral Chip Select 1
#define AT91C_PIO_PB14       ((unsigned int) 1 << 14) // Pin Controlled by PB14
#define AT91C_PB14_ERX3     ((unsigned int) AT91C_PIO_PB14) //  Ethernet MAC Receive Data 3
#define AT91C_PB14_SPI0_NPCS2 ((unsigned int) AT91C_PIO_PB14) //  SPI 0 Peripheral Chip Select 2
#define AT91C_PIO_PB15       ((unsigned int) 1 << 15) // Pin Controlled by PB15
#define AT91C_PB15_ERXDV_ECRSDV ((unsigned int) AT91C_PIO_PB15) //  Ethernet MAC Receive Data Valid
#define AT91C_PIO_PB16       ((unsigned int) 1 << 16) // Pin Controlled by PB16
#define AT91C_PB16_ECOL     ((unsigned int) AT91C_PIO_PB16) //  Ethernet MAC Collision Detected
#define AT91C_PB16_SPI1_NPCS3 ((unsigned int) AT91C_PIO_PB16) //  SPI 1 Peripheral Chip Select 3
#define AT91C_PIO_PB17       ((unsigned int) 1 << 17) // Pin Controlled by PB17
#define AT91C_PB17_ERXCK    ((unsigned int) AT91C_PIO_PB17) //  Ethernet MAC Receive Clock
#define AT91C_PB17_SPI0_NPCS3 ((unsigned int) AT91C_PIO_PB17) //  SPI 0 Peripheral Chip Select 3
#define AT91C_PIO_PB18       ((unsigned int) 1 << 18) // Pin Controlled by PB18
#define AT91C_PB18_EF100    ((unsigned int) AT91C_PIO_PB18) //  Ethernet MAC Force 100 Mbits/sec
#define AT91C_PB18_ADTRG    ((unsigned int) AT91C_PIO_PB18) //  ADC External Trigger
#define AT91C_PIO_PB19       ((unsigned int) 1 << 19) // Pin Controlled by PB19
#define AT91C_PB19_PWM0     ((unsigned int) AT91C_PIO_PB19) //  PWM Channel 0
#define AT91C_PB19_TCLK1    ((unsigned int) AT91C_PIO_PB19) //  Timer Counter 1 external clock input
#define AT91C_PIO_PB2        ((unsigned int) 1 <<  2) // Pin Controlled by PB2
#define AT91C_PB2_ETX0     ((unsigned int) AT91C_PIO_PB2) //  Ethernet MAC Transmit Data 0
#define AT91C_PIO_PB20       ((unsigned int) 1 << 20) // Pin Controlled by PB20
#define AT91C_PB20_PWM1     ((unsigned int) AT91C_PIO_PB20) //  PWM Channel 1
#define AT91C_PB20_PCK0     ((unsigned int) AT91C_PIO_PB20) //  PMC Programmable Clock Output 0
#define AT91C_PIO_PB21       ((unsigned int) 1 << 21) // Pin Controlled by PB21
#define AT91C_PB21_PWM2     ((unsigned int) AT91C_PIO_PB21) //  PWM Channel 2
#define AT91C_PB21_PCK1     ((unsigned int) AT91C_PIO_PB21) //  PMC Programmable Clock Output 1
#define AT91C_PIO_PB22       ((unsigned int) 1 << 22) // Pin Controlled by PB22
#define AT91C_PB22_PWM3     ((unsigned int) AT91C_PIO_PB22) //  PWM Channel 3
#define AT91C_PB22_PCK2     ((unsigned int) AT91C_PIO_PB22) //  PMC Programmable Clock Output 2
#define AT91C_PIO_PB23       ((unsigned int) 1 << 23) // Pin Controlled by PB23
#define AT91C_PB23_TIOA0    ((unsigned int) AT91C_PIO_PB23) //  Timer Counter 0 Multipurpose Timer I/O Pin A
#define AT91C_PB23_DCD1     ((unsigned int) AT91C_PIO_PB23) //  USART 1 Data Carrier Detect
#define AT91C_PIO_PB24       ((unsigned int) 1 << 24) // Pin Controlled by PB24
#define AT91C_PB24_TIOB0    ((unsigned int) AT91C_PIO_PB24) //  Timer Counter 0 Multipurpose Timer I/O Pin B
#define AT91C_PB24_DSR1     ((unsigned int) AT91C_PIO_PB24) //  USART 1 Data Set ready
#define AT91C_PIO_PB25       ((unsigned int) 1 << 25) // Pin Controlled by PB25
#define AT91C_PB25_TIOA1    ((unsigned int) AT91C_PIO_PB25) //  Timer Counter 1 Multipurpose Timer I/O Pin A
#define AT91C_PB25_DTR1     ((unsigned int) AT91C_PIO_PB25) //  USART 1 Data Terminal ready
#define AT91C_PIO_PB26       ((unsigned int) 1 << 26) // Pin Controlled by PB26
#define AT91C_PB26_TIOB1    ((unsigned int) AT91C_PIO_PB26) //  Timer Counter 1 Multipurpose Timer I/O Pin B
#define AT91C_PB26_RI1      ((unsigned int) AT91C_PIO_PB26) //  USART 1 Ring Indicator
#define AT91C_PIO_PB27       ((unsigned int) 1 << 27) // Pin Controlled by PB27
#define AT91C_PB27_TIOA2    ((unsigned int) AT91C_PIO_PB27) //  Timer Counter 2 Multipurpose Timer I/O Pin A
#define AT91C_PB27_PWM0     ((unsigned int) AT91C_PIO_PB27) //  PWM Channel 0
#define AT91C_PIO_PB28       ((unsigned int) 1 << 28) // Pin Controlled by PB28
#define AT91C_PB28_TIOB2    ((unsigned int) AT91C_PIO_PB28) //  Timer Counter 2 Multipurpose Timer I/O Pin B
#define AT91C_PB28_PWM1     ((unsigned int) AT91C_PIO_PB28) //  PWM Channel 1
#define AT91C_PIO_PB29       ((unsigned int) 1 << 29) // Pin Controlled by PB29
#define AT91C_PB29_PCK1     ((unsigned int) AT91C_PIO_PB29) //  PMC Programmable Clock Output 1
#define AT91C_PB29_PWM2     ((unsigned int) AT91C_PIO_PB29) //  PWM Channel 2
#define AT91C_PIO_PB3        ((unsigned int) 1 <<  3) // Pin Controlled by PB3
#define AT91C_PB3_ETX1     ((unsigned int) AT91C_PIO_PB3) //  Ethernet MAC Transmit Data 1
#define AT91C_PIO_PB30       ((unsigned int) 1 << 30) // Pin Controlled by PB30
#define AT91C_PB30_PCK2     ((unsigned int) AT91C_PIO_PB30) //  PMC Programmable Clock Output 2
#define AT91C_PB30_PWM3     ((unsigned int) AT91C_PIO_PB30) //  PWM Channel 3
#define AT91C_PIO_PB4        ((unsigned int) 1 <<  4) // Pin Controlled by PB4
#define AT91C_PB4_ECRS     ((unsigned int) AT91C_PIO_PB4) //  Ethernet MAC Carrier Sense/Carrier Sense and Data Valid
#define AT91C_PIO_PB5        ((unsigned int) 1 <<  5) // Pin Controlled by PB5
#define AT91C_PB5_ERX0     ((unsigned int) AT91C_PIO_PB5) //  Ethernet MAC Receive Data 0
#define AT91C_PIO_PB6        ((unsigned int) 1 <<  6) // Pin Controlled by PB6
#define AT91C_PB6_ERX1     ((unsigned int) AT91C_PIO_PB6) //  Ethernet MAC Receive Data 1
#define AT91C_PIO_PB7        ((unsigned int) 1 <<  7) // Pin Controlled by PB7
#define AT91C_PB7_ERXER    ((unsigned int) AT91C_PIO_PB7) //  Ethernet MAC Receive Error
#define AT91C_PIO_PB8        ((unsigned int) 1 <<  8) // Pin Controlled by PB8
#define AT91C_PB8_EMDC     ((unsigned int) AT91C_PIO_PB8) //  Ethernet MAC Management Data Clock
#define AT91C_PIO_PB9        ((unsigned int) 1 <<  9) // Pin Controlled by PB9
#define AT91C_PB9_EMDIO    ((unsigned int) AT91C_PIO_PB9) //  Ethernet MAC Management Data Input/Output

#define CARD_WP_PIN      AT91C_PIO_PA16
#define CARD_INS_PIN     AT91C_PIO_PA15
#define CARD_PWR_PIN     AT91C_PIO_PA12

typedef volatile unsigned int AT91S_REG;// Hardware register definition
// *****************************************************************************
//              SOFTWARE API DEFINITION  FOR Serial Parallel Interface
// *****************************************************************************
typedef struct _AT91S_SPI {
	AT91S_REG	 SPI_CR; 	// Control Register
	AT91S_REG	 SPI_MR; 	// Mode Register
	AT91S_REG	 SPI_RDR; 	// Receive Data Register
	AT91S_REG	 SPI_TDR; 	// Transmit Data Register
	AT91S_REG	 SPI_SR; 	// Status Register
	AT91S_REG	 SPI_IER; 	// Interrupt Enable Register
	AT91S_REG	 SPI_IDR; 	// Interrupt Disable Register
	AT91S_REG	 SPI_IMR; 	// Interrupt Mask Register
	AT91S_REG	 Reserved0[4]; 	// 
	AT91S_REG	 SPI_CSR[4]; 	// Chip Select Register
	AT91S_REG	 Reserved1[48]; 	// 
	AT91S_REG	 SPI_RPR; 	// Receive Pointer Register
	AT91S_REG	 SPI_RCR; 	// Receive Counter Register
	AT91S_REG	 SPI_TPR; 	// Transmit Pointer Register
	AT91S_REG	 SPI_TCR; 	// Transmit Counter Register
	AT91S_REG	 SPI_RNPR; 	// Receive Next Pointer Register
	AT91S_REG	 SPI_RNCR; 	// Receive Next Counter Register
	AT91S_REG	 SPI_TNPR; 	// Transmit Next Pointer Register
	AT91S_REG	 SPI_TNCR; 	// Transmit Next Counter Register
	AT91S_REG	 SPI_PTCR; 	// PDC Transfer Control Register
	AT91S_REG	 SPI_PTSR; 	// PDC Transfer Status Register
} AT91S_SPI, *AT91PS_SPI;
static AT91PS_SPI pSPI  = ((AT91PS_SPI) 0xFFFE0000);

// -------- SPI_CR : (SPI Offset: 0x0) SPI Control Register -------- 
#define AT91C_SPI_SPIEN       ((unsigned int) 0x1 <<  0) // (SPI) SPI Enable
#define AT91C_SPI_SPIDIS      ((unsigned int) 0x1 <<  1) // (SPI) SPI Disable
#define AT91C_SPI_SWRST       ((unsigned int) 0x1 <<  7) // (SPI) SPI Software reset
#define AT91C_SPI_LASTXFER    ((unsigned int) 0x1 << 24) // (SPI) SPI Last Transfer
// -------- SPI_MR : (SPI Offset: 0x4) SPI Mode Register -------- 
#define AT91C_SPI_MSTR        ((unsigned int) 0x1 <<  0) // (SPI) Master/Slave Mode
#define AT91C_SPI_PS          ((unsigned int) 0x1 <<  1) // (SPI) Peripheral Select
#define 	AT91C_SPI_PS_FIXED                ((unsigned int) 0x0 <<  1) // (SPI) Fixed Peripheral Select
#define 	AT91C_SPI_PS_VARIABLE             ((unsigned int) 0x1 <<  1) // (SPI) Variable Peripheral Select
#define AT91C_SPI_PCSDEC      ((unsigned int) 0x1 <<  2) // (SPI) Chip Select Decode
#define AT91C_SPI_FDIV        ((unsigned int) 0x1 <<  3) // (SPI) Clock Selection
#define AT91C_SPI_MODFDIS     ((unsigned int) 0x1 <<  4) // (SPI) Mode Fault Detection
#define AT91C_SPI_LLB         ((unsigned int) 0x1 <<  7) // (SPI) Clock Selection
#define AT91C_SPI_PCS         ((unsigned int) 0xF << 16) // (SPI) Peripheral Chip Select
#define AT91C_SPI_DLYBCS      ((unsigned int) 0xFF << 24) // (SPI) Delay Between Chip Selects
// -------- SPI_RDR : (SPI Offset: 0x8) Receive Data Register -------- 
#define AT91C_SPI_RD          ((unsigned int) 0xFFFF <<  0) // (SPI) Receive Data
#define AT91C_SPI_RPCS        ((unsigned int) 0xF << 16) // (SPI) Peripheral Chip Select Status
// -------- SPI_TDR : (SPI Offset: 0xc) Transmit Data Register -------- 
#define AT91C_SPI_TD          ((unsigned int) 0xFFFF <<  0) // (SPI) Transmit Data
#define AT91C_SPI_TPCS        ((unsigned int) 0xF << 16) // (SPI) Peripheral Chip Select Status
// -------- SPI_SR : (SPI Offset: 0x10) Status Register -------- 
#define AT91C_SPI_RDRF        ((unsigned int) 0x1 <<  0) // (SPI) Receive Data Register Full
#define AT91C_SPI_TDRE        ((unsigned int) 0x1 <<  1) // (SPI) Transmit Data Register Empty
#define AT91C_SPI_MODF        ((unsigned int) 0x1 <<  2) // (SPI) Mode Fault Error
#define AT91C_SPI_OVRES       ((unsigned int) 0x1 <<  3) // (SPI) Overrun Error Status
#define AT91C_SPI_ENDRX       ((unsigned int) 0x1 <<  4) // (SPI) End of Receiver Transfer
#define AT91C_SPI_ENDTX       ((unsigned int) 0x1 <<  5) // (SPI) End of Receiver Transfer
#define AT91C_SPI_RXBUFF      ((unsigned int) 0x1 <<  6) // (SPI) RXBUFF Interrupt
#define AT91C_SPI_TXBUFE      ((unsigned int) 0x1 <<  7) // (SPI) TXBUFE Interrupt
#define AT91C_SPI_NSSR        ((unsigned int) 0x1 <<  8) // (SPI) NSSR Interrupt
#define AT91C_SPI_TXEMPTY     ((unsigned int) 0x1 <<  9) // (SPI) TXEMPTY Interrupt
#define AT91C_SPI_SPIENS      ((unsigned int) 0x1 << 16) // (SPI) Enable Status
// -------- SPI_IER : (SPI Offset: 0x14) Interrupt Enable Register -------- 
// -------- SPI_IDR : (SPI Offset: 0x18) Interrupt Disable Register -------- 
// -------- SPI_IMR : (SPI Offset: 0x1c) Interrupt Mask Register -------- 
// -------- SPI_CSR : (SPI Offset: 0x30) Chip Select Register -------- 
#define AT91C_SPI_CPOL        ((unsigned int) 0x1 <<  0) // (SPI) Clock Polarity
#define AT91C_SPI_NCPHA       ((unsigned int) 0x1 <<  1) // (SPI) Clock Phase
#define AT91C_SPI_CSAAT       ((unsigned int) 0x1 <<  3) // (SPI) Chip Select Active After Transfer
#define AT91C_SPI_BITS        ((unsigned int) 0xF <<  4) // (SPI) Bits Per Transfer
#define 	AT91C_SPI_BITS_8                    ((unsigned int) 0x0 <<  4) // (SPI) 8 Bits Per transfer
#define 	AT91C_SPI_BITS_9                    ((unsigned int) 0x1 <<  4) // (SPI) 9 Bits Per transfer
#define 	AT91C_SPI_BITS_10                   ((unsigned int) 0x2 <<  4) // (SPI) 10 Bits Per transfer
#define 	AT91C_SPI_BITS_11                   ((unsigned int) 0x3 <<  4) // (SPI) 11 Bits Per transfer
#define 	AT91C_SPI_BITS_12                   ((unsigned int) 0x4 <<  4) // (SPI) 12 Bits Per transfer
#define 	AT91C_SPI_BITS_13                   ((unsigned int) 0x5 <<  4) // (SPI) 13 Bits Per transfer
#define 	AT91C_SPI_BITS_14                   ((unsigned int) 0x6 <<  4) // (SPI) 14 Bits Per transfer
#define 	AT91C_SPI_BITS_15                   ((unsigned int) 0x7 <<  4) // (SPI) 15 Bits Per transfer
#define 	AT91C_SPI_BITS_16                   ((unsigned int) 0x8 <<  4) // (SPI) 16 Bits Per transfer
#define AT91C_SPI_SCBR        ((unsigned int) 0xFF <<  8) // (SPI) Serial Clock Baud Rate
#define AT91C_SPI_DLYBS       ((unsigned int) 0xFF << 16) // (SPI) Delay Before SPCK
#define AT91C_SPI_DLYBCT      ((unsigned int) 0xFF << 24) // (SPI) Delay Between Consecutive Transfers

#define CARD_SELECT_PIN  AT91C_PA13_SPI0_NPCS1
#define SPI_CSR_NUM      0

#define SPI_SCBR_MIN     2

/* MMC/SD command (in SPI) */
#define CMD0    (0x40+0)    /* GO_IDLE_STATE */
#define CMD1    (0x40+1)    /* SEND_OP_COND */
#define CMD9    (0x40+9)    /* SEND_CSD */
#define CMD10   (0x40+10)   /* SEND_CID */
#define CMD12   (0x40+12)   /* STOP_TRANSMISSION */
#define CMD17   (0x40+17)   /* READ_SINGLE_BLOCK */
#define CMD18   (0x40+18)   /* READ_MULTIPLE_BLOCK */
#define CMD24   (0x40+24)   /* WRITE_BLOCK */
#define CMD25   (0x40+25)   /* WRITE_MULTIPLE_BLOCK */
#define CMD58   (0x40+58)   /* READ_OCR */

/* Control signals (Platform dependent) */
#define SELECT()        (AT91C_PIOA_CODR = CARD_SELECT_PIN) /* MMC CS = L */
#define DESELECT()      (AT91C_PIOA_SODR = CARD_SELECT_PIN) /* MMC CS = H */

#define SOCKWP          CARD_WP_PIN         /* Write protect switch (PB5) */
#define SOCKINS         CARD_INS_PIN        /* Card detect switch (PB4) */

#define POWER_ON()      (AT91C_PIOA_CODR = CARD_PWR_PIN)
#define POWER_OFF()     (AT91C_PIOA_SODR = CARD_PWR_PIN)

static struct rt_device sd;
static struct dfs_partition part;

static void AT91_spiSetSpeed(rt_uint8_t speed)
{
	rt_uint32_t reg;

	if ( speed < SPI_SCBR_MIN ) speed = SPI_SCBR_MIN;
	if ( speed > 1 ) speed &= 0xFE;

	reg = pSPI->SPI_CSR[SPI_CSR_NUM];
	reg = ( reg & ~(AT91C_SPI_SCBR) ) | ( (rt_uint32_t)speed << 8 );
	pSPI->SPI_CSR[SPI_CSR_NUM] = reg;
}

static rt_uint8_t AT91_spi(rt_uint8_t outgoing)
{
	rt_uint8_t incoming;

	while( !( pSPI->SPI_SR & AT91C_SPI_TDRE ) ); // transfer compl. wait
	pSPI->SPI_TDR = (rt_uint16_t)( outgoing );

	while( !( pSPI->SPI_SR & AT91C_SPI_RDRF ) ); // wait for char
	incoming = (rt_uint8_t)( pSPI->SPI_RDR );

	return incoming;
}

/*--------------------------------*/
/* Transmit a rt_uint8_t to MMC via SPI */
/* (Platform dependent)           */
rt_inline void xmit_spi(rt_uint8_t dat)
{
	AT91_spi(dat);
}

/*---------------------------------*/
/* Receive a rt_uint8_t from MMC via SPI */
/* (Platform dependent)            */
rt_inline rt_uint8_t rcvr_spi(void)
{
	return AT91_spi(0xff);
}

/* Alternative "macro" (not at AT91 so far) to receive data fast */
static void rcvr_spi_m(rt_uint8_t *dst)
{
	*dst = rcvr_spi();
}

/*---------------------*/
/* Wait for card ready */
static rt_uint8_t wait_ready ()
{
	rt_uint8_t res;

	rcvr_spi();
	do
	{
		res = rcvr_spi();
	} while ((res != 0xFF));

	return res;
}

/*--------------------------------*/
/* Receive a data packet from MMC */

rt_bool_t rcvr_datablock (rt_uint8_t *buff, rt_uint8_t wc)
{
	rt_uint8_t token;

	{
	    /* Wait for data packet in timeout of 100ms */
		token = rcvr_spi();
	}while ((token == 0xFF));

	if(token != 0xFE) return RT_FALSE;   /* If not valid data token, retutn with error */

	do
	{
	    /* Receive the data block into buffer */
		rcvr_spi_m(buff++);
		rcvr_spi_m(buff++);
	} while (--wc);

	rcvr_spi();                  /* Discard CRC */
	rcvr_spi();

	return RT_TRUE;               /* Return with success */
}

/*---------------------------*/
/* Send a data packet to MMC */
static rt_bool_t xmit_datablock(const rt_uint8_t *buff, rt_uint8_t token)
{
	rt_uint8_t resp, wc = 0;

	if (wait_ready() != 0xFF) return RT_FALSE;

	xmit_spi(token);                    /* Xmit data token */
	if (token != 0xFD)
	{   /* Is data token */
		do
		{
		    /* Xmit the 512 rt_uint8_t data block to MMC */
			xmit_spi(*buff++);
			xmit_spi(*buff++);
		} while (--wc);

		xmit_spi(0xFF);                 /* CRC (Dummy) */
		xmit_spi(0xFF);
		resp = rcvr_spi();              /* Reveive data response */

		if ((resp & 0x1F) != 0x05)      /* If not accepted, return with error */
			return RT_FALSE;
	}

	return RT_TRUE;
}

/*------------------------------*/
/* Send a command packet to MMC */
rt_uint8_t send_cmd (rt_uint8_t cmd, rt_uint32_t arg)
{
	rt_uint8_t n, res;

	if (wait_ready() != 0xFF) return 0xFF;

	/* Send command packet */
	xmit_spi(cmd);                      /* Command */
	xmit_spi((rt_uint8_t)(arg >> 24));  /* Argument[31..24] */
	xmit_spi((rt_uint8_t)(arg >> 16));  /* Argument[23..16] */
	xmit_spi((rt_uint8_t)(arg >> 8));   /* Argument[15..8] */
	xmit_spi((rt_uint8_t)arg);          /* Argument[7..0] */
	xmit_spi(0x95);                     /* CRC (valid for only CMD0) */

	/* Receive command response */
	if (cmd == CMD12) rcvr_spi();       /* Skip a stuff rt_uint8_t when stop reading */
	n = 10;                             /* Wait for a valid response in timeout of 10 attempts */
	do
	{
		res = rcvr_spi();
	}
	while ((res & 0x80) && --n);

	return res;         /* Return with the response value */
}

static rt_err_t rt_sdcard_init(rt_device_t dev)
{
	return RT_EOK;
}

static rt_err_t rt_sdcard_open(rt_device_t dev, rt_uint16_t oflag)
{
	return RT_EOK;
}

static rt_err_t rt_sdcard_close(rt_device_t dev)
{
	return RT_EOK;
}

static rt_size_t rt_sdcard_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
	rt_uint8_t count;

	count  = size / 512;

	/* CS = L */
	SELECT();
	
	/* append partition offset */
	pos += part.offset * 512;

	if (count == 1)
	{   /* Single block read */
		if ((send_cmd(CMD17, pos) == 0)   /* READ_SINGLE_BLOCK */
				&& rcvr_datablock(buffer, (rt_uint8_t)(512/2)))
			count = 0;
		else
			count = 1;
	}
	else
	{            /* Multiple block read */
		if (send_cmd(CMD18, pos) == 0)
		{
			rt_uint8_t* ptr;
			
			ptr = buffer;
			do
			{
				if (!rcvr_datablock(ptr, (rt_uint8_t)(512/2))) break;
				ptr += 512;
			} while (--count);

			send_cmd(CMD12, 0);            /* STOP_TRANSMISSION */
		}
	}

	DESELECT();         /* CS = H */
	rcvr_spi();         /* Idle (Release DO) */

	if (count)
	{
		// rt_set_errno(-RT_ERROR);
		return 0;
	}
	
	return size / 512;
}

static rt_size_t rt_sdcard_write (rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
{
	rt_uint8_t count;

	count = size / 512;

	/* CS = L */
	SELECT();

	/* append partition offset */
	pos += part.offset * 512;

	if (count == 1)
	{
	    /* Single block write */
		if ((send_cmd(CMD24, pos) == 0)   /* WRITE_BLOCK */
				&& xmit_datablock(buffer, 0xFE))
			count = 0;
		else
			count = 1;
	}
	else
	{
	    /* Multiple block write */
		if (send_cmd(CMD25, pos) == 0)
		{
			rt_uint8_t *ptr;
			
			ptr = (rt_uint8_t *)buffer;
			do
			{
				if (!xmit_datablock(ptr, 0xFC)) break;
				ptr += 512;
			} while (--count);

			if (!xmit_datablock(0, 0xFD))   /* STOP_TRAN token */
				count = 1;
		}
	}

	DESELECT();         /* CS = H */
	rcvr_spi();         /* Idle (Release DO) */

	if (count)
	{
		rt_set_errno(-RT_ERROR);
		return 0;
	}

	return size;
}

static rt_err_t rt_sdcard_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
	return RT_EOK;
}

void rt_hw_sdcard_init()
{
	rt_uint32_t n;
	rt_uint8_t* sector;
	
	sd.type     = RT_Device_Class_Block;
	sd.init 	= rt_sdcard_init;
	sd.open 	= rt_sdcard_open;
	sd.close    = rt_sdcard_close;
	sd.read 	= rt_sdcard_read;
	sd.write    = rt_sdcard_write;
	sd.control  = rt_sdcard_control;
	sd.user_data = RT_NULL;

	AT91C_PIOA_PER  = CARD_PWR_PIN; // enable GPIO of CS-pin
	AT91C_PIOA_CODR = CARD_PWR_PIN; // set high
	AT91C_PIOA_OER  = CARD_PWR_PIN; // output enable

	for (n = 0; n < 3000; n ++) ;

	// disable PIO from controlling MOSI, MISO, SCK (=hand over to SPI)
	// keep CS untouched - used as GPIO pin during init
	AT91C_PIOA_PDR = AT91C_PA16_SPI0_MISO | AT91C_PA17_SPI0_MOSI | AT91C_PA18_SPI0_SPCK; //  | NCPS_PDR_BIT;
	// set pin-functions in PIO Controller
	AT91C_PIOA_ASR = AT91C_PA16_SPI0_MISO | AT91C_PA17_SPI0_MOSI | AT91C_PA18_SPI0_SPCK; /// not here: | NCPS_ASR_BIT;

	// set chip-select as output high (unselect card)
	AT91C_PIOA_PER  = CARD_SELECT_PIN; // enable GPIO of CS-pin
	AT91C_PIOA_SODR = CARD_SELECT_PIN; // set high
	AT91C_PIOA_OER  = CARD_SELECT_PIN; // output enable

	// enable peripheral clock for SPI ( PID Bit 5 )
	AT91C_PMC_PCER = ( (rt_uint32_t) 1 << AT91C_ID_SPI0 ); // n.b. IDs are just bit-numbers

	// SPI enable and reset
	pSPI->SPI_CR = AT91C_SPI_SPIEN | AT91C_SPI_SWRST;

	// SPI mode: master, FDIV=0, fault detection disabled
	pSPI->SPI_MR  = AT91C_SPI_MSTR | AT91C_SPI_MODFDIS;

	// set chip-select-register
	// 8 bits per transfer, CPOL=1, ClockPhase=0, DLYBCT = 0
	pSPI->SPI_CSR[SPI_CSR_NUM] = AT91C_SPI_CPOL | AT91C_SPI_BITS_8;

	// slow during init
	AT91_spiSetSpeed(0xFE);

	// enable
	pSPI->SPI_CR = AT91C_SPI_SPIEN;

	n = 10;                  /* Dummy clock */
	do
	{
		rcvr_spi();
	} while (--n);

	SELECT();         /* CS = L */
	if (send_cmd(CMD0, 0) == 1)
	{
		/* Enter Idle state */
		while (send_cmd(CMD1, 0));
	}

	DESELECT();         /* CS = H */
	rcvr_spi();         /* Idle (Release DO) */

	AT91_spiSetSpeed(SPI_SCBR_MIN);

	/* get the first sector to read partition table */
	sector = (rt_uint8_t*) rt_malloc (512);
	if (sector == RT_NULL)
	{
		rt_kprintf("allocate partition sector buffer failed\n");
		return;
	}

	n = rt_sdcard_read((rt_device_t)&sd, 0, sector, 512);
	if (n == 512)
	{
		rt_err_t status;
		
		/* get the first partition */
		status = dfs_filesystem_get_partition(&part, sector, 0);
		if (status != RT_EOK)
		{
			/* there is no partition table */
			part.offset = 0;
			part.size   = 0;
		}
	}
	else
	{
		/* there is no partition table */
		part.offset = 0;
		part.size   = 0;
	}

	/* release sector buffer */
	rt_free(sector);

	/* register sd device */
	rt_device_register(&sd, "sd", RT_DEVICE_FLAG_RDWR);
}
