|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.