| 
					
				 | 
			
			
				@@ -8,6 +8,8 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "scsi_accel_greenpak.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "AzulSCSI_log.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "AzulSCSI_log_trace.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "AzulSCSI_config.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <minIni.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <scsi2sd.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 extern "C" { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -15,6 +17,17 @@ extern "C" { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <time.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// Acceleration mode in use 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static enum { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    PHY_MODE_UNKNOWN = 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    PHY_MODE_PIO = 1, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    PHY_MODE_DMA_TIMER = 2, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    PHY_MODE_GREENPAK_PIO = 3 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} g_scsi_phy_mode; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static const char *g_scsi_phy_mode_names[4] = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    "Unknown", "PIO", "DMA_TIMER", "GREENPAK_PIO" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void init_irqs(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /***********************/ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -100,6 +113,34 @@ static void scsi_rst_assert_interrupt() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void selectPhyMode() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int oldmode = g_scsi_phy_mode; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int wanted_mode = ini_getl("SCSI", "PhyMode", PHY_MODE_UNKNOWN, CONFIGFILE); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    g_scsi_phy_mode = PHY_MODE_PIO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef SCSI_ACCEL_DMA_AVAILABLE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (wanted_mode == PHY_MODE_UNKNOWN || wanted_mode == PHY_MODE_DMA_TIMER) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        g_scsi_phy_mode = PHY_MODE_DMA_TIMER; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (wanted_mode == PHY_MODE_UNKNOWN || wanted_mode == PHY_MODE_GREENPAK_PIO) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (greenpak_is_ready()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            g_scsi_phy_mode = PHY_MODE_GREENPAK_PIO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (g_scsi_phy_mode != oldmode) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        azlog("SCSI PHY operating mode: ", g_scsi_phy_mode_names[g_scsi_phy_mode]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 extern "C" void scsiPhyReset(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     SCSI_RELEASE_OUTPUTS(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -107,9 +148,8 @@ extern "C" void scsiPhyReset(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     g_scsi_ctrl_bsy = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     init_irqs(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#ifdef SCSI_ACCEL_DMA_AVAILABLE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    selectPhyMode(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     scsi_accel_dma_init(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /************************/ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -233,33 +273,39 @@ extern "C" void scsiStartWrite(const uint8_t* data, uint32_t count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     scsiLogDataIn(data, count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#ifdef SCSI_ACCEL_DMA_AVAILABLE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (gpio_input_bit_get(DIP_PORT, DIPSW1_PIN)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (g_scsi_phy_mode == PHY_MODE_PIO || g_scsi_phy_mode == PHY_MODE_GREENPAK_PIO) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Software based bit-banging. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Write requests are queued and then executed in isWriteFinished() callback. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // This allows better parallelism with SD card transfers. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (g_scsi_writereq.count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (data == g_scsi_writereq.data + g_scsi_writereq.count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Combine with previous one 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                g_scsi_writereq.count += count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                // Actually execute previous request 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                scsiFinishWrite(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        g_scsi_writereq.data = data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        g_scsi_writereq.count = count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else if (g_scsi_phy_mode == PHY_MODE_DMA_TIMER) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Accelerated writes using DMA and timers 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         scsi_accel_dma_startWrite(data, count, &scsiDev.resetFlag); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (g_scsi_writereq.count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (data == g_scsi_writereq.data + g_scsi_writereq.count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // Combine with previous one 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            g_scsi_writereq.count += count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // Actually execute previous request 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            scsiFinishWrite(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        azlog("Unknown SCSI PHY mode: ", (int)g_scsi_phy_mode); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Queue polling write requests. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // This allows better parallelism with SD card transfers. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    g_scsi_writereq.data = data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    g_scsi_writereq.count = count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void processPollingWrite(uint32_t count) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -272,7 +318,7 @@ static void processPollingWrite(uint32_t count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (count_words * 4 == count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // Use accelerated subroutine 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (greenpak_is_ready()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (g_scsi_phy_mode == PHY_MODE_GREENPAK_PIO) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             scsi_accel_greenpak_send((const uint32_t*)data, count_words, &scsiDev.resetFlag); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -320,33 +366,38 @@ static bool isPollingWriteFinished(const uint8_t *data) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 extern "C" bool scsiIsWriteFinished(const uint8_t *data) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#ifdef SCSI_ACCEL_DMA_AVAILABLE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!scsi_accel_dma_isWriteFinished(data)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Check if there is still a polling transfer in progress 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (!isPollingWriteFinished(data)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (g_scsi_phy_mode == PHY_MODE_DMA_TIMER) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Process the transfer piece-by-piece while waiting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // for SD card to react. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        processPollingWrite(256); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return isPollingWriteFinished(data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return scsi_accel_dma_isWriteFinished(data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Check if there is still a polling transfer in progress 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (!isPollingWriteFinished(data)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // Process the transfer piece-by-piece while waiting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // for SD card to react. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            processPollingWrite(256); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return isPollingWriteFinished(data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 extern "C" void scsiFinishWrite() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#ifdef SCSI_ACCEL_DMA_AVAILABLE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    scsi_accel_dma_finishWrite(&scsiDev.resetFlag); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    // Finish previously started polling write request. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (g_scsi_writereq.count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (g_scsi_phy_mode == PHY_MODE_DMA_TIMER) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        processPollingWrite(g_scsi_writereq.count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        scsi_accel_dma_finishWrite(&scsiDev.resetFlag); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Finish previously started polling write request. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (g_scsi_writereq.count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            processPollingWrite(g_scsi_writereq.count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |