Annotation of kernel/bsd/dev/ppc/drvApple96_SCSI/Apple96BusState.m, revision 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: /**
        !            26:  * Copyright 1997 Apple Computer Inc. All Rights Reserved.
        !            27:  * @revision   1997.02.17      Initial conversion from AMDPCSCSIDriver sources.
        !            28:  *
        !            29:  * Set tabs every 4 characters.
        !            30:  *
        !            31:  * Apple96Chip.m - Chip-specific methods for Apple96 SCSI driver.
        !            32:  *
        !            33:  * Edit History
        !            34:  * 1997.02.18  MM              Initial conversion from AMDPCSCSIDriver sources. 
        !            35:  * 1997.04.17  MM              Removed SCS_PHASECHANGE (not needed)
        !            36:  * 1997.06.24  MM              Radar 1669736 - correctly store autosense status
        !            37:  * 1997.09.10  MM              Radar 1678545 - Don't clear the gBusBusy flag until we
        !            38:  *                             get a "disconnected" interrupt.
        !            39:  */
        !            40: #import "Apple96SCSI.h"
        !            41: #import "Apple96BusState.h"
        !            42: #import "Apple96SCSIPrivate.h"
        !            43: #import "Apple96CurioPublic.h"
        !            44: #import "Apple96CurioPrivate.h"
        !            45: #import "Apple96CurioDBDMA.h"
        !            46: #import "Apple96HWPrivate.h"
        !            47: #import "Apple96ISR.h"
        !            48: #import "MacSCSICommand.h"
        !            49: #import "bringup.h"
        !            50: #import <driverkit/generalFuncs.h>
        !            51: #import <kernserv/prototypes.h>
        !            52: 
        !            53: #define IO_R_BV        0xDEADBEEF      /* TEMP */
        !            54: 
        !            55: extern IONamedValue scsiMsgValues[];   /* In Apple96ISR.m */
        !            56:        
        !            57: @implementation Apple96_SCSI(BusState)
        !            58: /*
        !            59:  * Disconnected - only legal event here is reselection.
        !            60:  * [self fsmHandleReselectionInterrupt] may set gBusState to SCS_INITIATOR
        !            61:  */
        !            62: - (void) fsmDisconnected
        !            63: {
        !            64:                UInt8                           selectByte;
        !            65:                UInt8                           target;
        !            66:                
        !            67:                ENTRY("Bdi fsmDisconnected");
        !            68:                ddmChip("fsmDisconnected\n", 1,2,3,4,5);
        !            69:                if ((gSaveInterrupt & iReselected) != 0) {
        !            70:                        [self fsmHandleReselectionInterrupt];
        !            71:                }
        !            72:                else if ((gSaveInterrupt & (iSelected | iSelectWAtn)) != 0) {
        !            73:                        /*
        !            74:                         * To do: allow selection by an external target and support
        !            75:                         * a few mandatory commands:
        !            76:                         *      (PowerUp:               gPendingTargetError = Unit Attention)
        !            77:                         *      Inquiry                 We're a CPU
        !            78:                         *      Test Unit Ready:
        !            79:                         *                                      if (gPendingTargetError == Unit Attention)
        !            80:                         *                                              Check Condition
        !            81:                         *                                      else {
        !            82:                         *                                              Success
        !            83:                         *                                      }
        !            84:                         *      All others              gPendingTargetError := Illegal Command.
        !            85:                         *                                      Check Condition
        !            86:                         *      Request Sense:  Send current error, clear current error.
        !            87:                         */
        !            88:            SynchronizeIO();
        !            89:            selectByte = CURIOgetFifoByte();
        !            90:                        selectByte &= ~gInitiatorIDMask;
        !            91:                        for (target = 0; target < 8; target++) {
        !            92:                                if ((selectByte & (1 << target)) != 0) {
        !            93:                                        break;
        !            94:                                }
        !            95:                        }
        !            96:                        IOLog("%s: Selected by external target %d -- not supported\n",
        !            97:                                [self name],
        !            98:                                target
        !            99:                        );
        !           100:            CURIOdisconnect();
        !           101:                }
        !           102:                else if (gFlagBusBusy == FALSE) {
        !           103:                        /*
        !           104:                         * disconnect interrupted while disconnected
        !           105:                         * This always happens when we finish an I/O request.
        !           106:                         * gFlagBusBusy is cleared when the "bus disconnected" bit
        !           107:                         * is set in the NCR 53C96 interrupt register.
        !           108:                         */
        !           109:                }
        !           110:                else {
        !           111:                        /*
        !           112:                         * Since we're disconnected, just ignore the interrupt
        !           113:                         */
        !           114:                        if (gActiveCommand != NULL
        !           115:                                && gActiveCommand->scsiReq != NULL
        !           116:                                && gActiveCommand->scsiReq->driverStatus == SR_IOST_INVALID) {
        !           117: #if 0 /* Radar 1678545 */
        !           118:                                IOLog("fsmDisconnected: timeout, target %d, int %02x, status %02x, step %02x\n",
        !           119:                                        gActiveCommand->scsiReq->target,
        !           120:                                        gSaveInterrupt & 0xFF,
        !           121:                                        gSaveStatus & 0xFF,
        !           122:                                        gSaveSeqStep & 0xFF
        !           123:                                );
        !           124: #endif 
        !           125:                                gActiveCommand->scsiReq->driverStatus = SR_IOST_SELTO;
        !           126:                        }
        !           127:                        if (gActiveCommand != NULL) {
        !           128:                [self ioComplete
        !           129:                            : gActiveCommand
        !           130:                    finalStatus : SR_IOST_INVALID
        !           131:                ];
        !           132:                        }
        !           133:                        gCurrentBusPhase = kBusPhaseBusFree;
        !           134:                }
        !           135:                EXIT();
        !           136: }
        !           137: 
        !           138: /*
        !           139:  * This state is called when we expect to disconnect from a target after
        !           140:  * receiving a Command Complete, Disconnect, or Abort message and the bus
        !           141:  * is still busy on exit from the finite state automaton (because
        !           142:  * curioQuickCheckForBusFree returned false).
        !           143:  */ 
        !           144: - (void) fsmWaitForBusFree
        !           145: {
        !           146:                if ((gSaveInterrupt & (iReselected | iSelected | iSelectWAtn)) != 0) {
        !           147:                        /*
        !           148:                         * Hmm, we went straight from command completion to (presumably)
        !           149:                         * reselection. Treat it as a normal selection/reselection
        !           150:                         * interrupt from "disconnected" state. (This is an abuse of
        !           151:                         * the finite-state automaton design.)
        !           152:                         */
        !           153:                        [self fsmDisconnected];
        !           154:                }
        !           155:                else if (gFlagBusBusy == FALSE) {
        !           156:                        /*
        !           157:                         * This is expected: the bus has just gone free after a command
        !           158:                         * completed. We can now safely try to start another command.
        !           159:                         */
        !           160:                        gBusState = SCS_DISCONNECTED;
        !           161:                }
        !           162:                else {
        !           163:                        /*
        !           164:                         * This is strange. It may not be an error, but I don't know
        !           165:                         * if there are other legal bus states after disconnect
        !           166:                         * (the one counter example would be after a linked command
        !           167:                         * when the target goes to Command phase, but we should have
        !           168:                         * rejected this at command complete.
        !           169:                         */
        !           170:                        [self fsmStartErrorRecovery
        !           171:                                                        : SR_IOST_HW
        !           172:                                        reason  : "Unexpected interrupt when disconnecting"
        !           173:                        ];
        !           174:                }
        !           175: }
        !           176:        
        !           177: /*
        !           178:  * This is called from fsmDisconnected when we receive a reselected interrupt.
        !           179:  */
        !           180: - (void) fsmHandleReselectionInterrupt
        !           181: {
        !           182:                UInt8                                   selectByte;
        !           183:                UInt32                                  fifoDepth;
        !           184:                UInt8                                   msgByte;
        !           185:                IOReturn                                ioReturn;
        !           186:                const char                              *reason = NULL;
        !           187: 
        !           188:                ENTRY("Bre fsmHandleReselectionInterrupt");
        !           189:                /* 
        !           190:                 * Make sure there's a selection byte and an identify message in the fifo.
        !           191:                 */
        !           192:                ioReturn = IO_R_SUCCESS;
        !           193:                gFlagBusBusy = ((gSaveInterrupt & iDisconnect) == 0);   /* Radar 1678545 */
        !           194:        SynchronizeIO();
        !           195:        fifoDepth = CURIOgetFifoCount();
        !           196:                ddmChip("reselect: fifoDepth %d\n", fifoDepth, 2,3,4,5);
        !           197:                if (fifoDepth != 2) {
        !           198:                        ddmError("reselection, fifoDepth %d\n", fifoDepth, 
        !           199:                                2,3,4,5);
        !           200: #if LOG_ERROR_RECOVERY
        !           201:                        IOLog("%s: Bad FIFO count (%d) (expect 2) on Reselect\n",
        !           202:                                [self name],
        !           203:                                fifoDepth
        !           204:                        );
        !           205: #endif /* LOG_ERROR_RECOVERY */
        !           206:                        ioReturn = SR_IOST_HW;
        !           207:                        reason =  "Bad FIFO count on reselect";
        !           208:                }
        !           209:                if (ioReturn == IO_R_SUCCESS) {
        !           210:            SynchronizeIO();
        !           211:            selectByte = CURIOgetFifoByte();
        !           212:                        ddmChip("reselection: select byte %02x\n", selectByte, 2, 3, 4, 5);
        !           213:                        ioReturn = [self getReselectionTargetID : selectByte];
        !           214:                        if (ioReturn != IO_R_SUCCESS) {
        !           215:                                reason = "Bad selection value on reselect";
        !           216:                        }
        !           217:                }
        !           218:                if (ioReturn == IO_R_SUCCESS) {
        !           219:                        /*
        !           220:                         * gCurrentTarget has the bus ID of the target that is reselecting.
        !           221:                         * The first message byte must be an Identify with the LUN.
        !           222:                         */
        !           223:            SynchronizeIO();
        !           224:            msgByte = CURIOgetFifoByte();
        !           225:                        if ((gSaveStatus & sParityErr) != 0) {
        !           226:                                ioReturn = SR_IOST_PARITY;
        !           227:                                reason = "Parity error on reselect";
        !           228:                        }
        !           229:                }
        !           230:                if (ioReturn == IO_R_SUCCESS) {
        !           231:                        if ((msgByte & kScsiMsgIdentify) == 0) {
        !           232:                                ioReturn = SR_IOST_BV;
        !           233:                                reason = "Bad ID Message (no identify) on reselect";
        !           234:                        }
        !           235:                        gCurrentLUN = msgByte & ~kScsiMsgIdentify;
        !           236:            /* gFlagBusBusy = TRUE; -- Radar 1678545: move to method start  */
        !           237:                        gBusState = SCS_RESELECTING;
        !           238:                        /*
        !           239:                         * At this point, the chip is waiting for us to validate 
        !           240:                         * the identify message. While we have a target and LUN,
        !           241:                         * we don't have a command to reconnect to (that's the
        !           242:                         * job of fsmReselectionAction).
        !           243:                         *
        !           244:                         * In case of sync mode, we need to load target context right
        !           245:                         * now, before dropping ACK, because the target might go
        !           246:                         * straight to a data in or data out as soon as ACK drops.
        !           247:                         */
        !           248:            CURIOmessageAccept();   /* Accept the identify message  */
        !           249:                        ddmChip("Successful reselect from %d.%d\n",
        !           250:                                        gCurrentTarget,
        !           251:                                        gCurrentLUN,
        !           252:                                        3, 4, 5
        !           253:                                );
        !           254:                }
        !           255:                if (ioReturn != IO_R_SUCCESS) {
        !           256:                        [self fsmStartErrorRecovery
        !           257:                                                        : ioReturn
        !           258:                                        reason  : reason
        !           259:                        ];
        !           260:                }
        !           261:                EXIT();
        !           262: }
        !           263: 
        !           264: /*
        !           265:  * One of three things can happen here - the selection could succeed (though
        !           266:  * with possible incomplete message out), it could time out, or we can be 
        !           267:  * reselected.
        !           268:  */
        !           269: - (void) fsmSelecting
        !           270: {
        !           271:                IOReturn                                ioReturn;
        !           272:                UInt8                                   fifoDepth;
        !           273:                CommandBuffer                   *cmdBuf;
        !           274:                IOSCSIRequest                   *scsiReq = NULL;
        !           275:                const char                              *reason = NULL;
        !           276: 
        !           277:                ENTRY("Bse fsmSelecting");
        !           278:                ddmChip("fsmSelecting\n", 1,2,3,4,5);
        !           279:                ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !           280:                scsiReq = gActiveCommand->scsiReq;
        !           281:                ioReturn = IO_R_SUCCESS;
        !           282:                gFlagBusBusy = ((gSaveInterrupt & iDisconnect) == 0);
        !           283:                if (gFlagBusBusy == FALSE) {
        !           284:                        /*
        !           285:                         * selection timed-out. Abort this request.
        !           286:                         */
        !           287:                        ddmChip("***SELECTION TIMEOUT for target %d.%d\n",
        !           288:                                scsiReq->target,
        !           289:                                scsiReq->lun,
        !           290:                                3,4,5
        !           291:                        );
        !           292:            CURIOflushFifo();
        !           293:                        gBusState = SCS_DISCONNECTED;
        !           294: #if 0 /* Radar 1678545 */
        !           295:                        IOLog("fsmSelecting: timeout, target %d, int %02x, status %02x, step %02x\n",
        !           296:                                gActiveCommand->scsiReq->target,
        !           297:                                gSaveInterrupt & 0xFF,
        !           298:                                gSaveStatus & 0xFF,
        !           299:                                gSaveSeqStep & 0xFF
        !           300:                        );
        !           301: #endif 
        !           302:            [self ioComplete
        !           303:                        : gActiveCommand
        !           304:                finalStatus : SR_IOST_SELTO
        !           305:            ];
        !           306:                        gActiveCommand = NULL;
        !           307:                }
        !           308:                else if (gSaveInterrupt == (iFuncComp | iBusService)) {
        !           309:                        ddmChip("selection seqstep=%d\n", 
        !           310:                                gSaveSeqStep & INS_STATE_MASK, 2,3,4,5);
        !           311:                        switch (gSaveSeqStep & INS_STATE_MASK) {
        !           312:            case 0: 
        !           313:                                /*
        !           314:                                 * No message phase. If we really wanted one,
        !           315:                                 * this could be significant...
        !           316:                                 */
        !           317:                                if (gActiveCommand->queueTag != QUEUE_TAG_NONTAGGED) {
        !           318:                                        /*
        !           319:                                         * This target can't do command queueing.
        !           320:                                         */
        !           321:                                        [self disableMode : kTargetModeCmdQueue];
        !           322:                                        /*
        !           323:                                         * Clear the queue tag so we don't get here on
        !           324:                                         * an eventual autosense.
        !           325:                                         */
        !           326:                                        gActiveCommand->queueTag = QUEUE_TAG_NONTAGGED;
        !           327:                                }
        !           328:                                /*
        !           329:                                 * OK, let's try to continue following phase changes.
        !           330:                                 */
        !           331:                                gBusState = SCS_INITIATOR;
        !           332:                                break;
        !           333:            case 3: /* didn't complete cmd phase, parity? */
        !           334:            case 4: /* everything worked */
        !           335:            case 1: /* everything worked, SCMD_SELECT_ATN_STOP case */
        !           336:                                /* 
        !           337:                                 * We're connected. Start following the target's phase
        !           338:                                 * changes.
        !           339:                                 *
        !           340:                                 * If we're trying to do sync negotiation,
        !           341:                                 * this is the place to do it. In that case, we
        !           342:                                 * sent a SCMD_SELECT_ATN_STOP command, and
        !           343:                                 * ATN is now asserted (and we're hopefully in
        !           344:                                 * msg out phase). We want to send 5 bytes. 
        !           345:                                 * Drop them into currMsgOut[] and prime the  
        !           346:                                 * msgOutState machine.
        !           347:                                 */
        !           348:                                gBusState = SCS_INITIATOR;
        !           349:                                break;
        !           350:            case 2: 
        !           351:                                /*
        !           352:                                 * Either no command phase, or incomplete message
        !           353:                                 * transfer.
        !           354:                                 */
        !           355:                SynchronizeIO();
        !           356:                fifoDepth = CURIOgetFifoCount();
        !           357: #if LOG_ERROR_RECOVERY
        !           358:                                IOLog("%s: Incomplete select (step 2); fifoDepth %d phase %s\n",
        !           359:                                        [self name],
        !           360:                                        fifoDepth, 
        !           361:                    IOFindNameForValue(gSaveStatus & mPhase, scsiPhaseValues)
        !           362:                                );
        !           363: #endif /* LOG_ERROR_RECOVERY */
        !           364:                                if (gActiveCommand->queueTag != QUEUE_TAG_NONTAGGED) {
        !           365:                                        /*
        !           366:                                         * This target can't do command queueing.
        !           367:                                         */
        !           368:                                        [self disableMode : kTargetModeCmdQueue];
        !           369:                                }
        !           370:                                /*
        !           371:                                 * Spec says ATN is asserted if all message bytes
        !           372:                                 * were not sent.
        !           373:                                 */
        !           374:                                if (fifoDepth > gActiveCommand->cdbLength) {
        !           375:                    CURIOclearATN();
        !           376:                                }
        !           377:                                /*
        !           378:                                 * 970611: clear the fifo. If we don't do this and the
        !           379:                                 * target is entering MSGI phase (trying to send us a
        !           380:                                 * Message Reject), it will sit on top of the fifo, and
        !           381:                                 * we'll read garbage from the fifo.
        !           382:                                 */
        !           383:                CURIOflushFifo();   /* The command is still in the fifo */
        !           384:                                /*
        !           385:                                 * OK, let's try to continue following phase changes.
        !           386:                                 */
        !           387:                                gBusState = SCS_INITIATOR;
        !           388:                                break;
        !           389:                        default:
        !           390:                                /* gFlagBusBusy = TRUE;         -- Radar 1678545 */
        !           391:                                ioReturn = SR_IOST_HW;
        !           392:                                reason = "Selection sequence Error (strange state)";
        !           393:                                break;
        !           394:                        }
        !           395:                }
        !           396:                else if ((gSaveInterrupt & iReselected) != 0) {
        !           397:                        /*
        !           398:                         * We were reselected while trying to do a selection. 
        !           399:                         * Enqueue this cmdBuf on the HEAD of pendingQ, then deal
        !           400:                         * with the reselect. 
        !           401:                         * Tricky case, we have to "deactivate" this command
        !           402:             * since this hardwareStart attempt failed.  
        !           403:                         */
        !           404:                        cmdBuf = gActiveCommand;
        !           405:                //      [ self deactivateCmd ];         // mlj - done by pushbackCurrentRequest
        !           406:                        [self pushbackCurrentRequest : cmdBuf];
        !           407:                        ddmChip("reselect while trying to select target %d.%d\n",
        !           408:                                        scsiReq->target,
        !           409:                                        scsiReq->lun,
        !           410:                                        3,4,5
        !           411:                                );
        !           412:                        gBusState = SCS_DISCONNECTED;
        !           413:                        /*
        !           414:                         * Go deal with reselect.
        !           415:                         */
        !           416:                        [self fsmDisconnected];
        !           417:                }
        !           418:                else if (gSaveInterrupt == iFuncComp
        !           419:                          && (gSaveSeqStep & INS_STATE_MASK) == 2
        !           420:                          && (gSaveStatus & mPhase) == kBusPhaseMSGI
        !           421:                          && (gLastMsgOut[0] & kScsiMsgIdentify) == kScsiMsgIdentify
        !           422:                          && (gLastMsgOut[0] & 0x07) != 0) {
        !           423:                                /*
        !           424:                                 * This shouldn't happen according to the NCR documentation,
        !           425:                                 * but we saw it if the bus scanner executes INQUIRY on
        !           426:                                 * a non-zero LUN on an Apple CD-300. The CD is sending a
        !           427:                                 * Message Reject to our Identify message byte. We'll
        !           428:                                 * handle this in the Message In code.
        !           429:                                 */
        !           430:                                gBusState = SCS_INITIATOR;
        !           431:                }
        !           432:                else {
        !           433:                        ioReturn = SR_IOST_HW;
        !           434:                        reason = "Bogus select/reselect interrupt";
        !           435:                }
        !           436:                if (ioReturn != IO_R_SUCCESS) {
        !           437:                        [self fsmStartErrorRecovery
        !           438:                                                        : ioReturn
        !           439:                                        reason  : "Error selecting target"
        !           440:                        ];
        !           441:                }
        !           442:                EXIT();
        !           443: }
        !           444: 
        !           445: /*
        !           446:  * This is a dummy interrupt service state that we enter after selection
        !           447:  * when the previous Curio operation has no interrupt-service completion
        !           448:  * requirement. For example, we can get here after a Message Out or
        !           449:  * reselection. Nothing happens here; we continue at fsmPhaseChange.
        !           450:  */
        !           451: - (void) fsmInitiator
        !           452: {
        !           453:                ENTRY("Bin fsmInitiator");
        !           454:                ddmChip("fsmInitiator\n", 1,2,3,4,5);
        !           455:                gBusState = SCS_INITIATOR;
        !           456:                EXIT();
        !           457: }
        !           458: 
        !           459: /*
        !           460:  * We just did a SCMD_INIT_CMD_CMPLT command, hopefully all that's left is
        !           461:  * to drop ACK. Command Complete message is handled in fscAcceptingMsg.
        !           462:  * We can't go to SCS_DISCONNECTED until the target disconnects. If we
        !           463:  * go to "disconnected" state too soon, we'll encounter a load-dependent
        !           464:  * race condition that causes us to start another command before we've
        !           465:  * cleaned up from the last command. The actual state change is in
        !           466:  * fsmProcessMessage.
        !           467:  */
        !           468: - (void) fsmCompleting
        !           469: {
        !           470:                unsigned                        fifoDepth;
        !           471:                IOReturn                        ioReturn;
        !           472:        UInt8               statusByte;
        !           473:                const char                      *reason = NULL;
        !           474:                
        !           475:                ENTRY("Bco fsmCompleting");
        !           476:                ddmChip("fsmCompleting\n", 1,2,3,4,5);
        !           477:                ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !           478:                ioReturn = IO_R_SUCCESS;
        !           479:                if ((gSaveInterrupt & iDisconnect) != 0) {
        !           480:                        ddmError("unexpected disconnect\n", 1,2,3,4,5);
        !           481:                        ioReturn = SR_IOST_HW;
        !           482:                        reason = "I/O complete, bus free before target completion complete";
        !           483:                }
        !           484:                if (ioReturn == IO_R_SUCCESS) {
        !           485:            SynchronizeIO();
        !           486:            fifoDepth = CURIOgetFifoCount();
        !           487:                        if ((gSaveInterrupt & iFuncComp) != 0) {
        !           488:                                /*
        !           489:                                 * Got both status and msg in fifo; ACK is still asserted.
        !           490:                                 */
        !           491:                                if (fifoDepth != 2) {
        !           492:                                        /*
        !           493:                                         * This is pretty bogus - we expect a status and 
        !           494:                                         * msg in the fifo.
        !           495:                                         */
        !           496:                                        ioReturn = SR_IOST_HW;
        !           497:                                        reason = "I/O complete, incorrect fifo count (expecting two bytes)";
        !           498:                                }
        !           499:                                if (ioReturn == IO_R_SUCCESS) {
        !           500:                    SynchronizeIO();
        !           501:                    statusByte = CURIOgetFifoByte();
        !           502:                    if (gActiveCommand->flagIsAutosense) {              /* Radar 1669736    */
        !           503:                        gActiveCommand->autosenseStatus = statusByte;
        !           504:                                        }
        !           505:                                        else {
        !           506:                        gActiveCommand->scsiReq->scsiStatus = statusByte;
        !           507:                                        }
        !           508:                    SynchronizeIO();
        !           509:                    gMsgInBuffer[0] = CURIOgetFifoByte();
        !           510:                                        gMsgInIndex             = 1;
        !           511:                                        ioReturn                = [self fsmProcessMessage];
        !           512:                                        reason                  = "Message in failed";
        !           513:                                }
        !           514:                        }
        !           515:                        else {
        !           516:                                /*
        !           517:                                 * We only received a status byte. This can occur
        !           518:                                 * if we responded to the interrupt before the device
        !           519:                                 * successfully transmitted the Command Complete message.
        !           520:                                 * This is kind of weird, but let's try to handle it.
        !           521:                                 */
        !           522:                                ddmError("fsmCompleting: status only on complete\n", 
        !           523:                                        1,2,3,4,5);
        !           524:                                if (fifoDepth != 1) {
        !           525:                                        ioReturn = SR_IOST_HW;
        !           526:                                        reason = "I/O complete: incorrect fifo count (expecting one byte)";
        !           527:                                }
        !           528:                                if (gActiveCommand->flagIsAutosense) {                          /* Radar 1669736        */
        !           529:                    SynchronizeIO();
        !           530:                    gActiveCommand->autosenseStatus = CURIOgetFifoByte();
        !           531:                                }
        !           532:                                else {
        !           533:                    SynchronizeIO();
        !           534:                    gActiveCommand->scsiReq->scsiStatus = CURIOgetFifoByte();
        !           535:                                }
        !           536:                                /*
        !           537:                                 * Back to watching phase changes. Presumably, the target
        !           538:                                 * will switch to MSGI phase and complete the command
        !           539:                                 * at its leasure.
        !           540:                                 */
        !           541:                                gBusState = SCS_INITIATOR;
        !           542:                        }
        !           543:                }
        !           544:                if (ioReturn != IO_R_SUCCESS) {
        !           545:                        [self fsmStartErrorRecovery
        !           546:                                                        : ioReturn
        !           547:                                        reason  : reason
        !           548:                        ];
        !           549:                }
        !           550:                EXIT();
        !           551: }
        !           552: 
        !           553: /*
        !           554:  * DMA Complete.
        !           555:  */
        !           556: - (void) fsmDMAComplete
        !           557: {
        !           558:                unsigned                bytesMoved;
        !           559: 
        !           560:                ENTRY("Bdc fsmDMAComplete");
        !           561:                ddmChip("fsmDMAComplete\n", 1,2,3,4,5);
        !           562:                ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !           563:                /*
        !           564:                 * Stop the dma engine and retrieve the total number of
        !           565:                 * bytes transferred. This will be
        !           566:                 *      gActiveCommand->thisTransferLength      The number of bytes requested
        !           567:                 *              - the current DMA residual count
        !           568:                 *              - the current FIFO residual count
        !           569:                 * Note that there may still be bytes in the fifo.
        !           570:                 */
        !           571:                bytesMoved = [self curioDMAComplete];
        !           572:                if ((gSaveStatus & sParityErr) != 0) {
        !           573:                        [self fsmStartErrorRecovery
        !           574:                                                        : SR_IOST_PARITY
        !           575:                                        reason  : "SCSI Data Parity Error"
        !           576:                        ];
        !           577:                }
        !           578:                else {
        !           579:                        /*
        !           580:                         * Continue following phase changes.
        !           581:                         */
        !           582:                        gBusState = SCS_INITIATOR;
        !           583:                }
        !           584:                EXIT();
        !           585: }
        !           586: 
        !           587: /*
        !           588:  * Just completed the SCMD_TRANSFER_INFO operation for message in. ACK is
        !           589:  * not asserted (we have not ACK'ed this byte). There is no parity error.
        !           590:  * We will not have a command if we're reselecting.
        !           591:  */
        !           592: - (void) fsmGettingMsg
        !           593: {
        !           594:                IOReturn                        ioReturn;
        !           595:                const char                      *reason         = NULL;
        !           596:                UInt32                          fifoCount;
        !           597:                UInt8                           msgInByte;
        !           598:                
        !           599:                ENTRY("Bmi fsmGettingMsg");
        !           600:                ioReturn = IO_R_SUCCESS;
        !           601:                if (gFlagBusBusy == FALSE) {
        !           602:                        ddmChip("fsmGettingMsg: message In Disconnect\n", 1,2,3,4,5);
        !           603:                        /*
        !           604:                         * This (non-fatal) error is handled on return...
        !           605:                         */
        !           606:                        ioReturn = IO_R_INTERNAL;       /* Any non-zero non-fatal error status  */
        !           607:                }
        !           608:                else {
        !           609:            SynchronizeIO();
        !           610:            fifoCount = CURIOgetFifoCount();
        !           611:                        if (fifoCount != 1) {
        !           612:                                ddmChip("Message in fifo count error, count = %d\n",
        !           613:                                        fifoCount,
        !           614:                                        2, 3, 4, 5
        !           615:                                );
        !           616:                                ioReturn = SR_IOST_HW;
        !           617:                                reason = "Message in fifo count error";
        !           618:                        }
        !           619:                }
        !           620:                if (ioReturn == IO_R_SUCCESS) {
        !           621:            SynchronizeIO();
        !           622:            msgInByte = CURIOgetFifoByte();
        !           623:                        if ((gSaveStatus & sParityErr) != 0) {
        !           624:                                ioReturn = SR_IOST_PARITY;
        !           625:                                reason = "Parity error getting Command Complete message";
        !           626:                        }
        !           627:                }
        !           628:                if (ioReturn == IO_R_SUCCESS) {
        !           629:                        if (gMsgInState == kMsgInIdle) {
        !           630:                                gMsgInCount = 0;
        !           631:                                gMsgInIndex = 0;
        !           632:                        }
        !           633:                        if (gMsgInIndex >= kMessageInBufferLength) {
        !           634:                                ioReturn = SR_IOST_HW;
        !           635:                                reason = "Message in too many bytes";
        !           636:                        }
        !           637:                }
        !           638:                if (ioReturn == IO_R_SUCCESS) {
        !           639:                        gMsgInBuffer[gMsgInIndex++] = msgInByte;
        !           640:                        switch (gMsgInState) {
        !           641:                        case kMsgInIdle:
        !           642:                                /*
        !           643:                                 * This is the first message byte. Check for 1-byte codes.
        !           644:                                 */
        !           645:                                ddmChip("fsmGettingMsg: msgByte = 0x%x (%s)\n",
        !           646:                                        msgInByte,
        !           647:                                        IOFindNameForValue(msgInByte, scsiMsgValues),
        !           648:                                        3, 4, 5
        !           649:                                );
        !           650:                                if ((/* msgInByte >= kScsiMsgOneByteMin && */ msgInByte <= kScsiMsgOneByteMax)
        !           651:                                 || msgInByte >= kScsiMsgIdentify) {
        !           652:                                        gMsgInState = kMsgInReady;
        !           653:                                }
        !           654:                                else if (msgInByte >= kScsiMsgTwoByteMin
        !           655:                                          && msgInByte <= kScsiMsgTwoByteMax) {
        !           656:                                        /*
        !           657:                                         * This is a two-byte message. Set the count and
        !           658:                                         * read the next byte.
        !           659:                                         */
        !           660:                    gMsgInState = kMsgInReading;        /* Need one more    */
        !           661:                                        gMsgInCount = 1;
        !           662:                                }
        !           663:                                else {
        !           664:                                        /*
        !           665:                                         * This is an extended message. The next byte has the count.
        !           666:                                         */
        !           667:                                        gMsgInState = kMsgInCounting;
        !           668:                                }
        !           669:                                break;
        !           670:                        case kMsgInCounting:
        !           671:                                /*
        !           672:                                 * Read the count byte of an extended message.
        !           673:                                 */
        !           674:                                gMsgInCount = msgInByte;
        !           675:                                gMsgInState = kMsgInReading;
        !           676:                                break;
        !           677:                        case kMsgInReading:
        !           678:                                if (--gMsgInCount <= 0) {
        !           679:                                        gMsgInState = kMsgInReady;
        !           680:                                }
        !           681:                                break;
        !           682:                        default:
        !           683:                                ASSERT(gMsgInState != 0xDEADBEEF /* Bogus state */);
        !           684:                                ioReturn = SR_IOST_BV;
        !           685:                                reason = "Message in bogus state";
        !           686:                        } /* Switch on message state */
        !           687:                }
        !           688:                if (ioReturn == IO_R_SUCCESS) {
        !           689:                        switch (gMsgInState) {
        !           690:                        case kMsgInReading:
        !           691:                        case kMsgInCounting:
        !           692:                                /*
        !           693:                                 * We have more message bytes to read. Accept this byte
        !           694:                                 * (this sets ACK) and setup to transfer the next byte.
        !           695:                                 */
        !           696:                CURIOmessageAccept();
        !           697:                                /*
        !           698:                                 * Since the message accept command sets "interrupt", eat
        !           699:                                 * it here so we don't get a second interrupt.
        !           700:                                 */
        !           701:                CURIOquickCheckForChipInterrupt();
        !           702:                CURIOstartMSGIAction();
        !           703:                                gBusState = SCS_GETTINGMSG;
        !           704:                                /*
        !           705:                                 * This would be a good place to spin-wait for
        !           706:                                 * completion, continuing at the start of this
        !           707:                                 * method if there is another byte (and we're still
        !           708:                                 * in message in phase). Perhaps this method should
        !           709:                                 * return a "spinwait" status to the mainline FSM.
        !           710:                                 */
        !           711:                                break;
        !           712:                        case kMsgInReady:
        !           713:                                gMsgInState = kMsgInIdle;
        !           714:                                ioReturn = [self fsmProcessMessage];
        !           715:                                if (ioReturn != IO_R_SUCCESS) {
        !           716:                                        reason = "Can't process received message";
        !           717:                                }
        !           718:                                break;
        !           719:                        case kMsgInIdle:
        !           720:                        default:
        !           721:                                /*
        !           722:                                 * Hmm, that's strange: we should never be in idle state
        !           723:                                 * *after* successfully reading a message byte.
        !           724:                                 */
        !           725:                                ioReturn = SR_IOST_BV;
        !           726:                                reason = "Getting message: bogus idle state";
        !           727:                                break;
        !           728:                        }
        !           729:                }
        !           730:                if (ioReturn != IO_R_SUCCESS) {
        !           731:                        [self fsmStartErrorRecovery
        !           732:                                                        : ioReturn
        !           733:                                        reason  : reason
        !           734:                        ];
        !           735:                }
        !           736:                EXIT();
        !           737: }
        !           738: 
        !           739: /*
        !           740:  * Just finished a message in; ACK is false and the message has been read
        !           741:  * into gMsgInBuffer[0..gMsgInIndex]. We have not ACK'ed the last byte yet.
        !           742:  * If we fail here, the caller will start error recovery.
        !           743:  */
        !           744: - (IOReturn) fsmProcessMessage
        !           745: {
        !           746:                IOReturn                        ioReturn                        = IO_R_SUCCESS;
        !           747:                const char                      *reason                         = "(Unknown)";
        !           748:                UInt8                           queueTag                        = QUEUE_TAG_NONTAGGED;
        !           749:                Boolean                         messageAckNeeded        = TRUE;
        !           750: 
        !           751:                ENTRY("Bmp fsmProcessMessage");
        !           752:                RAW_TAG(OSTag('*', "msg"), gMsgInBuffer[0]);
        !           753:                /*
        !           754:                 * Message in complete. Handle message(s) in currMsgIn[].
        !           755:                 */
        !           756:                if (gBusState == SCS_RESELECTING) {
        !           757:                        /*
        !           758:                         * The only interesting message here is queue tag.
        !           759:                         * (Hmm, what about target SDTR or Abort?)
        !           760:                         */
        !           761:                        ASSERT(gActiveCommand == NULL);
        !           762:                        ASSERT(gCurrentTarget != kInvalidTarget && gCurrentLUN != kInvalidLUN);
        !           763:                        ASSERT(gMsgInIndex > 0);
        !           764:                        switch (gMsgInBuffer[0]) {
        !           765:                        case kScsiMsgHeadOfQueueTag:
        !           766:                        case kScsiMsgOrderedQueueTag:
        !           767:                        case kScsiMsgSimpleQueueTag:
        !           768:                                if (gMsgInIndex != 2) {
        !           769:                                        ioReturn = SR_IOST_HW;
        !           770:                                        reason = "Queue tag message: queue tag without tag value";
        !           771:                                }
        !           772:                                else {
        !           773:                                        ioReturn = [self reselectNexusWithTag : gMsgInBuffer[1]];
        !           774:                                        if (ioReturn != IO_R_SUCCESS) {
        !           775:                                                reason = "Tagged queue reselection failed to locate command";
        !           776:                                        }
        !           777:                                }
        !           778:                                break;
        !           779:                        default:
        !           780:                                ddmError("Strange message byte %02x from %d.%d while reselecting (expect tag)\n",
        !           781:                                        gMsgInBuffer[0],
        !           782:                                        gCurrentTarget,
        !           783:                                        gCurrentLUN,
        !           784:                                        4, 5
        !           785:                                );
        !           786:                                ioReturn = SR_IOST_HW;
        !           787:                                reason = "Reselection failed (expecting queue tag message)";
        !           788:                                break;                          
        !           789:                        }
        !           790:                        if (ioReturn == IO_R_SUCCESS) {
        !           791:                                ASSERT(gActiveCommand != NULL);
        !           792:                                gActiveCommand->currentDataIndex = gActiveCommand->savedDataIndex;
        !           793:                if (gActiveCommand->mem != NULL) {
        !           794:                    [gActiveCommand->mem setState : &gActiveCommand->savedDataState];
        !           795:                }
        !           796:                        }
        !           797:                        /*
        !           798:                         * Since we process commands one by one, whack this command
        !           799:                         * so we fall through the regular message handler.
        !           800:                         */
        !           801:                        gMsgInBuffer[0] = kScsiMsgNop;
        !           802:                        gMsgInIndex = 1;
        !           803:                }
        !           804:                gBusState                                       = SCS_INITIATOR;
        !           805:                gFlagNeedAnotherInterrupt       = TRUE;
        !           806: 
        !           807:                switch (gMsgInBuffer[0]) {
        !           808:                case kScsiMsgNop:
        !           809:                        break;
        !           810:                case kScsiMsgCmdComplete:
        !           811:                        /*
        !           812:                         * Normally, we get here from fsmCommandComplete. All we need
        !           813:                         * to do is to ack the message and complete the command. Exit
        !           814:                         * in a transitional bus state that becomes SCS_DISCONNECTED
        !           815:                         * when the bus is no longer busy. 
        !           816:                         */
        !           817:                        gBusState = SCS_WAIT_FOR_BUS_FREE;
        !           818:                        /* gFlagBusBusy = FALSE;        -- Radar 1678545: wait for interrupt */
        !           819:                        if (gActiveCommand != NULL) {
        !           820:                [self ioComplete
        !           821:                            : gActiveCommand
        !           822:                    finalStatus : SR_IOST_GOOD
        !           823:                ];
        !           824:                        }
        !           825:                        ASSERT(gActiveCommand == NULL);
        !           826:                        break;
        !           827: 
        !           828:                case kScsiMsgDisconnect:
        !           829:                        ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !           830:                        if (gActiveCommand->scsiReq->disconnect == FALSE) {
        !           831:                                /*
        !           832:                                 * This is bogus; we could do a message reject, but
        !           833:                                 * ignoring it is simpler and, probably better.
        !           834:                                 */
        !           835:                                ddmChip("Illegal disconnect for %d.%d\n",
        !           836:                                        gActiveCommand->scsiReq->target,
        !           837:                                        gActiveCommand->scsiReq->lun,
        !           838:                                        3, 4, 5
        !           839:                                );
        !           840: #if LOG_ERROR_RECOVERY
        !           841:                                IOLog("%s: Unexpected disconnect attempt from target %d.%d\n",
        !           842:                                                [self name],
        !           843:                                                gActiveCommand->scsiReq->target,
        !           844:                                                gActiveCommand->scsiReq->lun
        !           845:                                );
        !           846: #endif /* LOG_ERROR_RECOVERY */
        !           847:                        }
        !           848:                        else {
        !           849:                                /*
        !           850:                                 * Some targets fail to do a restore pointers before
        !           851:                                 * disconnect if all requested data has been transferred.
        !           852:                                 * Do an implied save pointers if this is the case.
        !           853:                                 */
        !           854:                                if ( gActiveCommand->currentDataIndex >= gActiveCommand->scsiReq->maxTransfer )
        !           855:                                         gActiveCommand->savedDataIndex = gActiveCommand->currentDataIndex;
        !           856: 
        !           857:                                if ( gActiveCommand->mem != NULL )
        !           858:                                           [ gActiveCommand->mem state : &gActiveCommand->savedDataState ];
        !           859:                                [ self disconnect ];
        !           860:                        }
        !           861:                        /*
        !           862:                         * Exit the interrupt service routine so we don't miss a reselection interrupt.
        !           863:                         */
        !           864:                        /* gFlagBusBusy = FALSE;        -- Radar 1678545: wait for interrupt */
        !           865:                        gBusState = SCS_WAIT_FOR_BUS_FREE;
        !           866:                        gFlagCheckForAnotherInterrupt = FALSE;
        !           867:                        break;
        !           868:                case kScsiMsgSaveDataPointers:
        !           869:                        ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !           870:                        gActiveCommand->savedDataIndex = gActiveCommand->currentDataIndex;
        !           871:            if (gActiveCommand->mem != NULL) {
        !           872:                [gActiveCommand->mem state : &gActiveCommand->savedDataState];
        !           873:            }
        !           874:                        break;
        !           875:                case kScsiMsgRestorePointers:
        !           876:                        ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !           877:                        gActiveCommand->currentDataIndex = gActiveCommand->savedDataIndex;
        !           878:            if (gActiveCommand->mem != NULL) {
        !           879:                [gActiveCommand->mem setState : &gActiveCommand->savedDataState];
        !           880:            }
        !           881:                        break;
        !           882:                case kScsiMsgRejectMsg:
        !           883:                        /*
        !           884:                         * Hmm, the only message reject we should see would have to be
        !           885:                         * a queue tag (to a device that doesn't do queuing).
        !           886:                         */
        !           887:                        switch (gLastMsgOut[0]) {
        !           888:                        case kScsiMsgHeadOfQueueTag:
        !           889:                        case kScsiMsgOrderedQueueTag:
        !           890:                        case kScsiMsgSimpleQueueTag:
        !           891:                                [self disableMode : kTargetModeCmdQueue];
        !           892:                                break;
        !           893:                        default:
        !           894:                                if (gLastMsgOut[0] >= kScsiMsgIdentify
        !           895:                                 && (gLastMsgOut[0] & 0x07) != 0) {
        !           896:                                        ddmError("Target %d.%d rejected Identify message %02x\n",
        !           897:                                                gCurrentTarget,
        !           898:                                                gCurrentLUN,
        !           899:                                                gLastMsgOut[0],
        !           900:                                                4, 5
        !           901:                                        );
        !           902: #if LOG_ERROR_RECOVERY
        !           903:                                        /*
        !           904:                                         * The target rejected an identify message for a non-zero
        !           905:                                         * LUN. We treat this as a selection failure and tell the
        !           906:                                         * target to get off the bus.
        !           907:                                         */
        !           908:                                        IOLog("%s: Target %d.%d rejected Identify message %02x\n",
        !           909:                                                [self name],
        !           910:                                                gCurrentTarget,
        !           911:                                                gCurrentLUN,
        !           912:                                                gLastMsgOut[0]
        !           913:                                        );
        !           914: #endif /* LOG_ERROR_RECOVERY */
        !           915:                                        /*
        !           916:                                         * When we send an Abort to a target, we expect that it
        !           917:                                         * will immediately go to bus free. Unfortunately, some
        !           918:                                         * targets go to MSGI and send us an Abort, too.
        !           919:                                         */
        !           920:                                        if (gActiveCommand != NULL) {
        !           921:                                                if (gActiveCommand->scsiReq != NULL
        !           922:                                                 && gActiveCommand->scsiReq->driverStatus == SR_IOST_INVALID) {
        !           923: #if 0
        !           924:                        IOLog("fsmProcessMsg abort: timeout, target %d, int %02x, status %02x, step %02x\n",
        !           925:                                gActiveCommand->scsiReq->target,
        !           926:                                gSaveInterrupt & 0xFF,
        !           927:                                gSaveStatus & 0xFF,
        !           928:                                gSaveSeqStep & 0xFF
        !           929:                        );
        !           930: #endif 
        !           931:                                                        gActiveCommand->scsiReq->driverStatus = SR_IOST_SELTO;
        !           932:                                                }
        !           933:                                                /* [self ioComplete : gActiveCommand];  970610  */
        !           934:                                        }
        !           935:                                }
        !           936:                                else {
        !           937:                                        ddmError("%s Message rejected from target %d.%d\n",
        !           938:                                                IOFindNameForValue(gLastMsgOut[0], scsiMsgValues),
        !           939:                                                gCurrentTarget,
        !           940:                                                gCurrentLUN,
        !           941:                                                4, 5
        !           942:                                        );
        !           943: #if LOG_ERROR_RECOVERY
        !           944:                                        IOLog("%s: %s Message Rejected, that's strange.\n",
        !           945:                                                [self name],
        !           946:                                                IOFindNameForValue(gLastMsgOut[0], scsiMsgValues)
        !           947:                                        );
        !           948: #endif /* LOG_ERROR_RECOVERY */
        !           949:                                        ioReturn = SR_IOST_HW;                          /* 970610 */
        !           950:                                }
        !           951:                                /* ioReturn = SR_IOST_HW;       970610 */
        !           952:                                break;
        !           953:                        }
        !           954:                case kScsiMsgAbort:
        !           955:                case kScsiMsgAbortTag:
        !           956:                        if (gActiveCommand != NULL && gActiveCommand->scsiReq != NULL) {
        !           957:                                /*
        !           958:                                        * Oops: something is terribly wrong with this command.
        !           959:                                        * This can happen if we get a parity error, set ATN,
        !           960:                                        * and send an inititor detected error to the target.
        !           961:                                        */
        !           962:                                if (gCurrentTarget != kInvalidTarget) {
        !           963:                                        ddmError("Target %d.%d aborted request\n",
        !           964:                                                gCurrentTarget,
        !           965:                                                gCurrentLUN,
        !           966:                                                3, 4, 5
        !           967:                                        );
        !           968: #if LOG_ERROR_RECOVERY
        !           969:                                        IOLog("%s: Target %d.%d aborted request\n",
        !           970:                                                [self name],
        !           971:                                                gCurrentTarget,
        !           972:                                                gCurrentLUN
        !           973:                                        );
        !           974: #endif /* LOG_ERROR_RECOVERY */
        !           975:                                }
        !           976:                [self ioComplete
        !           977:                            : gActiveCommand
        !           978:                    finalStatus : SR_IOST_HW
        !           979:                ];
        !           980:                                gFlagCheckForAnotherInterrupt = FALSE;
        !           981:                                ASSERT(gActiveCommand == NULL);
        !           982:                        }
        !           983:                        /*
        !           984:                         * After receiving an Abort, the target will go free
        !           985:                         */
        !           986:                        /* gFlagBusBusy = FALSE;        -- Radar 1678545: wait for interrupt */
        !           987:                        gBusState = SCS_WAIT_FOR_BUS_FREE;
        !           988:                        break;
        !           989:                case kScsiMsgLinkedCmdComplete:
        !           990:                case kScsiMsgLinkedCmdCompleteFlag:
        !           991:                        ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !           992:                        /*
        !           993:                         * These are impossible: we reject commands with the link bit set.
        !           994:                         * About all we can do is to fail the client's command and
        !           995:                         * stagger onwards.
        !           996:                         */
        !           997:                        IOLog("%s: Target %d.%d terminated with unexpected linked command complete\n",
        !           998:                                [self name],
        !           999:                                gActiveCommand->scsiReq->target,
        !          1000:                                gActiveCommand->scsiReq->lun
        !          1001:                        );
        !          1002:            [self ioComplete
        !          1003:                        : gActiveCommand
        !          1004:                finalStatus : SR_IOST_HW
        !          1005:            ];
        !          1006:                        ASSERT(gActiveCommand == NULL);
        !          1007:                        /* gFlagBusBusy = FALSE;        -- Radar 1678545: wait for interrupt */
        !          1008:                        gBusState = SCS_WAIT_FOR_BUS_FREE;
        !          1009:                        break;
        !          1010:                case kScsiMsgExtended:
        !          1011:                        ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !          1012:                        /*
        !          1013:                         * The only expected extended message is synchronous negotiation.
        !          1014:                         * We don't support this yet.
        !          1015:                         */
        !          1016:                        switch (gMsgInBuffer[2]) {
        !          1017:                        case kScsiMsgSyncXferReq:
        !          1018:                                /*
        !          1019:                                 * We don't support SDTR (yet), so send a message reject
        !          1020:                                 * (Perhaps it would be better to send an "async only" response,
        !          1021:                                 * but message reject is legal.)
        !          1022:                                 */
        !          1023:                CURIOmessageReject();
        !          1024:                                messageAckNeeded = FALSE;
        !          1025:                                break;
        !          1026:                        default:
        !          1027:                                ddmError("Unexpected Extended Message (0x%x) received"
        !          1028:                                                "from target %d.%d\n",
        !          1029:                                        gMsgInBuffer[2],
        !          1030:                                        gActiveCommand->scsiReq->target,
        !          1031:                                        gActiveCommand->scsiReq->lun,
        !          1032:                                        4, 5
        !          1033:                                );
        !          1034:                CURIOmessageReject();
        !          1035:                                messageAckNeeded = FALSE;
        !          1036:                                break;
        !          1037:                        }
        !          1038:                        break;
        !          1039:                default:
        !          1040:                        /*
        !          1041:                         * all others are unacceptable. 
        !          1042:                         */
        !          1043:                        ddmError("Unsupported message (0x%x) received"
        !          1044:                                        " from target %d.%d \n", 
        !          1045:                                gMsgInBuffer[0],
        !          1046:                                gCurrentTarget,
        !          1047:                                gCurrentLUN,
        !          1048:                                4, 5
        !          1049:                        );
        !          1050:            CURIOmessageReject();
        !          1051:                        messageAckNeeded = FALSE;
        !          1052:                } /* Message byte switch */
        !          1053:                if (messageAckNeeded) {
        !          1054:            CURIOmessageAccept();
        !          1055:                }
        !          1056:                if (ioReturn != IO_R_SUCCESS && gCurrentTarget != kInvalidTarget) {
        !          1057:                        ddmError("Message from target %d.%d failed: %s\n",
        !          1058:                                gCurrentTarget,
        !          1059:                                gCurrentLUN,
        !          1060:                                reason,
        !          1061:                                4, 5
        !          1062:                        );
        !          1063:                }
        !          1064:                RESULT(ioReturn);
        !          1065:                return (ioReturn);
        !          1066: }
        !          1067: 
        !          1068: /*
        !          1069:  * This writes the message byte into the staging buffer. When the target
        !          1070:  * cycles to MSGO phase, we will send the message from the state automaton.
        !          1071:  */
        !          1072: - (void) putMessageOutByte
        !          1073:                                                : (UInt8)       messageByte
        !          1074:                        setATN          : (Boolean) setATN
        !          1075: {
        !          1076:                ENTRY("Bmo putMessageOutByte");
        !          1077:                ASSERT(gMsgOutPtr < &gMsgOutBuffer[kMessageOutBufferLength]);
        !          1078:                ASSERT(gMsgPutPtr <= gMsgOutPtr);
        !          1079:                *gMsgOutPtr++ = messageByte;
        !          1080:                if (setATN) {
        !          1081:            CURIOsetATN();
        !          1082:                }
        !          1083:                EXIT();
        !          1084: }
        !          1085: 
        !          1086: /*
        !          1087:  * Just completed the SCMD_TRANSFER_INFO operation for message out. 
        !          1088:  */
        !          1089: - (void) fsmSendingMsg
        !          1090: {
        !          1091:                ENTRY("Bms fsmSendingMsg");
        !          1092:                ddmChip("fsmSendingMsg\n", 1,2,3,4,5);
        !          1093:                ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !          1094:                EXIT();
        !          1095: }
        !          1096: 
        !          1097: /*
        !          1098:  * Just completed the SCMD_TRANSFER_INFO operation for command.
        !          1099:  */
        !          1100: - (void) fsmSendingCmd
        !          1101: {
        !          1102:                ENTRY("Bmc fsmSendingCmd");
        !          1103:                ddmChip("fsmSendingCmd\n", 1,2,3,4,5);
        !          1104:                ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !          1105:                gBusState = SCS_INITIATOR;
        !          1106:                EXIT();
        !          1107: }
        !          1108: 
        !          1109: /*
        !          1110:  * Continue to process reselection interrupts. We expect to be in
        !          1111:  * message in phase in order to get the tagged queue message. Anything
        !          1112:  * else is an error.
        !          1113:  */
        !          1114: - (void) fsmReselecting
        !          1115: {
        !          1116:                ENTRY("Bre fsmReselecting");
        !          1117: 
        !          1118:                [self fsmGettingMsg];
        !          1119:                if (gBusState == SCS_GETTINGMSG) {
        !          1120:                        gBusState = SCS_RESELECTING;    /* continue at fsmReselectinAction */
        !          1121:                }
        !          1122:                EXIT();
        !          1123: }
        !          1124: 
        !          1125: /*
        !          1126:  * Complete the processing of a reselection interrupt. We have just ack'ed
        !          1127:  * the identify message. Try to find the command that corresponds to this
        !          1128:  * target.lun (without a queue tag). If we're successful, complete the
        !          1129:  * reselection and start following phases by calling fsmPhaseChange directly.
        !          1130:  * If the first disconnected command has a non-zero tag queue, we expect to
        !          1131:  * be in messsage in phase, and will receive a tagged queue message in the
        !          1132:  * fullness of time.
        !          1133:  */
        !          1134: - (void) fsmReselectionAction
        !          1135: {
        !          1136:                IOReturn                        ioReturn;
        !          1137: 
        !          1138:                ENTRY("Bra fsmReselectionAction");
        !          1139:                ioReturn = [self reselectNexusWithoutTag];
        !          1140:                if (ioReturn == IO_R_SUCCESS) {
        !          1141:                        /*
        !          1142:                         * We have successfully reselected this target.
        !          1143:                         * Vamp until the target tells us what to do next.
        !          1144:                         */
        !          1145:                //      [self fsmPhaseChange];  // mlj ???
        !          1146:                        gBusState = SCS_INITIATOR;
        !          1147:                }
        !          1148:                else {
        !          1149:                        /*
        !          1150:                         * We don't have a nexus yet. If we're in MSGI phase,
        !          1151:                         * continue grabbing message bytes until we receive
        !          1152:                         * a queue tag message (we might receive an SDTR),
        !          1153:                         * continuing at fsmReselecting to process interrupts.
        !          1154:                         */
        !          1155:                        gCurrentBusPhase = gSaveStatus & mPhase;
        !          1156:                        // [curioQuickCheckForChipInterrupt];
        !          1157:                        if (gCurrentBusPhase == kBusPhaseMSGI) {
        !          1158:                CURIOstartMSGIAction();
        !          1159:                        }
        !          1160:                        else {
        !          1161:                                /*
        !          1162:                                 * We're in the wrong phase. Bail out.
        !          1163:                                 */
        !          1164:                                [self fsmStartErrorRecovery
        !          1165:                                                                : ioReturn
        !          1166:                                                reason  : "Unexpected SCSI bus phase while reselecting"
        !          1167:                                ];
        !          1168:                        }
        !          1169:                }
        !          1170:                EXIT();
        !          1171: }
        !          1172: 
        !          1173: 
        !          1174: /*
        !          1175:  * Follow SCSI Phase change. Called while SCS_INITIATOR. 
        !          1176:  */
        !          1177: - (void) fsmPhaseChange
        !          1178: {
        !          1179:                int                             i;
        !          1180: 
        !          1181:                ENTRY("Bph fsmPhaseChange");
        !          1182:                ddmChip("fsmPhaseChange, target %d.%d\n", 
        !          1183:                        gCurrentTarget,
        !          1184:                        gCurrentLUN,
        !          1185:                        3, 4, 5
        !          1186:                );
        !          1187:                gCurrentBusPhase = gSaveStatus & mPhase;
        !          1188:                ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !          1189:                ASSERT(gCurrentTarget   == gActiveCommand->scsiReq->target);
        !          1190:                ASSERT(gCurrentLUN              == gActiveCommand->scsiReq->lun);
        !          1191:                ddmChip("fsmPhaseChange:  phase = %s\n", 
        !          1192:                        IOFindNameForValue(gCurrentBusPhase, scsiPhaseValues),
        !          1193:                        2,3,4,5
        !          1194:                );
        !          1195:                switch (gCurrentBusPhase) {
        !          1196:                case kBusPhaseCMD:
        !          1197:                        /*
        !          1198:                         * The normal case here is after a host-initiated SDTR sequence. 
        !          1199:                         */
        !          1200:            CURIOflushFifo();
        !          1201:            CURIOputCommandIntoFifo();
        !          1202:            CURIOstartNonDMATransfer();
        !          1203:                        gMsgInState = kMsgInIdle;
        !          1204:                        gBusState = SCS_SENDINGCMD;
        !          1205:                        break;
        !          1206:                case kBusPhaseDATI:     /* From target to Initiator (read)      */
        !          1207:                case kBusPhaseDATO:     /* To Target from Initiator (write) */
        !          1208:                        gMsgInState = kMsgInIdle;
        !          1209:                        [self fsmStartDataPhase];
        !          1210:                        gFlagCheckForAnotherInterrupt = FALSE;
        !          1211:                        break;
        !          1212:                case kBusPhaseSTS:      /* Status from Target to Initiator */
        !          1213:                        /*
        !          1214:                         * fsmCompleting will collect the STATUS byte (and hopefully
        !          1215:                         * a MSG) from the fifo when this completes.
        !          1216:                         */
        !          1217:                        gMsgInState = kMsgInIdle;
        !          1218:                        gBusState = SCS_COMPLETING;
        !          1219:            CURIOflushFifo();
        !          1220:            CURIOinitiatorCommandComplete();
        !          1221:                        break;
        !          1222:                case kBusPhaseMSGI:     /* Message from Target to Initiator */
        !          1223:                        gBusState = SCS_GETTINGMSG;
        !          1224:            CURIOstartMSGIAction();
        !          1225:                        break;
        !          1226:                case kBusPhaseMSGO:     /* Message from Initiator to Target */
        !          1227:                        gMsgInState = kMsgInIdle;
        !          1228:            CURIOflushFifo();
        !          1229:                        if (gMsgPutPtr == gMsgOutPtr) {
        !          1230:                                /*
        !          1231:                                        * Hmm, there is no message waiting to be sent.
        !          1232:                                        */
        !          1233:                                *gMsgOutPtr++ = kScsiMsgNop;
        !          1234:                                ddmChip("msg out (%d.%d): forced nop\n",
        !          1235:                                        gCurrentTarget,
        !          1236:                                        gCurrentLUN,
        !          1237:                                        3, 4, 5
        !          1238:                                );
        !          1239:                        }
        !          1240:                        for (i = 0; i < 16 && gMsgPutPtr < gMsgOutPtr; i++) {
        !          1241:                                ddmChip("msg out[%d] = %02x\n", i, *gMsgPutPtr, 3, 4, 5);
        !          1242:                CURIOputByteIntoFifo(*gMsgPutPtr);
        !          1243:                gMsgPutPtr++;
        !          1244:                        }
        !          1245:                        if (gMsgPutPtr == gMsgOutPtr) {
        !          1246:                                gMsgPutPtr = gMsgOutPtr = gMsgOutBuffer;
        !          1247:                        }
        !          1248:                        gBusState = SCS_SENDINGMSG;
        !          1249:                        /* 
        !          1250:                         * ATN is automatically cleared when transfer info completes.
        !          1251:                         */
        !          1252:            CURIOstartNonDMATransfer();
        !          1253:                        break;
        !          1254:                default:
        !          1255:                        [self fsmStartErrorRecovery
        !          1256:                                                        : SR_IOST_HW
        !          1257:                                        reason  : "Strange bus phase"
        !          1258:                        ];
        !          1259:                        break;
        !          1260:                }
        !          1261:                EXIT();
        !          1262: }
        !          1263: 
        !          1264: - (void) fsmStartDataPhase
        !          1265: {
        !          1266:                UInt32                          phase;
        !          1267:                IOReturn                        ioReturn        = IO_R_SUCCESS;
        !          1268:                const char                      *reason         = NULL;
        !          1269:                Boolean                         isReadOK;
        !          1270: 
        !          1271: 
        !          1272:                ENTRY("Bdp startDataPhase");
        !          1273:                ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !          1274:                phase = gSaveStatus & mPhase;
        !          1275:                /*
        !          1276:                 * Data in phase is legal if this is a read command or we're
        !          1277:                 * doing autosense.
        !          1278:                 */
        !          1279:                isReadOK = (gActiveCommand->scsiReq->read || gActiveCommand->flagIsAutosense);
        !          1280:                if ((phase == kBusPhaseDATI) != isReadOK) {
        !          1281:                        ioReturn = SR_IOST_BV;
        !          1282:                        reason = "bad I/O direction";
        !          1283:                }
        !          1284:                if (ioReturn == IO_R_SUCCESS) {
        !          1285:                        ioReturn = [self hardwareInitializeCCL];
        !          1286:                        if (ioReturn != IO_R_SUCCESS) {
        !          1287:                                reason = "Cannot setup DBDMA Channel Command area";
        !          1288:                        }
        !          1289:                }
        !          1290:                if (ioReturn == IO_R_SUCCESS) {
        !          1291:                        if (gActiveCommand->thisTransferLength == 0) {
        !          1292:                                ioReturn = IO_R_BV;
        !          1293:                                reason = "No data for transfer";
        !          1294:                        }
        !          1295:                }
        !          1296:                if (ioReturn == IO_R_SUCCESS) {
        !          1297:                        DBDMASetCommandPtr((UInt32) gDBDMAChannelAddress);
        !          1298:            DBDMAstartTransfer();
        !          1299:            CURIOstartDMATransfer(gActiveCommand->thisTransferLength);
        !          1300:                        gBusState = SCS_DMACOMPLETE;
        !          1301:                }
        !          1302:                if (ioReturn != IO_R_SUCCESS) {
        !          1303:                        [self fsmStartErrorRecovery
        !          1304:                                                        : ioReturn
        !          1305:                                        reason  : "Illegal Data Phase (wrong direction or length error)"
        !          1306:                        ];
        !          1307:                }
        !          1308:                EXIT();
        !          1309: }
        !          1310: 
        !          1311: /*
        !          1312:  * Start error recovery by doing something reasonable for the current bus
        !          1313:  * phase. This is called when we enter error recovery (SCS_DEATH_MARCH)
        !          1314:  * from an interrupt or other bus phase action handler.
        !          1315:  */
        !          1316: - (void)                       fsmStartErrorRecovery
        !          1317:                                                : (sc_status_t) status
        !          1318:                        reason          : (const char *) reason
        !          1319: {
        !          1320:                ENTRY("Bes fsmStartErrorRecovery");
        !          1321:                TAG(__tag__, status);
        !          1322:                ddmChip("fsmStartErrorRecovery for %d.%d, phase \"%s\", status \"%s\": %s\n",
        !          1323:                        gCurrentTarget,
        !          1324:                        gCurrentLUN,
        !          1325:                        IOFindNameForValue(gCurrentBusPhase, scsiPhaseValues),
        !          1326:                        IOFindNameForValue(status, IOScStatusStrings),
        !          1327:                        (reason == NULL) ? "unspecified" : reason
        !          1328:                );
        !          1329: #if LOG_ERROR_RECOVERY
        !          1330:                if (gActiveCommand != NULL
        !          1331:                 && gActiveCommand->scsiReq != NULL
        !          1332:                 && gActiveCommand->scsiReq->target == gCurrentTarget
        !          1333:                 && gActiveCommand->scsiReq->lun == gCurrentLUN) {
        !          1334:                        IOLog("%s: Error recovery: active target %d.%d, error \"%s\" (\"%s\"), bus phase %s\n",
        !          1335:                                [self name],
        !          1336:                                gCurrentTarget,
        !          1337:                                gCurrentLUN,
        !          1338:                                IOFindNameForValue(status, IOScStatusStrings),
        !          1339:                                (reason == NULL) ? "no further explanation" : reason,
        !          1340:                                IOFindNameForValue(gCurrentBusPhase, scsiPhaseValues)
        !          1341:                        );
        !          1342:                }
        !          1343:                else if (gActiveCommand != NULL && gActiveCommand->scsiReq != NULL) {
        !          1344:                        IOLog("%s: Error recovery: command target %d.%d, error \"%s\" (\"%s\"), bus phase %s\n",
        !          1345:                                [self name],
        !          1346:                                gActiveCommand->scsiReq->target,
        !          1347:                                gActiveCommand->scsiReq->lun,
        !          1348:                                IOFindNameForValue(status, IOScStatusStrings),
        !          1349:                                (reason == NULL) ? "no further explanation" : reason,
        !          1350:                                IOFindNameForValue(gCurrentBusPhase, scsiPhaseValues)
        !          1351:                        );
        !          1352:                }
        !          1353:                else if (gCurrentTarget != kInvalidTarget && gCurrentLUN != kInvalidLUN) {
        !          1354:                        IOLog("%s: Error Recovery: expected target %d.%d, error \"%s\" (\"%s\"), bus phase %s\n",
        !          1355:                                [self name],
        !          1356:                                gCurrentTarget,
        !          1357:                                gCurrentLUN,
        !          1358:                                IOFindNameForValue(status, IOScStatusStrings),
        !          1359:                                (reason == NULL) ? "no further explanation" : reason,
        !          1360:                                IOFindNameForValue(gCurrentBusPhase, scsiPhaseValues)
        !          1361:                        );
        !          1362:                }
        !          1363:                else if (gCurrentTarget != kInvalidTarget && gCurrentLUN == kInvalidLUN) {
        !          1364:                        IOLog("%s: Error recovery: command target %d.[no lun], error \"%s\" (\"%s\"), bus phase %s\n",
        !          1365:                                [self name],
        !          1366:                                gCurrentTarget,
        !          1367:                                IOFindNameForValue(status, IOScStatusStrings),
        !          1368:                                (reason == NULL) ? "no further explanation" : reason,
        !          1369:                                IOFindNameForValue(gCurrentBusPhase, scsiPhaseValues)
        !          1370:                        );
        !          1371:                }
        !          1372:                else {
        !          1373:                        IOLog("%s: Error recovery: no current target, error \"%s\" (\"%s\"), bus phase %s\n",
        !          1374:                                [self name],
        !          1375:                                IOFindNameForValue(status, IOScStatusStrings),
        !          1376:                                (reason == NULL) ? "no further explanation" : reason,
        !          1377:                                IOFindNameForValue(gCurrentBusPhase, scsiPhaseValues)
        !          1378:                        );
        !          1379:                }
        !          1380:                [self logRegisters : FALSE reason : "At error recovery start"];
        !          1381: #endif /* LOG_ERROR_RECOVERY */
        !          1382:                [self killActiveCommand : status];
        !          1383:                /*
        !          1384:                 * Clean out the scsi and dbdma chips
        !          1385:                 */
        !          1386:        CURIOflushFifo();
        !          1387:        CURIOclearTransferCountZeroBit();
        !          1388:        DBDMAreset();
        !          1389:                if (gFlagBusBusy == FALSE) {
        !          1390:                        gBusState = SCS_DISCONNECTED;
        !          1391:                }
        !          1392:                else {
        !          1393:                        /*
        !          1394:                         * We will continue at fsmContinueErrorRecovery
        !          1395:                         */
        !          1396:                        gBusState = SCS_DEATH_MARCH;
        !          1397:                }
        !          1398:                gFlagCheckForAnotherInterrupt = FALSE;
        !          1399:                EXIT();
        !          1400: }
        !          1401: 
        !          1402: /*
        !          1403:  * Manage error recovery by responding to a target interrupt while in
        !          1404:  * an error recovery state. On exit, the bus state will be as follows:
        !          1405:  *     SCS_DEATH_MARCH         Still in error recovery. Call fsmContinueErrorRecovery
        !          1406:  *                                             to continue processing target requests.
        !          1407:  *     SCS_DISCONNECTED        The target is finally off the bus. We can restart
        !          1408:  *                                             normal operation.
        !          1409:  * Each bus phase requires a different action:
        !          1410:  *     Data Out        Clean up after DMA.
        !          1411:  *     Data In         Clean up after DMA.
        !          1412:  *     Command         Flush the fifo
        !          1413:  *     Status          Drain the fifo, if we get two bytes, just ACK the message
        !          1414:  *     Message Out     Do nothing
        !          1415:  *     Message In      Read the message byte, ACK it.
        !          1416:  */
        !          1417: - (void) fsmErrorRecoveryInterruptService
        !          1418: {
        !          1419:                ENTRY("Bei fsmErrorRecoveryInterruptService");
        !          1420: #if LOG_ERROR_RECOVERY
        !          1421:                [self logRegisters : FALSE reason : "At error recovery interrupt"];
        !          1422:                IOLog("%s: Error recovery interrupt in bus phase %s, sts %02x, int %02x\n",
        !          1423:                        [self name],
        !          1424:                        IOFindNameForValue(gSaveStatus & mPhase, scsiPhaseValues),
        !          1425:                        gSaveStatus,
        !          1426:                        gSaveInterrupt
        !          1427:                );
        !          1428:  #endif
        !          1429:        CURIOflushFifo();
        !          1430:                switch (gCurrentBusPhase) {
        !          1431:                case kBusPhaseDATO:
        !          1432:                case kBusPhaseDATI:
        !          1433: #if LOG_ERROR_RECOVERY
        !          1434:                        IOLog("%s: Error recovery interrupt in data in/out phase\n", [self name]);
        !          1435: #endif
        !          1436:            DBDMAreset();
        !          1437:            CURIOclearTransferCountZeroBit();
        !          1438:                        break;
        !          1439:                case kBusPhaseCMD:
        !          1440: #if LOG_ERROR_RECOVERY
        !          1441:                        IOLog("%s: Error recovery interrupt in command phase\n", [self name]);
        !          1442: #endif
        !          1443:                        break;
        !          1444:                case kBusPhaseSTS:
        !          1445: #if LOG_ERROR_RECOVERY
        !          1446:                        IOLog("%s: Error recovery interrupt in status phase\n", [self name]);
        !          1447: #endif
        !          1448:                        if ((gSaveInterrupt & iFuncComp) != 0) {
        !          1449: #if LOG_ERROR_RECOVERY
        !          1450:                                IOLog("%s: Error recovery interrupt in status phase with complete msg\n",
        !          1451:                                        [self name]
        !          1452:                                );
        !          1453: #endif
        !          1454:                                /*
        !          1455:                                 * We got both bytes: ACK the command complete
        !          1456:                                 */
        !          1457:                CURIOmessageAccept();
        !          1458:                        }
        !          1459:                        break;
        !          1460:                case kBusPhaseMSGO:
        !          1461: #if LOG_ERROR_RECOVERY
        !          1462:                        IOLog("%s: Error recovery interrupt in message out phase\n", [self name]);
        !          1463: #endif
        !          1464:                        break;
        !          1465:                case kBusPhaseMSGI:
        !          1466: #if LOG_ERROR_RECOVERY
        !          1467:                        IOLog("%s: Error recovery interrupt in message in phase\n", [self name]);
        !          1468: #endif
        !          1469:            CURIOmessageAccept();
        !          1470:                        break;
        !          1471:                case kBusPhaseBusFree:  /* Selecting */
        !          1472: #if LOG_ERROR_RECOVERY
        !          1473:                        IOLog("%s: Error recovery interrupt at bus free\n", [self name]);
        !          1474: #endif
        !          1475:                        break;
        !          1476:                default:
        !          1477: #if LOG_ERROR_RECOVERY
        !          1478:                        IOLog("%s: Strange bus phase %d in error recovery\n",
        !          1479:                                [self name],
        !          1480:                                gCurrentBusPhase
        !          1481:                        );
        !          1482: #endif
        !          1483:                        [self killActiveCommandAndResetBus
        !          1484:                                                : SR_IOST_HW
        !          1485:                                reason  : "Strange SCSI phase in error recovery interrupt"
        !          1486:                        ];
        !          1487:                        break;
        !          1488:                }
        !          1489:                EXIT();
        !          1490: }
        !          1491: 
        !          1492: /*
        !          1493:  * Continue to manage error recovery. We are here because the target
        !          1494:  * is still on the bus and doing strange bus phase things. Follow
        !          1495:  * the target bus phase (one phase at a time) until the target
        !          1496:  * disconnects. We just run bit-bucket commands until the target
        !          1497:  * gives up. (Note that this means that we might send a Command Complete
        !          1498:  * message to the target. We'll look for this case and send an Abort
        !          1499:  * or Abort Tag instead.)
        !          1500:  */
        !          1501: - (void)                       fsmContinueErrorRecovery
        !          1502: {
        !          1503:                UInt8                   msgByte;
        !          1504: 
        !          1505:                ENTRY("Bec fsmContinueErrorRecovery");
        !          1506:        CURIOquickCheckForChipInterrupt();
        !          1507: #if LOG_ERROR_RECOVERY
        !          1508:                IOLog("%s: Error recovery continues in bus phase %s, sts %02x, int %02x\n",
        !          1509:                        [self name],
        !          1510:                        IOFindNameForValue(gSaveStatus & mPhase, scsiPhaseValues),
        !          1511:                        gSaveStatus,
        !          1512:                        gSaveInterrupt
        !          1513:                );
        !          1514: #endif
        !          1515:                if (gFlagBusBusy) {
        !          1516:            (void) CURIOinterruptPending();
        !          1517:                        if ((gSaveInterrupt & iDisconnect) != 0) {
        !          1518:                                gFlagBusBusy = FALSE;
        !          1519:                        }
        !          1520:                }
        !          1521:                if (gFlagBusBusy == FALSE) {
        !          1522:                        gBusState = SCS_DISCONNECTED;
        !          1523:                }
        !          1524:                else {
        !          1525:                        gCurrentBusPhase = gSaveStatus & mPhase;
        !          1526:                        switch (gCurrentBusPhase) {
        !          1527:                        case kBusPhaseMSGO:
        !          1528:                                msgByte = kScsiMsgAbort;
        !          1529:                                if (gActiveCommand != NULL
        !          1530:                                 && gActiveCommand->queueTag != QUEUE_TAG_NONTAGGED) {
        !          1531:                                        msgByte = kScsiMsgAbortTag;
        !          1532:                                }
        !          1533:                CURIOputByteIntoFifo(msgByte);
        !          1534:                CURIOstartNonDMATransfer();
        !          1535:                                break;
        !          1536:                        case kBusPhaseDATO:
        !          1537:                        case kBusPhaseCMD:
        !          1538:                CURIOtransferPad(TRUE);             /* Output pad   */
        !          1539:                                break;
        !          1540:                        case kBusPhaseMSGI:
        !          1541:                        case kBusPhaseDATI:
        !          1542:                        case kBusPhaseSTS:
        !          1543:                CURIOtransferPad(FALSE);            /* Input pad    */
        !          1544:                                break;
        !          1545:                        default:
        !          1546:                                [self killActiveCommandAndResetBus
        !          1547:                                                : SR_IOST_HW
        !          1548:                                        reason  : "Strange SCSI phase in error recovery"
        !          1549:                                ];
        !          1550:                                break;
        !          1551:                        }
        !          1552:                }
        !          1553: #if LOG_ERROR_RECOVERY
        !          1554:                [self logRegisters : FALSE reason : "Registers at error recovery action exit"];
        !          1555: #endif /* -Debug */
        !          1556:                EXIT();
        !          1557: }
        !          1558: 
        !          1559: /*
        !          1560:  * Disable specified mode for gActiveCommand's target. If mode is currently 
        !          1561:  * enabled, we'll log a message to the console.
        !          1562:  */
        !          1563: - (void) disableMode : (TargetMode) mode
        !          1564: {
        !          1565:                int                                     target;
        !          1566:                PerTargetData           *perTargetPtr;
        !          1567:                const char                      *modeStr = NULL;
        !          1568: 
        !          1569:                ENTRY("Bdm disableMode");
        !          1570:                ASSERT(gActiveCommand != NULL && gActiveCommand->scsiReq != NULL);
        !          1571:                target = gActiveCommand->scsiReq->target;
        !          1572:                perTargetPtr = &gPerTargetData[target];
        !          1573:                switch (mode) {
        !          1574:                case kTargetModeCmdQueue:
        !          1575:                        if (perTargetPtr->cmdQueueDisable == 0) {
        !          1576:                                perTargetPtr->cmdQueueDisable = 1;
        !          1577:                                modeStr = "Command Queueing";
        !          1578:                        }
        !          1579:                        break;
        !          1580:                default:
        !          1581:                        IOLog("%s: Bogus target mode %d for target %d\n",
        !          1582:                                [self name],
        !          1583:                                mode,
        !          1584:                                target
        !          1585:                        );
        !          1586:                        break;
        !          1587:                }
        !          1588:                ddmChip("DISABLING %s for target %d\n", modeStr, target, 3,4,5);
        !          1589:                if (modeStr != NULL) {
        !          1590:                        IOLog("%s: DISABLING %s for target %d\n",
        !          1591:                                [self name],
        !          1592:                                modeStr,
        !          1593:                                target
        !          1594:                        );
        !          1595:                }
        !          1596:                EXIT();
        !          1597: }
        !          1598: 
        !          1599: /**
        !          1600:  * Validate the target's reselection byte (put on the bus before
        !          1601:  * reselecting us). Erase the initiator ID and convert the other
        !          1602:  * bit into an index. The algorithm should be faster than a
        !          1603:  * sequential search, but it probably doesn't matter much.
        !          1604:  * @return     TRUE if successful (gCurrentTarget is now valid).
        !          1605:  *                     This function does not check whether there actually
        !          1606:  *                     is a command pending for this target.
        !          1607:  */
        !          1608: - (IOReturn) getReselectionTargetID
        !          1609:                                                : (UInt8) selectByte
        !          1610: {
        !          1611:                IOReturn                        ioReturn        = SR_IOST_BV;
        !          1612:                register UInt8          targetBits      = selectByte;
        !          1613:                register UInt8          targetID        = 0;
        !          1614:                register UInt8          bitValue        = 0;    /* Supress warning      */
        !          1615: 
        !          1616:                ENTRY("Brt getReselectionTargetID");
        !          1617:                if ((targetBits & gInitiatorIDMask) == 0) {
        !          1618:                        IOLog("%s: Reselection failed: initiator ID bit not set, got %02x\n",
        !          1619:                                [self name],
        !          1620:                                selectByte
        !          1621:                        );
        !          1622:                }
        !          1623:                else {
        !          1624:                        targetBits &= ~gInitiatorIDMask;                        /* Remove our bit                       */
        !          1625:                        if (targetBits == 0) {
        !          1626:                                IOLog("%s: Reselection failed: target ID bit not set, got %02x\n",
        !          1627:                                        [self name],
        !          1628:                                        selectByte
        !          1629:                                );
        !          1630:                        }
        !          1631:                        else {
        !          1632:                                bitValue                = targetBits;
        !          1633:                                if ((bitValue > 0x0F) != 0) {
        !          1634:                                        targetID        += 4;
        !          1635:                                        bitValue        >>= 4;
        !          1636:                                }
        !          1637:                                if ((bitValue > 0x03) != 0) {
        !          1638:                                        targetID        += 2;
        !          1639:                                        bitValue        >>= 2;
        !          1640:                                }
        !          1641:                                if ((bitValue > 0x01) != 0) {
        !          1642:                                        targetID        += 1;
        !          1643:                                }
        !          1644:                targetBits      &= ~(1 << targetID);    /* Remove the target mask   */
        !          1645:                                if (targetBits == 0) {                                  /* Was exactly one set?         */
        !          1646:                                        ioReturn = IO_R_SUCCESS;                        /* Yes: success!                        */
        !          1647:                    gCurrentTarget = targetID;          /* Save the current target  */
        !          1648:                                        ddmChip("Reselection from target %d\n",
        !          1649:                                                gCurrentTarget,
        !          1650:                                                2, 3, 4, 5
        !          1651:                                        );
        !          1652:                                }
        !          1653:                                else {
        !          1654:                                        IOLog("%s: Reselection failed, multiple targets, got %02x\n",
        !          1655:                                                [self name],
        !          1656:                                                selectByte
        !          1657:                                        );
        !          1658:                                }
        !          1659:                        }
        !          1660:                }
        !          1661:                RESULT(ioReturn);
        !          1662:                return (ioReturn);
        !          1663: }
        !          1664: 
        !          1665: @end   /* Apple96_SCSI(BusState) */

unix.superglobalmegacorp.com

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