linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / scsi / gdth.c
index 5c0c927..f6d44b6 100644 (file)
@@ -4,9 +4,9 @@
  * Intel Corporation:  Storage RAID Controllers                         *
  *                                                                      *
  * gdth.c                                                               *
- * Copyright (C) 1995-06 ICP vortex GmbH, Achim Leubner                 *
+ * Copyright (C) 1995-04 ICP vortex GmbH, Achim Leubner                 *
  * Copyright (C) 2002-04 Intel Corporation                              *
- * Copyright (C) 2003-06 Adaptec Inc.                                   *
+ * Copyright (C) 2003-04 Adaptec Inc.                                   *
  * <achim_leubner@adaptec.com>                                          *
  *                                                                      *
  * Additions/Fixes:                                                     *
  * along with this kernel; if not, write to the Free Software           *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
  *                                                                      *
- * Linux kernel 2.4.x, 2.6.x supported                                  *
+ * Linux kernel 2.2.x, 2.4.x, 2.6.x supported                           *
  *                                                                      *
  * $Log: gdth.c,v $
- * Revision 1.74  2006/04/10 13:44:47  achim
- * Community changes for 2.6.x
- * Kernel 2.2.x no longer supported
- * scsi_request interface removed, thanks to Christoph Hellwig
- *
  * Revision 1.73  2004/03/31 13:33:03  achim
  * Special command 0xfd implemented to detect 64-bit DMA support
  *
@@ -99,7 +94,7 @@
  * Bugfix free_irq()
  *
  * Revision 1.56  2001/08/09 11:19:39  achim
- * Scsi_Host_Template changes
+ * struct scsi_host_template changes
  *
  * Revision 1.55  2001/08/09 10:11:28  achim
  * Command HOST_UNFREEZE_IO before cache service init.
 #include <linux/proc_fs.h>
 #include <linux/time.h>
 #include <linux/timer.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6)
-#include <linux/dma-mapping.h>
-#else
-#define DMA_32BIT_MASK 0x00000000ffffffffULL
-#define DMA_64BIT_MASK 0xffffffffffffffffULL
-#endif
-
 #ifdef GDTH_RTC
 #include <linux/mc146818rtc.h>
 #endif
 
 #include "scsi.h"
 #include <scsi/scsi_host.h>
-#include "gdth_kcompat.h"
 #include "gdth.h"
+#include "gdth_kcompat.h"
 
 static void gdth_delay(int milliseconds);
 static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs);
@@ -475,8 +463,6 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
 
 static void gdth_flush(int hanum);
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
-static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *));
-static void gdth_scsi_done(struct scsi_cmnd *scp);
 
 #ifdef DEBUG_GDTH
 static unchar   DebugState = DEBUG_GDTH;
@@ -569,8 +555,8 @@ static struct timer_list gdth_timer;
 #endif
 
 #define PTR2USHORT(a)   (ushort)(ulong)(a)
-#define GDTOFFSOF(a,b)  (size_t)&(((a*)0)->b)
-#define INDEX_OK(i,t)   ((i)<ARRAY_SIZE(t))
+#define GDTOFFSOF(a,b)  (size_t)&(((a*)0)->b)   
+#define INDEX_OK(i,t)   ((i)<sizeof(t)/sizeof((t)[0]))
 
 #define NUMDATA(a)      ( (gdth_num_str  *)((a)->hostdata))
 #define HADATA(a)       (&((gdth_ext_str *)((a)->hostdata))->haext)
@@ -656,7 +642,6 @@ static int probe_eisa_isa = 0;
 static int force_dma32 = 0;
 
 /* parameters for modprobe/insmod */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11)
 module_param_array(irq, int, NULL, 0);
 module_param(disable, int, 0);
 module_param(reserve_mode, int, 0);
@@ -669,23 +654,8 @@ module_param(virt_ctr, int, 0);
 module_param(shared_access, int, 0);
 module_param(probe_eisa_isa, int, 0);
 module_param(force_dma32, int, 0);
-#else
-MODULE_PARM(irq, "i");
-MODULE_PARM(disable, "i");
-MODULE_PARM(reserve_mode, "i");
-MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i");
-MODULE_PARM(reverse_scan, "i");
-MODULE_PARM(hdr_channel, "i");
-MODULE_PARM(max_ids, "i");
-MODULE_PARM(rescan, "i");
-MODULE_PARM(virt_ctr, "i");
-MODULE_PARM(shared_access, "i");
-MODULE_PARM(probe_eisa_isa, "i");
-MODULE_PARM(force_dma32, "i");
-#endif
 MODULE_AUTHOR("Achim Leubner");
 MODULE_LICENSE("GPL");
-MODULE_VERSION(GDTH_VERSION_STR);
 
 /* ioctl interface */
 static struct file_operations gdth_fops = {
@@ -701,7 +671,7 @@ static struct file_operations gdth_fops = {
 static struct notifier_block gdth_notifier = {
     gdth_halt, NULL, 0
 };
-static int notifier_disabled = 0;
+
 
 static void gdth_delay(int milliseconds)
 {
@@ -712,91 +682,6 @@ static void gdth_delay(int milliseconds)
     }
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-static void gdth_scsi_done(struct scsi_cmnd *scp)
-{
-    TRACE2(("gdth_scsi_done()\n"));
-
-    if (scp->request)
-        complete((struct completion *)scp->request);
-}
-
-int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
-                   int timeout, u32 *info)
-{
-    Scsi_Cmnd *scp;
-    DECLARE_COMPLETION_ONSTACK(wait);
-    int rval;
-
-    scp = kmalloc(sizeof(*scp), GFP_KERNEL);
-    if (!scp)
-        return -ENOMEM;
-    memset(scp, 0, sizeof(*scp));
-    scp->device = sdev;
-    /* use request field to save the ptr. to completion struct. */
-    scp->request = (struct request *)&wait;
-    scp->timeout_per_command = timeout*HZ;
-    scp->request_buffer = gdtcmd;
-    scp->cmd_len = 12;
-    memcpy(scp->cmnd, cmnd, 12);
-    scp->SCp.this_residual = IOCTL_PRI;   /* priority */
-    scp->done = gdth_scsi_done; /* some fn. test this */
-    gdth_queuecommand(scp, gdth_scsi_done);
-    wait_for_completion(&wait);
-
-    rval = scp->SCp.Status;
-    if (info)
-        *info = scp->SCp.Message;
-    kfree(scp);
-    return rval;
-}
-#else
-static void gdth_scsi_done(Scsi_Cmnd *scp)
-{
-    TRACE2(("gdth_scsi_done()\n"));
-
-    scp->request.rq_status = RQ_SCSI_DONE;
-    if (scp->request.waiting)
-        complete(scp->request.waiting);
-}
-
-int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd,
-                   int timeout, u32 *info)
-{
-    Scsi_Cmnd *scp = scsi_allocate_device(sdev, 1, FALSE);
-    unsigned bufflen = gdtcmd ? sizeof(gdth_cmd_str) : 0;
-    DECLARE_COMPLETION_ONSTACK(wait);
-    int rval;
-
-    if (!scp)
-        return -ENOMEM;
-    scp->cmd_len = 12;
-    scp->use_sg = 0;
-    scp->SCp.this_residual = IOCTL_PRI;   /* priority */
-    scp->request.rq_status = RQ_SCSI_BUSY;
-    scp->request.waiting = &wait;
-    scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
-    wait_for_completion(&wait);
-
-    rval = scp->SCp.Status;
-    if (info)
-        *info = scp->SCp.Message;
-
-    scsi_release_command(scp);
-    return rval;
-}
-#endif
-
-int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd,
-                 int timeout, u32 *info)
-{
-    struct scsi_device *sdev = scsi_get_host_dev(shost);
-    int rval = __gdth_execute(sdev, gdtcmd, cmnd, timeout, info);
-
-    scsi_free_host_dev(sdev);
-    return rval;
-}
-
 static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs)
 {
     *cyls = size /HEADS/SECS;
@@ -887,7 +772,7 @@ static struct pci_device_id gdthtable[] __attribute_used__ = {
 MODULE_DEVICE_TABLE(pci,gdthtable);
 
 static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt,
-                                   ushort vendor, ushort device)
+                                           ushort vendor, ushort device)
 {
     ulong base0, base1, base2;
     struct pci_dev *pdev;
@@ -2362,16 +2247,14 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority)
     ha = HADATA(gdth_ctr_tab[hanum]);
     spin_lock_irqsave(&ha->smp_lock, flags);
 
-    if (scp->done != gdth_scsi_done) {
-        scp->SCp.this_residual = (int)priority;
-        b = virt_ctr ? NUMDATA(scp->device->host)->busnum:scp->device->channel;
-        t = scp->device->id;
-        if (priority >= DEFAULT_PRI) {
-            if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
-                (b==ha->virt_bus && t<MAX_HDRIVES && ha->hdr[t].lock)) {
-                TRACE2(("gdth_putq(): locked IO ->update_timeout()\n"));
-                scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
-            }
+    scp->SCp.this_residual = (int)priority;
+    b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+    t = scp->device->id;
+    if (priority >= DEFAULT_PRI) {
+        if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
+            (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) {
+            TRACE2(("gdth_putq(): locked IO -> update_timeout()\n"));
+            scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
         }
     }
 
@@ -2425,18 +2308,14 @@ static void gdth_next(int hanum)
     for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) {
         if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr)
             pscp = (Scsi_Cmnd *)pscp->SCp.ptr;
-        if (nscp->done != gdth_scsi_done) {
-            b = virt_ctr ?
-                NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
-            t = nscp->device->id;
-            l = nscp->device->lun;
-            if (nscp->SCp.this_residual >= DEFAULT_PRI) {
-                if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
-                    (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock))
-                    continue;
-            }
-        } else
-            b = t = l = 0;
+        b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
+        t = nscp->device->id;
+        l = nscp->device->lun;
+        if (nscp->SCp.this_residual >= DEFAULT_PRI) {
+            if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) ||
+                (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) 
+                continue;
+        }
 
         if (firsttime) {
             if (gdth_test_busy(hanum)) {        /* controller busy ? */
@@ -2451,7 +2330,7 @@ static void gdth_next(int hanum)
             firsttime = FALSE;
         }
 
-        if (nscp->done != gdth_scsi_done) {
+        if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) {        
         if (nscp->SCp.phase == -1) {
             nscp->SCp.phase = CACHESERVICE;           /* default: cache svc. */ 
             if (nscp->cmnd[0] == TEST_UNIT_READY) {
@@ -2514,7 +2393,7 @@ static void gdth_next(int hanum)
                 else
                     nscp->scsi_done(nscp);
             }
-        } else if (nscp->done == gdth_scsi_done) {
+        } else if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) {
             if (!(cmd_index=gdth_special_cmd(hanum,nscp)))
                 this_cmd = FALSE;
             next_cmd = FALSE;
@@ -2662,13 +2541,13 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
     gdth_ha_str *ha;
     char *address;
 
-    cpcount = count<=(ushort)scp->request_bufflen ? count:(ushort)scp->request_bufflen;
+    cpcount = count<=(ushort)scp->bufflen ? count:(ushort)scp->bufflen;
     ha = HADATA(gdth_ctr_tab[hanum]);
 
     if (scp->use_sg) {
         sl = (struct scatterlist *)scp->request_buffer;
         for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) {
-            unsigned long flags;
+           unsigned long flags;
             cpnow = (ushort)sl->length;
             TRACE(("copy_internal() now %d sum %d count %d %d\n",
                           cpnow,cpsum,cpcount,(ushort)scp->bufflen));
@@ -2680,19 +2559,12 @@ static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
                        hanum);
                 return;
             }
-            local_irq_save(flags);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-            address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset;
-            memcpy(address,buffer,cpnow);
-            flush_dcache_page(sl->page);
-            kunmap_atomic(address, KM_BIO_SRC_IRQ);
-#else
-            address = kmap_atomic(sl->page, KM_BH_IRQ) + sl->offset;
+           local_irq_save(flags);
+           address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset;
             memcpy(address,buffer,cpnow);
-            flush_dcache_page(sl->page);
-            kunmap_atomic(address, KM_BH_IRQ);
-#endif
-            local_irq_restore(flags);
+           flush_dcache_page(sl->page);
+           kunmap_atomic(address, KM_BIO_SRC_IRQ);
+           local_irq_restore(flags);
             if (cpsum == cpcount)
                 break;
             buffer += cpnow;
@@ -3073,9 +2945,9 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
         offset = (ulong)scp->sense_buffer & ~PAGE_MASK;
         sense_paddr = pci_map_page(ha->pdev,page,offset,
                                    16,PCI_DMA_FROMDEVICE);
-        *(ulong32 *)&scp->SCp.buffer = (ulong32)sense_paddr;
+        scp->SCp.buffer = (struct scatterlist *)((ulong32)sense_paddr);
         /* high part, if 64bit */
-        *(ulong32 *)&scp->host_scribble = (ulong32)((ulong64)sense_paddr >> 32);
+        scp->host_scribble = (char *)(ulong32)((ulong64)sense_paddr >> 32);
         cmdp->OpCode           = GDT_WRITE;             /* always */
         cmdp->BoardNode        = LOCALBOARD;
         if (mode64) { 
@@ -3149,7 +3021,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b)
             }
 #endif
 
-        } else if (scp->request_bufflen) {
+        } else {
             scp->SCp.Status = GDTH_MAP_SINGLE;
             scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; 
             page = virt_to_page(scp->request_buffer);
@@ -3436,7 +3308,7 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
     }
 
     if (!gdth_polling)
-        spin_lock_irqsave(&ha2->smp_lock, flags);
+       spin_lock_irqsave(&ha2->smp_lock, flags);
     wait_index = 0;
 
     /* search controller */
@@ -3532,7 +3404,7 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
                 IStatus &= ~0x80;
 #ifdef INT_COAL
                 if (coalesced)
-                    ha->status = pcs->ext_status && 0xffff;
+                    ha->status = pcs->ext_status & 0xffff;
                 else 
 #endif
                     ha->status = gdth_readw(&dp6m_ptr->i960r.status);
@@ -3544,7 +3416,7 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
             if (coalesced) {    
                 ha->info = pcs->info0;
                 ha->info2 = pcs->info1;
-                ha->service = (pcs->ext_status >> 16) && 0xffff;
+                ha->service = (pcs->ext_status >> 16) & 0xffff;
             } else
 #endif
             {
@@ -3769,10 +3641,9 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
                            scp->request_bufflen,scp->SCp.Message);
         if (scp->SCp.buffer) {
             dma_addr_t addr;
-            addr = (dma_addr_t)*(ulong32 *)&scp->SCp.buffer;
+            addr = (dma_addr_t)(ulong32)scp->SCp.buffer;
             if (scp->host_scribble)
-                addr += (dma_addr_t)
-                    ((ulong64)(*(ulong32 *)&scp->host_scribble) << 32);
+                addr += (dma_addr_t)((ulong64)(ulong32)scp->host_scribble << 32);               
             pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE);
         }
 
@@ -4282,11 +4153,7 @@ int __init option_setup(char *str)
     return 1;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 static int __init gdth_detect(struct scsi_host_template *shtp)
-#else
-static int __init gdth_detect(Scsi_Host_Template *shtp)
-#endif
 {
     struct Scsi_Host *shp;
     gdth_pci_str pcistr[MAXHA];
@@ -4320,7 +4187,7 @@ static int __init gdth_detect(Scsi_Host_Template *shtp)
         return 0;
     }
 
-    printk("GDT-HA: Storage RAID Controller Driver. Version: %s\n",GDTH_VERSION_STR);
+    printk("GDT-HA: Storage RAID Controller Driver. Version: %s \n",GDTH_VERSION_STR);
     /* initializations */
     gdth_polling = TRUE; b = 0;
     gdth_clear_events();
@@ -4351,7 +4218,7 @@ static int __init gdth_detect(Scsi_Host_Template *shtp)
                 printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n",
                        isa_bios,ha->irq,ha->drq);
 
-                if (request_irq(ha->irq,gdth_interrupt,IRQF_DISABLED,"gdth",ha)) {
+                if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) {
                     printk("GDT-ISA: Unable to allocate IRQ\n");
                     scsi_unregister(shp);
                     continue;
@@ -4477,7 +4344,7 @@ static int __init gdth_detect(Scsi_Host_Template *shtp)
                 printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
                        eisa_slot>>12,ha->irq);
 
-                if (request_irq(ha->irq,gdth_interrupt,IRQF_DISABLED,"gdth",ha)) {
+                if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) {
                     printk("GDT-EISA: Unable to allocate IRQ\n");
                     scsi_unregister(shp);
                     continue;
@@ -4604,7 +4471,7 @@ static int __init gdth_detect(Scsi_Host_Template *shtp)
                pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq);
 
         if (request_irq(ha->irq, gdth_interrupt,
-                        IRQF_DISABLED|IRQF_SHARED, "gdth", ha))
+                        SA_INTERRUPT|SA_SHIRQ, "gdth", ha))
         {
             printk("GDT-PCI: Unable to allocate IRQ\n");
             scsi_unregister(shp);
@@ -4660,15 +4527,15 @@ static int __init gdth_detect(Scsi_Host_Template *shtp)
             if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)||
                 /* 64-bit DMA only supported from FW >= x.43 */
                 (!ha->dma64_support)) {
-                if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
+                if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) {
                     printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum);
                     err = TRUE;
                 }
             } else {
                 shp->max_cmd_len = 16;
-                if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) {
+                if (!pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffffffffffffULL)) {
                     printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum);
-                } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) {
+                } else if (pci_set_dma_mask(pcistr[ctr].pdev, 0xffffffff)) {
                     printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum);
                     err = TRUE;
                 }
@@ -4728,13 +4595,13 @@ static int __init gdth_detect(Scsi_Host_Template *shtp)
         add_timer(&gdth_timer);
 #endif
         major = register_chrdev(0,"gdth",&gdth_fops);
-        notifier_disabled = 0;
         register_reboot_notifier(&gdth_notifier);
     }
     gdth_polling = FALSE;
     return gdth_ctr_vcount;
 }
 
+
 static int gdth_release(struct Scsi_Host *shp)
 {
     int hanum;
@@ -4883,7 +4750,7 @@ static int gdth_eh_bus_reset(Scsi_Cmnd *scp)
         gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS,
                           BUS_L2P(ha,b), 0, 0);
         gdth_polling = FALSE;
-        spin_unlock_irqrestore(&ha->smp_lock, flags);
+       spin_unlock_irqrestore(&ha->smp_lock, flags);
     }
     return SUCCESS;
 }
@@ -4951,9 +4818,7 @@ static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *))
     priority = DEFAULT_PRI;
     if (scp->done == gdth_scsi_done)
         priority = scp->SCp.this_residual;
-    else
-        gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
-
+    gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
     gdth_putq( hanum, scp, priority );
     gdth_next( hanum );
     return 0;
@@ -5056,7 +4921,11 @@ static int ioc_resetdrv(void __user *arg, char *cmnd)
     gdth_cmd_str cmd;
     int hanum;
     gdth_ha_str *ha;
-    int rval;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Request *srp;
+#else
+    Scsi_Cmnd *scp;
+#endif
 
     if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) ||
         res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES)
@@ -5073,11 +4942,25 @@ static int ioc_resetdrv(void __user *arg, char *cmnd)
         cmd.u.cache64.DeviceNo = res.number;
     else
         cmd.u.cache.DeviceNo = res.number;
-
-    rval = __gdth_execute(ha->sdev, &cmd, cmnd, 30, NULL);
-    if (rval < 0)
-        return rval;
-    res.status = rval;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    srp  = scsi_allocate_request(ha->sdev, GFP_KERNEL);
+    if (!srp)
+        return -ENOMEM;
+    srp->sr_cmd_len = 12;
+    srp->sr_use_sg = 0;
+    gdth_do_req(srp, &cmd, cmnd, 30);
+    res.status = (ushort)srp->sr_command->SCp.Status;
+    scsi_release_request(srp);
+#else
+    scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
+    if (!scp)
+        return -ENOMEM;
+    scp->cmd_len = 12;
+    scp->use_sg = 0;
+    gdth_do_cmd(scp, &cmd, cmnd, 30);
+    res.status = (ushort)scp->SCp.Status;
+    scsi_release_command(scp);
+#endif
 
     if (copy_to_user(arg, &res, sizeof(gdth_ioctl_reset)))
         return -EFAULT;
@@ -5090,8 +4973,12 @@ static int ioc_general(void __user *arg, char *cmnd)
     char *buf = NULL;
     ulong64 paddr; 
     int hanum;
-    gdth_ha_str *ha;
-    int rval;
+        gdth_ha_str *ha; 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        Scsi_Request *srp;
+#else
+        Scsi_Cmnd *scp;
+#endif
         
     if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)) ||
         gen.ionode >= gdth_ctr_count)
@@ -5183,10 +5070,27 @@ static int ioc_general(void __user *arg, char *cmnd)
         }
     }
 
-    rval = __gdth_execute(ha->sdev, &gen.command, cmnd, gen.timeout, &gen.info);
-    if (rval < 0)
-        return rval;
-    gen.status = rval;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    srp  = scsi_allocate_request(ha->sdev, GFP_KERNEL);
+    if (!srp)
+        return -ENOMEM;
+    srp->sr_cmd_len = 12;
+    srp->sr_use_sg = 0;
+    gdth_do_req(srp, &gen.command, cmnd, gen.timeout);
+    gen.status = srp->sr_command->SCp.Status;
+    gen.info = srp->sr_command->SCp.Message;
+    scsi_release_request(srp);
+#else
+    scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
+    if (!scp)
+        return -ENOMEM;
+    scp->cmd_len = 12;
+    scp->use_sg = 0;
+    gdth_do_cmd(scp, &gen.command, cmnd, gen.timeout);
+    gen.status = scp->SCp.Status;
+    gen.info = scp->SCp.Message;
+    scsi_release_command(scp);
+#endif
 
     if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf, 
                      gen.data_len + gen.sense_len)) {
@@ -5209,22 +5113,40 @@ static int ioc_hdrlist(void __user *arg, char *cmnd)
     gdth_ha_str *ha;
     unchar i;
     int hanum, rc = -ENOMEM;
-    u32 cluster_type = 0;
-
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Request *srp;
+#else
+    Scsi_Cmnd *scp;
+#endif
+        
     rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
     cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
     if (!rsc || !cmd)
-        goto free_fail;
+       goto free_fail;
 
     if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
         rsc->ionode >= gdth_ctr_count) {
         rc = -EFAULT;
-        goto free_fail;
+       goto free_fail;
     }
     hanum = rsc->ionode;
     ha = HADATA(gdth_ctr_tab[hanum]);
     memset(cmd, 0, sizeof(gdth_cmd_str));
    
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    srp  = scsi_allocate_request(ha->sdev, GFP_KERNEL);
+    if (!srp)
+        goto free_fail;
+    srp->sr_cmd_len = 12;
+    srp->sr_use_sg = 0;
+#else
+    scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
+    if (!scp)
+        goto free_fail;
+    scp->cmd_len = 12;
+    scp->use_sg = 0;
+#endif
+
     for (i = 0; i < MAX_HDRIVES; ++i) { 
         if (!ha->hdr[i].present) {
             rsc->hdr_list[i].bus = 0xff; 
@@ -5241,15 +5163,27 @@ static int ioc_hdrlist(void __user *arg, char *cmnd)
                 cmd->u.cache64.DeviceNo = i;
             else
                 cmd->u.cache.DeviceNo = i;
-            if (__gdth_execute(ha->sdev, cmd, cmnd, 30, &cluster_type) == S_OK)
-                rsc->hdr_list[i].cluster_type = cluster_type;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            gdth_do_req(srp, cmd, cmnd, 30);
+            if (srp->sr_command->SCp.Status == S_OK)
+                rsc->hdr_list[i].cluster_type = srp->sr_command->SCp.Message;
+#else
+            gdth_do_cmd(scp, cmd, cmnd, 30);
+            if (scp->SCp.Status == S_OK)
+                rsc->hdr_list[i].cluster_type = scp->SCp.Message;
+#endif
         }
     } 
-
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    scsi_release_request(srp);
+#else
+    scsi_release_command(scp);
+#endif       
     if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan)))
         rc = -EFAULT;
     else
-        rc = 0;
+       rc = 0;
 
 free_fail:
     kfree(rsc);
@@ -5267,21 +5201,40 @@ static int ioc_rescan(void __user *arg, char *cmnd)
     int rc = -ENOMEM;
     ulong flags;
     gdth_ha_str *ha; 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Request *srp;
+#else
+    Scsi_Cmnd *scp;
+#endif
 
     rsc = kmalloc(sizeof(*rsc), GFP_KERNEL);
     cmd = kmalloc(sizeof(*cmd), GFP_KERNEL);
     if (!cmd || !rsc)
-        goto free_fail;
+       goto free_fail;
 
     if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) ||
         rsc->ionode >= gdth_ctr_count) {
-        rc = -EFAULT;
-        goto free_fail;
+       rc = -EFAULT;
+       goto free_fail;
     }
     hanum = rsc->ionode;
     ha = HADATA(gdth_ctr_tab[hanum]);
     memset(cmd, 0, sizeof(gdth_cmd_str));
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    srp  = scsi_allocate_request(ha->sdev, GFP_KERNEL);
+    if (!srp)
+        goto free_fail;
+    srp->sr_cmd_len = 12;
+    srp->sr_use_sg = 0;
+#else
+    scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
+    if (!scp)
+        goto free_fail;
+    scp->cmd_len = 12;
+    scp->use_sg = 0;
+#endif
+     
     if (rsc->flag == 0) {
         /* old method: re-init. cache service */
         cmd->Service = CACHESERVICE;
@@ -5292,8 +5245,19 @@ static int ioc_rescan(void __user *arg, char *cmnd)
             cmd->OpCode = GDT_INIT;
             cmd->u.cache.DeviceNo = LINUX_OS;
         }
-
-        status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        gdth_do_req(srp, cmd, cmnd, 30);
+        status = (ushort)srp->sr_command->SCp.Status;
+        info = (ulong32)srp->sr_command->SCp.Message;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+        gdth_do_cmd(scp, cmd, cmnd, 30);
+        status = (ushort)scp->SCp.Status;
+        info = (ulong32)scp->SCp.Message;
+#else
+        gdth_do_cmd(&scp, cmd, cmnd, 30);
+        status = (ushort)scp.SCp.Status;
+        info = (ulong32)scp.SCp.Message;
+#endif
         i = 0;
         hdr_cnt = (status == S_OK ? (ushort)info : 0);
     } else {
@@ -5308,9 +5272,15 @@ static int ioc_rescan(void __user *arg, char *cmnd)
             cmd->u.cache64.DeviceNo = i;
         else 
             cmd->u.cache.DeviceNo = i;
-
-        status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
-
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        gdth_do_req(srp, cmd, cmnd, 30);
+        status = (ushort)srp->sr_command->SCp.Status;
+        info = (ulong32)srp->sr_command->SCp.Message;
+#else
+        gdth_do_cmd(scp, cmd, cmnd, 30);
+        status = (ushort)scp->SCp.Status;
+        info = (ulong32)scp->SCp.Message;
+#endif
         spin_lock_irqsave(&ha->smp_lock, flags);
         rsc->hdr_list[i].bus = ha->virt_bus;
         rsc->hdr_list[i].target = i;
@@ -5342,9 +5312,15 @@ static int ioc_rescan(void __user *arg, char *cmnd)
             cmd->u.cache64.DeviceNo = i;
         else
             cmd->u.cache.DeviceNo = i;
-
-        status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
-
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        gdth_do_req(srp, cmd, cmnd, 30);
+        status = (ushort)srp->sr_command->SCp.Status;
+        info = (ulong32)srp->sr_command->SCp.Message;
+#else
+        gdth_do_cmd(scp, cmd, cmnd, 30);
+        status = (ushort)scp->SCp.Status;
+        info = (ulong32)scp->SCp.Message;
+#endif
         spin_lock_irqsave(&ha->smp_lock, flags);
         ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0);
         spin_unlock_irqrestore(&ha->smp_lock, flags);
@@ -5355,9 +5331,15 @@ static int ioc_rescan(void __user *arg, char *cmnd)
             cmd->u.cache64.DeviceNo = i;
         else
             cmd->u.cache.DeviceNo = i;
-
-        status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
-
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        gdth_do_req(srp, cmd, cmnd, 30);
+        status = (ushort)srp->sr_command->SCp.Status;
+        info = (ulong32)srp->sr_command->SCp.Message;
+#else
+        gdth_do_cmd(scp, cmd, cmnd, 30);
+        status = (ushort)scp->SCp.Status;
+        info = (ulong32)scp->SCp.Message;
+#endif
         spin_lock_irqsave(&ha->smp_lock, flags);
         ha->hdr[i].cluster_type = 
             ((status == S_OK && !shared_access) ? (ushort)info : 0);
@@ -5370,18 +5352,29 @@ static int ioc_rescan(void __user *arg, char *cmnd)
             cmd->u.cache64.DeviceNo = i;
         else
             cmd->u.cache.DeviceNo = i;
-
-        status = __gdth_execute(ha->sdev, cmd, cmnd, 30, &info);
-
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        gdth_do_req(srp, cmd, cmnd, 30);
+        status = (ushort)srp->sr_command->SCp.Status;
+        info = (ulong32)srp->sr_command->SCp.Message;
+#else
+        gdth_do_cmd(scp, cmd, cmnd, 30);
+        status = (ushort)scp->SCp.Status;
+        info = (ulong32)scp->SCp.Message;
+#endif
         spin_lock_irqsave(&ha->smp_lock, flags);
         ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0);
         spin_unlock_irqrestore(&ha->smp_lock, flags);
     }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    scsi_release_request(srp);
+#else
+    scsi_release_command(scp);
+#endif       
  
     if (copy_to_user(arg, rsc, sizeof(gdth_ioctl_rescan)))
         rc = -EFAULT;
     else
-        rc = 0;
+       rc = 0;
 
 free_fail:
     kfree(rsc);
@@ -5521,18 +5514,17 @@ static int gdth_ioctl(struct inode *inode, struct file *filep,
         hanum = res.ionode; 
         ha = HADATA(gdth_ctr_tab[hanum]);
 
+        /* Because we need a Scsi_Cmnd struct., we make a scsi_allocate device also for kernels >=2.6.x */        
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        scp  = kmalloc(sizeof(*scp), GFP_KERNEL);
+        scp  = scsi_get_command(ha->sdev, GFP_KERNEL);
         if (!scp)
             return -ENOMEM;
-        memset(scp, 0, sizeof(*scp));
-        scp->device = ha->sdev;
         scp->cmd_len = 12;
         scp->use_sg = 0;
         scp->device->channel = virt_ctr ? 0 : res.number;
         rval = gdth_eh_bus_reset(scp);
         res.status = (rval == SUCCESS ? S_OK : S_GENERR);
-        kfree(scp);
+        scsi_put_command(scp);
 #else
         scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
         if (!scp)
@@ -5565,12 +5557,34 @@ static void gdth_flush(int hanum)
     int             i;
     gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Request    *srp;
+#else
+    Scsi_Cmnd       *scp;
+#endif
+    struct scsi_device     *sdev;
     char            cmnd[MAX_COMMAND_SIZE];   
     memset(cmnd, 0xff, MAX_COMMAND_SIZE);
 
     TRACE2(("gdth_flush() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+    srp  = scsi_allocate_request(sdev, GFP_KERNEL);
+    if (!srp)
+        return;
+    srp->sr_cmd_len = 12;
+    srp->sr_use_sg = 0;
+#else
+    sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+    scp  = scsi_allocate_device(sdev, 1, FALSE);
+    if (!scp)
+        return;
+    scp->cmd_len = 12;
+    scp->use_sg = 0;
+#endif
+
     for (i = 0; i < MAX_HDRIVES; ++i) {
         if (ha->hdr[i].present) {
             gdtcmd.BoardNode = LOCALBOARD;
@@ -5586,10 +5600,20 @@ static void gdth_flush(int hanum)
                 gdtcmd.u.cache.sg_canz = 0;
             }
             TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
-
-            gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 30, NULL);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            gdth_do_req(srp, &gdtcmd, cmnd, 30);
+#else
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+#endif
         }
     }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    scsi_release_request(srp);
+    scsi_free_host_dev(sdev);
+#else
+    scsi_release_command(scp);
+    scsi_free_host_dev(sdev);
+#endif
 }
 
 /* shutdown routine */
@@ -5598,17 +5622,20 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
     int             hanum;
 #ifndef __alpha__
     gdth_cmd_str    gdtcmd;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Request    *srp;
+    struct scsi_device     *sdev;
+#else
+    Scsi_Cmnd       *scp;
+    struct scsi_device     *sdev;
+#endif
     char            cmnd[MAX_COMMAND_SIZE];   
 #endif
 
-    if (notifier_disabled)
-        return NOTIFY_OK;
-
     TRACE2(("gdth_halt() event %d\n",(int)event));
     if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
         return NOTIFY_DONE;
 
-    notifier_disabled = 1;
     printk("GDT-HA: Flushing all host drives .. ");
     for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
         gdth_flush(hanum);
@@ -5620,7 +5647,31 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
         gdtcmd.Service = CACHESERVICE;
         gdtcmd.OpCode = GDT_RESET;
         TRACE2(("gdth_halt(): reset controller %d\n", hanum));
-        gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 10, NULL);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        srp  = scsi_allocate_request(sdev, GFP_KERNEL);
+        if (!srp) {
+            unregister_reboot_notifier(&gdth_notifier);
+            return NOTIFY_OK;
+        }
+        srp->sr_cmd_len = 12;
+        srp->sr_use_sg = 0;
+        gdth_do_req(srp, &gdtcmd, cmnd, 10);
+        scsi_release_request(srp);
+        scsi_free_host_dev(sdev);
+#else
+        sdev = scsi_get_host_dev(gdth_ctr_tab[hanum]);
+        scp  = scsi_allocate_device(sdev, 1, FALSE);
+        if (!scp) {
+            unregister_reboot_notifier(&gdth_notifier);
+            return NOTIFY_OK;
+        }
+        scp->cmd_len = 12;
+        scp->use_sg = 0;
+        gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
+        scsi_release_command(scp);
+        scsi_free_host_dev(sdev);
+#endif
 #endif
     }
     printk("Done.\n");
@@ -5628,25 +5679,11 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
 #ifdef GDTH_STATISTICS
     del_timer(&gdth_timer);
 #endif
+    unregister_reboot_notifier(&gdth_notifier);
     return NOTIFY_OK;
 }
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-/* configure lun */
-static int gdth_slave_configure(struct scsi_device *sdev)
-{
-    scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun);
-    sdev->skip_ms_page_3f = 1;
-    sdev->skip_ms_page_8 = 1;
-    return 0;
-}
-#endif
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
 static struct scsi_host_template driver_template = {
-#else
-static Scsi_Host_Template driver_template = {
-#endif
         .proc_name              = "gdth", 
         .proc_info              = gdth_proc_info,
         .name                   = "GDT SCSI Disk Array Controller",
@@ -5657,9 +5694,6 @@ static Scsi_Host_Template driver_template = {
         .eh_bus_reset_handler   = gdth_eh_bus_reset,
         .bios_param             = gdth_bios_param,
         .can_queue              = GDTH_MAXCMDS,
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
-        .slave_configure        = gdth_slave_configure,
-#endif
         .this_id                = -1,
         .sg_tablesize           = GDTH_MAXSG,
         .cmd_per_lun            = GDTH_MAXC_P_L,