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