patch-2.2.19 linux/drivers/scsi/tmscsim.c

Next file: linux/drivers/scsi/tmscsim.h
Previous file: linux/drivers/scsi/st.c
Back to the patch index
Back to the overall index

diff -u --new-file --recursive --exclude-from /usr/src/exclude v2.2.18/drivers/scsi/tmscsim.c linux/drivers/scsi/tmscsim.c
@@ -5,11 +5,11 @@
  *		     Bus Master Host Adapter			       *
  * (C)Copyright 1995-1996 Tekram Technology Co., Ltd.		       *
  ***********************************************************************/
-/* (C) Copyright: put under GNU GPL in 10/96				*
+/* (C) Copyright: put under GNU GPL in 10/96  (see README.tmscsim)	*
 *************************************************************************/
-/* $Id: tmscsim.c,v 2.16 1998/12/25 17:54:44 garloff Exp $		*/
+/* $Id: tmscsim.c,v 2.60.2.30 2000/12/20 01:07:12 garloff Exp $		*/
 /*	Enhancements and bugfixes by					*
- *	Kurt Garloff <kurt@garloff.de>					*
+ *	Kurt Garloff <kurt@garloff.de>	<garloff@suse.de>		*
  ***********************************************************************/
 /*	HISTORY:							*
  *									*
@@ -95,8 +95,75 @@
  *	2.0c  98/11/19	KG	Cleaned up detect/init for SMP boxes, 	*
  *				Write Erase DMA (1.20t) caused problems	*
  *	2.0d  98/12/25	KG	Christmas release ;-) Message handling  *
- *				competely reworked. Handle target ini-	*
+ *				completely reworked. Handle target ini-	*
  *				tiated SDTR correctly.			*
+ *	2.0d1 99/01/25	KG	Try to handle RESTORE_PTR		*
+ *	2.0d2 99/02/08	KG	Check for failure of kmalloc, correct 	*
+ *				inclusion of scsicam.h, DelayReset	*
+ *	2.0d3 99/05/31	KG	DRIVER_OK -> DID_OK, DID_NO_CONNECT,	*
+ *				detect Target mode and warn.		*
+ *				pcmd->result handling cleaned up.	*
+ *	2.0d4 99/06/01	KG	Cleaned selection process. Found bug	*
+ *				which prevented more than 16 tags. Now:	*
+ *				24. SDTR cleanup. Cleaner multi-LUN	*
+ *				handling. Don't modify ControlRegs/FIFO	*
+ *				when connected.				*
+ *	2.0d5 99/06/01	KG	Clear DevID, Fix INQUIRY after cfg chg.	*
+ *	2.0d6 99/06/02	KG	Added ADD special command to allow cfg.	*
+ *				before detection. Reset SYNC_NEGO_DONE	*
+ *				after a bus reset.			*
+ *	2.0d7 99/06/03	KG	Fixed bugs wrt add,remove commands	*
+ *	2.0d8 99/06/04	KG	Removed copying of cmnd into CmdBlock.	*
+ *				Fixed Oops in _release().		*
+ *	2.0d9 99/06/06	KG	Also tag queue INQUIRY, T_U_R, ...	*
+ *				Allow arb. no. of Tagged Cmnds. Max 32	*
+ *	2.0d1099/06/20	KG	TagMaxNo changes now honoured! Queueing *
+ *				clearified (renamed ..) TagMask handling*
+ *				cleaned.				*
+ *	2.0d1199/06/28	KG	cmd->result now identical to 2.0d2	*
+ *	2.0d1299/07/04	KG	Changed order of processing in IRQ	*
+ *	2.0d1399/07/05	KG	Don't update DCB fields if removed	*
+ *	2.0d1499/07/05	KG	remove_dev: Move kfree() to the end	*
+ *	2.0d1599/07/12	KG	use_new_eh_code: 0, ULONG -> UINT where	*
+ *				appropriate				*
+ *	2.0d1699/07/13	KG	Reenable StartSCSI interrupt, Retry msg	*
+ *	2.0d1799/07/15	KG	Remove debug msg. Disable recfg. when	*
+ *				there are queued cmnds			*
+ *	2.0d1899/07/18	KG	Selection timeout: Don't requeue	*
+ *	2.0d1999/07/18	KG	Abort: Only call scsi_done if dequeued	*
+ *	2.0d2099/07/19	KG	Rst_Detect: DoingSRB_Done		*
+ *	2.0d2199/08/15	KG	dev_id for request/free_irq, cmnd[0] for*
+ *				RETRY, SRBdone does DID_ABORT for the 	*
+ *				cmd passed by DC390_reset()		*
+ *	2.0d2299/08/25	KG	dev_id fixed. can_queue: 42		*
+ *	2.0d2399/08/25	KG	Removed some debugging code. dev_id 	*
+ *				now is set to pACB. Use u8,u16,u32. 	*
+ *	2.0d2499/11/14	KG	Unreg. I/O if failed IRQ alloc. Call	*
+ * 				done () w/ DID_BAD_TARGET in case of	*
+ *				missing DCB. We	are old EH!!		*
+ *	2.0d2500/01/15	KG	2.3.3x compat from Andreas Schultz	*
+ *				set unique_id. Disable RETRY message.	*
+ *	2.0d2600/01/29	KG	Go to new EH.				*
+ *	2.0d2700/01/31	KG	... but maintain 2.0 compat.		*
+ *				and fix DCB freeing			*
+ *	2.0d2800/02/14	KG	Queue statistics fixed, dump special cmd*
+ *				Waiting_Timer for failed StartSCSI	*
+ *				New EH: Don't return cmnds to ML on RST *
+ *				Use old EH (don't have new EH fns yet)	*
+ * 				Reset: Unlock, but refuse to queue	*
+ * 				2.3 __setup function			*
+ *	2.0e  00/05/22	KG	Return residual for 2.3			*
+ *	2.0e1 00/05/25	KG	Compile fixes for 2.3.99		*
+ *	2.0e2 00/05/27	KG	Jeff Garzik's pci_enable_device()	*
+ *	2.0e3 00/09/29	KG	Some 2.4 changes. Don't try Sync Nego	*
+ *				before INQUIRY has reported ability. 	*
+ *				Recognise INQUIRY as scanning command.	*
+ *	2.0e4 00/10/13	KG	Allow compilation into 2.4 kernel	*
+ *	2.0e5 00/11/17	KG	Store Inq.flags in DCB			*
+ *	2.0e6 00/11/22  KG	2.4 init function (Thx to O.Schumann)	*
+ * 				2.4 PCI device table (Thx to A.Richter)	*
+ *	2.0e7 00/11/28	KG	Allow overriding of BIOS settings	*
+ *	2.0f  00/12/20	KG	Handle failed INQUIRYs during scan	*
  ***********************************************************************/
 
 /* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */
@@ -108,6 +175,7 @@
 //#define DC390_DCBDEBUG
 //#define DC390_PARSEDEBUG
 //#define DC390_REMOVABLEDEBUG
+//#define DC390_LOCKDEBUG
 
 /* Debug definitions */
 #ifdef DC390_DEBUG0
@@ -159,6 +227,7 @@
 #include <linux/config.h>
 #include <linux/version.h>
 #include <linux/blk.h>
+#include <linux/timer.h>
 
 #include "scsi.h"
 #include "hosts.h"
@@ -175,8 +244,7 @@
 
 /* Note: Starting from 2.1.9x, the mid-level scsi code issues a 
  * spinlock_irqsave (&io_request_lock) before calling the driver's 
- * routines, so we don't need to lock.
- * TODO: Verify, if we are locked in every case!
+ * routines, so we don't need to lock, except in the IRQ handler.
  * The policy 3, let the midlevel scsi code do the io_request_locks
  * and us locking on a driver specific lock, shouldn't hurt anybody; it
  * just causes a minor performance degradation for setting the locks.
@@ -189,31 +257,46 @@
  * undef  : traditional save_flags; cli; restore_flags;
  */
 
-//#define DEBUG_SPINLOCKS 2	/* Set to 0, 1 or 2 in include/asm/spinlock.h */
+//#define DEBUG_SPINLOCKS 2	/* Set to 0, 1 or 2 in include/linux/spinlock.h */
 
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)
 # include <linux/init.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30)
+# include <linux/spinlock.h>
+#else
 # include <asm/spinlock.h>
 #endif
+#endif
 
 
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93) 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) 
 # define USE_SPINLOCKS 1
 # define NEW_PCI 1
 #else
 # undef NEW_PCI
-# if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)
 #  define USE_SPINLOCKS 2
 # endif
 #endif
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,99)
+static struct pci_device_id tmscsim_pci_tbl[] __initdata = {
+	{
+		vendor: PCI_VENDOR_ID_AMD,
+		device: PCI_DEVICE_ID_AMD53C974,
+		subvendor: PCI_ANY_ID,
+		subdevice: PCI_ANY_ID,
+	},
+	{ }		/* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl);
+#endif
+	
 #ifdef USE_SPINLOCKS
 
 # if USE_SPINLOCKS == 3 /* both */
 
-#  if defined (__SMP__) || DEBUG_SPINLOCKS > 0
+#  if defined (CONFIG_SMP) || DEBUG_SPINLOCKS > 0
 #   define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; };
 #  else
 #   define DC390_LOCKA_INIT
@@ -320,7 +403,11 @@
 # define PCI_PRESENT pci_present ()
 # define PCI_SET_MASTER pci_set_master (pdev)
 # define PCI_FIND_DEVICE(vend, id) (pdev = pci_find_device (vend, id, pdev))
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,10)
+# define PCI_GET_IO_AND_IRQ io_port = pci_resource_start (pdev, 0); irq = pdev->irq
+#else
 # define PCI_GET_IO_AND_IRQ io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; irq = pdev->irq
+#endif
 #else
 # include <linux/bios32.h>
 # define PDEV pbus, pdevfn
@@ -369,7 +456,7 @@
 void dc390_Disconnect( PACB pACB );
 void dc390_Reselect( PACB pACB );
 void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB );
-void dc390_DoingSRB_Done( PACB pACB );
+void dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd );
 static void dc390_ScsiRstDetect( PACB pACB );
 static void dc390_ResetSCSIBus( PACB pACB );
 static void __inline__ dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB );
@@ -379,7 +466,7 @@
 void do_DC390_Interrupt( int, void *, struct pt_regs *);
 
 int    dc390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, UCHAR index );
-void   dc390_initDCB( PACB pACB, PDCB *ppDCB, PSCSICMD cmd );
+void   dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun);
 void   dc390_updateDCB (PACB pACB, PDCB pDCB);
 
 #ifdef MODULE
@@ -393,31 +480,19 @@
 //static PSH	dc390_pSH_current = NULL;
 static PACB	dc390_pACB_start= NULL;
 static PACB	dc390_pACB_current = NULL;
-static UCHAR	dc390_adapterCnt = 0;
-static UCHAR	dc390_CurrSyncOffset = 0;
 static ULONG	dc390_lastabortedpid = 0;
-static ULONG	dc390_laststatus = 0;
+static UINT	dc390_laststatus = 0;
+static UCHAR	dc390_adapterCnt = 0;
 
-#ifndef CONFIG_SCSI_DC390T_NOGENSUPP
 /* Startup values, to be overriden on the commandline */
-int tmscsim[] = {7, 1 /* 8MHz */, 
-		PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_
-		| SYNC_NEGO_ | TAG_QUEUEING_,
-		MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION
-		/* | NO_SEEK */
-# ifdef CONFIG_SCSI_MULTI_LUN
-		| LUN_CHECK
-# endif
-		, 3 /* 16 Tags per LUN */};
+int tmscsim[] = {-2, -2, -2, -2, -2, -2};
 
-# if defined(MODULE) && LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
-MODULE_PARM(tmscsim, "1-5i");
-MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1)");
+# if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)
+MODULE_PARM(tmscsim, "1-6i");
+MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)");
 # endif
 
-#endif /* CONFIG_SCSI_DC390T_NOGENSUPP */
-
-#if defined(MODULE) && LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30)
+#if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)
 MODULE_AUTHOR("C.L. Huang / Kurt Garloff");
 MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");
 MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
@@ -482,12 +557,14 @@
 static char*  dc390_adapname = "DC390";
 UCHAR  dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];
 UCHAR  dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
+UCHAR  dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,30)
 struct proc_dir_entry	DC390_proc_scsi_tmscsim ={
        PROC_SCSI_DC390T, 7 ,"tmscsim",
        S_IFDIR | S_IRUGO | S_IXUGO, 2
        };
-
+#endif
 
 /***********************************************************************
  * Functions for access to DC390 EEPROM
@@ -511,59 +588,107 @@
     udelay(160);
 }
 
-#ifndef CONFIG_SCSI_DC390T_NOGENSUPP
-static void __init dc390_EEpromDefaults (UCHAR index)
+
+/* Override EEprom values with explicitly set values */
+static void __init dc390_EEprom_Override (UCHAR index)
 {
     PUCHAR ptr;
     UCHAR  id;
     ptr = (PUCHAR) dc390_eepromBuf[index];
     
     /* Adapter Settings */
-    ptr[EE_ADAPT_SCSI_ID] = (UCHAR)tmscsim[0]; /* Adapter ID */
-    ptr[EE_MODE2] = (UCHAR)tmscsim[3];
-    ptr[EE_DELAY] = 0; /* ?? */
-    ptr[EE_TAG_CMD_NUM] = (UCHAR)tmscsim[4]; /* Tagged Comds */
+    if (tmscsim[0] != -2)
+	ptr[EE_ADAPT_SCSI_ID] = (UCHAR)tmscsim[0];	/* Adapter ID */
+    if (tmscsim[3] != -2)
+	ptr[EE_MODE2] = (UCHAR)tmscsim[3];
+    if (tmscsim[5] != -2)
+	ptr[EE_DELAY] = tmscsim[5];			/* Reset delay */
+    if (tmscsim[4] != -2)
+	ptr[EE_TAG_CMD_NUM] = (UCHAR)tmscsim[4];	/* Tagged Cmds */
     
     /* Device Settings */
     for (id = 0; id < MAX_SCSI_ID; id++)
     {
-      ptr[id<<2] = (UCHAR)tmscsim[2]; /* EE_MODE1 */
-      ptr[(id<<2) + 1] = (UCHAR)tmscsim[1]; /* EE_Speed */
+	if (tmscsim[2] != -2)
+		ptr[id<<2] = (UCHAR)tmscsim[2];		/* EE_MODE1 */
+	if (tmscsim[1] != -2)
+		ptr[(id<<2) + 1] = (UCHAR)tmscsim[1];	/* EE_Speed */
     };
-    dc390_adapname = "AM53C974";
 }
 
-static void __init dc390_checkparams (void)
+/* Handle "-1" case */
+static void __init dc390_check_for_safe_settings (void)
 {
-	PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x\n", tmscsim[0],\
-		      tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4]);)
-	if (tmscsim[0] < 0 || tmscsim[0] > 7) /* modules-2.0.0 passes -1 as string */
+	if (tmscsim[0] == -1 || tmscsim[0] > 15) /* modules-2.0.0 passes -1 as string */
 	{
-		tmscsim[0] = 7; tmscsim[1] = 4; 
-		tmscsim[2] = 9; tmscsim[3] = 15;
-		tmscsim[4] = 2;
+		tmscsim[0] = 7; tmscsim[1] = 4;
+		tmscsim[2] = 0x09; tmscsim[3] = 0x0f;
+		tmscsim[4] = 2; tmscsim[5] = 10;
 		printk (KERN_INFO "DC390: Using safe settings.\n");
 	}
-	else
+}
+
+
+#ifndef CONFIG_SCSI_DC390T_NOGENSUPP
+int __initdata tmscsim_def[] = {7, 0 /* 10MHz */,
+		PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_
+		| SYNC_NEGO_ | TAG_QUEUEING_,
+		MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION
+		/* | NO_SEEK */
+# ifdef CONFIG_SCSI_MULTI_LUN
+		| LUN_CHECK
+# endif
+		, 3 /* 16 Tags per LUN */, 1 /* s delay after Reset */ };
+
+/* Copy defaults over set values where missing */
+static void __init dc390_fill_with_defaults (void)
+{
+	int i;
+	PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x %08x\n", tmscsim[0],\
+		      tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4], tmscsim[5]);)
+	for (i = 0; i < 6; i++)
 	{
-		/* if (tmscsim[0] < 0 || tmscsim[0] > 7) tmscsim[0] = 7; */
-		if (tmscsim[1] < 0 || tmscsim[1] > 7) tmscsim[1] = 4;
-		if (tmscsim[4] < 0 || tmscsim[4] > 5) tmscsim[4] = 4;
-	};
+		if (tmscsim[i] < 0 || tmscsim[i] > 255)
+			tmscsim[i] = tmscsim_def[i];
+	}
+	/* Sanity checks */
+	if (tmscsim[0] >   7) tmscsim[0] =   7;
+	if (tmscsim[1] >   7) tmscsim[1] =   4;
+	if (tmscsim[4] >   5) tmscsim[4] =   4;
+	if (tmscsim[5] > 180) tmscsim[5] = 180;
 };
+#endif
+
 /* Override defaults on cmdline:
  * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped)
  */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)
+void __init dc390_setup (char *str)
+{	
+	int ints[8];
+	int i, im;
+	(void)get_options (str, ARRAY_SIZE(ints), ints);
+#else
 void __init dc390_setup (char *str, int *ints)
 {
-	int i;
-	for (i = 0; i < ints[0]; i++)
-		tmscsim[i] = ints[i+1];
-	if (ints[0] > 5)
+	int i, im;
+#endif
+	im = ints[0];
+	if (im > 6)
+	{
 		printk (KERN_NOTICE "DC390: ignore extra params!\n");
+		im = 6;
+	};
+	for (i = 0; i < im; i++)
+		tmscsim[i] = ints[i+1];
 	/* dc390_checkparams (); */
 };
-#endif /* CONFIG_SCSI_DC390T_NOGENSUPP */
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)
+#ifndef MODULE
+__setup("tmscsim=", dc390_setup);
+#endif
+#endif
 
 
 static void __init dc390_EEpromOutDI( PDEVDECL, PUCHAR regval, UCHAR Carry )
@@ -652,6 +777,12 @@
 }
 
 
+static void __init dc390_interpret_delay (UCHAR index)
+{
+    char interpd [] = {1,3,5,10,16,30,60,120};
+    dc390_eepromBuf[index][EE_DELAY] = interpd [dc390_eepromBuf[index][EE_DELAY]];
+};
+
 static UCHAR __init dc390_CheckEEpromCheckSum( PDEVDECL, UCHAR index )
 {
     UCHAR  i;
@@ -662,6 +793,8 @@
     memcpy (dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
     memcpy (&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID], 
 	    &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
+    dc390_interpret_delay (index);
+    
     wval = 0;
     for(i=0; i<0x40; i++, ptr++)
 	wval += *ptr;
@@ -674,65 +807,94 @@
  * (DCBs, SRBs, Queueing)
  *
  **********************************************************************/
-static PDCB __inline__ dc390_findDCB ( PACB pACB, Scsi_Cmnd *cmd)
+static PDCB __inline__ dc390_findDCB ( PACB pACB, UCHAR id, UCHAR lun)
 {
    PDCB pDCB = pACB->pLinkDCB; if (!pDCB) return 0;
-   while (pDCB->UnitSCSIID != cmd->target || pDCB->UnitSCSILUN != cmd->lun)
+   while (pDCB->TargetID != id || pDCB->TargetLUN != lun)
      {
 	pDCB = pDCB->pNextDCB;
 	if (pDCB == pACB->pLinkDCB)
 	  {
-	     printk (KERN_WARNING "DC390: DCB not found (DCB=%08x, DCBmap[%2x]=%2x)\n",
-		     (int)pDCB, cmd->target, pACB->DCBmap[cmd->target]);
+	     DCBDEBUG(printk (KERN_WARNING "DC390: DCB not found (DCB=%p, DCBmap[%2x]=%2x)\n",
+		     pDCB, id, pACB->DCBmap[id]);)
 	     return 0;
 	  }
      };
-   DCBDEBUG1( printk (KERN_DEBUG "DCB %08x (%02x,%02x) found.\n",	\
-	   (int)pDCB, pDCB->UnitSCSIID, pDCB->UnitSCSILUN);)
+   DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n",	\
+		      pDCB, pDCB->TargetID, pDCB->TargetLUN);)
    return pDCB;
 };
 
-static void dc390_QLinkcmd( PSCSICMD cmd, PDCB pDCB )
-{
-    PSCSICMD  pcmd;
+/* Queueing philosphy:
+ * There are a couple of lists:
+ * - Query: Contains the Scsi Commands not yet turned into SRBs (per ACB)
+ *   (Note: For new EH, it is unecessary!)
+ * - Waiting: Contains a list of SRBs not yet sent (per DCB)
+ * - Free: List of free SRB slots
+ * 
+ * If there are no waiting commands for the DCB, the new one is sent to the bus
+ * otherwise the oldest one is taken from the Waiting list and the new one is 
+ * queued to the Waiting List
+ * 
+ * Lists are managed using two pointers and eventually a counter
+ */
+
 
-    if( !pDCB->QIORBCnt )
+#if 0
+/* Look for a SCSI cmd in a SRB queue */
+static PSRB dc390_find_cmd_in_SRBq (PSCSICMD cmd, PSRB queue)
+{
+    PSRB q = queue;
+    while (q)
     {
-	pDCB->pQIORBhead = cmd;
-	pDCB->pQIORBtail = cmd;
-	pDCB->QIORBCnt++;
-	cmd->next = NULL;
+	if (q->pcmd == cmd) return q;
+	q = q->pNextSRB;
+	if (q == queue) return 0;
     }
+    return q;
+};
+#endif
+    
+
+/* Append to Query List */
+static void dc390_Query_append( PSCSICMD cmd, PACB pACB )
+{
+    DEBUG0(printk ("DC390: Append cmd %li to Query\n", cmd->pid);)
+    if( !pACB->QueryCnt )
+	pACB->pQueryHead = cmd;
     else
-    {
-	pcmd = pDCB->pQIORBtail;
-	pcmd->next = cmd;
-	pDCB->pQIORBtail = cmd;
-	pDCB->QIORBCnt++;
-	cmd->next = NULL;
-    }
+	pACB->pQueryTail->next = cmd;
 
+    pACB->pQueryTail = cmd;
+    pACB->QueryCnt++;
+    pACB->CmdOutOfSRB++;
+    cmd->next = NULL;
 }
 
 
-static __inline__ PSCSICMD dc390_Getcmd( PDCB pDCB )
+/* Return next cmd from Query list */
+static PSCSICMD dc390_Query_get ( PACB pACB )
 {
     PSCSICMD  pcmd;
 
-    pcmd = pDCB->pQIORBhead;
-    pDCB->pQIORBhead = pcmd->next;
+    pcmd = pACB->pQueryHead;
+    if (!pcmd) return pcmd;
+    DEBUG0(printk ("DC390: Get cmd %li from Query\n", pcmd->pid);)
+    pACB->pQueryHead = pcmd->next;
     pcmd->next = NULL;
-    pDCB->QIORBCnt--;
-
+    if (!pACB->pQueryHead) pACB->pQueryTail = NULL;
+    pACB->QueryCnt--;
     return( pcmd );
 }
 
 
-static __inline__ PSRB dc390_GetSRB( PACB pACB )
+/* Return next free SRB */
+static __inline__ PSRB dc390_Free_get ( PACB pACB )
 {
     PSRB   pSRB;
 
     pSRB = pACB->pFreeSRB;
+    DEBUG0(printk ("DC390: Get Free SRB %p\n", pSRB);)
     if( pSRB )
     {
 	pACB->pFreeSRB = pSRB->pNextSRB;
@@ -742,130 +904,174 @@
     return( pSRB );
 }
 
-
-static __inline__ void dc390_RewaitSRB0( PDCB pDCB, PSRB pSRB )
+/* Insert SRB oin top of free list */
+static __inline__ void dc390_Free_insert (PACB pACB, PSRB pSRB)
 {
-    PSRB   psrb1;
+    DEBUG0(printk ("DC390: Free SRB %p\n", pSRB);)
+    pSRB->pNextSRB = pACB->pFreeSRB;
+    pACB->pFreeSRB = pSRB;
+}
 
-    if( (psrb1 = pDCB->pWaitingSRB) )
-    {
-	pSRB->pNextSRB = psrb1;
-    }
-    else
-    {
-	pSRB->pNextSRB = NULL;
+
+/* Inserts a SRB to the top of the Waiting list */
+static __inline__ void dc390_Waiting_insert ( PDCB pDCB, PSRB pSRB )
+{
+    DEBUG0(printk ("DC390: Insert pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid);)
+    pSRB->pNextSRB = pDCB->pWaitingSRB;
+    if (!pDCB->pWaitingSRB)
 	pDCB->pWaitLast = pSRB;
-    }
     pDCB->pWaitingSRB = pSRB;
+    pDCB->WaitSRBCnt++;
 }
 
 
-static void dc390_RewaitSRB( PDCB pDCB, PSRB pSRB )
+/* Queue SRB to waiting list */
+static __inline__ void dc390_Waiting_append ( PDCB pDCB, PSRB pSRB)
 {
-    PSRB   psrb1;
-    UCHAR  bval;
-
-    pDCB->GoingSRBCnt--; pDCB->pDCBACB->SelLost++;
-    DEBUG0(printk(KERN_INFO "DC390: RewaitSRB (%p, %p) pid = %li\n", pDCB, pSRB, pSRB->pcmd->pid);)
-    psrb1 = pDCB->pGoingSRB;
-    if( pSRB == psrb1 )
-    {
-	pDCB->pGoingSRB = psrb1->pNextSRB;
-    }
+    DEBUG0(printk ("DC390: Append pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid);)
+    if( pDCB->pWaitingSRB )
+	pDCB->pWaitLast->pNextSRB = pSRB;
     else
-    {
-	while( pSRB != psrb1->pNextSRB )
-	    psrb1 = psrb1->pNextSRB;
-	psrb1->pNextSRB = pSRB->pNextSRB;
-	if( pSRB == pDCB->pGoingLast )
-	    pDCB->pGoingLast = psrb1;
-    }
-    if( (psrb1 = pDCB->pWaitingSRB) )
-    {
-	pSRB->pNextSRB = psrb1;
 	pDCB->pWaitingSRB = pSRB;
-    }
+
+    pDCB->pWaitLast = pSRB;
+    pSRB->pNextSRB = NULL;
+    pDCB->WaitSRBCnt++;
+    pDCB->pDCBACB->CmdInQ++;
+}
+
+static __inline__ void dc390_Going_append (PDCB pDCB, PSRB pSRB)
+{
+    pDCB->GoingSRBCnt++;
+    DEBUG0(printk("DC390: Append SRB %p to Going\n", pSRB);)
+    /* Append to the list of Going commands */
+    if( pDCB->pGoingSRB )
+	pDCB->pGoingLast->pNextSRB = pSRB;
     else
-    {
-	pSRB->pNextSRB = NULL;
-	pDCB->pWaitingSRB = pSRB;
-	pDCB->pWaitLast = pSRB;
-    }
+	pDCB->pGoingSRB = pSRB;
+
+    pDCB->pGoingLast = pSRB;
+    /* No next one in sent list */
+    pSRB->pNextSRB = NULL;
+};
+
+static __inline__ void dc390_Going_remove (PDCB pDCB, PSRB pSRB)
+{
+   DEBUG0(printk("DC390: Remove SRB %p from Going\n", pSRB);)
+   if (pSRB == pDCB->pGoingSRB)
+	pDCB->pGoingSRB = pSRB->pNextSRB;
+   else
+     {
+	PSRB psrb = pDCB->pGoingSRB;
+	while (psrb && psrb->pNextSRB != pSRB)
+	  psrb = psrb->pNextSRB;
+	if (!psrb) 
+	  { printk (KERN_ERR "DC390: Remove non-ex. SRB %p from Going!\n", pSRB); return; }
+	psrb->pNextSRB = pSRB->pNextSRB;
+	if (pSRB == pDCB->pGoingLast)
+	  pDCB->pGoingLast = psrb;
+     }
+   pDCB->GoingSRBCnt--;
+};
+
+/* Moves SRB from Going list to the top of Waiting list */
+static void dc390_Going_to_Waiting ( PDCB pDCB, PSRB pSRB )
+{
+    DEBUG0(printk(KERN_INFO "DC390: Going_to_Waiting (SRB %p) pid = %li\n", pSRB, pSRB->pcmd->pid);)
+    /* Remove SRB from Going */
+    dc390_Going_remove (pDCB, pSRB);
+    /* Insert on top of Waiting */
+    dc390_Waiting_insert (pDCB, pSRB);
+    /* Tag Mask must be freed elsewhere ! (KG, 99/06/18) */
+}
+
+/* Moves first SRB from Waiting list to Going list */
+static __inline__ void dc390_Waiting_to_Going ( PDCB pDCB, PSRB pSRB )
+{	
+	/* Remove from waiting list */
+	DEBUG0(printk("DC390: Remove SRB %p from head of Waiting\n", pSRB);)
+	pDCB->pWaitingSRB = pSRB->pNextSRB;
+	if( !pDCB->pWaitingSRB ) pDCB->pWaitLast = NULL;
+	pDCB->WaitSRBCnt--;
+	dc390_Going_append (pDCB, pSRB);
+}
+
+/* 2.0 timer compatibility */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,30)
+ static inline int timer_pending(struct timer_list * timer)
+ {
+	return timer->prev != NULL;
+ }
+ #define time_after(a,b)         ((long)(b) - (long)(a) < 0)
+ #define time_before(a,b)        time_after(b,a)
+#endif
 
-    bval = pSRB->TagNumber;
-    pDCB->TagMask &= (~(1 << bval));	  /* Free TAG number */
+void DC390_waiting_timed_out (unsigned long ptr);
+/* Sets the timer to wake us up */
+static void dc390_waiting_timer (PACB pACB, unsigned long to)
+{
+	if (timer_pending (&pACB->Waiting_Timer)) return;
+	init_timer (&pACB->Waiting_Timer);
+	pACB->Waiting_Timer.function = DC390_waiting_timed_out;
+	pACB->Waiting_Timer.data = (unsigned long)pACB;
+	if (time_before (jiffies + to, pACB->pScsiHost->last_reset))
+		pACB->Waiting_Timer.expires = pACB->pScsiHost->last_reset + 1;
+	else
+		pACB->Waiting_Timer.expires = jiffies + to + 1;
+	add_timer (&pACB->Waiting_Timer);
 }
 
 
-static void dc390_DoWaitingSRB( PACB pACB )
+/* Send the next command from the waiting list to the bus */
+static void dc390_Waiting_process ( PACB pACB )
 {
     PDCB   ptr, ptr1;
     PSRB   pSRB;
 
-    if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) )
-    {
-	ptr = pACB->pDCBRunRobin;
-	if( !ptr )
-	{
-	    ptr = pACB->pLinkDCB;
-	    pACB->pDCBRunRobin = ptr;
-	}
-	ptr1 = ptr;
-	for( ;ptr1; )
-	{
-	    pACB->pDCBRunRobin = ptr1->pNextDCB;
-	    if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) ||
-		!( pSRB = ptr1->pWaitingSRB ) )
-	    {
-		if(pACB->pDCBRunRobin == ptr)
-		    break;
-		ptr1 = ptr1->pNextDCB;
-	    }
+    if( (pACB->pActiveDCB) || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) )
+	return;
+    if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
+    ptr = pACB->pDCBRunRobin;
+    if( !ptr )
+      {
+	ptr = pACB->pLinkDCB;
+	pACB->pDCBRunRobin = ptr;
+      }
+    ptr1 = ptr;
+    if (!ptr1) return;
+    do 
+      {
+	pACB->pDCBRunRobin = ptr1->pNextDCB;
+	if( !( pSRB = ptr1->pWaitingSRB ) ||
+	    ( ptr1->MaxCommand <= ptr1->GoingSRBCnt ))
+	  ptr1 = ptr1->pNextDCB;
+	else
+	  {
+	    /* Try to send to the bus */
+	    if( !dc390_StartSCSI(pACB, ptr1, pSRB) )
+	      dc390_Waiting_to_Going (ptr1, pSRB);
 	    else
-	    {
-		if( !dc390_StartSCSI(pACB, ptr1, pSRB) )
-		{
-		    ptr1->GoingSRBCnt++;
-		    if( ptr1->pWaitLast == pSRB )
-		    {
-			ptr1->pWaitingSRB = NULL;
-			ptr1->pWaitLast = NULL;
-		    }
-		    else
-		    {
-			ptr1->pWaitingSRB = pSRB->pNextSRB;
-		    }
-		    pSRB->pNextSRB = NULL;
-
-		    if( ptr1->pGoingSRB )
-			ptr1->pGoingLast->pNextSRB = pSRB;
-		    else
-			ptr1->pGoingSRB = pSRB;
-		    ptr1->pGoingLast = pSRB;
-		}
-		break;
-	    }
-	}
-    }
+	      dc390_waiting_timer (pACB, HZ/5);
+	    break;
+	  }
+      } while (ptr1 != ptr);
     return;
 }
 
-
-static __inline__ void dc390_SRBwaiting( PDCB pDCB, PSRB pSRB)
+/* Wake up waiting queue */
+void DC390_waiting_timed_out (unsigned long ptr)
 {
-    if( pDCB->pWaitingSRB )
-    {
-	pDCB->pWaitLast->pNextSRB = pSRB;
-	pSRB->pNextSRB = NULL;
-    }
-    else
-    {
-	pDCB->pWaitingSRB = pSRB;
-    }
-    pDCB->pWaitLast = pSRB;
+	PACB pACB = (PACB)ptr;
+	DC390_IFLAGS
+	DC390_AFLAGS
+	DEBUG0(printk ("DC390: Debug: Waiting queue woken up by timer!\n");)
+	DC390_LOCK_IO;
+	DC390_LOCK_ACB;
+	dc390_Waiting_process (pACB);
+	DC390_UNLOCK_ACB;
+	DC390_UNLOCK_IO;
 }
 
-
 /***********************************************************************
  * Function: static void dc390_SendSRB (PACB pACB, PSRB pSRB)
  *
@@ -878,41 +1084,33 @@
     PDCB   pDCB;
 
     pDCB = pSRB->pSRBDCB;
-    if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) ||
+    if( (pDCB->MaxCommand <= pDCB->GoingSRBCnt) || (pACB->pActiveDCB) ||
 	(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) )
     {
-	dc390_SRBwaiting(pDCB, pSRB);
-	goto SND_EXIT;
+	dc390_Waiting_append (pDCB, pSRB);
+	dc390_Waiting_process (pACB);
+	return;
     }
 
+#if 0
     if( pDCB->pWaitingSRB )
     {
-	dc390_SRBwaiting(pDCB, pSRB);
+	dc390_Waiting_append (pDCB, pSRB);
 /*	pSRB = GetWaitingSRB(pDCB); */	/* non-existent */
 	pSRB = pDCB->pWaitingSRB;
+	/* Remove from waiting list */
 	pDCB->pWaitingSRB = pSRB->pNextSRB;
 	pSRB->pNextSRB = NULL;
+	if (!pDCB->pWaitingSRB) pDCB->pWaitLast = NULL;
     }
-
-    if( !dc390_StartSCSI(pACB, pDCB, pSRB) )
-    {
-	pDCB->GoingSRBCnt++;
-	if( pDCB->pGoingSRB )
-	{
-	    pDCB->pGoingLast->pNextSRB = pSRB;
-	    pDCB->pGoingLast = pSRB;
-	}
-	else
-	{
-	    pDCB->pGoingSRB = pSRB;
-	    pDCB->pGoingLast = pSRB;
-	}
-    }
-    else
-	dc390_RewaitSRB0( pDCB, pSRB );
-
-SND_EXIT:
-    return;
+#endif
+	
+    if (!dc390_StartSCSI(pACB, pDCB, pSRB))
+	dc390_Going_append (pDCB, pSRB);
+    else {
+	dc390_Waiting_insert (pDCB, pSRB);
+	dc390_waiting_timer (pACB, HZ/5);
+    };
 }
 
 /***********************************************************************
@@ -927,8 +1125,8 @@
 {
     pSRB->pSRBDCB = pDCB;
     pSRB->pcmd = pcmd;
-    pSRB->ScsiCmdLen = pcmd->cmd_len;
-    memcpy (pSRB->CmdBlock, pcmd->cmnd, pcmd->cmd_len);
+    //pSRB->ScsiCmdLen = pcmd->cmd_len;
+    //memcpy (pSRB->CmdBlock, pcmd->cmnd, pcmd->cmd_len);
     
     if( pcmd->use_sg )
     {
@@ -961,8 +1159,39 @@
     pSRB->SGToBeXferLen = 0;
     pSRB->ScsiPhase = 0;
     pSRB->EndMessage = 0;
+    pSRB->TagNumber = 255;
 };
 
+/* Put cmnd from Query to Waiting list and send next Waiting cmnd */
+static void dc390_Query_to_Waiting (PACB pACB)
+{
+    Scsi_Cmnd *pcmd;
+    PSRB   pSRB;
+    PDCB   pDCB;
+
+    if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) )
+	return;
+
+    while (pACB->QueryCnt)
+    {
+	pSRB = dc390_Free_get ( pACB );
+	if (!pSRB) return;
+	pcmd = dc390_Query_get ( pACB );
+	if (!pcmd) { dc390_Free_insert (pACB, pSRB); return; }; /* should not happen */
+	pDCB = dc390_findDCB (pACB, pcmd->target, pcmd->lun);
+	if (!pDCB) 
+	{ 
+		dc390_Free_insert (pACB, pSRB);
+		printk (KERN_ERR "DC390: Command in queue to non-existing device!\n");
+		pcmd->result = MK_RES(DRIVER_ERROR,DID_ERROR,0,0);
+		DC390_UNLOCK_ACB_NI;
+		pcmd->done (pcmd);
+		DC390_LOCK_ACB_NI;
+	};
+	dc390_BuildSRB (pcmd, pDCB, pSRB);
+	dc390_Waiting_append ( pDCB, pSRB );
+    }
+}
 
 /***********************************************************************
  * Function : static int DC390_queue_command (Scsi_Cmnd *cmd,
@@ -985,7 +1214,6 @@
 
 int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
 {
-    Scsi_Cmnd *pcmd;
     PDCB   pDCB;
     PSRB   pSRB;
     DC390_AFLAGS
@@ -993,7 +1221,7 @@
 
 
     DEBUG0(/*  if(pACB->scan_devices) */	\
-	printk(KERN_INFO "DC390: Queue Cmd=%02x,ID=%d,LUN=%d (pid=%li)\n",\
+	printk(KERN_INFO "DC390: Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li)\n",\
 		cmd->cmnd[0],cmd->target,cmd->lun,cmd->pid);)
 
     DC390_LOCK_ACB;
@@ -1014,25 +1242,32 @@
     if ( ( cmd->target >= pACB->pScsiHost->max_id ) || 
 	 (cmd->lun >= pACB->pScsiHost->max_lun) )
     {
-/*	printk("DC390: Ignore target %d lun %d\n",
+/*	printk ("DC390: Ignore target %d lun %d\n",
 		cmd->target, cmd->lun); */
 	DC390_UNLOCK_ACB;
-	done(cmd);
-	return( 0 );
+	//return (1);
+	done (cmd);
+	return (0);
     }
 
-    if( (pACB->scan_devices || cmd->cmnd[0] == TEST_UNIT_READY) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )
+    if( (pACB->scan_devices || cmd->cmnd[0] == TEST_UNIT_READY || cmd->cmnd[0] == INQUIRY) && 
+       !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) )
     {
-	pACB->DCBmap[cmd->target] |= (1 << cmd->lun);
         pACB->scan_devices = 1;
 
-	dc390_initDCB( pACB, &pDCB, cmd );
+	dc390_initDCB( pACB, &pDCB, cmd->target, cmd->lun );
 	if (!pDCB)
 	  {
-	    printk (KERN_ERR "DC390: kmalloc for DCB failed, ID=%2x\n", cmd->target);
+	    printk (KERN_ERR "DC390: kmalloc for DCB failed, target %02x lun %02x\n", 
+		    cmd->target, cmd->lun);
 	    DC390_UNLOCK_ACB;
-	    done(cmd);
-	    return(0);
+	    printk ("DC390: No DCB in queue_command!\n");
+#ifdef USE_NEW_EH
+	    return (1);
+#else
+	    done (cmd);
+	    return (0);
+#endif
 	  };
             
     }
@@ -1041,71 +1276,73 @@
 	printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n",
 		cmd->target, cmd->lun); 
 	DC390_UNLOCK_ACB;
-	done(cmd);
-	return(0);
+	//return (1);
+	done (cmd);
+	return (0);
     }
     else
     {
-	pDCB = dc390_findDCB (pACB, cmd);
+	pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun);
 	if (!pDCB)
 	 {  /* should never happen */
+	    printk (KERN_ERR "DC390: no DCB failed, target %02x lun %02x\n", 
+		    cmd->target, cmd->lun);
 	    DC390_UNLOCK_ACB;
-	    done(cmd);
-	    return(0);
+	    printk ("DC390: No DCB in queuecommand (2)!\n");
+#ifdef USE_NEW_EH
+	    return (1);
+#else
+	    done (cmd);
+	    return (0);
+#endif
 	 };
     }
 
     pACB->Cmds++;
     cmd->scsi_done = done;
     cmd->result = 0;
+	
+    dc390_Query_to_Waiting (pACB);
 
-    if( pDCB->QIORBCnt ) /* Unsent commands ? */
+    if( pACB->QueryCnt ) /* Unsent commands ? */
     {
-	dc390_QLinkcmd( cmd, pDCB );
-	pcmd = dc390_Getcmd( pDCB ); /* Get first command */
-        pACB->CmdInQ++;
+	DEBUG0(printk ("DC390: QueryCnt != 0\n");)
+	dc390_Query_append ( cmd, pACB );
+	dc390_Waiting_process (pACB);
     }
-    else
-	pcmd = cmd;
-
-    pSRB = dc390_GetSRB( pACB );
-
-    if( !pSRB )
+    else if (pDCB->pWaitingSRB)
     {
-        dc390_QLinkcmd( pcmd, pDCB ); /* Queue command at the end */
-	pACB->CmdOutOfSRB++;
-	DC390_UNLOCK_ACB;
-	return(0);
+ 	pSRB = dc390_Free_get ( pACB );
+	DEBUG0(if (!pSRB) printk ("DC390: No free SRB but Waiting\n"); else printk ("DC390: Free SRB w/ Waiting\n");)
+	if (!pSRB) dc390_Query_append (cmd, pACB);
+	else 
+	  {
+	    dc390_BuildSRB (cmd, pDCB, pSRB);
+	    dc390_Waiting_append (pDCB, pSRB);
+	  }
+	dc390_Waiting_process (pACB);
     }
-
-    dc390_BuildSRB (pcmd, pDCB, pSRB);
-    dc390_SendSRB( pACB, pSRB );
+    else
+    {
+ 	pSRB = dc390_Free_get ( pACB );
+	DEBUG0(if (!pSRB) printk ("DC390: No free SRB w/o Waiting\n"); else printk ("DC390: Free SRB w/o Waiting\n");)
+	if (!pSRB)
+	{
+	    dc390_Query_append (cmd, pACB);
+	    dc390_Waiting_process (pACB);
+	}
+	else 
+	{
+	    dc390_BuildSRB (cmd, pDCB, pSRB);
+	    dc390_SendSRB (pACB, pSRB);
+	};
+    };
 
     DC390_UNLOCK_ACB;
-    DEBUG1(printk (KERN_DEBUG " ... command (%02x) queued successfully.\n", pcmd->cmnd[0]);)
+    DEBUG1(printk (KERN_DEBUG " ... command (pid %li) queued successfully.\n", cmd->pid);)
     return(0);
 }
 
-
-static void dc390_DoNextCmd( PACB pACB, PDCB pDCB )
-{
-    Scsi_Cmnd *pcmd;
-    PSRB   pSRB;
-
-    if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) )
-	return;
-
-    pcmd = dc390_Getcmd( pDCB );
-    pSRB = dc390_GetSRB( pACB );
-    if( !pSRB )
-	dc390_QLinkcmd( pcmd, pDCB );
-    else
-      {
-	dc390_BuildSRB (pcmd, pDCB, pSRB);
-	dc390_SendSRB( pACB, pSRB );
-      };
-}
-
 /* We ignore mapping problems, as we expect everybody to respect 
  * valid partition tables. Waiting for complaints ;-) */
 
@@ -1242,15 +1479,17 @@
 void dc390_dumpinfo (PACB pACB, PDCB pDCB, PSRB pSRB)
 {
     USHORT pstat; PDEVDECL1;
+    if (!pDCB) pDCB = pACB->pActiveDCB;
+    if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB;
 
     if (pSRB) 
     {
-	printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08lx, Phase %02x\n",
+	printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08x, Phase %02x\n",
 		pSRB->TotalXferredLen, pSRB->SGToBeXferLen, pSRB->SRBState,
 		pSRB->ScsiPhase);
 	printk ("DC390: AdpaterStatus: %02x, SRB Status %02x\n", pSRB->AdaptStatus, pSRB->SRBStatus);
     };
-    printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08lx\n", dc390_laststatus);
+    printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08x\n", dc390_laststatus);
     printk ("DC390: Register dump: SCSI block:\n");
     printk ("DC390: XferCnt  Cmd Stat IntS IRQS FFIS Ctl1 Ctl2 Ctl3 Ctl4\n");
     printk ("DC390:  %06x   %02x   %02x   %02x",
@@ -1260,6 +1499,12 @@
 	    DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1),
 	    DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4));
     DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
+    if (DC390_read8(Current_Fifo) & 0x1f)
+      {
+	printk ("DC390: FIFO:");
+	while (DC390_read8(Current_Fifo) & 0x1f) printk (" %02x", DC390_read8(ScsiFifo));
+	printk ("\n");
+      };
     printk ("DC390: Register dump: DMA engine:\n");
     printk ("DC390: Cmd   STrCnt    SBusA    WrkBC    WrkAC Stat SBusCtrl\n");
     printk ("DC390:  %02x %08x %08x %08x %08x   %02x %08x\n",
@@ -1289,44 +1534,40 @@
 {
     PDCB  pDCB;
     PSRB  pSRB, psrb;
-    ULONG count, i;
-    PSCSICMD  pcmd, pcmd1;
+    UINT  count, i;
+    PSCSICMD  pcmd;
     int   status;
-    ULONG sbac;
+    //ULONG sbac;
     DC390_AFLAGS
     PACB  pACB = (PACB) cmd->host->hostdata;
 
     DC390_LOCK_ACB;
 
-    pDCB = dc390_findDCB (pACB, cmd);
-    /* abort() is too buggy at the moment. If it's called we are in trouble anyway.
-     * so let's dump some info into the syslog at least. (KG, 98/08/20) */
-    if (pDCB) pSRB = pDCB->pActiveSRB; else pSRB = 0;
-    printk ("DC390: Abort command (pid %li, DCB %p, SRB %p)\n",
-	    cmd->pid, pDCB, pSRB);
-    dc390_dumpinfo (pACB, pDCB, pSRB);
-
-    if( !pDCB ) goto  NOT_RUN;
+    printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n",
+	    cmd->pid, cmd->target, cmd->lun);
 
-    if( pDCB->QIORBCnt )
+    /* First scan Query list */
+    if( pACB->QueryCnt )
     {
-	pcmd = pDCB->pQIORBhead;
+	pcmd = pACB->pQueryHead;
 	if( pcmd == cmd )
 	{
-	    pDCB->pQIORBhead = pcmd->next;
+	    /* Found: Dequeue */
+	    pACB->pQueryHead = pcmd->next;
 	    pcmd->next = NULL;
-	    pDCB->QIORBCnt--;
+	    if (cmd == pACB->pQueryTail) pACB->pQueryTail = NULL;
+	    pACB->QueryCnt--;
 	    status = SCSI_ABORT_SUCCESS;
 	    goto  ABO_X;
 	}
-	for( count = pDCB->QIORBCnt, i=0; i<count-1; i++)
+	for( count = pACB->QueryCnt, i=0; i<count-1; i++)
 	{
 	    if( pcmd->next == cmd )
 	    {
-		pcmd1 = pcmd->next;
-		pcmd->next = pcmd1->next;
-		pcmd1->next = NULL;
-		pDCB->QIORBCnt--;
+		pcmd->next = cmd->next;
+		cmd->next = NULL;
+		if (cmd == pACB->pQueryTail) pACB->pQueryTail = NULL;
+		pACB->QueryCnt--;
 		status = SCSI_ABORT_SUCCESS;
 		goto  ABO_X;
 	    }
@@ -1337,14 +1578,21 @@
 	}
     }
 	
+    pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun);
+    if( !pDCB ) goto  NOT_RUN;
+
     /* Added 98/07/02 KG */
+    /*
     pSRB = pDCB->pActiveSRB;
     if (pSRB && pSRB->pcmd == cmd )
 	goto ON_GOING;
-	
+     */
+    
     pSRB = pDCB->pWaitingSRB;
     if( !pSRB )
 	goto  ON_GOING;
+
+    /* Now scan Waiting queue */
     if( pSRB->pcmd == cmd )
     {
 	pDCB->pWaitingSRB = pSRB->pNextSRB;
@@ -1364,16 +1612,21 @@
 	pSRB = psrb->pNextSRB;
 	psrb->pNextSRB = pSRB->pNextSRB;
 	if( pSRB == pDCB->pWaitLast )
-	    pDCB->pWaitLast = psrb; /* No check for psrb == NULL ? */
+	    pDCB->pWaitLast = psrb;
 IN_WAIT:
-	pSRB->pNextSRB = pACB->pFreeSRB;
-	pACB->pFreeSRB = pSRB;
+	dc390_Free_insert (pACB, pSRB);
+	pDCB->WaitSRBCnt--;
 	cmd->next = NULL;
 	status = SCSI_ABORT_SUCCESS;
 	goto  ABO_X;
     }
 
+    /* SRB has already been sent ! */
 ON_GOING:
+    /* abort() is too stupid for already sent commands at the moment. 
+     * If it's called we are in trouble anyway, so let's dump some info 
+     * into the syslog at least. (KG, 98/08/20,99/06/20) */
+    dc390_dumpinfo (pACB, pDCB, pSRB);
     pSRB = pDCB->pGoingSRB;
     pDCB->DCBFlag |= ABORT_DEV_;
     /* Now for the hard part: The command is currently processed */
@@ -1404,12 +1657,13 @@
 ABO_X:
     cmd->result = DID_ABORT << 16;
     printk(KERN_INFO "DC390: Aborted pid %li with status %i\n", cmd->pid, status);
+#if 0
     if (cmd->pid == dc390_lastabortedpid) /* repeated failure ? */
 	{
 		/* Let's do something to help the bus getting clean again */
 		DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
 		DC390_write8 (ScsiCmd, DMA_COMMAND);
-			//DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
+		//DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
 		//DC390_write8 (ScsiCmd, RESET_ATN_CMD);
 		DC390_write8 (ScsiCmd, NOP_CMD);
 		//udelay (10000);
@@ -1434,10 +1688,13 @@
 	sbac = DC390_read32 (DMA_ScsiBusCtrl);
 	printk ("%08lx\n", sbac);
     };
+#endif
     dc390_lastabortedpid = cmd->pid;
     DC390_UNLOCK_ACB;
     //do_DC390_Interrupt (pACB->IRQLevel, 0, 0);
-    cmd->scsi_done(cmd);
+#ifndef USE_NEW_EH	
+    if (status == SCSI_ABORT_SUCCESS) cmd->scsi_done(cmd);
+#endif	
     return( status );
 }
 
@@ -1454,20 +1711,24 @@
 	pDCB->SyncMode &= ~SYNC_NEGO_DONE;
 	pDCB->SyncPeriod = 0;
 	pDCB->SyncOffset = 0;
+	pDCB->TagMask = 0;
 	pDCB->CtrlR3 = FAST_CLK;
 	pDCB->CtrlR4 &= NEGATE_REQACKDATA | CTRL4_RESERVED | NEGATE_REQACK;
 	pDCB->CtrlR4 |= pACB->glitch_cfg;
 	pDCB = pDCB->pNextDCB;
     }
     while( pdcb != pDCB );
-}
+    pACB->ACBFlag &= ~(RESET_DEV | RESET_DONE | RESET_DETECT);
 
+}
 
+#if 0
+/* Moves all SRBs from Going to Waiting for all DCBs */
 static void dc390_RecoverSRB( PACB pACB )
 {
     PDCB   pDCB, pdcb;
     PSRB   psrb, psrb2;
-    ULONG  cnt, i;
+    UINT   cnt, i;
 
     pDCB = pACB->pLinkDCB;
     if( !pDCB ) return;
@@ -1499,7 +1760,7 @@
 	pdcb = pdcb->pNextDCB;
     } while( pdcb != pDCB );
 }
-
+#endif
 
 /***********************************************************************
  * Function : int DC390_reset (Scsi_Cmnd *cmd, ...)
@@ -1507,34 +1768,37 @@
  * Purpose : perform a hard reset on the SCSI bus
  *
  * Inputs : cmd - command which caused the SCSI RESET
+ *	    resetFlags - how hard to try
  *
  * Returns : 0 on success.
  ***********************************************************************/
 
-int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags)
+int DC390_reset (Scsi_Cmnd *cmd, unsigned int resetFlags)
 {
     UCHAR   bval;
-    ULONG   i;
     DC390_AFLAGS
     PACB    pACB = (PACB) cmd->host->hostdata;
 
     printk(KERN_INFO "DC390: RESET ... ");
 
     DC390_LOCK_ACB;
+    if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
     bval = DC390_read8 (CtrlReg1);
     bval |= DIS_INT_ON_SCSI_RST;
-    DC390_write8 (CtrlReg1, bval);	/* disable interrupt */
+    DC390_write8 (CtrlReg1, bval);	/* disable IRQ on bus reset */
 
+    pACB->ACBFlag |= RESET_DEV;
     dc390_ResetSCSIBus( pACB );
-    /* Unlock ? */
-    for( i=0; i<600; i++ )
-	udelay(1000);
 
+    dc390_ResetDevParam( pACB );
+    udelay (1000);
+    pACB->pScsiHost->last_reset = jiffies + 3*HZ/2 
+		+ HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
+    
     DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
     DC390_read8 (INT_Status);		/* Reset Pending INT */
 
-    dc390_ResetDevParam( pACB );
-    dc390_DoingSRB_Done( pACB );
+    dc390_DoingSRB_Done( pACB, cmd );
     /* dc390_RecoverSRB (pACB); */
     pACB->pActiveDCB = NULL;
 
@@ -1543,10 +1807,10 @@
     bval &= ~DIS_INT_ON_SCSI_RST;
     DC390_write8 (CtrlReg1, bval);	/* re-enable interrupt */
 
-    dc390_DoWaitingSRB( pACB );
+    dc390_Waiting_process( pACB );
 
-    DC390_UNLOCK_ACB;
     printk("done\n");
+    DC390_UNLOCK_ACB;
     return( SCSI_RESET_SUCCESS );
 }
 
@@ -1556,22 +1820,22 @@
 /***********************************************************************
  * Function : static void dc390_initDCB()
  *
- * Purpose :  initialize the internal structures for a given DCB
+ * Purpose :  initialize the internal structures for a DCB (to be malloced)
  *
- * Inputs : cmd - pointer to this scsi cmd request block structure
+ * Inputs : SCSI id and lun
  ***********************************************************************/
 
-void dc390_initDCB( PACB pACB, PDCB *ppDCB, PSCSICMD cmd )
+void dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun )
 {
     PEEprom	prom;
     UCHAR	index;
-    PDCB pDCB;
+    PDCB pDCB, pDCB2;
 
     pDCB = kmalloc (sizeof(DC390_DCB), GFP_ATOMIC);
-    DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): 0x%08x\n",	\
-	    cmd->target, cmd->lun, (int)pDCB);)
+    DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): %p\n"	\
+	    id, lun, pDCB);)
  
-    *ppDCB = pDCB;
+    *ppDCB = pDCB; pDCB2 = 0;
     if (!pDCB) return;
     if( pACB->DCBCnt == 0 )
     {
@@ -1585,37 +1849,58 @@
    
     pACB->DCBCnt++;
    
-    pACB->pLastDCB = pDCB;
     pDCB->pNextDCB = pACB->pLinkDCB;
+    pACB->pLastDCB = pDCB;
 
     pDCB->pDCBACB = pACB;
-    pDCB->QIORBCnt = 0;
-    pDCB->UnitSCSIID = cmd->target;
-    pDCB->UnitSCSILUN = cmd->lun;
+    pDCB->TargetID = id;
+    pDCB->TargetLUN = lun;
     pDCB->pWaitingSRB = NULL;
     pDCB->pGoingSRB = NULL;
     pDCB->GoingSRBCnt = 0;
+    pDCB->WaitSRBCnt = 0;
     pDCB->pActiveSRB = NULL;
     pDCB->TagMask = 0;
     pDCB->MaxCommand = 1;
     index = pACB->AdapterIndex;
     pDCB->DCBFlag = 0;
 
-    prom = (PEEprom) &dc390_eepromBuf[index][cmd->target << 2];
-    pDCB->DevMode = prom->EE_MODE1;
+    /* Is there a corresp. LUN==0 device ? */
+    if (lun != 0)
+	pDCB2 = dc390_findDCB (pACB, id, 0);
+    prom = (PEEprom) &dc390_eepromBuf[index][id << 2];
+    /* Some values are for all LUNs: Copy them */
+    /* In a clean way: We would have an own structure for a SCSI-ID */
+    if (pDCB2)
+    {
+      pDCB->DevMode = pDCB2->DevMode;
+      pDCB->SyncMode = pDCB2->SyncMode;
+      pDCB->SyncPeriod = pDCB2->SyncPeriod;
+      pDCB->SyncOffset = pDCB2->SyncOffset;
+      pDCB->NegoPeriod = pDCB2->NegoPeriod;
+      
+      pDCB->CtrlR3 = pDCB2->CtrlR3;
+      pDCB->CtrlR4 = pDCB2->CtrlR4;
+      pDCB->Inquiry7 = pDCB2->Inquiry7;
+    }
+    else
+    {		
+      pDCB->DevMode = prom->EE_MODE1;
+      pDCB->SyncMode = 0;
+      pDCB->SyncPeriod = 0;
+      pDCB->SyncOffset = 0;
+      pDCB->NegoPeriod = (dc390_clock_period1[prom->EE_SPEED] * 25) >> 2;
+            
+      pDCB->CtrlR3 = FAST_CLK;
+      
+      pDCB->CtrlR4 = pACB->glitch_cfg | CTRL4_RESERVED;
+      if( dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION)
+	pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK;
+      pDCB->Inquiry7 = 0;
+    }
 
-    pDCB->SyncMode = 0;
+    pACB->DCBmap[id] |= (1 << lun);
     dc390_updateDCB(pACB, pDCB);
-
-    pDCB->SyncPeriod = 0;
-    pDCB->SyncOffset = 0;
-    pDCB->NegoPeriod = (dc390_clock_period1[prom->EE_SPEED] * 25) >> 2;
-
-    pDCB->CtrlR3 = FAST_CLK;
-
-    pDCB->CtrlR4 = pACB->glitch_cfg | CTRL4_RESERVED;
-    if( dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION)
-	pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK;
 }
 
 /***********************************************************************
@@ -1626,24 +1911,26 @@
 
 void dc390_updateDCB (PACB pACB, PDCB pDCB)
 {
-  pDCB->IdentifyMsg = IDENTIFY (pDCB->DevMode & EN_DISCONNECT_, pDCB->UnitSCSILUN);
-  
-  if (pDCB->DevMode & TAG_QUEUEING_) pDCB->SyncMode &= EN_TAG_QUEUEING | SYNC_NEGO_DONE | EN_ATN_STOP;
-  else pDCB->SyncMode &= SYNC_NEGO_DONE | EN_ATN_STOP;
-  
-  if( pDCB->DevMode & SYNC_NEGO_ && (!(pDCB->UnitSCSILUN) || dc390_CurrSyncOffset) )
-     pDCB->SyncMode |= SYNC_ENABLE;
-  else
-     {
+  pDCB->SyncMode &= EN_TAG_QUEUEING | SYNC_NEGO_DONE /*| EN_ATN_STOP*/;
+  if (pDCB->DevMode & TAG_QUEUEING_) {
+	//if (pDCB->SyncMode & EN_TAG_QUEUEING) pDCB->MaxCommand = pACB->TagMaxNum;
+  } else {
+	pDCB->SyncMode &= ~EN_TAG_QUEUEING;
+	pDCB->MaxCommand = 1;
+  };
+
+  if( pDCB->DevMode & SYNC_NEGO_ )
+	pDCB->SyncMode |= SYNC_ENABLE;
+  else {
 	pDCB->SyncMode &= ~(SYNC_NEGO_DONE | SYNC_ENABLE);
 	pDCB->SyncOffset &= ~0x0f;
-     };
-   
-  if (! (pDCB->DevMode & EN_DISCONNECT_)) pDCB->SyncMode &= ~EN_ATN_STOP; 
-  
+  };
+
+  //if (! (pDCB->DevMode & EN_DISCONNECT_)) pDCB->SyncMode &= ~EN_ATN_STOP; 
+
   pDCB->CtrlR1 = pACB->pScsiHost->this_id;
   if( pDCB->DevMode & PARITY_CHK_ )
-    pDCB->CtrlR1 |= PARITY_ERR_REPO;
+	pDCB->CtrlR1 |= PARITY_ERR_REPO;
 };  
 
 
@@ -1657,7 +1944,7 @@
 {
   int i;
   PDCB pDCB = pACB->pLinkDCB;
-  for (i = 0; i < pACB->DeviceCnt; i++)
+  for (i = 0; i < pACB->DCBCnt; i++)
     {
       dc390_updateDCB (pACB, pDCB);
       pDCB = pDCB->pNextDCB;
@@ -1681,12 +1968,12 @@
 
 void dc390_linkSRB( PACB pACB )
 {
-    ULONG   count, i;
+    UINT   count, i;
 
     count = pACB->SRBCount;
-    for( i=0; i< count; i++)
+    for( i=0; i<count; i++)
     {
-	if( i != count - 1)
+	if( i != count-1 )
 	    pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
 	else
 	    pACB->SRB_array[i].pNextSRB = NULL;
@@ -1716,7 +2003,15 @@
     psh->io_port = io_port;
     psh->n_io_port = 0x80;
     psh->irq = Irq;
-
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,50)
+    psh->base = io_port;
+#else
+    psh->base = (char*)io_port;
+#endif	
+    psh->unique_id = io_port;
+    psh->dma_channel = -1;
+    psh->last_reset = jiffies;
+	
     pACB = (PACB) psh->hostdata;
     DC390_LOCKA_INIT;
     DC390_LOCK_ACB;
@@ -1741,6 +2036,8 @@
     pACB->pActiveDCB = NULL;
     pACB->pFreeSRB = pACB->SRB_array;
     pACB->SRBCount = MAX_SRB_CNT;
+    pACB->QueryCnt = 0;
+    pACB->pQueryHead = NULL;
     pACB->AdapterIndex = index;
     pACB->status = 0;
     psh->this_id = dc390_eepromBuf[index][EE_ADAPT_SCSI_ID];
@@ -1759,7 +2056,9 @@
 	pACB->DCBmap[i] = 0;
     pACB->sel_timeout = SEL_TIMEOUT;
     pACB->glitch_cfg = EATER_25NS;
-    pACB->Cmds = pACB->CmdInQ = pACB->CmdOutOfSRB = pACB->SelLost = 0;
+    pACB->Cmds = pACB->CmdInQ = pACB->CmdOutOfSRB = 0;
+    pACB->SelLost = pACB->SelConn = 0;
+    init_timer (&pACB->Waiting_Timer);
 }
 
 
@@ -1777,22 +2076,11 @@
 int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index)
 {
     PACB   pACB, pACB2;
-    UCHAR  used_irq = 0, dstate;
+    UCHAR  dstate;
     int    i;
     
     pACB = (PACB) psh->hostdata;
     
-    for ( pACB2 = dc390_pACB_start; pACB2 ; )
-      {
-	if( pACB2->IRQLevel == Irq )
-	  {
-	    used_irq = 1;
-	    break;
-	  }
-	else
-	  pACB2 = pACB2->pNextACB;
-      }
-
     if (check_region (io_port, psh->n_io_port))
 	{
 	    printk(KERN_ERR "DC390: register IO ports error!\n");
@@ -1803,14 +2091,12 @@
 
     DC390_read8_ (INT_Status, io_port);		/* Reset Pending INT */
 
-    if( !used_irq )
-    {
-	if( (i = request_irq(Irq, do_DC390_Interrupt, DC390_IRQ, "tmscsim", NULL) ))
-	    {
-		    printk(KERN_ERR "DC390: register IRQ error!\n");
-		    return( -1 );
-	    }
-    }
+    if( (i = request_irq(Irq, do_DC390_Interrupt, DC390_IRQ, "tmscsim", pACB) ))
+      {
+	printk(KERN_ERR "DC390: register IRQ error!\n");
+	release_region (io_port, psh->n_io_port);
+	return( -1 );
+      }
 
     if( !dc390_pACB_start )
       {
@@ -1832,9 +2118,13 @@
     if (pACB->Gmode2 & RST_SCSI_BUS)
     {
 	dc390_ResetSCSIBus( pACB );
-	/* Unlock before ? */
-	for( i=0; i<600; i++ )
+	udelay (1000);
+	pACB->pScsiHost->last_reset = jiffies + HZ/2
+		    + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
+	/*
+	for( i=0; i<(500 + 1000*dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]); i++ )
 		udelay(1000);
+	 */
     };
     pACB->ACBFlag = 0;
     DC390_read8 (INT_Status);				/* Reset Pending INT */
@@ -1846,6 +2136,7 @@
     DC390_write8 (CtrlReg3, FAST_CLK);			/* fast clock */
     DC390_write8 (CtrlReg4, pACB->glitch_cfg |			/* glitch eater */
 		(dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ? NEGATE_REQACKDATA : 0);	/* Negation */
+    DC390_write8 (CtcReg_High, 0);			/* Clear Transfer Count High: ID */
     DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
     DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
     DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
@@ -1885,18 +2176,24 @@
 	printk (KERN_ERR "DC390_init: No EEPROM found!\n");
 	return( -1 );
 #else
-	int period;
-	printk (KERN_INFO "DC390_init: No EEPROM found!\n");
-	printk (KERN_INFO "DC390_init: Trying default EEPROM settings:\n");
-	dc390_checkparams ();
-	period = dc390_clock_period1[tmscsim[1]];
+	int speed;
+	dc390_adapname = "AM53C974";
+	printk (KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
+	dc390_check_for_safe_settings ();
+	dc390_fill_with_defaults ();
+	dc390_EEprom_Override (index);
+	speed = dc390_clock_speed[tmscsim[1]];
 	printk (KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz),"
-		" DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i)\n", tmscsim[0], tmscsim[1],
-		40 / period, ((40%period)*10 + period/2) / period,
-		(UCHAR)tmscsim[2], (UCHAR)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]));
-	dc390_EEpromDefaults (index);
+		" DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n", 
+		tmscsim[0], tmscsim[1], speed/10, speed%10,
+		(UCHAR)tmscsim[2], (UCHAR)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]);
 #endif
-    };
+    }
+    else
+    {
+	dc390_check_for_safe_settings ();
+	dc390_EEprom_Override (index);
+    }
    
     psh = scsi_register( psht, sizeof(DC390_ACB) );
     if( !psh ) return( -1 );
@@ -2000,7 +2297,8 @@
     PDEVDECL0;
     UCHAR   irq;
     UINT    io_port;
-    DC390_IFLAGS DC390_DFLAGS
+    //DC390_IFLAGS
+    DC390_DFLAGS
 
     DC390_LOCK_DRV;
     //dc390_pSHT_start = psht;
@@ -2009,7 +2307,11 @@
     if ( PCI_PRESENT )
 	while (PCI_FIND_DEVICE (PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974))
 	{
-	    DC390_LOCK_IO;		/* Remove this when going to new eh */
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,30)
+	    if (pci_enable_device (pdev))
+		continue;
+#endif
+	    //DC390_LOCK_IO;		/* Remove this when going to new eh */
 	    PCI_GET_IO_AND_IRQ;
 	    DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq);)
 
@@ -2019,14 +2321,17 @@
 		dc390_set_pci_cfg (PDEV);
 		dc390_adapterCnt++;
 	    };
-	    DC390_UNLOCK_IO;		/* Remove when going to new eh */
+	    //DC390_UNLOCK_IO;		/* Remove when going to new eh */
 	}
     else
 	printk (KERN_ERR "DC390: No PCI BIOS found!\n");
    
     if (dc390_adapterCnt)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30)
+	psht->proc_name = "tmscsim";
+#else
 	psht->proc_dir = &DC390_proc_scsi_tmscsim;
-
+#endif
     printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt);
     DC390_UNLOCK_DRV;
     return( dc390_adapterCnt );
@@ -2048,7 +2353,7 @@
    if (cmd->result)
    {
 	PACB pACB = (PACB)cmd->host->hostdata;
-	PDCB pDCB = dc390_findDCB (pACB, cmd);
+	PDCB pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun);
 	printk ("DC390: Unsetting DsCn, Sync and TagQ!\n");
 	if (pDCB)
 	{
@@ -2056,7 +2361,6 @@
 		dc390_updateDCB (pACB, pDCB);
 	};
    };
-   kfree (cmd->buffer);
    kfree (cmd);
 };
 
@@ -2064,20 +2368,21 @@
 {
    char* buffer;
    Scsi_Cmnd* cmd;
-   buffer = kmalloc (256, GFP_ATOMIC);
-   cmd = kmalloc (sizeof (Scsi_Cmnd), GFP_ATOMIC);
+   cmd = kmalloc (sizeof(Scsi_Cmnd) + 256, GFP_ATOMIC);
+   if (!cmd) { printk ("DC390: kmalloc failed in inquiry!\n"); return; };
+   buffer = (char*)cmd + sizeof(Scsi_Cmnd);
 
-   memset (buffer, 0, 256);
-   memset (cmd, 0, sizeof(Scsi_Cmnd));
+   memset (cmd, 0, sizeof(Scsi_Cmnd) + 256);
    cmd->cmnd[0] = INQUIRY;
-   cmd->cmnd[1] = (pDCB->UnitSCSILUN << 5) & 0xe0;
+   cmd->cmnd[1] = (pDCB->TargetLUN << 5) & 0xe0;
    cmd->cmnd[4] = 0xff;
    
    cmd->cmd_len = 6; cmd->old_cmd_len = 6;
    cmd->host = pACB->pScsiHost;
-   cmd->target = pDCB->UnitSCSIID;
-   cmd->lun = pDCB->UnitSCSILUN; 
+   cmd->target = pDCB->TargetID;
+   cmd->lun = pDCB->TargetLUN; 
    cmd->serial_number = 1;
+   cmd->pid = 390;
    cmd->bufflen = 128;
    cmd->buffer = buffer;
    cmd->request_bufflen = 128;
@@ -2088,11 +2393,62 @@
 
    cmd->request.rq_status = RQ_SCSI_BUSY;
 
+   pDCB->SyncMode &= ~SYNC_NEGO_DONE;
    printk (KERN_INFO "DC390: Queue INQUIRY command to dev ID %02x LUN %02x\n",
-	   pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
+	   pDCB->TargetID, pDCB->TargetLUN);
    DC390_queue_command (cmd, dc390_inquiry_done);
 };
 
+/***********************************************************************
+ * Functions: dc390_sendstart(), dc390_sendstart_done()
+ *
+ * Purpose: When changing speed etc., we have to issue an INQUIRY
+ *	    command to make sure, we agree upon the nego parameters
+ *	    with the device
+ ***********************************************************************/
+
+static void dc390_sendstart_done (Scsi_Cmnd* cmd)
+{
+   printk (KERN_INFO "DC390: SENDSTART (ID %02x LUN %02x) returned %08x\n",
+	   cmd->target, cmd->lun, cmd->result);
+   kfree (cmd);
+};
+
+void dc390_sendstart (PACB pACB, PDCB pDCB)
+{
+   char* buffer;
+   Scsi_Cmnd* cmd;
+   cmd = kmalloc (sizeof(Scsi_Cmnd) + 256, GFP_ATOMIC);
+   if (!cmd) { printk ("DC390: kmalloc failed in sendstart!\n"); return; };
+   buffer = (char*)cmd + sizeof(Scsi_Cmnd);
+
+   memset (cmd, 0, sizeof(Scsi_Cmnd) + 256);
+   cmd->cmnd[0] = 0x1b; /* START_STOP_UNIT */
+   cmd->cmnd[1] = (pDCB->TargetLUN << 5) & 0xe0;
+   cmd->cmnd[4] = 0x01; /* START */
+   
+   cmd->cmd_len = 6; cmd->old_cmd_len = 6;
+   cmd->host = pACB->pScsiHost;
+   cmd->target = pDCB->TargetID;
+   cmd->lun = pDCB->TargetLUN; 
+   cmd->serial_number = 1;
+   cmd->pid = 310;
+   cmd->bufflen = 128;
+   cmd->buffer = buffer;
+   cmd->request_bufflen = 128;
+   cmd->request_buffer = &buffer[128];
+   cmd->done = dc390_sendstart_done;
+   cmd->scsi_done = dc390_sendstart_done;
+   cmd->timeout_per_command = 5*HZ;
+
+   cmd->request.rq_status = RQ_SCSI_BUSY;
+
+   pDCB->SyncMode &= ~SYNC_NEGO_DONE;
+   printk (KERN_INFO "DC390: Queue SEND_START command to dev ID %02x LUN %02x\n",
+	   pDCB->TargetID, pDCB->TargetLUN);
+   DC390_queue_command (cmd, dc390_sendstart_done);
+};
+
 /********************************************************************
  * Function: dc390_set_info()
  *
@@ -2210,6 +2566,9 @@
   if (!memcmp (pos, "RESET", 5)) goto reset;
   else if (!memcmp (pos, "INQUIRY", 7)) goto inquiry;
   else if (!memcmp (pos, "REMOVE", 6)) goto remove;
+  else if (!memcmp (pos, "ADD", 3)) goto add;
+  else if (!memcmp (pos, "START", 5)) goto start;
+  else if (!memcmp (pos, "DUMP", 4)) goto dump;
   
   if (isdigit (*pos))
     {
@@ -2226,13 +2585,20 @@
       pDCB = pACB->pLinkDCB;
       for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB;
       /* Sanity Check */
-      if (pDCB->UnitSCSIID != id || pDCB->UnitSCSILUN != lun) 
+      if (pDCB->TargetID != id || pDCB->TargetLUN != lun) 
 	 {
 	    printk (KERN_ERR "DC390: no such device: Idx=%02i ID=%02i LUN=%02i\n",
 		    dev, id, lun);
 	    goto einv2;
 	 };
 
+      if (pDCB->pWaitingSRB || pDCB->pGoingSRB)
+      {
+	  printk ("DC390: Cannot change dev (%i-%i) cfg: Pending requests\n",
+		  pDCB->TargetID, pDCB->TargetLUN);
+	  goto einv;
+      };
+	  
       olddevmode = pDCB->DevMode;
       YESNO (pos, pDCB->DevMode, PARITY_CHK_);
       needs_inquiry++;
@@ -2245,8 +2611,7 @@
       needs_inquiry++;
       YESNO (pos, pDCB->DevMode, TAG_QUEUEING_);
       if ((olddevmode & TAG_QUEUEING_) == (pDCB->DevMode & TAG_QUEUEING_)) needs_inquiry--;
-      YESNO (pos, pDCB->SyncMode, EN_ATN_STOP);
-      
+
       dc390_updateDCB (pACB, pDCB);
       if (!pos) goto ok;
        
@@ -2266,7 +2631,7 @@
       else pos = strtok (0, " \t\n:=,;.");
       if (!pos) goto ok;
       
-      /* Speed: NegoPeriod */
+      /* Sync Speed in MHz */
       if (*pos != '-')
 	{
 	  SCANF (pos, p0, dum, 1, 13); 
@@ -2281,11 +2646,11 @@
 		for (; p0-pos > 1; p0--) dum /= 10;
 		pDCB->NegoPeriod = (100000/(100*dumold + dum)) >> 2;
 		if (pDCB->NegoPeriod < 19) pDCB->NegoPeriod = 19;
-		if (pDCB->NegoPeriod != olddevmode) needs_inquiry++;
 		pos = strtok (0, " \t\n:=,;");
 		if (!pos) goto ok;
 	     };
 	  if (*pos == 'M') pos = strtok (0, " \t\n:=,;");
+	  if (pDCB->NegoPeriod != olddevmode) needs_inquiry++;
 	}
       else pos = strtok (0, " \t\n:=,;");
       /* dc390_updateDCB (pACB, pDCB); */
@@ -2300,28 +2665,49 @@
 	  if (pDCB->SyncOffset > olddevmode) needs_inquiry++;
 	}
       else pos = strtok (0, " \t\n:=,;");
+      if (!pos) goto ok;
       dc390_updateDCB (pACB, pDCB);
+
+      //olddevmode = pDCB->MaxCommand;
+      /* MaxCommand (Tags) */
+      if (*pos != '-')
+	{
+	  SCANF (pos, p0, dum, 1, 32 /*pACB->TagMaxNum*/);
+	  if (pDCB->SyncMode & EN_TAG_QUEUEING)
+		pDCB->MaxCommand = dum;
+	  else printk (KERN_INFO "DC390: Can't set MaxCmd larger than one without Tag Queueing!\n");
+	}
+      else pos = strtok (0, " \t\n:=,;");
+
     }
   else
     {
-      char* p1 = pos; UCHAR dum;
+      char* p1 = pos; UCHAR dum, newadaptid;
       PARSEDEBUG(printk (KERN_INFO "DC390: chg adapt cfg \"%s\"\n", prstr (pos, &buffer[length]));)
       dum = GLITCH_TO_NS (pACB->glitch_cfg);
       /* Adapter setting */
       SEARCH (pos, p0, pACB->pScsiHost->max_id, "MAXID", 8); 
       SEARCH (pos, p0, pACB->pScsiHost->max_lun, "MAXLUN", 8); 
-      SEARCH (pos, p0, pACB->pScsiHost->this_id, "ADAPTERID", 7); 
+      SEARCH (pos, p0, newadaptid, "ADAPTERID", 7);
       SEARCH (pos, p0, pACB->TagMaxNum, "TAGMAXNUM", 32);
       SEARCH (pos, p0, pACB->ACBFlag, "ACBFLAG", 255);
       SEARCH3 (pos, p0, dum, "GLITCHEATER", 40, 1000, "NS");
       SEARCH3 (pos, p0, pACB->sel_timeout, "SELTIMEOUT", 400, 163, "MS");
+      SEARCH3 (pos, p0, dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY], "DELAYRESET", 180, 100, "S");
     ok2:
       pACB->glitch_cfg = NS_TO_GLITCH (dum);
       if (pACB->sel_timeout < 60) pACB->sel_timeout = 60;
-      dum = 0; while (1 << dum <= pACB->TagMaxNum) dum ++;
-      pACB->TagMaxNum &= (1 << --dum);
-      if (pos == p1) goto einv;
+      DC390_write8 (Scsi_TimeOut, pACB->sel_timeout);
+      if (newadaptid != pACB->pScsiHost->this_id)
+      {
+	pACB->pScsiHost->this_id = newadaptid;
+	dc390_ResetDevParam (pACB);
+      }	    
+      //dum = 0; while (1 << dum <= pACB->TagMaxNum) dum ++;
+      //pACB->TagMaxNum &= (1 << --dum);
       dc390_updateDCBs (pACB);
+      // All devs should be INQUIRED now
+      if (pos == p1) goto einv;
     }
   if (pos) goto next;
       
@@ -2351,7 +2737,15 @@
 	DC390_UNLOCK_IO;
      };
   return (length);
-  
+
+ dump:
+     {
+	dc390_dumpinfo (pACB, 0, 0);
+	DC390_UNLOCK_ACB;
+	DC390_UNLOCK_IO;       
+     }
+  return (length);
+	
  inquiry:
      {
 	pos = strtok (0, " \t\n.:;="); if (!pos) goto einv;
@@ -2359,7 +2753,7 @@
 	if (dev >= pACB->DCBCnt) goto einv_dev;
 	for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB;
 	printk (KERN_NOTICE " DC390: Issue INQUIRY command to Dev(Idx) %i SCSI ID %i LUN %i\n",
-		dev, pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
+		dev, pDCB->TargetID, pDCB->TargetLUN);
 	DC390_UNLOCK_ACB;
 	dc390_inquiry (pACB, pDCB);
 	DC390_UNLOCK_IO;
@@ -2373,13 +2767,45 @@
 	if (dev >= pACB->DCBCnt) goto einv_dev;
 	for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB;
 	printk (KERN_NOTICE " DC390: Remove DCB for Dev(Idx) %i SCSI ID %i LUN %i\n",
-		dev, pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
+		dev, pDCB->TargetID, pDCB->TargetLUN);
+	/* TO DO: We should make sure no pending commands are left */
 	dc390_remove_dev (pACB, pDCB);
 	DC390_UNLOCK_ACB;
 	DC390_UNLOCK_IO;
      };
    return (length);
 
+ add:
+     {
+	int id, lun;
+	pos = strtok (0, " \t\n.:;=");
+	if (pos) { SCANF (pos, p0, id, 0, 7); } else goto einv;
+	if (pos) { SCANF (pos, p0, lun, 0, 7); } else goto einv;
+	pDCB = dc390_findDCB (pACB, id, lun);
+	if (pDCB) { printk ("DC390: ADD: Device already existing\n"); goto einv; };
+	dc390_initDCB (pACB, &pDCB, id, lun);
+	DC390_UNLOCK_ACB;
+	dc390_inquiry (pACB, pDCB);
+	DC390_UNLOCK_IO;
+     };
+   return (length);
+
+ start:
+     {
+	int id, lun;
+	pos = strtok (0, " \t\n.:;=");
+	if (pos) { SCANF (pos, p0, id, 0, 7); } else goto einv;
+	if (pos) { SCANF (pos, p0, lun, 0, 7); } else goto einv;
+	pDCB = dc390_findDCB (pACB, id, lun);
+	if (pDCB) printk ("DC390: SendStart: Device already existing ...\n");
+	else dc390_initDCB (pACB, &pDCB, id, lun);
+	DC390_UNLOCK_ACB;
+	dc390_sendstart (pACB, pDCB);
+	dc390_inquiry (pACB, pDCB);
+	DC390_UNLOCK_IO;
+     };
+   return (length);
+
  einv_dev:
    printk (KERN_WARNING "DC390: Ignore cmnd to illegal Dev(Idx) %i. Valid range: 0 - %i.\n", 
 	   dev, pACB->DCBCnt - 1);
@@ -2429,6 +2855,7 @@
   PSH shpnt;
   PACB pACB;
   PDCB pDCB;
+  PSCSICMD pcmd;
   DC390_AFLAGS
 
   pACB = dc390_pACB_start;
@@ -2454,46 +2881,87 @@
   SPRINTF("SCSI Host Nr %i, ", shpnt->host_no);
   SPRINTF("%s Adapter Nr %i\n", dc390_adapname, pACB->AdapterIndex);
   SPRINTF("IOPortBase 0x%04x, ", pACB->IOPortBase);
-  SPRINTF("IRQLevel 0x%02x\n", pACB->IRQLevel);
+  SPRINTF("IRQ %02i\n", pACB->IRQLevel);
 
   SPRINTF("MaxID %i, MaxLUN %i, ", shpnt->max_id, shpnt->max_lun);
-  SPRINTF("AdapterID %i, SelTimeout %i ms\n", 
-	  shpnt->this_id, (pACB->sel_timeout*164)/100);
+  SPRINTF("AdapterID %i, SelTimeout %i ms, DelayReset %i s\n", 
+	  shpnt->this_id, (pACB->sel_timeout*164)/100,
+	  dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]);
 
-  SPRINTF("TagMaxNum %i, Status %i, ACBFlag %i, GlitchEater %i ns\n",
+  SPRINTF("TagMaxNum %i, Status 0x%02x, ACBFlag 0x%02x, GlitchEater %i ns\n",
 	  pACB->TagMaxNum, pACB->status, pACB->ACBFlag, GLITCH_TO_NS(pACB->glitch_cfg)*12);
 
-  SPRINTF("Statistics: Cmnds %li, Cmnds not sent directly %li, Out of SRB conds %li\n",
+  SPRINTF("Statistics: Cmnds %li, Cmnds not sent directly %i, Out of SRB conds %i\n",
 	  pACB->Cmds, pACB->CmdInQ, pACB->CmdOutOfSRB);
-  SPRINTF("            Lost arbitrations %li\n", pACB->SelLost);
+  SPRINTF("            Lost arbitrations %i, Sel. connected %i, Connected: %s\n", 
+	  pACB->SelLost, pACB->SelConn, pACB->Connected? "Yes": "No");
    
   SPRINTF("Nr of attached devices: %i, Nr of DCBs: %i\n", pACB->DeviceCnt, pACB->DCBCnt);
+  SPRINTF("Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n",
+	  pACB->DCBmap[0], pACB->DCBmap[1], pACB->DCBmap[2], pACB->DCBmap[3], 
+	  pACB->DCBmap[4], pACB->DCBmap[5], pACB->DCBmap[6], pACB->DCBmap[7]);
 
-  SPRINTF("Idx ID LUN Prty Sync DsCn SndS TagQ STOP NegoPeriod SyncSpeed SyncOffs\n");
+  SPRINTF("Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs MaxCmd\n");
 
   pDCB = pACB->pLinkDCB;
   for (dev = 0; dev < pACB->DCBCnt; dev++)
      {
-      SPRINTF("%02i  %02i  %02i ", dev, pDCB->UnitSCSIID, pDCB->UnitSCSILUN);
+      SPRINTF("%02i  %02i  %02i ", dev, pDCB->TargetID, pDCB->TargetLUN);
       YESNO(pDCB->DevMode & PARITY_CHK_);
       YESNO(pDCB->SyncMode & SYNC_NEGO_DONE);
       YESNO(pDCB->DevMode & EN_DISCONNECT_);
-      //YESNO(pDCB->SyncMode & EN_ATN_STOP);
       YESNO(pDCB->DevMode & SEND_START_);
       YESNO(pDCB->SyncMode & EN_TAG_QUEUEING);
-      YESNO(pDCB->SyncMode & EN_ATN_STOP);
       if (pDCB->SyncOffset & 0x0f)
       {
 	 int sp = pDCB->SyncPeriod; if (! (pDCB->CtrlR3 & FAST_SCSI)) sp++;
 	 SPRINTF("  %03i ns ", (pDCB->NegoPeriod) << 2);
 	 spd = 40/(sp); spd1 = 40%(sp);
 	 spd1 = (spd1 * 10 + sp/2) / (sp);
-	 SPRINTF("   %2i.%1i M      %02i\n", spd, spd1, (pDCB->SyncOffset & 0x0f));
+	 SPRINTF("   %2i.%1i M      %02i", spd, spd1, (pDCB->SyncOffset & 0x0f));
       }
-      else SPRINTF(" (%03i ns)\n", (pDCB->NegoPeriod) << 2);
+      else SPRINTF(" (%03i ns)                 ", (pDCB->NegoPeriod) << 2);
       /* Add more info ...*/
+      SPRINTF ("      %02i\n", pDCB->MaxCommand);
       pDCB = pDCB->pNextDCB;
      }
+    SPRINTF ("Commands in Queues: Query: %li:", pACB->QueryCnt);
+    for (pcmd = pACB->pQueryHead; pcmd; pcmd = pcmd->next)
+	SPRINTF (" %li", pcmd->pid);
+    if (timer_pending(&pACB->Waiting_Timer)) SPRINTF ("Waiting queue timer running\n");
+    else SPRINTF ("\n");
+    pDCB = pACB->pLinkDCB;
+	
+    for (dev = 0; dev < pACB->DCBCnt; dev++)
+    {
+	PSRB pSRB;
+	if (pDCB->WaitSRBCnt) 
+		    SPRINTF ("DCB (%02i-%i): Waiting: %i:", pDCB->TargetID, pDCB->TargetLUN,
+			     pDCB->WaitSRBCnt);
+	for (pSRB = pDCB->pWaitingSRB; pSRB; pSRB = pSRB->pNextSRB)
+		SPRINTF(" %li", pSRB->pcmd->pid);
+	if (pDCB->GoingSRBCnt) 
+		    SPRINTF ("\nDCB (%02i-%i): Going  : %i:", pDCB->TargetID, pDCB->TargetLUN,
+			     pDCB->GoingSRBCnt);
+	for (pSRB = pDCB->pGoingSRB; pSRB; pSRB = pSRB->pNextSRB)
+#if 0 //def DC390_DEBUGTRACE
+		SPRINTF(" %s\n  ", pSRB->debugtrace);
+#else
+		SPRINTF(" %li", pSRB->pcmd->pid);
+#endif
+	if (pDCB->WaitSRBCnt || pDCB->GoingSRBCnt) SPRINTF ("\n");
+	pDCB = pDCB->pNextDCB;
+    }
+	
+#ifdef DC390_DEBUGDCB
+    SPRINTF ("DCB list for ACB %p:\n", pACB);
+    pDCB = pACB->pLinkDCB;
+    SPRINTF ("%p", pDCB);
+    for (dev = 0; dev < pACB->DCBCnt; dev++, pDCB=pDCB->pNextDCB)
+	SPRINTF ("->%p", pDCB->pNextDCB);
+    SPRINTF("\n");
+#endif
+  
 
   DC390_UNLOCK_ACB;
   *start = buffer + offset;
@@ -2528,13 +2996,14 @@
 
     printk(KERN_INFO "DC390: shutdown\n");
 
-    pACB->ACBFlag = RESET_DONE;
+    pACB->ACBFlag = RESET_DEV;
     bval = DC390_read8 (CtrlReg1);
     bval |= DIS_INT_ON_SCSI_RST;
     DC390_write8 (CtrlReg1, bval);	/* disable interrupt */
     if (pACB->Gmode2 & RST_SCSI_BUS)
 		dc390_ResetSCSIBus (pACB);
 
+    if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer);
     return( 0 );
 }
 
@@ -2548,41 +3017,30 @@
     do
     {
 	nDCB = pDCB->pNextDCB;
-	DCBDEBUG(printk (KERN_INFO "DC390: Free DCB (ID %i, LUN %i): 0x%08x\n",\
-		pDCB->UnitSCSIID, pDCB->UnitSCSILUN, (int)pDCB);)
-	kfree (pDCB);
+	DCBDEBUG(printk (KERN_INFO "DC390: Free DCB (ID %i, LUN %i): %p\n",\
+		pDCB->TargetID, pDCB->TargetLUN, pDCB);)
+	//kfree (pDCB);
+	dc390_remove_dev (pACB, pDCB);
 	pDCB = nDCB;
-    } while (pDCB && pDCB != pACB->pLinkDCB);
+    } while (pDCB && pACB->pLinkDCB);
 
 };
 
-int DC390_release(struct Scsi_Host *host)
+int DC390_release (struct Scsi_Host *host)
 {
-    int irq_count; 
-    PACB pACB;
     DC390_AFLAGS DC390_IFLAGS
-#if USE_SPINLOCKS > 1
     PACB pACB = (PACB)(host->hostdata);
-#endif
 
     DC390_LOCK_IO;
     DC390_LOCK_ACB;
 
+    /* TO DO: We should check for outstanding commands first. */
     dc390_shutdown (host);
 
     if (host->irq != IRQ_NONE)
     {
-	for (irq_count = 0, pACB = dc390_pACB_start; 
-	     pACB; pACB = pACB->pNextACB)
-	{
-	    if ( pACB->IRQLevel == host->irq )
-		++irq_count;
-	}
-	if (irq_count == 1)
-	 {
-	    DEBUG0(printk(KERN_INFO "DC390: Free IRQ %i\n",host->irq);)
-	    free_irq(host->irq,NULL);
-	 }
+	DEBUG0(printk(KERN_INFO "DC390: Free IRQ %i\n",host->irq);)
+	free_irq (host->irq, pACB);
     }
 
     release_region(host->io_port,host->n_io_port);
@@ -2591,7 +3049,12 @@
     DC390_UNLOCK_IO;
     return( 1 );
 }
+#endif /* def MODULE */
 
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,99)
+static Scsi_Host_Template driver_template = DC390_T;
+#include "scsi_module.c"
+#elif defined(MODULE)
 Scsi_Host_Template driver_template = DC390_T;
 #include "scsi_module.c"
-#endif /* def MODULE */
+#endif

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)