Annotation of Examples/DriverKit/AMDPCSCSIDriver/AMDPCSCSIDriver_reloc.tproj/AMD_ChipPrivate.m, revision 1.1.1.1

1.1       root        1: /*     Copyright (c) 1994 NeXT Computer, Inc.  All rights reserved. 
                      2:  *
                      3:  * AMD_ChipPrivate.m - methods used only by AMD_Chip module.
                      4:  *
                      5:  * HISTORY
                      6:  * 2 Nov 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: 
                     22: @implementation AMD_SCSI(ChipPrivate)
                     23: 
                     24: /*
                     25:  * Determine if SCSI interrupt is pending.
                     26:  */
                     27: - (sintPending_t)scsiInterruptPending
                     28: {
                     29:        unsigned char sstat;
                     30:        
                     31:        sstat = READ_REG(scsiStat);
                     32:        if (sstat & SS_INTERRUPT) {
                     33:                return SINT_DEVICE;
                     34:        }
                     35:        else {
                     36:                return SINT_NONE;
                     37:        }
                     38: }
                     39: 
                     40: /*
                     41:  * Methods invoked upon interrupt. One per legal scState. All assume that 
                     42:  * status and interrupt status have been captured in saveStatus and 
                     43:  * saveIntrStatus.
                     44:  */
                     45:  
                     46: /*
                     47:  * Disconnected - only legal event here is reselection.
                     48:  */
                     49: - (void)fsmDisconnected
                     50: {
                     51:        ddm_chip("fsmDisconnected\n", 1,2,3,4,5);
                     52:        ASSERT(activeCmd == NULL);
                     53:        if(saveIntrStatus & IS_RESELECTED) {
                     54:                /*
                     55:                 * We've been reselected. 
                     56:                 */
                     57:                                
                     58:                unsigned char   selectByte;
                     59:                unsigned        fifoDepth;
                     60:                unsigned char   msg;
                     61:        
                     62:                /* 
                     63:                 * Make sure there's a selection byte and an 
                     64:                 * identify message in the fifo.
                     65:                 */
                     66:                fifoDepth = READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK;
                     67:                ddm_chip("reselect: fifoDepth %d\n", fifoDepth, 2,3,4,5);
                     68:                if(fifoDepth != 2) {
                     69:                        ddm_err("reselection, fifoDepth %d\n", fifoDepth, 
                     70:                                2,3,4,5);
                     71:                        IOLog("AMD53C974: Bad FIFO count (%d) on Reselect\n",
                     72:                                fifoDepth);
                     73:                        [self hwAbort:SR_IOST_HW 
                     74:                                reason:NULL];
                     75:                        return;
                     76:                        
                     77:                }
                     78:                
                     79:                /* 
                     80:                 * make sure target set his bit.
                     81:                 */
                     82:                if ((selectByte = READ_REG(scsiFifo) &~ (1 << hostId)) == 0) {
                     83:                        ddm_err("fsmDisconnected: reselection failed"
                     84:                                " - no target bit\n", 1,2,3,4,5);
                     85:                        [self hwAbort:SR_IOST_BV 
                     86:                                reason:"No target bit on Reselect"];
                     87:                        return;
                     88:                }
                     89:                
                     90:                /* 
                     91:                 * figure out target from bit that's on.
                     92:                 */
                     93:                for (reselTarget = 0; 
                     94:                     (selectByte & 1) == 0; 
                     95:                     reselTarget++, selectByte>>=1) {
                     96:                        continue;
                     97:                }
                     98:                
                     99:                /* 
                    100:                 * first message byte must be identify.
                    101:                 */
                    102:                msg = READ_REG(scsiFifo);
                    103:                if (saveStatus & SS_PARITYERROR) {
                    104:                        ddm_err("fsmDisconnected: reselected parity error\n",
                    105:                                1,2,3,4,5);
                    106:                        [self hwAbort:SR_IOST_PARITY 
                    107:                                reason:"Parity error on Reselect"];
                    108:                        return;
                    109:                }
                    110:                if ((msg & MSG_IDENTIFYMASK) == 0) {
                    111:                        ddm_err("fsmDisconnected: reselection failed - "
                    112:                                "bad msg byte (0x%x)\n", msg, 2,3,4,5);
                    113:                        [self hwAbort:SR_IOST_BV 
                    114:                                reason:"Bad ID Message on Reselect"];
                    115:                        return;
                    116:                }
                    117:                reselLun = msg & MSG_ID_LUNMASK;
                    118:                currMsgInCnt = 0;
                    119:                
                    120:                /*
                    121:                 * At this point, the chip is waiting for us to validate 
                    122:                 * the identify message. If cmd queueing is enabled
                    123:                 * for this target, the target is waiting to send a queue 
                    124:                 * tag message, so we have to tell the chip to 
                    125:                 * drop ACK before we proceed with the reselection.
                    126:                 *
                    127:                 * In case of sync mode, we need to load target context right
                    128:                 * now, before dropping ACK, because the target might go
                    129:                 * straight to a data in or data out as soon as ACK drops.
                    130:                 */
                    131:                [self targetContext:reselTarget];
                    132:                scState = SCS_ACCEPTINGMSG;
                    133:                reselPending = 1;
                    134:                WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO);
                    135:                WRITE_REG(scsiCmd, SCMD_MSG_ACCEPTED);
                    136:                ddm_chip("reselPending: target %d lun %d\n",
                    137:                        reselTarget, reselLun, 3,4,5);
                    138:                 
                    139:        } else if(saveIntrStatus & IS_SCSIRESET) {
                    140:                /*
                    141:                 * TBD - for now ignore, we get one of these by resetting the
                    142:                 * chip. If an I/O is pending, it'll probably time out.
                    143:                 * Maybe we want to return SR_IOST_RESET on the pending 
                    144:                 * command...
                    145:                 */
                    146:                ddm_chip("fsmDisconnected: ignoring reset interrupt\n",
                    147:                        1,2,3,4,5);
                    148:        } else {
                    149:                /* 
                    150:                 * I'm confused.... 
                    151:                 */
                    152:                [self hwAbort:SR_IOST_BV 
                    153:                        reason:"bad interrupt while disconnected"];
                    154:        }
                    155: }
                    156: 
                    157: 
                    158: /*
                    159:  * One of three things can happen here - the selection could succeed (though
                    160:  * with possible imcomplete message out), it could time out, or we can be 
                    161:  * reselected.
                    162:  */
                    163: #define CATCH_SELECT_TO                1
                    164: 
                    165: - (void)fsmSelecting
                    166: {
                    167:        unsigned char fifoDepth;
                    168:        unsigned char phase;
                    169:        IOSCSIRequest *scsiReq = activeCmd->scsiReq;
                    170:        
                    171:        ddm_chip("fsmSelecting\n", 1,2,3,4,5);
                    172:        ASSERT(activeCmd != NULL);
                    173:        if (saveIntrStatus & IS_DISCONNECT) {
                    174:                /*
                    175:                 * selection timed-out. Abort this request.
                    176:                 */
                    177:                #if     CATCH_SELECT_TO
                    178:                /* DEBUG ONLY */
                    179:                if(scsiReq->cdb.cdb_opcode != C6OP_INQUIRY) {
                    180:                        IOLog("Unexpected Select Timeout\n");
                    181:                }
                    182:                #endif  CATCH_SELECT_TO
                    183:                ddm_chip("***SELECTION TIMEOUT for target %d\n",
                    184:                        activeCmd->scsiReq->target, 2,3,4,5);
                    185:                WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO);
                    186:                scState = SCS_DISCONNECTED;
                    187:                scsiReq->driverStatus = SR_IOST_SELTO;
                    188:                [self ioComplete:activeCmd];
                    189:                activeCmd = NULL;
                    190:        }
                    191:        else if(saveIntrStatus == (IS_SUCCESSFUL_OP|IS_SERVICE_REQ)) {
                    192: 
                    193:                ddm_chip("selection seqstep=%d\n", 
                    194:                        saveSeqStep & INS_STATE_MASK, 2,3,4,5);
                    195:                
                    196:                switch (saveSeqStep & INS_STATE_MASK) {
                    197:                    case 0:     
                    198:                        /*
                    199:                         * No message phase. If we really wanted one,
                    200:                         * this could be significant...
                    201:                         */
                    202:                        if(activeCmd->queueTag != QUEUE_TAG_NONTAGGED) {
                    203:                                /*
                    204:                                 * This target can't do command queueing.
                    205:                                 */
                    206:                                [self disableMode:AM_CmdQueue];
                    207:                        }       
                    208:                        if(SDTR_State == SNS_HOST_INIT_NEEDED) {
                    209:                                /*
                    210:                                 * We were trying to do an SDTR.
                    211:                                 */
                    212:                                [self disableMode:AM_Sync];
                    213:                                SDTR_State = SNS_NONE;
                    214:                        }
                    215:                        
                    216:                        /*
                    217:                         * OK, let's try to continue following phase
                    218:                         * changes.
                    219:                         */
                    220:                        scState = SCS_INITIATOR;
                    221:                        break;
                    222:                        
                    223:                    case 3:     /* didn't complete cmd phase, parity? */
                    224:                    case 4:     /* everything worked */
                    225:                    case 1:     /* everything worked, SCMD_SELECT_ATN_STOP
                    226:                                 * case */
                    227:                    
                    228:                        /* 
                    229:                         * We're connected. Start following the target's phase
                    230:                         * changes.
                    231:                         *
                    232:                         * If we're trying to do sync negotiation,
                    233:                         * this is the place to do it. In that case, we
                    234:                         * sent a SCMD_SELECT_ATN_STOP command, and
                    235:                         * ATN is now asserted (and we're hopefully in
                    236:                         * msg out phase). We want to send 5 bytes. 
                    237:                         * Drop them into currMsgOut[] and prime the  
                    238:                         * msgOutState machine.
                    239:                         */
                    240:                        if(SDTR_State == SNS_HOST_INIT_NEEDED) {
                    241:                                [self createSDTR:currMsgOut inboundMsg:NULL];
                    242:                                currMsgOutCnt = MSG_SDTR_LENGTH;
                    243:                                msgOutState = MOS_WAITING;
                    244:                        }
                    245:                        scState = SCS_INITIATOR;
                    246:                        break;
                    247:                        
                    248:                    case 2:     
                    249:                        /*
                    250:                         * Either no command phase, or imcomplete message
                    251:                         * transfer.
                    252:                         */
                    253:                        fifoDepth = READ_REG(currFifoState) & 
                    254:                                FS_FIFO_LEVEL_MASK;
                    255:                        phase = saveStatus & SS_PHASEMASK;
                    256:                        ddm_chip("INCOMPLETE SELECT; fifoDepth %d phase %s\n",
                    257:                                fifoDepth, 
                    258:                                IOFindNameForValue(phase, scsiPhaseValues),
                    259:                                3,4,5);
                    260:                        if(activeCmd->queueTag != QUEUE_TAG_NONTAGGED) {
                    261:                                /*
                    262:                                 * This target can't do command queueing.
                    263:                                 */
                    264:                                [self disableMode:AM_CmdQueue];
                    265:                        }       
                    266:                        
                    267:                        /*
                    268:                         * Spec says ATN is asserted if all message bytes
                    269:                         * were not sent.
                    270:                         */
                    271:                        if(fifoDepth > activeCmd->cdbLength) {
                    272:                                WRITE_REG(scsiCmd, SCMD_CLR_ATN);
                    273:                        }
                    274:                        
                    275:                        /*
                    276:                         * OK, let's try to continue following phase
                    277:                         * changes.
                    278:                         */
                    279:                        scState = SCS_INITIATOR;
                    280:                        break;
                    281: 
                    282:                    default:
                    283:                        [self hwAbort:SR_IOST_HW 
                    284:                                reason:"Selection sequence Error"];
                    285:                        break;
                    286:                }
                    287:        }
                    288:        else if(saveIntrStatus & IS_RESELECTED) {
                    289:                /*
                    290:                 * We got reselected while trying to do a selection. 
                    291:                 * Enqueue this cmdBuf on the HEAD of pendingQ, then deal
                    292:                 * with the reselect. 
                    293:                 * Tricky case, we have to "deactivate" this command
                    294:                 * since this hwStart attempt failed.  
                    295:                 */
                    296:                queue_enter_first(&pendingQ, activeCmd, commandBuf *, link);
                    297:                [self deactivateCmd:activeCmd];
                    298:                ddm_chip("reselect while trying to select target %d\n",
                    299:                        activeCmd->scsiReq->target, 2,3,4,5);
                    300:                activeCmd = NULL;
                    301:                scState = SCS_DISCONNECTED;
                    302:                
                    303:                /*
                    304:                 * Go deal with reselect.
                    305:                 */
                    306:                [self fsmDisconnected];
                    307:        }
                    308:        else {
                    309:                ddm_err("fsmSelecting: Bogus select/reselect interrupt\n", 
                    310:                        1,2,3,4,5);
                    311:                [self hwAbort:SR_IOST_HW 
                    312:                        reason: "Bogus select/reselect interrupt"];
                    313:                return;
                    314:        }
                    315:        return;
                    316: }
                    317: 
                    318: /*
                    319:  * This one is illegal.
                    320:  */
                    321: - (void)fsmInitiator
                    322: {
                    323:        ddm_chip("fsmInitiator\n", 1,2,3,4,5);
                    324:        [self hwAbort:SR_IOST_HW reason:"Interrupt as Initiator"];
                    325: }
                    326: 
                    327: /*
                    328:  * We just did a SCMD_INIT_CMD_CMPLT command, hopefully all that's left is
                    329:  * to drop ACK. Command Complete message is handled in fscAcceptingMsg.
                    330:  */
                    331: - (void)fsmCompleting
                    332: {              
                    333:        ddm_chip("fsmCompleting\n", 1,2,3,4,5);
                    334:        ASSERT(activeCmd != NULL);
                    335:        if(saveIntrStatus & IS_DISCONNECT) {
                    336:                ddm_err("unexpected completing disconnect\n",
                    337:                        1,2,3,4,5);
                    338:                return;
                    339:        }
                    340:        if(saveIntrStatus & IS_SUCCESSFUL_OP) {
                    341:                /*
                    342:                 * Got both status and msg in fifo; Ack is still true.
                    343:                 */
                    344:                if((READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK) != 2) {
                    345:                        /*
                    346:                         * This is pretty bogus - we expect a status and 
                    347:                         * msg in the fifo. 
                    348:                         */
                    349:                        [self hwAbort:SR_IOST_HW reason:"InitComplete fifo"
                    350:                                " level"];
                    351:                        return;
                    352:                }
                    353:                activeCmd->scsiReq->scsiStatus = READ_REG(scsiFifo);
                    354:                currMsgInCnt = 1;
                    355:                currMsgIn[0] = READ_REG(scsiFifo);
                    356:                ddm_chip("fsmCompleting: status 0x%x msg 0x%x\n",
                    357:                        activeCmd->scsiReq->scsiStatus, 
                    358:                        currMsgIn[0], 3,4,5);
                    359:                if (saveStatus & SS_PARITYERROR) {
                    360:                        ddm_err("fsmCompleting: parity error on msg in\n",
                    361:                                1,2,3,4,5);
                    362:                        [self hwAbort:SR_IOST_PARITY 
                    363:                                reason:"Parity error on message in"];
                    364:                        return;
                    365:                }
                    366:                scState = SCS_ACCEPTINGMSG;
                    367:                WRITE_REG(scsiCmd, SCMD_MSG_ACCEPTED);
                    368:                return;
                    369:        } else {
                    370:                /*
                    371:                 * Must have just got a status byte only. This is kind of
                    372:                 * weird, but let's try to handle it.
                    373:                 */
                    374:                ddm_err("fsmCompleting: status only on complete\n", 
                    375:                        1,2,3,4,5);
                    376:                if((READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK) != 1) {
                    377:                        [self hwAbort:SR_IOST_HW 
                    378:                                reason:"Bad Fifo level on Cmd Complete"];
                    379:                        return;
                    380:                }
                    381:                activeCmd->scsiReq->scsiStatus = READ_REG(scsiFifo);
                    382:                if(saveStatus & SS_PARITYERROR) {
                    383:                        ddm_err("fsmCompleting: parity error on status\n",
                    384:                                1,2,3,4,5);
                    385:                        [self hwAbort:SR_IOST_PARITY 
                    386:                                reason:"Parity Error on Cmd Complete"];
                    387:                        return;
                    388:                }
                    389:                
                    390:                /*
                    391:                 * Back to watching phase changes. Why the target isn't in 
                    392:                 * message in we have yet to find out.
                    393:                 */
                    394:                scState = SCS_INITIATOR;
                    395:        }
                    396: }
                    397: 
                    398: /*
                    399:  * DMA Complete.
                    400:  */
                    401: - (void)fsmDMAing
                    402: {
                    403:        u_int bytesMoved;
                    404:        
                    405:        ddm_chip("fsmDMAing\n", 1,2,3,4,5);
                    406:        ASSERT(activeCmd != NULL);
                    407:        
                    408:        bytesMoved = [self dmaTerminate];
                    409:        if(bytesMoved > activeCmd->currentByteCount) {
                    410:                ddm_err("fsmDMAing: DMA transfer count exceeeded\n",
                    411:                        1,2,3,4,5);
                    412:                ddm_err("  expected %d, moved %d\n", 
                    413:                        activeCmd->currentByteCount, bytesMoved, 3,4,5);
                    414:                bytesMoved = activeCmd->currentByteCount;
                    415:        }
                    416:        ((char *)activeCmd->currentPtr) += bytesMoved;
                    417:        activeCmd->currentByteCount     -= bytesMoved; 
                    418:        if(saveStatus & SS_PARITYERROR) {
                    419:                ddm_err("fsmDMAing: SCSI Data Parity Error\n", 1,2,3,4,5);
                    420:                [self hwAbort:SR_IOST_PARITY reason:"SCSI Data Parity Error"];
                    421:                return;
                    422:        }
                    423:        /*
                    424:         * Back to watching phase changes.
                    425:          */
                    426:        scState = SCS_INITIATOR;
                    427: }
                    428: 
                    429: /*
                    430:  * Just completed the SCMD_TRANSFER_INFO operation for message in. ACK is
                    431:  * still true. Stash the current message byte in currMsgIn[] and proceed to
                    432:  * fsmAcceptingMsg after a SCMD_MSG_ACCEPTED.
                    433:  */
                    434: - (void)fsmGettingMsg
                    435: {
                    436:        BOOL    setAtn = NO;
                    437:        
                    438:        ASSERT((activeCmd != NULL) || reselPending);
                    439:        if(saveIntrStatus & IS_DISCONNECT) {
                    440:                ddm_chip("fsmGettingMsg: message In Disconnect\n", 1,2,3,4,5);
                    441:                /*
                    442:                 * This error is handled on return...
                    443:                 */
                    444:                return;
                    445:        }
                    446:        if((READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK) != 1) {
                    447:                ddm_chip("Message In fifo error\n", 1,2,3,4,5);
                    448:                [self hwAbort:SR_IOST_HW reason:"Message In fifo error"];
                    449:                return;
                    450:        }
                    451: 
                    452:        currMsgIn[currMsgInCnt++] = READ_REG(scsiFifo);
                    453:        if(currMsgInCnt > AMD_MSG_SIZE) {
                    454:                [self hwAbort:SR_IOST_BV 
                    455:                        reason:"Too Many Message bytes received"];
                    456:        }
                    457:        if(saveStatus & SS_PARITYERROR) {
                    458:                ddm_err("fsmGettingMsg: parity error on Message In\n", 
                    459:                        1,2,3,4,5);
                    460:                [self hwAbort:SR_IOST_PARITY 
                    461:                        reason:"parity error on Message In"];
                    462:                return;
                    463:        }
                    464:        ddm_chip("fsmGettingMsg: currMsgIn[%d] = 0x%x (%s)\n", currMsgInCnt-1,
                    465:                currMsgIn[currMsgInCnt-1],
                    466:                IOFindNameForValue(currMsgIn[currMsgInCnt-1], 
                    467:                        scsiMsgValues), 4,5);
                    468:                        
                    469:        /*
                    470:         * Handle special cases. 
                    471:         */
                    472:         
                    473:        /*
                    474:         * 1. If this is the last byte of an unsolicited sync negotiation, 
                    475:         *    we have to assert ATN right now. The message is actually
                    476:         *    fully parsed, and a response SDTR message created, in
                    477:         *    fsmAcceptingMsg.
                    478:         *
                    479:         *    This parsing is pretty crude; if we come up with other special 
                    480:         *    cases, we might rewrite this or come up with some state variables
                    481:         *    to help us.
                    482:         */
                    483:        if((currMsgInCnt >= MSG_SDTR_LENGTH) && (SDTR_State == SNS_NONE)) {
                    484:        
                    485:                int start = currMsgInCnt - MSG_SDTR_LENGTH;
                    486:                
                    487:                if((currMsgIn[start] == MSG_EXTENDED) &&
                    488:                   (currMsgIn[start+1] == (MSG_SDTR_LENGTH - 2)) &&
                    489:                   (currMsgIn[start+2] == MSG_SDTR)) {
                    490:                        ddm_chip("UNSOLICITED SDTR IN; setting ATN\n",
                    491:                                 1,2,3,4,5);
                    492:                        WRITE_REG(scsiCmd, SCMD_SET_ATN);
                    493:                        setAtn = YES;
                    494:                        SDTR_State = SNS_TARGET_INIT;
                    495:                }
                    496:        }
                    497: 
                    498:        /*
                    499:         * 2. If this was a message reject, it's possible that an extended
                    500:         *    message out was prematurely aborted, with ATN still true.
                    501:         *    Clear it so we don't do another (needless) message out.
                    502:         *    Avoid this, of course, if we set ATN in this method for 
                    503:         *    any reason.
                    504:         */
                    505:        if((currMsgIn[currMsgInCnt - 1] == MSG_MSGREJECT) && 
                    506:           (currMsgOutCnt > 1) &&
                    507:           !setAtn) {
                    508:                ddm_chip("fsmGettingMsg: Message Reject; clearing ATN\n",
                    509:                        1,2,3,4,5);
                    510:                WRITE_REG(scsiCmd, SCMD_CLR_ATN);
                    511:        }
                    512:        
                    513:        /*
                    514:         * No need to clear FIFO; its depth was one on entry, and we read
                    515:         * the byte. Note that clearing FIFO after the SCS_ACCEPTINGMSG
                    516:         * might disturb possible sync data in transfer.
                    517:         */
                    518:        WRITE_REG(scsiCmd, SCMD_MSG_ACCEPTED);
                    519:        scState = SCS_ACCEPTINGMSG;
                    520: 
                    521: }
                    522: 
                    523: /*
                    524:  * Just finished a message in; Ack is false. If phase is still
                    525:  * message in, we're in the midst of an extended message or additional
                    526:  * message bytes on reselect. Otherwise, message in is complete;
                    527:  * process currMsgIn[].
                    528:  */
                    529: - (void)fsmAcceptingMsg
                    530: {
                    531:        unsigned char   phase = saveStatus & SS_PHASEMASK;
                    532:        unsigned        index;
                    533:        perTargetData   *perTargetPtr;
                    534:        
                    535:        ddm_chip("fsmAcceptingMsg: phase %s\n", 
                    536:                IOFindNameForValue(phase, scsiPhaseValues), 2,3,4,5);
                    537:        if((phase == PHASE_MSGIN) && !(saveIntrStatus & IS_DISCONNECT)) {
                    538:        
                    539:                /*
                    540:                 * More message bytes to follow.
                    541:                 * We have to qualify with !IS_DISCONNECT to cover the 
                    542:                 * case of some targets (like the Exabyte tape drive)
                    543:                 * which bogusly keep CD, IO, and MSG asserted after
                    544:                 * they drop BSY upon command complete.
                    545:                 */
                    546:                WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO);
                    547:                WRITE_REG(scsiCmd, SCMD_TRANSFER_INFO);
                    548:                scState = SCS_GETTINGMSG; 
                    549:                return;
                    550:        }
                    551:        
                    552:        /*
                    553:         * Message in complete. Handle message(s) in currMsgIn[].
                    554:         */
                    555:        if(reselPending) {
                    556:        
                    557:                /*
                    558:                 * We're expecting either:
                    559:                 * -- no messages, or 
                    560:                 * -- queue tag and/or Save Pointers.
                    561:                 */
                    562:                unsigned char tag = QUEUE_TAG_NONTAGGED;
                    563:                
                    564:                ASSERT(activeCmd == NULL);
                    565:                for(index=0; index<currMsgInCnt; index++) {
                    566:                    switch(currMsgIn[index]) {
                    567:                        case MSG_RESTOREPTRS:
                    568:                            ddm_chip("unnecessary restore pointers\n",
                    569:                                    1,2,3,4,5);
                    570:                            continue;   /* to next message */
                    571:                            
                    572:                        case MSG_SIMPLE_QUEUE_TAG:
                    573:                            if(index == (currMsgInCnt-1)) {
                    574:                                [self hwAbort: SR_IOST_BV
                    575:                                    reason:"Queue tag message, no tag"];
                    576:                                return;
                    577:                            }
                    578:                            tag = currMsgIn[++index];
                    579:                            break;
                    580:                            
                    581:                        /*
                    582:                         * handle others here...?
                    583:                         */
                    584:                        default:
                    585:                            IOLog("AMD53C974: bad msg (0x%x) after identify\n",
                    586:                                    currMsgIn[index]);
                    587:                            [self hwAbort: SR_IOST_BV reason:NULL];
                    588:                            return;
                    589:                    }
                    590:                }
                    591:                        
                    592:                if([self reselect:reselTarget 
                    593:                                lun:reselLun 
                    594:                                queueTag:tag] == YES) {
                    595:                        /*
                    596:                         * Found a disconnected commandBuf to reconnect.
                    597:                         *
                    598:                         * IDENTIFY msg implies restore ptrs.
                    599:                         */
                    600:                        reselPending = 0;
                    601:                        ASSERT(activeCmd != NULL);
                    602:                        activeCmd->currentPtr = activeCmd->savedPtr;
                    603:                        activeCmd->currentByteCount =  
                    604:                                activeCmd->savedByteCount;
                    605:                        scState = SCS_INITIATOR;
                    606:                        return;
                    607:                }
                    608:                else {
                    609:                        IOLog("AMD53C974: Illegal reselect (target %d lun "
                    610:                                "%d tag %d)\n", reselTarget, reselLun, tag);
                    611:                        [self hwAbort: SR_IOST_BV 
                    612:                                reason:NULL];
                    613:                        return;
                    614:                }
                    615:        }       /* reselect pending */
                    616:        
                    617:        /*
                    618:         * Handle all other messages.
                    619:         */
                    620:        ASSERT(activeCmd != NULL);
                    621:        perTargetPtr = &perTarget[activeCmd->scsiReq->target];
                    622:        for(index=0; index<currMsgInCnt; index++) {
                    623:            switch(currMsgIn[index]) {
                    624:                case MSG_CMDCMPLT:
                    625:                    /*
                    626:                     * Bus really should be free; we came here from 
                    627:                     * fsmCompleting.
                    628:                     */
                    629:                    if(!(saveIntrStatus & IS_DISCONNECT)) {
                    630:                            ddm_err("fsmAcceptingMsg: Command Complete"
                    631:                                    " but no Disconnect\n", 1,2,3,4,5);
                    632:                            [self hwAbort:SR_IOST_BV 
                    633:                                    reason:"No Disconnect On Command"
                    634:                                            " Complete"];
                    635:                            return;
                    636:                    }
                    637:                    
                    638:                    /*
                    639:                     * TA DA!
                    640:                     */
                    641:                    scState = SCS_DISCONNECTED;
                    642:                    activeCmd->scsiReq->driverStatus = SR_IOST_GOOD;
                    643:                    [self ioComplete:activeCmd];
                    644:                    activeCmd = NULL;
                    645:                    return;
                    646:                
                    647:                case MSG_DISCONNECT:
                    648:                    /*
                    649:                     * This could be in fsmGettingMsg, where we could 
                    650:                     * handle it gracefully by doing a MSGREJ, but this
                    651:                     * is such a bogus error that we'll just reset the
                    652:                     * offender.
                    653:                     */
                    654:                    if(!activeCmd->discEnable) {
                    655:                            ddm_chip("***Illegal Disconnect attempt\n",
                    656:                                    1,2,3,4,5);
                    657:                            IOLog("AMD53C974: Illegal disconnect attempt"
                    658:                                    " on target %d\n",
                    659:                                    activeCmd->scsiReq->target);
                    660:                            [self hwAbort:SR_IOST_BV
                    661:                                    reason:NULL];
                    662:                            return;
                    663:                    }
                    664:                    scState = SCS_DISCONNECTED;
                    665:                    [self disconnect];
                    666:                    return;
                    667: 
                    668:                case MSG_SAVEPTRS:
                    669:                    activeCmd->savedPtr = activeCmd->currentPtr;
                    670:                    activeCmd->savedByteCount = 
                    671:                            activeCmd->currentByteCount;
                    672:                    break;
                    673:                    
                    674:                case MSG_RESTOREPTRS:
                    675:                    activeCmd->currentPtr = activeCmd->savedPtr;
                    676:                    activeCmd->currentByteCount = 
                    677:                            activeCmd->savedByteCount;
                    678:                    break;
                    679:                            
                    680:                case MSG_MSGREJECT:
                    681:                    /*
                    682:                     * look at last message sent; may have to 
                    683:                     * disable sync or cmd queue mode for this target.
                    684:                     * This assumes that we don't send SDTR and queue tag
                    685:                     * in the same message.
                    686:                     */
                    687:                    ddm_chip("fsmAcceptingMsg: MESSAGE REJECT RECEIVED "
                    688:                            "from target %d\n", 
                    689:                            activeCmd->scsiReq->target, 2,3,4,5);
                    690:                    if(currMsgOutCnt == 0) {
                    691:                            /*
                    692:                             * Huh? We haven't sent a message recently...
                    693:                             */
                    694:                            [self hwAbort:SR_IOST_BV
                    695:                                    reason:"Unexpected Message Reject"];
                    696:                            return;
                    697:                    }
                    698:                    switch(currMsgOut[0]) {
                    699:                        case MSG_SIMPLE_QUEUE_TAG:      
                    700:                            [self disableMode:AM_CmdQueue];
                    701:                            break;
                    702:                        case MSG_EXTENDED:
                    703:                            /*
                    704:                             * Only one we ever send is sync negotiation..
                    705:                             */
                    706:                            if(currMsgOut[2] == MSG_SDTR) {
                    707:                                [self disableMode:AM_Sync];
                    708:                                SDTR_State = SNS_NONE;
                    709:                                break;
                    710:                            }
                    711:                            else {
                    712:                                [self hwAbort:SR_IOST_INT
                    713:                                    reason:"Currupted Message Buffer"];
                    714:                                return;
                    715:                            }
                    716:                        default:
                    717:                            IOLog("AMD53C974: %s Message Rejected\n",
                    718:                                    IOFindNameForValue(currMsgOut[0], 
                    719:                                    scsiMsgValues));
                    720:                            /* oh well... */
                    721:                            break;
                    722:                    }
                    723:                    
                    724:                    /*
                    725:                     * In any case, we're definitely thru with the 
                    726:                     * outbound message buffer.
                    727:                     */
                    728:                    currMsgOutCnt = 0;
                    729:                    break;
                    730:                    
                    731:                case MSG_LNKCMDCMPLT:
                    732:                case MSG_LNKCMDCMPLTFLAG:
                    733:                    /*
                    734:                     * This should never happen, because hwStart trashes
                    735:                     * commands with the LINK bit on.
                    736:                     */
                    737:                    [self hwAbort:SR_IOST_BV reason:"Linked command"];
                    738:                    return;
                    739:                    
                    740:                case MSG_EXTENDED:
                    741:                    /*
                    742:                     * The only valid one is sync negotiation....
                    743:                     */
                    744:                    switch(currMsgIn[index+2]) {
                    745:                        case MSG_SDTR:
                    746:                            if(currMsgIn[index+1] != (MSG_SDTR_LENGTH-2)) {
                    747:                                [self hwAbort:SR_IOST_BV 
                    748:                                    reason:"Bad Extended Msg Length"];
                    749:                                return;
                    750:                            }
                    751:                            switch(SDTR_State) {
                    752:                                case SNS_HOST_INIT:
                    753:                                    /* 
                    754:                                     * Just completed SDTR that we initiated.
                    755:                                     */
                    756:                                    if([self parseSDTR:&currMsgIn[index]] 
                    757:                                                == NO) {
                    758:                                        [self hwAbort:SR_IOST_HW 
                    759:                                            reason:"Bad SDTR Parameters"];
                    760:                                        return;
                    761:                                    }
                    762:                                   
                    763:                                   /*
                    764:                                    * Successful SDTR. 
                    765:                                    */
                    766:                                    ddm_chip("host-init SDTR COMPLETE\n", 
                    767:                                        1,2,3,4,5);
                    768:                                    SDTR_State = SNS_NONE;
                    769:                                    break;
                    770:                                
                    771:                                case SNS_TARGET_INIT:
                    772:                                    /*
                    773:                                     * Target-initiated negotiaited. This
                    774:                                     * was detected in fsmGettingMsg, where
                    775:                                     * we set ATN true.
                    776:                                     * Cons up a response and prime the message 
                    777:                                     * out state machine to send it.
                    778:                                     */
                    779:                                    [self createSDTR : currMsgOut
                    780:                                            inboundMsg : &currMsgIn[index]];
                    781:                                    currMsgOutCnt = MSG_SDTR_LENGTH;
                    782:                                    msgOutState = MOS_WAITING;
                    783:                                    break;
                    784:                                   
                    785:                                default:
                    786:                                    IOPanic("AMD53C974: Bad SDTR_State");
                    787:                            }
                    788:                            
                    789:                            /*
                    790:                             * Skip over the rest of this message; index
                    791:                             * should point to the last byte of this message.
                    792:                             */
                    793:                            index += (MSG_SDTR_LENGTH - 1);
                    794:                            break;
                    795:     
                    796:                        default:
                    797:                            IOLog("AMD53C974: Unexpected Extended Message "
                    798:                                    "(0x%x) Received\n",
                    799:                                    currMsgIn[index+2]);
                    800:                            [self hwAbort:SR_IOST_BV reason:NULL];
                    801:                            return;
                    802:                    }   
                    803:                    break;
                    804:                                
                    805:                default:
                    806:                    /*
                    807:                     * all others are unacceptable. 
                    808:                     */
                    809:                    IOLog("AMD53C974: Illegal message (0x%x)\n", 
                    810:                            currMsgIn[index]);
                    811:                    [self messageOut:MSG_MSGREJECT];
                    812:            } 
                    813:        } /* for index */
                    814:        
                    815:        /*
                    816:         * Default case for 'break' from above switch - back to following 
                    817:         * phase changes.
                    818:         */
                    819:        scState = SCS_INITIATOR;
                    820: }
                    821: 
                    822: /*
                    823:  * Just completed the SCMD_TRANSFER_INFO operation for message out. 
                    824:  */
                    825: - (void)fsmSendingMsg
                    826: {
                    827:        ddm_chip("fsmSendingMsg\n", 1,2,3,4,5);
                    828:        ASSERT(activeCmd != NULL);
                    829:        scState = SCS_INITIATOR;
                    830:        if(SDTR_State == SNS_TARGET_INIT) {
                    831:                /*
                    832:                 * If the message we just sent was a SDTR, we've just 
                    833:                 * completed a target-initiated SDTR sequence. 
                    834:                 * Note this assumes that an outbound SDTR in this 
                    835:                 * situation is the only message in currMsgOut[].
                    836:                 * This will have to change if we send a queue tag and
                    837:                 * SDTR in the sqame message.
                    838:                 */
                    839:                if((currMsgOutCnt == MSG_SDTR_LENGTH) &&
                    840:                   (currMsgOut[0] == MSG_EXTENDED) &&
                    841:                   (currMsgOut[1] == (MSG_SDTR_LENGTH - 2)) &&
                    842:                   (currMsgOut[2] == MSG_SDTR)) {
                    843:                        
                    844:                        ddm_chip("fsmSendingMsg: target-init SDTR complete\n",
                    845:                                1,2,3,4,5);
                    846:                        if([self parseSDTR:currMsgOut] == NO) {
                    847:                                /*
                    848:                                 * Shouldn't fail; we generated this 
                    849:                                 * message ourself...
                    850:                                 */
                    851:                                IOPanic("AMD53C974: SDTR Problem\n");
                    852:                        }
                    853:                        SDTR_State = SNS_NONE;
                    854:                }
                    855:        }
                    856: }
                    857: 
                    858: 
                    859: /*
                    860:  * Just completed the SCMD_TRANSFER_INFO operation for command.
                    861:  */
                    862: - (void)fsmSendingCmd
                    863: {
                    864:        ddm_chip("fsmSendingCmd\n", 1,2,3,4,5);
                    865:        ASSERT(activeCmd != NULL);
                    866:        scState = SCS_INITIATOR;
                    867: }
                    868: 
                    869: /*
                    870:  * Follow SCSI Phase change. Called while SCS_INITIATOR. 
                    871:  */
                    872: - (void)fsmPhaseChange
                    873: {
                    874:        int             phase;
                    875:        char            *cp;
                    876:        cdb_t           *cdbp;
                    877:        int             i;
                    878:        sc_status_t     rtn;
                    879:        
                    880:        ddm_chip("fsmPhaseChange\n", 1,2,3,4,5);
                    881:        ASSERT(activeCmd != NULL);
                    882: 
                    883:        /*
                    884:         * Advance msg out state machine -- SCSI spec says if
                    885:         * we do a msg out phase and then see another phase
                    886:         * we can assume msg was transmitted without error.
                    887:         * However, if we're in msg in, we may have a message reject
                    888:         * coming in, so we'll keep currMsgOut[] valid in that case.
                    889:         *
                    890:         * FIXME - one case which this would not cover is the queue tag
                    891:         * message saved in currMsgOut[] during selection. We don't 
                    892:         * go to MOS_SAWMSGOUT in that case. problem?
                    893:         */
                    894:        phase = saveStatus & SS_PHASEMASK;
                    895:        if ((phase != PHASE_MSGOUT) &&
                    896:            (phase != PHASE_MSGIN) &&
                    897:            (msgOutState == MOS_SAWMSGOUT)) {
                    898:                msgOutState = MOS_NONE;
                    899:                currMsgOutCnt = 0;
                    900:        }
                    901: 
                    902:        /*
                    903:         * If we just sent a host-initiated SDTR and the target went 
                    904:         * to something other than phase in, we assume that the negotiation
                    905:         * failed. This is in violation of the spec, but the Sony CDROM 
                    906:         * does this.
                    907:         */
                    908:        if((SDTR_State == SNS_HOST_INIT) && (phase != PHASE_MSGIN)) {
                    909:                ddm_chip("IMPLIED SNS_HOST_INIT Reject\n", 1,2,3,4,5);
                    910:                [self disableMode:AM_Sync];
                    911:                SDTR_State = SNS_NONE;
                    912:        }
                    913:        
                    914:        /* 
                    915:         * make sure we start off with a clean slate.
                    916:         *
                    917:         * NO - this can disturb possible sync data in! We'll need to cover
                    918:         * this in individual cases elsewhere...
                    919:         */
                    920:        /* WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO); */
                    921:        ddm_chip("fsmPhaseChange:  phase = %s\n", 
                    922:                IOFindNameForValue(phase, scsiPhaseValues), 2,3,4,5);
                    923: 
                    924:        switch (phase) {
                    925: 
                    926:            case PHASE_COMMAND:
                    927:                /*
                    928:                 * The normal case here is after a host-initiated SDTR
                    929:                 * sequence. 
                    930:                 */
                    931:                ddm_chip("fsmPhaseChange: command phase\n", 1,2,3,4,5);
                    932:                WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO);
                    933:                cdbp = &activeCmd->scsiReq->cdb;
                    934:                cp = (char *)cdbp;
                    935:                for(i=0; i<activeCmd->cdbLength; i++) {
                    936:                        WRITE_REG(scsiFifo, *cp++);
                    937:                }
                    938: 
                    939: #if    0
                    940:                /*
                    941:                 * This causes extra bytes to sit around in the fifo
                    942:                 * if we go straight to data phase after this, and
                    943:                 * we can't clear the fifo at that time in case
                    944:                 * we're in sync data in...
                    945:                 */
                    946:                /*
                    947:                 * fill fifo to avoid spurious command phase for target
                    948:                 * chips that try to get max command length
                    949:                 */
                    950:                for (i = 12 - activeCmd->cdbLength; i > 0; i--)
                    951:                        WRITE_REG(scsiFifo, 0);
                    952: #endif 0
                    953:                WRITE_REG(scsiCmd, SCMD_TRANSFER_INFO);
                    954:                scState = SCS_SENDINGCMD;
                    955:                break;
                    956: 
                    957:            case PHASE_DATAOUT: /* To Target from Initiator (write) */
                    958:                if(activeCmd->scsiReq->read) {
                    959:                        [self hwAbort:SR_IOST_BV reason:"bad i/o direction"];
                    960:                        break;
                    961:                }
                    962:                if(rtn = [self dmaStart]) {
                    963:                        [self hwAbort:rtn 
                    964:                                reason: IOFindNameForValue(rtn, 
                    965:                                        IOScStatusStrings)];
                    966:                        break;
                    967:                }
                    968:                break;
                    969:                
                    970:            case PHASE_DATAIN:  /* From Target to Initiator (read) */
                    971:                if(!activeCmd->scsiReq->read) {
                    972:                        [self hwAbort:SR_IOST_BV reason:"bad i/o direction"];
                    973:                        break;
                    974:                }
                    975:                if(rtn = [self dmaStart]) {
                    976:                        [self hwAbort:rtn 
                    977:                                reason: IOFindNameForValue(rtn, 
                    978:                                        IOScStatusStrings)];
                    979:                        break;
                    980:                }
                    981:                break;
                    982:        
                    983:            case PHASE_STATUS:  /* Status from Target to Initiator */
                    984:                /*
                    985:                 * fsmCompleting will collect the STATUS byte
                    986:                 * (and hopefully a MSG) from the fifo when this
                    987:                 * completes.
                    988:                 */
                    989:                scState = SCS_COMPLETING;
                    990:                currMsgInCnt = 0;
                    991:                WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO);
                    992:                WRITE_REG(scsiCmd, SCMD_INIT_CMD_CMPLT);
                    993:                break;
                    994:                
                    995:            case PHASE_MSGIN:   /* Message from Target to Initiator */
                    996:                scState = SCS_GETTINGMSG;
                    997:                currMsgInCnt = 0;
                    998:                WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO);
                    999:                WRITE_REG(scsiCmd, SCMD_TRANSFER_INFO);
                   1000:                break;
                   1001:                
                   1002:            case PHASE_MSGOUT:  /* Message from Initiator to Target */
                   1003:                WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO);
                   1004:                if(msgOutState == MOS_WAITING) {
                   1005:                        int i;
                   1006:                        
                   1007:                        ASSERT(currMsgOutCnt != 0);
                   1008:                        for(i=0; i<currMsgOutCnt; i++) {
                   1009:                                ddm_chip("msg out: writing 0x%x\n",
                   1010:                                        currMsgOut[i], 2,3,4,5);
                   1011:                                WRITE_REG(scsiFifo, currMsgOut[i]);
                   1012:                        }
                   1013:                        msgOutState = MOS_SAWMSGOUT;
                   1014:                        if(SDTR_State == SNS_HOST_INIT_NEEDED) {
                   1015:                                /*
                   1016:                                 * sending SDTR message after select.
                   1017:                                 */
                   1018:                                ASSERT(currMsgOut[0] == MSG_EXTENDED);
                   1019:                                ASSERT(currMsgOut[2] == MSG_SDTR);
                   1020:                                ASSERT(currMsgOutCnt == MSG_SDTR_LENGTH);
                   1021:                                ddm_chip("going to SNS_HOST_INIT\n",
                   1022:                                        1,2,3,4,5);
                   1023:                                SDTR_State = SNS_HOST_INIT;
                   1024:                        }
                   1025:                } else {
                   1026:                        /*
                   1027:                         * Target went to msg out and we don't have
                   1028:                         * anything to send!  Just give it a nop.
                   1029:                         */
                   1030:                        ddm_chip("msg out: sending MSG_NOP\n", 1,2,3,4,5);
                   1031:                        WRITE_REG(scsiFifo, MSG_NOP);
                   1032:                }
                   1033: 
                   1034:                scState = SCS_SENDINGMSG;
                   1035:                /* 
                   1036:                 * ATN is automatically cleared when transfer info completes.
                   1037:                 */
                   1038:                WRITE_REG(scsiCmd, SCMD_TRANSFER_INFO);
                   1039:                break;
                   1040:                
                   1041:            default:
                   1042:                [self hwAbort:SR_IOST_HW reason:"Bad SCSI phase"];
                   1043:                break;
                   1044:        }
                   1045: }
                   1046: 
                   1047: /*
                   1048:  * Set up to send single-byte message. 
                   1049:  */ 
                   1050: - (void) messageOut : (u_char)msg
                   1051: {
                   1052:        ddm_chip("messageOut (0x%x)\n", msg, 2,3,4,5);
                   1053:        currMsgOut[0] = msg;
                   1054:        currMsgOutCnt = 1;
                   1055:        msgOutState = MOS_WAITING;
                   1056:        WRITE_REG(scsiCmd, SCMD_SET_ATN);
                   1057: }
                   1058: 
                   1059: 
                   1060: /*
                   1061:  * Load syncPeriod, syncOffset for activeCmd per perTarget values.
                   1062:  */
                   1063: - (void)targetContext : (unsigned) target
                   1064: {
                   1065:        perTargetData *perTargetPtr;
                   1066:        
                   1067:        perTargetPtr = &perTarget[target];
                   1068:        if(!syncModeEnable || 
                   1069:           perTargetPtr->syncDisable ||
                   1070:           (perTargetPtr->syncXferOffset == 0)) {
                   1071:                /*
                   1072:                 * Easy case, async.
                   1073:                 */
                   1074:                WRITE_REG(syncOffset, 0);
                   1075:                ddm_chip("targetContext(%d): ASYNC\n", target, 2,3,4,5);
                   1076:                #ifdef  DEBUG
                   1077:                syncOffsetShadow = 0;
                   1078:                #endif  DEBUG
                   1079:        }
                   1080:        else {
                   1081:                unsigned char periodReg;
                   1082:                unsigned char offsetReg;
                   1083:                
                   1084:                periodReg = nsPeriodToSyncPeriodReg(
                   1085:                        perTargetPtr->syncXferPeriod,
                   1086:                        fastModeEnable, scsiClockRate);
                   1087:                WRITE_REG(syncPeriod, periodReg);
                   1088:                
                   1089:                /*
                   1090:                 * FIXME - might eventually want to use non-default
                   1091:                 * values for RAD and RAA...
                   1092:                 */
                   1093:                offsetReg = (perTargetPtr->syncXferOffset |
                   1094:                        SOR_RAD_DEFAULT | SOR_RAA_DEFAULT);
                   1095:                WRITE_REG(syncOffset, offsetReg);
                   1096:                ddm_chip("targetContext(%d): period 0x%x offset %d\n",
                   1097:                        target, periodReg, offsetReg, 4,5);
                   1098:                #ifdef  DEBUG
                   1099:                syncOffsetShadow = offsetReg;
                   1100:                syncPeriodShadow = periodReg;
                   1101:                #endif  DEBUG
                   1102:        }
                   1103: }
                   1104: 
                   1105: /*
                   1106:  * Parse and validate 5-byte SDTR message. If valid, save in perTarget 
                   1107:  * and in hardware. Returns YES if valid, else NO.
                   1108:  * 
                   1109:  * Specified message buffer could be from either currMsgIn[] or 
                   1110:  * currMsgOut[].
                   1111:  */
                   1112: - (BOOL)parseSDTR    : (unsigned char *)sdtrMessage
                   1113: {
                   1114:        unsigned nsPeriod;
                   1115:        unsigned char fastClock;
                   1116:        unsigned minPeriod;
                   1117:        perTargetData *perTargetPtr;
                   1118:        
                   1119:        ASSERT(activeCmd != NULL);
                   1120:        perTargetPtr = &perTarget[activeCmd->scsiReq->target];
                   1121:        
                   1122:        if(sdtrMessage[0] != MSG_EXTENDED) {
                   1123:                goto Bad;
                   1124:        }
                   1125:        if(sdtrMessage[1] != (MSG_SDTR_LENGTH - 2)) {
                   1126:                goto Bad;
                   1127:        }
                   1128:        if(sdtrMessage[2] != MSG_SDTR) {
                   1129:                goto Bad;
                   1130:        }
                   1131:        
                   1132:        /*
                   1133:         * period
                   1134:         */
                   1135:        nsPeriod = SDTR_TO_NS_PERIOD(sdtrMessage[3]);
                   1136:        fastClock = READ_REG(control3) & CR3_FAST_CLOCK;
                   1137:        if(fastClock && fastModeEnable) {
                   1138:                minPeriod = MIN_PERIOD_FASTCLK_FASTSCSI;
                   1139:        }
                   1140:        else {
                   1141:                minPeriod = MIN_PERIOD_NORM;
                   1142:        }
                   1143:        if(nsPeriod < minPeriod) {
                   1144:                goto Bad;
                   1145:        }
                   1146:        perTargetPtr->syncXferPeriod = nsPeriod;
                   1147:        
                   1148:        /*
                   1149:         * Offset
                   1150:         */
                   1151:        if(sdtrMessage[4] > AMD_MAX_SYNC_OFFSET) {
                   1152:                goto Bad;
                   1153:        }
                   1154:        perTargetPtr->syncXferOffset = sdtrMessage[4];
                   1155:        
                   1156:        /*
                   1157:         * Success.
                   1158:         */
                   1159:        perTargetPtr->syncDisable = 0;
                   1160:        perTargetPtr->syncNegotNeeded = 0;
                   1161:        [self targetContext:activeCmd->scsiReq->target];
                   1162:        
                   1163:        ddm_chip("parseSDTR SUCCESS: %02x %02x %02x %02x %02x\n",
                   1164:                sdtrMessage[0], sdtrMessage[1], sdtrMessage[2], 
                   1165:                sdtrMessage[3], sdtrMessage[4]);
                   1166:        ddm_chip("   period %d offset %d\n", perTargetPtr->syncXferPeriod,
                   1167:                perTargetPtr->syncXferOffset, 3,4,5);
                   1168:        return YES;
                   1169:        
                   1170: Bad:
                   1171:        ddm_chip("parseSDTR FAIL: 02%x %02x %02x %02x %02x\n",
                   1172:                sdtrMessage[0], sdtrMessage[1], sdtrMessage[2], 
                   1173:                sdtrMessage[3], sdtrMessage[4]);
                   1174:        return NO;
                   1175: }
                   1176: 
                   1177: /*
                   1178:  * Cons up a SDTR message appropriate for both our hardware and a possible
                   1179:  * target-generated SDTR message. If inboundMsg is NULL, we just use
                   1180:  * the parameters we want.
                   1181:  */
                   1182: - (void)createSDTR             : (unsigned char *)outboundMsg  // required
                   1183:                     inboundMsg : (unsigned char *)inboundMsg
                   1184: {
                   1185:        unsigned        desiredNsPeriod;
                   1186:        unsigned        inboundNsPeriod;
                   1187:        unsigned        offset = AMD_MAX_SYNC_OFFSET;
                   1188:        unsigned char   fastClock;
                   1189:        
                   1190:        outboundMsg[0] = MSG_EXTENDED;
                   1191:        outboundMsg[1] = MSG_SDTR_LENGTH - 2;
                   1192:        outboundMsg[2] = MSG_SDTR;
                   1193:        
                   1194:        /*
                   1195:         * period
                   1196:         */
                   1197:        fastClock = READ_REG(control3) & CR3_FAST_CLOCK;
                   1198:        if(fastClock && fastModeEnable) {
                   1199:                desiredNsPeriod = MIN_PERIOD_FASTCLK_FASTSCSI;
                   1200:        }
                   1201:        else {
                   1202:                desiredNsPeriod = MIN_PERIOD_NORM;
                   1203:        }
                   1204:        if(inboundMsg) {
                   1205:                inboundNsPeriod = SDTR_TO_NS_PERIOD(inboundMsg[3]);
                   1206:        }
                   1207:        else {
                   1208:                inboundNsPeriod = desiredNsPeriod;
                   1209:        }
                   1210:        if(inboundNsPeriod > desiredNsPeriod) {
                   1211:                /*
                   1212:                 * Target is slower than us
                   1213:                 */
                   1214:                desiredNsPeriod = inboundNsPeriod;
                   1215:        }
                   1216:        outboundMsg[3] = NS_PERIOD_TO_SDTR(desiredNsPeriod);
                   1217:        
                   1218:        /*
                   1219:         * Offset
                   1220:         */
                   1221:        if(inboundMsg) {
                   1222:                offset = inboundMsg[4];
                   1223:                if(offset > AMD_MAX_SYNC_OFFSET) {
                   1224:                        /* 
                   1225:                         * target's buffer smaller than ours
                   1226:                         */
                   1227:                        offset = AMD_MAX_SYNC_OFFSET;
                   1228:                }
                   1229:        }
                   1230:        outboundMsg[4] = offset;
                   1231:        
                   1232:        ddm_chip("createSDTR: %02x %02x %02x %02x %02x\n",
                   1233:                outboundMsg[0], outboundMsg[1], outboundMsg[2], 
                   1234:                outboundMsg[3], outboundMsg[4]);
                   1235:        ddm_chip("   period %d   offset %d\n", desiredNsPeriod, offset, 3,4,5);
                   1236: }
                   1237: 
                   1238: /*
                   1239:  * Disable specified mode for activeCmd's target. If mode is currently 
                   1240:  * enabled, we'll log a message to the console.
                   1241:  */
                   1242: - (void)disableMode : (AMD_Mode)mode
                   1243: {
                   1244:        int target;
                   1245:        perTargetData *perTargetPtr;
                   1246:        const char *modeStr = NULL;
                   1247:        
                   1248:        ASSERT(activeCmd != NULL);
                   1249:        target = activeCmd->scsiReq->target;
                   1250:        perTargetPtr = &perTarget[target];
                   1251:        switch(mode) {
                   1252:            case AM_Sync:
                   1253:                if(perTargetPtr->syncDisable == 0) {
                   1254:                        perTargetPtr->syncDisable = 1;
                   1255:                        modeStr = "Synchronous Transfer Mode";
                   1256:                }
                   1257:                [self targetContext:activeCmd->scsiReq->target];
                   1258:                break;
                   1259:            case AM_CmdQueue:
                   1260:                if(perTargetPtr->cmdQueueDisable == 0) {
                   1261:                        perTargetPtr->cmdQueueDisable = 1;
                   1262:                        modeStr = "Command Queueing";
                   1263:                }
                   1264:                break;
                   1265:        }
                   1266:        ddm_chip("DISABLING %s for target %d\n", modeStr, target, 3,4,5);
                   1267:        if(modeStr) {
                   1268:                IOLog("AMD53C974: DISABLING %s for target %d\n", 
                   1269:                        modeStr, target);
                   1270:        }
                   1271: }
                   1272: 
                   1273: @end   /* AMD_SCSI(ChipPrivate) */

unix.superglobalmegacorp.com

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