瀏覽代碼

Parity checking

Michael McMaster 9 年之前
父節點
當前提交
95bdfb1102

+ 2 - 1
lib/SCSI2SD/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.

二進制
lib/SCSI2SD/doc/SCSI2SD_QuickStartGuide.odt


二進制
lib/SCSI2SD/rtl/fpga_bitmap.o


+ 1 - 1
lib/SCSI2SD/src/firmware/config.c

@@ -37,7 +37,7 @@
 
 #include <string.h>
 
-static const uint16_t FIRMWARE_VERSION = 0x060B;
+static const uint16_t FIRMWARE_VERSION = 0x060C;
 
 // 1 flash row
 static const uint8_t DEFAULT_CONFIG[128] =

+ 10 - 6
lib/SCSI2SD/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;

+ 19 - 22
lib/SCSI2SD/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)
 	{

+ 26 - 24
lib/SCSI2SD/src/firmware/scsiPhy.c

@@ -28,18 +28,13 @@
 
 #include <string.h>
 
-// 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);
 
 }
 

+ 6 - 1
lib/SCSI2SD/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);
 

+ 0 - 1
lib/SCSI2SD/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));

+ 0 - 1
lib/SCSI2SD/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