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
25 #include "stm32f4xx.h"
\r
26 #include "stm32f4xx_hal.h"
\r
27 #include "stm32f4xx_hal_dma.h"
\r
33 #include "scsiPhy.h"
\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
47 #include "scsiPhyTiming108MHz.h"
\r
51 #include "scsiPhyTiming90MHz.h"
\r
54 // Private DMA variables.
\r
55 static int dmaInProgress = 0;
\r
57 static DMA_HandleTypeDef memToFSMC;
\r
58 static DMA_HandleTypeDef fsmcToMem;
\r
61 volatile uint8_t scsiRxDMAComplete;
\r
62 volatile uint8_t scsiTxDMAComplete;
\r
64 // scsi IRQ handler is initialised by the STM32 HAL. Connected to
\r
66 // Note: naming is important to ensure this function is listed in the
\r
68 void EXTI4_IRQHandler()
\r
70 // Make sure that interrupt flag is set
\r
71 if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_4) != RESET) {
\r
73 // Clear interrupt flag
\r
74 __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4);
\r
76 uint8_t statusFlags = *SCSI_STS_SCSI;
\r
78 scsiDev.resetFlag = scsiDev.resetFlag || (statusFlags & 0x04);
\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
85 scsiDev.selFlag = *SCSI_STS_SELECTED;
\r
91 scsiSetDataCount(uint32_t count)
\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
104 int scsiFifoReady(void)
\r
110 HAL_GPIO_ReadPin(GPIOE, FPGA_GPIO3_Pin);
\r
117 return HAL_GPIO_ReadPin(GPIOE, FPGA_GPIO3_Pin) != 0;
\r
123 scsiSetDataCount(1);
\r
125 // Ready immediately. setDataCount resets fifos
\r
128 while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
130 __WFI(); // Wait for interrupt
\r
134 uint8_t val = scsiPhyRx();
\r
135 // TODO scsiDev.parityError = scsiDev.parityError || SCSI_Parity_Error_Read();
\r
142 scsiReadPIO(uint8_t* data, uint32_t count, int* parityError)
\r
144 uint16_t* fifoData = (uint16_t*)data;
\r
145 uint32_t count16 = (count + 1) / 2;
\r
148 while ((i < count16) && likely(!scsiDev.resetFlag))
\r
150 // Wait until FIFO is full (or complete)
\r
151 while (!scsiFifoReady() && likely(!scsiDev.resetFlag))
\r
156 if (count16 - i >= SCSI_FIFO_DEPTH16)
\r
158 uint32_t chunk16 = SCSI_FIFO_DEPTH16;
\r
160 // Let gcc unroll the loop as much as possible.
\r
161 for (uint32_t k = 0; k + 128 <= chunk16; k += 128)
\r
163 fifoData[i + k] = scsiPhyRx();
\r
164 fifoData[i + k + 1] = scsiPhyRx();
\r
165 fifoData[i + k + 2] = scsiPhyRx();
\r
166 fifoData[i + k + 3] = scsiPhyRx();
\r
167 fifoData[i + k + 4] = scsiPhyRx();
\r
168 fifoData[i + k + 5] = scsiPhyRx();
\r
169 fifoData[i + k + 6] = scsiPhyRx();
\r
170 fifoData[i + k + 7] = scsiPhyRx();
\r
171 fifoData[i + k + 8] = scsiPhyRx();
\r
172 fifoData[i + k + 9] = scsiPhyRx();
\r
173 fifoData[i + k + 10] = scsiPhyRx();
\r
174 fifoData[i + k + 11] = scsiPhyRx();
\r
175 fifoData[i + k + 12] = scsiPhyRx();
\r
176 fifoData[i + k + 13] = scsiPhyRx();
\r
177 fifoData[i + k + 14] = scsiPhyRx();
\r
178 fifoData[i + k + 15] = scsiPhyRx();
\r
179 fifoData[i + k + 16] = scsiPhyRx();
\r
180 fifoData[i + k + 17] = scsiPhyRx();
\r
181 fifoData[i + k + 18] = scsiPhyRx();
\r
182 fifoData[i + k + 19] = scsiPhyRx();
\r
183 fifoData[i + k + 20] = scsiPhyRx();
\r
184 fifoData[i + k + 21] = scsiPhyRx();
\r
185 fifoData[i + k + 22] = scsiPhyRx();
\r
186 fifoData[i + k + 23] = scsiPhyRx();
\r
187 fifoData[i + k + 24] = scsiPhyRx();
\r
188 fifoData[i + k + 25] = scsiPhyRx();
\r
189 fifoData[i + k + 26] = scsiPhyRx();
\r
190 fifoData[i + k + 27] = scsiPhyRx();
\r
191 fifoData[i + k + 28] = scsiPhyRx();
\r
192 fifoData[i + k + 29] = scsiPhyRx();
\r
193 fifoData[i + k + 30] = scsiPhyRx();
\r
194 fifoData[i + k + 31] = scsiPhyRx();
\r
195 fifoData[i + k + 32] = scsiPhyRx();
\r
196 fifoData[i + k + 33] = scsiPhyRx();
\r
197 fifoData[i + k + 34] = scsiPhyRx();
\r
198 fifoData[i + k + 35] = scsiPhyRx();
\r
199 fifoData[i + k + 36] = scsiPhyRx();
\r
200 fifoData[i + k + 37] = scsiPhyRx();
\r
201 fifoData[i + k + 38] = scsiPhyRx();
\r
202 fifoData[i + k + 39] = scsiPhyRx();
\r
203 fifoData[i + k + 40] = scsiPhyRx();
\r
204 fifoData[i + k + 41] = scsiPhyRx();
\r
205 fifoData[i + k + 42] = scsiPhyRx();
\r
206 fifoData[i + k + 43] = scsiPhyRx();
\r
207 fifoData[i + k + 44] = scsiPhyRx();
\r
208 fifoData[i + k + 45] = scsiPhyRx();
\r
209 fifoData[i + k + 46] = scsiPhyRx();
\r
210 fifoData[i + k + 47] = scsiPhyRx();
\r
211 fifoData[i + k + 48] = scsiPhyRx();
\r
212 fifoData[i + k + 49] = scsiPhyRx();
\r
213 fifoData[i + k + 50] = scsiPhyRx();
\r
214 fifoData[i + k + 51] = scsiPhyRx();
\r
215 fifoData[i + k + 52] = scsiPhyRx();
\r
216 fifoData[i + k + 53] = scsiPhyRx();
\r
217 fifoData[i + k + 54] = scsiPhyRx();
\r
218 fifoData[i + k + 55] = scsiPhyRx();
\r
219 fifoData[i + k + 56] = scsiPhyRx();
\r
220 fifoData[i + k + 57] = scsiPhyRx();
\r
221 fifoData[i + k + 58] = scsiPhyRx();
\r
222 fifoData[i + k + 59] = scsiPhyRx();
\r
223 fifoData[i + k + 60] = scsiPhyRx();
\r
224 fifoData[i + k + 61] = scsiPhyRx();
\r
225 fifoData[i + k + 62] = scsiPhyRx();
\r
226 fifoData[i + k + 63] = scsiPhyRx();
\r
227 fifoData[i + k + 64] = scsiPhyRx();
\r
228 fifoData[i + k + 65] = scsiPhyRx();
\r
229 fifoData[i + k + 66] = scsiPhyRx();
\r
230 fifoData[i + k + 67] = scsiPhyRx();
\r
231 fifoData[i + k + 68] = scsiPhyRx();
\r
232 fifoData[i + k + 69] = scsiPhyRx();
\r
233 fifoData[i + k + 70] = scsiPhyRx();
\r
234 fifoData[i + k + 71] = scsiPhyRx();
\r
235 fifoData[i + k + 72] = scsiPhyRx();
\r
236 fifoData[i + k + 73] = scsiPhyRx();
\r
237 fifoData[i + k + 74] = scsiPhyRx();
\r
238 fifoData[i + k + 75] = scsiPhyRx();
\r
239 fifoData[i + k + 76] = scsiPhyRx();
\r
240 fifoData[i + k + 77] = scsiPhyRx();
\r
241 fifoData[i + k + 78] = scsiPhyRx();
\r
242 fifoData[i + k + 79] = scsiPhyRx();
\r
243 fifoData[i + k + 80] = scsiPhyRx();
\r
244 fifoData[i + k + 81] = scsiPhyRx();
\r
245 fifoData[i + k + 82] = scsiPhyRx();
\r
246 fifoData[i + k + 83] = scsiPhyRx();
\r
247 fifoData[i + k + 84] = scsiPhyRx();
\r
248 fifoData[i + k + 85] = scsiPhyRx();
\r
249 fifoData[i + k + 86] = scsiPhyRx();
\r
250 fifoData[i + k + 87] = scsiPhyRx();
\r
251 fifoData[i + k + 88] = scsiPhyRx();
\r
252 fifoData[i + k + 89] = scsiPhyRx();
\r
253 fifoData[i + k + 90] = scsiPhyRx();
\r
254 fifoData[i + k + 91] = scsiPhyRx();
\r
255 fifoData[i + k + 92] = scsiPhyRx();
\r
256 fifoData[i + k + 93] = scsiPhyRx();
\r
257 fifoData[i + k + 94] = scsiPhyRx();
\r
258 fifoData[i + k + 95] = scsiPhyRx();
\r
259 fifoData[i + k + 96] = scsiPhyRx();
\r
260 fifoData[i + k + 97] = scsiPhyRx();
\r
261 fifoData[i + k + 98] = scsiPhyRx();
\r
262 fifoData[i + k + 99] = scsiPhyRx();
\r
263 fifoData[i + k + 100] = scsiPhyRx();
\r
264 fifoData[i + k + 101] = scsiPhyRx();
\r
265 fifoData[i + k + 102] = scsiPhyRx();
\r
266 fifoData[i + k + 103] = scsiPhyRx();
\r
267 fifoData[i + k + 104] = scsiPhyRx();
\r
268 fifoData[i + k + 105] = scsiPhyRx();
\r
269 fifoData[i + k + 106] = scsiPhyRx();
\r
270 fifoData[i + k + 107] = scsiPhyRx();
\r
271 fifoData[i + k + 108] = scsiPhyRx();
\r
272 fifoData[i + k + 109] = scsiPhyRx();
\r
273 fifoData[i + k + 110] = scsiPhyRx();
\r
274 fifoData[i + k + 111] = scsiPhyRx();
\r
275 fifoData[i + k + 112] = scsiPhyRx();
\r
276 fifoData[i + k + 113] = scsiPhyRx();
\r
277 fifoData[i + k + 114] = scsiPhyRx();
\r
278 fifoData[i + k + 115] = scsiPhyRx();
\r
279 fifoData[i + k + 116] = scsiPhyRx();
\r
280 fifoData[i + k + 117] = scsiPhyRx();
\r
281 fifoData[i + k + 118] = scsiPhyRx();
\r
282 fifoData[i + k + 119] = scsiPhyRx();
\r
283 fifoData[i + k + 120] = scsiPhyRx();
\r
284 fifoData[i + k + 121] = scsiPhyRx();
\r
285 fifoData[i + k + 122] = scsiPhyRx();
\r
286 fifoData[i + k + 123] = scsiPhyRx();
\r
287 fifoData[i + k + 124] = scsiPhyRx();
\r
288 fifoData[i + k + 125] = scsiPhyRx();
\r
289 fifoData[i + k + 126] = scsiPhyRx();
\r
290 fifoData[i + k + 127] = scsiPhyRx();
\r
297 uint32_t chunk16 = count16 - i;
\r
300 for (; k + 4 <= chunk16; k += 4)
\r
302 fifoData[i + k] = scsiPhyRx();
\r
303 fifoData[i + 1 + k] = scsiPhyRx();
\r
304 fifoData[i + 2 + k] = scsiPhyRx();
\r
305 fifoData[i + 3 + k] = scsiPhyRx();
\r
307 for (; k < chunk16; ++k)
\r
309 fifoData[i + k] = scsiPhyRx();
\r
315 *parityError |= scsiParityError();
\r
319 scsiRead(uint8_t* data, uint32_t count, int* parityError)
\r
324 while (i < count && likely(!scsiDev.resetFlag))
\r
326 uint32_t chunk = ((count - i) > SCSI_XFER_MAX)
\r
327 ? SCSI_XFER_MAX : (count - i);
\r
328 scsiSetDataCount(chunk);
\r
330 scsiReadPIO(data + i, chunk, parityError);
\r
333 while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
344 scsiWriteByte(uint8_t value)
\r
346 scsiSetDataCount(1);
\r
350 while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
358 scsiWritePIO(const uint8_t* data, uint32_t count)
\r
360 uint16_t* fifoData = (uint16_t*)data;
\r
361 uint32_t count16 = (count + 1) / 2;
\r
364 while ((i < count16) && likely(!scsiDev.resetFlag))
\r
366 while (!scsiFifoReady() && likely(!scsiDev.resetFlag))
\r
371 if (count16 - i >= SCSI_FIFO_DEPTH16)
\r
373 uint32_t chunk16 = SCSI_FIFO_DEPTH16;
\r
375 // Let gcc unroll the loop as much as possible.
\r
376 for (uint32_t k = 0; k + 128 <= chunk16; k += 128)
\r
378 scsiPhyTx32(fifoData[i + k], fifoData[i + k + 1]);
\r
379 scsiPhyTx32(fifoData[i + 2 + k], fifoData[i + k + 3]);
\r
380 scsiPhyTx32(fifoData[i + 4 + k], fifoData[i + k + 5]);
\r
381 scsiPhyTx32(fifoData[i + 6 + k], fifoData[i + k + 7]);
\r
382 scsiPhyTx32(fifoData[i + 8 + k], fifoData[i + k + 9]);
\r
383 scsiPhyTx32(fifoData[i + 10 + k], fifoData[i + k + 11]);
\r
384 scsiPhyTx32(fifoData[i + 12 + k], fifoData[i + k + 13]);
\r
385 scsiPhyTx32(fifoData[i + 14 + k], fifoData[i + k + 15]);
\r
386 scsiPhyTx32(fifoData[i + 16 + k], fifoData[i + k + 17]);
\r
387 scsiPhyTx32(fifoData[i + 18 + k], fifoData[i + k + 19]);
\r
388 scsiPhyTx32(fifoData[i + 20 + k], fifoData[i + k + 21]);
\r
389 scsiPhyTx32(fifoData[i + 22 + k], fifoData[i + k + 23]);
\r
390 scsiPhyTx32(fifoData[i + 24 + k], fifoData[i + k + 25]);
\r
391 scsiPhyTx32(fifoData[i + 26 + k], fifoData[i + k + 27]);
\r
392 scsiPhyTx32(fifoData[i + 28 + k], fifoData[i + k + 29]);
\r
393 scsiPhyTx32(fifoData[i + 30 + k], fifoData[i + k + 31]);
\r
395 scsiPhyTx32(fifoData[i + 32 + k], fifoData[i + k + 33]);
\r
396 scsiPhyTx32(fifoData[i + 34 + k], fifoData[i + k + 35]);
\r
397 scsiPhyTx32(fifoData[i + 36 + k], fifoData[i + k + 37]);
\r
398 scsiPhyTx32(fifoData[i + 38 + k], fifoData[i + k + 39]);
\r
399 scsiPhyTx32(fifoData[i + 40 + k], fifoData[i + k + 41]);
\r
400 scsiPhyTx32(fifoData[i + 42 + k], fifoData[i + k + 43]);
\r
401 scsiPhyTx32(fifoData[i + 44 + k], fifoData[i + k + 45]);
\r
402 scsiPhyTx32(fifoData[i + 46 + k], fifoData[i + k + 47]);
\r
403 scsiPhyTx32(fifoData[i + 48 + k], fifoData[i + k + 49]);
\r
404 scsiPhyTx32(fifoData[i + 50 + k], fifoData[i + k + 51]);
\r
405 scsiPhyTx32(fifoData[i + 52 + k], fifoData[i + k + 53]);
\r
406 scsiPhyTx32(fifoData[i + 54 + k], fifoData[i + k + 55]);
\r
407 scsiPhyTx32(fifoData[i + 56 + k], fifoData[i + k + 57]);
\r
408 scsiPhyTx32(fifoData[i + 58 + k], fifoData[i + k + 59]);
\r
409 scsiPhyTx32(fifoData[i + 60 + k], fifoData[i + k + 61]);
\r
410 scsiPhyTx32(fifoData[i + 62 + k], fifoData[i + k + 63]);
\r
412 scsiPhyTx32(fifoData[i + 64 + k], fifoData[i + k + 65]);
\r
413 scsiPhyTx32(fifoData[i + 66 + k], fifoData[i + k + 67]);
\r
414 scsiPhyTx32(fifoData[i + 68 + k], fifoData[i + k + 69]);
\r
415 scsiPhyTx32(fifoData[i + 70 + k], fifoData[i + k + 71]);
\r
416 scsiPhyTx32(fifoData[i + 72 + k], fifoData[i + k + 73]);
\r
417 scsiPhyTx32(fifoData[i + 74 + k], fifoData[i + k + 75]);
\r
418 scsiPhyTx32(fifoData[i + 76 + k], fifoData[i + k + 77]);
\r
419 scsiPhyTx32(fifoData[i + 78 + k], fifoData[i + k + 79]);
\r
420 scsiPhyTx32(fifoData[i + 80 + k], fifoData[i + k + 81]);
\r
421 scsiPhyTx32(fifoData[i + 82 + k], fifoData[i + k + 83]);
\r
422 scsiPhyTx32(fifoData[i + 84 + k], fifoData[i + k + 85]);
\r
423 scsiPhyTx32(fifoData[i + 86 + k], fifoData[i + k + 87]);
\r
424 scsiPhyTx32(fifoData[i + 88 + k], fifoData[i + k + 89]);
\r
425 scsiPhyTx32(fifoData[i + 90 + k], fifoData[i + k + 91]);
\r
426 scsiPhyTx32(fifoData[i + 92 + k], fifoData[i + k + 93]);
\r
427 scsiPhyTx32(fifoData[i + 94 + k], fifoData[i + k + 95]);
\r
429 scsiPhyTx32(fifoData[i + 96 + k], fifoData[i + k + 97]);
\r
430 scsiPhyTx32(fifoData[i + 98 + k], fifoData[i + k + 99]);
\r
431 scsiPhyTx32(fifoData[i + 100 + k], fifoData[i + k + 101]);
\r
432 scsiPhyTx32(fifoData[i + 102 + k], fifoData[i + k + 103]);
\r
433 scsiPhyTx32(fifoData[i + 104 + k], fifoData[i + k + 105]);
\r
434 scsiPhyTx32(fifoData[i + 106 + k], fifoData[i + k + 107]);
\r
435 scsiPhyTx32(fifoData[i + 108 + k], fifoData[i + k + 109]);
\r
436 scsiPhyTx32(fifoData[i + 110 + k], fifoData[i + k + 111]);
\r
437 scsiPhyTx32(fifoData[i + 112 + k], fifoData[i + k + 113]);
\r
438 scsiPhyTx32(fifoData[i + 114 + k], fifoData[i + k + 115]);
\r
439 scsiPhyTx32(fifoData[i + 116 + k], fifoData[i + k + 117]);
\r
440 scsiPhyTx32(fifoData[i + 118 + k], fifoData[i + k + 119]);
\r
441 scsiPhyTx32(fifoData[i + 120 + k], fifoData[i + k + 121]);
\r
442 scsiPhyTx32(fifoData[i + 122 + k], fifoData[i + k + 123]);
\r
443 scsiPhyTx32(fifoData[i + 124 + k], fifoData[i + k + 125]);
\r
444 scsiPhyTx32(fifoData[i + 126 + k], fifoData[i + k + 127]);
\r
452 uint32_t chunk16 = count16 - i;
\r
455 for (; k + 4 <= chunk16; k += 4)
\r
457 scsiPhyTx32(fifoData[i + k], fifoData[i + k + 1]);
\r
458 scsiPhyTx32(fifoData[i + k + 2], fifoData[i + k + 3]);
\r
460 for (; k < chunk16; ++k)
\r
462 scsiPhyTx(fifoData[i + k]);
\r
471 scsiWrite(const uint8_t* data, uint32_t count)
\r
474 while (i < count && likely(!scsiDev.resetFlag))
\r
476 uint32_t chunk = ((count - i) > SCSI_XFER_MAX)
\r
477 ? SCSI_XFER_MAX : (count - i);
\r
478 scsiSetDataCount(chunk);
\r
480 scsiWritePIO(data + i, chunk);
\r
483 while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
\r
493 static inline void busSettleDelay(void)
\r
495 // Data Release time (switching IO) = 400ns
\r
496 // + Bus Settle time (switching phase) = 400ns.
\r
497 s2s_delay_us(1); // Close enough.
\r
500 void scsiEnterBusFree()
\r
502 *SCSI_CTRL_BSY = 0x00;
\r
503 // We now have a Bus Clear Delay of 800ns to release remaining signals.
\r
504 *SCSI_CTRL_PHASE = 0;
\r
509 uint8_t assertClocks,
\r
514 *SCSI_CTRL_DESKEW = ((hold & 7) << 5) | (deskew & 0x1F);
\r
515 *SCSI_CTRL_TIMING = (assertClocks & 0x3F);
\r
516 *SCSI_CTRL_TIMING3 = (glitch & 0xF);
\r
520 scsiSetDefaultTiming()
\r
522 const uint8_t* asyncTiming = asyncTimings[0];
\r
530 void scsiEnterPhase(int newPhase)
\r
532 uint32_t delay = scsiEnterPhaseImmediate(newPhase);
\r
535 s2s_delay_us(delay);
\r
539 // Returns microsecond delay
\r
540 uint32_t scsiEnterPhaseImmediate(int newPhase)
\r
542 // ANSI INCITS 362-2002 SPI-3 10.7.1:
\r
543 // Phase changes are not allowed while REQ or ACK is asserted.
\r
544 while (likely(!scsiDev.resetFlag) && scsiStatusACK()) {}
\r
546 int oldPhase = *SCSI_CTRL_PHASE;
\r
548 if (newPhase != oldPhase)
\r
550 if ((newPhase == DATA_IN || newPhase == DATA_OUT) &&
\r
551 scsiDev.target->syncOffset)
\r
553 if (scsiDev.target->syncPeriod < 23)
\r
555 scsiSetTiming(SCSI_FAST20_ASSERT, SCSI_FAST20_DESKEW, SCSI_FAST20_HOLD, 1);
\r
557 else if (scsiDev.target->syncPeriod <= 25)
\r
559 if (newPhase == DATA_IN)
\r
561 scsiSetTiming(SCSI_FAST10_WRITE_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);
\r
565 scsiSetTiming(SCSI_FAST10_READ_ASSERT, SCSI_FAST10_DESKEW, SCSI_FAST10_HOLD, 1);
\r
570 // Amiga A3000 OS3.9 sets period to 35 and fails with
\r
573 scsiDev.target->syncPeriod < 35 ? 1 :
\r
574 (scsiDev.target->syncPeriod < 45 ? 2 : 5);
\r
575 int deskew = syncDeskew(scsiDev.target->syncPeriod);
\r
577 if (newPhase == DATA_IN)
\r
579 assertion = syncAssertionWrite(scsiDev.target->syncPeriod, deskew);
\r
583 assertion = syncAssertionRead(scsiDev.target->syncPeriod);
\r
588 syncHold(scsiDev.target->syncPeriod),
\r
592 *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset;
\r
594 else if (newPhase >= 0)
\r
597 *SCSI_CTRL_SYNC_OFFSET = 0;
\r
598 const uint8_t* asyncTiming;
\r
600 if (scsiDev.boardCfg.scsiSpeed == S2S_CFG_SPEED_NoLimit)
\r
602 asyncTiming = asyncTimings[SCSI_ASYNC_SAFE];
\r
604 else if (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_TURBO)
\r
606 asyncTiming = asyncTimings[SCSI_ASYNC_TURBO];
\r
608 else if (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_ASYNC_50)
\r
610 asyncTiming = asyncTimings[SCSI_ASYNC_50];
\r
611 } else if (scsiDev.boardCfg.scsiSpeed >= S2S_CFG_SPEED_ASYNC_33) {
\r
613 asyncTiming = asyncTimings[SCSI_ASYNC_33];
\r
616 asyncTiming = asyncTimings[SCSI_ASYNC_15];
\r
625 uint32_t delayUs = 0;
\r
628 *SCSI_CTRL_PHASE = newPhase;
\r
629 delayUs += 1; // busSettleDelay
\r
631 if (scsiDev.compatMode < COMPAT_SCSI2)
\r
633 // EMU EMAX needs 100uS ! 10uS is not enough.
\r
639 *SCSI_CTRL_PHASE = 0;
\r
645 return 0; // No change
\r
648 // Returns a "safe" estimate of the host SCSI speed of
\r
649 // theoretical speed / 2
\r
650 uint32_t s2s_getScsiRateKBs()
\r
652 if (scsiDev.target->syncOffset)
\r
654 if (scsiDev.target->syncPeriod < 23)
\r
658 else if (scsiDev.target->syncPeriod <= 25)
\r
664 // 1000000000 / (scsiDev.target->syncPeriod * 4) bytes per second
\r
665 // (1000000000 / (scsiDev.target->syncPeriod * 4)) / 1000 kB/s
\r
666 return (1000000 / (scsiDev.target->syncPeriod * 4)) / 2;
\r
675 void scsiPhyReset()
\r
679 HAL_DMA_Abort(&memToFSMC);
\r
680 HAL_DMA_Abort(&fsmcToMem);
\r
685 s2s_fpgaReset(); // Clears fifos etc.
\r
687 *SCSI_CTRL_PHASE = 0x00;
\r
688 *SCSI_CTRL_BSY = 0x00;
\r
689 *SCSI_CTRL_DBX = 0;
\r
691 *SCSI_CTRL_SYNC_OFFSET = 0;
\r
692 scsiSetDefaultTiming();
\r
694 // DMA Benchmark code
\r
695 // Currently 14.9MB/s.
\r
696 #ifdef DMA_BENCHMARK
\r
701 for (int i = 0; i < (100LL * 1024 * 1024 / SCSI_FIFO_DEPTH); ++i)
\r
705 (uint32_t) &scsiDev.data[0],
\r
706 (uint32_t) SCSI_FIFO_DATA,
\r
707 SCSI_FIFO_DEPTH / 4);
\r
709 HAL_DMA_PollForTransfer(
\r
711 HAL_DMA_FULL_TRANSFER,
\r
718 for(int i = 0; i < 10; ++i) s2s_delay_ms(1000);
\r
722 // PIO Benchmark code
\r
723 // Currently 16.7MB/s.
\r
724 //#define PIO_BENCHMARK 1
\r
725 #ifdef PIO_BENCHMARK
\r
730 scsiEnterPhase(DATA_IN); // Need IO flag set for fifo ready flag
\r
733 for (int i = 0; i < (100LL * 1024 * 1024 / SCSI_FIFO_DEPTH); ++i)
\r
735 scsiSetDataCount(1); // Resets fifos.
\r
738 scsiDev.resetFlag = 0;
\r
739 scsiWritePIO(&scsiDev.data[0], SCSI_FIFO_DEPTH);
\r
743 for(int i = 0; i < 10; ++i) s2s_delay_ms(1000);
\r
747 #ifdef SCSI_FREQ_TEST
\r
750 *SCSI_CTRL_DBX = 0xAA;
\r
751 *SCSI_CTRL_DBX = 0x55;
\r
757 static void scsiPhyInitDMA()
\r
759 // One-time init only.
\r
760 static uint8_t init = 0;
\r
765 // Memory to memory transfers can only be done using DMA2
\r
766 __DMA2_CLK_ENABLE();
\r
768 // Transmit SCSI data. The source data is treated as the
\r
769 // peripheral (even though this is memory-to-memory)
\r
770 memToFSMC.Instance = DMA2_Stream0;
\r
771 memToFSMC.Init.Channel = DMA_CHANNEL_0;
\r
772 memToFSMC.Init.Direction = DMA_MEMORY_TO_MEMORY;
\r
773 memToFSMC.Init.PeriphInc = DMA_PINC_ENABLE;
\r
774 memToFSMC.Init.MemInc = DMA_MINC_DISABLE;
\r
775 memToFSMC.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
\r
776 memToFSMC.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
\r
777 memToFSMC.Init.Mode = DMA_NORMAL;
\r
778 memToFSMC.Init.Priority = DMA_PRIORITY_LOW;
\r
779 // FIFO mode is needed to allow conversion from 32bit words to the
\r
780 // 16bit FSMC interface.
\r
781 memToFSMC.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
\r
783 // We only use 1 word (4 bytes) in the fifo at a time. Normally it's
\r
784 // better to let the DMA fifo fill up then do burst transfers, but
\r
785 // bursting out the FSMC interface will be very slow and may starve
\r
786 // other (faster) transfers. We don't want to risk the SDIO transfers
\r
787 // from overrun/underrun conditions.
\r
788 memToFSMC.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
\r
789 memToFSMC.Init.MemBurst = DMA_MBURST_SINGLE;
\r
790 memToFSMC.Init.PeriphBurst = DMA_PBURST_SINGLE;
\r
791 HAL_DMA_Init(&memToFSMC);
\r
793 // Receive SCSI data. The source data (fsmc) is treated as the
\r
794 // peripheral (even though this is memory-to-memory)
\r
795 fsmcToMem.Instance = DMA2_Stream1;
\r
796 fsmcToMem.Init.Channel = DMA_CHANNEL_0;
\r
797 fsmcToMem.Init.Direction = DMA_MEMORY_TO_MEMORY;
\r
798 fsmcToMem.Init.PeriphInc = DMA_PINC_DISABLE;
\r
799 fsmcToMem.Init.MemInc = DMA_MINC_ENABLE;
\r
800 fsmcToMem.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
\r
801 fsmcToMem.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
\r
802 fsmcToMem.Init.Mode = DMA_NORMAL;
\r
803 fsmcToMem.Init.Priority = DMA_PRIORITY_LOW;
\r
804 fsmcToMem.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
\r
805 fsmcToMem.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
\r
806 fsmcToMem.Init.MemBurst = DMA_MBURST_SINGLE;
\r
807 fsmcToMem.Init.PeriphBurst = DMA_PBURST_SINGLE;
\r
808 HAL_DMA_Init(&fsmcToMem);
\r
810 // TODO configure IRQs
\r
819 *SCSI_CTRL_IDMASK = 0x00; // Reset in scsiPhyConfig
\r
820 *SCSI_CTRL_PHASE = 0x00;
\r
821 *SCSI_CTRL_BSY = 0x00;
\r
822 *SCSI_CTRL_DBX = 0;
\r
824 *SCSI_CTRL_SYNC_OFFSET = 0;
\r
825 scsiSetDefaultTiming();
\r
827 *SCSI_CTRL_SEL_TIMING = SCSI_DEFAULT_SELECTION;
\r
831 void scsiPhyConfig()
\r
833 if (scsiDev.boardCfg.flags6 & S2S_CFG_ENABLE_TERMINATOR)
\r
835 HAL_GPIO_WritePin(nTERM_EN_GPIO_Port, nTERM_EN_Pin, GPIO_PIN_RESET);
\r
839 HAL_GPIO_WritePin(nTERM_EN_GPIO_Port, nTERM_EN_Pin, GPIO_PIN_SET);
\r
843 uint8_t idMask = 0;
\r
844 for (int i = 0; i < 8; ++i)
\r
846 const S2S_TargetCfg* cfg = s2s_getConfigById(i);
\r
847 if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
\r
849 idMask |= (1 << i);
\r
852 *SCSI_CTRL_IDMASK = idMask;
\r
855 ((scsiDev.boardCfg.flags & S2S_CFG_DISABLE_GLITCH) ?
\r
856 SCSI_CTRL_FLAGS_DISABLE_GLITCH : 0) |
\r
857 ((scsiDev.boardCfg.flags & S2S_CFG_ENABLE_PARITY) ?
\r
858 SCSI_CTRL_FLAGS_ENABLE_PARITY : 0);
\r
860 *SCSI_CTRL_SEL_TIMING =
\r
861 (scsiDev.boardCfg.flags & S2S_CFG_ENABLE_SEL_LATCH) ?
\r
862 SCSI_FAST_SELECTION : SCSI_DEFAULT_SELECTION;
\r
867 // 2 = Parity error
\r
871 // 32 = other error
\r
872 // 64 = fpga comms error
\r
875 if (scsiDev.phase != BUS_FREE)
\r
880 // Acquire the SCSI bus.
\r
881 for (int i = 0; i < 100; ++i)
\r
883 if (scsiStatusBSY())
\r
888 if (scsiStatusBSY())
\r
890 // Error, couldn't acquire scsi bus
\r
893 *SCSI_CTRL_BSY = 1;
\r
895 if (! scsiStatusBSY())
\r
897 *SCSI_CTRL_BSY = 0;
\r
899 // Error, BSY doesn't work.
\r
903 // Should be safe to use the bus now.
\r
907 *SCSI_CTRL_DBX = 0;
\r
909 if ((*SCSI_STS_DBX & 0xff) != 0)
\r
914 *SCSI_CTRL_BSY = 0;
\r