\r
#include <string.h>\r
\r
-static const uint16_t FIRMWARE_VERSION = 0x0629;\r
+static const uint16_t FIRMWARE_VERSION = 0x062A;\r
+\r
+// Optional static config\r
+extern uint8_t* __fixed_config;\r
\r
// 1 flash row\r
static const uint8_t DEFAULT_CONFIG[128] =\r
{\r
usbInEpState = USB_IDLE;\r
\r
- if ((blockDev.state & DISK_PRESENT) && sdDev.capacity)\r
+ if (memcmp(__fixed_config, "BCFG", 4) == 0)\r
+ {\r
+ // Use hardcoded config\r
+ memcpy(s2s_cfg, __fixed_config, S2S_CFG_SIZE);\r
+ memcpy(config, s2s_cfg, sizeof(S2S_BoardCfg));\r
+ }\r
+\r
+ else if ((blockDev.state & DISK_PRESENT) && sdDev.capacity)\r
{\r
int cfgSectors = (S2S_CFG_SIZE + 511) / 512;\r
BSP_SD_ReadBlocks_DMA(\r
return commandHandled;\r
}\r
\r
+static uint32_t\r
+calcReadahead(uint32_t totalBytes, uint32_t sdSpeedKBs, uint32_t scsiSpeedKBs)\r
+{\r
+ if (scsiSpeedKBs == 0 || scsiDev.hostSpeedMeasured == 0)\r
+ {\r
+ return totalBytes;\r
+ }\r
+\r
+ // uint32_t readAheadBytes = totalBytes * (1 - scsiSpeedKBs / sdSpeedKBs);\r
+ // Won't overflow with 65536 max bytes, 20000 max scsi speed.\r
+ uint32_t readAheadBytes = totalBytes - totalBytes * scsiSpeedKBs / sdSpeedKBs;\r
+\r
+ // Round up to nearest FIFO size (* 4 for safety)\r
+ readAheadBytes = ((readAheadBytes / SCSI_FIFO_DEPTH) + 4) * SCSI_FIFO_DEPTH;\r
+\r
+ if (readAheadBytes > totalBytes)\r
+ {\r
+ readAheadBytes = totalBytes;\r
+ }\r
+\r
+ return readAheadBytes;\r
+}\r
+\r
void scsiDiskPoll()\r
{\r
uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;\r
transfer.lba);\r
int i = 0;\r
int clearBSY = 0;\r
- int extraSectors = 0;\r
\r
int parityError = 0;\r
int enableParity = scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY;\r
\r
- uint32_t scsiSpeed = s2s_getScsiRateMBs();\r
-\r
uint32_t maxSectors = sizeof(scsiDev.data) / SD_SECTOR_SIZE;\r
\r
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
\r
while ((i < totalSDSectors) &&\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
- int prevExtraSectors = extraSectors;\r
uint32_t totalBytes = sectors * SD_SECTOR_SIZE;\r
- extraSectors = 0;\r
\r
- int32_t readAheadBytes = totalBytes;\r
- uint32_t sdSpeed = s2s_getSdRateMBs() + (scsiDev.sdUnderrunCount / 2);\r
- // if (have blind writes)\r
- if (scsiSpeed > 0 && scsiDev.sdUnderrunCount < 16)\r
- {\r
- // readAhead = sectors * (sd / scsi - 1 + 0.1);\r
- readAheadBytes = totalBytes * sdSpeed / scsiSpeed - totalBytes;\r
-\r
- // Round up to nearest FIFO size.\r
- readAheadBytes = ((readAheadBytes / SCSI_FIFO_DEPTH) + 1) * SCSI_FIFO_DEPTH;\r
-\r
- if (readAheadBytes > totalBytes)\r
- {\r
- readAheadBytes = totalBytes;\r
- }\r
- }\r
-\r
- uint32_t prevExtraBytes = prevExtraSectors * SD_SECTOR_SIZE;\r
- uint32_t scsiBytesRead = prevExtraBytes;\r
- readAheadBytes -= prevExtraBytes; // Must be signed!\r
+ uint32_t sdSpeedKBs = s2s_getSdRateKBs() + (scsiDev.sdUnderrunCount * 256);\r
+ uint32_t readAheadBytes = calcReadahead(\r
+ totalBytes,\r
+ sdSpeedKBs,\r
+ scsiDev.hostSpeedKBs);\r
\r
+ uint32_t scsiBytesRead = 0;\r
if (readAheadBytes > 0)\r
{\r
scsiReadPIO(\r
readAheadBytes,\r
&parityError);\r
scsiBytesRead += readAheadBytes;\r
+\r
+ if (i == 0)\r
+ {\r
+ uint32_t elapsedCycles = DWT->CYCCNT;\r
+\r
+ // uint32_t rateKBs = (readAheadBytes / 1000) / (elapsedCycles / HAL_RCC_GetHCLKFreq());\r
+ // Scaled by 4 to avoid overflow w/ max 65536 at 108MHz.\r
+ uint32_t rateKBs = ((readAheadBytes / 4) * (HAL_RCC_GetHCLKFreq() / 1000) / elapsedCycles) * 4;\r
+\r
+ scsiDev.hostSpeedKBs = (scsiDev.hostSpeedKBs + rateKBs) / 2;\r
+ scsiDev.hostSpeedMeasured = 1;\r
+\r
+ if (rateKBs < scsiDev.hostSpeedKBs)\r
+ {\r
+ // Our readahead was too slow; assume remaining bytes\r
+ // will be as well.\r
+ if (readAheadBytes < totalBytes)\r
+ {\r
+ uint32_t properReadahead = calcReadahead(\r
+ totalBytes,\r
+ sdSpeedKBs,\r
+ rateKBs);\r
+\r
+ if (properReadahead > readAheadBytes)\r
+ {\r
+ uint32_t diff = properReadahead - readAheadBytes;\r
+ readAheadBytes = properReadahead;\r
+ scsiReadPIO(\r
+ &scsiDev.data[scsiBytesRead],\r
+ diff,\r
+ &parityError);\r
+ scsiBytesRead += diff;\r
+ }\r
+ }\r
+ }\r
+ }\r
}\r
\r
HAL_SD_WriteBlocks_DMA(&hsd, (uint32_t*) (&scsiDev.data[0]), (i + sdLBA) * 512ll, SD_SECTOR_SIZE, sectors);\r
scsiBytesRead += (totalBytes - readAheadBytes);\r
}\r
\r
- if (!underrun && rem > sectors)\r
- {\r
- // We probably have some time to waste reading more here.\r
- // While noting this is going to drop us down into\r
- // half-duplex operation (hence why we read max / 4 only)\r
-\r
- extraSectors = rem - sectors > (maxSectors / 4)\r
- ? (maxSectors / 4)\r
- : rem - sectors;\r
-\r
- scsiReadPIO(\r
- &scsiDev.data[0],\r
- extraSectors * SD_SECTOR_SIZE,\r
- &parityError);\r
- }\r
-\r
uint32_t dmaFinishTime = s2s_getTime_ms();\r
while ((!hsd.SdTransferCplt ||\r
__HAL_SD_SDIO_GET_FLAG(&hsd, SDIO_FLAG_TXACT)) &&\r