|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1990 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: aha154x.c ! 8: ! 9: Abstract: ! 10: ! 11: This is the port driver for the Adaptec 1540B SCSI Adapter. ! 12: ! 13: Author: ! 14: ! 15: Mike Glass ! 16: Tuong Hoang (Adaptec) ! 17: ! 18: Environment: ! 19: ! 20: kernel mode only ! 21: ! 22: Notes: ! 23: ! 24: Revision History: ! 25: ! 26: --*/ ! 27: ! 28: #include "miniport.h" ! 29: #include "aha154x.h" // includes scsi.h ! 30: ! 31: // ! 32: // This conditionally compiles in the code to force the DMA transfer speed ! 33: // to 5.0. ! 34: // ! 35: ! 36: #define FORCE_DMA_SPEED 1 ! 37: ! 38: // ! 39: // The following structure is allocated ! 40: // from noncached memory as data will be DMA'd to ! 41: // and from it. ! 42: // ! 43: ! 44: typedef struct _NONCACHED_EXTENSION { ! 45: ! 46: // ! 47: // Physical base address of mailboxes ! 48: // ! 49: ! 50: ULONG MailboxPA; ! 51: ! 52: // ! 53: // Mailboxes ! 54: // ! 55: ! 56: MBO Mbo[MB_COUNT]; ! 57: MBI Mbi[MB_COUNT]; ! 58: ! 59: } NONCACHED_EXTENSION, *PNONCACHED_EXTENSION; ! 60: ! 61: // ! 62: // Device extension ! 63: // ! 64: ! 65: typedef struct _HW_DEVICE_EXTENSION { ! 66: ! 67: // ! 68: // NonCached extension ! 69: // ! 70: ! 71: PNONCACHED_EXTENSION NoncachedExtension; ! 72: ! 73: // ! 74: // Adapter parameters ! 75: // ! 76: ! 77: PBASE_REGISTER BaseIoAddress; ! 78: ! 79: // ! 80: // Host Target id. ! 81: // ! 82: ! 83: UCHAR HostTargetId; ! 84: ! 85: // ! 86: // Old in\out box indexes. ! 87: // ! 88: ! 89: UCHAR MboIndex; ! 90: ! 91: UCHAR MbiIndex; ! 92: ! 93: // ! 94: // Pending request. ! 95: // ! 96: ! 97: BOOLEAN PendingRequest; ! 98: ! 99: // ! 100: // Bus on time to use. ! 101: // ! 102: ! 103: UCHAR BusOnTime; ! 104: ! 105: } HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION; ! 106: ! 107: // ! 108: // Logical unit extension ! 109: // ! 110: ! 111: typedef struct _HW_LU_EXTENSION { ! 112: PSCSI_REQUEST_BLOCK CurrentSrb; ! 113: } HW_LU_EXTENSION, *PHW_LU_EXTENSION; ! 114: ! 115: ! 116: // ! 117: // Function declarations ! 118: // ! 119: // Functions that start with 'A154x' are entry points ! 120: // for the OS port driver. ! 121: // ! 122: ! 123: ULONG ! 124: DriverEntry( ! 125: IN PVOID DriverObject, ! 126: IN PVOID Argument2 ! 127: ); ! 128: ! 129: ULONG ! 130: A154xDetermineInstalled( ! 131: IN PHW_DEVICE_EXTENSION HwDeviceExtension, ! 132: IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, ! 133: IN OUT PULONG AdapterCount, ! 134: OUT PBOOLEAN Again ! 135: ); ! 136: ! 137: ULONG ! 138: A154xFindAdapter( ! 139: IN PVOID HwDeviceExtension, ! 140: IN PVOID Context, ! 141: IN PVOID BusInformation, ! 142: IN PCHAR ArgumentString, ! 143: IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, ! 144: OUT PBOOLEAN Again ! 145: ); ! 146: ! 147: BOOLEAN ! 148: A154xHwInitialize( ! 149: IN PVOID DeviceExtension ! 150: ); ! 151: ! 152: BOOLEAN ! 153: A154xStartIo( ! 154: IN PVOID DeviceExtension, ! 155: IN PSCSI_REQUEST_BLOCK Srb ! 156: ); ! 157: ! 158: BOOLEAN ! 159: A154xInterrupt( ! 160: IN PVOID DeviceExtension ! 161: ); ! 162: ! 163: BOOLEAN ! 164: A154xResetBus( ! 165: IN PVOID HwDeviceExtension, ! 166: IN ULONG PathId ! 167: ); ! 168: ! 169: VOID ! 170: GetHostAdapterBoardId ( ! 171: IN PVOID HwDeviceExtension, ! 172: OUT PUCHAR BoardId ! 173: ); ! 174: ! 175: // ! 176: // This function is called from A154xStartIo. ! 177: // ! 178: ! 179: VOID ! 180: BuildCcb( ! 181: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 182: IN PSCSI_REQUEST_BLOCK Srb ! 183: ); ! 184: ! 185: // ! 186: // This function is called from BuildCcb. ! 187: // ! 188: ! 189: VOID ! 190: BuildSdl( ! 191: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 192: IN PSCSI_REQUEST_BLOCK Srb ! 193: ); ! 194: ! 195: // ! 196: // This function is called from A154xInitialize. ! 197: // ! 198: ! 199: BOOLEAN ! 200: AdapterPresent( ! 201: IN PVOID HwDeviceExtension ! 202: ); ! 203: ! 204: // ! 205: // This function is called from A154xInterrupt. ! 206: // ! 207: ! 208: UCHAR ! 209: MapError( ! 210: IN PVOID HwDeviceExtension, ! 211: IN PSCSI_REQUEST_BLOCK Srb, ! 212: IN PCCB Ccb ! 213: ); ! 214: ! 215: BOOLEAN ! 216: ReadCommandRegister( ! 217: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 218: OUT PUCHAR DataByte, ! 219: IN BOOLEAN TimeOutFlag ! 220: ); ! 221: ! 222: BOOLEAN ! 223: WriteCommandRegister( ! 224: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 225: IN UCHAR AdapterCommand, ! 226: IN BOOLEAN LogError ! 227: ); ! 228: ! 229: BOOLEAN ! 230: WriteDataRegister( ! 231: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 232: IN UCHAR DataByte ! 233: ); ! 234: ! 235: BOOLEAN ! 236: ScatterGatherSupported ( ! 237: IN PHW_DEVICE_EXTENSION HwDeviceExtension ! 238: ); ! 239: ! 240: BOOLEAN ! 241: FinishHBACmd( ! 242: IN PHW_DEVICE_EXTENSION HwDeviceExtension ! 243: ); ! 244: ! 245: BOOLEAN ! 246: SpinForInterrupt( ! 247: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 248: IN BOOLEAN TimeOutFlag ! 249: ); ! 250: ! 251: BOOLEAN SendUnlockCommand( ! 252: IN PVOID HwDeviceExtension, ! 253: IN UCHAR locktype ! 254: ); ! 255: ! 256: BOOLEAN UnlockMailBoxes( ! 257: IN PVOID HwDeviceExtension ! 258: ); ! 259: ! 260: ULONG ! 261: AhaParseArgumentString( ! 262: IN PCHAR String, ! 263: IN PCHAR KeyWord ! 264: ); ! 265: ! 266: ULONG ! 267: DriverEntry( ! 268: IN PVOID DriverObject, ! 269: IN PVOID Argument2 ! 270: ) ! 271: ! 272: /*++ ! 273: ! 274: Routine Description: ! 275: ! 276: Installable driver initialization entry point for system. ! 277: ! 278: Arguments: ! 279: ! 280: Driver Object ! 281: ! 282: Return Value: ! 283: ! 284: Status from ScsiPortInitialize() ! 285: ! 286: --*/ ! 287: ! 288: { ! 289: HW_INITIALIZATION_DATA hwInitializationData; ! 290: ULONG adapterCount; ! 291: ULONG isaStatus; ! 292: ULONG mcaStatus; ! 293: ULONG i; ! 294: ! 295: DebugPrint((1,"\n\nSCSI Adaptec 154X MiniPort Driver\n")); ! 296: ! 297: // ! 298: // Zero out structure. ! 299: // ! 300: ! 301: for (i=0; i<sizeof(HW_INITIALIZATION_DATA); i++) { ! 302: ((PUCHAR)&hwInitializationData)[i] = 0; ! 303: } ! 304: ! 305: // ! 306: // Set size of hwInitializationData. ! 307: // ! 308: ! 309: hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA); ! 310: ! 311: // ! 312: // Set entry points. ! 313: // ! 314: ! 315: hwInitializationData.HwInitialize = A154xHwInitialize; ! 316: hwInitializationData.HwResetBus = A154xResetBus; ! 317: hwInitializationData.HwStartIo = A154xStartIo; ! 318: hwInitializationData.HwInterrupt = A154xInterrupt; ! 319: hwInitializationData.HwFindAdapter = A154xFindAdapter; ! 320: ! 321: // ! 322: // Indicate no buffer mapping but will need physical addresses. ! 323: // ! 324: ! 325: hwInitializationData.NeedPhysicalAddresses = TRUE; ! 326: ! 327: // ! 328: // Specify size of extensions. ! 329: // ! 330: ! 331: hwInitializationData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); ! 332: hwInitializationData.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION); ! 333: ! 334: // ! 335: // Specifiy the bus type. ! 336: // ! 337: ! 338: hwInitializationData.AdapterInterfaceType = Isa; ! 339: hwInitializationData.NumberOfAccessRanges = 1; ! 340: ! 341: // ! 342: // Ask for SRB extensions for CCBs. ! 343: // ! 344: ! 345: hwInitializationData.SrbExtensionSize = sizeof(CCB); ! 346: ! 347: // ! 348: // The adapter count is used by the find adapter routine to track how ! 349: // which adapter addresses have been tested. ! 350: // ! 351: ! 352: adapterCount = 0; ! 353: ! 354: isaStatus = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, &adapterCount); ! 355: ! 356: // ! 357: // Now try to configure for the Mca bus. ! 358: // Specifiy the bus type. ! 359: // ! 360: ! 361: hwInitializationData.AdapterInterfaceType = MicroChannel; ! 362: adapterCount = 0; ! 363: mcaStatus = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, &adapterCount); ! 364: ! 365: // ! 366: // Return the smaller status. ! 367: // ! 368: ! 369: return(mcaStatus < isaStatus ? mcaStatus : isaStatus); ! 370: ! 371: } // end A154xEntry() ! 372: ! 373: ! 374: ULONG ! 375: A154xFindAdapter( ! 376: IN PVOID HwDeviceExtension, ! 377: IN PVOID Context, ! 378: IN PVOID BusInformation, ! 379: IN PCHAR ArgumentString, ! 380: IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, ! 381: OUT PBOOLEAN Again ! 382: ) ! 383: /*++ ! 384: ! 385: Routine Description: ! 386: ! 387: This function is called by the OS-specific port driver after ! 388: the necessary storage has been allocated, to gather information ! 389: about the adapter's configuration. ! 390: ! 391: Arguments: ! 392: ! 393: HwDeviceExtension - HBA miniport driver's adapter data storage ! 394: Context - Register base address ! 395: ConfigInfo - Configuration information structure describing HBA ! 396: This structure is defined in PORT.H. ! 397: ! 398: Return Value: ! 399: ! 400: ULONG ! 401: ! 402: --*/ ! 403: ! 404: { ! 405: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; ! 406: ULONG length; ! 407: ULONG status; ! 408: UCHAR adapterTid; ! 409: UCHAR dmaChannel; ! 410: UCHAR irq; ! 411: UCHAR bit; ! 412: ! 413: // ! 414: // Determine if there are any adapters installed. Determine installed ! 415: // will initialize the BaseIoAddress if an adapter is found. ! 416: // ! 417: ! 418: status = A154xDetermineInstalled(deviceExtension, ! 419: ConfigInfo, ! 420: Context, ! 421: Again); ! 422: ! 423: // ! 424: // If there are not adapter's found then return. ! 425: // ! 426: ! 427: if (status != SP_RETURN_FOUND) { ! 428: return(status); ! 429: } ! 430: ! 431: // ! 432: // Issue adapter command to get IRQ. ! 433: // ! 434: // Returns 3 data bytes: ! 435: // ! 436: // Byte 0 Dma Channel ! 437: // ! 438: // Byte 1 Interrupt Channel ! 439: // ! 440: // Byte 2 Adapter SCSI ID ! 441: // ! 442: ! 443: if (!WriteCommandRegister(deviceExtension, AC_RET_CONFIGURATION_DATA, TRUE)) { ! 444: DebugPrint((1,"A154xFindAdapter: Get configuration data command failed\n")); ! 445: return SP_RETURN_ERROR; ! 446: } ! 447: ! 448: // ! 449: // Determine DMA channel. ! 450: // ! 451: ! 452: if (!ReadCommandRegister(deviceExtension,&dmaChannel,TRUE)) { ! 453: DebugPrint((1,"A154xFindAdapter: Couldn't read dma channel\n")); ! 454: return SP_RETURN_ERROR; ! 455: } ! 456: ! 457: if (ConfigInfo->AdapterInterfaceType != MicroChannel) { ! 458: ! 459: WHICH_BIT(dmaChannel,bit); ! 460: ! 461: ConfigInfo->DmaChannel = bit; ! 462: ! 463: DebugPrint((2,"A154xFindAdapter: DMA channel is %x\n", ! 464: ConfigInfo->DmaChannel)); ! 465: ! 466: } else { ! 467: ConfigInfo->InterruptMode = LevelSensitive; ! 468: } ! 469: ! 470: // ! 471: // Determine hardware interrupt vector. ! 472: // ! 473: ! 474: if (!ReadCommandRegister(deviceExtension,&irq,TRUE)) { ! 475: DebugPrint((1,"A154xFindAdapter: Couldn't read adapter irq\n")); ! 476: return SP_RETURN_ERROR; ! 477: } ! 478: ! 479: WHICH_BIT(irq, bit); ! 480: ! 481: ConfigInfo->BusInterruptLevel = (UCHAR) 9 + bit; ! 482: ! 483: // ! 484: // Determine what SCSI bus id the adapter is on. ! 485: // ! 486: ! 487: if (!ReadCommandRegister(deviceExtension,&adapterTid,TRUE)) { ! 488: DebugPrint((1,"A154xFindAdapter: Couldn't read adapter SCSI id\n")); ! 489: return SP_RETURN_ERROR; ! 490: } ! 491: ! 492: // ! 493: // Set number of buses. ! 494: // ! 495: ! 496: ConfigInfo->NumberOfBuses = 1; ! 497: ConfigInfo->InitiatorBusId[0] = adapterTid; ! 498: deviceExtension->HostTargetId = adapterTid; ! 499: ! 500: ConfigInfo->MaximumTransferLength = MAX_TRANSFER_SIZE; ! 501: ConfigInfo->NumberOfPhysicalBreaks = MAX_SG_DESCRIPTORS - 1; ! 502: ConfigInfo->ScatterGather = ScatterGatherSupported(HwDeviceExtension); ! 503: ! 504: if (!ConfigInfo->ScatterGather) { ! 505: //ConfigInfo->NumberOfPhysicalBreaks = 1; ! 506: DebugPrint((1,"Aha154x: Scatter/Gather not supported!")); ! 507: } ! 508: ! 509: ConfigInfo->Master = TRUE; ! 510: ! 511: // ! 512: // Allocate a Noncached Extension to use for mail boxes. ! 513: // ! 514: ! 515: deviceExtension->NoncachedExtension = ScsiPortGetUncachedExtension( ! 516: deviceExtension, ! 517: ConfigInfo, ! 518: sizeof(NONCACHED_EXTENSION)); ! 519: ! 520: if (deviceExtension->NoncachedExtension == NULL) { ! 521: ! 522: // ! 523: // Log error. ! 524: // ! 525: ! 526: ScsiPortLogError( ! 527: deviceExtension, ! 528: NULL, ! 529: 0, ! 530: 0, ! 531: 0, ! 532: SP_INTERNAL_ADAPTER_ERROR, ! 533: 7 << 8 ! 534: ); ! 535: ! 536: return(SP_RETURN_ERROR); ! 537: } ! 538: ! 539: // ! 540: // Convert virtual to physical mailbox address. ! 541: // ! 542: ! 543: deviceExtension->NoncachedExtension->MailboxPA = ! 544: ScsiPortConvertPhysicalAddressToUlong( ! 545: ScsiPortGetPhysicalAddress(deviceExtension, ! 546: NULL, ! 547: deviceExtension->NoncachedExtension->Mbo, ! 548: &length)); ! 549: ! 550: // ! 551: // Set default bus on time. Then check for an override parameter. ! 552: // ! 553: ! 554: deviceExtension->BusOnTime = 0x07; ! 555: if (ArgumentString != NULL) { ! 556: ! 557: length = AhaParseArgumentString(ArgumentString, "BUSONTIME"); ! 558: ! 559: // ! 560: // Validate that the new bus on time is reasonable before attempting ! 561: // to set it. ! 562: // ! 563: ! 564: if (length >= 2 && length <= 15) { ! 565: ! 566: deviceExtension->BusOnTime = (UCHAR) length; ! 567: DebugPrint((1,"A154xFindAdapter: Setting bus on time: %ld\n", length)); ! 568: } ! 569: } ! 570: ! 571: DebugPrint((3,"A154xFindAdapter: Configuration completed\n")); ! 572: return SP_RETURN_FOUND; ! 573: } // end A154xFindAdapter() ! 574: ! 575: ! 576: BOOLEAN ! 577: AdaptecAdapter( ! 578: IN PHW_DEVICE_EXTENSION HwDeviceExtension, ! 579: IN ULONG IoPort, ! 580: IN BOOLEAN Mca ! 581: ) ! 582: ! 583: /*++ ! 584: ! 585: Routine Description: ! 586: ! 587: This routine checks the Special Options byte of the Adapter Inquiry ! 588: command to see if it is one of the two values returned by Adaptec ! 589: Adapters. This avoids claiming adapters from BusLogic and DTC. ! 590: ! 591: Arguments: ! 592: ! 593: HwDeviceExtension - miniport driver's adapter extension. ! 594: ! 595: Return Values: ! 596: ! 597: TRUE if the adapter looks like an Adaptec. ! 598: FALSE if not. ! 599: ! 600: --*/ ! 601: ! 602: { ! 603: ULONG i; ! 604: UCHAR byte; ! 605: UCHAR specialOptions; ! 606: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; ! 607: PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress; ! 608: ! 609: if (Mca == TRUE) { ! 610: INIT_DATA initData; ! 611: LONG slot; ! 612: LONG i; ! 613: ! 614: for (slot = 0; slot < NUMBER_POS_SLOTS; slot++) { ! 615: i = ScsiPortGetBusData(HwDeviceExtension, ! 616: Pos, ! 617: 0, ! 618: slot, ! 619: &initData.PosData[slot], ! 620: sizeof(POS_DATA)); ! 621: if (i < (sizeof(POS_DATA))) { ! 622: initData.PosData[slot].AdapterId = 0xffff; ! 623: } ! 624: } ! 625: ! 626: for (slot = 0; slot < NUMBER_POS_SLOTS; slot++) { ! 627: if (initData.PosData[slot].AdapterId == POS_IDENTIFIER) { ! 628: switch (initData.PosData[slot].IoPortInformation & POS_PORT_MASK) { ! 629: case POS_PORT_130: ! 630: if (IoPort == 0x0130) { ! 631: return TRUE; ! 632: } ! 633: break; ! 634: case POS_PORT_134: ! 635: if (IoPort == 0x0134) { ! 636: return TRUE; ! 637: } ! 638: break; ! 639: case POS_PORT_230: ! 640: if (IoPort == 0x0230) { ! 641: return TRUE; ! 642: } ! 643: break; ! 644: case POS_PORT_234: ! 645: if (IoPort == 0x234) { ! 646: return TRUE; ! 647: } ! 648: break; ! 649: case POS_PORT_330: ! 650: if (IoPort == 0x330) { ! 651: return TRUE; ! 652: } ! 653: break; ! 654: case POS_PORT_334: ! 655: if (IoPort == 0x334) { ! 656: return TRUE; ! 657: } ! 658: break; ! 659: } ! 660: } ! 661: } ! 662: return FALSE; ! 663: } ! 664: ! 665: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, ! 666: IOP_INTERRUPT_RESET); ! 667: ! 668: if (!WriteCommandRegister(HwDeviceExtension,AC_ADAPTER_INQUIRY,FALSE)) { ! 669: return FALSE; ! 670: } ! 671: ! 672: // ! 673: // Byte 0. ! 674: // ! 675: ! 676: if ((ReadCommandRegister(HwDeviceExtension,&byte,TRUE)) == FALSE) { ! 677: return FALSE; ! 678: } ! 679: ! 680: // ! 681: // Get the special options byte. ! 682: // ! 683: ! 684: if ((ReadCommandRegister(HwDeviceExtension,&specialOptions,TRUE)) == FALSE) { ! 685: return FALSE; ! 686: } ! 687: ! 688: // ! 689: // Get the last two bytes and clear the interrupt. ! 690: // ! 691: ! 692: if ((ReadCommandRegister(HwDeviceExtension,&byte,TRUE)) == FALSE) { ! 693: return FALSE; ! 694: } ! 695: ! 696: if ((ReadCommandRegister(HwDeviceExtension,&byte,TRUE)) == FALSE) { ! 697: return FALSE; ! 698: } ! 699: ! 700: // ! 701: // Interrupt handler is not yet installed so wait for HACC by hand. ! 702: // ! 703: ! 704: for (i = 0; i<5000; i++) { ! 705: if (ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister) == ! 706: (IOP_ANY_INTERRUPT | IOP_COMMAND_COMPLETE) ) { ! 707: break; ! 708: } ! 709: ScsiPortStallExecution(1); ! 710: } ! 711: ! 712: if ((specialOptions == 0x30) || (specialOptions == 0x42)) { ! 713: return TRUE; ! 714: } ! 715: ! 716: return FALSE; ! 717: } ! 718: ! 719: ULONG ! 720: A154xDetermineInstalled( ! 721: IN PHW_DEVICE_EXTENSION HwDeviceExtension, ! 722: IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, ! 723: IN OUT PULONG AdapterCount, ! 724: OUT PBOOLEAN Again ! 725: ) ! 726: ! 727: /*++ ! 728: ! 729: Routine Description: ! 730: ! 731: Determine if Adaptec 154X SCSI adapter is installed in system ! 732: by reading the status register as each base I/O address ! 733: and looking for a pattern. If an adapter is found, the BaseIoAddres is ! 734: initialized. ! 735: ! 736: Arguments: ! 737: ! 738: HwDeviceExtension - HBA miniport driver's adapter data storage ! 739: ! 740: ConfigInfo - Supplies the known configuraiton information. ! 741: ! 742: AdapterCount - Supplies the count of adapter slots which have been tested. ! 743: ! 744: Again - Returns whehter the OS specific driver should call again. ! 745: ! 746: Return Value: ! 747: ! 748: Returns a status indicating whether a driver is present or not. ! 749: ! 750: --*/ ! 751: ! 752: { ! 753: PBASE_REGISTER baseIoAddress; ! 754: PUCHAR ioSpace; ! 755: UCHAR portValue; ! 756: ! 757: // ! 758: // The following table specifies the ports to be checked when searching for ! 759: // an adapter. A zero entry terminates the search. ! 760: // ! 761: ! 762: CONST ULONG AdapterAddresses[7] = {0X330, 0X334, 0X234, 0X134, 0X130, 0X230, 0}; ! 763: ! 764: ! 765: // ! 766: // Get the system physical address for this card. The card uses I/O space. ! 767: // ! 768: ! 769: ioSpace = ScsiPortGetDeviceBase( ! 770: HwDeviceExtension, // HwDeviceExtension ! 771: ConfigInfo->AdapterInterfaceType, // AdapterInterfaceType ! 772: ConfigInfo->SystemIoBusNumber, // SystemIoBusNumber ! 773: ScsiPortConvertUlongToPhysicalAddress(0), ! 774: 0x400, // NumberOfBytes ! 775: TRUE // InIoSpace ! 776: ); ! 777: ! 778: // ! 779: // Scan though the adapter address looking for adapters. ! 780: // ! 781: ! 782: while (AdapterAddresses[*AdapterCount] != 0) { ! 783: ! 784: // ! 785: // Check to see if adapter present in system. ! 786: // ! 787: ! 788: baseIoAddress = (PBASE_REGISTER)(ioSpace + AdapterAddresses[*AdapterCount]); ! 789: HwDeviceExtension->BaseIoAddress = baseIoAddress; ! 790: ! 791: // ! 792: // Update the adapter count. ! 793: // ! 794: ! 795: (*AdapterCount)++; ! 796: ! 797: portValue = ScsiPortReadPortUchar((PUCHAR)baseIoAddress); ! 798: ! 799: // ! 800: // Check for Adaptec adapter. ! 801: // The mask (0x29) are bits that may or may not be set. ! 802: // The bit 0x10 (IOP_SCSI_HBA_IDLE) should be set. ! 803: // ! 804: ! 805: if ((portValue & ~0x29) == IOP_SCSI_HBA_IDLE) { ! 806: ! 807: if (!AdaptecAdapter(HwDeviceExtension, AdapterAddresses[(*AdapterCount) - 1], ! 808: (BOOLEAN)(ConfigInfo->AdapterInterfaceType == MicroChannel ? TRUE : FALSE))) { ! 809: DebugPrint((1,"A154xDetermineInstalled: Clone command completed successfully - \n not our board;")); ! 810: continue; ! 811: } ! 812: ! 813: // ! 814: // An adapter has been found. Set the base address in the device ! 815: // extension, and request another call. ! 816: // ! 817: ! 818: HwDeviceExtension->BaseIoAddress = baseIoAddress; ! 819: *Again = TRUE; ! 820: ! 821: // ! 822: // Fill in the access array information. ! 823: // ! 824: ! 825: (*ConfigInfo->AccessRanges)[0].RangeStart = ! 826: ScsiPortConvertUlongToPhysicalAddress( ! 827: AdapterAddresses[*AdapterCount - 1]); ! 828: (*ConfigInfo->AccessRanges)[0].RangeLength = 4; ! 829: (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE; ! 830: ! 831: return(SP_RETURN_FOUND); ! 832: } ! 833: } ! 834: ! 835: // ! 836: // The entire table has been searched and no adapters have been found. ! 837: // There is no need to call again and the device base can now be freed. ! 838: // Clear the adapter count for the next bus. ! 839: // ! 840: ! 841: *Again = FALSE; ! 842: *(AdapterCount) = 0; ! 843: ! 844: ScsiPortFreeDeviceBase( ! 845: HwDeviceExtension, ! 846: ioSpace ! 847: ); ! 848: ! 849: return(SP_RETURN_NOT_FOUND); ! 850: ! 851: } // end A154xDetermineInstalled() ! 852: ! 853: ! 854: BOOLEAN ! 855: A154xHwInitialize( ! 856: IN PVOID HwDeviceExtension ! 857: ) ! 858: ! 859: /*++ ! 860: ! 861: Routine Description: ! 862: ! 863: This routine is called from ScsiPortInitialize ! 864: to set up the adapter so that it is ready to service requests. ! 865: ! 866: Arguments: ! 867: ! 868: HwDeviceExtension - HBA miniport driver's adapter data storage ! 869: ! 870: Return Value: ! 871: ! 872: TRUE - if initialization successful. ! 873: FALSE - if initialization unsuccessful. ! 874: ! 875: --*/ ! 876: ! 877: { ! 878: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; ! 879: PNONCACHED_EXTENSION noncachedExtension = ! 880: deviceExtension->NoncachedExtension; ! 881: PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress; ! 882: UCHAR status; ! 883: ULONG i; ! 884: ! 885: DebugPrint((2,"A154xHwInitialize: Reset aha154X and SCSI bus\n")); ! 886: ! 887: // ! 888: // Reset SCSI chip. ! 889: // ! 890: ! 891: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_HARD_RESET); ! 892: ! 893: // ! 894: // Inform the port driver that the bus has been reset. ! 895: // ! 896: ! 897: ScsiPortNotification(ResetDetected, HwDeviceExtension, 0); ! 898: ! 899: ScsiPortStallExecution(500*1000); ! 900: ! 901: // ! 902: // Wait up to 5000 microseconds for adapter to initialize. ! 903: // ! 904: ! 905: for (i = 0; i < 5000; i++) { ! 906: ! 907: ScsiPortStallExecution(1); ! 908: ! 909: status = ScsiPortReadPortUchar(&deviceExtension->BaseIoAddress->StatusRegister); ! 910: ! 911: if (status & IOP_SCSI_HBA_IDLE) { ! 912: break; ! 913: } ! 914: } ! 915: ! 916: // ! 917: // Check if reset failed or succeeded. ! 918: // ! 919: ! 920: if (!(status & IOP_SCSI_HBA_IDLE) || !(status & IOP_MAILBOX_INIT_REQUIRED)) { ! 921: DebugPrint((1,"A154xInitialize: Reset SCSI bus failed\n")); ! 922: return FALSE; ! 923: } ! 924: ! 925: // ! 926: // Unlock mailboxes in case the adapter is a 1540B with 1Gb support ! 927: // or 1540C with extended translation enabled. ! 928: // ! 929: ! 930: status = UnlockMailBoxes(deviceExtension); ! 931: (VOID) SpinForInterrupt(deviceExtension,FALSE); ! 932: ! 933: // ! 934: // Zero out mailboxes. ! 935: // ! 936: ! 937: for (i=0; i<MB_COUNT; i++) { ! 938: ! 939: PMBO mailboxOut; ! 940: PMBI mailboxIn; ! 941: ! 942: mailboxIn = &noncachedExtension->Mbi[i]; ! 943: mailboxOut = &noncachedExtension->Mbo[i]; ! 944: ! 945: mailboxOut->Command = mailboxIn->Status = 0; ! 946: } ! 947: ! 948: // ! 949: // Zero preivous indexes. ! 950: // ! 951: ! 952: deviceExtension->MboIndex = 0; ! 953: deviceExtension->MbiIndex = 0; ! 954: ! 955: DebugPrint((3,"A154xHwInitialize: Initialize mailbox\n")); ! 956: ! 957: if (!WriteCommandRegister(deviceExtension,AC_MAILBOX_INITIALIZATION, TRUE)) { ! 958: DebugPrint((1,"A154xHwInitialize: Couldn't initialize mailboxes\n")); ! 959: return FALSE; ! 960: } ! 961: ! 962: // ! 963: // Send Adapter number of mailbox locations. ! 964: // ! 965: ! 966: if (!WriteDataRegister(deviceExtension, MB_COUNT)) { ! 967: return FALSE; ! 968: } ! 969: ! 970: // ! 971: // Send the most significant byte of the mailbox physical address. ! 972: // ! 973: ! 974: if (!WriteDataRegister(deviceExtension, ! 975: ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte2)) { ! 976: return FALSE; ! 977: } ! 978: ! 979: // ! 980: // Send the middle byte of the mailbox physical address. ! 981: // ! 982: ! 983: if (!WriteDataRegister(deviceExtension, ! 984: ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte1)) { ! 985: return FALSE; ! 986: } ! 987: ! 988: // ! 989: // Send the least significant byte of the mailbox physical address. ! 990: // ! 991: ! 992: if (!WriteDataRegister(deviceExtension, ! 993: ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte0)) { ! 994: return FALSE; ! 995: } ! 996: ! 997: #ifdef FORCE_DMA_SPEED ! 998: // ! 999: // Set the DMA transfer speed to 5.0 MB/second. This is because ! 1000: // faster transfer speeds cause data corruption on 486/33 machines. ! 1001: // This overrides the card jumper setting. ! 1002: // ! 1003: ! 1004: if (!WriteCommandRegister(deviceExtension, AC_SET_TRANSFER_SPEED, TRUE)) { ! 1005: ! 1006: DebugPrint((1,"Can't set dma transfer speed\n")); ! 1007: ! 1008: } else if (!WriteDataRegister(deviceExtension, DMA_SPEED_50_MBS)) { ! 1009: ! 1010: DebugPrint((1,"Can't set dma transfer speed\n")); ! 1011: } ! 1012: ! 1013: // ! 1014: // Wait for interrupt. ! 1015: // ! 1016: ! 1017: if (!SpinForInterrupt(deviceExtension,TRUE)) { ! 1018: ! 1019: DebugPrint((1,"Timed out waiting for adapter command to complete\n")); ! 1020: return TRUE; ! 1021: } ! 1022: #endif ! 1023: ! 1024: // ! 1025: // Override default setting for bus on time. This makes floppy ! 1026: // drives work better with this adapter. ! 1027: // ! 1028: ! 1029: if (!WriteCommandRegister(deviceExtension, AC_SET_BUS_ON_TIME, TRUE)) { ! 1030: ! 1031: DebugPrint((1,"Can't set bus on time\n")); ! 1032: ! 1033: } else if (!WriteDataRegister(deviceExtension, deviceExtension->BusOnTime)) { ! 1034: ! 1035: DebugPrint((1,"Can't set bus on time\n")); ! 1036: } ! 1037: ! 1038: // ! 1039: // Wait for interrupt. ! 1040: // ! 1041: ! 1042: if (!SpinForInterrupt(deviceExtension,TRUE)) { ! 1043: ! 1044: DebugPrint((1,"Timed out waiting for adapter command to complete\n")); ! 1045: return TRUE; ! 1046: } ! 1047: ! 1048: ! 1049: // ! 1050: // Override the default CCB timeout of 250 mseconds to 500 (0x1F4). ! 1051: // ! 1052: ! 1053: if (!WriteCommandRegister(deviceExtension, AC_SET_SELECTION_TIMEOUT, TRUE)) { ! 1054: DebugPrint((1,"A154xHwInitialize: Can't set CCB timeout\n")); ! 1055: } ! 1056: else { ! 1057: if (!WriteDataRegister(deviceExtension,0x01)) { ! 1058: DebugPrint((1,"A154xHwInitialize: Can't set timeout selection enable\n")); ! 1059: } ! 1060: ! 1061: if (!WriteDataRegister(deviceExtension,0x00)) { ! 1062: DebugPrint((1,"A154xHwInitialize: Can't set second byte\n")); ! 1063: } ! 1064: ! 1065: if (!WriteDataRegister(deviceExtension,0x01)) { ! 1066: DebugPrint((1,"A154xHwInitialize: Can't set MSB\n")); ! 1067: } ! 1068: ! 1069: if (!WriteDataRegister(deviceExtension,0xF4)) { ! 1070: DebugPrint((1,"A154xHwInitialize: Can't set LSB\n")); ! 1071: } ! 1072: } ! 1073: ! 1074: ! 1075: // ! 1076: // Wait for interrupt. ! 1077: // ! 1078: ! 1079: if (!SpinForInterrupt(deviceExtension,TRUE)) { ! 1080: ! 1081: DebugPrint((1,"Timed out waiting for adapter command to complete\n")); ! 1082: return TRUE; ! 1083: } ! 1084: ! 1085: ! 1086: return TRUE; ! 1087: ! 1088: } // end A154xHwInitialize() ! 1089: ! 1090: ! 1091: BOOLEAN ! 1092: A154xStartIo( ! 1093: IN PVOID HwDeviceExtension, ! 1094: IN PSCSI_REQUEST_BLOCK Srb ! 1095: ) ! 1096: ! 1097: /*++ ! 1098: ! 1099: Routine Description: ! 1100: ! 1101: This routine is called from the SCSI port driver synchronized ! 1102: with the kernel. The mailboxes are scanned for an empty one and ! 1103: the CCB is written to it. Then the doorbell is rung and the ! 1104: OS port driver is notified that the adapter can take ! 1105: another request, if any are available. ! 1106: ! 1107: Arguments: ! 1108: ! 1109: HwDeviceExtension - HBA miniport driver's adapter data storage ! 1110: Srb - IO request packet ! 1111: ! 1112: Return Value: ! 1113: ! 1114: TRUE ! 1115: ! 1116: --*/ ! 1117: ! 1118: { ! 1119: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; ! 1120: PNONCACHED_EXTENSION noncachedExtension = ! 1121: deviceExtension->NoncachedExtension; ! 1122: PMBO mailboxOut; ! 1123: PCCB ccb; ! 1124: PHW_LU_EXTENSION luExtension; ! 1125: ! 1126: ULONG i = deviceExtension->MboIndex; ! 1127: ULONG physicalCcb; ! 1128: ULONG length; ! 1129: ! 1130: DebugPrint((3,"A154xStartIo: Enter routine\n")); ! 1131: ! 1132: // ! 1133: // Check if command is an ABORT request. ! 1134: // ! 1135: ! 1136: if (Srb->Function == SRB_FUNCTION_ABORT_COMMAND) { ! 1137: ! 1138: // ! 1139: // Verify that SRB to abort is still outstanding. ! 1140: // ! 1141: ! 1142: luExtension = ! 1143: ScsiPortGetLogicalUnit(deviceExtension, ! 1144: Srb->PathId, ! 1145: Srb->TargetId, ! 1146: Srb->Lun); ! 1147: ! 1148: if (!luExtension->CurrentSrb) { ! 1149: ! 1150: DebugPrint((1, "A154xStartIo: SRB to abort already completed\n")); ! 1151: ! 1152: // ! 1153: // Complete abort SRB. ! 1154: // ! 1155: ! 1156: Srb->SrbStatus = SRB_STATUS_ABORT_FAILED; ! 1157: ! 1158: ScsiPortNotification(RequestComplete, ! 1159: deviceExtension, ! 1160: Srb); ! 1161: // ! 1162: // Adapter ready for next request. ! 1163: // ! 1164: ! 1165: ScsiPortNotification(NextRequest, ! 1166: deviceExtension, ! 1167: NULL); ! 1168: ! 1169: return TRUE; ! 1170: } ! 1171: ! 1172: // ! 1173: // Get CCB to abort. ! 1174: // ! 1175: ! 1176: ccb = Srb->NextSrb->SrbExtension; ! 1177: ! 1178: // ! 1179: // Set abort SRB for completion. ! 1180: // ! 1181: ! 1182: ccb->AbortSrb = Srb; ! 1183: ! 1184: } else { ! 1185: ! 1186: ccb = Srb->SrbExtension; ! 1187: ! 1188: // ! 1189: // Save SRB back pointer in CCB. ! 1190: // ! 1191: ! 1192: ccb->SrbAddress = Srb; ! 1193: } ! 1194: ! 1195: // ! 1196: // Get CCB physical address. ! 1197: // ! 1198: ! 1199: physicalCcb = ScsiPortConvertPhysicalAddressToUlong( ! 1200: ScsiPortGetPhysicalAddress(deviceExtension, NULL, ccb, &length)); ! 1201: ! 1202: // ! 1203: // Find free mailboxOut. ! 1204: // ! 1205: ! 1206: do { ! 1207: ! 1208: mailboxOut = &noncachedExtension->Mbo[i % MB_COUNT]; ! 1209: i++; ! 1210: ! 1211: } while (mailboxOut->Command != MBO_FREE); ! 1212: ! 1213: // ! 1214: // Save the next free location. ! 1215: // ! 1216: ! 1217: deviceExtension->MboIndex = (UCHAR) (i % MB_COUNT); ! 1218: ! 1219: DebugPrint((3,"A154xStartIo: MBO address %lx, Loop count = %d\n", mailboxOut, i)); ! 1220: ! 1221: // ! 1222: // Write CCB to mailbox. ! 1223: // ! 1224: ! 1225: FOUR_TO_THREE(&mailboxOut->Address, ! 1226: (PFOUR_BYTE)&physicalCcb); ! 1227: ! 1228: switch (Srb->Function) { ! 1229: ! 1230: case SRB_FUNCTION_ABORT_COMMAND: ! 1231: ! 1232: DebugPrint((1, "A154xStartIo: Abort request received\n")); ! 1233: ! 1234: // ! 1235: // BUGBUG: Race condition (what if CCB to be aborted ! 1236: // completes after setting new SrbAddress?) ! 1237: // ! 1238: ! 1239: mailboxOut->Command = MBO_ABORT; ! 1240: ! 1241: break; ! 1242: ! 1243: case SRB_FUNCTION_RESET_BUS: ! 1244: ! 1245: // ! 1246: // Reset aha154x and SCSI bus. ! 1247: // ! 1248: ! 1249: DebugPrint((1, "A154xStartIo: Reset bus request received\n")); ! 1250: ! 1251: if (!A154xResetBus( ! 1252: deviceExtension, ! 1253: Srb->PathId ! 1254: )) { ! 1255: ! 1256: DebugPrint((1,"A154xStartIo: Reset bus failed\n")); ! 1257: ! 1258: Srb->SrbStatus = SRB_STATUS_ERROR; ! 1259: ! 1260: } else { ! 1261: ! 1262: Srb->SrbStatus = SRB_STATUS_SUCCESS; ! 1263: } ! 1264: ! 1265: ! 1266: ScsiPortNotification(RequestComplete, ! 1267: deviceExtension, ! 1268: Srb); ! 1269: ! 1270: ScsiPortNotification(NextRequest, ! 1271: deviceExtension, ! 1272: NULL); ! 1273: ! 1274: return TRUE; ! 1275: ! 1276: case SRB_FUNCTION_EXECUTE_SCSI: ! 1277: ! 1278: // ! 1279: // Get logical unit extension. ! 1280: // ! 1281: ! 1282: luExtension = ! 1283: ScsiPortGetLogicalUnit(deviceExtension, ! 1284: Srb->PathId, ! 1285: Srb->TargetId, ! 1286: Srb->Lun); ! 1287: ! 1288: // ! 1289: // Move SRB to logical unit extension. ! 1290: // ! 1291: ! 1292: luExtension->CurrentSrb = Srb; ! 1293: ! 1294: // ! 1295: // Build CCB. ! 1296: // ! 1297: ! 1298: BuildCcb(deviceExtension, Srb); ! 1299: ! 1300: mailboxOut->Command = MBO_START; ! 1301: ! 1302: break; ! 1303: ! 1304: case SRB_FUNCTION_RESET_DEVICE: ! 1305: ! 1306: DebugPrint((1,"A154xStartIo: Reset device not supported\n")); ! 1307: ! 1308: // ! 1309: // Drop through to default. ! 1310: // ! 1311: ! 1312: default: ! 1313: ! 1314: // ! 1315: // Set error, complete request ! 1316: // and signal ready for next request. ! 1317: // ! 1318: ! 1319: Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; ! 1320: ! 1321: ScsiPortNotification(RequestComplete, ! 1322: deviceExtension, ! 1323: Srb); ! 1324: ! 1325: ScsiPortNotification(NextRequest, ! 1326: deviceExtension, ! 1327: NULL); ! 1328: ! 1329: return TRUE; ! 1330: ! 1331: } // end switch ! 1332: ! 1333: // ! 1334: // Tell 154xb a CCB is available now. ! 1335: // ! 1336: ! 1337: if (!WriteCommandRegister(deviceExtension,AC_START_SCSI_COMMAND, FALSE)) { ! 1338: ! 1339: // ! 1340: // Let request time out and fail. ! 1341: // ! 1342: ! 1343: DebugPrint((1,"A154xStartIo: Can't write command to adapter\n")); ! 1344: ! 1345: deviceExtension->PendingRequest = TRUE; ! 1346: ! 1347: } else { ! 1348: ! 1349: // ! 1350: // Command(s) submitted. Clear pending request flag. ! 1351: // ! 1352: ! 1353: deviceExtension->PendingRequest = FALSE; ! 1354: ! 1355: // ! 1356: // Adapter ready for next request. ! 1357: // ! 1358: ! 1359: ScsiPortNotification(NextRequest, ! 1360: deviceExtension, ! 1361: NULL); ! 1362: } ! 1363: ! 1364: return TRUE; ! 1365: ! 1366: } // end A154xStartIo() ! 1367: ! 1368: ! 1369: BOOLEAN ! 1370: A154xInterrupt( ! 1371: IN PVOID HwDeviceExtension ! 1372: ) ! 1373: ! 1374: /*++ ! 1375: ! 1376: Routine Description: ! 1377: ! 1378: This is the interrupt service routine for the adaptec 154x SCSI adapter. ! 1379: It reads the interrupt register to determine if the adapter is indeed ! 1380: the source of the interrupt and clears the interrupt at the device. ! 1381: If the adapter is interrupting because a mailbox is full, the CCB is ! 1382: retrieved to complete the request. ! 1383: ! 1384: Arguments: ! 1385: ! 1386: HwDeviceExtension - HBA miniport driver's adapter data storage ! 1387: ! 1388: Return Value: ! 1389: ! 1390: TRUE if MailboxIn full ! 1391: ! 1392: --*/ ! 1393: ! 1394: { ! 1395: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; ! 1396: PNONCACHED_EXTENSION noncachedExtension = ! 1397: deviceExtension->NoncachedExtension; ! 1398: PCCB ccb; ! 1399: PSCSI_REQUEST_BLOCK srb; ! 1400: PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress; ! 1401: PMBI mailboxIn; ! 1402: ULONG physicalCcb; ! 1403: PHW_LU_EXTENSION luExtension; ! 1404: ULONG residualBytes; ! 1405: ULONG i; ! 1406: ! 1407: UCHAR InterruptFlags; ! 1408: ! 1409: InterruptFlags = ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister); ! 1410: ! 1411: // ! 1412: // Determine cause of interrupt. ! 1413: // ! 1414: ! 1415: if (InterruptFlags & IOP_COMMAND_COMPLETE) { ! 1416: ! 1417: // ! 1418: // Adapter command completed. ! 1419: // ! 1420: ! 1421: DebugPrint((2,"A154xInterrupt: Adapter Command complete\n")); ! 1422: DebugPrint((3,"A154xInterrupt: Interrupt flags %x\n", InterruptFlags)); ! 1423: DebugPrint((3,"A154xInterrupt: Status %x\n", ! 1424: ScsiPortReadPortUchar(&baseIoAddress->StatusRegister))); ! 1425: ! 1426: // ! 1427: // Clear interrupt on adapter. ! 1428: // ! 1429: ! 1430: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET); ! 1431: ! 1432: return TRUE; ! 1433: ! 1434: } else if (InterruptFlags & IOP_MBI_FULL) { ! 1435: ! 1436: DebugPrint((3,"A154xInterrupt: MBI Full\n")); ! 1437: ! 1438: // ! 1439: // Clear interrupt on adapter. ! 1440: // ! 1441: ! 1442: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET); ! 1443: ! 1444: } else if (InterruptFlags & IOP_SCSI_RESET_DETECTED) { ! 1445: ! 1446: DebugPrint((1,"A154xInterrupt: SCSI Reset detected\n")); ! 1447: ! 1448: // ! 1449: // Clear interrupt on adapter. ! 1450: // ! 1451: ! 1452: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET); ! 1453: ! 1454: // ! 1455: // Notify of reset. ! 1456: // ! 1457: ! 1458: ScsiPortNotification(ResetDetected, ! 1459: deviceExtension, ! 1460: NULL); ! 1461: ! 1462: return TRUE; ! 1463: ! 1464: } else { ! 1465: ! 1466: DebugPrint((4,"A154xInterrupt: Spurious interrupt\n")); ! 1467: ! 1468: return FALSE; ! 1469: } ! 1470: ! 1471: // ! 1472: // Determine which MailboxIn location contains the CCB. ! 1473: // ! 1474: ! 1475: for (i=0; i<MB_COUNT; i++) { ! 1476: ! 1477: mailboxIn = &noncachedExtension->Mbi[deviceExtension->MbiIndex]; ! 1478: ! 1479: // ! 1480: // Look for a mailbox entry with a legitimate status. ! 1481: // ! 1482: ! 1483: if (mailboxIn->Status != MBI_FREE) { ! 1484: ! 1485: // ! 1486: // Point to the next in box. ! 1487: // ! 1488: ! 1489: deviceExtension->MbiIndex = (deviceExtension->MbiIndex + 1) % MB_COUNT; ! 1490: ! 1491: // ! 1492: // MBI found. Convert CCB to big endian. ! 1493: // ! 1494: ! 1495: THREE_TO_FOUR((PFOUR_BYTE)&physicalCcb, ! 1496: &mailboxIn->Address); ! 1497: ! 1498: DebugPrint((3, "A154xInterrupt: Physical CCB %lx\n", physicalCcb)); ! 1499: ! 1500: // ! 1501: // Check if physical CCB is zero. ! 1502: // This is done to cover for hardware errors. ! 1503: // ! 1504: ! 1505: if (!physicalCcb) { ! 1506: ! 1507: DebugPrint((1,"A154xInterrupt: Physical CCB address is 0\n")); ! 1508: ! 1509: // ! 1510: // Indicate MBI is available. ! 1511: // ! 1512: ! 1513: mailboxIn->Status = MBI_FREE; ! 1514: ! 1515: continue; ! 1516: } ! 1517: ! 1518: // ! 1519: // Convert Physical CCB to Virtual. ! 1520: // ! 1521: ! 1522: ccb = ScsiPortGetVirtualAddress(deviceExtension, ScsiPortConvertUlongToPhysicalAddress(physicalCcb)); ! 1523: ! 1524: ! 1525: DebugPrint((3, "A154xInterrupt: Virtual CCB %lx\n", ccb)); ! 1526: ! 1527: // ! 1528: // Make sure the virtual address was found. ! 1529: // ! 1530: ! 1531: if (ccb == NULL) { ! 1532: ! 1533: // ! 1534: // A bad physcial address was return by the adapter. ! 1535: // Log it as an error. ! 1536: // ! 1537: ! 1538: ScsiPortLogError( ! 1539: HwDeviceExtension, ! 1540: NULL, ! 1541: 0, ! 1542: deviceExtension->HostTargetId, ! 1543: 0, ! 1544: SP_INTERNAL_ADAPTER_ERROR, ! 1545: 5 << 8 ! 1546: ); ! 1547: ! 1548: // ! 1549: // Indicate MBI is available. ! 1550: // ! 1551: ! 1552: mailboxIn->Status = MBI_FREE; ! 1553: ! 1554: continue; ! 1555: } ! 1556: ! 1557: // ! 1558: // Get SRB from CCB. ! 1559: // ! 1560: ! 1561: srb = ccb->SrbAddress; ! 1562: ! 1563: // ! 1564: // Get logical unit extension. ! 1565: // ! 1566: ! 1567: luExtension = ! 1568: ScsiPortGetLogicalUnit(deviceExtension, ! 1569: srb->PathId, ! 1570: srb->TargetId, ! 1571: srb->Lun); ! 1572: ! 1573: // ! 1574: // Make sure the luExtension was found and it has a current request. ! 1575: // ! 1576: ! 1577: if (luExtension == NULL || (luExtension->CurrentSrb == NULL && ! 1578: mailboxIn->Status != MBI_NOT_FOUND)) { ! 1579: ! 1580: // ! 1581: // A bad physcial address was return by the adapter. ! 1582: // Log it as an error. ! 1583: // ! 1584: ! 1585: ScsiPortLogError( ! 1586: HwDeviceExtension, ! 1587: NULL, ! 1588: 0, ! 1589: deviceExtension->HostTargetId, ! 1590: 0, ! 1591: SP_INTERNAL_ADAPTER_ERROR, ! 1592: (6 << 8) | mailboxIn->Status ! 1593: ); ! 1594: ! 1595: // ! 1596: // Indicate MBI is available. ! 1597: // ! 1598: ! 1599: mailboxIn->Status = MBI_FREE; ! 1600: ! 1601: continue; ! 1602: } ! 1603: ! 1604: // ! 1605: // Check MBI status. ! 1606: // ! 1607: ! 1608: switch (mailboxIn->Status) { ! 1609: ! 1610: case MBI_SUCCESS: ! 1611: ! 1612: // ! 1613: // Update SRB with number of bytes transferred. ! 1614: // ! 1615: ! 1616: THREE_TO_FOUR((PFOUR_BYTE)&residualBytes, ! 1617: &ccb->DataLength); ! 1618: ! 1619: if (residualBytes != 0) { ! 1620: ! 1621: DebugPrint((1, "A154xInterrupt: Underrun occured. Request length = %lx, Residual length = %lx\n", srb->DataTransferLength, residualBytes)); ! 1622: srb->DataTransferLength -= residualBytes; ! 1623: srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; ! 1624: ! 1625: } else { ! 1626: ! 1627: srb->SrbStatus = SRB_STATUS_SUCCESS; ! 1628: ! 1629: } ! 1630: ! 1631: luExtension->CurrentSrb = NULL; ! 1632: ! 1633: break; ! 1634: ! 1635: case MBI_NOT_FOUND: ! 1636: ! 1637: DebugPrint((1, "A154xInterrupt: CCB abort failed %lx\n", ccb)); ! 1638: ! 1639: srb = ccb->AbortSrb; ! 1640: ! 1641: srb->SrbStatus = SRB_STATUS_ABORT_FAILED; ! 1642: ! 1643: // ! 1644: // Check if SRB still outstanding. ! 1645: // ! 1646: ! 1647: if (luExtension->CurrentSrb) { ! 1648: ! 1649: // ! 1650: // Complete this SRB. ! 1651: // ! 1652: ! 1653: luExtension->CurrentSrb->SrbStatus = SRB_STATUS_TIMEOUT; ! 1654: ! 1655: ScsiPortNotification(RequestComplete, ! 1656: deviceExtension, ! 1657: luExtension->CurrentSrb); ! 1658: ! 1659: luExtension->CurrentSrb = NULL; ! 1660: } ! 1661: ! 1662: break; ! 1663: ! 1664: case MBI_ABORT: ! 1665: ! 1666: DebugPrint((1, "A154xInterrupt: CCB aborted\n")); ! 1667: ! 1668: // ! 1669: // Update target status in aborted SRB. ! 1670: // ! 1671: ! 1672: srb->SrbStatus = SRB_STATUS_ABORTED; ! 1673: ! 1674: // ! 1675: // Call notification routine for the aborted SRB. ! 1676: // ! 1677: ! 1678: ScsiPortNotification(RequestComplete, ! 1679: deviceExtension, ! 1680: srb); ! 1681: ! 1682: luExtension->CurrentSrb = NULL; ! 1683: ! 1684: // ! 1685: // Get the abort SRB from CCB. ! 1686: // ! 1687: ! 1688: srb = ccb->AbortSrb; ! 1689: ! 1690: // ! 1691: // Set status for completing abort request. ! 1692: // ! 1693: ! 1694: srb->SrbStatus = SRB_STATUS_SUCCESS; ! 1695: ! 1696: break; ! 1697: ! 1698: case MBI_ERROR: ! 1699: ! 1700: DebugPrint((2, "A154xInterrupt: Error occurred\n")); ! 1701: ! 1702: srb->SrbStatus = MapError(deviceExtension, srb, ccb); ! 1703: ! 1704: // ! 1705: // Check if ABORT command. ! 1706: // ! 1707: ! 1708: if (srb->Function == SRB_FUNCTION_ABORT_COMMAND) { ! 1709: ! 1710: // ! 1711: // Check if SRB still outstanding. ! 1712: // ! 1713: ! 1714: if (luExtension->CurrentSrb) { ! 1715: ! 1716: // ! 1717: // Complete this SRB. ! 1718: // ! 1719: ! 1720: luExtension->CurrentSrb->SrbStatus = SRB_STATUS_TIMEOUT; ! 1721: ! 1722: ScsiPortNotification(RequestComplete, ! 1723: deviceExtension, ! 1724: luExtension->CurrentSrb); ! 1725: ! 1726: } ! 1727: ! 1728: DebugPrint((1,"A154xInterrupt: Abort command failed\n")); ! 1729: } ! 1730: ! 1731: luExtension->CurrentSrb = NULL; ! 1732: ! 1733: break; ! 1734: ! 1735: default: ! 1736: ! 1737: // ! 1738: // Log the error. ! 1739: // ! 1740: ! 1741: ScsiPortLogError( ! 1742: HwDeviceExtension, ! 1743: NULL, ! 1744: 0, ! 1745: deviceExtension->HostTargetId, ! 1746: 0, ! 1747: SP_INTERNAL_ADAPTER_ERROR, ! 1748: (1 << 8) | mailboxIn->Status ! 1749: ); ! 1750: ! 1751: DebugPrint((1, "A154xInterrupt: Unrecognized mailbox status\n")); ! 1752: ! 1753: mailboxIn->Status = MBI_FREE; ! 1754: ! 1755: continue; ! 1756: ! 1757: } // end switch ! 1758: ! 1759: // ! 1760: // Indicate MBI is available. ! 1761: // ! 1762: ! 1763: mailboxIn->Status = MBI_FREE; ! 1764: ! 1765: DebugPrint((2, "A154xInterrupt: SCSI Status %x\n", srb->ScsiStatus)); ! 1766: ! 1767: DebugPrint((2, "A154xInterrupt: Adapter Status %x\n", ccb->HostStatus)); ! 1768: ! 1769: // ! 1770: // Update target status in SRB. ! 1771: // ! 1772: ! 1773: srb->ScsiStatus = ccb->TargetStatus; ! 1774: ! 1775: // ! 1776: // Signal request completion. ! 1777: // ! 1778: ! 1779: ScsiPortNotification(RequestComplete, ! 1780: (PVOID)deviceExtension, ! 1781: srb); ! 1782: ! 1783: } else { ! 1784: ! 1785: break; ! 1786: ! 1787: } // end if ((mailboxIn->Status == MBI_SUCCESS ... ! 1788: ! 1789: } // end for (i=0; i<MB_COUNT; i++) { ! 1790: ! 1791: if (deviceExtension->PendingRequest) { ! 1792: ! 1793: // ! 1794: // The last write command to the adapter failed. Try and start it now. ! 1795: // ! 1796: ! 1797: deviceExtension->PendingRequest = FALSE; ! 1798: ! 1799: // ! 1800: // Tell 154xb a CCB is available now. ! 1801: // ! 1802: ! 1803: if (!WriteCommandRegister(deviceExtension,AC_START_SCSI_COMMAND, FALSE)) { ! 1804: ! 1805: // ! 1806: // Let request time out and fail. ! 1807: // ! 1808: ! 1809: DebugPrint((1,"A154xInterrupt: Can't write command to adapter\n")); ! 1810: ! 1811: deviceExtension->PendingRequest = TRUE; ! 1812: ! 1813: } else { ! 1814: ! 1815: // ! 1816: // Adapter ready for next request. ! 1817: // ! 1818: ! 1819: ScsiPortNotification(NextRequest, ! 1820: deviceExtension, ! 1821: NULL); ! 1822: } ! 1823: } ! 1824: ! 1825: return TRUE; ! 1826: ! 1827: } // end A154xInterrupt() ! 1828: ! 1829: ! 1830: VOID ! 1831: BuildCcb( ! 1832: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 1833: IN PSCSI_REQUEST_BLOCK Srb ! 1834: ) ! 1835: ! 1836: /*++ ! 1837: ! 1838: Routine Description: ! 1839: ! 1840: Build CCB for 154x. ! 1841: ! 1842: Arguments: ! 1843: ! 1844: DeviceExtenson ! 1845: SRB ! 1846: ! 1847: Return Value: ! 1848: ! 1849: Nothing. ! 1850: ! 1851: --*/ ! 1852: ! 1853: { ! 1854: PCCB ccb = Srb->SrbExtension; ! 1855: ! 1856: DebugPrint((3,"BuildCcb: Enter routine\n")); ! 1857: ! 1858: // ! 1859: // Set target id and LUN. ! 1860: // ! 1861: ! 1862: ccb->ControlByte = (UCHAR)(Srb->TargetId << 5) | Srb->Lun; ! 1863: ! 1864: // ! 1865: // Set CCB Operation Code. ! 1866: // ! 1867: ! 1868: ! 1869: ccb->OperationCode = SCATTER_GATHER_COMMAND; ! 1870: ! 1871: // ! 1872: // Set transfer direction bit. ! 1873: // ! 1874: ! 1875: if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT) { ! 1876: ! 1877: // ! 1878: // Check if both direction bits are set. This is an ! 1879: // indication that the direction has not been specified. ! 1880: // ! 1881: ! 1882: if (!(Srb->SrbFlags & SRB_FLAGS_DATA_IN)) { ! 1883: ccb->ControlByte |= CCB_DATA_XFER_OUT; ! 1884: } ! 1885: ! 1886: } else if (Srb->SrbFlags & SRB_FLAGS_DATA_IN) { ! 1887: ccb->ControlByte |= CCB_DATA_XFER_IN; ! 1888: } else { ! 1889: ! 1890: // ! 1891: // if no data transfer, we must set ccb command to to INITIATOR ! 1892: // instead of SCATTER_GATHER and zero ccb data pointer and length. ! 1893: // ! 1894: ! 1895: ccb->OperationCode = SCSI_INITIATOR_COMMAND; ! 1896: ccb->DataPointer.Msb = 0; ! 1897: ccb->DataPointer.Mid = 0; ! 1898: ccb->DataPointer.Lsb = 0; ! 1899: ccb->DataLength.Msb = 0; ! 1900: ccb->DataLength.Mid = 0; ! 1901: ccb->DataLength.Lsb = 0; ! 1902: } ! 1903: ! 1904: // ! 1905: // 01h disables auto request sense. ! 1906: // ! 1907: ! 1908: ccb->RequestSenseLength = 1; ! 1909: ! 1910: // ! 1911: // Set CDB length and copy to CCB. ! 1912: // ! 1913: ! 1914: ccb->CdbLength = (UCHAR)Srb->CdbLength; ! 1915: ! 1916: ScsiPortMoveMemory(ccb->Cdb, Srb->Cdb, ccb->CdbLength); ! 1917: ! 1918: // ! 1919: // Set reserved bytes to zero. ! 1920: // ! 1921: ! 1922: ccb->Reserved[0] = 0; ! 1923: ccb->Reserved[1] = 0; ! 1924: ! 1925: ccb->LinkIdentifier = 0; ! 1926: ! 1927: // ! 1928: // Zero link pointer. ! 1929: // ! 1930: ! 1931: ccb->LinkPointer.Msb = 0; ! 1932: ccb->LinkPointer.Lsb = 0; ! 1933: ccb->LinkPointer.Mid = 0; ! 1934: ! 1935: // ! 1936: // Build SDL in CCB if data transfer. ! 1937: // ! 1938: ! 1939: if (Srb->DataTransferLength > 0) { ! 1940: BuildSdl(DeviceExtension, Srb); ! 1941: } ! 1942: ! 1943: // ! 1944: // Move 0xff to Target Status to indicate ! 1945: // CCB has not completed. ! 1946: // ! 1947: ! 1948: ccb->TargetStatus = 0xFF; ! 1949: ! 1950: return; ! 1951: ! 1952: } // end BuildCcb() ! 1953: ! 1954: ! 1955: VOID ! 1956: BuildSdl( ! 1957: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 1958: IN PSCSI_REQUEST_BLOCK Srb ! 1959: ) ! 1960: ! 1961: /*++ ! 1962: ! 1963: Routine Description: ! 1964: ! 1965: This routine builds a scatter/gather descriptor list for the CCB. ! 1966: ! 1967: Arguments: ! 1968: ! 1969: DeviceExtension ! 1970: Srb ! 1971: ! 1972: Return Value: ! 1973: ! 1974: None ! 1975: ! 1976: --*/ ! 1977: ! 1978: { ! 1979: PVOID dataPointer = Srb->DataBuffer; ! 1980: ULONG bytesLeft = Srb->DataTransferLength; ! 1981: PCCB ccb = Srb->SrbExtension; ! 1982: PSDL sdl = &ccb->Sdl; ! 1983: ULONG physicalSdl; ! 1984: ULONG physicalAddress; ! 1985: ULONG length; ! 1986: ULONG four; ! 1987: PTHREE_BYTE three; ! 1988: ULONG i = 0; ! 1989: ! 1990: DebugPrint((3,"BuildSdl: Enter routine\n")); ! 1991: ! 1992: // ! 1993: // Get physical SDL address. ! 1994: // ! 1995: ! 1996: physicalSdl = ScsiPortConvertPhysicalAddressToUlong( ! 1997: ScsiPortGetPhysicalAddress(DeviceExtension, NULL, ! 1998: sdl, &length)); ! 1999: ! 2000: // ! 2001: // Create SDL segment descriptors. ! 2002: // ! 2003: ! 2004: do { ! 2005: ! 2006: DebugPrint((3, "BuildSdl: Data buffer %lx\n", dataPointer)); ! 2007: ! 2008: // ! 2009: // Get physical address and length of contiguous ! 2010: // physical buffer. ! 2011: // ! 2012: ! 2013: physicalAddress = ! 2014: ScsiPortConvertPhysicalAddressToUlong( ! 2015: ScsiPortGetPhysicalAddress(DeviceExtension, ! 2016: Srb, ! 2017: dataPointer, ! 2018: &length)); ! 2019: ! 2020: DebugPrint((3, "BuildSdl: Physical address %lx\n", physicalAddress)); ! 2021: DebugPrint((3, "BuildSdl: Data length %lx\n", length)); ! 2022: DebugPrint((3, "BuildSdl: Bytes left %lx\n", bytesLeft)); ! 2023: ! 2024: // ! 2025: // If length of physical memory is more ! 2026: // than bytes left in transfer, use bytes ! 2027: // left as final length. ! 2028: // ! 2029: ! 2030: if (length > bytesLeft) { ! 2031: length = bytesLeft; ! 2032: } ! 2033: ! 2034: // ! 2035: // Convert length to 3-byte big endian format. ! 2036: // ! 2037: ! 2038: four = length; ! 2039: three = &sdl->Sgd[i].Length; ! 2040: FOUR_TO_THREE(three, (PFOUR_BYTE)&four); ! 2041: ! 2042: // ! 2043: // Convert physical address to 3-byte big endian format. ! 2044: // ! 2045: ! 2046: four = (ULONG)physicalAddress; ! 2047: three = &sdl->Sgd[i].Address; ! 2048: FOUR_TO_THREE(three, (PFOUR_BYTE)&four); ! 2049: i++; ! 2050: ! 2051: // ! 2052: // Adjust counts. ! 2053: // ! 2054: ! 2055: dataPointer = (PUCHAR)dataPointer + length; ! 2056: bytesLeft -= length; ! 2057: ! 2058: } while (bytesLeft); ! 2059: ! 2060: // ! 2061: // Write SDL length to CCB. ! 2062: // ! 2063: ! 2064: four = i * sizeof(SGD); ! 2065: three = &ccb->DataLength; ! 2066: FOUR_TO_THREE(three, (PFOUR_BYTE)&four); ! 2067: ! 2068: DebugPrint((3,"BuildSdl: SDL length is %d\n", four)); ! 2069: ! 2070: // ! 2071: // Write SDL address to CCB. ! 2072: // ! 2073: ! 2074: FOUR_TO_THREE(&ccb->DataPointer, ! 2075: (PFOUR_BYTE)&physicalSdl); ! 2076: ! 2077: DebugPrint((3,"BuildSdl: SDL address is %lx\n", sdl)); ! 2078: ! 2079: DebugPrint((3,"BuildSdl: CCB address is %lx\n", ccb)); ! 2080: ! 2081: return; ! 2082: ! 2083: } // end BuildSdl() ! 2084: ! 2085: ! 2086: BOOLEAN ! 2087: A154xResetBus( ! 2088: IN PVOID HwDeviceExtension, ! 2089: IN ULONG PathId ! 2090: ) ! 2091: ! 2092: /*++ ! 2093: ! 2094: Routine Description: ! 2095: ! 2096: Reset Adaptec 154X SCSI adapter and SCSI bus. ! 2097: Initialize adapter mailbox. ! 2098: ! 2099: Arguments: ! 2100: ! 2101: HwDeviceExtension - HBA miniport driver's adapter data storage ! 2102: ! 2103: Return Value: ! 2104: ! 2105: Nothing. ! 2106: ! 2107: ! 2108: --*/ ! 2109: ! 2110: { ! 2111: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; ! 2112: PNONCACHED_EXTENSION noncachedExtension = ! 2113: deviceExtension->NoncachedExtension; ! 2114: PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress; ! 2115: UCHAR status; ! 2116: ULONG i; ! 2117: ! 2118: DebugPrint((2,"ResetBus: Reset aha154X and SCSI bus\n")); ! 2119: ! 2120: // ! 2121: // Complete all outstanding requests with SRB_STATUS_BUS_RESET. ! 2122: // ! 2123: ! 2124: ScsiPortCompleteRequest(deviceExtension, ! 2125: (UCHAR) PathId, ! 2126: 0xFF, ! 2127: 0xFF, ! 2128: (ULONG) SRB_STATUS_BUS_RESET); ! 2129: ! 2130: // ! 2131: // Reset SCSI chip. ! 2132: // ! 2133: ! 2134: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_HARD_RESET); ! 2135: ! 2136: ScsiPortStallExecution(500 * 1000); ! 2137: ! 2138: // ! 2139: // Wait up to 5000 microseconds for adapter to initialize. ! 2140: // ! 2141: ! 2142: for (i = 0; i < 5000; i++) { ! 2143: ! 2144: ScsiPortStallExecution(1); ! 2145: ! 2146: status = ScsiPortReadPortUchar(&deviceExtension->BaseIoAddress->StatusRegister); ! 2147: ! 2148: if (status & IOP_SCSI_HBA_IDLE) { ! 2149: break; ! 2150: } ! 2151: } ! 2152: ! 2153: // ! 2154: // Zero out mailboxes. ! 2155: // ! 2156: ! 2157: for (i=0; i<MB_COUNT; i++) { ! 2158: ! 2159: PMBO mailboxOut; ! 2160: PMBI mailboxIn; ! 2161: ! 2162: mailboxIn = &noncachedExtension->Mbi[i]; ! 2163: mailboxOut = &noncachedExtension->Mbo[i]; ! 2164: ! 2165: mailboxOut->Command = mailboxIn->Status = 0; ! 2166: } ! 2167: ! 2168: // ! 2169: // Zero previous indexes. ! 2170: // ! 2171: ! 2172: deviceExtension->MboIndex = 0; ! 2173: deviceExtension->MbiIndex = 0; ! 2174: ! 2175: if (deviceExtension->PendingRequest) { ! 2176: ! 2177: deviceExtension->PendingRequest = FALSE; ! 2178: ! 2179: // ! 2180: // Adapter ready for next request. ! 2181: // ! 2182: ! 2183: ScsiPortNotification(NextRequest, ! 2184: deviceExtension, ! 2185: NULL); ! 2186: } ! 2187: ! 2188: if (!(status & IOP_SCSI_HBA_IDLE)) { ! 2189: return(FALSE); ! 2190: } ! 2191: ! 2192: // ! 2193: // Unlock mailboxes in case the adapter is a 1540B with 1Gb support ! 2194: // or 1540C with extended translation enabled. Maiboxes cannot be ! 2195: // initialized until unlock code is sent. ! 2196: ! 2197: status = UnlockMailBoxes(deviceExtension); ! 2198: ! 2199: if (!SpinForInterrupt(deviceExtension,FALSE)) { ! 2200: DebugPrint((1,"A154xResetBus: Failed to unlock mailboxes\n")); ! 2201: return FALSE; ! 2202: } ! 2203: ! 2204: ! 2205: DebugPrint((3,"ResetBus: Initialize mailbox\n")); ! 2206: ! 2207: if (!WriteCommandRegister(deviceExtension,AC_MAILBOX_INITIALIZATION, TRUE)) { ! 2208: DebugPrint((1,"A154xResetBus: Couldn't initialize mailboxes\n")); ! 2209: return FALSE; ! 2210: } ! 2211: ! 2212: // ! 2213: // Send Adapter number of mailbox locations. ! 2214: // ! 2215: ! 2216: if (!WriteDataRegister(deviceExtension,MB_COUNT)) { ! 2217: return FALSE; ! 2218: } ! 2219: ! 2220: // ! 2221: // Send the most significant byte of the mailbox physical address. ! 2222: // ! 2223: ! 2224: if (!WriteDataRegister(deviceExtension, ! 2225: ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte2)) { ! 2226: return FALSE; ! 2227: } ! 2228: ! 2229: // ! 2230: // Send the middle byte of the mailbox physical address. ! 2231: // ! 2232: ! 2233: if (!WriteDataRegister(deviceExtension, ! 2234: ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte1)) { ! 2235: return FALSE; ! 2236: } ! 2237: ! 2238: // ! 2239: // Send the least significant byte of the mailbox physical address. ! 2240: // ! 2241: ! 2242: if (!WriteDataRegister(deviceExtension, ! 2243: ((PFOUR_BYTE)&noncachedExtension->MailboxPA)->Byte0)) { ! 2244: return FALSE; ! 2245: } ! 2246: ! 2247: #ifdef FORCE_DMA_SPEED ! 2248: // ! 2249: // Set the DMA transfer speed to 5.0 MB/second. This is because ! 2250: // faster transfer speeds cause data corruption on 486/33 machines. ! 2251: // This overrides the card jumper setting. ! 2252: // ! 2253: ! 2254: if (!WriteCommandRegister(deviceExtension, AC_SET_TRANSFER_SPEED, TRUE)) { ! 2255: ! 2256: DebugPrint((1,"Can't set dma transfer speed\n")); ! 2257: ! 2258: } else if (!WriteDataRegister(deviceExtension, DMA_SPEED_50_MBS)) { ! 2259: ! 2260: DebugPrint((1,"Can't set dma transfer speed\n")); ! 2261: } ! 2262: ! 2263: // ! 2264: // Wait for interrupt. ! 2265: // ! 2266: ! 2267: if (!SpinForInterrupt(deviceExtension,TRUE)) { ! 2268: ! 2269: DebugPrint((1,"Timed out waiting for adapter command to complete\n")); ! 2270: } ! 2271: #endif ! 2272: ! 2273: // ! 2274: // Override default setting for bus on time. This makes floppy ! 2275: // drives work better with this adapter. ! 2276: // ! 2277: ! 2278: if (!WriteCommandRegister(deviceExtension, AC_SET_BUS_ON_TIME, TRUE)) { ! 2279: ! 2280: DebugPrint((1,"Can't set bus on time\n")); ! 2281: ! 2282: } else if (!WriteDataRegister(deviceExtension, 0x07)) { ! 2283: ! 2284: DebugPrint((1,"Can't set bus on time\n")); ! 2285: } ! 2286: ! 2287: // ! 2288: // Wait for interrupt. ! 2289: // ! 2290: ! 2291: if (!SpinForInterrupt(deviceExtension,TRUE)) { ! 2292: ! 2293: DebugPrint((1,"Timed out waiting for adapter command to complete\n")); ! 2294: } ! 2295: ! 2296: return TRUE; ! 2297: ! 2298: } // end A154xResetBus() ! 2299: ! 2300: ! 2301: UCHAR ! 2302: MapError( ! 2303: IN PVOID HwDeviceExtension, ! 2304: IN PSCSI_REQUEST_BLOCK Srb, ! 2305: IN PCCB Ccb ! 2306: ) ! 2307: ! 2308: /*++ ! 2309: ! 2310: Routine Description: ! 2311: ! 2312: Translate A154x error to SRB error, and log an error if necessary. ! 2313: ! 2314: Arguments: ! 2315: ! 2316: HwDeviceExtension - The hardware device extension. ! 2317: ! 2318: Srb - The failing Srb. ! 2319: ! 2320: Ccb - Command Control Block contains error. ! 2321: ! 2322: Return Value: ! 2323: ! 2324: SRB Error ! 2325: ! 2326: --*/ ! 2327: ! 2328: { ! 2329: UCHAR status; ! 2330: ULONG logError; ! 2331: ULONG residualBytes; ! 2332: ! 2333: switch (Ccb->HostStatus) { ! 2334: ! 2335: case CCB_COMPLETE: ! 2336: case CCB_SELECTION_TIMEOUT: ! 2337: ! 2338: if (Ccb->TargetStatus == SCSISTAT_CHECK_CONDITION) { ! 2339: ! 2340: // ! 2341: // Update SRB with number of bytes transferred. ! 2342: // ! 2343: ! 2344: THREE_TO_FOUR((PFOUR_BYTE)&residualBytes, ! 2345: &Ccb->DataLength); ! 2346: ! 2347: DebugPrint((1, "Aha154x MapError: Underrun occured. Request length = %lx, Residual length = %lx\n", Srb->DataTransferLength, residualBytes)); ! 2348: Srb->DataTransferLength -= residualBytes; ! 2349: } ! 2350: ! 2351: return SRB_STATUS_ERROR; ! 2352: ! 2353: case CCB_DATA_OVER_UNDER_RUN: ! 2354: THREE_TO_FOUR((PFOUR_BYTE)&residualBytes, ! 2355: &Ccb->DataLength); ! 2356: if (residualBytes) { ! 2357: Srb->DataTransferLength -= residualBytes; ! 2358: } else { ! 2359: logError = SP_PROTOCOL_ERROR; ! 2360: } ! 2361: status = SRB_STATUS_DATA_OVERRUN; ! 2362: break; ! 2363: ! 2364: case CCB_UNEXPECTED_BUS_FREE: ! 2365: status = SRB_STATUS_UNEXPECTED_BUS_FREE; ! 2366: logError = SP_UNEXPECTED_DISCONNECT; ! 2367: break; ! 2368: ! 2369: case CCB_PHASE_SEQUENCE_FAIL: ! 2370: case CCB_INVALID_DIRECTION: ! 2371: status = SRB_STATUS_PHASE_SEQUENCE_FAILURE; ! 2372: logError = SP_PROTOCOL_ERROR; ! 2373: break; ! 2374: ! 2375: case CCB_BAD_MBO_COMMAND: ! 2376: case CCB_INVALID_OP_CODE: ! 2377: case CCB_BAD_LINKED_LUN: ! 2378: case CCB_DUPLICATE_CCB: ! 2379: case CCB_INVALID_CCB: ! 2380: status = SRB_STATUS_INVALID_REQUEST; ! 2381: logError = SP_INTERNAL_ADAPTER_ERROR; ! 2382: break; ! 2383: ! 2384: default: ! 2385: status = SRB_STATUS_ERROR; ! 2386: logError = SP_INTERNAL_ADAPTER_ERROR; ! 2387: break; ! 2388: } ! 2389: ! 2390: ScsiPortLogError( ! 2391: HwDeviceExtension, ! 2392: Srb, ! 2393: Srb->PathId, ! 2394: Srb->TargetId, ! 2395: Srb->Lun, ! 2396: logError, ! 2397: (2 << 8) | Ccb->HostStatus ! 2398: ); ! 2399: ! 2400: return(status); ! 2401: ! 2402: } // end MapError() ! 2403: ! 2404: ! 2405: BOOLEAN ! 2406: ReadCommandRegister( ! 2407: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 2408: OUT PUCHAR DataByte, ! 2409: IN BOOLEAN TimeOutFlag ! 2410: ) ! 2411: ! 2412: /*++ ! 2413: ! 2414: Routine Description: ! 2415: ! 2416: Read command register. ! 2417: ! 2418: Arguments: ! 2419: ! 2420: DeviceExtesion - Pointer to adapder extension ! 2421: DataByte - Byte read from register ! 2422: ! 2423: Return Value: ! 2424: ! 2425: TRUE if command register read. ! 2426: FALSE if timed out waiting for adapter. ! 2427: ! 2428: --*/ ! 2429: ! 2430: { ! 2431: PBASE_REGISTER baseIoAddress = DeviceExtension->BaseIoAddress; ! 2432: ULONG i; ! 2433: ! 2434: // ! 2435: // Wait up to 5000 microseconds for adapter to be ready. ! 2436: // ! 2437: ! 2438: for (i=0; i<5000; i++) { ! 2439: ! 2440: if (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) & ! 2441: IOP_DATA_IN_PORT_FULL) { ! 2442: ! 2443: // ! 2444: // Adapter ready. Break out of loop. ! 2445: // ! 2446: ! 2447: break; ! 2448: ! 2449: } else { ! 2450: ! 2451: // ! 2452: // Stall 1 microsecond before ! 2453: // trying again. ! 2454: // ! 2455: ! 2456: ScsiPortStallExecution(1); ! 2457: } ! 2458: } ! 2459: ! 2460: if ( (i==5000) && (TimeOutFlag == TRUE)) { ! 2461: ! 2462: ScsiPortLogError( ! 2463: DeviceExtension, ! 2464: NULL, ! 2465: 0, ! 2466: DeviceExtension->HostTargetId, ! 2467: 0, ! 2468: SP_INTERNAL_ADAPTER_ERROR, ! 2469: 3 << 8 ! 2470: ); ! 2471: ! 2472: DebugPrint((1, "Aha154x:ReadCommandRegister: Read command timed out\n")); ! 2473: return FALSE; ! 2474: } ! 2475: ! 2476: *DataByte = ScsiPortReadPortUchar(&baseIoAddress->CommandRegister); ! 2477: ! 2478: return TRUE; ! 2479: ! 2480: } // end ReadCommandRegister() ! 2481: ! 2482: ! 2483: BOOLEAN ! 2484: WriteCommandRegister( ! 2485: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 2486: IN UCHAR AdapterCommand, ! 2487: IN BOOLEAN WaitForIdle ! 2488: ) ! 2489: ! 2490: /*++ ! 2491: ! 2492: Routine Description: ! 2493: ! 2494: Write operation code to command register. ! 2495: ! 2496: Arguments: ! 2497: ! 2498: DeviceExtension - Pointer to adapter extension ! 2499: AdapterCommand - Value to be written to register ! 2500: WaitForIdle - Indicates if the idle bit needs to be checked ! 2501: ! 2502: Return Value: ! 2503: ! 2504: TRUE if command sent. ! 2505: FALSE if timed out waiting for adapter. ! 2506: ! 2507: --*/ ! 2508: ! 2509: { ! 2510: PBASE_REGISTER baseIoAddress = DeviceExtension->BaseIoAddress; ! 2511: ULONG i; ! 2512: UCHAR status; ! 2513: ! 2514: // ! 2515: // Wait up to 500 microseconds for adapter to be ready. ! 2516: // ! 2517: ! 2518: for (i=0; i<5000; i++) { ! 2519: ! 2520: status = ScsiPortReadPortUchar(&baseIoAddress->StatusRegister); ! 2521: ! 2522: if ((status & IOP_COMMAND_DATA_OUT_FULL) || ! 2523: ( WaitForIdle && !(status & IOP_SCSI_HBA_IDLE))) { ! 2524: ! 2525: // ! 2526: // Stall 1 microsecond before ! 2527: // trying again. ! 2528: // ! 2529: ! 2530: ScsiPortStallExecution(1); ! 2531: ! 2532: } else { ! 2533: ! 2534: // ! 2535: // Adapter ready. Break out of loop. ! 2536: // ! 2537: ! 2538: break; ! 2539: } ! 2540: } ! 2541: ! 2542: if (i==5000) { ! 2543: ! 2544: ScsiPortLogError( ! 2545: DeviceExtension, ! 2546: NULL, ! 2547: 0, ! 2548: DeviceExtension->HostTargetId, ! 2549: 0, ! 2550: SP_INTERNAL_ADAPTER_ERROR, ! 2551: (4 << 8) | status); ! 2552: ! 2553: DebugPrint((1, "Aha154x:WriteCommandRegister: Write command timed out\n")); ! 2554: return FALSE; ! 2555: } ! 2556: ! 2557: ScsiPortWritePortUchar(&baseIoAddress->CommandRegister, AdapterCommand); ! 2558: ! 2559: return TRUE; ! 2560: ! 2561: } // end WriteCommandRegister() ! 2562: ! 2563: ! 2564: BOOLEAN ! 2565: WriteDataRegister( ! 2566: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 2567: IN UCHAR DataByte ! 2568: ) ! 2569: ! 2570: /*++ ! 2571: ! 2572: Routine Description: ! 2573: ! 2574: Write data byte to data register. ! 2575: ! 2576: Arguments: ! 2577: ! 2578: DeviceExtension - Pointer to adapter extension ! 2579: DataByte - Value to be written to register ! 2580: ! 2581: Return Value: ! 2582: ! 2583: TRUE if byte sent. ! 2584: FALSE if timed out waiting for adapter. ! 2585: ! 2586: --*/ ! 2587: ! 2588: { ! 2589: PBASE_REGISTER baseIoAddress = DeviceExtension->BaseIoAddress; ! 2590: ULONG i; ! 2591: ! 2592: // ! 2593: // Wait up to 500 microseconds for adapter to be idle ! 2594: // and ready for next byte. ! 2595: // ! 2596: ! 2597: for (i=0; i<500; i++) { ! 2598: ! 2599: if (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) & ! 2600: IOP_COMMAND_DATA_OUT_FULL) { ! 2601: ! 2602: // ! 2603: // Stall 1 microsecond before ! 2604: // trying again. ! 2605: // ! 2606: ! 2607: ScsiPortStallExecution(1); ! 2608: ! 2609: } else { ! 2610: ! 2611: // ! 2612: // Adapter ready. Break out of loop. ! 2613: // ! 2614: ! 2615: break; ! 2616: } ! 2617: } ! 2618: ! 2619: if (i==500) { ! 2620: ! 2621: ScsiPortLogError( ! 2622: DeviceExtension, ! 2623: NULL, ! 2624: 0, ! 2625: DeviceExtension->HostTargetId, ! 2626: 0, ! 2627: SP_INTERNAL_ADAPTER_ERROR, ! 2628: 8 << 8); ! 2629: ! 2630: DebugPrint((1, "Aha154x:WriteDataRegister: Write data timed out\n")); ! 2631: return FALSE; ! 2632: } ! 2633: ! 2634: ScsiPortWritePortUchar(&baseIoAddress->CommandRegister, DataByte); ! 2635: ! 2636: return TRUE; ! 2637: ! 2638: } // end WriteDataRegister() ! 2639: ! 2640: ! 2641: BOOLEAN ! 2642: FirmwareBug ( ! 2643: IN PVOID HwDeviceExtension ! 2644: ) ! 2645: ! 2646: /*++ ! 2647: ! 2648: Routine Description: ! 2649: ! 2650: Check to see if the host adapter firmware has the scatter/gather ! 2651: bug. ! 2652: ! 2653: Arguments: ! 2654: ! 2655: HwDeviceExtension - HBA miniport driver's adapter data storage ! 2656: ! 2657: Return Value: ! 2658: ! 2659: Return FALSE if there is no firmware bug. ! 2660: Return TRUE if firmware has scatter/gather bug. ! 2661: ! 2662: --*/ ! 2663: ! 2664: { ! 2665: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; ! 2666: PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress; ! 2667: UCHAR ch; ! 2668: int i; ! 2669: ! 2670: // ! 2671: // Issue a RETURN SETUP DATA command ! 2672: // If timeout then return TRUE to indicate that there is a firmware bug. ! 2673: // ! 2674: ! 2675: if ((WriteCommandRegister(HwDeviceExtension, ! 2676: AC_RETURN_SETUP_DATA,FALSE)) == FALSE) { ! 2677: return TRUE; ! 2678: } ! 2679: ! 2680: ! 2681: // ! 2682: // Tell the adapter we want to read in 0x11 bytes. ! 2683: // ! 2684: ! 2685: if (WriteDataRegister(HwDeviceExtension,0x11) == FALSE) { ! 2686: return TRUE; ! 2687: } ! 2688: ! 2689: // ! 2690: // Now try to read in 0x11 bytes. ! 2691: // ! 2692: ! 2693: for (i = 0; i< 0x11; i++) { ! 2694: if (ReadCommandRegister(HwDeviceExtension,&ch,TRUE) == FALSE) { ! 2695: return TRUE; ! 2696: } ! 2697: } ! 2698: ! 2699: // ! 2700: // Clear adapter interrupt. ! 2701: // ! 2702: ! 2703: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, ! 2704: IOP_INTERRUPT_RESET); ! 2705: ! 2706: // ! 2707: // Issue SET HA OPTION command. ! 2708: // ! 2709: ! 2710: if (WriteCommandRegister(HwDeviceExtension, ! 2711: AC_SET_HA_OPTION,FALSE) == FALSE) { ! 2712: return TRUE; ! 2713: } ! 2714: ! 2715: // ! 2716: // Delay 500 microseconds. ! 2717: // ! 2718: ! 2719: ScsiPortStallExecution(500); ! 2720: ! 2721: // ! 2722: // Check for invalid command. ! 2723: // ! 2724: ! 2725: if ( (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) & ! 2726: IOP_INVALID_COMMAND) ) { ! 2727: // ! 2728: // Clear adapter interrupt. ! 2729: // ! 2730: ! 2731: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, ! 2732: IOP_INTERRUPT_RESET); ! 2733: return TRUE; ! 2734: } ! 2735: ! 2736: // ! 2737: // send 01h ! 2738: // ! 2739: ! 2740: if (WriteDataRegister(HwDeviceExtension,0x01) == FALSE) { ! 2741: return TRUE; ! 2742: } ! 2743: ! 2744: // ! 2745: // Send same byte as was last received. ! 2746: // ! 2747: ! 2748: if (WriteDataRegister(HwDeviceExtension,ch) == FALSE) { ! 2749: return TRUE; ! 2750: } ! 2751: ! 2752: // ! 2753: // Clear adapter interrupt. ! 2754: // ! 2755: ! 2756: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, ! 2757: IOP_INTERRUPT_RESET); ! 2758: return FALSE; ! 2759: } // end of FirmwareBug () ! 2760: ! 2761: ! 2762: VOID ! 2763: GetHostAdapterBoardId ( ! 2764: IN PVOID HwDeviceExtension, ! 2765: OUT PUCHAR BoardId ! 2766: ) ! 2767: ! 2768: /*++ ! 2769: ! 2770: Routine Description: ! 2771: ! 2772: Get board id, firmware id and hardware id from the host adapter. ! 2773: These info are used to determine if the host adapter supports ! 2774: scatter/gather. ! 2775: ! 2776: Arguments: ! 2777: ! 2778: HwDeviceExtension - HBA miniport driver's adapter data storage ! 2779: ! 2780: Return Value: ! 2781: ! 2782: Board id, hardware id and firmware id (in that order) by modyfing *BoardId ! 2783: If there is any error, it will just return with *BoardId unmodified ! 2784: ! 2785: --*/ ! 2786: ! 2787: { ! 2788: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; ! 2789: PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress; ! 2790: UCHAR firmwareId; ! 2791: UCHAR board_Id; ! 2792: UCHAR hardwareId; ! 2793: ULONG i; ! 2794: ! 2795: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, ! 2796: IOP_INTERRUPT_RESET); ! 2797: ! 2798: if (!WriteCommandRegister(HwDeviceExtension,AC_ADAPTER_INQUIRY,FALSE)) { ! 2799: return; ! 2800: } ! 2801: ! 2802: // ! 2803: // Save byte 0 as board ID. ! 2804: // ! 2805: ! 2806: if ((ReadCommandRegister(HwDeviceExtension,&board_Id,TRUE)) == FALSE) { ! 2807: return; ! 2808: } ! 2809: ! 2810: // ! 2811: // Ignore byte 1. Use hardwareId as scrap storage. ! 2812: // ! 2813: ! 2814: if ((ReadCommandRegister(HwDeviceExtension,&hardwareId,TRUE)) == FALSE) { ! 2815: return; ! 2816: } ! 2817: ! 2818: // ! 2819: // Save byte 2 as hardware revision in hardwareId. ! 2820: // ! 2821: ! 2822: if ((ReadCommandRegister(HwDeviceExtension,&hardwareId,TRUE)) == FALSE) { ! 2823: return; ! 2824: } ! 2825: ! 2826: if ((ReadCommandRegister(HwDeviceExtension,&firmwareId,TRUE)) == FALSE) { ! 2827: return; ! 2828: } ! 2829: ! 2830: // ! 2831: // Interrupt handler is not yet installed so wait for HACC by hand. ! 2832: // ! 2833: ! 2834: for (i = 0; i<5000; i++) { ! 2835: if (ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister) == ! 2836: (IOP_ANY_INTERRUPT | IOP_COMMAND_COMPLETE) ) { ! 2837: break; ! 2838: } ! 2839: ScsiPortStallExecution(1); ! 2840: } ! 2841: ! 2842: // ! 2843: // If timeout then return with *BoardId unmodified. This means that ! 2844: // scatter/gather won't be supported. ! 2845: // ! 2846: ! 2847: if (i == 5000) { ! 2848: return; ! 2849: } ! 2850: ! 2851: // ! 2852: // Clear adapter interrupt. ! 2853: // ! 2854: ! 2855: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,IOP_INTERRUPT_RESET); ! 2856: ! 2857: // ! 2858: // Return with appropriate ID's. ! 2859: // ! 2860: ! 2861: *BoardId++ = board_Id; ! 2862: *BoardId++ = hardwareId; ! 2863: *BoardId++ = firmwareId; ! 2864: ! 2865: DebugPrint((1,"board_id = %d\n",board_Id)); ! 2866: DebugPrint((1,"hardwareid = %d\n",hardwareId)); ! 2867: DebugPrint((1,"fid = %d\n",firmwareId)); ! 2868: ! 2869: } // end of GetHostAdapterBoardId () ! 2870: ! 2871: ! 2872: BOOLEAN ! 2873: ScatterGatherSupported ( ! 2874: IN PHW_DEVICE_EXTENSION HwDeviceExtension ! 2875: ) ! 2876: ! 2877: /*++ ! 2878: ! 2879: Routine Description: ! 2880: Determine if the host adapter supports scatter/gather. On older ! 2881: boards, scatter/gather is not supported. On some boards, there is ! 2882: a bug that causes data corruption on multi-segment WRITE commands. ! 2883: The algorithm to determine whether the board has the scatter/gather ! 2884: bug is not "clean" but there is no other way since the firmware revision ! 2885: levels returned by the host adapter are inconsistent with previous ! 2886: releases. ! 2887: ! 2888: Arguments: ! 2889: ! 2890: HwDeviceExtension - HBA miniport driver's adapter data storage ! 2891: ! 2892: Return Value: ! 2893: ! 2894: Return TRUE if the algorithm determines that there is no scatter/gather ! 2895: firmware bug. ! 2896: ! 2897: Return FALSE if the algorithm determines that the adapter is an older ! 2898: board or that the firmware contains the scatter gather bug ! 2899: ! 2900: --*/ ! 2901: { ! 2902: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; ! 2903: PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress; ! 2904: UCHAR HostAdapterId[3]; ! 2905: ! 2906: GetHostAdapterBoardId(HwDeviceExtension,&HostAdapterId[0]); ! 2907: ! 2908: // ! 2909: // If it's an older board then scatter/gather is not supported. ! 2910: // ! 2911: ! 2912: if ( (HostAdapterId[BOARD_ID] == OLD_BOARD_ID1) || ! 2913: (HostAdapterId[BOARD_ID] == OLD_BOARD_ID2) ) { ! 2914: return FALSE; ! 2915: } ! 2916: ! 2917: // ! 2918: // If 1540A/B then check for firmware bug. ! 2919: // ! 2920: ! 2921: if (HostAdapterId[BOARD_ID] == A154X_BOARD) { ! 2922: if (FirmwareBug(HwDeviceExtension)) { ! 2923: return FALSE; ! 2924: } ! 2925: } ! 2926: ! 2927: // ! 2928: // Now check hardware ID and firmware ID. ! 2929: // ! 2930: ! 2931: if (HostAdapterId[HARDWARE_ID] != A154X_BAD_HARDWARE_ID) { ! 2932: return TRUE; ! 2933: } ! 2934: ! 2935: if (HostAdapterId[FIRMWARE_ID] != A154X_BAD_FIRMWARE_ID) { ! 2936: return TRUE; ! 2937: } ! 2938: ! 2939: // ! 2940: // Host adapter has scatter/gather bug. ! 2941: // Clear interrupt on adapter. ! 2942: // ! 2943: ! 2944: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,IOP_INTERRUPT_RESET); ! 2945: ! 2946: return FALSE; ! 2947: ! 2948: } // end of ScatterGatherSupported () ! 2949: ! 2950: ! 2951: BOOLEAN ! 2952: SpinForInterrupt( ! 2953: IN PHW_DEVICE_EXTENSION DeviceExtension, ! 2954: IN BOOLEAN TimeOutFlag ! 2955: ) ! 2956: ! 2957: /*++ ! 2958: ! 2959: Routine Description: ! 2960: ! 2961: Wait for interrupt. ! 2962: ! 2963: Arguments: ! 2964: ! 2965: DeviceExtension - Pointer to adapter extension ! 2966: ! 2967: Return Value: ! 2968: ! 2969: TRUE if interrupt occurred. ! 2970: FALSE if timed out waiting for interrupt. ! 2971: ! 2972: --*/ ! 2973: ! 2974: { ! 2975: PBASE_REGISTER baseIoAddress = DeviceExtension->BaseIoAddress; ! 2976: ULONG i; ! 2977: ! 2978: // ! 2979: // Wait up to 1 millisecond for interrupt to occur. ! 2980: // ! 2981: ! 2982: for (i=0; i<1000; i++) { ! 2983: ! 2984: if (ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister) & IOP_COMMAND_COMPLETE) { ! 2985: ! 2986: // ! 2987: // Interrupt occurred. Break out of wait loop. ! 2988: // ! 2989: ! 2990: break; ! 2991: ! 2992: } else { ! 2993: ! 2994: // ! 2995: // Stall one microsecond. ! 2996: // ! 2997: ! 2998: ScsiPortStallExecution(1); ! 2999: } ! 3000: } ! 3001: ! 3002: if ( (i==1000) && (TimeOutFlag == TRUE)) { ! 3003: ! 3004: ScsiPortLogError(DeviceExtension, ! 3005: NULL, ! 3006: 0, ! 3007: DeviceExtension->HostTargetId, ! 3008: 0, ! 3009: SP_INTERNAL_ADAPTER_ERROR, ! 3010: 9 << 8); ! 3011: ! 3012: DebugPrint((1, "Aha154x:SpinForInterrupt: Timed out waiting for interrupt\n")); ! 3013: ! 3014: return FALSE; ! 3015: ! 3016: } else { ! 3017: ! 3018: // ! 3019: // Clear interrupt on adapter. ! 3020: // ! 3021: ! 3022: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET); ! 3023: ! 3024: return TRUE; ! 3025: } ! 3026: ! 3027: } // end SpinForInterrupt() ! 3028: ! 3029: ! 3030: BOOLEAN UnlockMailBoxes ( ! 3031: IN PVOID HwDeviceExtension ! 3032: ) ! 3033: ! 3034: /*++ ! 3035: ! 3036: Routine Description: ! 3037: ! 3038: Unlock 1542B+ or 1542C mailboxes so that the driver ! 3039: can zero out mailboxes when it's initializing the adapter. ! 3040: ! 3041: The mailboxes are locked if: ! 3042: 1. >1Gb option is enabled (this option is available for 154xB+ and ! 3043: 154xC). ! 3044: ! 3045: 2. Dynamic scan lock option is enabled (154xC board only) ! 3046: ! 3047: The reason the mailboxes are locked by the adapter's firmware is ! 3048: because the BIOS is now reporting 255/63 translation instead of 64/32. ! 3049: As such, if a user inadvertently enabled the >1Gb option (enabling ! 3050: 255/63 translation) and still uses an old driver, hard disk data ! 3051: will be corrupted. Therefore, the firmware will not allow mailboxes ! 3052: to be initialized unless the user knows what he is doing and updates ! 3053: his driver so that his disk won't be trashed. ! 3054: ! 3055: Arguments: ! 3056: ! 3057: DeviceExtension - Pointer to adapter extension ! 3058: ! 3059: Return Value: ! 3060: ! 3061: TRUE if mailboxes are unlocked. ! 3062: FALSE if mailboxes are not unlocked. ! 3063: Note that if the adapter is just a 154xB board (without the >1Gb ! 3064: option), this routine will return FALSE. ! 3065: ! 3066: --*/ ! 3067: ! 3068: { ! 3069: UCHAR locktype; ! 3070: ! 3071: // ! 3072: // Request information. ! 3073: // ! 3074: ! 3075: if (WriteCommandRegister(HwDeviceExtension, AC_GET_BIOS_INFO, TRUE) == FALSE) { ! 3076: return FALSE; ! 3077: } ! 3078: ! 3079: ! 3080: // ! 3081: // Retrieve first byte. ! 3082: // ! 3083: ! 3084: if (ReadCommandRegister(HwDeviceExtension,&locktype,FALSE) == FALSE) { ! 3085: return FALSE; ! 3086: } ! 3087: ! 3088: // ! 3089: // Check for extended bios translation enabled option on 1540C and ! 3090: // 1540B with 1GB support. ! 3091: // ! 3092: ! 3093: if (locktype != TRANSLATION_ENABLED) { ! 3094: ! 3095: // ! 3096: // Extended translation is disabled. Retrieve lock status. ! 3097: // ! 3098: ! 3099: if (ReadCommandRegister(HwDeviceExtension,&locktype,FALSE) == FALSE) { ! 3100: return FALSE; ! 3101: } ! 3102: ! 3103: if (locktype == DYNAMIC_SCAN_LOCK) { ! 3104: return(SendUnlockCommand(HwDeviceExtension,locktype)); ! 3105: } ! 3106: return FALSE; ! 3107: } ! 3108: ! 3109: // ! 3110: // Extended BIOS translation (255/63) is enabled. ! 3111: // ! 3112: ! 3113: ! 3114: if (ReadCommandRegister(HwDeviceExtension,&locktype,FALSE) == FALSE) { ! 3115: return FALSE; ! 3116: } ! 3117: ! 3118: if ((locktype == TRANSLATION_LOCK) || (locktype == DYNAMIC_SCAN_LOCK)) { ! 3119: return(SendUnlockCommand(HwDeviceExtension,locktype)); ! 3120: } ! 3121: ! 3122: return FALSE; ! 3123: } // end of UnlockMailBoxes () ! 3124: ! 3125: ! 3126: BOOLEAN ! 3127: SendUnlockCommand( ! 3128: IN PVOID HwDeviceExtension, ! 3129: IN UCHAR locktype ! 3130: ) ! 3131: ! 3132: /*++ ! 3133: ! 3134: Routine Description: ! 3135: ! 3136: Send unlock command to 1542B+ or 1542C board so that the driver ! 3137: can zero out mailboxes when it's initializing the adapter. ! 3138: ! 3139: ! 3140: Arguments: ! 3141: ! 3142: DeviceExtension - Pointer to adapter extension ! 3143: ! 3144: Return Value: ! 3145: ! 3146: TRUE if commands are sent successfully. ! 3147: FALSE if not. ! 3148: ! 3149: --*/ ! 3150: ! 3151: { ! 3152: PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; ! 3153: PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress; ! 3154: ! 3155: if (WriteCommandRegister(deviceExtension, ! 3156: AC_SET_MAILBOX_INTERFACE,TRUE) == FALSE) { ! 3157: return FALSE; ! 3158: } ! 3159: ! 3160: if (WriteDataRegister(deviceExtension,MAILBOX_UNLOCK) == FALSE) { ! 3161: return FALSE; ! 3162: } ! 3163: ! 3164: if (WriteDataRegister(deviceExtension,locktype) == FALSE) { ! 3165: return FALSE; ! 3166: } ! 3167: ! 3168: // ! 3169: // Clear interrupt on adapter. ! 3170: // ! 3171: ! 3172: ! 3173: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET); ! 3174: ! 3175: return TRUE; ! 3176: } // end of SendUnlockCommand () ! 3177: ! 3178: ! 3179: BOOLEAN ! 3180: FinishHBACmd( ! 3181: IN PHW_DEVICE_EXTENSION HwDeviceExtension ! 3182: ) ! 3183: ! 3184: /*++ ! 3185: ! 3186: Routine Description: ! 3187: ! 3188: Wait for command complete interrupt, clear interrupt, chk cmd status. ! 3189: This is done because the driver has not registered our interrupt handler ! 3190: (which would normally do this work). ! 3191: ! 3192: Arguments: ! 3193: ! 3194: HwDeviceExtension - Pointer to adapter extension ! 3195: ! 3196: Return Value: ! 3197: ! 3198: TRUE if command completed successfully. ! 3199: FALSE if timed out waiting for adapter or invalid command. ! 3200: ! 3201: --*/ ! 3202: ! 3203: { ! 3204: PBASE_REGISTER baseIoAddress = HwDeviceExtension->BaseIoAddress; ! 3205: ULONG i; ! 3206: ! 3207: for (i=0; i<500; i++) { ! 3208: ! 3209: if (!((ScsiPortReadPortUchar(&baseIoAddress->InterruptRegister) & ! 3210: (IOP_COMMAND_COMPLETE | IOP_ANY_INTERRUPT))== ! 3211: (IOP_COMMAND_COMPLETE | IOP_ANY_INTERRUPT))) { ! 3212: ! 3213: // ! 3214: // Stall 1 microsecond before ! 3215: // trying again. ! 3216: // ! 3217: ! 3218: ScsiPortStallExecution(1); ! 3219: ! 3220: } else { ! 3221: ! 3222: // ! 3223: // Adapter ready. Break out of loop. ! 3224: // ! 3225: ! 3226: break; ! 3227: } ! 3228: } ! 3229: ! 3230: if (i==500) { ! 3231: ! 3232: ScsiPortLogError(HwDeviceExtension, ! 3233: NULL, ! 3234: 0, ! 3235: HwDeviceExtension->HostTargetId, ! 3236: 0, ! 3237: SP_INTERNAL_ADAPTER_ERROR, ! 3238: 4 << 8); ! 3239: ! 3240: DebugPrint((1, "A154x:FinishHBACmd: Wait for CmdCmplt & AnyIntr failed\n")); ! 3241: return FALSE; ! 3242: } ! 3243: ! 3244: ScsiPortWritePortUchar(&baseIoAddress->StatusRegister,IOP_INTERRUPT_RESET); ! 3245: ! 3246: if (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) & (IOP_INVALID_COMMAND)) { ! 3247: return FALSE; ! 3248: } ! 3249: ! 3250: return TRUE; ! 3251: } // end FinishHBACmd() ! 3252: ! 3253: ! 3254: ULONG ! 3255: AhaParseArgumentString( ! 3256: IN PCHAR String, ! 3257: IN PCHAR KeyWord ! 3258: ) ! 3259: ! 3260: /*++ ! 3261: ! 3262: Routine Description: ! 3263: ! 3264: This routine will parse the string for a match on the keyword, then ! 3265: calculate the value for the keyword and return it to the caller. ! 3266: ! 3267: Arguments: ! 3268: ! 3269: String - The ASCII string to parse. ! 3270: KeyWord - The keyword for the value desired. ! 3271: ! 3272: Return Values: ! 3273: ! 3274: Zero if value not found ! 3275: Value converted from ASCII to binary. ! 3276: ! 3277: --*/ ! 3278: ! 3279: { ! 3280: PCHAR cptr; ! 3281: PCHAR kptr; ! 3282: ULONG value; ! 3283: ULONG stringLength = 0; ! 3284: ULONG keyWordLength = 0; ! 3285: ULONG index; ! 3286: ! 3287: // ! 3288: // Calculate the string length and lower case all characters. ! 3289: // ! 3290: cptr = String; ! 3291: while (*cptr) { ! 3292: ! 3293: if (*cptr >= 'A' && *cptr <= 'Z') { ! 3294: *cptr = *cptr + ('a' - 'A'); ! 3295: } ! 3296: cptr++; ! 3297: stringLength++; ! 3298: } ! 3299: ! 3300: // ! 3301: // Calculate the keyword length and lower case all characters. ! 3302: // ! 3303: cptr = KeyWord; ! 3304: while (*cptr) { ! 3305: ! 3306: if (*cptr >= 'A' && *cptr <= 'Z') { ! 3307: *cptr = *cptr + ('a' - 'A'); ! 3308: } ! 3309: cptr++; ! 3310: keyWordLength++; ! 3311: } ! 3312: ! 3313: if (keyWordLength > stringLength) { ! 3314: ! 3315: // ! 3316: // Can't possibly have a match. ! 3317: // ! 3318: return 0; ! 3319: } ! 3320: ! 3321: // ! 3322: // Now setup and start the compare. ! 3323: // ! 3324: cptr = String; ! 3325: ! 3326: ContinueSearch: ! 3327: // ! 3328: // The input string may start with white space. Skip it. ! 3329: // ! 3330: while (*cptr == ' ' || *cptr == '\t') { ! 3331: cptr++; ! 3332: } ! 3333: ! 3334: if (*cptr == '\0') { ! 3335: ! 3336: // ! 3337: // end of string. ! 3338: // ! 3339: return 0; ! 3340: } ! 3341: ! 3342: kptr = KeyWord; ! 3343: while (*cptr++ == *kptr++) { ! 3344: ! 3345: if (*(cptr - 1) == '\0') { ! 3346: ! 3347: // ! 3348: // end of string ! 3349: // ! 3350: return 0; ! 3351: } ! 3352: } ! 3353: ! 3354: if (*(kptr - 1) == '\0') { ! 3355: ! 3356: // ! 3357: // May have a match backup and check for blank or equals. ! 3358: // ! 3359: ! 3360: cptr--; ! 3361: while (*cptr == ' ' || *cptr == '\t') { ! 3362: cptr++; ! 3363: } ! 3364: ! 3365: // ! 3366: // Found a match. Make sure there is an equals. ! 3367: // ! 3368: if (*cptr != '=') { ! 3369: ! 3370: // ! 3371: // Not a match so move to the next semicolon. ! 3372: // ! 3373: while (*cptr) { ! 3374: if (*cptr++ == ';') { ! 3375: goto ContinueSearch; ! 3376: } ! 3377: } ! 3378: return 0; ! 3379: } ! 3380: ! 3381: // ! 3382: // Skip the equals sign. ! 3383: // ! 3384: cptr++; ! 3385: ! 3386: // ! 3387: // Skip white space. ! 3388: // ! 3389: while ((*cptr == ' ') || (*cptr == '\t')) { ! 3390: cptr++; ! 3391: } ! 3392: ! 3393: if (*cptr == '\0') { ! 3394: ! 3395: // ! 3396: // Early end of string, return not found ! 3397: // ! 3398: return 0; ! 3399: } ! 3400: ! 3401: if (*cptr == ';') { ! 3402: ! 3403: // ! 3404: // This isn't it either. ! 3405: // ! 3406: cptr++; ! 3407: goto ContinueSearch; ! 3408: } ! 3409: ! 3410: value = 0; ! 3411: if ((*cptr == '0') && (*(cptr + 1) == 'x')) { ! 3412: ! 3413: // ! 3414: // Value is in Hex. Skip the "0x" ! 3415: // ! 3416: cptr += 2; ! 3417: for (index = 0; *(cptr + index); index++) { ! 3418: ! 3419: if (*(cptr + index) == ' ' || ! 3420: *(cptr + index) == '\t' || ! 3421: *(cptr + index) == ';') { ! 3422: break; ! 3423: } ! 3424: ! 3425: if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) { ! 3426: value = (16 * value) + (*(cptr + index) - '0'); ! 3427: } else { ! 3428: if ((*(cptr + index) >= 'a') && (*(cptr + index) <= 'f')) { ! 3429: value = (16 * value) + (*(cptr + index) - 'a' + 10); ! 3430: } else { ! 3431: ! 3432: // ! 3433: // Syntax error, return not found. ! 3434: // ! 3435: return 0; ! 3436: } ! 3437: } ! 3438: } ! 3439: } else { ! 3440: ! 3441: // ! 3442: // Value is in Decimal. ! 3443: // ! 3444: for (index = 0; *(cptr + index); index++) { ! 3445: ! 3446: if (*(cptr + index) == ' ' || ! 3447: *(cptr + index) == '\t' || ! 3448: *(cptr + index) == ';') { ! 3449: break; ! 3450: } ! 3451: ! 3452: if ((*(cptr + index) >= '0') && (*(cptr + index) <= '9')) { ! 3453: value = (10 * value) + (*(cptr + index) - '0'); ! 3454: } else { ! 3455: ! 3456: // ! 3457: // Syntax error return not found. ! 3458: // ! 3459: return 0; ! 3460: } ! 3461: } ! 3462: } ! 3463: ! 3464: return value; ! 3465: } else { ! 3466: ! 3467: // ! 3468: // Not a match check for ';' to continue search. ! 3469: // ! 3470: while (*cptr) { ! 3471: if (*cptr++ == ';') { ! 3472: goto ContinueSearch; ! 3473: } ! 3474: } ! 3475: ! 3476: return 0; ! 3477: } ! 3478: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.