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