Multi-sector writes, increased SPI clock to 24MHz, Added support for SDHC/SDXC.
authorMichael McMaster <michael@codesrc.com>
Fri, 11 Oct 2013 14:37:27 +0000 (00:37 +1000)
committerMichael McMaster <michael@codesrc.com>
Fri, 11 Oct 2013 14:37:27 +0000 (00:37 +1000)
15 files changed:
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/config.hex
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter.h
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitter_cfg.c
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfittergnu.inc
software/SCSI2SD/SCSI2SD.cydsn/Generated_Source/PSoC5/cyfitterrv.inc
software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cycdx
software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cydwr
software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cyfit
software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cyprj
software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.svd
software/SCSI2SD/SCSI2SD.cydsn/TopDesign/TopDesign.cysch
software/SCSI2SD/SCSI2SD.cydsn/disk.c
software/SCSI2SD/SCSI2SD.cydsn/mode.c
software/SCSI2SD/SCSI2SD.cydsn/sd.c [new file with mode: 0755]
software/SCSI2SD/SCSI2SD.cydsn/sd.h [new file with mode: 0755]

index c281d8fb95b741e3a6c77667e5b1c09c8f1c8499..c6c8b6450641ad8b72d4347c93d330dac0857572 100644 (file)
@@ -1,30 +1,30 @@
-:20000000065200400165004034060140220701404314014043150140031601403F1701409B\r
-:2000200003400140024101400242014002430140064801400D49014004500140015101405F\r
-:2000400014FF18081CE12CFF34F06430870F81A1830E844785618698878288818A408BCF3F\r
-:200060008C048D4C9001914C924094889661974C98E299449A089B089C419D10A041A11029\r
-:20008000A441A508A720A840A944AC10AD4CB110B361B4C0B50FB63FB780B880B902BA2077\r
-:2000A000BB0CBE40BF40D409D604D80BD90BDB0BDC99DD90DF01008401200A6A102A1302EE\r
-:2000C00019201B80209421042244281029602A042B40302832013380381439425810590AE3\r
-:2000E0005A80628063407801C007C20FC40FCA0FCC0FCE0FD60FD809DE0102010404050176\r
-:20010000060807060A040E30120314101504160C1703182019031A0C1B041C0320032403E8\r
-:20012000280329052B022E483002324033073401363C3B083E1154405604580B590B5B0B91\r
-:200140005C995D905F0180E084208501860387028A088EE0900892109486950197049A01A1\r
-:200160009D06A210A645A902AB01B018B107B2E0B407B902BE05D808D908DB04DC99DF01A8\r
-:2001800000040180024003080404058007840A6A0C060D040E081028120113021501170833\r
-:2001A000184019821B181D041E882108278028042C0431083210378838043C0460806250DE\r
-:2001C00063206C0278017F01848089018B408D048E0490049108926A9302944097409801B7\r
-:2001E0009A519B0E9D02A028A508A640B704C0FFC27FC43FCA24CC56CE42D80FDE11E020BD\r
-:20020000E250E480EC1056085B045D90008401210A68102A13021B402018210122902308A9\r
-:20022000280229202A043028314032013814394240444104480449084B40500252555E8092\r
-:20024000610864016702682869416A427140730278019004910892089542966298029920F9\r
-:200260009C019D4A9E049F02A040A42AA680A740A812AF40C00FC20EC40FCA0ECC0FCE0F51\r
-:20028000D007D20CD610D812DE0130103640CC309C10A6409C10A6409C10A6402320270820\r
-:2002A0009C10AE40C860EE400B205004578084108B188C048F809B089C10B720C210D460F6\r
-:2002C000E64001010B0111011B01000FC02902461F172028802000D000D6600090D64000B2\r
-:2002E00000D0FF067FD2800400D60000C0000100C0040400C002080000219F8E000F00F0DE\r
-:20030000000FFF01002200080000404063024000050EFDBC3DFFFFFF2200F008040000005B\r
-:2003200000000228040B0B0B909900010000C00040011011C00100114001400100000000CE\r
-:2003400000000000000000000000000000FFFF00000000000800300008000000000000005F\r
-:200360000000000010000000FF000000000000010200F10E0E000C000000000000FCFC005A\r
-:2003800000000000F0000FF00000000000010000F00F0F000000000100000000000000005E\r
+:2000000006520040016500403706014023070140431401403F15014003160140401701409A\r
+:2000200003400140024101400242014002430140064801401049014004500140015101405C\r
+:2000400014FF18081CE12CFF34F06430870F5B045F018010818684418582870488818901B7\r
+:200060008A408BAE8C888D698E618F0690019186924094479698978698E299E79A089B0810\r
+:200080009C419D86A110A404A504A740A840A982AC41AD10B10FB3E0B4C0B510B63FB7087A\r
+:2000A000B880B922BA20BB0CBE40BF40D409D604D80BD90BDB0BDC99DD90DF010040012602\r
+:2000C0000A6910081220138019A02054226C2310281029A12A04300831403210330138500B\r
+:2000E0003905581059085A82628063406D407801C00FC20FC407CA0FCC0FCE0FD60FD809B0\r
+:20010000DE01023006040820095C0A0C0B200C100D380E0C0F421203140415401608173043\r
+:2001200019191A481B601C031D0722012307240328032C03303C3240337034013507360275\r
+:2001400037083B083E503F5054405604580B590B5B0B5C995D905F01820885018610870274\r
+:2001600089028B018D018E058F0494069A019D06AA03AC08AE10B018B107B407B902BE0108\r
+:20018000D808D908DC99DF010040010A02080448068008200A610E080F101028124013803D\r
+:2001A0001560190A1A021B901E88210822A027402902310832103340374038403B103C4019\r
+:2001C0003F1460806250632078017F018004848086808A028E2490409160926193169602FD\r
+:2001E00098219A509B80A028A208A508A6C2A780A821C0BFC26FC4CFCA01CC1ECE7CD80FA1\r
+:20020000DE11E250E42056085B045D90004401210A69102A190120102110221023042840C0\r
+:2002200029602A0430083210334138503904404041104380490A4A0A500352545E806108D9\r
+:2002400064016702682869056A406BC1714072017801904491409208931095059663984012\r
+:2002600099209C019D4B9E049F81A208A408A680AC40AE04AF40C00FC20FC407CA0FCC0F56\r
+:20028000CE0ED00DD20CD610D812DE0130103640CC309C10A6409C10A6409C10A640210887\r
+:2002A00025809C10AE40C860EE4009025004578081808410850889028C048F809C10A18852\r
+:2002C000C210D460E040E480E64001010B0111011B01000FC000020000D46008802000D0B5\r
+:2002E0000021FF4E90DC40001FD0200C7F118022C0DC01000020008FC0080400C0040800B3\r
+:2003000000DC9F00FF0000F0000F000000000008000001004602100005BEFDBC3FFFFFFF4B\r
+:200320002200F0080400000000000228040B0B0B909900010000C00040011011C001001132\r
+:20034000400140010000000000000000000000000000000000FFFF000000000008003000E5\r
+:2003600008000000000000000000000010000000FF000000000000010200F10E0E000C004A\r
+:200380000000000000FCFC0000000000F0000FF00000000000010000F00F0F000000000166\r
 :00000001FF\r
index 2dec2e010c79340722924e140b90d44a5c3d2f2f..610d0fc3182dbd2947dadb810d039cc5806085e6 100644 (file)
 /* SD_Clk_Ctl */\r
 #define SD_Clk_Ctl_Sync_ctrl_reg__0__MASK 0x01u\r
 #define SD_Clk_Ctl_Sync_ctrl_reg__0__POS 0\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_AUX_CTL_REG CYREG_B1_UDB05_06_ACTL\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_CONTROL_REG CYREG_B1_UDB05_06_CTL\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_COUNT_REG CYREG_B1_UDB05_06_CTL\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_CONTROL_REG CYREG_B1_UDB05_06_CTL\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_COUNT_REG CYREG_B1_UDB05_06_CTL\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_MASK_REG CYREG_B1_UDB05_06_MSK\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_PERIOD_REG CYREG_B1_UDB05_06_MSK\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_MASK_REG CYREG_B1_UDB05_06_MSK\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_PERIOD_REG CYREG_B1_UDB05_06_MSK\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_AUX_CTL_REG CYREG_B1_UDB05_ACTL\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_REG CYREG_B1_UDB05_CTL\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_ST_REG CYREG_B1_UDB05_ST_CTL\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__COUNT_REG CYREG_B1_UDB05_CTL\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__COUNT_ST_REG CYREG_B1_UDB05_ST_CTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_AUX_CTL_REG CYREG_B0_UDB06_07_ACTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_CONTROL_REG CYREG_B0_UDB06_07_CTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_COUNT_REG CYREG_B0_UDB06_07_CTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_CONTROL_REG CYREG_B0_UDB06_07_CTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_COUNT_REG CYREG_B0_UDB06_07_CTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_MASK_REG CYREG_B0_UDB06_07_MSK\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_PERIOD_REG CYREG_B0_UDB06_07_MSK\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_MASK_REG CYREG_B0_UDB06_07_MSK\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_PERIOD_REG CYREG_B0_UDB06_07_MSK\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_AUX_CTL_REG CYREG_B0_UDB06_ACTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_REG CYREG_B0_UDB06_CTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_ST_REG CYREG_B0_UDB06_ST_CTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__COUNT_REG CYREG_B0_UDB06_CTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__COUNT_ST_REG CYREG_B0_UDB06_ST_CTL\r
 #define SD_Clk_Ctl_Sync_ctrl_reg__MASK 0x01u\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__MASK_CTL_AUX_CTL_REG CYREG_B1_UDB05_MSK_ACTL\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__PERIOD_REG CYREG_B1_UDB05_MSK\r
-#define SD_Clk_Ctl_Sync_ctrl_reg__PER_CTL_AUX_CTL_REG CYREG_B1_UDB05_MSK_ACTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__MASK_CTL_AUX_CTL_REG CYREG_B0_UDB06_MSK_ACTL\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__PERIOD_REG CYREG_B0_UDB06_MSK\r
+#define SD_Clk_Ctl_Sync_ctrl_reg__PER_CTL_AUX_CTL_REG CYREG_B0_UDB06_MSK_ACTL\r
 \r
 /* PARITY_EN */\r
 #define PARITY_EN__0__MASK 0x10u\r
 #define CYDEV_CHIP_FAMILY_PSOC5 3u\r
 #define CYDEV_CHIP_DIE_PSOC5LP 4u\r
 #define CYDEV_CHIP_DIE_EXPECT CYDEV_CHIP_DIE_PSOC5LP\r
-#define BCLK__BUS_CLK__HZ 64000000U\r
-#define BCLK__BUS_CLK__KHZ 64000U\r
-#define BCLK__BUS_CLK__MHZ 64U\r
+#define BCLK__BUS_CLK__HZ 63000000U\r
+#define BCLK__BUS_CLK__KHZ 63000U\r
+#define BCLK__BUS_CLK__MHZ 63U\r
 #define CYDEV_CHIP_DIE_ACTUAL CYDEV_CHIP_DIE_EXPECT\r
 #define CYDEV_CHIP_DIE_LEOPARD 1u\r
 #define CYDEV_CHIP_DIE_PANTHER 3u\r
index 200ebad35e40554643983bd3654a5b21393491d1..d674761fb5f5ae410b0b0f3eda884653c543174e 100644 (file)
@@ -117,31 +117,31 @@ typedef struct
 #define cy_cfg_data_table ((const cy_cfg_addrvalue_t CYFAR *)0x48000040u)\r
 \r
 /* UDB_1_1_0_CONFIG Address: CYDEV_UCFG_B1_P3_U1_BASE Size (bytes): 128 */\r
-#define BS_UDB_1_1_0_CONFIG_VAL ((const uint8 CYFAR *)0x480002CCu)\r
+#define BS_UDB_1_1_0_CONFIG_VAL ((const uint8 CYFAR *)0x480002D4u)\r
 \r
 /* IOPINS0_0 Address: CYREG_PRT0_DM0 Size (bytes): 8 */\r
-#define BS_IOPINS0_0_VAL ((const uint8 CYFAR *)0x4800034Cu)\r
+#define BS_IOPINS0_0_VAL ((const uint8 CYFAR *)0x48000354u)\r
 \r
 /* IOPINS0_7 Address: CYREG_PRT12_DR Size (bytes): 10 */\r
-#define BS_IOPINS0_7_VAL ((const uint8 CYFAR *)0x48000354u)\r
+#define BS_IOPINS0_7_VAL ((const uint8 CYFAR *)0x4800035Cu)\r
 \r
 /* IOPINS1_7 Address: CYREG_PRT12_DR + 0x0000000Bu Size (bytes): 5 */\r
-#define BS_IOPINS1_7_VAL ((const uint8 CYFAR *)0x48000360u)\r
+#define BS_IOPINS1_7_VAL ((const uint8 CYFAR *)0x48000368u)\r
 \r
 /* IOPINS0_2 Address: CYREG_PRT2_DM0 Size (bytes): 8 */\r
-#define BS_IOPINS0_2_VAL ((const uint8 CYFAR *)0x48000368u)\r
+#define BS_IOPINS0_2_VAL ((const uint8 CYFAR *)0x48000370u)\r
 \r
 /* IOPINS0_3 Address: CYREG_PRT3_DR Size (bytes): 10 */\r
-#define BS_IOPINS0_3_VAL ((const uint8 CYFAR *)0x48000370u)\r
+#define BS_IOPINS0_3_VAL ((const uint8 CYFAR *)0x48000378u)\r
 \r
 /* IOPINS0_4 Address: CYREG_PRT4_DM0 Size (bytes): 8 */\r
-#define BS_IOPINS0_4_VAL ((const uint8 CYFAR *)0x4800037Cu)\r
+#define BS_IOPINS0_4_VAL ((const uint8 CYFAR *)0x48000384u)\r
 \r
 /* IOPINS0_5 Address: CYREG_PRT5_DR Size (bytes): 10 */\r
-#define BS_IOPINS0_5_VAL ((const uint8 CYFAR *)0x48000384u)\r
+#define BS_IOPINS0_5_VAL ((const uint8 CYFAR *)0x4800038Cu)\r
 \r
 /* IOPINS0_6 Address: CYREG_PRT6_DM0 Size (bytes): 8 */\r
-#define BS_IOPINS0_6_VAL ((const uint8 CYFAR *)0x48000390u)\r
+#define BS_IOPINS0_6_VAL ((const uint8 CYFAR *)0x48000398u)\r
 \r
 \r
 /*******************************************************************************\r
@@ -201,9 +201,9 @@ static void ClockSetup(void)
 \r
 \r
        /* Configure Digital Clocks based on settings from Clock DWR */\r
-       CY_SET_XTND_REG16((void CYFAR *)(CYREG_CLKDIST_DCFG0_CFG0), 0x0001u);\r
-       CY_SET_XTND_REG8((void CYFAR *)(CYREG_CLKDIST_DCFG0_CFG0 + 0x2u), 0x18u);\r
-       CY_SET_XTND_REG16((void CYFAR *)(CYREG_CLKDIST_DCFG1_CFG0), 0x001Du);\r
+       CY_SET_XTND_REG16((void CYFAR *)(CYREG_CLKDIST_DCFG0_CFG0), 0x0000u);\r
+       CY_SET_XTND_REG8((void CYFAR *)(CYREG_CLKDIST_DCFG0_CFG0 + 0x2u), 0x11u);\r
+       CY_SET_XTND_REG16((void CYFAR *)(CYREG_CLKDIST_DCFG1_CFG0), 0x003Bu);\r
        CY_SET_XTND_REG8((void CYFAR *)(CYREG_CLKDIST_DCFG1_CFG0 + 0x2u), 0x19u);\r
 \r
        /* Configure ILO based on settings from Clock DWR */\r
@@ -211,11 +211,11 @@ static void ClockSetup(void)
        CY_SET_XTND_REG8((void CYFAR *)(CYREG_CLKDIST_CR), 0x08u);\r
 \r
        /* Configure IMO based on settings from Clock DWR */\r
-       CY_SET_XTND_REG8((void CYFAR *)(CYREG_FASTCLK_IMO_CR), 0x02u);\r
-       CY_SET_XTND_REG8((void CYFAR *)(CYREG_IMO_TR1), (CY_GET_XTND_REG8((void CYFAR *)CYREG_FLSHID_CUST_TABLES_IMO_24MHZ)));\r
+       CY_SET_XTND_REG8((void CYFAR *)(CYREG_FASTCLK_IMO_CR), 0x04u);\r
+       CY_SET_XTND_REG8((void CYFAR *)(CYREG_IMO_TR1), (CY_GET_XTND_REG8((void CYFAR *)(CYREG_FLSHID_MFG_CFG_IMO_TR1 + 1u))));\r
 \r
        /* Configure PLL based on settings from Clock DWR */\r
-       CY_SET_XTND_REG16((void CYFAR *)(CYREG_FASTCLK_PLL_P), 0x0818u);\r
+       CY_SET_XTND_REG16((void CYFAR *)(CYREG_FASTCLK_PLL_P), 0x0F15u);\r
        CY_SET_XTND_REG16((void CYFAR *)(CYREG_FASTCLK_PLL_CFG0), 0x1051u);\r
        /* Wait up to 250us for the PLL to lock */\r
        pllLock = 0u;\r
index 629bee43d27d6f6d0b4a1a3b89fa2966b1235f43..88b1b13fc59395c69b5c08ea7ca7c4e29cb8e670 100644 (file)
 /* SD_Clk_Ctl */\r
 .set SD_Clk_Ctl_Sync_ctrl_reg__0__MASK, 0x01\r
 .set SD_Clk_Ctl_Sync_ctrl_reg__0__POS, 0\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_AUX_CTL_REG, CYREG_B1_UDB05_06_ACTL\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_CONTROL_REG, CYREG_B1_UDB05_06_CTL\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_COUNT_REG, CYREG_B1_UDB05_06_CTL\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_CONTROL_REG, CYREG_B1_UDB05_06_CTL\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_COUNT_REG, CYREG_B1_UDB05_06_CTL\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_MASK_REG, CYREG_B1_UDB05_06_MSK\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_PERIOD_REG, CYREG_B1_UDB05_06_MSK\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_MASK_REG, CYREG_B1_UDB05_06_MSK\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_PERIOD_REG, CYREG_B1_UDB05_06_MSK\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_AUX_CTL_REG, CYREG_B1_UDB05_ACTL\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_REG, CYREG_B1_UDB05_CTL\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_ST_REG, CYREG_B1_UDB05_ST_CTL\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__COUNT_REG, CYREG_B1_UDB05_CTL\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__COUNT_ST_REG, CYREG_B1_UDB05_ST_CTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_AUX_CTL_REG, CYREG_B0_UDB06_07_ACTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_CONTROL_REG, CYREG_B0_UDB06_07_CTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_COUNT_REG, CYREG_B0_UDB06_07_CTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_CONTROL_REG, CYREG_B0_UDB06_07_CTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_COUNT_REG, CYREG_B0_UDB06_07_CTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_MASK_REG, CYREG_B0_UDB06_07_MSK\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_PERIOD_REG, CYREG_B0_UDB06_07_MSK\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_MASK_REG, CYREG_B0_UDB06_07_MSK\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_PERIOD_REG, CYREG_B0_UDB06_07_MSK\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_AUX_CTL_REG, CYREG_B0_UDB06_ACTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_REG, CYREG_B0_UDB06_CTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_ST_REG, CYREG_B0_UDB06_ST_CTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__COUNT_REG, CYREG_B0_UDB06_CTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__COUNT_ST_REG, CYREG_B0_UDB06_ST_CTL\r
 .set SD_Clk_Ctl_Sync_ctrl_reg__MASK, 0x01\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__MASK_CTL_AUX_CTL_REG, CYREG_B1_UDB05_MSK_ACTL\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__PERIOD_REG, CYREG_B1_UDB05_MSK\r
-.set SD_Clk_Ctl_Sync_ctrl_reg__PER_CTL_AUX_CTL_REG, CYREG_B1_UDB05_MSK_ACTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__MASK_CTL_AUX_CTL_REG, CYREG_B0_UDB06_MSK_ACTL\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__PERIOD_REG, CYREG_B0_UDB06_MSK\r
+.set SD_Clk_Ctl_Sync_ctrl_reg__PER_CTL_AUX_CTL_REG, CYREG_B0_UDB06_MSK_ACTL\r
 \r
 /* PARITY_EN */\r
 .set PARITY_EN__0__MASK, 0x10\r
 .set CYDEV_CHIP_FAMILY_PSOC5, 3\r
 .set CYDEV_CHIP_DIE_PSOC5LP, 4\r
 .set CYDEV_CHIP_DIE_EXPECT, CYDEV_CHIP_DIE_PSOC5LP\r
-.set BCLK__BUS_CLK__HZ, 64000000\r
-.set BCLK__BUS_CLK__KHZ, 64000\r
-.set BCLK__BUS_CLK__MHZ, 64\r
+.set BCLK__BUS_CLK__HZ, 63000000\r
+.set BCLK__BUS_CLK__KHZ, 63000\r
+.set BCLK__BUS_CLK__MHZ, 63\r
 .set CYDEV_CHIP_DIE_ACTUAL, CYDEV_CHIP_DIE_EXPECT\r
 .set CYDEV_CHIP_DIE_LEOPARD, 1\r
 .set CYDEV_CHIP_DIE_PANTHER, 3\r
index 3699982ad63ea6096aa86e54d7de15907baa9961..49eb0dd0969ecc050237a026be71fead995d8913 100644 (file)
@@ -307,24 +307,24 @@ SD_Init_Clk__PM_STBY_MSK EQU 0x02
 ; SD_Clk_Ctl\r
 SD_Clk_Ctl_Sync_ctrl_reg__0__MASK EQU 0x01\r
 SD_Clk_Ctl_Sync_ctrl_reg__0__POS EQU 0\r
-SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_AUX_CTL_REG EQU CYREG_B1_UDB05_06_ACTL\r
-SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_CONTROL_REG EQU CYREG_B1_UDB05_06_CTL\r
-SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_COUNT_REG EQU CYREG_B1_UDB05_06_CTL\r
-SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_CONTROL_REG EQU CYREG_B1_UDB05_06_CTL\r
-SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_COUNT_REG EQU CYREG_B1_UDB05_06_CTL\r
-SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_MASK_REG EQU CYREG_B1_UDB05_06_MSK\r
-SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_PERIOD_REG EQU CYREG_B1_UDB05_06_MSK\r
-SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_MASK_REG EQU CYREG_B1_UDB05_06_MSK\r
-SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_PERIOD_REG EQU CYREG_B1_UDB05_06_MSK\r
-SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_AUX_CTL_REG EQU CYREG_B1_UDB05_ACTL\r
-SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_REG EQU CYREG_B1_UDB05_CTL\r
-SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_ST_REG EQU CYREG_B1_UDB05_ST_CTL\r
-SD_Clk_Ctl_Sync_ctrl_reg__COUNT_REG EQU CYREG_B1_UDB05_CTL\r
-SD_Clk_Ctl_Sync_ctrl_reg__COUNT_ST_REG EQU CYREG_B1_UDB05_ST_CTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_AUX_CTL_REG EQU CYREG_B0_UDB06_07_ACTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_CONTROL_REG EQU CYREG_B0_UDB06_07_CTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__16BIT_CONTROL_COUNT_REG EQU CYREG_B0_UDB06_07_CTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_CONTROL_REG EQU CYREG_B0_UDB06_07_CTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__16BIT_COUNT_COUNT_REG EQU CYREG_B0_UDB06_07_CTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_MASK_REG EQU CYREG_B0_UDB06_07_MSK\r
+SD_Clk_Ctl_Sync_ctrl_reg__16BIT_MASK_PERIOD_REG EQU CYREG_B0_UDB06_07_MSK\r
+SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_MASK_REG EQU CYREG_B0_UDB06_07_MSK\r
+SD_Clk_Ctl_Sync_ctrl_reg__16BIT_PERIOD_PERIOD_REG EQU CYREG_B0_UDB06_07_MSK\r
+SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_AUX_CTL_REG EQU CYREG_B0_UDB06_ACTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_REG EQU CYREG_B0_UDB06_CTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__CONTROL_ST_REG EQU CYREG_B0_UDB06_ST_CTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__COUNT_REG EQU CYREG_B0_UDB06_CTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__COUNT_ST_REG EQU CYREG_B0_UDB06_ST_CTL\r
 SD_Clk_Ctl_Sync_ctrl_reg__MASK EQU 0x01\r
-SD_Clk_Ctl_Sync_ctrl_reg__MASK_CTL_AUX_CTL_REG EQU CYREG_B1_UDB05_MSK_ACTL\r
-SD_Clk_Ctl_Sync_ctrl_reg__PERIOD_REG EQU CYREG_B1_UDB05_MSK\r
-SD_Clk_Ctl_Sync_ctrl_reg__PER_CTL_AUX_CTL_REG EQU CYREG_B1_UDB05_MSK_ACTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__MASK_CTL_AUX_CTL_REG EQU CYREG_B0_UDB06_MSK_ACTL\r
+SD_Clk_Ctl_Sync_ctrl_reg__PERIOD_REG EQU CYREG_B0_UDB06_MSK\r
+SD_Clk_Ctl_Sync_ctrl_reg__PER_CTL_AUX_CTL_REG EQU CYREG_B0_UDB06_MSK_ACTL\r
 \r
 ; PARITY_EN\r
 PARITY_EN__0__MASK EQU 0x10\r
@@ -1775,9 +1775,9 @@ CYDEV_CHIP_MEMBER_5B EQU 4
 CYDEV_CHIP_FAMILY_PSOC5 EQU 3\r
 CYDEV_CHIP_DIE_PSOC5LP EQU 4\r
 CYDEV_CHIP_DIE_EXPECT EQU CYDEV_CHIP_DIE_PSOC5LP\r
-BCLK__BUS_CLK__HZ EQU 64000000\r
-BCLK__BUS_CLK__KHZ EQU 64000\r
-BCLK__BUS_CLK__MHZ EQU 64\r
+BCLK__BUS_CLK__HZ EQU 63000000\r
+BCLK__BUS_CLK__KHZ EQU 63000\r
+BCLK__BUS_CLK__MHZ EQU 63\r
 CYDEV_CHIP_DIE_ACTUAL EQU CYDEV_CHIP_DIE_EXPECT\r
 CYDEV_CHIP_DIE_LEOPARD EQU 1\r
 CYDEV_CHIP_DIE_PANTHER EQU 3\r
index 880f831c0e755d79ea98d76b8febda754aeb2054..17485033b20a890f73e04734605e74b6f1e9f7ec 100644 (file)
@@ -7,7 +7,7 @@
   <block name="SCSI_ID" BASE="0x0" SIZE="0x0" desc="" visible="true" />\r
   <block name="SD_Clk_mux" BASE="0x0" SIZE="0x0" desc="" visible="true" />\r
   <block name="SD_Clk_Ctl" BASE="0x0" SIZE="0x0" desc="" visible="true">\r
-    <register name="SD_Clk_Ctl_CONTROL_REG" address="0x40006575" bitWidth="8" desc="" />\r
+    <register name="SD_Clk_Ctl_CONTROL_REG" address="0x40006476" bitWidth="8" desc="" />\r
   </block>\r
   <block name="SD_Data_Clk" BASE="0x0" SIZE="0x0" desc="" visible="true" />\r
   <block name="LED1" BASE="0x0" SIZE="0x0" desc="" visible="true" />\r
index 357f64c91c530b51384beefc6c569ddb64cb0826..ed4c6c4da4a6a98006dae19fb294bdac2edcdd34 100755 (executable)
Binary files a/software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cydwr and b/software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cydwr differ
index ddfbf10c593ea450634867cd0abd841f34a2fe69..ddd23b7fd0393eaac14434bf064c689f54a0e001 100644 (file)
Binary files a/software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cyfit and b/software/SCSI2SD/SCSI2SD.cydsn/SCSI2SD.cyfit differ
index 6dc1b1c401b5363e998c17d43ff05e843482d884..5fff1930270d90f543ca70918545afa292b07f9f 100755 (executable)
 <build_action v="C_FILE" />\r
 <PropertyDeltas />\r
 </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>\r
+<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFile" version="3" xml_contents_version="1">\r
+<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItem" version="2" name="sd.c" persistent="\\xengarden\michael\projects\SCSI2SD\git\software\SCSI2SD\SCSI2SD.cydsn\sd.c">\r
+<Hidden v="False" />\r
+</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>\r
+<build_action v="C_FILE" />\r
+<PropertyDeltas />\r
+</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>\r
 </dependencies>\r
 </CyGuid_0820c2e7-528d-4137-9a08-97257b946089>\r
 </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>\r
 <build_action v="NONE" />\r
 <PropertyDeltas />\r
 </CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>\r
+<CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtFile" version="3" xml_contents_version="1">\r
+<CyGuid_31768f72-0253-412b-af77-e7dba74d1330 type_name="CyDesigner.Common.ProjMgmt.Model.CyPrjMgmtItem" version="2" name="sd.h" persistent="\\xengarden\michael\projects\SCSI2SD\git\software\SCSI2SD\SCSI2SD.cydsn\sd.h">\r
+<Hidden v="False" />\r
+</CyGuid_31768f72-0253-412b-af77-e7dba74d1330>\r
+<build_action v="NONE" />\r
+<PropertyDeltas />\r
+</CyGuid_8b8ab257-35d3-4473-b57b-36315200b38b>\r
 </dependencies>\r
 </CyGuid_0820c2e7-528d-4137-9a08-97257b946089>\r
 </CyGuid_2f73275c-45bf-46ba-b3b1-00a2fe0c8dd8>\r
index 28ee2d33d000f94843bc85ea1465b2b602aa60cc..7719d7c528bba775f9213e0ba7aa79f8c54e7369 100644 (file)
@@ -9,7 +9,7 @@
     <peripheral>\r
       <name>SD_Clk_Ctl</name>\r
       <description>No description available</description>\r
-      <baseAddress>0x40006575</baseAddress>\r
+      <baseAddress>0x40006476</baseAddress>\r
       <addressBlock>\r
         <offset>0</offset>\r
         <size>0x1</size>\r
index 6eb486930a5e16fd944dfd0d7377d1142defa7a0..8c9586bafe6b1a80193df077bcc95e17c2797424 100755 (executable)
Binary files a/software/SCSI2SD/SCSI2SD.cydsn/TopDesign/TopDesign.cysch and b/software/SCSI2SD/SCSI2SD.cydsn/TopDesign/TopDesign.cysch differ
index ad0fac57b98292f473a9342d913eaefb8b9ad213..61e11010c96bf311921dec49c913bdcfcb301db2 100755 (executable)
@@ -18,6 +18,7 @@
 #include "device.h"\r
 #include "scsi.h"\r
 #include "disk.h"\r
+#include "sd.h"\r
 \r
 #include <string.h>\r
 \r
 BlockDevice blockDev;\r
 Transfer transfer;\r
 \r
-static void startRead(int nextBlock);\r
-static int sdInit();\r
+static int doSdInit()\r
+{\r
+       int result = sdInit();\r
+       if (result)\r
+       {\r
+               blockDev.state = blockDev.state | DISK_INITIALISED;\r
+               \r
+               // TODO artificially limit this value according to EEPROM config.\r
+               blockDev.capacity = sdDev.capacity;\r
+       }\r
+       return result;\r
+}\r
+\r
 \r
 static void doFormatUnit()\r
 {\r
@@ -85,7 +97,7 @@ static void doWrite(uint32 lba, uint32 blocks)
                scsiDev.status = CHECK_CONDITION;\r
                scsiDev.sense.code = ILLEGAL_REQUEST;\r
                scsiDev.sense.asc = WRITE_PROTECTED;\r
-               scsiDev.phase = STATUS; \r
+               scsiDev.phase = STATUS;\r
        }\r
        else if (((uint64) lba) + blocks > blockDev.capacity)\r
        {\r
@@ -102,6 +114,8 @@ static void doWrite(uint32 lba, uint32 blocks)
                transfer.currentBlock = 0;\r
                scsiDev.phase = DATA_OUT;\r
                scsiDev.dataLen = SCSI_BLOCK_SIZE;\r
+\r
+               sdPrepareWrite();\r
        }\r
 }\r
 \r
@@ -123,7 +137,7 @@ static void doRead(uint32 lba, uint32 blocks)
                transfer.currentBlock = 0;\r
                scsiDev.phase = DATA_IN;\r
                scsiDev.dataLen = 0; // No data yet\r
-               startRead(0);\r
+               sdPrepareRead(0);\r
        }\r
 }\r
 \r
@@ -187,15 +201,12 @@ int scsiDiskCommand()
                        blockDev.state = blockDev.state | DISK_STARTED;\r
                        if (!(blockDev.state & DISK_INITIALISED))\r
                        {\r
-                               if (sdInit())\r
-                               {\r
-                                       blockDev.state = blockDev.state | DISK_INITIALISED;\r
-                               }\r
+                               doSdInit();\r
                        }\r
                }\r
                else\r
                {\r
-                       blockDev.state = blockDev.state & (-1 ^ DISK_STARTED);\r
+                       blockDev.state &= ~DISK_STARTED;\r
                }\r
        }\r
        else if (command == 0x00)\r
@@ -331,285 +342,6 @@ int scsiDiskCommand()
        return commandHandled;\r
 }\r
 \r
-\r
-static uint8 sdCrc7(uint8* chr, uint8 cnt, uint8 crc)\r
-{\r
-       uint8 a;\r
-       for(a = 0; a < cnt; a++)\r
-       {\r
-               uint8 Data = chr[a];\r
-               uint8 i;\r
-               for(i = 0; i < 8; i++)\r
-               {\r
-                       crc <<= 1;\r
-                       if( (Data & 0x80) ^ (crc & 0x80) ) {crc ^= 0x09;}\r
-                       Data <<= 1;\r
-               }\r
-       }\r
-       return crc & 0x7F;\r
-}\r
-\r
-// Read and write 1 byte.\r
-static uint8 sdSpiByte(uint8 value)\r
-{\r
-       SDCard_WriteTxData(value);\r
-       while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE))\r
-       {}\r
-       while (!SDCard_GetRxBufferSize()) {}\r
-       return SDCard_ReadRxData();\r
-}\r
-\r
-static void sdSendCommand(uint8 cmd, uint32 param)\r
-{\r
-       uint8 send[6];\r
-\r
-       send[0] = cmd | 0x40;\r
-       send[1] = param >> 24;\r
-       send[2] = param >> 16;\r
-       send[3] = param >> 8;\r
-       send[4] = param;\r
-       send[5] = (sdCrc7(send, 5, 0) << 1) | 1;\r
-\r
-       for(cmd = 0; cmd < sizeof(send); cmd++)\r
-       {\r
-               sdSpiByte(send[cmd]);\r
-       }\r
-}\r
-\r
-static uint8 sdReadResp()\r
-{\r
-       uint8 v;\r
-       uint8 i = 128;\r
-       do\r
-       {\r
-               v = sdSpiByte(0xFF);\r
-       } while(i-- && (v == 0xFF));\r
-       return v;\r
-}\r
-\r
-static uint8 sdWaitResp()\r
-{\r
-       uint8 v;\r
-       uint8 i = 255;\r
-       do\r
-       {\r
-               v = sdSpiByte(0xFF);\r
-       } while(i-- && (v != 0xFE));\r
-       return v;\r
-}\r
-\r
-\r
-static uint8 sdCommandAndResponse(uint8 cmd, uint32 param)\r
-{\r
-       SDCard_ClearRxBuffer();\r
-       sdSpiByte(0xFF);\r
-       sdSendCommand(cmd, param);\r
-       return sdReadResp();\r
-}\r
-\r
-\r
-static int sdInit()\r
-{\r
-       int result = 0;\r
-       SD_CS_Write(1); // Set CS inactive (active low)\r
-       SD_Init_Clk_Start(); // Turn on the slow 400KHz clock\r
-       SD_Clk_Ctl_Write(0); // Select the 400KHz clock source.\r
-       SDCard_Start(); // Enable SPI hardware\r
-       \r
-       // Power on sequence. 74 clock cycles of a "1" while CS unasserted.\r
-       int i;\r
-       for (i = 0; i < 10; ++i)\r
-       {\r
-               sdSpiByte(0xFF);\r
-       }\r
-\r
-       SD_CS_Write(0); // Set CS active (active low)\r
-       CyDelayUs(1);\r
-\r
-       uint8 v = sdCommandAndResponse(0, 0);\r
-       if(v != 1){goto bad;}\r
-\r
-       // TODO CMD8 + valid CC for ver2 + cards. arg 0x00..01AA\r
-\r
-\r
-       // TODO SDv2 support: ACMD41, fallback to CMD1\r
-\r
-       v = sdCommandAndResponse(1, 0);\r
-     for(i=0;v != 0 && i<50;++i){\r
-          CyDelay(50);\r
-          v = sdCommandAndResponse(1, 0);\r
-     }\r
-     if(v){goto bad;}\r
-     \r
-       v = sdCommandAndResponse(16, SCSI_BLOCK_SIZE); //Force sector size\r
-       if(v){goto bad;}\r
-       v = sdCommandAndResponse(59, 0); //crc off\r
-       if(v){goto bad;}\r
-\r
-       // now set the sd card up for full speed\r
-       SD_Data_Clk_Start(); // Turn on the fast clock\r
-       SD_Clk_Ctl_Write(1); // Select the fast clock source.\r
-       SD_Init_Clk_Stop(); // Stop the slow clock.\r
-       \r
-       v = sdCommandAndResponse(0x9, 0);\r
-       if(v){goto bad;}\r
-       v = sdWaitResp();\r
-       if (v != 0xFE) { goto bad; }\r
-       uint8 buf[16];\r
-       for (i = 0; i < 16; ++i)\r
-       {\r
-               buf[i] = sdSpiByte(0xFF);\r
-       }\r
-       sdSpiByte(0xFF); // CRC \r
-       sdSpiByte(0xFF); // CRC\r
-       uint32 c_size = (((((uint32)buf[6]) & 0x3) << 16) | (((uint32)buf[7]) << 8) | buf[8]) >> 6;\r
-       uint32 c_mult = (((((uint32)buf[9]) & 0x3) << 8) | ((uint32)buf[0xa])) >> 7;\r
-       uint32 sectorSize = buf[5] & 0x0F;\r
-       blockDev.capacity = ((c_size+1) * ((uint64)1 << (c_mult+2)) * ((uint64)1 << sectorSize)) / SCSI_BLOCK_SIZE;\r
-       result = 1;\r
-       goto out;\r
-       \r
-bad:\r
-       blockDev.capacity = 0;\r
-       \r
-out:\r
-       return result;\r
-\r
-}\r
-\r
-static void startRead(int nextBlock)\r
-{\r
-// TODO 4Gb limit\r
-// NOTE: CMD17 is NOT in hex. decimal 17.\r
-       uint8 v = sdCommandAndResponse(17, ((uint32)SCSI_BLOCK_SIZE) * (transfer.lba + transfer.currentBlock + nextBlock));\r
-       if (v)\r
-       {\r
-               scsiDiskReset();\r
-\r
-               scsiDev.status = CHECK_CONDITION;\r
-               scsiDev.sense.code = HARDWARE_ERROR;\r
-               scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
-               scsiDev.phase = STATUS;\r
-       }\r
-}\r
-\r
-static int readReady()\r
-{\r
-       uint8 v = sdWaitResp();\r
-       if (v == 0xFF)\r
-       {\r
-               return 0;\r
-       }\r
-       else if (v == 0xFE)\r
-       {\r
-               return 1;\r
-       }\r
-       else\r
-       {\r
-               scsiDiskReset();\r
-               scsiDev.status = CHECK_CONDITION;\r
-               scsiDev.sense.code = HARDWARE_ERROR;\r
-               scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
-               scsiDev.phase = STATUS;\r
-               return 0;\r
-       }\r
-}\r
-static void readSector()\r
-{\r
-// TODO this is slow. Really slow.\r
-// Even if we don't use DMA, we still want to read/write multiple bytes\r
-// at a time.\r
-/*\r
-       int i;\r
-       for (i = 0; i < SCSI_BLOCK_SIZE; ++i)\r
-       {\r
-               scsiDev.data[i] = sdSpiByte(0xFF);\r
-       }\r
-*/\r
-\r
-       // We have a spi FIFO of 4 bytes. use it.\r
-       // This is much better, byut after 4 bytes we're still\r
-       // blocking a bit.\r
-       int i;\r
-       for (i = 0; i < SCSI_BLOCK_SIZE; i+=4)\r
-       {\r
-               SDCard_WriteTxData(0xFF);\r
-               SDCard_WriteTxData(0xFF);\r
-               SDCard_WriteTxData(0xFF);\r
-               SDCard_WriteTxData(0xFF);\r
-\r
-               while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE))\r
-               {}\r
-               scsiDev.data[i] = SDCard_ReadRxData();\r
-               scsiDev.data[i+1] = SDCard_ReadRxData();\r
-               scsiDev.data[i+2] = SDCard_ReadRxData();\r
-               scsiDev.data[i+3] = SDCard_ReadRxData();\r
-\r
-       }\r
-\r
-\r
-       sdSpiByte(0xFF); // CRC\r
-       sdSpiByte(0xFF); // CRC\r
-       scsiDev.dataLen = SCSI_BLOCK_SIZE;\r
-       scsiDev.dataPtr = 0;\r
-}\r
-\r
-static void writeSector()\r
-{\r
-       uint8 v = sdCommandAndResponse(24, ((uint32)SCSI_BLOCK_SIZE) * (transfer.lba + transfer.currentBlock));\r
-       if (v)\r
-       {\r
-               scsiDiskReset();\r
-\r
-               scsiDev.status = CHECK_CONDITION;\r
-               scsiDev.sense.code = HARDWARE_ERROR;\r
-               scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
-               scsiDev.phase = STATUS;\r
-       }\r
-       else\r
-       {\r
-               SDCard_WriteTxData(0xFE);\r
-               int i;\r
-               for (i = 0; i < SCSI_BLOCK_SIZE; ++i)\r
-               {\r
-                       SDCard_WriteTxData(scsiDev.data[i]);\r
-               }\r
-               while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE))\r
-               {}\r
-               sdSpiByte(0x00); // CRC\r
-               sdSpiByte(0x00); // CRC\r
-               SDCard_ClearRxBuffer();         \r
-               v = sdSpiByte(0x00); // Response\r
-               if (((v & 0x1F) >> 1) != 0x2) // Accepted.\r
-               {\r
-                       scsiDiskReset();\r
-\r
-                       scsiDev.status = CHECK_CONDITION;\r
-                       scsiDev.sense.code = HARDWARE_ERROR;\r
-                       scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
-                       scsiDev.phase = STATUS;\r
-               }\r
-               else\r
-               {\r
-                       // Wait for the card to come out of busy.\r
-                       v = sdSpiByte(0xFF);\r
-                       while (v == 0)\r
-                       {\r
-                               v = sdSpiByte(0xFF);\r
-                       }\r
-                       uint8 r1 = sdCommandAndResponse(13, 0); // send status\r
-                       uint8 r2 = sdSpiByte(0xFF);\r
-                       if (r1 || r2)\r
-                       {\r
-                               scsiDev.status = CHECK_CONDITION;\r
-                               scsiDev.sense.code = HARDWARE_ERROR;\r
-                               scsiDev.sense.asc = WRITE_ERROR_AUTO_REALLOCATION_FAILED;\r
-                               scsiDev.phase = STATUS;                 \r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
 void scsiDiskPoll()\r
 {\r
        if (scsiDev.phase == DATA_IN &&\r
@@ -617,12 +349,12 @@ void scsiDiskPoll()
        {\r
                if (scsiDev.dataLen == 0)\r
                {\r
-                       if (readReady())\r
+                       if (sdIsReadReady())\r
                        {\r
-                               readSector();\r
+                               sdReadSector();\r
                                if ((transfer.currentBlock + 1) < transfer.blocks)\r
                                {\r
-                                       startRead(1); // Tell SD card to grab data while we send\r
+                                       sdPrepareRead(1); // Tell SD card to grab data while we send\r
                                                                        // buffer to SCSI.\r
                                }\r
                        }\r
@@ -644,17 +376,23 @@ void scsiDiskPoll()
        {\r
                if (scsiDev.dataPtr == SCSI_BLOCK_SIZE)\r
                {\r
-                       writeSector();\r
+                       int writeOk = sdWriteSector();\r
                        scsiDev.dataPtr = 0;\r
                        transfer.currentBlock++;\r
                        if (transfer.currentBlock >= transfer.blocks)\r
+                               \r
                        {\r
                                scsiDev.dataLen = 0;\r
                                scsiDev.phase = STATUS;\r
                                scsiDiskReset();\r
+                               \r
+                               if (writeOk)\r
+                               {\r
+                                       sdCompleteWrite();\r
+                               }\r
                        }\r
                }\r
-       }       \r
+       }\r
 }\r
 \r
 void scsiDiskReset()\r
@@ -685,12 +423,18 @@ void scsiDiskInit()
        {\r
                blockDev.state = blockDev.state | DISK_PRESENT;\r
 \r
-// todo IF FAILS, TRY AGAIN LATER.\r
-// 5000 works well with the Mac.\r
-               CyDelay(5000); // allow the card to wake up.\r
-               if (sdInit())\r
+               // Wait up to 5 seconds for the SD card to wake up.\r
+               int retry;\r
+               for (retry = 0; retry < 5; ++retry)\r
                {\r
-                       blockDev.state = blockDev.state | DISK_INITIALISED;\r
+                       if (doSdInit())\r
+                       {\r
+                               break;\r
+                       }\r
+                       else\r
+                       {\r
+                               CyDelay(1000);\r
+                       }\r
                }\r
        }\r
 }\r
index 89639cc205251f2019e9f950b4d7ea7e98d741c0..83b00c7daa493b7dcf25c3f59ee642a84b34d773 100755 (executable)
@@ -38,7 +38,7 @@ static const uint8 DisconnectReconnectPage[] =
 \r
 static const uint8 FormatDevicePage[] =\r
 {\r
-x03, // Page code \r
+0x03, // Page code \r
 0x16, // Page length\r
 0x00, 0x00, // Single zone\r
 0x00, 0x00, // No alternate sectors\r
diff --git a/software/SCSI2SD/SCSI2SD.cydsn/sd.c b/software/SCSI2SD/SCSI2SD.cydsn/sd.c
new file mode 100755 (executable)
index 0000000..c76c72d
--- /dev/null
@@ -0,0 +1,451 @@
+//     Copyright (C) 2013 Michael McMaster <michael@codesrc.com>\r
+//\r
+//     This file is part of SCSI2SD.\r
+//\r
+//     SCSI2SD is free software: you can redistribute it and/or modify\r
+//     it under the terms of the GNU General Public License as published by\r
+//     the Free Software Foundation, either version 3 of the License, or\r
+//     (at your option) any later version.\r
+//\r
+//     SCSI2SD is distributed in the hope that it will be useful,\r
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+//     GNU General Public License for more details.\r
+//\r
+//     You should have received a copy of the GNU General Public License\r
+//     along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.\r
+\r
+#include "device.h"\r
+#include "scsi.h"\r
+#include "disk.h"\r
+#include "sd.h"\r
+\r
+#include <string.h>\r
+\r
+// Global\r
+SdDevice sdDev;\r
+\r
+static uint8 sdCrc7(uint8* chr, uint8 cnt, uint8 crc)\r
+{\r
+       uint8 a;\r
+       for(a = 0; a < cnt; a++)\r
+       {\r
+               uint8 Data = chr[a];\r
+               uint8 i;\r
+               for(i = 0; i < 8; i++)\r
+               {\r
+                       crc <<= 1;\r
+                       if( (Data & 0x80) ^ (crc & 0x80) ) {crc ^= 0x09;}\r
+                       Data <<= 1;\r
+               }\r
+       }\r
+       return crc & 0x7F;\r
+}\r
+\r
+// Read and write 1 byte.\r
+static uint8 sdSpiByte(uint8 value)\r
+{\r
+       SDCard_WriteTxData(value);\r
+       while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE))\r
+       {}\r
+       while (!SDCard_GetRxBufferSize()) {}\r
+       return SDCard_ReadRxData();\r
+}\r
+\r
+static void sdSendCommand(uint8 cmd, uint32 param)\r
+{\r
+       uint8 send[6];\r
+\r
+       send[0] = cmd | 0x40;\r
+       send[1] = param >> 24;\r
+       send[2] = param >> 16;\r
+       send[3] = param >> 8;\r
+       send[4] = param;\r
+       send[5] = (sdCrc7(send, 5, 0) << 1) | 1;\r
+\r
+       for(cmd = 0; cmd < sizeof(send); cmd++)\r
+       {\r
+               sdSpiByte(send[cmd]);\r
+       }\r
+}\r
+\r
+static uint8 sdReadResp()\r
+{\r
+       uint8 v;\r
+       uint8 i = 128;\r
+       do\r
+       {\r
+               v = sdSpiByte(0xFF);\r
+       } while(i-- && (v == 0xFF));\r
+       return v;\r
+}\r
+\r
+static uint8 sdWaitResp()\r
+{\r
+       uint8 v;\r
+       uint8 i = 255;\r
+       do\r
+       {\r
+               v = sdSpiByte(0xFF);\r
+       } while(i-- && (v != 0xFE));\r
+       return v;\r
+}\r
+\r
+\r
+static uint8 sdCommandAndResponse(uint8 cmd, uint32 param)\r
+{\r
+       SDCard_ClearRxBuffer();\r
+       sdSpiByte(0xFF);\r
+       sdSendCommand(cmd, param);\r
+       return sdReadResp();\r
+}\r
+\r
+\r
+void sdPrepareRead(int nextBlockOffset)\r
+{\r
+       uint32 len = (transfer.lba + transfer.currentBlock + nextBlockOffset);\r
+       if (!sdDev.ccs)\r
+       {\r
+               len = len * SCSI_BLOCK_SIZE;\r
+       }\r
+       uint8 v = sdCommandAndResponse(17, len);\r
+       if (v)\r
+       {\r
+               scsiDiskReset();\r
+\r
+               scsiDev.status = CHECK_CONDITION;\r
+               scsiDev.sense.code = HARDWARE_ERROR;\r
+               scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
+               scsiDev.phase = STATUS;\r
+       }\r
+}\r
+\r
+int sdIsReadReady()\r
+{\r
+       uint8 v = sdWaitResp();\r
+       if (v == 0xFF)\r
+       {\r
+               return 0;\r
+       }\r
+       else if (v == 0xFE)\r
+       {\r
+               return 1;\r
+       }\r
+       else\r
+       {\r
+               scsiDiskReset();\r
+               scsiDev.status = CHECK_CONDITION;\r
+               scsiDev.sense.code = HARDWARE_ERROR;\r
+               scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
+               scsiDev.phase = STATUS;\r
+               return 0;\r
+       }\r
+}\r
+\r
+void sdReadSector()\r
+{\r
+       // We have a spi FIFO of 4 bytes. use it.\r
+       // This is much better, byut after 4 bytes we're still\r
+       // blocking a bit.\r
+       int i;\r
+       for (i = 0; i < SCSI_BLOCK_SIZE; i+=4)\r
+       {\r
+               SDCard_WriteTxData(0xFF);\r
+               SDCard_WriteTxData(0xFF);\r
+               SDCard_WriteTxData(0xFF);\r
+               SDCard_WriteTxData(0xFF);\r
+\r
+               while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE))\r
+               {}\r
+               scsiDev.data[i] = SDCard_ReadRxData();\r
+               scsiDev.data[i+1] = SDCard_ReadRxData();\r
+               scsiDev.data[i+2] = SDCard_ReadRxData();\r
+               scsiDev.data[i+3] = SDCard_ReadRxData();\r
+\r
+       }\r
+\r
+\r
+       sdSpiByte(0xFF); // CRC\r
+       sdSpiByte(0xFF); // CRC\r
+       scsiDev.dataLen = SCSI_BLOCK_SIZE;\r
+       scsiDev.dataPtr = 0;\r
+}\r
+\r
+static void sdWaitWriteBusy()\r
+{\r
+       uint8 val;\r
+       do\r
+       {\r
+               val = sdSpiByte(0xFF);\r
+       } while (val != 0xFF);\r
+}\r
+\r
+int sdWriteSector()\r
+{\r
+       int result;\r
+       // Wait for a previously-written sector to complete.\r
+       sdWaitWriteBusy();\r
+\r
+               sdSpiByte(0xFC); // MULTIPLE byte start token\r
+               int i;\r
+               for (i = 0; i < SCSI_BLOCK_SIZE; i+=4)\r
+               {\r
+                       SDCard_WriteTxData(scsiDev.data[i]);\r
+                       SDCard_WriteTxData(scsiDev.data[i+1]);\r
+                       SDCard_WriteTxData(scsiDev.data[i+2]);\r
+                       SDCard_WriteTxData(scsiDev.data[i+3]);\r
+\r
+                       while(!(SDCard_ReadTxStatus() & SDCard_STS_SPI_DONE))\r
+                       {}\r
+               \r
+                       SDCard_ReadRxData();\r
+                       SDCard_ReadRxData();\r
+                       SDCard_ReadRxData();\r
+                       SDCard_ReadRxData();\r
+               }\r
+\r
+               sdSpiByte(0x00); // CRC\r
+               sdSpiByte(0x00); // CRC\r
+               uint8 dataToken = sdSpiByte(0xFF); // Response\r
+               if (((dataToken & 0x1F) >> 1) != 0x2) // Accepted.\r
+               {\r
+                       sdWaitWriteBusy();\r
+                       sdSpiByte(0xFD); // STOP TOKEN\r
+                       // Wait for the card to come out of busy.\r
+                       sdWaitWriteBusy();\r
+\r
+                       scsiDiskReset();\r
+\r
+                       scsiDev.status = CHECK_CONDITION;\r
+                       scsiDev.sense.code = HARDWARE_ERROR;\r
+                       scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
+                       scsiDev.phase = STATUS;\r
+                       result = 0;\r
+               }\r
+               else\r
+               {\r
+                       // The card is probably in the busy state.\r
+                       // Don't wait, as we could read the SCSI interface instead.\r
+                       result = 1;\r
+       }\r
+\r
+       return result;\r
+}\r
+\r
+void sdCompleteWrite()\r
+{\r
+       // Wait for a previously-written sector to complete.\r
+       sdWaitWriteBusy();\r
+\r
+       sdSpiByte(0xFD); // STOP TOKEN\r
+       // Wait for the card to come out of busy.\r
+       sdWaitWriteBusy();\r
+       \r
+       uint8 r1 = sdCommandAndResponse(13, 0); // send status\r
+       uint8 r2 = sdSpiByte(0xFF);\r
+       if (r1 || r2)\r
+       {\r
+               scsiDev.status = CHECK_CONDITION;\r
+               scsiDev.sense.code = HARDWARE_ERROR;\r
+               scsiDev.sense.asc = WRITE_ERROR_AUTO_REALLOCATION_FAILED;\r
+               scsiDev.phase = STATUS;\r
+       }\r
+}\r
+\r
+\r
+// SD Version 2 (SDHC) support\r
+static int sendIfCond()\r
+{\r
+       int retries = 50;\r
+\r
+       do\r
+       {\r
+               uint8 status = sdCommandAndResponse(SD_SEND_IF_COND, 0x000001AA);\r
+\r
+               if (status == SD_R1_IDLE)\r
+               {\r
+                       // Version 2 card.\r
+                       sdDev.version = 2;\r
+                       // Read 32bit response. Should contain the same bytes that\r
+                       // we sent in the command parameter.\r
+                       sdSpiByte(0xFF);\r
+                       sdSpiByte(0xFF);\r
+                       sdSpiByte(0xFF);\r
+                       sdSpiByte(0xFF);\r
+                       break;\r
+               }\r
+               else if (status & SD_R1_ILLEGAL)\r
+               {\r
+                       // Version 1 card.\r
+                       sdDev.version = 1;\r
+                       break;\r
+               }\r
+       } while (--retries > 0);\r
+\r
+       return retries > 0;\r
+}\r
+\r
+static int sdOpCond()\r
+{\r
+       int retries = 50;\r
+\r
+       uint8 status;\r
+       do\r
+       {\r
+               CyDelay(33); // Spec says to retry for 1 second.\r
+\r
+               sdCommandAndResponse(SD_APP_CMD, 0);\r
+               // Host Capacity Support = 1 (SDHC/SDXC supported)\r
+               status = sdCommandAndResponse(SD_APP_SEND_OP_COND, 0x40000000);\r
+       } while ((status != 0) && (--retries > 0));\r
+\r
+       return retries > 0;\r
+}\r
+\r
+static int sdReadOCR()\r
+{\r
+       uint8 status = sdCommandAndResponse(SD_READ_OCR, 0);\r
+       if(status){goto bad;}\r
+\r
+       uint8 buf[4];\r
+       int i;\r
+       for (i = 0; i < 4; ++i)\r
+       {\r
+               buf[i] = sdSpiByte(0xFF);\r
+       }\r
+\r
+       sdDev.ccs = (buf[0] & 0x40) ? 1 : 0;\r
+\r
+       return 1;\r
+bad:\r
+       return 0;\r
+}\r
+\r
+static int sdReadCSD()\r
+{\r
+       uint8 status = sdCommandAndResponse(SD_SEND_CSD, 0);\r
+       if(status){goto bad;}\r
+       status = sdWaitResp();\r
+       if (status != 0xFE) { goto bad; }\r
+\r
+       uint8 buf[16];\r
+       int i;\r
+       for (i = 0; i < 16; ++i)\r
+       {\r
+               buf[i] = sdSpiByte(0xFF);\r
+       }\r
+       sdSpiByte(0xFF); // CRC\r
+       sdSpiByte(0xFF); // CRC\r
+\r
+       if ((buf[0] >> 6) == 0x00)\r
+       {\r
+               // CSD version 1\r
+               // C_SIZE in bits [73:62]\r
+               uint32 c_size = (((((uint32)buf[6]) & 0x3) << 16) | (((uint32)buf[7]) << 8) | buf[8]) >> 6;\r
+               uint32 c_mult = (((((uint32)buf[9]) & 0x3) << 8) | ((uint32)buf[0xa])) >> 7;\r
+               uint32 sectorSize = buf[5] & 0x0F;\r
+               sdDev.capacity = ((c_size+1) * ((uint64)1 << (c_mult+2)) * ((uint64)1 << sectorSize)) / SCSI_BLOCK_SIZE;\r
+       }\r
+       else if ((buf[0] >> 6) == 0x01)\r
+       {\r
+               // CSD version 2\r
+               // C_SIZE in bits [69:48]\r
+\r
+               uint32 c_size =\r
+                       ((((uint32)buf[7]) & 0x3F) << 16) |\r
+                       (((uint32)buf[8]) << 8) |\r
+                       ((uint32)buf[7]);\r
+               sdDev.capacity = (c_size + 1) * 1024;\r
+       }\r
+       else\r
+       {\r
+               goto bad;\r
+       }\r
+\r
+       return 1;\r
+bad:\r
+       return 0;\r
+}\r
+\r
+int sdInit()\r
+{      \r
+       sdDev.version = 0;\r
+       sdDev.ccs = 0;\r
+       sdDev.capacity = 0;\r
+\r
+       int result = 0;\r
+       SD_CS_Write(1); // Set CS inactive (active low)\r
+       SD_Init_Clk_Start(); // Turn on the slow 400KHz clock\r
+       SD_Clk_Ctl_Write(0); // Select the 400KHz clock source.\r
+       SDCard_Start(); // Enable SPI hardware\r
+\r
+       // Power on sequence. 74 clock cycles of a "1" while CS unasserted.\r
+       int i;\r
+       for (i = 0; i < 10; ++i)\r
+       {\r
+               sdSpiByte(0xFF);\r
+       }\r
+\r
+       SD_CS_Write(0); // Set CS active (active low)\r
+       CyDelayUs(1);\r
+\r
+       uint8 v = sdCommandAndResponse(SD_GO_IDLE_STATE, 0);\r
+       if(v != 1){goto bad;}\r
+\r
+       if (!sendIfCond()) goto bad; // Sets V1 or V2 flag\r
+       if (!sdOpCond()) goto bad;\r
+       if (!sdReadOCR()) goto bad;\r
+\r
+       // This command will be ignored if sdDev.ccs is set.\r
+       // SDHC and SDXC are always 512bytes.\r
+       v = sdCommandAndResponse(SD_SET_BLOCKLEN, SCSI_BLOCK_SIZE); //Force sector size\r
+       if(v){goto bad;}\r
+       v = sdCommandAndResponse(SD_CRC_ON_OFF, 0); //crc off\r
+       if(v){goto bad;}\r
+\r
+       // now set the sd card up for full speed\r
+       SD_Data_Clk_Start(); // Turn on the fast clock\r
+       SD_Clk_Ctl_Write(1); // Select the fast clock source.\r
+       SD_Init_Clk_Stop(); // Stop the slow clock.\r
+\r
+       if (!sdReadCSD()) goto bad;\r
+\r
+       result = 1;\r
+       goto out;\r
+\r
+bad:\r
+       sdDev.capacity = 0;\r
+\r
+out:\r
+       return result;\r
+\r
+}\r
+\r
+\r
+void sdPrepareWrite()\r
+{\r
+       // Set the number of blocks to pre-erase by the multiple block write command\r
+       // We don't care about the response - if the command is not accepted, writes\r
+       // will just be a bit slower.\r
+       // Max 22bit parameter.\r
+       uint32 blocks = transfer.blocks > 0x7FFFFF ? 0x7FFFFF : transfer.blocks;\r
+       sdCommandAndResponse(SD_APP_CMD, 0);\r
+       sdCommandAndResponse(SD_APP_SET_WR_BLK_ERASE_COUNT, blocks);\r
+\r
+       uint32 len = (transfer.lba + transfer.currentBlock);\r
+       if (!sdDev.ccs)\r
+       {\r
+               len = len * SCSI_BLOCK_SIZE;\r
+       }\r
+       uint8 v = sdCommandAndResponse(25, len);\r
+       if (v)\r
+       {\r
+               scsiDiskReset();\r
+\r
+               scsiDev.status = CHECK_CONDITION;\r
+               scsiDev.sense.code = HARDWARE_ERROR;\r
+               scsiDev.sense.asc = LOGICAL_UNIT_COMMUNICATION_FAILURE;\r
+               scsiDev.phase = STATUS;\r
+       }\r
+}\r
+\r
diff --git a/software/SCSI2SD/SCSI2SD.cydsn/sd.h b/software/SCSI2SD/SCSI2SD.cydsn/sd.h
new file mode 100755 (executable)
index 0000000..3473a7d
--- /dev/null
@@ -0,0 +1,63 @@
+//     Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
+//
+//     This file is part of SCSI2SD.
+//
+//     SCSI2SD is free software: you can redistribute it and/or modify
+//     it under the terms of the GNU General Public License as published by
+//     the Free Software Foundation, either version 3 of the License, or
+//     (at your option) any later version.
+//
+//     SCSI2SD is distributed in the hope that it will be useful,
+//     but WITHOUT ANY WARRANTY; without even the implied warranty of
+//     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+//     GNU General Public License for more details.
+//
+//     You should have received a copy of the GNU General Public License
+//     along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.
+#ifndef SD_H
+#define SD_H
+
+typedef enum
+{
+       SD_GO_IDLE_STATE = 0,
+       SD_SEND_OP_COND = 1,
+       SD_SEND_IF_COND = 8, // SD V2
+       SD_SEND_CSD = 9,
+       SD_SET_BLOCKLEN = 16,
+       SD_APP_SET_WR_BLK_ERASE_COUNT = 23,
+       SD_APP_SEND_OP_COND = 41,
+       SD_APP_CMD = 55,
+       SD_READ_OCR = 58,
+       SD_CRC_ON_OFF = 59
+} SD_CMD;
+
+typedef enum
+{
+       SD_R1_IDLE = 1,
+       SD_R1_ERASE_RESET = 2,
+       SD_R1_ILLEGAL = 4,
+       SD_R1_CRC = 8,
+       SD_R1_ERASE_SEQ = 0x10,
+       SD_R1_ADDRESS = 0x20,
+       SD_R1_PARAMETER = 0x40
+} SD_R1;
+
+typedef struct
+{
+       int version; // SDHC = version 2.
+       int ccs; // Card Capacity Status. 1 = SDHC or SDXC
+       int capacity; // in 512 byte blocks
+} SdDevice;
+
+extern SdDevice sdDev;
+
+int sdInit();
+void sdPrepareWrite();
+int sdWriteSector();
+void sdCompleteWrite();
+
+void sdPrepareRead(int nextBlockOffset);
+int sdIsReadReady();
+void sdReadSector();
+
+#endif