|
|
1.1 ! root 1: ! 2: ; Copyright (c) 1997-1999 Apple Computer, Inc. All rights reserved. ! 3: ; ! 4: ; @APPLE_LICENSE_HEADER_START@ ! 5: ; ! 6: ; The contents of this file constitute Original Code as defined in and ! 7: ; are subject to the Apple Public Source License Version 1.1 (the ! 8: ; "License"). You may not use this file except in compliance with the ! 9: ; License. Please obtain a copy of the License at ! 10: ; http://www.apple.com/publicsource and read it before using this file. ! 11: ; ! 12: ; This Original Code and all software distributed under the License are ! 13: ; distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: ; EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: ; INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: ; FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: ; License for the specific language governing rights and limitations ! 18: ; under the License. ! 19: ; ! 20: ; @APPLE_LICENSE_HEADER_END@ ! 21: ; ! 22: ; File Ownership: ! 23: ; ! 24: ; DRI: Mike Johnson ! 25: ; ! 26: ; Other Contact: Russ Berkoff ! 27: ; ! 28: ; Technology: SCSI ! 29: ; ! 30: ; Writers: ! 31: ; ! 32: ; (MLJ) Mike Johnson ! 33: ; (RRA) Rick Auricchio ! 34: ! 35: ! 36: ; NCR Errata Listing 125 Item 1 : Clear the SCNTL0 start bit ! 37: ; when jump to reselect during select (try_reselect) ! 38: ; ! 39: ; NCR Errata Listing 117 Item 4 : Bad parity if odd bytes during ! 40: ; wide transfer. Only for DATA OUT in Initiator mode. ! 41: ; (Confirm by Manfred Eierle 3rd June 93 not during DATA IN) ! 42: ! 43: ARCH 825A ;specifically for 825a and 875 (new instructions) ! 44: ! 45: ! 46: ;***************************************************************** ! 47: ; ! 48: ; Phase codes - These values represent which action is being handled ! 49: ; ! 50: ;***************************************************************** ! 51: ! 52: ABSOLUTE kphase_DATA_OUT = 0x00 ! 53: ABSOLUTE kphase_DATA_IN = 0x01 ! 54: ABSOLUTE kphase_COMMAND = 0x02 ! 55: ABSOLUTE kphase_STATUS = 0x03 ! 56: ABSOLUTE kphase_MSG_OUT = 0x06 ! 57: ABSOLUTE kphase_MSG_IN = 0x07 ! 58: ABSOLUTE kphase_SELECT = 0x08 ! 59: ABSOLUTE kphase_RESELECT = 0x09 ! 60: ABSOLUTE kphase_ABORT_CURRENT = 0x0A ! 61: ABSOLUTE kphase_ABORT_MAILBOX = 0x0B ! 62: ABSOLUTE kphase_CMD_COMPLETE = 0x0C ! 63: ABSOLUTE kphase_DISCONNECT = 0x0D ! 64: ABSOLUTE kphase_saveDataPointer = 0x0E ; ??? driver work to be done ! 65: ABSOLUTE kphase_restoreDataPointer = 0x0F ; ??? driver work to be done ! 66: ! 67: ! 68: ;***************************************************************** ! 69: ; interrupt codes ! 70: ;***************************************************************** ! 71: ! 72: ABSOLUTE unknown_phase = 0x00 ; A spurious phase on SCSI Bus ! 73: ABSOLUTE status_error = 0x01 ; IO completes, but with status error ! 74: ABSOLUTE unexpected_msg = 0x02 ; An 'unknown' message is in ld_message var ! 75: ABSOLUTE unexpected_ext_msg = 0x03 ; An 'unknown' extended message in ld_message ! 76: ABSOLUTE wide_32_not_supported = 0x04 ; The device wants 32 bits data phase ! 77: ABSOLUTE no_msgin_after_reselect = 0x05 ; No message-in after reselection ! 78: ABSOLUTE reqack_too_large = 0x06 ; The device answer ReqAck offset is greater than 8 ! 79: ABSOLUTE unknown_reselect = 0x07 ; The valid bit in SFBR reg not set ! 80: ABSOLUTE unallocated_nexus = 0x08 ; nexus index -> 0xFFFFFFFF ! 81: ABSOLUTE abort_mailbox = 0x09 ; Abort/BDR mailbox completed ! 82: ABSOLUTE abort_current = 0x0A ; Abort/BDR current op completed ! 83: ABSOLUTE unknown_message_out = 0x0B ; Unknown phase before message out ! 84: ABSOLUTE unknown_msg_reject = 0x0C ; Unknown message reject ! 85: ABSOLUTE negotiateSDTR = 0x0D ; Sync negotiation rx'd ! 86: ABSOLUTE negotiateWDTR = 0x0E ; Wide negotiation rx'd ! 87: ABSOLUTE sglist_complete = 0x0F ; SGList complete ! 88: ! 89: ! 90: ;***************************************************************** ! 91: ; ! 92: ; Data structure for T/L/Q Nexus: ! 93: ; ! 94: ;***************************************************************** ! 95: ! 96: ABSOLUTE TLQ_SCSI_ID = 0 ; 4 SCSI ID et al for SELECT instruction ! 97: ABSOLUTE TLQ_xferAdr = 4 ; 4 Physical address of CHMOV instructions ! 98: ABSOLUTE TLQ_MSGOp = 8 ; 8 Byte count, data adr -> TLQ_MSGO ! 99: ABSOLUTE TLQ_CDBp = 16 ; 8 Byte count, data adr -> TLQ_CDB ! 100: ABSOLUTE TLQ_CDP = 24 ; 4 Current Data Pointer ! 101: ABSOLUTE TLQ_SDP = 28 ; 4 Saved Data Pointer ! 102: ABSOLUTE TLQ_index = 32 ; 1 index into nexus array ! 103: ABSOLUTE TLQ_xferStarted= 33 ; 1 transfer started flag ! 104: ABSOLUTE TLQ_IWR = 34 ; 1 flag to Ignore Wide Residue ! 105: ABSOLUTE TLQ_pad = 35 ; 1 pad byte ! 106: ! 107: ! 108: ;***************************************************************** ! 109: ; ! 110: ; ENTRY declarations - Declare entry points for driver ! 111: ; ! 112: ;***************************************************************** ! 113: ! 114: ENTRY select_phase ! 115: ENTRY phase_handler ! 116: ENTRY issueMessageOut ; for negotiation and Reject messages ! 117: ENTRY issueAbort_BDR ; to immediately Abort or Bus-Device-Reset ! 118: ENTRY clearACK ; MsgIn done - clr ACK, jump to phase handler ! 119: ! 120: ! 121: ;***************************************************************** ! 122: ; ! 123: ; Define local data structure at start of SCRIPTS. ! 124: ; This structure is allocated by the following nops. ! 125: ; ! 126: ;***************************************************************** ! 127: ; ! 128: ! 129: RELATIVE local_data \ ! 130: ld_AbortCode = 4{??}\ ; 1 byte code to Abort or BDR ! 131: ld_zeroes = 4{??}\ ; 4 bytes of 0 to clear registers ! 132: ld_status = 4{??}\ ; Status byte from target ! 133: ld_counter = 4{??}\ ; index into mailbox array ! 134: ld_AbortBdr_mailbox = 4{??}\ ; Abort/BusDeviceReset mailbox ! 135: ld_IOdone_mailbox = 4{??}\ ; [ nexus 0 0 semaphore ] ! 136: ld_sched_mlbx_base_adr = 4{??}\ ; base addr of mailbox array ! 137: ld_mailboxp = 4{??}\ ; address of current mailbox ! 138: ld_scsi_id = 4{??}\ ; ptr to current mailbox ! 139: ld_nexus_array_base = 4{??}\ ; base address of Nexus pointers ! 140: ld_nexus_index = 4{??}\ ; index to Nexus pointer ! 141: ld_nexus = 4{??}\ ; address of Nexus ! 142: ld_phase_flag = 4{??}\ ; for debugging ! 143: ld_device_table_base_adr = 4{??}\ ; device configuration table ! 144: ld_scratch = 4{??}\ ; scratch memory ! 145: ld_unused = 4{??}\ ; unused ! 146: ld_message = 4{??}\ ; buffer for MsgIn bytes ! 147: ld_message4 = 4{??}\ ; buffer continuation ! 148: ld_pad = 4{??}\ ; padding ! 149: ld_size = 4{??} ; size of this structure ! 150: ! 151: ! 152: PROC BSC_SCRIPT: ! 153: ! 154: ; *** These NOPs must be at address 0. *** ! 155: ; *** This is reserved space for the structure "local_data". *** ! 156: ; *** The driver inits this area to zero. *** ! 157: ! 158: nop 0 ; ld_AbortCode, ld_zeroes ! 159: nop 0 ; ld_status, ld_counter ! 160: ! 161: nop 0 ; ld_AbortBdr_mailbox, ld_IOdone_mailbox ! 162: nop 0 ; ld_sched_mlbx_base_adr, ld_mailboxp ! 163: ! 164: nop 0 ; ld_scsi_id, ld_nexus_array_base ! 165: nop 0 ; ld_nexus_index, ld_nexus ! 166: ! 167: nop 0 ; ld_phase_flag, ld_device_table_base_adr ! 168: nop 0 ; ld_scratch, ld_unused ! 169: ! 170: nop 0 ; ld_message, ld_message4 ! 171: nop ld_size ; ld_pad, ld_size (Use ld_size or lose it) ! 172: ! 173: nop sglist_complete ; use sglist_complete or lose it from gen'd output file ! 174: ! 175: ;**************************************************************************** ! 176: ; ! 177: ; findNexusFromIndex - load DSA with pointer to Nexus given a Nexus index: ! 178: ; ! 179: ;**************************************************************************** ! 180: ! 181: findNexusFromIndex: ! 182: ! 183: load SCRATCHA0, 4, ld_nexus_index ; load index and leading zeroes ! 184: clear CARRY ! 185: move SCRATCHA0 SHL 0 to SCRATCHA0 ; double the index ! 186: move SCRATCHA1 SHL 0 to SCRATCHA1 ! 187: move SCRATCHA0 SHL 0 to SCRATCHA0 ; double again ! 188: move SCRATCHA1 SHL 0 to SCRATCHA1 ; A0 now has index to 4-byte address ! 189: store SCRATCHA0, 4, patchArrayOffset+4 ; *** patch the code ! 190: ! 191: load DSA0, 4, ld_nexus_array_base ; load base address of array of Nexus pointers ! 192: patchArrayOffset: ! 193: load DSA0, 4, DSAREL( 0 ) ; *** patched offset. Load pointer. ! 194: ! 195: move DSA0 to SFBR ; Ensure pointer is not 0xFFFFFFFF ! 196: int unallocated_nexus, if 0xFF ; Interrupt if NFG ! 197: ! 198: store DSA0, 4, ld_nexus ; Store the Nexus pointer ! 199: return ; end findNexusFromIndex ! 200: ! 201: ! 202: ;**************************************************************************** ! 203: ; ! 204: ; initContext - Initialize the registers for Sync and Wide using ! 205: ; values stored in the device configuration table. ! 206: ; Return with values in SCRATCHB for Select code. ! 207: ; ! 208: ;**************************************************************************** ! 209: ! 210: initContext: ! 211: ! 212: load SCRATCHB0, 4, ld_scsi_id ; load 4-bit SCSI ID and zeroes ! 213: clear CARRY ! 214: move SCRATCHB0 SHL SCRATCHB0 ; * 2 ! 215: move SCRATCHB0 SHL SCRATCHB0 ; * 2 -> UInt32 index ! 216: store SCRATCHB0, 4, patchGetDevConfigOffset+4 ; *** Patch load code ! 217: ! 218: load DSA0, 4, ld_device_table_base_adr ; load base physical addr of tables ! 219: ! 220: patchGetDevConfigOffset: ! 221: load SCRATCHB0, 4, DSAREL( 0 ) ; *** Patched table offset *** ! 222: ! 223: ; SCRATCHB0 = 0 ! 224: ; SCRATCHB1 = TP,MO (SXFER bits7-5 bits3-0) ! 225: ; SCRATCHB2 = 0 (position for SCSI ID) ! 226: ; SCRATCHB3 = SCCF,EWS (SCNTL3 bits6-4 bit 3) ! 227: ! 228: move SCRATCHB1 to SFBR ; init SXFER from B1 ! 229: move SFBR to SXFER ! 230: ; Init SCNTL3 from B3 ! 231: move SCRATCHB3 to SFBR ! 232: move SFBR to SCNTL3 ! 233: return ; return with SCRATCHB intact. ! 234: ! 235: ! 236: ;***************************************************************** ! 237: ; ! 238: ; Select_phase: ! 239: ; Clear the SIGP bit. ! 240: ; Check if any Abort/BusDeviceReset request waiting. ! 241: ; Nexus is found in the list of 256 mailboxes. ! 242: ; If current mailbox is empty, jump to reselect_phase. ! 243: ; SCRIPTS tries to select device. ! 244: ; If select fails due to reselect, jump to reselect_phase ! 245: ; Select Timeout handled by driver. ! 246: ; If select succeeds, clear the mailbox entry ! 247: ; and increment the mailbox counter. ! 248: ; Jump to the phase_handler (hopefully for MSG_OUT) ! 249: ; ! 250: ;***************************************************************** ! 251: ! 252: select_phase: ! 253: ! 254: move CTEST2 | 0x00 to CTEST2 ; Clear SIGP bit from ISTAT reg ! 255: ! 256: ; Check abort mailbox: ! 257: ! 258: load SCRATCHA0, 4, ld_AbortBdr_mailbox ; Get AbortBdr mailbox ! 259: ; The Identify byte in byte 0 is also the semaphore ! 260: ; A0 = Identify byte (0xC0 + LUN N.B. Disconnect allowed) ! 261: ; A1 = Tag, if any ! 262: ; A2 = SCSI ID ! 263: ; A3 = Abort code Abort=0x06; Abort Tag=0D; Bus Device Reset=0x0C ! 264: move SCRATCHA0 to SFBR ; test the semaphore/Identify ! 265: jump rel( AbortMailbox ), if not 0 ; jump if aborting ! 266: ! 267: ! 268: ; Get the next IO nexus in the mailboxes circular list. ! 269: ; Calculate current mailbox address as so: ! 270: ; counter byte index * 4 to get mailbox index ! 271: ; add base physical address of mailboxes giving current mailbox address ! 272: ! 273: load SCRATCHA0, 4, ld_counter ; get 1-byte mailbox counter & 0s ! 274: clear CARRY ! 275: move SCRATCHA0 SHL 0 to SCRATCHA0 ; double it ! 276: move SCRATCHA1 SHL 0 to SCRATCHA1 ! 277: move SCRATCHA0 SHL 0 to SCRATCHA0 ; double it again ! 278: move SCRATCHA1 SHL 0 to SCRATCHA1 ; now have a UInt32 index ! 279: store SCRATCHA0, 4, fetchMailbox+4 ; *** patch the load DSA instruction ! 280: store SCRATCHA0, 4, clear_mailbox+4 ; *** patch the store DSA instruction ! 281: ! 282: load DSA0, 4, ld_sched_mlbx_base_adr ; load base physical address of mailboxes ! 283: ! 284: fetchMailbox: ! 285: load DSA0, 4, DSAREL( 0 ) ; *** Patched offset. Load Nexus address ! 286: store DSA0, 4, ld_nexus ; save pointer to current Nexus ! 287: load SCRATCHA0, 4, ld_nexus ; copy to A0 ! 288: ! 289: move SCRATCHA0 to SFBR ; ! 290: jump rel( next_mailbox ), if 1 ; if low-byte == 0x01 then cancelled mailbox ! 291: ! 292: move SCRATCHA1 | SFBR to SFBR ; if non-zero, have implicit semaphore ! 293: move SCRATCHA2 | SFBR to SFBR ! 294: move SCRATCHA3 | SFBR to SFBR ! 295: jump rel( reselect_phase ), if 0 ; go to reselect_phase if empty ! 296: ! 297: ;***************************************************************** ! 298: ; ! 299: ; Something in mailbox: we have work to do ! 300: ; ! 301: ;***************************************************************** ! 302: ! 303: move kphase_SELECT to SCRATCHB0 ; set phase indicator ! 304: store SCRATCHB0, 1, ld_phase_flag ! 305: ! 306: load SCRATCHB0, 4, ld_zeroes ; clr the invalid-nexus-index flag ! 307: load SCRATCHB0, 1, DSAREL( TLQ_index ) ; get index byte from nexus ! 308: store SCRATCHB0, 4, ld_nexus_index ; save it in local data ! 309: ! 310: load DSA0, 4, ld_nexus ; restore DSA register ! 311: load SCRATCHB2, 1, DSAREL( TLQ_SCSI_ID+2 ) ; get Target's SCSI ID ! 312: move SCRATCHB2 to SFBR ! 313: move SFBR to SCRATCHB0 ; position it ! 314: store SCRATCHB0, 1, ld_scsi_id ; save it ! 315: call rel( initContext ) ; setup Sync/Wide regs in SCRATCHB ! 316: load DSA0, 4, ld_nexus ; restore DSA register ! 317: store SCRATCHB1, 1, DSAREL( TLQ_SCSI_ID+1 ) ; SXFER ! 318: store SCRATCHB3, 1, DSAREL( TLQ_SCSI_ID+3 ) ; SCNTL3 ! 319: ! 320: ;********************** select the device ******************************** ! 321: SELECT ATN from TLQ_SCSI_ID, rel( try_reselect ) ; ************************ ! 322: ;************************************************************************* ! 323: ! 324: ; looking good - clear the mailbox: ! 325: ! 326: next_mailbox: ! 327: load SCRATCHA0, 4, ld_zeroes ; zero out scratch register A ! 328: load DSA0, 4, ld_sched_mlbx_base_adr ; load base physical address of mailboxes ! 329: clear_mailbox: ! 330: store SCRATCHA0, 4, DSAREL( 0 ) ; *** Patched offset. Zero the mailbox ! 331: ! 332: ; Update the index to the mailbox circular list: ! 333: load SCRATCHB0, 1, ld_counter ; get counter (mailbox index) ! 334: move SCRATCHB0 + 1 to SCRATCHB0 ; add 1 ! 335: store SCRATCHB0, 1, ld_counter ; put it back ! 336: ! 337: load SCRATCHB0, 1, ld_nexus ; if low-byte == 0x01 then cancelled mailbox ! 338: move SCRATCHB0 to SFBR ! 339: jump rel( select_phase ), if 1 ! 340: ! 341: ; *** FALL THROUGH TO phase_handler *** ! 342: ! 343: ! 344: ;***************************************************************** ! 345: ; ! 346: ; Phase_handler ! 347: ; The phase handler script is a dispatcher function of SCSI phase ! 348: ; ! 349: ;***************************************************************** ! 350: ! 351: phase_handler: ! 352: load DSA0, 4, ld_nexus ; reload DSA ! 353: jump rel( command_phase ), when CMD ; wait for REQ ! 354: jump rel( data_out_phase ), if DATA_OUT ; already latched REQ signal ! 355: jump rel( message_out_phase ), if MSG_OUT ! 356: jump rel( data_in_phase ), if DATA_IN ! 357: jump rel( status_phase ), if STATUS ! 358: jump rel( message_in_phase ), if MSG_IN ! 359: int unknown_phase ! 360: ! 361: ! 362: ;***************************************************************** ! 363: ; ! 364: ; Message-Out phase ! 365: ; ! 366: ;***************************************************************** ! 367: ! 368: message_out_phase: ! 369: move kphase_MSG_OUT to SCRATCHB0 ; Set phase indicator ! 370: store SCRATCHB0, 1, ld_phase_flag ! 371: ! 372: move from TLQ_MSGOp, when MSG_OUT ; put out the message(s) ! 373: jump rel( phase_handler ) ! 374: ! 375: ! 376: ; issueMessageOut - Driver entry point for Sync/Wide negotiation and ! 377: ; to issue message Reject: ! 378: ! 379: issueMessageOut: ! 380: set ATN ; tell Target we have something to say ! 381: clear ACK ! 382: jump rel( message_out_phase ), when MSG_OUT ; wait for REQ. Jump if msg-out phase. ! 383: jump rel( phase_handler ), if not MSG_IN ; jump if weird phase ! 384: move 1, ld_scratch+1, when MSG_IN ; dump the msg byte ! 385: clear ACK ; accept Target's last msg-in byte ! 386: jump rel( issueMessageOut ) ! 387: ! 388: ! 389: ;***************************************************************** ! 390: ; ! 391: ; Command phase ! 392: ; ! 393: ;***************************************************************** ! 394: ! 395: command_phase: ! 396: move kphase_COMMAND to SCRATCHB0 ; Set phase indicator ! 397: store SCRATCHB0, 1, ld_phase_flag ! 398: ! 399: clear ATN ; In case we missed the sending nego ! 400: move FROM TLQ_CDBp, when CMD ; issue the CDB ! 401: jump rel( phase_handler ) ! 402: ! 403: ! 404: ;***************************************************************** ! 405: ; ! 406: ; Data_out_phase ! 407: ; ! 408: ;***************************************************************** ! 409: ! 410: data_out_phase: ! 411: move kphase_DATA_OUT to SCRATCHB0 ; Set phase indicator ! 412: store SCRATCHB0, 1, ld_phase_flag ! 413: ! 414: call rel( driverXfer ) ; call driver-built CHMOV instructions ! 415: jump rel( phase_handler ) ; if all data xfer'd, get next phase ! 416: ! 417: driverXfer: ; get here from data-in code also ! 418: load SCRATCHA0, 4, DSAREL( TLQ_xferAdr ) ! 419: store SCRATCHA0, 4, doItPatch+4 ; *** patch the JUMP address ! 420: move 0xFF to SCRATCHA1 ! 421: store SCRATCHA1, 1, DSAREL( TLQ_xferStarted ) ! 422: ! 423: doItPatch: ! 424: jump 0x0333 ; *** patched address ! 425: ! 426: ! 427: ! 428: ;***************************************************************** ! 429: ; ! 430: ; Data_in_phase ! 431: ; 875 sets ATN if bad parity detected. ! 432: ; Use of CHMOV instructions assures that we properly handle ! 433: ; a leftover wide byte in the SWIDE or SODL register, depending ! 434: ; on the data direction. This can happen in either of two conditions: ! 435: ; 1. The Target disconnects at an odd boundary. This is ! 436: ; extremely unlikely with disk devices. ! 437: ; 2. The client passes either an odd buffer address or ! 438: ; an odd transfer count. When the Target disconnects (at ! 439: ; an even boundary, we end up with the extra wide ! 440: ; byte in SWIDE or SODL. MacOS does this with VM on. ! 441: ; ! 442: ;***************************************************************** ! 443: ! 444: data_in_phase: ! 445: move kphase_DATA_IN to SCRATCHB0 ; Set phase indicator ! 446: store SCRATCHB0, 1, ld_phase_flag ! 447: ! 448: call rel( driverXfer ) ; call driver-built CHMOV instructions ! 449: ! 450: ; The driver gets interrupted if a phase mismatch occurs as when ! 451: ; the Target goes MSG-IN with a Disconnect. ! 452: ; The driver codes either a RETURN if the Scatter/Gather list is complete or ! 453: ; an INT if more Scatter/Gather elements need to be generated. ! 454: ; On the Macintosh, client programs expect extra incoming data to be dumped. ! 455: ; For example, during boot the ROM reads 512 bytes from a 2K-byte-sector CD. ! 456: ! 457: bucket_loop: ! 458: jump rel( phase_handler ), when not DATA_IN ; wait for phase, exit if changed ! 459: CHMOV 1, ld_status, when DATA_IN ; eat a byte ! 460: jump rel( bucket_loop ); ; keep dumping bytes ! 461: ! 462: ! 463: ;***************************************************************** ! 464: ; ! 465: ; Status phase ! 466: ; ! 467: ;***************************************************************** ! 468: ! 469: status_phase: ! 470: move kphase_STATUS to SCRATCHB0 ; Set phase indicator ! 471: store SCRATCHB0, 1, ld_phase_flag ! 472: ! 473: move 1, ld_status, when STATUS ; Read Status byte from bus ! 474: jump rel( phase_handler ) ! 475: ! 476: ! 477: ;***************************************************************** ! 478: ; ! 479: ; Message-In phase ! 480: ; ! 481: ;***************************************************************** ! 482: ! 483: message_in_phase: ! 484: move kphase_MSG_IN to SCRATCHB0 ; Set phase indicator ! 485: store SCRATCHB0, 1, ld_phase_flag ! 486: ! 487: move 1, ld_message, when MSG_IN ; Read byte from bus ! 488: ! 489: jump rel( cmdComplete ), if 0x00 ; Command Complete ! 490: jump rel( saveDataPointer ), if 0x02 ; Save Data Pointer ! 491: jump rel( disconnect_msg ), if 0x04 ; Disconnect ! 492: jump rel( ignoreWideResidue ), if 0x23 ; Ignore Wide Residue ! 493: jump rel( restoreDataPointer ), if 0x03 ; Restore Data Pointer ! 494: jump rel( extended_msg ), if 0x01 ; Extended message ! 495: jump rel( msg_reject ), if 0x07 ; Message Reject ! 496: ; Identify, if 0x80-FF ; Identify + LUN ! 497: ; simple_queue_tag, if 0x20 ; Simple Queue Tag ! 498: ; initiate_recovery, if 0x0F ; Initiate Recovery ! 499: ; linked_cde_complete, if 0x0A/0x0B ! 500: int unexpected_msg ; unknown ! 501: ! 502: msg_reject: ! 503: int unknown_msg_reject ! 504: ! 505: clearACK: ; ENTRY point to end negotiation ! 506: clear ACK ! 507: jump rel( phase_handler ) ! 508: ! 509: ! 510: ! 511: ;***************************************************************** ! 512: ; ! 513: ; Ignore Wide Residue ! 514: ; ! 515: ;***************************************************************** ! 516: ! 517: ignoreWideResidue: ; this is a two byte message so snag the 2nd byte here ! 518: clear ACK ! 519: move 1, ld_message+1, when MSG_IN ; save residue count ! 520: move SFBR to SCRATCHB2 ; byte is still in SFBR. Position it. ! 521: store SCRATCHB2, 1, DSAREL( TLQ_IWR ) ; Store residue count in Nexus for driver. ! 522: clear ACK ! 523: jump rel( phase_handler ) ! 524: ! 525: ! 526: ;***************************************************************** ! 527: ; ! 528: ; Extended message ! 529: ; Accept Wide and Synchronous Data Transfer messages ! 530: ; ! 531: ;***************************************************************** ! 532: ! 533: extended_msg: ! 534: clear ACK ! 535: move 1, ld_message+1, when MSG_IN ; read msg length byte from bus ! 536: clear ACK ! 537: move 1, ld_message+2, when MSG_IN ; read ext msg code from bus ! 538: clear ACK ! 539: ; extended_identify, IF 0x02 ! 540: ; modify_data_pointer, if 0x00 ! 541: jump rel( sdtr ), if 0x01 ; jump if SDTR, sync negotiation msg ! 542: jump rel( wdtr ), if 0x03 ; jump if WDTR, wide negotiation msg ! 543: int unexpected_ext_msg ; let driver deal with unknown ! 544: ! 545: ! 546: ;***************************************************************** ! 547: ; ! 548: ; Command complete ! 549: ; The Command-Complete message is sent to indicate that the ! 550: ; IO operation has completed and valid status has been sent. ! 551: ; The Target should then disconnect. ! 552: ; SCRIPTS must spin until the IOdone mailbox is empty. ! 553: ; Then it sets the IOdone mailbox with the current Nexus. ! 554: ; The status message is analyzed. ! 555: ; If status is good, INTF the driver and jump to select_phase. ! 556: ; If status is NG, save it in the NEXUS and INT the driver. ! 557: ; ! 558: ;***************************************************************** ! 559: ! 560: cmdComplete: ! 561: move kphase_CMD_COMPLETE to SCRATCHB0 ; Set phase indicator ! 562: store SCRATCHB0, 1, ld_phase_flag ! 563: ! 564: move SCNTL2 & 0X7F to SCNTL2 ; Clr SDU: SCSI Disconnect Unexpected ! 565: clear ACK ! 566: WAIT DISCONNECT ! 567: ! 568: testMbxLp: ; loop until IOdone mailbox empty ! 569: load SCRATCHA0, 4, ld_IOdone_mailbox ! 570: move SCRATCHA3 to SFBR ; A3 = semaphore ! 571: jump rel( testMbxLp ), if not 0 ! 572: ! 573: ; Fill in the IOdone mailbox with the following: ! 574: ; A0 = index to Nexus ! 575: ; A1 = Status ! 576: ; A2 = 0 ! 577: ; A3 = semaphore (FF = set) ! 578: load SCRATCHA0, 1, ld_nexus_index ; A0 = index to Nexus ! 579: load SCRATCHB0, 1, ld_status ! 580: move SCRATCHB0 to SFBR ! 581: move SFBR to SCRATCHA1 ; A1 = Status ! 582: move 0x00 to SCRATCHA2 ; A2 = 0 ! 583: move 0xFF to SCRATCHA3 ; A3 = semaphore IOdone mailbox ! 584: store SCRATCHA0, 4, ld_IOdone_mailbox ! 585: ! 586: move SCRATCHA1 to SFBR ; Test the Status of this IO ! 587: ; SFBR = status msg ! 588: ; Test status - If good, Interrupt on the fly and jump to select phase ! 589: intfly 0xFF, if 0 and mask 0xC1 ; mask off reserved bits ! 590: jump rel( select_phase ), if 0 and mask 0xC1 ! 591: int status_error ; Status err. Interrupt driver & stop ! 592: ! 593: ! 594: ;***************************************************************** ! 595: ; ! 596: ; Disconnect ! 597: ; The 8xx Accepts the disconnection and jumps to the select_phase ! 598: ; to check for another IO ! 599: ; ! 600: ;***************************************************************** ! 601: ! 602: disconnect_msg: ! 603: load SCRATCHB0, 1, ld_phase_flag ! 604: move SCRATCHB0 to SFBR ! 605: ; If we got here from reselect just bailout since ld_nexus is ! 606: ; not setup and the code using it is not needed anyway (no data xfer) ! 607: jump rel( bailout ), if kphase_RESELECT ! 608: ! 609: move kphase_DISCONNECT to SCRATCHB0 ! 610: store SCRATCHB0, 1, ld_phase_flag ! 611: ! 612: bailout: ! 613: move 0xFF to SCRATCHB3 ; invalidate nexus index for driver ! 614: store SCRATCHB3, 1, ld_nexus_index+3 ! 615: move SCNTL2 & 0x7F to SCNTL2 ; Clr SDU: SCSI Disconnect Unexpected ! 616: clear ACK ! 617: WAIT DISCONNECT ; wait for bus-free ! 618: jump rel( select_phase ) ; go see if more to do ! 619: ! 620: ! 621: ;****************************************************************** ! 622: ; ! 623: ; ??? mlj - saveDataPointer and restoreDataPointer are incorrect. ! 624: ; ??? They basically do nothing. ! 625: ; Save Data Pointer ! 626: ; ! 627: ;***************************************************************** ! 628: ! 629: saveDataPointer: ! 630: move kphase_saveDataPointer to SCRATCHB0 ! 631: store SCRATCHB0, 1, ld_phase_flag ! 632: clear ACK ! 633: jump rel( phase_handler ) ! 634: ! 635: ! 636: ;****************************************************************** ! 637: ; ! 638: ; ??? mlj - saveDataPointer and restoreDataPointer are incorrect. ! 639: ; ??? They basically do nothing. ! 640: ; Restore Data Pointer ! 641: ; The local values still blocks, still bytes and data address ! 642: ; must be loaded from the corresponding NEXUS data set. ! 643: ; This message should followed an IDE (parity error) ! 644: ; ! 645: ;***************************************************************** ! 646: ! 647: restoreDataPointer: ! 648: move kphase_restoreDataPointer to SCRATCHB0 ! 649: store SCRATCHB0, 1, ld_phase_flag ! 650: clear ACK ! 651: jump rel( phase_handler ) ! 652: ! 653: ! 654: ;***************************************************************** ! 655: ; ! 656: ; Synchronous data transfer request or response ! 657: ; ! 658: ;***************************************************************** ! 659: sdtr: ! 660: move 2, ld_message+3, when MSG_IN ; Read period & offset from bus ! 661: int negotiateSDTR ! 662: ! 663: ! 664: ;*************************************************************************** ! 665: ; ! 666: ; Wide Data Transfer request or response ! 667: ; ! 668: ;*************************************************************************** ! 669: wdtr: ! 670: move 1, ld_message+3, when MSG_IN ; get Transfer Width Exponent fm bus ! 671: int negotiateWDTR ! 672: ! 673: ! 674: ;***************************************************************** ! 675: ; ! 676: ; Reselect phase ! 677: ; The chip waits here either for a Reselection from a Target or ! 678: ; a SIGP from the driver indicating something in the mailbox. ! 679: ; If reselected, the script uses the Nexus value which is either ! 680: ; a Tag or a SCSI ID/LUN combo to lookup the Nexus. ! 681: ; Then init the SXFER and SCNTL3 registers from the device config table. ! 682: ; ! 683: ;***************************************************************** ! 684: ! 685: try_reselect: ; Select failed - probably reselecting ! 686: ; Cf NCR Errata Listing 117 Item 1: ! 687: move SCNTL0 & 0xDF to SCNTL0 ; clr Start bit ! 688: move CTEST2 | 0x00 to CTEST2 ; Clear SIGP bit from ISTAT reg ! 689: ! 690: reselect_phase: ! 691: move kphase_RESELECT to SCRATCHB0 ; Set phase indicator ! 692: store SCRATCHB0, 1, ld_phase_flag ! 693: ! 694: move 0xFF to SCRATCHB3 ; invalidate nexus index for driver ! 695: store SCRATCHB3, 1, ld_nexus_index+3 ! 696: ! 697: ; wait here for reselect from a Target ! 698: ; or SIGP from the driver ! 699: ! 700: WAIT RESELECT REL( select_phase ) ; jump if SIGP ! 701: ! 702: ; Reselected: ! 703: ! 704: move SSID to SFBR ; SSID = [ Valxxx Scsi_id ] ! 705: int unknown_reselect, if 0 and mask 0x7F; Interrupt if VAL bit not set ! 706: move SFBR & 0x0F to SCRATCHB0 ; B0 = Target ID ! 707: store SCRATCHB0, 1, ld_scsi_id ; save it ! 708: ! 709: call rel( initContext ) ; setup sync regs here ! 710: ! 711: int no_msgin_after_reselect, when not MSG_IN ! 712: ! 713: move 1, ld_message, when MSG_IN ; Read Identify byte from bus ! 714: ! 715: ; if another REQ is asserted, a SimpleQueueTag message should be next ! 716: ! 717: clear ACK ; notify Target: msg byte rx'd ! 718: jump rel( getNextMsg ), when MSG_IN ; jump if SimpleQueueTag coming ! 719: ! 720: ; untagged operation: ! 721: ! 722: move SFBR & 0x07 to SCRATCHA0 ; isolate LUN from Identify byte ! 723: ! 724: load SCRATCHB0, 1, ld_scsi_id ; B0 = Target ID ! 725: clear CARRY ! 726: move SCRATCHB0 SHL SFBR ; shift left #1 ! 727: move SFBR SHL SCRATCHB0 ; shift left #2 ! 728: move SCRATCHB0 SHL SFBR ; shift left #3 ! 729: move SCRATCHA0 | SFBR to SCRATCHA0 ; form Nexus index = 0b0TTTTLLL ! 730: ! 731: store SCRATCHA0, 1, ld_nexus_index ; store as index to Nexus ! 732: jump rel( haveNexusIndex ) ! 733: ! 734: ; should be tagged operation: ! 735: ! 736: getNextMsg: ! 737: move 1, ld_message, when MSG_IN ; read message byte from bus ! 738: jump rel( disconnect_msg ), if 0x04 ; if Disconnect, oh well. ! 739: clear ACK ! 740: jump rel( phase_handler ), if not 0x20; Branch if not Queue tag code ! 741: ; get the Queue Tag and save as the nexus index ! 742: move 1, ld_nexus_index, when MSG_IN ; Nexus index <- Tag from bus ! 743: clear ACK ; acknowledge it ! 744: ! 745: haveNexusIndex: ! 746: move 0x00 to SCRATCHB3 ; clear invalid-nexus-index flag ! 747: store SCRATCHB3, 1, ld_nexus_index+3 ! 748: call rel( findNexusFromIndex ) ; set DSA <- Nexus pointer ! 749: jump rel( phase_handler ) ; start handling phases. ! 750: ! 751: ! 752: ;***************************************************************** ! 753: ; ! 754: ; AbortMailbox - Abort (or BusDeviceReset) the mailbox entry. ! 755: ; This is a queued operation - not an immediate ! 756: ; operation as is issueAbort_BDR. ! 757: ; The Abort message clears all IO processes for the ! 758: ; selecting Initiator on the specified LUN. ! 759: ; ! 760: ; The Bus Device Reset message clears all IO processes for ! 761: ; all Initiators on all LUNs of selected Target. ! 762: ; It forces a hard reset condition to the selected SCSI device. ! 763: ; ! 764: ; A0 = Identify byte (0xC0 + LUN N.B. Disconnect allowed) ! 765: ; A1 = Tag, if any ! 766: ; A2 = SCSI ID ! 767: ; A3 = Abort code Abort=0x06; Abort Tag=0D; Bus Device Reset=0x0C ! 768: ; ! 769: ; Mailbox not cleared by SCRIPTS so that driver can find SCSI ID when done ! 770: ; N.B.: Device is Async and Narrow after BDR!!! ! 771: ; Driver must set the device config table values accordingly. ! 772: ;***************************************************************** ! 773: ! 774: AbortMailbox: ! 775: move kphase_ABORT_MAILBOX to SCRATCHB0 ; Set phase code ! 776: store SCRATCHB0, 1, ld_phase_flag ! 777: ! 778: move 0xFF to SCRATCHB3 ; invalidate nexus index for driver ! 779: store SCRATCHB3, 1, ld_nexus_index+3 ! 780: ! 781: load SCRATCHB2, 1, ld_AbortBdr_mailbox+2 ; get SCSI ID ! 782: store SCRATCHB2, 1, AbortSelect+2 ; *** Patch the Select/ATN instruction ! 783: ! 784: AbortSelect: ! 785: SELECT ATN 0, REL( try_reselect ) ; *** Patched SCSI ID ! 786: ! 787: move SCRATCHA1 to SFBR ; check for Tag ! 788: jump rel( taggedAbort ) if not 0x00 ; jump if tagged abort ! 789: ! 790: ; untagged Abort or BusDeviceReset: ! 791: ! 792: move SCRATCHA3 to SFBR ; position the abort code ! 793: move SFBR to SCRATCHA1 ! 794: store SCRATCHA0, 2, ld_scratch ; Store Identify and Abort msgs ! 795: move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected ! 796: move 2, ld_scratch , when MSG_OUT ; emit Identify and Abort messages ! 797: WAIT DISCONNECT ! 798: int abort_mailbox ! 799: ! 800: ; AbortTag: ! 801: ! 802: taggedAbort: ! 803: move SCRATCHA1 to SFBR ; position the Tag ! 804: move SFBR to SCRATCHA2 ! 805: move 0x20 to SCRATCHA1 ; gen SimpleQueueTag code ! 806: store SCRATCHA0, 4, ld_scratch ; store Identify, SQT, Tag, AbortTag ! 807: move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected ! 808: move 4, ld_scratch, when MSG_OUT ; emit all 4 bytes ! 809: WAIT DISCONNECT ! 810: int abort_mailbox ! 811: ! 812: ! 813: ;***************************************************************** ! 814: ; ! 815: ; issueAbort_BDR - Abort (or BusDeviceReset) the current operation. ! 816: ; This is an immediate operation - not a queued operation ! 817: ; as is AbortMailbox. ! 818: ; The Abort message clears all IO processes for the ! 819: ; selecting Initiator on the specified LUN. ! 820: ; ! 821: ; The Bus Device Reset message clears all IO processes for ! 822: ; all Initiators on all LUNs of selected Target. ! 823: ; It forces a hard reset condition to the selected SCSI device. ! 824: ; ! 825: ;***************************************************************** ! 826: ! 827: issueAbort_BDR: ! 828: move kphase_ABORT_CURRENT to SCRATCHB0 ; Set phase code ! 829: store SCRATCHB0, 1, ld_phase_flag ! 830: ! 831: move ISTAT & 0x08 to SFBR ; see if Target connected to bus ! 832: int abort_current, if 0 ; interrupt driver if not connected ! 833: ! 834: SET ATN ; get Target's attention ! 835: load DSA0, 4, ld_nexus ; load pointer to Nexus ! 836: ! 837: bucketLoop: ! 838: clear ACK ! 839: jump rel( sendAbortBDR ), when MSG_OUT ; wait for REQ. Jump if OK. ! 840: ! 841: jump rel( BucketInStatus ), if STATUS ; bit bucket in ! 842: jump rel( BucketInMsg ), if MSG_IN ; bit bucket in ! 843: jump rel( BucketInData ), if DATA_IN ; bit bucket in ! 844: ! 845: move 0xAD to SCRATCHA0 ! 846: jump rel( BucketOutData ), if DATA_OUT ; bit bucket out ! 847: jump rel( BucketOutCmd ), if CMD ; bit bucket out ! 848: int unknown_phase ; back to driver for harsher measures ! 849: ! 850: ! 851: BucketInStatus: ! 852: move 1, ld_scratch, when STATUS ; eat the Status byte ! 853: jump rel( bucketLoop ); ; keep bit-bucketing bytes ! 854: ! 855: BucketInMsg: ! 856: move 1, ld_scratch, when MSG_IN ; eat a message byte ! 857: jump rel( bucketLoop ); ; keep bit-bucketing bytes ! 858: ! 859: BucketInData: ! 860: move 1, ld_scratch, when DATA_IN ; eat a data byte ! 861: jump rel( bucketLoop ); ; keep bit-bucketing bytes ! 862: ! 863: BucketOutData: ! 864: move SCRATCHA0 xor 0x73 to SCRATCHA0 ; gen 0xDEAD ... ! 865: store SCRATCHA0, 1, ld_scratch ! 866: move 1, ld_scratch, when DATA_OUT ; pad a byte out ! 867: jump rel( bucketLoop ); ; keep bit-bucketing bytes ! 868: ! 869: BucketOutCmd: ! 870: move 0x00 to SCRATCHA0 ; load Null, TestUnitReady, whatever ! 871: store SCRATCHA0, 1, ld_scratch ! 872: move 1, ld_scratch, when CMD ; pad a byte out ! 873: jump rel( bucketLoop ); ; keep bit-bucketing bytes ! 874: ! 875: ! 876: sendAbortBDR: ! 877: move 0x00 to SCNTL2 ; Clr SDU SCSI Disconnect Unexpected ! 878: move 1, ld_AbortCode, when MSG_OUT ; Send Abort(06) or BDR(0C) message ! 879: load SCRATCHA0, 4, ld_zeroes ; load 0's ! 880: store SCRATCHA0, 4, ld_AbortCode ; clear the Abort code ! 881: WAIT DISCONNECT ! 882: int abort_current ; went BusFree - tell Driver
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.