Annotation of ntddk/src/scsi/ncr53c9x/ncr53c9x.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1990  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     ncr53c9x.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This module contains the NCR 53c9x specific functions for the NT SCSI port
        !            12:     driver.
        !            13: 
        !            14: Author:
        !            15: 
        !            16:     Jeff Havens  (jhavens) 28-Feb-1991
        !            17: 
        !            18: Environment:
        !            19: 
        !            20:     Kernel Mode only
        !            21: 
        !            22: Revision History:
        !            23: 
        !            24: --*/
        !            25: 
        !            26: #include "miniport.h"
        !            27: #include "scsi.h"
        !            28: 
        !            29: #include "ncr53c9x.h"
        !            30: #include "mcadefs.h"
        !            31: #include "string.h"
        !            32: 
        !            33: #include "jazzdef.h"
        !            34: #include "jazzdma.h"
        !            35: 
        !            36: #undef ASSERT
        !            37: #if DBG
        !            38: VOID
        !            39: RtlAssert(
        !            40:     PVOID FailedAssertion,
        !            41:     PVOID FileName,
        !            42:     ULONG LineNumber,
        !            43:     PCHAR Message
        !            44:     );
        !            45: 
        !            46: #define ASSERT( exp ) \
        !            47:     if (!(exp)) \
        !            48:         RtlAssert( #exp, __FILE__, __LINE__, NULL )
        !            49: 
        !            50: #define ASSERTMSG( msg, exp ) \
        !            51:     if (!(exp)) \
        !            52:         RtlAssert( #exp, __FILE__, __LINE__, msg )
        !            53: 
        !            54: #else
        !            55: #define ASSERT( exp )
        !            56: #define ASSERTMSG( msg, exp )
        !            57: #endif // DBG
        !            58: 
        !            59: #if DBG
        !            60: int NcrDebug;
        !            61: #define NcrPrint(arg) ScsiDebugPrint arg
        !            62: #else
        !            63: #define NcrPrint(arg)
        !            64: #endif
        !            65: 
        !            66: //
        !            67: // Define SCSI Protocol Chip configuration parameters.
        !            68: //
        !            69: 
        !            70: #define INITIATOR_BUS_ID            0x7
        !            71: #define SELECT_TIMEOUT_FACTOR       33
        !            72: #define SYNCHRONOUS_OFFSET          0x0f
        !            73: #define ASYNCHRONOUS_OFFSET         0
        !            74: #define ASYNCHRONOUS_PERIOD         0x05
        !            75: #define RESET_STALL_TIME            25     // The minimum assertion time for
        !            76:                                            //   a SCSI bus reset.
        !            77: #define INTERRUPT_STALL_TIME        5      // Time to wait for the next interrupt.
        !            78: 
        !            79: 
        !            80: //
        !            81: // NCR 53c9x specific port driver device extension flags.
        !            82: //
        !            83: 
        !            84: #define PD_SYNCHRONOUS_RESPONSE_SENT    0x0001
        !            85: #define PD_SYNCHRONOUS_TRANSFER_SENT    0x0002
        !            86: #define PD_PENDING_START_IO             0x0004
        !            87: #define PD_MESSAGE_OUT_VALID            0x0008
        !            88: #define PD_DISCONNECT_EXPECTED          0x0010
        !            89: #define PD_SEND_MESSAGE_REQUEST         0x0020
        !            90: #define PD_POSSIBLE_EXTRA_MESSAGE_OUT   0x0040
        !            91: #define PD_PENDING_DATA_TRANSFER        0x0080
        !            92: #define PD_PARITY_ERROR_LOGGED          0x0100
        !            93: #define PD_EXPECTING_RESET_INTERRUPT    0x0200
        !            94: #define PD_EXPECTING_QUEUE_TAG          0x0400
        !            95: #define PD_TAGGED_SELECT                0x0800
        !            96: #define PD_NCR_ADAPTER                  0x1000
        !            97: 
        !            98: //
        !            99: // The following defines specify masks which are used to clear flags when
        !           100: // specific events occur, such as reset or disconnect.
        !           101: //
        !           102: 
        !           103: #define PD_ADAPTER_RESET_MASK ( PD_SYNCHRONOUS_TRANSFER_SENT  | \
        !           104:                                 PD_PENDING_START_IO           | \
        !           105:                                 PD_MESSAGE_OUT_VALID          | \
        !           106:                                 PD_SEND_MESSAGE_REQUEST       | \
        !           107:                                 PD_POSSIBLE_EXTRA_MESSAGE_OUT | \
        !           108:                                 PD_PENDING_DATA_TRANSFER      | \
        !           109:                                 PD_PARITY_ERROR_LOGGED        | \
        !           110:                                 PD_EXPECTING_QUEUE_TAG        | \
        !           111:                                 PD_TAGGED_SELECT              | \
        !           112:                                 PD_DISCONNECT_EXPECTED          \
        !           113:                                 )
        !           114: 
        !           115: #define PD_ADAPTER_DISCONNECT_MASK ( PD_SYNCHRONOUS_TRANSFER_SENT  | \
        !           116:                                      PD_MESSAGE_OUT_VALID          | \
        !           117:                                      PD_SEND_MESSAGE_REQUEST       | \
        !           118:                                      PD_POSSIBLE_EXTRA_MESSAGE_OUT | \
        !           119:                                      PD_PENDING_DATA_TRANSFER      | \
        !           120:                                      PD_PARITY_ERROR_LOGGED        | \
        !           121:                                      PD_EXPECTING_QUEUE_TAG        | \
        !           122:                                      PD_TAGGED_SELECT              | \
        !           123:                                      PD_DISCONNECT_EXPECTED          \
        !           124:                                      )
        !           125: 
        !           126: //
        !           127: // The largest SCSI bus message expected.
        !           128: //
        !           129: 
        !           130: #define MESSAGE_BUFFER_SIZE     8
        !           131: 
        !           132: //
        !           133: // Retry count limits.
        !           134: //
        !           135: 
        !           136: #define RETRY_SELECTION_LIMIT   1
        !           137: #define RETRY_ERROR_LIMIT       2
        !           138: #define MAX_INTERRUPT_COUNT     64
        !           139: 
        !           140: //
        !           141: // Bus and chip states.
        !           142: //
        !           143: 
        !           144: typedef enum _ADAPTER_STATE {
        !           145:     BusFree,
        !           146:     AttemptingSelect,
        !           147:     CommandComplete,
        !           148:     CommandOut,
        !           149:     DataTransfer,
        !           150:     DisconnectExpected,
        !           151:     MessageAccepted,
        !           152:     MessageIn,
        !           153:     MessageOut,
        !           154:     Reselected
        !           155: } ADAPTER_STATE, *PADAPTER_STATE;
        !           156: 
        !           157: //
        !           158: // Define the types of chips this driver will support.
        !           159: //
        !           160: 
        !           161: typedef enum _CHIP_TYPES {
        !           162:     Ncr53c90,
        !           163:     Ncr53c94,
        !           164:     Fas216,
        !           165:     Fas216Fast
        !           166: }CHIP_TYPES, *PCHIP_TYPES;
        !           167: 
        !           168: //
        !           169: // NCR 53c9x specific port driver logical unit flags.
        !           170: //
        !           171: 
        !           172: #define PD_STATUS_VALID                    0x0004
        !           173: #define PD_DO_NOT_CHECK_TRANSFER_LENGTH    0x0008
        !           174: #define PD_INITIATE_RECOVERY               0x0010
        !           175: #define PD_QUEUED_COMMANDS_EXECUTING       0x0020
        !           176: 
        !           177: //
        !           178: // The following defines specify masks which are used to clear flags when
        !           179: // specific events occur, such as reset or command complete.
        !           180: //
        !           181: 
        !           182: #define PD_LU_COMPLETE_MASK ( PD_STATUS_VALID                   | \
        !           183:                               PD_DO_NOT_CHECK_TRANSFER_LENGTH   | \
        !           184:                               PD_INITIATE_RECOVERY                \
        !           185:                               )
        !           186: 
        !           187: #define PD_LU_RESET_MASK ( PD_STATUS_VALID                  | \
        !           188:                            PD_DO_NOT_CHECK_TRANSFER_LENGTH  | \
        !           189:                            PD_QUEUED_COMMANDS_EXECUTING     | \
        !           190:                            PD_INITIATE_RECOVERY               \
        !           191:                            )
        !           192: 
        !           193: //
        !           194: // NCR 53c9x specific port driver SRB extension.
        !           195: //
        !           196: 
        !           197: typedef struct _SRB_EXTENSION {
        !           198:     ULONG SrbExtensionFlags;
        !           199:     ULONG SavedDataPointer;
        !           200:     ULONG SavedDataLength;
        !           201:     ULONG MaximumTransferLength;
        !           202: }SRB_EXTENSION, *PSRB_EXTENSION;
        !           203: 
        !           204: #define SRB_EXT(x) ((PSRB_EXTENSION)(x->SrbExtension))
        !           205: 
        !           206: //
        !           207: // NCR 53c9x specific port driver logical unit extension.
        !           208: //
        !           209: 
        !           210: typedef struct _SPECIFIC_LOGICAL_UNIT_EXTENSION {
        !           211:     USHORT LuFlags;
        !           212:     UCHAR RetryCount;
        !           213:     ULONG SavedDataPointer;
        !           214:     ULONG SavedDataLength;
        !           215:     PSCSI_REQUEST_BLOCK ActiveLuRequest;
        !           216:     PSCSI_REQUEST_BLOCK ActiveSendRequest;
        !           217: }SPECIFIC_LOGICAL_UNIT_EXTENSION, *PSPECIFIC_LOGICAL_UNIT_EXTENSION;
        !           218: 
        !           219: //
        !           220: // NCR 53c9x specific per target controller information.
        !           221: //
        !           222: 
        !           223: typedef struct _SPECIFIC_TARGET_EXTENSION {
        !           224:     UCHAR TargetFlags;
        !           225:     UCHAR SynchronousPeriod;
        !           226:     UCHAR SynchronousOffset;
        !           227:     SCSI_CONFIGURATION3 Configuration3;
        !           228: }SPECIFIC_TARGET_EXTENSION, *PSPECIFIC_TARGET_EXTENSION;
        !           229: 
        !           230: //
        !           231: // Define target controller specific flags.
        !           232: //
        !           233: 
        !           234: #define PD_SYNCHRONOUS_NEGOTIATION_DONE    0x0001
        !           235: #define PD_DO_NOT_NEGOTIATE                0x0002
        !           236: 
        !           237: //
        !           238: // NCR 53c9x specific port driver device object extension.
        !           239: //
        !           240: 
        !           241: typedef struct _SPECIFIC_DEVICE_EXTENSION {
        !           242:     ULONG AdapterFlags;
        !           243:     ADAPTER_STATE AdapterState;         // Current state of the adapter
        !           244:     PADAPTER_REGISTERS AdapterBase;     // Address of the NCR 53c9x adapter
        !           245:     PSCSI_REGISTERS Adapter;            // Address of the NCR 53c9x chip
        !           246:     PSCSI_REQUEST_BLOCK ActiveLuRequest;
        !           247:     PSPECIFIC_LOGICAL_UNIT_EXTENSION ActiveLogicalUnit;
        !           248:                                         // Pointer to the acitive request.
        !           249:     PSCSI_REQUEST_BLOCK NextSrbRequest; // Pointer to the next SRB to process.
        !           250:     ULONG ActiveDataPointer;            // SCSI bus active data pointer
        !           251:     ULONG ActiveDataLength;             // The amount of data to be transferred.
        !           252:     LONG InterruptCount;                // Count of interrupts since connection.
        !           253:     SPECIFIC_TARGET_EXTENSION TargetState[SCSI_MAXIMUM_TARGETS];
        !           254:     CHIP_TYPES ChipType;                // Type or version of the chip.
        !           255:     SCSI_STATUS AdapterStatus;          // Saved status register value
        !           256:     SCSI_SEQUENCE_STEP SequenceStep;    // Saved sequence step register value
        !           257:     SCSI_INTERRUPT AdapterInterrupt;    // Saved interrupt status register
        !           258:     SCSI_CONFIGURATION3 Configuration3;
        !           259:     UCHAR AdapterBusId;                 // This adapter's SCSI bus ID
        !           260:     UCHAR AdapterBusIdMask;             // This adapter's SCSI bus ID bit mask
        !           261:     UCHAR ClockSpeed;                   // Chip clock speed in megahetrz.
        !           262:     BOOLEAN InterruptPending;           // Interrupt pending indicator
        !           263:     UCHAR MessageBuffer[MESSAGE_BUFFER_SIZE]; // SCSI bus message buffer
        !           264:     UCHAR MessageCount;                 // Count of bytes in message buffer
        !           265:     UCHAR MessageSent;                  // Count of bytes sent to target
        !           266:     UCHAR TargetId;                     // Saved target id.
        !           267:     UCHAR Lun;                          // Saved lun id.
        !           268:     UCHAR ErrorCount;
        !           269: } SPECIFIC_DEVICE_EXTENSION, *PSPECIFIC_DEVICE_EXTENSION;
        !           270: 
        !           271: 
        !           272: //
        !           273: // Define the synchrouns data transfer parameters structure.
        !           274: //
        !           275: 
        !           276: typedef struct _SYNCHRONOUS_TYPE_PARAMETERS {
        !           277:     UCHAR MaximumPeriodCyles;
        !           278:     UCHAR SynchronousPeriodCyles;
        !           279:     UCHAR InitialRegisterValue;
        !           280: }SYNCHRONOUS_TYPE_PARAMETERS, *PSYNCHRONOUS_TYPE_PARAMETERS;
        !           281: 
        !           282: //
        !           283: // Define the table of synchronous transfer types.
        !           284: //
        !           285: 
        !           286: const SYNCHRONOUS_TYPE_PARAMETERS SynchronousTransferTypes[] = {
        !           287:     {   0,      0,      5},
        !           288:     {   32,     5,      5},
        !           289:     {   32,     8,      7},
        !           290:     {   12,     4,      4}
        !           291: };
        !           292: 
        !           293: //
        !           294: // SCSI Protocol Chip Control read and write macros.
        !           295: //
        !           296: 
        !           297: #ifdef SCSI_READ
        !           298: #undef SCSI_READ
        !           299: #undef SCSI_WRITE
        !           300: #endif
        !           301: 
        !           302: #if defined(DECSTATION)
        !           303: 
        !           304: #define SCSI_READ(ChipAddr, Register) ScsiPortReadRegisterUchar(&((ChipAddr)->ReadRegisters.Register.Byte))
        !           305: 
        !           306: #define SCSI_WRITE(ChipAddr, Register, Value) ScsiPortWriteRegisterUchar(&((ChipAddr)->WriteRegisters.Register.Byte), (Value))
        !           307: 
        !           308: #else
        !           309: 
        !           310: #define SCSI_READ(ChipAddr, Register) ScsiPortReadPortUchar(&((ChipAddr)->ReadRegisters.Register))
        !           311: #define SCSI_WRITE(ChipAddr, Register, Value) (ScsiPortWritePortUchar(&((ChipAddr)->WriteRegisters.Register), (Value)))
        !           312: 
        !           313: #endif
        !           314: 
        !           315: 
        !           316: //
        !           317: // Functions passed to the OS-specific port driver.
        !           318: //
        !           319: 
        !           320: ULONG
        !           321: NcrEisaFindAdapter(
        !           322:     IN PVOID ServiceContext,
        !           323:     IN PVOID Context,
        !           324:     IN PVOID BusInformation,
        !           325:     IN PCHAR ArgumentString,
        !           326:     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
        !           327:     OUT PBOOLEAN Again
        !           328:     );
        !           329: 
        !           330: ULONG
        !           331: NcrMcaFindAdapter(
        !           332:     IN PVOID ServiceContext,
        !           333:     IN PVOID Context,
        !           334:     IN PVOID BusInformation,
        !           335:     IN PCHAR ArgumentString,
        !           336:     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
        !           337:     OUT PBOOLEAN Again
        !           338:     );
        !           339: 
        !           340: ULONG
        !           341: NcrMipsFindAdapter(
        !           342:     IN PVOID ServiceContext,
        !           343:     IN PVOID Context,
        !           344:     IN PVOID BusInformation,
        !           345:     IN PCHAR ArgumentString,
        !           346:     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
        !           347:     OUT PBOOLEAN Again
        !           348:     );
        !           349: 
        !           350: BOOLEAN
        !           351: NcrInitializeAdapter(
        !           352:     IN PVOID ServiceContext
        !           353:     );
        !           354: 
        !           355: BOOLEAN
        !           356: NcrInterruptServiceRoutine(
        !           357:     IN PVOID ServiceContext
        !           358:     );
        !           359: 
        !           360: BOOLEAN
        !           361: NcrResetScsiBus(
        !           362:     IN PVOID ServiceContext,
        !           363:     IN ULONG PathId
        !           364:     );
        !           365: 
        !           366: BOOLEAN
        !           367: NcrStartIo(
        !           368:     IN PVOID ServiceContext,
        !           369:     IN PSCSI_REQUEST_BLOCK Srb
        !           370:     );
        !           371: 
        !           372: VOID
        !           373: NcrStartDataTransfer(
        !           374:     IN PVOID ServiceContext
        !           375:     );
        !           376: 
        !           377: //
        !           378: // NCR 53c9x internal mini-port driver functions.
        !           379: //
        !           380: 
        !           381: VOID
        !           382: NcrAcceptMessage(
        !           383:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           384:     IN BOOLEAN SetAttention,
        !           385:     IN BOOLEAN SetSynchronousParameters
        !           386:     );
        !           387: 
        !           388: VOID
        !           389: NcrCleanupAfterReset(
        !           390:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           391:     IN BOOLEAN ExternalReset
        !           392:     );
        !           393: 
        !           394: VOID
        !           395: NcrCompleteSendMessage(
        !           396:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           397:     IN UCHAR SrbStatus
        !           398:     );
        !           399: 
        !           400: BOOLEAN
        !           401: NcrDecodeSynchronousRequest(
        !           402:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           403:     IN PSPECIFIC_TARGET_EXTENSION TargetState,
        !           404:     IN BOOLEAN ResponseExpected
        !           405:     );
        !           406: 
        !           407: VOID
        !           408: NcrDumpState(
        !           409:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension
        !           410:     );
        !           411: 
        !           412: BOOLEAN
        !           413: NcrMessageDecode(
        !           414:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension
        !           415:     );
        !           416: 
        !           417: VOID
        !           418: NcrLogError(
        !           419:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           420:     IN ULONG ErrorCode,
        !           421:     IN ULONG UniqueCode
        !           422:     );
        !           423: 
        !           424: VOID
        !           425: NcrProcessRequestCompletion(
        !           426:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension
        !           427:     );
        !           428: 
        !           429: VOID
        !           430: NcrResetScsiBusInternal(
        !           431:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           432:     IN ULONG PathId
        !           433:     );
        !           434: 
        !           435: VOID
        !           436: NcrSelectTarget(
        !           437:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           438:     IN PSPECIFIC_LOGICAL_UNIT_EXTENSION LuExtension
        !           439:     );
        !           440: 
        !           441: VOID
        !           442: NcrSendMessage(
        !           443:     IN PSCSI_REQUEST_BLOCK Srb,
        !           444:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           445:     IN PSPECIFIC_LOGICAL_UNIT_EXTENSION LuExtension
        !           446:     );
        !           447: 
        !           448: VOID
        !           449: NcrStartExecution(
        !           450:     PSCSI_REQUEST_BLOCK Srb,
        !           451:     PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           452:     PSPECIFIC_LOGICAL_UNIT_EXTENSION LuExtension
        !           453:     );
        !           454: 
        !           455: 
        !           456: VOID
        !           457: NcrAcceptMessage(
        !           458:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           459:     IN BOOLEAN SetAttention,
        !           460:     IN BOOLEAN SetSynchronousParameters
        !           461:     )
        !           462: /*++
        !           463: 
        !           464: Routine Description:
        !           465: 
        !           466:     This procedure tells the adapter to accept a pending message on the SCSI
        !           467:     bus.  Optionally, it will set the synchronous transfer parameters and the
        !           468:     attention signal.
        !           469: 
        !           470: Arguments:
        !           471: 
        !           472:     DeviceExtension - Supplies a pointer to the device extension.
        !           473: 
        !           474:     SetAttention - Indicates the attention line on the SCSI bus should be set.
        !           475: 
        !           476:     SetSynchronousParameters - Indicates the synchronous data transfer
        !           477:         parameters should be set.
        !           478: 
        !           479: Return Value:
        !           480: 
        !           481:     None.
        !           482: 
        !           483: --*/
        !           484: 
        !           485: {
        !           486: 
        !           487:     PSPECIFIC_TARGET_EXTENSION targetState;
        !           488: 
        !           489:     //
        !           490:     // Check to see if the synchonous data transfer parameters need to be set.
        !           491:     //
        !           492: 
        !           493:     if (SetSynchronousParameters) {
        !           494: 
        !           495:         //
        !           496:         // These must be set before a data transfer is started.
        !           497:         //
        !           498: 
        !           499:         targetState = &DeviceExtension->TargetState[DeviceExtension->TargetId];
        !           500: 
        !           501:         SCSI_WRITE( DeviceExtension->Adapter,
        !           502:                     SynchronousPeriod,
        !           503:                     targetState->SynchronousPeriod
        !           504:                     );
        !           505:         SCSI_WRITE( DeviceExtension->Adapter,
        !           506:                     SynchronousOffset,
        !           507:                     targetState->SynchronousOffset
        !           508:                     );
        !           509:         SCSI_WRITE( DeviceExtension->Adapter,
        !           510:                     Configuration3,
        !           511:                     *((PUCHAR) &targetState->Configuration3)
        !           512:                     );
        !           513:     }
        !           514: 
        !           515:     //
        !           516:     // Check to see if the attention signal needs to be set.
        !           517:     //
        !           518: 
        !           519:     if (SetAttention) {
        !           520: 
        !           521:         //
        !           522:         // This requests that the target enter the message-out phase.
        !           523:         //
        !           524: 
        !           525:         SCSI_WRITE( DeviceExtension->Adapter, Command, SET_ATTENTION );
        !           526:     }
        !           527: 
        !           528:     //
        !           529:     // Indicate to the adapter that the message-in phase may now be completed.
        !           530:     //
        !           531: 
        !           532:     SCSI_WRITE(DeviceExtension->Adapter, Command, MESSAGE_ACCEPTED);
        !           533: }
        !           534: 
        !           535: 
        !           536: VOID
        !           537: NcrCleanupAfterReset(
        !           538:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           539:     IN BOOLEAN ExternalReset
        !           540:     )
        !           541: 
        !           542: /*++
        !           543: 
        !           544: Routine Description:
        !           545: 
        !           546:     This routine cleans up the adapter-specific
        !           547:     and logical-unit-specific data structures.  Any active requests are
        !           548:     completed and the synchronous negotiation flags are cleared.
        !           549: 
        !           550: Arguments:
        !           551: 
        !           552:     DeviceExtension - Supplies a pointer to device extension for the bus that
        !           553:         was reset.
        !           554: 
        !           555:     ExternalReset - When set, indicates that the reset was generated by a
        !           556:         SCSI device other than this host adapter.
        !           557: 
        !           558: Return Value:
        !           559: 
        !           560:     None.
        !           561: 
        !           562: --*/
        !           563: 
        !           564: {
        !           565:     UCHAR pathId = 0;
        !           566:     UCHAR targetId;
        !           567:     UCHAR luId;
        !           568:     PSPECIFIC_LOGICAL_UNIT_EXTENSION luExtension;
        !           569:     PSPECIFIC_TARGET_EXTENSION targetState;
        !           570: 
        !           571:     //
        !           572:     // Check to see if a data transfer was in progress, if so, flush the DMA.
        !           573:     //
        !           574: 
        !           575:     if (DeviceExtension->AdapterState == DataTransfer) {
        !           576: 
        !           577:         SCSI_WRITE(DeviceExtension->Adapter, Command, FLUSH_FIFO);
        !           578:         ScsiPortFlushDma(DeviceExtension);
        !           579: 
        !           580:     }
        !           581: 
        !           582:     //
        !           583:     // if the current state is AttemptingSelect then SCSI port driver needs
        !           584:     // to be notified that new requests can be sent.
        !           585:     //
        !           586: 
        !           587:     if (DeviceExtension->AdapterFlags & PD_PENDING_START_IO) {
        !           588: 
        !           589:         //
        !           590:         // Ask for another request and clear the pending one.  The pending
        !           591:         // request will be processed when the request of the active requests
        !           592:         // are returned.
        !           593: 
        !           594:         DeviceExtension->NextSrbRequest = NULL;
        !           595:         DeviceExtension->AdapterFlags &= ~PD_PENDING_START_IO;
        !           596: 
        !           597:         ScsiPortNotification( NextRequest, DeviceExtension, NULL );
        !           598: 
        !           599:     }
        !           600: 
        !           601:     //
        !           602:     // If there was an active request, then complete it with
        !           603:     // SRB_STATUS_PHASE_SEQUENCE_FAILURE so the class driver will know not
        !           604:     // to retry it too many times.
        !           605:     //
        !           606: 
        !           607:     if (DeviceExtension->ActiveLuRequest != NULL) {
        !           608: 
        !           609:         //
        !           610:         // Set the SrbStatus in the SRB, complete the request and
        !           611:         // clear the active pointers
        !           612:         //
        !           613: 
        !           614:         luExtension = DeviceExtension->ActiveLogicalUnit;
        !           615: 
        !           616:         DeviceExtension->ActiveLuRequest->SrbStatus =
        !           617:             SRB_STATUS_PHASE_SEQUENCE_FAILURE;
        !           618: 
        !           619:         targetState = &DeviceExtension->TargetState[DeviceExtension->TargetId];
        !           620: 
        !           621:         ScsiPortNotification(
        !           622:             RequestComplete,
        !           623:             DeviceExtension,
        !           624:             DeviceExtension->ActiveLuRequest
        !           625:             );
        !           626: 
        !           627:         //
        !           628:         // Check to see if there was a synchronous negotiation in progress.  If
        !           629:         // there was then do not try to negotiate with this target again.
        !           630:         //
        !           631: 
        !           632:         if (DeviceExtension->AdapterFlags & (PD_SYNCHRONOUS_RESPONSE_SENT |
        !           633:             PD_SYNCHRONOUS_TRANSFER_SENT)) {
        !           634: 
        !           635:             //
        !           636:             // This target cannot negotiate properly.  Set a flag to prevent
        !           637:             // further attempts and set the synchronous parameters to use
        !           638:             // asynchronous data transfer.
        !           639:             //
        !           640: 
        !           641:             targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE;
        !           642:             targetState->SynchronousOffset = ASYNCHRONOUS_OFFSET;
        !           643:             targetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD;
        !           644:             targetState->Configuration3.FastScsi = 0;
        !           645: 
        !           646:         }
        !           647: 
        !           648:         luExtension->ActiveLuRequest = NULL;
        !           649:         luExtension->RetryCount  = 0;
        !           650:         DeviceExtension->ActiveLogicalUnit = NULL;
        !           651:         DeviceExtension->ActiveLuRequest = NULL;
        !           652:     }
        !           653: 
        !           654:     //
        !           655:     // Clear the appropriate state flags as well as the next request.
        !           656:     // The request will actually be cleared when the logical units are processed.
        !           657:     // Note that it is not necessary to fail the request waiting to be started
        !           658:     // since it will be processed properly by the target controller, but it
        !           659:     // is cleared anyway.
        !           660:     //
        !           661: 
        !           662:     for (targetId = 0; targetId < SCSI_MAXIMUM_TARGETS; targetId++) {
        !           663: 
        !           664:         //
        !           665:         // Loop through each of the possible logical units for this target.
        !           666:         //
        !           667: 
        !           668:         //
        !           669:         // Clear the synchronous negotiation flage for the target controller.
        !           670:         //
        !           671: 
        !           672:         DeviceExtension->TargetState[targetId].TargetFlags &=
        !           673:             ~PD_SYNCHRONOUS_NEGOTIATION_DONE;
        !           674: 
        !           675:         for (luId = 0; luId < SCSI_MAXIMUM_LOGICAL_UNITS; luId++) {
        !           676: 
        !           677:             luExtension = ScsiPortGetLogicalUnit( DeviceExtension,
        !           678:                                                           pathId,
        !           679:                                                           targetId,
        !           680:                                                           luId
        !           681:                                                           );
        !           682: 
        !           683:             if (luExtension == NULL) {
        !           684:                 continue;
        !           685:             }
        !           686: 
        !           687:             ScsiPortCompleteRequest(
        !           688:                 DeviceExtension,
        !           689:                 pathId,
        !           690:                 targetId,
        !           691:                 luId,
        !           692:                 SRB_STATUS_BUS_RESET
        !           693:                 );
        !           694: 
        !           695:             luExtension->ActiveLuRequest = NULL;
        !           696: 
        !           697:             if (luExtension->ActiveSendRequest != NULL) {
        !           698: 
        !           699:                 //
        !           700:                 // Set the SrbStatus in the SRB, complete the request and
        !           701:                 // clear the active pointers
        !           702:                 //
        !           703: 
        !           704:                 luExtension->ActiveSendRequest->SrbStatus =
        !           705:                     SRB_STATUS_BUS_RESET;
        !           706: 
        !           707:                 //
        !           708:                 // Complete the request.
        !           709:                 //
        !           710: 
        !           711:                 ScsiPortNotification(
        !           712:                     RequestComplete,
        !           713:                     DeviceExtension,
        !           714:                     luExtension->ActiveSendRequest
        !           715:                     );
        !           716: 
        !           717:                 luExtension->ActiveSendRequest = NULL;
        !           718: 
        !           719:             }
        !           720: 
        !           721:             //
        !           722:             // Clear the necessary logical unit flags.
        !           723:             //
        !           724: 
        !           725:             luExtension->LuFlags &= ~PD_LU_RESET_MASK;
        !           726: 
        !           727:         } /* for luId */
        !           728:     } /* for targetId */
        !           729: 
        !           730:     //
        !           731:     // Clear the adapter flags and set the bus state to free.
        !           732:     //
        !           733: 
        !           734:     DeviceExtension->AdapterState = BusFree;
        !           735:     DeviceExtension->AdapterFlags &= ~PD_ADAPTER_RESET_MASK;
        !           736: 
        !           737: }
        !           738: 
        !           739: VOID
        !           740: NcrCompleteSendMessage(
        !           741:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !           742:     IN UCHAR SrbStatus
        !           743:     )
        !           744: /*++
        !           745: 
        !           746: Routine Description:
        !           747: 
        !           748:     This function does the cleanup necessary to complete a send-message request.
        !           749:     This includes completing any affected execute-I/O requests and cleaning
        !           750:     up the device extension state.
        !           751: 
        !           752: Arguments:
        !           753: 
        !           754:     DeviceExtension - Supplies a pointer to the device extension of the SCSI bus
        !           755:         adapter.  The active logical unit is stored in ActiveLogicalUnit.
        !           756: 
        !           757:     SrbStatus - Indicates the status that the request should be completeted with
        !           758:         if the request did not complete normally, then any active execute
        !           759:         requests are not considered to have been affected.
        !           760: 
        !           761: Return Value:
        !           762: 
        !           763:     None.
        !           764: 
        !           765: --*/
        !           766: 
        !           767: {
        !           768:     PSPECIFIC_LOGICAL_UNIT_EXTENSION luExtension;
        !           769:     PSCSI_REQUEST_BLOCK srb;
        !           770:     PSCSI_REQUEST_BLOCK srbAbort;
        !           771:     UCHAR pathId = 0;
        !           772:     UCHAR targetId;
        !           773:     UCHAR luId;
        !           774: 
        !           775:     luExtension = DeviceExtension->ActiveLogicalUnit;
        !           776:     srb = luExtension->ActiveSendRequest;
        !           777: 
        !           778:     //
        !           779:     // Clean up any EXECUTE requests which may have been affected by this
        !           780:     // message.
        !           781:     //
        !           782: 
        !           783:     if (SrbStatus == SRB_STATUS_SUCCESS) {
        !           784:         switch (srb->Function) {
        !           785:         case SRB_FUNCTION_ABORT_COMMAND:
        !           786: 
        !           787:             //
        !           788:             // Make sure there is still a request to complete.  If so complete
        !           789:             // it with an SRB_STATUS_ABORTED status.
        !           790:             //
        !           791: 
        !           792:             srbAbort = ScsiPortGetSrb(
        !           793:                 DeviceExtension,
        !           794:                 srb->PathId,
        !           795:                 srb->TargetId,
        !           796:                 srb->Lun,
        !           797:                 srb->QueueTag
        !           798:                 );
        !           799: 
        !           800:             if (srbAbort != srb->NextSrb) {
        !           801: 
        !           802:                 //
        !           803:                 // If there is no request, then fail the abort.
        !           804:                 //
        !           805: 
        !           806:                 SrbStatus = SRB_STATUS_ABORT_FAILED;
        !           807:                 break;
        !           808:             }
        !           809: 
        !           810:             srbAbort->SrbStatus = SRB_STATUS_ABORTED;
        !           811: 
        !           812:             ScsiPortNotification(
        !           813:                 RequestComplete,
        !           814:                 DeviceExtension,
        !           815:                 srbAbort
        !           816:                 );
        !           817: 
        !           818:             if (DeviceExtension->ActiveLuRequest == srbAbort) {
        !           819: 
        !           820:                 DeviceExtension->ActiveLuRequest = NULL;
        !           821:             }
        !           822: 
        !           823:             luExtension->ActiveLuRequest = NULL;
        !           824:             luExtension->LuFlags &= ~PD_LU_COMPLETE_MASK;
        !           825:             luExtension->RetryCount = 0;
        !           826: 
        !           827:             break;
        !           828: 
        !           829:         case SRB_FUNCTION_RESET_DEVICE:
        !           830: 
        !           831:             //
        !           832:             // Cycle through each of the possible logical units looking
        !           833:             // for requests which have been cleared by the target reset.
        !           834:             //
        !           835: 
        !           836:             targetId = srb->TargetId;
        !           837:             DeviceExtension->TargetState[targetId].TargetFlags &=
        !           838:                 ~PD_SYNCHRONOUS_NEGOTIATION_DONE;
        !           839: 
        !           840:             for (luId = 0; luId < SCSI_MAXIMUM_LOGICAL_UNITS; luId) {
        !           841: 
        !           842:                 luExtension = ScsiPortGetLogicalUnit( DeviceExtension,
        !           843:                                                       pathId,
        !           844:                                                       targetId,
        !           845:                                                       luId
        !           846:                                                       );
        !           847: 
        !           848:                 if (luExtension == NULL) {
        !           849:                     continue;
        !           850:                 }
        !           851: 
        !           852:                 ScsiPortCompleteRequest(
        !           853:                     DeviceExtension,
        !           854:                     pathId,
        !           855:                     targetId,
        !           856:                     luId,
        !           857:                     SRB_STATUS_BUS_RESET
        !           858:                     );
        !           859: 
        !           860:                 luExtension->ActiveLuRequest = NULL;
        !           861:                 luExtension->RetryCount = 0;
        !           862: 
        !           863:                 //
        !           864:                 // Clear the necessary logical unit flags.
        !           865:                 //
        !           866: 
        !           867:                 luExtension->LuFlags &= ~PD_LU_RESET_MASK;
        !           868: 
        !           869:             } /* for luId */
        !           870: 
        !           871:         /* TODO: Handle CLEAR QUEUE */
        !           872:         }
        !           873:     } else {
        !           874: 
        !           875:         //
        !           876:         // If an abort request fails then complete target of the abort;
        !           877:         // otherwise the target of the ABORT may never be compileted.
        !           878:         //
        !           879: 
        !           880:         if (srb->Function == SRB_FUNCTION_ABORT_COMMAND) {
        !           881: 
        !           882:             //
        !           883:             // Make sure there is still a request to complete.  If so
        !           884:             // it with an SRB_STATUS_ABORTED status.
        !           885:             //
        !           886: 
        !           887:             srbAbort = ScsiPortGetSrb(
        !           888:                 DeviceExtension,
        !           889:                 srb->PathId,
        !           890:                 srb->TargetId,
        !           891:                 srb->Lun,
        !           892:                 srb->QueueTag
        !           893:                 );
        !           894: 
        !           895:             if (srbAbort == srb->NextSrb) {
        !           896: 
        !           897:                 srbAbort->SrbStatus = SRB_STATUS_ABORTED;
        !           898: 
        !           899:                 ScsiPortNotification(
        !           900:                     RequestComplete,
        !           901:                     DeviceExtension,
        !           902:                     srbAbort
        !           903:                     );
        !           904: 
        !           905:                 luExtension->ActiveLuRequest = NULL;
        !           906:                 luExtension->LuFlags &= ~PD_LU_COMPLETE_MASK;
        !           907:                 luExtension->RetryCount  = 0;
        !           908: 
        !           909:             }
        !           910:         }
        !           911: 
        !           912:     }
        !           913: 
        !           914:     //
        !           915:     // Complete the actual send-message request.
        !           916:     //
        !           917: 
        !           918:     srb->SrbStatus = SrbStatus;
        !           919:     ScsiPortNotification(
        !           920:         RequestComplete,
        !           921:         DeviceExtension,
        !           922:         srb
        !           923:         );
        !           924: 
        !           925:     //
        !           926:     // Clear the active send request and PD_SEND_MESSAGE_REQUEST flag.
        !           927:     //
        !           928: 
        !           929:     luExtension->RetryCount = 0;
        !           930:     luExtension->ActiveSendRequest = NULL;
        !           931:     DeviceExtension->AdapterFlags &= ~PD_SEND_MESSAGE_REQUEST;
        !           932: }
        !           933: 
        !           934: BOOLEAN
        !           935: NcrMessageDecode(
        !           936:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension
        !           937:     )
        !           938: /*++
        !           939: 
        !           940: Routine Description:
        !           941: 
        !           942:     This function decodes the SCSI bus message-in the device extension message
        !           943:     buffer.  After the message is decoded it decides what action to take in
        !           944:     response to the message.  If an outgoing message needs to be sent, then
        !           945:     it is placed in the message buffer and TRUE is returned. If the message
        !           946:     is acceptable, then the device state is set either to DisconnectExpected or
        !           947:     MessageAccepted and the MessageCount is reset to 0.
        !           948: 
        !           949:     Some messages are made up of several bytes.  This funtion will simply
        !           950:     return false when an incomplete message is detected, allowing the target
        !           951:     to send the rest of the message.  The message count is left unchanged.
        !           952: 
        !           953: Arguments:
        !           954: 
        !           955:     DeviceExtension - Supplies a pointer to the specific device extension.
        !           956: 
        !           957: Return Value:
        !           958: 
        !           959:     TRUE - Returns true if there is a reponse message to be sent.
        !           960: 
        !           961:     FALSE - If there is no response message.
        !           962: 
        !           963: --*/
        !           964: 
        !           965: {
        !           966:     PSCSI_REQUEST_BLOCK srb;
        !           967:     PSPECIFIC_LOGICAL_UNIT_EXTENSION luExtension;
        !           968:     LONG offset;
        !           969:     PSPECIFIC_TARGET_EXTENSION targetState;
        !           970:     LONG i;
        !           971:     ULONG savedAdapterFlags;
        !           972:     PSCSI_EXTENDED_MESSAGE extendedMessage;
        !           973: 
        !           974:     //
        !           975:     // NOTE:  The ActivelogicalUnit field could be invalid if the
        !           976:     // PD_DISCONNECT_EXPECTED flag is set, so luExtension cannot
        !           977:     // be used until this flag has been checked.
        !           978:     //
        !           979: 
        !           980:     luExtension = DeviceExtension->ActiveLogicalUnit;
        !           981:     savedAdapterFlags = DeviceExtension->AdapterFlags;
        !           982:     srb = DeviceExtension->ActiveLuRequest;
        !           983:     targetState = &DeviceExtension->TargetState[DeviceExtension->TargetId];
        !           984: 
        !           985:     //
        !           986:     // If a queue message is expected then it must be the first message byte.
        !           987:     //
        !           988: 
        !           989:     if (DeviceExtension->AdapterFlags & PD_EXPECTING_QUEUE_TAG &&
        !           990:         DeviceExtension->MessageBuffer[0] != SRB_SIMPLE_TAG_REQUEST) {
        !           991: 
        !           992:         NcrPrint((1, "NcrMessageDecode: Unexpected message recieved when que tag expected.\n"));
        !           993: 
        !           994:         //
        !           995:         // The target did not reselect correctly Send a
        !           996:         // message reject of this message.
        !           997:         //
        !           998: 
        !           999:         DeviceExtension->MessageCount = 1;
        !          1000:         DeviceExtension->MessageSent = 0;
        !          1001:         DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1002:         DeviceExtension->AdapterState = MessageOut;
        !          1003: 
        !          1004:         return(TRUE);
        !          1005:     }
        !          1006: 
        !          1007:     //
        !          1008:     // A number of special cases must be handled if a special message has
        !          1009:     // just been sent.  These special messages are synchronous negotiations
        !          1010:     // or a messages which implie a disconnect.  The special cases are:
        !          1011:     //
        !          1012:     // If a disconnect is expected because of a send-message request,
        !          1013:     // then the only valid message-in is a MESSAGE REJECT; other messages
        !          1014:     // are a protocol error and are rejected.
        !          1015:     //
        !          1016:     // If a synchronous negotiation response was just sent and the message
        !          1017:     // in was not a MESSAGE REJECT, then the negotiation has been accepted.
        !          1018:     //
        !          1019:     // If a synchronous negotiation request was just sent, then valid responses
        !          1020:     // are a MESSAGE REJECT or an extended synchronous message back.
        !          1021:     //
        !          1022: 
        !          1023:     if (DeviceExtension->AdapterFlags & (PD_SYNCHRONOUS_RESPONSE_SENT |
        !          1024:         PD_DISCONNECT_EXPECTED | PD_SYNCHRONOUS_TRANSFER_SENT)) {
        !          1025: 
        !          1026:         if (DeviceExtension->AdapterFlags & PD_DISCONNECT_EXPECTED &&
        !          1027:             DeviceExtension->MessageBuffer[0] != SCSIMESS_MESSAGE_REJECT) {
        !          1028: 
        !          1029:             //
        !          1030:             // The target is not responding correctly to the message.  Send a
        !          1031:             // message reject of this message.
        !          1032:             //
        !          1033: 
        !          1034:             DeviceExtension->MessageCount = 1;
        !          1035:             DeviceExtension->MessageSent = 0;
        !          1036:             DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1037:             DeviceExtension->AdapterState = MessageOut;
        !          1038: 
        !          1039:             return(TRUE);
        !          1040:         }
        !          1041: 
        !          1042:         if (DeviceExtension->AdapterFlags & PD_SYNCHRONOUS_RESPONSE_SENT &&
        !          1043:             DeviceExtension->MessageBuffer[0] != SCSIMESS_MESSAGE_REJECT) {
        !          1044: 
        !          1045:             //
        !          1046:             // The target did not reject our response so the synchronous
        !          1047:             // transfer negotiation is done.  Clear the adapter flags and
        !          1048:             // set the logical unit flags indicating this. Continue processing
        !          1049:             // the message which is unrelated to negotiation.
        !          1050:             //
        !          1051: 
        !          1052:             DeviceExtension->AdapterFlags &= ~PD_SYNCHRONOUS_RESPONSE_SENT;
        !          1053:             targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE;
        !          1054:         }
        !          1055: 
        !          1056:         //
        !          1057:         // Save the adapter flags for later use.
        !          1058:         //
        !          1059: 
        !          1060:         savedAdapterFlags = DeviceExtension->AdapterFlags;
        !          1061: 
        !          1062:         if (DeviceExtension->AdapterFlags & PD_SYNCHRONOUS_TRANSFER_SENT ) {
        !          1063: 
        !          1064:             //
        !          1065:             // The target is sending a message after a synchronous transfer
        !          1066:             // request was sent.  Valid responses are a MESSAGE REJECT or an
        !          1067:             // extended synchronous message; any other message negates the
        !          1068:             // fact that a negotiation was started.  However, since extended
        !          1069:             // messages are multi-byte, it is difficult to determine what the
        !          1070:             // incoming message is.  So at this point, the fact that a
        !          1071:             // sychronous transfer was sent will be saved and cleared from the
        !          1072:             // AdapterFlags.  If the message looks like a synchronous transfer
        !          1073:             // request, then restore this fact back into the AdapterFlags. If
        !          1074:             // the complete message is not the one expected, then opening
        !          1075:             // negotiation will be forgotten. This is an error by the target,
        !          1076:             // but minor so nothing will be done about it.  Finally, to prevent
        !          1077:             // this cycle from reoccurring on the next request indicate that
        !          1078:             // the negotiation is done.
        !          1079:             //
        !          1080: 
        !          1081:             DeviceExtension->AdapterFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT;
        !          1082:             targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE;
        !          1083:         }
        !          1084: 
        !          1085:     }
        !          1086: 
        !          1087:     switch (DeviceExtension->MessageBuffer[0]) {
        !          1088:     case SCSIMESS_COMMAND_COMPLETE:
        !          1089: 
        !          1090:         //
        !          1091:         // For better or worse the command is complete.  Process request which
        !          1092:         // set the SrbStatus and clean up the device and logical unit states.
        !          1093:         //
        !          1094: 
        !          1095:         NcrProcessRequestCompletion(DeviceExtension);
        !          1096: 
        !          1097:         //
        !          1098:         // Complete the request.
        !          1099:         //
        !          1100: 
        !          1101:         ScsiPortNotification(
        !          1102:             RequestComplete,
        !          1103:             DeviceExtension,
        !          1104:             srb
        !          1105:             );
        !          1106: 
        !          1107:         //
        !          1108:         // Everything is ok with the message so do not send one and set the
        !          1109:         // state to DisconnectExpected.
        !          1110:         //
        !          1111: 
        !          1112:         DeviceExtension->AdapterState = DisconnectExpected;
        !          1113:         DeviceExtension->MessageCount = 0;
        !          1114:         return(FALSE);
        !          1115: 
        !          1116:     case SCSIMESS_DISCONNECT:
        !          1117: 
        !          1118:         //
        !          1119:         // The target wants to disconnect.  Set the state to DisconnectExpected,
        !          1120:         // and do not request a message-out.
        !          1121:         //
        !          1122: 
        !          1123:         DeviceExtension->AdapterState = DisconnectExpected;
        !          1124:         DeviceExtension->MessageCount = 0;
        !          1125:         return(FALSE);
        !          1126: 
        !          1127:     case SCSIMESS_EXTENDED_MESSAGE:
        !          1128: 
        !          1129:         //
        !          1130:         // The format of an extended message is:
        !          1131:         //    Extended Message Code
        !          1132:         //    Length of Message
        !          1133:         //    Extended Message Type
        !          1134:         //            .
        !          1135:         //            .
        !          1136:         //
        !          1137:         // Until the entire message has been read in, just keep getting bytes
        !          1138:         // from the target, making sure that the message buffer is not
        !          1139:         // overrun.
        !          1140:         //
        !          1141: 
        !          1142:         extendedMessage = (PSCSI_EXTENDED_MESSAGE)
        !          1143:             DeviceExtension->MessageBuffer;
        !          1144: 
        !          1145:         if (DeviceExtension->MessageCount < 2 ||
        !          1146:             (DeviceExtension->MessageCount < MESSAGE_BUFFER_SIZE &&
        !          1147:             DeviceExtension->MessageCount < extendedMessage->MessageLength + 2)
        !          1148:             ) {
        !          1149: 
        !          1150:             //
        !          1151:             // Update the state and return; also restore the AdapterFlags.
        !          1152:             //
        !          1153: 
        !          1154:             DeviceExtension->AdapterFlags = savedAdapterFlags;
        !          1155:             DeviceExtension->AdapterState = MessageAccepted;
        !          1156:             return(FALSE);
        !          1157: 
        !          1158:         }
        !          1159: 
        !          1160:         //
        !          1161:         // Make sure the length includes an extended op-code.
        !          1162:         //
        !          1163: 
        !          1164:         if (DeviceExtension->MessageCount < 3) {
        !          1165: 
        !          1166:             //
        !          1167:             // This is an illegal extended message. Send a MESSAGE_REJECT.
        !          1168:             //
        !          1169: 
        !          1170:             DeviceExtension->MessageCount = 1;
        !          1171:             DeviceExtension->MessageSent = 0;
        !          1172:             DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1173:             DeviceExtension->AdapterState = MessageOut;
        !          1174: 
        !          1175:             return(TRUE);
        !          1176:         }
        !          1177: 
        !          1178:         //
        !          1179:         // Determine the extended message type.
        !          1180:         //
        !          1181: 
        !          1182:         switch (extendedMessage->MessageType) {
        !          1183:         case SCSIMESS_MODIFY_DATA_POINTER:
        !          1184: 
        !          1185:             //
        !          1186:             // Verify the message length.
        !          1187:             //
        !          1188: 
        !          1189:             if (extendedMessage->MessageLength != SCSIMESS_MODIFY_DATA_LENGTH) {
        !          1190: 
        !          1191:                 //
        !          1192:                 // Reject the message.
        !          1193:                 //
        !          1194: 
        !          1195:                 DeviceExtension->MessageCount = 1;
        !          1196:                 DeviceExtension->MessageSent = 0;
        !          1197:                 DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1198:                 DeviceExtension->AdapterState = MessageOut;
        !          1199: 
        !          1200:                 return(TRUE);
        !          1201:             }
        !          1202: 
        !          1203:             //
        !          1204:             // Calculate the modification to be added to the data pointer.
        !          1205:             //
        !          1206: 
        !          1207:             offset = 0;
        !          1208:             for (i = 0; i < 4; i++) {
        !          1209:                 offset << 8;
        !          1210:                 offset += extendedMessage->ExtendedArguments.Modify.Modifier[i];
        !          1211:             }
        !          1212: 
        !          1213:             //
        !          1214:             // Verify that the new data pointer is still within the range
        !          1215:             // of the buffer.
        !          1216:             //
        !          1217: 
        !          1218:             if (DeviceExtension->ActiveDataLength - offset >
        !          1219:                 srb->DataTransferLength ||
        !          1220:                 ((LONG) DeviceExtension->ActiveDataLength - offset) < 0 ) {
        !          1221: 
        !          1222:                 //
        !          1223:                 // The new pointer is not valid, so reject the message.
        !          1224:                 //
        !          1225: 
        !          1226:                 DeviceExtension->MessageCount = 1;
        !          1227:                 DeviceExtension->MessageSent = 0;
        !          1228:                 DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1229:                 DeviceExtension->AdapterState = MessageOut;
        !          1230: 
        !          1231:                 return(TRUE);
        !          1232:             }
        !          1233: 
        !          1234:             //
        !          1235:             // Everything has checked out, so update the pointer.
        !          1236:             //
        !          1237: 
        !          1238:             DeviceExtension->ActiveDataPointer += offset;
        !          1239:             DeviceExtension->ActiveDataLength -= offset;
        !          1240: 
        !          1241:             //
        !          1242:             // Everything is ok, so accept the message as is.
        !          1243:             //
        !          1244: 
        !          1245:             DeviceExtension->MessageCount = 0;
        !          1246:             DeviceExtension->AdapterState = MessageAccepted;
        !          1247:             return(FALSE);
        !          1248: 
        !          1249:         case SCSIMESS_SYNCHRONOUS_DATA_REQ:
        !          1250: 
        !          1251:             //
        !          1252:             // A SYNCHRONOUS DATA TRANSFER REQUEST message was received.
        !          1253:             // Make sure the length is correct.
        !          1254:             //
        !          1255: 
        !          1256:             if ( extendedMessage->MessageLength !=
        !          1257:                 SCSIMESS_SYNCH_DATA_LENGTH) {
        !          1258: 
        !          1259:                 //
        !          1260:                 // The length is invalid, so reject the message.
        !          1261:                 //
        !          1262: 
        !          1263:                 DeviceExtension->MessageCount = 1;
        !          1264:                 DeviceExtension->MessageSent = 0;
        !          1265:                 DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1266:                 DeviceExtension->AdapterState = MessageOut;
        !          1267:                 return(TRUE);
        !          1268:             }
        !          1269: 
        !          1270:             //
        !          1271:             // If synchrouns negotiation has been disabled for this request,
        !          1272:             // then reject any synchronous messages; however, when synchronous
        !          1273:             // transfers are allowed then a new attempt can be made.
        !          1274:             //
        !          1275: 
        !          1276:             if (srb != NULL &&
        !          1277:                 !(savedAdapterFlags & PD_SYNCHRONOUS_TRANSFER_SENT) &&
        !          1278:                 srb->SrbFlags & SRB_FLAGS_DISABLE_SYNCH_TRANSFER) {
        !          1279: 
        !          1280:                 //
        !          1281:                 // Reject the synchronous transfer message since synchonrous
        !          1282:                 // transfers are not desired at this time.
        !          1283:                 //
        !          1284: 
        !          1285:                 DeviceExtension->MessageCount = 1;
        !          1286:                 DeviceExtension->MessageSent = 0;
        !          1287:                 DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1288:                 DeviceExtension->AdapterState = MessageOut;
        !          1289:                 return(TRUE);
        !          1290: 
        !          1291:             }
        !          1292: 
        !          1293:             //
        !          1294:             // Call NcrDecodeSynchronousMessage to decode the message and
        !          1295:             // formulate a response if necessary.
        !          1296:             // NcrDecodeSynchronousRequest will return FALSE if the
        !          1297:             // message is not accepable and should be rejected.
        !          1298:             //
        !          1299: 
        !          1300:             if (!NcrDecodeSynchronousRequest(
        !          1301:                 DeviceExtension,
        !          1302:                 targetState,
        !          1303:                 !(savedAdapterFlags & PD_SYNCHRONOUS_TRANSFER_SENT)
        !          1304:                 )) {
        !          1305: 
        !          1306:                 //
        !          1307:                 // Indicate that a negotiation has been done in the logical
        !          1308:                 // unit and clear the negotiation flags.
        !          1309:                 //
        !          1310: 
        !          1311:                 targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE;
        !          1312: 
        !          1313:                 DeviceExtension->AdapterFlags &=
        !          1314:                     ~(PD_SYNCHRONOUS_RESPONSE_SENT|
        !          1315:                     PD_SYNCHRONOUS_TRANSFER_SENT);
        !          1316: 
        !          1317:                 //
        !          1318:                 // The message was not acceptable so send a MESSAGE_REJECT.
        !          1319:                 //
        !          1320: 
        !          1321:                 DeviceExtension->MessageCount = 1;
        !          1322:                 DeviceExtension->MessageSent = 0;
        !          1323:                 DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1324:                 DeviceExtension->AdapterState = MessageOut;
        !          1325:                 return(TRUE);
        !          1326:             }
        !          1327: 
        !          1328:             //
        !          1329:             // If a reponse was expected, then set the state for a message-out.
        !          1330:             // Otherwise, NcrDecodeSynchronousRequest has put a reponse
        !          1331:             // in the message buffer to be returned to the target.
        !          1332:             //
        !          1333: 
        !          1334:             if (savedAdapterFlags & PD_SYNCHRONOUS_TRANSFER_SENT){
        !          1335: 
        !          1336:                 //
        !          1337:                 // We initiated the negotiation, so no response is necessary.
        !          1338:                 //
        !          1339: 
        !          1340:                 DeviceExtension->AdapterState = MessageAccepted;
        !          1341:                 DeviceExtension->AdapterFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT;
        !          1342:                 targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE;
        !          1343:                 DeviceExtension->MessageCount = 0;
        !          1344:                 return(FALSE);
        !          1345:             }
        !          1346: 
        !          1347:             //
        !          1348:             // Set up the state to send the reponse.  The message count is
        !          1349:             // still correct.
        !          1350:             //
        !          1351: 
        !          1352:             DeviceExtension->MessageSent = 0;
        !          1353:             DeviceExtension->AdapterState = MessageOut;
        !          1354:             DeviceExtension->AdapterFlags &= ~PD_SYNCHRONOUS_TRANSFER_SENT;
        !          1355:             DeviceExtension->AdapterFlags |= PD_SYNCHRONOUS_RESPONSE_SENT;
        !          1356:             return(TRUE);
        !          1357: 
        !          1358:         case SCSIMESS_WIDE_DATA_REQUEST:
        !          1359: 
        !          1360:             //
        !          1361:             // A WIDE DATA TRANSFER REQUEST message was received.
        !          1362:             // Make sure the length is correct.
        !          1363:             //
        !          1364: 
        !          1365:             if ( extendedMessage->MessageLength !=
        !          1366:                 SCSIMESS_WIDE_DATA_LENGTH) {
        !          1367: 
        !          1368:                 //
        !          1369:                 // The length is invalid reject the message.
        !          1370:                 //
        !          1371: 
        !          1372:                 DeviceExtension->MessageCount = 1;
        !          1373:                 DeviceExtension->MessageSent = 0;
        !          1374:                 DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1375:                 DeviceExtension->AdapterState = MessageOut;
        !          1376:                 return(TRUE);
        !          1377:             }
        !          1378: 
        !          1379:             //
        !          1380:             // Since this SCSI protocol chip only supports 8-bits return
        !          1381:             // a width of 0 which indicates an 8-bit-wide transfers.  The
        !          1382:             // MessageCount is still correct for the message.
        !          1383:             //
        !          1384: 
        !          1385:             extendedMessage->ExtendedArguments.Wide.Width = 0;
        !          1386:             DeviceExtension->MessageSent = 0;
        !          1387:             DeviceExtension->AdapterState = MessageOut;
        !          1388:             return(TRUE);
        !          1389: 
        !          1390:         default:
        !          1391: 
        !          1392:             //
        !          1393:             // This is an unknown or illegal message, so send-message REJECT.
        !          1394:             //
        !          1395: 
        !          1396:             DeviceExtension->MessageCount = 1;
        !          1397:             DeviceExtension->MessageSent = 0;
        !          1398:             DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1399:             DeviceExtension->AdapterState = MessageOut;
        !          1400:             return(TRUE);
        !          1401:         }
        !          1402: 
        !          1403:     case SCSIMESS_INITIATE_RECOVERY:
        !          1404: 
        !          1405:         //
        !          1406:         // Save the fact that a INITIATE RECOVERY message was received.
        !          1407:         //
        !          1408: 
        !          1409:         SRB_EXT(srb)->SrbExtensionFlags |= PD_INITIATE_RECOVERY;
        !          1410:         DeviceExtension->MessageCount = 0;
        !          1411:         return(FALSE);
        !          1412: 
        !          1413:     case SCSIMESS_LINK_CMD_COMP:
        !          1414: 
        !          1415:         //
        !          1416:         // A link command completed. Process the completion.  Since the link
        !          1417:         // FLAG was not set, do not call ScsiPortNotification.  Get the next
        !          1418:         // segment of the request and accept the message.
        !          1419:         //
        !          1420: 
        !          1421:         //
        !          1422:         // Make sure that this is a linked command.
        !          1423:         // Linked commands are not supported.
        !          1424:         //
        !          1425: 
        !          1426:         if (TRUE) {
        !          1427: 
        !          1428:             //
        !          1429:             // Something is messed up.  Reject the message.
        !          1430:             //
        !          1431: 
        !          1432:             DeviceExtension->MessageCount = 1;
        !          1433:             DeviceExtension->MessageSent = 0;
        !          1434:             DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1435:             DeviceExtension->AdapterState = MessageOut;
        !          1436:             return(TRUE);
        !          1437:         }
        !          1438: 
        !          1439:         NcrProcessRequestCompletion(DeviceExtension);
        !          1440: 
        !          1441:         DeviceExtension->ActiveLuRequest = srb->NextSrb;
        !          1442: 
        !          1443:         //
        !          1444:         // Everything is ok with the message, so do not send one and set the
        !          1445:         // state to MessageAccepted.
        !          1446:         //
        !          1447: 
        !          1448:         DeviceExtension->AdapterState = MessageAccepted;
        !          1449:         DeviceExtension->MessageCount = 0;
        !          1450:         return(FALSE);
        !          1451: 
        !          1452:     case SCSIMESS_LINK_CMD_COMP_W_FLAG:
        !          1453: 
        !          1454:         //
        !          1455:         // A link command completed. Process the completion and get the next
        !          1456:         // segment of the request.  Since the link FLAG was set, call
        !          1457:         // ScsiPortNotification to notify the class driver.
        !          1458:         //
        !          1459: 
        !          1460:         //
        !          1461:         // Make sure that this is a linked command.
        !          1462:         // Linked commands are not supported.
        !          1463:         //
        !          1464: 
        !          1465:         if (TRUE) {
        !          1466: 
        !          1467:             //
        !          1468:             // Something is messed up.  Reject the message.
        !          1469:             //
        !          1470: 
        !          1471:             DeviceExtension->MessageCount = 1;
        !          1472:             DeviceExtension->MessageSent = 0;
        !          1473:             DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1474:             DeviceExtension->AdapterState = MessageOut;
        !          1475:             return(TRUE);
        !          1476:         }
        !          1477: 
        !          1478:         NcrProcessRequestCompletion(DeviceExtension);
        !          1479: 
        !          1480:         DeviceExtension->ActiveLuRequest = srb->NextSrb;
        !          1481: 
        !          1482:         //
        !          1483:         // Complete the request.
        !          1484:         //
        !          1485: 
        !          1486:         ScsiPortNotification(
        !          1487:             RequestComplete,
        !          1488:             DeviceExtension,
        !          1489:             srb
        !          1490:             );
        !          1491: 
        !          1492:         //
        !          1493:         // Everything is ok with the message, so do not send one and set the
        !          1494:         // state to MessageAccepted.
        !          1495:         //
        !          1496: 
        !          1497:         DeviceExtension->AdapterState = MessageAccepted;
        !          1498:         DeviceExtension->MessageCount = 0;
        !          1499:         return(FALSE);
        !          1500: 
        !          1501:     case SCSIMESS_MESSAGE_REJECT:
        !          1502: 
        !          1503:         //
        !          1504:         // The last message we sent was rejected.  If this was a send
        !          1505:         // message request, then set the proper status and complete the
        !          1506:         // request. Set the state to message accepted.
        !          1507:         //
        !          1508: 
        !          1509:         /* TODO: Handle message reject correctly. */
        !          1510:         if (DeviceExtension->AdapterFlags & PD_SEND_MESSAGE_REQUEST) {
        !          1511: 
        !          1512:             //
        !          1513:             // Complete the request with message rejected status.
        !          1514:             //
        !          1515: 
        !          1516:             NcrCompleteSendMessage(
        !          1517:                 DeviceExtension,
        !          1518:                 SRB_STATUS_MESSAGE_REJECTED
        !          1519:                 );
        !          1520:         }
        !          1521: 
        !          1522:         //
        !          1523:         // Check to see if a synchronous negotiation is in progress.
        !          1524:         //
        !          1525: 
        !          1526:         if (savedAdapterFlags & (PD_SYNCHRONOUS_RESPONSE_SENT|
        !          1527:             PD_SYNCHRONOUS_TRANSFER_SENT)) {
        !          1528: 
        !          1529:             //
        !          1530:             // The negotiation failed so use asynchronous data transfers.
        !          1531:             // Indicate that the negotiation has been attempted and set
        !          1532:             // the transfer for asynchronous.  Clear the negotiation flags.
        !          1533:             //
        !          1534: 
        !          1535:             targetState->TargetFlags |= PD_SYNCHRONOUS_NEGOTIATION_DONE;
        !          1536:             targetState->SynchronousOffset = ASYNCHRONOUS_OFFSET;
        !          1537:             targetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD;
        !          1538:             targetState->Configuration3.FastScsi = 0;
        !          1539:             DeviceExtension->AdapterFlags &=  ~(PD_SYNCHRONOUS_RESPONSE_SENT|
        !          1540:                 PD_SYNCHRONOUS_TRANSFER_SENT);
        !          1541: 
        !          1542:             //
        !          1543:             // Even though the negotiation appeared to go ok, there is no reason
        !          1544:             // to try again, and some targets get messed up later, so do not try
        !          1545:             // synchronous negotiation again.
        !          1546:             //
        !          1547: 
        !          1548:             targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE;
        !          1549: 
        !          1550:         }
        !          1551: 
        !          1552:         DeviceExtension->AdapterState = MessageAccepted;
        !          1553:         DeviceExtension->MessageCount = 0;
        !          1554:         return(FALSE);
        !          1555: 
        !          1556:     case SCSIMESS_SIMPLE_QUEUE_TAG:
        !          1557:     case SCSIMESS_ORDERED_QUEUE_TAG:
        !          1558:     case SCSIMESS_HEAD_OF_QUEUE_TAG:
        !          1559: 
        !          1560:         //
        !          1561:         // A queue tag message was recieve.  If this is the first byte just
        !          1562:         // accept the message and wait for the next one.
        !          1563:         //
        !          1564: 
        !          1565:         if (DeviceExtension->MessageCount < 2) {
        !          1566: 
        !          1567:             DeviceExtension->AdapterState = MessageAccepted;
        !          1568:             return(FALSE);
        !          1569: 
        !          1570:         }
        !          1571: 
        !          1572:         //
        !          1573:         // Make sure that a queue tag message is expected.
        !          1574:         //
        !          1575: 
        !          1576:         if (!(DeviceExtension->AdapterFlags & PD_EXPECTING_QUEUE_TAG) ||
        !          1577:             luExtension == NULL) {
        !          1578: 
        !          1579:             NcrPrint((1, "NcrMessageDecode: Unexpected queue tag message recieved\n"));
        !          1580: 
        !          1581:             //
        !          1582:             // Something is messed up.  Reject the message.
        !          1583:             //
        !          1584: 
        !          1585:             DeviceExtension->MessageCount = 1;
        !          1586:             DeviceExtension->MessageSent = 0;
        !          1587:             DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1588:             DeviceExtension->AdapterFlags |=  PD_DISCONNECT_EXPECTED;
        !          1589:             DeviceExtension->AdapterState = MessageOut;
        !          1590:             NcrLogError( DeviceExtension, SP_PROTOCOL_ERROR, 17);
        !          1591:             return(TRUE);
        !          1592: 
        !          1593:         }
        !          1594: 
        !          1595:         //
        !          1596:         // The second byte contains the tag used to locate the srb.
        !          1597:         //
        !          1598: 
        !          1599:         srb = ScsiPortGetSrb(
        !          1600:             DeviceExtension,
        !          1601:             0,
        !          1602:             DeviceExtension->TargetId,
        !          1603:             DeviceExtension->Lun,
        !          1604:             DeviceExtension->MessageBuffer[1]
        !          1605:             );
        !          1606: 
        !          1607:         if (srb == NULL) {
        !          1608: 
        !          1609:             NcrPrint((1, "NcrMessageDecode: Invalid queue tag recieved\n"));
        !          1610: 
        !          1611:             //
        !          1612:             // Something is messed up.  Reject the message.
        !          1613:             //
        !          1614: 
        !          1615:             DeviceExtension->AdapterFlags &= ~PD_EXPECTING_QUEUE_TAG;
        !          1616:             DeviceExtension->AdapterFlags |=  PD_DISCONNECT_EXPECTED;
        !          1617:             DeviceExtension->MessageCount = 1;
        !          1618:             DeviceExtension->MessageSent = 0;
        !          1619:             DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1620:             DeviceExtension->AdapterState = MessageOut;
        !          1621: 
        !          1622:             NcrLogError( DeviceExtension, SP_PROTOCOL_ERROR, 16);
        !          1623: 
        !          1624:             return(TRUE);
        !          1625: 
        !          1626:         }
        !          1627: 
        !          1628:         //
        !          1629:         // Everthing is ok. Set up the device extension and accept the message.
        !          1630:         // Restore the data pointers.
        !          1631:         //
        !          1632: 
        !          1633:         DeviceExtension->ActiveLuRequest = srb;
        !          1634:         DeviceExtension->ActiveDataPointer = SRB_EXT(srb)->SavedDataPointer;
        !          1635:         DeviceExtension->ActiveDataLength = SRB_EXT(srb)->SavedDataLength;
        !          1636:         DeviceExtension->AdapterFlags &= ~PD_EXPECTING_QUEUE_TAG;
        !          1637:         DeviceExtension->AdapterState = MessageAccepted;
        !          1638:         DeviceExtension->MessageCount = 0;
        !          1639:         return(FALSE);
        !          1640: 
        !          1641:     case SCSIMESS_RESTORE_POINTERS:
        !          1642: 
        !          1643:         //
        !          1644:         // Restore data pointer message.  Just copy the saved data pointer
        !          1645:         // and the length to the active data pointers.
        !          1646:         //
        !          1647: 
        !          1648:         DeviceExtension->ActiveDataPointer = SRB_EXT(srb)->SavedDataPointer;
        !          1649:         DeviceExtension->ActiveDataLength = SRB_EXT(srb)->SavedDataLength;
        !          1650:         DeviceExtension->AdapterState = MessageAccepted;
        !          1651:         DeviceExtension->MessageCount = 0;
        !          1652:         return(FALSE);
        !          1653: 
        !          1654:     case SCSIMESS_SAVE_DATA_POINTER:
        !          1655: 
        !          1656:         //
        !          1657:         // SAVE DATA POINTER message request that the active data pointer and
        !          1658:         // length be copied to the saved location.
        !          1659:         //
        !          1660: 
        !          1661:         SRB_EXT(srb)->SavedDataPointer = DeviceExtension->ActiveDataPointer;
        !          1662:         SRB_EXT(srb)->SavedDataLength = DeviceExtension->ActiveDataLength;
        !          1663:         DeviceExtension->AdapterState = MessageAccepted;
        !          1664:         DeviceExtension->MessageCount = 0;
        !          1665:         return(FALSE);
        !          1666: 
        !          1667:     default:
        !          1668: 
        !          1669:         //
        !          1670:         // An unrecognized or unsupported message. send-message reject.
        !          1671:         //
        !          1672: 
        !          1673:         DeviceExtension->MessageCount = 1;
        !          1674:         DeviceExtension->MessageSent = 0;
        !          1675:         DeviceExtension->MessageBuffer[0] = SCSIMESS_MESSAGE_REJECT;
        !          1676:         DeviceExtension->AdapterState = MessageOut;
        !          1677:         return(TRUE);
        !          1678:     }
        !          1679: }
        !          1680: 
        !          1681: BOOLEAN
        !          1682: NcrDecodeSynchronousRequest(
        !          1683:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !          1684:     PSPECIFIC_TARGET_EXTENSION TargetState,
        !          1685:     IN BOOLEAN ResponseExpected
        !          1686:     )
        !          1687: /*++
        !          1688: 
        !          1689: Routine Description:
        !          1690: 
        !          1691:     This function decodes the synchronous data transfer request message from
        !          1692:     the target.  It will update the synchronous message-in the buffer and the
        !          1693:     synchronous transfer parameters in the logical unit extension.  These
        !          1694:     parameters are specific for the NCR 53C9X protocol chip.  The updated
        !          1695:     message-in the device extension message buffer might be returned to the
        !          1696:     target.
        !          1697: 
        !          1698:     This function should be called before the final byte of the message is
        !          1699:     accepted from the SCSI bus.
        !          1700: 
        !          1701: Arguments:
        !          1702: 
        !          1703:     DeviceExtension - Supplies a pointer to the adapter specific device
        !          1704:         extension.
        !          1705: 
        !          1706:     TargetState - Supplies a pointer to the target controller's state.
        !          1707:         The synchronous transfer fields are updated  in this structure to
        !          1708:         reflect the new parameter in the message.
        !          1709: 
        !          1710:     ResponseExpected - When set, indicates that the target initiated the
        !          1711:         negotiation and that it expects a response.
        !          1712: 
        !          1713: Return Value:
        !          1714: 
        !          1715:     TRUE - Returned if the request is acceptable.
        !          1716: 
        !          1717:     FALSE - Returned if the request should be rejected and asynchronous
        !          1718:         transfer should be used.
        !          1719: 
        !          1720: --*/
        !          1721: 
        !          1722: {
        !          1723:     PSCSI_EXTENDED_MESSAGE extendedMessage;
        !          1724:     CHIP_TYPES chipType;
        !          1725:     LONG period;
        !          1726:     ULONG localPeriod;
        !          1727:     ULONG step;
        !          1728:     LONG i;
        !          1729: 
        !          1730:     extendedMessage = (PSCSI_EXTENDED_MESSAGE) DeviceExtension->MessageBuffer;
        !          1731: 
        !          1732:     //
        !          1733:     // Determine the transfer offset.  It is the minimum of the SCSI protocol
        !          1734:     // chip's maximum offset and the requested offset.
        !          1735:     //
        !          1736: 
        !          1737:     if (extendedMessage->ExtendedArguments.Synchronous.ReqAckOffset >
        !          1738:         SYNCHRONOUS_OFFSET) {
        !          1739: 
        !          1740:         if (!ResponseExpected) {
        !          1741: 
        !          1742:             //
        !          1743:             // The negotiation failed for some reason; fall back to
        !          1744:             // asynchronous data transfer.
        !          1745:             //
        !          1746: 
        !          1747:             TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET;
        !          1748:             TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD;
        !          1749:             TargetState->Configuration3.FastScsi = 0;
        !          1750:             return(FALSE);
        !          1751:         }
        !          1752: 
        !          1753:         extendedMessage->ExtendedArguments.Synchronous.ReqAckOffset = SYNCHRONOUS_OFFSET;
        !          1754:         TargetState->SynchronousOffset = SYNCHRONOUS_OFFSET;
        !          1755: 
        !          1756:     } else {
        !          1757: 
        !          1758:         TargetState->SynchronousOffset =
        !          1759:             extendedMessage->ExtendedArguments.Synchronous.ReqAckOffset;
        !          1760: 
        !          1761:     }
        !          1762: 
        !          1763:     //
        !          1764:     // If the offset requests asynchronous transfers then set the default
        !          1765:     // period and return.
        !          1766:     //
        !          1767: 
        !          1768:     if (extendedMessage->ExtendedArguments.Synchronous.ReqAckOffset ==
        !          1769:         ASYNCHRONOUS_OFFSET) {
        !          1770:         TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD;
        !          1771:         TargetState->Configuration3.FastScsi = 0;
        !          1772:         return(TRUE);
        !          1773:     }
        !          1774: 
        !          1775:     //
        !          1776:     // Calculate the period in nanoseconds from the message.
        !          1777:     //
        !          1778: 
        !          1779:     period = extendedMessage->ExtendedArguments.Synchronous.TransferPeriod;
        !          1780: 
        !          1781:     NcrPrint((1, "NcrDecodeSynchronousRequest: Requested period %d, ", period));
        !          1782: 
        !          1783:     //
        !          1784:     // If the chip supports fast SCSI and the requested period is faster than
        !          1785:     // 200 ns then assume fast SCSI.
        !          1786:     //
        !          1787: 
        !          1788:     if (DeviceExtension->ChipType == Fas216 &&  period < 200 / 4) {
        !          1789: 
        !          1790:         chipType = Fas216Fast;
        !          1791: 
        !          1792:         //
        !          1793:         // Set the fast SCSI bit in the configuration register.
        !          1794:         //
        !          1795: 
        !          1796:         TargetState->Configuration3.FastScsi = 1;
        !          1797: 
        !          1798:     } else {
        !          1799:         chipType = DeviceExtension->ChipType;
        !          1800:     }
        !          1801: 
        !          1802:     //
        !          1803:     // The initial sychronous transfer period is:
        !          1804:     //
        !          1805:     //  SynchronousPeriodCyles * 1000
        !          1806:     //  -----------------------------
        !          1807:     //    ClockSpeed * 4
        !          1808:     //
        !          1809:     // Note the result of the divide by four must be rounded up.
        !          1810:     //
        !          1811: 
        !          1812:     localPeriod =  ((SynchronousTransferTypes[chipType].SynchronousPeriodCyles
        !          1813:         * 1000) / DeviceExtension->ClockSpeed + 3) / 4;
        !          1814: 
        !          1815:     //
        !          1816:     // Check to see if the period is less than the SCSI protocol chip can
        !          1817:     // use.  If it is then update the message with our minimum and return.
        !          1818:     //
        !          1819: 
        !          1820:     if ((ULONG) period < localPeriod ) {
        !          1821: 
        !          1822:         if (!ResponseExpected) {
        !          1823: 
        !          1824:             //
        !          1825:             // The negotiation failed for some reason; fall back to
        !          1826:             // asynchronous data transfer.
        !          1827:             //
        !          1828: 
        !          1829:             TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET;
        !          1830:             TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD;
        !          1831:             TargetState->Configuration3.FastScsi = 0;
        !          1832:             NcrPrint((1, "Too fast. Local period %d\n", localPeriod));
        !          1833:             return(FALSE);
        !          1834:         }
        !          1835: 
        !          1836:         extendedMessage->ExtendedArguments.Synchronous.TransferPeriod =
        !          1837:             (UCHAR) localPeriod;
        !          1838:         period = localPeriod;
        !          1839:     }
        !          1840: 
        !          1841:     //
        !          1842:     // The synchronous transfer cycle count is calculated by:
        !          1843:     //
        !          1844:     //  (RequestedPeriod - BasePeriod) * 1000
        !          1845:     //  ------------------------------------- + InitialRegisterValue
        !          1846:     //             ClockSpeed * 4
        !          1847:     //
        !          1848:     // Note the divide must be rounded up.
        !          1849:     //
        !          1850: 
        !          1851:     step = (1000 / 4) / DeviceExtension->ClockSpeed;
        !          1852:     period -= localPeriod;
        !          1853:     for (i = SynchronousTransferTypes[chipType].InitialRegisterValue;
        !          1854:         i < SynchronousTransferTypes[chipType].MaximumPeriodCyles;
        !          1855:         i++) {
        !          1856: 
        !          1857:         if (period <= 0) {
        !          1858:             break;
        !          1859:         }
        !          1860: 
        !          1861:         period -= step;
        !          1862:         localPeriod += step;
        !          1863:     }
        !          1864: 
        !          1865:     NcrPrint((1, "Local period: %d, Register value: %d\n", localPeriod, i));
        !          1866: 
        !          1867:     if (i >= SynchronousTransferTypes[chipType].MaximumPeriodCyles) {
        !          1868: 
        !          1869:         //
        !          1870:         // The requested transfer period is too long for the SCSI protocol
        !          1871:         // chip.  Fall back to synchronous and reject the request.
        !          1872:         //
        !          1873: 
        !          1874:         TargetState->SynchronousOffset = ASYNCHRONOUS_OFFSET;
        !          1875:         TargetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD;
        !          1876:         TargetState->Configuration3.FastScsi = 0;
        !          1877: 
        !          1878:         return(FALSE);
        !          1879:     }
        !          1880: 
        !          1881:     TargetState->SynchronousPeriod = (UCHAR) i;
        !          1882: 
        !          1883:     //
        !          1884:     // If no response was expected then the negotation has completed
        !          1885:     // successfully. Set the synchronous data transfer parameter registers
        !          1886:     // to the new values.  These must be set before a data transfer
        !          1887:     // is started.
        !          1888:     //
        !          1889: 
        !          1890:     SCSI_WRITE( DeviceExtension->Adapter,
        !          1891:                 SynchronousPeriod,
        !          1892:                 TargetState->SynchronousPeriod
        !          1893:                 );
        !          1894:     SCSI_WRITE( DeviceExtension->Adapter,
        !          1895:                 SynchronousOffset,
        !          1896:                 TargetState->SynchronousOffset
        !          1897:                 );
        !          1898:     SCSI_WRITE( DeviceExtension->Adapter,
        !          1899:                 Configuration3,
        !          1900:                 *((PUCHAR) &TargetState->Configuration3)
        !          1901:                 );
        !          1902: 
        !          1903:     return(TRUE);
        !          1904: 
        !          1905: }
        !          1906: 
        !          1907: VOID
        !          1908: NcrDumpState(
        !          1909:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension
        !          1910:     )
        !          1911: 
        !          1912: /*++
        !          1913: 
        !          1914: Routine Description:
        !          1915: 
        !          1916:     This function prints the interesting state information about the requested
        !          1917:     SCSI bus adapter.
        !          1918: 
        !          1919: Arguments:
        !          1920: 
        !          1921:     DeviceExtension - Supplies a pointer to device extension for the SCSI
        !          1922:         bus adapter that should be displayed.
        !          1923: 
        !          1924: Return Value:
        !          1925: 
        !          1926:     None.
        !          1927: 
        !          1928: --*/
        !          1929: 
        !          1930: {
        !          1931:     NcrPrint((0, "NcrDumpState: Specific device extension: %8x; Active Logical Unit: %8x;\n",
        !          1932:              DeviceExtension,
        !          1933:              DeviceExtension->ActiveLogicalUnit
        !          1934:              ));
        !          1935:     NcrPrint((0, "NcrDumpState: Adapter Status: %2x; Adapter Interrupt: %2x; Adapter Step: %2x;\n",
        !          1936:              *((PUCHAR) &DeviceExtension->AdapterStatus),
        !          1937:              *((PUCHAR) &DeviceExtension->AdapterInterrupt),
        !          1938:              *((PUCHAR) &DeviceExtension->SequenceStep)
        !          1939:              ));
        !          1940:     NcrPrint((0, "NcrDumpState: Adapter flags: %4x; Adapter state: %d;\n",
        !          1941:              DeviceExtension->AdapterFlags,
        !          1942:              DeviceExtension->AdapterState
        !          1943:              ));
        !          1944: 
        !          1945: }
        !          1946: 
        !          1947: 
        !          1948: BOOLEAN
        !          1949: NcrInitializeAdapter(
        !          1950:     IN PVOID ServiceContext
        !          1951:     )
        !          1952: /*++
        !          1953: 
        !          1954: Routine Description:
        !          1955: 
        !          1956:     This function initializes the NCR 53c9x SCSI host adpater and protocol
        !          1957:     chip.  This function must be called before any other operations are
        !          1958:     performed.  It should also be called after a power failure.  This
        !          1959:     function does not cause any interrupts; however, after it completes
        !          1960:     interrupts can occur.
        !          1961: 
        !          1962: Arguments:
        !          1963: 
        !          1964:     ServiceContext - Pointer to the specific device extension for this SCSI
        !          1965:         bus.
        !          1966: 
        !          1967: Return Value:
        !          1968: 
        !          1969:     TRUE - Returns true indicating that the initialization of the chip is
        !          1970:         complete.
        !          1971: 
        !          1972: --*/
        !          1973: 
        !          1974: {
        !          1975:     PSPECIFIC_DEVICE_EXTENSION deviceExtension = ServiceContext;
        !          1976:     UCHAR dataByte;
        !          1977: 
        !          1978:     //
        !          1979:     // Clear the adapter flags, but preserve the NCR adapter flag.
        !          1980:     //
        !          1981: 
        !          1982:     deviceExtension->AdapterFlags =
        !          1983:         deviceExtension->AdapterFlags & PD_NCR_ADAPTER;
        !          1984: 
        !          1985:     //
        !          1986:     // Initialize the NCR 53c9x SCSI protocol chip.
        !          1987:     //
        !          1988: 
        !          1989:     SCSI_WRITE( deviceExtension->Adapter, Command, RESET_SCSI_CHIP );
        !          1990:     SCSI_WRITE( deviceExtension->Adapter, Command, NO_OPERATION_DMA );
        !          1991: 
        !          1992:     //
        !          1993:     // Set the configuration register for slow cable mode, parity enable,
        !          1994:     // and allow reset interrupts, also set the host adapter SCSI bus id.
        !          1995:     // Configuration registers 2 and 3 are cleared by the chip reset and
        !          1996:     // do not need to be changed.
        !          1997:     //
        !          1998: 
        !          1999:     dataByte = deviceExtension->AdapterBusId;
        !          2000:     ((PSCSI_CONFIGURATION1)(&dataByte))->ParityEnable = 1;
        !          2001: 
        !          2002:     SCSI_WRITE(deviceExtension->Adapter, Configuration1, dataByte);
        !          2003: 
        !          2004:     //
        !          2005:     // Configuration registers 2 and 3 are cleared by a chip reset and do
        !          2006:     // need to be initialized. Note these registers do not exist on the
        !          2007:     // Ncr53c90, but the writes will do no harm. Set configuration register 3
        !          2008:     // with the value determined by the find adapter routine.
        !          2009:     //
        !          2010: 
        !          2011:     SCSI_WRITE(
        !          2012:         deviceExtension->Adapter,
        !          2013:         Configuration3,
        !          2014:         *((PUCHAR)&deviceExtension->Configuration3)
        !          2015:         );
        !          2016: 
        !          2017:     //
        !          2018:     // Enable the SCSI-2 features.
        !          2019:     //
        !          2020: 
        !          2021:     dataByte = 0;
        !          2022:     ((PSCSI_CONFIGURATION2)(&dataByte))->Scsi2 = 1;
        !          2023:     ((PSCSI_CONFIGURATION2)(&dataByte))->EnablePhaseLatch = 1;
        !          2024: 
        !          2025:     SCSI_WRITE(deviceExtension->Adapter, Configuration2, dataByte);
        !          2026: 
        !          2027:     //
        !          2028:     // Set the clock conversion register. The clock convertion factor is the
        !          2029:     // clock speed divided by 5 rounded up. Only the low three bits are used.
        !          2030:     //
        !          2031: 
        !          2032:     dataByte = (deviceExtension->ClockSpeed + 4) / 5;
        !          2033:     SCSI_WRITE(
        !          2034:         deviceExtension->Adapter,
        !          2035:         ClockConversionFactor,
        !          2036:         (dataByte & 0x07)
        !          2037:         );
        !          2038: 
        !          2039:     //
        !          2040:     // Set the SelectTimeOut Register to 250ms.  This value is based on the
        !          2041:     // clock conversion factor and the clock speed.
        !          2042:     //
        !          2043: 
        !          2044:     dataByte = SELECT_TIMEOUT_FACTOR  * deviceExtension->ClockSpeed / dataByte;
        !          2045: 
        !          2046:     SCSI_WRITE( deviceExtension->Adapter, SelectTimeOut, dataByte);
        !          2047: 
        !          2048:     //
        !          2049:     // NOTE:  Reselection does not need to be enabled until a request is sent
        !          2050:     // to a target.  The process of sending a target a request will cause a
        !          2051:     // disconnect interrupt so that an ENABLE_SELECTION_RESELECTION request
        !          2052:     // will be performed.
        !          2053:     //
        !          2054: 
        !          2055:     if (deviceExtension->AdapterFlags & PD_NCR_ADAPTER) {
        !          2056: 
        !          2057:         //
        !          2058:         // Enable Adapter Interrupts
        !          2059:         //
        !          2060: 
        !          2061:         dataByte = SCSI_READ(deviceExtension->AdapterBase, OptionSelect1);
        !          2062:         ((PPOS_DATA_1)(&dataByte))->InterruptEnable = 1;
        !          2063:         SCSI_WRITE(deviceExtension->AdapterBase, OptionSelect1, dataByte);
        !          2064: 
        !          2065:     }
        !          2066: 
        !          2067:     return( TRUE );
        !          2068: }
        !          2069: 
        !          2070: BOOLEAN
        !          2071: NcrInterruptServiceRoutine(
        !          2072:     PVOID ServiceContext
        !          2073:     )
        !          2074: /*++
        !          2075: 
        !          2076: Routine Description:
        !          2077: 
        !          2078:     This routine is the interrupt service routine for the NCR 53c9x SCSI
        !          2079:     host adapter.  It is the main SCSI protocol engine of the driver and
        !          2080:     is driven by service requests from targets on the SCSI bus.  This routine
        !          2081:     also detects errors and performs error recovery. Generally, this routine
        !          2082:     handles one interrupt per invokation.
        !          2083: 
        !          2084:     The general flow of this routine is as follows:
        !          2085: 
        !          2086:         Check for an interrupt.
        !          2087: 
        !          2088:         Determine if there are any pending errors.
        !          2089: 
        !          2090:         Check to see if the bus disconnected.
        !          2091: 
        !          2092:         Check that the previous function completed normally.
        !          2093: 
        !          2094:         Determine what the target wants to do next and program the chip
        !          2095:         appropriately.
        !          2096: 
        !          2097:         Check for the next interrupt.
        !          2098: 
        !          2099: Arguments:
        !          2100: 
        !          2101:     ServiceContext - Supplies a pointer to the device extension for the
        !          2102:         interrupting adapter.
        !          2103: 
        !          2104: Return Value:
        !          2105: 
        !          2106:     TRUE - Indicates that an interrupt was found.
        !          2107: 
        !          2108:     FALSE - Indicates the device was not interrupting.
        !          2109: 
        !          2110: --*/
        !          2111: 
        !          2112: {
        !          2113:     PSPECIFIC_DEVICE_EXTENSION deviceExtension = ServiceContext;
        !          2114:     PSPECIFIC_LOGICAL_UNIT_EXTENSION luExtension;
        !          2115:     PSCSI_REQUEST_BLOCK srb;
        !          2116:     LONG i;
        !          2117:     SCSI_DMA_STATUS DmaStatus;
        !          2118:     BOOLEAN setAttention;
        !          2119: 
        !          2120:     /* POWERFAIL */
        !          2121: 
        !          2122:     //
        !          2123:     // Make sure there is really an interrupt before reading the other
        !          2124:     // registers, particularly, the interrupt register.
        !          2125:     //
        !          2126: 
        !          2127:     if (deviceExtension->AdapterFlags & PD_NCR_ADAPTER) {
        !          2128: 
        !          2129:         *((PUCHAR) &DmaStatus) = SCSI_READ( deviceExtension->AdapterBase, DmaStatus );
        !          2130:         if (DmaStatus.Interrupt != deviceExtension->InterruptPending ) {
        !          2131:             return(FALSE);
        !          2132:         }
        !          2133: 
        !          2134:         *((PUCHAR) &deviceExtension->AdapterStatus) = SCSI_READ ( deviceExtension->Adapter, ScsiStatus );
        !          2135: 
        !          2136:     } else {
        !          2137: 
        !          2138:         *((PUCHAR) &deviceExtension->AdapterStatus) = SCSI_READ ( deviceExtension->Adapter, ScsiStatus );
        !          2139:         if (!deviceExtension->AdapterStatus.Interrupt) {
        !          2140:             return(FALSE);
        !          2141:         }
        !          2142:     }
        !          2143: 
        !          2144: NextInterrupt:
        !          2145: 
        !          2146:     //
        !          2147:     // Get the current chip state which includes the status register, the
        !          2148:     // sequence step register and the interrupt register. These registers are
        !          2149:     // frozen until the interrupt register is read.
        !          2150:     //
        !          2151: 
        !          2152:     *((PUCHAR) &deviceExtension->SequenceStep) = SCSI_READ(
        !          2153:                                                  deviceExtension->Adapter,
        !          2154:                                                  SequenceStep
        !          2155:                                                  );
        !          2156:     //
        !          2157:     // This read will dismiss the interrupt.
        !          2158:     //
        !          2159: 
        !          2160:     *((PUCHAR) &deviceExtension->AdapterInterrupt) = SCSI_READ(
        !          2161:                                                      deviceExtension->Adapter,
        !          2162:                                                      ScsiInterrupt
        !          2163:                                                      );
        !          2164: 
        !          2165: #if DBG
        !          2166:     if (!deviceExtension->AdapterInterrupt.Disconnect && NcrDebug) {
        !          2167:     NcrPrint((0, "NcrInterrupt: Adapter Status: %2x; Adapter Interrupt: %2x; Adapter Step: %2x;\n",
        !          2168:              *((PUCHAR) &deviceExtension->AdapterStatus),
        !          2169:              *((PUCHAR) &deviceExtension->AdapterInterrupt),
        !          2170:              *((PUCHAR) &deviceExtension->SequenceStep)
        !          2171:              ));
        !          2172:     }
        !          2173: #endif
        !          2174: 
        !          2175:     deviceExtension->InterruptCount++;
        !          2176: 
        !          2177:     if (deviceExtension->AdapterInterrupt.IllegalCommand) {
        !          2178:         NcrPrint((1, "NcrInterrupt: IllegalCommand\n" ));
        !          2179: 
        !          2180: #if DBG
        !          2181:         if ( NcrDebug != 0) {
        !          2182:             NcrDumpState(deviceExtension);
        !          2183:         }
        !          2184: #endif
        !          2185: 
        !          2186:         if (deviceExtension->AdapterState == AttemptingSelect ||
        !          2187:             deviceExtension->AdapterState == Reselected) {
        !          2188: 
        !          2189:             //
        !          2190:             // If an IllegalCommand interrupt has occurred and a select
        !          2191:             // is being attempted, flush the FIFO and exit. This occurs
        !          2192:             // when the fifo is being filled for a new command at the
        !          2193:             // same time time a reselection occurs.
        !          2194:             //
        !          2195: 
        !          2196:             SCSI_WRITE(deviceExtension->Adapter, Command, FLUSH_FIFO);
        !          2197: 
        !          2198:         } else {
        !          2199: 
        !          2200:             //
        !          2201:             // An illegal command occured at an unexpected time.  Reset the
        !          2202:             // bus and log an error.
        !          2203:             //
        !          2204: 
        !          2205:             NcrResetScsiBusInternal(deviceExtension, 0);
        !          2206:             NcrInitializeAdapter(deviceExtension);
        !          2207: 
        !          2208: #ifdef MIPS
        !          2209:             //
        !          2210:             // There is a chip bug with the Emulex 216 part which causes
        !          2211:             // illegal commands interrupts to be generated.  This problem
        !          2212:             // can be prevented on the mips systems by setting a bit in the
        !          2213:             // DMA controller to provide better DMA service to the adapter.
        !          2214:             //
        !          2215: 
        !          2216:             if (deviceExtension->ErrorCount++ == 1) {
        !          2217: 
        !          2218:                 //
        !          2219:                 // Clear on board DMA
        !          2220:                 //
        !          2221: 
        !          2222:                 i = ScsiPortReadRegisterUlong(
        !          2223:                     (PULONG) &DMA_CONTROL->Channel[SCSI_CHANNEL].Enable.Long
        !          2224:                     );
        !          2225: 
        !          2226:                 ((PDMA_CHANNEL_ENABLE) &i)->ChannelEnable = 0;
        !          2227:                 ScsiPortWriteRegisterUlong(
        !          2228:                     (PULONG) &DMA_CONTROL->Channel[SCSI_CHANNEL].Enable.Long,
        !          2229:                     i
        !          2230:                     );
        !          2231: 
        !          2232: 
        !          2233:                 //
        !          2234:                 // Enable brust mode in the DMA controller.
        !          2235:                 //
        !          2236: 
        !          2237:                 i = ScsiPortReadRegisterUlong(
        !          2238:                     (PULONG) &DMA_CONTROL->Channel[SCSI_CHANNEL].Mode.Long
        !          2239:                     );
        !          2240: 
        !          2241: 
        !          2242:                 ((PDMA_CHANNEL_MODE) &i)->BurstMode = 1;
        !          2243: 
        !          2244:                 ScsiPortWriteRegisterUlong(
        !          2245:                     (PULONG) &DMA_CONTROL->Channel[SCSI_CHANNEL].Mode.Long,
        !          2246:                     i
        !          2247:                     );
        !          2248: 
        !          2249:                  NcrLogError(deviceExtension, SP_BAD_FW_WARNING, 15);
        !          2250: 
        !          2251:             }
        !          2252: #endif
        !          2253:             NcrLogError(deviceExtension, SP_INTERNAL_ADAPTER_ERROR, 14);
        !          2254: 
        !          2255:         }
        !          2256: 
        !          2257:         return(TRUE);
        !          2258:     }
        !          2259: 
        !          2260:     //
        !          2261:     // Check for major errors these should never occur.
        !          2262:     //
        !          2263: 
        !          2264:     if ( deviceExtension->AdapterInterrupt.Selected ||
        !          2265:          deviceExtension->AdapterInterrupt.SelectedWithAttention ||
        !          2266:          deviceExtension->AdapterStatus.GrossError ||
        !          2267:          deviceExtension->InterruptCount > MAX_INTERRUPT_COUNT) {
        !          2268: 
        !          2269:         //
        !          2270:         // Things are really messed up.  Reset the bus, the chip and
        !          2271:         // bail out.
        !          2272:         //
        !          2273: 
        !          2274:         NcrPrint((0,
        !          2275:             "NcrInterruptServiceRoutine: Unexpected error. Interrupt Count=%d\n",
        !          2276:             deviceExtension->InterruptCount
        !          2277:             ));
        !          2278: 
        !          2279:         NcrDumpState(deviceExtension);
        !          2280: 
        !          2281:         NcrResetScsiBusInternal(deviceExtension, 0);
        !          2282:         NcrInitializeAdapter(deviceExtension);
        !          2283: 
        !          2284:         NcrLogError(deviceExtension, SP_INTERNAL_ADAPTER_ERROR, 1);
        !          2285:         return(TRUE);
        !          2286:     }
        !          2287: 
        !          2288:     //
        !          2289:     // Check for a bus reset.
        !          2290:     //
        !          2291: 
        !          2292:     if (deviceExtension->AdapterInterrupt.ScsiReset) {
        !          2293: 
        !          2294:         //
        !          2295:         // Check if this was an expected reset.
        !          2296:         //
        !          2297: 
        !          2298:         if (!(deviceExtension->AdapterFlags & PD_EXPECTING_RESET_INTERRUPT)) {
        !          2299: 
        !          2300:             NcrPrint((0, "NcrInterruptServiceRoutine: SCSI bus reset detected\n"));
        !          2301: 
        !          2302:             //
        !          2303:             // Cleanup the logical units and notify the port driver,
        !          2304:             // then return.
        !          2305:             //
        !          2306: 
        !          2307:             NcrCleanupAfterReset(deviceExtension, TRUE);
        !          2308:             ScsiPortNotification(
        !          2309:                 ResetDetected,
        !          2310:                 deviceExtension,
        !          2311:                 NULL
        !          2312:                 );
        !          2313: 
        !          2314:         } else {
        !          2315:             deviceExtension->AdapterFlags &= ~PD_EXPECTING_RESET_INTERRUPT;
        !          2316:         }
        !          2317: 
        !          2318:         //
        !          2319:         // Stall for a short time. This allows interrupt to clear.
        !          2320:         //
        !          2321: 
        !          2322:         ScsiPortStallExecution(INTERRUPT_STALL_TIME);
        !          2323: 
        !          2324:         SCSI_WRITE(deviceExtension->Adapter, Command, FLUSH_FIFO);
        !          2325: 
        !          2326:         //
        !          2327:         // Note that this should only happen in firmware where the interrupts
        !          2328:         // are polled.
        !          2329:         //
        !          2330: 
        !          2331:         if (deviceExtension->AdapterFlags & PD_PENDING_START_IO) {
        !          2332: 
        !          2333:             //
        !          2334:             // Call NcrStartIo to start the pending request.
        !          2335:             // Note that NcrStartIo is idempotent when called with
        !          2336:             // the same arguments.
        !          2337:             //
        !          2338: 
        !          2339:             NcrStartIo(
        !          2340:                 deviceExtension,
        !          2341:                 deviceExtension->NextSrbRequest
        !          2342:                 );
        !          2343: 
        !          2344:         }
        !          2345: 
        !          2346:         return(TRUE);
        !          2347:     }
        !          2348: 
        !          2349:     //
        !          2350:     // Check for parity errors.
        !          2351:     //
        !          2352: 
        !          2353:     if (deviceExtension->AdapterStatus.ParityError) {
        !          2354: 
        !          2355:         //
        !          2356:         // The SCSI protocol chip has set ATN: we expect the target to
        !          2357:         // go into message-out so that a error message can be sent and the
        !          2358:         // operation retried. After the error has been noted, continue
        !          2359:         // processing the interrupt. The message sent depends on whether a
        !          2360:         // message was being received or something else.  If the status
        !          2361:         // is currently message-in then send-message PARITY ERROR;
        !          2362:         // otherwise, send INITIATOR DETECTED ERROR.
        !          2363:         //
        !          2364: 
        !          2365:         NcrPrint((0, "NcrInterruptServiceRoutine: Parity error detected.\n"));
        !          2366:         NcrDumpState(deviceExtension);
        !          2367: 
        !          2368:         //
        !          2369:         // If the current phase is MESSAGE_IN then special handling is requred.
        !          2370:         //
        !          2371: 
        !          2372:         if (deviceExtension->AdapterStatus.Phase == MESSAGE_IN) {
        !          2373: 
        !          2374:             //
        !          2375:             // If the current state is CommandComplete, then the fifo contains
        !          2376:             // a good status byte.  Save the status byte before handling the
        !          2377:             // message parity error.
        !          2378:             //
        !          2379: 
        !          2380:             if (deviceExtension->AdapterState == CommandComplete) {
        !          2381: 
        !          2382:                 srb = deviceExtension->ActiveLuRequest;
        !          2383: 
        !          2384:                 srb->ScsiStatus = SCSI_READ(
        !          2385:                     deviceExtension->Adapter,
        !          2386:                     Fifo
        !          2387:                     );
        !          2388: 
        !          2389:                 SRB_EXT(srb)->SrbExtensionFlags |= PD_STATUS_VALID;
        !          2390: 
        !          2391:             }
        !          2392: 
        !          2393:             //
        !          2394:             // Set the message to indicate a message parity error, flush the
        !          2395:             // fifo and accept the message.
        !          2396:             //
        !          2397: 
        !          2398:             deviceExtension->MessageBuffer[0] = SCSIMESS_MESS_PARITY_ERROR;
        !          2399:             SCSI_WRITE(deviceExtension->Adapter, Command, FLUSH_FIFO);
        !          2400:             NcrAcceptMessage(deviceExtension, TRUE, TRUE);
        !          2401: 
        !          2402:             //
        !          2403:             // Since the message which was in the fifo is no good. Clear the
        !          2404:             // function complete interrupt which indicates that a message byte
        !          2405:             // has been recieved.  If this is a reselection, then this will
        !          2406:             // a bus reset to occur.  This cause is not handled well in this
        !          2407:             // code, because it is not setup to deal with a target id and no
        !          2408:             // logical unit.
        !          2409:             //
        !          2410: 
        !          2411:             deviceExtension->AdapterInterrupt.FunctionComplete = FALSE;
        !          2412: 
        !          2413:         } else {
        !          2414: 
        !          2415:             deviceExtension->MessageBuffer[0] = SCSIMESS_INIT_DETECTED_ERROR;
        !          2416: 
        !          2417:         }
        !          2418: 
        !          2419:         deviceExtension->MessageCount = 1;
        !          2420:         deviceExtension->MessageSent = 0;
        !          2421:         deviceExtension->AdapterState = MessageOut;
        !          2422:         deviceExtension->AdapterFlags |= PD_MESSAGE_OUT_VALID;
        !          2423: 
        !          2424:         if (!(deviceExtension->AdapterFlags & PD_PARITY_ERROR_LOGGED)) {
        !          2425:             NcrLogError(deviceExtension, SP_BUS_PARITY_ERROR, 2);
        !          2426:             deviceExtension->AdapterFlags |= PD_PARITY_ERROR_LOGGED;
        !          2427:         }
        !          2428: 
        !          2429:     }
        !          2430: 
        !          2431: 
        !          2432:     //
        !          2433:     // Check for bus disconnection.  If this was expected, then the next request
        !          2434:     // can be processed.  If a selection was being attempted, then perhaps the
        !          2435:     // logical unit is not there or has gone away.  Otherwise, this is an
        !          2436:     // unexpected disconnect and should be reported as an error.
        !          2437:     //
        !          2438: 
        !          2439:     if (deviceExtension->AdapterInterrupt.Disconnect) {
        !          2440: 
        !          2441:         srb = deviceExtension->NextSrbRequest;
        !          2442: 
        !          2443:         //
        !          2444:         // Check for an unexpected disconnect.  This occurs if the state is
        !          2445:         // not ExpectingDisconnect and a selection did not fail.  A selection
        !          2446:         // failure is indicated by state of AttemptingSelect and a sequence
        !          2447:         // step of 0.
        !          2448:         //
        !          2449: 
        !          2450:         if (deviceExtension->AdapterState == AttemptingSelect &&
        !          2451:                deviceExtension->SequenceStep.Step == 0) {
        !          2452: 
        !          2453:             //
        !          2454:             // The target selection failed.  Log the error.  If the retry
        !          2455:             // count is not exceeded then retry the selection; otherwise
        !          2456:             // fail the request.
        !          2457:             //
        !          2458: 
        !          2459:             luExtension = ScsiPortGetLogicalUnit(
        !          2460:                 deviceExtension,
        !          2461:                 srb->PathId,
        !          2462:                 srb->TargetId,
        !          2463:                 srb->Lun
        !          2464:                 );
        !          2465: 
        !          2466:             if (luExtension->RetryCount++ >= RETRY_SELECTION_LIMIT) {
        !          2467: 
        !          2468:                 //
        !          2469:                 // Clear the Active request in the logical unit.
        !          2470:                 //
        !          2471: 
        !          2472:                 luExtension->RetryCount = 0;
        !          2473: 
        !          2474:                 if (deviceExtension->AdapterFlags & PD_SEND_MESSAGE_REQUEST) {
        !          2475: 
        !          2476:                     //
        !          2477:                     // Process the completion of the send message request.
        !          2478:                     // Set the ActiveLogicalUnit for NcrCompleteSendMessage.
        !          2479:                     // ActiveLogicalUnit is cleared after it returns.
        !          2480:                     //
        !          2481: 
        !          2482:                     deviceExtension->ActiveLogicalUnit = luExtension;
        !          2483: 
        !          2484:                     NcrCompleteSendMessage(
        !          2485:                         deviceExtension,
        !          2486:                         SRB_STATUS_SELECTION_TIMEOUT
        !          2487:                         );
        !          2488: 
        !          2489:                     deviceExtension->ActiveLogicalUnit = NULL;
        !          2490: 
        !          2491:                 } else {
        !          2492: 
        !          2493:                     srb->SrbStatus = SRB_STATUS_SELECTION_TIMEOUT;
        !          2494: 
        !          2495:                     ScsiPortNotification(
        !          2496:                         RequestComplete,
        !          2497:                         deviceExtension,
        !          2498:                         srb
        !          2499:                         );
        !          2500: 
        !          2501:                     luExtension->ActiveLuRequest = NULL;
        !          2502:                 }
        !          2503: 
        !          2504:                 deviceExtension->NextSrbRequest = NULL;
        !          2505:                 deviceExtension->AdapterFlags &= ~PD_PENDING_START_IO;
        !          2506: 
        !          2507:                 ScsiPortNotification(
        !          2508:                     NextRequest,
        !          2509:                     deviceExtension,
        !          2510:                     NULL
        !          2511:                     );
        !          2512: 
        !          2513:             }
        !          2514: 
        !          2515:             //
        !          2516:             // If the request needs to be retried, it will be automatically
        !          2517:             // because the PD_PENDING_START_IO flag is still set, and the
        !          2518:             // following code will cause it to be restarted.
        !          2519:             //
        !          2520: 
        !          2521:             //
        !          2522:             // The chip leaves some of the command in the FIFO, so clear the
        !          2523:             // FIFO so there is no garbage left in it.
        !          2524:             //
        !          2525: 
        !          2526:             SCSI_WRITE(deviceExtension->Adapter, Command, FLUSH_FIFO);
        !          2527: 
        !          2528:         } else if ( deviceExtension->AdapterState == DisconnectExpected ||
        !          2529:             deviceExtension->AdapterFlags & PD_DISCONNECT_EXPECTED) {
        !          2530: 
        !          2531:             //
        !          2532:             // Check to see if this was a send-message request which is
        !          2533:             // completed when the disconnect occurs.
        !          2534:             //
        !          2535: 
        !          2536:             if (deviceExtension->AdapterFlags & PD_SEND_MESSAGE_REQUEST) {
        !          2537: 
        !          2538:                 //
        !          2539:                 // Complete the request.
        !          2540:                 //
        !          2541: 
        !          2542:                 NcrCompleteSendMessage( deviceExtension,
        !          2543:                                         SRB_STATUS_SUCCESS
        !          2544:                                         );
        !          2545:             }
        !          2546: 
        !          2547:         } else {
        !          2548: 
        !          2549:             //
        !          2550:             // The disconnect was unexpected treat it as an error.
        !          2551:             // Check to see if a data transfer was in progress, if so flush
        !          2552:             // the DMA.
        !          2553:             //
        !          2554: 
        !          2555:             if (deviceExtension->AdapterState == DataTransfer) {
        !          2556:                 ScsiPortFlushDma(deviceExtension);
        !          2557:             }
        !          2558: 
        !          2559:             //
        !          2560:             // NOTE: If the state is AttemptingSelect, then ActiveLogicalUnit
        !          2561:             //       is NULL!
        !          2562:             //
        !          2563: 
        !          2564:             //
        !          2565:             // The chip leaves some of the command in the FIFO, so clear the
        !          2566:             // FIFO so there is not garbage left in it.
        !          2567:             //
        !          2568: 
        !          2569:             SCSI_WRITE(deviceExtension->Adapter, Command, FLUSH_FIFO);
        !          2570: 
        !          2571:             //
        !          2572:             // An unexpected disconnect has occurred.  Log the error.  It is
        !          2573:             // not clear if the device will respond again, so let the time-out
        !          2574:             // code clean up the request if necessary.
        !          2575:             //
        !          2576: 
        !          2577:             NcrPrint((0, "NcrInterruptServiceRoutine: Unexpected bus disconnect\n"));
        !          2578: 
        !          2579:             NcrLogError(deviceExtension, SP_UNEXPECTED_DISCONNECT, 3);
        !          2580:         }
        !          2581: 
        !          2582:         //
        !          2583:         // Clean up the adapter state to indicate the bus is now free, enable
        !          2584:         // reselection, and start any pending request.
        !          2585:         //
        !          2586: 
        !          2587:         deviceExtension->AdapterState = BusFree;
        !          2588:         deviceExtension->AdapterFlags &= ~PD_ADAPTER_DISCONNECT_MASK;
        !          2589:         deviceExtension->ActiveLuRequest = NULL;
        !          2590:         SCSI_WRITE(deviceExtension->Adapter, Command, ENABLE_SELECTION_RESELECTION);
        !          2591: 
        !          2592: #if DBG
        !          2593:         if (NcrDebug) {
        !          2594:             NcrPrint((0, "NcrInterruptServiceRoutine: DisconnectComplete.\n"));
        !          2595:         }
        !          2596: #endif
        !          2597: 
        !          2598:         if (deviceExtension->AdapterFlags & PD_PENDING_START_IO) {
        !          2599: 
        !          2600:             ASSERT(deviceExtension->NextSrbRequest->SrbExtension != NULL);
        !          2601: 
        !          2602:             //
        !          2603:             // Check that the next request is still active.  This should not
        !          2604:             // be necessary, but it appears there is a hole somewhere.
        !          2605:             //
        !          2606: 
        !          2607:             srb = deviceExtension->NextSrbRequest;
        !          2608:             srb = ScsiPortGetSrb(
        !          2609:                     deviceExtension,
        !          2610:                     srb->PathId,
        !          2611:                     srb->TargetId,
        !          2612:                     srb->Lun,
        !          2613:                     srb->QueueTag
        !          2614:                     );
        !          2615: 
        !          2616:             ASSERT(srb == deviceExtension->NextSrbRequest ||
        !          2617:                deviceExtension->NextSrbRequest->Function != SRB_FUNCTION_EXECUTE_SCSI);
        !          2618:             
        !          2619:             if (srb != deviceExtension->NextSrbRequest &&
        !          2620:                 deviceExtension->NextSrbRequest->Function == SRB_FUNCTION_EXECUTE_SCSI) {
        !          2621: 
        !          2622:                 NcrPrint((1, "NcrInterruptServiceRoutine:  Found in active SRB in next request field.\n"));
        !          2623:                 NcrDumpState(deviceExtension);
        !          2624: 
        !          2625:                 //
        !          2626:                 // Dump it on the floor.
        !          2627:                 //
        !          2628:         
        !          2629:                 deviceExtension->NextSrbRequest = NULL;
        !          2630:                 deviceExtension->AdapterFlags &= ~PD_PENDING_START_IO;
        !          2631:         
        !          2632:                 NcrLogError(deviceExtension, SP_INTERNAL_ADAPTER_ERROR, 18);
        !          2633:         
        !          2634:                 ScsiPortNotification(
        !          2635:                     NextRequest,
        !          2636:                     deviceExtension,
        !          2637:                     NULL
        !          2638:                     );
        !          2639:         
        !          2640:             } else {
        !          2641: 
        !          2642:                 //
        !          2643:                 // Call NcrStartIo to start the pending request.
        !          2644:                 // Note that NcrStartIo is idempotent when called with
        !          2645:                 // the same arguments.
        !          2646:                 //
        !          2647:     
        !          2648:                 NcrStartIo(
        !          2649:                     deviceExtension,
        !          2650:                     deviceExtension->NextSrbRequest
        !          2651:                     );
        !          2652:     
        !          2653:             }
        !          2654:         }
        !          2655:     }
        !          2656: 
        !          2657: 
        !          2658:     //
        !          2659:     // Check for a reselection interrupt.
        !          2660:     //
        !          2661: 
        !          2662:     if (deviceExtension->AdapterInterrupt.Reselected) {
        !          2663:         UCHAR targetId;
        !          2664:         UCHAR luId;
        !          2665: 
        !          2666:         //
        !          2667:         // The usual case is not to set attention so initialize the
        !          2668:         // varible to FALSE.
        !          2669:         //
        !          2670: 
        !          2671:         setAttention = FALSE;
        !          2672: 
        !          2673:         //
        !          2674:         // If the FunctionComplete interrupt is not set then the target did
        !          2675:         // not send an IDENTFY message.  This is a fatal protocol violation.
        !          2676:         // Reset the bus to get rid of this target.
        !          2677:         //
        !          2678: 
        !          2679:         if (!deviceExtension->AdapterInterrupt.FunctionComplete) {
        !          2680: 
        !          2681:             NcrPrint((0, "NcrInterruptServiceRoutine: Reselection Failed.\n"));
        !          2682:             NcrDumpState(deviceExtension);
        !          2683: 
        !          2684:             NcrResetScsiBusInternal(deviceExtension, 0);
        !          2685:             NcrInitializeAdapter(deviceExtension);
        !          2686: 
        !          2687:             NcrLogError(deviceExtension, SP_PROTOCOL_ERROR, 4);
        !          2688: 
        !          2689:             return(TRUE);
        !          2690:         }
        !          2691: 
        !          2692:         //
        !          2693:         // The target Id and the logical unit id are in the FIFO. Use them to
        !          2694:         // get the connected active logical unit.
        !          2695:         //
        !          2696: 
        !          2697:         luId = SCSI_READ(deviceExtension->Adapter, Fifo);
        !          2698: 
        !          2699:         //
        !          2700:         // The select id has two bits set.   One is the SCSI bus id of the
        !          2701:         // initiator and the other is the reselecting target id.  The initiator
        !          2702:         // id must be stripped and the remaining bit converted to a bit number
        !          2703:         // to get the target id.
        !          2704:         //
        !          2705: 
        !          2706:         luId &= ~deviceExtension->AdapterBusIdMask;
        !          2707:         WHICH_BIT(luId, targetId);
        !          2708: 
        !          2709:         luId = SCSI_READ(deviceExtension->Adapter, Fifo);
        !          2710: 
        !          2711:         //
        !          2712:         // The logical unit id is stored in the low-order 3 bits of the
        !          2713:         // IDENTIFY message, so the upper bits must be stripped off the
        !          2714:         // byte read from the FIFO to get the logical unit number.
        !          2715:         //
        !          2716: 
        !          2717:         luId &= SCSI_MAXIMUM_LOGICAL_UNITS - 1;
        !          2718: 
        !          2719:         luExtension = ScsiPortGetLogicalUnit( deviceExtension,
        !          2720:                                               0,
        !          2721:                                               targetId,
        !          2722:                                               luId
        !          2723:                                               );
        !          2724: 
        !          2725:         //
        !          2726:         // Check to that this is a valid logical unit.
        !          2727:         //
        !          2728: 
        !          2729:         if (luExtension == NULL) {
        !          2730: 
        !          2731:             NcrPrint((0, "NcrInterruptServiceRoutine: Reselection Failed.\n"));
        !          2732:             NcrDumpState(deviceExtension);
        !          2733: 
        !          2734: 
        !          2735:             ScsiPortLogError(
        !          2736:                 deviceExtension,                    //  HwDeviceExtension,
        !          2737:                 NULL,                               //  Srb
        !          2738:                 0,                                  //  PathId,
        !          2739:                 targetId,                           //  TargetId,
        !          2740:                 luId,                               //  Lun,
        !          2741:                 SP_INVALID_RESELECTION,             //  ErrorCode,
        !          2742:                 4                                   //  UniqueId
        !          2743:                 );
        !          2744: 
        !          2745:             //
        !          2746:             // Send an abort message.  Put the message in the buffer, set the
        !          2747:             // state,  indicate that a disconnect is expected after this, and
        !          2748:             // set the attention signal.
        !          2749:             //
        !          2750: 
        !          2751:             deviceExtension->MessageBuffer[0] = SCSIMESS_ABORT;
        !          2752:             deviceExtension->MessageCount = 1;
        !          2753:             deviceExtension->MessageSent = 0;
        !          2754:             deviceExtension->AdapterState = MessageOut;
        !          2755:             deviceExtension->AdapterFlags &= ~PD_ADAPTER_DISCONNECT_MASK;
        !          2756:             deviceExtension->AdapterFlags |= PD_MESSAGE_OUT_VALID |
        !          2757:                 PD_DISCONNECT_EXPECTED;
        !          2758: 
        !          2759:             setAttention = TRUE;
        !          2760: 
        !          2761:         } else {
        !          2762: 
        !          2763:             //
        !          2764:             // Everything looks ok.
        !          2765:             //
        !          2766: 
        !          2767:             //
        !          2768:             // A reselection has been completed.  Set the active logical
        !          2769:             // unit, restore the active data pointer, and set the state.
        !          2770:             // In addition, any adpater flags set by a pending select
        !          2771:             // must be cleared using the disconnect mask.
        !          2772:             //
        !          2773: 
        !          2774:             deviceExtension->AdapterFlags &= ~PD_ADAPTER_DISCONNECT_MASK;
        !          2775:             deviceExtension->ActiveLogicalUnit = luExtension;
        !          2776:             deviceExtension->AdapterState = Reselected;
        !          2777:             deviceExtension->MessageCount = 0;
        !          2778: 
        !          2779:             srb = luExtension->ActiveLuRequest;
        !          2780:             deviceExtension->ActiveLuRequest = srb;
        !          2781: 
        !          2782:             if (srb == NULL) {
        !          2783: 
        !          2784:                 //
        !          2785:                 // This must be a reconnect for a tagged request.
        !          2786:                 // Indicate a queue tag message is expected next and save
        !          2787:                 // the target and logical unit ids.
        !          2788:                 //
        !          2789: 
        !          2790:                 deviceExtension->AdapterFlags |= PD_EXPECTING_QUEUE_TAG;
        !          2791:                 deviceExtension->Lun = luId;
        !          2792:             } else {
        !          2793: 
        !          2794:                 deviceExtension->ActiveDataPointer = SRB_EXT(srb)->SavedDataPointer;
        !          2795:                 deviceExtension->ActiveDataLength = SRB_EXT(srb)->SavedDataLength;
        !          2796: 
        !          2797:             }
        !          2798:         }
        !          2799: 
        !          2800:         //
        !          2801:         // The bus is waiting for the message to be accepted.  The attention
        !          2802:         // signal will be set if this is not a valid reselection.  Finally,
        !          2803:         // the synchronous data tranfer parameters need to be set in case a
        !          2804:         // data transfer is done.
        !          2805:         //
        !          2806: 
        !          2807:         deviceExtension->TargetId = targetId;
        !          2808:         NcrAcceptMessage(deviceExtension, setAttention, TRUE);
        !          2809:         deviceExtension->InterruptCount = 0;
        !          2810: 
        !          2811:     } else if (deviceExtension->AdapterInterrupt.FunctionComplete) {
        !          2812: 
        !          2813:         //
        !          2814:         // Check for function complete interrupt if there was not a reselected
        !          2815:         // interrupt.  The function complete interrupt has already been checked
        !          2816:         // in the previous case.
        !          2817:         //
        !          2818:         // The function complete interrupt occurs after the following cases:
        !          2819:         //    A select succeeded
        !          2820:         //    A message byte has been read
        !          2821:         //    A status byte and message byte have been read when in the
        !          2822:         //      command complete state.
        !          2823:         //    A reselection (handled above)
        !          2824:         //
        !          2825:         // Switch on the state current state of the bus to determine what
        !          2826:         // action should be taken now the function has completed.
        !          2827:         //
        !          2828: 
        !          2829:         switch (deviceExtension->AdapterState) {
        !          2830:         case AttemptingSelect:
        !          2831: 
        !          2832:             //
        !          2833:             // The target was successfully selected.  Set the active
        !          2834:             // logical unit field, clear the next logical unit, and
        !          2835:             // notify the OS-dependent driver that a new request can
        !          2836:             // be accepted.  The state is set to MessageOut since is
        !          2837:             // the next thing done after a selection.
        !          2838:             //
        !          2839: 
        !          2840:             deviceExtension->ActiveLogicalUnit = ScsiPortGetLogicalUnit(
        !          2841:                 deviceExtension,
        !          2842:                 deviceExtension->NextSrbRequest->PathId,
        !          2843:                 deviceExtension->NextSrbRequest->TargetId,
        !          2844:                 deviceExtension->NextSrbRequest->Lun
        !          2845:                 );
        !          2846: 
        !          2847:             srb = deviceExtension->NextSrbRequest;
        !          2848:             deviceExtension->ActiveLuRequest = srb;
        !          2849: 
        !          2850:             //
        !          2851:             // Restore the data pointers.
        !          2852:             //
        !          2853: 
        !          2854:             deviceExtension->ActiveDataPointer = SRB_EXT(srb)->SavedDataPointer;
        !          2855:             deviceExtension->ActiveDataLength = SRB_EXT(srb)->SavedDataLength;
        !          2856: 
        !          2857:             //
        !          2858:             // The next request has now become the active request.
        !          2859:             // Clear the state associated with the next request and ask for
        !          2860:             // another one to start.
        !          2861:             //
        !          2862: 
        !          2863:             deviceExtension->AdapterFlags &= ~PD_PENDING_START_IO;
        !          2864:             deviceExtension->NextSrbRequest = NULL;
        !          2865:             deviceExtension->AdapterState = MessageOut;
        !          2866: 
        !          2867:             //
        !          2868:             // If this was a tagged request then indicate that the next
        !          2869:             // request for this lu may be sent.
        !          2870:             //
        !          2871: 
        !          2872:             if (deviceExtension->AdapterFlags & PD_TAGGED_SELECT) {
        !          2873: 
        !          2874:                 ScsiPortNotification(
        !          2875:                     NextLuRequest,
        !          2876:                     deviceExtension,
        !          2877:                     srb->PathId,
        !          2878:                     srb->TargetId,
        !          2879:                     srb->Lun
        !          2880:                     );
        !          2881: 
        !          2882:             } else {
        !          2883: 
        !          2884:                 ScsiPortNotification(
        !          2885:                     NextRequest,
        !          2886:                     deviceExtension,
        !          2887:                     NULL
        !          2888:                     );
        !          2889: 
        !          2890:             }
        !          2891: 
        !          2892:             break;
        !          2893: 
        !          2894:         case CommandComplete:
        !          2895: 
        !          2896:             //
        !          2897:             // The FIFO contains the status byte and a message byte.  Save the
        !          2898:             // status byte and set the state to look like MessageIn, then fall
        !          2899:             // through to the message-in state.
        !          2900:             //
        !          2901: 
        !          2902:             srb = deviceExtension->ActiveLuRequest;
        !          2903: 
        !          2904:             ASSERT(deviceExtension->NextSrbRequest != srb);
        !          2905: 
        !          2906:             srb->ScsiStatus = SCSI_READ(
        !          2907:                 deviceExtension->Adapter,
        !          2908:                 Fifo
        !          2909:                 );
        !          2910: 
        !          2911:             SRB_EXT(srb)->SrbExtensionFlags |= PD_STATUS_VALID;
        !          2912: 
        !          2913:             deviceExtension->AdapterState = MessageIn;
        !          2914:             deviceExtension->MessageCount = 0;
        !          2915:             deviceExtension->AdapterFlags &= ~PD_MESSAGE_OUT_VALID;
        !          2916: 
        !          2917:             //
        !          2918:             // Fall through and process the message byte in the FIFO.
        !          2919:             //
        !          2920: 
        !          2921:         case MessageIn:
        !          2922: 
        !          2923:             //
        !          2924:             // A message byte has been received. Store it in the message buffer
        !          2925:             // and call message decode to determine what to do.  The message
        !          2926:             // byte will either be accepted, or cause a message to be sent.
        !          2927:             // A message-out is indicated to the target by setting the ATN
        !          2928:             // line before sending the SCSI protocol chip the MESSAGE_ACCEPTED
        !          2929:             // command.
        !          2930:             //
        !          2931: 
        !          2932:             deviceExtension->MessageBuffer[deviceExtension->MessageCount++] =
        !          2933:                 SCSI_READ( deviceExtension->Adapter, Fifo );
        !          2934: 
        !          2935:             if (NcrMessageDecode( deviceExtension )) {
        !          2936: 
        !          2937:                 //
        !          2938:                 // NcrMessageDecode returns TRUE if there is a message to be
        !          2939:                 // sent out.  This message will normally be a MESSAGE REJECT
        !          2940:                 // or a  SYNCHRONOUS DATA TRANSFER REQUEST.  In any case, the
        !          2941:                 // message has been set by NcrMessageDecode.  All that needs
        !          2942:                 // to be done here is set the ATN signal and set
        !          2943:                 // PD_MESSAGE_OUT_VALID in the adapter flags.
        !          2944:                 //
        !          2945: 
        !          2946:                 deviceExtension->AdapterFlags |= PD_MESSAGE_OUT_VALID;
        !          2947:                 setAttention = TRUE;
        !          2948:             } else {
        !          2949:                 setAttention = FALSE;
        !          2950:             }
        !          2951: 
        !          2952:             //
        !          2953:             // In either case, tell the SCSI protocol chip to acknowlege or
        !          2954:             // accept the message. The synchronous data transfer parameters
        !          2955:             // do not need to be set.
        !          2956:             //
        !          2957: 
        !          2958:             NcrAcceptMessage( deviceExtension, setAttention, FALSE);
        !          2959:             break;
        !          2960: 
        !          2961:         default:
        !          2962: 
        !          2963:             //
        !          2964:             // A function complete should not occur while in any other states.
        !          2965:             //
        !          2966: 
        !          2967:             NcrPrint((0, "NcrInterruptServiceRoutine: Unexpected function complete interrupt.\n"));
        !          2968:             NcrDumpState(deviceExtension);
        !          2969: 
        !          2970:         }
        !          2971:     }
        !          2972: 
        !          2973: 
        !          2974:     //
        !          2975:     // Check for a bus service interrupt. This interrupt indicates the target
        !          2976:     // is requesting some form of bus transfer. The bus transfer type is
        !          2977:     // determined by the bus phase.
        !          2978:     //
        !          2979: 
        !          2980:     if (deviceExtension->AdapterInterrupt.BusService) {
        !          2981: 
        !          2982:         luExtension = deviceExtension->ActiveLogicalUnit;
        !          2983: 
        !          2984:        if (luExtension == NULL) {
        !          2985: 
        !          2986:             //
        !          2987:             // There should never be an bus service interrupt without an
        !          2988:             // active locgial unit.  The bus or the chip is really messed up.
        !          2989:             // Reset the bus and return.
        !          2990:             //
        !          2991: 
        !          2992:             NcrPrint((0, "NcrInterruptServiceRoutine: Unexpected Bus service interrupt.\n"));
        !          2993:             NcrDumpState(deviceExtension);
        !          2994: 
        !          2995:             NcrResetScsiBusInternal(deviceExtension, 0);
        !          2996:             NcrInitializeAdapter(deviceExtension);
        !          2997: 
        !          2998:             NcrLogError(deviceExtension, SP_PROTOCOL_ERROR, 6);
        !          2999: 
        !          3000:             return(TRUE);
        !          3001:         }
        !          3002: 
        !          3003:         srb = deviceExtension->ActiveLuRequest;
        !          3004: 
        !          3005:         //
        !          3006:         // If there is no current srb request then the bus service interrupt
        !          3007:         // must be a message in with a tag.
        !          3008:         //
        !          3009: 
        !          3010:         if (deviceExtension->AdapterFlags & PD_EXPECTING_QUEUE_TAG &&
        !          3011:             deviceExtension->AdapterStatus.Phase != MESSAGE_IN ) {
        !          3012: 
        !          3013:             //
        !          3014:             // A bus service interrupt occured when a queue tag message
        !          3015:             // was exepected.  Is a protocol error by the target reset the
        !          3016:             // bus.
        !          3017:             //
        !          3018: 
        !          3019:             NcrPrint((0, "NcrInterruptServiceRoutine: Unexpected Bus service interrupt when queue tag expected.\n"));
        !          3020:             NcrDumpState(deviceExtension);
        !          3021: 
        !          3022:             NcrResetScsiBusInternal(deviceExtension, 0);
        !          3023:             NcrInitializeAdapter(deviceExtension);
        !          3024: 
        !          3025:             NcrLogError(deviceExtension, SP_PROTOCOL_ERROR, 13);
        !          3026: 
        !          3027:             return(TRUE);
        !          3028: 
        !          3029:         }
        !          3030: 
        !          3031:         //
        !          3032:         // The bus is changing phases or needs more data. Generally, the target
        !          3033:         // can change bus phase at any time:  in particular, in the middle of
        !          3034:         // a data transfer.  The initiator must be able to restart a transfer
        !          3035:         // where it left off. To do this it must know how much data was
        !          3036:         // transferred. If the previous state was a data transfer, then the
        !          3037:         // amount of data transferred needs to be determined, saved and
        !          3038:         // the DMA flushed.
        !          3039:         //
        !          3040: 
        !          3041:         if (deviceExtension->AdapterState == DataTransfer) {
        !          3042:             SCSI_FIFO_FLAGS fifoFlags;
        !          3043: 
        !          3044:             //
        !          3045:             // Figure out how many bytes have been transferred based on the
        !          3046:             // original transfer count stored in the ActiveLengthField,
        !          3047:             // SCSI protocol chip transfer counters, and
        !          3048:             // the number of bytes in the FIFO.  The normal case is when all
        !          3049:             // the bytes have been transferred so check for that using the
        !          3050:             // TerminalCount bit in the status field.
        !          3051:             //
        !          3052: 
        !          3053:             i = 0;
        !          3054: 
        !          3055:             if (!deviceExtension->AdapterStatus.TerminalCount) {
        !          3056: 
        !          3057:                 //
        !          3058:                 // Read bits 23-16 if this chip has that register.
        !          3059:                 //
        !          3060: 
        !          3061:                 if (deviceExtension->ChipType == Fas216) {
        !          3062: 
        !          3063:                     i = (SCSI_READ(deviceExtension->Adapter,
        !          3064:                                         TransferCountPage
        !          3065:                                         )) << 16;
        !          3066: 
        !          3067:                 }
        !          3068: 
        !          3069:                 //
        !          3070:                 // Read the current value of the tranfer count registers;
        !          3071:                 //
        !          3072: 
        !          3073:                 i |= (SCSI_READ(deviceExtension->Adapter, TransferCountHigh)) << 8;
        !          3074:                 i |= SCSI_READ(deviceExtension->Adapter, TransferCountLow );
        !          3075: 
        !          3076:                 //
        !          3077:                 // A value of zero in i and TerminalCount clear indicates
        !          3078:                 // that the transfer length was 64K and that no bytes were
        !          3079:                 // transferred. Set i to 64K.
        !          3080:                 //
        !          3081: 
        !          3082:                 if (i == 0) {
        !          3083:                     i = 0x10000;
        !          3084:                 }
        !          3085: 
        !          3086:             }
        !          3087: 
        !          3088:             //
        !          3089:             // If this is a write then there may still be some bytes in the
        !          3090:             // FIFO which have yet to be transferred to the target.
        !          3091:             //
        !          3092: 
        !          3093:             if (srb->SrbFlags & SRB_FLAGS_DATA_OUT) {
        !          3094:                 *((PUCHAR) &fifoFlags) = SCSI_READ(deviceExtension->Adapter,
        !          3095:                                                    FifoFlags
        !          3096:                                                    );
        !          3097:                 i += fifoFlags.ByteCount;
        !          3098: 
        !          3099: 
        !          3100:                 if (i == 1 && deviceExtension->ChipType == Fas216) {
        !          3101: 
        !          3102:                     //
        !          3103:                     // This is a chip bug.  If the bus state is still data
        !          3104:                     // out then tell the chip to transfer one more byte.
        !          3105:                     //
        !          3106: 
        !          3107:                     NcrPrint((1, "NcrInterruptServiceRoutine: One byte left!\n"));
        !          3108: 
        !          3109:                     //
        !          3110:                     // Set the transfer count.
        !          3111:                     //
        !          3112: 
        !          3113:                     SCSI_WRITE( deviceExtension->Adapter,
        !          3114:                                 TransferCountLow,
        !          3115:                                 1
        !          3116:                                 );
        !          3117:                     SCSI_WRITE( deviceExtension->Adapter,
        !          3118:                                 TransferCountHigh,
        !          3119:                                 0
        !          3120:                                 );
        !          3121: 
        !          3122:                     SCSI_WRITE(deviceExtension->Adapter,
        !          3123:                                TransferCountPage,
        !          3124:                                0
        !          3125:                                );
        !          3126: 
        !          3127:                      SCSI_WRITE(deviceExtension->Adapter, Command, TRANSFER_INFORMATION);
        !          3128: 
        !          3129:                      return(TRUE);
        !          3130:                 }
        !          3131: 
        !          3132:                 //
        !          3133:                 // The chip leaves some data in the FIFO, so clear the
        !          3134:                 // FIFO so there is not garbage left in it.
        !          3135:                 //
        !          3136: 
        !          3137:                 SCSI_WRITE(deviceExtension->Adapter, Command, FLUSH_FIFO);
        !          3138:             }
        !          3139: 
        !          3140:             //
        !          3141:             // i now contains the number of bytes to be transferred.
        !          3142:             // Check to see if this the maximum that has be transferred so far,
        !          3143:             // and update the active data pointer and the active length.
        !          3144:             //
        !          3145: 
        !          3146:             if (srb->DataTransferLength - i >
        !          3147:                 SRB_EXT(srb)->MaximumTransferLength) {
        !          3148:                 SRB_EXT(srb)->MaximumTransferLength = srb->DataTransferLength -
        !          3149:                     i;
        !          3150:             }
        !          3151: 
        !          3152:             deviceExtension->ActiveDataPointer +=
        !          3153:                 deviceExtension->ActiveDataLength - i;
        !          3154:             deviceExtension->ActiveDataLength = i;
        !          3155: 
        !          3156:             //
        !          3157:             // Flush the DMA to ensure all the bytes are transferred.
        !          3158:             //
        !          3159: 
        !          3160:             deviceExtension->AdapterFlags &= ~PD_PENDING_DATA_TRANSFER;
        !          3161:             ScsiPortFlushDma(deviceExtension);
        !          3162: 
        !          3163:         } else if (deviceExtension->AdapterState == DisconnectExpected) {
        !          3164: 
        !          3165:             //
        !          3166:             // This is an error; however, some contollers attempt to read more
        !          3167:             // message bytes even after a message indicating a disconnect.
        !          3168:             // If the request is for a message transfer and extra bytes
        !          3169:             // are expected, then allow the transfer; otherwise, reset the bus.
        !          3170:             //
        !          3171: 
        !          3172:             if (!(deviceExtension->AdapterFlags & PD_POSSIBLE_EXTRA_MESSAGE_OUT)
        !          3173:                 || (deviceExtension->AdapterStatus.Phase != MESSAGE_OUT &&
        !          3174:                 deviceExtension->AdapterStatus.Phase != MESSAGE_IN)) {
        !          3175: 
        !          3176:                 //
        !          3177:                 // If a disconnect was expected and a bus service interrupt was
        !          3178:                 // detected, then a SCSI protocol error has been detected and the
        !          3179:                 // SCSI bus should be reset to clear the condition.
        !          3180:                 //
        !          3181: 
        !          3182:                 NcrPrint((0, "NcrInterruptServiceRoutine: Bus request while disconnect expected.\n"));
        !          3183:                 NcrDumpState(deviceExtension);
        !          3184: 
        !          3185:                 NcrResetScsiBusInternal(deviceExtension, 0);
        !          3186:                 NcrInitializeAdapter(deviceExtension);
        !          3187: 
        !          3188:                 NcrLogError(deviceExtension, SP_PROTOCOL_ERROR, 7);
        !          3189: 
        !          3190:                 return(TRUE);
        !          3191:             } else {
        !          3192: 
        !          3193:                 //
        !          3194:                 // Make sure the disconnect-expected flag is set.
        !          3195:                 //
        !          3196: 
        !          3197:                 deviceExtension->AdapterFlags |= PD_DISCONNECT_EXPECTED;
        !          3198:             }
        !          3199:         } else if (deviceExtension->AdapterState == MessageOut) {
        !          3200: 
        !          3201:             //
        !          3202:             // The SCSI protocol chip indicates that the message has been sent;
        !          3203:             // however, the target may need to reread the message or there
        !          3204:             // may be more messages to send.  This condition is indicated by a
        !          3205:             // message-out bus phase; otherwise, the message has been accepted
        !          3206:             // by the target.  If message has been accepted then check to see
        !          3207:             // if any special processing is necessary.  Note that the driver
        !          3208:             // state is set to MessageOut after the PD_DISCONNECT_EXPECTED is
        !          3209:             // set, or after a selection.  So it is only necessary to check for
        !          3210:             // PD_DISCONNECT_EXPECTED when the driver state is currently in
        !          3211:             // MessageOut.
        !          3212:             //
        !          3213: 
        !          3214:             if (deviceExtension->AdapterFlags & (PD_DISCONNECT_EXPECTED |
        !          3215:                 PD_SYNCHRONOUS_TRANSFER_SENT | PD_SYNCHRONOUS_RESPONSE_SENT) &&
        !          3216:                 deviceExtension->AdapterStatus.Phase != MESSAGE_OUT &&
        !          3217:                 deviceExtension->AdapterStatus.Phase != MESSAGE_IN) {
        !          3218: 
        !          3219:                 if (deviceExtension->AdapterFlags & PD_DISCONNECT_EXPECTED) {
        !          3220: 
        !          3221:                     //
        !          3222:                     // If a disconnect was expected and a bus service interrupt was
        !          3223:                     // detected, then a SCSI protocol error has been detected and the
        !          3224:                     // SCSI bus should be reset to clear the condition.
        !          3225:                     //
        !          3226: 
        !          3227:                     NcrPrint((0, "NcrInterruptServiceRoutine: Bus request while disconnect expected after message-out.\n"));
        !          3228:                     NcrDumpState(deviceExtension);
        !          3229: 
        !          3230:                     NcrResetScsiBusInternal(deviceExtension, 0);
        !          3231:                     NcrInitializeAdapter(deviceExtension);
        !          3232: 
        !          3233:                     NcrLogError(deviceExtension, SP_PROTOCOL_ERROR, 8);
        !          3234: 
        !          3235:                     return(TRUE);
        !          3236: 
        !          3237:                 } else if (deviceExtension->AdapterFlags &
        !          3238:                            PD_SYNCHRONOUS_TRANSFER_SENT) {
        !          3239: 
        !          3240:                     //
        !          3241:                     // The controller ignored the synchronous transfer message.
        !          3242:                     // Treat it as a rejection and clear the necessary state.
        !          3243:                     //
        !          3244: 
        !          3245:                     deviceExtension->TargetState[deviceExtension->TargetId]
        !          3246:                         .TargetFlags |=
        !          3247:                         PD_SYNCHRONOUS_NEGOTIATION_DONE | PD_DO_NOT_NEGOTIATE;
        !          3248:                     deviceExtension->AdapterFlags &=
        !          3249:                         ~(PD_SYNCHRONOUS_RESPONSE_SENT |
        !          3250:                         PD_SYNCHRONOUS_TRANSFER_SENT);
        !          3251:                 } else if (deviceExtension->AdapterFlags &
        !          3252:                            PD_SYNCHRONOUS_RESPONSE_SENT) {
        !          3253: 
        !          3254:                     //
        !          3255:                     // The target controller accepted the negotiation. Set
        !          3256:                     // the done flag in the logical unit and clear the
        !          3257:                     // negotiation flags in the adapter.
        !          3258:                     //
        !          3259: 
        !          3260:                     deviceExtension->TargetState[deviceExtension->TargetId].TargetFlags |=
        !          3261:                         PD_SYNCHRONOUS_NEGOTIATION_DONE | PD_DO_NOT_NEGOTIATE;
        !          3262:                     deviceExtension->AdapterFlags &=
        !          3263:                         ~(PD_SYNCHRONOUS_RESPONSE_SENT |
        !          3264:                         PD_SYNCHRONOUS_TRANSFER_SENT);
        !          3265: 
        !          3266:                 }
        !          3267:             }
        !          3268:         }
        !          3269: 
        !          3270:         //
        !          3271:         // If the bus phase is not DATA_IN then the FIFO may need to be
        !          3272:         // flushed.  The FIFO cannot be flushed while the bus is in the
        !          3273:         // DATA_IN phase because the FIFO already has data bytes in it.
        !          3274:         // The only case where a target can legally switch phases while
        !          3275:         // there are message bytes in the FIFO to the MESSAGE_OUT bus
        !          3276:         // phase. If the target leaves message bytes and attempts to
        !          3277:         // goto a DATA_IN phase, then the transfer will appear to overrun
        !          3278:         // and be detected as an error.
        !          3279:         //
        !          3280: 
        !          3281:         if (deviceExtension->AdapterStatus.Phase != DATA_IN) {
        !          3282:             SCSI_WRITE(deviceExtension->Adapter, Command, FLUSH_FIFO);
        !          3283:         }
        !          3284: 
        !          3285:         //
        !          3286:         // Decode the current bus phase.
        !          3287:         //
        !          3288: 
        !          3289:         switch (deviceExtension->AdapterStatus.Phase) {
        !          3290: 
        !          3291:         case COMMAND_OUT:
        !          3292: 
        !          3293:             //
        !          3294:             // Fill the FIFO with the commnad and tell the SCSI protocol chip
        !          3295:             // to go.
        !          3296:             //
        !          3297: 
        !          3298:             for (i = 0; i < srb->CdbLength; i++) {
        !          3299:                 SCSI_WRITE( deviceExtension->Adapter,
        !          3300:                             Fifo,
        !          3301:                             srb->Cdb[i]
        !          3302:                             );
        !          3303:             }
        !          3304: 
        !          3305:             SCSI_WRITE( deviceExtension->Adapter,
        !          3306:                         Command,
        !          3307:                         TRANSFER_INFORMATION
        !          3308:                         );
        !          3309: 
        !          3310:             deviceExtension->AdapterState = CommandOut;
        !          3311: 
        !          3312:             break;
        !          3313: 
        !          3314:         case STATUS_IN:
        !          3315: 
        !          3316:             //
        !          3317:             // Setup of the SCSI protocol chip to read in the status and the
        !          3318:             // following message byte, and set the adapter state.
        !          3319:             //
        !          3320: 
        !          3321:             SCSI_WRITE( deviceExtension->Adapter, Command, COMMAND_COMPLETE );
        !          3322:             deviceExtension->AdapterState = CommandComplete;
        !          3323: 
        !          3324:             break;
        !          3325: 
        !          3326:         case MESSAGE_OUT:
        !          3327: 
        !          3328:             //
        !          3329:             // The target is requesting a message-out.  There are three
        !          3330:             // possible cases.  First, the target is improperly requesting
        !          3331:             // a message. Second, a message has been sent, but the target
        !          3332:             // could not read it properly.  Third, a message has been
        !          3333:             // partially sent and the target is requesting the remainder
        !          3334:             // of the message.
        !          3335:             //
        !          3336:             // The first case is indicated when the MessageCount is zero or
        !          3337:             // the message-out flag is not set.
        !          3338:             //
        !          3339: 
        !          3340:             if ( deviceExtension->MessageCount == 0 ||
        !          3341:                 !(deviceExtension->AdapterFlags & PD_MESSAGE_OUT_VALID)) {
        !          3342: 
        !          3343:                 //
        !          3344:                 // If extra message-outs are possible then just send a NOP
        !          3345:                 // message.
        !          3346: 
        !          3347:                 if (deviceExtension->AdapterFlags &
        !          3348:                     PD_POSSIBLE_EXTRA_MESSAGE_OUT) {
        !          3349: 
        !          3350:                     //
        !          3351:                     // Set the message to NOP and clear the extra message
        !          3352:                     // flag.  This is a hack for controllers that do not
        !          3353:                     // properly read the entire message.
        !          3354:                     //
        !          3355: 
        !          3356:                     deviceExtension->MessageBuffer[0] = SCSIMESS_NO_OPERATION;
        !          3357:                     deviceExtension->AdapterFlags &=
        !          3358:                         ~PD_POSSIBLE_EXTRA_MESSAGE_OUT;
        !          3359:                 } else {
        !          3360: 
        !          3361:                     //
        !          3362:                     // Send an INITIATOR DETECTED ERROR message.
        !          3363:                     //
        !          3364: 
        !          3365:                     deviceExtension->MessageBuffer[0] =
        !          3366:                         SCSIMESS_INIT_DETECTED_ERROR;
        !          3367:                     NcrLogError(deviceExtension, SP_PROTOCOL_ERROR, 9);
        !          3368:                     NcrPrint((0, "NcrInterruptServiceRoutine: Unexpected message-out request\n"));
        !          3369:                     NcrDumpState(deviceExtension);
        !          3370: 
        !          3371:                 }
        !          3372: 
        !          3373:                 deviceExtension->MessageCount = 1;
        !          3374:                 deviceExtension->MessageSent = 0;
        !          3375:                 deviceExtension->AdapterState = MessageOut;
        !          3376: 
        !          3377:             }
        !          3378: 
        !          3379:             //
        !          3380:             // The second case is indicated when MessageCount and MessageSent
        !          3381:             // are equal and nonzero.
        !          3382:             //
        !          3383: 
        !          3384:             if (deviceExtension->MessageCount == deviceExtension->MessageSent){
        !          3385: 
        !          3386:                 //
        !          3387:                 // The message needs to be resent, so set ATN, clear MessageSent
        !          3388:                 // and fall through to the next case.
        !          3389:                 //
        !          3390: 
        !          3391:                 SCSI_WRITE(deviceExtension->Adapter, Command, SET_ATTENTION);
        !          3392:                 deviceExtension->MessageSent = 0;
        !          3393:             }
        !          3394: 
        !          3395:             if (deviceExtension->MessageCount != deviceExtension->MessageSent){
        !          3396: 
        !          3397:                 //
        !          3398:                 // The ATTENTION signal needs to be set if the current state
        !          3399:                 // is not MessageOut.
        !          3400:                 //
        !          3401: 
        !          3402:                 if (deviceExtension->AdapterState != MessageOut) {
        !          3403: 
        !          3404:                     SCSI_WRITE(
        !          3405:                         deviceExtension->Adapter,
        !          3406:                         Command,
        !          3407:                         SET_ATTENTION
        !          3408:                         );
        !          3409:                 }
        !          3410: 
        !          3411:                 //
        !          3412:                 // There is more message to send.  Fill the FIFO with the
        !          3413:                 // message and tell the SCSI protocol chip to transfer the
        !          3414:                 // message.
        !          3415:                 //
        !          3416: 
        !          3417:                 for (;
        !          3418:                      deviceExtension->MessageSent <
        !          3419:                      deviceExtension->MessageCount;
        !          3420:                      deviceExtension->MessageSent++ ) {
        !          3421: 
        !          3422:                     SCSI_WRITE(deviceExtension->Adapter,
        !          3423:                                Fifo,
        !          3424:                                deviceExtension->
        !          3425:                                MessageBuffer[deviceExtension->MessageSent]
        !          3426:                                );
        !          3427: 
        !          3428:                 }
        !          3429: 
        !          3430:                 SCSI_WRITE(deviceExtension->Adapter,
        !          3431:                            Command,
        !          3432:                            TRANSFER_INFORMATION
        !          3433:                            );
        !          3434: 
        !          3435:             }
        !          3436: 
        !          3437:             break;
        !          3438: 
        !          3439:         case MESSAGE_IN:
        !          3440: 
        !          3441:             //
        !          3442:             // If this is the first byte of the message then initialize
        !          3443:             // MessageCount and the adapter state.  The message buffer
        !          3444:             // cannot overflow because the message decode function will
        !          3445:             // take care of the message before the buffer is full.
        !          3446:             // The SCSI protocol chip will interrupt for each message
        !          3447:             // byte.
        !          3448:             //
        !          3449: 
        !          3450:             if ( deviceExtension->AdapterState != MessageIn &&
        !          3451:                  deviceExtension->AdapterState != MessageAccepted ) {
        !          3452: 
        !          3453:                 deviceExtension->AdapterFlags &= ~PD_MESSAGE_OUT_VALID;
        !          3454:                 deviceExtension->MessageCount = 0;
        !          3455:             }
        !          3456: 
        !          3457:             deviceExtension->AdapterState = MessageIn;
        !          3458: 
        !          3459:             SCSI_WRITE( deviceExtension->Adapter,
        !          3460:                         Command,
        !          3461:                         TRANSFER_INFORMATION
        !          3462:                         );
        !          3463: 
        !          3464:             break;
        !          3465: 
        !          3466:         case DATA_OUT:
        !          3467:         case DATA_IN:
        !          3468: 
        !          3469:             //
        !          3470:             // Check that the transfer direction is ok, setup the DMA, set
        !          3471:             // the synchronous transfer parameter, and tell the chip to go.
        !          3472:             // Also check that there is still data to be transferred.
        !          3473:             //
        !          3474: 
        !          3475:             if ((!(srb->SrbFlags & SRB_FLAGS_DATA_IN) &&
        !          3476:                 deviceExtension->AdapterStatus.Phase == DATA_IN) ||
        !          3477: 
        !          3478:                 (!(srb->SrbFlags & SRB_FLAGS_DATA_OUT) &&
        !          3479:                 deviceExtension->AdapterStatus.Phase == DATA_OUT) ||
        !          3480: 
        !          3481:                 deviceExtension->ActiveDataLength == 0 ) {
        !          3482: 
        !          3483:                 //
        !          3484:                 // The data direction is incorrect. Reset the bus to clear
        !          3485:                 // things up.
        !          3486:                 //
        !          3487: 
        !          3488:                 NcrPrint((0, "NcrInterruptServiceRoutine: Illegal transfer direction.\n"));
        !          3489:                 NcrDumpState(deviceExtension);
        !          3490: 
        !          3491:                 NcrResetScsiBusInternal(deviceExtension, 0);
        !          3492:                 NcrInitializeAdapter(deviceExtension);
        !          3493: 
        !          3494:                 NcrLogError(deviceExtension, SP_PROTOCOL_ERROR, 10);
        !          3495: 
        !          3496:                 return(TRUE);
        !          3497:             }
        !          3498: 
        !          3499:             //
        !          3500:             // Set the transfer count.
        !          3501:             //
        !          3502: 
        !          3503:             SCSI_WRITE( deviceExtension->Adapter,
        !          3504:                         TransferCountLow,
        !          3505:                         (UCHAR) deviceExtension->ActiveDataLength
        !          3506:                         );
        !          3507:             SCSI_WRITE( deviceExtension->Adapter,
        !          3508:                         TransferCountHigh,
        !          3509:                         (UCHAR) (deviceExtension->ActiveDataLength >> 8)
        !          3510:                         );
        !          3511: 
        !          3512:             //
        !          3513:             // Write bits 23-16 if this chip has that register.
        !          3514:             //
        !          3515: 
        !          3516:             if (deviceExtension->ChipType == Fas216) {
        !          3517: 
        !          3518:                 SCSI_WRITE(deviceExtension->Adapter,
        !          3519:                            TransferCountPage,
        !          3520:                            (UCHAR) (deviceExtension->ActiveDataLength >> 16)
        !          3521:                            );
        !          3522: 
        !          3523:             }
        !          3524: 
        !          3525:             //
        !          3526:             // Clear the extra data transfer flags correctly.
        !          3527:             //
        !          3528: 
        !          3529:             if (deviceExtension->AdapterStatus.Phase == DATA_IN) {
        !          3530:                 srb->SrbFlags &= ~SRB_FLAGS_DATA_OUT;
        !          3531:             } else {
        !          3532:                 srb->SrbFlags &= ~SRB_FLAGS_DATA_IN;
        !          3533:             }
        !          3534: 
        !          3535:             //
        !          3536:             // Set up the DMA controller.
        !          3537:             //
        !          3538: 
        !          3539:             deviceExtension->AdapterState = DataTransfer;
        !          3540:             deviceExtension->AdapterFlags |= PD_PENDING_DATA_TRANSFER;
        !          3541: 
        !          3542:             ScsiPortIoMapTransfer( deviceExtension,
        !          3543:                                    srb,
        !          3544:                                    (PVOID) deviceExtension->ActiveDataPointer,
        !          3545:                                    deviceExtension->ActiveDataLength
        !          3546:                                    );
        !          3547: 
        !          3548:             break;
        !          3549: 
        !          3550:         default:
        !          3551: 
        !          3552:             //
        !          3553:             // This phase is illegal and indicates a serious error. Reset the
        !          3554:             // bus to clear the problem.
        !          3555:             //
        !          3556: 
        !          3557:             NcrPrint((0, "NcrInterruptServiceRoutine: Illegal bus state detected.\n"));
        !          3558:             NcrDumpState(deviceExtension);
        !          3559: 
        !          3560:             NcrResetScsiBusInternal(deviceExtension, 0);
        !          3561:             NcrInitializeAdapter(deviceExtension);
        !          3562: 
        !          3563:             NcrLogError(deviceExtension, SP_PROTOCOL_ERROR, 11);
        !          3564: 
        !          3565:             return(TRUE);
        !          3566:         }
        !          3567:     }
        !          3568: 
        !          3569:     //
        !          3570:     // Stall for a short time. This allows interrupt to clear and gives new
        !          3571:     // interrupts a chance to fire.
        !          3572:     //
        !          3573: 
        !          3574:     ScsiPortStallExecution(INTERRUPT_STALL_TIME);
        !          3575: 
        !          3576:     //
        !          3577:     // Make sure there is really an interrupt before reading the other
        !          3578:     // registers, particularly, the interrupt register.
        !          3579:     //
        !          3580: 
        !          3581:     if (deviceExtension->AdapterFlags & PD_NCR_ADAPTER) {
        !          3582: 
        !          3583:         *((PUCHAR) &DmaStatus) = SCSI_READ( deviceExtension->AdapterBase, DmaStatus );
        !          3584: 
        !          3585:         if (DmaStatus.Interrupt == deviceExtension->InterruptPending) {
        !          3586:             *((PUCHAR) &deviceExtension->AdapterStatus) = SCSI_READ( deviceExtension->Adapter, ScsiStatus );
        !          3587:             deviceExtension->InterruptCount++;
        !          3588:             goto NextInterrupt;
        !          3589: 
        !          3590:         }
        !          3591:     } else {
        !          3592: 
        !          3593:         *((PUCHAR) &deviceExtension->AdapterStatus) = SCSI_READ ( deviceExtension->Adapter, ScsiStatus );
        !          3594: 
        !          3595:         if (deviceExtension->AdapterStatus.Interrupt) {
        !          3596:             deviceExtension->InterruptCount++;
        !          3597:             goto NextInterrupt;
        !          3598: 
        !          3599:         }
        !          3600:     }
        !          3601: 
        !          3602:     return(TRUE);
        !          3603: }
        !          3604: 
        !          3605: VOID
        !          3606: NcrLogError(
        !          3607:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !          3608:     IN ULONG ErrorCode,
        !          3609:     IN ULONG UniqueId
        !          3610:     )
        !          3611: /*++
        !          3612: 
        !          3613: Routine Description:
        !          3614: 
        !          3615:     This routine logs an error.
        !          3616: 
        !          3617: Arguments:
        !          3618: 
        !          3619:     DeviceExtension - Supplies a pointer to the device extension for the
        !          3620:         port adapter to which the completing target controller is connected.
        !          3621: 
        !          3622:     ErrorCode - Supplies the error code to log with the error.
        !          3623: 
        !          3624:     UniqueId - Supplies the unique error identifier.
        !          3625: 
        !          3626: Return Value:
        !          3627: 
        !          3628:     None.
        !          3629: 
        !          3630: --*/
        !          3631: {
        !          3632: 
        !          3633:     PSCSI_REQUEST_BLOCK srb;
        !          3634: 
        !          3635:     //
        !          3636:     // Look for a current request in the device extension.
        !          3637:     //
        !          3638: 
        !          3639:     if (DeviceExtension->ActiveLogicalUnit != NULL) {
        !          3640: 
        !          3641:         if (DeviceExtension->ActiveLuRequest != NULL) {
        !          3642: 
        !          3643:             srb = DeviceExtension->ActiveLuRequest;
        !          3644: 
        !          3645:         } else {
        !          3646: 
        !          3647:             srb = DeviceExtension->ActiveLogicalUnit->ActiveSendRequest;
        !          3648: 
        !          3649:         }
        !          3650: 
        !          3651:     } else {
        !          3652: 
        !          3653:         srb = DeviceExtension->NextSrbRequest;
        !          3654: 
        !          3655:     }
        !          3656: 
        !          3657:     //
        !          3658:     // If the srb is NULL, then log the error against the host adapter address.
        !          3659:     //
        !          3660: 
        !          3661:     if (srb == NULL) {
        !          3662: 
        !          3663:         ScsiPortLogError(
        !          3664:             DeviceExtension,                        //  HwDeviceExtension,
        !          3665:             NULL,                                   //  Srb
        !          3666:             0,                                      //  PathId,
        !          3667:             DeviceExtension->AdapterBusId,          //  TargetId,
        !          3668:             0,                                      //  Lun,
        !          3669:             ErrorCode,                              //  ErrorCode,
        !          3670:             UniqueId                                //  UniqueId
        !          3671:             );
        !          3672: 
        !          3673:     } else {
        !          3674: 
        !          3675:         ScsiPortLogError(
        !          3676:             DeviceExtension,                        //  HwDeviceExtension,
        !          3677:             srb,                                    //  Srb
        !          3678:             srb->PathId,                            //  PathId,
        !          3679:             srb->TargetId,                          //  TargetId,
        !          3680:             srb->Lun,                               //  Lun,
        !          3681:             ErrorCode,                              //  ErrorCode,
        !          3682:             UniqueId                                //  UniqueId
        !          3683:             );
        !          3684: 
        !          3685:     }
        !          3686: 
        !          3687: }
        !          3688: 
        !          3689: 
        !          3690: VOID
        !          3691: NcrProcessRequestCompletion(
        !          3692:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension
        !          3693:     )
        !          3694: /*++
        !          3695: 
        !          3696: Routine Description:
        !          3697: 
        !          3698:     This routine does all of checking and state updating necessary when a
        !          3699:     request terminates normally.  It determines what the SrbStatus
        !          3700:     should be and updates the state in the DeviceExtension, the
        !          3701:     logicalUnitExtension and the srb.
        !          3702: 
        !          3703: Arguments:
        !          3704: 
        !          3705:     DeviceExtension - Supplies a pointer to the device extension for the
        !          3706:         port adapter on to which the completing target controller is connected.
        !          3707: 
        !          3708: Return Value:
        !          3709: 
        !          3710:     None.
        !          3711: 
        !          3712: --*/
        !          3713: 
        !          3714: {
        !          3715:     PSPECIFIC_LOGICAL_UNIT_EXTENSION luExtension;
        !          3716:     PSCSI_REQUEST_BLOCK srb;
        !          3717: 
        !          3718:     luExtension = DeviceExtension->ActiveLogicalUnit;
        !          3719:     srb = DeviceExtension->ActiveLuRequest;
        !          3720: 
        !          3721:     ASSERT(DeviceExtension->NextSrbRequest != srb);
        !          3722:     
        !          3723:     if ( srb->ScsiStatus != SCSISTAT_GOOD &&
        !          3724:         srb->ScsiStatus != SCSISTAT_CONDITION_MET &&
        !          3725:         srb->ScsiStatus != SCSISTAT_INTERMEDIATE &&
        !          3726:         srb->ScsiStatus != SCSISTAT_INTERMEDIATE_COND_MET ) {
        !          3727: 
        !          3728:         //
        !          3729:         // Indicate an abnormal status code.
        !          3730:         //
        !          3731: 
        !          3732:         srb->SrbStatus = SRB_STATUS_ERROR;
        !          3733: 
        !          3734:         //
        !          3735:         // Indicate that a INITIATE RECOVERY message was received.  This
        !          3736:         // indicates to the class driver that it must send a TERMINATE
        !          3737:         // RECOVERY message before the logical unit will resume normal
        !          3738:         // operation.
        !          3739:         //
        !          3740: 
        !          3741:         if (SRB_EXT(srb)->SrbExtensionFlags & PD_INITIATE_RECOVERY) {
        !          3742: 
        !          3743:             //
        !          3744:             // Modify the SrbStatus.
        !          3745:             //
        !          3746: 
        !          3747:             srb->SrbStatus = SRB_STATUS_ERROR_RECOVERY;
        !          3748:         }
        !          3749: 
        !          3750:         //
        !          3751:         // If this is a check condition, then clear the synchronous negotiation
        !          3752:         // done flag.  This is done in case the controller was power cycled.
        !          3753:         //
        !          3754: 
        !          3755:         if (srb->ScsiStatus == SCSISTAT_CHECK_CONDITION) {
        !          3756: 
        !          3757:             DeviceExtension->TargetState[srb->TargetId].TargetFlags
        !          3758:                 &= ~PD_SYNCHRONOUS_NEGOTIATION_DONE;
        !          3759: 
        !          3760:         }
        !          3761: 
        !          3762:         //
        !          3763:         // If there is a pending request for this logical unit then return
        !          3764:         // that request with a busy status.  This situation only occurs when
        !          3765:         // command queuing is enabled an a command pending for a logical unit
        !          3766:         // at the same time that an error has occured.  This may be a BUSY,
        !          3767:         // QUEUE FULL or CHECK CONDITION.  The important case is CHECK CONDITION
        !          3768:         // because a contingatent aligance condition has be established and the
        !          3769:         // port driver needs a chance to send a Reqeust Sense before the
        !          3770:         // pending command is started.
        !          3771:         //
        !          3772: 
        !          3773:         if (DeviceExtension->AdapterFlags & PD_PENDING_START_IO &&
        !          3774:             DeviceExtension->NextSrbRequest->PathId == srb->PathId &&
        !          3775:             DeviceExtension->NextSrbRequest->TargetId == srb->TargetId &&
        !          3776:             DeviceExtension->NextSrbRequest->Lun == srb->Lun) {
        !          3777: 
        !          3778:             NcrPrint((1, "NcrProcessRequestCompletion:  Failing request with busy status due to check condition\n"));
        !          3779:             DeviceExtension->NextSrbRequest->SrbStatus =
        !          3780:                 SCSISTAT_CHECK_CONDITION;
        !          3781: 
        !          3782:             DeviceExtension->NextSrbRequest->ScsiStatus = SCSISTAT_BUSY;
        !          3783: 
        !          3784:             ScsiPortNotification(
        !          3785:                 RequestComplete,
        !          3786:                 DeviceExtension,
        !          3787:                 DeviceExtension->NextSrbRequest
        !          3788:                 );
        !          3789: 
        !          3790:             //
        !          3791:             // Make sure the request is not sitting in the logical unit.
        !          3792:             //
        !          3793: 
        !          3794:             if (DeviceExtension->NextSrbRequest == luExtension->ActiveLuRequest) {
        !          3795: 
        !          3796:                 luExtension->ActiveLuRequest = NULL;
        !          3797: 
        !          3798:             } else if (DeviceExtension->NextSrbRequest ==
        !          3799:                 luExtension->ActiveSendRequest) {
        !          3800: 
        !          3801:                 luExtension->ActiveSendRequest = NULL;
        !          3802:             }
        !          3803: 
        !          3804:             DeviceExtension->NextSrbRequest = NULL;
        !          3805:             DeviceExtension->AdapterFlags &= ~PD_PENDING_START_IO;
        !          3806: 
        !          3807:             ScsiPortNotification(
        !          3808:                 NextRequest,
        !          3809:                 DeviceExtension,
        !          3810:                 NULL
        !          3811:                 );
        !          3812: 
        !          3813:         }
        !          3814: 
        !          3815:     } else {
        !          3816: 
        !          3817:         //
        !          3818:         // Everything looks correct so far.
        !          3819:         //
        !          3820: 
        !          3821:         srb->SrbStatus = SRB_STATUS_SUCCESS;
        !          3822: 
        !          3823:         //
        !          3824:         // Make sure that status is valid.
        !          3825:         //
        !          3826: 
        !          3827:         if (!(SRB_EXT(srb)->SrbExtensionFlags & PD_STATUS_VALID)) {
        !          3828: 
        !          3829:             //
        !          3830:             // The status byte is not valid.
        !          3831:             //
        !          3832: 
        !          3833:             srb->SrbStatus = SRB_STATUS_PHASE_SEQUENCE_FAILURE;
        !          3834: 
        !          3835:             //
        !          3836:             // Log the error.
        !          3837:             //
        !          3838: 
        !          3839:             NcrLogError(DeviceExtension, SP_PROTOCOL_ERROR, 12);
        !          3840: 
        !          3841:         }
        !          3842: 
        !          3843: 
        !          3844:     }
        !          3845: 
        !          3846:     //
        !          3847:     // Check that data was transferred to the end of the buffer.
        !          3848:     //
        !          3849: 
        !          3850:     if ( SRB_EXT(srb)->MaximumTransferLength != srb->DataTransferLength ){
        !          3851: 
        !          3852:         //
        !          3853:         // The entire buffer was not transferred.  Update the length
        !          3854:         // and update the status code.
        !          3855:         //
        !          3856: 
        !          3857:         if (srb->SrbStatus == SRB_STATUS_SUCCESS) {
        !          3858: 
        !          3859:             NcrPrint((1, "NcrProcessRequestCompletion: Short transfer, Actual: %x; Expected: %x;\n",
        !          3860:                 SRB_EXT(srb)->MaximumTransferLength,
        !          3861:                 srb->DataTransferLength
        !          3862:                 ));
        !          3863: 
        !          3864:             //
        !          3865:             // If no data was transferred then indicated this was a
        !          3866:             // protocol error rather than a data under/over run.
        !          3867:             //
        !          3868: 
        !          3869:             if (srb->DataTransferLength == 0) {
        !          3870:                 srb->SrbStatus = SRB_STATUS_PHASE_SEQUENCE_FAILURE;
        !          3871:             } else {
        !          3872:                 srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
        !          3873:             }
        !          3874: 
        !          3875:             srb->DataTransferLength = SRB_EXT(srb)->MaximumTransferLength;
        !          3876:         } else {
        !          3877: 
        !          3878:             //
        !          3879:             // Update the length if a check condition was returned.
        !          3880:             //
        !          3881: 
        !          3882:             if (srb->ScsiStatus == SCSISTAT_CHECK_CONDITION) {
        !          3883:                 srb->DataTransferLength = SRB_EXT(srb)->MaximumTransferLength;
        !          3884:             }
        !          3885:         }
        !          3886:     }
        !          3887: 
        !          3888:     if (srb->SrbStatus != SRB_STATUS_SUCCESS) {
        !          3889:             NcrPrint((1, "NcrProcessRequestCompletion: Request failed. ScsiStatus: %x, SrbStatus: %x\n",
        !          3890:             srb->ScsiStatus,
        !          3891:             srb->SrbStatus
        !          3892:             ));
        !          3893:     }
        !          3894: 
        !          3895:     //
        !          3896:     // Clear the request but not the ActiveLogicalUnit since the target has
        !          3897:     // not disconnected from the SCSI bus yet.
        !          3898:     //
        !          3899: 
        !          3900:     DeviceExtension->ActiveLuRequest = NULL;
        !          3901:     luExtension->ActiveLuRequest = NULL;
        !          3902:     luExtension->RetryCount = 0;
        !          3903:     luExtension->LuFlags &= ~PD_LU_COMPLETE_MASK;
        !          3904: }
        !          3905: 
        !          3906: BOOLEAN
        !          3907: NcrResetScsiBus(
        !          3908:     IN PVOID ServiceContext,
        !          3909:     IN ULONG PathId
        !          3910:     )
        !          3911: 
        !          3912: /*++
        !          3913: 
        !          3914: Routine Description:
        !          3915: 
        !          3916:     This function resets the SCSI bus and calls the reset cleanup function.
        !          3917: 
        !          3918: Arguments:
        !          3919: 
        !          3920:     ServiceContext  - Supplies a pointer to the specific device extension.
        !          3921: 
        !          3922:     PathId - Supplies the path id of the bus.
        !          3923: 
        !          3924: Return Value:
        !          3925: 
        !          3926:     TRUE - Indicating the reset is complete.
        !          3927: 
        !          3928: --*/
        !          3929: 
        !          3930: {
        !          3931:     PSPECIFIC_DEVICE_EXTENSION deviceExtension = ServiceContext;
        !          3932: 
        !          3933:     NcrPrint((1, "NcrResetScsiBus: Resetting the SCSI bus.\n"));
        !          3934: 
        !          3935:     //
        !          3936:     // The bus should be reset regardless of what is occurring on the bus or in
        !          3937:     // the chip. The reset SCSI bus command executes immediately.
        !          3938:     //
        !          3939: 
        !          3940:     SCSI_WRITE(deviceExtension->Adapter, Command, RESET_SCSI_BUS);
        !          3941: 
        !          3942:     //
        !          3943:     // Delay the minimum assertion time for a SCSI bus reset to make sure a
        !          3944:     // valid reset signal is sent.
        !          3945:     //
        !          3946: 
        !          3947:     ScsiPortStallExecution( RESET_STALL_TIME );
        !          3948: 
        !          3949:     NcrCleanupAfterReset(deviceExtension, FALSE);
        !          3950:     deviceExtension->AdapterFlags |= PD_EXPECTING_RESET_INTERRUPT;
        !          3951: 
        !          3952:     return(TRUE);
        !          3953: }
        !          3954: 
        !          3955: VOID
        !          3956: NcrResetScsiBusInternal(
        !          3957:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !          3958:     IN ULONG PathId
        !          3959:     )
        !          3960: /*++
        !          3961: 
        !          3962: Routine Description:
        !          3963: 
        !          3964:     This function resets the SCSI bus and notifies the port driver.
        !          3965: 
        !          3966: Arguments:
        !          3967: 
        !          3968:     DeviceExtension  - Supplies a pointer to the specific device extension.
        !          3969: 
        !          3970:     PathId - Supplies the path id of the bus.
        !          3971: 
        !          3972: Return Value:
        !          3973: 
        !          3974:     None
        !          3975: 
        !          3976: --*/
        !          3977: {
        !          3978: 
        !          3979:     ScsiPortNotification(
        !          3980:         ResetDetected,
        !          3981:         DeviceExtension,
        !          3982:         NULL
        !          3983:         );
        !          3984: 
        !          3985:     NcrResetScsiBus(DeviceExtension, 0);
        !          3986: }
        !          3987: 
        !          3988: VOID
        !          3989: NcrSelectTarget(
        !          3990:     IN PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !          3991:     IN PSPECIFIC_LOGICAL_UNIT_EXTENSION LuExtension
        !          3992:     )
        !          3993: /*++
        !          3994: 
        !          3995: Routine Description:
        !          3996: 
        !          3997:     This routine sets up the hardware to select a target.  If a valid message
        !          3998:     is in the message buffer, it will be sent to the target.  If the request
        !          3999:     includes a SCSI command descriptor block, it will also be passed to the
        !          4000:     target.
        !          4001: 
        !          4002: Arguments:
        !          4003: 
        !          4004:     DeviceExtension - Supplies the device extension for this HBA adapter.
        !          4005: 
        !          4006:     LuExtension - Supplies the logical unit extension for the target being
        !          4007:         selected.
        !          4008: 
        !          4009: Return Value:
        !          4010: 
        !          4011:     None
        !          4012: 
        !          4013: --*/
        !          4014: 
        !          4015: {
        !          4016:     PSCSI_REQUEST_BLOCK srb;
        !          4017:     PSPECIFIC_TARGET_EXTENSION targetState;
        !          4018:     SCSI_DMA_STATUS DmaStatus;
        !          4019:     LONG i;
        !          4020: 
        !          4021:     srb = DeviceExtension->NextSrbRequest;
        !          4022: 
        !          4023:     targetState = &DeviceExtension->TargetState[srb->TargetId];
        !          4024: 
        !          4025: #if DBG
        !          4026:     if (NcrDebug) {
        !          4027:         NcrPrint((0, "NcrSelectTarget: Attempting target select.\n"));
        !          4028:     }
        !          4029: #endif
        !          4030:     /* Powerfail Start */
        !          4031: 
        !          4032:     //
        !          4033:     // Set up the SCSI protocol chip to select the target, transfer the
        !          4034:     // IDENTIFY message and the CDB.  This can be done by following steps:
        !          4035:     //
        !          4036:     //        setting the destination register,
        !          4037:     //        filling the FIFO with the IDENTIFY message and the CDB
        !          4038:     //        setting the command register
        !          4039:     //
        !          4040:     // If the chip is not interrupting, then set up for selection.  If the
        !          4041:     // chip is interrupting then return.  The interrupt will process the
        !          4042:     // request.  Note that if we get reselected after this point the chip
        !          4043:     // will ignore the bytes written until the interrupt register is read.
        !          4044:     // The commands that handle a message and a CDB can only be used if the
        !          4045:     // message is one byte or 3 bytes long; otherwise only a one-byte message
        !          4046:     // is transferred on the select and the remaining bytes are handled in the
        !          4047:     // interrupt routine.
        !          4048:     //
        !          4049: 
        !          4050:     if (DeviceExtension->AdapterFlags & PD_NCR_ADAPTER) {
        !          4051: 
        !          4052:         *((PUCHAR) &DmaStatus) = SCSI_READ( DeviceExtension->AdapterBase, DmaStatus );
        !          4053:         if (DmaStatus.Interrupt == DeviceExtension->InterruptPending) {
        !          4054:             return;
        !          4055:         }
        !          4056: 
        !          4057:     }  else {
        !          4058: 
        !          4059:         *((PUCHAR) &DeviceExtension->AdapterStatus) = SCSI_READ( DeviceExtension->Adapter, ScsiStatus );
        !          4060:         if (DeviceExtension->AdapterStatus.Interrupt) {
        !          4061:             return;
        !          4062:         }
        !          4063: 
        !          4064:     }
        !          4065: 
        !          4066:     //
        !          4067:     // Set the destination ID.  Put the first byte of the message-in
        !          4068:     // the fifo and set the command to select with ATN.  This command
        !          4069:     // selects the target, sends one message byte and interrupts.  The
        !          4070:     // ATN line remains set.  The succeeding bytes are loaded into the
        !          4071:     // FIFO and sent to the target by the interrupt service routine.
        !          4072:     //
        !          4073: 
        !          4074:     SCSI_WRITE(DeviceExtension->Adapter, DestinationId, srb->TargetId);
        !          4075:     SCSI_WRITE( DeviceExtension->Adapter,
        !          4076:                 Fifo,
        !          4077:                 DeviceExtension->MessageBuffer[DeviceExtension->MessageSent++]
        !          4078:                 );
        !          4079: 
        !          4080:     //
        !          4081:     // Set the synchronous data transfer parameter registers in case a
        !          4082:     // data transfer is done.  These must be set before a data transfer
        !          4083:     // is started.
        !          4084:     //
        !          4085: 
        !          4086:     SCSI_WRITE( DeviceExtension->Adapter,
        !          4087:                 SynchronousPeriod,
        !          4088:                 targetState->SynchronousPeriod
        !          4089:                 );
        !          4090:     SCSI_WRITE( DeviceExtension->Adapter,
        !          4091:                 SynchronousOffset,
        !          4092:                 targetState->SynchronousOffset
        !          4093:                 );
        !          4094: 
        !          4095:     SCSI_WRITE( DeviceExtension->Adapter,
        !          4096:                 Configuration3,
        !          4097:                 *((PCHAR) &targetState->Configuration3)
        !          4098:                 );
        !          4099: 
        !          4100: 
        !          4101:     //
        !          4102:     // Determine if this srb has a Cdb with it and whether the message is such that
        !          4103:     // the message and the Cdb can be loaded into the fifo; otherwise, just
        !          4104:     // load the first byte of the message.
        !          4105:     //
        !          4106: 
        !          4107:     if (srb->Function == SRB_FUNCTION_EXECUTE_SCSI &&
        !          4108:         (DeviceExtension->MessageCount == 1 ||
        !          4109:         DeviceExtension->MessageCount == 3)) {
        !          4110: 
        !          4111:         //
        !          4112:         // Copy the entire message and Cdb into the fifo.
        !          4113:         //
        !          4114: 
        !          4115:         for (;
        !          4116:              DeviceExtension->MessageSent <
        !          4117:              DeviceExtension->MessageCount;
        !          4118:              DeviceExtension->MessageSent++ ) {
        !          4119: 
        !          4120:             SCSI_WRITE( DeviceExtension->Adapter,
        !          4121:                         Fifo,
        !          4122:                         DeviceExtension->
        !          4123:                         MessageBuffer[DeviceExtension->MessageSent]
        !          4124:                         );
        !          4125: 
        !          4126:         }
        !          4127: 
        !          4128:         for (i = 0; i < srb->CdbLength; i++) {
        !          4129:             SCSI_WRITE(DeviceExtension->Adapter,
        !          4130:                        Fifo,
        !          4131:                        srb->Cdb[i]
        !          4132:                        );
        !          4133:         }
        !          4134: 
        !          4135:         if (DeviceExtension->MessageCount == 1) {
        !          4136: 
        !          4137:             //
        !          4138:             // One message byte so use select with attention which uses one
        !          4139:             // message byte.
        !          4140:             //
        !          4141: 
        !          4142:             SCSI_WRITE(
        !          4143:                 DeviceExtension->Adapter,
        !          4144:                 Command,
        !          4145:                 SELECT_WITH_ATTENTION
        !          4146:                 );
        !          4147: 
        !          4148:         } else {
        !          4149: 
        !          4150:             //
        !          4151:             // Three byte message, so use the select with attention which uses
        !          4152:             // three byte messages.
        !          4153:             //
        !          4154: 
        !          4155:             SCSI_WRITE(
        !          4156:                 DeviceExtension->Adapter,
        !          4157:                 Command,
        !          4158:                 SELECT_WITH_ATTENTION3
        !          4159:                 );
        !          4160: 
        !          4161:         }
        !          4162: 
        !          4163:     } else {
        !          4164: 
        !          4165:         //
        !          4166:         // Only the first byte of the message can be sent so select with
        !          4167:         // ATTENTION and the target will request the rest.
        !          4168:         //
        !          4169: 
        !          4170:         SCSI_WRITE(
        !          4171:             DeviceExtension->Adapter,
        !          4172:             Command,
        !          4173:             SELECT_WITH_ATTENTION_STOP
        !          4174:             );
        !          4175: 
        !          4176:     }
        !          4177: 
        !          4178:     /* Powerfail release */
        !          4179: 
        !          4180:     //
        !          4181:     // Set the device state to message-out and indicate that a message
        !          4182:     // is being sent.
        !          4183:     //
        !          4184: 
        !          4185:     DeviceExtension->AdapterFlags |= PD_MESSAGE_OUT_VALID;
        !          4186:     DeviceExtension->AdapterState = AttemptingSelect;
        !          4187:     DeviceExtension->InterruptCount = 0;
        !          4188: 
        !          4189: }
        !          4190: 
        !          4191: 
        !          4192: VOID
        !          4193: NcrSendMessage(
        !          4194:     PSCSI_REQUEST_BLOCK Srb,
        !          4195:     PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !          4196:     PSPECIFIC_LOGICAL_UNIT_EXTENSION LuExtension
        !          4197:     )
        !          4198: 
        !          4199: /*++
        !          4200: 
        !          4201: Routine Description:
        !          4202: 
        !          4203:     This routine attempts to send the indicated message to the target
        !          4204:     controller.  There are three classes of messages:
        !          4205:         Those which terminate a specific request and end in bus free.
        !          4206:         Those which apply to a specific request and then proceed.
        !          4207:         Those which end in bus free.
        !          4208: 
        !          4209:     For those messages that apply to a specific request, check to see that
        !          4210:     the request is currently being processed and an INDENTIFY message prefixed
        !          4211:     to the message.
        !          4212: 
        !          4213:     It is possible that the destination logical unit is the active logical unit;
        !          4214:     however, it would difficult to jump in and send the requested message, so
        !          4215:     just wait for the bus to become free.
        !          4216: 
        !          4217:     In the case where the target is not currently active, then set up the SCSI
        !          4218:     protocol chip to select the target controller and send the message.
        !          4219: 
        !          4220: Arguments:
        !          4221: 
        !          4222:     Srb - Supplies the request to be started.
        !          4223: 
        !          4224:     DeviceExtension - Supplies the extended device extension for this SCSI bus.
        !          4225: 
        !          4226:     LuExtension - Supplies the logical unit extension for this request.
        !          4227: 
        !          4228: Notes:
        !          4229: 
        !          4230:     This routine must be synchronized with the interrupt routine.
        !          4231: 
        !          4232: Return Value:
        !          4233: 
        !          4234:     None
        !          4235: 
        !          4236: --*/
        !          4237: {
        !          4238:     PSCSI_REQUEST_BLOCK linkedSrb;
        !          4239:     BOOLEAN impliesDisconnect;
        !          4240:     BOOLEAN useTag;
        !          4241:     UCHAR message;
        !          4242: 
        !          4243:     impliesDisconnect = FALSE;
        !          4244:     useTag = FALSE;
        !          4245: 
        !          4246:     //
        !          4247:     // Decode the type of message.
        !          4248:     //
        !          4249: 
        !          4250:     switch (Srb->Function) {
        !          4251: 
        !          4252:     case SRB_FUNCTION_TERMINATE_IO:
        !          4253:     case SRB_FUNCTION_ABORT_COMMAND:
        !          4254: 
        !          4255:         //
        !          4256:         // Verify that the request is being processed by the logical unit.
        !          4257:         //
        !          4258: 
        !          4259:         linkedSrb = ScsiPortGetSrb(
        !          4260:             DeviceExtension,
        !          4261:             Srb->PathId,
        !          4262:             Srb->TargetId,
        !          4263:             Srb->Lun,
        !          4264:             Srb->QueueTag
        !          4265:             );
        !          4266: 
        !          4267:         if (linkedSrb != Srb->NextSrb) {
        !          4268: 
        !          4269:             //
        !          4270:             // The specified request is not here.  Complete the request
        !          4271:             // without error.
        !          4272:             //
        !          4273: 
        !          4274:             Srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
        !          4275:             ScsiPortNotification(
        !          4276:                 RequestComplete,
        !          4277:                 DeviceExtension,
        !          4278:                 Srb
        !          4279:                 );
        !          4280: 
        !          4281:             ScsiPortNotification(
        !          4282:                 NextRequest,
        !          4283:                 DeviceExtension,
        !          4284:                 NULL
        !          4285:                 );
        !          4286: 
        !          4287:             return;
        !          4288:         }
        !          4289: 
        !          4290:         if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) {
        !          4291:             impliesDisconnect = TRUE;
        !          4292:             message = SCSIMESS_ABORT;
        !          4293:         } else {
        !          4294:             message = SCSIMESS_TERMINATE_IO_PROCESS;
        !          4295:             impliesDisconnect = FALSE;
        !          4296:         }
        !          4297: 
        !          4298:         //
        !          4299:         // Use a tagged message if the original request was tagged.
        !          4300:         //
        !          4301: 
        !          4302:         useTag = linkedSrb->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE ?
        !          4303:             TRUE : FALSE;
        !          4304: 
        !          4305:         break;
        !          4306: 
        !          4307:     case SRB_FUNCTION_RESET_DEVICE:
        !          4308: 
        !          4309:         //
        !          4310:         // Because of the way the chip works it is easiest to send an IDENTIFY
        !          4311:         // message along with the BUS DEVICE RESET message. That is because
        !          4312:         // there is no way to select a target with ATN and send one message
        !          4313:         // byte.  This IDENTIFY message is not necessary for the SCSI protocol,
        !          4314:         // but it is legal and should not cause any problem.
        !          4315:         //
        !          4316: 
        !          4317:         message = SCSIMESS_BUS_DEVICE_RESET;
        !          4318:         impliesDisconnect = TRUE;
        !          4319:         break;
        !          4320: 
        !          4321:     case SRB_FUNCTION_RELEASE_RECOVERY:
        !          4322: 
        !          4323:         //
        !          4324:         // These messages require an IDENTIFY message and imply a disconnect.
        !          4325:         //
        !          4326: 
        !          4327:         impliesDisconnect = TRUE;
        !          4328:         message = SCSIMESS_RELEASE_RECOVERY;
        !          4329:         break;
        !          4330: 
        !          4331:     case SCSIMESS_CLEAR_QUEUE:
        !          4332: 
        !          4333:         //
        !          4334:         // These messages require an IDENTIFY message and imply a disconnect.
        !          4335:         //
        !          4336: 
        !          4337:         message = SCSIMESS_CLEAR_QUEUE;
        !          4338:         impliesDisconnect = TRUE;
        !          4339:         break;
        !          4340: 
        !          4341:     default:
        !          4342: 
        !          4343:         //
        !          4344:         // This is an unsupported message request. Fail the request.
        !          4345:         //
        !          4346: 
        !          4347:         Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
        !          4348:         ScsiPortNotification(
        !          4349:             RequestComplete,
        !          4350:             DeviceExtension,
        !          4351:             Srb
        !          4352:             );
        !          4353: 
        !          4354:         ScsiPortNotification(
        !          4355:             NextRequest,
        !          4356:             DeviceExtension,
        !          4357:             NULL
        !          4358:             );
        !          4359: 
        !          4360:         return;
        !          4361:     }
        !          4362: 
        !          4363:     //
        !          4364:     // Save away the parameters in case nothing can be done now.
        !          4365:     //
        !          4366: 
        !          4367:     DeviceExtension->NextSrbRequest = Srb;
        !          4368:     DeviceExtension->AdapterFlags |= PD_PENDING_START_IO;
        !          4369:     LuExtension->ActiveSendRequest = Srb;
        !          4370: 
        !          4371:     //
        !          4372:     // Check to see if the bus is free.  If it is not, then return.  Since
        !          4373:     // the request parameters have been saved, indicate that the request has
        !          4374:     // been accepted.  The request will be processed when the bus becomes free.
        !          4375:     //
        !          4376: 
        !          4377:     if (DeviceExtension->AdapterState != BusFree) {
        !          4378:         return;
        !          4379:     }
        !          4380: 
        !          4381:     //
        !          4382:     // Create the identify command and copy the message to the buffer.
        !          4383:     //
        !          4384: 
        !          4385:     DeviceExtension->MessageBuffer[0] = SCSIMESS_IDENTIFY_WITH_DISCON |
        !          4386:         Srb->Lun;
        !          4387:     DeviceExtension->MessageCount = 1;
        !          4388:     DeviceExtension->MessageSent = 0;
        !          4389: 
        !          4390:     if (useTag && Srb->QueueTag != SP_UNTAGGED) {
        !          4391:         DeviceExtension->MessageBuffer[DeviceExtension->MessageCount++] = SCSIMESS_SIMPLE_QUEUE_TAG;
        !          4392:         DeviceExtension->MessageBuffer[DeviceExtension->MessageCount++] = Srb->QueueTag;
        !          4393: 
        !          4394:         if (message == SCSIMESS_ABORT) {
        !          4395:             message = SCSIMESS_ABORT_WITH_TAG;
        !          4396:         }
        !          4397:     }
        !          4398: 
        !          4399:     DeviceExtension->MessageBuffer[DeviceExtension->MessageCount++] = message;
        !          4400: 
        !          4401:     //
        !          4402:     // Attempt to select the target and update the adapter flags.
        !          4403:     //
        !          4404: 
        !          4405:     NcrSelectTarget( DeviceExtension, LuExtension );
        !          4406: 
        !          4407:     DeviceExtension->AdapterFlags |= impliesDisconnect ?
        !          4408:         PD_DISCONNECT_EXPECTED | PD_SEND_MESSAGE_REQUEST
        !          4409:         : PD_SEND_MESSAGE_REQUEST;
        !          4410: 
        !          4411: }
        !          4412: 
        !          4413: VOID
        !          4414: NcrStartExecution(
        !          4415:     PSCSI_REQUEST_BLOCK Srb,
        !          4416:     PSPECIFIC_DEVICE_EXTENSION DeviceExtension,
        !          4417:     PSPECIFIC_LOGICAL_UNIT_EXTENSION LuExtension
        !          4418:     )
        !          4419: 
        !          4420: /*++
        !          4421: 
        !          4422: Routine Description:
        !          4423: 
        !          4424:     This procedure sets up the chip to select the target and notify it that
        !          4425:     a request is available.  For the NCR chip, the chip is set up to select,
        !          4426:     send the IDENTIFY message and send the command data block.  A check is
        !          4427:     made to determine if synchronous negotiation is necessary.
        !          4428: 
        !          4429: Arguments:
        !          4430: 
        !          4431:     Srb - Supplies the request to be started.
        !          4432: 
        !          4433:     DeviceExtension - Supplies the extended device extension for this SCSI bus.
        !          4434: 
        !          4435:     LuExtension - Supplies the logical unit extension for this requst.
        !          4436: 
        !          4437: Notes:
        !          4438: 
        !          4439:     This routine must be synchronized with the interrupt routine.
        !          4440: 
        !          4441: Return Value:
        !          4442: 
        !          4443:     None
        !          4444: 
        !          4445: --*/
        !          4446: 
        !          4447: {
        !          4448: 
        !          4449:     PSCSI_EXTENDED_MESSAGE extendedMessage;
        !          4450:     CHIP_TYPES chipType;
        !          4451:     PSPECIFIC_TARGET_EXTENSION targetState;
        !          4452: 
        !          4453:     //
        !          4454:     // Save away the parameters in case nothing can be done now.
        !          4455:     //
        !          4456: 
        !          4457:     SRB_EXT(Srb)->SavedDataPointer = (ULONG) Srb->DataBuffer;
        !          4458:     SRB_EXT(Srb)->SavedDataLength = Srb->DataTransferLength;
        !          4459:     SRB_EXT(Srb)->SrbExtensionFlags = 0;
        !          4460:     SRB_EXT(Srb)->MaximumTransferLength = 0;
        !          4461:     DeviceExtension->NextSrbRequest = Srb;
        !          4462:     DeviceExtension->AdapterFlags |= PD_PENDING_START_IO;
        !          4463: 
        !          4464:     //
        !          4465:     // Check to see if the bus is free.  If it is not, then return.  Since
        !          4466:     // the request parameters have been saved, indicate that the request has
        !          4467:     // been accepted.  The request will be processed when the bus becomes free.
        !          4468:     //
        !          4469: 
        !          4470:     if (DeviceExtension->AdapterState != BusFree) {
        !          4471:         return;
        !          4472:     }
        !          4473: 
        !          4474:     //
        !          4475:     // Create the identify command.
        !          4476:     //
        !          4477: 
        !          4478:     DeviceExtension->MessageCount = 1;
        !          4479:     DeviceExtension->MessageSent = 0;
        !          4480:     DeviceExtension->AdapterFlags |= PD_MESSAGE_OUT_VALID;
        !          4481: 
        !          4482:     DeviceExtension->MessageBuffer[0] = SCSIMESS_IDENTIFY | Srb->Lun;
        !          4483: 
        !          4484:     DeviceExtension->TargetId = Srb->TargetId;
        !          4485:     targetState = &DeviceExtension->TargetState[Srb->TargetId];
        !          4486: 
        !          4487:     //
        !          4488:     // Check to see if disconnect is allowed.  If not then don't do tagged
        !          4489:     // queuing either.
        !          4490:     //
        !          4491: 
        !          4492:     if (!(Srb->SrbFlags & SRB_FLAGS_DISABLE_DISCONNECT)) {
        !          4493: 
        !          4494:         //
        !          4495:         // Enable disconnects in the message.
        !          4496:         //
        !          4497: 
        !          4498:         DeviceExtension->MessageBuffer[0] |= SCSIMESS_IDENTIFY_WITH_DISCON;
        !          4499: 
        !          4500:         //
        !          4501:         // If this is a tagged command then create a tagged message.
        !          4502:         //
        !          4503: 
        !          4504:         if (Srb->SrbFlags & SRB_FLAGS_QUEUE_ACTION_ENABLE) {
        !          4505: 
        !          4506:             //
        !          4507:             // The queue tag message is two bytes the first is the queue action
        !          4508:             // and the second is the queue tag.
        !          4509:             //
        !          4510: 
        !          4511:             DeviceExtension->MessageBuffer[1] = Srb->QueueAction;
        !          4512:             DeviceExtension->MessageBuffer[2] = Srb->QueueTag;
        !          4513:             DeviceExtension->MessageCount += 2;
        !          4514:             DeviceExtension->AdapterFlags |= PD_TAGGED_SELECT;
        !          4515: 
        !          4516:         } else {
        !          4517:             LuExtension->ActiveLuRequest = Srb;
        !          4518:         }
        !          4519: 
        !          4520:     } else {
        !          4521:             LuExtension->ActiveLuRequest = Srb;
        !          4522:     }
        !          4523: 
        !          4524:     //
        !          4525:     // Check to see if synchronous negotiation is necessary.
        !          4526:     //
        !          4527: 
        !          4528:     if (!(targetState->TargetFlags &
        !          4529:         (PD_SYNCHRONOUS_NEGOTIATION_DONE | PD_DO_NOT_NEGOTIATE))) {
        !          4530: 
        !          4531:         //
        !          4532:         // Initialize the synchronous transfer register values to an
        !          4533:         // asynchronous transfer, which is what will be used if anything
        !          4534:         // goes wrong with the negotiation.
        !          4535:         //
        !          4536: 
        !          4537:         targetState->SynchronousOffset = ASYNCHRONOUS_OFFSET;
        !          4538:         targetState->SynchronousPeriod = ASYNCHRONOUS_PERIOD;
        !          4539:         targetState->Configuration3 = DeviceExtension->Configuration3;
        !          4540: 
        !          4541:         if (Srb->SrbFlags & SRB_FLAGS_DISABLE_SYNCH_TRANSFER) {
        !          4542: 
        !          4543:             //
        !          4544:             // Synchronous transfers are disabled by the SRB.
        !          4545:             //
        !          4546: 
        !          4547:             NcrSelectTarget( DeviceExtension, LuExtension );
        !          4548:             return;
        !          4549:         }
        !          4550: 
        !          4551:         if (DeviceExtension->ChipType == Fas216) {
        !          4552: 
        !          4553:             //
        !          4554:             // The Fas216 supports fast synchronous transfers.
        !          4555:             //
        !          4556: 
        !          4557:             chipType = Fas216Fast;
        !          4558: 
        !          4559:         } else if (DeviceExtension->ChipType == Ncr53c90) {
        !          4560: 
        !          4561:             //
        !          4562:             // The 53c90 does not support synchronous transfers.
        !          4563:             // Set the do not negotate flag in the logical unit structure.
        !          4564:             //
        !          4565: 
        !          4566:             targetState->TargetFlags |= PD_DO_NOT_NEGOTIATE;
        !          4567:             NcrSelectTarget( DeviceExtension, LuExtension );
        !          4568:             return;
        !          4569: 
        !          4570:         } else {
        !          4571: 
        !          4572:             chipType = DeviceExtension->ChipType;
        !          4573: 
        !          4574:         }
        !          4575: 
        !          4576:         //
        !          4577:         // Create the synchronous data transfer request message.
        !          4578:         // The format of the message is:
        !          4579:         //
        !          4580:         //        EXTENDED_MESSAGE op-code
        !          4581:         //        Length of message
        !          4582:         //        Synchronous transfer data request op-code
        !          4583:         //        Our Transfer period
        !          4584:         //        Our REQ/ACK offset
        !          4585:         //
        !          4586:         //  The message is placed after the IDENTIFY message.
        !          4587:         //
        !          4588: 
        !          4589:         extendedMessage = (PSCSI_EXTENDED_MESSAGE)
        !          4590:             &DeviceExtension->MessageBuffer[DeviceExtension->MessageCount];
        !          4591:         DeviceExtension->MessageCount += 2 + SCSIMESS_SYNCH_DATA_LENGTH;
        !          4592: 
        !          4593:         extendedMessage->InitialMessageCode = SCSIMESS_EXTENDED_MESSAGE;
        !          4594:         extendedMessage->MessageLength = SCSIMESS_SYNCH_DATA_LENGTH;
        !          4595:         extendedMessage->MessageType = SCSIMESS_SYNCHRONOUS_DATA_REQ;
        !          4596: 
        !          4597:         //
        !          4598:         // If this chips does not suport fast SCSI, just calculate the normal
        !          4599:         // minimum transfer period; otherwise use the fast value.
        !          4600:         //
        !          4601: 
        !          4602:         //
        !          4603:         // The initial sychronous transfer period is:
        !          4604:         //
        !          4605:         //  SynchronousPeriodCyles * 1000
        !          4606:         //  -----------------------------
        !          4607:         //    ClockSpeed * 4
        !          4608:         //
        !          4609:         // Note the result of the divide by four must be rounded up.
        !          4610:         //
        !          4611: 
        !          4612:         extendedMessage->ExtendedArguments.Synchronous.TransferPeriod =
        !          4613:             ((SynchronousTransferTypes[chipType].SynchronousPeriodCyles * 1000) /
        !          4614:             DeviceExtension->ClockSpeed + 3) / 4;
        !          4615:         extendedMessage->ExtendedArguments.Synchronous.ReqAckOffset = SYNCHRONOUS_OFFSET;
        !          4616: 
        !          4617:         //
        !          4618:         // Attempt to select the target and update the adapter flags.
        !          4619:         //
        !          4620: 
        !          4621:         NcrSelectTarget( DeviceExtension, LuExtension );
        !          4622: 
        !          4623:         //
        !          4624:         // Many controllers reject the first byte of a synchronous
        !          4625:         // negotiation message.  Since this is a multibyte message the
        !          4626:         // ATN signal remains set after the first byte is sent.  Some
        !          4627:         // controllers remember this attempt to do a message-out
        !          4628:         // later.  Setting the PD_POSSIBLE_EXTRA_MESSAGE_OUT flag allows
        !          4629:         // this extra message transfer to occur without error.
        !          4630:         //
        !          4631: 
        !          4632:         DeviceExtension->AdapterFlags |= PD_POSSIBLE_EXTRA_MESSAGE_OUT |
        !          4633:             PD_SYNCHRONOUS_TRANSFER_SENT;
        !          4634: 
        !          4635:         return;
        !          4636:     }
        !          4637: 
        !          4638:     NcrSelectTarget( DeviceExtension, LuExtension );
        !          4639: 
        !          4640: }
        !          4641: 
        !          4642: BOOLEAN
        !          4643: NcrStartIo(
        !          4644:     IN PVOID ServiceContext,
        !          4645:     IN PSCSI_REQUEST_BLOCK Srb
        !          4646:     )
        !          4647: /*++
        !          4648: 
        !          4649: Routine Description:
        !          4650: 
        !          4651:     This function is used by the OS dependent port driver to pass requests to
        !          4652:     the dependent driver.  This function begins the execution of the request.
        !          4653:     Requests to reset the SCSI bus are handled immediately.  Requests to send
        !          4654:     a message or start a SCSI command are handled when the bus is free.
        !          4655: 
        !          4656: Arguments:
        !          4657: 
        !          4658:     ServiceContext - Supplies the device Extension for the SCSI bus adapter.
        !          4659: 
        !          4660:     Srb - Supplies the SCSI request block to be started.
        !          4661: 
        !          4662: Return Value:
        !          4663: 
        !          4664:     TRUE - If the request can be accepted at this time.
        !          4665: 
        !          4666:     FALSE - If the request must be submitted later.
        !          4667: 
        !          4668: --*/
        !          4669: 
        !          4670: {
        !          4671:     PSPECIFIC_DEVICE_EXTENSION deviceExtension = ServiceContext;
        !          4672:     PSPECIFIC_LOGICAL_UNIT_EXTENSION luExtension;
        !          4673: 
        !          4674:     switch (Srb->Function) {
        !          4675:     case SRB_FUNCTION_EXECUTE_SCSI:
        !          4676: 
        !          4677:         //
        !          4678:         // Determine the logical unit that this request is for.
        !          4679:         //
        !          4680: 
        !          4681:         luExtension = ScsiPortGetLogicalUnit(
        !          4682:             deviceExtension,
        !          4683:             Srb->PathId,
        !          4684:             Srb->TargetId,
        !          4685:             Srb->Lun
        !          4686:             );
        !          4687: 
        !          4688:         NcrStartExecution(
        !          4689:             Srb,
        !          4690:             deviceExtension,
        !          4691:             luExtension
        !          4692:             );
        !          4693: 
        !          4694:         return(TRUE);
        !          4695: 
        !          4696:     case SRB_FUNCTION_ABORT_COMMAND:
        !          4697:     case SRB_FUNCTION_RESET_DEVICE:
        !          4698:     case SRB_FUNCTION_TERMINATE_IO:
        !          4699: 
        !          4700:         //
        !          4701:         // Determine the logical unit that this request is for.
        !          4702:         //
        !          4703: 
        !          4704:         luExtension = ScsiPortGetLogicalUnit(
        !          4705:             deviceExtension,
        !          4706:             Srb->PathId,
        !          4707:             Srb->TargetId,
        !          4708:             Srb->Lun
        !          4709:             );
        !          4710: 
        !          4711:         NcrSendMessage(
        !          4712:             Srb,
        !          4713:             deviceExtension,
        !          4714:             luExtension
        !          4715:             );
        !          4716: 
        !          4717:         return(TRUE);
        !          4718: 
        !          4719:     case SRB_FUNCTION_RESET_BUS:
        !          4720: 
        !          4721:         //
        !          4722:         // There is no logical unit so just reset the bus.
        !          4723:         //
        !          4724: 
        !          4725:         NcrResetScsiBusInternal( deviceExtension, 0 );
        !          4726:         return(TRUE);
        !          4727: 
        !          4728:     default:
        !          4729: 
        !          4730:         //
        !          4731:         // Unknown function code in the request.  Complete the request with
        !          4732:         // an error and ask for the next request.
        !          4733:         //
        !          4734: 
        !          4735:         Srb->SrbStatus = SRB_STATUS_BAD_FUNCTION;
        !          4736:         ScsiPortNotification(
        !          4737:             RequestComplete,
        !          4738:             deviceExtension,
        !          4739:             Srb
        !          4740:             );
        !          4741: 
        !          4742:         ScsiPortNotification(
        !          4743:             NextRequest,
        !          4744:             deviceExtension,
        !          4745:             NULL
        !          4746:             );
        !          4747: 
        !          4748:         return(TRUE);
        !          4749:     }
        !          4750: 
        !          4751: }
        !          4752: 
        !          4753: VOID
        !          4754: NcrStartDataTransfer(
        !          4755:     IN PVOID ServiceContext
        !          4756:     )
        !          4757: /*++
        !          4758: 
        !          4759: Routine Description:
        !          4760: 
        !          4761:     This routine sets up the scsi bus protocol chip to perform a data transfer.
        !          4762:     It is called after the DMA has been initialized.
        !          4763: 
        !          4764: Arguments:
        !          4765: 
        !          4766:     ServiceContext - Supplies a pointer to the specific device extension.
        !          4767: 
        !          4768: Return Value:
        !          4769: 
        !          4770:     None.
        !          4771: 
        !          4772: --*/
        !          4773: 
        !          4774: {
        !          4775:     PSPECIFIC_DEVICE_EXTENSION deviceExtension = ServiceContext;
        !          4776: 
        !          4777:     //
        !          4778:     // If the data tranfer is no longer expected then ignore the notification.
        !          4779:     //
        !          4780: 
        !          4781:     if (!(deviceExtension->AdapterFlags & PD_PENDING_DATA_TRANSFER)) {
        !          4782: 
        !          4783:         return;
        !          4784: 
        !          4785:     }
        !          4786: 
        !          4787:     //
        !          4788:     // Set up the SCSI protocol chip for the data transfer with the
        !          4789:     // command to start.
        !          4790:     //
        !          4791: 
        !          4792:     SCSI_WRITE( deviceExtension->Adapter,
        !          4793:                 Command,
        !          4794:                 TRANSFER_INFORMATION_DMA
        !          4795:                 );
        !          4796: 
        !          4797:     deviceExtension->AdapterFlags &= ~PD_PENDING_DATA_TRANSFER;
        !          4798: 
        !          4799: }
        !          4800: 
        !          4801: ULONG
        !          4802: DriverEntry(
        !          4803:     IN PVOID DriverObject,
        !          4804:     IN PVOID Argument2
        !          4805:     )
        !          4806: 
        !          4807: /*++
        !          4808: 
        !          4809: Routine Description:
        !          4810: 
        !          4811: Arguments:
        !          4812: 
        !          4813:     Driver Object is passed to ScsiPortInitialize()
        !          4814: 
        !          4815: Return Value:
        !          4816: 
        !          4817:     Status from ScsiPortInitialize()
        !          4818: 
        !          4819: --*/
        !          4820: 
        !          4821: {
        !          4822:     HW_INITIALIZATION_DATA hwInitializationData;
        !          4823:     ULONG i;
        !          4824:     ULONG Status1;
        !          4825:     ULONG Status2;
        !          4826:     INIT_DATA InitData;
        !          4827: 
        !          4828:     ScsiDebugPrint(1,"\n\nNCR 53c9x SCSI MiniPort Driver\n");
        !          4829: 
        !          4830:     //
        !          4831:     // Zero out hardware initialization data structure.
        !          4832:     //
        !          4833: 
        !          4834:     for (i=0; i<sizeof(HW_INITIALIZATION_DATA); i++) {
        !          4835:        ((PUCHAR)&hwInitializationData)[i] = 0;
        !          4836:     }
        !          4837: 
        !          4838:     //
        !          4839:     // Fill in the hardware initialization data structure.
        !          4840:     //
        !          4841: 
        !          4842:     hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
        !          4843:     hwInitializationData.HwInitialize = NcrInitializeAdapter;
        !          4844:     hwInitializationData.HwStartIo = NcrStartIo;
        !          4845:     hwInitializationData.HwInterrupt = NcrInterruptServiceRoutine;
        !          4846:     hwInitializationData.HwFindAdapter = NcrMcaFindAdapter;
        !          4847:     hwInitializationData.HwResetBus = NcrResetScsiBus;
        !          4848:     hwInitializationData.HwDmaStarted = NcrStartDataTransfer;
        !          4849:     hwInitializationData.NumberOfAccessRanges = 1;
        !          4850:     hwInitializationData.AdapterInterfaceType = MicroChannel;
        !          4851:     hwInitializationData.DeviceExtensionSize = sizeof(SPECIFIC_DEVICE_EXTENSION);
        !          4852:     hwInitializationData.SpecificLuExtensionSize =
        !          4853:         sizeof(SPECIFIC_LOGICAL_UNIT_EXTENSION);
        !          4854:     hwInitializationData.SrbExtensionSize = sizeof(SRB_EXTENSION);
        !          4855: 
        !          4856:     //
        !          4857:     // Initialize configuration information.
        !          4858:     //
        !          4859:     // The following adapter search order should be observed:
        !          4860:     //   1. Onboard 53c94 scsi host adapter
        !          4861:     //   2. Onboard 53c90 scsi host adapter
        !          4862:     //   3. Plug-in 53c90 scsi host adapter
        !          4863:     //
        !          4864: 
        !          4865:     InitData.AdapterId = 0;
        !          4866:     InitData.CardSlot = 7;
        !          4867: 
        !          4868:     Status1 = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, &InitData);
        !          4869: 
        !          4870:     //
        !          4871:     // Look for internal mips adapter.
        !          4872:     //
        !          4873: 
        !          4874:     hwInitializationData.AdapterInterfaceType = Internal;
        !          4875:     hwInitializationData.HwFindAdapter = NcrMipsFindAdapter;
        !          4876: 
        !          4877:     Status2 = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, &InitData);
        !          4878: 
        !          4879:     Status1 = Status2 < Status1 ? Status2 : Status1;
        !          4880: 
        !          4881:     //
        !          4882:     // Look for an Eisa adapter.
        !          4883:     //
        !          4884: 
        !          4885:     InitData.AdapterId = 0;
        !          4886:     hwInitializationData.AdapterInterfaceType = Eisa;
        !          4887:     hwInitializationData.HwFindAdapter = NcrEisaFindAdapter;
        !          4888: 
        !          4889:     Status2 = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, &InitData);
        !          4890: 
        !          4891:     return(Status2 < Status1 ? Status2 : Status1);
        !          4892: 
        !          4893: } // end PortInitialize()
        !          4894: 
        !          4895: ULONG
        !          4896: NcrMcaFindAdapter(
        !          4897:     IN PVOID ServiceContext,
        !          4898:     IN PVOID Context,
        !          4899:     IN PVOID BusInformation,
        !          4900:     IN PCHAR ArgumentString,
        !          4901:     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
        !          4902:     OUT PBOOLEAN Again
        !          4903:     )
        !          4904: /*++
        !          4905: 
        !          4906: Routine Description:
        !          4907: 
        !          4908:     This function fills in the configuration information structure.  This
        !          4909:     routine is temporary until the configuration manager supplies similar
        !          4910:     informtion.  It also fills in the capabilities structure.
        !          4911: 
        !          4912: Arguments:
        !          4913: 
        !          4914:     ServiceContext - Supplies a pointer to the device extension.
        !          4915: 
        !          4916:     Context - Unused.
        !          4917: 
        !          4918:     BusInformation - Unused.
        !          4919: 
        !          4920:     ArgumentString - Unused.
        !          4921: 
        !          4922:     ConfigInfo - Pointer to the configuration information structure to be
        !          4923:         filled in.
        !          4924: 
        !          4925:     Again - Returns back a request to call this function again.
        !          4926: 
        !          4927: Return Value:
        !          4928: 
        !          4929:     Returns a status value for the initialazitaition.
        !          4930: 
        !          4931: --*/
        !          4932: 
        !          4933: {
        !          4934: 
        !          4935:     PSPECIFIC_DEVICE_EXTENSION deviceExtension = ServiceContext;
        !          4936:     PINIT_DATA InitData = Context;
        !          4937:     LONG Slot;
        !          4938:     LONG i;
        !          4939:     ULONG Status = SP_RETURN_NOT_FOUND;
        !          4940: 
        !          4941:     //
        !          4942:     //  Determine if bus information array needs to be filled in.
        !          4943:     //
        !          4944: 
        !          4945:     if ( InitData->AdapterId == 0 ) {
        !          4946: 
        !          4947:         //
        !          4948:         //  Fill in the POS data structure.
        !          4949:         //
        !          4950: 
        !          4951:         for ( Slot = 0; Slot < 8; Slot++ ) {
        !          4952: 
        !          4953:             i = ScsiPortGetBusData ( deviceExtension,
        !          4954:                                      Pos,
        !          4955:                                      0,
        !          4956:                                      Slot,
        !          4957:                                      &InitData->PosData[Slot],
        !          4958:                                      sizeof( POS_DATA )
        !          4959:                                      );
        !          4960: 
        !          4961:             //
        !          4962:             //  If less that the requested amount of data is returned, then
        !          4963:             //  insure that this adapter is ignored.
        !          4964:             //
        !          4965: 
        !          4966:             if ( i < (sizeof( POS_DATA ))) {
        !          4967:                 InitData->PosData[Slot].AdapterId = 0xffff;
        !          4968:             }
        !          4969: 
        !          4970:         }
        !          4971: 
        !          4972:     }
        !          4973: 
        !          4974:     for ( Slot = InitData->CardSlot; Slot >= 0; Slot-- ) {
        !          4975:         if (( InitData->PosData[Slot].AdapterId == ONBOARD_C94_ADAPTER_ID ||
        !          4976:            InitData->PosData[Slot].AdapterId == ONBOARD_C90_ADAPTER_ID ||
        !          4977:            InitData->PosData[Slot].AdapterId == PLUGIN_C90_ADAPTER_ID ) &&
        !          4978:            (*(PPOS_DATA_1)&InitData->PosData[Slot].OptionData1).AdapterEnable) {
        !          4979:             InitData->CardSlot = Slot - 1;
        !          4980:             Status = SP_RETURN_FOUND;
        !          4981:             break;
        !          4982:         }
        !          4983:     }
        !          4984: 
        !          4985:     if ( Status == SP_RETURN_FOUND ) {
        !          4986: 
        !          4987:         *Again = TRUE;
        !          4988: 
        !          4989:         deviceExtension->AdapterBase = (PVOID) AdapterBaseAddress[
        !          4990:             (*(PPOS_DATA_1) &InitData->PosData[Slot].OptionData1).IoAddressSelects];
        !          4991:         deviceExtension->Adapter = (PSCSI_REGISTERS)
        !          4992:             ((PCHAR) deviceExtension->AdapterBase + sizeof(ADAPTER_REGISTERS));
        !          4993:         if ( InitData->PosData[Slot].AdapterId == ONBOARD_C94_ADAPTER_ID ) {
        !          4994:             deviceExtension->ChipType = Ncr53c94;
        !          4995:             deviceExtension->AdapterBusId = AdapterScsiIdC94[
        !          4996:                 (*(PPOS_DATA_3) &InitData->PosData[Slot].OptionData3).HostIdSelects];
        !          4997:             deviceExtension->InterruptPending = FALSE;
        !          4998:         } else {
        !          4999:             deviceExtension->ChipType = Ncr53c90;
        !          5000:             deviceExtension->AdapterBusId = AdapterScsiIdC90[
        !          5001:                 (*(PPOS_DATA_4) &InitData->PosData[Slot].OptionData4).HostIdSelects];
        !          5002:             deviceExtension->InterruptPending = TRUE;
        !          5003:         }
        !          5004: 
        !          5005:         deviceExtension->AdapterBusIdMask = 1 << deviceExtension->AdapterBusId;
        !          5006: 
        !          5007:         //
        !          5008:         // Set configuration information
        !          5009:         //
        !          5010: 
        !          5011:         ConfigInfo->NumberOfPhysicalBreaks = 16;
        !          5012:         ConfigInfo->BusInterruptLevel = AdapterInterruptLevel[
        !          5013:             (*(PPOS_DATA_1) &InitData->PosData[Slot].OptionData1).InterruptSelects];
        !          5014:         ConfigInfo->InitiatorBusId[0] = deviceExtension->AdapterBusId;
        !          5015:         ConfigInfo->DmaChannel = AdapterDmaLevel[
        !          5016:             (*(PPOS_DATA_2) &InitData->PosData[Slot].OptionData2).DmaSelects];
        !          5017:         ConfigInfo->DmaPort = (ULONG) deviceExtension->AdapterBase + (ULONG)
        !          5018:             &((PADAPTER_WRITE_REGISTERS) 0)->DmaDecode;
        !          5019:         if ( InitData->PosData[Slot].AdapterId == ONBOARD_C94_ADAPTER_ID ) {
        !          5020:             ConfigInfo->DmaWidth = Width16Bits;
        !          5021:             ConfigInfo->AlignmentMask = 1;
        !          5022:             ConfigInfo->AdapterScansDown = TRUE;
        !          5023:             ConfigInfo->TaggedQueuing = 1;
        !          5024:         } else {
        !          5025:             ConfigInfo->DmaWidth = Width8Bits;
        !          5026:         }
        !          5027: 
        !          5028:         ConfigInfo->DmaSpeed = Compatible;
        !          5029:         ConfigInfo->MaximumTransferLength = 0xf000;
        !          5030:         ConfigInfo->NumberOfBuses = 1;
        !          5031: 
        !          5032:         //
        !          5033:         // Fill in the access array information.
        !          5034:         //
        !          5035: 
        !          5036:         (*ConfigInfo->AccessRanges)[0].RangeStart =
        !          5037:             ScsiPortConvertUlongToPhysicalAddress((ULONG) deviceExtension->AdapterBase);
        !          5038:         (*ConfigInfo->AccessRanges)[0].RangeLength = sizeof(ADAPTER_REGISTERS) +
        !          5039:                                                      sizeof(SCSI_REGISTERS);
        !          5040:         (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
        !          5041: 
        !          5042:         //
        !          5043:         // Initialize hardware.
        !          5044:         //
        !          5045: 
        !          5046:         SCSI_WRITE(deviceExtension->Adapter, Command, RESET_SCSI_CHIP);
        !          5047:         SCSI_WRITE(deviceExtension->Adapter, Command, NO_OPERATION_DMA);
        !          5048: 
        !          5049:         deviceExtension->ClockSpeed = 14;       // set clock speed at 14 Mhz.
        !          5050:         deviceExtension->AdapterFlags |= PD_NCR_ADAPTER;
        !          5051: 
        !          5052:         ScsiDebugPrint(1, "   ScsiId = %x\n", ConfigInfo->InitiatorBusId[0]);
        !          5053:         ScsiDebugPrint(1, "   IoBase = %2x\n", deviceExtension->Adapter);
        !          5054:         ScsiDebugPrint(1, "   Irq    = %x\n", ConfigInfo->BusInterruptLevel);
        !          5055:         ScsiDebugPrint(1, "   Dma    = %x\n", ConfigInfo->DmaChannel);
        !          5056: 
        !          5057:     } else {
        !          5058: 
        !          5059:         *Again = FALSE;
        !          5060: 
        !          5061:     }
        !          5062: 
        !          5063:     return(Status);
        !          5064: 
        !          5065: }
        !          5066: 
        !          5067: ULONG
        !          5068: NcrEisaFindAdapter(
        !          5069:     IN PVOID ServiceContext,
        !          5070:     IN PVOID Context,
        !          5071:     IN PVOID BusInformation,
        !          5072:     IN PCHAR ArgumentString,
        !          5073:     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
        !          5074:     OUT PBOOLEAN Again
        !          5075:     )
        !          5076: /*++
        !          5077: 
        !          5078: Routine Description:
        !          5079: 
        !          5080:     This function fills in the configuration information structure.     This
        !          5081:     routine is temporary until the configuration manager supplies similar
        !          5082:     informtion.  It also fills in the capabilities structure.
        !          5083: 
        !          5084: Arguments:
        !          5085: 
        !          5086:     ServiceContext - Supplies a pointer to the device extension.
        !          5087: 
        !          5088:     Context - Unused.
        !          5089: 
        !          5090:     BusInformation - Unused.
        !          5091: 
        !          5092:     ArgumentString - Unused.
        !          5093: 
        !          5094:     ConfigInfo - Pointer to the configuration information structure to be
        !          5095:         filled in.
        !          5096: 
        !          5097:     Again - Returns back a request to call this function again.
        !          5098: 
        !          5099: Return Value:
        !          5100: 
        !          5101:     Returns a status value for the initialazitaition.
        !          5102: 
        !          5103: --*/
        !          5104: 
        !          5105: {
        !          5106: 
        !          5107:     PSPECIFIC_DEVICE_EXTENSION deviceExtension = ServiceContext;
        !          5108:     PCM_EISA_FUNCTION_INFORMATION functionInformation;
        !          5109:     PCM_EISA_SLOT_INFORMATION slotInformation;
        !          5110:     UCHAR dataByte;
        !          5111:     PUCHAR configurationRegister;
        !          5112:     ULONG boardId;
        !          5113:     ULONG numberOfFunctions;
        !          5114:     ULONG slotNumber;
        !          5115: 
        !          5116:     *Again = FALSE;
        !          5117: 
        !          5118:     for (slotNumber = 0; slotNumber < 16; slotNumber++) {
        !          5119: 
        !          5120:         boardId = ScsiPortGetBusData( deviceExtension,
        !          5121:                                       EisaConfiguration,
        !          5122:                                       ConfigInfo->SystemIoBusNumber,
        !          5123:                                       slotNumber,
        !          5124:                                       &slotInformation,
        !          5125:                                       0);
        !          5126: 
        !          5127:         if (boardId == 0 || slotInformation == NULL) {
        !          5128:             continue;
        !          5129:         }
        !          5130: 
        !          5131:         //
        !          5132:         // Calculate the actual number of functions returned.
        !          5133:         //
        !          5134: 
        !          5135:         numberOfFunctions = (boardId - sizeof(CM_EISA_SLOT_INFORMATION)) /
        !          5136:                sizeof(CM_EISA_FUNCTION_INFORMATION);
        !          5137: 
        !          5138:         if (numberOfFunctions > (ULONG) slotInformation->NumberFunctions) {
        !          5139:             numberOfFunctions = slotInformation->NumberFunctions;
        !          5140:         }
        !          5141: 
        !          5142:         functionInformation = (PCM_EISA_FUNCTION_INFORMATION) (slotInformation + 1);
        !          5143:         for (; 0 < numberOfFunctions; numberOfFunctions--, functionInformation++) {
        !          5144: 
        !          5145:             if (!(functionInformation->FunctionFlags & EISA_FUNCTION_ENABLED) &&
        !          5146:                 !strcmp(functionInformation->TypeString, "MSD,CDROM1")) {
        !          5147: 
        !          5148:                 DebugPrint((1, "NcrEisaFindAdapter: Found type string. Function information: %lx\n", functionInformation));
        !          5149:                 ConfigInfo->DmaWidth = Width8Bits;
        !          5150:                 ConfigInfo->DmaSpeed = Compatible;
        !          5151:                 deviceExtension->ChipType = Ncr53c90;
        !          5152:                 goto found;
        !          5153: 
        !          5154:             } else if (!(functionInformation->FunctionFlags & EISA_FUNCTION_ENABLED) &&
        !          5155:                 !strcmp(functionInformation->TypeString, "MSD,SCSI,C94")) {
        !          5156: 
        !          5157:                 DebugPrint((1, "NcrEisaFindAdapter: Found type string. Function information: %lx\n", functionInformation));
        !          5158:                 ConfigInfo->DmaWidth = Width16Bits;
        !          5159:                 ConfigInfo->AlignmentMask = 1;
        !          5160:                 ConfigInfo->DmaSpeed = TypeB;
        !          5161:                 ConfigInfo->MaximumTransferLength = 0x10000;
        !          5162:                 deviceExtension->ChipType = Ncr53c94;
        !          5163:                 goto found;
        !          5164:             }
        !          5165:         }
        !          5166:     }
        !          5167: 
        !          5168:     //
        !          5169:     // Determine if this is the correct Eisa board.
        !          5170:     //
        !          5171: 
        !          5172:     if (slotNumber >= 16) {
        !          5173: 
        !          5174:         //
        !          5175:         // The device was not found.
        !          5176:         //
        !          5177: 
        !          5178:         return(SP_RETURN_NOT_FOUND);
        !          5179:     }
        !          5180: 
        !          5181: found:
        !          5182: 
        !          5183:     ConfigInfo->BusInterruptVector = 0;
        !          5184:     ConfigInfo->NumberOfBuses = 1;
        !          5185: 
        !          5186:     //
        !          5187:     // Get the SCSI bus Id from the configuration information if there
        !          5188:     // is any.
        !          5189:     //
        !          5190: 
        !          5191:     if (ConfigInfo->InitiatorBusId[0] == (CCHAR) SP_UNINITIALIZED_VALUE) {
        !          5192:         deviceExtension->AdapterBusId = INITIATOR_BUS_ID;
        !          5193:         deviceExtension->AdapterBusIdMask = 1 << INITIATOR_BUS_ID;
        !          5194:         ConfigInfo->InitiatorBusId[0] = INITIATOR_BUS_ID;
        !          5195:     } else {
        !          5196:         deviceExtension->AdapterBusId = ConfigInfo->InitiatorBusId[0];
        !          5197:         deviceExtension->AdapterBusIdMask = 1 << ConfigInfo->InitiatorBusId[0];
        !          5198:     }
        !          5199: 
        !          5200:     configurationRegister = ScsiPortGetDeviceBase(
        !          5201:         deviceExtension,                      // HwDeviceExtension
        !          5202:         ConfigInfo->AdapterInterfaceType,     // AdapterInterfaceType
        !          5203:         ConfigInfo->SystemIoBusNumber,        // SystemIoBusNumber
        !          5204:         ScsiPortConvertUlongToPhysicalAddress(functionInformation->EisaPort->PortAddress),
        !          5205:         functionInformation->EisaPort->Configuration.NumberPorts, // NumberOfBytes
        !          5206:         TRUE                                  // InIoSpace
        !          5207:         );
        !          5208: 
        !          5209:     if (configurationRegister == (PUCHAR) SP_UNINITIALIZED_VALUE) {
        !          5210:         return(SP_RETURN_ERROR);
        !          5211:     }
        !          5212: 
        !          5213:     deviceExtension->ClockSpeed = 25;       // Assume a 25 Mhz clock speed.
        !          5214:     deviceExtension->Adapter = (PSCSI_REGISTERS) configurationRegister;
        !          5215: 
        !          5216:     //
        !          5217:     // The Emulex chip loads the TransferCountPage register with the chip id,
        !          5218:     // if the EnablePhaseLatch is set and a NOP DMA command has been loaded.
        !          5219:     //
        !          5220: 
        !          5221:     if (deviceExtension->ChipType == Ncr53c94) {
        !          5222: 
        !          5223:         //
        !          5224:         // Now write to the command register with a reset.
        !          5225:         //
        !          5226: 
        !          5227:         SCSI_WRITE( deviceExtension->Adapter, Command, RESET_SCSI_CHIP );
        !          5228: 
        !          5229:         //
        !          5230:         // A NOP command is required by the FAS218 to
        !          5231:         // load the TransferCountPage register with the chip Id.
        !          5232:         //
        !          5233: 
        !          5234:         SCSI_WRITE( deviceExtension->Adapter, Command, NO_OPERATION_DMA );
        !          5235: 
        !          5236:         dataByte = SCSI_READ( deviceExtension->Adapter, TransferCountPage);
        !          5237: 
        !          5238:         if (((PNCR_PART_CODE) &dataByte)->ChipFamily == EMULEX_FAS_216) {
        !          5239: 
        !          5240:             deviceExtension->ChipType = Fas216;
        !          5241:         }  else if (((PNCR_PART_CODE) &dataByte)->ChipFamily == NCR_53c96) {
        !          5242: 
        !          5243:             NcrPrint((1, "NcrFindAdapter: NCR 53c96 chip detected.\n"));
        !          5244:             deviceExtension->ChipType = Fas216;
        !          5245:         }
        !          5246:     }
        !          5247: 
        !          5248:     //
        !          5249:     // Set the parameters according to the chip type.
        !          5250:     //
        !          5251: 
        !          5252:     switch (deviceExtension->ChipType) {
        !          5253:     case Ncr53c94:
        !          5254: 
        !          5255:         NcrPrint((1, "NcrFindAdapter: Ncr 53C94 chip detected.\n"));
        !          5256:         ConfigInfo->TaggedQueuing = 1;
        !          5257:         ConfigInfo->MaximumTransferLength = 0x10000;
        !          5258:         break;
        !          5259: 
        !          5260:     case Fas216:
        !          5261:         NcrPrint((1, "NcrFindAdapter: Emulex FAS 216 chip detected.\n"));
        !          5262:         deviceExtension->ClockSpeed = EMULEX_SCSI_CLOCK_SPEED;
        !          5263:         ConfigInfo->TaggedQueuing = 1;
        !          5264:         ConfigInfo->MaximumTransferLength = 0x1000000-0x1000;
        !          5265:         deviceExtension->Configuration3.CheckIdMessage = 1;
        !          5266:         break;
        !          5267: 
        !          5268:     case Ncr53c90:
        !          5269: 
        !          5270:         NcrPrint((1, "NcrFindAdapter: Ncr 53C90 chip detected.\n"));
        !          5271:         ConfigInfo->MaximumTransferLength = 0x10000 - 0x1000;
        !          5272:         break;
        !          5273: 
        !          5274:     default:
        !          5275:         *Again = FALSE;
        !          5276:         return(SP_RETURN_BAD_CONFIG);
        !          5277:     }
        !          5278: 
        !          5279:     //
        !          5280:     // If the clock speed is greater than 25 Mhz then set the fast clock
        !          5281:     // bit in configuration register.
        !          5282:     //
        !          5283: 
        !          5284:     if (deviceExtension->ClockSpeed > 25) {
        !          5285:         deviceExtension->Configuration3.FastClock = 1;
        !          5286:     }
        !          5287: 
        !          5288:     ConfigInfo->DmaChannel =
        !          5289:         functionInformation->EisaDma->ConfigurationByte0.Channel;
        !          5290:     ConfigInfo->BusInterruptLevel =
        !          5291:         functionInformation->EisaIrq->ConfigurationByte.Interrupt;
        !          5292:     ConfigInfo->InterruptMode =
        !          5293:         functionInformation->EisaIrq->ConfigurationByte.LevelTriggered ?
        !          5294:         LevelSensitive : Latched;
        !          5295: 
        !          5296:     //
        !          5297:     // Fill in the access array information.
        !          5298:     //
        !          5299: 
        !          5300:     (*ConfigInfo->AccessRanges)[0].RangeStart =
        !          5301:     ScsiPortConvertUlongToPhysicalAddress(
        !          5302:         functionInformation->EisaPort->PortAddress);
        !          5303:     (*ConfigInfo->AccessRanges)[0].RangeLength =
        !          5304:         functionInformation->EisaPort->Configuration.NumberPorts;
        !          5305:     (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
        !          5306: 
        !          5307:     //
        !          5308:     // Make sure the interrupt and DMA channel are properly configured.
        !          5309:     //
        !          5310: 
        !          5311:     if (ConfigInfo->DmaChannel == (UCHAR) ~0 ||
        !          5312:         ConfigInfo->BusInterruptLevel == (UCHAR) ~0) {
        !          5313: 
        !          5314:         return(SP_RETURN_BAD_CONFIG);
        !          5315:     }
        !          5316: 
        !          5317:     //
        !          5318:     // Test for the interrupt bit in the status register. Some chips do not
        !          5319:     // implement this bit; however, this driver assumes that it exists.
        !          5320:     // The itnerrupt bit is tested for by reseting the chip, giving an
        !          5321:     // illegal command, and checking for an gross error interrupt.
        !          5322:     //
        !          5323: 
        !          5324:     SCSI_WRITE( deviceExtension->Adapter, Command, RESET_SCSI_CHIP );
        !          5325:     SCSI_WRITE( deviceExtension->Adapter, Command, NO_OPERATION_DMA );
        !          5326: 
        !          5327:     SCSI_WRITE( deviceExtension->Adapter, Command, COMMAND_COMPLETE );
        !          5328: 
        !          5329:     *((PUCHAR) &deviceExtension->AdapterStatus) = SCSI_READ(
        !          5330:                                                   deviceExtension->Adapter,
        !          5331:                                                   ScsiStatus
        !          5332:                                                   );
        !          5333: 
        !          5334:     dataByte = SCSI_READ( deviceExtension->Adapter, ScsiInterrupt );
        !          5335: 
        !          5336:     //
        !          5337:     // Test for the interrupt.
        !          5338:     //
        !          5339: 
        !          5340:     if (!deviceExtension->AdapterStatus.Interrupt) {
        !          5341: 
        !          5342:         NcrPrint((0, "\nNcrEisaFindAdapter: Ncr53c90 chip without status register interrupt detected.\n"));
        !          5343:         NcrPrint((0, "NcrInterrupt: Adapter Status: %2x; Adapter Interrupt: %2x\n",
        !          5344:              *((PUCHAR) &deviceExtension->AdapterStatus),
        !          5345:              dataByte
        !          5346:              ));
        !          5347: 
        !          5348:         ScsiPortFreeDeviceBase(deviceExtension, deviceExtension->Adapter);
        !          5349:         return(SP_RETURN_BAD_CONFIG);
        !          5350:     }
        !          5351: 
        !          5352:     //
        !          5353:     // Now write to the command register with a reset and a DMA nop.
        !          5354:     //
        !          5355: 
        !          5356:     SCSI_WRITE( deviceExtension->Adapter, Command, RESET_SCSI_CHIP );
        !          5357:     SCSI_WRITE( deviceExtension->Adapter, Command, NO_OPERATION_DMA );
        !          5358: 
        !          5359:     return(SP_RETURN_FOUND);
        !          5360: 
        !          5361: }
        !          5362: 
        !          5363: ULONG
        !          5364: NcrMipsFindAdapter(
        !          5365:     IN PVOID ServiceContext,
        !          5366:     IN PVOID Context,
        !          5367:     IN PVOID BusInformation,
        !          5368:     IN PCHAR ArgumentString,
        !          5369:     IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
        !          5370:     OUT PBOOLEAN Again
        !          5371:     )
        !          5372: /*++
        !          5373: 
        !          5374: Routine Description:
        !          5375: 
        !          5376:     This function fills in the configuration information structure and mapes
        !          5377:     the SCSI protocol chip for access.  This routine is temporary until
        !          5378:     the configuration manager supplies similar informtion.
        !          5379: 
        !          5380: Arguments:
        !          5381: 
        !          5382:     ServiceContext - Supplies a pointer to the device extension.
        !          5383: 
        !          5384:     Context - Unused.
        !          5385: 
        !          5386:     BusInformation - Unused.
        !          5387: 
        !          5388:     ArgumentString - Unused.
        !          5389: 
        !          5390:     ConfigInfo - Pointer to the configuration information structure to be
        !          5391:         filled in.
        !          5392: 
        !          5393:     Again - Returns back a request to call this function again.
        !          5394: 
        !          5395: Return Value:
        !          5396: 
        !          5397:     Returns a status value for the initialazitaition.
        !          5398: 
        !          5399: --*/
        !          5400: 
        !          5401: {
        !          5402:     PSPECIFIC_DEVICE_EXTENSION deviceExtension = ServiceContext;
        !          5403:     UCHAR dataByte;
        !          5404:     UCHAR commandSave;
        !          5405: 
        !          5406:     if (ConfigInfo->DmaChannel == SP_UNINITIALIZED_VALUE
        !          5407:         || ConfigInfo->BusInterruptLevel == 0 ||
        !          5408:         (*ConfigInfo->AccessRanges)[0].RangeLength == 0) {
        !          5409:         return(SP_RETURN_NOT_FOUND);
        !          5410:     }
        !          5411: 
        !          5412:     ConfigInfo->NumberOfBuses = 1;
        !          5413: 
        !          5414:     //
        !          5415:     // Get the SCSI bus Id from the configuration information if there
        !          5416:     // is any.
        !          5417:     //
        !          5418: 
        !          5419:     if (ConfigInfo->InitiatorBusId[0] == (CCHAR) SP_UNINITIALIZED_VALUE) {
        !          5420:         deviceExtension->AdapterBusId = INITIATOR_BUS_ID;
        !          5421:         deviceExtension->AdapterBusIdMask = 1 << INITIATOR_BUS_ID;
        !          5422:         ConfigInfo->InitiatorBusId[0] = INITIATOR_BUS_ID;
        !          5423:     } else {
        !          5424:         deviceExtension->AdapterBusId = ConfigInfo->InitiatorBusId[0];
        !          5425:         deviceExtension->AdapterBusIdMask = 1 << ConfigInfo->InitiatorBusId[0];
        !          5426:     }
        !          5427: 
        !          5428:     //
        !          5429:     // Map the SCSI protocol chip into the virtual address space.
        !          5430:     //
        !          5431: 
        !          5432:     deviceExtension->Adapter = ScsiPortGetDeviceBase(
        !          5433:         deviceExtension,                      // HwDeviceExtension
        !          5434:         ConfigInfo->AdapterInterfaceType,     // AdapterInterfaceType
        !          5435:         ConfigInfo->SystemIoBusNumber,        // SystemIoBusNumber
        !          5436:         (*ConfigInfo->AccessRanges)[0].RangeStart,
        !          5437:         (*ConfigInfo->AccessRanges)[0].RangeLength,   // NumberOfBytes
        !          5438:         FALSE                                         // InIoSpace
        !          5439:         );
        !          5440: 
        !          5441:     if (deviceExtension->Adapter == NULL) {
        !          5442:         NcrPrint((0, "\nScsiPortInitialize: Failed to map SCSI device registers into system space.\n"));
        !          5443:         return(SP_RETURN_ERROR);
        !          5444:     }
        !          5445: 
        !          5446:     //
        !          5447:     // Check the iterrupt register.  If it is not equal zero then read it
        !          5448:     // agian it should now be zero.
        !          5449:     //
        !          5450: 
        !          5451:     dataByte = SCSI_READ( deviceExtension->Adapter, ScsiInterrupt );
        !          5452: 
        !          5453:     if (dataByte != 0) {
        !          5454: 
        !          5455:         ScsiPortStallExecution(INTERRUPT_STALL_TIME);
        !          5456:         dataByte = SCSI_READ( deviceExtension->Adapter, ScsiInterrupt );
        !          5457: 
        !          5458:         if (dataByte != 0 ) {
        !          5459:             NcrPrint((1, "NcrMipsFindAdapter: No Ncr53c9x chip found!  Interrupt will not clear.\n"));
        !          5460:             ScsiPortFreeDeviceBase(deviceExtension, deviceExtension->Adapter);
        !          5461:             return(SP_RETURN_NOT_FOUND);
        !          5462:         }
        !          5463:     }
        !          5464: 
        !          5465:     //
        !          5466:     // Test for the interrupt bit in the status register. Some chips do not
        !          5467:     // implement this bit; however, this driver assumes that it exists.
        !          5468:     // The itnerrupt bit is tested for by reseting the chip, giving an
        !          5469:     // illegal command, and checking for an gross error interrupt.
        !          5470:     //
        !          5471: 
        !          5472:     commandSave = SCSI_READ(deviceExtension->Adapter, Command);
        !          5473: 
        !          5474:     SCSI_WRITE( deviceExtension->Adapter, Command, RESET_SCSI_CHIP );
        !          5475:     ScsiPortStallExecution(1);
        !          5476:     SCSI_WRITE( deviceExtension->Adapter, Command, NO_OPERATION_DMA );
        !          5477:     ScsiPortStallExecution(1);
        !          5478: 
        !          5479:     SCSI_WRITE( deviceExtension->Adapter, Command, COMMAND_COMPLETE );
        !          5480:     ScsiPortStallExecution(1);
        !          5481: 
        !          5482:     *((PUCHAR) &deviceExtension->AdapterStatus) = SCSI_READ(
        !          5483:                                                   deviceExtension->Adapter,
        !          5484:                                                   ScsiStatus
        !          5485:                                                   );
        !          5486: 
        !          5487:     dataByte = SCSI_READ( deviceExtension->Adapter, ScsiInterrupt );
        !          5488: 
        !          5489:     //
        !          5490:     // Test for the interrupt.
        !          5491:     //
        !          5492: 
        !          5493:     if (!deviceExtension->AdapterStatus.Interrupt) {
        !          5494: 
        !          5495:         NcrPrint((0, "\nNcrMipsFindAdapter: Ncr53c90 chip without status register interrupt detected.\n"));
        !          5496:         NcrPrint((0, "NcrMipsFindAdapter: Adapter Status: %2x; Adapter Interrupt: %2x\n",
        !          5497:              *((PUCHAR) &deviceExtension->AdapterStatus),
        !          5498:              dataByte
        !          5499:              ));
        !          5500: 
        !          5501:         //
        !          5502:         // Restore the command register.
        !          5503:         //
        !          5504: 
        !          5505:         SCSI_WRITE( deviceExtension->Adapter, Command, commandSave );
        !          5506: 
        !          5507:         ScsiPortFreeDeviceBase(deviceExtension, deviceExtension->Adapter);
        !          5508:         return(SP_RETURN_NOT_FOUND);
        !          5509:     }
        !          5510: 
        !          5511:     //
        !          5512:     // Initialize the NCR SCSI Chip.
        !          5513:     //
        !          5514: 
        !          5515:     SCSI_WRITE( deviceExtension->Adapter, Command, RESET_SCSI_CHIP );
        !          5516: 
        !          5517:     //
        !          5518:     // A NOP command is required to clear the chip reset command.
        !          5519:     //
        !          5520: 
        !          5521:     SCSI_WRITE( deviceExtension->Adapter, Command, NO_OPERATION_DMA );
        !          5522: 
        !          5523:     //
        !          5524:     // Determine the chip type.
        !          5525:     //
        !          5526: 
        !          5527:     //
        !          5528:     // The Ncr53c90 is detected by the absense of configuration register 3.
        !          5529:     // On the other to chips this register is zero after a reset and is read
        !          5530:     // writable.
        !          5531:     //
        !          5532: 
        !          5533:     dataByte = SCSI_READ( deviceExtension->Adapter, Configuration2);
        !          5534: 
        !          5535:     if (dataByte != 0) {
        !          5536: 
        !          5537:         deviceExtension->ChipType = Ncr53c90;
        !          5538: 
        !          5539:     } else {
        !          5540: 
        !          5541:         //
        !          5542:         // Set the Scsi2 and EnablePhaseLatch of the configuration regisiter.
        !          5543:         //
        !          5544: 
        !          5545:         ((PSCSI_CONFIGURATION2)(&dataByte))->Scsi2 = 1;
        !          5546:         ((PSCSI_CONFIGURATION2)(&dataByte))->EnablePhaseLatch = 1;
        !          5547: 
        !          5548:         SCSI_WRITE( deviceExtension->Adapter, Configuration2, dataByte);
        !          5549: 
        !          5550:         //
        !          5551:         // Read the register back if the value is not the same as was written,
        !          5552:         // then this an Ncr53c90.
        !          5553:         //
        !          5554: 
        !          5555:         if (dataByte != SCSI_READ( deviceExtension->Adapter, Configuration2)) {
        !          5556: 
        !          5557:             deviceExtension->ChipType = Ncr53c90;
        !          5558: 
        !          5559:         } else {
        !          5560: 
        !          5561:             deviceExtension->ChipType = Ncr53c94;
        !          5562: 
        !          5563:         }
        !          5564:     }
        !          5565: 
        !          5566:     //
        !          5567:     // The Emulex chip loads the TransferCountPage register with the chip id,
        !          5568:     // if the EnablePhaseLatch is set and a NOP DMA command has been loaded.
        !          5569:     //
        !          5570: 
        !          5571:     if (deviceExtension->ChipType == Ncr53c94) {
        !          5572: 
        !          5573:         //
        !          5574:         // A NOP command is required by the FAS218 to
        !          5575:         // load the TransferCountPage register with the chip Id.
        !          5576:         //
        !          5577: 
        !          5578:         SCSI_WRITE( deviceExtension->Adapter, Command, NO_OPERATION_DMA );
        !          5579: 
        !          5580:         dataByte = SCSI_READ( deviceExtension->Adapter, TransferCountPage);
        !          5581: 
        !          5582:         if (((PNCR_PART_CODE) &dataByte)->ChipFamily == EMULEX_FAS_216) {
        !          5583: 
        !          5584:             deviceExtension->ChipType = Fas216;
        !          5585: 
        !          5586:         } else if (((PNCR_PART_CODE) &dataByte)->ChipFamily == NCR_53c96) {
        !          5587: 
        !          5588:             NcrPrint((1, "NcrFindAdapter: NCR 53c96 chip detected.\n"));
        !          5589:             deviceExtension->ChipType = Fas216;
        !          5590:         }
        !          5591:     }
        !          5592: 
        !          5593:     //
        !          5594:     // Set the parameters according to the chip type.
        !          5595:     //
        !          5596: 
        !          5597:     switch (deviceExtension->ChipType) {
        !          5598:     case Ncr53c94:
        !          5599: 
        !          5600:         NcrPrint((1, "NcrFindAdapter: Ncr 53C94 chip detected.\n"));
        !          5601:         deviceExtension->ClockSpeed = NCR_SCSI_CLOCK_SPEED;
        !          5602:         ConfigInfo->TaggedQueuing = 1;
        !          5603:         ConfigInfo->MaximumTransferLength = 0x10000;
        !          5604:         break;
        !          5605: 
        !          5606:     case Fas216:
        !          5607:         NcrPrint((1, "NcrFindAdapter: Emulex FAS 216 chip detected.\n"));
        !          5608:         deviceExtension->ClockSpeed = EMULEX_SCSI_CLOCK_SPEED;
        !          5609:         ConfigInfo->TaggedQueuing = 1;
        !          5610:         ConfigInfo->MaximumTransferLength = 0x1000000-0x1000;
        !          5611:         deviceExtension->Configuration3.CheckIdMessage = 1;
        !          5612:         break;
        !          5613: 
        !          5614:     case Ncr53c90:
        !          5615: 
        !          5616:         NcrPrint((1, "NcrFindAdapter: Ncr 53C90 chip detected.\n"));
        !          5617: 
        !          5618:     default:
        !          5619:         *Again = FALSE;
        !          5620:         return(SP_RETURN_BAD_CONFIG);
        !          5621:     }
        !          5622: 
        !          5623:     //
        !          5624:     // If the clock speed is greater than 25 Mhz then set the fast clock
        !          5625:     // bit in configuration register.
        !          5626:     //
        !          5627: 
        !          5628:     if (deviceExtension->ClockSpeed > 25) {
        !          5629:         deviceExtension->Configuration3.FastClock = 1;
        !          5630:     }
        !          5631: 
        !          5632:    *Again = FALSE;
        !          5633:    return(SP_RETURN_FOUND);
        !          5634: 
        !          5635: }

unix.superglobalmegacorp.com

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