Annotation of XNU/iokit/Drivers/scsi/drvSymbios8xx/Sym8xxScript.ss, revision 1.1.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.