1; Script for the NCR (or symbios) 53c700 and 53c700-66 chip
2;
3; Copyright (C) 2001 James.Bottomley@HansenPartnership.com
4;;-----------------------------------------------------------------------------
5;;
6;;  This program is free software; you can redistribute it and/or modify
7;;  it under the terms of the GNU General Public License as published by
8;;  the Free Software Foundation; either version 2 of the License, or
9;;  (at your option) any later version.
10;;
11;;  This program is distributed in the hope that it will be useful,
12;;  but WITHOUT ANY WARRANTY; without even the implied warranty of
13;;  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14;;  GNU General Public License for more details.
15;;
16;;  You should have received a copy of the GNU General Public License
17;;  along with this program; if not, write to the Free Software
18;;  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19;;
20;;-----------------------------------------------------------------------------
21;
22; This script is designed to be modified for the particular command in
23; operation.  The particular variables pertaining to the commands are:
24;
25ABSOLUTE	Device_ID = 0		; ID of target for command
26ABSOLUTE	MessageCount = 0	; Number of bytes in message
27ABSOLUTE	MessageLocation = 0	; Addr of message
28ABSOLUTE	CommandCount = 0	; Number of bytes in command
29ABSOLUTE	CommandAddress = 0	; Addr of Command
30ABSOLUTE	StatusAddress = 0	; Addr to receive status return
31ABSOLUTE	ReceiveMsgAddress = 0	; Addr to receive msg
32;
33; This is the magic component for handling scatter-gather.  Each of the
34; SG components is preceded by a script fragment which moves the
35; necessary amount of data and jumps to the next SG segment.  The final
36; SG segment jumps back to .  However, this address is the first SG script
37; segment.
38;
39ABSOLUTE	SGScriptStartAddress = 0
40
41; The following represent status interrupts we use 3 hex digits for
42; this: 0xPRS where
43
44; P:
45ABSOLUTE	AFTER_SELECTION 	= 0x100
46ABSOLUTE	BEFORE_CMD 		= 0x200
47ABSOLUTE	AFTER_CMD 		= 0x300
48ABSOLUTE	AFTER_STATUS 		= 0x400
49ABSOLUTE	AFTER_DATA_IN		= 0x500
50ABSOLUTE	AFTER_DATA_OUT		= 0x600
51ABSOLUTE	DURING_DATA_IN		= 0x700
52
53; R:
54ABSOLUTE	NOT_MSG_OUT 		= 0x10
55ABSOLUTE	UNEXPECTED_PHASE 	= 0x20
56ABSOLUTE	NOT_MSG_IN 		= 0x30
57ABSOLUTE	UNEXPECTED_MSG		= 0x40
58ABSOLUTE	MSG_IN			= 0x50
59ABSOLUTE	SDTR_MSG_R		= 0x60
60ABSOLUTE	REJECT_MSG_R		= 0x70
61ABSOLUTE	DISCONNECT		= 0x80
62ABSOLUTE	MSG_OUT			= 0x90
63ABSOLUTE	WDTR_MSG_R		= 0xA0
64
65; S:
66ABSOLUTE	GOOD_STATUS 		= 0x1
67
68; Combinations, since the script assembler can't process |
69ABSOLUTE	NOT_MSG_OUT_AFTER_SELECTION = 0x110
70ABSOLUTE	UNEXPECTED_PHASE_BEFORE_CMD = 0x220
71ABSOLUTE	UNEXPECTED_PHASE_AFTER_CMD = 0x320
72ABSOLUTE	NOT_MSG_IN_AFTER_STATUS = 0x430
73ABSOLUTE	GOOD_STATUS_AFTER_STATUS = 0x401
74ABSOLUTE	UNEXPECTED_PHASE_AFTER_DATA_IN = 0x520
75ABSOLUTE	UNEXPECTED_PHASE_AFTER_DATA_OUT = 0x620
76ABSOLUTE	UNEXPECTED_MSG_BEFORE_CMD = 0x240
77ABSOLUTE	MSG_IN_BEFORE_CMD = 0x250
78ABSOLUTE	MSG_IN_AFTER_CMD = 0x350
79ABSOLUTE	SDTR_MSG_BEFORE_CMD = 0x260
80ABSOLUTE	REJECT_MSG_BEFORE_CMD = 0x270
81ABSOLUTE	DISCONNECT_AFTER_CMD = 0x380
82ABSOLUTE	SDTR_MSG_AFTER_CMD = 0x360
83ABSOLUTE	WDTR_MSG_AFTER_CMD = 0x3A0
84ABSOLUTE	MSG_IN_AFTER_STATUS = 0x440
85ABSOLUTE	DISCONNECT_AFTER_DATA = 0x580
86ABSOLUTE	MSG_IN_AFTER_DATA_IN = 0x550
87ABSOLUTE	MSG_IN_AFTER_DATA_OUT = 0x650
88ABSOLUTE	MSG_OUT_AFTER_DATA_IN = 0x590
89ABSOLUTE	DATA_IN_AFTER_DATA_IN = 0x5a0
90ABSOLUTE	MSG_IN_DURING_DATA_IN = 0x750
91ABSOLUTE	DISCONNECT_DURING_DATA = 0x780
92
93;
94; Other interrupt conditions
95;
96ABSOLUTE	RESELECTED_DURING_SELECTION = 0x1000
97ABSOLUTE	COMPLETED_SELECTION_AS_TARGET = 0x1001
98ABSOLUTE	RESELECTION_IDENTIFIED = 0x1003
99;
100; Fatal interrupt conditions.  If you add to this, also add to the
101; array of corresponding messages
102;
103ABSOLUTE	FATAL = 0x2000
104ABSOLUTE	FATAL_UNEXPECTED_RESELECTION_MSG = 0x2000
105ABSOLUTE	FATAL_SEND_MSG = 0x2001
106ABSOLUTE	FATAL_NOT_MSG_IN_AFTER_SELECTION = 0x2002
107ABSOLUTE	FATAL_ILLEGAL_MSG_LENGTH = 0x2003
108
109ABSOLUTE	DEBUG_INTERRUPT	= 0x3000
110ABSOLUTE	DEBUG_INTERRUPT1 = 0x3001
111ABSOLUTE	DEBUG_INTERRUPT2 = 0x3002
112ABSOLUTE	DEBUG_INTERRUPT3 = 0x3003
113ABSOLUTE	DEBUG_INTERRUPT4 = 0x3004
114ABSOLUTE	DEBUG_INTERRUPT5 = 0x3005
115ABSOLUTE	DEBUG_INTERRUPT6 = 0x3006
116
117
118;
119; SCSI Messages we interpret in the script
120;
121ABSOLUTE	COMMAND_COMPLETE_MSG	= 0x00
122ABSOLUTE	EXTENDED_MSG		= 0x01
123ABSOLUTE	SDTR_MSG		= 0x01
124ABSOLUTE	SAVE_DATA_PTRS_MSG	= 0x02
125ABSOLUTE	RESTORE_DATA_PTRS_MSG	= 0x03
126ABSOLUTE	WDTR_MSG		= 0x03
127ABSOLUTE	DISCONNECT_MSG		= 0x04
128ABSOLUTE	REJECT_MSG		= 0x07
129ABSOLUTE	PARITY_ERROR_MSG	= 0x09
130ABSOLUTE	SIMPLE_TAG_MSG		= 0x20
131ABSOLUTE	IDENTIFY_MSG		= 0x80
132ABSOLUTE	IDENTIFY_MSG_MASK	= 0x7F
133ABSOLUTE	TWO_BYTE_MSG		= 0x20
134ABSOLUTE	TWO_BYTE_MSG_MASK	= 0x0F
135
136; This is where the script begins
137
138ENTRY	StartUp
139
140StartUp:
141	SELECT	ATN Device_ID, Reselect
142	JUMP	Finish, WHEN STATUS
143	JUMP	SendIdentifyMsg, IF MSG_OUT
144	INT	NOT_MSG_OUT_AFTER_SELECTION
145
146Reselect:
147	WAIT	RESELECT SelectedAsTarget
148	INT	RESELECTED_DURING_SELECTION, WHEN MSG_IN
149	INT	FATAL_NOT_MSG_IN_AFTER_SELECTION
150
151	ENTRY	GetReselectionData
152GetReselectionData:
153	MOVE	1, ReceiveMsgAddress, WHEN MSG_IN
154	INT	RESELECTION_IDENTIFIED
155
156	ENTRY	GetReselectionWithTag
157GetReselectionWithTag:
158	MOVE	3, ReceiveMsgAddress, WHEN MSG_IN
159	INT	RESELECTION_IDENTIFIED
160
161	ENTRY	SelectedAsTarget
162SelectedAsTarget:
163; Basically tell the selecting device that there's nothing here
164	SET	TARGET
165	DISCONNECT
166	CLEAR	TARGET
167	INT	COMPLETED_SELECTION_AS_TARGET
168;
169; These are the messaging entries
170;
171; Send a message.  Message count should be correctly patched
172	ENTRY	SendMessage
173SendMessage:
174	MOVE	MessageCount, MessageLocation, WHEN MSG_OUT
175ResumeSendMessage:
176	RETURN,	WHEN NOT MSG_OUT
177	INT	FATAL_SEND_MSG
178
179	ENTRY	SendMessagePhaseMismatch
180SendMessagePhaseMismatch:
181	CLEAR	ACK
182	JUMP	ResumeSendMessage
183;
184; Receive a message.  Need to identify the message to
185; receive it correctly
186	ENTRY	ReceiveMessage
187ReceiveMessage:
188	MOVE	1, ReceiveMsgAddress, WHEN MSG_IN
189;
190; Use this entry if we've just tried to look at the first byte
191; of the message and want to process it further
192ProcessReceiveMessage:
193	JUMP	ReceiveExtendedMessage, IF EXTENDED_MSG
194	RETURN,	IF NOT TWO_BYTE_MSG, AND MASK TWO_BYTE_MSG_MASK
195	CLEAR	ACK
196	MOVE	1, ReceiveMsgAddress + 1, WHEN MSG_IN
197	RETURN
198ReceiveExtendedMessage:
199	CLEAR	ACK
200	MOVE	1, ReceiveMsgAddress + 1, WHEN MSG_IN
201	JUMP	Receive1Byte, IF 0x01
202	JUMP	Receive2Byte, IF 0x02
203	JUMP	Receive3Byte, IF 0x03
204	JUMP	Receive4Byte, IF 0x04
205	JUMP	Receive5Byte, IF 0x05
206	INT	FATAL_ILLEGAL_MSG_LENGTH
207Receive1Byte:
208	CLEAR	ACK
209	MOVE	1, ReceiveMsgAddress + 2, WHEN MSG_IN
210	RETURN
211Receive2Byte:
212	CLEAR	ACK
213	MOVE	2, ReceiveMsgAddress + 2, WHEN MSG_IN
214	RETURN
215Receive3Byte:
216	CLEAR	ACK
217	MOVE	3, ReceiveMsgAddress + 2, WHEN MSG_IN
218	RETURN
219Receive4Byte:
220	CLEAR	ACK
221	MOVE	4, ReceiveMsgAddress + 2, WHEN MSG_IN
222	RETURN
223Receive5Byte:
224	CLEAR	ACK
225	MOVE	5, ReceiveMsgAddress + 2, WHEN MSG_IN
226	RETURN
227;
228; Come here from the message processor to ignore the message
229;
230	ENTRY	IgnoreMessage
231IgnoreMessage:
232	CLEAR	ACK
233	RETURN
234;
235; Come here to send a reply to a message
236;
237	ENTRY	SendMessageWithATN
238SendMessageWithATN:
239	SET	ATN
240	CLEAR	ACK
241	JUMP	SendMessage
242
243SendIdentifyMsg:
244	CALL	SendMessage
245	CLEAR	ATN
246
247IgnoreMsgBeforeCommand:
248	CLEAR	ACK
249	ENTRY	SendCommand
250SendCommand:
251	JUMP	Finish, WHEN STATUS
252	JUMP	MsgInBeforeCommand, IF MSG_IN
253	INT	UNEXPECTED_PHASE_BEFORE_CMD, IF NOT CMD
254	MOVE	CommandCount, CommandAddress, WHEN CMD
255ResumeSendCommand:
256	JUMP	Finish, WHEN STATUS
257	JUMP	MsgInAfterCmd, IF MSG_IN
258	JUMP	DataIn, IF DATA_IN
259	JUMP	DataOut, IF DATA_OUT
260	INT	UNEXPECTED_PHASE_AFTER_CMD
261
262IgnoreMsgDuringData:
263	CLEAR	ACK
264	; fall through to MsgInDuringData
265
266Entry MsgInDuringData
267MsgInDuringData:
268;
269; Could be we have nothing more to transfer
270;
271	JUMP	Finish, WHEN STATUS
272	MOVE	1, ReceiveMsgAddress, WHEN MSG_IN
273	JUMP	DisconnectDuringDataIn, IF DISCONNECT_MSG
274	JUMP	IgnoreMsgDuringData, IF SAVE_DATA_PTRS_MSG
275	JUMP	IgnoreMsgDuringData, IF RESTORE_DATA_PTRS_MSG
276	INT	MSG_IN_DURING_DATA_IN
277
278MsgInAfterCmd:
279	MOVE	1, ReceiveMsgAddress, WHEN MSG_IN
280	JUMP	DisconnectAfterCmd, IF DISCONNECT_MSG
281	JUMP	IgnoreMsgInAfterCmd, IF SAVE_DATA_PTRS_MSG
282	JUMP	IgnoreMsgInAfterCmd, IF RESTORE_DATA_PTRS_MSG
283	CALL	ProcessReceiveMessage
284	INT	MSG_IN_AFTER_CMD
285	CLEAR	ACK
286	JUMP	ResumeSendCommand
287
288IgnoreMsgInAfterCmd:
289	CLEAR	ACK
290	JUMP	ResumeSendCommand
291
292DisconnectAfterCmd:
293	CLEAR	ACK
294	WAIT	DISCONNECT
295	ENTRY	Disconnect1
296Disconnect1:
297	INT	DISCONNECT_AFTER_CMD
298	ENTRY	Disconnect2
299Disconnect2:
300; We return here after a reselection
301	CLEAR	ACK
302	JUMP	ResumeSendCommand
303
304MsgInBeforeCommand:
305	MOVE	1, ReceiveMsgAddress, WHEN MSG_IN
306	JUMP	IgnoreMsgBeforeCommand, IF SAVE_DATA_PTRS_MSG
307	JUMP	IgnoreMsgBeforeCommand, IF RESTORE_DATA_PTRS_MSG
308	CALL	ProcessReceiveMessage
309	INT	MSG_IN_BEFORE_CMD
310	CLEAR	ACK
311	JUMP	SendCommand
312
313DataIn:
314	CALL	SGScriptStartAddress
315ResumeDataIn:
316	JUMP	Finish, WHEN STATUS
317	JUMP	MsgInAfterDataIn, IF MSG_IN
318	JUMP	DataInAfterDataIn, if DATA_IN
319	INT	MSG_OUT_AFTER_DATA_IN, if MSG_OUT
320	INT	UNEXPECTED_PHASE_AFTER_DATA_IN
321
322DataInAfterDataIn:
323	INT	DATA_IN_AFTER_DATA_IN
324	JUMP	ResumeDataIn
325
326DataOut:
327	CALL	SGScriptStartAddress
328ResumeDataOut:
329	JUMP	Finish, WHEN STATUS
330	JUMP	MsgInAfterDataOut, IF MSG_IN
331	INT	UNEXPECTED_PHASE_AFTER_DATA_OUT
332
333MsgInAfterDataIn:
334	MOVE	1, ReceiveMsgAddress, WHEN MSG_IN
335	JUMP	DisconnectAfterDataIn, IF DISCONNECT_MSG
336	JUMP	IgnoreMsgAfterData, IF SAVE_DATA_PTRS_MSG
337	JUMP	IgnoreMsgAfterData, IF RESTORE_DATA_PTRS_MSG
338	CALL	ProcessReceiveMessage
339	INT	MSG_IN_AFTER_DATA_IN
340	CLEAR	ACK
341	JUMP	ResumeDataIn
342
343DisconnectDuringDataIn:
344	CLEAR	ACK
345	WAIT	DISCONNECT
346	ENTRY	Disconnect3
347Disconnect3:
348	INT	DISCONNECT_DURING_DATA
349	ENTRY	Disconnect4
350Disconnect4:
351; we return here after a reselection
352	CLEAR	ACK
353	JUMP	ResumeSendCommand
354
355
356DisconnectAfterDataIn:
357	CLEAR	ACK
358	WAIT	DISCONNECT
359	ENTRY	Disconnect5
360Disconnect5:
361	INT	DISCONNECT_AFTER_DATA
362	ENTRY	Disconnect6
363Disconnect6:
364; we return here after a reselection
365	CLEAR	ACK
366	JUMP	ResumeDataIn
367
368MsgInAfterDataOut:
369	MOVE	1, ReceiveMsgAddress, WHEN MSG_IN
370	JUMP	DisconnectAfterDataOut, if DISCONNECT_MSG
371	JUMP	IgnoreMsgAfterData, IF SAVE_DATA_PTRS_MSG
372	JUMP	IgnoreMsgAfterData, IF RESTORE_DATA_PTRS_MSG
373	CALL	ProcessReceiveMessage
374	INT	MSG_IN_AFTER_DATA_OUT
375	CLEAR	ACK
376	JUMP	ResumeDataOut
377
378IgnoreMsgAfterData:
379	CLEAR	ACK
380; Data in and out do the same thing on resume, so pick one
381	JUMP	ResumeDataIn
382
383DisconnectAfterDataOut:
384	CLEAR	ACK
385	WAIT	DISCONNECT
386	ENTRY	Disconnect7
387Disconnect7:
388	INT	DISCONNECT_AFTER_DATA
389	ENTRY	Disconnect8
390Disconnect8:
391; we return here after a reselection
392	CLEAR	ACK
393	JUMP	ResumeDataOut
394
395Finish:
396	MOVE	1, StatusAddress, WHEN STATUS
397	INT	NOT_MSG_IN_AFTER_STATUS, WHEN NOT MSG_IN
398	MOVE	1, ReceiveMsgAddress, WHEN MSG_IN
399	JUMP	FinishCommandComplete, IF COMMAND_COMPLETE_MSG
400	CALL	ProcessReceiveMessage
401	INT	MSG_IN_AFTER_STATUS
402	ENTRY	FinishCommandComplete
403FinishCommandComplete:
404	CLEAR	ACK
405	WAIT	DISCONNECT
406	ENTRY	Finish1
407Finish1:
408	INT	GOOD_STATUS_AFTER_STATUS
409	ENTRY	Finish2
410Finish2:
411
412