From: Michael McMaster Date: Thu, 6 Oct 2016 10:07:49 +0000 (+1000) Subject: Parity checking X-Git-Tag: v6.0.12 X-Git-Url: http://git.codesrc.com/gitweb.cgi?a=commitdiff_plain;h=20c5778fe878ec531be68c9369d9c813b1ec06ae;p=SCSI2SD-V6.git Parity checking --- diff --git a/CHANGELOG b/CHANGELOG index a6cd8c64..f58e8e33 100644 --- 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. diff --git a/doc/SCSI2SD_QuickStartGuide.odt b/doc/SCSI2SD_QuickStartGuide.odt index 6d929b39..fd661691 100644 Binary files a/doc/SCSI2SD_QuickStartGuide.odt and b/doc/SCSI2SD_QuickStartGuide.odt differ diff --git a/rtl/fpga_bitmap.o b/rtl/fpga_bitmap.o index 20717dbc..d9597043 100644 Binary files a/rtl/fpga_bitmap.o and b/rtl/fpga_bitmap.o differ diff --git a/src/firmware/config.c b/src/firmware/config.c index 7ab2001b..686698f4 100755 --- a/src/firmware/config.c +++ b/src/firmware/config.c @@ -37,7 +37,7 @@ #include -static const uint16_t FIRMWARE_VERSION = 0x060B; +static const uint16_t FIRMWARE_VERSION = 0x060C; // 1 flash row static const uint8_t DEFAULT_CONFIG[128] = diff --git a/src/firmware/disk.c b/src/firmware/disk.c index 7d6d4757..b3e612fe 100755 --- a/src/firmware/disk.c +++ b/src/firmware/disk.c @@ -669,10 +669,12 @@ void scsiDiskPoll() // int scsiActive = 0; // int sdActive = 0; + int parityError = 0; while ((i < totalSDSectors) && (likely(scsiDev.phase == DATA_OUT) || // scsiDisconnect keeps our phase. scsiComplete) && - likely(!scsiDev.resetFlag)) + likely(!scsiDev.resetFlag) && + likely(!parityError)) { // Well, until we have some proper non-blocking SD code, we must // do this in a half-duplex fashion. We need to write as much as @@ -681,8 +683,11 @@ void scsiDiskPoll() uint32_t rem = totalSDSectors - i; uint32_t sectors = rem < maxSectors ? rem : maxSectors; - scsiRead(&scsiDev.data[0], sectors * SD_SECTOR_SIZE); - sdTmpWrite(&scsiDev.data[0], i + sdLBA, sectors); + scsiRead(&scsiDev.data[0], sectors * SD_SECTOR_SIZE, &parityError); + if (!parityError) + { + sdTmpWrite(&scsiDev.data[0], i + sdLBA, sectors); + } i += sectors; #if 0 // Wait for the next DMA interrupt. It's beneficial to halt the @@ -825,9 +830,8 @@ void scsiDiskPoll() if (scsiDev.phase == DATA_OUT) { - if (scsiDev.parityError && - (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) && - (scsiDev.compatMode >= COMPAT_SCSI2)) + if (parityError && + (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY)) { scsiDev.target->sense.code = ABORTED_COMMAND; scsiDev.target->sense.asc = SCSI_PARITY_ERROR; diff --git a/src/firmware/scsi.c b/src/firmware/scsi.c index 176a0a7c..914c0774 100755 --- a/src/firmware/scsi.c +++ b/src/firmware/scsi.c @@ -97,7 +97,6 @@ void process_MessageIn() { // Go back to the command phase and start again. scsiDev.phase = COMMAND; - scsiDev.parityError = 0; scsiDev.dataPtr = 0; scsiDev.savedDataPtr = 0; scsiDev.dataLen = 0; @@ -201,18 +200,17 @@ static void process_DataOut() scsiDev.dataLen = sizeof(scsiDev.data); } - scsiDev.parityError = 0; len = scsiDev.dataLen - scsiDev.dataPtr; if (len > 0) { scsiEnterPhase(DATA_OUT); - scsiRead(scsiDev.data + scsiDev.dataPtr, len); + int parityError = 0; + scsiRead(scsiDev.data + scsiDev.dataPtr, len, &parityError); scsiDev.dataPtr += len; - if (scsiDev.parityError && - (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) && - (scsiDev.compatMode >= COMPAT_SCSI2)) + if (parityError && + (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY)) { scsiDev.target->sense.code = ABORTED_COMMAND; scsiDev.target->sense.asc = SCSI_PARITY_ERROR; @@ -242,16 +240,22 @@ static void process_Command() uint8_t control; scsiEnterPhase(COMMAND); - scsiDev.parityError = 0; memset(scsiDev.cdb + 6, 0, sizeof(scsiDev.cdb) - 6); - scsiRead(scsiDev.cdb, 6); + int parityError = 0; + scsiRead(scsiDev.cdb, 6, &parityError); group = scsiDev.cdb[0] >> 5; scsiDev.cdbLen = CmdGroupBytes[group]; - if (scsiDev.cdbLen - 6 > 0) + if (parityError && + (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY)) { - scsiRead(scsiDev.cdb + 6, scsiDev.cdbLen - 6); + // Don't try and read more bytes, as we cannot be sure what group + // the command should be. + } + else if (scsiDev.cdbLen - 6 > 0) + { + scsiRead(scsiDev.cdb + 6, scsiDev.cdbLen - 6, &parityError); } command = scsiDev.cdb[0]; @@ -274,9 +278,8 @@ static void process_Command() memset(scsiDev.cdb, 0xff, sizeof(scsiDev.cdb)); return; } - else if (scsiDev.parityError && - (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) && - (scsiDev.compatMode >= COMPAT_SCSI2)) + else if (parityError && + (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY)) { scsiDev.target->sense.code = ABORTED_COMMAND; scsiDev.target->sense.asc = SCSI_PARITY_ERROR; @@ -461,7 +464,6 @@ static void scsiReset() scsiPhyReset(); - scsiDev.parityError = 0; scsiDev.phase = BUS_FREE; scsiDev.atnFlag = 0; scsiDev.resetFlag = 0; @@ -507,7 +509,6 @@ static void enter_SelectionPhase() // Ignore stale versions of this flag, but ensure we know the // current value if the flag is still set. scsiDev.atnFlag = 0; - scsiDev.parityError = 0; scsiDev.dataPtr = 0; scsiDev.savedDataPtr = 0; scsiDev.dataLen = 0; @@ -559,7 +560,6 @@ static void process_SelectionPhase() } } if ((target != NULL) && (selStatus & 0x40)) -// TODO (goodParity || !(scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) || !atnFlag) { // We've been selected! // Assert BSY - Selection success! @@ -591,7 +591,7 @@ static void process_SelectionPhase() { scsiDev.compatMode = COMPAT_SCSI1; } - else if (scsiDev.compatMode == COMPAT_UNKNOWN) + else { scsiDev.compatMode = COMPAT_SCSI2; } @@ -622,13 +622,11 @@ static void process_MessageOut() scsiEnterPhase(MESSAGE_OUT); scsiDev.atnFlag = 0; - scsiDev.parityError = 0; scsiDev.msgOut = scsiReadByte(); scsiDev.msgCount++; - if (scsiDev.parityError && - (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) && - (scsiDev.compatMode >= COMPAT_SCSI2)) + if (scsiParityError() && + (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY)) { // Skip the remaining message bytes, and then start the MESSAGE_OUT // phase again from the start. The initiator will re-send the @@ -640,7 +638,6 @@ static void process_MessageOut() // Go-back and try the message again. scsiDev.atnFlag = 1; - scsiDev.parityError = 0; } else if (scsiDev.msgOut == 0x00) { diff --git a/src/firmware/scsiPhy.c b/src/firmware/scsiPhy.c index ca3b494a..68317598 100755 --- a/src/firmware/scsiPhy.c +++ b/src/firmware/scsiPhy.c @@ -28,18 +28,13 @@ #include -// Slowest timing. Aim for 1.5MB/s, but it's likely to be faster. -// Assumes a 96MHz fpga clock. -#define SCSI_SCSI1_DESKEW 0x7 -#define SCSI_SCSI1_TIMING ((0x7 << 4) | 0xF) - // 5MB/s sync and async. // Assumes a 96MHz fpga clock. // 2:0 Deskew count, 55ns // 6:4 Hold count, 53ns // 3:0 Assertion count, 80ns -#define SCSI_SCSI2_DESKEW 0x6 -#define SCSI_SCSI2_TIMING ((0x5 << 4) | 0x8) +#define SCSI_DEFAULT_DESKEW 0x6 +#define SCSI_DEFAULT_TIMING ((0x5 << 4) | 0x8) // 10MB/s // 2:0 Deskew count, 25ns @@ -161,7 +156,6 @@ scsiReadPIO(uint8_t* data, uint32_t count) { fifoData[i] = scsiPhyRx(); // TODO ASSUMES LITTLE ENDIAN } - // TODO scsiDev.parityError = scsiDev.parityError || SCSI_Parity_Error_Read(); } void @@ -205,9 +199,10 @@ scsiReadDMAPoll() } void -scsiRead(uint8_t* data, uint32_t count) +scsiRead(uint8_t* data, uint32_t count, int* parityError) { int i = 0; + *parityError = 0; uint32_t chunk = ((count - i) > SCSI_FIFO_DEPTH) @@ -224,6 +219,7 @@ scsiRead(uint8_t* data, uint32_t count) while (i < count && likely(!scsiDev.resetFlag)) { while (!scsiPhyComplete() && likely(!scsiDev.resetFlag)) {} + *parityError |= scsiParityError(); scsiPhyFifoFlip(); uint32_t nextChunk = ((count - i - chunk) > SCSI_FIFO_DEPTH) @@ -456,22 +452,17 @@ void scsiEnterPhase(int phase) *SCSI_CTRL_TIMING = SCSI_FAST10_TIMING; } else { // 5MB/s Timing - *SCSI_CTRL_DESKEW = SCSI_SCSI2_DESKEW; - *SCSI_CTRL_TIMING = SCSI_SCSI2_TIMING; + *SCSI_CTRL_DESKEW = SCSI_DEFAULT_DESKEW; + *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING; } *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset; } else { *SCSI_CTRL_SYNC_OFFSET = 0; - if (scsiDev.compatMode >= COMPAT_SCSI2) { - // 5MB/s Timing - *SCSI_CTRL_DESKEW = SCSI_SCSI2_DESKEW; - *SCSI_CTRL_TIMING = SCSI_SCSI2_TIMING; - } else { - *SCSI_CTRL_DESKEW = SCSI_SCSI1_DESKEW; - *SCSI_CTRL_TIMING = SCSI_SCSI1_TIMING; - } + // 5MB/s Timing + *SCSI_CTRL_DESKEW = SCSI_DEFAULT_DESKEW; + *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING; } *SCSI_CTRL_PHASE = newPhase; @@ -506,8 +497,8 @@ void scsiPhyReset() *SCSI_CTRL_DBX = 0; *SCSI_CTRL_SYNC_OFFSET = 0; - *SCSI_CTRL_DESKEW = SCSI_SCSI1_DESKEW; - *SCSI_CTRL_TIMING = SCSI_SCSI1_TIMING; + *SCSI_CTRL_DESKEW = SCSI_DEFAULT_DESKEW; + *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING; // DMA Benchmark code // Currently 11MB/s. @@ -601,6 +592,14 @@ void scsiPhyReset() } #endif + //#ifdef SCSI_FREQ_TEST + while(1) + { + *SCSI_CTRL_DBX = 0xAA; + *SCSI_CTRL_DBX = 0x55; + } + //#endif + } static void scsiPhyInitDMA() @@ -673,8 +672,8 @@ void scsiPhyInit() *SCSI_CTRL_DBX = 0; *SCSI_CTRL_SYNC_OFFSET = 0; - *SCSI_CTRL_DESKEW = SCSI_SCSI1_DESKEW; - *SCSI_CTRL_TIMING = SCSI_SCSI1_TIMING; + *SCSI_CTRL_DESKEW = SCSI_DEFAULT_DESKEW; + *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING; } @@ -702,7 +701,10 @@ void scsiPhyConfig() *SCSI_CTRL_IDMASK = idMask; *SCSI_CTRL_FLAGS = - (scsiDev.boardCfg.flags & S2S_CFG_DISABLE_GLITCH) ? 1 : 0; + ((scsiDev.boardCfg.flags & S2S_CFG_DISABLE_GLITCH) ? + SCSI_CTRL_FLAGS_DISABLE_GLITCH : 0) | + ((scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) ? + SCSI_CTRL_FLAGS_ENABLE_PARITY : 0); } diff --git a/src/firmware/scsiPhy.h b/src/firmware/scsiPhy.h index 7f52280c..1df96b95 100755 --- a/src/firmware/scsiPhy.h +++ b/src/firmware/scsiPhy.h @@ -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); diff --git a/src/firmware/sd.c b/src/firmware/sd.c index 204936db..71ec535c 100755 --- a/src/firmware/sd.c +++ b/src/firmware/sd.c @@ -278,7 +278,6 @@ void sdTmpWrite(uint8_t* data, uint32_t lba, int sectors) static void sdClear() { sdDev.version = 0; - sdDev.ccs = 0; sdDev.capacity = 0; memset(sdDev.csd, 0, sizeof(sdDev.csd)); memset(sdDev.cid, 0, sizeof(sdDev.cid)); diff --git a/src/firmware/sd.h b/src/firmware/sd.h index 74f89a6a..0a9d6328 100755 --- a/src/firmware/sd.h +++ b/src/firmware/sd.h @@ -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