| 
					
				 | 
			
			
				@@ -4,6 +4,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "scsiPhy.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "AzulSCSI_platform.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "scsi_accel_asm.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "scsi_accel_dma.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "AzulSCSI_log.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "AzulSCSI_log_trace.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -104,6 +105,10 @@ extern "C" void scsiPhyReset(void) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     g_scsi_sts_selection = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     g_scsi_ctrl_bsy = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     init_irqs(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#ifdef SCSI_ACCEL_DMA_AVAILABLE 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    scsi_accel_dma_init(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /************************/ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -214,8 +219,55 @@ extern "C" void scsiWriteByte(uint8_t value) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 extern "C" void scsiWrite(const uint8_t* data, uint32_t count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    uint32_t count_words = count / 4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    scsiStartWrite(data, count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    scsiFinishWrite(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const uint8_t *data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    uint32_t count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} g_scsi_writereq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+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)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        scsi_accel_dma_startWrite(data, count, &scsiDev.resetFlag); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    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(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    // 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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (count > g_scsi_writereq.count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        count = g_scsi_writereq.count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const uint8_t *data = g_scsi_writereq.data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    uint32_t count_words = count / 4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (count_words * 4 == count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // Use accelerated subroutine 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -229,6 +281,65 @@ extern "C" void scsiWrite(const uint8_t* data, uint32_t count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             scsiWriteOneByte(data[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    g_scsi_writereq.count -= count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (g_scsi_writereq.count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        g_scsi_writereq.data += count; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        g_scsi_writereq.data = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static bool isPollingWriteFinished(const uint8_t *data) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+{ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (g_scsi_writereq.count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        if (data == NULL) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        else if (data >= g_scsi_writereq.data && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            data < g_scsi_writereq.data + g_scsi_writereq.count) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+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)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // Process the transfer piece-by-piece while waiting 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // for SD card to react. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        processPollingWrite(256); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return isPollingWriteFinished(data); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        processPollingWrite(g_scsi_writereq.count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /*********************/ 
			 |