hc
2024-12-19 9370bb92b2d16684ee45cf24e879c93c509162da
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
; Script for the NCR (or symbios) 53c700 and 53c700-66 chip
;
; Copyright (C) 2001 James.Bottomley@HansenPartnership.com
;;-----------------------------------------------------------------------------
;;  
;;  This program is free software; you can redistribute it and/or modify
;;  it under the terms of the GNU General Public License as published by
;;  the Free Software Foundation; either version 2 of the License, or
;;  (at your option) any later version.
;;
;;  This program is distributed in the hope that it will be useful,
;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;  GNU General Public License for more details.
;;
;;  You should have received a copy of the GNU General Public License
;;  along with this program; if not, write to the Free Software
;;  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
;;
;;-----------------------------------------------------------------------------
;
; This script is designed to be modified for the particular command in
; operation.  The particular variables pertaining to the commands are:
;
ABSOLUTE    Device_ID = 0        ; ID of target for command
ABSOLUTE    MessageCount = 0    ; Number of bytes in message
ABSOLUTE    MessageLocation = 0    ; Addr of message
ABSOLUTE    CommandCount = 0    ; Number of bytes in command
ABSOLUTE    CommandAddress = 0    ; Addr of Command
ABSOLUTE    StatusAddress = 0    ; Addr to receive status return
ABSOLUTE    ReceiveMsgAddress = 0    ; Addr to receive msg
;
; This is the magic component for handling scatter-gather.  Each of the
; SG components is preceded by a script fragment which moves the
; necessary amount of data and jumps to the next SG segment.  The final
; SG segment jumps back to .  However, this address is the first SG script
; segment.
;
ABSOLUTE    SGScriptStartAddress = 0
 
; The following represent status interrupts we use 3 hex digits for
; this: 0xPRS where 
 
; P:
ABSOLUTE    AFTER_SELECTION     = 0x100
ABSOLUTE    BEFORE_CMD         = 0x200
ABSOLUTE    AFTER_CMD         = 0x300
ABSOLUTE    AFTER_STATUS         = 0x400
ABSOLUTE    AFTER_DATA_IN        = 0x500
ABSOLUTE    AFTER_DATA_OUT        = 0x600
ABSOLUTE    DURING_DATA_IN        = 0x700
 
; R:
ABSOLUTE    NOT_MSG_OUT         = 0x10
ABSOLUTE    UNEXPECTED_PHASE     = 0x20
ABSOLUTE    NOT_MSG_IN         = 0x30
ABSOLUTE    UNEXPECTED_MSG        = 0x40
ABSOLUTE    MSG_IN            = 0x50
ABSOLUTE    SDTR_MSG_R        = 0x60
ABSOLUTE    REJECT_MSG_R        = 0x70
ABSOLUTE    DISCONNECT        = 0x80
ABSOLUTE    MSG_OUT            = 0x90
ABSOLUTE    WDTR_MSG_R        = 0xA0
 
; S:
ABSOLUTE    GOOD_STATUS         = 0x1
 
; Combinations, since the script assembler can't process |
ABSOLUTE    NOT_MSG_OUT_AFTER_SELECTION = 0x110
ABSOLUTE    UNEXPECTED_PHASE_BEFORE_CMD = 0x220
ABSOLUTE    UNEXPECTED_PHASE_AFTER_CMD = 0x320
ABSOLUTE    NOT_MSG_IN_AFTER_STATUS = 0x430
ABSOLUTE    GOOD_STATUS_AFTER_STATUS = 0x401
ABSOLUTE    UNEXPECTED_PHASE_AFTER_DATA_IN = 0x520
ABSOLUTE    UNEXPECTED_PHASE_AFTER_DATA_OUT = 0x620
ABSOLUTE    UNEXPECTED_MSG_BEFORE_CMD = 0x240
ABSOLUTE    MSG_IN_BEFORE_CMD = 0x250
ABSOLUTE    MSG_IN_AFTER_CMD = 0x350
ABSOLUTE    SDTR_MSG_BEFORE_CMD = 0x260
ABSOLUTE    REJECT_MSG_BEFORE_CMD = 0x270
ABSOLUTE    DISCONNECT_AFTER_CMD = 0x380
ABSOLUTE    SDTR_MSG_AFTER_CMD = 0x360
ABSOLUTE    WDTR_MSG_AFTER_CMD = 0x3A0
ABSOLUTE    MSG_IN_AFTER_STATUS = 0x440
ABSOLUTE    DISCONNECT_AFTER_DATA = 0x580
ABSOLUTE    MSG_IN_AFTER_DATA_IN = 0x550
ABSOLUTE    MSG_IN_AFTER_DATA_OUT = 0x650
ABSOLUTE    MSG_OUT_AFTER_DATA_IN = 0x590
ABSOLUTE    DATA_IN_AFTER_DATA_IN = 0x5a0
ABSOLUTE    MSG_IN_DURING_DATA_IN = 0x750
ABSOLUTE    DISCONNECT_DURING_DATA = 0x780
 
;
; Other interrupt conditions
ABSOLUTE    RESELECTED_DURING_SELECTION = 0x1000
ABSOLUTE    COMPLETED_SELECTION_AS_TARGET = 0x1001
ABSOLUTE    RESELECTION_IDENTIFIED = 0x1003
;
; Fatal interrupt conditions.  If you add to this, also add to the
; array of corresponding messages
;
ABSOLUTE    FATAL = 0x2000
ABSOLUTE    FATAL_UNEXPECTED_RESELECTION_MSG = 0x2000
ABSOLUTE    FATAL_SEND_MSG = 0x2001
ABSOLUTE    FATAL_NOT_MSG_IN_AFTER_SELECTION = 0x2002
ABSOLUTE    FATAL_ILLEGAL_MSG_LENGTH = 0x2003
 
ABSOLUTE    DEBUG_INTERRUPT    = 0x3000
ABSOLUTE    DEBUG_INTERRUPT1 = 0x3001
ABSOLUTE    DEBUG_INTERRUPT2 = 0x3002
ABSOLUTE    DEBUG_INTERRUPT3 = 0x3003
ABSOLUTE    DEBUG_INTERRUPT4 = 0x3004
ABSOLUTE    DEBUG_INTERRUPT5 = 0x3005
ABSOLUTE    DEBUG_INTERRUPT6 = 0x3006
 
 
;
; SCSI Messages we interpret in the script
;
ABSOLUTE    COMMAND_COMPLETE_MSG    = 0x00
ABSOLUTE    EXTENDED_MSG        = 0x01
ABSOLUTE    SDTR_MSG        = 0x01
ABSOLUTE    SAVE_DATA_PTRS_MSG    = 0x02
ABSOLUTE    RESTORE_DATA_PTRS_MSG    = 0x03
ABSOLUTE    WDTR_MSG        = 0x03
ABSOLUTE    DISCONNECT_MSG        = 0x04
ABSOLUTE    REJECT_MSG        = 0x07
ABSOLUTE    PARITY_ERROR_MSG    = 0x09
ABSOLUTE    SIMPLE_TAG_MSG        = 0x20
ABSOLUTE    IDENTIFY_MSG        = 0x80
ABSOLUTE    IDENTIFY_MSG_MASK    = 0x7F
ABSOLUTE    TWO_BYTE_MSG        = 0x20
ABSOLUTE    TWO_BYTE_MSG_MASK    = 0x0F
 
; This is where the script begins
 
ENTRY    StartUp
 
StartUp:
   SELECT    ATN Device_ID, Reselect
   JUMP    Finish, WHEN STATUS
   JUMP    SendIdentifyMsg, IF MSG_OUT
   INT    NOT_MSG_OUT_AFTER_SELECTION
 
Reselect:
   WAIT    RESELECT SelectedAsTarget
   INT    RESELECTED_DURING_SELECTION, WHEN MSG_IN
   INT    FATAL_NOT_MSG_IN_AFTER_SELECTION
 
   ENTRY    GetReselectionData
GetReselectionData:
   MOVE    1, ReceiveMsgAddress, WHEN MSG_IN
   INT    RESELECTION_IDENTIFIED
 
   ENTRY    GetReselectionWithTag
GetReselectionWithTag:
   MOVE    3, ReceiveMsgAddress, WHEN MSG_IN
   INT    RESELECTION_IDENTIFIED
   
   ENTRY    SelectedAsTarget
SelectedAsTarget:
; Basically tell the selecting device that there's nothing here
   SET    TARGET
   DISCONNECT
   CLEAR    TARGET
   INT    COMPLETED_SELECTION_AS_TARGET
;
; These are the messaging entries
;
; Send a message.  Message count should be correctly patched
   ENTRY    SendMessage
SendMessage:
   MOVE    MessageCount, MessageLocation, WHEN MSG_OUT
ResumeSendMessage:
   RETURN,    WHEN NOT MSG_OUT
   INT    FATAL_SEND_MSG
 
   ENTRY    SendMessagePhaseMismatch
SendMessagePhaseMismatch:
   CLEAR    ACK
   JUMP    ResumeSendMessage
;
; Receive a message.  Need to identify the message to
; receive it correctly
   ENTRY    ReceiveMessage
ReceiveMessage:
   MOVE    1, ReceiveMsgAddress, WHEN MSG_IN
;
; Use this entry if we've just tried to look at the first byte
; of the message and want to process it further
ProcessReceiveMessage:
   JUMP    ReceiveExtendedMessage, IF EXTENDED_MSG
   RETURN,    IF NOT TWO_BYTE_MSG, AND MASK TWO_BYTE_MSG_MASK
   CLEAR    ACK
   MOVE    1, ReceiveMsgAddress + 1, WHEN MSG_IN
   RETURN
ReceiveExtendedMessage:
   CLEAR    ACK
   MOVE    1, ReceiveMsgAddress + 1, WHEN MSG_IN
   JUMP    Receive1Byte, IF 0x01
   JUMP    Receive2Byte, IF 0x02
   JUMP    Receive3Byte, IF 0x03
   JUMP    Receive4Byte, IF 0x04
   JUMP    Receive5Byte, IF 0x05
   INT    FATAL_ILLEGAL_MSG_LENGTH
Receive1Byte:
   CLEAR    ACK
   MOVE    1, ReceiveMsgAddress + 2, WHEN MSG_IN
   RETURN
Receive2Byte:
   CLEAR    ACK
   MOVE    2, ReceiveMsgAddress + 2, WHEN MSG_IN
   RETURN
Receive3Byte:
   CLEAR    ACK
   MOVE    3, ReceiveMsgAddress + 2, WHEN MSG_IN
   RETURN
Receive4Byte:
   CLEAR    ACK
   MOVE    4, ReceiveMsgAddress + 2, WHEN MSG_IN
   RETURN
Receive5Byte:
   CLEAR    ACK
   MOVE    5, ReceiveMsgAddress + 2, WHEN MSG_IN
   RETURN
;
; Come here from the message processor to ignore the message
;
   ENTRY    IgnoreMessage
IgnoreMessage:
   CLEAR    ACK
   RETURN
;
; Come here to send a reply to a message
;
   ENTRY    SendMessageWithATN
SendMessageWithATN:
   SET    ATN
   CLEAR    ACK
   JUMP    SendMessage
 
SendIdentifyMsg:
   CALL    SendMessage
   CLEAR    ATN
 
IgnoreMsgBeforeCommand:
   CLEAR    ACK
   ENTRY    SendCommand
SendCommand:
   JUMP    Finish, WHEN STATUS
   JUMP    MsgInBeforeCommand, IF MSG_IN
   INT    UNEXPECTED_PHASE_BEFORE_CMD, IF NOT CMD
   MOVE    CommandCount, CommandAddress, WHEN CMD
ResumeSendCommand:
   JUMP    Finish, WHEN STATUS
   JUMP    MsgInAfterCmd, IF MSG_IN
   JUMP    DataIn, IF DATA_IN
   JUMP    DataOut, IF DATA_OUT
   INT    UNEXPECTED_PHASE_AFTER_CMD
 
IgnoreMsgDuringData:
   CLEAR    ACK
   ; fall through to MsgInDuringData
 
Entry MsgInDuringData
MsgInDuringData:
;
; Could be we have nothing more to transfer
;
   JUMP    Finish, WHEN STATUS
   MOVE    1, ReceiveMsgAddress, WHEN MSG_IN
   JUMP    DisconnectDuringDataIn, IF DISCONNECT_MSG
   JUMP    IgnoreMsgDuringData, IF SAVE_DATA_PTRS_MSG
   JUMP    IgnoreMsgDuringData, IF RESTORE_DATA_PTRS_MSG
   INT    MSG_IN_DURING_DATA_IN
 
MsgInAfterCmd:
   MOVE    1, ReceiveMsgAddress, WHEN MSG_IN
   JUMP    DisconnectAfterCmd, IF DISCONNECT_MSG
   JUMP    IgnoreMsgInAfterCmd, IF SAVE_DATA_PTRS_MSG
   JUMP    IgnoreMsgInAfterCmd, IF RESTORE_DATA_PTRS_MSG
   CALL    ProcessReceiveMessage
   INT    MSG_IN_AFTER_CMD
   CLEAR    ACK
   JUMP    ResumeSendCommand
 
IgnoreMsgInAfterCmd:
   CLEAR    ACK
   JUMP    ResumeSendCommand
 
DisconnectAfterCmd:
   CLEAR    ACK
   WAIT    DISCONNECT
   ENTRY    Disconnect1
Disconnect1:
   INT    DISCONNECT_AFTER_CMD
   ENTRY    Disconnect2
Disconnect2:
; We return here after a reselection
   CLEAR    ACK
   JUMP    ResumeSendCommand
 
MsgInBeforeCommand:
   MOVE    1, ReceiveMsgAddress, WHEN MSG_IN
   JUMP    IgnoreMsgBeforeCommand, IF SAVE_DATA_PTRS_MSG
   JUMP    IgnoreMsgBeforeCommand, IF RESTORE_DATA_PTRS_MSG
   CALL    ProcessReceiveMessage
   INT    MSG_IN_BEFORE_CMD
   CLEAR    ACK
   JUMP    SendCommand
 
DataIn:
   CALL    SGScriptStartAddress
ResumeDataIn:
   JUMP    Finish, WHEN STATUS
   JUMP    MsgInAfterDataIn, IF MSG_IN
   JUMP    DataInAfterDataIn, if DATA_IN
   INT    MSG_OUT_AFTER_DATA_IN, if MSG_OUT
   INT    UNEXPECTED_PHASE_AFTER_DATA_IN
 
DataInAfterDataIn:
   INT    DATA_IN_AFTER_DATA_IN
   JUMP    ResumeDataIn
 
DataOut:
   CALL    SGScriptStartAddress
ResumeDataOut:
   JUMP    Finish, WHEN STATUS
   JUMP    MsgInAfterDataOut, IF MSG_IN
   INT    UNEXPECTED_PHASE_AFTER_DATA_OUT
 
MsgInAfterDataIn:
   MOVE    1, ReceiveMsgAddress, WHEN MSG_IN
   JUMP    DisconnectAfterDataIn, IF DISCONNECT_MSG
   JUMP    IgnoreMsgAfterData, IF SAVE_DATA_PTRS_MSG
   JUMP    IgnoreMsgAfterData, IF RESTORE_DATA_PTRS_MSG
   CALL    ProcessReceiveMessage
   INT    MSG_IN_AFTER_DATA_IN
   CLEAR    ACK
   JUMP    ResumeDataIn
 
DisconnectDuringDataIn:
   CLEAR    ACK
   WAIT    DISCONNECT
   ENTRY    Disconnect3
Disconnect3:
   INT    DISCONNECT_DURING_DATA
   ENTRY    Disconnect4
Disconnect4:
; we return here after a reselection
   CLEAR    ACK
   JUMP    ResumeSendCommand
 
 
DisconnectAfterDataIn:
   CLEAR    ACK
   WAIT    DISCONNECT
   ENTRY    Disconnect5
Disconnect5:
   INT    DISCONNECT_AFTER_DATA
   ENTRY    Disconnect6
Disconnect6:
; we return here after a reselection
   CLEAR    ACK
   JUMP    ResumeDataIn
 
MsgInAfterDataOut:
   MOVE    1, ReceiveMsgAddress, WHEN MSG_IN
   JUMP    DisconnectAfterDataOut, if DISCONNECT_MSG
   JUMP    IgnoreMsgAfterData, IF SAVE_DATA_PTRS_MSG
   JUMP    IgnoreMsgAfterData, IF RESTORE_DATA_PTRS_MSG
   CALL    ProcessReceiveMessage
   INT    MSG_IN_AFTER_DATA_OUT
   CLEAR    ACK
   JUMP    ResumeDataOut
 
IgnoreMsgAfterData:
   CLEAR    ACK
; Data in and out do the same thing on resume, so pick one
   JUMP    ResumeDataIn
 
DisconnectAfterDataOut:
   CLEAR    ACK
   WAIT    DISCONNECT
   ENTRY    Disconnect7
Disconnect7:
   INT    DISCONNECT_AFTER_DATA
   ENTRY    Disconnect8
Disconnect8:
; we return here after a reselection
   CLEAR    ACK
   JUMP    ResumeDataOut
 
Finish:
   MOVE    1, StatusAddress, WHEN STATUS
   INT    NOT_MSG_IN_AFTER_STATUS, WHEN NOT MSG_IN
   MOVE    1, ReceiveMsgAddress, WHEN MSG_IN
   JUMP    FinishCommandComplete, IF COMMAND_COMPLETE_MSG
   CALL    ProcessReceiveMessage
   INT    MSG_IN_AFTER_STATUS
   ENTRY    FinishCommandComplete
FinishCommandComplete:
   CLEAR    ACK
   WAIT    DISCONNECT
   ENTRY    Finish1
Finish1:
   INT    GOOD_STATUS_AFTER_STATUS
   ENTRY    Finish2
Finish2: