Annotation of Examples/DriverKit/AMDPCSCSIDriver/AMDPCSCSIDriver_reloc.tproj/AMD_Chip.m, revision 1.1

1.1     ! root        1: /*     Copyright (c) 1994 NeXT Computer, Inc.  All rights reserved. 
        !             2:  *
        !             3:  * AMD_Chip.m - chip (53C974/79C974) specific methods for AMD SCSI driver
        !             4:  *
        !             5:  * HISTORY
        !             6:  * 21 Oct 94    Doug Mitchell at NeXT
        !             7:  *      Created. 
        !             8:  */
        !             9: 
        !            10: #import "AMD_Chip.h"
        !            11: #import "AMD_ChipPrivate.h"
        !            12: #import "AMD_Private.h"
        !            13: #import "AMD_x86.h"
        !            14: #import "AMD_Regs.h"
        !            15: #import "AMD_Types.h"
        !            16: #import "AMD_ddm.h"
        !            17: #import "bringup.h"
        !            18: #import <driverkit/generalFuncs.h>
        !            19: #import <kernserv/prototypes.h>
        !            20: 
        !            21: IONamedValue scsiMsgValues[] = {
        !            22:        {MSG_CMDCMPLT,          "Command Complete"      },
        !            23:        {MSG_EXTENDED,          "Extended Message"      },
        !            24:        {MSG_SAVEPTRS,          "Save Pointers"         },
        !            25:        {MSG_RESTOREPTRS,       "Restore Pointers"      },
        !            26:        {MSG_DISCONNECT,        "Disconnect"            },
        !            27:        {MSG_IDETERR,           "Initiator Det Error"   },
        !            28:        {MSG_ABORT,             "Abort"                 },
        !            29:        {MSG_MSGREJECT,         "Message Reject"        },
        !            30:        {MSG_NOP,               "Nop"                   },
        !            31:        {MSG_MSGPARERR,         "Message parity Error"  },
        !            32:        {0,                     NULL                    }
        !            33: };
        !            34: 
        !            35: #ifdef DDM_DEBUG
        !            36: IONamedValue scsiPhaseValues[] = {
        !            37:        {PHASE_DATAOUT,         "data_out"              },
        !            38:        {PHASE_DATAIN,          "data_in"               },
        !            39:        {PHASE_COMMAND,         "command"               },
        !            40:        {PHASE_STATUS,          "status"                },
        !            41:        {PHASE_MSGOUT,          "message_out"           },
        !            42:        {PHASE_MSGIN,           "message_in"            },
        !            43:        {0,                     NULL                    }
        !            44: };
        !            45: 
        !            46: #endif DDM_DEBUG
        !            47: 
        !            48: #ifdef DEBUG
        !            49: /*
        !            50:  * For IOFindNameForValue() and ddm's.
        !            51:  */
        !            52: IONamedValue scStateValues[] = { 
        !            53:        {SCS_UNINITIALIZED,     "SCS_UNINITIALIZED"     },
        !            54:         {SCS_DISCONNECTED,     "SCS_DISCONNECTED"      },
        !            55:         {SCS_SELECTING,                "SCS_SELECTING"         },
        !            56:         {SCS_INITIATOR,                "SCS_INITIATOR"         },
        !            57:         {SCS_COMPLETING,       "SCS_COMPLETING"        },
        !            58:         {SCS_DMAING,           "SCS_DMAING"            },      
        !            59:         {SCS_ACCEPTINGMSG,     "SCS_ACCEPTINGMSG"      },
        !            60:         {SCS_SENDINGMSG,       "SCS_SENDINGMSG"        },      
        !            61:         {SCS_GETTINGMSG,       "SCS_GETTINGMSG"        },      
        !            62:        {SCS_SENDINGCMD,        "SCS_SENDINGCMD"        },
        !            63:        {0,                     NULL                    },
        !            64: };
        !            65: #endif DEBUG
        !            66: 
        !            67: @implementation AMD_SCSI(Chip)
        !            68: 
        !            69: /*
        !            70:  * One-time-only init and probe. Returns YES if a functioning chip is 
        !            71:  * found, else returns NO. -hwReset must be called subsequent to this 
        !            72:  * to enable operation of the chip.
        !            73:  */
        !            74: - (BOOL)probeChip
        !            75: {
        !            76:        int target;
        !            77:        
        !            78:        /*
        !            79:         * Init sync mode to async, until we negotiate.
        !            80:         */
        !            81:        for(target=0; target<SCSI_NTARGETS; target++) {
        !            82:                perTarget[target].syncXferOffset = 0;
        !            83:        }
        !            84:        return YES;
        !            85: }
        !            86: 
        !            87: /*
        !            88:  * Reusable 53C974 init function. This includes a SCSI reset.
        !            89:  * Handling of ioComplete of active and disconnected commands must be done
        !            90:  * elsewhere. Returns non-zero on error. 
        !            91:  */
        !            92: - (int)hwReset : (const char *)reason
        !            93: {
        !            94:        int             target;
        !            95:        unsigned char   reg;
        !            96:        
        !            97:        /*
        !            98:         * First of all, reset interrupts, the SCSI block, and the DMA engine.
        !            99:         */
        !           100:        [self disableAllInterrupts];
        !           101:        WRITE_REG(scsiCmd, SCMD_RESET_DEVICE);
        !           102:        WRITE_REG(scsiCmd, SCMD_NOP);
        !           103:        [self dmaIdle];
        !           104:        
        !           105:        /*
        !           106:         * Clear possible pending interrupt.
        !           107:         */
        !           108:        READ_REG(intrStatus);
        !           109:        
        !           110:        /*
        !           111:         * Init state variables.
        !           112:         */
        !           113:        reselPending  = 0;
        !           114:        scState       = SCS_DISCONNECTED;
        !           115:        activeCmd     = NULL;
        !           116:        currMsgInCnt  = 0;
        !           117:        currMsgOutCnt = 0;
        !           118:        msgOutState   = MOS_NONE;
        !           119:        SDTR_State    = SNS_NONE;
        !           120:        
        !           121:        /*
        !           122:         * Sync negotiation is needed after a reset.
        !           123:         */
        !           124:        for(target=0; target<SCSI_NTARGETS; target++) {
        !           125:                perTarget[target].syncNegotNeeded = 1;
        !           126:        }
        !           127:        
        !           128:        /*
        !           129:         * Control1....
        !           130:         */
        !           131:        reg = CR1_RESET_INTR_DIS | CR1_PERR_ENABLE | AMD_SCSI_ID;
        !           132:        if(extendTiming) {
        !           133:                /*
        !           134:                 * Per instance table. This slows down transfers on the
        !           135:                 * bus.
        !           136:                 */
        !           137:                reg |= CR1_EXTEND_TIMING;
        !           138:        }
        !           139:        WRITE_REG(control1, reg);
        !           140:        ddm_init("control1 = 0x%x\n", reg, 2,3,4,5);
        !           141:        hostId = AMD_SCSI_ID;
        !           142:        
        !           143:        /*
        !           144:         * Clock factor and select timeout.
        !           145:         */
        !           146:        ASSERT(scsiClockRate != 0);
        !           147:        if(scsiClockRate < 10) {
        !           148:                IOLog("AMD53C974: Clock %d MHZ too low; using 10 MHz\n",
        !           149:                         scsiClockRate);
        !           150:                scsiClockRate = 10;
        !           151:        }
        !           152:        if(scsiClockRate > 40) {
        !           153:                IOLog("AMD53C974: Clock %d MHZ too high; using 40 MHz\n",
        !           154:                         scsiClockRate);
        !           155:                scsiClockRate = 40;
        !           156:        }
        !           157:        reg = AMD_CLOCK_FACTOR(scsiClockRate) & 0x7;
        !           158:        WRITE_REG(clockFactor, reg);
        !           159:        ddm_init("clockFactor %d\n", reg, 2,3,4,5);
        !           160:        reg = amdSelectTimeout(AMD_SELECT_TO, scsiClockRate);
        !           161:        WRITE_REG(scsiTimeout, reg);
        !           162:        ddm_init("select timeout reg 0x%x\n", reg, 2,3,4,5);
        !           163:        
        !           164:        /*
        !           165:         * control2 - enable extended features - mainly, 24-bit transfer count.
        !           166:         */
        !           167:        WRITE_REG(control2, CR2_ENABLE_FEAT);
        !           168:        
        !           169:        /*
        !           170:         * control3
        !           171:         */
        !           172:        reg = 0;
        !           173:        if(fastModeEnable) {
        !           174:                reg |= CR3_FAST_SCSI;
        !           175:        }
        !           176:        if(scsiClockRate > 25) {
        !           177:                reg |= CR3_FAST_CLOCK;
        !           178:        }
        !           179:        ddm_init("control3 = 0x%x\n", reg, 2,3,4,5);
        !           180:        WRITE_REG(control3, reg);
        !           181:        
        !           182:        /*
        !           183:         * control4 - glitch eater, active negation. Let's not 
        !           184:         * worry about these whizzy features just yet.
        !           185:         */
        !           186:        WRITE_REG(control4, 0);
        !           187:        
        !           188:        /*
        !           189:         * Go to async xfer mode for now. Sync gets enabled on a per-target 
        !           190:         * basis in -targetContext.
        !           191:         */
        !           192:        WRITE_REG(syncOffset, 0);
        !           193:        
        !           194:        /*
        !           195:         * Reset SCSI bus, wait, clear possible interrupt.
        !           196:         */
        !           197:        WRITE_REG(scsiCmd, SCMD_RESET_SCSI);
        !           198:        if(reason) {
        !           199:                IOLog("AMD53C974: Resetting SCSI bus (%s)\n", reason);
        !           200:        }
        !           201:        else {
        !           202:                IOLog("AMD53C974: Resetting SCSI bus\n");
        !           203:        }
        !           204:        IOSleep(AMD_SCSI_RESET_DELAY);
        !           205:        READ_REG(intrStatus);
        !           206: 
        !           207:        ddm_init("hwReset: enabling interrupts\n", 1,2,3,4,5);
        !           208:        [self enableAllInterrupts];
        !           209:        
        !           210:        ddm_init("hwReset: DONE\n", 1,2,3,4,5);
        !           211:        return 0;       
        !           212: }
        !           213: 
        !           214: /*
        !           215:  * reset SCSI bus.
        !           216:  */
        !           217: - (void)scsiReset
        !           218: {
        !           219:        WRITE_REG(scsiCmd, SCMD_RESET_SCSI);
        !           220:        READ_REG(intrStatus);
        !           221: }
        !           222: 
        !           223: /*
        !           224:  * Start a SCSI transaction for the specified command. ActiveCmd must be 
        !           225:  * NULL. A return of HWS_REJECT indicates that caller may try again
        !           226:  * with another command; HWS_BUSY indicates a condition other than
        !           227:  * (activeCmd != NULL) which prevents the processing of the command.
        !           228:  */
        !           229: - (hwStartReturn)hwStart : (commandBuf *)cmdBuf
        !           230: {      
        !           231:        unsigned char   cdb_ctrl;
        !           232:        IOSCSIRequest   *scsiReq = cmdBuf->scsiReq;
        !           233:        cdb_t           *cdbp = &scsiReq->cdb;
        !           234:        unsigned char   identify_msg = 0;
        !           235:        unsigned char   *cp;
        !           236:        unsigned char   okToDisc;
        !           237:        unsigned char   okToQueue;
        !           238:        perTargetData   *perTargetPtr;
        !           239:        int             i;
        !           240:        BOOL            cmdQueueDisableFlag = NO;
        !           241:        unsigned char   selectCmd;
        !           242:        
        !           243:        ddm_chip("hwStart cmdBuf = 0x%x opcode %s\n", cmdBuf, 
        !           244:                IOFindNameForValue(cdbp->cdb_opcode, IOSCSIOpcodeStrings),
        !           245:                        3,4,5);
        !           246:        ASSERT(activeCmd == NULL);
        !           247:        
        !           248:        /*
        !           249:         * Currently, the only reason we return HWS_BUSY is if we have
        !           250:         * a reselect pending.
        !           251:         */
        !           252:        if(reselPending) {
        !           253:                queue_enter(&pendingQ, cmdBuf, commandBuf *, link);
        !           254:                return HWS_BUSY;
        !           255:        }
        !           256:        ASSERT(scState == SCS_DISCONNECTED);
        !           257:                
        !           258:        /*
        !           259:         * Initialize driver return values and state machine.
        !           260:         */
        !           261:        cmdBuf->currentByteCount = cmdBuf->savedByteCount = 
        !           262:                scsiReq->maxTransfer;
        !           263:        scsiReq->bytesTransferred = 0;
        !           264:        cmdBuf->savedPtr = cmdBuf->currentPtr = (vm_offset_t)cmdBuf->buffer;
        !           265:        scsiReq->driverStatus = SR_IOST_INVALID;
        !           266:        scsiReq->totalTime  = 0ULL;
        !           267:        scsiReq->latentTime = 0ULL;
        !           268:        
        !           269:        /*
        !           270:         * Figure out what kind of cdb we've been given and grab the ctrl byte.
        !           271:         */
        !           272:        switch (SCSI_OPGROUP(cdbp->cdb_opcode)) {
        !           273:            case OPGROUP_0:
        !           274:                cmdBuf->cdbLength = sizeof(cdb_6_t);
        !           275:                cdb_ctrl  = cdbp->cdb_c6.c6_ctrl;
        !           276:                break;
        !           277:            case OPGROUP_1:
        !           278:            case OPGROUP_2:
        !           279:                cmdBuf->cdbLength = sizeof(cdb_10_t);
        !           280:                cdb_ctrl  = cdbp->cdb_c10.c10_ctrl;
        !           281:                break;
        !           282:            case OPGROUP_5:
        !           283:                cmdBuf->cdbLength = sizeof(cdb_12_t);
        !           284:                cdb_ctrl  = cdbp->cdb_c12.c12_ctrl;
        !           285:                break;
        !           286:             case OPGROUP_6:
        !           287:                cmdBuf->cdbLength = (scsiReq->cdbLength ? 
        !           288:                         scsiReq->cdbLength : sizeof (struct cdb_6));
        !           289:                cdb_ctrl = 0;
        !           290:                break;
        !           291:            case OPGROUP_7:
        !           292:                cmdBuf->cdbLength = (scsiReq->cdbLength ? 
        !           293:                         scsiReq->cdbLength : sizeof (struct cdb_10));
        !           294:                cdb_ctrl = 0;
        !           295:                break;
        !           296:            default:
        !           297:                goto abortReq;
        !           298:        }
        !           299:        ddm_chip("cdbLength = %d\n", cmdBuf->cdbLength, 2,3,4,5);
        !           300:        
        !           301:        /*
        !           302:         * Do a little command snooping.
        !           303:         */
        !           304:        perTargetPtr = &perTarget[scsiReq->target];
        !           305:        switch(cdbp->cdb_opcode) {
        !           306:            case C6OP_INQUIRY:
        !           307:                /*
        !           308:                 * The first command SCSIDisk sends us is an Inquiry command.
        !           309:                 * This never gets retried, so avoid a possible 
        !           310:                 * reject of a command queue tag. Avoid this hack if
        !           311:                 * there are any other commands outstanding for this
        !           312:                 * target/lun.
        !           313:                 */
        !           314:                if(activeArray[scsiReq->target][scsiReq->lun] == 0) {
        !           315:                        cmdQueueDisableFlag = YES;
        !           316:                }
        !           317:                break;
        !           318:                
        !           319:            case C6OP_REQSENSE:
        !           320:                /*
        !           321:                 * Always force sync renegotiation on this one to 
        !           322:                 * catch independent target power cycles.
        !           323:                 */
        !           324:                if(SYNC_RENEGOT_ON_REQ_SENSE) {
        !           325:                        perTargetPtr->syncNegotNeeded = 1;
        !           326:                }
        !           327:                break;
        !           328:        }
        !           329:                
        !           330:        /*
        !           331:         * Avoid command queueing if if we're going to do sync
        !           332:         * negotiation.
        !           333:         * FIXME - this might be illegal - what if we're doing a request 
        !           334:         * sense in response to a legitimate error, and there are 
        !           335:         * tagged commands pending?
        !           336:         */
        !           337:        if(perTargetPtr->syncNegotNeeded &&
        !           338:           !perTargetPtr->syncDisable &&
        !           339:           syncModeEnable) {
        !           340:                cmdQueueDisableFlag = YES;
        !           341:                SDTR_State = SNS_HOST_INIT_NEEDED;
        !           342:                ddm_chip("hwStart: entering SNS_HOST_INIT_NEEDED state\n", 
        !           343:                        1,2,3,4,5);
        !           344:        }
        !           345:        else {
        !           346:                SDTR_State = SNS_NONE;
        !           347:        }
        !           348:        
        !           349:        /*
        !           350:         * Determine from myriad sources whether or not it's OK to 
        !           351:         * disconnect and to use command queueing. 
        !           352:         */
        !           353:        okToQueue = cmdQueueEnable &&                   // global per driver
        !           354:                    !scsiReq->cmdQueueDisable &&        // per I/O
        !           355:                    !perTargetPtr->cmdQueueDisable &&   // per target
        !           356:                    !cmdQueueDisableFlag;               // inquiry hack
        !           357:        okToDisc  = ([self numReserved] >               // > 1 target on bus
        !           358:                        (1 + SCSI_NLUNS)) || 
        !           359:                    okToQueue;                          // hope to do cmd q'ing
        !           360:        #if     FORCE_DISCONNECTS
        !           361:        okToDisc = 1;
        !           362:        #else   FORCE_DISCONNECTS
        !           363:        if(!scsiReq->disconnect) {
        !           364:                /*
        !           365:                 * This overrides everything...
        !           366:                 */
        !           367:                okToQueue = okToDisc = 0;
        !           368:        }
        !           369:        #endif  FORCE_DISCONNECTS
        !           370:        cmdBuf->discEnable = okToDisc;
        !           371:        if(okToQueue) {
        !           372:                /*
        !           373:                 * Avoid using tag QUEUE_TAG_NONTAGGED...
        !           374:                 */
        !           375:                cmdBuf->queueTag = nextQueueTag;
        !           376:                if(++nextQueueTag == QUEUE_TAG_NONTAGGED) {
        !           377:                        nextQueueTag++;
        !           378:                }
        !           379:        }
        !           380:        else {
        !           381:                cmdBuf->queueTag = QUEUE_TAG_NONTAGGED;
        !           382:        }
        !           383:        
        !           384:        /*
        !           385:         * Make sure nothing unreasonable has been asked of us. 
        !           386:         */
        !           387:        if((cdb_ctrl & CTRL_LINKFLAG) != CTRL_NOLINK) {
        !           388:                ddm_err("Linked CDB (Unimplemented)\n",
        !           389:                        1,2,3,4,5);
        !           390:                goto abortReq;
        !           391:        }
        !           392: 
        !           393:        /*
        !           394:         * OK, this command is hot.
        !           395:         */
        !           396:        [self activateCommand:cmdBuf];
        !           397:        
        !           398:        scState = SCS_SELECTING;
        !           399:        msgOutState = MOS_NONE;
        !           400:        bzero(currMsgIn, AMD_MSG_SIZE);
        !           401:        bzero(currMsgOut, AMD_MSG_SIZE);
        !           402:        currMsgInCnt = 0;
        !           403:        currMsgOutCnt = 0;
        !           404:        
        !           405:        /*
        !           406:         * Load per-target context.
        !           407:         */
        !           408:        [self targetContext:scsiReq->target];
        !           409: 
        !           410:        /*
        !           411:         * set target bus id
        !           412:         * punch message(s), optional cdb into fifo
        !           413:         * write appropriate select command
        !           414:         */
        !           415:        ddm_chip("hwStart: opcode 0x%x targ %d lun %d maxTransfer 0x%x\n", 
        !           416:             cdbp->cdb_opcode, scsiReq->target, scsiReq->lun, 
        !           417:             scsiReq->maxTransfer, 5);
        !           418:        WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO);
        !           419:        WRITE_REG(scsiDestID, scsiReq->target);
        !           420:        identify_msg = MSG_IDENTIFYMASK | (scsiReq->lun & MSG_ID_LUNMASK);
        !           421:        if(okToDisc) {
        !           422:                identify_msg |= MSG_ID_DISCONN;
        !           423:        }
        !           424: 
        !           425:        WRITE_REG(scsiFifo, identify_msg);
        !           426:        
        !           427:        /*
        !           428:         * Note this logic assumes that queue tag and SDTR messages are
        !           429:         * mutually exclusive...
        !           430:         */
        !           431:        if(SDTR_State == SNS_HOST_INIT_NEEDED) {
        !           432:                selectCmd = SCMD_SELECT_ATN_STOP;
        !           433:        }
        !           434:        else {
        !           435:                if(okToQueue) {
        !           436:                        WRITE_REG(scsiFifo, MSG_SIMPLE_QUEUE_TAG);
        !           437:                        WRITE_REG(scsiFifo, cmdBuf->queueTag);
        !           438:                        
        !           439:                        /*
        !           440:                         * Save these in currMsgOut[] in case 
        !           441:                         * the target rejects this message.
        !           442:                         */
        !           443:                        currMsgOut[0] = MSG_SIMPLE_QUEUE_TAG;
        !           444:                        currMsgOut[1] = cmdBuf->queueTag;
        !           445:                        currMsgOutCnt = 2;
        !           446:                }
        !           447:                cp = (u_char *)cdbp;
        !           448:                for(i=0; i<cmdBuf->cdbLength; i++) {
        !           449:                        WRITE_REG(scsiFifo, *cp++);
        !           450:                }
        !           451:                if(okToQueue) {
        !           452:                        selectCmd = SCMD_SELECT_ATN_3;
        !           453:                }
        !           454:                else {
        !           455:                        selectCmd = SCMD_SELECT_ATN;
        !           456:                }
        !           457:        }
        !           458:        WRITE_REG(scsiCmd, selectCmd);
        !           459:        IOGetTimestamp(&cmdBuf->startTime);
        !           460:        return HWS_OK;
        !           461:        
        !           462: abortReq:
        !           463:        scsiReq->driverStatus = SR_IOST_CMDREJ;
        !           464:        [self ioComplete:cmdBuf];
        !           465:        return HWS_REJECT;
        !           466: }
        !           467: 
        !           468: /*
        !           469:  * SCSI device interrupt handler.
        !           470:  */
        !           471: - (void)hwInterrupt
        !           472: {
        !           473:        ddm_chip("hwInterrupt: activeCmd 0x%x\n", activeCmd, 2,3,4,5);
        !           474:        
        !           475:        switch([self scsiInterruptPending]) {
        !           476:            case SINT_NONE:
        !           477:                /*
        !           478:                 * Must be another device....
        !           479:                 */
        !           480:                [self enableAllInterrupts];
        !           481:                return;
        !           482:            case SINT_DEVICE:
        !           483:            case SINT_DMA:
        !           484:                break;
        !           485:            default:
        !           486:                /* 
        !           487:                 * What do we do now, batman?
        !           488:                 */
        !           489:                [self hwAbort:SR_IOST_HW reason:"Bad Interrupt Received"];
        !           490:                return;
        !           491:        }
        !           492:        
        !           493: goAgain:
        !           494:        /*
        !           495:         * Save interrupt state.
        !           496:         */
        !           497:        saveStatus     = READ_REG(scsiStat);
        !           498:        saveSeqStep    = READ_REG(internState);
        !           499:        saveIntrStatus = READ_REG(intrStatus);
        !           500:                
        !           501:        ddm_chip("   status 0x%x intstatus 0x%x scState %s\n", 
        !           502:                saveStatus, saveIntrStatus, 
        !           503:                IOFindNameForValue(scState, scStateValues), 4,5);
        !           504:        if((saveStatus & SS_ILLEGALOP) || (saveIntrStatus & IS_ILLEGALCMD)) {
        !           505:           
        !           506:                /*
        !           507:                 * Software screwup. Start over from scratch.
        !           508:                 */
        !           509:                IOLog("AMD53C974: hardware command reject\n");
        !           510:                [self hwAbort:SR_IOST_INT reason:"Hardware Command Reject"];
        !           511:                return;
        !           512:        }
        !           513: 
        !           514:        /*
        !           515:         * OK, grind thru the state machine.
        !           516:         */
        !           517:        switch(scState) {
        !           518:            case SCS_DISCONNECTED:
        !           519:                [self fsmDisconnected];
        !           520:                break;
        !           521:            case SCS_SELECTING:
        !           522:                [self fsmSelecting];
        !           523:                break;
        !           524:            case SCS_INITIATOR:
        !           525:                [self fsmInitiator];
        !           526:                break;
        !           527:            case SCS_COMPLETING:
        !           528:                [self fsmCompleting];
        !           529:                break;
        !           530:            case SCS_DMAING:
        !           531:                [self fsmDMAing];
        !           532:                break;
        !           533:            case SCS_ACCEPTINGMSG:
        !           534:                [self fsmAcceptingMsg];
        !           535:                break;
        !           536:            case SCS_SENDINGMSG:
        !           537:                [self fsmSendingMsg];
        !           538:                break;
        !           539:            case SCS_GETTINGMSG:
        !           540:                [self fsmGettingMsg];
        !           541:                break;
        !           542:           case SCS_SENDINGCMD:
        !           543:                [self fsmSendingCmd];
        !           544:                break;
        !           545:           default:
        !           546:                IOPanic("AMD53C974: Bad scState");
        !           547:        } /* switch scState */
        !           548:        
        !           549:        if ((scState != SCS_DISCONNECTED) &&
        !           550:            (saveIntrStatus & IS_DISCONNECT)) {
        !           551:                /*
        !           552:                 * the target just up and went away. This is a catch-all
        !           553:                 * trap for any unexpected disconnect.
        !           554:                 */
        !           555:                ddm_err("hwInterrupt: target disconnected\n", 1,2,3,4,5);
        !           556:                scState = SCS_DISCONNECTED;
        !           557:                if(activeCmd != NULL) {
        !           558:                        activeCmd->scsiReq->driverStatus = SR_IOST_TABT;
        !           559:                        [self ioComplete:activeCmd];
        !           560:                        activeCmd = NULL;
        !           561:                }
        !           562:        }
        !           563:        
        !           564:        /*
        !           565:         * Handle a SCSI Phase change if necessary.
        !           566:         */
        !           567:        if (scState == SCS_INITIATOR)
        !           568:                [self fsmPhaseChange];
        !           569: #ifdef DEBUG
        !           570:        else {
        !           571:                ddm_chip("hwInterrupt #2: scState %s\n", 
        !           572:                        IOFindNameForValue(scState, scStateValues),
        !           573:                        2,3,4,5);
        !           574:        }
        !           575: #endif DEBUG
        !           576: 
        !           577:        /*
        !           578:         * If we're off the bus, enable reselection at chip level.
        !           579:         */
        !           580:        if (scState == SCS_DISCONNECTED) {
        !           581:                ddm_chip("hwInterrupt: enabling reselection\n", 1,2,3,4,5);
        !           582:                WRITE_REG(scsiCmd, SCMD_ENABLE_SELECT);
        !           583:        }
        !           584:        
        !           585:        
        !           586:        /*
        !           587:         * If another SCSI interrupt is pending, go for it again (avoiding 
        !           588:         * an unnecessary enableInterrupt and msg_receive()).
        !           589:         */
        !           590:        switch([self scsiInterruptPending]) {
        !           591:            case SINT_DEVICE:
        !           592:                #if     INTR_LATENCY_TEST
        !           593:                ddm_chip("hwInterrupt: INTR TRUE; EXITING FOR MEASUREMENT\n",
        !           594:                        1,2,3,4,5);
        !           595:                break;
        !           596:                #else   INTR_LATENCY_TEST
        !           597:                ddm_chip("hwInterrupt: going again without enabling "
        !           598:                        "interrupt\n", 1,2,3,4,5);
        !           599:                goto goAgain;
        !           600:                #endif  INTR_LATENCY_TEST
        !           601:            default:
        !           602:                break;
        !           603:        }
        !           604: 
        !           605:        [self enableAllInterrupts];
        !           606:        
        !           607:        /*
        !           608:         * One more thing - if we're still disconnected, enable processing
        !           609:         * of new commands. 
        !           610:         */
        !           611:        if(scState == SCS_DISCONNECTED)
        !           612:                [self busFree];
        !           613:        ddm_chip("hwInterrupt: DONE; scState %s\n", 
        !           614:                IOFindNameForValue(scState, scStateValues), 2,3,4,5);
        !           615: }
        !           616: 
        !           617: 
        !           618: - (void)logRegs
        !           619: {
        !           620: #if    DEBUG
        !           621:        unsigned char   cs, cis;
        !           622:        unsigned char   fifoDepth;
        !           623:        unsigned        scsiXfrCnt;
        !           624:        unsigned        value;
        !           625:        
        !           626:        IOLog("*** saveStatus 0x%x saveIntrStatus 0x%x\n", 
        !           627:                saveStatus, saveIntrStatus);
        !           628:        IOLog("*** scState = %s  scsiCmd = 0x%x\n", 
        !           629:                IOFindNameForValue(scState, scStateValues),
        !           630:                READ_REG(scsiCmd));
        !           631:                
        !           632:        cs = READ_REG(scsiStat);
        !           633:        cis = READ_REG(intrStatus);
        !           634:        IOLog("*** current status 0x%x current intrStatus 0x%x\n", cs, cis);
        !           635:        
        !           636:        IOLog("*** syncOffset %d  syncPeriod 0x%x\n", 
        !           637:                syncOffsetShadow, syncPeriodShadow);
        !           638:        
        !           639:        fifoDepth = READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK;
        !           640:        scsiXfrCnt = READ_REG(currXfrCntLow);
        !           641:        value = READ_REG(currXfrCntMid);
        !           642:        scsiXfrCnt += (value << 8);
        !           643:        value = READ_REG(currXfrCntHi);
        !           644:        scsiXfrCnt += (value << 16);
        !           645:        IOLog("*** fifoDepth %d  scsiXfrCnt 0x%x\n", fifoDepth, scsiXfrCnt);
        !           646: #endif DEBUG
        !           647: }
        !           648: 
        !           649: 
        !           650: @end   /* AMD_SCSI(Chip) */
        !           651: 
        !           652: /* end of AMD_Chip.m */
        !           653: 

unix.superglobalmegacorp.com

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