scsiPhy.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787
  1. // Copyright (C) 2013 Michael McMaster <michael@codesrc.com>
  2. //
  3. // This file is part of SCSI2SD.
  4. //
  5. // SCSI2SD is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // SCSI2SD is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with SCSI2SD. If not, see <http://www.gnu.org/licenses/>.
  17. #include "stm32f2xx.h"
  18. #include "stm32f2xx_hal.h"
  19. #include "stm32f2xx_hal_dma.h"
  20. #include "scsi.h"
  21. #include "scsiPhy.h"
  22. #include "trace.h"
  23. #include "time.h"
  24. #include "fpga.h"
  25. #include "led.h"
  26. #include <string.h>
  27. // Assumes a 60MHz fpga clock.
  28. // 7:6 Hold count, 45ns
  29. // 5:3 Assertion count, 90ns
  30. // 2:0 Deskew count, 55ns
  31. #define SCSI_DEFAULT_TIMING ((0x3 << 6) | (0x6 << 3) | 0x4)
  32. // 7:6 Hold count, 10ns
  33. // 5:3 Assertion count, 30ns
  34. // 2:0 Deskew count, 25ns
  35. #define SCSI_FAST_TIMING ((0x1 << 6) | (0x2 << 3) | 0x2)
  36. // Private DMA variables.
  37. static int dmaInProgress = 0;
  38. static DMA_HandleTypeDef memToFSMC;
  39. static DMA_HandleTypeDef fsmcToMem;
  40. volatile uint8_t scsiRxDMAComplete;
  41. volatile uint8_t scsiTxDMAComplete;
  42. #if 0
  43. CY_ISR_PROTO(scsiRxCompleteISR);
  44. CY_ISR(scsiRxCompleteISR)
  45. {
  46. traceIrq(trace_scsiRxCompleteISR);
  47. scsiRxDMAComplete = 1;
  48. }
  49. CY_ISR_PROTO(scsiTxCompleteISR);
  50. CY_ISR(scsiTxCompleteISR)
  51. {
  52. traceIrq(trace_scsiTxCompleteISR);
  53. scsiTxDMAComplete = 1;
  54. }
  55. #endif
  56. uint8_t scsiPhyFifoSel = 0; // global
  57. // scsi IRQ handler is initialised by the STM32 HAL. Connected to
  58. // PE4
  59. // Note: naming is important to ensure this function is listed in the
  60. // vector table.
  61. void EXTI4_IRQHandler()
  62. {
  63. traceIrq(trace_scsiResetISR);
  64. // Make sure that interrupt flag is set
  65. if (__HAL_GPIO_EXTI_GET_IT(GPIO_PIN_4) != RESET) {
  66. // Clear interrupt flag
  67. __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_4);
  68. scsiDev.resetFlag = scsiDev.resetFlag || scsiStatusRST();
  69. // TODO grab SEL status as well
  70. }
  71. }
  72. static void assertFail()
  73. {
  74. while (1)
  75. {
  76. s2s_ledOn();
  77. s2s_delay_ms(100);
  78. s2s_ledOff();
  79. s2s_delay_ms(100);
  80. }
  81. }
  82. static void
  83. startScsiRx(uint32_t count)
  84. {
  85. *SCSI_DATA_CNT_HI = count >> 8;
  86. *SCSI_DATA_CNT_LO = count & 0xff;
  87. *SCSI_DATA_CNT_SET = 1;
  88. }
  89. uint8_t
  90. scsiReadByte(void)
  91. {
  92. #if FIFODEBUG
  93. if (!scsiPhyFifoAltEmpty()) {
  94. // Force a lock-up.
  95. assertFail();
  96. }
  97. #endif
  98. startScsiRx(1);
  99. trace(trace_spinPhyRxFifo);
  100. while (!scsiPhyComplete() && likely(!scsiDev.resetFlag)) {}
  101. scsiPhyFifoFlip();
  102. uint8_t val = scsiPhyRx();
  103. // TODO scsiDev.parityError = scsiDev.parityError || SCSI_Parity_Error_Read();
  104. #if FIFODEBUG
  105. if (!scsiPhyFifoEmpty()) {
  106. int j = 0;
  107. uint8_t k __attribute((unused));
  108. while (!scsiPhyFifoEmpty()) { k = scsiPhyRx(); ++j; }
  109. // Force a lock-up.
  110. assertFail();
  111. }
  112. #endif
  113. return val;
  114. }
  115. static void
  116. scsiReadPIO(uint8_t* data, uint32_t count)
  117. {
  118. for (int i = 0; i < count; ++i)
  119. {
  120. data[i] = scsiPhyRx();
  121. }
  122. // TODO scsiDev.parityError = scsiDev.parityError || SCSI_Parity_Error_Read();
  123. }
  124. void
  125. scsiReadDMA(uint8_t* data, uint32_t count)
  126. {
  127. // Prepare DMA transfer
  128. dmaInProgress = 1;
  129. trace(trace_doRxSingleDMA);
  130. scsiTxDMAComplete = 1; // TODO not used much
  131. scsiRxDMAComplete = 0; // TODO not used much
  132. HAL_DMA_Start(&fsmcToMem, (uint32_t) SCSI_FIFO_DATA, (uint32_t) data, count);
  133. }
  134. int
  135. scsiReadDMAPoll()
  136. {
  137. int complete = __HAL_DMA_GET_COUNTER(&fsmcToMem) == 0;
  138. complete = complete && (HAL_DMA_PollForTransfer(&fsmcToMem, HAL_DMA_FULL_TRANSFER, 0xffffffff) == HAL_OK);
  139. if (complete)
  140. {
  141. scsiTxDMAComplete = 1; // TODO MM FIX IRQ
  142. scsiRxDMAComplete = 1;
  143. dmaInProgress = 0;
  144. #if 0
  145. // TODO MM scsiDev.parityError = scsiDev.parityError || SCSI_Parity_Error_Read();
  146. #endif
  147. return 1;
  148. }
  149. else
  150. {
  151. return 0;
  152. }
  153. }
  154. void
  155. scsiRead(uint8_t* data, uint32_t count)
  156. {
  157. int i = 0;
  158. uint32_t chunk = ((count - i) > SCSI_FIFO_DEPTH)
  159. ? SCSI_FIFO_DEPTH : (count - i);
  160. if (chunk >= 16)
  161. {
  162. // DMA is doing 32bit transfers.
  163. chunk = chunk & 0xFFFFFFF8;
  164. }
  165. startScsiRx(chunk);
  166. while (i < count && likely(!scsiDev.resetFlag))
  167. {
  168. while (!scsiPhyComplete() && likely(!scsiDev.resetFlag)) {}
  169. scsiPhyFifoFlip();
  170. uint32_t nextChunk = ((count - i - chunk) > SCSI_FIFO_DEPTH)
  171. ? SCSI_FIFO_DEPTH : (count - i - chunk);
  172. if (nextChunk >= 16)
  173. {
  174. nextChunk = nextChunk & 0xFFFFFFF8;
  175. }
  176. if (nextChunk > 0)
  177. {
  178. startScsiRx(nextChunk);
  179. }
  180. if (chunk < 16)
  181. {
  182. scsiReadPIO(data + i, chunk);
  183. }
  184. else
  185. {
  186. scsiReadDMA(data + i, chunk);
  187. trace(trace_spinReadDMAPoll);
  188. while (!scsiReadDMAPoll() && likely(!scsiDev.resetFlag))
  189. {
  190. };
  191. }
  192. i += chunk;
  193. chunk = nextChunk;
  194. }
  195. #if 1
  196. if (!scsiPhyFifoEmpty() || !scsiPhyFifoAltEmpty()) {
  197. int j = 0;
  198. while (!scsiPhyFifoEmpty()) { scsiPhyRx(); ++j; }
  199. scsiPhyFifoFlip();
  200. int k = 0;
  201. while (!scsiPhyFifoEmpty()) { scsiPhyRx(); ++k; }
  202. // Force a lock-up.
  203. assertFail();
  204. }
  205. #endif
  206. }
  207. void
  208. scsiWriteByte(uint8_t value)
  209. {
  210. #if FIFODEBUG
  211. if (!scsiPhyFifoEmpty()) {
  212. // Force a lock-up.
  213. assertFail();
  214. }
  215. #endif
  216. trace(trace_spinPhyTxFifo);
  217. scsiPhyTx(value);
  218. scsiPhyFifoFlip();
  219. trace(trace_spinTxComplete);
  220. while (!scsiPhyComplete() && likely(!scsiDev.resetFlag)) {}
  221. #if FIFODEBUG
  222. if (!scsiPhyFifoAltEmpty()) {
  223. // Force a lock-up.
  224. assertFail();
  225. }
  226. #endif
  227. }
  228. static void
  229. scsiWritePIO(const uint8_t* data, uint32_t count)
  230. {
  231. for (int i = 0; i < count; ++i)
  232. {
  233. scsiPhyTx(data[i]);
  234. }
  235. }
  236. void
  237. scsiWriteDMA(const uint8_t* data, uint32_t count)
  238. {
  239. // Prepare DMA transfer
  240. dmaInProgress = 1;
  241. trace(trace_doTxSingleDMA);
  242. scsiTxDMAComplete = 0;
  243. scsiRxDMAComplete = 1;
  244. HAL_DMA_Start(
  245. &memToFSMC,
  246. (uint32_t) data,
  247. (uint32_t) SCSI_FIFO_DATA,
  248. count / 4);
  249. }
  250. int
  251. scsiWriteDMAPoll()
  252. {
  253. int complete = __HAL_DMA_GET_COUNTER(&memToFSMC) == 0;
  254. complete = complete && (HAL_DMA_PollForTransfer(&memToFSMC, HAL_DMA_FULL_TRANSFER, 0xffffffff) == HAL_OK);
  255. if (complete)
  256. {
  257. scsiTxDMAComplete = 1; // TODO MM FIX IRQ
  258. scsiRxDMAComplete = 1;
  259. dmaInProgress = 0;
  260. return 1;
  261. }
  262. else
  263. {
  264. return 0;
  265. }
  266. }
  267. void
  268. scsiWrite(const uint8_t* data, uint32_t count)
  269. {
  270. int i = 0;
  271. while (i < count && likely(!scsiDev.resetFlag))
  272. {
  273. uint32_t chunk = ((count - i) > SCSI_FIFO_DEPTH)
  274. ? SCSI_FIFO_DEPTH : (count - i);
  275. #if FIFODEBUG
  276. if (!scsiPhyFifoEmpty()) {
  277. // Force a lock-up.
  278. assertFail();
  279. }
  280. #endif
  281. if (chunk < 16)
  282. {
  283. scsiWritePIO(data + i, chunk);
  284. }
  285. else
  286. {
  287. // DMA is doing 32bit transfers.
  288. chunk = chunk & 0xFFFFFFF8;
  289. scsiWriteDMA(data + i, chunk);
  290. trace(trace_spinReadDMAPoll);
  291. while (!scsiWriteDMAPoll() && likely(!scsiDev.resetFlag))
  292. {
  293. }
  294. }
  295. while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
  296. {
  297. }
  298. #if FIFODEBUG
  299. if (!scsiPhyFifoAltEmpty()) {
  300. // Force a lock-up.
  301. assertFail();
  302. }
  303. #endif
  304. scsiPhyFifoFlip();
  305. i += chunk;
  306. }
  307. while (!scsiPhyComplete() && likely(!scsiDev.resetFlag))
  308. {
  309. }
  310. #if FIFODEBUG
  311. if (!scsiPhyFifoAltEmpty()) {
  312. // Force a lock-up.
  313. assertFail();
  314. }
  315. #endif
  316. }
  317. static inline void busSettleDelay(void)
  318. {
  319. // Data Release time (switching IO) = 400ns
  320. // + Bus Settle time (switching phase) = 400ns.
  321. s2s_delay_us(1); // Close enough.
  322. }
  323. void scsiEnterBusFree()
  324. {
  325. *SCSI_CTRL_BSY = 0x00;
  326. // We now have a Bus Clear Delay of 800ns to release remaining signals.
  327. *SCSI_CTRL_PHASE = 0;
  328. }
  329. void scsiEnterPhase(int phase)
  330. {
  331. // ANSI INCITS 362-2002 SPI-3 10.7.1:
  332. // Phase changes are not allowed while REQ or ACK is asserted.
  333. while (likely(!scsiDev.resetFlag) && scsiStatusACK()) {}
  334. int newPhase = phase > 0 ? phase : 0;
  335. int oldPhase = *SCSI_CTRL_PHASE;
  336. if (!scsiDev.resetFlag && (!scsiPhyFifoEmpty() || !scsiPhyFifoAltEmpty())) {
  337. // Force a lock-up.
  338. assertFail();
  339. }
  340. if (newPhase != oldPhase)
  341. {
  342. if ((newPhase == DATA_IN || newPhase == DATA_OUT) &&
  343. scsiDev.target->syncOffset)
  344. {
  345. if (scsiDev.target->syncPeriod == 25)
  346. {
  347. // SCSI2 FAST Timing. 10MB/s.
  348. *SCSI_CTRL_TIMING = SCSI_FAST_TIMING;
  349. } else {
  350. // 5MB/s Timing
  351. *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING;
  352. }
  353. *SCSI_CTRL_SYNC_OFFSET = scsiDev.target->syncOffset;
  354. } else {
  355. *SCSI_CTRL_SYNC_OFFSET = 0;
  356. *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING;
  357. }
  358. *SCSI_CTRL_PHASE = newPhase;
  359. busSettleDelay();
  360. if (scsiDev.compatMode < COMPAT_SCSI2)
  361. {
  362. s2s_delay_us(100);
  363. }
  364. }
  365. }
  366. void scsiPhyReset()
  367. {
  368. trace(trace_scsiPhyReset);
  369. if (dmaInProgress)
  370. {
  371. trace(trace_spinDMAReset);
  372. HAL_DMA_Abort(&memToFSMC);
  373. HAL_DMA_Abort(&fsmcToMem);
  374. dmaInProgress = 0;
  375. }
  376. #if 0
  377. // Set the Clear bits for both SCSI device FIFOs
  378. scsiTarget_AUX_CTL = scsiTarget_AUX_CTL | 0x03;
  379. // Trigger RST outselves. It is connected to the datapath and will
  380. // ensure it returns to the idle state. The datapath runs at the BUS clk
  381. // speed (ie. same as the CPU), so we can be sure it is active for a sufficient
  382. // duration.
  383. SCSI_RST_ISR_Disable();
  384. SCSI_SetPin(SCSI_Out_RST);
  385. SCSI_CTL_PHASE_Write(0);
  386. SCSI_ClearPin(SCSI_Out_ATN);
  387. SCSI_ClearPin(SCSI_Out_BSY);
  388. SCSI_ClearPin(SCSI_Out_ACK);
  389. SCSI_ClearPin(SCSI_Out_RST);
  390. SCSI_ClearPin(SCSI_Out_SEL);
  391. SCSI_ClearPin(SCSI_Out_REQ);
  392. // Allow the FIFOs to fill up again.
  393. SCSI_ClearPin(SCSI_Out_RST);
  394. SCSI_RST_ISR_Enable();
  395. scsiTarget_AUX_CTL = scsiTarget_AUX_CTL & ~(0x03);
  396. SCSI_Parity_Error_Read(); // clear sticky bits
  397. #endif
  398. *SCSI_CTRL_PHASE = 0x00;
  399. *SCSI_CTRL_BSY = 0x00;
  400. s2s_fpgaReset(); // Clears fifos etc.
  401. scsiPhyFifoSel = 0;
  402. *SCSI_FIFO_SEL = 0;
  403. *SCSI_CTRL_DBX = 0;
  404. *SCSI_CTRL_SYNC_OFFSET = 0;
  405. *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING;
  406. // DMA Benchmark code
  407. // Currently 10MB/s. Assume 20MB/s is achievable with 16 bits.
  408. #ifdef DMA_BENCHMARK
  409. while(1)
  410. {
  411. s2s_ledOn();
  412. // 100MB
  413. for (int i = 0; i < (100LL * 1024 * 1024 / SCSI_FIFO_DEPTH); ++i)
  414. {
  415. HAL_DMA_Start(
  416. &memToFSMC,
  417. (uint32_t) &scsiDev.data[0],
  418. (uint32_t) SCSI_FIFO_DATA,
  419. SCSI_FIFO_DEPTH / 4);
  420. HAL_DMA_PollForTransfer(
  421. &memToFSMC,
  422. HAL_DMA_FULL_TRANSFER,
  423. 0xffffffff);
  424. s2s_fpgaReset();
  425. }
  426. s2s_ledOff();
  427. for(int i = 0; i < 10; ++i) s2s_delay_ms(1000);
  428. }
  429. #endif
  430. // FPGA comms test code
  431. #ifdef FPGA_TEST
  432. while(1)
  433. {
  434. for (int j = 0; j < SCSI_FIFO_DEPTH; ++j)
  435. {
  436. scsiDev.data[j] = j;
  437. }
  438. if (!scsiPhyFifoEmpty())
  439. {
  440. assertFail();
  441. }
  442. *SCSI_CTRL_PHASE = DATA_IN;
  443. HAL_DMA_Start(
  444. &memToFSMC,
  445. (uint32_t) &scsiDev.data[0],
  446. (uint32_t) SCSI_FIFO_DATA,
  447. SCSI_FIFO_DEPTH / 4);
  448. HAL_DMA_PollForTransfer(
  449. &memToFSMC,
  450. HAL_DMA_FULL_TRANSFER,
  451. 0xffffffff);
  452. if (!scsiPhyFifoFull())
  453. {
  454. assertFail();
  455. }
  456. memset(&scsiDev.data[0], 0, SCSI_FIFO_DEPTH);
  457. *SCSI_CTRL_PHASE = DATA_OUT;
  458. HAL_DMA_Start(
  459. &fsmcToMem,
  460. (uint32_t) SCSI_FIFO_DATA,
  461. (uint32_t) &scsiDev.data[0],
  462. SCSI_FIFO_DEPTH);
  463. HAL_DMA_PollForTransfer(
  464. &fsmcToMem,
  465. HAL_DMA_FULL_TRANSFER,
  466. 0xffffffff);
  467. if (!scsiPhyFifoEmpty())
  468. {
  469. assertFail();
  470. }
  471. for (int j = 0; j < SCSI_FIFO_DEPTH; ++j)
  472. {
  473. if (scsiDev.data[j] != (uint8_t) j)
  474. {
  475. assertFail();
  476. }
  477. }
  478. s2s_fpgaReset();
  479. }
  480. #endif
  481. }
  482. static void scsiPhyInitDMA()
  483. {
  484. // One-time init only.
  485. static uint8_t init = 0;
  486. if (init == 0)
  487. {
  488. init = 1;
  489. // Memory to memory transfers can only be done using DMA2
  490. __DMA2_CLK_ENABLE();
  491. // Transmit SCSI data. The source data is treated as the
  492. // peripheral (even though this is memory-to-memory)
  493. memToFSMC.Instance = DMA2_Stream0;
  494. memToFSMC.Init.Channel = DMA_CHANNEL_0;
  495. memToFSMC.Init.Direction = DMA_MEMORY_TO_MEMORY;
  496. memToFSMC.Init.PeriphInc = DMA_PINC_ENABLE;
  497. memToFSMC.Init.MemInc = DMA_MINC_DISABLE;
  498. memToFSMC.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD;
  499. memToFSMC.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
  500. memToFSMC.Init.Mode = DMA_NORMAL;
  501. memToFSMC.Init.Priority = DMA_PRIORITY_LOW;
  502. // FIFO mode is needed to allow conversion from 32bit words to the
  503. // 8bit FSMC interface.
  504. memToFSMC.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
  505. // We only use 1 word (4 bytes) in the fifo at a time. Normally it's
  506. // better to let the DMA fifo fill up then do burst transfers, but
  507. // bursting out the FSMC interface will be very slow and may starve
  508. // other (faster) transfers. We don't want to risk the SDIO transfers
  509. // from overrun/underrun conditions.
  510. memToFSMC.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
  511. memToFSMC.Init.MemBurst = DMA_MBURST_SINGLE;
  512. memToFSMC.Init.PeriphBurst = DMA_PBURST_SINGLE;
  513. HAL_DMA_Init(&memToFSMC);
  514. // Receive SCSI data. The source data (fsmc) is treated as the
  515. // peripheral (even though this is memory-to-memory)
  516. fsmcToMem.Instance = DMA2_Stream1;
  517. fsmcToMem.Init.Channel = DMA_CHANNEL_0;
  518. fsmcToMem.Init.Direction = DMA_MEMORY_TO_MEMORY;
  519. fsmcToMem.Init.PeriphInc = DMA_PINC_DISABLE;
  520. fsmcToMem.Init.MemInc = DMA_MINC_ENABLE;
  521. fsmcToMem.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
  522. fsmcToMem.Init.MemDataAlignment = DMA_MDATAALIGN_WORD;
  523. fsmcToMem.Init.Mode = DMA_NORMAL;
  524. fsmcToMem.Init.Priority = DMA_PRIORITY_LOW;
  525. fsmcToMem.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
  526. fsmcToMem.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
  527. fsmcToMem.Init.MemBurst = DMA_MBURST_SINGLE;
  528. fsmcToMem.Init.PeriphBurst = DMA_PBURST_SINGLE;
  529. HAL_DMA_Init(&fsmcToMem);
  530. // TODO configure IRQs
  531. }
  532. }
  533. void scsiPhyInit()
  534. {
  535. scsiPhyInitDMA();
  536. *SCSI_CTRL_IDMASK = 0x00; // Reset in scsiPhyConfig
  537. *SCSI_CTRL_PHASE = 0x00;
  538. *SCSI_CTRL_BSY = 0x00;
  539. scsiPhyFifoSel = 0;
  540. *SCSI_FIFO_SEL = 0;
  541. *SCSI_CTRL_DBX = 0;
  542. *SCSI_CTRL_SYNC_OFFSET = 0;
  543. *SCSI_CTRL_TIMING = SCSI_DEFAULT_TIMING;
  544. }
  545. void scsiPhyConfig()
  546. {
  547. if (scsiDev.boardCfg.flags6 & S2S_CFG_ENABLE_TERMINATOR)
  548. {
  549. HAL_GPIO_WritePin(nTERM_EN_GPIO_Port, nTERM_EN_Pin, GPIO_PIN_RESET);
  550. }
  551. else
  552. {
  553. HAL_GPIO_WritePin(nTERM_EN_GPIO_Port, nTERM_EN_Pin, GPIO_PIN_SET);
  554. }
  555. uint8_t idMask = 0;
  556. for (int i = 0; i < 8; ++i)
  557. {
  558. const S2S_TargetCfg* cfg = s2s_getConfigById(i);
  559. if (cfg && (cfg->scsiId & S2S_CFG_TARGET_ENABLED))
  560. {
  561. idMask |= (1 << i);
  562. }
  563. }
  564. *SCSI_CTRL_IDMASK = idMask;
  565. }
  566. // 1 = DBx error
  567. // 2 = Parity error
  568. // 4 = MSG error
  569. // 8 = CD error
  570. // 16 = IO error
  571. // 32 = other error
  572. int scsiSelfTest()
  573. {
  574. if (scsiDev.phase != BUS_FREE)
  575. {
  576. return 32;
  577. }
  578. // Acquire the SCSI bus.
  579. for (int i = 0; i < 100; ++i)
  580. {
  581. if (scsiStatusBSY())
  582. {
  583. s2s_delay_ms(1);
  584. }
  585. }
  586. if (scsiStatusBSY())
  587. {
  588. // Error, couldn't acquire scsi bus
  589. return 32;
  590. }
  591. *SCSI_CTRL_BSY = 1;
  592. if (! scsiStatusBSY())
  593. {
  594. // Error, BSY doesn't work.
  595. return 32;
  596. }
  597. // Should be safe to use the bus now.
  598. int result = 0;
  599. // TEST DBx
  600. // TODO test DBp
  601. int i;
  602. for (i = 0; i < 256; ++i)
  603. {
  604. *SCSI_CTRL_DBX = i;
  605. busSettleDelay();
  606. if (*SCSI_STS_DBX != (i & 0xff))
  607. {
  608. result |= 1;
  609. }
  610. /*if (Lookup_OddParity[i & 0xff] != SCSI_ReadPin(SCSI_In_DBP))
  611. {
  612. result |= 2;
  613. }*/
  614. }
  615. *SCSI_CTRL_DBX = 0;
  616. // TEST MSG, CD, IO
  617. /* TODO
  618. for (i = 0; i < 8; ++i)
  619. {
  620. SCSI_CTL_PHASE_Write(i);
  621. scsiDeskewDelay();
  622. if (SCSI_ReadPin(SCSI_In_MSG) != !!(i & __scsiphase_msg))
  623. {
  624. result |= 4;
  625. }
  626. if (SCSI_ReadPin(SCSI_In_CD) != !!(i & __scsiphase_cd))
  627. {
  628. result |= 8;
  629. }
  630. if (SCSI_ReadPin(SCSI_In_IO) != !!(i & __scsiphase_io))
  631. {
  632. result |= 16;
  633. }
  634. }
  635. SCSI_CTL_PHASE_Write(0);
  636. uint32_t signalsOut[] = { SCSI_Out_ATN, SCSI_Out_BSY, SCSI_Out_RST, SCSI_Out_SEL };
  637. uint32_t signalsIn[] = { SCSI_Filt_ATN, SCSI_Filt_BSY, SCSI_Filt_RST, SCSI_Filt_SEL };
  638. for (i = 0; i < 4; ++i)
  639. {
  640. SCSI_SetPin(signalsOut[i]);
  641. scsiDeskewDelay();
  642. int j;
  643. for (j = 0; j < 4; ++j)
  644. {
  645. if (i == j)
  646. {
  647. if (! SCSI_ReadFilt(signalsIn[j]))
  648. {
  649. result |= 32;
  650. }
  651. }
  652. else
  653. {
  654. if (SCSI_ReadFilt(signalsIn[j]))
  655. {
  656. result |= 32;
  657. }
  658. }
  659. }
  660. SCSI_ClearPin(signalsOut[i]);
  661. }
  662. */
  663. *SCSI_CTRL_BSY = 0;
  664. return result;
  665. }