-20160922 6.0.??
+20161006 6.0.12
- Fixed SCSI timing issue
- Added glitch filter on SCSI signals.
+ - Re-implemented SCSI parity checking.
20160912 6.0.10
- Fixed write issue with UHS-I Speed Class 3 SD cards.
\r
#include <string.h>\r
\r
-static const uint16_t FIRMWARE_VERSION = 0x060B;\r
+static const uint16_t FIRMWARE_VERSION = 0x060C;\r
\r
// 1 flash row\r
static const uint8_t DEFAULT_CONFIG[128] =\r
// int scsiActive = 0;\r
// int sdActive = 0;\r
\r
+ int parityError = 0;\r
while ((i < totalSDSectors) &&\r
(likely(scsiDev.phase == DATA_OUT) || // scsiDisconnect keeps our phase.\r
scsiComplete) &&\r
- likely(!scsiDev.resetFlag))\r
+ likely(!scsiDev.resetFlag) &&\r
+ likely(!parityError))\r
{\r
// Well, until we have some proper non-blocking SD code, we must\r
// do this in a half-duplex fashion. We need to write as much as\r
uint32_t rem = totalSDSectors - i;\r
uint32_t sectors =\r
rem < maxSectors ? rem : maxSectors;\r
- scsiRead(&scsiDev.data[0], sectors * SD_SECTOR_SIZE);\r
- sdTmpWrite(&scsiDev.data[0], i + sdLBA, sectors);\r
+ scsiRead(&scsiDev.data[0], sectors * SD_SECTOR_SIZE, &parityError);\r
+ if (!parityError)\r
+ {\r
+ sdTmpWrite(&scsiDev.data[0], i + sdLBA, sectors);\r
+ }\r
i += sectors;\r
#if 0\r
// Wait for the next DMA interrupt. It's beneficial to halt the\r
\r
if (scsiDev.phase == DATA_OUT)\r
{\r
- if (scsiDev.parityError &&\r
- (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) &&\r
- (scsiDev.compatMode >= COMPAT_SCSI2))\r
+ if (parityError &&\r
+ (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))\r
{\r
scsiDev.target->sense.code = ABORTED_COMMAND;\r
scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
{\r
// Go back to the command phase and start again.\r
scsiDev.phase = COMMAND;\r
- scsiDev.parityError = 0;\r
scsiDev.dataPtr = 0;\r
scsiDev.savedDataPtr = 0;\r
scsiDev.dataLen = 0;\r
scsiDev.dataLen = sizeof(scsiDev.data);\r
}\r
\r
- scsiDev.parityError = 0;\r
len = scsiDev.dataLen - scsiDev.dataPtr;\r
if (len > 0)\r
{\r
scsiEnterPhase(DATA_OUT);\r
\r
- scsiRead(scsiDev.data + scsiDev.dataPtr, len);\r
+ int parityError = 0;\r
+ scsiRead(scsiDev.data + scsiDev.dataPtr, len, &parityError);\r
scsiDev.dataPtr += len;\r
\r
- if (scsiDev.parityError &&\r
- (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) &&\r
- (scsiDev.compatMode >= COMPAT_SCSI2))\r
+ if (parityError &&\r
+ (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))\r
{\r
scsiDev.target->sense.code = ABORTED_COMMAND;\r
scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
uint8_t control;\r
\r
scsiEnterPhase(COMMAND);\r
- scsiDev.parityError = 0;\r
\r
memset(scsiDev.cdb + 6, 0, sizeof(scsiDev.cdb) - 6);\r
- scsiRead(scsiDev.cdb, 6);\r
+ int parityError = 0;\r
+ scsiRead(scsiDev.cdb, 6, &parityError);\r
\r
group = scsiDev.cdb[0] >> 5;\r
scsiDev.cdbLen = CmdGroupBytes[group];\r
- if (scsiDev.cdbLen - 6 > 0)\r
+ if (parityError &&\r
+ (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))\r
{\r
- scsiRead(scsiDev.cdb + 6, scsiDev.cdbLen - 6);\r
+ // Don't try and read more bytes, as we cannot be sure what group\r
+ // the command should be.\r
+ }\r
+ else if (scsiDev.cdbLen - 6 > 0)\r
+ {\r
+ scsiRead(scsiDev.cdb + 6, scsiDev.cdbLen - 6, &parityError);\r
}\r
\r
command = scsiDev.cdb[0];\r
memset(scsiDev.cdb, 0xff, sizeof(scsiDev.cdb));\r
return;\r
}\r
- else if (scsiDev.parityError &&\r
- (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) &&\r
- (scsiDev.compatMode >= COMPAT_SCSI2))\r
+ else if (parityError &&\r
+ (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))\r
{\r
scsiDev.target->sense.code = ABORTED_COMMAND;\r
scsiDev.target->sense.asc = SCSI_PARITY_ERROR;\r
\r
scsiPhyReset();\r
\r
- scsiDev.parityError = 0;\r
scsiDev.phase = BUS_FREE;\r
scsiDev.atnFlag = 0;\r
scsiDev.resetFlag = 0;\r
// Ignore stale versions of this flag, but ensure we know the\r
// current value if the flag is still set.\r
scsiDev.atnFlag = 0;\r
- scsiDev.parityError = 0;\r
scsiDev.dataPtr = 0;\r
scsiDev.savedDataPtr = 0;\r
scsiDev.dataLen = 0;\r
}\r
}\r
if ((target != NULL) && (selStatus & 0x40))\r
-// TODO (goodParity || !(scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) || !atnFlag)\r
{\r
// We've been selected!\r
// Assert BSY - Selection success!\r
{\r
scsiDev.compatMode = COMPAT_SCSI1;\r
}\r
- else if (scsiDev.compatMode == COMPAT_UNKNOWN)\r
+ else\r
{\r
scsiDev.compatMode = COMPAT_SCSI2;\r
}\r
scsiEnterPhase(MESSAGE_OUT);\r
\r
scsiDev.atnFlag = 0;\r
- scsiDev.parityError = 0;\r
scsiDev.msgOut = scsiReadByte();\r
scsiDev.msgCount++;\r
\r
- if (scsiDev.parityError &&\r
- (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) &&\r
- (scsiDev.compatMode >= COMPAT_SCSI2))\r
+ if (scsiParityError() &&\r
+ (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY))\r
{\r
// Skip the remaining message bytes, and then start the MESSAGE_OUT\r
// phase again from the start. The initiator will re-send the\r
\r
// Go-back and try the message again.\r
scsiDev.atnFlag = 1;\r
- scsiDev.parityError = 0;\r
}\r
else if (scsiDev.msgOut == 0x00)\r
{\r
\r
#include <string.h>\r
\r
-// Slowest timing. Aim for 1.5MB/s, but it's likely to be faster.\r
-// Assumes a 96MHz fpga clock.\r
-#define SCSI_SCSI1_DESKEW 0x7\r
-#define SCSI_SCSI1_TIMING ((0x7 << 4) | 0xF)\r
-\r
// 5MB/s sync and async.\r
// Assumes a 96MHz fpga clock.\r
// 2:0 Deskew count, 55ns\r
// 6:4 Hold count, 53ns\r
// 3:0 Assertion count, 80ns\r
-#define SCSI_SCSI2_DESKEW 0x6\r
-#define SCSI_SCSI2_TIMING ((0x5 << 4) | 0x8)\r
+#define SCSI_DEFAULT_DESKEW 0x6\r
+#define SCSI_DEFAULT_TIMING ((0x5 << 4) | 0x8)\r
\r
// 10MB/s\r
// 2:0 Deskew count, 25ns\r
{\r
fifoData[i] = scsiPhyRx(); // TODO ASSUMES LITTLE ENDIAN\r
}\r
- // TODO scsiDev.parityError = scsiDev.parityError || SCSI_Parity_Error_Read();\r
}\r
\r
void\r
}\r
\r
void\r
-scsiRead(uint8_t* data, uint32_t count)\r
+scsiRead(uint8_t* data, uint32_t count, int* parityError)\r
{\r
int i = 0;\r
+ *parityError = 0;\r
\r
\r
uint32_t chunk = ((count - i) > SCSI_FIFO_DEPTH)\r
while (i < count && likely(!scsiDev.resetFlag))\r
{\r
while (!scsiPhyComplete() && likely(!scsiDev.resetFlag)) {}\r
+ *parityError |= scsiParityError();\r
scsiPhyFifoFlip();\r
\r
uint32_t nextChunk = ((count - i - chunk) > SCSI_FIFO_DEPTH)\r
*SCSI_CTRL_TIMING = SCSI_FAST10_TIMING;\r
} else {\r
// 5MB/s Timing\r
- *SCSI_CTRL_DESKEW = SCSI_SCSI2_DESKEW;\r
- *SCSI_CTRL_TIMING = SCSI_SCSI2_TIMING;\r
+ *SCSI_CTRL_DESKEW = SCSI_DEFAULT_DESKEW;\r
+ *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING;\r
}\r
\r
*SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset;\r
} else {\r
*SCSI_CTRL_SYNC_OFFSET = 0;\r
\r
- if (scsiDev.compatMode >= COMPAT_SCSI2) {\r
- // 5MB/s Timing\r
- *SCSI_CTRL_DESKEW = SCSI_SCSI2_DESKEW;\r
- *SCSI_CTRL_TIMING = SCSI_SCSI2_TIMING;\r
- } else {\r
- *SCSI_CTRL_DESKEW = SCSI_SCSI1_DESKEW;\r
- *SCSI_CTRL_TIMING = SCSI_SCSI1_TIMING;\r
- }\r
+ // 5MB/s Timing\r
+ *SCSI_CTRL_DESKEW = SCSI_DEFAULT_DESKEW;\r
+ *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING;\r
}\r
\r
*SCSI_CTRL_PHASE = newPhase;\r
*SCSI_CTRL_DBX = 0;\r
\r
*SCSI_CTRL_SYNC_OFFSET = 0;\r
- *SCSI_CTRL_DESKEW = SCSI_SCSI1_DESKEW;\r
- *SCSI_CTRL_TIMING = SCSI_SCSI1_TIMING;\r
+ *SCSI_CTRL_DESKEW = SCSI_DEFAULT_DESKEW;\r
+ *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING;\r
\r
// DMA Benchmark code\r
// Currently 11MB/s.\r
}\r
#endif\r
\r
+ //#ifdef SCSI_FREQ_TEST\r
+ while(1)\r
+ {\r
+ *SCSI_CTRL_DBX = 0xAA;\r
+ *SCSI_CTRL_DBX = 0x55;\r
+ }\r
+ //#endif\r
+\r
}\r
\r
static void scsiPhyInitDMA()\r
*SCSI_CTRL_DBX = 0;\r
\r
*SCSI_CTRL_SYNC_OFFSET = 0;\r
- *SCSI_CTRL_DESKEW = SCSI_SCSI1_DESKEW;\r
- *SCSI_CTRL_TIMING = SCSI_SCSI1_TIMING;\r
+ *SCSI_CTRL_DESKEW = SCSI_DEFAULT_DESKEW;\r
+ *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING;\r
\r
}\r
\r
*SCSI_CTRL_IDMASK = idMask;\r
\r
*SCSI_CTRL_FLAGS =\r
- (scsiDev.boardCfg.flags & S2S_CFG_DISABLE_GLITCH) ? 1 : 0;\r
+ ((scsiDev.boardCfg.flags & S2S_CFG_DISABLE_GLITCH) ?\r
+ SCSI_CTRL_FLAGS_DISABLE_GLITCH : 0) |\r
+ ((scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) ?\r
+ SCSI_CTRL_FLAGS_ENABLE_PARITY : 0);\r
\r
}\r
\r
#define SCSI_CTRL_DESKEW ((volatile uint8_t*)0x60000012)
#define SCSI_CTRL_TIMING ((volatile uint8_t*)0x60000014)
#define SCSI_CTRL_FLAGS ((volatile uint8_t*)0x60000016)
+#define SCSI_CTRL_FLAGS_DISABLE_GLITCH 0x1
+#define SCSI_CTRL_FLAGS_ENABLE_PARITY 0x2
#define SCSI_STS_FIFO ((volatile uint8_t*)0x60000020)
#define SCSI_STS_ALTFIFO ((volatile uint8_t*)0x60000022)
#define SCSI_STS_SELECTED ((volatile uint8_t*)0x60000026)
#define SCSI_STS_SCSI ((volatile uint8_t*)0x60000028)
#define SCSI_STS_DBX ((volatile uint8_t*)0x6000002A)
+#define SCSI_STS_PARITY_ERR ((volatile uint8_t*)0x6000002C)
#define SCSI_FIFO_DATA ((volatile uint16_t*)0x60000040)
#define SCSI_FIFO_DEPTH 512
#define scsiStatusSEL() ((*SCSI_STS_SCSI & 0x08) == 0x08)
#define scsiStatusACK() ((*SCSI_STS_SCSI & 0x10) == 0x10)
+#define scsiParityError() ((*SCSI_STS_PARITY_ERR & 0x1) == 0x1)
+
// Disable DMA due to errate with the STM32F205 DMA2 controller when
// concurrently transferring FSMC (with FIFO) and APB (ie. sdio)
// peripherals.
void scsiSetDataCount(uint32_t count);
void scsiWrite(const uint8_t* data, uint32_t count);
-void scsiRead(uint8_t* data, uint32_t count);
+void scsiRead(uint8_t* data, uint32_t count, int* parityError);
void scsiWriteByte(uint8_t value);
uint8_t scsiReadByte(void);
static void sdClear()\r
{\r
sdDev.version = 0;\r
- sdDev.ccs = 0;\r
sdDev.capacity = 0;\r
memset(sdDev.csd, 0, sizeof(sdDev.csd));\r
memset(sdDev.cid, 0, sizeof(sdDev.cid));\r
typedef struct
{
int version; // SDHC = version 2.
- int ccs; // Card Capacity Status. 1 = SDHC or SDXC
uint32_t capacity; // in 512 byte blocks
uint8_t csd[16]; // Unparsed CSD