Parity checking v6.0.12
authorMichael McMaster <michael@codesrc.com>
Thu, 6 Oct 2016 10:07:49 +0000 (20:07 +1000)
committerMichael McMaster <michael@codesrc.com>
Thu, 6 Oct 2016 10:07:49 +0000 (20:07 +1000)
CHANGELOG
doc/SCSI2SD_QuickStartGuide.odt
rtl/fpga_bitmap.o
src/firmware/config.c
src/firmware/disk.c
src/firmware/scsi.c
src/firmware/scsiPhy.c
src/firmware/scsiPhy.h
src/firmware/sd.c
src/firmware/sd.h

index a6cd8c6..f58e8e3 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
-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.
index 6d929b3..fd66169 100644 (file)
Binary files a/doc/SCSI2SD_QuickStartGuide.odt and b/doc/SCSI2SD_QuickStartGuide.odt differ
index 20717db..d959704 100644 (file)
Binary files a/rtl/fpga_bitmap.o and b/rtl/fpga_bitmap.o differ
index 7ab2001..686698f 100755 (executable)
@@ -37,7 +37,7 @@
 \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
index 7d6d475..b3e612f 100755 (executable)
@@ -669,10 +669,12 @@ void scsiDiskPoll()
                // 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
@@ -681,8 +683,11 @@ void scsiDiskPoll()
                        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
@@ -825,9 +830,8 @@ void scsiDiskPoll()
 \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
index 176a0a7..914c077 100755 (executable)
@@ -97,7 +97,6 @@ void process_MessageIn()
        {\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
@@ -201,18 +200,17 @@ static void process_DataOut()
                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
@@ -242,16 +240,22 @@ static void process_Command()
        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
@@ -274,9 +278,8 @@ static void process_Command()
                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
@@ -461,7 +464,6 @@ static void scsiReset()
 \r
        scsiPhyReset();\r
 \r
-       scsiDev.parityError = 0;\r
        scsiDev.phase = BUS_FREE;\r
        scsiDev.atnFlag = 0;\r
        scsiDev.resetFlag = 0;\r
@@ -507,7 +509,6 @@ static void enter_SelectionPhase()
        // 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
@@ -559,7 +560,6 @@ static void process_SelectionPhase()
                }\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
@@ -591,7 +591,7 @@ static void process_SelectionPhase()
                {\r
                        scsiDev.compatMode = COMPAT_SCSI1;\r
                }\r
-               else if (scsiDev.compatMode == COMPAT_UNKNOWN)\r
+               else\r
                {\r
                        scsiDev.compatMode = COMPAT_SCSI2;\r
                }\r
@@ -622,13 +622,11 @@ static void process_MessageOut()
        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
@@ -640,7 +638,6 @@ static void process_MessageOut()
 \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
index ca3b494..6831759 100755 (executable)
 \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
@@ -161,7 +156,6 @@ scsiReadPIO(uint8_t* data, uint32_t count)
        {\r
                fifoData[i] = scsiPhyRx(); // TODO ASSUMES LITTLE ENDIAN\r
        }\r
-       // TODO scsiDev.parityError = scsiDev.parityError || SCSI_Parity_Error_Read();\r
 }\r
 \r
 void\r
@@ -205,9 +199,10 @@ scsiReadDMAPoll()
 }\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
@@ -224,6 +219,7 @@ scsiRead(uint8_t* data, uint32_t count)
        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
@@ -456,22 +452,17 @@ void scsiEnterPhase(int phase)
                                *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
@@ -506,8 +497,8 @@ void scsiPhyReset()
        *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
@@ -601,6 +592,14 @@ void scsiPhyReset()
        }\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
@@ -673,8 +672,8 @@ void scsiPhyInit()
        *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
@@ -702,7 +701,10 @@ void scsiPhyConfig()
        *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
index 7f52280..1df96b9 100755 (executable)
@@ -29,6 +29,8 @@
 #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)
@@ -36,6 +38,7 @@
 #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
@@ -61,6 +64,8 @@
 #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.
@@ -78,7 +83,7 @@ void scsiEnterBusFree(void);
 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);
 
index 204936d..71ec535 100755 (executable)
@@ -278,7 +278,6 @@ void sdTmpWrite(uint8_t* data, uint32_t lba, int sectors)
 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
index 74f89a6..0a9d632 100755 (executable)
@@ -24,7 +24,6 @@
 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