Annotation of ntddk/src/scsi/ncr53c9x/ncr53c9x.c, revision 1.1.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.