1 // Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
\r
3 // This file is part of SCSI2SD.
\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
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
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
19 #include "stm32f2xx.h"
\r
20 #include "stm32f2xx_hal.h"
\r
21 #include "stm32f2xx_hal_dma.h"
\r
23 #define FMC_NORSRAM_TimingTypeDef FSMC_NORSRAM_TimingTypeDef
\r
24 #define FMC_ACCESS_MODE_A FSMC_ACCESS_MODE_A
\r
25 #define FMC_NORSRAM_Timing_Init FSMC_NORSRAM_Timing_Init
\r
26 #define FMC_NORSRAM_DEVICE FSMC_NORSRAM_DEVICE
\r
30 #include "stm32f4xx.h"
\r
31 #include "stm32f4xx_hal.h"
\r
32 #include "stm32f4xx_hal_dma.h"
\r
39 #include "scsiPhy.h"
\r
46 #define SCSI_ASYNC_15 0
\r
47 #define SCSI_ASYNC_33 1
\r
48 #define SCSI_ASYNC_50 2
\r
49 #define SCSI_ASYNC_SAFE 3
\r
50 #define SCSI_ASYNC_TURBO 4
\r
53 #include "scsiPhyTiming108MHz.h"
\r
57 #include "scsiPhyTiming90MHz.h"
\r
60 // Private DMA variables.
\r
61 static int dmaInProgress = 0;
\r
63 static DMA_HandleTypeDef memToFSMC;
\r
64 static DMA_HandleTypeDef fsmcToMem;
\r
67 volatile uint8_t scsiRxDMAComplete;
\r
68 volatile uint8_t scsiTxDMAComplete;
\r
70 // scsi IRQ handler is initialised by the STM32 HAL. Connected to
\r
72 // Note: naming is important to ensure this function is listed in the
\r
74 void EXTI4_IRQHandler()
\r
76 // Make sure that interrupt flag is set
\r
77 if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_4) != RESET) {
\r
79 // Clear interrupt flag
\r
80 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4);
\r
82 uint8_t statusFlags = *SCSI_STS_SCSI;
\r
84 scsiDev.resetFlag = scsiDev.resetFlag || (statusFlags & 0x04);
\r
86 // selFlag is required for Philips P2000C which releases it after 600ns
\r
87 // without waiting for BSY.
\r
88 // Also required for some early Mac Plus roms
\r
89 if (statusFlags & 0x08) // Check SEL flag
\r
91 scsiDev.selFlag = *SCSI_STS_SELECTED;
\r
97 scsiSetDataCount(uint32_t count)
\r
99 *SCSI_DATA_CNT_HI = (count >> 16) & 0xff;
\r
100 *SCSI_DATA_CNT_MID = (count >> 8) & 0xff;
\r
101 *SCSI_DATA_CNT_LO = count & 0xff;
\r
102 *SCSI_DATA_CNT_SET = 1;
\r
110 int scsiFifoReady(void)
\r
113 uint8_t test1 = HAL_GPIO_ReadPin(GPIOE, FPGA_GPIO3_Pin);
\r
120 uint8_t test2 = HAL_GPIO_ReadPin(GPIOE, FPGA_GPIO3_Pin);
\r
121 return test1 != 0 && test2 != 0;
\r
127 scsiSetDataCount(1);
\r
129 // Ready immediately. setDataCount resets fifos
\r
132 while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
134 //__WFI(); // Wait for interrupt
\r
138 uint8_t val = scsiPhyRx();
\r
139 // TODO scsiDev.parityError = scsiDev.parityError || SCSI_Parity_Error_Read();
\r
146 scsiReadPIO(uint8_t* data, uint32_t count, int* parityError)
\r
148 uint16_t* fifoData = (uint16_t*)data;
\r
149 uint32_t count16 = (count + 1) / 2;
\r
152 while ((i < count16) && likely(!scsiDev.resetFlag))
\r
154 // Wait until FIFO is full (or complete)
\r
155 while (!scsiFifoReady() && likely(!scsiDev.resetFlag))
\r
160 if (count16 - i >= SCSI_FIFO_DEPTH16)
\r
162 uint32_t chunk16 = SCSI_FIFO_DEPTH16;
\r
164 // Let gcc unroll the loop as much as possible.
\r
165 for (uint32_t k = 0; k + 128 <= chunk16; k += 128)
\r
167 fifoData[i + k] = scsiPhyRx();
\r
168 fifoData[i + k + 1] = scsiPhyRx();
\r
169 fifoData[i + k + 2] = scsiPhyRx();
\r
170 fifoData[i + k + 3] = scsiPhyRx();
\r
171 fifoData[i + k + 4] = scsiPhyRx();
\r
172 fifoData[i + k + 5] = scsiPhyRx();
\r
173 fifoData[i + k + 6] = scsiPhyRx();
\r
174 fifoData[i + k + 7] = scsiPhyRx();
\r
175 fifoData[i + k + 8] = scsiPhyRx();
\r
176 fifoData[i + k + 9] = scsiPhyRx();
\r
177 fifoData[i + k + 10] = scsiPhyRx();
\r
178 fifoData[i + k + 11] = scsiPhyRx();
\r
179 fifoData[i + k + 12] = scsiPhyRx();
\r
180 fifoData[i + k + 13] = scsiPhyRx();
\r
181 fifoData[i + k + 14] = scsiPhyRx();
\r
182 fifoData[i + k + 15] = scsiPhyRx();
\r
183 fifoData[i + k + 16] = scsiPhyRx();
\r
184 fifoData[i + k + 17] = scsiPhyRx();
\r
185 fifoData[i + k + 18] = scsiPhyRx();
\r
186 fifoData[i + k + 19] = scsiPhyRx();
\r
187 fifoData[i + k + 20] = scsiPhyRx();
\r
188 fifoData[i + k + 21] = scsiPhyRx();
\r
189 fifoData[i + k + 22] = scsiPhyRx();
\r
190 fifoData[i + k + 23] = scsiPhyRx();
\r
191 fifoData[i + k + 24] = scsiPhyRx();
\r
192 fifoData[i + k + 25] = scsiPhyRx();
\r
193 fifoData[i + k + 26] = scsiPhyRx();
\r
194 fifoData[i + k + 27] = scsiPhyRx();
\r
195 fifoData[i + k + 28] = scsiPhyRx();
\r
196 fifoData[i + k + 29] = scsiPhyRx();
\r
197 fifoData[i + k + 30] = scsiPhyRx();
\r
198 fifoData[i + k + 31] = scsiPhyRx();
\r
199 fifoData[i + k + 32] = scsiPhyRx();
\r
200 fifoData[i + k + 33] = scsiPhyRx();
\r
201 fifoData[i + k + 34] = scsiPhyRx();
\r
202 fifoData[i + k + 35] = scsiPhyRx();
\r
203 fifoData[i + k + 36] = scsiPhyRx();
\r
204 fifoData[i + k + 37] = scsiPhyRx();
\r
205 fifoData[i + k + 38] = scsiPhyRx();
\r
206 fifoData[i + k + 39] = scsiPhyRx();
\r
207 fifoData[i + k + 40] = scsiPhyRx();
\r
208 fifoData[i + k + 41] = scsiPhyRx();
\r
209 fifoData[i + k + 42] = scsiPhyRx();
\r
210 fifoData[i + k + 43] = scsiPhyRx();
\r
211 fifoData[i + k + 44] = scsiPhyRx();
\r
212 fifoData[i + k + 45] = scsiPhyRx();
\r
213 fifoData[i + k + 46] = scsiPhyRx();
\r
214 fifoData[i + k + 47] = scsiPhyRx();
\r
215 fifoData[i + k + 48] = scsiPhyRx();
\r
216 fifoData[i + k + 49] = scsiPhyRx();
\r
217 fifoData[i + k + 50] = scsiPhyRx();
\r
218 fifoData[i + k + 51] = scsiPhyRx();
\r
219 fifoData[i + k + 52] = scsiPhyRx();
\r
220 fifoData[i + k + 53] = scsiPhyRx();
\r
221 fifoData[i + k + 54] = scsiPhyRx();
\r
222 fifoData[i + k + 55] = scsiPhyRx();
\r
223 fifoData[i + k + 56] = scsiPhyRx();
\r
224 fifoData[i + k + 57] = scsiPhyRx();
\r
225 fifoData[i + k + 58] = scsiPhyRx();
\r
226 fifoData[i + k + 59] = scsiPhyRx();
\r
227 fifoData[i + k + 60] = scsiPhyRx();
\r
228 fifoData[i + k + 61] = scsiPhyRx();
\r
229 fifoData[i + k + 62] = scsiPhyRx();
\r
230 fifoData[i + k + 63] = scsiPhyRx();
\r
231 fifoData[i + k + 64] = scsiPhyRx();
\r
232 fifoData[i + k + 65] = scsiPhyRx();
\r
233 fifoData[i + k + 66] = scsiPhyRx();
\r
234 fifoData[i + k + 67] = scsiPhyRx();
\r
235 fifoData[i + k + 68] = scsiPhyRx();
\r
236 fifoData[i + k + 69] = scsiPhyRx();
\r
237 fifoData[i + k + 70] = scsiPhyRx();
\r
238 fifoData[i + k + 71] = scsiPhyRx();
\r
239 fifoData[i + k + 72] = scsiPhyRx();
\r
240 fifoData[i + k + 73] = scsiPhyRx();
\r
241 fifoData[i + k + 74] = scsiPhyRx();
\r
242 fifoData[i + k + 75] = scsiPhyRx();
\r
243 fifoData[i + k + 76] = scsiPhyRx();
\r
244 fifoData[i + k + 77] = scsiPhyRx();
\r
245 fifoData[i + k + 78] = scsiPhyRx();
\r
246 fifoData[i + k + 79] = scsiPhyRx();
\r
247 fifoData[i + k + 80] = scsiPhyRx();
\r
248 fifoData[i + k + 81] = scsiPhyRx();
\r
249 fifoData[i + k + 82] = scsiPhyRx();
\r
250 fifoData[i + k + 83] = scsiPhyRx();
\r
251 fifoData[i + k + 84] = scsiPhyRx();
\r
252 fifoData[i + k + 85] = scsiPhyRx();
\r
253 fifoData[i + k + 86] = scsiPhyRx();
\r
254 fifoData[i + k + 87] = scsiPhyRx();
\r
255 fifoData[i + k + 88] = scsiPhyRx();
\r
256 fifoData[i + k + 89] = scsiPhyRx();
\r
257 fifoData[i + k + 90] = scsiPhyRx();
\r
258 fifoData[i + k + 91] = scsiPhyRx();
\r
259 fifoData[i + k + 92] = scsiPhyRx();
\r
260 fifoData[i + k + 93] = scsiPhyRx();
\r
261 fifoData[i + k + 94] = scsiPhyRx();
\r
262 fifoData[i + k + 95] = scsiPhyRx();
\r
263 fifoData[i + k + 96] = scsiPhyRx();
\r
264 fifoData[i + k + 97] = scsiPhyRx();
\r
265 fifoData[i + k + 98] = scsiPhyRx();
\r
266 fifoData[i + k + 99] = scsiPhyRx();
\r
267 fifoData[i + k + 100] = scsiPhyRx();
\r
268 fifoData[i + k + 101] = scsiPhyRx();
\r
269 fifoData[i + k + 102] = scsiPhyRx();
\r
270 fifoData[i + k + 103] = scsiPhyRx();
\r
271 fifoData[i + k + 104] = scsiPhyRx();
\r
272 fifoData[i + k + 105] = scsiPhyRx();
\r
273 fifoData[i + k + 106] = scsiPhyRx();
\r
274 fifoData[i + k + 107] = scsiPhyRx();
\r
275 fifoData[i + k + 108] = scsiPhyRx();
\r
276 fifoData[i + k + 109] = scsiPhyRx();
\r
277 fifoData[i + k + 110] = scsiPhyRx();
\r
278 fifoData[i + k + 111] = scsiPhyRx();
\r
279 fifoData[i + k + 112] = scsiPhyRx();
\r
280 fifoData[i + k + 113] = scsiPhyRx();
\r
281 fifoData[i + k + 114] = scsiPhyRx();
\r
282 fifoData[i + k + 115] = scsiPhyRx();
\r
283 fifoData[i + k + 116] = scsiPhyRx();
\r
284 fifoData[i + k + 117] = scsiPhyRx();
\r
285 fifoData[i + k + 118] = scsiPhyRx();
\r
286 fifoData[i + k + 119] = scsiPhyRx();
\r
287 fifoData[i + k + 120] = scsiPhyRx();
\r
288 fifoData[i + k + 121] = scsiPhyRx();
\r
289 fifoData[i + k + 122] = scsiPhyRx();
\r
290 fifoData[i + k + 123] = scsiPhyRx();
\r
291 fifoData[i + k + 124] = scsiPhyRx();
\r
292 fifoData[i + k + 125] = scsiPhyRx();
\r
293 fifoData[i + k + 126] = scsiPhyRx();
\r
294 fifoData[i + k + 127] = scsiPhyRx();
\r
301 uint32_t chunk16 = count16 - i;
\r
304 for (; k + 4 <= chunk16; k += 4)
\r
306 fifoData[i + k] = scsiPhyRx();
\r
307 fifoData[i + 1 + k] = scsiPhyRx();
\r
308 fifoData[i + 2 + k] = scsiPhyRx();
\r
309 fifoData[i + 3 + k] = scsiPhyRx();
\r
311 for (; k < chunk16; ++k)
\r
313 fifoData[i + k] = scsiPhyRx();
\r
319 *parityError |= scsiParityError();
\r
323 scsiRead(uint8_t* data, uint32_t count, int* parityError)
\r
328 while (i < count && likely(!scsiDev.resetFlag))
\r
330 uint32_t chunk = ((count - i) > SCSI_XFER_MAX)
\r
331 ? SCSI_XFER_MAX : (count - i);
\r
332 scsiSetDataCount(chunk);
\r
334 scsiReadPIO(data + i, chunk, parityError);
\r
336 while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
339 if (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
351 scsiWriteByte(uint8_t value)
\r
353 scsiSetDataCount(1);
\r
357 while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
365 scsiWritePIO(const uint8_t* data, uint32_t count)
\r
367 uint16_t* fifoData = (uint16_t*)data;
\r
368 uint32_t count16 = (count + 1) / 2;
\r
371 while ((i < count16) && likely(!scsiDev.resetFlag))
\r
373 while (!scsiFifoReady() && likely(!scsiDev.resetFlag))
\r
378 if (count16 - i >= SCSI_FIFO_DEPTH16)
\r
380 uint32_t chunk16 = SCSI_FIFO_DEPTH16;
\r
382 // Let gcc unroll the loop as much as possible.
\r
383 for (uint32_t k = 0; k + 128 <= chunk16; k += 128)
\r
385 scsiPhyTx32(fifoData[i + k], fifoData[i + k + 1]);
\r
386 scsiPhyTx32(fifoData[i + 2 + k], fifoData[i + k + 3]);
\r
387 scsiPhyTx32(fifoData[i + 4 + k], fifoData[i + k + 5]);
\r
388 scsiPhyTx32(fifoData[i + 6 + k], fifoData[i + k + 7]);
\r
389 scsiPhyTx32(fifoData[i + 8 + k], fifoData[i + k + 9]);
\r
390 scsiPhyTx32(fifoData[i + 10 + k], fifoData[i + k + 11]);
\r
391 scsiPhyTx32(fifoData[i + 12 + k], fifoData[i + k + 13]);
\r
392 scsiPhyTx32(fifoData[i + 14 + k], fifoData[i + k + 15]);
\r
393 scsiPhyTx32(fifoData[i + 16 + k], fifoData[i + k + 17]);
\r
394 scsiPhyTx32(fifoData[i + 18 + k], fifoData[i + k + 19]);
\r
395 scsiPhyTx32(fifoData[i + 20 + k], fifoData[i + k + 21]);
\r
396 scsiPhyTx32(fifoData[i + 22 + k], fifoData[i + k + 23]);
\r
397 scsiPhyTx32(fifoData[i + 24 + k], fifoData[i + k + 25]);
\r
398 scsiPhyTx32(fifoData[i + 26 + k], fifoData[i + k + 27]);
\r
399 scsiPhyTx32(fifoData[i + 28 + k], fifoData[i + k + 29]);
\r
400 scsiPhyTx32(fifoData[i + 30 + k], fifoData[i + k + 31]);
\r
402 scsiPhyTx32(fifoData[i + 32 + k], fifoData[i + k + 33]);
\r
403 scsiPhyTx32(fifoData[i + 34 + k], fifoData[i + k + 35]);
\r
404 scsiPhyTx32(fifoData[i + 36 + k], fifoData[i + k + 37]);
\r
405 scsiPhyTx32(fifoData[i + 38 + k], fifoData[i + k + 39]);
\r
406 scsiPhyTx32(fifoData[i + 40 + k], fifoData[i + k + 41]);
\r
407 scsiPhyTx32(fifoData[i + 42 + k], fifoData[i + k + 43]);
\r
408 scsiPhyTx32(fifoData[i + 44 + k], fifoData[i + k + 45]);
\r
409 scsiPhyTx32(fifoData[i + 46 + k], fifoData[i + k + 47]);
\r
410 scsiPhyTx32(fifoData[i + 48 + k], fifoData[i + k + 49]);
\r
411 scsiPhyTx32(fifoData[i + 50 + k], fifoData[i + k + 51]);
\r
412 scsiPhyTx32(fifoData[i + 52 + k], fifoData[i + k + 53]);
\r
413 scsiPhyTx32(fifoData[i + 54 + k], fifoData[i + k + 55]);
\r
414 scsiPhyTx32(fifoData[i + 56 + k], fifoData[i + k + 57]);
\r
415 scsiPhyTx32(fifoData[i + 58 + k], fifoData[i + k + 59]);
\r
416 scsiPhyTx32(fifoData[i + 60 + k], fifoData[i + k + 61]);
\r
417 scsiPhyTx32(fifoData[i + 62 + k], fifoData[i + k + 63]);
\r
419 scsiPhyTx32(fifoData[i + 64 + k], fifoData[i + k + 65]);
\r
420 scsiPhyTx32(fifoData[i + 66 + k], fifoData[i + k + 67]);
\r
421 scsiPhyTx32(fifoData[i + 68 + k], fifoData[i + k + 69]);
\r
422 scsiPhyTx32(fifoData[i + 70 + k], fifoData[i + k + 71]);
\r
423 scsiPhyTx32(fifoData[i + 72 + k], fifoData[i + k + 73]);
\r
424 scsiPhyTx32(fifoData[i + 74 + k], fifoData[i + k + 75]);
\r
425 scsiPhyTx32(fifoData[i + 76 + k], fifoData[i + k + 77]);
\r
426 scsiPhyTx32(fifoData[i + 78 + k], fifoData[i + k + 79]);
\r
427 scsiPhyTx32(fifoData[i + 80 + k], fifoData[i + k + 81]);
\r
428 scsiPhyTx32(fifoData[i + 82 + k], fifoData[i + k + 83]);
\r
429 scsiPhyTx32(fifoData[i + 84 + k], fifoData[i + k + 85]);
\r
430 scsiPhyTx32(fifoData[i + 86 + k], fifoData[i + k + 87]);
\r
431 scsiPhyTx32(fifoData[i + 88 + k], fifoData[i + k + 89]);
\r
432 scsiPhyTx32(fifoData[i + 90 + k], fifoData[i + k + 91]);
\r
433 scsiPhyTx32(fifoData[i + 92 + k], fifoData[i + k + 93]);
\r
434 scsiPhyTx32(fifoData[i + 94 + k], fifoData[i + k + 95]);
\r
436 scsiPhyTx32(fifoData[i + 96 + k], fifoData[i + k + 97]);
\r
437 scsiPhyTx32(fifoData[i + 98 + k], fifoData[i + k + 99]);
\r
438 scsiPhyTx32(fifoData[i + 100 + k], fifoData[i + k + 101]);
\r
439 scsiPhyTx32(fifoData[i + 102 + k], fifoData[i + k + 103]);
\r
440 scsiPhyTx32(fifoData[i + 104 + k], fifoData[i + k + 105]);
\r
441 scsiPhyTx32(fifoData[i + 106 + k], fifoData[i + k + 107]);
\r
442 scsiPhyTx32(fifoData[i + 108 + k], fifoData[i + k + 109]);
\r
443 scsiPhyTx32(fifoData[i + 110 + k], fifoData[i + k + 111]);
\r
444 scsiPhyTx32(fifoData[i + 112 + k], fifoData[i + k + 113]);
\r
445 scsiPhyTx32(fifoData[i + 114 + k], fifoData[i + k + 115]);
\r
446 scsiPhyTx32(fifoData[i + 116 + k], fifoData[i + k + 117]);
\r
447 scsiPhyTx32(fifoData[i + 118 + k], fifoData[i + k + 119]);
\r
448 scsiPhyTx32(fifoData[i + 120 + k], fifoData[i + k + 121]);
\r
449 scsiPhyTx32(fifoData[i + 122 + k], fifoData[i + k + 123]);
\r
450 scsiPhyTx32(fifoData[i + 124 + k], fifoData[i + k + 125]);
\r
451 scsiPhyTx32(fifoData[i + 126 + k], fifoData[i + k + 127]);
\r
458 uint32_t chunk16 = count16 - i;
\r
461 for (; k + 4 <= chunk16; k += 4)
\r
463 scsiPhyTx32(fifoData[i + k], fifoData[i + k + 1]);
\r
464 scsiPhyTx32(fifoData[i + k + 2], fifoData[i + k + 3]);
\r
466 for (; k < chunk16; ++k)
\r
468 scsiPhyTx(fifoData[i + k]);
\r
477 scsiWrite(const uint8_t* data, uint32_t count)
\r
480 while (i < count && likely(!scsiDev.resetFlag))
\r
482 uint32_t chunk = ((count - i) > SCSI_XFER_MAX)
\r
483 ? SCSI_XFER_MAX : (count - i);
\r
484 scsiSetDataCount(chunk);
\r
486 scsiWritePIO(data + i, chunk);
\r
488 while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
491 if (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
502 static inline void busSettleDelay(void)
\r
504 // Data Release time (switching IO) = 400ns
\r
505 // + Bus Settle time (switching phase) = 400ns.
\r
506 s2s_delay_us(1); // Close enough.
\r
509 void scsiEnterBusFree()
\r
511 *SCSI_CTRL_BSY = 0x00;
\r
512 // We now have a Bus Clear Delay of 800ns to release remaining signals.
\r
513 *SCSI_CTRL_PHASE = 0;
\r
518 uint8_t assertClocks,
\r
523 *SCSI_CTRL_DESKEW = ((hold & 7) << 5) | (deskew & 0x1F);
\r
524 *SCSI_CTRL_TIMING = (assertClocks & 0x3F);
\r
525 *SCSI_CTRL_TIMING3 = (glitch & 0xF);
\r
529 scsiSetDefaultTiming()
\r
531 const uint8_t* asyncTiming = asyncTimings[0];
\r
539 void scsiEnterPhase(int newPhase)
\r
541 uint32_t delay = scsiEnterPhaseImmediate(newPhase);
\r
544 s2s_delay_us(delay);
\r
548 // Returns microsecond delay
\r
549 uint32_t scsiEnterPhaseImmediate(int newPhase)
\r
551 // ANSI INCITS 362-2002 SPI-3 10.7.1:
\r
552 // Phase changes are not allowed while REQ or ACK is asserted.
\r
553 while (likely(!scsiDev.resetFlag) && scsiStatusACK()) {}
\r
555 int oldPhase = *SCSI_CTRL_PHASE;
\r
557 if (newPhase != oldPhase)
\r
559 if ((newPhase == DATA_IN || newPhase == DATA_OUT) &&
\r
560 scsiDev.target->syncOffset)
\r
562 if (scsiDev.target->syncPeriod < 23)
\r
564 scsiSetTiming(SCSI_FAST20_ASSERT, SCSI_FAST20_DESKEW, SCSI_FAST20_HOLD, 1);
\r
566 else if (scsiDev.target->syncPeriod <= 25)
\r
568 if (newPhase == DATA_IN)
\r
570 scsiSetTiming(SCSI_FAST10_WRITE_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);
\r
574 scsiSetTiming(SCSI_FAST10_READ_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);
\r
579 // Amiga A3000 OS3.9 sets period to 35 and fails with
\r
582 scsiDev.target->syncPeriod < 35 ? 1 :
\r
583 (scsiDev.target->syncPeriod < 45 ? 2 : 5);
\r
584 int deskew = syncDeskew(scsiDev.target->syncPeriod);
\r
586 if (newPhase == DATA_IN)
\r
588 assertion = syncAssertionWrite(scsiDev.target->syncPeriod, deskew);
\r
592 assertion = syncAssertionRead(scsiDev.target->syncPeriod);
\r
597 syncHold(scsiDev.target->syncPeriod),
\r
601 *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset;
\r
603 else if (newPhase >= 0)
\r
606 *SCSI_CTRL_SYNC_OFFSET = 0;
\r
607 const uint8_t* asyncTiming;
\r
609 if (scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_NoLimit)
\r
611 asyncTiming = asyncTimings[SCSI_ASYNC_SAFE];
\r
613 else if (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_TURBO)
\r
615 asyncTiming = asyncTimings[SCSI_ASYNC_TURBO];
\r
617 else if (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_ASYNC_50)
\r
619 asyncTiming = asyncTimings[SCSI_ASYNC_50];
\r
620 } else if (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_ASYNC_33) {
\r
622 asyncTiming = asyncTimings[SCSI_ASYNC_33];
\r
625 asyncTiming = asyncTimings[SCSI_ASYNC_15];
\r
634 uint32_t delayUs = 0;
\r
637 *SCSI_CTRL_PHASE = newPhase;
\r
638 delayUs += 1; // busSettleDelay
\r
640 if (scsiDev.compatMode < COMPAT_SCSI2)
\r
642 // EMU EMAX needs 100uS ! 10uS is not enough.
\r
648 *SCSI_CTRL_PHASE = 0;
\r
654 return 0; // No change
\r
657 // Returns a "safe" estimate of the host SCSI speed of
\r
658 // theoretical speed / 2
\r
659 uint32_t s2s_getScsiRateKBs()
\r
661 if (scsiDev.target->syncOffset)
\r
663 if (scsiDev.target->syncPeriod < 23)
\r
667 else if (scsiDev.target->syncPeriod <= 25)
\r
673 // 1000000000 / (scsiDev.target->syncPeriod * 4) bytes per second
\r
674 // (1000000000 / (scsiDev.target->syncPeriod * 4)) / 1000 kB/s
\r
675 return (1000000 / (scsiDev.target->syncPeriod * 4)) / 2;
\r
685 void scsiPhyReset()
\r
689 HAL_DMA_Abort(&memToFSMC);
\r
690 HAL_DMA_Abort(&fsmcToMem);
\r
695 s2s_fpgaReset(); // Clears fifos etc.
\r
697 *SCSI_CTRL_PHASE = 0x00;
\r
698 *SCSI_CTRL_BSY = 0x00;
\r
699 *SCSI_CTRL_DBX = 0;
\r
701 *SCSI_CTRL_SYNC_OFFSET = 0;
\r
702 scsiSetDefaultTiming();
\r
704 // DMA Benchmark code
\r
705 // Currently 14.9MB/s.
\r
706 #ifdef DMA_BENCHMARK
\r
711 for (int i = 0; i < (100LL * 1024 * 1024 / SCSI_FIFO_DEPTH); ++i)
\r
715 (uint32_t) &scsiDev.data[0],
\r
716 (uint32_t) SCSI_FIFO_DATA,
\r
717 SCSI_FIFO_DEPTH / 4);
\r
719 HAL_DMA_PollForTransfer(
\r
721 HAL_DMA_FULL_TRANSFER,
\r
728 for(int i = 0; i < 10; ++i) s2s_delay_ms(1000);
\r
732 // PIO Benchmark code
\r
733 // Currently 16.7MB/s.
\r
734 //#define PIO_BENCHMARK 1
\r
735 #ifdef PIO_BENCHMARK
\r
740 scsiEnterPhase(DATA_IN); // Need IO flag set for fifo ready flag
\r
743 for (int i = 0; i < (100LL * 1024 * 1024 / SCSI_FIFO_DEPTH); ++i)
\r
745 scsiSetDataCount(1); // Resets fifos.
\r
748 scsiDev.resetFlag = 0;
\r
749 scsiWritePIO(&scsiDev.data[0], SCSI_FIFO_DEPTH);
\r
753 for(int i = 0; i < 10; ++i) s2s_delay_ms(1000);
\r
757 #ifdef SCSI_FREQ_TEST
\r
760 *SCSI_CTRL_DBX = 0xAA;
\r
761 *SCSI_CTRL_DBX = 0x55;
\r
766 static void scsiPhyInitDMA()
\r
768 // One-time init only.
\r
769 static uint8_t init = 0;
\r
774 // Memory to memory transfers can only be done using DMA2
\r
775 __DMA2_CLK_ENABLE();
\r
777 // Transmit SCSI data. The source data is treated as the
\r
778 // peripheral (even though this is memory-to-memory)
\r
779 memToFSMC.Instance = DMA2_Stream0;
\r
780 memToFSMC.Init.Channel = DMA_CHANNEL_0;
\r
781 memToFSMC.Init.Direction = DMA_MEMORY_TO_MEMORY;
\r
782 memToFSMC.Init.PeriphInc = DMA_PINC_ENABLE;
\r
783 memToFSMC.Init.MemInc = DMA_MINC_DISABLE;
\r
784 memToFSMC.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
\r
785 memToFSMC.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
\r
786 memToFSMC.Init.Mode = DMA_NORMAL;
\r
787 memToFSMC.Init.Priority = DMA_PRIORITY_LOW;
\r
788 // FIFO mode is needed to allow conversion from 32bit words to the
\r
789 // 16bit FSMC interface.
\r
790 memToFSMC.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
\r
792 // We only use 1 word (4 bytes) in the fifo at a time. Normally it's
\r
793 // better to let the DMA fifo fill up then do burst transfers, but
\r
794 // bursting out the FSMC interface will be very slow and may starve
\r
795 // other (faster) transfers. We don't want to risk the SDIO transfers
\r
796 // from overrun/underrun conditions.
\r
797 memToFSMC.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
\r
798 memToFSMC.Init.MemBurst = DMA_MBURST_SINGLE;
\r
799 memToFSMC.Init.PeriphBurst = DMA_PBURST_SINGLE;
\r
800 HAL_DMA_Init(&memToFSMC);
\r
802 // Receive SCSI data. The source data (fsmc) is treated as the
\r
803 // peripheral (even though this is memory-to-memory)
\r
804 fsmcToMem.Instance = DMA2_Stream1;
\r
805 fsmcToMem.Init.Channel = DMA_CHANNEL_0;
\r
806 fsmcToMem.Init.Direction = DMA_MEMORY_TO_MEMORY;
\r
807 fsmcToMem.Init.PeriphInc = DMA_PINC_DISABLE;
\r
808 fsmcToMem.Init.MemInc = DMA_MINC_ENABLE;
\r
809 fsmcToMem.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
\r
810 fsmcToMem.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
\r
811 fsmcToMem.Init.Mode = DMA_NORMAL;
\r
812 fsmcToMem.Init.Priority = DMA_PRIORITY_LOW;
\r
813 fsmcToMem.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
\r
814 fsmcToMem.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
\r
815 fsmcToMem.Init.MemBurst = DMA_MBURST_SINGLE;
\r
816 fsmcToMem.Init.PeriphBurst = DMA_PBURST_SINGLE;
\r
817 HAL_DMA_Init(&fsmcToMem);
\r
819 // TODO configure IRQs
\r
828 *SCSI_CTRL_IDMASK = 0x00; // Reset in scsiPhyConfig
\r
829 *SCSI_CTRL_PHASE = 0x00;
\r
830 *SCSI_CTRL_BSY = 0x00;
\r
831 *SCSI_CTRL_DBX = 0;
\r
833 *SCSI_CTRL_SYNC_OFFSET = 0;
\r
834 scsiSetDefaultTiming();
\r
836 *SCSI_CTRL_SEL_TIMING = SCSI_DEFAULT_SELECTION;
\r
840 void scsiPhyConfig()
\r
842 if (scsiDev.boardCfg.flags6 & S2S_CFG_ENABLE_TERMINATOR)
\r
844 HAL_GPIO_WritePin(nTERM_EN_GPIO_Port, nTERM_EN_Pin, GPIO_PIN_RESET);
\r
848 HAL_GPIO_WritePin(nTERM_EN_GPIO_Port, nTERM_EN_Pin, GPIO_PIN_SET);
\r
851 uint8_t idMask = 0;
\r
852 for (int i = 0; i < 8; ++i)
\r
854 const S2S_TargetCfg* cfg = s2s_getConfigById(i);
\r
855 if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
\r
857 idMask |= (1 << i);
\r
860 *SCSI_CTRL_IDMASK = idMask;
\r
863 ((scsiDev.boardCfg.flags & S2S_CFG_DISABLE_GLITCH) ?
\r
864 SCSI_CTRL_FLAGS_DISABLE_GLITCH : 0) |
\r
865 ((scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) ?
\r
866 SCSI_CTRL_FLAGS_ENABLE_PARITY : 0);
\r
868 *SCSI_CTRL_SEL_TIMING =
\r
869 (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_SEL_LATCH) ?
\r
870 SCSI_FAST_SELECTION : SCSI_DEFAULT_SELECTION;
\r
874 // 2 = Parity error
\r
878 // 32 = other error
\r
879 // 64 = fpga comms error
\r
882 if (scsiDev.phase != BUS_FREE)
\r
887 // Acquire the SCSI bus.
\r
888 for (int i = 0; i < 100; ++i)
\r
890 if (scsiStatusBSY())
\r
895 if (scsiStatusBSY())
\r
897 // Error, couldn't acquire scsi bus
\r
900 *SCSI_CTRL_BSY = 1;
\r
902 if (! scsiStatusBSY())
\r
904 *SCSI_CTRL_BSY = 0;
\r
906 // Error, BSY doesn't work.
\r
910 // Should be safe to use the bus now.
\r
914 *SCSI_CTRL_DBX = 0;
\r
916 if ((*SCSI_STS_DBX & 0xff) != 0)
\r
921 *SCSI_CTRL_BSY = 0;
\r