0001 ; Script for the NCR (or symbios) 53c700 and 53c700-66 chip
0002 ;
0003 ; Copyright (C) 2001 James.Bottomley@HansenPartnership.com
0004 ;;-----------------------------------------------------------------------------
0005 ;;
0006 ;; This program is free software; you can redistribute it and/or modify
0007 ;; it under the terms of the GNU General Public License as published by
0008 ;; the Free Software Foundation; either version 2 of the License, or
0009 ;; (at your option) any later version.
0010 ;;
0011 ;; This program is distributed in the hope that it will be useful,
0012 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
0013 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
0014 ;; GNU General Public License for more details.
0015 ;;
0016 ;; You should have received a copy of the GNU General Public License
0017 ;; along with this program; if not, write to the Free Software
0018 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
0019 ;;
0020 ;;-----------------------------------------------------------------------------
0021 ;
0022 ; This script is designed to be modified for the particular command in
0023 ; operation. The particular variables pertaining to the commands are:
0024 ;
0025 ABSOLUTE Device_ID = 0 ; ID of target for command
0026 ABSOLUTE MessageCount = 0 ; Number of bytes in message
0027 ABSOLUTE MessageLocation = 0 ; Addr of message
0028 ABSOLUTE CommandCount = 0 ; Number of bytes in command
0029 ABSOLUTE CommandAddress = 0 ; Addr of Command
0030 ABSOLUTE StatusAddress = 0 ; Addr to receive status return
0031 ABSOLUTE ReceiveMsgAddress = 0 ; Addr to receive msg
0032 ;
0033 ; This is the magic component for handling scatter-gather. Each of the
0034 ; SG components is preceded by a script fragment which moves the
0035 ; necessary amount of data and jumps to the next SG segment. The final
0036 ; SG segment jumps back to . However, this address is the first SG script
0037 ; segment.
0038 ;
0039 ABSOLUTE SGScriptStartAddress = 0
0040
0041 ; The following represent status interrupts we use 3 hex digits for
0042 ; this: 0xPRS where
0043
0044 ; P:
0045 ABSOLUTE AFTER_SELECTION = 0x100
0046 ABSOLUTE BEFORE_CMD = 0x200
0047 ABSOLUTE AFTER_CMD = 0x300
0048 ABSOLUTE AFTER_STATUS = 0x400
0049 ABSOLUTE AFTER_DATA_IN = 0x500
0050 ABSOLUTE AFTER_DATA_OUT = 0x600
0051 ABSOLUTE DURING_DATA_IN = 0x700
0052
0053 ; R:
0054 ABSOLUTE NOT_MSG_OUT = 0x10
0055 ABSOLUTE UNEXPECTED_PHASE = 0x20
0056 ABSOLUTE NOT_MSG_IN = 0x30
0057 ABSOLUTE UNEXPECTED_MSG = 0x40
0058 ABSOLUTE MSG_IN = 0x50
0059 ABSOLUTE SDTR_MSG_R = 0x60
0060 ABSOLUTE REJECT_MSG_R = 0x70
0061 ABSOLUTE DISCONNECT = 0x80
0062 ABSOLUTE MSG_OUT = 0x90
0063 ABSOLUTE WDTR_MSG_R = 0xA0
0064
0065 ; S:
0066 ABSOLUTE GOOD_STATUS = 0x1
0067
0068 ; Combinations, since the script assembler can't process |
0069 ABSOLUTE NOT_MSG_OUT_AFTER_SELECTION = 0x110
0070 ABSOLUTE UNEXPECTED_PHASE_BEFORE_CMD = 0x220
0071 ABSOLUTE UNEXPECTED_PHASE_AFTER_CMD = 0x320
0072 ABSOLUTE NOT_MSG_IN_AFTER_STATUS = 0x430
0073 ABSOLUTE GOOD_STATUS_AFTER_STATUS = 0x401
0074 ABSOLUTE UNEXPECTED_PHASE_AFTER_DATA_IN = 0x520
0075 ABSOLUTE UNEXPECTED_PHASE_AFTER_DATA_OUT = 0x620
0076 ABSOLUTE UNEXPECTED_MSG_BEFORE_CMD = 0x240
0077 ABSOLUTE MSG_IN_BEFORE_CMD = 0x250
0078 ABSOLUTE MSG_IN_AFTER_CMD = 0x350
0079 ABSOLUTE SDTR_MSG_BEFORE_CMD = 0x260
0080 ABSOLUTE REJECT_MSG_BEFORE_CMD = 0x270
0081 ABSOLUTE DISCONNECT_AFTER_CMD = 0x380
0082 ABSOLUTE SDTR_MSG_AFTER_CMD = 0x360
0083 ABSOLUTE WDTR_MSG_AFTER_CMD = 0x3A0
0084 ABSOLUTE MSG_IN_AFTER_STATUS = 0x440
0085 ABSOLUTE DISCONNECT_AFTER_DATA = 0x580
0086 ABSOLUTE MSG_IN_AFTER_DATA_IN = 0x550
0087 ABSOLUTE MSG_IN_AFTER_DATA_OUT = 0x650
0088 ABSOLUTE MSG_OUT_AFTER_DATA_IN = 0x590
0089 ABSOLUTE DATA_IN_AFTER_DATA_IN = 0x5a0
0090 ABSOLUTE MSG_IN_DURING_DATA_IN = 0x750
0091 ABSOLUTE DISCONNECT_DURING_DATA = 0x780
0092
0093 ;
0094 ; Other interrupt conditions
0095 ;
0096 ABSOLUTE RESELECTED_DURING_SELECTION = 0x1000
0097 ABSOLUTE COMPLETED_SELECTION_AS_TARGET = 0x1001
0098 ABSOLUTE RESELECTION_IDENTIFIED = 0x1003
0099 ;
0100 ; Fatal interrupt conditions. If you add to this, also add to the
0101 ; array of corresponding messages
0102 ;
0103 ABSOLUTE FATAL = 0x2000
0104 ABSOLUTE FATAL_UNEXPECTED_RESELECTION_MSG = 0x2000
0105 ABSOLUTE FATAL_SEND_MSG = 0x2001
0106 ABSOLUTE FATAL_NOT_MSG_IN_AFTER_SELECTION = 0x2002
0107 ABSOLUTE FATAL_ILLEGAL_MSG_LENGTH = 0x2003
0108
0109 ABSOLUTE DEBUG_INTERRUPT = 0x3000
0110 ABSOLUTE DEBUG_INTERRUPT1 = 0x3001
0111 ABSOLUTE DEBUG_INTERRUPT2 = 0x3002
0112 ABSOLUTE DEBUG_INTERRUPT3 = 0x3003
0113 ABSOLUTE DEBUG_INTERRUPT4 = 0x3004
0114 ABSOLUTE DEBUG_INTERRUPT5 = 0x3005
0115 ABSOLUTE DEBUG_INTERRUPT6 = 0x3006
0116
0117
0118 ;
0119 ; SCSI Messages we interpret in the script
0120 ;
0121 ABSOLUTE COMMAND_COMPLETE_MSG = 0x00
0122 ABSOLUTE EXTENDED_MSG = 0x01
0123 ABSOLUTE SDTR_MSG = 0x01
0124 ABSOLUTE SAVE_DATA_PTRS_MSG = 0x02
0125 ABSOLUTE RESTORE_DATA_PTRS_MSG = 0x03
0126 ABSOLUTE WDTR_MSG = 0x03
0127 ABSOLUTE DISCONNECT_MSG = 0x04
0128 ABSOLUTE REJECT_MSG = 0x07
0129 ABSOLUTE PARITY_ERROR_MSG = 0x09
0130 ABSOLUTE SIMPLE_TAG_MSG = 0x20
0131 ABSOLUTE IDENTIFY_MSG = 0x80
0132 ABSOLUTE IDENTIFY_MSG_MASK = 0x7F
0133 ABSOLUTE TWO_BYTE_MSG = 0x20
0134 ABSOLUTE TWO_BYTE_MSG_MASK = 0x0F
0135
0136 ; This is where the script begins
0137
0138 ENTRY StartUp
0139
0140 StartUp:
0141 SELECT ATN Device_ID, Reselect
0142 JUMP Finish, WHEN STATUS
0143 JUMP SendIdentifyMsg, IF MSG_OUT
0144 INT NOT_MSG_OUT_AFTER_SELECTION
0145
0146 Reselect:
0147 WAIT RESELECT SelectedAsTarget
0148 INT RESELECTED_DURING_SELECTION, WHEN MSG_IN
0149 INT FATAL_NOT_MSG_IN_AFTER_SELECTION
0150
0151 ENTRY GetReselectionData
0152 GetReselectionData:
0153 MOVE 1, ReceiveMsgAddress, WHEN MSG_IN
0154 INT RESELECTION_IDENTIFIED
0155
0156 ENTRY GetReselectionWithTag
0157 GetReselectionWithTag:
0158 MOVE 3, ReceiveMsgAddress, WHEN MSG_IN
0159 INT RESELECTION_IDENTIFIED
0160
0161 ENTRY SelectedAsTarget
0162 SelectedAsTarget:
0163 ; Basically tell the selecting device that there's nothing here
0164 SET TARGET
0165 DISCONNECT
0166 CLEAR TARGET
0167 INT COMPLETED_SELECTION_AS_TARGET
0168 ;
0169 ; These are the messaging entries
0170 ;
0171 ; Send a message. Message count should be correctly patched
0172 ENTRY SendMessage
0173 SendMessage:
0174 MOVE MessageCount, MessageLocation, WHEN MSG_OUT
0175 ResumeSendMessage:
0176 RETURN, WHEN NOT MSG_OUT
0177 INT FATAL_SEND_MSG
0178
0179 ENTRY SendMessagePhaseMismatch
0180 SendMessagePhaseMismatch:
0181 CLEAR ACK
0182 JUMP ResumeSendMessage
0183 ;
0184 ; Receive a message. Need to identify the message to
0185 ; receive it correctly
0186 ENTRY ReceiveMessage
0187 ReceiveMessage:
0188 MOVE 1, ReceiveMsgAddress, WHEN MSG_IN
0189 ;
0190 ; Use this entry if we've just tried to look at the first byte
0191 ; of the message and want to process it further
0192 ProcessReceiveMessage:
0193 JUMP ReceiveExtendedMessage, IF EXTENDED_MSG
0194 RETURN, IF NOT TWO_BYTE_MSG, AND MASK TWO_BYTE_MSG_MASK
0195 CLEAR ACK
0196 MOVE 1, ReceiveMsgAddress + 1, WHEN MSG_IN
0197 RETURN
0198 ReceiveExtendedMessage:
0199 CLEAR ACK
0200 MOVE 1, ReceiveMsgAddress + 1, WHEN MSG_IN
0201 JUMP Receive1Byte, IF 0x01
0202 JUMP Receive2Byte, IF 0x02
0203 JUMP Receive3Byte, IF 0x03
0204 JUMP Receive4Byte, IF 0x04
0205 JUMP Receive5Byte, IF 0x05
0206 INT FATAL_ILLEGAL_MSG_LENGTH
0207 Receive1Byte:
0208 CLEAR ACK
0209 MOVE 1, ReceiveMsgAddress + 2, WHEN MSG_IN
0210 RETURN
0211 Receive2Byte:
0212 CLEAR ACK
0213 MOVE 2, ReceiveMsgAddress + 2, WHEN MSG_IN
0214 RETURN
0215 Receive3Byte:
0216 CLEAR ACK
0217 MOVE 3, ReceiveMsgAddress + 2, WHEN MSG_IN
0218 RETURN
0219 Receive4Byte:
0220 CLEAR ACK
0221 MOVE 4, ReceiveMsgAddress + 2, WHEN MSG_IN
0222 RETURN
0223 Receive5Byte:
0224 CLEAR ACK
0225 MOVE 5, ReceiveMsgAddress + 2, WHEN MSG_IN
0226 RETURN
0227 ;
0228 ; Come here from the message processor to ignore the message
0229 ;
0230 ENTRY IgnoreMessage
0231 IgnoreMessage:
0232 CLEAR ACK
0233 RETURN
0234 ;
0235 ; Come here to send a reply to a message
0236 ;
0237 ENTRY SendMessageWithATN
0238 SendMessageWithATN:
0239 SET ATN
0240 CLEAR ACK
0241 JUMP SendMessage
0242
0243 SendIdentifyMsg:
0244 CALL SendMessage
0245 CLEAR ATN
0246
0247 IgnoreMsgBeforeCommand:
0248 CLEAR ACK
0249 ENTRY SendCommand
0250 SendCommand:
0251 JUMP Finish, WHEN STATUS
0252 JUMP MsgInBeforeCommand, IF MSG_IN
0253 INT UNEXPECTED_PHASE_BEFORE_CMD, IF NOT CMD
0254 MOVE CommandCount, CommandAddress, WHEN CMD
0255 ResumeSendCommand:
0256 JUMP Finish, WHEN STATUS
0257 JUMP MsgInAfterCmd, IF MSG_IN
0258 JUMP DataIn, IF DATA_IN
0259 JUMP DataOut, IF DATA_OUT
0260 INT UNEXPECTED_PHASE_AFTER_CMD
0261
0262 IgnoreMsgDuringData:
0263 CLEAR ACK
0264 ; fall through to MsgInDuringData
0265
0266 Entry MsgInDuringData
0267 MsgInDuringData:
0268 ;
0269 ; Could be we have nothing more to transfer
0270 ;
0271 JUMP Finish, WHEN STATUS
0272 MOVE 1, ReceiveMsgAddress, WHEN MSG_IN
0273 JUMP DisconnectDuringDataIn, IF DISCONNECT_MSG
0274 JUMP IgnoreMsgDuringData, IF SAVE_DATA_PTRS_MSG
0275 JUMP IgnoreMsgDuringData, IF RESTORE_DATA_PTRS_MSG
0276 INT MSG_IN_DURING_DATA_IN
0277
0278 MsgInAfterCmd:
0279 MOVE 1, ReceiveMsgAddress, WHEN MSG_IN
0280 JUMP DisconnectAfterCmd, IF DISCONNECT_MSG
0281 JUMP IgnoreMsgInAfterCmd, IF SAVE_DATA_PTRS_MSG
0282 JUMP IgnoreMsgInAfterCmd, IF RESTORE_DATA_PTRS_MSG
0283 CALL ProcessReceiveMessage
0284 INT MSG_IN_AFTER_CMD
0285 CLEAR ACK
0286 JUMP ResumeSendCommand
0287
0288 IgnoreMsgInAfterCmd:
0289 CLEAR ACK
0290 JUMP ResumeSendCommand
0291
0292 DisconnectAfterCmd:
0293 CLEAR ACK
0294 WAIT DISCONNECT
0295 ENTRY Disconnect1
0296 Disconnect1:
0297 INT DISCONNECT_AFTER_CMD
0298 ENTRY Disconnect2
0299 Disconnect2:
0300 ; We return here after a reselection
0301 CLEAR ACK
0302 JUMP ResumeSendCommand
0303
0304 MsgInBeforeCommand:
0305 MOVE 1, ReceiveMsgAddress, WHEN MSG_IN
0306 JUMP IgnoreMsgBeforeCommand, IF SAVE_DATA_PTRS_MSG
0307 JUMP IgnoreMsgBeforeCommand, IF RESTORE_DATA_PTRS_MSG
0308 CALL ProcessReceiveMessage
0309 INT MSG_IN_BEFORE_CMD
0310 CLEAR ACK
0311 JUMP SendCommand
0312
0313 DataIn:
0314 CALL SGScriptStartAddress
0315 ResumeDataIn:
0316 JUMP Finish, WHEN STATUS
0317 JUMP MsgInAfterDataIn, IF MSG_IN
0318 JUMP DataInAfterDataIn, if DATA_IN
0319 INT MSG_OUT_AFTER_DATA_IN, if MSG_OUT
0320 INT UNEXPECTED_PHASE_AFTER_DATA_IN
0321
0322 DataInAfterDataIn:
0323 INT DATA_IN_AFTER_DATA_IN
0324 JUMP ResumeDataIn
0325
0326 DataOut:
0327 CALL SGScriptStartAddress
0328 ResumeDataOut:
0329 JUMP Finish, WHEN STATUS
0330 JUMP MsgInAfterDataOut, IF MSG_IN
0331 INT UNEXPECTED_PHASE_AFTER_DATA_OUT
0332
0333 MsgInAfterDataIn:
0334 MOVE 1, ReceiveMsgAddress, WHEN MSG_IN
0335 JUMP DisconnectAfterDataIn, IF DISCONNECT_MSG
0336 JUMP IgnoreMsgAfterData, IF SAVE_DATA_PTRS_MSG
0337 JUMP IgnoreMsgAfterData, IF RESTORE_DATA_PTRS_MSG
0338 CALL ProcessReceiveMessage
0339 INT MSG_IN_AFTER_DATA_IN
0340 CLEAR ACK
0341 JUMP ResumeDataIn
0342
0343 DisconnectDuringDataIn:
0344 CLEAR ACK
0345 WAIT DISCONNECT
0346 ENTRY Disconnect3
0347 Disconnect3:
0348 INT DISCONNECT_DURING_DATA
0349 ENTRY Disconnect4
0350 Disconnect4:
0351 ; we return here after a reselection
0352 CLEAR ACK
0353 JUMP ResumeSendCommand
0354
0355
0356 DisconnectAfterDataIn:
0357 CLEAR ACK
0358 WAIT DISCONNECT
0359 ENTRY Disconnect5
0360 Disconnect5:
0361 INT DISCONNECT_AFTER_DATA
0362 ENTRY Disconnect6
0363 Disconnect6:
0364 ; we return here after a reselection
0365 CLEAR ACK
0366 JUMP ResumeDataIn
0367
0368 MsgInAfterDataOut:
0369 MOVE 1, ReceiveMsgAddress, WHEN MSG_IN
0370 JUMP DisconnectAfterDataOut, if DISCONNECT_MSG
0371 JUMP IgnoreMsgAfterData, IF SAVE_DATA_PTRS_MSG
0372 JUMP IgnoreMsgAfterData, IF RESTORE_DATA_PTRS_MSG
0373 CALL ProcessReceiveMessage
0374 INT MSG_IN_AFTER_DATA_OUT
0375 CLEAR ACK
0376 JUMP ResumeDataOut
0377
0378 IgnoreMsgAfterData:
0379 CLEAR ACK
0380 ; Data in and out do the same thing on resume, so pick one
0381 JUMP ResumeDataIn
0382
0383 DisconnectAfterDataOut:
0384 CLEAR ACK
0385 WAIT DISCONNECT
0386 ENTRY Disconnect7
0387 Disconnect7:
0388 INT DISCONNECT_AFTER_DATA
0389 ENTRY Disconnect8
0390 Disconnect8:
0391 ; we return here after a reselection
0392 CLEAR ACK
0393 JUMP ResumeDataOut
0394
0395 Finish:
0396 MOVE 1, StatusAddress, WHEN STATUS
0397 INT NOT_MSG_IN_AFTER_STATUS, WHEN NOT MSG_IN
0398 MOVE 1, ReceiveMsgAddress, WHEN MSG_IN
0399 JUMP FinishCommandComplete, IF COMMAND_COMPLETE_MSG
0400 CALL ProcessReceiveMessage
0401 INT MSG_IN_AFTER_STATUS
0402 ENTRY FinishCommandComplete
0403 FinishCommandComplete:
0404 CLEAR ACK
0405 WAIT DISCONNECT
0406 ENTRY Finish1
0407 Finish1:
0408 INT GOOD_STATUS_AFTER_STATUS
0409 ENTRY Finish2
0410 Finish2:
0411