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

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