53c700.scr 10.6 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 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: