fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / block / DAC960.c
index 56b9ce9..7f14350 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
@@ -16,8 +17,8 @@
 */
 
 
-#define DAC960_DriverVersion                   "2.5.47"
-#define DAC960_DriverDate                      "14 November 2002"
+#define DAC960_DriverVersion                   "2.5.48"
+#define DAC960_DriverDate                      "14 May 2006"
 
 
 #include <linux/module.h>
@@ -40,6 +41,8 @@
 #include <linux/timer.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/jiffies.h>
+#include <linux/random.h>
 #include <asm/io.h>
 #include <asm/uaccess.h>
 #include "DAC960.h"
@@ -91,34 +94,28 @@ static int DAC960_open(struct inode *inode, struct file *file)
        return 0;
 }
 
-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 = (long)disk->private_data;
-       struct hd_geometry g;
-       struct hd_geometry __user *loc = (struct hd_geometry __user *)arg;
-
-       if (cmd != HDIO_GETGEO || !loc)
-               return -EINVAL;
 
        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",
@@ -126,12 +123,11 @@ 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)
@@ -156,7 +152,7 @@ static int DAC960_revalidate_disk(struct gendisk *disk)
 static struct block_device_operations DAC960_BlockDeviceOperations = {
        .owner                  = THIS_MODULE,
        .open                   = DAC960_open,
-       .ioctl                  = DAC960_ioctl,
+       .getgeo                 = DAC960_getgeo,
        .media_changed          = DAC960_media_changed,
        .revalidate_disk        = DAC960_revalidate_disk,
 };
@@ -233,8 +229,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;
@@ -288,12 +283,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;
     }
@@ -312,11 +312,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;
@@ -325,13 +324,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,
@@ -411,14 +410,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)
     {
@@ -429,30 +426,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;
     }
 }
 
@@ -527,6 +517,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.
@@ -535,7 +553,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;
@@ -560,7 +578,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;
@@ -586,7 +604,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;
@@ -612,7 +630,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;
@@ -638,7 +656,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;
@@ -664,7 +682,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;
@@ -689,7 +707,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))
@@ -706,7 +724,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)
@@ -752,7 +770,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;
 
@@ -1127,7 +1145,7 @@ static boolean DAC960_V2_DeviceOperation(DAC960_Controller_T *Controller,
 static boolean 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;
@@ -1333,7 +1351,7 @@ skip_mailboxes:
 static boolean 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;
@@ -1459,6 +1477,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);
@@ -2501,7 +2530,6 @@ static boolean DAC960_RegisterBlockDevice(DAC960_Controller_T *Controller)
        blk_queue_max_sectors(RequestQueue, Controller->MaxBlocksPerCommand);
        disk->queue = RequestQueue;
        sprintf(disk->disk_name, "rd/c%dd%d", Controller->ControllerNumber, n);
-       sprintf(disk->devfs_name, "rd/host%d/target%d", Controller->ControllerNumber, n);
        disk->major = MajorNumber;
        disk->first_minor = n << DAC960_MaxPartitionsBits;
        disk->fops = &DAC960_BlockDeviceOperations;
@@ -2622,6 +2650,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;
@@ -2667,24 +2698,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;
@@ -2695,13 +2723,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;
@@ -2733,7 +2762,7 @@ DAC960_DetectController(struct pci_dev *PCI_Device,
   }
   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.
@@ -2753,6 +2782,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);
@@ -2953,7 +3012,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",
@@ -3270,7 +3330,7 @@ static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_
                Command->DmaDirection = PCI_DMA_TODEVICE;
                Command->CommandType = DAC960_WriteCommand;
        }
-       Command->Completion = Request->waiting;
+       Command->Completion = Request->end_io_data;
        Command->LogicalDriveNumber = (long)Request->rq_disk->private_data;
        Command->BlockNumber = Request->sector;
        Command->BlockCount = Request->nr_sectors;
@@ -3399,8 +3459,8 @@ static inline boolean DAC960_ProcessCompletedRequest(DAC960_Command_T *Command,
                Command->SegmentCount, Command->DmaDirection);
 
         if (!end_that_request_first(Request, UpToDate, Command->BlockCount)) {
-
-               end_that_request_last(Request);
+               add_disk_randomness(Request->rq_disk);
+               end_that_request_last(Request, UpToDate);
 
                if (Command->Completion) {
                        complete(Command->Completion);
@@ -3593,8 +3653,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 =
@@ -3696,7 +3756,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,
@@ -4718,15 +4778,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;
                }
@@ -5185,6 +5246,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
@@ -5192,11 +5293,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;
 
@@ -5235,11 +5335,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;
 
@@ -5278,11 +5377,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;
 
@@ -5317,11 +5415,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;
 
@@ -5356,11 +5453,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);
@@ -5395,11 +5491,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);
@@ -5538,8 +5633,8 @@ static void DAC960_MonitoringTimerFunction(unsigned long TimerData)
       unsigned int StatusChangeCounter =
        Controller->V2.HealthStatusBuffer->StatusChangeCounter;
       boolean ForceMonitoringCommand = false;
-      if (jiffies - Controller->SecondaryMonitoringTime
-         > DAC960_SecondaryMonitoringInterval)
+      if (time_after(jiffies, Controller->SecondaryMonitoringTime
+         + DAC960_SecondaryMonitoringInterval))
        {
          int LogicalDriveNumber;
          for (LogicalDriveNumber = 0;
@@ -5567,8 +5662,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 =
@@ -5705,8 +5800,8 @@ static void DAC960_Message(DAC960_MessageLevel_T MessageLevel,
       Controller->ProgressBufferLength = Length;
       if (Controller->EphemeralProgressMessage)
        {
-         if (jiffies - Controller->LastProgressReportTime
-             >= DAC960_ProgressReportingInterval)
+         if (time_after_eq(jiffies, Controller->LastProgressReportTime
+             + DAC960_ProgressReportingInterval))
            {
              printk("%sDAC960#%d: %s", DAC960_MessageLevelMap[MessageLevel],
                     Controller->ControllerNumber, Buffer);
@@ -6126,6 +6221,9 @@ static boolean DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller,
   unsigned long flags;
   unsigned char Channel, TargetID, LogicalDriveNumber;
   unsigned short LogicalDeviceNumber;
+  wait_queue_t __wait;
+  
+  init_waitqueue_entry(&__wait, current);
 
   spin_lock_irqsave(&Controller->queue_lock, flags);
   while ((Command = DAC960_AllocateCommand(Controller)) == NULL)
@@ -6308,11 +6406,18 @@ static boolean DAC960_V2_ExecuteUserCommand(DAC960_Controller_T *Controller,
                                        .SegmentByteCount =
            CommandMailbox->ControllerInfo.DataTransferSize;
          DAC960_ExecuteCommand(Command);
+         add_wait_queue(&Controller->CommandWaitQueue, &__wait);
+         set_current_state(TASK_UNINTERRUPTIBLE);
+         
          while (Controller->V2.NewControllerInformation->PhysicalScanActive)
            {
              DAC960_ExecuteCommand(Command);
-             sleep_on_timeout(&Controller->CommandWaitQueue, HZ);
+             schedule_timeout(HZ);
+             set_current_state(TASK_UNINTERRUPTIBLE);
            }
+         current->state = TASK_RUNNING;
+         remove_wait_queue(&Controller->CommandWaitQueue, &__wait);
+          
          DAC960_UserCritical("Discovery Completed\n", Controller);
        }
     }
@@ -6958,6 +7063,14 @@ static void DAC960_gam_cleanup(void)
 
 #endif /* DAC960_GAM_MINOR */
 
+static struct DAC960_privdata DAC960_GEM_privdata = {
+       .HardwareType =         DAC960_GEM_Controller,
+       .FirmwareType   =       DAC960_V2_Controller,
+       .InterruptHandler =     DAC960_GEM_InterruptHandler,
+       .MemoryWindowSize =     DAC960_GEM_RegisterWindowSize,
+};
+
+
 static struct DAC960_privdata DAC960_BA_privdata = {
        .HardwareType =         DAC960_BA_Controller,
        .FirmwareType   =       DAC960_V2_Controller,
@@ -7001,6 +7114,13 @@ static struct DAC960_privdata DAC960_P_privdata = {
 };
 
 static 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,
@@ -7059,7 +7179,7 @@ static int DAC960_init_module(void)
 {
        int ret;
 
-       ret =  pci_module_init(&DAC960_pci_driver);
+       ret =  pci_register_driver(&DAC960_pci_driver);
 #ifdef DAC960_GAM_MINOR
        if (!ret)
                DAC960_gam_init();
@@ -7093,3 +7213,4 @@ module_init(DAC960_init_module);
 module_exit(DAC960_cleanup_module);
 
 MODULE_LICENSE("GPL");
+MODULE_VERSION(DAC960_DriverVersion);