Annotation of kernel/bsd/dev/ppc/drvApple96_SCSI/Apple96BusState.m, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
                      3:  *
                      4:  * @APPLE_LICENSE_HEADER_START@
                      5:  * 
                      6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
                      7:  * Reserved.  This file contains Original Code and/or Modifications of
                      8:  * Original Code as defined in and that are subject to the Apple Public
                      9:  * Source License Version 1.1 (the "License").  You may not use this file
                     10:  * except in compliance with the License.  Please obtain a copy of the
                     11:  * License at http://www.apple.com/publicsource and read it before using
                     12:  * this file.
                     13:  * 
                     14:  * The Original Code and all software distributed under the License are
                     15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
                     16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
                     17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
                     19:  * License for the specific language governing rights and limitations
                     20:  * under the License.
                     21:  * 
                     22:  * @APPLE_LICENSE_HEADER_END@
                     23:  */
                     24: 
                     25: /**
                     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.