Update to 3.4-final.
[linux-flexiantxendom0-3.2.10.git] / drivers / block / DAC960.c
index 09cc1c1..9a13e88 100644 (file)
@@ -3,6 +3,7 @@
   Linux Driver for Mylex DAC960/AcceleRAID/eXtremeRAID PCI RAID Controllers
 
   Copyright 1998-2001 by Leonard N. Zubkoff <lnz@dandelion.com>
+  Portions Copyright 2002 by Mylex (An IBM Business Unit)
 
   This program is free software; you may redistribute and/or modify it under
   the terms of the GNU General Public License Version 2 as published by the
 */
 
 
-#define DAC960_DriverVersion                   "2.5.47"
-#define DAC960_DriverDate                      "14 November 2002"
+#define DAC960_DriverVersion                   "2.5.49"
+#define DAC960_DriverDate                      "21 Aug 2007"
 
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/types.h>
-#include <linux/blk.h>
+#include <linux/miscdevice.h>
 #include <linux/blkdev.h>
 #include <linux/bio.h>
 #include <linux/completion.h>
 #include <linux/genhd.h>
 #include <linux/hdreg.h>
 #include <linux/blkpg.h>
+#include <linux/dma-mapping.h>
 #include <linux/interrupt.h>
 #include <linux/ioport.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
+#include <linux/mutex.h>
 #include <linux/proc_fs.h>
+#include <linux/seq_file.h>
 #include <linux/reboot.h>
 #include <linux/spinlock.h>
 #include <linux/timer.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/random.h>
+#include <linux/scatterlist.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include "DAC960.h"
 
+#define DAC960_GAM_MINOR       252
 
+
+static DEFINE_MUTEX(DAC960_mutex);
 static DAC960_Controller_T *DAC960_Controllers[DAC960_MaxControllers];
 static int DAC960_ControllerCount;
 static struct proc_dir_entry *DAC960_ProcDirectoryEntry;
@@ -66,64 +75,57 @@ static long disk_size(DAC960_Controller_T *p, int drive_nr)
        }
 }
 
-static int DAC960_open(struct inode *inode, struct file *file)
+static int DAC960_open(struct block_device *bdev, fmode_t mode)
 {
-       struct gendisk *disk = inode->i_bdev->bd_disk;
+       struct gendisk *disk = bdev->bd_disk;
        DAC960_Controller_T *p = disk->queue->queuedata;
-       int drive_nr = (int)disk->private_data;
-
-       /* bad hack for the "user" ioctls */
-       if (!p->ControllerNumber && !drive_nr && (file->f_flags & O_NONBLOCK))
-               return 0;
+       int drive_nr = (long)disk->private_data;
+       int ret = -ENXIO;
 
+       mutex_lock(&DAC960_mutex);
        if (p->FirmwareType == DAC960_V1_Controller) {
                if (p->V1.LogicalDriveInformation[drive_nr].
                    LogicalDriveState == DAC960_V1_LogicalDrive_Offline)
-                       return -ENXIO;
+                       goto out;
        } else {
                DAC960_V2_LogicalDeviceInfo_T *i =
                        p->V2.LogicalDeviceInformation[drive_nr];
-               if (i->LogicalDeviceState == DAC960_V2_LogicalDevice_Offline)
-                       return -ENXIO;
+               if (!i || i->LogicalDeviceState == DAC960_V2_LogicalDevice_Offline)
+                       goto out;
        }
 
-       check_disk_change(inode->i_bdev);
+       check_disk_change(bdev);
 
        if (!get_capacity(p->disks[drive_nr]))
-               return -ENXIO;
-       return 0;
+               goto out;
+       ret = 0;
+out:
+       mutex_unlock(&DAC960_mutex);
+       return ret;
 }
 
-static int DAC960_ioctl(struct inode *inode, struct file *file,
-                       unsigned int cmd, unsigned long arg)
+static int DAC960_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-       struct gendisk *disk = inode->i_bdev->bd_disk;
+       struct gendisk *disk = bdev->bd_disk;
        DAC960_Controller_T *p = disk->queue->queuedata;
-       int drive_nr = (int)disk->private_data;
-       struct hd_geometry g, *loc = (struct hd_geometry *)arg;
-
-       if (file->f_flags & O_NONBLOCK)
-               return DAC960_UserIOCTL(inode, file, cmd, arg);
-
-       if (cmd != HDIO_GETGEO || !loc)
-               return -EINVAL;
+       int drive_nr = (long)disk->private_data;
 
        if (p->FirmwareType == DAC960_V1_Controller) {
-               g.heads = p->V1.GeometryTranslationHeads;
-               g.sectors = p->V1.GeometryTranslationSectors;
-               g.cylinders = p->V1.LogicalDriveInformation[drive_nr].
-                       LogicalDriveSize / (g.heads * g.sectors);
+               geo->heads = p->V1.GeometryTranslationHeads;
+               geo->sectors = p->V1.GeometryTranslationSectors;
+               geo->cylinders = p->V1.LogicalDriveInformation[drive_nr].
+                       LogicalDriveSize / (geo->heads * geo->sectors);
        } else {
                DAC960_V2_LogicalDeviceInfo_T *i =
                        p->V2.LogicalDeviceInformation[drive_nr];
                switch (i->DriveGeometry) {
                case DAC960_V2_Geometry_128_32:
-                       g.heads = 128;
-                       g.sectors = 32;
+                       geo->heads = 128;
+                       geo->sectors = 32;
                        break;
                case DAC960_V2_Geometry_255_63:
-                       g.heads = 255;
-                       g.sectors = 63;
+                       geo->heads = 255;
+                       geo->sectors = 63;
                        break;
                default:
                        DAC960_Error("Illegal Logical Device Geometry %d\n",
@@ -131,38 +133,38 @@ static int DAC960_ioctl(struct inode *inode, struct file *file,
                        return -EINVAL;
                }
 
-               g.cylinders = i->ConfigurableDeviceSize / (g.heads * g.sectors);
+               geo->cylinders = i->ConfigurableDeviceSize /
+                       (geo->heads * geo->sectors);
        }
        
-       g.start = get_start_sect(inode->i_bdev);
-
-       return copy_to_user(loc, &g, sizeof g) ? -EFAULT : 0; 
+       return 0;
 }
 
-static int DAC960_media_changed(struct gendisk *disk)
+static unsigned int DAC960_check_events(struct gendisk *disk,
+                                       unsigned int clearing)
 {
        DAC960_Controller_T *p = disk->queue->queuedata;
-       int drive_nr = (int)disk->private_data;
+       int drive_nr = (long)disk->private_data;
 
        if (!p->LogicalDriveInitiallyAccessible[drive_nr])
-               return 1;
+               return DISK_EVENT_MEDIA_CHANGE;
        return 0;
 }
 
 static int DAC960_revalidate_disk(struct gendisk *disk)
 {
        DAC960_Controller_T *p = disk->queue->queuedata;
-       int unit = (int)disk->private_data;
+       int unit = (long)disk->private_data;
 
        set_capacity(disk, disk_size(p, unit));
        return 0;
 }
 
-static struct block_device_operations DAC960_BlockDeviceOperations = {
+static const struct block_device_operations DAC960_BlockDeviceOperations = {
        .owner                  = THIS_MODULE,
        .open                   = DAC960_open,
-       .ioctl                  = DAC960_ioctl,
-       .media_changed          = DAC960_media_changed,
+       .getgeo                 = DAC960_getgeo,
+       .check_events           = DAC960_check_events,
        .revalidate_disk        = DAC960_revalidate_disk,
 };
 
@@ -186,7 +188,7 @@ static void DAC960_AnnounceDriver(DAC960_Controller_T *Controller)
   DAC960_Failure prints a standardized error message, and then returns false.
 */
 
-static boolean DAC960_Failure(DAC960_Controller_T *Controller,
+static bool DAC960_Failure(DAC960_Controller_T *Controller,
                              unsigned char *ErrorMessage)
 {
   DAC960_Error("While configuring DAC960 PCI RAID Controller at\n",
@@ -215,7 +217,7 @@ static boolean DAC960_Failure(DAC960_Controller_T *Controller,
   that are passed in.
  */
 
-static boolean init_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf,
+static bool init_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf,
                                                                 size_t len)
 {
        void *cpu_addr;
@@ -238,8 +240,7 @@ static void *slice_dma_loaf(struct dma_loaf *loaf, size_t len,
        void *cpu_end = loaf->cpu_free + len;
        void *cpu_addr = loaf->cpu_free;
 
-       if (cpu_end > loaf->cpu_base + loaf->length)
-               BUG();
+       BUG_ON(cpu_end > loaf->cpu_base + loaf->length);
        *dma_handle = loaf->dma_free;
        loaf->cpu_free = cpu_end;
        loaf->dma_free += len;
@@ -260,7 +261,7 @@ static void free_dma_loaf(struct pci_dev *dev, struct dma_loaf *loaf_handle)
   failure.
 */
 
-static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
+static bool DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
 {
   int CommandAllocationLength, CommandAllocationGroupSize;
   int CommandsRemaining = 0, CommandIdentifier, CommandGroupByteCount;
@@ -293,12 +294,17 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
                Controller->PCIDevice,
        DAC960_V2_ScatterGatherLimit * sizeof(DAC960_V2_ScatterGatherSegment_T),
        sizeof(DAC960_V2_ScatterGatherSegment_T), 0);
+      if (ScatterGatherPool == NULL)
+           return DAC960_Failure(Controller,
+                       "AUXILIARY STRUCTURE CREATION (SG)");
       RequestSensePool = pci_pool_create("DAC960_V2_RequestSense",
                Controller->PCIDevice, sizeof(DAC960_SCSI_RequestSense_T),
                sizeof(int), 0);
-      if (ScatterGatherPool == NULL || RequestSensePool == NULL)
+      if (RequestSensePool == NULL) {
+           pci_pool_destroy(ScatterGatherPool);
            return DAC960_Failure(Controller,
                        "AUXILIARY STRUCTURE CREATION (SG)");
+      }
       Controller->ScatterGatherPool = ScatterGatherPool;
       Controller->V2.RequestSensePool = RequestSensePool;
     }
@@ -317,11 +323,10 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
                CommandsRemaining = CommandAllocationGroupSize;
          CommandGroupByteCount =
                CommandsRemaining * CommandAllocationLength;
-         AllocationPointer = kmalloc(CommandGroupByteCount, GFP_ATOMIC);
+         AllocationPointer = kzalloc(CommandGroupByteCount, GFP_ATOMIC);
          if (AllocationPointer == NULL)
                return DAC960_Failure(Controller,
                                        "AUXILIARY STRUCTURE CREATION");
-         memset(AllocationPointer, 0, CommandGroupByteCount);
         }
       Command = (DAC960_Command_T *) AllocationPointer;
       AllocationPointer += CommandAllocationLength;
@@ -330,13 +335,13 @@ 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,
+      ScatterGatherCPU = pci_pool_alloc(ScatterGatherPool, GFP_ATOMIC,
                                                        &ScatterGatherDMA);
       if (ScatterGatherCPU == NULL)
          return DAC960_Failure(Controller, "AUXILIARY STRUCTURE CREATION");
 
       if (RequestSensePool != NULL) {
-         RequestSenseCPU = pci_pool_alloc(RequestSensePool, SLAB_ATOMIC,
+         RequestSenseCPU = pci_pool_alloc(RequestSensePool, GFP_ATOMIC,
                                                &RequestSenseDMA);
          if (RequestSenseCPU == NULL) {
                 pci_pool_free(ScatterGatherPool, ScatterGatherCPU,
@@ -350,6 +355,7 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
        Command->V1.ScatterGatherList =
                (DAC960_V1_ScatterGatherSegment_T *)ScatterGatherCPU;
        Command->V1.ScatterGatherListDMA = ScatterGatherDMA;
+       sg_init_table(Command->cmd_sglist, DAC960_V1_ScatterGatherLimit);
       } else {
         Command->cmd_sglist = Command->V2.ScatterList;
        Command->V2.ScatterGatherList =
@@ -358,6 +364,7 @@ static boolean DAC960_CreateAuxiliaryStructures(DAC960_Controller_T *Controller)
        Command->V2.RequestSense =
                                (DAC960_SCSI_RequestSense_T *)RequestSenseCPU;
        Command->V2.RequestSenseDMA = RequestSenseDMA;
+       sg_init_table(Command->cmd_sglist, DAC960_V2_ScatterGatherLimit);
       }
     }
   return true;
@@ -416,14 +423,12 @@ static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller)
             * 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;
+          kfree(CommandGroup);
+          CommandGroup = Command;
       }
       Controller->Commands[i] = NULL;
     }
-  if (CommandGroup != NULL)
-      kfree(CommandGroup);
+  kfree(CommandGroup);
 
   if (Controller->CombinedStatusBuffer != NULL)
     {
@@ -434,30 +439,23 @@ static void DAC960_DestroyAuxiliaryStructures(DAC960_Controller_T *Controller)
 
   if (ScatterGatherPool != NULL)
        pci_pool_destroy(ScatterGatherPool);
-  if (Controller->FirmwareType == DAC960_V1_Controller) return;
+  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)
-      {
+  for (i = 0; i < DAC960_MaxLogicalDrives; i++) {
        kfree(Controller->V2.LogicalDeviceInformation[i]);
        Controller->V2.LogicalDeviceInformation[i] = NULL;
-      }
+  }
 
   for (i = 0; i < DAC960_V2_MaxPhysicalDevices; i++)
     {
-      if (Controller->V2.PhysicalDeviceInformation[i] != NULL)
-       {
-         kfree(Controller->V2.PhysicalDeviceInformation[i]);
-         Controller->V2.PhysicalDeviceInformation[i] = NULL;
-       }
-      if (Controller->V2.InquiryUnitSerialNumber[i] != NULL)
-       {
-         kfree(Controller->V2.InquiryUnitSerialNumber[i]);
-         Controller->V2.InquiryUnitSerialNumber[i] = NULL;
-       }
+      kfree(Controller->V2.PhysicalDeviceInformation[i]);
+      Controller->V2.PhysicalDeviceInformation[i] = NULL;
+      kfree(Controller->V2.InquiryUnitSerialNumber[i]);
+      Controller->V2.InquiryUnitSerialNumber[i] = NULL;
     }
 }
 
@@ -532,6 +530,34 @@ static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
   spin_lock_irq(&Controller->queue_lock);
 }
 
+/*
+  DAC960_GEM_QueueCommand queues Command for DAC960 GEM Series Controllers.
+*/
+
+static void DAC960_GEM_QueueCommand(DAC960_Command_T *Command)
+{
+  DAC960_Controller_T *Controller = Command->Controller;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
+  DAC960_V2_CommandMailbox_T *NextCommandMailbox =
+      Controller->V2.NextCommandMailbox;
+
+  CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier;
+  DAC960_GEM_WriteCommandMailbox(NextCommandMailbox, CommandMailbox);
+
+  if (Controller->V2.PreviousCommandMailbox1->Words[0] == 0 ||
+      Controller->V2.PreviousCommandMailbox2->Words[0] == 0)
+      DAC960_GEM_MemoryMailboxNewCommand(ControllerBaseAddress);
+
+  Controller->V2.PreviousCommandMailbox2 =
+      Controller->V2.PreviousCommandMailbox1;
+  Controller->V2.PreviousCommandMailbox1 = NextCommandMailbox;
+
+  if (++NextCommandMailbox > Controller->V2.LastCommandMailbox)
+      NextCommandMailbox = Controller->V2.FirstCommandMailbox;
+
+  Controller->V2.NextCommandMailbox = NextCommandMailbox;
+}
 
 /*
   DAC960_BA_QueueCommand queues Command for DAC960 BA Series Controllers.
@@ -540,7 +566,7 @@ static void DAC960_WaitForCommand(DAC960_Controller_T *Controller)
 static void DAC960_BA_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_CommandMailbox_T *NextCommandMailbox =
     Controller->V2.NextCommandMailbox;
@@ -565,7 +591,7 @@ static void DAC960_BA_QueueCommand(DAC960_Command_T *Command)
 static void DAC960_LP_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
   DAC960_V2_CommandMailbox_T *NextCommandMailbox =
     Controller->V2.NextCommandMailbox;
@@ -591,7 +617,7 @@ static void DAC960_LP_QueueCommand(DAC960_Command_T *Command)
 static void DAC960_LA_QueueCommandDualMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -617,7 +643,7 @@ static void DAC960_LA_QueueCommandDualMode(DAC960_Command_T *Command)
 static void DAC960_LA_QueueCommandSingleMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -643,7 +669,7 @@ static void DAC960_LA_QueueCommandSingleMode(DAC960_Command_T *Command)
 static void DAC960_PG_QueueCommandDualMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -669,7 +695,7 @@ static void DAC960_PG_QueueCommandDualMode(DAC960_Command_T *Command)
 static void DAC960_PG_QueueCommandSingleMode(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   DAC960_V1_CommandMailbox_T *NextCommandMailbox =
     Controller->V1.NextCommandMailbox;
@@ -694,7 +720,7 @@ static void DAC960_PG_QueueCommandSingleMode(DAC960_Command_T *Command)
 static void DAC960_PD_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier;
   while (DAC960_PD_MailboxFullP(ControllerBaseAddress))
@@ -711,7 +737,7 @@ static void DAC960_PD_QueueCommand(DAC960_Command_T *Command)
 static void DAC960_P_QueueCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_CommandMailbox_T *CommandMailbox = &Command->V1.CommandMailbox;
   CommandMailbox->Common.CommandIdentifier = Command->CommandIdentifier;
   switch (CommandMailbox->Common.CommandOpcode)
@@ -757,7 +783,7 @@ static void DAC960_P_QueueCommand(DAC960_Command_T *Command)
 static void DAC960_ExecuteCommand(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
-  DECLARE_COMPLETION(Completion);
+  DECLARE_COMPLETION_ONSTACK(Completion);
   unsigned long flags;
   Command->Completion = &Completion;
 
@@ -777,7 +803,7 @@ static void DAC960_ExecuteCommand(DAC960_Command_T *Command)
   on failure.
 */
 
-static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller,
+static bool DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller,
                                      DAC960_V1_CommandOpcode_T CommandOpcode,
                                      dma_addr_t DataDMA)
 {
@@ -801,7 +827,7 @@ static boolean DAC960_V1_ExecuteType3(DAC960_Controller_T *Controller,
   on failure.
 */
 
-static boolean DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller,
+static bool DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller,
                                       DAC960_V1_CommandOpcode_T CommandOpcode,
                                       unsigned char CommandOpcode2,
                                       dma_addr_t DataDMA)
@@ -827,7 +853,7 @@ static boolean DAC960_V1_ExecuteType3B(DAC960_Controller_T *Controller,
   on failure.
 */
 
-static boolean DAC960_V1_ExecuteType3D(DAC960_Controller_T *Controller,
+static bool DAC960_V1_ExecuteType3D(DAC960_Controller_T *Controller,
                                       DAC960_V1_CommandOpcode_T CommandOpcode,
                                       unsigned char Channel,
                                       unsigned char TargetID,
@@ -857,7 +883,7 @@ static boolean DAC960_V1_ExecuteType3D(DAC960_Controller_T *Controller,
   Return data in The controller's HealthStatusBuffer, which is dma-able memory
 */
 
-static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller)
+static bool DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
@@ -895,7 +921,7 @@ static boolean DAC960_V2_GeneralInfo(DAC960_Controller_T *Controller)
   memory buffer.
 */
 
-static boolean DAC960_V2_NewControllerInfo(DAC960_Controller_T *Controller)
+static bool DAC960_V2_NewControllerInfo(DAC960_Controller_T *Controller)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
@@ -933,7 +959,7 @@ static boolean DAC960_V2_NewControllerInfo(DAC960_Controller_T *Controller)
   Data is returned in the controller's V2.NewLogicalDeviceInformation
 */
 
-static boolean DAC960_V2_NewLogicalDeviceInfo(DAC960_Controller_T *Controller,
+static bool DAC960_V2_NewLogicalDeviceInfo(DAC960_Controller_T *Controller,
                                           unsigned short LogicalDeviceNumber)
 {
   DAC960_Command_T *Command = DAC960_AllocateCommand(Controller);
@@ -984,7 +1010,7 @@ static boolean DAC960_V2_NewLogicalDeviceInfo(DAC960_Controller_T *Controller,
 
 */
 
-static boolean DAC960_V2_NewPhysicalDeviceInfo(DAC960_Controller_T *Controller,
+static bool DAC960_V2_NewPhysicalDeviceInfo(DAC960_Controller_T *Controller,
                                            unsigned char Channel,
                                            unsigned char TargetID,
                                            unsigned char LogicalUnit)
@@ -1069,7 +1095,7 @@ static void DAC960_V2_ConstructNewUnitSerialNumber(
   memory buffer.
 */
 
-static boolean DAC960_V2_NewInquiryUnitSerialNumber(DAC960_Controller_T *Controller,
+static bool DAC960_V2_NewInquiryUnitSerialNumber(DAC960_Controller_T *Controller,
                        int Channel, int TargetID, int LogicalUnit)
 {
       DAC960_Command_T *Command;
@@ -1097,7 +1123,7 @@ static boolean DAC960_V2_NewInquiryUnitSerialNumber(DAC960_Controller_T *Control
   success and false on failure.
 */
 
-static boolean DAC960_V2_DeviceOperation(DAC960_Controller_T *Controller,
+static bool DAC960_V2_DeviceOperation(DAC960_Controller_T *Controller,
                                         DAC960_V2_IOCTL_Opcode_T IOCTL_Opcode,
                                         DAC960_V2_OperationDevice_T
                                           OperationDevice)
@@ -1129,10 +1155,10 @@ static boolean DAC960_V2_DeviceOperation(DAC960_Controller_T *Controller,
   other dma mapped memory.
 */
 
-static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
+static bool DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
                                                      *Controller)
 {
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_HardwareType_T hw_type = Controller->HardwareType;
   struct pci_dev *PCI_Device = Controller->PCIDevice;
   struct dma_loaf *DmaPages = &Controller->DmaPages;
@@ -1151,10 +1177,11 @@ static boolean DAC960_V1_EnableMemoryMailboxInterface(DAC960_Controller_T
   int TimeoutCounter;
   int i;
 
-  
-  if (pci_set_dma_mask(Controller->PCIDevice, DAC690_V1_PciDmaMask))
+  memset(&CommandMailbox, 0, sizeof(DAC960_V1_CommandMailbox_T));
+
+  if (pci_set_dma_mask(Controller->PCIDevice, DMA_BIT_MASK(32)))
        return DAC960_Failure(Controller, "DMA mask out of range");
-  Controller->BounceBufferLimit = DAC690_V1_PciDmaMask;
+  Controller->BounceBufferLimit = DMA_BIT_MASK(32);
 
   if ((hw_type == DAC960_PD_Controller) || (hw_type == DAC960_P_Controller)) {
     CommandMailboxesSize =  0;
@@ -1335,10 +1362,10 @@ skip_mailboxes:
   the structures that are contained in that region.
 */
 
-static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
+static bool DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
                                                      *Controller)
 {
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   struct pci_dev *PCI_Device = Controller->PCIDevice;
   struct dma_loaf *DmaPages = &Controller->DmaPages;
   size_t DmaPagesSize;
@@ -1355,13 +1382,15 @@ static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
   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");
-  Controller->BounceBufferLimit = DAC690_V2_PciDmaMask;
+       if (!pci_set_dma_mask(Controller->PCIDevice, DMA_BIT_MASK(64)))
+               Controller->BounceBufferLimit = DMA_BIT_MASK(64);
+       else if (!pci_set_dma_mask(Controller->PCIDevice, DMA_BIT_MASK(32)))
+               Controller->BounceBufferLimit = DMA_BIT_MASK(32);
+       else
+               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,
+  CommandMailbox = pci_alloc_consistent(PCI_Device,
                sizeof(DAC960_V2_CommandMailbox_T), &CommandMailboxDMA);
   if (CommandMailbox == NULL)
          return false;
@@ -1464,6 +1493,17 @@ static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
                                        Controller->V2.FirstStatusMailboxDMA;
   switch (Controller->HardwareType)
     {
+    case DAC960_GEM_Controller:
+      while (DAC960_GEM_HardwareMailboxFullP(ControllerBaseAddress))
+       udelay(1);
+      DAC960_GEM_WriteHardwareMailbox(ControllerBaseAddress, CommandMailboxDMA);
+      DAC960_GEM_HardwareMailboxNewCommand(ControllerBaseAddress);
+      while (!DAC960_GEM_HardwareMailboxStatusAvailableP(ControllerBaseAddress))
+       udelay(1);
+      CommandStatus = DAC960_GEM_ReadCommandStatus(ControllerBaseAddress);
+      DAC960_GEM_AcknowledgeHardwareMailboxInterrupt(ControllerBaseAddress);
+      DAC960_GEM_AcknowledgeHardwareMailboxStatus(ControllerBaseAddress);
+      break;
     case DAC960_BA_Controller:
       while (DAC960_BA_HardwareMailboxFullP(ControllerBaseAddress))
        udelay(1);
@@ -1502,7 +1542,7 @@ static boolean DAC960_V2_EnableMemoryMailboxInterface(DAC960_Controller_T
   from DAC960 V1 Firmware Controllers and initializes the Controller structure.
 */
 
-static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
+static bool DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
                                                     *Controller)
 {
   DAC960_V1_Enquiry2_T *Enquiry2;
@@ -1609,6 +1649,26 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
     DAC960PU/PD/PL         3.51 and above
     DAC960PU/PD/PL/P       2.73 and above
   */
+#if defined(CONFIG_ALPHA)
+  /*
+    DEC Alpha machines were often equipped with DAC960 cards that were
+    OEMed from Mylex, and had their own custom firmware. Version 2.70,
+    the last custom FW revision to be released by DEC for these older
+    controllers, appears to work quite well with this driver.
+
+    Cards tested successfully were several versions each of the PD and
+    PU, called by DEC the KZPSC and KZPAC, respectively, and having
+    the Manufacturer Numbers (from Mylex), usually on a sticker on the
+    back of the board, of:
+
+    KZPSC:  D040347 (1-channel) or D040348 (2-channel) or D040349 (3-channel)
+    KZPAC:  D040395 (1-channel) or D040396 (2-channel) or D040397 (3-channel)
+  */
+# define FIRMWARE_27X  "2.70"
+#else
+# define FIRMWARE_27X  "2.73"
+#endif
+
   if (Enquiry2->FirmwareID.MajorVersion == 0)
     {
       Enquiry2->FirmwareID.MajorVersion =
@@ -1628,7 +1688,7 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
        (Controller->FirmwareVersion[0] == '3' &&
         strcmp(Controller->FirmwareVersion, "3.51") >= 0) ||
        (Controller->FirmwareVersion[0] == '2' &&
-        strcmp(Controller->FirmwareVersion, "2.73") >= 0)))
+        strcmp(Controller->FirmwareVersion, FIRMWARE_27X) >= 0)))
     {
       DAC960_Failure(Controller, "FIRMWARE VERSION VERIFICATION");
       DAC960_Error("Firmware Version = '%s'\n", Controller,
@@ -1723,7 +1783,7 @@ static boolean DAC960_V1_ReadControllerConfiguration(DAC960_Controller_T
   from DAC960 V2 Firmware Controllers and initializes the Controller structure.
 */
 
-static boolean DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T
+static bool DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T
                                                     *Controller)
 {
   DAC960_V2_ControllerInfo_T *ControllerInfo =
@@ -1731,7 +1791,7 @@ static boolean DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T
   unsigned short LogicalDeviceNumber = 0;
   int ModelNameLength;
 
-  /* Get data into dma-able area, then copy into permanant location */
+  /* Get data into dma-able area, then copy into permanent location */
   if (!DAC960_V2_NewControllerInfo(Controller))
     return DAC960_Failure(Controller, "GET CONTROLLER INFO");
   memcpy(ControllerInfo, Controller->V2.NewControllerInformation,
@@ -1835,8 +1895,8 @@ static boolean DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T
       if (NewLogicalDeviceInfo->LogicalDeviceState !=
          DAC960_V2_LogicalDevice_Offline)
        Controller->LogicalDriveInitiallyAccessible[LogicalDeviceNumber] = true;
-      LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *)
-       kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC);
+      LogicalDeviceInfo = kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T),
+                                  GFP_ATOMIC);
       if (LogicalDeviceInfo == NULL)
        return DAC960_Failure(Controller, "LOGICAL DEVICE ALLOCATION");
       Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] =
@@ -1854,7 +1914,7 @@ static boolean DAC960_V2_ReadControllerConfiguration(DAC960_Controller_T
   for Controller.
 */
 
-static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T
+static bool DAC960_ReportControllerConfiguration(DAC960_Controller_T
                                                    *Controller)
 {
   DAC960_Info("Configuring Mylex %s PCI RAID Controller\n",
@@ -1903,7 +1963,7 @@ static boolean DAC960_ReportControllerConfiguration(DAC960_Controller_T
   Controller.
 */
 
-static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T
+static bool DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T
                                                 *Controller)
 {
   struct dma_loaf local_dma;
@@ -2051,7 +2111,7 @@ static boolean DAC960_V1_ReadDeviceConfiguration(DAC960_Controller_T
   device connected to Controller.
 */
 
-static boolean DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T
+static bool DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T
                                                 *Controller)
 {
   unsigned char Channel = 0, TargetID = 0, LogicalUnit = 0;
@@ -2069,8 +2129,8 @@ static boolean DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T
       if (!DAC960_V2_NewPhysicalDeviceInfo(Controller, Channel, TargetID, LogicalUnit))
          break;
 
-      PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *)
-               kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC);
+      PhysicalDeviceInfo = kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T),
+                                   GFP_ATOMIC);
       if (PhysicalDeviceInfo == NULL)
                return DAC960_Failure(Controller, "PHYSICAL DEVICE ALLOCATION");
       Controller->V2.PhysicalDeviceInformation[PhysicalDeviceIndex] =
@@ -2078,8 +2138,8 @@ static boolean DAC960_V2_ReadDeviceConfiguration(DAC960_Controller_T
       memcpy(PhysicalDeviceInfo, NewPhysicalDeviceInfo,
                sizeof(DAC960_V2_PhysicalDeviceInfo_T));
 
-      InquiryUnitSerialNumber = (DAC960_SCSI_Inquiry_UnitSerialNumber_T *)
-       kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC);
+      InquiryUnitSerialNumber = kmalloc(
+             sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T), GFP_ATOMIC);
       if (InquiryUnitSerialNumber == NULL) {
        kfree(PhysicalDeviceInfo);
        return DAC960_Failure(Controller, "SERIAL NUMBER ALLOCATION");
@@ -2175,7 +2235,7 @@ static void DAC960_SanitizeInquiryData(DAC960_SCSI_Inquiry_T
   Information for DAC960 V1 Firmware Controllers.
 */
 
-static boolean DAC960_V1_ReportDeviceConfiguration(DAC960_Controller_T
+static bool DAC960_V1_ReportDeviceConfiguration(DAC960_Controller_T
                                                   *Controller)
 {
   int LogicalDriveNumber, Channel, TargetID;
@@ -2272,7 +2332,7 @@ static boolean DAC960_V1_ReportDeviceConfiguration(DAC960_Controller_T
   Information for DAC960 V2 Firmware Controllers.
 */
 
-static boolean DAC960_V2_ReportDeviceConfiguration(DAC960_Controller_T
+static bool DAC960_V2_ReportDeviceConfiguration(DAC960_Controller_T
                                                   *Controller)
 {
   int PhysicalDeviceIndex, LogicalDriveNumber;
@@ -2309,8 +2369,7 @@ static boolean DAC960_V2_ReportDeviceConfiguration(DAC960_Controller_T
                    (PhysicalDeviceInfo->NegotiatedDataWidthBits == 16
                     ? "Wide " :""),
                    (PhysicalDeviceInfo->NegotiatedSynchronousMegaTransfers
-                    * (PhysicalDeviceInfo->NegotiatedDataWidthBits == 16
-                       ? 2 : 1)));
+                    * PhysicalDeviceInfo->NegotiatedDataWidthBits/8));
       if (InquiryUnitSerialNumber->PeripheralDeviceType != 0x1F)
        DAC960_Info("         Serial Number: %s\n", Controller, SerialNumber);
       if (PhysicalDeviceInfo->PhysicalDeviceState ==
@@ -2458,10 +2517,9 @@ static boolean DAC960_V2_ReportDeviceConfiguration(DAC960_Controller_T
   associated with Controller.
 */
 
-static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
+static bool DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
 {
   int MajorNumber = DAC960_MAJOR + Controller->ControllerNumber;
-  struct request_queue *RequestQueue;
   int n;
 
   /*
@@ -2470,21 +2528,22 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
   if (register_blkdev(MajorNumber, "dac960") < 0)
       return false;
 
-  /*
-    Initialize the I/O Request Queue.
-  */
-  RequestQueue = &Controller->RequestQueue;
-  blk_init_queue(RequestQueue, DAC960_RequestFunction, &Controller->queue_lock);
-  blk_queue_bounce_limit(RequestQueue, Controller->BounceBufferLimit);
-  RequestQueue->queuedata = Controller;
-  blk_queue_max_hw_segments(RequestQueue,
-                           Controller->DriverScatterGatherLimit);
-  blk_queue_max_phys_segments(RequestQueue,
-                           Controller->DriverScatterGatherLimit);
-  blk_queue_max_sectors(RequestQueue, Controller->MaxBlocksPerCommand);
-
   for (n = 0; n < DAC960_MaxLogicalDrives; n++) {
        struct gendisk *disk = Controller->disks[n];
+       struct request_queue *RequestQueue;
+
+       /* for now, let all request queues share controller's lock */
+       RequestQueue = blk_init_queue(DAC960_RequestFunction,&Controller->queue_lock);
+       if (!RequestQueue) {
+               printk("DAC960: failure to allocate request queue\n");
+               continue;
+       }
+       Controller->RequestQueue[n] = RequestQueue;
+       blk_queue_bounce_limit(RequestQueue, Controller->BounceBufferLimit);
+       RequestQueue->queuedata = Controller;
+       blk_queue_max_segments(RequestQueue, Controller->DriverScatterGatherLimit);
+       blk_queue_max_hw_sectors(RequestQueue, Controller->MaxBlocksPerCommand);
+       disk->queue = RequestQueue;
        sprintf(disk->disk_name, "rd/c%dd%d", Controller->ControllerNumber, n);
        disk->major = MajorNumber;
        disk->first_minor = n << DAC960_MaxPartitionsBits;
@@ -2507,17 +2566,17 @@ 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]);
+  /* does order matter when deleting gendisk and cleanup in request queue? */
+  for (disk = 0; disk < DAC960_MaxLogicalDrives; disk++) {
+       del_gendisk(Controller->disks[disk]);
+       blk_cleanup_queue(Controller->RequestQueue[disk]);
+       Controller->RequestQueue[disk] = NULL;
+  }
 
   /*
     Unregister the Block Device Major Number for this DAC960 Controller.
   */
   unregister_blkdev(MajorNumber, "dac960");
-  /*
-    Remove the I/O Request Queue.
-  */
-  blk_cleanup_queue(&Controller->RequestQueue);
 }
 
 /*
@@ -2538,7 +2597,7 @@ static void DAC960_ComputeGenericDiskInfo(DAC960_Controller_T *Controller)
   It returns true for fatal errors and false otherwise.
 */
 
-static boolean DAC960_ReportErrorStatus(DAC960_Controller_T *Controller,
+static bool DAC960_ReportErrorStatus(DAC960_Controller_T *Controller,
                                        unsigned char ErrorStatus,
                                        unsigned char Parameter0,
                                        unsigned char Parameter1)
@@ -2606,6 +2665,9 @@ static void DAC960_DetectCleanup(DAC960_Controller_T *Controller)
   if (Controller->MemoryMappedAddress) {
        switch(Controller->HardwareType)
        {
+               case DAC960_GEM_Controller:
+                       DAC960_GEM_DisableInterrupts(Controller->BaseAddress);
+                       break;
                case DAC960_BA_Controller:
                        DAC960_BA_DisableInterrupts(Controller->BaseAddress);
                        break;
@@ -2651,24 +2713,21 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
 {
   struct DAC960_privdata *privdata =
                (struct DAC960_privdata *)entry->driver_data;
-  irqreturn_t (*InterruptHandler)(int, void *, struct pt_regs *) =
-               privdata->InterruptHandler;
+  irq_handler_t InterruptHandler = privdata->InterruptHandler;
   unsigned int MemoryWindowSize = privdata->MemoryWindowSize;
   DAC960_Controller_T *Controller = NULL;
   unsigned char DeviceFunction = PCI_Device->devfn;
   unsigned char ErrorStatus, Parameter0, Parameter1;
-  unsigned int IRQ_Channel = PCI_Device->irq;
-  void *BaseAddress;
+  unsigned int IRQ_Channel;
+  void __iomem *BaseAddress;
   int i;
 
-  Controller = (DAC960_Controller_T *)
-       kmalloc(sizeof(DAC960_Controller_T), GFP_ATOMIC);
+  Controller = kzalloc(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;
@@ -2679,13 +2738,14 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
   Controller->PCIDevice = PCI_Device;
   strcpy(Controller->FullModelName, "DAC960");
 
-  if (pci_enable_device(PCI_Device))  {
-        kfree(Controller);
+  if (pci_enable_device(PCI_Device))
        goto Failure;
-  }
 
   switch (Controller->HardwareType)
   {
+       case DAC960_GEM_Controller:
+         Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
+         break;
        case DAC960_BA_Controller:
          Controller->PCI_Address = pci_resource_start(PCI_Device, 0);
          break;
@@ -2708,17 +2768,16 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
          break;
   }
 
-  pci_set_drvdata(PCI_Device, (void *)((int)Controller->ControllerNumber));
+  pci_set_drvdata(PCI_Device, (void *)((long)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;
+       Controller->disks[i]->private_data = (void *)((long)i);
   }
   init_waitqueue_head(&Controller->CommandWaitQueue);
   init_waitqueue_head(&Controller->HealthStatusWaitQueue);
-  Controller->queue_lock = SPIN_LOCK_UNLOCKED; 
+  spin_lock_init(&Controller->queue_lock);
   DAC960_AnnounceDriver(Controller);
   /*
     Map the Controller Register Window.
@@ -2738,6 +2797,36 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
   BaseAddress = Controller->BaseAddress;
   switch (Controller->HardwareType)
   {
+       case DAC960_GEM_Controller:
+         DAC960_GEM_DisableInterrupts(BaseAddress);
+         DAC960_GEM_AcknowledgeHardwareMailboxStatus(BaseAddress);
+         udelay(1000);
+         while (DAC960_GEM_InitializationInProgressP(BaseAddress))
+           {
+             if (DAC960_GEM_ReadErrorStatus(BaseAddress, &ErrorStatus,
+                                           &Parameter0, &Parameter1) &&
+                 DAC960_ReportErrorStatus(Controller, ErrorStatus,
+                                          Parameter0, Parameter1))
+               goto Failure;
+             udelay(10);
+           }
+         if (!DAC960_V2_EnableMemoryMailboxInterface(Controller))
+           {
+             DAC960_Error("Unable to Enable Memory Mailbox Interface "
+                          "for Controller at\n", Controller);
+             goto Failure;
+           }
+         DAC960_GEM_EnableInterrupts(BaseAddress);
+         Controller->QueueCommand = DAC960_GEM_QueueCommand;
+         Controller->ReadControllerConfiguration =
+           DAC960_V2_ReadControllerConfiguration;
+         Controller->ReadDeviceConfiguration =
+           DAC960_V2_ReadDeviceConfiguration;
+         Controller->ReportDeviceConfiguration =
+           DAC960_V2_ReportDeviceConfiguration;
+         Controller->QueueReadWriteCommand =
+           DAC960_V2_QueueReadWriteCommand;
+         break;
        case DAC960_BA_Controller:
          DAC960_BA_DisableInterrupts(BaseAddress);
          DAC960_BA_AcknowledgeHardwareMailboxStatus(BaseAddress);
@@ -2938,7 +3027,8 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
   /*
      Acquire shared access to the IRQ Channel.
   */
-  if (request_irq(IRQ_Channel, InterruptHandler, SA_SHIRQ,
+  IRQ_Channel = PCI_Device->irq;
+  if (request_irq(IRQ_Channel, InterruptHandler, IRQF_SHARED,
                      Controller->FullModelName, Controller) < 0)
   {
        DAC960_Error("Unable to acquire IRQ Channel %d for Controller at\n",
@@ -2973,7 +3063,7 @@ Failure:
   DAC960_InitializeController initializes Controller.
 */
 
-static boolean 
+static bool 
 DAC960_InitializeController(DAC960_Controller_T *Controller)
 {
   if (DAC960_ReadControllerConfiguration(Controller) &&
@@ -3098,7 +3188,7 @@ DAC960_Probe(struct pci_dev *dev, const struct pci_device_id *entry)
 
 static void DAC960_Remove(struct pci_dev *PCI_Device)
 {
-  int Controller_Number = (int)pci_get_drvdata(PCI_Device);
+  int Controller_Number = (long)pci_get_drvdata(PCI_Device);
   DAC960_Controller_T *Controller = DAC960_Controllers[Controller_Number];
   if (Controller != NULL)
       DAC960_FinalizeController(Controller);
@@ -3234,58 +3324,83 @@ static void DAC960_V2_QueueReadWriteCommand(DAC960_Command_T *Command)
 }
 
 
+static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_queue *req_q)
+{
+       struct request *Request;
+       DAC960_Command_T *Command;
+
+   while(1) {
+       Request = blk_peek_request(req_q);
+       if (!Request)
+               return 1;
+
+       Command = DAC960_AllocateCommand(Controller);
+       if (Command == NULL)
+               return 0;
+
+       if (rq_data_dir(Request) == READ) {
+               Command->DmaDirection = PCI_DMA_FROMDEVICE;
+               Command->CommandType = DAC960_ReadCommand;
+       } else {
+               Command->DmaDirection = PCI_DMA_TODEVICE;
+               Command->CommandType = DAC960_WriteCommand;
+       }
+       Command->Completion = Request->end_io_data;
+       Command->LogicalDriveNumber = (long)Request->rq_disk->private_data;
+       Command->BlockNumber = blk_rq_pos(Request);
+       Command->BlockCount = blk_rq_sectors(Request);
+       Command->Request = Request;
+       blk_start_request(Request);
+       Command->SegmentCount = blk_rq_map_sg(req_q,
+                 Command->Request, Command->cmd_sglist);
+       /* pci_map_sg MAY change the value of SegCount */
+       Command->SegmentCount = pci_map_sg(Controller->PCIDevice, Command->cmd_sglist,
+                Command->SegmentCount, Command->DmaDirection);
+
+       DAC960_QueueReadWriteCommand(Command);
+  }
+}
+
 /*
   DAC960_ProcessRequest attempts to remove one I/O Request from Controller's
   I/O Request Queue and queues it to the Controller.  WaitForCommand is true if
   this function should wait for a Command to become available if necessary.
   This function returns true if an I/O Request was queued and false otherwise.
 */
-
-static boolean DAC960_ProcessRequest(DAC960_Controller_T *Controller,
-                                    boolean WaitForCommand)
+static void DAC960_ProcessRequest(DAC960_Controller_T *controller)
 {
-  struct request_queue *RequestQueue = &Controller->RequestQueue;
-  struct request *Request;
-  DAC960_Command_T *Command;
+       int i;
 
-  if (!Controller->ControllerInitialized)
-     return false;
+       if (!controller->ControllerInitialized)
+               return;
 
-  while (true) {
-      Request = elv_next_request(RequestQueue);
-      if (!Request)
-             return false;
+       /* Do this better later! */
+       for (i = controller->req_q_index; i < DAC960_MaxLogicalDrives; i++) {
+               struct request_queue *req_q = controller->RequestQueue[i];
 
-      Command = DAC960_AllocateCommand(Controller);
-      if (Command != NULL)
-          break;
+               if (req_q == NULL)
+                       continue;
 
-      if (!WaitForCommand)
-          return false;
+               if (!DAC960_process_queue(controller, req_q)) {
+                       controller->req_q_index = i;
+                       return;
+               }
+       }
 
-      DAC960_WaitForCommand(Controller);
-  }
-  if (rq_data_dir(Request) == READ) {
-    Command->DmaDirection = PCI_DMA_FROMDEVICE;
-    Command->CommandType = DAC960_ReadCommand;
-  } else {
-    Command->DmaDirection = PCI_DMA_TODEVICE;
-    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->Request = Request;
-  blkdev_dequeue_request(Request);
-  Command->SegmentCount = blk_rq_map_sg(&Controller->RequestQueue,
-                 Command->Request, Command->cmd_sglist);
-  /* pci_map_sg MAY change the value of SegCount */
-  Command->SegmentCount = pci_map_sg(Command->PciDevice, Command->cmd_sglist,
-                Command->SegmentCount, Command->DmaDirection);
+       if (controller->req_q_index == 0)
+               return;
 
-  DAC960_QueueReadWriteCommand(Command);
-  return true;
+       for (i = 0; i < controller->req_q_index; i++) {
+               struct request_queue *req_q = controller->RequestQueue[i];
+
+               if (req_q == NULL)
+                       continue;
+
+               if (!DAC960_process_queue(controller, req_q)) {
+                       controller->req_q_index = i;
+                       return;
+               }
+       }
 }
 
 
@@ -3302,6 +3417,7 @@ static void DAC960_queue_partial_rw(DAC960_Command_T *Command)
 {
   DAC960_Controller_T *Controller = Command->Controller;
   struct request *Request = Command->Request;
+  struct request_queue *req_q = Controller->RequestQueue[Command->LogicalDriveNumber];
 
   if (Command->DmaDirection == PCI_DMA_FROMDEVICE)
     Command->CommandType = DAC960_ReadRetryCommand;
@@ -3314,11 +3430,9 @@ static void DAC960_queue_partial_rw(DAC960_Command_T *Command)
    * code should almost never be called, just go with a
    * simple coding.
    */
-  (void)blk_rq_map_sg(&Controller->RequestQueue, Command->Request,
-                                        Command->cmd_sglist);
+  (void)blk_rq_map_sg(req_q, Command->Request, Command->cmd_sglist);
 
-  (void)pci_map_sg(Command->PciDevice, Command->cmd_sglist, 1,
-                                       Command->DmaDirection);
+  (void)pci_map_sg(Controller->PCIDevice, Command->cmd_sglist, 1, Command->DmaDirection);
   /*
    * Resubmitting the request sector at a time is really tedious.
    * But, this should almost never happen.  So, we're willing to pay
@@ -3326,7 +3440,7 @@ static void DAC960_queue_partial_rw(DAC960_Command_T *Command)
    * successfully as possible.
    */
   Command->SegmentCount = 1;
-  Command->BlockNumber = Request->sector;
+  Command->BlockNumber = blk_rq_pos(Request);
   Command->BlockCount = 1;
   DAC960_QueueReadWriteCommand(Command);
   return;
@@ -3338,9 +3452,7 @@ static void DAC960_queue_partial_rw(DAC960_Command_T *Command)
 
 static void DAC960_RequestFunction(struct request_queue *RequestQueue)
 {
-       int i = 0;
-       while (DAC960_ProcessRequest(RequestQueue->queuedata, (i++ == 0)))
-               ;
+       DAC960_ProcessRequest(RequestQueue->queuedata);
 }
 
 /*
@@ -3348,23 +3460,16 @@ static void DAC960_RequestFunction(struct request_queue *RequestQueue)
   individual Buffer.
 */
 
-static inline boolean DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
-                                                boolean SuccessfulIO)
+static inline bool DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
+                                                bool SuccessfulIO)
 {
        struct request *Request = Command->Request;
-       int UpToDate;
+       int Error = SuccessfulIO ? 0 : -EIO;
 
-       UpToDate = 0;
-       if (SuccessfulIO)
-               UpToDate = 1;
-
-       pci_unmap_sg(Command->PciDevice, Command->cmd_sglist,
+       pci_unmap_sg(Command->Controller->PCIDevice, Command->cmd_sglist,
                Command->SegmentCount, Command->DmaDirection);
 
-        if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) {
-
-               end_that_request_last(Request);
-
+        if (!__blk_end_request(Request, Error, Command->BlockCount << 9)) {
                if (Command->Completion) {
                        complete(Command->Completion);
                        Command->Completion = NULL;
@@ -3475,7 +3580,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
   else if (CommandType == DAC960_ReadRetryCommand ||
           CommandType == DAC960_WriteRetryCommand)
     {
-      boolean normal_completion;
+      bool normal_completion;
 #ifdef FORCE_RETRY_FAILURE_DEBUG
       static int retry_count = 1;
 #endif
@@ -3556,8 +3661,8 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
              (NewEnquiry->EventLogSequenceNumber !=
               OldEnquiry->EventLogSequenceNumber) ||
              Controller->MonitoringTimerCount == 0 ||
-             (jiffies - Controller->SecondaryMonitoringTime
-              >= DAC960_SecondaryMonitoringInterval))
+             time_after_eq(jiffies, Controller->SecondaryMonitoringTime
+              + DAC960_SecondaryMonitoringInterval))
            {
              Controller->V1.NeedLogicalDriveInformation = true;
              Controller->V1.NewEventLogSequenceNumber =
@@ -3659,7 +3764,7 @@ static void DAC960_V1_ProcessCompletedCommand(DAC960_Command_T *Command)
              if (SenseKey == DAC960_SenseKey_VendorSpecific &&
                  AdditionalSenseCode == 0x80 &&
                  AdditionalSenseCodeQualifier <
-                 sizeof(DAC960_EventMessages) / sizeof(char *))
+                 ARRAY_SIZE(DAC960_EventMessages))
                DAC960_Critical("Physical Device %d:%d %s\n", Controller,
                                EventLogEntry->Channel,
                                EventLogEntry->TargetID,
@@ -4523,7 +4628,8 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
   DAC960_Controller_T *Controller = Command->Controller;
   DAC960_CommandType_T CommandType = Command->CommandType;
   DAC960_V2_CommandMailbox_T *CommandMailbox = &Command->V2.CommandMailbox;
-  DAC960_V2_IOCTL_Opcode_T CommandOpcode = CommandMailbox->Common.IOCTL_Opcode;
+  DAC960_V2_IOCTL_Opcode_T IOCTLOpcode = CommandMailbox->Common.IOCTL_Opcode;
+  DAC960_V2_CommandOpcode_T CommandOpcode = CommandMailbox->SCSI_10.CommandOpcode;
   DAC960_V2_CommandStatus_T CommandStatus = Command->V2.CommandStatus;
 
   if (CommandType == DAC960_ReadCommand ||
@@ -4562,7 +4668,7 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
   else if (CommandType == DAC960_ReadRetryCommand ||
           CommandType == DAC960_WriteRetryCommand)
     {
-      boolean normal_completion;
+      bool normal_completion;
 
 #ifdef FORCE_RETRY_FAILURE_DEBUG
       static int retry_count = 1;
@@ -4595,7 +4701,7 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
     {
       if (Controller->ShutdownMonitoringTimer)
              return;
-      if (CommandOpcode == DAC960_V2_GetControllerInfo)
+      if (IOCTLOpcode == DAC960_V2_GetControllerInfo)
        {
          DAC960_V2_ControllerInfo_T *NewControllerInfo =
            Controller->V2.NewControllerInformation;
@@ -4615,14 +4721,14 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
          memcpy(ControllerInfo, NewControllerInfo,
                 sizeof(DAC960_V2_ControllerInfo_T));
        }
-      else if (CommandOpcode == DAC960_V2_GetEvent)
+      else if (IOCTLOpcode == DAC960_V2_GetEvent)
        {
          if (CommandStatus == DAC960_V2_NormalCompletion) {
            DAC960_V2_ReportEvent(Controller, Controller->V2.Event);
          }
          Controller->V2.NextEventSequenceNumber++;
        }
-      else if (CommandOpcode == DAC960_V2_GetPhysicalDeviceInfoValid &&
+      else if (IOCTLOpcode == DAC960_V2_GetPhysicalDeviceInfoValid &&
               CommandStatus == DAC960_V2_NormalCompletion)
        {
          DAC960_V2_PhysicalDeviceInfo_T *NewPhysicalDeviceInfo =
@@ -4681,15 +4787,16 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
              (NewPhysicalDeviceInfo->LogicalUnit !=
               PhysicalDeviceInfo->LogicalUnit))
            {
-             PhysicalDeviceInfo = (DAC960_V2_PhysicalDeviceInfo_T *)
+             PhysicalDeviceInfo =
                kmalloc(sizeof(DAC960_V2_PhysicalDeviceInfo_T), GFP_ATOMIC);
              InquiryUnitSerialNumber =
-               (DAC960_SCSI_Inquiry_UnitSerialNumber_T *)
                  kmalloc(sizeof(DAC960_SCSI_Inquiry_UnitSerialNumber_T),
                          GFP_ATOMIC);
-             if (InquiryUnitSerialNumber == NULL &&
-                 PhysicalDeviceInfo != NULL)
+             if (InquiryUnitSerialNumber == NULL ||
+                 PhysicalDeviceInfo == NULL)
                {
+                 kfree(InquiryUnitSerialNumber);
+                 InquiryUnitSerialNumber = NULL;
                  kfree(PhysicalDeviceInfo);
                  PhysicalDeviceInfo = NULL;
                }
@@ -4810,7 +4917,7 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
          NewPhysicalDeviceInfo->LogicalUnit++;
          Controller->V2.PhysicalDeviceIndex++;
        }
-      else if (CommandOpcode == DAC960_V2_GetPhysicalDeviceInfoValid)
+      else if (IOCTLOpcode == DAC960_V2_GetPhysicalDeviceInfoValid)
        {
          unsigned int DeviceIndex;
          for (DeviceIndex = Controller->V2.PhysicalDeviceIndex;
@@ -4833,7 +4940,7 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
            }
          Controller->V2.NeedPhysicalDeviceInformation = false;
        }
-      else if (CommandOpcode == DAC960_V2_GetLogicalDeviceInfoValid &&
+      else if (IOCTLOpcode == DAC960_V2_GetLogicalDeviceInfoValid &&
               CommandStatus == DAC960_V2_NormalCompletion)
        {
          DAC960_V2_LogicalDeviceInfo_T *NewLogicalDeviceInfo =
@@ -4851,8 +4958,8 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
              PhysicalDevice.LogicalUnit = NewLogicalDeviceInfo->LogicalUnit;
              Controller->V2.LogicalDriveToVirtualDevice[LogicalDeviceNumber] =
                PhysicalDevice;
-             LogicalDeviceInfo = (DAC960_V2_LogicalDeviceInfo_T *)
-               kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T), GFP_ATOMIC);
+             LogicalDeviceInfo = kmalloc(sizeof(DAC960_V2_LogicalDeviceInfo_T),
+                                         GFP_ATOMIC);
              Controller->V2.LogicalDeviceInformation[LogicalDeviceNumber] =
                LogicalDeviceInfo;
              DAC960_Critical("Logical Drive %d (/dev/rd/c%dd%d) "
@@ -4960,7 +5067,7 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
                         [LogicalDeviceNumber] = true;
          NewLogicalDeviceInfo->LogicalDeviceNumber++;
        }
-      else if (CommandOpcode == DAC960_V2_GetLogicalDeviceInfoValid)
+      else if (IOCTLOpcode == DAC960_V2_GetLogicalDeviceInfoValid)
        {
          int LogicalDriveNumber;
          for (LogicalDriveNumber = 0;
@@ -5148,6 +5255,46 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
   wake_up(&Controller->CommandWaitQueue);
 }
 
+/*
+  DAC960_GEM_InterruptHandler handles hardware interrupts from DAC960 GEM Series
+  Controllers.
+*/
+
+static irqreturn_t DAC960_GEM_InterruptHandler(int IRQ_Channel,
+                                      void *DeviceIdentifier)
+{
+  DAC960_Controller_T *Controller = DeviceIdentifier;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_V2_StatusMailbox_T *NextStatusMailbox;
+  unsigned long flags;
+
+  spin_lock_irqsave(&Controller->queue_lock, flags);
+  DAC960_GEM_AcknowledgeInterrupt(ControllerBaseAddress);
+  NextStatusMailbox = Controller->V2.NextStatusMailbox;
+  while (NextStatusMailbox->Fields.CommandIdentifier > 0)
+    {
+       DAC960_V2_CommandIdentifier_T CommandIdentifier =
+           NextStatusMailbox->Fields.CommandIdentifier;
+       DAC960_Command_T *Command = Controller->Commands[CommandIdentifier-1];
+       Command->V2.CommandStatus = NextStatusMailbox->Fields.CommandStatus;
+       Command->V2.RequestSenseLength =
+           NextStatusMailbox->Fields.RequestSenseLength;
+       Command->V2.DataTransferResidue =
+           NextStatusMailbox->Fields.DataTransferResidue;
+       NextStatusMailbox->Words[0] = 0;
+       if (++NextStatusMailbox > Controller->V2.LastStatusMailbox)
+           NextStatusMailbox = Controller->V2.FirstStatusMailbox;
+       DAC960_V2_ProcessCompletedCommand(Command);
+    }
+  Controller->V2.NextStatusMailbox = NextStatusMailbox;
+  /*
+    Attempt to remove additional I/O Requests from the Controller's
+    I/O Request Queue and queue them to the Controller.
+  */
+  DAC960_ProcessRequest(Controller);
+  spin_unlock_irqrestore(&Controller->queue_lock, flags);
+  return IRQ_HANDLED;
+}
 
 /*
   DAC960_BA_InterruptHandler handles hardware interrupts from DAC960 BA Series
@@ -5155,11 +5302,10 @@ static void DAC960_V2_ProcessCompletedCommand(DAC960_Command_T *Command)
 */
 
 static irqreturn_t DAC960_BA_InterruptHandler(int IRQ_Channel,
-                                      void *DeviceIdentifier,
-                                      struct pt_regs *InterruptRegisters)
+                                      void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5186,8 +5332,7 @@ static irqreturn_t DAC960_BA_InterruptHandler(int IRQ_Channel,
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-         ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
@@ -5199,11 +5344,10 @@ static irqreturn_t DAC960_BA_InterruptHandler(int IRQ_Channel,
 */
 
 static irqreturn_t DAC960_LP_InterruptHandler(int IRQ_Channel,
-                                      void *DeviceIdentifier,
-                                      struct pt_regs *InterruptRegisters)
+                                      void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V2_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5230,8 +5374,7 @@ static irqreturn_t DAC960_LP_InterruptHandler(int IRQ_Channel,
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-         ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
@@ -5243,11 +5386,10 @@ static irqreturn_t DAC960_LP_InterruptHandler(int IRQ_Channel,
 */
 
 static irqreturn_t DAC960_LA_InterruptHandler(int IRQ_Channel,
-                                      void *DeviceIdentifier,
-                                      struct pt_regs *InterruptRegisters)
+                                      void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5270,8 +5412,7 @@ static irqreturn_t DAC960_LA_InterruptHandler(int IRQ_Channel,
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-         ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
@@ -5283,11 +5424,10 @@ static irqreturn_t DAC960_LA_InterruptHandler(int IRQ_Channel,
 */
 
 static irqreturn_t DAC960_PG_InterruptHandler(int IRQ_Channel,
-                                      void *DeviceIdentifier,
-                                      struct pt_regs *InterruptRegisters)
+                                      void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   DAC960_V1_StatusMailbox_T *NextStatusMailbox;
   unsigned long flags;
 
@@ -5310,8 +5450,7 @@ static irqreturn_t DAC960_PG_InterruptHandler(int IRQ_Channel,
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-         ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
@@ -5323,11 +5462,10 @@ static irqreturn_t DAC960_PG_InterruptHandler(int IRQ_Channel,
 */
 
 static irqreturn_t DAC960_PD_InterruptHandler(int IRQ_Channel,
-                                      void *DeviceIdentifier,
-                                      struct pt_regs *InterruptRegisters)
+                                      void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   unsigned long flags;
 
   spin_lock_irqsave(&Controller->queue_lock, flags);
@@ -5346,8 +5484,7 @@ static irqreturn_t DAC960_PD_InterruptHandler(int IRQ_Channel,
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-         ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
@@ -5363,11 +5500,10 @@ static irqreturn_t DAC960_PD_InterruptHandler(int IRQ_Channel,
 */
 
 static irqreturn_t DAC960_P_InterruptHandler(int IRQ_Channel,
-                                     void *DeviceIdentifier,
-                                     struct pt_regs *InterruptRegisters)
+                                     void *DeviceIdentifier)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) DeviceIdentifier;
-  void *ControllerBaseAddress = Controller->BaseAddress;
+  DAC960_Controller_T *Controller = DeviceIdentifier;
+  void __iomem *ControllerBaseAddress = Controller->BaseAddress;
   unsigned long flags;
 
   spin_lock_irqsave(&Controller->queue_lock, flags);
@@ -5421,8 +5557,7 @@ static irqreturn_t DAC960_P_InterruptHandler(int IRQ_Channel,
     Attempt to remove additional I/O Requests from the Controller's
     I/O Request Queue and queue them to the Controller.
   */
-  while (DAC960_ProcessRequest(Controller, false))
-         ;
+  DAC960_ProcessRequest(Controller);
   spin_unlock_irqrestore(&Controller->queue_lock, flags);
   return IRQ_HANDLED;
 }
@@ -5506,9 +5641,9 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
        &Controller->V2.ControllerInformation;
       unsigned int StatusChangeCounter =
        Controller->V2.HealthStatusBuffer->StatusChangeCounter;
-      boolean ForceMonitoringCommand = false;
-      if (jiffies - Controller->SecondaryMonitoringTime
-         > DAC960_SecondaryMonitoringInterval)
+      bool ForceMonitoringCommand = false;
+      if (time_after(jiffies, Controller->SecondaryMonitoringTime
+         + DAC960_SecondaryMonitoringInterval))
        {
          int LogicalDriveNumber;
          for (LogicalDriveNumber = 0;
@@ -5536,8 +5671,8 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
           ControllerInfo->ConsistencyChecksActive +
           ControllerInfo->RebuildsActive +
           ControllerInfo->OnlineExpansionsActive == 0 ||
-          jiffies - Controller->PrimaryMonitoringTime
-          < DAC960_MonitoringTimerInterval) &&
+          time_before(jiffies, Controller->PrimaryMonitoringTime
+          + DAC960_MonitoringTimerInterval)) &&
          !ForceMonitoringCommand)
        {
          Controller->MonitoringTimer.expires =
@@ -5565,522 +5700,121 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
 }
 
 /*
-  DAC960_UserIOCTL is the User IOCTL Function for the DAC960 Driver.
+  DAC960_CheckStatusBuffer verifies that there is room to hold ByteCount
+  additional bytes in the Combined Status Buffer and grows the buffer if
+  necessary.  It returns true if there is enough room and false otherwise.
 */
 
-static int DAC960_UserIOCTL(struct inode *inode, struct file *file,
-                           unsigned int Request, unsigned long Argument)
+static bool DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller,
+                                       unsigned int ByteCount)
 {
-  int ErrorCode = 0;
-  if (!capable(CAP_SYS_ADMIN)) return -EACCES;
-  switch (Request)
+  unsigned char *NewStatusBuffer;
+  if (Controller->InitialStatusLength + 1 +
+      Controller->CurrentStatusLength + ByteCount + 1 <=
+      Controller->CombinedStatusBufferLength)
+    return true;
+  if (Controller->CombinedStatusBufferLength == 0)
     {
-    case DAC960_IOCTL_GET_CONTROLLER_COUNT:
-      return DAC960_ControllerCount;
-    case DAC960_IOCTL_GET_CONTROLLER_INFO:
-      {
-       DAC960_ControllerInfo_T *UserSpaceControllerInfo =
-         (DAC960_ControllerInfo_T *) Argument;
-       DAC960_ControllerInfo_T ControllerInfo;
-       DAC960_Controller_T *Controller;
-       int ControllerNumber;
-       if (UserSpaceControllerInfo == NULL) return -EINVAL;
-       ErrorCode = get_user(ControllerNumber,
-                            &UserSpaceControllerInfo->ControllerNumber);
-       if (ErrorCode != 0) return ErrorCode;
-       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 (copy_to_user(UserSpaceControllerInfo, &ControllerInfo,
-                            sizeof(DAC960_ControllerInfo_T)) ? -EFAULT : 0);
-      }
-    case DAC960_IOCTL_V1_EXECUTE_COMMAND:
-      {
-       DAC960_V1_UserCommand_T *UserSpaceUserCommand =
-         (DAC960_V1_UserCommand_T *) Argument;
-       DAC960_V1_UserCommand_T UserCommand;
-       DAC960_Controller_T *Controller;
-       DAC960_Command_T *Command = NULL;
-       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;
-       unsigned long flags;
-       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 Failure1a;
-       }
-       ControllerNumber = UserCommand.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 = UserCommand.CommandMailbox.Common.CommandOpcode;
-       DataTransferLength = UserCommand.DataTransferLength;
-       if (CommandOpcode & 0x80) return -EINVAL;
-       if (CommandOpcode == DAC960_V1_DCDB)
-         {
-           if (copy_from_user(&DCDB, UserCommand.DCDB,
-                              sizeof(DAC960_V1_DCDB_T))) {
-               ErrorCode = -EFAULT;
-               goto Failure1a;
-           }
-           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;
-           DCDB_IOBUF = pci_alloc_consistent(Controller->PCIDevice,
-                       sizeof(DAC960_V1_DCDB_T), &DCDB_IOBUFDMA);
-           if (DCDB_IOBUF == NULL)
-                       return -ENOMEM;
-         }
-       if (DataTransferLength > 0)
-         {
-           DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
-                               DataTransferLength, &DataTransferBufferDMA);
-           if (DataTransferBuffer == NULL) {
-               ErrorCode = -ENOMEM;
-               goto Failure1;
-           }
-           memset(DataTransferBuffer, 0, DataTransferLength);
-         }
-       else if (DataTransferLength < 0)
-         {
-           DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
-                               -DataTransferLength, &DataTransferBufferDMA);
-           if (DataTransferBuffer == NULL) {
-               ErrorCode = -ENOMEM;
-               goto Failure1;
-           }
-           if (copy_from_user(DataTransferBuffer,
-                              UserCommand.DataTransferBuffer,
-                              -DataTransferLength)) {
-               ErrorCode = -EFAULT;
-               goto Failure1;
-           }
-         }
-       if (CommandOpcode == DAC960_V1_DCDB)
-         {
-           spin_lock_irqsave(&Controller->queue_lock, flags);
-           while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
-             DAC960_WaitForCommand(Controller);
-           while (Controller->V1.DirectCommandActive[DCDB.Channel]
-                                                    [DCDB.TargetID])
-             {
-               spin_unlock_irq(&Controller->queue_lock);
-               __wait_event(Controller->CommandWaitQueue,
-                            !Controller->V1.DirectCommandActive
-                                            [DCDB.Channel][DCDB.TargetID]);
-               spin_lock_irq(&Controller->queue_lock);
-             }
-           Controller->V1.DirectCommandActive[DCDB.Channel]
-                                             [DCDB.TargetID] = true;
-           spin_unlock_irqrestore(&Controller->queue_lock, flags);
-           DAC960_V1_ClearCommand(Command);
-           Command->CommandType = DAC960_ImmediateCommand;
-           memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox,
-                  sizeof(DAC960_V1_CommandMailbox_T));
-           Command->V1.CommandMailbox.Type3.BusAddress = DCDB_IOBUFDMA;
-           DCDB.BusAddress = DataTransferBufferDMA;
-           memcpy(DCDB_IOBUF, &DCDB, sizeof(DAC960_V1_DCDB_T));
-         }
-       else
-         {
-           spin_lock_irqsave(&Controller->queue_lock, flags);
-           while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
-             DAC960_WaitForCommand(Controller);
-           spin_unlock_irqrestore(&Controller->queue_lock, flags);
-           DAC960_V1_ClearCommand(Command);
-           Command->CommandType = DAC960_ImmediateCommand;
-           memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox,
-                  sizeof(DAC960_V1_CommandMailbox_T));
-           if (DataTransferBuffer != NULL)
-             Command->V1.CommandMailbox.Type3.BusAddress =
-               DataTransferBufferDMA;
-         }
-       DAC960_ExecuteCommand(Command);
-       CommandStatus = Command->V1.CommandStatus;
-       spin_lock_irqsave(&Controller->queue_lock, flags);
-       DAC960_DeallocateCommand(Command);
-       spin_unlock_irqrestore(&Controller->queue_lock, flags);
-       if (DataTransferLength > 0)
-         {
-           if (copy_to_user(UserCommand.DataTransferBuffer,
-                            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_IOBUF,
-                            sizeof(DAC960_V1_DCDB_T))) {
-               ErrorCode = -EFAULT;
-               goto Failure1;
+      unsigned int NewStatusBufferLength = DAC960_InitialStatusBufferSize;
+      while (NewStatusBufferLength < ByteCount)
+       NewStatusBufferLength *= 2;
+      Controller->CombinedStatusBuffer = kmalloc(NewStatusBufferLength,
+                                                 GFP_ATOMIC);
+      if (Controller->CombinedStatusBuffer == NULL) return false;
+      Controller->CombinedStatusBufferLength = NewStatusBufferLength;
+      return true;
+    }
+  NewStatusBuffer = kmalloc(2 * Controller->CombinedStatusBufferLength,
+                            GFP_ATOMIC);
+  if (NewStatusBuffer == NULL)
+    {
+      DAC960_Warning("Unable to expand Combined Status Buffer - Truncating\n",
+                    Controller);
+      return false;
+    }
+  memcpy(NewStatusBuffer, Controller->CombinedStatusBuffer,
+        Controller->CombinedStatusBufferLength);
+  kfree(Controller->CombinedStatusBuffer);
+  Controller->CombinedStatusBuffer = NewStatusBuffer;
+  Controller->CombinedStatusBufferLength *= 2;
+  Controller->CurrentStatusBuffer =
+    &NewStatusBuffer[Controller->InitialStatusLength + 1];
+  return true;
+}
+
+
+/*
+  DAC960_Message prints Driver Messages.
+*/
+
+static void DAC960_Message(DAC960_MessageLevel_T MessageLevel,
+                          unsigned char *Format,
+                          DAC960_Controller_T *Controller,
+                          ...)
+{
+  static unsigned char Buffer[DAC960_LineBufferSize];
+  static bool BeginningOfLine = true;
+  va_list Arguments;
+  int Length = 0;
+  va_start(Arguments, Controller);
+  Length = vsprintf(Buffer, Format, Arguments);
+  va_end(Arguments);
+  if (Controller == NULL)
+    printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+          DAC960_ControllerCount, Buffer);
+  else if (MessageLevel == DAC960_AnnounceLevel ||
+          MessageLevel == DAC960_InfoLevel)
+    {
+      if (!Controller->ControllerInitialized)
+       {
+         if (DAC960_CheckStatusBuffer(Controller, Length))
+           {
+             strcpy(&Controller->CombinedStatusBuffer
+                                 [Controller->InitialStatusLength],
+                    Buffer);
+             Controller->InitialStatusLength += Length;
+             Controller->CurrentStatusBuffer =
+               &Controller->CombinedStatusBuffer
+                            [Controller->InitialStatusLength + 1];
+           }
+         if (MessageLevel == DAC960_AnnounceLevel)
+           {
+             static int AnnouncementLines = 0;
+             if (++AnnouncementLines <= 2)
+               printk("%sDAC960: %s", DAC960_MessageLevelMap[MessageLevel],
+                      Buffer);
+           }
+         else
+           {
+             if (BeginningOfLine)
+               {
+                 if (Buffer[0] != '\n' || Length > 1)
+                   printk("%sDAC960#%d: %s",
+                          DAC960_MessageLevelMap[MessageLevel],
+                          Controller->ControllerNumber, Buffer);
+               }
+             else printk("%s", Buffer);
            }
-         }
-       ErrorCode = CommandStatus;
-      Failure1:
-       if (DataTransferBuffer != NULL)
-         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:
-      {
-       DAC960_V2_UserCommand_T *UserSpaceUserCommand =
-         (DAC960_V2_UserCommand_T *) Argument;
-       DAC960_V2_UserCommand_T UserCommand;
-       DAC960_Controller_T *Controller;
-       DAC960_Command_T *Command = NULL;
-       DAC960_V2_CommandMailbox_T *CommandMailbox;
-       DAC960_V2_CommandStatus_T CommandStatus;
-       unsigned long flags;
-       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 Failure2a;
        }
-       ControllerNumber = UserCommand.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 = UserCommand.DataTransferLength;
-       if (DataTransferLength > 0)
-         {
-           DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
-                               DataTransferLength, &DataTransferBufferDMA);
-           if (DataTransferBuffer == NULL) return -ENOMEM;
-           memset(DataTransferBuffer, 0, DataTransferLength);
-         }
-       else if (DataTransferLength < 0)
-         {
-           DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
-                               -DataTransferLength, &DataTransferBufferDMA);
-           if (DataTransferBuffer == NULL) return -ENOMEM;
-           if (copy_from_user(DataTransferBuffer,
-                              UserCommand.DataTransferBuffer,
-                              -DataTransferLength)) {
-               ErrorCode = -EFAULT;
-               goto Failure2;
-           }
-         }
-       RequestSenseLength = UserCommand.RequestSenseLength;
-       if (RequestSenseLength > 0)
-         {
-           RequestSenseBuffer = pci_alloc_consistent(Controller->PCIDevice,
-                       RequestSenseLength, &RequestSenseBufferDMA);
-           if (RequestSenseBuffer == NULL)
-             {
-               ErrorCode = -ENOMEM;
-               goto Failure2;
-             }
-           memset(RequestSenseBuffer, 0, RequestSenseLength);
-         }
-       spin_lock_irqsave(&Controller->queue_lock, flags);
-       while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
-         DAC960_WaitForCommand(Controller);
-       spin_unlock_irqrestore(&Controller->queue_lock, flags);
-       DAC960_V2_ClearCommand(Command);
-       Command->CommandType = DAC960_ImmediateCommand;
-       CommandMailbox = &Command->V2.CommandMailbox;
-       memcpy(CommandMailbox, &UserCommand.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 = DataTransferBufferDMA;
-           CommandMailbox->Common.DataTransferMemoryAddress
-                                 .ScatterGatherSegments[0]
-                                 .SegmentByteCount =
-             CommandMailbox->Common.DataTransferSize;
-         }
-       if (RequestSenseLength > 0)
-         {
-           CommandMailbox->Common.CommandControlBits
-                                 .NoAutoRequestSense = false;
-           CommandMailbox->Common.RequestSenseSize = RequestSenseLength;
-           CommandMailbox->Common.RequestSenseBusAddress =
-                                                       RequestSenseBufferDMA;
-         }
-       DAC960_ExecuteCommand(Command);
-       CommandStatus = Command->V2.CommandStatus;
-       RequestSenseLength = Command->V2.RequestSenseLength;
-       DataTransferResidue = Command->V2.DataTransferResidue;
-       spin_lock_irqsave(&Controller->queue_lock, flags);
-       DAC960_DeallocateCommand(Command);
-       spin_unlock_irqrestore(&Controller->queue_lock, flags);
-       if (RequestSenseLength > UserCommand.RequestSenseLength)
-         RequestSenseLength = UserCommand.RequestSenseLength;
-       if (copy_to_user(&UserSpaceUserCommand->DataTransferLength,
-                                &DataTransferResidue,
-                                sizeof(DataTransferResidue))) {
-               ErrorCode = -EFAULT;
-               goto Failure2;
-       }
-       if (copy_to_user(&UserSpaceUserCommand->RequestSenseLength,
-                        &RequestSenseLength, sizeof(RequestSenseLength))) {
-               ErrorCode = -EFAULT;
-               goto Failure2;
-       }
-       if (DataTransferLength > 0)
-         {
-           if (copy_to_user(UserCommand.DataTransferBuffer,
-                            DataTransferBuffer, DataTransferLength)) {
-               ErrorCode = -EFAULT;
-               goto Failure2;
-           }
-         }
-       if (RequestSenseLength > 0)
-         {
-           if (copy_to_user(UserCommand.RequestSenseBuffer,
-                            RequestSenseBuffer, RequestSenseLength)) {
-               ErrorCode = -EFAULT;
-               goto Failure2;
-           }
-         }
-       ErrorCode = CommandStatus;
-      Failure2:
-         pci_free_consistent(Controller->PCIDevice, abs(DataTransferLength),
-               DataTransferBuffer, DataTransferBufferDMA);
-       if (RequestSenseBuffer != NULL)
-         pci_free_consistent(Controller->PCIDevice, RequestSenseLength,
-               RequestSenseBuffer, RequestSenseBufferDMA);
-      Failure2a:
-       return ErrorCode;
-      }
-    case DAC960_IOCTL_V2_GET_HEALTH_STATUS:
-      {
-       DAC960_V2_GetHealthStatus_T *UserSpaceGetHealthStatus =
-         (DAC960_V2_GetHealthStatus_T *) Argument;
-       DAC960_V2_GetHealthStatus_T GetHealthStatus;
-       DAC960_V2_HealthStatusBuffer_T HealthStatusBuffer;
-       DAC960_Controller_T *Controller;
-       int ControllerNumber;
-       if (UserSpaceGetHealthStatus == NULL) return -EINVAL;
-       if (copy_from_user(&GetHealthStatus, UserSpaceGetHealthStatus,
-                          sizeof(DAC960_V2_GetHealthStatus_T)))
-               return -EFAULT;
-       ControllerNumber = GetHealthStatus.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;
-       if (copy_from_user(&HealthStatusBuffer,
-                          GetHealthStatus.HealthStatusBuffer,
-                          sizeof(DAC960_V2_HealthStatusBuffer_T)))
-               return -EFAULT;
-       while (Controller->V2.HealthStatusBuffer->StatusChangeCounter
-              == HealthStatusBuffer.StatusChangeCounter &&
-              Controller->V2.HealthStatusBuffer->NextEventSequenceNumber
-              == HealthStatusBuffer.NextEventSequenceNumber)
-         {
-           interruptible_sleep_on_timeout(&Controller->HealthStatusWaitQueue,
-                                          DAC960_MonitoringTimerInterval);
-           if (signal_pending(current)) return -EINTR;
-         }
-       if (copy_to_user(GetHealthStatus.HealthStatusBuffer,
-                        Controller->V2.HealthStatusBuffer,
-                        sizeof(DAC960_V2_HealthStatusBuffer_T)))
-               return -EFAULT;
-       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
-  necessary.  It returns true if there is enough room and false otherwise.
-*/
-
-static boolean DAC960_CheckStatusBuffer(DAC960_Controller_T *Controller,
-                                       unsigned int ByteCount)
-{
-  unsigned char *NewStatusBuffer;
-  if (Controller->InitialStatusLength + 1 +
-      Controller->CurrentStatusLength + ByteCount + 1 <=
-      Controller->CombinedStatusBufferLength)
-    return true;
-  if (Controller->CombinedStatusBufferLength == 0)
-    {
-      unsigned int NewStatusBufferLength = DAC960_InitialStatusBufferSize;
-      while (NewStatusBufferLength < ByteCount)
-       NewStatusBufferLength *= 2;
-      Controller->CombinedStatusBuffer =
-       (unsigned char *) kmalloc(NewStatusBufferLength, GFP_ATOMIC);
-      if (Controller->CombinedStatusBuffer == NULL) return false;
-      Controller->CombinedStatusBufferLength = NewStatusBufferLength;
-      return true;
-    }
-  NewStatusBuffer = (unsigned char *)
-    kmalloc(2 * Controller->CombinedStatusBufferLength, GFP_ATOMIC);
-  if (NewStatusBuffer == NULL)
-    {
-      DAC960_Warning("Unable to expand Combined Status Buffer - Truncating\n",
-                    Controller);
-      return false;
-    }
-  memcpy(NewStatusBuffer, Controller->CombinedStatusBuffer,
-        Controller->CombinedStatusBufferLength);
-  kfree(Controller->CombinedStatusBuffer);
-  Controller->CombinedStatusBuffer = NewStatusBuffer;
-  Controller->CombinedStatusBufferLength *= 2;
-  Controller->CurrentStatusBuffer =
-    &NewStatusBuffer[Controller->InitialStatusLength + 1];
-  return true;
-}
-
-
-/*
-  DAC960_Message prints Driver Messages.
-*/
-
-static void DAC960_Message(DAC960_MessageLevel_T MessageLevel,
-                          unsigned char *Format,
-                          DAC960_Controller_T *Controller,
-                          ...)
-{
-  static unsigned char Buffer[DAC960_LineBufferSize];
-  static boolean BeginningOfLine = true;
-  va_list Arguments;
-  int Length = 0;
-  va_start(Arguments, Controller);
-  Length = vsprintf(Buffer, Format, Arguments);
-  va_end(Arguments);
-  if (Controller == NULL)
-    printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
-          DAC960_ControllerCount, Buffer);
-  else if (MessageLevel == DAC960_AnnounceLevel ||
-          MessageLevel == DAC960_InfoLevel)
-    {
-      if (!Controller->ControllerInitialized)
-       {
-         if (DAC960_CheckStatusBuffer(Controller, Length))
-           {
-             strcpy(&Controller->CombinedStatusBuffer
-                                 [Controller->InitialStatusLength],
-                    Buffer);
-             Controller->InitialStatusLength += Length;
-             Controller->CurrentStatusBuffer =
-               &Controller->CombinedStatusBuffer
-                            [Controller->InitialStatusLength + 1];
-           }
-         if (MessageLevel == DAC960_AnnounceLevel)
-           {
-             static int AnnouncementLines = 0;
-             if (++AnnouncementLines <= 2)
-               printk("%sDAC960: %s", DAC960_MessageLevelMap[MessageLevel],
-                      Buffer);
-           }
-         else
-           {
-             if (BeginningOfLine)
-               {
-                 if (Buffer[0] != '\n' || Length > 1)
-                   printk("%sDAC960#%d: %s",
-                          DAC960_MessageLevelMap[MessageLevel],
-                          Controller->ControllerNumber, Buffer);
-               }
-             else printk("%s", Buffer);
-           }
-       }
-      else if (DAC960_CheckStatusBuffer(Controller, Length))
-       {
-         strcpy(&Controller->CurrentStatusBuffer[
-                   Controller->CurrentStatusLength], Buffer);
-         Controller->CurrentStatusLength += Length;
-       }
-    }
-  else if (MessageLevel == DAC960_ProgressLevel)
-    {
-      strcpy(Controller->ProgressBuffer, Buffer);
-      Controller->ProgressBufferLength = Length;
-      if (Controller->EphemeralProgressMessage)
-       {
-         if (jiffies - Controller->LastProgressReportTime
-             >= DAC960_ProgressReportingInterval)
-           {
-             printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
-                    Controller->ControllerNumber, Buffer);
-             Controller->LastProgressReportTime = jiffies;
+      else if (DAC960_CheckStatusBuffer(Controller, Length))
+       {
+         strcpy(&Controller->CurrentStatusBuffer[
+                   Controller->CurrentStatusLength], Buffer);
+         Controller->CurrentStatusLength += Length;
+       }
+    }
+  else if (MessageLevel == DAC960_ProgressLevel)
+    {
+      strcpy(Controller->ProgressBuffer, Buffer);
+      Controller->ProgressBufferLength = Length;
+      if (Controller->EphemeralProgressMessage)
+       {
+         if (time_after_eq(jiffies, Controller->LastProgressReportTime
+             + DAC960_ProgressReportingInterval))
+           {
+             printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
+                    Controller->ControllerNumber, Buffer);
+             Controller->LastProgressReportTime = jiffies;
            }
        }
       else printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
@@ -6112,7 +5846,7 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel,
   Channel and TargetID and returns true on success and false on failure.
 */
 
-static boolean DAC960_ParsePhysicalDevice(DAC960_Controller_T *Controller,
+static bool DAC960_ParsePhysicalDevice(DAC960_Controller_T *Controller,
                                          char *UserCommandString,
                                          unsigned char *Channel,
                                          unsigned char *TargetID)
@@ -6145,7 +5879,7 @@ static boolean DAC960_ParsePhysicalDevice(DAC960_Controller_T *Controller,
   returns true on success and false on failure.
 */
 
-static boolean DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller,
+static bool DAC960_ParseLogicalDrive(DAC960_Controller_T *Controller,
                                        char *UserCommandString,
                                        unsigned char *LogicalDriveNumber)
 {
@@ -6226,7 +5960,7 @@ static void DAC960_V1_SetDeviceState(DAC960_Controller_T *Controller,
   Controllers.
 */
 
-static boolean DAC960_V1_ExecuteUserCommand(DAC960_Controller_T *Controller,
+static bool DAC960_V1_ExecuteUserCommand(DAC960_Controller_T *Controller,
                                            unsigned char *UserCommand)
 {
   DAC960_Command_T *Command;
@@ -6441,7 +6175,7 @@ failure:
   on failure.
 */
 
-static boolean DAC960_V2_TranslatePhysicalDevice(DAC960_Command_T *Command,
+static bool DAC960_V2_TranslatePhysicalDevice(DAC960_Command_T *Command,
                                                 unsigned char Channel,
                                                 unsigned char TargetID,
                                                 unsigned short
@@ -6488,7 +6222,7 @@ static boolean DAC960_V2_TranslatePhysicalDevice(DAC960_Command_T *Command,
   Controllers.
 */
 
-static boolean DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller,
+static bool DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller,
                                            unsigned char *UserCommand)
 {
   DAC960_Command_T *Command;
@@ -6683,219 +6417,686 @@ static boolean DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller,
              DAC960_ExecuteCommand(Command);
              sleep_on_timeout(&Controller->CommandWaitQueue, HZ);
            }
-         DAC960_UserCritical("Discovery Completed\n", Controller);
-       }
-    }
-  else if (strcmp(UserCommand, "suppress-enclosure-messages") == 0)
-    Controller->SuppressEnclosureMessages = true;
-  else DAC960_UserCritical("Illegal User Command: '%s'\n",
-                          Controller, UserCommand);
-
-  spin_lock_irqsave(&Controller->queue_lock, flags);
-  DAC960_DeallocateCommand(Command);
-  spin_unlock_irqrestore(&Controller->queue_lock, flags);
-  return true;
-}
-
-
-/*
-  DAC960_ProcReadStatus implements reading /proc/rd/status.
-*/
-
-static int DAC960_ProcReadStatus(char *Page, char **Start, off_t Offset,
-                                int Count, int *EOF, void *Data)
-{
-  unsigned char *StatusMessage = "OK\n";
-  int ControllerNumber, BytesAvailable;
-  for (ControllerNumber = 0;
-       ControllerNumber < DAC960_ControllerCount;
-       ControllerNumber++)
-    {
-      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
-      if (Controller == NULL) continue;
-      if (Controller->MonitoringAlertMode)
-       {
-         StatusMessage = "ALERT\n";
-         break;
+         DAC960_UserCritical("Discovery Completed\n", Controller);
+       }
+    }
+  else if (strcmp(UserCommand, "suppress-enclosure-messages") == 0)
+    Controller->SuppressEnclosureMessages = true;
+  else DAC960_UserCritical("Illegal User Command: '%s'\n",
+                          Controller, UserCommand);
+
+  spin_lock_irqsave(&Controller->queue_lock, flags);
+  DAC960_DeallocateCommand(Command);
+  spin_unlock_irqrestore(&Controller->queue_lock, flags);
+  return true;
+}
+
+static int dac960_proc_show(struct seq_file *m, void *v)
+{
+  unsigned char *StatusMessage = "OK\n";
+  int ControllerNumber;
+  for (ControllerNumber = 0;
+       ControllerNumber < DAC960_ControllerCount;
+       ControllerNumber++)
+    {
+      DAC960_Controller_T *Controller = DAC960_Controllers[ControllerNumber];
+      if (Controller == NULL) continue;
+      if (Controller->MonitoringAlertMode)
+       {
+         StatusMessage = "ALERT\n";
+         break;
+       }
+    }
+  seq_puts(m, StatusMessage);
+  return 0;
+}
+
+static int dac960_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dac960_proc_show, NULL);
+}
+
+static const struct file_operations dac960_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = dac960_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int dac960_initial_status_proc_show(struct seq_file *m, void *v)
+{
+       DAC960_Controller_T *Controller = (DAC960_Controller_T *)m->private;
+       seq_printf(m, "%.*s", Controller->InitialStatusLength, Controller->CombinedStatusBuffer);
+       return 0;
+}
+
+static int dac960_initial_status_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dac960_initial_status_proc_show, PDE(inode)->data);
+}
+
+static const struct file_operations dac960_initial_status_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = dac960_initial_status_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int dac960_current_status_proc_show(struct seq_file *m, void *v)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) m->private;
+  unsigned char *StatusMessage =
+    "No Rebuild or Consistency Check in Progress\n";
+  int ProgressMessageLength = strlen(StatusMessage);
+  if (jiffies != Controller->LastCurrentStatusTime)
+    {
+      Controller->CurrentStatusLength = 0;
+      DAC960_AnnounceDriver(Controller);
+      DAC960_ReportControllerConfiguration(Controller);
+      DAC960_ReportDeviceConfiguration(Controller);
+      if (Controller->ProgressBufferLength > 0)
+       ProgressMessageLength = Controller->ProgressBufferLength;
+      if (DAC960_CheckStatusBuffer(Controller, 2 + ProgressMessageLength))
+       {
+         unsigned char *CurrentStatusBuffer = Controller->CurrentStatusBuffer;
+         CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
+         CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
+         if (Controller->ProgressBufferLength > 0)
+           strcpy(&CurrentStatusBuffer[Controller->CurrentStatusLength],
+                  Controller->ProgressBuffer);
+         else
+           strcpy(&CurrentStatusBuffer[Controller->CurrentStatusLength],
+                  StatusMessage);
+         Controller->CurrentStatusLength += ProgressMessageLength;
+       }
+      Controller->LastCurrentStatusTime = jiffies;
+    }
+       seq_printf(m, "%.*s", Controller->CurrentStatusLength, Controller->CurrentStatusBuffer);
+       return 0;
+}
+
+static int dac960_current_status_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dac960_current_status_proc_show, PDE(inode)->data);
+}
+
+static const struct file_operations dac960_current_status_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = dac960_current_status_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+};
+
+static int dac960_user_command_proc_show(struct seq_file *m, void *v)
+{
+       DAC960_Controller_T *Controller = (DAC960_Controller_T *)m->private;
+
+       seq_printf(m, "%.*s", Controller->UserStatusLength, Controller->UserStatusBuffer);
+       return 0;
+}
+
+static int dac960_user_command_proc_open(struct inode *inode, struct file *file)
+{
+       return single_open(file, dac960_user_command_proc_show, PDE(inode)->data);
+}
+
+static ssize_t dac960_user_command_proc_write(struct file *file,
+                                      const char __user *Buffer,
+                                      size_t Count, loff_t *pos)
+{
+  DAC960_Controller_T *Controller = (DAC960_Controller_T *) PDE(file->f_path.dentry->d_inode)->data;
+  unsigned char CommandBuffer[80];
+  int Length;
+  if (Count > sizeof(CommandBuffer)-1) return -EINVAL;
+  if (copy_from_user(CommandBuffer, Buffer, Count)) return -EFAULT;
+  CommandBuffer[Count] = '\0';
+  Length = strlen(CommandBuffer);
+  if (Length > 0 && CommandBuffer[Length-1] == '\n')
+    CommandBuffer[--Length] = '\0';
+  if (Controller->FirmwareType == DAC960_V1_Controller)
+    return (DAC960_V1_ExecuteUserCommand(Controller, CommandBuffer)
+           ? Count : -EBUSY);
+  else
+    return (DAC960_V2_ExecuteUserCommand(Controller, CommandBuffer)
+           ? Count : -EBUSY);
+}
+
+static const struct file_operations dac960_user_command_proc_fops = {
+       .owner          = THIS_MODULE,
+       .open           = dac960_user_command_proc_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = single_release,
+       .write          = dac960_user_command_proc_write,
+};
+
+/*
+  DAC960_CreateProcEntries creates the /proc/rd/... entries for the
+  DAC960 Driver.
+*/
+
+static void DAC960_CreateProcEntries(DAC960_Controller_T *Controller)
+{
+       struct proc_dir_entry *ControllerProcEntry;
+
+       if (DAC960_ProcDirectoryEntry == NULL) {
+               DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL);
+               proc_create("status", 0, DAC960_ProcDirectoryEntry,
+                           &dac960_proc_fops);
+       }
+
+       sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
+       ControllerProcEntry = proc_mkdir(Controller->ControllerName,
+                                        DAC960_ProcDirectoryEntry);
+       proc_create_data("initial_status", 0, ControllerProcEntry, &dac960_initial_status_proc_fops, Controller);
+       proc_create_data("current_status", 0, ControllerProcEntry, &dac960_current_status_proc_fops, Controller);
+       proc_create_data("user_command", S_IWUSR | S_IRUSR, ControllerProcEntry, &dac960_user_command_proc_fops, Controller);
+       Controller->ControllerProcEntry = ControllerProcEntry;
+}
+
+
+/*
+  DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the
+  DAC960 Driver.
+*/
+
+static void DAC960_DestroyProcEntries(DAC960_Controller_T *Controller)
+{
+      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);
+      Controller->ControllerProcEntry = NULL;
+}
+
+#ifdef DAC960_GAM_MINOR
+
+/*
+ * DAC960_gam_ioctl is the ioctl function for performing RAID operations.
+*/
+
+static long DAC960_gam_ioctl(struct file *file, unsigned int Request,
+                                               unsigned long Argument)
+{
+  long ErrorCode = 0;
+  if (!capable(CAP_SYS_ADMIN)) return -EACCES;
+
+  mutex_lock(&DAC960_mutex);
+  switch (Request)
+    {
+    case DAC960_IOCTL_GET_CONTROLLER_COUNT:
+      ErrorCode = DAC960_ControllerCount;
+      break;
+    case DAC960_IOCTL_GET_CONTROLLER_INFO:
+      {
+       DAC960_ControllerInfo_T __user *UserSpaceControllerInfo =
+         (DAC960_ControllerInfo_T __user *) Argument;
+       DAC960_ControllerInfo_T ControllerInfo;
+       DAC960_Controller_T *Controller;
+       int ControllerNumber;
+       if (UserSpaceControllerInfo == NULL)
+               ErrorCode = -EINVAL;
+       else ErrorCode = get_user(ControllerNumber,
+                            &UserSpaceControllerInfo->ControllerNumber);
+       if (ErrorCode != 0)
+               break;
+       ErrorCode = -ENXIO;
+       if (ControllerNumber < 0 ||
+           ControllerNumber > DAC960_ControllerCount - 1) {
+         break;
+       }
+       Controller = DAC960_Controllers[ControllerNumber];
+       if (Controller == NULL)
+               break;
+       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);
+       ErrorCode = (copy_to_user(UserSpaceControllerInfo, &ControllerInfo,
+                            sizeof(DAC960_ControllerInfo_T)) ? -EFAULT : 0);
+       break;
+      }
+    case DAC960_IOCTL_V1_EXECUTE_COMMAND:
+      {
+       DAC960_V1_UserCommand_T __user *UserSpaceUserCommand =
+         (DAC960_V1_UserCommand_T __user *) Argument;
+       DAC960_V1_UserCommand_T UserCommand;
+       DAC960_Controller_T *Controller;
+       DAC960_Command_T *Command = NULL;
+       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;
+       unsigned long flags;
+       int ControllerNumber, DataTransferLength;
+       unsigned char *DataTransferBuffer = NULL;
+       dma_addr_t DataTransferBufferDMA;
+       if (UserSpaceUserCommand == NULL) {
+               ErrorCode = -EINVAL;
+               break;
+       }
+       if (copy_from_user(&UserCommand, UserSpaceUserCommand,
+                                  sizeof(DAC960_V1_UserCommand_T))) {
+               ErrorCode = -EFAULT;
+               break;
+       }
+       ControllerNumber = UserCommand.ControllerNumber;
+       ErrorCode = -ENXIO;
+       if (ControllerNumber < 0 ||
+           ControllerNumber > DAC960_ControllerCount - 1)
+               break;
+       Controller = DAC960_Controllers[ControllerNumber];
+       if (Controller == NULL)
+               break;
+       ErrorCode = -EINVAL;
+       if (Controller->FirmwareType != DAC960_V1_Controller)
+               break;
+       CommandOpcode = UserCommand.CommandMailbox.Common.CommandOpcode;
+       DataTransferLength = UserCommand.DataTransferLength;
+       if (CommandOpcode & 0x80)
+               break;
+       if (CommandOpcode == DAC960_V1_DCDB)
+         {
+           if (copy_from_user(&DCDB, UserCommand.DCDB,
+                              sizeof(DAC960_V1_DCDB_T))) {
+               ErrorCode = -EFAULT;
+               break;
+           }
+           if (DCDB.Channel >= DAC960_V1_MaxChannels)
+                       break;
+           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)))
+                       break;
+           if (((DCDB.TransferLengthHigh4 << 16) | DCDB.TransferLength)
+               != abs(DataTransferLength))
+                       break;
+           DCDB_IOBUF = pci_alloc_consistent(Controller->PCIDevice,
+                       sizeof(DAC960_V1_DCDB_T), &DCDB_IOBUFDMA);
+           if (DCDB_IOBUF == NULL) {
+                       ErrorCode = -ENOMEM;
+                       break;
+               }
+         }
+       ErrorCode = -ENOMEM;
+       if (DataTransferLength > 0)
+         {
+           DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+                               DataTransferLength, &DataTransferBufferDMA);
+           if (DataTransferBuffer == NULL)
+               break;
+           memset(DataTransferBuffer, 0, DataTransferLength);
+         }
+       else if (DataTransferLength < 0)
+         {
+           DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+                               -DataTransferLength, &DataTransferBufferDMA);
+           if (DataTransferBuffer == NULL)
+               break;
+           if (copy_from_user(DataTransferBuffer,
+                              UserCommand.DataTransferBuffer,
+                              -DataTransferLength)) {
+               ErrorCode = -EFAULT;
+               break;
+           }
+         }
+       if (CommandOpcode == DAC960_V1_DCDB)
+         {
+           spin_lock_irqsave(&Controller->queue_lock, flags);
+           while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
+             DAC960_WaitForCommand(Controller);
+           while (Controller->V1.DirectCommandActive[DCDB.Channel]
+                                                    [DCDB.TargetID])
+             {
+               spin_unlock_irq(&Controller->queue_lock);
+               __wait_event(Controller->CommandWaitQueue,
+                            !Controller->V1.DirectCommandActive
+                                            [DCDB.Channel][DCDB.TargetID]);
+               spin_lock_irq(&Controller->queue_lock);
+             }
+           Controller->V1.DirectCommandActive[DCDB.Channel]
+                                             [DCDB.TargetID] = true;
+           spin_unlock_irqrestore(&Controller->queue_lock, flags);
+           DAC960_V1_ClearCommand(Command);
+           Command->CommandType = DAC960_ImmediateCommand;
+           memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox,
+                  sizeof(DAC960_V1_CommandMailbox_T));
+           Command->V1.CommandMailbox.Type3.BusAddress = DCDB_IOBUFDMA;
+           DCDB.BusAddress = DataTransferBufferDMA;
+           memcpy(DCDB_IOBUF, &DCDB, sizeof(DAC960_V1_DCDB_T));
+         }
+       else
+         {
+           spin_lock_irqsave(&Controller->queue_lock, flags);
+           while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
+             DAC960_WaitForCommand(Controller);
+           spin_unlock_irqrestore(&Controller->queue_lock, flags);
+           DAC960_V1_ClearCommand(Command);
+           Command->CommandType = DAC960_ImmediateCommand;
+           memcpy(&Command->V1.CommandMailbox, &UserCommand.CommandMailbox,
+                  sizeof(DAC960_V1_CommandMailbox_T));
+           if (DataTransferBuffer != NULL)
+             Command->V1.CommandMailbox.Type3.BusAddress =
+               DataTransferBufferDMA;
+         }
+       DAC960_ExecuteCommand(Command);
+       CommandStatus = Command->V1.CommandStatus;
+       spin_lock_irqsave(&Controller->queue_lock, flags);
+       DAC960_DeallocateCommand(Command);
+       spin_unlock_irqrestore(&Controller->queue_lock, flags);
+       if (DataTransferLength > 0)
+         {
+           if (copy_to_user(UserCommand.DataTransferBuffer,
+                            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_IOBUF,
+                            sizeof(DAC960_V1_DCDB_T))) {
+               ErrorCode = -EFAULT;
+               goto Failure1;
+           }
+         }
+       ErrorCode = CommandStatus;
+      Failure1:
+       if (DataTransferBuffer != NULL)
+         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);
+       break;
+      }
+    case DAC960_IOCTL_V2_EXECUTE_COMMAND:
+      {
+       DAC960_V2_UserCommand_T __user *UserSpaceUserCommand =
+         (DAC960_V2_UserCommand_T __user *) Argument;
+       DAC960_V2_UserCommand_T UserCommand;
+       DAC960_Controller_T *Controller;
+       DAC960_Command_T *Command = NULL;
+       DAC960_V2_CommandMailbox_T *CommandMailbox;
+       DAC960_V2_CommandStatus_T CommandStatus;
+       unsigned long flags;
+       int ControllerNumber, DataTransferLength;
+       int DataTransferResidue, RequestSenseLength;
+       unsigned char *DataTransferBuffer = NULL;
+       dma_addr_t DataTransferBufferDMA;
+       unsigned char *RequestSenseBuffer = NULL;
+       dma_addr_t RequestSenseBufferDMA;
+
+       ErrorCode = -EINVAL;
+       if (UserSpaceUserCommand == NULL)
+               break;
+       if (copy_from_user(&UserCommand, UserSpaceUserCommand,
+                          sizeof(DAC960_V2_UserCommand_T))) {
+               ErrorCode = -EFAULT;
+               break;
+       }
+       ErrorCode = -ENXIO;
+       ControllerNumber = UserCommand.ControllerNumber;
+       if (ControllerNumber < 0 ||
+           ControllerNumber > DAC960_ControllerCount - 1)
+               break;
+       Controller = DAC960_Controllers[ControllerNumber];
+       if (Controller == NULL)
+               break;
+       if (Controller->FirmwareType != DAC960_V2_Controller){
+               ErrorCode = -EINVAL;
+               break;
+       }
+       DataTransferLength = UserCommand.DataTransferLength;
+       ErrorCode = -ENOMEM;
+       if (DataTransferLength > 0)
+         {
+           DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+                               DataTransferLength, &DataTransferBufferDMA);
+           if (DataTransferBuffer == NULL)
+               break;
+           memset(DataTransferBuffer, 0, DataTransferLength);
+         }
+       else if (DataTransferLength < 0)
+         {
+           DataTransferBuffer = pci_alloc_consistent(Controller->PCIDevice,
+                               -DataTransferLength, &DataTransferBufferDMA);
+           if (DataTransferBuffer == NULL)
+               break;
+           if (copy_from_user(DataTransferBuffer,
+                              UserCommand.DataTransferBuffer,
+                              -DataTransferLength)) {
+               ErrorCode = -EFAULT;
+               goto Failure2;
+           }
+         }
+       RequestSenseLength = UserCommand.RequestSenseLength;
+       if (RequestSenseLength > 0)
+         {
+           RequestSenseBuffer = pci_alloc_consistent(Controller->PCIDevice,
+                       RequestSenseLength, &RequestSenseBufferDMA);
+           if (RequestSenseBuffer == NULL)
+             {
+               ErrorCode = -ENOMEM;
+               goto Failure2;
+             }
+           memset(RequestSenseBuffer, 0, RequestSenseLength);
+         }
+       spin_lock_irqsave(&Controller->queue_lock, flags);
+       while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
+         DAC960_WaitForCommand(Controller);
+       spin_unlock_irqrestore(&Controller->queue_lock, flags);
+       DAC960_V2_ClearCommand(Command);
+       Command->CommandType = DAC960_ImmediateCommand;
+       CommandMailbox = &Command->V2.CommandMailbox;
+       memcpy(CommandMailbox, &UserCommand.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 = DataTransferBufferDMA;
+           CommandMailbox->Common.DataTransferMemoryAddress
+                                 .ScatterGatherSegments[0]
+                                 .SegmentByteCount =
+             CommandMailbox->Common.DataTransferSize;
+         }
+       if (RequestSenseLength > 0)
+         {
+           CommandMailbox->Common.CommandControlBits
+                                 .NoAutoRequestSense = false;
+           CommandMailbox->Common.RequestSenseSize = RequestSenseLength;
+           CommandMailbox->Common.RequestSenseBusAddress =
+                                                       RequestSenseBufferDMA;
+         }
+       DAC960_ExecuteCommand(Command);
+       CommandStatus = Command->V2.CommandStatus;
+       RequestSenseLength = Command->V2.RequestSenseLength;
+       DataTransferResidue = Command->V2.DataTransferResidue;
+       spin_lock_irqsave(&Controller->queue_lock, flags);
+       DAC960_DeallocateCommand(Command);
+       spin_unlock_irqrestore(&Controller->queue_lock, flags);
+       if (RequestSenseLength > UserCommand.RequestSenseLength)
+         RequestSenseLength = UserCommand.RequestSenseLength;
+       if (copy_to_user(&UserSpaceUserCommand->DataTransferLength,
+                                &DataTransferResidue,
+                                sizeof(DataTransferResidue))) {
+               ErrorCode = -EFAULT;
+               goto Failure2;
+       }
+       if (copy_to_user(&UserSpaceUserCommand->RequestSenseLength,
+                        &RequestSenseLength, sizeof(RequestSenseLength))) {
+               ErrorCode = -EFAULT;
+               goto Failure2;
+       }
+       if (DataTransferLength > 0)
+         {
+           if (copy_to_user(UserCommand.DataTransferBuffer,
+                            DataTransferBuffer, DataTransferLength)) {
+               ErrorCode = -EFAULT;
+               goto Failure2;
+           }
+         }
+       if (RequestSenseLength > 0)
+         {
+           if (copy_to_user(UserCommand.RequestSenseBuffer,
+                            RequestSenseBuffer, RequestSenseLength)) {
+               ErrorCode = -EFAULT;
+               goto Failure2;
+           }
+         }
+       ErrorCode = CommandStatus;
+      Failure2:
+         pci_free_consistent(Controller->PCIDevice, abs(DataTransferLength),
+               DataTransferBuffer, DataTransferBufferDMA);
+       if (RequestSenseBuffer != NULL)
+         pci_free_consistent(Controller->PCIDevice, RequestSenseLength,
+               RequestSenseBuffer, RequestSenseBufferDMA);
+        break;
+      }
+    case DAC960_IOCTL_V2_GET_HEALTH_STATUS:
+      {
+       DAC960_V2_GetHealthStatus_T __user *UserSpaceGetHealthStatus =
+         (DAC960_V2_GetHealthStatus_T __user *) Argument;
+       DAC960_V2_GetHealthStatus_T GetHealthStatus;
+       DAC960_V2_HealthStatusBuffer_T HealthStatusBuffer;
+       DAC960_Controller_T *Controller;
+       int ControllerNumber;
+       if (UserSpaceGetHealthStatus == NULL) {
+               ErrorCode = -EINVAL;
+               break;
        }
-    }
-  BytesAvailable = strlen(StatusMessage) - Offset;
-  if (Count >= BytesAvailable)
-    {
-      Count = BytesAvailable;
-      *EOF = true;
-    }
-  if (Count <= 0) return 0;
-  *Start = Page;
-  memcpy(Page, &StatusMessage[Offset], Count);
-  return Count;
-}
-
-
-/*
-  DAC960_ProcReadInitialStatus implements reading /proc/rd/cN/initial_status.
-*/
-
-static int DAC960_ProcReadInitialStatus(char *Page, char **Start, off_t Offset,
-                                       int Count, int *EOF, void *Data)
-{
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
-  int BytesAvailable = Controller->InitialStatusLength - Offset;
-  if (Count >= BytesAvailable)
-    {
-      Count = BytesAvailable;
-      *EOF = true;
-    }
-  if (Count <= 0) return 0;
-  *Start = Page;
-  memcpy(Page, &Controller->CombinedStatusBuffer[Offset], Count);
-  return Count;
-}
-
-
-/*
-  DAC960_ProcReadCurrentStatus implements reading /proc/rd/cN/current_status.
-*/
-
-static int DAC960_ProcReadCurrentStatus(char *Page, char **Start, off_t Offset,
-                                       int Count, int *EOF, void *Data)
-{
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
-  unsigned char *StatusMessage =
-    "No Rebuild or Consistency Check in Progress\n";
-  int ProgressMessageLength = strlen(StatusMessage);
-  int BytesAvailable;
-  if (jiffies != Controller->LastCurrentStatusTime)
-    {
-      Controller->CurrentStatusLength = 0;
-      DAC960_AnnounceDriver(Controller);
-      DAC960_ReportControllerConfiguration(Controller);
-      DAC960_ReportDeviceConfiguration(Controller);
-      if (Controller->ProgressBufferLength > 0)
-       ProgressMessageLength = Controller->ProgressBufferLength;
-      if (DAC960_CheckStatusBuffer(Controller, 2 + ProgressMessageLength))
-       {
-         unsigned char *CurrentStatusBuffer = Controller->CurrentStatusBuffer;
-         CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
-         CurrentStatusBuffer[Controller->CurrentStatusLength++] = ' ';
-         if (Controller->ProgressBufferLength > 0)
-           strcpy(&CurrentStatusBuffer[Controller->CurrentStatusLength],
-                  Controller->ProgressBuffer);
-         else
-           strcpy(&CurrentStatusBuffer[Controller->CurrentStatusLength],
-                  StatusMessage);
-         Controller->CurrentStatusLength += ProgressMessageLength;
+       if (copy_from_user(&GetHealthStatus, UserSpaceGetHealthStatus,
+                          sizeof(DAC960_V2_GetHealthStatus_T))) {
+               ErrorCode = -EFAULT;
+               break;
        }
-      Controller->LastCurrentStatusTime = jiffies;
-    }
-  BytesAvailable = Controller->CurrentStatusLength - Offset;
-  if (Count >= BytesAvailable)
-    {
-      Count = BytesAvailable;
-      *EOF = true;
+       ErrorCode = -ENXIO;
+       ControllerNumber = GetHealthStatus.ControllerNumber;
+       if (ControllerNumber < 0 ||
+           ControllerNumber > DAC960_ControllerCount - 1)
+                   break;
+       Controller = DAC960_Controllers[ControllerNumber];
+       if (Controller == NULL)
+               break;
+       if (Controller->FirmwareType != DAC960_V2_Controller) {
+               ErrorCode = -EINVAL;
+               break;
+       }
+       if (copy_from_user(&HealthStatusBuffer,
+                          GetHealthStatus.HealthStatusBuffer,
+                          sizeof(DAC960_V2_HealthStatusBuffer_T))) {
+               ErrorCode = -EFAULT;
+               break;
+       }
+       while (Controller->V2.HealthStatusBuffer->StatusChangeCounter
+              == HealthStatusBuffer.StatusChangeCounter &&
+              Controller->V2.HealthStatusBuffer->NextEventSequenceNumber
+              == HealthStatusBuffer.NextEventSequenceNumber)
+         {
+           interruptible_sleep_on_timeout(&Controller->HealthStatusWaitQueue,
+                                          DAC960_MonitoringTimerInterval);
+           if (signal_pending(current)) {
+               ErrorCode = -EINTR;
+               break;
+           }
+         }
+       if (copy_to_user(GetHealthStatus.HealthStatusBuffer,
+                        Controller->V2.HealthStatusBuffer,
+                        sizeof(DAC960_V2_HealthStatusBuffer_T)))
+               ErrorCode = -EFAULT;
+       else
+               ErrorCode =  0;
+      }
+      default:
+       ErrorCode = -ENOTTY;
     }
-  if (Count <= 0) return 0;
-  *Start = Page;
-  memcpy(Page, &Controller->CurrentStatusBuffer[Offset], Count);
-  return Count;
+  mutex_unlock(&DAC960_mutex);
+  return ErrorCode;
 }
 
+static const struct file_operations DAC960_gam_fops = {
+       .owner          = THIS_MODULE,
+       .unlocked_ioctl = DAC960_gam_ioctl,
+       .llseek         = noop_llseek,
+};
 
-/*
-  DAC960_ProcReadUserCommand implements reading /proc/rd/cN/user_command.
-*/
+static struct miscdevice DAC960_gam_dev = {
+       DAC960_GAM_MINOR,
+       "dac960_gam",
+       &DAC960_gam_fops
+};
 
-static int DAC960_ProcReadUserCommand(char *Page, char **Start, off_t Offset,
-                                     int Count, int *EOF, void *Data)
+static int DAC960_gam_init(void)
 {
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
-  int BytesAvailable = Controller->UserStatusLength - Offset;
-  if (Count >= BytesAvailable)
-    {
-      Count = BytesAvailable;
-      *EOF = true;
-    }
-  if (Count <= 0) return 0;
-  *Start = Page;
-  memcpy(Page, &Controller->UserStatusBuffer[Offset], Count);
-  return Count;
-}
+       int ret;
 
-
-/*
-  DAC960_ProcWriteUserCommand implements writing /proc/rd/cN/user_command.
-*/
-
-static int DAC960_ProcWriteUserCommand(struct file *file, const char *Buffer,
-                                      unsigned long Count, void *Data)
-{
-  DAC960_Controller_T *Controller = (DAC960_Controller_T *) Data;
-  unsigned char CommandBuffer[80];
-  int Length;
-  if (Count > sizeof(CommandBuffer)-1) return -EINVAL;
-  if (copy_from_user(CommandBuffer, Buffer, Count)) return -EFAULT;
-  CommandBuffer[Count] = '\0';
-  Length = strlen(CommandBuffer);
-  if (CommandBuffer[Length-1] == '\n')
-    CommandBuffer[--Length] = '\0';
-  if (Controller->FirmwareType == DAC960_V1_Controller)
-    return (DAC960_V1_ExecuteUserCommand(Controller, CommandBuffer)
-           ? Count : -EBUSY);
-  else
-    return (DAC960_V2_ExecuteUserCommand(Controller, CommandBuffer)
-           ? Count : -EBUSY);
+       ret = misc_register(&DAC960_gam_dev);
+       if (ret)
+               printk(KERN_ERR "DAC960_gam: can't misc_register on minor %d\n", DAC960_GAM_MINOR);
+       return ret;
 }
 
-
-/*
-  DAC960_CreateProcEntries creates the /proc/rd/... entries for the
-  DAC960 Driver.
-*/
-
-static void DAC960_CreateProcEntries(DAC960_Controller_T *Controller)
+static void DAC960_gam_cleanup(void)
 {
-       struct proc_dir_entry *StatusProcEntry;
-       struct proc_dir_entry *ControllerProcEntry;
-       struct proc_dir_entry *UserCommandProcEntry;
-
-       if (DAC960_ProcDirectoryEntry == NULL) {
-               DAC960_ProcDirectoryEntry = proc_mkdir("rd", NULL);
-               StatusProcEntry = create_proc_read_entry("status", 0,
-                                          DAC960_ProcDirectoryEntry,
-                                          DAC960_ProcReadStatus, NULL);
-       }
-
-      sprintf(Controller->ControllerName, "c%d", Controller->ControllerNumber);
-      ControllerProcEntry = proc_mkdir(Controller->ControllerName,
-                                      DAC960_ProcDirectoryEntry);
-      create_proc_read_entry("initial_status", 0, ControllerProcEntry,
-                            DAC960_ProcReadInitialStatus, Controller);
-      create_proc_read_entry("current_status", 0, ControllerProcEntry,
-                            DAC960_ProcReadCurrentStatus, Controller);
-      UserCommandProcEntry =
-       create_proc_read_entry("user_command", S_IWUSR | S_IRUSR,
-                              ControllerProcEntry, DAC960_ProcReadUserCommand,
-                              Controller);
-      UserCommandProcEntry->write_proc = DAC960_ProcWriteUserCommand;
-      Controller->ControllerProcEntry = ControllerProcEntry;
+       misc_deregister(&DAC960_gam_dev);
 }
 
+#endif /* DAC960_GAM_MINOR */
 
-/*
-  DAC960_DestroyProcEntries destroys the /proc/rd/... entries for the
-  DAC960 Driver.
-*/
+static struct DAC960_privdata DAC960_GEM_privdata = {
+       .HardwareType =         DAC960_GEM_Controller,
+       .FirmwareType   =       DAC960_V2_Controller,
+       .InterruptHandler =     DAC960_GEM_InterruptHandler,
+       .MemoryWindowSize =     DAC960_GEM_RegisterWindowSize,
+};
 
-static void DAC960_DestroyProcEntries(DAC960_Controller_T *Controller)
-{
-      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);
-      Controller->ControllerProcEntry = NULL;
-}
 
 static struct DAC960_privdata DAC960_BA_privdata = {
        .HardwareType =         DAC960_BA_Controller,
@@ -6906,7 +7107,7 @@ static struct DAC960_privdata DAC960_BA_privdata = {
 
 static struct DAC960_privdata DAC960_LP_privdata = {
        .HardwareType =         DAC960_LP_Controller,
-       .FirmwareType   =       DAC960_LP_Controller,
+       .FirmwareType   =       DAC960_V2_Controller,
        .InterruptHandler =     DAC960_LP_InterruptHandler,
        .MemoryWindowSize =     DAC960_LP_RegisterWindowSize,
 };
@@ -6939,7 +7140,14 @@ static struct DAC960_privdata DAC960_P_privdata = {
        .MemoryWindowSize =     DAC960_PD_RegisterWindowSize,
 };
 
-static struct pci_device_id DAC960_id_table[] = {
+static const struct pci_device_id DAC960_id_table[] = {
+       {
+               .vendor         = PCI_VENDOR_ID_MYLEX,
+               .device         = PCI_DEVICE_ID_MYLEX_DAC960_GEM,
+               .subvendor      = PCI_VENDOR_ID_MYLEX,
+               .subdevice      = PCI_ANY_ID,
+               .driver_data    = (unsigned long) &DAC960_GEM_privdata,
+       },
        {
                .vendor         = PCI_VENDOR_ID_MYLEX,
                .device         = PCI_DEVICE_ID_MYLEX_DAC960_BA,
@@ -6994,15 +7202,26 @@ static struct pci_driver DAC960_pci_driver = {
        .remove         = DAC960_Remove,
 };
 
-static int DAC960_init_module(void)
+static int __init DAC960_init_module(void)
 {
-       return pci_module_init(&DAC960_pci_driver);
+       int ret;
+
+       ret =  pci_register_driver(&DAC960_pci_driver);
+#ifdef DAC960_GAM_MINOR
+       if (!ret)
+               DAC960_gam_init();
+#endif
+       return ret;
 }
 
-static void DAC960_cleanup_module(void)
+static void __exit DAC960_cleanup_module(void)
 {
        int i;
 
+#ifdef DAC960_GAM_MINOR
+       DAC960_gam_cleanup();
+#endif
+
        for (i = 0; i < DAC960_ControllerCount; i++) {
                DAC960_Controller_T *Controller = DAC960_Controllers[i];
                if (Controller == NULL)