瀏覽代碼

Fixup initiator

Eric Helgeson 4 月之前
父節點
當前提交
ecee70befc

+ 20 - 32
lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform.cpp

@@ -454,22 +454,7 @@ void platform_init()
 }
 void platform_enable_initiator_mode()
 {
-    if (ini_getbool("SCSI", "InitiatorMode", false, CONFIGFILE))
-    {
-        logmsg("InitiatorMode true");
-
-        if (g_supports_initiator) {
-            g_scsi_initiator = true;
-            logmsg("SCSI Initiator Mode");
-            if (! ini_getbool("SCSI", "InitiatorParity", true, CONFIGFILE))
-            {
-                logmsg("Initiator Mode Skipping Parity Check.");
-                // setInitiatorModeParityCheck(false);
-            }
-        } else {
-            logmsg("SCSI Initiator Mode not supported.");
-        }
-    }
+    g_scsi_initiator = true;
 }
 
 // late_init() only runs in main application, SCSI not needed in bootloader
@@ -487,8 +472,7 @@ void platform_late_init()
         logmsg("SCSI target/disk mode selected by DIP switch, acting as a SCSI disk");
     }
 #else
-    // Initiator mode detected via ini.
-    platform_enable_initiator_mode();
+    // Initiator mode detected will be detected via ini.
 #endif // defined(HAS_DIP_SWITCHES) && defined(PLATFORM_HAS_INITIATOR_MODE)
 
     /* Initialize SCSI pins to required modes.
@@ -606,20 +590,7 @@ void platform_late_init()
 #ifndef PLATFORM_HAS_INITIATOR_MODE
         assert(false);
 #else
-        // Act as SCSI initiator
-
-        //        pin             function       pup   pdown  out    state fast
-        gpio_conf(SCSI_IN_IO,     GPIO_FUNC_SIO, true ,false, false, true, false);
-        gpio_conf(SCSI_IN_MSG,    GPIO_FUNC_SIO, true ,false, false, true, false);
-        gpio_conf(SCSI_IN_CD,     GPIO_FUNC_SIO, true ,false, false, true, false);
-        gpio_conf(SCSI_IN_REQ,    GPIO_FUNC_SIO, true ,false, false, true, false);
-        gpio_conf(SCSI_IN_BSY,    GPIO_FUNC_SIO, true, false, false, true, false);
-        gpio_conf(SCSI_IN_RST,    GPIO_FUNC_SIO, true, false, false, true, false);
-        // Reinitialize OUT_RST to output mode. On RP Pico variant the pin is shared with IN_RST.
-        gpio_conf(SCSI_OUT_RST,   GPIO_FUNC_SIO, false, false, true,  true, true);
-        gpio_conf(SCSI_OUT_SEL,   GPIO_FUNC_SIO, false,false, true,  true, true);
-        gpio_conf(SCSI_OUT_ACK,   GPIO_FUNC_SIO, false,false, true,  true, true);
-        gpio_conf(SCSI_OUT_ATN,   GPIO_FUNC_SIO, false,false, true,  true, true);
+        platform_initiator_gpio_setup();
 #endif  // PLATFORM_HAS_INITIATOR_MODE
     }
 
@@ -629,6 +600,23 @@ void platform_late_init()
     scsi_accel_rp2040_init();
 }
 
+// Act as SCSI initiator
+void platform_initiator_gpio_setup() {
+    //        pin                   function       pup   pdown  out    state fast
+    gpio_conf(SCSI_IN_IO,     GPIO_FUNC_SIO, true ,false, false, true, false);
+    gpio_conf(SCSI_IN_MSG,    GPIO_FUNC_SIO, true ,false, false, true, false);
+    gpio_conf(SCSI_IN_CD,     GPIO_FUNC_SIO, true ,false, false, true, false);
+    gpio_conf(SCSI_IN_REQ,    GPIO_FUNC_SIO, true ,false, false, true, false);
+    gpio_conf(SCSI_IN_BSY,    GPIO_FUNC_SIO, true, false, false, true, false);
+    gpio_conf(SCSI_IN_RST,    GPIO_FUNC_SIO, true, false, false, true, false);
+    gpio_conf(SCSI_OUT_RST,   GPIO_FUNC_SIO, false,false, true,  true, true);
+    gpio_conf(SCSI_OUT_ACK,   GPIO_FUNC_SIO, true,false, true,  true, true);
+    //gpio_conf(SCSI_OUT_ATN,   GPIO_FUNC_SIO, false,false, true,  true, true);  // ATN output is unused
+}
+
+bool platform_supports_initiator_mode() {
+    return g_supports_initiator;
+}
 void platform_post_sd_card_init() {}
 
 bool platform_is_initiator_mode_enabled()

+ 3 - 0
lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform.h

@@ -111,6 +111,9 @@ uint8_t platform_no_sd_card_on_init_error_code();
 // Query whether initiator mode is enabled on targets with PLATFORM_HAS_INITIATOR_MODE
 bool platform_is_initiator_mode_enabled();
 
+void platform_initiator_gpio_setup();
+bool platform_supports_initiator_mode();
+void platform_enable_initiator_mode();
 // Setup soft watchdog if supported
 void platform_reset_watchdog();
 

+ 11 - 2
lib/BlueSCSI_platform_RP2MCU/BlueSCSI_platform_gpio_v2.h

@@ -119,11 +119,20 @@ extern uint32_t SCSI_ACCEL_PINMASK;
 // Set pin directions for initiator vs. target mode
 #define SCSI_ENABLE_INITIATOR() \
     (sio_hw->gpio_oe_set = (1 << SCSI_OUT_ACK) | \
-    (1 << SCSI_OUT_ATN)), \
+    (1 << SCSI_OUT_SEL)), \
     (sio_hw->gpio_oe_clr = (1 << SCSI_IN_IO) | \
     (1 << SCSI_IN_CD) | \
     (1 << SCSI_IN_MSG) | \
-    (1 << SCSI_IN_REQ))
+    (1 << SCSI_OUT_REQ))
+
+// Used in test mode only
+#define SCSI_RELEASE_INITIATOR() \
+    (sio_hw->gpio_oe_clr = (1 << SCSI_OUT_ACK) | \
+    (1 << SCSI_OUT_SEL)), \
+    (sio_hw->gpio_oe_set = (1 << SCSI_IN_IO) | \
+    (1 << SCSI_IN_CD) | \
+    (1 << SCSI_IN_MSG) | \
+    (1 << SCSI_OUT_REQ))
 
 // Enable driving of shared control pins
 #define SCSI_ENABLE_CONTROL_OUT() \

+ 11 - 4
lib/BlueSCSI_platform_RP2MCU/scsiHostPhy.cpp

@@ -32,6 +32,7 @@ extern "C" {
 }
 
 volatile int g_scsiHostPhyReset;
+bool perform_parity_checking = true;
 
 #ifndef PLATFORM_HAS_INITIATOR_MODE
 
@@ -66,12 +67,14 @@ void scsiHostPhyReset(void)
 // Returns true if the target answers to selection request.
 bool scsiHostPhySelect(int target_id, uint8_t initiator_id)
 {
+    SCSI_ENABLE_INITIATOR();
     SCSI_RELEASE_OUTPUTS();
 
     // We can't write individual data bus bits, so use a bit modified
     // arbitration scheme. We always yield to any other initiator on
     // the bus.
     scsiLogInitiatorPhaseChange(BUS_BUSY);
+    SCSI_OUT(REQ, 0);
     SCSI_OUT(BSY, 1);
     for (int wait = 0; wait < 10; wait++)
     {
@@ -114,8 +117,9 @@ bool scsiHostPhySelect(int target_id, uint8_t initiator_id)
 
     // We need to assert OUT_BSY to enable IO buffer U105 to read status signals.
     SCSI_RELEASE_DATA_REQ();
-    SCSI_OUT(BSY, 1);
+    // SCSI_OUT(BSY, 1);
     SCSI_OUT(SEL, 0);
+    SCSI_ENABLE_INITIATOR();
     return true;
 }
 
@@ -139,8 +143,8 @@ int scsiHostPhyGetPhase()
 
     if (phase == 0 && absolute_time_diff_us(last_online_time, get_absolute_time()) > 100)
     {
-        // Disable OUT_BSY for a short time to see if the target is still on line
-        SCSI_OUT(BSY, 0);
+        // BlueSCSI doesn't need to assert OUT_BSY to check whether the bus is in use
+        // SCSI_OUT(BSY, 0);
         delayMicroseconds(1);
 
         if (!SCSI_IN(BSY))
@@ -150,7 +154,7 @@ int scsiHostPhyGetPhase()
         }
 
         // Still online, re-enable OUT_BSY to enable IO buffers
-        SCSI_OUT(BSY, 1);
+        // SCSI_OUT(BSY, 1);
         last_online_time = get_absolute_time();
     }
     else if (phase != 0)
@@ -365,4 +369,7 @@ void scsiHostPhyRelease()
     SCSI_RELEASE_OUTPUTS();
 }
 
+void setInitiatorModeParityCheck(const bool checkParity) {
+    perform_parity_checking = checkParity;
+}
 #endif

+ 3 - 0
lib/BlueSCSI_platform_RP2MCU/scsiHostPhy.h

@@ -57,3 +57,6 @@ void scsiHostWaitBusFree();
 
 // Release all bus signals
 void scsiHostPhyRelease();
+
+// Set whether to perform parity checking on SCSI transfers.
+void setInitiatorModeParityCheck(bool checkParity);

+ 8 - 6
lib/BlueSCSI_platform_RP2MCU/scsi_accel_host.cpp

@@ -64,11 +64,13 @@ static void scsi_accel_host_config_gpio()
     }
     else if (g_scsi_host_state == SCSIHOST_READ)
     {
-        // Data bus and REQ as input, ACK pin as output
-        pio_sm_set_pins(SCSI_PIO, SCSI_SM, SCSI_IO_DATA_MASK | 1 << SCSI_IN_REQ | 1 << SCSI_OUT_ACK);
-        pio_sm_set_consecutive_pindirs(SCSI_PIO, SCSI_SM, SCSI_IO_DB0, 9, false);
-        pio_sm_set_consecutive_pindirs(SCSI_PIO, SCSI_SM, SCSI_IN_REQ, 1, false);
-        pio_sm_set_consecutive_pindirs(SCSI_PIO, SCSI_SM, SCSI_OUT_ACK, 1, true);
+        // 100000010000000000111111111
+        // ACK    REQ        PDB
+        //
+        pio_sm_set_pins(SCSI_PIO, SCSI_SM, 0x40801FF);
+        pio_sm_set_consecutive_pindirs(SCSI_PIO, SCSI_SM, 0, 9, false);  // DBP Input
+        pio_sm_set_consecutive_pindirs(SCSI_PIO, SCSI_SM, SCSI_IN_REQ, 1, false);  // REQ Input
+        pio_sm_set_consecutive_pindirs(SCSI_PIO, SCSI_SM, SCSI_OUT_ACK, 1, true);  // ACK Output
 
         iobank0_hw->io[SCSI_IO_DB0].ctrl  = GPIO_FUNC_SIO;
         iobank0_hw->io[SCSI_IO_DB1].ctrl  = GPIO_FUNC_SIO;
@@ -79,7 +81,7 @@ static void scsi_accel_host_config_gpio()
         iobank0_hw->io[SCSI_IO_DB6].ctrl  = GPIO_FUNC_SIO;
         iobank0_hw->io[SCSI_IO_DB7].ctrl  = GPIO_FUNC_SIO;
         iobank0_hw->io[SCSI_IO_DBP].ctrl  = GPIO_FUNC_SIO;
-        iobank0_hw->io[SCSI_IN_REQ].ctrl  = GPIO_FUNC_SIO;
+        // iobank0_hw->io[SCSI_IN_REQ].ctrl  = GPIO_FUNC_SIO;
         iobank0_hw->io[SCSI_OUT_ACK].ctrl = GPIO_FUNC_PIO0;
     }
 }

+ 16 - 0
src/BlueSCSI.cpp

@@ -779,6 +779,8 @@ static void reinitSCSI()
     // Initialize scsiDev to zero values even though it is not used
     scsiInit();
 
+    // Setup GPIO pins for initiator mode
+    platform_initiator_gpio_setup();
     // Initializer initiator mode state machine
     scsiInitiatorInit();
 
@@ -1159,6 +1161,20 @@ static void bluescsi_setup_sd_card(bool wait_for_card = true)
     }
   }
 #ifdef PLATFORM_HAS_INITIATOR_MODE
+  if (ini_getbool("SCSI", "InitiatorMode", false, CONFIGFILE))
+  {
+    if (platform_supports_initiator_mode()) {
+      logmsg("SCSI Initiator Mode");
+      platform_enable_initiator_mode();
+      if (! ini_getbool("SCSI", "InitiatorParity", true, CONFIGFILE))
+      {
+        logmsg("Initiator Mode Skipping Parity Check.");
+        setInitiatorModeParityCheck(false);
+      }
+    } else {
+      logmsg("SCSI Initiator Mode requested but not supported.");
+    }
+  }
   if (!platform_is_initiator_mode_enabled())
 #endif
   {

+ 6 - 0
src/BlueSCSI_initiator.cpp

@@ -212,6 +212,8 @@ static int scsiTypeToIniType(int scsi_type, bool removable)
 // High level logic of the initiator mode
 void scsiInitiatorMainLoop()
 {
+    SCSI_RELEASE_OUTPUTS();
+    SCSI_ENABLE_INITIATOR();
     if (g_scsiHostPhyReset)
     {
         logmsg("Executing BUS RESET after aborted command");
@@ -269,6 +271,7 @@ void scsiInitiatorMainLoop()
 
         if (!(g_initiator_state.drives_imaged & (1 << g_initiator_state.target_id)))
         {
+            logmsg("Scanning SCSI ID ", g_initiator_state.target_id);
             delay_with_poll(1000);
 
             uint8_t inquiry_data[36] = {0};
@@ -277,14 +280,17 @@ void scsiInitiatorMainLoop()
             bool startstopok =
                 scsiTestUnitReady(g_initiator_state.target_id) &&
                 scsiStartStopUnit(g_initiator_state.target_id, true);
+            dbgmsg("startstop: ", startstopok ? "OK" : "FAILED");
 
             bool readcapok = startstopok &&
                 scsiInitiatorReadCapacity(g_initiator_state.target_id,
                                           &g_initiator_state.sectorcount,
                                           &g_initiator_state.sectorsize);
+            dbgmsg("read capacity: ", readcapok ? "OK" : "FAILED");
 
             bool inquiryok = startstopok &&
                 scsiInquiry(g_initiator_state.target_id, inquiry_data);
+            dbgmsg("inquiry: ", inquiryok ? "OK" : "FAILED");
 
             LED_OFF();