Use DMA for SCSI and SD card transfers for a massive performance boost.
[SCSI2SD-V6.git] / software / SCSI2SD / src / disk.c
index 6ae4d857746ecb58415f6f727342f227775417f6..3974ccff07ef324d96ca91a436c2ec1d14e54024 100755 (executable)
@@ -66,7 +66,7 @@ static void doFormatUnitPatternHeader(void)
        int defectLength =\r
                ((((uint16_t)scsiDev.data[2])) << 8) +\r
                        scsiDev.data[3];\r
-                       \r
+\r
        int patternLength =\r
                ((((uint16_t)scsiDev.data[4 + 2])) << 8) +\r
                scsiDev.data[4 + 3];\r
@@ -181,7 +181,7 @@ static void doWrite(uint32 lba, uint32 blocks)
                transfer.multiBlock = 1;\r
                \r
                if (blocks > 1) scsiDev.needReconnect = 1;\r
-               sdPrepareWrite();\r
+               sdWriteMultiSectorPrep();\r
        }\r
 }\r
 \r
@@ -217,7 +217,7 @@ static void doRead(uint32 lba, uint32 blocks)
                {\r
                        transfer.multiBlock = 1;\r
                        scsiDev.needReconnect = 1;\r
-                       sdPrepareRead();\r
+                       sdReadMultiSectorPrep();\r
                }\r
        }\r
 }\r
@@ -463,43 +463,106 @@ void scsiDiskPoll()
        if (scsiDev.phase == DATA_IN &&\r
                transfer.currentBlock != transfer.blocks)\r
        {\r
-               if (scsiDev.dataLen == 0)\r
+               int totalSDSectors = transfer.blocks * SDSectorsPerSCSISector();\r
+               uint32_t sdLBA = SCSISector2SD(transfer.lba);\r
+               int buffers = sizeof(scsiDev.data) / SD_SECTOR_SIZE;\r
+               int prep = 0;\r
+               int i = 0;\r
+               int scsiActive = 0;\r
+               int sdActive = 0;\r
+               while ((i < totalSDSectors) &&\r
+                       (scsiDev.phase == DATA_IN) &&\r
+                       !scsiDev.resetFlag)\r
                {\r
-                       if (transfer.multiBlock)\r
+                       if ((sdActive == 1) && sdReadSectorDMAPoll())\r
                        {\r
-                               sdReadSectorMulti();\r
+                               sdActive = 0;\r
+                               prep++;\r
                        }\r
-                       else\r
+                       else if ((sdActive == 0) && (prep - i < buffers) && (prep < totalSDSectors))\r
                        {\r
-                               sdReadSectorSingle();\r
+                               // Start an SD transfer if we have space.\r
+                               if (transfer.multiBlock)\r
+                               {\r
+                                       sdReadMultiSectorDMA(&scsiDev.data[SD_SECTOR_SIZE * (prep % buffers)]);\r
+                               }\r
+                               else\r
+                               {\r
+                                       sdReadSingleSectorDMA(sdLBA + prep, &scsiDev.data[SD_SECTOR_SIZE * (prep % buffers)]);\r
+                               }\r
+                               sdActive = 1;\r
                        }\r
-               }\r
-               else if (scsiDev.dataPtr == scsiDev.dataLen)\r
-               {\r
-                       scsiDev.dataLen = 0;\r
-                       scsiDev.dataPtr = 0;\r
-                       transfer.currentBlock++;\r
-                       if (transfer.currentBlock >= transfer.blocks)\r
+\r
+                       if ((scsiActive == 1) && scsiWriteDMAPoll())\r
                        {\r
-                               scsiDev.phase = STATUS;\r
-                               scsiDiskReset();\r
+                               scsiActive = 0;\r
+                               ++i;\r
+                       }\r
+                       else if ((scsiActive == 0) && ((prep - i) > 0))\r
+                       {\r
+                               int dmaBytes = SD_SECTOR_SIZE;\r
+                               if (i % SDSectorsPerSCSISector() == SDSectorsPerSCSISector() - 1)\r
+                               {\r
+                                       dmaBytes = config->bytesPerSector % SD_SECTOR_SIZE;\r
+                                       if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;\r
+                               }\r
+                               scsiWriteDMA(&scsiDev.data[SD_SECTOR_SIZE * (i % buffers)], dmaBytes);\r
+                               scsiActive = 1;\r
                        }\r
                }\r
+               if (scsiDev.phase == DATA_IN)\r
+               {\r
+                       scsiDev.phase = STATUS;\r
+               }\r
+               scsiDiskReset();\r
        }\r
        else if (scsiDev.phase == DATA_OUT &&\r
                transfer.currentBlock != transfer.blocks)\r
        {\r
-               sdWriteSector();\r
-               // TODO FIX scsiDiskPoll() scsiDev.dataPtr = 0;\r
-               transfer.currentBlock++;\r
-               if (transfer.currentBlock >= transfer.blocks)\r
+               int totalSDSectors = transfer.blocks * SDSectorsPerSCSISector();\r
+               int buffers = sizeof(scsiDev.data) / SD_SECTOR_SIZE;\r
+               int prep = 0;\r
+               int i = 0;\r
+               int scsiActive = 0;\r
+               int sdActive = 0;\r
+               while ((i < totalSDSectors) &&\r
+                       (scsiDev.phase == DATA_OUT) &&\r
+                       !scsiDev.resetFlag)\r
                {\r
-                       scsiDev.dataLen = 0;\r
-                       scsiDev.dataPtr = 0;\r
-                       scsiDev.phase = STATUS;\r
+                       if ((sdActive == 1) && sdWriteSectorDMAPoll())\r
+                       {\r
+                               sdActive = 0;\r
+                               i++;\r
+                       }\r
+                       else if ((sdActive == 0) && ((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
 \r
-                       scsiDiskReset();\r
+                       if ((scsiActive == 1) && scsiReadDMAPoll())\r
+                       {\r
+                               scsiActive = 0;\r
+                               ++prep;\r
+                       }\r
+                       else if ((scsiActive == 0) && ((prep - i) < buffers) && (prep < totalSDSectors))\r
+                       {\r
+                               int dmaBytes = SD_SECTOR_SIZE;\r
+                               if (prep % SDSectorsPerSCSISector() == SDSectorsPerSCSISector() - 1)\r
+                               {\r
+                                       dmaBytes = config->bytesPerSector % SD_SECTOR_SIZE;\r
+                                       if (dmaBytes == 0) dmaBytes = SD_SECTOR_SIZE;\r
+                               }\r
+                               scsiReadDMA(&scsiDev.data[SD_SECTOR_SIZE * (prep % buffers)], dmaBytes);\r
+                               scsiActive = 1;\r
+                       }\r
+               }\r
+               if (scsiDev.phase == DATA_OUT)\r
+               {\r
+                       scsiDev.phase = STATUS;\r
                }\r
+               scsiDiskReset();\r
        }\r
 }\r
 \r