1 // NCR 53c8xx driver for Plan 9
2 // Nigel Roles (nigel@9fs.org)
6 // 27/5/02 Fixed problems with transfers >= 256 * 512
8 // 13/3/01 Fixed microcode to support targets > 7
22 SIR_MSG_IO_COMPLETE = 0
23 error_not_cmd_complete = 1
24 error_disconnected = 2
26 error_unexpected_phase = 4
27 error_weird_message = 5
28 SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT = 6
29 error_not_identify_after_reselect = 7
30 error_too_much_data = 8
31 error_too_little_data = 9
34 SIR_EV_RESPONSE_OK = 12
36 SIR_EV_PHASE_SWITCH_AFTER_ID = 14
38 SIR_MSG_IGNORE_WIDE_RESIDUE = 16
40 SIR_NOTIFY_RESELECT = 101
41 SIR_NOTIFY_MSG_IN = 102
42 SIR_NOTIFY_STATUS = 103
44 SIR_NOTIFY_DUMP2 = 105
46 SIR_NOTIFY_ISSUE = 107
47 SIR_NOTIFY_WAIT_RESELECT = 108
48 SIR_NOTIFY_ISSUE_CHECK = 109
49 SIR_NOTIFY_DUMP_NEXT_CODE = 110
50 SIR_NOTIFY_COMMAND = 111
51 SIR_NOTIFY_DATA_IN = 112
52 SIR_NOTIFY_DATA_OUT = 113
53 SIR_NOTIFY_BLOCK_DATA_IN = 114
55 SIR_NOTIFY_LOAD_SYNC = 116
56 SIR_NOTIFY_RESELECTED_ON_SELECT = 117
57 SIR_NOTIFY_LOAD_STATE = 118
62 STATE_DISCONNECTED = 3
70 MSG_SAVE_DATA_POINTER = 0x02
71 MSG_RESTORE_POINTERS = 0x03
72 MSG_IGNORE_WIDE_RESIDUE = 0x23
82 jump wait_for_reselection
86 // int SIR_NOTIFY_ISSUE
88 select atn from scsi_id_buf, reselected_on_select // do I need to clear ATN here?
89 jump start1, when msg_in // why is this here?
92 move from msg_out_buf, when msg_out
94 jump start1, when msg_out // repeat on parity grounds
95 jump to_decisions, when not cmd
97 // int SIR_NOTIFY_COMMAND
99 move from cmd_buf, when cmd
101 jump to_decisions, when not data_in
103 move memory 4, state, scratcha
104 move memory 4, dmaaddr, scratchb
105 // int SIR_NOTIFY_DATA_IN
107 move scratcha2 to sfbr
108 jump data_in_normal, if 0
109 // int SIR_NOTIFY_BLOCK_DATA_IN
110 move BSIZE, ptr dmaaddr, when data_in // transfer BSIZE bytes
111 data_in_block_mismatch:
112 move scratchb1 + BSIZE / 256 to scratchb1 // add BSIZE to scratchb
113 move scratchb2 + 0 to scratchb2 with carry
114 move scratchb3 + 0 to scratchb3 with carry
115 move scratcha2 + 255 to scratcha2 // sub one from block count
116 move memory 4, scratchb, dmaaddr // save latest dmaddr
117 jump data_in_block_loop, when data_in
118 move memory 4, scratcha, state // save latest state
121 data_block_mismatch_recover:
122 move memory 4, scratchb, dmaaddr // save latest dmaddr
123 data_mismatch_recover:
124 move memory 4, scratcha, state // save latest state
125 jump to_decisions // no need to save
126 // as interrupt routine
129 move scratcha3 to sfbr
130 int error_too_much_data, if not 0
131 move from data_buf, when data_in
134 move memory 4, scratcha, state
136 jump post_data_to_decisions
138 // int SIR_NOTIFY_DATA_OUT
139 move memory 4, state, scratcha
140 move memory 4, dmaaddr, scratchb
142 move scratcha2 to sfbr
143 jump data_out_normal, if 0
144 move memory 4, dmaaddr, scratchb
145 move BSIZE, ptr dmaaddr, when data_out // transfer BSIZE bytes
146 data_out_block_mismatch:
147 move scratchb1 + BSIZE / 256 to scratchb1 // add BSIZE to scratchb
148 move scratchb2 + 0 to scratchb2 with carry
149 move scratchb3 + 0 to scratchb3 with carry
150 move scratcha2 + 255 to scratcha2 // sub one from block count
151 move memory 4, scratchb, dmaaddr // save latest dmaddr
152 jump data_out_block_loop, when data_out
153 move memory 4, scratcha, state // save latest state
156 move scratcha3 to sfbr
157 int error_too_little_data, if not 0
158 move from data_buf, when data_out
161 move memory 4, scratcha, state
163 jump post_data_to_decisions
165 move from status_buf, when status
166 // int SIR_NOTIFY_STATUS
167 int error_unexpected_phase, when not msg_in
169 move 1, scratcha, when msg_in
170 // int SIR_NOTIFY_MSG_IN
171 jump rejected, if MSG_REJECT
173 jump disconnected, if MSG_DISCONNECT
174 jump msg_in_skip, if MSG_SAVE_DATA_POINTER
175 jump msg_in_skip, if MSG_RESTORE_POINTERS
176 jump ignore_wide, if MSG_IGNORE_WIDE_RESIDUE
177 jump extended, if X_MSG
178 int error_not_cmd_complete, if not 0
179 move scntl2&0x7e to scntl2 // take care not to clear WSR
183 move memory 4, state, scratcha
184 move STATE_DONE to scratcha0
185 move RESULT_OK to scratcha1
186 move memory 4, scratcha, state
188 // int SIR_MSG_IO_COMPLETE
202 int error_unexpected_phase, when not msg_in
203 move 1, scratcha1, when msg_in
206 int error_weird_message, if not 1
209 int error_unexpected_phase, when not msg_in
210 move 1, scratcha1, when msg_in
214 int error_unexpected_phase, when not msg_in
215 move 1, scratcha1, when msg_in
217 int error_unexpected_phase, when not msg_in
218 move 1, scratcha2, when msg_in
220 int error_unexpected_phase, when not msg_in
221 move 1, scratcha3, when msg_in
222 move scratcha1 to sfbr
223 jump ext_done, if not X_MSG_SDTR
225 // the target sent SDTR - leave ACK asserted and signal kernel
226 // kernel will either restart at reject, or continue
227 sdtr: int SIR_MSG_SDTR
232 int error_unexpected_phase, when not msg_in
233 move 1, scratcha1, when msg_in
235 int error_unexpected_phase, when not msg_in
236 move 1, scratcha2, when msg_in
237 move scratcha1 to sfbr
238 jump ext_done, if not X_MSG_WDTR
240 wdtr: int SIR_MSG_WDTR
245 // ought to check message here, but instead reject all
248 set atn // get target's ATN
249 clear ack // finish ACK
250 move MSG_REJECT to scratcha // prepare message
251 int error_unexpected_phase, when not msg_out// didn't get ATN
252 clear atn // last byte coming
253 move 1, scratcha, when msg_out // send byte
254 clear ack // finish ACK
255 jump reject, when msg_out // parity error
260 int error_unexpected_phase, when not msg_in
261 move 1, scratcha1, when msg_in
262 int SIR_MSG_IGNORE_WIDE_RESIDUE
266 // sends a response to a message
270 int error_unexpected_phase, when not msg_out
272 move from msg_out_buf, when msg_out
273 jump response_repeat, when msg_out // repeat on parity grounds
274 // now look for response
275 // msg_in could be a REJECT
276 // anything other message is something else so signal kernel first
277 jump response_msg_in, when msg_in
278 int SIR_EV_RESPONSE_OK // not a MSG_IN so OK
282 move 1, scratcha, when msg_in
283 jump rejected, if MSG_REJECT // go and generate rej interrupt
284 int SIR_EV_RESPONSE_OK // not a REJECT so OK
285 jump msg_in_not_reject // try others
289 move scntl2&0x7e to scntl2 // don't clear WSR
292 // UPDATE state to disconnected
293 move memory 4, state, scratcha
294 move STATE_DISCONNECTED to scratcha0
295 move memory 4, scratcha, state
298 move scntl2&0x01 to sfbr
299 int SIR_NOTIFY_WSR, if not 0
300 // int SIR_NOTIFY_DISC
303 reselected_on_select:
304 int SIR_NOTIFY_RESELECTED_ON_SELECT
307 wait_for_reselection:
309 // int SIR_NOTIFY_WAIT_RESELECT
310 wait reselect sigp_set
314 int SIR_ERROR_NOT_MSG_IN_AFTER_RESELECT, when not msg_in
315 move 1, scratchb, when msg_in
316 int error_not_identify_after_reselect, if not MSG_IDENTIFY and mask 0x1f
317 // int SIR_NOTIFY_RESELECT
318 // now locate the right DSA - note do not clear ACK, so target doesn't start
319 // synchronous transfer until we are ready
322 move memory 4, dsa_head, dsa
326 // load state from DSA into dsa_copy
328 move memory 4, state, scratcha // get dsastate in scratcha
329 move scratcha0 to sfbr // and state variable in sfbr
330 jump find_dsa_next, if not STATE_DISCONNECTED // wrong state
331 int error_reselected, if STATE_END
332 move ssid & ssid_mask to sfbr // get target ID
333 move memory 1, targ, find_dsa_smc1 // forge target comparison instruction
335 jump find_dsa_next, if not 255 // jump if not matched
336 move memory 1, lun, find_dsa_smc2 // forge lun comparison instruction
337 move scratchb0 to sfbr // recover IDENTIFY message
339 jump reload_sync, if 255 and mask ~7 // off we jolly well go
341 move memory 4, next, dsa // find next
344 // id_out terminated early
345 // most likely the message wasn't recognised
346 // clear ATN and accept the message in
347 // called from sd53c8xx.c directly
348 id_out_mismatch_recover:
350 jump msg_in_phase, when msg_in
354 // Reload synchronous registers after a reconnect. If the transfer is a synchronous read, then
355 // as soon as we clear ACK, the target will switch to data_in and start blasting data into the
356 // fifo. We need to be executing the 'jump when data_in' instruction before the target stops REQing
357 // since it is the REQ which latches the 'when'. The target will do 16 REQs before stopping, so
358 // we have 16 bytes (160uS) plus delays to do this after clearing ACK. Once the jump is executing,
359 // the target will wait, so as much debugging as you like can happen in data_in_phase, just don't
360 // stick any delays between 'clear ack' and 'jump data_in_phase, when data_in'.
366 jump data_in_phase, when data_in
367 jump cmd_phase, if cmd
368 jump data_out_phase, if data_out
369 jump status_phase, if status
370 jump msg_in_phase, if msg_in
371 int error_unexpected_phase
373 post_data_to_decisions:
374 jump status_phase, when status
375 jump msg_in_phase, if msg_in
376 int error_unexpected_phase
381 // following must mirror top of dsa structure
382 // the first section is loaded and saved, the
383 // second section loaded only
385 state: defw 0 // a0 is state, a1 result, a2 dma block count
386 dmaaddr: defw 0 // dma address for block moves
388 targ: defw 0 // lsb is target
389 lun: defw 0 // lsb is lun
390 sync: defw 0 // lsb is scntl3, sxfer
393 dsa_load_len = dsa_load_end - dsa_copy
394 dsa_save_len = dsa_save_end - dsa_copy
397 // int SIR_NOTIFY_LOAD_STATE
401 jump load_state_okay, if not 0
403 jump load_state_okay, if not 0
405 jump load_state_okay, if not 0
407 jump load_state_okay, if not 0
409 move memory 4, dsa, dmaaddr
410 move memory 4, dsa, targ
411 move memory 4, dsa, lun
412 move memory 4, dsa, sync
413 move memory 4, dsa, next
414 move memory 4, dsa, scratcha
415 move STATE_END to sfbr
416 move sfbr to scratcha0
417 move memory 4, scratcha, state
421 // load state from DSA into dsa_copy
423 move memory 4, dsa, load_state_smc0 + 4
425 move memory dsa_load_len, 0, dsa_copy
429 move memory 4, dsa, save_state_smc0 + 8
431 move memory dsa_save_len, dsa_copy, 0
435 // int SIR_NOTIFY_SIGP
436 move ctest2 to sfbr // clear SIGP
438 // int SIR_NOTIFY_ISSUE_CHECK
440 move memory 4, dsa_head, dsa
443 move memory 4, state, scratcha // get dsastate in scratcha
444 move scratcha0 to sfbr // and state variable in sfbr
445 jump start, if STATE_ISSUE // right state
446 jump wait_for_reselection, if STATE_END
448 move memory 4, next, dsa // find next
449 jump issue_check_loop
453 move memory 4, sync, scratcha // load the sync stuff
454 move scratcha0 to sfbr // assuming load_state has been called
456 move scratcha1 to sfbr
458 // int SIR_NOTIFY_LOAD_SYNC