Annotation of Examples/DriverKit/AMDPCSCSIDriver/AMDPCSCSIDriver_reloc.tproj/AMD_Chip.m, revision 1.1.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.