0c0c46c0e8ff0cac258752f3b99bdfc7bde4da05
[SCSI2SD-V6.git] / src / firmware / scsiPhy.c
1 //    Copyright (C) 2013 Michael McMaster <michael@codesrc.com>\r
2 //\r
3 //    This file is part of SCSI2SD.\r
4 //\r
5 //    SCSI2SD is free software: you can redistribute it and/or modify\r
6 //    it under the terms of the GNU General Public License as published by\r
7 //    the Free Software Foundation, either version 3 of the License, or\r
8 //    (at your option) any later version.\r
9 //\r
10 //    SCSI2SD is distributed in the hope that it will be useful,\r
11 //    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
12 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
13 //    GNU General Public License for more details.\r
14 //\r
15 //    You should have received a copy of the GNU General Public License\r
16 //    along with SCSI2SD.  If not, see <http://www.gnu.org/licenses/>.\r
17 \r
18 #ifdef STM32F2xx\r
19 #include "stm32f2xx.h"\r
20 #include "stm32f2xx_hal.h"\r
21 #include "stm32f2xx_hal_dma.h"\r
22 #endif\r
23 \r
24 #ifdef STM32F4xx\r
25 #include "stm32f4xx.h"\r
26 #include "stm32f4xx_hal.h"\r
27 #include "stm32f4xx_hal_dma.h"\r
28 #endif\r
29 \r
30 #include "gpio.h"\r
31 \r
32 #include "scsi.h"\r
33 #include "scsiPhy.h"\r
34 #include "time.h"\r
35 #include "fpga.h"\r
36 #include "led.h"\r
37 \r
38 #include <string.h>\r
39 \r
40 #define SCSI_ASYNC_15 0\r
41 #define SCSI_ASYNC_33 1\r
42 #define SCSI_ASYNC_50 2\r
43 #define SCSI_ASYNC_SAFE 3\r
44 #define SCSI_ASYNC_TURBO 4\r
45 \r
46 #ifdef STM32F2xx\r
47 #include "scsiPhyTiming108MHz.h"\r
48 #endif\r
49 \r
50 #ifdef STM32F4xx\r
51 #include "scsiPhyTiming90MHz.h"\r
52 #endif\r
53 \r
54 // Private DMA variables.\r
55 static int dmaInProgress = 0;\r
56 \r
57 static DMA_HandleTypeDef memToFSMC;\r
58 static DMA_HandleTypeDef fsmcToMem;\r
59 \r
60 \r
61 volatile uint8_t scsiRxDMAComplete;\r
62 volatile uint8_t scsiTxDMAComplete;\r
63 \r
64 // scsi IRQ handler is initialised by the STM32 HAL. Connected to\r
65 // PE4\r
66 // Note: naming is important to ensure this function is listed in the\r
67 // vector table.\r
68 void EXTI4_IRQHandler()\r
69 {\r
70     // Make sure that interrupt flag is set\r
71     if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_4) != RESET) {\r
72 \r
73         // Clear interrupt flag\r
74         __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4);\r
75 \r
76         uint8_t statusFlags = *SCSI_STS_SCSI;\r
77 \r
78         scsiDev.resetFlag = scsiDev.resetFlag || (statusFlags & 0x04);\r
79 \r
80         // selFlag is required for Philips P2000C which releases it after 600ns\r
81         // without waiting for BSY.\r
82         // Also required for some early Mac Plus roms\r
83         if (statusFlags & 0x08) // Check SEL flag\r
84         {\r
85             scsiDev.selFlag = *SCSI_STS_SELECTED;\r
86         }\r
87     }\r
88 }\r
89 \r
90 void\r
91 scsiSetDataCount(uint32_t count)\r
92 {\r
93     *SCSI_DATA_CNT_HI = (count >> 16) & 0xff;\r
94     *SCSI_DATA_CNT_MID = (count >> 8) & 0xff;\r
95     *SCSI_DATA_CNT_LO = count & 0xff;\r
96     *SCSI_DATA_CNT_SET = 1;\r
97 \r
98 #ifdef STM32F4xx\r
99     __NOP();\r
100     __NOP();\r
101 #endif\r
102 }\r
103 \r
104 int scsiFifoReady(void)\r
105 {\r
106     __NOP();\r
107     uint8_t test1 = HAL_GPIO_ReadPin(GPIOE, FPGA_GPIO3_Pin);\r
108     __NOP();\r
109 #ifdef STM32F4xx\r
110     __NOP();\r
111     __NOP();\r
112     __NOP();\r
113 #endif\r
114     uint8_t test2 = HAL_GPIO_ReadPin(GPIOE, FPGA_GPIO3_Pin);\r
115     return test1 != 0 && test2 != 0;\r
116 }\r
117 \r
118 uint8_t\r
119 scsiReadByte(void)\r
120 {\r
121     scsiSetDataCount(1);\r
122 \r
123     // Ready immediately. setDataCount resets fifos\r
124 \r
125     //__disable_irq();\r
126     while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))\r
127     {\r
128         //__WFI(); // Wait for interrupt\r
129     }\r
130     //__enable_irq();\r
131 \r
132     uint8_t val = scsiPhyRx();\r
133     // TODO scsiDev.parityError = scsiDev.parityError || SCSI_Parity_Error_Read();\r
134 \r
135     return val;\r
136 }\r
137 \r
138 \r
139 void\r
140 scsiReadPIO(uint8_t* data, uint32_t count, int* parityError)\r
141 {\r
142     uint16_t* fifoData = (uint16_t*)data;\r
143     uint32_t count16 = (count + 1) / 2;\r
144 \r
145     int i = 0;\r
146     while ((i  < count16) && likely(!scsiDev.resetFlag))\r
147     {\r
148         // Wait until FIFO is full (or complete)\r
149         while (!scsiFifoReady() && likely(!scsiDev.resetFlag))\r
150         {\r
151             // spin\r
152         }\r
153 \r
154         if (count16 - i >= SCSI_FIFO_DEPTH16)\r
155         {\r
156             uint32_t chunk16 = SCSI_FIFO_DEPTH16;\r
157 \r
158             // Let gcc unroll the loop as much as possible.\r
159             for (uint32_t k = 0; k + 128 <= chunk16; k += 128)\r
160             {\r
161                 fifoData[i + k] = scsiPhyRx();\r
162                 fifoData[i + k + 1] = scsiPhyRx();\r
163                 fifoData[i + k + 2] = scsiPhyRx();\r
164                 fifoData[i + k + 3] = scsiPhyRx();\r
165                 fifoData[i + k + 4] = scsiPhyRx();\r
166                 fifoData[i + k + 5] = scsiPhyRx();\r
167                 fifoData[i + k + 6] = scsiPhyRx();\r
168                 fifoData[i + k + 7] = scsiPhyRx();\r
169                 fifoData[i + k + 8] = scsiPhyRx();\r
170                 fifoData[i + k + 9] = scsiPhyRx();\r
171                 fifoData[i + k + 10] = scsiPhyRx();\r
172                 fifoData[i + k + 11] = scsiPhyRx();\r
173                 fifoData[i + k + 12] = scsiPhyRx();\r
174                 fifoData[i + k + 13] = scsiPhyRx();\r
175                 fifoData[i + k + 14] = scsiPhyRx();\r
176                 fifoData[i + k + 15] = scsiPhyRx();\r
177                 fifoData[i + k + 16] = scsiPhyRx();\r
178                 fifoData[i + k + 17] = scsiPhyRx();\r
179                 fifoData[i + k + 18] = scsiPhyRx();\r
180                 fifoData[i + k + 19] = scsiPhyRx();\r
181                 fifoData[i + k + 20] = scsiPhyRx();\r
182                 fifoData[i + k + 21] = scsiPhyRx();\r
183                 fifoData[i + k + 22] = scsiPhyRx();\r
184                 fifoData[i + k + 23] = scsiPhyRx();\r
185                 fifoData[i + k + 24] = scsiPhyRx();\r
186                 fifoData[i + k + 25] = scsiPhyRx();\r
187                 fifoData[i + k + 26] = scsiPhyRx();\r
188                 fifoData[i + k + 27] = scsiPhyRx();\r
189                 fifoData[i + k + 28] = scsiPhyRx();\r
190                 fifoData[i + k + 29] = scsiPhyRx();\r
191                 fifoData[i + k + 30] = scsiPhyRx();\r
192                 fifoData[i + k + 31] = scsiPhyRx();\r
193                 fifoData[i + k + 32] = scsiPhyRx();\r
194                 fifoData[i + k + 33] = scsiPhyRx();\r
195                 fifoData[i + k + 34] = scsiPhyRx();\r
196                 fifoData[i + k + 35] = scsiPhyRx();\r
197                 fifoData[i + k + 36] = scsiPhyRx();\r
198                 fifoData[i + k + 37] = scsiPhyRx();\r
199                 fifoData[i + k + 38] = scsiPhyRx();\r
200                 fifoData[i + k + 39] = scsiPhyRx();\r
201                 fifoData[i + k + 40] = scsiPhyRx();\r
202                 fifoData[i + k + 41] = scsiPhyRx();\r
203                 fifoData[i + k + 42] = scsiPhyRx();\r
204                 fifoData[i + k + 43] = scsiPhyRx();\r
205                 fifoData[i + k + 44] = scsiPhyRx();\r
206                 fifoData[i + k + 45] = scsiPhyRx();\r
207                 fifoData[i + k + 46] = scsiPhyRx();\r
208                 fifoData[i + k + 47] = scsiPhyRx();\r
209                 fifoData[i + k + 48] = scsiPhyRx();\r
210                 fifoData[i + k + 49] = scsiPhyRx();\r
211                 fifoData[i + k + 50] = scsiPhyRx();\r
212                 fifoData[i + k + 51] = scsiPhyRx();\r
213                 fifoData[i + k + 52] = scsiPhyRx();\r
214                 fifoData[i + k + 53] = scsiPhyRx();\r
215                 fifoData[i + k + 54] = scsiPhyRx();\r
216                 fifoData[i + k + 55] = scsiPhyRx();\r
217                 fifoData[i + k + 56] = scsiPhyRx();\r
218                 fifoData[i + k + 57] = scsiPhyRx();\r
219                 fifoData[i + k + 58] = scsiPhyRx();\r
220                 fifoData[i + k + 59] = scsiPhyRx();\r
221                 fifoData[i + k + 60] = scsiPhyRx();\r
222                 fifoData[i + k + 61] = scsiPhyRx();\r
223                 fifoData[i + k + 62] = scsiPhyRx();\r
224                 fifoData[i + k + 63] = scsiPhyRx();\r
225                 fifoData[i + k + 64] = scsiPhyRx();\r
226                 fifoData[i + k + 65] = scsiPhyRx();\r
227                 fifoData[i + k + 66] = scsiPhyRx();\r
228                 fifoData[i + k + 67] = scsiPhyRx();\r
229                 fifoData[i + k + 68] = scsiPhyRx();\r
230                 fifoData[i + k + 69] = scsiPhyRx();\r
231                 fifoData[i + k + 70] = scsiPhyRx();\r
232                 fifoData[i + k + 71] = scsiPhyRx();\r
233                 fifoData[i + k + 72] = scsiPhyRx();\r
234                 fifoData[i + k + 73] = scsiPhyRx();\r
235                 fifoData[i + k + 74] = scsiPhyRx();\r
236                 fifoData[i + k + 75] = scsiPhyRx();\r
237                 fifoData[i + k + 76] = scsiPhyRx();\r
238                 fifoData[i + k + 77] = scsiPhyRx();\r
239                 fifoData[i + k + 78] = scsiPhyRx();\r
240                 fifoData[i + k + 79] = scsiPhyRx();\r
241                 fifoData[i + k + 80] = scsiPhyRx();\r
242                 fifoData[i + k + 81] = scsiPhyRx();\r
243                 fifoData[i + k + 82] = scsiPhyRx();\r
244                 fifoData[i + k + 83] = scsiPhyRx();\r
245                 fifoData[i + k + 84] = scsiPhyRx();\r
246                 fifoData[i + k + 85] = scsiPhyRx();\r
247                 fifoData[i + k + 86] = scsiPhyRx();\r
248                 fifoData[i + k + 87] = scsiPhyRx();\r
249                 fifoData[i + k + 88] = scsiPhyRx();\r
250                 fifoData[i + k + 89] = scsiPhyRx();\r
251                 fifoData[i + k + 90] = scsiPhyRx();\r
252                 fifoData[i + k + 91] = scsiPhyRx();\r
253                 fifoData[i + k + 92] = scsiPhyRx();\r
254                 fifoData[i + k + 93] = scsiPhyRx();\r
255                 fifoData[i + k + 94] = scsiPhyRx();\r
256                 fifoData[i + k + 95] = scsiPhyRx();\r
257                 fifoData[i + k + 96] = scsiPhyRx();\r
258                 fifoData[i + k + 97] = scsiPhyRx();\r
259                 fifoData[i + k + 98] = scsiPhyRx();\r
260                 fifoData[i + k + 99] = scsiPhyRx();\r
261                 fifoData[i + k + 100] = scsiPhyRx();\r
262                 fifoData[i + k + 101] = scsiPhyRx();\r
263                 fifoData[i + k + 102] = scsiPhyRx();\r
264                 fifoData[i + k + 103] = scsiPhyRx();\r
265                 fifoData[i + k + 104] = scsiPhyRx();\r
266                 fifoData[i + k + 105] = scsiPhyRx();\r
267                 fifoData[i + k + 106] = scsiPhyRx();\r
268                 fifoData[i + k + 107] = scsiPhyRx();\r
269                 fifoData[i + k + 108] = scsiPhyRx();\r
270                 fifoData[i + k + 109] = scsiPhyRx();\r
271                 fifoData[i + k + 110] = scsiPhyRx();\r
272                 fifoData[i + k + 111] = scsiPhyRx();\r
273                 fifoData[i + k + 112] = scsiPhyRx();\r
274                 fifoData[i + k + 113] = scsiPhyRx();\r
275                 fifoData[i + k + 114] = scsiPhyRx();\r
276                 fifoData[i + k + 115] = scsiPhyRx();\r
277                 fifoData[i + k + 116] = scsiPhyRx();\r
278                 fifoData[i + k + 117] = scsiPhyRx();\r
279                 fifoData[i + k + 118] = scsiPhyRx();\r
280                 fifoData[i + k + 119] = scsiPhyRx();\r
281                 fifoData[i + k + 120] = scsiPhyRx();\r
282                 fifoData[i + k + 121] = scsiPhyRx();\r
283                 fifoData[i + k + 122] = scsiPhyRx();\r
284                 fifoData[i + k + 123] = scsiPhyRx();\r
285                 fifoData[i + k + 124] = scsiPhyRx();\r
286                 fifoData[i + k + 125] = scsiPhyRx();\r
287                 fifoData[i + k + 126] = scsiPhyRx();\r
288                 fifoData[i + k + 127] = scsiPhyRx();\r
289             }\r
290 \r
291             i += chunk16;\r
292         }\r
293         else\r
294         {\r
295             uint32_t chunk16 = count16 - i;\r
296 \r
297             uint32_t k = 0;\r
298             for (; k + 4 <= chunk16; k += 4)\r
299             {\r
300                 fifoData[i + k] = scsiPhyRx();\r
301                 fifoData[i + 1 + k] = scsiPhyRx();\r
302                 fifoData[i + 2 + k] = scsiPhyRx();\r
303                 fifoData[i + 3 + k] = scsiPhyRx();\r
304             }\r
305             for (; k < chunk16; ++k)\r
306             {\r
307                 fifoData[i + k] = scsiPhyRx();\r
308             }\r
309             i += chunk16;\r
310         }\r
311     }\r
312 \r
313     *parityError |= scsiParityError();\r
314 }\r
315 \r
316 void\r
317 scsiRead(uint8_t* data, uint32_t count, int* parityError)\r
318 {\r
319     int i = 0;\r
320     *parityError = 0;\r
321 \r
322     while (i < count && likely(!scsiDev.resetFlag))\r
323     {\r
324         uint32_t chunk = ((count - i) > SCSI_XFER_MAX)\r
325             ? SCSI_XFER_MAX : (count - i);\r
326         scsiSetDataCount(chunk);\r
327 \r
328         scsiReadPIO(data + i, chunk, parityError);\r
329 \r
330         while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))\r
331         {\r
332             __disable_irq();\r
333             if (!scsiPhyComplete() && likely(!scsiDev.resetFlag))\r
334             {\r
335                 __WFI();\r
336             }\r
337             __enable_irq();\r
338         }\r
339 \r
340         i += chunk;\r
341     }\r
342 }\r
343 \r
344 void\r
345 scsiWriteByte(uint8_t value)\r
346 {\r
347     scsiSetDataCount(1);\r
348     scsiPhyTx(value);\r
349 \r
350     //__disable_irq();\r
351     while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))\r
352     {\r
353         //__WFI();\r
354     }\r
355     //__enable_irq();\r
356 }\r
357 \r
358 void\r
359 scsiWritePIO(const uint8_t* data, uint32_t count)\r
360 {\r
361     uint16_t* fifoData = (uint16_t*)data;\r
362     uint32_t count16 = (count + 1) / 2;\r
363 \r
364     int i = 0;\r
365     while ((i  < count16) && likely(!scsiDev.resetFlag))\r
366     {\r
367         while (!scsiFifoReady() && likely(!scsiDev.resetFlag))\r
368         {\r
369             // Spin\r
370         }\r
371 \r
372         if (count16 - i >= SCSI_FIFO_DEPTH16)\r
373         {\r
374             uint32_t chunk16 = SCSI_FIFO_DEPTH16;\r
375 \r
376             // Let gcc unroll the loop as much as possible.\r
377             for (uint32_t k = 0; k + 128 <= chunk16; k += 128)\r
378             {\r
379                 scsiPhyTx32(fifoData[i + k], fifoData[i + k + 1]);\r
380                 scsiPhyTx32(fifoData[i + 2 + k], fifoData[i + k + 3]);\r
381                 scsiPhyTx32(fifoData[i + 4 + k], fifoData[i + k + 5]);\r
382                 scsiPhyTx32(fifoData[i + 6 + k], fifoData[i + k + 7]);\r
383                 scsiPhyTx32(fifoData[i + 8 + k], fifoData[i + k + 9]);\r
384                 scsiPhyTx32(fifoData[i + 10 + k], fifoData[i + k + 11]);\r
385                 scsiPhyTx32(fifoData[i + 12 + k], fifoData[i + k + 13]);\r
386                 scsiPhyTx32(fifoData[i + 14 + k], fifoData[i + k + 15]);\r
387                 scsiPhyTx32(fifoData[i + 16 + k], fifoData[i + k + 17]);\r
388                 scsiPhyTx32(fifoData[i + 18 + k], fifoData[i + k + 19]);\r
389                 scsiPhyTx32(fifoData[i + 20 + k], fifoData[i + k + 21]);\r
390                 scsiPhyTx32(fifoData[i + 22 + k], fifoData[i + k + 23]);\r
391                 scsiPhyTx32(fifoData[i + 24 + k], fifoData[i + k + 25]);\r
392                 scsiPhyTx32(fifoData[i + 26 + k], fifoData[i + k + 27]);\r
393                 scsiPhyTx32(fifoData[i + 28 + k], fifoData[i + k + 29]);\r
394                 scsiPhyTx32(fifoData[i + 30 + k], fifoData[i + k + 31]);\r
395 \r
396                 scsiPhyTx32(fifoData[i + 32 + k], fifoData[i + k + 33]);\r
397                 scsiPhyTx32(fifoData[i + 34 + k], fifoData[i + k + 35]);\r
398                 scsiPhyTx32(fifoData[i + 36 + k], fifoData[i + k + 37]);\r
399                 scsiPhyTx32(fifoData[i + 38 + k], fifoData[i + k + 39]);\r
400                 scsiPhyTx32(fifoData[i + 40 + k], fifoData[i + k + 41]);\r
401                 scsiPhyTx32(fifoData[i + 42 + k], fifoData[i + k + 43]);\r
402                 scsiPhyTx32(fifoData[i + 44 + k], fifoData[i + k + 45]);\r
403                 scsiPhyTx32(fifoData[i + 46 + k], fifoData[i + k + 47]);\r
404                 scsiPhyTx32(fifoData[i + 48 + k], fifoData[i + k + 49]);\r
405                 scsiPhyTx32(fifoData[i + 50 + k], fifoData[i + k + 51]);\r
406                 scsiPhyTx32(fifoData[i + 52 + k], fifoData[i + k + 53]);\r
407                 scsiPhyTx32(fifoData[i + 54 + k], fifoData[i + k + 55]);\r
408                 scsiPhyTx32(fifoData[i + 56 + k], fifoData[i + k + 57]);\r
409                 scsiPhyTx32(fifoData[i + 58 + k], fifoData[i + k + 59]);\r
410                 scsiPhyTx32(fifoData[i + 60 + k], fifoData[i + k + 61]);\r
411                 scsiPhyTx32(fifoData[i + 62 + k], fifoData[i + k + 63]);\r
412 \r
413                 scsiPhyTx32(fifoData[i + 64 + k], fifoData[i + k + 65]);\r
414                 scsiPhyTx32(fifoData[i + 66 + k], fifoData[i + k + 67]);\r
415                 scsiPhyTx32(fifoData[i + 68 + k], fifoData[i + k + 69]);\r
416                 scsiPhyTx32(fifoData[i + 70 + k], fifoData[i + k + 71]);\r
417                 scsiPhyTx32(fifoData[i + 72 + k], fifoData[i + k + 73]);\r
418                 scsiPhyTx32(fifoData[i + 74 + k], fifoData[i + k + 75]);\r
419                 scsiPhyTx32(fifoData[i + 76 + k], fifoData[i + k + 77]);\r
420                 scsiPhyTx32(fifoData[i + 78 + k], fifoData[i + k + 79]);\r
421                 scsiPhyTx32(fifoData[i + 80 + k], fifoData[i + k + 81]);\r
422                 scsiPhyTx32(fifoData[i + 82 + k], fifoData[i + k + 83]);\r
423                 scsiPhyTx32(fifoData[i + 84 + k], fifoData[i + k + 85]);\r
424                 scsiPhyTx32(fifoData[i + 86 + k], fifoData[i + k + 87]);\r
425                 scsiPhyTx32(fifoData[i + 88 + k], fifoData[i + k + 89]);\r
426                 scsiPhyTx32(fifoData[i + 90 + k], fifoData[i + k + 91]);\r
427                 scsiPhyTx32(fifoData[i + 92 + k], fifoData[i + k + 93]);\r
428                 scsiPhyTx32(fifoData[i + 94 + k], fifoData[i + k + 95]);\r
429 \r
430                 scsiPhyTx32(fifoData[i + 96 + k], fifoData[i + k + 97]);\r
431                 scsiPhyTx32(fifoData[i + 98 + k], fifoData[i + k + 99]);\r
432                 scsiPhyTx32(fifoData[i + 100 + k], fifoData[i + k + 101]);\r
433                 scsiPhyTx32(fifoData[i + 102 + k], fifoData[i + k + 103]);\r
434                 scsiPhyTx32(fifoData[i + 104 + k], fifoData[i + k + 105]);\r
435                 scsiPhyTx32(fifoData[i + 106 + k], fifoData[i + k + 107]);\r
436                 scsiPhyTx32(fifoData[i + 108 + k], fifoData[i + k + 109]);\r
437                 scsiPhyTx32(fifoData[i + 110 + k], fifoData[i + k + 111]);\r
438                 scsiPhyTx32(fifoData[i + 112 + k], fifoData[i + k + 113]);\r
439                 scsiPhyTx32(fifoData[i + 114 + k], fifoData[i + k + 115]);\r
440                 scsiPhyTx32(fifoData[i + 116 + k], fifoData[i + k + 117]);\r
441                 scsiPhyTx32(fifoData[i + 118 + k], fifoData[i + k + 119]);\r
442                 scsiPhyTx32(fifoData[i + 120 + k], fifoData[i + k + 121]);\r
443                 scsiPhyTx32(fifoData[i + 122 + k], fifoData[i + k + 123]);\r
444                 scsiPhyTx32(fifoData[i + 124 + k], fifoData[i + k + 125]);\r
445 \r
446                 // Last write must be 16bit to avoid having data waiting in the AHB bus\r
447                 // somewhere still waiting to be written while we're off checking\r
448                 // for empty fifos\r
449                 // Note also that the fmc fifo is disabled on stm32f446 because it's too big\r
450                 // (64 bytes) and we may think the fpga fifo is empty even though\r
451                 // there's pending writes\r
452                 scsiPhyTx(fifoData[i + 126 + k]);\r
453                 scsiPhyTx(fifoData[i + k + 127]);\r
454 \r
455             }\r
456 \r
457             i += chunk16;\r
458         }\r
459         else\r
460         {\r
461             uint32_t chunk16 = count16 - i;\r
462 \r
463             uint32_t k = 0;\r
464             // Note that last 4 bytes will fall through to next loop, which avoids\r
465             // ending on a 32bit write.\r
466             for (; k + 4 < chunk16; k += 4)\r
467             {\r
468                 scsiPhyTx32(fifoData[i + k], fifoData[i + k + 1]);\r
469                 scsiPhyTx32(fifoData[i + k + 2], fifoData[i + k + 3]);\r
470             }\r
471             for (; k < chunk16; ++k)\r
472             {\r
473                 scsiPhyTx(fifoData[i + k]);\r
474             }\r
475             i += chunk16;\r
476         }\r
477     }\r
478 }\r
479 \r
480 \r
481 void\r
482 scsiWrite(const uint8_t* data, uint32_t count)\r
483 {\r
484     int i = 0;\r
485     while (i < count && likely(!scsiDev.resetFlag))\r
486     {\r
487         uint32_t chunk = ((count - i) > SCSI_XFER_MAX)\r
488             ? SCSI_XFER_MAX : (count - i);\r
489         scsiSetDataCount(chunk);\r
490 \r
491         scsiWritePIO(data + i, chunk);\r
492 \r
493         while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))\r
494         {\r
495             __disable_irq();\r
496             if (!scsiPhyComplete() && likely(!scsiDev.resetFlag))\r
497             {\r
498                 __WFI();\r
499             }\r
500             __enable_irq();\r
501         }\r
502 \r
503         i += chunk;\r
504     }\r
505 }\r
506 \r
507 static inline void busSettleDelay(void)\r
508 {\r
509     // Data Release time (switching IO) = 400ns\r
510     // + Bus Settle time (switching phase) = 400ns.\r
511     s2s_delay_us(1); // Close enough.\r
512 }\r
513 \r
514 void scsiEnterBusFree()\r
515 {\r
516     *SCSI_CTRL_BSY = 0x00;\r
517     // We now have a Bus Clear Delay of 800ns to release remaining signals.\r
518     *SCSI_CTRL_PHASE = 0;\r
519 }\r
520 \r
521 static void\r
522 scsiSetTiming(\r
523     uint8_t assertClocks,\r
524     uint8_t deskew,\r
525     uint8_t hold,\r
526     uint8_t glitch)\r
527 {\r
528     *SCSI_CTRL_DESKEW = ((hold & 7) << 5) | (deskew & 0x1F);\r
529     *SCSI_CTRL_TIMING = (assertClocks & 0x3F);\r
530     *SCSI_CTRL_TIMING3 = (glitch & 0xF);\r
531 }\r
532 \r
533 static void\r
534 scsiSetDefaultTiming()\r
535 {\r
536     const uint8_t* asyncTiming = asyncTimings[0];\r
537     scsiSetTiming(\r
538         asyncTiming[0],\r
539         asyncTiming[1],\r
540         asyncTiming[2],\r
541         asyncTiming[3]);\r
542 }\r
543 \r
544 void scsiEnterPhase(int newPhase)\r
545 {\r
546     uint32_t delay = scsiEnterPhaseImmediate(newPhase);\r
547     if (delay > 0)\r
548     {\r
549         s2s_delay_us(delay);\r
550     }\r
551 }\r
552 \r
553 // Returns microsecond delay\r
554 uint32_t scsiEnterPhaseImmediate(int newPhase)\r
555 {\r
556     // ANSI INCITS 362-2002 SPI-3 10.7.1:\r
557     // Phase changes are not allowed while REQ or ACK is asserted.\r
558     while (likely(!scsiDev.resetFlag) && scsiStatusACK()) {}\r
559 \r
560     int oldPhase = *SCSI_CTRL_PHASE;\r
561 \r
562     if (newPhase != oldPhase)\r
563     {\r
564         if ((newPhase == DATA_IN || newPhase == DATA_OUT) &&\r
565             scsiDev.target->syncOffset)\r
566         {\r
567             if (scsiDev.target->syncPeriod < 23)\r
568             {\r
569                 scsiSetTiming(SCSI_FAST20_ASSERT, SCSI_FAST20_DESKEW, SCSI_FAST20_HOLD, 1);\r
570             }\r
571             else if (scsiDev.target->syncPeriod <= 25)\r
572             {\r
573                 if (newPhase == DATA_IN)\r
574                 {\r
575                     scsiSetTiming(SCSI_FAST10_WRITE_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);\r
576                 }\r
577                 else\r
578                 {\r
579                     scsiSetTiming(SCSI_FAST10_READ_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);\r
580                 }\r
581             }\r
582             else\r
583             {\r
584                 // Amiga A3000 OS3.9 sets period to 35 and fails with\r
585                 // glitch == 1.\r
586                 int glitch =\r
587                     scsiDev.target->syncPeriod < 35 ? 1 :\r
588                         (scsiDev.target->syncPeriod < 45 ? 2 : 5);\r
589                 int deskew = syncDeskew(scsiDev.target->syncPeriod);\r
590                 int assertion;\r
591                 if (newPhase == DATA_IN)\r
592                 {\r
593                     assertion = syncAssertionWrite(scsiDev.target->syncPeriod, deskew);\r
594                 }\r
595                 else\r
596                 {\r
597                     assertion = syncAssertionRead(scsiDev.target->syncPeriod);\r
598                 }\r
599                 scsiSetTiming(\r
600                     assertion,\r
601                     deskew,\r
602                     syncHold(scsiDev.target->syncPeriod),\r
603                     glitch);\r
604             }\r
605 \r
606             *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset;\r
607         }\r
608         else if (newPhase >= 0)\r
609         {\r
610 \r
611             *SCSI_CTRL_SYNC_OFFSET = 0;\r
612             const uint8_t* asyncTiming;\r
613 \r
614             if (scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_NoLimit)\r
615             {\r
616                 asyncTiming = asyncTimings[SCSI_ASYNC_SAFE];\r
617             }\r
618             else if (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_TURBO)\r
619             {\r
620                 asyncTiming = asyncTimings[SCSI_ASYNC_TURBO];\r
621             }\r
622             else if (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_ASYNC_50)\r
623             {\r
624                 asyncTiming = asyncTimings[SCSI_ASYNC_50];\r
625             } else if (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_ASYNC_33) {\r
626 \r
627                 asyncTiming = asyncTimings[SCSI_ASYNC_33];\r
628 \r
629             } else {\r
630                 asyncTiming = asyncTimings[SCSI_ASYNC_15];\r
631             }\r
632             scsiSetTiming(\r
633                 asyncTiming[0],\r
634                 asyncTiming[1],\r
635                 asyncTiming[2],\r
636                 asyncTiming[3]);\r
637         }\r
638 \r
639         uint32_t delayUs = 0;\r
640         if (newPhase >= 0)\r
641         {\r
642             *SCSI_CTRL_PHASE = newPhase;\r
643             delayUs += 1; // busSettleDelay\r
644 \r
645             if (scsiDev.compatMode < COMPAT_SCSI2)\r
646             {\r
647                 // EMU EMAX needs 100uS ! 10uS is not enough.\r
648                 delayUs += 100;\r
649             }\r
650         }\r
651         else\r
652         {\r
653             *SCSI_CTRL_PHASE = 0;\r
654         }\r
655 \r
656         return delayUs;\r
657     }\r
658 \r
659     return 0; // No change\r
660 }\r
661 \r
662 // Returns a "safe" estimate of the host SCSI speed of\r
663 // theoretical speed / 2\r
664 uint32_t s2s_getScsiRateKBs()\r
665 {\r
666     if (scsiDev.target->syncOffset)\r
667     {\r
668         if (scsiDev.target->syncPeriod < 23)\r
669         {\r
670             return 20 / 2;\r
671         }\r
672         else if (scsiDev.target->syncPeriod <= 25)\r
673         {\r
674             return 10 / 2;\r
675         }\r
676         else\r
677         {\r
678             // 1000000000 / (scsiDev.target->syncPeriod * 4) bytes per second\r
679             // (1000000000 / (scsiDev.target->syncPeriod * 4)) / 1000  kB/s\r
680             return (1000000 / (scsiDev.target->syncPeriod * 4)) / 2;\r
681         }\r
682     }\r
683     else\r
684     {\r
685         return 0;\r
686     }\r
687 }\r
688 \r
689 \r
690 void scsiPhyReset()\r
691 {\r
692     if (dmaInProgress)\r
693     {\r
694         HAL_DMA_Abort(&memToFSMC);\r
695         HAL_DMA_Abort(&fsmcToMem);\r
696 \r
697         dmaInProgress = 0;\r
698     }\r
699 \r
700     s2s_fpgaReset(); // Clears fifos etc.\r
701 \r
702     *SCSI_CTRL_PHASE = 0x00;\r
703     *SCSI_CTRL_BSY = 0x00;\r
704     *SCSI_CTRL_DBX = 0;\r
705 \r
706     *SCSI_CTRL_SYNC_OFFSET = 0;\r
707     scsiSetDefaultTiming();\r
708 \r
709     // DMA Benchmark code\r
710     // Currently 14.9MB/s.\r
711     #ifdef DMA_BENCHMARK\r
712     while(1)\r
713     {\r
714         s2s_ledOn();\r
715         // 100MB\r
716         for (int i = 0; i < (100LL * 1024 * 1024 / SCSI_FIFO_DEPTH); ++i)\r
717         {\r
718             HAL_DMA_Start(\r
719                 &memToFSMC,\r
720                 (uint32_t) &scsiDev.data[0],\r
721                 (uint32_t) SCSI_FIFO_DATA,\r
722                 SCSI_FIFO_DEPTH / 4);\r
723 \r
724             HAL_DMA_PollForTransfer(\r
725                 &memToFSMC,\r
726                 HAL_DMA_FULL_TRANSFER,\r
727                 0xffffffff);\r
728 \r
729             s2s_fpgaReset();\r
730         }\r
731         s2s_ledOff();\r
732 \r
733         for(int i = 0; i < 10; ++i) s2s_delay_ms(1000);\r
734     }\r
735     #endif\r
736 \r
737     // PIO Benchmark code\r
738     // Currently 16.7MB/s.\r
739     //#define PIO_BENCHMARK 1\r
740     #ifdef PIO_BENCHMARK\r
741     while(1)\r
742     {\r
743         s2s_ledOn();\r
744 \r
745         scsiEnterPhase(DATA_IN); // Need IO flag set for fifo ready flag\r
746 \r
747         // 100MB\r
748         for (int i = 0; i < (100LL * 1024 * 1024 / SCSI_FIFO_DEPTH); ++i)\r
749         {\r
750             scsiSetDataCount(1); // Resets fifos.\r
751 \r
752             // Shouldn't block\r
753             scsiDev.resetFlag = 0;\r
754             scsiWritePIO(&scsiDev.data[0], SCSI_FIFO_DEPTH);\r
755         }\r
756         s2s_ledOff();\r
757 \r
758         for(int i = 0; i < 10; ++i) s2s_delay_ms(1000);\r
759     }\r
760     #endif\r
761 \r
762     #ifdef SCSI_FREQ_TEST\r
763     while(1)\r
764     {\r
765         *SCSI_CTRL_DBX = 0xAA;\r
766         *SCSI_CTRL_DBX = 0x55;\r
767     }\r
768     #endif\r
769 }\r
770 \r
771 static void scsiPhyInitDMA()\r
772 {\r
773     // One-time init only.\r
774     static uint8_t init = 0;\r
775     if (init == 0)\r
776     {\r
777         init = 1;\r
778 \r
779         // Memory to memory transfers can only be done using DMA2\r
780         __DMA2_CLK_ENABLE();\r
781 \r
782         // Transmit SCSI data. The source data is treated as the\r
783         // peripheral (even though this is memory-to-memory)\r
784         memToFSMC.Instance = DMA2_Stream0;\r
785         memToFSMC.Init.Channel = DMA_CHANNEL_0;\r
786         memToFSMC.Init.Direction = DMA_MEMORY_TO_MEMORY;\r
787         memToFSMC.Init.PeriphInc = DMA_PINC_ENABLE;\r
788         memToFSMC.Init.MemInc = DMA_MINC_DISABLE;\r
789         memToFSMC.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;\r
790         memToFSMC.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;\r
791         memToFSMC.Init.Mode = DMA_NORMAL;\r
792         memToFSMC.Init.Priority = DMA_PRIORITY_LOW;\r
793         // FIFO mode is needed to allow conversion from 32bit words to the\r
794         // 16bit FSMC interface.\r
795         memToFSMC.Init.FIFOMode = DMA_FIFOMODE_ENABLE;\r
796 \r
797         // We only use 1 word (4 bytes) in the fifo at a time. Normally it's\r
798         // better to let the DMA fifo fill up then do burst transfers, but\r
799         // bursting out the FSMC interface will be very slow and may starve\r
800         // other (faster) transfers. We don't want to risk the SDIO transfers\r
801         // from overrun/underrun conditions.\r
802         memToFSMC.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;\r
803         memToFSMC.Init.MemBurst = DMA_MBURST_SINGLE;\r
804         memToFSMC.Init.PeriphBurst = DMA_PBURST_SINGLE;\r
805         HAL_DMA_Init(&memToFSMC);\r
806 \r
807         // Receive SCSI data. The source data (fsmc) is treated as the\r
808         // peripheral (even though this is memory-to-memory)\r
809         fsmcToMem.Instance = DMA2_Stream1;\r
810         fsmcToMem.Init.Channel = DMA_CHANNEL_0;\r
811         fsmcToMem.Init.Direction = DMA_MEMORY_TO_MEMORY;\r
812         fsmcToMem.Init.PeriphInc = DMA_PINC_DISABLE;\r
813         fsmcToMem.Init.MemInc = DMA_MINC_ENABLE;\r
814         fsmcToMem.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;\r
815         fsmcToMem.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;\r
816         fsmcToMem.Init.Mode = DMA_NORMAL;\r
817         fsmcToMem.Init.Priority = DMA_PRIORITY_LOW;\r
818         fsmcToMem.Init.FIFOMode = DMA_FIFOMODE_ENABLE;\r
819         fsmcToMem.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;\r
820         fsmcToMem.Init.MemBurst = DMA_MBURST_SINGLE;\r
821         fsmcToMem.Init.PeriphBurst = DMA_PBURST_SINGLE;\r
822         HAL_DMA_Init(&fsmcToMem);\r
823 \r
824         // TODO configure IRQs\r
825     }\r
826 }\r
827 \r
828 \r
829 void scsiPhyInit()\r
830 {\r
831     scsiPhyInitDMA();\r
832 \r
833     *SCSI_CTRL_IDMASK = 0x00; // Reset in scsiPhyConfig\r
834     *SCSI_CTRL_PHASE = 0x00;\r
835     *SCSI_CTRL_BSY = 0x00;\r
836     *SCSI_CTRL_DBX = 0;\r
837 \r
838     *SCSI_CTRL_SYNC_OFFSET = 0;\r
839     scsiSetDefaultTiming();\r
840 \r
841     *SCSI_CTRL_SEL_TIMING = SCSI_DEFAULT_SELECTION;\r
842 \r
843 }\r
844 \r
845 void scsiPhyConfig()\r
846 {\r
847     if (scsiDev.boardCfg.flags6 & S2S_CFG_ENABLE_TERMINATOR)\r
848     {\r
849         HAL_GPIO_WritePin(nTERM_EN_GPIO_Port, nTERM_EN_Pin, GPIO_PIN_RESET);\r
850     }\r
851     else\r
852     {\r
853         HAL_GPIO_WritePin(nTERM_EN_GPIO_Port, nTERM_EN_Pin, GPIO_PIN_SET);\r
854     }\r
855 \r
856 \r
857     uint8_t idMask = 0;\r
858     for (int i = 0; i < 8; ++i)\r
859     {\r
860         const S2S_TargetCfg* cfg = s2s_getConfigById(i);\r
861         if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))\r
862         {\r
863             idMask |= (1 << i);\r
864         }\r
865     }\r
866     *SCSI_CTRL_IDMASK = idMask;\r
867 \r
868     *SCSI_CTRL_FLAGS =\r
869         ((scsiDev.boardCfg.flags & S2S_CFG_DISABLE_GLITCH) ?\r
870             SCSI_CTRL_FLAGS_DISABLE_GLITCH : 0) |\r
871         ((scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) ?\r
872             SCSI_CTRL_FLAGS_ENABLE_PARITY : 0);\r
873 \r
874     *SCSI_CTRL_SEL_TIMING =\r
875         (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_SEL_LATCH) ?\r
876             SCSI_FAST_SELECTION : SCSI_DEFAULT_SELECTION;\r
877 }\r
878 \r
879 \r
880 // 1 = DBx error\r
881 // 2 = Parity error\r
882 // 4 = MSG error\r
883 // 8 = CD error\r
884 // 16 = IO error\r
885 // 32 = other error\r
886 // 64 = fpga comms error\r
887 int scsiSelfTest()\r
888 {\r
889     if (scsiDev.phase != BUS_FREE)\r
890     {\r
891         return 32;\r
892     }\r
893 \r
894     // Acquire the SCSI bus.\r
895     for (int i = 0; i < 100; ++i)\r
896     {\r
897         if (scsiStatusBSY())\r
898         {\r
899             s2s_delay_ms(1);\r
900         }\r
901     }\r
902     if (scsiStatusBSY())\r
903     {\r
904         // Error, couldn't acquire scsi bus\r
905         return 32;\r
906     }\r
907     *SCSI_CTRL_BSY = 1;\r
908     s2s_delay_ms(1);\r
909     if (! scsiStatusBSY())\r
910     {\r
911         *SCSI_CTRL_BSY = 0;\r
912 \r
913         // Error, BSY doesn't work.\r
914         return 32;\r
915     }\r
916 \r
917     // Should be safe to use the bus now.\r
918 \r
919     int result = 0;\r
920 \r
921     *SCSI_CTRL_DBX = 0;\r
922     busSettleDelay();\r
923     if ((*SCSI_STS_DBX & 0xff) != 0)\r
924     {\r
925         result = 1;\r
926     }\r
927 \r
928     *SCSI_CTRL_BSY = 0;\r
929 \r
930     return result;\r
931 }\r
932 \r