Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > DoxygenBusLogic958.c
Go to the documentation of this file.
00001 /* 00002 * vmscsi-- Miniport driver for the Buslogic BT 958 SCSI Controller 00003 * under Windows 2000/XP/Server 2003 00004 * 00005 * Based in parts on the buslogic driver for the same device 00006 * available with the GNU Linux Operating System. 00007 * 00008 * This program is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU General Public License 00010 * as published by the Free Software Foundation; either version 2 00011 * of the License, or (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License along 00019 * with this program; if not, write to the Free Software Foundation, Inc., 00020 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00021 */ 00022 00023 //____________________________________________________________________________________ 00024 // 00025 // File description :The driver for BusLogic-BT958 SCSI Host adapter card. 00026 // This driver assumes that the host adapter(HA from now on) is a PCI device. 00027 // This is an effort to build a driver for this card for the windows XP ennvironment 00028 // since the native XP installation doesnt provide this driver. 00029 // 00030 // The technical refernece for this device is at : 00031 // 00032 // Author: Namita Lal, Sirish Raghuram Calsoft Pvt Ltd 00033 // Date: 5th Feb 2003 00034 // Status: Driver version 1.2.0.0 00035 // Performance tuned 00036 // Correctness tested for 00037 // 1. Installation at OS install time 00038 // 2. Installation in an installed OS 00039 // 3. Installation by upgrading a previous version 00040 // on all flavours of WinXP and Win Server 2003 00041 // For Win2k however, please refer PR 22812 00042 /* 00043 Revision History: 00044 v1.0.0.4 // Pre final release to VMware in Sep 2001, without WMI 00045 | 00046 | 00047 v 00048 v1.0.0.5 // Sep 2001 release to VMware, with WMI 00049 | 00050 | 00051 v 00052 v1.0.0.6 // Fix for bug with Nero Burning ROM in XP 00053 | // where SCSI_AUTO_SENSE is turned off at times 00054 | 00055 | 00056 |---------> v1.1.0.0 // Performance optimizations: 00057 | | // A. WMI disabled, B. Queueing depth increased 00058 | | // C. Control flow changed (bug) 00059 | | 00060 | v 00061 | v1.1.0.1 // Fix for .NET restart freeze with 1.1.0.0 00062 | // Breaks on XP 00063 | 00064 v 00065 v1.2.0.0 // A. WMI disabled, B. Queueing depth increased 00066 | 00067 | 00068 | 00069 v 00070 v1.2.0.1 // Fix PR 40284, affects pure ACPI Win2k systems. 00071 | 00072 | 00073 | 00074 v 00075 v1.2.0.2 // Fix PR 40284 correctly, disable interrupts in the initialization routine. 00076 // CURRENT VERSION 00077 */ 00078 //____________________________________________________________________________________ 00079 00080 #include "BusLogic958.h" 00081 00082 ULONG 00083 NTAPI 00084 DriverEntry(IN PVOID DriverObject, 00085 IN PVOID Argument2 00086 ) 00087 //_________________________________________________________________________ 00088 // Routine Description: 00089 // Installable driver initialization entry point for system. 00090 // Arguments: 00091 // Driver Object 00092 // Return Value: 00093 // Status from ScsiPortInitialize() 00094 //_________________________________________________________________________ 00095 { 00096 HW_INITIALIZATION_DATA hwInitializationData; 00097 ULONG Status; 00098 ULONG i; 00099 ULONG HwContext; 00100 // static int cardNo = 0; 00101 00102 UCHAR VendorId[4] = { '1', '0', '4', 'b' }; 00103 UCHAR DeviceId[4] = { '1', '0', '4', '0' }; 00104 00105 DebugPrint((TRACE,"\n BusLogic - Inside the DriverEntry function \n")); 00106 00107 // Zero out structure. 00108 for (i = 0; i < sizeof(HW_INITIALIZATION_DATA); i++) 00109 { 00110 ((PUCHAR) & hwInitializationData)[i] = 0; 00111 } 00112 00113 // Set size of hwInitializationData. 00114 hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA); 00115 00116 // Set entry points. 00117 hwInitializationData.HwInitialize = BT958HwInitialize; 00118 hwInitializationData.HwResetBus = BT958HwResetBus; 00119 hwInitializationData.HwStartIo = BT958HwStartIO; 00120 hwInitializationData.HwInterrupt = BT958HwInterrupt; 00121 hwInitializationData.HwAdapterControl = BT958HwAdapterControl; 00122 hwInitializationData.HwFindAdapter = BT958HwFindAdapter; 00123 00124 // Inidicate no buffer mapping but will need physical addresses 00125 hwInitializationData.NeedPhysicalAddresses = TRUE; 00126 00127 // Indicate Auto request sense is supported 00128 hwInitializationData.AutoRequestSense = TRUE; 00129 hwInitializationData.MultipleRequestPerLu = TRUE; 00130 00131 #if TAG_QUEUING 00132 hwInitializationData.TaggedQueuing = TRUE; 00133 #else 00134 hwInitializationData.TaggedQueuing = FALSE; 00135 #endif 00136 00137 hwInitializationData.AdapterInterfaceType = PCIBus; 00138 00139 // Fill in the vendor id and the device id 00140 hwInitializationData.VendorId = &VendorId; 00141 hwInitializationData.VendorIdLength = 4; 00142 hwInitializationData.DeviceId = &DeviceId; 00143 hwInitializationData.DeviceIdLength = 4; 00144 00145 00146 hwInitializationData.NumberOfAccessRanges = 2; 00147 00148 00149 // Specify size of extensions. 00150 hwInitializationData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION); 00151 00152 // logical unit extension 00153 hwInitializationData.SrbExtensionSize = sizeof(BusLogic_CCB_T); 00154 00155 HwContext = 0; 00156 00157 DebugPrint((TRACE,"\n BusLogic - Calling the ScsiPortInitialize Routine\n")); 00158 00159 Status = ScsiPortInitialize(DriverObject, 00160 Argument2, 00161 &hwInitializationData, 00162 &HwContext); 00163 00164 DebugPrint((TRACE,"\n BusLogic - Exiting the DriverEntry function \n")); 00165 DebugPrint((INFO,"\n BusLogic - Status = %ul \n", Status)); 00166 return( Status ); 00167 00168 } // end DriverEntry() 00169 00170 00171 ULONG 00172 NTAPI 00173 BT958HwFindAdapter(IN PVOID HwDeviceExtension, 00174 IN PVOID Context, 00175 IN PVOID BusInformation, 00176 IN PCHAR ArgumentString, 00177 IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo, 00178 OUT PBOOLEAN Again 00179 ) 00180 //_________________________________________________________________________________________________ 00181 // Routine Description: 00182 // This function is called by the OS-specific port driver after the necessary storage 00183 // has been allocated, to gather information about the adapter's configuration. 00184 // 00185 // Arguments: 00186 // HwDeviceExtension - HBA miniport driver's adapter data storage 00187 // Context - Register base address 00188 // ConfigInfo - Configuration information structure describing HBA 00189 // This structure is defined in PORT.H. 00190 // 00191 // Return Value: 00192 // HwScsiFindAdapter must return one of the following status values: 00193 // SP_RETURN_FOUND: Indicates a supported HBA was found and that the HBA-relevant 00194 // configuration information was successfully determined and set in 00195 // the PORT_CONFIGURATION_INFORMATION structure. 00196 // SP_RETURN_ERROR: Indicates an HBA was found but there was error obtaining the 00197 // configuration information. If possible, such an error should be 00198 // logged with ScsiPortLogError. 00199 // SP_RETURN_BAD_CONFIG: Indicates the supplied configuration information was invalid 00200 // for the adapter. 00201 // SP_RETURN_NOT_FOUND: Indicates no supported HBA was found for the supplied 00202 // configuration information. 00203 //________________________________________________________________________________________________ 00204 { 00205 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 00206 BusLogic_HostAdapter_T *hcsp = &(deviceExtension->hcs); 00207 // static UCHAR k = 0; 00208 PACCESS_RANGE accessRange; 00209 // PCI_COMMON_CONFIG PCICommonConfig; 00210 PUCHAR pciAddress; 00211 char NumPort = 0; 00212 00213 DebugPrint((TRACE,"\n BusLogic - Inside the Find Adapter Routine\n")); 00214 00215 *Again = FALSE; 00216 00217 accessRange = &((*(ConfigInfo->AccessRanges))[0]); 00218 00219 // Inform SCSIPORT that we are NOT a WMI data provider 00220 // Sirish, 10th June 2002 00221 ConfigInfo->WmiDataProvider = FALSE; 00222 /*Sirish, 10th June 2002 BT958WmiInitialize(deviceExtension);*/ 00223 00224 // Check for configuration information passed in form the system 00225 if ((*ConfigInfo->AccessRanges)[0].RangeLength != 0) 00226 { 00227 // check if the system supplied bus-relative address is valid and has not been 00228 // claimed by anyother device 00229 if ( ScsiPortValidateRange(deviceExtension, 00230 ConfigInfo->AdapterInterfaceType, 00231 ConfigInfo->SystemIoBusNumber, 00232 accessRange->RangeStart, 00233 accessRange->RangeLength, 00234 TRUE) ) // TRUE: iniospace 00235 { 00236 DebugPrint((INFO,"\n BusLogic - Validate Range function succeeded \n")); 00237 00238 // Map the Bus-relative range addresses to system-space logical range addresses 00239 // so that these mapped logical addresses can be called with SciPortRead/Writexxx 00240 // to determine whether the adapter is an HBA that the driver supports 00241 00242 pciAddress = (PUCHAR) ScsiPortGetDeviceBase(deviceExtension, 00243 ConfigInfo->AdapterInterfaceType, 00244 ConfigInfo->SystemIoBusNumber, 00245 accessRange->RangeStart, 00246 accessRange->RangeLength, 00247 TRUE); // TRUE: iniospace 00248 00249 if(pciAddress) 00250 { 00251 DebugPrint((INFO,"\n BusLogic - Get Device Base function succeeded \n")); 00252 00253 memset(hcsp, 0, sizeof(BusLogic_HostAdapter_T)); 00254 00255 // points to structure of type BT958_HA which has device specific information. This needs 00256 // to be either changed or modified with our specific info. 00257 hcsp->IO_Address = pciAddress; 00258 hcsp->IRQ_Channel = (UCHAR)ConfigInfo->BusInterruptLevel; 00259 NumPort++; 00260 } 00261 } 00262 } 00263 00264 if (NumPort == 0) 00265 { 00266 return(SP_RETURN_NOT_FOUND); 00267 } 00268 00269 // Hardware found, let's find out hardware configuration 00270 // and fill out ConfigInfo table for WinNT 00271 ConfigInfo->NumberOfBuses = 1; 00272 ConfigInfo->MaximumTransferLength = MAX_TRANSFER_SIZE; 00273 00274 #if SG_SUPPORT 00275 ConfigInfo->ScatterGather = TRUE; 00276 #else 00277 ConfigInfo->ScatterGather = FALSE; 00278 #endif 00279 00280 ConfigInfo->Master = TRUE; 00281 ConfigInfo->NeedPhysicalAddresses = TRUE; 00282 ConfigInfo->Dma32BitAddresses = TRUE; 00283 ConfigInfo->InterruptMode = LevelSensitive; 00284 00285 #if TAG_QUEUING 00286 ConfigInfo->TaggedQueuing = TRUE; 00287 #else 00288 ConfigInfo->TaggedQueuing = FALSE; 00289 #endif 00290 00291 // Should we change this to double-word aligned to increase performance 00292 ConfigInfo->AlignmentMask = 0x0; 00293 00294 if (!Buslogic_InitBT958(deviceExtension,ConfigInfo)) // harware specific initializations. Find what's for our card 00295 { 00296 ScsiPortLogError(deviceExtension, 00297 NULL, 00298 0, 00299 0, 00300 0, 00301 SP_INTERNAL_ADAPTER_ERROR, 00302 7 << 8); 00303 00304 return(SP_RETURN_ERROR); 00305 } 00306 00307 if (NumPort != 0) 00308 *Again = TRUE; 00309 00310 return(SP_RETURN_FOUND); 00311 00312 } // end BT958FindAdapter() 00313 00314 00315 BOOLEAN 00316 Buslogic_InitBT958(PHW_DEVICE_EXTENSION deviceExtension, 00317 PPORT_CONFIGURATION_INFORMATION ConfigInfo) 00318 //_________________________________________________________________________ 00319 // Routine Description: 00320 // This routine is called from the driver's FindAdapter routine 00321 // On invocation this routine probes the host adapter to check 00322 // if its hardware registers are responding correctly, and 00323 // initializes the device and makes it ready for IO 00324 // Arguments: 00325 // 1. deviceExtension 00326 // 2. Port Configuration info 00327 // Return Value: 00328 // TRUE : Device initialized properly 00329 // FALSE : Device failed to initialize 00330 //_________________________________________________________________________ 00331 { 00332 CHAR ch; 00333 00334 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 00335 00336 // Probe the Host Adapter. 00337 // If unsuccessful, abort further initialization. 00338 if (!BusLogic_ProbeHostAdapter(HostAdapter)) 00339 return FALSE; 00340 00341 // Hard Reset the Host Adapter. 00342 // If unsuccessful, abort further initialization. 00343 if (!BusLogic_HardwareResetHostAdapter(HostAdapter, TRUE)) 00344 return FALSE; 00345 00346 /* 00347 * PR 40284 -- Disable interrupts until driver initialization is complete. 00348 */ 00349 ch = 0; 00350 if (BusLogic_Command(HostAdapter, BusLogic_DisableHostAdapterInterrupt, 00351 &ch, sizeof(ch), NULL, 0) < 0) { 00352 DebugPrint((WARNING, "\n BusLogic - Could not disable interrupts!\n")); 00353 } else { 00354 DebugPrint((INFO, "\n BusLogic - Disabled interrupts.\n")); 00355 } 00356 00357 // Check the Host Adapter. 00358 // If unsuccessful, abort further initialization. 00359 if (!BusLogic_CheckHostAdapter(HostAdapter)) 00360 return FALSE; 00361 00362 // Allocate a Noncached Extension to use for mail boxes. 00363 deviceExtension->NoncachedExtension = ScsiPortGetUncachedExtension(deviceExtension, 00364 ConfigInfo, 00365 sizeof(NONCACHED_EXTENSION)); 00366 00367 if (deviceExtension->NoncachedExtension == NULL) 00368 { 00369 // Log error. 00370 ScsiPortLogError(deviceExtension, 00371 NULL, 00372 0, 00373 0, 00374 0, 00375 SP_INTERNAL_ADAPTER_ERROR, 00376 7 << 8); 00377 00378 // abort further initialization 00379 return FALSE; 00380 } 00381 00382 // Read the Host Adapter Configuration, Configure the Host Adapter, 00383 // Acquire the System Resources necessary to use the Host Adapter, then 00384 // Create the Initial CCBs, Initialize the Host Adapter, and finally 00385 // perform Target Device Inquiry. 00386 if (BusLogic_ReadHostAdapterConfiguration(HostAdapter) && 00387 //BusLogic_ReportHostAdapterConfiguration(HostAdapter) && 00388 BusLogic_InitializeHostAdapter(deviceExtension, ConfigInfo) && 00389 BusLogic_TargetDeviceInquiry(HostAdapter)) 00390 { 00391 // Fill in the: 00392 // 1.Maximum number of scsi target devices that are supported by our adapter 00393 ConfigInfo->MaximumNumberOfTargets = HostAdapter->MaxTargetDevices; 00394 // 2. Maximum number of logical units per target the HBA can control. 00395 ConfigInfo->MaximumNumberOfLogicalUnits = HostAdapter->MaxLogicalUnits; 00396 ConfigInfo->InitiatorBusId[0] = HostAdapter->SCSI_ID; 00397 // Maximum number of breaks between address ranges that a data buffer can 00398 // have if the HBA supports scatter/gather. In other words, the number of 00399 // scatter/gather lists minus one. 00400 ConfigInfo->NumberOfPhysicalBreaks = HostAdapter->DriverScatterGatherLimit; 00401 } 00402 else 00403 { 00404 // An error occurred during Host Adapter Configuration Querying, Host 00405 // Adapter Configuration, Host Adapter Initialization, or Target Device Inquiry, 00406 // so return FALSE 00407 00408 return FALSE; 00409 } 00410 // Initialization completed successfully 00411 return TRUE; 00412 } // end Buslogic_InitBT958 00413 00414 00415 BOOLEAN 00416 BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter) 00417 //____________________________________________________________________________________ 00418 // Routine Description: BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter. 00419 // The routine reads the status, interrupt and geometry regiter and 00420 // checks if their contents are valid 00421 // Arguments: 00422 // 1. Host Adapter structure 00423 // 00424 // Return Value: 00425 // TRUE: Probe completed successfully 00426 // FALSE: Probe failed 00427 //____________________________________________________________________________________ 00428 { 00429 BusLogic_StatusRegister_T StatusRegister; 00430 BusLogic_InterruptRegister_T InterruptRegister; 00431 BusLogic_GeometryRegister_T GeometryRegister; 00432 00433 DebugPrint((TRACE,"\n BusLogic - Inside ProbeHostaAdapter function \n")); 00434 // Read the Status, Interrupt, and Geometry Registers to test if there are I/O 00435 // ports that respond, and to check the values to determine if they are from a 00436 // BusLogic Host Adapter. A nonexistent I/O port will return 0xFF, in which 00437 // case there is definitely no BusLogic Host Adapter at this base I/O Address. 00438 // The test here is a subset of that used by the BusLogic Host Adapter BIOS. 00439 00440 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); 00441 GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); 00442 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 00443 00444 if (StatusRegister.All == 0 || 00445 StatusRegister.Bits.DiagnosticActive || 00446 StatusRegister.Bits.CommandParameterRegisterBusy || 00447 StatusRegister.Bits.Reserved || 00448 StatusRegister.Bits.CommandInvalid || 00449 InterruptRegister.Bits.Reserved != 0) 00450 return FALSE; 00451 00452 // Check the undocumented Geometry Register to test if there is an I/O port 00453 // that responded. Adaptec Host Adapters do not implement the Geometry 00454 // Register, so this test helps serve to avoid incorrectly recognizing an 00455 // Adaptec 1542A or 1542B as a BusLogic. Unfortunately, the Adaptec 1542C 00456 // series does respond to the Geometry Register I/O port, but it will be 00457 // rejected later when the Inquire Extended Setup Information command is 00458 // issued in BusLogic_CheckHostAdapter. The AMI FastDisk Host Adapter is a 00459 // BusLogic clone that implements the same interface as earlier BusLogic 00460 // Host Adapters, including the undocumented commands, and is therefore 00461 // supported by this driver. However, the AMI FastDisk always returns 0x00 00462 // upon reading the Geometry Register, so the extended translation option 00463 // should always be left disabled on the AMI FastDisk. 00464 00465 if (GeometryRegister.All == 0xFF) return FALSE; 00466 return TRUE; 00467 }// end BusLogic_ProbeHostAdapter 00468 00469 BOOLEAN 00470 BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T *HostAdapter, 00471 BOOLEAN HardReset) 00472 //_________________________________________________________________________ 00473 // Routine Description: BusLogic_HardwareResetHostAdapter issues a Hardware 00474 // Reset to the Host Adapter and waits for Host Adapter 00475 // Diagnostics to complete. If HardReset is TRUE, a 00476 // Hard Reset is performed which also initiates a SCSI 00477 // Bus Reset. Otherwise, a Soft Reset is performed which 00478 // only resets the Host Adapter without forcing a SCSI 00479 // Bus Reset. 00480 // Arguments: 00481 // 1. Host Adapter structure 00482 // 2. Boolean HardReset - True: Do hard reset 00483 // Return Value: 00484 // TRUE : Reset completed successfully 00485 // FALSE : Reset failed 00486 //_________________________________________________________________________ 00487 { 00488 BusLogic_StatusRegister_T StatusRegister; 00489 int TimeoutCounter; 00490 00491 // Issue a Hard Reset or Soft Reset Command to the Host Adapter. The Host 00492 // Adapter should respond by setting Diagnostic Active in the Status Register. 00493 if (HardReset) 00494 BusLogic_HardReset(HostAdapter); 00495 else 00496 BusLogic_SoftReset(HostAdapter); 00497 00498 // Wait until Diagnostic Active is set in the Status Register. 00499 TimeoutCounter = 100; 00500 while (--TimeoutCounter >= 0) 00501 { 00502 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 00503 if (StatusRegister.Bits.DiagnosticActive) 00504 break; 00505 } 00506 00507 // if inspite of waiting for time out period , if it didn't et set, then something is wrong-- so just return. 00508 if (TimeoutCounter < 0) 00509 return FALSE; 00510 00511 // 00512 // Wait 100 microseconds to allow completion of any initial diagnostic 00513 // activity which might leave the contents of the Status Register 00514 // unpredictable. 00515 ScsiPortStallExecution(100); 00516 00517 // Wait until Diagnostic Active is reset in the Status Register. 00518 TimeoutCounter = 10*10000; 00519 while (--TimeoutCounter >= 0) 00520 { 00521 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 00522 if (!StatusRegister.Bits.DiagnosticActive) 00523 break; 00524 ScsiPortStallExecution(100); 00525 } 00526 00527 if (TimeoutCounter < 0) 00528 return FALSE; 00529 00530 // Wait until at least one of the Diagnostic Failure, Host Adapter Ready, 00531 // or Data In Register Ready bits is set in the Status Register. 00532 TimeoutCounter = 10000; 00533 while (--TimeoutCounter >= 0) 00534 { 00535 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 00536 if (StatusRegister.Bits.DiagnosticFailure || 00537 StatusRegister.Bits.HostAdapterReady || 00538 StatusRegister.Bits.DataInRegisterReady) 00539 { 00540 break; 00541 } 00542 ScsiPortStallExecution(100); 00543 } 00544 00545 //device didn't respond to reset 00546 if (TimeoutCounter < 0) 00547 return FALSE; 00548 00549 // If Diagnostic Failure is set or Host Adapter Ready is reset, then an 00550 // error occurred during the Host Adapter diagnostics. If Data In Register 00551 // Ready is set, then there is an Error Code available. 00552 if (StatusRegister.Bits.DiagnosticFailure || !StatusRegister.Bits.HostAdapterReady) 00553 { 00554 DebugPrint((ERROR, "\n BusLogic - Failure - HOST ADAPTER STATUS REGISTER = %02X\n", StatusRegister.All)); 00555 00556 if (StatusRegister.Bits.DataInRegisterReady) 00557 { 00558 DebugPrint((ERROR, "HOST ADAPTER ERROR CODE = %d\n", BusLogic_ReadDataInRegister(HostAdapter))); 00559 } 00560 return FALSE; 00561 } 00562 00563 // Indicate the Host Adapter Hard Reset completed successfully. 00564 return TRUE; 00565 }// end BusLogic_HardwareResetHostAdapter 00566 00567 00568 BOOLEAN 00569 BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter) 00570 //_________________________________________________________________________ 00571 // Routine Description: BusLogic_CheckHostAdapter checks to be sure this 00572 // really is a BusLogic 00573 // Arguments: 00574 // 1. Host Adapter Structure 00575 // Return Value: 00576 // TRUE : Buslogic adapter detected 00577 // FALSE : Card is not a Buslogic adapter 00578 //_________________________________________________________________________ 00579 { 00580 BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; 00581 BusLogic_RequestedReplyLength_T RequestedReplyLength; 00582 BOOLEAN Result = TRUE; 00583 00584 DebugPrint((TRACE, "\n BusLogic - Inside BusLogic_CheckHostAdapter function \n")); 00585 00586 // 00587 // Issue the Inquire Extended Setup Information command. Only genuine 00588 // BusLogic Host Adapters and TRUE clones support this command. Adaptec 1542C 00589 // series Host Adapters that respond to the Geometry Register I/O port will 00590 // fail this command. 00591 RequestedReplyLength = sizeof(ExtendedSetupInformation); 00592 if (BusLogic_Command(HostAdapter, 00593 BusLogic_InquireExtendedSetupInformation, 00594 &RequestedReplyLength, 00595 sizeof(RequestedReplyLength), 00596 &ExtendedSetupInformation, 00597 sizeof(ExtendedSetupInformation)) 00598 != sizeof(ExtendedSetupInformation)) 00599 { 00600 Result = FALSE; 00601 } 00602 return Result; 00603 }// end BusLogic_CheckHostAdapter 00604 00605 int 00606 BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter, 00607 BusLogic_OperationCode_T OperationCode, 00608 void *ParameterData, 00609 int ParameterLength, 00610 void *ReplyData, 00611 int ReplyLength) 00612 //______________________________________________________________________________________________ 00613 // Routine Description: 00614 // BusLogic_Command sends the command OperationCode to HostAdapter, optionally 00615 // providing ParameterLength bytes of ParameterData and receiving at most 00616 // ReplyLength bytes of ReplyData; any excess reply data is received but 00617 // discarded. 00618 // 00619 // BusLogic_Command is called exclusively during host adapter detection and 00620 // initialization, so performance and latency are not critical, and exclusive 00621 // access to the Host Adapter hardware is assumed. Once the host adapter and 00622 // driver are initialized, the only Host Adapter command that is issued is the 00623 // single byte Execute Mailbox Command operation code, which does not require 00624 // waiting for the Host Adapter Ready bit to be set in the Status Register. 00625 // Arguments: 00626 // 1. HostAdapter - Host Adapter structure 00627 // 2. OperationCode - Operation code for the command 00628 // 3. ParameterData - Buffer containing parameters that needs to be passed as part 00629 // of the command 00630 // 4. ParameterLength - Number of parameters 00631 // 5. ReplyData - Buffer where reply data is copied 00632 // 6. ReplyLength - The length of the reply data 00633 // Return Value: 00634 // On success, this function returns the number of reply bytes read from 00635 // the Host Adapter (including any discarded data); on failure, it returns 00636 // -1 if the command was invalid, or -2 if a timeout occurred. 00637 //_________________________________________________________________________________________________ 00638 { 00639 UCHAR *ParameterPointer = (UCHAR *) ParameterData; 00640 UCHAR *ReplyPointer = (UCHAR *) ReplyData; 00641 BusLogic_StatusRegister_T StatusRegister; 00642 BusLogic_InterruptRegister_T InterruptRegister; 00643 int ReplyBytes = 0, Result; 00644 long TimeoutCounter; 00645 00646 // Clear out the Reply Data if provided. 00647 if (ReplyLength > 0) 00648 memset(ReplyData, 0, ReplyLength); 00649 00650 // If the IRQ Channel has not yet been acquired, then interrupts must be 00651 // disabled while issuing host adapter commands since a Command Complete 00652 // interrupt could occur if the IRQ Channel was previously enabled by another 00653 // BusLogic Host Adapter or another driver sharing the same IRQ Channel. 00654 00655 // Wait for the Host Adapter Ready bit to be set and the Command/Parameter 00656 // Register Busy bit to be reset in the Status Register. 00657 TimeoutCounter = 10000; 00658 while (--TimeoutCounter >= 0) 00659 { 00660 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 00661 if ( StatusRegister.Bits.HostAdapterReady && 00662 !StatusRegister.Bits.CommandParameterRegisterBusy) 00663 { 00664 break; 00665 } 00666 ScsiPortStallExecution(100); 00667 } 00668 if (TimeoutCounter < 0) 00669 { 00670 //BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready"; 00671 Result = -2; 00672 goto Done; 00673 } 00674 00675 // Write the OperationCode to the Command/Parameter Register. 00676 HostAdapter->HostAdapterCommandCompleted = FALSE; 00677 BusLogic_WriteCommandParameterRegister(HostAdapter, (UCHAR)OperationCode); 00678 00679 //Write any additional Parameter Bytes. 00680 TimeoutCounter = 10000; 00681 while (ParameterLength > 0 && --TimeoutCounter >= 0) 00682 { 00683 // 00684 // Wait 100 microseconds to give the Host Adapter enough time to determine 00685 // whether the last value written to the Command/Parameter Register was 00686 // valid or not. If the Command Complete bit is set in the Interrupt 00687 // Register, then the Command Invalid bit in the Status Register will be 00688 // reset if the Operation Code or Parameter was valid and the command 00689 // has completed, or set if the Operation Code or Parameter was invalid. 00690 // If the Data In Register Ready bit is set in the Status Register, then 00691 // the Operation Code was valid, and data is waiting to be read back 00692 // from the Host Adapter. Otherwise, wait for the Command/Parameter 00693 // Register Busy bit in the Status Register to be reset. 00694 00695 ScsiPortStallExecution(100); 00696 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); 00697 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 00698 if (InterruptRegister.Bits.CommandComplete) 00699 break; 00700 if (HostAdapter->HostAdapterCommandCompleted) 00701 break; 00702 if (StatusRegister.Bits.DataInRegisterReady) 00703 break; 00704 if (StatusRegister.Bits.CommandParameterRegisterBusy) 00705 continue; 00706 BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++); 00707 ParameterLength--; 00708 } 00709 if (TimeoutCounter < 0) 00710 { 00711 //BusLogic_CommandFailureReason = "Timeout waiting for Parameter Acceptance"; 00712 Result = -2; 00713 goto Done; 00714 } 00715 00716 // The Modify I/O Address command does not cause a Command Complete Interrupt. 00717 if (OperationCode == BusLogic_ModifyIOAddress) 00718 { 00719 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 00720 if (StatusRegister.Bits.CommandInvalid) 00721 { 00722 //BusLogic_CommandFailureReason = "Modify I/O Address Invalid"; 00723 Result = -1; 00724 goto Done; 00725 } 00726 Result = 0; 00727 goto Done; 00728 } 00729 00730 // Select an appropriate timeout value for awaiting command completion. 00731 switch (OperationCode) 00732 { 00733 case BusLogic_InquireInstalledDevicesID0to7: 00734 case BusLogic_InquireInstalledDevicesID8to15: 00735 case BusLogic_InquireTargetDevices: 00736 // Approximately 60 seconds. 00737 TimeoutCounter = 60*10000; 00738 break; 00739 default: 00740 // Approximately 1 second. 00741 TimeoutCounter = 10000; 00742 break; 00743 } 00744 00745 // 00746 // Receive any Reply Bytes, waiting for either the Command Complete bit to 00747 // be set in the Interrupt Register, or for the Interrupt Handler to set the 00748 // Host Adapter Command Completed bit in the Host Adapter structure. 00749 while (--TimeoutCounter >= 0) 00750 { 00751 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); 00752 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 00753 if (InterruptRegister.Bits.CommandComplete) 00754 break; 00755 if (HostAdapter->HostAdapterCommandCompleted) 00756 break; 00757 if (StatusRegister.Bits.DataInRegisterReady) 00758 { 00759 if (++ReplyBytes <= ReplyLength) 00760 { 00761 *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter); 00762 } 00763 else 00764 { 00765 BusLogic_ReadDataInRegister(HostAdapter); 00766 } 00767 } 00768 if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && 00769 StatusRegister.Bits.HostAdapterReady) 00770 { 00771 break; 00772 } 00773 ScsiPortStallExecution(100); 00774 } 00775 if (TimeoutCounter < 0) 00776 { 00777 //BusLogic_CommandFailureReason = "Timeout waiting for Command Complete"; 00778 Result = -2; 00779 goto Done; 00780 } 00781 00782 // Clear any pending Command Complete Interrupt. 00783 BusLogic_InterruptReset(HostAdapter); 00784 00785 // Process Command Invalid conditions. 00786 if (StatusRegister.Bits.CommandInvalid) 00787 { 00788 // 00789 // Some early BusLogic Host Adapters may not recover properly from 00790 // a Command Invalid condition, so if this appears to be the case, 00791 // a Soft Reset is issued to the Host Adapter. Potentially invalid 00792 // commands are never attempted after Mailbox Initialization is 00793 // performed, so there should be no Host Adapter state lost by a 00794 // Soft Reset in response to a Command Invalid condition. 00795 00796 ScsiPortStallExecution(1000); 00797 StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); 00798 if (StatusRegister.Bits.CommandInvalid || 00799 StatusRegister.Bits.Reserved || 00800 StatusRegister.Bits.DataInRegisterReady || 00801 StatusRegister.Bits.CommandParameterRegisterBusy || 00802 !StatusRegister.Bits.HostAdapterReady || 00803 !StatusRegister.Bits.InitializationRequired || 00804 StatusRegister.Bits.DiagnosticActive || 00805 StatusRegister.Bits.DiagnosticFailure) 00806 { 00807 BusLogic_SoftReset(HostAdapter); 00808 ScsiPortStallExecution(1000); 00809 } 00810 //BusLogic_CommandFailureReason = "Command Invalid"; 00811 Result = -1; 00812 goto Done; 00813 } 00814 00815 // Handle Excess Parameters Supplied conditions. 00816 if (ParameterLength > 0) 00817 { 00818 //BusLogic_CommandFailureReason = "Excess Parameters Supplied"; 00819 Result = -1; 00820 goto Done; 00821 } 00822 00823 // Indicate the command completed successfully. 00824 Result = ReplyBytes; 00825 00826 // Restore the interrupt status if necessary and return. 00827 Done: 00828 return Result; 00829 }// end BusLogic_Command 00830 00831 00832 BOOLEAN 00833 BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T *HostAdapter) 00834 //___________________________________________________________________________________________ 00835 // Routine Description: 00836 // BusLogic_ReadHostAdapterConfiguration reads the Configuration Information 00837 // from Host Adapter and initializes the Host Adapter structure. 00838 // Arguments: 00839 // 1. Host adapter structure 00840 // Return Value: 00841 // TRUE : Configuration read properly 00842 // FALSE : Encounter failure 00843 //___________________________________________________________________________________________ 00844 { 00845 BusLogic_BoardID_T BoardID; 00846 BusLogic_Configuration_T Configuration; 00847 BusLogic_SetupInformation_T SetupInformation; 00848 BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation; 00849 BusLogic_HostAdapterModelNumber_T HostAdapterModelNumber; 00850 BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit; 00851 BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter; 00852 BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation; 00853 BusLogic_FetchHostAdapterLocalRAMRequest_T FetchHostAdapterLocalRAMRequest; 00854 BusLogic_AutoSCSIData_T AutoSCSIData; 00855 BusLogic_GeometryRegister_T GeometryRegister; 00856 BusLogic_RequestedReplyLength_T RequestedReplyLength; 00857 UCHAR *TargetPointer, Character; 00858 ULONG /*TargetID,*/ i; 00859 00860 00861 // Issue the Inquire Board ID command. 00862 if (BusLogic_Command(HostAdapter, 00863 BusLogic_InquireBoardID, 00864 NULL, 00865 0, 00866 &BoardID, sizeof(BoardID)) 00867 != sizeof(BoardID)) 00868 { 00869 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE BOARD ID\n")); 00870 return FALSE; 00871 } 00872 00873 // Issue the Inquire Configuration command. 00874 if (BusLogic_Command(HostAdapter, 00875 BusLogic_InquireConfiguration, 00876 NULL, 00877 0, 00878 &Configuration, sizeof(Configuration)) 00879 != sizeof(Configuration)) 00880 { 00881 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE CONFIGURATION\n")); 00882 return FALSE; 00883 } 00884 00885 // Issue the Inquire Setup Information command. 00886 RequestedReplyLength = sizeof(SetupInformation); 00887 if (BusLogic_Command(HostAdapter, 00888 BusLogic_InquireSetupInformation, 00889 &RequestedReplyLength, 00890 sizeof(RequestedReplyLength), 00891 &SetupInformation, 00892 sizeof(SetupInformation)) 00893 != sizeof(SetupInformation)) 00894 { 00895 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE SETUP INFORMATION\n")); 00896 return FALSE; 00897 } 00898 00899 // Issue the Inquire Extended Setup Information command. 00900 RequestedReplyLength = sizeof(ExtendedSetupInformation); 00901 if (BusLogic_Command(HostAdapter, 00902 BusLogic_InquireExtendedSetupInformation, 00903 &RequestedReplyLength, 00904 sizeof(RequestedReplyLength), 00905 &ExtendedSetupInformation, 00906 sizeof(ExtendedSetupInformation)) 00907 != sizeof(ExtendedSetupInformation)) 00908 { 00909 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE EXTENDED SETUP INFORMATION\n")); 00910 return FALSE; 00911 } 00912 00913 // Issue the Inquire Firmware Version 3rd Digit command. 00914 FirmwareVersion3rdDigit = '\0'; 00915 if (BoardID.FirmwareVersion1stDigit > '0') 00916 { 00917 if (BusLogic_Command(HostAdapter, 00918 BusLogic_InquireFirmwareVersion3rdDigit, 00919 NULL, 00920 0, 00921 &FirmwareVersion3rdDigit, 00922 sizeof(FirmwareVersion3rdDigit)) 00923 != sizeof(FirmwareVersion3rdDigit)) 00924 { 00925 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE FIRMWARE 3RD DIGIT\n")); 00926 return FALSE; 00927 } 00928 } 00929 00930 // Issue the Inquire Host Adapter Model Number command. 00931 RequestedReplyLength = sizeof(HostAdapterModelNumber); 00932 if (BusLogic_Command(HostAdapter, 00933 BusLogic_InquireHostAdapterModelNumber, 00934 &RequestedReplyLength, 00935 sizeof(RequestedReplyLength), 00936 &HostAdapterModelNumber, 00937 sizeof(HostAdapterModelNumber)) 00938 != sizeof(HostAdapterModelNumber)) 00939 { 00940 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE HOST ADAPTER MODEL NUMBER\n")); 00941 return FALSE; 00942 } 00943 00944 // BusLogic MultiMaster Host Adapters can be identified by their model number 00945 // and the major version number of their firmware as follows: 00946 // 00947 // 5.xx BusLogic "W" Series Host Adapters: 00948 // BT-948/958/958D 00949 // Save the Model Name and Host Adapter Name in the Host Adapter structure. 00950 TargetPointer = HostAdapter->ModelName; 00951 *TargetPointer++ = 'B'; 00952 *TargetPointer++ = 'T'; 00953 *TargetPointer++ = '-'; 00954 for (i = 0; i < sizeof(HostAdapterModelNumber); i++) 00955 { 00956 Character = HostAdapterModelNumber[i]; 00957 if (Character == ' ' || Character == '\0') break; 00958 *TargetPointer++ = Character; 00959 } 00960 *TargetPointer++ = '\0'; 00961 00962 // Save the Firmware Version in the Host Adapter structure. 00963 TargetPointer = HostAdapter->FirmwareVersion; 00964 *TargetPointer++ = BoardID.FirmwareVersion1stDigit; 00965 *TargetPointer++ = '.'; 00966 *TargetPointer++ = BoardID.FirmwareVersion2ndDigit; 00967 if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0') 00968 *TargetPointer++ = FirmwareVersion3rdDigit; 00969 *TargetPointer = '\0'; 00970 00971 // Issue the Inquire Firmware Version Letter command. 00972 if (strcmp((char*)HostAdapter->FirmwareVersion, "3.3") >= 0) 00973 { 00974 if (BusLogic_Command(HostAdapter, 00975 BusLogic_InquireFirmwareVersionLetter, 00976 NULL, 00977 0, 00978 &FirmwareVersionLetter, 00979 sizeof(FirmwareVersionLetter)) 00980 != sizeof(FirmwareVersionLetter)) 00981 { 00982 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE FIRMWARE VERSION LETTER\n")); 00983 return FALSE; 00984 } 00985 if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0') 00986 { 00987 *TargetPointer++ = FirmwareVersionLetter; 00988 } 00989 *TargetPointer = '\0'; 00990 } 00991 00992 00993 // Save the Host Adapter SCSI ID in the Host Adapter structure. 00994 HostAdapter->SCSI_ID = Configuration.HostAdapterID; 00995 00996 // Determine the Bus Type and save it in the Host Adapter structure, determine 00997 // and save the IRQ Channel if necessary, and determine and save the DMA 00998 // Channel for ISA Host Adapters. 00999 HostAdapter->HostAdapterBusType = BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4']; 01000 01001 GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); 01002 01003 // Determine whether Extended Translation is enabled and save it in 01004 // the Host Adapter structure. 01005 // HostAdapter->ExtendedTranslationEnabled = GeometryRegister.Bits.ExtendedTranslationEnabled; 01006 HostAdapter->ExtendedTranslationEnabled = GeometryRegister.All; 01007 01008 01009 // Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide 01010 // SCSI flag, Differential SCSI flag, SCAM Supported flag, and 01011 // Ultra SCSI flag in the Host Adapter structure. 01012 HostAdapter->HostAdapterScatterGatherLimit = ExtendedSetupInformation.ScatterGatherLimit; 01013 01014 HostAdapter->DriverScatterGatherLimit = HostAdapter->HostAdapterScatterGatherLimit; 01015 01016 if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit) 01017 { 01018 HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit; 01019 } 01020 if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt) 01021 { 01022 HostAdapter->LevelSensitiveInterrupt = TRUE; 01023 } 01024 01025 HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI; 01026 01027 HostAdapter->HostDifferentialSCSI = ExtendedSetupInformation.HostDifferentialSCSI; 01028 01029 HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM; 01030 01031 HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI; 01032 01033 01034 // Determine whether Extended LUN Format CCBs are supported and save the 01035 // information in the Host Adapter structure. 01036 if (HostAdapter->FirmwareVersion[0] == '5' || 01037 (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI)) 01038 { 01039 HostAdapter->ExtendedLUNSupport = TRUE; 01040 } 01041 // Issue the Inquire PCI Host Adapter Information command to read the 01042 // Termination Information from "W" series MultiMaster Host Adapters. 01043 if (HostAdapter->FirmwareVersion[0] == '5') 01044 { 01045 if (BusLogic_Command(HostAdapter, 01046 BusLogic_InquirePCIHostAdapterInformation, 01047 NULL, 01048 0, 01049 &PCIHostAdapterInformation, 01050 sizeof(PCIHostAdapterInformation)) 01051 != sizeof(PCIHostAdapterInformation)) 01052 { 01053 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE PCI HOST ADAPTER INFORMATION\n")); 01054 return FALSE; 01055 } 01056 01057 // Save the Termination Information in the Host Adapter structure. 01058 if (PCIHostAdapterInformation.GenericInfoValid) 01059 { 01060 HostAdapter->TerminationInfoValid = TRUE; 01061 HostAdapter->LowByteTerminated = PCIHostAdapterInformation.LowByteTerminated; 01062 HostAdapter->HighByteTerminated = PCIHostAdapterInformation.HighByteTerminated; 01063 } 01064 } 01065 01066 // Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data 01067 // from "W" and "C" series MultiMaster Host Adapters. 01068 if (HostAdapter->FirmwareVersion[0] >= '4') 01069 { 01070 FetchHostAdapterLocalRAMRequest.ByteOffset = BusLogic_AutoSCSI_BaseOffset; 01071 FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData); 01072 if (BusLogic_Command(HostAdapter, 01073 BusLogic_FetchHostAdapterLocalRAM, 01074 &FetchHostAdapterLocalRAMRequest, 01075 sizeof(FetchHostAdapterLocalRAMRequest), 01076 &AutoSCSIData, 01077 sizeof(AutoSCSIData)) 01078 != sizeof(AutoSCSIData)) 01079 { 01080 DebugPrint((ERROR, "\n BusLogic - Failure: FETCH HOST ADAPTER LOCAL RAM\n")); 01081 return FALSE; 01082 } 01083 // Save the Parity Checking Enabled, Bus Reset Enabled, and Termination 01084 // Information in the Host Adapter structure. 01085 HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled; 01086 HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled; 01087 01088 // Save the Wide Permitted, Fast Permitted, Synchronous Permitted, 01089 // Disconnect Permitted, Ultra Permitted, and SCAM Information in the 01090 // Host Adapter structure. 01091 HostAdapter->WidePermitted = AutoSCSIData.WidePermitted; 01092 HostAdapter->FastPermitted = AutoSCSIData.FastPermitted; 01093 HostAdapter->SynchronousPermitted = AutoSCSIData.SynchronousPermitted; 01094 HostAdapter->DisconnectPermitted = AutoSCSIData.DisconnectPermitted; 01095 if (HostAdapter->HostUltraSCSI) 01096 { 01097 HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted; 01098 } 01099 if (HostAdapter->HostSupportsSCAM) 01100 { 01101 HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled; 01102 HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2; 01103 } 01104 } 01105 01106 // Determine the maximum number of Target IDs and Logical Units supported by 01107 // this driver for Wide and Narrow Host Adapters. 01108 HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8); 01109 HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8); 01110 01111 // Select appropriate values for the Mailbox Count, 01112 // Initial CCBs, and Incremental CCBs variables based on whether or not Strict 01113 // Round Robin Mode is supported. If Strict Round Robin Mode is supported, 01114 // then there is no performance degradation in using the maximum possible 01115 // number of Outgoing and Incoming Mailboxes and allowing the Tagged and 01116 // Untagged Queue Depths to determine the actual utilization. If Strict Round 01117 // Robin Mode is not supported, then the Host Adapter must scan all the 01118 // Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can 01119 // cause a substantial performance penalty. The host adapters actually have 01120 // room to store the following number of CCBs internally; that is, they can 01121 // internally queue and manage this many active commands on the SCSI bus 01122 // simultaneously. Performance measurements demonstrate that the Driver Queue 01123 // Depth should be set to the Mailbox Count, rather than the Host Adapter 01124 // Queue Depth (internal CCB capacity), as it is more efficient to have the 01125 // queued commands waiting in Outgoing Mailboxes if necessary than to block 01126 // the process in the higher levels of the SCSI Subsystem. 01127 // 01128 // 192 BT-948/958/958D 01129 if (HostAdapter->FirmwareVersion[0] == '5') 01130 { 01131 HostAdapter->HostAdapterQueueDepth = 192; 01132 } 01133 01134 if (strcmp((char*)HostAdapter->FirmwareVersion, "3.31") >= 0) 01135 { 01136 HostAdapter->StrictRoundRobinModeSupport = TRUE; 01137 HostAdapter->MailboxCount = BusLogic_MaxMailboxes; 01138 } 01139 01140 // 01141 // Tagged Queuing support is available and operates properly on all "W" series 01142 // MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with 01143 // firmware version 4.22 and above, and on "S" series MultiMaster Host 01144 // Adapters with firmware version 3.35 and above. 01145 HostAdapter->TaggedQueuingPermitted = 0xFFFF; 01146 01147 // 01148 // Determine the Host Adapter BIOS Address if the BIOS is enabled and 01150 // BIOS_Address is 0. 01151 HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12; 01152 01153 // 01154 //Initialize parameters for MultiMaster Host Adapters. 01155 01156 // 01157 // Initialize the Host Adapter Full Model Name from the Model Name. 01158 strcpy((char*)HostAdapter->FullModelName, "BusLogic "); 01159 strcat((char*)HostAdapter->FullModelName, (char*)HostAdapter->ModelName); 01160 01161 // Tagged Queuing is only allowed if Disconnect/Reconnect is permitted. 01162 // Therefore, mask the Tagged Queuing Permitted Default bits with the 01163 // Disconnect/Reconnect Permitted bits. 01164 HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted; 01165 01166 // Select an appropriate value for Bus Settle Time either from a BusLogic 01167 // Driver Options specification, or from BusLogic_DefaultBusSettleTime. 01168 HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime; 01169 01170 // Indicate reading the Host Adapter Configuration completed successfully. 01171 return TRUE; 01172 }// end BusLogic_ReadHostAdapterConfiguration 01173 01174 BOOLEAN 01175 BusLogic_InitializeHostAdapter(PHW_DEVICE_EXTENSION deviceExtension, 01176 PPORT_CONFIGURATION_INFORMATION ConfigInfo) 01177 //_____________________________________________________________________________________________ 01178 // Routine Description: 01179 // BusLogic_InitializeHostAdapter initializes Host Adapter. This is the only 01180 // function called during SCSI Host Adapter detection which modifies the state 01181 // of the Host Adapter from its initial power on or hard reset state. 01182 // Arguments: 01183 // 1. device extension 01184 // 2. port config information 01185 // Return Value: 01186 // TRUE : Host Adapter initialization completed successfully 01187 // FALSE : Initialization failed 01188 //______________________________________________________________________________________________ 01189 { 01190 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 01191 BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest; 01192 UCHAR RoundRobinModeRequest; 01193 UCHAR SetCCBFormatRequest; 01194 int TargetID, LunID; 01195 01196 // Used when we get the Physical address of the mail boxes 01197 ULONG length; 01198 01199 // Initialize the pointers to the first and last CCBs that are queued for 01200 // completion processing. 01201 HostAdapter->FirstCompletedCCB = NULL; 01202 HostAdapter->LastCompletedCCB = NULL; 01203 01204 // Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active, 01205 // Command Successful Flag, Active Commands, and Commands Since Reset 01206 // for each Target Device. 01207 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) 01208 { 01209 HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; 01210 HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = FALSE; 01211 HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = FALSE; 01212 01213 HostAdapter->ActiveCommandsPerTarget[TargetID] = 0; 01214 for (LunID = 0; LunID < HostAdapter->MaxLogicalUnits; LunID++) 01215 HostAdapter->ActiveCommandsPerLun[TargetID][LunID] = 0; 01216 01217 HostAdapter->CommandsSinceReset[TargetID] = 0; 01218 } 01219 01220 // Convert virtual to physical mailbox address. 01221 deviceExtension->NoncachedExtension->MailboxPA = ScsiPortConvertPhysicalAddressToUlong( 01222 ScsiPortGetPhysicalAddress(deviceExtension, 01223 NULL, 01224 deviceExtension->NoncachedExtension->MailboxOut, 01225 &length)); 01226 01227 HostAdapter->FirstOutgoingMailbox = (BusLogic_OutgoingMailbox_T *) deviceExtension->NoncachedExtension->MailboxOut; 01228 HostAdapter->LastOutgoingMailbox = HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1; 01229 HostAdapter->NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; 01230 01231 HostAdapter->FirstIncomingMailbox = (BusLogic_IncomingMailbox_T *) deviceExtension->NoncachedExtension->MailboxIn; 01232 HostAdapter->LastIncomingMailbox = HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1; 01233 HostAdapter->NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; 01234 01235 // Initialize the Outgoing and Incoming Mailbox structures. 01236 memset(HostAdapter->FirstOutgoingMailbox, 01237 0, 01238 HostAdapter->MailboxCount * sizeof(BusLogic_OutgoingMailbox_T)); 01239 memset(HostAdapter->FirstIncomingMailbox, 01240 0, 01241 HostAdapter->MailboxCount * sizeof(BusLogic_IncomingMailbox_T)); 01242 01243 01244 ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount; 01245 ExtendedMailboxRequest.BaseMailboxAddress = deviceExtension->NoncachedExtension->MailboxPA ; 01246 01247 if (BusLogic_Command(HostAdapter, 01248 BusLogic_InitializeExtendedMailbox, 01249 &ExtendedMailboxRequest, 01250 sizeof(ExtendedMailboxRequest), 01251 NULL, 0) 01252 < 0) 01253 { 01254 DebugPrint((ERROR, "\n BusLogic - Failure: MAILBOX INITIALIZATION\n")); 01255 return FALSE; 01256 } 01257 01258 // Enable Strict Round Robin Mode if supported by the Host Adapter. In 01259 // Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing 01260 // Mailbox for each new command, rather than scanning through all the 01261 // Outgoing Mailboxes to find any that have new commands in them. Strict 01262 // Round Robin Mode is significantly more efficient. 01263 if (HostAdapter->StrictRoundRobinModeSupport) 01264 { 01265 RoundRobinModeRequest = BusLogic_StrictRoundRobinMode; 01266 if (BusLogic_Command(HostAdapter, 01267 BusLogic_EnableStrictRoundRobinMode, 01268 &RoundRobinModeRequest, 01269 sizeof(RoundRobinModeRequest), 01270 NULL, 01271 0) 01272 < 0) 01273 { 01274 DebugPrint((ERROR, "\n BusLogic - Failure: ENABLE STRICT ROUND ROBIN MODE\n")); 01275 return FALSE; 01276 } 01277 } 01278 01279 // For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB 01280 // Format command to allow 32 Logical Units per Target Device. 01281 01282 if (HostAdapter->ExtendedLUNSupport) 01283 { 01284 SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB; 01285 if (BusLogic_Command(HostAdapter, 01286 BusLogic_SetCCBFormat, 01287 &SetCCBFormatRequest, 01288 sizeof(SetCCBFormatRequest), 01289 NULL, 01290 0) 01291 < 0) 01292 { 01293 DebugPrint((ERROR, "\n BusLogic - Failure: SET CCB FORMAT\n")); 01294 return FALSE; 01295 } 01296 } 01297 01298 // Announce Successful Initialization. 01299 if (!HostAdapter->HostAdapterInitialized) 01300 { 01301 DebugPrint((INFO, "\n BusLogic - %s Initialized Successfully\n", 01302 HostAdapter, HostAdapter->FullModelName)); 01303 } 01304 else 01305 { 01306 DebugPrint((WARNING, "\n BusLogic - %s not initialized Successfully\n", 01307 HostAdapter, HostAdapter->FullModelName)); 01308 } 01309 HostAdapter->HostAdapterInitialized = TRUE; 01310 // Indicate the Host Adapter Initialization completed successfully. 01311 return TRUE; 01312 }// end BusLogic_InitializeHostAdapter 01313 01314 01315 BOOLEAN 01316 BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T *HostAdapter) 01317 //_________________________________________________________________________________________ 01318 // Routine Description: 01319 // BusLogic_TargetDeviceInquiry inquires about the Target Devices accessible 01320 // through Host Adapter. 01321 // Arguments: 01322 // 1. Host Adpater structure 01323 // 2. 01324 // Return Value: 01325 // TRUE : Inquiry successful 01326 // FALSE : Inquiry failed 01327 //_________________________________________________________________________ 01328 { 01329 BusLogic_InstalledDevices_T InstalledDevices; 01330 // BusLogic_InstalledDevices8_T InstalledDevicesID0to7; 01331 BusLogic_SetupInformation_T SetupInformation; 01332 BusLogic_SynchronousPeriod_T SynchronousPeriod; 01333 BusLogic_RequestedReplyLength_T RequestedReplyLength; 01334 int TargetID; 01335 01336 // Wait a few seconds between the Host Adapter Hard Reset which initiates 01337 // a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get 01338 // confused if they receive SCSI Commands too soon after a SCSI Bus Reset. 01339 ScsiPortStallExecution(HostAdapter->BusSettleTime); 01340 01341 // 01342 // Issue the Inquire Target Devices command for host adapters with firmware 01343 // version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command 01344 // for older host adapters. This is necessary to force Synchronous Transfer 01345 // Negotiation so that the Inquire Setup Information and Inquire Synchronous 01346 // Period commands will return valid data. The Inquire Target Devices command 01347 // is preferable to Inquire Installed Devices ID 0 to 7 since it only probes 01348 // Logical Unit 0 of each Target Device. 01349 if (strcmp((char*)HostAdapter->FirmwareVersion, "4.25") >= 0) 01350 { 01351 if (BusLogic_Command(HostAdapter, 01352 BusLogic_InquireTargetDevices, 01353 NULL, 01354 0, 01355 &InstalledDevices, 01356 sizeof(InstalledDevices)) 01357 != sizeof(InstalledDevices)) 01358 { 01359 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE TARGET DEVICES\n")); 01360 return FALSE; 01361 } 01362 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) 01363 { 01364 HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevices & (1 << TargetID) ? TRUE : FALSE); 01365 } 01366 } 01367 01368 // Issue the Inquire Setup Information command. 01369 RequestedReplyLength = sizeof(SetupInformation); 01370 if (BusLogic_Command(HostAdapter, 01371 BusLogic_InquireSetupInformation, 01372 &RequestedReplyLength, 01373 sizeof(RequestedReplyLength), 01374 &SetupInformation, sizeof(SetupInformation)) 01375 != sizeof(SetupInformation)) 01376 { 01377 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE SETUP INFORMATION\n")); 01378 return FALSE; 01379 } 01380 01381 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) 01382 { 01383 HostAdapter->SynchronousOffset[TargetID] = (TargetID < 8 01384 ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset 01385 : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset); 01386 } 01387 if (strcmp((char*)HostAdapter->FirmwareVersion, "5.06L") >= 0) 01388 { 01389 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) 01390 { 01391 HostAdapter->TargetFlags[TargetID].WideTransfersActive = (TargetID < 8 01392 ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID) 01393 ? TRUE : FALSE) 01394 : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8)) 01395 ? TRUE : FALSE)); 01396 } 01397 } 01398 01399 01400 // Issue the Inquire Synchronous Period command. 01401 if (HostAdapter->FirmwareVersion[0] >= '3') 01402 { 01403 RequestedReplyLength = sizeof(SynchronousPeriod); 01404 if (BusLogic_Command(HostAdapter, 01405 BusLogic_InquireSynchronousPeriod, 01406 &RequestedReplyLength, 01407 sizeof(RequestedReplyLength), 01408 &SynchronousPeriod, 01409 sizeof(SynchronousPeriod)) 01410 != sizeof(SynchronousPeriod)) 01411 { 01412 DebugPrint((ERROR, "\n BusLogic - Failure: INQUIRE SYNCHRONOUS PERIOD\n")); 01413 return FALSE; 01414 } 01415 for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++) 01416 { 01417 HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID]; 01418 } 01419 } 01420 01421 // Indicate the Target Device Inquiry completed successfully. 01422 return TRUE; 01423 }// end BusLogic_TargetDeviceInquiry 01424 01425 VOID BusLogic_InitializeCCB( PBuslogic_CCB_T CCB) 01426 { 01427 CCB->Opcode = BusLogic_InitiatorCCB; 01428 CCB->DataDirection = 0; 01429 CCB->TagEnable = 0; 01430 CCB->QueueTag = 0 ; 01431 CCB->CDB_Length = 0; 01432 CCB->SenseDataLength = 0; 01433 CCB->DataLength = 0; 01434 CCB->DataPointer = 0; 01435 CCB->HostAdapterStatus = 0; 01436 CCB->TargetDeviceStatus = 0; 01437 CCB->TargetID = 0; 01438 CCB->LogicalUnit = 0; 01439 CCB->LegacyTagEnable = 0; 01440 CCB->LegacyQueueTag = 0; 01441 01442 CCB->SenseDataPointer = 0; 01443 01444 // BusLogic Driver Defined Portion 01445 CCB->Status = 0; 01446 CCB->SerialNumber = 0; 01447 CCB->Next = NULL; 01448 CCB->HostAdapter = NULL; 01449 01450 CCB->CompletionCode = 0; 01451 // Pointer to the CCB 01452 CCB->SrbAddress = NULL; 01453 CCB->AbortSrb = NULL; 01454 } 01455 01456 BOOLEAN 01457 NTAPI 01458 BT958HwStartIO(IN PVOID HwDeviceExtension, 01459 IN PSCSI_REQUEST_BLOCK Srb 01460 ) 01461 //__________________________________________________________________________________ 01462 // Routine Description: 01463 // As soon as it receives the initial request for a 01464 // target peripheral, the OS-specific port driver calls 01465 // the HwScsiStartIo routine with an input SRB. After 01466 // this call, the HBA miniport driver owns the request 01467 // and is expected to complete it. 01468 // Arguments: 01469 // 1. DeviceExtension: Points to the miniport driver's per-HBA storage area. 01470 // 2. Srb: Points to the SCSI request block to be started. 01471 // Return Value: 01472 // TRUE : HwScsiStartIo returns TRUE to acknowledge receipt of the SRB. 01473 //__________________________________________________________________________________ 01474 { 01475 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 01476 // PNONCACHED_EXTENSION noncachedExtension = deviceExtension->NoncachedExtension; 01477 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 01478 // BusLogic_OutgoingMailbox_T mailboxOut; 01479 PSCSI_REQUEST_BLOCK AbortSRB; 01480 01481 PBuslogic_CCB_T ccb; 01482 BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[Srb->TargetId]; 01483 01484 01485 DebugPrint((TRACE, "\n BusLogic - Inside Start IO routine\n")); 01486 01487 // Make sure that this request isn't too long for the adapter. If so 01488 // bounce it back as an invalid request 01489 if (BusLogic_CDB_MaxLength < Srb->CdbLength) 01490 { 01491 01492 DebugPrint((WARNING, "\n BusLogic - Srb->CdbLength [%d] > MaxCdbLength [%d]." 01493 " Invalid request\n", Srb->CdbLength, BusLogic_CDB_MaxLength)); 01494 01495 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; 01496 ScsiPortNotification(RequestComplete,deviceExtension,Srb); 01497 ScsiPortNotification(NextRequest,deviceExtension,NULL); 01498 return TRUE; 01499 } 01500 01501 switch (Srb->Function) 01502 { 01503 /* 01504 Sirish, 10th June 2002 01505 // Check if command is a WMI request. 01506 case SRB_FUNCTION_WMI: 01507 // Process the WMI request and return. 01508 return BT958WmiSrb(HwDeviceExtension, (PSCSI_WMI_REQUEST_BLOCK) Srb); 01509 */ 01510 01511 case SRB_FUNCTION_EXECUTE_SCSI: 01512 01513 // get the ccb structure from the extension 01514 ccb = Srb->SrbExtension; 01515 BusLogic_InitializeCCB(ccb); 01516 01517 // Save SRB back pointer in CCB. 01518 ccb->SrbAddress = Srb; 01519 01520 // Build CCB. - Have some way of knowing that a srb has already been 01521 // completed and you just need to return from here 01522 BusLogic_QueueCommand(HwDeviceExtension ,Srb, ccb); 01523 01524 // Place the CCB in an Outgoing Mailbox. The higher levels of the SCSI 01525 // Subsystem should not attempt to queue more commands than can be placed 01526 // in Outgoing Mailboxes, so there should always be one free. In the 01527 // unlikely event that there are none available, wait 1 second and try 01528 // again. If that fails, the Host Adapter is probably hung so signal an 01529 // error as a Host Adapter Hard Reset should be initiated soon. 01530 01531 if (!BusLogic_WriteOutgoingMailbox(deviceExtension , BusLogic_MailboxStartCommand, ccb)) 01532 { 01533 DebugPrint((ERROR, "\n BusLogic - Unable to write Outgoing Mailbox - " 01534 "Pausing for 1 second\n")); 01535 ScsiPortStallExecution(1000); 01536 if (!BusLogic_WriteOutgoingMailbox(deviceExtension , BusLogic_MailboxStartCommand, ccb)) 01537 { 01538 DebugPrint((ERROR, "\n BusLogic - Still unable to write Outgoing" 01539 "Mailbox - Host Adapter Dead?\n")); 01540 01541 Srb->SrbStatus = SRB_STATUS_ERROR; 01542 ScsiPortNotification(RequestComplete,deviceExtension,Srb); 01543 ScsiPortNotification(NextRequest,deviceExtension,NULL); 01544 01545 } 01546 } 01547 else 01548 { 01549 /* 01550 * Reverted to pre 1.1.0.0 control flow 01551 * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts 01552 * And the fix for that in 1.1.0.1 causes BSODs in XP 01553 * Side note: Ben: the Buslogic emulation never exports more than 1 lun 01554 */ 01555 if (TargetFlags->TaggedQueuingActive 01556 && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS) { 01557 ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); 01558 } 01559 else { 01560 ScsiPortNotification(NextRequest,deviceExtension,NULL); 01561 } 01562 } 01563 return TRUE; 01564 01565 case SRB_FUNCTION_ABORT_COMMAND: 01566 01567 // Get CCB to abort. 01568 ccb = Srb->NextSrb->SrbExtension; 01569 01570 // Set abort SRB for completion. 01571 ccb->AbortSrb = Srb; 01572 01573 AbortSRB = ScsiPortGetSrb(HwDeviceExtension, 01574 Srb->PathId, 01575 Srb->TargetId, 01576 Srb->Lun, 01577 Srb->QueueTag); 01578 01579 if ((AbortSRB != Srb->NextSrb) || (AbortSRB->SrbStatus != SRB_STATUS_PENDING)) 01580 { 01581 Srb->SrbStatus = SRB_STATUS_ABORT_FAILED; 01582 ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb); 01583 ScsiPortNotification(NextRequest, HwDeviceExtension, NULL); 01584 return TRUE; 01585 } 01586 01587 // write the abort information into a mailbox 01588 if (BusLogic_WriteOutgoingMailbox( deviceExtension, BusLogic_MailboxAbortCommand, ccb)) 01589 { 01590 DebugPrint((WARNING, "\n BusLogic - Aborting CCB #%ld to Target %d\n", 01591 ccb->SerialNumber, Srb->TargetId)); 01592 // Adapter ready for next request. 01593 01594 /* 01595 * Reverted to pre 1.1.0.0 control flow 01596 * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts 01597 * And the fix for that in 1.1.0.1 causes BSODs in XP 01598 * Side note: Ben: the Buslogic emulation never exports more than 1 lun 01599 */ 01600 if (TargetFlags->TaggedQueuingActive 01601 && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS) { 01602 ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); 01603 } 01604 else { 01605 ScsiPortNotification(NextRequest,deviceExtension,NULL); 01606 } 01607 } 01608 else 01609 { 01610 DebugPrint((WARNING, "\n BusLogic - Unable to Abort CCB #%ld to Target %d" 01611 " - No Outgoing Mailboxes\n", ccb->SerialNumber, 01612 Srb->TargetId)); 01613 Srb->SrbStatus = SRB_STATUS_ERROR; 01614 ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb); 01615 ScsiPortNotification(NextRequest, HwDeviceExtension, NULL); 01616 } 01617 return TRUE; 01618 01619 01620 case SRB_FUNCTION_RESET_BUS: 01621 01622 // Reset SCSI bus. 01623 DebugPrint((INFO, "\n BusLogic - SRB_FUNCTION_RESET_BUS, srb=%x \n",Srb)); 01624 BT958HwResetBus(HwDeviceExtension, Srb->PathId); 01625 01626 Srb->SrbStatus = SRB_STATUS_SUCCESS; 01627 ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb); 01628 ScsiPortNotification(NextRequest, HwDeviceExtension, NULL); 01629 return TRUE; 01630 01631 01632 case SRB_FUNCTION_RESET_DEVICE: 01633 01634 ccb = Srb->SrbExtension; 01635 BusLogic_InitializeCCB(ccb); 01636 01637 // Save SRB back pointer in CCB. 01638 ccb->SrbAddress = Srb; 01639 01640 if(!BusLogic_SendBusDeviceReset(HostAdapter, Srb)) 01641 { 01642 BT958HwResetBus(HwDeviceExtension, SP_UNTAGGED); 01643 Srb->SrbStatus = SRB_STATUS_SUCCESS; 01644 ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb); 01645 ScsiPortNotification(NextRequest, HwDeviceExtension, NULL); 01646 return TRUE; 01647 } 01648 01649 /* 01650 * Reverted to pre 1.1.0.0 control flow 01651 * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts 01652 * And the fix for that in 1.1.0.1 causes BSODs in XP 01653 * Side note: Ben: the Buslogic emulation never exports more than 1 lun 01654 */ 01655 if (TargetFlags->TaggedQueuingActive 01656 && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS) { 01657 ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); 01658 } 01659 else { 01660 ScsiPortNotification(NextRequest,deviceExtension,NULL); 01661 } 01662 return TRUE; 01663 01664 default: 01665 01666 // Set error, complete request and signal ready for next request. 01667 Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; 01668 ScsiPortNotification(RequestComplete,deviceExtension,Srb); 01669 ScsiPortNotification(NextRequest,deviceExtension,NULL); 01670 01671 return TRUE; 01672 01673 } // end switch 01674 01675 }// end BusLogic_TargetDeviceInquiry 01676 01677 01678 BOOLEAN 01679 BusLogic_WriteOutgoingMailbox(PHW_DEVICE_EXTENSION deviceExtension , 01680 BusLogic_ActionCode_T ActionCode, 01681 BusLogic_CCB_T *CCB) 01682 //______________________________________________________________________________________________ 01683 // Routine Description: 01684 // BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing 01685 // Mailbox for execution by Host Adapter. The Host Adapter's Lock should 01686 // already have been acquired by the caller. 01687 01688 // Arguments: 01689 // 1. deviceExtension: device extension 01690 // 2. ActionCode : action code for the mailbox which can be 01691 // BusLogic_OutgoingMailboxFree = 0x00, 01692 // BusLogic_MailboxStartCommand = 0x01, 01693 // BusLogic_MailboxAbortCommand = 0x02 01694 // 3. CCB :The CCB that has to be written into the mailbox 01695 // Return Value: 01696 // TRUE : write to the mailbox was successful 01697 // FALSE : write failed 01698 //______________________________________________________________________________________________ 01699 { 01700 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 01701 BusLogic_OutgoingMailbox_T *NextOutgoingMailbox; 01702 ULONG length; 01703 01704 NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox; 01705 01706 if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree) 01707 { 01708 CCB->Status = BusLogic_CCB_Active; 01709 01710 // The CCB field must be written before the Action Code field since 01711 // the Host Adapter is operating asynchronously and the locking code 01712 // does not protect against simultaneous access by the Host Adapter. 01713 01714 // Get CCB physical address. 01715 NextOutgoingMailbox->CCB = ScsiPortConvertPhysicalAddressToUlong( ScsiPortGetPhysicalAddress(deviceExtension, 01716 NULL, 01717 CCB, 01718 &length)); 01719 01720 NextOutgoingMailbox->ActionCode = (UCHAR)ActionCode; 01721 01722 BusLogic_StartMailboxCommand(HostAdapter); 01723 01724 if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox) 01725 { 01726 NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox; 01727 } 01728 01729 HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox; 01730 if (ActionCode == BusLogic_MailboxStartCommand) 01731 { 01732 HostAdapter->ActiveCommandsPerTarget[CCB->TargetID]++; 01733 // check this Namita 01734 HostAdapter->ActiveCommandsPerLun[CCB->TargetID][CCB->LogicalUnit]++; 01735 if (CCB->Opcode != BusLogic_BusDeviceReset) 01736 { 01737 HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++; 01738 } 01739 } 01740 return TRUE; 01741 } 01742 return FALSE; 01743 }// end BusLogic_WriteOutgoingMailbox 01744 01745 01746 int 01747 BusLogic_QueueCommand(IN PVOID HwDeviceExtension , 01748 IN PSCSI_REQUEST_BLOCK Srb, 01749 PBuslogic_CCB_T CCB) 01750 //_________________________________________________________________________ 01751 // Routine Description: 01752 // BusLogic_QueueCommand creates a CCB for Command 01753 // Arguments: 01754 // 1. HwDeviceExtemsion: device extension 01755 // 2. Srb: Pointe to the SRB 01756 // 3. CCB: POinter to the buffer containing the space for CCB 01757 // Return Value: 01758 // Function returns 0 if successful 01759 //_________________________________________________________________________ 01760 { 01761 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 01762 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 01763 BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[Srb->TargetId]; 01764 BusLogic_TargetStatistics_T *TargetStatistics = HostAdapter->TargetStatistics; 01765 01766 ULONG length; 01767 01768 // UCHAR *Cdb = Srb->Cdb; 01769 // PCDB RealCdb ; 01770 UCHAR CDB_Length = Srb->CdbLength; 01771 UCHAR TargetID = Srb->TargetId; 01772 UCHAR LogicalUnit = Srb->Lun; 01773 // void *BufferPointer = Srb->DataBuffer; 01774 int BufferLength = Srb->DataTransferLength; 01775 01776 if (Srb->DataTransferLength > 0) 01777 { 01778 CCB->DataLength = Srb->DataTransferLength; 01779 01780 // Initialize the fields in the BusLogic Command Control Block (CCB). 01781 #if SG_SUPPORT 01782 { 01783 ULONG xferLength, remainLength; 01784 PVOID virtualAddress; 01785 UCHAR i = 0; 01786 01787 virtualAddress = Srb->DataBuffer; 01788 xferLength = Srb->DataTransferLength; 01789 remainLength = xferLength; 01790 /* Build scatter gather list */ 01791 do 01792 { 01793 CCB->ScatterGatherList[i].SegmentDataPointer = (ULONG)ScsiPortConvertPhysicalAddressToUlong( 01794 ScsiPortGetPhysicalAddress(HwDeviceExtension, 01795 Srb, 01796 virtualAddress, 01797 &length)); 01798 if ( length > remainLength ) 01799 length = remainLength; 01800 CCB->ScatterGatherList[i].SegmentByteCount = length; 01801 01802 virtualAddress = (PUCHAR) virtualAddress + length; 01803 if (length >= remainLength) 01804 remainLength = 0; 01805 else 01806 remainLength -= length; 01807 i++; 01808 } while ( remainLength > 0); 01809 01810 // For data transfers that have less than one scatter gather element, convert 01811 // CCB to one transfer without using SG element. This will clear up the data 01812 // overrun/underrun problem with small transfers that reak havoc with scanners 01813 // and CD-ROM's etc. This is the method employed in ASPI4DOS to avoid similar 01814 // problems. 01815 if (i > 1) 01816 { 01817 CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather; 01818 CCB->DataLength = i * sizeof(BusLogic_ScatterGatherSegment_T); 01819 virtualAddress = (PVOID) & (CCB->ScatterGatherList); 01820 CCB->DataPointer = ScsiPortConvertPhysicalAddressToUlong( 01821 ScsiPortGetPhysicalAddress(HwDeviceExtension, 01822 0, 01823 (PVOID)virtualAddress, 01824 &length)); 01825 } 01826 else /* Turn off SG */ 01827 { 01828 CCB->Opcode = BusLogic_InitiatorCCB; 01829 CCB->DataLength = CCB->ScatterGatherList[0].SegmentByteCount; 01830 CCB->DataPointer = CCB->ScatterGatherList[0].SegmentDataPointer; 01831 01832 } 01833 } 01834 #else 01835 CCB->Opcode = BusLogic_InitiatorCCB; 01836 CCB->DataLength = BufferLength; 01837 CCB->DataPointer = ScsiPortConvertPhysicalAddressToUlong(ScsiPortGetPhysicalAddress(deviceExtension, 01838 Srb, 01839 BufferPointer, 01840 &length)); 01841 #endif 01842 } 01843 01844 switch (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) 01845 { 01846 case SRB_FLAGS_NO_DATA_TRANSFER: 01847 CCB->DataDirection = BusLogic_NoDataTransfer; 01848 break; 01849 01850 case SRB_FLAGS_DATA_IN: 01851 CCB->DataDirection = BusLogic_DataInLengthChecked; 01852 TargetStatistics[TargetID].ReadCommands++; 01853 BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesRead, 01854 BufferLength); 01855 BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].ReadCommandSizeBuckets, 01856 BufferLength); 01857 break; 01858 01859 case SRB_FLAGS_DATA_OUT: 01860 CCB->DataDirection = BusLogic_DataOutLengthChecked; 01861 TargetStatistics[TargetID].WriteCommands++; 01862 BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesWritten, 01863 BufferLength); 01864 BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].WriteCommandSizeBuckets, 01865 BufferLength); 01866 01867 break; 01868 01869 case SRB_FLAGS_UNSPECIFIED_DIRECTION: /* let device decide direction */ 01870 default: 01871 CCB->DataDirection = BusLogic_UncheckedDataTransfer; 01872 break; 01873 } 01874 01875 01876 CCB->CDB_Length = CDB_Length; 01877 CCB->SenseDataLength = Srb->SenseInfoBufferLength; 01878 CCB->HostAdapterStatus = 0; 01879 CCB->TargetDeviceStatus = 0; 01880 CCB->TargetID = TargetID; 01881 CCB->LogicalUnit = LogicalUnit; 01882 CCB->TagEnable = FALSE; 01883 CCB->LegacyTagEnable = FALSE; 01884 01885 // BusLogic recommends that after a Reset the first couple of commands that 01886 // are sent to a Target Device be sent in a non Tagged Queue fashion so that 01887 // the Host Adapter and Target Device can establish Synchronous and Wide 01888 // Transfer before Queue Tag messages can interfere with the Synchronous and 01889 // Wide Negotiation messages. By waiting to enable Tagged Queuing until after 01890 // the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is 01891 // assured that after a Reset any pending commands are requeued before Tagged 01892 // Queuing is enabled and that the Tagged Queuing message will not occur while 01893 // the partition table is being printed. In addition, some devices do not 01894 // properly handle the transition from non-tagged to tagged commands, so it is 01895 // necessary to wait until there are no pending commands for a target device 01896 // before queuing tagged commands. 01897 01898 if (HostAdapter->CommandsSinceReset[TargetID]++ >= BusLogic_MaxTaggedQueueDepth && 01899 HostAdapter->ActiveCommandsPerTarget[TargetID] == 0 && 01900 !TargetFlags->TaggedQueuingActive && 01901 TargetFlags->TaggedQueuingSupported && 01902 (HostAdapter->TaggedQueuingPermitted & (1 << TargetID))) 01903 { 01904 TargetFlags->TaggedQueuingActive = TRUE; 01905 DebugPrint((INFO, "\n BusLogic - Tagged Queuing now active for Target %d\n", 01906 TargetID)); 01907 } 01908 if (TargetFlags->TaggedQueuingActive) 01909 { 01910 BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag; 01911 01912 // When using Tagged Queuing with Simple Queue Tags, it appears that disk 01913 // drive controllers do not guarantee that a queued command will not 01914 // remain in a disconnected state indefinitely if commands that read or 01915 // write nearer the head position continue to arrive without interruption. 01916 // Therefore, for each Target Device this driver keeps track of the last 01917 // time either the queue was empty or an Ordered Queue Tag was issued. If 01918 // more than 4 seconds (one fifth of the 20 second disk timeout) have 01919 // elapsed since this last sequence point, this command will be issued 01920 // with an Ordered Queue Tag rather than a Simple Queue Tag, which forces 01921 // the Target Device to complete all previously queued commands before 01922 // this command may be executed. 01923 /* 01924 if (HostAdapter->ActiveCommandsPerTarget[TargetID] == 0) 01925 HostAdapter->LastSequencePoint[TargetID] = jiffies; 01926 else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ) 01927 { 01928 HostAdapter->LastSequencePoint[TargetID] = jiffies; 01929 QueueTag = BusLogic_OrderedQueueTag; 01930 } 01931 */ 01932 if (HostAdapter->ExtendedLUNSupport) 01933 { 01934 CCB->TagEnable = TRUE; 01935 CCB->QueueTag = (UCHAR)QueueTag; 01936 } 01937 else 01938 { 01939 CCB->LegacyTagEnable = TRUE; 01940 CCB->LegacyQueueTag = (UCHAR)QueueTag; 01941 } 01942 } 01943 01944 ScsiPortMoveMemory(CCB->CDB, Srb->Cdb, CDB_Length); 01945 01946 //Fix for the XP Port driver - shuts of auto sense at times. 22nd May 2002 01947 //{sirish, shobhit}@calsoftinc.com 01948 if ((Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) || 01949 (Srb->SenseInfoBufferLength <= 0)) { 01950 01951 //Disable auto request sense 01952 CCB->SenseDataLength = BusLogic_DisableAutoReqSense; 01953 } else { 01954 //Enable auto request sense 01955 CCB->SenseDataLength = (unsigned char) Srb->SenseInfoBufferLength; 01956 01957 //Sense Buffer physical addr 01958 CCB->SenseDataPointer = ScsiPortConvertPhysicalAddressToUlong(ScsiPortGetPhysicalAddress(HwDeviceExtension, 01959 Srb, 01960 Srb->SenseInfoBuffer, 01961 &length)); 01962 if (Srb->SenseInfoBufferLength > length ) { 01963 CCB->SenseDataLength = (unsigned char) length; 01964 } 01965 } 01966 01967 return 0; 01968 }// end BusLogic_QueueCommand 01969 01970 01971 BOOLEAN 01972 NTAPI 01973 BT958HwInterrupt(IN PVOID HwDeviceExtension) 01974 //_________________________________________________________________________ 01975 // Routine Description: 01976 // HwScsiInterrupt is called when the HBA generates an 01977 // interrupt. Miniport drivers of HBAs that do not 01978 // generate interrupts do not have this routine. 01979 // HwScsiInterrupt is responsible for completing 01980 // interrupt-driven I/O operations. This routine must 01981 // clear the interrupt on the HBA before it returns TRUE. 01982 // Arguments: 01983 // 1. HwDeviceExtension: Points to the miniport driver's per-HBA storage area. 01984 // Return Value: 01985 // TRUE : Acknowledged the interrupts on the HBA 01986 // FALSE: If the miniport finds that its HBA did not generate 01987 // the interrupt, HwScsiInterrupt should return FALSE 01988 // as soon as possible. 01989 //_________________________________________________________________________ 01990 { 01991 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 01992 // PNONCACHED_EXTENSION noncachedExtension = deviceExtension->NoncachedExtension; 01993 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 01994 // PBuslogic_CCB_T ccb; 01995 // PSCSI_REQUEST_BLOCK srb; 01996 01997 // ULONG residualBytes; 01998 // ULONG i; 01999 02000 BusLogic_InterruptRegister_T InterruptRegister; 02001 02002 02003 // Read the Host Adapter Interrupt Register. 02004 InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); 02005 if (InterruptRegister.Bits.InterruptValid) 02006 { 02007 02008 // Acknowledge the interrupt and reset the Host Adapter 02009 // Interrupt Register. 02010 BusLogic_InterruptReset(HostAdapter); 02011 // Process valid External SCSI Bus Reset and Incoming Mailbox 02012 // Loaded Interrupts. Command Complete Interrupts are noted, 02013 // and Outgoing Mailbox Available Interrupts are ignored, as 02014 // they are never enabled. 02015 if (InterruptRegister.Bits.ExternalBusReset) 02016 { 02017 HostAdapter->HostAdapterExternalReset = TRUE; 02018 } 02019 else if (InterruptRegister.Bits.IncomingMailboxLoaded) 02020 { 02021 BusLogic_ScanIncomingMailboxes(deviceExtension); 02022 } 02023 else if (InterruptRegister.Bits.CommandComplete) 02024 { 02025 HostAdapter->HostAdapterCommandCompleted = TRUE; 02026 } 02027 } 02028 else 02029 return FALSE; 02030 02031 // Process any completed CCBs. 02032 if (HostAdapter->FirstCompletedCCB != NULL) 02033 BusLogic_ProcessCompletedCCBs(deviceExtension); 02034 02035 // Reset the Host Adapter if requested. 02036 if (HostAdapter->HostAdapterExternalReset || 02037 HostAdapter->HostAdapterInternalError) 02038 { 02039 // I have replaced the NULL with srb->pathid check if this is correct 02040 BT958HwResetBus(HwDeviceExtension, SP_UNTAGGED); 02041 HostAdapter->HostAdapterExternalReset = FALSE; 02042 HostAdapter->HostAdapterInternalError = FALSE; 02043 } 02044 return TRUE; 02045 }// end BT958HwInterrupt 02046 02047 void 02048 BusLogic_ScanIncomingMailboxes(PHW_DEVICE_EXTENSION deviceExtension) 02049 //________________________________________________________________________________________ 02050 // Routine Description: 02051 // BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any 02052 // Incoming Mailbox entries for completion processing. 02053 // Arguments: 02054 // 1. deviceExtension : pointer to the device extension 02055 //_________________________________________________________________________________________ 02056 { 02057 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 02058 02059 02060 // Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving 02061 // any completed CCBs for further processing. It is essential that for each 02062 // CCB and SCSI Command issued, command completion processing is performed 02063 // exactly once. Therefore, only Incoming Mailboxes with completion code 02064 // Command Completed Without Error, Command Completed With Error, or Command 02065 // Aborted At Host Request are saved for completion processing. When an 02066 // Incoming Mailbox has a completion code of Aborted Command Not Found, the 02067 // CCB had already completed or been aborted before the current Abort request 02068 // was processed, and so completion processing has already occurred and no 02069 // further action should be taken. 02070 BusLogic_IncomingMailbox_T *NextIncomingMailbox = HostAdapter->NextIncomingMailbox; 02071 BusLogic_CompletionCode_T CompletionCode; 02072 02073 while ((CompletionCode = NextIncomingMailbox->CompletionCode) != BusLogic_IncomingMailboxFree) 02074 { 02075 // Convert Physical CCB to Virtual. 02076 BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) ScsiPortGetVirtualAddress(deviceExtension, 02077 ScsiPortConvertUlongToPhysicalAddress(NextIncomingMailbox->CCB)); 02078 02079 DebugPrint((INFO, "\n Buslogic - Virtual CCB %lx\n", CCB)); 02080 if (CompletionCode != BusLogic_AbortedCommandNotFound) 02081 { 02082 if (CCB->Status == BusLogic_CCB_Active || CCB->Status == BusLogic_CCB_Reset) 02083 { 02084 02085 // Save the Completion Code for this CCB and queue the CCB 02086 // for completion processing. 02087 CCB->CompletionCode = CompletionCode; 02088 BusLogic_QueueCompletedCCB(deviceExtension,CCB); 02089 } 02090 else 02091 { 02092 // If a CCB ever appears in an Incoming Mailbox and is not marked 02093 // as status Active or Reset, then there is most likely a bug in 02094 // the Host Adapter firmware. 02095 DebugPrint((ERROR, "\n BusLogic - Illegal CCB #%ld status %d in " 02096 "Incoming Mailbox\n", CCB->SerialNumber, CCB->Status)); 02097 } 02098 } 02099 NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree; 02100 if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox) 02101 NextIncomingMailbox = HostAdapter->FirstIncomingMailbox; 02102 } 02103 HostAdapter->NextIncomingMailbox = NextIncomingMailbox; 02104 }// end BusLogic_ScanIncomingMailboxes 02105 02106 02107 void 02108 BusLogic_QueueCompletedCCB(PHW_DEVICE_EXTENSION deviceExtension, 02109 BusLogic_CCB_T *CCB) 02110 //_________________________________________________________________________________ 02111 // Routine Description: 02112 // BusLogic_QueueCompletedCCB queues CCB for completion processing. 02113 // Arguments: 02114 // 1. deviceExtension : pointer to device extension 02115 // 2. CCB: pointe t CCB that needs to be queued 02116 //_________________________________________________________________________________ 02117 { 02118 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 02119 02120 CCB->Status = BusLogic_CCB_Completed; 02121 CCB->Next = NULL; 02122 if (HostAdapter->FirstCompletedCCB == NULL) 02123 { 02124 HostAdapter->FirstCompletedCCB = CCB; 02125 HostAdapter->LastCompletedCCB = CCB; 02126 } 02127 else 02128 { 02129 HostAdapter->LastCompletedCCB->Next = CCB; 02130 HostAdapter->LastCompletedCCB = CCB; 02131 } 02132 HostAdapter->ActiveCommandsPerTarget[CCB->TargetID]--; 02133 HostAdapter->ActiveCommandsPerLun[CCB->TargetID][CCB->LogicalUnit]--; 02134 02135 }// end BusLogic_QueueCompletedCCB 02136 02137 02138 void 02139 BusLogic_ProcessCompletedCCBs(PHW_DEVICE_EXTENSION deviceExtension) 02140 //_________________________________________________________________________________ 02141 // Routine Description: 02142 // BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host 02143 // Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and 02144 // calling the SCSI Subsystem Completion Routines. The Host Adapter's Lock 02145 // should already have been acquired by the caller. 02146 // 02147 // Arguments: 02148 // 1. deviceExtension : pointer to device extension 02149 //_________________________________________________________________________________ 02150 { 02151 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 02152 PSCSI_REQUEST_BLOCK srb; 02153 PCDB RealCdb; 02154 02155 if (HostAdapter->ProcessCompletedCCBsActive) 02156 return; 02157 HostAdapter->ProcessCompletedCCBsActive = TRUE; 02158 while (HostAdapter->FirstCompletedCCB != NULL) 02159 { 02160 BusLogic_CCB_T *CCB = HostAdapter->FirstCompletedCCB; 02161 02162 // Get SRB from CCB. 02163 srb = CCB->SrbAddress; 02164 02165 HostAdapter->FirstCompletedCCB = CCB->Next; 02166 if (HostAdapter->FirstCompletedCCB == NULL) 02167 HostAdapter->LastCompletedCCB = NULL; 02168 02169 // Process the Completed CCB. 02170 if (CCB->Opcode == BusLogic_BusDeviceReset) 02171 { 02172 int TargetID = CCB->TargetID, LunID; 02173 DebugPrint((TRACE, "\n BusLogic - Bus Device Reset CCB #%ld to Target " 02174 "%d Completed\n", CCB->SerialNumber, TargetID)); 02175 BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted); 02176 02177 HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = FALSE; 02178 HostAdapter->CommandsSinceReset[TargetID] = 0; 02179 //HostAdapter->LastResetCompleted[TargetID] = jiffies; 02180 HostAdapter->ActiveCommandsPerTarget[TargetID] = 0; 02181 for (LunID = 0; LunID < HostAdapter->MaxLogicalUnits; LunID++) 02182 HostAdapter->ActiveCommandsPerLun[TargetID][LunID] = 0; 02183 02184 // Complete all outstanding requests with SRB_STATUS_BUS_RESET. 02185 ScsiPortCompleteRequest(deviceExtension, 02186 (UCHAR)srb->PathId, 02187 srb->TargetId, 02188 0xFF, 02189 (ULONG)SRB_STATUS_BUS_RESET); 02190 02191 02192 HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL; 02193 } 02194 else 02195 { 02196 // Translate the Completion Code, Host Adapter Status, and Target 02197 // Device Status into a SCSI Subsystem Result Code. 02198 switch (CCB->CompletionCode) 02199 { 02200 case BusLogic_IncomingMailboxFree: 02201 case BusLogic_InvalidCCB: 02202 { 02203 DebugPrint((ERROR, "\n BusLogic - CCB #%ld to Target %d Impossible " 02204 "State\n", CCB->SerialNumber, CCB->TargetID)); 02205 break; 02206 } 02207 02208 //Processing for CCB that was to be aborted 02209 case BusLogic_AbortedCommandNotFound: 02210 { 02211 srb = CCB->AbortSrb; 02212 srb->SrbStatus = SRB_STATUS_ABORT_FAILED; 02213 break; 02214 } 02215 02216 case BusLogic_CommandCompletedWithoutError: 02217 { 02218 HostAdapter->TargetStatistics[CCB->TargetID].CommandsCompleted++; 02219 HostAdapter->TargetFlags[CCB->TargetID].CommandSuccessfulFlag = TRUE; 02220 02221 srb->SrbStatus = SRB_STATUS_SUCCESS; 02222 break; 02223 } 02224 02225 case BusLogic_CommandAbortedAtHostRequest: 02226 { 02227 DebugPrint((TRACE, "\n BusLogic - CCB #%ld to Target %d Aborted\n", 02228 CCB->SerialNumber, CCB->TargetID)); 02229 //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[CCB->TargetID].CommandAbortsCompleted); 02230 02231 srb->SrbStatus = SRB_STATUS_ABORTED; 02232 02233 // Call notification routine for the aborted SRB. 02234 ScsiPortNotification(RequestComplete, 02235 deviceExtension, 02236 srb); 02237 02238 // Get the abort SRB from CCB. 02239 srb = CCB->AbortSrb; 02240 02241 // Set status for completing abort request. 02242 srb->SrbStatus = SRB_STATUS_SUCCESS; 02243 break; 02244 } 02245 02246 case BusLogic_CommandCompletedWithError: 02247 { 02248 RealCdb = (PCDB)CCB->CDB; 02249 DebugPrint((ERROR, "\n BusLogic - %x Command completed with error Host - " 02250 "%x Target %x \n", RealCdb->CDB6GENERIC.OperationCode, 02251 CCB->HostAdapterStatus, CCB->TargetDeviceStatus)); 02252 02253 srb->SrbStatus = BusLogic_ComputeResultCode(HostAdapter, 02254 CCB->HostAdapterStatus, 02255 CCB->TargetDeviceStatus, 02256 CCB->SenseDataLength); 02257 if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout) 02258 { 02259 HostAdapter->TargetStatistics[CCB->TargetID].CommandsCompleted++; 02260 } 02261 break; 02262 } 02263 02264 default: 02265 { 02266 // Log the error. 02267 ScsiPortLogError(deviceExtension, 02268 NULL, 02269 0, 02270 srb->TargetId, 02271 0, 02272 SP_INTERNAL_ADAPTER_ERROR, 02273 143); 02274 02275 DebugPrint((ERROR, "\n BusLogic - Unrecognized mailbox status\n")); 02276 } 02277 02278 }// end switch 02279 02280 02281 // When an INQUIRY command completes normally, save the CmdQue (Tagged Queuing Supported) 02282 // and WBus16 (16 Bit Wide Data Transfers Supported) bits. 02283 RealCdb = (PCDB) CCB->CDB; 02284 if (RealCdb->CDB6INQUIRY.OperationCode == SCSIOP_INQUIRY && 02285 CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally) 02286 { 02287 BusLogic_TargetFlags_T *TargetFlags =&HostAdapter->TargetFlags[CCB->TargetID]; 02288 SCSI_Inquiry_T *InquiryResult =(SCSI_Inquiry_T *) srb->DataBuffer; 02289 TargetFlags->TargetExists = TRUE; 02290 TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue; 02291 TargetFlags->WideTransfersSupported = InquiryResult->WBus16; 02292 } 02293 02294 DebugPrint((INFO, "\n BusLogic - SCSI Status %x\n", srb->ScsiStatus)); 02295 DebugPrint((INFO, "\n BusLogic - HBA Status %x\n", CCB->HostAdapterStatus)); 02296 02297 // Update target status in SRB. 02298 srb->ScsiStatus = (UCHAR)CCB->TargetDeviceStatus; 02299 02300 // Signal request completion. 02301 ScsiPortNotification(RequestComplete, (PVOID)deviceExtension, srb); 02302 } 02303 } 02304 HostAdapter->ProcessCompletedCCBsActive = FALSE; 02305 }// end BusLogic_ProcessCompletedCCBs 02306 02307 02308 UCHAR 02309 BusLogic_ComputeResultCode(BusLogic_HostAdapter_T *HostAdapter, 02310 BusLogic_HostAdapterStatus_T HostAdapterStatus, 02311 BusLogic_TargetDeviceStatus_T TargetDeviceStatus, 02312 UCHAR SenseDataLength) 02313 //_________________________________________________________________________________________ 02314 // Routine Description: 02315 // BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from 02316 // the Host Adapter Status and Target Device Status. 02317 // Arguments: 02318 // 1.HostAdapter: Pointer to the host adapter structure 02319 // 2.HostAdapterStatus: Host adapter status returned in the completed CCB 02320 // 3.TargetDeviceStatus: 02321 // Return Value: 02322 // This function returns the error code that should be returned to port driver 02323 //_________________________________________________________________________________________ 02324 { 02325 UCHAR HostStatus = 0; 02326 02327 // Namita 2Oct CDROM issue 02328 if (TargetDeviceStatus != BusLogic_OperationGood && (HostAdapterStatus == BusLogic_CommandCompletedNormally || 02329 HostAdapterStatus == BusLogic_LinkedCommandCompleted || 02330 HostAdapterStatus == BusLogic_LinkedCommandCompletedWithFlag)) 02331 { 02332 switch(TargetDeviceStatus) 02333 { 02334 case BusLogic_CheckCondition: 02335 { 02336 HostStatus = SRB_STATUS_ERROR; 02337 if(SenseDataLength != BusLogic_DisableAutoReqSense) 02338 HostStatus |= SRB_STATUS_AUTOSENSE_VALID; 02339 break; 02340 } 02341 case BusLogic_DeviceBusy: 02342 { 02343 HostStatus = SRB_STATUS_BUSY; 02344 break; 02345 } 02346 case BusLogic_OperationGood: 02347 { 02348 HostStatus = SRB_STATUS_SUCCESS; 02349 break; 02350 } 02351 } 02352 } 02353 02354 else 02355 { 02356 02357 switch (HostAdapterStatus) 02358 { 02359 case BusLogic_CommandCompletedNormally: 02360 case BusLogic_LinkedCommandCompleted: 02361 case BusLogic_LinkedCommandCompletedWithFlag: 02362 { 02363 HostStatus = SRB_STATUS_SUCCESS; 02364 break; 02365 } 02366 case BusLogic_SCSISelectionTimeout: 02367 { 02368 HostStatus = SRB_STATUS_SELECTION_TIMEOUT; 02369 break; 02370 } 02371 case BusLogic_InvalidOutgoingMailboxActionCode: 02372 case BusLogic_InvalidCommandOperationCode: 02373 case BusLogic_InvalidCommandParameter: 02374 DebugPrint((WARNING, "\n BusLogic - Driver Protocol Error 0x%02X\n", 02375 HostAdapterStatus)); 02376 case BusLogic_DataUnderRun: 02377 02378 case BusLogic_DataOverRun: 02379 // SRB_STATUS_DATA_OVERRUN 02380 02381 case BusLogic_LinkedCCBhasInvalidLUN: 02382 02383 case BusLogic_TaggedQueuingMessageRejected: 02384 // SRB_STATUS_MESSAGE_REJECTED 02385 case BusLogic_TargetDeviceReconnectedImproperly: 02386 case BusLogic_AbortQueueGenerated: 02387 case BusLogic_HostAdapterSoftwareError: 02388 02389 case BusLogic_HostAdapterHardwareTimeoutError: 02390 // SRB_STATUS_TIMEOUT 02391 { 02392 HostStatus = SRB_STATUS_ERROR; 02393 break; 02394 } 02395 case BusLogic_TargetFailedResponseToATN: 02396 case BusLogic_HostAdapterAssertedRST: 02397 case BusLogic_OtherDeviceAssertedRST: 02398 case BusLogic_HostAdapterAssertedBusDeviceReset: 02399 { 02400 HostStatus = SRB_STATUS_BUS_RESET; 02401 break; 02402 } 02403 case BusLogic_SCSIParityErrorDetected: 02404 { 02405 HostStatus = SRB_STATUS_PARITY_ERROR; 02406 break; 02407 } 02408 case BusLogic_UnexpectedBusFree: 02409 { 02410 HostStatus = SRB_STATUS_UNEXPECTED_BUS_FREE; 02411 break; 02412 } 02413 case BusLogic_InvalidBusPhaseRequested: 02414 { 02415 HostStatus = SRB_STATUS_PHASE_SEQUENCE_FAILURE; 02416 break; 02417 } 02418 case BusLogic_AutoRequestSenseFailed: 02419 { 02420 HostStatus = SRB_STATUS_REQUEST_SENSE_FAILED; 02421 break; 02422 } 02423 case BusLogic_UnsupportedMessageReceived: 02424 { 02425 HostStatus = SRB_STATUS_INVALID_REQUEST; 02426 break; 02427 } 02428 case BusLogic_HostAdapterHardwareFailed: 02429 { 02430 HostStatus = SRB_STATUS_NO_HBA; 02431 break; 02432 } 02433 default: 02434 { 02435 DebugPrint((WARNING, "\n BusLogic - Unknown HBA Status 0x%02X\n", 02436 HostAdapterStatus)); 02437 HostStatus = SRB_STATUS_ERROR; 02438 break; 02439 } 02440 } 02441 } 02442 return HostStatus; 02443 }// end BusLogic_ComputeResultCode 02444 02445 02446 BOOLEAN 02447 NTAPI 02448 BT958HwResetBus(IN PVOID HwDeviceExtension, 02449 IN ULONG PathId) 02450 //_____________________________________________________________________________________ 02451 // Routine Description: 02452 // BT958HwResetBus resets Host Adapter if possible, marking all 02453 // currently executing SCSI Commands as having been Reset. 02454 // Arguments: 02455 // 1. HwDeviceExtension: Points to the miniport driver's per-HBA storage area. 02456 // 2. PathId: Identifies the SCSI bus to be reset. 02457 // Return Value: 02458 // TRUE : If the bus is successfully reset, HwScsiResetBus returns TRUE. 02459 // FALSE : reset did not complete successfully 02460 //_____________________________________________________________________________________ 02461 { 02462 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 02463 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 02464 // BusLogic_CCB_T *CCB; 02465 // int TargetID; 02466 BOOLEAN Result; 02467 BOOLEAN HardReset; 02468 02469 DebugPrint((TRACE, "\n BusLogic - Reset SCSI bus\n")); 02470 02471 // Complete all outstanding requests with SRB_STATUS_BUS_RESET. 02472 ScsiPortCompleteRequest(deviceExtension, 02473 (UCHAR)PathId, 02474 0xFF, 02475 0xFF, 02476 (ULONG) SRB_STATUS_BUS_RESET); 02477 02478 if (HostAdapter->HostAdapterExternalReset) 02479 { 02480 //BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets); 02481 HardReset = FALSE; 02482 } 02483 else if (HostAdapter->HostAdapterInternalError) 02484 { 02485 //BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors); 02486 HardReset = TRUE; 02487 } 02488 else 02489 { 02490 //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[srb->TargetId].HostAdapterResetsRequested); 02491 HardReset = TRUE; 02492 } 02493 02494 // Think of a way of doing this - Namita 02495 /* 02496 if(srb == NULL) 02497 { 02498 if (HostAdapter->HostAdapterInternalError) 02499 DebugPrint((0,"BusLogic Warning: Resetting %s due to Host Adapter Internal Error\n",HostAdapter->FullModelName)); 02500 else 02501 DebugPrint((0,"BUsLogic Warning: Resetting %s due to External SCSI Bus Reset\n",HostAdapter->FullModelName)); 02502 } 02503 else 02504 { 02505 DebugPrint((0,"BusLogic Warning: Resetting %s due to Target %d\n", HostAdapter->FullModelName, srb->TargetId)); 02506 //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[srb->TargetId].HostAdapterResetsAttempted); 02507 } 02508 */ 02509 02510 // Attempt to Reset and Reinitialize the Host Adapter. 02511 // Change the initialize routine to make allocation some place else 02512 if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && BusLogic_InitializeHostAdapter(deviceExtension, NULL))) 02513 { 02514 DebugPrint((ERROR, "\n Buslogic - Resetting %s Failed\n", 02515 HostAdapter->FullModelName)); 02516 Result = FALSE; 02517 goto Done; 02518 } 02519 02520 // Check if we have to do this, document says that the scsi port driver takes care of the reset delays - Namita 02521 // Wait a few seconds between the Host Adapter Hard Reset which initiates 02522 // a SCSI Bus Reset and issuing any SCSI Commands. Some SCSI devices get 02523 // confused if they receive SCSI Commands too soon after a SCSI Bus Reset. 02524 // Note that a timer interrupt may occur here, but all active CCBs have 02525 // already been marked Reset and so a reentrant call will return Pending. 02526 if (HardReset) 02527 ScsiPortStallExecution(HostAdapter->BusSettleTime); 02528 Result = TRUE; 02529 02530 Done: 02531 return Result; 02532 }// end BT958HwResetBus 02533 02534 BOOLEAN 02535 BusLogic_SendBusDeviceReset(IN PVOID HwDeviceExtension, 02536 PSCSI_REQUEST_BLOCK Srb) 02537 //_____________________________________________________________________________________ 02538 // Routine Description: 02539 // BusLogic_SendBusDeviceReset causes a BUS DEVICE reset command to 02540 // be send to particular target. 02541 // Arguments: 02542 // 1. HwDeviceExtension: Points to the miniport driver's per-HBA storage area. 02543 // 2. Srb: pointer to the SCSI request block 02544 // Return Value: 02545 // TRUE : If the bus is successfully reset, HwScsiResetBus returns TRUE. 02546 // FALSE : reset did not complete successfully 02547 //_____________________________________________________________________________________ 02548 { 02549 02550 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 02551 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 02552 02553 UCHAR TargetID = Srb->TargetId; 02554 PBuslogic_CCB_T CCB = Srb->SrbExtension; 02555 BOOLEAN Result = FALSE; 02556 BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsRequested); 02557 02558 // If this is a Synchronous Reset and a Bus Device Reset is already pending 02559 // for this Target Device, do not send a second one. Add this Command to 02560 // the list of Commands for which completion processing must be performed 02561 // when the Bus Device Reset CCB completes. 02562 02563 if (HostAdapter->BusDeviceResetPendingCCB[TargetID] != NULL) 02564 { 02565 DebugPrint((WARNING, "\n BusLogic - Unable to Reset Command to Target %d - " 02566 "Reset Pending\n", TargetID)); 02567 Result = TRUE; 02568 goto Done; 02569 } 02570 02571 DebugPrint((WARNING, "\n BusLogic - Sending Bus Device Reset CCB #%ld to Target %d\n", 02572 CCB->SerialNumber, TargetID)); 02573 CCB->Opcode = BusLogic_BusDeviceReset; 02574 CCB->TargetID = TargetID; 02575 02576 02577 // Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB. 02578 // If sending a Bus Device Reset is impossible, attempt a full Host 02579 // Adapter Hard Reset and SCSI Bus Reset. 02580 if (!(BusLogic_WriteOutgoingMailbox(deviceExtension, BusLogic_MailboxStartCommand, CCB))) 02581 { 02582 DebugPrint((WARNING, "\n BusLogic - Unable to write Outgoing Mailbox for " 02583 "Bus Device Reset\n")); 02584 goto Done; 02585 } 02586 02587 // If there is a currently executing CCB in the Host Adapter for this Command 02588 // (i.e. this is an Asynchronous Reset), then an Incoming Mailbox entry may be 02589 // made with a completion code of BusLogic_HostAdapterAssertedBusDeviceReset. 02590 // If there is no active CCB for this Command (i.e. this is a Synchronous 02591 // Reset), then the Bus Device Reset CCB's Command field will have been set 02592 // to the Command so that the interrupt for the completion of the Bus Device 02593 // Reset can call the Completion Routine for the Command. On successful 02594 // execution of a Bus Device Reset, older firmware versions did return the 02595 // pending CCBs with the appropriate completion code, but more recent firmware 02596 // versions only return the Bus Device Reset CCB itself. This driver handles 02597 // both cases by marking all the currently executing CCBs to this Target 02598 // Device as Reset. When the Bus Device Reset CCB is processed by the 02599 // interrupt handler, any remaining CCBs marked as Reset will have completion 02600 // processing performed. 02601 02602 BusLogic_IncrementErrorCounter( &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsAttempted); 02603 HostAdapter->BusDeviceResetPendingCCB[TargetID] = CCB; 02604 //HostAdapter->LastResetAttempted[TargetID] = jiffies; 02605 02606 // FlashPoint Host Adapters may have already completed the Bus Device 02607 // Reset and BusLogic_QueueCompletedCCB been called, or it may still be 02608 // pending. 02609 02610 Result = TRUE; 02611 // If a Bus Device Reset was not possible for some reason, force a full 02612 // Host Adapter Hard Reset and SCSI Bus Reset. 02613 02614 Done: 02615 return Result; 02616 } 02617 02618 BOOLEAN 02619 NTAPI 02620 BT958HwInitialize(IN PVOID HwDeviceExtension) 02621 //_______________________________________________________________________________ 02622 // Routine Description: 02623 // This routine initializes the adapter by enabling its interrupts 02624 // Arguments: 02625 // 1. device extension 02626 // Return Value: 02627 // TRUE : initialzation successful 02628 // FALSE : initialization failed 02629 //_______________________________________________________________________________ 02630 { 02631 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 02632 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 02633 CHAR Parameter = 1; 02634 02635 // enable interrupts 02636 if (BusLogic_Command(HostAdapter, 02637 BusLogic_DisableHostAdapterInterrupt, 02638 &Parameter, 02639 sizeof(Parameter), 02640 NULL, 02641 0) 02642 < 0) 02643 { 02644 return FALSE; 02645 } 02646 return TRUE; 02647 }// end BT958HwInitialize 02648 02649 SCSI_ADAPTER_CONTROL_STATUS 02650 NTAPI 02651 BT958HwAdapterControl(IN PVOID HwDeviceExtension, 02652 IN SCSI_ADAPTER_CONTROL_TYPE ControlType, 02653 IN PVOID Parameters) 02654 //__________________________________________________________________________________________ 02655 // Routine Description: 02656 // A miniport driver's HwScsiAdapterControl routine is called to perform 02657 // synchronous operations to control the state or behavior of an HBA, such as 02658 // stopping or restarting the HBA for power management. 02659 // Arguments: 02660 // 1. HwDeviceExtension: device extension 02661 // 2. ControlType: Specifies one of the following adapter-control operations. 02662 // ScsiQuerySupportedControlTypes : Reports the adapter-control operations 02663 // implemented by the miniport. 02664 // ScsiStopAdapter: Shuts down the HBA. 02665 // ScsiRestartAdapter: Reinitializes an HBA. 02666 // ScsiSetBootConfig: Not supported 02667 // ScsiSetRunningConfig: Not supported 02668 // 3. Parameters: 02669 // Return Value: 02670 // TRUE : 02671 // FALSE : 02672 //_________________________________________________________________________ 02673 { 02674 PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension; 02675 BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs); 02676 // UCHAR *ParameterPointer; 02677 // BusLogic_StatusRegister_T StatusRegister; 02678 // BusLogic_InterruptRegister_T InterruptRegister; 02679 // int Result,ParameterLength; 02680 // long TimeoutCounter; 02681 02682 PSCSI_SUPPORTED_CONTROL_TYPE_LIST ControlTypeList; 02683 ULONG AdjustedMaxControlType; 02684 02685 ULONG Index; 02686 // UCHAR Retries; 02687 02688 // Default Status 02689 // SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess; 02690 02691 // 02692 // Structure defining which functions this miniport supports 02693 // 02694 BOOLEAN SupportedConrolTypes[ScsiAdapterControlMax] = 02695 { 02696 TRUE, // ScsiQuerySupportedControlTypes 02697 TRUE, // ScsiStopAdapter 02698 TRUE, // ScsiRestartAdapter 02699 FALSE, // ScsiSetBootConfig 02700 FALSE // ScsiSetRunningConfig 02701 }; 02702 02703 DebugPrint((TRACE, "\n BusLogic - Inside HwAdapterControl function \n")); 02704 switch(ControlType) 02705 { 02706 case ScsiQuerySupportedControlTypes: 02707 // Reports the adapter-control operations implemented by the miniport. The port 02708 // driver calls HwScsiAdapterControl with this control type after the HBA has been 02709 // initialized but before the first I/O. The miniport fills in the 02710 // SCSI_SUPPORTED_CONTROL_TYPE_LIST structure at Parameters with the operations it 02711 // supports. After HwScsiAdapterControl returns from this call, the port driver 02712 // calls the miniport's HwScsiAdapterControl only for supported operations. 02713 { 02714 02715 // This entry point provides the method by which SCSIPort determines the 02716 // supported ControlTypes. Parameters is a pointer to a 02717 // SCSI_SUPPORTED_CONTROL_TYPE_LIST structure. Fill in this structure 02718 // honoring the size limits. 02719 ControlTypeList = Parameters; 02720 AdjustedMaxControlType = (ControlTypeList->MaxControlType < ScsiAdapterControlMax) ? ControlTypeList->MaxControlType :ScsiAdapterControlMax; 02721 for (Index = 0; Index < AdjustedMaxControlType; Index++) 02722 { 02723 ControlTypeList->SupportedTypeList[Index] = SupportedConrolTypes[Index]; 02724 } 02725 break; 02726 } 02727 02728 case ScsiStopAdapter: 02729 // Shuts down the HBA. The port driver calls HwScsiAdapterControl with this control 02730 // type when the HBA has been removed from the system, stopped for resource reconfiguration, 02731 // shut down for power management, or otherwise reconfigured or disabled. The port driver 02732 // ensures that there are no uncompleted requests and issues an SRB_FUNCTION_FLUSH request 02733 // to the miniport before calling this routine. The miniport disables interrupts on its HBA, 02734 // halts all processing, (including background processing not subject to interrupts or processing 02735 // of which the port driver is unaware, such as reconstructing fault-tolerant volumes), flushes 02736 // any remaining cached data to persistent storage, and puts the HBA into a state from which it 02737 // can be reinitialized or restarted. 02738 // The miniport should not free its resources when stopping its HBA. If the HBA was removed or 02739 // stopped for PnP resource reconfiguration, the port driver releases resources on behalf of the 02740 // miniport driver. If the HBA is shut down for power management, the miniport's resources are 02741 // preserved so the HBA can be restarted. 02742 { 02743 CHAR Parameter = 0; 02744 DebugPrint((INFO, "\n BusLogic - stopping the device \n")); 02745 if (BusLogic_Command(HostAdapter, 02746 BusLogic_DisableHostAdapterInterrupt, 02747 &Parameter, 02748 sizeof(Parameter), 02749 NULL, 02750 0) 02751 < 0) 02752 { 02753 return ScsiAdapterControlUnsuccessful; 02754 } 02755 break; 02756 } 02757 02758 case ScsiRestartAdapter: 02759 // Reinitializes an HBA. The port driver calls HwScsiAdapterControl with this control type to power 02760 // up an HBA that was shut down for power management. All resources previously assigned to the miniport 02761 // are still available, and its device extension and logical unit extensions, if any, are intact. 02762 // The miniport performs the same operations as in its HwScsiInitialize routine, such as setting up 02763 // the HBA's registers and its initial state, if any. 02764 // The miniport must not call routines that can only be called from HwScsiFindAdapter or from 02765 // HwScsiAdapterControl when the control type is ScsiSetRunningConfig, such as ScsiPortGetBusData and 02766 // ScsiPortSetBusDataByOffset. If the miniport must call such routines to restart its HBA, it must also 02767 // implement ScsiSetRunningConfig. 02768 // 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. 02769 02770 // See PR 69004. We were not calling BT958HwInitialize earlier if the 02771 // first two calls succeeded thus causing resume from standby to fail. 02772 { 02773 if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, TRUE) && 02774 BusLogic_InitializeHostAdapter(deviceExtension, NULL) && 02775 BT958HwInitialize(HwDeviceExtension)) 02776 ) 02777 { 02778 DebugPrint((ERROR, "\n Buslogic - Resetting %s Failed\n", 02779 HostAdapter->FullModelName)); 02780 return ScsiAdapterControlUnsuccessful; 02781 } 02782 02783 ScsiPortStallExecution(HostAdapter->BusSettleTime); 02784 break; 02785 } 02786 default: 02787 { 02788 return ScsiAdapterControlUnsuccessful; 02789 } 02790 } 02791 return ScsiAdapterControlSuccess; 02792 }// end BT958HwAdapterControl 02793 02794 // END OF FILE BusLogic958.c Generated on Sat May 26 2012 04:27:01 for ReactOS by
1.7.6.1
|