diff options
Diffstat (limited to 'drivers/scsi/53c700.scr')
-rw-r--r-- | drivers/scsi/53c700.scr | 411 |
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: + |