2005-04-17 06:20:36 +08:00
|
|
|
; 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
|
2011-03-31 09:57:33 +08:00
|
|
|
; SG components is preceded by a script fragment which moves the
|
2005-04-17 06:20:36 +08:00
|
|
|
; 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:
|
|
|
|
|