ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

BusLogic958.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.