[SCSI] ses: add subenclosure support
[linux-2.6.git] / drivers / scsi / 53c700.scr
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 ;
25 ABSOLUTE        Device_ID = 0           ; ID of target for command
26 ABSOLUTE        MessageCount = 0        ; Number of bytes in message
27 ABSOLUTE        MessageLocation = 0     ; Addr of message
28 ABSOLUTE        CommandCount = 0        ; Number of bytes in command
29 ABSOLUTE        CommandAddress = 0      ; Addr of Command
30 ABSOLUTE        StatusAddress = 0       ; Addr to receive status return
31 ABSOLUTE        ReceiveMsgAddress = 0   ; Addr to receive msg
32 ;
33 ; This is the magic component for handling scatter-gather.  Each of the
34 ; SG components is preceeded 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 ;
39 ABSOLUTE        SGScriptStartAddress = 0
40
41 ; The following represent status interrupts we use 3 hex digits for
42 ; this: 0xPRS where 
43
44 ; P:
45 ABSOLUTE        AFTER_SELECTION         = 0x100
46 ABSOLUTE        BEFORE_CMD              = 0x200
47 ABSOLUTE        AFTER_CMD               = 0x300
48 ABSOLUTE        AFTER_STATUS            = 0x400
49 ABSOLUTE        AFTER_DATA_IN           = 0x500
50 ABSOLUTE        AFTER_DATA_OUT          = 0x600
51 ABSOLUTE        DURING_DATA_IN          = 0x700
52
53 ; R:
54 ABSOLUTE        NOT_MSG_OUT             = 0x10
55 ABSOLUTE        UNEXPECTED_PHASE        = 0x20
56 ABSOLUTE        NOT_MSG_IN              = 0x30
57 ABSOLUTE        UNEXPECTED_MSG          = 0x40
58 ABSOLUTE        MSG_IN                  = 0x50
59 ABSOLUTE        SDTR_MSG_R              = 0x60
60 ABSOLUTE        REJECT_MSG_R            = 0x70
61 ABSOLUTE        DISCONNECT              = 0x80
62 ABSOLUTE        MSG_OUT                 = 0x90
63 ABSOLUTE        WDTR_MSG_R              = 0xA0
64
65 ; S:
66 ABSOLUTE        GOOD_STATUS             = 0x1
67
68 ; Combinations, since the script assembler can't process |
69 ABSOLUTE        NOT_MSG_OUT_AFTER_SELECTION = 0x110
70 ABSOLUTE        UNEXPECTED_PHASE_BEFORE_CMD = 0x220
71 ABSOLUTE        UNEXPECTED_PHASE_AFTER_CMD = 0x320
72 ABSOLUTE        NOT_MSG_IN_AFTER_STATUS = 0x430
73 ABSOLUTE        GOOD_STATUS_AFTER_STATUS = 0x401
74 ABSOLUTE        UNEXPECTED_PHASE_AFTER_DATA_IN = 0x520
75 ABSOLUTE        UNEXPECTED_PHASE_AFTER_DATA_OUT = 0x620
76 ABSOLUTE        UNEXPECTED_MSG_BEFORE_CMD = 0x240
77 ABSOLUTE        MSG_IN_BEFORE_CMD = 0x250
78 ABSOLUTE        MSG_IN_AFTER_CMD = 0x350
79 ABSOLUTE        SDTR_MSG_BEFORE_CMD = 0x260
80 ABSOLUTE        REJECT_MSG_BEFORE_CMD = 0x270
81 ABSOLUTE        DISCONNECT_AFTER_CMD = 0x380
82 ABSOLUTE        SDTR_MSG_AFTER_CMD = 0x360
83 ABSOLUTE        WDTR_MSG_AFTER_CMD = 0x3A0
84 ABSOLUTE        MSG_IN_AFTER_STATUS = 0x440
85 ABSOLUTE        DISCONNECT_AFTER_DATA = 0x580
86 ABSOLUTE        MSG_IN_AFTER_DATA_IN = 0x550
87 ABSOLUTE        MSG_IN_AFTER_DATA_OUT = 0x650
88 ABSOLUTE        MSG_OUT_AFTER_DATA_IN = 0x590
89 ABSOLUTE        DATA_IN_AFTER_DATA_IN = 0x5a0
90 ABSOLUTE        MSG_IN_DURING_DATA_IN = 0x750
91 ABSOLUTE        DISCONNECT_DURING_DATA = 0x780
92
93 ;
94 ; Other interrupt conditions
95
96 ABSOLUTE        RESELECTED_DURING_SELECTION = 0x1000
97 ABSOLUTE        COMPLETED_SELECTION_AS_TARGET = 0x1001
98 ABSOLUTE        RESELECTION_IDENTIFIED = 0x1003
99 ;
100 ; Fatal interrupt conditions.  If you add to this, also add to the
101 ; array of corresponding messages
102 ;
103 ABSOLUTE        FATAL = 0x2000
104 ABSOLUTE        FATAL_UNEXPECTED_RESELECTION_MSG = 0x2000
105 ABSOLUTE        FATAL_SEND_MSG = 0x2001
106 ABSOLUTE        FATAL_NOT_MSG_IN_AFTER_SELECTION = 0x2002
107 ABSOLUTE        FATAL_ILLEGAL_MSG_LENGTH = 0x2003
108
109 ABSOLUTE        DEBUG_INTERRUPT = 0x3000
110 ABSOLUTE        DEBUG_INTERRUPT1 = 0x3001
111 ABSOLUTE        DEBUG_INTERRUPT2 = 0x3002
112 ABSOLUTE        DEBUG_INTERRUPT3 = 0x3003
113 ABSOLUTE        DEBUG_INTERRUPT4 = 0x3004
114 ABSOLUTE        DEBUG_INTERRUPT5 = 0x3005
115 ABSOLUTE        DEBUG_INTERRUPT6 = 0x3006
116
117
118 ;
119 ; SCSI Messages we interpret in the script
120 ;
121 ABSOLUTE        COMMAND_COMPLETE_MSG    = 0x00
122 ABSOLUTE        EXTENDED_MSG            = 0x01
123 ABSOLUTE        SDTR_MSG                = 0x01
124 ABSOLUTE        SAVE_DATA_PTRS_MSG      = 0x02
125 ABSOLUTE        RESTORE_DATA_PTRS_MSG   = 0x03
126 ABSOLUTE        WDTR_MSG                = 0x03
127 ABSOLUTE        DISCONNECT_MSG          = 0x04
128 ABSOLUTE        REJECT_MSG              = 0x07
129 ABSOLUTE        PARITY_ERROR_MSG        = 0x09
130 ABSOLUTE        SIMPLE_TAG_MSG          = 0x20
131 ABSOLUTE        IDENTIFY_MSG            = 0x80
132 ABSOLUTE        IDENTIFY_MSG_MASK       = 0x7F
133 ABSOLUTE        TWO_BYTE_MSG            = 0x20
134 ABSOLUTE        TWO_BYTE_MSG_MASK       = 0x0F
135
136 ; This is where the script begins
137
138 ENTRY   StartUp
139
140 StartUp:
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
146 Reselect:
147         WAIT    RESELECT SelectedAsTarget
148         INT     RESELECTED_DURING_SELECTION, WHEN MSG_IN
149         INT     FATAL_NOT_MSG_IN_AFTER_SELECTION
150
151         ENTRY   GetReselectionData
152 GetReselectionData:
153         MOVE    1, ReceiveMsgAddress, WHEN MSG_IN
154         INT     RESELECTION_IDENTIFIED
155
156         ENTRY   GetReselectionWithTag
157 GetReselectionWithTag:
158         MOVE    3, ReceiveMsgAddress, WHEN MSG_IN
159         INT     RESELECTION_IDENTIFIED
160         
161         ENTRY   SelectedAsTarget
162 SelectedAsTarget:
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
173 SendMessage:
174         MOVE    MessageCount, MessageLocation, WHEN MSG_OUT
175 ResumeSendMessage:
176         RETURN, WHEN NOT MSG_OUT
177         INT     FATAL_SEND_MSG
178
179         ENTRY   SendMessagePhaseMismatch
180 SendMessagePhaseMismatch:
181         CLEAR   ACK
182         JUMP    ResumeSendMessage
183 ;
184 ; Receive a message.  Need to identify the message to
185 ; receive it correctly
186         ENTRY   ReceiveMessage
187 ReceiveMessage:
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
192 ProcessReceiveMessage:
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
198 ReceiveExtendedMessage:
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
207 Receive1Byte:
208         CLEAR   ACK
209         MOVE    1, ReceiveMsgAddress + 2, WHEN MSG_IN
210         RETURN
211 Receive2Byte:
212         CLEAR   ACK
213         MOVE    2, ReceiveMsgAddress + 2, WHEN MSG_IN
214         RETURN
215 Receive3Byte:
216         CLEAR   ACK
217         MOVE    3, ReceiveMsgAddress + 2, WHEN MSG_IN
218         RETURN
219 Receive4Byte:
220         CLEAR   ACK
221         MOVE    4, ReceiveMsgAddress + 2, WHEN MSG_IN
222         RETURN
223 Receive5Byte:
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
231 IgnoreMessage:
232         CLEAR   ACK
233         RETURN
234 ;
235 ; Come here to send a reply to a message
236 ;
237         ENTRY   SendMessageWithATN
238 SendMessageWithATN:
239         SET     ATN
240         CLEAR   ACK
241         JUMP    SendMessage
242
243 SendIdentifyMsg:
244         CALL    SendMessage
245         CLEAR   ATN
246
247 IgnoreMsgBeforeCommand:
248         CLEAR   ACK
249         ENTRY   SendCommand
250 SendCommand:
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
255 ResumeSendCommand:
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
262 IgnoreMsgDuringData:
263         CLEAR   ACK
264         ; fall through to MsgInDuringData
265
266 Entry MsgInDuringData
267 MsgInDuringData:
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
278 MsgInAfterCmd:
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
288 IgnoreMsgInAfterCmd:
289         CLEAR   ACK
290         JUMP    ResumeSendCommand
291
292 DisconnectAfterCmd:
293         CLEAR   ACK
294         WAIT    DISCONNECT
295         ENTRY   Disconnect1
296 Disconnect1:
297         INT     DISCONNECT_AFTER_CMD
298         ENTRY   Disconnect2
299 Disconnect2:
300 ; We return here after a reselection
301         CLEAR   ACK
302         JUMP    ResumeSendCommand
303
304 MsgInBeforeCommand:
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
313 DataIn:
314         CALL    SGScriptStartAddress
315 ResumeDataIn:
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
322 DataInAfterDataIn:
323         INT     DATA_IN_AFTER_DATA_IN
324         JUMP    ResumeDataIn
325
326 DataOut:
327         CALL    SGScriptStartAddress
328 ResumeDataOut:
329         JUMP    Finish, WHEN STATUS
330         JUMP    MsgInAfterDataOut, IF MSG_IN
331         INT     UNEXPECTED_PHASE_AFTER_DATA_OUT
332
333 MsgInAfterDataIn:
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
343 DisconnectDuringDataIn:
344         CLEAR   ACK
345         WAIT    DISCONNECT
346         ENTRY   Disconnect3
347 Disconnect3:
348         INT     DISCONNECT_DURING_DATA
349         ENTRY   Disconnect4
350 Disconnect4:
351 ; we return here after a reselection
352         CLEAR   ACK
353         JUMP    ResumeSendCommand
354
355
356 DisconnectAfterDataIn:
357         CLEAR   ACK
358         WAIT    DISCONNECT
359         ENTRY   Disconnect5
360 Disconnect5:
361         INT     DISCONNECT_AFTER_DATA
362         ENTRY   Disconnect6
363 Disconnect6:
364 ; we return here after a reselection
365         CLEAR   ACK
366         JUMP    ResumeDataIn
367
368 MsgInAfterDataOut:
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
378 IgnoreMsgAfterData:
379         CLEAR   ACK
380 ; Data in and out do the same thing on resume, so pick one
381         JUMP    ResumeDataIn
382
383 DisconnectAfterDataOut:
384         CLEAR   ACK
385         WAIT    DISCONNECT
386         ENTRY   Disconnect7
387 Disconnect7:
388         INT     DISCONNECT_AFTER_DATA
389         ENTRY   Disconnect8
390 Disconnect8:
391 ; we return here after a reselection
392         CLEAR   ACK
393         JUMP    ResumeDataOut
394
395 Finish:
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
403 FinishCommandComplete:
404         CLEAR   ACK
405         WAIT    DISCONNECT
406         ENTRY   Finish1
407 Finish1:
408         INT     GOOD_STATUS_AFTER_STATUS
409         ENTRY   Finish2
410 Finish2:
411