scsi_accel_target.cpp 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302
  1. /**
  2. * ZuluSCSI™ - Copyright (c) 2022 Rabbit Hole Computing™
  3. *
  4. * This work incorporates work from the following
  5. * Copyright (c) 2023 joshua stein <jcs@jcs.org>
  6. *
  7. * ZuluSCSI™ firmware is licensed under the GPL version 3 or any later version.
  8. *
  9. * https://www.gnu.org/licenses/gpl-3.0.html
  10. * ----
  11. * This program is free software: you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License as published by
  13. * the Free Software Foundation, either version 3 of the License, or
  14. * (at your option) any later version.
  15. *
  16. * This program is distributed in the hope that it will be useful,
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. * GNU General Public License for more details.
  20. *
  21. * You should have received a copy of the GNU General Public License
  22. * along with this program.  If not, see <https://www.gnu.org/licenses/>.
  23. **/
  24. /* Data flow in SCSI acceleration:
  25. *
  26. * 1. Application provides a buffer of bytes to send.
  27. * 2. Code in this module adds parity bit to the bytes and packs two bytes into 32 bit words.
  28. * 3. DMA controller copies the words to PIO peripheral FIFO.
  29. * 4. PIO peripheral handles low-level SCSI handshake and writes bytes and parity to GPIO.
  30. */
  31. #include "ZuluSCSI_platform.h"
  32. #include "ZuluSCSI_log.h"
  33. #include "scsi_accel_target.h"
  34. #include "timings.h"
  35. #include <hardware/pio.h>
  36. #include <hardware/dma.h>
  37. #include <hardware/irq.h>
  38. #include <hardware/structs/iobank0.h>
  39. #include <hardware/sync.h>
  40. #include <pico/multicore.h>
  41. #ifdef ENABLE_AUDIO_OUTPUT
  42. #include <audio.h>
  43. #endif // ENABLE_AUDIO_OUTPUT
  44. #if defined(ZULUSCSI_PICO) || defined(ZULUSCSI_BS2)
  45. # include "scsi_accel_target_Pico.pio.h"
  46. #elif defined(ZULUSCSI_PICO_2)
  47. # include "scsi_accel_target_Pico_2.pio.h"
  48. #elif defined(ZULUSCSI_RP2350A)
  49. # include "scsi_accel_target_RP2350A.pio.h"
  50. #else
  51. # include "scsi_accel_target_RP2040.pio.h"
  52. #endif
  53. // SCSI bus write acceleration uses up to 3 PIO state machines:
  54. // SM0: Convert data bytes to lookup addresses to add parity
  55. // SM1: Write data to SCSI bus
  56. // SM2: For synchronous mode only, count ACK pulses
  57. #ifdef ZULUSCSI_NETWORK
  58. # define SCSI_DMA_PIO pio0
  59. # define SCSI_PARITY_SM 1
  60. # define SCSI_DATA_SM 2
  61. # define SCSI_SYNC_SM 3
  62. #else
  63. # define SCSI_DMA_PIO pio0
  64. # define SCSI_PARITY_SM 0
  65. # define SCSI_DATA_SM 1
  66. # define SCSI_SYNC_SM 2
  67. #endif // ZULUSCSI_NETWORK
  68. // SCSI bus write acceleration uses 3 or 4 DMA channels (data flow A->B->C->D):
  69. // A: Bytes from RAM to scsi_parity PIO
  70. // B: Addresses from scsi_parity PIO to lookup DMA READ_ADDR register
  71. // C: Lookup from g_scsi_parity_lookup and copy to scsi_accel_async_write or scsi_sync_write PIO
  72. // D: For sync transfers, scsi_sync_write to scsi_sync_write_pacer PIO
  73. //
  74. // SCSI bus read acceleration uses 4 DMA channels (data flow D->C->B->A):
  75. // A: Bytes from scsi_read_parity PIO to memory buffer
  76. // B: Lookup from g_scsi_parity_check_lookup and copy to scsi_read_parity PIO
  77. // C: Addresses from scsi_accel_read PIO to lookup DMA READ_ADDR register
  78. // D: From pacer to data state machine to trigger transfers
  79. #ifdef ZULUSCSI_NETWORK
  80. # define SCSI_DMA_CH_A 6
  81. # define SCSI_DMA_CH_B 7
  82. # define SCSI_DMA_CH_C 8
  83. # define SCSI_DMA_CH_D 9
  84. #else
  85. # define SCSI_DMA_CH_A 0
  86. # define SCSI_DMA_CH_B 1
  87. # define SCSI_DMA_CH_C 2
  88. # define SCSI_DMA_CH_D 3
  89. #endif
  90. static struct {
  91. uint8_t *app_buf; // Buffer provided by application
  92. uint32_t app_bytes; // Bytes available in application buffer
  93. uint32_t dma_bytes; // Bytes that have been scheduled for DMA so far
  94. uint8_t *next_app_buf; // Next buffer from application after current one finishes
  95. uint32_t next_app_bytes; // Bytes in next buffer
  96. // Synchronous mode?
  97. int syncOffset;
  98. int syncPeriod;
  99. int syncOffsetDivider; // Autopush/autopull threshold for the write pacer state machine
  100. int syncOffsetPreload; // Number of items to preload in the RX fifo of scsi_sync_write
  101. // PIO configurations
  102. uint32_t pio_offset_parity;
  103. uint32_t pio_offset_async_write;
  104. uint32_t pio_offset_sync_write_pacer;
  105. uint32_t pio_offset_sync_write;
  106. uint32_t pio_offset_read;
  107. uint32_t pio_offset_read_parity;
  108. uint32_t pio_offset_sync_read_pacer;
  109. pio_sm_config pio_cfg_parity;
  110. pio_sm_config pio_cfg_async_write;
  111. pio_sm_config pio_cfg_sync_write_pacer;
  112. pio_sm_config pio_cfg_sync_write;
  113. pio_sm_config pio_cfg_read;
  114. pio_sm_config pio_cfg_read_parity;
  115. pio_sm_config pio_cfg_sync_read_pacer;
  116. bool pio_removed_parity;
  117. bool pio_removed_async_write;
  118. bool pio_removed_sync_write_pacer;
  119. bool pio_removed_sync_write;
  120. bool pio_removed_read;
  121. bool pio_removed_read_parity;
  122. bool pio_removed_sync_read_pacer;
  123. // DMA configurations for write
  124. dma_channel_config dmacfg_write_chA; // Data from RAM to scsi_parity PIO
  125. dma_channel_config dmacfg_write_chB; // Addresses from scsi_parity PIO to lookup DMA
  126. dma_channel_config dmacfg_write_chC; // Data from g_scsi_parity_lookup to scsi write PIO
  127. dma_channel_config dmacfg_write_chD; // In synchronous mode only, transfer between state machines
  128. // DMA configurations for read
  129. dma_channel_config dmacfg_read_chA; // Data to destination memory buffer
  130. dma_channel_config dmacfg_read_chB; // From lookup table to scsi_read_parity PIO
  131. dma_channel_config dmacfg_read_chC; // From scsi_accel_read to channel B READ_ADDR
  132. dma_channel_config dmacfg_read_chD; // From pacer to data state machine
  133. } g_scsi_dma;
  134. enum scsidma_state_t { SCSIDMA_IDLE = 0,
  135. SCSIDMA_WRITE, SCSIDMA_WRITE_DONE,
  136. SCSIDMA_READ, SCSIDMA_READ_DONE };
  137. static const char* scsidma_states[5] = {"IDLE", "WRITE", "WRITE_DONE", "READ", "READ_DONE"};
  138. static volatile scsidma_state_t g_scsi_dma_state;
  139. static bool g_channels_claimed = false;
  140. static void scsidma_config_gpio();
  141. void scsi_accel_log_state()
  142. {
  143. logmsg("SCSI DMA state: ", scsidma_states[g_scsi_dma_state]);
  144. logmsg("Current buffer: ", g_scsi_dma.dma_bytes, "/", g_scsi_dma.app_bytes, ", next ", g_scsi_dma.next_app_bytes, " bytes");
  145. logmsg("SyncOffset: ", g_scsi_dma.syncOffset, " SyncPeriod ", g_scsi_dma.syncPeriod);
  146. logmsg("PIO Parity SM:",
  147. " tx_fifo ", (int)pio_sm_get_tx_fifo_level(SCSI_DMA_PIO, SCSI_PARITY_SM),
  148. ", rx_fifo ", (int)pio_sm_get_rx_fifo_level(SCSI_DMA_PIO, SCSI_PARITY_SM),
  149. ", pc ", (int)pio_sm_get_pc(SCSI_DMA_PIO, SCSI_PARITY_SM),
  150. ", instr ", SCSI_DMA_PIO->sm[SCSI_PARITY_SM].instr);
  151. logmsg("PIO Data SM:",
  152. " tx_fifo ", (int)pio_sm_get_tx_fifo_level(SCSI_DMA_PIO, SCSI_DATA_SM),
  153. ", rx_fifo ", (int)pio_sm_get_rx_fifo_level(SCSI_DMA_PIO, SCSI_DATA_SM),
  154. ", pc ", (int)pio_sm_get_pc(SCSI_DMA_PIO, SCSI_DATA_SM),
  155. ", instr ", SCSI_DMA_PIO->sm[SCSI_DATA_SM].instr);
  156. logmsg("PIO Sync SM:",
  157. " tx_fifo ", (int)pio_sm_get_tx_fifo_level(SCSI_DMA_PIO, SCSI_SYNC_SM),
  158. ", rx_fifo ", (int)pio_sm_get_rx_fifo_level(SCSI_DMA_PIO, SCSI_SYNC_SM),
  159. ", pc ", (int)pio_sm_get_pc(SCSI_DMA_PIO, SCSI_SYNC_SM),
  160. ", instr ", SCSI_DMA_PIO->sm[SCSI_SYNC_SM].instr);
  161. logmsg("DMA CH A:",
  162. " ctrl: ", dma_hw->ch[SCSI_DMA_CH_A].ctrl_trig,
  163. " count: ", dma_hw->ch[SCSI_DMA_CH_A].transfer_count);
  164. logmsg("DMA CH B:",
  165. " ctrl: ", dma_hw->ch[SCSI_DMA_CH_B].ctrl_trig,
  166. " count: ", dma_hw->ch[SCSI_DMA_CH_B].transfer_count);
  167. logmsg("DMA CH C:",
  168. " ctrl: ", dma_hw->ch[SCSI_DMA_CH_C].ctrl_trig,
  169. " count: ", dma_hw->ch[SCSI_DMA_CH_C].transfer_count);
  170. logmsg("DMA CH D:",
  171. " ctrl: ", dma_hw->ch[SCSI_DMA_CH_D].ctrl_trig,
  172. " count: ", dma_hw->ch[SCSI_DMA_CH_D].transfer_count);
  173. logmsg("GPIO states: ", sio_hw->gpio_in);
  174. }
  175. /****************************************/
  176. /* Accelerated writes to SCSI bus */
  177. /****************************************/
  178. // Load the SCSI parity state machine with the address of the parity lookup table.
  179. // Also sets up DMA channels B and C
  180. static void config_parity_sm_for_write()
  181. {
  182. // Load base address to state machine register X
  183. uint32_t addrbase = (uint32_t)&g_scsi_parity_lookup[0];
  184. assert((addrbase & 0x1FF) == 0);
  185. pio_sm_init(SCSI_DMA_PIO, SCSI_PARITY_SM, g_scsi_dma.pio_offset_parity, &g_scsi_dma.pio_cfg_parity);
  186. pio_sm_put(SCSI_DMA_PIO, SCSI_PARITY_SM, addrbase >> 9);
  187. pio_sm_exec(SCSI_DMA_PIO, SCSI_PARITY_SM, pio_encode_pull(false, false));
  188. pio_sm_exec(SCSI_DMA_PIO, SCSI_PARITY_SM, pio_encode_mov(pio_x, pio_osr));
  189. // DMA channel B will copy addresses from parity PIO to DMA channel C read address register.
  190. // It is triggered by the parity SM RX FIFO request
  191. dma_channel_configure(SCSI_DMA_CH_B,
  192. &g_scsi_dma.dmacfg_write_chB,
  193. &dma_hw->ch[SCSI_DMA_CH_C].al3_read_addr_trig,
  194. &SCSI_DMA_PIO->rxf[SCSI_PARITY_SM],
  195. 1, true);
  196. // DMA channel C will read g_scsi_parity_lookup to copy data + parity to SCSI write state machine.
  197. // It is triggered by SCSI write machine TX FIFO request and chains to re-enable channel B.
  198. dma_channel_configure(SCSI_DMA_CH_C,
  199. &g_scsi_dma.dmacfg_write_chC,
  200. &SCSI_DMA_PIO->txf[SCSI_DATA_SM],
  201. NULL,
  202. 1, false);
  203. }
  204. static void start_dma_write()
  205. {
  206. if (g_scsi_dma.app_bytes <= g_scsi_dma.dma_bytes)
  207. {
  208. // Buffer has been fully processed, swap it
  209. g_scsi_dma.dma_bytes = 0;
  210. g_scsi_dma.app_buf = g_scsi_dma.next_app_buf;
  211. g_scsi_dma.app_bytes = g_scsi_dma.next_app_bytes;
  212. g_scsi_dma.next_app_buf = 0;
  213. g_scsi_dma.next_app_bytes = 0;
  214. }
  215. // Check if we are all done.
  216. // From SCSIDMA_WRITE_DONE state we can either go to IDLE in stopWrite()
  217. // or back to WRITE in startWrite().
  218. uint32_t bytes_to_send = g_scsi_dma.app_bytes - g_scsi_dma.dma_bytes;
  219. if (bytes_to_send == 0)
  220. {
  221. g_scsi_dma_state = SCSIDMA_WRITE_DONE;
  222. return;
  223. }
  224. uint8_t *src_buf = &g_scsi_dma.app_buf[g_scsi_dma.dma_bytes];
  225. g_scsi_dma.dma_bytes += bytes_to_send;
  226. // Start DMA from current buffer to parity generator
  227. dma_channel_configure(SCSI_DMA_CH_A,
  228. &g_scsi_dma.dmacfg_write_chA,
  229. &SCSI_DMA_PIO->txf[SCSI_PARITY_SM],
  230. src_buf,
  231. bytes_to_send,
  232. true
  233. );
  234. }
  235. void scsi_accel_rp2040_startWrite(const uint8_t* data, uint32_t count, volatile int *resetFlag)
  236. {
  237. // Any read requests should be matched with a stopRead()
  238. assert(g_scsi_dma_state != SCSIDMA_READ && g_scsi_dma_state != SCSIDMA_READ_DONE);
  239. uint32_t saved_irq = save_and_disable_interrupts();
  240. if (g_scsi_dma_state == SCSIDMA_WRITE)
  241. {
  242. if (!g_scsi_dma.next_app_buf && data == g_scsi_dma.app_buf + g_scsi_dma.app_bytes)
  243. {
  244. // Combine with currently running request
  245. g_scsi_dma.app_bytes += count;
  246. count = 0;
  247. }
  248. else if (data == g_scsi_dma.next_app_buf + g_scsi_dma.next_app_bytes)
  249. {
  250. // Combine with queued request
  251. g_scsi_dma.next_app_bytes += count;
  252. count = 0;
  253. }
  254. else if (!g_scsi_dma.next_app_buf)
  255. {
  256. // Add as queued request
  257. g_scsi_dma.next_app_buf = (uint8_t*)data;
  258. g_scsi_dma.next_app_bytes = count;
  259. count = 0;
  260. }
  261. }
  262. restore_interrupts(saved_irq);
  263. // Check if the request was combined
  264. if (count == 0) return;
  265. if (g_scsi_dma_state != SCSIDMA_IDLE && g_scsi_dma_state != SCSIDMA_WRITE_DONE)
  266. {
  267. // Wait for previous request to finish
  268. scsi_accel_rp2040_finishWrite(resetFlag);
  269. if (*resetFlag)
  270. {
  271. return;
  272. }
  273. }
  274. bool must_reconfig_gpio = (g_scsi_dma_state == SCSIDMA_IDLE);
  275. g_scsi_dma_state = SCSIDMA_WRITE;
  276. g_scsi_dma.app_buf = (uint8_t*)data;
  277. g_scsi_dma.app_bytes = count;
  278. g_scsi_dma.dma_bytes = 0;
  279. g_scsi_dma.next_app_buf = 0;
  280. g_scsi_dma.next_app_bytes = 0;
  281. if (must_reconfig_gpio)
  282. {
  283. SCSI_ENABLE_DATA_OUT();
  284. if (g_scsi_dma.syncOffset == 0)
  285. {
  286. // Asynchronous write
  287. config_parity_sm_for_write();
  288. pio_sm_init(SCSI_DMA_PIO, SCSI_DATA_SM, g_scsi_dma.pio_offset_async_write, &g_scsi_dma.pio_cfg_async_write);
  289. scsidma_config_gpio();
  290. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_DATA_SM, true);
  291. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_PARITY_SM, true);
  292. }
  293. else
  294. {
  295. // Synchronous write
  296. // Data state machine writes data to SCSI bus and dummy bits to its RX fifo.
  297. // Sync state machine empties the dummy bits every time ACK is received, to control the transmit pace.
  298. config_parity_sm_for_write();
  299. pio_sm_init(SCSI_DMA_PIO, SCSI_DATA_SM, g_scsi_dma.pio_offset_sync_write, &g_scsi_dma.pio_cfg_sync_write);
  300. pio_sm_init(SCSI_DMA_PIO, SCSI_SYNC_SM, g_scsi_dma.pio_offset_sync_write_pacer, &g_scsi_dma.pio_cfg_sync_write_pacer);
  301. scsidma_config_gpio();
  302. // Prefill RX fifo to set the syncOffset
  303. for (int i = 0; i < g_scsi_dma.syncOffsetPreload; i++)
  304. {
  305. pio_sm_exec(SCSI_DMA_PIO, SCSI_DATA_SM,
  306. pio_encode_push(false, false) | pio_encode_sideset(1, 1));
  307. }
  308. // Fill the pacer TX fifo
  309. // DMA should start transferring only after ACK pulses are received
  310. for (int i = 0; i < 4; i++)
  311. {
  312. pio_sm_put(SCSI_DMA_PIO, SCSI_SYNC_SM, 0);
  313. }
  314. // Fill the pacer OSR
  315. pio_sm_exec(SCSI_DMA_PIO, SCSI_SYNC_SM,
  316. pio_encode_mov(pio_osr, pio_null));
  317. // Start DMA transfer to move dummy bits to write pacer
  318. dma_channel_configure(SCSI_DMA_CH_D,
  319. &g_scsi_dma.dmacfg_write_chD,
  320. &SCSI_DMA_PIO->txf[SCSI_SYNC_SM],
  321. &SCSI_DMA_PIO->rxf[SCSI_DATA_SM],
  322. 0xFFFFFFFF,
  323. true
  324. );
  325. // Enable state machines
  326. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_SYNC_SM, true);
  327. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_DATA_SM, true);
  328. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_PARITY_SM, true);
  329. }
  330. dma_channel_set_irq0_enabled(SCSI_DMA_CH_A, true);
  331. }
  332. start_dma_write();
  333. }
  334. bool scsi_accel_rp2040_isWriteFinished(const uint8_t* data)
  335. {
  336. // Check if everything has completed
  337. if (g_scsi_dma_state == SCSIDMA_IDLE || g_scsi_dma_state == SCSIDMA_WRITE_DONE)
  338. {
  339. return true;
  340. }
  341. if (!data)
  342. return false;
  343. // Check if this data item is still in queue.
  344. bool finished = true;
  345. uint32_t saved_irq = save_and_disable_interrupts();
  346. if (data >= g_scsi_dma.app_buf &&
  347. data < g_scsi_dma.app_buf + g_scsi_dma.app_bytes &&
  348. (uint32_t)data >= dma_hw->ch[SCSI_DMA_CH_A].al1_read_addr)
  349. {
  350. finished = false; // In current transfer
  351. }
  352. else if (data >= g_scsi_dma.next_app_buf &&
  353. data < g_scsi_dma.next_app_buf + g_scsi_dma.next_app_bytes)
  354. {
  355. finished = false; // In queued transfer
  356. }
  357. restore_interrupts(saved_irq);
  358. return finished;
  359. }
  360. // Once DMA has finished, check if all PIO queues have been drained
  361. static bool scsi_accel_rp2040_isWriteDone()
  362. {
  363. // Check if data is still waiting in PIO FIFO
  364. if (!pio_sm_is_tx_fifo_empty(SCSI_DMA_PIO, SCSI_PARITY_SM) ||
  365. !pio_sm_is_rx_fifo_empty(SCSI_DMA_PIO, SCSI_PARITY_SM) ||
  366. !pio_sm_is_tx_fifo_empty(SCSI_DMA_PIO, SCSI_DATA_SM))
  367. {
  368. return false;
  369. }
  370. if (g_scsi_dma.syncOffset > 0)
  371. {
  372. // Check if all bytes of synchronous write have been acknowledged
  373. if (pio_sm_get_rx_fifo_level(SCSI_DMA_PIO, SCSI_DATA_SM) > g_scsi_dma.syncOffsetPreload)
  374. return false;
  375. }
  376. else
  377. {
  378. // Check if state machine has written out its OSR
  379. if (pio_sm_get_pc(SCSI_DMA_PIO, SCSI_DATA_SM) != g_scsi_dma.pio_offset_async_write)
  380. return false;
  381. }
  382. // Check if ACK of the final byte has finished
  383. if (SCSI_IN(ACK))
  384. return false;
  385. return true;
  386. }
  387. static void scsi_accel_rp2040_stopWrite(volatile int *resetFlag)
  388. {
  389. // Wait for TX fifo to be empty and ACK to go high
  390. // For synchronous writes wait for all ACKs to be received also
  391. uint32_t start = millis();
  392. while (!scsi_accel_rp2040_isWriteDone() && !*resetFlag)
  393. {
  394. if ((uint32_t)(millis() - start) > 5000)
  395. {
  396. logmsg("scsi_accel_rp2040_stopWrite() timeout");
  397. scsi_accel_log_state();
  398. *resetFlag = 1;
  399. break;
  400. }
  401. }
  402. dma_channel_abort(SCSI_DMA_CH_A);
  403. dma_channel_abort(SCSI_DMA_CH_B);
  404. dma_channel_abort(SCSI_DMA_CH_C);
  405. dma_channel_abort(SCSI_DMA_CH_D);
  406. dma_channel_set_irq0_enabled(SCSI_DMA_CH_A, false);
  407. g_scsi_dma_state = SCSIDMA_IDLE;
  408. SCSI_RELEASE_DATA_REQ();
  409. scsidma_config_gpio();
  410. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_PARITY_SM, false);
  411. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_DATA_SM, false);
  412. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_SYNC_SM, false);
  413. }
  414. void scsi_accel_rp2040_finishWrite(volatile int *resetFlag)
  415. {
  416. uint32_t start = millis();
  417. while (g_scsi_dma_state != SCSIDMA_IDLE && !*resetFlag)
  418. {
  419. if ((uint32_t)(millis() - start) > 5000)
  420. {
  421. logmsg("scsi_accel_rp2040_finishWrite() timeout");
  422. scsi_accel_log_state();
  423. *resetFlag = 1;
  424. break;
  425. }
  426. if (g_scsi_dma_state == SCSIDMA_WRITE_DONE || *resetFlag)
  427. {
  428. // DMA done, wait for PIO to finish also and reconfig GPIO.
  429. scsi_accel_rp2040_stopWrite(resetFlag);
  430. }
  431. }
  432. }
  433. /****************************************/
  434. /* Accelerated reads from SCSI bus */
  435. /****************************************/
  436. // Load the SCSI read state machine with the address of the parity lookup table.
  437. // Also sets up DMA channels B, C and D
  438. static void config_parity_sm_for_read()
  439. {
  440. // Configure parity check state machine
  441. pio_sm_init(SCSI_DMA_PIO, SCSI_PARITY_SM, g_scsi_dma.pio_offset_read_parity, &g_scsi_dma.pio_cfg_read_parity);
  442. // Load base address to state machine register X
  443. uint32_t addrbase = (uint32_t)&g_scsi_parity_check_lookup[0];
  444. assert((addrbase & 0x3FF) == 0);
  445. pio_sm_init(SCSI_DMA_PIO, SCSI_DATA_SM, g_scsi_dma.pio_offset_read, &g_scsi_dma.pio_cfg_read);
  446. pio_sm_put(SCSI_DMA_PIO, SCSI_DATA_SM, addrbase >> 10);
  447. pio_sm_exec(SCSI_DMA_PIO, SCSI_DATA_SM, pio_encode_pull(false, false) | pio_encode_sideset(1, 1));
  448. pio_sm_exec(SCSI_DMA_PIO, SCSI_DATA_SM, pio_encode_mov(pio_y, pio_osr) | pio_encode_sideset(1, 1));
  449. // For synchronous mode, the REQ pin is driven by SCSI_SYNC_SM, so disable it in SCSI_DATA_SM
  450. if (g_scsi_dma.syncOffset > 0)
  451. {
  452. pio_sm_set_sideset_pins(SCSI_DMA_PIO, SCSI_DATA_SM, 0);
  453. }
  454. // DMA channel B will read g_scsi_parity_check_lookup and write to scsi_read_parity PIO.
  455. dma_channel_configure(SCSI_DMA_CH_B,
  456. &g_scsi_dma.dmacfg_read_chB,
  457. &SCSI_DMA_PIO->txf[SCSI_PARITY_SM],
  458. NULL,
  459. 1, false);
  460. // DMA channel C will copy addresses from data PIO to DMA channel B read address register.
  461. // It is triggered by the data SM RX FIFO request.
  462. // This triggers channel B by writing to READ_ADDR_TRIG
  463. // Channel B chaining re-enables this channel.
  464. dma_channel_configure(SCSI_DMA_CH_C,
  465. &g_scsi_dma.dmacfg_read_chC,
  466. &dma_hw->ch[SCSI_DMA_CH_B].al3_read_addr_trig,
  467. &SCSI_DMA_PIO->rxf[SCSI_DATA_SM],
  468. 1, true);
  469. if (g_scsi_dma.syncOffset == 0)
  470. {
  471. // DMA channel D will copy dummy words to scsi_accel_read PIO to set the number
  472. // of bytes to transfer.
  473. static const uint32_t dummy = 0;
  474. dma_channel_configure(SCSI_DMA_CH_D,
  475. &g_scsi_dma.dmacfg_read_chD,
  476. &SCSI_DMA_PIO->txf[SCSI_DATA_SM],
  477. &dummy,
  478. 0, false);
  479. }
  480. else
  481. {
  482. pio_sm_init(SCSI_DMA_PIO, SCSI_SYNC_SM, g_scsi_dma.pio_offset_sync_read_pacer, &g_scsi_dma.pio_cfg_sync_read_pacer);
  483. // DMA channel D will copy words from scsi_sync_read_pacer to scsi_accel_read PIO
  484. // to control the offset between REQ pulses sent and ACK pulses received.
  485. dma_channel_configure(SCSI_DMA_CH_D,
  486. &g_scsi_dma.dmacfg_read_chD,
  487. &SCSI_DMA_PIO->txf[SCSI_DATA_SM],
  488. &SCSI_DMA_PIO->rxf[SCSI_SYNC_SM],
  489. 0, false);
  490. }
  491. // Clear PIO IRQ flag that is used to detect parity error
  492. SCSI_DMA_PIO->irq = 1;
  493. }
  494. static void start_dma_read()
  495. {
  496. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_PARITY_SM, false);
  497. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_DATA_SM, false);
  498. pio_sm_clear_fifos(SCSI_DMA_PIO, SCSI_PARITY_SM);
  499. pio_sm_clear_fifos(SCSI_DMA_PIO, SCSI_DATA_SM);
  500. if (g_scsi_dma.app_bytes <= g_scsi_dma.dma_bytes)
  501. {
  502. // Buffer has been fully processed, swap it
  503. g_scsi_dma.dma_bytes = 0;
  504. g_scsi_dma.app_buf = g_scsi_dma.next_app_buf;
  505. g_scsi_dma.app_bytes = g_scsi_dma.next_app_bytes;
  506. g_scsi_dma.next_app_buf = 0;
  507. g_scsi_dma.next_app_bytes = 0;
  508. }
  509. // Check if we are all done.
  510. // From SCSIDMA_READ_DONE state we can either go to IDLE in stopRead()
  511. // or back to READ in startWrite().
  512. uint32_t bytes_to_read = g_scsi_dma.app_bytes - g_scsi_dma.dma_bytes;
  513. if (bytes_to_read == 0)
  514. {
  515. g_scsi_dma_state = SCSIDMA_READ_DONE;
  516. return;
  517. }
  518. if (g_scsi_dma.syncOffset == 0)
  519. {
  520. // Start sending dummy words to scsi_accel_read state machine
  521. dma_channel_set_trans_count(SCSI_DMA_CH_D, bytes_to_read, true);
  522. }
  523. else
  524. {
  525. // Set number of bytes to receive to the scsi_sync_read_pacer state machine register X
  526. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_SYNC_SM, false);
  527. hw_clear_bits(&SCSI_DMA_PIO->sm[SCSI_SYNC_SM].shiftctrl, PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS);
  528. pio_sm_put(SCSI_DMA_PIO, SCSI_SYNC_SM, bytes_to_read - 1);
  529. pio_sm_exec(SCSI_DMA_PIO, SCSI_SYNC_SM, pio_encode_pull(false, false) | pio_encode_sideset(1, 1));
  530. pio_sm_exec(SCSI_DMA_PIO, SCSI_SYNC_SM, pio_encode_mov(pio_x, pio_osr) | pio_encode_sideset(1, 1));
  531. hw_set_bits(&SCSI_DMA_PIO->sm[SCSI_SYNC_SM].shiftctrl, PIO_SM0_SHIFTCTRL_FJOIN_RX_BITS);
  532. // Prefill FIFOs to get correct syncOffset
  533. int prefill = 12 - g_scsi_dma.syncOffset;
  534. // Always at least 1 word to avoid race condition between REQ and ACK pulses
  535. if (prefill < 1) prefill = 1;
  536. // Up to 4 words in SCSI_DATA_SM TX fifo
  537. for (int i = 0; i < 4 && prefill > 0; i++)
  538. {
  539. pio_sm_put(SCSI_DMA_PIO, SCSI_DATA_SM, 0);
  540. prefill--;
  541. }
  542. // Up to 8 words in SCSI_SYNC_SM RX fifo
  543. for (int i = 0; i < 8 && prefill > 0; i++)
  544. {
  545. pio_sm_exec(SCSI_DMA_PIO, SCSI_SYNC_SM, pio_encode_push(false, false) | pio_encode_sideset(1, 1));
  546. prefill--;
  547. }
  548. pio_sm_exec(SCSI_DMA_PIO, SCSI_SYNC_SM, pio_encode_jmp(g_scsi_dma.pio_offset_sync_read_pacer) | pio_encode_sideset(1, 1));
  549. // Start transfers
  550. dma_channel_set_trans_count(SCSI_DMA_CH_D, bytes_to_read, true);
  551. }
  552. // Start DMA to fill the destination buffer
  553. uint8_t *dest_buf = &g_scsi_dma.app_buf[g_scsi_dma.dma_bytes];
  554. g_scsi_dma.dma_bytes += bytes_to_read;
  555. dma_channel_configure(SCSI_DMA_CH_A,
  556. &g_scsi_dma.dmacfg_read_chA,
  557. dest_buf,
  558. &SCSI_DMA_PIO->rxf[SCSI_PARITY_SM],
  559. bytes_to_read,
  560. true
  561. );
  562. // Ready to start the data and parity check state machines
  563. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_PARITY_SM, true);
  564. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_DATA_SM, true);
  565. if (g_scsi_dma.syncOffset > 0)
  566. {
  567. // Start sending REQ pulses
  568. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_SYNC_SM, true);
  569. }
  570. }
  571. void scsi_accel_rp2040_startRead(uint8_t *data, uint32_t count, int *parityError, volatile int *resetFlag)
  572. {
  573. // Any write requests should be matched with a stopWrite()
  574. assert(g_scsi_dma_state != SCSIDMA_WRITE && g_scsi_dma_state != SCSIDMA_WRITE_DONE);
  575. uint32_t saved_irq = save_and_disable_interrupts();
  576. if (g_scsi_dma_state == SCSIDMA_READ)
  577. {
  578. if (!g_scsi_dma.next_app_buf && data == g_scsi_dma.app_buf + g_scsi_dma.app_bytes)
  579. {
  580. // Combine with currently running request
  581. g_scsi_dma.app_bytes += count;
  582. count = 0;
  583. }
  584. else if (data == g_scsi_dma.next_app_buf + g_scsi_dma.next_app_bytes)
  585. {
  586. // Combine with queued request
  587. g_scsi_dma.next_app_bytes += count;
  588. count = 0;
  589. }
  590. else if (!g_scsi_dma.next_app_buf)
  591. {
  592. // Add as queued request
  593. g_scsi_dma.next_app_buf = (uint8_t*)data;
  594. g_scsi_dma.next_app_bytes = count;
  595. count = 0;
  596. }
  597. }
  598. restore_interrupts(saved_irq);
  599. // Check if the request was combined
  600. if (count == 0) return;
  601. if (g_scsi_dma_state != SCSIDMA_IDLE && g_scsi_dma_state != SCSIDMA_READ_DONE)
  602. {
  603. // Wait for previous request to finish
  604. scsi_accel_rp2040_finishRead(NULL, 0, parityError, resetFlag);
  605. if (*resetFlag)
  606. {
  607. return;
  608. }
  609. }
  610. bool must_reconfig_gpio = (g_scsi_dma_state == SCSIDMA_IDLE);
  611. g_scsi_dma_state = SCSIDMA_READ;
  612. g_scsi_dma.app_buf = (uint8_t*)data;
  613. g_scsi_dma.app_bytes = count;
  614. g_scsi_dma.dma_bytes = 0;
  615. g_scsi_dma.next_app_buf = 0;
  616. g_scsi_dma.next_app_bytes = 0;
  617. if (must_reconfig_gpio)
  618. {
  619. config_parity_sm_for_read();
  620. scsidma_config_gpio();
  621. dma_channel_set_irq0_enabled(SCSI_DMA_CH_A, true);
  622. }
  623. start_dma_read();
  624. }
  625. bool scsi_accel_rp2040_isReadFinished(const uint8_t* data)
  626. {
  627. // Check if everything has completed
  628. if (g_scsi_dma_state == SCSIDMA_IDLE || g_scsi_dma_state == SCSIDMA_READ_DONE)
  629. {
  630. return true;
  631. }
  632. if (!data)
  633. return false;
  634. // Check if this data item is still in queue.
  635. bool finished = true;
  636. uint32_t saved_irq = save_and_disable_interrupts();
  637. if (data >= g_scsi_dma.app_buf &&
  638. data < g_scsi_dma.app_buf + g_scsi_dma.app_bytes &&
  639. (uint32_t)data >= dma_hw->ch[SCSI_DMA_CH_A].write_addr)
  640. {
  641. finished = false; // In current transfer
  642. }
  643. else if (data >= g_scsi_dma.next_app_buf &&
  644. data < g_scsi_dma.next_app_buf + g_scsi_dma.next_app_bytes)
  645. {
  646. finished = false; // In queued transfer
  647. }
  648. restore_interrupts(saved_irq);
  649. return finished;
  650. }
  651. static void scsi_accel_rp2040_stopRead()
  652. {
  653. dma_channel_abort(SCSI_DMA_CH_A);
  654. dma_channel_abort(SCSI_DMA_CH_B);
  655. dma_channel_abort(SCSI_DMA_CH_C);
  656. dma_channel_abort(SCSI_DMA_CH_D);
  657. dma_channel_set_irq0_enabled(SCSI_DMA_CH_A, false);
  658. g_scsi_dma_state = SCSIDMA_IDLE;
  659. SCSI_RELEASE_DATA_REQ();
  660. scsidma_config_gpio();
  661. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_PARITY_SM, false);
  662. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_DATA_SM, false);
  663. pio_sm_set_enabled(SCSI_DMA_PIO, SCSI_SYNC_SM, false);
  664. }
  665. void scsi_accel_rp2040_finishRead(const uint8_t *data, uint32_t count, int *parityError, volatile int *resetFlag)
  666. {
  667. uint32_t start = millis();
  668. const uint8_t *query_addr = (data ? (data + count - 1) : NULL);
  669. while (!scsi_accel_rp2040_isReadFinished(query_addr) && !*resetFlag)
  670. {
  671. if ((uint32_t)(millis() - start) > 5000)
  672. {
  673. logmsg("scsi_accel_rp2040_finishRead timeout");
  674. scsi_accel_log_state();
  675. *resetFlag = 1;
  676. break;
  677. }
  678. }
  679. if (g_scsi_dma_state == SCSIDMA_READ_DONE || *resetFlag)
  680. {
  681. // This was last buffer, release bus
  682. scsi_accel_rp2040_stopRead();
  683. }
  684. // Check if any parity errors have been detected during the transfer so far
  685. if (parityError != NULL && (SCSI_DMA_PIO->irq & 1))
  686. {
  687. dbgmsg("scsi_accel_rp2040_finishRead(", bytearray(data, count), ") detected parity error");
  688. *parityError = true;
  689. }
  690. }
  691. /*******************************************************/
  692. /* Write SCSI PIO program timings and ACK pin */
  693. /*******************************************************/
  694. static void zulu_pio_remove_program(PIO pio, const pio_program_t *program, uint loaded_offset, bool &removed)
  695. {
  696. if (!removed)
  697. {
  698. pio_remove_program(pio, program, loaded_offset);
  699. removed = true;
  700. }
  701. }
  702. static int pio_add_scsi_accel_async_write_program()
  703. {
  704. zulu_pio_remove_program(SCSI_DMA_PIO,
  705. &scsi_accel_async_write_program,
  706. g_scsi_dma.pio_offset_async_write,
  707. g_scsi_dma.pio_removed_async_write);
  708. uint16_t rewrote_instructions[sizeof(scsi_accel_async_write_program_instructions)/sizeof(scsi_accel_async_write_program_instructions[0])];
  709. pio_program rewrote_program = {rewrote_instructions,
  710. scsi_accel_async_write_program.length,
  711. scsi_accel_async_write_program.origin,
  712. scsi_accel_async_write_program.pio_version};
  713. memcpy(rewrote_instructions,
  714. scsi_accel_async_write_program_instructions,
  715. sizeof(scsi_accel_async_write_program_instructions));
  716. // out null, 23 side 1 [0] ;[REQ_DLY-2] ; Discard unused bits, wait for data preset time
  717. uint8_t delay = g_zuluscsi_timings.scsi.req_delay - 2;
  718. assert( delay <= 0xF);
  719. rewrote_instructions[2] |= pio_encode_delay(delay);
  720. // wait 1 gpio ACK side 1 ; Wait for ACK to be inactive
  721. rewrote_instructions[3] = pio_encode_wait_gpio(true, SCSI_IN_ACK) | pio_encode_sideset(1, 1);
  722. // wait 0 gpio ACK side 0 ; Assert REQ, wait for ACK low
  723. rewrote_instructions[4] = pio_encode_wait_gpio(false, SCSI_IN_ACK) | pio_encode_sideset(1, 0);
  724. g_scsi_dma.pio_removed_async_write = false;
  725. return pio_add_program(SCSI_DMA_PIO, &rewrote_program);
  726. }
  727. static int pio_add_scsi_accel_read_program()
  728. {
  729. zulu_pio_remove_program(SCSI_DMA_PIO,
  730. &scsi_accel_read_program,
  731. g_scsi_dma.pio_offset_read,
  732. g_scsi_dma.pio_removed_read);
  733. uint16_t rewrote_instructions[sizeof(scsi_accel_read_program_instructions)/sizeof(scsi_accel_read_program_instructions[0])];
  734. pio_program rewrote_program = {
  735. rewrote_instructions,
  736. scsi_accel_read_program.length,
  737. scsi_accel_read_program.origin,
  738. scsi_accel_read_program.pio_version};
  739. memcpy(rewrote_instructions,
  740. scsi_accel_read_program_instructions,
  741. sizeof(scsi_accel_read_program_instructions));
  742. // wait 1 gpio ACK side 1 ; Wait for ACK high
  743. rewrote_instructions[1] = pio_encode_wait_gpio(true, SCSI_IN_ACK) | pio_encode_sideset(1, 1);
  744. // wait 0 gpio ACK side 0 ; Assert REQ, wait for ACK low
  745. rewrote_instructions[3] = pio_encode_wait_gpio(false, SCSI_IN_ACK) | pio_encode_sideset(1, 0);
  746. g_scsi_dma.pio_removed_read = false;
  747. return pio_add_program(SCSI_DMA_PIO, &rewrote_program);
  748. }
  749. static int pio_add_scsi_sync_write_pacer_program()
  750. {
  751. zulu_pio_remove_program(SCSI_DMA_PIO,
  752. &scsi_sync_write_pacer_program,
  753. g_scsi_dma.pio_offset_sync_write_pacer,
  754. g_scsi_dma.pio_removed_sync_write_pacer);
  755. uint16_t rewrote_instructions[sizeof(scsi_sync_write_pacer_program_instructions)/sizeof(scsi_sync_write_pacer_program_instructions[0])];
  756. pio_program rewrote_program = {
  757. rewrote_instructions,
  758. scsi_sync_write_pacer_program.length,
  759. scsi_sync_write_pacer_program.origin,
  760. scsi_sync_write_pacer_program.pio_version};
  761. memcpy(rewrote_instructions,
  762. scsi_sync_write_pacer_program_instructions,
  763. sizeof(scsi_sync_write_pacer_program_instructions));
  764. // wait 1 gpio ACK
  765. rewrote_instructions[0] = pio_encode_wait_gpio(true, SCSI_IN_ACK);
  766. // wait 0 gpio ACK ; Wait for falling edge on ACK
  767. rewrote_instructions[1] = pio_encode_wait_gpio(false, SCSI_IN_ACK);
  768. g_scsi_dma.pio_removed_sync_write_pacer = false;
  769. return pio_add_program(SCSI_DMA_PIO, &rewrote_program);
  770. }
  771. static int pio_add_scsi_parity_program()
  772. {
  773. g_scsi_dma.pio_removed_parity = false;
  774. return pio_add_program(SCSI_DMA_PIO, &scsi_parity_program);
  775. }
  776. static int pio_add_scsi_sync_read_pacer_program()
  777. {
  778. g_scsi_dma.pio_removed_sync_read_pacer = false;
  779. return pio_add_program(SCSI_DMA_PIO, &scsi_sync_read_pacer_program);
  780. }
  781. static int pio_add_scsi_read_parity_program()
  782. {
  783. g_scsi_dma.pio_removed_read_parity = false;
  784. return pio_add_program(SCSI_DMA_PIO, &scsi_read_parity_program);
  785. }
  786. static int pio_add_scsi_sync_write_program()
  787. {
  788. g_scsi_dma.pio_removed_sync_write = false;
  789. return pio_add_program(SCSI_DMA_PIO, &scsi_sync_write_program);
  790. }
  791. /*******************************************************/
  792. /* Initialization functions common to read/write */
  793. /*******************************************************/
  794. static void scsi_dma_irq()
  795. {
  796. #ifndef ENABLE_AUDIO_OUTPUT
  797. dma_hw->ints0 = (1 << SCSI_DMA_CH_A);
  798. #else
  799. // see audio.h for whats going on here
  800. if (dma_hw->intr & (1 << SCSI_DMA_CH_A)) {
  801. dma_hw->ints0 = (1 << SCSI_DMA_CH_A);
  802. } else {
  803. audio_dma_irq();
  804. return;
  805. }
  806. #endif
  807. scsidma_state_t state = g_scsi_dma_state;
  808. if (state == SCSIDMA_WRITE)
  809. {
  810. // Start writing from next buffer, if any, or set state to SCSIDMA_WRITE_DONE
  811. start_dma_write();
  812. }
  813. else if (state == SCSIDMA_READ)
  814. {
  815. // Start reading into next buffer, if any, or set state to SCSIDMA_READ_DONE
  816. start_dma_read();
  817. }
  818. }
  819. // Select GPIO from PIO peripheral or from software controlled SIO
  820. static void scsidma_config_gpio()
  821. {
  822. if (g_scsi_dma_state == SCSIDMA_IDLE)
  823. {
  824. iobank0_hw->io[SCSI_IO_DB0].ctrl = GPIO_FUNC_SIO;
  825. iobank0_hw->io[SCSI_IO_DB1].ctrl = GPIO_FUNC_SIO;
  826. iobank0_hw->io[SCSI_IO_DB2].ctrl = GPIO_FUNC_SIO;
  827. iobank0_hw->io[SCSI_IO_DB3].ctrl = GPIO_FUNC_SIO;
  828. iobank0_hw->io[SCSI_IO_DB4].ctrl = GPIO_FUNC_SIO;
  829. iobank0_hw->io[SCSI_IO_DB5].ctrl = GPIO_FUNC_SIO;
  830. iobank0_hw->io[SCSI_IO_DB6].ctrl = GPIO_FUNC_SIO;
  831. iobank0_hw->io[SCSI_IO_DB7].ctrl = GPIO_FUNC_SIO;
  832. iobank0_hw->io[SCSI_IO_DBP].ctrl = GPIO_FUNC_SIO;
  833. iobank0_hw->io[SCSI_OUT_REQ].ctrl = GPIO_FUNC_SIO;
  834. }
  835. else if (g_scsi_dma_state == SCSIDMA_WRITE)
  836. {
  837. // Make sure the initial state of all pins is high and output
  838. pio_sm_set_pins(SCSI_DMA_PIO, SCSI_DATA_SM, SCSI_IO_DATA_MASK | (1 << SCSI_OUT_REQ));
  839. pio_sm_set_consecutive_pindirs(SCSI_DMA_PIO, SCSI_DATA_SM, SCSI_IO_DB0, 9, true);
  840. pio_sm_set_consecutive_pindirs(SCSI_DMA_PIO, SCSI_DATA_SM, SCSI_OUT_REQ, 1, true);
  841. iobank0_hw->io[SCSI_IO_DB0].ctrl = GPIO_FUNC_PIO0;
  842. iobank0_hw->io[SCSI_IO_DB1].ctrl = GPIO_FUNC_PIO0;
  843. iobank0_hw->io[SCSI_IO_DB2].ctrl = GPIO_FUNC_PIO0;
  844. iobank0_hw->io[SCSI_IO_DB3].ctrl = GPIO_FUNC_PIO0;
  845. iobank0_hw->io[SCSI_IO_DB4].ctrl = GPIO_FUNC_PIO0;
  846. iobank0_hw->io[SCSI_IO_DB5].ctrl = GPIO_FUNC_PIO0;
  847. iobank0_hw->io[SCSI_IO_DB6].ctrl = GPIO_FUNC_PIO0;
  848. iobank0_hw->io[SCSI_IO_DB7].ctrl = GPIO_FUNC_PIO0;
  849. iobank0_hw->io[SCSI_IO_DBP].ctrl = GPIO_FUNC_PIO0;
  850. iobank0_hw->io[SCSI_OUT_REQ].ctrl = GPIO_FUNC_PIO0;
  851. }
  852. else if (g_scsi_dma_state == SCSIDMA_READ)
  853. {
  854. if (g_scsi_dma.syncOffset == 0)
  855. {
  856. // Asynchronous read
  857. // Data bus as input, REQ pin as output
  858. pio_sm_set_pins(SCSI_DMA_PIO, SCSI_DATA_SM, SCSI_IO_DATA_MASK | (1 << SCSI_OUT_REQ));
  859. pio_sm_set_consecutive_pindirs(SCSI_DMA_PIO, SCSI_DATA_SM, SCSI_IO_DB0, 9, false);
  860. pio_sm_set_consecutive_pindirs(SCSI_DMA_PIO, SCSI_DATA_SM, SCSI_OUT_REQ, 1, true);
  861. }
  862. else
  863. {
  864. // Synchronous read, REQ pin is written by SYNC_SM
  865. pio_sm_set_pins(SCSI_DMA_PIO, SCSI_SYNC_SM, SCSI_IO_DATA_MASK | (1 << SCSI_OUT_REQ));
  866. pio_sm_set_consecutive_pindirs(SCSI_DMA_PIO, SCSI_DATA_SM, SCSI_IO_DB0, 9, false);
  867. pio_sm_set_consecutive_pindirs(SCSI_DMA_PIO, SCSI_SYNC_SM, SCSI_OUT_REQ, 1, true);
  868. }
  869. iobank0_hw->io[SCSI_IO_DB0].ctrl = GPIO_FUNC_SIO;
  870. iobank0_hw->io[SCSI_IO_DB1].ctrl = GPIO_FUNC_SIO;
  871. iobank0_hw->io[SCSI_IO_DB2].ctrl = GPIO_FUNC_SIO;
  872. iobank0_hw->io[SCSI_IO_DB3].ctrl = GPIO_FUNC_SIO;
  873. iobank0_hw->io[SCSI_IO_DB4].ctrl = GPIO_FUNC_SIO;
  874. iobank0_hw->io[SCSI_IO_DB5].ctrl = GPIO_FUNC_SIO;
  875. iobank0_hw->io[SCSI_IO_DB6].ctrl = GPIO_FUNC_SIO;
  876. iobank0_hw->io[SCSI_IO_DB7].ctrl = GPIO_FUNC_SIO;
  877. iobank0_hw->io[SCSI_IO_DBP].ctrl = GPIO_FUNC_SIO;
  878. iobank0_hw->io[SCSI_OUT_REQ].ctrl = GPIO_FUNC_PIO0;
  879. }
  880. }
  881. void scsi_accel_rp2040_init()
  882. {
  883. g_scsi_dma_state = SCSIDMA_IDLE;
  884. scsidma_config_gpio();
  885. static bool first_init = true;
  886. if (first_init)
  887. {
  888. g_scsi_dma.pio_removed_parity = true;
  889. g_scsi_dma.pio_removed_async_write = true;
  890. g_scsi_dma.pio_removed_sync_write_pacer = true;
  891. g_scsi_dma.pio_removed_sync_write = true;
  892. g_scsi_dma.pio_removed_read = true;
  893. g_scsi_dma.pio_removed_read_parity = true;
  894. g_scsi_dma.pio_removed_sync_read_pacer = true;
  895. first_init = false;
  896. }
  897. if (g_channels_claimed) {
  898. // Un-claim all SCSI state machines
  899. pio_sm_unclaim(SCSI_DMA_PIO, SCSI_PARITY_SM);
  900. pio_sm_unclaim(SCSI_DMA_PIO, SCSI_DATA_SM);
  901. pio_sm_unclaim(SCSI_DMA_PIO, SCSI_SYNC_SM);
  902. // Remove all SCSI programs
  903. zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_parity_program, g_scsi_dma.pio_offset_parity, g_scsi_dma.pio_removed_parity);
  904. zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_accel_async_write_program, g_scsi_dma.pio_offset_async_write, g_scsi_dma.pio_removed_async_write);
  905. zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_sync_write_pacer_program, g_scsi_dma.pio_offset_sync_write_pacer, g_scsi_dma.pio_removed_sync_write_pacer);
  906. zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_accel_read_program, g_scsi_dma.pio_offset_read, g_scsi_dma.pio_removed_read);
  907. zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_sync_read_pacer_program, g_scsi_dma.pio_offset_sync_read_pacer, g_scsi_dma.pio_removed_sync_read_pacer);
  908. zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_read_parity_program, g_scsi_dma.pio_offset_read_parity, g_scsi_dma.pio_removed_read_parity);
  909. zulu_pio_remove_program(SCSI_DMA_PIO, &scsi_sync_write_program, g_scsi_dma.pio_offset_sync_write, g_scsi_dma.pio_removed_sync_write);
  910. // Un-claim all SCSI DMA channels
  911. dma_channel_unclaim(SCSI_DMA_CH_A);
  912. dma_channel_unclaim(SCSI_DMA_CH_B);
  913. dma_channel_unclaim(SCSI_DMA_CH_C);
  914. dma_channel_unclaim(SCSI_DMA_CH_D);
  915. // Set flag to re-initialize SCSI PIO system
  916. g_channels_claimed = false;
  917. }
  918. if (!g_channels_claimed)
  919. {
  920. // Mark channels as being in use, unless it has been done already
  921. pio_sm_claim(SCSI_DMA_PIO, SCSI_PARITY_SM);
  922. pio_sm_claim(SCSI_DMA_PIO, SCSI_DATA_SM);
  923. pio_sm_claim(SCSI_DMA_PIO, SCSI_SYNC_SM);
  924. dma_channel_claim(SCSI_DMA_CH_A);
  925. dma_channel_claim(SCSI_DMA_CH_B);
  926. dma_channel_claim(SCSI_DMA_CH_C);
  927. dma_channel_claim(SCSI_DMA_CH_D);
  928. g_channels_claimed = true;
  929. }
  930. // Parity lookup generator
  931. g_scsi_dma.pio_offset_parity = pio_add_scsi_parity_program();
  932. g_scsi_dma.pio_cfg_parity = scsi_parity_program_get_default_config(g_scsi_dma.pio_offset_parity);
  933. sm_config_set_out_shift(&g_scsi_dma.pio_cfg_parity, true, false, 32);
  934. sm_config_set_in_shift(&g_scsi_dma.pio_cfg_parity, true, true, 32);
  935. // Asynchronous SCSI write
  936. g_scsi_dma.pio_offset_async_write = pio_add_scsi_accel_async_write_program();
  937. g_scsi_dma.pio_cfg_async_write = scsi_accel_async_write_program_get_default_config(g_scsi_dma.pio_offset_async_write);
  938. sm_config_set_out_pins(&g_scsi_dma.pio_cfg_async_write, SCSI_IO_DB0, 9);
  939. sm_config_set_sideset_pins(&g_scsi_dma.pio_cfg_async_write, SCSI_OUT_REQ);
  940. sm_config_set_fifo_join(&g_scsi_dma.pio_cfg_async_write, PIO_FIFO_JOIN_TX);
  941. sm_config_set_out_shift(&g_scsi_dma.pio_cfg_async_write, true, false, 32);
  942. // Synchronous SCSI write pacer / ACK handler
  943. g_scsi_dma.pio_offset_sync_write_pacer = pio_add_scsi_sync_write_pacer_program();
  944. g_scsi_dma.pio_cfg_sync_write_pacer = scsi_sync_write_pacer_program_get_default_config(g_scsi_dma.pio_offset_sync_write_pacer);
  945. sm_config_set_out_shift(&g_scsi_dma.pio_cfg_sync_write_pacer, true, true, 1);
  946. // Asynchronous / synchronous SCSI read
  947. g_scsi_dma.pio_offset_read = pio_add_scsi_accel_read_program();
  948. g_scsi_dma.pio_cfg_read = scsi_accel_read_program_get_default_config(g_scsi_dma.pio_offset_read);
  949. sm_config_set_in_pins(&g_scsi_dma.pio_cfg_read, SCSI_IO_DB0);
  950. sm_config_set_sideset_pins(&g_scsi_dma.pio_cfg_read, SCSI_OUT_REQ);
  951. sm_config_set_out_shift(&g_scsi_dma.pio_cfg_read, true, false, 32);
  952. sm_config_set_in_shift(&g_scsi_dma.pio_cfg_read, true, true, 32);
  953. // Synchronous SCSI read pacer
  954. g_scsi_dma.pio_offset_sync_read_pacer = pio_add_scsi_sync_read_pacer_program();
  955. g_scsi_dma.pio_cfg_sync_read_pacer = scsi_sync_read_pacer_program_get_default_config(g_scsi_dma.pio_offset_sync_read_pacer);
  956. sm_config_set_sideset_pins(&g_scsi_dma.pio_cfg_sync_read_pacer, SCSI_OUT_REQ);
  957. // Read parity check
  958. g_scsi_dma.pio_offset_read_parity = pio_add_scsi_read_parity_program();
  959. g_scsi_dma.pio_cfg_read_parity = scsi_read_parity_program_get_default_config(g_scsi_dma.pio_offset_read_parity);
  960. sm_config_set_out_shift(&g_scsi_dma.pio_cfg_read_parity, true, true, 32);
  961. sm_config_set_in_shift(&g_scsi_dma.pio_cfg_read_parity, true, false, 32);
  962. // Synchronous SCSI data writer
  963. g_scsi_dma.pio_offset_sync_write = pio_add_scsi_sync_write_program();
  964. g_scsi_dma.pio_cfg_sync_write = scsi_sync_write_program_get_default_config(g_scsi_dma.pio_offset_sync_write);
  965. sm_config_set_out_pins(&g_scsi_dma.pio_cfg_sync_write, SCSI_IO_DB0, 9);
  966. sm_config_set_sideset_pins(&g_scsi_dma.pio_cfg_sync_write, SCSI_OUT_REQ);
  967. sm_config_set_out_shift(&g_scsi_dma.pio_cfg_sync_write, true, true, 32);
  968. sm_config_set_in_shift(&g_scsi_dma.pio_cfg_sync_write, true, true, 1);
  969. // Create DMA channel configurations so they can be applied quickly later
  970. // For write to SCSI BUS:
  971. // Channel A: Bytes from RAM to scsi_parity PIO
  972. dma_channel_config cfg = dma_channel_get_default_config(SCSI_DMA_CH_A);
  973. channel_config_set_transfer_data_size(&cfg, DMA_SIZE_8);
  974. channel_config_set_read_increment(&cfg, true);
  975. channel_config_set_write_increment(&cfg, false);
  976. channel_config_set_dreq(&cfg, pio_get_dreq(SCSI_DMA_PIO, SCSI_PARITY_SM, true));
  977. g_scsi_dma.dmacfg_write_chA = cfg;
  978. // Channel B: Addresses from scsi_parity PIO to lookup DMA READ_ADDR register
  979. cfg = dma_channel_get_default_config(SCSI_DMA_CH_B);
  980. channel_config_set_transfer_data_size(&cfg, DMA_SIZE_32);
  981. channel_config_set_read_increment(&cfg, false);
  982. channel_config_set_write_increment(&cfg, false);
  983. channel_config_set_dreq(&cfg, pio_get_dreq(SCSI_DMA_PIO, SCSI_PARITY_SM, false));
  984. g_scsi_dma.dmacfg_write_chB = cfg;
  985. // Channel C: Lookup from g_scsi_parity_lookup and copy to scsi_accel_async_write or scsi_sync_write PIO
  986. // When done, chain to channel B
  987. cfg = dma_channel_get_default_config(SCSI_DMA_CH_C);
  988. channel_config_set_transfer_data_size(&cfg, DMA_SIZE_16);
  989. channel_config_set_read_increment(&cfg, false);
  990. channel_config_set_write_increment(&cfg, false);
  991. channel_config_set_dreq(&cfg, pio_get_dreq(SCSI_DMA_PIO, SCSI_DATA_SM, true));
  992. channel_config_set_chain_to(&cfg, SCSI_DMA_CH_B);
  993. g_scsi_dma.dmacfg_write_chC = cfg;
  994. // Channel D: In synchronous mode a second DMA channel is used to transfer dummy bits
  995. // from first state machine to second one.
  996. cfg = dma_channel_get_default_config(SCSI_DMA_CH_D);
  997. channel_config_set_transfer_data_size(&cfg, DMA_SIZE_32);
  998. channel_config_set_read_increment(&cfg, false);
  999. channel_config_set_write_increment(&cfg, false);
  1000. channel_config_set_dreq(&cfg, pio_get_dreq(SCSI_DMA_PIO, SCSI_SYNC_SM, true));
  1001. g_scsi_dma.dmacfg_write_chD = cfg;
  1002. // For read from SCSI BUS:
  1003. // Channel A: Bytes from scsi_read_parity PIO to destination memory buffer
  1004. // This takes the bottom 8 bits which is the data without parity bit.
  1005. // Triggered by scsi_read_parity RX FIFO.
  1006. cfg = dma_channel_get_default_config(SCSI_DMA_CH_A);
  1007. channel_config_set_transfer_data_size(&cfg, DMA_SIZE_8);
  1008. channel_config_set_read_increment(&cfg, false);
  1009. channel_config_set_write_increment(&cfg, true);
  1010. channel_config_set_dreq(&cfg, pio_get_dreq(SCSI_DMA_PIO, SCSI_PARITY_SM, false));
  1011. g_scsi_dma.dmacfg_read_chA = cfg;
  1012. // Channel B: Lookup from g_scsi_parity_check_lookup and copy to scsi_read_parity PIO
  1013. // Triggered by channel C writing to READ_ADDR_TRIG
  1014. // Re-enables channel C by chaining after done.
  1015. cfg = dma_channel_get_default_config(SCSI_DMA_CH_B);
  1016. channel_config_set_transfer_data_size(&cfg, DMA_SIZE_16);
  1017. channel_config_set_read_increment(&cfg, false);
  1018. channel_config_set_write_increment(&cfg, false);
  1019. channel_config_set_dreq(&cfg, DREQ_FORCE);
  1020. channel_config_set_chain_to(&cfg, SCSI_DMA_CH_C);
  1021. cfg.ctrl |= DMA_CH0_CTRL_TRIG_HIGH_PRIORITY_BITS;
  1022. g_scsi_dma.dmacfg_read_chB = cfg;
  1023. // Channel C: Addresses from scsi_read PIO to channel B READ_ADDR register
  1024. // A single transfer starts when PIO RX FIFO has data.
  1025. // The DMA channel is re-enabled by channel B chaining.
  1026. cfg = dma_channel_get_default_config(SCSI_DMA_CH_C);
  1027. channel_config_set_transfer_data_size(&cfg, DMA_SIZE_32);
  1028. channel_config_set_read_increment(&cfg, false);
  1029. channel_config_set_write_increment(&cfg, false);
  1030. channel_config_set_dreq(&cfg, pio_get_dreq(SCSI_DMA_PIO, SCSI_DATA_SM, false));
  1031. g_scsi_dma.dmacfg_read_chC = cfg;
  1032. // Channel D: In synchronous mode a second DMA channel is used to transfer dummy words
  1033. // from first state machine to second one to control the pace of data transfer.
  1034. // In asynchronous mode this just transfers words to control the number of bytes.
  1035. cfg = dma_channel_get_default_config(SCSI_DMA_CH_D);
  1036. channel_config_set_transfer_data_size(&cfg, DMA_SIZE_32);
  1037. channel_config_set_read_increment(&cfg, false);
  1038. channel_config_set_write_increment(&cfg, false);
  1039. channel_config_set_dreq(&cfg, pio_get_dreq(SCSI_DMA_PIO, SCSI_DATA_SM, true));
  1040. g_scsi_dma.dmacfg_read_chD = cfg;
  1041. // Interrupts are used for data buffer swapping
  1042. irq_set_exclusive_handler(DMA_IRQ_0, scsi_dma_irq);
  1043. irq_set_enabled(DMA_IRQ_0, true);
  1044. }
  1045. bool scsi_accel_rp2040_setSyncMode(int syncOffset, int syncPeriod)
  1046. {
  1047. if (g_scsi_dma_state != SCSIDMA_IDLE)
  1048. {
  1049. logmsg("ERROR: SCSI DMA was in state ", (int)g_scsi_dma_state, " when changing sync mode, forcing bus reset");
  1050. scsi_accel_log_state();
  1051. return false;
  1052. }
  1053. if (syncOffset != g_scsi_dma.syncOffset || syncPeriod != g_scsi_dma.syncPeriod)
  1054. {
  1055. g_scsi_dma.syncOffset = syncOffset;
  1056. g_scsi_dma.syncPeriod = syncPeriod;
  1057. if (syncOffset > 0)
  1058. {
  1059. // Set up offset amount to PIO state machine configs.
  1060. // The RX fifo of scsi_sync_write has 4 slots.
  1061. // We can preload it with 0-3 items and set the autopush threshold 1, 2, 4 ... 32
  1062. // to act as a divider. This allows offsets 1 to 128 bytes.
  1063. // SCSI2SD code currently only uses offsets up to 15.
  1064. if (syncOffset <= 4)
  1065. {
  1066. g_scsi_dma.syncOffsetDivider = 1;
  1067. g_scsi_dma.syncOffsetPreload = 5 - syncOffset;
  1068. }
  1069. else if (syncOffset <= 8)
  1070. {
  1071. g_scsi_dma.syncOffsetDivider = 2;
  1072. g_scsi_dma.syncOffsetPreload = 5 - syncOffset / 2;
  1073. }
  1074. else if (syncOffset <= 16)
  1075. {
  1076. g_scsi_dma.syncOffsetDivider = 4;
  1077. g_scsi_dma.syncOffsetPreload = 5 - syncOffset / 4;
  1078. }
  1079. else
  1080. {
  1081. g_scsi_dma.syncOffsetDivider = 4;
  1082. g_scsi_dma.syncOffsetPreload = 0;
  1083. }
  1084. // To properly detect when all bytes have been ACKed,
  1085. // we need at least one vacant slot in the FIFO.
  1086. if (g_scsi_dma.syncOffsetPreload > 3)
  1087. g_scsi_dma.syncOffsetPreload = 3;
  1088. sm_config_set_out_shift(&g_scsi_dma.pio_cfg_sync_write_pacer, true, true, g_scsi_dma.syncOffsetDivider);
  1089. sm_config_set_in_shift(&g_scsi_dma.pio_cfg_sync_write, true, true, g_scsi_dma.syncOffsetDivider);
  1090. // Set up the timing parameters to PIO program
  1091. // The scsi_sync_write PIO program consists of three instructions.
  1092. // The delays are in clock cycles, each taking 6.66 ns. (@150 MHz)
  1093. // delay0: Delay from data write to REQ assertion (data setup)
  1094. // delay1: Delay from REQ assert to REQ deassert (req pulse width)
  1095. // delay2: Delay from REQ deassert to data write (data hold)
  1096. int delay0, delay1, delay2, initialDelay, remainderDelay;
  1097. uint32_t up_rounder = g_zuluscsi_timings.scsi.clk_period_ps / 2 + 1;
  1098. uint32_t delay_in_ps = (syncPeriod * 4) * 1000;
  1099. // This is the delay in clock cycles rounded up
  1100. int totalDelay = (delay_in_ps + up_rounder) / g_zuluscsi_timings.scsi.clk_period_ps;
  1101. if (syncPeriod < 25)
  1102. {
  1103. // Fast-20 SCSI timing: 15 ns assertion period
  1104. // The hardware rise and fall time require some extra delay,
  1105. // These delays are in addition to the 1 cycle that the PIO takes to execute the instruction
  1106. totalDelay += g_zuluscsi_timings.scsi_20.total_delay_adjust;
  1107. delay0 = g_zuluscsi_timings.scsi_20.delay0; //Data setup time, should be min 11.5ns according to the spec for FAST-20
  1108. delay1 = g_zuluscsi_timings.scsi_20.delay1; //Data hold time, should be min 16.5ns according to the spec for FAST-20
  1109. delay2 = totalDelay - delay0 - delay1 - 3; //pulse width, should be min 15ns according to the spec for FAST-20
  1110. if (delay2 < 0) delay2 = 0;
  1111. if (delay2 > 15) delay2 = 15;
  1112. }
  1113. else if (syncPeriod < 50 )
  1114. {
  1115. // Fast-10 SCSI timing: 30 ns assertion period, 25 ns skew delay
  1116. // The hardware rise and fall time require some extra delay,
  1117. totalDelay += g_zuluscsi_timings.scsi_10.total_delay_adjust;
  1118. delay0 = g_zuluscsi_timings.scsi_10.delay0; // 4;
  1119. delay1 = g_zuluscsi_timings.scsi_10.delay1; // 6;
  1120. delay2 = totalDelay - delay0 - delay1 - 3;
  1121. if (delay2 < 0) delay2 = 0;
  1122. if (delay2 > 15) delay2 = 15;
  1123. }
  1124. else
  1125. {
  1126. // \TODO set RP23XX timings here
  1127. // Slow SCSI timing: 90 ns assertion period, 55 ns skew delay
  1128. totalDelay += g_zuluscsi_timings.scsi_5.total_delay_adjust;
  1129. delay0 = g_zuluscsi_timings.scsi_5.delay0;
  1130. delay1 = g_zuluscsi_timings.scsi_5.delay1;
  1131. delay2 = totalDelay - delay0 - delay1 - 3;
  1132. if (delay2 < 0) delay2 = 0;
  1133. if (delay2 > 15) delay2 = 15;
  1134. }
  1135. // Patch the delay values into the instructions in scsi_sync_write.
  1136. // The code in scsi_accel.pio must have delay set to 0 for this to work correctly.
  1137. uint16_t instr0 = scsi_sync_write_program_instructions[0] | pio_encode_delay(delay0);
  1138. uint16_t instr1 = scsi_sync_write_program_instructions[1] | pio_encode_delay(delay1);
  1139. uint16_t instr2 = scsi_sync_write_program_instructions[2] | pio_encode_delay(delay2);
  1140. SCSI_DMA_PIO->instr_mem[g_scsi_dma.pio_offset_sync_write + 0] = instr0;
  1141. SCSI_DMA_PIO->instr_mem[g_scsi_dma.pio_offset_sync_write + 1] = instr1;
  1142. SCSI_DMA_PIO->instr_mem[g_scsi_dma.pio_offset_sync_write + 2] = instr2;
  1143. // And similar patching for scsi_sync_read_pacer
  1144. int rdelay2 = totalDelay - delay1 - 2;
  1145. if (rdelay2 > 15) rdelay2 = 15;
  1146. if (rdelay2 < 5) rdelay2 = 5;
  1147. uint16_t rinstr0 = scsi_sync_read_pacer_program_instructions[0] | pio_encode_delay(rdelay2);
  1148. uint16_t rinstr1 = (scsi_sync_read_pacer_program_instructions[1] + g_scsi_dma.pio_offset_sync_read_pacer) | pio_encode_delay(delay1);
  1149. SCSI_DMA_PIO->instr_mem[g_scsi_dma.pio_offset_sync_read_pacer + 0] = rinstr0;
  1150. SCSI_DMA_PIO->instr_mem[g_scsi_dma.pio_offset_sync_read_pacer + 1] = rinstr1;
  1151. }
  1152. }
  1153. return true;
  1154. }