瀏覽代碼

Merge pull request #84 from ZuluSCSI/akai_s1000_read_delay

Akai S1000 read delay
Alex Perez 3 年之前
父節點
當前提交
1bb1782db8

+ 20 - 10
lib/ZuluSCSI_platform_GD32F205/gd32_sdio_sdcard.c

@@ -1997,18 +1997,20 @@ static sd_error_enum r1_error_check(uint8_t cmdindex)
 {
     sd_error_enum status = SD_OK;
     uint32_t reg_status = 0, resp_r1 = 0;
+    __IO uint32_t timeout = 100000;
 
     /* store the content of SDIO_STAT */
     reg_status = SDIO_STAT;
-    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV))) {
+    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV)) && (timeout > 0)) {
         reg_status = SDIO_STAT;
+        --timeout;
     }
     /* check whether an error or timeout occurs or command response received */
     if(reg_status & SDIO_FLAG_CCRCERR) {
         status = SD_CMD_CRC_ERROR;
         sdio_flag_clear(SDIO_FLAG_CCRCERR);
         return status;
-    } else if(reg_status & SDIO_FLAG_CMDTMOUT) {
+    } else if((reg_status & SDIO_FLAG_CMDTMOUT) || (0 == timeout)) {
         status = SD_CMD_RESP_TIMEOUT;
         sdio_flag_clear(SDIO_FLAG_CMDTMOUT);
         return status;
@@ -2044,18 +2046,20 @@ static sd_error_enum r2_error_check(void)
 {
     sd_error_enum status = SD_OK;
     uint32_t reg_status = 0;
+    __IO uint32_t timeout = 100000;
 
     /* store the content of SDIO_STAT */
     reg_status = SDIO_STAT;
-    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV))) {
+    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV)) && (timeout > 0)) {
         reg_status = SDIO_STAT;
+        --timeout;
     }
     /* check whether an error or timeout occurs or command response received */
     if(reg_status & SDIO_FLAG_CCRCERR) {
         status = SD_CMD_CRC_ERROR;
         sdio_flag_clear(SDIO_FLAG_CCRCERR);
         return status;
-    } else if(reg_status & SDIO_FLAG_CMDTMOUT) {
+    } else if((reg_status & SDIO_FLAG_CMDTMOUT) || (0 == timeout)) {
         status = SD_CMD_RESP_TIMEOUT;
         sdio_flag_clear(SDIO_FLAG_CMDTMOUT);
         return status;
@@ -2075,13 +2079,15 @@ static sd_error_enum r3_error_check(void)
 {
     sd_error_enum status = SD_OK;
     uint32_t reg_status = 0;
+    __IO uint32_t timeout = 100000;
 
     /* store the content of SDIO_STAT */
     reg_status = SDIO_STAT;
-    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV))) {
+    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV)) && (timeout > 0)) {
         reg_status = SDIO_STAT;
+        --timeout;
     }
-    if(reg_status & SDIO_FLAG_CMDTMOUT) {
+    if((reg_status & SDIO_FLAG_CMDTMOUT) || (0 == timeout)) {
         status = SD_CMD_RESP_TIMEOUT;
         sdio_flag_clear(SDIO_FLAG_CMDTMOUT);
         return status;
@@ -2101,18 +2107,20 @@ static sd_error_enum r6_error_check(uint8_t cmdindex, uint16_t *prca)
 {
     sd_error_enum status = SD_OK;
     uint32_t reg_status = 0, response = 0;
+    __IO uint32_t timeout = 100000;
 
     /* store the content of SDIO_STAT */
     reg_status = SDIO_STAT;
-    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV))) {
+    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV)) && (timeout > 0)) {
         reg_status = SDIO_STAT;
+        --timeout;
     }
     /* check whether an error or timeout occurs or command response received */
     if(reg_status & SDIO_FLAG_CCRCERR) {
         status = SD_CMD_CRC_ERROR;
         sdio_flag_clear(SDIO_FLAG_CCRCERR);
         return status;
-    } else if(reg_status & SDIO_FLAG_CMDTMOUT) {
+    } else if((reg_status & SDIO_FLAG_CMDTMOUT) || (0 == timeout)) {
         status = SD_CMD_RESP_TIMEOUT;
         sdio_flag_clear(SDIO_FLAG_CMDTMOUT);
         return status;
@@ -2196,6 +2204,7 @@ static sd_error_enum sd_card_state_get(uint8_t *pcardstate)
 {
     sd_error_enum status = SD_OK;
     __IO uint32_t reg_status = 0, response = 0;
+    __IO uint32_t timeout = 100000;
 
     /* send CMD13(SEND_STATUS), addressed card sends its status register */
     sdio_csm_disable();
@@ -2205,15 +2214,16 @@ static sd_error_enum sd_card_state_get(uint8_t *pcardstate)
 
     /* store the content of SDIO_STAT */
     reg_status = SDIO_STAT;
-    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV))) {
+    while(!(reg_status & (SDIO_FLAG_CCRCERR | SDIO_FLAG_CMDTMOUT | SDIO_FLAG_CMDRECV)) && (timeout > 0)) {
         reg_status = SDIO_STAT;
+        --timeout;
     }
     /* check whether an error or timeout occurs or command response received */
     if(reg_status & SDIO_FLAG_CCRCERR) {
         status = SD_CMD_CRC_ERROR;
         sdio_flag_clear(SDIO_FLAG_CCRCERR);
         return status;
-    } else if(reg_status & SDIO_FLAG_CMDTMOUT) {
+    } else if((reg_status & SDIO_FLAG_CMDTMOUT) || (0 == timeout)) {
         status = SD_CMD_RESP_TIMEOUT;
         sdio_flag_clear(SDIO_FLAG_CMDTMOUT);
         return status;

+ 12 - 4
lib/ZuluSCSI_platform_GD32F205/scsiPhy.cpp

@@ -212,12 +212,20 @@ extern "C" void scsiEnterPhase(int phase)
 // Change state and return nanosecond delay to wait
 extern "C" uint32_t scsiEnterPhaseImmediate(int phase)
 {
-    // ANSI INCITS 362-2002 SPI-3 10.7.1:
-    // Phase changes are not allowed while REQ or ACK is asserted.
-    while (likely(!scsiDev.resetFlag) && SCSI_IN(ACK)) {}
-
     if (phase != g_scsi_phase)
     {
+        // ANSI INCITS 362-2002 SPI-3 10.7.1:
+        // Phase changes are not allowed while REQ or ACK is asserted.
+        while (likely(!scsiDev.resetFlag) && SCSI_IN(ACK)) {}
+
+        if (scsiDev.compatMode < COMPAT_SCSI2 && (phase == DATA_IN || phase == DATA_OUT))
+        {
+            // Akai S1000/S3000 seems to need extra delay before changing to data phase
+            // after a command. The code in ZuluSCSI_disk.cpp tries to do this while waiting
+            // for SD card, to avoid any extra latency.
+            s2s_delay_ns(400000);
+        }
+
         int oldphase = g_scsi_phase;
         g_scsi_phase = (SCSI_PHASE)phase;
         scsiLogPhaseChange(phase);

+ 12 - 4
lib/ZuluSCSI_platform_RP2040/scsiPhy.cpp

@@ -168,12 +168,20 @@ extern "C" void scsiEnterPhase(int phase)
 // Change state and return nanosecond delay to wait
 extern "C" uint32_t scsiEnterPhaseImmediate(int phase)
 {
-    // ANSI INCITS 362-2002 SPI-3 10.7.1:
-    // Phase changes are not allowed while REQ or ACK is asserted.
-    while (likely(!scsiDev.resetFlag) && SCSI_IN(ACK)) {}
-
     if (phase != g_scsi_phase)
     {
+        // ANSI INCITS 362-2002 SPI-3 10.7.1:
+        // Phase changes are not allowed while REQ or ACK is asserted.
+        while (likely(!scsiDev.resetFlag) && SCSI_IN(ACK)) {}
+
+        if (scsiDev.compatMode < COMPAT_SCSI2 && (phase == DATA_IN || phase == DATA_OUT))
+        {
+            // Akai S1000/S3000 seems to need extra delay before changing to data phase
+            // after a command. The code in ZuluSCSI_disk.cpp tries to do this while waiting
+            // for SD card, to avoid any extra latency.
+            s2s_delay_ns(400000);
+        }
+
         int oldphase = g_scsi_phase;
         g_scsi_phase = (SCSI_PHASE)phase;
         scsiLogPhaseChange(phase);

+ 12 - 4
lib/ZuluSCSI_platform_template/scsiPhy.cpp

@@ -133,12 +133,20 @@ extern "C" void scsiEnterPhase(int phase)
 // Change state and return nanosecond delay to wait
 extern "C" uint32_t scsiEnterPhaseImmediate(int phase)
 {
-    // ANSI INCITS 362-2002 SPI-3 10.7.1:
-    // Phase changes are not allowed while REQ or ACK is asserted.
-    while (likely(!scsiDev.resetFlag) && SCSI_IN(ACK)) {}
-
     if (phase != g_scsi_phase)
     {
+        // ANSI INCITS 362-2002 SPI-3 10.7.1:
+        // Phase changes are not allowed while REQ or ACK is asserted.
+        while (likely(!scsiDev.resetFlag) && SCSI_IN(ACK)) {}
+
+        if (scsiDev.compatMode < COMPAT_SCSI2 && (phase == DATA_IN || phase == DATA_OUT))
+        {
+            // Akai S1000/S3000 seems to need extra delay before changing to data phase
+            // after a command. The code in ZuluSCSI_disk.cpp tries to do this while waiting
+            // for SD card, to avoid any extra latency.
+            s2s_delay_ns(400000);
+        }
+
         int oldphase = g_scsi_phase;
         g_scsi_phase = (SCSI_PHASE)phase;
         scsiLogPhaseChange(phase);

+ 4 - 2
src/ZuluSCSI_disk.cpp

@@ -1266,6 +1266,10 @@ static void doRead(uint32_t lba, uint32_t blocks)
 
 void diskDataIn_callback(uint32_t bytes_complete)
 {
+    // On SCSI-1 devices the phase change has some extra delays.
+    // Doing it here lets the SD card transfer proceed in background.
+    scsiEnterPhase(DATA_IN);
+
     // For best performance, do writes in blocks of 4 or more bytes
     if (bytes_complete < g_disk_transfer.bytes_sd)
     {
@@ -1335,8 +1339,6 @@ static void start_dataInTransfer(uint8_t *buffer, uint32_t count)
 
 static void diskDataIn()
 {
-    scsiEnterPhase(DATA_IN);
-
     // Figure out how many blocks we can fit in buffer
     uint32_t bytesPerSector = scsiDev.target->liveCfg.bytesPerSector;
     uint32_t maxblocks = sizeof(scsiDev.data) / bytesPerSector;