Annotation of kernel/bsd/dev/ppc/drvSymbios8xx/Sym8xxExecute.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /* Sym8xxExecute.m created by russb2 on Sat 30-May-1998 */
                     26: 
                     27: #import "Sym8xxController.h"
                     28: 
                     29: /*-----------------------------------------------------------------------------*
                     30:  * IOThread Routines
                     31:  *
                     32:  * This module contains routines that run on the driver's IOThread.
                     33:  *
                     34:  *-----------------------------------------------------------------------------*/
                     35: 
                     36: @implementation Sym8xxController(Execute)
                     37: 
                     38: /*-----------------------------------------------------------------------------*
                     39:  *  This is the main command processing loop for the driver's I/O thread.
                     40:  *  It removes SRBs from the driver's command queue and processes them according
                     41:  *  to the command code in srb->srbCmd.
                     42:  *
                     43:  *-----------------------------------------------------------------------------*/
                     44: - (void) commandRequestOccurred
                     45: {
                     46:     SRB                                *srb = NULL;
                     47: 
                     48:     while ( 1 )
                     49:     {
                     50:        [srbPendingQLock lock];
                     51: 
                     52:        if ( queue_empty(&srbPendingQ) )
                     53:        {
                     54:           [srbPendingQLock unlock];
                     55:            break;
                     56:        }
                     57:        queue_remove_first( &srbPendingQ, srb, SRB *, srbQ );
                     58: 
                     59:        [srbPendingQLock unlock];
                     60: 
                     61:     
                     62:         /*
                     63:          * If we are in the quiet period after a SCSI Bus reset, then reject new SRBs. In
                     64:          * general the client thread processing will block new SRBs, however, some may have
                     65:          * been on the IOThread's SRB queue when the reset occurred.
                     66:          */
                     67:         if ( resetQuiesceTimer )
                     68:         {
                     69:             srb->srbSCSIResult = SR_IOST_RESET;
                     70:             [srb->srbCmdLock unlockWith: ksrbCmdComplete];  
                     71:             continue;
                     72:         }
                     73: 
                     74:         switch ( srb->srbCmd )
                     75:         {
                     76:             /*
                     77:              * For a SCSI CDB request, stuff the physical address of the SRB's  Nexus struct into a
                     78:              * mailbox and signal the Symbios script engine.
                     79:              */
                     80:             case ksrbCmdExecuteReq:
                     81:                 srb->nexus.targetParms.scntl3Reg = adapter->targetClocks[srb->target].scntl3Reg;
                     82:                 srb->nexus.targetParms.sxferReg  = adapter->targetClocks[srb->target].sxferReg;
                     83: 
                     84:                 adapter->nexusPtrsVirt[srb->nexus.tag] = &srb->nexus;
                     85:                 adapter->nexusPtrsPhys[srb->nexus.tag] = (Nexus *)EndianSwap32( (u_int32_t)&srb->srbPhys->nexus );
                     86:                 adapter->schedMailBox[mailBoxIndex++]  = (Nexus *)EndianSwap32 ( (u_int32_t)&srb->srbPhys->nexus );
                     87: 
                     88:                 [self Sym8xxSignalScript: srb];
                     89:                 break;
                     90: 
                     91:             case ksrbCmdResetSCSIBus:
                     92:                 [self Sym8xxSCSIBusReset: srb];
                     93:                 break;
                     94:            
                     95:             case ksrbCmdAbortReq:
                     96:            case ksrbCmdBusDevReset:
                     97:                 [self Sym8xxAbortBdr: srb];
                     98:                 break;
                     99: 
                    100:             default:
                    101:                 ; 
                    102:         }         
                    103:     }
                    104: }
                    105: 
                    106: 
                    107: /*-----------------------------------------------------------------------------*
                    108:  * Interrupts from the Symbios chipset are dispatched here at task time under the
                    109:  * IOThread's context.
                    110:  *-----------------------------------------------------------------------------*/
                    111: - (void) interruptOccurred
                    112: {
                    113:     do
                    114:     {
                    115:         /* 
                    116:          * The chipset's ISTAT reg gives us the general interrupting condiditions,
                    117:          * with DSTAT and SIST providing more detailed information.
                    118:          */
                    119:         istatReg = Sym8xxReadRegs( chipBaseAddr, ISTAT, ISTAT_SIZE );
                    120: 
                    121:         /* The INTF bit in ISTAT indicates that the script is signalling the driver
                    122:          * that its IODone mailbox is full and that we should process a completed
                    123:          * request. The script continues to run after posting this interrupt unlike 
                    124:          * other chipset interrupts which require the driver to restart the script
                    125:          * engine.
                    126:          */
                    127:         if ( istatReg & INTF )
                    128:         {
                    129:             Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, istatReg );
                    130:             [self Sym8xxProcessIODone];
                    131:         }
                    132: 
                    133:         /*
                    134:          * Handle remaining interrupting conditions
                    135:          */  
                    136:         if ( istatReg & (SIP | DIP) )
                    137:         {
                    138:             [self Sym8xxProcessInterrupt];    
                    139:         }
                    140:     }
                    141:     while ( istatReg & (SIP | DIP | INTF) );
                    142: 
                    143:     [self enableAllInterrupts];
                    144: 
                    145: }
                    146: 
                    147: /*-----------------------------------------------------------------------------*
                    148:  * Process a request posted in the script's IODone mailbox.
                    149:  *
                    150:  *-----------------------------------------------------------------------------*/
                    151: - (void) Sym8xxProcessIODone
                    152: {
                    153:     SRB                                *srb;
                    154:     Nexus                      *nexus;
                    155:     IODoneMailBox              *pMailBox;
                    156:     
                    157:  
                    158:     /*
                    159:      * The IODone mailbox contains an index into our Nexus pointer tables.
                    160:      *
                    161:      * The Nexus struct is part of the SRB so we can get our SRB address
                    162:      * by subtracting the offset of the Nexus struct in the SRB.
                    163:      */
                    164:     pMailBox = (IODoneMailBox *)&SCRIPT_VAR(R_ld_IOdone_mailbox);
                    165:     nexus = adapter->nexusPtrsVirt[pMailBox->nexus];        
                    166:     srb   = (SRB *)((u_int32_t)nexus - offsetof(SRB, nexus));    
                    167: 
                    168:     /*
                    169:      * If there was no request sense performed, then update the transfer
                    170:      * counts in the SRB.
                    171:      */
                    172:     if ( srb->srbState == ksrbStateCDBDone  )
                    173:     {
                    174:         [self Sym8xxUpdateXferOffset: srb];
                    175:     }
                    176: 
                    177:     /* 
                    178:      * Clear the completed Nexus pointer from our tables and clear the
                    179:      * IODone mailbox.
                    180:      */
                    181:     adapter->nexusPtrsVirt[pMailBox->nexus] = (Nexus *) -1;
                    182:     adapter->nexusPtrsPhys[pMailBox->nexus] = (Nexus *) -1;
                    183:     SCRIPT_VAR(R_ld_IOdone_mailbox)       = 0;
                    184: 
                    185:     /*
                    186:      * Don't ask why we need to do this -- we shouldn't if the Indirect SCSI
                    187:      * drivers worked properly!
                    188:      * 
                    189:      */
                    190:     if ( nexus->cdbData.cdb_opcode == C6OP_INQUIRY )
                    191:     {
                    192:         [self Sym8xxCheckInquiryData: srb];
                    193:     }
                    194: 
                    195:     /*
                    196:      * Wake up the client's thread to do post-processing
                    197:      */
                    198:     [srb->srbCmdLock unlockWith: ksrbCmdComplete];  
                    199: }
                    200: 
                    201: /*-----------------------------------------------------------------------------*
                    202:  * General script interrupt processing
                    203:  *
                    204:  *-----------------------------------------------------------------------------*/
                    205: - (void) Sym8xxProcessInterrupt
                    206: {
                    207:     SRB                        *srb            = NULL;
                    208:     Nexus              *nexus          = NULL;
                    209:     u_int32_t          nexusIndex;
                    210:     u_int32_t          scriptPhase;
                    211:     u_int32_t          fifoCnt         = 0;
                    212:     u_int32_t          dspsReg         = 0;
                    213:     u_int32_t          dspReg          = 0;
                    214: 
                    215: 
                    216:     /*
                    217:      * Read DSTAT/SIST regs to determine why the script stopped.
                    218:      */
                    219:     dstatReg = Sym8xxReadRegs( chipBaseAddr,  DSTAT, DSTAT_SIZE );
                    220:     IODelay(5);
                    221:     sistReg =  Sym8xxReadRegs( chipBaseAddr,  SIST,  SIST_SIZE );
                    222: 
                    223: //  kprintf( "SCSI(Symbios8xx): SIST = %04x DSTAT = %02x\n\r", sistReg, dstatReg  );
                    224: 
                    225:     /*
                    226:      * This Script var tells us what the script thinks it was doing when the interrupt occurred.
                    227:      */
                    228:     scriptPhase = EndianSwap32( SCRIPT_VAR(R_ld_phase_flag) );
                    229: 
                    230:     /*
                    231:      * SCSI Bus reset detected 
                    232:      *
                    233:      * Clean up the carnage.     
                    234:      * Note: This may be either an adapter or target initiated reset.
                    235:      */
                    236:     if ( sistReg & RSTI )
                    237:     {
                    238:         [self Sym8xxProcessSCSIBusReset];
                    239:         return;
                    240:     }
                    241: 
                    242:     /*
                    243:      * Calculate our current SRB/Nexus.
                    244:      *
                    245:      * Read a script var to determine the index of the nexus it was processing
                    246:      * when the interrupt occurred. The script will invalidate the index if there
                    247:      * is no target currently connected or the script cannot determine which target
                    248:      * has reconnected.
                    249:      */
                    250:     nexusIndex = EndianSwap32(SCRIPT_VAR(R_ld_nexus_index));
                    251:     if ( nexusIndex >= MAX_SCSI_TAG )
                    252:     {
                    253:         [self Sym8xxProcessNoNexus];
                    254:         return;
                    255:     }
                    256:     nexus  = adapter->nexusPtrsVirt[nexusIndex];        
                    257:     if ( nexus == (Nexus *) -1 )
                    258:     {
                    259:         [self Sym8xxProcessNoNexus];
                    260:         return;
                    261:     }
                    262:     srb = (SRB *)((u_int32_t)nexus - offsetof(SRB, nexus));  
                    263: 
                    264:     scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_phase_handler];
                    265:    
                    266:     /*   
                    267:      * Parity and SCSI Gross Errors.
                    268:      *
                    269:      * Abort the current connection. The abort completion will trigger
                    270:      * clean-up of the current SRB/Nexus.
                    271:      */
                    272:     if ( sistReg & PAR )
                    273:     {  
                    274:          srb->srbSCSIResult = SR_IOST_PARITY;
                    275:          [self Sym8xxAbortCurrent: srb];
                    276:     }
                    277: 
                    278:     else if ( sistReg & SGE )
                    279:     {
                    280:          srb->srbSCSIResult = SR_IOST_BV;
                    281:          [self Sym8xxAbortCurrent: srb];
                    282:     }
                    283:        
                    284:     /*
                    285:      * Unexpected disconnect. 
                    286:      *
                    287:      * If we were currently trying to abort this connection then mark the abort
                    288:      * as completed. For all cases clean-up and wake-up the client thread.
                    289:      */ 
                    290:     else if ( sistReg & UDC )
                    291:     {
                    292:         if ( srb->srbSCSIResult == SR_IOST_GOOD )
                    293:         {
                    294:             srb->srbSCSIResult = SR_IOST_BV;
                    295:         }
                    296:         adapter->nexusPtrsVirt[nexusIndex] = (Nexus *) -1;
                    297:         adapter->nexusPtrsPhys[nexusIndex] = (Nexus *) -1;
                    298: 
                    299:         if ( scriptPhase == A_kphase_ABORT_CURRENT )
                    300:         {
                    301:             abortCurrentSRB = NULL;
                    302:         }
                    303: 
                    304:         [srb->srbCmdLock unlockWith: ksrbCmdComplete];  
                    305: 
                    306:         scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_select_phase];
                    307:     }
                    308: 
                    309:     /*
                    310:      * Phase Mis-match
                    311:      *
                    312:      * If we are in MsgOut phase then calculate how much of the message we sent. For
                    313:      * now, however, we dont handle the target rejecting messages, so the request is aborted.
                    314:      *
                    315:      * If we are in DataIn/DataOut phase. We update the SRB/Nexus with our current data 
                    316:      * pointers.
                    317:      */
                    318:     else if ( sistReg & MA )
                    319:     {
                    320:         if ( scriptPhase == A_kphase_MSG_OUT )
                    321:         {
                    322:             srb->srbMsgResid = [self Sym8xxCheckFifo:srb FifoCnt:&fifoCnt];
                    323:             nexus->msg.ppData   = EndianSwap32( EndianSwap32(nexus->msg.ppData) + EndianSwap32(nexus->msg.length) 
                    324:                                          - srb->srbMsgResid );
                    325:             nexus->msg.length   = EndianSwap32( srb->srbMsgResid );
                    326: 
                    327:             [self Sym8xxAbortCurrent: srb];
                    328:         }
                    329:         else if ( (scriptPhase == A_kphase_DATA_OUT) || (scriptPhase == A_kphase_DATA_IN) )
                    330:         {
                    331:             [self Sym8xxAdjustDataPtrs:srb Nexus:nexus];
                    332:         }
                    333:         else
                    334:         {
                    335: //          kprintf("SCSI(Symbios8xx): Unexpected phase mismatch - scriptPhase = %08x\n\r", scriptPhase);
                    336:             srb->srbSCSIResult = SR_IOST_BV;
                    337:             [self Sym8xxAbortCurrent: srb];
                    338:         }
                    339: 
                    340:         [self Sym8xxClearFifo];
                    341:     }
                    342:     
                    343:     /*
                    344:      * Selection Timeout.
                    345:      *
                    346:      * Clean-up the current request.
                    347:      */
                    348:     else if ( sistReg & STO )
                    349:     {
                    350:         srb->srbSCSIResult = SR_IOST_SELTO;
                    351: 
                    352:         adapter->nexusPtrsVirt[nexusIndex] = (Nexus *) -1;
                    353:         adapter->nexusPtrsPhys[nexusIndex] = (Nexus *) -1;
                    354:         SCRIPT_VAR(R_ld_IOdone_mailbox)    = 0;
                    355: 
                    356:         [srb->srbCmdLock unlockWith: ksrbCmdComplete];  
                    357: 
                    358:         scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_select_phase];
                    359:     }
                    360:         
                    361:     /*
                    362:      * Handle script initiated interrupts
                    363:      */
                    364:     else if ( dstatReg & SIR )
                    365:     {
                    366:         dspsReg = Sym8xxReadRegs( chipBaseAddr, DSPS, DSPS_SIZE );
                    367: 
                    368:         switch ( dspsReg )
                    369:         {
                    370:             /* 
                    371:              * Non-zero SCSI status
                    372:              *
                    373:              * Send request sense CDB or complete request depending on SCSI status value
                    374:              */
                    375:             case A_status_error:
                    376:                 if ( [self Sym8xxProcessStatus:srb] == NO )
                    377:                 {
                    378:                     [self Sym8xxProcessIODone];
                    379:                 }
                    380:                 break;
                    381:              
                    382:             /*
                    383:              * Received SDTR/WDTR message from target.
                    384:              *
                    385:              * Prepare reply message if we requested negotiation. Otherwise reject
                    386:              * target initiated negotiation.
                    387:              */
                    388:            case A_negotiateSDTR:
                    389:                 [self Sym8xxNegotiateSDTR:srb Nexus: nexus];
                    390:                 break;
                    391: 
                    392:            case A_negotiateWDTR:
                    393:                 [self Sym8xxNegotiateWDTR:srb Nexus: nexus];
                    394:                 break;
                    395: 
                    396:             /*
                    397:              * Partial SG List completed.
                    398:              *
                    399:              * Refresh the list from the remaining addresses to be transfered and set the
                    400:              * script engine to branch into the list.
                    401:              */
                    402:             case A_sglist_complete:
                    403:                 [self Sym8xxUpdateSGList:srb];
                    404:                 scriptRestartAddr = (u_int32_t)&srb->srbPhys->nexus.sgListData[2];
                    405:                 break;
                    406: 
                    407:             /*
                    408:              * Completed abort request
                    409:              *
                    410:              * Clean-up the aborted request.
                    411:              */
                    412:            case A_abort_current:       
                    413:                 if ( srb->srbSCSIResult == SR_IOST_GOOD )
                    414:                 {
                    415:                     srb->srbSCSIResult = SR_IOST_BV;
                    416:                 }
                    417: 
                    418:                 adapter->nexusPtrsVirt[nexusIndex] = (Nexus *) -1;
                    419:                 adapter->nexusPtrsPhys[nexusIndex] = (Nexus *) -1; 
                    420: 
                    421:                 abortCurrentSRB = NULL;
                    422: 
                    423:                 [srb->srbCmdLock unlockWith: ksrbCmdComplete];  
                    424: 
                    425:                 scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_select_phase];
                    426:                 break;
                    427:     
                    428:             /*
                    429:              * Script detected protocol errors
                    430:              *
                    431:              * Abort the current request.
                    432:              */
                    433:             case A_unknown_msg_reject:
                    434:             case A_unknown_phase:
                    435:             case A_unexpected_msg:
                    436:             case A_unexpected_ext_msg:
                    437:                 srb->srbSCSIResult = SR_IOST_TABT;
                    438:                 [self Sym8xxAbortCurrent: srb];
                    439:                 break;
                    440: 
                    441:             default:
                    442:                 kprintf( "SCSI(Symbios8xx): Unknown Script Int = %08x\n\r", dspsReg );
                    443:                 srb->srbSCSIResult = SR_IOST_INT;
                    444:                 [self Sym8xxAbortCurrent: srb];
                    445:         }
                    446:     }
                    447: 
                    448:     /*
                    449:      * Illegal script instruction.
                    450:      *
                    451:      * We're toast! Abort the current request and hope for the best!
                    452:      */
                    453:     else if ( dstatReg & IID )
                    454:     {
                    455:         dspReg  = Sym8xxReadRegs( chipBaseAddr, DSP, DSP_SIZE );
                    456: 
                    457:         kprintf("SCSI(Symbios8xx): Illegal script instruction - dsp = %08x srb=%08x\n\r", dspReg, (u_int32_t)srb );
                    458: 
                    459:         srb->srbSCSIResult = SR_IOST_INT;
                    460:         [self Sym8xxAbortCurrent: srb];
                    461:     }
                    462: 
                    463:     if ( scriptRestartAddr )
                    464:     {
                    465:         Sym8xxWriteRegs( chipBaseAddr, DSP, DSP_SIZE, scriptRestartAddr );
                    466:     }
                    467: }    
                    468: 
                    469: /*-----------------------------------------------------------------------------*
                    470:  * Handle non-zero SCSI status
                    471:  *
                    472:  * Returns: 
                    473:  *    NO  - Clean-up request now.
                    474:  *    YES - Wait for request sense to complete.
                    475:  *
                    476:  * This routine filter's out BUSY and more arcane SCSI status conditions,
                    477:  * leaving CHECK_CONDITION, for which it set's up a request sense operation.
                    478:  *
                    479:  *-----------------------------------------------------------------------------*/
                    480: - (BOOL) Sym8xxProcessStatus: (SRB *) srb;
                    481: {
                    482:     IODoneMailBox              *pMailBox;
                    483: 
                    484:     scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_select_phase];
                    485:  
                    486:     pMailBox = (IODoneMailBox *)&SCRIPT_VAR(R_ld_IOdone_mailbox);
                    487: 
                    488:     /*
                    489:      * If a previous request sense failed, then clean-up the request now.
                    490:      */
                    491:     if ( srb->srbState != ksrbStateCDBDone )
                    492:     {
                    493:         if ( srb->srbSCSIResult == SR_IOST_GOOD )
                    494:         {
                    495:             srb->srbSCSIResult = SR_IOST_CHKSNV;
                    496:         }
                    497:         return NO;
                    498:     }
                    499: 
                    500:     /*
                    501:      * Update the SRB with our byte transferred count and SCSI status.
                    502:      * This information needs to be captured before we issue the request
                    503:      * sense.
                    504:      */
                    505:     srb->srbSCSIStatus = pMailBox->status;
                    506: 
                    507:     [self Sym8xxUpdateXferOffset: srb];
                    508: 
                    509:     if ( pMailBox->status != STAT_CHECK )
                    510:     {
                    511:         srb->srbSCSIResult = ST_IOST_BADST;
                    512:         return NO;
                    513:     }
                    514:     if ( srb->senseData == NULL )
                    515:     {
                    516:         srb->srbSCSIResult = SR_IOST_CHKSNV;
                    517:         return NO;
                    518:     }
                    519: 
                    520:     [self Sym8xxIssueRequestSense: srb];
                    521: 
                    522:     return YES;
                    523: }
                    524: 
                    525: /*-----------------------------------------------------------------------------*
                    526:  * Prepare request sense request.
                    527:  *
                    528:  *-----------------------------------------------------------------------------*/
                    529: - (void) Sym8xxIssueRequestSense:(SRB *) srb
                    530: {
                    531:     IODoneMailBox              *pMailBox;
                    532:     u_int32_t                  reqSenseMailBox;
                    533: 
                    534:     pMailBox = (IODoneMailBox *)&SCRIPT_VAR(R_ld_IOdone_mailbox);
                    535: 
                    536:     /*
                    537:      * We put the request sense Nexus in the last completed script mailbox and
                    538:      * back-up the script's mailbox pointer.
                    539:      */
                    540:     reqSenseMailBox = (u_int8_t)(EndianSwap32(SCRIPT_VAR(R_ld_counter)) - 1);
                    541:     SCRIPT_VAR(R_ld_counter) = EndianSwap32( reqSenseMailBox );
                    542: 
                    543:     srb->srbTimeout = kReqSenseTimeoutMS / kSCSITimerIntervalMS + 1; 
                    544: 
                    545:     srb->srbState      = ksrbStateReqSenseDone;
                    546:     srb->srbSCSIResult = SR_IOST_CHKSV;
                    547: 
                    548:     /*
                    549:      * Reuse the original Nexus struct. The original CDB is not preserved. The
                    550:      * original status and transfer counts and tag are kept in the SRB.
                    551:      */
                    552:     bzero( &srb->nexus.cdbData, 6 );
                    553:     srb->nexus.cdbData.cdb_c6.c6_opcode = C6OP_REQSENSE;
                    554:     srb->nexus.cdbData.cdb_c6.c6_lun    = srb->lun;
                    555:     srb->nexus.cdbData.cdb_c6.c6_len    = srb->senseDataLength;
                    556:     srb->nexus.cdb.length               = EndianSwap32( 6 );
                    557: 
                    558:     /* 
                    559:      * Force renegotiation on request sense.
                    560:      */
                    561:     targets[srb->target].flags &= ~(kTFXferSync | kTFXferWide16);
                    562:     srb->srbRequestFlags       &= ~(ksrbRFCmdQueueAllowed | ksrbRFDisconnectAllowed);
                    563:     [self Sym8xxCalcMsgs:srb];
                    564: 
                    565:     /*
                    566:      * Create a new SG List for the request sense data
                    567:      *
                    568:      */
                    569:     srb->xferOffset        = 0;
                    570:     srb->xferOffsetPrev    = 0;
                    571:     srb->xferClient        = IOVmTaskSelf();
                    572:     srb->xferBuffer        = srb->senseData;
                    573:     srb->xferCount         = srb->senseDataLength;
                    574:     srb->directionMask     = 0x01000000;
                    575:     srb->nexus.ppSGList    = (SGEntry *)EndianSwap32((u_int32_t)&srb->srbPhys->nexus.sgListData[2]);
                    576:     [self Sym8xxUpdateSGList: srb];
                    577: 
                    578:     /*
                    579:      * If the original request was using cmd-queuing, we clean-up the original tagged request
                    580:      * and convert it to a non-tagged request sense.
                    581:      */
                    582:     if ( srb->nexus.tag >= MIN_SCSI_TAG )
                    583:     {
                    584:         adapter->nexusPtrsVirt[pMailBox->nexus] = (Nexus *) -1;
                    585:         adapter->nexusPtrsPhys[pMailBox->nexus] = (Nexus *) -1;
                    586: 
                    587:         srb->nexus.tag  = (srb->target << 3) | srb->lun;
                    588:         adapter->nexusPtrsVirt[srb->nexus.tag] = &srb->nexus;
                    589:         adapter->nexusPtrsPhys[srb->nexus.tag] = (Nexus *)EndianSwap32( (u_int32_t)&srb->srbPhys->nexus );
                    590:     }
                    591: 
                    592:     adapter->schedMailBox[reqSenseMailBox]  = (Nexus *)EndianSwap32 ( (u_int32_t)&srb->srbPhys->nexus );
                    593: 
                    594:     [self Sym8xxSignalScript: srb];
                    595: 
                    596:     SCRIPT_VAR(R_ld_IOdone_mailbox) = 0;
                    597: }
                    598: 
                    599: /*-----------------------------------------------------------------------------*
                    600:  * Current Data Pointer calculations
                    601:  * 
                    602:  * To do data transfers the driver generates a list of script instructions 
                    603:  * in system storage to deliver data to the requested physical addresses. The
                    604:  * script branches to the list when the target enters data transfer phase.
                    605:  *
                    606:  * When the target changes phase during a data transfer, data is left trapped
                    607:  * inside the various script engine registers. This routine determines how much
                    608:  * data was not actually transfered to/from the target and generates a new
                    609:  * S/G List entry for the partial transfer and a branch back into the original
                    610:  * S/G list. These script instructions are stored in two reserved slots at the
                    611:  * top of the original S/G List.
                    612:  *
                    613:  *-----------------------------------------------------------------------------*/
                    614: - (void) Sym8xxAdjustDataPtrs:(SRB *) srb Nexus:(Nexus *) nexus
                    615: {
                    616:     u_int32_t          i;
                    617:     u_int32_t          sgResid;
                    618:     u_int32_t          fifoCnt;
                    619:     u_int32_t          dspReg;
                    620:     u_int32_t          sgDone;
                    621:     u_int8_t           scntl2Reg;
                    622:     Nexus              *nexusPhys;
                    623: 
                    624:     /*
                    625:      * Determine SG element residual
                    626:      *
                    627:      * This routine returns how much of the current S/G List element the 
                    628:      * script was processing remains to be sent/received. All the information
                    629:      * required to do this is stored in the script engine's registers.
                    630:      */
                    631:     sgResid = [self Sym8xxCheckFifo:srb FifoCnt:&fifoCnt];
                    632: 
                    633:     /*
                    634:      * Determine which script instruction in our SGList we were executing when
                    635:      * the target changed phase.
                    636:      *
                    637:      * The script engine's dspReg tells us where the script thinks it was. Based
                    638:      * on the physical address of our current SRB/Nexus we can calculate
                    639:      * an index into our S/G List.  
                    640:      */
                    641:     dspReg  = Sym8xxReadRegs( chipBaseAddr, DSP, DSP_SIZE );
                    642: 
                    643:     i = ((dspReg - (u_int32_t)srb->srbPhys->nexus.sgListData) / sizeof(SGEntry)) - 1;
                    644:        
                    645:     if ( i > MAX_SGLIST_ENTRIES-1 )
                    646:     {
                    647:        kprintf("SCSI(Symbios8xx): Bad sgListIndex\n\r");
                    648:        [self Sym8xxAbortCurrent: srb];
                    649:        return;
                    650:     }
                    651: 
                    652:     /* 
                    653:      * Wide/odd-byte transfers.
                    654:      *     
                    655:      * When dealing with Wide data transfers, if a S/G List ends with an odd-transfer count, then a
                    656:      * valid received data byte is left in the script engine's SWIDE register. The least painful way
                    657:      * to recover this byte is to construct a small script thunk to transfer one additional byte. The
                    658:      * script will automatically draw this byte from the SWIDE register rather than the SCSI bus.
                    659:      * The script thunk then branches back to script's PhaseHandler entrypoint.
                    660:      * 
                    661:      */
                    662:     nexusPhys = &srb->srbPhys->nexus;
                    663: 
                    664:     scntl2Reg = Sym8xxReadRegs( chipBaseAddr, SCNTL2, SCNTL2_SIZE );
                    665:     if ( scntl2Reg & WSR )
                    666:     {
                    667:         adapter->xferSWideInst[0] = EndianSwap32( srb->directionMask | 1 );
                    668:         adapter->xferSWideInst[1] = nexus->sgListData[i].physAddr;
                    669:         adapter->xferSWideInst[2] = EndianSwap32( 0x80080000 );
                    670:         adapter->xferSWideInst[3] = EndianSwap32( (u_int32_t)&chipRamAddrPhys[Ent_phase_handler] );
                    671: 
                    672:         scriptRestartAddr = (u_int32_t) adapterPhys->xferSWideInst;
                    673:         
                    674:         /*
                    675:          * Note: There is an assumption here that the sgResid count will be > 1. It appears 
                    676:          *       that the script engine does not generate a phase-mismatch interrupt until 
                    677:          *       we attempt to move > 1 byte from the SCSI bus and the only byte available is
                    678:          *       in SWIDE. 
                    679:          */        
                    680:         sgResid--;
                    681:     }
                    682: 
                    683:     /*
                    684:      * Calculate partial S/G List instruction and branch
                    685:      *
                    686:      * Fill in slots 0/1 of the SGList based on the SGList index (i) and SGList residual count
                    687:      * (sgResid) calculated above.
                    688:      *
                    689:      */
                    690:     sgDone  = (EndianSwap32( nexus->sgListData[i].length ) & 0x00ffffff) - sgResid;
                    691: 
                    692:     nexus->sgListData[0].length   = EndianSwap32( sgResid | srb->directionMask );
                    693:     nexus->sgListData[0].physAddr = EndianSwap32( EndianSwap32(nexus->sgListData[i].physAddr) + sgDone );
                    694:     /*
                    695:      * If a previously calculated SGList 0 entry was interrupted again, we dont need to calculate
                    696:      * a new branch address since the previous one is still valid.
                    697:      */
                    698:     if ( i != 0 )
                    699:     {
                    700:         nexus->sgListData[1].length   = EndianSwap32( 0x80080000 );
                    701:         nexus->sgListData[1].physAddr = EndianSwap32( (u_int32_t)&nexusPhys->sgListData[i+1] );
                    702:         nexus->sgNextIndex            = i + 1;
                    703:     }
                    704:     nexus->ppSGList = (SGEntry *)EndianSwap32( (u_int32_t) &nexusPhys->sgListData[0] );
                    705:  
                    706:     /*
                    707:      * The script sets this Nexus variable to non-zero each time it calls the driver generated
                    708:      * S/G list. This allows the driver's completion routines to differentiate between a successful
                    709:      * transfer vs no data transfer at all.
                    710:      */
                    711:     nexus->dataXferCalled = 0;
                    712: 
                    713:     return;
                    714: }
                    715: 
                    716: /*-----------------------------------------------------------------------------*
                    717:  * Determine SG element residual
                    718:  *
                    719:  * This routine returns how much of the current S/G List element the 
                    720:  * script was processing remains to be sent/received. All the information
                    721:  * required to do this is stored in the script engine's registers.
                    722:  *
                    723:  *-----------------------------------------------------------------------------*/
                    724: - (u_int32_t) Sym8xxCheckFifo: (SRB *) srb FifoCnt:(u_int32_t *)pfifoCnt
                    725: {
                    726:     BOOL               fSCSISend;
                    727:     BOOL               fXferSync;
                    728:     u_int32_t          scriptPhase     = 0;
                    729:     u_int32_t          dbcReg          = 0;
                    730:     u_int32_t          dfifoReg        = 0;
                    731:     u_int32_t          ctest5Reg       = 0;
                    732:     u_int8_t           sstat0Reg       = 0;
                    733:     u_int8_t           sstat1Reg       = 0;
                    734:     u_int8_t           sstat2Reg       = 0;
                    735:     u_int32_t          fifoCnt         = 0;
                    736:     u_int32_t          sgResid         = 0;
                    737: 
                    738:     scriptPhase = EndianSwap32( SCRIPT_VAR(R_ld_phase_flag) );
                    739: 
                    740:     fSCSISend =  (scriptPhase == A_kphase_DATA_OUT) || (scriptPhase == A_kphase_MSG_OUT);
                    741:  
                    742:     fXferSync =  ((scriptPhase == A_kphase_DATA_OUT) || (scriptPhase == A_kphase_DATA_IN)) 
                    743:                          && (srb->nexus.targetParms.sxferReg & 0x1F);  
                    744: 
                    745:     dbcReg = Sym8xxReadRegs( chipBaseAddr, DBC, DBC_SIZE ) & 0x00ffffff;
                    746: 
                    747:     if ( !(dstatReg & DFE) )
                    748:     {
                    749:         ctest5Reg = Sym8xxReadRegs( chipBaseAddr, CTEST5, CTEST5_SIZE );
                    750:         dfifoReg  = Sym8xxReadRegs( chipBaseAddr, DFIFO,  DFIFO_SIZE );
                    751: 
                    752:         if ( ctest5Reg & DFS )
                    753:         {
                    754:             fifoCnt = ((((ctest5Reg & 0x03) << 8) | dfifoReg) - dbcReg) & 0x3ff;
                    755:         }
                    756:         else
                    757:         {
                    758:             fifoCnt = (dfifoReg - dbcReg) & 0x7f;
                    759:         }
                    760:     }
                    761: 
                    762:     sstat0Reg = Sym8xxReadRegs( chipBaseAddr, SSTAT0, SSTAT0_SIZE );
                    763:     sstat2Reg = Sym8xxReadRegs( chipBaseAddr, SSTAT2, SSTAT2_SIZE );
                    764:  
                    765:     if ( fSCSISend )
                    766:     {    
                    767:         fifoCnt += (sstat0Reg & OLF )  ? 1 : 0;
                    768:         fifoCnt += (sstat2Reg & OLF1)  ? 1 : 0;
                    769: 
                    770:         if ( fXferSync )
                    771:         {
                    772:             fifoCnt += (sstat0Reg & ORF )  ? 1 : 0;
                    773:             fifoCnt += (sstat2Reg & ORF1)  ? 1 : 0;
                    774:         }
                    775:     }
                    776:     else
                    777:     {
                    778:         if ( fXferSync )
                    779:         {
                    780:             sstat1Reg = Sym8xxReadRegs( chipBaseAddr, SSTAT0, SSTAT0_SIZE );
                    781:             fifoCnt +=  (sstat1Reg >> 4) | (sstat2Reg & FF4);  
                    782:         }
                    783:         else
                    784:         {
                    785:             fifoCnt += (sstat0Reg & ILF )  ? 1 : 0;
                    786:             fifoCnt += (sstat2Reg & ILF1)  ? 1 : 0;
                    787:         }
                    788:     }   
                    789:     
                    790:     sgResid   = dbcReg + fifoCnt;
                    791:     *pfifoCnt = fifoCnt;
                    792: 
                    793:     return sgResid;
                    794: }
                    795: 
                    796: /*-----------------------------------------------------------------------------*
                    797:  * Calculate transfer counts.
                    798:  *
                    799:  * This routine updates srb->xferDone with the amount of data transferred
                    800:  * by the last S/G List executed.
                    801:  *
                    802:  *-----------------------------------------------------------------------------*/
                    803: - (void) Sym8xxUpdateXferOffset:(SRB *) srb
                    804: {
                    805:     u_int32_t          i;
                    806:     u_int32_t          xferOffset;
                    807: 
                    808:     /*
                    809:      * srb->xferOffset contains the client buffer offset INCLUDING the range
                    810:      * covered by the current SGList.
                    811:      */
                    812:     xferOffset = srb->xferOffset;
                    813: 
                    814:     /*
                    815:      * If script did not complete the current transfer list then we need to determine
                    816:      * how much of the list was completed.
                    817:      */
                    818:     if ( srb->nexus.dataXferCalled == 0 )
                    819:     {
                    820:         /* 
                    821:          * srb->xferOffsetPrev contains the client buffer offset EXCLUDING the
                    822:          * range covered by the current SGList.
                    823:          */
                    824:         xferOffset = srb->xferOffsetPrev;
                    825: 
                    826:         /*
                    827:          * Calculate bytes transferred for partially completed list.
                    828:          *
                    829:          * To calculate the amount of this list completed, we sum the residual amount
                    830:          * in SGList Slot 0 and the completed list elements 2 to sgNextIndex-1.
                    831:          */
                    832:         if ( srb->nexus.sgNextIndex != 0 )
                    833:         {
                    834:             xferOffset += EndianSwap32( srb->nexus.sgListData[srb->nexus.sgNextIndex-1].length )
                    835:                              - EndianSwap32( srb->nexus.sgListData[0].length );
                    836: 
                    837:             for ( i=2; i < srb->nexus.sgNextIndex-1; i++ )
                    838:             {
                    839:                 xferOffset += EndianSwap32( srb->nexus.sgListData[i].length ) & 0x00ffffff;
                    840:             }
                    841:         }
                    842:     }
                    843:     
                    844:     /*
                    845:      * The script leaves the result of any Ignore Wide Residual message received from the target
                    846:      * during the transfer.
                    847:      */
                    848:     xferOffset -= srb->nexus.wideResidCount;
                    849: 
                    850: 
                    851: #if 0
                    852:     {
                    853:         u_int32_t      resid = srb->xferOffset - xferOffset;
                    854:         if ( resid )
                    855:         {
                    856:             kprintf( "SCSI(Symbios8xx): Incomplete transfer - Req Count = %08x Act Count = %08x - srb = %08x\n\r", 
                    857:                     srb->xferCount, xferOffset, (u_int32_t)srb );
                    858:         }   
                    859:     }
                    860: #endif
                    861: 
                    862:     srb->xferDone = xferOffset;
                    863: }
                    864: 
                    865: /*-----------------------------------------------------------------------------*
                    866:  * No SRB/Nexus Processing.
                    867:  *
                    868:  * In some cases (mainly Aborts) not having a SRB/Nexus is normal. In other
                    869:  * cases it indicates a problem such a reconnection from a target that we
                    870:  * have no record of.
                    871:  *
                    872:  *-----------------------------------------------------------------------------*/
                    873: - (void) Sym8xxProcessNoNexus
                    874: {
                    875:     u_int32_t                  dspsReg;
                    876:     u_int32_t                  dspReg      = 0;
                    877:     u_int32_t                  scriptPhase = -1 ;
                    878: 
                    879:     scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_select_phase];
                    880: 
                    881:     dspsReg = Sym8xxReadRegs( chipBaseAddr, DSPS, DSPS_SIZE );
                    882: 
                    883:     scriptPhase = EndianSwap32( SCRIPT_VAR(R_ld_phase_flag) );
                    884: 
                    885:     /* 
                    886:      * If we were trying to abort or disconnect a target and the bus
                    887:      * is now free we consider the abort to have completed.
                    888:      */
                    889:     if ( sistReg & UDC ) 
                    890:     {
                    891:         if ( (scriptPhase == A_kphase_ABORT_MAILBOX) && abortSRB )
                    892:         {
                    893:             [abortSRB->srbCmdLock unlockWith: ksrbCmdComplete];
                    894:             abortSRB = (SRB *) NULL;  
                    895:             SCRIPT_VAR(R_ld_AbortBdr_mailbox) = 0;
                    896:         }         
                    897:         else if ( scriptPhase == A_kphase_ABORT_CURRENT )
                    898:         {
                    899:             abortCurrentSRB = NULL;
                    900:         }
                    901:     }
                    902:     /*
                    903:      * If we were trying to connect to a target to send it an abort message, and
                    904:      * we timed out, we consider the abort as completed.
                    905:      *
                    906:      * Note: In this case the target may be hung, but at least its not on the bus.
                    907:      */
                    908:     else if ( sistReg & STO )
                    909:     {
                    910:         if ( (scriptPhase == A_kphase_ABORT_MAILBOX) && abortSRB )
                    911:         {
                    912:             [abortSRB->srbCmdLock unlockWith: ksrbCmdComplete];
                    913:             abortSRB = (SRB *) NULL;  
                    914:             SCRIPT_VAR(R_ld_AbortBdr_mailbox) = 0;
                    915:         }         
                    916:     }     
                    917:     
                    918:     /*
                    919:      * If the script died, without a vaild nexusIndex, we abort anything that is currently
                    920:      * connected and hope for the best!
                    921:      */
                    922:     else if ( dstatReg & IID )
                    923:     {
                    924:         dspReg  = Sym8xxReadRegs( chipBaseAddr, DSP, DSP_SIZE );
                    925:         kprintf("SCSI(Symbios8xx): Illegal script instruction - dsp = %08x srb=0\n\r", dspReg );
                    926:         [self Sym8xxAbortCurrent: (SRB *) -1];
                    927:     }
                    928: 
                    929:     /*
                    930:      * Script signaled conditions
                    931:      */
                    932:     else if ( dstatReg & SIR )
                    933:     {
                    934:         switch ( dspsReg )
                    935:         {
                    936:             case A_abort_current:
                    937:                 abortCurrentSRB = NULL;
                    938:                 break;
                    939:               
                    940:             case A_abort_mailbox:
                    941:                 [abortSRB->srbCmdLock unlockWith: ksrbCmdComplete];
                    942:                 abortSRB = (SRB *) NULL;  
                    943:                 SCRIPT_VAR(R_ld_AbortBdr_mailbox) = 0;
                    944:                 break;
                    945:            
                    946:             default:
                    947:                [self Sym8xxAbortCurrent: (SRB *)-1];
                    948:         }
                    949:     }             
                    950:     else
                    951:     {
                    952:         [self Sym8xxAbortCurrent: (SRB *)-1];
                    953:     }
                    954: 
                    955:     if ( scriptRestartAddr )
                    956:     {
                    957:         Sym8xxWriteRegs( chipBaseAddr, DSP, DSP_SIZE, scriptRestartAddr );
                    958:     }
                    959: }
                    960:  
                    961: 
                    962: /*-----------------------------------------------------------------------------*
                    963:  * Abort currently connected target.
                    964:  *
                    965:  *-----------------------------------------------------------------------------*/
                    966: - (void) Sym8xxAbortCurrent:(SRB *)srb
                    967: {
                    968:     if ( abortCurrentSRB )
                    969:     {
                    970:         if ( abortCurrentSRB != srb )
                    971:         {
                    972: //          kprintf("SCSI(Symbios8xx): Multiple abort immediate SRBs - resetting\n\r");
                    973:             [self Sym8xxSCSIBusReset: (SRB *)NULL];
                    974:         }
                    975:         return;
                    976:     }
                    977:    
                    978:     abortCurrentSRB        = srb;
                    979:     abortCurrentSRBTimeout = kAbortTimeoutMS / kSCSITimerIntervalMS + 1; 
                    980: 
                    981:     /*
                    982:      * Issue abort or abort tag depending on whether the is a tagged request
                    983:      */
                    984:     SCRIPT_VAR(R_ld_AbortCode) = EndianSwap32( ((srb != (SRB *)-1) && (srb->nexus.tag >= MIN_SCSI_TAG)) ? 0x0d : 0x06 );
                    985:     scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_issueAbort_BDR];
                    986: 
                    987:     [self Sym8xxClearFifo];
                    988: }
                    989: 
                    990: /*-----------------------------------------------------------------------------*
                    991:  * This routine clears the script engine's SCSI and DMA fifos.
                    992:  *
                    993:  *-----------------------------------------------------------------------------*/
                    994: - (void) Sym8xxClearFifo
                    995: {
                    996:     u_int8_t           ctest3Reg;
                    997:     u_int8_t           stest2Reg;
                    998:     u_int8_t           stest3Reg;
                    999: 
                   1000:     stest2Reg  = Sym8xxReadRegs( chipBaseAddr, STEST2, STEST2_SIZE );
                   1001:     if ( stest2Reg & ROF )
                   1002:     {
                   1003:         Sym8xxWriteRegs( chipBaseAddr, STEST2, STEST2_SIZE, stest2Reg );
                   1004:     }
                   1005: 
                   1006:     ctest3Reg = Sym8xxReadRegs( chipBaseAddr, CTEST3, CTEST3_SIZE );
                   1007:     ctest3Reg |= CLF;
                   1008:     Sym8xxWriteRegs( chipBaseAddr, CTEST3, CTEST3_SIZE, ctest3Reg );
                   1009: 
                   1010:     stest3Reg = Sym8xxReadRegs( chipBaseAddr, STEST3, STEST3_SIZE );
                   1011:     stest3Reg |= CSF;
                   1012:     Sym8xxWriteRegs( chipBaseAddr,STEST3, STEST3_SIZE, stest3Reg );
                   1013: 
                   1014:     do
                   1015:     {
                   1016:         ctest3Reg = Sym8xxReadRegs( chipBaseAddr, CTEST3, CTEST3_SIZE );
                   1017:         stest2Reg = Sym8xxReadRegs( chipBaseAddr, STEST3, STEST3_SIZE );
                   1018:         stest3Reg = Sym8xxReadRegs( chipBaseAddr, STEST3, STEST3_SIZE );
                   1019:     } 
                   1020:     while( (ctest3Reg & CLF) || (stest3Reg & CSF) || (stest2Reg & ROF) );            
                   1021: }
                   1022: 
                   1023: /*-----------------------------------------------------------------------------*
                   1024:  * This routine processes the target's response to our SDTR message.
                   1025:  * 
                   1026:  * We calculate the values for the script engine's timing registers
                   1027:  * for synchronous registers, and update our tables indicating that
                   1028:  * requested data transfer mode is in-effect.
                   1029:  *
                   1030:  *-----------------------------------------------------------------------------*/
                   1031: - (void) Sym8xxNegotiateSDTR:(SRB *) srb Nexus:(Nexus *)nexus
                   1032: {
                   1033:     u_int32_t          x;
                   1034:     u_int8_t           *pMsg;
                   1035:     u_int32_t          syncPeriod;
                   1036:     
                   1037:     /*
                   1038:      * If we were not negotiating, the send MsgReject to targets negotiation
                   1039:      * attempt.
                   1040:      */
                   1041:     if ( !(srb->srbRequestFlags & ksrbRFNegotiateSync) )
                   1042:     {
                   1043:         [self Sym8xxSendMsgReject: srb];
                   1044:         return;
                   1045:     }
                   1046: 
                   1047:     /* 
                   1048:      * Get pointer to negotiation message received from target.
                   1049:      */
                   1050:     pMsg = (u_int8_t *) &SCRIPT_VAR(R_ld_message);
                   1051: 
                   1052:     /*
                   1053:      * The target's SDTR response contains the (transfer period / 4).
                   1054:      *
                   1055:      * We set our sync clock divisor to 1, 2, or 4 giving us a clock rates
                   1056:      * of:
                   1057:      *     80Mhz (Period = 12.5ns), 
                   1058:      *     40Mhz (Period = 25.0ns)
                   1059:      *     20Mhz (Period = 50.0ns) 
                   1060:      *
                   1061:      * This is further divided by the value in the sxfer reg to give us the final sync clock rate.
                   1062:      *
                   1063:      * The requested sync period is scaled up by 1000 and the clock periods are scaled up by 10
                   1064:      * giving a result scaled up by 100. This is rounded-up and converted to sxfer reg values.
                   1065:      */
                   1066:     syncPeriod = (u_int32_t)pMsg[3] << 2;
                   1067:     if ( syncPeriod < 100 )
                   1068:     {
                   1069:         nexus->targetParms.scntl3Reg |= SCNTL3_INIT_875_ULTRA;
                   1070:         x = (syncPeriod * 1000) / 125;
                   1071:     }
                   1072:     else if ( syncPeriod < 200 )
                   1073:     {
                   1074:         nexus->targetParms.scntl3Reg  |= SCNTL3_INIT_875_FAST;
                   1075:         x = (syncPeriod * 1000) / 250;
                   1076:     }
                   1077:     else 
                   1078:     {
                   1079:         nexus->targetParms.scntl3Reg  |= SCNTL3_INIT_875_SLOW;
                   1080:         x = (syncPeriod * 1000) / 500;
                   1081:     }
                   1082:            
                   1083:     if ( x % 100 ) x += 100;
                   1084:     
                   1085:     /*
                   1086:      * sxferReg  Bits: 5-0 - Transfer offset
                   1087:      *                 7-6 - Sync Clock Divisor (0 = sync clock / 4)
                   1088:      */
                   1089:     nexus->targetParms.sxferReg = ((x/100 - 4) << 5) | pMsg[4];
                   1090: 
                   1091:     /*
                   1092:      * Update our per-target tables and set-up the hardware regs for this request.
                   1093:      *
                   1094:      * On reconnection attempts, the script will use our per-target tables to set-up
                   1095:      * the scntl3 and sxfer registers in the script engine.
                   1096:      */
                   1097:     adapter->targetClocks[srb->target].sxferReg  = nexus->targetParms.sxferReg;
                   1098:     adapter->targetClocks[srb->target].scntl3Reg = nexus->targetParms.scntl3Reg;
                   1099: 
                   1100:     Sym8xxWriteRegs( chipBaseAddr, SCNTL3, SCNTL3_SIZE, nexus->targetParms.scntl3Reg );
                   1101:     Sym8xxWriteRegs( chipBaseAddr, SXFER,  SXFER_SIZE,  nexus->targetParms.sxferReg );
                   1102: 
                   1103:     targets[srb->target].flags |= kTFXferSync;
                   1104: 
                   1105:     scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_clearACK];
                   1106: }
                   1107:    
                   1108: /*-----------------------------------------------------------------------------*
                   1109:  * This routine processes the target's response to our WDTR message.
                   1110:  *
                   1111:  * In addition, if there is a pending SDTR message, this routine sends it
                   1112:  * to the target.
                   1113:  *
                   1114:  *-----------------------------------------------------------------------------*/
                   1115: - (void) Sym8xxNegotiateWDTR:(SRB *) srb Nexus:(Nexus *)nexus
                   1116: {
                   1117:     u_int8_t           *pMsg;
                   1118:     u_int32_t          msgBytesSent;
                   1119:     u_int32_t           msgBytesLeft;
                   1120: 
                   1121:     /*
                   1122:      * If we were not negotiating, the send MsgReject to targets negotiation
                   1123:      * attempt.
                   1124:      */
                   1125:    if ( !(srb->srbRequestFlags & ksrbRFNegotiateWide) )
                   1126:     {
                   1127:         [self Sym8xxSendMsgReject: srb];
                   1128:         return;
                   1129:     }
                   1130: 
                   1131:     /* 
                   1132:      * Set Wide (16-bit) vs Narrow (8-bit) data transfer mode based on target's response.
                   1133:      */
                   1134:     pMsg = (u_int8_t *) &SCRIPT_VAR(R_ld_message);
                   1135: 
                   1136:     if ( pMsg[3] == 1 )
                   1137:     {
                   1138:         nexus->targetParms.scntl3Reg |= EWS;
                   1139:     }
                   1140:     else
                   1141:     {
                   1142:         nexus->targetParms.scntl3Reg &= ~EWS;
                   1143:     }
                   1144: 
                   1145:     /*
                   1146:      * Update our per-target tables and set-up the hardware regs for this request.
                   1147:      *
                   1148:      * On reconnection attempts, the script will use our per-target tables to set-up
                   1149:      * the scntl3 and sxfer registers in the script engine.
                   1150:      */
                   1151: 
                   1152:     adapter->targetClocks[srb->target].scntl3Reg = nexus->targetParms.scntl3Reg;
                   1153:     Sym8xxWriteRegs( chipBaseAddr, SCNTL3, SCNTL3_SIZE, nexus->targetParms.scntl3Reg );
                   1154: 
                   1155:     targets[srb->target].flags |= kTFXferWide16;
                   1156: 
                   1157:     /*
                   1158:      * If there any pending messages left for the target, send them now, 
                   1159:      */
                   1160:     msgBytesSent = EndianSwap32( nexus->msg.length );
                   1161:     msgBytesLeft = srb->srbMsgLength - msgBytesSent;
                   1162:     if ( msgBytesLeft )
                   1163:     {
                   1164:         nexus->msg.length = EndianSwap32( msgBytesLeft );
                   1165:         nexus->msg.ppData = EndianSwap32( EndianSwap32( nexus->msg.ppData ) + msgBytesSent );                
                   1166:         scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_issueMessageOut];
                   1167:     }
                   1168: 
                   1169:     /*
                   1170:      * Otherwise, tell the script we're done with MsgOut phase.
                   1171:      */
                   1172:     else
                   1173:     {
                   1174:         scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_clearACK];
                   1175:     }
                   1176: }  
                   1177: 
                   1178: /*-----------------------------------------------------------------------------*
                   1179:  * Reject message received from target.
                   1180:  *
                   1181:  *-----------------------------------------------------------------------------*/
                   1182: - (void) Sym8xxSendMsgReject:(SRB *) srb
                   1183: {
                   1184:     srb->nexus.msg.ppData = EndianSwap32((u_int32_t)&srb->srbPhys->nexus.msgData);
                   1185:     srb->nexus.msg.length = EndianSwap32(0x01);
                   1186:     srb->nexus.msgData[0] = 0x07;
                   1187: 
                   1188:     scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_issueMessageOut];
                   1189: }
                   1190:   
                   1191: /*-----------------------------------------------------------------------------*
                   1192:  * This routine snoops inquiry data.
                   1193:  *
                   1194:  * The indirect SCSI Disk driver in driverKit, does not bother to check the target's 
                   1195:  * capabilities before enabling Synchronous Negotiation or Cmd Queueing. If things 
                   1196:  * were left to themselves, targets that did not support tags would be broken since 
                   1197:  * the request comming from driverKit always indicate that tags are allowed.
                   1198:  *
                   1199:  *-----------------------------------------------------------------------------*/
                   1200: - (void) Sym8xxCheckInquiryData: (SRB *)srb
                   1201: {
                   1202:     IOMemoryDescriptor                 *mem;
                   1203:     inquiry_reply_t                    inqData;
                   1204:     u_int32_t                          inqSize;
                   1205: 
                   1206:     bzero( &inqData, sizeof(inqData) );
                   1207: 
                   1208:     inqSize = (srb->xferDone < sizeof(inqData)) ? srb->xferDone : sizeof(inqData);
                   1209: 
                   1210:     mem = [[ IOSimpleMemoryDescriptor alloc ] initWithAddress: (void *)srb->xferBuffer length: inqSize ];
                   1211:     [mem setClient: srb->xferClient];
                   1212: 
                   1213:     do
                   1214:     {
                   1215:         if ( srb->srbSCSIResult != SR_IOST_GOOD )
                   1216:         {
                   1217:             continue;
                   1218:         }
                   1219:         if ( srb->xferDone < offsetof(inquiry_reply_t, ir_vendorid) )
                   1220:         {
                   1221:             continue;
                   1222:         }
                   1223:           
                   1224:         if ( [mem readFromClient: (void *) &inqData count: inqSize] != inqSize )
                   1225:         {
                   1226:             continue;
                   1227:         }
                   1228:         if ( inqData.ir_qual != DEVQUAL_OK )
                   1229:         {
                   1230:             continue;
                   1231:         }
                   1232: 
                   1233:         if ( inqData.ir_wbus16 )
                   1234:         {
                   1235:             targets[srb->target].flags |= kTFXferWide16Supported;
                   1236:         }
                   1237:         if ( inqData.ir_sync )
                   1238:         {
                   1239:            targets[srb->target].flags |= kTFXferSyncSupported;
                   1240:         }
                   1241:         if ( inqData.ir_cmdque )
                   1242:         {
                   1243:            targets[srb->target].flags |= kTFCmdQueueSupported;
                   1244:         }
                   1245:     }
                   1246:     while ( 0 );
                   1247:     [mem release];
                   1248: }
                   1249: 
                   1250: 
                   1251: /*-----------------------------------------------------------------------------*
                   1252:  * This routine initiates a SCSI Bus Reset.
                   1253:  *
                   1254:  * This may be an internally generated request as part of error recovery or
                   1255:  * a client's bus reset request.
                   1256:  *
                   1257:  *-----------------------------------------------------------------------------*/
                   1258: - (void) Sym8xxSCSIBusReset: (SRB *)srb
                   1259: {
                   1260:     if ( srb )
                   1261:     {
                   1262:         if ( resetSRB )
                   1263:         {
                   1264:             srb->srbSCSIResult = SR_IOST_CMDREJ;
                   1265:             [srb->srbCmdLock unlockWith: ksrbCmdComplete];  
                   1266:             return;
                   1267:         }    
                   1268:         resetSRB = srb;
                   1269:     }
                   1270: 
                   1271:     Sym8xxWriteRegs( chipBaseAddr, SCNTL1, SCNTL1_SIZE, SCNTL1_SCSI_RST );
                   1272:     IODelay( 25 );
                   1273:     Sym8xxWriteRegs( chipBaseAddr, SCNTL1, SCNTL1_SIZE, SCNTL1_INIT );
                   1274: }
                   1275:     
                   1276: /*-----------------------------------------------------------------------------*
                   1277:  * This routine handles a SCSI Bus Reset interrupt.
                   1278:  *
                   1279:  * The SCSI Bus reset may be generated by a target on the bus, internally from
                   1280:  * the driver's error recovery or from a client request.
                   1281:  *
                   1282:  * Once the reset is detected we establish a settle period where new client requests
                   1283:  * are blocked in the client thread. In addition we flush all currently executing
                   1284:  * scsi requests back to the client.
                   1285:  *
                   1286:  *-----------------------------------------------------------------------------*/
                   1287: - (void) Sym8xxProcessSCSIBusReset
                   1288: {
                   1289:     SRB                        *srb   = 0;
                   1290:     Nexus              *nexus = 0;
                   1291:     u_int32_t          i;
                   1292: 
                   1293:     /*
                   1294:      * If we got another bus reset event during the settle period we extend the settle
                   1295:      * period accordingly.
                   1296:      */
                   1297:     if ( resetQuiesceTimer )
                   1298:     {
                   1299:         resetQuiesceTimer = kResetQuiesceDelayMS / kSCSITimerIntervalMS + 1;
                   1300:         return;
                   1301:     }
                   1302: 
                   1303:     resetSeqNum = srbSeqNum;
                   1304: //  kprintf("SCSI(Symbios8xx): Reset Started - SRB Seq = %d\n\r", resetSeqNum);
                   1305: 
                   1306:     /*
                   1307:      * We take the resetQuiesceSem lock which will block new client thread requests.
                   1308:      * 
                   1309:      * Note: The client thread checks resetQuiesceTimer for <> 0 before taking this lock.
                   1310:      */
                   1311:     [resetQuiesceSem lock];
                   1312:     resetQuiesceTimer = kResetQuiesceDelayMS / kSCSITimerIntervalMS + 1;
                   1313: 
                   1314:     /*
                   1315:      * We end any aborts currently in progress
                   1316:      */
                   1317:     abortCurrentSRB = (SRB *)NULL;
                   1318: 
                   1319:     if ( abortSRB )
                   1320:     {
                   1321:         [abortSRB->srbCmdLock unlockWith: ksrbCmdComplete];
                   1322:         abortSRB = (SRB *) NULL;  
                   1323:     }
                   1324: 
                   1325:    [self Sym8xxClearFifo];
                   1326: 
                   1327:    /* 
                   1328:     * We return anything in our Nexus table back to the client
                   1329:     */
                   1330:    for ( i=0; i < MAX_SCSI_TAG; i++ )
                   1331:     {
                   1332:         nexus = adapter->nexusPtrsVirt[i];
                   1333:         if ( nexus == (Nexus *) -1 )
                   1334:         {
                   1335:             continue;
                   1336:         }
                   1337: 
                   1338:         srb = (SRB *)((u_int32_t)nexus - offsetof(SRB, nexus));
                   1339:   
                   1340:         srb->srbSCSIResult = SR_IOST_RESET;
                   1341: 
                   1342:         adapter->nexusPtrsVirt[i] = (Nexus *) -1;
                   1343:         adapter->nexusPtrsPhys[i] = (Nexus *) -1;
                   1344: 
                   1345:         [srb->srbCmdLock unlockWith: ksrbCmdComplete];  
                   1346:     }
                   1347: 
                   1348:     /*
                   1349:      * We clear the script's request mailboxes. Any work in the script mailboxes is
                   1350:      * already in the NexusPtr tables so we have already have handled the SRB/Nexus
                   1351:      * cleanup.
                   1352:      */
                   1353:     for ( i=0; i < MAX_SCHED_MAILBOXES; i++ )
                   1354:     {
                   1355:         adapter->schedMailBox[i] = 0;
                   1356:     }
                   1357: 
                   1358:     SCRIPT_VAR(R_ld_AbortBdr_mailbox) = 0;
                   1359:     SCRIPT_VAR(R_ld_IOdone_mailbox)   = 0;
                   1360:     SCRIPT_VAR(R_ld_counter)          = 0;
                   1361:     mailBoxIndex                      = 0;
                   1362: 
                   1363:     /*
                   1364:      * Reset the data transfer mode/clocks in our per-target tables back to Async/Narrow 8-bit
                   1365:      */
                   1366:     for ( i=0; i < MAX_SCSI_TARGETS; i++ )
                   1367:     {
                   1368:         targets[i].flags &= ~(kTFXferSync | kTFXferWide16);
                   1369: 
                   1370:         adapter->targetClocks[i].scntl3Reg = SCNTL3_INIT_875;
                   1371:         adapter->targetClocks[i].sxferReg  = 0;
                   1372:     }
                   1373: 
                   1374:     scriptRestartAddr = (u_int32_t) &chipRamAddrPhys[Ent_select_phase];
                   1375:     Sym8xxWriteRegs( chipBaseAddr, DSP, DSP_SIZE, scriptRestartAddr );
                   1376: 
                   1377: }
                   1378: 
                   1379: /*-----------------------------------------------------------------------------*
                   1380:  * This routine sets the SIGP bit in the script engine's ISTAT
                   1381:  * register. This signals the script to wake-up for a WAIT for
                   1382:  * reselection instruction. The script will then check the mailboxes
                   1383:  * for work to do.
                   1384:  *
                   1385:  *-----------------------------------------------------------------------------*/
                   1386: - (void) Sym8xxSignalScript:(SRB *)srb
                   1387: {
                   1388:     Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, SIGP );
                   1389: }
                   1390: 
                   1391: /*-----------------------------------------------------------------------------*
                   1392:  * Timeout handler.
                   1393:  *
                   1394:  * This routine is scheduled and implements timeouts for the driver.
                   1395:  *
                   1396:  * The following items are timed:
                   1397:  *
                   1398:  * - Reset settle period.
                   1399:  * - Aborts
                   1400:  * - SRBs
                   1401:  *
                   1402:  *-----------------------------------------------------------------------------*/
                   1403: - (void) timeoutOccurred
                   1404: {
                   1405:     SRB                                *srb;
                   1406:     Nexus                      *nexus;
                   1407:     u_int32_t                  i;
                   1408:     u_int32_t                  nexusIndex;
                   1409:     u_int32_t                  mailboxNexusIndex = -1;
                   1410: 
                   1411:     if ( SCRIPT_VAR( R_ld_IOdone_mailbox ) )
                   1412:     {
                   1413:         mailboxNexusIndex = ((IODoneMailBox *)&SCRIPT_VAR(R_ld_IOdone_mailbox))->nexus;
                   1414:     }
                   1415: 
                   1416:     nexusIndex = EndianSwap32( SCRIPT_VAR(R_ld_nexus_index) );
                   1417: 
                   1418:     /*
                   1419:      * If we are in a reset settle period, suspend all other timing. 
                   1420:      *
                   1421:      * When the reset settle period completes, return the SRB if the
                   1422:      * client requested the bus reset. Also unlock the reset semaphore.
                   1423:      */
                   1424:     if ( resetQuiesceTimer )
                   1425:     {
                   1426:         if ( --resetQuiesceTimer )
                   1427:         {
                   1428:             goto timeoutOccurred_Exit;
                   1429:         }
                   1430: 
                   1431:         if ( resetSRB )
                   1432:         {
                   1433:             [resetSRB->srbCmdLock unlockWith: ksrbCmdComplete];  
                   1434:             resetSRB = (SRB *) NULL;
                   1435:         }
                   1436: //      kprintf("SCSI(Symbios8xx): Reset Ended - SRB Seq = %d\n\r", srbSeqNum);
                   1437:         [resetQuiesceSem unlock];
                   1438:     }
                   1439: 
                   1440:     /*
                   1441:      * Check whether an abort timed out. If it does, then its likely that a target is
                   1442:      * hung on the bus. In this case the only recourse is to issue a SCSI Bus reset.
                   1443:      */
                   1444:     if ( abortCurrentSRB && abortCurrentSRBTimeout )
                   1445:     {
                   1446:         if ( !(--abortCurrentSRBTimeout) )
                   1447:         {
                   1448: //          kprintf("SCSI(Symbios8xx): Abort Current SRB failed - resetting\n\r");
                   1449:             [self Sym8xxSCSIBusReset: (SRB *)NULL];
                   1450:             goto timeoutOccurred_Exit;
                   1451:         }
                   1452:     }
                   1453: 
                   1454:     if ( abortSRB && abortSRBTimeout )
                   1455:     {
                   1456:         if ( !(--abortSRBTimeout) )
                   1457:         {
                   1458: //          kprintf("SCSI(Symbios8xx): MailBox abort failed - resetting\n\r");
                   1459:             [self Sym8xxSCSIBusReset: (SRB *)NULL];
                   1460:             goto timeoutOccurred_Exit;
                   1461:         }
                   1462:     }
                   1463: 
                   1464:     /*
                   1465:      * Scan the Nexus pointer table looking for SRBs to timeout
                   1466:      */
                   1467:     for ( i=0; i < MAX_SCSI_TAG; i++ )
                   1468:     {
                   1469:          nexus = adapter->nexusPtrsVirt[i];
                   1470:          if ( nexus == (Nexus *) -1 )
                   1471:          {
                   1472:              continue;
                   1473:          }
                   1474: 
                   1475:          srb = (SRB *)((u_int32_t)nexus - offsetof(SRB, nexus));
                   1476:          if ( srb->srbTimeout )
                   1477:          {
                   1478:              if ( !(--srb->srbTimeout) )
                   1479:              {  
                   1480: //               kprintf("SCSI(Symbios8xx): Timeout - Target = %d SRB = %08x SRB Seq = %d\n\r", 
                   1481: //                            srb->target, (u_int32_t)srb, srb->srbSeqNum );
                   1482: 
                   1483:                  /* If the SRB we're timing out is in the script's IODone mailbox, then
                   1484:                   * clear the mailbox in addition to timing out the request.
                   1485:                   */
                   1486:                  if ( i == mailboxNexusIndex )
                   1487:                  {
                   1488:                      SCRIPT_VAR(R_ld_IOdone_mailbox) = 0;
                   1489:                  }
                   1490:                  
                   1491:                  /* 
                   1492:                   * If the target for the SRB we're timing out is currently connected on 
                   1493:                   * the SCSI Bus, then issue an abort. Since it is likely that the script
                   1494:                   * is running in this scenario, we call a Sym8xxAbortScript to shutdown the
                   1495:                   * script engine in an orderly fashion.
                   1496:                   */
                   1497:                  if ( i == nexusIndex )
                   1498:                  {
                   1499:                      [self Sym8xxAbortScript];
                   1500:                      srb->srbSCSIResult = SR_IOST_IOTO;
                   1501:                      [self Sym8xxAbortCurrent: srb];
                   1502:                      Sym8xxWriteRegs( chipBaseAddr, DSP, DSP_SIZE, scriptRestartAddr );
                   1503:                  }  
                   1504:                 
                   1505:                  /* 
                   1506:                   * If target for the SRB we're timing out is not on the SCSI bus, then
                   1507:                   * we mark the request as requiring an Abort and return it to the client
                   1508:                   * thread. The client thread will then schedule the abort.
                   1509:                   */ 
                   1510:                  else
                   1511:                  {
                   1512:                      adapter->nexusPtrsVirt[i] = (Nexus *) -1;
                   1513:                      adapter->nexusPtrsPhys[i] = (Nexus *) -1;
                   1514:                      
                   1515:                      srb->srbSCSIResult = SR_IOST_IOTO;
                   1516:                      srb->srbCmd        = ksrbCmdProcessTimeout;
                   1517:                      [srb->srbCmdLock unlockWith: ksrbCmdComplete];  
                   1518:                  }
                   1519:              }
                   1520:          }
                   1521:     }
                   1522: 
                   1523:    
                   1524: timeoutOccurred_Exit: ;
                   1525:     /*
                   1526:      * Reschedule the next timer interval.
                   1527:      */
                   1528:     ns_timeout((func) Sym8xxTimerReq, (void *) self, (ns_time_t) kSCSITimerIntervalMS * 1000 * 1000, (int)CALLOUT_PRI_THREAD);
                   1529: }  
                   1530:   
                   1531: /*-----------------------------------------------------------------------------*
                   1532:  * This routine does a mailbox abort.
                   1533:  *
                   1534:  * This type of abort is used for targets not currently connected to the SCSI Bus.
                   1535:  *
                   1536:  * The script will select the target and send a tag (if required) followed by the
                   1537:  * appropriate abort message (abort/abort-tag)
                   1538:  *
                   1539:  *-----------------------------------------------------------------------------*/
                   1540: - (void) Sym8xxAbortBdr:(SRB *) srb
                   1541: {
                   1542:     IOAbortBdrMailBox                  abortMailBox;
                   1543: 
                   1544:     abortSRB        = srb;
                   1545:     abortSRBTimeout = kAbortTimeoutMS / kSCSITimerIntervalMS + 1; 
                   1546: 
                   1547:     /*
                   1548:      * Setup a script variable containing the abort information.
                   1549:      */
                   1550:     abortMailBox.message   = ( srb->nexus.tag < MIN_SCSI_TAG) ? 0x06 : 0x0d;
                   1551:     abortMailBox.identify  = srb->lun | 0xC0 ;
                   1552:     abortMailBox.scsi_id   = srb->target;
                   1553:     abortMailBox.tag       = ( srb->nexus.tag < MIN_SCSI_TAG) ? 0 : srb->nexus.tag;
                   1554: 
                   1555:     SCRIPT_VAR(R_ld_AbortBdr_mailbox) = *(u_int32_t *) &abortMailBox;
                   1556: 
                   1557:     [self Sym8xxSignalScript: srb];
                   1558: }
                   1559: 
                   1560: /*-----------------------------------------------------------------------------*
                   1561:  * This routine is used to shutdown the script engine in an orderly fashion.
                   1562:  *
                   1563:  * Normally the script engine automatically stops when an interrupt is generated. However,
                   1564:  * in the case of timeouts we need to change the script engine's dsp reg (instruction pointer).
                   1565:  * to issue an abort.
                   1566:  *
                   1567:  *-----------------------------------------------------------------------------*/
                   1568: - (void) Sym8xxAbortScript
                   1569: {
                   1570:     ns_time_t          currentTime;
                   1571:     ns_time_t          endTime;
                   1572: 
                   1573:     [self disableAllInterrupts];
                   1574:     
                   1575:     /*
                   1576:      * We set the ABRT bit in ISTAT and spin until the script engine acknowledges the
                   1577:      * abort or we timeout.
                   1578:      */
                   1579:     Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, ABRT );
                   1580:     
                   1581:     IOGetTimestamp( &endTime );
                   1582: 
                   1583:     endTime += (kAbortScriptTimeoutMS * 1000 * 1000);
                   1584: 
                   1585:     do
                   1586:     {
                   1587:         IOGetTimestamp( &currentTime );
                   1588: 
                   1589:         istatReg = Sym8xxReadRegs( chipBaseAddr, ISTAT, ISTAT_SIZE );
                   1590: 
                   1591:         if ( istatReg & SIP )
                   1592:         {
                   1593:             Sym8xxReadRegs( chipBaseAddr, SIST, SIST_SIZE );
                   1594:             continue;
                   1595:         }
                   1596:     
                   1597:         if ( istatReg & DIP )
                   1598:         {
                   1599:             Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, 0x00 );
                   1600:             Sym8xxReadRegs( chipBaseAddr, DSTAT, DSTAT_SIZE );
                   1601:             break;
                   1602:         }
                   1603:     }
                   1604:     while ( currentTime < endTime );
                   1605:     
                   1606:     istatReg = SIGP;
                   1607:     Sym8xxWriteRegs( chipBaseAddr, ISTAT, ISTAT_SIZE, istatReg );
                   1608: 
                   1609:     [self enableAllInterrupts];
                   1610: 
                   1611:     if ( currentTime >= endTime )
                   1612:     {
                   1613: //      kprintf( "SCSI(Symbios8xx): Abort script failed - resetting bus\n\r" );
                   1614:         [self Sym8xxSCSIBusReset: NULL];
                   1615:     }  
                   1616: 
                   1617:   }
                   1618:     
                   1619: @end

unix.superglobalmegacorp.com

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