Improved scsi signal noise rejection, fixed write performance, fixed bug with multipl...
authorMichael McMaster <michael@codesrc.com>
Wed, 19 Sep 2018 11:31:30 +0000 (21:31 +1000)
committerMichael McMaster <michael@codesrc.com>
Wed, 19 Sep 2018 11:31:30 +0000 (21:31 +1000)
12 files changed:
CHANGELOG
rtl/fpga_bitmap.o
src/firmware/bsp.c
src/firmware/bsp.h
src/firmware/config.c
src/firmware/disk.c
src/firmware/scsi.c
src/firmware/scsi.h
src/firmware/scsiPhy.c
src/firmware/scsiPhy.h
src/firmware/usb_device/usbd_msc_scsi.c
src/firmware/usb_device/usbd_msc_storage_sd.c

index 812d557..e8f1227 100644 (file)
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,8 @@
+2018XXXX        6.2.1
+       - Fix bug with non-512 byte sectors.
+       - Fix bug when writing with multiple SCSI devices on the chain
+       - Performance improvements to write speeds.
+
 20180430               6.1.4
        - Fix bug in self-test function
 
index 6613f58..cb1310f 100644 (file)
Binary files a/rtl/fpga_bitmap.o and b/rtl/fpga_bitmap.o differ
index 23da16a..0c0a477 100644 (file)
@@ -23,6 +23,18 @@ static int usingFastClock = 0;
 
 // TODO keep clock routines consistent with those in STM32Cubemx main.c
 
+uint32_t s2s_getSdRateMBs()
+{
+       if (usingFastClock)
+       {
+               return 18; // ((72MHz / 2) / 8bits) * 4bitparallel
+       }
+       else
+       {
+               return 12; // ((48MHz / 2) / 8bits) * 4bitparallel
+       }
+}
+
 // The standard clock is 108MHz with 48MHz SDIO clock
 void s2s_setNormalClock()
 {
index 353c9ea..a11c850 100644 (file)
@@ -18,6 +18,8 @@
 #ifndef S2S_BSP_h
 #define S2S_BSP_h
 
+#include <stdint.h>
+
 // For the STM32F205, DMA bursts may not cross 1KB address boundaries.
 // The maximum burst is 16 bytes.
 #define S2S_DMA_ALIGN __attribute__((aligned(1024)))
@@ -25,5 +27,7 @@
 void s2s_setNormalClock();
 void s2s_setFastClock();
 
+uint32_t s2s_getSdRateMBs();
+
 #endif
 
index 058c8c3..2f68ab5 100755 (executable)
@@ -38,7 +38,7 @@
 \r
 #include <string.h>\r
 \r
-static const uint16_t FIRMWARE_VERSION = 0x0614;\r
+static const uint16_t FIRMWARE_VERSION = 0x0620;\r
 \r
 // 1 flash row\r
 static const uint8_t DEFAULT_CONFIG[128] =\r
index 5b11400..89db179 100755 (executable)
 \r
 #include "stm32f2xx.h"\r
 \r
+// For SD write direct routines\r
+#include "sdio.h"\r
+#include "bsp_driver_sd.h"\r
+\r
+\r
 #include "scsi.h"\r
 #include "scsiPhy.h"\r
 #include "config.h"\r
 #include "disk.h"\r
 #include "sd.h"\r
 #include "time.h"\r
+#include "bsp.h"\r
 \r
 #include <string.h>\r
 \r
@@ -533,7 +539,6 @@ void scsiDiskPoll()
        if (scsiDev.phase == DATA_IN &&\r
                transfer.currentBlock != transfer.blocks)\r
        {\r
-               scsiEnterPhase(DATA_IN);\r
 \r
                int totalSDSectors =\r
                        transfer.blocks * SDSectorsPerSCSISector(bytesPerSector);\r
@@ -549,8 +554,15 @@ void scsiDiskPoll()
                int i = 0;\r
                int scsiActive __attribute__((unused)) = 0; // unused if DMA disabled\r
                int sdActive = 0;\r
+\r
+               uint32_t partialScsiChunk = 0;\r
+\r
+               // Start reading from the SD card FIRST, because we change state and\r
+               // wai for SCSI signals\r
+               int dataInStarted = 0;\r
+\r
                while ((i < totalSDSectors) &&\r
-                       likely(scsiDev.phase == DATA_IN) &&\r
+                       (!dataInStarted || likely(scsiDev.phase == DATA_IN)) &&\r
                        likely(!scsiDev.resetFlag))\r
                {\r
                        int completedDmaSectors;\r
@@ -594,9 +606,16 @@ void scsiDiskPoll()
                                sdReadDMA(sdLBA + prep, sectors, &scsiDev.data[SD_SECTOR_SIZE * startBuffer]);\r
 \r
                                sdActive = sectors;\r
+\r
+                               if (!dataInStarted)\r
+                               {\r
+                                       dataInStarted = 1;\r
+                                       scsiEnterPhase(DATA_IN); // Will wait a few microseconds.\r
+                               }\r
                        }\r
 \r
 #ifdef SCSI_FSMC_DMA\r
+                       #error this code not updated for 256 max bytes in scsi fifo\r
                        if (scsiActive && scsiPhyComplete() && scsiWriteDMAPoll())\r
                        {\r
                                scsiActive = 0;\r
@@ -624,33 +643,49 @@ void scsiDiskPoll()
                                        if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;\r
                                }\r
 \r
-                               uint16_t* scsiDmaData = (uint16_t*) &(scsiDev.data[SD_SECTOR_SIZE * (i % buffers)]);\r
                                // Manually unrolled loop for performance.\r
                                // -Os won't unroll this for us automatically,\r
                                // especially since scsiPhyTx does volatile stuff.\r
                                // Reduces bus utilisation by making the fsmc split\r
                                // 32bits into 2 16 bit writes.\r
+\r
+                               uint16_t* scsiDmaData = (uint16_t*) &(scsiDev.data[SD_SECTOR_SIZE * (i % buffers) + partialScsiChunk]);\r
+\r
+                               uint32_t chunk = ((dmaBytes - partialScsiChunk) > SCSI_FIFO_DEPTH)\r
+                                       ? SCSI_FIFO_DEPTH : (dmaBytes - partialScsiChunk);\r
+\r
                                int k = 0;\r
-                               for (; k + 4 < (dmaBytes + 1) / 2; k += 4)\r
+                               for (; k + 4 < (chunk + 1) / 2; k += 4)\r
                                {\r
                                        scsiPhyTx32(scsiDmaData[k], scsiDmaData[k+1]);\r
                                        scsiPhyTx32(scsiDmaData[k+2], scsiDmaData[k+3]);\r
                                }\r
-                               for (; k < (dmaBytes + 1) / 2; ++k)\r
+                               for (; k < (chunk + 1) / 2; ++k)\r
                                {\r
                                        scsiPhyTx(scsiDmaData[k]);\r
                                }\r
-                               i++;\r
                                while (!scsiPhyComplete() && !scsiDev.resetFlag)\r
                                {\r
                                        __WFE(); // Wait for event\r
                                }\r
                                scsiPhyFifoFlip();\r
-                               scsiSetDataCount(dmaBytes);\r
+                               scsiSetDataCount(chunk);\r
+\r
+                               partialScsiChunk += chunk;\r
+                               if (partialScsiChunk == dmaBytes)\r
+                               {\r
+                                       partialScsiChunk = 0;\r
+                                       ++i;\r
+                               }\r
                        }\r
 #endif\r
                }\r
 \r
+               if (!dataInStarted && !scsiDev.resetFlag) // zero bytes ?\r
+               {\r
+                       scsiEnterPhase(DATA_IN); // Will wait a few microseconds.\r
+               }\r
+\r
                // We've finished transferring the data to the FPGA, now wait until it's\r
                // written to he SCSI bus.\r
                while (!scsiPhyComplete() &&\r
@@ -679,22 +714,16 @@ void scsiDiskPoll()
                                scsiDev.target->cfg->sdSectorStart,\r
                                bytesPerSector,\r
                                transfer.lba);\r
-               // int buffers = sizeof(scsiDev.data) / SD_SECTOR_SIZE;\r
-               // int prep = 0;\r
                int i = 0;\r
-               // int scsiDisconnected = 0;\r
-               int scsiComplete = 0;\r
-               //uint32_t lastActivityTime = s2s_getTime_ms();\r
-               // int scsiActive = 0;\r
-               // int sdActive = 0;\r
                int clearBSY = 0;\r
 \r
                int parityError = 0;\r
+               int enableParity = scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY;\r
+\r
                while ((i < totalSDSectors) &&\r
-                       (likely(scsiDev.phase == DATA_OUT) || // scsiDisconnect keeps our phase.\r
-                               scsiComplete) &&\r
+                       likely(scsiDev.phase == DATA_OUT) &&\r
                        likely(!scsiDev.resetFlag) &&\r
-                       likely(!parityError))\r
+                       likely(!parityError || !enableParity))\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
@@ -703,178 +732,146 @@ 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, &parityError);\r
 \r
-                       if (i + sectors >= totalSDSectors)\r
+                       if (bytesPerSector == SD_SECTOR_SIZE)\r
                        {\r
-                               // We're transferring over the SCSI bus faster than the SD card\r
-                               // can write.  All data is buffered, and we're just waiting for\r
-                               // the SD card to complete. The host won't let us disconnect.\r
-                               // Some drivers set a 250ms timeout on transfers to complete.\r
-                               // SD card writes are supposed to complete\r
-                               // within 200ms, but sometimes they don'to.\r
-                               // Just pretend we're finished.\r
-                               process_Status();\r
-                               process_MessageIn(); // Will go to BUS_FREE state\r
-\r
-                               // Try and prevent anyone else using the SCSI bus while we're not ready.\r
-                               if (*SCSI_CTRL_BSY == 0) // Could be busy for a linked command\r
+                               // We assume the SD card is faster than the SCSI interface, but has\r
+                               // no flow control. This can be handled if a) the scsi interface\r
+                               // doesn't block and b) we read enough SCSI sectors first so that\r
+                               // the SD interface cannot catch up.\r
+                               uint32_t totalBytes = sectors * SD_SECTOR_SIZE;\r
+                               uint32_t readAheadBytes = sectors * SD_SECTOR_SIZE;\r
+                               uint32_t sdSpeed = s2s_getSdRateMBs() + (scsiDev.sdUnderrunCount / 2);\r
+                               uint32_t scsiSpeed = s2s_getScsiRateMBs();\r
+                               // if (have blind writes)\r
+                               if (scsiSpeed > 0 && scsiDev.sdUnderrunCount < 16)\r
                                {\r
-                                       *SCSI_CTRL_BSY = 1;\r
-                                       clearBSY = 1;\r
+                                       // readAhead = sectors * (sd / scsi - 1 + 0.1);\r
+                                       readAheadBytes = totalBytes * sdSpeed / scsiSpeed - totalBytes + SCSI_FIFO_DEPTH;\r
+                                       if (readAheadBytes < SCSI_FIFO_DEPTH)\r
+                                       {\r
+                                               readAheadBytes = SCSI_FIFO_DEPTH;\r
+                                       }\r
+\r
+                                       if (readAheadBytes > totalBytes)\r
+                                       {\r
+                                               readAheadBytes = totalBytes;\r
+                                       }\r
                                }\r
-                       }\r
 \r
+                               uint32_t chunk = (readAheadBytes > SCSI_FIFO_DEPTH) ? SCSI_FIFO_DEPTH : readAheadBytes;\r
+                               scsiSetDataCount(chunk);\r
 \r
-                       if (!parityError)\r
-                       {\r
-                               sdTmpWrite(&scsiDev.data[0], i + sdLBA, sectors);\r
-                       }\r
-                       i += sectors;\r
+                               uint32_t scsiBytesRead = 0;\r
+                               while (scsiBytesRead < readAheadBytes)\r
+                               {\r
+                                       while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))\r
+                                       {\r
+                                               __WFE(); // Wait for event\r
+                                       }\r
+                                       parityError |= scsiParityError();\r
+                                       scsiPhyFifoFlip();\r
+                                       uint32_t nextChunk = ((totalBytes - scsiBytesRead - chunk) > SCSI_FIFO_DEPTH)\r
+                                               ? SCSI_FIFO_DEPTH : (totalBytes - scsiBytesRead - chunk);\r
+\r
+                                       if (nextChunk > 0) scsiSetDataCount(nextChunk);\r
+                                       scsiReadPIO(&scsiDev.data[scsiBytesRead], chunk);\r
+                                       scsiBytesRead += chunk;\r
+                                       chunk = nextChunk;\r
+                               }\r
 \r
-#if 0\r
-                       // Wait for the next DMA interrupt. It's beneficial to halt the\r
-                       // processor to give the DMA controller more memory bandwidth to\r
-                       // work with.\r
-                       int scsiBusy = 1;\r
-                       int sdBusy = 1;\r
-                       while (scsiBusy && sdBusy)\r
-                       {\r
-                               uint8_t intr = CyEnterCriticalSection();\r
-                               scsiBusy = scsiDMABusy();\r
-                               sdBusy = sdDMABusy();\r
-                               if (scsiBusy && sdBusy)\r
+                               HAL_SD_WriteBlocks_DMA(&hsd, (uint32_t*) (&scsiDev.data[0]), (i + sdLBA) * 512ll, SD_SECTOR_SIZE, sectors);\r
+\r
+                               while (scsiBytesRead < totalBytes)\r
                                {\r
-                                       __WFI();\r
+                                       while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))\r
+                                       {\r
+                                               __WFE(); // Wait for event\r
+                                       }\r
+                                       parityError |= scsiParityError();\r
+                                       scsiPhyFifoFlip();\r
+                                       uint32_t nextChunk = ((totalBytes - scsiBytesRead - chunk) > SCSI_FIFO_DEPTH)\r
+                                               ? SCSI_FIFO_DEPTH : (totalBytes - scsiBytesRead - chunk);\r
+\r
+                                       if (nextChunk > 0) scsiSetDataCount(nextChunk);\r
+                                       scsiReadPIO(&scsiDev.data[scsiBytesRead], chunk);\r
+                                       scsiBytesRead += chunk;\r
+                                       chunk = nextChunk;\r
                                }\r
-                               CyExitCriticalSection(intr);\r
-                       }\r
 \r
-                       if (sdActive && !sdBusy && sdWriteSectorDMAPoll())\r
-                       {\r
-                               sdActive = 0;\r
-                               i++;\r
-                       }\r
-                       if (!sdActive && ((prep - i) > 0))\r
-                       {\r
-                               // Start an SD transfer if we have space.\r
-                               sdWriteMultiSectorDMA(&scsiDev.data[SD_SECTOR_SIZE * (i % buffers)]);\r
-                               sdActive = 1;\r
-                       }\r
+                               // Oh dear, SD finished first.\r
+                               int underrun = totalBytes > readAheadBytes && hsd.DmaTransferCplt;\r
 \r
-                       uint32_t now = getTime_ms();\r
+                               uint32_t dmaFinishTime = s2s_getTime_ms();\r
+                               while (!hsd.SdTransferCplt &&\r
+                                       s2s_elapsedTime_ms(dmaFinishTime) < 180)\r
+                               {\r
+                                       // Wait while keeping BSY.\r
+                               }\r
+                               while((__HAL_SD_SDIO_GET_FLAG(&hsd, SDIO_FLAG_TXACT)) &&\r
+                                       s2s_elapsedTime_ms(dmaFinishTime) < 180)\r
+                               {\r
+                                       // Wait for SD card while keeping BSY.\r
+                               }\r
 \r
-                       if (scsiActive && !scsiBusy && scsiReadDMAPoll())\r
-                       {\r
-                               scsiActive = 0;\r
-                               ++prep;\r
-                               lastActivityTime = now;\r
-                       }\r
-                       if (!scsiActive &&\r
-                               ((prep - i) < buffers) &&\r
-                               (prep < totalSDSectors) &&\r
-                               likely(!scsiDisconnected))\r
-                       {\r
-                               int dmaBytes = SD_SECTOR_SIZE;\r
-                               if ((prep % sdPerScsi) == (sdPerScsi - 1))\r
+                               if (i + sectors >= totalSDSectors &&\r
+                                       !underrun &&\r
+                                       (!parityError || !enableParity))\r
                                {\r
-                                       dmaBytes = bytesPerSector % SD_SECTOR_SIZE;\r
-                                       if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;\r
+                                       // We're transferring over the SCSI bus faster than the SD card\r
+                                       // can write.  All data is buffered, and we're just waiting for\r
+                                       // the SD card to complete. The host won't let us disconnect.\r
+                                       // Some drivers set a 250ms timeout on transfers to complete.\r
+                                       // SD card writes are supposed to complete\r
+                                       // within 200ms, but sometimes they don't.\r
+                                       // Just pretend we're finished.\r
+                                       process_Status();\r
+                                       clearBSY = process_MessageIn(0); // Will go to BUS_FREE state but keep BSY asserted.\r
                                }\r
-                               scsiReadDMA(&scsiDev.data[SD_SECTOR_SIZE * (prep % buffers)], dmaBytes);\r
-                               scsiActive = 1;\r
-                       }\r
-                       else if (\r
-                               (scsiDev.boardCfg.flags & CONFIG_ENABLE_DISCONNECT) &&\r
-                               (scsiActive == 0) &&\r
-                               likely(!scsiDisconnected) &&\r
-                               unlikely(scsiDev.discPriv) &&\r
-                               unlikely(diffTime_ms(lastActivityTime, now) >= 20) &&\r
-                               likely(scsiDev.phase == DATA_OUT))\r
-                       {\r
-                               // We're transferring over the SCSI bus faster than the SD card\r
-                               // can write.  There is no more buffer space once we've finished\r
-                               // this SCSI transfer.\r
-                               // The NCR 53C700 interface chips have a 250ms "byte-to-byte"\r
-                               // timeout buffer. SD card writes are supposed to complete\r
-                               // within 200ms, but sometimes they don't.\r
-                               // The NCR 53C700 series is used on HP 9000 workstations.\r
-                               scsiDisconnect();\r
-                               scsiDisconnected = 1;\r
-                               lastActivityTime = getTime_ms();\r
+\r
+                               HAL_SD_CheckWriteOperation(&hsd, (uint32_t)SD_DATATIMEOUT);\r
+\r
+                               if (underrun)\r
+                               {\r
+                                       // Try again. Data is still in memory.\r
+                                       sdTmpWrite(&scsiDev.data[0], i + sdLBA, sectors);\r
+                                       scsiDev.sdUnderrunCount++;\r
+                               }\r
+                               i += sectors;\r
+\r
                        }\r
-                       else if (unlikely(scsiDisconnected) &&\r
-                               (\r
-                                       (prep == i) || // Buffers empty.\r
-                                       // Send some messages every 100ms so we don't timeout.\r
-                                       // At a minimum, a reselection involves an IDENTIFY message.\r
-                                       unlikely(diffTime_ms(lastActivityTime, now) >= 100)\r
-                               ))\r
+                       else\r
                        {\r
-                               int reconnected = scsiReconnect();\r
-                               if (reconnected)\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
+                               // possible in each SD card transaction.\r
+                               // use sg_dd from sg_utils3 tools to test.\r
+                               uint32_t maxSectors = sizeof(scsiDev.data) / SD_SECTOR_SIZE;\r
+                               uint32_t rem = totalSDSectors - i;\r
+                               uint32_t sectors = rem < maxSectors ? rem : maxSectors;\r
+                               int scsiSector;\r
+                               for (scsiSector = i; scsiSector < i + sectors; ++scsiSector)\r
                                {\r
-                                       scsiDisconnected = 0;\r
-                                       lastActivityTime = getTime_ms(); // Don't disconnect immediately.\r
+                                       int dmaBytes = SD_SECTOR_SIZE;\r
+                                       if ((scsiSector % sdPerScsi) == (sdPerScsi - 1))\r
+                                       {\r
+                                               dmaBytes = bytesPerSector % SD_SECTOR_SIZE;\r
+                                               if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;\r
+                                       }\r
+                                       scsiRead(&scsiDev.data[SD_SECTOR_SIZE * (scsiSector - i)], dmaBytes, &parityError);\r
                                }\r
-                               else if (diffTime_ms(lastActivityTime, getTime_ms()) >= 10000)\r
+                               if (!parityError)\r
                                {\r
-                                       // Give up after 10 seconds of trying to reconnect.\r
-                                       scsiDev.resetFlag = 1;\r
+                                       sdTmpWrite(&scsiDev.data[0], i + sdLBA, sectors);\r
                                }\r
+                               i += sectors;\r
                        }\r
-                       else if (\r
-                               likely(!scsiComplete) &&\r
-                               (sdActive == 1) &&\r
-                               (prep == totalSDSectors) && // All scsi data read and buffered\r
-                               likely(!scsiDev.discPriv) && // Prefer disconnect where possible.\r
-                               unlikely(diffTime_ms(lastActivityTime, now) >= 150) &&\r
-\r
-                               likely(scsiDev.phase == DATA_OUT) &&\r
-                               !(scsiDev.cdb[scsiDev.cdbLen - 1] & 0x01) // Not linked command\r
-                               )\r
-                       {\r
-                               // We're transferring over the SCSI bus faster than the SD card\r
-                               // can write.  All data is buffered, and we're just waiting for\r
-                               // the SD card to complete. The host won't let us disconnect.\r
-                               // Some drivers set a 250ms timeout on transfers to complete.\r
-                               // SD card writes are supposed to complete\r
-                               // within 200ms, but sometimes they don'to.\r
-                               // Just pretend we're finished.\r
-                               scsiComplete = 1;\r
-\r
-                               process_Status();\r
-                               process_MessageIn(); // Will go to BUS_FREE state\r
-\r
-                               // Try and prevent anyone else using the SCSI bus while we're not ready.\r
-                               SCSI_SetPin(SCSI_Out_BSY); \r
-                       }\r
-#endif\r
                }\r
 \r
                if (clearBSY)\r
                {\r
-                       *SCSI_CTRL_BSY = 0;\r
-               }\r
-\r
-#if 0\r
-               if (scsiComplete)\r
-               {\r
-                       SCSI_ClearPin(SCSI_Out_BSY);\r
-               }\r
-               while (\r
-                       !scsiDev.resetFlag &&\r
-                       unlikely(scsiDisconnected) &&\r
-                       (s2s_elapsedTime_ms(lastActivityTime) <= 10000))\r
-               {\r
-                       scsiDisconnected = !scsiReconnect();\r
-               }\r
-               if (scsiDisconnected)\r
-               {\r
-                       // Failed to reconnect\r
-                       scsiDev.resetFlag = 1;\r
+                       enter_BusFree();\r
                }\r
-#endif\r
 \r
                if (scsiDev.phase == DATA_OUT)\r
                {\r
index 81af617..ce886e7 100755 (executable)
@@ -38,7 +38,6 @@ ScsiDevice scsiDev S2S_DMA_ALIGN;
 \r
 static void enter_SelectionPhase(void);\r
 static void process_SelectionPhase(void);\r
-static void enter_BusFree(void);\r
 static void enter_MessageIn(uint8_t message);\r
 static void enter_Status(uint8_t status);\r
 static void enter_DataIn(int len);\r
@@ -48,7 +47,7 @@ static void process_Command(void);
 \r
 static void doReserveRelease(void);\r
 \r
-static void enter_BusFree()\r
+void enter_BusFree()\r
 {\r
        // This delay probably isn't needed for most SCSI hosts, but it won't\r
        // hurt either. It's possible some of the samplers needed this delay.\r
@@ -84,7 +83,7 @@ static void enter_MessageIn(uint8_t message)
        scsiDev.phase = MESSAGE_IN;\r
 }\r
 \r
-void process_MessageIn()\r
+int process_MessageIn(int releaseBusFree)\r
 {\r
        scsiEnterPhase(MESSAGE_IN);\r
        scsiWriteByte(scsiDev.msgIn);\r
@@ -94,6 +93,7 @@ void process_MessageIn()
                // If there was a parity error, we go\r
                // back to MESSAGE_OUT first, get out parity error message, then come\r
                // back here.\r
+               return 0;\r
        }\r
        else if ((scsiDev.msgIn == MSG_LINKED_COMMAND_COMPLETE) ||\r
                (scsiDev.msgIn == MSG_LINKED_COMMAND_COMPLETE_WITH_FLAG))\r
@@ -106,10 +106,16 @@ void process_MessageIn()
                scsiDev.status = GOOD;\r
                transfer.blocks = 0;\r
                transfer.currentBlock = 0;\r
+               return 0;\r
        }\r
-       else /*if (scsiDev.msgIn == MSG_COMMAND_COMPLETE)*/\r
+       else if (releaseBusFree) /*if (scsiDev.msgIn == MSG_COMMAND_COMPLETE)*/\r
        {\r
                enter_BusFree();\r
+               return 1;\r
+       }\r
+       else\r
+       {\r
+               return 1;\r
        }\r
 }\r
 \r
@@ -517,6 +523,7 @@ static void scsiReset()
 \r
        scsiDev.postDataOutHook = NULL;\r
 \r
+       scsiDev.sdUnderrunCount = 0;\r
 \r
        // Sleep to allow the bus to settle down a bit.\r
        // We must be ready again within the "Reset to selection time" of\r
@@ -865,6 +872,7 @@ static void process_MessageOut()
                                uint8_t SDTR[] = {0x01, 0x03, 0x01, scsiDev.target->syncPeriod, scsiDev.target->syncOffset};\r
                                scsiWrite(SDTR, sizeof(SDTR));\r
                                scsiDev.needSyncNegotiationAck = 1; // Check if this message is rejected.\r
+                               scsiDev.sdUnderrunCount = 0;  // reset counter, may work now.\r
                        }\r
                }\r
                else\r
@@ -1004,7 +1012,7 @@ void scsiPoll(void)
                }\r
                else\r
                {\r
-                       process_MessageIn();\r
+                       process_MessageIn(1);\r
                }\r
 \r
        break;\r
index 5072456..5480a6a 100755 (executable)
@@ -162,12 +162,14 @@ typedef struct
        uint8_t minSyncPeriod; // Debug use only.
 
        int needSyncNegotiationAck;
+       int sdUnderrunCount;
 } ScsiDevice;
 
 extern ScsiDevice scsiDev;
 
 void process_Status(void);
-void process_MessageIn(void);
+int process_MessageIn(int releaseBusFree);
+void enter_BusFree(void);
 
 void scsiInit(void);
 void scsiPoll(void);
index b2bb258..739b21d 100755 (executable)
@@ -187,7 +187,7 @@ scsiReadByte(void)
 }\r
 \r
 \r
-static void\r
+void\r
 scsiReadPIO(uint8_t* data, uint32_t count)\r
 {\r
        uint16_t* fifoData = (uint16_t*)data;\r
@@ -598,6 +598,29 @@ void scsiEnterPhase(int newPhase)
        }\r
 }\r
 \r
+uint32_t s2s_getScsiRateMBs()\r
+{\r
+       if (scsiDev.target->syncOffset)\r
+       {\r
+               if (scsiDev.target->syncPeriod < 23)\r
+               {\r
+                       return 20;\r
+               }\r
+               else if (scsiDev.target->syncPeriod <= 25)\r
+               {\r
+                       return 10;\r
+               }\r
+               else\r
+               {\r
+                       return 1000 / (scsiDev.target->syncPeriod * 4);\r
+               }\r
+       }\r
+       else\r
+       {\r
+               return 0;\r
+       }\r
+}\r
+\r
 void scsiPhyReset()\r
 {\r
        trace(trace_scsiPhyReset);\r
index f8f5bdd..a99ed36 100755 (executable)
@@ -47,7 +47,7 @@
 #define SCSI_STS_PARITY_ERR ((volatile uint8_t*)0x6000002C)
 
 #define SCSI_FIFO_DATA ((volatile uint16_t*)0x60000040)
-#define SCSI_FIFO_DEPTH 512
+#define SCSI_FIFO_DEPTH 256
 
 
 #define scsiPhyFifoFull() ((*SCSI_STS_FIFO & 0x01) == 0x01)
@@ -109,9 +109,14 @@ extern volatile uint8_t scsiTxDMAComplete;
 void scsiReadDMA(uint8_t* data, uint32_t count);
 int scsiReadDMAPoll();
 
+// Low-level.
+void scsiReadPIO(uint8_t* data, uint32_t count);
+
 void scsiWriteDMA(const uint8_t* data, uint32_t count);
 int scsiWriteDMAPoll();
 
 int scsiSelfTest(void);
 
+uint32_t s2s_getScsiRateMBs();
+
 #endif
index b7ea9a7..30b7fd1 100755 (executable)
@@ -662,8 +662,24 @@ static int8_t SCSI_CheckAddressRange (USBD_HandleTypeDef  *pdev, uint8_t lun , u
 {
        USBD_CompositeClassData *classData = (USBD_CompositeClassData*) pdev->pClassData;
        USBD_MSC_BOT_HandleTypeDef *hmsc = &(classData->msc);
-  
-  if ((blk_offset + blk_nbr) > hmsc->scsi_blk_nbr )
+
+       // michael@codesrc.com: Re-check block limits in cause we have different values
+       // for different LUN's.
+    uint32_t blkNbr;
+       uint16_t blkSize;
+       if(((USBD_StorageTypeDef *)pdev->pUserData)->GetCapacity(lun, &blkNbr, &blkSize) != 0)
+       {
+    SCSI_SenseCode(pdev,
+                   lun,
+                   NOT_READY, 
+                   MEDIUM_NOT_PRESENT);
+    return -1;
+  } 
+       // global variables. wooo
+       hmsc->scsi_blk_size = blkSize;
+       hmsc->scsi_blk_nbr = blkNbr;
+
+  if ((blk_offset + blk_nbr) > blkNbr )
   {
     SCSI_SenseCode(pdev,
                    lun, 
index 3cb4487..263eb2b 100755 (executable)
@@ -205,6 +205,8 @@ int8_t s2s_usbd_storage_Write (uint8_t lun,
                        for (int i = 0; i < SDSectorsPerSCSISector(cfg->bytesPerSector); ++i)
                        {
                                uint8_t partial[512] S2S_DMA_ALIGN;
+                               memcpy(partial, buf, 512);
+
                                BSP_SD_WriteBlocks_DMA(
                                        (uint32_t*) partial,
                                        sdSectorNum * 512LL,
@@ -215,8 +217,6 @@ int8_t s2s_usbd_storage_Write (uint8_t lun,
                                int validBytes = cfg->bytesPerSector % SD_SECTOR_SIZE;
                                if (validBytes == 0) validBytes = SD_SECTOR_SIZE;
 
-                               memcpy(buf, partial, validBytes);
-
                                buf += validBytes;
                        }