Эх сурвалжийг харах

Fix for large writes and data corruption over 64k

Michael McMaster 5 жил өмнө
parent
commit
2c15baa7f1

+ 6 - 0
lib/SCSI2SD/CHANGELOG

@@ -1,3 +1,9 @@
+20200130		6.2.15
+	- Fix issue writing more than 512kb of data in one write command
+	(bug introduced 6.2.7)
+	- Fix possible data corruption bug when reading or writing more than
+	64kb per command (fixed in most cases by 6.2.14)
+
 20200101		6.2.14
 	- Fix for invalid CDROM READ TOC responses (Thanks Simon Gander)
 	- Fix for data corruption for hosts that transfer more than 64k per

BIN
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 = 0x062E;
+static const uint16_t FIRMWARE_VERSION = 0x062F;
 
 // Optional static config
 extern uint8_t* __fixed_config;

+ 24 - 3
lib/SCSI2SD/src/firmware/disk.c

@@ -736,8 +736,17 @@ void scsiDiskPoll()
 		static_assert(SCSI_XFER_MAX >= sizeof(scsiDev.data), "Assumes SCSI_XFER_MAX >= sizeof(scsiDev.data)");
 
 		// Start reading and filling fifos as soon as possible.
-		DWT->CYCCNT = 0; // Start counting cycles
-		scsiSetDataCount(transfer.blocks * bytesPerSector);
+		// It's highly unlikely that someone is going to use huge transfers
+		// per scsi command, but if they do it'll be slower than usual.
+		// Note: Happens in Macintosh FWB HDD Toolkit benchmarks which default
+		// to 768kb
+		uint32_t totalTransferBytes = transfer.blocks * bytesPerSector;
+		int useSlowDataCount = totalTransferBytes >= SCSI_XFER_MAX;
+		if (!useSlowDataCount)
+		{
+			DWT->CYCCNT = 0; // Start counting cycles
+			scsiSetDataCount(totalTransferBytes);
+		}
 
 		while ((i < totalSDSectors) &&
 			likely(scsiDev.phase == DATA_OUT) &&
@@ -762,6 +771,12 @@ void scsiDiskPoll()
 					sdSpeedKBs,
 					scsiDev.hostSpeedKBs);
 
+				if (useSlowDataCount)
+				{
+					DWT->CYCCNT = 0; // Start counting cycles
+					scsiSetDataCount(totalBytes);
+				}
+
 				uint32_t scsiBytesRead = 0;
 				if (readAheadBytes > 0)
 				{
@@ -771,7 +786,7 @@ void scsiDiskPoll()
 						&parityError);
 					scsiBytesRead += readAheadBytes;
 
-					if (i == 0)
+					if (i == 0 && !useSlowDataCount)
 					{
 						uint32_t elapsedCycles = DWT->CYCCNT;
 
@@ -864,6 +879,12 @@ void scsiDiskPoll()
 				// do this in a half-duplex fashion. We need to write as much as
 				// possible in each SD card transaction.
 				// use sg_dd from sg_utils3 tools to test.
+
+				if (useSlowDataCount)
+				{
+					scsiSetDataCount(sectors * bytesPerSector);
+				}
+
 				for (int scsiSector = i; scsiSector < i + sectors; ++scsiSector)
 				{
 					int dmaBytes = SD_SECTOR_SIZE;