summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/53c700.scr
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/53c700.scr')
-rw-r--r--drivers/scsi/53c700.scr411
1 files changed, 411 insertions, 0 deletions
diff --git a/drivers/scsi/53c700.scr b/drivers/scsi/53c700.scr
new file mode 100644
index 000000000..ec822e3b7
--- /dev/null
+++ b/drivers/scsi/53c700.scr
@@ -0,0 +1,411 @@
+; 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:
+