Fix for large writes and data corruption over 64k 6.2.15
authorMichael McMaster <michael@codesrc.com>
Thu, 30 Jan 2020 09:17:49 +0000 (19:17 +1000)
committerMichael McMaster <michael@codesrc.com>
Thu, 30 Jan 2020 09:17:49 +0000 (19:17 +1000)
CHANGELOG
rtl/fpga_bitmap.o
src/firmware/config.c
src/firmware/disk.c

index ef65698..3e76dc9 100644 (file)
--- a/CHANGELOG
+++ b/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
index e423f33..e351fea 100644 (file)
Binary files a/rtl/fpga_bitmap.o and b/rtl/fpga_bitmap.o differ
index f2e6d1e..929921a 100755 (executable)
@@ -37,7 +37,7 @@
 \r
 #include <string.h>\r
 \r
-static const uint16_t FIRMWARE_VERSION = 0x062E;\r
+static const uint16_t FIRMWARE_VERSION = 0x062F;\r
 \r
 // Optional static config\r
 extern uint8_t* __fixed_config;\r
index 3c562e3..f79842f 100755 (executable)
@@ -736,8 +736,17 @@ void scsiDiskPoll()
                static_assert(SCSI_XFER_MAX >= sizeof(scsiDev.data), "Assumes SCSI_XFER_MAX >= sizeof(scsiDev.data)");\r
 \r
                // Start reading and filling fifos as soon as possible.\r
-               DWT->CYCCNT = 0; // Start counting cycles\r
-               scsiSetDataCount(transfer.blocks * bytesPerSector);\r
+               // It's highly unlikely that someone is going to use huge transfers\r
+               // per scsi command, but if they do it'll be slower than usual.\r
+               // Note: Happens in Macintosh FWB HDD Toolkit benchmarks which default\r
+               // to 768kb\r
+               uint32_t totalTransferBytes = transfer.blocks * bytesPerSector;\r
+               int useSlowDataCount = totalTransferBytes >= SCSI_XFER_MAX;\r
+               if (!useSlowDataCount)\r
+               {\r
+                       DWT->CYCCNT = 0; // Start counting cycles\r
+                       scsiSetDataCount(totalTransferBytes);\r
+               }\r
 \r
                while ((i < totalSDSectors) &&\r
                        likely(scsiDev.phase == DATA_OUT) &&\r
@@ -762,6 +771,12 @@ void scsiDiskPoll()
                                        sdSpeedKBs,\r
                                        scsiDev.hostSpeedKBs);\r
 \r
+                               if (useSlowDataCount)\r
+                               {\r
+                                       DWT->CYCCNT = 0; // Start counting cycles\r
+                                       scsiSetDataCount(totalBytes);\r
+                               }\r
+\r
                                uint32_t scsiBytesRead = 0;\r
                                if (readAheadBytes > 0)\r
                                {\r
@@ -771,7 +786,7 @@ void scsiDiskPoll()
                                                &parityError);\r
                                        scsiBytesRead += readAheadBytes;\r
 \r
-                                       if (i == 0)\r
+                                       if (i == 0 && !useSlowDataCount)\r
                                        {\r
                                                uint32_t elapsedCycles = DWT->CYCCNT;\r
 \r
@@ -864,6 +879,12 @@ void scsiDiskPoll()
                                // do this in a half-duplex fashion. We need to write as much as\r
                                // possible in each SD card transaction.\r
                                // use sg_dd from sg_utils3 tools to test.\r
+\r
+                               if (useSlowDataCount)\r
+                               {\r
+                                       scsiSetDataCount(sectors * bytesPerSector);\r
+                               }\r
+\r
                                for (int scsiSector = i; scsiSector < i + sectors; ++scsiSector)\r
                                {\r
                                        int dmaBytes = SD_SECTOR_SIZE;\r