1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
 firmware/target/arm/as3525/sd-as3525v2.c |  122 +++++++++++++++++++++++++-----
 1 files changed, 103 insertions(+), 19 deletions(-)


diff --git a/firmware/target/arm/as3525/sd-as3525v2.c b/firmware/target/arm/as3525/sd-as3525v2.c
index d42f7b4..34f7a8a 100644
--- a/firmware/target/arm/as3525/sd-as3525v2.c
+++ b/firmware/target/arm/as3525/sd-as3525v2.c
@@ -32,8 +32,8 @@
 #include <stdlib.h>
 #include <string.h>
 #include "as3525v2.h"
-#include "pl081.h"  /* DMA controller */
-#include "dma-target.h" /* DMA request lines */
+//#include "pl081.h"  /* DMA controller */
+//#include "dma-target.h" /* DMA request lines */
 #include "clock-target.h"
 #include "panic.h"
 #include "stdbool.h"
@@ -315,8 +315,8 @@
 #define MCI_FIFO        ((unsigned long *) (SD_BASE+0x100))

 #define UNALIGNED_NUM_SECTORS 10
-static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS* SD_BLOCK_SIZE] __attribute__((aligned(32)));   /* align on cache line size */
-static unsigned char *uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]);
+//static unsigned char aligned_buffer[UNALIGNED_NUM_SECTORS* SD_BLOCK_SIZE] __attribute__((aligned(32)));   /* align on cache line size */
+//static unsigned char *uncached_buffer = UNCACHED_ADDR(&aligned_buffer[0]);

 static void init_controller(void);
 static int sd_wait_for_state(const int drive, unsigned int state);
@@ -338,7 +338,7 @@ bool sd_enabled = false;
 #endif

 static struct wakeup transfer_completion_signal;
-static volatile bool retry;
+//static volatile bool retry;

 #if defined(HAVE_MULTIDRIVE)
 int active_card = 0;
@@ -347,18 +347,81 @@ int active_card = 0;

 static inline void mci_delay(void) { udelay(1000); }

+static unsigned irq_bytes;
+static uint32_t *irq_ptr;
+static bool irq_write;
+static unsigned irq_counter = 0;
+static bool irq_dto;
+
+
+
+
+#define MCI_FIFO_BYTES  ((MCI_STATUS >> 17) & 0x1FFF)
+
 void INT_NAND(void)
 {
     MCI_CTRL &= ~INT_ENABLE;
     const int status = MCI_MASK_STATUS;

-    MCI_RAW_STATUS = status;    /* clear status */
-
     if(status & MCI_DATA_ERROR)
-        retry = true;
+        //retry = true;
+        panicf("error 0x%x", status);
+
+    if(status & (MCI_INT_RXDR|MCI_INT_DTO))
+    {
+        if(status & MCI_INT_DTO)
+            irq_dto = true;
+
+        irq_counter++;
+        /* PIO */
+        volatile unsigned int *fifo = (volatile unsigned int*)MCI_FIFO;
+        unsigned int fifo_bytes = MCI_FIFO_BYTES;

-    if( status & (MCI_INT_DTO|MCI_DATA_ERROR))
-        wakeup_signal(&transfer_completion_signal);
+        if(irq_write)
+        {
+            // TODO
+        }
+        else
+        {
+            /* If we have reached the end of the block, we can
+            * read a word and get 1 to 3 bytes.  If we are in the
+            * middle of the block, we have to read full words,
+            * otherwise we will write garbage, so round down to
+            * an even multiple of 4. */
+            if(fifo_bytes >= irq_bytes)
+                fifo_bytes = irq_bytes;
+            else
+                fifo_bytes -= fifo_bytes & 3;
+
+            irq_bytes -= fifo_bytes;
+
+            unsigned int fifo_words = fifo_bytes >>2;
+
+            while(fifo_words--) 
+                *irq_ptr++ = *fifo;
+
+            if(fifo_bytes & 3)
+            {
+                unsigned int n = fifo_bytes & 3;
+                unsigned int data = *fifo;
+                char *p = (char *) irq_ptr;
+
+                while (n--)
+                {
+                    *p++ = data;
+                    data >>= 8;
+                }
+            }
+
+            if(irq_bytes == 0)
+                wakeup_signal(&transfer_completion_signal);
+        }
+    }
+
+    MCI_RAW_STATUS = status;    /* clear status */
+
+    /*if(status & MCI_INT_DTO)
+        wakeup_signal(&transfer_completion_signal);*/

     MCI_CTRL |= INT_ENABLE;
 }
@@ -657,7 +720,7 @@ static void init_controller(void)
     MCI_DEBNCE = 0xfffff;               /* default value */

     /* Rx watermark = 63(sd reads)  Tx watermark = 128 (sd writes) */
-    MCI_FIFOTH = (MCI_FIFOTH & MCI_FIFOTH_MASK) | 0x503f0080;
+    MCI_FIFOTH = (MCI_FIFOTH & MCI_FIFOTH_MASK) | 0x00200020;

     GPIOB_DIR |= (1<<5);                 /* Set pin B5 to output  */

@@ -783,12 +846,13 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
 #endif

     last_disk_activity = current_tick;
-    dma_retain();
+    //dma_retain();

     const int cmd = write ? SD_WRITE_MULTIPLE_BLOCK : SD_READ_MULTIPLE_BLOCK;

     do
     {
+#if 0
         void *dma_buf = aligned_buffer;
         unsigned int transfer = count;
         if(transfer > UNALIGNED_NUM_SECTORS)
@@ -796,12 +860,13 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,

         if(write)
             memcpy(uncached_buffer, buf, transfer * SD_BLOCK_SIZE);
+#endif

         /* Interrupt handler might set this to true during transfer */
-        retry = false;
+        //retry = false;

         MCI_BLKSIZ = SD_BLOCK_SIZE;
-        MCI_BYTCNT = transfer * SD_BLOCK_SIZE;
+        MCI_BYTCNT = /*transfer*/ count * SD_BLOCK_SIZE;

         ret = sd_wait_for_state(drive, SD_TRAN);
         if (ret < 0)
@@ -817,8 +882,13 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
             goto sd_transfer_error;
         }

-        MCI_MASK |= (MCI_DATA_ERROR | MCI_INT_DTO);
-        MCI_CTRL |= DMA_ENABLE;
+        MCI_MASK |= (MCI_DATA_ERROR | MCI_INT_DTO | MCI_INT_RXDR);
+        //MCI_CTRL |= DMA_ENABLE;
+
+        irq_write = write;
+        irq_bytes = count * SD_BLOCK_SIZE;
+        irq_ptr = buf;
+        irq_dto = false;

         int arg = start;
         if(!(card_info[drive].ocr & (1<<30))) /* not SDHC */
@@ -827,6 +897,7 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
         if(!send_cmd(drive, cmd, arg, MCI_NO_RESP, NULL))
             panicf("%s multiple blocks failed", write ? "write" : "read");

+#if 0
         if(write)
             dma_enable_channel(0, dma_buf, MCI_FIFO, DMA_PERI_SD,
                 DMAC_FLOWCTRL_PERI_MEM_TO_PERI, true, false, 0, DMA_S8, NULL);
@@ -834,9 +905,20 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
             dma_enable_channel(0, MCI_FIFO, dma_buf, DMA_PERI_SD,
                 DMAC_FLOWCTRL_PERI_PERI_TO_MEM, false, true, 0, DMA_S8, NULL);

+
+#endif
+
+        while(irq_bytes != 0)
+        {
+            splashf(HZ, "%d rem. (%d)%s", irq_bytes, irq_counter,
+                irq_dto?"DTO":""
+            );
+        }
+
+        panicf("TRANSFER OK");
         wakeup_wait(&transfer_completion_signal, TIMEOUT_BLOCK);

-        MCI_MASK &= ~(MCI_DATA_ERROR | MCI_INT_DTO);
+        MCI_MASK &= ~(MCI_DATA_ERROR | MCI_INT_DTO | MCI_INT_RXDR);

         last_disk_activity = current_tick;

@@ -847,6 +929,7 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
             goto sd_transfer_error;
         }

+#if 0
         if(!retry)
         {
             if(!write)
@@ -861,10 +944,11 @@ static int sd_transfer_sectors(IF_MD2(int drive,) unsigned long start,
             while(MCI_CTRL & (FIFO_RESET|DMA_RESET))
                 ;
         }
+#endif

-    } while(retry || count);
+    } while(/*retry || count*/ 0);

-    dma_release();
+    //dma_release();

 #ifdef HAVE_MULTIDRIVE
     /* CMD lines are separate, not common, so we need to actively deselect */