diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS	2004-08-28 02:19:18 -07:00
+++ b/CREDITS	2004-09-27 04:21:44 -07:00
@@ -1809,10 +1809,10 @@
 S: Germany
 
 N: Achim Leubner
-E: achim@vortex.de
-D: GDT SCSI Disk Array Controller driver
-S: ICP vortex Computersysteme GmbH
-S: Flein
+E: achim_leubner@adaptec.com
+D: GDT Disk Array Controller/Storage RAID controller driver
+S: ICP vortex GmbH
+S: Neckarsulm
 S: Germany
 
 N: Phil Lewis
diff -Nru a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients
--- a/Documentation/i2c/writing-clients	2003-12-09 22:50:17 -08:00
+++ b/Documentation/i2c/writing-clients	2004-09-14 13:15:14 -07:00
@@ -24,24 +24,25 @@
 routines, a client structure specific information like the actual I2C
 address.
 
-  struct i2c_driver foo_driver
-  {  
-    /* name           */  "Foo version 2.3 and later driver",
-    /* id             */  I2C_DRIVERID_FOO,
-    /* flags          */  I2C_DF_NOTIFY,
-    /* attach_adapter */  &foo_attach_adapter,
-    /* detach_client  */  &foo_detach_client,
-    /* command        */  &foo_command,   /* May be NULL */
-    /* inc_use        */  &foo_inc_use,   /* May be NULL */
-    /* dec_use        */  &foo_dec_use    /* May be NULL */
-  }
+static struct i2c_driver foo_driver = {
+	.name		= "Foo version 2.3 driver",
+	.id		= I2C_DRIVERID_FOO, /* from i2c-id.h, optional */
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= &foo_attach_adapter,
+	.detach_client	= &foo_detach_client,
+	.command	= &foo_command, /* may be NULL */
+	.inc_use	= &foo_inc_use, /* May be NULL */
+	.dec_use	= &foo_dec_use, /* May be NULL */
+}
  
 The name can be chosen freely, and may be upto 40 characters long. Please
 use something descriptive here.
 
-The id should be a unique ID. The range 0xf000 to 0xffff is reserved for
-local use, and you can use one of those until you start distributing the
-driver. Before you do that, contact the i2c authors to get your own ID(s).
+If used, the id should be a unique ID. The range 0xf000 to 0xffff is
+reserved for local use, and you can use one of those until you start
+distributing the driver, at which time you should contact the i2c authors
+to get your own ID(s). Note that most of the time you don't need an ID
+at all so you can just omit it.
 
 Don't worry about the flags field; just put I2C_DF_NOTIFY into it. This
 means that your driver will be notified when new adapters are found.
diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS	2004-08-28 02:18:52 -07:00
+++ b/MAINTAINERS	2004-09-27 04:21:44 -07:00
@@ -766,7 +766,7 @@
 
 GDT SCSI DISK ARRAY CONTROLLER DRIVER
 P:	Achim Leubner
-M:	achim@vortex.de
+M:	achim_leubner@adaptec.com
 L:	linux-scsi@vger.kernel.org
 W:	http://www.icp-vortex.com/
 S:	Supported
diff -Nru a/Makefile b/Makefile
--- a/Makefile	2004-09-10 11:46:40 -07:00
+++ b/Makefile	2004-09-29 02:48:49 -07:00
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 4
 SUBLEVEL = 28
-EXTRAVERSION = -pre3
+EXTRAVERSION = -pre3-bk5
 
 KERNELRELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 
diff -Nru a/arch/ppc/platforms/residual.c b/arch/ppc/platforms/residual.c
--- a/arch/ppc/platforms/residual.c	2003-07-03 09:56:35 -07:00
+++ b/arch/ppc/platforms/residual.c	2004-09-12 12:32:52 -07:00
@@ -493,7 +493,7 @@
 			size=tag_small_count(pkt->S1_Pack.Tag)+1;
 			printsmallpacket(pkt, size);
 		}
-		(unsigned char *) pkt+=size;
+		pkt = (PnP_TAG_PACKET *)((unsigned char *) pkt + size);
 	} while (pkt->S1_Pack.Tag != END_TAG);
 }
 
diff -Nru a/drivers/atm/atmtcp.c b/drivers/atm/atmtcp.c
--- a/drivers/atm/atmtcp.c	2003-10-14 14:01:53 -07:00
+++ b/drivers/atm/atmtcp.c	2004-09-11 16:56:20 -07:00
@@ -246,7 +246,7 @@
 	dev_data = PRIV(atmtcp_dev);
 	dev_data->vcc = NULL;
 	if (dev_data->persist) return;
-	PRIV(atmtcp_dev) = NULL;
+	atmtcp_dev->dev_data = NULL;
 	kfree(dev_data);
 	shutdown_atm_dev(atmtcp_dev);
 	vcc->dev_data = NULL;
@@ -362,7 +362,7 @@
 	}
 	dev->ci_range.vpi_bits = MAX_VPI_BITS;
 	dev->ci_range.vci_bits = MAX_VCI_BITS;
-	PRIV(dev) = dev_data;
+	dev->dev_data = dev_data;
 	PRIV(dev)->vcc = NULL;
 	PRIV(dev)->persist = persist;
 	if (result) *result = dev;
diff -Nru a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
--- a/drivers/atm/fore200e.c	2004-08-11 12:37:48 -07:00
+++ b/drivers/atm/fore200e.c	2004-09-11 16:56:20 -07:00
@@ -1621,7 +1621,7 @@
     set_bit(ATM_VF_PARTIAL,&vcc->flags);
     set_bit(ATM_VF_ADDR, &vcc->flags);
 
-    FORE200E_VCC(vcc) = fore200e_vcc;
+    vcc->dev_data = fore200e_vcc;
 
     if (fore200e_activate_vcin(fore200e, 1, vcc, vcc->qos.rxtp.max_sdu) < 0) {
 
@@ -1630,7 +1630,7 @@
 	clear_bit(ATM_VF_ADDR, &vcc->flags);
 	clear_bit(ATM_VF_PARTIAL,&vcc->flags);
 
-	FORE200E_VCC(vcc) = NULL;
+	vcc->dev_data = NULL;
 
 	fore200e->available_cell_rate += vcc->qos.txtp.max_pcr;
 
@@ -1692,7 +1692,7 @@
     vcc->itf = vcc->vci = vcc->vpi = 0;
 
     fore200e_vcc = FORE200E_VCC(vcc);
-    FORE200E_VCC(vcc) = NULL;
+    vcc->dev_data = NULL;
 
     spin_unlock_irqrestore(&fore200e->q_lock, flags);
 
@@ -2739,7 +2739,7 @@
 	return -ENODEV;
     }
 
-    FORE200E_DEV(atm_dev) = fore200e;
+    atm_dev->dev_data = fore200e;
     fore200e->atm_dev = atm_dev;
 
     atm_dev->ci_range.vpi_bits = FORE200E_VPI_BITS;
diff -Nru a/drivers/atm/he.c b/drivers/atm/he.c
--- a/drivers/atm/he.c	2004-02-11 22:00:07 -08:00
+++ b/drivers/atm/he.c	2004-09-11 16:56:20 -07:00
@@ -378,7 +378,7 @@
 	he_dev->pci_dev = pci_dev;
 	he_dev->atm_dev = atm_dev;
 	he_dev->atm_dev->dev_data = he_dev;
-	HE_DEV(atm_dev) = he_dev;
+	atm_dev->dev_data = he_dev;
 	he_dev->number = atm_dev->number;
 	if (he_start(atm_dev)) {
 		he_stop(he_dev);
@@ -2347,7 +2347,7 @@
 	init_waitqueue_head(&he_vcc->rx_waitq);
 	init_waitqueue_head(&he_vcc->tx_waitq);
 
-	HE_VCC(vcc) = he_vcc;
+	vcc->dev_data = he_vcc;
 
 	if (vcc->qos.txtp.traffic_class != ATM_NONE) {
 		int pcr_goal;
diff -Nru a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c
--- a/drivers/atm/idt77105.c	2003-03-23 01:11:13 -08:00
+++ b/drivers/atm/idt77105.c	2004-09-11 16:56:20 -07:00
@@ -267,7 +267,7 @@
 {
 	unsigned long flags;
 
-	if (!(PRIV(dev) = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL)))
+	if (!(dev->phy_data = kmalloc(sizeof(struct idt77105_priv),GFP_KERNEL)))
 		return -ENOMEM;
 	PRIV(dev)->dev = dev;
 	spin_lock_irqsave(&idt77105_priv_lock, flags);
@@ -345,7 +345,7 @@
                 else
                     idt77105_all = walk->next;
 	        dev->phy = NULL;
-                PRIV(dev) = NULL;
+                dev->phy_data = NULL;
                 kfree(walk);
                 break;
             }
diff -Nru a/drivers/atm/iphase.c b/drivers/atm/iphase.c
--- a/drivers/atm/iphase.c	2003-06-29 08:16:52 -07:00
+++ b/drivers/atm/iphase.c	2004-09-11 16:56:20 -07:00
@@ -1782,7 +1782,7 @@
                          (iadev->tx_buf_sz - sizeof(struct cpcs_trailer))){
            printk("IA:  SDU size over (%d) the configured SDU size %d\n",
 		  vcc->qos.txtp.max_sdu,iadev->tx_buf_sz);
-	   INPH_IA_VCC(vcc) = NULL;  
+	   vcc->dev_data = NULL;  
            kfree(ia_vcc);
            return -EINVAL; 
         }
@@ -2707,7 +2707,7 @@
         }
 	kfree(INPH_IA_VCC(vcc));  
         ia_vcc = NULL;
-        INPH_IA_VCC(vcc) = NULL;  
+        vcc->dev_data = NULL;  
         clear_bit(ATM_VF_ADDR,&vcc->flags);
         return;        
 }  
@@ -2720,7 +2720,7 @@
 	if (!test_bit(ATM_VF_PARTIAL,&vcc->flags))  
 	{  
 		IF_EVENT(printk("ia: not partially allocated resources\n");)  
-		INPH_IA_VCC(vcc) = NULL;  
+		vcc->dev_data = NULL;  
 	}  
 	iadev = INPH_IA_DEV(vcc->dev);  
 	error = atm_find_ci(vcc, &vpi, &vci);  
@@ -2744,7 +2744,7 @@
 	/* Device dependent initialization */  
 	ia_vcc = kmalloc(sizeof(*ia_vcc), GFP_KERNEL);  
 	if (!ia_vcc) return -ENOMEM;  
-	INPH_IA_VCC(vcc) = ia_vcc;  
+	vcc->dev_data = ia_vcc;  
   
 	if ((error = open_rx(vcc)))  
 	{  
@@ -3256,7 +3256,7 @@
 		ret = -ENOMEM;
 		goto err_out_disable_dev;
 	}
-	INPH_IA_DEV(dev) = iadev; 
+	dev->dev_data = iadev; 
 	IF_INIT(printk(DEV_LABEL "registered at (itf :%d)\n", dev->number);)
 	IF_INIT(printk("dev_id = 0x%x iadev->LineRate = %d \n", (u32)dev,
 		iadev->LineRate);)
diff -Nru a/drivers/atm/uPD98402.c b/drivers/atm/uPD98402.c
--- a/drivers/atm/uPD98402.c	2002-02-04 23:45:13 -08:00
+++ b/drivers/atm/uPD98402.c	2004-09-11 16:56:20 -07:00
@@ -212,7 +212,7 @@
 static int uPD98402_start(struct atm_dev *dev)
 {
 	DPRINTK("phy_start\n");
-	if (!(PRIV(dev) = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL)))
+	if (!(dev->phy_data = kmalloc(sizeof(struct uPD98402_priv),GFP_KERNEL)))
 		return -ENOMEM;
 	memset(&PRIV(dev)->sonet_stats,0,sizeof(struct k_sonet_stats));
 	(void) GET(PCR); /* clear performance events */
diff -Nru a/drivers/atm/zatm.c b/drivers/atm/zatm.c
--- a/drivers/atm/zatm.c	2003-06-26 22:59:31 -07:00
+++ b/drivers/atm/zatm.c	2004-09-11 16:56:20 -07:00
@@ -1565,7 +1565,7 @@
         DPRINTK("zatm_close: done waiting\n");
         /* deallocate memory */
         kfree(ZATM_VCC(vcc));
-        ZATM_VCC(vcc) = NULL;
+	vcc->dev_data = NULL;
 	clear_bit(ATM_VF_ADDR,&vcc->flags);
 }
 
@@ -1578,7 +1578,7 @@
 
 	DPRINTK(">zatm_open\n");
 	zatm_dev = ZATM_DEV(vcc->dev);
-	if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) ZATM_VCC(vcc) = NULL;
+	if (!test_bit(ATM_VF_PARTIAL,&vcc->flags)) vcc->dev_data = NULL;
 	error = atm_find_ci(vcc,&vpi,&vci);
 	if (error) return error;
 	vcc->vpi = vpi;
@@ -1594,7 +1594,7 @@
 			clear_bit(ATM_VF_ADDR,&vcc->flags);
 			return -ENOMEM;
 		}
-		ZATM_VCC(vcc) = zatm_vcc;
+		vcc->dev_data = zatm_vcc;
 		ZATM_VCC(vcc)->tx_chan = 0; /* for zatm_close after open_rx */
 		if ((error = open_rx_first(vcc))) {
 	                zatm_close(vcc);
@@ -1828,7 +1828,7 @@
 			dev = atm_dev_register(DEV_LABEL,&ops,-1,NULL);
 			if (!dev) break;
 			zatm_dev->pci_dev = pci_dev;
-			ZATM_DEV(dev) = zatm_dev;
+			dev->dev_data = zatm_dev;
 			zatm_dev->copper = type;
 			if (zatm_init(dev) || zatm_start(dev)) {
 				atm_dev_deregister(dev);
diff -Nru a/drivers/hotplug/Makefile b/drivers/hotplug/Makefile
--- a/drivers/hotplug/Makefile	2004-03-17 14:00:30 -08:00
+++ b/drivers/hotplug/Makefile	2004-04-16 15:17:42 -07:00
@@ -20,7 +20,6 @@
 
 cpqphp-objs		:=	cpqphp_core.o	\
 				cpqphp_ctrl.o	\
-				cpqphp_proc.o	\
 				cpqphp_pci.o
 
 ibmphp-objs		:=	ibmphp_core.o	\
@@ -62,6 +61,10 @@
 
 ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y)
 	cpqphp-objs += cpqphp_nvram.o
+endif
+
+ifeq ($(CONFIG_PROC_FS),y)
+	cpqphp-objs += cpqphp_proc.o
 endif
 
 include $(TOPDIR)/Rules.make
diff -Nru a/drivers/hotplug/ibmphp_hpc.c b/drivers/hotplug/ibmphp_hpc.c
--- a/drivers/hotplug/ibmphp_hpc.c	2003-08-28 04:21:26 -07:00
+++ b/drivers/hotplug/ibmphp_hpc.c	2004-09-11 16:56:20 -07:00
@@ -184,14 +184,14 @@
 	}
 
 	wpg_data = swab32 (data);	// swap data before writing
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMOSUP_OFFSET;
+	wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
 	// READ - step 2 : clear the message buffer
 	data = 0x00000000;
 	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
+	wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
@@ -199,7 +199,7 @@
 	//                 2020 : [20] OR operation at [20] offset 0x20
 	data = WPG_I2CMCNTL_STARTOP_MASK;
 	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET + (ulong) WPG_I2C_OR;
+	wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
@@ -207,7 +207,7 @@
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
 		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET;
+		wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
 		if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
@@ -223,7 +223,7 @@
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
 		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CSTAT_OFFSET;
+		wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
 		if (HPC_I2CSTATUS_CHECK (data))
@@ -237,7 +237,7 @@
 
 	//--------------------------------------------------------------------
 	// READ - step 6 : get DATA
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
+	wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
 	wpg_data = readl (wpg_addr);
 	data = swab32 (wpg_data);
 
@@ -295,14 +295,14 @@
 	}
 
 	wpg_data = swab32 (data);	// swap data before writing
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMOSUP_OFFSET;
+	wpg_addr = WPGBbar + WPG_I2CMOSUP_OFFSET;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
 	// WRITE - step 2 : clear the message buffer
 	data = 0x00000000 | (ulong) cmd;
 	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMBUFL_OFFSET;
+	wpg_addr = WPGBbar + WPG_I2CMBUFL_OFFSET;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
@@ -310,7 +310,7 @@
 	//                 2020 : [20] OR operation at [20] offset 0x20
 	data = WPG_I2CMCNTL_STARTOP_MASK;
 	wpg_data = swab32 (data);
-	(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET + (ulong) WPG_I2C_OR;
+	wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET + WPG_I2C_OR;
 	writel (wpg_data, wpg_addr);
 
 	//--------------------------------------------------------------------
@@ -318,7 +318,7 @@
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
 		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CMCNTL_OFFSET;
+		wpg_addr = WPGBbar + WPG_I2CMCNTL_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
 		if (!(data & WPG_I2CMCNTL_STARTOP_MASK))
@@ -335,7 +335,7 @@
 	i = CMD_COMPLETE_TOUT_SEC;
 	while (i) {
 		long_delay (1 * HZ / 100);
-		(ulong) wpg_addr = (ulong) WPGBbar + (ulong) WPG_I2CSTAT_OFFSET;
+		wpg_addr = WPGBbar + WPG_I2CSTAT_OFFSET;
 		wpg_data = readl (wpg_addr);
 		data = swab32 (wpg_data);
 		if (HPC_I2CSTATUS_CHECK (data))
diff -Nru a/drivers/isdn/eicon/eicon_idi.c b/drivers/isdn/eicon/eicon_idi.c
--- a/drivers/isdn/eicon/eicon_idi.c	2002-02-05 06:07:03 -08:00
+++ b/drivers/isdn/eicon/eicon_idi.c	2004-09-11 16:56:20 -07:00
@@ -2054,7 +2054,8 @@
 				OutBuf.Len++;
 			} else {
 				*OutBuf.Next++ = 0;
-				*((__u16 *) OutBuf.Next)++ = (__u16) LineBuf.Len;
+				*(__u16 *) OutBuf.Next = (__u16) LineBuf.Len;
+				OutBuf.Next += sizeof(__u16);
 				OutBuf.Len += 3;
 			}
 			memcpy(OutBuf.Next, LineBuf.Data, LineBuf.Len);
diff -Nru a/drivers/isdn/hisax/avm_pci.c b/drivers/isdn/hisax/avm_pci.c
--- a/drivers/isdn/hisax/avm_pci.c	2002-03-31 17:34:43 -08:00
+++ b/drivers/isdn/hisax/avm_pci.c	2004-09-11 16:56:20 -07:00
@@ -291,7 +291,8 @@
 			debugl1(cs, "hdlc_empty_fifo: incoming packet too large");
 		return;
 	}
-	ptr = (u_int *) p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
+	p = bcs->hw.hdlc.rcvbuf + bcs->hw.hdlc.rcvidx;
+	ptr = (u_int *)p;
 	bcs->hw.hdlc.rcvidx += count;
 	if (cs->subtyp == AVM_FRITZ_PCI) {
 		outl(idx, cs->hw.avm.cfg_reg + 4);
@@ -352,7 +353,8 @@
 	}
 	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
 		debugl1(cs, "hdlc_fill_fifo %d/%ld", count, bcs->tx_skb->len);
-	ptr = (u_int *) p = bcs->tx_skb->data;
+	p = bcs->tx_skb->data;
+	ptr = (u_int *)p;
 	skb_pull(bcs->tx_skb, count);
 	bcs->tx_cnt -= count;
 	bcs->hw.hdlc.count += count;
diff -Nru a/drivers/isdn/hisax/hfc_pci.c b/drivers/isdn/hisax/hfc_pci.c
--- a/drivers/isdn/hisax/hfc_pci.c	2003-05-01 06:09:17 -07:00
+++ b/drivers/isdn/hisax/hfc_pci.c	2004-09-11 16:56:20 -07:00
@@ -1746,7 +1746,7 @@
 			printk(KERN_WARNING "HFC-PCI: Error allocating memory for FIFO!\n");
 			return 0;
 		}
-		(ulong) cs->hw.hfcpci.fifos =
+		cs->hw.hfcpci.fifos = (void *)
 		    (((ulong) cs->hw.hfcpci.share_start) & ~0x7FFF) + 0x8000;
 		pcibios_write_config_dword(cs->hw.hfcpci.pci_bus,
 				       cs->hw.hfcpci.pci_device_fn, 0x80,
diff -Nru a/drivers/isdn/hysdn/hysdn_proclog.c b/drivers/isdn/hysdn/hysdn_proclog.c
--- a/drivers/isdn/hysdn/hysdn_proclog.c	2004-07-30 06:29:39 -07:00
+++ b/drivers/isdn/hysdn/hysdn_proclog.c	2004-09-11 16:56:20 -07:00
@@ -235,7 +235,7 @@
 		return (0);
 
 	inf->usage_cnt--;	/* new usage count */
-	(struct log_data **) file->private_data = &inf->next;	/* next structure */
+	file->private_data = &inf->next;	/* next structure */
 	if ((len = strlen(inf->log_start)) <= count) {
 		if (copy_to_user(buf, inf->log_start, len))
 			return -EFAULT;
@@ -278,9 +278,9 @@
 		cli();
 		pd->if_used++;
 		if (pd->log_head)
-			(struct log_data **) filep->private_data = &(pd->log_tail->next);
+			filep->private_data = &(pd->log_tail->next);
 		else
-			(struct log_data **) filep->private_data = &(pd->log_head);
+			filep->private_data = &(pd->log_head);
 		restore_flags(flags);
 	} else {		/* simultaneous read/write access forbidden ! */
 		unlock_kernel();
diff -Nru a/drivers/md/raid1.c b/drivers/md/raid1.c
--- a/drivers/md/raid1.c	2004-03-28 14:13:33 -08:00
+++ b/drivers/md/raid1.c	2004-06-23 20:41:54 -07:00
@@ -325,18 +325,22 @@
 {
 	raid1_conf_t *conf = mddev_to_conf(mddev);
 	int i, disks = MD_SB_DISKS;
+	unsigned long flags;
 
 	/*
 	 * Later we do read balancing on the read side 
 	 * now we use the first available disk.
 	 */
 
+	md_spin_lock_irqsave(&conf->device_lock, flags);
 	for (i = 0; i < disks; i++) {
 		if (conf->mirrors[i].operational) {
 			*rdev = conf->mirrors[i].dev;
+			md_spin_unlock_irqrestore(&conf->device_lock, flags);
 			return (0);
 		}
 	}
+	md_spin_unlock_irqrestore(&conf->device_lock, flags);
 
 	printk (KERN_ERR "raid1_map(): huh, no more operational devices?\n");
 	return (-1);
@@ -592,6 +596,7 @@
 	int disks = MD_SB_DISKS;
 	int i, sum_bhs = 0;
 	struct mirror_info *mirror;
+	kdev_t dev;
 
 	if (!buffer_locked(bh))
 		BUG();
@@ -635,13 +640,16 @@
 		/*
 		 * read balancing logic:
 		 */
+		spin_lock_irq(&conf->device_lock);
 		mirror = conf->mirrors + raid1_read_balance(conf, bh);
+		dev = mirror->dev;
+		spin_unlock_irq(&conf->device_lock);
 
 		bh_req = &r1_bh->bh_req;
 		memcpy(bh_req, bh, sizeof(*bh));
 		bh_req->b_blocknr = bh->b_rsector;
-		bh_req->b_dev = mirror->dev;
-		bh_req->b_rdev = mirror->dev;
+		bh_req->b_dev = dev;
+		bh_req->b_rdev = dev;
 	/*	bh_req->b_rsector = bh->n_rsector; */
 		bh_req->b_end_io = raid1_end_request;
 		bh_req->b_private = r1_bh;
@@ -654,6 +662,7 @@
 	 */
 
 	bhl = raid1_alloc_bh(conf, conf->raid_disks);
+	spin_lock_irq(&conf->device_lock);
 	for (i = 0; i < disks; i++) {
 		struct buffer_head *mbh;
 		if (!conf->mirrors[i].operational) 
@@ -702,6 +711,7 @@
 		r1_bh->mirror_bh_list = mbh;
 		sum_bhs++;
 	}
+	spin_unlock_irq(&conf->device_lock);
 	if (bhl) raid1_free_bh(conf,bhl);
 	if (!sum_bhs) {
 		/* Gag - all mirrors non-operational.. */
@@ -771,6 +781,8 @@
 	mark_disk_inactive(sb->disks+mirror->number);
 	if (!mirror->write_only)
 		sb->active_disks--;
+	else
+		sb->spare_disks--;
 	sb->working_disks--;
 	sb->failed_disks++;
 	mddev->sb_dirty = 1;
@@ -787,6 +799,7 @@
 	struct mirror_info * mirrors = conf->mirrors;
 	int disks = MD_SB_DISKS;
 	int i;
+	unsigned long flags;
 
 	/* Find the drive.
 	 * If it is not operational, then we have already marked it as dead
@@ -808,7 +821,9 @@
 
 		return 1;
 	}
+	md_spin_lock_irqsave(&conf->device_lock, flags);
 	mark_disk_bad(mddev, i);
+	md_spin_unlock_irqrestore(&conf->device_lock, flags);
 	return 0;
 }
 
@@ -876,7 +891,6 @@
 	mdp_disk_t *failed_desc, *spare_desc, *added_desc;
 	mdk_rdev_t *spare_rdev, *failed_rdev;
 
-	print_raid1_conf(conf);
 
 	switch (state) {
 	case DISKOP_SPARE_ACTIVE:
@@ -887,6 +901,10 @@
 
 	md_spin_lock_irq(&conf->device_lock);
 	/*
+	 * Need the conf lock when printing out state else we get BUG()s
+	 */
+	print_raid1_conf(conf);
+	/*
 	 * find the disk ...
 	 */
 	switch (state) {
@@ -1136,12 +1154,12 @@
 		goto abort;
 	}
 abort:
+	print_raid1_conf(conf);
 	md_spin_unlock_irq(&conf->device_lock);
 	if (state == DISKOP_SPARE_ACTIVE || state == DISKOP_SPARE_INACTIVE)
 		/* should move to "END_REBUILD" when such exists */
 		raid1_shrink_buffers(conf);
 
-	print_raid1_conf(conf);
 	return err;
 }
 
@@ -1196,6 +1214,7 @@
 				
 				conf = mddev_to_conf(mddev);
 				bhl = raid1_alloc_bh(conf, conf->raid_disks); /* don't really need this many */
+				spin_lock_irq(&conf->device_lock);
 				for (i = 0; i < disks ; i++) {
 					if (!conf->mirrors[i].operational)
 						continue;
@@ -1238,6 +1257,7 @@
 
 					sum_bhs++;
 				}
+				spin_unlock_irq(&conf->device_lock);
 				md_atomic_set(&r1_bh->remaining, sum_bhs);
 				if (bhl) raid1_free_bh(conf, bhl);
 				mbh = r1_bh->mirror_bh_list;
@@ -1373,6 +1393,7 @@
 	int disk;
 	int block_nr;
 	int buffs;
+	kdev_t dev;
 
 	if (!sector_nr) {
 		/* we want enough buffers to hold twice the window of 128*/
@@ -1426,6 +1447,7 @@
 	 * could dedicate one to rebuild and others to
 	 * service read requests ..
 	 */
+	spin_lock_irq(&conf->device_lock);
 	disk = conf->last_used;
 	/* make sure disk is operational */
 	while (!conf->mirrors[disk].operational) {
@@ -1437,6 +1459,8 @@
 	conf->last_used = disk;
 	
 	mirror = conf->mirrors+conf->last_used;
+	dev = mirror->dev;
+	spin_unlock_irq(&conf->device_lock);
 	
 	r1_bh = raid1_alloc_buf (conf);
 	r1_bh->master_bh = NULL;
@@ -1453,8 +1477,8 @@
 	}
 	bh->b_size = bsize;
 	bh->b_list = BUF_LOCKED;
-	bh->b_dev = mirror->dev;
-	bh->b_rdev = mirror->dev;
+	bh->b_dev = dev;
+	bh->b_rdev = dev;
 	bh->b_state = (1<<BH_Req) | (1<<BH_Mapped) | (1<<BH_Lock);
 	if (!bh->b_page)
 		BUG();
diff -Nru a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
--- a/drivers/mtd/chips/cfi_cmdset_0001.c	2003-03-18 04:32:44 -08:00
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c	2004-09-11 16:56:20 -07:00
@@ -1201,13 +1201,17 @@
 	/* Write data */
 	for (z = 0; z < len; z += CFIDEV_BUSWIDTH) {
 		if (cfi_buswidth_is_1()) {
-			map->write8 (map, *((__u8*)buf)++, adr+z);
+			map->write8 (map, *(__u8*)buf, adr+z);
+			buf += sizeof(__u8);
 		} else if (cfi_buswidth_is_2()) {
-			map->write16 (map, *((__u16*)buf)++, adr+z);
+			map->write16 (map, *(__u16*)buf, adr+z);
+			buf += sizeof(__u16);
 		} else if (cfi_buswidth_is_4()) {
-			map->write32 (map, *((__u32*)buf)++, adr+z);
+			map->write32 (map, *(__u32*)buf, adr+z);
+			buf += sizeof(__u32);
 		} else if (cfi_buswidth_is_8()) {
-			map->write64 (map, *((__u64*)buf)++, adr+z);
+			map->write64 (map, *(__u64*)buf, adr+z);
+			buf += sizeof(__u64);
 		} else {
 			DISABLE_VPP(map);
 			ret = -EINVAL;
diff -Nru a/drivers/mtd/chips/cfi_cmdset_0020.c b/drivers/mtd/chips/cfi_cmdset_0020.c
--- a/drivers/mtd/chips/cfi_cmdset_0020.c	2003-01-24 16:25:21 -08:00
+++ b/drivers/mtd/chips/cfi_cmdset_0020.c	2004-09-11 16:56:20 -07:00
@@ -540,11 +540,14 @@
 	/* Write data */
 	for (z = 0; z < len; z += CFIDEV_BUSWIDTH) {
 		if (cfi_buswidth_is_1()) {
-			map->write8 (map, *((__u8*)buf)++, adr+z);
+			map->write8 (map, *(__u8*)buf, adr+z);
+			buf += sizeof(__u8);
 		} else if (cfi_buswidth_is_2()) {
-			map->write16 (map, *((__u16*)buf)++, adr+z);
+			map->write16 (map, *(__u16*)buf, adr+z);
+			buf += sizeof(__u16);
 		} else if (cfi_buswidth_is_4()) {
-			map->write32 (map, *((__u32*)buf)++, adr+z);
+			map->write32 (map, *(__u32*)buf, adr+z);
+			buf += sizeof(__u32);
 		} else {
 			DISABLE_VPP(map);
 			return -EINVAL;
diff -Nru a/drivers/mtd/maps/elan-104nc.c b/drivers/mtd/maps/elan-104nc.c
--- a/drivers/mtd/maps/elan-104nc.c	2002-03-21 06:20:47 -08:00
+++ b/drivers/mtd/maps/elan-104nc.c	2004-09-11 16:56:20 -07:00
@@ -147,7 +147,7 @@
 		elan_104nc_page(map, from);
 		memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen);
 		spin_unlock(&elan_104nc_spin);
-		(__u8*)to += thislen;
+		to += thislen;
 		from += thislen;
 		len -= thislen;
 	}
diff -Nru a/drivers/mtd/maps/sbc_gxx.c b/drivers/mtd/maps/sbc_gxx.c
--- a/drivers/mtd/maps/sbc_gxx.c	2003-01-24 16:25:20 -08:00
+++ b/drivers/mtd/maps/sbc_gxx.c	2004-09-11 16:56:20 -07:00
@@ -155,7 +155,7 @@
 		sbc_gxx_page(map, from);
 		memcpy_fromio(to, iomapadr + (from & WINDOW_MASK), thislen);
 		spin_unlock(&sbc_gxx_spin);
-		(__u8*)to += thislen;
+		to += thislen;
 		from += thislen;
 		len -= thislen;
 	}
diff -Nru a/drivers/net/e100/e100.h b/drivers/net/e100/e100.h
--- a/drivers/net/e100/e100.h	2004-04-09 17:30:21 -07:00
+++ b/drivers/net/e100/e100.h	2004-09-11 17:06:57 -07:00
@@ -501,7 +501,7 @@
 	u8 scb_fc_thld;	/* Flow Control threshold */
 	u8 scb_fc_xon_xoff;	/* Flow Control XON/XOFF values */
 	u8 scb_pmdr;	/* Power Mgmt. Driver Reg */
-} d101_scb_ext __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) d101_scb_ext;
 
 /* Changed for 82559 enhancement */
 typedef struct _d101m_scb_ext_t {
@@ -517,7 +517,7 @@
 	u32 scb_function_event_mask;	/* Cardbus Function Mask */
 	u32 scb_function_present_state;	/* Cardbus Function state */
 	u32 scb_force_event;	/* Cardbus Force Event */
-} d101m_scb_ext __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) d101m_scb_ext;
 
 /* Changed for 82550 enhancement */
 typedef struct _d102_scb_ext_t {
@@ -536,7 +536,7 @@
 	u32 scb_function_event_mask;	/* Cardbus Function Mask */
 	u32 scb_function_present_state;	/* Cardbus Function state */
 	u32 scb_force_event;	/* Cardbus Force Event */
-} d102_scb_ext __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) d102_scb_ext;
 
 /*
  * 82557 status control block. this will be memory mapped & will hang of the
@@ -558,7 +558,7 @@
 		d101m_scb_ext d101m_scb;	/* 82559 specific fields */
 		d102_scb_ext d102_scb;
 	} scb_ext;
-} scb_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) scb_t;
 
 /* Self test
  * This is used to dump results of the self test 
@@ -566,7 +566,7 @@
 typedef struct _self_test_t {
 	u32 st_sign;	/* Self Test Signature */
 	u32 st_result;	/* Self Test Results */
-} self_test_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) self_test_t;
 
 /* 
  *  Statistical Counters 
@@ -649,39 +649,39 @@
 	u16 cb_status;	/* Command Block Status */
 	u16 cb_cmd;	/* Command Block Command */
 	u32 cb_lnk_ptr;	/* Link To Next CB */
-} cb_header_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) cb_header_t;
 
 //* Individual Address Command Block (IA_CB)*/
 typedef struct _ia_cb_t {
 	cb_header_t ia_cb_hdr;
 	u8 ia_addr[ETH_ALEN];
-} ia_cb_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) ia_cb_t;
 
 /* Configure Command Block (CONFIG_CB)*/
 typedef struct _config_cb_t {
 	cb_header_t cfg_cbhdr;
 	u8 cfg_byte[CB_CFIG_BYTE_COUNT + CB_CFIG_D102_BYTE_COUNT];
-} config_cb_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) config_cb_t;
 
 /* MultiCast Command Block (MULTICAST_CB)*/
 typedef struct _multicast_cb_t {
 	cb_header_t mc_cbhdr;
 	u16 mc_count;	/* Number of multicast addresses */
 	u8 mc_addr[(ETH_ALEN * MAX_MULTICAST_ADDRS)];
-} mltcst_cb_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) mltcst_cb_t;
 
 #define UCODE_MAX_DWORDS	134
 /* Load Microcode Command Block (LOAD_UCODE_CB)*/
 typedef struct _load_ucode_cb_t {
 	cb_header_t load_ucode_cbhdr;
 	u32 ucode_dword[UCODE_MAX_DWORDS];
-} load_ucode_cb_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) load_ucode_cb_t;
 
 /* Load Programmable Filter Data*/
 typedef struct _filter_cb_t {
 	cb_header_t filter_cb_hdr;
 	u32 filter_data[MAX_FILTER];
-} filter_cb_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) filter_cb_t;
 
 /* NON_TRANSMIT_CB -- Generic Non-Transmit Command Block 
  */
@@ -693,7 +693,7 @@
 		mltcst_cb_t multicast;
 		filter_cb_t filter;
 	} ntcb;
-} nxmit_cb_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) nxmit_cb_t;
 
 /*Block for queuing for postponed execution of the non-transmit commands*/
 typedef struct _nxmit_cb_entry_t {
@@ -724,7 +724,7 @@
 	u32 tbd_buf_addr;	/* Physical Transmit Buffer Address */
 	u16 tbd_buf_cnt;	/* Actual Count Of Bytes */
 	u16 padd;
-} tbd_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) tbd_t;
 
 /* d102 specific fields */
 typedef struct _tcb_ipcb_t {
@@ -743,7 +743,7 @@
 		u16 tbd_zero_size;
 	} tbd_sec_size;
 	u16 total_tcp_payload;
-} tcb_ipcb_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) tcb_ipcb_t;
 
 #define E100_TBD_ARRAY_SIZE (2+MAX_SKB_FRAGS)
 
@@ -806,7 +806,7 @@
 	u32 rbd_rcb_addr;	/* Receive Buffer Address */
 	u16 rbd_sz;	/* Receive Buffer Size */
 	u16 rbd_filler1;
-} rbd_t __attribute__ ((__packed__));
+} __attribute__ ((__packed__)) rbd_t;
 
 /*
  * This structure is used to maintain a FIFO access to a resource that is 
diff -Nru a/drivers/net/tg3.c b/drivers/net/tg3.c
--- a/drivers/net/tg3.c	2004-08-30 15:36:20 -07:00
+++ b/drivers/net/tg3.c	2004-09-14 22:13:00 -07:00
@@ -59,8 +59,8 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define PFX DRV_MODULE_NAME	": "
-#define DRV_MODULE_VERSION	"3.9"
-#define DRV_MODULE_RELDATE	"August 30, 2004"
+#define DRV_MODULE_VERSION	"3.10"
+#define DRV_MODULE_RELDATE	"September 14, 2004"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -1121,29 +1121,33 @@
 	u32 old_rx_mode = tp->rx_mode;
 	u32 old_tx_mode = tp->tx_mode;
 
-	if (local_adv & ADVERTISE_PAUSE_CAP) {
-		if (local_adv & ADVERTISE_PAUSE_ASYM) {
-			if (remote_adv & LPA_PAUSE_CAP)
-				new_tg3_flags |=
-					(TG3_FLAG_RX_PAUSE |
-					 TG3_FLAG_TX_PAUSE);
-			else if (remote_adv & LPA_PAUSE_ASYM)
-				new_tg3_flags |=
-					(TG3_FLAG_RX_PAUSE);
-		} else {
-			if (remote_adv & LPA_PAUSE_CAP)
-				new_tg3_flags |=
-					(TG3_FLAG_RX_PAUSE |
-					 TG3_FLAG_TX_PAUSE);
+	if (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) {
+		if (local_adv & ADVERTISE_PAUSE_CAP) {
+			if (local_adv & ADVERTISE_PAUSE_ASYM) {
+				if (remote_adv & LPA_PAUSE_CAP)
+					new_tg3_flags |=
+						(TG3_FLAG_RX_PAUSE |
+					 	TG3_FLAG_TX_PAUSE);
+				else if (remote_adv & LPA_PAUSE_ASYM)
+					new_tg3_flags |=
+						(TG3_FLAG_RX_PAUSE);
+			} else {
+				if (remote_adv & LPA_PAUSE_CAP)
+					new_tg3_flags |=
+						(TG3_FLAG_RX_PAUSE |
+					 	TG3_FLAG_TX_PAUSE);
+			}
+		} else if (local_adv & ADVERTISE_PAUSE_ASYM) {
+			if ((remote_adv & LPA_PAUSE_CAP) &&
+		    	(remote_adv & LPA_PAUSE_ASYM))
+				new_tg3_flags |= TG3_FLAG_TX_PAUSE;
 		}
-	} else if (local_adv & ADVERTISE_PAUSE_ASYM) {
-		if ((remote_adv & LPA_PAUSE_CAP) &&
-		    (remote_adv & LPA_PAUSE_ASYM))
-			new_tg3_flags |= TG3_FLAG_TX_PAUSE;
-	}
 
-	tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
-	tp->tg3_flags |= new_tg3_flags;
+		tp->tg3_flags &= ~(TG3_FLAG_RX_PAUSE | TG3_FLAG_TX_PAUSE);
+		tp->tg3_flags |= new_tg3_flags;
+	} else {
+		new_tg3_flags = tp->tg3_flags;
+	}
 
 	if (new_tg3_flags & TG3_FLAG_RX_PAUSE)
 		tp->rx_mode |= RX_MODE_FLOW_CTRL_ENABLE;
@@ -2167,7 +2171,7 @@
 					else
 						val |= 0x4010880;
 
-					tw32_f(MAC_SERDES_CFG, serdes_cfg);
+					tw32_f(MAC_SERDES_CFG, val);
 				}
 
 				tw32_f(SG_DIG_CTRL, 0x01388400);
@@ -2954,6 +2958,7 @@
 			dma_addr_t mapping, int len, u32 flags,
 			u32 mss_and_is_end)
 {
+	struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
 	int is_end = (mss_and_is_end & 0x1);
 	u32 mss = (mss_and_is_end >> 1);
 	u32 vlan_tag = 0;
@@ -2965,35 +2970,11 @@
 		flags &= 0xffff;
 	}
 	vlan_tag |= (mss << TXD_MSS_SHIFT);
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		struct tg3_tx_buffer_desc *txd = &tp->tx_ring[entry];
-
-		txd->addr_hi = ((u64) mapping >> 32);
-		txd->addr_lo = ((u64) mapping & 0xffffffff);
-		txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
-		txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
-	} else {
-		struct tx_ring_info *txr = &tp->tx_buffers[entry];
-		unsigned long txd;
 
-		txd = (tp->regs +
-		       NIC_SRAM_WIN_BASE +
-		       NIC_SRAM_TX_BUFFER_DESC);
-		txd += (entry * TXD_SIZE);
-
-		/* Save some PIOs */
-		if (sizeof(dma_addr_t) != sizeof(u32))
-			writel(((u64) mapping >> 32),
-			       txd + TXD_ADDR + TG3_64BIT_REG_HIGH);
-
-		writel(((u64) mapping & 0xffffffff),
-		       txd + TXD_ADDR + TG3_64BIT_REG_LOW);
-		writel(len << TXD_LEN_SHIFT | flags, txd + TXD_LEN_FLAGS);
-		if (txr->prev_vlan_tag != vlan_tag) {
-			writel(vlan_tag << TXD_VLAN_TAG_SHIFT, txd + TXD_VLAN_TAG);
-			txr->prev_vlan_tag = vlan_tag;
-		}
-	}
+	txd->addr_hi = ((u64) mapping >> 32);
+	txd->addr_lo = ((u64) mapping & 0xffffffff);
+	txd->len_flags = (len << TXD_LEN_SHIFT) | flags;
+	txd->vlan_tag = vlan_tag << TXD_VLAN_TAG_SHIFT;
 }
 
 static inline int tg3_4g_overflow_test(dma_addr_t mapping, int len)
@@ -3182,19 +3163,7 @@
 	}
 
 	/* Packets are ready, update Tx producer idx local and on card. */
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 +
-			      TG3_64BIT_REG_LOW), entry);
-	} else {
-		/* First, make sure tg3 sees last descriptor fully
-		 * in SRAM.
-		 */
-		if (tp->tg3_flags & TG3_FLAG_MBOX_WRITE_REORDER)
-			tr32(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW);
-
-		tw32_tx_mbox((MAILBOX_SNDNIC_PROD_IDX_0 +
-			      TG3_64BIT_REG_LOW), entry);
-	}
+	tw32_tx_mbox((MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW), entry);
 
 	tp->tx_prod = entry;
 	if (TX_BUFFS_AVAIL(tp) <= (MAX_SKB_FRAGS + 1))
@@ -3333,7 +3302,6 @@
  */
 static void tg3_init_rings(struct tg3 *tp)
 {
-	unsigned long start, end;
 	u32 i;
 
 	/* Free up all the SKBs. */
@@ -3343,21 +3311,7 @@
 	memset(tp->rx_std, 0, TG3_RX_RING_BYTES);
 	memset(tp->rx_jumbo, 0, TG3_RX_JUMBO_RING_BYTES);
 	memset(tp->rx_rcb, 0, TG3_RX_RCB_RING_BYTES(tp));
-
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
-	} else {
-		start = (tp->regs +
-			 NIC_SRAM_WIN_BASE +
-			 NIC_SRAM_TX_BUFFER_DESC);
-		end = start + TG3_TX_RING_BYTES;
-		while (start < end) {
-			writel(0, start);
-			start += 4;
-		}
-		for (i = 0; i < TG3_TX_RING_SIZE; i++)
-			tp->tx_buffers[i].prev_vlan_tag = 0;
-	}
+	memset(tp->tx_ring, 0, TG3_TX_RING_BYTES);
 
 	/* Initialize invariants of the rings, we only set this
 	 * stuff once.  This works because the card does not
@@ -3488,15 +3442,10 @@
 	if (!tp->rx_rcb)
 		goto err_out;
 
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
-						   &tp->tx_desc_mapping);
-		if (!tp->tx_ring)
-			goto err_out;
-	} else {
-		tp->tx_ring = NULL;
-		tp->tx_desc_mapping = 0;
-	}
+	tp->tx_ring = pci_alloc_consistent(tp->pdev, TG3_TX_RING_BYTES,
+					   &tp->tx_desc_mapping);
+	if (!tp->tx_ring)
+		goto err_out;
 
 	tp->hw_status = pci_alloc_consistent(tp->pdev,
 					     TG3_HW_STATUS_SIZE,
@@ -3747,7 +3696,7 @@
 	u32 flags_save;
 	int i;
 
-	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_5704))
+	if (!(tp->tg3_flags2 & TG3_FLG2_SUN_570X))
 		tg3_nvram_lock(tp);
 
 	/*
@@ -3878,7 +3827,7 @@
 		udelay(10);
 	}
 	if (i >= 100000 &&
-	    !(tp->tg3_flags2 & TG3_FLG2_SUN_5704)) {
+	    !(tp->tg3_flags2 & TG3_FLG2_SUN_570X)) {
 		printk(KERN_ERR PFX "tg3_reset_hw timed out for %s, "
 		       "firmware will not restart magic=%08x\n",
 		       tp->dev->name, val);
@@ -4960,10 +4909,7 @@
 			  GRC_MODE_4X_NIC_SEND_RINGS |
 			  GRC_MODE_NO_TX_PHDR_CSUM |
 			  GRC_MODE_NO_RX_PHDR_CSUM);
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS)
-		tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
-	else
-		tp->grc_mode |= GRC_MODE_4X_NIC_SEND_RINGS;
+	tp->grc_mode |= GRC_MODE_HOST_SENDBDS;
 	if (tp->tg3_flags & TG3_FLAG_NO_TX_PSEUDO_CSUM)
 		tp->grc_mode |= GRC_MODE_NO_TX_PHDR_CSUM;
 	if (tp->tg3_flags & TG3_FLAG_NO_RX_PSEUDO_CSUM)
@@ -5116,18 +5062,11 @@
 	tw32_mailbox(MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
 	tw32_tx_mbox(MAILBOX_SNDNIC_PROD_IDX_0 + TG3_64BIT_REG_LOW, 0);
 
-	if (tp->tg3_flags & TG3_FLAG_HOST_TXDS) {
-		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
-			       tp->tx_desc_mapping,
-			       (TG3_TX_RING_SIZE <<
-				BDINFO_FLAGS_MAXLEN_SHIFT),
-			       NIC_SRAM_TX_BUFFER_DESC);
-	} else {
-		tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
-			       0,
-			       BDINFO_FLAGS_DISABLED,
-			       NIC_SRAM_TX_BUFFER_DESC);
-	}
+	tg3_set_bdinfo(tp, NIC_SRAM_SEND_RCB,
+		       tp->tx_desc_mapping,
+		       (TG3_TX_RING_SIZE <<
+			BDINFO_FLAGS_MAXLEN_SHIFT),
+		       NIC_SRAM_TX_BUFFER_DESC);
 
 	/* There is only one receive return ring on 5705/5750, no need
 	 * to explicitly disable the others.
@@ -5673,8 +5612,8 @@
 	spin_unlock(&tp->tx_lock);
 	spin_unlock_irq(&tp->lock);
 
-	/* If you move this call, make sure TG3_FLAG_HOST_TXDS in
-	 * tp->tg3_flags is accurate at that new place.
+	/* The placement of this call is tied
+	 * to the setup and use of Host TX descriptors.
 	 */
 	err = tg3_alloc_consistent(tp);
 	if (err)
@@ -6642,8 +6581,8 @@
 	struct tg3 *tp = netdev_priv(dev);
   
 	epause->autoneg = (tp->tg3_flags & TG3_FLAG_PAUSE_AUTONEG) != 0;
-	epause->rx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_RX) != 0;
-	epause->tx_pause = (tp->tg3_flags & TG3_FLAG_PAUSE_TX) != 0;
+	epause->rx_pause = (tp->tg3_flags & TG3_FLAG_RX_PAUSE) != 0;
+	epause->tx_pause = (tp->tg3_flags & TG3_FLAG_TX_PAUSE) != 0;
 }
   
 static int tg3_set_pauseparam(struct net_device *dev, struct ethtool_pauseparam *epause)
@@ -6658,13 +6597,13 @@
 	else
 		tp->tg3_flags &= ~TG3_FLAG_PAUSE_AUTONEG;
 	if (epause->rx_pause)
-		tp->tg3_flags |= TG3_FLAG_PAUSE_RX;
+		tp->tg3_flags |= TG3_FLAG_RX_PAUSE;
 	else
-		tp->tg3_flags &= ~TG3_FLAG_PAUSE_RX;
+		tp->tg3_flags &= ~TG3_FLAG_RX_PAUSE;
 	if (epause->tx_pause)
-		tp->tg3_flags |= TG3_FLAG_PAUSE_TX;
+		tp->tg3_flags |= TG3_FLAG_TX_PAUSE;
 	else
-		tp->tg3_flags &= ~TG3_FLAG_PAUSE_TX;
+		tp->tg3_flags &= ~TG3_FLAG_TX_PAUSE;
 	tg3_halt(tp);
 	tg3_init_hw(tp);
 	tg3_netif_start(tp);
@@ -6856,7 +6795,7 @@
 {
 	int j;
 
-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704)
+	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X)
 		return;
 
 	tw32_f(GRC_EEPROM_ADDR,
@@ -6943,8 +6882,8 @@
 {
 	int i;
 
-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) {
-		printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 5704\n");
+	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
+		printk(KERN_ERR PFX "Attempt to do nvram_read on Sun 570X\n");
 		return -EINVAL;
 	}
 
@@ -7279,11 +7218,11 @@
 	unsigned char vpd_data[256];
 	int i;
 
-	if (tp->tg3_flags2 & TG3_FLG2_SUN_5704) {
+	if (tp->tg3_flags2 & TG3_FLG2_SUN_570X) {
 		/* Sun decided not to put the necessary bits in the
 		 * NVRAM of their onboard tg3 parts :(
 		 */
-		strcpy(tp->board_part_number, "Sun 5704");
+		strcpy(tp->board_part_number, "Sun 570X");
 		return;
 	}
 
@@ -7344,27 +7283,21 @@
 }
 
 #ifdef CONFIG_SPARC64
-static int __devinit tg3_is_sun_5704(struct tg3 *tp)
+static int __devinit tg3_is_sun_570X(struct tg3 *tp)
 {
 	struct pci_dev *pdev = tp->pdev;
 	struct pcidev_cookie *pcp = pdev->sysdata;
 
 	if (pcp != NULL) {
 		int node = pcp->prom_node;
-		u32 venid, devid;
+		u32 venid;
 		int err;
 
 		err = prom_getproperty(node, "subsystem-vendor-id",
 				       (char *) &venid, sizeof(venid));
 		if (err == 0 || err == -1)
 			return 0;
-		err = prom_getproperty(node, "subsystem-id",
-				       (char *) &devid, sizeof(devid));
-		if (err == 0 || err == -1)
-			return 0;
-
-		if (venid == PCI_VENDOR_ID_SUN &&
-		    devid == PCI_DEVICE_ID_TIGON3_5704)
+		if (venid == PCI_VENDOR_ID_SUN)
 			return 1;
 	}
 	return 0;
@@ -7381,8 +7314,8 @@
 	int err;
 
 #ifdef CONFIG_SPARC64
-	if (tg3_is_sun_5704(tp))
-		tp->tg3_flags2 |= TG3_FLG2_SUN_5704;
+	if (tg3_is_sun_570X(tp))
+		tp->tg3_flags2 |= TG3_FLG2_SUN_570X;
 #endif
 
 	/* If we have an AMD 762 or Intel ICH/ICH0/ICH2 chipset, write
@@ -7627,23 +7560,6 @@
 	udelay(50);
 	tg3_nvram_init(tp);
 
-	/* Always use host TXDs, it performs better in particular
-	 * with multi-frag packets.  The tests below are kept here
-	 * as documentation should we change this decision again
-	 * in the future.
-	 */
-	tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
-
-#if 0
-	/* Determine if TX descriptors will reside in
-	 * main memory or in the chip SRAM.
-	 */
-	if ((tp->tg3_flags & TG3_FLAG_PCIX_TARGET_HWBUG) != 0 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)
-		tp->tg3_flags |= TG3_FLAG_HOST_TXDS;
-#endif
-
 	grc_misc_cfg = tr32(GRC_MISC_CFG);
 	grc_misc_cfg &= GRC_MISC_CFG_BOARD_ID_MASK;
 
@@ -7781,7 +7697,7 @@
 
 	mac_offset = 0x7c;
 	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 &&
-	    !(tp->tg3_flags & TG3_FLG2_SUN_5704)) {
+	    !(tp->tg3_flags & TG3_FLG2_SUN_570X)) {
 		if (tr32(TG3PCI_DUAL_MAC_CTRL) & DUAL_MAC_CTRL_ID)
 			mac_offset = 0xcc;
 		if (tg3_nvram_lock(tp))
@@ -7803,7 +7719,7 @@
 		dev->dev_addr[5] = (lo >>  0) & 0xff;
 	}
 	/* Next, try NVRAM. */
-	else if (!(tp->tg3_flags & TG3_FLG2_SUN_5704) &&
+	else if (!(tp->tg3_flags & TG3_FLG2_SUN_570X) &&
 		 !tg3_nvram_read(tp, mac_offset + 0, &hi) &&
 		 !tg3_nvram_read(tp, mac_offset + 4, &lo)) {
 		dev->dev_addr[0] = ((hi >> 16) & 0xff);
@@ -8408,6 +8324,9 @@
 	if (tp->tg3_flags2 & TG3_FLG2_IS_5788)
 		dev->features &= ~NETIF_F_HIGHDMA;
 
+	/* flow control autonegotiation is default behavior */
+	tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
+
 	err = register_netdev(dev);
 	if (err) {
 		printk(KERN_ERR PFX "Cannot register net device, "
@@ -8439,11 +8358,10 @@
 		printk("%2.2x%c", dev->dev_addr[i],
 		       i == 5 ? '\n' : ':');
 
-	printk(KERN_INFO "%s: HostTXDS[%d] RXcsums[%d] LinkChgREG[%d] "
+	printk(KERN_INFO "%s: RXcsums[%d] LinkChgREG[%d] "
 	       "MIirq[%d] ASF[%d] Split[%d] WireSpeed[%d] "
 	       "TSOcap[%d] \n",
 	       dev->name,
-	       (tp->tg3_flags & TG3_FLAG_HOST_TXDS) != 0,
 	       (tp->tg3_flags & TG3_FLAG_RX_CHECKSUMS) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_LINKCHG_REG) != 0,
 	       (tp->tg3_flags & TG3_FLAG_USE_MI_INTERRUPT) != 0,
diff -Nru a/drivers/net/tg3.h b/drivers/net/tg3.h
--- a/drivers/net/tg3.h	2004-08-30 15:25:29 -07:00
+++ b/drivers/net/tg3.h	2004-09-14 22:12:15 -07:00
@@ -1549,7 +1549,7 @@
  * exist only in the cards on-chip SRAM.  All 16 send bds are under
  * the same mode, they may not be configured individually.
  *
- * The mode we use is controlled by TG3_FLAG_HOST_TXDS in tp->tg3_flags.
+ * This driver always uses host memory TX descriptors.
  *
  * To use host memory TX descriptors:
  *	1) Set GRC_MODE_HOST_SENDBDS in GRC_MODE register.
@@ -2005,7 +2005,6 @@
 
 	spinlock_t			tx_lock;
 
-	/* TX descs are only used if TG3_FLAG_HOST_TXDS is set. */
 	struct tg3_tx_buffer_desc	*tx_ring;
 	struct tx_ring_info		*tx_buffers;
 	dma_addr_t			tx_desc_mapping;
@@ -2041,7 +2040,6 @@
 
 	u32				rx_offset;
 	u32				tg3_flags;
-#define TG3_FLAG_HOST_TXDS		0x00000001
 #define TG3_FLAG_TXD_MBOX_HWBUG		0x00000002
 #define TG3_FLAG_RX_CHECKSUMS		0x00000004
 #define TG3_FLAG_USE_LINKCHG_REG	0x00000008
@@ -2071,15 +2069,13 @@
 #define TG3_FLAG_JUMBO_ENABLE		0x00800000
 #define TG3_FLAG_10_100_ONLY		0x01000000
 #define TG3_FLAG_PAUSE_AUTONEG		0x02000000
-#define TG3_FLAG_PAUSE_RX		0x04000000
-#define TG3_FLAG_PAUSE_TX		0x08000000
 #define TG3_FLAG_BROKEN_CHECKSUMS	0x10000000
 #define TG3_FLAG_GOT_SERDES_FLOWCTL	0x20000000
 #define TG3_FLAG_SPLIT_MODE		0x40000000
 #define TG3_FLAG_INIT_COMPLETE		0x80000000
 	u32				tg3_flags2;
 #define TG3_FLG2_RESTART_TIMER		0x00000001
-#define TG3_FLG2_SUN_5704		0x00000002
+#define TG3_FLG2_SUN_570X		0x00000002
 #define TG3_FLG2_NO_ETH_WIRE_SPEED	0x00000004
 #define TG3_FLG2_IS_5788		0x00000008
 #define TG3_FLG2_MAX_RXPEND_64		0x00000010
diff -Nru a/drivers/scsi/53c700.h b/drivers/scsi/53c700.h
--- a/drivers/scsi/53c700.h	2002-02-05 06:10:17 -08:00
+++ b/drivers/scsi/53c700.h	2004-09-11 17:09:09 -07:00
@@ -109,8 +109,11 @@
 static inline void
 NCR_700_set_SXFER(Scsi_Device *SDp, __u8 sxfer)
 {
-	((unsigned long)SDp->hostdata) &= 0xffffff00;
-	((unsigned long)SDp->hostdata) |= sxfer & 0xff;
+	long l = (long)SDp->hostdata;
+
+	l &= 0xffffff00;
+	l |= sxfer & 0xff;
+	SDp->hostdata = (void *)l;
 }
 static inline __u8 NCR_700_get_SXFER(Scsi_Device *SDp)
 {
@@ -119,8 +122,11 @@
 static inline void
 NCR_700_set_depth(Scsi_Device *SDp, __u8 depth)
 {
-	((unsigned long)SDp->hostdata) &= 0xffff00ff;
-	((unsigned long)SDp->hostdata) |= (0xff00 & (depth << 8));
+	long l = (long)SDp->hostdata;
+
+	l &= 0xffff00ff;
+	l |= 0xff00 & (depth << 8);
+	SDp->hostdata = (void *)l;
 }
 static inline __u8
 NCR_700_get_depth(Scsi_Device *SDp)
@@ -140,12 +146,12 @@
 static inline void
 NCR_700_set_flag(Scsi_Device *SDp, __u32 flag)
 {
-	((unsigned long)SDp->hostdata) |= (flag & 0xffff0000);
+	SDp->hostdata = (void *)((long)SDp->hostdata | (flag & 0xffff0000));
 }
 static inline void
 NCR_700_clear_flag(Scsi_Device *SDp, __u32 flag)
 {
-	((unsigned long)SDp->hostdata) &= ~(flag & 0xffff0000);
+	SDp->hostdata = (void *)((long)SDp->hostdata & ~(flag & 0xffff0000));
 }
 
 /* These represent the Nexus hashing functions.  A Nexus in SCSI terms
diff -Nru a/drivers/scsi/ata_piix.c b/drivers/scsi/ata_piix.c
--- a/drivers/scsi/ata_piix.c	2004-08-30 11:43:40 -07:00
+++ b/drivers/scsi/ata_piix.c	2004-09-13 19:35:23 -07:00
@@ -106,7 +106,7 @@
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
-	.ioctl                  = ata_scsi_ioctl,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -126,15 +126,15 @@
 	.set_piomode		= piix_set_piomode,
 	.set_dmamode		= piix_set_dmamode,
 
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
 
 	.phy_reset		= piix_pata_phy_reset,
 
-	.bmdma_setup		= ata_bmdma_setup_pio,
-	.bmdma_start		= ata_bmdma_start_pio,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 
@@ -150,15 +150,15 @@
 static struct ata_port_operations piix_sata_ops = {
 	.port_disable		= ata_port_disable,
 
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
 
 	.phy_reset		= piix_sata_phy_reset,
 
-	.bmdma_setup		= ata_bmdma_setup_pio,
-	.bmdma_start		= ata_bmdma_start_pio,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 
diff -Nru a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c
--- a/drivers/scsi/gdth.c	2003-06-29 08:10:05 -07:00
+++ b/drivers/scsi/gdth.c	2004-09-27 04:36:40 -07:00
@@ -4,11 +4,14 @@
  * Intel Corporation:  Storage RAID Controllers                         *
  *                                                                      *
  * gdth.c                                                               *
- * Copyright (C) 1995-02 ICP vortex, an Intel company,  Achim Leubner   *
- * <achim.leubner@intel.com>                                            *
+ * Copyright (C) 1995-04 ICP vortex GmbH, Achim Leubner                 *
+ * Copyright (C) 2002-03 Intel Corporation                              *
+ * Copyright (C) 2003-04 Adaptec Inc.                                   *
+ * <achim_leubner@adaptec.com>                                          *
  *                                                                      *
- * Additions/Fixes: Boji Tony Kannanthanam                              *
- * <boji.t.kannanthanam@intel.com>                                      *
+ * Additions/Fixes:                                                     *
+ * Boji Tony Kannanthanam <boji.t.kannanthanam@intel.com>               *
+ * Johannes Dinner <johannes_dinner@adaptec.com>                        *
  *                                                                      *
  * This program is free software; you can redistribute it and/or modify *
  * it under the terms of the GNU General Public License as published    *
@@ -24,11 +27,57 @@
  * along with this kernel; if not, write to the Free Software           *
  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.            *
  *                                                                      *
- * Tested with Linux 1.2.13, ..., 2.2.20, ..., 2.4.18                   *
+ * Linux kernel 2.2.x, 2.4.x, 2.6.x supported                           *
  *                                                                      *
  * $Log: gdth.c,v $
- * Revision 1.61  2002/10/03 09:35:22  boji
- * Fixed SCREENSERVICE intialisation in SMP cases.
+ * Revision 1.73  2004/03/31 13:33:03  achim
+ * Special command 0xfd implemented to detect 64-bit DMA support
+ *
+ * Revision 1.72  2004/03/17 08:56:04  achim
+ * 64-bit DMA only enabled if FW >= x.43
+ *
+ * Revision 1.71  2004/03/05 15:51:29  achim
+ * Screen service: separate message buffer, bugfixes
+ *
+ * Revision 1.70  2004/02/27 12:19:07  achim
+ * Bugfix: Reset bit in config (0xfe) call removed
+ *
+ * Revision 1.69  2004/02/20 09:50:24  achim
+ * Compatibility changes for kernels < 2.4.20
+ * Bugfix screen service command size
+ * pci_set_dma_mask() error handling added
+ *
+ * Revision 1.68  2004/02/19 15:46:54  achim
+ * 64-bit DMA bugfixes
+ * Drive size bugfix for drives > 1TB
+ *
+ * Revision 1.67  2004/01/14 13:11:57  achim
+ * Tool access over /proc no longer supported
+ * Bugfixes IOCTLs
+ *
+ * Revision 1.66  2003/12/19 15:04:06  achim
+ * Bugfixes support for drives > 2TB
+ *
+ * Revision 1.65  2003/12/15 11:21:56  achim
+ * 64-bit DMA support added
+ * Support for drives > 2 TB implemented
+ * Kernels 2.2.x, 2.4.x, 2.6.x supported
+ *
+ * Revision 1.64  2003/09/17 08:30:26  achim
+ * EISA/ISA controller scan disabled
+ * Command line switch probe_eisa_isa added
+ *
+ * Revision 1.63  2003/07/12 14:01:00  Daniele Bellucci <bellucda@tiscali.it>
+ * Minor cleanups in gdth_ioctl.
+ *
+ * Revision 1.62  2003/02/27 15:01:59  achim
+ * Dynamic DMA mapping implemented
+ * New (character device) IOCTL interface added
+ * Other controller related changes made
+ *
+ * Revision 1.61  2002/11/08 13:09:52  boji
+ * Added support for XSCALE based RAID Controllers
+ * Fixed SCREENSERVICE initialization in SMP cases
  * Added checks for gdth_polling before GDTH_HA_LOCK
  *
  * Revision 1.60  2002/02/05 09:35:22  achim
@@ -216,7 +265,7 @@
  *
  * Revision 1.9  1997/09/04 10:07:25  achim
  * IO-mapping with virt_to_bus(), gdth_readb(), gdth_writeb(), ...
- * register_reboot_notifier() to get a notify on shutdown used
+ * register_reboot_notifier() to get a notify on shutown used
  *
  * Revision 1.8  1997/04/02 12:14:30  achim
  * Version 1.00 (see gdth.h), tested with kernel 2.0.29
@@ -248,7 +297,6 @@
  * Initial revision
  *
  ************************************************************************/
-#ident "$Id: gdth.c,v 1.60 2002/02/05 09:35:22 achim Exp $" 
 
 /* All GDT Disk Array Controllers are fully supported by this driver.
  * This includes the PCI/EISA/ISA SCSI Disk Array Controllers and the
@@ -282,10 +330,14 @@
  *                              access a shared resource from several nodes, 
  *                              appropiate controller firmware required
  * shared_access:N              enable driver reserve/release protocol
+ * probe_eisa_isa:Y             scan for EISA/ISA controllers
+ * probe_eisa_isa:N             do not scan for EISA/ISA controllers
+ * force_dma32:Y                use only 32 bit DMA mode
+ * force_dma32:N                use 64 bit DMA mode, if supported
  *
  * The default values are: "gdth=disable:N,reserve_mode:1,reverse_scan:N,
  *                          max_ids:127,rescan:N,virt_ctr:N,hdr_channel:0,
- *                          shared_access:Y".
+ *                          shared_access:Y,probe_eisa_isa:N,force_dma32:N".
  * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y".
  * 
  * When loading the gdth driver as a module, the same options are available. 
@@ -295,22 +347,31 @@
  * '1' in place of 'Y' and '0' in place of 'N'.
  * 
  * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0
- *           max_ids=127 rescan=0 virt_ctr=0 hdr_channel=0 shared_access=0"
+ *           max_ids=127 rescan=0 virt_ctr=0 hdr_channel=0 shared_access=0 
+ *           probe_eisa_isa=0 force_dma32=0"
  * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1".
  */
 
 /* The meaning of the Scsi_Pointer members in this driver is as follows:
- * ptr:                         Chaining
- * this_residual:               Command priority
- * buffer:                      Unused
- * buffers_residual:            Timeout value
- * Status:                      Command status (gdth_do_cmd())
- * Message:                     Additional info (gdth_do_cmd())
- * have_data_in:                Flag for gdth_wait_completion()
- * sent_command:                Opcode special command
- * phase:                       Service/parameter/return code special command
+ * ptr:                     Chaining
+ * this_residual:           Command priority
+ * buffer:                  phys. DMA sense buffer 
+ * dma_handle:              phys. DMA buffer (kernel >= 2.4.0)
+ * buffers_residual:        Timeout value
+ * Status:                  Command status (gdth_do_cmd()), DMA mem. mappings
+ * Message:                 Additional info (gdth_do_cmd()), DMA direction
+ * have_data_in:            Flag for gdth_wait_completion()
+ * sent_command:            Opcode special command
+ * phase:                   Service/parameter/return code special command
  */
 
+
+/* interrupt coalescing */
+/* #define INT_COAL */
+
+/* statistics */
+#define GDTH_STATISTICS
+
 #include <linux/module.h>
 
 #include <linux/version.h>
@@ -322,6 +383,7 @@
 #include <linux/ioport.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
+#include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/proc_fs.h>
 #include <linux/time.h>
@@ -329,38 +391,34 @@
 #ifdef GDTH_RTC
 #include <linux/mc146818rtc.h>
 #endif
-#if LINUX_VERSION_CODE >= 0x020100
 #include <linux/reboot.h>
-#else
-#include <linux/bios32.h>
-#endif
 
 #include <asm/dma.h>
 #include <asm/system.h>
 #include <asm/io.h>
-#if LINUX_VERSION_CODE >= 0x020322
+#include <asm/uaccess.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 #include <linux/spinlock.h>
-#elif LINUX_VERSION_CODE >= 0x02015F
+#else
 #include <asm/spinlock.h>
 #endif
-
-#if LINUX_VERSION_CODE >= 0x010300
-#include <linux/blk.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#include <linux/blkdev.h>
 #else
-#include "../block/blk.h"
+#include <linux/blk.h>
+#include "sd.h"
 #endif
+
 #include "scsi.h"
 #include "hosts.h"
-#include "sd.h"
-
 #include "gdth.h"
 
 static void gdth_delay(int milliseconds);
-static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs);
-#if LINUX_VERSION_CODE >= 0x010346
-static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs);
+static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static irqreturn_t gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 #else
-static void gdth_interrupt(int irq,struct pt_regs *regs);
+static void gdth_interrupt(int irq, void *dev_id, struct pt_regs *regs);
 #endif
 static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp);
 static int gdth_async_event(int hanum);
@@ -377,7 +435,8 @@
                                gdth_evt_str *estr);
 static void gdth_clear_events(void);
 
-static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count);
+static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
+                                    char *buffer,ushort count);
 static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp);
 static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive);
 
@@ -398,24 +457,19 @@
 static void gdth_release_event(int hanum);
 static int gdth_wait(int hanum,int index,ulong32 time);
 static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
-                             ulong32 p2,ulong32 p3);
+                             ulong64 p2,ulong64 p3);
 static int gdth_search_drives(int hanum);
 static int gdth_analyse_hdrive(int hanum, ushort hdrive);
 
-static void *gdth_mmap(ulong paddr, ulong size);
-static void gdth_munmap(void *addr);
-
 static const char *gdth_ctr_name(int hanum);
 
-#if LINUX_VERSION_CODE >= 0x010300
+static int gdth_open(struct inode *inode, struct file *filep);
+static int gdth_close(struct inode *inode, struct file *filep);
+static int gdth_ioctl(struct inode *inode, struct file *filep,
+                      unsigned int cmd, unsigned long arg);
+
 static void gdth_flush(int hanum);
-#if LINUX_VERSION_CODE >= 0x020100
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf);
-#else
-static int halt_called = FALSE;
-void gdth_halt(void);
-#endif
-#endif
 
 #ifdef DEBUG_GDTH
 static unchar   DebugState = DEBUG_GDTH;
@@ -500,6 +554,9 @@
 
 #ifdef GDTH_STATISTICS
 static ulong32 max_rq=0, max_index=0, max_sg=0;
+#ifdef INT_COAL
+static ulong32 max_int_coal=0;
+#endif
 static ulong32 act_ints=0, act_ios=0, act_stats=0, act_rq=0;
 static struct timer_list gdth_timer;
 #endif
@@ -514,56 +571,6 @@
 
 #define BUS_L2P(a,b)    ((b)>(a)->virt_bus ? (b-1):(b))
 
-#if LINUX_VERSION_CODE < 0x010300
-static void *gdth_mmap(ulong paddr, ulong size) 
-{
-    if (paddr >= high_memory)
-        return NULL; 
-    else
-        return (void *)paddr;
-}
-static void gdth_munmap(void *addr) 
-{
-}
-inline ulong32 virt_to_phys(volatile void *addr)
-{
-    return (ulong32)addr;
-}
-inline void *phys_to_virt(ulong32 addr)
-{
-    return (void *)addr;
-}
-#define virt_to_bus             virt_to_phys
-#define bus_to_virt             phys_to_virt
-#define gdth_readb(addr)        (*(volatile unchar *)(addr))
-#define gdth_readw(addr)        (*(volatile ushort *)(addr))
-#define gdth_readl(addr)        (*(volatile ulong32 *)(addr))
-#define gdth_writeb(b,addr)     (*(volatile unchar *)(addr) = (b))
-#define gdth_writew(b,addr)     (*(volatile ushort *)(addr) = (b))
-#define gdth_writel(b,addr)     (*(volatile ulong32 *)(addr) = (b))
-#define memset_io(a,b,c)        memset((void *)(a),(b),(c))
-#define memcpy_fromio(a,b,c)    memcpy((a),(void *)(b),(c))
-#define memcpy_toio(a,b,c)      memcpy((void *)(a),(b),(c))
-
-#define PCI_SLOT(devfn)         ((devfn >> 3) & 0x1f)
-
-#elif LINUX_VERSION_CODE < 0x020100
-static int remapped = FALSE;
-static void *gdth_mmap(ulong paddr, ulong size) 
-{
-    if ( paddr >= high_memory) {
-        remapped = TRUE;
-        return vremap(paddr, size);
-    } else {
-        return (void *)paddr; 
-    }
-}
-static void gdth_munmap(void *addr) 
-{
-    if (remapped)
-        vfree(addr);
-    remapped = FALSE;
-}
 #define gdth_readb(addr)        readb((ulong)(addr))
 #define gdth_readw(addr)        readw((ulong)(addr))
 #define gdth_readl(addr)        (ulong32)readl((ulong)(addr))
@@ -571,24 +578,6 @@
 #define gdth_writew(b,addr)     writew((b),(ulong)(addr))
 #define gdth_writel(b,addr)     writel((ulong32)(b),(ulong)(addr))
 
-#else
-static void *gdth_mmap(ulong paddr, ulong size) 
-{ 
-    return ioremap(paddr, size); 
-}
-static void gdth_munmap(void *addr) 
-{
-    return iounmap(addr);
-}
-#define gdth_readb(addr)        readb((ulong)(addr))
-#define gdth_readw(addr)        readw((ulong)(addr))
-#define gdth_readl(addr)        (ulong32)readl((ulong)(addr))
-#define gdth_writeb(b,addr)     writeb((b),(ulong)(addr))
-#define gdth_writew(b,addr)     writew((b),(ulong)(addr))
-#define gdth_writel(b,addr)     writel((ulong32)(b),(ulong)(addr))
-#endif
-
-
 static unchar   gdth_drq_tab[4] = {5,6,7,7};            /* DRQ table */
 static unchar   gdth_irq_tab[6] = {0,10,11,12,14,0};    /* IRQ table */
 static unchar   gdth_polling;                           /* polling if TRUE */
@@ -603,6 +592,7 @@
 static gdth_evt_str ebuffer[MAX_EVENTS];                /* event buffer */
 static int elastidx;
 static int eoldidx;
+static int major;
 
 #define DIN     1                               /* IN data direction */
 #define DOU     2                               /* OUT data direction */
@@ -617,8 +607,8 @@
     DUN,DUN,DUN,DUN,DUN,DOU,DUN,DUN,DUN,DUN,DIN,DUN,DUN,DUN,DUN,DUN,
     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
     DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
-    DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
-    DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
+    DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,
+    DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DIN,DUN,
     DUN,DUN,DUN,DUN,DUN,DNO,DNO,DUN,DIN,DNO,DOU,DUN,DNO,DUN,DOU,DOU,
     DOU,DOU,DOU,DNO,DUN,DIN,DOU,DIN,DIN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
     DUN,DUN,DOU,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,DUN,
@@ -628,36 +618,32 @@
 };
 
 /* __initfunc, __initdata macros */
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#define __devinitdata
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 #define GDTH_INITFUNC(type, func)       type __init func 
 #include <linux/init.h>
-#elif LINUX_VERSION_CODE >= 0x020126
+#else
 #define GDTH_INITFUNC(type, func)       __initfunc(type func)
 #include <linux/init.h>
-#else
-#define GDTH_INITFUNC(type, func)       type func
-#define __initdata
-#define __init
 #endif
 
-#if LINUX_VERSION_CODE >= 0x02015F
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+#define GDTH_INIT_LOCK_HA(ha)           spin_lock_init(&(ha)->smp_lock)
+#define GDTH_LOCK_HA(ha,flags)          spin_lock_irqsave(&(ha)->smp_lock,flags)
+#define GDTH_UNLOCK_HA(ha,flags)        spin_unlock_irqrestore(&(ha)->smp_lock,flags)
+
+#define GDTH_LOCK_SCSI_DONE(dev, flags) spin_lock_irqsave(dev->host_lock,flags)
+#define GDTH_UNLOCK_SCSI_DONE(dev, flags) spin_unlock_irqrestore(dev->host_lock,flags)
+
+#else
 #define GDTH_INIT_LOCK_HA(ha)           spin_lock_init(&(ha)->smp_lock)
 #define GDTH_LOCK_HA(ha,flags)          spin_lock_irqsave(&(ha)->smp_lock,flags)
 #define GDTH_UNLOCK_HA(ha,flags)        spin_unlock_irqrestore(&(ha)->smp_lock,flags)
 
 #define GDTH_LOCK_SCSI_DONE(flags)      spin_lock_irqsave(&io_request_lock,flags)
 #define GDTH_UNLOCK_SCSI_DONE(flags)    spin_unlock_irqrestore(&io_request_lock,flags)
-#define GDTH_LOCK_SCSI_DOCMD()          spin_lock_irq(&io_request_lock)
-#define GDTH_UNLOCK_SCSI_DOCMD()        spin_unlock_irq(&io_request_lock)
-#else
-#define GDTH_INIT_LOCK_HA(ha)           do {} while (0)
-#define GDTH_LOCK_HA(ha,flags)          do {save_flags(flags); cli();} while (0)
-#define GDTH_UNLOCK_HA(ha,flags)        do {restore_flags(flags);} while (0)
-
-#define GDTH_LOCK_SCSI_DONE(flags)      do {} while (0)
-#define GDTH_UNLOCK_SCSI_DONE(flags)    do {} while (0)
-#define GDTH_LOCK_SCSI_DOCMD()          do {} while (0)
-#define GDTH_UNLOCK_SCSI_DOCMD()        do {} while (0)
 #endif
 
 /* LILO and modprobe/insmod parameters */
@@ -686,9 +672,12 @@
 static int virt_ctr = 0;
 /* shared access */
 static int shared_access = 1;
+/* enable support for EISA and ISA controllers */
+static int probe_eisa_isa = 0;
+/* 64 bit DMA mode, support for drives > 2 TB, if force_dma32 = 0 */
+static int force_dma32 = 0;
 
 #ifdef MODULE
-#if LINUX_VERSION_CODE >= 0x02011A
 /* parameters for modprobe/insmod */
 MODULE_PARM(irq, "i");
 MODULE_PARM(disable, "i");
@@ -700,32 +689,43 @@
 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");
 MODULE_AUTHOR("Achim Leubner");
-#endif
-#if LINUX_VERSION_CODE >= 0x02040B
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,11)
 MODULE_LICENSE("GPL");
 #endif
 #endif
 
+/* ioctl interface */
+static struct file_operations gdth_fops = {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    .ioctl   = gdth_ioctl,
+    .open    = gdth_open,
+    .release = gdth_close,
+#else
+    ioctl:gdth_ioctl,
+    open:gdth_open,
+    release:gdth_close,
+#endif
+};
+
 /* /proc support */
-#if LINUX_VERSION_CODE >= 0x010300
 #include <linux/stat.h> 
-#if LINUX_VERSION_CODE < 0x020322
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
 struct proc_dir_entry proc_scsi_gdth = {
     PROC_SCSI_GDTH, 4, "gdth",
     S_IFDIR | S_IRUGO | S_IXUGO, 2
 };
 #endif
+
 #include "gdth_proc.h"
 #include "gdth_proc.c"
-#endif
 
-#if LINUX_VERSION_CODE >= 0x020100
 /* notifier block to get a notify on system shutdown/halt/reboot */
 static struct notifier_block gdth_notifier = {
     gdth_halt, NULL, 0
 };
-#endif
 
 
 static void gdth_delay(int milliseconds)
@@ -733,17 +733,11 @@
     if (milliseconds == 0) {
         udelay(1);
     } else {
-#if LINUX_VERSION_CODE >= 0x020168
         mdelay(milliseconds);
-#else
-        int i;
-        for (i = 0; i < milliseconds; ++i) 
-            udelay(1000);
-#endif
     }
 }
 
-static void gdth_eval_mapping(ulong32 size, int *cyls, int *heads, int *secs)
+static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs)
 {
     *cyls = size /HEADS/SECS;
     if (*cyls <= MAXCYLS) {
@@ -788,9 +782,9 @@
     ulong32 id;
 
     TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr));
-    if ((addr = gdth_mmap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) {
+    if ((addr = ioremap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) {
         id = gdth_readl(addr);
-        gdth_munmap(addr);
+        iounmap(addr);
         if (id == GDT2_ID)                          /* GDT2000 */
             return 1;
     }
@@ -812,19 +806,24 @@
         gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, device);
     gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, 
                     PCI_DEVICE_ID_VORTEX_GDTNEWRX);
+    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_VORTEX, 
+                    PCI_DEVICE_ID_VORTEX_GDTNEWRX2);
     gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
                     PCI_DEVICE_ID_INTEL_SRC);
+    gdth_search_dev(pcistr, &cnt, PCI_VENDOR_ID_INTEL,
+                    PCI_DEVICE_ID_INTEL_SRC_XSCALE);
     return cnt;
 }
 
-#if LINUX_VERSION_CODE >= 0x20363
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 /* Vortex only makes RAID controllers.
  * We do not really want to specify all 550 ids here, so wildcard match.
  */
-static struct pci_device_id gdthtable[] = {
-	{PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID },
-	{PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID }, 
-	{0}
+static struct pci_device_id gdthtable[] __devinitdata = {
+    {PCI_VENDOR_ID_VORTEX,PCI_ANY_ID,PCI_ANY_ID, PCI_ANY_ID},
+    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC,PCI_ANY_ID,PCI_ANY_ID}, 
+    {PCI_VENDOR_ID_INTEL,PCI_DEVICE_ID_INTEL_SRC_XSCALE,PCI_ANY_ID,PCI_ANY_ID}, 
+    {0}
 };
 MODULE_DEVICE_TABLE(pci,gdthtable);
 #endif
@@ -833,17 +832,12 @@
                                            ushort vendor, ushort device))
 {
     ulong base0, base1, base2;
-#if LINUX_VERSION_CODE >= 0x2015C
     struct pci_dev *pdev;
-#else
-    int error;
-    ushort idx;
-#endif
     
     TRACE(("gdth_search_dev() cnt %d vendor %x device %x\n",
           *cnt, vendor, device));
 
-#if LINUX_VERSION_CODE >= 0x20363
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     pdev = NULL;
     while ((pdev = pci_find_device(vendor, device, pdev)) 
            != NULL) {
@@ -881,7 +875,7 @@
                 pcistr[*cnt].irq, pcistr[*cnt].dpmem));
         (*cnt)++;
     }       
-#elif LINUX_VERSION_CODE >= 0x2015C
+#else
     pdev = NULL;
     while ((pdev = pci_find_device(vendor, device, pdev)) 
            != NULL) {
@@ -922,66 +916,6 @@
                 pcistr[*cnt].irq, pcistr[*cnt].dpmem));
         (*cnt)++;
     }       
-#else   
-    idx = 0;
-    while (!pcibios_find_device(vendor, device, idx++,
-                                &pcistr[*cnt].bus,&pcistr[*cnt].device_fn)) {
-        if (*cnt >= MAXHA)
-            return;
-        /* GDT PCI ctr. found, now read resources from config space */
-#if LINUX_VERSION_CODE >= 0x010300
-#define GDTH_BASEP      (int *)
-#else
-#define GDTH_BASEP
-#endif
-        if ((error = pcibios_read_config_dword(pcistr[*cnt].bus,
-                                               pcistr[*cnt].device_fn,
-                                               PCI_BASE_ADDRESS_0,
-                                               GDTH_BASEP&base0)) ||
-            (error = pcibios_read_config_dword(pcistr[*cnt].bus,
-                                               pcistr[*cnt].device_fn,
-                                               PCI_BASE_ADDRESS_1,
-                                               GDTH_BASEP&base1)) ||
-            (error = pcibios_read_config_dword(pcistr[*cnt].bus,
-                                               pcistr[*cnt].device_fn,
-                                               PCI_BASE_ADDRESS_2,
-                                               GDTH_BASEP&base2)) ||
-            (error = pcibios_read_config_word(pcistr[*cnt].bus,
-                                              pcistr[*cnt].device_fn,
-                                              PCI_SUBSYSTEM_ID,
-                                              &pcistr[*cnt].subdevice_id)) ||
-            (error = pcibios_read_config_byte(pcistr[*cnt].bus,
-                                              pcistr[*cnt].device_fn,
-                                              PCI_INTERRUPT_LINE,
-                                              &pcistr[*cnt].irq))) {
-            printk("GDT-PCI: error %d reading configuration space", error);
-            continue;
-        }
-        pcistr[*cnt].vendor_id = vendor;
-        pcistr[*cnt].device_id = device;
-        if (device <= PCI_DEVICE_ID_VORTEX_GDT6000B ||   /* GDT6000/B */
-            device >= PCI_DEVICE_ID_VORTEX_GDT6x17RP) {  /* MPR */
-            if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
-                PCI_BASE_ADDRESS_SPACE_MEMORY)
-                continue;
-            pcistr[*cnt].dpmem = base0 & PCI_BASE_ADDRESS_MEM_MASK;
-        } else {                                    /* GDT6110, GDT6120, .. */
-            if ((base0 & PCI_BASE_ADDRESS_SPACE) !=
-                PCI_BASE_ADDRESS_SPACE_MEMORY ||
-                (base2 & PCI_BASE_ADDRESS_SPACE) !=
-                PCI_BASE_ADDRESS_SPACE_MEMORY ||
-                (base1 & PCI_BASE_ADDRESS_SPACE) !=
-                PCI_BASE_ADDRESS_SPACE_IO)
-                continue;
-            pcistr[*cnt].dpmem = base2 & PCI_BASE_ADDRESS_MEM_MASK;
-            pcistr[*cnt].io_mm = base0 & PCI_BASE_ADDRESS_MEM_MASK;
-            pcistr[*cnt].io    = base1 & PCI_BASE_ADDRESS_IO_MASK;
-        }
-        TRACE2(("Controller found at %d/%d, irq %d, dpmem 0x%lx\n",
-                pcistr[*cnt].bus, PCI_SLOT(pcistr[*cnt].device_fn), 
-                pcistr[*cnt].irq, pcistr[*cnt].dpmem));
-        (*cnt)++;
-    }
 #endif
 }   
 
@@ -1111,6 +1045,8 @@
         ha->type = GDT_EISA;
         ha->stype = id;
     }
+
+    ha->dma64_support = 0;
     return 1;
 }
 
@@ -1124,7 +1060,7 @@
 
     TRACE(("gdth_init_isa() bios adr. %x\n",bios_adr));
 
-    ha->brd = gdth_mmap(bios_adr, sizeof(gdt2_dpram_str));
+    ha->brd = ioremap(bios_adr, sizeof(gdt2_dpram_str));
     if (ha->brd == NULL) {
         printk("GDT-ISA: Initialization error (DPMEM remap error)\n");
         return 0;
@@ -1134,8 +1070,8 @@
     /* reset interface area */
     memset_io((char *)&dp2_ptr->u,0,sizeof(dp2_ptr->u));
     if (gdth_readl(&dp2_ptr->u) != 0) {
-        printk("GDT-PCI: Initialization error (DPMEM write error)\n");
-        gdth_munmap(ha->brd);
+        printk("GDT-ISA: Initialization error (DPMEM write error)\n");
+        iounmap(ha->brd);
         return 0;
     }
 
@@ -1170,7 +1106,7 @@
     while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) {
         if (--retries == 0) {
             printk("GDT-ISA: Initialization error (DEINIT failed)\n");
-            gdth_munmap(ha->brd);
+            iounmap(ha->brd);
             return 0;
         }
         gdth_delay(1);
@@ -1180,7 +1116,7 @@
     gdth_writeb(0xff, &dp2_ptr->io.irqdel);
     if (prot_ver != PROTOCOL_VERSION) {
         printk("GDT-ISA: Illegal protocol version\n");
-        gdth_munmap(ha->brd);
+        iounmap(ha->brd);
         return 0;
     }
 
@@ -1202,13 +1138,15 @@
     while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) {
         if (--retries == 0) {
             printk("GDT-ISA: Initialization error\n");
-            gdth_munmap(ha->brd);
+            iounmap(ha->brd);
             return 0;
         }
         gdth_delay(1);
     }
     gdth_writeb(0, &dp2_ptr->u.ic.Status);
     gdth_writeb(0xff, &dp2_ptr->io.irqdel);
+
+    ha->dma64_support = 0;
     return 1;
 }
 
@@ -1222,9 +1160,6 @@
     unchar prot_ver;
     ushort command;
     int i, found = FALSE;
-#if LINUX_VERSION_CODE < 0x2015C
-    int rom_addr;
-#endif
 
     TRACE(("gdth_init_pci()\n"));
 
@@ -1236,10 +1171,13 @@
     ha->stype = (ulong32)pcistr->device_id;
     ha->subdevice_id = pcistr->subdevice_id;
     ha->irq = pcistr->irq;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    ha->pdev = pcistr->pdev;
+#endif
     
     if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6000B) {  /* GDT6000/B */
         TRACE2(("init_pci() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
-        ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6_dpram_str));
+        ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6_dpram_str));
         if (ha->brd == NULL) {
             printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
             return 0;
@@ -1252,8 +1190,8 @@
                    pcistr->dpmem);
             found = FALSE;
             for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
-                gdth_munmap(ha->brd);
-                ha->brd = gdth_mmap(i, sizeof(ushort)); 
+                iounmap(ha->brd);
+                ha->brd = ioremap(i, sizeof(ushort)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
@@ -1262,15 +1200,10 @@
                     TRACE2(("init_pci_old() address 0x%x busy\n", i));
                     continue;
                 }
-                gdth_munmap(ha->brd);
-#if LINUX_VERSION_CODE >= 0x2015C
+                iounmap(ha->brd);
                 pci_write_config_dword(pcistr->pdev, 
                                        PCI_BASE_ADDRESS_0, i);
-#else
-                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
-                                           PCI_BASE_ADDRESS_0, i);
-#endif
-                ha->brd = gdth_mmap(i, sizeof(gdt6_dpram_str)); 
+                ha->brd = ioremap(i, sizeof(gdt6_dpram_str)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
@@ -1285,20 +1218,20 @@
             }   
             if (!found) {
                 printk("GDT-PCI: No free address found!\n");
-                gdth_munmap(ha->brd);
+                iounmap(ha->brd);
                 return 0;
             }
         }
         memset_io((char *)&dp6_ptr->u,0,sizeof(dp6_ptr->u));
         if (gdth_readl(&dp6_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
-            gdth_munmap(ha->brd);
+            iounmap(ha->brd);
             return 0;
         }
         
         /* disable board interrupts, deinit services */
         gdth_writeb(0xff, &dp6_ptr->io.irqdel);
-        gdth_writeb(0x00, &dp6_ptr->io.irqen);;
+        gdth_writeb(0x00, &dp6_ptr->io.irqen);
         gdth_writeb(0x00, &dp6_ptr->u.ic.S_Status);
         gdth_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index);
 
@@ -1310,7 +1243,7 @@
         while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
-                gdth_munmap(ha->brd);
+                iounmap(ha->brd);
                 return 0;
             }
             gdth_delay(1);
@@ -1320,7 +1253,7 @@
         gdth_writeb(0xff, &dp6_ptr->io.irqdel);
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
-            gdth_munmap(ha->brd);
+            iounmap(ha->brd);
             return 0;
         }
 
@@ -1330,7 +1263,7 @@
         /* special command to controller BIOS */
         gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]);
         gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]);
-        gdth_writel(0x01, &dp6_ptr->u.ic.S_Info[2]);
+        gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[2]);
         gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]);
         gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx);
         gdth_writeb(0, &dp6_ptr->io.event);
@@ -1339,7 +1272,7 @@
         while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
-                gdth_munmap(ha->brd);
+                iounmap(ha->brd);
                 return 0;
             }
             gdth_delay(1);
@@ -1347,14 +1280,16 @@
         gdth_writeb(0, &dp6_ptr->u.ic.S_Status);
         gdth_writeb(0xff, &dp6_ptr->io.irqdel);
 
+        ha->dma64_support = 0;
+
     } else if (ha->stype <= PCI_DEVICE_ID_VORTEX_GDT6555) { /* GDT6110, ... */
         ha->plx = (gdt6c_plx_regs *)pcistr->io;
         TRACE2(("init_pci_new() dpmem %lx irq %d\n",
             pcistr->dpmem,ha->irq));
-        ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6c_dpram_str));
+        ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6c_dpram_str));
         if (ha->brd == NULL) {
             printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
-            gdth_munmap(ha->brd);
+            iounmap(ha->brd);
             return 0;
         }
         /* check and reset interface area */
@@ -1365,8 +1300,8 @@
                    pcistr->dpmem);
             found = FALSE;
             for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
-                gdth_munmap(ha->brd);
-                ha->brd = gdth_mmap(i, sizeof(ushort)); 
+                iounmap(ha->brd);
+                ha->brd = ioremap(i, sizeof(ushort)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
@@ -1375,15 +1310,10 @@
                     TRACE2(("init_pci_plx() address 0x%x busy\n", i));
                     continue;
                 }
-                gdth_munmap(ha->brd);
-#if LINUX_VERSION_CODE >= 0x2015C
+                iounmap(ha->brd);
                 pci_write_config_dword(pcistr->pdev, 
                                        PCI_BASE_ADDRESS_2, i);
-#else
-                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
-                                           PCI_BASE_ADDRESS_2, i);
-#endif
-                ha->brd = gdth_mmap(i, sizeof(gdt6c_dpram_str)); 
+                ha->brd = ioremap(i, sizeof(gdt6c_dpram_str)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
@@ -1398,14 +1328,14 @@
             }   
             if (!found) {
                 printk("GDT-PCI: No free address found!\n");
-                gdth_munmap(ha->brd);
+                iounmap(ha->brd);
                 return 0;
             }
         }
         memset_io((char *)&dp6c_ptr->u,0,sizeof(dp6c_ptr->u));
         if (gdth_readl(&dp6c_ptr->u) != 0) {
             printk("GDT-PCI: Initialization error (DPMEM write error)\n");
-            gdth_munmap(ha->brd);
+            iounmap(ha->brd);
             return 0;
         }
         
@@ -1426,7 +1356,7 @@
         while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
-                gdth_munmap(ha->brd);
+                iounmap(ha->brd);
                 return 0;
             }
             gdth_delay(1);
@@ -1435,7 +1365,7 @@
         gdth_writeb(0, &dp6c_ptr->u.ic.Status);
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
-            gdth_munmap(ha->brd);
+            iounmap(ha->brd);
             return 0;
         }
 
@@ -1445,7 +1375,7 @@
         /* special command to controller BIOS */
         gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]);
         gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]);
-        gdth_writel(0x01, &dp6c_ptr->u.ic.S_Info[2]);
+        gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[2]);
         gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]);
         gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx);
         
@@ -1456,23 +1386,25 @@
         while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
-                gdth_munmap(ha->brd);
+                iounmap(ha->brd);
                 return 0;
             }
             gdth_delay(1);
         }
         gdth_writeb(0, &dp6c_ptr->u.ic.S_Status);
 
+        ha->dma64_support = 0;
+
     } else {                                            /* MPR */
         TRACE2(("init_pci_mpr() dpmem %lx irq %d\n",pcistr->dpmem,ha->irq));
-        ha->brd = gdth_mmap(pcistr->dpmem, sizeof(gdt6m_dpram_str));
+        ha->brd = ioremap(pcistr->dpmem, sizeof(gdt6m_dpram_str));
         if (ha->brd == NULL) {
             printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
             return 0;
         }
 
         /* manipulate config. space to enable DPMEM, start RP controller */
-#if LINUX_VERSION_CODE >= 0x20363
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
         pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
         command |= 6;
         pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
@@ -1483,7 +1415,7 @@
         gdth_delay(1);
         pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
                                pci_resource_start(pcistr->pdev, 8));
-#elif LINUX_VERSION_CODE >= 0x2015C
+#else
         pci_read_config_word(pcistr->pdev, PCI_COMMAND, &command);
         command |= 6;
         pci_write_config_word(pcistr->pdev, PCI_COMMAND, command);
@@ -1494,24 +1426,13 @@
         gdth_delay(1);
         pci_write_config_dword(pcistr->pdev, PCI_ROM_ADDRESS,
                                pcistr->pdev->rom_address);
-#else
-        pcibios_read_config_word(pcistr->bus, pcistr->device_fn,
-                                 PCI_COMMAND, &command);
-        command |= 6;
-        pcibios_write_config_word(pcistr->bus, pcistr->device_fn, 
-                                  PCI_COMMAND, command);
-        pcibios_read_config_dword(pcistr->bus, pcistr->device_fn,
-                                  PCI_ROM_ADDRESS, &rom_addr);
-        if (rom_addr == 1UL)
-            rom_addr = 0UL;
-        i = 0xFEFF0001UL;
-        pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
-                                   PCI_ROM_ADDRESS, i);
-        gdth_delay(1);
-        pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
-                                   PCI_ROM_ADDRESS, rom_addr);
 #endif
         
+        /* Ensure that it is safe to access the non HW portions of DPMEM.
+         * Aditional check needed for Xscale based RAID controllers */
+        while( ((int)gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.sema0_reg) ) & 3 )
+            gdth_delay(1);
+        
         /* check and reset interface area */
         dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
         gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u);
@@ -1520,8 +1441,8 @@
                    pcistr->dpmem);
             found = FALSE;
             for (i = 0xC8000; i < 0xE8000; i += 0x4000) {
-                gdth_munmap(ha->brd);
-                ha->brd = gdth_mmap(i, sizeof(ushort)); 
+                iounmap(ha->brd);
+                ha->brd = ioremap(i, sizeof(ushort)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
@@ -1530,15 +1451,10 @@
                     TRACE2(("init_pci_mpr() address 0x%x busy\n", i));
                     continue;
                 }
-                gdth_munmap(ha->brd);
-#if LINUX_VERSION_CODE >= 0x2015C
+                iounmap(ha->brd);
                 pci_write_config_dword(pcistr->pdev, 
                                        PCI_BASE_ADDRESS_0, i);
-#else
-                pcibios_write_config_dword(pcistr->bus, pcistr->device_fn,
-                                           PCI_BASE_ADDRESS_0, i);
-#endif
-                ha->brd = gdth_mmap(i, sizeof(gdt6m_dpram_str)); 
+                ha->brd = ioremap(i, sizeof(gdt6m_dpram_str)); 
                 if (ha->brd == NULL) {
                     printk("GDT-PCI: Initialization error (DPMEM remap error)\n");
                     return 0;
@@ -1553,7 +1469,7 @@
             }   
             if (!found) {
                 printk("GDT-PCI: No free address found!\n");
-                gdth_munmap(ha->brd);
+                iounmap(ha->brd);
                 return 0;
             }
         }
@@ -1574,7 +1490,7 @@
         while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error (DEINIT failed)\n");
-                gdth_munmap(ha->brd);
+                iounmap(ha->brd);
                 return 0;
             }
             gdth_delay(1);
@@ -1583,7 +1499,7 @@
         gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
         if (prot_ver != PROTOCOL_VERSION) {
             printk("GDT-PCI: Illegal protocol version\n");
-            gdth_munmap(ha->brd);
+            iounmap(ha->brd);
             return 0;
         }
 
@@ -1593,7 +1509,7 @@
         /* special command to controller BIOS */
         gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[0]);
         gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[1]);
-        gdth_writel(0x01, &dp6m_ptr->u.ic.S_Info[2]);
+        gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[2]);
         gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[3]);
         gdth_writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx);
         gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
@@ -1602,12 +1518,32 @@
         while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) {
             if (--retries == 0) {
                 printk("GDT-PCI: Initialization error\n");
-                gdth_munmap(ha->brd);
+                iounmap(ha->brd);
                 return 0;
             }
             gdth_delay(1);
         }
         gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
+
+        /* read FW version to detect 64-bit DMA support */
+        gdth_writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx);
+        gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg);
+        retries = INIT_RETRIES;
+        gdth_delay(20);
+        while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) {
+            if (--retries == 0) {
+                printk("GDT-PCI: Initialization error (DEINIT failed)\n");
+                iounmap(ha->brd);
+                return 0;
+            }
+            gdth_delay(1);
+        }
+        prot_ver = (unchar)(gdth_readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16);
+        gdth_writeb(0, &dp6m_ptr->u.ic.S_Status);
+        if (prot_ver < 0x2b)      /* FW < x.43: no 64-bit DMA support */
+            ha->dma64_support = 0;
+        else 
+            ha->dma64_support = 1;
     }
 
     return 1;
@@ -1841,7 +1777,7 @@
 
     if (ha->type == GDT_EISA) {
         if (ha->pccb->OpCode == GDT_INIT)               /* store DMA buffer */
-            outl(virt_to_bus(ha->pccb), ha->bmic + MAILBOXREG);
+            outl(ha->ccb_phys, ha->bmic + MAILBOXREG);
         outb(ha->pccb->Service, ha->bmic + LDOORREG);
     } else if (ha->type == GDT_ISA) {
         gdth_writeb(0, &((gdt2_dpram_str *)ha->brd)->io.event);
@@ -1868,11 +1804,7 @@
 
     gdth_from_wait = TRUE;
     do {
-#if LINUX_VERSION_CODE >= 0x010346
         gdth_interrupt((int)ha->irq,ha,NULL);
-#else
-        gdth_interrupt((int)ha->irq,NULL);
-#endif
         if (wait_hanum==hanum && wait_index==index) {
             answer_found = TRUE;
             break;
@@ -1889,7 +1821,7 @@
 
 
 static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1,
-                             ulong32 p2,ulong32 p3)
+                             ulong64 p2,ulong64 p3)
 {
     register gdth_ha_str *ha;
     register gdth_cmd_str *cmd_ptr;
@@ -1915,23 +1847,35 @@
         if (service == CACHESERVICE) {
             if (opcode == GDT_IOCTL) {
                 cmd_ptr->u.ioctl.subfunc = p1;
-                cmd_ptr->u.ioctl.channel = p2;
+                cmd_ptr->u.ioctl.channel = (ulong32)p2;
                 cmd_ptr->u.ioctl.param_size = (ushort)p3;
-                cmd_ptr->u.ioctl.p_param = virt_to_bus(ha->pscratch);
+                cmd_ptr->u.ioctl.p_param = ha->scratch_phys;
             } else {
-                cmd_ptr->u.cache.DeviceNo = (ushort)p1;
-                cmd_ptr->u.cache.BlockNo  = p2;
+                if (ha->cache_feat & GDT_64BIT) {
+                    cmd_ptr->u.cache64.DeviceNo = (ushort)p1;
+                    cmd_ptr->u.cache64.BlockNo  = p2;
+                } else {
+                    cmd_ptr->u.cache.DeviceNo = (ushort)p1;
+                    cmd_ptr->u.cache.BlockNo  = (ulong32)p2;
+                }
             }
         } else if (service == SCSIRAWSERVICE) {
-            cmd_ptr->u.raw.direction  = p1;
-            cmd_ptr->u.raw.bus        = (unchar)p2;
-            cmd_ptr->u.raw.target     = (unchar)p3;
-            cmd_ptr->u.raw.lun        = (unchar)(p3 >> 8);
+            if (ha->raw_feat & GDT_64BIT) {
+                cmd_ptr->u.raw64.direction  = p1;
+                cmd_ptr->u.raw64.bus        = (unchar)p2;
+                cmd_ptr->u.raw64.target     = (unchar)p3;
+                cmd_ptr->u.raw64.lun        = (unchar)(p3 >> 8);
+            } else {
+                cmd_ptr->u.raw.direction  = p1;
+                cmd_ptr->u.raw.bus        = (unchar)p2;
+                cmd_ptr->u.raw.target     = (unchar)p3;
+                cmd_ptr->u.raw.lun        = (unchar)(p3 >> 8);
+            }
         } else if (service == SCREENSERVICE) {
             if (opcode == GDT_REALTIME) {
                 *(ulong32 *)&cmd_ptr->u.screen.su.data[0] = p1;
-                *(ulong32 *)&cmd_ptr->u.screen.su.data[4] = p2;
-                *(ulong32 *)&cmd_ptr->u.screen.su.data[8] = p3;
+                *(ulong32 *)&cmd_ptr->u.screen.su.data[4] = (ulong32)p2;
+                *(ulong32 *)&cmd_ptr->u.screen.su.data[8] = (ulong32)p3;
             }
         }
         ha->cmd_len          = sizeof(gdth_cmd_str);
@@ -1959,6 +1903,7 @@
 {
     register gdth_ha_str *ha;
     ushort cdev_cnt, i;
+    int ok;
     ulong32 bus_no, drv_cnt, drv_no, j;
     gdth_getch_str *chn;
     gdth_drlist_str *drl;
@@ -1966,6 +1911,11 @@
     gdth_raw_iochan_str *iocr;
     gdth_arcdl_str *alst;
     gdth_alist_str *alst2;
+    gdth_oem_str_ioctl *oemstr;
+#ifdef INT_COAL
+    gdth_perf_modes *pmod;
+#endif
+
 #ifdef GDTH_RTC
     unchar rtc[12];
     ulong flags;
@@ -1973,11 +1923,20 @@
    
     TRACE(("gdth_search_drives() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
+    ok = 0;
 
     /* initialize controller services, at first: screen service */
-    if (!gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0)) {
-        printk("GDT: Initialization error screen service (code %d)\n",
-               ha->status);
+    ha->screen_feat = 0;
+    if (!force_dma32) {
+        ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_X_INIT_SCR,0,0,0);
+        if (ok)
+            ha->screen_feat = GDT_64BIT;
+    }
+    if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
+        ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0);
+    if (!ok) {
+        printk("GDT-HA %d: Initialization error screen service (code %d)\n",
+               hanum, ha->status);
         return 0;
     }
     TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n"));
@@ -2009,15 +1968,52 @@
     gdth_internal_cmd(hanum,CACHESERVICE,GDT_UNFREEZE_IO,0,0,0);
  
     /* initialize cache service */
-    if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0)) {
-        printk("GDT: Initialization error cache service (code %d)\n",
-               ha->status);
+    ha->cache_feat = 0;
+    if (!force_dma32) {
+        ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INIT_HOST,LINUX_OS,0,0);
+        if (ok)
+            ha->cache_feat = GDT_64BIT;
+    }
+    if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
+        ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0);
+    if (!ok) {
+        printk("GDT-HA %d: Initialization error cache service (code %d)\n",
+               hanum, ha->status);
         return 0;
     }
     TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n"));
     cdev_cnt = (ushort)ha->info;
     ha->fw_vers = ha->service;
 
+#ifdef INT_COAL
+    if (ha->type == GDT_PCIMPR) {
+        /* set perf. modes */
+        pmod = (gdth_perf_modes *)ha->pscratch;
+        pmod->version          = 1;
+        pmod->st_mode          = 1;    /* enable one status buffer */
+        *((ulong64 *)&pmod->st_buff_addr1) = ha->coal_stat_phys;
+        pmod->st_buff_indx1    = COALINDEX;
+        pmod->st_buff_addr2    = 0;
+        pmod->st_buff_u_addr2  = 0;
+        pmod->st_buff_indx2    = 0;
+        pmod->st_buff_size     = sizeof(gdth_coal_status) * MAXOFFSETS;
+        pmod->cmd_mode         = 0;    // disable all cmd buffers
+        pmod->cmd_buff_addr1   = 0;
+        pmod->cmd_buff_u_addr1 = 0;
+        pmod->cmd_buff_indx1   = 0;
+        pmod->cmd_buff_addr2   = 0;
+        pmod->cmd_buff_u_addr2 = 0;
+        pmod->cmd_buff_indx2   = 0;
+        pmod->cmd_buff_size    = 0;
+        pmod->reserved1        = 0;            
+        pmod->reserved2        = 0;            
+        if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,SET_PERF_MODES,
+                              INVALID_CHANNEL,sizeof(gdth_perf_modes))) {
+            printk("GDT-HA %d: Interrupt coalescing activated\n", hanum);
+        }
+    }
+#endif
+
     /* detect number of buses - try new IOCTL */
     iocr = (gdth_raw_iochan_str *)ha->pscratch;
     iocr->hdr.version        = 0xffffffff;
@@ -2045,8 +2041,8 @@
                                    IO_CHANNEL | INVALID_CHANNEL,
                                    sizeof(gdth_getch_str))) {
                 if (bus_no == 0) {
-                    printk("GDT: Error detecting channel count (0x%x)\n",
-                           ha->status);
+                    printk("GDT-HA %d: Error detecting channel count (0x%x)\n",
+                           hanum, ha->status);
                     return 0;
                 }
                 break;
@@ -2063,8 +2059,8 @@
     /* read cache configuration */
     if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO,
                            INVALID_CHANNEL,sizeof(gdth_cinfo_str))) {
-        printk("GDT: Initialization error cache service (code %d)\n",
-               ha->status);
+        printk("GDT-HA %d: Initialization error cache service (code %d)\n",
+               hanum, ha->status);
         return 0;
     }
     ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar;
@@ -2183,9 +2179,17 @@
     }       
                                   
     /* initialize raw service */
-    if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0)) {
-        printk("GDT: Initialization error raw service (code %d)\n",
-               ha->status);
+    ha->raw_feat = 0;
+    if (!force_dma32) {
+        ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_X_INIT_RAW,0,0,0);
+        if (ok)
+            ha->raw_feat = GDT_64BIT;
+    }
+    if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC))
+        ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0);
+    if (!ok) {
+        printk("GDT-HA %d: Initialization error raw service (code %d)\n",
+               hanum, ha->status);
         return 0;
     }
     TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n"));
@@ -2197,7 +2201,7 @@
         if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) {
             TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n",
                     ha->info));
-            ha->raw_feat = (ushort)ha->info;
+            ha->raw_feat |= (ushort)ha->info;
         }
     } 
 
@@ -2208,7 +2212,7 @@
         if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) {
             TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n",
                     ha->info));
-            ha->cache_feat = (ushort)ha->info;
+            ha->cache_feat |= (ushort)ha->info;
         }
     }
 
@@ -2228,12 +2232,48 @@
             if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0,
                                    reserve_list[i+1], reserve_list[i+2] | 
                                    (reserve_list[i+3] << 8))) {
-                printk("GDT: Error raw service (RESERVE, code %d)\n",
-                       ha->status);
+                printk("GDT-HA %d: Error raw service (RESERVE, code %d)\n",
+                       hanum, ha->status);
              }
         }
     }
 
+    /* Determine OEM string using IOCTL */
+    oemstr = (gdth_oem_str_ioctl *)ha->pscratch;
+    oemstr->params.ctl_version = 0x01;
+    oemstr->params.buffer_size = sizeof(oemstr->text);
+    if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,
+                          CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL,
+                          sizeof(gdth_oem_str_ioctl))) {
+        TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n"));
+        printk("GDT-HA %d: Vendor: %s Name: %s\n",
+               hanum,oemstr->text.oem_company_name,ha->binfo.type_string);
+        /* Save the Host Drive inquiry data */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        strlcpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,
+                sizeof(ha->oem_name));
+#else
+        strncpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,7);
+        ha->oem_name[7] = '\0';
+#endif
+    } else {
+        /* Old method, based on PCI ID */
+        TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n"));
+        printk("GDT-HA %d: Name: %s\n",
+               hanum,ha->binfo.type_string);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        if (ha->oem_id == OEM_ID_INTEL)
+            strlcpy(ha->oem_name,"Intel  ", sizeof(ha->oem_name));
+        else
+            strlcpy(ha->oem_name,"ICP    ", sizeof(ha->oem_name));
+#else 
+        if (ha->oem_id == OEM_ID_INTEL)
+            strcpy(ha->oem_name,"Intel  ");
+        else
+            strcpy(ha->oem_name,"ICP    ");
+#endif
+    }
+
     /* scanning for host drives */
     for (i = 0; i < cdev_cnt; ++i) 
         gdth_analyse_hdrive(hanum,i);
@@ -2245,7 +2285,8 @@
 static int gdth_analyse_hdrive(int hanum,ushort hdrive)
 {
     register gdth_ha_str *ha;
-    int drv_cyls, drv_hds, drv_secs;
+    ulong32 drv_cyls;
+    int drv_hds, drv_secs;
 
     TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n",hanum,hdrive));
     if (hdrive >= MAX_HDRIVES)
@@ -2256,7 +2297,7 @@
         return 0;
     ha->hdr[hdrive].present = TRUE;
     ha->hdr[hdrive].size = ha->info;
-
+   
     /* evaluate mapping (sectors per head, heads per cylinder) */
     ha->hdr[hdrive].size &= ~SECS32;
     if (ha->info2 == 0) {
@@ -2264,15 +2305,22 @@
     } else {
         drv_hds = ha->info2 & 0xff;
         drv_secs = (ha->info2 >> 8) & 0xff;
-        drv_cyls = ha->hdr[hdrive].size /drv_hds/drv_secs;
+        drv_cyls = (ulong32)ha->hdr[hdrive].size / drv_hds / drv_secs;
     }
     ha->hdr[hdrive].heads = (unchar)drv_hds;
     ha->hdr[hdrive].secs  = (unchar)drv_secs;
     /* round size */
     ha->hdr[hdrive].size  = drv_cyls * drv_hds * drv_secs;
+    
+    if (ha->cache_feat & GDT_64BIT) {
+        if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INFO,hdrive,0,0)
+            && ha->info2 != 0) {
+            ha->hdr[hdrive].size = ((ulong64)ha->info2 << 32) | ha->info;
+        }
+    }
     TRACE2(("gdth_search_dr() cdr. %d size %d hds %d scs %d\n",
             hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs));
-            
+
     /* get informations about device */
     if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,hdrive,0,0)) {
         TRACE2(("gdth_search_dr() cache drive %d devtype %d\n",
@@ -2314,9 +2362,13 @@
     GDTH_LOCK_HA(ha, flags);
 
     scp->SCp.this_residual = (int)priority;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+    t = scp->device->id;
+#else
     b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
     t = scp->target;
-#if LINUX_VERSION_CODE >= 0x010300
+#endif
     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)) {
@@ -2324,7 +2376,6 @@
             scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
         }
     }
-#endif
 
     if (ha->req_first==NULL) {
         ha->req_first = scp;                    /* queue was empty */
@@ -2358,7 +2409,7 @@
     register gdth_ha_str *ha;
     register Scsi_Cmnd *pscp;
     register Scsi_Cmnd *nscp;
-    unchar b, t, firsttime;
+    unchar b, t, l, firsttime;
     unchar this_cmd, next_cmd;
     ulong flags = 0;
     int cmd_index;
@@ -2366,7 +2417,7 @@
     TRACE(("gdth_next() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
     if (!gdth_polling) 
-    	GDTH_LOCK_HA(ha, flags);
+        GDTH_LOCK_HA(ha, flags);
 
     ha->cmd_cnt = ha->cmd_offs_dpmem = 0;
     this_cmd = firsttime = TRUE;
@@ -2376,8 +2427,15 @@
     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 LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        b = virt_ctr ? NUMDATA(nscp->device->host)->busnum : nscp->device->channel;
+        t = nscp->device->id;
+        l = nscp->device->lun;
+#else
         b = virt_ctr ? NUMDATA(nscp->host)->busnum : nscp->channel;
         t = nscp->target;
+        l = nscp->lun;
+#endif
         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)) 
@@ -2397,24 +2455,21 @@
             firsttime = FALSE;
         }
 
-#if LINUX_VERSION_CODE >= 0x010300
-        if (nscp->done != gdth_scsi_done || nscp->cmnd[0] != 0xff) 
-#endif
-        {
+        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) {
                 TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n", 
-                        b, t, nscp->lun));
+                        b, t, l));
                 /* TEST_UNIT_READY -> set scan mode */
                 if ((ha->scan_mode & 0x0f) == 0) {
-                    if (b == 0 && t == 0 && nscp->lun == 0) {
+                    if (b == 0 && t == 0 && l == 0) {
                         ha->scan_mode |= 1;
                         TRACE2(("Scan mode: 0x%x\n", ha->scan_mode));
                     }
                 } else if ((ha->scan_mode & 0x0f) == 1) {
-                    if (b == 0 && ((t == 0 && nscp->lun == 1) ||
-                         (t == 1 && nscp->lun == 0))) {
+                    if (b == 0 && ((t == 0 && l == 1) ||
+                         (t == 1 && l == 0))) {
                         nscp->SCp.sent_command = GDT_SCAN_START;
                         nscp->SCp.phase = ((ha->scan_mode & 0x10 ? 1:0) << 8) 
                             | SCSIRAWSERVICE;
@@ -2466,37 +2521,32 @@
                     /* io_request_lock already active ! */
                     nscp->scsi_done(nscp);
                     if (!gdth_polling) 
-                    	GDTH_LOCK_HA(ha,flags);
+                        GDTH_LOCK_HA(ha,flags);
                 }
             }
-        } else
-
-#if LINUX_VERSION_CODE >= 0x010300
-        if (nscp->done == gdth_scsi_done && nscp->cmnd[0] == 0xff) {
+        } 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;
-        } else
-#endif
-        if (b != ha->virt_bus) {
+        } else if (b != ha->virt_bus) {
             if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW ||
                 !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) 
                 this_cmd = FALSE;
             else 
                 ha->raw[BUS_L2P(ha,b)].io_cnt[t]++;
-        } else if (t >= MAX_HDRIVES || !ha->hdr[t].present || nscp->lun != 0) {
+        } else if (t >= MAX_HDRIVES || !ha->hdr[t].present || l != 0) {
             TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n",
-                    nscp->cmnd[0], b, t, nscp->lun));
+                    nscp->cmnd[0], b, t, l));
             nscp->result = DID_BAD_TARGET << 16;
             if (!nscp->SCp.have_data_in)
                 nscp->SCp.have_data_in++;
             else {
                 if (!gdth_polling) 
-                	GDTH_UNLOCK_HA(ha,flags);
+                    GDTH_UNLOCK_HA(ha,flags);
                 /* io_request_lock already active ! */      
                 nscp->scsi_done(nscp);
                 if (!gdth_polling) 
-                	GDTH_LOCK_HA(ha,flags);
+                    GDTH_LOCK_HA(ha,flags);
             }
         } else {
             switch (nscp->cmnd[0]) {
@@ -2507,6 +2557,9 @@
               case VERIFY:
               case START_STOP:
               case MODE_SENSE:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+              case SERVICE_ACTION_IN:
+#endif
                 TRACE(("cache cmd %x/%x/%x/%x/%x/%x\n",nscp->cmnd[0],
                        nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                        nscp->cmnd[4],nscp->cmnd[5]));
@@ -2522,20 +2575,20 @@
                     if (!nscp->SCp.have_data_in)
                         nscp->SCp.have_data_in++;
                     else {
-                	if (!gdth_polling) 
-                        	GDTH_UNLOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_UNLOCK_HA(ha,flags);
                         /* io_request_lock already active ! */      
                         nscp->scsi_done(nscp);
-                	if (!gdth_polling) 
-                        	GDTH_LOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_LOCK_HA(ha,flags);
                     }
                 } else if (gdth_internal_cache_cmd(hanum,nscp)) {
                     if (!gdth_polling) 
-                    	GDTH_UNLOCK_HA(ha,flags);
+                        GDTH_UNLOCK_HA(ha,flags);
                     /* io_request_lock already active ! */      
                     nscp->scsi_done(nscp);
                     if (!gdth_polling) 
-                    	GDTH_LOCK_HA(ha,flags);
+                        GDTH_LOCK_HA(ha,flags);
                 }
                 break;
 
@@ -2550,12 +2603,12 @@
                     if (!nscp->SCp.have_data_in)
                         nscp->SCp.have_data_in++;
                     else {
-                    	if (!gdth_polling) 
-                        	GDTH_UNLOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_UNLOCK_HA(ha,flags);
                         /* io_request_lock already active ! */      
                         nscp->scsi_done(nscp);
-                    	if (!gdth_polling) 
-                        	GDTH_LOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_LOCK_HA(ha,flags);
                     }
                 } else {
                     nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0;
@@ -2578,6 +2631,10 @@
               case WRITE_6:
               case READ_10:
               case WRITE_10:
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+              case READ_16:
+              case WRITE_16:
+#endif
                 if (ha->hdr[t].media_changed) {
                     /* return UNIT_ATTENTION */
                     TRACE2(("cmd 0x%x target %d: UNIT_ATTENTION\n",
@@ -2590,12 +2647,12 @@
                     if (!nscp->SCp.have_data_in)
                         nscp->SCp.have_data_in++;
                     else {
-                    	if (!gdth_polling) 
-                        	GDTH_UNLOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_UNLOCK_HA(ha,flags);
                         /* io_request_lock already active ! */      
                         nscp->scsi_done(nscp);
-                    	if (!gdth_polling) 
-                        	GDTH_LOCK_HA(ha,flags);
+                        if (!gdth_polling) 
+                            GDTH_LOCK_HA(ha,flags);
                     }
                 } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t)))
                     this_cmd = FALSE;
@@ -2605,18 +2662,18 @@
                 TRACE2(("cache cmd %x/%x/%x/%x/%x/%x unknown\n",nscp->cmnd[0],
                         nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3],
                         nscp->cmnd[4],nscp->cmnd[5]));
-                printk("GDT: Unknown SCSI command 0x%x to cache service !\n",
-                       nscp->cmnd[0]);
+                printk("GDT-HA %d: Unknown SCSI command 0x%x to cache service !\n",
+                       hanum, nscp->cmnd[0]);
                 nscp->result = DID_ABORT << 16;
                 if (!nscp->SCp.have_data_in)
                     nscp->SCp.have_data_in++;
                 else {
                     if (!gdth_polling) 
-                    	GDTH_UNLOCK_HA(ha,flags);
+                        GDTH_UNLOCK_HA(ha,flags);
                     /* io_request_lock already active ! */  
                     nscp->scsi_done(nscp);
                     if (!gdth_polling) 
-                    	GDTH_LOCK_HA(ha,flags);
+                        GDTH_LOCK_HA(ha,flags);
                 }
                 break;
             }
@@ -2637,36 +2694,68 @@
     }
 
     if (!gdth_polling) 
-    	GDTH_UNLOCK_HA(ha, flags);
+        GDTH_UNLOCK_HA(ha, flags);
 
     if (gdth_polling && ha->cmd_cnt > 0) {
         if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT))
-            printk("GDT: Controller %d: Command %d timed out !\n",
+            printk("GDT-HA %d: Command %d timed out !\n",
                    hanum,cmd_index);
     }
 }
-    
-static void gdth_copy_internal_data(Scsi_Cmnd *scp,char *buffer,ushort count)
+   
+static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp,
+                                    char *buffer,ushort count)
 {
     ushort cpcount,i;
     ushort cpsum,cpnow;
     struct scatterlist *sl;
+    gdth_ha_str *ha;
+    int sgcnt;
+    char *address;
 
     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) {
-            cpnow = (ushort)sl->length;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
+        sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,PCI_DMA_FROMDEVICE);
+        for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
+            cpnow = (ushort)sg_dma_len(sl);
             TRACE(("copy_internal() now %d sum %d count %d %d\n",
                           cpnow,cpsum,cpcount,(ushort)scp->bufflen));
             if (cpsum+cpnow > cpcount) 
                 cpnow = cpcount - cpsum;
             cpsum += cpnow;
-            memcpy((char*)sl->address,buffer,cpnow);
+            if (!sl->page) {
+                printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n",
+                       hanum);
+                return;
+            }
+            address = (char *)(page_address(sl->page) + sl->offset);
+            memcpy(address,buffer,cpnow);
+            if (cpsum == cpcount)
+                break;
+            buffer += cpnow;
+        }
+        pci_unmap_sg(ha->pdev,scp->request_buffer,
+                     scp->use_sg,PCI_DMA_FROMDEVICE);
+#else
+        sgcnt = scp->use_sg;
+        for (i=0,cpsum=0; i<sgcnt; ++i,++sl) {
+            cpnow = (ushort)sl->length;
+            TRACE(("copy_internal() now %d sum %d count %d %d\n",
+                          cpnow,cpsum,cpcount,(ushort)scp->bufflen));
+            if (cpsum+cpnow > cpcount) 
+               cpnow = cpcount - cpsum;
+            cpsum += cpnow;
+            address = (char *)sl->address;
+            memcpy(address,buffer,cpnow);
             if (cpsum == cpcount)
                 break;
             buffer += cpnow;
         }
+#endif
     } else {
         TRACE(("copy_internal() count %d\n",cpcount));
         memcpy((char*)scp->request_buffer,buffer,cpcount);
@@ -2683,10 +2772,17 @@
     gdth_modep_data mpd;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    t  = scp->device->id;
+#else
     t  = scp->target;
+#endif
     TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n",
            scp->cmnd[0],t));
 
+    scp->result = DID_OK << 16;
+    scp->sense_buffer[0] = 0;
+
     switch (scp->cmnd[0]) {
       case TEST_UNIT_READY:
       case VERIFY:
@@ -2707,13 +2803,10 @@
         inq.version   = 2;
         inq.resp_aenc = 2;
         inq.add_length= 32;
-        if (ha->oem_id == OEM_ID_INTEL)
-            strcpy(inq.vendor,"Intel  ");
-        else 
-            strcpy(inq.vendor,"ICP    ");
+        strcpy(inq.vendor,ha->oem_name);
         sprintf(inq.product,"Host Drive  #%02d",t);
         strcpy(inq.revision,"   ");
-        gdth_copy_internal_data(scp,(char*)&inq,sizeof(gdth_inq_data));
+        gdth_copy_internal_data(hanum,scp,(char*)&inq,sizeof(gdth_inq_data));
         break;
 
       case REQUEST_SENSE:
@@ -2723,7 +2816,7 @@
         sd.key       = NO_SENSE;
         sd.info      = 0;
         sd.add_length= 0;
-        gdth_copy_internal_data(scp,(char*)&sd,sizeof(gdth_sense_data));
+        gdth_copy_internal_data(hanum,scp,(char*)&sd,sizeof(gdth_sense_data));
         break;
 
       case MODE_SENSE:
@@ -2735,24 +2828,40 @@
         mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16;
         mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8;
         mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff);
-        gdth_copy_internal_data(scp,(char*)&mpd,sizeof(gdth_modep_data));
+        gdth_copy_internal_data(hanum,scp,(char*)&mpd,sizeof(gdth_modep_data));
         break;
 
       case READ_CAPACITY:
         TRACE2(("Read capacity hdrive %d\n",t));
-        rdc.last_block_no = ntohl(ha->hdr[t].size-1);
-        rdc.block_length  = ntohl(SECTOR_SIZE);
-        gdth_copy_internal_data(scp,(char*)&rdc,sizeof(gdth_rdcap_data));
+        if (ha->hdr[t].size > (ulong64)0xffffffff)
+            rdc.last_block_no = 0xffffffff;
+        else
+            rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1);
+        rdc.block_length  = cpu_to_be32(SECTOR_SIZE);
+        gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data));
         break;
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+      case SERVICE_ACTION_IN:
+        if ((scp->cmnd[1] & 0x1f) == SAI_READ_CAPACITY_16 &&
+            (ha->cache_feat & GDT_64BIT)) {
+            gdth_rdcap16_data rdc16;
+
+            TRACE2(("Read capacity (16) hdrive %d\n",t));
+            rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1);
+            rdc16.block_length  = cpu_to_be32(SECTOR_SIZE);
+            gdth_copy_internal_data(hanum,scp,(char*)&rdc16,sizeof(gdth_rdcap16_data));
+        } else { 
+            scp->result = DID_ABORT << 16;
+        }
+        break;
+#endif
+
       default:
         TRACE2(("Internal cache cmd 0x%x unknown\n",scp->cmnd[0]));
         break;
     }
 
-    scp->result = DID_OK << 16;
-    scp->sense_buffer[0] = 0;
-
     if (!scp->SCp.have_data_in)
         scp->SCp.have_data_in++;
     else 
@@ -2766,9 +2875,14 @@
     register gdth_ha_str *ha;
     register gdth_cmd_str *cmdp;
     struct scatterlist *sl;
-    ushort i, cnt;
-    ulong32 no;
-    int cmd_index, read_write;
+    ulong32 cnt, blockcnt;
+    ulong64 no, blockno;
+    dma_addr_t phys_addr;
+    int i, cmd_index, read_write, sgcnt, mode64;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
+    struct page *page;
+    ulong offset;
+#endif
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     cmdp = ha->pccb;
@@ -2778,6 +2892,11 @@
     if (ha->type==GDT_EISA && ha->cmd_cnt>0) 
         return 0;
 
+    mode64 = (ha->cache_feat & GDT_64BIT) ? TRUE : FALSE;
+    /* test for READ_16, WRITE_16 if !mode64 ? ---
+       not required, should not occur due to error return on 
+       READ_CAPACITY_16 */
+
     cmdp->Service = CACHESERVICE;
     cmdp->RequestBuffer = scp;
     /* search free command index */
@@ -2790,7 +2909,7 @@
         gdth_set_sema0(hanum);
 
     /* fill command */
-    read_write = FALSE;
+    read_write = 0;
     if (scp->SCp.sent_command != -1) 
         cmdp->OpCode = scp->SCp.sent_command;   /* special cache cmd. */
     else if (scp->cmnd[0] == RESERVE) 
@@ -2804,76 +2923,173 @@
             cmdp->OpCode = GDT_UNMOUNT;
         else
             cmdp->OpCode = GDT_FLUSH;
-    } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10) {
-        read_write = TRUE;
+    } else if (scp->cmnd[0] == WRITE_6 || scp->cmnd[0] == WRITE_10 ||
+               scp->cmnd[0] == WRITE_12 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+               || scp->cmnd[0] == WRITE_16
+#endif
+    ) {
+        read_write = 1;
         if (gdth_write_through || ((ha->hdr[hdrive].rw_attribs & 1) && 
                                    (ha->cache_feat & GDT_WR_THROUGH)))
             cmdp->OpCode = GDT_WRITE_THR;
         else
             cmdp->OpCode = GDT_WRITE;
     } else {
-        read_write = TRUE;
+        read_write = 2;
         cmdp->OpCode = GDT_READ;
     }
-    
-    cmdp->BoardNode        = LOCALBOARD;
-    cmdp->u.cache.DeviceNo = hdrive;
-    cmdp->u.cache.BlockNo  = 1;
-    cmdp->u.cache.sg_canz  = 0;
+
+    cmdp->BoardNode = LOCALBOARD;
+    if (mode64) {
+        cmdp->u.cache64.DeviceNo = hdrive;
+        cmdp->u.cache64.BlockNo  = 1;
+        cmdp->u.cache64.sg_canz  = 0;
+    } else {
+        cmdp->u.cache.DeviceNo = hdrive;
+        cmdp->u.cache.BlockNo  = 1;
+        cmdp->u.cache.sg_canz  = 0;
+    }
 
     if (read_write) {
-        if (scp->cmd_len != 6) {
+        if (scp->cmd_len == 16) {
+            memcpy(&no, &scp->cmnd[2], sizeof(ulong64));
+            blockno = be64_to_cpu(no);
+            memcpy(&cnt, &scp->cmnd[10], sizeof(ulong32));
+            blockcnt = be32_to_cpu(cnt);
+        } else if (scp->cmd_len == 10) {
             memcpy(&no, &scp->cmnd[2], sizeof(ulong32));
-            cmdp->u.cache.BlockNo = ntohl(no);
+            blockno = be32_to_cpu(no);
             memcpy(&cnt, &scp->cmnd[7], sizeof(ushort));
-            cmdp->u.cache.BlockCnt = (ulong32)ntohs(cnt);
+            blockcnt = be16_to_cpu(cnt);
         } else {
             memcpy(&no, &scp->cmnd[0], sizeof(ulong32));
-            cmdp->u.cache.BlockNo = ntohl(no) & 0x001fffffUL;
-            cmdp->u.cache.BlockCnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
+            blockno = be32_to_cpu(no) & 0x001fffffUL;
+            blockcnt= scp->cmnd[4]==0 ? 0x100 : scp->cmnd[4];
+        }
+        if (mode64) {
+            cmdp->u.cache64.BlockNo = blockno;
+            cmdp->u.cache64.BlockCnt = blockcnt;
+        } else {
+            cmdp->u.cache.BlockNo = (ulong32)blockno;
+            cmdp->u.cache.BlockCnt = blockcnt;
         }
 
         if (scp->use_sg) {
-            cmdp->u.cache.DestAddr= 0xffffffff;
             sl = (struct scatterlist *)scp->request_buffer;
-            for (i=0; i<scp->use_sg; ++i,++sl) {
-                cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
-                cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
+            sgcnt = scp->use_sg;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
+            scp->SCp.Status = GDTH_MAP_SG;
+            scp->SCp.Message = (read_write == 1 ? 
+                PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);   
+            sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
+            if (mode64) {
+                cmdp->u.cache64.DestAddr= (ulong64)-1;
+                cmdp->u.cache64.sg_canz = sgcnt;
+                for (i=0; i<sgcnt; ++i,++sl) {
+                    cmdp->u.cache64.sg_lst[i].sg_ptr = sg_dma_address(sl);
+#ifdef GDTH_DMA_STATISTICS
+                    if (cmdp->u.cache64.sg_lst[i].sg_ptr > (ulong64)0xffffffff)
+                        ha->dma64_cnt++;
+                    else
+                        ha->dma32_cnt++;
+#endif
+                    cmdp->u.cache64.sg_lst[i].sg_len = sg_dma_len(sl);
+                }
+            } else {
+                cmdp->u.cache.DestAddr= 0xffffffff;
+                cmdp->u.cache.sg_canz = sgcnt;
+                for (i=0; i<sgcnt; ++i,++sl) {
+                    cmdp->u.cache.sg_lst[i].sg_ptr = sg_dma_address(sl);
+#ifdef GDTH_DMA_STATISTICS
+                    ha->dma32_cnt++;
+#endif
+                    cmdp->u.cache.sg_lst[i].sg_len = sg_dma_len(sl);
+                }
+            }
+#else
+            if (mode64) {
+                cmdp->u.cache64.DestAddr= (ulong64)-1;
+                cmdp->u.cache64.sg_canz = sgcnt;
+                for (i=0; i<sgcnt; ++i,++sl) {
+                    cmdp->u.cache64.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
+                    cmdp->u.cache64.sg_lst[i].sg_len = (ulong32)sl->length;
+                }
+            } else {
+                cmdp->u.cache.DestAddr= 0xffffffff;
+                cmdp->u.cache.sg_canz = sgcnt;
+                for (i=0; i<sgcnt; ++i,++sl) {
+                    cmdp->u.cache.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
+                    cmdp->u.cache.sg_lst[i].sg_len = (ulong32)sl->length;
+                }
             }
-            cmdp->u.cache.sg_canz = (ulong32)i;
+#endif
 
 #ifdef GDTH_STATISTICS
-            if (max_sg < (ulong32)i) {
-                max_sg = (ulong32)i;
-                TRACE3(("GDT: max_sg = %d\n",i));
+            if (max_sg < (ulong32)sgcnt) {
+                max_sg = (ulong32)sgcnt;
+                TRACE3(("GDT: max_sg = %d\n",max_sg));
             }
 #endif
-            if (i<GDTH_MAXSG)
-                cmdp->u.cache.sg_lst[i].sg_len = 0;
+
         } else {
-            if (ha->cache_feat & SCATTER_GATHER) {
-                cmdp->u.cache.DestAddr = 0xffffffff;
-                cmdp->u.cache.sg_canz = 1;
-                cmdp->u.cache.sg_lst[0].sg_ptr = 
-                    virt_to_bus(scp->request_buffer);
-                cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen;
-                cmdp->u.cache.sg_lst[1].sg_len = 0;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
+            scp->SCp.Status = GDTH_MAP_SINGLE;
+            scp->SCp.Message = (read_write == 1 ? 
+                PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+            page = virt_to_page(scp->request_buffer);
+            offset = (ulong)scp->request_buffer & ~PAGE_MASK;
+            phys_addr = pci_map_page(ha->pdev,page,offset,
+                                     scp->request_bufflen,scp->SCp.Message);
+            scp->SCp.dma_handle = phys_addr;
+#else
+            phys_addr = virt_to_bus(scp->request_buffer);
+#endif
+            if (mode64) {
+                if (ha->cache_feat & SCATTER_GATHER) {
+                    cmdp->u.cache64.DestAddr = (ulong64)-1;
+                    cmdp->u.cache64.sg_canz = 1;
+                    cmdp->u.cache64.sg_lst[0].sg_ptr = phys_addr;
+                    cmdp->u.cache64.sg_lst[0].sg_len = scp->request_bufflen;
+                    cmdp->u.cache64.sg_lst[1].sg_len = 0;
+                } else {
+                    cmdp->u.cache64.DestAddr  = phys_addr;
+                    cmdp->u.cache64.sg_canz= 0;
+                }
             } else {
-                cmdp->u.cache.DestAddr  = virt_to_bus(scp->request_buffer);
-                cmdp->u.cache.sg_canz= 0;
+                if (ha->cache_feat & SCATTER_GATHER) {
+                    cmdp->u.cache.DestAddr = 0xffffffff;
+                    cmdp->u.cache.sg_canz = 1;
+                    cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr;
+                    cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen;
+                    cmdp->u.cache.sg_lst[1].sg_len = 0;
+                } else {
+                    cmdp->u.cache.DestAddr  = phys_addr;
+                    cmdp->u.cache.sg_canz= 0;
+                }
             }
         }
     }
-    TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
-           cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz,
-           cmdp->u.cache.sg_lst[0].sg_ptr,
-           cmdp->u.cache.sg_lst[0].sg_len));
-    TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n",
-           cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt));
-
     /* evaluate command size, check space */
-    ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) +
-        (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str);
+    if (mode64) {
+        TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
+               cmdp->u.cache64.DestAddr,cmdp->u.cache64.sg_canz,
+               cmdp->u.cache64.sg_lst[0].sg_ptr,
+               cmdp->u.cache64.sg_lst[0].sg_len));
+        TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n",
+               cmdp->OpCode,cmdp->u.cache64.BlockNo,cmdp->u.cache64.BlockCnt));
+        ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) +
+            (ushort)cmdp->u.cache64.sg_canz * sizeof(gdth_sg64_str);
+    } else {
+        TRACE(("cache cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
+               cmdp->u.cache.DestAddr,cmdp->u.cache.sg_canz,
+               cmdp->u.cache.sg_lst[0].sg_ptr,
+               cmdp->u.cache.sg_lst[0].sg_len));
+        TRACE(("cache cmd: cmd %d blockno. %d, blockcnt %d\n",
+               cmdp->OpCode,cmdp->u.cache.BlockNo,cmdp->u.cache.BlockCnt));
+        ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) +
+            (ushort)cmdp->u.cache.sg_canz * sizeof(gdth_sg_str);
+    }
     if (ha->cmd_len & 3)
         ha->cmd_len += (4 - (ha->cmd_len & 3));
 
@@ -2897,12 +3113,22 @@
     register gdth_cmd_str *cmdp;
     struct scatterlist *sl;
     ushort i;
-    int cmd_index;
+    dma_addr_t phys_addr, sense_paddr;
+    int cmd_index, sgcnt, mode64;
     unchar t,l;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
+    struct page *page;
+    ulong offset;
+#endif
 
     ha = HADATA(gdth_ctr_tab[hanum]);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    t = scp->device->id;
+    l = scp->device->lun;
+#else
     t = scp->target;
     l = scp->lun;
+#endif
     cmdp = ha->pccb;
     TRACE(("gdth_fill_raw_cmd() cmd 0x%x bus %d ID %d LUN %d\n",
            scp->cmnd[0],b,t,l));
@@ -2910,6 +3136,8 @@
     if (ha->type==GDT_EISA && ha->cmd_cnt>0) 
         return 0;
 
+    mode64 = (ha->raw_feat & GDT_64BIT) ? TRUE : FALSE;
+
     cmdp->Service = SCSIRAWSERVICE;
     cmdp->RequestBuffer = scp;
     /* search free command index */
@@ -2925,68 +3153,176 @@
     if (scp->SCp.sent_command != -1) {
         cmdp->OpCode           = scp->SCp.sent_command; /* special raw cmd. */
         cmdp->BoardNode        = LOCALBOARD;
-        cmdp->u.raw.direction  = (scp->SCp.phase >> 8);
-        TRACE2(("special raw cmd 0x%x param 0x%x\n", 
-                cmdp->OpCode, cmdp->u.raw.direction));
+        if (mode64) {
+            cmdp->u.raw64.direction = (scp->SCp.phase >> 8);
+            TRACE2(("special raw cmd 0x%x param 0x%x\n", 
+                    cmdp->OpCode, cmdp->u.raw64.direction));
+            /* evaluate command size */
+            ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst);
+        } else {
+            cmdp->u.raw.direction  = (scp->SCp.phase >> 8);
+            TRACE2(("special raw cmd 0x%x param 0x%x\n", 
+                    cmdp->OpCode, cmdp->u.raw.direction));
+            /* evaluate command size */
+            ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst);
+        }
 
-        /* evaluate command size */
-        ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst);
     } else {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
+        page = virt_to_page(scp->sense_buffer);
+        offset = (ulong)scp->sense_buffer & ~PAGE_MASK;
+        sense_paddr = pci_map_page(ha->pdev,page,offset,
+                                   16,PCI_DMA_FROMDEVICE);
+        scp->SCp.buffer = (struct scatterlist *)((ulong32)sense_paddr);
+        /* high part, if 64bit */
+        scp->host_scribble = (char *)(ulong32)((ulong64)sense_paddr >> 32);
+#else
+        sense_paddr = virt_to_bus(scp->sense_buffer);
+#endif
         cmdp->OpCode           = GDT_WRITE;             /* always */
         cmdp->BoardNode        = LOCALBOARD;
-        cmdp->u.raw.reserved   = 0;
-        cmdp->u.raw.mdisc_time = 0;
-        cmdp->u.raw.mcon_time  = 0;
-        cmdp->u.raw.clen       = scp->cmd_len;
-        cmdp->u.raw.target     = t;
-        cmdp->u.raw.lun        = l;
-        cmdp->u.raw.bus        = b;
-        cmdp->u.raw.priority   = 0;
-        cmdp->u.raw.link_p     = 0;
-        cmdp->u.raw.sdlen      = scp->request_bufflen;
-        cmdp->u.raw.sense_len  = 16;
-        cmdp->u.raw.sense_data = virt_to_bus(scp->sense_buffer);
-        cmdp->u.raw.direction  = 
-            gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
-        memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
+        if (mode64) { 
+            cmdp->u.raw64.reserved   = 0;
+            cmdp->u.raw64.mdisc_time = 0;
+            cmdp->u.raw64.mcon_time  = 0;
+            cmdp->u.raw64.clen       = scp->cmd_len;
+            cmdp->u.raw64.target     = t;
+            cmdp->u.raw64.lun        = l;
+            cmdp->u.raw64.bus        = b;
+            cmdp->u.raw64.priority   = 0;
+            cmdp->u.raw64.sdlen      = scp->request_bufflen;
+            cmdp->u.raw64.sense_len  = 16;
+            cmdp->u.raw64.sense_data = sense_paddr;
+            cmdp->u.raw64.direction  = 
+                gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
+            memcpy(cmdp->u.raw64.cmd,scp->cmnd,16);
+        } else {
+            cmdp->u.raw.reserved   = 0;
+            cmdp->u.raw.mdisc_time = 0;
+            cmdp->u.raw.mcon_time  = 0;
+            cmdp->u.raw.clen       = scp->cmd_len;
+            cmdp->u.raw.target     = t;
+            cmdp->u.raw.lun        = l;
+            cmdp->u.raw.bus        = b;
+            cmdp->u.raw.priority   = 0;
+            cmdp->u.raw.link_p     = 0;
+            cmdp->u.raw.sdlen      = scp->request_bufflen;
+            cmdp->u.raw.sense_len  = 16;
+            cmdp->u.raw.sense_data = sense_paddr;
+            cmdp->u.raw.direction  = 
+                gdth_direction_tab[scp->cmnd[0]]==DOU ? GDTH_DATA_OUT:GDTH_DATA_IN;
+            memcpy(cmdp->u.raw.cmd,scp->cmnd,12);
+        }
 
         if (scp->use_sg) {
-            cmdp->u.raw.sdata  = 0xffffffff;
             sl = (struct scatterlist *)scp->request_buffer;
-            for (i=0; i<scp->use_sg; ++i,++sl) {
-                cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
-                cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
+            sgcnt = scp->use_sg;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
+            scp->SCp.Status = GDTH_MAP_SG;
+            scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; 
+            sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message);
+            if (mode64) {
+                cmdp->u.raw64.sdata = (ulong64)-1;
+                cmdp->u.raw64.sg_ranz = sgcnt;
+                for (i=0; i<sgcnt; ++i,++sl) {
+                    cmdp->u.raw64.sg_lst[i].sg_ptr = sg_dma_address(sl);
+#ifdef GDTH_DMA_STATISTICS
+                    if (cmdp->u.raw64.sg_lst[i].sg_ptr > (ulong64)0xffffffff)
+                        ha->dma64_cnt++;
+                    else
+                        ha->dma32_cnt++;
+#endif
+                    cmdp->u.raw64.sg_lst[i].sg_len = sg_dma_len(sl);
+                }
+            } else {
+                cmdp->u.raw.sdata = 0xffffffff;
+                cmdp->u.raw.sg_ranz = sgcnt;
+                for (i=0; i<sgcnt; ++i,++sl) {
+                    cmdp->u.raw.sg_lst[i].sg_ptr = sg_dma_address(sl);
+#ifdef GDTH_DMA_STATISTICS
+                    ha->dma32_cnt++;
+#endif
+                    cmdp->u.raw.sg_lst[i].sg_len = sg_dma_len(sl);
+                }
             }
-            cmdp->u.raw.sg_ranz = (ulong32)i;
+#else
+            if (mode64) {
+                cmdp->u.raw64.sdata = (ulong64)-1;
+                cmdp->u.raw64.sg_ranz = sgcnt;
+                for (i=0; i<sgcnt; ++i,++sl) {
+                    cmdp->u.raw64.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
+                    cmdp->u.raw64.sg_lst[i].sg_len = (ulong32)sl->length;
+                }
+            } else {
+                cmdp->u.raw.sdata = 0xffffffff;
+                cmdp->u.raw.sg_ranz = sgcnt;
+                for (i=0; i<sgcnt; ++i,++sl) {
+                    cmdp->u.raw.sg_lst[i].sg_ptr = virt_to_bus(sl->address);
+                    cmdp->u.raw.sg_lst[i].sg_len = (ulong32)sl->length;
+                }
+            }
+#endif
 
 #ifdef GDTH_STATISTICS
-            if (max_sg < (ulong32)i) {
-                max_sg = (ulong32)i;
-                TRACE3(("GDT: max_sg = %d\n",i));
+            if (max_sg < sgcnt) {
+                max_sg = sgcnt;
+                TRACE3(("GDT: max_sg = %d\n",sgcnt));
             }
 #endif
-            if (i<GDTH_MAXSG)
-                cmdp->u.raw.sg_lst[i].sg_len = 0;
+
         } else {
-            if (ha->raw_feat & SCATTER_GATHER) {
-                cmdp->u.raw.sdata  = 0xffffffff;
-                cmdp->u.raw.sg_ranz= 1;
-                cmdp->u.raw.sg_lst[0].sg_ptr = virt_to_bus(scp->request_buffer);
-                cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
-                cmdp->u.raw.sg_lst[1].sg_len = 0;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
+            scp->SCp.Status = GDTH_MAP_SINGLE;
+            scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; 
+            page = virt_to_page(scp->request_buffer);
+            offset = (ulong)scp->request_buffer & ~PAGE_MASK;
+            phys_addr = pci_map_page(ha->pdev,page,offset,
+                                     scp->request_bufflen,scp->SCp.Message);
+            scp->SCp.dma_handle = phys_addr;
+#else
+            phys_addr = virt_to_bus(scp->request_buffer);
+#endif
+            if (mode64) {
+                if (ha->raw_feat & SCATTER_GATHER) {
+                    cmdp->u.raw64.sdata  = (ulong64)-1;
+                    cmdp->u.raw64.sg_ranz= 1;
+                    cmdp->u.raw64.sg_lst[0].sg_ptr = phys_addr;
+                    cmdp->u.raw64.sg_lst[0].sg_len = scp->request_bufflen;
+                    cmdp->u.raw64.sg_lst[1].sg_len = 0;
+                } else {
+                    cmdp->u.raw64.sdata  = phys_addr;
+                    cmdp->u.raw64.sg_ranz= 0;
+                }
             } else {
-                cmdp->u.raw.sdata  = virt_to_bus(scp->request_buffer);
-                cmdp->u.raw.sg_ranz= 0;
+                if (ha->raw_feat & SCATTER_GATHER) {
+                    cmdp->u.raw.sdata  = 0xffffffff;
+                    cmdp->u.raw.sg_ranz= 1;
+                    cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr;
+                    cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen;
+                    cmdp->u.raw.sg_lst[1].sg_len = 0;
+                } else {
+                    cmdp->u.raw.sdata  = phys_addr;
+                    cmdp->u.raw.sg_ranz= 0;
+                }
             }
         }
-        TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
-               cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz,
-               cmdp->u.raw.sg_lst[0].sg_ptr,
-               cmdp->u.raw.sg_lst[0].sg_len));
-
-        /* evaluate command size */
-        ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) +
-            (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str);
+        if (mode64) {
+            TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
+                   cmdp->u.raw64.sdata,cmdp->u.raw64.sg_ranz,
+                   cmdp->u.raw64.sg_lst[0].sg_ptr,
+                   cmdp->u.raw64.sg_lst[0].sg_len));
+            /* evaluate command size */
+            ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) +
+                (ushort)cmdp->u.raw64.sg_ranz * sizeof(gdth_sg64_str);
+        } else {
+            TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n",
+                   cmdp->u.raw.sdata,cmdp->u.raw.sg_ranz,
+                   cmdp->u.raw.sg_lst[0].sg_ptr,
+                   cmdp->u.raw.sg_lst[0].sg_len));
+            /* evaluate command size */
+            ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) +
+                (ushort)cmdp->u.raw.sg_ranz * sizeof(gdth_sg_str);
+        }
     }
     /* check space */
     if (ha->cmd_len & 3)
@@ -3036,15 +3372,23 @@
     if (cmdp->OpCode == GDT_IOCTL) {
         TRACE2(("IOCTL\n"));
         ha->cmd_len = 
-            GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong32);
+            GDTOFFSOF(gdth_cmd_str,u.ioctl.p_param) + sizeof(ulong64);
     } else if (cmdp->Service == CACHESERVICE) {
         TRACE2(("cache command %d\n",cmdp->OpCode));
-        ha->cmd_len = 
-            GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str);
+        if (ha->cache_feat & GDT_64BIT)
+            ha->cmd_len = 
+                GDTOFFSOF(gdth_cmd_str,u.cache64.sg_lst) + sizeof(gdth_sg64_str);
+        else
+            ha->cmd_len = 
+                GDTOFFSOF(gdth_cmd_str,u.cache.sg_lst) + sizeof(gdth_sg_str);
     } else if (cmdp->Service == SCSIRAWSERVICE) {
-        TRACE2(("raw command %d/%d\n",cmdp->OpCode,cmdp->u.raw.cmd[0]));
-        ha->cmd_len = 
-            GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str);
+        TRACE2(("raw command %d\n",cmdp->OpCode));
+        if (ha->raw_feat & GDT_64BIT)
+            ha->cmd_len = 
+                GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst) + sizeof(gdth_sg64_str);
+        else
+            ha->cmd_len = 
+                GDTOFFSOF(gdth_cmd_str,u.raw.sg_lst) + sizeof(gdth_sg_str);
     }
 
     if (ha->cmd_len & 3)
@@ -3187,14 +3531,14 @@
 
 /* SCSI interface functions */
 
-#if LINUX_VERSION_CODE >= 0x010346
-static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static irqreturn_t gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
 #else
-static void gdth_interrupt(int irq,struct pt_regs *regs)
+static void gdth_interrupt(int irq,void *dev_id,struct pt_regs *regs)
 #endif
 {
     register gdth_ha_str *ha;
-    gdt6m_dpram_str *dp6m_ptr;
+    gdt6m_dpram_str *dp6m_ptr = NULL;
     gdt6_dpram_str *dp6_ptr;
     gdt2_dpram_str *dp2_ptr;
     Scsi_Cmnd *scp;
@@ -3202,13 +3546,23 @@
     unchar IStatus;
     ushort Service;
     ulong flags = 0;
+#ifdef INT_COAL
+    int coalesced = FALSE;
+    int next = FALSE;
+    gdth_coal_status *pcs = NULL;
+    int act_int_coal = 0;       
+#endif
 
     TRACE(("gdth_interrupt() IRQ %d\n",irq));
 
     /* if polling and not from gdth_wait() -> return */
     if (gdth_polling) {
         if (!gdth_from_wait) {
-            return;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            return IRQ_HANDLED;
+#else
+            return;             
+#endif
         }
     }
 
@@ -3221,163 +3575,261 @@
         /* spurious interrupt */
         if (!gdth_polling)
             GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-        return;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            return IRQ_HANDLED;
+#else
+            return;             
+#endif
     }
+    ha = HADATA(gdth_ctr_tab[hanum]);
 
 #ifdef GDTH_STATISTICS
     ++act_ints;
 #endif
-    
-    ha = HADATA(gdth_ctr_tab[hanum]);
-    if (ha->type == GDT_EISA) {
-        if (IStatus & 0x80) {                       /* error flag */
-            IStatus &= ~0x80;
-            ha->status = inw(ha->bmic + MAILBOXREG+8);
-            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
-        } else                                      /* no error */
-            ha->status = S_OK;
-        ha->info = inl(ha->bmic + MAILBOXREG+12);
-        ha->service = inw(ha->bmic + MAILBOXREG+10);
-        ha->info2 = inl(ha->bmic + MAILBOXREG+4);
-
-        outb(0xff, ha->bmic + EDOORREG);            /* acknowledge interrupt */
-        outb(0x00, ha->bmic + SEMA1REG);            /* reset status semaphore */
-    } else if (ha->type == GDT_ISA) {
-        dp2_ptr = (gdt2_dpram_str *)ha->brd;
-        if (IStatus & 0x80) {                       /* error flag */
-            IStatus &= ~0x80;
-            ha->status = gdth_readw(&dp2_ptr->u.ic.Status);
-            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
-        } else                                      /* no error */
-            ha->status = S_OK;
-        ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]);
-        ha->service = gdth_readw(&dp2_ptr->u.ic.Service);
-        ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
-
-        gdth_writeb(0xff, &dp2_ptr->io.irqdel);     /* acknowledge interrupt */
-        gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);   /* reset command index */
-        gdth_writeb(0, &dp2_ptr->io.Sema1);         /* reset status semaphore */
-    } else if (ha->type == GDT_PCI) {
-        dp6_ptr = (gdt6_dpram_str *)ha->brd;
-        if (IStatus & 0x80) {                       /* error flag */
-            IStatus &= ~0x80;
-            ha->status = gdth_readw(&dp6_ptr->u.ic.Status);
-            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
-        } else                                      /* no error */
-            ha->status = S_OK;
-        ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]);
-        ha->service = gdth_readw(&dp6_ptr->u.ic.Service);
-        ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
-
-        gdth_writeb(0xff, &dp6_ptr->io.irqdel);     /* acknowledge interrupt */
-        gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);   /* reset command index */
-        gdth_writeb(0, &dp6_ptr->io.Sema1);         /* reset status semaphore */
-    } else if (ha->type == GDT_PCINEW) {
-        if (IStatus & 0x80) {                       /* error flag */
-            IStatus &= ~0x80;
-            ha->status = inw(PTR2USHORT(&ha->plx->status));
-            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
-        } else
-            ha->status = S_OK;
-        ha->info = inl(PTR2USHORT(&ha->plx->info[0]));
-        ha->service = inw(PTR2USHORT(&ha->plx->service));
-        ha->info2 = inl(PTR2USHORT(&ha->plx->info[1]));
 
-        outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); 
-        outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); 
-    } else if (ha->type == GDT_PCIMPR) {
-        dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
-        if (IStatus & 0x80) {                       /* error flag */
-            IStatus &= ~0x80;
-            ha->status = gdth_readw(&dp6m_ptr->i960r.status);
-            TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
-        } else                                      /* no error */
-            ha->status = S_OK;
-        ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]);
-        ha->service = gdth_readw(&dp6m_ptr->i960r.service);
-        ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
+#ifdef INT_COAL
+    /* See if the fw is returning coalesced status */
+    if (IStatus == COALINDEX) {
+        /* Coalesced status.  Setup the initial status 
+           buffer pointer and flags */
+        pcs = ha->coal_stat;
+        coalesced = TRUE;        
+        next = TRUE;
+    }
 
-        /* event string */
-        if (IStatus == ASYNCINDEX) {
-            if (ha->service != SCREENSERVICE &&
-                (ha->fw_vers & 0xff) >= 0x1a) {
-                ha->dvr.severity =   
-                    gdth_readb(&((gdt6m_dpram_str *)ha->brd)->i960r.severity);
-                for (i = 0; i < 256; ++i) {
-                    ha->dvr.event_string[i] = gdth_readb
-                        (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]);
-                    if (ha->dvr.event_string[i] == 0)
-                        break;
+    do {
+        if (coalesced) {
+            /* For coalesced requests all status
+               information is found in the status buffer */
+            IStatus = (unchar)(pcs->status & 0xff);
+        }
+#endif
+    
+        if (ha->type == GDT_EISA) {
+            if (IStatus & 0x80) {                       /* error flag */
+                IStatus &= ~0x80;
+                ha->status = inw(ha->bmic + MAILBOXREG+8);
+                TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
+            } else                                      /* no error */
+                ha->status = S_OK;
+            ha->info = inl(ha->bmic + MAILBOXREG+12);
+            ha->service = inw(ha->bmic + MAILBOXREG+10);
+            ha->info2 = inl(ha->bmic + MAILBOXREG+4);
+
+            outb(0xff, ha->bmic + EDOORREG);    /* acknowledge interrupt */
+            outb(0x00, ha->bmic + SEMA1REG);    /* reset status semaphore */
+        } else if (ha->type == GDT_ISA) {
+            dp2_ptr = (gdt2_dpram_str *)ha->brd;
+            if (IStatus & 0x80) {                       /* error flag */
+                IStatus &= ~0x80;
+                ha->status = gdth_readw(&dp2_ptr->u.ic.Status);
+                TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
+            } else                                      /* no error */
+                ha->status = S_OK;
+            ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]);
+            ha->service = gdth_readw(&dp2_ptr->u.ic.Service);
+            ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]);
+
+            gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */
+            gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);/* reset command index */
+            gdth_writeb(0, &dp2_ptr->io.Sema1);     /* reset status semaphore */
+        } else if (ha->type == GDT_PCI) {
+            dp6_ptr = (gdt6_dpram_str *)ha->brd;
+            if (IStatus & 0x80) {                       /* error flag */
+                IStatus &= ~0x80;
+                ha->status = gdth_readw(&dp6_ptr->u.ic.Status);
+                TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
+            } else                                      /* no error */
+                ha->status = S_OK;
+            ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]);
+            ha->service = gdth_readw(&dp6_ptr->u.ic.Service);
+            ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]);
+
+            gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */
+            gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);/* reset command index */
+            gdth_writeb(0, &dp6_ptr->io.Sema1);     /* reset status semaphore */
+        } else if (ha->type == GDT_PCINEW) {
+            if (IStatus & 0x80) {                       /* error flag */
+                IStatus &= ~0x80;
+                ha->status = inw(PTR2USHORT(&ha->plx->status));
+                TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
+            } else
+                ha->status = S_OK;
+            ha->info = inl(PTR2USHORT(&ha->plx->info[0]));
+            ha->service = inw(PTR2USHORT(&ha->plx->service));
+            ha->info2 = inl(PTR2USHORT(&ha->plx->info[1]));
+
+            outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); 
+            outb(0x00, PTR2USHORT(&ha->plx->sema1_reg)); 
+        } else if (ha->type == GDT_PCIMPR) {
+            dp6m_ptr = (gdt6m_dpram_str *)ha->brd;
+            if (IStatus & 0x80) {                       /* error flag */
+                IStatus &= ~0x80;
+#ifdef INT_COAL
+                if (coalesced)
+                    ha->status = pcs->ext_status && 0xffff;
+                else 
+#endif
+                    ha->status = gdth_readw(&dp6m_ptr->i960r.status);
+                TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status));
+            } else                                      /* no error */
+                ha->status = S_OK;
+#ifdef INT_COAL
+            /* get information */
+            if (coalesced) {    
+                ha->info = pcs->info0;
+                ha->info2 = pcs->info1;
+                ha->service = (pcs->ext_status >> 16) && 0xffff;
+            } else
+#endif
+            {
+                ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]);
+                ha->service = gdth_readw(&dp6m_ptr->i960r.service);
+                ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]);
+            }
+            /* event string */
+            if (IStatus == ASYNCINDEX) {
+                if (ha->service != SCREENSERVICE &&
+                    (ha->fw_vers & 0xff) >= 0x1a) {
+                    ha->dvr.severity = gdth_readb
+                        (&((gdt6m_dpram_str *)ha->brd)->i960r.severity);
+                    for (i = 0; i < 256; ++i) {
+                        ha->dvr.event_string[i] = gdth_readb
+                            (&((gdt6m_dpram_str *)ha->brd)->i960r.evt_str[i]);
+                        if (ha->dvr.event_string[i] == 0)
+                            break;
+                    }
                 }
             }
+#ifdef INT_COAL
+            /* Make sure that non coalesced interrupts get cleared
+               before being handled by gdth_async_event/gdth_sync_event */
+            if (!coalesced)
+#endif                          
+            {
+                gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+                gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg);
+            }
+        } else {
+            TRACE2(("gdth_interrupt() unknown controller type\n"));
+            if (!gdth_polling)
+                GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            return IRQ_HANDLED;
+#else
+            return;             
+#endif
         }
-        gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
-        gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg);
-    } else {
-        TRACE2(("gdth_interrupt() unknown controller type\n"));
-        if (!gdth_polling)
-            GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-        return;
-    }
 
-    TRACE(("gdth_interrupt() index %d stat %d info %d\n",
-           IStatus,ha->status,ha->info));
+        TRACE(("gdth_interrupt() index %d stat %d info %d\n",
+               IStatus,ha->status,ha->info));
 
-    if (gdth_from_wait) {
-        wait_hanum = hanum;
-        wait_index = (int)IStatus;
-    }
+        if (gdth_from_wait) {
+            wait_hanum = hanum;
+            wait_index = (int)IStatus;
+        }
 
-    if (IStatus == ASYNCINDEX) {
-        TRACE2(("gdth_interrupt() async. event\n"));
-        gdth_async_event(hanum);
-        if (!gdth_polling)
-            GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-        gdth_next(hanum);
-        return;
-    } 
+        if (IStatus == ASYNCINDEX) {
+            TRACE2(("gdth_interrupt() async. event\n"));
+            gdth_async_event(hanum);
+            if (!gdth_polling)
+                GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+            gdth_next(hanum);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            return IRQ_HANDLED;
+#else
+            return;             
+#endif
+        } 
+
+        if (IStatus == SPEZINDEX) {
+            TRACE2(("Service unknown or not initialized !\n"));
+            ha->dvr.size = sizeof(ha->dvr.eu.driver);
+            ha->dvr.eu.driver.ionode = hanum;
+            gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr);
+            if (!gdth_polling)
+                GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            return IRQ_HANDLED;
+#else
+            return;             
+#endif
+        }
+        scp     = ha->cmd_tab[IStatus-2].cmnd;
+        Service = ha->cmd_tab[IStatus-2].service;
+        ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND;
+        if (scp == UNUSED_CMND) {
+            TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
+            ha->dvr.size = sizeof(ha->dvr.eu.driver);
+            ha->dvr.eu.driver.ionode = hanum;
+            ha->dvr.eu.driver.index = IStatus;
+            gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
+            if (!gdth_polling)
+                GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            return IRQ_HANDLED;
+#else
+            return;             
+#endif
+        }
+        if (scp == INTERNAL_CMND) {
+            TRACE(("gdth_interrupt() answer to internal command\n"));
+            if (!gdth_polling)
+                GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            return IRQ_HANDLED;
+#else
+            return;             
+#endif
+        }
 
-    if (IStatus == SPEZINDEX) {
-        TRACE2(("Service unknown or not initialized !\n"));
-        ha->dvr.size = sizeof(ha->dvr.eu.driver);
-        ha->dvr.eu.driver.ionode = hanum;
-        gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr);
-        if (!gdth_polling)
-            GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-        return;
-    }
-    scp     = ha->cmd_tab[IStatus-2].cmnd;
-    Service = ha->cmd_tab[IStatus-2].service;
-    ha->cmd_tab[IStatus-2].cmnd = UNUSED_CMND;
-    if (scp == UNUSED_CMND) {
-        TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus));
-        ha->dvr.size = sizeof(ha->dvr.eu.driver);
-        ha->dvr.eu.driver.ionode = hanum;
-        ha->dvr.eu.driver.index = IStatus;
-        gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr);
-        if (!gdth_polling)
-            GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-        return;
-    }
-    if (scp == INTERNAL_CMND) {
-        TRACE(("gdth_interrupt() answer to internal command\n"));
+        TRACE(("gdth_interrupt() sync. status\n"));
+        rval = gdth_sync_event(hanum,Service,IStatus,scp);
         if (!gdth_polling)
             GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-        return;
-    }
+        if (rval == 2) {
+            gdth_putq(hanum,scp,scp->SCp.this_residual);
+        } else if (rval == 1) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            GDTH_LOCK_SCSI_DONE(scp->device->host, flags);
+            scp->scsi_done(scp);
+            GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags);
+#else
+            GDTH_LOCK_SCSI_DONE(flags);
+            scp->scsi_done(scp);
+            GDTH_UNLOCK_SCSI_DONE(flags);
+#endif
+        }
 
-    TRACE(("gdth_interrupt() sync. status\n"));
-    rval = gdth_sync_event(hanum,Service,IStatus,scp);
-    if (!gdth_polling)
-        GDTH_UNLOCK_HA((gdth_ha_str *)dev_id,flags);
-    if (rval == 2) {
-        gdth_putq(hanum,scp,scp->SCp.this_residual);
-    } else if (rval == 1) {
-        GDTH_LOCK_SCSI_DONE(flags);
-        scp->scsi_done(scp);
-        GDTH_UNLOCK_SCSI_DONE(flags);
+#ifdef INT_COAL
+        if (coalesced) {
+            /* go to the next status in the status buffer */
+            ++pcs;
+#ifdef GDTH_STATISTICS
+            ++act_int_coal;
+            if (act_int_coal > max_int_coal) {
+                max_int_coal = act_int_coal;
+                printk("GDT: max_int_coal = %d\n",(ushort)max_int_coal);
+            }
+#endif      
+            /* see if there is another status */
+            if (pcs->status == 0)    
+                /* Stop the coalesce loop */
+                next = FALSE;
+        }
+    } while (next);
+
+    /* coalescing only for new GDT_PCIMPR controllers available */      
+    if (ha->type == GDT_PCIMPR && coalesced) {
+        gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg);
+        gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg);
     }
+#endif
+
     gdth_next(hanum);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    return IRQ_HANDLED;
+#endif
 }
 
 static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp)
@@ -3385,7 +3837,7 @@
     register gdth_ha_str *ha;
     gdth_msg_str *msg;
     gdth_cmd_str *cmdp;
-    unchar b;
+    unchar b, t;
 
     ha   = HADATA(gdth_ctr_tab[hanum]);
     cmdp = ha->pccb;
@@ -3393,10 +3845,11 @@
            service,ha->status));
 
     if (service == SCREENSERVICE) {
-        msg  = (gdth_msg_str *)ha->pscratch;
-        ha->scratch_busy = FALSE;
+        msg  = ha->pmsg;
         TRACE(("len: %d, answer: %d, ext: %d, alen: %d\n",
                msg->msg_len,msg->msg_answer,msg->msg_ext,msg->msg_alen));
+        if (msg->msg_len > MSGLEN+1)
+            msg->msg_len = MSGLEN+1;
         if (msg->msg_len)
             if (!(msg->msg_answer && msg->msg_ext)) {
                 msg->msg_text[msg->msg_len] = '\0';
@@ -3414,11 +3867,10 @@
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
-            cmdp->u.screen.su.msg.msg_addr  = virt_to_bus(msg);
-            ha->scratch_busy = TRUE;
+            cmdp->u.screen.su.msg.msg_addr  = ha->msg_phys;
             ha->cmd_offs_dpmem = 0;
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
-                + sizeof(ulong32);
+                + sizeof(ulong64);
             ha->cmd_cnt = 0;
             gdth_copy_command(hanum);
             gdth_release_event(hanum);
@@ -3449,11 +3901,10 @@
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             cmdp->u.screen.su.msg.msg_handle= msg->msg_handle;
-            cmdp->u.screen.su.msg.msg_addr  = virt_to_bus(msg);
-            ha->scratch_busy = TRUE;
+            cmdp->u.screen.su.msg.msg_addr  = ha->msg_phys;
             ha->cmd_offs_dpmem = 0;
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
-                + sizeof(ulong32);
+                + sizeof(ulong64);
             ha->cmd_cnt = 0;
             gdth_copy_command(hanum);
             gdth_release_event(hanum);
@@ -3462,11 +3913,39 @@
         printk("\n");
 
     } else {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+        t = scp->device->id;
+#else
         b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+        t = scp->target;
+#endif
         if (scp->SCp.sent_command == -1 && b != ha->virt_bus) {
-            ha->raw[BUS_L2P(ha,b)].io_cnt[scp->target]--;
+            ha->raw[BUS_L2P(ha,b)].io_cnt[t]--;
         }
         /* cache or raw service */
+        if (ha->status == S_BSY) {
+            TRACE2(("Controller busy -> retry !\n"));
+            if (scp->SCp.sent_command == GDT_MOUNT)
+                scp->SCp.sent_command = GDT_CLUST_INFO;
+            /* retry */
+            return 2;
+        }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,13)
+        if (scp->SCp.Status == GDTH_MAP_SG) 
+            pci_unmap_sg(ha->pdev,scp->request_buffer,
+                         scp->use_sg,scp->SCp.Message);
+        else if (scp->SCp.Status == GDTH_MAP_SINGLE) 
+            pci_unmap_page(ha->pdev,scp->SCp.dma_handle,
+                           scp->request_bufflen,scp->SCp.Message);
+        if (scp->SCp.buffer) {
+            dma_addr_t addr;
+            addr = (dma_addr_t)(ulong32)scp->SCp.buffer;
+            if (scp->host_scribble)
+                addr += (dma_addr_t)((ulong64)(ulong32)scp->host_scribble << 32);               
+            pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE);
+        }
+#endif
         if (ha->status == S_OK) {
             scp->SCp.Status = S_OK;
             scp->SCp.Message = ha->info;
@@ -3475,12 +3954,12 @@
                         scp->SCp.sent_command));
                 /* special commands GDT_CLUST_INFO/GDT_MOUNT ? */
                 if (scp->SCp.sent_command == GDT_CLUST_INFO) {
-                    ha->hdr[scp->target].cluster_type = (unchar)ha->info;
-                    if (!(ha->hdr[scp->target].cluster_type & 
+                    ha->hdr[t].cluster_type = (unchar)ha->info;
+                    if (!(ha->hdr[t].cluster_type & 
                         CLUSTER_MOUNTED)) {
                         /* NOT MOUNTED -> MOUNT */
                         scp->SCp.sent_command = GDT_MOUNT;
-                        if (ha->hdr[scp->target].cluster_type & 
+                        if (ha->hdr[t].cluster_type & 
                             CLUSTER_RESERVED) {
                             /* cluster drive RESERVED (on the other node) */
                             scp->SCp.phase = -2;      /* reservation conflict */
@@ -3490,11 +3969,11 @@
                     }
                 } else {
                     if (scp->SCp.sent_command == GDT_MOUNT) {
-                        ha->hdr[scp->target].cluster_type |= CLUSTER_MOUNTED;
-                        ha->hdr[scp->target].media_changed = TRUE;
+                        ha->hdr[t].cluster_type |= CLUSTER_MOUNTED;
+                        ha->hdr[t].media_changed = TRUE;
                     } else if (scp->SCp.sent_command == GDT_UNMOUNT) {
-                        ha->hdr[scp->target].cluster_type &= ~CLUSTER_MOUNTED;
-                        ha->hdr[scp->target].media_changed = TRUE;
+                        ha->hdr[t].cluster_type &= ~CLUSTER_MOUNTED;
+                        ha->hdr[t].media_changed = TRUE;
                     } 
                     scp->SCp.sent_command = -1;
                 }
@@ -3504,21 +3983,13 @@
             } else {
                 /* RESERVE/RELEASE ? */
                 if (scp->cmnd[0] == RESERVE) {
-                    ha->hdr[scp->target].cluster_type |= CLUSTER_RESERVED;
+                    ha->hdr[t].cluster_type |= CLUSTER_RESERVED;
                 } else if (scp->cmnd[0] == RELEASE) {
-                    ha->hdr[scp->target].cluster_type &= ~CLUSTER_RESERVED;
+                    ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
                 }           
                 scp->result = DID_OK << 16;
                 scp->sense_buffer[0] = 0;
             }
-        } else if (ha->status == S_BSY) {
-            TRACE2(("Controller busy -> retry !\n"));
-            scp->SCp.Status = S_BSY;
-            scp->SCp.Message = ha->info;
-            if (scp->SCp.sent_command == GDT_MOUNT)
-                scp->SCp.sent_command = GDT_CLUST_INFO;
-            /* retry */
-            return 2;
         } else {
             scp->SCp.Status = ha->status;
             scp->SCp.Message = ha->info;
@@ -3539,10 +4010,10 @@
                 scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
             } else if (service == CACHESERVICE) {
                 if (ha->status == S_CACHE_UNKNOWN &&
-                    (ha->hdr[scp->target].cluster_type & 
+                    (ha->hdr[t].cluster_type & 
                      CLUSTER_RESERVE_STATE) == CLUSTER_RESERVE_STATE) {
                     /* bus reset -> force GDT_CLUST_INFO */
-                    ha->hdr[scp->target].cluster_type &= ~CLUSTER_RESERVED;
+                    ha->hdr[t].cluster_type &= ~CLUSTER_RESERVED;
                 }
                 memset((char*)scp->sense_buffer,0,16);
                 if (ha->status == (ushort)S_CACHE_RESERV) {
@@ -3552,16 +4023,13 @@
                     scp->sense_buffer[2] = NOT_READY;
                     scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
                 }
-#if LINUX_VERSION_CODE >= 0x010300
-                if (scp->done != gdth_scsi_done)
-#endif  
-                {
+                if (scp->done != gdth_scsi_done) {
                     ha->dvr.size = sizeof(ha->dvr.eu.sync);
                     ha->dvr.eu.sync.ionode  = hanum;
                     ha->dvr.eu.sync.service = service;
                     ha->dvr.eu.sync.status  = ha->status;
                     ha->dvr.eu.sync.info    = ha->info;
-                    ha->dvr.eu.sync.hostdrive = scp->target;
+                    ha->dvr.eu.sync.hostdrive = t;
                     if (ha->status >= 0x8000)
                         gdth_store_event(ha, ES_SYNC, 0, &ha->dvr);
                     else
@@ -3651,9 +4119,9 @@
 /*31*/  "\007\000\002\012\001\013\001"
         "GDT HA %u, Fault bus %u, ID %u: old disk detected",
 /*32*/  "\007\000\002\012\001\013\001"
-        "GDT HA %u, Fault bus %u, ID %u: plugging an active disk is illegal",
+        "GDT HA %u, Fault bus %u, ID %u: plugging an active disk is invalid",
 /*33*/  "\007\000\002\012\001\013\001"
-        "GDT HA %u, Fault bus %u, ID %u: illegal device detected",
+        "GDT HA %u, Fault bus %u, ID %u: invalid device detected",
 /*34*/  "\011\000\002\012\001\013\001\006\004"
         "GDT HA %u, Fault bus %u, ID %u: insufficient disk capacity (%lu MB required)",
 /*35*/  "\007\000\002\012\001\013\001"
@@ -3744,13 +4212,11 @@
 static int gdth_async_event(int hanum)
 {
     gdth_ha_str *ha;
-    gdth_msg_str *msg;
     gdth_cmd_str *cmdp;
     int cmd_index;
 
     ha  = HADATA(gdth_ctr_tab[hanum]);
     cmdp= ha->pccb;
-    msg = (gdth_msg_str *)ha->pscratch;
     TRACE2(("gdth_async_event() ha %d serv %d\n",
             hanum,ha->service));
 
@@ -3766,11 +4232,10 @@
             cmdp->BoardNode     = LOCALBOARD;
             cmdp->u.screen.reserved  = 0;
             cmdp->u.screen.su.msg.msg_handle= MSG_INV_HANDLE;
-            cmdp->u.screen.su.msg.msg_addr  = virt_to_bus(msg);
-            ha->scratch_busy = TRUE;
+            cmdp->u.screen.su.msg.msg_addr  = ha->msg_phys;
             ha->cmd_offs_dpmem = 0;
             ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) 
-                + sizeof(ulong32);
+                + sizeof(ulong64);
             ha->cmd_cnt = 0;
             gdth_copy_command(hanum);
             if (ha->type == GDT_EISA)
@@ -3943,6 +4408,8 @@
             virt_ctr = val;
         else if (!strncmp(argv, "shared_access:", 14))
             shared_access = val;
+        else if (!strncmp(argv, "probe_eisa_isa:", 15))
+            probe_eisa_isa = val;
         else if (!strncmp(argv, "reserve_list:", 13)) {
             reserve_list[0] = val;
             for (i = 1; i < MAX_RES_ARGS; i++) {
@@ -3988,10 +4455,11 @@
 GDTH_INITFUNC(int, gdth_detect(Scsi_Host_Template *shtp))
 {
     struct Scsi_Host *shp;
+    gdth_pci_str pcistr[MAXHA];
     gdth_ha_str *ha;
     ulong32 isa_bios;
     ushort eisa_slot;
-    int i,hanum,cnt,ctr;
+    int i,hanum,cnt,ctr,err;
     unchar b;
     
  
@@ -4014,347 +4482,493 @@
     TRACE(("gdth_detect()\n"));
 
     if (disable) {
-        printk("GDT: Controller driver disabled from command line !\n");
+        printk("GDT-HA: Controller driver disabled from command line !\n");
         return 0;
     }
 
-    printk("GDT: 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();
 
-    /* scanning for controllers, at first: ISA controller */
-    for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) {
-        if (gdth_ctr_count >= MAXHA) 
-            break;
-        if (gdth_search_isa(isa_bios)) {        /* controller found */
-            shp = scsi_register(shtp,sizeof(gdth_ext_str));
-            if(shp == NULL)
-            	continue;
-            ha = HADATA(shp);
-            if (!gdth_init_isa(isa_bios,ha)) {
-                scsi_unregister(shp);
-                continue;
-            }
-#ifdef __ia64__
-            break;
-#else
-            /* controller found and initialized */
-            printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n",
-                   isa_bios,ha->irq,ha->drq);
+    /* As default we do not probe for EISA or ISA controllers */
+    if (probe_eisa_isa) {    
+        /* scanning for controllers, at first: ISA controller */
+        for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) {
+            dma_addr_t scratch_dma_handle;
+            scratch_dma_handle = 0;
 
-#if LINUX_VERSION_CODE >= 0x010346 
-            if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
-#else
-            if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) 
-#endif
-            {
-                printk("GDT-ISA: Unable to allocate IRQ\n");
-                scsi_unregister(shp);
-                continue;
-            }
-            if (request_dma(ha->drq,"gdth")) {
-                printk("GDT-ISA: Unable to allocate DMA channel\n");
-#if LINUX_VERSION_CODE >= 0x010346 
-                free_irq(ha->irq,ha);
-#else
-                free_irq(ha->irq);
-#endif
-                scsi_unregister(shp);
-                continue;
-            }
-            set_dma_mode(ha->drq,DMA_MODE_CASCADE);
-            enable_dma(ha->drq);
-            shp->unchecked_isa_dma = 1;
-            shp->irq = ha->irq;
-            shp->dma_channel = ha->drq;
-            hanum = gdth_ctr_count;         
-            gdth_ctr_tab[gdth_ctr_count++] = shp;
-            gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-
-            NUMDATA(shp)->hanum = (ushort)hanum;
-            NUMDATA(shp)->busnum= 0;
-
-            ha->pccb = CMDDATA(shp);
-#if LINUX_VERSION_CODE >= 0x020322
-            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
-                                                     GDTH_SCRATCH_ORD);
-#else
-            ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
-#endif
-            ha->scratch_busy = FALSE;
-            ha->req_first = NULL;
-            ha->tid_cnt = MAX_HDRIVES;
-            if (max_ids > 0 && max_ids < ha->tid_cnt)
-                ha->tid_cnt = max_ids;
-            for (i=0; i<GDTH_MAXCMDS; ++i)
-                ha->cmd_tab[i].cmnd = UNUSED_CMND;
-            ha->scan_mode = rescan ? 0x10 : 0;
-
-            if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
-                printk("GDT-ISA: Error during device scan\n");
-                --gdth_ctr_count;
-                --gdth_ctr_vcount;
-                if (ha->pscratch != NULL)
-#if LINUX_VERSION_CODE >= 0x020322
-                    free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
-#else
-                    scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
-#endif
-#if LINUX_VERSION_CODE >= 0x010346 
-                free_irq(ha->irq,ha);
+            if (gdth_ctr_count >= MAXHA) 
+                break;
+            if (gdth_search_isa(isa_bios)) {        /* controller found */
+                shp = scsi_register(shtp,sizeof(gdth_ext_str));
+                if (shp == NULL)
+                    continue;  
+
+                ha = HADATA(shp);
+                if (!gdth_init_isa(isa_bios,ha)) {
+                    scsi_unregister(shp);
+                    continue;
+                }
+#ifdef __ia64__
+                break;
 #else
-                free_irq(ha->irq);
+                /* controller found and initialized */
+                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,SA_INTERRUPT,"gdth",ha)) {
+                    printk("GDT-ISA: Unable to allocate IRQ\n");
+                    scsi_unregister(shp);
+                    continue;
+                }
+                if (request_dma(ha->drq,"gdth")) {
+                    printk("GDT-ISA: Unable to allocate DMA channel\n");
+                    free_irq(ha->irq,ha);
+                    scsi_unregister(shp);
+                    continue;
+                }
+                set_dma_mode(ha->drq,DMA_MODE_CASCADE);
+                enable_dma(ha->drq);
+                shp->unchecked_isa_dma = 1;
+                shp->irq = ha->irq;
+                shp->dma_channel = ha->drq;
+                hanum = gdth_ctr_count;         
+                gdth_ctr_tab[gdth_ctr_count++] = shp;
+                gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
+
+                NUMDATA(shp)->hanum = (ushort)hanum;
+                NUMDATA(shp)->busnum= 0;
+
+                ha->pccb = CMDDATA(shp);
+                ha->ccb_phys = 0L;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+                ha->pdev = NULL;
+                ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, 
+                                                    &scratch_dma_handle);
+                ha->scratch_phys = scratch_dma_handle;
+                ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), 
+                                                &scratch_dma_handle);
+                ha->msg_phys = scratch_dma_handle;
+#ifdef INT_COAL
+                ha->coal_stat = (gdth_coal_status *)
+                    pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) *
+                        MAXOFFSETS, &scratch_dma_handle);
+                ha->coal_stat_phys = scratch_dma_handle;
+#endif
+#else
+                ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+                if (ha->pscratch)
+                    ha->scratch_phys = virt_to_bus(ha->pscratch);
+                ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
+                if (ha->pmsg)
+                    ha->msg_phys = virt_to_bus(ha->pmsg);
+#ifdef INT_COAL
+                ha->coal_stat = 
+                    scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS, 
+                                     GFP_ATOMIC | GFP_DMA);
+                if (ha->coal_stat)
+                    ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
+#endif
+#endif
+                ha->scratch_busy = FALSE;
+                ha->req_first = NULL;
+                ha->tid_cnt = MAX_HDRIVES;
+                if (max_ids > 0 && max_ids < ha->tid_cnt)
+                    ha->tid_cnt = max_ids;
+                for (i=0; i<GDTH_MAXCMDS; ++i)
+                    ha->cmd_tab[i].cmnd = UNUSED_CMND;
+                ha->scan_mode = rescan ? 0x10 : 0;
+
+                if (ha->pscratch == NULL || ha->pmsg == NULL || 
+                    !gdth_search_drives(hanum)) {
+                    printk("GDT-ISA: Error during device scan\n");
+                    --gdth_ctr_count;
+                    --gdth_ctr_vcount;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#ifdef INT_COAL
+                    if (ha->coal_stat)
+                        pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
+                                            MAXOFFSETS, ha->coal_stat,
+                                            ha->coal_stat_phys);
+#endif
+                    if (ha->pscratch)
+                        pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
+                                            ha->pscratch, ha->scratch_phys);
+                    if (ha->pmsg)
+                        pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), 
+                                            ha->pmsg, ha->msg_phys);
+#else
+#ifdef INT_COAL
+                    if (ha->coal_stat)
+                        scsi_init_free((void *)ha->coal_stat, 
+                                       sizeof(gdth_coal_status) * MAXOFFSETS);
+#endif
+                    if (ha->pscratch)
+                        scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+                    if (ha->pmsg)
+                        scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
 #endif
-                scsi_unregister(shp);
-                continue;
+                    free_irq(ha->irq,ha);
+                    scsi_unregister(shp);
+                    continue;
+                }
+                if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
+                    hdr_channel = ha->bus_cnt;
+                ha->virt_bus = hdr_channel;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \
+    LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+                shp->highmem_io  = 0;
+#endif
+                if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) 
+                    shp->max_cmd_len = 16;
+#endif
+                shp->max_id      = ha->tid_cnt;
+                shp->max_lun     = MAXLUN;
+                shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
+                if (virt_ctr) {
+                    virt_ctr = 1;
+                    /* register addit. SCSI channels as virtual controllers */
+                    for (b = 1; b < ha->bus_cnt + 1; ++b) {
+                        shp = scsi_register(shtp,sizeof(gdth_num_str));
+                        shp->unchecked_isa_dma = 1;
+                        shp->irq = ha->irq;
+                        shp->dma_channel = ha->drq;
+                        gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
+                        NUMDATA(shp)->hanum = (ushort)hanum;
+                        NUMDATA(shp)->busnum = b;
+                    }
+                }  
+
+                GDTH_INIT_LOCK_HA(ha);
+                gdth_enable_int(hanum);
+#endif /* !__ia64__ */
             }
-            if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
-                hdr_channel = ha->bus_cnt;
-            ha->virt_bus = hdr_channel;
+        }
 
-#if LINUX_VERSION_CODE >= 0x020000
-            shp->max_id      = ha->tid_cnt;
-            shp->max_lun     = MAXLUN;
-            shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
-            if (virt_ctr)  
+        /* scanning for EISA controllers */
+        for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) {
+            dma_addr_t scratch_dma_handle;
+            scratch_dma_handle = 0;
+
+            if (gdth_ctr_count >= MAXHA) 
+                break;
+            if (gdth_search_eisa(eisa_slot)) {      /* controller found */
+                shp = scsi_register(shtp,sizeof(gdth_ext_str));
+                if (shp == NULL)
+                    continue;  
+
+                ha = HADATA(shp);
+                if (!gdth_init_eisa(eisa_slot,ha)) {
+                    scsi_unregister(shp);
+                    continue;
+                }
+                /* controller found and initialized */
+                printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
+                       eisa_slot>>12,ha->irq);
+
+                if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha)) {
+                    printk("GDT-EISA: Unable to allocate IRQ\n");
+                    scsi_unregister(shp);
+                    continue;
+                }
+                shp->unchecked_isa_dma = 0;
+                shp->irq = ha->irq;
+                shp->dma_channel = 0xff;
+                hanum = gdth_ctr_count;
+                gdth_ctr_tab[gdth_ctr_count++] = shp;
+                gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
+
+                NUMDATA(shp)->hanum = (ushort)hanum;
+                NUMDATA(shp)->busnum= 0;
+                TRACE2(("EISA detect Bus 0: hanum %d\n",
+                        NUMDATA(shp)->hanum));
+
+                ha->pccb = CMDDATA(shp);
+                ha->ccb_phys = 0L; 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+                ha->pdev = NULL;
+                ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, 
+                                                    &scratch_dma_handle);
+                ha->scratch_phys = scratch_dma_handle;
+                ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), 
+                                                &scratch_dma_handle);
+                ha->msg_phys = scratch_dma_handle;
+#ifdef INT_COAL
+                ha->coal_stat = (gdth_coal_status *)
+                    pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) *
+                                         MAXOFFSETS, &scratch_dma_handle);
+                ha->coal_stat_phys = scratch_dma_handle;
+#endif
+                ha->ccb_phys = 
+                    pci_map_single(ha->pdev,ha->pccb,
+                                   sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
+#else
+                ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+                if (ha->pscratch)
+                    ha->scratch_phys = virt_to_bus(ha->pscratch);
+                ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
+                if (ha->pmsg)
+                    ha->msg_phys = virt_to_bus(ha->pmsg);
+#ifdef INT_COAL
+                ha->coal_stat = 
+                    scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS, 
+                                     GFP_ATOMIC | GFP_DMA);
+                if (ha->coal_stat)
+                    ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
+#endif
+                ha->ccb_phys = virt_to_bus(ha->pccb);
+#endif
+                ha->scratch_busy = FALSE;
+                ha->req_first = NULL;
+                ha->tid_cnt = MAX_HDRIVES;
+                if (max_ids > 0 && max_ids < ha->tid_cnt)
+                    ha->tid_cnt = max_ids;
+                for (i=0; i<GDTH_MAXCMDS; ++i)
+                    ha->cmd_tab[i].cmnd = UNUSED_CMND;
+                ha->scan_mode = rescan ? 0x10 : 0;
+
+                if (ha->pscratch == NULL || ha->pmsg == NULL || 
+                    !gdth_search_drives(hanum)) {
+                    printk("GDT-EISA: Error during device scan\n");
+                    --gdth_ctr_count;
+                    --gdth_ctr_vcount;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#ifdef INT_COAL
+                    if (ha->coal_stat)
+                        pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
+                                            MAXOFFSETS, ha->coal_stat,
+                                            ha->coal_stat_phys);
+#endif
+                    if (ha->pscratch)
+                        pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
+                                            ha->pscratch, ha->scratch_phys);
+                    if (ha->pmsg)
+                        pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), 
+                                            ha->pmsg, ha->msg_phys);
+                    if (ha->ccb_phys)
+                        pci_unmap_single(ha->pdev,ha->ccb_phys,
+                                        sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
+#else
+#ifdef INT_COAL
+                    if (ha->coal_stat)
+                        scsi_init_free((void *)ha->coal_stat, 
+                                       sizeof(gdth_coal_status) * MAXOFFSETS);
+#endif
+                    if (ha->pscratch)
+                        scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+                    if (ha->pmsg)
+                        scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
 #endif
-            {
-                virt_ctr = 1;
-                /* register addit. SCSI channels as virtual controllers */
-                for (b = 1; b < ha->bus_cnt + 1; ++b) {
-                    shp = scsi_register(shtp,sizeof(gdth_num_str));
-                    shp->unchecked_isa_dma = 1;
-                    shp->irq = ha->irq;
-                    shp->dma_channel = ha->drq;
-                    gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-                    NUMDATA(shp)->hanum = (ushort)hanum;
-                    NUMDATA(shp)->busnum = b;
+                    free_irq(ha->irq,ha);
+                    scsi_unregister(shp);
+                    continue;
                 }
-            }  
+                if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
+                    hdr_channel = ha->bus_cnt;
+                ha->virt_bus = hdr_channel;
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \
+    LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+                shp->highmem_io  = 0;
+#endif
+                if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) 
+                    shp->max_cmd_len = 16;
+#endif
+                shp->max_id      = ha->tid_cnt;
+                shp->max_lun     = MAXLUN;
+                shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
+                if (virt_ctr) {
+                    virt_ctr = 1;
+                    /* register addit. SCSI channels as virtual controllers */
+                    for (b = 1; b < ha->bus_cnt + 1; ++b) {
+                        shp = scsi_register(shtp,sizeof(gdth_num_str));
+                        shp->unchecked_isa_dma = 0;
+                        shp->irq = ha->irq;
+                        shp->dma_channel = 0xff;
+                        gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
+                        NUMDATA(shp)->hanum = (ushort)hanum;
+                        NUMDATA(shp)->busnum = b;
+                    }
+                }  
 
-            GDTH_INIT_LOCK_HA(ha);
-            gdth_enable_int(hanum);
-#endif /* !__ia64__ */
+                GDTH_INIT_LOCK_HA(ha);
+                gdth_enable_int(hanum);
+            }
         }
     }
 
-    /* scanning for EISA controllers */
-    for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) {
-        if (gdth_ctr_count >= MAXHA) 
+    /* scanning for PCI controllers */
+    cnt = gdth_search_pci(pcistr);
+    printk("GDT-HA: Found %d PCI Storage RAID Controllers\n",cnt);
+    gdth_sort_pci(pcistr,cnt);
+    for (ctr = 0; ctr < cnt; ++ctr) {
+        dma_addr_t scratch_dma_handle;
+        scratch_dma_handle = 0;
+
+        if (gdth_ctr_count >= MAXHA)
             break;
-        if (gdth_search_eisa(eisa_slot)) {      /* controller found */
-            shp = scsi_register(shtp,sizeof(gdth_ext_str));
-	    if(shp == NULL)
-		    continue;
-
-            ha = HADATA(shp);
-            if (!gdth_init_eisa(eisa_slot,ha)) {
-                scsi_unregister(shp);
-                continue;
-            }
-            /* controller found and initialized */
-            printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n",
-                   eisa_slot>>12,ha->irq);
+        shp = scsi_register(shtp,sizeof(gdth_ext_str));
+        if (shp == NULL)
+            continue;  
+
+        ha = HADATA(shp);
+        if (!gdth_init_pci(&pcistr[ctr],ha)) {
+            scsi_unregister(shp);
+            continue;
+        }
+        /* controller found and initialized */
+        printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n",
+               pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq);
 
-#if LINUX_VERSION_CODE >= 0x010346 
-            if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth",ha))
-#else
-            if (request_irq(ha->irq,gdth_interrupt,SA_INTERRUPT,"gdth")) 
-#endif
-            {
-                printk("GDT-EISA: Unable to allocate IRQ\n");
-                scsi_unregister(shp);
-                continue;
-            }
-            shp->unchecked_isa_dma = 0;
-            shp->irq = ha->irq;
-            shp->dma_channel = 0xff;
-            hanum = gdth_ctr_count;
-            gdth_ctr_tab[gdth_ctr_count++] = shp;
-            gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-
-            NUMDATA(shp)->hanum = (ushort)hanum;
-            NUMDATA(shp)->busnum= 0;
-            TRACE2(("EISA detect Bus 0: hanum %d\n",
-                    NUMDATA(shp)->hanum));
-
-            ha->pccb = CMDDATA(shp);
-#if LINUX_VERSION_CODE >= 0x020322
-            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
-                                                     GDTH_SCRATCH_ORD);
-#else
-            ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
-#endif
-            ha->scratch_busy = FALSE;
-            ha->req_first = NULL;
-            ha->tid_cnt = MAX_HDRIVES;
-            if (max_ids > 0 && max_ids < ha->tid_cnt)
-                ha->tid_cnt = max_ids;
-            for (i=0; i<GDTH_MAXCMDS; ++i)
-                ha->cmd_tab[i].cmnd = UNUSED_CMND;
-            ha->scan_mode = rescan ? 0x10 : 0;
-
-            if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
-                printk("GDT-EISA: Error during device scan\n");
-                --gdth_ctr_count;
-                --gdth_ctr_vcount;
-                if (ha->pscratch != NULL)
-#if LINUX_VERSION_CODE >= 0x020322
-                    free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
-#else
-                    scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+        if (request_irq(ha->irq, gdth_interrupt,
+                        SA_INTERRUPT|SA_SHIRQ, "gdth", ha))
+        {
+            printk("GDT-PCI: Unable to allocate IRQ\n");
+            scsi_unregister(shp);
+            continue;
+        }
+        shp->unchecked_isa_dma = 0;
+        shp->irq = ha->irq;
+        shp->dma_channel = 0xff;
+        hanum = gdth_ctr_count;
+        gdth_ctr_tab[gdth_ctr_count++] = shp;
+        gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
+
+        NUMDATA(shp)->hanum = (ushort)hanum;
+        NUMDATA(shp)->busnum= 0;
+
+        ha->pccb = CMDDATA(shp);
+        ha->ccb_phys = 0L;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+        ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, 
+                                            &scratch_dma_handle);
+        ha->scratch_phys = scratch_dma_handle;
+        ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), 
+                                        &scratch_dma_handle);
+        ha->msg_phys = scratch_dma_handle;
+#ifdef INT_COAL
+        ha->coal_stat = (gdth_coal_status *)
+            pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) *
+                                 MAXOFFSETS, &scratch_dma_handle);
+        ha->coal_stat_phys = scratch_dma_handle;
+#endif
+#else
+        ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+        if (ha->pscratch)
+            ha->scratch_phys = virt_to_bus(ha->pscratch);
+        ha->pmsg = scsi_init_malloc(sizeof(gdth_msg_str), GFP_ATOMIC | GFP_DMA);
+        if (ha->pmsg)
+            ha->msg_phys = virt_to_bus(ha->pmsg);
+#ifdef INT_COAL
+        ha->coal_stat = 
+            scsi_init_malloc(sizeof(gdth_coal_status) * MAXOFFSETS, 
+                             GFP_ATOMIC | GFP_DMA);
+        if (ha->coal_stat)
+            ha->coal_stat_phys = virt_to_bus(ha->coal_stat);
 #endif
-#if LINUX_VERSION_CODE >= 0x010346 
-                free_irq(ha->irq,ha);
-#else
-                free_irq(ha->irq);
 #endif
-                scsi_unregister(shp);
-                continue;
-            }
+        ha->scratch_busy = FALSE;
+        ha->req_first = NULL;
+        ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES;
+        if (max_ids > 0 && max_ids < ha->tid_cnt)
+            ha->tid_cnt = max_ids;
+        for (i=0; i<GDTH_MAXCMDS; ++i)
+            ha->cmd_tab[i].cmnd = UNUSED_CMND;
+        ha->scan_mode = rescan ? 0x10 : 0;
+
+        err = FALSE;
+        if (ha->pscratch == NULL || ha->pmsg == NULL || 
+            !gdth_search_drives(hanum)) {
+            err = TRUE;
+        } else {
             if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
                 hdr_channel = ha->bus_cnt;
             ha->virt_bus = hdr_channel;
 
-#if LINUX_VERSION_CODE >= 0x020000
-            shp->max_id      = ha->tid_cnt;
-            shp->max_lun     = MAXLUN;
-            shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
-            if (virt_ctr)  
-#endif
-            {
-                virt_ctr = 1;
-                /* register addit. SCSI channels as virtual controllers */
-                for (b = 1; b < ha->bus_cnt + 1; ++b) {
-                    shp = scsi_register(shtp,sizeof(gdth_num_str));
-                    shp->unchecked_isa_dma = 0;
-                    shp->irq = ha->irq;
-                    shp->dma_channel = 0xff;
-                    gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-                    NUMDATA(shp)->hanum = (ushort)hanum;
-                    NUMDATA(shp)->busnum = b;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            scsi_set_device(shp, &pcistr[ctr].pdev->dev);
+#else
+            scsi_set_pci_device(shp, pcistr[ctr].pdev);
+#endif
+            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, 0xffffffff)) {
+                    printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum);
+                    err = TRUE;
                 }
-            }  
-
-            GDTH_INIT_LOCK_HA(ha);
-            gdth_enable_int(hanum);
+            } else {
+                shp->max_cmd_len = 16;
+                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, 0xffffffff)) {
+                    printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum);
+                    err = TRUE;
+                }
+            }
+#endif
         }
-    }
 
-    /* scanning for PCI controllers */
-#if LINUX_VERSION_CODE >= 0x2015C
-    if (pci_present())
-#else
-    if (pcibios_present())
+        if (err) {
+            printk("GDT-PCI %d: Error during device scan\n", hanum);
+            --gdth_ctr_count;
+            --gdth_ctr_vcount;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#ifdef INT_COAL
+            if (ha->coal_stat)
+                pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
+                                    MAXOFFSETS, ha->coal_stat,
+                                    ha->coal_stat_phys);
+#endif
+            if (ha->pscratch)
+                pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
+                                    ha->pscratch, ha->scratch_phys);
+            if (ha->pmsg)
+                pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), 
+                                    ha->pmsg, ha->msg_phys);
+#else
+#ifdef INT_COAL
+            if (ha->coal_stat)
+                scsi_init_free((void *)ha->coal_stat, 
+                               sizeof(gdth_coal_status) * MAXOFFSETS);
+#endif
+            if (ha->pscratch)
+                scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+            if (ha->pmsg)
+                scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
 #endif
-    {
-        gdth_pci_str pcistr[MAXHA];
+            free_irq(ha->irq,ha);
+            scsi_unregister(shp);
+            continue;
+        }
 
-        cnt = gdth_search_pci(pcistr);
-	printk("GDT: Found %d PCI Storage RAID Controllers\n",cnt);
-        gdth_sort_pci(pcistr,cnt);
-        for (ctr = 0; ctr < cnt; ++ctr) {
-            if (gdth_ctr_count >= MAXHA)
-                break;
-            shp = scsi_register(shtp,sizeof(gdth_ext_str));
-	    if(shp == NULL)
-		    continue;
-
-            ha = HADATA(shp);
-            if (!gdth_init_pci(&pcistr[ctr],ha)) {
-                scsi_unregister(shp);
-                continue;
+        shp->max_id      = ha->tid_cnt;
+        shp->max_lun     = MAXLUN;
+        shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
+        if (virt_ctr) {
+            virt_ctr = 1;
+            /* register addit. SCSI channels as virtual controllers */
+            for (b = 1; b < ha->bus_cnt + 1; ++b) {
+                shp = scsi_register(shtp,sizeof(gdth_num_str));
+                shp->unchecked_isa_dma = 0;
+                shp->irq = ha->irq;
+                shp->dma_channel = 0xff;
+                gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
+                NUMDATA(shp)->hanum = (ushort)hanum;
+                NUMDATA(shp)->busnum = b;
             }
-            /* controller found and initialized */
-            printk("GDT CTR%d: Configuring GDT-PCI HA at %d/%d IRQ %u\n",
-                   ctr,pcistr[ctr].bus,PCI_SLOT(pcistr[ctr].device_fn),ha->irq);
-
-#if LINUX_VERSION_CODE >= 0x010346 
-            if (request_irq(ha->irq, gdth_interrupt,
-                            SA_INTERRUPT|SA_SHIRQ, "gdth", ha))
-#else
-            if (request_irq(ha->irq, gdth_interrupt,
-                            SA_INTERRUPT|SA_SHIRQ, "gdth")) 
-#endif
-            {
-                printk("GDT-PCI: Unable to allocate IRQ\n");
-                scsi_unregister(shp);
-                continue;
-            }
-            shp->unchecked_isa_dma = 0;
-            shp->irq = ha->irq;
-            shp->dma_channel = 0xff;
-            hanum = gdth_ctr_count;
-            gdth_ctr_tab[gdth_ctr_count++] = shp;
-            gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-
-            NUMDATA(shp)->hanum = (ushort)hanum;
-            NUMDATA(shp)->busnum= 0;
-
-            ha->pccb = CMDDATA(shp);
-#if LINUX_VERSION_CODE >= 0x020322
-            ha->pscratch = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
-                                                     GDTH_SCRATCH_ORD);
-#else
-            ha->pscratch = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
-#endif
-            ha->scratch_busy = FALSE;
-            ha->req_first = NULL;
-            ha->tid_cnt = pcistr[ctr].device_id >= 0x200 ? MAXID : MAX_HDRIVES;
-            if (max_ids > 0 && max_ids < ha->tid_cnt)
-                ha->tid_cnt = max_ids;
-            for (i=0; i<GDTH_MAXCMDS; ++i)
-                ha->cmd_tab[i].cmnd = UNUSED_CMND;
-            ha->scan_mode = rescan ? 0x10 : 0;
-
-            if (ha->pscratch == NULL || !gdth_search_drives(hanum)) {
-                printk("GDT-PCI: Error during device scan\n");
-                --gdth_ctr_count;
-                --gdth_ctr_vcount;
-                if (ha->pscratch != NULL)
-#if LINUX_VERSION_CODE >= 0x020322
-                    free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
-#else
-                    scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
-#endif
-#if LINUX_VERSION_CODE >= 0x010346 
-                free_irq(ha->irq,ha);
-#else
-                free_irq(ha->irq);
-#endif
-                scsi_unregister(shp);
-                continue;
-            }
-            if (hdr_channel < 0 || hdr_channel > ha->bus_cnt)
-                hdr_channel = ha->bus_cnt;
-            ha->virt_bus = hdr_channel;
+        }  
 
-#if LINUX_VERSION_CODE >= 0x020000
-            shp->max_id      = ha->tid_cnt;
-            shp->max_lun     = MAXLUN;
-            shp->max_channel = virt_ctr ? 0 : ha->bus_cnt;
-            if (virt_ctr)  
-#endif
-            {
-                virt_ctr = 1;
-                /* register addit. SCSI channels as virtual controllers */
-                for (b = 1; b < ha->bus_cnt + 1; ++b) {
-                    shp = scsi_register(shtp,sizeof(gdth_num_str));
-                    shp->unchecked_isa_dma = 0;
-                    shp->irq = ha->irq;
-                    shp->dma_channel = 0xff;
-                    gdth_ctr_vtab[gdth_ctr_vcount++] = shp;
-                    NUMDATA(shp)->hanum = (ushort)hanum;
-                    NUMDATA(shp)->busnum = b;
-                }
-            }  
 
-            GDTH_INIT_LOCK_HA(ha);
-            gdth_enable_int(hanum);
-        }
+        GDTH_INIT_LOCK_HA(ha);
+        gdth_enable_int(hanum);
     }
-
+    
     TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count));
     if (gdth_ctr_count > 0) {
 #ifdef GDTH_STATISTICS
@@ -4365,9 +4979,8 @@
         gdth_timer.function = gdth_timeout;
         add_timer(&gdth_timer);
 #endif
-#if LINUX_VERSION_CODE >= 0x020100
+        major = register_chrdev(0,"gdth",&gdth_fops);
         register_reboot_notifier(&gdth_notifier);
-#endif
     }
     gdth_polling = FALSE;
     return gdth_ctr_vcount;
@@ -4383,26 +4996,47 @@
     if (NUMDATA(shp)->busnum == 0) {
         hanum = NUMDATA(shp)->hanum;
         ha    = HADATA(gdth_ctr_tab[hanum]);
-#if LINUX_VERSION_CODE >= 0x010300
-        gdth_flush(hanum);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+        if (ha->sdev) {
+            scsi_free_host_dev(ha->sdev);
+            ha->sdev = NULL;
+        }
 #endif
+        gdth_flush(hanum);
 
         if (shp->irq) {
-#if LINUX_VERSION_CODE >= 0x010346
             free_irq(shp->irq,ha);
-#else
-            free_irq(shp->irq);
-#endif
         }
 #ifndef __ia64__
         if (shp->dma_channel != 0xff) {
             free_dma(shp->dma_channel);
         }
 #endif
-#if LINUX_VERSION_CODE >= 0x020322
-        free_pages((unsigned long)ha->pscratch, GDTH_SCRATCH_ORD);
-#else
-        scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+#ifdef INT_COAL
+        if (ha->coal_stat)
+            pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) *
+                                MAXOFFSETS, ha->coal_stat, ha->coal_stat_phys);
+#endif
+        if (ha->pscratch)
+            pci_free_consistent(ha->pdev, GDTH_SCRATCH, 
+                                ha->pscratch, ha->scratch_phys);
+        if (ha->pmsg)
+            pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), 
+                                ha->pmsg, ha->msg_phys);
+        if (ha->ccb_phys)
+            pci_unmap_single(ha->pdev,ha->ccb_phys,
+                             sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL);
+#else
+#ifdef INT_COAL
+        if (ha->coal_stat)
+            scsi_init_free((void *)ha->coal_stat, 
+                           sizeof(gdth_coal_status) * MAXOFFSETS);
+#endif
+        if (ha->pscratch)
+            scsi_init_free((void *)ha->pscratch, GDTH_SCRATCH);
+        if (ha->pmsg)
+            scsi_init_free((void *)ha->pmsg, sizeof(gdth_msg_str));
 #endif
         gdth_ctr_released++;
         TRACE2(("gdth_release(): HA %d of %d\n", 
@@ -4412,9 +5046,8 @@
 #ifdef GDTH_STATISTICS
             del_timer(&gdth_timer);
 #endif
-#if LINUX_VERSION_CODE >= 0x020100
+            unregister_chrdev(major,"gdth");
             unregister_reboot_notifier(&gdth_notifier);
-#endif
         }
     }
 
@@ -4467,6 +5100,7 @@
     return ((const char *)ha->binfo.type_string);
 }
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
 /* old error handling */
 int gdth_abort(Scsi_Cmnd *scp)
 {
@@ -4474,17 +5108,13 @@
     return SCSI_ABORT_SNOOZE;
 }
 
-#if LINUX_VERSION_CODE >= 0x010346
 int gdth_reset(Scsi_Cmnd *scp, unsigned int reset_flags)
-#else
-int gdth_reset(Scsi_Cmnd *scp)
-#endif
 {
     TRACE2(("gdth_reset()\n"));
     return SCSI_RESET_PUNT;
 }
+#endif
 
-#if LINUX_VERSION_CODE >= 0x02015F
 /* new error handling */
 int gdth_eh_abort(Scsi_Cmnd *scp)
 {
@@ -4507,15 +5137,24 @@
     unchar b;
 
     TRACE2(("gdth_eh_bus_reset()\n"));
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    hanum = NUMDATA(scp->device->host)->hanum;
+    b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+#else
     hanum = NUMDATA(scp->host)->hanum;
     b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
+#endif
     ha    = HADATA(gdth_ctr_tab[hanum]);
 
     /* clear command tab */
     GDTH_LOCK_HA(ha, flags);
     for (i = 0; i < GDTH_MAXCMDS; ++i) {
         cmnd = ha->cmd_tab[i].cmnd;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        if (!SPECIAL_SCP(cmnd) && cmnd->device->channel == b)
+#else
         if (!SPECIAL_SCP(cmnd) && cmnd->channel == b)
+#endif
             ha->cmd_tab[i].cmnd = UNUSED_CMND;
     }
     GDTH_UNLOCK_HA(ha, flags);
@@ -4556,32 +5195,41 @@
     TRACE2(("gdth_eh_host_reset()\n"));
     return FAILED;
 }
-#endif
 
-#if LINUX_VERSION_CODE >= 0x010300
-int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip)
 #else
-int gdth_bios_param(Disk *disk,int dev,int *ip)
+int gdth_bios_param(Disk *disk,kdev_t dev,int *ip)
 #endif
 {
     unchar b, t;
     int hanum;
     gdth_ha_str *ha;
+    struct scsi_device *sd;
+    unsigned capacity;
 
-    hanum = NUMDATA(disk->device->host)->hanum;
-    b = virt_ctr ? NUMDATA(disk->device->host)->busnum : disk->device->channel;
-    t = disk->device->id;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    sd = sdev;
+    capacity = cap;
+#else
+    sd = disk->device;
+    capacity = disk->capacity;
+#endif
+    hanum = NUMDATA(sd->host)->hanum;
+    b = virt_ctr ? NUMDATA(sd->host)->busnum : sd->channel;
+    t = sd->id;
     TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t)); 
     ha = HADATA(gdth_ctr_tab[hanum]);
 
     if (b != ha->virt_bus || ha->hdr[t].heads == 0) {
         /* raw device or host drive without mapping information */
         TRACE2(("Evaluate mapping\n"));
-        gdth_eval_mapping(disk->capacity,&ip[2],&ip[0],&ip[1]);
+        gdth_eval_mapping(capacity,&ip[2],&ip[0],&ip[1]);
     } else {
         ip[0] = ha->hdr[t].heads;
         ip[1] = ha->hdr[t].secs;
-        ip[2] = disk->capacity / ip[0] / ip[1];
+        ip[2] = capacity / ip[0] / ip[1];
     }
 
     TRACE2(("gdth_bios_param(): %d heads, %d secs, %d cyls\n",
@@ -4595,37 +5243,813 @@
     int hanum;
     int priority;
 
-    TRACE(("gdth_queuecommand() cmd 0x%x id %d lun %d\n",
-           scp->cmnd[0],scp->target,scp->lun));
+    TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0]));
     
     scp->scsi_done = (void *)done;
     scp->SCp.have_data_in = 1;
     scp->SCp.phase = -1;
     scp->SCp.sent_command = -1;
+    scp->SCp.Status = GDTH_MAP_NONE;
+    scp->SCp.buffer = (struct scatterlist *)NULL;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    hanum = NUMDATA(scp->device->host)->hanum;
+#else
     hanum = NUMDATA(scp->host)->hanum;
+#endif
 #ifdef GDTH_STATISTICS
     ++act_ios;
 #endif
 
     priority = DEFAULT_PRI;
-#if LINUX_VERSION_CODE >= 0x010300
     if (scp->done == gdth_scsi_done)
         priority = scp->SCp.this_residual;
-#endif
     gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6);
     gdth_putq( hanum, scp, priority );
     gdth_next( hanum );
     return 0;
 }
 
-#if LINUX_VERSION_CODE >= 0x010300
+
+static int gdth_open(struct inode *inode, struct file *filep)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    gdth_ha_str *ha;
+    int i;
+
+    for (i = 0; i < gdth_ctr_count; i++) {
+        ha = HADATA(gdth_ctr_tab[i]);
+        if (!ha->sdev)
+            ha->sdev = scsi_get_host_dev(gdth_ctr_tab[i]);
+    }
+#endif
+
+    TRACE(("gdth_open()\n"));
+    return 0;
+}
+
+static int gdth_close(struct inode *inode, struct file *filep)
+{
+    TRACE(("gdth_close()\n"));
+    return 0;
+}
+
+static int ioc_event(unsigned long arg)
+{
+    gdth_ioctl_event evt;
+    gdth_ha_str *ha;
+    ulong flags;
+
+    if (copy_from_user(&evt, (char *)arg, sizeof(gdth_ioctl_event)) ||
+        evt.ionode >= gdth_ctr_count)
+        return -EFAULT;
+    ha = HADATA(gdth_ctr_tab[evt.ionode]);
+
+    if (evt.erase == 0xff) {
+        if (evt.event.event_source == ES_TEST)
+            evt.event.event_data.size=sizeof(evt.event.event_data.eu.test); 
+        else if (evt.event.event_source == ES_DRIVER)
+            evt.event.event_data.size=sizeof(evt.event.event_data.eu.driver); 
+        else if (evt.event.event_source == ES_SYNC)
+            evt.event.event_data.size=sizeof(evt.event.event_data.eu.sync); 
+        else
+            evt.event.event_data.size=sizeof(evt.event.event_data.eu.async);
+        GDTH_LOCK_HA(ha, flags);
+        gdth_store_event(ha, evt.event.event_source, evt.event.event_idx,
+                         &evt.event.event_data);
+        GDTH_UNLOCK_HA(ha, flags);
+    } else if (evt.erase == 0xfe) {
+        gdth_clear_events();
+    } else if (evt.erase == 0) {
+        evt.handle = gdth_read_event(ha, evt.handle, &evt.event);
+    } else {
+        gdth_readapp_event(ha, evt.erase, &evt.event);
+    }     
+    if (copy_to_user((char *)arg, &evt, sizeof(gdth_ioctl_event)))
+        return -EFAULT;
+    return 0;
+}
+
+static int ioc_lockdrv(unsigned long arg)
+{
+    gdth_ioctl_lockdrv ldrv;
+    unchar i, j;
+    ulong flags;
+    gdth_ha_str *ha;
+
+    if (copy_from_user(&ldrv, (char *)arg, sizeof(gdth_ioctl_lockdrv)) ||
+        ldrv.ionode >= gdth_ctr_count)
+        return -EFAULT;
+    ha = HADATA(gdth_ctr_tab[ldrv.ionode]);
+ 
+    for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) {
+        j = ldrv.drives[i];
+        if (j >= MAX_HDRIVES || !ha->hdr[j].present)
+            continue;
+        if (ldrv.lock) {
+            GDTH_LOCK_HA(ha, flags);
+            ha->hdr[j].lock = 1;
+            GDTH_UNLOCK_HA(ha, flags);
+            gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j); 
+            gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j); 
+        } else {
+            GDTH_LOCK_HA(ha, flags);
+            ha->hdr[j].lock = 0;
+            GDTH_UNLOCK_HA(ha, flags);
+            gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j); 
+            gdth_next(ldrv.ionode); 
+        }
+    } 
+    return 0;
+}
+
+static int ioc_resetdrv(unsigned long arg, char *cmnd)
+{
+    gdth_ioctl_reset res;
+    gdth_cmd_str cmd;
+    int hanum;
+    gdth_ha_str *ha;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        Scsi_Request *srp;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+        Scsi_Cmnd *scp;
+#else
+        Scsi_Cmnd scp;
+#endif
+
+    if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) ||
+        res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES)
+        return -EFAULT;
+    hanum = res.ionode;
+    ha = HADATA(gdth_ctr_tab[hanum]);
+ 
+    if (!ha->hdr[res.number].present)
+        return 0;
+    memset(&cmd, 0, sizeof(gdth_cmd_str));
+    cmd.Service = CACHESERVICE;
+    cmd.OpCode = GDT_CLUST_RESET;
+    if (ha->cache_feat & GDT_64BIT)
+        cmd.u.cache64.DeviceNo = res.number;
+    else
+        cmd.u.cache.DeviceNo = res.number;
+#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);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    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);
+#else
+    memset(&ha->sdev,0,sizeof(Scsi_Device));
+    memset(&scp, 0,sizeof(Scsi_Cmnd));
+    ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
+    ha->sdev.id = scp.target = ha->sdev.host->this_id;
+    scp.device = &ha->sdev;
+    gdth_do_cmd(&scp, &cmd, cmnd, 30);
+    res.status = (ushort)scp.SCp.Status;
+#endif
+    if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset)))
+        return -EFAULT;
+    return 0;
+}
+
+static int ioc_general(unsigned long arg, char *cmnd)
+{
+    gdth_ioctl_general gen;
+    char *buf = NULL;
+    ulong64 paddr; 
+    int hanum;
+        gdth_ha_str *ha; 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        Scsi_Request *srp;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+        Scsi_Cmnd *scp;
+#else
+        Scsi_Cmnd scp;
+#endif
+        
+    if (copy_from_user(&gen, (char *)arg, sizeof(gdth_ioctl_general)) ||
+        gen.ionode >= gdth_ctr_count)
+        return -EFAULT;
+    hanum = gen.ionode; 
+    ha = HADATA(gdth_ctr_tab[hanum]);
+    if (gen.data_len + gen.sense_len != 0) {
+        if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len, 
+                                     FALSE, &paddr)))
+            return -EFAULT;
+        if (copy_from_user(buf, (char *)arg + sizeof(gdth_ioctl_general),  
+                           gen.data_len + gen.sense_len)) {
+            gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+            return -EFAULT;
+        }
+
+        if (gen.command.OpCode == GDT_IOCTL) {
+            gen.command.u.ioctl.p_param = paddr;
+        } else if (gen.command.Service == CACHESERVICE) {
+            if (ha->cache_feat & GDT_64BIT) {
+                /* copy elements from 32-bit IOCTL structure */
+                gen.command.u.cache64.BlockCnt = gen.command.u.cache.BlockCnt;
+                gen.command.u.cache64.BlockNo = gen.command.u.cache.BlockNo;
+                gen.command.u.cache64.DeviceNo = gen.command.u.cache.DeviceNo;
+                /* addresses */
+                if (ha->cache_feat & SCATTER_GATHER) {
+                    gen.command.u.cache64.DestAddr = (ulong64)-1;
+                    gen.command.u.cache64.sg_canz = 1;
+                    gen.command.u.cache64.sg_lst[0].sg_ptr = paddr;
+                    gen.command.u.cache64.sg_lst[0].sg_len = gen.data_len;
+                    gen.command.u.cache64.sg_lst[1].sg_len = 0;
+                } else {
+                    gen.command.u.cache64.DestAddr = paddr;
+                    gen.command.u.cache64.sg_canz = 0;
+                }
+            } else {
+                if (ha->cache_feat & SCATTER_GATHER) {
+                    gen.command.u.cache.DestAddr = 0xffffffff;
+                    gen.command.u.cache.sg_canz = 1;
+                    gen.command.u.cache.sg_lst[0].sg_ptr = (ulong32)paddr;
+                    gen.command.u.cache.sg_lst[0].sg_len = gen.data_len;
+                    gen.command.u.cache.sg_lst[1].sg_len = 0;
+                } else {
+                    gen.command.u.cache.DestAddr = paddr;
+                    gen.command.u.cache.sg_canz = 0;
+                }
+            }
+        } else if (gen.command.Service == SCSIRAWSERVICE) {
+            if (ha->raw_feat & GDT_64BIT) {
+                /* copy elements from 32-bit IOCTL structure */
+                char cmd[16];
+                gen.command.u.raw64.sense_len = gen.command.u.raw.sense_len;
+                gen.command.u.raw64.bus = gen.command.u.raw.bus;
+                gen.command.u.raw64.lun = gen.command.u.raw.lun;
+                gen.command.u.raw64.target = gen.command.u.raw.target;
+                memcpy(cmd, gen.command.u.raw.cmd, 16);
+                memcpy(gen.command.u.raw64.cmd, cmd, 16);
+                gen.command.u.raw64.clen = gen.command.u.raw.clen;
+                gen.command.u.raw64.sdlen = gen.command.u.raw.sdlen;
+                gen.command.u.raw64.direction = gen.command.u.raw.direction;
+                /* addresses */
+                if (ha->raw_feat & SCATTER_GATHER) {
+                    gen.command.u.raw64.sdata = (ulong64)-1;
+                    gen.command.u.raw64.sg_ranz = 1;
+                    gen.command.u.raw64.sg_lst[0].sg_ptr = paddr;
+                    gen.command.u.raw64.sg_lst[0].sg_len = gen.data_len;
+                    gen.command.u.raw64.sg_lst[1].sg_len = 0;
+                } else {
+                    gen.command.u.raw64.sdata = paddr;
+                    gen.command.u.raw64.sg_ranz = 0;
+                }
+                gen.command.u.raw64.sense_data = paddr + gen.data_len;
+            } else {
+                if (ha->raw_feat & SCATTER_GATHER) {
+                    gen.command.u.raw.sdata = 0xffffffff;
+                    gen.command.u.raw.sg_ranz = 1;
+                    gen.command.u.raw.sg_lst[0].sg_ptr = (ulong32)paddr;
+                    gen.command.u.raw.sg_lst[0].sg_len = gen.data_len;
+                    gen.command.u.raw.sg_lst[1].sg_len = 0;
+                } else {
+                    gen.command.u.raw.sdata = paddr;
+                    gen.command.u.raw.sg_ranz = 0;
+                }
+                gen.command.u.raw.sense_data = (ulong32)paddr + gen.data_len;
+            }
+        } else {
+            gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+            return -EFAULT;
+        }
+    }
+
+#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);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    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);
+#else
+    memset(&ha->sdev,0,sizeof(Scsi_Device));
+    memset(&scp, 0,sizeof(Scsi_Cmnd));
+    ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
+    ha->sdev.id = scp.target = ha->sdev.host->this_id;
+    scp.device = &ha->sdev;
+    gdth_do_cmd(&scp, &gen.command, cmnd, gen.timeout);
+    gen.status = scp.SCp.Status;
+    gen.info = scp.SCp.Message;
+#endif
+
+    if (copy_to_user((char *)arg + sizeof(gdth_ioctl_general), buf, 
+                     gen.data_len + gen.sense_len)) {
+        gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+        return -EFAULT; 
+    } 
+    if (copy_to_user((char *)arg, &gen, 
+        sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) {
+        gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+        return -EFAULT;
+    }
+    gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr);
+    return 0;
+}
+ 
+static int ioc_hdrlist(unsigned long arg, char *cmnd)
+{
+    gdth_ioctl_rescan rsc;
+    gdth_cmd_str cmd;
+    gdth_ha_str *ha;
+    unchar i;
+    int hanum;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Request *srp;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    Scsi_Cmnd *scp;
+#else
+    Scsi_Cmnd scp;
+#endif
+        
+    if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) ||
+        rsc.ionode >= gdth_ctr_count)
+        return -EFAULT;
+    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)
+        return -ENOMEM;
+    srp->sr_cmd_len = 12;
+    srp->sr_use_sg = 0;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
+    if (!scp)
+        return -ENOMEM;
+    scp->cmd_len = 12;
+    scp->use_sg = 0;
+#else
+    memset(&ha->sdev,0,sizeof(Scsi_Device));
+    memset(&scp, 0,sizeof(Scsi_Cmnd));
+    ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
+    ha->sdev.id = scp.target = ha->sdev.host->this_id;
+    scp.device = &ha->sdev;
+#endif
+
+    for (i = 0; i < MAX_HDRIVES; ++i) { 
+        if (!ha->hdr[i].present) {
+            rsc.hdr_list[i].bus = 0xff; 
+            continue;
+        } 
+        rsc.hdr_list[i].bus = ha->virt_bus;
+        rsc.hdr_list[i].target = i;
+        rsc.hdr_list[i].lun = 0;
+        rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
+        if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) { 
+            cmd.Service = CACHESERVICE;
+            cmd.OpCode = GDT_CLUST_INFO;
+            if (ha->cache_feat & GDT_64BIT)
+                cmd.u.cache64.DeviceNo = i;
+            else
+                cmd.u.cache.DeviceNo = i;
+#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;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+            gdth_do_cmd(scp, &cmd, cmnd, 30);
+            if (scp->SCp.Status == S_OK)
+                rsc.hdr_list[i].cluster_type = scp->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);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    scsi_release_command(scp);
+#endif       
+ 
+    if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan)))
+        return -EFAULT;
+    return 0;
+}
+
+static int ioc_rescan(unsigned long arg, char *cmnd)
+{
+    gdth_ioctl_rescan rsc;
+    gdth_cmd_str cmd;
+    ushort i, status, hdr_cnt;
+    ulong32 info;
+    int hanum, cyls, hds, secs;
+    ulong flags;
+    gdth_ha_str *ha; 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Request *srp;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    Scsi_Cmnd *scp;
+#else
+    Scsi_Cmnd scp;
+#endif
+        
+    if (copy_from_user(&rsc, (char *)arg, sizeof(gdth_ioctl_rescan)) ||
+        rsc.ionode >= gdth_ctr_count)
+        return -EFAULT;
+    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)
+        return -ENOMEM;
+    srp->sr_cmd_len = 12;
+    srp->sr_use_sg = 0;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
+    if (!scp)
+        return -ENOMEM;
+    scp->cmd_len = 12;
+    scp->use_sg = 0;
+#else
+    memset(&ha->sdev,0,sizeof(Scsi_Device));
+    memset(&scp, 0,sizeof(Scsi_Cmnd));
+    ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
+    ha->sdev.id = scp.target = ha->sdev.host->this_id;
+    scp.device = &ha->sdev;
+#endif
+     
+    if (rsc.flag == 0) {
+        /* old method: re-init. cache service */
+        cmd.Service = CACHESERVICE;
+        if (ha->cache_feat & GDT_64BIT) {
+            cmd.OpCode = GDT_X_INIT_HOST;
+            cmd.u.cache64.DeviceNo = LINUX_OS;
+        } else {
+            cmd.OpCode = GDT_INIT;
+            cmd.u.cache.DeviceNo = LINUX_OS;
+        }
+#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 {
+        i = rsc.hdr_no;
+        hdr_cnt = i + 1;
+    }
+    for (; i < hdr_cnt && i < MAX_HDRIVES; ++i) {
+        cmd.Service = CACHESERVICE;
+        cmd.OpCode = GDT_INFO;
+        if (ha->cache_feat & GDT_64BIT) 
+            cmd.u.cache64.DeviceNo = i;
+        else 
+            cmd.u.cache.DeviceNo = i;
+#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
+        GDTH_LOCK_HA(ha, flags);
+        rsc.hdr_list[i].bus = ha->virt_bus;
+        rsc.hdr_list[i].target = i;
+        rsc.hdr_list[i].lun = 0;
+        if (status != S_OK) {
+            ha->hdr[i].present = FALSE;
+        } else {
+            ha->hdr[i].present = TRUE;
+            ha->hdr[i].size = info;
+            /* evaluate mapping */
+            ha->hdr[i].size &= ~SECS32;
+            gdth_eval_mapping(ha->hdr[i].size,&cyls,&hds,&secs); 
+            ha->hdr[i].heads = hds;
+            ha->hdr[i].secs = secs;
+            /* round size */
+            ha->hdr[i].size = cyls * hds * secs;
+        }
+        GDTH_UNLOCK_HA(ha, flags);
+        if (status != S_OK)
+            continue; 
+        
+        /* extended info, if GDT_64BIT, for drives > 2 TB */
+        /* but we need ha->info2, not yet stored in scp->SCp */
+
+        /* devtype, cluster info, R/W attribs */
+        cmd.Service = CACHESERVICE;
+        cmd.OpCode = GDT_DEVTYPE;
+        if (ha->cache_feat & GDT_64BIT) 
+            cmd.u.cache64.DeviceNo = i;
+        else
+            cmd.u.cache.DeviceNo = i;
+#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
+        GDTH_LOCK_HA(ha, flags);
+        ha->hdr[i].devtype = (status == S_OK ? (ushort)info : 0);
+        GDTH_UNLOCK_HA(ha, flags);
+
+        cmd.Service = CACHESERVICE;
+        cmd.OpCode = GDT_CLUST_INFO;
+        if (ha->cache_feat & GDT_64BIT) 
+            cmd.u.cache64.DeviceNo = i;
+        else
+            cmd.u.cache.DeviceNo = i;
+#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
+        GDTH_LOCK_HA(ha, flags);
+        ha->hdr[i].cluster_type = 
+            ((status == S_OK && !shared_access) ? (ushort)info : 0);
+        GDTH_UNLOCK_HA(ha, flags);
+        rsc.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
+
+        cmd.Service = CACHESERVICE;
+        cmd.OpCode = GDT_RW_ATTRIBS;
+        if (ha->cache_feat & GDT_64BIT) 
+            cmd.u.cache64.DeviceNo = i;
+        else
+            cmd.u.cache.DeviceNo = i;
+#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
+        GDTH_LOCK_HA(ha, flags);
+        ha->hdr[i].rw_attribs = (status == S_OK ? (ushort)info : 0);
+        GDTH_UNLOCK_HA(ha, flags);
+    }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    scsi_release_request(srp);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    scsi_release_command(scp);
+#endif       
+ 
+    if (copy_to_user((char *)arg, &rsc, sizeof(gdth_ioctl_rescan)))
+        return -EFAULT;
+    return 0;
+}
+  
+static int gdth_ioctl(struct inode *inode, struct file *filep,
+                      unsigned int cmd, unsigned long arg)
+{
+    gdth_ha_str *ha; 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Cmnd *scp;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    Scsi_Cmnd *scp;
+#else
+    Scsi_Cmnd scp;
+#endif
+    ulong flags;
+    char cmnd[MAX_COMMAND_SIZE];   
+
+    memset(cmnd, 0xff, 12);
+    
+    TRACE(("gdth_ioctl() cmd 0x%x\n", cmd));
+ 
+    switch (cmd) {
+      case GDTIOCTL_CTRCNT:
+      { 
+        int cnt = gdth_ctr_count;
+        if (put_user(cnt, (int *)arg))
+                return -EFAULT;
+        break;
+      }
+
+      case GDTIOCTL_DRVERS:
+      { 
+        int ver = (GDTH_VERSION<<8) | GDTH_SUBVERSION;
+        if (put_user(ver, (int *)arg))
+                return -EFAULT;
+        break;
+      }
+      
+      case GDTIOCTL_OSVERS:
+      { 
+        gdth_ioctl_osvers osv; 
+
+        osv.version = (unchar)(LINUX_VERSION_CODE >> 16);
+        osv.subversion = (unchar)(LINUX_VERSION_CODE >> 8);
+        osv.revision = (ushort)(LINUX_VERSION_CODE & 0xff);
+        if (copy_to_user((char *)arg, &osv, sizeof(gdth_ioctl_osvers)))
+                return -EFAULT;
+        break;
+      }
+
+      case GDTIOCTL_CTRTYPE:
+      { 
+        gdth_ioctl_ctrtype ctrt;
+        
+        if (copy_from_user(&ctrt, (char *)arg, sizeof(gdth_ioctl_ctrtype)) ||
+            ctrt.ionode >= gdth_ctr_count)
+            return -EFAULT;
+        ha = HADATA(gdth_ctr_tab[ctrt.ionode]);
+        if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
+            ctrt.type = (unchar)((ha->stype>>20) - 0x10);
+        } else {
+            if (ha->type != GDT_PCIMPR) {
+                ctrt.type = (unchar)((ha->stype<<4) + 6);
+            } else {
+                ctrt.type = 
+                    (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe);
+                if (ha->stype >= 0x300)
+                    ctrt.ext_type = 0x6000 | ha->subdevice_id;
+                else 
+                    ctrt.ext_type = 0x6000 | ha->stype;
+            }
+            ctrt.device_id = ha->stype;
+            ctrt.sub_device_id = ha->subdevice_id;
+        }
+        ctrt.info = ha->brd_phys;
+        ctrt.oem_id = ha->oem_id;
+        if (copy_to_user((char *)arg, &ctrt, sizeof(gdth_ioctl_ctrtype)))
+            return -EFAULT;
+        break;
+      }
+        
+      case GDTIOCTL_GENERAL:
+        return ioc_general(arg, cmnd);
+
+      case GDTIOCTL_EVENT:
+        return ioc_event(arg);
+
+      case GDTIOCTL_LOCKDRV:
+        return ioc_lockdrv(arg);
+
+      case GDTIOCTL_LOCKCHN:
+      {
+        gdth_ioctl_lockchn lchn;
+        unchar i, j;
+
+        if (copy_from_user(&lchn, (char *)arg, sizeof(gdth_ioctl_lockchn)) ||
+            lchn.ionode >= gdth_ctr_count)
+            return -EFAULT;
+        ha = HADATA(gdth_ctr_tab[lchn.ionode]);
+        
+        i = lchn.channel;
+        if (i < ha->bus_cnt) {
+            if (lchn.lock) {
+                GDTH_LOCK_HA(ha, flags);
+                ha->raw[i].lock = 1;
+                GDTH_UNLOCK_HA(ha, flags);
+                for (j = 0; j < ha->tid_cnt; ++j) {
+                    gdth_wait_completion(lchn.ionode, i, j); 
+                    gdth_stop_timeout(lchn.ionode, i, j); 
+                }
+            } else {
+                GDTH_LOCK_HA(ha, flags);
+                ha->raw[i].lock = 0;
+                GDTH_UNLOCK_HA(ha, flags);
+                for (j = 0; j < ha->tid_cnt; ++j) {
+                    gdth_start_timeout(lchn.ionode, i, j); 
+                    gdth_next(lchn.ionode); 
+                }
+            }
+        } 
+        break;
+      }
+
+      case GDTIOCTL_RESCAN:
+        return ioc_rescan(arg, cmnd);
+
+      case GDTIOCTL_HDRLIST:
+        return ioc_hdrlist(arg, cmnd);
+
+      case GDTIOCTL_RESET_BUS:
+      {
+        gdth_ioctl_reset res;
+        int hanum, rval;
+
+        if (copy_from_user(&res, (char *)arg, sizeof(gdth_ioctl_reset)) ||
+            res.ionode >= gdth_ctr_count)
+            return -EFAULT;
+        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  = scsi_get_command(ha->sdev, GFP_KERNEL);
+        if (!scp)
+            return -ENOMEM;
+        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);
+        scsi_put_command(scp);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+        scp  = scsi_allocate_device(ha->sdev, 1, FALSE);
+        if (!scp)
+            return -ENOMEM;
+        scp->cmd_len = 12;
+        scp->use_sg = 0;
+        scp->channel = virt_ctr ? 0 : res.number;
+        rval = gdth_eh_bus_reset(scp);
+        res.status = (rval == SUCCESS ? S_OK : S_GENERR);
+        scsi_release_command(scp);
+#else 
+        memset(&ha->sdev,0,sizeof(Scsi_Device));
+        memset(&scp, 0,sizeof(Scsi_Cmnd));
+        ha->sdev.host = scp.host = gdth_ctr_tab[hanum];
+        ha->sdev.id = scp.target = ha->sdev.host->this_id;
+        scp.device = &ha->sdev;
+        scp.channel = virt_ctr ? 0 : res.number;
+        rval = gdth_eh_bus_reset(&scp);
+        res.status = (rval == SUCCESS ? S_OK : S_GENERR);
+#endif
+        if (copy_to_user((char *)arg, &res, sizeof(gdth_ioctl_reset)))
+            return -EFAULT;
+        break;
+      }
+
+      case GDTIOCTL_RESET_DRV:
+        return ioc_resetdrv(arg, cmnd);
+
+      default:
+        break; 
+    }
+    return 0;
+}
+
+
 /* flush routine */
 static void gdth_flush(int hanum)
 {
     int             i;
     gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Request    *srp;
+    Scsi_Device     *sdev;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     Scsi_Cmnd       *scp;
     Scsi_Device     *sdev;
 #else
@@ -4638,9 +6062,18 @@
     TRACE2(("gdth_flush() hanum %d\n",hanum));
     ha = HADATA(gdth_ctr_tab[hanum]);
 
-#if LINUX_VERSION_CODE >= 0x020322
+#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;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     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;
 #else
@@ -4656,34 +6089,44 @@
             gdtcmd.BoardNode = LOCALBOARD;
             gdtcmd.Service = CACHESERVICE;
             gdtcmd.OpCode = GDT_FLUSH;
-            gdtcmd.u.cache.DeviceNo = i;
-            gdtcmd.u.cache.BlockNo = 1;
-            gdtcmd.u.cache.sg_canz = 0;
+            if (ha->cache_feat & GDT_64BIT) { 
+                gdtcmd.u.cache64.DeviceNo = i;
+                gdtcmd.u.cache64.BlockNo = 1;
+                gdtcmd.u.cache64.sg_canz = 0;
+            } else {
+                gdtcmd.u.cache.DeviceNo = i;
+                gdtcmd.u.cache.BlockNo = 1;
+                gdtcmd.u.cache.sg_canz = 0;
+            }
             TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i));
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            gdth_do_req(srp, &gdtcmd, cmnd, 30);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
             gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
 #else
             gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
 #endif
         }
     }
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    scsi_release_request(srp);
+    scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     scsi_release_command(scp);
     scsi_free_host_dev(sdev);
 #endif
 }
 
 /* shutdown routine */
-#if LINUX_VERSION_CODE >= 0x020100
 static int gdth_halt(struct notifier_block *nb, ulong event, void *buf)
-#else
-void gdth_halt(void)
-#endif
 {
     int             hanum;
 #ifndef __alpha__
     gdth_cmd_str    gdtcmd;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Request    *srp;
+    Scsi_Device     *sdev;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     Scsi_Cmnd       *scp;
     Scsi_Device     *sdev;
 #else
@@ -4693,47 +6136,51 @@
     char            cmnd[MAX_COMMAND_SIZE];   
 #endif
 
-#if LINUX_VERSION_CODE >= 0x020100
     TRACE2(("gdth_halt() event %d\n",(int)event));
     if (event != SYS_RESTART && event != SYS_HALT && event != SYS_POWER_OFF)
         return NOTIFY_DONE;
-#else
-    TRACE2(("gdth_halt()\n"));
-    if (halt_called) {
-        TRACE2(("already called\n"));
-        return;
-    }
-    halt_called = TRUE;
-#endif
-    printk("GDT: Flushing all host drives .. ");
+
+    printk("GDT-HA: Flushing all host drives .. ");
     for (hanum = 0; hanum < gdth_ctr_count; ++hanum) {
         gdth_flush(hanum);
 
 #ifndef __alpha__
         /* controller reset */
         memset(cmnd, 0xff, MAX_COMMAND_SIZE);
-#if LINUX_VERSION_CODE >= 0x020322
+        gdtcmd.BoardNode = LOCALBOARD;
+        gdtcmd.Service = CACHESERVICE;
+        gdtcmd.OpCode = GDT_RESET;
+        TRACE2(("gdth_halt(): reset controller %d\n", 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) {
+            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);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
         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);
 #else
         memset(&sdev,0,sizeof(Scsi_Device));
         memset(&scp, 0,sizeof(Scsi_Cmnd));
         sdev.host = scp.host = gdth_ctr_tab[hanum];
         sdev.id = scp.target = sdev.host->this_id;
         scp.device = &sdev;
-#endif
-
-        gdtcmd.BoardNode = LOCALBOARD;
-        gdtcmd.Service = CACHESERVICE;
-        gdtcmd.OpCode = GDT_RESET;
-        TRACE2(("gdth_halt(): reset controller %d\n", hanum));
-#if LINUX_VERSION_CODE >= 0x020322
-        gdth_do_cmd(scp, &gdtcmd, cmnd, 10);
-        scsi_release_command(scp);
-        scsi_free_host_dev(sdev);
-#else
         gdth_do_cmd(&scp, &gdtcmd, cmnd, 10);
 #endif
 #endif
@@ -4743,15 +6190,12 @@
 #ifdef GDTH_STATISTICS
     del_timer(&gdth_timer);
 #endif
-#if LINUX_VERSION_CODE >= 0x020100
     unregister_reboot_notifier(&gdth_notifier);
     return NOTIFY_OK;
-#endif
 }
-#endif
 
 
-#if LINUX_VERSION_CODE < 0x020400 && !defined(MODULE)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0) && !defined(MODULE)
 
 GDTH_INITFUNC(void, gdth_setup(char *str,int *ints)) 
 {    
@@ -4762,7 +6206,37 @@
 
 #else
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+static Scsi_Host_Template driver_template = {
+        .proc_name              = "gdth", 
+        .proc_info              = gdth_proc_info,
+        .name                   = "GDT SCSI Disk Array Controller",
+        .detect                 = gdth_detect, 
+        .release                = gdth_release,
+        .info                   = gdth_info, 
+        .queuecommand           = gdth_queuecommand,
+        .eh_abort_handler       = gdth_eh_abort, 
+        .eh_device_reset_handler = gdth_eh_device_reset,
+        .eh_bus_reset_handler   = gdth_eh_bus_reset,
+        .eh_host_reset_handler  = gdth_eh_host_reset,
+        .bios_param             = gdth_bios_param,
+        .can_queue              = GDTH_MAXCMDS,
+        .this_id                = -1,
+        .sg_tablesize           = GDTH_MAXSG,
+        .cmd_per_lun            = GDTH_MAXC_P_L,
+        .unchecked_isa_dma      = 1,
+        .use_clustering         = ENABLE_CLUSTERING,
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+        .use_new_eh_code        = 1,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20)
+        .highmem_io             = 1,
+#endif
+#endif
+};
+#else
 static Scsi_Host_Template driver_template = GDTH;
+#endif
+
 #include "scsi_module.c"
 #ifndef MODULE
 __setup("gdth=", option_setup);
diff -Nru a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h
--- a/drivers/scsi/gdth.h	2002-10-08 04:23:41 -07:00
+++ b/drivers/scsi/gdth.h	2004-09-27 04:36:43 -07:00
@@ -4,21 +4,18 @@
 /*
  * Header file for the GDT Disk Array/Storage RAID controllers driver for Linux
  * 
- * gdth.h Copyright (C) 1995-02 ICP vortex, an Intel company, Achim Leubner
+ * gdth.h Copyright (C) 1995-03 ICP vortex, Achim Leubner
  * See gdth.c for further informations and 
  * below for supported controller types
  *
- * <achim.leubner@intel.com>
+ * <achim_leubner@adaptec.com>
  *
- * $Id: gdth.h,v 1.46 2002/02/05 09:39:53 achim Exp $
+ * $Id: gdth.h,v 1.57 2004/03/31 11:52:09 achim Exp $
  */
 
 #include <linux/version.h>
 #include <linux/types.h>
 
-#ifndef NULL
-#define NULL 0
-#endif
 #ifndef TRUE
 #define TRUE 1
 #endif
@@ -29,16 +26,16 @@
 /* defines, macros */
 
 /* driver version */
-#define GDTH_VERSION_STR        "2.05"
-#define GDTH_VERSION            2
-#define GDTH_SUBVERSION         5
+#define GDTH_VERSION_STR        "3.04"
+#define GDTH_VERSION            3
+#define GDTH_SUBVERSION         4
 
 /* protocol version */
 #define PROTOCOL_VERSION        1
 
 /* OEM IDs */
-#define OEM_ID_ICP	0x941c
-#define OEM_ID_INTEL	0x8000
+#define OEM_ID_ICP      0x941c
+#define OEM_ID_INTEL    0x8000
 
 /* controller classes */
 #define GDT_ISA         0x01                    /* ISA controller */
@@ -134,18 +131,27 @@
 
 #ifndef PCI_DEVICE_ID_VORTEX_GDTNEWRX
 /* new GDT Rx Controller */
-#define PCI_DEVICE_ID_VORTEX_GDTNEWRX	0x300
+#define PCI_DEVICE_ID_VORTEX_GDTNEWRX   0x300
 #endif
-	
+
+#ifndef PCI_DEVICE_ID_VORTEX_GDTNEWRX2
+/* new(2) GDT Rx Controller */
+#define PCI_DEVICE_ID_VORTEX_GDTNEWRX2  0x301
+#endif        
+
 #ifndef PCI_DEVICE_ID_INTEL_SRC
 /* Intel Storage RAID Controller */
-#define PCI_DEVICE_ID_INTEL_SRC		0x600
+#define PCI_DEVICE_ID_INTEL_SRC         0x600
+#endif
+
+#ifndef PCI_DEVICE_ID_INTEL_SRC_XSCALE
+/* Intel Storage RAID Controller */
+#define PCI_DEVICE_ID_INTEL_SRC_XSCALE  0x601
 #endif
 
 /* limits */
 #define GDTH_SCRATCH    PAGE_SIZE               /* 4KB scratch buffer */
-#define GDTH_SCRATCH_ORD 0                      /* order 0 means 1 page */
-#define GDTH_MAXCMDS    124
+#define GDTH_MAXCMDS    120
 #define GDTH_MAXC_P_L   16                      /* max. cmds per lun */
 #define GDTH_MAX_RAW    2                       /* max. cmds per raw device */
 #define MAXOFFSETS      128
@@ -153,8 +159,6 @@
 #define MAXID           127
 #define MAXLUN          8
 #define MAXBUS          6
-#define MAX_HDRIVES     100                     /* max. host drive count */
-#define MAX_LDRIVES     255                     /* max. log. drive count */
 #define MAX_EVENTS      100                     /* event buffer count */
 #define MAX_RES_ARGS    40                      /* device reservation, 
                                                    must be a multiple of 4 */
@@ -221,6 +225,8 @@
 #define GDT_CLUST_RESET 24                      /* releases the cluster drives*/
 #define GDT_FREEZE_IO   25                      /* freezes all IOs */
 #define GDT_UNFREEZE_IO 26                      /* unfreezes all IOs */
+#define GDT_X_INIT_HOST 29                      /* ext. init: 64 bit support */
+#define GDT_X_INFO      30                      /* ext. info for drives>2TB */
 
 /* raw service commands */
 #define GDT_RESERVE     14                      /* reserve dev. to raw serv. */
@@ -230,9 +236,11 @@
 #define GDT_RESET_BUS   18                      /* reset bus */
 #define GDT_SCAN_START  19                      /* start device scan */
 #define GDT_SCAN_END    20                      /* stop device scan */  
+#define GDT_X_INIT_RAW  21                      /* ext. init: 64 bit support */
 
 /* screen service commands */
 #define GDT_REALTIME    3                       /* realtime clock to screens. */
+#define GDT_X_INIT_SCR  4                       /* ext. init: 64 bit support */
 
 /* IOCTL command defines */
 #define SCSI_DR_INFO    0x00                    /* SCSI drive info */                   
@@ -254,6 +262,9 @@
 #define CACHE_DRV_INFO  0x07                    /* cache drive info */
 #define BOARD_FEATURES  0x15                    /* controller features */
 #define BOARD_INFO      0x28                    /* controller info */
+#define SET_PERF_MODES  0x82                    /* set mode (coalescing,..) */
+#define GET_PERF_MODES  0x83                    /* get mode */
+#define CACHE_READ_OEM_STRING_RECORD 0x84       /* read OEM string record */ 
 #define HOST_GET        0x10001L                /* get host drive list */
 #define IO_CHANNEL      0x00020000L             /* default IO channel */
 #define INVALID_CHANNEL 0x0000ffffL             /* invalid channel */
@@ -265,7 +276,8 @@
 #define S_CACHE_UNKNOWN 12                      /* cache serv.: drive unknown */
 #define S_RAW_SCSI      12                      /* raw serv.: target error */
 #define S_RAW_ILL       0xff                    /* raw serv.: illegal */
-#define S_CACHE_RESERV	-24			/* cache: reserv. conflict */	
+#define S_NOFUNC        -2                      /* unknown function */
+#define S_CACHE_RESERV  -24                     /* cache: reserv. conflict */   
 
 /* timeout values */
 #define INIT_RETRIES    100000                  /* 100000 * 1ms = 100s */
@@ -292,21 +304,28 @@
 #define MAILBOXREG      0x0c90                  /* mailbox reg. (16 bytes) */
 #define EISAREG         0x0cc0                  /* EISA configuration */
 
+/* DMA memory mappings */
+#define GDTH_MAP_NONE   0
+#define GDTH_MAP_SINGLE 1
+#define GDTH_MAP_SG     2
+#define GDTH_MAP_IOCTL  3 
+
 /* other defines */
 #define LINUX_OS        8                       /* used for cache optim. */
 #define SCATTER_GATHER  1                       /* s/g feature */
-#define GDTH_MAXSG      32                      /* max. s/g elements */
 #define SECS32          0x1f                    /* round capacity */
 #define BIOS_ID_OFFS    0x10                    /* offset contr-ID in ISABIOS */
 #define LOCALBOARD      0                       /* board node always 0 */
 #define ASYNCINDEX      0                       /* cmd index async. event */
 #define SPEZINDEX       1                       /* cmd index unknown service */
-#define GDT_WR_THROUGH  0x100                   /* WRITE_THROUGH supported */
+#define COALINDEX       (GDTH_MAXCMDS + 2)
 
+/* features */
+#define SCATTER_GATHER  1                       /* s/g feature */
+#define GDT_WR_THROUGH  0x100                   /* WRITE_THROUGH supported */
+#define GDT_64BIT       0x200                   /* 64bit / drv>2TB support */
 
-/* typedefs */
-typedef u32     ulong32;
-#define PACKED  __attribute__((packed))
+#include "gdth_ioctl.h"
 
 /* screenservice message */
 typedef struct {                               
@@ -319,7 +338,40 @@
     char        msg_text[MSGLEN+2];             /* the message text */
 } PACKED gdth_msg_str;
 
+
 /* IOCTL data structures */
+
+/* Status coalescing buffer for returning multiple requests per interrupt */
+typedef struct {
+    ulong32     status;
+    ulong32     ext_status;
+    ulong32     info0;
+    ulong32     info1;
+} PACKED gdth_coal_status;
+
+/* performance mode data structure */
+typedef struct {
+    ulong32     version;            /* The version of this IOCTL structure. */
+    ulong32     st_mode;            /* 0=dis., 1=st_buf_addr1 valid, 2=both  */
+    ulong32     st_buff_addr1;      /* physical address of status buffer 1 */
+    ulong32     st_buff_u_addr1;    /* reserved for 64 bit addressing */
+    ulong32     st_buff_indx1;      /* reserved command idx. for this buffer */
+    ulong32     st_buff_addr2;      /* physical address of status buffer 1 */
+    ulong32     st_buff_u_addr2;    /* reserved for 64 bit addressing */
+    ulong32     st_buff_indx2;      /* reserved command idx. for this buffer */
+    ulong32     st_buff_size;       /* size of each buffer in bytes */
+    ulong32     cmd_mode;           /* 0 = mode disabled, 1 = cmd_buff_addr1 */ 
+    ulong32     cmd_buff_addr1;     /* physical address of cmd buffer 1 */   
+    ulong32     cmd_buff_u_addr1;   /* reserved for 64 bit addressing */
+    ulong32     cmd_buff_indx1;     /* cmd buf addr1 unique identifier */
+    ulong32     cmd_buff_addr2;     /* physical address of cmd buffer 1 */   
+    ulong32     cmd_buff_u_addr2;   /* reserved for 64 bit addressing */
+    ulong32     cmd_buff_indx2;     /* cmd buf addr1 unique identifier */
+    ulong32     cmd_buff_size;      /* size of each cmd bufer in bytes */
+    ulong32     reserved1;
+    ulong32     reserved2;
+} PACKED gdth_perf_modes;
+
 /* SCSI drive info */
 typedef struct {
     unchar      vendor[8];                      /* vendor string */
@@ -535,6 +587,50 @@
     unchar      ld_error;                       /* error */
 } PACKED gdth_cdrinfo_str;
 
+/* OEM string */
+typedef struct {
+    ulong32     ctl_version;
+    ulong32     file_major_version;
+    ulong32     file_minor_version;
+    ulong32     buffer_size;
+    ulong32     cpy_count;
+    ulong32     ext_error;
+    ulong32     oem_id;
+    ulong32     board_id;
+} PACKED gdth_oem_str_params;
+
+typedef struct {
+    unchar      product_0_1_name[16];
+    unchar      product_4_5_name[16];
+    unchar      product_cluster_name[16];
+    unchar      product_reserved[16];
+    unchar      scsi_cluster_target_vendor_id[16];
+    unchar      cluster_raid_fw_name[16];
+    unchar      oem_brand_name[16];
+    unchar      oem_raid_type[16];
+    unchar      bios_type[13];
+    unchar      bios_title[50];
+    unchar      oem_company_name[37];
+    ulong32     pci_id_1;
+    ulong32     pci_id_2;
+    unchar      validation_status[80];
+    unchar      reserved_1[4];
+    unchar      scsi_host_drive_inquiry_vendor_id[16];
+    unchar      library_file_template[16];
+    unchar      reserved_2[16];
+    unchar      tool_name_1[32];
+    unchar      tool_name_2[32];
+    unchar      tool_name_3[32];
+    unchar      oem_contact_1[84];
+    unchar      oem_contact_2[84];
+    unchar      oem_contact_3[84];
+} PACKED gdth_oem_str;
+
+typedef struct {
+    gdth_oem_str_params params;
+    gdth_oem_str        text;
+} PACKED gdth_oem_str_ioctl;
+
 /* board features */
 typedef struct {
     unchar      chaining;                       /* Chaining supported */
@@ -594,118 +690,6 @@
     gdth_hentry_str entry[MAX_HDRIVES];         /* entries */
 } PACKED gdth_hget_str;    
 
-/* scatter/gather element */
-typedef struct {
-    ulong32     sg_ptr;                         /* address */
-    ulong32     sg_len;                         /* length */
-} PACKED gdth_sg_str;
-
-/* command structure */
-typedef struct {
-    ulong32     BoardNode;                      /* board node (always 0) */
-    ulong32     CommandIndex;                   /* command number */
-    ushort      OpCode;                         /* the command (READ,..) */
-    union {
-        struct {
-            ushort      DeviceNo;               /* number of cache drive */
-            ulong32     BlockNo;                /* block number */
-            ulong32     BlockCnt;               /* block count */
-            ulong32     DestAddr;               /* dest. addr. (if s/g: -1) */
-            ulong32     sg_canz;                /* s/g element count */
-            gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
-        } PACKED cache;                         /* cache service cmd. str. */
-        struct {
-            ushort      param_size;             /* size of p_param buffer */
-            ulong32     subfunc;                /* IOCTL function */
-            ulong32     channel;                /* device */
-            ulong32     p_param;                /* buffer */
-        } PACKED ioctl;                         /* IOCTL command structure */
-        struct {
-            ushort      reserved;
-            union {
-                struct {
-                    ulong32  msg_handle;        /* message handle */
-                    ulong32  msg_addr;          /* message buffer address */
-                } PACKED msg;
-                unchar       data[12];          /* buffer for rtc data, ... */
-            } su;
-        } PACKED screen;                        /* screen service cmd. str. */
-        struct {
-            ushort      reserved;
-            ulong32     direction;              /* data direction */
-            ulong32     mdisc_time;             /* disc. time (0: no timeout)*/
-            ulong32     mcon_time;              /* connect time(0: no to.) */
-            ulong32     sdata;                  /* dest. addr. (if s/g: -1) */
-            ulong32     sdlen;                  /* data length (bytes) */
-            ulong32     clen;                   /* SCSI cmd. length(6,10,12) */
-            unchar      cmd[12];                /* SCSI command */
-            unchar      target;                 /* target ID */
-            unchar      lun;                    /* LUN */
-            unchar      bus;                    /* SCSI bus number */
-            unchar      priority;               /* only 0 used */
-            ulong32     sense_len;              /* sense data length */
-            ulong32     sense_data;             /* sense data addr. */
-            ulong32     link_p;                 /* linked cmds (not supp.) */
-            ulong32     sg_ranz;                /* s/g element count */
-            gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
-        } PACKED raw;                           /* raw service cmd. struct. */
-    } u;
-    /* additional variables */
-    unchar      Service;                        /* controller service */
-    ushort      Status;                         /* command result */
-    ulong32     Info;                           /* additional information */
-    Scsi_Cmnd   *RequestBuffer;                 /* request buffer */
-} PACKED gdth_cmd_str;
-
-/* controller event structure */
-#define ES_ASYNC    1
-#define ES_DRIVER   2
-#define ES_TEST     3
-#define ES_SYNC     4
-typedef struct {
-    ushort                  size;               /* size of structure */
-    union {
-        char                stream[16];
-        struct {
-            ushort          ionode;
-            ushort          service;
-            ulong32         index;
-        } PACKED driver;
-        struct {
-            ushort          ionode;
-            ushort          service;
-            ushort          status;
-            ulong32         info;
-            unchar          scsi_coord[3];
-        } PACKED async;
-        struct {
-            ushort          ionode;
-            ushort          service;
-            ushort          status;
-            ulong32         info;
-            ushort          hostdrive;
-            unchar          scsi_coord[3];
-            unchar          sense_key;
-        } PACKED sync;
-        struct {
-            ulong32         l1, l2, l3, l4;
-        } PACKED test;
-    } eu;
-    ulong32                 severity;
-    unchar                  event_string[256];          
-} PACKED gdth_evt_data;
-
-typedef struct {
-    ulong32         first_stamp;
-    ulong32         last_stamp;
-    ushort          same_count;
-    ushort          event_source;
-    ushort          event_idx;
-    unchar          application;
-    unchar          reserved;
-    gdth_evt_data   event_data;
-} PACKED gdth_evt_str;
-
 
 /* DPRAM structures */
 
@@ -860,9 +844,7 @@
 
 /* PCI resources */
 typedef struct {
-#if LINUX_VERSION_CODE >= 0x02015C
     struct pci_dev      *pdev;
-#endif
     ushort              vendor_id;              /* vendor (ICP, Intel, ..) */
     ushort              device_id;              /* device ID (0,..,9) */
     ushort              subdevice_id;           /* sub device ID */
@@ -879,18 +861,28 @@
 typedef struct {
     ushort              oem_id;                 /* OEM */
     ushort              type;                   /* controller class */
-    ushort              raw_feat;               /* feat. raw service (s/g,..) */
     ulong32             stype;                  /* subtype (PCI: device ID) */
     ushort              subdevice_id;           /* sub device ID (PCI) */
     ushort              fw_vers;                /* firmware version */
-    ushort              cache_feat;             /* feat. cache serv. (s/g,..) */
+    ushort              cache_feat;             /* feat. cache serv. (s/g,..)*/
+    ushort              raw_feat;               /* feat. raw service (s/g,..)*/
+    ushort              screen_feat;            /* feat. raw service (s/g,..)*/
     ushort              bmic;                   /* BMIC address (EISA) */
     void                *brd;                   /* DPRAM address */
     ulong32             brd_phys;               /* slot number/BIOS address */
     gdt6c_plx_regs      *plx;                   /* PLX regs (new PCI contr.) */
     gdth_cmd_str        *pccb;                  /* address command structure */
+    ulong32             ccb_phys;               /* phys. address */
+#ifdef INT_COAL
+    gdth_coal_status    *coal_stat;             /* buffer for coalescing int.*/
+    ulong64             coal_stat_phys;         /* phys. address */
+#endif
     char                *pscratch;              /* scratch (DMA) buffer */
+    ulong64             scratch_phys;           /* phys. address */
     unchar              scratch_busy;           /* in use? */
+    unchar              dma64_support;          /* 64-bit DMA supported? */
+    gdth_msg_str        *pmsg;                  /* message buffer */
+    ulong64             msg_phys;               /* phys. address */
     unchar              scan_mode;              /* current scan mode */
     unchar              irq;                    /* IRQ */
     unchar              drq;                    /* DRQ (ISA controllers) */
@@ -911,7 +903,7 @@
         unchar          heads;                  /* mapping */
         unchar          secs;
         ushort          devtype;                /* further information */
-        ulong32         size;                   /* capacity */
+        ulong64         size;                   /* capacity */
         unchar          ldr_no;                 /* log. drive no. */
         unchar          rw_attribs;             /* r/w attributes */
         unchar          cluster_type;           /* cluster properties */
@@ -943,8 +935,18 @@
     gdth_bfeat_str      bfeat;                  /* controller features */
     gdth_binfo_str      binfo;                  /* controller info */
     gdth_evt_data       dvr;                    /* event structure */
-#if LINUX_VERSION_CODE >= 0x02015F
     spinlock_t          smp_lock;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    struct pci_dev      *pdev;
+#endif
+    char                oem_name[8];
+#ifdef GDTH_DMA_STATISTICS
+    ulong               dma32_cnt, dma64_cnt;   /* statistics: DMA buffer */
+#endif
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    Scsi_Device         *sdev;
+#else
+    Scsi_Device         sdev;
 #endif
 } gdth_ha_str;
 
@@ -983,6 +985,12 @@
     ulong32     block_length;
 } PACKED gdth_rdcap_data;
 
+/* READ_CAPACITY (16) data format */
+typedef struct {
+    ulong64     last_block_no;
+    ulong32     block_length;
+} PACKED gdth_rdcap16_data;
+
 /* REQUEST_SENSE data format */
 typedef struct {
     unchar      errorcode;
@@ -1024,53 +1032,20 @@
 int gdth_detect(Scsi_Host_Template *);
 int gdth_release(struct Scsi_Host *);
 int gdth_queuecommand(Scsi_Cmnd *,void (*done)(Scsi_Cmnd *));
-int gdth_abort(Scsi_Cmnd *);
-#if LINUX_VERSION_CODE >= 0x010346
-int gdth_reset(Scsi_Cmnd *, unsigned int reset_flags);
-#else
-int gdth_reset(Scsi_Cmnd *);
-#endif
 const char *gdth_info(struct Scsi_Host *);
 
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+int gdth_bios_param(struct scsi_device *,struct block_device *,sector_t,int *);
+int gdth_proc_info(struct Scsi_Host *, char *,char **,off_t,int,int);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 int gdth_bios_param(Disk *,kdev_t,int *);
 int gdth_proc_info(char *,char **,off_t,int,int,int);
-int gdth_eh_abort(Scsi_Cmnd *scp);
-int gdth_eh_device_reset(Scsi_Cmnd *scp);
-int gdth_eh_bus_reset(Scsi_Cmnd *scp);
-int gdth_eh_host_reset(Scsi_Cmnd *scp);
-#define GDTH { proc_name:       "gdth",                          \
-               proc_info:       gdth_proc_info,                  \
-               name:            "GDT SCSI Disk Array Controller",\
-               detect:          gdth_detect,                     \
-               release:         gdth_release,                    \
-               info:            gdth_info,                       \
-               command:         NULL,                            \
-               queuecommand:    gdth_queuecommand,               \
-               eh_abort_handler: gdth_eh_abort,                  \
-               eh_device_reset_handler: gdth_eh_device_reset,    \
-               eh_bus_reset_handler: gdth_eh_bus_reset,          \
-               eh_host_reset_handler: gdth_eh_host_reset,        \
-               abort:           gdth_abort,                      \
-               reset:           gdth_reset,                      \
-               bios_param:      gdth_bios_param,                 \
-               can_queue:       GDTH_MAXCMDS,                    \
-               this_id:         -1,                              \
-               sg_tablesize:    GDTH_MAXSG,                      \
-               cmd_per_lun:     GDTH_MAXC_P_L,                   \
-               present:         0,                               \
-               unchecked_isa_dma: 1,                             \
-               use_clustering:  ENABLE_CLUSTERING,               \
-               use_new_eh_code: 1       /* use new error code */ }    
-
-#elif LINUX_VERSION_CODE >= 0x02015F
+#else
 int gdth_bios_param(Disk *,kdev_t,int *);
 extern struct proc_dir_entry proc_scsi_gdth;
 int gdth_proc_info(char *,char **,off_t,int,int,int);
-int gdth_eh_abort(Scsi_Cmnd *scp);
-int gdth_eh_device_reset(Scsi_Cmnd *scp);
-int gdth_eh_bus_reset(Scsi_Cmnd *scp);
-int gdth_eh_host_reset(Scsi_Cmnd *scp);
+int gdth_abort(Scsi_Cmnd *);
+int gdth_reset(Scsi_Cmnd *,unsigned int); 
 #define GDTH { proc_dir:        &proc_scsi_gdth,                 \
                proc_info:       gdth_proc_info,                  \
                name:            "GDT SCSI Disk Array Controller",\
@@ -1094,53 +1069,11 @@
                unchecked_isa_dma: 1,                             \
                use_clustering:  ENABLE_CLUSTERING,               \
                use_new_eh_code: 1       /* use new error code */ }    
-
-#elif LINUX_VERSION_CODE >= 0x010300
-int gdth_bios_param(Disk *,kdev_t,int *);
-extern struct proc_dir_entry proc_scsi_gdth;
-int gdth_proc_info(char *,char **,off_t,int,int,int);
-#define GDTH { NULL, NULL,                              \
-                   &proc_scsi_gdth,                     \
-                   gdth_proc_info,                      \
-                   "GDT SCSI Disk Array Controller",    \
-                   gdth_detect,                         \
-                   gdth_release,                        \
-                   gdth_info,                           \
-                   NULL,                                \
-                   gdth_queuecommand,                   \
-                   gdth_abort,                          \
-                   gdth_reset,                          \
-                   NULL,                                \
-                   gdth_bios_param,                     \
-                   GDTH_MAXCMDS,                        \
-                   -1,                                  \
-                   GDTH_MAXSG,                          \
-                   GDTH_MAXC_P_L,                       \
-                   0,                                   \
-                   1,                                   \
-                   ENABLE_CLUSTERING}
-
-#else
-int gdth_bios_param(Disk *,int,int *);
-#define GDTH { NULL, NULL,                              \
-                   "GDT SCSI Disk Array Controller",    \
-                   gdth_detect,                         \
-                   gdth_release,                        \
-                   gdth_info,                           \
-                   NULL,                                \
-                   gdth_queuecommand,                   \
-                   gdth_abort,                          \
-                   gdth_reset,                          \
-                   NULL,                                \
-                   gdth_bios_param,                     \
-                   GDTH_MAXCMDS,                        \
-                   -1,                                  \
-                   GDTH_MAXSG,                          \
-                   GDTH_MAXC_P_L,                       \
-                   0,                                   \
-                   1,                                   \
-                   ENABLE_CLUSTERING}
 #endif
 
-#endif
+int gdth_eh_abort(Scsi_Cmnd *scp);
+int gdth_eh_device_reset(Scsi_Cmnd *scp);
+int gdth_eh_bus_reset(Scsi_Cmnd *scp);
+int gdth_eh_host_reset(Scsi_Cmnd *scp);
 
+#endif
diff -Nru a/drivers/scsi/gdth_ioctl.h b/drivers/scsi/gdth_ioctl.h
--- a/drivers/scsi/gdth_ioctl.h	2002-02-04 23:44:55 -08:00
+++ b/drivers/scsi/gdth_ioctl.h	2004-09-27 04:21:44 -07:00
@@ -2,7 +2,7 @@
 #define _GDTH_IOCTL_H
 
 /* gdth_ioctl.h
- * $Id: gdth_ioctl.h,v 1.10 2001/05/22 06:28:59 achim Exp $
+ * $Id: gdth_ioctl.h,v 1.14 2004/02/19 15:43:15 achim Exp $
  */
 
 /* IOCTLs */
@@ -21,10 +21,172 @@
 #define GDTIOCTL_RESCAN     (GDTIOCTL_MASK |11) /* rescan host drives */
 #define GDTIOCTL_RESET_DRV  (GDTIOCTL_MASK |12) /* reset (remote) drv. res. */
 
-#define GDTIOCTL_MAGIC      0xaffe0004
-#define EVENT_SIZE          294 
-#define MAX_HDRIVES         100                     
+#define GDTIOCTL_MAGIC  0xaffe0004
+#define EVENT_SIZE      294 
+#define GDTH_MAXSG      32                      /* max. s/g elements */
 
+#define MAX_LDRIVES     255                     /* max. log. drive count */
+#ifdef GDTH_IOCTL_PROC
+#define MAX_HDRIVES     100                     /* max. host drive count */
+#else
+#define MAX_HDRIVES     MAX_LDRIVES             /* max. host drive count */
+#endif
+
+/* typedefs */
+#ifdef __KERNEL__
+typedef u32     ulong32;
+typedef u64     ulong64;
+#endif
+
+#define PACKED  __attribute__((packed))
+
+/* scatter/gather element */
+typedef struct {
+    ulong32     sg_ptr;                         /* address */
+    ulong32     sg_len;                         /* length */
+} PACKED gdth_sg_str;
+
+/* scatter/gather element - 64bit addresses */
+typedef struct {
+    ulong64     sg_ptr;                         /* address */
+    ulong32     sg_len;                         /* length */
+} PACKED gdth_sg64_str;
+
+/* command structure */
+typedef struct {
+    ulong32     BoardNode;                      /* board node (always 0) */
+    ulong32     CommandIndex;                   /* command number */
+    ushort      OpCode;                         /* the command (READ,..) */
+    union {
+        struct {
+            ushort      DeviceNo;               /* number of cache drive */
+            ulong32     BlockNo;                /* block number */
+            ulong32     BlockCnt;               /* block count */
+            ulong32     DestAddr;               /* dest. addr. (if s/g: -1) */
+            ulong32     sg_canz;                /* s/g element count */
+            gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
+        } PACKED cache;                         /* cache service cmd. str. */
+        struct {
+            ushort      DeviceNo;               /* number of cache drive */
+            ulong64     BlockNo;                /* block number */
+            ulong32     BlockCnt;               /* block count */
+            ulong64     DestAddr;               /* dest. addr. (if s/g: -1) */
+            ulong32     sg_canz;                /* s/g element count */
+            gdth_sg64_str sg_lst[GDTH_MAXSG];   /* s/g list */
+        } PACKED cache64;                       /* cache service cmd. str. */
+        struct {
+            ushort      param_size;             /* size of p_param buffer */
+            ulong32     subfunc;                /* IOCTL function */
+            ulong32     channel;                /* device */
+            ulong64     p_param;                /* buffer */
+        } PACKED ioctl;                         /* IOCTL command structure */
+        struct {
+            ushort      reserved;
+            union {
+                struct {
+                    ulong32  msg_handle;        /* message handle */
+                    ulong64  msg_addr;          /* message buffer address */
+                } PACKED msg;
+                unchar       data[12];          /* buffer for rtc data, ... */
+            } su;
+        } PACKED screen;                        /* screen service cmd. str. */
+        struct {
+            ushort      reserved;
+            ulong32     direction;              /* data direction */
+            ulong32     mdisc_time;             /* disc. time (0: no timeout)*/
+            ulong32     mcon_time;              /* connect time(0: no to.) */
+            ulong32     sdata;                  /* dest. addr. (if s/g: -1) */
+            ulong32     sdlen;                  /* data length (bytes) */
+            ulong32     clen;                   /* SCSI cmd. length(6,10,12) */
+            unchar      cmd[12];                /* SCSI command */
+            unchar      target;                 /* target ID */
+            unchar      lun;                    /* LUN */
+            unchar      bus;                    /* SCSI bus number */
+            unchar      priority;               /* only 0 used */
+            ulong32     sense_len;              /* sense data length */
+            ulong32     sense_data;             /* sense data addr. */
+            ulong32     link_p;                 /* linked cmds (not supp.) */
+            ulong32     sg_ranz;                /* s/g element count */
+            gdth_sg_str sg_lst[GDTH_MAXSG];     /* s/g list */
+        } PACKED raw;                           /* raw service cmd. struct. */
+        struct {
+            ushort      reserved;
+            ulong32     direction;              /* data direction */
+            ulong32     mdisc_time;             /* disc. time (0: no timeout)*/
+            ulong32     mcon_time;              /* connect time(0: no to.) */
+            ulong64     sdata;                  /* dest. addr. (if s/g: -1) */
+            ulong32     sdlen;                  /* data length (bytes) */
+            ulong32     clen;                   /* SCSI cmd. length(6,..,16) */
+            unchar      cmd[16];                /* SCSI command */
+            unchar      target;                 /* target ID */
+            unchar      lun;                    /* LUN */
+            unchar      bus;                    /* SCSI bus number */
+            unchar      priority;               /* only 0 used */
+            ulong32     sense_len;              /* sense data length */
+            ulong64     sense_data;             /* sense data addr. */
+            ulong32     sg_ranz;                /* s/g element count */
+            gdth_sg64_str sg_lst[GDTH_MAXSG];   /* s/g list */
+        } PACKED raw64;                         /* raw service cmd. struct. */
+    } u;
+    /* additional variables */
+    unchar      Service;                        /* controller service */
+    unchar      reserved;
+    ushort      Status;                         /* command result */
+    ulong32     Info;                           /* additional information */
+    void        *RequestBuffer;                 /* request buffer */
+} PACKED gdth_cmd_str;
+
+/* controller event structure */
+#define ES_ASYNC    1
+#define ES_DRIVER   2
+#define ES_TEST     3
+#define ES_SYNC     4
+typedef struct {
+    ushort                  size;               /* size of structure */
+    union {
+        char                stream[16];
+        struct {
+            ushort          ionode;
+            ushort          service;
+            ulong32         index;
+        } PACKED driver;
+        struct {
+            ushort          ionode;
+            ushort          service;
+            ushort          status;
+            ulong32         info;
+            unchar          scsi_coord[3];
+        } PACKED async;
+        struct {
+            ushort          ionode;
+            ushort          service;
+            ushort          status;
+            ulong32         info;
+            ushort          hostdrive;
+            unchar          scsi_coord[3];
+            unchar          sense_key;
+        } PACKED sync;
+        struct {
+            ulong32         l1, l2, l3, l4;
+        } PACKED test;
+    } eu;
+    ulong32                 severity;
+    unchar                  event_string[256];          
+} PACKED gdth_evt_data;
+
+typedef struct {
+    ulong32         first_stamp;
+    ulong32         last_stamp;
+    ushort          same_count;
+    ushort          event_source;
+    ushort          event_idx;
+    unchar          application;
+    unchar          reserved;
+    gdth_evt_data   event_data;
+} PACKED gdth_evt_str;
+
+
+#ifdef GDTH_IOCTL_PROC
 /* IOCTL structure (write) */
 typedef struct {
     ulong32                 magic;              /* IOCTL magic */
@@ -106,7 +268,80 @@
         } hdr_list[MAX_HDRIVES];                /* index is host drive number */
     } iu;
 } gdth_iord_str;
+#endif
 
+/* GDTIOCTL_GENERAL */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    ushort timeout;                             /* timeout */
+    ulong32 info;                               /* error info */ 
+    ushort status;                              /* status */
+    ulong data_len;                             /* data buffer size */
+    ulong sense_len;                            /* sense buffer size */
+    gdth_cmd_str command;                       /* command */                   
+} gdth_ioctl_general;
 
-#endif
+/* GDTIOCTL_LOCKDRV */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    unchar lock;                                /* lock/unlock */
+    unchar drive_cnt;                           /* drive count */
+    ushort drives[MAX_HDRIVES];                 /* drives */
+} gdth_ioctl_lockdrv;
+
+/* GDTIOCTL_LOCKCHN */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    unchar lock;                                /* lock/unlock */
+    unchar channel;                             /* channel */
+} gdth_ioctl_lockchn;
+
+/* GDTIOCTL_OSVERS */
+typedef struct {
+    unchar version;                             /* OS version */
+    unchar subversion;                          /* OS subversion */
+    ushort revision;                            /* revision */
+} gdth_ioctl_osvers;
 
+/* GDTIOCTL_CTRTYPE */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    unchar type;                                /* controller type */
+    ushort info;                                /* slot etc. */
+    ushort oem_id;                              /* OEM ID */
+    ushort bios_ver;                            /* not used */
+    ushort access;                              /* not used */
+    ushort ext_type;                            /* extended type */
+    ushort device_id;                           /* device ID */
+    ushort sub_device_id;                       /* sub device ID */
+} gdth_ioctl_ctrtype;
+
+/* GDTIOCTL_EVENT */
+typedef struct {
+    ushort ionode;
+    int erase;                                  /* erase event? */
+    int handle;                                 /* event handle */
+    gdth_evt_str event;
+} gdth_ioctl_event;
+
+/* GDTIOCTL_RESCAN/GDTIOCTL_HDRLIST */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    unchar flag;                                /* add/remove */
+    ushort hdr_no;                              /* drive no. */
+    struct {
+        unchar bus;                             /* SCSI bus */
+        unchar target;                          /* target ID */
+        unchar lun;                             /* LUN */
+        unchar cluster_type;                    /* cluster properties */
+    } hdr_list[MAX_HDRIVES];                    /* index is host drive number */
+} gdth_ioctl_rescan;
+
+/* GDTIOCTL_RESET_BUS/GDTIOCTL_RESET_DRV */
+typedef struct {
+    ushort ionode;                              /* controller number */
+    ushort number;                              /* bus/host drive number */
+    ushort status;                              /* status */
+} gdth_ioctl_reset;
+
+#endif
diff -Nru a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c
--- a/drivers/scsi/gdth_proc.c	2002-12-02 07:18:47 -08:00
+++ b/drivers/scsi/gdth_proc.c	2004-09-27 04:21:44 -07:00
@@ -1,53 +1,80 @@
 /* gdth_proc.c 
- * $Id: gdth_proc.c,v 1.33 2001/08/10 07:54:39 achim Exp $
+ * $Id: gdth_proc.c,v 1.42 2004/03/05 15:50:20 achim Exp $
  */
 
-#include "gdth_ioctl.h"
-#if LINUX_VERSION_CODE >= 0x020407
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
 #include <linux/completion.h>
 #endif
 
-int gdth_proc_info(char *buffer,char **start,off_t offset,int length,   
-                   int hostno,int inout)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length,   
+                   int inout)
+{
+    int hanum,busnum;
+
+    TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
+            length,(int)offset,inout));
+
+    hanum = NUMDATA(host)->hanum;
+    busnum= NUMDATA(host)->busnum;
+
+    if (inout)
+        return(gdth_set_info(buffer,length,host,hanum,busnum));
+    else
+        return(gdth_get_info(buffer,start,offset,length,host,hanum,busnum));
+}
+#else
+int gdth_proc_info(char *buffer,char **start,off_t offset,int length,int hostno,   
+                   int inout)
 {
     int hanum,busnum,i;
 
-    TRACE2(("gdth_proc_info() length %d ha %d offs %d inout %d\n",
-            length,hostno,(int)offset,inout));
+    TRACE2(("gdth_proc_info() length %d offs %d inout %d\n",
+            length,(int)offset,inout));
 
-    for (i=0; i<gdth_ctr_vcount; ++i) {
+    for (i = 0; i < gdth_ctr_vcount; ++i) {
         if (gdth_ctr_vtab[i]->host_no == hostno)
             break;
     }
-    if (i==gdth_ctr_vcount)
+    if (i == gdth_ctr_vcount)
         return(-EINVAL);
 
     hanum = NUMDATA(gdth_ctr_vtab[i])->hanum;
     busnum= NUMDATA(gdth_ctr_vtab[i])->busnum;
 
     if (inout)
-        return(gdth_set_info(buffer,length,i,hanum,busnum));
+        return(gdth_set_info(buffer,length,gdth_ctr_vtab[i],hanum,busnum));
     else
-        return(gdth_get_info(buffer,start,offset,length,i,hanum,busnum));
+        return(gdth_get_info(buffer,start,offset,length,
+                             gdth_ctr_vtab[i],hanum,busnum));
 }
+#endif
 
-static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum)
+static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
+                         int hanum,int busnum)
 {
-    int             ret_val;
-#if LINUX_VERSION_CODE >= 0x020322
+    int             ret_val = -EINVAL;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Request    *scp;
+    Scsi_Device     *sdev;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     Scsi_Cmnd       *scp;
     Scsi_Device     *sdev;
 #else
     Scsi_Cmnd       scp;
     Scsi_Device     sdev;
 #endif
-    gdth_iowr_str   *piowr;
-
     TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum));
-    piowr = (gdth_iowr_str *)buffer;
 
-#if LINUX_VERSION_CODE >= 0x020322
-    sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    sdev = scsi_get_host_dev(host);
+    scp  = scsi_allocate_request(sdev, GFP_KERNEL);
+    if (!scp)
+        return -ENOMEM;
+    scp->sr_cmd_len = 12;
+    scp->sr_use_sg = 0;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    sdev = scsi_get_host_dev(host);
     scp  = scsi_allocate_device(sdev, 1, FALSE);
     if (!scp)
         return -ENOMEM;
@@ -56,7 +83,7 @@
 #else
     memset(&sdev,0,sizeof(Scsi_Device));
     memset(&scp, 0,sizeof(Scsi_Cmnd));
-    sdev.host = scp.host = gdth_ctr_vtab[vh];
+    sdev.host = scp.host = host;
     sdev.id = scp.target = sdev.host->this_id;
     scp.device = &sdev;
 #endif
@@ -66,28 +93,21 @@
             buffer += 5;
             length -= 5;
             ret_val = gdth_set_asc_info( buffer, length, hanum, scp );
-        } else if (piowr->magic == GDTIOCTL_MAGIC) {
-            ret_val = gdth_set_bin_info( buffer, length, hanum, scp );
-        } else {
-            printk("GDT: Wrong signature %x (%x required)!\n",
-                   piowr->magic, GDTIOCTL_MAGIC);
-            if (piowr->magic > GDTIOCTL_MAGIC)
-                printk("GDT: Please update your driver.\n");
-            else
-                printk("GDT: Please update your tool.\n");
-            ret_val = -EINVAL;
         }
-    } else {
-        ret_val = -EINVAL;
     }
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    scsi_release_request(scp);
+    scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     scsi_release_command(scp);
     scsi_free_host_dev(sdev);
 #endif
     return ret_val;
 }
          
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp)
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
 static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
 #else
 static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
@@ -98,6 +118,7 @@
     gdth_ha_str     *ha;
     gdth_cmd_str    gdtcmd;
     gdth_cpar_str   *pcpar;
+    ulong64         paddr;
 
     char            cmnd[MAX_COMMAND_SIZE];
     memset(cmnd, 0xff, 12);
@@ -131,9 +152,16 @@
                 found = TRUE;
                 gdtcmd.Service = CACHESERVICE;
                 gdtcmd.OpCode = GDT_FLUSH;
-                gdtcmd.u.cache.DeviceNo = i;
-                gdtcmd.u.cache.BlockNo = 1;
-#if LINUX_VERSION_CODE >= 0x020322
+                if (ha->cache_feat & GDT_64BIT) {
+                    gdtcmd.u.cache64.DeviceNo = i;
+                    gdtcmd.u.cache64.BlockNo = 1;
+                } else {
+                    gdtcmd.u.cache.DeviceNo = i;
+                    gdtcmd.u.cache.BlockNo = 1;
+                }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+                gdth_do_req(scp, &gdtcmd, cmnd, 30);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
                 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
 #else
                 gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
@@ -178,23 +206,25 @@
     }
 
     if (wb_mode) {
-        if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE))
+        if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE, &paddr))
             return(-EBUSY);
         pcpar = (gdth_cpar_str *)ha->pscratch;
         memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) );
         gdtcmd.Service = CACHESERVICE;
         gdtcmd.OpCode = GDT_IOCTL;
-        gdtcmd.u.ioctl.p_param = virt_to_bus(pcpar);
+        gdtcmd.u.ioctl.p_param = paddr;
         gdtcmd.u.ioctl.param_size = sizeof(gdth_cpar_str);
         gdtcmd.u.ioctl.subfunc = CACHE_CONFIG;
         gdtcmd.u.ioctl.channel = INVALID_CHANNEL;
         pcpar->write_back = wb_mode==1 ? 0:1;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        gdth_do_req(scp, &gdtcmd, cmnd, 30);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
         gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
 #else
         gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
 #endif
-        gdth_ioctl_free(hanum, ha->pscratch);
+        gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr);
         printk("Done.\n");
         return(orig_length);
     }
@@ -203,489 +233,23 @@
     return(-EINVAL);
 }
 
-#if LINUX_VERSION_CODE >= 0x020322
-static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp)
-#else
-static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp)
-#endif
-{
-    unchar          i, j;
-    ushort          k, hdr_cnt, status;
-    gdth_ha_str     *ha;
-    gdth_iowr_str   *piowr;
-    gdth_iord_str   *piord;
-    gdth_cmd_str    *pcmd;
-    gdth_evt_str    *pevt;
-    ulong32         *ppadd, add_size, *ppadd2, add_size2, info;
-    ulong           flags;
-    gdth_cmd_str    gdtcmd;
-    int             drv_cyls, drv_hds, drv_secs;
- 
-    char            cmnd[MAX_COMMAND_SIZE];   
-    memset(cmnd, 0xff, 12);
-    memset(&gdtcmd, 0, sizeof(gdth_cmd_str));
-
-    TRACE2(("gdth_set_bin_info() ha %d\n",hanum));
-    ha = HADATA(gdth_ctr_tab[hanum]);
-    piowr = (gdth_iowr_str *)buffer;
-    piord = NULL;
-    pcmd = NULL;
-    ppadd = ppadd2 = NULL;
-    add_size = add_size2 = 0;
-
-    if (length < GDTOFFSOF(gdth_iowr_str,iu))
-        return(-EINVAL);
-
-    switch (piowr->ioctl) {
-      case GDTIOCTL_GENERAL:
-        if (length < GDTOFFSOF(gdth_iowr_str,iu.general.data[0]))
-            return(-EINVAL);
-        pcmd = (gdth_cmd_str *)piowr->iu.general.command;
-        pcmd->Service = piowr->service;
-        if (pcmd->OpCode == GDT_IOCTL) {
-            ppadd = &pcmd->u.ioctl.p_param;
-            add_size = pcmd->u.ioctl.param_size;
-        } else if (piowr->service == CACHESERVICE) {
-            add_size = pcmd->u.cache.BlockCnt * SECTOR_SIZE;
-            if (ha->cache_feat & SCATTER_GATHER) {
-                ppadd = &pcmd->u.cache.sg_lst[0].sg_ptr;
-                pcmd->u.cache.DestAddr = 0xffffffff;
-                pcmd->u.cache.sg_lst[0].sg_len = add_size;
-                pcmd->u.cache.sg_canz = 1;
-            } else {
-                ppadd = &pcmd->u.cache.DestAddr;
-                pcmd->u.cache.sg_canz = 0;
-            }
-        } else if (piowr->service == SCSIRAWSERVICE) {
-            add_size = pcmd->u.raw.sdlen;
-            add_size2 = pcmd->u.raw.sense_len;
-            if (ha->raw_feat & SCATTER_GATHER) {
-                ppadd = &pcmd->u.raw.sg_lst[0].sg_ptr;
-                pcmd->u.raw.sdata = 0xffffffff;
-                pcmd->u.raw.sg_lst[0].sg_len = add_size;
-                pcmd->u.raw.sg_ranz = 1;
-            } else {
-                ppadd = &pcmd->u.raw.sdata;
-                pcmd->u.raw.sg_ranz = 0;
-            }
-            ppadd2 = &pcmd->u.raw.sense_data;
-        } else {
-            return(-EINVAL);
-        }
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str)+add_size+add_size2,
-                               TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-
-        piord->size = sizeof(gdth_iord_str) + add_size + add_size2;
-        if (add_size > 0) {
-            memcpy(piord->iu.general.data, piowr->iu.general.data, add_size);
-            *ppadd = virt_to_bus(piord->iu.general.data);
-        }
-        if (add_size2 > 0) {
-            memcpy(piord->iu.general.data+add_size, piowr->iu.general.data, add_size2);
-            *ppadd2 = virt_to_bus(piord->iu.general.data+add_size);
-        }
-        /* do IOCTL */
-#if LINUX_VERSION_CODE >= 0x020322
-        gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout);
-        piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
-#else
-        gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout);
-        piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;
-#endif
-        break;
-
-      case GDTIOCTL_DRVERS:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-        piord->size = sizeof(gdth_iord_str);
-        piord->status = S_OK;
-        piord->iu.drvers.version = (GDTH_VERSION<<8) | GDTH_SUBVERSION;
-        break;
-
-      case GDTIOCTL_CTRTYPE:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-        piord->size = sizeof(gdth_iord_str);
-        piord->status = S_OK;
-        if (ha->type == GDT_ISA || ha->type == GDT_EISA) {
-            piord->iu.ctrtype.type = (unchar)((ha->stype>>20) - 0x10);
-        } else {
-            if (ha->type != GDT_PCIMPR) {
-                piord->iu.ctrtype.type = (unchar)((ha->stype<<4) + 6);
-            } else {
-                piord->iu.ctrtype.type = 
-                    (ha->oem_id == OEM_ID_INTEL ? 0xfd : 0xfe);
-                if (ha->stype >= 0x300)
-                    piord->iu.ctrtype.ext_type = 0x6000 | ha->subdevice_id;
-                else 
-                    piord->iu.ctrtype.ext_type = 0x6000 | ha->stype;
-            }
-            piord->iu.ctrtype.device_id = ha->stype;
-            piord->iu.ctrtype.sub_device_id = ha->subdevice_id;
-        }
-        piord->iu.ctrtype.info = ha->brd_phys;
-        piord->iu.ctrtype.oem_id = ha->oem_id;
-        break;
-
-      case GDTIOCTL_CTRCNT:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-        piord->size = sizeof(gdth_iord_str);
-        piord->status = S_OK;
-        piord->iu.ctrcnt.count = (ushort)gdth_ctr_count;
-        break;
-
-      case GDTIOCTL_OSVERS:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-        piord->size = sizeof(gdth_iord_str);
-        piord->status = S_OK;
-        piord->iu.osvers.version = (unchar)(LINUX_VERSION_CODE >> 16);
-        piord->iu.osvers.subversion = (unchar)(LINUX_VERSION_CODE >> 8);
-        piord->iu.osvers.revision = (ushort)(LINUX_VERSION_CODE & 0xff);
-        break;
-
-      case GDTIOCTL_LOCKDRV:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-        for (i = 0; i < piowr->iu.lockdrv.drive_cnt; ++i) {
-            j = piowr->iu.lockdrv.drives[i];
-            if (j >= MAX_HDRIVES || !ha->hdr[j].present) 
-                continue;
-            if (piowr->iu.lockdrv.lock) {
-                GDTH_LOCK_HA(ha, flags);
-                ha->hdr[j].lock = 1;
-                GDTH_UNLOCK_HA(ha, flags);
-                gdth_wait_completion( hanum, ha->bus_cnt, j );
-                gdth_stop_timeout( hanum, ha->bus_cnt, j );
-            } else {
-                GDTH_LOCK_HA(ha, flags);
-                ha->hdr[j].lock = 0;
-                GDTH_UNLOCK_HA(ha, flags);
-                gdth_start_timeout( hanum, ha->bus_cnt, j );
-                gdth_next( hanum );
-            }
-        }
-        piord->size = sizeof(gdth_iord_str);
-        piord->status = S_OK;
-        break;
-
-      case GDTIOCTL_LOCKCHN:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        i = piowr->iu.lockchn.channel;
-        if (i < ha->bus_cnt) {
-            if (piowr->iu.lockchn.lock) {
-                GDTH_LOCK_HA(ha, flags);
-                ha->raw[i].lock = 1;
-                GDTH_UNLOCK_HA(ha, flags);
-                for (j = 0; j < ha->tid_cnt; ++j) {
-                    gdth_wait_completion( hanum, i, j );
-                    gdth_stop_timeout( hanum, i, j );
-                }
-            } else {
-                GDTH_LOCK_HA(ha, flags);
-                ha->raw[i].lock = 0;
-                GDTH_UNLOCK_HA(ha, flags);
-                for (j = 0; j < ha->tid_cnt; ++j) {
-                    gdth_start_timeout( hanum, i, j );
-                    gdth_next( hanum );
-                }
-            }
-        }
-        piord = (gdth_iord_str *)ha->pscratch;
-        piord->size = sizeof(gdth_iord_str);
-        piord->status = S_OK;
-        break;
-
-      case GDTIOCTL_EVENT:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-        if (piowr->iu.event.erase == 0xff) {
-            pevt = (gdth_evt_str *)piowr->iu.event.evt;
-            if (pevt->event_source == ES_TEST) 
-                pevt->event_data.size = sizeof(pevt->event_data.eu.test);
-            else if (pevt->event_source == ES_DRIVER) 
-                pevt->event_data.size = sizeof(pevt->event_data.eu.driver);
-            else if (pevt->event_source == ES_SYNC) 
-                pevt->event_data.size = sizeof(pevt->event_data.eu.sync);
-            else {
-                pevt->event_data.size = sizeof(pevt->event_data.eu.async);
-                gdth_log_event(&pevt->event_data, NULL);
-            }
-            GDTH_LOCK_HA(ha, flags);
-            gdth_store_event(ha, pevt->event_source, pevt->event_idx,
-                             &pevt->event_data);
-            GDTH_UNLOCK_HA(ha, flags);
-        } else if (piowr->iu.event.erase == 0xfe) {
-            gdth_clear_events();
-        } else if (piowr->iu.event.erase == 0) {
-            piord->iu.event.handle = 
-                gdth_read_event(ha,piowr->iu.event.handle,
-                                (gdth_evt_str *)piord->iu.event.evt);
-        } else {
-            piord->iu.event.handle = piowr->iu.event.handle;
-            gdth_readapp_event(ha, (unchar)piowr->iu.event.erase,
-                               (gdth_evt_str *)piord->iu.event.evt);
-        }
-        piord->size = sizeof(gdth_iord_str);
-        piord->status = S_OK;
-        break;
-
-      case GDTIOCTL_SCSI:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-        piord->size = sizeof(gdth_iord_str);
-        memcpy(cmnd, piowr->iu.scsi.cmd, 12);
-#if LINUX_VERSION_CODE >= 0x020322
-        scp->target = piowr->iu.scsi.target;
-        scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
-        scp->cmd_len = piowr->iu.scsi.cmd_len;
-        gdth_do_cmd(scp, pcmd, cmnd, piowr->timeout);
-        piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
-#else
-        scp.target = piowr->iu.scsi.target;
-        scp.channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
-        scp.cmd_len = piowr->iu.scsi.cmd_len;
-        gdth_do_cmd(&scp, pcmd, cmnd, piowr->timeout);
-        piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;
-#endif
-        break;
-
-      case GDTIOCTL_RESET_BUS:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-        piord->size = sizeof(gdth_iord_str);
-#if LINUX_VERSION_CODE >= 0x020322
-        scp->channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
-        piord->status = (ulong32)gdth_eh_bus_reset( scp );
-        if (piord->status == SUCCESS)
-            piord->status = S_OK;
-        else
-            piord->status = S_GENERR;
-#elif LINUX_VERSION_CODE >= 0x02015F
-        scp.channel = virt_ctr ? 0 : piowr->iu.scsi.bus;
-        piord->status = (ulong32)gdth_eh_bus_reset( &scp );
-        if (piord->status == SUCCESS)
-            piord->status = S_OK;
-        else
-            piord->status = S_GENERR;
-#else
-        piord->status = S_OK;
-#endif
-        break;
-
-      case GDTIOCTL_HDRLIST:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-        piord->size = sizeof(gdth_iord_str);
-        piord->status = S_OK;
-        for (i = 0; i < MAX_HDRIVES; ++i) {
-            if (ha->hdr[i].present) {
-                piord->iu.hdr_list[i].bus = ha->virt_bus;
-                piord->iu.hdr_list[i].target = i;
-                piord->iu.hdr_list[i].lun = 0;
-                piord->iu.hdr_list[i].cluster_type = ha->hdr[i].cluster_type;
-                if (ha->hdr[i].cluster_type & CLUSTER_DRIVE) {  
-                    gdtcmd.Service = CACHESERVICE;
-                    gdtcmd.OpCode = GDT_CLUST_INFO;
-                    gdtcmd.u.cache.DeviceNo = i;
-#if LINUX_VERSION_CODE >= 0x020322
-                    gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-                    if (scp->SCp.Status == S_OK)
-                        piord->iu.hdr_list[i].cluster_type = 
-                            (unchar)scp->SCp.Message;
-#else
-                    gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-                    if (scp.SCp.Status == S_OK)
-                        piord->iu.hdr_list[i].cluster_type = 
-                            (unchar)scp.SCp.Message;
-#endif
-                }
-            } else {
-                piord->iu.hdr_list[i].bus = 0xff;
-            }
-        }
-        break;
-
-      case GDTIOCTL_RESCAN:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-        piord->size = sizeof(gdth_iord_str);
-        piord->status = S_OK;
-        if (piowr->iu.rescan.flag == 0) {
-            /* old method: scan all host drives 
-               re-initialize cache service to get host drive count
-            */
-            gdtcmd.Service = CACHESERVICE;
-            gdtcmd.OpCode = GDT_INIT;
-            gdtcmd.u.cache.DeviceNo = LINUX_OS;
-#if LINUX_VERSION_CODE >= 0x020322
-            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-            status = (ushort)scp->SCp.Status; 
-            info = (ulong32)scp->SCp.Message;
-#else
-            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-            status = (ushort)scp.SCp.Status;
-            info = (ulong32)scp.SCp.Message;
-#endif
-            if (status != S_OK)
-                break;
-            k = 0;
-            hdr_cnt = (ushort)info;
-        } else {
-            k = piowr->iu.rescan.hdr_no;
-            hdr_cnt = k + 1;
-        }
-        if (hdr_cnt > MAX_HDRIVES)
-            hdr_cnt = MAX_HDRIVES;
-        /* scanning for host drives */
-        for (; k < hdr_cnt; ++k) {
-            /* info about host drive */
-            gdtcmd.Service = CACHESERVICE;
-            gdtcmd.OpCode = GDT_INFO;
-            gdtcmd.u.cache.DeviceNo = k;
-#if LINUX_VERSION_CODE >= 0x020322
-            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-            status = (ushort)scp->SCp.Status; 
-            info = (ulong32)scp->SCp.Message;
-#else
-            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-            status = (ushort)scp.SCp.Status;
-            info = (ulong32)scp.SCp.Message;
-#endif
-            GDTH_LOCK_HA(ha, flags);
-            piord->iu.hdr_list[k].bus = ha->virt_bus;
-            piord->iu.hdr_list[k].target = k;
-            piord->iu.hdr_list[k].lun = 0;
-            if (status != S_OK) {
-                ha->hdr[k].present = FALSE;
-            } else {
-                ha->hdr[k].present = TRUE;
-                ha->hdr[k].size = info;
-                /* evaluate mapping (sectors per head, heads per cylinder) */
-                ha->hdr[k].size &= ~SECS32;
-                gdth_eval_mapping(ha->hdr[k].size,&drv_cyls,&drv_hds,&drv_secs);
-                ha->hdr[k].heads = (unchar)drv_hds;
-                ha->hdr[k].secs = (unchar)drv_secs;
-                /* round size */
-                ha->hdr[k].size = drv_cyls * drv_hds * drv_secs;
-            }
-            GDTH_UNLOCK_HA(ha, flags);
-            if (status != S_OK)
-                continue;       /* next host drive */
-
-            /* devtype, cluster info, R/W attributes */
-            gdtcmd.Service = CACHESERVICE;
-            gdtcmd.OpCode = GDT_DEVTYPE;
-            gdtcmd.u.cache.DeviceNo = k;
-#if LINUX_VERSION_CODE >= 0x020322
-            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-            status = (ushort)scp->SCp.Status; 
-            info = (ulong32)scp->SCp.Message;
-#else
-            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-            status = (ushort)scp.SCp.Status;
-            info = (ulong32)scp.SCp.Message;
-#endif
-            GDTH_LOCK_HA(ha, flags);
-            ha->hdr[k].devtype = 0;
-            if (status == S_OK)
-                ha->hdr[k].devtype = (ushort)info;
-            GDTH_UNLOCK_HA(ha, flags);
-
-            gdtcmd.Service = CACHESERVICE;
-            gdtcmd.OpCode = GDT_CLUST_INFO;
-            gdtcmd.u.cache.DeviceNo = k;
-#if LINUX_VERSION_CODE >= 0x020322
-            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-            status = (ushort)scp->SCp.Status; 
-            info = (ulong32)scp->SCp.Message;
-#else
-            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-            status = (ushort)scp.SCp.Status;
-            info = (ulong32)scp.SCp.Message;
-#endif
-            GDTH_LOCK_HA(ha, flags);
-            ha->hdr[k].cluster_type = 0;
-            if (status == S_OK && !shared_access)
-                ha->hdr[k].cluster_type = (ushort)info;
-            GDTH_UNLOCK_HA(ha, flags);
-            piord->iu.hdr_list[k].cluster_type = ha->hdr[k].cluster_type;
-
-            gdtcmd.Service = CACHESERVICE;
-            gdtcmd.OpCode = GDT_RW_ATTRIBS;
-            gdtcmd.u.cache.DeviceNo = k;
-#if LINUX_VERSION_CODE >= 0x020322
-            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-            status = (ushort)scp->SCp.Status; 
-            info = (ulong32)scp->SCp.Message;
-#else
-            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-            status = (ushort)scp.SCp.Status;
-            info = (ulong32)scp.SCp.Message;
-#endif
-            GDTH_LOCK_HA(ha, flags);
-            ha->hdr[k].rw_attribs = 0;
-            if (status == S_OK)
-                ha->hdr[k].rw_attribs = (ushort)info;
-            GDTH_UNLOCK_HA(ha, flags);
-        }
-        break;
-
-      case GDTIOCTL_RESET_DRV:
-        if (!gdth_ioctl_alloc( hanum, sizeof(gdth_iord_str), TRUE ))
-            return(-EBUSY);
-        piord = (gdth_iord_str *)ha->pscratch;
-        piord->size = sizeof(gdth_iord_str);
-        piord->status = S_OK;
-        i = piowr->iu.scsi.target;
-        if (ha->hdr[i].present) {
-            gdtcmd.Service = CACHESERVICE;
-            gdtcmd.OpCode = GDT_CLUST_RESET;
-            gdtcmd.u.cache.DeviceNo = i;
-#if LINUX_VERSION_CODE >= 0x020322
-            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-            piord->status = (scp->SCp.Message<<16)|scp->SCp.Status;
-#else
-            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-            piord->status = (scp.SCp.Message<<16)|scp.SCp.Status;
-#endif
-        }
-        break;
-
-      default:
-        return(-EINVAL);
-    }
-    return length;
-}
-
-static int gdth_get_info(char *buffer,char **start,off_t offset,
-                         int length,int vh,int hanum,int busnum)
+static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
+                         struct Scsi_Host *host,int hanum,int busnum)
 {
     int size = 0,len = 0;
     off_t begin = 0,pos = 0;
     gdth_ha_str *ha;
-    gdth_iord_str *piord;
     int id, i, j, k, sec, flag;
     int no_mdrv = 0, drv_no, is_mirr;
     ulong32 cnt;
+    ulong64 paddr;
 
     gdth_cmd_str gdtcmd;
     gdth_evt_str estr;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    Scsi_Request *scp;
+    Scsi_Device *sdev; 
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     Scsi_Cmnd *scp;
     Scsi_Device *sdev;
 #else
@@ -710,8 +274,15 @@
     TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum));
     ha = HADATA(gdth_ctr_tab[hanum]);
 
-#if LINUX_VERSION_CODE >= 0x020322
-    sdev = scsi_get_host_dev(gdth_ctr_vtab[vh]);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    sdev = scsi_get_host_dev(host);
+    scp  = scsi_allocate_request(sdev, GFP_KERNEL);
+    if (!scp)
+        return -ENOMEM;
+    scp->sr_cmd_len = 12;
+    scp->sr_use_sg = 0;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+    sdev = scsi_get_host_dev(host);
     scp  = scsi_allocate_device(sdev, 1, FALSE);
     if (!scp)
         return -ENOMEM;
@@ -720,465 +291,415 @@
 #else
     memset(&sdev,0,sizeof(Scsi_Device));
     memset(&scp, 0,sizeof(Scsi_Cmnd));
-    sdev.host = scp.host = gdth_ctr_vtab[vh];
+    sdev.host = scp.host = host;
     sdev.id = scp.target = sdev.host->this_id;
     scp.device = &sdev;
 #endif
-
-    /* ioctl from tool? */
-    if (!gdth_ioctl_check_bin(hanum, (ushort)length)) {
-        /* request is i.e. "cat /proc/scsi/gdth/0" */ 
-        /* format: %-15s\t%-10s\t%-15s\t%s */
-        /* driver parameters */
-        size = sprintf(buffer+len,"Driver Parameters:\n");
-        len += size;  pos = begin + len;
-        if (reserve_list[0] == 0xff)
-            strcpy(hrec, "--");
-        else {
-            sprintf(hrec, "%d", reserve_list[0]);
-            for (i = 1;  i < MAX_RES_ARGS; i++) {
-                if (reserve_list[i] == 0xff) 
-                    break;
-                sprintf(hrec,"%s,%d", hrec, reserve_list[i]);
-            }
+    
+    
+    /* request is i.e. "cat /proc/scsi/gdth/0" */ 
+    /* format: %-15s\t%-10s\t%-15s\t%s */
+    /* driver parameters */
+    size = sprintf(buffer+len,"Driver Parameters:\n");
+    len += size;  pos = begin + len;
+    if (reserve_list[0] == 0xff)
+        strcpy(hrec, "--");
+    else {
+        sprintf(hrec, "%d", reserve_list[0]);
+        for (i = 1;  i < MAX_RES_ARGS; i++) {
+            if (reserve_list[i] == 0xff) 
+                break;
+            sprintf(hrec,"%s,%d", hrec, reserve_list[i]);
         }
-        size = sprintf(buffer+len,
-                       " reserve_mode: \t%d         \treserve_list:  \t%s\n",
-                       reserve_mode, hrec);
-        len += size;  pos = begin + len;
-        size = sprintf(buffer+len,
-                       " max_ids:      \t%-3d       \thdr_channel:   \t%d\n",
-                       max_ids, hdr_channel);
-        len += size;  pos = begin + len;
+    }
+    size = sprintf(buffer+len,
+                   " reserve_mode: \t%d         \treserve_list:  \t%s\n",
+                   reserve_mode, hrec);
+    len += size;  pos = begin + len;
+    size = sprintf(buffer+len,
+                   " max_ids:      \t%-3d       \thdr_channel:   \t%d\n",
+                   max_ids, hdr_channel);
+    len += size;  pos = begin + len;
+
+    /* controller information */
+    size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
+    len += size;  pos = begin + len;
+    if (virt_ctr)
+        sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum);
+    else
+        strcpy(hrec, ha->binfo.type_string);
+    size = sprintf(buffer+len,
+                   " Number:       \t%d         \tName:          \t%s\n",
+                   hanum, hrec);
+    len += size;  pos = begin + len;
+
+    if (ha->more_proc)
+        sprintf(hrec, "%d.%02d.%02d-%c%03X", 
+                (unchar)(ha->binfo.upd_fw_ver>>24),
+                (unchar)(ha->binfo.upd_fw_ver>>16),
+                (unchar)(ha->binfo.upd_fw_ver),
+                ha->bfeat.raid ? 'R':'N',
+                ha->binfo.upd_revision);
+    else
+        sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8),
+                (unchar)(ha->cpar.version));
 
-        /* controller information */
-        size = sprintf(buffer+len,"\nDisk Array Controller Information:\n");
-        len += size;  pos = begin + len;
-        if (virt_ctr)
-            sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum);
-        else
-            strcpy(hrec, ha->binfo.type_string);
+    size = sprintf(buffer+len,
+                   " Driver Ver.:  \t%-10s\tFirmware Ver.: \t%s\n",
+                   GDTH_VERSION_STR, hrec);
+    len += size;  pos = begin + len;
+ 
+    if (ha->more_proc) {
+        /* more information: 1. about controller */
         size = sprintf(buffer+len,
-                       " Number:       \t%d         \tName:          \t%s\n",
-                       hanum, hrec);
+                       " Serial No.:   \t0x%8X\tCache RAM size:\t%d KB\n",
+                       ha->binfo.ser_no, ha->binfo.memsize / 1024);
         len += size;  pos = begin + len;
+    }
 
-        if (ha->more_proc)
-            sprintf(hrec, "%d.%02d.%02d-%c%03X", 
-                    (unchar)(ha->binfo.upd_fw_ver>>24),
-                    (unchar)(ha->binfo.upd_fw_ver>>16),
-                    (unchar)(ha->binfo.upd_fw_ver),
-                    ha->bfeat.raid ? 'R':'N',
-                    ha->binfo.upd_revision);
-        else
-            sprintf(hrec, "%d.%02d", (unchar)(ha->cpar.version>>8),
-                    (unchar)(ha->cpar.version));
+#ifdef GDTH_DMA_STATISTICS
+    /* controller statistics */
+    size = sprintf(buffer+len,"\nController Statistics:\n");
+    len += size;  pos = begin + len;
+    size = sprintf(buffer+len,
+                   " 32-bit DMA buffer:\t%lu\t64-bit DMA buffer:\t%lu\n",
+                   ha->dma32_cnt, ha->dma64_cnt);
+    len += size;  pos = begin + len;
+#endif
 
-        size = sprintf(buffer+len,
-                       " Driver Ver.:  \t%-10s\tFirmware Ver.: \t%s\n",
-                       GDTH_VERSION_STR, hrec);
+    if (pos < offset) {
+        len = 0;
+        begin = pos;
+    }
+    if (pos > offset + length)
+        goto stop_output;
+
+    if (ha->more_proc) {
+        /* more information: 2. about physical devices */
+        size = sprintf(buffer+len,"\nPhysical Devices:");
         len += size;  pos = begin + len;
- 
-        if (pos < offset) {
-            len = 0;
-            begin = pos;
-        }
-        if (pos > offset + length)
+        flag = FALSE;
+            
+        buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
+        if (!buf) 
             goto stop_output;
+        for (i = 0; i < ha->bus_cnt; ++i) {
+            /* 2.a statistics (and retries/reassigns) */
+            TRACE2(("pdr_statistics() chn %d\n",i));                
+            pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4);
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_IOCTL;
+            gdtcmd.u.ioctl.p_param = paddr + GDTH_SCRATCH/4;
+            gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4;
+            gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
+            gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
+            pds->bid = ha->raw[i].local_no;
+            pds->first = 0;
+            pds->entries = ha->raw[i].pdev_cnt;
+            cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) /
+                sizeof(pds->list[0]);
+            if (pds->entries > cnt)
+                pds->entries = cnt;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            gdth_do_req(scp, &gdtcmd, cmnd, 30);
+            if (scp->sr_command->SCp.Status != S_OK) 
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+            if (scp->SCp.Status != S_OK) 
+#else
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+            if (scp.SCp.Status != S_OK) 
+#endif
+            { 
+                pds->count = 0;
+            }
 
-        if (ha->more_proc) {
-            /* more information: 1. about controller */
-            size = sprintf(buffer+len,
-                           " Serial No.:   \t0x%8X\tCache RAM size:\t%d KB\n",
-                           ha->binfo.ser_no, ha->binfo.memsize / 1024);
-            len += size;  pos = begin + len;
-
-            /* 2. about physical devices */
-            size = sprintf(buffer+len,"\nPhysical Devices:");
-            len += size;  pos = begin + len;
-            flag = FALSE;
-            
-            buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
-            if (!buf) 
-                goto stop_output;
-            for (i = 0; i < ha->bus_cnt; ++i) {
-                /* 2.a statistics (and retries/reassigns) */
-                TRACE2(("pdr_statistics() chn %d\n",i));                
-                pds = (gdth_dskstat_str *)(buf + GDTH_SCRATCH/4);
+            /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
+            for (j = 0; j < ha->raw[i].pdev_cnt; ++j) {
+                /* 2.b drive info */
+                TRACE2(("scsi_drv_info() chn %d dev %d\n",
+                    i, ha->raw[i].id_list[j]));             
+                pdi = (gdth_diskinfo_str *)buf;
                 gdtcmd.Service = CACHESERVICE;
                 gdtcmd.OpCode = GDT_IOCTL;
-                gdtcmd.u.ioctl.p_param = virt_to_bus(pds);
-                gdtcmd.u.ioctl.param_size = 3*GDTH_SCRATCH/4;
-                gdtcmd.u.ioctl.subfunc = DSK_STATISTICS | L_CTRL_PATTERN;
-                gdtcmd.u.ioctl.channel = ha->raw[i].address | INVALID_CHANNEL;
-                pds->bid = ha->raw[i].local_no;
-                pds->first = 0;
-                pds->entries = ha->raw[i].pdev_cnt;
-                cnt = (3*GDTH_SCRATCH/4 - 5 * sizeof(ulong32)) /
-                    sizeof(pds->list[0]);
-                if (pds->entries > cnt)
-                    pds->entries = cnt;
-#if LINUX_VERSION_CODE >= 0x020322
+                gdtcmd.u.ioctl.p_param = paddr;
+                gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str);
+                gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
+                gdtcmd.u.ioctl.channel = 
+                    ha->raw[i].address | ha->raw[i].id_list[j];
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+                gdth_do_req(scp, &gdtcmd, cmnd, 30);
+                if (scp->sr_command->SCp.Status == S_OK) 
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
                 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-                if (scp->SCp.Status != S_OK) 
+                if (scp->SCp.Status == S_OK) 
 #else
                 gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-                if (scp.SCp.Status != S_OK) 
+                if (scp.SCp.Status == S_OK) 
 #endif
-                { 
-                    pds->count = 0;
+                {
+                    strncpy(hrec,pdi->vendor,8);
+                    strncpy(hrec+8,pdi->product,16);
+                    strncpy(hrec+24,pdi->revision,4);
+                    hrec[28] = 0;
+                    size = sprintf(buffer+len,
+                                   "\n Chn/ID/LUN:   \t%c/%02d/%d    \tName:          \t%s\n",
+                                   'A'+i,pdi->target_id,pdi->lun,hrec);
+                    len += size;  pos = begin + len;
+                    flag = TRUE;
+                    pdi->no_ldrive &= 0xffff;
+                    if (pdi->no_ldrive == 0xffff)
+                        strcpy(hrec,"--");
+                    else
+                        sprintf(hrec,"%d",pdi->no_ldrive);
+                    size = sprintf(buffer+len,
+                                   " Capacity [MB]:\t%-6d    \tTo Log. Drive: \t%s\n",
+                                   pdi->blkcnt/(1024*1024/pdi->blksize),
+                                   hrec);
+                    len += size;  pos = begin + len;
+                } else {
+                    pdi->devtype = 0xff;
                 }
-
-                /* other IOCTLs must fit into area GDTH_SCRATCH/4 */
-                for (j = 0; j < ha->raw[i].pdev_cnt; ++j) {
-                    /* 2.b drive info */
-                    TRACE2(("scsi_drv_info() chn %d dev %d\n",
-                        i, ha->raw[i].id_list[j]));             
-                    pdi = (gdth_diskinfo_str *)buf;
-                    gdtcmd.Service = CACHESERVICE;
-                    gdtcmd.OpCode = GDT_IOCTL;
-                    gdtcmd.u.ioctl.p_param = virt_to_bus(pdi);
-                    gdtcmd.u.ioctl.param_size = sizeof(gdth_diskinfo_str);
-                    gdtcmd.u.ioctl.subfunc = SCSI_DR_INFO | L_CTRL_PATTERN;
-                    gdtcmd.u.ioctl.channel = 
-                        ha->raw[i].address | ha->raw[i].id_list[j];
-#if LINUX_VERSION_CODE >= 0x020322
-                    gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-                    if (scp->SCp.Status == S_OK) 
-#else
-                    gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-                    if (scp.SCp.Status == S_OK) 
-#endif
-                    {
-                        strncpy(hrec,pdi->vendor,8);
-                        strncpy(hrec+8,pdi->product,16);
-                        strncpy(hrec+24,pdi->revision,4);
-                        hrec[28] = 0;
-                        size = sprintf(buffer+len,
-                                       "\n Chn/ID/LUN:   \t%c/%02d/%d    \tName:          \t%s\n",
-                                       'A'+i,pdi->target_id,pdi->lun,hrec);
-                        len += size;  pos = begin + len;
-                        flag = TRUE;
-                        pdi->no_ldrive &= 0xffff;
-                        if (pdi->no_ldrive == 0xffff)
-                            strcpy(hrec,"--");
-                        else
-                            sprintf(hrec,"%d",pdi->no_ldrive);
-                        size = sprintf(buffer+len,
-                                       " Capacity [MB]:\t%-6d    \tTo Log. Drive: \t%s\n",
-                                       pdi->blkcnt/(1024*1024/pdi->blksize),
-                                       hrec);
-                        len += size;  pos = begin + len;
-                    } else {
-                        pdi->devtype = 0xff;
-                    }
                     
-                    if (pdi->devtype == 0) {
-                        /* search retries/reassigns */
-                        for (k = 0; k < pds->count; ++k) {
-                            if (pds->list[k].tid == pdi->target_id &&
-                                pds->list[k].lun == pdi->lun) {
-                                size = sprintf(buffer+len,
-                                               " Retries:      \t%-6d    \tReassigns:     \t%d\n",
-                                               pds->list[k].retries,
-                                               pds->list[k].reassigns);
-                                len += size;  pos = begin + len;
-                                break;
-                            }
-                        }
-                        /* 2.c grown defects */
-                        TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
-                                i, ha->raw[i].id_list[j]));             
-                        pdef = (gdth_defcnt_str *)buf;
-                        gdtcmd.Service = CACHESERVICE;
-                        gdtcmd.OpCode = GDT_IOCTL;
-                        gdtcmd.u.ioctl.p_param = virt_to_bus(pdef);
-                        gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str);
-                        gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
-                        gdtcmd.u.ioctl.channel = 
-                            ha->raw[i].address | ha->raw[i].id_list[j];
-                        pdef->sddc_type = 0x08;
-#if LINUX_VERSION_CODE >= 0x020322
-                        gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-                        if (scp->SCp.Status == S_OK) 
-#else
-                        gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-                        if (scp.SCp.Status == S_OK) 
-#endif
-                        {
+                if (pdi->devtype == 0) {
+                    /* search retries/reassigns */
+                    for (k = 0; k < pds->count; ++k) {
+                        if (pds->list[k].tid == pdi->target_id &&
+                            pds->list[k].lun == pdi->lun) {
                             size = sprintf(buffer+len,
-                                           " Grown Defects:\t%d\n",
-                                           pdef->sddc_cnt);
+                                           " Retries:      \t%-6d    \tReassigns:     \t%d\n",
+                                           pds->list[k].retries,
+                                           pds->list[k].reassigns);
                             len += size;  pos = begin + len;
+                            break;
                         }
                     }
-                    if (pos < offset) {
-                        len = 0;
-                        begin = pos;
-                    }
-                    if (pos > offset + length)
-                        goto stop_output;
-                }
-            }
-            gdth_ioctl_free(hanum, buf);
-
-            if (!flag) {
-                size = sprintf(buffer+len, "\n --\n");
-                len += size;  pos = begin + len;
-            }
-
-            /* 3. about logical drives */
-            size = sprintf(buffer+len,"\nLogical Drives:");
-            len += size;  pos = begin + len;
-            flag = FALSE;
-
-            buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
-            if (!buf) 
-                goto stop_output;
-            for (i = 0; i < MAX_LDRIVES; ++i) {
-                if (!ha->hdr[i].is_logdrv)
-                    continue;
-                drv_no = i;
-                j = k = 0;
-                is_mirr = FALSE;
-                do {
-                    /* 3.a log. drive info */
-                    TRACE2(("cache_drv_info() drive no %d\n",drv_no));
-                    pcdi = (gdth_cdrinfo_str *)buf;
+                    /* 2.c grown defects */
+                    TRACE2(("scsi_drv_defcnt() chn %d dev %d\n",
+                            i, ha->raw[i].id_list[j]));             
+                    pdef = (gdth_defcnt_str *)buf;
                     gdtcmd.Service = CACHESERVICE;
                     gdtcmd.OpCode = GDT_IOCTL;
-                    gdtcmd.u.ioctl.p_param = virt_to_bus(pcdi);
-                    gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
-                    gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO;
-                    gdtcmd.u.ioctl.channel = drv_no;
-#if LINUX_VERSION_CODE >= 0x020322
+                    gdtcmd.u.ioctl.p_param = paddr;
+                    gdtcmd.u.ioctl.param_size = sizeof(gdth_defcnt_str);
+                    gdtcmd.u.ioctl.subfunc = SCSI_DEF_CNT | L_CTRL_PATTERN;
+                    gdtcmd.u.ioctl.channel = 
+                        ha->raw[i].address | ha->raw[i].id_list[j];
+                    pdef->sddc_type = 0x08;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+                    gdth_do_req(scp, &gdtcmd, cmnd, 30);
+                    if (scp->sr_command->SCp.Status == S_OK) 
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
                     gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-                    if (scp->SCp.Status != S_OK)
+                    if (scp->SCp.Status == S_OK) 
 #else
                     gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-                    if (scp.SCp.Status != S_OK)
+                    if (scp.SCp.Status == S_OK) 
 #endif
                     {
-                        break;
-                    }
-                    pcdi->ld_dtype >>= 16;
-                    j++;
-                    if (pcdi->ld_dtype > 2) {
-                        strcpy(hrec, "missing");
-                    } else if (pcdi->ld_error & 1) {
-                        strcpy(hrec, "fault");
-                    } else if (pcdi->ld_error & 2) {
-                        strcpy(hrec, "invalid");
-                        k++; j--;
-                    } else {
-                        strcpy(hrec, "ok");
-                    }
-                    
-                    if (drv_no == i) {
-                        size = sprintf(buffer+len,
-                                       "\n Number:       \t%-2d        \tStatus:        \t%s\n",
-                                       drv_no, hrec);
-                        len += size;  pos = begin + len;
-                        flag = TRUE;
-                        no_mdrv = pcdi->cd_ldcnt;
-                        if (no_mdrv > 1 || pcdi->ld_slave != -1) {
-                            is_mirr = TRUE;
-                            strcpy(hrec, "RAID-1");
-                        } else if (pcdi->ld_dtype == 0) {
-                            strcpy(hrec, "Disk");
-                        } else if (pcdi->ld_dtype == 1) {
-                            strcpy(hrec, "RAID-0");
-                        } else if (pcdi->ld_dtype == 2) {
-                            strcpy(hrec, "Chain");
-                        } else {
-                            strcpy(hrec, "???");
-                        }
-                        size = sprintf(buffer+len,
-                                       " Capacity [MB]:\t%-6d    \tType:          \t%s\n",
-                                       pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize),
-                                       hrec);
-                        len += size;  pos = begin + len;
-                    } else {
                         size = sprintf(buffer+len,
-                                       " Slave Number: \t%-2d        \tStatus:        \t%s\n",
-                                       drv_no & 0x7fff, hrec);
+                                       " Grown Defects:\t%d\n",
+                                       pdef->sddc_cnt);
                         len += size;  pos = begin + len;
                     }
-                    drv_no = pcdi->ld_slave;
-                    if (pos < offset) {
-                        len = 0;
-                        begin = pos;
-                    }
-                    if (pos > offset + length)
-                        goto stop_output;
-                } while (drv_no != -1);
-                
-                if (is_mirr) {
-                    size = sprintf(buffer+len,
-                                   " Missing Drv.: \t%-2d        \tInvalid Drv.:  \t%d\n",
-                                   no_mdrv - j - k, k);
-                    len += size;  pos = begin + len;
                 }
-                
-                if (!ha->hdr[i].is_arraydrv)
-                    strcpy(hrec, "--");
-                else
-                    sprintf(hrec, "%d", ha->hdr[i].master_no);
-                size = sprintf(buffer+len,
-                               " To Array Drv.:\t%s\n", hrec);
-                len += size;  pos = begin + len;
                 if (pos < offset) {
                     len = 0;
                     begin = pos;
                 }
                 if (pos > offset + length)
                     goto stop_output;
-            }       
-            gdth_ioctl_free(hanum, buf);
-        
-            if (!flag) {
-                size = sprintf(buffer+len, "\n --\n");
-                len += size;  pos = begin + len;
-            }   
+            }
+        }
+        gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
 
-            /* 4. about array drives */
-            size = sprintf(buffer+len,"\nArray Drives:");
+        if (!flag) {
+            size = sprintf(buffer+len, "\n --\n");
             len += size;  pos = begin + len;
-            flag = FALSE;
+        }
 
-            buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
-            if (!buf) 
-                goto stop_output;
-            for (i = 0; i < MAX_LDRIVES; ++i) {
-                if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master))
-                    continue;
-                /* 4.a array drive info */
-                TRACE2(("array_info() drive no %d\n",i));
-                pai = (gdth_arrayinf_str *)buf;
+        /* 3. about logical drives */
+        size = sprintf(buffer+len,"\nLogical Drives:");
+        len += size;  pos = begin + len;
+        flag = FALSE;
+
+        buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
+        if (!buf) 
+            goto stop_output;
+        for (i = 0; i < MAX_LDRIVES; ++i) {
+            if (!ha->hdr[i].is_logdrv)
+                continue;
+            drv_no = i;
+            j = k = 0;
+            is_mirr = FALSE;
+            do {
+                /* 3.a log. drive info */
+                TRACE2(("cache_drv_info() drive no %d\n",drv_no));
+                pcdi = (gdth_cdrinfo_str *)buf;
                 gdtcmd.Service = CACHESERVICE;
                 gdtcmd.OpCode = GDT_IOCTL;
-                gdtcmd.u.ioctl.p_param = virt_to_bus(pai);
-                gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str);
-                gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
-                gdtcmd.u.ioctl.channel = i;
-#if LINUX_VERSION_CODE >= 0x020322
+                gdtcmd.u.ioctl.p_param = paddr;
+                gdtcmd.u.ioctl.param_size = sizeof(gdth_cdrinfo_str);
+                gdtcmd.u.ioctl.subfunc = CACHE_DRV_INFO;
+                gdtcmd.u.ioctl.channel = drv_no;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+                gdth_do_req(scp, &gdtcmd, cmnd, 30);
+                if (scp->sr_command->SCp.Status != S_OK) 
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
                 gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-                if (scp->SCp.Status == S_OK) 
+                if (scp->SCp.Status != S_OK)
 #else
                 gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-                if (scp.SCp.Status == S_OK) 
+                if (scp.SCp.Status != S_OK)
 #endif
                 {
-                    if (pai->ai_state == 0)
-                        strcpy(hrec, "idle");
-                    else if (pai->ai_state == 2)
-                        strcpy(hrec, "build");
-                    else if (pai->ai_state == 4)
-                        strcpy(hrec, "ready");
-                    else if (pai->ai_state == 6)
-                        strcpy(hrec, "fail");
-                    else if (pai->ai_state == 8 || pai->ai_state == 10)
-                        strcpy(hrec, "rebuild");
-                    else
-                        strcpy(hrec, "error");
-                    if (pai->ai_ext_state & 0x10)
-                        strcat(hrec, "/expand");
-                    else if (pai->ai_ext_state & 0x1)
-                        strcat(hrec, "/patch");
+                    break;
+                }
+                pcdi->ld_dtype >>= 16;
+                j++;
+                if (pcdi->ld_dtype > 2) {
+                    strcpy(hrec, "missing");
+                } else if (pcdi->ld_error & 1) {
+                    strcpy(hrec, "fault");
+                } else if (pcdi->ld_error & 2) {
+                    strcpy(hrec, "invalid");
+                    k++; j--;
+                } else {
+                    strcpy(hrec, "ok");
+                }
+                    
+                if (drv_no == i) {
                     size = sprintf(buffer+len,
                                    "\n Number:       \t%-2d        \tStatus:        \t%s\n",
-                                   i,hrec);
+                                   drv_no, hrec);
                     len += size;  pos = begin + len;
                     flag = TRUE;
-
-                    if (pai->ai_type == 0)
+                    no_mdrv = pcdi->cd_ldcnt;
+                    if (no_mdrv > 1 || pcdi->ld_slave != -1) {
+                        is_mirr = TRUE;
+                        strcpy(hrec, "RAID-1");
+                    } else if (pcdi->ld_dtype == 0) {
+                        strcpy(hrec, "Disk");
+                    } else if (pcdi->ld_dtype == 1) {
                         strcpy(hrec, "RAID-0");
-                    else if (pai->ai_type == 4)
-                        strcpy(hrec, "RAID-4");
-                    else if (pai->ai_type == 5)
-                        strcpy(hrec, "RAID-5");
-                    else 
-                        strcpy(hrec, "RAID-10");
+                    } else if (pcdi->ld_dtype == 2) {
+                        strcpy(hrec, "Chain");
+                    } else {
+                        strcpy(hrec, "???");
+                    }
                     size = sprintf(buffer+len,
                                    " Capacity [MB]:\t%-6d    \tType:          \t%s\n",
-                                   pai->ai_size/(1024*1024/pai->ai_secsize),
+                                   pcdi->ld_blkcnt/(1024*1024/pcdi->ld_blksize),
                                    hrec);
                     len += size;  pos = begin + len;
-                    if (pos < offset) {
-                        len = 0;
-                        begin = pos;
-                    }
-                    if (pos > offset + length)
-                        goto stop_output;
+                } else {
+                    size = sprintf(buffer+len,
+                                   " Slave Number: \t%-2d        \tStatus:        \t%s\n",
+                                   drv_no & 0x7fff, hrec);
+                    len += size;  pos = begin + len;
                 }
-            }
-            gdth_ioctl_free(hanum, buf);
-        
-            if (!flag) {
-                size = sprintf(buffer+len, "\n --\n");
+                drv_no = pcdi->ld_slave;
+                if (pos < offset) {
+                    len = 0;
+                    begin = pos;
+                }
+                if (pos > offset + length)
+                    goto stop_output;
+            } while (drv_no != -1);
+             
+            if (is_mirr) {
+                size = sprintf(buffer+len,
+                               " Missing Drv.: \t%-2d        \tInvalid Drv.:  \t%d\n",
+                               no_mdrv - j - k, k);
                 len += size;  pos = begin + len;
             }
-
-            /* 5. about host drives */
-            size = sprintf(buffer+len,"\nHost Drives:");
+              
+            if (!ha->hdr[i].is_arraydrv)
+                strcpy(hrec, "--");
+            else
+                sprintf(hrec, "%d", ha->hdr[i].master_no);
+            size = sprintf(buffer+len,
+                           " To Array Drv.:\t%s\n", hrec);
             len += size;  pos = begin + len;
-            flag = FALSE;
-
-            buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE);
-            if (!buf) 
+            if (pos < offset) {
+                len = 0;
+                begin = pos;
+            }
+            if (pos > offset + length)
                 goto stop_output;
-            for (i = 0; i < MAX_LDRIVES; ++i) {
-                if (!ha->hdr[i].is_logdrv || 
-                    (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master))
-                    continue;
-                /* 5.a get host drive list */
-                TRACE2(("host_get() drv_no %d\n",i));           
-                phg = (gdth_hget_str *)buf;
-                gdtcmd.Service = CACHESERVICE;
-                gdtcmd.OpCode = GDT_IOCTL;
-                gdtcmd.u.ioctl.p_param = virt_to_bus(phg);
-                gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str);
-                gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
-                gdtcmd.u.ioctl.channel = i;
-                phg->entries = MAX_HDRIVES;
-                phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); 
-#if LINUX_VERSION_CODE >= 0x020322
-                gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
-                if (scp->SCp.Status != S_OK) 
+        }       
+        gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
+        
+        if (!flag) {
+            size = sprintf(buffer+len, "\n --\n");
+            len += size;  pos = begin + len;
+        }   
+
+        /* 4. about array drives */
+        size = sprintf(buffer+len,"\nArray Drives:");
+        len += size;  pos = begin + len;
+        flag = FALSE;
+
+        buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr);
+        if (!buf) 
+            goto stop_output;
+        for (i = 0; i < MAX_LDRIVES; ++i) {
+            if (!(ha->hdr[i].is_arraydrv && ha->hdr[i].is_master))
+                continue;
+            /* 4.a array drive info */
+            TRACE2(("array_info() drive no %d\n",i));
+            pai = (gdth_arrayinf_str *)buf;
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_IOCTL;
+            gdtcmd.u.ioctl.p_param = paddr;
+            gdtcmd.u.ioctl.param_size = sizeof(gdth_arrayinf_str);
+            gdtcmd.u.ioctl.subfunc = ARRAY_INFO | LA_CTRL_PATTERN;
+            gdtcmd.u.ioctl.channel = i;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            gdth_do_req(scp, &gdtcmd, cmnd, 30);
+            if (scp->sr_command->SCp.Status == S_OK) 
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+            if (scp->SCp.Status == S_OK) 
 #else
-                gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
-                if (scp.SCp.Status != S_OK) 
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+            if (scp.SCp.Status == S_OK) 
 #endif
-                {
-                    ha->hdr[i].ldr_no = i;
-                    ha->hdr[i].rw_attribs = 0;
-                    ha->hdr[i].start_sec = 0;
-                } else {
-                    for (j = 0; j < phg->entries; ++j) {
-                        k = phg->entry[j].host_drive;
-                        if (k >= MAX_LDRIVES)
-                            continue;
-                        ha->hdr[k].ldr_no = phg->entry[j].log_drive;
-                        ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs;
-                        ha->hdr[k].start_sec = phg->entry[j].start_sec;
-                    }
-                }
-            }
-            gdth_ioctl_free(hanum, buf);
-
-            for (i = 0; i < MAX_HDRIVES; ++i) {
-                if (!(ha->hdr[i].present))
-                    continue;
-                
+            {
+                if (pai->ai_state == 0)
+                    strcpy(hrec, "idle");
+                else if (pai->ai_state == 2)
+                    strcpy(hrec, "build");
+                else if (pai->ai_state == 4)
+                    strcpy(hrec, "ready");
+                else if (pai->ai_state == 6)
+                    strcpy(hrec, "fail");
+                else if (pai->ai_state == 8 || pai->ai_state == 10)
+                    strcpy(hrec, "rebuild");
+                else
+                    strcpy(hrec, "error");
+                if (pai->ai_ext_state & 0x10)
+                    strcat(hrec, "/expand");
+                else if (pai->ai_ext_state & 0x1)
+                    strcat(hrec, "/patch");
                 size = sprintf(buffer+len,
-                               "\n Number:       \t%-2d        \tArr/Log. Drive:\t%d\n",
-                               i, ha->hdr[i].ldr_no);
+                               "\n Number:       \t%-2d        \tStatus:        \t%s\n",
+                               i,hrec);
                 len += size;  pos = begin + len;
                 flag = TRUE;
 
+                if (pai->ai_type == 0)
+                    strcpy(hrec, "RAID-0");
+                else if (pai->ai_type == 4)
+                    strcpy(hrec, "RAID-4");
+                else if (pai->ai_type == 5)
+                    strcpy(hrec, "RAID-5");
+                else 
+                    strcpy(hrec, "RAID-10");
                 size = sprintf(buffer+len,
-                               " Capacity [MB]:\t%-6d    \tStart Sector:  \t%d\n",
-                               ha->hdr[i].size/2048, ha->hdr[i].start_sec);
+                               " Capacity [MB]:\t%-6d    \tType:          \t%s\n",
+                               pai->ai_size/(1024*1024/pai->ai_secsize),
+                               hrec);
                 len += size;  pos = begin + len;
                 if (pos < offset) {
                     len = 0;
@@ -1187,53 +708,125 @@
                 if (pos > offset + length)
                     goto stop_output;
             }
+        }
+        gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr);
         
-            if (!flag) {
-                size = sprintf(buffer+len, "\n --\n");
-                len += size;  pos = begin + len;
-            }
+        if (!flag) {
+            size = sprintf(buffer+len, "\n --\n");
+            len += size;  pos = begin + len;
         }
 
-        /* controller events */
-        size = sprintf(buffer+len,"\nController Events:\n");
+        /* 5. about host drives */
+        size = sprintf(buffer+len,"\nHost Drives:");
         len += size;  pos = begin + len;
+        flag = FALSE;
 
-        for (id = -1;;) {
-            id = gdth_read_event(ha, id, &estr);
-            if (estr.event_source == 0)
-                break;
-            if (estr.event_data.eu.driver.ionode == hanum &&
-                estr.event_source == ES_ASYNC) { 
-                gdth_log_event(&estr.event_data, hrec);
-                do_gettimeofday(&tv);
-                sec = (int)(tv.tv_sec - estr.first_stamp);
-                if (sec < 0) sec = 0;
-                size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n",
-                               sec/3600, sec%3600/60, sec%60, hrec);
-                len += size;  pos = begin + len;
-                if (pos < offset) {
-                    len = 0;
-                    begin = pos;
+        buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr);
+        if (!buf) 
+            goto stop_output;
+        for (i = 0; i < MAX_LDRIVES; ++i) {
+            if (!ha->hdr[i].is_logdrv || 
+                (ha->hdr[i].is_arraydrv && !ha->hdr[i].is_master))
+                continue;
+            /* 5.a get host drive list */
+            TRACE2(("host_get() drv_no %d\n",i));           
+            phg = (gdth_hget_str *)buf;
+            gdtcmd.Service = CACHESERVICE;
+            gdtcmd.OpCode = GDT_IOCTL;
+            gdtcmd.u.ioctl.p_param = paddr;
+            gdtcmd.u.ioctl.param_size = sizeof(gdth_hget_str);
+            gdtcmd.u.ioctl.subfunc = HOST_GET | LA_CTRL_PATTERN;
+            gdtcmd.u.ioctl.channel = i;
+            phg->entries = MAX_HDRIVES;
+            phg->offset = GDTOFFSOF(gdth_hget_str, entry[0]); 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            gdth_do_req(scp, &gdtcmd, cmnd, 30);
+            if (scp->sr_command->SCp.Status != S_OK) 
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+            gdth_do_cmd(scp, &gdtcmd, cmnd, 30);
+            if (scp->SCp.Status != S_OK) 
+#else
+            gdth_do_cmd(&scp, &gdtcmd, cmnd, 30);
+            if (scp.SCp.Status != S_OK) 
+#endif
+            {
+                ha->hdr[i].ldr_no = i;
+                ha->hdr[i].rw_attribs = 0;
+                ha->hdr[i].start_sec = 0;
+            } else {
+                for (j = 0; j < phg->entries; ++j) {
+                    k = phg->entry[j].host_drive;
+                    if (k >= MAX_LDRIVES)
+                        continue;
+                    ha->hdr[k].ldr_no = phg->entry[j].log_drive;
+                    ha->hdr[k].rw_attribs = phg->entry[j].rw_attribs;
+                    ha->hdr[k].start_sec = phg->entry[j].start_sec;
                 }
-                if (pos > offset + length)
-                    goto stop_output;
             }
-            if (id == -1)
-                break;
         }
-    } else {
-        /* request from tool (GDTMON,..) */
-        piord = (gdth_iord_str *)ha->pscratch;
-        if (piord == NULL)
-            goto stop_output;
-        length = piord->size;
-        memcpy(buffer+len, (char *)piord, length);
-        gdth_ioctl_free(hanum, ha->pscratch);
-        len = length; 
+        gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr);
+
+        for (i = 0; i < MAX_HDRIVES; ++i) {
+            if (!(ha->hdr[i].present))
+                continue;
+              
+            size = sprintf(buffer+len,
+                           "\n Number:       \t%-2d        \tArr/Log. Drive:\t%d\n",
+                           i, ha->hdr[i].ldr_no);
+            len += size;  pos = begin + len;
+            flag = TRUE;
+
+            size = sprintf(buffer+len,
+                           " Capacity [MB]:\t%-6d    \tStart Sector:  \t%d\n",
+                           (ulong32)(ha->hdr[i].size/2048), ha->hdr[i].start_sec);
+            len += size;  pos = begin + len;
+            if (pos < offset) {
+                len = 0;
+                begin = pos;
+            }
+            if (pos > offset + length)
+                goto stop_output;
+        }
+        
+        if (!flag) {
+            size = sprintf(buffer+len, "\n --\n");
+            len += size;  pos = begin + len;
+        }
+    }
+
+    /* controller events */
+    size = sprintf(buffer+len,"\nController Events:\n");
+    len += size;  pos = begin + len;
+
+    for (id = -1;;) {
+        id = gdth_read_event(ha, id, &estr);
+        if (estr.event_source == 0)
+            break;
+        if (estr.event_data.eu.driver.ionode == hanum &&
+            estr.event_source == ES_ASYNC) { 
+            gdth_log_event(&estr.event_data, hrec);
+            do_gettimeofday(&tv);
+            sec = (int)(tv.tv_sec - estr.first_stamp);
+            if (sec < 0) sec = 0;
+            size = sprintf(buffer+len," date- %02d:%02d:%02d\t%s\n",
+                           sec/3600, sec%3600/60, sec%60, hrec);
+            len += size;  pos = begin + len;
+            if (pos < offset) {
+                len = 0;
+                begin = pos;
+            }
+            if (pos > offset + length)
+                goto stop_output;
+        }
+        if (id == -1)
+            break;
     }
 
 stop_output:
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    scsi_release_request(scp);
+    scsi_free_host_dev(sdev);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     scsi_release_command(scp);
     scsi_free_host_dev(sdev);
 #endif
@@ -1246,13 +839,34 @@
     return(len);
 }
 
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static void gdth_do_req(Scsi_Request *scp, gdth_cmd_str *gdtcmd, 
+                        char *cmnd, int timeout)
+{
+    unsigned bufflen;
+    DECLARE_COMPLETION(wait);
+
+    TRACE2(("gdth_do_req()\n"));
+    if (gdtcmd != NULL) { 
+        bufflen = sizeof(gdth_cmd_str);
+    } else {
+        bufflen = 0;
+    }
+    scp->sr_request->rq_status = RQ_SCSI_BUSY;
+    scp->sr_request->waiting = &wait;
+    scsi_do_req(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
+    wait_for_completion(&wait);
+}
+
+#else
 static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *gdtcmd, 
                         char *cmnd, int timeout)
 {
     unsigned bufflen;
-#if LINUX_VERSION_CODE >= 0x020407
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
     DECLARE_COMPLETION(wait);
-#elif LINUX_VERSION_CODE >= 0x020322
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     DECLARE_MUTEX_LOCKED(sem);
 #else
     struct semaphore sem = MUTEX_LOCKED;
@@ -1266,63 +880,73 @@
         scp->SCp.this_residual = DEFAULT_PRI;
         bufflen = 0;
     }
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
     scp->request.rq_status = RQ_SCSI_BUSY;
-#if LINUX_VERSION_CODE >= 0x020407
     scp->request.waiting = &wait;
     scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
     wait_for_completion(&wait);
 #else
     scp->request.sem = &sem;
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
     scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
 #else
-    GDTH_LOCK_SCSI_DOCMD();
+    spin_lock_irq(&io_request_lock);
     scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1);
-    GDTH_UNLOCK_SCSI_DOCMD();
+    spin_unlock_irq(&io_request_lock);
 #endif
     down(&sem);
 #endif
 }
+#endif
 
 void gdth_scsi_done(Scsi_Cmnd *scp)
 {
     TRACE2(("gdth_scsi_done()\n"));
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+    scp->request->rq_status = RQ_SCSI_DONE;
+    if (scp->request->waiting != NULL)
+        complete(scp->request->waiting);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,7)
     scp->request.rq_status = RQ_SCSI_DONE;
-
-#if LINUX_VERSION_CODE >= 0x020407
     if (scp->request.waiting != NULL)
         complete(scp->request.waiting);
 #else
+    scp->request.rq_status = RQ_SCSI_DONE;
     if (scp->request.sem != NULL)
         up(scp->request.sem);
 #endif
 }
 
-static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch)
+static char *gdth_ioctl_alloc(int hanum, int size, int scratch, 
+                              ulong64 *paddr)
 {
     gdth_ha_str *ha;
     ulong flags;
     char *ret_val;
 
-    if (size == 0 || size > GDTH_SCRATCH)
-        return FALSE;
+    if (size == 0)
+        return NULL;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     GDTH_LOCK_HA(ha, flags);
 
-    if (scratch) { 
-        if (!ha->scratch_busy) {
-            ha->scratch_busy = TRUE;
-            ret_val = ha->pscratch;
-        } else
-            ret_val = NULL;
+    if (!ha->scratch_busy && size <= GDTH_SCRATCH) {
+        ha->scratch_busy = TRUE;
+        ret_val = ha->pscratch;
+        *paddr = ha->scratch_phys;
+    } else if (scratch) {
+        ret_val = NULL;
     } else {
-#if LINUX_VERSION_CODE >= 0x020322
-        ret_val = (void *) __get_free_pages(GFP_ATOMIC | GFP_DMA, 
-                                            GDTH_SCRATCH_ORD);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+        dma_addr_t dma_addr;
+
+        ret_val = pci_alloc_consistent(ha->pdev, size, &dma_addr);
+        *paddr = dma_addr;
 #else
-        ret_val = scsi_init_malloc(GDTH_SCRATCH, GFP_ATOMIC | GFP_DMA);
+        ret_val = scsi_init_malloc(size, GFP_ATOMIC | GFP_DMA);
+        if (ret_val)
+            *paddr = virt_to_bus(ret_val);
 #endif
     }
 
@@ -1330,7 +954,7 @@
     return ret_val;
 }
 
-static void gdth_ioctl_free(int hanum, char *buf)
+static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr)
 {
     gdth_ha_str *ha;
     ulong flags;
@@ -1341,16 +965,17 @@
     if (buf == ha->pscratch) {
         ha->scratch_busy = FALSE;
     } else {
-#if LINUX_VERSION_CODE >= 0x020322
-        free_pages((unsigned long)buf, GDTH_SCRATCH_ORD);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+        pci_free_consistent(ha->pdev, size, buf, paddr);
 #else
-        scsi_init_free((void *)buf, GDTH_SCRATCH);
+        scsi_init_free((void *)buf, size);
 #endif
     }
 
     GDTH_UNLOCK_HA(ha, flags);
 }
 
+#ifdef GDTH_IOCTL_PROC
 static int gdth_ioctl_check_bin(int hanum, ushort size)
 {
     gdth_ha_str *ha;
@@ -1368,7 +993,7 @@
     GDTH_UNLOCK_HA(ha, flags);
     return ret_val;
 }
-
+#endif
 
 static void gdth_wait_completion(int hanum, int busnum, int id)
 {
@@ -1376,23 +1001,35 @@
     ulong flags;
     int i;
     Scsi_Cmnd *scp;
-    unchar b;
+    unchar b, t;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     GDTH_LOCK_HA(ha, flags);
 
     for (i = 0; i < GDTH_MAXCMDS; ++i) {
         scp = ha->cmd_tab[i].cmnd;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+        t = scp->device->id;
+#else
         b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
-        if (!SPECIAL_SCP(scp) && scp->target == (unchar)id && 
+        t = scp->target;
+#endif
+        if (!SPECIAL_SCP(scp) && t == (unchar)id && 
             b == (unchar)busnum) {
             scp->SCp.have_data_in = 0;
             GDTH_UNLOCK_HA(ha, flags);
             while (!scp->SCp.have_data_in)
                 barrier();
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+            GDTH_LOCK_SCSI_DONE(scp->device->host, flags);
+            scp->scsi_done(scp);
+            GDTH_UNLOCK_SCSI_DONE(scp->device->host, flags);
+#else
             GDTH_LOCK_SCSI_DONE(flags);
             scp->scsi_done(scp);
             GDTH_UNLOCK_SCSI_DONE(flags);
+#endif
         GDTH_LOCK_HA(ha, flags);
         }
     }
@@ -1404,14 +1041,20 @@
     gdth_ha_str *ha;
     ulong flags;
     Scsi_Cmnd *scp;
-    unchar b;
+    unchar b, t;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     GDTH_LOCK_HA(ha, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+        t = scp->device->id;
+#else
         b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
-        if (scp->target == (unchar)id && b == (unchar)busnum) {
+        t = scp->target;
+#endif
+        if (t == (unchar)id && b == (unchar)busnum) {
             TRACE2(("gdth_stop_timeout(): update_timeout()\n"));
             scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0);
         }
@@ -1424,14 +1067,20 @@
     gdth_ha_str *ha;
     ulong flags;
     Scsi_Cmnd *scp;
-    unchar b;
+    unchar b, t;
 
     ha = HADATA(gdth_ctr_tab[hanum]);
     GDTH_LOCK_HA(ha, flags);
 
     for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+        b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel;
+        t = scp->device->id;
+#else
         b = virt_ctr ? NUMDATA(scp->host)->busnum : scp->channel;
-        if (scp->target == (unchar)id && b == (unchar)busnum) {
+        t = scp->target;
+#endif
+        if (t == (unchar)id && b == (unchar)busnum) {
             TRACE2(("gdth_start_timeout(): update_timeout()\n"));
             gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual);
         }
@@ -1446,7 +1095,6 @@
     oldto = scp->timeout_per_command;
     scp->timeout_per_command = timeout;
 
-#if LINUX_VERSION_CODE >= 0x02014B
     if (timeout == 0) {
         del_timer(&scp->eh_timeout);
         scp->eh_timeout.data = (unsigned long) NULL;
@@ -1458,17 +1106,6 @@
         scp->eh_timeout.expires = jiffies + timeout;
         add_timer(&scp->eh_timeout);
     }
-#else
-    if (timeout > 0) {
-        if (timer_table[SCSI_TIMER].expires == 0) {
-            timer_table[SCSI_TIMER].expires = jiffies + timeout;
-            timer_active |= 1 << SCSI_TIMER;
-        } else {
-            if (time_before(jiffies + timeout < timer_table[SCSI_TIMER].expires))
-                timer_table[SCSI_TIMER].expires = jiffies + timeout;
-        }
-    }
-#endif
 
     return oldto;
 }
diff -Nru a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h
--- a/drivers/scsi/gdth_proc.h	2002-02-04 23:44:55 -08:00
+++ b/drivers/scsi/gdth_proc.h	2004-09-27 04:21:44 -07:00
@@ -2,26 +2,31 @@
 #define _GDTH_PROC_H
 
 /* gdth_proc.h 
- * $Id: gdth_proc.h,v 1.11 2001/07/25 15:37:40 achim Exp $
+ * $Id: gdth_proc.h,v 1.16 2004/01/14 13:09:01 achim Exp $
  */
 
-static int gdth_set_info(char *buffer,int length,int vh,int hanum,int busnum);
-static int gdth_get_info(char *buffer,char **start,off_t offset,
-                         int length,int vh,int hanum,int busnum);
+static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host,
+                         int hanum,int busnum);
+static int gdth_get_info(char *buffer,char **start,off_t offset,int length,
+                         struct Scsi_Host *host,int hanum,int busnum);
 
-#if LINUX_VERSION_CODE >= 0x020322
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
+static void gdth_do_req(Scsi_Request *srp, gdth_cmd_str *cmd, 
+                        char *cmnd, int timeout);
+static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Request *scp);
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, 
+                        char *cmnd, int timeout);
 static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
-static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd *scp);
 #else 
-static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
-static int gdth_set_bin_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
-#endif
 static void gdth_do_cmd(Scsi_Cmnd *scp, gdth_cmd_str *cmd, 
                         char *cmnd, int timeout);
+static int gdth_set_asc_info(char *buffer,int length,int hanum,Scsi_Cmnd scp);
+#endif
 
-static char *gdth_ioctl_alloc(int hanum, ushort size, int scratch);
-static void gdth_ioctl_free(int hanum, char *buf);
-static int gdth_ioctl_check_bin(int hanum, ushort size);
+static char *gdth_ioctl_alloc(int hanum, int size, int scratch,
+                              ulong64 *paddr);  
+static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr);
 static void gdth_wait_completion(int hanum, int busnum, int id);
 static void gdth_stop_timeout(int hanum, int busnum, int id);
 static void gdth_start_timeout(int hanum, int busnum, int id);
diff -Nru a/drivers/scsi/ips.h b/drivers/scsi/ips.h
--- a/drivers/scsi/ips.h	2004-08-20 00:18:04 -07:00
+++ b/drivers/scsi/ips.h	2004-09-14 10:19:15 -07:00
@@ -95,15 +95,13 @@
       #define scsi_set_pci_device(sh,dev) (0)
    #endif
 
-   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
-   
-      #ifndef irqreturn_t
-         typedef void irqreturn_t;
-      #endif 
-      
+   #ifndef IRQ_NONE
+      typedef void irqreturn_t;
       #define IRQ_NONE
       #define IRQ_HANDLED
       #define IRQ_RETVAL(x)
+   #endif
+   #if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
       #define IPS_REGISTER_HOSTS(SHT)      scsi_register_module(MODULE_SCSI_HA,SHT)
       #define IPS_UNREGISTER_HOSTS(SHT)    scsi_unregister_module(MODULE_SCSI_HA,SHT)
       #define IPS_ADD_HOST(shost,device)
diff -Nru a/drivers/scsi/libata-core.c b/drivers/scsi/libata-core.c
--- a/drivers/scsi/libata-core.c	2004-08-31 00:01:32 -07:00
+++ b/drivers/scsi/libata-core.c	2004-09-14 19:40:02 -07:00
@@ -90,17 +90,17 @@
 }
 
 /**
- *	ata_tf_load_pio - send taskfile registers to host controller
+ *	ata_tf_load - send taskfile registers to host controller
  *	@ap: Port to which output is sent
  *	@tf: ATA taskfile register set
  *
- *	Outputs ATA taskfile to standard ATA host controller using PIO.
+ *	Outputs ATA taskfile to standard ATA host controller.
  *
  *	LOCKING:
  *	Inherited from caller.
  */
 
-void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
@@ -158,23 +158,23 @@
  *	Inherited from caller.
  */
 
-void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 	unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR;
 
 	if (tf->ctl != ap->last_ctl) {
-		writeb(tf->ctl, ap->ioaddr.ctl_addr);
+		writeb(tf->ctl, (void __iomem *) ap->ioaddr.ctl_addr);
 		ap->last_ctl = tf->ctl;
 		ata_wait_idle(ap);
 	}
 
 	if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) {
-		writeb(tf->hob_feature, (void *) ioaddr->feature_addr);
-		writeb(tf->hob_nsect, (void *) ioaddr->nsect_addr);
-		writeb(tf->hob_lbal, (void *) ioaddr->lbal_addr);
-		writeb(tf->hob_lbam, (void *) ioaddr->lbam_addr);
-		writeb(tf->hob_lbah, (void *) ioaddr->lbah_addr);
+		writeb(tf->hob_feature, (void __iomem *) ioaddr->feature_addr);
+		writeb(tf->hob_nsect, (void __iomem *) ioaddr->nsect_addr);
+		writeb(tf->hob_lbal, (void __iomem *) ioaddr->lbal_addr);
+		writeb(tf->hob_lbam, (void __iomem *) ioaddr->lbam_addr);
+		writeb(tf->hob_lbah, (void __iomem *) ioaddr->lbah_addr);
 		VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n",
 			tf->hob_feature,
 			tf->hob_nsect,
@@ -184,11 +184,11 @@
 	}
 
 	if (is_addr) {
-		writeb(tf->feature, (void *) ioaddr->feature_addr);
-		writeb(tf->nsect, (void *) ioaddr->nsect_addr);
-		writeb(tf->lbal, (void *) ioaddr->lbal_addr);
-		writeb(tf->lbam, (void *) ioaddr->lbam_addr);
-		writeb(tf->lbah, (void *) ioaddr->lbah_addr);
+		writeb(tf->feature, (void __iomem *) ioaddr->feature_addr);
+		writeb(tf->nsect, (void __iomem *) ioaddr->nsect_addr);
+		writeb(tf->lbal, (void __iomem *) ioaddr->lbal_addr);
+		writeb(tf->lbam, (void __iomem *) ioaddr->lbam_addr);
+		writeb(tf->lbah, (void __iomem *) ioaddr->lbah_addr);
 		VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n",
 			tf->feature,
 			tf->nsect,
@@ -198,26 +198,34 @@
 	}
 
 	if (tf->flags & ATA_TFLAG_DEVICE) {
-		writeb(tf->device, (void *) ioaddr->device_addr);
+		writeb(tf->device, (void __iomem *) ioaddr->device_addr);
 		VPRINTK("device 0x%X\n", tf->device);
 	}
 
 	ata_wait_idle(ap);
 }
 
+void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_tf_load_mmio(ap, tf);
+	else
+		ata_tf_load_pio(ap, tf);
+}
+
 /**
- *	ata_exec_command_pio - issue ATA command to host controller
+ *	ata_exec_command - issue ATA command to host controller
  *	@ap: port to which command is being issued
  *	@tf: ATA taskfile register set
  *
- *	Issues PIO write to ATA command register, with proper
+ *	Issues PIO/MMIO write to ATA command register, with proper
  *	synchronization with interrupt handler / other threads.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
 
@@ -238,20 +246,28 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
 
-       	writeb(tf->command, (void *) ap->ioaddr.command_addr);
+       	writeb(tf->command, (void __iomem *) ap->ioaddr.command_addr);
 	ata_pause(ap);
 }
 
+void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_exec_command_mmio(ap, tf);
+	else
+		ata_exec_command_pio(ap, tf);
+}
+
 /**
  *	ata_exec - issue ATA command to host controller
  *	@ap: port to which command is being issued
  *	@tf: ATA taskfile register set
  *
- *	Issues PIO write to ATA command register, with proper
+ *	Issues PIO/MMIO write to ATA command register, with proper
  *	synchronization with interrupt handler / other threads.
  *
  *	LOCKING:
@@ -274,7 +290,7 @@
  *	@tf: ATA taskfile register set
  *
  *	Issues ATA taskfile register set to ATA host controller,
- *	via PIO, with proper synchronization with interrupt handler and
+ *	with proper synchronization with interrupt handler and
  *	other threads.
  *
  *	LOCKING:
@@ -294,7 +310,7 @@
  *	@tf: ATA taskfile register set
  *
  *	Issues ATA taskfile register set to ATA host controller,
- *	via PIO, with proper synchronization with interrupt handler and
+ *	with proper synchronization with interrupt handler and
  *	other threads.
  *
  *	LOCKING:
@@ -308,18 +324,18 @@
 }
 
 /**
- *	ata_tf_read_pio - input device's ATA taskfile shadow registers
+ *	ata_tf_read - input device's ATA taskfile shadow registers
  *	@ap: Port from which input is read
  *	@tf: ATA taskfile register set for storing input
  *
  *	Reads ATA taskfile registers for currently-selected device
- *	into @tf via PIO.
+ *	into @tf.
  *
  *	LOCKING:
  *	Inherited from caller.
  */
 
-void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
@@ -351,38 +367,46 @@
  *	Inherited from caller.
  */
 
-void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
+static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
 {
 	struct ata_ioports *ioaddr = &ap->ioaddr;
 
-	tf->nsect = readb((void *)ioaddr->nsect_addr);
-	tf->lbal = readb((void *)ioaddr->lbal_addr);
-	tf->lbam = readb((void *)ioaddr->lbam_addr);
-	tf->lbah = readb((void *)ioaddr->lbah_addr);
-	tf->device = readb((void *)ioaddr->device_addr);
+	tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
+	tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
+	tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
+	tf->lbah = readb((void __iomem *)ioaddr->lbah_addr);
+	tf->device = readb((void __iomem *)ioaddr->device_addr);
 
 	if (tf->flags & ATA_TFLAG_LBA48) {
-		writeb(tf->ctl | ATA_HOB, ap->ioaddr.ctl_addr);
-		tf->hob_feature = readb((void *)ioaddr->error_addr);
-		tf->hob_nsect = readb((void *)ioaddr->nsect_addr);
-		tf->hob_lbal = readb((void *)ioaddr->lbal_addr);
-		tf->hob_lbam = readb((void *)ioaddr->lbam_addr);
-		tf->hob_lbah = readb((void *)ioaddr->lbah_addr);
+		writeb(tf->ctl | ATA_HOB, (void __iomem *) ap->ioaddr.ctl_addr);
+		tf->hob_feature = readb((void __iomem *)ioaddr->error_addr);
+		tf->hob_nsect = readb((void __iomem *)ioaddr->nsect_addr);
+		tf->hob_lbal = readb((void __iomem *)ioaddr->lbal_addr);
+		tf->hob_lbam = readb((void __iomem *)ioaddr->lbam_addr);
+		tf->hob_lbah = readb((void __iomem *)ioaddr->lbah_addr);
 	}
 }
 
+void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		ata_tf_read_mmio(ap, tf);
+	else
+		ata_tf_read_pio(ap, tf);
+}
+
 /**
- *	ata_check_status_pio - Read device status reg & clear interrupt
+ *	ata_check_status - Read device status reg & clear interrupt
  *	@ap: port where the device is
  *
  *	Reads ATA taskfile status register for currently-selected device
- *	via PIO and return it's value. This also clears pending interrupts
+ *	and return it's value. This also clears pending interrupts
  *      from this device
  *
  *	LOCKING:
  *	Inherited from caller.
  */
-u8 ata_check_status_pio(struct ata_port *ap)
+static u8 ata_check_status_pio(struct ata_port *ap)
 {
 	return inb(ap->ioaddr.status_addr);
 }
@@ -398,9 +422,16 @@
  *	LOCKING:
  *	Inherited from caller.
  */
-u8 ata_check_status_mmio(struct ata_port *ap)
+static u8 ata_check_status_mmio(struct ata_port *ap)
 {
-       	return readb((void *) ap->ioaddr.status_addr);
+       	return readb((void __iomem *) ap->ioaddr.status_addr);
+}
+
+u8 ata_check_status(struct ata_port *ap)
+{
+	if (ap->flags & ATA_FLAG_MMIO)
+		return ata_check_status_mmio(ap);
+	return ata_check_status_pio(ap);
 }
 
 /**
@@ -674,17 +705,17 @@
 
 	__ata_dev_select(ap, device);
 
-	writeb(0x55, (void *) ioaddr->nsect_addr);
-	writeb(0xaa, (void *) ioaddr->lbal_addr);
+	writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
+	writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
 
-	writeb(0xaa, (void *) ioaddr->nsect_addr);
-	writeb(0x55, (void *) ioaddr->lbal_addr);
+	writeb(0xaa, (void __iomem *) ioaddr->nsect_addr);
+	writeb(0x55, (void __iomem *) ioaddr->lbal_addr);
 
-	writeb(0x55, (void *) ioaddr->nsect_addr);
-	writeb(0xaa, (void *) ioaddr->lbal_addr);
+	writeb(0x55, (void __iomem *) ioaddr->nsect_addr);
+	writeb(0xaa, (void __iomem *) ioaddr->lbal_addr);
 
-	nsect = readb((void *) ioaddr->nsect_addr);
-	lbal = readb((void *) ioaddr->lbal_addr);
+	nsect = readb((void __iomem *) ioaddr->nsect_addr);
+	lbal = readb((void __iomem *) ioaddr->lbal_addr);
 
 	if ((nsect == 0x55) && (lbal == 0xaa))
 		return 1;	/* we found a device */
@@ -693,7 +724,7 @@
 }
 
 /**
- *	ata_dev_devchk - PATA device presence detection
+ *	ata_devchk - PATA device presence detection
  *	@ap: ATA channel to examine
  *	@device: Device to examine (starting at zero)
  *
@@ -705,7 +736,7 @@
  *	caller.
  */
 
-static unsigned int ata_dev_devchk(struct ata_port *ap,
+static unsigned int ata_devchk(struct ata_port *ap,
 				    unsigned int device)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
@@ -863,7 +894,7 @@
 		tmp = ATA_DEVICE_OBS | ATA_DEV1;
 
 	if (ap->flags & ATA_FLAG_MMIO) {
-		writeb(tmp, (void *) ap->ioaddr.device_addr);
+		writeb(tmp, (void __iomem *) ap->ioaddr.device_addr);
 	} else {
 		outb(tmp, ap->ioaddr.device_addr);
 	}
@@ -1461,13 +1492,13 @@
 	unsigned int dev1 = devmask & (1 << 1);
 	unsigned long timeout;
 
-	/* if device 0 was found in ata_dev_devchk, wait for its
+	/* if device 0 was found in ata_devchk, wait for its
 	 * BSY bit to clear
 	 */
 	if (dev0)
 		ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT);
 
-	/* if device 1 was found in ata_dev_devchk, wait for
+	/* if device 1 was found in ata_devchk, wait for
 	 * register access, then wait for BSY to clear
 	 */
 	timeout = jiffies + ATA_TMOUT_BOOT;
@@ -1476,8 +1507,8 @@
 
 		__ata_dev_select(ap, 1);
 		if (ap->flags & ATA_FLAG_MMIO) {
-			nsect = readb((void *) ioaddr->nsect_addr);
-			lbal = readb((void *) ioaddr->lbal_addr);
+			nsect = readb((void __iomem *) ioaddr->nsect_addr);
+			lbal = readb((void __iomem *) ioaddr->lbal_addr);
 		} else {
 			nsect = inb(ioaddr->nsect_addr);
 			lbal = inb(ioaddr->lbal_addr);
@@ -1541,11 +1572,11 @@
 
 	/* software reset.  causes dev0 to be selected */
 	if (ap->flags & ATA_FLAG_MMIO) {
-		writeb(ap->ctl, ioaddr->ctl_addr);
+		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 		udelay(20);	/* FIXME: flush */
-		writeb(ap->ctl | ATA_SRST, ioaddr->ctl_addr);
+		writeb(ap->ctl | ATA_SRST, (void __iomem *) ioaddr->ctl_addr);
 		udelay(20);	/* FIXME: flush */
-		writeb(ap->ctl, ioaddr->ctl_addr);
+		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 	} else {
 		outb(ap->ctl, ioaddr->ctl_addr);
 		udelay(10);
@@ -1602,9 +1633,9 @@
 	if (ap->flags & ATA_FLAG_SATA_RESET)
 		dev0 = 1;
 	else {
-		dev0 = ata_dev_devchk(ap, 0);
+		dev0 = ata_devchk(ap, 0);
 		if (slave_possible)
-			dev1 = ata_dev_devchk(ap, 1);
+			dev1 = ata_devchk(ap, 1);
 	}
 
 	if (dev0)
@@ -1621,7 +1652,7 @@
 	else if ((ap->flags & ATA_FLAG_SATA_RESET) == 0) {
 		/* set up device control */
 		if (ap->flags & ATA_FLAG_MMIO)
-			writeb(ap->ctl, ioaddr->ctl_addr);
+			writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 		else
 			outb(ap->ctl, ioaddr->ctl_addr);
 		rc = ata_bus_edd(ap);
@@ -1654,7 +1685,7 @@
 	if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) {
 		/* set up device control for ATA_FLAG_SATA_RESET */
 		if (ap->flags & ATA_FLAG_MMIO)
-			writeb(ap->ctl, ioaddr->ctl_addr);
+			writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 		else
 			outb(ap->ctl, ioaddr->ctl_addr);
 	}
@@ -2101,7 +2132,7 @@
 	unsigned int i;
 	unsigned int words = buflen >> 1;
 	u16 *buf16 = (u16 *) buf;
-	void *mmio = (void *)ap->ioaddr.data_addr;
+	void __iomem *mmio = (void __iomem *)ap->ioaddr.data_addr;
 
 	if (write_data) {
 		for (i = 0; i < words; i++)
@@ -2182,7 +2213,7 @@
 	/* shall be cleared to zero, indicating xfer of data */
 	if (ireason & (1 << 0))
 		goto err_out;
-	
+
 	/* make sure transfer direction matches expected */
 	i_write = ((ireason & (1 << 1)) == 0) ? 1 : 0;
 	if (do_write != i_write)
@@ -2198,7 +2229,7 @@
 
 	for (i = 0; i < (bytes >> 9); i++)
 		ata_pio_sector(qc);
-	
+
 	return;
 
 err_out:
@@ -2627,19 +2658,19 @@
 }
 
 /**
- *	ata_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
+ *	ata_bmdma_setup - Set up PCI IDE BMDMA transaction
  *	@qc: Info associated with this ATA transaction.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+static void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
 	u8 dmactl;
-	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 
 	/* load PRD table addr. */
 	mb();	/* make sure PRD table writes are visible to controller */
@@ -2657,17 +2688,17 @@
 }
 
 /**
- *	ata_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
+ *	ata_bmdma_start - Start a PCI IDE BMDMA transaction
  *	@qc: Info associated with this ATA transaction.
  *
  *	LOCKING:
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
+static void ata_bmdma_start_mmio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
-	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 	u8 dmactl;
 
 	/* start host DMA transaction */
@@ -2695,7 +2726,7 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
+static void ata_bmdma_setup_pio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
@@ -2723,7 +2754,7 @@
  *	spin_lock_irqsave(host_set lock)
  */
 
-void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
+static void ata_bmdma_start_pio (struct ata_queued_cmd *qc)
 {
 	struct ata_port *ap = qc->ap;
 	u8 dmactl;
@@ -2734,6 +2765,22 @@
 	     ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
 }
 
+void ata_bmdma_start(struct ata_queued_cmd *qc)
+{
+	if (qc->ap->flags & ATA_FLAG_MMIO)
+		ata_bmdma_start_mmio(qc);
+	else
+		ata_bmdma_start_pio(qc);
+}
+
+void ata_bmdma_setup(struct ata_queued_cmd *qc)
+{
+	if (qc->ap->flags & ATA_FLAG_MMIO)
+		ata_bmdma_setup_mmio(qc);
+	else
+		ata_bmdma_setup_pio(qc);
+}
+
 void ata_bmdma_irq_clear(struct ata_port *ap)
 {
 	ata_bmdma_ack_irq(ap);
@@ -3244,6 +3291,95 @@
 	ioaddr->command_addr = ioaddr->cmd_addr + ATA_REG_CMD;
 }
 
+static struct ata_probe_ent *
+ata_probe_ent_alloc(int n, struct pci_dev *pdev, struct ata_port_info **port)
+{
+	struct ata_probe_ent *probe_ent;
+	int i;
+
+	probe_ent = kmalloc(sizeof(*probe_ent) * n, GFP_KERNEL);
+	if (!probe_ent) {
+		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
+		       pci_name(pdev));
+		return NULL;
+	}
+
+	memset(probe_ent, 0, sizeof(*probe_ent) * n);
+
+	for (i = 0; i < n; i++) {
+		INIT_LIST_HEAD(&probe_ent[i].node);
+		probe_ent[i].pdev = pdev;
+
+		probe_ent[i].sht = port[i]->sht;
+		probe_ent[i].host_flags = port[i]->host_flags;
+		probe_ent[i].pio_mask = port[i]->pio_mask;
+		probe_ent[i].mwdma_mask = port[i]->mwdma_mask;
+		probe_ent[i].udma_mask = port[i]->udma_mask;
+		probe_ent[i].port_ops = port[i]->port_ops;
+
+	}
+
+	return probe_ent;
+}
+
+struct ata_probe_ent *
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port)
+{
+	struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(1, pdev, port);
+	if (!probe_ent)
+		return NULL;
+
+	probe_ent->n_ports = 2;
+	probe_ent->irq = pdev->irq;
+	probe_ent->irq_flags = SA_SHIRQ;
+
+	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
+	probe_ent->port[0].altstatus_addr =
+	probe_ent->port[0].ctl_addr =
+		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
+	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+
+	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
+	probe_ent->port[1].altstatus_addr =
+	probe_ent->port[1].ctl_addr =
+		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
+	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
+
+	ata_std_ports(&probe_ent->port[0]);
+	ata_std_ports(&probe_ent->port[1]);
+
+	return probe_ent;
+}
+
+struct ata_probe_ent *
+ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port)
+{
+	struct ata_probe_ent *probe_ent = ata_probe_ent_alloc(2, pdev, port);
+	if (!probe_ent)
+		return NULL;
+
+	probe_ent[0].n_ports = 1;
+	probe_ent[0].irq = 14;
+
+	probe_ent[1].n_ports = 1;
+	probe_ent[1].irq = 15;
+
+	probe_ent[0].port[0].cmd_addr = 0x1f0;
+	probe_ent[0].port[0].altstatus_addr =
+	probe_ent[0].port[0].ctl_addr = 0x3f6;
+	probe_ent[0].port[0].bmdma_addr = pci_resource_start(pdev, 4);
+
+	probe_ent[1].port[0].cmd_addr = 0x170;
+	probe_ent[1].port[0].altstatus_addr =
+	probe_ent[1].port[0].ctl_addr = 0x376;
+	probe_ent[1].port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
+
+	ata_std_ports(&probe_ent[0].port[0]);
+	ata_std_ports(&probe_ent[1].port[0]);
+
+	return probe_ent;
+}
+
 /**
  *	ata_pci_init_one - Initialize/register PCI IDE host controller
  *	@pdev: Controller to be initialized
@@ -3261,20 +3397,20 @@
 		      unsigned int n_ports)
 {
 	struct ata_probe_ent *probe_ent, *probe_ent2 = NULL;
-	struct ata_port_info *port0, *port1;
+	struct ata_port_info *port[2];
 	u8 tmp8, mask;
 	unsigned int legacy_mode = 0;
 	int rc;
 
 	DPRINTK("ENTER\n");
 
-	port0 = port_info[0];
+	port[0] = port_info[0];
 	if (n_ports > 1)
-		port1 = port_info[1];
+		port[1] = port_info[1];
 	else
-		port1 = port0;
+		port[1] = port[0];
 
-	if ((port0->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
+	if ((port[0]->host_flags & ATA_FLAG_NO_LEGACY) == 0) {
 		/* TODO: support transitioning to native mode? */
 		pci_read_config_byte(pdev, PCI_CLASS_PROG, &tmp8);
 		mask = (1 << 2) | (1 << 0);
@@ -3318,89 +3454,32 @@
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	if (legacy_mode) {
+		probe_ent = ata_pci_init_legacy_mode(pdev, port);
+		if (probe_ent)
+			probe_ent2 = &probe_ent[1];
+	} else
+		probe_ent = ata_pci_init_native_mode(pdev, port);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	probe_ent->pdev = pdev;
-	INIT_LIST_HEAD(&probe_ent->node);
-
-	if (legacy_mode) {
-		probe_ent2 = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
-		if (!probe_ent2) {
-			rc = -ENOMEM;
-			goto err_out_free_ent;
-		}
-
-		memset(probe_ent2, 0, sizeof(*probe_ent));
-		probe_ent2->pdev = pdev;
-		INIT_LIST_HEAD(&probe_ent2->node);
-	}
-
-	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-	probe_ent->sht = port0->sht;
-	probe_ent->host_flags = port0->host_flags;
-	probe_ent->pio_mask = port0->pio_mask;
-	probe_ent->mwdma_mask = port0->mwdma_mask;
-	probe_ent->udma_mask = port0->udma_mask;
-	probe_ent->port_ops = port0->port_ops;
-
-	if (legacy_mode) {
-		probe_ent->port[0].cmd_addr = 0x1f0;
-		probe_ent->port[0].altstatus_addr =
-		probe_ent->port[0].ctl_addr = 0x3f6;
-		probe_ent->n_ports = 1;
-		probe_ent->irq = 14;
-		ata_std_ports(&probe_ent->port[0]);
-
-		probe_ent2->port[0].cmd_addr = 0x170;
-		probe_ent2->port[0].altstatus_addr =
-		probe_ent2->port[0].ctl_addr = 0x376;
-		probe_ent2->port[0].bmdma_addr = pci_resource_start(pdev, 4)+8;
-		probe_ent2->n_ports = 1;
-		probe_ent2->irq = 15;
-		ata_std_ports(&probe_ent2->port[0]);
-
-		probe_ent2->sht = port1->sht;
-		probe_ent2->host_flags = port1->host_flags;
-		probe_ent2->pio_mask = port1->pio_mask;
-		probe_ent2->mwdma_mask = port1->mwdma_mask;
-		probe_ent2->udma_mask = port1->udma_mask;
-		probe_ent2->port_ops = port1->port_ops;
-	} else {
-		probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-		ata_std_ports(&probe_ent->port[0]);
-		probe_ent->port[0].altstatus_addr =
-		probe_ent->port[0].ctl_addr =
-			pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-
-		probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-		ata_std_ports(&probe_ent->port[1]);
-		probe_ent->port[1].altstatus_addr =
-		probe_ent->port[1].ctl_addr =
-			pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-		probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
-
-		probe_ent->n_ports = 2;
-		probe_ent->irq = pdev->irq;
-		probe_ent->irq_flags = SA_SHIRQ;
-	}
-
 	pci_set_master(pdev);
 
 	spin_lock(&ata_module_lock);
 	if (legacy_mode) {
+		int free = 0;
 		if (legacy_mode & (1 << 0))
 			list_add_tail(&probe_ent->node, &ata_probe_list);
 		else
-			kfree(probe_ent);
+			free++;
 		if (legacy_mode & (1 << 1))
 			list_add_tail(&probe_ent2->node, &ata_probe_list);
 		else
-			kfree(probe_ent2);
+			free++;
+		if (free > 1)
+			kfree(probe_ent);
 	} else {
 		list_add_tail(&probe_ent->node, &ata_probe_list);
 	}
@@ -3408,8 +3487,6 @@
 
 	return 0;
 
-err_out_free_ent:
-	kfree(probe_ent);
 err_out_regions:
 	if (legacy_mode & (1 << 0))
 		release_region(0x1f0, 8);
@@ -3567,24 +3644,20 @@
 EXPORT_SYMBOL_GPL(ata_qc_complete);
 EXPORT_SYMBOL_GPL(ata_qc_issue_prot);
 EXPORT_SYMBOL_GPL(ata_eng_timeout);
-EXPORT_SYMBOL_GPL(ata_tf_load_pio);
-EXPORT_SYMBOL_GPL(ata_tf_load_mmio);
-EXPORT_SYMBOL_GPL(ata_tf_read_pio);
-EXPORT_SYMBOL_GPL(ata_tf_read_mmio);
+EXPORT_SYMBOL_GPL(ata_tf_load);
+EXPORT_SYMBOL_GPL(ata_tf_read);
 EXPORT_SYMBOL_GPL(ata_tf_to_fis);
 EXPORT_SYMBOL_GPL(ata_tf_from_fis);
-EXPORT_SYMBOL_GPL(ata_check_status_pio);
-EXPORT_SYMBOL_GPL(ata_check_status_mmio);
-EXPORT_SYMBOL_GPL(ata_exec_command_pio);
-EXPORT_SYMBOL_GPL(ata_exec_command_mmio);
+EXPORT_SYMBOL_GPL(ata_pci_init_legacy_mode);
+EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
+EXPORT_SYMBOL_GPL(ata_check_status);
+EXPORT_SYMBOL_GPL(ata_exec_command);
 EXPORT_SYMBOL_GPL(ata_port_start);
 EXPORT_SYMBOL_GPL(ata_port_stop);
 EXPORT_SYMBOL_GPL(ata_interrupt);
 EXPORT_SYMBOL_GPL(ata_qc_prep);
-EXPORT_SYMBOL_GPL(ata_bmdma_setup_pio);
-EXPORT_SYMBOL_GPL(ata_bmdma_start_pio);
-EXPORT_SYMBOL_GPL(ata_bmdma_setup_mmio);
-EXPORT_SYMBOL_GPL(ata_bmdma_start_mmio);
+EXPORT_SYMBOL_GPL(ata_bmdma_setup);
+EXPORT_SYMBOL_GPL(ata_bmdma_start);
 EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
 EXPORT_SYMBOL_GPL(ata_port_probe);
 EXPORT_SYMBOL_GPL(sata_phy_reset);
diff -Nru a/drivers/scsi/sata_nv.c b/drivers/scsi/sata_nv.c
--- a/drivers/scsi/sata_nv.c	2004-08-28 16:29:46 -07:00
+++ b/drivers/scsi/sata_nv.c	2004-09-14 19:40:02 -07:00
@@ -50,8 +50,6 @@
 #define NV_PIO_MASK			0x1f
 #define NV_MWDMA_MASK			0x07
 #define NV_UDMA_MASK			0x7f
-#define NV_PORT0_BMDMA_REG_OFFSET	0x00
-#define NV_PORT1_BMDMA_REG_OFFSET	0x08
 #define NV_PORT0_SCR_REG_OFFSET		0x00
 #define NV_PORT1_SCR_REG_OFFSET		0x40
 
@@ -184,7 +182,7 @@
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
-	.ioctl                  = ata_scsi_ioctl,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -201,13 +199,13 @@
 
 static struct ata_port_operations nv_ops = {
 	.port_disable		= ata_port_disable,
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.exec_command		= ata_exec_command_pio,
-	.check_status		= ata_check_status_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.exec_command		= ata_exec_command,
+	.check_status		= ata_check_status,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup		= ata_bmdma_setup_pio,
-	.bmdma_start		= ata_bmdma_start_pio,
+	.bmdma_setup		= ata_bmdma_setup,
+	.bmdma_start		= ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -220,6 +218,18 @@
 	.host_stop		= nv_host_stop,
 };
 
+static struct ata_port_info nv_port_info = {
+	.sht		= &nv_sht,
+	.host_flags	= ATA_FLAG_SATA |
+			  ATA_FLAG_SATA_RESET |
+			  ATA_FLAG_SRST |
+			  ATA_FLAG_NO_LEGACY,
+	.pio_mask	= NV_PIO_MASK,
+	.mwdma_mask	= NV_MWDMA_MASK,
+	.udma_mask	= NV_UDMA_MASK,
+	.port_ops	= &nv_ops,
+};
+
 MODULE_AUTHOR("NVIDIA");
 MODULE_DESCRIPTION("low-level driver for NVIDIA nForce SATA controller");
 MODULE_LICENSE("GPL");
@@ -300,6 +310,7 @@
 {
 	static int printed_version = 0;
 	struct nv_host *host;
+	struct ata_port_info *ppi;
 	struct ata_probe_ent *probe_ent = NULL;
 	int rc;
 
@@ -318,7 +329,8 @@
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	ppi = &nv_port_info;
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
@@ -331,40 +343,6 @@
 	}
 
 	host->host_desc = &nv_device_tbl[ent->driver_data];
-
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	INIT_LIST_HEAD(&probe_ent->node);
-
-	probe_ent->pdev = pdev;
-	probe_ent->sht = &nv_sht;
-	probe_ent->host_flags = ATA_FLAG_SATA |
-				ATA_FLAG_SATA_RESET |
-				ATA_FLAG_SRST |
-				ATA_FLAG_NO_LEGACY;
-
-	probe_ent->port_ops = &nv_ops;
-	probe_ent->n_ports = NV_PORTS;
-	probe_ent->irq = pdev->irq;
-	probe_ent->irq_flags = SA_SHIRQ;
-	probe_ent->pio_mask = NV_PIO_MASK;
-	probe_ent->mwdma_mask = NV_MWDMA_MASK;
-	probe_ent->udma_mask = NV_UDMA_MASK;
-
-	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-	ata_std_ports(&probe_ent->port[0]);
-	probe_ent->port[0].altstatus_addr =
-	probe_ent->port[0].ctl_addr =
-		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-	probe_ent->port[0].bmdma_addr =
-		pci_resource_start(pdev, 4) | NV_PORT0_BMDMA_REG_OFFSET;
-
-	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-	ata_std_ports(&probe_ent->port[1]);
-	probe_ent->port[1].altstatus_addr =
-	probe_ent->port[1].ctl_addr =
-		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-	probe_ent->port[1].bmdma_addr =
-		pci_resource_start(pdev, 4) | NV_PORT1_BMDMA_REG_OFFSET;
 
 	probe_ent->private_data = host;
 
diff -Nru a/drivers/scsi/sata_promise.c b/drivers/scsi/sata_promise.c
--- a/drivers/scsi/sata_promise.c	2004-08-14 12:38:51 -07:00
+++ b/drivers/scsi/sata_promise.c	2004-09-13 19:35:23 -07:00
@@ -91,7 +91,7 @@
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
-	.ioctl                  = ata_scsi_ioctl,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -109,8 +109,8 @@
 static struct ata_port_operations pdc_sata_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
-	.tf_read		= ata_tf_read_mmio,
-	.check_status		= ata_check_status_mmio,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
 	.exec_command		= pdc_exec_command_mmio,
 	.phy_reset		= pdc_phy_reset,
 	.qc_prep		= pdc_qc_prep,
@@ -470,7 +470,7 @@
 {
 	WARN_ON (tf->protocol == ATA_PROT_DMA ||
 		 tf->protocol == ATA_PROT_NODATA);
-	ata_tf_load_mmio(ap, tf);
+	ata_tf_load(ap, tf);
 }
 
 
@@ -478,7 +478,7 @@
 {
 	WARN_ON (tf->protocol == ATA_PROT_DMA ||
 		 tf->protocol == ATA_PROT_NODATA);
-	ata_exec_command_mmio(ap, tf);
+	ata_exec_command(ap, tf);
 }
 
 
diff -Nru a/drivers/scsi/sata_sil.c b/drivers/scsi/sata_sil.c
--- a/drivers/scsi/sata_sil.c	2004-08-14 12:38:51 -07:00
+++ b/drivers/scsi/sata_sil.c	2004-09-13 19:35:23 -07:00
@@ -108,7 +108,7 @@
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
-	.ioctl                  = ata_scsi_ioctl,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -126,14 +126,14 @@
 static struct ata_port_operations sil_ops = {
 	.port_disable		= ata_port_disable,
 	.dev_config		= sil_dev_config,
-	.tf_load		= ata_tf_load_mmio,
-	.tf_read		= ata_tf_read_mmio,
-	.check_status		= ata_check_status_mmio,
-	.exec_command		= ata_exec_command_mmio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
 	.phy_reset		= sata_phy_reset,
 	.post_set_mode		= sil_post_set_mode,
-	.bmdma_setup            = ata_bmdma_setup_mmio,
-	.bmdma_start            = ata_bmdma_start_mmio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
diff -Nru a/drivers/scsi/sata_sis.c b/drivers/scsi/sata_sis.c
--- a/drivers/scsi/sata_sis.c	2004-08-14 12:38:51 -07:00
+++ b/drivers/scsi/sata_sis.c	2004-09-13 20:31:19 -07:00
@@ -78,7 +78,7 @@
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
-	.ioctl                  = ata_scsi_ioctl,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -95,13 +95,13 @@
 
 static struct ata_port_operations sis_ops = {
 	.port_disable		= ata_port_disable,
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup            = ata_bmdma_setup_pio,
-	.bmdma_start            = ata_bmdma_start_pio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -113,6 +113,16 @@
 	.port_stop		= ata_port_stop,
 };
 
+static struct ata_port_info sis_port_info = {
+	.sht		= &sis_sht,
+	.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
+			  ATA_FLAG_NO_LEGACY,
+	.pio_mask	= 0x1f,
+	.mwdma_mask	= 0x7,
+	.udma_mask	= 0x7f,
+	.port_ops	= &sis_ops,
+};
+
 
 MODULE_AUTHOR("Uwe Koziolek");
 MODULE_DESCRIPTION("low-level driver for Silicon Integratad Systems SATA controller");
@@ -186,6 +196,7 @@
 	struct ata_probe_ent *probe_ent = NULL;
 	int rc;
 	u32 genctl;
+	struct ata_port_info *ppi;
 
 	rc = pci_enable_device(pdev);
 	if (rc)
@@ -199,20 +210,13 @@
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	ppi = &sis_port_info;
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
 	if (!probe_ent) {
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
 
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	probe_ent->pdev = pdev;
-	INIT_LIST_HEAD(&probe_ent->node);
-
-	probe_ent->sht = &sis_sht;
-	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
-				ATA_FLAG_NO_LEGACY;
-
 	/* check and see if the SCRs are in IO space or PCI cfg space */
 	pci_read_config_dword(pdev, SIS_GENCTL, &genctl);
 	if ((genctl & GENCTL_IOMAPPED_SCR) == 0)
@@ -229,32 +233,12 @@
 		probe_ent->host_flags |= SIS_FLAG_CFGSCR;
 	}
 
-	probe_ent->pio_mask = 0x1f;
-	probe_ent->mwdma_mask = 0x7;
-	probe_ent->udma_mask = 0x7f;
-	probe_ent->port_ops = &sis_ops;
-
-	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-	ata_std_ports(&probe_ent->port[0]);
-	probe_ent->port[0].ctl_addr =
-		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
-	if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
+	if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR)) {
 		probe_ent->port[0].scr_addr =
 			pci_resource_start(pdev, SIS_SCR_PCI_BAR);
-
-	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-	ata_std_ports(&probe_ent->port[1]);
-	probe_ent->port[1].ctl_addr =
-		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
-	if (!(probe_ent->host_flags & SIS_FLAG_CFGSCR))
 		probe_ent->port[1].scr_addr =
 			pci_resource_start(pdev, SIS_SCR_PCI_BAR) + 64;
-
-	probe_ent->n_ports = 2;
-	probe_ent->irq = pdev->irq;
-	probe_ent->irq_flags = SA_SHIRQ;
+	}
 
 	pci_set_master(pdev);
 	pci_enable_intx(pdev);
diff -Nru a/drivers/scsi/sata_svw.c b/drivers/scsi/sata_svw.c
--- a/drivers/scsi/sata_svw.c	2004-08-14 12:38:51 -07:00
+++ b/drivers/scsi/sata_svw.c	2004-09-14 19:40:18 -07:00
@@ -148,7 +148,73 @@
         }
 }
 
+/**
+ *	k2_bmdma_setup_mmio - Set up PCI IDE BMDMA transaction (MMIO)
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void k2_bmdma_setup_mmio (struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE);
+	u8 dmactl;
+	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	/* load PRD table addr. */
+	mb();	/* make sure PRD table writes are visible to controller */
+	writel(ap->prd_dma, mmio + ATA_DMA_TABLE_OFS);
+
+	/* specify data direction, triple-check start bit is clear */
+	dmactl = readb(mmio + ATA_DMA_CMD);
+	dmactl &= ~(ATA_DMA_WR | ATA_DMA_START);
+	if (!rw)
+		dmactl |= ATA_DMA_WR;
+	writeb(dmactl, mmio + ATA_DMA_CMD);
+
+	/* issue r/w command if this is not a ATA DMA command*/
+	if (qc->tf.protocol != ATA_PROT_DMA)
+		ap->ops->exec_command(ap, &qc->tf);
+}
+
+/**
+ *	k2_bmdma_start_mmio - Start a PCI IDE BMDMA transaction (MMIO)
+ *	@qc: Info associated with this ATA transaction.
+ *
+ *	LOCKING:
+ *	spin_lock_irqsave(host_set lock)
+ */
+
+void k2_bmdma_start_mmio (struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	void *mmio = (void *) ap->ioaddr.bmdma_addr;
+	u8 dmactl;
+
+	/* start host DMA transaction */
+	dmactl = readb(mmio + ATA_DMA_CMD);
+	writeb(dmactl | ATA_DMA_START, mmio + ATA_DMA_CMD);
+	/* There is a race condition in certain SATA controllers that can 
+	   be seen when the r/w command is given to the controller before the 
+	   host DMA is started. On a Read command, the controller would initiate
+	   the command to the drive even before it sees the DMA start. When there
+	   are very fast drives connected to the controller, or when the data request 
+	   hits in the drive cache, there is the possibility that the drive returns a part
+	   or all of the requested data to the controller before the DMA start is issued.
+	   In this case, the controller would become confused as to what to do with the data.
+	   In the worst case when all the data is returned back to the controller, the
+	   controller could hang. In other cases it could return partial data returning
+	   in data corruption. This problem has been seen in PPC systems and can also appear
+	   on an system with very fast disks, where the SATA controller is sitting behind a 
+	   number of bridges, and hence there is significant latency between the r/w command
+	   and the start command. */
+	/* issue r/w command if the access is to ATA*/
+	if (qc->tf.protocol == ATA_PROT_DMA)
+		ap->ops->exec_command(ap, &qc->tf);
+}
 
+									      
 static u8 k2_stat_check_status(struct ata_port *ap)
 {
        	return readl((void *) ap->ioaddr.status_addr);
@@ -207,7 +273,7 @@
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
-	.ioctl                  = ata_scsi_ioctl,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -231,10 +297,10 @@
 	.tf_load		= k2_sata_tf_load,
 	.tf_read		= k2_sata_tf_read,
 	.check_status		= k2_stat_check_status,
-	.exec_command		= ata_exec_command_mmio,
+	.exec_command		= ata_exec_command,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup            = ata_bmdma_setup_mmio,
-	.bmdma_start            = ata_bmdma_start_mmio,
+	.bmdma_setup		= k2_bmdma_setup_mmio,
+	.bmdma_start		= k2_bmdma_start_mmio,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
@@ -369,6 +435,8 @@
 
 static struct pci_device_id k2_sata_pci_tbl[] = {
 	{ 0x1166, 0x0240, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0x1166, 0x0241, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	{ 0x1166, 0x0242, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ }
 };
 
diff -Nru a/drivers/scsi/sata_sx4.c b/drivers/scsi/sata_sx4.c
--- a/drivers/scsi/sata_sx4.c	2004-08-14 12:38:51 -07:00
+++ b/drivers/scsi/sata_sx4.c	2004-09-13 19:35:23 -07:00
@@ -176,7 +176,7 @@
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
-	.ioctl                  = ata_scsi_ioctl,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -194,8 +194,8 @@
 static struct ata_port_operations pdc_20621_ops = {
 	.port_disable		= ata_port_disable,
 	.tf_load		= pdc_tf_load_mmio,
-	.tf_read		= ata_tf_read_mmio,
-	.check_status		= ata_check_status_mmio,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
 	.exec_command		= pdc_exec_command_mmio,
 	.phy_reset		= pdc_20621_phy_reset,
 	.qc_prep		= pdc20621_qc_prep,
@@ -888,7 +888,7 @@
 {
 	WARN_ON (tf->protocol == ATA_PROT_DMA ||
 		 tf->protocol == ATA_PROT_NODATA);
-	ata_tf_load_mmio(ap, tf);
+	ata_tf_load(ap, tf);
 }
 
 
@@ -896,7 +896,7 @@
 {
 	WARN_ON (tf->protocol == ATA_PROT_DMA ||
 		 tf->protocol == ATA_PROT_NODATA);
-	ata_exec_command_mmio(ap, tf);
+	ata_exec_command(ap, tf);
 }
 
 
diff -Nru a/drivers/scsi/sata_via.c b/drivers/scsi/sata_via.c
--- a/drivers/scsi/sata_via.c	2004-08-14 12:38:51 -07:00
+++ b/drivers/scsi/sata_via.c	2004-09-13 20:31:19 -07:00
@@ -83,7 +83,7 @@
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
-	.ioctl                  = ata_scsi_ioctl,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -101,15 +101,15 @@
 static struct ata_port_operations svia_sata_ops = {
 	.port_disable		= ata_port_disable,
 
-	.tf_load		= ata_tf_load_pio,
-	.tf_read		= ata_tf_read_pio,
-	.check_status		= ata_check_status_pio,
-	.exec_command		= ata_exec_command_pio,
+	.tf_load		= ata_tf_load,
+	.tf_read		= ata_tf_read,
+	.check_status		= ata_check_status,
+	.exec_command		= ata_exec_command,
 
 	.phy_reset		= sata_phy_reset,
 
-	.bmdma_setup            = ata_bmdma_setup_pio,
-	.bmdma_start            = ata_bmdma_start_pio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 
@@ -125,6 +125,15 @@
 	.port_stop		= ata_port_stop,
 };
 
+static struct ata_port_info svia_port_info = {
+	.sht		= &svia_sht,
+	.host_flags	= ATA_FLAG_SATA | ATA_FLAG_SRST | ATA_FLAG_NO_LEGACY,
+	.pio_mask	= 0x1f,
+	.mwdma_mask	= 0x07,
+	.udma_mask	= 0x7f,
+	.port_ops	= &svia_sata_ops,
+};
+
 MODULE_AUTHOR("Jeff Garzik");
 MODULE_DESCRIPTION("SCSI low-level driver for VIA SATA controllers");
 MODULE_LICENSE("GPL");
@@ -158,6 +167,7 @@
 	static int printed_version;
 	unsigned int i;
 	int rc;
+	struct ata_port_info *ppi;
 	struct ata_probe_ent *probe_ent;
 	u8 tmp8;
 
@@ -195,42 +205,17 @@
 	if (rc)
 		goto err_out_regions;
 
-	probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
+	ppi = &svia_port_info;
+	probe_ent = ata_pci_init_native_mode(pdev, &ppi);
 	if (!probe_ent) {
 		printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
 		       pci_name(pdev));
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
-	memset(probe_ent, 0, sizeof(*probe_ent));
-	INIT_LIST_HEAD(&probe_ent->node);
-	probe_ent->pdev = pdev;
-	probe_ent->sht = &svia_sht;
-	probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SRST |
-				ATA_FLAG_NO_LEGACY;
-	probe_ent->port_ops = &svia_sata_ops;
-	probe_ent->n_ports = 2;
-	probe_ent->irq = pdev->irq;
-	probe_ent->irq_flags = SA_SHIRQ;
-	probe_ent->pio_mask = 0x1f;
-	probe_ent->mwdma_mask = 0x07;
-	probe_ent->udma_mask = 0x7f;
-
-	probe_ent->port[0].cmd_addr = pci_resource_start(pdev, 0);
-	ata_std_ports(&probe_ent->port[0]);
-	probe_ent->port[0].altstatus_addr =
-	probe_ent->port[0].ctl_addr =
-		pci_resource_start(pdev, 1) | ATA_PCI_CTL_OFS;
-	probe_ent->port[0].bmdma_addr = pci_resource_start(pdev, 4);
+
 	probe_ent->port[0].scr_addr =
 		svia_scr_addr(pci_resource_start(pdev, 5), 0);
-
-	probe_ent->port[1].cmd_addr = pci_resource_start(pdev, 2);
-	ata_std_ports(&probe_ent->port[1]);
-	probe_ent->port[1].altstatus_addr =
-	probe_ent->port[1].ctl_addr =
-		pci_resource_start(pdev, 3) | ATA_PCI_CTL_OFS;
-	probe_ent->port[1].bmdma_addr = pci_resource_start(pdev, 4) + 8;
 	probe_ent->port[1].scr_addr =
 		svia_scr_addr(pci_resource_start(pdev, 5), 1);
 
diff -Nru a/drivers/scsi/sata_vsc.c b/drivers/scsi/sata_vsc.c
--- a/drivers/scsi/sata_vsc.c	2004-08-14 12:38:51 -07:00
+++ b/drivers/scsi/sata_vsc.c	2004-09-13 19:35:23 -07:00
@@ -192,7 +192,7 @@
 	.name			= DRV_NAME,
 	.detect			= ata_scsi_detect,
 	.release		= ata_scsi_release,
-	.ioctl                  = ata_scsi_ioctl,
+	.ioctl			= ata_scsi_ioctl,
 	.queuecommand		= ata_scsi_queuecmd,
 	.eh_strategy_handler	= ata_scsi_error,
 	.can_queue		= ATA_DEF_QUEUE,
@@ -212,11 +212,11 @@
 	.port_disable		= ata_port_disable,
 	.tf_load		= vsc_sata_tf_load,
 	.tf_read		= vsc_sata_tf_read,
-	.exec_command		= ata_exec_command_mmio,
-	.check_status		= ata_check_status_mmio,
+	.exec_command		= ata_exec_command,
+	.check_status		= ata_check_status,
 	.phy_reset		= sata_phy_reset,
-	.bmdma_setup            = ata_bmdma_setup_mmio,
-	.bmdma_start            = ata_bmdma_start_mmio,
+	.bmdma_setup            = ata_bmdma_setup,
+	.bmdma_start            = ata_bmdma_start,
 	.qc_prep		= ata_qc_prep,
 	.qc_issue		= ata_qc_issue_prot,
 	.eng_timeout		= ata_eng_timeout,
diff -Nru a/drivers/usb/audio.c b/drivers/usb/audio.c
--- a/drivers/usb/audio.c	2004-07-15 04:46:52 -07:00
+++ b/drivers/usb/audio.c	2004-09-12 17:49:35 -07:00
@@ -593,9 +593,10 @@
 	return 0;
 }
 
-static void dmabuf_copyin(struct dmabuf *db, const void *buffer, unsigned int size)
+static void dmabuf_copyin(struct dmabuf *db, const void *_buffer, unsigned int size)
 {
 	unsigned int pgrem, rem;
+	const char *buffer = _buffer;
 
 	db->total_bytes += size;
 	for (;;) {
@@ -609,16 +610,17 @@
 			pgrem = rem;
 		memcpy((db->sgbuf[db->wrptr >> PAGE_SHIFT]) + (db->wrptr & (PAGE_SIZE-1)), buffer, pgrem);
 		size -= pgrem;
-		(char *)buffer += pgrem;
+		buffer += pgrem;
 		db->wrptr += pgrem;
 		if (db->wrptr >= db->dmasize)
 			db->wrptr = 0;
 	}
 }
 
-static void dmabuf_copyout(struct dmabuf *db, void *buffer, unsigned int size)
+static void dmabuf_copyout(struct dmabuf *db, void *_buffer, unsigned int size)
 {
 	unsigned int pgrem, rem;
+	char *buffer = _buffer;
 
 	db->total_bytes += size;
 	for (;;) {
@@ -632,16 +634,17 @@
 			pgrem = rem;
 		memcpy(buffer, (db->sgbuf[db->rdptr >> PAGE_SHIFT]) + (db->rdptr & (PAGE_SIZE-1)), pgrem);
 		size -= pgrem;
-		(char *)buffer += pgrem;
+		buffer += pgrem;
 		db->rdptr += pgrem;
 		if (db->rdptr >= db->dmasize)
 			db->rdptr = 0;
 	}
 }
 
-static int dmabuf_copyin_user(struct dmabuf *db, unsigned int ptr, const void *buffer, unsigned int size)
+static int dmabuf_copyin_user(struct dmabuf *db, unsigned int ptr, const void *_buffer, unsigned int size)
 {
 	unsigned int pgrem, rem;
+	const char *buffer = _buffer;
 
 	if (!db->ready || db->mapped)
 		return -EINVAL;
@@ -657,16 +660,17 @@
 		if (copy_from_user((db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), buffer, pgrem))
 			return -EFAULT;
 		size -= pgrem;
-		(char *)buffer += pgrem;
+		buffer += pgrem;
 		ptr += pgrem;
 		if (ptr >= db->dmasize)
 			ptr = 0;
 	}
 }
 
-static int dmabuf_copyout_user(struct dmabuf *db, unsigned int ptr, void *buffer, unsigned int size)
+static int dmabuf_copyout_user(struct dmabuf *db, unsigned int ptr, void *_buffer, unsigned int size)
 {
 	unsigned int pgrem, rem;
+	char *buffer = _buffer;
 
 	if (!db->ready || db->mapped)
 		return -EINVAL;
@@ -682,7 +686,7 @@
 		if (copy_to_user(buffer, (db->sgbuf[ptr >> PAGE_SHIFT]) + (ptr & (PAGE_SIZE-1)), pgrem))
 			return -EFAULT;
 		size -= pgrem;
-		(char *)buffer += pgrem;
+		buffer += pgrem;
 		ptr += pgrem;
 		if (ptr >= db->dmasize)
 			ptr = 0;
diff -Nru a/drivers/usb/hpusbscsi.c b/drivers/usb/hpusbscsi.c
--- a/drivers/usb/hpusbscsi.c	2003-03-05 05:41:30 -08:00
+++ b/drivers/usb/hpusbscsi.c	2004-09-12 17:23:57 -07:00
@@ -182,7 +182,7 @@
 
 	memcpy (&(new->ctempl), &hpusbscsi_scsi_host_template,
 		sizeof (hpusbscsi_scsi_host_template));
-	(struct hpusbscsi *) new->ctempl.proc_dir = new;
+	new->ctempl.proc_dir = (void *) new;
 	new->ctempl.module = THIS_MODULE;
 
 	if (scsi_register_module (MODULE_SCSI_HA, &(new->ctempl)))
diff -Nru a/drivers/usb/microtek.c b/drivers/usb/microtek.c
--- a/drivers/usb/microtek.c	2002-08-20 14:53:02 -07:00
+++ b/drivers/usb/microtek.c	2004-09-12 17:23:58 -07:00
@@ -987,7 +987,7 @@
 	/* Initialize the host template based on the default one */
 	memcpy(&(new_desc->ctempl), &mts_scsi_host_template, sizeof(mts_scsi_host_template));
 	/* HACK from usb-storage - this is needed for scsi detection */
-	(struct mts_desc *)new_desc->ctempl.proc_dir = new_desc; /* FIXME */
+	new_desc->ctempl.proc_dir = (void *)new_desc; /* FIXME */
 
 	MTS_DEBUG("registering SCSI module\n");
 
diff -Nru a/drivers/usb/uss720.c b/drivers/usb/uss720.c
--- a/drivers/usb/uss720.c	2002-02-04 23:52:52 -08:00
+++ b/drivers/usb/uss720.c	2004-09-12 20:48:13 -07:00
@@ -327,13 +327,14 @@
 {
 	struct parport_uss720_private *priv = pp->private_data;	
 	size_t got = 0;
+	char *buff = buf;
 
 	if (change_mode(pp, ECR_EPP))
 		return 0;
 	for (; got < length; got++) {
-		if (get_1284_register(pp, 4, (char *)buf))
+		if (get_1284_register(pp, 4, buff))
 			break;
-		((char*)buf)++;
+		buff++;
 		if (priv->reg[0] & 0x01) {
 			clear_epp_timeout(pp);
 			break;
@@ -348,13 +349,14 @@
 #if 0
 	struct parport_uss720_private *priv = pp->private_data;	
 	size_t written = 0;
+	const char *buff = buf;
 
 	if (change_mode(pp, ECR_EPP))
 		return 0;
 	for (; written < length; written++) {
-		if (set_1284_register(pp, 4, (char *)buf))
+		if (set_1284_register(pp, 4, *buff))
 			break;
-		((char*)buf)++;
+		buff++;
 		if (get_1284_register(pp, 1, NULL))
 			break;
 		if (priv->reg[0] & 0x01) {
@@ -386,13 +388,14 @@
 {
 	struct parport_uss720_private *priv = pp->private_data;	
 	size_t got = 0;
+	char *buff = buf;
 
 	if (change_mode(pp, ECR_EPP))
 		return 0;
 	for (; got < length; got++) {
-		if (get_1284_register(pp, 3, (char *)buf))
+		if (get_1284_register(pp, 3, buff))
 			break;
-		((char*)buf)++;
+		buff++;
 		if (priv->reg[0] & 0x01) {
 			clear_epp_timeout(pp);
 			break;
@@ -406,13 +409,14 @@
 {
 	struct parport_uss720_private *priv = pp->private_data;	
 	size_t written = 0;
+	const char *buff = buf;
 
 	if (change_mode(pp, ECR_EPP))
 		return 0;
 	for (; written < length; written++) {
-		if (set_1284_register(pp, 3, *(char *)buf))
+		if (set_1284_register(pp, 3, *buff))
 			break;
-		((char*)buf)++;
+		buff++;
 		if (get_1284_register(pp, 1, NULL))
 			break;
 		if (priv->reg[0] & 0x01) {
@@ -463,13 +467,14 @@
 static size_t parport_uss720_ecp_write_addr(struct parport *pp, const void *buffer, size_t len, int flags)
 {
 	size_t written = 0;
+	const char *buff = buffer;
 
 	if (change_mode(pp, ECR_ECP))
 		return 0;
 	for (; written < len; written++) {
-		if (set_1284_register(pp, 5, *(char *)buffer))
+		if (set_1284_register(pp, 5, *buff))
 			break;
-		((char*)buffer)++;
+		buff++;
 	}
 	change_mode(pp, ECR_PS2);
 	return written;
diff -Nru a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h
--- a/drivers/video/matrox/matroxfb_base.h	2003-07-29 13:57:01 -07:00
+++ b/drivers/video/matrox/matroxfb_base.h	2004-09-12 12:32:52 -07:00
@@ -253,21 +253,21 @@
 #ifdef MEMCPYTOIO_WORKS
 	memcpy_toio(va.vaddr + offs, src, len);
 #elif defined(MEMCPYTOIO_WRITEL)
-#define srcd ((const u_int32_t*)src)
 	if (offs & 3) {
 		while (len >= 4) {
-			mga_writel(va, offs, get_unaligned(srcd++));
+			mga_writel(va, offs, get_unaligned((u32 *)src));
 			offs += 4;
 			len -= 4;
+			src += 4;
 		}
 	} else {
 		while (len >= 4) {
-			mga_writel(va, offs, *srcd++);
+			mga_writel(va, offs, *(u32 *)src);
 			offs += 4;
 			len -= 4;
+			src += 4;
 		}
 	}
-#undef srcd
 	if (len) {
 		u_int32_t tmp;
 
diff -Nru a/drivers/video/radeonfb.c b/drivers/video/radeonfb.c
--- a/drivers/video/radeonfb.c	2004-02-26 05:04:20 -08:00
+++ b/drivers/video/radeonfb.c	2004-04-16 21:24:02 -07:00
@@ -935,6 +935,7 @@
 #endif /* CONFIG_PMAC_BACKLIGHT */
 
 static struct fb_ops radeon_fb_ops = {
+	owner:			THIS_MODULE,
 	fb_get_fix:		radeonfb_get_fix,
 	fb_get_var:		radeonfb_get_var,
 	fb_set_var:		radeonfb_set_var,
@@ -2368,7 +2369,7 @@
 			disp->visual = FB_VISUAL_DIRECTCOLOR;
 			v.red.offset = 10;
 			v.green.offset = 5;
-			v.red.offset = 0;
+			v.blue.offset = 0;
 			v.red.length = v.green.length = v.blue.length = 5;
 			v.transp.offset = v.transp.length = 0;
 			break;
diff -Nru a/drivers/video/riva/accel.c b/drivers/video/riva/accel.c
--- a/drivers/video/riva/accel.c	2002-11-28 04:08:49 -08:00
+++ b/drivers/video/riva/accel.c	2004-09-11 16:56:20 -07:00
@@ -153,8 +153,10 @@
 		for (j = 0; j < cnt; j++) {
 			if (w <= 8) 
 				cdat2 = *cdat++;
-			else
-				cdat2 = *((u16*)cdat)++;
+			else {
+				cdat2 = *(u16*)cdat;
+				cdat += sizeof(u16);
+			}
 			fbcon_reverse_order(&cdat2);
 			d[j] = cdat2;
 		}
diff -Nru a/fs/dcache.c b/fs/dcache.c
--- a/fs/dcache.c	2003-07-08 12:31:53 -07:00
+++ b/fs/dcache.c	2004-09-09 10:37:56 -07:00
@@ -55,7 +55,10 @@
 /* Statistics gathering. */
 struct dentry_stat_t dentry_stat = {0, 0, 45, 0,};
 
-/* no dcache_lock, please */
+/*
+ * no dcache_lock, please.  The caller must decrement dentry_stat.nr_dentry
+ * inside dcache_lock.
+ */
 static inline void d_free(struct dentry *dentry)
 {
 	if (dentry->d_op && dentry->d_op->d_release)
@@ -63,7 +66,6 @@
 	if (dname_external(dentry)) 
 		kfree(dentry->d_name.name);
 	kmem_cache_free(dentry_cache, dentry); 
-	dentry_stat.nr_dentry--;
 }
 
 /*
@@ -148,6 +150,7 @@
 kill_it: {
 		struct dentry *parent;
 		list_del(&dentry->d_child);
+		dentry_stat.nr_dentry--;	/* For d_free, below */
 		/* drops the lock, at that point nobody can reach this dentry */
 		dentry_iput(dentry);
 		parent = dentry->d_parent;
@@ -297,6 +300,7 @@
 
 	list_del_init(&dentry->d_hash);
 	list_del(&dentry->d_child);
+	dentry_stat.nr_dentry--;	/* For d_free, below */
 	dentry_iput(dentry);
 	parent = dentry->d_parent;
 	d_free(dentry);
@@ -623,13 +627,15 @@
 	if (parent) {
 		dentry->d_parent = dget(parent);
 		dentry->d_sb = parent->d_sb;
-		spin_lock(&dcache_lock);
-		list_add(&dentry->d_child, &parent->d_subdirs);
-		spin_unlock(&dcache_lock);
 	} else
 		INIT_LIST_HEAD(&dentry->d_child);
 
+	spin_lock(&dcache_lock);
+	if (parent)
+		list_add(&dentry->d_child, &parent->d_subdirs);
 	dentry_stat.nr_dentry++;
+	spin_unlock(&dcache_lock);
+
 	return dentry;
 }
 
diff -Nru a/include/linux/compiler.h b/include/linux/compiler.h
--- a/include/linux/compiler.h	2004-05-10 23:26:46 -07:00
+++ b/include/linux/compiler.h	2004-09-13 18:47:33 -07:00
@@ -37,5 +37,6 @@
 
 /* no checker support, so we unconditionally define this as (null) */
 #define __user
+#define __iomem
 
 #endif /* __LINUX_COMPILER_H */
diff -Nru a/include/linux/libata.h b/include/linux/libata.h
--- a/include/linux/libata.h	2004-08-31 00:01:32 -07:00
+++ b/include/linux/libata.h	2004-09-13 20:31:19 -07:00
@@ -197,7 +197,7 @@
 	unsigned long		irq;
 	unsigned int		irq_flags;
 	unsigned long		host_flags;
-	void			*mmio_base;
+	void __iomem		*mmio_base;
 	void			*private_data;
 };
 
@@ -205,7 +205,7 @@
 	spinlock_t		lock;
 	struct pci_dev		*pdev;
 	unsigned long		irq;
-	void			*mmio_base;
+	void __iomem		*mmio_base;
 	unsigned int		n_ports;
 	void			*private_data;
 	struct ata_port_operations *ops;
@@ -380,19 +380,19 @@
 /*
  * Default driver ops implementations
  */
-extern void ata_tf_load_pio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_load_mmio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_tf_load(struct ata_port *ap, struct ata_taskfile *tf);
+extern void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf);
 extern void ata_tf_to_fis(struct ata_taskfile *tf, u8 *fis, u8 pmp);
 extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf);
-extern u8 ata_check_status_pio(struct ata_port *ap);
-extern u8 ata_check_status_mmio(struct ata_port *ap);
-extern void ata_exec_command_pio(struct ata_port *ap, struct ata_taskfile *tf);
-extern void ata_exec_command_mmio(struct ata_port *ap, struct ata_taskfile *tf);
+extern u8 ata_check_status(struct ata_port *ap);
+extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
 extern int ata_port_start (struct ata_port *ap);
 extern void ata_port_stop (struct ata_port *ap);
 extern irqreturn_t ata_interrupt (int irq, void *dev_instance, struct pt_regs *regs);
+extern struct ata_probe_ent *
+ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port);
+extern struct ata_probe_ent *
+ata_pci_init_legacy_mode(struct pci_dev *pdev, struct ata_port_info **port);
 extern void ata_qc_prep(struct ata_queued_cmd *qc);
 extern int ata_qc_issue_prot(struct ata_queued_cmd *qc);
 extern void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf,
@@ -401,10 +401,8 @@
 		 unsigned int n_elem);
 extern void ata_dev_id_string(struct ata_device *dev, unsigned char *s,
 			      unsigned int ofs, unsigned int len);
-extern void ata_bmdma_setup_mmio (struct ata_queued_cmd *qc);
-extern void ata_bmdma_start_mmio (struct ata_queued_cmd *qc);
-extern void ata_bmdma_setup_pio (struct ata_queued_cmd *qc);
-extern void ata_bmdma_start_pio (struct ata_queued_cmd *qc);
+extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
+extern void ata_bmdma_start (struct ata_queued_cmd *qc);
 extern void ata_bmdma_irq_clear(struct ata_port *ap);
 extern int pci_test_config_bits(struct pci_dev *pdev, struct pci_bits *bits);
 extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
@@ -433,7 +431,7 @@
 static inline u8 ata_chk_err(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO) {
-		return readb((void *) ap->ioaddr.error_addr);
+		return readb((void __iomem *) ap->ioaddr.error_addr);
 	}
 	return inb(ap->ioaddr.error_addr);
 }
@@ -446,7 +444,7 @@
 static inline u8 ata_altstatus(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO)
-		return readb(ap->ioaddr.altstatus_addr);
+		return readb((void __iomem *)ap->ioaddr.altstatus_addr);
 	return inb(ap->ioaddr.altstatus_addr);
 }
 
@@ -517,7 +515,7 @@
 	ap->last_ctl = ap->ctl;
 
 	if (ap->flags & ATA_FLAG_MMIO)
-		writeb(ap->ctl, ioaddr->ctl_addr);
+		writeb(ap->ctl, (void __iomem *) ioaddr->ctl_addr);
 	else
 		outb(ap->ctl, ioaddr->ctl_addr);
 	tmp = ata_wait_idle(ap);
@@ -538,7 +536,7 @@
 
 	/* get controller status; clear intr, err bits */
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 		host_stat = readb(mmio + ATA_DMA_STATUS);
 		writeb(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
 		       mmio + ATA_DMA_STATUS);
@@ -576,7 +574,7 @@
 static inline void ata_bmdma_stop(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 
 		/* clear start/stop bit */
 		writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
@@ -594,7 +592,7 @@
 static inline void ata_bmdma_ack_irq(struct ata_port *ap)
 {
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = ((void *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
+		void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
 		writeb(readb(mmio), mmio);
 	} else {
 		unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
@@ -606,7 +604,7 @@
 {
 	u8 host_stat;
 	if (ap->flags & ATA_FLAG_MMIO) {
-		void *mmio = (void *) ap->ioaddr.bmdma_addr;
+		void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
 		host_stat = readb(mmio + ATA_DMA_STATUS);
 	} else
 		host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
diff -Nru a/include/linux/string.h b/include/linux/string.h
--- a/include/linux/string.h	2002-02-04 23:39:41 -08:00
+++ b/include/linux/string.h	2004-09-17 16:19:23 -07:00
@@ -7,6 +7,7 @@
 
 #include <linux/types.h>	/* for size_t */
 #include <linux/stddef.h>	/* for NULL */
+#include <linux/compiler.h>	/* for inline ((always_inline)) */
 
 #ifdef __cplusplus
 extern "C" {
diff -Nru a/include/pcmcia/mem_op.h b/include/pcmcia/mem_op.h
--- a/include/pcmcia/mem_op.h	2002-02-04 23:37:44 -08:00
+++ b/include/pcmcia/mem_op.h	2004-09-11 16:56:20 -07:00
@@ -81,7 +81,9 @@
     n -= odd;
     while (n) {
 	*(u_short *)to = __raw_readw(from);
-	(char *)to += 2; (char *)from += 2; n -= 2;
+	to = (void *)((long)to + 2);
+	from = (const void *)((long)from + 2);
+	n -= 2;
     }
     if (odd)
 	*(u_char *)to = readb(from);
@@ -93,7 +95,9 @@
     n -= odd;
     while (n) {
 	__raw_writew(*(u_short *)from, to);
-	(char *)to += 2; (char *)from += 2; n -= 2;
+	to = (void *)((long)to + 2);
+	from = (const void *)((long)from + 2);
+	n -= 2;
     }
     if (odd)
 	writeb(*(u_char *)from, to);
@@ -105,7 +109,9 @@
     n -= odd;
     while (n) {
 	put_user(__raw_readw(from), (short *)to);
-	(char *)to += 2; (char *)from += 2; n -= 2;
+	to = (void *)((long)to + 2);
+	from = (const void *)((long)from + 2);
+	n -= 2;
     }
     if (odd)
 	put_user(readb(from), (char *)to);
@@ -120,7 +126,9 @@
     while (n) {
 	get_user(s, (short *)from);
 	__raw_writew(s, to);
-	(char *)to += 2; (char *)from += 2; n -= 2;
+	to = (void *)((long)to + 2);
+	from = (const void *)((long)from + 2);
+	n -= 2;
     }
     if (odd) {
 	get_user(c, (char *)from);
