Import VMware open source BusLogic driver
authorGé van Geldorp <ge@gse.nl>
Thu, 18 Aug 2005 21:59:20 +0000 (21:59 +0000)
committerGé van Geldorp <ge@gse.nl>
Thu, 18 Aug 2005 21:59:20 +0000 (21:59 +0000)
Hartmut made it work in ReactOS.

svn path=/trunk/; revision=17434

19 files changed:
reactos/boot/freeldr/freeldr/reactos/setupldr.c
reactos/bootdata/hivesys.inf
reactos/bootdata/txtsetup.sif
reactos/drivers/storage/buslogic/BT958.bmf [new file with mode: 0644]
reactos/drivers/storage/buslogic/BT958.mof [new file with mode: 0644]
reactos/drivers/storage/buslogic/BT958dt.h [new file with mode: 0644]
reactos/drivers/storage/buslogic/BusLogic958.c [new file with mode: 0644]
reactos/drivers/storage/buslogic/BusLogic958.h [new file with mode: 0644]
reactos/drivers/storage/buslogic/BusLogic958.rc [new file with mode: 0644]
reactos/drivers/storage/buslogic/Log.c [new file with mode: 0644]
reactos/drivers/storage/buslogic/Log.h [new file with mode: 0644]
reactos/drivers/storage/buslogic/README.ReactOS [new file with mode: 0644]
reactos/drivers/storage/buslogic/buslogic.xml [new file with mode: 0644]
reactos/drivers/storage/buslogic/makefile.inc [new file with mode: 0644]
reactos/drivers/storage/buslogic/makefile.original [new file with mode: 0644]
reactos/drivers/storage/buslogic/resource.h [new file with mode: 0644]
reactos/drivers/storage/buslogic/sources [new file with mode: 0644]
reactos/drivers/storage/buslogic/wmi.c [new file with mode: 0644]
reactos/drivers/storage/directory.xml

index 7d27ce4..5d840ed 100644 (file)
@@ -611,6 +611,10 @@ for(;;);
   if (!LoadDriver(SourcePath, "atapi.sys"))
     return;
 
+  /* Load buslogic.sys (depends on hardware detection) */
+  if (!LoadDriver(SourcePath, "buslogic.sys"))
+    return;
+
   /* Load class2.sys */
   if (!LoadDriver(SourcePath, "class2.sys"))
     return;
index 5eb0ae7..0b5c432 100644 (file)
@@ -376,6 +376,14 @@ HKLM,"SYSTEM\CurrentControlSet\Services\Atapi","Start",0x00010001,0x00000000
 HKLM,"SYSTEM\CurrentControlSet\Services\Atapi","Type",0x00010001,0x00000001
 HKLM,"SYSTEM\CurrentControlSet\Services\Atapi","Tag",0x00010001,0x00000010
 
+; BusLogic 958 miniport driver
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","ErrorControl",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","Group",0x00000000,"SCSI Miniport"
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","ImagePath",0x00020000,"system32\drivers\buslogic.sys"
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","Start",0x00010001,0x00000000
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","Type",0x00010001,0x00000001
+HKLM,"SYSTEM\CurrentControlSet\Services\BusLogic","Tag",0x00010001,0x00000020
+
 ; ACPI driver
 HKLM,"SYSTEM\CurrentControlSet\Services\ACPI","ErrorControl",0x00010001,0x00000001
 HKLM,"SYSTEM\CurrentControlSet\Services\ACPI","Group",0x00000000,"Boot Bus Extender"
index 2262db2..c9113c2 100644 (file)
@@ -14,6 +14,7 @@ Signature = "$ReactOS$"
 [SourceFiles]
 ; <filename> = <directory_id>
 atapi.sys     = 3
+buslogic.sys  = 3
 blue.sys      = 3
 c_437.nls     = 2
 c_1252.nls    = 2
diff --git a/reactos/drivers/storage/buslogic/BT958.bmf b/reactos/drivers/storage/buslogic/BT958.bmf
new file mode 100644 (file)
index 0000000..0f1036b
Binary files /dev/null and b/reactos/drivers/storage/buslogic/BT958.bmf differ
diff --git a/reactos/drivers/storage/buslogic/BT958.mof b/reactos/drivers/storage/buslogic/BT958.mof
new file mode 100644 (file)
index 0000000..bdb4e77
--- /dev/null
@@ -0,0 +1,30 @@
+[
+    Dynamic, Provider("WMIProv"),
+    WMI,
+    Description ("BT958 Extended Setup Information (Operation Code 8Dh)"),
+    guid ("{CBD60D59-CE49-4cf4-AB7A-DEC6F4988D1A}"),
+    HeaderName("BT958ExtendedSetupInfo"),
+    GuidName1("BT958Wmi_ExtendedSetupInfo_Guid"),
+    WmiExpense(0)
+]
+class BT958ExtendedSetupInfoGuid
+{
+    [read,key] String InstanceName;
+    [read] boolean Active;
+
+    [read, WmiDataId(1), WmiVersion(1)]        uint8 BusType;                                      
+       [read, WmiDataId(2), WmiVersion(1)]     uint8  BIOS_Address;                                    
+       [read, WmiDataId(3), WmiVersion(1)]     uint16 ScatterGatherLimit;              
+       [read, WmiDataId(4), WmiVersion(1)]     uint8  MailboxCount;                                    
+       [read, WmiDataId(5), WmiVersion(1)] uint32 BaseMailboxAddress;  
+       [read, WmiDataId(6), WmiVersion(1)] boolean FastOnEISA:1;
+       [read, WmiDataId(7), WmiVersion(1)] boolean LevelSensitiveInterrupt:1;  
+       [read, WmiDataId(8), WmiVersion(1), max(3)] uint8 FirmwareRevision[];                   
+    [read, WmiDataId(9), WmiVersion(1)] boolean HostWideSCSI:1;                                    
+       [read, WmiDataId(10), WmiVersion(1)] boolean HostDifferentialSCSI:1;                    
+       [read, WmiDataId(11), WmiVersion(1)] boolean HostSupportsSCAM:1;                                
+       [read, WmiDataId(12), WmiVersion(1)] boolean HostUltraSCSI:1;                               
+       [read, WmiDataId(13), WmiVersion(1)] boolean HostSmartTermination:1;                    
+};
+
+
diff --git a/reactos/drivers/storage/buslogic/BT958dt.h b/reactos/drivers/storage/buslogic/BT958dt.h
new file mode 100644 (file)
index 0000000..6d839fd
--- /dev/null
@@ -0,0 +1,105 @@
+/*
+ * vmscsi-- Miniport driver for the Buslogic BT 958 SCSI Controller 
+ *          under Windows 2000/XP/Server 2003
+ *
+ *          Based in parts on the buslogic driver for the same device
+ *          available with the GNU Linux Operating System.
+ *          
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+
+#ifndef _BT958dt_h_
+#define _BT958dt_h_
+
+// BT958ExtendedSetupInfoGuid - BT958ExtendedSetupInfo
+// BT958 Extended Setup Information (Operation Code 8Dh)
+#define BT958Wmi_ExtendedSetupInfo_Guid \
+    { 0xcbd60d59,0xce49,0x4cf4, { 0xab,0x7a,0xde,0xc6,0xf4,0x98,0x8d,0x1a } }
+
+DEFINE_GUID(BT958ExtendedSetupInfoGuid_GUID, \
+            0xcbd60d59,0xce49,0x4cf4,0xab,0x7a,0xde,0xc6,0xf4,0x98,0x8d,0x1a);
+
+
+typedef struct _BT958ExtendedSetupInfo
+{
+    // 
+    UCHAR BusType;
+    #define BT958ExtendedSetupInfo_BusType_SIZE sizeof(UCHAR)
+    #define BT958ExtendedSetupInfo_BusType_ID 1
+
+    // 
+    UCHAR BIOS_Address;
+    #define BT958ExtendedSetupInfo_BIOS_Address_SIZE sizeof(UCHAR)
+    #define BT958ExtendedSetupInfo_BIOS_Address_ID 2
+
+    // 
+    USHORT ScatterGatherLimit;
+    #define BT958ExtendedSetupInfo_ScatterGatherLimit_SIZE sizeof(USHORT)
+    #define BT958ExtendedSetupInfo_ScatterGatherLimit_ID 3
+
+    // 
+    UCHAR MailboxCount;
+    #define BT958ExtendedSetupInfo_MailboxCount_SIZE sizeof(UCHAR)
+    #define BT958ExtendedSetupInfo_MailboxCount_ID 4
+
+    // 
+    ULONG BaseMailboxAddress;
+    #define BT958ExtendedSetupInfo_BaseMailboxAddress_SIZE sizeof(ULONG)
+    #define BT958ExtendedSetupInfo_BaseMailboxAddress_ID 5
+
+    // 
+    BOOLEAN FastOnEISA;
+    #define BT958ExtendedSetupInfo_FastOnEISA_SIZE sizeof(BOOLEAN)
+    #define BT958ExtendedSetupInfo_FastOnEISA_ID 6
+
+    // 
+    BOOLEAN LevelSensitiveInterrupt;
+    #define BT958ExtendedSetupInfo_LevelSensitiveInterrupt_SIZE sizeof(BOOLEAN)
+    #define BT958ExtendedSetupInfo_LevelSensitiveInterrupt_ID 7
+
+    // 
+    UCHAR FirmwareRevision[3];
+    #define BT958ExtendedSetupInfo_FirmwareRevision_SIZE sizeof(UCHAR[3])
+    #define BT958ExtendedSetupInfo_FirmwareRevision_ID 8
+
+    // 
+    BOOLEAN HostWideSCSI;
+    #define BT958ExtendedSetupInfo_HostWideSCSI_SIZE sizeof(BOOLEAN)
+    #define BT958ExtendedSetupInfo_HostWideSCSI_ID 9
+
+    // 
+    BOOLEAN HostDifferentialSCSI;
+    #define BT958ExtendedSetupInfo_HostDifferentialSCSI_SIZE sizeof(BOOLEAN)
+    #define BT958ExtendedSetupInfo_HostDifferentialSCSI_ID 10
+
+    // 
+    BOOLEAN HostSupportsSCAM;
+    #define BT958ExtendedSetupInfo_HostSupportsSCAM_SIZE sizeof(BOOLEAN)
+    #define BT958ExtendedSetupInfo_HostSupportsSCAM_ID 11
+
+    // 
+    BOOLEAN HostUltraSCSI;
+    #define BT958ExtendedSetupInfo_HostUltraSCSI_SIZE sizeof(BOOLEAN)
+    #define BT958ExtendedSetupInfo_HostUltraSCSI_ID 12
+
+    // 
+    BOOLEAN HostSmartTermination;
+    #define BT958ExtendedSetupInfo_HostSmartTermination_SIZE sizeof(BOOLEAN)
+    #define BT958ExtendedSetupInfo_HostSmartTermination_ID 13
+
+} BT958ExtendedSetupInfo, *PBT958ExtendedSetupInfo;
+
+#endif
diff --git a/reactos/drivers/storage/buslogic/BusLogic958.c b/reactos/drivers/storage/buslogic/BusLogic958.c
new file mode 100644 (file)
index 0000000..0653c6e
--- /dev/null
@@ -0,0 +1,2754 @@
+/*
+ * vmscsi-- Miniport driver for the Buslogic BT 958 SCSI Controller 
+ *          under Windows 2000/XP/Server 2003
+ *
+ *          Based in parts on the buslogic driver for the same device
+ *          available with the GNU Linux Operating System.
+ *          
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+//____________________________________________________________________________________
+//
+// File description :The driver for BusLogic-BT958 SCSI Host adapter card.
+// This driver assumes that the host adapter(HA from now on) is a PCI device.
+// This is an effort to build a driver for this card for the windows XP ennvironment
+// since the native XP installation doesnt provide this driver.
+//
+// The technical refernece for this device is at :
+//
+// Author: Namita Lal, Sirish Raghuram Calsoft Pvt Ltd
+// Date:   5th Feb 2003
+// Status: Driver version 1.2.0.0
+//         Performance tuned
+//         Correctness tested for
+//            1. Installation at OS install time
+//            2. Installation in an installed OS
+//            3. Installation by upgrading a previous version
+//         on all flavours of WinXP and Win Server 2003
+//         For Win2k however, please refer PR 22812
+/*
+Revision History: 
+v1.0.0.4  // Pre final release to VMware in Sep 2001, without WMI
+    |
+    |
+    v
+v1.0.0.5  // Sep 2001 release to VMware, with WMI
+    |
+    |
+    v
+v1.0.0.6  // Fix for bug with Nero Burning ROM in XP
+    |    // where SCSI_AUTO_SENSE is turned off at times
+    |
+    |
+    |---------> v1.1.0.0       // Performance optimizations:
+    |              |                   // A. WMI disabled, B. Queueing depth increased
+    |              |                   // C. Control flow changed (bug)
+    |              |
+    |              v
+    |          v1.1.0.1        // Fix for .NET restart freeze with 1.1.0.0
+    |                                  // Breaks on XP
+    |
+    v
+v1.2.0.0  // A. WMI disabled, B. Queueing depth increased
+                 // CURRENT VERSION
+*/
+//____________________________________________________________________________________
+
+#include "BusLogic958.h"
+
+ULONG
+STDCALL
+DriverEntry(IN PVOID DriverObject,
+                       IN PVOID Argument2
+                  )
+//_________________________________________________________________________
+// Routine Description:
+//              Installable driver initialization entry point for system.
+// Arguments:
+//              Driver Object
+// Return Value:
+//              Status from ScsiPortInitialize()
+//_________________________________________________________________________
+{
+    HW_INITIALIZATION_DATA hwInitializationData;
+    ULONG Status;
+    ULONG i;
+    ULONG HwContext;
+//    static int    cardNo = 0;
+
+    UCHAR VendorId[4] = { '1', '0', '4', 'b'        };
+    UCHAR DeviceId[4] = { '1', '0', '4', '0'        };
+
+    DebugPrint((0,"\n BusLogic -  Inside the DriverEntry function \n"));
+
+       // Zero out structure. 
+    for (i = 0; i < sizeof(HW_INITIALIZATION_DATA); i++) 
+    {
+        ((PUCHAR) & hwInitializationData)[i] = 0;
+    }
+
+    // Set size of hwInitializationData. 
+    hwInitializationData.HwInitializationDataSize = sizeof(HW_INITIALIZATION_DATA);
+
+    // Set entry points. 
+    hwInitializationData.HwInitialize =     BT958HwInitialize;
+    hwInitializationData.HwResetBus =       BT958HwResetBus;
+    hwInitializationData.HwStartIo =        BT958HwStartIO;
+    hwInitializationData.HwInterrupt =      BT958HwInterrupt;
+    hwInitializationData.HwAdapterControl = BT958HwAdapterControl;
+    hwInitializationData.HwFindAdapter =    BT958HwFindAdapter;
+
+    // Inidicate no buffer mapping but will need physical addresses
+    hwInitializationData.NeedPhysicalAddresses = TRUE;
+    
+    // Indicate Auto request sense is supported
+    hwInitializationData.AutoRequestSense = TRUE;
+    hwInitializationData.MultipleRequestPerLu = TRUE;
+
+#if TAG_QUEUING
+    hwInitializationData.TaggedQueuing = TRUE;
+#else
+    hwInitializationData.TaggedQueuing = FALSE;
+#endif
+        
+    hwInitializationData.AdapterInterfaceType = PCIBus;
+
+    // Fill in the vendor id and the device id
+    hwInitializationData.VendorId = &VendorId;
+    hwInitializationData.VendorIdLength = 4;
+    hwInitializationData.DeviceId = &DeviceId;
+    hwInitializationData.DeviceIdLength = 4;
+       
+
+    hwInitializationData.NumberOfAccessRanges = 2;
+
+
+    // Specify size of extensions. 
+    hwInitializationData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
+
+    // logical unit extension 
+    hwInitializationData.SrbExtensionSize = sizeof(BusLogic_CCB_T);
+
+    HwContext = 0;
+
+    DebugPrint((0,"\n BusLogic -  Calling the ScsiPortInitialize Routine\n"));
+
+    Status = ScsiPortInitialize(DriverObject,
+                                                               Argument2,
+                                                               &hwInitializationData, 
+                                                               &HwContext);
+
+    DebugPrint((0,"\n BusLogic -  Exiting the DriverEntry function \n"));
+    DebugPrint((0,"\n BusLogic - Status = %ul \n", Status));
+    return( Status );
+
+} // end DriverEntry() 
+
+
+ULONG
+STDCALL
+BT958HwFindAdapter(IN PVOID HwDeviceExtension,
+                  IN PVOID Context,
+                  IN PVOID BusInformation,
+                  IN PCHAR ArgumentString,
+                  IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+                  OUT PBOOLEAN  Again)
+//_________________________________________________________________________________________________
+// Routine Description:
+//              This function is called by the OS-specific port driver after the necessary storage 
+//              has been allocated, to gather information about the adapter's configuration.
+//
+// Arguments:
+//              HwDeviceExtension - HBA miniport driver's adapter data storage
+//              Context - Register base address
+//              ConfigInfo - Configuration information structure describing HBA
+//              This structure is defined in PORT.H.
+//
+// Return Value:
+//              HwScsiFindAdapter must return one of the following status values:
+//                             SP_RETURN_FOUND: Indicates a supported HBA was found and that the HBA-relevant 
+//                                                              configuration information was successfully determined and set in 
+//                                                              the PORT_CONFIGURATION_INFORMATION structure. 
+//                             SP_RETURN_ERROR: Indicates an HBA was found but there was error obtaining the 
+//                                                              configuration information. If possible, such an error should be 
+//                                                              logged with ScsiPortLogError. 
+//                             SP_RETURN_BAD_CONFIG: Indicates the supplied configuration information was invalid 
+//                                                                       for the adapter. 
+//                             SP_RETURN_NOT_FOUND: Indicates no supported HBA was found for the supplied 
+//                                                                      configuration information. 
+//________________________________________________________________________________________________
+{
+    PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+    BusLogic_HostAdapter_T *hcsp = &(deviceExtension->hcs);
+//    static UCHAR k = 0;
+    PACCESS_RANGE   accessRange;
+//    PCI_COMMON_CONFIG PCICommonConfig;
+    PUCHAR   pciAddress, portFound;
+    char    NumPort = 0;
+
+    DebugPrint((0,"\n BusLogic -  Inside the Find Adapter Routine\n"));
+
+    *Again = FALSE;
+
+    accessRange = &((*(ConfigInfo->AccessRanges))[0]);
+
+    // Inform SCSIPORT that we are NOT a WMI data provider 
+    // Sirish, 10th June 2002
+    ConfigInfo->WmiDataProvider = FALSE;
+    /*Sirish, 10th June 2002 BT958WmiInitialize(deviceExtension);*/
+
+    // Check for configuration information passed in form the system
+    if ((*ConfigInfo->AccessRanges)[0].RangeLength != 0) 
+    {
+        // check if the system supplied bus-relative address is valid and has not been
+       // claimed by anyother device
+       if ( ScsiPortValidateRange(deviceExtension,
+                                  ConfigInfo->AdapterInterfaceType,
+                                   ConfigInfo->SystemIoBusNumber,
+                                   accessRange->RangeStart,
+                                   accessRange->RangeLength,
+                                   TRUE) )  // TRUE: iniospace  
+       {
+            DebugPrint((0,"\n BusLogic -  BusLogic - Validate Range function suceeded \n"));
+
+           // Map the Bus-relative range addresses to system-space logical range addresses
+           // so that these mapped logical addresses can be called with SciPortRead/Writexxx 
+           // to determine whether the adapter is an HBA that the driver supports
+
+           pciAddress = (PUCHAR) ScsiPortGetDeviceBase(deviceExtension,
+                                                        ConfigInfo->AdapterInterfaceType,
+                                                        ConfigInfo->SystemIoBusNumber,
+                                                        accessRange->RangeStart,
+                                                        accessRange->RangeLength,
+                                                        TRUE);  // TRUE: iniospace 
+
+           if(pciAddress)
+           {
+               DebugPrint((0,"\n BusLogic -  Get Device Base  function suceeded \n"));
+
+               memset(hcsp, 0, sizeof(BusLogic_HostAdapter_T));
+
+               // points to structure of type BT958_HA which has device specific information. This needs
+               // to be either changed or modified with our specific info.
+               hcsp->IO_Address = pciAddress;
+               hcsp->IRQ_Channel = (UCHAR)ConfigInfo->BusInterruptLevel;
+               NumPort++;
+           }
+          }
+       }
+
+    if (NumPort == 0) 
+       {
+        return(SP_RETURN_NOT_FOUND);
+    }
+
+    //  Hardware found, let's find out hardware configuration
+    //  and fill out ConfigInfo table for WinNT     
+       ConfigInfo->NumberOfBuses = 1;
+    ConfigInfo->MaximumTransferLength = MAX_TRANSFER_SIZE; 
+    
+#if SG_SUPPORT                                     
+    ConfigInfo->ScatterGather = TRUE;
+#else
+    ConfigInfo->ScatterGather = FALSE;
+#endif
+
+    ConfigInfo->Master = TRUE;
+    ConfigInfo->NeedPhysicalAddresses = TRUE;
+    ConfigInfo->Dma32BitAddresses = TRUE;
+    ConfigInfo->InterruptMode =  LevelSensitive;
+
+#if TAG_QUEUING
+    ConfigInfo->TaggedQueuing = TRUE;
+#else
+    ConfigInfo->TaggedQueuing = FALSE;
+#endif
+
+       // Should we change this to double-word aligned to increase performance
+       ConfigInfo->AlignmentMask = 0x0;     
+       
+    portFound =     hcsp->IO_Address;
+
+    if (!Buslogic_InitBT958(deviceExtension,ConfigInfo)) // harware specific initializations. Find what's for our card
+       {
+       ScsiPortLogError(deviceExtension,
+                         NULL,
+                         0,
+                         0,
+                         0,
+                         SP_INTERNAL_ADAPTER_ERROR,
+                         7 << 8);
+
+       return(SP_RETURN_ERROR);
+       }
+       
+       if (NumPort != 0)
+        *Again = TRUE;
+
+    return(SP_RETURN_FOUND);
+
+} // end BT958FindAdapter() 
+
+
+BOOLEAN 
+Buslogic_InitBT958(PHW_DEVICE_EXTENSION deviceExtension, 
+                                  PPORT_CONFIGURATION_INFORMATION ConfigInfo)
+//_________________________________________________________________________
+// Routine Description:
+//                         This routine is called from the driver's FindAdapter routine
+//                         On invocation this routine probes the host adapter to check 
+//                             if its hardware registers are responding correctly, and 
+//                         initializes the device and makes it ready for IO
+// Arguments:
+//              1. deviceExtension
+//              2. Port Configuration info 
+// Return Value:
+//              TRUE : Device initialized properly
+//              FALSE : Device failed to initialize
+//_________________________________________________________________________
+{
+
+       BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+               
+       // Probe the Host Adapter.  
+       // If unsuccessful, abort further initialization.
+    if (!BusLogic_ProbeHostAdapter(HostAdapter)) 
+               return   FALSE; 
+    
+       // Hard Reset the Host Adapter.  
+       // If unsuccessful, abort further initialization.
+    if (!BusLogic_HardwareResetHostAdapter(HostAdapter, TRUE)) 
+               return FALSE;
+
+       // Check the Host Adapter.  
+       // If unsuccessful, abort further initialization.
+    if (!BusLogic_CheckHostAdapter(HostAdapter)) 
+               return FALSE;    
+       
+       // Allocate a Noncached Extension to use for mail boxes.
+       deviceExtension->NoncachedExtension =  ScsiPortGetUncachedExtension(deviceExtension,
+                                                                                                                                         ConfigInfo,
+                                                                                                                                         sizeof(NONCACHED_EXTENSION));
+
+       if (deviceExtension->NoncachedExtension == NULL) 
+       {     
+               // Log error.
+               ScsiPortLogError(deviceExtension,
+                                                        NULL,
+                                                        0,
+                                                        0,
+                                                        0,
+                                                        SP_INTERNAL_ADAPTER_ERROR,
+                                                        7 << 8);
+
+               // abort further initialization
+               return FALSE;
+       }
+
+       // Read the Host Adapter Configuration, Configure the Host Adapter,
+       // Acquire the System Resources necessary to use the Host Adapter, then
+       // Create the Initial CCBs, Initialize the Host Adapter, and finally
+       // perform Target Device Inquiry.
+    if (BusLogic_ReadHostAdapterConfiguration(HostAdapter)           &&
+               //BusLogic_ReportHostAdapterConfiguration(HostAdapter)       &&
+           BusLogic_InitializeHostAdapter(deviceExtension, ConfigInfo)  &&
+           BusLogic_TargetDeviceInquiry(HostAdapter))
+       {
+               // Fill in the:
+               // 1.Maximum number of scsi target devices that are supported by our adapter
+               ConfigInfo->MaximumNumberOfTargets = HostAdapter->MaxTargetDevices;
+               // 2. Maximum number of logical units per target the HBA can control. 
+               ConfigInfo->MaximumNumberOfLogicalUnits  = HostAdapter->MaxLogicalUnits;
+               ConfigInfo->InitiatorBusId[0] = HostAdapter->SCSI_ID;
+               // Maximum number of breaks between address ranges that a data buffer can 
+               // have if the HBA supports scatter/gather. In other words, the number of 
+               // scatter/gather lists minus one. 
+               ConfigInfo->NumberOfPhysicalBreaks = HostAdapter->DriverScatterGatherLimit;             
+       }
+    else
+       {
+               // An error occurred during Host Adapter Configuration Querying, Host
+               // Adapter Configuration, Host Adapter Initialization, or Target Device Inquiry,
+               // so return FALSE
+                 
+               return FALSE;     
+       }       
+       // Initialization completed successfully
+       return TRUE;
+} // end Buslogic_InitBT958
+
+
+BOOLEAN
+BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
+//____________________________________________________________________________________
+// Routine Description: BusLogic_ProbeHostAdapter probes for a BusLogic Host Adapter.
+//                                             The routine reads the status, interrupt and geometry regiter and
+//                                         checks if their contents are valid
+// Arguments:
+//              1. Host Adapter structure 
+//
+// Return Value:
+//              TRUE: Probe completed successfully
+//              FALSE: Probe failed
+//____________________________________________________________________________________
+{
+  BusLogic_StatusRegister_T StatusRegister;
+  BusLogic_InterruptRegister_T InterruptRegister;
+  BusLogic_GeometryRegister_T GeometryRegister;
+  
+  DebugPrint((0,"\n BusLogic -  Inside ProbeHostaAdapter funtion \n"));
+  //  Read the Status, Interrupt, and Geometry Registers to test if there are I/O
+  //  ports that respond, and to check the values to determine if they are from a
+  //  BusLogic Host Adapter.  A nonexistent I/O port will return 0xFF, in which
+  //  case there is definitely no BusLogic Host Adapter at this base I/O Address.
+  //  The test here is a subset of that used by the BusLogic Host Adapter BIOS.
+  
+  InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+  GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
+  StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+  
+  if (StatusRegister.All == 0 ||
+      StatusRegister.Bits.DiagnosticActive ||
+      StatusRegister.Bits.CommandParameterRegisterBusy ||
+      StatusRegister.Bits.Reserved ||
+      StatusRegister.Bits.CommandInvalid ||
+      InterruptRegister.Bits.Reserved != 0)
+    return FALSE;
+  
+  //  Check the undocumented Geometry Register to test if there is an I/O port
+  //  that responded.  Adaptec Host Adapters do not implement the Geometry
+  //  Register, so this test helps serve to avoid incorrectly recognizing an
+  //  Adaptec 1542A or 1542B as a BusLogic.  Unfortunately, the Adaptec 1542C
+  //  series does respond to the Geometry Register I/O port, but it will be
+  //  rejected later when the Inquire Extended Setup Information command is
+  //  issued in BusLogic_CheckHostAdapter.  The AMI FastDisk Host Adapter is a
+  //  BusLogic clone that implements the same interface as earlier BusLogic
+  //  Host Adapters, including the undocumented commands, and is therefore
+  //  supported by this driver.  However, the AMI FastDisk always returns 0x00
+  //  upon reading the Geometry Register, so the extended translation option
+  //  should always be left disabled on the AMI FastDisk.
+  
+  if (GeometryRegister.All == 0xFF) return FALSE;
+  return TRUE;
+}// end BusLogic_ProbeHostAdapter
+
+BOOLEAN 
+BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T  *HostAdapter, 
+                                                                 BOOLEAN HardReset)
+//_________________________________________________________________________
+// Routine Description: BusLogic_HardwareResetHostAdapter issues a Hardware 
+//                      Reset to the Host Adapter and waits for Host Adapter 
+//                      Diagnostics to complete.  If HardReset is TRUE, a
+//                                             Hard Reset is performed which also initiates a SCSI 
+//                      Bus Reset.  Otherwise, a Soft Reset is performed which 
+//                      only resets the Host Adapter without forcing a SCSI 
+//                      Bus Reset.
+// Arguments:
+//              1. Host Adapter structure 
+//              2. Boolean HardReset - True: Do hard reset
+// Return Value:
+//              TRUE : Reset completed successfully
+//              FALSE : Reset failed
+//_________________________________________________________________________
+{
+  BusLogic_StatusRegister_T StatusRegister;
+  int TimeoutCounter;
+  
+  //  Issue a Hard Reset or Soft Reset Command to the Host Adapter.  The Host
+  //  Adapter should respond by setting Diagnostic Active in the Status Register.
+  if (HardReset)
+       BusLogic_HardReset(HostAdapter);
+  else 
+       BusLogic_SoftReset(HostAdapter);
+  
+  // Wait until Diagnostic Active is set in the Status Register.
+  TimeoutCounter = 5*10000;
+  while (--TimeoutCounter >= 0)
+  {
+      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+      if (StatusRegister.Bits.DiagnosticActive) 
+                 break;
+      ScsiPortStallExecution(100);
+  }
+  
+  // if inspite of waiting for time out period , if it didn't et set, then something is wrong-- so just return.
+  if (TimeoutCounter < 0) 
+         return FALSE;
+  
+  //
+  //  Wait 100 microseconds to allow completion of any initial diagnostic
+  //  activity which might leave the contents of the Status Register
+  //  unpredictable.
+  ScsiPortStallExecution(100);
+  
+  //  Wait until Diagnostic Active is reset in the Status Register.
+  TimeoutCounter = 10*10000;
+  while (--TimeoutCounter >= 0)
+  {
+      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+      if (!StatusRegister.Bits.DiagnosticActive) 
+                 break;
+      ScsiPortStallExecution(100);
+  }
+  
+  if (TimeoutCounter < 0) 
+         return FALSE;
+  
+  //  Wait until at least one of the Diagnostic Failure, Host Adapter Ready,
+  //  or Data In Register Ready bits is set in the Status Register.  
+  TimeoutCounter = 10000;
+  while (--TimeoutCounter >= 0)
+  {
+      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+      if (StatusRegister.Bits.DiagnosticFailure ||
+                 StatusRegister.Bits.HostAdapterReady ||
+             StatusRegister.Bits.DataInRegisterReady)
+         {
+               break;
+         }
+      ScsiPortStallExecution(100);
+   }
+  
+  //device didn't respond to reset
+  if (TimeoutCounter < 0)
+         return FALSE;
+  
+  //  If Diagnostic Failure is set or Host Adapter Ready is reset, then an
+  //  error occurred during the Host Adapter diagnostics.  If Data In Register
+  //  Ready is set, then there is an Error Code available.
+  if (StatusRegister.Bits.DiagnosticFailure || !StatusRegister.Bits.HostAdapterReady)
+  {
+         DebugPrint((0,"Failure - HOST ADAPTER STATUS REGISTER = %02X\n",  StatusRegister.All));
+      
+      if (StatusRegister.Bits.DataInRegisterReady)
+         {
+               DebugPrint((0,"HOST ADAPTER ERROR CODE = %d\n", BusLogic_ReadDataInRegister(HostAdapter)));
+         }
+      return FALSE;
+  }  
+  //  Indicate the Host Adapter Hard Reset completed successfully.  
+  return TRUE;
+}// end BusLogic_HardwareResetHostAdapter
+
+
+BOOLEAN 
+BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter)
+//_________________________________________________________________________
+// Routine Description: BusLogic_CheckHostAdapter checks to be sure this 
+//                      really is a BusLogic
+// Arguments:
+//              1. Host Adapter Structure
+// Return Value:
+//              TRUE : Buslogic adapter detected
+//              FALSE : Card is not a Buslogic adapter
+//_________________________________________________________________________
+{
+  BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
+  BusLogic_RequestedReplyLength_T RequestedReplyLength;
+  BOOLEAN Result = TRUE;
+
+  DebugPrint((0,"\n BusLogic -  Inside BusLogic_CheckHostAdapter funtion \n"));
+  //
+  //  Issue the Inquire Extended Setup Information command.  Only genuine
+  //  BusLogic Host Adapters and TRUE clones support this command.  Adaptec 1542C
+  //  series Host Adapters that respond to the Geometry Register I/O port will
+  //  fail this command.
+  RequestedReplyLength = sizeof(ExtendedSetupInformation);
+  if (BusLogic_Command(HostAdapter,
+                                          BusLogic_InquireExtendedSetupInformation,
+                                          &RequestedReplyLength,
+                                          sizeof(RequestedReplyLength),
+                                          &ExtendedSetupInformation,
+                                          sizeof(ExtendedSetupInformation))
+      != sizeof(ExtendedSetupInformation))
+  {
+    Result = FALSE;
+  }
+  return Result;
+}// end BusLogic_CheckHostAdapter
+
+int 
+BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter,
+                                BusLogic_OperationCode_T OperationCode,
+                                void *ParameterData,
+                                int ParameterLength,
+                                void *ReplyData,
+                                int ReplyLength)
+//______________________________________________________________________________________________
+// Routine Description:
+//                                             BusLogic_Command sends the command OperationCode to HostAdapter, optionally
+//                                             providing ParameterLength bytes of ParameterData and receiving at most
+//                                             ReplyLength bytes of ReplyData; any excess reply data is received but
+//                                             discarded.
+//
+//                                             BusLogic_Command is called exclusively during host adapter detection and
+//                                             initialization, so performance and latency are not critical, and exclusive
+//                                             access to the Host Adapter hardware is assumed.  Once the host adapter and
+//                                             driver are initialized, the only Host Adapter command that is issued is the
+//                                             single byte Execute Mailbox Command operation code, which does not require
+//                                             waiting for the Host Adapter Ready bit to be set in the Status Register.
+// Arguments:
+//              1. HostAdapter - Host Adapter structure
+//              2. OperationCode - Operation code for the command
+//                             3. ParameterData - Buffer containing parameters that needs to be passed as part 
+//                        of the command
+//                             4. ParameterLength - Number of parameters
+//                             5. ReplyData - Buffer where reply data is copied
+//                             6. ReplyLength - The length of the reply data
+// Return Value:
+//                             On success, this function returns the number of reply bytes read from
+//                             the Host Adapter (including any discarded data); on failure, it returns
+//                             -1 if the command was invalid, or -2 if a timeout occurred.
+//_________________________________________________________________________________________________
+{
+  UCHAR *ParameterPointer = (UCHAR *) ParameterData;
+  UCHAR *ReplyPointer = (UCHAR *) ReplyData;
+  BusLogic_StatusRegister_T StatusRegister;
+  BusLogic_InterruptRegister_T InterruptRegister;
+  int ReplyBytes = 0, Result;
+  long TimeoutCounter;
+
+  //  Clear out the Reply Data if provided.
+  if (ReplyLength > 0)
+    memset(ReplyData, 0, ReplyLength);
+  
+  //  If the IRQ Channel has not yet been acquired, then interrupts must be
+  //  disabled while issuing host adapter commands since a Command Complete
+  //  interrupt could occur if the IRQ Channel was previously enabled by another
+  //  BusLogic Host Adapter or another driver sharing the same IRQ Channel.
+  
+  //  Wait for the Host Adapter Ready bit to be set and the Command/Parameter
+  //  Register Busy bit to be reset in the Status Register.  
+  TimeoutCounter = 10000;
+  while (--TimeoutCounter >= 0)
+  {
+      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+      if ( StatusRegister.Bits.HostAdapterReady &&
+                 !StatusRegister.Bits.CommandParameterRegisterBusy)
+         {
+                       break;
+         }
+      ScsiPortStallExecution(100);
+  }
+  if (TimeoutCounter < 0)
+  {
+      //BusLogic_CommandFailureReason = "Timeout waiting for Host Adapter Ready";
+      Result = -2;
+      goto Done;
+  }
+  
+  //  Write the OperationCode to the Command/Parameter Register.
+  HostAdapter->HostAdapterCommandCompleted = FALSE;
+  BusLogic_WriteCommandParameterRegister(HostAdapter, (UCHAR)OperationCode);
+  
+  //Write any additional Parameter Bytes.
+  TimeoutCounter = 10000;
+  while (ParameterLength > 0 && --TimeoutCounter >= 0)
+  {
+    //
+       // Wait 100 microseconds to give the Host Adapter enough time to determine
+       // whether the last value written to the Command/Parameter Register was
+       // valid or not.  If the Command Complete bit is set in the Interrupt
+       // Register, then the Command Invalid bit in the Status Register will be
+       // reset if the Operation Code or Parameter was valid and the command
+       // has completed, or set if the Operation Code or Parameter was invalid.
+       // If the Data In Register Ready bit is set in the Status Register, then
+       // the Operation Code was valid, and data is waiting to be read back
+       // from the Host Adapter.  Otherwise, wait for the Command/Parameter
+       // Register Busy bit in the Status Register to be reset.
+      
+      ScsiPortStallExecution(100);
+      InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+      StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+      if (InterruptRegister.Bits.CommandComplete) 
+                 break;
+      if (HostAdapter->HostAdapterCommandCompleted) 
+                 break;
+      if (StatusRegister.Bits.DataInRegisterReady) 
+                 break;
+      if (StatusRegister.Bits.CommandParameterRegisterBusy)
+                 continue;
+      BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++);
+      ParameterLength--;
+  }
+  if (TimeoutCounter < 0)
+  {
+      //BusLogic_CommandFailureReason =  "Timeout waiting for Parameter Acceptance";
+      Result = -2;
+      goto Done;
+  }
+  
+  // The Modify I/O Address command does not cause a Command Complete Interrupt.
+  if (OperationCode == BusLogic_ModifyIOAddress)
+  {
+    StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+    if (StatusRegister.Bits.CommandInvalid)
+       {
+         //BusLogic_CommandFailureReason = "Modify I/O Address Invalid";
+         Result = -1;
+         goto Done;
+       }
+    Result = 0;
+    goto Done;
+  }
+  
+  //  Select an appropriate timeout value for awaiting command completion.
+  switch (OperationCode)
+  {
+    case BusLogic_InquireInstalledDevicesID0to7:
+    case BusLogic_InquireInstalledDevicesID8to15:
+    case BusLogic_InquireTargetDevices:
+      // Approximately 60 seconds. 
+      TimeoutCounter = 60*10000;
+      break;
+    default:
+      // Approximately 1 second. 
+      TimeoutCounter = 10000;
+      break;
+  }
+
+  //
+  //  Receive any Reply Bytes, waiting for either the Command Complete bit to
+  //  be set in the Interrupt Register, or for the Interrupt Handler to set the
+  //  Host Adapter Command Completed bit in the Host Adapter structure.
+  while (--TimeoutCounter >= 0)
+  {
+    InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+    StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+    if (InterruptRegister.Bits.CommandComplete) 
+               break;
+    if (HostAdapter->HostAdapterCommandCompleted) 
+               break;
+    if (StatusRegister.Bits.DataInRegisterReady)
+       {
+         if (++ReplyBytes <= ReplyLength)
+         {
+           *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter);
+         }
+         else
+         {
+                 BusLogic_ReadDataInRegister(HostAdapter);
+         }
+       }
+    if (OperationCode == BusLogic_FetchHostAdapterLocalRAM &&
+               StatusRegister.Bits.HostAdapterReady) 
+       {
+         break;
+       }
+    ScsiPortStallExecution(100);
+  }
+  if (TimeoutCounter < 0)
+  {
+      //BusLogic_CommandFailureReason = "Timeout waiting for Command Complete";
+      Result = -2;
+      goto Done;
+  }
+  
+  //  Clear any pending Command Complete Interrupt.
+  BusLogic_InterruptReset(HostAdapter);
+  
+  //  Process Command Invalid conditions.
+  if (StatusRegister.Bits.CommandInvalid)
+  {
+    //
+       // Some early BusLogic Host Adapters may not recover properly from
+       // a Command Invalid condition, so if this appears to be the case,
+       // a Soft Reset is issued to the Host Adapter.  Potentially invalid
+       // commands are never attempted after Mailbox Initialization is
+       // performed, so there should be no Host Adapter state lost by a
+       // Soft Reset in response to a Command Invalid condition.
+      
+       ScsiPortStallExecution(1000);
+       StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter);
+       if (StatusRegister.Bits.CommandInvalid             ||
+         StatusRegister.Bits.Reserved                     ||
+         StatusRegister.Bits.DataInRegisterReady          ||
+         StatusRegister.Bits.CommandParameterRegisterBusy ||
+         !StatusRegister.Bits.HostAdapterReady            ||
+         !StatusRegister.Bits.InitializationRequired      ||
+         StatusRegister.Bits.DiagnosticActive             ||
+         StatusRegister.Bits.DiagnosticFailure)
+       {
+               BusLogic_SoftReset(HostAdapter);
+               ScsiPortStallExecution(1000);
+       }
+       //BusLogic_CommandFailureReason = "Command Invalid";
+       Result = -1;
+       goto Done;
+  }
+  
+  // Handle Excess Parameters Supplied conditions.
+  if (ParameterLength > 0)
+  {
+      //BusLogic_CommandFailureReason = "Excess Parameters Supplied";
+      Result = -1;
+      goto Done;
+  }
+  
+  //  Indicate the command completed successfully.
+  Result = ReplyBytes;
+  
+  //  Restore the interrupt status if necessary and return.
+Done:
+  return Result;
+}// end BusLogic_Command
+
+
+BOOLEAN 
+BusLogic_ReadHostAdapterConfiguration(BusLogic_HostAdapter_T  *HostAdapter)
+//___________________________________________________________________________________________
+// Routine Description:
+//                                     BusLogic_ReadHostAdapterConfiguration reads the Configuration Information
+//                                     from Host Adapter and initializes the Host Adapter structure.
+// Arguments:
+//              1. Host adapter structure
+// Return Value:
+//              TRUE : Configuration read properly
+//              FALSE : Encounter failure
+//___________________________________________________________________________________________
+{
+  BusLogic_BoardID_T BoardID;
+  BusLogic_Configuration_T Configuration;
+  BusLogic_SetupInformation_T SetupInformation;
+  BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
+  BusLogic_HostAdapterModelNumber_T HostAdapterModelNumber;
+  BusLogic_FirmwareVersion3rdDigit_T FirmwareVersion3rdDigit;
+  BusLogic_FirmwareVersionLetter_T FirmwareVersionLetter;
+  BusLogic_PCIHostAdapterInformation_T PCIHostAdapterInformation;
+  BusLogic_FetchHostAdapterLocalRAMRequest_T FetchHostAdapterLocalRAMRequest;
+  BusLogic_AutoSCSIData_T AutoSCSIData;
+  BusLogic_GeometryRegister_T GeometryRegister;
+  BusLogic_RequestedReplyLength_T RequestedReplyLength;
+  UCHAR *TargetPointer, Character;
+  ULONG /*TargetID,*/ i;
+  
+  //  Issue the Inquire Board ID command.  
+  if (BusLogic_Command(HostAdapter, 
+                                          BusLogic_InquireBoardID,
+                                          NULL,
+                                          0,
+                              &BoardID, sizeof(BoardID))  
+         != sizeof(BoardID))
+  {
+               DebugPrint((0,"BusLogic_Failure: INQUIRE BOARD ID"));
+               return FALSE;
+  }
+
+  //  Issue the Inquire Configuration command.
+  if (BusLogic_Command(HostAdapter, 
+                          BusLogic_InquireConfiguration, 
+                                          NULL, 
+                                          0,
+                              &Configuration, sizeof(Configuration))
+      != sizeof(Configuration))
+  {
+         DebugPrint((0,"BusLogic_Failure: INQUIRE CONFIGURATION"));
+      return FALSE;
+  }
+  
+  //  Issue the Inquire Setup Information command.
+  RequestedReplyLength = sizeof(SetupInformation);
+  if (BusLogic_Command(HostAdapter, 
+                                          BusLogic_InquireSetupInformation,
+                              &RequestedReplyLength,
+                                          sizeof(RequestedReplyLength),
+                              &SetupInformation, 
+                                          sizeof(SetupInformation))
+      != sizeof(SetupInformation))
+  {
+        DebugPrint((0,"BusLogic_Failure: INQUIRE SETUP INFORMATION"));
+        return FALSE;
+  }
+  
+  //  Issue the Inquire Extended Setup Information command.
+  RequestedReplyLength = sizeof(ExtendedSetupInformation);
+  if (BusLogic_Command(HostAdapter, 
+                          BusLogic_InquireExtendedSetupInformation,
+                                          &RequestedReplyLength, 
+                                          sizeof(RequestedReplyLength),
+                                          &ExtendedSetupInformation,
+                                          sizeof(ExtendedSetupInformation))
+      != sizeof(ExtendedSetupInformation))
+  {
+         DebugPrint((0,"BusLogic_Failure: INQUIRE EXTENDED SETUP INFORMATION"));
+      return FALSE;
+  }
+  
+  //  Issue the Inquire Firmware Version 3rd Digit command.
+  FirmwareVersion3rdDigit = '\0';
+  if (BoardID.FirmwareVersion1stDigit > '0')
+  {
+    if (BusLogic_Command(HostAdapter,
+                                BusLogic_InquireFirmwareVersion3rdDigit,
+                                                NULL,
+                                                0,
+                                                &FirmwareVersion3rdDigit,
+                                                sizeof(FirmwareVersion3rdDigit))
+               != sizeof(FirmwareVersion3rdDigit))
+       {
+               DebugPrint((0,"BusLogic_Failure: INQUIRE FIRMWARE 3RD DIGIT"));
+       return FALSE;
+       }
+  }
+  
+  //  Issue the Inquire Host Adapter Model Number command.
+  RequestedReplyLength = sizeof(HostAdapterModelNumber);
+  if (BusLogic_Command(HostAdapter, 
+                                          BusLogic_InquireHostAdapterModelNumber,
+                                          &RequestedReplyLength, 
+                                          sizeof(RequestedReplyLength),
+                                          &HostAdapterModelNumber,
+                                          sizeof(HostAdapterModelNumber))
+         != sizeof(HostAdapterModelNumber))
+  {
+         DebugPrint((0,"BusLogic_Failure: INQUIRE HOST ADAPTER MODEL NUMBER"));
+         return FALSE;
+  }
+  
+  //  BusLogic MultiMaster Host Adapters can be identified by their model number
+  //  and the major version number of their firmware as follows:
+  //   
+  //  5.xx     BusLogic "W" Series Host Adapters:
+  //             BT-948/958/958D
+  //  Save the Model Name and Host Adapter Name in the Host Adapter structure.
+  TargetPointer = HostAdapter->ModelName;
+  *TargetPointer++ = 'B';
+  *TargetPointer++ = 'T';
+  *TargetPointer++ = '-';
+  for (i = 0; i < sizeof(HostAdapterModelNumber); i++)
+  {
+      Character = HostAdapterModelNumber[i];
+      if (Character == ' ' || Character == '\0') break;
+      *TargetPointer++ = Character;
+  }
+  *TargetPointer++ = '\0';
+  
+  // Save the Firmware Version in the Host Adapter structure.
+  TargetPointer = HostAdapter->FirmwareVersion;
+  *TargetPointer++ = BoardID.FirmwareVersion1stDigit;
+  *TargetPointer++ = '.';
+  *TargetPointer++ = BoardID.FirmwareVersion2ndDigit;
+  if (FirmwareVersion3rdDigit != ' ' && FirmwareVersion3rdDigit != '\0')
+    *TargetPointer++ = FirmwareVersion3rdDigit;
+  *TargetPointer = '\0';
+  
+  // Issue the Inquire Firmware Version Letter command.
+  if (strcmp((char*)HostAdapter->FirmwareVersion, "3.3") >= 0)
+  {
+      if (BusLogic_Command(HostAdapter,
+                                                  BusLogic_InquireFirmwareVersionLetter,
+                                                  NULL,
+                                                  0,
+                                                  &FirmwareVersionLetter,
+                                                  sizeof(FirmwareVersionLetter))
+                 != sizeof(FirmwareVersionLetter))
+         {
+                 DebugPrint((0,"BusLogic_Failure: INQUIRE FIRMWARE VERSION LETTER"));
+                 return FALSE;
+         }
+      if (FirmwareVersionLetter != ' ' && FirmwareVersionLetter != '\0')
+         {
+               *TargetPointer++ = FirmwareVersionLetter;
+         }
+      *TargetPointer = '\0';
+  }
+  
+  
+  //  Save the Host Adapter SCSI ID in the Host Adapter structure.
+  HostAdapter->SCSI_ID = Configuration.HostAdapterID;
+  
+  //  Determine the Bus Type and save it in the Host Adapter structure, determine
+  //  and save the IRQ Channel if necessary, and determine and save the DMA
+  //  Channel for ISA Host Adapters.
+  HostAdapter->HostAdapterBusType =  BusLogic_HostAdapterBusTypes[HostAdapter->ModelName[3] - '4'];
+    
+  GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter);
+  
+  //  Determine whether Extended Translation is enabled and save it in
+  //  the Host Adapter structure.
+  //  HostAdapter->ExtendedTranslationEnabled =  GeometryRegister.Bits.ExtendedTranslationEnabled;
+  HostAdapter->ExtendedTranslationEnabled =  GeometryRegister.All;
+  
+  
+  //  Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide
+  //  SCSI flag, Differential SCSI flag, SCAM Supported flag, and
+  //  Ultra SCSI flag in the Host Adapter structure.
+  HostAdapter->HostAdapterScatterGatherLimit =  ExtendedSetupInformation.ScatterGatherLimit;
+
+  HostAdapter->DriverScatterGatherLimit =   HostAdapter->HostAdapterScatterGatherLimit;
+
+  if (HostAdapter->HostAdapterScatterGatherLimit > BusLogic_ScatterGatherLimit)
+  {
+    HostAdapter->DriverScatterGatherLimit = BusLogic_ScatterGatherLimit;
+  }
+  if (ExtendedSetupInformation.Misc.LevelSensitiveInterrupt)
+  {
+    HostAdapter->LevelSensitiveInterrupt = TRUE;
+  }
+
+  HostAdapter->HostWideSCSI = ExtendedSetupInformation.HostWideSCSI;
+
+  HostAdapter->HostDifferentialSCSI =  ExtendedSetupInformation.HostDifferentialSCSI;
+
+  HostAdapter->HostSupportsSCAM = ExtendedSetupInformation.HostSupportsSCAM;
+
+  HostAdapter->HostUltraSCSI = ExtendedSetupInformation.HostUltraSCSI;
+  
+  
+  //  Determine whether Extended LUN Format CCBs are supported and save the
+  //  information in the Host Adapter structure.
+  if (HostAdapter->FirmwareVersion[0] == '5' ||
+      (HostAdapter->FirmwareVersion[0] == '4' && HostAdapter->HostWideSCSI))
+  {
+    HostAdapter->ExtendedLUNSupport = TRUE;
+  }
+  // Issue the Inquire PCI Host Adapter Information command to read the
+  // Termination Information from "W" series MultiMaster Host Adapters.
+  if (HostAdapter->FirmwareVersion[0] == '5')
+  {
+      if (BusLogic_Command(HostAdapter,
+                                                  BusLogic_InquirePCIHostAdapterInformation,
+                                                  NULL,
+                                                  0,
+                                                  &PCIHostAdapterInformation,
+                                                  sizeof(PCIHostAdapterInformation))
+                 != sizeof(PCIHostAdapterInformation))
+         {
+                 DebugPrint((0, "BusLogic_Failure: INQUIRE PCI HOST ADAPTER INFORMATION"));
+                 return FALSE; 
+         }
+
+       // Save the Termination Information in the Host Adapter structure.
+      if (PCIHostAdapterInformation.GenericInfoValid)
+         {
+               HostAdapter->TerminationInfoValid = TRUE;
+               HostAdapter->LowByteTerminated =  PCIHostAdapterInformation.LowByteTerminated;
+               HostAdapter->HighByteTerminated = PCIHostAdapterInformation.HighByteTerminated;
+         }
+  }   
+  
+  //  Issue the Fetch Host Adapter Local RAM command to read the AutoSCSI data
+  //  from "W" and "C" series MultiMaster Host Adapters.
+  if (HostAdapter->FirmwareVersion[0] >= '4')
+  {
+         FetchHostAdapterLocalRAMRequest.ByteOffset =  BusLogic_AutoSCSI_BaseOffset;
+      FetchHostAdapterLocalRAMRequest.ByteCount = sizeof(AutoSCSIData);
+      if (BusLogic_Command(HostAdapter,
+                                  BusLogic_FetchHostAdapterLocalRAM,
+                                                  &FetchHostAdapterLocalRAMRequest,
+                                                  sizeof(FetchHostAdapterLocalRAMRequest),
+                                                  &AutoSCSIData,
+                                                  sizeof(AutoSCSIData))
+                 != sizeof(AutoSCSIData))
+         {
+                 DebugPrint((0, "BusLogic_Failure: FETCH HOST ADAPTER LOCAL RAM"));
+                 return FALSE;
+         }
+         // Save the Parity Checking Enabled, Bus Reset Enabled, and Termination
+         // Information in the Host Adapter structure.
+      HostAdapter->ParityCheckingEnabled = AutoSCSIData.ParityCheckingEnabled;
+      HostAdapter->BusResetEnabled = AutoSCSIData.BusResetEnabled;
+      
+      // Save the Wide Permitted, Fast Permitted, Synchronous Permitted,
+         // Disconnect Permitted, Ultra Permitted, and SCAM Information in the
+         // Host Adapter structure.
+      HostAdapter->WidePermitted = AutoSCSIData.WidePermitted;
+      HostAdapter->FastPermitted = AutoSCSIData.FastPermitted;
+      HostAdapter->SynchronousPermitted =      AutoSCSIData.SynchronousPermitted;
+      HostAdapter->DisconnectPermitted =       AutoSCSIData.DisconnectPermitted;
+      if (HostAdapter->HostUltraSCSI)
+         {
+               HostAdapter->UltraPermitted = AutoSCSIData.UltraPermitted;
+         }
+      if (HostAdapter->HostSupportsSCAM)
+         {
+                 HostAdapter->SCAM_Enabled = AutoSCSIData.SCAM_Enabled;
+                 HostAdapter->SCAM_Level2 = AutoSCSIData.SCAM_Level2;
+         }
+    }  
+       
+    // Determine the maximum number of Target IDs and Logical Units supported by
+    // this driver for Wide and Narrow Host Adapters.
+       HostAdapter->MaxTargetDevices = (HostAdapter->HostWideSCSI ? 16 : 8);
+       HostAdapter->MaxLogicalUnits = (HostAdapter->ExtendedLUNSupport ? 32 : 8);
+       
+       // Select appropriate values for the Mailbox Count, 
+    // Initial CCBs, and Incremental CCBs variables based on whether or not Strict
+    // Round Robin Mode is supported.  If Strict Round Robin Mode is supported,
+    // then there is no performance degradation in using the maximum possible
+    // number of Outgoing and Incoming Mailboxes and allowing the Tagged and
+    // Untagged Queue Depths to determine the actual utilization.  If Strict Round
+    // Robin Mode is not supported, then the Host Adapter must scan all the
+    // Outgoing Mailboxes whenever an Outgoing Mailbox entry is made, which can
+    // cause a substantial performance penalty.  The host adapters actually have
+    // room to store the following number of CCBs internally; that is, they can
+    // internally queue and manage this many active commands on the SCSI bus
+    // simultaneously.  Performance measurements demonstrate that the Driver Queue
+    // Depth should be set to the Mailbox Count, rather than the Host Adapter
+    // Queue Depth (internal CCB capacity), as it is more efficient to have the
+    // queued commands waiting in Outgoing Mailboxes if necessary than to block
+    // the process in the higher levels of the SCSI Subsystem.
+    //
+       // 192    BT-948/958/958D
+       if (HostAdapter->FirmwareVersion[0] == '5')
+       {
+               HostAdapter->HostAdapterQueueDepth = 192;
+       }
+       
+       if (strcmp((char*)HostAdapter->FirmwareVersion, "3.31") >= 0)
+    {
+      HostAdapter->StrictRoundRobinModeSupport = TRUE;
+      HostAdapter->MailboxCount = BusLogic_MaxMailboxes;
+    }
+    
+       //
+    // Tagged Queuing support is available and operates properly on all "W" series
+    // MultiMaster Host Adapters, on "C" series MultiMaster Host Adapters with
+    // firmware version 4.22 and above, and on "S" series MultiMaster Host
+    // Adapters with firmware version 3.35 and above.
+    HostAdapter->TaggedQueuingPermitted = 0xFFFF;
+    
+       //
+    // Determine the Host Adapter BIOS Address if the BIOS is enabled and
+    ///save it in the Host Adapter structure.  The BIOS is disabled if the
+    // BIOS_Address is 0.
+    HostAdapter->BIOS_Address = ExtendedSetupInformation.BIOS_Address << 12;
+    
+    //
+    //Initialize parameters for MultiMaster Host Adapters.
+
+    //
+    // Initialize the Host Adapter Full Model Name from the Model Name.
+    strcpy((char*)HostAdapter->FullModelName, "BusLogic ");
+    strcat((char*)HostAdapter->FullModelName, (char*)HostAdapter->ModelName);
+   
+    // Tagged Queuing is only allowed if Disconnect/Reconnect is permitted.
+    // Therefore, mask the Tagged Queuing Permitted Default bits with the
+    // Disconnect/Reconnect Permitted bits.
+    HostAdapter->TaggedQueuingPermitted &= HostAdapter->DisconnectPermitted;
+    
+       // Select an appropriate value for Bus Settle Time either from a BusLogic
+    // Driver Options specification, or from BusLogic_DefaultBusSettleTime.
+    HostAdapter->BusSettleTime = BusLogic_DefaultBusSettleTime;
+    
+       // Indicate reading the Host Adapter Configuration completed successfully.
+    return TRUE;
+}// end BusLogic_ReadHostAdapterConfiguration
+
+BOOLEAN 
+BusLogic_InitializeHostAdapter(PHW_DEVICE_EXTENSION deviceExtension, 
+                                                          PPORT_CONFIGURATION_INFORMATION ConfigInfo)
+//_____________________________________________________________________________________________
+// Routine Description:
+//                                     BusLogic_InitializeHostAdapter initializes Host Adapter.  This is the only
+//                                     function called during SCSI Host Adapter detection which modifies the state
+//                                     of the Host Adapter from its initial power on or hard reset state.
+// Arguments:
+//              1. device extension
+//              2. port config information
+// Return Value:
+//              TRUE : Host Adapter initialization completed successfully
+//              FALSE : Initialization failed 
+//______________________________________________________________________________________________
+{
+  BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+  BusLogic_ExtendedMailboxRequest_T ExtendedMailboxRequest;
+  UCHAR RoundRobinModeRequest;
+  UCHAR SetCCBFormatRequest;
+  int TargetID, LunID;
+
+  // Used when we get the Physical address of the mail boxes
+  ULONG length;
+  
+  // Initialize the pointers to the first and last CCBs that are queued for
+  // completion processing.
+  HostAdapter->FirstCompletedCCB = NULL;
+  HostAdapter->LastCompletedCCB = NULL;
+  
+  //  Initialize the Bus Device Reset Pending CCB, Tagged Queuing Active,
+  //  Command Successful Flag, Active Commands, and Commands Since Reset
+  //  for each Target Device.
+  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+  {
+      HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
+      HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = FALSE;
+      HostAdapter->TargetFlags[TargetID].CommandSuccessfulFlag = FALSE;
+      
+         HostAdapter->ActiveCommandsPerTarget[TargetID] = 0;
+         for (LunID = 0; LunID < HostAdapter->MaxLogicalUnits; LunID++)
+               HostAdapter->ActiveCommandsPerLun[TargetID][LunID] = 0;
+
+      HostAdapter->CommandsSinceReset[TargetID] = 0;
+  }
+  
+  // Convert virtual to physical mailbox address.
+  deviceExtension->NoncachedExtension->MailboxPA =   ScsiPortConvertPhysicalAddressToUlong(
+                                                                                                                                               ScsiPortGetPhysicalAddress(deviceExtension,
+                                                                                                                                                                                                  NULL,
+                                                                                                                                                                                                  deviceExtension->NoncachedExtension->MailboxOut,
+                                                                                                                                                                                                  &length));
+
+  HostAdapter->FirstOutgoingMailbox = (BusLogic_OutgoingMailbox_T *) deviceExtension->NoncachedExtension->MailboxOut;
+  HostAdapter->LastOutgoingMailbox =  HostAdapter->FirstOutgoingMailbox + HostAdapter->MailboxCount - 1;
+  HostAdapter->NextOutgoingMailbox =  HostAdapter->FirstOutgoingMailbox;
+
+  HostAdapter->FirstIncomingMailbox = (BusLogic_IncomingMailbox_T *) deviceExtension->NoncachedExtension->MailboxIn;
+  HostAdapter->LastIncomingMailbox =  HostAdapter->FirstIncomingMailbox + HostAdapter->MailboxCount - 1;
+  HostAdapter->NextIncomingMailbox =  HostAdapter->FirstIncomingMailbox;
+
+  //  Initialize the Outgoing and Incoming Mailbox structures.
+  memset(HostAdapter->FirstOutgoingMailbox, 
+            0,
+                HostAdapter->MailboxCount * sizeof(BusLogic_OutgoingMailbox_T));
+  memset(HostAdapter->FirstIncomingMailbox, 
+            0,
+                HostAdapter->MailboxCount * sizeof(BusLogic_IncomingMailbox_T));
+  
+
+  ExtendedMailboxRequest.MailboxCount = HostAdapter->MailboxCount;
+  ExtendedMailboxRequest.BaseMailboxAddress = deviceExtension->NoncachedExtension->MailboxPA ;
+
+  if (BusLogic_Command(HostAdapter,
+                                          BusLogic_InitializeExtendedMailbox,
+                                          &ExtendedMailboxRequest,
+                                          sizeof(ExtendedMailboxRequest), 
+                                          NULL, 0) 
+          < 0)
+  {
+      DebugPrint((0,"BusLogic_Failure: MAILBOX INITIALIZATION"));
+         return FALSE;
+  }
+    
+  //  Enable Strict Round Robin Mode if supported by the Host Adapter.  In
+  //  Strict Round Robin Mode, the Host Adapter only looks at the next Outgoing
+  //  Mailbox for each new command, rather than scanning through all the
+  //  Outgoing Mailboxes to find any that have new commands in them.  Strict
+  //  Round Robin Mode is significantly more efficient.
+  if (HostAdapter->StrictRoundRobinModeSupport)
+  {
+               RoundRobinModeRequest = BusLogic_StrictRoundRobinMode;
+               if (BusLogic_Command(HostAdapter, 
+                                                        BusLogic_EnableStrictRoundRobinMode,
+                                                        &RoundRobinModeRequest,
+                                                        sizeof(RoundRobinModeRequest), 
+                                                        NULL,
+                                                        0)
+                       < 0)
+               {
+                       DebugPrint((0,"BusLogic_Failure: ENABLE STRICT ROUND ROBIN MODE"));
+                       return FALSE;
+               }
+   }
+  
+  //  For Host Adapters that support Extended LUN Format CCBs, issue the Set CCB
+  //  Format command to allow 32 Logical Units per Target Device.
+
+  if (HostAdapter->ExtendedLUNSupport)
+  {
+      SetCCBFormatRequest = BusLogic_ExtendedLUNFormatCCB;
+      if (BusLogic_Command(HostAdapter,
+                                                  BusLogic_SetCCBFormat,
+                                                  &SetCCBFormatRequest,
+                                                  sizeof(SetCCBFormatRequest),
+                                                  NULL,
+                                                  0)
+                 < 0)
+         {
+                 DebugPrint((0, "BusLogic_Failure: SET CCB FORMAT"));
+                 return FALSE;
+         }
+    }
+  //  Announce Successful Initialization.  
+  if (!HostAdapter->HostAdapterInitialized)
+  {
+      DebugPrint((0,"Info *** %s Initialized Successfully ***\n",  HostAdapter, HostAdapter->FullModelName));      
+  }
+  else
+  {
+         DebugPrint((0,"Warning *** %s Initialized Successfully ***\n",        HostAdapter, HostAdapter->FullModelName));
+  }
+  HostAdapter->HostAdapterInitialized = TRUE;  
+  //  Indicate the Host Adapter Initialization completed successfully.
+  return TRUE;
+}// end BusLogic_InitializeHostAdapter
+
+
+BOOLEAN 
+BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T *HostAdapter)
+//_________________________________________________________________________________________
+// Routine Description:
+//                                     BusLogic_TargetDeviceInquiry inquires about the Target Devices accessible
+//                                     through Host Adapter.
+// Arguments:
+//              1. Host Adpater structure
+//              2. 
+// Return Value:
+//              TRUE : Inquiry successful
+//              FALSE : Inquiry failed
+//_________________________________________________________________________
+{
+  BusLogic_InstalledDevices_T InstalledDevices;
+//  BusLogic_InstalledDevices8_T InstalledDevicesID0to7;
+  BusLogic_SetupInformation_T SetupInformation;
+  BusLogic_SynchronousPeriod_T SynchronousPeriod;
+  BusLogic_RequestedReplyLength_T RequestedReplyLength;
+  int TargetID;
+  
+  //  Wait a few seconds between the Host Adapter Hard Reset which initiates
+  //  a SCSI Bus Reset and issuing any SCSI Commands.  Some SCSI devices get
+  //  confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
+  ScsiPortStallExecution(HostAdapter->BusSettleTime);
+
+  //
+  //  Issue the Inquire Target Devices command for host adapters with firmware
+  //  version 4.25 or later, or the Inquire Installed Devices ID 0 to 7 command
+  //  for older host adapters.  This is necessary to force Synchronous Transfer
+  //  Negotiation so that the Inquire Setup Information and Inquire Synchronous
+  //  Period commands will return valid data.  The Inquire Target Devices command
+  //  is preferable to Inquire Installed Devices ID 0 to 7 since it only probes
+  //  Logical Unit 0 of each Target Device.
+  if (strcmp((char*)HostAdapter->FirmwareVersion, "4.25") >= 0)
+  {
+      if (BusLogic_Command(HostAdapter,
+                                                  BusLogic_InquireTargetDevices, 
+                                                  NULL,
+                                                  0,
+                                                  &InstalledDevices,
+                                                  sizeof(InstalledDevices))
+                       != sizeof(InstalledDevices))
+         {
+                 DebugPrint((0, "BusLogic_Failure: INQUIRE TARGET DEVICES"));
+                 return FALSE;
+         }
+      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+         {
+                       HostAdapter->TargetFlags[TargetID].TargetExists = (InstalledDevices & (1 << TargetID) ? TRUE : FALSE);
+         }
+  }
+  
+  //  Issue the Inquire Setup Information command.
+  RequestedReplyLength = sizeof(SetupInformation);
+  if (BusLogic_Command(HostAdapter, 
+                                          BusLogic_InquireSetupInformation,
+                                          &RequestedReplyLength,
+                                          sizeof(RequestedReplyLength),
+                      &SetupInformation, sizeof(SetupInformation))
+      != sizeof(SetupInformation))
+  {
+      DebugPrint((0, "BusLogic_Failure: INQUIRE SETUP INFORMATION"));
+         return FALSE;
+  }
+
+  for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+  {
+      HostAdapter->SynchronousOffset[TargetID] = (TargetID < 8
+                                                                                                 ? SetupInformation.SynchronousValuesID0to7[TargetID].Offset
+                                                                                                 : SetupInformation.SynchronousValuesID8to15[TargetID-8].Offset);
+  }
+  if (strcmp((char*)HostAdapter->FirmwareVersion, "5.06L") >= 0)
+  {
+    for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+       {
+      HostAdapter->TargetFlags[TargetID].WideTransfersActive = (TargetID < 8
+                                                                                                                               ? (SetupInformation.WideTransfersActiveID0to7 & (1 << TargetID)
+                                                                                                                                       ? TRUE : FALSE)
+                                                                                                                               : (SetupInformation.WideTransfersActiveID8to15 & (1 << (TargetID-8))
+                                                                                                                                       ? TRUE : FALSE));
+       }
+  }
+
+  
+  //  Issue the Inquire Synchronous Period command.
+  if (HostAdapter->FirmwareVersion[0] >= '3')
+  {
+      RequestedReplyLength = sizeof(SynchronousPeriod);
+      if (BusLogic_Command(HostAdapter,
+                                                  BusLogic_InquireSynchronousPeriod,
+                                                  &RequestedReplyLength,
+                                                  sizeof(RequestedReplyLength),
+                                                  &SynchronousPeriod, 
+                                                  sizeof(SynchronousPeriod))
+               != sizeof(SynchronousPeriod))
+         {
+                 DebugPrint((0, "BusLogic_Failure: INQUIRE SYNCHRONOUS PERIOD"));
+                 return FALSE;
+         }
+      for (TargetID = 0; TargetID < HostAdapter->MaxTargetDevices; TargetID++)
+         {
+               HostAdapter->SynchronousPeriod[TargetID] = SynchronousPeriod[TargetID];
+         }
+  }
+  
+  //  Indicate the Target Device Inquiry completed successfully.
+  return TRUE;
+}// end BusLogic_TargetDeviceInquiry
+
+VOID
+BusLogic_InitializeCCB(        PBuslogic_CCB_T CCB)
+{
+  CCB->Opcode = BusLogic_InitiatorCCB;
+  CCB->DataDirection = 0;              
+  CCB->TagEnable = 0;                  
+  CCB->QueueTag = 0 ;                  
+  CCB->CDB_Length = 0;                 
+  CCB->SenseDataLength = 0;            
+  CCB->DataLength = 0;
+  CCB->DataPointer = 0;
+  CCB->HostAdapterStatus = 0;
+  CCB->TargetDeviceStatus = 0;
+  CCB->TargetID = 0;           
+  CCB->LogicalUnit = 0;                
+  CCB->LegacyTagEnable = 0;    
+  CCB->LegacyQueueTag = 0;     
+    
+  CCB->SenseDataPointer = 0;
+
+  // BusLogic Driver Defined Portion
+  CCB->Status = 0;
+  CCB->SerialNumber = 0;
+  CCB->Next = NULL;
+  CCB->HostAdapter = NULL;
+  
+  CCB->CompletionCode = 0;
+  // Pointer to the CCB
+  CCB->SrbAddress = NULL;
+  CCB->AbortSrb = NULL;
+}
+
+BOOLEAN
+STDCALL
+BT958HwStartIO(IN PVOID HwDeviceExtension,
+                          IN PSCSI_REQUEST_BLOCK Srb
+              )
+//__________________________________________________________________________________
+// Routine Description:
+//                    As soon as it receives the initial request for a 
+//                    target peripheral, the OS-specific port driver calls 
+//                    the HwScsiStartIo routine with an input SRB. After 
+//                    this call, the HBA miniport driver owns the request 
+//                     and is expected to complete it.
+// Arguments:
+//           1. DeviceExtension: Points to the miniport driver's per-HBA storage area. 
+//                      2. Srb: Points to the SCSI request block to be started. 
+// Return Value:
+//              TRUE : HwScsiStartIo returns TRUE to acknowledge receipt of the SRB.
+//__________________________________________________________________________________
+{
+       PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+//    PNONCACHED_EXTENSION noncachedExtension =   deviceExtension->NoncachedExtension;
+       BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+//    BusLogic_OutgoingMailbox_T mailboxOut;
+    PSCSI_REQUEST_BLOCK AbortSRB;
+
+       PBuslogic_CCB_T ccb;
+       BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[Srb->TargetId];
+  
+        
+    DebugPrint((0,"BusLogic: Inside Start IO routine\n"));
+  
+    // Make sure that this request isn't too long for the adapter.  If so
+    // bounce it back as an invalid request
+    if (BusLogic_CDB_MaxLength &&
+        (BusLogic_CDB_MaxLength< Srb->CdbLength)) 
+       {
+
+        DebugPrint((0,"DebugPrint: Srb->CdbLength [%d] > MaxCdbLength [%d].  Invalid request\n",
+                    Srb->CdbLength,
+                    BusLogic_CDB_MaxLength
+                  ));
+
+        Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+        ScsiPortNotification(RequestComplete,deviceExtension,Srb);
+        ScsiPortNotification(NextRequest,deviceExtension,NULL);
+        return TRUE;
+    }
+
+    switch (Srb->Function) 
+       { 
+        /*
+               Sirish, 10th June 2002 
+               // Check if command is a WMI request.
+               case SRB_FUNCTION_WMI:
+                       // Process the WMI request and return.
+                       return BT958WmiSrb(HwDeviceExtension, (PSCSI_WMI_REQUEST_BLOCK) Srb);
+               */
+        
+        case SRB_FUNCTION_EXECUTE_SCSI:
+
+                       // get the ccb structure from the extension
+                       ccb = Srb->SrbExtension;
+                       BusLogic_InitializeCCB(ccb);
+
+                       // Save SRB back pointer in CCB.
+                       ccb->SrbAddress = Srb;
+
+            // Build CCB. - Have some way of knowing that a srb has already been 
+                       // completed and you just need to return from here
+            BusLogic_QueueCommand(HwDeviceExtension ,Srb,      ccb);   
+
+                       // Place the CCB in an Outgoing Mailbox.  The higher levels of the SCSI
+                       // Subsystem should not attempt to queue more commands than can be placed
+                       // in Outgoing Mailboxes, so there should always be one free.  In the
+                       // unlikely event that there are none available, wait 1 second and try
+                       // again.  If that fails, the Host Adapter is probably hung so signal an
+                       // error as a Host Adapter Hard Reset should be initiated soon.
+
+                       if (!BusLogic_WriteOutgoingMailbox(deviceExtension , BusLogic_MailboxStartCommand, ccb))
+                       {
+                               DebugPrint((0,"Unable to write Outgoing Mailbox - " "Pausing for 1 second\n"));
+                               ScsiPortStallExecution(1000);
+                               if (!BusLogic_WriteOutgoingMailbox(deviceExtension , BusLogic_MailboxStartCommand, ccb))
+                               {
+                                         DebugPrint((0,"Still unable to write Outgoing Mailbox - " "Host Adapter Dead?\n"));
+
+                                         Srb->SrbStatus = SRB_STATUS_ERROR;
+                                         ScsiPortNotification(RequestComplete,deviceExtension,Srb);
+                                         ScsiPortNotification(NextRequest,deviceExtension,NULL);
+
+                               }
+                       }
+                       else 
+                       {
+                               /*
+                                * Reverted to pre 1.1.0.0 control flow
+                                * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts
+                                * And the fix for that in 1.1.0.1 causes BSODs in XP
+                                * Side note: Ben: the Buslogic emulation never exports more than 1 lun
+                                */
+                               if (TargetFlags->TaggedQueuingActive
+                                       && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS)  {
+                                       ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
+                               }
+                               else    {
+                                       ScsiPortNotification(NextRequest,deviceExtension,NULL);
+                               }
+                       } 
+                       return TRUE;
+
+               case SRB_FUNCTION_ABORT_COMMAND:
+                       
+                       // Get CCB to abort.
+                       ccb = Srb->NextSrb->SrbExtension;
+
+                       // Set abort SRB for completion.
+                       ccb->AbortSrb = Srb;
+
+            AbortSRB = ScsiPortGetSrb(HwDeviceExtension, 
+                                                                         Srb->PathId, 
+                                                                         Srb->TargetId, 
+                                                                         Srb->Lun, 
+                                                                         Srb->QueueTag);
+                       
+                       if ((AbortSRB != Srb->NextSrb) || (AbortSRB->SrbStatus != SRB_STATUS_PENDING)) 
+                       {
+                               Srb->SrbStatus = SRB_STATUS_ABORT_FAILED;
+                               ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb);
+                               ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
+                               return TRUE;
+                       }    
+
+                       // write the abort information into a mailbox
+                       if (BusLogic_WriteOutgoingMailbox( deviceExtension, BusLogic_MailboxAbortCommand, ccb))
+                       {
+                         DebugPrint((0, "BusLogic_Warning: Aborting CCB #%ld to Target %d\n",ccb->SerialNumber, Srb->TargetId));
+                         // Adapter ready for next request.
+
+                               /*
+                                * Reverted to pre 1.1.0.0 control flow
+                                * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts
+                                * And the fix for that in 1.1.0.1 causes BSODs in XP
+                                * Side note: Ben: the Buslogic emulation never exports more than 1 lun
+                                */
+                               if (TargetFlags->TaggedQueuingActive
+                                       && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS)  {
+                                       ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
+                               }
+                               else    {
+                                       ScsiPortNotification(NextRequest,deviceExtension,NULL);
+                               }
+                       }
+                       else
+                       {
+                         DebugPrint((0,"BusLogic_Warning: Unable to Abort CCB #%ld to Target %d - ""No Outgoing Mailboxes\n",ccb->SerialNumber, Srb->TargetId));
+                         Srb->SrbStatus = SRB_STATUS_ERROR;
+                         ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb);
+                         ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
+                       }
+                       return TRUE;
+
+
+               case SRB_FUNCTION_RESET_BUS:
+                       
+                       // Reset SCSI bus. 
+                       DebugPrint((0,"BusLogic - SRB_FUNCTION_RESET_BUS,srb=%x \n",Srb)); 
+                       BT958HwResetBus(HwDeviceExtension, Srb->PathId);
+
+                       Srb->SrbStatus = SRB_STATUS_SUCCESS;
+                       ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb);
+                       ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
+                       return TRUE;
+                       
+
+        case SRB_FUNCTION_RESET_DEVICE:
+                       
+                       ccb = Srb->SrbExtension;
+                       BusLogic_InitializeCCB(ccb);
+
+                       // Save SRB back pointer in CCB.
+                       ccb->SrbAddress = Srb;
+
+            if(!BusLogic_SendBusDeviceReset(HostAdapter, Srb))
+                       {
+                           BT958HwResetBus(HwDeviceExtension, SP_UNTAGGED);
+                               Srb->SrbStatus = SRB_STATUS_SUCCESS;
+                               ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb);
+                               ScsiPortNotification(NextRequest, HwDeviceExtension, NULL);
+                               return TRUE;                    
+                       }  
+                       
+                       /*
+                        * Reverted to pre 1.1.0.0 control flow
+                        * The 1.1.0.0 control flow causes the .NET Server freeze during installs/restarts
+                        * And the fix for that in 1.1.0.1 causes BSODs in XP
+                        * Side note: Ben: the Buslogic emulation never exports more than 1 lun
+                        */
+                       if (TargetFlags->TaggedQueuingActive
+                               && HostAdapter->ActiveCommandsPerLun[Srb->TargetId][Srb->Lun] < BUSLOGIC_MAXIMUM_TAGS)  {
+                               ScsiPortNotification(NextLuRequest, HwDeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun);
+                       }
+                       else    {
+                               ScsiPortNotification(NextRequest,deviceExtension,NULL);
+                       }
+                       return TRUE;
+                       
+        default:
+            
+            // Set error, complete request and signal ready for next request.
+                       Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
+            ScsiPortNotification(RequestComplete,deviceExtension,Srb);
+            ScsiPortNotification(NextRequest,deviceExtension,NULL);
+
+            return TRUE;
+
+    } // end switch  
+       
+}// end BusLogic_TargetDeviceInquiry
+
+
+BOOLEAN 
+BusLogic_WriteOutgoingMailbox(PHW_DEVICE_EXTENSION deviceExtension ,
+                                                         BusLogic_ActionCode_T ActionCode,
+                                                 BusLogic_CCB_T *CCB)
+//______________________________________________________________________________________________
+// Routine Description:
+//                     BusLogic_WriteOutgoingMailbox places CCB and Action Code into an Outgoing
+//                     Mailbox for execution by Host Adapter.  The Host Adapter's Lock should
+//                     already have been acquired by the caller.
+
+// Arguments:
+//              1. deviceExtension: device extension
+//              2. ActionCode : action code for the mailbox which can be
+//                                     BusLogic_OutgoingMailboxFree =          0x00,
+//                                     BusLogic_MailboxStartCommand =          0x01,
+//                                     BusLogic_MailboxAbortCommand =          0x02
+//                             3. CCB :The CCB that has to be written into the mailbox
+// Return Value:
+//              TRUE : write to the mailbox was successful
+//              FALSE : write failed
+//______________________________________________________________________________________________
+{
+  BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+  BusLogic_OutgoingMailbox_T *NextOutgoingMailbox;
+  ULONG length;
+
+  NextOutgoingMailbox = HostAdapter->NextOutgoingMailbox;
+
+  if (NextOutgoingMailbox->ActionCode == BusLogic_OutgoingMailboxFree)
+  {
+      CCB->Status = BusLogic_CCB_Active;
+      
+         // The CCB field must be written before the Action Code field since
+         // the Host Adapter is operating asynchronously and the locking code
+         // does not protect against simultaneous access by the Host Adapter.
+      
+         // Get CCB physical address.
+      NextOutgoingMailbox->CCB = ScsiPortConvertPhysicalAddressToUlong( ScsiPortGetPhysicalAddress(deviceExtension, 
+                                                                                                                                                                       NULL,
+                                                                                                                                                                       CCB,
+                                                                                                                                                                       &length));
+
+      NextOutgoingMailbox->ActionCode = (UCHAR)ActionCode;
+
+         BusLogic_StartMailboxCommand(HostAdapter);
+
+      if (++NextOutgoingMailbox > HostAdapter->LastOutgoingMailbox)
+         {
+               NextOutgoingMailbox = HostAdapter->FirstOutgoingMailbox;
+         }
+
+      HostAdapter->NextOutgoingMailbox = NextOutgoingMailbox;
+      if (ActionCode == BusLogic_MailboxStartCommand)
+         {
+           HostAdapter->ActiveCommandsPerTarget[CCB->TargetID]++;
+               // check this Namita
+               HostAdapter->ActiveCommandsPerLun[CCB->TargetID][CCB->LogicalUnit]++;
+           if (CCB->Opcode != BusLogic_BusDeviceReset)
+               {
+             HostAdapter->TargetStatistics[CCB->TargetID].CommandsAttempted++;
+               }
+         }
+      return TRUE;
+  }
+  return FALSE;
+}// end BusLogic_WriteOutgoingMailbox
+
+
+int 
+BusLogic_QueueCommand(IN PVOID HwDeviceExtension ,
+                                         IN PSCSI_REQUEST_BLOCK Srb,   
+                                         PBuslogic_CCB_T CCB)
+//_________________________________________________________________________
+// Routine Description:
+//                                             BusLogic_QueueCommand creates a CCB for Command 
+// Arguments:
+//              1. HwDeviceExtemsion: device extension
+//              2. Srb: Pointe to the SRB
+//                             3. CCB: POinter to the buffer containing the space for CCB
+// Return Value:
+//              Function returns 0 if successful
+//_________________________________________________________________________
+{
+  PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+  BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+  BusLogic_TargetFlags_T *TargetFlags = &HostAdapter->TargetFlags[Srb->TargetId];
+  BusLogic_TargetStatistics_T *TargetStatistics = HostAdapter->TargetStatistics;
+
+  ULONG length;
+
+//  UCHAR *Cdb = Srb->Cdb;
+//  PCDB RealCdb ;
+  UCHAR CDB_Length = Srb->CdbLength;
+  UCHAR TargetID = Srb->TargetId;
+  UCHAR LogicalUnit = Srb->Lun;
+//  void *BufferPointer = Srb->DataBuffer;
+  int BufferLength = Srb->DataTransferLength;
+
+  if (Srb->DataTransferLength > 0) 
+  {
+       CCB->DataLength = Srb->DataTransferLength;              
+
+  // Initialize the fields in the BusLogic Command Control Block (CCB).
+#if SG_SUPPORT
+       { 
+           ULONG length, xferLength, remainLength;
+           PVOID virtualAddress;
+           UCHAR i = 0;
+               
+               virtualAddress =  Srb->DataBuffer;
+           xferLength = Srb->DataTransferLength;
+           remainLength = xferLength;
+        /* Build scatter gather list  */
+        do
+               {
+            CCB->ScatterGatherList[i].SegmentDataPointer =  (ULONG)ScsiPortConvertPhysicalAddressToUlong(
+                                                                                                                                               ScsiPortGetPhysicalAddress(HwDeviceExtension,
+                                                                                                                                                                                                  Srb,
+                                                                                                                                                                                                  virtualAddress,
+                                                                                                                                                                                                  &length));
+            if ( length > remainLength )
+                length = remainLength;
+            CCB->ScatterGatherList[i].SegmentByteCount = length;
+
+            virtualAddress = (PUCHAR) virtualAddress + length;
+            if (length >= remainLength)
+                remainLength = 0;
+            else
+                remainLength -= length;
+            i++;
+        } while ( remainLength > 0);
+
+               // For data transfers that have less than one scatter gather element, convert
+        // CCB to one transfer without using SG element. This will clear up the data
+        // overrun/underrun problem with small transfers that reak havoc with scanners
+        // and CD-ROM's etc. This is the method employed in ASPI4DOS to avoid similar
+        // problems.
+        if (i > 1)
+               {
+            CCB->Opcode = BusLogic_InitiatorCCB_ScatterGather;
+            CCB->DataLength = i * sizeof(BusLogic_ScatterGatherSegment_T);   
+                       virtualAddress = (PVOID) & (CCB->ScatterGatherList);
+            CCB->DataPointer =  ScsiPortConvertPhysicalAddressToUlong(
+                                                                       ScsiPortGetPhysicalAddress(HwDeviceExtension,
+                                                                                                                          0,
+                                                                                                                          (PVOID)virtualAddress,
+                                                                                                                          &length));
+        } 
+               else /* Turn off SG */           
+               {
+            CCB->Opcode = BusLogic_InitiatorCCB;
+                       CCB->DataLength = CCB->ScatterGatherList[0].SegmentByteCount;
+            CCB->DataPointer = CCB->ScatterGatherList[0].SegmentDataPointer;
+            
+        }
+       }
+#else
+    CCB->Opcode = BusLogic_InitiatorCCB;
+    CCB->DataLength = BufferLength;
+    CCB->DataPointer =  ScsiPortConvertPhysicalAddressToUlong(ScsiPortGetPhysicalAddress(deviceExtension,
+                                                                                                                                                                          Srb,
+                                                                                                                                                                          BufferPointer,
+                                                                                                                                                                          &length));
+#endif  
+  }
+
+  switch (Srb->SrbFlags & SRB_FLAGS_UNSPECIFIED_DIRECTION) 
+  {
+    case SRB_FLAGS_NO_DATA_TRANSFER:  
+               CCB->DataDirection = BusLogic_NoDataTransfer;
+        break;
+
+    case SRB_FLAGS_DATA_IN:
+               CCB->DataDirection = BusLogic_DataInLengthChecked;
+               TargetStatistics[TargetID].ReadCommands++;
+               BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesRead, 
+                                                                         BufferLength);
+               BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].ReadCommandSizeBuckets,
+                                                                        BufferLength);  
+        break;
+
+    case SRB_FLAGS_DATA_OUT:
+               CCB->DataDirection = BusLogic_DataOutLengthChecked;
+               TargetStatistics[TargetID].WriteCommands++;
+               BusLogic_IncrementByteCounter(&TargetStatistics[TargetID].TotalBytesWritten, 
+                                                                         BufferLength);
+               BusLogic_IncrementSizeBucket(TargetStatistics[TargetID].WriteCommandSizeBuckets, 
+                                                                        BufferLength);         
+               
+        break;
+       
+       case SRB_FLAGS_UNSPECIFIED_DIRECTION:  /* let device decide direction */
+    default:
+               CCB->DataDirection = BusLogic_UncheckedDataTransfer;
+        break;
+  }
+
+
+  CCB->CDB_Length = CDB_Length;
+  CCB->SenseDataLength = Srb->SenseInfoBufferLength;
+  CCB->HostAdapterStatus = 0;
+  CCB->TargetDeviceStatus = 0;
+  CCB->TargetID = TargetID;
+  CCB->LogicalUnit = LogicalUnit;
+  CCB->TagEnable = FALSE;
+  CCB->LegacyTagEnable = FALSE;
+  
+  //  BusLogic recommends that after a Reset the first couple of commands that
+  //  are sent to a Target Device be sent in a non Tagged Queue fashion so that
+  //  the Host Adapter and Target Device can establish Synchronous and Wide
+  //  Transfer before Queue Tag messages can interfere with the Synchronous and
+  //  Wide Negotiation messages.  By waiting to enable Tagged Queuing until after
+  //  the first BusLogic_MaxTaggedQueueDepth commands have been queued, it is
+  //  assured that after a Reset any pending commands are requeued before Tagged
+  //  Queuing is enabled and that the Tagged Queuing message will not occur while
+  //  the partition table is being printed.  In addition, some devices do not
+  //  properly handle the transition from non-tagged to tagged commands, so it is
+  //  necessary to wait until there are no pending commands for a target device
+  //  before queuing tagged commands.
+
+  if (HostAdapter->CommandsSinceReset[TargetID]++ >= BusLogic_MaxTaggedQueueDepth &&
+      HostAdapter->ActiveCommandsPerTarget[TargetID] == 0                                            &&
+         !TargetFlags->TaggedQueuingActive                                                                                       &&
+      TargetFlags->TaggedQueuingSupported                                                                                &&
+      (HostAdapter->TaggedQueuingPermitted & (1 << TargetID)))
+  {
+         TargetFlags->TaggedQueuingActive = TRUE;
+      DebugPrint((0,"Tagged Queuing now active for Target %d\n", TargetID));
+  }
+  if (TargetFlags->TaggedQueuingActive)
+  {
+    BusLogic_QueueTag_T QueueTag = BusLogic_SimpleQueueTag;
+    
+       // When using Tagged Queuing with Simple Queue Tags, it appears that disk
+       // drive controllers do not guarantee that a queued command will not
+       // remain in a disconnected state indefinitely if commands that read or
+       // write nearer the head position continue to arrive without interruption.
+       // Therefore, for each Target Device this driver keeps track of the last
+       // time either the queue was empty or an Ordered Queue Tag was issued.  If
+       // more than 4 seconds (one fifth of the 20 second disk timeout) have
+       // elapsed since this last sequence point, this command will be issued
+       // with an Ordered Queue Tag rather than a Simple Queue Tag, which forces
+       // the Target Device to complete all previously queued commands before
+       // this command may be executed.
+    /*
+    if (HostAdapter->ActiveCommandsPerTarget[TargetID] == 0)
+               HostAdapter->LastSequencePoint[TargetID] = jiffies;
+    else if (jiffies - HostAdapter->LastSequencePoint[TargetID] > 4*HZ)
+       {
+         HostAdapter->LastSequencePoint[TargetID] = jiffies;
+         QueueTag = BusLogic_OrderedQueueTag;
+       }
+       */
+      if (HostAdapter->ExtendedLUNSupport)
+       {
+         CCB->TagEnable = TRUE;
+         CCB->QueueTag = (UCHAR)QueueTag;
+       }
+    else
+       {
+         CCB->LegacyTagEnable = TRUE;
+         CCB->LegacyQueueTag = (UCHAR)QueueTag;
+       }
+  }
+
+  ScsiPortMoveMemory(CCB->CDB, Srb->Cdb, CDB_Length);
+  
+  //Fix for the XP Port driver - shuts of auto sense at times. 22nd May 2002 
+  //{sirish, shobhit}@calsoftinc.com
+  if ((Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) || 
+        (Srb->SenseInfoBufferLength <= 0)) {
+         
+         //Disable auto request sense
+         CCB->SenseDataLength = BusLogic_DisableAutoReqSense;
+  } else {
+         //Enable auto request sense
+         CCB->SenseDataLength  = (unsigned char) Srb->SenseInfoBufferLength;
+
+         //Sense Buffer physical addr
+         CCB->SenseDataPointer = ScsiPortConvertPhysicalAddressToUlong(ScsiPortGetPhysicalAddress(HwDeviceExtension,
+                                                                                                                                                                              Srb,
+                                                                                                                                                                                  Srb->SenseInfoBuffer,
+                                                                                                                                                                                  &length));
+         if (Srb->SenseInfoBufferLength > length ) {
+                 CCB->SenseDataLength = (unsigned char) length;
+         }
+  }
+  
+  return 0;
+}// end BusLogic_QueueCommand
+
+
+BOOLEAN
+STDCALL
+BT958HwInterrupt(IN PVOID HwDeviceExtension)
+//_________________________________________________________________________
+// Routine Description:
+//                                             HwScsiInterrupt is called when the HBA generates an 
+//                                             interrupt. Miniport drivers of HBAs that do not 
+//                                             generate interrupts do not have this routine.
+//                                             HwScsiInterrupt is responsible for completing 
+//                                             interrupt-driven I/O operations. This routine must 
+//                                             clear the interrupt on the HBA before it returns TRUE.
+// Arguments:
+//              1. HwDeviceExtension: Points to the miniport driver's per-HBA storage area. 
+// Return Value:
+//              TRUE : Acknowledged the interrupts on the HBA
+//              FALSE: If the miniport finds that its HBA did not generate 
+//                     the interrupt, HwScsiInterrupt should return FALSE 
+//                                        as soon as possible.
+//_________________________________________________________________________
+{
+       PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+//    PNONCACHED_EXTENSION noncachedExtension =    deviceExtension->NoncachedExtension;
+       BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+//    PBuslogic_CCB_T ccb;
+//    PSCSI_REQUEST_BLOCK srb;
+    
+//    ULONG residualBytes;
+//    ULONG i;
+       
+       BusLogic_InterruptRegister_T InterruptRegister;
+
+         
+       // Read the Host Adapter Interrupt Register.
+    InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter);
+    if (InterruptRegister.Bits.InterruptValid)
+       {
+       
+         // Acknowledge the interrupt and reset the Host Adapter
+         // Interrupt Register.
+         BusLogic_InterruptReset(HostAdapter);
+         // Process valid External SCSI Bus Reset and Incoming Mailbox
+         // Loaded Interrupts.  Command Complete Interrupts are noted,
+         // and Outgoing Mailbox Available Interrupts are ignored, as
+         // they are never enabled.
+         if (InterruptRegister.Bits.ExternalBusReset)
+         {
+           HostAdapter->HostAdapterExternalReset = TRUE;
+         }
+         else if (InterruptRegister.Bits.IncomingMailboxLoaded)
+         {
+           BusLogic_ScanIncomingMailboxes(deviceExtension);
+         }
+         else if (InterruptRegister.Bits.CommandComplete)
+         {
+           HostAdapter->HostAdapterCommandCompleted = TRUE;
+         }
+       }
+       else
+               return FALSE;   
+       
+    // Process any completed CCBs.
+    if (HostAdapter->FirstCompletedCCB != NULL)
+               BusLogic_ProcessCompletedCCBs(deviceExtension);
+
+       // Reset the Host Adapter if requested.
+    if (HostAdapter->HostAdapterExternalReset ||
+        HostAdapter->HostAdapterInternalError)
+    {
+         // I have replaced the NULL with srb->pathid check if this is correct
+      BT958HwResetBus(HwDeviceExtension, SP_UNTAGGED);
+      HostAdapter->HostAdapterExternalReset = FALSE;
+      HostAdapter->HostAdapterInternalError = FALSE;     
+    } 
+    return TRUE;
+}// end BT958HwInterrupt
+
+void 
+BusLogic_ScanIncomingMailboxes(PHW_DEVICE_EXTENSION deviceExtension)
+//________________________________________________________________________________________
+// Routine Description:
+//                     BusLogic_ScanIncomingMailboxes scans the Incoming Mailboxes saving any
+//                  Incoming Mailbox entries for completion processing.
+// Arguments:
+//              1. deviceExtension : pointer to the device extension
+//_________________________________________________________________________________________
+{    
+  BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+    
+  
+  //  Scan through the Incoming Mailboxes in Strict Round Robin fashion, saving
+  //  any completed CCBs for further processing.  It is essential that for each
+  //  CCB and SCSI Command issued, command completion processing is performed
+  //  exactly once.  Therefore, only Incoming Mailboxes with completion code
+  //  Command Completed Without Error, Command Completed With Error, or Command
+  //  Aborted At Host Request are saved for completion processing.  When an
+  //  Incoming Mailbox has a completion code of Aborted Command Not Found, the
+  //  CCB had already completed or been aborted before the current Abort request
+  //  was processed, and so completion processing has already occurred and no
+  //  further action should be taken.
+  BusLogic_IncomingMailbox_T *NextIncomingMailbox =    HostAdapter->NextIncomingMailbox;
+  BusLogic_CompletionCode_T CompletionCode;
+
+  while ((CompletionCode = NextIncomingMailbox->CompletionCode) != BusLogic_IncomingMailboxFree)
+  {
+         // Convert Physical CCB to Virtual.
+      BusLogic_CCB_T *CCB = (BusLogic_CCB_T *) ScsiPortGetVirtualAddress(deviceExtension, 
+                                                                                                                                                ScsiPortConvertUlongToPhysicalAddress(NextIncomingMailbox->CCB));
+
+         DebugPrint((0, "Buslogic: Virtual CCB %lx\n", CCB));
+      if (CompletionCode != BusLogic_AbortedCommandNotFound)
+         {
+               if (CCB->Status == BusLogic_CCB_Active || CCB->Status == BusLogic_CCB_Reset)
+           {
+                       
+                       // Save the Completion Code for this CCB and queue the CCB
+                       // for completion processing.
+                       CCB->CompletionCode = CompletionCode;
+                       BusLogic_QueueCompletedCCB(deviceExtension,CCB);
+           }
+           else
+           {
+                       // If a CCB ever appears in an Incoming Mailbox and is not marked
+                       // as status Active or Reset, then there is most likely a bug in
+                       // the Host Adapter firmware.
+                       DebugPrint((0,"Illegal CCB #%ld status %d in "  "Incoming Mailbox\n",CCB->SerialNumber, CCB->Status));
+           }
+         }
+      NextIncomingMailbox->CompletionCode = BusLogic_IncomingMailboxFree;
+      if (++NextIncomingMailbox > HostAdapter->LastIncomingMailbox)
+               NextIncomingMailbox = HostAdapter->FirstIncomingMailbox;
+  }
+  HostAdapter->NextIncomingMailbox = NextIncomingMailbox;
+}// end BusLogic_ScanIncomingMailboxes
+
+
+void 
+BusLogic_QueueCompletedCCB(PHW_DEVICE_EXTENSION deviceExtension, 
+                                                  BusLogic_CCB_T *CCB)
+//_________________________________________________________________________________
+// Routine Description:
+//                                     BusLogic_QueueCompletedCCB queues CCB for completion processing.
+// Arguments:
+//              1. deviceExtension : pointer to device extension
+//              2. CCB: pointe t CCB that needs to be queued
+//_________________________________________________________________________________
+{
+  BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+
+  CCB->Status = BusLogic_CCB_Completed;
+  CCB->Next = NULL;
+  if (HostAdapter->FirstCompletedCCB == NULL)
+  {
+      HostAdapter->FirstCompletedCCB = CCB;
+      HostAdapter->LastCompletedCCB = CCB;
+  }
+  else
+  {
+      HostAdapter->LastCompletedCCB->Next = CCB;
+      HostAdapter->LastCompletedCCB = CCB;
+  }
+  HostAdapter->ActiveCommandsPerTarget[CCB->TargetID]--;
+  HostAdapter->ActiveCommandsPerLun[CCB->TargetID][CCB->LogicalUnit]--;
+
+}// end BusLogic_QueueCompletedCCB
+
+
+void 
+BusLogic_ProcessCompletedCCBs(PHW_DEVICE_EXTENSION deviceExtension)
+//_________________________________________________________________________________
+// Routine Description:
+//            BusLogic_ProcessCompletedCCBs iterates over the completed CCBs for Host
+//            Adapter setting the SCSI Command Result Codes, deallocating the CCBs, and
+//                       calling the SCSI Subsystem Completion Routines.  The Host Adapter's Lock
+//                       should already have been acquired by the caller.
+//
+// Arguments:
+//              1. deviceExtension : pointer to device extension
+//_________________________________________________________________________________
+{
+  BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+  PSCSI_REQUEST_BLOCK srb;
+  PCDB RealCdb;
+
+  if (HostAdapter->ProcessCompletedCCBsActive) 
+         return;
+  HostAdapter->ProcessCompletedCCBsActive = TRUE;
+  while (HostAdapter->FirstCompletedCCB != NULL)
+  {
+      BusLogic_CCB_T *CCB = HostAdapter->FirstCompletedCCB;
+     
+         // Get SRB from CCB.
+      srb = CCB->SrbAddress;
+
+          HostAdapter->FirstCompletedCCB = CCB->Next;
+       if (HostAdapter->FirstCompletedCCB == NULL)
+                       HostAdapter->LastCompletedCCB = NULL;
+      
+         // Process the Completed CCB.
+      if (CCB->Opcode == BusLogic_BusDeviceReset)
+         {
+                 int TargetID = CCB->TargetID, LunID;
+                 DebugPrint((0,"Bus Device Reset CCB #%ld to Target " "%d Completed\n", CCB->SerialNumber, TargetID)); 
+                 BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsCompleted);
+                 
+                 HostAdapter->TargetFlags[TargetID].TaggedQueuingActive = FALSE;
+                 HostAdapter->CommandsSinceReset[TargetID] = 0;
+                 //HostAdapter->LastResetCompleted[TargetID] = jiffies;
+                 HostAdapter->ActiveCommandsPerTarget[TargetID] = 0;                   
+                 for (LunID = 0; LunID < HostAdapter->MaxLogicalUnits; LunID++)
+                       HostAdapter->ActiveCommandsPerLun[TargetID][LunID] = 0;
+
+                 // Complete all outstanding requests with SRB_STATUS_BUS_RESET.
+                 ScsiPortCompleteRequest(deviceExtension,
+                                                                 (UCHAR)srb->PathId,
+                                                                 srb->TargetId,
+                                                                 0xFF,
+                                                                 (ULONG)SRB_STATUS_BUS_RESET);
+  
+                       
+                 HostAdapter->BusDeviceResetPendingCCB[TargetID] = NULL;
+         }
+      else
+         {
+                 // Translate the Completion Code, Host Adapter Status, and Target
+                 // Device Status into a SCSI Subsystem Result Code.
+                 switch (CCB->CompletionCode)
+                 {
+                       case BusLogic_IncomingMailboxFree:
+                       case BusLogic_InvalidCCB:
+                       {
+                               DebugPrint((0," CCB #%ld to Target %d Impossible State\n", CCB->SerialNumber, CCB->TargetID));
+                           break;
+                       }
+
+                       //Processing for CCB that was to be aborted 
+                       case BusLogic_AbortedCommandNotFound:
+                       {
+                               srb = CCB->AbortSrb;
+                               srb->SrbStatus = SRB_STATUS_ABORT_FAILED;                               
+                               break;
+                       }
+
+                       case BusLogic_CommandCompletedWithoutError:
+                       {
+                          HostAdapter->TargetStatistics[CCB->TargetID].CommandsCompleted++;
+                          HostAdapter->TargetFlags[CCB->TargetID].CommandSuccessfulFlag = TRUE;
+
+                          srb->SrbStatus = SRB_STATUS_SUCCESS;
+                          break;
+                       }
+
+                       case BusLogic_CommandAbortedAtHostRequest:
+                       {
+                         DebugPrint((0, "CCB #%ld to Target %d Aborted\n", CCB->SerialNumber, CCB->TargetID));
+                         //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[CCB->TargetID].CommandAbortsCompleted);
+
+                         srb->SrbStatus = SRB_STATUS_ABORTED;
+
+                         // Call notification routine for the aborted SRB.
+              ScsiPortNotification(RequestComplete,
+                                                                  deviceExtension,
+                                                                  srb);
+
+                         // Get the abort SRB from CCB.
+              srb = CCB->AbortSrb;
+
+               // Set status for completing abort request.
+              srb->SrbStatus = SRB_STATUS_SUCCESS;
+                         break;        
+                       }
+
+                       case BusLogic_CommandCompletedWithError:
+                       {
+//                       PCDB RealCdb = (PCDB)CCB->CDB;
+                         DebugPrint((0,"%x Command completed with error Host - %x Target %x \n",((PCDB)CCB->CDB)->CDB6GENERIC.OperationCode,
+                                                                                                                                                                 CCB->HostAdapterStatus, 
+                                                                                                                                                                 CCB->TargetDeviceStatus)); 
+
+                         srb->SrbStatus = BusLogic_ComputeResultCode(HostAdapter,
+                                                                                                                  CCB->HostAdapterStatus,
+                                                                                                                  CCB->TargetDeviceStatus,
+                                                                                                                  CCB->SenseDataLength);
+                         if (CCB->HostAdapterStatus != BusLogic_SCSISelectionTimeout)
+                         {
+                               HostAdapter->TargetStatistics[CCB->TargetID].CommandsCompleted++;
+                         }
+                         break;
+                       }
+
+                   default:
+                       {
+                       // Log the error.
+               ScsiPortLogError(deviceExtension,
+                                                               NULL,
+                                                               0,
+                                                               srb->TargetId,
+                                                               0,
+                                                               SP_INTERNAL_ADAPTER_ERROR,
+                                                               143);
+
+                DebugPrint((0, "BusLogic Interrupt: Unrecognized mailbox status\n"));
+                       }
+
+                 }// end switch
+
+                 
+                 // When an INQUIRY command completes normally, save the CmdQue (Tagged Queuing Supported)
+                 // and WBus16 (16 Bit Wide Data Transfers Supported) bits.
+                 RealCdb = (PCDB) CCB->CDB;
+                 if (RealCdb->CDB6INQUIRY.OperationCode == SCSIOP_INQUIRY &&
+                         CCB->HostAdapterStatus == BusLogic_CommandCompletedNormally)
+                 {
+                         BusLogic_TargetFlags_T *TargetFlags =&HostAdapter->TargetFlags[CCB->TargetID];
+                         SCSI_Inquiry_T *InquiryResult =(SCSI_Inquiry_T *) srb->DataBuffer;
+                         TargetFlags->TargetExists = TRUE;
+                         TargetFlags->TaggedQueuingSupported = InquiryResult->CmdQue;
+                         TargetFlags->WideTransfersSupported = InquiryResult->WBus16;
+                 }
+       
+                 DebugPrint((0, "BusLogic: SCSI Status %x\n", srb->ScsiStatus));
+                 DebugPrint((0, "BusLogic: Adapter Status %x\n", CCB->HostAdapterStatus));
+
+                 // Update target status in SRB.
+                 srb->ScsiStatus = (UCHAR)CCB->TargetDeviceStatus;
+
+                 // Signal request completion.
+                 ScsiPortNotification(RequestComplete, (PVOID)deviceExtension, srb);
+          }
+    }
+    HostAdapter->ProcessCompletedCCBsActive = FALSE;
+}// end BusLogic_ProcessCompletedCCBs
+
+
+UCHAR 
+BusLogic_ComputeResultCode(BusLogic_HostAdapter_T *HostAdapter,
+                                                  BusLogic_HostAdapterStatus_T HostAdapterStatus,
+                                                  BusLogic_TargetDeviceStatus_T TargetDeviceStatus,
+                                                  UCHAR SenseDataLength)
+//_________________________________________________________________________________________
+// Routine Description:
+//                               BusLogic_ComputeResultCode computes a SCSI Subsystem Result Code from
+//                               the Host Adapter Status and Target Device Status.
+// Arguments:
+//              1.HostAdapter:  Pointer to the host adapter structure
+//              2.HostAdapterStatus: Host adapter status returned in the completed CCB
+//                             3.TargetDeviceStatus:
+// Return Value:
+//                             This function returns the error code that should be returned to port driver
+//_________________________________________________________________________________________
+{
+  UCHAR HostStatus = 0;
+
+  // Namita 2Oct CDROM issue
+  if (TargetDeviceStatus != BusLogic_OperationGood && (HostAdapterStatus == BusLogic_CommandCompletedNormally || 
+                                                                                                          HostAdapterStatus == BusLogic_LinkedCommandCompleted   ||
+                                                                                                          HostAdapterStatus == BusLogic_LinkedCommandCompletedWithFlag))
+  {
+       switch(TargetDeviceStatus)
+       {
+               case BusLogic_CheckCondition:
+               {
+                   HostStatus = SRB_STATUS_ERROR;
+                       if(SenseDataLength != BusLogic_DisableAutoReqSense)
+                               HostStatus |= SRB_STATUS_AUTOSENSE_VALID;                                         
+                       break;
+               }
+               case BusLogic_DeviceBusy:
+               {
+                       HostStatus = SRB_STATUS_BUSY;
+               }
+               break;
+               case BusLogic_OperationGood:
+
+               HostStatus = SRB_STATUS_SUCCESS;
+               break;
+       }
+  }
+
+  else
+  {
+
+         switch (HostAdapterStatus)
+         {
+                       case BusLogic_CommandCompletedNormally:
+                       case BusLogic_LinkedCommandCompleted:
+                       case BusLogic_LinkedCommandCompletedWithFlag:
+                       {
+                         HostStatus = SRB_STATUS_SUCCESS;
+                         break;
+                       }
+                       case BusLogic_SCSISelectionTimeout:
+                       {
+                         HostStatus = SRB_STATUS_SELECTION_TIMEOUT;
+                         break;
+                       }
+                       case BusLogic_InvalidOutgoingMailboxActionCode:
+                       case BusLogic_InvalidCommandOperationCode:
+                       case BusLogic_InvalidCommandParameter:
+                         DebugPrint((0,"BusLogic_Warning!! BusLogic Driver Protocol Error 0x%02X\n",HostAdapterStatus));
+                       case BusLogic_DataUnderRun:
+                       
+                       case BusLogic_DataOverRun:
+                               // SRB_STATUS_DATA_OVERRUN
+
+                       case BusLogic_LinkedCCBhasInvalidLUN:
+                       
+                       case BusLogic_TaggedQueuingMessageRejected:
+                               // SRB_STATUS_MESSAGE_REJECTED
+                       case BusLogic_TargetDeviceReconnectedImproperly:
+                       case BusLogic_AbortQueueGenerated:
+                       case BusLogic_HostAdapterSoftwareError:
+                       
+                       case BusLogic_HostAdapterHardwareTimeoutError:
+                               // SRB_STATUS_TIMEOUT
+                       {
+                         HostStatus = SRB_STATUS_ERROR;
+                         break;
+                       }
+                       case BusLogic_TargetFailedResponseToATN:
+                       case BusLogic_HostAdapterAssertedRST:
+                       case BusLogic_OtherDeviceAssertedRST:
+                       case BusLogic_HostAdapterAssertedBusDeviceReset:
+                       {
+                         HostStatus = SRB_STATUS_BUS_RESET;
+                         break;
+                       }
+                       case BusLogic_SCSIParityErrorDetected:
+                       {
+                               HostStatus = SRB_STATUS_PARITY_ERROR;
+                               break;
+                       }
+                       case BusLogic_UnexpectedBusFree:
+                       {
+                               HostStatus = SRB_STATUS_UNEXPECTED_BUS_FREE;
+                               break;
+                       }
+                       case BusLogic_InvalidBusPhaseRequested:
+                       {
+                               HostStatus = SRB_STATUS_PHASE_SEQUENCE_FAILURE;
+                               break;
+                       }
+                       case BusLogic_AutoRequestSenseFailed:
+                       {
+                               HostStatus = SRB_STATUS_REQUEST_SENSE_FAILED;
+                               break;
+                       }
+                       case BusLogic_UnsupportedMessageReceived:
+                       {
+                               HostStatus = SRB_STATUS_INVALID_REQUEST;
+                               break;
+                       }
+                       case BusLogic_HostAdapterHardwareFailed:
+                       {
+                               HostStatus = SRB_STATUS_NO_HBA;
+                               break;
+                       }
+                       default:
+                       {
+                         DebugPrint((0,"BusLogic_Warning: Unknown Host Adapter Status 0x%02X\n",HostAdapterStatus));
+                         HostStatus = SRB_STATUS_ERROR;
+                         break;
+                       }
+               }
+  }
+  return HostStatus;
+}// end BusLogic_ComputeResultCode
+
+
+BOOLEAN 
+STDCALL
+BT958HwResetBus(IN PVOID HwDeviceExtension,
+                               IN ULONG PathId)
+//_____________________________________________________________________________________
+// Routine Description:
+//                                      BT958HwResetBus resets Host Adapter if possible, marking all
+//                                      currently executing SCSI Commands as having been Reset.
+// Arguments:
+//              1. HwDeviceExtension: Points to the miniport driver's per-HBA storage area. 
+//           2. PathId: Identifies the SCSI bus to be reset. 
+// Return Value:
+//              TRUE : If the bus is successfully reset, HwScsiResetBus returns TRUE.
+//              FALSE : reset did not complete successfully
+//_____________________________________________________________________________________
+{
+  PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+  BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+//  BusLogic_CCB_T *CCB;
+//  int TargetID;
+  BOOLEAN Result;
+  BOOLEAN HardReset;
+
+  DebugPrint((0,"BuslogicResetBus: Reset aha154X and SCSI bus\n"));
+
+  // Complete all outstanding requests with SRB_STATUS_BUS_RESET.
+  ScsiPortCompleteRequest(deviceExtension,
+                                                               (UCHAR)PathId,
+                                                               0xFF,
+                                                               0xFF,
+                                                               (ULONG) SRB_STATUS_BUS_RESET);
+  
+  if (HostAdapter->HostAdapterExternalReset)
+  {
+      //BusLogic_IncrementErrorCounter(&HostAdapter->ExternalHostAdapterResets);
+      HardReset = FALSE;
+  }
+  else if (HostAdapter->HostAdapterInternalError)
+  {
+      //BusLogic_IncrementErrorCounter(&HostAdapter->HostAdapterInternalErrors);
+      HardReset = TRUE;
+  }
+  else
+  {
+      //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[srb->TargetId].HostAdapterResetsRequested);
+      HardReset = TRUE;
+  }
+
+  // Think of a way of doing this - Namita
+  /*
+  if(srb == NULL)
+  {
+       if (HostAdapter->HostAdapterInternalError)
+               DebugPrint((0,"BusLogic Warning: Resetting %s due to Host Adapter Internal Error\n",HostAdapter->FullModelName));
+       else 
+               DebugPrint((0,"BUsLogic Warning: Resetting %s due to External SCSI Bus Reset\n",HostAdapter->FullModelName));
+  }
+  else
+  {
+      DebugPrint((0,"BusLogic Warning: Resetting %s due to Target %d\n", HostAdapter->FullModelName, srb->TargetId));
+      //BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[srb->TargetId].HostAdapterResetsAttempted);
+  }
+  */
+  // Attempt to Reset and Reinitialize the Host Adapter.
+  // Change the initialize routine to make allocation some place else
+  if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, HardReset) && BusLogic_InitializeHostAdapter(deviceExtension, NULL)))
+  {
+      DebugPrint((0,"Buslogic Error, Resetting %s Failed\n", HostAdapter->FullModelName));
+      Result = FALSE;
+      goto Done;
+  }
+
+  // Check if we have to do this, document says that the scsi port driver takes care of the reset delays - Namita
+  // Wait a few seconds between the Host Adapter Hard Reset which initiates
+  // a SCSI Bus Reset and issuing any SCSI Commands.  Some SCSI devices get
+  // confused if they receive SCSI Commands too soon after a SCSI Bus Reset.
+  // Note that a timer interrupt may occur here, but all active CCBs have
+  // already been marked Reset and so a reentrant call will return Pending.
+  if (HardReset)
+       ScsiPortStallExecution(HostAdapter->BusSettleTime);
+  Result = TRUE;
+    
+Done:
+  return Result;
+}// end BT958HwResetBus
+
+BOOLEAN
+BusLogic_SendBusDeviceReset(IN PVOID HwDeviceExtension,
+                                                       PSCSI_REQUEST_BLOCK Srb)
+//_____________________________________________________________________________________
+// Routine Description:
+//                     BusLogic_SendBusDeviceReset causes a BUS DEVICE reset command to
+//                                        be send to particular target.
+// Arguments:
+//              1. HostAdpater: Points to Host adapter structure
+//           2. Srb: pointer to the SCSI request block
+// Return Value:
+//              TRUE : If the bus is successfully reset, HwScsiResetBus returns TRUE.
+//              FALSE : reset did not complete successfully
+//_____________________________________________________________________________________
+{
+
+  PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+  BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+  
+  UCHAR TargetID = Srb->TargetId;
+  PBuslogic_CCB_T CCB = Srb->SrbExtension;
+  BOOLEAN Result = FALSE;
+  BusLogic_IncrementErrorCounter(&HostAdapter->TargetStatistics[TargetID].BusDeviceResetsRequested);
+       
+  //  If this is a Synchronous Reset and a Bus Device Reset is already pending
+  //  for this Target Device, do not send a second one.  Add this Command to
+  //  the list of Commands for which completion processing must be performed
+  //  when the Bus Device Reset CCB completes.
+  
+  if ((CCB = HostAdapter->BusDeviceResetPendingCCB[TargetID]) != NULL)
+  {
+       DebugPrint((0,"BusLogic_Warning: Unable to Reset Command to Target %d - Reset Pending\n", TargetID));
+       Result = TRUE;
+       goto Done;
+  }
+  
+  DebugPrint((0,"BusLogic_Warning: Sending Bus Device Reset CCB #%ld to Target %d\n",CCB->SerialNumber, TargetID));
+  CCB->Opcode = BusLogic_BusDeviceReset;
+  CCB->TargetID = TargetID;
+  
+
+  //   Attempt to write an Outgoing Mailbox with the Bus Device Reset CCB.
+  //   If sending a Bus Device Reset is impossible, attempt a full Host
+  //   Adapter Hard Reset and SCSI Bus Reset.
+  if (!(BusLogic_WriteOutgoingMailbox(deviceExtension, BusLogic_MailboxStartCommand, CCB)))
+  {
+         DebugPrint((0,"BusLogic_Warning: Unable to write Outgoing Mailbox for " "Bus Device Reset\n"));
+         goto Done;
+  }
+  
+  //  If there is a currently executing CCB in the Host Adapter for this Command
+  //  (i.e. this is an Asynchronous Reset), then an Incoming Mailbox entry may be
+  //  made with a completion code of BusLogic_HostAdapterAssertedBusDeviceReset.
+  //  If there is no active CCB for this Command (i.e. this is a Synchronous
+  //  Reset), then the Bus Device Reset CCB's Command field will have been set
+  //  to the Command so that the interrupt for the completion of the Bus Device
+  //  Reset can call the Completion Routine for the Command.  On successful
+  //  execution of a Bus Device Reset, older firmware versions did return the
+  //  pending CCBs with the appropriate completion code, but more recent firmware
+  //  versions only return the Bus Device Reset CCB itself.  This driver handles
+  //  both cases by marking all the currently executing CCBs to this Target
+  //  Device as Reset.  When the Bus Device Reset CCB is processed by the
+  //  interrupt handler, any remaining CCBs marked as Reset will have completion
+  //  processing performed.
+  
+  BusLogic_IncrementErrorCounter( &HostAdapter->TargetStatistics[TargetID].BusDeviceResetsAttempted);
+  HostAdapter->BusDeviceResetPendingCCB[TargetID] = CCB;
+  //HostAdapter->LastResetAttempted[TargetID] = jiffies;
+  
+  // FlashPoint Host Adapters may have already completed the Bus Device
+  // Reset and BusLogic_QueueCompletedCCB been called, or it may still be
+  // pending.
+  
+  Result = TRUE;  
+  //  If a Bus Device Reset was not possible for some reason, force a full
+  //  Host Adapter Hard Reset and SCSI Bus Reset.
+  
+Done:
+  return Result;
+}
+
+BOOLEAN 
+STDCALL
+BT958HwInitialize(IN PVOID HwDeviceExtension)
+//_______________________________________________________________________________
+// Routine Description:
+//                         This routine initializes the adapter by enabling its interrupts
+// Arguments:
+//              1. device extension
+// Return Value:
+//              TRUE : initialzation successful
+//              FALSE : initialization failed
+//_______________________________________________________________________________
+{
+       PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+    BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+       CHAR Parameter = 1;
+
+       // enable interrupts
+       if (BusLogic_Command(HostAdapter,
+                                                  BusLogic_DisableHostAdapterInterrupt,
+                                                  &Parameter,
+                                                  sizeof(Parameter), 
+                                                  NULL, 
+                                                  0) 
+               < 0)
+       {
+       return FALSE;
+       }  
+       return TRUE;
+}// end BT958HwInitialize
+
+SCSI_ADAPTER_CONTROL_STATUS 
+STDCALL
+BT958HwAdapterControl(IN PVOID HwDeviceExtension,
+                                         IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
+                                         IN PVOID Parameters)
+//__________________________________________________________________________________________
+// Routine Description:
+//               A miniport driver's HwScsiAdapterControl routine is called to perform 
+//               synchronous operations to control the state or behavior of an HBA, such as 
+//               stopping or restarting the HBA for power management.
+// Arguments:
+//              1. HwDeviceExtension: device extension
+//              2. ControlType: Specifies one of the following adapter-control operations. 
+//                 ScsiQuerySupportedControlTypes : Reports the adapter-control operations
+//                                                                                                     implemented by the miniport. 
+//                                ScsiStopAdapter:  Shuts down the HBA. 
+//                 ScsiRestartAdapter: Reinitializes an HBA. 
+//                 ScsiSetBootConfig: Not supported
+//                 ScsiSetRunningConfig: Not supported
+//                             3. Parameters:
+// Return Value:
+//              TRUE : 
+//              FALSE : 
+//_________________________________________________________________________
+{
+    PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+    BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+//     UCHAR *ParameterPointer;
+//     BusLogic_StatusRegister_T StatusRegister;
+//     BusLogic_InterruptRegister_T InterruptRegister;
+//     int Result,ParameterLength;
+//     long TimeoutCounter;
+
+       PSCSI_SUPPORTED_CONTROL_TYPE_LIST ControlTypeList;
+    ULONG AdjustedMaxControlType;
+
+    ULONG Index;
+//    UCHAR Retries;
+
+    // Default Status
+//    SCSI_ADAPTER_CONTROL_STATUS Status = ScsiAdapterControlSuccess;
+
+    //
+    // Structure defining which functions this miniport supports
+    //
+    BOOLEAN SupportedConrolTypes[ScsiAdapterControlMax] = 
+       {
+        TRUE,   // ScsiQuerySupportedControlTypes
+        TRUE,   // ScsiStopAdapter
+        TRUE,   // ScsiRestartAdapter
+        FALSE,  // ScsiSetBootConfig
+        FALSE   // ScsiSetRunningConfig
+    };
+
+       DebugPrint((0,"\n BusLogic -  Inside HwAdapterControl funtion \n"));
+    switch(ControlType) 
+       {
+           case ScsiQuerySupportedControlTypes:
+               //      Reports the adapter-control operations implemented by the miniport. The port 
+               //      driver calls HwScsiAdapterControl with this control type after the HBA has been 
+               //      initialized but before the first I/O. The miniport fills in the 
+               //  SCSI_SUPPORTED_CONTROL_TYPE_LIST structure at Parameters with the operations it
+        //     supports. After HwScsiAdapterControl returns from this call, the port driver 
+               //  calls the miniport's HwScsiAdapterControl only for supported operations. 
+               {
+
+            // This entry point provides the method by which SCSIPort determines the
+            // supported ControlTypes. Parameters is a pointer to a
+            // SCSI_SUPPORTED_CONTROL_TYPE_LIST structure. Fill in this structure
+            // honoring the size limits.
+            ControlTypeList = Parameters;
+            AdjustedMaxControlType =  (ControlTypeList->MaxControlType < ScsiAdapterControlMax) ?  ControlTypeList->MaxControlType :ScsiAdapterControlMax;
+            for (Index = 0; Index < AdjustedMaxControlType; Index++) 
+                       {
+                ControlTypeList->SupportedTypeList[Index] = SupportedConrolTypes[Index];
+            }
+            break;
+               }
+
+        case ScsiStopAdapter: 
+               // Shuts down the HBA. The port driver calls HwScsiAdapterControl with this control
+               // type when the HBA has been removed from the system, stopped for resource reconfiguration,
+               // shut down for power management, or otherwise reconfigured or disabled. The port driver 
+               // ensures that there are no uncompleted requests and issues an SRB_FUNCTION_FLUSH request 
+               // to the miniport before calling this routine. The miniport disables interrupts on its HBA, 
+               // halts all processing, (including background processing not subject to interrupts or processing
+               // of which the port driver is unaware, such as reconstructing fault-tolerant volumes), flushes 
+               // any remaining cached data to persistent storage, and puts the HBA into a state from which it 
+               // can be reinitialized or restarted. 
+               // The miniport should not free its resources when stopping its HBA. If the HBA was removed or 
+               // stopped for PnP resource reconfiguration, the port driver releases resources on behalf of the 
+               // miniport driver. If the HBA is shut down for power management, the miniport's resources are 
+               // preserved so the HBA can be restarted. 
+               {
+                       CHAR Parameter = 0;
+                       DebugPrint((0,"\n BusLogic -  stopping the device \n"));
+                       if (BusLogic_Command(HostAdapter,
+                                                                  BusLogic_DisableHostAdapterInterrupt,
+                                                                  &Parameter,
+                                                                  sizeof(Parameter), 
+                                                                  NULL, 
+                                                                  0) 
+                               < 0)
+                       {           
+                                 return ScsiAdapterControlUnsuccessful;
+                       }
+                       break;
+        }
+
+               case ScsiRestartAdapter:
+               // Reinitializes an HBA. The port driver calls HwScsiAdapterControl with this control type to power 
+               // up an HBA that was shut down for power management. All resources previously assigned to the miniport 
+               // are still available, and its device extension and logical unit extensions, if any, are intact. 
+               // The miniport performs the same operations as in its HwScsiInitialize routine, such as setting up 
+               // the HBA's registers and its initial state, if any. 
+               // The miniport must not call routines that can only be called from HwScsiFindAdapter or from 
+               // HwScsiAdapterControl when the control type is ScsiSetRunningConfig, such as ScsiPortGetBusData and 
+               // ScsiPortSetBusDataByOffset. If the miniport must call such routines to restart its HBA, it must also 
+               // implement ScsiSetRunningConfig. 
+               // 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. 
+               {
+                       if (!(BusLogic_HardwareResetHostAdapter(HostAdapter, TRUE) && 
+                                 BusLogic_InitializeHostAdapter(deviceExtension, NULL)) &&
+                                 BT958HwInitialize(HwDeviceExtension)
+                          )
+                       {
+                               DebugPrint((0,"Buslogic Error, Resetting %s Failed\n", HostAdapter->FullModelName));
+                               return ScsiAdapterControlUnsuccessful;
+                       }
+
+                   ScsiPortStallExecution(HostAdapter->BusSettleTime);                 
+                       break;
+               }
+        default: 
+               {
+            return ScsiAdapterControlUnsuccessful;
+        }
+    }
+    return ScsiAdapterControlSuccess;
+}// end BT958HwAdapterControl
+
+// END OF FILE BusLogic958.c
diff --git a/reactos/drivers/storage/buslogic/BusLogic958.h b/reactos/drivers/storage/buslogic/BusLogic958.h
new file mode 100644 (file)
index 0000000..5e2a92b
--- /dev/null
@@ -0,0 +1,1179 @@
+/*
+ * vmscsi-- Miniport driver for the Buslogic BT 958 SCSI Controller 
+ *          under Windows 2000/XP/Server 2003
+ *
+ *          Based in parts on the buslogic driver for the same device
+ *          available with the GNU Linux Operating System.
+ *          
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ */
+
+//_________________________________________________________________________________________
+//
+// File description :The header file the driver for BusLogic-958 SCSI Host adapter card.
+// The technical refernece for this driver is at :
+//
+// Author: Namita Lal, Sirish Raghuram ( Calsoft Pvt Ltd)
+// Date: 10th June 2002
+// Status: Released
+// Revision History: Changed queue depth to 191 - June 2002
+//
+//_________________________________________________________________________________________
+
+// Prototype for functions
+
+#ifndef _BT958_H_
+#define _BT958_H_
+
+#include <ddk/ntddk.h>
+#include <ddk/srb.h>
+#include <ddk/scsi.h>
+#include <ddk/ntddscsi.h>
+#include <ddk/scsiwmi.h>
+//#include <ntos/kefuncs.h>
+
+
+//#include "miniport.h"
+//#include "scsi.h"    
+//#include "scsiwmi.h"
+
+//_________________________________________________________________________________________
+// #defines
+//_________________________________________________________________________________________
+
+// Max transfer size
+#define MAX_TRANSFER_SIZE  64 * 1024
+// flag to turn on Scatter gather support
+#define SG_SUPPORT 1
+// flag to turn on tagged command queuing
+#define TAG_QUEUING 1
+
+#define BUSLOGIC_MAXIMUM_TAGS 128
+
+//  Define the maximum, maximum automatic, minimum automatic, and default Queue
+//  Depth to allow for Target Devices depending on whether or not they support
+//  Tagged Queuing and whether or not ISA Bounce Buffers are required.
+#define BusLogic_MaxTaggedQueueDepth            128
+
+//  Define the default amount of time in seconds to wait between a Host Adapter
+//  Hard Reset which initiates a SCSI Bus Reset and issuing any SCSI commands.
+//  Some SCSI devices get confused if they receive SCSI commands too soon after
+//  a SCSI Bus Reset.
+#define BusLogic_DefaultBusSettleTime          2
+
+//  Define the maximum number of Target Devices supported by this driver.
+#define BusLogic_MaxTargetDevices              16
+
+//  Define the maximum number of Logical unit supported/Target Devices supported by this driver.
+#define BusLogic_MaxLogicalUnits         32
+
+//  Define the maximum number of Mailboxes that should be used for MultiMaster
+//  Host Adapters.  This number is chosen to be larger than the maximum Host
+//  Adapter Queue Depth and small enough so that the Host Adapter structure
+//  does not cross an allocation block size boundary.
+#define BusLogic_MaxMailboxes                  211
+
+//  Define the Fetch Host Adapter Local RAM request type.
+#define BusLogic_BIOS_BaseOffset               0
+#define BusLogic_AutoSCSI_BaseOffset           64
+
+//  Define the SCSI Command Descriptor Block (CDB).
+#define BusLogic_CDB_MaxLength                 12
+
+//  Define the maximum number of Scatter/Gather Segments used by this driver.
+//  For optimal performance, it is important that this limit be at least as
+//  large as the largest single request generated by the I/O Subsystem.
+#define BusLogic_ScatterGatherLimit            128
+#define MAX_SG_LIMIT BusLogic_ScatterGatherLimit
+
+#define  BusLogic_AggressiveRoundRobinMode 0
+#define  BusLogic_StrictRoundRobinMode            1
+
+//  Define the Codes for byte 3 (Request sense allocation length) of the CCB structure.
+#define  BusLogic_Allocate14Bytes              0x00
+#define  BusLogic_DisableAutoReqSense  0x01
+//_________________________________________________________________________________________
+
+
+//_________________________________________________________________________________________
+// typedef 
+//_________________________________________________________________________________________
+typedef enum
+{
+  BusLogic_TestCommandCompleteInterrupt = 0x00,
+  BusLogic_InitializeMailbox =                   0x01,
+  BusLogic_ExecuteMailboxCommand =               0x02,
+  BusLogic_ExecuteBIOSCommand =                          0x03,
+  BusLogic_InquireBoardID =                          0x04,
+  BusLogic_EnableOutgoingMailboxAvailableInt = 0x05,
+  BusLogic_SetSCSISelectionTimeout =     0x06,
+  BusLogic_SetPreemptTimeOnBus =                 0x07,
+  BusLogic_SetTimeOffBus =                           0x08,
+  BusLogic_SetBusTransferRate =                          0x09,
+  BusLogic_InquireInstalledDevicesID0to7 =0x0A,
+  BusLogic_InquireConfiguration =                0x0B,
+  BusLogic_EnableTargetMode =                    0x0C,
+  BusLogic_InquireSetupInformation =     0x0D,
+  BusLogic_WriteAdapterLocalRAM =                0x1A,
+  BusLogic_ReadAdapterLocalRAM =                 0x1B,
+  BusLogic_WriteBusMasterChipFIFO =              0x1C,
+  BusLogic_ReadBusMasterChipFIFO =               0x1D,
+  BusLogic_EchoCommandData =                     0x1F,
+  BusLogic_HostAdapterDiagnostic =               0x20,
+  BusLogic_SetAdapterOptions =                   0x21,
+  BusLogic_InquireInstalledDevicesID8to15 =    0x23,
+  BusLogic_InquireTargetDevices =                0x24,
+  BusLogic_DisableHostAdapterInterrupt =  0x25,
+  BusLogic_InitializeExtendedMailbox =   0x81,
+  BusLogic_ExecuteSCSICommand =                          0x83,
+  BusLogic_InquireFirmwareVersion3rdDigit =    0x84,
+  BusLogic_InquireFirmwareVersionLetter = 0x85,
+  BusLogic_InquirePCIHostAdapterInformation = 0x86,
+  BusLogic_InquireHostAdapterModelNumber =0x8B,
+  BusLogic_InquireSynchronousPeriod =    0x8C,
+  BusLogic_InquireExtendedSetupInformation = 0x8D,
+  BusLogic_EnableStrictRoundRobinMode =          0x8F,
+  BusLogic_StoreHostAdapterLocalRAM =    0x90,
+  BusLogic_FetchHostAdapterLocalRAM =    0x91,
+  BusLogic_StoreLocalDataInEEPROM =              0x92,
+  BusLogic_UploadAutoSCSICode =                          0x94,
+  BusLogic_ModifyIOAddress =                     0x95,
+  BusLogic_SetCCBFormat =                            0x96,
+  BusLogic_WriteInquiryBuffer =                          0x9A,
+  BusLogic_ReadInquiryBuffer =                   0x9B,
+  BusLogic_FlashROMUploadDownload =              0xA7,
+  BusLogic_ReadSCAMData =                            0xA8,
+  BusLogic_WriteSCAMData =                           0xA9
+}BusLogic_OperationCode_T;
+
+
+//  Define the Requested Reply Length type used by the Inquire Setup Information,
+//  Inquire Host Adapter Model Number, Inquire Synchronous Period, and Inquire
+//  Extended Setup Information commands.
+typedef UCHAR BusLogic_RequestedReplyLength_T;
+
+//  Define a 32 bit Bus Address data type.
+typedef unsigned int BusLogic_BusAddress_T;
+
+//  Define the Inquire Host Adapter Model Number reply type.
+typedef UCHAR BusLogic_HostAdapterModelNumber_T[5];
+
+//  Define the Inquire Firmware Version 3rd Digit reply type.
+typedef UCHAR BusLogic_FirmwareVersion3rdDigit_T;
+
+//  Define the Inquire Firmware Version Letter reply type.
+typedef UCHAR BusLogic_FirmwareVersionLetter_T;
+
+//  Define a 32 bit Byte Count data type.
+typedef unsigned int BusLogic_ByteCount_T;
+
+typedef struct BusLogic_FetchHostAdapterLocalRAMRequest
+{
+  UCHAR ByteOffset;                            // Byte 0 
+  UCHAR ByteCount;                             // Byte 1 
+}
+BusLogic_FetchHostAdapterLocalRAMRequest_T;
+
+//  Define the Inquire PCI Host Adapter Information reply type.  The ISA
+//  Compatible I/O Port values are defined here and are also used with
+//  the Modify I/O Address command.
+typedef enum BusLogic_ISACompatibleIOPort
+{
+  BusLogic_IO_330 =                            0,
+  BusLogic_IO_334 =                            1,
+  BusLogic_IO_230 =                            2,
+  BusLogic_IO_234 =                            3,
+  BusLogic_IO_130 =                            4,
+  BusLogic_IO_134 =                            5,
+  BusLogic_IO_Disable =                        6,
+  BusLogic_IO_Disable2 =               7
+}
+BusLogic_ISACompatibleIOPort_T;
+
+#pragma pack (1)
+typedef struct BusLogic_PCIHostAdapterInformation
+{
+  UCHAR ISACompatibleIOPort;       /* Byte 0 */
+  UCHAR PCIAssignedIRQChannel;         /* Byte 1 */
+  BOOLEAN LowByteTerminated:1;         /* Byte 2 Bit 0 */
+  BOOLEAN HighByteTerminated:1;                /* Byte 2 Bit 1 */
+  UCHAR :2;                                            /* Byte 2 Bits 2-3 */
+  BOOLEAN JP1:1;                                       /* Byte 2 Bit 4 */
+  BOOLEAN JP2:1;                                       /* Byte 2 Bit 5 */
+  BOOLEAN JP3:1;                                       /* Byte 2 Bit 6 */
+  BOOLEAN GenericInfoValid:1;          /* Byte 2 Bit 7 */
+  UCHAR :8;                                            /* Byte 3 */
+}BusLogic_PCIHostAdapterInformation_T;
+
+//  Define the Inquire Board ID reply structure.
+typedef struct BusLogic_BoardID
+{
+  UCHAR BoardType;                                 /* Byte 0 */
+  UCHAR CustomFeatures;                                /* Byte 1 */
+  UCHAR FirmwareVersion1stDigit;       /* Byte 2 */
+  UCHAR FirmwareVersion2ndDigit;       /* Byte 3 */
+} BusLogic_BoardID_T;
+#pragma pack ()
+
+//  Define the Host Adapter Target Flags structure.
+typedef struct BusLogic_TargetFlags
+{
+  BOOLEAN TargetExists:1;
+  BOOLEAN TaggedQueuingSupported:1;
+  BOOLEAN WideTransfersSupported:1;
+  BOOLEAN TaggedQueuingActive:1;
+  BOOLEAN WideTransfersActive:1;
+  BOOLEAN CommandSuccessfulFlag:1;
+  BOOLEAN TargetInfoReported:1;
+}
+BusLogic_TargetFlags_T;
+
+//  Define the Host Adapter Target Statistics structure.
+#define BusLogic_SizeBuckets                   10
+
+//  Define a 10^18 Statistics Byte Counter data type.
+typedef struct BusLogic_ByteCounter
+{
+  unsigned int Units;
+  unsigned int Billions;
+}BusLogic_ByteCounter_T;
+
+typedef unsigned int BusLogic_CommandSizeBuckets_T[BusLogic_SizeBuckets];
+
+typedef struct BusLogic_TargetStatistics
+{
+  unsigned int CommandsAttempted;
+  unsigned int CommandsCompleted;
+  unsigned int ReadCommands;
+  unsigned int WriteCommands;
+  BusLogic_ByteCounter_T TotalBytesRead;
+  BusLogic_ByteCounter_T TotalBytesWritten;
+  BusLogic_CommandSizeBuckets_T ReadCommandSizeBuckets;
+  BusLogic_CommandSizeBuckets_T WriteCommandSizeBuckets;
+  unsigned short CommandAbortsRequested;
+  unsigned short CommandAbortsAttempted;
+  unsigned short CommandAbortsCompleted;
+  unsigned short BusDeviceResetsRequested;
+  unsigned short BusDeviceResetsAttempted;
+  unsigned short BusDeviceResetsCompleted;
+  unsigned short HostAdapterResetsRequested;
+  unsigned short HostAdapterResetsAttempted;
+  unsigned short HostAdapterResetsCompleted;
+}
+BusLogic_TargetStatistics_T;
+
+#pragma pack (1)
+//  Define the Inquire Configuration reply structure.
+typedef struct BusLogic_Configuration
+{
+  UCHAR :5;                                    /* Byte 0 Bits 0-4 */
+  BOOLEAN DMA_Channel5:1;      /* Byte 0 Bit 5 */
+  BOOLEAN DMA_Channel6:1;      /* Byte 0 Bit 6 */
+  BOOLEAN DMA_Channel7:1;      /* Byte 0 Bit 7 */
+  BOOLEAN IRQ_Channel9:1;      /* Byte 1 Bit 0 */
+  BOOLEAN IRQ_Channel10:1;     /* Byte 1 Bit 1 */
+  BOOLEAN IRQ_Channel11:1;     /* Byte 1 Bit 2 */
+  BOOLEAN IRQ_Channel12:1;     /* Byte 1 Bit 3 */
+  UCHAR :1;                                    /* Byte 1 Bit 4 */
+  BOOLEAN IRQ_Channel14:1;     /* Byte 1 Bit 5 */
+  BOOLEAN IRQ_Channel15:1;     /* Byte 1 Bit 6 */
+  UCHAR :1;                                    /* Byte 1 Bit 7 */
+  UCHAR HostAdapterID:4;       /* Byte 2 Bits 0-3 */
+  UCHAR :4;                                    /* Byte 2 Bits 4-7 */
+}BusLogic_Configuration_T;
+
+//  Define the Inquire Setup Information reply structure.
+typedef struct BusLogic_SynchronousValue
+{
+  UCHAR Offset:4;                              /* Bits 0-3 */
+  UCHAR TransferPeriod:3;              /* Bits 4-6 */
+  BOOLEAN Synchronous:1;               /* Bit 7    */
+}BusLogic_SynchronousValue_T;
+
+typedef BusLogic_SynchronousValue_T
+  BusLogic_SynchronousValues8_T[8];
+
+typedef struct BusLogic_SetupInformation
+{
+  BOOLEAN SynchronousInitiationEnabled:1;                /* Byte 0 Bit 0 */
+  BOOLEAN ParityCheckingEnabled:1;                              /* Byte 0 Bit 1 */
+  UCHAR :6;                                                                 /* Byte 0 Bits 2-7 */
+  UCHAR BusTransferRate;                                            /* Byte 1 */
+  UCHAR PreemptTimeOnBus;                                           /* Byte 2 */
+  UCHAR TimeOffBus;                                                     /* Byte 3 */
+  UCHAR MailboxCount;                                               /* Byte 4 */
+  UCHAR MailboxAddress[3];                                          /* Bytes 5-7 */
+  BusLogic_SynchronousValues8_T SynchronousValuesID0to7; /* Bytes 8-15 */
+  UCHAR DisconnectPermittedID0to7;                                              /* Byte 16 */
+  UCHAR Signature;                                                      /* Byte 17 */
+  UCHAR CharacterD;                                                                             /* Byte 18 */
+  UCHAR HostBusType;                                                /* Byte 19 */
+  UCHAR WideTransfersPermittedID0to7;                       /* Byte 20 */
+  UCHAR WideTransfersActiveID0to7;                              /* Byte 21 */
+  BusLogic_SynchronousValues8_T SynchronousValuesID8to15;/* Bytes 22-29 */
+  UCHAR DisconnectPermittedID8to15;                             /* Byte 30 */
+  UCHAR :8;                                                                 /* Byte 31 */
+  UCHAR WideTransfersPermittedID8to15;                      /* Byte 32 */
+  UCHAR WideTransfersActiveID8to15;                             /* Byte 33 */
+}BusLogic_SetupInformation_T;
+
+// Something has to be done about the packing machanism of these structures - Namita
+// Define the Inquire Extended Setup Information reply structure.
+typedef struct BusLogic_ExtendedSetupInformation
+{
+  UCHAR BusType;                                           // Byte 0    
+  UCHAR BIOS_Address;                                  // Byte 1    
+  unsigned short ScatterGatherLimit;           // Bytes 2-3 
+  UCHAR MailboxCount;                                  // Byte 4 
+  BusLogic_BusAddress_T BaseMailboxAddress;    // Bytes 5-8 
+  struct
+  {
+         UCHAR :2;                                                     // Byte 9 Bits 0-1 
+         BOOLEAN FastOnEISA:1;                                 // Byte 9 Bit 2 
+         UCHAR :3;                                                     // Byte 9 Bits 3-5 
+         BOOLEAN LevelSensitiveInterrupt:1;    // Byte 9 Bit 6 
+         UCHAR :1; 
+  } Misc;                                                                      // Byte 9 Bit 7 
+  UCHAR FirmwareRevision[3];                   // Bytes 10-12 
+  BOOLEAN HostWideSCSI:1;                                  // Byte 13 Bit 0 
+  BOOLEAN HostDifferentialSCSI:1;                      // Byte 13 Bit 1 
+  BOOLEAN HostSupportsSCAM:1;                          // Byte 13 Bit 2 
+  BOOLEAN HostUltraSCSI:1;                                 // Byte 13 Bit 3 
+  BOOLEAN HostSmartTermination:1;                      // Byte 13 Bit 4 
+  UCHAR :3;                                                    // Byte 13 Bits 5-7 
+}BusLogic_ExtendedSetupInformation_T;
+
+//  Define the Host Adapter Local RAM AutoSCSI structure.
+typedef struct BusLogic_AutoSCSIData
+{
+  UCHAR InternalFactorySignature[2];/* Bytes 0-1 */
+  UCHAR InformationByteCount;          /* Byte 2 */
+  UCHAR HostAdapterType[6];                    /* Bytes 3-8 */
+  UCHAR :8;                                            /* Byte 9 */
+  UCHAR FloppyEnabled:1;                       /* Byte 10 Bit 0 */
+  UCHAR FloppySecondary:1;                     /* Byte 10 Bit 1 */
+  UCHAR LevelSensitiveInterrupt:1;     /* Byte 10 Bit 2 */
+  UCHAR :2;                                            /* Byte 10 Bits 3-4 */
+  UCHAR SystemRAMAreaForBIOS:3;                /* Byte 10 Bits 5-7 */
+  UCHAR DMA_Channel:7;                         /* Byte 11 Bits 0-6 */
+  UCHAR DMA_AutoConfiguration:1;       /* Byte 11 Bit 7 */
+  UCHAR IRQ_Channel:7;                         /* Byte 12 Bits 0-6 */
+  UCHAR IRQ_AutoConfiguration:1;       /* Byte 12 Bit 7 */
+  UCHAR DMA_TransferRate;                      /* Byte 13 */
+  UCHAR SCSI_ID;                                   /* Byte 14 */
+  UCHAR LowByteTerminated:1;                            /* Byte 15 Bit 0 */
+  UCHAR ParityCheckingEnabled:1;                        /* Byte 15 Bit 1 */
+  UCHAR HighByteTerminated:1;                           /* Byte 15 Bit 2 */
+  UCHAR NoisyCablingEnvironment:1;                      /* Byte 15 Bit 3 */
+  UCHAR FastSynchronousNegotiation:1;           /* Byte 15 Bit 4 */
+  UCHAR BusResetEnabled:1;                                  /* Byte 15 Bit 5 */
+  UCHAR :1;                                                         /* Byte 15 Bit 6 */
+  UCHAR ActiveNegationEnabled:1;                        /* Byte 15 Bit 7 */
+  UCHAR BusOnDelay;                                         /* Byte 16 */
+  UCHAR BusOffDelay;                                    /* Byte 17 */
+  UCHAR HostAdapterBIOSEnabled:1;                       /* Byte 18 Bit 0 */
+  UCHAR BIOSRedirectionOfINT19Enabled:1;        /* Byte 18 Bit 1 */
+  UCHAR ExtendedTranslationEnabled:1;           /* Byte 18 Bit 2 */
+  UCHAR MapRemovableAsFixedEnabled:1;           /* Byte 18 Bit 3 */
+  UCHAR :1;                                                         /* Byte 18 Bit 4 */
+  UCHAR BIOSSupportsMoreThan2DrivesEnabled:1;/* Byte 18 Bit 5 */
+  UCHAR BIOSInterruptModeEnabled:1;                     /* Byte 18 Bit 6 */
+  UCHAR FlopticalSupportEnabled:1;                      /* Byte 19 Bit 7 */
+  unsigned short DeviceEnabled:16;                      /* Bytes 19-20 */
+  unsigned short WidePermitted:16;                      /* Bytes 21-22 */
+  unsigned short FastPermitted:16;                      /* Bytes 23-24 */
+  unsigned short SynchronousPermitted:16;       /* Bytes 25-26 */
+  unsigned short DisconnectPermitted:16;        /* Bytes 27-28 */
+  unsigned short SendStartUnitCommand:16;       /* Bytes 29-30 */
+  unsigned short IgnoreInBIOSScan:16;           /* Bytes 31-32 */
+  UCHAR PCIInterruptPin:2;                              /* Byte 33 Bits 0-1 */
+  UCHAR HostAdapterIOPortAddress:2;             /* Byte 33 Bits 2-3 */
+  UCHAR StrictRoundRobinModeEnabled:1;          /* Byte 33 Bit 4 */
+  UCHAR VESABusSpeedGreaterThan33MHz:1;                 /* Byte 33 Bit 5 */
+  UCHAR VESABurstWriteEnabled:1;                        /* Byte 33 Bit 6 */
+  UCHAR VESABurstReadEnabled:1;                             /* Byte 33 Bit 7 */
+  unsigned short UltraPermitted:16;                     /* Bytes 34-35 */
+  unsigned int :32;                                             /* Bytes 36-39 */
+  UCHAR :8;                                                                     /* Byte 40 */
+  UCHAR AutoSCSIMaximumLUN;                                     /* Byte 41 */
+  UCHAR :1;                                                                     /* Byte 42 Bit 0 */
+  UCHAR SCAM_Dominant:1;                                        /* Byte 42 Bit 1 */
+  UCHAR SCAM_Enabled:1;                                                 /* Byte 42 Bit 2 */
+  UCHAR SCAM_Level2:1;                                          /* Byte 42 Bit 3 */
+  UCHAR :4;                                                                     /* Byte 42 Bits 4-7 */
+  UCHAR INT13ExtensionEnabled:1;                        /* Byte 43 Bit 0 */
+  UCHAR :1;                                                                     /* Byte 43 Bit 1 */
+  UCHAR CDROMBootEnabled:1;                                     /* Byte 43 Bit 2 */
+  UCHAR :5;                                                                     /* Byte 43 Bits 3-7 */
+  UCHAR BootTargetID:4;                                                 /* Byte 44 Bits 0-3 */
+  UCHAR BootChannel:4;                                          /* Byte 44 Bits 4-7 */
+  UCHAR ForceBusDeviceScanningOrder:1;          /* Byte 45 Bit 0 */
+  UCHAR :7;                                                                     /* Byte 45 Bits 1-7 */
+  unsigned short NonTaggedToAlternateLUNPermitted;      /* Bytes 46-47 */
+  unsigned short RenegotiateSyncAfterCheckCondition; /* Bytes 48-49 */
+  UCHAR Reserved[10];                                   /* Bytes 50-59 */
+  UCHAR ManufacturingDiagnostic[2];                 /* Bytes 60-61 */
+  unsigned short Checksum:16;                           /* Bytes 62-63 */
+}BusLogic_AutoSCSIData_T;
+#pragma pack()
+
+//  Define the Outgoing Mailbox Action Codes.
+typedef enum
+{
+  BusLogic_OutgoingMailboxFree =               0x00,
+  BusLogic_MailboxStartCommand =               0x01,
+  BusLogic_MailboxAbortCommand =               0x02
+}BusLogic_ActionCode_T;
+
+
+//  Define the Incoming Mailbox Completion Codes.  The MultiMaster Firmware
+//  only uses codes 0 - 4.  The FlashPoint SCCB Manager has no mailboxes, so
+//  completion codes are stored in the CCB; it only uses codes 1, 2, 4, and 5.
+typedef enum
+{
+  BusLogic_IncomingMailboxFree =                   0x00,
+  BusLogic_CommandCompletedWithoutError =      0x01,
+  BusLogic_CommandAbortedAtHostRequest =       0x02,
+  BusLogic_AbortedCommandNotFound =                0x03,
+  BusLogic_CommandCompletedWithError =         0x04,
+  BusLogic_InvalidCCB =                                        0x05
+}BusLogic_CompletionCode_T;
+
+//  Define the Command Control Block (CCB) Opcodes.
+typedef enum
+{
+  BusLogic_InitiatorCCB =                                  0x00,
+  BusLogic_TargetCCB =                                                 0x01,
+  BusLogic_InitiatorCCB_ScatterGather =                        0x02,
+  BusLogic_InitiatorCCB_ResidualDataLength =   0x03,
+  BusLogic_InitiatorCCB_ScatterGatherResidual =        0x04,
+  BusLogic_BusDeviceReset =                                            0x81
+}BusLogic_CCB_Opcode_T;
+
+
+//  Define the CCB Data Direction Codes.
+typedef enum
+{
+  BusLogic_UncheckedDataTransfer =             0,
+  BusLogic_DataInLengthChecked =               1,
+  BusLogic_DataOutLengthChecked =              2,
+  BusLogic_NoDataTransfer =                            3
+}BusLogic_DataDirection_T;
+
+
+//  Define the Host Adapter Status Codes.  The MultiMaster Firmware does not
+//  return status code 0x0C; it uses 0x12 for both overruns and underruns.
+typedef enum
+{
+  BusLogic_CommandCompletedNormally =          0x00,
+  BusLogic_LinkedCommandCompleted =                0x0A,
+  BusLogic_LinkedCommandCompletedWithFlag =    0x0B,
+  BusLogic_DataUnderRun =                                      0x0C,
+  BusLogic_SCSISelectionTimeout =                      0x11,
+  BusLogic_DataOverRun =                                       0x12,
+  BusLogic_UnexpectedBusFree =                         0x13,
+  BusLogic_InvalidBusPhaseRequested =          0x14,
+  BusLogic_InvalidOutgoingMailboxActionCode =  0x15,
+  BusLogic_InvalidCommandOperationCode =       0x16,
+  BusLogic_LinkedCCBhasInvalidLUN =                    0x17,
+  BusLogic_InvalidCommandParameter =           0x1A,
+  BusLogic_AutoRequestSenseFailed =                    0x1B,
+  BusLogic_TaggedQueuingMessageRejected =      0x1C,
+  BusLogic_UnsupportedMessageReceived =                0x1D,
+  BusLogic_HostAdapterHardwareFailed =         0x20,
+  BusLogic_TargetFailedResponseToATN =         0x21,
+  BusLogic_HostAdapterAssertedRST =                    0x22,
+  BusLogic_OtherDeviceAssertedRST =                    0x23,
+  BusLogic_TargetDeviceReconnectedImproperly = 0x24,
+  BusLogic_HostAdapterAssertedBusDeviceReset = 0x25,
+  BusLogic_AbortQueueGenerated =                       0x26,
+  BusLogic_HostAdapterSoftwareError =          0x27,
+  BusLogic_HostAdapterHardwareTimeoutError=    0x30,
+  BusLogic_SCSIParityErrorDetected =           0x34
+}BusLogic_HostAdapterStatus_T;
+
+//  Define the SCSI Target Device Status Codes.
+typedef enum
+{
+  BusLogic_OperationGood =                     0x00,
+  BusLogic_CheckCondition =                    0x02,
+  BusLogic_DeviceBusy =                                0x08
+}BusLogic_TargetDeviceStatus_T;
+
+//  Define the Queue Tag Codes.
+typedef enum
+{
+  BusLogic_SimpleQueueTag =                    0,
+  BusLogic_HeadOfQueueTag =                    1,
+  BusLogic_OrderedQueueTag =           2,
+  BusLogic_ReservedQT =                                3
+}BusLogic_QueueTag_T;
+
+//  Define the Scatter/Gather Segment structure required by the MultiMaster
+//  Firmware Interface and the FlashPoint SCCB Manager.
+typedef struct BusLogic_ScatterGatherSegment
+{
+  BusLogic_ByteCount_T SegmentByteCount;               /* Bytes 0-3 */
+  BusLogic_BusAddress_T SegmentDataPointer;            /* Bytes 4-7 */
+}BusLogic_ScatterGatherSegment_T;
+
+
+typedef UCHAR SCSI_CDB_T[BusLogic_CDB_MaxLength];
+
+//  Define the Driver CCB Status Codes.
+typedef enum
+{
+  BusLogic_CCB_Free =                          0,
+  BusLogic_CCB_Active =                                1,
+  BusLogic_CCB_Completed =                     2,
+  BusLogic_CCB_Reset =                         3
+}BusLogic_CCB_Status_T;
+
+//  Define the 32 Bit Mode Command Control Block (CCB) structure.  The first 40
+//  bytes are defined by the MultiMaster Firmware The remaining components are 
+//  defined by the Scsi MiniportDriver.  
+//  Extended LUN Format CCBs differ from Legacy LUN Format 32 Bit Mode
+//  CCBs only in having the TagEnable and QueueTag fields moved from byte 17 to
+//  byte 1, and the Logical Unit field in byte 17 expanded to 6 bits.  In theory,
+//  Extended LUN Format CCBs can support up to 64 Logical Units, but in practice
+//  many devices will respond improperly to Logical Units between 32 and 63, and
+//  the SCSI-2 specification defines Bit 5 as LUNTAR.  Extended LUN Format CCBs
+//  are used by recent versions of the MultiMaster Firmware.
+//  Since 64 Logical Units are unlikely to be needed in practice, and
+//  since they are problematic for the above reasons, and since limiting them to
+//  5 bits simplifies the CCB structure definition, this driver only supports
+//  32 Logical Units per Target Device.
+typedef struct BusLogic_CCB
+{
+  UCHAR Opcode;                                    /* Byte 0 */
+  UCHAR :3;                                        /* Byte 1 Bits 0-2 */
+  UCHAR DataDirection:2;               /* Byte 1 Bits 3-4 */
+  UCHAR TagEnable:1;                   /* Byte 1 Bit 5 */
+  UCHAR QueueTag:2;                        /* Byte 1 Bits 6-7 */
+  UCHAR CDB_Length;                            /* Byte 2 */
+  UCHAR SenseDataLength;               /* Byte 3 */
+  BusLogic_ByteCount_T DataLength;     /* Bytes 4-7 */
+  BusLogic_BusAddress_T DataPointer;/* Bytes 8-11 */
+  UCHAR :8;                                            /* Byte 12 */
+  UCHAR :8;                                            /* Byte 13 */
+  UCHAR HostAdapterStatus;                     /* Byte 14 */
+  UCHAR TargetDeviceStatus;                    /* Byte 15 */
+  UCHAR TargetID;                                  /* Byte 16 */
+  UCHAR LogicalUnit:5;                         /* Byte 17 Bits 0-4 */
+  UCHAR LegacyTagEnable:1;                     /* Byte 17 Bit 5 */
+  UCHAR LegacyQueueTag:2;                      /* Byte 17 Bits 6-7 */
+  SCSI_CDB_T CDB;                                      /* Bytes 18-29 */
+  UCHAR :8;                                            /* Byte 30 */
+  UCHAR :8;                                            /* Byte 31 */
+  unsigned int :32;                                    /* Bytes 32-35 */
+  BusLogic_BusAddress_T SenseDataPointer;/* Bytes 36-39 */
+
+  // BusLogic Driver Defined Portion.
+  BusLogic_CCB_Status_T Status;
+  unsigned long SerialNumber;
+  struct BusLogic_HostAdapter *HostAdapter;
+  struct BusLogic_CCB *Next;
+    BusLogic_ScatterGatherSegment_T ScatterGatherList[BusLogic_ScatterGatherLimit];
+
+  BusLogic_CompletionCode_T CompletionCode;
+  // Pointer to the CCB
+  PVOID SrbAddress;
+  PVOID AbortSrb;
+}BusLogic_CCB_T, *PBuslogic_CCB_T;
+
+#pragma pack(1)
+//  Define the 32 Bit Mode Outgoing Mailbox structure.
+typedef struct BusLogic_OutgoingMailbox
+{
+  BusLogic_BusAddress_T CCB;/* Bytes 0-3 */
+  UCHAR :8;                                    /* Bytes 4 */
+  UCHAR :8;                                    /* Bytes 5 */
+  UCHAR :8;                                    /* Bytes 6 */
+  UCHAR ActionCode;                    /* Byte 7 */
+}BusLogic_OutgoingMailbox_T;
+
+//  Define the 32 Bit Mode Incoming Mailbox structure.
+typedef struct BusLogic_IncomingMailbox
+{
+  BusLogic_BusAddress_T CCB;   /* Bytes 0-3 */
+  UCHAR HostAdapterStatus;             /* Byte 4 */
+  UCHAR TargetDeviceStatus;            /* Byte 5 */
+  UCHAR :8;                                            /* Byte 6 */
+  UCHAR CompletionCode;                        /* Byte 7 */
+}BusLogic_IncomingMailbox_T;
+#pragma pack ()
+
+//
+// The following structure is allocated
+// from noncached memory as data will be DMA'd to
+// and from it.
+typedef struct _NONCACHED_EXTENSION 
+{
+    // Physical base address of mailboxes
+    ULONG MailboxPA;
+
+    // Mailboxes
+       UCHAR MailboxOut[BusLogic_MaxMailboxes * sizeof(BusLogic_OutgoingMailbox_T)];                                                                                                           
+       UCHAR MailboxIn[BusLogic_MaxMailboxes * sizeof(BusLogic_IncomingMailbox_T)];
+} NONCACHED_EXTENSION, *PNONCACHED_EXTENSION;
+
+//  Define the types of BusLogic Host Adapters that are supported and the number
+//  of I/O Addresses required by each type.
+typedef enum
+{
+  BusLogic_MultiMaster =                       1,
+  BusLogic_FlashPoint =                                2
+}BusLogic_HostAdapterType_T;
+
+//  Define the possible Host Adapter Bus Types.
+typedef enum
+{
+  BusLogic_Unknown_Bus =                       0,
+  BusLogic_ISA_Bus =                           1,
+  BusLogic_EISA_Bus =                          2,
+  BusLogic_PCI_Bus =                           3,
+  BusLogic_VESA_Bus =                          4,
+  BusLogic_MCA_Bus =                           5
+}BusLogic_HostAdapterBusType_T;
+
+#if 0
+static char *BusLogic_HostAdapterBusNames[] = { "Unknown", "ISA", "EISA", "PCI", "VESA", "MCA" };
+#endif
+static BusLogic_HostAdapterBusType_T
+  BusLogic_HostAdapterBusTypes[] ={ BusLogic_VESA_Bus,    /* BT-4xx */
+                                                                       BusLogic_ISA_Bus,          /* BT-5xx */
+                                                                       BusLogic_MCA_Bus,          /* BT-6xx */
+                                                                       BusLogic_EISA_Bus,         /* BT-7xx */
+                                                                       BusLogic_Unknown_Bus,  /* BT-8xx */
+                                                                       BusLogic_PCI_Bus       /* BT-9xx */
+                                  };                           
+//  Define the BusLogic Driver Host Adapter structure
+typedef struct BusLogic_HostAdapter
+{
+
+  BusLogic_HostAdapterType_T HostAdapterType;
+  BusLogic_HostAdapterBusType_T HostAdapterBusType;
+    
+  UCHAR ModelName[9];
+  UCHAR FirmwareVersion[6];
+  UCHAR FullModelName[18];
+  UCHAR Bus;
+
+  PUCHAR IO_Address;
+  UCHAR IRQ_Channel;
+  UCHAR SCSI_ID;
+  
+  BOOLEAN ExtendedTranslationEnabled:1;
+  BOOLEAN ParityCheckingEnabled:1;
+  BOOLEAN BusResetEnabled:1;
+  BOOLEAN LevelSensitiveInterrupt:1;
+  BOOLEAN HostWideSCSI:1;
+  BOOLEAN HostDifferentialSCSI:1;
+  BOOLEAN HostSupportsSCAM:1;
+  BOOLEAN HostUltraSCSI:1;
+  BOOLEAN ExtendedLUNSupport:1;
+  BOOLEAN TerminationInfoValid:1;
+  BOOLEAN LowByteTerminated:1;
+  BOOLEAN HighByteTerminated:1;
+  BOOLEAN BounceBuffersRequired:1;
+  BOOLEAN StrictRoundRobinModeSupport:1;
+  BOOLEAN SCAM_Enabled:1;
+  BOOLEAN SCAM_Level2:1;
+  BOOLEAN HostAdapterInitialized:1;
+  BOOLEAN HostAdapterExternalReset:1;
+  BOOLEAN HostAdapterInternalError:1;
+
+  BOOLEAN ProcessCompletedCCBsActive;
+  volatile BOOLEAN HostAdapterCommandCompleted;
+  unsigned short HostAdapterScatterGatherLimit;
+  unsigned short DriverScatterGatherLimit;
+  
+  UCHAR MaxTargetDevices;
+  UCHAR MaxLogicalUnits;
+
+  unsigned short DriverQueueDepth;
+  unsigned short HostAdapterQueueDepth;
+  unsigned short UntaggedQueueDepth;
+  unsigned short CommonQueueDepth;
+  unsigned short BusSettleTime;
+  unsigned short SynchronousPermitted;
+  unsigned short FastPermitted;
+  unsigned short UltraPermitted;
+  unsigned short WidePermitted;
+  unsigned short DisconnectPermitted;
+  unsigned short TaggedQueuingPermitted;
+  unsigned short ExternalHostAdapterResets;
+  unsigned short HostAdapterInternalErrors;
+  unsigned short TargetDeviceCount;
+  
+  BusLogic_BusAddress_T BIOS_Address;
+
+  BusLogic_CCB_T *FirstCompletedCCB;
+  BusLogic_CCB_T *LastCompletedCCB;
+  BusLogic_CCB_T *BusDeviceResetPendingCCB[BusLogic_MaxTargetDevices];
+
+  BusLogic_TargetFlags_T TargetFlags[BusLogic_MaxTargetDevices];
+  UCHAR SynchronousPeriod[BusLogic_MaxTargetDevices];
+  UCHAR SynchronousOffset[BusLogic_MaxTargetDevices];
+  UCHAR ActiveCommandsPerTarget[BusLogic_MaxTargetDevices];
+  UCHAR ActiveCommandsPerLun[BusLogic_MaxTargetDevices][BusLogic_MaxLogicalUnits];
+  unsigned int CommandsSinceReset[BusLogic_MaxTargetDevices];
+  unsigned long LastSequencePoint[BusLogic_MaxTargetDevices];
+  unsigned long LastResetAttempted[BusLogic_MaxTargetDevices];
+  unsigned long LastResetCompleted[BusLogic_MaxTargetDevices];
+
+  UCHAR MailboxCount;
+  BusLogic_OutgoingMailbox_T *FirstOutgoingMailbox;
+  BusLogic_OutgoingMailbox_T *LastOutgoingMailbox;
+  BusLogic_OutgoingMailbox_T *NextOutgoingMailbox;
+  BusLogic_IncomingMailbox_T *FirstIncomingMailbox;
+  BusLogic_IncomingMailbox_T *LastIncomingMailbox;
+  BusLogic_IncomingMailbox_T *NextIncomingMailbox;
+  BusLogic_TargetStatistics_T TargetStatistics[BusLogic_MaxTargetDevices];  
+}BusLogic_HostAdapter_T;
+
+
+// Buslogic specific port driver device object extension. 
+typedef struct 
+_HW_DEVICE_EXTENSION
+{ 
+  BusLogic_HostAdapter_T   hcs;
+  PNONCACHED_EXTENSION NoncachedExtension;
+  SCSI_WMILIB_CONTEXT WmiLibContext;
+
+} HW_DEVICE_EXTENSION, *PHW_DEVICE_EXTENSION;
+
+
+//  Define a structure for the SCSI Inquiry command results.
+#pragma pack (1)
+typedef struct SCSI_Inquiry
+{
+  UCHAR PeripheralDeviceType:5;        /* Byte 0 Bits 0-4 */
+  UCHAR PeripheralQualifier:3; /* Byte 0 Bits 5-7 */
+  UCHAR DeviceTypeModifier:7;  /* Byte 1 Bits 0-6 */
+  BOOLEAN RMB:1;                               /* Byte 1 Bit 7 */
+  UCHAR ANSI_ApprovedVersion:3;        /* Byte 2 Bits 0-2 */
+  UCHAR ECMA_Version:3;                        /* Byte 2 Bits 3-5 */
+  UCHAR ISO_Version:2;                 /* Byte 2 Bits 6-7 */
+  UCHAR ResponseDataFormat:4;  /* Byte 3 Bits 0-3 */
+  UCHAR :2;                                            /* Byte 3 Bits 4-5 */
+  BOOLEAN TrmIOP:1;                            /* Byte 3 Bit 6 */
+  BOOLEAN AENC:1;                              /* Byte 3 Bit 7 */
+  UCHAR AdditionalLength;              /* Byte 4 */
+  UCHAR :8;                                            /* Byte 5 */
+  UCHAR :8;                                            /* Byte 6 */
+  BOOLEAN SftRe:1;                             /* Byte 7 Bit 0 */
+  BOOLEAN CmdQue:1;                            /* Byte 7 Bit 1 */
+  BOOLEAN :1;                                  /* Byte 7 Bit 2 */
+  BOOLEAN Linked:1;                            /* Byte 7 Bit 3 */
+  BOOLEAN Sync:1;                              /* Byte 7 Bit 4 */
+  BOOLEAN WBus16:1;                            /* Byte 7 Bit 5 */
+  BOOLEAN WBus32:1;                            /* Byte 7 Bit 6 */
+  BOOLEAN RelAdr:1;                            /* Byte 7 Bit 7 */
+  UCHAR VendorIdentification[8];/* Bytes 8-15 */
+  UCHAR ProductIdentification[16];/* Bytes 16-31 */
+  UCHAR ProductRevisionLevel[4];/* Bytes 32-35 */
+}SCSI_Inquiry_T;
+
+typedef struct BusLogic_WmiExtendedSetupInformation
+{
+  UCHAR BusType;                                           // Byte 0    
+  UCHAR BIOS_Address;                                  // Byte 1    
+  unsigned short ScatterGatherLimit;           // Bytes 2-3 
+  UCHAR MailboxCount;                                  // Byte 4 
+  BusLogic_BusAddress_T BaseMailboxAddress;    // Bytes 5-8 
+  BOOLEAN FastOnEISA;                                  // Byte 9 
+  BOOLEAN LevelSensitiveInterrupt;         // Byte 10
+  UCHAR FirmwareRevision[3];               // Bytes 11-14 
+  BOOLEAN HostWideSCSI;                                    // Byte 15
+  BOOLEAN HostDifferentialSCSI;                        // Byte 16
+  BOOLEAN HostSupportsSCAM;                            // Byte 17
+  BOOLEAN HostUltraSCSI;                               // Byte 18
+  BOOLEAN HostSmartTermination;                        // Byte 19
+}BusLogic_WmiExtendedSetupInformation_T, *PBusLogic_WmiExtendedSetupInformation_T;
+
+#pragma pack ()
+
+//_________________________________________________________________________________________
+// function declaractions
+//_________________________________________________________________________________________
+ULONG
+STDCALL
+DriverEntry(IN PVOID DriverObject,
+                       IN PVOID Argument2
+                       );
+
+ULONG
+STDCALL
+BT958HwFindAdapter(IN PVOID HwDeviceExtension,
+                                  IN PVOID Context,
+                                  IN PVOID BusInformation,
+                                  IN PCHAR ArgumentString,
+                                  IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
+                                  OUT PBOOLEAN Again);
+
+BOOLEAN 
+STDCALL
+BT958HwInitialize(IN PVOID HwDeviceExtension);
+
+BOOLEAN
+STDCALL
+BT958HwStartIO(IN PVOID HwDeviceExtension,
+                          IN PSCSI_REQUEST_BLOCK Srb
+                         );
+
+BOOLEAN
+STDCALL
+BT958HwInterrupt(IN PVOID HwDeviceExtension);
+
+BOOLEAN
+STDCALL
+BT958HwResetBus(IN PVOID HwDeviceExtension,
+                               IN ULONG PathId
+                          );
+
+SCSI_ADAPTER_CONTROL_STATUS
+STDCALL
+BT958HwAdapterControl(IN PVOID HwDeviceExtension,
+                                         IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
+                                         IN PVOID Parameters
+                                         );
+#if 0
+BOOLEAN
+BT958WmiSrb(IN     PHW_DEVICE_EXTENSION    HwDeviceExtension,
+                       IN OUT PSCSI_WMI_REQUEST_BLOCK Srb);
+#endif
+void 
+BT958WmiInitialize( IN PHW_DEVICE_EXTENSION HwDeviceExtension);
+
+
+BOOLEAN 
+Buslogic_InitBT958(PHW_DEVICE_EXTENSION deviceExtension, 
+                                  PPORT_CONFIGURATION_INFORMATION ConfigInfo);
+
+BOOLEAN 
+BusLogic_ProbeHostAdapter(BusLogic_HostAdapter_T *HostAdapter);
+
+BOOLEAN 
+BusLogic_HardwareResetHostAdapter(BusLogic_HostAdapter_T  *HostAdapter, 
+                                                                 BOOLEAN HardReset);
+
+BOOLEAN 
+BusLogic_CheckHostAdapter(BusLogic_HostAdapter_T *HostAdapter);
+
+int 
+BusLogic_Command(BusLogic_HostAdapter_T *HostAdapter,
+                            BusLogic_OperationCode_T OperationCode,
+                                void *ParameterData,
+                                int ParameterLength,
+                                void *ReplyData,
+                                int ReplyLength);
+
+BOOLEAN 
+BusLogic_ReadHostAdapterConfiguration( BusLogic_HostAdapter_T  *HostAdapter);
+                                                                                                        
+BOOLEAN 
+BusLogic_InitializeHostAdapter(PHW_DEVICE_EXTENSION deviceExtension,
+                                                          PPORT_CONFIGURATION_INFORMATION ConfigInfo);
+
+BOOLEAN 
+BusLogic_TargetDeviceInquiry(BusLogic_HostAdapter_T *HostAdapter);
+
+int 
+BusLogic_QueueCommand(IN PVOID HwDeviceExtension,
+                                         IN PSCSI_REQUEST_BLOCK Srb, 
+                                         IN PBuslogic_CCB_T ccb);
+
+BOOLEAN 
+BusLogic_WriteOutgoingMailbox(PHW_DEVICE_EXTENSION deviceExtension ,
+                                                         BusLogic_ActionCode_T ActionCode,
+                                                         BusLogic_CCB_T *CCB);
+
+void 
+BusLogic_ScanIncomingMailboxes(PHW_DEVICE_EXTENSION deviceExtension);
+
+void 
+BusLogic_QueueCompletedCCB(PHW_DEVICE_EXTENSION deviceExtension, BusLogic_CCB_T *CCB);
+
+void 
+BusLogic_ProcessCompletedCCBs(PHW_DEVICE_EXTENSION deviceExtension);
+
+UCHAR 
+BusLogic_ComputeResultCode(BusLogic_HostAdapter_T        *HostAdapter,
+                                                  BusLogic_HostAdapterStatus_T  HostAdapterStatus,
+                                                  BusLogic_TargetDeviceStatus_T TargetDeviceStatus,
+                                                  UCHAR SenseDataLength);
+
+BOOLEAN
+BusLogic_SendBusDeviceReset(IN PVOID HwDeviceExtension,
+                                                       PSCSI_REQUEST_BLOCK Srb);
+
+UCHAR 
+ReadBusLogicPort(PUCHAR adr )
+{
+       return ScsiPortReadPortUchar( adr );
+}
+
+VOID 
+WriteBusLogicPort(UCHAR data,
+                                 PUCHAR adr)
+{
+       ScsiPortWritePortUchar(adr, data);
+}
+
+//_________________________________________________________________________________________
+// Declarations for the device registers and rewading and writing to them
+//_________________________________________________________________________________________
+
+//  Define the BusLogic SCSI Host Adapter I/O Register Offsets.
+#define BusLogic_ControlRegisterOffset             0   // WO register 
+#define BusLogic_StatusRegisterOffset              0   // RO register 
+#define BusLogic_CommandParameterRegisterOffset        1       // WO register 
+#define BusLogic_DataInRegisterOffset              1   // RO register 
+#define BusLogic_InterruptRegisterOffset           2   // RO register 
+#define BusLogic_GeometryRegisterOffset                    3   // RO register 
+
+
+//  Define the structure of the write-only Control Register.
+typedef union BusLogic_ControlRegister
+{
+  UCHAR All;
+  struct
+  {
+    UCHAR :4;                                  // Bits 0-3 
+    BOOLEAN SCSIBusReset:1;            // Bit 4 
+    BOOLEAN InterruptReset:1;  // Bit 5 
+    BOOLEAN SoftReset:1;               // Bit 6 
+    BOOLEAN HardReset:1;               // Bit 7 
+  } Bits;
+}BusLogic_ControlRegister_T;
+
+
+//  Define the structure of the read-only Status Register.
+typedef union BusLogic_StatusRegister
+{
+  UCHAR All;
+  struct 
+  {
+    BOOLEAN CommandInvalid:1;                          // Bit 0 
+    BOOLEAN Reserved:1;                                            // Bit 1 
+    BOOLEAN DataInRegisterReady:1;                     // Bit 2 
+    BOOLEAN CommandParameterRegisterBusy:1;    // Bit 3 
+    BOOLEAN HostAdapterReady:1;                                // Bit 4 
+    BOOLEAN InitializationRequired:1;          // Bit 5 
+    BOOLEAN DiagnosticFailure:1;                       // Bit 6 
+    BOOLEAN DiagnosticActive:1;                                // Bit 7 
+  } Bits;
+}BusLogic_StatusRegister_T;
+
+
+
+//  Define the structure of the read-only Interrupt Register.
+typedef union BusLogic_InterruptRegister
+{
+  UCHAR All;
+  struct
+  {
+    BOOLEAN IncomingMailboxLoaded:1;   // Bit 0 
+    BOOLEAN OutgoingMailboxAvailable:1;        // Bit 1 
+    BOOLEAN CommandComplete:1;                 // Bit 2 
+    BOOLEAN ExternalBusReset:1;                        // Bit 3 
+    UCHAR Reserved:3;                              // Bits 4-6 
+    BOOLEAN InterruptValid:1;                  // Bit 7 
+  } Bits;
+}BusLogic_InterruptRegister_T;
+
+//  Define the possible Host Adapter BIOS Disk Geometry Translations.
+typedef enum BusLogic_BIOS_DiskGeometryTranslation
+{
+  BusLogic_BIOS_Disk_Not_Installed =           0,
+  BusLogic_BIOS_Disk_Installed_64x32 =         1,
+  BusLogic_BIOS_Disk_Installed_128x32 =                2,
+  BusLogic_BIOS_Disk_Installed_255x63 =                3
+}BusLogic_BIOS_DiskGeometryTranslation_T;
+
+//  Define the structure of the read-only Geometry Register
+typedef union BusLogic_GeometryRegister
+{
+  UCHAR All;
+  struct
+  {
+    BusLogic_BIOS_DiskGeometryTranslation_T Drive0Geometry:2; // Bits 0-1 
+    BusLogic_BIOS_DiskGeometryTranslation_T Drive1Geometry:2; // Bits 2-3 
+    UCHAR :3;                                                                // Bits 4-6 
+    BOOLEAN ExtendedTranslationEnabled:1;                            // Bit 7 
+  } Bits;
+}
+BusLogic_GeometryRegister_T;
+
+void 
+BusLogic_InterruptReset(BusLogic_HostAdapter_T *HostAdapter)
+{
+  BusLogic_ControlRegister_T ControlRegister;
+  ControlRegister.All = 0;
+  ControlRegister.Bits.InterruptReset = TRUE;
+
+  WriteBusLogicPort(ControlRegister.All,
+       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+}
+
+void
+BusLogic_SoftReset(BusLogic_HostAdapter_T *HostAdapter)
+{
+  BusLogic_ControlRegister_T ControlRegister;
+  ControlRegister.All = 0;
+  ControlRegister.Bits.SoftReset = TRUE;
+  WriteBusLogicPort(ControlRegister.All,
+       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+}
+
+void 
+BusLogic_HardReset(BusLogic_HostAdapter_T *HostAdapter)
+{
+  BusLogic_ControlRegister_T ControlRegister;
+  ControlRegister.All = 0;
+  ControlRegister.Bits.HardReset = TRUE;
+  WriteBusLogicPort(ControlRegister.All,
+       HostAdapter->IO_Address + BusLogic_ControlRegisterOffset);
+}
+
+UCHAR 
+BusLogic_ReadStatusRegister(BusLogic_HostAdapter_T *HostAdapter)
+{
+  return ReadBusLogicPort(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset);
+}
+
+UCHAR 
+BusLogic_ReadInterruptRegister(BusLogic_HostAdapter_T *HostAdapter)
+{
+  return ReadBusLogicPort(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset);
+}
+
+UCHAR 
+BusLogic_ReadGeometryRegister(BusLogic_HostAdapter_T *HostAdapter)
+{
+  return ReadBusLogicPort(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset);
+}
+
+UCHAR 
+BusLogic_ReadDataInRegister(BusLogic_HostAdapter_T *HostAdapter)
+{
+  return ReadBusLogicPort(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset);
+}
+
+void 
+BusLogic_WriteCommandParameterRegister(BusLogic_HostAdapter_T *HostAdapter,
+                                                                          UCHAR Value)
+{
+  WriteBusLogicPort(Value,
+                                       HostAdapter->IO_Address + BusLogic_CommandParameterRegisterOffset);
+}
+
+//  BusLogic_StartMailboxCommand issues an Execute Mailbox Command, which
+//  notifies the Host Adapter that an entry has been made in an Outgoing
+//  Mailbox.
+void 
+BusLogic_StartMailboxCommand(BusLogic_HostAdapter_T *HostAdapter)
+{
+  BusLogic_WriteCommandParameterRegister(HostAdapter, 
+                                                                                BusLogic_ExecuteMailboxCommand);
+}
+
+//  Define the Inquire Synchronous Period reply type.  For each Target Device,
+//  a byte is returned which represents the Synchronous Transfer Period in units
+//  of 10 nanoseconds.
+typedef UCHAR BusLogic_SynchronousPeriod_T[BusLogic_MaxTargetDevices];
+
+//  Define the Inquire Installed Devices ID 0 to 7 and Inquire Installed
+//  Devices ID 8 to 15 reply type.  For each Target Device, a byte is returned
+//  where bit 0 set indicates that Logical Unit 0 exists, bit 1 set indicates
+//  that Logical Unit 1 exists, and so on.
+typedef UCHAR BusLogic_InstalledDevices8_T[8];
+
+//  Define the Inquire Target Devices reply type.  Inquire Target Devices only
+//  tests Logical Unit 0 of each Target Device unlike the Inquire Installed
+//  Devices commands which test Logical Units 0 - 7.  Two bytes are returned,
+//  where byte 0 bit 0 set indicates that Target Device 0 exists, and so on.
+typedef unsigned short BusLogic_InstalledDevices_T;
+
+//  Define the Initialize Extended Mailbox request structure.
+#pragma pack (1)
+typedef struct BusLogic_ExtendedMailboxRequest
+{
+       UCHAR MailboxCount;                     /* Byte 0 */
+       ULONG BaseMailboxAddress;       /* Bytes 1-4 */
+}BusLogic_ExtendedMailboxRequest_T;
+#pragma pack ()
+
+//  Define the Set CCB Format request type.  Extended LUN Format CCBs are
+//  necessary to support more than 8 Logical Units per Target Device.
+typedef enum BusLogic_SetCCBFormatRequest
+{
+  BusLogic_LegacyLUNFormatCCB =                        0,
+  BusLogic_ExtendedLUNFormatCCB =              1
+}BusLogic_SetCCBFormatRequest_T;
+
+//______________________________________________________________________________________
+// Statistics
+//______________________________________________________________________________________
+//  BusLogic_IncrementByteCounter increments Byte Counter by Amount.
+void 
+BusLogic_IncrementByteCounter(BusLogic_ByteCounter_T *ByteCounter,
+                                                         unsigned int Amount)
+{
+  ByteCounter->Units += Amount;
+  if (ByteCounter->Units > 999999999)
+  {
+      ByteCounter->Units -= 1000000000;
+      ByteCounter->Billions++;
+  }
+}
+
+//  BusLogic_IncrementSizeBucket increments the Bucket for Amount.
+void 
+BusLogic_IncrementSizeBucket(BusLogic_CommandSizeBuckets_T CommandSizeBuckets,
+                                                    unsigned int Amount)
+{
+  int Index = 0;
+  if (Amount < 8*1024)
+  {
+    if (Amount < 2*1024)
+               Index = (Amount < 1*1024 ? 0 : 1);
+    else 
+               Index = (Amount < 4*1024 ? 2 : 3);
+  }
+  else if (Amount < 128*1024)
+  {
+    if (Amount < 32*1024)
+               Index = (Amount < 16*1024 ? 4 : 5);
+    else 
+               Index = (Amount < 64*1024 ? 6 : 7);
+  }
+  else 
+         Index = (Amount < 256*1024 ? 8 : 9);
+  CommandSizeBuckets[Index]++;
+}
+
+
+//  BusLogic_IncrementErrorCounter increments Error Counter by 1, stopping at
+//  65535 rather than wrapping around to 0.
+void 
+BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter)
+{
+  if (*ErrorCounter < 65535) (*ErrorCounter)++;
+}
+//____________________________________________________________________________________________
+
+#endif  // _BT958_H_ 
diff --git a/reactos/drivers/storage/buslogic/BusLogic958.rc b/reactos/drivers/storage/buslogic/BusLogic958.rc
new file mode 100644 (file)
index 0000000..ff3191d
--- /dev/null
@@ -0,0 +1,116 @@
+//Microsoft Developer Studio generated resource script.
+//
+#include "resource.h"
+
+#define APSTUDIO_READONLY_SYMBOLS
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 2 resource.
+//
+#include "afxres.h"
+
+/////////////////////////////////////////////////////////////////////////////
+#undef APSTUDIO_READONLY_SYMBOLS
+
+/////////////////////////////////////////////////////////////////////////////
+// English (U.S.) resources
+
+#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
+#ifdef _WIN32
+LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
+#pragma code_page(1252)
+#endif //_WIN32
+
+#ifndef _MAC
+/////////////////////////////////////////////////////////////////////////////
+//
+// Version
+//
+
+VS_VERSION_INFO VERSIONINFO
+ FILEVERSION 1,2,0,0
+ PRODUCTVERSION 1,2,0,0
+ FILEFLAGSMASK 0x3fL
+#ifdef _DEBUG
+ FILEFLAGS 0x1L
+#else
+ FILEFLAGS 0x0L
+#endif
+ FILEOS 0x40004L
+ FILETYPE 0x3L
+ FILESUBTYPE 0x7L
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK "040904b0"
+        BEGIN
+            VALUE "Comments", "\0"
+            VALUE "CompanyName", "VMware, Inc.\0"
+            VALUE "FileDescription", "VMware SCSI Controller\0"
+            VALUE "FileVersion", "1, 2, 0, 0\0"
+            VALUE "InternalName", "vmscsi.sys\0"
+            VALUE "LegalCopyright", "Copyright © 1998-2003 VMware, Inc.\0"
+            VALUE "LegalTrademarks", "\0"
+            VALUE "OriginalFilename", "vmscsi.sys\0"
+            VALUE "PrivateBuild", "\0"
+            VALUE "ProductName", "VMware, Inc. Script1 Application\0"
+            VALUE "ProductVersion", "1, 2, 0, 0\0"
+            VALUE "SpecialBuild", "\0"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", 0x409, 1200
+    END
+END
+
+#endif    // !_MAC
+
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// MOFDATA
+//
+
+MOFRESOURCE             MOFDATA MOVEABLE PURE   "BT958.bmf"
+
+#ifdef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// TEXTINCLUDE
+//
+
+1 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "resource.h\0"
+END
+
+2 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "#include ""afxres.h""\r\n"
+    "\0"
+END
+
+3 TEXTINCLUDE DISCARDABLE 
+BEGIN
+    "\r\n"
+    "\0"
+END
+
+#endif    // APSTUDIO_INVOKED
+
+#endif    // English (U.S.) resources
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef APSTUDIO_INVOKED
+/////////////////////////////////////////////////////////////////////////////
+//
+// Generated from the TEXTINCLUDE 3 resource.
+//
+
+
+/////////////////////////////////////////////////////////////////////////////
+#endif    // not APSTUDIO_INVOKED
+
diff --git a/reactos/drivers/storage/buslogic/Log.c b/reactos/drivers/storage/buslogic/Log.c
new file mode 100644 (file)
index 0000000..c29671b
--- /dev/null
@@ -0,0 +1,104 @@
+#include "Log.h"
+#include <stdarg.h>
+#include <stdio.h>
+#pragma hdrstop        
+
+BOOLEAN LogMessage(PCHAR szFormat, ...)
+{
+       ULONG Length;
+       char messagebuf[256];
+       va_list va;
+    IO_STATUS_BLOCK  IoStatus;
+       OBJECT_ATTRIBUTES objectAttributes;
+       NTSTATUS status;
+       HANDLE FileHandle;
+    UNICODE_STRING fileName;
+
+               
+       //format the string
+    va_start(va,szFormat);
+       vsprintf(messagebuf,szFormat,va);
+       va_end(va);
+
+       //get a handle to the log file object
+    fileName.Buffer = NULL;
+    fileName.Length = 0;
+    fileName.MaximumLength = sizeof(DEFAULT_LOG_FILE_NAME) + sizeof(UNICODE_NULL);
+    fileName.Buffer = ExAllocatePool(PagedPool,
+                                        fileName.MaximumLength);
+    if (!fileName.Buffer)
+    {
+        return FALSE;
+    }
+    RtlZeroMemory(fileName.Buffer, fileName.MaximumLength);
+    status = RtlAppendUnicodeToString(&fileName, (PWSTR)DEFAULT_LOG_FILE_NAME);
+       
+       //DbgPrint("\n Initializing Object attributes");
+
+       InitializeObjectAttributes (&objectAttributes,
+                                                               (PUNICODE_STRING)&fileName,
+                                                               OBJ_CASE_INSENSITIVE,
+                                                               NULL,
+                                                               NULL );
+
+       DbgPrint("\n BusLogic - Creating the file");
+       
+       status = ZwCreateFile(&FileHandle,
+                                         FILE_APPEND_DATA,
+                                         &objectAttributes,
+                                         &IoStatus,
+                                         0, 
+                                         FILE_ATTRIBUTE_NORMAL,
+                                         FILE_SHARE_WRITE,
+                                         FILE_OPEN_IF,
+                                         FILE_SYNCHRONOUS_IO_NONALERT,
+                                         NULL,     
+                                         0 );
+
+       if(NT_SUCCESS(status))
+       {
+               CHAR buf[300];
+               LARGE_INTEGER time;
+               KeQuerySystemTime(&time);
+
+               DbgPrint("\n BusLogic - Created the file");
+
+               //put a time stamp on the output message
+               sprintf(buf,"%10u-%10u  %s",time.HighPart,time.LowPart,messagebuf);
+
+               //format the string to make sure it appends a newline carrage-return to the 
+               //end of the string.
+               Length=strlen(buf);
+               if(buf[Length-1]=='\n')
+               {
+                       buf[Length-1]='\r';
+                       strcat(buf,"\n");
+                       Length++;
+               }
+               else
+               {
+                       strcat(buf,"\r\n");
+                       Length+=2;
+               }
+
+               buf[Length+1] = '\0';
+               DbgPrint("\n BusLogic - Writing to the file");
+               DbgPrint("\n BusLogic - Buf = %s", buf);
+               
+               status = ZwWriteFile(FileHandle,
+                                 NULL,
+                                 NULL,
+                                 NULL,
+                                 &IoStatus,
+                                 buf,
+                                 Length,
+                                 NULL,
+                                 NULL );
+
+               ZwClose(FileHandle);
+       }
+       if (fileName.Buffer)
+        ExFreePool (fileName.Buffer);
+
+       return STATUS_SUCCESS;
+}
diff --git a/reactos/drivers/storage/buslogic/Log.h b/reactos/drivers/storage/buslogic/Log.h
new file mode 100644 (file)
index 0000000..817e2bd
--- /dev/null
@@ -0,0 +1,5 @@
+#include "ntddk.h"
+
+#define DEFAULT_LOG_FILE_NAME  L"\\??\\D:\\Temp\\BL958.log"
+
+BOOLEAN LogMessage(PCHAR szFormat, ...);
diff --git a/reactos/drivers/storage/buslogic/README.ReactOS b/reactos/drivers/storage/buslogic/README.ReactOS
new file mode 100644 (file)
index 0000000..1af5801
--- /dev/null
@@ -0,0 +1,11 @@
+This code was published by VMware on their website at
+http://www.vmware.com/download/open_sources.html. The intro there says:
+
+This open source software is licensed under the terms of various open source
+license agreements included with the materials relating to the open source
+software. Copyrights in the open source software are held by the copyright
+holders indicated in the copyright notices in the open source files. You may
+download this software free of charge.
+
+The source files indicate they are GPL licenced, so we're ok to include it
+in ReactOS.
diff --git a/reactos/drivers/storage/buslogic/buslogic.xml b/reactos/drivers/storage/buslogic/buslogic.xml
new file mode 100644 (file)
index 0000000..2387d3a
--- /dev/null
@@ -0,0 +1,10 @@
+<module name="buslogic" type="kernelmodedriver" installbase="system32/drivers" installname="buslogic.sys">
+       <bootstrap base="reactos" />
+       <define name="__USE_W32API" />
+       <include base="buslogic">.</include>
+       <library>ntoskrnl</library>
+       <library>hal</library>
+       <library>scsiport</library>
+       <file>BusLogic958.c</file>
+       <file>BusLogic958.rc</file>
+</module>
diff --git a/reactos/drivers/storage/buslogic/makefile.inc b/reactos/drivers/storage/buslogic/makefile.inc
new file mode 100644 (file)
index 0000000..828967c
--- /dev/null
@@ -0,0 +1,5 @@
+clean:
+       del BT958dt.h BT958.bmf
+
+BT958dt.h: BT958.bmf
+       wmimofck -hBT958dt.h BT958.bmf
diff --git a/reactos/drivers/storage/buslogic/makefile.original b/reactos/drivers/storage/buslogic/makefile.original
new file mode 100644 (file)
index 0000000..5818975
--- /dev/null
@@ -0,0 +1,7 @@
+#
+# DO NOT EDIT THIS FILE!!!  Edit .\sources. if you want to add a new source
+# file to this component.  This file merely indirects to the real make file
+# that is shared by all the driver components of the Windows NT DDK
+#
+
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/reactos/drivers/storage/buslogic/resource.h b/reactos/drivers/storage/buslogic/resource.h
new file mode 100644 (file)
index 0000000..009dfad
--- /dev/null
@@ -0,0 +1,15 @@
+//{{NO_DEPENDENCIES}}
+// Microsoft Visual C++ generated include file.
+// Used by BusLogic958.rc
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/reactos/drivers/storage/buslogic/sources b/reactos/drivers/storage/buslogic/sources
new file mode 100644 (file)
index 0000000..27e6cf1
--- /dev/null
@@ -0,0 +1,17 @@
+TARGETNAME=vmscsi
+TARGETPATH=obj
+TARGETTYPE=MINIPORT
+
+TARGETLIBS=$(DDK_LIB_PATH)\scsiport.lib \
+           $(DDK_LIB_PATH)\scsiwmi.lib  \
+          $(SDK_LIB_PATH)\ntoskrnl.lib
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES=BT958.mof      \
+        BusLogic958.c  \
+        BusLogic958.rc \
+        wmi.c          \
+        Log.c
+
+NTTARGETFILE0=BT958dt.h
diff --git a/reactos/drivers/storage/buslogic/wmi.c b/reactos/drivers/storage/buslogic/wmi.c
new file mode 100644 (file)
index 0000000..a1b7c64
--- /dev/null
@@ -0,0 +1,416 @@
+#include "miniport.h"
+#include "BusLogic958.h"        // includes scsi.h
+#include "wmistr.h"             // WMI definitions
+
+#include "BT958dt.h"
+
+#define BT958Wmi_MofResourceName        L"MofResource"
+
+#define BT958_SETUP_GUID_INDEX 0
+
+GUID BT958WmiExtendedSetupInfoGuid = BT958Wmi_ExtendedSetupInfo_Guid;
+
+UCHAR
+BT958ReadExtendedSetupInfo
+(
+   IN  PHW_DEVICE_EXTENSION HwDeviceExtension,
+   OUT PUCHAR               Buffer
+);
+
+BOOLEAN
+BT958QueryWmiDataBlock
+(
+    IN PVOID Context,
+    IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
+    IN ULONG GuidIndex,
+    IN ULONG InstanceIndex,
+    IN ULONG InstanceCount,
+    IN OUT PULONG InstanceLengthArray,
+    IN ULONG OutBufferSize,
+    OUT PUCHAR Buffer
+);
+
+UCHAR
+BT958QueryWmiRegInfo
+(
+    IN PVOID Context,
+    IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
+    OUT PWCHAR *MofResourceName
+);
+
+SCSIWMIGUIDREGINFO BT958GuidList[] = 
+{
+   {&BT958WmiExtendedSetupInfoGuid,
+    1,
+    0
+   },
+};
+
+#define BT958GuidCount (sizeof(BT958GuidList) / sizeof(SCSIWMIGUIDREGINFO))
+
+
+void BT958WmiInitialize(
+    IN PHW_DEVICE_EXTENSION HwDeviceExtension
+    )
+{
+    PSCSI_WMILIB_CONTEXT WmiLibContext;
+    
+    WmiLibContext = &HwDeviceExtension->WmiLibContext;
+    
+    WmiLibContext->GuidList = BT958GuidList;
+    WmiLibContext->GuidCount = BT958GuidCount;
+    WmiLibContext->QueryWmiRegInfo = BT958QueryWmiRegInfo;
+    WmiLibContext->QueryWmiDataBlock = BT958QueryWmiDataBlock;
+    WmiLibContext->SetWmiDataItem = NULL;
+    WmiLibContext->SetWmiDataBlock = NULL;
+    WmiLibContext->WmiFunctionControl = NULL;
+    WmiLibContext->ExecuteWmiMethod = NULL;    
+}
+
+
+
+BOOLEAN
+BT958WmiSrb(
+    IN     PHW_DEVICE_EXTENSION    HwDeviceExtension,
+    IN OUT PSCSI_WMI_REQUEST_BLOCK Srb
+    )
+/*++
+
+Routine Description:
+
+   Process an SRB_FUNCTION_WMI request packet.
+
+   This routine is called from the SCSI port driver synchronized with the
+   kernel via BT958StartIo.   On completion of WMI processing, the SCSI
+   port driver is notified that the adapter can take another request,  if
+   any are available.
+
+Arguments:
+
+   HwDeviceExtension - HBA miniport driver's adapter data storage.
+
+   Srb               - IO request packet.
+
+Return Value:
+
+   Value to return to BT958StartIo caller.   Always TRUE.
+
+--*/
+{
+   UCHAR status;
+   SCSIWMI_REQUEST_CONTEXT requestContext;
+   ULONG retSize;
+   BOOLEAN pending;
+
+   // Validate our assumptions.
+   ASSERT(Srb->Function == SRB_FUNCTION_WMI);
+   ASSERT(Srb->Length == sizeof(SCSI_WMI_REQUEST_BLOCK));
+   ASSERT(Srb->DataTransferLength >= sizeof(ULONG));
+   ASSERT(Srb->DataBuffer);
+   
+   // Check if the WMI SRB is targetted for the adapter or one of the disks
+   if (!(Srb->WMIFlags & SRB_WMI_FLAGS_ADAPTER_REQUEST)) 
+   {
+           
+      // This is targetted to one of the disks, since there are no per disk
+      // wmi information we return an error. Note that if there was per
+      // disk information, then you'd likely have a differen WmiLibContext
+      // and a different set of guids.
+      Srb->DataTransferLength = 0;
+      Srb->SrbStatus = SRB_STATUS_SUCCESS;
+
+   } 
+   else
+   {
+       // Process the incoming WMI request.
+       pending = ScsiPortWmiDispatchFunction(&HwDeviceExtension->WmiLibContext,
+                                                Srb->WMISubFunction,
+                                                HwDeviceExtension,
+                                                &requestContext,
+                                                Srb->DataPath,
+                                                Srb->DataTransferLength,
+                                                Srb->DataBuffer);
+                    
+       // We assune that the wmi request will never pend so that we can
+       // allocate the requestContext from stack. If the WMI request could
+       // ever pend then we'd need to allocate the request context from
+       // the SRB extension.
+       //
+       ASSERT(! pending);
+     
+       retSize =  ScsiPortWmiGetReturnSize(&requestContext);
+       status =  ScsiPortWmiGetReturnStatus(&requestContext);
+    
+       // We can do this since we assume it is done synchronously       
+       Srb->DataTransferLength = retSize;
+           
+       //
+       // Adapter ready for next request.
+       //
+    
+       Srb->SrbStatus = status;
+   }
+
+   ScsiPortNotification(RequestComplete, HwDeviceExtension, Srb);
+   ScsiPortNotification(NextRequest,     HwDeviceExtension, NULL);
+
+   return TRUE;
+}
+
+
+
+BOOLEAN
+BT958QueryWmiDataBlock(
+    IN PVOID Context,
+    IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
+    IN ULONG GuidIndex,
+    IN ULONG InstanceIndex,
+    IN ULONG InstanceCount,
+    IN OUT PULONG InstanceLengthArray,
+    IN ULONG OutBufferSize,
+    OUT PUCHAR Buffer
+    )
+/*++
+
+Routine Description:
+
+    This routine is a callback into the miniport to query for the contents of
+    one or more instances of a data block. This callback may be called with 
+    an output buffer that is too small to return all of the data queried.
+    In this case the callback is responsible to report the correct output 
+        buffer size needed.
+        
+    If the request can be completed immediately without pending, 
+        ScsiPortWmiPostProcess should be called from within this callback and 
+    FALSE returned.
+                
+    If the request cannot be completed within this callback then TRUE should
+    be returned. Once the pending operations are finished the miniport should
+    call ScsiPortWmiPostProcess and then complete the srb.
+        
+Arguments:
+
+    DeviceContext is a caller specified context value originally passed to
+        ScsiPortWmiDispatchFunction.
+
+    RequestContext is a context associated with the srb being processed.
+                        
+    GuidIndex is the index into the list of guids provided when the
+        miniport registered
+
+    InstanceIndex is the index that denotes first instance of the data block
+        is being queried.
+            
+    InstanceCount is the number of instances expected to be returned for
+        the data block.
+            
+    InstanceLengthArray is a pointer to an array of ULONG that returns the 
+        lengths of each instance of the data block. This may be NULL when
+        there is not enough space in the output buffer to fufill the request.
+        In this case the miniport should call ScsiPortWmiPostProcess with
+        a status of SRB_STATUS_DATA_OVERRUN and the size of the output buffer
+        needed to fufill the request.
+            
+    BufferAvail on entry has the maximum size available to write the data
+        blocks in the output buffer. If the output buffer is not large enough 
+        to return all of the data blocks then the miniport should call 
+        ScsiPortWmiPostProcess with a status of SRB_STATUS_DATA_OVERRUN 
+        and the size of the output buffer needed to fufill the request.
+
+    Buffer on return is filled with the returned data blocks. Note that each
+        instance of the data block must be aligned on a 8 byte boundry. This 
+        may be NULL when there is not enough space in the output buffer to 
+        fufill the request. In this case the miniport should call 
+        ScsiPortWmiPostProcess with a status of SRB_STATUS_DATA_OVERRUN and 
+        the size of the output buffer needed to fufill the request.
+
+
+Return Value:
+
+    TRUE if request is pending else FALSE
+
+--*/
+{
+    PHW_DEVICE_EXTENSION HwDeviceExtension = (PHW_DEVICE_EXTENSION)Context;
+    ULONG size;
+    UCHAR status;
+
+    //
+    // Only ever registers 1 instance per guid
+    ASSERT((InstanceIndex == 0) &&
+           (InstanceCount == 1));
+
+    switch (GuidIndex) 
+    {
+        case BT958_SETUP_GUID_INDEX:
+        {
+            size = sizeof(BT958ExtendedSetupInfo)-1;
+            if (OutBufferSize < size) 
+            {
+                //
+                // The buffer passed to return the data is too small
+                //
+                status = SRB_STATUS_DATA_OVERRUN;
+                break;
+            }
+
+            if ( !BT958ReadExtendedSetupInfo(HwDeviceExtension,
+                                     Buffer))
+            {
+                ASSERT(FALSE);
+                size = 0;
+                status = SRB_STATUS_ERROR;
+            }
+                       else
+                       {
+                *InstanceLengthArray = size;
+                status = SRB_STATUS_SUCCESS;
+            }
+            break;
+        }
+
+        default:
+        {
+            status = SRB_STATUS_ERROR;
+        }
+    }
+
+    ScsiPortWmiPostProcess(       RequestContext,
+                                  status,
+                                  size);
+
+    return status;
+}
+
+UCHAR
+BT958QueryWmiRegInfo(
+    IN PVOID Context,
+    IN PSCSIWMI_REQUEST_CONTEXT RequestContext,
+    OUT PWCHAR *MofResourceName
+    )
+/*++
+
+Routine Description:
+
+    This routine is a callback into the driver to retrieve information about
+    the guids being registered.
+
+    Implementations of this routine may be in paged memory
+
+Arguments:
+
+    DeviceObject is the device whose registration information is needed
+
+    *RegFlags returns with a set of flags that describe all of the guids being
+        registered for this device. If the device wants enable and disable
+        collection callbacks before receiving queries for the registered
+        guids then it should return the WMIREG_FLAG_EXPENSIVE flag. Also the
+        returned flags may specify WMIREG_FLAG_INSTANCE_PDO in which case
+        the instance name is determined from the PDO associated with the
+        device object. Note that the PDO must have an associated devnode. If
+        WMIREG_FLAG_INSTANCE_PDO is not set then Name must return a unique
+        name for the device. These flags are ORed into the flags specified
+        by the GUIDREGINFO for each guid.
+
+    InstanceName returns with the instance name for the guids if
+        WMIREG_FLAG_INSTANCE_PDO is not set in the returned *RegFlags. The
+        caller will call ExFreePool with the buffer returned.
+
+    *RegistryPath returns with the registry path of the driver. This is
+        required
+
+    *MofResourceName returns with the name of the MOF resource attached to
+        the binary file. If the driver does not have a mof resource attached
+        then this can be returned as NULL.
+
+    *Pdo returns with the device object for the PDO associated with this
+        device if the WMIREG_FLAG_INSTANCE_PDO flag is retured in
+        *RegFlags.
+
+Return Value:
+
+    status
+
+--*/
+{
+    *MofResourceName = BT958Wmi_MofResourceName;    
+    return SRB_STATUS_SUCCESS;
+}
+
+
+UCHAR
+BT958ReadExtendedSetupInfo(
+   IN  PHW_DEVICE_EXTENSION HwDeviceExtension,
+   OUT PUCHAR               Buffer
+   )
+/*++
+
+Routine Description:
+
+   Read the adapter setup information into the supplied buffer.  The buffer
+   must be RM_CFG_MAX_SIZE (255) bytes large.
+
+Arguments:
+
+   HwDeviceExtension - HBA miniport driver's adapter data storage.
+
+   Buffer - Buffer to hold adapter's setup information structure [manual 5-10].
+
+Return Value:
+
+   TRUE on success, FALSE on failure.
+
+--*/
+{
+   UCHAR numberOfBytes = sizeof(BT958ExtendedSetupInfo)-1;
+
+   PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
+   BusLogic_HostAdapter_T *HostAdapter = &(deviceExtension->hcs);
+   BusLogic_ExtendedSetupInformation_T ExtendedSetupInformation;
+   BusLogic_RequestedReplyLength_T RequestedReplyLength = sizeof(ExtendedSetupInformation);
+   BOOLEAN Result = TRUE;
+
+   BusLogic_WmiExtendedSetupInformation_T WmiExtendedSetupInfo;
+   PUCHAR SourceBuf = (PUCHAR) &WmiExtendedSetupInfo;
+
+      
+   //
+   //  Issue the Inquire Extended Setup Information command.  Only genuine
+   //  BusLogic Host Adapters and TRUE clones support this command.  Adaptec 1542C
+   //  series Host Adapters that respond to the Geometry Register I/O port will
+   //  fail this command.
+   RequestedReplyLength = sizeof(ExtendedSetupInformation);
+   if (BusLogic_Command(HostAdapter,
+                                          BusLogic_InquireExtendedSetupInformation,
+                                          &RequestedReplyLength,
+                                          sizeof(RequestedReplyLength),
+                                          &ExtendedSetupInformation,
+                                          sizeof(ExtendedSetupInformation))
+      != sizeof(ExtendedSetupInformation))
+   {
+     Result = FALSE;
+   }
+  
+   WmiExtendedSetupInfo.BusType      =            ExtendedSetupInformation.BusType;                                       
+   WmiExtendedSetupInfo.BIOS_Address =            ExtendedSetupInformation.BIOS_Address;                                      
+   WmiExtendedSetupInfo.ScatterGatherLimit =      ExtendedSetupInformation.ScatterGatherLimit; 
+   WmiExtendedSetupInfo.MailboxCount       =      ExtendedSetupInformation.MailboxCount;                                      
+   WmiExtendedSetupInfo.BaseMailboxAddress =      ExtendedSetupInformation.BaseMailboxAddress;
+   WmiExtendedSetupInfo.FastOnEISA         =      ExtendedSetupInformation.Misc.FastOnEISA;                                    
+   WmiExtendedSetupInfo.LevelSensitiveInterrupt = ExtendedSetupInformation.Misc.LevelSensitiveInterrupt;           
+   WmiExtendedSetupInfo.FirmwareRevision[3] =     ExtendedSetupInformation.FirmwareRevision[3];                    
+   WmiExtendedSetupInfo.FirmwareRevision[3] =     ExtendedSetupInformation.FirmwareRevision[3];                    
+   WmiExtendedSetupInfo.FirmwareRevision[3] =     ExtendedSetupInformation.FirmwareRevision[3];                    
+   WmiExtendedSetupInfo.HostWideSCSI        =     ExtendedSetupInformation.HostWideSCSI;                                   
+   WmiExtendedSetupInfo.HostDifferentialSCSI=     ExtendedSetupInformation.HostDifferentialSCSI;                       
+   WmiExtendedSetupInfo.HostSupportsSCAM    =     ExtendedSetupInformation.HostSupportsSCAM;                           
+   WmiExtendedSetupInfo.HostUltraSCSI       =     ExtendedSetupInformation.HostUltraSCSI;                              
+   WmiExtendedSetupInfo.HostSmartTermination=     ExtendedSetupInformation.HostSmartTermination;                       
+   
+   for (; numberOfBytes; numberOfBytes--)
+   {
+      *Buffer++ = *SourceBuf++;
+   }
+   return TRUE;
+}
+
index b710286..e62ac01 100644 (file)
@@ -1,6 +1,9 @@
 <directory name="atapi">
        <xi:include href="atapi/atapi.xml" />
 </directory>
+<directory name="buslogic">
+       <xi:include href="buslogic/buslogic.xml" />
+</directory>
 <directory name="cdrom">
        <xi:include href="cdrom/cdrom.xml" />
 </directory>