1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 2 ; ; 3 ; Generic SCRIPTS for 53C875 chip ; 4 ; ; 5 ; This script is designed to minimise host CPU intervention ; 6 ; ; 7 ; Unfortunately, CPU intervention is required: ; 8 ; 1) If a target wants to disconnect in the middle of a transfer ; 9 ; 2) On just about any error condition ; 10 ; ; 11 ; In the absense of errors, the CPU queues requests to the ; 12 ; scsi_id_table[scsi_id].queue_head and sets the SIGP bit in the ISTAT reg. ; 13 ; It gets an 'INTFLY' as each request completes. This script runs ; 14 ; continuously waiting for requests to process. ; 15 ; ; 16 ; If an error occurrs, this chip halts and the host CPU gets an interrupt. ; 17 ; The host CPU will attempt to recover the condition and restart the chip. ; 18 ; The host CPU may decide the best recovery is to software reset this chip ; 19 ; and perform a SCSI reset, at which point it will re-load this code and re- ; 20 ; start this chip. ; 21 ; ; 22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 23 ; 24 ARCH 875 ; chip is an 53C875 25 ; 26 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 27 ; 28 ; List of entrypoints that the host can start us at 29 ; 30 ENTRY select_timedout ; jump here after 'SELECT' timeout 31 ENTRY startup ; initialization 32 ENTRY transfer_data_done ; the list of rp_datamovs JUMP's here when done 33 ENTRY transfer_data_mismatch ; re-enter here if phase mismatch during data transfer 34 ; 35 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 36 ; 37 ; Transfer requested negotiation options 38 ; 39 ABSOLUTE REQ_ACK_OFFSET = 16 ; can send up to 16 unacknowleged data at a time 40 ABSOLUTE XFER_PERIOD_FACT = 12 ; 12=50ns (20MHz) 41 ; 42 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 43 ; 44 ; Scsi id table entry definitions 45 ; 46 ; There is one entry per possible scsi id. These are stored in the internal RAM. 47 ; The table must be aligned on a 256-byte boundary. Each element can have up to 48 ; 16 bytes. 49 ; 50 ; se_queue_head[32]: pointer to first request in queue 51 ; se0_state[8]: state the current request is in (init to STATE_EMPTY) 52 ; gets changed in real-time to the current state 53 ; (used for debugging only) 54 ; se1_sxfer[8]: negotiated value (default startup value 0x00) 55 ; se2_unused[8]: unused 56 ; se3_scntl3[8]: negotiated value (default startup value 0x55) 57 ; se_saved_pointer[32]: saved data offset 58 ; 59 ABSOLUTE se_queue_head = 0 60 ABSOLUTE se0_state = 4 61 ABSOLUTE SE_STATE_IDLE = 0 62 ABSOLUTE SE_STATE_GETTING_MESSAGE = 1 63 ABSOLUTE SE_STATE_GETTING_STATUS = 2 64 ABSOLUTE SE_STATE_MESSAGE_OUT = 3 65 ABSOLUTE SE_STATE_CHECKING_TARGET = 4 66 ABSOLUTE SE_STATE_SELECTED = 5 67 ABSOLUTE SE_STATE_SELECTING = 6 68 ABSOLUTE SE_STATE_SENDING_COMMAND = 7 69 ABSOLUTE SE_STATE_TRANSFERRING_DATA = 8 70 ABSOLUTE SE_STATE_WAITING_FOR_RESELECT = 9 71 ABSOLUTE se1_sxfer = 5 72 ABSOLUTE se3_scntl3 = 7 73 ABSOLUTE se_saved_pointer = 8 74 ; 75 ; Initialization value for longword at offset 4 76 ; 77 ABSOLUTE INIT_SCSI_TABLE_SCNTL3 = 0x55 78 ABSOLUTE INIT_SCSI_TABLE_SXFER = 0x00 79 ABSOLUTE INIT_SCSI_TABLE_4 = SE_STATE_IDLE | (INIT_SCSI_TABLE_SXFER << 8) | (INIT_SCSI_TABLE_SCNTL3 << 24) 80 ; 81 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 82 ; 83 ; Request packet definitions. There is one per outstanding I/O request. These 84 ; are stored in the host CPU's general memory. 85 ; 86 ; rp_this_va[32]: host's virtual address of this packet 87 ; rp_next_pa[32]: pointer to next request in queue 88 ; (0 if end of queue, else address with low bit set) 89 ; rp_datamov_pa[32]: pointer to data transfer CHMOV's 90 ; low bit set means there either aren't any 91 ; ... or they have all been executed 92 ; rp0_flags[8]: flag bits: 93 ; <0> : 0=have already done identify message 94 ; 1=have yet to do identify message (this is the initial state) 95 ; <1> : 0=don't do width negotiation 96 ; 1=do width negotiation 97 ; <2> : 0=don't do synchronous negotiation 98 ; 1=do sync negotiation 99 ; <3> : 0=disconnect not allowed 100 ; 1=disconnect allowed 101 ; <4> : 0=haven't received status yet 102 ; 1=status byte has been received 103 ; <5> : 0=request still pending 104 ; 1=request completed 105 ; rp1_abort[8]: 0=host wants request executed as is 106 ; else=host wants request aborted asap (set RP_FLAG_DONE and unhook abort complete) 107 ; rp2_status[8]: final scsi status byte 108 ; rp3_cmdlen[8]: number of bytes in command (1..??) 109 ; rp_command[??]: command bytes 110 ; 111 ABSOLUTE rp_this_va = 0 112 ABSOLUTE rp_next_pa = 4 113 ABSOLUTE rp_datamov_pa = 8 114 ABSOLUTE rp0_flags = 12 115 ABSOLUTE RP_FLAG_NEEDTOIDENT = 0x01 116 ABSOLUTE RP_FLAG_NEGWIDTH = 0x02 117 ABSOLUTE RP_FLAG_NEGSYNCH = 0x04 118 ABSOLUTE RP_FLAG_GOTSTATUS = 0x08 119 ABSOLUTE RP_FLAG_DONE = 0x10 120 ABSOLUTE rp1_abort = 13 121 ABSOLUTE rp2_status = 14 122 ABSOLUTE rp3_cmdlen = 15 123 ABSOLUTE rp_command = 16 124 ; 125 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 126 ; 127 ; Scratch registers 128 ; 129 ; next_scsi_index = SCRATCHJ3 ; next scsi index to be processed 130 ; scsi_index = SCRATCHJ2 ; scsi index being processed 131 ; doing_data_xfer = SCRATCHJ1 ; used to inform host CPU when we expect that an exception might occur 132 ; request_packet = SCRATCHI ; base address of request being processed 133 ; request_packetv = SCRATCHH ; host virt address of request being processed 134 ; (only valid when SCRATCHJ1 = 1) 135 ; scsi_id_entry = SCRATCHG ; scsi_id_table entry 136 ; 137 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 138 ; 139 ; Flags that go in SCRATCHJ1. The host cpu driver uses these values when it 140 ; gets an interrupt to see if it should do anything special to process it. 141 ; 142 ABSOLUTE SCRATCHJ1_CHMOVS = 1 143 ABSOLUTE SCRATCHJ1_SELECT = 2 144 ; 145 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 146 ; 147 ; Internal memory 148 ; 149 ; - this should be first as it must be on a 256-byte boundary 150 ; 151 00000000: 00000000 55000000 scsi_id_table: CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT ; table of 256 bytes 152 00000008: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 153 00000010: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 154 00000018: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 155 00000020: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 156 00000028: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 157 00000030: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 158 00000038: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 159 00000040: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 160 00000048: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 161 00000050: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 162 00000058: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 163 00000060: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 164 00000068: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 165 00000070: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 166 00000078: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 167 00000080: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 168 00000088: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 169 00000090: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 170 00000098: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 171 000000A0: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 172 000000A8: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 173 000000B0: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 174 000000B8: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 175 000000C0: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 176 000000C8: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 177 000000D0: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 178 000000D8: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 179 000000E0: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 180 000000E8: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 181 000000F0: 00000000 55000000 CHMOV 0, INIT_SCSI_TABLE_4, WHEN DATA_OUT 182 000000F8: 00000000 00000000 CHMOV 0, 0, WHEN DATA_OUT 183 ; 184 00000100: 00000000 00000000 scsi_id_ptr: CHMOV 0, scsi_id_table, WHEN DATA_OUT ; point to scsi_id_table 185 ; 186 00000108: 00000000 00000000 msg_buf: CHMOV 0, 0, WHEN DATA_OUT ; 8-byte temp message-in or -out buffer 187 ; 188 ; Predefined messages 189 ; 190 00000110: 00000006 00000000 abort_task: CHMOV 0x06, 0, WHEN DATA_OUT ; ABORT TASK (0x06) 191 00000118: 00000007 00000000 message_reject: CHMOV 0x07, 0, WHEN DATA_OUT ; MESSAGE REJECT (0x07) 192 00000120: 00000008 00000000 noop_message: CHMOV 0x08, 0, WHEN DATA_OUT ; NO-OP (0x08) 193 194 00000128: 030201C0 00000001 message_ident_width: CHMOV 0x0201C0, 1, WHEN STATUS 195 ; IDENTIFY AND ALLOW DISCONNECT (0xC0), 196 ; NEGOTIATE WIDE DATA TRANSFER (0x01,0x02,0x03,1) 197 198 00000130: 010301C0 0000100C message_ident_synch: CHMOV 0x0301C0, XFER_PERIOD_FACT+(REQ_ACK_OFFSET<<8), WHEN DATA_IN 199 ; IDENTIFY AND ALLOW DISCONNECT (0xC0), 200 ; NEGOTIATE SYNCHRONOUS TRANSFER (0x01,0x03,0x01,XFER_PERIOD_FACT,REQ_ACK_OFFSET) 201 ; 202 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 203 ; 204 ; This is the initial start entrypoint 205 ; 206 00000138: startup: 207 00000138: 787D0000 00000000 MOVE 0 TO SCRATCHJ1 ; we are not doing anything special 208 ; - so if host gets an interrupt (other than INTFLY), 209 ; it should consider it a fatal error 210 00000140: 787F0000 00000000 MOVE 0 TO SCRATCHJ3 ; start looking at device 0 211 00000148: E1700004 00000104 LOAD SCRATCHG0, 4, scsi_id_ptr+4 ; set scsi_id_table entry pointer 212 ; 213 ; See if there is any new request to start 214 ; 215 ; New requests will have the low bit set in scsi_id_table[scsi_id].queue_head 216 ; When the queue is empty, scsi_id_table[scsi_id].queue_head will be zero 217 ; When the request is in progress, scsi_id_table[scsi_id].queue_head will be non-zero but will have low bit clear 218 ; 219 00000150: select_timedout: 220 00000150: mainloop: 221 00000150: 7C14DF00 00000000 MOVE ISTAT & 0xDF TO ISTAT ; about to scan loop, so clear SIGP flag bit 222 ; if host queues something while we're scanning, 223 ; ... it will set this bit again and we won't 224 ; ... hang in the WAIT RESELECT instruction 225 00000158: 7834F000 00000000 MOVE 0xF0 TO SCRATCHA0 ; max of 16 devices to scan 226 00000160: new_req_scanloop: 227 00000160: 727F0000 00000000 MOVE SCRATCHJ3 TO SFBR ; get which device to scan for 228 00000168: 6A7E0000 00000000 MOVE SFBR TO SCRATCHJ2 229 00000170: 7E7F0100 00000000 MOVE SCRATCHJ3 + 1 TO SCRATCHJ3 ; set up id of next device to check 230 00000178: 7C7F0F00 00000000 MOVE SCRATCHJ3 & 15 TO SCRATCHJ3 231 00000180: 88880000 00000760 CALL REL (get_request_packet) ; point to request packet 232 00000188: 72780000 00000000 MOVE SCRATCHI0 TO SFBR ; test low bit of request_packet 233 00000190: 808CFE01 000000B8 JUMP REL (got_new_req), IF 1 AND MASK 0xFE ; break out if we got something new 234 00000198: 7E340100 00000000 MOVE SCRATCHA0 + 1 TO SCRATCHA0 ; nothing new there, try next device 235 000001A0: 80A00000 FFFFFFB8 JUMP REL (new_req_scanloop), IF NOT CARRY 236 ; 237 ; Check for some target trying to reselect 238 ; Presumably, it is ready for data or status transfer 239 ; 240 000001A8: check_reselect: 241 000001A8: 787D0000 00000000 MOVE 0 TO SCRATCHJ1 ; we are no longer doing the SELECT instruction 242 000001B0: 54000000 00000070 WAIT RESELECT REL (not_reselect) ; wait for reselection 243 ; - this will jump to 'not_reselect' if either ISTAT is set 244 ; (meaning there are new requests to process) or some dumbell is 245 ; trying to select me 246 ; 247 ; Something is trying to re-select, resume processing the target 248 ; 249 000001B8: 720A0000 00000000 MOVE SSID TO SFBR ; see who is calling us 250 000001C0: 808C7F00 00000040 JUMP REL (bad_reselect_scsi_id), IF 0 AND MASK 0x7F ; bad if the 'valid' bit is not set 251 000001C8: 6C7E0F00 00000000 MOVE SFBR & 0x0F TO SCRATCHJ2 ; save the scsi id in the scsi_index scratch register 252 253 000001D0: 88880000 00000710 CALL REL (get_request_packet) ; set request_packet = first queue entry for the scsi_index 254 255 000001D8: 72780000 00000000 MOVE SCRATCHI0 TO SFBR ; queue entry not active if low bit is set 256 000001E0: 808CFE01 00000020 JUMP REL (bad_reselect_scsi_id), IF 1 AND MASK 0xFE 257 258 000001E8: 72F90000 00000000 MOVE SCRATCHI1 | SFBR TO SFBR ; queue entry zero means not active also 259 000001F0: 72FA0000 00000000 MOVE SCRATCHI2 | SFBR TO SFBR 260 000001F8: 72FB0000 00000000 MOVE SCRATCHI3 | SFBR TO SFBR 261 00000200: 80840000 000000C0 JUMP REL (check_target_state), IF NOT 0 ; go see what target wants 262 263 00000208: bad_reselect_scsi_id: 264 00000208: 88880000 000007F0 CALL REL (set_atn) ; tell target we have something to tell it 265 00000210: 0E000001 00000110 MOVE 1, abort_task, WHEN MSG_OUT ; reselect from unknown source, tell it to abort what it is trying to do 266 00000218: 48000000 00000000 WAIT DISCONNECT ; wait for target to disconnect from scsi bus 267 00000220: 80880000 FFFFFF28 JUMP REL (mainloop) ; go find something else to do 268 ; 269 ; Not being reselected, maybe some idiot is trying to select me 270 ; 271 00000228: not_reselect: 272 00000228: 54000000 FFFFFF20 WAIT SELECT REL (mainloop) ; see if someone is trying to select me 273 ; - this will jump to 'mainloop' if either ISTAT is set 274 ; (meaning there are new requests to process) or some target 275 ; is trying to reselect me 276 00000230: 06000001 00000110 MOVE 1, abort_task, WITH MSG_OUT 277 00000238: 48000000 00000000 DISCONNECT 278 00000240: 60000200 00000000 CLEAR TARGET 279 00000248: 80880000 FFFFFF00 JUMP REL (mainloop) 280 ; 281 ; New request found, decrement the base address to eliminate the low bit being set 282 ; then try to select the device. If another target tries to reselect us in the 283 ; mean time, forget about this for now and go process it 284 ; 285 ; Registers: 286 ; 287 ; SCRATCHJ2 (scsi_index) = scsi-id of device that has a new request 288 ; DSA = points to scsi_id_table entry for the device 289 ; SCRATCHI (request_packet) = points to the request packet (but it has its low bit set) 290 ; 291 00000250: got_new_req: 292 00000250: 7C78FE00 00000000 MOVE SCRATCHI0 & 0xFE TO SCRATCHI0 ; clear low flag bit 293 00000258: 88880000 00000758 CALL REL (request_packet_to_dsa) ; see if host CPU wants this request aborted 294 00000260: F1350001 0000000D LOAD SCRATCHA1, 1, DSAREL (rp1_abort) 295 00000268: 72350000 00000000 MOVE SCRATCHA1 TO SFBR 296 00000270: 80840000 000005B0 JUMP REL (req_complete2), IF NOT 0 ; if so, go post it as completed 297 00000278: 88880000 000006F0 CALL REL (scsi_id_entry_to_dsa) ; set the state to 'SELECTING' 298 00000280: 78080600 00000000 MOVE SE_STATE_SELECTING TO SFBR 299 00000288: F2080001 00000004 STORE NOFLUSH SFBR, 1, DSAREL (se0_state) 300 00000290: 787D0200 00000000 MOVE SCRATCHJ1_SELECT TO SCRATCHJ1 ; tell host CPU we are about to to the SELECT instruction 301 00000298: E07E0001 000002A2 STORE SCRATCHJ2, 1, select_instr+2 ; store scsi_id in select instruction 302 ; - this is the one instance where we DO need it to flush! 303 000002A0: select_instr: 304 000002A0: 45000000 FFFFFF00 SELECT ATN 0, REL (check_reselect) ; (this instr is modified with the scsi_id register contents) 305 ; a jump is made to 'check_reselect' if someone is trying to (re)select 306 ; - note that SIGP is probably still clear so the WAIT instructions should 307 ; do their job. If SIGP was set by the host in the mean time, this idiot 308 ; computer skips the WAIT instructions and thus we should end up right 309 ; back here very quickly only to do it all over again (but hopefully with 310 ; SIGP cleared) 311 ; if this times out, host CPU will jump to 'select_timedout' 312 ; - the host aborts all requests from the queue first, however 313 ; - the jump goes back to clear SIGP and re-scan for more requests to start 314 000002A8: 787D0000 00000000 MOVE 0 TO SCRATCHJ1 ; we are no longer doing the SELECT instruction 315 ; 316 ; We have selected the target, mark the queue entry as being 'in progress' 317 ; Also, clear the low bit in queue_head entry so we won't think we need to select again 318 ; 319 000002B0: 78080500 00000000 MOVE SE_STATE_SELECTED TO SFBR ; set the state to 'SELECTED' 320 000002B8: F2080001 00000004 STORE NOFLUSH SFBR, 1, DSAREL (se0_state) 321 000002C0: F2780001 00000000 STORE NOFLUSH SCRATCHI0, 1, DSAREL (se_queue_head) ; store the request_packet without the low bit 322 ; 323 ; Now see what target wants to do 324 ; 325 ; Registers: 326 ; 327 ; SCRATCHJ2 (scsi_index) = the scsi-id of the device we are processing 328 ; SCRATCHG (scsi_id_entry) = points to entry in the scsi_id_table that we are processing 329 ; SCRATCHI (request_packet) = points to the request packet for the device 330 ; 331 000002C8: check_target_state: 332 000002C8: 88880000 000006A0 CALL REL (scsi_id_entry_to_dsa) ; set state to 'checking target' 333 000002D0: 78080400 00000000 MOVE SE_STATE_CHECKING_TARGET TO SFBR 334 000002D8: F2080001 00000004 STORE NOFLUSH SFBR, 1, DSAREL (se0_state) 335 000002E0: 868B0000 00000030 JUMP REL (transfer_message_out), WHEN MSG_OUT ; now see what target wants to do 336 000002E8: 828A0000 00000228 JUMP REL (transfer_command), IF CMD 337 000002F0: 818A0000 00000288 JUMP REL (transfer_data_in), IF DATA_IN 338 000002F8: 808A0000 00000280 JUMP REL (transfer_data_out), IF DATA_OUT 339 00000300: 838A0000 00000308 JUMP REL (transfer_status), IF STATUS 340 00000308: 878A0000 00000350 JUMP REL (transfer_message_in), IF MSG_IN 341 00000310: 98080000 000000A1 INT 0xA1 ; ?? don't know what to do - target must have disconnected ?? 342 ; 343 ; Target is ready to accept a message from us 344 ; We generally have three messages to send it (in this order): 345 ; 1) Identify (always) 346 ; 2) Negotiate width (optional) 347 ; 3) Negotiate speed (optional) 348 ; 349 00000318: transfer_message_out: 350 00000318: 78080300 00000000 MOVE SE_STATE_MESSAGE_OUT TO SFBR 351 00000320: F2080001 00000004 STORE NOFLUSH SFBR, 1, DSAREL (se0_state) 352 353 00000328: 88880000 00000688 CALL REL (request_packet_to_dsa) ; see what we have yet to send 354 00000330: F1340001 0000000C LOAD SCRATCHA0, 1, DSAREL (rp0_flags) 355 00000338: 72340000 00000000 MOVE SCRATCHA0 TO SFBR 356 00000340: 808CF801 00000030 JUMP REL (send_message_ident), IF RP_FLAG_NEEDTOIDENT AND MASK 0xFF - (RP_FLAG_NEGSYNCH | RP_FLAG_NEGWIDTH | RP_FLAG_NEEDTOIDENT) 357 00000348: 808CFC02 00000068 JUMP REL (send_message_width), IF RP_FLAG_NEGWIDTH AND MASK 0xFF - ( RP_FLAG_NEGWIDTH | RP_FLAG_NEEDTOIDENT) 358 00000350: 808CFC03 00000040 JUMP REL (send_message_ident_width), IF RP_FLAG_NEGWIDTH | RP_FLAG_NEEDTOIDENT AND MASK 0xFF - ( RP_FLAG_NEGWIDTH | RP_FLAG_NEEDTOIDENT) 359 00000358: 808CF804 00000120 JUMP REL (send_message_synch), IF RP_FLAG_NEGSYNCH AND MASK 0xFF - (RP_FLAG_NEGSYNCH | RP_FLAG_NEGWIDTH | RP_FLAG_NEEDTOIDENT) 360 00000360: 808CF805 000000F8 JUMP REL (send_message_ident_synch), IF RP_FLAG_NEGSYNCH | RP_FLAG_NEEDTOIDENT AND MASK 0xFF - (RP_FLAG_NEGSYNCH | RP_FLAG_NEGWIDTH | RP_FLAG_NEEDTOIDENT) 361 362 00000368: 0E000001 00000120 MOVE 1, noop_message, WHEN MSG_OUT ; we have nothing to send, so send a noop (this also clears the ATN bit) 363 00000370: 80880000 FFFFFF50 JUMP REL (check_target_state) 364 365 00000378: send_message_ident: 366 00000378: 6C08FE00 00000000 MOVE SFBR & 0xFF - RP_FLAG_NEEDTOIDENT TO SFBR ; clear flag bit 367 00000380: F0080001 0000000C STORE SFBR, 1, DSAREL (rp0_flags) 368 00000388: 0E000001 00000128 MOVE 1, message_ident_width, WHEN MSG_OUT ; send ident message (this also clears the ATN bit) 369 00000390: 80880000 FFFFFF30 JUMP REL (check_target_state) 370 371 00000398: send_message_ident_width: 372 00000398: 6C08FC00 00000000 MOVE SFBR & 0xFF - (RP_FLAG_NEEDTOIDENT | RP_FLAG_NEGWIDTH) TO SFBR ; clear flag bits 373 000003A0: F0080001 0000000C STORE SFBR, 1, DSAREL (rp0_flags) 374 000003A8: 0E000005 00000128 MOVE 5, message_ident_width, WHEN MSG_OUT ; send ident and width messages (this also clears the ATN bit) 375 000003B0: 80880000 00000018 JUMP REL (proc_width_reply) 376 377 000003B8: send_message_width: 378 000003B8: 6C08FD00 00000000 MOVE SFBR & 0xFF - RP_FLAG_NEGWIDTH TO SFBR ; clear flag bit 379 000003C0: F0080001 0000000C STORE SFBR, 1, DSAREL (rp0_flags) 380 000003C8: 0E000004 00000129 MOVE 4, message_ident_width+1, WHEN MSG_OUT ; send width message (this also clears the ATN bit) 381 382 proc_width_reply: 383 000003D0: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN ; read the reply, byte-by-byte 384 000003D8: 80840001 000004B8 JUMP REL (bad_nego_mess), IF NOT 0x01 ; - it must be an extended message 385 000003E0: 60000040 00000000 CLEAR ACK 386 000003E8: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN 387 000003F0: 80840002 000004A8 JUMP REL (bad_nego_mess_reject), IF NOT 0x02 ; - it must have length 2 388 000003F8: 60000040 00000000 CLEAR ACK 389 00000400: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN 390 00000408: 80840003 00000490 JUMP REL (bad_nego_mess_reject), IF NOT 0x03 ; - it must be a 'wide data transfer' message 391 00000410: 60000040 00000000 CLEAR ACK 392 00000418: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN ; ok, get the resultant width (either 8 or 16 bits) 393 00000420: 88880000 00000690 CALL REL (save_transfer_width) ; save it in memory 394 00000428: 88880000 00000588 CALL REL (request_packet_to_dsa) ; see if we have to send synchronous negotiation message, too 395 00000430: F1340001 0000000C LOAD SCRATCHA0, 1, DSAREL (rp0_flags) 396 00000438: 72340000 00000000 MOVE SCRATCHA0 TO SFBR 397 00000440: 808CFB00 00000008 JUMP REL (proc_width_reply_clear_ack), IF 0 AND MASK 0xFF - RP_FLAG_NEGSYNCH 398 00000448: 58000008 00000000 SET ATN ; need to do synch negotiation, tell target we have another message 399 proc_width_reply_clear_ack: 400 00000450: 60000040 00000000 CLEAR ACK ; anyway, clear ack to indicate we got all the incoming message 401 00000458: 80880000 FFFFFE68 JUMP REL (check_target_state) ; and check to see what target wants now 402 403 00000460: send_message_ident_synch: 404 00000460: 6C08FA00 00000000 MOVE SFBR & 0xFF - (RP_FLAG_NEEDTOIDENT | RP_FLAG_NEGSYNCH) TO SFBR ; clear flag bits 405 00000468: F0080001 0000000C STORE SFBR, 1, DSAREL (rp0_flags) 406 00000470: 0E000006 00000130 MOVE 6, message_ident_synch, WHEN MSG_OUT ; send ident and synch messages (this also clears the ATN bit) 407 00000478: 80880000 00000018 JUMP REL (proc_synch_reply) 408 409 00000480: send_message_synch: 410 00000480: 6C08FB00 00000000 MOVE SFBR & 0xFF - RP_FLAG_NEGSYNCH TO SFBR ; clear flag bit 411 00000488: F0080001 0000000C STORE SFBR, 1, DSAREL (rp0_flags) 412 00000490: 0E000005 00000131 MOVE 5, message_ident_synch+1, WHEN MSG_OUT ; send synch message (this also clears the ATN bit) 413 414 proc_synch_reply: 415 00000498: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN ; read the reply, byte-by-byte 416 000004A0: 80840001 000003F0 JUMP REL (bad_nego_mess), IF NOT 0x01 ; - it must be an extended message 417 000004A8: 60000040 00000000 CLEAR ACK 418 000004B0: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN 419 000004B8: 80840003 000003E0 JUMP REL (bad_nego_mess_reject), IF NOT 0x03 ; - it must have length 3 420 000004C0: 60000040 00000000 CLEAR ACK 421 000004C8: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN 422 000004D0: 80840001 000003C8 JUMP REL (bad_nego_mess_reject), IF NOT 0x01 ; - it must be a 'synchronous data transfer' message 423 000004D8: 60000040 00000000 CLEAR ACK 424 000004E0: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN ; ok, get the resultant tranfer period factor 425 000004E8: 88880000 000005F8 CALL REL (save_transfer_period) ; save it in memory 426 000004F0: 60000040 00000000 CLEAR ACK 427 000004F8: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN ; get the resultant req/ack offset 428 00000500: 88880000 00000658 CALL REL (save_req_ack_offset) ; save it in memory 429 00000508: 60000040 00000000 CLEAR ACK ; clear ack to indicate we got all the incoming message 430 00000510: 80880000 FFFFFDB0 JUMP REL (check_target_state) 431 432 ; 433 ; Target is ready to accept the command from us 434 ; 435 00000518: transfer_command: 436 00000518: 78080700 00000000 MOVE SE_STATE_SENDING_COMMAND TO SFBR ; set state 'sending command' 437 00000520: F2080001 00000004 STORE NOFLUSH SFBR, 1, DSAREL (se0_state) 438 00000528: 88880000 00000488 CALL REL (request_packet_to_dsa) ; point to the request packet 439 00000530: F1370001 0000000F LOAD SCRATCHA3, 1, DSAREL (rp3_cmdlen) ; get length of command 440 00000538: 72370000 00000000 MOVE SCRATCHA3 TO SFBR 441 00000540: E2080001 00000570 STORE NOFLUSH SFBR, 1, command_move+0 ; store in the 'command_move' instruction 442 00000548: 7E101000 00000000 MOVE DSA0 + rp_command TO DSA0 ; point to the command bytes 443 00000550: 7F110000 00000000 MOVE DSA1 + 0 TO DSA1 WITH CARRY 444 00000558: 7F120000 00000000 MOVE DSA2 + 0 TO DSA2 WITH CARRY 445 00000560: 7F130000 00000000 MOVE DSA3 + 0 TO DSA3 WITH CARRY 446 00000568: E0100004 00000574 STORE DSA0, 4, command_move+4 447 00000570: command_move: 448 00000570: 0A000000 00000000 MOVE 0, 0, WHEN CMD ; transfer the command bytes to the target 449 00000578: 80880000 FFFFFD48 JUMP REL (check_target_state) ; now see what target wants to do 450 ; 451 ; Target is ready to transfer data 452 ; 453 00000580: transfer_data_in: 454 00000580: transfer_data_out: 455 00000580: 78080800 00000000 MOVE SE_STATE_TRANSFERRING_DATA TO SFBR ; set state 'transferring data' 456 00000588: F2080001 00000004 STORE NOFLUSH SFBR, 1, DSAREL (se0_state) 457 00000590: F1030001 00000007 LOAD SCNTL3, 1, DSAREL (se3_scntl3) ; set up transfer speed and width 458 00000598: F1050001 00000005 LOAD SXFER, 1, DSAREL (se1_sxfer) 459 000005A0: 88880000 00000410 CALL REL (request_packet_to_dsa) ; point to the request packet 460 000005A8: F11C0004 00000008 LOAD TEMP0, 4, DSAREL (rp_datamov_pa) ; get where the CHMOV's are 461 000005B0: 721C0000 00000000 MOVE TEMP0 TO SFBR ; low bit says we're all done moving data 462 000005B8: 808CFE01 00000038 JUMP REL (transfer_no_data), IF 0x01 AND MASK 0xFE 463 000005C0: F1740004 00000000 LOAD SCRATCHH0, 4, DSAREL (rp_this_va) ; get virt address of request packet 464 000005C8: 787D0100 00000000 MOVE SCRATCHJ1_CHMOVS TO SCRATCHJ1 ; set the 'CHMOV in progress' flag 465 000005D0: 90080000 00000000 RETURN ; execute the CHMOV's (jumps to address in TEMP) 466 ; code with jump to 'transfer_data_done' if it gets to the end ok 467 ; otherwise, if a phase mismatch occurrs, the host cpu will modify 468 ; the 'rp_datamov_pa' pointer accordingly then jump to 469 ; 'transfer_data_mismatch' 470 ; 471 000005D8: transfer_data_done: 472 000005D8: 78080100 00000000 MOVE 1 TO SFBR ; data has all transferred, mark it done 473 000005E0: F2080001 00000008 STORE NOFLUSH SFBR, 1, DSAREL (rp_datamov_pa) ; - by storing a value with the low bit set 474 000005E8: transfer_data_mismatch: 475 000005E8: 787D0000 00000000 MOVE 0 TO SCRATCHJ1 ; clear the 'CHMOV in progress' flag 476 000005F0: 80880000 FFFFFCD0 JUMP REL (check_target_state) ; go see what target wants now 477 ; 478 000005F8: transfer_no_data: 479 000005F8: 88880000 00000400 CALL REL (set_atn) ; target wants more data but there isn't any 480 00000600: 0E000001 00000110 MOVE 1, abort_task, WHEN MSG_OUT ; - sent it a nasty message 481 00000608: 80880000 FFFFFCB8 JUMP REL (check_target_state) ; - then hopefully it will disconnect 482 ; 483 ; Target has status byte ready for us 484 ; 485 00000610: transfer_status: 486 00000610: 78080200 00000000 MOVE SE_STATE_GETTING_STATUS TO SFBR ; set state 'getting status' 487 00000618: F2080001 00000004 STORE NOFLUSH SFBR, 1, DSAREL (se0_state) 488 00000620: 0B000001 00000108 MOVE 1, msg_buf, WHEN STATUS ; read the status byte 489 00000628: 88880000 00000388 CALL REL (request_packet_to_dsa) ; store in request packet struct 490 00000630: 6A360000 00000000 MOVE SFBR TO SCRATCHA2 491 00000638: F2360001 0000000E STORE NOFLUSH SCRATCHA2, 1, DSAREL (rp2_status) 492 00000640: F11C0001 0000000C LOAD TEMP0, 1, DSAREL (rp0_flags) ; ... and say that we got it 493 00000648: 7A1C0800 00000000 MOVE TEMP0 | RP_FLAG_GOTSTATUS TO TEMP0 494 00000650: F01C0001 0000000C STORE TEMP0, 1, DSAREL (rp0_flags) 495 00000658: 80880000 FFFFFC68 JUMP REL (check_target_state) 496 ; 497 ; Target has an unsolicited message for us 498 ; 499 00000660: transfer_message_in: 500 00000660: 78080100 00000000 MOVE SE_STATE_GETTING_MESSAGE TO SFBR ; set state 'getting message' 501 00000668: F2080001 00000004 STORE NOFLUSH SFBR, 1, DSAREL (se0_state) 502 00000670: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN ; see what the target wants 503 00000678: 808C0000 00000198 JUMP REL (req_complete), IF 0x00 ; 00 means the request is now complete 504 00000680: 808C0001 00000048 JUMP REL (got_extended_message), IF 0x01 ; check for 'extended' messages 505 ;; JUMP REL (save_data_pointer), IF 0x02 ; 02 means to save data transfer pointer 506 ;; JUMP REL (restore_pointers), IF 0x03 ; 03 means to restore transfer pointers 507 00000688: 808C0004 00000160 JUMP REL (disconnecting), IF 0x04 ; 04 means it is disconnecting and will reselect us later 508 00000690: 808C0007 00000028 JUMP REL (ignore_message), IF 0x07 ; skip over reject's 509 00000698: 808C0008 00000020 JUMP REL (ignore_message), IF 0x08 ; skip over nop's 510 000006A0: 808C7F80 00000018 JUMP REL (ignore_message), IF 0x80 AND MASK 0x7F ; ignore all identify messages from target 511 512 000006A8: reject_message: 513 000006A8: 88880000 00000350 CALL REL (set_atn) ; tell target we are rejecting its message 514 000006B0: 0E000001 00000118 MOVE 1, message_reject, WHEN MSG_OUT ; send reject message, clear ATN 515 000006B8: 80880000 FFFFFC08 JUMP REL (check_target_state) 516 517 000006C0: ignore_message: 518 000006C0: 60000040 00000000 CLEAR ACK ; acknowledge it 519 000006C8: 80880000 FFFFFBF8 JUMP REL (check_target_state) ; go see what target wants now 520 521 ;;save_data_pointer: 522 ;; CLEAR ACK ; acknowledge it 523 ;; CALL REL (request_packet_to_dsa) ; get current pointer 524 ;; LOAD SCRATCHA0, 4, DSAREL (rp_data_offset) 525 ;; CALL scsi_id_entry_to_dsa ; store in saved pointer 526 ;; STORE NOFLUSH SCRATCHA0, 4, DSAREL (se_saved_pointer) 527 ;; JUMP REL (check_target_state) 528 529 ;;restore_pointers: 530 ;; CLEAR ACK ; acknowledge it 531 ;; LOAD SCRATCHA0, 4, DSAREL (se_saved_pointer) ; get saved pointer 532 ;; CALL REL (request_packet_to_dsa) ; store in current pointer 533 ;; STORE NOFLUSH SCRATCHA0, 4, DSAREL (rp_data_offset) 534 ;; JUMP REL (check_target_state) 535 536 000006D0: got_extended_message: 537 000006D0: 60000040 00000000 CLEAR ACK 538 000006D8: 0F000002 00000108 MOVE 2, msg_buf, WHEN MSG_IN ; get extended message length and code 539 000006E0: E1340002 00000108 LOAD SCRATCHA0, 2, msg_buf ; get length in A0, code in A1 540 000006E8: 72350000 00000000 MOVE SCRATCHA1 TO SFBR ; check out the code 541 000006F0: 808C0001 0000007C JUMP REL (got_sync_data_xfer_msg), IF 0x01 542 000006F8: 808C0003 00000008 JUMP REL (got_wide_data_xfer_msg), IF 0x03 543 00000700: 80880000 FFFFFFA0 JUMP REL (reject_message) 544 545 00000708: got_wide_data_xfer_msg: 546 00000708: 72340000 00000000 MOVE SCRATCHA0 TO SFBR ; make sure the length is 2 547 00000710: 80840002 00000188 JUMP REL (bad_nego_mess_reject), IF NOT 0x02 548 00000718: 60000040 00000000 CLEAR ACK 549 00000720: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN ; get the requested width factor 550 00000728: 60000040 00000000 CLEAR ACK ; tell target we got the last byte of message 551 00000730: C1000008 00000128 00000108 MOVE MEMORY NOFLUSH 8, message_ident_width, msg_buf ; copy a template message 552 0000073C: 808C0000 00000008 JUMP REL (width_ok), IF 0 ; width 0 (8-bits) is ok as is 553 00000744: 78080100 00000000 MOVE 1 TO SFBR ; if else, do width 1 (16-bits) 554 0000074C: width_ok: 555 0000074C: E2080001 0000010C STORE NOFLUSH SFBR, 1, msg_buf+4 ; save it in outgoing message buffer 556 00000754: 88880000 00000214 CALL REL (scsi_id_entry_to_dsa) ; save negotiated width in scsi_id_table entry 557 0000075C: 88880000 00000354 CALL REL (save_transfer_width) 558 00000764: 0E000004 00000109 MOVE 4, msg_buf+1, WHEN MSG_OUT ; send reply message 559 0000076C: 80880000 FFFFFB54 JUMP REL (check_target_state) ; now go see what target wants 560 561 00000774: got_sync_data_xfer_msg: 562 00000774: 72340000 00000000 MOVE SCRATCHA0 to SFBR ; make sure the length is 3 563 0000077C: 80840003 0000011C JUMP REL (bad_nego_mess_reject), IF NOT 0x03 564 00000784: 60000040 00000000 CLEAR ACK 565 0000078C: 0F000002 00000108 MOVE 2, msg_buf, WHEN MSG_IN ; get the transfer period factor and req/ack offset bytes 566 00000794: 60000040 00000000 CLEAR ACK ; tell target we got the last bytes of message 567 0000079C: E1370001 00000109 LOAD SCRATCHA3, 1, msg_buf+1 ; save req/ack offset factor 568 000007A4: C1000005 00000131 00000109 MOVE MEMORY NOFLUSH 5, message_ident_synch+1, msg_buf+1 ; set up a template message 569 000007B0: 88880000 000001B8 CALL REL (scsi_id_entry_to_dsa) 570 000007B8: 88880000 00000328 CALL REL (save_transfer_period) ; process negotiated speed setting 571 000007C0: E2360001 0000010C STORE NOFLUSH SCRATCHA2, 1, msg_buf+4 ; save it in reply message buffer 572 000007C8: 72370000 00000000 MOVE SCRATCHA3 TO SFBR ; get requested req/ack offset 573 000007D0: 88880000 00000388 CALL REL (save_req_ack_offset) ; process it 574 000007D8: E2360001 0000010D STORE NOFLUSH SCRATCHA2, 1, msg_buf+5 ; save negotiated value in reply message 575 000007E0: 0E000005 00000109 MOVE 5, msg_buf+1, WHEN MSG_OUT ; send reply message 576 000007E8: 80880000 FFFFFAD8 JUMP REL (check_target_state) ; now go see what target wants 577 ; 578 ; Target is disconnecting, remember the state and go do something else in the mean time 579 ; 580 000007F0: disconnecting: 581 000007F0: 60000040 00000000 CLEAR ACK ; acknowledge it 582 000007F8: 78080900 00000000 MOVE SE_STATE_WAITING_FOR_RESELECT TO SFBR ; remember we're waiting for a reselect from it 583 00000800: F2080001 00000004 STORE NOFLUSH SFBR, 1, DSAREL (se0_state) 584 00000808: 48000000 00000000 WAIT DISCONNECT ; wait for target to disconnect from scsi bus 585 00000810: 80880000 FFFFF938 JUMP REL (mainloop) ; go find something else to do 586 ; 587 ; The request is complete 588 ; 589 00000818: req_complete: 590 00000818: 60000040 00000000 CLEAR ACK ; acknowledge it 591 00000820: 48000000 00000000 WAIT DISCONNECT ; wait for target to disconnect from scsi bus 592 00000828: req_complete2: 593 00000828: 78080000 00000000 MOVE SE_STATE_IDLE TO SFBR ; remember this device isn't doing anything now 594 00000830: F2080001 00000004 STORE NOFLUSH SFBR, 1, DSAREL (se0_state) 595 00000838: 88880000 00000178 CALL REL (request_packet_to_dsa) 596 00000840: 7A141000 00000000 MOVE ISTAT | 0x10 TO ISTAT ; set the SEM bit to let host know were modifying queue and RP_FLAG_DONE 597 00000848: F1340004 00000004 LOAD SCRATCHA0, 4, DSAREL (rp_next_pa) ; find the next item in the list (it is either zero or has the low bit set) 598 00000850: 88880000 00000118 CALL REL (scsi_id_entry_to_dsa) 599 00000858: F2340004 00000000 STORE NOFLUSH SCRATCHA0, 4, DSAREL (se_queue_head) ; unlink request from queue 600 00000860: 88880000 00000150 CALL REL (request_packet_to_dsa) 601 00000868: F1340001 0000000C LOAD SCRATCHA0, 1, DSAREL (rp0_flags) ; flag the request as 'done' 602 00000870: 7A341000 00000000 MOVE SCRATCHA0 | RP_FLAG_DONE TO SCRATCHA0 603 00000878: F0340001 0000000C STORE SCRATCHA0, 1, DSAREL (rp0_flags) 604 00000880: 7C14EF00 00000000 MOVE ISTAT & 0xEF TO ISTAT ; clear SEM bit to let host know were done with mods 605 00000888: 98180000 00000000 INTFLY ; tell the host computer that a request completed 606 00000890: 80880000 FFFFF8B8 JUMP REL (mainloop) ; go find something to do 607 ; 608 ; Something was bad about the negotiation reply, send reject then set up async mode 609 ; 610 00000898: bad_nego_mess: 611 00000898: 808C0007 00000010 JUMP REL (bad_nego_mess_async), IF 0x07 ; maybe it is rejecting my request 612 000008A0: bad_nego_mess_reject: 613 000008A0: 88880000 00000158 CALL REL (set_atn) ; something else bad with message, reject it 614 000008A8: 0E000001 00000118 MOVE 1, message_reject, WHEN MSG_OUT 615 000008B0: bad_nego_mess_async: 616 000008B0: 60000040 00000000 CLEAR ACK 617 000008B8: 88880000 000000B0 CALL REL (scsi_id_entry_to_dsa) 618 000008C0: 78375500 00000000 MOVE INIT_SCSI_TABLE_SCNTL3 TO SCRATCHA3 ; set up async transfer mode 619 000008C8: F2370001 00000007 STORE NOFLUSH SCRATCHA3, 1, DSAREL (se3_scntl3) 620 000008D0: 78350000 00000000 MOVE INIT_SCSI_TABLE_SXFER TO SCRATCHA1 621 000008D8: F2350001 00000005 STORE NOFLUSH SCRATCHA1, 1, DSAREL (se1_sxfer) 622 000008E0: 80880000 FFFFF9E0 JUMP REL (check_target_state) 623 ; 624 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 625 ; 626 ; Get pointer to first request packet queued to a scsi device 627 ; 628 ; Input: 629 ; 630 ; SCRATCHJ2 (scsi_index) = scsi id to get packet for 631 ; 632 ; Output: 633 ; 634 ; SCRATCHI (request_packet) = 0 : nothing is queued 635 ; odd : address of new packet queued + 1 636 ; even : address of previously queued packet 637 ; SCRATCHG (scsi_id_entry) = DSA = points to scsi_id_table entry 638 ; 639 000008E8: get_request_packet: 640 000008E8: 60000400 00000000 CLEAR CARRY 641 000008F0: 727E0000 00000000 MOVE SCRATCHJ2 TO SFBR ; multiply scsi_index by 16 to get offset in scsi_id_table 642 000008F8: 6A700000 00000000 MOVE SFBR TO SCRATCHG0 643 00000900: 79700000 00000000 MOVE SCRATCHG0 SHL SCRATCHG0 644 00000908: 79700000 00000000 MOVE SCRATCHG0 SHL SCRATCHG0 645 00000910: 79700000 00000000 MOVE SCRATCHG0 SHL SCRATCHG0 646 00000918: 79700000 00000000 MOVE SCRATCHG0 SHL SCRATCHG0 647 648 00000920: 72700000 00000000 MOVE SCRATCHG0 TO SFBR ; point the DSA at the scsi_id_table entry for the device 649 00000928: 6A100000 00000000 MOVE SFBR TO DSA0 650 00000930: 72710000 00000000 MOVE SCRATCHG1 TO SFBR 651 00000938: 6A110000 00000000 MOVE SFBR TO DSA1 652 00000940: 72720000 00000000 MOVE SCRATCHG2 TO SFBR 653 00000948: 6A120000 00000000 MOVE SFBR TO DSA2 654 00000950: 72730000 00000000 MOVE SCRATCHG3 TO SFBR 655 00000958: 6A130000 00000000 MOVE SFBR TO DSA3 656 657 00000960: F1780004 00000000 LOAD SCRATCHI0, 4, DSAREL (se_queue_head) ; load the scsi_id_table[scsi_index].queue_head entry into 'request_packet' 658 659 00000968: 90080000 00000000 RETURN 660 ; 661 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 662 ; 663 ; Copy the scsi_id_entry register to the DSA 664 ; 665 00000970: scsi_id_entry_to_dsa: 666 00000970: 72700000 00000000 MOVE SCRATCHG0 TO SFBR 667 00000978: 6A100000 00000000 MOVE SFBR TO DSA0 668 00000980: 72710000 00000000 MOVE SCRATCHG1 TO SFBR 669 00000988: 6A110000 00000000 MOVE SFBR TO DSA1 670 00000990: 72720000 00000000 MOVE SCRATCHG2 TO SFBR 671 00000998: 6A120000 00000000 MOVE SFBR TO DSA2 672 000009A0: 72730000 00000000 MOVE SCRATCHG3 TO SFBR 673 000009A8: 6A130000 00000000 MOVE SFBR TO DSA3 674 000009B0: 90080000 00000000 RETURN 675 ; 676 ; Copy the request_packet register to the DSA 677 ; 678 000009B8: request_packet_to_dsa: 679 000009B8: 72780000 00000000 MOVE SCRATCHI0 TO SFBR 680 000009C0: 6A100000 00000000 MOVE SFBR TO DSA0 681 000009C8: 72790000 00000000 MOVE SCRATCHI1 TO SFBR 682 000009D0: 6A110000 00000000 MOVE SFBR TO DSA1 683 000009D8: 727A0000 00000000 MOVE SCRATCHI2 TO SFBR 684 000009E0: 6A120000 00000000 MOVE SFBR TO DSA2 685 000009E8: 727B0000 00000000 MOVE SCRATCHI3 TO SFBR 686 000009F0: 6A130000 00000000 MOVE SFBR TO DSA3 687 000009F8: 90080000 00000000 RETURN 688 ; 689 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 690 ; 691 ; Set ATN and wait for target to enter MSG_OUT phase 692 ; 693 ; Output: 694 ; 695 ; target now in MSG_OUT phase 696 ; 697 ; Scratch: 698 ; 699 ; SFBR, msg_buf[0] 700 ; 701 00000A00: set_atn: 702 00000A00: 58000008 00000000 SET ATN ; tell target we have something to say 703 00000A08: set_atn_clrack: 704 00000A08: 60000040 00000000 CLEAR ACK ; in case last thing was a MSG_IN 705 00000A10: set_atn_loop: 706 00000A10: 960B0000 00000000 RETURN, WHEN MSG_OUT ; if target is in MSG_OUT, return to caller 707 00000A18: 818B0000 00000028 JUMP REL (set_atn_data_in), WHEN DATA_IN ; if target is in DATA_IN, read (& ignore) a byte 708 00000A20: 808B0000 00000030 JUMP REL (set_atn_data_out), WHEN DATA_OUT ; if target is in DATA_OUT, send it a null byte 709 00000A28: 878B0000 00000048 JUMP REL (set_atn_msg_in), WHEN MSG_IN ; if target is in MSG_IN, read (& ignore) a byte 710 00000A30: 828B0000 00000050 JUMP REL (set_atn_command), WHEN CMD ; if target is in CMD, send it a null byte 711 00000A38: 838B0000 00000068 JUMP REL (set_atn_status), WHEN STATUS ; if target is in STATUS, read (& ignore) a byte 712 00000A40: 98080000 000000A2 INT 0xA2 ; don't know what state target is in, barf 713 00000A48: set_atn_data_in: 714 00000A48: 09000001 00000108 MOVE 1, msg_buf, WHEN DATA_IN 715 00000A50: 80880000 FFFFFFB8 JUMP REL (set_atn_loop) 716 00000A58: set_atn_data_out: 717 00000A58: 78080000 00000000 MOVE 0 TO SFBR 718 00000A60: E0080001 00000108 STORE SFBR, 1, msg_buf 719 00000A68: 08000001 00000108 MOVE 1, msg_buf, WHEN DATA_OUT 720 00000A70: 80880000 FFFFFF98 JUMP REL (set_atn_loop) 721 00000A78: set_atn_msg_in: 722 00000A78: 0F000001 00000108 MOVE 1, msg_buf, WHEN MSG_IN 723 00000A80: 80880000 FFFFFF80 JUMP REL (set_atn_clrack) 724 00000A88: set_atn_command: 725 00000A88: 78080000 00000000 MOVE 0 TO SFBR 726 00000A90: E0080001 00000108 STORE SFBR, 1, msg_buf 727 00000A98: 0A000001 00000108 MOVE 1, msg_buf, WHEN COMMAND 728 00000AA0: 80880000 FFFFFF68 JUMP REL (set_atn_loop) 729 00000AA8: set_atn_status: 730 00000AA8: 0B000001 00000108 MOVE 1, msg_buf, WHEN STATUS 731 00000AB0: 80880000 FFFFFF58 JUMP REL (set_atn_loop) 732 ; 733 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 734 ; 735 ; Clock and width routines 736 ; 737 ; These routines take the results of negotiation messages and updates the 738 ; se3_scntl3 and se1_sxfer locations accordingly 739 ; 740 ; scntl3 consists of the following bits 741 ; 742 ; <7> = 0 : normal de-glitching 743 ; 1 : ultra synchronous de-glitching 744 ; this gets set only for 20MHz synchronous mode 745 ; <4:6> = SCF divider (sets synchronous receive rate = 80MHz/4/SCF) 746 ; 000 = /3 747 ; 001 = /1 748 ; 010 = /1.5 749 ; 011 = /2 750 ; 100 = /3 751 ; 101 = /4 752 ; <3> = 0 : 8-bit transfers 753 ; 1 : 16-bit transfers 754 ; <0:2> = CCF divider (sets asynchronous clock = 80MHz/CCF) (must not exceed 25MHz) 755 ; 101 = /4 756 ; 757 ; sxfer consists of these bits: 758 ; 759 ; <5:7> = TP (synchronous clock = 80MHz/SCF/TP) 760 ; 000 = /4 761 ; 001 = /5 762 ; 010 = /6 763 ; 011 = /7 764 ; 100 = /8 765 ; 101 = /9 766 ; 110 = /10 767 ; 111 = /11 768 ; <0:4> = req/ack offset 769 ; 0 = async 770 ; 771 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 772 ; 773 ; Save transfer width 774 ; 775 ; Input: 776 ; 777 ; SFBR = as defined in scsi standard for the negotiation value 778 ; 0: 8-bit transfers 779 ; 1: 16-bit transfers 780 ; DSA = points to scsi_id_table entry 781 ; 782 ; Output: 783 ; 784 ; se3_scntl3 = modified 785 ; 786 ; Scratch: 787 ; 788 ; SCRATCHA3 789 ; 790 00000AB8: save_transfer_width: 791 00000AB8: F1370001 00000007 LOAD SCRATCHA3, 1, DSAREL (se3_scntl3) ; get what was in there before 792 00000AC0: 7C37F700 00000000 MOVE SCRATCHA3 & 0xF7 TO SCRATCHA3 ; clear the 'wide' bit 793 00000AC8: 808C0000 00000008 JUMP REL (save_transfer_width_ok), IF 0 794 00000AD0: 7A370800 00000000 MOVE SCRATCHA3 | 0x08 TO SCRATCHA3 ; ok, set it then 795 00000AD8: save_transfer_width_ok: 796 00000AD8: F2370001 00000007 STORE NOFLUSH SCRATCHA3, 1, DSAREL (se3_scntl3) 797 00000AE0: 90080000 00000000 RETURN 798 ; 799 ; This is the rate that synchronous transfers will happen at 800 ; 801 ; Input: 802 ; 803 ; SFBR = as defined in scsi standard for the negotiation value 804 ; ... 10=25ns period, 11=30.3ns, 12=50ns, 13=52nS, 14=56nS, 15=60nS, ... 805 ; 806 ; Output: 807 ; 808 ; se3_scntl3 = modified accordingly 809 ; SCRATCHA2 = resultant negotiation value 810 ; 811 ; Scratch: 812 ; 813 ; SFBR, SCRATCHA1, SCRATCHA3 814 ; 815 ; Note: 816 ; 817 ; requested we do giving SCF 818 ; <= 50ns (12) 20MHz /1 (001) 819 ; <=100ns (25) 10MHz /2 (011) 820 ; else..... 5MHz /4 (101) 821 ; 822 00000AE8: save_transfer_period: 823 00000AE8: F1370001 00000007 LOAD SCRATCHA3, 1, DSAREL (se3_scntl3) ; get what's in se3_scntl3 824 00000AF0: 7C378F00 00000000 MOVE SCRATCHA3 & 0x8F TO SCRATCHA3 ; clear out the SCF bits 825 00000AF8: 7A375000 00000000 MOVE SCRATCHA3 | 0x50 TO SCRATCHA3 ; set SCF = 101 (/4) for 5MHz rate 826 00000B00: 78363200 00000000 MOVE 50 TO SCRATCHA2 ; set up negotiation value for 5MHz 827 00000B08: 6E08E600 00000000 MOVE SFBR + (0xFF - 25) TO SFBR ; sets carry iff sfbr > 25 828 00000B10: 80A80000 00000030 JUMP REL (save_transfer_period_ok), IF CARRY 829 00000B18: 7E37E000 00000000 MOVE SCRATCHA3 - 0x20 TO SCRATCHA3 ; set SCF = 011 (/2) for 10MHz rate 830 00000B20: 78361900 00000000 MOVE 25 TO SCRATCHA2 ; set up negotiation value for 10MHz 831 00000B28: 6E080D00 00000000 MOVE SFBR + 13 TO SFBR ; sets carry iff original sfbr > 12 832 00000B30: 80A00000 00000010 JUMP REL (save_transfer_period_ok), IF NOT CARRY 833 00000B38: 78360C00 00000000 MOVE 12 TO SCRATCHA2 ; set up negotiation value for 20MHz 834 00000B40: 7E37E000 00000000 MOVE SCRATCHA3 - 0x20 TO SCRATCHA3 ; set SCF = 101 (/4) for 5MHz rate 835 00000B48: save_transfer_period_ok: 836 00000B48: F2370001 00000007 STORE NOFLUSH SCRATCHA3, 1, DSAREL (se3_scntl3) 837 00000B50: F1350001 00000005 LOAD SCRATCHA1, 1, DSAREL (se1_sxfer) 838 00000B58: 80880000 00000050 JUMP REL (check_ultra_enable) 839 ; 840 ; This is the maximum number of req's than can be sent out without having 841 ; received the corresponding ack's for a synchronous transfer. 842 ; 843 ; Zero means use asynchronous transfer (the default case) 844 ; 845 ; Input: 846 ; 847 ; SFBR = as defined in scsi standard for the negotiation value 848 ; range 0..16 849 ; DSA = points to scsi_id_table entry 850 ; 851 ; Output: 852 ; 853 ; se1_sxfer = modified accordingly 854 ; SCRATCHA2 = resultant negotiated value 855 ; 856 ; Scratch: 857 ; 858 ; SFBR, SCRATCHA1, SCRATCHA3 859 ; 860 00000B60: save_req_ack_offset: 861 00000B60: 6A360000 00000000 MOVE SFBR TO SCRATCHA2 ; assume sfbr value is ok as is 862 00000B68: 6E08EF00 00000000 MOVE SFBR + (0xFF - 16) TO SFBR ; sets carry iff sfbr > 16 863 00000B70: 80A00000 00000008 JUMP REL (save_req_ack_offset_ok), IF NOT CARRY 864 00000B78: 78361000 00000000 MOVE 16 TO SCRATCHA2 ; if too big, just use 16 865 00000B80: save_req_ack_offset_ok: 866 00000B80: 72360000 00000000 MOVE SCRATCHA2 TO SFBR 867 00000B88: F1350001 00000005 LOAD SCRATCHA1, 1, DSAREL (se1_sxfer) ; get what is there 868 00000B90: 7C35E000 00000000 MOVE SCRATCHA1 & 0xE0 TO SCRATCHA1 ; save the existing rate info 869 00000B98: 7AB50000 00000000 MOVE SCRATCHA1 | SFBR TO SCRATCHA1 ; put in the new offset info 870 00000BA0: F2350001 00000005 STORE NOFLUSH SCRATCHA1, 1, DSAREL (se1_sxfer) 871 00000BA8: F1370001 00000007 LOAD SCRATCHA3, 1, DSAREL (se3_scntl3) 872 ; 873 ; Set the ULTRA enable bit in SCNTL3 iff SXFER indicates max speed synchronous 874 ; 875 ; Input: 876 ; 877 ; SCRATCHA1 = se1_sxfer contents 878 ; SCRATCHA3 = se3_scntl3 contents 879 ; 880 00000BB0: check_ultra_enable: 881 00000BB0: 7C377F00 00000000 MOVE SCRATCHA3 & 0x7F TO SCRATCHA3 ; clear ultra enable 882 00000BB8: 72350000 00000000 MOVE SCRATCHA1 TO SFBR 883 00000BC0: 808CE000 00000018 JUMP REL (check_ultra_enable_ok), IF 0x00 AND MASK 0xE0 ; don't bother setting it if async mode 884 00000BC8: 72370000 00000000 MOVE SCRATCHA3 TO SFBR 885 00000BD0: 80848F10 00000008 JUMP REL (check_ultra_enable_ok), IF NOT 0x10 AND MASK 0x8F ; don't bother setting if not max speed 886 00000BD8: 7A378000 00000000 MOVE SCRATCHA3 | 0x80 TO SCRATCHA3 ; synchronous and max speed, set ultra enable bit 887 00000BE0: check_ultra_enable_ok: 888 00000BE0: F0370001 00000007 STORE SCRATCHA3, 1, DSAREL (se3_scntl3) 889 00000BE8: 90080000 00000000 RETURN 890 ; 891 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 892 --SYMBOL---------------------------VALUE------TYPE------- INIT_SCSI_TABLE_4 55000000 ABSOLUTE INIT_SCSI_TABLE_SXFER 00000000 ABSOLUTE INIT_SCSI_TABLE_SCNTL3 00000055 ABSOLUTE RP_FLAG_DONE 00000010 ABSOLUTE RP_FLAG_GOTSTATUS 00000008 ABSOLUTE RP_FLAG_NEGSYNCH 00000004 ABSOLUTE RP_FLAG_NEGWIDTH 00000002 ABSOLUTE RP_FLAG_NEEDTOIDENT 00000001 ABSOLUTE rp0_flags 0000000C ABSOLUTE rp1_abort 0000000D ABSOLUTE rp2_status 0000000E ABSOLUTE rp3_cmdlen 0000000F ABSOLUTE rp_command 00000010 ABSOLUTE rp_datamov_pa 00000008 ABSOLUTE rp_next_pa 00000004 ABSOLUTE rp_this_va 00000000 ABSOLUTE REQ_ACK_OFFSET 00000010 ABSOLUTE SCRATCHJ1_SELECT 00000002 ABSOLUTE SCRATCHJ1_CHMOVS 00000001 ABSOLUTE SE_STATE_CHECKING_TARGET 00000004 ABSOLUTE SE_STATE_GETTING_STATUS 00000002 ABSOLUTE SE_STATE_GETTING_MESSAGE 00000001 ABSOLUTE SE_STATE_IDLE 00000000 ABSOLUTE SE_STATE_MESSAGE_OUT 00000003 ABSOLUTE SE_STATE_SELECTED 00000005 ABSOLUTE SE_STATE_SELECTING 00000006 ABSOLUTE SE_STATE_SENDING_COMMAND 00000007 ABSOLUTE SE_STATE_TRANSFERRING_DATA 00000008 ABSOLUTE SE_STATE_WAITING_FOR_RESELECT 00000009 ABSOLUTE se0_state 00000004 ABSOLUTE se1_sxfer 00000005 ABSOLUTE se3_scntl3 00000007 ABSOLUTE se_queue_head 00000000 ABSOLUTE se_saved_pointer 00000008 ABSOLUTE XFER_PERIOD_FACT 0000000C ABSOLUTE SCRIPT 00000000 CODE SEGMENT select_timedout 00000150 ENTRY startup 00000138 ENTRY transfer_data_mismatch 000005E8 ENTRY transfer_data_done 000005D8 ENTRY abort_task 00000110 LABEL bad_nego_mess_async 000008B0 LABEL bad_nego_mess_reject 000008A0 LABEL bad_nego_mess 00000898 LABEL bad_reselect_scsi_id 00000208 LABEL check_target_state 000002C8 LABEL check_reselect 000001A8 LABEL check_ultra_enable 00000BB0 LABEL check_ultra_enable_ok 00000BE0 LABEL command_move 00000570 LABEL disconnecting 000007F0 LABEL got_extended_message 000006D0 LABEL got_new_req 00000250 LABEL get_request_packet 000008E8 LABEL got_sync_data_xfer_msg 00000774 LABEL got_wide_data_xfer_msg 00000708 LABEL ignore_message 000006C0 LABEL mainloop 00000150 LABEL message_ident_synch 00000130 LABEL message_ident_width 00000128 LABEL message_reject 00000118 LABEL msg_buf 00000108 LABEL new_req_scanloop 00000160 LABEL noop_message 00000120 LABEL not_reselect 00000228 LABEL proc_synch_reply 00000498 LABEL proc_width_reply_clear_ack 00000450 LABEL proc_width_reply 000003D0 LABEL reject_message 000006A8 LABEL req_complete 00000818 LABEL req_complete2 00000828 LABEL request_packet_to_dsa 000009B8 LABEL save_req_ack_offset 00000B60 LABEL save_req_ack_offset_ok 00000B80 LABEL save_transfer_period 00000AE8 LABEL save_transfer_period_ok 00000B48 LABEL save_transfer_width 00000AB8 LABEL save_transfer_width_ok 00000AD8 LABEL scsi_id_entry_to_dsa 00000970 LABEL scsi_id_ptr 00000100 LABEL scsi_id_table 00000000 LABEL select_instr 000002A0 LABEL send_message_ident 00000378 LABEL send_message_ident_synch 00000460 LABEL send_message_ident_width 00000398 LABEL send_message_synch 00000480 LABEL send_message_width 000003B8 LABEL set_atn 00000A00 LABEL set_atn_clrack 00000A08 LABEL set_atn_command 00000A88 LABEL set_atn_data_in 00000A48 LABEL set_atn_data_out 00000A58 LABEL set_atn_loop 00000A10 LABEL set_atn_msg_in 00000A78 LABEL set_atn_status 00000AA8 LABEL transfer_data_in 00000580 LABEL transfer_command 00000518 LABEL transfer_data_out 00000580 LABEL transfer_message_in 00000660 LABEL transfer_message_out 00000318 LABEL transfer_no_data 000005F8 LABEL transfer_status 00000610 LABEL width_ok 0000074C LABEL