📄 aha154x.c
字号:
if ((ConfigInfo->MaximumTransferLength+1) == 0)
ConfigInfo->MaximumTransferLength = MAX_TRANSFER_SIZE;
//
// NumberOfPhysicalBreaks incorrectly defined.
// Must be set to MAX_SG_DESCRIPTORS.
//
if ((ConfigInfo->NumberOfPhysicalBreaks+1) == 0)
ConfigInfo->NumberOfPhysicalBreaks = MAX_SG_DESCRIPTORS;
//ConfigInfo->NumberOfPhysicalBreaks = MAX_SG_DESCRIPTORS - 1;
if (!ConfigInfo->ScatterGather)
ConfigInfo->ScatterGather = ScatterGatherSupported(HwDeviceExtension);
if (!ConfigInfo->ScatterGather) {
//ConfigInfo->NumberOfPhysicalBreaks = 1;
DebugPrint((1,"Aha154x: Scatter/Gather not supported!\n"));
}
ConfigInfo->Master = TRUE;
//
// 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);
return(SP_RETURN_ERROR);
}
//
// Convert virtual to physical mailbox address.
//
deviceExtension->NoncachedExtension->MailboxPA =
ScsiPortConvertPhysicalAddressToUlong(
ScsiPortGetPhysicalAddress(deviceExtension,
NULL,
deviceExtension->NoncachedExtension->Mbo,
&length));
//
// Set default bus on time. Then check for an override parameter.
//
deviceExtension->BusOnTime = 0x07;
if (ArgumentString != NULL) {
length = AhaParseArgumentString(ArgumentString, "BUSONTIME");
//
// Validate that the new bus on time is reasonable before attempting
// to set it.
//
if (length >= 2 && length <= 15) {
deviceExtension->BusOnTime = (UCHAR) length;
DebugPrint((1,"A154xFindAdapter: Setting bus on time: %ld\n", length));
}
}
//
// Set maximum cdb length to zero unless the user has overridden the value
//
if( ArgumentString != NULL) {
length = AhaParseArgumentString(ArgumentString, "MAXCDBLENGTH");
//
// Validate the maximum cdb length before attempting to set it
//
if (length >= 6 && length <= 20) {
deviceExtension->MaxCdbLength = (UCHAR) length;
DebugPrint((1, "A154xFindAdapter: Setting maximum cdb length: %ld\n", length));
}
} else {
GetHostAdapterBoardId(HwDeviceExtension,&hostAdapterId[0]);
if(hostAdapterId[BOARD_ID] < 'E') {
deviceExtension->MaxCdbLength = 10;
DebugPrint((1, "A154xFindAdapter: Old firmware - Setting maximum cdb length: %ld\n", length));
} else {
length = deviceExtension->MaxCdbLength = 0;
DebugPrint((1, "A154xFindAdapter: Setting maximum cdb length: %ld\n", length));
}
}
#if defined(_SCAM_ENABLED)
//
// Get info to determine if miniport must issues SCAM command.
//
DebugPrint((1,"A154x => Start SCAM enabled determination.", length));
deviceExtension->PerformScam = FALSE;
do {
//
// Fall through do loop if a command fails.
//
if (!WriteCommandRegister(deviceExtension,AC_ADAPTER_INQUIRY,FALSE)) {
break;
}
if ((ReadCommandRegister(deviceExtension,&BoardID,TRUE)) == FALSE) {
break;
}
//
// Don't care about three other bytes
//
for (i=0; i < 0x3; i++) {
if ((ReadCommandRegister(deviceExtension,&temp,TRUE)) == FALSE) {
break;
}
}
SpinForInterrupt(HwDeviceExtension,FALSE);
//
// Check to see that three 'extra bytes' were read.
//
if (i != 0x3)
break;
if (BoardID >= 'F') {
if (!WriteCommandRegister(deviceExtension,AC_RETURN_EEPROM,FALSE)) {
break;
}
//
// Flag Byte => set returns configured options
//
if (!WriteCommandRegister(deviceExtension,0x01,FALSE)) {
break;
}
//
// Data length => reading one byte.
//
if (!WriteCommandRegister(deviceExtension,0x01,FALSE)) {
break;
}
//
// Data offset => read SCSI_BUS_CONTROL_FLAG
//
if (!WriteCommandRegister(deviceExtension,SCSI_BUS_CONTROL_FLAG,FALSE)) {
break;
}
//
// Read it!
//
if ((ReadCommandRegister(deviceExtension,&EepromData,TRUE)) == FALSE) {
break;
}
SpinForInterrupt(HwDeviceExtension,FALSE);
//
// SCAM only if it's enabled in SCSISelect.
//
if (EepromData | SCAM_ENABLED) {
DebugPrint((1,"A154x => SCAM Enabled\n"));
deviceExtension->PerformScam = TRUE;
}
}
} while (FALSE);
#endif
DebugPrint((3,"A154xFindAdapter: Configuration completed\n"));
return SP_RETURN_FOUND;
} // end A154xFindAdapter()
BOOLEAN
A154xAdapterState(
IN PVOID HwDeviceExtension,
IN PVOID Context,
IN BOOLEAN SaveState
)
/*++
Routine Description:
This function is called after FindAdapter with SaveState set to TRUE,
inidicating that the adapter state should be saved. Before Chicago
exits, this function is again called with SaveState set to FALSE,
indicating the adapter should be restored to the same state it was
when this function was first called. By saving its real mode state
and restoring it during protected mode exit will give the adapter
a higher chance of working back in real mode.
Arguments:
HwDeviceExtension - HBA miniport driver's adapter data storage
Context - Register base address
SaveState - Flag to indicate whether to perform SAVE or RESTORE.
TRUE == SAVE, FALSE == RESTORE.
Return Value:
TRUE SAVE/RESTORE operation was successful.
--*/
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
UCHAR idx;
UCHAR cfgsz = sizeof(RM_CFG);
PRM_CFG SaveCfg;
deviceExtension = HwDeviceExtension;
SaveCfg = &deviceExtension->RMSaveState;
//
// SAVE real mode state
//
if (SaveState) {
//
// Read off config data from AHA154X...
//
if (!WriteCommandRegister(deviceExtension, AC_RETURN_SETUP_DATA, TRUE))
return FALSE;
if (!WriteDataRegister(deviceExtension, cfgsz))
return FALSE;
for (idx=0;idx<cfgsz;idx++) {
if (!(ReadCommandRegister(HwDeviceExtension,(PUCHAR)(SaveCfg),TRUE)))
return FALSE;
((PUCHAR)SaveCfg)++;
}
//
// ...and wait for interrupt
//
if (!SpinForInterrupt(deviceExtension,TRUE))
return FALSE;
//
// RESTORE state to real mode
//
} else {
//
// If mailbox count was not zero, re-initialize mailbox addresses
// saved from real mode
//
if (SaveCfg->NumMailBoxes) {
if (!WriteCommandRegister(deviceExtension, AC_MAILBOX_INITIALIZATION, TRUE))
return FALSE;
if (!WriteDataRegister(deviceExtension, SaveCfg->NumMailBoxes))
return FALSE;
if (!WriteDataRegister(deviceExtension, SaveCfg->MBAddrHiByte))
return FALSE;
if (!WriteDataRegister(deviceExtension, SaveCfg->MBAddrMiByte))
return FALSE;
if (!WriteDataRegister(deviceExtension, SaveCfg->MBAddrLoByte))
return FALSE;
//
// ... and wait for interrupt.
//
if (!SpinForInterrupt(deviceExtension,TRUE))
return FALSE;
}
//
// Restore transfer speed gotten from real mode...
//
if (!WriteCommandRegister(deviceExtension, AC_SET_TRANSFER_SPEED, TRUE))
return FALSE;
if (!WriteDataRegister(deviceExtension, SaveCfg->TxSpeed))
return FALSE;
//
// ... and wait for interrupt.
//
if (!SpinForInterrupt(deviceExtension,TRUE))
return FALSE;
//
// Restore setting for bus on time from real mode...
//
if (!WriteCommandRegister(deviceExtension, AC_SET_BUS_ON_TIME, TRUE))
return FALSE;
if (!WriteDataRegister(deviceExtension, SaveCfg->BusOnTime))
return FALSE;
//
// ...and wait for interrupt
//
if (!SpinForInterrupt(deviceExtension,TRUE))
return FALSE;
//
// Restore setting for bus off time from real mode...
//
if (!WriteCommandRegister(deviceExtension, AC_SET_BUS_OFF_TIME, TRUE))
return FALSE;
if (!WriteDataRegister(deviceExtension, SaveCfg->BusOffTime))
return FALSE;
//
// ...and wait for interrupt
//
if (!SpinForInterrupt(deviceExtension,TRUE))
return FALSE;
//
// Reset any pending interrupts
//
ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_INTERRUPT_RESET);
}
return TRUE;
} // end A154xAdapterState()
SCSI_ADAPTER_CONTROL_STATUS
A154xAdapterControl(
IN PVOID HwDeviceExtension,
IN SCSI_ADAPTER_CONTROL_TYPE ControlType,
IN PVOID Parameters
)
/*++
Routine Description:
This routine is called at various time's by SCSIPort and is used
to provide a control function over the adapter. Most commonly, NT
uses this entry point to control the power state of the HBA during
a hibernation operation.
Arguments:
HwDeviceExtension - HBA miniport driver's per adapter storage
Parameters - This varies by control type, see below.
ControlType - Indicates which adapter control function should be
executed. Conrol Types are detailed below.
Return Value:
ScsiAdapterControlSuccess - requested ControlType completed successfully
ScsiAdapterControlUnsuccessful - requested ControlType failed
--*/
{
PHW_DEVICE_EXTENSION deviceExtension = HwDeviceExtension;
PBASE_REGISTER baseIoAddress = deviceExtension->BaseIoAddress;
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[A154X_TYPE_MAX] = {
TRUE, // ScsiQuerySupportedControlTypes
TRUE, // ScsiStopAdapter
TRUE, // ScsiRestartAdapter
FALSE, // ScsiSetBootConfig
FALSE // ScsiSetRunningConfig
};
//
// Execute the correct code path based on ControlType
//
switch (ControlType) {
case ScsiQuerySupportedControlTypes:
//
// 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 < A154X_TYPE_MAX) ?
ControlTypeList->MaxControlType :
A154X_TYPE_MAX;
for (Index = 0; Index < AdjustedMaxControlType; Index++) {
ControlTypeList->SupportedTypeList[Index] =
SupportedConrolTypes[Index];
}
break;
case ScsiStopAdapter:
//
// This entry point is called by SCSIPort when it needs to stop/disable
// the HBA. Parameters is a pointer to the HBA's HwDeviceExtension. The adapter
// has already been quiesced by SCSIPort (i.e. no outstanding SRBs). Hence the adapter
// should abort/complete any internally generated commands, disable adapter interrupts
// and optionally power down the adapter.
//
//
// Before we stop the adapter, we need to save the adapter's state
// information for reinitialization purposes. For this adpater the
// HwSaveState entry point will suffice.
//
if (A154xAdapterState(HwDeviceExtension, NULL, TRUE) == FALSE) {
//
// Adapter is unable to save it's state information, we must fail this
// request since the process of restarting the adapter will not succeed.
//
return ScsiAdapterControlUnsuccessful;
}
//
// It is not possible to disable interrupts on the 1540 series of cards. The alternative is to
// reset the adapter, clear any remaining interrupts and return success. If it is impossible to
// queiese the interrupt line, we may not honor the request to stop the adapter. It should be
// noted that while this solution is not perfect, the typical usage of the 1540 series of adapters
// renders the likelihood of asyncnronous interrupts nil.
//
Retries = 0x0;
do {
//
// Reset the adapter
//
ScsiPortWritePortUchar(&baseIoAddress->StatusRegister, IOP_HARD_RESET);
//
// Wait for idle with timeout (500ms timer)
//
for (Index = 0; Index < 500000; Index++) {
if (ScsiPortReadPortUchar(&baseIoAddress->StatusRegister) & IOP_SCSI_HBA_IDLE) {
//
// Upon reaching this point, the adapter has been reset and idled. If there are no interrupts
// pending, we can leave having given ourselves the greatest level of assurance that no
// future interrupts await.
//
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -