/*
 * 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.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

//_________________________________________________________________________________________
//
// File description :The header file the driver for BusLogic-958 SCSI Host adapter card.
// The technical reference 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

#pragma once

#include <ntddk.h>
#include <srb.h>
#include <scsi.h>
#include <ntddscsi.h>
#include <scsiwmi.h>
//#include <ntos/kefuncs.h>


//#include "miniport.h"
//#include "scsi.h"
//#include "scsiwmi.h"
//_________________________________________________________________________________________
// #defines
//_________________________________________________________________________________________

// Debug levels
#define ERROR   1
#define WARNING 2
#define TRACE   3
#define INFO    4

// 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 mechanism 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 declarations
//_________________________________________________________________________________________
ULONG
NTAPI
DriverEntry(IN PVOID DriverObject,
            IN PVOID Argument2
            );

ULONG
NTAPI
BT958HwFindAdapter(IN PVOID HwDeviceExtension,
                   IN PVOID Context,
                   IN PVOID BusInformation,
                   IN PCHAR ArgumentString,
                   IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
                   OUT PBOOLEAN Again
                  );

BOOLEAN
NTAPI
BT958HwInitialize(IN PVOID HwDeviceExtension);

BOOLEAN
NTAPI
BT958HwStartIO(IN PVOID HwDeviceExtension,
               IN PSCSI_REQUEST_BLOCK Srb
              );

BOOLEAN
NTAPI
BT958HwInterrupt(IN PVOID HwDeviceExtension);

BOOLEAN
NTAPI
BT958HwResetBus(IN PVOID HwDeviceExtension,
                IN ULONG PathId
               );

SCSI_ADAPTER_CONTROL_STATUS
NTAPI
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);

static UCHAR
ReadBusLogicPort(PUCHAR adr )
{
    return ScsiPortReadPortUchar( adr );
}

static VOID
WriteBusLogicPort(UCHAR data,
                  PUCHAR adr)
{
    ScsiPortWritePortUchar(adr, data);
}

//_________________________________________________________________________________________
// Declarations for the device registers and reading 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;

static 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);
}

static 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);
}

static 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);
}

static UCHAR
BusLogic_ReadStatusRegister(BusLogic_HostAdapter_T *HostAdapter)
{
  return ReadBusLogicPort(HostAdapter->IO_Address + BusLogic_StatusRegisterOffset);
}

static UCHAR
BusLogic_ReadInterruptRegister(BusLogic_HostAdapter_T *HostAdapter)
{
  return ReadBusLogicPort(HostAdapter->IO_Address + BusLogic_InterruptRegisterOffset);
}

static UCHAR
BusLogic_ReadGeometryRegister(BusLogic_HostAdapter_T *HostAdapter)
{
  return ReadBusLogicPort(HostAdapter->IO_Address + BusLogic_GeometryRegisterOffset);
}

static UCHAR
BusLogic_ReadDataInRegister(BusLogic_HostAdapter_T *HostAdapter)
{
  return ReadBusLogicPort(HostAdapter->IO_Address + BusLogic_DataInRegisterOffset);
}

static 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.
static 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.
static 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.
static 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.
static void
BusLogic_IncrementErrorCounter(unsigned short *ErrorCounter)
{
  if (*ErrorCounter < 65535) (*ErrorCounter)++;
}
//____________________________________________________________________________________________