Enscript Output

extractedLnx/linux-2.5.9/drivers/block/DAC960.c_DAC960_V1_ProcessCompletedCommand.c

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;
  BufferHeader_T *BufferHeader = Command->BufferHeader;
  if (CommandType == DAC960_ReadCommand ||
      CommandType == DAC960_WriteCommand)
    {
      if (CommandStatus == DAC960_V1_NormalCompletion)
	{
	  /*
	    Perform completion processing for all buffers in this I/O Request.
	  */
	  while (BufferHeader != NULL)
	    {
	      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
	      BufferHeader->bi_next = NULL;
	      DAC960_ProcessCompletedBuffer(BufferHeader, true);
	      BufferHeader = NextBufferHeader;
	    }
	  if (Command->Completion != NULL)
	    {
	      complete(Command->Completion);
	      Command->Completion = NULL;
	    }
	  add_blkdev_randomness(DAC960_MAJOR + Controller->ControllerNumber);
	}
      else if ((CommandStatus == DAC960_V1_IrrecoverableDataError ||
		CommandStatus == DAC960_V1_BadDataEncountered) &&
	       BufferHeader != NULL &&
	       BufferHeader->bi_next != NULL)
	{
	  DAC960_V1_CommandMailbox_T *CommandMailbox =
	    &Command->V1.CommandMailbox;
	  if (CommandType == DAC960_ReadCommand)
	    {
	      Command->CommandType = DAC960_ReadRetryCommand;
	      CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read;
	    }
	  else
	    {
	      Command->CommandType = DAC960_WriteRetryCommand;
	      CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write;
	    }
	  Command->BlockCount = bio_size(BufferHeader) >> DAC960_BlockSizeBits;
	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
	  CommandMailbox->Type5.BusAddress =
	    Virtual_to_Bus32(bio_data(BufferHeader));
	  DAC960_QueueCommand(Command);
	  return;
	}
      else
	{
	  if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline)
	    DAC960_V1_ReadWriteError(Command);
	  /*
	    Perform completion processing for all buffers in this I/O Request.
	  */
	  while (BufferHeader != NULL)
	    {
	      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
	      BufferHeader->bi_next = NULL;
	      DAC960_ProcessCompletedBuffer(BufferHeader, false);
	      BufferHeader = NextBufferHeader;
	    }
	  if (Command->Completion != NULL)
	    {
	      complete(Command->Completion);
	      Command->Completion = NULL;
	    }
	}
    }
  else if (CommandType == DAC960_ReadRetryCommand ||
	   CommandType == DAC960_WriteRetryCommand)
    {
      BufferHeader_T *NextBufferHeader = BufferHeader->bi_next;
      BufferHeader->bi_next = NULL;
      /*
	Perform completion processing for this single buffer.
      */
      if (CommandStatus == DAC960_V1_NormalCompletion)
	DAC960_ProcessCompletedBuffer(BufferHeader, true);
      else
	{
	  if (CommandStatus != DAC960_V1_LogicalDriveNonexistentOrOffline)
	    DAC960_V1_ReadWriteError(Command);
	  DAC960_ProcessCompletedBuffer(BufferHeader, false);
	}
      if (NextBufferHeader != NULL)
	{
	  DAC960_V1_CommandMailbox_T *CommandMailbox =
	    &Command->V1.CommandMailbox;
	  Command->BlockNumber +=
	    bio_size(BufferHeader) >> DAC960_BlockSizeBits;
	  Command->BlockCount =
	    bio_size(NextBufferHeader) >> DAC960_BlockSizeBits;
	  Command->BufferHeader = NextBufferHeader;
	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
	  CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
	  CommandMailbox->Type5.BusAddress =
	    Virtual_to_Bus32(bio_data(NextBufferHeader));
	  DAC960_QueueCommand(Command);
	  return;
	}
    }
  else if (CommandType == DAC960_MonitoringCommand ||
	   CommandOpcode == DAC960_V1_Enquiry ||
	   CommandOpcode == DAC960_V1_GetRebuildProgress)
    {
      if (CommandType != DAC960_MonitoringCommand)
	{
	  if (CommandOpcode == DAC960_V1_Enquiry)
	    memcpy(&Controller->V1.NewEnquiry,
		   Bus32_to_Virtual(Command->V1.CommandMailbox
					       .Type3.BusAddress),
		   sizeof(DAC960_V1_Enquiry_T));
	  else if (CommandOpcode == DAC960_V1_GetRebuildProgress)
	    memcpy(&Controller->V1.RebuildProgress,
		   Bus32_to_Virtual(Command->V1.CommandMailbox
					       .Type3.BusAddress),
		   sizeof(DAC960_V1_RebuildProgress_T));
	}
      if (CommandOpcode == DAC960_V1_Enquiry &&
	  Controller->ControllerInitialized)
	{
	  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 ||
	      (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 (CommandType != DAC960_MonitoringCommand &&
	      Controller->V1.RebuildFlagPending)
	    {
	      DAC960_V1_Enquiry_T *Enquiry = (DAC960_V1_Enquiry_T *)
		Bus32_to_Virtual(Command->V1.CommandMailbox.Type3.BusAddress);
	      Enquiry->RebuildFlag = Controller->V1.PendingRebuildFlag;
	      Controller->V1.RebuildFlagPending = false;
	    }
	  else if (CommandType == DAC960_MonitoringCommand &&
		   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 <
		  sizeof(DAC960_EventMessages) / sizeof(char *))
		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;
	    }
	}
    }
  if (CommandType == DAC960_MonitoringCommand)
    {
      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 =
	    Virtual_to_Bus32(&Controller->V1.EventLogEntry);
	  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 =
	    Virtual_to_Bus32(&Controller->V1.NewErrorTable);
	  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 =
	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
	  DAC960_QueueCommand(Command);
	  return;
	}
      if (Controller->V1.NeedDeviceStateInformation)
	{
	  if (Controller->V1.NeedDeviceInquiryInformation)
	    {
	      DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB;
	      DAC960_SCSI_Inquiry_T *InquiryStandardData =
		&Controller->V1.InquiryStandardData
				[Controller->V1.DeviceStateChannel]
				[Controller->V1.DeviceStateTargetID];
	      InquiryStandardData->PeripheralDeviceType = 0x1F;
	      Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB;
	      Command->V1.CommandMailbox.Type3.BusAddress =
		Virtual_to_Bus32(DCDB);
	      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 = Virtual_to_Bus32(InquiryStandardData);
	      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);
	      Controller->V1.NeedDeviceInquiryInformation = false;
	      return;
	    }
	  if (Controller->V1.NeedDeviceSerialNumberInformation)
	    {
	      DAC960_V1_DCDB_T *DCDB = &Controller->V1.MonitoringDCDB;
	      DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
		&Controller->V1.InquiryUnitSerialNumber
				[Controller->V1.DeviceStateChannel]
				[Controller->V1.DeviceStateTargetID];
	      InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
	      Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB;
	      Command->V1.CommandMailbox.Type3.BusAddress =
		Virtual_to_Bus32(DCDB);
	      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 = Virtual_to_Bus32(InquiryUnitSerialNumber);
	      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);
	      Controller->V1.NeedDeviceSerialNumberInformation = false;
	      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 =
		Virtual_to_Bus32(&Controller->V1.NewDeviceState);
	      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 =
	    Virtual_to_Bus32(&Controller->V1.NewLogicalDriveInformation);
	  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 =
	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
	  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 =
	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
	  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 =
	    Virtual_to_Bus32(&Controller->V1.BackgroundInitializationStatus);
	  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);
}

Generated by GNU enscript 1.6.4.