Annotation of XNU/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.ss, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.