📄 aha154x.c
字号:
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
aha154x.c
Abstract:
This is the port driver for the Adaptec 1540B SCSI Adapter.
Author:
Mike Glass
Tuong Hoang (Adaptec)
Renato Maranon (Adaptec)
Bill Williams (Adaptec)
Environment:
kernel mode only
Notes:
Revision History:
--*/
#include "miniport.h"
#include "aha154x.h" // includes scsi.h
VOID
ScsiPortZeroMemory(
IN PVOID Destination,
IN ULONG Length
);
//
// This conditionally compiles in the code to force the DMA transfer speed
// to 5.0.
//
#define FORCE_DMA_SPEED 1
//
// Function declarations
//
// Functions that start with 'A154x' are entry points
// for the OS port driver.
//
ULONG
DriverEntry(
IN PVOID DriverObject,
IN PVOID Argument2
);
ULONG
A154xDetermineInstalled(
IN PHW_DEVICE_EXTENSION HwDeviceExtension,
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
IN OUT PSCAN_CONTEXT Context,
OUT PBOOLEAN Again
);
VOID
A154xClaimBIOSSpace(
IN PHW_DEVICE_EXTENSION HwDeviceExtension,
IN PBASE_REGISTER baseIoAddress,
IN PSCAN_CONTEXT Context,
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
);
ULONG
A154xFindAdapter(
IN PVOID HwDeviceExtension,
IN PSCAN_CONTEXT Context,
IN PVOID BusInformation,
IN PCHAR ArgumentString,
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
OUT PBOOLEAN Again
);
BOOLEAN
A154xAdapterState(
IN PVOID HwDeviceExtension,
IN PVOID Context,
IN BOOLEAN SaveState
);
BOOLEAN
A154xHwInitialize(
IN PVOID DeviceExtension
);
#if defined(_SCAM_ENABLED)
//
// Issues SCAM command to HA
//
BOOLEAN
PerformScamProtocol(
IN PHW_DEVICE_EXTENSION DeviceExtension
);
#endif
BOOLEAN
A154xStartIo(
IN PVOID DeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb
);
BOOLEAN
A154xInterrupt(
IN PVOID DeviceExtension
);
BOOLEAN
A154xResetBus(
IN PVOID HwDeviceExtension,
IN ULONG PathId
);
SCSI_ADAPTER_CONTROL_STATUS
A154xAdapterControl(
IN PVOID HwDeviceExtension,
IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
IN PVOID Parameters
);
BOOLEAN
GetHostAdapterBoardId (
IN PVOID HwDeviceExtension,
OUT PUCHAR BoardId
);
//
// This function is called from A154xStartIo.
//
VOID
BuildCcb(
IN PHW_DEVICE_EXTENSION DeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb
);
//
// This function is called from BuildCcb.
//
VOID
BuildSdl(
IN PHW_DEVICE_EXTENSION DeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb
);
//
// This function is called from A154xInitialize.
//
BOOLEAN
AdapterPresent(
IN PVOID HwDeviceExtension
);
//
// This function is called from A154xInterrupt.
//
UCHAR
MapError(
IN PVOID HwDeviceExtension,
IN PSCSI_REQUEST_BLOCK Srb,
IN PCCB Ccb
);
BOOLEAN
ScatterGatherSupported (
IN PHW_DEVICE_EXTENSION HwDeviceExtension
);
BOOLEAN SendUnlockCommand(
IN PVOID HwDeviceExtension,
IN UCHAR locktype
);
BOOLEAN UnlockMailBoxes(
IN PVOID HwDeviceExtension
);
ULONG
AhaParseArgumentString(
IN PCHAR String,
IN PCHAR KeyWord
);
//
// This function determines whether adapter is an AMI
//
BOOLEAN
A4448IsAmi(
IN PHW_DEVICE_EXTENSION HwDeviceExtension,
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
ULONG portNumber
);
ULONG
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;
SCAN_CONTEXT context;
ULONG isaStatus;
ULONG mcaStatus;
ULONG i;
DebugPrint((1,"\n\nSCSI Adaptec 154X MiniPort Driver\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 = A154xHwInitialize;
hwInitializationData.HwResetBus = A154xResetBus;
hwInitializationData.HwStartIo = A154xStartIo;
hwInitializationData.HwInterrupt = A154xInterrupt;
hwInitializationData.HwFindAdapter = A154xFindAdapter;
hwInitializationData.HwAdapterState = A154xAdapterState;
hwInitializationData.HwAdapterControl = A154xAdapterControl;
//
// Indicate no buffer mapping but will need physical addresses.
//
hwInitializationData.NeedPhysicalAddresses = TRUE;
//
// Specify size of extensions.
//
hwInitializationData.DeviceExtensionSize = sizeof(HW_DEVICE_EXTENSION);
hwInitializationData.SpecificLuExtensionSize = sizeof(HW_LU_EXTENSION);
//
// Specifiy the bus type.
//
hwInitializationData.AdapterInterfaceType = Isa;
hwInitializationData.NumberOfAccessRanges = 2;
//
// Ask for SRB extensions for CCBs.
//
hwInitializationData.SrbExtensionSize = sizeof(CCB);
//
// The adapter count is used by the find adapter routine to track how
// which adapter addresses have been tested.
//
context.adapterCount = 0;
context.biosScanStart = 0;
isaStatus = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, &context);
//
// Now try to configure for the Mca bus.
// Specifiy the bus type.
//
hwInitializationData.AdapterInterfaceType = MicroChannel;
context.adapterCount = 0;
context.biosScanStart = 0;
mcaStatus = ScsiPortInitialize(DriverObject, Argument2, &hwInitializationData, &context);
//
// Return the smaller status.
//
return(mcaStatus < isaStatus ? mcaStatus : isaStatus);
} // end A154xEntry()
ULONG
A154xFindAdapter(
IN PVOID HwDeviceExtension,
IN PSCAN_CONTEXT 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:
ULONG
--*/
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
ULONG length;
ULONG status;
UCHAR adapterTid;
UCHAR dmaChannel;
UCHAR irq;
UCHAR bit;
UCHAR hostAdapterId[4];
#if defined(_SCAM_ENABLED)
UCHAR temp, i;
UCHAR BoardID;
UCHAR EepromData;
#endif
//
// Inform SCSIPORT that we are a WMI data provider and have we GUIDs
// to register.
//
ConfigInfo->WmiDataProvider = TRUE;
A154xWmiInitialize(deviceExtension);
//
// Determine if there are any adapters installed. Determine installed
// will initialize the BaseIoAddress if an adapter is found.
//
status = A154xDetermineInstalled(deviceExtension,
ConfigInfo,
Context,
Again);
//
// If there are no adapters found then return.
//
if (status != SP_RETURN_FOUND) {
return(status);
}
//
// Issue adapter command to get IRQ, DMA channel, and adapter SCSI ID.
// But first, check for PnP non-default values. If any of these values
// are default, then we do 'em all to save code space, since the same
// command is used.
//
// Returns 3 data bytes:
//
// Byte 0 Dma Channel
//
// Byte 1 Interrupt Channel
//
// Byte 2 Adapter SCSI ID
//
if (((ConfigInfo->DmaChannel+1) == 0) || // default DMA channel ?
(ConfigInfo->BusInterruptLevel == 0) || // default IRQ ?
((ConfigInfo->InitiatorBusId[0]+1) == 0) // default adapter ID ?
) {
if (!WriteCommandRegister(deviceExtension, AC_RET_CONFIGURATION_DATA, TRUE)) {
DebugPrint((1,"A154xFindAdapter: Get configuration data command failed\n"));
return SP_RETURN_ERROR;
}
//
// Determine DMA channel.
//
if (!ReadCommandRegister(deviceExtension,&dmaChannel,TRUE)) {
DebugPrint((1,"A154xFindAdapter: Can't read dma channel\n"));
return SP_RETURN_ERROR;
}
if (ConfigInfo->AdapterInterfaceType != MicroChannel) {
WHICH_BIT(dmaChannel,bit);
ConfigInfo->DmaChannel = bit;
DebugPrint((2,"A154xFindAdapter: DMA channel is %x\n",
ConfigInfo->DmaChannel));
} else {
ConfigInfo->InterruptMode = LevelSensitive;
}
//
// Determine hardware interrupt vector.
//
if (!ReadCommandRegister(deviceExtension,&irq,TRUE)) {
DebugPrint((1,"A154xFindAdapter: Can't read adapter irq\n"));
return SP_RETURN_ERROR;
}
WHICH_BIT(irq, bit);
ConfigInfo->BusInterruptLevel = (UCHAR) 9 + bit;
//
// Determine what SCSI bus id the adapter is on.
//
if (!ReadCommandRegister(deviceExtension,&adapterTid,TRUE)) {
DebugPrint((1,"A154xFindAdapter: Can't read adapter SCSI id\n"));
return SP_RETURN_ERROR;
}
//
// Wait for HACC interrupt.
//
SpinForInterrupt(deviceExtension,FALSE); // eddy
//
// Use PnP fields
//
} else {
adapterTid = ConfigInfo->InitiatorBusId[0];
}
//
// Set number of buses.
//
ConfigInfo->NumberOfBuses = 1;
ConfigInfo->InitiatorBusId[0] = adapterTid;
deviceExtension->HostTargetId = adapterTid;
//
// Set default CCB command to scatter/gather with residual counts.
// If the adapter rejects this command, then set the command
// to scatter/gather without residual.
//
deviceExtension->CcbScatterGatherCommand = SCATTER_GATHER_COMMAND;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -