Index: oldkernel/linux/Documentation/README.DAC960
diff -u linux/Documentation/README.DAC960:1.1.1.1 linux/Documentation/README.DAC960:1.2
--- linux/Documentation/README.DAC960:1.1.1.1	Wed May 31 12:33:54 2000
+++ linux/Documentation/README.DAC960	Wed May 31 14:57:57 2000
@@ -1,17 +1,17 @@
 	   Mylex DAC960/DAC1100 PCI RAID Controller Driver for Linux
 
-			Version 2.2.4 for Linux 2.2.11
-			Version 2.0.4 for Linux 2.0.37
+			Version 2.2.5 for Linux 2.2.14
+			Version 2.0.5 for Linux 2.0.38
 
 			      PRODUCTION RELEASE
 
-				23 August 1999
+				23 January 2000
 
 			       Leonard N. Zubkoff
 			       Dandelion Digital
 			       lnz@dandelion.com
 
-	 Copyright 1998-1999 by Leonard N. Zubkoff <lnz@dandelion.com>
+	 Copyright 1998-2000 by Leonard N. Zubkoff <lnz@dandelion.com>
 
 
 				 INTRODUCTION
@@ -87,7 +87,9 @@
 The following list comprises the supported DAC960 and DAC1100 PCI RAID
 Controllers as of the date of this document.  It is recommended that anyone
 purchasing a Mylex PCI RAID Controller not in the following table contact the
-author beforehand to verify that it is or will be supported.
+author beforehand to verify that it is or will be supported.  The eXtremeRAID
+2000, eXtremeRAID 3000, and AcceleRAID 352 have an entirely new firmware
+interface and are not yet supported by this driver.
 
 eXtremeRAID 1100 (DAC1164P)
 	    3 Wide Ultra-2/LVD SCSI channels
@@ -163,16 +165,16 @@
 
 			      DRIVER INSTALLATION
 
-This distribution was prepared for Linux kernel version 2.2.11 or 2.0.37.
+This distribution was prepared for Linux kernel version 2.2.14 or 2.0.38.
 
 To install the DAC960 RAID driver, you may use the following commands,
 replacing "/usr/src" with wherever you keep your Linux kernel source tree:
 
   cd /usr/src
-  tar -xvzf DAC960-2.2.4.tar.gz (or DAC960-2.0.4.tar.gz)
+  tar -xvzf DAC960-2.2.5.tar.gz (or DAC960-2.0.5.tar.gz)
   mv README.DAC960 linux/Documentation
   mv DAC960.[ch] linux/drivers/block
-  patch -p0 < DAC960.patch
+  patch -p0 < DAC960.patch (driver 2.0.5 only)
   cd linux
   make config
   make depend
Index: oldkernel/linux/drivers/block/DAC960.c
diff -u linux/drivers/block/DAC960.c:1.1.1.1 linux/drivers/block/DAC960.c:1.2
--- linux/drivers/block/DAC960.c:1.1.1.1	Wed May 31 12:33:50 2000
+++ linux/drivers/block/DAC960.c	Wed May 31 14:57:57 2000
@@ -19,8 +19,8 @@
 */
 
 
-#define DAC960_DriverVersion			"2.2.4"
-#define DAC960_DriverDate			"23 August 1999"
+#define DAC960_DriverVersion			"2.2.5"
+#define DAC960_DriverDate			"23 January 2000"
 
 
 #include <linux/version.h>
@@ -120,7 +120,7 @@
   DAC960_Announce("***** DAC960 RAID Driver Version "
 		  DAC960_DriverVersion " of "
 		  DAC960_DriverDate " *****\n", Controller);
-  DAC960_Announce("Copyright 1998-1999 by Leonard N. Zubkoff "
+  DAC960_Announce("Copyright 1998-2000 by Leonard N. Zubkoff "
 		  "<lnz@dandelion.com>\n", Controller);
 }
 
@@ -194,6 +194,23 @@
 
 
 /*
+  DAC960_WaitForCommand waits for a wake_up on Controller's Command Wait Queue.
+*/
+
+static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
+{
+  WaitQueue_T WaitQueueEntry = { current, NULL };
+  add_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry);
+  current->state = TASK_UNINTERRUPTIBLE;
+  spin_unlock(&io_request_lock);
+  schedule();
+  current->state = TASK_RUNNING;
+  remove_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry);
+  spin_lock_irq(&io_request_lock);
+}
+
+
+/*
   DAC960_QueueCommand queues Command.
 */
 
@@ -317,6 +334,62 @@
 
 
 /*
+  DAC960_ReportErrorStatus reports Controller BIOS Messages passed through
+  the Error Status Register when the driver performs the BIOS handshaking.
+  It returns true for fatal errors and false otherwise.
+*/
+
+static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller,
+					unsigned char ErrorStatus,
+					unsigned char Parameter0,
+					unsigned char Parameter1)
+{
+  switch (ErrorStatus)
+    {
+    case 0x00:
+      DAC960_Notice("Physical Drive %d:%d Not Responding\n",
+		    Controller, Parameter1, Parameter0);
+      break;
+    case 0x08:
+      if (Controller->DriveSpinUpMessageDisplayed) break;
+      DAC960_Notice("Spinning Up Drives\n", Controller);
+      Controller->DriveSpinUpMessageDisplayed = true;
+      break;
+    case 0x30:
+      DAC960_Notice("Configuration Checksum Error\n", Controller);
+      break;
+    case 0x60:
+      DAC960_Notice("Mirror Race Recovery Failed\n", Controller);
+      break;
+    case 0x70:
+      DAC960_Notice("Mirror Race Recovery In Progress\n", Controller);
+      break;
+    case 0x90:
+      DAC960_Notice("Physical Drive %d:%d COD Mismatch\n",
+		    Controller, Parameter1, Parameter0);
+      break;
+    case 0xA0:
+      DAC960_Notice("Logical Drive Installation Aborted\n", Controller);
+      break;
+    case 0xB0:
+      DAC960_Notice("Mirror Race On A Critical Logical Drive\n", Controller);
+      break;
+    case 0xD0:
+      DAC960_Notice("New Controller Configuration Found\n", Controller);
+      break;
+    case 0xF0:
+      DAC960_Error("Fatal Memory Parity Error for Controller at\n", Controller);
+      return true;
+    default:
+      DAC960_Error("Unknown Initialization Error %02X for Controller at\n",
+		   Controller, ErrorStatus);
+      return true;
+    }
+  return false;
+}
+
+
+/*
   DAC960_EnableMemoryMailboxInterface enables the Memory Mailbox Interface.
 */
 
@@ -382,7 +455,7 @@
       case DAC960_V5_Controller:
 	while (--TimeoutCounter >= 0)
 	  {
-	    if (DAC960_V5_HardwareMailboxEmptyP(ControllerBaseAddress))
+	    if (!DAC960_V5_HardwareMailboxFullP(ControllerBaseAddress))
 	      break;
 	    udelay(10);
 	  }
@@ -474,11 +547,13 @@
       unsigned char DeviceFunction = PCI_Device->devfn;
       unsigned char Device = DeviceFunction >> 3;
       unsigned char Function = DeviceFunction & 0x7;
+      unsigned char ErrorStatus, Parameter0, Parameter1;
       unsigned int IRQ_Channel = PCI_Device->irq;
       unsigned long BaseAddress0 = PCI_Device->base_address[0];
       unsigned long BaseAddress1 = PCI_Device->base_address[1];
       unsigned short SubsystemVendorID, SubsystemDeviceID;
       int CommandIdentifier;
+      void *BaseAddress;
       pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_VENDOR_ID,
 			   &SubsystemVendorID);
       pci_read_config_word(PCI_Device, PCI_SUBSYSTEM_ID,
@@ -524,24 +599,6 @@
       Controller->Function = Function;
       sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
       /*
-	Acquire shared access to the IRQ Channel.
-      */
-      if (IRQ_Channel == 0)
-	{
-	  DAC960_Error("IRQ Channel %d illegal for Controller at\n",
-		       Controller, IRQ_Channel);
-	  goto Failure;
-	}
-      strcpy(Controller->FullModelName, "DAC960");
-      if (request_irq(IRQ_Channel, DAC960_InterruptHandler,
-		      SA_SHIRQ, Controller->FullModelName, Controller) < 0)
-	{
-	  DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
-		       Controller, IRQ_Channel);
-	  goto Failure;
-	}
-      Controller->IRQ_Channel = IRQ_Channel;
-      /*
 	Map the Controller Register Window.
       */
       if (MemoryWindowSize < PAGE_SIZE)
@@ -556,34 +613,87 @@
 		       "Controller at\n", Controller);
 	  goto Failure;
 	}
+      BaseAddress = Controller->BaseAddress;
       switch (ControllerType)
 	{
 	case DAC960_V5_Controller:
-	  DAC960_V5_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_V5_DisableInterrupts(BaseAddress);
+	  DAC960_V5_AcknowledgeHardwareMailboxStatus(BaseAddress);
+	  udelay(1000);
+	  while (DAC960_V5_InitializationInProgressP(BaseAddress))
+	    {
+	      if (DAC960_V5_ReadErrorStatus(BaseAddress, &ErrorStatus,
+					    &Parameter0, &Parameter1) &&
+		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
+					   Parameter0, Parameter1))
+		goto Failure;
+	      udelay(10);
+	    }
 	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
 	    {
 	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_V5_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_V5_EnableInterrupts(BaseAddress);
 	  break;
 	case DAC960_V4_Controller:
-	  DAC960_V4_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_V4_DisableInterrupts(BaseAddress);
+	  DAC960_V4_AcknowledgeHardwareMailboxStatus(BaseAddress);
+	  udelay(1000);
+	  while (DAC960_V4_InitializationInProgressP(BaseAddress))
+	    {
+	      if (DAC960_V4_ReadErrorStatus(BaseAddress, &ErrorStatus,
+					    &Parameter0, &Parameter1) &&
+		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
+					   Parameter0, Parameter1))
+		goto Failure;
+	      udelay(10);
+	    }
 	  if (!DAC960_EnableMemoryMailboxInterface(Controller))
 	    {
 	      DAC960_Error("Unable to Enable Memory Mailbox Interface "
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_V4_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_V4_EnableInterrupts(BaseAddress);
 	  break;
 	case DAC960_V3_Controller:
 	  request_region(Controller->IO_Address, 0x80,
 			 Controller->FullModelName);
-	  DAC960_V3_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_V3_DisableInterrupts(BaseAddress);
+	  DAC960_V3_AcknowledgeStatus(BaseAddress);
+	  udelay(1000);
+	  while (DAC960_V3_InitializationInProgressP(BaseAddress))
+	    {
+	      if (DAC960_V3_ReadErrorStatus(BaseAddress, &ErrorStatus,
+					    &Parameter0, &Parameter1) &&
+		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
+					   Parameter0, Parameter1))
+		goto Failure;
+	      udelay(10);
+	    }
+	  DAC960_V3_EnableInterrupts(BaseAddress);
 	  break;
 	}
+      /*
+	Acquire shared access to the IRQ Channel.
+      */
+      if (IRQ_Channel == 0)
+	{
+	  DAC960_Error("IRQ Channel %d illegal for Controller at\n",
+		       Controller, IRQ_Channel);
+	  goto Failure;
+	}
+      strcpy(Controller->FullModelName, "DAC960");
+      if (request_irq(IRQ_Channel, DAC960_InterruptHandler,
+		      SA_SHIRQ, Controller->FullModelName, Controller) < 0)
+	{
+	  DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
+		       Controller, IRQ_Channel);
+	  goto Failure;
+	}
+      Controller->IRQ_Channel = IRQ_Channel;
       DAC960_ActiveControllerCount++;
       for (CommandIdentifier = 0;
 	   CommandIdentifier < DAC960_MaxChannels;
@@ -604,11 +714,11 @@
 			"0x%X PCI Address 0x%X\n", Controller,
 			Bus, Device, Function, IO_Address, PCI_Address);
       if (Controller == NULL) break;
-      if (Controller->IRQ_Channel > 0)
-	free_irq(IRQ_Channel, Controller);
       if (Controller->MemoryMappedAddress != NULL)
 	iounmap(Controller->MemoryMappedAddress);
       DAC960_Controllers[Controller->ControllerNumber] = NULL;
+      if (Controller->IRQ_Channel > 0)
+	free_irq(IRQ_Channel, Controller);
     Ignore:
       kfree(Controller);
     }
@@ -1282,9 +1392,7 @@
       Command = DAC960_AllocateCommand(Controller);
       if (Command != NULL) break;
       if (!WaitForCommand) return false;
-      spin_unlock(&io_request_lock);
-      sleep_on(&Controller->CommandWaitQueue);
-      spin_lock_irq(&io_request_lock);
+      DAC960_WaitForCommand(Controller);
     }
   DAC960_ClearCommand(Command);
   if (Request->cmd == READ)
@@ -1836,6 +1944,20 @@
 	      }
 	  else if (NewEnquiry->RebuildFlag == DAC960_BackgroundCheckInProgress)
 	    Controller->NeedConsistencyCheckProgress = true;
+	  if (CommandType != DAC960_MonitoringCommand &&
+	      Controller->RebuildFlagPending)
+	    {
+	      DAC960_Enquiry_T *Enquiry = (DAC960_Enquiry_T *)
+		Bus_to_Virtual(Command->CommandMailbox.Type3.BusAddress);
+	      Enquiry->RebuildFlag = Controller->PendingRebuildFlag;
+	      Controller->RebuildFlagPending = false;
+	    }
+	  else if (CommandType == DAC960_MonitoringCommand &&
+		   NewEnquiry->RebuildFlag > DAC960_BackgroundCheckInProgress)
+	    {
+	      Controller->PendingRebuildFlag = NewEnquiry->RebuildFlag;
+	      Controller->RebuildFlagPending = true;
+	    }
 	}
       else if (CommandOpcode == DAC960_PerformEventLogOperation)
 	{
@@ -2019,6 +2141,9 @@
 	    Controller->RebuildProgress.LogicalDriveSize;
 	  unsigned int BlocksCompleted =
 	    LogicalDriveSize - Controller->RebuildProgress.RemainingBlocks;
+	  if (CommandStatus == DAC960_NoRebuildOrCheckInProgress &&
+	      Controller->LastRebuildStatus == DAC960_NormalCompletion)
+	    CommandStatus = DAC960_RebuildSuccessful;
 	  switch (CommandStatus)
 	    {
 	    case DAC960_NormalCompletion:
@@ -2046,13 +2171,28 @@
 			      "Failure of Drive Being Rebuilt\n", Controller);
 	      break;
 	    case DAC960_NoRebuildOrCheckInProgress:
-	      if (Controller->LastRebuildStatus != DAC960_NormalCompletion)
-		break;
+	      break;
 	    case DAC960_RebuildSuccessful:
 	      DAC960_Progress("Rebuild Completed Successfully\n", Controller);
 	      break;
+	    case DAC960_RebuildSuccessfullyTerminated:
+	      DAC960_Progress("Rebuild Successfully Terminated\n", Controller);
+	      break;
 	    }
 	  Controller->LastRebuildStatus = CommandStatus;
+	  if (CommandType != DAC960_MonitoringCommand &&
+	      Controller->RebuildStatusPending)
+	    {
+	      Command->CommandStatus = Controller->PendingRebuildStatus;
+	      Controller->RebuildStatusPending = false;
+	    }
+	  else if (CommandType == DAC960_MonitoringCommand &&
+		   CommandStatus != DAC960_NormalCompletion &&
+		   CommandStatus != DAC960_NoRebuildOrCheckInProgress)
+	    {
+	      Controller->PendingRebuildStatus = CommandStatus;
+	      Controller->RebuildStatusPending = true;
+	    }
 	}
       else if (CommandOpcode == DAC960_RebuildStat)
 	{
@@ -2267,7 +2407,7 @@
   if (CommandType == DAC960_QueuedCommand)
     {
       DAC960_KernelCommand_T *KernelCommand = Command->KernelCommand;
-      KernelCommand->CommandStatus = CommandStatus;
+      KernelCommand->CommandStatus = Command->CommandStatus;
       Command->KernelCommand = NULL;
       if (CommandOpcode == DAC960_DCDB)
 	Controller->DirectCommandActive[KernelCommand->DCDB->Channel]
@@ -2288,9 +2428,12 @@
       return;
     }
   /*
-    Deallocate the Command, and wake up any processes waiting on a free Command.
+    Deallocate the Command.
   */
   DAC960_DeallocateCommand(Command);
+  /*
+    Wake up any processes waiting on a free Command.
+  */
   wake_up(&Controller->CommandWaitQueue);
 }
 
@@ -2696,19 +2839,14 @@
 	  }
 	if (CommandOpcode == DAC960_DCDB)
 	  {
-	    while (true)
-	      {
-		DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-		if (!Controller->DirectCommandActive[DCDB.Channel]
-						    [DCDB.TargetID])
-		  Command = DAC960_AllocateCommand(Controller);
-		if (Command != NULL)
-		  Controller->DirectCommandActive[DCDB.Channel]
-						 [DCDB.TargetID] = true;
-		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-		if (Command != NULL) break;
-		sleep_on(&Controller->CommandWaitQueue);
-	      }
+	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	    while (Controller->DirectCommandActive[DCDB.Channel]
+						  [DCDB.TargetID] ||
+		   (Command = DAC960_AllocateCommand(Controller)) == NULL)
+	      DAC960_WaitForCommand(Controller);
+	    Controller->DirectCommandActive[DCDB.Channel]
+					   [DCDB.TargetID] = true;
+	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
 	    DAC960_ClearCommand(Command);
 	    Command->CommandType = DAC960_ImmediateCommand;
 	    memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
@@ -2718,14 +2856,10 @@
 	  }
 	else
 	  {
-	    while (true)
-	      {
-		DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-		Command = DAC960_AllocateCommand(Controller);
-		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-		if (Command != NULL) break;
-		sleep_on(&Controller->CommandWaitQueue);
-	      }
+	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+	    while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
+	      DAC960_WaitForCommand(Controller);
+	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
 	    DAC960_ClearCommand(Command);
 	    Command->CommandType = DAC960_ImmediateCommand;
 	    memcpy(&Command->CommandMailbox, &UserCommand.CommandMailbox,
@@ -3127,14 +3261,10 @@
   DAC960_CommandMailbox_T *CommandMailbox;
   ProcessorFlags_T ProcessorFlags;
   unsigned char Channel, TargetID, LogicalDriveNumber;
-  while (true)
-    {
-      DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-      Command = DAC960_AllocateCommand(Controller);
-      DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-      if (Command != NULL) break;
-      sleep_on(&Controller->CommandWaitQueue);
-    }
+  DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+  while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
+    DAC960_WaitForCommand(Controller);
+  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
   Controller->UserStatusLength = 0;
   DAC960_ClearCommand(Command);
   Command->CommandType = DAC960_ImmediateCommand;
Index: oldkernel/linux/drivers/block/DAC960.h
diff -u linux/drivers/block/DAC960.h:1.1.1.1 linux/drivers/block/DAC960.h:1.2
--- linux/drivers/block/DAC960.h:1.1.1.1	Wed May 31 12:33:50 2000
+++ linux/drivers/block/DAC960.h	Wed May 31 14:57:57 2000
@@ -55,17 +55,17 @@
 
 
 /*
-  Define a 32 bit I/O Address data type.
+  Define a 32/64 bit I/O Address data type.
 */
 
-typedef unsigned int DAC960_IO_Address_T;
+typedef unsigned long DAC960_IO_Address_T;
 
 
 /*
-  Define a 32 bit PCI Bus Address data type.
+  Define a 32/64 bit PCI Bus Address data type.
 */
 
-typedef unsigned int DAC960_PCI_Address_T;
+typedef unsigned long DAC960_PCI_Address_T;
 
 
 /*
@@ -196,6 +196,7 @@
 #define DAC960_RebuildFailed_BadBlocksOnOther	0x0003	/* Consistency */
 #define DAC960_RebuildFailed_NewDriveFailed	0x0004	/* Consistency */
 #define DAC960_RebuildSuccessful		0x0100	/* Consistency */
+#define DAC960_RebuildSuccessfullyTerminated	0x0107	/* Consistency */
 #define DAC960_AddCapacityInProgress		0x0004	/* Consistency */
 #define DAC960_AddCapacityFailedOrSuspended	0x00F4	/* Consistency */
 #define DAC960_Config2ChecksumError		0x0002	/* Configuration */
@@ -513,7 +514,7 @@
   unsigned char SynchronousMultiplier;			/* Byte 4 */
   unsigned char SynchronousOffset:5;			/* Byte 5 Bits 0-4 */
   unsigned char :3;					/* Byte 5 Bits 5-7 */
-  unsigned long DiskSize __attribute__ ((packed));	/* Bytes 6-9 */
+  unsigned int DiskSize __attribute__ ((packed));	/* Bytes 6-9 */
 }
 DAC960_DeviceState_T;
 
@@ -1212,6 +1213,7 @@
   unsigned char LogicalDriveCount;
   unsigned char GeometryTranslationHeads;
   unsigned char GeometryTranslationSectors;
+  unsigned char PendingRebuildFlag;
   unsigned short ControllerQueueDepth;
   unsigned short DriverQueueDepth;
   unsigned short MaxBlocksPerCommand;
@@ -1247,6 +1249,9 @@
   boolean NeedRebuildProgress;
   boolean NeedConsistencyCheckProgress;
   boolean EphemeralProgressMessage;
+  boolean RebuildFlagPending;
+  boolean RebuildStatusPending;
+  boolean DriveSpinUpMessageDisplayed;
   Timer_T MonitoringTimer;
   GenericDiskInfo_T GenericDiskInfo;
   DAC960_Command_T *FreeCommands;
@@ -1269,6 +1274,7 @@
   DAC960_EventLogEntry_T EventLogEntry;
   DAC960_RebuildProgress_T RebuildProgress;
   DAC960_CommandStatus_T LastRebuildStatus;
+  DAC960_CommandStatus_T PendingRebuildStatus;
   DAC960_LogicalDriveInformation_T
     LogicalDriveInformation[2][DAC960_MaxLogicalDrives];
   DAC960_LogicalDriveState_T LogicalDriveInitialState[DAC960_MaxLogicalDrives];
@@ -1393,7 +1399,8 @@
   DAC960_V5_MailboxRegister11Offset =		0x5B,
   DAC960_V5_MailboxRegister12Offset =		0x5C,
   DAC960_V5_StatusCommandIdentifierRegOffset =	0x5D,
-  DAC960_V5_StatusRegisterOffset =		0x5E
+  DAC960_V5_StatusRegisterOffset =		0x5E,
+  DAC960_V5_ErrorStatusRegisterOffset =		0x63
 }
 DAC960_V5_RegisterOffsets_T;
 
@@ -1415,7 +1422,8 @@
   } Write;
   struct {
     boolean HardwareMailboxEmpty:1;			/* Bit 0 */
-    unsigned char :7;					/* Bits 1-7 */
+    boolean InitializationNotInProgress:1;		/* Bit 1 */
+    unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
 DAC960_V5_InboundDoorBellRegister_T;
@@ -1459,6 +1467,22 @@
 
 
 /*
+  Define the structure of the DAC960 V5 Error Status Register.
+*/
+
+typedef union DAC960_V5_ErrorStatusRegister
+{
+  unsigned char All;
+  struct {
+    unsigned int :2;					/* Bits 0-1 */
+    boolean ErrorStatusPending:1;			/* Bit 2 */
+    unsigned int :5;					/* Bits 3-7 */
+  } Bits;
+}
+DAC960_V5_ErrorStatusRegister_T;
+
+
+/*
   Define inline functions to provide an abstraction for reading and writing the
   DAC960 V5 Controller Interface Registers.
 */
@@ -1514,15 +1538,24 @@
 }
 
 static inline
-boolean DAC960_V5_HardwareMailboxEmptyP(void *ControllerBaseAddress)
+boolean DAC960_V5_HardwareMailboxFullP(void *ControllerBaseAddress)
 {
   DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
   InboundDoorBellRegister.All =
     readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
-  return InboundDoorBellRegister.Read.HardwareMailboxEmpty;
+  return !InboundDoorBellRegister.Read.HardwareMailboxEmpty;
 }
 
 static inline
+boolean DAC960_V5_InitializationInProgressP(void *ControllerBaseAddress)
+{
+  DAC960_V5_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_InboundDoorBellRegisterOffset);
+  return !InboundDoorBellRegister.Read.InitializationNotInProgress;
+}
+
+static inline
 void DAC960_V5_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 {
   DAC960_V5_OutboundDoorBellRegister_T OutboundDoorBellRegister;
@@ -1575,7 +1608,7 @@
 void DAC960_V5_EnableInterrupts(void *ControllerBaseAddress)
 {
   DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.All = 0xFF;
   InterruptMaskRegister.Bits.DisableInterrupts = false;
   writeb(InterruptMaskRegister.All,
 	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
@@ -1585,7 +1618,7 @@
 void DAC960_V5_DisableInterrupts(void *ControllerBaseAddress)
 {
   DAC960_V5_InterruptMaskRegister_T InterruptMaskRegister;
-  InterruptMaskRegister.All = 0;
+  InterruptMaskRegister.All = 0xFF;
   InterruptMaskRegister.Bits.DisableInterrupts = true;
   writeb(InterruptMaskRegister.All,
 	 ControllerBaseAddress + DAC960_V5_InterruptMaskRegisterOffset);
@@ -1607,7 +1640,9 @@
   NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
   NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
   NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+  wmb();
   NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+  mb();
 }
 
 static inline
@@ -1637,6 +1672,26 @@
   return readw(ControllerBaseAddress + DAC960_V5_StatusRegisterOffset);
 }
 
+static inline boolean
+DAC960_V5_ReadErrorStatus(void *ControllerBaseAddress,
+			  unsigned char *ErrorStatus,
+			  unsigned char *Parameter0,
+			  unsigned char *Parameter1)
+{
+  DAC960_V5_ErrorStatusRegister_T ErrorStatusRegister;
+  ErrorStatusRegister.All =
+    readb(ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset);
+  if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false;
+  ErrorStatusRegister.Bits.ErrorStatusPending = false;
+  *ErrorStatus = ErrorStatusRegister.All;
+  *Parameter0 =
+    readb(ControllerBaseAddress + DAC960_V5_CommandOpcodeRegisterOffset);
+  *Parameter1 =
+    readb(ControllerBaseAddress + DAC960_V5_CommandIdentifierRegisterOffset);
+  writeb(0xFF, ControllerBaseAddress + DAC960_V5_ErrorStatusRegisterOffset);
+  return true;
+}
+
 static inline
 void DAC960_V5_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
 {
@@ -1695,7 +1750,8 @@
   DAC960_V4_MailboxRegister11Offset =		0x100B,
   DAC960_V4_MailboxRegister12Offset =		0x100C,
   DAC960_V4_StatusCommandIdentifierRegOffset =	0x1018,
-  DAC960_V4_StatusRegisterOffset =		0x101A
+  DAC960_V4_StatusRegisterOffset =		0x101A,
+  DAC960_V4_ErrorStatusRegisterOffset =		0x103F
 }
 DAC960_V4_RegisterOffsets_T;
 
@@ -1717,7 +1773,8 @@
   } Write;
   struct {
     boolean HardwareMailboxFull:1;			/* Bit 0 */
-    unsigned int :31;					/* Bits 1-31 */
+    boolean InitializationInProgress:1;			/* Bit 1 */
+    unsigned int :30;					/* Bits 2-31 */
   } Read;
 }
 DAC960_V4_InboundDoorBellRegister_T;
@@ -1762,6 +1819,22 @@
 
 
 /*
+  Define the structure of the DAC960 V4 Error Status Register.
+*/
+
+typedef union DAC960_V4_ErrorStatusRegister
+{
+  unsigned char All;
+  struct {
+    unsigned int :2;					/* Bits 0-1 */
+    boolean ErrorStatusPending:1;			/* Bit 2 */
+    unsigned int :5;					/* Bits 3-7 */
+  } Bits;
+}
+DAC960_V4_ErrorStatusRegister_T;
+
+
+/*
   Define inline functions to provide an abstraction for reading and writing the
   DAC960 V4 Controller Interface Registers.
 */
@@ -1826,6 +1899,15 @@
 }
 
 static inline
+boolean DAC960_V4_InitializationInProgressP(void *ControllerBaseAddress)
+{
+  DAC960_V4_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readl(ControllerBaseAddress + DAC960_V4_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.InitializationInProgress;
+}
+
+static inline
 void DAC960_V4_AcknowledgeHardwareMailboxInterrupt(void *ControllerBaseAddress)
 {
   DAC960_V4_OutboundDoorBellRegister_T OutboundDoorBellRegister;
@@ -1914,7 +1996,9 @@
   NextCommandMailbox->Words[1] = CommandMailbox->Words[1];
   NextCommandMailbox->Words[2] = CommandMailbox->Words[2];
   NextCommandMailbox->Words[3] = CommandMailbox->Words[3];
+  wmb();
   NextCommandMailbox->Words[0] = CommandMailbox->Words[0];
+  mb();
 }
 
 static inline
@@ -1944,11 +2028,31 @@
   return readw(ControllerBaseAddress + DAC960_V4_StatusRegisterOffset);
 }
 
+static inline boolean
+DAC960_V4_ReadErrorStatus(void *ControllerBaseAddress,
+			  unsigned char *ErrorStatus,
+			  unsigned char *Parameter0,
+			  unsigned char *Parameter1)
+{
+  DAC960_V4_ErrorStatusRegister_T ErrorStatusRegister;
+  ErrorStatusRegister.All =
+    readb(ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset);
+  if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false;
+  ErrorStatusRegister.Bits.ErrorStatusPending = false;
+  *ErrorStatus = ErrorStatusRegister.All;
+  *Parameter0 =
+    readb(ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
+  *Parameter1 =
+    readb(ControllerBaseAddress + DAC960_V4_CommandIdentifierRegisterOffset);
+  writeb(0, ControllerBaseAddress + DAC960_V4_ErrorStatusRegisterOffset);
+  return true;
+}
+
 static inline
 void DAC960_V4_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
 {
   void *ControllerBaseAddress = Controller->BaseAddress;
-  writel(0xAABBFFFF,
+  writel(0x743C485E,
 	 ControllerBaseAddress + DAC960_V4_CommandOpcodeRegisterOffset);
   writel((unsigned long) Controller->FirstCommandMailbox,
 	 ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
@@ -1966,7 +2070,7 @@
 {
   void *ControllerBaseAddress = Controller->BaseAddress;
   if (readl(ControllerBaseAddress
-	    + DAC960_V4_CommandOpcodeRegisterOffset) != 0xAABBFFFF)
+	    + DAC960_V4_CommandOpcodeRegisterOffset) != 0x743C485E)
     return;
   *MemoryMailboxAddress =
     (void *) readl(ControllerBaseAddress + DAC960_V4_MailboxRegister4Offset);
@@ -2000,6 +2104,7 @@
   DAC960_V3_MailboxRegister12Offset =		0x0C,
   DAC960_V3_StatusCommandIdentifierRegOffset =	0x0D,
   DAC960_V3_StatusRegisterOffset =		0x0E,
+  DAC960_V3_ErrorStatusRegisterOffset =		0x3F,
   DAC960_V3_InboundDoorBellRegisterOffset =	0x40,
   DAC960_V3_OutboundDoorBellRegisterOffset =	0x41,
   DAC960_V3_InterruptEnableRegisterOffset =	0x43
@@ -2023,7 +2128,8 @@
   } Write;
   struct {
     boolean MailboxFull:1;				/* Bit 0 */
-    unsigned char :7;					/* Bits 1-7 */
+    boolean InitializationInProgress:1;			/* Bit 1 */
+    unsigned char :6;					/* Bits 2-7 */
   } Read;
 }
 DAC960_V3_InboundDoorBellRegister_T;
@@ -2064,6 +2170,22 @@
 
 
 /*
+  Define the structure of the DAC960 V3 Error Status Register.
+*/
+
+typedef union DAC960_V3_ErrorStatusRegister
+{
+  unsigned char All;
+  struct {
+    unsigned int :2;					/* Bits 0-1 */
+    boolean ErrorStatusPending:1;			/* Bit 2 */
+    unsigned int :5;					/* Bits 3-7 */
+  } Bits;
+}
+DAC960_V3_ErrorStatusRegister_T;
+
+
+/*
   Define inline functions to provide an abstraction for reading and writing the
   DAC960 V3 Controller Interface Registers.
 */
@@ -2118,6 +2240,15 @@
 }
 
 static inline
+boolean DAC960_V3_InitializationInProgressP(void *ControllerBaseAddress)
+{
+  DAC960_V3_InboundDoorBellRegister_T InboundDoorBellRegister;
+  InboundDoorBellRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_InboundDoorBellRegisterOffset);
+  return InboundDoorBellRegister.Read.InitializationInProgress;
+}
+
+static inline
 void DAC960_V3_AcknowledgeInterrupt(void *ControllerBaseAddress)
 {
   DAC960_V3_OutboundDoorBellRegister_T OutboundDoorBellRegister;
@@ -2190,6 +2321,26 @@
 DAC960_V3_ReadStatusRegister(void *ControllerBaseAddress)
 {
   return readw(ControllerBaseAddress + DAC960_V3_StatusRegisterOffset);
+}
+
+static inline boolean
+DAC960_V3_ReadErrorStatus(void *ControllerBaseAddress,
+			  unsigned char *ErrorStatus,
+			  unsigned char *Parameter0,
+			  unsigned char *Parameter1)
+{
+  DAC960_V3_ErrorStatusRegister_T ErrorStatusRegister;
+  ErrorStatusRegister.All =
+    readb(ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset);
+  if (!ErrorStatusRegister.Bits.ErrorStatusPending) return false;
+  ErrorStatusRegister.Bits.ErrorStatusPending = false;
+  *ErrorStatus = ErrorStatusRegister.All;
+  *Parameter0 =
+    readb(ControllerBaseAddress + DAC960_V3_CommandOpcodeRegisterOffset);
+  *Parameter1 =
+    readb(ControllerBaseAddress + DAC960_V3_CommandIdentifierRegisterOffset);
+  writeb(0, ControllerBaseAddress + DAC960_V3_ErrorStatusRegisterOffset);
+  return true;
 }
 
 
