1 /* 2 * vmscsi-- Miniport driver for the Buslogic BT 958 SCSI Controller 3 * under Windows 2000/XP/Server 2003 4 * 5 * Based in parts on the buslogic driver for the same device 6 * available with the GNU Linux Operating System. 7 * 8 * This program is free software; you can redistribute it and/or 9 * modify it under the terms of the GNU General Public License 10 * as published by the Free Software Foundation; either version 2 11 * of the License, or (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 * 18 * You should have received a copy of the GNU General Public License along 19 * with this program; if not, write to the Free Software Foundation, Inc., 20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 21 */ 22 23 //____________________________________________________________________________________ 24 // 25 // File description :The driver for BusLogic-BT958 SCSI Host adapter card. 26 // This driver assumes that the host adapter(HA from now on) is a PCI device. 27 // This is an effort to build a driver for this card for the windows XP environment 28 // since the native XP installation doesnt provide this driver. 29 // 30 // The technical reference for this device is at : 31 // 32 // Author: Namita Lal, Sirish Raghuram Calsoft Pvt Ltd 33 // Date: 5th Feb 2003 34 // Status: Driver version 1.2.0.0 35 // Performance tuned 36 // Correctness tested for 37 // 1. Installation at OS install time 38 // 2. Installation in an installed OS 39 // 3. Installation by upgrading a previous version 40 // on all flavours of WinXP and Win Server 2003 41 // For Win2k however, please refer PR 22812 42 /* 43 Revision History: 44 v1.0.0.4 // Pre final release to VMware in Sep 2001, without WMI 45 | 46 | 47 v 48 v1.0.0.5 // Sep 2001 release to VMware, with WMI 49 | 50 | 51 v 52 v1.0.0.6 // Fix for bug with Nero Burning ROM in XP 53 | // where SCSI_AUTO_SENSE is turned off at times 54 | 55 | 56 |---------> v1.1.0.0 // Performance optimizations: 57 | | // A. WMI disabled, B. Queueing depth increased 58 | | // C. Control flow changed (bug) 59 | | 60 | v 61 | v1.1.0.1 // Fix for .NET restart freeze with 1.1.0.0 62 | // Breaks on XP 63 | 64 v 65 v1.2.0.0 // A. WMI disabled, B. Queueing depth increased 66 | 67 | 68 | 69 v 70 v1.2.0.1 // Fix PR 40284, affects pure ACPI Win2k systems. 71 | 72 | 73 | 74 v 75 v1.2.0.2 // Fix PR 40284 correctly, disable interrupts in the initialization routine. 76 // CURRENT VERSION 77 */ 78 //____________________________________________________________________________________ 79 80 #include "BusLogic958.h" 81 82 ULONG 83 NTAPI 84 DriverEntry(IN PVOID DriverObject, 85 IN PVOID Argument2 86 ) 87 //_________________________________________________________________________ 88 // Routine Description: 89 // Installable driver initialization entry point for system. 90 // Arguments: 91 // Driver Object 92 // Return Value: 93 // Status from ScsiPortInitialize() 94 //_________________________________________________________________________ 95 { 96 HW_INITIALIZATION_DATA hwInitializationData; 97 ULONG Status; 98 ULONG i; 99 ULONG HwContext; 100 // static int cardNo = 0; 101 102 UCHAR VendorId[4] = { '1', '0', '4', 'b' }; 103 UCHAR DeviceId[4] = { '1', '0', '4', '0' }; 104 105 DebugPrint((TRACE,"\n BusLogic - Inside the DriverEntry function \n")); 106 107 // Zero out structure. 108 for (i = 0; i < sizeof(HW_INITIALIZATION_DATA); i++) 109 { 110 ((PUCHAR) & hwInitializationData)[i] = 0; 111 } 112 113 // Set size of hwInitializationData. 114 hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA); 115 116 // Set entry points. 117 hwInitializationData.HwInitialize = BT958HwInitialize; 118 hwInitializationData.HwResetBus = BT958HwResetBus; 119 hwInitializationData.HwStartIo = BT958HwStartIO; 120 hwInitializationData.HwInterrupt = BT958HwInterrupt; 121 hwInitializationData.HwAdapterControl = BT958HwAdapterControl; 122 hwInitializationData.HwFindAdapter = BT958HwFindAdapter; 123 124 // Indicate no buffer mapping but will need physical addresses 125 hwInitializationData.NeedPhysicalAddresses = TRUE; 126 127 // Indicate Auto request sense is supported 128 hwInitializationData.AutoRequestSense = TRUE; 129 hwInitializationData.MultipleRequestPerLu = TRUE; 130 131 #if TAG_QUEUING 132 hwInitializationData.TaggedQueuing = TRUE; 133 #else 134 hwInitializationData.TaggedQueuing = FALSE; 135 #endif 136 137 hwInitializationData.AdapterInterfaceType = PCIBus; 138 139 // Fill in the vendor id and the device id 140 hwInitializationData.VendorId = &VendorId; 141 hwInitializationData.VendorIdLength = 4; 142 hwInitializationData.DeviceId = &DeviceId; 143 hwInitializationData.DeviceIdLength = 4; 144 145 146 hwInitializationData.NumberOfAccessRanges = 2; 147 148 149 // Specify size of extensions. 150 hwInitializationData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); 151 152 // logical unit extension 153 hwInitializationData.SrbExtensionSize = sizeof(BusLogic_CCB_T); 154 155 HwContext = 0; 156 157 DebugPrint((TRACE,"\n BusLogic - Calling the ScsiPortInitialize Routine\n")); 158 159 Status = ScsiPortInitialize(DriverObject, 160 Argument2, 161 &hwInitializationData, 162 &HwContext); 163 164 DebugPrint((TRACE,"\n BusLogic - Exiting the DriverEntry function \n")); 165 DebugPrint((INFO,"\n BusLogic - Status = %ul \n", Status)); 166 return( Status ); 167 168 } // end DriverEntry() 169 170 171 ULONG 172 NTAPI 173 BT958HwFindAdapter(IN PVOID HwDeviceExtension, 174 IN PVOID Context, 175 IN PVOID BusInformation, 176 IN PCHAR ArgumentString, 177 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, 178 OUT PBOOLEAN Again 179 ) 180 //_________________________________________________________________________________________________ 181 // Routine Description: 182 // This function is called by the OS-specific port driver after the necessary storage 183 // has been allocated, to gather information about the adapter's configuration. 184 // 185 // Arguments: 186 // HwDeviceExtension - HBA miniport driver's adapter data storage 187 // Context - Register base address 188 // ConfigInfo - Configuration information structure describing HBA 189 // This structure is defined in PORT.H. 190 // 191 // Return Value: 192 // HwScsiFindAdapter must return one of the following status values: 193 // SP_RETURN_FOUND: Indicates a supported HBA was found and that the HBA-relevant 194 // configuration information was successfully determined and set in 195 // the PORT_CONFIGURATION_INFORMATION structure. 196 // SP_RETURN_ERROR: Indicates an HBA was found but there was error obtaining the 197 // configuration information. If possible, such an error should be 198 // logged with ScsiPortLogError. 199 // SP_RETURN_BAD_CONFIG: Indicates the supplied configuration information was invalid 200 // for the adapter. 201 // SP_RETURN_NOT_FOUND: Indicates no supported HBA was found for the supplied 202 // configuration information. 203 //________________________________________________________________________________________________ 204 { 205 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 206 BusLogic_HostAdapter_T *hcsp = &(deviceExtension->hcs); 207 // static UCHAR k = 0; 208 PACCESS_RANGE accessRange; 209 // PCI_COMMON_CONFIG PCICommonConfig; 210 PUCHAR pciAddress; 211 char NumPort = 0; 212 213 DebugPrint((TRACE,"\n BusLogic - Inside the Find Adapter Routine\n")); 214 215 *Again = FALSE; 216 217 accessRange = &((*(ConfigInfo->AccessRanges))[0]); 218 219 // Inform SCSIPORT that we are NOT a WMI data provider 220 // Sirish, 10th June 2002 221 ConfigInfo->WmiDataProvider = FALSE; 222 /*Sirish, 10th June 2002 BT958WmiInitialize(deviceExtension);*/ 223 224 // Check for configuration information passed in form the system 225 if ((*ConfigInfo->AccessRanges)[0].RangeLength != 0) 226 { 227 // check if the system supplied bus-relative address is valid and has not been 228 // claimed by another device 229 if ( ScsiPortValidateRange(deviceExtension, 230 ConfigInfo->AdapterInterfaceType, 231 ConfigInfo->SystemIoBusNumber, 232 accessRange->RangeStart, 233 accessRange->RangeLength, 234 TRUE) ) // TRUE: iniospace 235 { 236 DebugPrint((INFO,"\n BusLogic - Validate Range function succeeded \n")); 237 238 // Map the Bus-relative range addresses to system-space logical range addresses 239 // so that these mapped logical addresses can be called with SciPortRead/Writexxx 240 // to determine whether the adapter is an HBA that the driver supports 241 242 pciAddress = (PUCHAR) ScsiPortGetDeviceBase(deviceExtension, 243 ConfigInfo->AdapterInterfaceType, 244 ConfigInfo->SystemIoBusNumber, 245 accessRange->RangeStart, 246 accessRange->RangeLength, 247 TRUE); // TRUE: iniospace 248 249 if(pciAddress) 250 { 251 DebugPrint((INFO,"\n BusLogic - Get Device Base function succeeded \n")); 252 253 memset(hcsp, 0, sizeof(BusLogic_HostAdapter_T)); 254 255 // points to structure of type BT958_HA which has device specific information. This needs 256 // to be either changed or modified with our specific info. 257 hcsp->IO_Address = pciAddress; 258 hcsp->IRQ_Channel = (UCHAR)ConfigInfo->BusInterruptLevel; 259 NumPort++; 260 } 261 } 262 } 263 264 if (NumPort == 0) 265 { 266 return(SP_RETURN_NOT_FOUND); 267 } 268 269 // Hardware found, let's find out hardware configuration 270 // and fill out ConfigInfo table for WinNT 271 ConfigInfo->NumberOfBuses = 1; 272 ConfigInfo->MaximumTransferLength = MAX_TRANSFER_SIZE; 273 274 #if SG_SUPPORT 275 ConfigInfo->ScatterGather = TRUE; 276 #else 277 ConfigInfo->ScatterGather = FALSE; 278 #endif 279 280 ConfigInfo->Master = TRUE; 281 ConfigInfo->NeedPhysicalAddresses = TRUE; 282 ConfigInfo->Dma32BitAddresses = TRUE; 283 ConfigInfo->InterruptMode = LevelSensitive; 284 285 #if TAG_QUEUING 286 ConfigInfo->TaggedQueuing = TRUE; 287 #else 288 ConfigInfo->TaggedQueuing = FALSE; 289 #endif 290 291 // Should we change this to double-word aligned to increase performance 292 ConfigInfo->AlignmentMask = 0x0; 293 294 if (!Buslogic_InitBT958(deviceExtension,ConfigInfo)) // hardware specific initializations. Find what's for our card 295 { 296 ScsiPortLogError(deviceExtension, 297 NULL, 298 0, 299 0, 300 0, 301 SP_INTERNAL_ADAPTER_ERROR, 302 7 << 8); 303 304 return(SP_RETURN_ERROR); 305 } 306 307 if (NumPort != 0) 308 *Again = TRUE; 309 310 return(SP_RETURN_FOUND); 311 312 } // end BT958FindAdapter() 313 314 315 BOOLEAN 316 Buslogic_InitBT958(PHW_DEVICE_EXTENSION deviceExtension, 317 PPORT_CONFIGURATION_INFORMATION ConfigInfo) 318 //_________________________________________________________________________ 319 // Routine Description: 320 // This routine is called from the driver's FindAdapter routine 321 // On invocation this routine probes the host adapter to check 322 // if its hardware registers are responding correctly, and 323 // initializes the device and makes it ready for IO 324 // Arguments: 325 // 1. deviceExtension 326 // 2. Port Configuration info 327 // Return Value: 328 // TRUE : Device initialized properly 329 // FALSE : Device failed to initialize 330 //_________________________________________________________________________ 331 { 332 CHAR ch; 333 334 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 335 336 // Probe the Host Adapter. 337 // If unsuccessful, abort further initialization. 338 if (!BusLogic_ProbeHostAdapter(HostAdapter)) 339 return FALSE; 340 341 // Hard Reset the Host Adapter. 342 // If unsuccessful, abort further initialization. 343 if (!BusLogic_HardwareResetHostAdapter(HostAdapter, TRUE)) 344 return FALSE; 345 346 /* 347 * PR 40284 -- Disable interrupts until driver initialization is complete. 348 */ 349 ch = 0; 350 if (BusLogic_Command(HostAdapter, BusLogic_DisableHostAdapterInterrupt, 351 &ch, sizeof(ch), NULL, 0) < 0) { 352 DebugPrint((WARNING, "\n BusLogic - Could not disable interrupts!\n")); 353 } else { 354 DebugPrint((INFO, "\n BusLogic - Disabled interrupts.\n")); 355 } 356 357 // Check the Host Adapter. 358 // If unsuccessful, abort further initialization. 359 if (!BusLogic_CheckHostAdapter(HostAdapter)) 360 return FALSE; 361 362 // Allocate a Noncached Extension to use for mail boxes. 363 deviceExtension->NoncachedExtension = ScsiPortGetUncachedExtension(deviceExtension, 364 ConfigInfo, 365 sizeof(NONCACHED_EXTENSION)); 366 367 if (deviceExtension->NoncachedExtension == NULL) 368 { 369 // Log error. 370 ScsiPortLogError(deviceExtension, 371 NULL, 372 0, 373 0, 374 0, 375 SP_INTERNAL_ADAPTER_ERROR, 376 7 << 8); 377 378 // abort further initialization 379 return FALSE; 380 } 381 382 // Read the Host Adapter Configuration, Configure the Host Adapter, 383 // Acquire the System Resources necessary to use the Host Adapter, then 384 // Create the Initial CCBs, Initialize the Host Adapter, and finally 385 // perform Target Device Inquiry. 386 if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && 387 //BusLogic_ReportHostAdapterConfiguration(HostAdapter) && 388 BusLogic_InitializeHostAdapter(deviceExtension, ConfigInfo) && 389 BusLogic_TargetDeviceInquiry(HostAdapter)) 390 { 391 // Fill in the: 392 // 1.Maximum number of scsi target devices that are supported by our adapter 393 ConfigInfo->MaximumNumberOfTargets = HostAdapter->MaxTargetDevices; 394 // 2. Maximum number of logical units per target the HBA can control. 395 ConfigInfo->MaximumNumberOfLogicalUnits = HostAdapter->MaxLogicalUnits; 396 ConfigInfo->InitiatorBusId[0] = HostAdapter->SCSI_ID; 397 // Maximum number of breaks between address ranges that a data buffer can 398 // have if the HBA supports scatter/gather. In other words, the number of 399 // scatter/gather lists minus one. 400 ConfigInfo->NumberOfPhysicalBreaks = HostAdapter->DriverScatterGatherLimit; 401 } 402 else 403 { 404 // An error occurred during Host Adapter Configuration Querying, Host 405 // Adapter Configuration, Host Adapter Initialization, or Target Device Inquiry, 406 // so return FALSE 407 408 return FALSE; 409 } 410 // Initialization completed successfully 411 return TRUE; 412 } // end Buslogic_InitBT958 413 414 415 BOOLEAN 416 BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter) 417 //____________________________________________________________________________________ 418 // Routine Description: BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter. 419 // The routine reads the status, interrupt and geometry regiter and 420 // checks if their contents are valid 421 // Arguments: 422 // 1. Host Adapter structure 423 // 424 // Return Value: 425 // TRUE: Probe completed successfully 426 // FALSE: Probe failed 427 //____________________________________________________________________________________ 428 { 429 BusLogic_StatusRegister_T StatusRegister; 430 BusLogic_InterruptRegister_T InterruptRegister; 431 BusLogic_GeometryRegister_T GeometryRegister; 432 433 DebugPrint((TRACE,"\n BusLogic - Inside ProbeHostaAdapter function \n")); 434 // Read the Status, Interrupt, and Geometry Registers to test if there are I/O 435 // ports that respond, and to check the values to determine if they are from a 436 // BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which 437 // case there is definitely no BusLogic Host Adapter at this base I/O Address. 438 // The test here is a subset of that used by the BusLogic Host Adapter BIOS. 439 440 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); 441 GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); 442 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 443 444 if (StatusRegister.All == 0 || 445 StatusRegister.Bits.DiagnosticActive || 446 StatusRegister.Bits.CommandParameterRegisterBusy || 447 StatusRegister.Bits.Reserved || 448 StatusRegister.Bits.CommandInvalid || 449 InterruptRegister.Bits.Reserved != 0) 450 return FALSE; 451 452 // Check the undocumented Geometry Register to test if there is an I/O port 453 // that responded. Adaptec Host Adapters do not implement the Geometry 454 // Register, so this test helps serve to avoid incorrectly recognizing an 455 // Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C 456 // series does respond to the Geometry Register I/O port, but it will be 457 // rejected later when the Inquire Extended Setup Information command is 458 // issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a 459 // BusLogic clone that implements the same interface as earlier BusLogic 460 // Host Adapters, including the undocumented commands, and is therefore 461 // supported by this driver. However, the AMI FastDisk always returns 0x00 462 // upon reading the Geometry Register, so the extended translation option 463 // should always be left disabled on the AMI FastDisk. 464 465 if (GeometryRegister.All == 0xFF) return FALSE; 466 return TRUE; 467 }// end BusLogic_ProbeHostAdapter 468 469 BOOLEAN 470 BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter, 471 BOOLEAN HardReset) 472 //_________________________________________________________________________ 473 // Routine Description: BusLogic_HardwareResetHostAdapter issues a Hardware 474 // Reset to the Host Adapter and waits for Host Adapter 475 // Diagnostics to complete. If HardReset is TRUE, a 476 // Hard Reset is performed which also initiates a SCSI 477 // Bus Reset. Otherwise, a Soft Reset is performed which 478 // only resets the Host Adapter without forcing a SCSI 479 // Bus Reset. 480 // Arguments: 481 // 1. Host Adapter structure 482 // 2. Boolean HardReset - True: Do hard reset 483 // Return Value: 484 // TRUE : Reset completed successfully 485 // FALSE : Reset failed 486 //_________________________________________________________________________ 487 { 488 BusLogic_StatusRegister_T StatusRegister; 489 int TimeoutCounter; 490 491 // Issue a Hard Reset or Soft Reset Command to the Host Adapter. The Host 492 // Adapter should respond by setting Diagnostic Active in the Status Register. 493 if (HardReset) 494 BusLogic_HardReset(HostAdapter); 495 else 496 BusLogic_SoftReset(HostAdapter); 497 498 // Wait until Diagnostic Active is set in the Status Register. 499 TimeoutCounter = 100; 500 while (--TimeoutCounter >= 0) 501 { 502 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 503 if (StatusRegister.Bits.DiagnosticActive) 504 break; 505 } 506 507 // if in spite of waiting for time out period , if it didn't et set, then something is wrong-- so just return. 508 if (TimeoutCounter < 0) 509 return FALSE; 510 511 // 512 // Wait 100 microseconds to allow completion of any initial diagnostic 513 // activity which might leave the contents of the Status Register 514 // unpredictable. 515 ScsiPortStallExecution(100); 516 517 // Wait until Diagnostic Active is reset in the Status Register. 518 TimeoutCounter = 10*10000; 519 while (--TimeoutCounter >= 0) 520 { 521 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 522 if (!StatusRegister.Bits.DiagnosticActive) 523 break; 524 ScsiPortStallExecution(100); 525 } 526 527 if (TimeoutCounter < 0) 528 return FALSE; 529 530 // Wait until at least one of the Diagnostic Failure, Host Adapter Ready, 531 // or Data In Register Ready bits is set in the Status Register. 532 TimeoutCounter = 10000; 533 while (--TimeoutCounter >= 0) 534 { 535 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 536 if (StatusRegister.Bits.DiagnosticFailure || 537 StatusRegister.Bits.HostAdapterReady || 538 StatusRegister.Bits.DataInRegisterReady) 539 { 540 break; 541 } 542 ScsiPortStallExecution(100); 543 } 544 545 //device didn't respond to reset 546 if (TimeoutCounter < 0) 547 return FALSE; 548 549 // If Diagnostic Failure is set or Host Adapter Ready is reset, then an 550 // error occurred during the Host Adapter diagnostics. If Data In Register 551 // Ready is set, then there is an Error Code available. 552 if (StatusRegister.Bits.DiagnosticFailure || !StatusRegister.Bits.HostAdapterReady) 553 { 554 DebugPrint((ERROR, "\n BusLogic - Failure - HOST ADAPTER STATUS REGISTER = %02X\n", StatusRegister.All)); 555 556 if (StatusRegister.Bits.DataInRegisterReady) 557 { 558 DebugPrint((ERROR, "HOST ADAPTER ERROR CODE = %d\n", BusLogic_ReadDataInRegister(HostAdapter))); 559 } 560 return FALSE; 561 } 562 563 // Indicate the Host Adapter Hard Reset completed successfully. 564 return TRUE; 565 }// end BusLogic_HardwareResetHostAdapter 566 567 568 BOOLEAN 569 BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter) 570 //_________________________________________________________________________ 571 // Routine Description: BusLogic_CheckHostAdapter checks to be sure this 572 // really is a BusLogic 573 // Arguments: 574 // 1. Host Adapter Structure 575 // Return Value: 576 // TRUE : Buslogic adapter detected 577 // FALSE : Card is not a Buslogic adapter 578 //_________________________________________________________________________ 579 { 580 BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; 581 BusLogic_RequestedReplyLength_T RequestedReplyLength; 582 BOOLEAN Result = TRUE; 583 584 DebugPrint((TRACE, "\n BusLogic - Inside BusLogic_CheckHostAdapter function \n")); 585 586 // 587 // Issue the Inquire Extended Setup Information command. Only genuine 588 // BusLogic Host Adapters and TRUE clones support this command. Adaptec 1542C 589 // series Host Adapters that respond to the Geometry Register I/O port will 590 // fail this command. 591 RequestedReplyLength = sizeof(ExtendedSetupInformation); 592 if (BusLogic_Command(HostAdapter, 593 BusLogic_InquireExtendedSetupInformation, 594 &RequestedReplyLength, 595 sizeof(RequestedReplyLength), 596 &ExtendedSetupInformation, 597 sizeof(ExtendedSetupInformation)) 598 != sizeof(ExtendedSetupInformation)) 599 { 600 Result = FALSE; 601 } 602 return Result; 603 }// end BusLogic_CheckHostAdapter 604 605 int 606 BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter, 607 BusLogic_OperationCode_T OperationCode, 608 void *ParameterData, 609 int ParameterLength, 610 void *ReplyData, 611 int ReplyLength) 612 //______________________________________________________________________________________________ 613 // Routine Description: 614 // BusLogic_Command sends the command OperationCode to HostAdapter, optionally 615 // providing ParameterLength bytes of ParameterData and receiving at most 616 // ReplyLength bytes of ReplyData; any excess reply data is received but 617 // discarded. 618 // 619 // BusLogic_Command is called exclusively during host adapter detection and 620 // initialization, so performance and latency are not critical, and exclusive 621 // access to the Host Adapter hardware is assumed. Once the host adapter and 622 // driver are initialized, the only Host Adapter command that is issued is the 623 // single byte Execute Mailbox Command operation code, which does not require 624 // waiting for the Host Adapter Ready bit to be set in the Status Register. 625 // Arguments: 626 // 1. HostAdapter - Host Adapter structure 627 // 2. OperationCode - Operation code for the command 628 // 3. ParameterData - Buffer containing parameters that needs to be passed as part 629 // of the command 630 // 4. ParameterLength - Number of parameters 631 // 5. ReplyData - Buffer where reply data is copied 632 // 6. ReplyLength - The length of the reply data 633 // Return Value: 634 // On success, this function returns the number of reply bytes read from 635 // the Host Adapter (including any discarded data); on failure, it returns 636 // -1 if the command was invalid, or -2 if a timeout occurred. 637 //_________________________________________________________________________________________________ 638 { 639 UCHAR *ParameterPointer = (UCHAR *) ParameterData; 640 UCHAR *ReplyPointer = (UCHAR *) ReplyData; 641 BusLogic_StatusRegister_T StatusRegister; 642 BusLogic_InterruptRegister_T InterruptRegister; 643 int ReplyBytes = 0, Result; 644 long TimeoutCounter; 645 646 // Clear out the Reply Data if provided. 647 if (ReplyLength > 0) 648 memset(ReplyData, 0, ReplyLength); 649 650 // If the IRQ Channel has not yet been acquired, then interrupts must be 651 // disabled while issuing host adapter commands since a Command Complete 652 // interrupt could occur if the IRQ Channel was previously enabled by another 653 // BusLogic Host Adapter or another driver sharing the same IRQ Channel. 654 655 // Wait for the Host Adapter Ready bit to be set and the Command/Parameter 656 // Register Busy bit to be reset in the Status Register. 657 TimeoutCounter = 10000; 658 while (--TimeoutCounter >= 0) 659 { 660 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 661 if ( StatusRegister.Bits.HostAdapterReady && 662 !StatusRegister.Bits.CommandParameterRegisterBusy) 663 { 664 break; 665 } 666 ScsiPortStallExecution(100); 667 } 668 if (TimeoutCounter < 0) 669 { 670 //BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready"; 671 Result = -2; 672 goto Done; 673 } 674 675 // Write the OperationCode to the Command/Parameter Register. 676 HostAdapter->HostAdapterCommandCompleted = FALSE; 677 BusLogic_WriteCommandParameterRegister(HostAdapter, (UCHAR)OperationCode); 678 679 //Write any additional Parameter Bytes. 680 TimeoutCounter = 10000; 681 while (ParameterLength > 0 && --TimeoutCounter >= 0) 682 { 683 // 684 // Wait 100 microseconds to give the Host Adapter enough time to determine 685 // whether the last value written to the Command/Parameter Register was 686 // valid or not. If the Command Complete bit is set in the Interrupt 687 // Register, then the Command Invalid bit in the Status Register will be 688 // reset if the Operation Code or Parameter was valid and the command 689 // has completed, or set if the Operation Code or Parameter was invalid. 690 // If the Data In Register Ready bit is set in the Status Register, then 691 // the Operation Code was valid, and data is waiting to be read back 692 // from the Host Adapter. Otherwise, wait for the Command/Parameter 693 // Register Busy bit in the Status Register to be reset. 694 695 ScsiPortStallExecution(100); 696 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); 697 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 698 if (InterruptRegister.Bits.CommandComplete) 699 break; 700 if (HostAdapter->HostAdapterCommandCompleted) 701 break; 702 if (StatusRegister.Bits.DataInRegisterReady) 703 break; 704 if (StatusRegister.Bits.CommandParameterRegisterBusy) 705 continue; 706 BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++); 707 ParameterLength--; 708 } 709 if (TimeoutCounter < 0) 710 { 711 //BusLogic_CommandFailureReason = "Timeout waiting for Parameter Acceptance"; 712 Result = -2; 713 goto Done; 714 } 715 716 // The Modify I/O Address command does not cause a Command Complete Interrupt. 717 if (OperationCode == BusLogic_ModifyIOAddress) 718 { 719 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 720 if (StatusRegister.Bits.CommandInvalid) 721 { 722 //BusLogic_CommandFailureReason = "Modify I/O Address Invalid"; 723 Result = -1; 724 goto Done; 725 } 726 Result = 0; 727 goto Done; 728 } 729 730 // Select an appropriate timeout value for awaiting command completion. 731 switch (OperationCode) 732 { 733 case BusLogic_InquireInstalledDevicesID0to7: 734 case BusLogic_InquireInstalledDevicesID8to15: 735 case BusLogic_InquireTargetDevices: 736 // Approximately 60 seconds. 737 TimeoutCounter = 60*10000; 738 break; 739 default: 740 // Approximately 1 second. 741 TimeoutCounter = 10000; 742 break; 743 } 744 745 // 746 // Receive any Reply Bytes, waiting for either the Command Complete bit to 747 // be set in the Interrupt Register, or for the Interrupt Handler to set the 748 // Host Adapter Command Completed bit in the Host Adapter structure. 749 while (--TimeoutCounter >= 0) 750 { 751 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); 752 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 753 if (InterruptRegister.Bits.CommandComplete) 754 break; 755 if (HostAdapter->HostAdapterCommandCompleted) 756 break; 757 if (StatusRegister.Bits.DataInRegisterReady) 758 { 759 if (++ReplyBytes <= ReplyLength) 760 { 761 *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter); 762 } 763 else 764 { 765 BusLogic_ReadDataInRegister(HostAdapter); 766 } 767 } 768 if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && 769 StatusRegister.Bits.HostAdapterReady) 770 { 771 break; 772 } 773 ScsiPortStallExecution(100); 774 } 775 if (TimeoutCounter < 0) 776 { 777 //BusLogic_CommandFailureReason = "Timeout waiting for Command Complete"; 778 Result = -2; 779 goto Done; 780 } 781 782 // Clear any pending Command Complete Interrupt. 783 BusLogic_InterruptReset(HostAdapter); 784 785 // Process Command Invalid conditions. 786 if (StatusRegister.Bits.CommandInvalid) 787 { 788 // 789 // Some early BusLogic Host Adapters may not recover properly from 790 // a Command Invalid condition, so if this appears to be the case, 791 // a Soft Reset is issued to the Host Adapter. Potentially invalid 792 // commands are never attempted after Mailbox Initialization is 793 // performed, so there should be no Host Adapter state lost by a 794 // Soft Reset in response to a Command Invalid condition. 795 796 ScsiPortStallExecution(1000); 797 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 798 if (StatusRegister.Bits.CommandInvalid || 799 StatusRegister.Bits.Reserved || 800 StatusRegister.Bits.DataInRegisterReady || 801 StatusRegister.Bits.CommandParameterRegisterBusy || 802 !StatusRegister.Bits.HostAdapterReady || 803 !StatusRegister.Bits.InitializationRequired || 804 StatusRegister.Bits.DiagnosticActive || 805 StatusRegister.Bits.DiagnosticFailure) 806 { 807 BusLogic_SoftReset(HostAdapter); 808 ScsiPortStallExecution(1000); 809 } 810 //BusLogic_CommandFailureReason = "Command Invalid"; 811 Result = -1; 812 goto Done; 813 } 814 815 // Handle Excess Parameters Supplied conditions. 816 if (ParameterLength > 0) 817 { 818 //BusLogic_CommandFailureReason = "Excess Parameters Supplied"; 819 Result = -1; 820 goto Done; 821 } 822 823 // Indicate the command completed successfully. 824 Result = ReplyBytes; 825 826 // Restore the interrupt status if necessary and return. 827 Done: 828 return Result; 829 }// end BusLogic_Command 830 831 832 BOOLEAN 833 BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T *HostAdapter) 834 //___________________________________________________________________________________________ 835 // Routine Description: 836 // BusLogic_ReadHostAdapterConfiguration reads the Configuration Information 837 // from Host Adapter and initializes the Host Adapter structure. 838 // Arguments: 839 // 1. Host adapter structure 840 // Return Value: 841 // TRUE : Configuration read properly 842 // FALSE : Encounter failure 843 //___________________________________________________________________________________________ 844 { 845 BusLogic_BoardID_T BoardID; 846 BusLogic_Configuration_T Configuration; 847 BusLogic_SetupInformation_T SetupInformation; 848 BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; 849 BusLogic_HostAdapterModelNumber_T HostAdapterModelNumber; 850 BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit; 851 BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter; 852 BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation; 853 BusLogic_FetchHostAdapterLocalRAMRequest_T FetchHostAdapterLocalRAMRequest; 854 BusLogic_AutoSCSIData_T AutoSCSIData; 855 BusLogic_GeometryRegister_T GeometryRegister; 856 BusLogic_RequestedReplyLength_T RequestedReplyLength; 857 UCHAR *TargetPointer, Character; 858 ULONG /*TargetID,*/ i; 859 860 861 // Issue the Inquire Board ID command. 862 if (BusLogic_Command(HostAdapter, 863 BusLogic_InquireBoardID, 864 NULL, 865 0, 866 &BoardID, sizeof(BoardID)) 867 != sizeof(BoardID)) 868 { 869 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE BOARD ID\n")); 870 return FALSE; 871 } 872 873 // Issue the Inquire Configuration command. 874 if (BusLogic_Command(HostAdapter, 875 BusLogic_InquireConfiguration, 876 NULL, 877 0, 878 &Configuration, sizeof(Configuration)) 879 != sizeof(Configuration)) 880 { 881 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE CONFIGURATION\n")); 882 return FALSE; 883 } 884 885 // Issue the Inquire Setup Information command. 886 RequestedReplyLength = sizeof(SetupInformation); 887 if (BusLogic_Command(HostAdapter, 888 BusLogic_InquireSetupInformation, 889 &RequestedReplyLength, 890 sizeof(RequestedReplyLength), 891 &SetupInformation, 892 sizeof(SetupInformation)) 893 != sizeof(SetupInformation)) 894 { 895 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE SETUP INFORMATION\n")); 896 return FALSE; 897 } 898 899 // Issue the Inquire Extended Setup Information command. 900 RequestedReplyLength = sizeof(ExtendedSetupInformation); 901 if (BusLogic_Command(HostAdapter, 902 BusLogic_InquireExtendedSetupInformation, 903 &RequestedReplyLength, 904 sizeof(RequestedReplyLength), 905 &ExtendedSetupInformation, 906 sizeof(ExtendedSetupInformation)) 907 != sizeof(ExtendedSetupInformation)) 908 { 909 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE EXTENDED SETUP INFORMATION\n")); 910 return FALSE; 911 } 912 913 // Issue the Inquire Firmware Version 3rd Digit command. 914 FirmwareVersion3rdDigit = '\0'; 915 if (BoardID.FirmwareVersion1stDigit > '0') 916 { 917 if (BusLogic_Command(HostAdapter, 918 BusLogic_InquireFirmwareVersion3rdDigit, 919 NULL, 920 0, 921 &FirmwareVersion3rdDigit, 922 sizeof(FirmwareVersion3rdDigit)) 923 != sizeof(FirmwareVersion3rdDigit)) 924 { 925 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE FIRMWARE 3RD DIGIT\n")); 926 return FALSE; 927 } 928 } 929 930 // Issue the Inquire Host Adapter Model Number command. 931 RequestedReplyLength = sizeof(HostAdapterModelNumber); 932 if (BusLogic_Command(HostAdapter, 933 BusLogic_InquireHostAdapterModelNumber, 934 &RequestedReplyLength, 935 sizeof(RequestedReplyLength), 936 &HostAdapterModelNumber, 937 sizeof(HostAdapterModelNumber)) 938 != sizeof(HostAdapterModelNumber)) 939 { 940 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE HOST ADAPTER MODEL NUMBER\n")); 941 return FALSE; 942 } 943 944 // BusLogic MultiMaster Host Adapters can be identified by their model number 945 // and the major version number of their firmware as follows: 946 // 947 // 5.xx BusLogic "W" Series Host Adapters: 948 // BT-948/958/958D 949 // Save the Model Name and Host Adapter Name in the Host Adapter structure. 950 TargetPointer = HostAdapter->ModelName; 951 *TargetPointer++ = 'B'; 952 *TargetPointer++ = 'T'; 953 *TargetPointer++ = '-'; 954 for (i = 0; i < sizeof(HostAdapterModelNumber); i++) 955 { 956 Character = HostAdapterModelNumber[i]; 957 if (Character == ' ' || Character == '\0') break; 958 *TargetPointer++ = Character; 959 } 960 *TargetPointer++ = '\0'; 961 962 // Save the Firmware Version in the Host Adapter structure. 963 TargetPointer = HostAdapter->FirmwareVersion; 964 *TargetPointer++ = BoardID.FirmwareVersion1stDigit; 965 *TargetPointer++ = '.'; 966 *TargetPointer++ = BoardID.FirmwareVersion2ndDigit; 967 if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0') 968 *TargetPointer++ = FirmwareVersion3rdDigit; 969 *TargetPointer = '\0'; 970 971 // Issue the Inquire Firmware Version Letter command. 972 if (strcmp((char*)HostAdapter->FirmwareVersion, "3.3") >= 0) 973 { 974 if (BusLogic_Command(HostAdapter, 975 BusLogic_InquireFirmwareVersionLetter, 976 NULL, 977 0, 978 &FirmwareVersionLetter, 979 sizeof(FirmwareVersionLetter)) 980 != sizeof(FirmwareVersionLetter)) 981 { 982 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE FIRMWARE VERSION LETTER\n")); 983 return FALSE; 984 } 985 if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0') 986 { 987 *TargetPointer++ = FirmwareVersionLetter; 988 } 989 *TargetPointer = '\0'; 990 } 991 992 993 // Save the Host Adapter SCSI ID in the Host Adapter structure. 994 HostAdapter->SCSI_ID = Configuration.HostAdapterID; 995 996 // Determine the Bus Type and save it in the Host Adapter structure, determine 997 // and save the IRQ Channel if necessary, and determine and save the DMA 998 // Channel for ISA Host Adapters. 999 HostAdapter->HostAdapterBusType = BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4']; 1000 1001 GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); 1002 1003 // Determine whether Extended Translation is enabled and save it in 1004 // the Host Adapter structure. 1005 // HostAdapter->ExtendedTranslationEnabled = GeometryRegister.Bits.ExtendedTranslationEnabled; 1006 HostAdapter->ExtendedTranslationEnabled = GeometryRegister.All; 1007 1008 1009 // Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide 1010 // SCSI flag, Differential SCSI flag, SCAM Supported flag, and 1011 // Ultra SCSI flag in the Host Adapter structure. 1012 HostAdapter->HostAdapterScatterGatherLimit = ExtendedSetupInformation.ScatterGatherLimit; 1013 1014 HostAdapter->DriverScatterGatherLimit = HostAdapter->HostAdapterScatterGatherLimit; 1015 1016 if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit) 1017 { 1018 HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; 1019 } 1020 if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt) 1021 { 1022 HostAdapter->LevelSensitiveInterrupt = TRUE; 1023 } 1024 1025 HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI; 1026 1027 HostAdapter->HostDifferentialSCSI = ExtendedSetupInformation.HostDifferentialSCSI; 1028 1029 HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM; 1030 1031 HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI; 1032 1033 1034 // Determine whether Extended LUN Format CCBs are supported and save the 1035 // information in the Host Adapter structure. 1036 if (HostAdapter->FirmwareVersion[0] == '5' || 1037 (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI)) 1038 { 1039 HostAdapter->ExtendedLUNSupport = TRUE; 1040 } 1041 // Issue the Inquire PCI Host Adapter Information command to read the 1042 // Termination Information from "W" series MultiMaster Host Adapters. 1043 if (HostAdapter->FirmwareVersion[0] == '5') 1044 { 1045 if (BusLogic_Command(HostAdapter, 1046 BusLogic_InquirePCIHostAdapterInformation, 1047 NULL, 1048 0, 1049 &PCIHostAdapterInformation, 1050 sizeof(PCIHostAdapterInformation)) 1051 != sizeof(PCIHostAdapterInformation)) 1052 { 1053 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE PCI HOST ADAPTER INFORMATION\n")); 1054 return FALSE; 1055 } 1056 1057 // Save the Termination Information in the Host Adapter structure. 1058 if (PCIHostAdapterInformation.GenericInfoValid) 1059 { 1060 HostAdapter->TerminationInfoValid = TRUE; 1061 HostAdapter->LowByteTerminated = PCIHostAdapterInformation.LowByteTerminated; 1062 HostAdapter->HighByteTerminated = PCIHostAdapterInformation.HighByteTerminated; 1063 } 1064 } 1065 1066 // Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data 1067 // from "W" and "C" series MultiMaster Host Adapters. 1068 if (HostAdapter->FirmwareVersion[0] >= '4') 1069 { 1070 FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset; 1071 FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData); 1072 if (BusLogic_Command(HostAdapter, 1073 BusLogic_FetchHostAdapterLocalRAM, 1074 &FetchHostAdapterLocalRAMRequest, 1075 sizeof(FetchHostAdapterLocalRAMRequest), 1076 &AutoSCSIData, 1077 sizeof(AutoSCSIData)) 1078 != sizeof(AutoSCSIData)) 1079 { 1080 DebugPrint((ERROR, "\n BusLogic - Failure: FETCH HOST ADAPTER LOCAL RAM\n")); 1081 return FALSE; 1082 } 1083 // Save the Parity Checking Enabled, Bus Reset Enabled, and Termination 1084 // Information in the Host Adapter structure. 1085 HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled; 1086 HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled; 1087 1088 // Save the Wide Permitted, Fast Permitted, Synchronous Permitted, 1089 // Disconnect Permitted, Ultra Permitted, and SCAM Information in the 1090 // Host Adapter structure. 1091 HostAdapter->WidePermitted = AutoSCSIData.WidePermitted; 1092 HostAdapter->FastPermitted = AutoSCSIData.FastPermitted; 1093 HostAdapter->SynchronousPermitted = AutoSCSIData.SynchronousPermitted; 1094 HostAdapter->DisconnectPermitted = AutoSCSIData.DisconnectPermitted; 1095 if (HostAdapter->HostUltraSCSI) 1096 { 1097 HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted; 1098 } 1099 if (HostAdapter->HostSupportsSCAM) 1100 { 1101 HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled; 1102 HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2; 1103 } 1104 } 1105 1106 // Determine the maximum number of Target IDs and Logical Units supported by 1107 // this driver for Wide and Narrow Host Adapters. 1108 HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); 1109 HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8); 1110 1111 // Select appropriate values for the Mailbox Count, 1112 // Initial CCBs, and Incremental CCBs variables based on whether or not Strict 1113 // Round Robin Mode is supported. If Strict Round Robin Mode is supported, 1114 // then there is no performance degradation in using the maximum possible 1115 // number of Outgoing and Incoming Mailboxes and allowing the Tagged and 1116 // Untagged Queue Depths to determine the actual utilization. If Strict Round 1117 // Robin Mode is not supported, then the Host Adapter must scan all the 1118 // Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can 1119 // cause a substantial performance penalty. The host adapters actually have 1120 // room to store the following number of CCBs internally; that is, they can 1121 // internally queue and manage this many active commands on the SCSI bus 1122 // simultaneously. Performance measurements demonstrate that the Driver Queue 1123 // Depth should be set to the Mailbox Count, rather than the Host Adapter 1124 // Queue Depth (internal CCB capacity), as it is more efficient to have the 1125 // queued commands waiting in Outgoing Mailboxes if necessary than to block 1126 // the process in the higher levels of the SCSI Subsystem. 1127 // 1128 // 192 BT-948/958/958D 1129 if (HostAdapter->FirmwareVersion[0] == '5') 1130 { 1131 HostAdapter->HostAdapterQueueDepth = 192; 1132 } 1133 1134 if (strcmp((char*)HostAdapter->FirmwareVersion, "3.31") >= 0) 1135 { 1136 HostAdapter->StrictRoundRobinModeSupport = TRUE; 1137 HostAdapter->MailboxCount = BusLogic_MaxMailboxes; 1138 } 1139 1140 // 1141 // Tagged Queuing support is available and operates properly on all "W" series 1142 // MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with 1143 // firmware version 4.22 and above, and on "S" series MultiMaster Host 1144 // Adapters with firmware version 3.35 and above. 1145 HostAdapter->TaggedQueuingPermitted = 0xFFFF; 1146 1147 // 1148 // Determine the Host Adapter BIOS Address if the BIOS is enabled and 1149 ///save it in the Host Adapter structure. The BIOS is disabled if the 1150 // BIOS_Address is 0. 1151 HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12; 1152 1153 // 1154 //Initialize parameters for MultiMaster Host Adapters. 1155 1156 // 1157 // Initialize the Host Adapter Full Model Name from the Model Name. 1158 strcpy((char*)HostAdapter->FullModelName, "BusLogic "); 1159 strcat((char*)HostAdapter->FullModelName, (char*)HostAdapter->ModelName); 1160 1161 // Tagged Queuing is only allowed if Disconnect/Reconnect is permitted. 1162 // Therefore, mask the Tagged Queuing Permitted Default bits with the 1163 // Disconnect/Reconnect Permitted bits. 1164 HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted; 1165 1166 // Select an appropriate value for Bus Settle Time either from a BusLogic 1167 // Driver Options specification, or from BusLogic_DefaultBusSettleTime. 1168 HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime; 1169 1170 // Indicate reading the Host Adapter Configuration completed successfully. 1171 return TRUE; 1172 }// end BusLogic_ReadHostAdapterConfiguration 1173 1174 BOOLEAN 1175 BusLogic_InitializeHostAdapter(PHW_DEVICE_EXTENSION deviceExtension, 1176 PPORT_CONFIGURATION_INFORMATION ConfigInfo) 1177 //_____________________________________________________________________________________________ 1178 // Routine Description: 1179 // BusLogic_InitializeHostAdapter initializes Host Adapter. This is the only 1180 // function called during SCSI Host Adapter detection which modifies the state 1181 // of the Host Adapter from its initial power on or hard reset state. 1182 // Arguments: 1183 // 1. device extension 1184 // 2. port config information 1185 // Return Value: 1186 // TRUE : Host Adapter initialization completed successfully 1187 // FALSE : Initialization failed 1188 //______________________________________________________________________________________________ 1189 { 1190 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 1191 BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest; 1192 UCHAR RoundRobinModeRequest; 1193 UCHAR SetCCBFormatRequest; 1194 int TargetID, LunID; 1195 1196 // Used when we get the Physical address of the mail boxes 1197 ULONG length; 1198 1199 // Initialize the pointers to the first and last CCBs that are queued for 1200 // completion processing. 1201 HostAdapter->FirstCompletedCCB = NULL; 1202 HostAdapter->LastCompletedCCB = NULL; 1203 1204 // Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active, 1205 // Command Successful Flag, Active Commands, and Commands Since Reset 1206 // for each Target Device. 1207 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) 1208 { 1209 HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; 1210 HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = FALSE; 1211 HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = FALSE; 1212 1213 HostAdapter->ActiveCommandsPerTarget[TargetID] = 0; 1214 for (LunID = 0; LunID < HostAdapter->MaxLogicalUnits; LunID++) 1215 HostAdapter->ActiveCommandsPerLun[TargetID][LunID] = 0; 1216 1217 HostAdapter->CommandsSinceReset[TargetID] = 0; 1218 } 1219 1220 // Convert virtual to physical mailbox address. 1221 deviceExtension->NoncachedExtension->MailboxPA = ScsiPortConvertPhysicalAddressToUlong( 1222 ScsiPortGetPhysicalAddress(deviceExtension, 1223 NULL, 1224 deviceExtension->NoncachedExtension->MailboxOut, 1225 &length)); 1226 1227 HostAdapter->FirstOutgoingMailbox = (BusLogic_OutgoingMailbox_T *) deviceExtension->NoncachedExtension->MailboxOut; 1228 HostAdapter->LastOutgoingMailbox = HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1; 1229 HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; 1230 1231 HostAdapter->FirstIncomingMailbox = (BusLogic_IncomingMailbox_T *) deviceExtension->NoncachedExtension->MailboxIn; 1232 HostAdapter->LastIncomingMailbox = HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1; 1233 HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; 1234 1235 // Initialize the Outgoing and Incoming Mailbox structures. 1236 memset(HostAdapter->FirstOutgoingMailbox, 1237 0, 1238 HostAdapter->MailboxCount * sizeof(BusLogic_OutgoingMailbox_T)); 1239 memset(HostAdapter->FirstIncomingMailbox, 1240 0, 1241 HostAdapter->MailboxCount * sizeof(BusLogic_IncomingMailbox_T)); 1242 1243 1244 ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount; 1245 ExtendedMailboxRequest.BaseMailboxAddress = deviceExtension->NoncachedExtension->MailboxPA ; 1246 1247 if (BusLogic_Command(HostAdapter, 1248 BusLogic_InitializeExtendedMailbox, 1249 &ExtendedMailboxRequest, 1250 sizeof(ExtendedMailboxRequest), 1251 NULL, 0) 1252 < 0) 1253 { 1254 DebugPrint((ERROR, "\n BusLogic - Failure: MAILBOX INITIALIZATION\n")); 1255 return FALSE; 1256 } 1257 1258 // Enable Strict Round Robin Mode if supported by the Host Adapter. In 1259 // Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing 1260 // Mailbox for each new command, rather than scanning through all the 1261 // Outgoing Mailboxes to find any that have new commands in them. Strict 1262 // Round Robin Mode is significantly more efficient. 1263 if (HostAdapter->StrictRoundRobinModeSupport) 1264 { 1265 RoundRobinModeRequest = BusLogic_StrictRoundRobinMode; 1266 if (BusLogic_Command(HostAdapter, 1267 BusLogic_EnableStrictRoundRobinMode, 1268 &RoundRobinModeRequest, 1269 sizeof(RoundRobinModeRequest), 1270 NULL, 1271 0) 1272 < 0) 1273 { 1274 DebugPrint((ERROR, "\n BusLogic - Failure: ENABLE STRICT ROUND ROBIN MODE\n")); 1275 return FALSE; 1276 } 1277 } 1278 1279 // For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB 1280 // Format command to allow 32 Logical Units per Target Device. 1281 1282 if (HostAdapter->ExtendedLUNSupport) 1283 { 1284 SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB; 1285 if (BusLogic_Command(HostAdapter, 1286 BusLogic_SetCCBFormat, 1287 &SetCCBFormatRequest, 1288 sizeof(SetCCBFormatRequest), 1289 NULL, 1290 0) 1291 < 0) 1292 { 1293 DebugPrint((ERROR, "\n BusLogic - Failure: SET CCB FORMAT\n")); 1294 return FALSE; 1295 } 1296 } 1297 1298 // Announce Successful Initialization. 1299 if (!HostAdapter->HostAdapterInitialized) 1300 { 1301 DebugPrint((INFO, "\n BusLogic - %s Initialized Successfully\n", 1302 HostAdapter, HostAdapter->FullModelName)); 1303 } 1304 else 1305 { 1306 DebugPrint((WARNING, "\n BusLogic - %s not initialized Successfully\n", 1307 HostAdapter, HostAdapter->FullModelName)); 1308 } 1309 HostAdapter->HostAdapterInitialized = TRUE; 1310 // Indicate the Host Adapter Initialization completed successfully. 1311 return TRUE; 1312 }// end BusLogic_InitializeHostAdapter 1313 1314 1315 BOOLEAN 1316 BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T *HostAdapter) 1317 //_________________________________________________________________________________________ 1318 // Routine Description: 1319 // BusLogic_TargetDeviceInquiry inquires about the Target Devices accessible 1320 // through Host Adapter. 1321 // Arguments: 1322 // 1. Host Adapter structure 1323 // 2. 1324 // Return Value: 1325 // TRUE : Inquiry successful 1326 // FALSE : Inquiry failed 1327 //_________________________________________________________________________ 1328 { 1329 BusLogic_InstalledDevices_T InstalledDevices; 1330 // BusLogic_InstalledDevices8_T InstalledDevicesID0to7; 1331 BusLogic_SetupInformation_T SetupInformation; 1332 BusLogic_SynchronousPeriod_T SynchronousPeriod; 1333 BusLogic_RequestedReplyLength_T RequestedReplyLength; 1334 int TargetID; 1335 1336 // Wait a few seconds between the Host Adapter Hard Reset which initiates 1337 // a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get 1338 // confused if they receive SCSI Commands too soon after a SCSI Bus Reset. 1339 ScsiPortStallExecution(HostAdapter->BusSettleTime); 1340 1341 // 1342 // Issue the Inquire Target Devices command for host adapters with firmware 1343 // version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command 1344 // for older host adapters. This is necessary to force Synchronous Transfer 1345 // Negotiation so that the Inquire Setup Information and Inquire Synchronous 1346 // Period commands will return valid data. The Inquire Target Devices command 1347 // is preferable to Inquire Installed Devices ID 0 to 7 since it only probes 1348 // Logical Unit 0 of each Target Device. 1349 if (strcmp((char*)HostAdapter->FirmwareVersion, "4.25") >= 0) 1350 { 1351 if (BusLogic_Command(HostAdapter, 1352 BusLogic_InquireTargetDevices, 1353 NULL, 1354 0, 1355 &InstalledDevices, 1356 sizeof(InstalledDevices)) 1357 != sizeof(InstalledDevices)) 1358 { 1359 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE TARGET DEVICES\n")); 1360 return FALSE; 1361 } 1362 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) 1363 { 1364 HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevices & (1 << TargetID) ? TRUE : FALSE); 1365 } 1366 } 1367 1368 // Issue the Inquire Setup Information command. 1369 RequestedReplyLength = sizeof(SetupInformation); 1370 if (BusLogic_Command(HostAdapter, 1371 BusLogic_InquireSetupInformation, 1372 &RequestedReplyLength, 1373 sizeof(RequestedReplyLength), 1374 &SetupInformation, sizeof(SetupInformation)) 1375 != sizeof(SetupInformation)) 1376 { 1377 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE SETUP INFORMATION\n")); 1378 return FALSE; 1379 } 1380 1381 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) 1382 { 1383 HostAdapter->SynchronousOffset[TargetID] = (TargetID < 8 1384 ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset 1385 : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset); 1386 } 1387 if (strcmp((char*)HostAdapter->FirmwareVersion, "5.06L") >= 0) 1388 { 1389 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) 1390 { 1391 HostAdapter->TargetFlags[TargetID].WideTransfersActive = (TargetID < 8 1392 ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID) 1393 ? TRUE : FALSE) 1394 : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8)) 1395 ? TRUE : FALSE)); 1396 } 1397 } 1398 1399 1400 // Issue the Inquire Synchronous Period command. 1401 if (HostAdapter->FirmwareVersion[0] >= '3') 1402 { 1403 RequestedReplyLength = sizeof(SynchronousPeriod); 1404 if (BusLogic_Command(HostAdapter, 1405 BusLogic_InquireSynchronousPeriod, 1406 &RequestedReplyLength, 1407 sizeof(RequestedReplyLength), 1408 &SynchronousPeriod, 1409 sizeof(SynchronousPeriod)) 1410 != sizeof(SynchronousPeriod)) 1411 { 1412 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE SYNCHRONOUS PERIOD\n")); 1413 return FALSE; 1414 } 1415 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) 1416 { 1417 HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID]; 1418 } 1419 } 1420 1421 // Indicate the Target Device Inquiry completed successfully. 1422 return TRUE; 1423 }// end BusLogic_TargetDeviceInquiry 1424 1425 VOID BusLogic_InitializeCCB( PBuslogic_CCB_T CCB) 1426 { 1427 CCB->Opcode = BusLogic_InitiatorCCB; 1428 CCB->DataDirection = 0; 1429 CCB->TagEnable = 0; 1430 CCB->QueueTag = 0 ; 1431 CCB->CDB_Length = 0; 1432 CCB->SenseDataLength = 0; 1433 CCB->DataLength = 0; 1434 CCB->DataPointer = 0; 1435 CCB->HostAdapterStatus = 0; 1436 CCB->TargetDeviceStatus = 0; 1437 CCB->TargetID = 0; 1438 CCB->LogicalUnit = 0; 1439 CCB->LegacyTagEnable = 0; 1440 CCB->LegacyQueueTag = 0; 1441 1442 CCB->SenseDataPointer = 0; 1443 1444 // BusLogic Driver Defined Portion 1445 CCB->Status = 0; 1446 CCB->SerialNumber = 0; 1447 CCB->Next = NULL; 1448 CCB->HostAdapter = NULL; 1449 1450 CCB->CompletionCode = 0; 1451 // Pointer to the CCB 1452 CCB->SrbAddress = NULL; 1453 CCB->AbortSrb = NULL; 1454 } 1455 1456 BOOLEAN 1457 NTAPI 1458 BT958HwStartIO(IN PVOID HwDeviceExtension, 1459 IN PSCSI_REQUEST_BLOCK Srb 1460 ) 1461 //__________________________________________________________________________________ 1462 // Routine Description: 1463 // As soon as it receives the initial request for a 1464 // target peripheral, the OS-specific port driver calls 1465 // the HwScsiStartIo routine with an input SRB. After 1466 // this call, the HBA miniport driver owns the request 1467 // and is expected to complete it. 1468 // Arguments: 1469 // 1. DeviceExtension: Points to the miniport driver's per-HBA storage area. 1470 // 2. Srb: Points to the SCSI request block to be started. 1471 // Return Value: 1472 // TRUE : HwScsiStartIo returns TRUE to acknowledge receipt of the SRB. 1473 //__________________________________________________________________________________ 1474 { 1475 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 1476 // PNONCACHED_EXTENSION noncachedExtension = deviceExtension->NoncachedExtension; 1477 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 1478 // BusLogic_OutgoingMailbox_T mailboxOut; 1479 PSCSI_REQUEST_BLOCK AbortSRB; 1480 1481 PBuslogic_CCB_T ccb; 1482 BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[Srb->TargetId]; 1483 1484 1485 DebugPrint((TRACE, "\n BusLogic - Inside Start IO routine\n")); 1486 1487 // Make sure that this request isn't too long for the adapter. If so 1488 // bounce it back as an invalid request 1489 if (BusLogic_CDB_MaxLength < Srb->CdbLength) 1490 { 1491 1492 DebugPrint((WARNING, "\n BusLogic - Srb->CdbLength [%d] > MaxCdbLength [%d]." 1493 " Invalid request\n", Srb->CdbLength, BusLogic_CDB_MaxLength)); 1494 1495 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; 1496 ScsiPortNotification(RequestComplete,deviceExtension,Srb); 1497 ScsiPortNotification(NextRequest,deviceExtension,NULL); 1498 return TRUE; 1499 } 1500 1501 switch (Srb->Function) 1502 { 1503 /* 1504 Sirish, 10th June 2002 1505 // Check if command is a WMI request. 1506 case SRB_FUNCTION_WMI: 1507 // Process the WMI request and return. 1508 return BT958WmiSrb(HwDeviceExtension, (PSCSI_WMI_REQUEST_BLOCK) Srb); 1509 */ 1510 1511 case SRB_FUNCTION_EXECUTE_SCSI: 1512 1513 // get the ccb structure from the extension 1514 ccb = Srb->SrbExtension; 1515 BusLogic_InitializeCCB(ccb); 1516 1517 // Save SRB back pointer in CCB. 1518 ccb->SrbAddress = Srb; 1519 1520 // Build CCB. - Have some way of knowing that a srb has already been 1521 // completed and you just need to return from here 1522 BusLogic_QueueCommand(HwDeviceExtension ,Srb, ccb); 1523 1524 // Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI 1525 // Subsystem should not attempt to queue more commands than can be placed 1526 // in Outgoing Mailboxes, so there should always be one free. In the 1527 // unlikely event that there are none available, wait 1 second and try 1528 // again. If that fails, the Host Adapter is probably hung so signal an 1529 // error as a Host Adapter Hard Reset should be initiated soon. 1530 1531 if (!BusLogic_WriteOutgoingMailbox(deviceExtension , BusLogic_MailboxStartCommand, ccb)) 1532 { 1533 DebugPrint((ERROR, "\n BusLogic - Unable to write Outgoing Mailbox - " 1534 "Pausing for 1 second\n")); 1535 ScsiPortStallExecution(1000); 1536 if (!BusLogic_WriteOutgoingMailbox(deviceExtension , BusLogic_MailboxStartCommand, ccb)) 1537 { 1538 DebugPrint((ERROR, "\n BusLogic - Still unable to write Outgoing" 1539 "Mailbox - Host Adapter Dead?\n")); 1540 1541 Srb->SrbStatus = SRB_STATUS_ERROR; 1542 ScsiPortNotification(RequestComplete,deviceExtension,Srb); 1543 ScsiPortNotification(NextRequest,deviceExtension,NULL); 1544 1545 } 1546 } 1547 else 1548 { 1549 /* 1550 * Reverted to pre 1.1.0.0 control flow 1551 * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts 1552 * And the fix for that in 1.1.0.1 causes BSODs in XP 1553 * Side note: Ben: the Buslogic emulation never exports more than 1 lun 1554 */ 1555 if (TargetFlags->TaggedQueuingActive 1556 && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS) { 1557 ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); 1558 } 1559 else { 1560 ScsiPortNotification(NextRequest,deviceExtension,NULL); 1561 } 1562 } 1563 return TRUE; 1564 1565 case SRB_FUNCTION_ABORT_COMMAND: 1566 1567 // Get CCB to abort. 1568 ccb = Srb->NextSrb->SrbExtension; 1569 1570 // Set abort SRB for completion. 1571 ccb->AbortSrb = Srb; 1572 1573 AbortSRB = ScsiPortGetSrb(HwDeviceExtension, 1574 Srb->PathId, 1575 Srb->TargetId, 1576 Srb->Lun, 1577 Srb->QueueTag); 1578 1579 if ((AbortSRB != Srb->NextSrb) || (AbortSRB->SrbStatus != SRB_STATUS_PENDING)) 1580 { 1581 Srb->SrbStatus = SRB_STATUS_ABORT_FAILED; 1582 ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb); 1583 ScsiPortNotification(NextRequest, HwDeviceExtension, NULL); 1584 return TRUE; 1585 } 1586 1587 // write the abort information into a mailbox 1588 if (BusLogic_WriteOutgoingMailbox( deviceExtension, BusLogic_MailboxAbortCommand, ccb)) 1589 { 1590 DebugPrint((WARNING, "\n BusLogic - Aborting CCB #%ld to Target %d\n", 1591 ccb->SerialNumber, Srb->TargetId)); 1592 // Adapter ready for next request. 1593 1594 /* 1595 * Reverted to pre 1.1.0.0 control flow 1596 * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts 1597 * And the fix for that in 1.1.0.1 causes BSODs in XP 1598 * Side note: Ben: the Buslogic emulation never exports more than 1 lun 1599 */ 1600 if (TargetFlags->TaggedQueuingActive 1601 && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS) { 1602 ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); 1603 } 1604 else { 1605 ScsiPortNotification(NextRequest,deviceExtension,NULL); 1606 } 1607 } 1608 else 1609 { 1610 DebugPrint((WARNING, "\n BusLogic - Unable to Abort CCB #%ld to Target %d" 1611 " - No Outgoing Mailboxes\n", ccb->SerialNumber, 1612 Srb->TargetId)); 1613 Srb->SrbStatus = SRB_STATUS_ERROR; 1614 ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb); 1615 ScsiPortNotification(NextRequest, HwDeviceExtension, NULL); 1616 } 1617 return TRUE; 1618 1619 1620 case SRB_FUNCTION_RESET_BUS: 1621 1622 // Reset SCSI bus. 1623 DebugPrint((INFO, "\n BusLogic - SRB_FUNCTION_RESET_BUS, srb=%x \n",Srb)); 1624 BT958HwResetBus(HwDeviceExtension, Srb->PathId); 1625 1626 Srb->SrbStatus = SRB_STATUS_SUCCESS; 1627 ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb); 1628 ScsiPortNotification(NextRequest, HwDeviceExtension, NULL); 1629 return TRUE; 1630 1631 1632 case SRB_FUNCTION_RESET_DEVICE: 1633 1634 ccb = Srb->SrbExtension; 1635 BusLogic_InitializeCCB(ccb); 1636 1637 // Save SRB back pointer in CCB. 1638 ccb->SrbAddress = Srb; 1639 1640 if(!BusLogic_SendBusDeviceReset(HostAdapter, Srb)) 1641 { 1642 BT958HwResetBus(HwDeviceExtension, SP_UNTAGGED); 1643 Srb->SrbStatus = SRB_STATUS_SUCCESS; 1644 ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb); 1645 ScsiPortNotification(NextRequest, HwDeviceExtension, NULL); 1646 return TRUE; 1647 } 1648 1649 /* 1650 * Reverted to pre 1.1.0.0 control flow 1651 * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts 1652 * And the fix for that in 1.1.0.1 causes BSODs in XP 1653 * Side note: Ben: the Buslogic emulation never exports more than 1 lun 1654 */ 1655 if (TargetFlags->TaggedQueuingActive 1656 && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS) { 1657 ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); 1658 } 1659 else { 1660 ScsiPortNotification(NextRequest,deviceExtension,NULL); 1661 } 1662 return TRUE; 1663 1664 default: 1665 1666 // Set error, complete request and signal ready for next request. 1667 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; 1668 ScsiPortNotification(RequestComplete,deviceExtension,Srb); 1669 ScsiPortNotification(NextRequest,deviceExtension,NULL); 1670 1671 return TRUE; 1672 1673 } // end switch 1674 1675 }// end BusLogic_TargetDeviceInquiry 1676 1677 1678 BOOLEAN 1679 BusLogic_WriteOutgoingMailbox(PHW_DEVICE_EXTENSION deviceExtension , 1680 BusLogic_ActionCode_T ActionCode, 1681 BusLogic_CCB_T *CCB) 1682 //______________________________________________________________________________________________ 1683 // Routine Description: 1684 // BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing 1685 // Mailbox for execution by Host Adapter. The Host Adapter's Lock should 1686 // already have been acquired by the caller. 1687 1688 // Arguments: 1689 // 1. deviceExtension: device extension 1690 // 2. ActionCode : action code for the mailbox which can be 1691 // BusLogic_OutgoingMailboxFree = 0x00, 1692 // BusLogic_MailboxStartCommand = 0x01, 1693 // BusLogic_MailboxAbortCommand = 0x02 1694 // 3. CCB :The CCB that has to be written into the mailbox 1695 // Return Value: 1696 // TRUE : write to the mailbox was successful 1697 // FALSE : write failed 1698 //______________________________________________________________________________________________ 1699 { 1700 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 1701 BusLogic_OutgoingMailbox_T *NextOutgoingMailbox; 1702 ULONG length; 1703 1704 NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox; 1705 1706 if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) 1707 { 1708 CCB->Status = BusLogic_CCB_Active; 1709 1710 // The CCB field must be written before the Action Code field since 1711 // the Host Adapter is operating asynchronously and the locking code 1712 // does not protect against simultaneous access by the Host Adapter. 1713 1714 // Get CCB physical address. 1715 NextOutgoingMailbox->CCB = ScsiPortConvertPhysicalAddressToUlong( ScsiPortGetPhysicalAddress(deviceExtension, 1716 NULL, 1717 CCB, 1718 &length)); 1719 1720 NextOutgoingMailbox->ActionCode = (UCHAR)ActionCode; 1721 1722 BusLogic_StartMailboxCommand(HostAdapter); 1723 1724 if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox) 1725 { 1726 NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; 1727 } 1728 1729 HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox; 1730 if (ActionCode == BusLogic_MailboxStartCommand) 1731 { 1732 HostAdapter->ActiveCommandsPerTarget[CCB->TargetID]++; 1733 // check this Namita 1734 HostAdapter->ActiveCommandsPerLun[CCB->TargetID][CCB->LogicalUnit]++; 1735 if (CCB->Opcode != BusLogic_BusDeviceReset) 1736 { 1737 HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++; 1738 } 1739 } 1740 return TRUE; 1741 } 1742 return FALSE; 1743 }// end BusLogic_WriteOutgoingMailbox 1744 1745 1746 int 1747 BusLogic_QueueCommand(IN PVOID HwDeviceExtension , 1748 IN PSCSI_REQUEST_BLOCK Srb, 1749 PBuslogic_CCB_T CCB) 1750 //_________________________________________________________________________ 1751 // Routine Description: 1752 // BusLogic_QueueCommand creates a CCB for Command 1753 // Arguments: 1754 // 1. HwDeviceExtension: device extension 1755 // 2. Srb: Pointe to the SRB 1756 // 3. CCB: POinter to the buffer containing the space for CCB 1757 // Return Value: 1758 // Function returns 0 if successful 1759 //_________________________________________________________________________ 1760 { 1761 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 1762 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 1763 BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[Srb->TargetId]; 1764 BusLogic_TargetStatistics_T *TargetStatistics = HostAdapter->TargetStatistics; 1765 1766 ULONG length; 1767 1768 // UCHAR *Cdb = Srb->Cdb; 1769 // PCDB RealCdb ; 1770 UCHAR CDB_Length = Srb->CdbLength; 1771 UCHAR TargetID = Srb->TargetId; 1772 UCHAR LogicalUnit = Srb->Lun; 1773 // void *BufferPointer = Srb->DataBuffer; 1774 int BufferLength = Srb->DataTransferLength; 1775 1776 if (Srb->DataTransferLength > 0) 1777 { 1778 CCB->DataLength = Srb->DataTransferLength; 1779 1780 // Initialize the fields in the BusLogic Command Control Block (CCB). 1781 #if SG_SUPPORT 1782 { 1783 ULONG xferLength, remainLength; 1784 PVOID virtualAddress; 1785 UCHAR i = 0; 1786 1787 virtualAddress = Srb->DataBuffer; 1788 xferLength = Srb->DataTransferLength; 1789 remainLength = xferLength; 1790 /* Build scatter gather list */ 1791 do 1792 { 1793 CCB->ScatterGatherList[i].SegmentDataPointer = (ULONG)ScsiPortConvertPhysicalAddressToUlong( 1794 ScsiPortGetPhysicalAddress(HwDeviceExtension, 1795 Srb, 1796 virtualAddress, 1797 &length)); 1798 if ( length > remainLength ) 1799 length = remainLength; 1800 CCB->ScatterGatherList[i].SegmentByteCount = length; 1801 1802 virtualAddress = (PUCHAR) virtualAddress + length; 1803 if (length >= remainLength) 1804 remainLength = 0; 1805 else 1806 remainLength -= length; 1807 i++; 1808 } while ( remainLength > 0); 1809 1810 // For data transfers that have less than one scatter gather element, convert 1811 // CCB to one transfer without using SG element. This will clear up the data 1812 // overrun/underrun problem with small transfers that reak havoc with scanners 1813 // and CD-ROM's etc. This is the method employed in ASPI4DOS to avoid similar 1814 // problems. 1815 if (i > 1) 1816 { 1817 CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather; 1818 CCB->DataLength = i * sizeof(BusLogic_ScatterGatherSegment_T); 1819 virtualAddress = (PVOID) & (CCB->ScatterGatherList); 1820 CCB->DataPointer = ScsiPortConvertPhysicalAddressToUlong( 1821 ScsiPortGetPhysicalAddress(HwDeviceExtension, 1822 0, 1823 (PVOID)virtualAddress, 1824 &length)); 1825 } 1826 else /* Turn off SG */ 1827 { 1828 CCB->Opcode = BusLogic_InitiatorCCB; 1829 CCB->DataLength = CCB->ScatterGatherList[0].SegmentByteCount; 1830 CCB->DataPointer = CCB->ScatterGatherList[0].SegmentDataPointer; 1831 1832 } 1833 } 1834 #else 1835 CCB->Opcode = BusLogic_InitiatorCCB; 1836 CCB->DataLength = BufferLength; 1837 CCB->DataPointer = ScsiPortConvertPhysicalAddressToUlong(ScsiPortGetPhysicalAddress(deviceExtension, 1838 Srb, 1839 BufferPointer, 1840 &length)); 1841 #endif 1842 } 1843 1844 switch (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) 1845 { 1846 case SRB_FLAGS_NO_DATA_TRANSFER: 1847 CCB->DataDirection = BusLogic_NoDataTransfer; 1848 break; 1849 1850 case SRB_FLAGS_DATA_IN: 1851 CCB->DataDirection = BusLogic_DataInLengthChecked; 1852 TargetStatistics[TargetID].ReadCommands++; 1853 BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesRead, 1854 BufferLength); 1855 BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].ReadCommandSizeBuckets, 1856 BufferLength); 1857 break; 1858 1859 case SRB_FLAGS_DATA_OUT: 1860 CCB->DataDirection = BusLogic_DataOutLengthChecked; 1861 TargetStatistics[TargetID].WriteCommands++; 1862 BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesWritten, 1863 BufferLength); 1864 BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].WriteCommandSizeBuckets, 1865 BufferLength); 1866 1867 break; 1868 1869 case SRB_FLAGS_UNSPECIFIED_DIRECTION: /* let device decide direction */ 1870 default: 1871 CCB->DataDirection = BusLogic_UncheckedDataTransfer; 1872 break; 1873 } 1874 1875 1876 CCB->CDB_Length = CDB_Length; 1877 CCB->SenseDataLength = Srb->SenseInfoBufferLength; 1878 CCB->HostAdapterStatus = 0; 1879 CCB->TargetDeviceStatus = 0; 1880 CCB->TargetID = TargetID; 1881 CCB->LogicalUnit = LogicalUnit; 1882 CCB->TagEnable = FALSE; 1883 CCB->LegacyTagEnable = FALSE; 1884 1885 // BusLogic recommends that after a Reset the first couple of commands that 1886 // are sent to a Target Device be sent in a non Tagged Queue fashion so that 1887 // the Host Adapter and Target Device can establish Synchronous and Wide 1888 // Transfer before Queue Tag messages can interfere with the Synchronous and 1889 // Wide Negotiation messages. By waiting to enable Tagged Queuing until after 1890 // the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is 1891 // assured that after a Reset any pending commands are requeued before Tagged 1892 // Queuing is enabled and that the Tagged Queuing message will not occur while 1893 // the partition table is being printed. In addition, some devices do not 1894 // properly handle the transition from non-tagged to tagged commands, so it is 1895 // necessary to wait until there are no pending commands for a target device 1896 // before queuing tagged commands. 1897 1898 if (HostAdapter->CommandsSinceReset[TargetID]++ >= BusLogic_MaxTaggedQueueDepth && 1899 HostAdapter->ActiveCommandsPerTarget[TargetID] == 0 && 1900 !TargetFlags->TaggedQueuingActive && 1901 TargetFlags->TaggedQueuingSupported && 1902 (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) 1903 { 1904 TargetFlags->TaggedQueuingActive = TRUE; 1905 DebugPrint((INFO, "\n BusLogic - Tagged Queuing now active for Target %d\n", 1906 TargetID)); 1907 } 1908 if (TargetFlags->TaggedQueuingActive) 1909 { 1910 BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag; 1911 1912 // When using Tagged Queuing with Simple Queue Tags, it appears that disk 1913 // drive controllers do not guarantee that a queued command will not 1914 // remain in a disconnected state indefinitely if commands that read or 1915 // write nearer the head position continue to arrive without interruption. 1916 // Therefore, for each Target Device this driver keeps track of the last 1917 // time either the queue was empty or an Ordered Queue Tag was issued. If 1918 // more than 4 seconds (one fifth of the 20 second disk timeout) have 1919 // elapsed since this last sequence point, this command will be issued 1920 // with an Ordered Queue Tag rather than a Simple Queue Tag, which forces 1921 // the Target Device to complete all previously queued commands before 1922 // this command may be executed. 1923 /* 1924 if (HostAdapter->ActiveCommandsPerTarget[TargetID] == 0) 1925 HostAdapter->LastSequencePoint[TargetID] = jiffies; 1926 else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ) 1927 { 1928 HostAdapter->LastSequencePoint[TargetID] = jiffies; 1929 QueueTag = BusLogic_OrderedQueueTag; 1930 } 1931 */ 1932 if (HostAdapter->ExtendedLUNSupport) 1933 { 1934 CCB->TagEnable = TRUE; 1935 CCB->QueueTag = (UCHAR)QueueTag; 1936 } 1937 else 1938 { 1939 CCB->LegacyTagEnable = TRUE; 1940 CCB->LegacyQueueTag = (UCHAR)QueueTag; 1941 } 1942 } 1943 1944 ScsiPortMoveMemory(CCB->CDB, Srb->Cdb, CDB_Length); 1945 1946 //Fix for the XP Port driver - shuts of auto sense at times. 22nd May 2002 1947 //{sirish, shobhit}@calsoftinc.com 1948 if ((Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) || 1949 (Srb->SenseInfoBufferLength <= 0)) { 1950 1951 //Disable auto request sense 1952 CCB->SenseDataLength = BusLogic_DisableAutoReqSense; 1953 } else { 1954 //Enable auto request sense 1955 CCB->SenseDataLength = (unsigned char) Srb->SenseInfoBufferLength; 1956 1957 //Sense Buffer physical addr 1958 CCB->SenseDataPointer = ScsiPortConvertPhysicalAddressToUlong(ScsiPortGetPhysicalAddress(HwDeviceExtension, 1959 Srb, 1960 Srb->SenseInfoBuffer, 1961 &length)); 1962 if (Srb->SenseInfoBufferLength > length ) { 1963 CCB->SenseDataLength = (unsigned char) length; 1964 } 1965 } 1966 1967 return 0; 1968 }// end BusLogic_QueueCommand 1969 1970 1971 BOOLEAN 1972 NTAPI 1973 BT958HwInterrupt(IN PVOID HwDeviceExtension) 1974 //_________________________________________________________________________ 1975 // Routine Description: 1976 // HwScsiInterrupt is called when the HBA generates an 1977 // interrupt. Miniport drivers of HBAs that do not 1978 // generate interrupts do not have this routine. 1979 // HwScsiInterrupt is responsible for completing 1980 // interrupt-driven I/O operations. This routine must 1981 // clear the interrupt on the HBA before it returns TRUE. 1982 // Arguments: 1983 // 1. HwDeviceExtension: Points to the miniport driver's per-HBA storage area. 1984 // Return Value: 1985 // TRUE : Acknowledged the interrupts on the HBA 1986 // FALSE: If the miniport finds that its HBA did not generate 1987 // the interrupt, HwScsiInterrupt should return FALSE 1988 // as soon as possible. 1989 //_________________________________________________________________________ 1990 { 1991 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 1992 // PNONCACHED_EXTENSION noncachedExtension = deviceExtension->NoncachedExtension; 1993 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 1994 // PBuslogic_CCB_T ccb; 1995 // PSCSI_REQUEST_BLOCK srb; 1996 1997 // ULONG residualBytes; 1998 // ULONG i; 1999 2000 BusLogic_InterruptRegister_T InterruptRegister; 2001 2002 2003 // Read the Host Adapter Interrupt Register. 2004 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); 2005 if (InterruptRegister.Bits.InterruptValid) 2006 { 2007 2008 // Acknowledge the interrupt and reset the Host Adapter 2009 // Interrupt Register. 2010 BusLogic_InterruptReset(HostAdapter); 2011 // Process valid External SCSI Bus Reset and Incoming Mailbox 2012 // Loaded Interrupts. Command Complete Interrupts are noted, 2013 // and Outgoing Mailbox Available Interrupts are ignored, as 2014 // they are never enabled. 2015 if (InterruptRegister.Bits.ExternalBusReset) 2016 { 2017 HostAdapter->HostAdapterExternalReset = TRUE; 2018 } 2019 else if (InterruptRegister.Bits.IncomingMailboxLoaded) 2020 { 2021 BusLogic_ScanIncomingMailboxes(deviceExtension); 2022 } 2023 else if (InterruptRegister.Bits.CommandComplete) 2024 { 2025 HostAdapter->HostAdapterCommandCompleted = TRUE; 2026 } 2027 } 2028 else 2029 return FALSE; 2030 2031 // Process any completed CCBs. 2032 if (HostAdapter->FirstCompletedCCB != NULL) 2033 BusLogic_ProcessCompletedCCBs(deviceExtension); 2034 2035 // Reset the Host Adapter if requested. 2036 if (HostAdapter->HostAdapterExternalReset || 2037 HostAdapter->HostAdapterInternalError) 2038 { 2039 // I have replaced the NULL with srb->pathid check if this is correct 2040 BT958HwResetBus(HwDeviceExtension, SP_UNTAGGED); 2041 HostAdapter->HostAdapterExternalReset = FALSE; 2042 HostAdapter->HostAdapterInternalError = FALSE; 2043 } 2044 return TRUE; 2045 }// end BT958HwInterrupt 2046 2047 void 2048 BusLogic_ScanIncomingMailboxes(PHW_DEVICE_EXTENSION deviceExtension) 2049 //________________________________________________________________________________________ 2050 // Routine Description: 2051 // BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any 2052 // Incoming Mailbox entries for completion processing. 2053 // Arguments: 2054 // 1. deviceExtension : pointer to the device extension 2055 //_________________________________________________________________________________________ 2056 { 2057 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 2058 2059 2060 // Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving 2061 // any completed CCBs for further processing. It is essential that for each 2062 // CCB and SCSI Command issued, command completion processing is performed 2063 // exactly once. Therefore, only Incoming Mailboxes with completion code 2064 // Command Completed Without Error, Command Completed With Error, or Command 2065 // Aborted At Host Request are saved for completion processing. When an 2066 // Incoming Mailbox has a completion code of Aborted Command Not Found, the 2067 // CCB had already completed or been aborted before the current Abort request 2068 // was processed, and so completion processing has already occurred and no 2069 // further action should be taken. 2070 BusLogic_IncomingMailbox_T *NextIncomingMailbox = HostAdapter->NextIncomingMailbox; 2071 BusLogic_CompletionCode_T CompletionCode; 2072 2073 while ((CompletionCode = NextIncomingMailbox->CompletionCode) != BusLogic_IncomingMailboxFree) 2074 { 2075 // Convert Physical CCB to Virtual. 2076 BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) ScsiPortGetVirtualAddress(deviceExtension, 2077 ScsiPortConvertUlongToPhysicalAddress(NextIncomingMailbox->CCB)); 2078 2079 DebugPrint((INFO, "\n Buslogic - Virtual CCB %lx\n", CCB)); 2080 if (CompletionCode != BusLogic_AbortedCommandNotFound) 2081 { 2082 if (CCB->Status == BusLogic_CCB_Active || CCB->Status == BusLogic_CCB_Reset) 2083 { 2084 2085 // Save the Completion Code for this CCB and queue the CCB 2086 // for completion processing. 2087 CCB->CompletionCode = CompletionCode; 2088 BusLogic_QueueCompletedCCB(deviceExtension,CCB); 2089 } 2090 else 2091 { 2092 // If a CCB ever appears in an Incoming Mailbox and is not marked 2093 // as status Active or Reset, then there is most likely a bug in 2094 // the Host Adapter firmware. 2095 DebugPrint((ERROR, "\n BusLogic - Illegal CCB #%ld status %d in " 2096 "Incoming Mailbox\n", CCB->SerialNumber, CCB->Status)); 2097 } 2098 } 2099 NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree; 2100 if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox) 2101 NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; 2102 } 2103 HostAdapter->NextIncomingMailbox = NextIncomingMailbox; 2104 }// end BusLogic_ScanIncomingMailboxes 2105 2106 2107 void 2108 BusLogic_QueueCompletedCCB(PHW_DEVICE_EXTENSION deviceExtension, 2109 BusLogic_CCB_T *CCB) 2110 //_________________________________________________________________________________ 2111 // Routine Description: 2112 // BusLogic_QueueCompletedCCB queues CCB for completion processing. 2113 // Arguments: 2114 // 1. deviceExtension : pointer to device extension 2115 // 2. CCB: pointe t CCB that needs to be queued 2116 //_________________________________________________________________________________ 2117 { 2118 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 2119 2120 CCB->Status = BusLogic_CCB_Completed; 2121 CCB->Next = NULL; 2122 if (HostAdapter->FirstCompletedCCB == NULL) 2123 { 2124 HostAdapter->FirstCompletedCCB = CCB; 2125 HostAdapter->LastCompletedCCB = CCB; 2126 } 2127 else 2128 { 2129 HostAdapter->LastCompletedCCB->Next = CCB; 2130 HostAdapter->LastCompletedCCB = CCB; 2131 } 2132 HostAdapter->ActiveCommandsPerTarget[CCB->TargetID]--; 2133 HostAdapter->ActiveCommandsPerLun[CCB->TargetID][CCB->LogicalUnit]--; 2134 2135 }// end BusLogic_QueueCompletedCCB 2136 2137 2138 void 2139 BusLogic_ProcessCompletedCCBs(PHW_DEVICE_EXTENSION deviceExtension) 2140 //_________________________________________________________________________________ 2141 // Routine Description: 2142 // BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host 2143 // Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and 2144 // calling the SCSI Subsystem Completion Routines. The Host Adapter's Lock 2145 // should already have been acquired by the caller. 2146 // 2147 // Arguments: 2148 // 1. deviceExtension : pointer to device extension 2149 //_________________________________________________________________________________ 2150 { 2151 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 2152 PSCSI_REQUEST_BLOCK srb; 2153 PCDB RealCdb; 2154 2155 if (HostAdapter->ProcessCompletedCCBsActive) 2156 return; 2157 HostAdapter->ProcessCompletedCCBsActive = TRUE; 2158 while (HostAdapter->FirstCompletedCCB != NULL) 2159 { 2160 BusLogic_CCB_T *CCB = HostAdapter->FirstCompletedCCB; 2161 2162 // Get SRB from CCB. 2163 srb = CCB->SrbAddress; 2164 2165 HostAdapter->FirstCompletedCCB = CCB->Next; 2166 if (HostAdapter->FirstCompletedCCB == NULL) 2167 HostAdapter->LastCompletedCCB = NULL; 2168 2169 // Process the Completed CCB. 2170 if (CCB->Opcode == BusLogic_BusDeviceReset) 2171 { 2172 int TargetID = CCB->TargetID, LunID; 2173 DebugPrint((TRACE, "\n BusLogic - Bus Device Reset CCB #%ld to Target " 2174 "%d Completed\n", CCB->SerialNumber, TargetID)); 2175 BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted); 2176 2177 HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = FALSE; 2178 HostAdapter->CommandsSinceReset[TargetID] = 0; 2179 //HostAdapter->LastResetCompleted[TargetID] = jiffies; 2180 HostAdapter->ActiveCommandsPerTarget[TargetID] = 0; 2181 for (LunID = 0; LunID < HostAdapter->MaxLogicalUnits; LunID++) 2182 HostAdapter->ActiveCommandsPerLun[TargetID][LunID] = 0; 2183 2184 // Complete all outstanding requests with SRB_STATUS_BUS_RESET. 2185 ScsiPortCompleteRequest(deviceExtension, 2186 (UCHAR)srb->PathId, 2187 srb->TargetId, 2188 0xFF, 2189 (ULONG)SRB_STATUS_BUS_RESET); 2190 2191 2192 HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; 2193 } 2194 else 2195 { 2196 // Translate the Completion Code, Host Adapter Status, and Target 2197 // Device Status into a SCSI Subsystem Result Code. 2198 switch (CCB->CompletionCode) 2199 { 2200 case BusLogic_IncomingMailboxFree: 2201 case BusLogic_InvalidCCB: 2202 { 2203 DebugPrint((ERROR, "\n BusLogic - CCB #%ld to Target %d Impossible " 2204 "State\n", CCB->SerialNumber, CCB->TargetID)); 2205 break; 2206 } 2207 2208 //Processing for CCB that was to be aborted 2209 case BusLogic_AbortedCommandNotFound: 2210 { 2211 srb = CCB->AbortSrb; 2212 srb->SrbStatus = SRB_STATUS_ABORT_FAILED; 2213 break; 2214 } 2215 2216 case BusLogic_CommandCompletedWithoutError: 2217 { 2218 HostAdapter->TargetStatistics[CCB->TargetID].CommandsCompleted++; 2219 HostAdapter->TargetFlags[CCB->TargetID].CommandSuccessfulFlag = TRUE; 2220 2221 srb->SrbStatus = SRB_STATUS_SUCCESS; 2222 break; 2223 } 2224 2225 case BusLogic_CommandAbortedAtHostRequest: 2226 { 2227 DebugPrint((TRACE, "\n BusLogic - CCB #%ld to Target %d Aborted\n", 2228 CCB->SerialNumber, CCB->TargetID)); 2229 //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[CCB->TargetID].CommandAbortsCompleted); 2230 2231 srb->SrbStatus = SRB_STATUS_ABORTED; 2232 2233 // Call notification routine for the aborted SRB. 2234 ScsiPortNotification(RequestComplete, 2235 deviceExtension, 2236 srb); 2237 2238 // Get the abort SRB from CCB. 2239 srb = CCB->AbortSrb; 2240 2241 // Set status for completing abort request. 2242 srb->SrbStatus = SRB_STATUS_SUCCESS; 2243 break; 2244 } 2245 2246 case BusLogic_CommandCompletedWithError: 2247 { 2248 RealCdb = (PCDB)CCB->CDB; 2249 DebugPrint((ERROR, "\n BusLogic - %x Command completed with error Host - " 2250 "%x Target %x \n", RealCdb->CDB6GENERIC.OperationCode, 2251 CCB->HostAdapterStatus, CCB->TargetDeviceStatus)); 2252 2253 srb->SrbStatus = BusLogic_ComputeResultCode(HostAdapter, 2254 CCB->HostAdapterStatus, 2255 CCB->TargetDeviceStatus, 2256 CCB->SenseDataLength); 2257 if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) 2258 { 2259 HostAdapter->TargetStatistics[CCB->TargetID].CommandsCompleted++; 2260 } 2261 break; 2262 } 2263 2264 default: 2265 { 2266 // Log the error. 2267 ScsiPortLogError(deviceExtension, 2268 NULL, 2269 0, 2270 srb->TargetId, 2271 0, 2272 SP_INTERNAL_ADAPTER_ERROR, 2273 143); 2274 2275 DebugPrint((ERROR, "\n BusLogic - Unrecognized mailbox status\n")); 2276 } 2277 2278 }// end switch 2279 2280 2281 // When an INQUIRY command completes normally, save the CmdQue (Tagged Queuing Supported) 2282 // and WBus16 (16 Bit Wide Data Transfers Supported) bits. 2283 RealCdb = (PCDB) CCB->CDB; 2284 if (RealCdb->CDB6INQUIRY.OperationCode == SCSIOP_INQUIRY && 2285 CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) 2286 { 2287 BusLogic_TargetFlags_T *TargetFlags =&HostAdapter->TargetFlags[CCB->TargetID]; 2288 SCSI_Inquiry_T *InquiryResult =(SCSI_Inquiry_T *) srb->DataBuffer; 2289 TargetFlags->TargetExists = TRUE; 2290 TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue; 2291 TargetFlags->WideTransfersSupported = InquiryResult->WBus16; 2292 } 2293 2294 DebugPrint((INFO, "\n BusLogic - SCSI Status %x\n", srb->ScsiStatus)); 2295 DebugPrint((INFO, "\n BusLogic - HBA Status %x\n", CCB->HostAdapterStatus)); 2296 2297 // Update target status in SRB. 2298 srb->ScsiStatus = (UCHAR)CCB->TargetDeviceStatus; 2299 2300 // Signal request completion. 2301 ScsiPortNotification(RequestComplete, (PVOID)deviceExtension, srb); 2302 } 2303 } 2304 HostAdapter->ProcessCompletedCCBsActive = FALSE; 2305 }// end BusLogic_ProcessCompletedCCBs 2306 2307 2308 UCHAR 2309 BusLogic_ComputeResultCode(BusLogic_HostAdapter_T *HostAdapter, 2310 BusLogic_HostAdapterStatus_T HostAdapterStatus, 2311 BusLogic_TargetDeviceStatus_T TargetDeviceStatus, 2312 UCHAR SenseDataLength) 2313 //_________________________________________________________________________________________ 2314 // Routine Description: 2315 // BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from 2316 // the Host Adapter Status and Target Device Status. 2317 // Arguments: 2318 // 1.HostAdapter: Pointer to the host adapter structure 2319 // 2.HostAdapterStatus: Host adapter status returned in the completed CCB 2320 // 3.TargetDeviceStatus: 2321 // Return Value: 2322 // This function returns the error code that should be returned to port driver 2323 //_________________________________________________________________________________________ 2324 { 2325 UCHAR HostStatus = 0; 2326 2327 // Namita 2Oct CDROM issue 2328 if (TargetDeviceStatus != BusLogic_OperationGood && (HostAdapterStatus == BusLogic_CommandCompletedNormally || 2329 HostAdapterStatus == BusLogic_LinkedCommandCompleted || 2330 HostAdapterStatus == BusLogic_LinkedCommandCompletedWithFlag)) 2331 { 2332 switch(TargetDeviceStatus) 2333 { 2334 case BusLogic_CheckCondition: 2335 { 2336 HostStatus = SRB_STATUS_ERROR; 2337 if(SenseDataLength != BusLogic_DisableAutoReqSense) 2338 HostStatus |= SRB_STATUS_AUTOSENSE_VALID; 2339 break; 2340 } 2341 case BusLogic_DeviceBusy: 2342 { 2343 HostStatus = SRB_STATUS_BUSY; 2344 break; 2345 } 2346 case BusLogic_OperationGood: 2347 { 2348 HostStatus = SRB_STATUS_SUCCESS; 2349 break; 2350 } 2351 } 2352 } 2353 2354 else 2355 { 2356 2357 switch (HostAdapterStatus) 2358 { 2359 case BusLogic_CommandCompletedNormally: 2360 case BusLogic_LinkedCommandCompleted: 2361 case BusLogic_LinkedCommandCompletedWithFlag: 2362 { 2363 HostStatus = SRB_STATUS_SUCCESS; 2364 break; 2365 } 2366 case BusLogic_SCSISelectionTimeout: 2367 { 2368 HostStatus = SRB_STATUS_SELECTION_TIMEOUT; 2369 break; 2370 } 2371 case BusLogic_InvalidOutgoingMailboxActionCode: 2372 case BusLogic_InvalidCommandOperationCode: 2373 case BusLogic_InvalidCommandParameter: 2374 DebugPrint((WARNING, "\n BusLogic - Driver Protocol Error 0x%02X\n", 2375 HostAdapterStatus)); 2376 case BusLogic_DataUnderRun: 2377 2378 case BusLogic_DataOverRun: 2379 // SRB_STATUS_DATA_OVERRUN 2380 2381 case BusLogic_LinkedCCBhasInvalidLUN: 2382 2383 case BusLogic_TaggedQueuingMessageRejected: 2384 // SRB_STATUS_MESSAGE_REJECTED 2385 case BusLogic_TargetDeviceReconnectedImproperly: 2386 case BusLogic_AbortQueueGenerated: 2387 case BusLogic_HostAdapterSoftwareError: 2388 2389 case BusLogic_HostAdapterHardwareTimeoutError: 2390 // SRB_STATUS_TIMEOUT 2391 { 2392 HostStatus = SRB_STATUS_ERROR; 2393 break; 2394 } 2395 case BusLogic_TargetFailedResponseToATN: 2396 case BusLogic_HostAdapterAssertedRST: 2397 case BusLogic_OtherDeviceAssertedRST: 2398 case BusLogic_HostAdapterAssertedBusDeviceReset: 2399 { 2400 HostStatus = SRB_STATUS_BUS_RESET; 2401 break; 2402 } 2403 case BusLogic_SCSIParityErrorDetected: 2404 { 2405 HostStatus = SRB_STATUS_PARITY_ERROR; 2406 break; 2407 } 2408 case BusLogic_UnexpectedBusFree: 2409 { 2410 HostStatus = SRB_STATUS_UNEXPECTED_BUS_FREE; 2411 break; 2412 } 2413 case BusLogic_InvalidBusPhaseRequested: 2414 { 2415 HostStatus = SRB_STATUS_PHASE_SEQUENCE_FAILURE; 2416 break; 2417 } 2418 case BusLogic_AutoRequestSenseFailed: 2419 { 2420 HostStatus = SRB_STATUS_REQUEST_SENSE_FAILED; 2421 break; 2422 } 2423 case BusLogic_UnsupportedMessageReceived: 2424 { 2425 HostStatus = SRB_STATUS_INVALID_REQUEST; 2426 break; 2427 } 2428 case BusLogic_HostAdapterHardwareFailed: 2429 { 2430 HostStatus = SRB_STATUS_NO_HBA; 2431 break; 2432 } 2433 default: 2434 { 2435 DebugPrint((WARNING, "\n BusLogic - Unknown HBA Status 0x%02X\n", 2436 HostAdapterStatus)); 2437 HostStatus = SRB_STATUS_ERROR; 2438 break; 2439 } 2440 } 2441 } 2442 return HostStatus; 2443 }// end BusLogic_ComputeResultCode 2444 2445 2446 BOOLEAN 2447 NTAPI 2448 BT958HwResetBus(IN PVOID HwDeviceExtension, 2449 IN ULONG PathId) 2450 //_____________________________________________________________________________________ 2451 // Routine Description: 2452 // BT958HwResetBus resets Host Adapter if possible, marking all 2453 // currently executing SCSI Commands as having been Reset. 2454 // Arguments: 2455 // 1. HwDeviceExtension: Points to the miniport driver's per-HBA storage area. 2456 // 2. PathId: Identifies the SCSI bus to be reset. 2457 // Return Value: 2458 // TRUE : If the bus is successfully reset, HwScsiResetBus returns TRUE. 2459 // FALSE : reset did not complete successfully 2460 //_____________________________________________________________________________________ 2461 { 2462 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 2463 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 2464 // BusLogic_CCB_T *CCB; 2465 // int TargetID; 2466 BOOLEAN Result; 2467 BOOLEAN HardReset; 2468 2469 DebugPrint((TRACE, "\n BusLogic - Reset SCSI bus\n")); 2470 2471 // Complete all outstanding requests with SRB_STATUS_BUS_RESET. 2472 ScsiPortCompleteRequest(deviceExtension, 2473 (UCHAR)PathId, 2474 0xFF, 2475 0xFF, 2476 (ULONG) SRB_STATUS_BUS_RESET); 2477 2478 if (HostAdapter->HostAdapterExternalReset) 2479 { 2480 //BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets); 2481 HardReset = FALSE; 2482 } 2483 else if (HostAdapter->HostAdapterInternalError) 2484 { 2485 //BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors); 2486 HardReset = TRUE; 2487 } 2488 else 2489 { 2490 //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[srb->TargetId].HostAdapterResetsRequested); 2491 HardReset = TRUE; 2492 } 2493 2494 // Think of a way of doing this - Namita 2495 /* 2496 if(srb == NULL) 2497 { 2498 if (HostAdapter->HostAdapterInternalError) 2499 DebugPrint((0,"BusLogic Warning: Resetting %s due to Host Adapter Internal Error\n",HostAdapter->FullModelName)); 2500 else 2501 DebugPrint((0,"BUsLogic Warning: Resetting %s due to External SCSI Bus Reset\n",HostAdapter->FullModelName)); 2502 } 2503 else 2504 { 2505 DebugPrint((0,"BusLogic Warning: Resetting %s due to Target %d\n", HostAdapter->FullModelName, srb->TargetId)); 2506 //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[srb->TargetId].HostAdapterResetsAttempted); 2507 } 2508 */ 2509 2510 // Attempt to Reset and Reinitialize the Host Adapter. 2511 // Change the initialize routine to make allocation some place else 2512 if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && BusLogic_InitializeHostAdapter(deviceExtension, NULL))) 2513 { 2514 DebugPrint((ERROR, "\n Buslogic - Resetting %s Failed\n", 2515 HostAdapter->FullModelName)); 2516 Result = FALSE; 2517 goto Done; 2518 } 2519 2520 // Check if we have to do this, document says that the scsi port driver takes care of the reset delays - Namita 2521 // Wait a few seconds between the Host Adapter Hard Reset which initiates 2522 // a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get 2523 // confused if they receive SCSI Commands too soon after a SCSI Bus Reset. 2524 // Note that a timer interrupt may occur here, but all active CCBs have 2525 // already been marked Reset and so a reentrant call will return Pending. 2526 if (HardReset) 2527 ScsiPortStallExecution(HostAdapter->BusSettleTime); 2528 Result = TRUE; 2529 2530 Done: 2531 return Result; 2532 }// end BT958HwResetBus 2533 2534 BOOLEAN 2535 BusLogic_SendBusDeviceReset(IN PVOID HwDeviceExtension, 2536 PSCSI_REQUEST_BLOCK Srb) 2537 //_____________________________________________________________________________________ 2538 // Routine Description: 2539 // BusLogic_SendBusDeviceReset causes a BUS DEVICE reset command to 2540 // be send to particular target. 2541 // Arguments: 2542 // 1. HwDeviceExtension: Points to the miniport driver's per-HBA storage area. 2543 // 2. Srb: pointer to the SCSI request block 2544 // Return Value: 2545 // TRUE : If the bus is successfully reset, HwScsiResetBus returns TRUE. 2546 // FALSE : reset did not complete successfully 2547 //_____________________________________________________________________________________ 2548 { 2549 2550 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 2551 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 2552 2553 UCHAR TargetID = Srb->TargetId; 2554 PBuslogic_CCB_T CCB = Srb->SrbExtension; 2555 BOOLEAN Result = FALSE; 2556 BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsRequested); 2557 2558 // If this is a Synchronous Reset and a Bus Device Reset is already pending 2559 // for this Target Device, do not send a second one. Add this Command to 2560 // the list of Commands for which completion processing must be performed 2561 // when the Bus Device Reset CCB completes. 2562 2563 if (HostAdapter->BusDeviceResetPendingCCB[TargetID] != NULL) 2564 { 2565 DebugPrint((WARNING, "\n BusLogic - Unable to Reset Command to Target %d - " 2566 "Reset Pending\n", TargetID)); 2567 Result = TRUE; 2568 goto Done; 2569 } 2570 2571 DebugPrint((WARNING, "\n BusLogic - Sending Bus Device Reset CCB #%ld to Target %d\n", 2572 CCB->SerialNumber, TargetID)); 2573 CCB->Opcode = BusLogic_BusDeviceReset; 2574 CCB->TargetID = TargetID; 2575 2576 2577 // Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB. 2578 // If sending a Bus Device Reset is impossible, attempt a full Host 2579 // Adapter Hard Reset and SCSI Bus Reset. 2580 if (!(BusLogic_WriteOutgoingMailbox(deviceExtension, BusLogic_MailboxStartCommand, CCB))) 2581 { 2582 DebugPrint((WARNING, "\n BusLogic - Unable to write Outgoing Mailbox for " 2583 "Bus Device Reset\n")); 2584 goto Done; 2585 } 2586 2587 // If there is a currently executing CCB in the Host Adapter for this Command 2588 // (i.e. this is an Asynchronous Reset), then an Incoming Mailbox entry may be 2589 // made with a completion code of BusLogic_HostAdapterAssertedBusDeviceReset. 2590 // If there is no active CCB for this Command (i.e. this is a Synchronous 2591 // Reset), then the Bus Device Reset CCB's Command field will have been set 2592 // to the Command so that the interrupt for the completion of the Bus Device 2593 // Reset can call the Completion Routine for the Command. On successful 2594 // execution of a Bus Device Reset, older firmware versions did return the 2595 // pending CCBs with the appropriate completion code, but more recent firmware 2596 // versions only return the Bus Device Reset CCB itself. This driver handles 2597 // both cases by marking all the currently executing CCBs to this Target 2598 // Device as Reset. When the Bus Device Reset CCB is processed by the 2599 // interrupt handler, any remaining CCBs marked as Reset will have completion 2600 // processing performed. 2601 2602 BusLogic_IncrementErrorCounter( &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsAttempted); 2603 HostAdapter->BusDeviceResetPendingCCB[TargetID] = CCB; 2604 //HostAdapter->LastResetAttempted[TargetID] = jiffies; 2605 2606 // FlashPoint Host Adapters may have already completed the Bus Device 2607 // Reset and BusLogic_QueueCompletedCCB been called, or it may still be 2608 // pending. 2609 2610 Result = TRUE; 2611 // If a Bus Device Reset was not possible for some reason, force a full 2612 // Host Adapter Hard Reset and SCSI Bus Reset. 2613 2614 Done: 2615 return Result; 2616 } 2617 2618 BOOLEAN 2619 NTAPI 2620 BT958HwInitialize(IN PVOID HwDeviceExtension) 2621 //_______________________________________________________________________________ 2622 // Routine Description: 2623 // This routine initializes the adapter by enabling its interrupts 2624 // Arguments: 2625 // 1. device extension 2626 // Return Value: 2627 // TRUE : initialization successful 2628 // FALSE : initialization failed 2629 //_______________________________________________________________________________ 2630 { 2631 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 2632 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 2633 CHAR Parameter = 1; 2634 2635 // enable interrupts 2636 if (BusLogic_Command(HostAdapter, 2637 BusLogic_DisableHostAdapterInterrupt, 2638 &Parameter, 2639 sizeof(Parameter), 2640 NULL, 2641 0) 2642 < 0) 2643 { 2644 return FALSE; 2645 } 2646 return TRUE; 2647 }// end BT958HwInitialize 2648 2649 SCSI_ADAPTER_CONTROL_STATUS 2650 NTAPI 2651 BT958HwAdapterControl(IN PVOID HwDeviceExtension, 2652 IN SCSI_ADAPTER_CONTROL_TYPE ControlType, 2653 IN PVOID Parameters) 2654 //__________________________________________________________________________________________ 2655 // Routine Description: 2656 // A miniport driver's HwScsiAdapterControl routine is called to perform 2657 // synchronous operations to control the state or behavior of an HBA, such as 2658 // stopping or restarting the HBA for power management. 2659 // Arguments: 2660 // 1. HwDeviceExtension: device extension 2661 // 2. ControlType: Specifies one of the following adapter-control operations. 2662 // ScsiQuerySupportedControlTypes : Reports the adapter-control operations 2663 // implemented by the miniport. 2664 // ScsiStopAdapter: Shuts down the HBA. 2665 // ScsiRestartAdapter: Reinitializes an HBA. 2666 // ScsiSetBootConfig: Not supported 2667 // ScsiSetRunningConfig: Not supported 2668 // 3. Parameters: 2669 // Return Value: 2670 // TRUE : 2671 // FALSE : 2672 //_________________________________________________________________________ 2673 { 2674 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 2675 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 2676 // UCHAR *ParameterPointer; 2677 // BusLogic_StatusRegister_T StatusRegister; 2678 // BusLogic_InterruptRegister_T InterruptRegister; 2679 // int Result,ParameterLength; 2680 // long TimeoutCounter; 2681 2682 PSCSI_SUPPORTED_CONTROL_TYPE_LIST ControlTypeList; 2683 ULONG AdjustedMaxControlType; 2684 2685 ULONG Index; 2686 // UCHAR Retries; 2687 2688 // Default Status 2689 // SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess; 2690 2691 // 2692 // Structure defining which functions this miniport supports 2693 // 2694 BOOLEAN SupportedConrolTypes[ScsiAdapterControlMax] = 2695 { 2696 TRUE, // ScsiQuerySupportedControlTypes 2697 TRUE, // ScsiStopAdapter 2698 TRUE, // ScsiRestartAdapter 2699 FALSE, // ScsiSetBootConfig 2700 FALSE // ScsiSetRunningConfig 2701 }; 2702 2703 DebugPrint((TRACE, "\n BusLogic - Inside HwAdapterControl function \n")); 2704 switch(ControlType) 2705 { 2706 case ScsiQuerySupportedControlTypes: 2707 // Reports the adapter-control operations implemented by the miniport. The port 2708 // driver calls HwScsiAdapterControl with this control type after the HBA has been 2709 // initialized but before the first I/O. The miniport fills in the 2710 // SCSI_SUPPORTED_CONTROL_TYPE_LIST structure at Parameters with the operations it 2711 // supports. After HwScsiAdapterControl returns from this call, the port driver 2712 // calls the miniport's HwScsiAdapterControl only for supported operations. 2713 { 2714 2715 // This entry point provides the method by which SCSIPort determines the 2716 // supported ControlTypes. Parameters is a pointer to a 2717 // SCSI_SUPPORTED_CONTROL_TYPE_LIST structure. Fill in this structure 2718 // honoring the size limits. 2719 ControlTypeList = Parameters; 2720 AdjustedMaxControlType = (ControlTypeList->MaxControlType < ScsiAdapterControlMax) ? ControlTypeList->MaxControlType :ScsiAdapterControlMax; 2721 for (Index = 0; Index < AdjustedMaxControlType; Index++) 2722 { 2723 ControlTypeList->SupportedTypeList[Index] = SupportedConrolTypes[Index]; 2724 } 2725 break; 2726 } 2727 2728 case ScsiStopAdapter: 2729 // Shuts down the HBA. The port driver calls HwScsiAdapterControl with this control 2730 // type when the HBA has been removed from the system, stopped for resource reconfiguration, 2731 // shut down for power management, or otherwise reconfigured or disabled. The port driver 2732 // ensures that there are no uncompleted requests and issues an SRB_FUNCTION_FLUSH request 2733 // to the miniport before calling this routine. The miniport disables interrupts on its HBA, 2734 // halts all processing, (including background processing not subject to interrupts or processing 2735 // of which the port driver is unaware, such as reconstructing fault-tolerant volumes), flushes 2736 // any remaining cached data to persistent storage, and puts the HBA into a state from which it 2737 // can be reinitialized or restarted. 2738 // The miniport should not free its resources when stopping its HBA. If the HBA was removed or 2739 // stopped for PnP resource reconfiguration, the port driver releases resources on behalf of the 2740 // miniport driver. If the HBA is shut down for power management, the miniport's resources are 2741 // preserved so the HBA can be restarted. 2742 { 2743 CHAR Parameter = 0; 2744 DebugPrint((INFO, "\n BusLogic - stopping the device \n")); 2745 if (BusLogic_Command(HostAdapter, 2746 BusLogic_DisableHostAdapterInterrupt, 2747 &Parameter, 2748 sizeof(Parameter), 2749 NULL, 2750 0) 2751 < 0) 2752 { 2753 return ScsiAdapterControlUnsuccessful; 2754 } 2755 break; 2756 } 2757 2758 case ScsiRestartAdapter: 2759 // Reinitializes an HBA. The port driver calls HwScsiAdapterControl with this control type to power 2760 // up an HBA that was shut down for power management. All resources previously assigned to the miniport 2761 // are still available, and its device extension and logical unit extensions, if any, are intact. 2762 // The miniport performs the same operations as in its HwScsiInitialize routine, such as setting up 2763 // the HBA's registers and its initial state, if any. 2764 // The miniport must not call routines that can only be called from HwScsiFindAdapter or from 2765 // HwScsiAdapterControl when the control type is ScsiSetRunningConfig, such as ScsiPortGetBusData and 2766 // ScsiPortSetBusDataByOffset. If the miniport must call such routines to restart its HBA, it must also 2767 // implement ScsiSetRunningConfig. 2768 // If the miniport does not implement ScsiRestartAdapter, the port driver calls the miniport's HwScsiFindAdapter and HwScsiInitialize routines. However, because such routines might do detection work which is unnecessary for restarting the HBA, such a miniport will not power up its HBA as quickly as a miniport that implements ScsiRestartAdapter. 2769 2770 // See PR 69004. We were not calling BT958HwInitialize earlier if the 2771 // first two calls succeeded thus causing resume from standby to fail. 2772 { 2773 if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, TRUE) && 2774 BusLogic_InitializeHostAdapter(deviceExtension, NULL) && 2775 BT958HwInitialize(HwDeviceExtension)) 2776 ) 2777 { 2778 DebugPrint((ERROR, "\n Buslogic - Resetting %s Failed\n", 2779 HostAdapter->FullModelName)); 2780 return ScsiAdapterControlUnsuccessful; 2781 } 2782 2783 ScsiPortStallExecution(HostAdapter->BusSettleTime); 2784 break; 2785 } 2786 default: 2787 { 2788 return ScsiAdapterControlUnsuccessful; 2789 } 2790 } 2791 return ScsiAdapterControlSuccess; 2792 }// end BT958HwAdapterControl 2793 2794 // END OF FILE BusLogic958.c 2795