|
|
@@ -17,6 +17,7 @@ extern "C" {
|
|
|
#include <hardware/flash.h>
|
|
|
|
|
|
const char *g_azplatform_name = PLATFORM_NAME;
|
|
|
+static bool g_scsi_initiator = false;
|
|
|
|
|
|
void mbed_error_hook(const mbed_error_ctx * error_context);
|
|
|
|
|
|
@@ -56,7 +57,6 @@ void azplatform_init()
|
|
|
|
|
|
delay(10); // 10 ms delay to let pull-ups do their work
|
|
|
|
|
|
- bool initiator = !gpio_get(DIP_INITIATOR);
|
|
|
bool dbglog = !gpio_get(DIP_DBGLOG);
|
|
|
bool termination = !gpio_get(DIP_TERM);
|
|
|
|
|
|
@@ -65,12 +65,7 @@ void azplatform_init()
|
|
|
uart_init(uart0, 1000000);
|
|
|
mbed_set_error_hook(mbed_error_hook);
|
|
|
|
|
|
- azlog("DIP switch settings: initiator ", (int)initiator, ", debug log ", (int)dbglog, ", termination ", (int)termination);
|
|
|
-
|
|
|
- if (initiator)
|
|
|
- {
|
|
|
- azlog("ERROR: SCSI initiator mode is not implemented yet, turn DIP switch off for proper operation!");
|
|
|
- }
|
|
|
+ azlog("DIP switch settings: debug log ", (int)dbglog, ", termination ", (int)termination);
|
|
|
|
|
|
g_azlog_debug = dbglog;
|
|
|
|
|
|
@@ -83,7 +78,76 @@ void azplatform_init()
|
|
|
azlog("NOTE: SCSI termination is disabled");
|
|
|
}
|
|
|
|
|
|
- /* Initialize SCSI and SD card pins to required modes.
|
|
|
+ // SD card pins
|
|
|
+ // Card is used in SDIO mode for main program, and in SPI mode for crash handler & bootloader.
|
|
|
+ // pin function pup pdown out state fast
|
|
|
+ gpio_conf(SD_SPI_SCK, GPIO_FUNC_SPI, true, false, true, true, true);
|
|
|
+ gpio_conf(SD_SPI_MOSI, GPIO_FUNC_SPI, true, false, true, true, true);
|
|
|
+ gpio_conf(SD_SPI_MISO, GPIO_FUNC_SPI, true, false, false, true, true);
|
|
|
+ gpio_conf(SD_SPI_CS, GPIO_FUNC_SIO, true, false, true, true, true);
|
|
|
+ gpio_conf(SDIO_D1, GPIO_FUNC_SIO, true, false, false, true, true);
|
|
|
+ gpio_conf(SDIO_D2, GPIO_FUNC_SIO, true, false, false, true, true);
|
|
|
+
|
|
|
+ // LED pin
|
|
|
+ gpio_conf(LED_PIN, GPIO_FUNC_SIO, false,false, true, false, false);
|
|
|
+
|
|
|
+ // I2C pins
|
|
|
+ // pin function pup pdown out state fast
|
|
|
+ gpio_conf(GPIO_I2C_SCL, GPIO_FUNC_I2C, true,false, false, true, true);
|
|
|
+ gpio_conf(GPIO_I2C_SDA, GPIO_FUNC_I2C, true,false, false, true, true);
|
|
|
+}
|
|
|
+
|
|
|
+static bool read_initiator_dip_switch()
|
|
|
+{
|
|
|
+ /* Revision 2022d hardware has problems reading initiator DIP switch setting.
|
|
|
+ * The 74LVT245 hold current is keeping the GPIO_ACK state too strongly.
|
|
|
+ * Detect this condition by toggling the pin up and down and seeing if it sticks.
|
|
|
+ */
|
|
|
+
|
|
|
+ // Strong output high, then pulldown
|
|
|
+ // pin function pup pdown out state fast
|
|
|
+ gpio_conf(DIP_INITIATOR, GPIO_FUNC_SIO, false, false, true, true, false);
|
|
|
+ gpio_conf(DIP_INITIATOR, GPIO_FUNC_SIO, false, true, false, true, false);
|
|
|
+ delay(1);
|
|
|
+ bool initiator_state1 = gpio_get(DIP_INITIATOR);
|
|
|
+
|
|
|
+ // Strong output low, then pullup
|
|
|
+ // pin function pup pdown out state fast
|
|
|
+ gpio_conf(DIP_INITIATOR, GPIO_FUNC_SIO, false, false, true, false, false);
|
|
|
+ gpio_conf(DIP_INITIATOR, GPIO_FUNC_SIO, true, false, false, false, false);
|
|
|
+ delay(1);
|
|
|
+ bool initiator_state2 = gpio_get(DIP_INITIATOR);
|
|
|
+
|
|
|
+ if (initiator_state1 == initiator_state2)
|
|
|
+ {
|
|
|
+ // Ok, was able to read the state directly
|
|
|
+ return !initiator_state1;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Enable OUT_BSY for a short time.
|
|
|
+ // If in target mode, this will force GPIO_ACK high.
|
|
|
+ gpio_put(SCSI_OUT_BSY, 0);
|
|
|
+ delay_100ns();
|
|
|
+ gpio_put(SCSI_OUT_BSY, 1);
|
|
|
+
|
|
|
+ return !gpio_get(DIP_INITIATOR);
|
|
|
+}
|
|
|
+
|
|
|
+// late_init() only runs in main application, SCSI not needed in bootloader
|
|
|
+void azplatform_late_init()
|
|
|
+{
|
|
|
+ if (read_initiator_dip_switch())
|
|
|
+ {
|
|
|
+ g_scsi_initiator = true;
|
|
|
+ azlog("SCSI initiator mode selected by DIP switch, expecting SCSI disks on the bus");
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ g_scsi_initiator = false;
|
|
|
+ azlog("SCSI target mode selected by DIP switch, acting as an SCSI disk");
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Initialize SCSI pins to required modes.
|
|
|
* SCSI pins should be inactive / input at this point.
|
|
|
*/
|
|
|
|
|
|
@@ -100,57 +164,57 @@ void azplatform_init()
|
|
|
gpio_conf(SCSI_IO_DB7, GPIO_FUNC_SIO, true, false, false, true, true);
|
|
|
gpio_conf(SCSI_IO_DBP, GPIO_FUNC_SIO, true, false, false, true, true);
|
|
|
|
|
|
- // SCSI control outputs
|
|
|
- // pin function pup pdown out state fast
|
|
|
- gpio_conf(SCSI_OUT_IO, GPIO_FUNC_SIO, false,false, true, true, true);
|
|
|
- gpio_conf(SCSI_OUT_MSG, GPIO_FUNC_SIO, false,false, true, true, true);
|
|
|
-
|
|
|
- // REQ pin is switched between PIO and SIO, pull-up makes sure no glitches
|
|
|
- gpio_conf(SCSI_OUT_REQ, GPIO_FUNC_SIO, true ,false, true, true, true);
|
|
|
-
|
|
|
- // Shared pins are changed to input / output depending on communication phase
|
|
|
- gpio_conf(SCSI_IN_SEL, GPIO_FUNC_SIO, true, false, false, true, true);
|
|
|
- if (SCSI_OUT_CD != SCSI_IN_SEL)
|
|
|
+ if (!g_scsi_initiator)
|
|
|
{
|
|
|
- gpio_conf(SCSI_OUT_CD, GPIO_FUNC_SIO, false,false, true, true, true);
|
|
|
- }
|
|
|
+ // Act as SCSI device / target
|
|
|
|
|
|
- gpio_conf(SCSI_IN_BSY, GPIO_FUNC_SIO, true, false, false, true, true);
|
|
|
- if (SCSI_OUT_MSG != SCSI_IN_BSY)
|
|
|
- {
|
|
|
- gpio_conf(SCSI_OUT_MSG, GPIO_FUNC_SIO, false,false, true, true, true);
|
|
|
- }
|
|
|
+ // SCSI control outputs
|
|
|
+ // pin function pup pdown out state fast
|
|
|
+ gpio_conf(SCSI_OUT_IO, GPIO_FUNC_SIO, false,false, true, true, true);
|
|
|
+ gpio_conf(SCSI_OUT_MSG, GPIO_FUNC_SIO, false,false, true, true, true);
|
|
|
|
|
|
- // SCSI control inputs
|
|
|
- // pin function pup pdown out state fast
|
|
|
- gpio_conf(SCSI_IN_ACK, GPIO_FUNC_SIO, true, false, false, true, false);
|
|
|
- gpio_conf(SCSI_IN_ATN, GPIO_FUNC_SIO, true, false, false, true, false);
|
|
|
- gpio_conf(SCSI_IN_RST, GPIO_FUNC_SIO, true, false, false, true, false);
|
|
|
+ // REQ pin is switched between PIO and SIO, pull-up makes sure no glitches
|
|
|
+ gpio_conf(SCSI_OUT_REQ, GPIO_FUNC_SIO, true ,false, true, true, true);
|
|
|
|
|
|
- // SD card pins
|
|
|
- // Card is used in SDIO mode for main program, and in SPI mode for crash handler & bootloader.
|
|
|
- // pin function pup pdown out state fast
|
|
|
- gpio_conf(SD_SPI_SCK, GPIO_FUNC_SPI, true, false, true, true, true);
|
|
|
- gpio_conf(SD_SPI_MOSI, GPIO_FUNC_SPI, true, false, true, true, true);
|
|
|
- gpio_conf(SD_SPI_MISO, GPIO_FUNC_SPI, true, false, false, true, true);
|
|
|
- gpio_conf(SD_SPI_CS, GPIO_FUNC_SIO, true, false, true, true, true);
|
|
|
- gpio_conf(SDIO_D1, GPIO_FUNC_SIO, true, false, false, true, true);
|
|
|
- gpio_conf(SDIO_D2, GPIO_FUNC_SIO, true, false, false, true, true);
|
|
|
+ // Shared pins are changed to input / output depending on communication phase
|
|
|
+ gpio_conf(SCSI_IN_SEL, GPIO_FUNC_SIO, true, false, false, true, true);
|
|
|
+ if (SCSI_OUT_CD != SCSI_IN_SEL)
|
|
|
+ {
|
|
|
+ gpio_conf(SCSI_OUT_CD, GPIO_FUNC_SIO, false,false, true, true, true);
|
|
|
+ }
|
|
|
|
|
|
- // LED pin
|
|
|
- gpio_conf(LED_PIN, GPIO_FUNC_SIO, false,false, true, false, false);
|
|
|
+ gpio_conf(SCSI_IN_BSY, GPIO_FUNC_SIO, true, false, false, true, true);
|
|
|
+ if (SCSI_OUT_MSG != SCSI_IN_BSY)
|
|
|
+ {
|
|
|
+ gpio_conf(SCSI_OUT_MSG, GPIO_FUNC_SIO, false,false, true, true, true);
|
|
|
+ }
|
|
|
|
|
|
- // I2C pins
|
|
|
- // pin function pup pdown out state fast
|
|
|
- gpio_conf(GPIO_I2C_SCL, GPIO_FUNC_I2C, true,false, false, true, true);
|
|
|
- gpio_conf(GPIO_I2C_SDA, GPIO_FUNC_I2C, true,false, false, true, true);
|
|
|
+ // SCSI control inputs
|
|
|
+ // pin function pup pdown out state fast
|
|
|
+ gpio_conf(SCSI_IN_ACK, GPIO_FUNC_SIO, true, false, false, true, false);
|
|
|
+ gpio_conf(SCSI_IN_ATN, GPIO_FUNC_SIO, true, false, false, true, false);
|
|
|
+ gpio_conf(SCSI_IN_RST, GPIO_FUNC_SIO, true, false, false, true, 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);
|
|
|
+ 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);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-void azplatform_late_init()
|
|
|
+bool azplatform_is_initiator_mode_enabled()
|
|
|
{
|
|
|
- /* This function can usually be left empty.
|
|
|
- * It can be used for initialization code that should not run in bootloader.
|
|
|
- */
|
|
|
+ return g_scsi_initiator;
|
|
|
}
|
|
|
|
|
|
/*****************************************/
|
|
|
@@ -247,6 +311,7 @@ static void watchdog_callback(unsigned alarm_num)
|
|
|
{
|
|
|
azlog("WATCHDOG TIMEOUT, attempting bus reset");
|
|
|
scsiDev.resetFlag = 1;
|
|
|
+ g_scsiHostPhyReset = true;
|
|
|
}
|
|
|
|
|
|
if (g_watchdog_timeout <= 0)
|