|
@@ -548,6 +548,29 @@ int scsiDiskCommand()
|
|
|
return commandHandled;
|
|
return commandHandled;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+static uint32_t
|
|
|
|
|
+calcReadahead(uint32_t totalBytes, uint32_t sdSpeedKBs, uint32_t scsiSpeedKBs)
|
|
|
|
|
+{
|
|
|
|
|
+ if (scsiSpeedKBs == 0 || scsiDev.hostSpeedMeasured == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ return totalBytes;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // uint32_t readAheadBytes = totalBytes * (1 - scsiSpeedKBs / sdSpeedKBs);
|
|
|
|
|
+ // Won't overflow with 65536 max bytes, 20000 max scsi speed.
|
|
|
|
|
+ uint32_t readAheadBytes = totalBytes - totalBytes * scsiSpeedKBs / sdSpeedKBs;
|
|
|
|
|
+
|
|
|
|
|
+ // Round up to nearest FIFO size (* 4 for safety)
|
|
|
|
|
+ readAheadBytes = ((readAheadBytes / SCSI_FIFO_DEPTH) + 4) * SCSI_FIFO_DEPTH;
|
|
|
|
|
+
|
|
|
|
|
+ if (readAheadBytes > totalBytes)
|
|
|
|
|
+ {
|
|
|
|
|
+ readAheadBytes = totalBytes;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return readAheadBytes;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
void scsiDiskPoll()
|
|
void scsiDiskPoll()
|
|
|
{
|
|
{
|
|
|
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
|
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
|
|
@@ -704,18 +727,16 @@ void scsiDiskPoll()
|
|
|
transfer.lba);
|
|
transfer.lba);
|
|
|
int i = 0;
|
|
int i = 0;
|
|
|
int clearBSY = 0;
|
|
int clearBSY = 0;
|
|
|
- int extraSectors = 0;
|
|
|
|
|
|
|
|
|
|
int parityError = 0;
|
|
int parityError = 0;
|
|
|
int enableParity = scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY;
|
|
int enableParity = scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY;
|
|
|
|
|
|
|
|
- uint32_t scsiSpeed = s2s_getScsiRateMBs();
|
|
|
|
|
-
|
|
|
|
|
uint32_t maxSectors = sizeof(scsiDev.data) / SD_SECTOR_SIZE;
|
|
uint32_t maxSectors = sizeof(scsiDev.data) / SD_SECTOR_SIZE;
|
|
|
|
|
|
|
|
static_assert(SCSI_XFER_MAX >= sizeof(scsiDev.data), "Assumes SCSI_XFER_MAX >= sizeof(scsiDev.data)");
|
|
static_assert(SCSI_XFER_MAX >= sizeof(scsiDev.data), "Assumes SCSI_XFER_MAX >= sizeof(scsiDev.data)");
|
|
|
|
|
|
|
|
// Start reading and filling fifos as soon as possible.
|
|
// Start reading and filling fifos as soon as possible.
|
|
|
|
|
+ DWT->CYCCNT = 0; // Start counting cycles
|
|
|
scsiSetDataCount(transfer.blocks * bytesPerSector);
|
|
scsiSetDataCount(transfer.blocks * bytesPerSector);
|
|
|
|
|
|
|
|
while ((i < totalSDSectors) &&
|
|
while ((i < totalSDSectors) &&
|
|
@@ -733,31 +754,15 @@ void scsiDiskPoll()
|
|
|
// no flow control. This can be handled if a) the scsi interface
|
|
// no flow control. This can be handled if a) the scsi interface
|
|
|
// doesn't block and b) we read enough SCSI sectors first so that
|
|
// doesn't block and b) we read enough SCSI sectors first so that
|
|
|
// the SD interface cannot catch up.
|
|
// the SD interface cannot catch up.
|
|
|
- int prevExtraSectors = extraSectors;
|
|
|
|
|
uint32_t totalBytes = sectors * SD_SECTOR_SIZE;
|
|
uint32_t totalBytes = sectors * SD_SECTOR_SIZE;
|
|
|
- extraSectors = 0;
|
|
|
|
|
|
|
|
|
|
- int32_t readAheadBytes = totalBytes;
|
|
|
|
|
- uint32_t sdSpeed = s2s_getSdRateMBs() + (scsiDev.sdUnderrunCount / 2);
|
|
|
|
|
- // if (have blind writes)
|
|
|
|
|
- if (scsiSpeed > 0 && scsiDev.sdUnderrunCount < 16)
|
|
|
|
|
- {
|
|
|
|
|
- // readAhead = sectors * (sd / scsi - 1 + 0.1);
|
|
|
|
|
- readAheadBytes = totalBytes * sdSpeed / scsiSpeed - totalBytes;
|
|
|
|
|
-
|
|
|
|
|
- // Round up to nearest FIFO size.
|
|
|
|
|
- readAheadBytes = ((readAheadBytes / SCSI_FIFO_DEPTH) + 1) * SCSI_FIFO_DEPTH;
|
|
|
|
|
-
|
|
|
|
|
- if (readAheadBytes > totalBytes)
|
|
|
|
|
- {
|
|
|
|
|
- readAheadBytes = totalBytes;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- uint32_t prevExtraBytes = prevExtraSectors * SD_SECTOR_SIZE;
|
|
|
|
|
- uint32_t scsiBytesRead = prevExtraBytes;
|
|
|
|
|
- readAheadBytes -= prevExtraBytes; // Must be signed!
|
|
|
|
|
|
|
+ uint32_t sdSpeedKBs = s2s_getSdRateKBs() + (scsiDev.sdUnderrunCount * 256);
|
|
|
|
|
+ uint32_t readAheadBytes = calcReadahead(
|
|
|
|
|
+ totalBytes,
|
|
|
|
|
+ sdSpeedKBs,
|
|
|
|
|
+ scsiDev.hostSpeedKBs);
|
|
|
|
|
|
|
|
|
|
+ uint32_t scsiBytesRead = 0;
|
|
|
if (readAheadBytes > 0)
|
|
if (readAheadBytes > 0)
|
|
|
{
|
|
{
|
|
|
scsiReadPIO(
|
|
scsiReadPIO(
|
|
@@ -765,6 +770,42 @@ void scsiDiskPoll()
|
|
|
readAheadBytes,
|
|
readAheadBytes,
|
|
|
&parityError);
|
|
&parityError);
|
|
|
scsiBytesRead += readAheadBytes;
|
|
scsiBytesRead += readAheadBytes;
|
|
|
|
|
+
|
|
|
|
|
+ if (i == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ uint32_t elapsedCycles = DWT->CYCCNT;
|
|
|
|
|
+
|
|
|
|
|
+ // uint32_t rateKBs = (readAheadBytes / 1000) / (elapsedCycles / HAL_RCC_GetHCLKFreq());
|
|
|
|
|
+ // Scaled by 4 to avoid overflow w/ max 65536 at 108MHz.
|
|
|
|
|
+ uint32_t rateKBs = ((readAheadBytes / 4) * (HAL_RCC_GetHCLKFreq() / 1000) / elapsedCycles) * 4;
|
|
|
|
|
+
|
|
|
|
|
+ scsiDev.hostSpeedKBs = (scsiDev.hostSpeedKBs + rateKBs) / 2;
|
|
|
|
|
+ scsiDev.hostSpeedMeasured = 1;
|
|
|
|
|
+
|
|
|
|
|
+ if (rateKBs < scsiDev.hostSpeedKBs)
|
|
|
|
|
+ {
|
|
|
|
|
+ // Our readahead was too slow; assume remaining bytes
|
|
|
|
|
+ // will be as well.
|
|
|
|
|
+ if (readAheadBytes < totalBytes)
|
|
|
|
|
+ {
|
|
|
|
|
+ uint32_t properReadahead = calcReadahead(
|
|
|
|
|
+ totalBytes,
|
|
|
|
|
+ sdSpeedKBs,
|
|
|
|
|
+ rateKBs);
|
|
|
|
|
+
|
|
|
|
|
+ if (properReadahead > readAheadBytes)
|
|
|
|
|
+ {
|
|
|
|
|
+ uint32_t diff = properReadahead - readAheadBytes;
|
|
|
|
|
+ readAheadBytes = properReadahead;
|
|
|
|
|
+ scsiReadPIO(
|
|
|
|
|
+ &scsiDev.data[scsiBytesRead],
|
|
|
|
|
+ diff,
|
|
|
|
|
+ &parityError);
|
|
|
|
|
+ scsiBytesRead += diff;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
HAL_SD_WriteBlocks_DMA(&hsd, (uint32_t*) (&scsiDev.data[0]), (i + sdLBA) * 512ll, SD_SECTOR_SIZE, sectors);
|
|
HAL_SD_WriteBlocks_DMA(&hsd, (uint32_t*) (&scsiDev.data[0]), (i + sdLBA) * 512ll, SD_SECTOR_SIZE, sectors);
|
|
@@ -783,22 +824,6 @@ void scsiDiskPoll()
|
|
|
scsiBytesRead += (totalBytes - readAheadBytes);
|
|
scsiBytesRead += (totalBytes - readAheadBytes);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (!underrun && rem > sectors)
|
|
|
|
|
- {
|
|
|
|
|
- // We probably have some time to waste reading more here.
|
|
|
|
|
- // While noting this is going to drop us down into
|
|
|
|
|
- // half-duplex operation (hence why we read max / 4 only)
|
|
|
|
|
-
|
|
|
|
|
- extraSectors = rem - sectors > (maxSectors / 4)
|
|
|
|
|
- ? (maxSectors / 4)
|
|
|
|
|
- : rem - sectors;
|
|
|
|
|
-
|
|
|
|
|
- scsiReadPIO(
|
|
|
|
|
- &scsiDev.data[0],
|
|
|
|
|
- extraSectors * SD_SECTOR_SIZE,
|
|
|
|
|
- &parityError);
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
uint32_t dmaFinishTime = s2s_getTime_ms();
|
|
uint32_t dmaFinishTime = s2s_getTime_ms();
|
|
|
while ((!hsd.SdTransferCplt ||
|
|
while ((!hsd.SdTransferCplt ||
|
|
|
__HAL_SD_SDIO_GET_FLAG(&hsd, SDIO_FLAG_TXACT)) &&
|
|
__HAL_SD_SDIO_GET_FLAG(&hsd, SDIO_FLAG_TXACT)) &&
|