Annotation of kernel/bsd/dev/ppc/drvApple96_SCSI/Apple96ISR.m, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /**
        !            26:  * Copyright (c) 1994-1996 NeXT Software, Inc.  All rights reserved. 
        !            27:  * Copyright 1997 Apple Computer Inc. All Rights Reserved.
        !            28:  * @author     Martin Minow    mailto:[email protected]
        !            29:  * @revision   1997.02.17      Initial conversion from AMDPCSCSIDriver sources.
        !            30:  *
        !            31:  * Set tabs every 4 characters.
        !            32:  *
        !            33:  * Apple96Chip.m - Chip-specific methods for Apple96 SCSI driver.
        !            34:  *
        !            35:  * Edit History
        !            36:  * 1997.02.18  MM              Initial conversion from AMDPCSCSIDriver sources.
        !            37:  * 1997.04.17  MM              Removed SCS_PHASECHANGE (not needed)
        !            38:  */
        !            39: #import "Apple96SCSI.h"
        !            40: #import "Apple96ISR.h"
        !            41: #import "Apple96BusState.h"
        !            42: #import "Apple96Curio.h"
        !            43: #import "Apple96CurioPublic.h"
        !            44: #import "Apple96CurioPrivate.h"
        !            45: #import "Apple96SCSIPrivate.h"
        !            46: #import "MacSCSICommand.h"
        !            47: #import "bringup.h"
        !            48: #import <driverkit/generalFuncs.h>
        !            49: #import <kernserv/prototypes.h>
        !            50: 
        !            51: IONamedValue scsiMsgValues[] = {
        !            52:        { kScsiMsgCmdComplete,                  "Command Complete"              },
        !            53:        { kScsiMsgExtended,                             "Extended Message"              },
        !            54:        { kScsiMsgSaveDataPointers,             "Save Pointers"                 },
        !            55:        { kScsiMsgRestorePointers,              "Restore Pointers"              },
        !            56:        { kScsiMsgDisconnect,                   "Disconnect"                    },
        !            57:        { kScsiMsgInitiatorDetectedErr, "Initiator Det Error"   },
        !            58:        { kScsiMsgAbort,                                "Abort"                                 },
        !            59:        { kScsiMsgRejectMsg,                    "Message Reject"                },
        !            60:        { kScsiMsgNop,                                  "Nop"                                   },
        !            61:        { kScsiMsgParityErr,                    "Message parity Error"  },
        !            62:        { 0,                                                    NULL                                    }
        !            63: };
        !            64: 
        !            65: IONamedValue scsiPhaseValues[] = {
        !            66:        { kBusPhaseDATO,                "data out"                              },
        !            67:        { kBusPhaseDATI,                "data in"                               },
        !            68:        { kBusPhaseCMD,                 "command"                               },
        !            69:        { kBusPhaseSTS,                 "status"                                },
        !            70:        { kBusPhaseMSGO,                "message out"                   },
        !            71:        { kBusPhaseMSGI,                "message in"                    },
        !            72:        { kBusPhaseBusFree,             "bus free"                              },
        !            73:        { 0,                                    NULL                                    }
        !            74: };
        !            75: 
        !            76: /*
        !            77:  * For IOFindNameForValue() and ddm's.
        !            78:  */
        !            79: IONamedValue gAutomatonStateValues[] = { 
        !            80:        {SCS_UNINITIALIZED,             "uninitialized"                                 },
        !            81:        {SCS_DISCONNECTED,              "disconnected"                                  },
        !            82:        {SCS_SELECTING,                 "selecting"                                             },
        !            83:        {SCS_RESELECTING,               "reselection in progress"               },
        !            84:        {SCS_INITIATOR,                 "in progress, initiator"                },
        !            85:        {SCS_COMPLETING,                "completing command"                    },
        !            86:        {SCS_WAIT_FOR_BUS_FREE, "waiting for bus free"                  },
        !            87:        {SCS_DMACOMPLETE,               "waiting for dma completion"    },
        !            88:        {SCS_SENDINGMSG,                "sending message bytes"                 },
        !            89:        {SCS_GETTINGMSG,                "receiving message bytes"               },
        !            90:        {SCS_SENDINGCMD,                "sending command bytes"                 },
        !            91:        {SCS_DEATH_MARCH,               "error recovery"                                },
        !            92:        {0,                             NULL                                    },
        !            93: };
        !            94: 
        !            95: @implementation Apple96_SCSI(InterruptService)
        !            96: 
        !            97: /*
        !            98:  * SCSI device interrupt handler. We are called with interrupts disabled.
        !            99:  * ** ** ** Check whether interrupts are actually disabled!
        !           100:  */
        !           101: - (void) hardwareInterrupt
        !           102: {
        !           103:                ENTRY("Hin hardwareInterrupt");
        !           104:        if (CURIOinterruptPending()) {
        !           105:                        ddmChip("hardwareInterrupt entry: cmd %08x [%02x],"
        !           106:                        " status %02x, intr %02x, bus state: %s\n",
        !           107:                        gActiveCommand,
        !           108:                        (gCurrentTarget << 4) | gCurrentLUN,
        !           109:                        gSaveStatus,
        !           110:                        gSaveInterrupt,
        !           111:                        IOFindNameForValue(gBusState, gAutomatonStateValues)
        !           112:                );
        !           113:                        /*
        !           114:                         * There is an interrupt pending for this device. Note:
        !           115:                         * because we can cycle through this sequence, it must
        !           116:                         * be executed from a (high-priority) I/O thread, and not
        !           117:                         * from a primary interrupt service routine.
        !           118:                         */
        !           119:                        gFlagCheckForAnotherInterrupt = TRUE;
        !           120:                        do {
        !           121:                                gFlagNeedAnotherInterrupt = FALSE;
        !           122:                                ddmChip("hardwareInterrupt loop: cmd %08x [%02x],"
        !           123:                                        " status %02x, intr %02x, bus state: %s\n",
        !           124:                                        gActiveCommand,
        !           125:                                        (gCurrentTarget << 4) | gCurrentLUN,
        !           126:                                        gSaveStatus,
        !           127:                                        gSaveInterrupt,
        !           128:                                        IOFindNameForValue(gBusState, gAutomatonStateValues)
        !           129:                                );
        !           130:                                if ((gSaveInterrupt & sGrossErr) != 0) {
        !           131:                        /*
        !           132:                                         * Gross error is set incorrectly (according to
        !           133:                                         * Clinton Bauder).
        !           134:                         */
        !           135:                    ddmChip("Gross error: ignored, sts %02x, int %02x\n",
        !           136:                                gSaveStatus, gSaveInterrupt, 3, 4, 5);
        !           137:                                        gSaveInterrupt &= ~sGrossErr;
        !           138:                                }
        !           139:                                if ((gSaveInterrupt & iIlegalCmd) != 0) {
        !           140:                                /*
        !           141:                                 * Software screwup (gross error). Start over from scratch.
        !           142:                                 * We can get this if we write too many commands into the register.
        !           143:                                 */
        !           144:                                        [self logRegisters : FALSE reason : "Illegal command interrupt"];
        !           145:                                        if (gBusState != SCS_DEATH_MARCH) {
        !           146:                                                [self fsmStartErrorRecovery
        !           147:                                                                : SR_IOST_INT
        !           148:                                                                        reason  : "Illegal command interrupt"
        !           149:                                ];
        !           150:                        }
        !           151:                                        gFlagCheckForAnotherInterrupt = FALSE;
        !           152:                                } /* If chip error */
        !           153:                                if ((gSaveInterrupt & iDisconnect) != 0) {
        !           154:                                        ddmChip("hardwareInterrupt: enabling reselection\n", 1,2,3,4,5);
        !           155:                    CURIOenableSelectionOrReselection();
        !           156:                                        /*
        !           157:                                         * Radar 1678545: this is the only (normal) place
        !           158:                                         * that gFlagBusBusy is cleared. (It's also cleared by
        !           159:                                         * bus reset and driver initialization.)
        !           160:                                         */
        !           161:                                        gFlagBusBusy = FALSE;
        !           162:                                }
        !           163:                                if ((gSaveInterrupt & iResetDetect) != 0) {
        !           164:                                IOLog("%s: SCSI Bus Reset\n", [self name]);
        !           165:                                /*
        !           166:                                 * While we would like to abort all pending and active commands,
        !           167:                                 * we can't do this without taking the pending command lock,
        !           168:                                 * which can, conceivably, lead to a race condition. If this
        !           169:                                 * (quick and dirty) analysis is incorrect, enable the following:
        !           170:                                 *              [self abortAllCommands : SR_IOST_RESET];
        !           171:                                 */
        !           172:                                [self curioHardwareReset
        !           173:                                                                : FALSE
        !           174:                                                reason  : "SCSI Bus Reset"
        !           175:                                ];
        !           176:                                        gFlagCheckForAnotherInterrupt = FALSE;
        !           177:                                } /* If bus reset */
        !           178:                                else if ((gSaveStatus & sParityErr) != 0 && gFlagBusBusy) {
        !           179:                                        [self fsmStartErrorRecovery
        !           180:                                                                : SR_IOST_PARITY
        !           181:                                                reason  : "SCSI bus parity error"
        !           182:                                ];
        !           183:                                        gFlagCheckForAnotherInterrupt = FALSE;
        !           184:                                } /* If device parity error and not disconnected */
        !           185:                        else {
        !           186:                                /*
        !           187:                                         * Only certain states are legal if the bus is busy.
        !           188:                                         */
        !           189:                                        if (gFlagBusBusy) {
        !           190:                                                /*
        !           191:                                 * This is a legitimate interrupt (parity error and bus reset
        !           192:                                 * have already been handled). The entity that started the
        !           193:                                 * chip action that caused the interrupt (deep breath)
        !           194:                                 * set gBusState to indicate why the interrupt happened.
        !           195:                                 * Call the proper finite-state machine function. On return,
        !           196:                                 * gBusState will be set to one of the following values:
        !           197:                                 *      SCS_INITIATOR           Start an action on the current phase.
        !           198:                                         *      SCS_DISCONNECT                  The bus is free.
        !           199:                                         *      SCS_WAIT_FOR_BUS_FREE   The bus should go free shortly.
        !           200:                                         * Note that SCS_WAIT_FOR_BUS_FREE and fsmWaitForBusFree
        !           201:                                         * short-circuit some of the automaton to avoid unnecessary
        !           202:                                         * interrupt events.
        !           203:                                 */
        !           204:                                switch (gBusState) {
        !           205:                                case SCS_DISCONNECTED:  [self fsmDisconnected];         break;
        !           206:                                case SCS_SELECTING:             [self fsmSelecting];            break;
        !           207:                                                case SCS_RESELECTING:           [self fsmReselecting];                          break;
        !           208:                                case SCS_INITIATOR:             [self fsmInitiator];            break;
        !           209:                                case SCS_COMPLETING:    [self fsmCompleting];           break;
        !           210:                                case SCS_DMACOMPLETE:   [self fsmDMAComplete];          break;
        !           211:                                case SCS_SENDINGMSG:    [self fsmSendingMsg];           break;
        !           212:                                case SCS_GETTINGMSG:    [self fsmGettingMsg];           break;
        !           213:                                case SCS_SENDINGCMD:    [self fsmSendingCmd];           break;
        !           214:                                        case SCS_WAIT_FOR_BUS_FREE:     [self fsmWaitForBusFree];                       break;
        !           215:                                        case SCS_DEATH_MARCH:           [self fsmErrorRecoveryInterruptService];        break;
        !           216:                                case SCS_UNINITIALIZED: /* Illegal here */
        !           217:                                default:
        !           218:                                        IOLog("%s: Bug: illegal interrupt state: %s\n",
        !           219:                                                [self name],
        !           220:                                                IOFindNameForValue(gSaveStatus & mPhase, scsiPhaseValues)
        !           221:                                        );
        !           222:                                        IOPanic("Apple96 SCSI: Illegal bus automaton state.");
        !           223:                                } /* switch gBusState */
        !           224:                                        }
        !           225:                                        else {
        !           226:                                        /*
        !           227:                                                 * The bus is (or just went) free. We only allow selection, reselection,
        !           228:                                                 * wait for disconnect, or death march interrupts.
        !           229:                                         */
        !           230:                                                switch (gBusState) {
        !           231:                                                case SCS_DISCONNECTED:          [self fsmDisconnected];                         break;
        !           232:                                                case SCS_SELECTING:                     [self fsmSelecting];                            break;
        !           233:                                                case SCS_WAIT_FOR_BUS_FREE:     [self fsmWaitForBusFree];                       break;
        !           234:                                                case SCS_DEATH_MARCH:           [self fsmErrorRecoveryInterruptService];        break;
        !           235:                                                default:
        !           236:                                                        [self fsmStartErrorRecovery
        !           237:                                                                                                : SR_IOST_HW
        !           238:                                                                                reason  : "Strange SCSI state when bus free"
        !           239:                                                        ];
        !           240:                                                        gFlagCheckForAnotherInterrupt = FALSE;
        !           241:                                                } /* switch gBusState */
        !           242:                                }
        !           243:                        }
        !           244:                        /*
        !           245:                         * We have (presumably) completely handled the previous interrupt.
        !           246:                                 * At this point, there are five legitimate gBusState values:
        !           247:                                 *      SCS_RESELECTING                 Just got a reselection interrupt
        !           248:                         *      SCS_INITIATOR           Continue operation for this target.
        !           249:                                 *      SCS_DISCONNECTED                Enable selection/reselection
        !           250:                                 *      SCS_WAIT_FOR_BUS_FREE   Command completion transition
        !           251:                                 *      SCS_DEATH_MARCH                 Error recovery
        !           252:                         * Handle a SCSI Phase change if necessary. This will leave
        !           253:                         * the bus state in the "expected" state for the next operation.
        !           254:                         */
        !           255:                                switch (gBusState) {
        !           256:                                case SCS_DEATH_MARCH:
        !           257:                                        gFlagCheckForAnotherInterrupt = FALSE;
        !           258:                                        break;
        !           259:                                case SCS_RESELECTING:
        !           260:                                        [self fsmReselectionAction];
        !           261:                                        break;
        !           262:                                case SCS_INITIATOR:
        !           263:                                        if ( gFlagNeedAnotherInterrupt )        // from tagged reselect
        !           264:                                        {
        !           265:                                                gFlagNeedAnotherInterrupt = FALSE;
        !           266:                                                if ( [ self curioQuickCheckForChipInterrupt ] )
        !           267:                                                         [ self fsmPhaseChange ];
        !           268:                                        }
        !           269:                                        else
        !           270:                                        {
        !           271:                                                [ self fsmPhaseChange ];
        !           272:                                        }
        !           273:                                        break;
        !           274:                                case SCS_WAIT_FOR_BUS_FREE:
        !           275:                                        break;
        !           276:                                default:
        !           277:                                        break;
        !           278:                        }
        !           279:                        /*
        !           280:                                 * This is the final check: if we determine that the previous action will
        !           281:                                 * complete quickly (for example, it's a message in byte), we'll spin for
        !           282:                                 * up to ten microseconds to see if the chip is ready for another operation.
        !           283:                         */
        !           284:            } while (gFlagCheckForAnotherInterrupt && CURIOquickCheckForChipInterrupt());
        !           285:                        if (gBusState == SCS_DEATH_MARCH) {
        !           286:                                [self fsmContinueErrorRecovery];
        !           287:                        }
        !           288:                        if (gBusState == SCS_DISCONNECTED) {
        !           289:                                [self busFree];
        !           290:                        }
        !           291:                        ddmChip("hardwareInterrupt: DONE; state: %s, phase %s\n", 
        !           292:                                IOFindNameForValue(gBusState, gAutomatonStateValues),
        !           293:                                IOFindNameForValue(gCurrentBusPhase, scsiPhaseValues),
        !           294:                                3,4,5
        !           295:                        );
        !           296:                }
        !           297:                EXIT();
        !           298: }
        !           299: 
        !           300: @end   /* Apple96_SCSI(InterruptService) */
        !           301: 
        !           302: /* end of Apple96_Chip.m */
        !           303: 

unix.superglobalmegacorp.com

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