in drivers/block/DAC960.c [3540:4335]
static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
{
DAC960_Controller_T *Controller = Command->Controller;
DAC960_CommandType_T CommandType = Command->CommandType;
DAC960_V1_CommandOpcode_T CommandOpcode =
Command->V1.CommandMailbox.Common.CommandOpcode;
DAC960_V1_CommandStatus_T CommandStatus = Command->V1.CommandStatus;
if (CommandType == DAC960_ReadCommand ||
CommandType == DAC960_WriteCommand)
{
#ifdef FORCE_RETRY_DEBUG
CommandStatus = DAC960_V1_IrrecoverableDataError;
#endif
if (CommandStatus == DAC960_V1_NormalCompletion) {
if (!DAC960_ProcessCompletedRequest(Command, true))
BUG();
} else if (CommandStatus == DAC960_V1_IrrecoverableDataError ||
CommandStatus == DAC960_V1_BadDataEncountered)
{
/*
* break the command down into pieces and resubmit each
* piece, hoping that some of them will succeed.
*/
DAC960_queue_partial_rw(Command);
return;
}
else
{
if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline)
DAC960_V1_ReadWriteError(Command);
if (!DAC960_ProcessCompletedRequest(Command, false))
BUG();
}
}
else if (CommandType == DAC960_ReadRetryCommand ||
CommandType == DAC960_WriteRetryCommand)
{
bool normal_completion;
#ifdef FORCE_RETRY_FAILURE_DEBUG
static int retry_count = 1;
#endif
/*
Perform completion processing for the portion that was
retried, and submit the next portion, if any.
*/
normal_completion = true;
if (CommandStatus != DAC960_V1_NormalCompletion) {
normal_completion = false;
if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline)
DAC960_V1_ReadWriteError(Command);
}
#ifdef FORCE_RETRY_FAILURE_DEBUG
if (!(++retry_count % 10000)) {
printk("V1 error retry failure test\n");
normal_completion = false;
DAC960_V1_ReadWriteError(Command);
}
#endif
if (!DAC960_ProcessCompletedRequest(Command, normal_completion)) {
DAC960_queue_partial_rw(Command);
return;
}
}
else if (CommandType == DAC960_MonitoringCommand)
{
if (Controller->ShutdownMonitoringTimer)
return;
if (CommandOpcode == DAC960_V1_Enquiry)
{
DAC960_V1_Enquiry_T *OldEnquiry = &Controller->V1.Enquiry;
DAC960_V1_Enquiry_T *NewEnquiry = Controller->V1.NewEnquiry;
unsigned int OldCriticalLogicalDriveCount =
OldEnquiry->CriticalLogicalDriveCount;
unsigned int NewCriticalLogicalDriveCount =
NewEnquiry->CriticalLogicalDriveCount;
if (NewEnquiry->NumberOfLogicalDrives > Controller->LogicalDriveCount)
{
int LogicalDriveNumber = Controller->LogicalDriveCount - 1;
while (++LogicalDriveNumber < NewEnquiry->NumberOfLogicalDrives)
DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
"Now Exists\n", Controller,
LogicalDriveNumber,
Controller->ControllerNumber,
LogicalDriveNumber);
Controller->LogicalDriveCount = NewEnquiry->NumberOfLogicalDrives;
DAC960_ComputeGenericDiskInfo(Controller);
}
if (NewEnquiry->NumberOfLogicalDrives < Controller->LogicalDriveCount)
{
int LogicalDriveNumber = NewEnquiry->NumberOfLogicalDrives - 1;
while (++LogicalDriveNumber < Controller->LogicalDriveCount)
DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
"No Longer Exists\n", Controller,
LogicalDriveNumber,
Controller->ControllerNumber,
LogicalDriveNumber);
Controller->LogicalDriveCount = NewEnquiry->NumberOfLogicalDrives;
DAC960_ComputeGenericDiskInfo(Controller);
}
if (NewEnquiry->StatusFlags.DeferredWriteError !=
OldEnquiry->StatusFlags.DeferredWriteError)
DAC960_Critical("Deferred Write Error Flag is now %s\n", Controller,
(NewEnquiry->StatusFlags.DeferredWriteError
? "TRUE" : "FALSE"));
if ((NewCriticalLogicalDriveCount > 0 ||
NewCriticalLogicalDriveCount != OldCriticalLogicalDriveCount) ||
(NewEnquiry->OfflineLogicalDriveCount > 0 ||
NewEnquiry->OfflineLogicalDriveCount !=
OldEnquiry->OfflineLogicalDriveCount) ||
(NewEnquiry->DeadDriveCount > 0 ||
NewEnquiry->DeadDriveCount !=
OldEnquiry->DeadDriveCount) ||
(NewEnquiry->EventLogSequenceNumber !=
OldEnquiry->EventLogSequenceNumber) ||
Controller->MonitoringTimerCount == 0 ||
time_after_eq(jiffies, Controller->SecondaryMonitoringTime
+ DAC960_SecondaryMonitoringInterval))
{
Controller->V1.NeedLogicalDriveInformation = true;
Controller->V1.NewEventLogSequenceNumber =
NewEnquiry->EventLogSequenceNumber;
Controller->V1.NeedErrorTableInformation = true;
Controller->V1.NeedDeviceStateInformation = true;
Controller->V1.StartDeviceStateScan = true;
Controller->V1.NeedBackgroundInitializationStatus =
Controller->V1.BackgroundInitializationStatusSupported;
Controller->SecondaryMonitoringTime = jiffies;
}
if (NewEnquiry->RebuildFlag == DAC960_V1_StandbyRebuildInProgress ||
NewEnquiry->RebuildFlag
== DAC960_V1_BackgroundRebuildInProgress ||
OldEnquiry->RebuildFlag == DAC960_V1_StandbyRebuildInProgress ||
OldEnquiry->RebuildFlag == DAC960_V1_BackgroundRebuildInProgress)
{
Controller->V1.NeedRebuildProgress = true;
Controller->V1.RebuildProgressFirst =
(NewEnquiry->CriticalLogicalDriveCount <
OldEnquiry->CriticalLogicalDriveCount);
}
if (OldEnquiry->RebuildFlag == DAC960_V1_BackgroundCheckInProgress)
switch (NewEnquiry->RebuildFlag)
{
case DAC960_V1_NoStandbyRebuildOrCheckInProgress:
DAC960_Progress("Consistency Check Completed Successfully\n",
Controller);
break;
case DAC960_V1_StandbyRebuildInProgress:
case DAC960_V1_BackgroundRebuildInProgress:
break;
case DAC960_V1_BackgroundCheckInProgress:
Controller->V1.NeedConsistencyCheckProgress = true;
break;
case DAC960_V1_StandbyRebuildCompletedWithError:
DAC960_Progress("Consistency Check Completed with Error\n",
Controller);
break;
case DAC960_V1_BackgroundRebuildOrCheckFailed_DriveFailed:
DAC960_Progress("Consistency Check Failed - "
"Physical Device Failed\n", Controller);
break;
case DAC960_V1_BackgroundRebuildOrCheckFailed_LogicalDriveFailed:
DAC960_Progress("Consistency Check Failed - "
"Logical Drive Failed\n", Controller);
break;
case DAC960_V1_BackgroundRebuildOrCheckFailed_OtherCauses:
DAC960_Progress("Consistency Check Failed - Other Causes\n",
Controller);
break;
case DAC960_V1_BackgroundRebuildOrCheckSuccessfullyTerminated:
DAC960_Progress("Consistency Check Successfully Terminated\n",
Controller);
break;
}
else if (NewEnquiry->RebuildFlag
== DAC960_V1_BackgroundCheckInProgress)
Controller->V1.NeedConsistencyCheckProgress = true;
Controller->MonitoringAlertMode =
(NewEnquiry->CriticalLogicalDriveCount > 0 ||
NewEnquiry->OfflineLogicalDriveCount > 0 ||
NewEnquiry->DeadDriveCount > 0);
if (NewEnquiry->RebuildFlag > DAC960_V1_BackgroundCheckInProgress)
{
Controller->V1.PendingRebuildFlag = NewEnquiry->RebuildFlag;
Controller->V1.RebuildFlagPending = true;
}
memcpy(&Controller->V1.Enquiry, &Controller->V1.NewEnquiry,
sizeof(DAC960_V1_Enquiry_T));
}
else if (CommandOpcode == DAC960_V1_PerformEventLogOperation)
{
static char
*DAC960_EventMessages[] =
{ "killed because write recovery failed",
"killed because of SCSI bus reset failure",
"killed because of double check condition",
"killed because it was removed",
"killed because of gross error on SCSI chip",
"killed because of bad tag returned from drive",
"killed because of timeout on SCSI command",
"killed because of reset SCSI command issued from system",
"killed because busy or parity error count exceeded limit",
"killed because of 'kill drive' command from system",
"killed because of selection timeout",
"killed due to SCSI phase sequence error",
"killed due to unknown status" };
DAC960_V1_EventLogEntry_T *EventLogEntry =
Controller->V1.EventLogEntry;
if (EventLogEntry->SequenceNumber ==
Controller->V1.OldEventLogSequenceNumber)
{
unsigned char SenseKey = EventLogEntry->SenseKey;
unsigned char AdditionalSenseCode =
EventLogEntry->AdditionalSenseCode;
unsigned char AdditionalSenseCodeQualifier =
EventLogEntry->AdditionalSenseCodeQualifier;
if (SenseKey == DAC960_SenseKey_VendorSpecific &&
AdditionalSenseCode == 0x80 &&
AdditionalSenseCodeQualifier <
ARRAY_SIZE(DAC960_EventMessages))
DAC960_Critical("Physical Device %d:%d %s\n", Controller,
EventLogEntry->Channel,
EventLogEntry->TargetID,
DAC960_EventMessages[
AdditionalSenseCodeQualifier]);
else if (SenseKey == DAC960_SenseKey_UnitAttention &&
AdditionalSenseCode == 0x29)
{
if (Controller->MonitoringTimerCount > 0)
Controller->V1.DeviceResetCount[EventLogEntry->Channel]
[EventLogEntry->TargetID]++;
}
else if (!(SenseKey == DAC960_SenseKey_NoSense ||
(SenseKey == DAC960_SenseKey_NotReady &&
AdditionalSenseCode == 0x04 &&
(AdditionalSenseCodeQualifier == 0x01 ||
AdditionalSenseCodeQualifier == 0x02))))
{
DAC960_Critical("Physical Device %d:%d Error Log: "
"Sense Key = %X, ASC = %02X, ASCQ = %02X\n",
Controller,
EventLogEntry->Channel,
EventLogEntry->TargetID,
SenseKey,
AdditionalSenseCode,
AdditionalSenseCodeQualifier);
DAC960_Critical("Physical Device %d:%d Error Log: "
"Information = %02X%02X%02X%02X "
"%02X%02X%02X%02X\n",
Controller,
EventLogEntry->Channel,
EventLogEntry->TargetID,
EventLogEntry->Information[0],
EventLogEntry->Information[1],
EventLogEntry->Information[2],
EventLogEntry->Information[3],
EventLogEntry->CommandSpecificInformation[0],
EventLogEntry->CommandSpecificInformation[1],
EventLogEntry->CommandSpecificInformation[2],
EventLogEntry->CommandSpecificInformation[3]);
}
}
Controller->V1.OldEventLogSequenceNumber++;
}
else if (CommandOpcode == DAC960_V1_GetErrorTable)
{
DAC960_V1_ErrorTable_T *OldErrorTable = &Controller->V1.ErrorTable;
DAC960_V1_ErrorTable_T *NewErrorTable = Controller->V1.NewErrorTable;
int Channel, TargetID;
for (Channel = 0; Channel < Controller->Channels; Channel++)
for (TargetID = 0; TargetID < Controller->Targets; TargetID++)
{
DAC960_V1_ErrorTableEntry_T *NewErrorEntry =
&NewErrorTable->ErrorTableEntries[Channel][TargetID];
DAC960_V1_ErrorTableEntry_T *OldErrorEntry =
&OldErrorTable->ErrorTableEntries[Channel][TargetID];
if ((NewErrorEntry->ParityErrorCount !=
OldErrorEntry->ParityErrorCount) ||
(NewErrorEntry->SoftErrorCount !=
OldErrorEntry->SoftErrorCount) ||
(NewErrorEntry->HardErrorCount !=
OldErrorEntry->HardErrorCount) ||
(NewErrorEntry->MiscErrorCount !=
OldErrorEntry->MiscErrorCount))
DAC960_Critical("Physical Device %d:%d Errors: "
"Parity = %d, Soft = %d, "
"Hard = %d, Misc = %d\n",
Controller, Channel, TargetID,
NewErrorEntry->ParityErrorCount,
NewErrorEntry->SoftErrorCount,
NewErrorEntry->HardErrorCount,
NewErrorEntry->MiscErrorCount);
}
memcpy(&Controller->V1.ErrorTable, Controller->V1.NewErrorTable,
sizeof(DAC960_V1_ErrorTable_T));
}
else if (CommandOpcode == DAC960_V1_GetDeviceState)
{
DAC960_V1_DeviceState_T *OldDeviceState =
&Controller->V1.DeviceState[Controller->V1.DeviceStateChannel]
[Controller->V1.DeviceStateTargetID];
DAC960_V1_DeviceState_T *NewDeviceState =
Controller->V1.NewDeviceState;
if (NewDeviceState->DeviceState != OldDeviceState->DeviceState)
DAC960_Critical("Physical Device %d:%d is now %s\n", Controller,
Controller->V1.DeviceStateChannel,
Controller->V1.DeviceStateTargetID,
(NewDeviceState->DeviceState
== DAC960_V1_Device_Dead
? "DEAD"
: NewDeviceState->DeviceState
== DAC960_V1_Device_WriteOnly
? "WRITE-ONLY"
: NewDeviceState->DeviceState
== DAC960_V1_Device_Online
? "ONLINE" : "STANDBY"));
if (OldDeviceState->DeviceState == DAC960_V1_Device_Dead &&
NewDeviceState->DeviceState != DAC960_V1_Device_Dead)
{
Controller->V1.NeedDeviceInquiryInformation = true;
Controller->V1.NeedDeviceSerialNumberInformation = true;
Controller->V1.DeviceResetCount
[Controller->V1.DeviceStateChannel]
[Controller->V1.DeviceStateTargetID] = 0;
}
memcpy(OldDeviceState, NewDeviceState,
sizeof(DAC960_V1_DeviceState_T));
}
else if (CommandOpcode == DAC960_V1_GetLogicalDriveInformation)
{
int LogicalDriveNumber;
for (LogicalDriveNumber = 0;
LogicalDriveNumber < Controller->LogicalDriveCount;
LogicalDriveNumber++)
{
DAC960_V1_LogicalDriveInformation_T *OldLogicalDriveInformation =
&Controller->V1.LogicalDriveInformation[LogicalDriveNumber];
DAC960_V1_LogicalDriveInformation_T *NewLogicalDriveInformation =
&(*Controller->V1.NewLogicalDriveInformation)[LogicalDriveNumber];
if (NewLogicalDriveInformation->LogicalDriveState !=
OldLogicalDriveInformation->LogicalDriveState)
DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
"is now %s\n", Controller,
LogicalDriveNumber,
Controller->ControllerNumber,
LogicalDriveNumber,
(NewLogicalDriveInformation->LogicalDriveState
== DAC960_V1_LogicalDrive_Online
? "ONLINE"
: NewLogicalDriveInformation->LogicalDriveState
== DAC960_V1_LogicalDrive_Critical
? "CRITICAL" : "OFFLINE"));
if (NewLogicalDriveInformation->WriteBack !=
OldLogicalDriveInformation->WriteBack)
DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
"is now %s\n", Controller,
LogicalDriveNumber,
Controller->ControllerNumber,
LogicalDriveNumber,
(NewLogicalDriveInformation->WriteBack
? "WRITE BACK" : "WRITE THRU"));
}
memcpy(&Controller->V1.LogicalDriveInformation,
Controller->V1.NewLogicalDriveInformation,
sizeof(DAC960_V1_LogicalDriveInformationArray_T));
}
else if (CommandOpcode == DAC960_V1_GetRebuildProgress)
{
unsigned int LogicalDriveNumber =
Controller->V1.RebuildProgress->LogicalDriveNumber;
unsigned int LogicalDriveSize =
Controller->V1.RebuildProgress->LogicalDriveSize;
unsigned int BlocksCompleted =
LogicalDriveSize - Controller->V1.RebuildProgress->RemainingBlocks;
if (CommandStatus == DAC960_V1_NoRebuildOrCheckInProgress &&
Controller->V1.LastRebuildStatus == DAC960_V1_NormalCompletion)
CommandStatus = DAC960_V1_RebuildSuccessful;
switch (CommandStatus)
{
case DAC960_V1_NormalCompletion:
Controller->EphemeralProgressMessage = true;
DAC960_Progress("Rebuild in Progress: "
"Logical Drive %d (/dev/rd/c%dd%d) "
"%d%% completed\n",
Controller, LogicalDriveNumber,
Controller->ControllerNumber,
LogicalDriveNumber,
(100 * (BlocksCompleted >> 7))
/ (LogicalDriveSize >> 7));
Controller->EphemeralProgressMessage = false;
break;
case DAC960_V1_RebuildFailed_LogicalDriveFailure:
DAC960_Progress("Rebuild Failed due to "
"Logical Drive Failure\n", Controller);
break;
case DAC960_V1_RebuildFailed_BadBlocksOnOther:
DAC960_Progress("Rebuild Failed due to "
"Bad Blocks on Other Drives\n", Controller);
break;
case DAC960_V1_RebuildFailed_NewDriveFailed:
DAC960_Progress("Rebuild Failed due to "
"Failure of Drive Being Rebuilt\n", Controller);
break;
case DAC960_V1_NoRebuildOrCheckInProgress:
break;
case DAC960_V1_RebuildSuccessful:
DAC960_Progress("Rebuild Completed Successfully\n", Controller);
break;
case DAC960_V1_RebuildSuccessfullyTerminated:
DAC960_Progress("Rebuild Successfully Terminated\n", Controller);
break;
}
Controller->V1.LastRebuildStatus = CommandStatus;
if (CommandType != DAC960_MonitoringCommand &&
Controller->V1.RebuildStatusPending)
{
Command->V1.CommandStatus = Controller->V1.PendingRebuildStatus;
Controller->V1.RebuildStatusPending = false;
}
else if (CommandType == DAC960_MonitoringCommand &&
CommandStatus != DAC960_V1_NormalCompletion &&
CommandStatus != DAC960_V1_NoRebuildOrCheckInProgress)
{
Controller->V1.PendingRebuildStatus = CommandStatus;
Controller->V1.RebuildStatusPending = true;
}
}
else if (CommandOpcode == DAC960_V1_RebuildStat)
{
unsigned int LogicalDriveNumber =
Controller->V1.RebuildProgress->LogicalDriveNumber;
unsigned int LogicalDriveSize =
Controller->V1.RebuildProgress->LogicalDriveSize;
unsigned int BlocksCompleted =
LogicalDriveSize - Controller->V1.RebuildProgress->RemainingBlocks;
if (CommandStatus == DAC960_V1_NormalCompletion)
{
Controller->EphemeralProgressMessage = true;
DAC960_Progress("Consistency Check in Progress: "
"Logical Drive %d (/dev/rd/c%dd%d) "
"%d%% completed\n",
Controller, LogicalDriveNumber,
Controller->ControllerNumber,
LogicalDriveNumber,
(100 * (BlocksCompleted >> 7))
/ (LogicalDriveSize >> 7));
Controller->EphemeralProgressMessage = false;
}
}
else if (CommandOpcode == DAC960_V1_BackgroundInitializationControl)
{
unsigned int LogicalDriveNumber =
Controller->V1.BackgroundInitializationStatus->LogicalDriveNumber;
unsigned int LogicalDriveSize =
Controller->V1.BackgroundInitializationStatus->LogicalDriveSize;
unsigned int BlocksCompleted =
Controller->V1.BackgroundInitializationStatus->BlocksCompleted;
switch (CommandStatus)
{
case DAC960_V1_NormalCompletion:
switch (Controller->V1.BackgroundInitializationStatus->Status)
{
case DAC960_V1_BackgroundInitializationInvalid:
break;
case DAC960_V1_BackgroundInitializationStarted:
DAC960_Progress("Background Initialization Started\n",
Controller);
break;
case DAC960_V1_BackgroundInitializationInProgress:
if (BlocksCompleted ==
Controller->V1.LastBackgroundInitializationStatus.
BlocksCompleted &&
LogicalDriveNumber ==
Controller->V1.LastBackgroundInitializationStatus.
LogicalDriveNumber)
break;
Controller->EphemeralProgressMessage = true;
DAC960_Progress("Background Initialization in Progress: "
"Logical Drive %d (/dev/rd/c%dd%d) "
"%d%% completed\n",
Controller, LogicalDriveNumber,
Controller->ControllerNumber,
LogicalDriveNumber,
(100 * (BlocksCompleted >> 7))
/ (LogicalDriveSize >> 7));
Controller->EphemeralProgressMessage = false;
break;
case DAC960_V1_BackgroundInitializationSuspended:
DAC960_Progress("Background Initialization Suspended\n",
Controller);
break;
case DAC960_V1_BackgroundInitializationCancelled:
DAC960_Progress("Background Initialization Cancelled\n",
Controller);
break;
}
memcpy(&Controller->V1.LastBackgroundInitializationStatus,
Controller->V1.BackgroundInitializationStatus,
sizeof(DAC960_V1_BackgroundInitializationStatus_T));
break;
case DAC960_V1_BackgroundInitSuccessful:
if (Controller->V1.BackgroundInitializationStatus->Status ==
DAC960_V1_BackgroundInitializationInProgress)
DAC960_Progress("Background Initialization "
"Completed Successfully\n", Controller);
Controller->V1.BackgroundInitializationStatus->Status =
DAC960_V1_BackgroundInitializationInvalid;
break;
case DAC960_V1_BackgroundInitAborted:
if (Controller->V1.BackgroundInitializationStatus->Status ==
DAC960_V1_BackgroundInitializationInProgress)
DAC960_Progress("Background Initialization Aborted\n",
Controller);
Controller->V1.BackgroundInitializationStatus->Status =
DAC960_V1_BackgroundInitializationInvalid;
break;
case DAC960_V1_NoBackgroundInitInProgress:
break;
}
}
else if (CommandOpcode == DAC960_V1_DCDB)
{
/*
This is a bit ugly.
The InquiryStandardData and
the InquiryUntitSerialNumber information
retrieval operations BOTH use the DAC960_V1_DCDB
commands. the test above can't distinguish between
these two cases.
Instead, we rely on the order of code later in this
function to ensure that DeviceInquiryInformation commands
are submitted before DeviceSerialNumber commands.
*/
if (Controller->V1.NeedDeviceInquiryInformation)
{
DAC960_SCSI_Inquiry_T *InquiryStandardData =
&Controller->V1.InquiryStandardData
[Controller->V1.DeviceStateChannel]
[Controller->V1.DeviceStateTargetID];
if (CommandStatus != DAC960_V1_NormalCompletion)
{
memset(InquiryStandardData, 0,
sizeof(DAC960_SCSI_Inquiry_T));
InquiryStandardData->PeripheralDeviceType = 0x1F;
}
else
memcpy(InquiryStandardData,
Controller->V1.NewInquiryStandardData,
sizeof(DAC960_SCSI_Inquiry_T));
Controller->V1.NeedDeviceInquiryInformation = false;
}
else if (Controller->V1.NeedDeviceSerialNumberInformation)
{
DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
&Controller->V1.InquiryUnitSerialNumber
[Controller->V1.DeviceStateChannel]
[Controller->V1.DeviceStateTargetID];
if (CommandStatus != DAC960_V1_NormalCompletion)
{
memset(InquiryUnitSerialNumber, 0,
sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
}
else
memcpy(InquiryUnitSerialNumber,
Controller->V1.NewInquiryUnitSerialNumber,
sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
Controller->V1.NeedDeviceSerialNumberInformation = false;
}
}
/*
Begin submitting new monitoring commands.
*/
if (Controller->V1.NewEventLogSequenceNumber
- Controller->V1.OldEventLogSequenceNumber > 0)
{
Command->V1.CommandMailbox.Type3E.CommandOpcode =
DAC960_V1_PerformEventLogOperation;
Command->V1.CommandMailbox.Type3E.OperationType =
DAC960_V1_GetEventLogEntry;
Command->V1.CommandMailbox.Type3E.OperationQualifier = 1;
Command->V1.CommandMailbox.Type3E.SequenceNumber =
Controller->V1.OldEventLogSequenceNumber;
Command->V1.CommandMailbox.Type3E.BusAddress =
Controller->V1.EventLogEntryDMA;
DAC960_QueueCommand(Command);
return;
}
if (Controller->V1.NeedErrorTableInformation)
{
Controller->V1.NeedErrorTableInformation = false;
Command->V1.CommandMailbox.Type3.CommandOpcode =
DAC960_V1_GetErrorTable;
Command->V1.CommandMailbox.Type3.BusAddress =
Controller->V1.NewErrorTableDMA;
DAC960_QueueCommand(Command);
return;
}
if (Controller->V1.NeedRebuildProgress &&
Controller->V1.RebuildProgressFirst)
{
Controller->V1.NeedRebuildProgress = false;
Command->V1.CommandMailbox.Type3.CommandOpcode =
DAC960_V1_GetRebuildProgress;
Command->V1.CommandMailbox.Type3.BusAddress =
Controller->V1.RebuildProgressDMA;
DAC960_QueueCommand(Command);
return;
}
if (Controller->V1.NeedDeviceStateInformation)
{
if (Controller->V1.NeedDeviceInquiryInformation)
{
DAC960_V1_DCDB_T *DCDB = Controller->V1.MonitoringDCDB;
dma_addr_t DCDB_DMA = Controller->V1.MonitoringDCDB_DMA;
dma_addr_t NewInquiryStandardDataDMA =
Controller->V1.NewInquiryStandardDataDMA;
Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB;
Command->V1.CommandMailbox.Type3.BusAddress = DCDB_DMA;
DCDB->Channel = Controller->V1.DeviceStateChannel;
DCDB->TargetID = Controller->V1.DeviceStateTargetID;
DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem;
DCDB->EarlyStatus = false;
DCDB->Timeout = DAC960_V1_DCDB_Timeout_10_seconds;
DCDB->NoAutomaticRequestSense = false;
DCDB->DisconnectPermitted = true;
DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T);
DCDB->BusAddress = NewInquiryStandardDataDMA;
DCDB->CDBLength = 6;
DCDB->TransferLengthHigh4 = 0;
DCDB->SenseLength = sizeof(DCDB->SenseData);
DCDB->CDB[0] = 0x12; /* INQUIRY */
DCDB->CDB[1] = 0; /* EVPD = 0 */
DCDB->CDB[2] = 0; /* Page Code */
DCDB->CDB[3] = 0; /* Reserved */
DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_T);
DCDB->CDB[5] = 0; /* Control */
DAC960_QueueCommand(Command);
return;
}
if (Controller->V1.NeedDeviceSerialNumberInformation)
{
DAC960_V1_DCDB_T *DCDB = Controller->V1.MonitoringDCDB;
dma_addr_t DCDB_DMA = Controller->V1.MonitoringDCDB_DMA;
dma_addr_t NewInquiryUnitSerialNumberDMA =
Controller->V1.NewInquiryUnitSerialNumberDMA;
Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB;
Command->V1.CommandMailbox.Type3.BusAddress = DCDB_DMA;
DCDB->Channel = Controller->V1.DeviceStateChannel;
DCDB->TargetID = Controller->V1.DeviceStateTargetID;
DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem;
DCDB->EarlyStatus = false;
DCDB->Timeout = DAC960_V1_DCDB_Timeout_10_seconds;
DCDB->NoAutomaticRequestSense = false;
DCDB->DisconnectPermitted = true;
DCDB->TransferLength =
sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
DCDB->BusAddress = NewInquiryUnitSerialNumberDMA;
DCDB->CDBLength = 6;
DCDB->TransferLengthHigh4 = 0;
DCDB->SenseLength = sizeof(DCDB->SenseData);
DCDB->CDB[0] = 0x12; /* INQUIRY */
DCDB->CDB[1] = 1; /* EVPD = 1 */
DCDB->CDB[2] = 0x80; /* Page Code */
DCDB->CDB[3] = 0; /* Reserved */
DCDB->CDB[4] = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
DCDB->CDB[5] = 0; /* Control */
DAC960_QueueCommand(Command);
return;
}
if (Controller->V1.StartDeviceStateScan)
{
Controller->V1.DeviceStateChannel = 0;
Controller->V1.DeviceStateTargetID = 0;
Controller->V1.StartDeviceStateScan = false;
}
else if (++Controller->V1.DeviceStateTargetID == Controller->Targets)
{
Controller->V1.DeviceStateChannel++;
Controller->V1.DeviceStateTargetID = 0;
}
if (Controller->V1.DeviceStateChannel < Controller->Channels)
{
Controller->V1.NewDeviceState->DeviceState =
DAC960_V1_Device_Dead;
Command->V1.CommandMailbox.Type3D.CommandOpcode =
DAC960_V1_GetDeviceState;
Command->V1.CommandMailbox.Type3D.Channel =
Controller->V1.DeviceStateChannel;
Command->V1.CommandMailbox.Type3D.TargetID =
Controller->V1.DeviceStateTargetID;
Command->V1.CommandMailbox.Type3D.BusAddress =
Controller->V1.NewDeviceStateDMA;
DAC960_QueueCommand(Command);
return;
}
Controller->V1.NeedDeviceStateInformation = false;
}
if (Controller->V1.NeedLogicalDriveInformation)
{
Controller->V1.NeedLogicalDriveInformation = false;
Command->V1.CommandMailbox.Type3.CommandOpcode =
DAC960_V1_GetLogicalDriveInformation;
Command->V1.CommandMailbox.Type3.BusAddress =
Controller->V1.NewLogicalDriveInformationDMA;
DAC960_QueueCommand(Command);
return;
}
if (Controller->V1.NeedRebuildProgress)
{
Controller->V1.NeedRebuildProgress = false;
Command->V1.CommandMailbox.Type3.CommandOpcode =
DAC960_V1_GetRebuildProgress;
Command->V1.CommandMailbox.Type3.BusAddress =
Controller->V1.RebuildProgressDMA;
DAC960_QueueCommand(Command);
return;
}
if (Controller->V1.NeedConsistencyCheckProgress)
{
Controller->V1.NeedConsistencyCheckProgress = false;
Command->V1.CommandMailbox.Type3.CommandOpcode =
DAC960_V1_RebuildStat;
Command->V1.CommandMailbox.Type3.BusAddress =
Controller->V1.RebuildProgressDMA;
DAC960_QueueCommand(Command);
return;
}
if (Controller->V1.NeedBackgroundInitializationStatus)
{
Controller->V1.NeedBackgroundInitializationStatus = false;
Command->V1.CommandMailbox.Type3B.CommandOpcode =
DAC960_V1_BackgroundInitializationControl;
Command->V1.CommandMailbox.Type3B.CommandOpcode2 = 0x20;
Command->V1.CommandMailbox.Type3B.BusAddress =
Controller->V1.BackgroundInitializationStatusDMA;
DAC960_QueueCommand(Command);
return;
}
Controller->MonitoringTimerCount++;
Controller->MonitoringTimer.expires =
jiffies + DAC960_MonitoringTimerInterval;
add_timer(&Controller->MonitoringTimer);
}
if (CommandType == DAC960_ImmediateCommand)
{
complete(Command->Completion);
Command->Completion = NULL;
return;
}
if (CommandType == DAC960_QueuedCommand)
{
DAC960_V1_KernelCommand_T *KernelCommand = Command->V1.KernelCommand;
KernelCommand->CommandStatus = Command->V1.CommandStatus;
Command->V1.KernelCommand = NULL;
if (CommandOpcode == DAC960_V1_DCDB)
Controller->V1.DirectCommandActive[KernelCommand->DCDB->Channel]
[KernelCommand->DCDB->TargetID] =
false;
DAC960_DeallocateCommand(Command);
KernelCommand->CompletionFunction(KernelCommand);
return;
}
/*
Queue a Status Monitoring Command to the Controller using the just
completed Command if one was deferred previously due to lack of a
free Command when the Monitoring Timer Function was called.
*/
if (Controller->MonitoringCommandDeferred)
{
Controller->MonitoringCommandDeferred = false;
DAC960_V1_QueueMonitoringCommand(Command);
return;
}
/*
Deallocate the Command.
*/
DAC960_DeallocateCommand(Command);
/*
Wake up any processes waiting on a free Command.
*/
wake_up(&Controller->CommandWaitQueue);
}