From fa8bb677460bb841e5e34b5c5ccba26167b525e8 Mon Sep 17 00:00:00 2001
From: Alan Cox <alan@lxorguk.ukuu.org.uk>
Date: Mon, 25 Nov 2002 02:15:23 -0800
Subject: [PATCH] [PATCH] update to OSDL DAC960 driver

Its not perfect but it works
---
 drivers/block/DAC960.c | 2849 ++++++++++++++++++++++------------------
 drivers/block/DAC960.h |  285 ++--
 2 files changed, 1691 insertions(+), 1443 deletions(-)

diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c
index b64c7facfd4f..c28072cbb910 100644
--- a/drivers/block/DAC960.c
+++ b/drivers/block/DAC960.c
@@ -19,8 +19,8 @@
 */
 
 
-#define DAC960_DriverVersion			"2.4.11"
-#define DAC960_DriverDate			"11 October 2001"
+#define DAC960_DriverVersion			"2.5.47"
+#define DAC960_DriverDate			"14 November 2002"
 
 
 #include <linux/version.h>
@@ -56,16 +56,6 @@
 static int
   DAC960_ControllerCount =			0;
 
-
-/*
-  DAC960_ActiveControllerCount is the number of active DAC960 Controllers
-  detected.
-*/
-
-static int
-  DAC960_ActiveControllerCount =		0;
-
-
 /*
   DAC960_Controllers is an array of pointers to the DAC960 Controller
   structures.
@@ -82,11 +72,11 @@ static int DAC960_revalidate(struct gendisk *);
 */
 
 static struct block_device_operations DAC960_BlockDeviceOperations = {
-	.owner		= THIS_MODULE,
-	.open		= DAC960_Open,
-	.release	= DAC960_Release,
-	.ioctl		= DAC960_IOCTL,
-	.revalidate_disk= DAC960_revalidate,
+	.owner		=THIS_MODULE,
+	.open		=DAC960_Open,
+	.release	=DAC960_Release,
+	.ioctl		=DAC960_IOCTL,
+	.revalidate_disk=DAC960_revalidate,
 };
 
 
@@ -98,14 +88,6 @@ static PROC_DirectoryEntry_T
   *DAC960_ProcDirectoryEntry;
 
 
-/*
-  DAC960_NotifierBlock is the Notifier Block structure for DAC960 Driver.
-*/
-
-static NotifierBlock_T
-  DAC960_NotifierBlock =    { DAC960_Notifier, NULL, 0 };
-
-
 /*
   DAC960_AnnounceDriver announces the Driver Version and Date, Author's Name,
   Copyright Notice, and Electronic Mail Address.
@@ -144,6 +126,54 @@ static boolean DAC960_Failure(DAC960_Controller_T *Controller,
   return false;
 }
 
+/*
+  init_dma_loaf() and slice_dma_loaf() are helper functions for
+  aggregating the dma-mapped memory for a well-known collection of
+  data structures that are of different lengths.
+
+  These routines don't guarantee any alignment.  The caller must
+  include any space needed for alignment in the sizes of the structures
+  that are passed in.
+ */
+
+static boolean init_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf,
+								 size_t len)
+{
+	void *cpu_addr;
+	dma_addr_t dma_handle;
+
+	cpu_addr = pci_alloc_consistent(dev, len, &dma_handle);
+	if (cpu_addr == NULL)
+		return false;
+	
+	loaf->cpu_free = loaf->cpu_base = cpu_addr;
+	loaf->dma_free =loaf->dma_base = dma_handle;
+	loaf->length = len;
+	memset(cpu_addr, 0, len);
+	return true;
+}
+
+static void *slice_dma_loaf(struct dma_loaf *loaf, size_t len,
+					dma_addr_t *dma_handle)
+{
+	void *cpu_end = loaf->cpu_free + len;
+	void *cpu_addr = loaf->cpu_free;
+
+	if (cpu_end > loaf->cpu_base + loaf->length)
+		BUG();
+	*dma_handle = loaf->dma_free;
+	loaf->cpu_free = cpu_end;
+	loaf->dma_free += len;
+	return cpu_addr;
+}
+
+static void free_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf_handle)
+{
+	if (loaf_handle->cpu_base != NULL)
+		pci_free_consistent(dev, loaf_handle->length,
+			loaf_handle->cpu_base, loaf_handle->dma_base);
+}
+
 
 /*
   DAC960_CreateAuxiliaryStructures allocates and initializes the auxiliary
@@ -156,15 +186,42 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
   int CommandAllocationLength, CommandAllocationGroupSize;
   int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount;
   void *AllocationPointer = NULL;
+  void *ScatterGatherCPU = NULL;
+  dma_addr_t ScatterGatherDMA;
+  struct pci_pool *ScatterGatherPool;
+  void *RequestSenseCPU = NULL;
+  dma_addr_t RequestSenseDMA;
+  struct pci_pool *RequestSensePool = NULL;
+
   if (Controller->FirmwareType == DAC960_V1_Controller)
     {
       CommandAllocationLength = offsetof(DAC960_Command_T, V1.EndMarker);
       CommandAllocationGroupSize = DAC960_V1_CommandAllocationGroupSize;
+      ScatterGatherPool = pci_pool_create("DAC960_V1_ScatterGather",
+		Controller->PCIDevice,
+	DAC960_V1_ScatterGatherLimit * sizeof(DAC960_V1_ScatterGatherSegment_T),
+	sizeof(DAC960_V1_ScatterGatherSegment_T), 0);
+      if (ScatterGatherPool == NULL)
+	    return DAC960_Failure(Controller,
+			"AUXILIARY STRUCTURE CREATION (SG)");
+      Controller->ScatterGatherPool = ScatterGatherPool;
     }
   else
     {
       CommandAllocationLength = offsetof(DAC960_Command_T, V2.EndMarker);
       CommandAllocationGroupSize = DAC960_V2_CommandAllocationGroupSize;
+      ScatterGatherPool = pci_pool_create("DAC960_V2_ScatterGather",
+		Controller->PCIDevice,
+	DAC960_V2_ScatterGatherLimit * sizeof(DAC960_V2_ScatterGatherSegment_T),
+	sizeof(DAC960_V2_ScatterGatherSegment_T), 0);
+      RequestSensePool = pci_pool_create("DAC960_V2_RequestSense",
+		Controller->PCIDevice, sizeof(DAC960_SCSI_RequestSense_T),
+		sizeof(int), 0);
+      if (ScatterGatherPool == NULL || RequestSensePool == NULL)
+	    return DAC960_Failure(Controller,
+			"AUXILIARY STRUCTURE CREATION (SG)");
+      Controller->ScatterGatherPool = ScatterGatherPool;
+      Controller->V2.RequestSensePool = RequestSensePool;
     }
   Controller->CommandAllocationGroupSize = CommandAllocationGroupSize;
   Controller->FreeCommands = NULL;
@@ -176,16 +233,17 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
       if (--CommandsRemaining <= 0)
 	{
 	  CommandsRemaining =
-	    Controller->DriverQueueDepth - CommandIdentifier + 1;
+		Controller->DriverQueueDepth - CommandIdentifier + 1;
 	  if (CommandsRemaining > CommandAllocationGroupSize)
-	    CommandsRemaining = CommandAllocationGroupSize;
+		CommandsRemaining = CommandAllocationGroupSize;
 	  CommandGroupByteCount =
-	    CommandsRemaining * CommandAllocationLength;
+		CommandsRemaining * CommandAllocationLength;
 	  AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC);
 	  if (AllocationPointer == NULL)
-	    return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION");
+		return DAC960_Failure(Controller,
+					"AUXILIARY STRUCTURE CREATION");
 	  memset(AllocationPointer, 0, CommandGroupByteCount);
-	}
+	 }
       Command = (DAC960_Command_T *) AllocationPointer;
       AllocationPointer += CommandAllocationLength;
       Command->CommandIdentifier = CommandIdentifier;
@@ -193,6 +251,33 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
       Command->Next = Controller->FreeCommands;
       Controller->FreeCommands = Command;
       Controller->Commands[CommandIdentifier-1] = Command;
+      ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, SLAB_ATOMIC,
+							&ScatterGatherDMA);
+      if (ScatterGatherCPU == NULL)
+	  return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION");
+
+      if (RequestSensePool != NULL) {
+  	  RequestSenseCPU = pci_pool_alloc(RequestSensePool, SLAB_ATOMIC,
+						&RequestSenseDMA);
+  	  if (RequestSenseCPU == NULL) {
+                pci_pool_free(ScatterGatherPool, ScatterGatherCPU,
+                                ScatterGatherDMA);
+    		return DAC960_Failure(Controller,
+					"AUXILIARY STRUCTURE CREATION");
+	  }
+        }
+     if (Controller->FirmwareType == DAC960_V1_Controller) {
+	Command->V1.ScatterGatherList =
+		(DAC960_V1_ScatterGatherSegment_T *)ScatterGatherCPU;
+	Command->V1.ScatterGatherListDMA = ScatterGatherDMA;
+      } else {
+	Command->V2.ScatterGatherList =
+		(DAC960_V2_ScatterGatherSegment_T *)ScatterGatherCPU;
+	Command->V2.ScatterGatherListDMA = ScatterGatherDMA;
+	Command->V2.RequestSense =
+				(DAC960_SCSI_RequestSense_T *)RequestSenseCPU;
+	Command->V2.RequestSenseDMA = RequestSenseDMA;
+      }
     }
   return true;
 }
@@ -206,29 +291,80 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
 static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller)
 {
   int i;
+  struct pci_pool *ScatterGatherPool = Controller->ScatterGatherPool;
+  struct pci_pool *RequestSensePool = NULL;
+  void *ScatterGatherCPU;
+  dma_addr_t ScatterGatherDMA;
+  void *RequestSenseCPU;
+  dma_addr_t RequestSenseDMA;
+  DAC960_Command_T *CommandGroup = NULL;
+  
+
+  if (Controller->FirmwareType == DAC960_V2_Controller)
+        RequestSensePool = Controller->V2.RequestSensePool;
+
   Controller->FreeCommands = NULL;
   for (i = 0; i < Controller->DriverQueueDepth; i++)
     {
       DAC960_Command_T *Command = Controller->Commands[i];
-      if (Command != NULL &&
-	  (Command->CommandIdentifier
-	   % Controller->CommandAllocationGroupSize) == 1)
-	kfree(Command);
+
+      if (Command == NULL)
+	  continue;
+
+      if (Controller->FirmwareType == DAC960_V1_Controller) {
+	  ScatterGatherCPU = (void *)Command->V1.ScatterGatherList;
+	  ScatterGatherDMA = Command->V1.ScatterGatherListDMA;
+	  RequestSenseCPU = NULL;
+	  RequestSenseDMA = (dma_addr_t)0;
+      } else {
+          ScatterGatherCPU = (void *)Command->V2.ScatterGatherList;
+	  ScatterGatherDMA = Command->V2.ScatterGatherListDMA;
+	  RequestSenseCPU = (void *)Command->V2.RequestSense;
+	  RequestSenseDMA = Command->V2.RequestSenseDMA;
+      }
+      if (ScatterGatherCPU != NULL)
+          pci_pool_free(ScatterGatherPool, ScatterGatherCPU, ScatterGatherDMA);
+      if (RequestSenseCPU != NULL)
+          pci_pool_free(RequestSensePool, RequestSenseCPU, RequestSenseDMA);
+
+      if ((Command->CommandIdentifier
+	   % Controller->CommandAllocationGroupSize) == 1) {
+	   /*
+	    * We can't free the group of commands until all of the
+	    * request sense and scatter gather dma structures are free.
+            * Remember the beginning of the group, but don't free it
+	    * until we've reached the beginning of the next group.
+	    */
+	   if (CommandGroup != NULL)
+		kfree(CommandGroup);
+	    CommandGroup = Command;
+      }
       Controller->Commands[i] = NULL;
     }
+  if (CommandGroup != NULL)
+      kfree(CommandGroup);
+
   if (Controller->CombinedStatusBuffer != NULL)
     {
       kfree(Controller->CombinedStatusBuffer);
       Controller->CombinedStatusBuffer = NULL;
       Controller->CurrentStatusBuffer = NULL;
     }
+
+  if (ScatterGatherPool != NULL)
+  	pci_pool_destroy(ScatterGatherPool);
   if (Controller->FirmwareType == DAC960_V1_Controller) return;
+
+  if (RequestSensePool != NULL)
+	pci_pool_destroy(RequestSensePool);
+
   for (i = 0; i < DAC960_MaxLogicalDrives; i++)
     if (Controller->V2.LogicalDeviceInformation[i] != NULL)
       {
 	kfree(Controller->V2.LogicalDeviceInformation[i]);
 	Controller->V2.LogicalDeviceInformation[i] = NULL;
       }
+
   for (i = 0; i < DAC960_V2_MaxPhysicalDevices; i++)
     {
       if (Controller->V2.PhysicalDeviceInformation[i] != NULL)
@@ -297,6 +433,8 @@ static inline DAC960_Command_T *DAC960_AllocateCommand(DAC960_Controller_T
 static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
+
+  Command->Request = NULL;
   Command->Next = Controller->FreeCommands;
   Controller->FreeCommands = Command;
 }
@@ -308,9 +446,9 @@ static inline void DAC960_DeallocateCommand(DAC960_Command_T *Command)
 
 static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
 {
-  spin_unlock_irq(Controller->RequestQueue.queue_lock);
+  spin_unlock_irq(&Controller->queue_lock);
   __wait_event(Controller->CommandWaitQueue, Controller->FreeCommands);
-  spin_lock_irq(Controller->RequestQueue.queue_lock);
+  spin_lock_irq(&Controller->queue_lock);
 }
 
 
@@ -557,7 +695,7 @@ static void DAC960_ExecuteCommand(DAC960_Command_T *Command)
 
 static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller,
 				      DAC960_V1_CommandOpcode_T CommandOpcode,
-				      void *DataPointer)
+				      dma_addr_t DataDMA)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
@@ -565,7 +703,7 @@ static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller,
   DAC960_V1_ClearCommand(Command);
   Command->CommandType = DAC960_ImmediateCommand;
   CommandMailbox->Type3.CommandOpcode = CommandOpcode;
-  CommandMailbox->Type3.BusAddress = Virtual_to_Bus32(DataPointer);
+  CommandMailbox->Type3.BusAddress = DataDMA;
   DAC960_ExecuteCommand(Command);
   CommandStatus = Command->V1.CommandStatus;
   DAC960_DeallocateCommand(Command);
@@ -582,7 +720,7 @@ static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller,
 static boolean DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller,
 				       DAC960_V1_CommandOpcode_T CommandOpcode,
 				       unsigned char CommandOpcode2,
-				       void *DataPointer)
+				       dma_addr_t DataDMA)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
@@ -591,7 +729,7 @@ static boolean DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller,
   Command->CommandType = DAC960_ImmediateCommand;
   CommandMailbox->Type3B.CommandOpcode = CommandOpcode;
   CommandMailbox->Type3B.CommandOpcode2 = CommandOpcode2;
-  CommandMailbox->Type3B.BusAddress = Virtual_to_Bus32(DataPointer);
+  CommandMailbox->Type3B.BusAddress = DataDMA;
   DAC960_ExecuteCommand(Command);
   CommandStatus = Command->V1.CommandStatus;
   DAC960_DeallocateCommand(Command);
@@ -609,7 +747,7 @@ static boolean DAC960_V1_ExecuteType3D(DAC960_Controller_T *Controller,
 				       DAC960_V1_CommandOpcode_T CommandOpcode,
 				       unsigned char Channel,
 				       unsigned char TargetID,
-				       void *DataPointer)
+				       dma_addr_t DataDMA)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
@@ -619,7 +757,7 @@ static boolean DAC960_V1_ExecuteType3D(DAC960_Controller_T *Controller,
   CommandMailbox->Type3D.CommandOpcode = CommandOpcode;
   CommandMailbox->Type3D.Channel = Channel;
   CommandMailbox->Type3D.TargetID = TargetID;
-  CommandMailbox->Type3D.BusAddress = Virtual_to_Bus32(DataPointer);
+  CommandMailbox->Type3D.BusAddress = DataDMA;
   DAC960_ExecuteCommand(Command);
   CommandStatus = Command->V1.CommandStatus;
   DAC960_DeallocateCommand(Command);
@@ -631,12 +769,11 @@ static boolean DAC960_V1_ExecuteType3D(DAC960_Controller_T *Controller,
   DAC960_V2_GeneralInfo executes a DAC960 V2 Firmware General Information
   Reading IOCTL Command and waits for completion.  It returns true on success
   and false on failure.
+
+  Return data in The controller's HealthStatusBuffer, which is dma-able memory
 */
 
-static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller,
-				     DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode,
-				     void *DataPointer,
-				     unsigned int DataByteCount)
+static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
@@ -648,12 +785,12 @@ static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller,
 			.DataTransferControllerToHost = true;
   CommandMailbox->Common.CommandControlBits
 			.NoAutoRequestSense = true;
-  CommandMailbox->Common.DataTransferSize = DataByteCount;
-  CommandMailbox->Common.IOCTL_Opcode = IOCTL_Opcode;
+  CommandMailbox->Common.DataTransferSize = sizeof(DAC960_V2_HealthStatusBuffer_T);
+  CommandMailbox->Common.IOCTL_Opcode = DAC960_V2_GetHealthStatus;
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentDataPointer =
-    Virtual_to_Bus64(DataPointer);
+    Controller->V2.HealthStatusBufferDMA;
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentByteCount =
@@ -669,12 +806,12 @@ static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller,
   DAC960_V2_ControllerInfo executes a DAC960 V2 Firmware Controller
   Information Reading IOCTL Command and waits for completion.  It returns
   true on success and false on failure.
+
+  Data is returned in the controller's V2.NewControllerInformation dma-able
+  memory buffer.
 */
 
-static boolean DAC960_V2_ControllerInfo(DAC960_Controller_T *Controller,
-					DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode,
-					void *DataPointer,
-					unsigned int DataByteCount)
+static boolean DAC960_V2_NewControllerInfo(DAC960_Controller_T *Controller)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
@@ -686,13 +823,13 @@ static boolean DAC960_V2_ControllerInfo(DAC960_Controller_T *Controller,
 				.DataTransferControllerToHost = true;
   CommandMailbox->ControllerInfo.CommandControlBits
 				.NoAutoRequestSense = true;
-  CommandMailbox->ControllerInfo.DataTransferSize = DataByteCount;
+  CommandMailbox->ControllerInfo.DataTransferSize = sizeof(DAC960_V2_ControllerInfo_T);
   CommandMailbox->ControllerInfo.ControllerNumber = 0;
-  CommandMailbox->ControllerInfo.IOCTL_Opcode = IOCTL_Opcode;
+  CommandMailbox->ControllerInfo.IOCTL_Opcode = DAC960_V2_GetControllerInfo;
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentDataPointer =
-    Virtual_to_Bus64(DataPointer);
+    	Controller->V2.NewControllerInformationDMA;
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentByteCount =
@@ -708,34 +845,34 @@ static boolean DAC960_V2_ControllerInfo(DAC960_Controller_T *Controller,
   DAC960_V2_LogicalDeviceInfo executes a DAC960 V2 Firmware Controller Logical
   Device Information Reading IOCTL Command and waits for completion.  It
   returns true on success and false on failure.
+
+  Data is returned in the controller's V2.NewLogicalDeviceInformation
 */
 
-static boolean DAC960_V2_LogicalDeviceInfo(DAC960_Controller_T *Controller,
-					   DAC960_V2_IOCTL_Opcode_T
-					     IOCTL_Opcode,
-					   unsigned short
-					     LogicalDeviceNumber,
-					   void *DataPointer,
-					   unsigned int DataByteCount)
+static boolean DAC960_V2_NewLogicalDeviceInfo(DAC960_Controller_T *Controller,
+					   unsigned short LogicalDeviceNumber)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_CommandStatus_T CommandStatus;
+
   DAC960_V2_ClearCommand(Command);
   Command->CommandType = DAC960_ImmediateCommand;
-  CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
+  CommandMailbox->LogicalDeviceInfo.CommandOpcode =
+				DAC960_V2_IOCTL;
   CommandMailbox->LogicalDeviceInfo.CommandControlBits
 				   .DataTransferControllerToHost = true;
   CommandMailbox->LogicalDeviceInfo.CommandControlBits
 				   .NoAutoRequestSense = true;
-  CommandMailbox->LogicalDeviceInfo.DataTransferSize = DataByteCount;
+  CommandMailbox->LogicalDeviceInfo.DataTransferSize = 
+				sizeof(DAC960_V2_LogicalDeviceInfo_T);
   CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber =
     LogicalDeviceNumber;
-  CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode;
+  CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode = DAC960_V2_GetLogicalDeviceInfoValid;
   CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 				   .ScatterGatherSegments[0]
 				   .SegmentDataPointer =
-    Virtual_to_Bus64(DataPointer);
+    	Controller->V2.NewLogicalDeviceInformationDMA;
   CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 				   .ScatterGatherSegments[0]
 				   .SegmentByteCount =
@@ -748,23 +885,30 @@ static boolean DAC960_V2_LogicalDeviceInfo(DAC960_Controller_T *Controller,
 
 
 /*
-  DAC960_V2_PhysicalDeviceInfo executes a DAC960 V2 Firmware Controller Physical
-  Device Information Reading IOCTL Command and waits for completion.  It
+  DAC960_V2_PhysicalDeviceInfo executes a DAC960 V2 Firmware Controller "Read
+  Physical Device Information" IOCTL Command and waits for completion.  It
   returns true on success and false on failure.
+
+  The Channel, TargetID, LogicalUnit arguments should be 0 the first time
+  this function is called for a given controller.  This will return data
+  for the "first" device on that controller.  The returned data includes a
+  Channel, TargetID, LogicalUnit that can be passed in to this routine to
+  get data for the NEXT device on that controller.
+
+  Data is stored in the controller's V2.NewPhysicalDeviceInfo dma-able
+  memory buffer.
+
 */
 
-static boolean DAC960_V2_PhysicalDeviceInfo(DAC960_Controller_T *Controller,
-					    DAC960_V2_IOCTL_Opcode_T
-					      IOCTL_Opcode,
+static boolean DAC960_V2_NewPhysicalDeviceInfo(DAC960_Controller_T *Controller,
 					    unsigned char Channel,
 					    unsigned char TargetID,
-					    unsigned char LogicalUnit,
-					    void *DataPointer,
-					    unsigned int DataByteCount)
+					    unsigned char LogicalUnit)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_CommandStatus_T CommandStatus;
+
   DAC960_V2_ClearCommand(Command);
   Command->CommandType = DAC960_ImmediateCommand;
   CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
@@ -772,15 +916,17 @@ static boolean DAC960_V2_PhysicalDeviceInfo(DAC960_Controller_T *Controller,
 				    .DataTransferControllerToHost = true;
   CommandMailbox->PhysicalDeviceInfo.CommandControlBits
 				    .NoAutoRequestSense = true;
-  CommandMailbox->PhysicalDeviceInfo.DataTransferSize = DataByteCount;
+  CommandMailbox->PhysicalDeviceInfo.DataTransferSize =
+				sizeof(DAC960_V2_PhysicalDeviceInfo_T);
   CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit = LogicalUnit;
   CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID = TargetID;
   CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel = Channel;
-  CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode = IOCTL_Opcode;
+  CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode =
+					DAC960_V2_GetPhysicalDeviceInfoValid;
   CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 				    .ScatterGatherSegments[0]
 				    .SegmentDataPointer =
-    Virtual_to_Bus64(DataPointer);
+    					Controller->V2.NewPhysicalDeviceInformationDMA;
   CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 				    .ScatterGatherSegments[0]
 				    .SegmentByteCount =
@@ -792,6 +938,75 @@ static boolean DAC960_V2_PhysicalDeviceInfo(DAC960_Controller_T *Controller,
 }
 
 
+static void DAC960_V2_ConstructNewUnitSerialNumber(
+	DAC960_Controller_T *Controller,
+	DAC960_V2_CommandMailbox_T *CommandMailbox, int Channel, int TargetID,
+	int LogicalUnit)
+{
+      CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10_Passthru;
+      CommandMailbox->SCSI_10.CommandControlBits
+			     .DataTransferControllerToHost = true;
+      CommandMailbox->SCSI_10.CommandControlBits
+			     .NoAutoRequestSense = true;
+      CommandMailbox->SCSI_10.DataTransferSize =
+	sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+      CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = LogicalUnit;
+      CommandMailbox->SCSI_10.PhysicalDevice.TargetID = TargetID;
+      CommandMailbox->SCSI_10.PhysicalDevice.Channel = Channel;
+      CommandMailbox->SCSI_10.CDBLength = 6;
+      CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */
+      CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */
+      CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */
+      CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */
+      CommandMailbox->SCSI_10.SCSI_CDB[4] =
+	sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+      CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */
+      CommandMailbox->SCSI_10.DataTransferMemoryAddress
+			     .ScatterGatherSegments[0]
+			     .SegmentDataPointer =
+		Controller->V2.NewInquiryUnitSerialNumberDMA;
+      CommandMailbox->SCSI_10.DataTransferMemoryAddress
+			     .ScatterGatherSegments[0]
+			     .SegmentByteCount =
+		CommandMailbox->SCSI_10.DataTransferSize;
+}
+
+
+/*
+  DAC960_V2_NewUnitSerialNumber executes an SCSI pass-through
+  Inquiry command to a SCSI device identified by Channel number,
+  Target id, Logical Unit Number.  This function Waits for completion
+  of the command.
+
+  The return data includes Unit Serial Number information for the
+  specified device.
+
+  Data is stored in the controller's V2.NewPhysicalDeviceInfo dma-able
+  memory buffer.
+*/
+
+static boolean DAC960_V2_NewInquiryUnitSerialNumber(DAC960_Controller_T *Controller,
+			int Channel, int TargetID, int LogicalUnit)
+{
+      DAC960_Command_T *Command;
+      DAC960_V2_CommandMailbox_T *CommandMailbox;
+      DAC960_V2_CommandStatus_T CommandStatus;
+
+      Command = DAC960_AllocateCommand(Controller);
+      CommandMailbox = &Command->V2.CommandMailbox;
+      DAC960_V2_ClearCommand(Command);
+      Command->CommandType = DAC960_ImmediateCommand;
+
+      DAC960_V2_ConstructNewUnitSerialNumber(Controller, CommandMailbox,
+			Channel, TargetID, LogicalUnit);
+
+      DAC960_ExecuteCommand(Command);
+      CommandStatus = Command->V2.CommandStatus;
+      DAC960_DeallocateCommand(Command);
+      return (CommandStatus == DAC960_V2_NormalCompletion);
+}
+
+
 /*
   DAC960_V2_DeviceOperation executes a DAC960 V2 Firmware Controller Device
   Operation IOCTL Command and waits for completion.  It returns true on
@@ -825,84 +1040,144 @@ static boolean DAC960_V2_DeviceOperation(DAC960_Controller_T *Controller,
 /*
   DAC960_V1_EnableMemoryMailboxInterface enables the Memory Mailbox Interface
   for DAC960 V1 Firmware Controllers.
+
+  PD and P controller types have no memory mailbox, but still need the
+  other dma mapped memory.
 */
 
 static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
 						      *Controller)
 {
   void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_HardwareType_T hw_type = Controller->HardwareType;
+  PCI_Device_T	*PCI_Device = Controller->PCIDevice;
+  struct dma_loaf *DmaPages = &Controller->DmaPages;
+  size_t DmaPagesSize;
+  size_t CommandMailboxesSize;
+  size_t StatusMailboxesSize;
+
   DAC960_V1_CommandMailbox_T *CommandMailboxesMemory;
+  dma_addr_t CommandMailboxesMemoryDMA;
+
   DAC960_V1_StatusMailbox_T *StatusMailboxesMemory;
+  dma_addr_t StatusMailboxesMemoryDMA;
+
   DAC960_V1_CommandMailbox_T CommandMailbox;
   DAC960_V1_CommandStatus_T CommandStatus;
-  unsigned long MemoryMailboxPagesAddress;
-  unsigned long MemoryMailboxPagesOrder;
-  unsigned long MemoryMailboxPagesSize;
-  void *SavedMemoryMailboxesAddress = NULL;
-  short NextCommandMailboxIndex = 0;
-  short NextStatusMailboxIndex = 0;
-  int TimeoutCounter = 1000000, i;
-  MemoryMailboxPagesOrder = 0;
-  MemoryMailboxPagesSize =
-    DAC960_V1_CommandMailboxCount * sizeof(DAC960_V1_CommandMailbox_T) +
-    DAC960_V1_StatusMailboxCount * sizeof(DAC960_V1_StatusMailbox_T);
-  while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder)
-    MemoryMailboxPagesOrder++;
-  if (Controller->HardwareType == DAC960_LA_Controller)
-    DAC960_LA_RestoreMemoryMailboxInfo(Controller,
-				       &SavedMemoryMailboxesAddress,
-				       &NextCommandMailboxIndex,
-				       &NextStatusMailboxIndex);
-  else DAC960_PG_RestoreMemoryMailboxInfo(Controller,
-					  &SavedMemoryMailboxesAddress,
-					  &NextCommandMailboxIndex,
-					  &NextStatusMailboxIndex);
-  if (SavedMemoryMailboxesAddress == NULL)
-    {
-      MemoryMailboxPagesAddress =
-	__get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder);
-      Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress;
-      CommandMailboxesMemory =
-	(DAC960_V1_CommandMailbox_T *) MemoryMailboxPagesAddress;
-    }
-  else CommandMailboxesMemory = SavedMemoryMailboxesAddress;
-  if (CommandMailboxesMemory == NULL) return false;
-  Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder;
-  memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize);
+  int TimeoutCounter;
+  int i;
+
+  
+  if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V1_PciDmaMask))
+	return DAC960_Failure(Controller, "DMA mask out of range");
+
+  if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) {
+    CommandMailboxesSize =  0;
+    StatusMailboxesSize = 0;
+  } else {
+    CommandMailboxesSize =  DAC960_V1_CommandMailboxCount * sizeof(DAC960_V1_CommandMailbox_T);
+    StatusMailboxesSize = DAC960_V1_StatusMailboxCount * sizeof(DAC960_V1_StatusMailbox_T);
+  }
+  DmaPagesSize = CommandMailboxesSize + StatusMailboxesSize + 
+	sizeof(DAC960_V1_DCDB_T) + sizeof(DAC960_V1_Enquiry_T) +
+	sizeof(DAC960_V1_ErrorTable_T) + sizeof(DAC960_V1_EventLogEntry_T) +
+	sizeof(DAC960_V1_RebuildProgress_T) +
+	sizeof(DAC960_V1_LogicalDriveInformationArray_T) +
+	sizeof(DAC960_V1_BackgroundInitializationStatus_T) +
+	sizeof(DAC960_V1_DeviceState_T) + sizeof(DAC960_SCSI_Inquiry_T) +
+	sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
+
+  if (!init_dma_loaf(PCI_Device, DmaPages, DmaPagesSize))
+	return false;
+
+
+  if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) 
+	goto skip_mailboxes;
+
+  CommandMailboxesMemory = slice_dma_loaf(DmaPages,
+                CommandMailboxesSize, &CommandMailboxesMemoryDMA);
+  
+  /* These are the base addresses for the command memory mailbox array */
   Controller->V1.FirstCommandMailbox = CommandMailboxesMemory;
+  Controller->V1.FirstCommandMailboxDMA = CommandMailboxesMemoryDMA;
+
   CommandMailboxesMemory += DAC960_V1_CommandMailboxCount - 1;
   Controller->V1.LastCommandMailbox = CommandMailboxesMemory;
-  Controller->V1.NextCommandMailbox =
-    &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex];
-  if (--NextCommandMailboxIndex < 0)
-    NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1;
-  Controller->V1.PreviousCommandMailbox1 =
-    &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex];
-  if (--NextCommandMailboxIndex < 0)
-    NextCommandMailboxIndex = DAC960_V1_CommandMailboxCount - 1;
+  Controller->V1.NextCommandMailbox = Controller->V1.FirstCommandMailbox;
+  Controller->V1.PreviousCommandMailbox1 = Controller->V1.LastCommandMailbox;
   Controller->V1.PreviousCommandMailbox2 =
-    &Controller->V1.FirstCommandMailbox[NextCommandMailboxIndex];
-  StatusMailboxesMemory =
-    (DAC960_V1_StatusMailbox_T *) (CommandMailboxesMemory + 1);
+	  				Controller->V1.LastCommandMailbox - 1;
+
+  /* These are the base addresses for the status memory mailbox array */
+  StatusMailboxesMemory = slice_dma_loaf(DmaPages,
+                StatusMailboxesSize, &StatusMailboxesMemoryDMA);
+
   Controller->V1.FirstStatusMailbox = StatusMailboxesMemory;
+  Controller->V1.FirstStatusMailboxDMA = StatusMailboxesMemoryDMA;
   StatusMailboxesMemory += DAC960_V1_StatusMailboxCount - 1;
   Controller->V1.LastStatusMailbox = StatusMailboxesMemory;
-  Controller->V1.NextStatusMailbox =
-    &Controller->V1.FirstStatusMailbox[NextStatusMailboxIndex];
-  if (SavedMemoryMailboxesAddress != NULL) return true;
+  Controller->V1.NextStatusMailbox = Controller->V1.FirstStatusMailbox;
+
+skip_mailboxes:
+  Controller->V1.MonitoringDCDB = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_DCDB_T),
+                &Controller->V1.MonitoringDCDB_DMA);
+
+  Controller->V1.NewEnquiry = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_Enquiry_T),
+                &Controller->V1.NewEnquiryDMA);
+
+  Controller->V1.NewErrorTable = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_ErrorTable_T),
+                &Controller->V1.NewErrorTableDMA);
+
+  Controller->V1.EventLogEntry = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_EventLogEntry_T),
+                &Controller->V1.EventLogEntryDMA);
+
+  Controller->V1.RebuildProgress = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_RebuildProgress_T),
+                &Controller->V1.RebuildProgressDMA);
+
+  Controller->V1.NewLogicalDriveInformation = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_LogicalDriveInformationArray_T),
+                &Controller->V1.NewLogicalDriveInformationDMA);
+
+  Controller->V1.BackgroundInitializationStatus = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_BackgroundInitializationStatus_T),
+                &Controller->V1.BackgroundInitializationStatusDMA);
+
+  Controller->V1.NewDeviceState = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V1_DeviceState_T),
+                &Controller->V1.NewDeviceStateDMA);
+
+  Controller->V1.NewInquiryStandardData = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_SCSI_Inquiry_T),
+                &Controller->V1.NewInquiryStandardDataDMA);
+
+  Controller->V1.NewInquiryUnitSerialNumber = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T),
+                &Controller->V1.NewInquiryUnitSerialNumberDMA);
+
+  if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller))
+	return true;
+ 
   /* Enable the Memory Mailbox Interface. */
   Controller->V1.DualModeMemoryMailboxInterface = true;
   CommandMailbox.TypeX.CommandOpcode = 0x2B;
   CommandMailbox.TypeX.CommandIdentifier = 0;
   CommandMailbox.TypeX.CommandOpcode2 = 0x14;
   CommandMailbox.TypeX.CommandMailboxesBusAddress =
-    Virtual_to_Bus32(Controller->V1.FirstCommandMailbox);
+    				Controller->V1.FirstCommandMailboxDMA;
   CommandMailbox.TypeX.StatusMailboxesBusAddress =
-    Virtual_to_Bus32(Controller->V1.FirstStatusMailbox);
+    				Controller->V1.FirstStatusMailboxDMA;
+#define TIMEOUT_COUNT 1000000
+
   for (i = 0; i < 2; i++)
     switch (Controller->HardwareType)
       {
       case DAC960_LA_Controller:
+	TimeoutCounter = TIMEOUT_COUNT;
 	while (--TimeoutCounter >= 0)
 	  {
 	    if (!DAC960_LA_HardwareMailboxFullP(ControllerBaseAddress))
@@ -912,6 +1187,7 @@ static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
 	if (TimeoutCounter < 0) return false;
 	DAC960_LA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
 	DAC960_LA_HardwareMailboxNewCommand(ControllerBaseAddress);
+	TimeoutCounter = TIMEOUT_COUNT;
 	while (--TimeoutCounter >= 0)
 	  {
 	    if (DAC960_LA_HardwareMailboxStatusAvailableP(
@@ -928,6 +1204,7 @@ static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
 	CommandMailbox.TypeX.CommandOpcode2 = 0x10;
 	break;
       case DAC960_PG_Controller:
+	TimeoutCounter = TIMEOUT_COUNT;
 	while (--TimeoutCounter >= 0)
 	  {
 	    if (!DAC960_PG_HardwareMailboxFullP(ControllerBaseAddress))
@@ -937,6 +1214,8 @@ static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
 	if (TimeoutCounter < 0) return false;
 	DAC960_PG_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
 	DAC960_PG_HardwareMailboxNewCommand(ControllerBaseAddress);
+
+	TimeoutCounter = TIMEOUT_COUNT;
 	while (--TimeoutCounter >= 0)
 	  {
 	    if (DAC960_PG_HardwareMailboxStatusAvailableP(
@@ -953,6 +1232,7 @@ static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
 	CommandMailbox.TypeX.CommandOpcode2 = 0x10;
 	break;
       default:
+        DAC960_Failure(Controller, "Unknown Controller Type\n");
 	break;
       }
   return false;
@@ -962,75 +1242,146 @@ static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
 /*
   DAC960_V2_EnableMemoryMailboxInterface enables the Memory Mailbox Interface
   for DAC960 V2 Firmware Controllers.
+
+  Aggregate the space needed for the controller's memory mailbox and
+  the other data structures that will be targets of dma transfers with
+  the controller.  Allocate a dma-mapped region of memory to hold these
+  structures.  Then, save CPU pointers and dma_addr_t values to reference
+  the structures that are contained in that region.
 */
 
 static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
 						      *Controller)
 {
   void *ControllerBaseAddress = Controller->BaseAddress;
+  PCI_Device_T	*PCI_Device = Controller->PCIDevice;
+  struct dma_loaf *DmaPages = &Controller->DmaPages;
+  size_t DmaPagesSize;
+  size_t CommandMailboxesSize;
+  size_t StatusMailboxesSize;
+
   DAC960_V2_CommandMailbox_T *CommandMailboxesMemory;
+  dma_addr_t CommandMailboxesMemoryDMA;
+
   DAC960_V2_StatusMailbox_T *StatusMailboxesMemory;
-  DAC960_V2_CommandMailbox_T CommandMailbox;
-  DAC960_V2_CommandStatus_T CommandStatus = 0;
-  unsigned long MemoryMailboxPagesAddress;
-  unsigned long MemoryMailboxPagesOrder;
-  unsigned long MemoryMailboxPagesSize;
-  MemoryMailboxPagesOrder = 0;
-  MemoryMailboxPagesSize =
-    DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T) +
-    DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T) +
-    sizeof(DAC960_V2_HealthStatusBuffer_T);
-  while (MemoryMailboxPagesSize > PAGE_SIZE << MemoryMailboxPagesOrder)
-    MemoryMailboxPagesOrder++;
-  MemoryMailboxPagesAddress =
-    __get_free_pages(GFP_KERNEL, MemoryMailboxPagesOrder);
-  Controller->MemoryMailboxPagesAddress = MemoryMailboxPagesAddress;
-  CommandMailboxesMemory =
-    (DAC960_V2_CommandMailbox_T *) MemoryMailboxPagesAddress;
-  if (CommandMailboxesMemory == NULL) return false;
-  Controller->MemoryMailboxPagesOrder = MemoryMailboxPagesOrder;
-  memset(CommandMailboxesMemory, 0, MemoryMailboxPagesSize);
+  dma_addr_t StatusMailboxesMemoryDMA;
+
+  DAC960_V2_CommandMailbox_T *CommandMailbox;
+  dma_addr_t	CommandMailboxDMA;
+  DAC960_V2_CommandStatus_T CommandStatus;
+
+  if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V2_PciDmaMask))
+	return DAC960_Failure(Controller, "DMA mask out of range");
+
+  /* This is a temporary dma mapping, used only in the scope of this function */
+  CommandMailbox =
+	  (DAC960_V2_CommandMailbox_T *)pci_alloc_consistent( PCI_Device,
+		sizeof(DAC960_V2_CommandMailbox_T), &CommandMailboxDMA);
+  if (CommandMailbox == NULL)
+	  return false;
+
+  CommandMailboxesSize = DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T);
+  StatusMailboxesSize = DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T);
+  DmaPagesSize =
+    CommandMailboxesSize + StatusMailboxesSize +
+    sizeof(DAC960_V2_HealthStatusBuffer_T) +
+    sizeof(DAC960_V2_ControllerInfo_T) +
+    sizeof(DAC960_V2_LogicalDeviceInfo_T) +
+    sizeof(DAC960_V2_PhysicalDeviceInfo_T) +
+    sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T) +
+    sizeof(DAC960_V2_Event_T) +
+    sizeof(DAC960_V2_PhysicalToLogicalDevice_T);
+
+  if (!init_dma_loaf(PCI_Device, DmaPages, DmaPagesSize)) {
+  	pci_free_consistent(PCI_Device, sizeof(DAC960_V2_CommandMailbox_T),
+					CommandMailbox, CommandMailboxDMA);
+	return false;
+  }
+
+  CommandMailboxesMemory = slice_dma_loaf(DmaPages,
+		CommandMailboxesSize, &CommandMailboxesMemoryDMA);
+
+  /* These are the base addresses for the command memory mailbox array */
   Controller->V2.FirstCommandMailbox = CommandMailboxesMemory;
+  Controller->V2.FirstCommandMailboxDMA = CommandMailboxesMemoryDMA;
+
   CommandMailboxesMemory += DAC960_V2_CommandMailboxCount - 1;
   Controller->V2.LastCommandMailbox = CommandMailboxesMemory;
   Controller->V2.NextCommandMailbox = Controller->V2.FirstCommandMailbox;
   Controller->V2.PreviousCommandMailbox1 = Controller->V2.LastCommandMailbox;
   Controller->V2.PreviousCommandMailbox2 =
-    Controller->V2.LastCommandMailbox - 1;
-  StatusMailboxesMemory =
-    (DAC960_V2_StatusMailbox_T *) (CommandMailboxesMemory + 1);
+    					Controller->V2.LastCommandMailbox - 1;
+
+  /* These are the base addresses for the status memory mailbox array */
+  StatusMailboxesMemory = slice_dma_loaf(DmaPages,
+		StatusMailboxesSize, &StatusMailboxesMemoryDMA);
+
   Controller->V2.FirstStatusMailbox = StatusMailboxesMemory;
+  Controller->V2.FirstStatusMailboxDMA = StatusMailboxesMemoryDMA;
   StatusMailboxesMemory += DAC960_V2_StatusMailboxCount - 1;
   Controller->V2.LastStatusMailbox = StatusMailboxesMemory;
   Controller->V2.NextStatusMailbox = Controller->V2.FirstStatusMailbox;
-  Controller->V2.HealthStatusBuffer =
-    (DAC960_V2_HealthStatusBuffer_T *) (StatusMailboxesMemory + 1);
-  /* Enable the Memory Mailbox Interface. */
-  memset(&CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T));
-  CommandMailbox.SetMemoryMailbox.CommandIdentifier = 1;
-  CommandMailbox.SetMemoryMailbox.CommandOpcode = DAC960_V2_IOCTL;
-  CommandMailbox.SetMemoryMailbox.CommandControlBits.NoAutoRequestSense = true;
-  CommandMailbox.SetMemoryMailbox.FirstCommandMailboxSizeKB =
+
+  Controller->V2.HealthStatusBuffer = slice_dma_loaf(DmaPages,
+		sizeof(DAC960_V2_HealthStatusBuffer_T),
+		&Controller->V2.HealthStatusBufferDMA);
+
+  Controller->V2.NewControllerInformation = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V2_ControllerInfo_T), 
+                &Controller->V2.NewControllerInformationDMA);
+
+  Controller->V2.NewLogicalDeviceInformation =  slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V2_LogicalDeviceInfo_T),
+                &Controller->V2.NewLogicalDeviceInformationDMA);
+
+  Controller->V2.NewPhysicalDeviceInformation = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V2_PhysicalDeviceInfo_T),
+                &Controller->V2.NewPhysicalDeviceInformationDMA);
+
+  Controller->V2.NewInquiryUnitSerialNumber = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T),
+                &Controller->V2.NewInquiryUnitSerialNumberDMA);
+
+  Controller->V2.Event = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V2_Event_T),
+                &Controller->V2.EventDMA);
+
+  Controller->V2.PhysicalToLogicalDevice = slice_dma_loaf(DmaPages,
+                sizeof(DAC960_V2_PhysicalToLogicalDevice_T),
+                &Controller->V2.PhysicalToLogicalDeviceDMA);
+
+  /*
+    Enable the Memory Mailbox Interface.
+    
+    I don't know why we can't just use one of the memory mailboxes
+    we just allocated to do this, instead of using this temporary one.
+    Try this change later.
+  */
+  memset(CommandMailbox, 0, sizeof(DAC960_V2_CommandMailbox_T));
+  CommandMailbox->SetMemoryMailbox.CommandIdentifier = 1;
+  CommandMailbox->SetMemoryMailbox.CommandOpcode = DAC960_V2_IOCTL;
+  CommandMailbox->SetMemoryMailbox.CommandControlBits.NoAutoRequestSense = true;
+  CommandMailbox->SetMemoryMailbox.FirstCommandMailboxSizeKB =
     (DAC960_V2_CommandMailboxCount * sizeof(DAC960_V2_CommandMailbox_T)) >> 10;
-  CommandMailbox.SetMemoryMailbox.FirstStatusMailboxSizeKB =
+  CommandMailbox->SetMemoryMailbox.FirstStatusMailboxSizeKB =
     (DAC960_V2_StatusMailboxCount * sizeof(DAC960_V2_StatusMailbox_T)) >> 10;
-  CommandMailbox.SetMemoryMailbox.SecondCommandMailboxSizeKB = 0;
-  CommandMailbox.SetMemoryMailbox.SecondStatusMailboxSizeKB = 0;
-  CommandMailbox.SetMemoryMailbox.RequestSenseSize = 0;
-  CommandMailbox.SetMemoryMailbox.IOCTL_Opcode = DAC960_V2_SetMemoryMailbox;
-  CommandMailbox.SetMemoryMailbox.HealthStatusBufferSizeKB = 1;
-  CommandMailbox.SetMemoryMailbox.HealthStatusBufferBusAddress =
-    Virtual_to_Bus64(Controller->V2.HealthStatusBuffer);
-  CommandMailbox.SetMemoryMailbox.FirstCommandMailboxBusAddress =
-    Virtual_to_Bus64(Controller->V2.FirstCommandMailbox);
-  CommandMailbox.SetMemoryMailbox.FirstStatusMailboxBusAddress =
-    Virtual_to_Bus64(Controller->V2.FirstStatusMailbox);
+  CommandMailbox->SetMemoryMailbox.SecondCommandMailboxSizeKB = 0;
+  CommandMailbox->SetMemoryMailbox.SecondStatusMailboxSizeKB = 0;
+  CommandMailbox->SetMemoryMailbox.RequestSenseSize = 0;
+  CommandMailbox->SetMemoryMailbox.IOCTL_Opcode = DAC960_V2_SetMemoryMailbox;
+  CommandMailbox->SetMemoryMailbox.HealthStatusBufferSizeKB = 1;
+  CommandMailbox->SetMemoryMailbox.HealthStatusBufferBusAddress =
+    					Controller->V2.HealthStatusBufferDMA;
+  CommandMailbox->SetMemoryMailbox.FirstCommandMailboxBusAddress =
+    					Controller->V2.FirstCommandMailboxDMA;
+  CommandMailbox->SetMemoryMailbox.FirstStatusMailboxBusAddress =
+    					Controller->V2.FirstStatusMailboxDMA;
   switch (Controller->HardwareType)
     {
     case DAC960_BA_Controller:
       while (DAC960_BA_HardwareMailboxFullP(ControllerBaseAddress))
 	udelay(1);
-      DAC960_BA_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
+      DAC960_BA_WriteHardwareMailbox(ControllerBaseAddress, CommandMailboxDMA);
       DAC960_BA_HardwareMailboxNewCommand(ControllerBaseAddress);
       while (!DAC960_BA_HardwareMailboxStatusAvailableP(ControllerBaseAddress))
 	udelay(1);
@@ -1041,7 +1392,7 @@ static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
     case DAC960_LP_Controller:
       while (DAC960_LP_HardwareMailboxFullP(ControllerBaseAddress))
 	udelay(1);
-      DAC960_LP_WriteHardwareMailbox(ControllerBaseAddress, &CommandMailbox);
+      DAC960_LP_WriteHardwareMailbox(ControllerBaseAddress, CommandMailboxDMA);
       DAC960_LP_HardwareMailboxNewCommand(ControllerBaseAddress);
       while (!DAC960_LP_HardwareMailboxStatusAvailableP(ControllerBaseAddress))
 	udelay(1);
@@ -1050,8 +1401,12 @@ static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
       DAC960_LP_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
       break;
     default:
+      DAC960_Failure(Controller, "Unknown Controller Type\n");
+      CommandStatus = DAC960_V2_AbormalCompletion;
       break;
     }
+  pci_free_consistent(PCI_Device, sizeof(DAC960_V2_CommandMailbox_T),
+					CommandMailbox, CommandMailboxDMA);
   return (CommandStatus == DAC960_V2_NormalCompletion);
 }
 
@@ -1064,33 +1419,65 @@ static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
 static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
 						     *Controller)
 {
-  DAC960_V1_Enquiry2_T Enquiry2;
-  DAC960_V1_Config2_T Config2;
+  DAC960_V1_Enquiry2_T *Enquiry2;
+  dma_addr_t Enquiry2DMA;
+  DAC960_V1_Config2_T *Config2;
+  dma_addr_t Config2DMA;
   int LogicalDriveNumber, Channel, TargetID;
+  struct dma_loaf local_dma;
+
+  if (!init_dma_loaf(Controller->PCIDevice, &local_dma,
+		sizeof(DAC960_V1_Enquiry2_T) + sizeof(DAC960_V1_Config2_T)))
+	return DAC960_Failure(Controller, "LOGICAL DEVICE ALLOCATION");
+
+  Enquiry2 = slice_dma_loaf(&local_dma, sizeof(DAC960_V1_Enquiry2_T), &Enquiry2DMA);
+  Config2 = slice_dma_loaf(&local_dma, sizeof(DAC960_V1_Config2_T), &Config2DMA);
+
   if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry,
-			      &Controller->V1.Enquiry))
+			      Controller->V1.NewEnquiryDMA)) {
+    free_dma_loaf(Controller->PCIDevice, &local_dma);
     return DAC960_Failure(Controller, "ENQUIRY");
-  if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry2, &Enquiry2))
+  }
+  memcpy(&Controller->V1.Enquiry, Controller->V1.NewEnquiry,
+						sizeof(DAC960_V1_Enquiry_T));
+
+  if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_Enquiry2, Enquiry2DMA)) {
+    free_dma_loaf(Controller->PCIDevice, &local_dma);
     return DAC960_Failure(Controller, "ENQUIRY2");
-  if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_ReadConfig2, &Config2))
+  }
+
+  if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_ReadConfig2, Config2DMA)) {
+    free_dma_loaf(Controller->PCIDevice, &local_dma);
     return DAC960_Failure(Controller, "READ CONFIG2");
+  }
+
   if (!DAC960_V1_ExecuteType3(Controller, DAC960_V1_GetLogicalDriveInformation,
-			      &Controller->V1.LogicalDriveInformation))
+			      Controller->V1.NewLogicalDriveInformationDMA)) {
+    free_dma_loaf(Controller->PCIDevice, &local_dma);
     return DAC960_Failure(Controller, "GET LOGICAL DRIVE INFORMATION");
-  for (Channel = 0; Channel < Enquiry2.ActualChannels; Channel++)
-    for (TargetID = 0; TargetID < Enquiry2.MaxTargets; TargetID++)
+  }
+  memcpy(&Controller->V1.LogicalDriveInformation,
+		Controller->V1.NewLogicalDriveInformation,
+		sizeof(DAC960_V1_LogicalDriveInformationArray_T));
+
+  for (Channel = 0; Channel < Enquiry2->ActualChannels; Channel++)
+    for (TargetID = 0; TargetID < Enquiry2->MaxTargets; TargetID++) {
       if (!DAC960_V1_ExecuteType3D(Controller, DAC960_V1_GetDeviceState,
 				   Channel, TargetID,
-				   &Controller->V1.DeviceState
-						   [Channel][TargetID]))
-	return DAC960_Failure(Controller, "GET DEVICE STATE");
+				   Controller->V1.NewDeviceStateDMA)) {
+    		free_dma_loaf(Controller->PCIDevice, &local_dma);
+		return DAC960_Failure(Controller, "GET DEVICE STATE");
+	}
+	memcpy(&Controller->V1.DeviceState[Channel][TargetID],
+		Controller->V1.NewDeviceState, sizeof(DAC960_V1_DeviceState_T));
+     }
   /*
     Initialize the Controller Model Name and Full Model Name fields.
   */
-  switch (Enquiry2.HardwareID.SubModel)
+  switch (Enquiry2->HardwareID.SubModel)
     {
     case DAC960_V1_P_PD_PU:
-      if (Enquiry2.SCSICapability.BusSpeed == DAC960_V1_Ultra)
+      if (Enquiry2->SCSICapability.BusSpeed == DAC960_V1_Ultra)
 	strcpy(Controller->ModelName, "DAC960PU");
       else strcpy(Controller->ModelName, "DAC960PD");
       break;
@@ -1122,6 +1509,7 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
       strcpy(Controller->ModelName, "DAC1164P");
       break;
     default:
+      free_dma_loaf(Controller->PCIDevice, &local_dma);
       return DAC960_Failure(Controller, "MODEL VERIFICATION");
     }
   strcpy(Controller->FullModelName, "Mylex ");
@@ -1135,18 +1523,18 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
     DAC960PU/PD/PL	    3.51 and above
     DAC960PU/PD/PL/P	    2.73 and above
   */
-  if (Enquiry2.FirmwareID.MajorVersion == 0)
+  if (Enquiry2->FirmwareID.MajorVersion == 0)
     {
-      Enquiry2.FirmwareID.MajorVersion =
+      Enquiry2->FirmwareID.MajorVersion =
 	Controller->V1.Enquiry.MajorFirmwareVersion;
-      Enquiry2.FirmwareID.MinorVersion =
+      Enquiry2->FirmwareID.MinorVersion =
 	Controller->V1.Enquiry.MinorFirmwareVersion;
-      Enquiry2.FirmwareID.FirmwareType = '0';
-      Enquiry2.FirmwareID.TurnID = 0;
+      Enquiry2->FirmwareID.FirmwareType = '0';
+      Enquiry2->FirmwareID.TurnID = 0;
     }
   sprintf(Controller->FirmwareVersion, "%d.%02d-%c-%02d",
-	  Enquiry2.FirmwareID.MajorVersion, Enquiry2.FirmwareID.MinorVersion,
-	  Enquiry2.FirmwareID.FirmwareType, Enquiry2.FirmwareID.TurnID);
+	  Enquiry2->FirmwareID.MajorVersion, Enquiry2->FirmwareID.MinorVersion,
+	  Enquiry2->FirmwareID.FirmwareType, Enquiry2->FirmwareID.TurnID);
   if (!((Controller->FirmwareVersion[0] == '5' &&
 	 strcmp(Controller->FirmwareVersion, "5.06") >= 0) ||
 	(Controller->FirmwareVersion[0] == '4' &&
@@ -1159,17 +1547,18 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
       DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION");
       DAC960_Error("Firmware Version = '%s'\n", Controller,
 		   Controller->FirmwareVersion);
+      free_dma_loaf(Controller->PCIDevice, &local_dma);
       return false;
     }
   /*
     Initialize the Controller Channels, Targets, Memory Size, and SAF-TE
     Enclosure Management Enabled fields.
   */
-  Controller->Channels = Enquiry2.ActualChannels;
-  Controller->Targets = Enquiry2.MaxTargets;
-  Controller->MemorySize = Enquiry2.MemorySize >> 20;
+  Controller->Channels = Enquiry2->ActualChannels;
+  Controller->Targets = Enquiry2->MaxTargets;
+  Controller->MemorySize = Enquiry2->MemorySize >> 20;
   Controller->V1.SAFTE_EnclosureManagementEnabled =
-    (Enquiry2.FaultManagementType == DAC960_V1_SAFTE);
+    (Enquiry2->FaultManagementType == DAC960_V1_SAFTE);
   /*
     Initialize the Controller Queue Depth, Driver Queue Depth, Logical Drive
     Count, Maximum Blocks per Command, Controller Scatter/Gather Limit, and
@@ -1183,8 +1572,8 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
     Controller->DriverQueueDepth = DAC960_MaxDriverQueueDepth;
   Controller->LogicalDriveCount =
     Controller->V1.Enquiry.NumberOfLogicalDrives;
-  Controller->MaxBlocksPerCommand = Enquiry2.MaxBlocksPerCommand;
-  Controller->ControllerScatterGatherLimit = Enquiry2.MaxScatterGatherEntries;
+  Controller->MaxBlocksPerCommand = Enquiry2->MaxBlocksPerCommand;
+  Controller->ControllerScatterGatherLimit = Enquiry2->MaxScatterGatherEntries;
   Controller->DriverScatterGatherLimit =
     Controller->ControllerScatterGatherLimit;
   if (Controller->DriverScatterGatherLimit > DAC960_V1_ScatterGatherLimit)
@@ -1192,11 +1581,11 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
   /*
     Initialize the Stripe Size, Segment Size, and Geometry Translation.
   */
-  Controller->V1.StripeSize = Config2.BlocksPerStripe * Config2.BlockFactor
+  Controller->V1.StripeSize = Config2->BlocksPerStripe * Config2->BlockFactor
 			      >> (10 - DAC960_BlockSizeBits);
-  Controller->V1.SegmentSize = Config2.BlocksPerCacheLine * Config2.BlockFactor
+  Controller->V1.SegmentSize = Config2->BlocksPerCacheLine * Config2->BlockFactor
 			       >> (10 - DAC960_BlockSizeBits);
-  switch (Config2.DriveGeometry)
+  switch (Config2->DriveGeometry)
     {
     case DAC960_V1_Geometry_128_32:
       Controller->V1.GeometryTranslationHeads = 128;
@@ -1207,6 +1596,7 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
       Controller->V1.GeometryTranslationSectors = 63;
       break;
     default:
+      free_dma_loaf(Controller->PCIDevice, &local_dma);
       return DAC960_Failure(Controller, "CONFIG2 DRIVE GEOMETRY");
     }
   /*
@@ -1220,8 +1610,11 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
       Controller->V1.BackgroundInitializationStatusSupported = true;
       DAC960_V1_ExecuteType3B(Controller,
 			      DAC960_V1_BackgroundInitializationControl, 0x20,
-			      &Controller->
-			       V1.LastBackgroundInitializationStatus);
+			      Controller->
+			       V1.BackgroundInitializationStatusDMA);
+      memcpy(&Controller->V1.LastBackgroundInitializationStatus,
+		Controller->V1.BackgroundInitializationStatus,
+		sizeof(DAC960_V1_BackgroundInitializationStatus_T));
     }
   /*
     Initialize the Logical Drive Initially Accessible flag.
@@ -1234,6 +1627,7 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
 	DAC960_V1_LogicalDrive_Offline)
       Controller->LogicalDriveInitiallyAccessible[LogicalDriveNumber] = true;
   Controller->V1.LastRebuildStatus = DAC960_V1_NoRebuildOrCheckInProgress;
+  free_dma_loaf(Controller->PCIDevice, &local_dma);
   return true;
 }
 
@@ -1247,17 +1641,20 @@ static boolean DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T
 						     *Controller)
 {
   DAC960_V2_ControllerInfo_T *ControllerInfo =
-    &Controller->V2.ControllerInformation;
+    		&Controller->V2.ControllerInformation;
   unsigned short LogicalDeviceNumber = 0;
   int ModelNameLength;
-  if (!DAC960_V2_ControllerInfo(Controller, DAC960_V2_GetControllerInfo,
-				ControllerInfo,
-				sizeof(DAC960_V2_ControllerInfo_T)))
+
+  /* Get data into dma-able area, then copy into permanant location */
+  if (!DAC960_V2_NewControllerInfo(Controller))
     return DAC960_Failure(Controller, "GET CONTROLLER INFO");
-  if (!DAC960_V2_GeneralInfo(Controller, DAC960_V2_GetHealthStatus,
-			     Controller->V2.HealthStatusBuffer,
-			     sizeof(DAC960_V2_HealthStatusBuffer_T)))
+  memcpy(ControllerInfo, Controller->V2.NewControllerInformation,
+			sizeof(DAC960_V2_ControllerInfo_T));
+	 
+  
+  if (!DAC960_V2_GeneralInfo(Controller))
     return DAC960_Failure(Controller, "GET HEALTH STATUS");
+
   /*
     Initialize the Controller Model Name and Full Model Name fields.
   */
@@ -1325,14 +1722,11 @@ static boolean DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T
   while (true)
     {
       DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo =
-	&Controller->V2.NewLogicalDeviceInformation;
+	Controller->V2.NewLogicalDeviceInformation;
       DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo;
       DAC960_V2_PhysicalDevice_T PhysicalDevice;
-      if (!DAC960_V2_LogicalDeviceInfo(Controller,
-				       DAC960_V2_GetLogicalDeviceInfoValid,
-				       LogicalDeviceNumber,
-				       NewLogicalDeviceInfo,
-				       sizeof(DAC960_V2_LogicalDeviceInfo_T)))
+
+      if (!DAC960_V2_NewLogicalDeviceInfo(Controller, LogicalDeviceNumber))
 	break;
       LogicalDeviceNumber = NewLogicalDeviceInfo->LogicalDeviceNumber;
       if (LogicalDeviceNumber > DAC960_MaxLogicalDrives)
@@ -1421,26 +1815,61 @@ static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T
 static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T
 						 *Controller)
 {
-  DAC960_V1_DCDB_T DCDBs[DAC960_V1_MaxChannels], *DCDB;
-  Completion_T Completions[DAC960_V1_MaxChannels], *Completion;
+  struct dma_loaf local_dma;
+
+  dma_addr_t DCDBs_dma[DAC960_V1_MaxChannels];
+  DAC960_V1_DCDB_T *DCDBs_cpu[DAC960_V1_MaxChannels];
+
+  dma_addr_t SCSI_Inquiry_dma[DAC960_V1_MaxChannels];
+  DAC960_SCSI_Inquiry_T *SCSI_Inquiry_cpu[DAC960_V1_MaxChannels];
+
+  dma_addr_t SCSI_NewInquiryUnitSerialNumberDMA[DAC960_V1_MaxChannels];
+  DAC960_SCSI_Inquiry_UnitSerialNumber_T *SCSI_NewInquiryUnitSerialNumberCPU[DAC960_V1_MaxChannels];
+
+  Completion_T Completions[DAC960_V1_MaxChannels];
   unsigned long ProcessorFlags;
   int Channel, TargetID;
+
+  if (!init_dma_loaf(Controller->PCIDevice, &local_dma, 
+		DAC960_V1_MaxChannels*(sizeof(DAC960_V1_DCDB_T) +
+			sizeof(DAC960_SCSI_Inquiry_T) +
+			sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T))))
+     return DAC960_Failure(Controller,
+                        "DMA ALLOCATION FAILED IN ReadDeviceConfiguration"); 
+   
+  for (Channel = 0; Channel < Controller->Channels; Channel++) {
+	DCDBs_cpu[Channel] = slice_dma_loaf(&local_dma,
+			sizeof(DAC960_V1_DCDB_T), DCDBs_dma + Channel);
+	SCSI_Inquiry_cpu[Channel] = slice_dma_loaf(&local_dma,
+			sizeof(DAC960_SCSI_Inquiry_T),
+			SCSI_Inquiry_dma + Channel);
+	SCSI_NewInquiryUnitSerialNumberCPU[Channel] = slice_dma_loaf(&local_dma,
+			sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T),
+			SCSI_NewInquiryUnitSerialNumberDMA + Channel);
+  }
+		
   for (TargetID = 0; TargetID < Controller->Targets; TargetID++)
     {
+      /*
+       * For each channel, submit a probe for a device on that channel.
+       * The timeout interval for a device that is present is 10 seconds.
+       * With this approach, the timeout periods can elapse in parallel
+       * on each channel.
+       */
       for (Channel = 0; Channel < Controller->Channels; Channel++)
 	{
+	  dma_addr_t NewInquiryStandardDataDMA = SCSI_Inquiry_dma[Channel];
+  	  DAC960_V1_DCDB_T *DCDB = DCDBs_cpu[Channel];
+  	  dma_addr_t DCDB_dma = DCDBs_dma[Channel];
 	  DAC960_Command_T *Command = Controller->Commands[Channel];
-	  DAC960_SCSI_Inquiry_T *InquiryStandardData =
-	    &Controller->V1.InquiryStandardData[Channel][TargetID];
-	  InquiryStandardData->PeripheralDeviceType = 0x1F;
-	  Completion = &Completions[Channel];
+          Completion_T *Completion = &Completions[Channel];
+
 	  init_completion(Completion);
-	  DCDB = &DCDBs[Channel];
 	  DAC960_V1_ClearCommand(Command);
 	  Command->CommandType = DAC960_ImmediateCommand;
 	  Command->Completion = Completion;
 	  Command->V1.CommandMailbox.Type3.CommandOpcode = DAC960_V1_DCDB;
-	  Command->V1.CommandMailbox.Type3.BusAddress = Virtual_to_Bus32(DCDB);
+	  Command->V1.CommandMailbox.Type3.BusAddress = DCDB_dma;
 	  DCDB->Channel = Channel;
 	  DCDB->TargetID = TargetID;
 	  DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem;
@@ -1449,7 +1878,7 @@ static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T
 	  DCDB->NoAutomaticRequestSense = false;
 	  DCDB->DisconnectPermitted = true;
 	  DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T);
-	  DCDB->BusAddress = Virtual_to_Bus32(InquiryStandardData);
+	  DCDB->BusAddress = NewInquiryStandardDataDMA;
 	  DCDB->CDBLength = 6;
 	  DCDB->TransferLengthHigh4 = 0;
 	  DCDB->SenseLength = sizeof(DCDB->SenseData);
@@ -1463,20 +1892,39 @@ static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T
 	  DAC960_QueueCommand(Command);
 	  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
 	}
+      /*
+       * Wait for the problems submitted in the previous loop
+       * to complete.  On the probes that are successful, 
+       * get the serial number of the device that was found.
+       */
       for (Channel = 0; Channel < Controller->Channels; Channel++)
 	{
-	  DAC960_Command_T *Command = Controller->Commands[Channel];
+	  DAC960_SCSI_Inquiry_T *InquiryStandardData =
+	    &Controller->V1.InquiryStandardData[Channel][TargetID];
+	  DAC960_SCSI_Inquiry_T *NewInquiryStandardData = SCSI_Inquiry_cpu[Channel];
+	  dma_addr_t NewInquiryUnitSerialNumberDMA =
+			SCSI_NewInquiryUnitSerialNumberDMA[Channel];
+	  DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber =
+	    		SCSI_NewInquiryUnitSerialNumberCPU[Channel];
 	  DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
 	    &Controller->V1.InquiryUnitSerialNumber[Channel][TargetID];
-	  InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
-	  Completion = &Completions[Channel];
+	  DAC960_Command_T *Command = Controller->Commands[Channel];
+  	  DAC960_V1_DCDB_T *DCDB = DCDBs_cpu[Channel];
+          Completion_T *Completion = &Completions[Channel];
+
 	  wait_for_completion(Completion);
-	  if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion)
+
+	  if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) {
+	    memset(InquiryStandardData, 0, sizeof(DAC960_SCSI_Inquiry_T));
+	    InquiryStandardData->PeripheralDeviceType = 0x1F;
 	    continue;
+	  } else
+	    memcpy(InquiryStandardData, NewInquiryStandardData, sizeof(DAC960_SCSI_Inquiry_T));
+	
+	  /* Preserve Channel and TargetID values from the previous loop */
 	  Command->Completion = Completion;
-	  DCDB = &DCDBs[Channel];
 	  DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-	  DCDB->BusAddress = Virtual_to_Bus32(InquiryUnitSerialNumber);
+	  DCDB->BusAddress = NewInquiryUnitSerialNumberDMA;
 	  DCDB->SenseLength = sizeof(DCDB->SenseData);
 	  DCDB->CDB[0] = 0x12; /* INQUIRY */
 	  DCDB->CDB[1] = 1; /* EVPD = 1 */
@@ -1488,8 +1936,17 @@ static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T
 	  DAC960_QueueCommand(Command);
 	  DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
 	  wait_for_completion(Completion);
+
+	  if (Command->V1.CommandStatus != DAC960_V1_NormalCompletion) {
+	  	memset(InquiryUnitSerialNumber, 0,
+			sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+	  	InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+	  } else
+	  	memcpy(InquiryUnitSerialNumber, NewInquiryUnitSerialNumber,
+			sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
 	}
     }
+    free_dma_loaf(Controller->PCIDevice, &local_dma);
   return true;
 }
 
@@ -1506,74 +1963,55 @@ static boolean DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T
 {
   unsigned char Channel = 0, TargetID = 0, LogicalUnit = 0;
   unsigned short PhysicalDeviceIndex = 0;
+
   while (true)
     {
       DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo =
-	&Controller->V2.NewPhysicalDeviceInformation;
+		Controller->V2.NewPhysicalDeviceInformation;
       DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo;
+      DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber =
+		Controller->V2.NewInquiryUnitSerialNumber;
       DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber;
-      DAC960_Command_T *Command;
-      DAC960_V2_CommandMailbox_T *CommandMailbox;
-      if (!DAC960_V2_PhysicalDeviceInfo(Controller,
-					DAC960_V2_GetPhysicalDeviceInfoValid,
-					Channel,
-					TargetID,
-					LogicalUnit,
-					NewPhysicalDeviceInfo,
-					sizeof(DAC960_V2_PhysicalDeviceInfo_T)))
+
+      if (!DAC960_V2_NewPhysicalDeviceInfo(Controller, Channel, TargetID, LogicalUnit))
 	  break;
-      Channel = NewPhysicalDeviceInfo->Channel;
-      TargetID = NewPhysicalDeviceInfo->TargetID;
-      LogicalUnit = NewPhysicalDeviceInfo->LogicalUnit;
+
       PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *)
-	kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC);
+		kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC);
       if (PhysicalDeviceInfo == NULL)
-	return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION");
+		return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION");
       Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex] =
-	PhysicalDeviceInfo;
+		PhysicalDeviceInfo;
       memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo,
-	     sizeof(DAC960_V2_PhysicalDeviceInfo_T));
+		sizeof(DAC960_V2_PhysicalDeviceInfo_T));
+
       InquiryUnitSerialNumber = (DAC960_SCSI_Inquiry_UnitSerialNumber_T *)
 	kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC);
-      if (InquiryUnitSerialNumber == NULL)
+      if (InquiryUnitSerialNumber == NULL) {
+	kfree(PhysicalDeviceInfo);
 	return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION");
+      }
       Controller->V2.InquiryUnitSerialNumber[PhysicalDeviceIndex] =
-	InquiryUnitSerialNumber;
-      memset(InquiryUnitSerialNumber, 0,
-	     sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
-      InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
-      Command = DAC960_AllocateCommand(Controller);
-      CommandMailbox = &Command->V2.CommandMailbox;
-      DAC960_V2_ClearCommand(Command);
-      Command->CommandType = DAC960_ImmediateCommand;
-      CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10_Passthru;
-      CommandMailbox->SCSI_10.CommandControlBits
-			     .DataTransferControllerToHost = true;
-      CommandMailbox->SCSI_10.CommandControlBits
-			     .NoAutoRequestSense = true;
-      CommandMailbox->SCSI_10.DataTransferSize =
-	sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-      CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit = LogicalUnit;
-      CommandMailbox->SCSI_10.PhysicalDevice.TargetID = TargetID;
-      CommandMailbox->SCSI_10.PhysicalDevice.Channel = Channel;
-      CommandMailbox->SCSI_10.CDBLength = 6;
-      CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */
-      CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */
-      CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */
-      CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */
-      CommandMailbox->SCSI_10.SCSI_CDB[4] =
-	sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-      CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */
-      CommandMailbox->SCSI_10.DataTransferMemoryAddress
-			     .ScatterGatherSegments[0]
-			     .SegmentDataPointer =
-	Virtual_to_Bus64(InquiryUnitSerialNumber);
-      CommandMailbox->SCSI_10.DataTransferMemoryAddress
-			     .ScatterGatherSegments[0]
-			     .SegmentByteCount =
-	CommandMailbox->SCSI_10.DataTransferSize;
-      DAC960_ExecuteCommand(Command);
-      DAC960_DeallocateCommand(Command);
+		InquiryUnitSerialNumber;
+
+      Channel = NewPhysicalDeviceInfo->Channel;
+      TargetID = NewPhysicalDeviceInfo->TargetID;
+      LogicalUnit = NewPhysicalDeviceInfo->LogicalUnit;
+
+      /*
+	 Some devices do NOT have Unit Serial Numbers.
+	 This command fails for them.  But, we still want to
+	 remember those devices are there.  Construct a
+	 UnitSerialNumber structure for the failure case.
+      */
+      if (!DAC960_V2_NewInquiryUnitSerialNumber(Controller, Channel, TargetID, LogicalUnit)) {
+      	memset(InquiryUnitSerialNumber, 0,
+             sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+     	InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+      } else
+      	memcpy(InquiryUnitSerialNumber, NewInquiryUnitSerialNumber,
+		sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+
       PhysicalDeviceIndex++;
       LogicalUnit++;
     }
@@ -1947,12 +2385,12 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
     Initialize the I/O Request Queue.
   */
   RequestQueue = &Controller->RequestQueue;
-  Controller->queue_lock = SPIN_LOCK_UNLOCKED;
   blk_init_queue(RequestQueue, DAC960_RequestFunction, &Controller->queue_lock);
   RequestQueue->queuedata = Controller;
   blk_queue_max_hw_segments(RequestQueue,
 			    Controller->DriverScatterGatherLimit);
-  blk_queue_max_phys_segments(RequestQueue, ~0);
+  blk_queue_max_phys_segments(RequestQueue,
+		 	    Controller->DriverScatterGatherLimit);
   blk_queue_max_sectors(RequestQueue, Controller->MaxBlocksPerCommand);
 
   for (n = 0; n < DAC960_MaxLogicalDrives; n++) {
@@ -1978,8 +2416,10 @@ static void DAC960_UnregisterBlockDevice(DAC960_Controller_T *Controller)
 {
   int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
   int disk;
+
   for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++)
 	  del_gendisk(Controller->disks[disk]);
+
   /*
     Unregister the Block Device Major Number for this DAC960 Controller.
   */
@@ -2082,159 +2522,155 @@ static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller,
 
 
 /*
-  DAC960_DetectControllers detects Mylex DAC960/AcceleRAID/eXtremeRAID
+ * DAC960_DetectCleanup releases the resources that were allocated
+ * during DAC960_DetectController().  DAC960_DetectController can
+ * has several internal failure points, so not ALL resources may 
+ * have been allocated.  It's important to free only
+ * resources that HAVE been allocated.  The code below always
+ * tests that the resource has been allocated before attempting to
+ * free it.
+ */
+static void DAC960_DetectCleanup(DAC960_Controller_T *Controller)
+{
+  int i;
+
+  /* Free the memory mailbox, status, and related structures */
+  free_dma_loaf(Controller->PCIDevice, &Controller->DmaPages);
+  if (Controller->MemoryMappedAddress) {
+  	switch(Controller->HardwareType)
+  	{
+		case DAC960_BA_Controller:
+			DAC960_BA_DisableInterrupts(Controller->BaseAddress);
+			break;
+		case DAC960_LP_Controller:
+			DAC960_LP_DisableInterrupts(Controller->BaseAddress);
+			break;
+		case DAC960_LA_Controller:
+			DAC960_LA_DisableInterrupts(Controller->BaseAddress);
+			break;
+		case DAC960_PG_Controller:
+			DAC960_PG_DisableInterrupts(Controller->BaseAddress);
+			break;
+		case DAC960_PD_Controller:
+			DAC960_PD_DisableInterrupts(Controller->BaseAddress);
+			break;
+		case DAC960_P_Controller:
+			DAC960_PD_DisableInterrupts(Controller->BaseAddress);
+			break;
+  	}
+  	iounmap(Controller->MemoryMappedAddress);
+  }
+  if (Controller->IRQ_Channel)
+  	free_irq(Controller->IRQ_Channel, Controller);
+  if (Controller->IO_Address)
+	release_region(Controller->IO_Address, 0x80);
+  pci_disable_device(Controller->PCIDevice);
+  for (i = 0; (i < DAC960_MaxLogicalDrives) && Controller->disks[i]; i++)
+       put_disk(Controller->disks[i]);
+  DAC960_Controllers[Controller->ControllerNumber] = NULL;
+  kfree(Controller);
+}
+
+
+/*
+  DAC960_DetectController detects Mylex DAC960/AcceleRAID/eXtremeRAID
   PCI RAID Controllers by interrogating the PCI Configuration Space for
   Controller Type.
 */
 
-static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
+static DAC960_Controller_T * 
+DAC960_DetectController(PCI_Device_T *PCI_Device,
+					const struct pci_device_id *entry)
 {
-  void (*InterruptHandler)(int, void *, Registers_T *) = NULL;
+  struct DAC960_privdata *privdata = (struct DAC960_privdata *)entry->driver_data;
+  void (*InterruptHandler)(int, void *, Registers_T *) = privdata->InterruptHandler;
+  unsigned int MemoryWindowSize = privdata->MemoryWindowSize;
   DAC960_Controller_T *Controller = NULL;
-  DAC960_FirmwareType_T FirmwareType = 0;
-  unsigned short VendorID = 0, DeviceID = 0;
-  unsigned int MemoryWindowSize = 0;
-  PCI_Device_T *PCI_Device = NULL;
+  unsigned char DeviceFunction = PCI_Device->devfn;
+  unsigned char ErrorStatus, Parameter0, Parameter1;
+  unsigned int IRQ_Channel = PCI_Device->irq;
+  void *BaseAddress;
   int i;
-  switch (HardwareType)
-    {
-    case DAC960_BA_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_BA;
-      FirmwareType = DAC960_V2_Controller;
-      InterruptHandler = DAC960_BA_InterruptHandler;
-      MemoryWindowSize = DAC960_BA_RegisterWindowSize;
-      break;
-    case DAC960_LP_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_LP;
-      FirmwareType = DAC960_LP_Controller;
-      InterruptHandler = DAC960_LP_InterruptHandler;
-      MemoryWindowSize = DAC960_LP_RegisterWindowSize;
-      break;
-    case DAC960_LA_Controller:
-      VendorID = PCI_VENDOR_ID_DEC;
-      DeviceID = PCI_DEVICE_ID_DEC_21285;
-      FirmwareType = DAC960_V1_Controller;
-      InterruptHandler = DAC960_LA_InterruptHandler;
-      MemoryWindowSize = DAC960_LA_RegisterWindowSize;
-      break;
-    case DAC960_PG_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PG;
-      FirmwareType = DAC960_V1_Controller;
-      InterruptHandler = DAC960_PG_InterruptHandler;
-      MemoryWindowSize = DAC960_PG_RegisterWindowSize;
-      break;
-    case DAC960_PD_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_PD;
-      FirmwareType = DAC960_V1_Controller;
-      InterruptHandler = DAC960_PD_InterruptHandler;
-      MemoryWindowSize = DAC960_PD_RegisterWindowSize;
-      break;
-    case DAC960_P_Controller:
-      VendorID = PCI_VENDOR_ID_MYLEX;
-      DeviceID = PCI_DEVICE_ID_MYLEX_DAC960_P;
-      FirmwareType = DAC960_V1_Controller;
-      InterruptHandler = DAC960_P_InterruptHandler;
-      MemoryWindowSize = DAC960_PD_RegisterWindowSize;
-      break;
-    }
-  while ((PCI_Device = pci_find_device(VendorID, DeviceID, PCI_Device)) != NULL)
-    {
-      DAC960_IO_Address_T IO_Address = 0;
-      DAC960_PCI_Address_T PCI_Address = 0;
-      unsigned char Bus = PCI_Device->bus->number;
-      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;
-      void *BaseAddress;
-      Controller = NULL;
-      if (pci_enable_device(PCI_Device) != 0) continue;
-      switch (HardwareType)
-	{
+
+  Controller = (DAC960_Controller_T *)
+	kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
+  if (Controller == NULL) {
+	DAC960_Error("Unable to allocate Controller structure for "
+                       "Controller at\n", NULL);
+	return NULL;
+  }
+  memset(Controller, 0, sizeof(DAC960_Controller_T));
+  Controller->ControllerNumber = DAC960_ControllerCount;
+  DAC960_Controllers[DAC960_ControllerCount++] = Controller;
+  Controller->Bus = PCI_Device->bus->number;
+  Controller->FirmwareType = privdata->FirmwareType;
+  Controller->HardwareType = privdata->HardwareType;
+  Controller->Device = DeviceFunction >> 3;
+  Controller->Function = DeviceFunction & 0x7;
+  Controller->PCIDevice = PCI_Device;
+  strcpy(Controller->FullModelName, "DAC960");
+
+  if (pci_enable_device(PCI_Device))  {
+        kfree(Controller);
+	goto Failure;
+  }
+
+  switch (Controller->HardwareType)
+  {
 	case DAC960_BA_Controller:
-	  PCI_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
 	  break;
 	case DAC960_LP_Controller:
-	  PCI_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
 	  break;
 	case DAC960_LA_Controller:
-	  if (!(PCI_Device->subsystem_vendor == PCI_VENDOR_ID_MYLEX &&
-		PCI_Device->subsystem_device == PCI_DEVICE_ID_MYLEX_DAC960_LA))
-	    continue;
-	  PCI_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
 	  break;
 	case DAC960_PG_Controller:
-	  PCI_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
 	  break;
 	case DAC960_PD_Controller:
-	  IO_Address = pci_resource_start(PCI_Device, 0);
-	  PCI_Address = pci_resource_start(PCI_Device, 1);
+	  Controller->IO_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 1);
 	  break;
 	case DAC960_P_Controller:
-	  IO_Address = pci_resource_start(PCI_Device, 0);
-	  PCI_Address = pci_resource_start(PCI_Device, 1);
+	  Controller->IO_Address = pci_resource_start(PCI_Device, 0);
+	  Controller->PCI_Address = pci_resource_start(PCI_Device, 1);
 	  break;
-	}
-      if (DAC960_ControllerCount == DAC960_MaxControllers)
-	{
-	  DAC960_Error("More than %d DAC960 Controllers detected - "
-		       "ignoring from Controller at\n",
-		       NULL, DAC960_MaxControllers);
-	  goto Failure;
-	}
-      Controller = (DAC960_Controller_T *)
-	kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
-      if (Controller == NULL)
-	{
-	  DAC960_Error("Unable to allocate Controller structure for "
-		       "Controller at\n", NULL);
-	  goto Failure;
-	}
-      memset(Controller, 0, sizeof(DAC960_Controller_T));
-      for (i = 0; i < DAC960_MaxLogicalDrives; i++) {
-		Controller->disks[i] = alloc_disk(1<<DAC960_MaxPartitionsBits);
-		if (!Controller->disks[i])
-			goto Enomem;
-		Controller->disks[i]->private_data = (void*)i;
-		Controller->disks[i]->queue = &Controller->RequestQueue;
-      }
-      Controller->ControllerNumber = DAC960_ControllerCount;
-      init_waitqueue_head(&Controller->CommandWaitQueue);
-      init_waitqueue_head(&Controller->HealthStatusWaitQueue);
-      DAC960_Controllers[DAC960_ControllerCount++] = Controller;
-      DAC960_AnnounceDriver(Controller);
-      Controller->FirmwareType = FirmwareType;
-      Controller->HardwareType = HardwareType;
-      Controller->IO_Address = IO_Address;
-      Controller->PCI_Address = PCI_Address;
-      Controller->Bus = Bus;
-      Controller->Device = Device;
-      Controller->Function = Function;
-      /*
-	Map the Controller Register Window.
-      */
-      if (MemoryWindowSize < PAGE_SIZE)
+  }
+
+  pci_set_drvdata(PCI_Device, (void *)((int)Controller->ControllerNumber));
+  for (i = 0; i < DAC960_MaxLogicalDrives; i++) {
+	Controller->disks[i] = alloc_disk(1<<DAC960_MaxPartitionsBits);
+	if (!Controller->disks[i])
+		goto Failure;
+	Controller->disks[i]->private_data = (void *)i;
+	Controller->disks[i]->queue = &Controller->RequestQueue;
+  }
+  init_waitqueue_head(&Controller->CommandWaitQueue);
+  init_waitqueue_head(&Controller->HealthStatusWaitQueue);
+  Controller->queue_lock = SPIN_LOCK_UNLOCKED; 
+  DAC960_AnnounceDriver(Controller);
+  /*
+    Map the Controller Register Window.
+  */
+ if (MemoryWindowSize < PAGE_SIZE)
 	MemoryWindowSize = PAGE_SIZE;
-      Controller->MemoryMappedAddress =
-	ioremap_nocache(PCI_Address & PAGE_MASK, MemoryWindowSize);
-      Controller->BaseAddress =
-	Controller->MemoryMappedAddress + (PCI_Address & ~PAGE_MASK);
-      if (Controller->MemoryMappedAddress == NULL)
-	{
+  Controller->MemoryMappedAddress =
+	ioremap_nocache(Controller->PCI_Address & PAGE_MASK, MemoryWindowSize);
+  Controller->BaseAddress =
+	Controller->MemoryMappedAddress + (Controller->PCI_Address & ~PAGE_MASK);
+  if (Controller->MemoryMappedAddress == NULL)
+  {
 	  DAC960_Error("Unable to map Controller Register Window for "
 		       "Controller at\n", Controller);
 	  goto Failure;
-	}
-      BaseAddress = Controller->BaseAddress;
-      switch (HardwareType)
-	{
+  }
+  BaseAddress = Controller->BaseAddress;
+  switch (Controller->HardwareType)
+  {
 	case DAC960_BA_Controller:
-	  DAC960_BA_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_BA_DisableInterrupts(BaseAddress);
 	  DAC960_BA_AcknowledgeHardwareMailboxStatus(BaseAddress);
 	  udelay(1000);
 	  while (DAC960_BA_InitializationInProgressP(BaseAddress))
@@ -2252,7 +2688,7 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_BA_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_BA_EnableInterrupts(BaseAddress);
 	  Controller->QueueCommand = DAC960_BA_QueueCommand;
 	  Controller->ReadControllerConfiguration =
 	    DAC960_V2_ReadControllerConfiguration;
@@ -2264,7 +2700,7 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
 	    DAC960_V2_QueueReadWriteCommand;
 	  break;
 	case DAC960_LP_Controller:
-	  DAC960_LP_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_LP_DisableInterrupts(BaseAddress);
 	  DAC960_LP_AcknowledgeHardwareMailboxStatus(BaseAddress);
 	  udelay(1000);
 	  while (DAC960_LP_InitializationInProgressP(BaseAddress))
@@ -2282,7 +2718,7 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_LP_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_LP_EnableInterrupts(BaseAddress);
 	  Controller->QueueCommand = DAC960_LP_QueueCommand;
 	  Controller->ReadControllerConfiguration =
 	    DAC960_V2_ReadControllerConfiguration;
@@ -2294,7 +2730,7 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
 	    DAC960_V2_QueueReadWriteCommand;
 	  break;
 	case DAC960_LA_Controller:
-	  DAC960_LA_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_LA_DisableInterrupts(BaseAddress);
 	  DAC960_LA_AcknowledgeHardwareMailboxStatus(BaseAddress);
 	  udelay(1000);
 	  while (DAC960_LA_InitializationInProgressP(BaseAddress))
@@ -2312,7 +2748,7 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_LA_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_LA_EnableInterrupts(BaseAddress);
 	  if (Controller->V1.DualModeMemoryMailboxInterface)
 	    Controller->QueueCommand = DAC960_LA_QueueCommandDualMode;
 	  else Controller->QueueCommand = DAC960_LA_QueueCommandSingleMode;
@@ -2326,7 +2762,7 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
 	    DAC960_V1_QueueReadWriteCommand;
 	  break;
 	case DAC960_PG_Controller:
-	  DAC960_PG_DisableInterrupts(Controller->BaseAddress);
+	  DAC960_PG_DisableInterrupts(BaseAddress);
 	  DAC960_PG_AcknowledgeHardwareMailboxStatus(BaseAddress);
 	  udelay(1000);
 	  while (DAC960_PG_InitializationInProgressP(BaseAddress))
@@ -2344,7 +2780,7 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
 			   "for Controller at\n", Controller);
 	      goto Failure;
 	    }
-	  DAC960_PG_EnableInterrupts(Controller->BaseAddress);
+	  DAC960_PG_EnableInterrupts(BaseAddress);
 	  if (Controller->V1.DualModeMemoryMailboxInterface)
 	    Controller->QueueCommand = DAC960_PG_QueueCommandDualMode;
 	  else Controller->QueueCommand = DAC960_PG_QueueCommandSingleMode;
@@ -2373,10 +2809,16 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
 					    &Parameter0, &Parameter1) &&
 		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
 					   Parameter0, Parameter1))
-		goto Failure1;
+		goto Failure;
 	      udelay(10);
 	    }
-	  DAC960_PD_EnableInterrupts(Controller->BaseAddress);
+	  if (!DAC960_V1_EnableMemoryMailboxInterface(Controller))
+	    {
+	      DAC960_Error("Unable to allocate DMA mapped memory "
+			   "for Controller at\n", Controller);
+	      goto Failure;
+	    }
+	  DAC960_PD_EnableInterrupts(BaseAddress);
 	  Controller->QueueCommand = DAC960_PD_QueueCommand;
 	  Controller->ReadControllerConfiguration =
 	    DAC960_V1_ReadControllerConfiguration;
@@ -2403,10 +2845,16 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
 					    &Parameter0, &Parameter1) &&
 		  DAC960_ReportErrorStatus(Controller, ErrorStatus,
 					   Parameter0, Parameter1))
-		goto Failure1;
+		goto Failure;
 	      udelay(10);
 	    }
-	  DAC960_PD_EnableInterrupts(Controller->BaseAddress);
+	  if (!DAC960_V1_EnableMemoryMailboxInterface(Controller))
+	    {
+	      DAC960_Error("Unable to allocate DMA mapped memory"
+			   "for Controller at\n", Controller);
+	      goto Failure;
+	    }
+	  DAC960_PD_EnableInterrupts(BaseAddress);
 	  Controller->QueueCommand = DAC960_P_QueueCommand;
 	  Controller->ReadControllerConfiguration =
 	    DAC960_V1_ReadControllerConfiguration;
@@ -2417,107 +2865,47 @@ static void DAC960_DetectControllers(DAC960_HardwareType_T HardwareType)
 	  Controller->QueueReadWriteCommand =
 	    DAC960_V1_QueueReadWriteCommand;
 	  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 Failure1;
-	}
-      strcpy(Controller->FullModelName, "DAC960");
-      if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ,
+  }
+  /*
+     Acquire shared access to the IRQ Channel.
+  */
+  if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ,
 		      Controller->FullModelName, Controller) < 0)
-	{
-	  DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
-		       Controller, IRQ_Channel);
-	  goto Failure1;
-	}
-      Controller->IRQ_Channel = IRQ_Channel;
-      DAC960_ActiveControllerCount++;
-      Controller->InitialCommand.CommandIdentifier = 1;
-      Controller->InitialCommand.Controller = Controller;
-      Controller->Commands[0] = &Controller->InitialCommand;
-      Controller->FreeCommands = &Controller->InitialCommand;
-      Controller->ControllerDetectionSuccessful = true;
-      continue;
-    Failure1:
-      if (Controller->IO_Address) release_region(Controller->IO_Address, 0x80);
-    Failure:
-      if (IO_Address == 0)
+  {
+	DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
+		       Controller, Controller->IRQ_Channel);
+	goto Failure;
+  }
+  Controller->IRQ_Channel = IRQ_Channel;
+  Controller->InitialCommand.CommandIdentifier = 1;
+  Controller->InitialCommand.Controller = Controller;
+  Controller->Commands[0] = &Controller->InitialCommand;
+  Controller->FreeCommands = &Controller->InitialCommand;
+  return Controller;
+      
+Failure:
+  if (Controller->IO_Address == 0)
 	DAC960_Error("PCI Bus %d Device %d Function %d I/O Address N/A "
 		     "PCI Address 0x%X\n", Controller,
-		     Bus, Device, Function, PCI_Address);
-      else DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
+		     Controller->Bus, Controller->Device,
+		     Controller->Function, Controller->PCI_Address);
+  else
+	DAC960_Error("PCI Bus %d Device %d Function %d I/O Address "
 			"0x%X PCI Address 0x%X\n", Controller,
-			Bus, Device, Function, IO_Address, PCI_Address);
-      if (Controller == NULL) break;
-      if (Controller->MemoryMappedAddress != NULL)
-	iounmap(Controller->MemoryMappedAddress);
-      if (Controller->IRQ_Channel > 0)
-	free_irq(IRQ_Channel, Controller);
-    }
-    return;
-Enomem:
-      while (i--)
-	put_disk(Controller->disks[i]);
-      kfree(Controller);
-      goto Failure;
+			Controller->Bus, Controller->Device,
+			Controller->Function, Controller->IO_Address,
+			Controller->PCI_Address);
+  DAC960_DetectCleanup(Controller);
+  DAC960_ControllerCount--;
+  return NULL;
 }
 
-
-/*
-  DAC960_SortControllers sorts the Controllers by PCI Bus and Device Number.
-*/
-
-static void DAC960_SortControllers(void)
-{
-  int ControllerNumber, LastInterchange, Bound, j;
-  LastInterchange = DAC960_ControllerCount-1;
-  while (LastInterchange > 0)
-    {
-      Bound = LastInterchange;
-      LastInterchange = 0;
-      for (j = 0; j < Bound; j++)
-	{
-	  DAC960_Controller_T *Controller1 = DAC960_Controllers[j];
-	  DAC960_Controller_T *Controller2 = DAC960_Controllers[j+1];
-	  if (Controller1->Bus > Controller2->Bus ||
-	      (Controller1->Bus == Controller2->Bus &&
-	       (Controller1->Device > Controller2->Device)))
-	    {
-	      Controller2->ControllerNumber = j;
-	      DAC960_Controllers[j] = Controller2;
-	      Controller1->ControllerNumber = j+1;
-	      DAC960_Controllers[j+1] = Controller1;
-	      LastInterchange = j;
-	    }
-	}
-    }
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-      if (!Controller->ControllerDetectionSuccessful)
-	{
-	  int i;
-	  DAC960_Controllers[ControllerNumber] = NULL;
-	  for (i = 0; i < DAC960_MaxLogicalDrives; i++)
-		put_disk(Controller->disks[i]);
-	  kfree(Controller);
-	}
-    }
-}
-
-
 /*
   DAC960_InitializeController initializes Controller.
 */
 
-static void DAC960_InitializeController(DAC960_Controller_T *Controller)
+static boolean 
+DAC960_InitializeController(DAC960_Controller_T *Controller)
 {
   if (DAC960_ReadControllerConfiguration(Controller) &&
       DAC960_ReportControllerConfiguration(Controller) &&
@@ -2536,8 +2924,9 @@ static void DAC960_InitializeController(DAC960_Controller_T *Controller)
       Controller->MonitoringTimer.function = DAC960_MonitoringTimerFunction;
       add_timer(&Controller->MonitoringTimer);
       Controller->ControllerInitialized = true;
+      return true;
     }
-  else DAC960_FinalizeController(Controller);
+  return false;
 }
 
 
@@ -2547,35 +2936,38 @@ static void DAC960_InitializeController(DAC960_Controller_T *Controller)
 
 static void DAC960_FinalizeController(DAC960_Controller_T *Controller)
 {
-  int i;
   if (Controller->ControllerInitialized)
     {
-      del_timer(&Controller->MonitoringTimer);
+      unsigned long ProcessorFlags;
+
+      /*
+       * Acquiring and releasing lock here eliminates
+       * a very low probability race.
+       *
+       * The code below allocates controller command structures
+       * from the free list without holding the controller lock.
+       * This is safe assuming there is no other activity on
+       * the controller at the time.
+       * 
+       * But, there might be a monitoring command still
+       * in progress.  Setting the Shutdown flag while holding
+       * the lock ensures that there is no monitoring command
+       * in the interrupt handler currently, and any monitoring
+       * commands that complete from this time on will NOT return
+       * their command structure to the free list.
+       */
+      DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
+      Controller->ShutdownMonitoringTimer = 1;
+      DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
+      del_timer_sync(&Controller->MonitoringTimer);
       if (Controller->FirmwareType == DAC960_V1_Controller)
 	{
 	  DAC960_Notice("Flushing Cache...", Controller);
-	  DAC960_V1_ExecuteType3(Controller, DAC960_V1_Flush, NULL);
+	  DAC960_V1_ExecuteType3(Controller, DAC960_V1_Flush, 0);
 	  DAC960_Notice("done\n", Controller);
-	  switch (Controller->HardwareType)
-	    {
-	    case DAC960_LA_Controller:
-	      if (Controller->V1.DualModeMemoryMailboxInterface)
-		free_pages(Controller->MemoryMailboxPagesAddress,
-			   Controller->MemoryMailboxPagesOrder);
-	      else DAC960_LA_SaveMemoryMailboxInfo(Controller);
-	      break;
-	    case DAC960_PG_Controller:
-	      if (Controller->V1.DualModeMemoryMailboxInterface)
-		free_pages(Controller->MemoryMailboxPagesAddress,
-			   Controller->MemoryMailboxPagesOrder);
-	      else DAC960_PG_SaveMemoryMailboxInfo(Controller);
-	      break;
-	    case DAC960_PD_Controller:
+
+	  if (Controller->HardwareType == DAC960_PD_Controller)
 	      release_region(Controller->IO_Address, 0x80);
-	      break;
-	    default:
-	      break;
-	    }
 	}
       else
 	{
@@ -2583,51 +2975,48 @@ static void DAC960_FinalizeController(DAC960_Controller_T *Controller)
 	  DAC960_V2_DeviceOperation(Controller, DAC960_V2_PauseDevice,
 				    DAC960_V2_RAID_Controller);
 	  DAC960_Notice("done\n", Controller);
-	  free_pages(Controller->MemoryMailboxPagesAddress,
-		     Controller->MemoryMailboxPagesOrder);
 	}
     }
-  free_irq(Controller->IRQ_Channel, Controller);
-  iounmap(Controller->MemoryMappedAddress);
   DAC960_UnregisterBlockDevice(Controller);
   DAC960_DestroyAuxiliaryStructures(Controller);
-  DAC960_Controllers[Controller->ControllerNumber] = NULL;
-  for (i = 0; i < DAC960_MaxLogicalDrives; i++)
-	put_disk(Controller->disks[i]);
-  kfree(Controller);
+  DAC960_DestroyProcEntries(Controller);
+  DAC960_DetectCleanup(Controller);
 }
 
 
 /*
-  DAC960_Initialize initializes the DAC960 Driver.
+  DAC960_Probe verifies controller's existence and
+  initializes the DAC960 Driver for that controller.
 */
 
-static int DAC960_Initialize(void)
+static int 
+DAC960_Probe(struct pci_dev *dev, const struct pci_device_id *entry)
 {
-  int ControllerNumber;
-  DAC960_DetectControllers(DAC960_BA_Controller);
-  DAC960_DetectControllers(DAC960_LP_Controller);
-  DAC960_DetectControllers(DAC960_LA_Controller);
-  DAC960_DetectControllers(DAC960_PG_Controller);
-  DAC960_DetectControllers(DAC960_PD_Controller);
-  DAC960_DetectControllers(DAC960_P_Controller);
-  DAC960_SortControllers();
-  if (DAC960_ActiveControllerCount == 0) return -ENODEV;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-      int disk;
-      if (Controller == NULL) continue;
-      DAC960_InitializeController(Controller);
-      for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) {
-	set_capacity(Controller->disks[disk], disk_size(Controller, disk));
-	add_disk(Controller->disks[disk]);
-      }
-    }
-  DAC960_CreateProcEntries();
-  register_reboot_notifier(&DAC960_NotifierBlock);
+  int disk;
+  DAC960_Controller_T *Controller;
+
+  if (DAC960_ControllerCount == DAC960_MaxControllers)
+  {
+	DAC960_Error("More than %d DAC960 Controllers detected - "
+                       "ignoring from Controller at\n",
+                       NULL, DAC960_MaxControllers);
+	return -ENODEV;
+  }
+
+  Controller = DAC960_DetectController(dev, entry);
+  if (!Controller)
+	return -ENODEV;
+
+  if (!DAC960_InitializeController(Controller)) {
+  	DAC960_FinalizeController(Controller);
+	return -ENODEV;
+  }
+
+  for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) {
+        set_capacity(Controller->disks[disk], disk_size(Controller, disk));
+        add_disk(Controller->disks[disk]);
+  }
+  DAC960_CreateProcEntries(Controller);
   return 0;
 }
 
@@ -2636,32 +3025,12 @@ static int DAC960_Initialize(void)
   DAC960_Finalize finalizes the DAC960 Driver.
 */
 
-static void DAC960_Finalize(void)
+static void DAC960_Remove(PCI_Device_T *PCI_Device)
 {
-  int ControllerNumber;
-  if (DAC960_ActiveControllerCount == 0) return;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    if (DAC960_Controllers[ControllerNumber] != NULL)
-      DAC960_FinalizeController(DAC960_Controllers[ControllerNumber]);
-  DAC960_DestroyProcEntries();
-  unregister_reboot_notifier(&DAC960_NotifierBlock);
-}
-
-
-/*
-  DAC960_Notifier is the notifier for the DAC960 Driver.
-*/
-
-static int DAC960_Notifier(NotifierBlock_T *NotifierBlock,
-			   unsigned long Event,
-			   void *Buffer)
-{
-  if (!(Event == SYS_RESTART || Event == SYS_HALT || Event == SYS_POWER_OFF))
-    return NOTIFY_DONE;
-  DAC960_Finalize();
-  return NOTIFY_OK;
+  int Controller_Number = (int)pci_get_drvdata(PCI_Device);
+  DAC960_Controller_T *Controller = DAC960_Controllers[Controller_Number];
+  if (Controller != NULL)
+      DAC960_FinalizeController(Controller);
 }
 
 
@@ -2674,57 +3043,60 @@ static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
+  DAC960_V1_ScatterGatherSegment_T *ScatterGatherList =
+					Command->V1.ScatterGatherList;
+  struct scatterlist *ScatterList = Command->V1.ScatterList;
+  int DmaDirection, SegCount;
+
   DAC960_V1_ClearCommand(Command);
-  if (Command->SegmentCount == 1)
+
+  if (Command->CommandType == DAC960_ReadCommand)
+        DmaDirection = PCI_DMA_FROMDEVICE;
+  else
+        DmaDirection = PCI_DMA_TODEVICE;
+
+  SegCount = blk_rq_map_sg(&Controller->RequestQueue, Command->Request,
+								ScatterList);
+  /* pci_map_sg MAY change the value of SegCount */
+  SegCount = pci_map_sg(Command->PciDevice, ScatterList, SegCount,
+								DmaDirection);
+  Command->SegmentCount = SegCount;
+
+  if (SegCount == 1)
     {
       if (Command->CommandType == DAC960_ReadCommand)
 	CommandMailbox->Type5.CommandOpcode = DAC960_V1_Read;
-      else CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write;
+      else 
+        CommandMailbox->Type5.CommandOpcode = DAC960_V1_Write;
+
       CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
       CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
       CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
       CommandMailbox->Type5.BusAddress =
-	Virtual_to_Bus32(Command->RequestBuffer);
+			(DAC960_BusAddress32_T)sg_dma_address(ScatterList);	
     }
   else
     {
-      DAC960_V1_ScatterGatherSegment_T
-	*ScatterGatherList = Command->V1.ScatterGatherList;
-      BufferHeader_T *BufferHeader = Command->BufferHeader;
-      char *LastDataEndPointer = NULL;
-      int SegmentNumber = 0;
+      int i;
+
       if (Command->CommandType == DAC960_ReadCommand)
 	CommandMailbox->Type5.CommandOpcode = DAC960_V1_ReadWithScatterGather;
       else
 	CommandMailbox->Type5.CommandOpcode = DAC960_V1_WriteWithScatterGather;
+
       CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
       CommandMailbox->Type5.LD.LogicalDriveNumber = Command->LogicalDriveNumber;
       CommandMailbox->Type5.LogicalBlockAddress = Command->BlockNumber;
-      CommandMailbox->Type5.BusAddress = Virtual_to_Bus32(ScatterGatherList);
-      CommandMailbox->Type5.ScatterGatherCount = Command->SegmentCount;
-      while (BufferHeader != NULL)
-	{
-	  if (bio_data(BufferHeader) == LastDataEndPointer)
-	    {
-	      ScatterGatherList[SegmentNumber-1].SegmentByteCount +=
-		BufferHeader->bi_size;
-	      LastDataEndPointer += BufferHeader->bi_size;
-	    }
-	  else
-	    {
-	      ScatterGatherList[SegmentNumber].SegmentDataPointer =
-		Virtual_to_Bus32(bio_data(BufferHeader));
-	      ScatterGatherList[SegmentNumber].SegmentByteCount =
-		BufferHeader->bi_size;
-	      LastDataEndPointer = bio_data(BufferHeader) +
-		BufferHeader->bi_size;
-	      if (SegmentNumber++ > Controller->DriverScatterGatherLimit)
-		panic("DAC960: Scatter/Gather Segment Overflow\n");
-	    }
-	  BufferHeader = BufferHeader->bi_next;
-	}
-      if (SegmentNumber != Command->SegmentCount)
-	panic("DAC960: SegmentNumber != SegmentCount\n");
+      CommandMailbox->Type5.BusAddress = Command->V1.ScatterGatherListDMA;
+
+      CommandMailbox->Type5.ScatterGatherCount = SegCount;
+
+      for (i = 0; i < SegCount; i++, ScatterList++, ScatterGatherList++) {
+		ScatterGatherList->SegmentDataPointer =
+			(DAC960_BusAddress32_T)sg_dma_address(ScatterList);
+		ScatterGatherList->SegmentByteCount =
+			(DAC960_ByteCount32_T)sg_dma_len(ScatterList);
+      }
     }
   DAC960_QueueCommand(Command);
 }
@@ -2739,18 +3111,32 @@ static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
+  struct scatterlist *ScatterList = Command->V2.ScatterList;
+  int DmaDirection, SegCount;
+
   DAC960_V2_ClearCommand(Command);
+
+  if (Command->CommandType == DAC960_ReadCommand)
+        DmaDirection = PCI_DMA_FROMDEVICE;
+  else
+        DmaDirection = PCI_DMA_TODEVICE;
+
+  SegCount = blk_rq_map_sg(&Controller->RequestQueue, Command->Request,
+								ScatterList);
+  /* pci_map_sg MAY change the value of SegCount */
+  SegCount = pci_map_sg(Command->PciDevice, ScatterList, SegCount,
+								DmaDirection);
+  Command->SegmentCount = SegCount;
+
   CommandMailbox->SCSI_10.CommandOpcode = DAC960_V2_SCSI_10;
   CommandMailbox->SCSI_10.CommandControlBits.DataTransferControllerToHost =
     (Command->CommandType == DAC960_ReadCommand);
   CommandMailbox->SCSI_10.DataTransferSize =
     Command->BlockCount << DAC960_BlockSizeBits;
-  CommandMailbox->SCSI_10.RequestSenseBusAddress =
-    Virtual_to_Bus64(&Command->V2.RequestSense);
+  CommandMailbox->SCSI_10.RequestSenseBusAddress = Command->V2.RequestSenseDMA;
   CommandMailbox->SCSI_10.PhysicalDevice =
     Controller->V2.LogicalDriveToVirtualDevice[Command->LogicalDriveNumber];
-  CommandMailbox->SCSI_10.RequestSenseSize =
-    sizeof(DAC960_SCSI_RequestSense_T);
+  CommandMailbox->SCSI_10.RequestSenseSize = sizeof(DAC960_SCSI_RequestSense_T);
   CommandMailbox->SCSI_10.CDBLength = 10;
   CommandMailbox->SCSI_10.SCSI_CDB[0] =
     (Command->CommandType == DAC960_ReadCommand ? 0x28 : 0x2A);
@@ -2760,12 +3146,13 @@ static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *Command)
   CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber;
   CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8;
   CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount;
-  if (Command->SegmentCount == 1)
+
+  if (SegCount == 1)
     {
       CommandMailbox->SCSI_10.DataTransferMemoryAddress
 			     .ScatterGatherSegments[0]
 			     .SegmentDataPointer =
-	Virtual_to_Bus64(Command->RequestBuffer);
+	(DAC960_BusAddress64_T)sg_dma_address(ScatterList);
       CommandMailbox->SCSI_10.DataTransferMemoryAddress
 			     .ScatterGatherSegments[0]
 			     .SegmentByteCount =
@@ -2773,49 +3160,30 @@ static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *Command)
     }
   else
     {
-      DAC960_V2_ScatterGatherSegment_T
-	*ScatterGatherList = Command->V2.ScatterGatherList;
-      BufferHeader_T *BufferHeader = Command->BufferHeader;
-      char *LastDataEndPointer = NULL;
-      int SegmentNumber = 0;
-      if (Command->SegmentCount > 2)
+      DAC960_V2_ScatterGatherSegment_T *ScatterGatherList;
+      int i;
+
+      if (SegCount > 2)
 	{
+          ScatterGatherList = Command->V2.ScatterGatherList;
 	  CommandMailbox->SCSI_10.CommandControlBits
 			 .AdditionalScatterGatherListMemory = true;
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
-			 .ExtendedScatterGather.ScatterGatherList0Length =
-	    Command->SegmentCount;
+		.ExtendedScatterGather.ScatterGatherList0Length = SegCount;
 	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
 			 .ExtendedScatterGather.ScatterGatherList0Address =
-	    Virtual_to_Bus64(ScatterGatherList);
+	    Command->V2.ScatterGatherListDMA;
 	}
       else
-	ScatterGatherList =
-	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
+	ScatterGatherList = CommandMailbox->SCSI_10.DataTransferMemoryAddress
 				 .ScatterGatherSegments;
-      while (BufferHeader != NULL)
-	{
-	  if (bio_data(BufferHeader) == LastDataEndPointer)
-	    {
-	      ScatterGatherList[SegmentNumber-1].SegmentByteCount +=
-		BufferHeader->bi_size;
-	      LastDataEndPointer += BufferHeader->bi_size;
-	    }
-	  else
-	    {
-	      ScatterGatherList[SegmentNumber].SegmentDataPointer =
-		Virtual_to_Bus64(bio_data(BufferHeader));
-	      ScatterGatherList[SegmentNumber].SegmentByteCount =
-		BufferHeader->bi_size;
-	      LastDataEndPointer = bio_data(BufferHeader) +
-		BufferHeader->bi_size;
-	      if (SegmentNumber++ > Controller->DriverScatterGatherLimit)
-		panic("DAC960: Scatter/Gather Segment Overflow\n");
-	    }
-	  BufferHeader = BufferHeader->bi_next;
-	}
-      if (SegmentNumber != Command->SegmentCount)
-	panic("DAC960: SegmentNumber != SegmentCount\n");
+
+      for (i = 0; i < SegCount; i++, ScatterList++, ScatterGatherList++) {
+		ScatterGatherList->SegmentDataPointer =
+			(DAC960_BusAddress64_T)sg_dma_address(ScatterList);
+		ScatterGatherList->SegmentByteCount =
+			(DAC960_ByteCount64_T)sg_dma_len(ScatterList);
+      }
     }
   DAC960_QueueCommand(Command);
 }
@@ -2832,32 +3200,36 @@ static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
 				     boolean WaitForCommand)
 {
   RequestQueue_T *RequestQueue = &Controller->RequestQueue;
-  ListHead_T *RequestQueueHead;
   IO_Request_T *Request;
   DAC960_Command_T *Command;
-  if (RequestQueue == NULL) return false;
-  RequestQueueHead = &RequestQueue->queue_head;
-  while (true)
-    {
-      if (list_empty(RequestQueueHead)) return false;
+
+  if (!Controller->ControllerInitialized)
+     return false;
+
+  while (true) {
+      if (blk_queue_empty(RequestQueue))
+          return false;
+
       Request = elv_next_request(RequestQueue);
       Command = DAC960_AllocateCommand(Controller);
-      if (Command != NULL) break;
-      if (!WaitForCommand) return false;
+      if (Command != NULL)
+          break;
+
+      if (!WaitForCommand)
+          return false;
+
       DAC960_WaitForCommand(Controller);
-    }
-  if (Request->cmd == READ)
+  }
+  if (rq_data_dir(Request) == READ)
     Command->CommandType = DAC960_ReadCommand;
-  else Command->CommandType = DAC960_WriteCommand;
+  else
+    Command->CommandType = DAC960_WriteCommand;
   Command->Completion = Request->waiting;
   Command->LogicalDriveNumber = (int)Request->rq_disk->private_data;
   Command->BlockNumber = Request->sector;
   Command->BlockCount = Request->nr_sectors;
-  Command->SegmentCount = Request->nr_phys_segments;
-  Command->BufferHeader = Request->bio;
-  Command->RequestBuffer = Request->buffer;
+  Command->Request = Request;
   blkdev_dequeue_request(Request);
-  blk_put_request(Request);
   DAC960_QueueReadWriteCommand(Command);
   return true;
 }
@@ -2904,16 +3276,43 @@ static void DAC960_RequestFunction(RequestQueue_T *RequestQueue)
   individual Buffer.
 */
 
-static inline void DAC960_ProcessCompletedBuffer(BufferHeader_T *BufferHeader,
+static inline void DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
 						 boolean SuccessfulIO)
 {
-  bio_endio(BufferHeader, BufferHeader->bi_size, SuccessfulIO ? 0 : -EIO);
-  blk_finished_io(bio_sectors(BufferHeader));
-}
-
-static inline int DAC960_PartitionByCommand(DAC960_Command_T *Command)
-{
-	return (int)Command->BufferHeader->bi_bdev->bd_disk->private_data;
+	DAC960_CommandType_T CommandType = Command->CommandType;
+	IO_Request_T *Request = Command->Request;
+	int DmaDirection, UpToDate;
+
+	UpToDate = 0;
+	if (SuccessfulIO)
+		UpToDate = 1;
+
+	/*
+	 * We could save DmaDirection in the command structure
+	 * and just reuse that information here.
+	 */
+	if (CommandType == DAC960_ReadCommand ||
+		CommandType == DAC960_ReadRetryCommand)
+		DmaDirection = PCI_DMA_FROMDEVICE;
+	else
+		DmaDirection = PCI_DMA_TODEVICE;
+
+	pci_unmap_sg(Command->PciDevice, Command->V1.ScatterList,
+		Command->SegmentCount, DmaDirection);
+	/*
+	 * BlockCount is redundant with nr_sectors in the request
+	 * structure.  Consider eliminating BlockCount from the
+	 * command structure now that Command includes a pointer to
+	 * the request.
+	 */
+	 while (end_that_request_first(Request, UpToDate, Command->BlockCount))
+		 ;
+ 	 end_that_request_last(Request);
+
+	if (Command->Completion) {
+		complete(Command->Completion);
+		Command->Completion = NULL;
+	}
 }
 
 /*
@@ -2966,13 +3365,6 @@ static void DAC960_V1_ReadWriteError(DAC960_Command_T *Command)
 	       Controller, Controller->ControllerNumber,
 	       Command->LogicalDriveNumber, Command->BlockNumber,
 	       Command->BlockNumber + Command->BlockCount - 1);
-  if (DAC960_PartitionByCommand(Command) > 0)
-    DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %u..%u\n",
-		 Controller, Controller->ControllerNumber,
-		 Command->LogicalDriveNumber,
-		 DAC960_PartitionByCommand(Command),
-		 Command->BufferHeader->bi_sector,
-		 Command->BufferHeader->bi_sector + Command->BlockCount - 1);
 }
 
 
@@ -2988,129 +3380,60 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
   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)
+
+		DAC960_ProcessCompletedRequest(Command, true);
+
+      else if (CommandStatus == DAC960_V1_IrrecoverableDataError ||
+		CommandStatus == DAC960_V1_BadDataEncountered)
 	{
+
 	  /*
-	    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_disk_randomness(Controller->disks[Command->LogicalDriveNumber]);
-	}
-      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 = BufferHeader->bi_size >> DAC960_BlockSizeBits;
-	  CommandMailbox->Type5.LD.TransferLength = Command->BlockCount;
-	  CommandMailbox->Type5.BusAddress =
-	    Virtual_to_Bus32(bio_data(BufferHeader));
-	  DAC960_QueueCommand(Command);
-	  return;
+	   * Finish this later.
+	   *
+	   * We should call "complete_that_request_first()"
+	   * to remove the first part of the request.  Then, if there
+	   * is still more I/O to be done, resubmit the request.
+	   *
+	   * We want to recalculate scatter/gather list,
+	   * and requeue the command.
+	   *
+	   * For now, print a message on the console, and clone
+	   * the code for "normal" completion.
+	   */
+	  printk("V1_ProcessCompletedCommand: I/O error on read/write\n");
+
+	  DAC960_ProcessCompletedRequest(Command, false);
 	}
       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;
-	    }
+
+	  DAC960_ProcessCompletedRequest(Command, false);
 	}
     }
   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 +=
-	    BufferHeader->bi_size >> DAC960_BlockSizeBits;
-	  Command->BlockCount =
-	    NextBufferHeader->bi_size >> 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;
-	}
+	/*
+	 * We're not doing retry commands yet.
+	 */
+	printk("DAC960_ProcessCompletedCommand: RetryCommand not done yet\n");
     }
-  else if (CommandType == DAC960_MonitoringCommand ||
-	   CommandOpcode == DAC960_V1_Enquiry ||
-	   CommandOpcode == DAC960_V1_GetRebuildProgress)
+
+  else if (CommandType == DAC960_MonitoringCommand)
     {
-      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)
+      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;
+	  DAC960_V1_Enquiry_T *NewEnquiry = Controller->V1.NewEnquiry;
 	  unsigned int OldCriticalLogicalDriveCount =
 	    OldEnquiry->CriticalLogicalDriveCount;
 	  unsigned int NewCriticalLogicalDriveCount =
@@ -3220,17 +3543,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	    (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)
+	  if (NewEnquiry->RebuildFlag > DAC960_V1_BackgroundCheckInProgress)
 	    {
 	      Controller->V1.PendingRebuildFlag = NewEnquiry->RebuildFlag;
 	      Controller->V1.RebuildFlagPending = true;
@@ -3256,7 +3569,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 		 "killed due to SCSI phase sequence error",
 		 "killed due to unknown status" };
 	  DAC960_V1_EventLogEntry_T *EventLogEntry =
-	    &Controller->V1.EventLogEntry;
+	    	Controller->V1.EventLogEntry;
 	  if (EventLogEntry->SequenceNumber ==
 	      Controller->V1.OldEventLogSequenceNumber)
 	    {
@@ -3316,7 +3629,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
       else if (CommandOpcode == DAC960_V1_GetErrorTable)
 	{
 	  DAC960_V1_ErrorTable_T *OldErrorTable = &Controller->V1.ErrorTable;
-	  DAC960_V1_ErrorTable_T *NewErrorTable = &Controller->V1.NewErrorTable;
+	  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++)
@@ -3342,7 +3655,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 				  NewErrorEntry->HardErrorCount,
 				  NewErrorEntry->MiscErrorCount);
 	      }
-	  memcpy(&Controller->V1.ErrorTable, &Controller->V1.NewErrorTable,
+	  memcpy(&Controller->V1.ErrorTable, Controller->V1.NewErrorTable,
 		 sizeof(DAC960_V1_ErrorTable_T));
 	}
       else if (CommandOpcode == DAC960_V1_GetDeviceState)
@@ -3351,7 +3664,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	    &Controller->V1.DeviceState[Controller->V1.DeviceStateChannel]
 				       [Controller->V1.DeviceStateTargetID];
 	  DAC960_V1_DeviceState_T *NewDeviceState =
-	    &Controller->V1.NewDeviceState;
+	    Controller->V1.NewDeviceState;
 	  if (NewDeviceState->DeviceState != OldDeviceState->DeviceState)
 	    DAC960_Critical("Physical Device %d:%d is now %s\n", Controller,
 			    Controller->V1.DeviceStateChannel,
@@ -3387,7 +3700,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	      DAC960_V1_LogicalDriveInformation_T *OldLogicalDriveInformation =
 		&Controller->V1.LogicalDriveInformation[LogicalDriveNumber];
 	      DAC960_V1_LogicalDriveInformation_T *NewLogicalDriveInformation =
-		&Controller->V1.NewLogicalDriveInformation[LogicalDriveNumber];
+		&(*Controller->V1.NewLogicalDriveInformation)[LogicalDriveNumber];
 	      if (NewLogicalDriveInformation->LogicalDriveState !=
 		  OldLogicalDriveInformation->LogicalDriveState)
 		DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
@@ -3412,17 +3725,17 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 				 ? "WRITE BACK" : "WRITE THRU"));
 	    }
 	  memcpy(&Controller->V1.LogicalDriveInformation,
-		 &Controller->V1.NewLogicalDriveInformation,
+		 Controller->V1.NewLogicalDriveInformation,
 		 sizeof(DAC960_V1_LogicalDriveInformationArray_T));
 	}
       else if (CommandOpcode == DAC960_V1_GetRebuildProgress)
 	{
 	  unsigned int LogicalDriveNumber =
-	    Controller->V1.RebuildProgress.LogicalDriveNumber;
+	    Controller->V1.RebuildProgress->LogicalDriveNumber;
 	  unsigned int LogicalDriveSize =
-	    Controller->V1.RebuildProgress.LogicalDriveSize;
+	    Controller->V1.RebuildProgress->LogicalDriveSize;
 	  unsigned int BlocksCompleted =
-	    LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks;
+	    LogicalDriveSize - Controller->V1.RebuildProgress->RemainingBlocks;
 	  if (CommandStatus == DAC960_V1_NoRebuildOrCheckInProgress &&
 	      Controller->V1.LastRebuildStatus == DAC960_V1_NormalCompletion)
 	    CommandStatus = DAC960_V1_RebuildSuccessful;
@@ -3479,11 +3792,11 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
       else if (CommandOpcode == DAC960_V1_RebuildStat)
 	{
 	  unsigned int LogicalDriveNumber =
-	    Controller->V1.RebuildProgress.LogicalDriveNumber;
+	    Controller->V1.RebuildProgress->LogicalDriveNumber;
 	  unsigned int LogicalDriveSize =
-	    Controller->V1.RebuildProgress.LogicalDriveSize;
+	    Controller->V1.RebuildProgress->LogicalDriveSize;
 	  unsigned int BlocksCompleted =
-	    LogicalDriveSize - Controller->V1.RebuildProgress.RemainingBlocks;
+	    LogicalDriveSize - Controller->V1.RebuildProgress->RemainingBlocks;
 	  if (CommandStatus == DAC960_V1_NormalCompletion)
 	    {
 	      Controller->EphemeralProgressMessage = true;
@@ -3501,15 +3814,15 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
       else if (CommandOpcode == DAC960_V1_BackgroundInitializationControl)
 	{
 	  unsigned int LogicalDriveNumber =
-	    Controller->V1.BackgroundInitializationStatus.LogicalDriveNumber;
+	    Controller->V1.BackgroundInitializationStatus->LogicalDriveNumber;
 	  unsigned int LogicalDriveSize =
-	    Controller->V1.BackgroundInitializationStatus.LogicalDriveSize;
+	    Controller->V1.BackgroundInitializationStatus->LogicalDriveSize;
 	  unsigned int BlocksCompleted =
-	    Controller->V1.BackgroundInitializationStatus.BlocksCompleted;
+	    Controller->V1.BackgroundInitializationStatus->BlocksCompleted;
 	  switch (CommandStatus)
 	    {
 	    case DAC960_V1_NormalCompletion:
-	      switch (Controller->V1.BackgroundInitializationStatus.Status)
+	      switch (Controller->V1.BackgroundInitializationStatus->Status)
 		{
 		case DAC960_V1_BackgroundInitializationInvalid:
 		  break;
@@ -3519,11 +3832,11 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 		  break;
 		case DAC960_V1_BackgroundInitializationInProgress:
 		  if (BlocksCompleted ==
-		      Controller->V1.LastBackgroundInitializationStatus
-				    .BlocksCompleted &&
+		      Controller->V1.LastBackgroundInitializationStatus.
+				BlocksCompleted &&
 		      LogicalDriveNumber ==
-		      Controller->V1.LastBackgroundInitializationStatus
-				    .LogicalDriveNumber)
+		      Controller->V1.LastBackgroundInitializationStatus.
+				LogicalDriveNumber)
 		    break;
 		  Controller->EphemeralProgressMessage = true;
 		  DAC960_Progress("Background Initialization in Progress: "
@@ -3546,32 +3859,84 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 		  break;
 		}
 	      memcpy(&Controller->V1.LastBackgroundInitializationStatus,
-		     &Controller->V1.BackgroundInitializationStatus,
+		     Controller->V1.BackgroundInitializationStatus,
 		     sizeof(DAC960_V1_BackgroundInitializationStatus_T));
 	      break;
 	    case DAC960_V1_BackgroundInitSuccessful:
-	      if (Controller->V1.BackgroundInitializationStatus.Status ==
+	      if (Controller->V1.BackgroundInitializationStatus->Status ==
 		  DAC960_V1_BackgroundInitializationInProgress)
 		DAC960_Progress("Background Initialization "
 				"Completed Successfully\n", Controller);
-	      Controller->V1.BackgroundInitializationStatus.Status =
+	      Controller->V1.BackgroundInitializationStatus->Status =
 		DAC960_V1_BackgroundInitializationInvalid;
 	      break;
 	    case DAC960_V1_BackgroundInitAborted:
-	      if (Controller->V1.BackgroundInitializationStatus.Status ==
+	      if (Controller->V1.BackgroundInitializationStatus->Status ==
 		  DAC960_V1_BackgroundInitializationInProgress)
 		DAC960_Progress("Background Initialization Aborted\n",
 				Controller);
-	      Controller->V1.BackgroundInitializationStatus.Status =
+	      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;
+	     }
 	}
-    }
-  if (CommandType == DAC960_MonitoringCommand)
-    {
+      /*
+        Begin submitting new monitoring commands.
+       */
       if (Controller->V1.NewEventLogSequenceNumber
 	  - Controller->V1.OldEventLogSequenceNumber > 0)
 	{
@@ -3583,7 +3948,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	  Command->V1.CommandMailbox.Type3E.SequenceNumber =
 	    Controller->V1.OldEventLogSequenceNumber;
 	  Command->V1.CommandMailbox.Type3E.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.EventLogEntry);
+	    	Controller->V1.EventLogEntryDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3593,7 +3958,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetErrorTable;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.NewErrorTable);
+	    	Controller->V1.NewErrorTableDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3604,7 +3969,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetRebuildProgress;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
+	    Controller->V1.RebuildProgressDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3612,15 +3977,14 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	{
 	  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;
+	      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 =
-		Virtual_to_Bus32(DCDB);
+	      Command->V1.CommandMailbox.Type3.BusAddress = DCDB_DMA;
 	      DCDB->Channel = Controller->V1.DeviceStateChannel;
 	      DCDB->TargetID = Controller->V1.DeviceStateTargetID;
 	      DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem;
@@ -3629,7 +3993,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	      DCDB->NoAutomaticRequestSense = false;
 	      DCDB->DisconnectPermitted = true;
 	      DCDB->TransferLength = sizeof(DAC960_SCSI_Inquiry_T);
-	      DCDB->BusAddress = Virtual_to_Bus32(InquiryStandardData);
+	      DCDB->BusAddress = NewInquiryStandardDataDMA;
 	      DCDB->CDBLength = 6;
 	      DCDB->TransferLengthHigh4 = 0;
 	      DCDB->SenseLength = sizeof(DCDB->SenseData);
@@ -3640,20 +4004,17 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	      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;
+	      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 =
-		Virtual_to_Bus32(DCDB);
+	      Command->V1.CommandMailbox.Type3.BusAddress = DCDB_DMA;
 	      DCDB->Channel = Controller->V1.DeviceStateChannel;
 	      DCDB->TargetID = Controller->V1.DeviceStateTargetID;
 	      DCDB->Direction = DAC960_V1_DCDB_DataTransferDeviceToSystem;
@@ -3663,7 +4024,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	      DCDB->DisconnectPermitted = true;
 	      DCDB->TransferLength =
 		sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-	      DCDB->BusAddress = Virtual_to_Bus32(InquiryUnitSerialNumber);
+	      DCDB->BusAddress = NewInquiryUnitSerialNumberDMA;
 	      DCDB->CDBLength = 6;
 	      DCDB->TransferLengthHigh4 = 0;
 	      DCDB->SenseLength = sizeof(DCDB->SenseData);
@@ -3674,7 +4035,6 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	      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)
@@ -3690,7 +4050,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	    }
 	  if (Controller->V1.DeviceStateChannel < Controller->Channels)
 	    {
-	      Controller->V1.NewDeviceState.DeviceState =
+	      Controller->V1.NewDeviceState->DeviceState =
 		DAC960_V1_Device_Dead;
 	      Command->V1.CommandMailbox.Type3D.CommandOpcode =
 		DAC960_V1_GetDeviceState;
@@ -3699,7 +4059,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	      Command->V1.CommandMailbox.Type3D.TargetID =
 		Controller->V1.DeviceStateTargetID;
 	      Command->V1.CommandMailbox.Type3D.BusAddress =
-		Virtual_to_Bus32(&Controller->V1.NewDeviceState);
+		Controller->V1.NewDeviceStateDMA;
 	      DAC960_QueueCommand(Command);
 	      return;
 	    }
@@ -3711,7 +4071,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetLogicalDriveInformation;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.NewLogicalDriveInformation);
+	    Controller->V1.NewLogicalDriveInformationDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3721,7 +4081,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_GetRebuildProgress;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
+	    	Controller->V1.RebuildProgressDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3731,7 +4091,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	  Command->V1.CommandMailbox.Type3.CommandOpcode =
 	    DAC960_V1_RebuildStat;
 	  Command->V1.CommandMailbox.Type3.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.RebuildProgress);
+	    Controller->V1.RebuildProgressDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
@@ -3742,14 +4102,14 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
 	    DAC960_V1_BackgroundInitializationControl;
 	  Command->V1.CommandMailbox.Type3B.CommandOpcode2 = 0x20;
 	  Command->V1.CommandMailbox.Type3B.BusAddress =
-	    Virtual_to_Bus32(&Controller->V1.BackgroundInitializationStatus);
+	    Controller->V1.BackgroundInitializationStatusDMA;
 	  DAC960_QueueCommand(Command);
 	  return;
 	}
       Controller->MonitoringTimerCount++;
       Controller->MonitoringTimer.expires =
 	jiffies + DAC960_MonitoringTimerInterval;
-      add_timer(&Controller->MonitoringTimer);
+      	add_timer(&Controller->MonitoringTimer);
     }
   if (CommandType == DAC960_ImmediateCommand)
     {
@@ -3825,18 +4185,11 @@ static void DAC960_V2_ReadWriteError(DAC960_Command_T *Command)
       break;
     }
   DAC960_Error("Error Condition %s on %s:\n", Controller,
-	       SenseErrors[Command->V2.RequestSense.SenseKey], CommandName);
+	       SenseErrors[Command->V2.RequestSense->SenseKey], CommandName);
   DAC960_Error("  /dev/rd/c%dd%d:   absolute blocks %u..%u\n",
 	       Controller, Controller->ControllerNumber,
 	       Command->LogicalDriveNumber, Command->BlockNumber,
 	       Command->BlockNumber + Command->BlockCount - 1);
-  if (DAC960_PartitionByCommand(Command) > 0)
-    DAC960_Error("  /dev/rd/c%dd%dp%d: relative blocks %u..%u\n",
-		 Controller, Controller->ControllerNumber,
-		 Command->LogicalDriveNumber,
-		 DAC960_PartitionByCommand(Command),
-		 Command->BufferHeader->bi_sector,
-		 Command->BufferHeader->bi_sector + Command->BlockCount - 1);
 }
 
 
@@ -4094,123 +4447,51 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_IOCTL_Opcode_T CommandOpcode = CommandMailbox->Common.IOCTL_Opcode;
   DAC960_V2_CommandStatus_T CommandStatus = Command->V2.CommandStatus;
-  BufferHeader_T *BufferHeader = Command->BufferHeader;
+
   if (CommandType == DAC960_ReadCommand ||
       CommandType == DAC960_WriteCommand)
     {
       if (CommandStatus == DAC960_V2_NormalCompletion)
+
+		DAC960_ProcessCompletedRequest(Command, true);
+
+      else if (Command->V2.RequestSense->SenseKey == DAC960_SenseKey_MediumError)
 	{
+	  
 	  /*
-	    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_disk_randomness(Controller->disks[Command->LogicalDriveNumber]);
-	}
-      else if (Command->V2.RequestSense.SenseKey
-	       == DAC960_SenseKey_MediumError &&
-	       BufferHeader != NULL &&
-	       BufferHeader->bi_next != NULL)
-	{
-	  if (CommandType == DAC960_ReadCommand)
-	    Command->CommandType = DAC960_ReadRetryCommand;
-	  else Command->CommandType = DAC960_WriteRetryCommand;
-	  Command->BlockCount = BufferHeader->bi_size >> DAC960_BlockSizeBits;
-	  CommandMailbox->SCSI_10.CommandControlBits
-				 .AdditionalScatterGatherListMemory = false;
-	  CommandMailbox->SCSI_10.DataTransferSize =
-	    Command->BlockCount << DAC960_BlockSizeBits;
-	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				 .ScatterGatherSegments[0].SegmentDataPointer =
-	    Virtual_to_Bus64(bio_data(BufferHeader));
-	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				 .ScatterGatherSegments[0].SegmentByteCount =
-	    CommandMailbox->SCSI_10.DataTransferSize;
-	  CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8;
-	  CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount;
-	  DAC960_QueueCommand(Command);
-	  return;
+	   * Don't know yet how to handle this case.  
+	   * See comments in DAC960_V1_ProcessCompletedCommand()
+	   *
+	   * For now, print a message on the console, and clone
+	   * the code for "normal" completion.
+	   */
+	  printk("V1_ProcessCompletedCommand: I/O error on read/write\n");
+
+	  DAC960_ProcessCompletedRequest(Command, false);
 	}
       else
 	{
-	  if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady)
+	  if (Command->V2.RequestSense->SenseKey != DAC960_SenseKey_NotReady)
 	    DAC960_V2_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;
-	    }
+          DAC960_ProcessCompletedRequest(Command, false);
 	}
     }
   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_V2_NormalCompletion)
-	DAC960_ProcessCompletedBuffer(BufferHeader, true);
-      else
-	{
-	  if (Command->V2.RequestSense.SenseKey != DAC960_SenseKey_NotReady)
-	    DAC960_V2_ReadWriteError(Command);
-	  DAC960_ProcessCompletedBuffer(BufferHeader, false);
-	}
-      if (NextBufferHeader != NULL)
-	{
-	  Command->BlockNumber +=
-	    BufferHeader->bi_size >> DAC960_BlockSizeBits;
-	  Command->BlockCount =
-	    NextBufferHeader->bi_size >> DAC960_BlockSizeBits;
-	  Command->BufferHeader = NextBufferHeader;
-	  CommandMailbox->SCSI_10.DataTransferSize =
-	    Command->BlockCount << DAC960_BlockSizeBits;
-	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				 .ScatterGatherSegments[0]
-				 .SegmentDataPointer =
-	    Virtual_to_Bus64(bio_data(NextBufferHeader));
-	  CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				 .ScatterGatherSegments[0]
-				 .SegmentByteCount =
-	    CommandMailbox->SCSI_10.DataTransferSize;
-	  CommandMailbox->SCSI_10.SCSI_CDB[2] = Command->BlockNumber >> 24;
-	  CommandMailbox->SCSI_10.SCSI_CDB[3] = Command->BlockNumber >> 16;
-	  CommandMailbox->SCSI_10.SCSI_CDB[4] = Command->BlockNumber >> 8;
-	  CommandMailbox->SCSI_10.SCSI_CDB[5] = Command->BlockNumber;
-	  CommandMailbox->SCSI_10.SCSI_CDB[7] = Command->BlockCount >> 8;
-	  CommandMailbox->SCSI_10.SCSI_CDB[8] = Command->BlockCount;
-	  DAC960_QueueCommand(Command);
-	  return;
-	}
+	printk("DAC960_V2_ProcessCompletedCommand: retries not coded yet\n");
     }
   else if (CommandType == DAC960_MonitoringCommand)
     {
+      if (Controller->ShutdownMonitoringTimer)
+	      return;
       if (CommandOpcode == DAC960_V2_GetControllerInfo)
 	{
 	  DAC960_V2_ControllerInfo_T *NewControllerInfo =
-	    &Controller->V2.NewControllerInformation;
+	    Controller->V2.NewControllerInformation;
 	  DAC960_V2_ControllerInfo_T *ControllerInfo =
 	    &Controller->V2.ControllerInformation;
 	  Controller->LogicalDriveCount =
@@ -4229,15 +4510,16 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
 	}
       else if (CommandOpcode == DAC960_V2_GetEvent)
 	{
-	  if (CommandStatus == DAC960_V2_NormalCompletion)
-	    DAC960_V2_ReportEvent(Controller, &Controller->V2.Event);
+	  if (CommandStatus == DAC960_V2_NormalCompletion) {
+	    DAC960_V2_ReportEvent(Controller, Controller->V2.Event);
+	  }
 	  Controller->V2.NextEventSequenceNumber++;
 	}
       else if (CommandOpcode == DAC960_V2_GetPhysicalDeviceInfoValid &&
 	       CommandStatus == DAC960_V2_NormalCompletion)
 	{
 	  DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo =
-	    &Controller->V2.NewPhysicalDeviceInformation;
+	    Controller->V2.NewPhysicalDeviceInformation;
 	  unsigned int PhysicalDeviceIndex = Controller->V2.PhysicalDeviceIndex;
 	  DAC960_V2_PhysicalDeviceInfo_T *PhysicalDeviceInfo =
 	    Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex];
@@ -4448,7 +4730,7 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
 	       CommandStatus == DAC960_V2_NormalCompletion)
 	{
 	  DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo =
-	    &Controller->V2.NewLogicalDeviceInformation;
+	    Controller->V2.NewLogicalDeviceInformation;
 	  unsigned short LogicalDeviceNumber =
 	    NewLogicalDeviceInfo->LogicalDeviceNumber;
 	  DAC960_V2_LogicalDeviceInfo_T *LogicalDeviceInfo =
@@ -4598,6 +4880,23 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
 	    }
 	  Controller->V2.NeedLogicalDeviceInformation = false;
 	}
+      else if (CommandOpcode == DAC960_V2_SCSI_10_Passthru)
+        {
+	    DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
+		Controller->V2.InquiryUnitSerialNumber[Controller->V2.PhysicalDeviceIndex - 1];
+
+	    if (CommandStatus != DAC960_V2_NormalCompletion) {
+		memset(InquiryUnitSerialNumber,
+			0, sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+		InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
+	    } else
+	  	memcpy(InquiryUnitSerialNumber,
+			Controller->V2.NewInquiryUnitSerialNumber,
+			sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T));
+
+	     Controller->V2.NeedDeviceSerialNumberInformation = false;
+        }
+
       if (Controller->V2.HealthStatusBuffer->NextEventSequenceNumber
 	  - Controller->V2.NextEventSequenceNumber > 0)
 	{
@@ -4613,7 +4912,7 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
 	  CommandMailbox->GetEvent.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentDataPointer =
-	    Virtual_to_Bus64(&Controller->V2.Event);
+	    Controller->V2.EventDMA;
 	  CommandMailbox->GetEvent.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentByteCount =
@@ -4626,62 +4925,41 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
 	  if (Controller->V2.NeedDeviceSerialNumberInformation)
 	    {
 	      DAC960_SCSI_Inquiry_UnitSerialNumber_T *InquiryUnitSerialNumber =
-		Controller->V2.InquiryUnitSerialNumber
-			       [Controller->V2.PhysicalDeviceIndex - 1];
+                Controller->V2.NewInquiryUnitSerialNumber;
 	      InquiryUnitSerialNumber->PeripheralDeviceType = 0x1F;
-	      CommandMailbox->SCSI_10.CommandOpcode =
-		DAC960_V2_SCSI_10_Passthru;
-	      CommandMailbox->SCSI_10.DataTransferSize =
-		sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-	      CommandMailbox->SCSI_10.PhysicalDevice.LogicalUnit =
-		Controller->V2.NewPhysicalDeviceInformation.LogicalUnit - 1;
-	      CommandMailbox->SCSI_10.PhysicalDevice.TargetID =
-		Controller->V2.NewPhysicalDeviceInformation.TargetID;
-	      CommandMailbox->SCSI_10.PhysicalDevice.Channel =
-		Controller->V2.NewPhysicalDeviceInformation.Channel;
-	      CommandMailbox->SCSI_10.CDBLength = 6;
-	      CommandMailbox->SCSI_10.SCSI_CDB[0] = 0x12; /* INQUIRY */
-	      CommandMailbox->SCSI_10.SCSI_CDB[1] = 1; /* EVPD = 1 */
-	      CommandMailbox->SCSI_10.SCSI_CDB[2] = 0x80; /* Page Code */
-	      CommandMailbox->SCSI_10.SCSI_CDB[3] = 0; /* Reserved */
-	      CommandMailbox->SCSI_10.SCSI_CDB[4] =
-		sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T);
-	      CommandMailbox->SCSI_10.SCSI_CDB[5] = 0; /* Control */
-	      CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				     .ScatterGatherSegments[0]
-				     .SegmentDataPointer =
-		Virtual_to_Bus64(InquiryUnitSerialNumber);
-	      CommandMailbox->SCSI_10.DataTransferMemoryAddress
-				     .ScatterGatherSegments[0]
-				     .SegmentByteCount =
-		CommandMailbox->SCSI_10.DataTransferSize;
+
+	      DAC960_V2_ConstructNewUnitSerialNumber(Controller, CommandMailbox,
+			Controller->V2.NewPhysicalDeviceInformation->Channel,
+			Controller->V2.NewPhysicalDeviceInformation->TargetID,
+		Controller->V2.NewPhysicalDeviceInformation->LogicalUnit - 1);
+
+
 	      DAC960_QueueCommand(Command);
-	      Controller->V2.NeedDeviceSerialNumberInformation = false;
 	      return;
 	    }
 	  if (Controller->V2.StartPhysicalDeviceInformationScan)
 	    {
 	      Controller->V2.PhysicalDeviceIndex = 0;
-	      Controller->V2.NewPhysicalDeviceInformation.Channel = 0;
-	      Controller->V2.NewPhysicalDeviceInformation.TargetID = 0;
-	      Controller->V2.NewPhysicalDeviceInformation.LogicalUnit = 0;
+	      Controller->V2.NewPhysicalDeviceInformation->Channel = 0;
+	      Controller->V2.NewPhysicalDeviceInformation->TargetID = 0;
+	      Controller->V2.NewPhysicalDeviceInformation->LogicalUnit = 0;
 	      Controller->V2.StartPhysicalDeviceInformationScan = false;
 	    }
 	  CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
 	  CommandMailbox->PhysicalDeviceInfo.DataTransferSize =
 	    sizeof(DAC960_V2_PhysicalDeviceInfo_T);
 	  CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.LogicalUnit =
-	    Controller->V2.NewPhysicalDeviceInformation.LogicalUnit;
+	    Controller->V2.NewPhysicalDeviceInformation->LogicalUnit;
 	  CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.TargetID =
-	    Controller->V2.NewPhysicalDeviceInformation.TargetID;
+	    Controller->V2.NewPhysicalDeviceInformation->TargetID;
 	  CommandMailbox->PhysicalDeviceInfo.PhysicalDevice.Channel =
-	    Controller->V2.NewPhysicalDeviceInformation.Channel;
+	    Controller->V2.NewPhysicalDeviceInformation->Channel;
 	  CommandMailbox->PhysicalDeviceInfo.IOCTL_Opcode =
 	    DAC960_V2_GetPhysicalDeviceInfoValid;
 	  CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 					    .ScatterGatherSegments[0]
 					    .SegmentDataPointer =
-	    Virtual_to_Bus64(&Controller->V2.NewPhysicalDeviceInformation);
+	    Controller->V2.NewPhysicalDeviceInformationDMA;
 	  CommandMailbox->PhysicalDeviceInfo.DataTransferMemoryAddress
 					    .ScatterGatherSegments[0]
 					    .SegmentByteCount =
@@ -4699,21 +4977,20 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
 		   LogicalDriveNumber++)
 		Controller->V2.LogicalDriveFoundDuringScan
 			       [LogicalDriveNumber] = false;
-	      Controller->V2.NewLogicalDeviceInformation
-			    .LogicalDeviceNumber = 0;
+	      Controller->V2.NewLogicalDeviceInformation->LogicalDeviceNumber = 0;
 	      Controller->V2.StartLogicalDeviceInformationScan = false;
 	    }
 	  CommandMailbox->LogicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
 	  CommandMailbox->LogicalDeviceInfo.DataTransferSize =
 	    sizeof(DAC960_V2_LogicalDeviceInfo_T);
 	  CommandMailbox->LogicalDeviceInfo.LogicalDevice.LogicalDeviceNumber =
-	    Controller->V2.NewLogicalDeviceInformation.LogicalDeviceNumber;
+	    Controller->V2.NewLogicalDeviceInformation->LogicalDeviceNumber;
 	  CommandMailbox->LogicalDeviceInfo.IOCTL_Opcode =
 	    DAC960_V2_GetLogicalDeviceInfoValid;
 	  CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 					   .ScatterGatherSegments[0]
 					   .SegmentDataPointer =
-	    Virtual_to_Bus64(&Controller->V2.NewLogicalDeviceInformation);
+	    Controller->V2.NewLogicalDeviceInformationDMA;
 	  CommandMailbox->LogicalDeviceInfo.DataTransferMemoryAddress
 					   .ScatterGatherSegments[0]
 					   .SegmentByteCount =
@@ -4724,7 +5001,7 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
       Controller->MonitoringTimerCount++;
       Controller->MonitoringTimer.expires =
 	jiffies + DAC960_HealthStatusMonitoringInterval;
-      add_timer(&Controller->MonitoringTimer);
+      	add_timer(&Controller->MonitoringTimer);
     }
   if (CommandType == DAC960_ImmediateCommand)
     {
@@ -5002,6 +5279,10 @@ static void DAC960_PD_InterruptHandler(int IRQ_Channel,
 /*
   DAC960_P_InterruptHandler handles hardware interrupts from DAC960 P Series
   Controllers.
+
+  Translations of DAC960_V1_Enquiry and DAC960_V1_GetDeviceState rely
+  on the data having been placed into DAC960_Controller_T, rather than
+  an arbitrary buffer.
 */
 
 static void DAC960_P_InterruptHandler(int IRQ_Channel,
@@ -5034,14 +5315,12 @@ static void DAC960_P_InterruptHandler(int IRQ_Channel,
 	{
 	case DAC960_V1_Enquiry_Old:
 	  Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Enquiry;
-	  DAC960_P_To_PD_TranslateEnquiry(
-	    Bus32_to_Virtual(CommandMailbox->Type3.BusAddress));
+	  DAC960_P_To_PD_TranslateEnquiry(Controller->V1.NewEnquiry);
 	  break;
 	case DAC960_V1_GetDeviceState_Old:
 	  Command->V1.CommandMailbox.Common.CommandOpcode =
-	    DAC960_V1_GetDeviceState;
-	  DAC960_P_To_PD_TranslateDeviceState(
-	    Bus32_to_Virtual(CommandMailbox->Type3.BusAddress));
+	    					DAC960_V1_GetDeviceState;
+	  DAC960_P_To_PD_TranslateDeviceState(Controller->V1.NewDeviceState);
 	  break;
 	case DAC960_V1_Read_Old:
 	  Command->V1.CommandMailbox.Common.CommandOpcode = DAC960_V1_Read;
@@ -5090,8 +5369,7 @@ static void DAC960_V1_QueueMonitoringCommand(DAC960_Command_T *Command)
   DAC960_V1_ClearCommand(Command);
   Command->CommandType = DAC960_MonitoringCommand;
   CommandMailbox->Type3.CommandOpcode = DAC960_V1_Enquiry;
-  CommandMailbox->Type3.BusAddress =
-    Virtual_to_Bus32(&Controller->V1.NewEnquiry);
+  CommandMailbox->Type3.BusAddress = Controller->V1.NewEnquiryDMA;
   DAC960_QueueCommand(Command);
 }
 
@@ -5119,7 +5397,7 @@ static void DAC960_V2_QueueMonitoringCommand(DAC960_Command_T *Command)
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentDataPointer =
-    Virtual_to_Bus64(&Controller->V2.NewControllerInformation);
+    Controller->V2.NewControllerInformationDMA;
   CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 				.ScatterGatherSegments[0]
 				.SegmentByteCount =
@@ -5198,7 +5476,7 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
 	{
 	  Controller->MonitoringTimer.expires =
 	    jiffies + DAC960_HealthStatusMonitoringInterval;
-	  add_timer(&Controller->MonitoringTimer);
+	    add_timer(&Controller->MonitoringTimer);
 	  return;
 	}
       Controller->V2.StatusChangeCounter = StatusChangeCounter;
@@ -5225,6 +5503,7 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
     }
 }
 
+
 /*
   DAC960_Open is the Device Open Function for the DAC960 Driver.
 */
@@ -5423,14 +5702,17 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	DAC960_V1_CommandOpcode_T CommandOpcode;
 	DAC960_V1_CommandStatus_T CommandStatus;
 	DAC960_V1_DCDB_T DCDB;
+	DAC960_V1_DCDB_T *DCDB_IOBUF = NULL;
+	dma_addr_t	DCDB_IOBUFDMA;
 	ProcessorFlags_T ProcessorFlags;
 	int ControllerNumber, DataTransferLength;
 	unsigned char *DataTransferBuffer = NULL;
+	dma_addr_t DataTransferBufferDMA;
 	if (UserSpaceUserCommand == NULL) return -EINVAL;
 	if (copy_from_user(&UserCommand, UserSpaceUserCommand,
 				   sizeof(DAC960_V1_UserCommand_T))) {
 		ErrorCode = -EFAULT;
-		goto Failure1;
+		goto Failure1a;
 	}
 	ControllerNumber = UserCommand.ControllerNumber;
 	if (ControllerNumber < 0 ||
@@ -5447,7 +5729,7 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	    if (copy_from_user(&DCDB, UserCommand.DCDB,
 			       sizeof(DAC960_V1_DCDB_T))) {
 		ErrorCode = -EFAULT;
-		goto Failure1;
+		goto Failure1a;
 	    }
 	    if (DCDB.Channel >= DAC960_V1_MaxChannels) return -EINVAL;
 	    if (!((DataTransferLength == 0 &&
@@ -5463,17 +5745,29 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	    if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength)
 		!= abs(DataTransferLength))
 	      return -EINVAL;
+	    DCDB_IOBUF = pci_alloc_consistent(Controller->PCIDevice,
+			sizeof(DAC960_V1_DCDB_T), &DCDB_IOBUFDMA);
+	    if (DCDB_IOBUF == NULL)
+			return -ENOMEM;
 	  }
 	if (DataTransferLength > 0)
 	  {
-	    DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL);
-	    if (DataTransferBuffer == NULL) return -ENOMEM;
+	    DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+				DataTransferLength, &DataTransferBufferDMA);
+	    if (DataTransferBuffer == NULL) {
+		ErrorCode = -ENOMEM;
+		goto Failure1;
+	    }
 	    memset(DataTransferBuffer, 0, DataTransferLength);
 	  }
 	else if (DataTransferLength < 0)
 	  {
-	    DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL);
-	    if (DataTransferBuffer == NULL) return -ENOMEM;
+	    DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+				-DataTransferLength, &DataTransferBufferDMA);
+	    if (DataTransferBuffer == NULL) {
+		ErrorCode = -ENOMEM;
+		goto Failure1;
+	    }
 	    if (copy_from_user(DataTransferBuffer,
 			       UserCommand.DataTransferBuffer,
 			       -DataTransferLength)) {
@@ -5489,11 +5783,11 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	    while (Controller->V1.DirectCommandActive[DCDB.Channel]
 						     [DCDB.TargetID])
 	      {
-		spin_unlock_irq(Controller->RequestQueue.queue_lock);
+		spin_unlock_irq(&Controller->queue_lock);
 		__wait_event(Controller->CommandWaitQueue,
 			     !Controller->V1.DirectCommandActive
 					     [DCDB.Channel][DCDB.TargetID]);
-		spin_lock_irq(Controller->RequestQueue.queue_lock);
+		spin_lock_irq(&Controller->queue_lock);
 	      }
 	    Controller->V1.DirectCommandActive[DCDB.Channel]
 					      [DCDB.TargetID] = true;
@@ -5502,9 +5796,9 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	    Command->CommandType = DAC960_ImmediateCommand;
 	    memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox,
 		   sizeof(DAC960_V1_CommandMailbox_T));
-	    Command->V1.CommandMailbox.Type3.BusAddress =
-	      Virtual_to_Bus32(&DCDB);
-	    DCDB.BusAddress = Virtual_to_Bus32(DataTransferBuffer);
+	    Command->V1.CommandMailbox.Type3.BusAddress = DCDB_IOBUFDMA;
+	    DCDB.BusAddress = DataTransferBufferDMA;
+	    memcpy(DCDB_IOBUF, &DCDB, sizeof(DAC960_V1_DCDB_T));
 	  }
 	else
 	  {
@@ -5518,7 +5812,7 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 		   sizeof(DAC960_V1_CommandMailbox_T));
 	    if (DataTransferBuffer != NULL)
 	      Command->V1.CommandMailbox.Type3.BusAddress =
-		Virtual_to_Bus32(DataTransferBuffer);
+		DataTransferBufferDMA;
 	  }
 	DAC960_ExecuteCommand(Command);
 	CommandStatus = Command->V1.CommandStatus;
@@ -5528,15 +5822,20 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	if (DataTransferLength > 0)
 	  {
 	    if (copy_to_user(UserCommand.DataTransferBuffer,
-			     DataTransferBuffer, DataTransferLength))
+			     DataTransferBuffer, DataTransferLength)) {
 		ErrorCode = -EFAULT;
 		goto Failure1;
+            }
 	  }
 	if (CommandOpcode == DAC960_V1_DCDB)
 	  {
+	    /*
+	      I don't believe Target or Channel in the DCDB_IOBUF
+	      should be any different from the contents of DCDB.
+	     */
 	    Controller->V1.DirectCommandActive[DCDB.Channel]
 					      [DCDB.TargetID] = false;
-	    if (copy_to_user(UserCommand.DCDB, &DCDB,
+	    if (copy_to_user(UserCommand.DCDB, DCDB_IOBUF,
 			     sizeof(DAC960_V1_DCDB_T))) {
 		ErrorCode = -EFAULT;
 		goto Failure1;
@@ -5545,7 +5844,12 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	ErrorCode = CommandStatus;
       Failure1:
 	if (DataTransferBuffer != NULL)
-	  kfree(DataTransferBuffer);
+	  pci_free_consistent(Controller->PCIDevice, abs(DataTransferLength),
+			DataTransferBuffer, DataTransferBufferDMA);
+	if (DCDB_IOBUF != NULL)
+	  pci_free_consistent(Controller->PCIDevice, sizeof(DAC960_V1_DCDB_T),
+			DCDB_IOBUF, DCDB_IOBUFDMA);
+      Failure1a:
 	return ErrorCode;
       }
     case DAC960_IOCTL_V2_EXECUTE_COMMAND:
@@ -5561,12 +5865,14 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	int ControllerNumber, DataTransferLength;
 	int DataTransferResidue, RequestSenseLength;
 	unsigned char *DataTransferBuffer = NULL;
+	dma_addr_t DataTransferBufferDMA;
 	unsigned char *RequestSenseBuffer = NULL;
+	dma_addr_t RequestSenseBufferDMA;
 	if (UserSpaceUserCommand == NULL) return -EINVAL;
 	if (copy_from_user(&UserCommand, UserSpaceUserCommand,
 			   sizeof(DAC960_V2_UserCommand_T))) {
 		ErrorCode = -EFAULT;
-		goto Failure2;
+		goto Failure2a;
 	}
 	ControllerNumber = UserCommand.ControllerNumber;
 	if (ControllerNumber < 0 ||
@@ -5578,13 +5884,15 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	DataTransferLength = UserCommand.DataTransferLength;
 	if (DataTransferLength > 0)
 	  {
-	    DataTransferBuffer = kmalloc(DataTransferLength, GFP_KERNEL);
+	    DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+				DataTransferLength, &DataTransferBufferDMA);
 	    if (DataTransferBuffer == NULL) return -ENOMEM;
 	    memset(DataTransferBuffer, 0, DataTransferLength);
 	  }
 	else if (DataTransferLength < 0)
 	  {
-	    DataTransferBuffer = kmalloc(-DataTransferLength, GFP_KERNEL);
+	    DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+				-DataTransferLength, &DataTransferBufferDMA);
 	    if (DataTransferBuffer == NULL) return -ENOMEM;
 	    if (copy_from_user(DataTransferBuffer,
 			       UserCommand.DataTransferBuffer,
@@ -5596,7 +5904,8 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	RequestSenseLength = UserCommand.RequestSenseLength;
 	if (RequestSenseLength > 0)
 	  {
-	    RequestSenseBuffer = kmalloc(RequestSenseLength, GFP_KERNEL);
+	    RequestSenseBuffer = pci_alloc_consistent(Controller->PCIDevice,
+			RequestSenseLength, &RequestSenseBufferDMA);
 	    if (RequestSenseBuffer == NULL)
 	      {
 		ErrorCode = -ENOMEM;
@@ -5637,8 +5946,7 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	      }
 	    CommandMailbox->Common.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
-				  .SegmentDataPointer =
-	      Virtual_to_Bus64(DataTransferBuffer);
+				  .SegmentDataPointer = DataTransferBufferDMA;
 	    CommandMailbox->Common.DataTransferMemoryAddress
 				  .ScatterGatherSegments[0]
 				  .SegmentByteCount =
@@ -5650,7 +5958,7 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 				  .NoAutoRequestSense = false;
 	    CommandMailbox->Common.RequestSenseSize = RequestSenseLength;
 	    CommandMailbox->Common.RequestSenseBusAddress =
-	      Virtual_to_Bus64(RequestSenseBuffer);
+	      						RequestSenseBufferDMA;
 	  }
 	DAC960_ExecuteCommand(Command);
 	CommandStatus = Command->V2.CommandStatus;
@@ -5690,10 +5998,12 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 	  }
 	ErrorCode = CommandStatus;
       Failure2:
-	if (DataTransferBuffer != NULL)
-	  kfree(DataTransferBuffer);
+	  pci_free_consistent(Controller->PCIDevice, abs(DataTransferLength),
+		DataTransferBuffer, DataTransferBufferDMA);
 	if (RequestSenseBuffer != NULL)
-	  kfree(RequestSenseBuffer);
+	  pci_free_consistent(Controller->PCIDevice, RequestSenseLength,
+		RequestSenseBuffer, RequestSenseBufferDMA);
+      Failure2a:
 	return ErrorCode;
       }
     case DAC960_IOCTL_V2_GET_HEALTH_STATUS:
@@ -5739,226 +6049,6 @@ static int DAC960_UserIOCTL(Inode_T *Inode, File_T *File,
 }
 
 
-/*
-  DAC960_KernelIOCTL is the Kernel IOCTL Function for the DAC960 Driver.
-*/
-
-int DAC960_KernelIOCTL(unsigned int Request, void *Argument)
-{
-  switch (Request)
-    {
-    case DAC960_IOCTL_GET_CONTROLLER_COUNT:
-      return DAC960_ControllerCount;
-    case DAC960_IOCTL_GET_CONTROLLER_INFO:
-      {
-	DAC960_ControllerInfo_T *ControllerInfo =
-	  (DAC960_ControllerInfo_T *) Argument;
-	DAC960_Controller_T *Controller;
-	int ControllerNumber;
-	if (ControllerInfo == NULL) return -EINVAL;
-	ControllerNumber = ControllerInfo->ControllerNumber;
-	if (ControllerNumber < 0 ||
-	    ControllerNumber > DAC960_ControllerCount - 1)
-	  return -ENXIO;
-	Controller = DAC960_Controllers[ControllerNumber];
-	if (Controller == NULL) return -ENXIO;
-	memset(ControllerInfo, 0, sizeof(DAC960_ControllerInfo_T));
-	ControllerInfo->ControllerNumber = ControllerNumber;
-	ControllerInfo->FirmwareType = Controller->FirmwareType;
-	ControllerInfo->Channels = Controller->Channels;
-	ControllerInfo->Targets = Controller->Targets;
-	ControllerInfo->PCI_Bus = Controller->Bus;
-	ControllerInfo->PCI_Device = Controller->Device;
-	ControllerInfo->PCI_Function = Controller->Function;
-	ControllerInfo->IRQ_Channel = Controller->IRQ_Channel;
-	ControllerInfo->PCI_Address = Controller->PCI_Address;
-	strcpy(ControllerInfo->ModelName, Controller->ModelName);
-	strcpy(ControllerInfo->FirmwareVersion, Controller->FirmwareVersion);
-	return 0;
-      }
-    case DAC960_IOCTL_V1_EXECUTE_COMMAND:
-      {
-	DAC960_V1_KernelCommand_T *KernelCommand =
-	  (DAC960_V1_KernelCommand_T *) Argument;
-	DAC960_Controller_T *Controller;
-	DAC960_Command_T *Command = NULL;
-	DAC960_V1_CommandOpcode_T CommandOpcode;
-	DAC960_V1_DCDB_T *DCDB = NULL;
-	ProcessorFlags_T ProcessorFlags;
-	int ControllerNumber, DataTransferLength;
-	unsigned char *DataTransferBuffer = NULL;
-	if (KernelCommand == NULL) return -EINVAL;
-	ControllerNumber = KernelCommand->ControllerNumber;
-	if (ControllerNumber < 0 ||
-	    ControllerNumber > DAC960_ControllerCount - 1)
-	  return -ENXIO;
-	Controller = DAC960_Controllers[ControllerNumber];
-	if (Controller == NULL) return -ENXIO;
-	if (Controller->FirmwareType != DAC960_V1_Controller) return -EINVAL;
-	CommandOpcode = KernelCommand->CommandMailbox.Common.CommandOpcode;
-	DataTransferLength = KernelCommand->DataTransferLength;
-	DataTransferBuffer = KernelCommand->DataTransferBuffer;
-	if (CommandOpcode & 0x80) return -EINVAL;
-	if (CommandOpcode == DAC960_V1_DCDB)
-	  {
-	    DCDB = KernelCommand->DCDB;
-	    if (DCDB->Channel >= DAC960_V1_MaxChannels) return -EINVAL;
-	    if (!((DataTransferLength == 0 &&
-		   DCDB->Direction == DAC960_V1_DCDB_NoDataTransfer) ||
-		  (DataTransferLength > 0 &&
-		   DCDB->Direction
-		   == DAC960_V1_DCDB_DataTransferDeviceToSystem) ||
-		  (DataTransferLength < 0 &&
-		   DCDB->Direction
-		   == DAC960_V1_DCDB_DataTransferSystemToDevice)))
-	      return -EINVAL;
-	    if (((DCDB->TransferLengthHigh4 << 16) | DCDB->TransferLength)
-		!= abs(DataTransferLength))
-	      return -EINVAL;
-	  }
-	if (DataTransferLength != 0 && DataTransferBuffer == NULL)
-	  return -EINVAL;
-	if (DataTransferLength > 0)
-	  memset(DataTransferBuffer, 0, DataTransferLength);
-	if (CommandOpcode == DAC960_V1_DCDB)
-	  {
-	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-	    if (!Controller->V1.DirectCommandActive[DCDB->Channel]
-						   [DCDB->TargetID])
-	      Command = DAC960_AllocateCommand(Controller);
-	    if (Command == NULL)
-	      {
-		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-		return -EBUSY;
-	      }
-	    else Controller->V1.DirectCommandActive[DCDB->Channel]
-						   [DCDB->TargetID] = true;
-	    DAC960_V1_ClearCommand(Command);
-	    Command->CommandType = DAC960_QueuedCommand;
-	    memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox,
-		   sizeof(DAC960_V1_CommandMailbox_T));
-	    Command->V1.CommandMailbox.Type3.BusAddress =
-	      Virtual_to_Bus32(DCDB);
-	    Command->V1.KernelCommand = KernelCommand;
-	    DCDB->BusAddress = Virtual_to_Bus32(DataTransferBuffer);
-	    DAC960_QueueCommand(Command);
-	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-	  }
-	else
-	  {
-	    DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-	    Command = DAC960_AllocateCommand(Controller);
-	    if (Command == NULL)
-	      {
-		DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-		return -EBUSY;
-	      }
-	    DAC960_V1_ClearCommand(Command);
-	    Command->CommandType = DAC960_QueuedCommand;
-	    memcpy(&Command->V1.CommandMailbox, &KernelCommand->CommandMailbox,
-		   sizeof(DAC960_V1_CommandMailbox_T));
-	    if (DataTransferBuffer != NULL)
-	      Command->V1.CommandMailbox.Type3.BusAddress =
-		Virtual_to_Bus32(DataTransferBuffer);
-	    Command->V1.KernelCommand = KernelCommand;
-	    DAC960_QueueCommand(Command);
-	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-	  }
-	return 0;
-      }
-    case DAC960_IOCTL_V2_EXECUTE_COMMAND:
-      {
-	DAC960_V2_KernelCommand_T *KernelCommand =
-	  (DAC960_V2_KernelCommand_T *) Argument;
-	DAC960_Controller_T *Controller;
-	DAC960_Command_T *Command = NULL;
-	DAC960_V2_CommandMailbox_T *CommandMailbox;
-	ProcessorFlags_T ProcessorFlags;
-	int ControllerNumber, DataTransferLength, RequestSenseLength;
-	unsigned char *DataTransferBuffer = NULL;
-	unsigned char *RequestSenseBuffer = NULL;
-	if (KernelCommand == NULL) return -EINVAL;
-	ControllerNumber = KernelCommand->ControllerNumber;
-	if (ControllerNumber < 0 ||
-	    ControllerNumber > DAC960_ControllerCount - 1)
-	  return -ENXIO;
-	Controller = DAC960_Controllers[ControllerNumber];
-	if (Controller == NULL) return -ENXIO;
-	if (Controller->FirmwareType != DAC960_V2_Controller) return -EINVAL;
-	DataTransferLength = KernelCommand->DataTransferLength;
-	RequestSenseLength = KernelCommand->RequestSenseLength;
-	DataTransferBuffer = KernelCommand->DataTransferBuffer;
-	RequestSenseBuffer = KernelCommand->RequestSenseBuffer;
-	if (DataTransferLength != 0 && DataTransferBuffer == NULL)
-	  return -EINVAL;
-	if (RequestSenseLength < 0)
-	  return -EINVAL;
-	if (RequestSenseLength > 0 && RequestSenseBuffer == NULL)
-	  return -EINVAL;
-	if (DataTransferLength > 0)
-	  memset(DataTransferBuffer, 0, DataTransferLength);
-	if (RequestSenseLength > 0)
-	  memset(RequestSenseBuffer, 0, RequestSenseLength);
-	DAC960_AcquireControllerLock(Controller, &ProcessorFlags);
-	Command = DAC960_AllocateCommand(Controller);
-	if (Command == NULL)
-	  {
-	    DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-	    return -EBUSY;
-	  }
-	DAC960_V2_ClearCommand(Command);
-	Command->CommandType = DAC960_QueuedCommand;
-	CommandMailbox = &Command->V2.CommandMailbox;
-	memcpy(CommandMailbox, &KernelCommand->CommandMailbox,
-	       sizeof(DAC960_V2_CommandMailbox_T));
-	CommandMailbox->Common.CommandControlBits
-			      .AdditionalScatterGatherListMemory = false;
-	CommandMailbox->Common.CommandControlBits
-			      .NoAutoRequestSense = true;
-	CommandMailbox->Common.DataTransferSize = 0;
-	CommandMailbox->Common.DataTransferPageNumber = 0;
-	memset(&CommandMailbox->Common.DataTransferMemoryAddress, 0,
-	       sizeof(DAC960_V2_DataTransferMemoryAddress_T));
-	if (DataTransferLength != 0)
-	  {
-	    if (DataTransferLength > 0)
-	      {
-		CommandMailbox->Common.CommandControlBits
-				      .DataTransferControllerToHost = true;
-		CommandMailbox->Common.DataTransferSize = DataTransferLength;
-	      }
-	    else
-	      {
-		CommandMailbox->Common.CommandControlBits
-				      .DataTransferControllerToHost = false;
-		CommandMailbox->Common.DataTransferSize = -DataTransferLength;
-	      }
-	    CommandMailbox->Common.DataTransferMemoryAddress
-				  .ScatterGatherSegments[0]
-				  .SegmentDataPointer =
-	      Virtual_to_Bus64(DataTransferBuffer);
-	    CommandMailbox->Common.DataTransferMemoryAddress
-				  .ScatterGatherSegments[0]
-				  .SegmentByteCount =
-	      CommandMailbox->Common.DataTransferSize;
-	  }
-	if (RequestSenseLength > 0)
-	  {
-	    CommandMailbox->Common.CommandControlBits
-				  .NoAutoRequestSense = false;
-	    CommandMailbox->Common.RequestSenseBusAddress =
-	      Virtual_to_Bus64(RequestSenseBuffer);
-	  }
-	Command->V2.KernelCommand = KernelCommand;
-	DAC960_QueueCommand(Command);
-	DAC960_ReleaseControllerLock(Controller, &ProcessorFlags);
-	return 0;
-      }
-    }
-  return -EINVAL;
-}
-
-
 /*
   DAC960_CheckStatusBuffer verifies that there is room to hold ByteCount
   additional bytes in the Combined Status Buffer and grows the buffer if
@@ -6381,11 +6471,25 @@ static boolean DAC960_V1_ExecuteUserCommand(DAC960_Controller_T *Controller,
   else if (strcmp(UserCommand, "cancel-rebuild") == 0 ||
 	   strcmp(UserCommand, "cancel-consistency-check") == 0)
     {
-      unsigned char OldRebuildRateConstant;
+      /*
+        the OldRebuildRateConstant is never actually used
+        once its value is retrieved from the controller.
+       */
+      unsigned char *OldRebuildRateConstant;
+      dma_addr_t OldRebuildRateConstantDMA;
+
+      OldRebuildRateConstant = pci_alloc_consistent( Controller->PCIDevice,
+		sizeof(char), &OldRebuildRateConstantDMA);
+      if (OldRebuildRateConstant == NULL) {
+         DAC960_UserCritical("Cancellation of Rebuild or "
+			     "Consistency Check Failed - "
+			     "Out of Memory",
+                             Controller);
+	 goto failure;
+      }
       CommandMailbox->Type3R.CommandOpcode = DAC960_V1_RebuildControl;
       CommandMailbox->Type3R.RebuildRateConstant = 0xFF;
-      CommandMailbox->Type3R.BusAddress =
-	Virtual_to_Bus32(&OldRebuildRateConstant);
+      CommandMailbox->Type3R.BusAddress = OldRebuildRateConstantDMA;
       DAC960_ExecuteCommand(Command);
       switch (Command->V1.CommandStatus)
 	{
@@ -6400,6 +6504,9 @@ static boolean DAC960_V1_ExecuteUserCommand(DAC960_Controller_T *Controller,
 			      Controller, Command->V1.CommandStatus);
 	  break;
 	}
+failure:
+  	pci_free_consistent(Controller->PCIDevice, sizeof(char),
+		OldRebuildRateConstant, OldRebuildRateConstantDMA);
     }
   else DAC960_UserCritical("Illegal User Command: '%s'\n",
 			   Controller, UserCommand);
@@ -6423,10 +6530,12 @@ static boolean DAC960_V2_TranslatePhysicalDevice(DAC960_Command_T *Command,
 						   *LogicalDeviceNumber)
 {
   DAC960_V2_CommandMailbox_T SavedCommandMailbox, *CommandMailbox;
-  DAC960_V2_PhysicalToLogicalDevice_T PhysicalToLogicalDevice;
+  DAC960_Controller_T *Controller =  Command->Controller;
+
   CommandMailbox = &Command->V2.CommandMailbox;
   memcpy(&SavedCommandMailbox, CommandMailbox,
 	 sizeof(DAC960_V2_CommandMailbox_T));
+
   CommandMailbox->PhysicalDeviceInfo.CommandOpcode = DAC960_V2_IOCTL;
   CommandMailbox->PhysicalDeviceInfo.CommandControlBits
 				    .DataTransferControllerToHost = true;
@@ -6441,15 +6550,17 @@ static boolean DAC960_V2_TranslatePhysicalDevice(DAC960_Command_T *Command,
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentDataPointer =
-    Virtual_to_Bus64(&PhysicalToLogicalDevice);
+    		Controller->V2.PhysicalToLogicalDeviceDMA;
   CommandMailbox->Common.DataTransferMemoryAddress
 			.ScatterGatherSegments[0]
 			.SegmentByteCount =
-    CommandMailbox->Common.DataTransferSize;
+    		CommandMailbox->Common.DataTransferSize;
+
   DAC960_ExecuteCommand(Command);
+  *LogicalDeviceNumber = Controller->V2.PhysicalToLogicalDevice->LogicalDeviceNumber;
+
   memcpy(CommandMailbox, &SavedCommandMailbox,
 	 sizeof(DAC960_V2_CommandMailbox_T));
-  *LogicalDeviceNumber = PhysicalToLogicalDevice.LogicalDeviceNumber;
   return (Command->V2.CommandStatus == DAC960_V2_NormalCompletion);
 }
 
@@ -6635,16 +6746,20 @@ static boolean DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller,
 	  CommandMailbox->ControllerInfo.ControllerNumber = 0;
 	  CommandMailbox->ControllerInfo.IOCTL_Opcode =
 	    DAC960_V2_GetControllerInfo;
+	  /*
+	   * How does this NOT race with the queued Monitoring
+	   * usage of this structure?
+	   */
 	  CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 					.ScatterGatherSegments[0]
 					.SegmentDataPointer =
-	    Virtual_to_Bus64(&Controller->V2.NewControllerInformation);
+	    Controller->V2.NewControllerInformationDMA;
 	  CommandMailbox->ControllerInfo.DataTransferMemoryAddress
 					.ScatterGatherSegments[0]
 					.SegmentByteCount =
 	    CommandMailbox->ControllerInfo.DataTransferSize;
 	  DAC960_ExecuteCommand(Command);
-	  while (Controller->V2.NewControllerInformation.PhysicalScanActive)
+	  while (Controller->V2.NewControllerInformation->PhysicalScanActive)
 	    {
 	      DAC960_ExecuteCommand(Command);
 	      sleep_on_timeout(&Controller->CommandWaitQueue, HZ);
@@ -6817,22 +6932,19 @@ static int DAC960_ProcWriteUserCommand(File_T *File, const char *Buffer,
   DAC960 Driver.
 */
 
-static void DAC960_CreateProcEntries(void)
+static void DAC960_CreateProcEntries(DAC960_Controller_T *Controller)
 {
-  PROC_DirectoryEntry_T *StatusProcEntry;
-  int ControllerNumber;
-  DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL);
-  StatusProcEntry = create_proc_read_entry("status", 0,
+	PROC_DirectoryEntry_T *StatusProcEntry;
+	PROC_DirectoryEntry_T *ControllerProcEntry;
+	PROC_DirectoryEntry_T *UserCommandProcEntry;
+
+	if (DAC960_ProcDirectoryEntry == NULL) {
+  		DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL);
+  		StatusProcEntry = create_proc_read_entry("status", 0,
 					   DAC960_ProcDirectoryEntry,
 					   DAC960_ProcReadStatus, NULL);
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-      PROC_DirectoryEntry_T *ControllerProcEntry;
-      PROC_DirectoryEntry_T *UserCommandProcEntry;
-      if (Controller == NULL) continue;
+	}
+
       sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
       ControllerProcEntry = proc_mkdir(Controller->ControllerName,
 				       DAC960_ProcDirectoryEntry);
@@ -6846,7 +6958,6 @@ static void DAC960_CreateProcEntries(void)
 			       Controller);
       UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand;
       Controller->ControllerProcEntry = ControllerProcEntry;
-    }
 }
 
 
@@ -6855,26 +6966,138 @@ static void DAC960_CreateProcEntries(void)
   DAC960 Driver.
 */
 
-static void DAC960_DestroyProcEntries(void)
+static void DAC960_DestroyProcEntries(DAC960_Controller_T *Controller)
 {
-  int ControllerNumber;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-      if (Controller == NULL) continue;
+      if (Controller->ControllerProcEntry == NULL)
+	      return;
       remove_proc_entry("initial_status", Controller->ControllerProcEntry);
       remove_proc_entry("current_status", Controller->ControllerProcEntry);
       remove_proc_entry("user_command", Controller->ControllerProcEntry);
       remove_proc_entry(Controller->ControllerName, DAC960_ProcDirectoryEntry);
-    }
-  remove_proc_entry("rd/status", NULL);
-  remove_proc_entry("rd", NULL);
+      Controller->ControllerProcEntry = NULL;
+}
+
+static struct DAC960_privdata DAC960_BA_privdata = {
+	.HardwareType =		DAC960_BA_Controller,
+	.FirmwareType 	=	DAC960_V2_Controller,
+	.InterruptHandler =	DAC960_BA_InterruptHandler,
+	.MemoryWindowSize =	DAC960_BA_RegisterWindowSize,
+};
+
+static struct DAC960_privdata DAC960_LP_privdata = {
+	.HardwareType =		DAC960_LP_Controller,
+	.FirmwareType 	=	DAC960_LP_Controller,
+	.InterruptHandler =	DAC960_LP_InterruptHandler,
+	.MemoryWindowSize =	DAC960_LP_RegisterWindowSize,
+};
+
+static struct DAC960_privdata DAC960_LA_privdata = {
+	.HardwareType =		DAC960_LA_Controller,
+	.FirmwareType 	=	DAC960_V1_Controller,
+	.InterruptHandler =	DAC960_LA_InterruptHandler,
+	.MemoryWindowSize =	DAC960_LA_RegisterWindowSize,
+};
+
+static struct DAC960_privdata DAC960_PG_privdata = {
+	.HardwareType =		DAC960_PG_Controller,
+	.FirmwareType 	=	DAC960_V1_Controller,
+	.InterruptHandler =	DAC960_PG_InterruptHandler,
+	.MemoryWindowSize =	DAC960_PG_RegisterWindowSize,
+};
+
+static struct DAC960_privdata DAC960_PD_privdata = {
+	.HardwareType =		DAC960_PD_Controller,
+	.FirmwareType 	=	DAC960_V1_Controller,
+	.InterruptHandler =	DAC960_PD_InterruptHandler,
+	.MemoryWindowSize =	DAC960_PD_RegisterWindowSize,
+};
+
+static struct DAC960_privdata DAC960_P_privdata = {
+	.HardwareType =		DAC960_P_Controller,
+	.FirmwareType 	=	DAC960_V1_Controller,
+	.InterruptHandler =	DAC960_P_InterruptHandler,
+	.MemoryWindowSize =	DAC960_PD_RegisterWindowSize,
+};
+
+static struct pci_device_id DAC960_id_table[] = {
+	{
+		.vendor 	= PCI_VENDOR_ID_MYLEX,
+		.device		= PCI_DEVICE_ID_MYLEX_DAC960_BA,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long) &DAC960_BA_privdata,
+	},
+	{
+		.vendor 	= PCI_VENDOR_ID_MYLEX,
+		.device		= PCI_DEVICE_ID_MYLEX_DAC960_LP,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long) &DAC960_LP_privdata,
+	},
+	{
+		.vendor 	= PCI_VENDOR_ID_DEC,
+		.device		= PCI_DEVICE_ID_DEC_21285,
+		.subvendor	= PCI_VENDOR_ID_MYLEX,
+		.subdevice	= PCI_DEVICE_ID_MYLEX_DAC960_LA,
+		.driver_data	= (unsigned long) &DAC960_LA_privdata,
+	},
+	{
+		.vendor 	= PCI_VENDOR_ID_MYLEX,
+		.device		= PCI_DEVICE_ID_MYLEX_DAC960_PG,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long) &DAC960_PG_privdata,
+	},
+	{
+		.vendor 	= PCI_VENDOR_ID_MYLEX,
+		.device		= PCI_DEVICE_ID_MYLEX_DAC960_PD,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long) &DAC960_PD_privdata,
+	},
+	{
+		.vendor 	= PCI_VENDOR_ID_MYLEX,
+		.device		= PCI_DEVICE_ID_MYLEX_DAC960_P,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.driver_data	= (unsigned long) &DAC960_P_privdata,
+	},
+	{0, },
+};
+
+MODULE_DEVICE_TABLE(pci, DAC960_id_table);
+
+static struct pci_driver DAC960_pci_driver = {
+	.name		= "DAC960",
+	.id_table	= DAC960_id_table,
+	.probe		= DAC960_Probe,
+	.remove		= DAC960_Remove,
+};
+
+static int DAC960_init_module(void)
+{
+	return pci_module_init(&DAC960_pci_driver);
 }
 
+static void DAC960_cleanup_module(void)
+{
+	int i;
+
+	for (i = 0; i < DAC960_ControllerCount; i++) {
+		DAC960_Controller_T *Controller = DAC960_Controllers[i];
+		if (Controller == NULL)
+			continue;
+		DAC960_FinalizeController(Controller);
+	}
+	if (DAC960_ProcDirectoryEntry != NULL) {
+  		remove_proc_entry("rd/status", NULL);
+  		remove_proc_entry("rd", NULL);
+	}
+	DAC960_ControllerCount = 0;
+	pci_unregister_driver(&DAC960_pci_driver);
+}
 
-module_init(DAC960_Initialize);
-module_exit(DAC960_Finalize);
+module_init(DAC960_init_module);
+module_exit(DAC960_cleanup_module);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/block/DAC960.h b/drivers/block/DAC960.h
index e66cd95f87dd..1d3ea76554b9 100644
--- a/drivers/block/DAC960.h
+++ b/drivers/block/DAC960.h
@@ -60,6 +60,17 @@
 #define DAC960_V1_MaxPhysicalDevices		45
 #define DAC960_V2_MaxPhysicalDevices		272
 
+/*
+  Define the pci dma mask supported by DAC960 V1 and V2 Firmware Controlers
+
+  For now set the V2 mask to only 32 bits.  The controller IS capable
+  of doing 64 bit dma.  But I have yet to find out whether this needs to
+  be explicitely enabled in the controller, or of the controller adapts
+  automatically.
+ */
+
+#define DAC690_V1_PciDmaMask	0xffffffff
+#define DAC690_V2_PciDmaMask	0xffffffffffffffff
 
 /*
   Define a Boolean data type.
@@ -110,6 +121,20 @@ typedef unsigned int DAC960_ByteCount32_T;
 typedef unsigned long long DAC960_ByteCount64_T;
 
 
+/*
+  dma_loaf is used by helper routines to divide a region of
+  dma mapped memory into smaller pieces, where those pieces
+  are not of uniform size.
+ */
+
+struct dma_loaf {
+	void	*cpu_base;
+	dma_addr_t dma_base;
+	size_t  length;
+	void	*cpu_free;
+	dma_addr_t dma_free;
+};
+
 /*
   Define the SCSI INQUIRY Standard Data structure.
 */
@@ -2059,9 +2084,6 @@ extern int DAC960_KernelIOCTL(unsigned int Request, void *Argument);
 #define DAC960_LogicalDriveNumber(Device) \
   (minor(Device) >> DAC960_MaxPartitionsBits)
 
-#define DAC960_PartitionNumber(Device) \
-  (minor(Device) & (DAC960_MaxPartitions - 1))
-
 #define DAC960_MajorNumber(ControllerNumber) \
   (DAC960_MAJOR + (ControllerNumber))
 
@@ -2191,7 +2213,6 @@ static char
   of the Linux Kernel and I/O Subsystem.
 */
 
-typedef struct bio BufferHeader_T;
 typedef struct file File_T;
 typedef struct block_device_operations BlockDeviceOperations_T;
 typedef struct completion Completion_T;
@@ -2200,7 +2221,6 @@ typedef struct inode Inode_T;
 typedef struct inode_operations InodeOperations_T;
 typedef kdev_t KernelDevice_T;
 typedef struct list_head ListHead_T;
-typedef struct notifier_block NotifierBlock_T;
 typedef struct pci_dev PCI_Device_T;
 typedef struct proc_dir_entry PROC_DirectoryEntry_T;
 typedef unsigned long ProcessorFlags_T;
@@ -2211,6 +2231,13 @@ typedef struct super_block SuperBlock_T;
 typedef struct timer_list Timer_T;
 typedef wait_queue_head_t WaitQueue_T;
 
+struct DAC960_privdata {
+	DAC960_HardwareType_T	HardwareType;
+	DAC960_FirmwareType_T	FirmwareType;
+	void (*InterruptHandler)(int, void *, Registers_T *);
+	unsigned int		MemoryWindowSize;
+};
+
 
 /*
   Define the DAC960 V1 Firmware Controller Status Mailbox structure.
@@ -2278,16 +2305,16 @@ typedef struct DAC960_Command
   unsigned int BlockNumber;
   unsigned int BlockCount;
   unsigned int SegmentCount;
-  BufferHeader_T *BufferHeader;
-  void *RequestBuffer;
+  IO_Request_T *Request;
+  struct pci_dev *PciDevice;
   union {
     struct {
       DAC960_V1_CommandMailbox_T CommandMailbox;
       DAC960_V1_KernelCommand_T *KernelCommand;
       DAC960_V1_CommandStatus_T CommandStatus;
-      DAC960_V1_ScatterGatherSegment_T
-	ScatterGatherList[DAC960_V1_ScatterGatherLimit]
-	__attribute__ ((aligned (sizeof(DAC960_V1_ScatterGatherSegment_T))));
+      DAC960_V1_ScatterGatherSegment_T *ScatterGatherList;
+      dma_addr_t ScatterGatherListDMA;
+      struct scatterlist ScatterList[DAC960_V1_ScatterGatherLimit];
       unsigned int EndMarker[0];
     } V1;
     struct {
@@ -2296,11 +2323,11 @@ typedef struct DAC960_Command
       DAC960_V2_CommandStatus_T CommandStatus;
       unsigned char RequestSenseLength;
       int DataTransferResidue;
-      DAC960_V2_ScatterGatherSegment_T
-	ScatterGatherList[DAC960_V2_ScatterGatherLimit]
-	__attribute__ ((aligned (sizeof(DAC960_V2_ScatterGatherSegment_T))));
-      DAC960_SCSI_RequestSense_T RequestSense
-	__attribute__ ((aligned (sizeof(int))));
+      DAC960_V2_ScatterGatherSegment_T *ScatterGatherList;
+      dma_addr_t ScatterGatherListDMA;
+      DAC960_SCSI_RequestSense_T *RequestSense;
+      dma_addr_t RequestSenseDMA;
+      struct scatterlist ScatterList[DAC960_V2_ScatterGatherLimit];
       unsigned int EndMarker[0];
     } V2;
   } FW;
@@ -2320,6 +2347,7 @@ typedef struct DAC960_Controller
   DAC960_HardwareType_T HardwareType;
   DAC960_IO_Address_T IO_Address;
   DAC960_PCI_Address_T PCI_Address;
+  PCI_Device_T  *PCIDevice;
   unsigned char ControllerNumber;
   unsigned char ControllerName[4];
   unsigned char ModelName[20];
@@ -2345,14 +2373,13 @@ typedef struct DAC960_Controller
   unsigned int CurrentStatusLength;
   unsigned int ProgressBufferLength;
   unsigned int UserStatusLength;
-  unsigned long MemoryMailboxPagesAddress;
-  unsigned long MemoryMailboxPagesOrder;
+  struct dma_loaf DmaPages;
   unsigned long MonitoringTimerCount;
   unsigned long PrimaryMonitoringTime;
   unsigned long SecondaryMonitoringTime;
+  unsigned long ShutdownMonitoringTimer;
   unsigned long LastProgressReportTime;
   unsigned long LastCurrentStatusTime;
-  boolean ControllerDetectionSuccessful;
   boolean ControllerInitialized;
   boolean MonitoringCommandDeferred;
   boolean EphemeralProgressMessage;
@@ -2361,6 +2388,7 @@ typedef struct DAC960_Controller
   boolean SuppressEnclosureMessages;
   Timer_T MonitoringTimer;
   struct gendisk *disks[DAC960_MaxLogicalDrives];
+  struct pci_pool *ScatterGatherPool;
   DAC960_Command_T *FreeCommands;
   unsigned char *CombinedStatusBuffer;
   unsigned char *CurrentStatusBuffer;
@@ -2404,36 +2432,63 @@ typedef struct DAC960_Controller
       boolean RebuildProgressFirst;
       boolean RebuildFlagPending;
       boolean RebuildStatusPending;
+
+      dma_addr_t	FirstCommandMailboxDMA;
       DAC960_V1_CommandMailbox_T *FirstCommandMailbox;
       DAC960_V1_CommandMailbox_T *LastCommandMailbox;
       DAC960_V1_CommandMailbox_T *NextCommandMailbox;
       DAC960_V1_CommandMailbox_T *PreviousCommandMailbox1;
       DAC960_V1_CommandMailbox_T *PreviousCommandMailbox2;
+
+      dma_addr_t	FirstStatusMailboxDMA;
       DAC960_V1_StatusMailbox_T *FirstStatusMailbox;
       DAC960_V1_StatusMailbox_T *LastStatusMailbox;
       DAC960_V1_StatusMailbox_T *NextStatusMailbox;
-      DAC960_V1_DCDB_T MonitoringDCDB;
+
+      DAC960_V1_DCDB_T *MonitoringDCDB;
+      dma_addr_t MonitoringDCDB_DMA;
+
       DAC960_V1_Enquiry_T Enquiry;
-      DAC960_V1_Enquiry_T NewEnquiry;
+      DAC960_V1_Enquiry_T *NewEnquiry;
+      dma_addr_t NewEnquiryDMA;
+
       DAC960_V1_ErrorTable_T ErrorTable;
-      DAC960_V1_ErrorTable_T NewErrorTable;
-      DAC960_V1_EventLogEntry_T EventLogEntry;
-      DAC960_V1_RebuildProgress_T RebuildProgress;
+      DAC960_V1_ErrorTable_T *NewErrorTable;
+      dma_addr_t NewErrorTableDMA;
+
+      DAC960_V1_EventLogEntry_T *EventLogEntry;
+      dma_addr_t EventLogEntryDMA;
+
+      DAC960_V1_RebuildProgress_T *RebuildProgress;
+      dma_addr_t RebuildProgressDMA;
       DAC960_V1_CommandStatus_T LastRebuildStatus;
       DAC960_V1_CommandStatus_T PendingRebuildStatus;
+
       DAC960_V1_LogicalDriveInformationArray_T LogicalDriveInformation;
-      DAC960_V1_LogicalDriveInformationArray_T NewLogicalDriveInformation;
+      DAC960_V1_LogicalDriveInformationArray_T *NewLogicalDriveInformation;
+      dma_addr_t NewLogicalDriveInformationDMA;
+
       DAC960_V1_BackgroundInitializationStatus_T
-        BackgroundInitializationStatus;
+        	*BackgroundInitializationStatus;
+      dma_addr_t BackgroundInitializationStatusDMA;
       DAC960_V1_BackgroundInitializationStatus_T
-        LastBackgroundInitializationStatus;
+        	LastBackgroundInitializationStatus;
+
       DAC960_V1_DeviceState_T
 	DeviceState[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
-      DAC960_V1_DeviceState_T NewDeviceState;
+      DAC960_V1_DeviceState_T *NewDeviceState;
+      dma_addr_t	NewDeviceStateDMA;
+
       DAC960_SCSI_Inquiry_T
 	InquiryStandardData[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
+      DAC960_SCSI_Inquiry_T *NewInquiryStandardData;
+      dma_addr_t NewInquiryStandardDataDMA;
+
       DAC960_SCSI_Inquiry_UnitSerialNumber_T
 	InquiryUnitSerialNumber[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
+      DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber;
+      dma_addr_t NewInquiryUnitSerialNumberDMA;
+
       int DeviceResetCount[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
       boolean DirectCommandActive[DAC960_V1_MaxChannels][DAC960_V1_MaxTargets];
     } V1;
@@ -2446,28 +2501,50 @@ typedef struct DAC960_Controller
       boolean NeedDeviceSerialNumberInformation;
       boolean StartLogicalDeviceInformationScan;
       boolean StartPhysicalDeviceInformationScan;
+      struct pci_pool *RequestSensePool;
+
+      dma_addr_t	FirstCommandMailboxDMA;
       DAC960_V2_CommandMailbox_T *FirstCommandMailbox;
       DAC960_V2_CommandMailbox_T *LastCommandMailbox;
       DAC960_V2_CommandMailbox_T *NextCommandMailbox;
       DAC960_V2_CommandMailbox_T *PreviousCommandMailbox1;
       DAC960_V2_CommandMailbox_T *PreviousCommandMailbox2;
+
+      dma_addr_t	FirstStatusMailboxDMA;
       DAC960_V2_StatusMailbox_T *FirstStatusMailbox;
       DAC960_V2_StatusMailbox_T *LastStatusMailbox;
       DAC960_V2_StatusMailbox_T *NextStatusMailbox;
+
+      dma_addr_t	HealthStatusBufferDMA;
       DAC960_V2_HealthStatusBuffer_T *HealthStatusBuffer;
+
       DAC960_V2_ControllerInfo_T ControllerInformation;
-      DAC960_V2_ControllerInfo_T NewControllerInformation;
+      DAC960_V2_ControllerInfo_T *NewControllerInformation;
+      dma_addr_t	NewControllerInformationDMA;
+
       DAC960_V2_LogicalDeviceInfo_T
 	*LogicalDeviceInformation[DAC960_MaxLogicalDrives];
-      DAC960_V2_LogicalDeviceInfo_T NewLogicalDeviceInformation;
+      DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInformation;
+      dma_addr_t	 NewLogicalDeviceInformationDMA;
+
       DAC960_V2_PhysicalDeviceInfo_T
 	*PhysicalDeviceInformation[DAC960_V2_MaxPhysicalDevices];
-      DAC960_V2_PhysicalDeviceInfo_T NewPhysicalDeviceInformation;
+      DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInformation;
+      dma_addr_t	NewPhysicalDeviceInformationDMA;
+
+      DAC960_SCSI_Inquiry_UnitSerialNumber_T *NewInquiryUnitSerialNumber;
+      dma_addr_t	NewInquiryUnitSerialNumberDMA;
       DAC960_SCSI_Inquiry_UnitSerialNumber_T
 	*InquiryUnitSerialNumber[DAC960_V2_MaxPhysicalDevices];
+
+      DAC960_V2_Event_T *Event;
+      dma_addr_t EventDMA;
+
+      DAC960_V2_PhysicalToLogicalDevice_T *PhysicalToLogicalDevice;
+      dma_addr_t PhysicalToLogicalDeviceDMA;
+
       DAC960_V2_PhysicalDevice_T
 	LogicalDriveToVirtualDevice[DAC960_MaxLogicalDrives];
-      DAC960_V2_Event_T Event;
       boolean LogicalDriveFoundDuringScan[DAC960_MaxLogicalDrives];
     } V2;
   } FW;
@@ -2495,16 +2572,47 @@ DAC960_Controller_T;
 #define DAC960_QueueReadWriteCommand(Command) \
   (Controller->QueueReadWriteCommand)(Command)
 
+/*
+ * dma_addr_writeql is provided to write dma_addr_t types
+ * to a 64-bit pci address space register.  The controller
+ * will accept having the register written as two 32-bit
+ * values.
+ *
+ * In HIGHMEM kernels, dma_addr_t is a 64-bit value.
+ * without HIGHMEM,  dma_addr_t is a 32-bit value.
+ *
+ * The compiler should always fix up the assignment
+ * to u.wq appropriately, depending upon the size of
+ * dma_addr_t.
+ */
+static inline
+void dma_addr_writeql(dma_addr_t addr, void *write_address)
+{
+	union {
+		u64 wq;
+		uint wl[2];
+	} u;
+
+	u.wq = addr;
+
+	writel(u.wl[0], write_address);
+	writel(u.wl[1], write_address + 4);
+}
 
 /*
   DAC960_AcquireControllerLock acquires exclusive access to Controller.
+	Reference the queue_lock through the controller structure,
+	rather than through the request queue.  These macros are
+        used to mutex on the controller structure during initialization,
+	BEFORE the request queue is allocated and initialized in
+	DAC960_RegisterBlockDevice().
 */
 
 static inline
 void DAC960_AcquireControllerLock(DAC960_Controller_T *Controller,
 				  ProcessorFlags_T *ProcessorFlags)
 {
-  spin_lock_irqsave(Controller->RequestQueue.queue_lock, *ProcessorFlags);
+  spin_lock_irqsave(&Controller->queue_lock, *ProcessorFlags);
 }
 
 
@@ -2516,7 +2624,7 @@ static inline
 void DAC960_ReleaseControllerLock(DAC960_Controller_T *Controller,
 				  ProcessorFlags_T *ProcessorFlags)
 {
-  spin_unlock_irqrestore(Controller->RequestQueue.queue_lock, *ProcessorFlags);
+  spin_unlock_irqrestore(&Controller->queue_lock, *ProcessorFlags);
 }
 
 
@@ -2553,7 +2661,7 @@ static inline
 void DAC960_AcquireControllerLockIH(DAC960_Controller_T *Controller,
 				    ProcessorFlags_T *ProcessorFlags)
 {
-  spin_lock_irqsave(Controller->RequestQueue.queue_lock, *ProcessorFlags);
+  spin_lock_irqsave(&Controller->queue_lock, *ProcessorFlags);
 }
 
 
@@ -2566,10 +2674,9 @@ static inline
 void DAC960_ReleaseControllerLockIH(DAC960_Controller_T *Controller,
 				    ProcessorFlags_T *ProcessorFlags)
 {
-  spin_unlock_irqrestore(Controller->RequestQueue.queue_lock, *ProcessorFlags);
+  spin_unlock_irqrestore(&Controller->queue_lock, *ProcessorFlags);
 }
 
-#error I am a non-portable driver, please convert me to use the Documentation/DMA-mapping.txt interfaces
 
 /*
   Define the DAC960 BA Series Controller Interface Register Offsets.
@@ -2834,17 +2941,14 @@ void DAC960_BA_WriteCommandMailbox(DAC960_V2_CommandMailbox_T
   mb();
 }
 
+
 static inline
 void DAC960_BA_WriteHardwareMailbox(void *ControllerBaseAddress,
-				    DAC960_V2_CommandMailbox_T *CommandMailbox)
+				    dma_addr_t CommandMailboxDMA)
 {
-#ifdef __ia64__
-  writeq(Virtual_to_Bus64(CommandMailbox),
-	 ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset);
-#else
-  writel(Virtual_to_Bus32(CommandMailbox),
-	 ControllerBaseAddress + DAC960_BA_CommandMailboxBusAddressOffset);
-#endif
+	dma_addr_writeql(CommandMailboxDMA,
+		ControllerBaseAddress +
+		DAC960_BA_CommandMailboxBusAddressOffset);
 }
 
 static inline DAC960_V2_CommandIdentifier_T
@@ -3142,15 +3246,11 @@ void DAC960_LP_WriteCommandMailbox(DAC960_V2_CommandMailbox_T
 
 static inline
 void DAC960_LP_WriteHardwareMailbox(void *ControllerBaseAddress,
-				    DAC960_V2_CommandMailbox_T *CommandMailbox)
+				    dma_addr_t CommandMailboxDMA)
 {
-#ifdef __ia64__
-  writeq(Virtual_to_Bus64(CommandMailbox),
-	 ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset);
-#else
-  writel(Virtual_to_Bus32(CommandMailbox),
-	 ControllerBaseAddress + DAC960_LP_CommandMailboxBusAddressOffset);
-#endif
+	dma_addr_writeql(CommandMailboxDMA,
+		ControllerBaseAddress +
+		DAC960_LP_CommandMailboxBusAddressOffset);
 }
 
 static inline DAC960_V2_CommandIdentifier_T
@@ -3506,43 +3606,6 @@ DAC960_LA_ReadErrorStatus(void *ControllerBaseAddress,
   return true;
 }
 
-static inline
-void DAC960_LA_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
-{
-#ifdef __i386__
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  writel(0x743C485E,
-	 ControllerBaseAddress + DAC960_LA_CommandOpcodeRegisterOffset);
-  writel((unsigned long) Controller->V1.FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset);
-  writew(Controller->V1.NextCommandMailbox - Controller->V1.FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset);
-  writew(Controller->V1.NextStatusMailbox - Controller->V1.FirstStatusMailbox,
-	 ControllerBaseAddress + DAC960_LA_MailboxRegister10Offset);
-#endif
-}
-
-static inline
-void DAC960_LA_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
-					void **MemoryMailboxAddress,
-					short *NextCommandMailboxIndex,
-					short *NextStatusMailboxIndex)
-{
-#ifdef __i386__
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  if (readl(ControllerBaseAddress
-	    + DAC960_LA_CommandOpcodeRegisterOffset) != 0x743C485E)
-    return;
-  *MemoryMailboxAddress =
-    (void *) readl(ControllerBaseAddress + DAC960_LA_MailboxRegister4Offset);
-  *NextCommandMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_LA_MailboxRegister8Offset);
-  *NextStatusMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_LA_MailboxRegister10Offset);
-#endif
-}
-
-
 /*
   Define the DAC960 PG Series Controller Interface Register Offsets.
 */
@@ -3868,43 +3931,6 @@ DAC960_PG_ReadErrorStatus(void *ControllerBaseAddress,
   return true;
 }
 
-static inline
-void DAC960_PG_SaveMemoryMailboxInfo(DAC960_Controller_T *Controller)
-{
-#ifdef __i386__
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  writel(0x743C485E,
-	 ControllerBaseAddress + DAC960_PG_CommandOpcodeRegisterOffset);
-  writel((unsigned long) Controller->V1.FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset);
-  writew(Controller->V1.NextCommandMailbox - Controller->V1.FirstCommandMailbox,
-	 ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset);
-  writew(Controller->V1.NextStatusMailbox - Controller->V1.FirstStatusMailbox,
-	 ControllerBaseAddress + DAC960_PG_MailboxRegister10Offset);
-#endif
-}
-
-static inline
-void DAC960_PG_RestoreMemoryMailboxInfo(DAC960_Controller_T *Controller,
-					void **MemoryMailboxAddress,
-					short *NextCommandMailboxIndex,
-					short *NextStatusMailboxIndex)
-{
-#ifdef __i386__
-  void *ControllerBaseAddress = Controller->BaseAddress;
-  if (readl(ControllerBaseAddress
-	    + DAC960_PG_CommandOpcodeRegisterOffset) != 0x743C485E)
-    return;
-  *MemoryMailboxAddress =
-    (void *) readl(ControllerBaseAddress + DAC960_PG_MailboxRegister4Offset);
-  *NextCommandMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_PG_MailboxRegister8Offset);
-  *NextStatusMailboxIndex =
-    readw(ControllerBaseAddress + DAC960_PG_MailboxRegister10Offset);
-#endif
-}
-
-
 /*
   Define the DAC960 PD Series Controller Interface Register Offsets.
 */
@@ -4206,9 +4232,8 @@ void DAC960_P_To_PD_TranslateReadWriteCommand(DAC960_V1_CommandMailbox_T
 */
 
 static void DAC960_FinalizeController(DAC960_Controller_T *);
-static int DAC960_Notifier(NotifierBlock_T *, unsigned long, void *);
 static void DAC960_V1_QueueReadWriteCommand(DAC960_Command_T *);
-static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *);
+static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *); 
 static void DAC960_RequestFunction(RequestQueue_T *);
 static void DAC960_BA_InterruptHandler(int, void *, Registers_T *);
 static void DAC960_LP_InterruptHandler(int, void *, Registers_T *);
@@ -4225,7 +4250,7 @@ static int DAC960_IOCTL(Inode_T *, File_T *, unsigned int, unsigned long);
 static int DAC960_UserIOCTL(Inode_T *, File_T *, unsigned int, unsigned long);
 static void DAC960_Message(DAC960_MessageLevel_T, unsigned char *,
 			   DAC960_Controller_T *, ...);
-static void DAC960_CreateProcEntries(void);
-static void DAC960_DestroyProcEntries(void);
+static void DAC960_CreateProcEntries(DAC960_Controller_T *);
+static void DAC960_DestroyProcEntries(DAC960_Controller_T *);
 
 #endif /* DAC960_DriverVersion */
-- 
2.30.9