Quellcode durchsuchen

Merge pull request #521 from ZuluSCSI/dev_initiator_recover_target_bsy

Initiator: recover from target holding BSY after command complete
Alex Perez vor 8 Monaten
Ursprung
Commit
dec20e2783

+ 51 - 0
lib/ZuluSCSI_platform_RP2MCU/scsiHostPhy.cpp

@@ -307,6 +307,57 @@ uint32_t scsiHostRead(uint8_t *data, uint32_t count)
     }
 }
 
+// Release bus signals and expect the target to do the same.
+// Cycles ACK in case target still holds BSY and REQ.
+void scsiHostWaitBusFree()
+{
+    SCSI_RELEASE_OUTPUTS();
+
+    sleep_us(2);
+
+    // Wait for the target to release BSY signal.
+    // If the target is expecting more data, transfer dummy bytes.
+    // This happens for some reason with READ6 command on IBM H3171-S2.
+    uint32_t start = millis();
+    int extra_bytes = 0;
+    while (SCSI_IN(BSY))
+    {
+        platform_poll();
+
+        if (SCSI_IN(REQ))
+        {
+            // Target is expecting something more
+            // Transfer dummy bytes
+             SCSI_OUT(BSY, 1);
+             sleep_us(1);
+
+             while (SCSI_IN(REQ))
+             {
+                scsiHostReadOneByte(nullptr);
+                extra_bytes++;
+                sleep_us(1);
+             }
+
+             SCSI_OUT(BSY, 0);
+             sleep_us(1);
+        }
+
+        if ((uint32_t)(millis() - start) > 10000)
+        {
+            logmsg("Target is holding BSY for unexpectedly long, running reset.");
+            scsiHostPhyReset();
+            break;
+        }
+    }
+
+    if (extra_bytes > 0)
+    {
+        dbgmsg("---- Target requested ", extra_bytes, " extra bytes after command complete");
+    }
+
+    scsiHostPhyRelease();
+}
+
 // Release all bus signals
 void scsiHostPhyRelease()
 {

+ 4 - 0
lib/ZuluSCSI_platform_RP2MCU/scsiHostPhy.h

@@ -51,5 +51,9 @@ bool scsiHostRequestWaiting();
 uint32_t scsiHostWrite(const uint8_t *data, uint32_t count);
 uint32_t scsiHostRead(uint8_t *data, uint32_t count);
 
+// Release bus signals and expect the target to do the same.
+// Cycles ACK in case target still holds BSY and REQ.
+void scsiHostWaitBusFree();
+
 // Release all bus signals
 void scsiHostPhyRelease();

+ 16 - 6
src/ZuluSCSI_initiator.cpp

@@ -613,8 +613,13 @@ int scsiInitiatorRunCommand(int target_id,
 
         if (phase == MESSAGE_IN)
         {
-            uint8_t dummy = 0;
-            scsiHostRead(&dummy, 1);
+            uint8_t msg = 0;
+            scsiHostRead(&msg, 1);
+
+            if (msg == MSG_COMMAND_COMPLETE)
+            {
+                break;
+            }
         }
         else if (phase == MESSAGE_OUT)
         {
@@ -672,7 +677,7 @@ int scsiInitiatorRunCommand(int target_id,
         }
     }
 
-    scsiHostPhyRelease();
+    scsiHostWaitBusFree();
 
     return status;
 }
@@ -1048,8 +1053,13 @@ bool scsiInitiatorReadDataToFile(int target_id, uint32_t start_sector, uint32_t
 
         if (phase == MESSAGE_IN)
         {
-            uint8_t dummy = 0;
-            scsiHostRead(&dummy, 1);
+            uint8_t msg = 0;
+            scsiHostRead(&msg, 1);
+
+            if (msg == MSG_COMMAND_COMPLETE)
+            {
+                break;
+            }
         }
         else if (phase == MESSAGE_OUT)
         {
@@ -1065,7 +1075,7 @@ bool scsiInitiatorReadDataToFile(int target_id, uint32_t start_sector, uint32_t
         }
     }
 
-    scsiHostPhyRelease();
+    scsiHostWaitBusFree();
 
     if (!g_initiator_transfer.all_ok)
     {