sd53c8xx.n 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. // NCR 53c8xx driver for Plan 9
  2. // Nigel Roles (nigel@9fs.org)
  3. //
  4. // Microcode
  5. //
  6. // 27/5/02 Fixed problems with transfers >= 256 * 512
  7. //
  8. // 13/3/01 Fixed microcode to support targets > 7
  9. //
  10. extern scsi_id_buf
  11. extern msg_out_buf
  12. extern cmd_buf
  13. extern data_buf
  14. extern status_buf
  15. extern msgin_buf
  16. extern dsa_0
  17. extern dsa_1
  18. extern dsa_head
  19. extern ssid_mask
  20. SIR_MSG_IO_COMPLETE = 0
  21. error_not_cmd_complete = 1
  22. error_disconnected = 2
  23. error_reselected = 3
  24. error_unexpected_phase = 4
  25. error_weird_message = 5
  26. SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT = 6
  27. error_not_identify_after_reselect = 7
  28. error_too_much_data = 8
  29. error_too_little_data = 9
  30. SIR_MSG_REJECT = 10
  31. SIR_MSG_SDTR = 11
  32. SIR_EV_RESPONSE_OK = 12
  33. error_sigp_set = 13
  34. SIR_EV_PHASE_SWITCH_AFTER_ID = 14
  35. SIR_MSG_WDTR = 15
  36. SIR_MSG_IGNORE_WIDE_RESIDUE = 16
  37. SIR_NOTIFY_DISC = 100
  38. SIR_NOTIFY_RESELECT = 101
  39. SIR_NOTIFY_MSG_IN = 102
  40. SIR_NOTIFY_STATUS = 103
  41. SIR_NOTIFY_DUMP = 104
  42. SIR_NOTIFY_DUMP2 = 105
  43. SIR_NOTIFY_SIGP = 106
  44. SIR_NOTIFY_ISSUE = 107
  45. SIR_NOTIFY_WAIT_RESELECT = 108
  46. SIR_NOTIFY_ISSUE_CHECK = 109
  47. SIR_NOTIFY_DUMP_NEXT_CODE = 110
  48. SIR_NOTIFY_COMMAND = 111
  49. SIR_NOTIFY_DATA_IN = 112
  50. SIR_NOTIFY_DATA_OUT = 113
  51. SIR_NOTIFY_BLOCK_DATA_IN = 114
  52. SIR_NOTIFY_WSR = 115
  53. SIR_NOTIFY_LOAD_SYNC = 116
  54. SIR_NOTIFY_RESELECTED_ON_SELECT = 117
  55. SIR_NOTIFY_LOAD_STATE = 118
  56. STATE_FREE = 0
  57. STATE_ALLOCATED = 1
  58. STATE_ISSUE = 2
  59. STATE_DISCONNECTED = 3
  60. STATE_DONE = 4
  61. STATE_END = 5
  62. RESULT_OK = 0
  63. MSG_IDENTIFY = 0x80
  64. MSG_DISCONNECT = 0x04
  65. MSG_SAVE_DATA_POINTER = 0x02
  66. MSG_RESTORE_POINTERS = 0x03
  67. MSG_IGNORE_WIDE_RESIDUE = 0x23
  68. X_MSG = 0x01
  69. X_MSG_SDTR = 0x01
  70. X_MSG_WDTR = 0x03
  71. MSG_REJECT = 0x07
  72. BSIZE = 512
  73. //BSIZE=4096
  74. // idle:
  75. jump wait_for_reselection
  76. start:
  77. call load_sync
  78. // move 13 to ctest0
  79. // int SIR_NOTIFY_ISSUE
  80. clear target
  81. select atn from scsi_id_buf, reselected_on_select // do I need to clear ATN here?
  82. jump start1, when msg_in // why is this here?
  83. start1:
  84. // move 14 to ctest0
  85. move from msg_out_buf, when msg_out
  86. id_out_mismatch:
  87. jump start1, when msg_out // repeat on parity grounds
  88. jump to_decisions, when not cmd
  89. cmd_phase:
  90. // int SIR_NOTIFY_COMMAND
  91. clear atn
  92. move from cmd_buf, when cmd
  93. cmd_out_mismatch:
  94. jump to_decisions, when not data_in
  95. data_in_phase:
  96. move memory 4, state, scratcha
  97. move memory 4, dmaaddr, scratchb
  98. // int SIR_NOTIFY_DATA_IN
  99. data_in_block_loop:
  100. move scratcha2 to sfbr
  101. jump data_in_normal, if 0
  102. // int SIR_NOTIFY_BLOCK_DATA_IN
  103. move BSIZE, ptr dmaaddr, when data_in // transfer BSIZE bytes
  104. data_in_block_mismatch:
  105. move scratchb1 + BSIZE / 256 to scratchb1 // add BSIZE to scratchb
  106. move scratchb2 + 0 to scratchb2 with carry
  107. move scratchb3 + 0 to scratchb3 with carry
  108. move scratcha2 + 255 to scratcha2 // sub one from block count
  109. move memory 4, scratchb, dmaaddr // save latest dmaddr
  110. jump data_in_block_loop, when data_in
  111. move memory 4, scratcha, state // save latest state
  112. call save_state
  113. jump to_decisions
  114. data_block_mismatch_recover:
  115. move memory 4, scratchb, dmaaddr // save latest dmaddr
  116. data_mismatch_recover:
  117. move memory 4, scratcha, state // save latest state
  118. jump to_decisions // no need to save
  119. // as interrupt routine
  120. // did this
  121. data_in_normal:
  122. move scratcha3 to sfbr
  123. int error_too_much_data, if not 0
  124. move from data_buf, when data_in
  125. data_in_mismatch:
  126. move 2 to scratcha3
  127. move memory 4, scratcha, state
  128. call save_state
  129. jump post_data_to_decisions
  130. data_out_phase:
  131. // int SIR_NOTIFY_DATA_OUT
  132. move memory 4, state, scratcha
  133. move memory 4, dmaaddr, scratchb
  134. data_out_block_loop:
  135. move scratcha2 to sfbr
  136. jump data_out_normal, if 0
  137. move memory 4, dmaaddr, scratchb
  138. move BSIZE, ptr dmaaddr, when data_out // transfer BSIZE bytes
  139. data_out_block_mismatch:
  140. move scratchb1 + BSIZE / 256 to scratchb1 // add BSIZE to scratchb
  141. move scratchb2 + 0 to scratchb2 with carry
  142. move scratchb3 + 0 to scratchb3 with carry
  143. move scratcha2 + 255 to scratcha2 // sub one from block count
  144. move memory 4, scratchb, dmaaddr // save latest dmaddr
  145. jump data_out_block_loop, when data_out
  146. move memory 4, scratcha, state // save latest state
  147. jump to_decisions
  148. data_out_normal:
  149. move scratcha3 to sfbr
  150. int error_too_little_data, if not 0
  151. move from data_buf, when data_out
  152. data_out_mismatch:
  153. move 2 to scratcha3
  154. move memory 4, scratcha, state
  155. call save_state
  156. jump post_data_to_decisions
  157. status_phase:
  158. move from status_buf, when status
  159. // int SIR_NOTIFY_STATUS
  160. int error_unexpected_phase, when not msg_in
  161. msg_in_phase:
  162. move 1, scratcha, when msg_in
  163. // int SIR_NOTIFY_MSG_IN
  164. jump rejected, if MSG_REJECT
  165. msg_in_not_reject:
  166. jump disconnected, if MSG_DISCONNECT
  167. jump msg_in_skip, if MSG_SAVE_DATA_POINTER
  168. jump msg_in_skip, if MSG_RESTORE_POINTERS
  169. jump ignore_wide, if MSG_IGNORE_WIDE_RESIDUE
  170. jump extended, if X_MSG
  171. int error_not_cmd_complete, if not 0
  172. move scntl2&0x7e to scntl2 // take care not to clear WSR
  173. clear ack
  174. wait disconnect
  175. // update state
  176. move memory 4, state, scratcha
  177. move STATE_DONE to scratcha0
  178. move RESULT_OK to scratcha1
  179. move memory 4, scratcha, state
  180. call save_state
  181. // int SIR_MSG_IO_COMPLETE
  182. intfly 0
  183. jump issue_check
  184. rejected:
  185. int SIR_MSG_REJECT
  186. clear ack
  187. jump to_decisions
  188. msg_in_skip:
  189. clear ack
  190. jump to_decisions
  191. extended:
  192. clear ack
  193. int error_unexpected_phase, when not msg_in
  194. move 1, scratcha1, when msg_in
  195. jump ext_3, if 3
  196. jump ext_2, if 2
  197. int error_weird_message, if not 1
  198. ext_1:
  199. clear ack
  200. int error_unexpected_phase, when not msg_in
  201. move 1, scratcha1, when msg_in
  202. jump ext_done
  203. ext_3: clear ack
  204. int error_unexpected_phase, when not msg_in
  205. move 1, scratcha1, when msg_in
  206. clear ack
  207. int error_unexpected_phase, when not msg_in
  208. move 1, scratcha2, when msg_in
  209. clear ack
  210. int error_unexpected_phase, when not msg_in
  211. move 1, scratcha3, when msg_in
  212. move scratcha1 to sfbr
  213. jump ext_done, if not X_MSG_SDTR
  214. // the target sent SDTR - leave ACK asserted and signal kernel
  215. // kernel will either restart at reject, or continue
  216. sdtr: int SIR_MSG_SDTR
  217. clear ack
  218. jump to_decisions
  219. ext_2: clear ack
  220. int error_unexpected_phase, when not msg_in
  221. move 1, scratcha1, when msg_in
  222. clear ack
  223. int error_unexpected_phase, when not msg_in
  224. move 1, scratcha2, when msg_in
  225. move scratcha1 to sfbr
  226. jump ext_done, if not X_MSG_WDTR
  227. wdtr: int SIR_MSG_WDTR
  228. clear ack
  229. jump to_decisions
  230. ext_done:
  231. // ought to check message here, but instead reject all
  232. // NB ATN set
  233. reject:
  234. set atn // get target's ATN
  235. clear ack // finish ACK
  236. move MSG_REJECT to scratcha // prepare message
  237. int error_unexpected_phase, when not msg_out// didn't get ATN
  238. clear atn // last byte coming
  239. move 1, scratcha, when msg_out // send byte
  240. clear ack // finish ACK
  241. jump reject, when msg_out // parity error
  242. jump to_decisions
  243. ignore_wide:
  244. clear ack
  245. int error_unexpected_phase, when not msg_in
  246. move 1, scratcha1, when msg_in
  247. int SIR_MSG_IGNORE_WIDE_RESIDUE
  248. clear ack
  249. jump to_decisions
  250. // sends a response to a message
  251. response:
  252. set atn
  253. clear ack
  254. int error_unexpected_phase, when not msg_out
  255. response_repeat:
  256. move from msg_out_buf, when msg_out
  257. jump response_repeat, when msg_out // repeat on parity grounds
  258. // now look for response
  259. // msg_in could be a REJECT
  260. // anything other message is something else so signal kernel first
  261. jump response_msg_in, when msg_in
  262. int SIR_EV_RESPONSE_OK // not a MSG_IN so OK
  263. jump to_decisions
  264. response_msg_in:
  265. move 1, scratcha, when msg_in
  266. jump rejected, if MSG_REJECT // go and generate rej interrupt
  267. int SIR_EV_RESPONSE_OK // not a REJECT so OK
  268. jump msg_in_not_reject // try others
  269. disconnected:
  270. // move 5 to ctest0
  271. move scntl2&0x7e to scntl2 // don't clear WSR
  272. clear ack
  273. wait disconnect
  274. // UPDATE state to disconnected
  275. move memory 4, state, scratcha
  276. move STATE_DISCONNECTED to scratcha0
  277. move memory 4, scratcha, state
  278. call save_state
  279. wsr_check:
  280. move scntl2&0x01 to sfbr
  281. int SIR_NOTIFY_WSR, if not 0
  282. // int SIR_NOTIFY_DISC
  283. jump issue_check
  284. reselected_on_select:
  285. int SIR_NOTIFY_RESELECTED_ON_SELECT
  286. jump reselected
  287. wait_for_reselection:
  288. // move 11 to ctest0
  289. // int SIR_NOTIFY_WAIT_RESELECT
  290. wait reselect sigp_set
  291. reselected:
  292. // move 12 to ctest0
  293. clear target
  294. int SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT, when not msg_in
  295. move 1, scratchb, when msg_in
  296. int error_not_identify_after_reselect, if not MSG_IDENTIFY and mask 0x1f
  297. // int SIR_NOTIFY_RESELECT
  298. // now locate the right DSA - note do not clear ACK, so target doesn't start
  299. // synchronous transfer until we are ready
  300. find_dsa:
  301. // move 6 to ctest0
  302. move memory 4, dsa_head, dsa
  303. find_dsa_loop:
  304. // move 7 to ctest0
  305. // move 8 to ctest0
  306. // load state from DSA into dsa_copy
  307. call load_state
  308. move memory 4, state, scratcha // get dsastate in scratcha
  309. move scratcha0 to sfbr // and state variable in sfbr
  310. jump find_dsa_next, if not STATE_DISCONNECTED // wrong state
  311. int error_reselected, if STATE_END
  312. move ssid & ssid_mask to sfbr // get target ID
  313. move memory 1, targ, find_dsa_smc1 // forge target comparison instruction
  314. find_dsa_smc1:
  315. jump find_dsa_next, if not 255 // jump if not matched
  316. move memory 1, lun, find_dsa_smc2 // forge lun comparison instruction
  317. move scratchb0 to sfbr // recover IDENTIFY message
  318. find_dsa_smc2:
  319. jump reload_sync, if 255 and mask ~7 // off we jolly well go
  320. find_dsa_next:
  321. move memory 4, next, dsa // find next
  322. jump find_dsa_loop
  323. // id_out terminated early
  324. // most likely the message wasn't recognised
  325. // clear ATN and accept the message in
  326. // called from sd53c8xx.c directly
  327. id_out_mismatch_recover:
  328. clear atn
  329. jump msg_in_phase, when msg_in
  330. int SIR_MSG_REJECT
  331. jump to_decisions
  332. // Reload synchronous registers after a reconnect. If the transfer is a synchronous read, then
  333. // as soon as we clear ACK, the target will switch to data_in and start blasting data into the
  334. // fifo. We need to be executing the 'jump when data_in' instruction before the target stops REQing
  335. // since it is the REQ which latches the 'when'. The target will do 16 REQs before stopping, so
  336. // we have 16 bytes (160uS) plus delays to do this after clearing ACK. Once the jump is executing,
  337. // the target will wait, so as much debugging as you like can happen in data_in_phase, just don't
  338. // stick any delays between 'clear ack' and 'jump data_in_phase, when data_in'.
  339. reload_sync:
  340. call load_sync
  341. clear ack
  342. to_decisions:
  343. jump data_in_phase, when data_in
  344. jump cmd_phase, if cmd
  345. jump data_out_phase, if data_out
  346. jump status_phase, if status
  347. jump msg_in_phase, if msg_in
  348. int error_unexpected_phase
  349. post_data_to_decisions:
  350. jump status_phase, when status
  351. jump msg_in_phase, if msg_in
  352. int error_unexpected_phase
  353. //
  354. // MULTI_TARGET
  355. //
  356. // following must mirror top of dsa structure
  357. // the first section is loaded and saved, the
  358. // second section loaded only
  359. dsa_copy:
  360. state: defw 0 // a0 is state, a1 result, a2 dma block count
  361. dmaaddr: defw 0 // dma address for block moves
  362. dsa_save_end:
  363. targ: defw 0 // lsb is target
  364. lun: defw 0 // lsb is lun
  365. sync: defw 0 // lsb is scntl3, sxfer
  366. next: defw 0
  367. dsa_load_end:
  368. dsa_load_len = dsa_load_end - dsa_copy
  369. dsa_save_len = dsa_save_end - dsa_copy
  370. load_state:
  371. // int SIR_NOTIFY_LOAD_STATE
  372. jump load_state_okay
  373. move dsa0 to sfbr
  374. jump load_state_okay, if not 0
  375. move dsa1 to sfbr
  376. jump load_state_okay, if not 0
  377. move dsa2 to sfbr
  378. jump load_state_okay, if not 0
  379. move dsa3 to sfbr
  380. jump load_state_okay, if not 0
  381. // dsa is 0
  382. move memory 4, dsa, dmaaddr
  383. move memory 4, dsa, targ
  384. move memory 4, dsa, lun
  385. move memory 4, dsa, sync
  386. move memory 4, dsa, next
  387. move memory 4, dsa, scratcha
  388. move STATE_END to sfbr
  389. move sfbr to scratcha0
  390. move memory 4, scratcha, state
  391. return
  392. load_state_okay:
  393. // load state from DSA into dsa_copy
  394. // move 9 to ctest0
  395. move memory 4, dsa, load_state_smc0 + 4
  396. load_state_smc0:
  397. move memory dsa_load_len, 0, dsa_copy
  398. // move 20 to ctest0
  399. return
  400. save_state:
  401. move memory 4, dsa, save_state_smc0 + 8
  402. save_state_smc0:
  403. move memory dsa_save_len, dsa_copy, 0
  404. return
  405. sigp_set:
  406. // int SIR_NOTIFY_SIGP
  407. move ctest2 to sfbr // clear SIGP
  408. issue_check:
  409. // int SIR_NOTIFY_ISSUE_CHECK
  410. // move 1 to ctest0
  411. move memory 4, dsa_head, dsa
  412. issue_check_loop:
  413. call load_state
  414. move memory 4, state, scratcha // get dsastate in scratcha
  415. move scratcha0 to sfbr // and state variable in sfbr
  416. jump start, if STATE_ISSUE // right state
  417. jump wait_for_reselection, if STATE_END
  418. // move 4 to ctest0
  419. move memory 4, next, dsa // find next
  420. jump issue_check_loop
  421. load_sync:
  422. move memory 4, sync, scratcha // load the sync stuff
  423. move scratcha0 to sfbr // assuming load_state has been called
  424. move sfbr to scntl3
  425. move scratcha1 to sfbr
  426. move sfbr to sxfer
  427. // int SIR_NOTIFY_LOAD_SYNC
  428. return