patch-2.4.21 linux-2.4.21/drivers/scsi/cpqfcTSinit.c

Next file: linux-2.4.21/drivers/scsi/cpqfcTSioctl.h
Previous file: linux-2.4.21/drivers/scsi/cpqfcTSi2c.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/drivers/scsi/cpqfcTSinit.c linux-2.4.21/drivers/scsi/cpqfcTSinit.c
@@ -29,8 +29,6 @@
 */
 
 
-#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
-
 #include <linux/blk.h>
 #include <linux/kernel.h>
 #include <linux/string.h>
@@ -39,17 +37,17 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
-#include <linux/ioport.h>  // request_region() prototype
-#include <linux/vmalloc.h> // ioremap()
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,7)
+#include <linux/ioport.h>	// request_region() prototype
+#include <linux/slab.h>
+#include <linux/vmalloc.h>	// ioremap()
 #include <linux/completion.h>
-#endif
+#include <linux/init.h>
 #ifdef __alpha__
 #define __KERNEL_SYSCALLS__
 #endif
 #include <asm/unistd.h>
 #include <asm/io.h>
-#include <asm/uaccess.h>   // ioctl related
+#include <asm/uaccess.h>	// ioctl related
 #include <asm/irq.h>
 #include <linux/spinlock.h>
 #include "sd.h"
@@ -61,48 +59,21 @@
 
 #include "cpqfcTS.h"
 
-#include <linux/config.h>  
+#include <linux/config.h>
 #include <linux/module.h>
-#include <linux/version.h> 
+#include <linux/version.h>
 
 /* Embedded module documentation macros - see module.h */
 MODULE_AUTHOR("Compaq Computer Corporation");
-MODULE_DESCRIPTION("Driver for Compaq 64-bit/66Mhz PCI Fibre Channel HBA v. 2.1.1");
+MODULE_DESCRIPTION("Driver for Compaq 64-bit/66Mhz PCI Fibre Channel HBA v. 2.1.2");
 MODULE_LICENSE("GPL");
-  
-int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev, unsigned int reset_flags);
-
-// This struct was originally defined in 
-// /usr/src/linux/include/linux/proc_fs.h
-// since it's only partially implemented, we only use first
-// few fields...
-// NOTE: proc_fs changes in 2.4 kernel
-
-#if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
-static struct proc_dir_entry proc_scsi_cpqfcTS =
-{
-  PROC_SCSI_CPQFCTS,           // ushort low_ino (enumerated list)
-  7,                           // ushort namelen
-  DEV_NAME,                    // const char* name
-  S_IFDIR | S_IRUGO | S_IXUGO, // mode_t mode
-  2                            // nlink_t nlink
-	                       // etc. ...
-};
 
+int cpqfcTS_TargetDeviceReset(Scsi_Device * ScsiDev, unsigned int reset_flags);
 
-#endif
-
-#if LINUX_VERSION_CODE >= LinuxVersionCode(2,4,7)
-#  define CPQFC_DECLARE_COMPLETION(x) DECLARE_COMPLETION(x)
-#  define CPQFC_WAITING waiting
-#  define CPQFC_COMPLETE(x) complete(x)
-#  define CPQFC_WAIT_FOR_COMPLETION(x) wait_for_completion(x);
-#else
-#  define CPQFC_DECLARE_COMPLETION(x) DECLARE_MUTEX_LOCKED(x)
-#  define CPQFC_WAITING sem
-#  define CPQFC_COMPLETE(x) up(x)
-#  define CPQFC_WAIT_FOR_COMPLETION(x) down(x)
-#endif
+#define CPQFC_DECLARE_COMPLETION(x) DECLARE_COMPLETION(x)
+#define CPQFC_WAITING waiting
+#define CPQFC_COMPLETE(x) complete(x)
+#define CPQFC_WAIT_FOR_COMPLETION(x) wait_for_completion(x);
 
 /* local function to load our per-HBA (local) data for chip
    registers, FC link state, all FC exchanges, etc.
@@ -112,120 +83,86 @@
    Name) are not necessary.
    
 */
-static void Cpqfc_initHBAdata( CPQFCHBA *cpqfcHBAdata, struct pci_dev *PciDev )
+static void Cpqfc_initHBAdata(CPQFCHBA * cpqfcHBAdata, struct pci_dev *PciDev)
 {
-             
-  cpqfcHBAdata->PciDev = PciDev; // copy PCI info ptr
 
-  // since x86 port space is 64k, we only need the lower 16 bits
-  cpqfcHBAdata->fcChip.Registers.IOBaseL = 
-    PciDev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
-  
-  cpqfcHBAdata->fcChip.Registers.IOBaseU = 
-    PciDev->resource[2].start & PCI_BASE_ADDRESS_IO_MASK;
-  
-  // 32-bit memory addresses
-  cpqfcHBAdata->fcChip.Registers.MemBase = 
-    PciDev->resource[3].start & PCI_BASE_ADDRESS_MEM_MASK;
-
-  cpqfcHBAdata->fcChip.Registers.ReMapMemBase = 
-    ioremap( PciDev->resource[3].start & PCI_BASE_ADDRESS_MEM_MASK,
-             0x200);
-  
-  cpqfcHBAdata->fcChip.Registers.RAMBase = 
-    PciDev->resource[4].start;
-  
-  cpqfcHBAdata->fcChip.Registers.SROMBase =  // NULL for HP TS adapter
-    PciDev->resource[5].start;
-  
-  // now the Tachlite chip registers
-  // the REGISTER struct holds both the physical address & last
-  // written value (some TL registers are WRITE ONLY)
-
-  cpqfcHBAdata->fcChip.Registers.SFQconsumerIndex.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_SFQ_CONSUMER_INDEX;
-
-  cpqfcHBAdata->fcChip.Registers.ERQproducerIndex.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_ERQ_PRODUCER_INDEX;
-      
-  // TL Frame Manager
-  cpqfcHBAdata->fcChip.Registers.FMconfig.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_CONFIG;
-  cpqfcHBAdata->fcChip.Registers.FMcontrol.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_CONTROL;
-  cpqfcHBAdata->fcChip.Registers.FMstatus.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_STATUS;
-  cpqfcHBAdata->fcChip.Registers.FMLinkStatus1.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_LINK_STAT1;
-  cpqfcHBAdata->fcChip.Registers.FMLinkStatus2.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_LINK_STAT2;
-  cpqfcHBAdata->fcChip.Registers.FMBB_CreditZero.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_BB_CREDIT0;
-      
-      // TL Control Regs
-  cpqfcHBAdata->fcChip.Registers.TYconfig.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_TACH_CONFIG;
-  cpqfcHBAdata->fcChip.Registers.TYcontrol.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_TACH_CONTROL;
-  cpqfcHBAdata->fcChip.Registers.TYstatus.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_TACH_STATUS;
-  cpqfcHBAdata->fcChip.Registers.rcv_al_pa.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_RCV_AL_PA;
-  cpqfcHBAdata->fcChip.Registers.ed_tov.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_ED_TOV;
-
-
-  cpqfcHBAdata->fcChip.Registers.INTEN.address = 
-	        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + IINTEN;
-  cpqfcHBAdata->fcChip.Registers.INTPEND.address = 
-	        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + IINTPEND;
-  cpqfcHBAdata->fcChip.Registers.INTSTAT.address = 
-        cpqfcHBAdata->fcChip.Registers.ReMapMemBase + IINTSTAT;
-
-  DEBUG_PCI(printk("  cpqfcHBAdata->fcChip.Registers. :\n"));
-  DEBUG_PCI(printk("    IOBaseL = %x\n", 
-    cpqfcHBAdata->fcChip.Registers.IOBaseL));
-  DEBUG_PCI(printk("    IOBaseU = %x\n", 
-    cpqfcHBAdata->fcChip.Registers.IOBaseU));
-  
-  printk(" ioremap'd Membase: %p\n", cpqfcHBAdata->fcChip.Registers.ReMapMemBase);
-  
-  DEBUG_PCI(printk("    SFQconsumerIndex.address = %p\n", 
-    cpqfcHBAdata->fcChip.Registers.SFQconsumerIndex.address));
-  DEBUG_PCI(printk("    ERQproducerIndex.address = %p\n", 
-    cpqfcHBAdata->fcChip.Registers.ERQproducerIndex.address));
-  DEBUG_PCI(printk("    TYconfig.address = %p\n", 
-    cpqfcHBAdata->fcChip.Registers.TYconfig.address));
-  DEBUG_PCI(printk("    FMconfig.address = %p\n", 
-    cpqfcHBAdata->fcChip.Registers.FMconfig.address));
-  DEBUG_PCI(printk("    FMcontrol.address = %p\n", 
-    cpqfcHBAdata->fcChip.Registers.FMcontrol.address));
-
-  // set default options for FC controller (chip)
-  cpqfcHBAdata->fcChip.Options.initiator = 1;  // default: SCSI initiator
-  cpqfcHBAdata->fcChip.Options.target = 0;     // default: SCSI target
-  cpqfcHBAdata->fcChip.Options.extLoopback = 0;// default: no loopback @GBIC
-  cpqfcHBAdata->fcChip.Options.intLoopback = 0;// default: no loopback inside chip
-
-  // set highest and lowest FC-PH version the adapter/driver supports
-  // (NOT strict compliance)
-  cpqfcHBAdata->fcChip.highest_FCPH_ver = FC_PH3;
-  cpqfcHBAdata->fcChip.lowest_FCPH_ver = FC_PH43;
-
-  // set function points for this controller / adapter
-  cpqfcHBAdata->fcChip.ResetTachyon = CpqTsResetTachLite;
-  cpqfcHBAdata->fcChip.FreezeTachyon = CpqTsFreezeTachlite;
-  cpqfcHBAdata->fcChip.UnFreezeTachyon = CpqTsUnFreezeTachlite;
-  cpqfcHBAdata->fcChip.CreateTachyonQues = CpqTsCreateTachLiteQues;
-  cpqfcHBAdata->fcChip.DestroyTachyonQues = CpqTsDestroyTachLiteQues;
-  cpqfcHBAdata->fcChip.InitializeTachyon = CpqTsInitializeTachLite;  
-  cpqfcHBAdata->fcChip.LaserControl = CpqTsLaserControl;  
-  cpqfcHBAdata->fcChip.ProcessIMQEntry = CpqTsProcessIMQEntry;
-  cpqfcHBAdata->fcChip.InitializeFrameManager = CpqTsInitializeFrameManager;;  
-  cpqfcHBAdata->fcChip.ReadWriteWWN = CpqTsReadWriteWWN;
-  cpqfcHBAdata->fcChip.ReadWriteNVRAM = CpqTsReadWriteNVRAM;
+	cpqfcHBAdata->PciDev = PciDev;	// copy PCI info ptr
+
+	// since x86 port space is 64k, we only need the lower 16 bits
+	cpqfcHBAdata->fcChip.Registers.IOBaseL = PciDev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
+	cpqfcHBAdata->fcChip.Registers.IOBaseU = PciDev->resource[2].start & PCI_BASE_ADDRESS_IO_MASK;
+
+	// 32-bit memory addresses
+	cpqfcHBAdata->fcChip.Registers.MemBase = PciDev->resource[3].start & PCI_BASE_ADDRESS_MEM_MASK;
+	cpqfcHBAdata->fcChip.Registers.ReMapMemBase = ioremap(PciDev->resource[3].start & PCI_BASE_ADDRESS_MEM_MASK, 0x200);
+	cpqfcHBAdata->fcChip.Registers.RAMBase = PciDev->resource[4].start;
+	cpqfcHBAdata->fcChip.Registers.SROMBase = PciDev->resource[5].start; // NULL for HP TS adapter
+
+	// now the Tachlite chip registers
+	// the REGISTER struct holds both the physical address & last
+	// written value (some TL registers are WRITE ONLY)
+
+	cpqfcHBAdata->fcChip.Registers.SFQconsumerIndex.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_SFQ_CONSUMER_INDEX;
+
+	cpqfcHBAdata->fcChip.Registers.ERQproducerIndex.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_ERQ_PRODUCER_INDEX;
+
+	// TL Frame Manager
+	cpqfcHBAdata->fcChip.Registers.FMconfig.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_CONFIG;
+	cpqfcHBAdata->fcChip.Registers.FMcontrol.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_CONTROL;
+	cpqfcHBAdata->fcChip.Registers.FMstatus.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_STATUS;
+	cpqfcHBAdata->fcChip.Registers.FMLinkStatus1.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_LINK_STAT1;
+	cpqfcHBAdata->fcChip.Registers.FMLinkStatus2.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_LINK_STAT2;
+	cpqfcHBAdata->fcChip.Registers.FMBB_CreditZero.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_BB_CREDIT0;
+
+	// TL Control Regs
+	cpqfcHBAdata->fcChip.Registers.TYconfig.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_TACH_CONFIG;
+	cpqfcHBAdata->fcChip.Registers.TYcontrol.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_TACH_CONTROL;
+	cpqfcHBAdata->fcChip.Registers.TYstatus.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_TACH_STATUS;
+	cpqfcHBAdata->fcChip.Registers.rcv_al_pa.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_RCV_AL_PA;
+	cpqfcHBAdata->fcChip.Registers.ed_tov.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + TL_MEM_FM_ED_TOV;
+
+
+	cpqfcHBAdata->fcChip.Registers.INTEN.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + IINTEN;
+	cpqfcHBAdata->fcChip.Registers.INTPEND.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + IINTPEND;
+	cpqfcHBAdata->fcChip.Registers.INTSTAT.address = cpqfcHBAdata->fcChip.Registers.ReMapMemBase + IINTSTAT;
+
+	DEBUG_PCI(printk("  cpqfcHBAdata->fcChip.Registers. :\n"));
+	DEBUG_PCI(printk("    IOBaseL = %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseL));
+	DEBUG_PCI(printk("    IOBaseU = %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseU));
+
+	printk(" ioremap'd Membase: %p\n", cpqfcHBAdata->fcChip.Registers.ReMapMemBase);
+
+	DEBUG_PCI(printk("    SFQconsumerIndex.address = %p\n", cpqfcHBAdata->fcChip.Registers.SFQconsumerIndex.address));
+	DEBUG_PCI(printk("    ERQproducerIndex.address = %p\n", cpqfcHBAdata->fcChip.Registers.ERQproducerIndex.address));
+	DEBUG_PCI(printk("    TYconfig.address = %p\n", cpqfcHBAdata->fcChip.Registers.TYconfig.address));
+	DEBUG_PCI(printk("    FMconfig.address = %p\n", cpqfcHBAdata->fcChip.Registers.FMconfig.address));
+	DEBUG_PCI(printk("    FMcontrol.address = %p\n", cpqfcHBAdata->fcChip.Registers.FMcontrol.address));
+
+	// set default options for FC controller (chip)
+	cpqfcHBAdata->fcChip.Options.initiator = 1;	// default: SCSI initiator
+	cpqfcHBAdata->fcChip.Options.target = 0;	// default: SCSI target
+	cpqfcHBAdata->fcChip.Options.extLoopback = 0;	// default: no loopback @GBIC
+	cpqfcHBAdata->fcChip.Options.intLoopback = 0;	// default: no loopback inside chip
+
+	// set highest and lowest FC-PH version the adapter/driver supports
+	// (NOT strict compliance)
+	cpqfcHBAdata->fcChip.highest_FCPH_ver = FC_PH3;
+	cpqfcHBAdata->fcChip.lowest_FCPH_ver = FC_PH43;
+
+	// set function points for this controller / adapter
+	cpqfcHBAdata->fcChip.ResetTachyon = CpqTsResetTachLite;
+	cpqfcHBAdata->fcChip.FreezeTachyon = CpqTsFreezeTachlite;
+	cpqfcHBAdata->fcChip.UnFreezeTachyon = CpqTsUnFreezeTachlite;
+	cpqfcHBAdata->fcChip.CreateTachyonQues = CpqTsCreateTachLiteQues;
+	cpqfcHBAdata->fcChip.DestroyTachyonQues = CpqTsDestroyTachLiteQues;
+	cpqfcHBAdata->fcChip.InitializeTachyon = CpqTsInitializeTachLite;
+	cpqfcHBAdata->fcChip.LaserControl = CpqTsLaserControl;
+	cpqfcHBAdata->fcChip.ProcessIMQEntry = CpqTsProcessIMQEntry;
+	cpqfcHBAdata->fcChip.InitializeFrameManager = CpqTsInitializeFrameManager;;
+	cpqfcHBAdata->fcChip.ReadWriteWWN = CpqTsReadWriteWWN;
+	cpqfcHBAdata->fcChip.ReadWriteNVRAM = CpqTsReadWriteNVRAM;
+
 
- 
 
 }
 
@@ -233,28 +170,27 @@
 /* (borrowed from linux/drivers/scsi/hosts.c) */
 static void launch_FCworker_thread(struct Scsi_Host *HostAdapter)
 {
-  DECLARE_MUTEX_LOCKED(sem);
+	DECLARE_MUTEX_LOCKED(sem);
+
+	CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) HostAdapter->hostdata;
+
+	ENTER("launch_FC_worker_thread");
 
-  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
+	cpqfcHBAdata->notify_wt = &sem;
 
-  ENTER("launch_FC_worker_thread");
-             
-  cpqfcHBAdata->notify_wt = &sem;
-
-  /* must unlock before kernel_thread(), for it may cause a reschedule. */
-  spin_unlock_irq(&io_request_lock);
-  kernel_thread((int (*)(void *))cpqfcTSWorkerThread, 
-                          (void *) HostAdapter, 0);
-  /*
-   * Now wait for the kernel error thread to initialize itself
-
-   */
-  down (&sem);
-  spin_lock_irq(&io_request_lock);
-  cpqfcHBAdata->notify_wt = NULL;
+	/* must unlock before kernel_thread(), for it may cause a reschedule. */
+	spin_unlock_irq(&io_request_lock);
+	kernel_thread((int (*)(void *)) cpqfcTSWorkerThread, (void *) HostAdapter, 0);
+	/*
+	 * Now wait for the kernel error thread to initialize itself
+
+	 */
+	down(&sem);
+	spin_lock_irq(&io_request_lock);
+	cpqfcHBAdata->notify_wt = NULL;
+
+	LEAVE("launch_FC_worker_thread");
 
-  LEAVE("launch_FC_worker_thread");
- 
 }
 
 
@@ -279,436 +215,398 @@
 };
 
 
-int cpqfcTS_detect(Scsi_Host_Template *ScsiHostTemplate)
+int cpqfcTS_detect(Scsi_Host_Template * ScsiHostTemplate)
 {
-  int NumberOfAdapters=0; // how many of our PCI adapters are found?
-  struct pci_dev *PciDev = NULL;
-  struct Scsi_Host *HostAdapter = NULL;
-  CPQFCHBA *cpqfcHBAdata = NULL; 
-  struct timer_list *cpqfcTStimer = NULL;
-  int i;
+	int NumberOfAdapters = 0;	// how many of our PCI adapters are found?
+	struct pci_dev *PciDev = NULL;
+	struct Scsi_Host *HostAdapter = NULL;
+	CPQFCHBA *cpqfcHBAdata = NULL;
+	struct timer_list *cpqfcTStimer = NULL;
+	int i;
 
-  ENTER("cpqfcTS_detect");
+	ENTER("cpqfcTS_detect");
 
 #if LINUX_VERSION_CODE < LinuxVersionCode(2,3,27)
-  ScsiHostTemplate->proc_dir = &proc_scsi_cpqfcTS;
+	ScsiHostTemplate->proc_dir = &proc_scsi_cpqfcTS;
 #else
-  ScsiHostTemplate->proc_name = "cpqfcTS";
+	ScsiHostTemplate->proc_name = "cpqfcTS";
 #endif
 
-  if( pci_present() == 0) // no PCI busses?
-  {
-    printk( "  no PCI bus?@#!\n");
-    return NumberOfAdapters;
-  }
-
-  for( i=0; i < HBA_TYPES; i++)
-  {
-    // look for all HBAs of each type
-
-    while((PciDev = pci_find_device(cpqfc_boards[i].vendor_id,
-				    cpqfc_boards[i].device_id, PciDev)))
-    {
-
-      if (pci_set_dma_mask(PciDev, CPQFCTS_DMA_MASK) != 0) {
-	printk(KERN_WARNING 
-		"cpqfc: HBA cannot support required DMA mask, skipping.\n");
-	continue;
-      }
-
-      // NOTE: (kernel 2.2.12-32) limits allocation to 128k bytes...
-      printk(" scsi_register allocating %d bytes for FC HBA\n",
-		      (ULONG)sizeof(CPQFCHBA));
-
-      HostAdapter = scsi_register( ScsiHostTemplate, sizeof( CPQFCHBA ) );
-      
-      if(HostAdapter == NULL)
-      	continue;
-      DEBUG_PCI( printk("  HBA found!\n"));
-      DEBUG_PCI( printk("  HostAdapter->PciDev->irq = %u\n", PciDev->irq) );
-      DEBUG_PCI(printk("  PciDev->baseaddress[0]= %lx\n", 
-				PciDev->resource[0].start));
-      DEBUG_PCI(printk("  PciDev->baseaddress[1]= %lx\n", 
-				PciDev->resource[1].start));
-      DEBUG_PCI(printk("  PciDev->baseaddress[2]= %lx\n", 
-				PciDev->resource[2].start));
-      DEBUG_PCI(printk("  PciDev->baseaddress[3]= %lx\n", 
-				PciDev->resource[3].start));
-
-      scsi_set_pci_device(HostAdapter, PciDev);      
-      HostAdapter->irq = PciDev->irq;  // copy for Scsi layers
-      
-      // HP Tachlite uses two (255-byte) ranges of Port I/O (lower & upper),
-      // for a total I/O port address space of 512 bytes.
-      // mask out the I/O port address (lower) & record
-      HostAdapter->io_port = (unsigned int)
-	     PciDev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
-      HostAdapter->n_io_port = 0xff;
-      
-      // i.e., expect 128 targets (arbitrary number), while the
-      //  RA-4000 supports 32 LUNs
-      HostAdapter->max_id =  0;   // incremented as devices log in    
-      HostAdapter->max_lun = CPQFCTS_MAX_LUN;         // LUNs per FC device
-      HostAdapter->max_channel = CPQFCTS_MAX_CHANNEL; // multiple busses?
-      
-      // get the pointer to our HBA specific data... (one for
-      // each HBA on the PCI bus(ses)).
-      cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
-      
-      // make certain our data struct is clear
-      memset( cpqfcHBAdata, 0, sizeof( CPQFCHBA ) );
-
-
-      // initialize our HBA info
-      cpqfcHBAdata->HBAnum = NumberOfAdapters;
-
-      cpqfcHBAdata->HostAdapter = HostAdapter; // back ptr
-      Cpqfc_initHBAdata( cpqfcHBAdata, PciDev ); // fill MOST fields
-     
-      cpqfcHBAdata->HBAnum = NumberOfAdapters;
-      cpqfcHBAdata->hba_spinlock = SPIN_LOCK_UNLOCKED;
-
-      // request necessary resources and check for conflicts
-      if( request_irq( HostAdapter->irq,
-		       cpqfcTS_intr_handler,
-	               SA_INTERRUPT | SA_SHIRQ,
-	               DEV_NAME,
-		       HostAdapter) )
-      {
-	printk(" IRQ %u already used\n", HostAdapter->irq);
-        scsi_unregister( HostAdapter);
-	continue;
-      }
-
-      // Since we have two 256-byte I/O port ranges (upper
-      // and lower), check them both
-      if( check_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff) )
-      {
-	printk("  cpqfcTS address in use: %x\n", 
-			cpqfcHBAdata->fcChip.Registers.IOBaseU);
-	free_irq( HostAdapter->irq, HostAdapter);
-        scsi_unregister( HostAdapter);
-	continue;
-      }	
-      
-      if( check_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff) )
-      {
-  	printk("  cpqfcTS address in use: %x\n", 
-	      			cpqfcHBAdata->fcChip.Registers.IOBaseL);
-	free_irq( HostAdapter->irq, HostAdapter);
-        scsi_unregister( HostAdapter);
-	continue;
-      }	
-      
-      // OK, we should be able to grab everything we need now.
-      request_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff, DEV_NAME);
-      request_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff, DEV_NAME);
-      DEBUG_PCI(printk("  Requesting 255 I/O addresses @ %x\n",
-        cpqfcHBAdata->fcChip.Registers.IOBaseL ));
-      DEBUG_PCI(printk("  Requesting 255 I/O addresses @ %x\n",
-        cpqfcHBAdata->fcChip.Registers.IOBaseU ));
-
-      
-      // start our kernel worker thread
-
-      launch_FCworker_thread(HostAdapter);
-
-
-      // start our TimerTask...
-
-      cpqfcTStimer = &cpqfcHBAdata->cpqfcTStimer;
-
-      init_timer( cpqfcTStimer); // Linux clears next/prev values
-      cpqfcTStimer->expires = jiffies + HZ; // one second
-      cpqfcTStimer->data = (unsigned long)cpqfcHBAdata; // this adapter
-      cpqfcTStimer->function = cpqfcTSheartbeat; // handles timeouts, housekeeping
-
-      add_timer( cpqfcTStimer);  // give it to Linux
-
-
-      // now initialize our hardware...
-      if (cpqfcHBAdata->fcChip.InitializeTachyon( cpqfcHBAdata, 1,1)) {
-	printk(KERN_WARNING "cpqfc: initialization of HBA hardware failed.\n");
-	// FIXME: might want to do something better than nothing here.
-      }
-
-      cpqfcHBAdata->fcStatsTime = jiffies;  // (for FC Statistics delta)
-      
-      // give our HBA time to initialize and login current devices...
-      {
-	// The Brocade switch (e.g. 2400, 2010, etc.) as of March 2000,
-	// has the following algorithm for FL_Port startup:
-	// Time(sec) Action
-	// 0:        Device Plugin and LIP(F7,F7) transmission
-	// 1.0       LIP incoming
-        // 1.027     LISA incoming, no CLS! (link not up)
-	// 1.028     NOS incoming (switch test for N_Port)
-        // 1.577     ED_TOV expired, transmit LIPs again	
-	// 3.0       LIP(F8,F7) incoming (switch passes Tach Prim.Sig)
-	// 3.028     LILP received, link up, FLOGI starts
-	// slowest(worst) case, measured on 1Gb Finisar GT analyzer
-	
-	unsigned long stop_time;
-
-        spin_unlock_irq(&io_request_lock);
-	stop_time = jiffies + 4*HZ;
-        while ( time_before(jiffies, stop_time) ) 
-	  	schedule();  // (our worker task needs to run)
+	if (pci_present() == 0)	// no PCI busses?
+	{
+		printk("  no PCI bus?@#!\n");
+		return NumberOfAdapters;
+	}
 
-	spin_lock_irq(&io_request_lock);
-      }
-      
-      NumberOfAdapters++; 
-    } // end of while()
-  }
-
-  LEAVE("cpqfcTS_detect");
- 
-  return NumberOfAdapters;
-}
-
-static void my_ioctl_done (Scsi_Cmnd * SCpnt)
-{
-    struct request * req;
-    
-    req = &SCpnt->request;
-    req->rq_status = RQ_SCSI_DONE; /* Busy, but indicate request done */
-  
-    if (req->CPQFC_WAITING != NULL)
-	CPQFC_COMPLETE(req->CPQFC_WAITING);
-}   
-
-
-
-int cpqfcTS_ioctl( Scsi_Device *ScsiDev, int Cmnd, void *arg)
-{
-  int result = 0;
-  struct Scsi_Host *HostAdapter = ScsiDev->host;
-  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  PFC_LOGGEDIN_PORT pLoggedInPort;
-  Scsi_Cmnd DumCmnd;
-  int i, j;
-  VENDOR_IOCTL_REQ ioc;
-  cpqfc_passthru_t *vendor_cmd;
-  Scsi_Device *SDpnt;
-  Scsi_Cmnd *ScsiPassThruCmnd;
-
-  ENTER("cpqfcTS_ioctl ");
-  
-  // can we find an FC device mapping to this SCSI target?
-  DumCmnd.channel = ScsiDev->channel;		// For searching
-  DumCmnd.target  = ScsiDev->id;
-  pLoggedInPort = fcFindLoggedInPort( fcChip,
-    &DumCmnd, // search Scsi Nexus
-    0,        // DON'T search linked list for FC port id
-    NULL,     // DON'T search linked list for FC WWN
-    NULL);    // DON'T care about end of list
- 
-  if( pLoggedInPort == NULL )      // not found!
-  {
-    result = -ENXIO;
-  }
- 
-  else  // we know what FC device to operate on...
-  {
-	// printk("ioctl CMND %d", Cmnd);
-    switch (Cmnd) 
-    {
-      // Passthrough provides a mechanism to bypass the RAID
-      // or other controller and talk directly to the devices
-      // (e.g. physical disk drive)
-      // Passthrough commands, unfortunately, tend to be vendor
-      // specific; this is tailored to COMPAQ's RAID (RA4x00)
-      case CPQFCTS_SCSI_PASSTHRU:
-      {
-	void *buf = NULL; // for kernel space buffer for user data
-	
-	if( !arg)
-	  return -EINVAL;
-
-	// must be super user to send stuff directly to the
-	// controller and/or physical drives...
-	if( !suser() )
-	  return -EPERM;
-
-	// copy the caller's struct to our space.
-        if( copy_from_user( &ioc, arg, sizeof( VENDOR_IOCTL_REQ)))
-		return( -EFAULT);
+	for (i = 0; i < HBA_TYPES; i++) {
+		// look for all HBAs of each type
 
-	vendor_cmd = ioc.argp;  // i.e., CPQ specific command struct
+		while ((PciDev = pci_find_device(cpqfc_boards[i].vendor_id, cpqfc_boards[i].device_id, PciDev))) {
 
-	// If necessary, grab a kernel/DMA buffer
-	if( vendor_cmd->len)
-	{
-  	  buf = kmalloc( vendor_cmd->len, GFP_KERNEL);
-	  if( !buf)
-	    return -ENOMEM;
-	}
-
-        // Now build a SCSI_CMND to pass down...
-	// This function allocates and sets Scsi_Cmnd ptrs such as
-	//  ->channel, ->target, ->host
-        ScsiPassThruCmnd = scsi_allocate_device(ScsiDev, 1, 1);
-
-        // Need data from user?
-	// make sure caller's buffer is in kernel space.
-	if( (vendor_cmd->rw_flag == VENDOR_WRITE_OPCODE) &&
-	    vendor_cmd->len)
-        if(  copy_from_user( buf, vendor_cmd->bufp, vendor_cmd->len))
-		return( -EFAULT);
-	    
-	// copy the CDB (if/when MAX_COMMAND_SIZE is 16, remove copy below)
-        memcpy( &ScsiPassThruCmnd->cmnd[0], 
-		&vendor_cmd->cdb[0], 
-		MAX_COMMAND_SIZE);  
-        // we want to copy all 16 bytes into the FCP-SCSI CDB,
-	// although the actual passthru only uses up to the
-	// first 12.
-	
-	ScsiPassThruCmnd->cmd_len = 16; // sizeof FCP-SCSI CDB
-
-	// Unfortunately, the SCSI command cmnd[] field has only
-	// 12 bytes.  Ideally the MAX_COMMAND_SIZE should be increased
-	// to 16 for newer Fibre Channel and SCSI-3 larger CDBs.
-	// However, to avoid a mandatory kernel rebuild, we use the SCp
-	// spare field to store the extra 4 bytes ( ugly :-(
+			if (pci_enable_device(PciDev) != 0) {
+				printk(KERN_WARNING "cpqfc: pci_enable_devive failed, skipping.\n");
+				continue;
+			}
+			if (pci_set_dma_mask(PciDev, CPQFCTS_DMA_MASK) != 0) {
+				printk(KERN_WARNING "cpqfc: HBA cannot support required DMA mask, skipping.\n");
+				continue;
+			}
+			// NOTE: (kernel 2.2.12-32) limits allocation to 128k bytes...
+			printk(" scsi_register allocating %d bytes for FC HBA\n", (u32) sizeof(CPQFCHBA));
+
+			HostAdapter = scsi_register(ScsiHostTemplate, sizeof(CPQFCHBA));
+
+			if (HostAdapter == NULL)
+				continue;
+			DEBUG_PCI(printk("  HBA found!\n"));
+			DEBUG_PCI(printk("  HostAdapter->PciDev->irq = %u\n", PciDev->irq));
+			DEBUG_PCI(printk("  PciDev->baseaddress[0]= %lx\n", PciDev->resource[0].start));
+			DEBUG_PCI(printk("  PciDev->baseaddress[1]= %lx\n", PciDev->resource[1].start));
+			DEBUG_PCI(printk("  PciDev->baseaddress[2]= %lx\n", PciDev->resource[2].start));
+			DEBUG_PCI(printk("  PciDev->baseaddress[3]= %lx\n", PciDev->resource[3].start));
+
+			scsi_set_pci_device(HostAdapter, PciDev);
+			HostAdapter->irq = PciDev->irq;	// copy for Scsi layers
+
+			// HP Tachlite uses two (255-byte) ranges of Port I/O (lower & upper),
+			// for a total I/O port address space of 512 bytes.
+			// mask out the I/O port address (lower) & record
+			HostAdapter->io_port = (unsigned int)
+			    PciDev->resource[1].start & PCI_BASE_ADDRESS_IO_MASK;
+			HostAdapter->n_io_port = 0xff;
+
+			// i.e., expect 128 targets (arbitrary number), while the
+			//  RA-4000 supports 32 LUNs
+			HostAdapter->max_id = 0;	// incremented as devices log in    
+			HostAdapter->max_lun = CPQFCTS_MAX_LUN;	// LUNs per FC device
+			HostAdapter->max_channel = CPQFCTS_MAX_CHANNEL;	// multiple busses?
+
+			// get the pointer to our HBA specific data... (one for
+			// each HBA on the PCI bus(ses)).
+			cpqfcHBAdata = (CPQFCHBA *) HostAdapter->hostdata;
+
+			// make certain our data struct is clear
+			memset(cpqfcHBAdata, 0, sizeof(CPQFCHBA));
+
+
+			// initialize our HBA info
+			cpqfcHBAdata->HBAnum = NumberOfAdapters;
+
+			cpqfcHBAdata->HostAdapter = HostAdapter;	// back ptr
+			Cpqfc_initHBAdata(cpqfcHBAdata, PciDev);	// fill MOST fields
+
+			cpqfcHBAdata->HBAnum = NumberOfAdapters;
+			cpqfcHBAdata->hba_spinlock = SPIN_LOCK_UNLOCKED;
+
+			// request necessary resources and check for conflicts
+			if (request_irq(HostAdapter->irq, cpqfcTS_intr_handler, SA_INTERRUPT | SA_SHIRQ, DEV_NAME, HostAdapter)) {
+				printk(" IRQ %u already used\n", HostAdapter->irq);
+				scsi_unregister(HostAdapter);
+				continue;
+			}
+			// Since we have two 256-byte I/O port ranges (upper
+			// and lower), check them both
+			if (check_region(cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff)) {
+				printk("  cpqfcTS address in use: %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseU);
+				free_irq(HostAdapter->irq, HostAdapter);
+				scsi_unregister(HostAdapter);
+				continue;
+			}
+
+			if (check_region(cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff)) {
+				printk("  cpqfcTS address in use: %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseL);
+				free_irq(HostAdapter->irq, HostAdapter);
+				scsi_unregister(HostAdapter);
+				continue;
+			}
+			// OK, we should be able to grab everything we need now.
+			request_region(cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff, DEV_NAME);
+			request_region(cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff, DEV_NAME);
+			DEBUG_PCI(printk("  Requesting 255 I/O addresses @ %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseL));
+			DEBUG_PCI(printk("  Requesting 255 I/O addresses @ %x\n", cpqfcHBAdata->fcChip.Registers.IOBaseU));
+
+
+			// start our kernel worker thread
+
+			launch_FCworker_thread(HostAdapter);
+
+
+			// start our TimerTask...
+
+			cpqfcTStimer = &cpqfcHBAdata->cpqfcTStimer;
+
+			init_timer(cpqfcTStimer);	// Linux clears next/prev values
+			cpqfcTStimer->expires = jiffies + HZ;	// one second
+			cpqfcTStimer->data = (unsigned long) cpqfcHBAdata;	// this adapter
+			cpqfcTStimer->function = cpqfcTSheartbeat;	// handles timeouts, housekeeping
+
+			add_timer(cpqfcTStimer);	// give it to Linux
+
+
+			// now initialize our hardware...
+			if (cpqfcHBAdata->fcChip.InitializeTachyon(cpqfcHBAdata, 1, 1)) {
+				printk(KERN_WARNING "cpqfc: initialization of HBA hardware failed.\n");
+				// FIXME: might want to do something better than nothing here.
+			}
+
+			cpqfcHBAdata->fcStatsTime = jiffies;	// (for FC Statistics delta)
+
+			// give our HBA time to initialize and login current devices...
+			{
+				// The Brocade switch (e.g. 2400, 2010, etc.) as of March 2000,
+				// has the following algorithm for FL_Port startup:
+				// Time(sec) Action
+				// 0:        Device Plugin and LIP(F7,F7) transmission
+				// 1.0       LIP incoming
+				// 1.027     LISA incoming, no CLS! (link not up)
+				// 1.028     NOS incoming (switch test for N_Port)
+				// 1.577     ED_TOV expired, transmit LIPs again        
+				// 3.0       LIP(F8,F7) incoming (switch passes Tach Prim.Sig)
+				// 3.028     LILP received, link up, FLOGI starts
+				// slowest(worst) case, measured on 1Gb Finisar GT analyzer
+
+				unsigned long stop_time;
+
+				spin_unlock_irq(&io_request_lock);
+				stop_time = jiffies + 4 * HZ;
+				while (time_before(jiffies, stop_time))
+					schedule();	// (our worker task needs to run)
 
-	if( MAX_COMMAND_SIZE < 16)
+				spin_lock_irq(&io_request_lock);
+			}
+
+			NumberOfAdapters++;
+		}		// end of while()
+	}
+
+	LEAVE("cpqfcTS_detect");
+
+	return NumberOfAdapters;
+}
+
+static void my_ioctl_done(Scsi_Cmnd * SCpnt)
+{
+	struct request *req;
+
+	req = &SCpnt->request;
+	req->rq_status = RQ_SCSI_DONE;	/* Busy, but indicate request done */
+
+	if (req->CPQFC_WAITING != NULL)
+		CPQFC_COMPLETE(req->CPQFC_WAITING);
+}
+
+
+
+int cpqfcTS_ioctl(Scsi_Device * ScsiDev, int Cmnd, void *arg)
+{
+	int result = 0;
+	struct Scsi_Host *HostAdapter = ScsiDev->host;
+	CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) HostAdapter->hostdata;
+	PTACHYON fcChip = &cpqfcHBAdata->fcChip;
+	PFC_LOGGEDIN_PORT pLoggedInPort;
+	Scsi_Cmnd DumCmnd;
+	int i, j;
+	VENDOR_IOCTL_REQ ioc;
+	cpqfc_passthru_t *vendor_cmd;
+	Scsi_Device *SDpnt;
+	Scsi_Cmnd *ScsiPassThruCmnd;
+
+	ENTER("cpqfcTS_ioctl ");
+
+	// can we find an FC device mapping to this SCSI target?
+	DumCmnd.channel = ScsiDev->channel;	// For searching
+	DumCmnd.target = ScsiDev->id;
+	DumCmnd.lun = ScsiDev->lun;
+	pLoggedInPort = fcFindLoggedInPort(fcChip, &DumCmnd,	// search Scsi Nexus
+					   0,	// DON'T search linked list for FC port id
+					   NULL,	// DON'T search linked list for FC WWN
+					   NULL);	// DON'T care about end of list
+
+	if (pLoggedInPort == NULL)	// not found!
 	{
-          memcpy( &ScsiPassThruCmnd->SCp.buffers_residual,
-		  &vendor_cmd->cdb[12], 4);
-	}	  
-                  
-	
-        ScsiPassThruCmnd->SCp.sent_command = 1; // PASSTHRU!
-	                                        // suppress LUN masking
-	                                        // and VSA logic
-
-	// Use spare fields to copy FCP-SCSI LUN address info...
-        ScsiPassThruCmnd->SCp.phase = vendor_cmd->bus;
-	ScsiPassThruCmnd->SCp.have_data_in = vendor_cmd->pdrive;
-
-        // We copy the scheme used by scsi.c to submit commands
-	// to our own HBA.  We do this in order to stall the
-	// thread calling the IOCTL until it completes, and use
-	// the same "_quecommand" function for synchronizing
-	// FC Link events with our "worker thread".
-
-        {
-          CPQFC_DECLARE_COMPLETION(wait);
-          ScsiPassThruCmnd->request.CPQFC_WAITING = &wait;
-          // eventually gets us to our own _quecommand routine
-          scsi_do_cmd( ScsiPassThruCmnd, &vendor_cmd->cdb[0], 
-	       buf, 
-	       vendor_cmd->len, 
-	       my_ioctl_done, 
-	       10*HZ, 1);// timeout,retries
-          // Other I/Os can now resume; we wait for our ioctl
-	  // command to complete
-	  CPQFC_WAIT_FOR_COMPLETION(&wait);
-          ScsiPassThruCmnd->request.CPQFC_WAITING = NULL;
-        }
-	
-        result = ScsiPassThruCmnd->result;
+		result = -ENXIO;
+	}
 
-        // copy any sense data back to caller
-        if( result != 0 )
+	else			// we know what FC device to operate on...
 	{
-	  memcpy( vendor_cmd->sense_data, // see struct def - size=40
-		  ScsiPassThruCmnd->sense_buffer, 
-		  sizeof(ScsiPassThruCmnd->sense_buffer)); 
-	}
-        SDpnt = ScsiPassThruCmnd->device;
-        scsi_release_command(ScsiPassThruCmnd); // "de-allocate"
-        ScsiPassThruCmnd = NULL;
-
-        // if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
-        //  (*SDpnt->scsi_request_fn)();
-
-        wake_up(&SDpnt->scpnt_wait);
-
-	// need to pass data back to user (space)?
-	if( (vendor_cmd->rw_flag == VENDOR_READ_OPCODE) &&
-	     vendor_cmd->len )
-        if(  copy_to_user( vendor_cmd->bufp, buf, vendor_cmd->len))
-		return( -EFAULT);
-
-        if( buf) 
-	  kfree( buf);
-
-        return result;
-      }
-      
-      case CPQFCTS_GETPCIINFO:
-      {
-	cpqfc_pci_info_struct pciinfo;
-	
-	if( !arg)
-	  return -EINVAL;
-
-         	
-	
-        pciinfo.bus = cpqfcHBAdata->PciDev->bus->number;
-        pciinfo.dev_fn = cpqfcHBAdata->PciDev->devfn;  
-	pciinfo.board_id = cpqfcHBAdata->PciDev->device |
-			  (cpqfcHBAdata->PciDev->vendor <<16); 
-	      
-        if(copy_to_user( arg, &pciinfo, sizeof(cpqfc_pci_info_struct)))
-		return( -EFAULT);
-        return 0;
-      }
-
-      case CPQFCTS_GETDRIVVER:
-      {
-	DriverVer_type DriverVer = 
-		CPQFCTS_DRIVER_VER( VER_MAJOR,VER_MINOR,VER_SUBMINOR);
-	
-	if( !arg)
-	  return -EINVAL;
-
-        if(copy_to_user( arg, &DriverVer, sizeof(DriverVer)))
-		return( -EFAULT);
-        return 0;
-      }
-
-
-
-      case CPQFC_IOCTL_FC_TARGET_ADDRESS:
-      result = 
-        verify_area(VERIFY_WRITE, arg, sizeof(Scsi_FCTargAddress));
-      if (result) 
-	break;
- 
-      put_user(pLoggedInPort->port_id,
-		&((Scsi_FCTargAddress *) arg)->host_port_id);
- 
-      for( i=3,j=0; i>=0; i--)   	// copy the LOGIN port's WWN
-        put_user(pLoggedInPort->u.ucWWN[i], 
-		&((Scsi_FCTargAddress *) arg)->host_wwn[j++]);
-      for( i=7; i>3; i--)		// copy the LOGIN port's WWN
-        put_user(pLoggedInPort->u.ucWWN[i], 
-		&((Scsi_FCTargAddress *) arg)->host_wwn[j++]);
-        break;
-
-
-      case CPQFC_IOCTL_FC_TDR:
-          
-        result = cpqfcTS_TargetDeviceReset( ScsiDev, 0);
-
-        break;
-
-
-
-
-    default:
-      result = -EINVAL;
-      break;
-    }
-  }
+		// printk("ioctl CMND %d", Cmnd);
+		switch (Cmnd) {
+			// Passthrough provides a mechanism to bypass the RAID
+			// or other controller and talk directly to the devices
+			// (e.g. physical disk drive)
+			// Passthrough commands, unfortunately, tend to be vendor
+			// specific; this is tailored to COMPAQ's RAID (RA4x00)
+		case CPQFCTS_SCSI_PASSTHRU:
+			{
+				void *buf = NULL;	// for kernel space buffer for user data
+
+				if (!arg)
+					return -EINVAL;
+
+				// must be super user to send stuff directly to the
+				// controller and/or physical drives...
+				if (!suser())
+					return -EPERM;
+
+				// copy the caller's struct to our space.
+				if (copy_from_user(&ioc, arg, sizeof(VENDOR_IOCTL_REQ)))
+					return (-EFAULT);
+
+				vendor_cmd = ioc.argp;	// i.e., CPQ specific command struct
+
+				// If necessary, grab a kernel/DMA buffer
+				if (vendor_cmd->len) {
+					buf = kmalloc(vendor_cmd->len, GFP_KERNEL);
+					if (!buf)
+						return -ENOMEM;
+				}
+				// Now build a SCSI_CMND to pass down...
+				// This function allocates and sets Scsi_Cmnd ptrs such as
+				//  ->channel, ->target, ->host
+				ScsiPassThruCmnd = scsi_allocate_device(ScsiDev, 1, 1);
+
+				// Need data from user?
+				// make sure caller's buffer is in kernel space.
+				if ((vendor_cmd->rw_flag == VENDOR_WRITE_OPCODE) && vendor_cmd->len)
+					if (copy_from_user(buf, vendor_cmd->bufp, vendor_cmd->len)) {
+						kfree(buf);
+						return (-EFAULT);
+					}
+
+				// copy the CDB (if/when MAX_COMMAND_SIZE is 16, remove copy below)
+				memcpy(&ScsiPassThruCmnd->cmnd[0], &vendor_cmd->cdb[0], MAX_COMMAND_SIZE);
+				// we want to copy all 16 bytes into the FCP-SCSI CDB,
+				// although the actual passthru only uses up to the
+				// first 12.
+
+				ScsiPassThruCmnd->cmd_len = 16;	// sizeof FCP-SCSI CDB
+
+				// Unfortunately, the SCSI command cmnd[] field has only
+				// 12 bytes.  Ideally the MAX_COMMAND_SIZE should be increased
+				// to 16 for newer Fibre Channel and SCSI-3 larger CDBs.
+				// However, to avoid a mandatory kernel rebuild, we use the SCp
+				// spare field to store the extra 4 bytes ( ugly :-(
+
+				if (MAX_COMMAND_SIZE < 16) {
+					memcpy(&ScsiPassThruCmnd->SCp.buffers_residual, &vendor_cmd->cdb[12], 4);
+				}
+
+
+				ScsiPassThruCmnd->SCp.sent_command = 1;	// PASSTHRU!
+				// suppress LUN masking
+				// and VSA logic
+
+				// Use spare fields to copy FCP-SCSI LUN address info...
+				ScsiPassThruCmnd->SCp.phase = vendor_cmd->bus;
+				ScsiPassThruCmnd->SCp.have_data_in = vendor_cmd->pdrive;
+
+				// We copy the scheme used by scsi.c to submit commands
+				// to our own HBA.  We do this in order to stall the
+				// thread calling the IOCTL until it completes, and use
+				// the same "_quecommand" function for synchronizing
+				// FC Link events with our "worker thread".
+
+				{
+					CPQFC_DECLARE_COMPLETION(wait);
+					ScsiPassThruCmnd->request.CPQFC_WAITING = &wait;
+					// eventually gets us to our own _quecommand routine
+					scsi_do_cmd(ScsiPassThruCmnd, &vendor_cmd->cdb[0], buf, vendor_cmd->len, my_ioctl_done, 10 * HZ, 1);	// timeout,retries
+					// Other I/Os can now resume; we wait for our ioctl
+					// command to complete
+					CPQFC_WAIT_FOR_COMPLETION(&wait);
+					ScsiPassThruCmnd->request.CPQFC_WAITING = NULL;
+				}
+
+				result = ScsiPassThruCmnd->result;
+
+				// copy any sense data back to caller
+				if (result != 0) {
+					memcpy(vendor_cmd->sense_data,	// see struct def - size=40
+					       ScsiPassThruCmnd->sense_buffer, sizeof(ScsiPassThruCmnd->sense_buffer));
+				}
+				SDpnt = ScsiPassThruCmnd->device;
+				scsi_release_command(ScsiPassThruCmnd);	// "de-allocate"
+				ScsiPassThruCmnd = NULL;
+
+				// if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
+				//  (*SDpnt->scsi_request_fn)();
 
-  LEAVE("cpqfcTS_ioctl");
-  return result;
+				wake_up(&SDpnt->scpnt_wait);
+
+				// need to pass data back to user (space)?
+				if ((vendor_cmd->rw_flag == VENDOR_READ_OPCODE) && vendor_cmd->len)
+					if (copy_to_user(vendor_cmd->bufp, buf, vendor_cmd->len))
+						result = -EFAULT;
+
+				if (buf)
+					kfree(buf);
+
+				return result;
+			}
+
+		case CPQFCTS_GETPCIINFO:
+			{
+				cpqfc_pci_info_struct pciinfo;
+
+				if (!arg)
+					return -EINVAL;
+
+
+
+				pciinfo.bus = cpqfcHBAdata->PciDev->bus->number;
+				pciinfo.dev_fn = cpqfcHBAdata->PciDev->devfn;
+				pciinfo.board_id = cpqfcHBAdata->PciDev->device | (cpqfcHBAdata->PciDev->vendor << 16);
+
+				if (copy_to_user(arg, &pciinfo, sizeof(cpqfc_pci_info_struct)))
+					return (-EFAULT);
+				return 0;
+			}
+
+		case CPQFCTS_GETDRIVVER:
+			{
+				DriverVer_type DriverVer = CPQFCTS_DRIVER_VER(VER_MAJOR, VER_MINOR, VER_SUBMINOR);
+
+				if (!arg)
+					return -EINVAL;
+
+				if (copy_to_user(arg, &DriverVer, sizeof(DriverVer)))
+					return (-EFAULT);
+				return 0;
+			}
+
+
+
+		case CPQFC_IOCTL_FC_TARGET_ADDRESS:
+			result = verify_area(VERIFY_WRITE, arg, sizeof(Scsi_FCTargAddress));
+			if (result)
+				break;
+
+			put_user(pLoggedInPort->port_id, &((Scsi_FCTargAddress *) arg)->host_port_id);
+
+			for (i = 3, j = 0; i >= 0; i--)	// copy the LOGIN port's WWN
+				put_user(pLoggedInPort->u.ucWWN[i], &((Scsi_FCTargAddress *) arg)->host_wwn[j++]);
+			for (i = 7; i > 3; i--)	// copy the LOGIN port's WWN
+				put_user(pLoggedInPort->u.ucWWN[i], &((Scsi_FCTargAddress *) arg)->host_wwn[j++]);
+			break;
+
+
+		case CPQFC_IOCTL_FC_TDR:
+
+			result = cpqfcTS_TargetDeviceReset(ScsiDev, 0);
+
+			break;
+
+
+
+
+		default:
+			result = -EINVAL;
+			break;
+		}
+	}
+
+	LEAVE("cpqfcTS_ioctl");
+	return result;
 }
 
 
@@ -718,84 +616,73 @@
 
 int cpqfcTS_release(struct Scsi_Host *HostAdapter)
 {
-  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; 
+	CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) HostAdapter->hostdata;
 
 
-  ENTER("cpqfcTS_release");
-	
-  DEBUG_PCI( printk(" cpqfcTS: delete timer...\n"));
-  del_timer( &cpqfcHBAdata->cpqfcTStimer);  
-    
-  // disable the hardware...
-  DEBUG_PCI( printk(" disable hardware, destroy queues, free mem\n"));
-  cpqfcHBAdata->fcChip.ResetTachyon( cpqfcHBAdata, CLEAR_FCPORTS);
-
-  // kill kernel thread
-  if( cpqfcHBAdata->worker_thread ) // (only if exists)
-  {
-    DECLARE_MUTEX_LOCKED(sem);  // synchronize thread kill
-
-    cpqfcHBAdata->notify_wt = &sem;
-    DEBUG_PCI( printk(" killing kernel thread\n"));
-    send_sig( SIGKILL, cpqfcHBAdata->worker_thread, 1);
-    down( &sem);
-    cpqfcHBAdata->notify_wt = NULL;
-    
-  }
-
-  // free Linux resources
-  DEBUG_PCI( printk(" cpqfcTS: freeing resources...\n"));
-  free_irq( HostAdapter->irq, HostAdapter);
-  scsi_unregister( HostAdapter);
-  release_region( cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff);
-  release_region( cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff);
- /* we get "vfree: bad address" executing this - need to investigate... 
-  if( (void*)((unsigned long)cpqfcHBAdata->fcChip.Registers.MemBase) !=
-      cpqfcHBAdata->fcChip.Registers.ReMapMemBase)
-    vfree( cpqfcHBAdata->fcChip.Registers.ReMapMemBase);
-*/
+	ENTER("cpqfcTS_release");
+
+	DEBUG_PCI(printk(" cpqfcTS: delete timer...\n"));
+	del_timer(&cpqfcHBAdata->cpqfcTStimer);
 
-  LEAVE("cpqfcTS_release");
-  return 0;
+	// disable the hardware...
+	DEBUG_PCI(printk(" disable hardware, destroy queues, free mem\n"));
+	cpqfcHBAdata->fcChip.ResetTachyon(cpqfcHBAdata, CLEAR_FCPORTS);
+
+	// kill kernel thread
+	if (cpqfcHBAdata->worker_thread)	// (only if exists)
+	{
+		DECLARE_MUTEX_LOCKED(sem);	// synchronize thread kill
+
+		cpqfcHBAdata->notify_wt = &sem;
+		DEBUG_PCI(printk(" killing kernel thread\n"));
+		send_sig(SIGKILL, cpqfcHBAdata->worker_thread, 1);
+		down(&sem);
+		cpqfcHBAdata->notify_wt = NULL;
+
+	}
+	// free Linux resources
+	DEBUG_PCI(printk(" cpqfcTS: freeing resources...\n"));
+	free_irq(HostAdapter->irq, HostAdapter);
+	scsi_unregister(HostAdapter);
+	release_region(cpqfcHBAdata->fcChip.Registers.IOBaseL, 0xff);
+	release_region(cpqfcHBAdata->fcChip.Registers.IOBaseU, 0xff);
+	/* we get "vfree: bad address" executing this - need to investigate... 
+	   if( (void*)((unsigned long)cpqfcHBAdata->fcChip.Registers.MemBase) !=
+	   cpqfcHBAdata->fcChip.Registers.ReMapMemBase)
+	   vfree( cpqfcHBAdata->fcChip.Registers.ReMapMemBase);
+	 */
+
+	LEAVE("cpqfcTS_release");
+	return 0;
 }
 
 
-const char * cpqfcTS_info(struct Scsi_Host *HostAdapter)
+const char *cpqfcTS_info(struct Scsi_Host *HostAdapter)
 {
-  static char buf[300];
-  CPQFCHBA *cpqfcHBA;
-  int BusSpeed, BusWidth;
-  
-  // get the pointer to our Scsi layer HBA buffer  
-  cpqfcHBA = (CPQFCHBA *)HostAdapter->hostdata;
-
-  BusWidth = (cpqfcHBA->fcChip.Registers.PCIMCTR &0x4) > 0 ?
-               64 : 32;
-
-  if( cpqfcHBA->fcChip.Registers.TYconfig.value & 0x80000000)
-    BusSpeed = 66;
-  else
-    BusSpeed = 33;
-
-  sprintf(buf, 
-"%s: WWN %08X%08X\n on PCI bus %d device 0x%02x irq %d IObaseL 0x%x, MEMBASE 0x%x\nPCI bus width %d bits, bus speed %d MHz\nFCP-SCSI Driver v%d.%d.%d",
-      cpqfcHBA->fcChip.Name, 
-      cpqfcHBA->fcChip.Registers.wwn_hi,
-      cpqfcHBA->fcChip.Registers.wwn_lo,
-      cpqfcHBA->PciDev->bus->number,
-      cpqfcHBA->PciDev->device,  
-      HostAdapter->irq,
-      cpqfcHBA->fcChip.Registers.IOBaseL,
-      cpqfcHBA->fcChip.Registers.MemBase,
-      BusWidth,
-      BusSpeed,
-      VER_MAJOR, VER_MINOR, VER_SUBMINOR
-);
-
-  
-  cpqfcTSDecodeGBICtype( &cpqfcHBA->fcChip, &buf[ strlen(buf)]);
-  cpqfcTSGetLPSM( &cpqfcHBA->fcChip, &buf[ strlen(buf)]);
-  return buf;
+	static char buf[300];
+	CPQFCHBA *cpqfcHBA;
+	int BusSpeed, BusWidth;
+
+	// get the pointer to our Scsi layer HBA buffer  
+	cpqfcHBA = (CPQFCHBA *) HostAdapter->hostdata;
+
+	BusWidth = (cpqfcHBA->fcChip.Registers.PCIMCTR & 0x4) > 0 ? 64 : 32;
+
+	if (cpqfcHBA->fcChip.Registers.TYconfig.value & 0x80000000)
+		BusSpeed = 66;
+	else
+		BusSpeed = 33;
+
+	sprintf(buf,
+		"%s: WWN %08X%08X\n on PCI bus %d device 0x%02x irq %d IObaseL 0x%x, MEMBASE 0x%x\nPCI bus width %d bits, bus speed %d MHz\nFCP-SCSI Driver v%d.%d.%d",
+		cpqfcHBA->fcChip.Name,
+		cpqfcHBA->fcChip.Registers.wwn_hi,
+		cpqfcHBA->fcChip.Registers.wwn_lo, cpqfcHBA->PciDev->bus->number, cpqfcHBA->PciDev->device, HostAdapter->irq, cpqfcHBA->fcChip.Registers.IOBaseL, cpqfcHBA->fcChip.Registers.MemBase, BusWidth, BusSpeed, VER_MAJOR, VER_MINOR, VER_SUBMINOR);
+
+
+	cpqfcTSDecodeGBICtype(&cpqfcHBA->fcChip, &buf[strlen(buf)]);
+	cpqfcTSGetLPSM(&cpqfcHBA->fcChip, &buf[strlen(buf)]);
+	return buf;
 }
 
 //
@@ -806,178 +693,167 @@
 // programming to use it to make programming a little simpler. This piece
 // of coding is borrowed from ncr53c8xx.c with some modifications 
 //
-struct info_str
-{
-        char *buffer;			// Pointer to output buffer
-        int buflength;			// It's length
-        int bufoffset;			// File offset corresponding with buf[0]
-	int buffillen;			// Current filled length 
-        int filpos;			// Current file offset
+struct info_str {
+	char *buffer;		// Pointer to output buffer
+	int buflength;		// It's length
+	int bufoffset;		// File offset corresponding with buf[0]
+	int buffillen;		// Current filled length 
+	int filpos;		// Current file offset
 };
 
 static void copy_mem_info(struct info_str *info, char *data, int datalen)
 {
 
-  if (info->filpos < info->bufoffset) {	// Current offset before buffer offset
-    if (info->filpos + datalen <= info->bufoffset) {
-      info->filpos += datalen; 		// Discard if completely before buffer
-      return;
-    } else {				// Partial copy, set to begin
-      data += (info->bufoffset - info->filpos);
-      datalen  -= (info->bufoffset - info->filpos);
-      info->filpos = info->bufoffset;
-    }
-  }
-
-  info->filpos += datalen;		// Update current offset
+	if (info->filpos < info->bufoffset) {	// Current offset before buffer offset
+		if (info->filpos + datalen <= info->bufoffset) {
+			info->filpos += datalen;	// Discard if completely before buffer
+			return;
+		} else {	// Partial copy, set to begin
+			data += (info->bufoffset - info->filpos);
+			datalen -= (info->bufoffset - info->filpos);
+			info->filpos = info->bufoffset;
+		}
+	}
+
+	info->filpos += datalen;	// Update current offset
 
-  if (info->buffillen == info->buflength) // Buffer full, discard
-    return;
+	if (info->buffillen == info->buflength)	// Buffer full, discard
+		return;
 
-  if (info->buflength - info->buffillen < datalen)  // Overflows buffer ?
-    datalen = info->buflength - info->buffillen;
+	if (info->buflength - info->buffillen < datalen)	// Overflows buffer ?
+		datalen = info->buflength - info->buffillen;
 
-  memcpy(info->buffer + info->buffillen, data, datalen);
-  info->buffillen += datalen;
+	memcpy(info->buffer + info->buffillen, data, datalen);
+	info->buffillen += datalen;
 }
 
 static int copy_info(struct info_str *info, char *fmt, ...)
 {
-        va_list args;
-        char buf[400];
-        int len;
-
-        va_start(args, fmt);
-        len = vsprintf(buf, fmt, args);
-        va_end(args);
+	va_list args;
+	char buf[400];
+	int len;
+
+	va_start(args, fmt);
+	len = vsprintf(buf, fmt, args);
+	va_end(args);
 
-        copy_mem_info(info, buf, len);
-        return len;
+	copy_mem_info(info, buf, len);
+	return len;
 }
 
 
 // Routine to get data for /proc RAM filesystem
 //
-int cpqfcTS_proc_info (char *buffer, char **start, off_t offset, int length, 
-		       int hostno, int inout)
+int cpqfcTS_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout)
 {
-  struct Scsi_Host *host;
-  Scsi_Cmnd DumCmnd;
-  int Chan, Targ, i;
-  struct info_str info;
-  CPQFCHBA *cpqfcHBA;
-  PTACHYON fcChip;
-  PFC_LOGGEDIN_PORT pLoggedInPort;
-  char buf[81];
-
-  // Search the Scsi host list for our controller
-  for (host=scsi_hostlist; host; host=host->next)
-    if (host->host_no == hostno)
-      break;
-
-  if (!host) return -ESRCH;
-
-  if (inout) return -EINVAL;
-
-  // get the pointer to our Scsi layer HBA buffer  
-  cpqfcHBA = (CPQFCHBA *)host->hostdata;
-  fcChip = &cpqfcHBA->fcChip;
-  
-  *start 	  = buffer;
-
-  info.buffer     = buffer;
-  info.buflength  = length;
-  info.bufoffset  = offset;
-  info.filpos     = 0;
-  info.buffillen  = 0;
-  copy_info(&info, "Driver version = %d.%d.%d", VER_MAJOR, VER_MINOR, VER_SUBMINOR); 
-  cpqfcTSDecodeGBICtype( &cpqfcHBA->fcChip, &buf[0]);
-  cpqfcTSGetLPSM( &cpqfcHBA->fcChip, &buf[ strlen(buf)]);
-  copy_info(&info, "%s\n", buf); 
+	struct Scsi_Host *host;
+	Scsi_Cmnd DumCmnd;
+	int Chan, Targ, i;
+	struct info_str info;
+	CPQFCHBA *cpqfcHBA;
+	PTACHYON fcChip;
+	PFC_LOGGEDIN_PORT pLoggedInPort;
+	char buf[81];
+
+	// Search the Scsi host list for our controller
+	for (host = scsi_hostlist; host; host = host->next)
+		if (host->host_no == hostno)
+			break;
+
+	if (!host)
+		return -ESRCH;
+
+	if (inout)
+		return -EINVAL;
+
+	// get the pointer to our Scsi layer HBA buffer  
+	cpqfcHBA = (CPQFCHBA *) host->hostdata;
+	fcChip = &cpqfcHBA->fcChip;
+
+	*start = buffer;
+
+	info.buffer = buffer;
+	info.buflength = length;
+	info.bufoffset = offset;
+	info.filpos = 0;
+	info.buffillen = 0;
+	copy_info(&info, "Driver version = %d.%d.%d", VER_MAJOR, VER_MINOR, VER_SUBMINOR);
+	cpqfcTSDecodeGBICtype(&cpqfcHBA->fcChip, &buf[0]);
+	cpqfcTSGetLPSM(&cpqfcHBA->fcChip, &buf[strlen(buf)]);
+	copy_info(&info, "%s\n", buf);
 
 #define DISPLAY_WWN_INFO
 #ifdef DISPLAY_WWN_INFO
-  copy_info(&info, "WWN database: (\"port_id: 000000\" means disconnected)\n");
-  for ( Chan=0; Chan <= host->max_channel; Chan++) {
-    DumCmnd.channel = Chan;
-    for (Targ=0; Targ <= host->max_id; Targ++) {
-      DumCmnd.target = Targ;
-      if ((pLoggedInPort = fcFindLoggedInPort( fcChip,
-	    			&DumCmnd, // search Scsi Nexus
-    				0,        // DON'T search list for FC port id
-    				NULL,     // DON'T search list for FC WWN
-    				NULL))){   // DON'T care about end of list
-	copy_info(&info, "Host: scsi%d Channel: %02d TargetId: %02d -> WWN: ",
-			   hostno, Chan, Targ);
-        for( i=3; i>=0; i--)        // copy the LOGIN port's WWN
-          copy_info(&info, "%02X", pLoggedInPort->u.ucWWN[i]);
-        for( i=7; i>3; i--)             // copy the LOGIN port's WWN
-          copy_info(&info, "%02X", pLoggedInPort->u.ucWWN[i]);
-	copy_info(&info, " port_id: %06X\n", pLoggedInPort->port_id); 
-      }
-    }
-  }
+	copy_info(&info, "WWN database: (\"port_id: 000000\" means disconnected)\n");
+	for (Chan = 0; Chan <= host->max_channel; Chan++) {
+		DumCmnd.channel = Chan;
+		for (Targ = 0; Targ <= host->max_id; Targ++) {
+			DumCmnd.target = Targ;
+			if ((pLoggedInPort = fcFindLoggedInPort(fcChip, &DumCmnd,	// search Scsi Nexus
+								0,	// DON'T search list for FC port id
+								NULL,	// DON'T search list for FC WWN
+								NULL))) {	// DON'T care about end of list
+				copy_info(&info, "Host: scsi%d Channel: %02d TargetId: %02d -> WWN: ", hostno, Chan, Targ);
+				for (i = 3; i >= 0; i--)	// copy the LOGIN port's WWN
+					copy_info(&info, "%02X", pLoggedInPort->u.ucWWN[i]);
+				for (i = 7; i > 3; i--)	// copy the LOGIN port's WWN
+					copy_info(&info, "%02X", pLoggedInPort->u.ucWWN[i]);
+				copy_info(&info, " port_id: %06X\n", pLoggedInPort->port_id);
+			}
+		}
+	}
 #endif
 
 
 
-  
-  
+
+
 // Unfortunately, the proc_info buffer isn't big enough
 // for everything we would like...
 // For FC stats, compile this and turn off WWN stuff above  
 //#define DISPLAY_FC_STATS
 #ifdef DISPLAY_FC_STATS
 // get the Fibre Channel statistics
-  {
-    int DeltaSecs = (jiffies - cpqfcHBA->fcStatsTime) / HZ;
-    int days,hours,minutes,secs;
-    
-    days = DeltaSecs / (3600*24); // days
-    hours = (DeltaSecs% (3600*24)) / 3600; // hours
-    minutes = (DeltaSecs%3600 /60); // minutes
-    secs =  DeltaSecs%60;  // secs
-copy_info( &info, "Fibre Channel Stats (time dd:hh:mm:ss %02u:%02u:%02u:%02u\n",
-      days, hours, minutes, secs);
-  }
-    
-  cpqfcHBA->fcStatsTime = jiffies;  // (for next delta)
-
-  copy_info( &info, "  LinkUp           %9u     LinkDown      %u\n",
-        fcChip->fcStats.linkUp, fcChip->fcStats.linkDown);
-        
-  copy_info( &info, "  Loss of Signal   %9u     Loss of Sync  %u\n",
-    fcChip->fcStats.LossofSignal, fcChip->fcStats.LossofSync);
-		  
-  copy_info( &info, "  Discarded Frames %9u     Bad CRC Frame %u\n",
-    fcChip->fcStats.Dis_Frm, fcChip->fcStats.Bad_CRC);
-
-  copy_info( &info, "  TACH LinkFailTX  %9u     TACH LinkFailRX     %u\n",
-    fcChip->fcStats.linkFailTX, fcChip->fcStats.linkFailRX);
-  
-  copy_info( &info, "  TACH RxEOFa      %9u     TACH Elastic Store  %u\n",
-    fcChip->fcStats.Rx_EOFa, fcChip->fcStats.e_stores);
-
-  copy_info( &info, "  BufferCreditWait %9uus   TACH FM Inits %u\n",
-    fcChip->fcStats.BB0_Timer*10, fcChip->fcStats.FMinits );
-	
-  copy_info( &info, "  FC-2 Timeouts    %9u     FC-2 Logouts  %u\n",
-    fcChip->fcStats.timeouts, fcChip->fcStats.logouts); 
-        
-  copy_info( &info, "  FC-2 Aborts      %9u     FC-4 Aborts   %u\n",
-    fcChip->fcStats.FC2aborted, fcChip->fcStats.FC4aborted);
-   
-  // clear the counters
-  cpqfcTSClearLinkStatusCounters( fcChip);
+	{
+		int DeltaSecs = (jiffies - cpqfcHBA->fcStatsTime) / HZ;
+		int days, hours, minutes, secs;
+
+		days = DeltaSecs / (3600 * 24);	// days
+		hours = (DeltaSecs % (3600 * 24)) / 3600;	// hours
+		minutes = (DeltaSecs % 3600 / 60);	// minutes
+		secs = DeltaSecs % 60;	// secs
+		copy_info(&info, "Fibre Channel Stats (time dd:hh:mm:ss %02u:%02u:%02u:%02u\n", days, hours, minutes, secs);
+	}
+
+	cpqfcHBA->fcStatsTime = jiffies;	// (for next delta)
+
+	copy_info(&info, "  LinkUp           %9u     LinkDown      %u\n", fcChip->fcStats.linkUp, fcChip->fcStats.linkDown);
+
+	copy_info(&info, "  Loss of Signal   %9u     Loss of Sync  %u\n", fcChip->fcStats.LossofSignal, fcChip->fcStats.LossofSync);
+
+	copy_info(&info, "  Discarded Frames %9u     Bad CRC Frame %u\n", fcChip->fcStats.Dis_Frm, fcChip->fcStats.Bad_CRC);
+
+	copy_info(&info, "  TACH LinkFailTX  %9u     TACH LinkFailRX     %u\n", fcChip->fcStats.linkFailTX, fcChip->fcStats.linkFailRX);
+
+	copy_info(&info, "  TACH RxEOFa      %9u     TACH Elastic Store  %u\n", fcChip->fcStats.Rx_EOFa, fcChip->fcStats.e_stores);
+
+	copy_info(&info, "  BufferCreditWait %9uus   TACH FM Inits %u\n", fcChip->fcStats.BB0_Timer * 10, fcChip->fcStats.FMinits);
+
+	copy_info(&info, "  FC-2 Timeouts    %9u     FC-2 Logouts  %u\n", fcChip->fcStats.timeouts, fcChip->fcStats.logouts);
+
+	copy_info(&info, "  FC-2 Aborts      %9u     FC-4 Aborts   %u\n", fcChip->fcStats.FC2aborted, fcChip->fcStats.FC4aborted);
+
+	// clear the counters
+	cpqfcTSClearLinkStatusCounters(fcChip);
 #endif
-	
-  return info.buffillen;
+
+	return info.buffillen;
 }
 
 
 #if DEBUG_CMND
 
-UCHAR *ScsiToAscii( UCHAR ScsiCommand)
+u8 *ScsiToAscii(u8 ScsiCommand)
 {
 
 /*++
@@ -1000,152 +876,148 @@
 --*/
 
 
-   switch (ScsiCommand)
-   {
-      case 0x00:
-         return( "Test Unit Ready" );
+	switch (ScsiCommand) {
+	case 0x00:
+		return ("Test Unit Ready");
 
-      case 0x01:
-         return( "Rezero Unit or Rewind" );
+	case 0x01:
+		return ("Rezero Unit or Rewind");
 
-      case 0x02:
-         return( "Request Block Address" );
+	case 0x02:
+		return ("Request Block Address");
 
-      case 0x03:
-         return( "Requese Sense" );
+	case 0x03:
+		return ("Requese Sense");
 
-      case 0x04:
-         return( "Format Unit" );
+	case 0x04:
+		return ("Format Unit");
 
-      case 0x05:
-         return( "Read Block Limits" );
+	case 0x05:
+		return ("Read Block Limits");
 
-      case 0x07:
-         return( "Reassign Blocks" );
+	case 0x07:
+		return ("Reassign Blocks");
 
-      case 0x08:
-         return( "Read (6)" );
+	case 0x08:
+		return ("Read (6)");
 
-      case 0x0a:
-         return( "Write (6)" );
+	case 0x0a:
+		return ("Write (6)");
 
-      case 0x0b:
-         return( "Seek (6)" );
+	case 0x0b:
+		return ("Seek (6)");
 
-      case 0x12:
-         return( "Inquiry" );
+	case 0x12:
+		return ("Inquiry");
 
-      case 0x15:
-         return( "Mode Select (6)" );
+	case 0x15:
+		return ("Mode Select (6)");
 
-      case 0x16:
-         return( "Reserve" );
+	case 0x16:
+		return ("Reserve");
 
-      case 0x17:
-         return( "Release" );
+	case 0x17:
+		return ("Release");
 
-      case 0x1a:
-         return( "ModeSen(6)" );
+	case 0x1a:
+		return ("ModeSen(6)");
 
-      case 0x1b:
-         return( "Start/Stop Unit" );
+	case 0x1b:
+		return ("Start/Stop Unit");
 
-      case 0x1c:
-         return( "Receive Diagnostic Results" );
+	case 0x1c:
+		return ("Receive Diagnostic Results");
 
-      case 0x1d:
-         return( "Send Diagnostic" );
+	case 0x1d:
+		return ("Send Diagnostic");
 
-      case 0x25:
-         return( "Read Capacity" );
+	case 0x25:
+		return ("Read Capacity");
 
-      case 0x28:
-         return( "Read (10)" );
+	case 0x28:
+		return ("Read (10)");
 
-      case 0x2a:
-         return( "Write (10)" );
+	case 0x2a:
+		return ("Write (10)");
 
-      case 0x2b:
-         return( "Seek (10)" );
+	case 0x2b:
+		return ("Seek (10)");
 
-      case 0x2e:
-         return( "Write and Verify" );
+	case 0x2e:
+		return ("Write and Verify");
 
-      case 0x2f:
-         return( "Verify" );
+	case 0x2f:
+		return ("Verify");
 
-      case 0x34:
-         return( "Pre-Fetch" );
+	case 0x34:
+		return ("Pre-Fetch");
 
-      case 0x35:
-         return( "Synchronize Cache" );
+	case 0x35:
+		return ("Synchronize Cache");
 
-      case 0x37:
-         return( "Read Defect Data (10)" );
+	case 0x37:
+		return ("Read Defect Data (10)");
 
-      case 0x3b:
-         return( "Write Buffer" );
+	case 0x3b:
+		return ("Write Buffer");
 
-      case 0x3c:
-         return( "Read Buffer" );
+	case 0x3c:
+		return ("Read Buffer");
 
-      case 0x3e:
-         return( "Read Long" );
+	case 0x3e:
+		return ("Read Long");
 
-      case 0x3f:
-         return( "Write Long" );
+	case 0x3f:
+		return ("Write Long");
 
-      case 0x41:
-         return( "Write Same" );
+	case 0x41:
+		return ("Write Same");
 
-      case 0x4c:
-         return( "Log Select" );
+	case 0x4c:
+		return ("Log Select");
 
-      case 0x4d:
-         return( "Log Sense" );
+	case 0x4d:
+		return ("Log Sense");
 
-      case 0x56:
-         return( "Reserve (10)" );
+	case 0x56:
+		return ("Reserve (10)");
 
-      case 0x57:
-         return( "Release (10)" );
+	case 0x57:
+		return ("Release (10)");
 
-      case 0xa0:
-         return( "ReportLuns" );
+	case 0xa0:
+		return ("ReportLuns");
 
-      case 0xb7:
-         return( "Read Defect Data (12)" );
+	case 0xb7:
+		return ("Read Defect Data (12)");
 
-      case 0xca:
-         return( "Peripheral Device Addressing SCSI Passthrough" );
+	case 0xca:
+		return ("Peripheral Device Addressing SCSI Passthrough");
 
-      case 0xcb:
-         return( "Compaq Array Firmware Passthrough" );
+	case 0xcb:
+		return ("Compaq Array Firmware Passthrough");
 
-      default:
-         return( NULL );
-   }
+	default:
+		return (NULL);
+	}
 
-} // end ScsiToAscii()
+}				// end ScsiToAscii()
 
 void cpqfcTS_print_scsi_cmd(Scsi_Cmnd * cmd)
 {
 
-printk("cpqfcTS: (%s) chnl 0x%02x, trgt = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", 
-    ScsiToAscii( cmd->cmnd[0]), cmd->channel, cmd->target, cmd->lun, cmd->cmd_len);
+	printk("cpqfcTS: (%s) chnl 0x%02x, trgt = 0x%02x, lun = 0x%02x, cmd_len = 0x%02x\n", ScsiToAscii(cmd->cmnd[0]), cmd->channel, cmd->target, cmd->lun, cmd->cmd_len);
 
-if( cmd->cmnd[0] == 0)   // Test Unit Ready?
-{
-  int i;
+	if (cmd->cmnd[0] == 0)	// Test Unit Ready?
+	{
+		int i;
 
-  printk("Cmnd->request_bufflen = 0x%X, ->use_sg = %d, ->bufflen = %d\n",
-    cmd->request_bufflen, cmd->use_sg, cmd->bufflen);
-  printk("Cmnd->request_buffer = %p, ->sglist_len = %d, ->buffer = %p\n",
-    cmd->request_buffer, cmd->sglist_len, cmd->buffer);
-  for (i = 0; i < cmd->cmd_len; i++)
-    printk("0x%02x ", cmd->cmnd[i]);
-  printk("\n");
-}
+		printk("Cmnd->request_bufflen = 0x%X, ->use_sg = %d, ->bufflen = %d\n", cmd->request_bufflen, cmd->use_sg, cmd->bufflen);
+		printk("Cmnd->request_buffer = %p, ->sglist_len = %d, ->buffer = %p\n", cmd->request_buffer, cmd->sglist_len, cmd->buffer);
+		for (i = 0; i < cmd->cmd_len; i++)
+			printk("0x%02x ", cmd->cmnd[i]);
+		printk("\n");
+	}
 
 }
 
@@ -1154,51 +1026,48 @@
 
 
 
-static void QueCmndOnBoardLock( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd)
+static void QueCmndOnBoardLock(CPQFCHBA * cpqfcHBAdata, Scsi_Cmnd * Cmnd)
 {
-  int i;
+	int i;
 
-  for( i=0; i< CPQFCTS_REQ_QUEUE_LEN; i++)
-  {    // find spare slot
-    if( cpqfcHBAdata->BoardLockCmnd[i] == NULL )
-    {
-      cpqfcHBAdata->BoardLockCmnd[i] = Cmnd;
+	for (i = 0; i < CPQFCTS_REQ_QUEUE_LEN; i++) {	// find spare slot
+		if (cpqfcHBAdata->BoardLockCmnd[i] == NULL) {
+			cpqfcHBAdata->BoardLockCmnd[i] = Cmnd;
 //      printk(" BoardLockCmnd[%d] %p Queued, chnl/target/lun %d/%d/%d\n",
 //        i,Cmnd, Cmnd->channel, Cmnd->target, Cmnd->lun);
-      break;
-    }
-  }
-  if( i >= CPQFCTS_REQ_QUEUE_LEN)
-  {
-    printk(" cpqfcTS WARNING: Lost Cmnd %p on BoardLock Q full!", Cmnd);
-  }
+			break;
+		}
+	}
+	if (i >= CPQFCTS_REQ_QUEUE_LEN) {
+		printk(" cpqfcTS WARNING: Lost Cmnd %p on BoardLock Q full!", Cmnd);
+	}
 
 }
 
 
-static void QueLinkDownCmnd( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd)
+static void QueLinkDownCmnd(CPQFCHBA * cpqfcHBAdata, Scsi_Cmnd * Cmnd)
 {
-  int indx;
+	int indx;
 
-  // Remember the command ptr so we can return; we'll complete when
-  // the device comes back, causing immediate retry
-  for( indx=0; indx < CPQFCTS_REQ_QUEUE_LEN; indx++)//, SCptr++)
-  {
-    if( cpqfcHBAdata->LinkDnCmnd[indx] == NULL ) // available?
-    {
+	// Remember the command ptr so we can return; we'll complete when
+	// the device comes back, causing immediate retry
+	for (indx = 0; indx < CPQFCTS_REQ_QUEUE_LEN; indx++)	//, SCptr++)
+	{
+		if (cpqfcHBAdata->LinkDnCmnd[indx] == NULL)	// available?
+		{
 #ifdef DUMMYCMND_DBG
-      printk(" @add Cmnd %p to LnkDnCmnd[%d]@ ", Cmnd,indx);
+			printk(" @add Cmnd %p to LnkDnCmnd[%d]@ ", Cmnd, indx);
 #endif
-      cpqfcHBAdata->LinkDnCmnd[indx] = Cmnd;
-      break;
-    }
-  }
-
-  if( indx >= CPQFCTS_REQ_QUEUE_LEN ) // no space for Cmnd??
-  {
-    // this will result in an _abort call later (with possible trouble)
-    printk("no buffer for LinkDnCmnd!! %p\n", Cmnd);
-  }
+			cpqfcHBAdata->LinkDnCmnd[indx] = Cmnd;
+			break;
+		}
+	}
+
+	if (indx >= CPQFCTS_REQ_QUEUE_LEN)	// no space for Cmnd??
+	{
+		// this will result in an _abort call later (with possible trouble)
+		printk("no buffer for LinkDnCmnd!! %p\n", Cmnd);
+	}
 }
 
 
@@ -1211,185 +1080,162 @@
 // for cases that don't go to the hardware like scsi cmds destined
 // for LUNs we know don't exist, so this code might be simplified...)
 
-static void QueBadTargetCmnd( CPQFCHBA *cpqfcHBAdata, Scsi_Cmnd *Cmnd)
+static void QueBadTargetCmnd(CPQFCHBA * cpqfcHBAdata, Scsi_Cmnd * Cmnd)
 {
-  int i;
-    //    printk(" can't find target %d\n", Cmnd->target);
+	int i;
+	//    printk(" can't find target %d\n", Cmnd->target);
 
-  for( i=0; i< CPQFCTS_MAX_TARGET_ID; i++)
-  {    // find spare slot
-    if( cpqfcHBAdata->BadTargetCmnd[i] == NULL )
-    {
-      cpqfcHBAdata->BadTargetCmnd[i] = Cmnd;
+	for (i = 0; i < CPQFCTS_MAX_TARGET_ID; i++) {	// find spare slot
+		if (cpqfcHBAdata->BadTargetCmnd[i] == NULL) {
+			cpqfcHBAdata->BadTargetCmnd[i] = Cmnd;
 //      printk(" BadTargetCmnd[%d] %p Queued, chnl/target/lun %d/%d/%d\n",
 //          i,Cmnd, Cmnd->channel, Cmnd->target, Cmnd->lun);
-      break;
-    }
-  }
+			break;
+		}
+	}
 }
 
 
 // This is the "main" entry point for Linux Scsi commands --
 // it all starts here.
 
-int cpqfcTS_queuecommand(Scsi_Cmnd *Cmnd, void (* done)(Scsi_Cmnd *))
+int cpqfcTS_queuecommand(Scsi_Cmnd * Cmnd, void (*done) (Scsi_Cmnd *))
 {
-  struct Scsi_Host *HostAdapter = Cmnd->host;
-  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  TachFCHDR_GCMND fchs;  // only use for FC destination id field  
-  PFC_LOGGEDIN_PORT pLoggedInPort;
-  ULONG ulStatus, SESTtype;
-  LONG ExchangeID;
+	struct Scsi_Host *HostAdapter = Cmnd->host;
+	CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) HostAdapter->hostdata;
+	PTACHYON fcChip = &cpqfcHBAdata->fcChip;
+	TachFCHDR_GCMND fchs;	// only use for FC destination id field  
+	PFC_LOGGEDIN_PORT pLoggedInPort;
+	u32 ulStatus, SESTtype;
+	s32 ExchangeID;
+
+
 
 
+	ENTER("cpqfcTS_queuecommand");
 
+	PCI_TRACEO((u32) Cmnd, 0x98)
 
-  ENTER("cpqfcTS_queuecommand");
-      
-  PCI_TRACEO( (ULONG)Cmnd, 0x98)
-      
-  
-  Cmnd->scsi_done = done;
-#ifdef DEBUG_CMND  
-  cpqfcTS_print_scsi_cmd( Cmnd);
+
+	    Cmnd->scsi_done = done;
+#ifdef DEBUG_CMND
+	cpqfcTS_print_scsi_cmd(Cmnd);
 #endif
 
-  // prevent board contention with kernel thread...  
-  
-   if( cpqfcHBAdata->BoardLock )
-  {
+	// prevent board contention with kernel thread...  
+
+	if (cpqfcHBAdata->BoardLock) {
 //    printk(" @BrdLck Hld@ ");
-    QueCmndOnBoardLock( cpqfcHBAdata, Cmnd);
-  }
-  
-  else
-  {
-
-    // in the current system (2.2.12), this routine is called
-    // after spin_lock_irqsave(), so INTs are disabled. However,
-    // we might have something pending in the LinkQ, which
-    // might cause the WorkerTask to run.  In case that
-    // happens, make sure we lock it out.
-    
-    
-    
-    PCI_TRACE( 0x98) 
-    CPQ_SPINLOCK_HBA( cpqfcHBAdata)
-    PCI_TRACE( 0x98) 
-	    
-  // can we find an FC device mapping to this SCSI target?
-    pLoggedInPort = fcFindLoggedInPort( fcChip,
-      Cmnd,     // search Scsi Nexus
-      0,        // DON'T search linked list for FC port id
-      NULL,     // DON'T search linked list for FC WWN
-      NULL);    // DON'T care about end of list
- 
-    if( pLoggedInPort == NULL )      // not found!
-    {
+		QueCmndOnBoardLock(cpqfcHBAdata, Cmnd);
+	}
+
+	else {
+
+		// in the current system (2.2.12), this routine is called
+		// after spin_lock_irqsave(), so INTs are disabled. However,
+		// we might have something pending in the LinkQ, which
+		// might cause the WorkerTask to run.  In case that
+		// happens, make sure we lock it out.
+
+
+
+		PCI_TRACE(0x98)
+		    CPQ_SPINLOCK_HBA(cpqfcHBAdata)
+		    PCI_TRACE(0x98)
+		    // can we find an FC device mapping to this SCSI target?
+		    pLoggedInPort = fcFindLoggedInPort(fcChip, Cmnd,	// search Scsi Nexus
+						       0,	// DON'T search linked list for FC port id
+						       NULL,	// DON'T search linked list for FC WWN
+						       NULL);	// DON'T care about end of list
+
+		if (pLoggedInPort == NULL)	// not found!
+		{
 //    printk(" @Q bad targ cmnd %p@ ", Cmnd);
-      QueBadTargetCmnd( cpqfcHBAdata, Cmnd);
-    }
-    else if (Cmnd->lun >= CPQFCTS_MAX_LUN)
-    {
-      printk(KERN_WARNING "cpqfc: Invalid LUN: %d\n", Cmnd->lun);
-      QueBadTargetCmnd( cpqfcHBAdata, Cmnd);
-    } 
-
-    else  // we know what FC device to send to...
-    {
-
-      // does this device support FCP target functions?
-      // (determined by PRLI field)
-
-      if( !(pLoggedInPort->fcp_info & TARGET_FUNCTION) )
-      {
-        printk(" Doesn't support TARGET functions port_id %Xh\n",
-          pLoggedInPort->port_id );
-        QueBadTargetCmnd( cpqfcHBAdata, Cmnd);
-      }
-
-    // In this case (previous login OK), the device is temporarily
-    // unavailable waiting for re-login, in which case we expect it
-    // to be back in between 25 - 500ms.  
-    // If the FC port doesn't log back in within several seconds
-    // (i.e. implicit "logout"), or we get an explicit logout,
-    // we set "device_blocked" in Scsi_Device struct; in this
-    // case 30 seconds will elapse before Linux/Scsi sends another
-    // command to the device.
-      else if( pLoggedInPort->prli != TRUE )
-      {
+			QueBadTargetCmnd(cpqfcHBAdata, Cmnd);
+		} else if (Cmnd->lun >= CPQFCTS_MAX_LUN) {
+			printk(KERN_WARNING "cpqfc: Invalid LUN: %d\n", Cmnd->lun);
+			QueBadTargetCmnd(cpqfcHBAdata, Cmnd);
+		}
+
+		else		// we know what FC device to send to...
+		{
+
+			// does this device support FCP target functions?
+			// (determined by PRLI field)
+
+			if (!(pLoggedInPort->fcp_info & TARGET_FUNCTION)) {
+				printk(" Doesn't support TARGET functions port_id %Xh\n", pLoggedInPort->port_id);
+				QueBadTargetCmnd(cpqfcHBAdata, Cmnd);
+			}
+			// In this case (previous login OK), the device is temporarily
+			// unavailable waiting for re-login, in which case we expect it
+			// to be back in between 25 - 500ms.  
+			// If the FC port doesn't log back in within several seconds
+			// (i.e. implicit "logout"), or we get an explicit logout,
+			// we set "device_blocked" in Scsi_Device struct; in this
+			// case 30 seconds will elapse before Linux/Scsi sends another
+			// command to the device.
+			else if (pLoggedInPort->prli != TRUE) {
 //      printk("Device (Chnl/Target %d/%d) invalid PRLI, port_id %06lXh\n",
 //        Cmnd->channel, Cmnd->target, pLoggedInPort->port_id);
-        QueLinkDownCmnd( cpqfcHBAdata, Cmnd);
-//    Need to use "blocked" flag??   	
-//	Cmnd->device->device_blocked = TRUE; // just let it timeout
-      }
-      else  // device supports TARGET functions, and is logged in...
-      {
-      // (context of fchs is to "reply" to...)
-        fchs.s_id = pLoggedInPort->port_id; // destination FC address
-
-      // what is the data direction?  For data TO the device,
-      // we need IWE (Intiator Write Entry).  Otherwise, IRE.
-
-        if( Cmnd->cmnd[0] == WRITE_10 ||
-  	  Cmnd->cmnd[0] == WRITE_6 ||
-	  Cmnd->cmnd[0] == WRITE_BUFFER ||      
-	  Cmnd->cmnd[0] == VENDOR_WRITE_OPCODE ||  // CPQ specific 
-	  Cmnd->cmnd[0] == MODE_SELECT )
-        {
-          SESTtype = SCSI_IWE; // data from HBA to Device
-        }
-        else
-          SESTtype = SCSI_IRE; // data from Device to HBA
-    	  
-        ulStatus = cpqfcTSBuildExchange(
-          cpqfcHBAdata,
-          SESTtype,     // e.g. Initiator Read Entry (IRE)
-          &fchs,        // we are originator; only use d_id
-          Cmnd,         // Linux SCSI command (with scatter/gather list)
-          &ExchangeID );// fcController->fcExchanges index, -1 if failed
+				QueLinkDownCmnd(cpqfcHBAdata, Cmnd);
+//    Need to use "blocked" flag??      
+//      Cmnd->device->device_blocked = TRUE; // just let it timeout
+			} else	// device supports TARGET functions, and is logged in...
+			{
+				// (context of fchs is to "reply" to...)
+				fchs.s_id = pLoggedInPort->port_id;	// destination FC address
+
+				// what is the data direction?  For data TO the device,
+				// we need IWE (Intiator Write Entry).  Otherwise, IRE.
+
+				if (Cmnd->cmnd[0] == WRITE_10 || Cmnd->cmnd[0] == WRITE_6 || Cmnd->cmnd[0] == WRITE_BUFFER || Cmnd->cmnd[0] == VENDOR_WRITE_OPCODE ||	// CPQ specific 
+				    Cmnd->cmnd[0] == MODE_SELECT) {
+					SESTtype = SCSI_IWE;	// data from HBA to Device
+				} else
+					SESTtype = SCSI_IRE;	// data from Device to HBA
+
+				ulStatus = cpqfcTSBuildExchange(cpqfcHBAdata, SESTtype,	// e.g. Initiator Read Entry (IRE)
+								&fchs,	// we are originator; only use d_id
+								Cmnd,	// Linux SCSI command (with scatter/gather list)
+								&ExchangeID);	// fcController->fcExchanges index, -1 if failed
+
+				if (!ulStatus)	// Exchange setup?
+
+				{
+					if (cpqfcHBAdata->BoardLock) {
+						TriggerHBA(fcChip->Registers.ReMapMemBase, 0);
+						printk(" @bl! %d, xID %Xh@ ", current->pid, ExchangeID);
+					}
+
+					ulStatus = cpqfcTSStartExchange(cpqfcHBAdata, ExchangeID);
+					if (!ulStatus) {
+						PCI_TRACEO(ExchangeID, 0xB8)
+						    // submitted to Tach's Outbound Que (ERQ PI incremented)
+						    // waited for completion for ELS type (Login frames issued
+						    // synchronously)
+					} else
+						// check reason for Exchange not being started - we might
+						// want to Queue and start later, or fail with error
+					{
+						printk("quecommand: cpqfcTSStartExchange failed: %Xh\n", ulStatus);
+					}
+				}	// end good BuildExchange status
+
+				else	// SEST table probably full  -- why? hardware hang?
+				{
+					printk("quecommand: cpqfcTSBuildExchange faild: %Xh\n", ulStatus);
+				}
+			}	// end can't do FCP-SCSI target functions
+		}		// end can't find target (FC device)
 
-        if( !ulStatus ) // Exchange setup?
-   
-        {
-          if( cpqfcHBAdata->BoardLock )
-          {
-    TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
-	    printk(" @bl! %d, xID %Xh@ ", current->pid, ExchangeID);
-          }
-
-	  ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );
-	  if( !ulStatus )
-          {
-            PCI_TRACEO( ExchangeID, 0xB8) 
-          // submitted to Tach's Outbound Que (ERQ PI incremented)
-          // waited for completion for ELS type (Login frames issued
-          // synchronously)
-	  }
-          else
-            // check reason for Exchange not being started - we might
-            // want to Queue and start later, or fail with error
-          {
-            printk("quecommand: cpqfcTSStartExchange failed: %Xh\n", ulStatus );
-          }
-        }            // end good BuildExchange status
-        
-        else  // SEST table probably full  -- why? hardware hang?
-        {
-	  printk("quecommand: cpqfcTSBuildExchange faild: %Xh\n", ulStatus);
-        }
-      }  // end can't do FCP-SCSI target functions
-    } // end can't find target (FC device)
-
-    CPQ_SPINUNLOCK_HBA( cpqfcHBAdata)
-  }
-	
-  PCI_TRACEO( (ULONG)Cmnd, 0x9C) 
-  LEAVE("cpqfcTS_queuecommand");
-  return 0;
-}    
+		CPQ_SPINUNLOCK_HBA(cpqfcHBAdata)
+	}
+
+	PCI_TRACEO((u32) Cmnd, 0x9C)
+	    LEAVE("cpqfcTS_queuecommand");
+	return 0;
+}
 
 
 // Entry point for upper Scsi layer intiated abort.  Typically
@@ -1403,148 +1249,140 @@
 // errors, it should be considered a driver error and reported to
 // the author.
 
-int cpqfcTS_abort(Scsi_Cmnd *Cmnd)
+int cpqfcTS_abort(Scsi_Cmnd * Cmnd)
 {
-//	printk(" cpqfcTS_abort called?? \n");
- 	return 0;
+//      printk(" cpqfcTS_abort called?? \n");
+	return 0;
 }
- 
-int cpqfcTS_eh_abort(Scsi_Cmnd *Cmnd)
+
+int cpqfcTS_eh_abort(Scsi_Cmnd * Cmnd)
 {
 
-  struct Scsi_Host *HostAdapter = Cmnd->host;
-  // get the pointer to our Scsi layer HBA buffer  
-  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  int i;
-  ENTER("cpqfcTS_eh_abort");
-
-  Cmnd->result = DID_ABORT <<16;  // assume we'll find it
-
-  printk(" @Linux _abort Scsi_Cmnd %p ", Cmnd);
-  // See if we can find a Cmnd pointer that matches...
-  // The most likely case is we accepted the command
-  // from Linux Scsi (e.g. ceated a SEST entry) and it
-  // got lost somehow.  If we can't find any reference
-  // to the passed pointer, we can only presume it
-  // got completed as far as our driver is concerned.
-  // If we found it, we will try to abort it through
-  // common mechanism.  If FC ABTS is successful (ACC)
-  // or is rejected (RJT) by target, we will call
-  // Scsi "done" quickly.  Otherwise, the ABTS will timeout
-  // and we'll call "done" later.
-
-  // Search the SEST exchanges for a matching Cmnd ptr.
-  for( i=0; i< TACH_SEST_LEN; i++)
-  {
-    if( Exchanges->fcExchange[i].Cmnd == Cmnd )
-    {
-      
-      // found it!
-      printk(" x_ID %Xh, type %Xh\n", i, Exchanges->fcExchange[i].type);
-
-      Exchanges->fcExchange[i].status = INITIATOR_ABORT; // seconds default
-      Exchanges->fcExchange[i].timeOut = 10; // seconds default (changed later)
-
-      // Since we need to immediately return the aborted Cmnd to Scsi 
-      // upper layers, we can't make future reference to any of it's 
-      // fields (e.g the Nexus).
-
-      cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &i);
-
-      break;
-    }
-  }
-
-  if( i >= TACH_SEST_LEN ) // didn't find Cmnd ptr in chip's SEST?
-  {
-    // now search our non-SEST buffers (i.e. Cmnd waiting to
-    // start on the HBA or waiting to complete with error for retry).
-    
-    // first check BadTargetCmnd
-    for( i=0; i< CPQFCTS_MAX_TARGET_ID; i++)
-    { 
-      if( cpqfcHBAdata->BadTargetCmnd[i] == Cmnd )
-      {
-        cpqfcHBAdata->BadTargetCmnd[i] = NULL;
-	printk("in BadTargetCmnd Q\n");
-	goto Done; // exit
-      }
-    }
-
-    // if not found above...
-
-    for( i=0; i < CPQFCTS_REQ_QUEUE_LEN; i++)
-    {
-      if( cpqfcHBAdata->LinkDnCmnd[i] == Cmnd ) 
-      {
-	cpqfcHBAdata->LinkDnCmnd[i] = NULL;
-	printk("in LinkDnCmnd Q\n");
-	goto Done;
-      }
-    }
-
-
-    for( i=0; i< CPQFCTS_REQ_QUEUE_LEN; i++)
-    {    // find spare slot
-      if( cpqfcHBAdata->BoardLockCmnd[i] == Cmnd )
-      {
-        cpqfcHBAdata->BoardLockCmnd[i] = NULL;
-	printk("in BoardLockCmnd Q\n");
-	goto Done;
-      }
-    }
-    
-    Cmnd->result = DID_ERROR <<16;  // Hmmm...
-    printk("Not found! ");
+	struct Scsi_Host *HostAdapter = Cmnd->host;
+	// get the pointer to our Scsi layer HBA buffer  
+	CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *) HostAdapter->hostdata;
+	PTACHYON fcChip = &cpqfcHBAdata->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	int i;
+	ENTER("cpqfcTS_eh_abort");
+
+	Cmnd->result = DID_ABORT << 16;	// assume we'll find it
+
+	printk(" @Linux _abort Scsi_Cmnd %p ", Cmnd);
+	// See if we can find a Cmnd pointer that matches...
+	// The most likely case is we accepted the command
+	// from Linux Scsi (e.g. ceated a SEST entry) and it
+	// got lost somehow.  If we can't find any reference
+	// to the passed pointer, we can only presume it
+	// got completed as far as our driver is concerned.
+	// If we found it, we will try to abort it through
+	// common mechanism.  If FC ABTS is successful (ACC)
+	// or is rejected (RJT) by target, we will call
+	// Scsi "done" quickly.  Otherwise, the ABTS will timeout
+	// and we'll call "done" later.
+
+	// Search the SEST exchanges for a matching Cmnd ptr.
+	for (i = 0; i < TACH_SEST_LEN; i++) {
+		if (Exchanges->fcExchange[i].Cmnd == Cmnd) {
+
+			// found it!
+			printk(" x_ID %Xh, type %Xh\n", i, Exchanges->fcExchange[i].type);
+
+			Exchanges->fcExchange[i].status = INITIATOR_ABORT;	// seconds default
+			Exchanges->fcExchange[i].timeOut = 10;	// seconds default (changed later)
+
+			// Since we need to immediately return the aborted Cmnd to Scsi 
+			// upper layers, we can't make future reference to any of it's 
+			// fields (e.g the Nexus).
+
+			cpqfcTSPutLinkQue(cpqfcHBAdata, BLS_ABTS, &i);
+
+			break;
+		}
+	}
+
+	if (i >= TACH_SEST_LEN)	// didn't find Cmnd ptr in chip's SEST?
+	{
+		// now search our non-SEST buffers (i.e. Cmnd waiting to
+		// start on the HBA or waiting to complete with error for retry).
+
+		// first check BadTargetCmnd
+		for (i = 0; i < CPQFCTS_MAX_TARGET_ID; i++) {
+			if (cpqfcHBAdata->BadTargetCmnd[i] == Cmnd) {
+				cpqfcHBAdata->BadTargetCmnd[i] = NULL;
+				printk("in BadTargetCmnd Q\n");
+				goto Done;	// exit
+			}
+		}
+
+		// if not found above...
+
+		for (i = 0; i < CPQFCTS_REQ_QUEUE_LEN; i++) {
+			if (cpqfcHBAdata->LinkDnCmnd[i] == Cmnd) {
+				cpqfcHBAdata->LinkDnCmnd[i] = NULL;
+				printk("in LinkDnCmnd Q\n");
+				goto Done;
+			}
+		}
+
+
+		for (i = 0; i < CPQFCTS_REQ_QUEUE_LEN; i++) {	// find spare slot
+			if (cpqfcHBAdata->BoardLockCmnd[i] == Cmnd) {
+				cpqfcHBAdata->BoardLockCmnd[i] = NULL;
+				printk("in BoardLockCmnd Q\n");
+				goto Done;
+			}
+		}
+
+		Cmnd->result = DID_ERROR << 16;	// Hmmm...
+		printk("Not found! ");
 //    panic("_abort");
-  }
-  
-Done:
-  
+	}
+
+      Done:
+
 //    panic("_abort");
-  LEAVE("cpqfcTS_eh_abort");
-  return 0;  // (see scsi.h)
-}    
+	LEAVE("cpqfcTS_eh_abort");
+	return 0;		// (see scsi.h)
+}
 
 
 // FCP-SCSI Target Device Reset
 // See dpANS Fibre Channel Protocol for SCSI
 // X3.269-199X revision 12, pg 25
 
-int cpqfcTS_TargetDeviceReset( Scsi_Device *ScsiDev, 
-                               unsigned int reset_flags)
+int cpqfcTS_TargetDeviceReset(Scsi_Device * ScsiDev, unsigned int reset_flags)
 {
-  int timeout = 10*HZ;
-  int retries = 1;
-  char scsi_cdb[12];
-  int result;
-  Scsi_Cmnd * SCpnt;
-  Scsi_Device * SDpnt;
-
-
-  // printk("   ENTERING cpqfcTS_TargetDeviceReset() - flag=%d \n",reset_flags);
-
-  if (ScsiDev->host->eh_active) return FAILED;
-
-  memset( scsi_cdb, 0, sizeof( scsi_cdb));
-
-  scsi_cdb[0] = RELEASE;
-
-  // allocate with wait = true, interruptible = false 
-  SCpnt = scsi_allocate_device(ScsiDev, 1, 0);
-  {
-    CPQFC_DECLARE_COMPLETION(wait);
-        
-    SCpnt->SCp.buffers_residual = FCP_TARGET_RESET;
-
-	SCpnt->request.CPQFC_WAITING = &wait;
-	scsi_do_cmd(SCpnt,  scsi_cdb, NULL,  0, my_ioctl_done,  timeout, retries);
-	CPQFC_WAIT_FOR_COMPLETION(&wait);
-	SCpnt->request.CPQFC_WAITING = NULL;
-  }
-    
+	int timeout = 10 * HZ;
+	int retries = 1;
+	char scsi_cdb[12];
+	int result;
+	Scsi_Cmnd *SCpnt;
+	Scsi_Device *SDpnt;
+
+
+	// printk("   ENTERING cpqfcTS_TargetDeviceReset() - flag=%d \n",reset_flags);
+
+	if (ScsiDev->host->eh_active)
+		return FAILED;
+
+	memset(scsi_cdb, 0, sizeof(scsi_cdb));
+
+	scsi_cdb[0] = RELEASE;
+
+	// allocate with wait = true, interruptible = false 
+	SCpnt = scsi_allocate_device(ScsiDev, 1, 0);
+	{
+		CPQFC_DECLARE_COMPLETION(wait);
+
+		SCpnt->SCp.buffers_residual = FCP_TARGET_RESET;
+
+		SCpnt->request.CPQFC_WAITING = &wait;
+		scsi_do_cmd(SCpnt, scsi_cdb, NULL, 0, my_ioctl_done, timeout, retries);
+		CPQFC_WAIT_FOR_COMPLETION(&wait);
+		SCpnt->request.CPQFC_WAITING = NULL;
+	}
+
 /*
       if(driver_byte(SCpnt->result) != 0)
 	  switch(SCpnt->sense_buffer[2] & 0xf) {
@@ -1577,41 +1415,41 @@
 		   SCpnt->sense_buffer[2] & 0xf);
 	    
       };
-*/    
-  result = SCpnt->result;
+*/
+	result = SCpnt->result;
 
-  SDpnt = SCpnt->device;
-  scsi_release_command(SCpnt);
-  SCpnt = NULL;
+	SDpnt = SCpnt->device;
+	scsi_release_command(SCpnt);
+	SCpnt = NULL;
 
-  // if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
-  // 	(*SDpnt->scsi_request_fn)();
+	// if (!SDpnt->was_reset && SDpnt->scsi_request_fn)
+	//    (*SDpnt->scsi_request_fn)();
 
-  wake_up(&SDpnt->scpnt_wait);
-  // printk("   LEAVING cpqfcTS_TargetDeviceReset() - return SUCCESS \n");
-  return SUCCESS;
+	wake_up(&SDpnt->scpnt_wait);
+	// printk("   LEAVING cpqfcTS_TargetDeviceReset() - return SUCCESS \n");
+	return SUCCESS;
 }
 
 
-int cpqfcTS_eh_device_reset(Scsi_Cmnd *Cmnd)
+int cpqfcTS_eh_device_reset(Scsi_Cmnd * Cmnd)
 {
-  int retval;
-  Scsi_Device *SDpnt = Cmnd->device;
-  // printk("   ENTERING cpqfcTS_eh_device_reset() \n");
-  spin_unlock_irq(&io_request_lock);
-  retval = cpqfcTS_TargetDeviceReset( SDpnt, 0);
-  spin_lock_irq(&io_request_lock);
-  return retval;
+	int retval;
+	Scsi_Device *SDpnt = Cmnd->device;
+	// printk("   ENTERING cpqfcTS_eh_device_reset() \n");
+	spin_unlock_irq(&io_request_lock);
+	retval = cpqfcTS_TargetDeviceReset(SDpnt, 0);
+	spin_lock_irq(&io_request_lock);
+	return retval;
 }
 
-	
-int cpqfcTS_reset(Scsi_Cmnd *Cmnd, unsigned int reset_flags)
+
+int cpqfcTS_reset(Scsi_Cmnd * Cmnd, unsigned int reset_flags)
 {
 
-  ENTER("cpqfcTS_reset");
+	ENTER("cpqfcTS_reset");
 
-  LEAVE("cpqfcTS_reset");
-  return SCSI_RESET_ERROR;      /* Bus Reset Not supported */
+	LEAVE("cpqfcTS_reset");
+	return SCSI_RESET_ERROR;	/* Bus Reset Not supported */
 }
 
 /* This function determines the bios parameters for a given
@@ -1621,228 +1459,210 @@
    (from hosts.h)
 */
 
-int cpqfcTS_biosparam(Disk *disk, kdev_t n, int ip[])
+int cpqfcTS_biosparam(Disk * disk, kdev_t n, int ip[])
 {
-  int size = disk->capacity;
-  
-  ENTER("cpqfcTS_biosparam");
-  ip[0] = 64;
-  ip[1] = 32;
-  ip[2] = size >> 11;
-  
-  if( ip[2] > 1024 )
-  {
-    ip[0] = 255;
-    ip[1] = 63;
-    ip[2] = size / (ip[0] * ip[1]);
-  }
-
-  LEAVE("cpqfcTS_biosparam");
-  return 0;
-}    
+	int size = disk->capacity;
 
+	ENTER("cpqfcTS_biosparam");
+	ip[0] = 64;
+	ip[1] = 32;
+	ip[2] = size >> 11;
+
+	if (ip[2] > 1024) {
+		ip[0] = 255;
+		ip[1] = 63;
+		ip[2] = size / (ip[0] * ip[1]);
+	}
 
+	LEAVE("cpqfcTS_biosparam");
+	return 0;
+}
 
-void cpqfcTS_intr_handler( int irq, 
-		void *dev_id, 
-		struct pt_regs *regs)
-{
-
-  unsigned long flags, InfLoopBrk=0;
-  struct Scsi_Host *HostAdapter = dev_id;
-  CPQFCHBA *cpqfcHBA = (CPQFCHBA *)HostAdapter->hostdata;
-  int MoreMessages = 1; // assume we have something to do
-  UCHAR IntPending;
-  
-  ENTER("intr_handler");
-
-  spin_lock_irqsave( &io_request_lock, flags);
-  // is this our INT?
-  IntPending = readb( cpqfcHBA->fcChip.Registers.INTPEND.address);
 
-  // broken boards can generate messages forever, so
-  // prevent the infinite loop
+
+void cpqfcTS_intr_handler(int irq, void *dev_id, struct pt_regs *regs)
+{
+
+	unsigned long flags, InfLoopBrk = 0;
+	struct Scsi_Host *HostAdapter = dev_id;
+	CPQFCHBA *cpqfcHBA = (CPQFCHBA *) HostAdapter->hostdata;
+	int MoreMessages = 1;	// assume we have something to do
+	u8 IntPending;
+
+	ENTER("intr_handler");
+
+	spin_lock_irqsave(&io_request_lock, flags);
+	// is this our INT?
+	IntPending = readb(cpqfcHBA->fcChip.Registers.INTPEND.address);
+
+	// broken boards can generate messages forever, so
+	// prevent the infinite loop
 #define INFINITE_IMQ_BREAK 10000
-  if( IntPending )
-  {
-    
-    // mask our HBA interrupts until we handle it...
-    writeb( 0, cpqfcHBA->fcChip.Registers.INTEN.address);
-
-    if( IntPending & 0x4) // "INT" - Tach wrote to IMQ
-    {
-      while( (++InfLoopBrk < INFINITE_IMQ_BREAK) && (MoreMessages ==1) ) 
-      {
-        MoreMessages = CpqTsProcessIMQEntry( HostAdapter); // ret 0 when done
-      }
-      if( InfLoopBrk >= INFINITE_IMQ_BREAK )
-      {
-        printk("WARNING: Compaq FC adapter generating excessive INTs -REPLACE\n");
-        printk("or investigate alternate causes (e.g. physical FC layer)\n");
-      }
-
-      else  // working normally - re-enable INTs and continue
-        writeb( 0x1F, cpqfcHBA->fcChip.Registers.INTEN.address);
-    
-    }  // (...ProcessIMQEntry() clears INT by writing IMQ consumer)
-    else  // indications of errors or problems...
-          // these usually indicate critical system hardware problems.
-    {
-      if( IntPending & 0x10 )
-  	printk(" cpqfcTS adapter external memory parity error detected\n");
-      if( IntPending & 0x8 )
-  	printk(" cpqfcTS adapter PCI master address crossed 45-bit boundary\n");
-      if( IntPending & 0x2 )
-	printk(" cpqfcTS adapter DMA error detected\n");
-      if( IntPending & 0x1 ) {
-  	UCHAR IntStat;
-  	printk(" cpqfcTS adapter PCI error detected\n");
-  	IntStat = readb( cpqfcHBA->fcChip.Registers.INTSTAT.address);
-	if (IntStat & 0x4) printk("(INT)\n");
-	if (IntStat & 0x8) 
-		printk("CRS: PCI master address crossed 46 bit bouandary\n");
-	if (IntStat & 0x10) printk("MRE: external memory parity error.\n");
-      }
-    }      
-  }
-  spin_unlock_irqrestore( &io_request_lock, flags);
-  LEAVE("intr_handler");
+	if (IntPending) {
+
+		// mask our HBA interrupts until we handle it...
+		writeb(0, cpqfcHBA->fcChip.Registers.INTEN.address);
+
+		if (IntPending & 0x4)	// "INT" - Tach wrote to IMQ
+		{
+			while ((++InfLoopBrk < INFINITE_IMQ_BREAK) && (MoreMessages == 1)) {
+				MoreMessages = CpqTsProcessIMQEntry(HostAdapter);	// ret 0 when done
+			}
+			if (InfLoopBrk >= INFINITE_IMQ_BREAK) {
+				printk("WARNING: Compaq FC adapter generating excessive INTs -REPLACE\n");
+				printk("or investigate alternate causes (e.g. physical FC layer)\n");
+			}
+
+			else	// working normally - re-enable INTs and continue
+				writeb(0x1F, cpqfcHBA->fcChip.Registers.INTEN.address);
+
+		}		// (...ProcessIMQEntry() clears INT by writing IMQ consumer)
+		else		// indications of errors or problems...
+			// these usually indicate critical system hardware problems.
+		{
+			if (IntPending & 0x10)
+				printk(" cpqfcTS adapter external memory parity error detected\n");
+			if (IntPending & 0x8)
+				printk(" cpqfcTS adapter PCI master address crossed 45-bit boundary\n");
+			if (IntPending & 0x2)
+				printk(" cpqfcTS adapter DMA error detected\n");
+			if (IntPending & 0x1) {
+				u8 IntStat;
+				printk(" cpqfcTS adapter PCI error detected\n");
+				IntStat = readb(cpqfcHBA->fcChip.Registers.INTSTAT.address);
+				if (IntStat & 0x4)
+					printk("(INT)\n");
+				if (IntStat & 0x8)
+					printk("CRS: PCI master address crossed 46 bit bouandary\n");
+				if (IntStat & 0x10)
+					printk("MRE: external memory parity error.\n");
+			}
+		}
+	}
+	spin_unlock_irqrestore(&io_request_lock, flags);
+	LEAVE("intr_handler");
 }
 
 
 
 
-int cpqfcTSDecodeGBICtype( PTACHYON fcChip, char cErrorString[])
-{
-        // Verify GBIC type (if any) and correct Tachyon Port State Machine
-        // (GBIC) module definition is:
-        // GPIO1, GPIO0, GPIO4 for MD2, MD1, MD0.  The input states appear
-        // to be inverted -- i.e., a setting of 111 is read when there is NO
-        // GBIC present.  The Module Def (MD) spec says 000 is "no GBIC"
-        // Hard code the bit states to detect Copper, 
-        // Long wave (single mode), Short wave (multi-mode), and absent GBIC
-
-  ULONG ulBuff;
-
-  sprintf( cErrorString, "\nGBIC detected: ");
-
-  ulBuff = fcChip->Registers.TYstatus.value & 0x13; 
-  switch( ulBuff )
-  {
-  case 0x13:  // GPIO4, GPIO1, GPIO0 = 111; no GBIC!
-    sprintf( &cErrorString[ strlen( cErrorString)],
-            "NONE! ");
-    return FALSE;          
-          
-       
-  case 0x11:   // Copper GBIC detected
-    sprintf( &cErrorString[ strlen( cErrorString)],
-            "Copper. ");
-    break;
-
-  case 0x10:   // Long-wave (single mode) GBIC detected
-    sprintf( &cErrorString[ strlen( cErrorString)],
-        "Long-wave. ");
-    break;
-  case 0x1:    // Short-wave (multi mode) GBIC detected
-    sprintf( &cErrorString[ strlen( cErrorString)],
-        "Short-wave. ");
-    break;
-  default:     // unknown GBIC - presumably it will work (?)
-    sprintf( &cErrorString[ strlen( cErrorString)],
-            "Unknown. ");
-          
-    break;
-  }  // end switch GBIC detection
-
-  return TRUE;
-}
+int cpqfcTSDecodeGBICtype(PTACHYON fcChip, char cErrorString[])
+{
+	// Verify GBIC type (if any) and correct Tachyon Port State Machine
+	// (GBIC) module definition is:
+	// GPIO1, GPIO0, GPIO4 for MD2, MD1, MD0.  The input states appear
+	// to be inverted -- i.e., a setting of 111 is read when there is NO
+	// GBIC present.  The Module Def (MD) spec says 000 is "no GBIC"
+	// Hard code the bit states to detect Copper, 
+	// Long wave (single mode), Short wave (multi-mode), and absent GBIC
 
+	u32 ulBuff;
 
+	sprintf(cErrorString, "\nGBIC detected: ");
 
+	ulBuff = fcChip->Registers.TYstatus.value & 0x13;
+	switch (ulBuff) {
+	case 0x13:		// GPIO4, GPIO1, GPIO0 = 111; no GBIC!
+		sprintf(&cErrorString[strlen(cErrorString)], "NONE! ");
+		return FALSE;
 
 
+	case 0x11:		// Copper GBIC detected
+		sprintf(&cErrorString[strlen(cErrorString)], "Copper. ");
+		break;
+
+	case 0x10:		// Long-wave (single mode) GBIC detected
+		sprintf(&cErrorString[strlen(cErrorString)], "Long-wave. ");
+		break;
+	case 0x1:		// Short-wave (multi mode) GBIC detected
+		sprintf(&cErrorString[strlen(cErrorString)], "Short-wave. ");
+		break;
+	default:		// unknown GBIC - presumably it will work (?)
+		sprintf(&cErrorString[strlen(cErrorString)], "Unknown. ");
 
-int cpqfcTSGetLPSM( PTACHYON fcChip, char cErrorString[])
-{
-  // Tachyon's Frame Manager LPSM in LinkDown state?
-  // (For non-loop port, check PSM instead.)
-  // return string with state and FALSE is Link Down
-
-  int LinkUp;
-
-  if( fcChip->Registers.FMstatus.value & 0x80 ) 
-    LinkUp = FALSE;
-  else
-    LinkUp = TRUE;
-
-  sprintf( &cErrorString[ strlen( cErrorString)],
-    " LPSM %Xh ", 
-     (fcChip->Registers.FMstatus.value >>4) & 0xf );
-
-
-  switch( fcChip->Registers.FMstatus.value & 0xF0)
-  {
-                    // bits set in LPSM
-    case 0x10:
-      sprintf( &cErrorString[ strlen( cErrorString)], "ARB");
-      break;
-    case 0x20:
-      sprintf( &cErrorString[ strlen( cErrorString)], "ARBwon");
-      break;
-    case 0x30:
-      sprintf( &cErrorString[ strlen( cErrorString)], "OPEN");
-      break;
-    case 0x40:
-      sprintf( &cErrorString[ strlen( cErrorString)], "OPENed");
-      break;
-    case 0x50:
-      sprintf( &cErrorString[ strlen( cErrorString)], "XmitCLS");
-      break;
-    case 0x60:
-      sprintf( &cErrorString[ strlen( cErrorString)], "RxCLS");
-      break;
-    case 0x70:
-      sprintf( &cErrorString[ strlen( cErrorString)], "Xfer");
-      break;
-    case 0x80:
-      sprintf( &cErrorString[ strlen( cErrorString)], "Init");
-      break;
-    case 0x90:
-      sprintf( &cErrorString[ strlen( cErrorString)], "O-IInitFin");
-      break;
-    case 0xa0:
-      sprintf( &cErrorString[ strlen( cErrorString)], "O-IProtocol");
-      break;
-    case 0xb0:
-      sprintf( &cErrorString[ strlen( cErrorString)], "O-ILipRcvd");
-      break;
-    case 0xc0:
-      sprintf( &cErrorString[ strlen( cErrorString)], "HostControl");
-      break;
-    case 0xd0:
-      sprintf( &cErrorString[ strlen( cErrorString)], "LoopFail");
-      break;
-    case 0xe0:
-      sprintf( &cErrorString[ strlen( cErrorString)], "Offline");
-      break;
-    case 0xf0:
-      sprintf( &cErrorString[ strlen( cErrorString)], "OldPort");
-      break;
-    case 0:
-    default:
-      sprintf( &cErrorString[ strlen( cErrorString)], "Monitor");
-      break;
-
-  }
+		break;
+	}			// end switch GBIC detection
 
-  return LinkUp;
+	return TRUE;
 }
 
 
 
 
-#include "linux/slab.h"
+
+
+int cpqfcTSGetLPSM(PTACHYON fcChip, char cErrorString[])
+{
+	// Tachyon's Frame Manager LPSM in LinkDown state?
+	// (For non-loop port, check PSM instead.)
+	// return string with state and FALSE is Link Down
+
+	int LinkUp;
+
+	if (fcChip->Registers.FMstatus.value & 0x80)
+		LinkUp = FALSE;
+	else
+		LinkUp = TRUE;
+
+	sprintf(&cErrorString[strlen(cErrorString)], " LPSM %Xh ", (fcChip->Registers.FMstatus.value >> 4) & 0xf);
+
+
+	switch (fcChip->Registers.FMstatus.value & 0xF0) {
+		// bits set in LPSM
+	case 0x10:
+		sprintf(&cErrorString[strlen(cErrorString)], "ARB");
+		break;
+	case 0x20:
+		sprintf(&cErrorString[strlen(cErrorString)], "ARBwon");
+		break;
+	case 0x30:
+		sprintf(&cErrorString[strlen(cErrorString)], "OPEN");
+		break;
+	case 0x40:
+		sprintf(&cErrorString[strlen(cErrorString)], "OPENed");
+		break;
+	case 0x50:
+		sprintf(&cErrorString[strlen(cErrorString)], "XmitCLS");
+		break;
+	case 0x60:
+		sprintf(&cErrorString[strlen(cErrorString)], "RxCLS");
+		break;
+	case 0x70:
+		sprintf(&cErrorString[strlen(cErrorString)], "Xfer");
+		break;
+	case 0x80:
+		sprintf(&cErrorString[strlen(cErrorString)], "Init");
+		break;
+	case 0x90:
+		sprintf(&cErrorString[strlen(cErrorString)], "O-IInitFin");
+		break;
+	case 0xa0:
+		sprintf(&cErrorString[strlen(cErrorString)], "O-IProtocol");
+		break;
+	case 0xb0:
+		sprintf(&cErrorString[strlen(cErrorString)], "O-ILipRcvd");
+		break;
+	case 0xc0:
+		sprintf(&cErrorString[strlen(cErrorString)], "HostControl");
+		break;
+	case 0xd0:
+		sprintf(&cErrorString[strlen(cErrorString)], "LoopFail");
+		break;
+	case 0xe0:
+		sprintf(&cErrorString[strlen(cErrorString)], "Offline");
+		break;
+	case 0xf0:
+		sprintf(&cErrorString[strlen(cErrorString)], "OldPort");
+		break;
+	case 0:
+	default:
+		sprintf(&cErrorString[strlen(cErrorString)], "Monitor");
+		break;
+
+	}
+
+	return LinkUp;
+}
 
 // Dynamic memory allocation alignment routines
 // HP's Tachyon Fibre Channel Controller chips require
@@ -1885,96 +1705,86 @@
 // we need about 8 allocations per HBA.  Figuring at most 10 HBAs per server
 // size the dynamic_mem array at 80.
 
-void* fcMemManager( struct pci_dev *pdev, ALIGNED_MEM *dynamic_mem, 
-		   ULONG n_alloc, ULONG ab, ULONG u32_AlignedAddress,
-			dma_addr_t *dma_handle)
-{
-  USHORT allocBoundary=1;   // compiler specific - worst case 1
-                                  // best case - replace malloc() call
-                                  // with function that allocates exactly
-                                  // at desired boundary
-
-  unsigned long ulAddress;
-  ULONG t_alloc, i;
-  void *alloc_address = 0;  // def. error code / address not found
-  LONG mask;                // must be 32-bits wide!
-
-  ENTER("fcMemManager");
-  if( u32_AlignedAddress )          // are we freeing existing memory?
-  {
+void *fcMemManager(struct pci_dev *pdev, ALIGNED_MEM * dynamic_mem, u32 n_alloc, u32 ab, u32 u32_AlignedAddress, dma_addr_t * dma_handle)
+{
+	u16 allocBoundary = 1;	// compiler specific - worst case 1
+	// best case - replace malloc() call
+	// with function that allocates exactly
+	// at desired boundary
+
+	unsigned long ulAddress;
+	u32 t_alloc, i;
+	void *alloc_address = 0;	// def. error code / address not found
+	s32 mask;		// must be 32-bits wide!
+
+	ENTER("fcMemManager");
+	if (u32_AlignedAddress)	// are we freeing existing memory?
+	{
 //    printk(" freeing AlignedAddress %Xh\n", u32_AlignedAddress);
-    for( i=0; i<DYNAMIC_ALLOCATIONS; i++) // look for the base address
-    {
+		for (i = 0; i < DYNAMIC_ALLOCATIONS; i++)	// look for the base address
+		{
 //    printk("dynamic_mem[%u].AlignedAddress %lX\n", i, dynamic_mem[i].AlignedAddress);
-      if( dynamic_mem[i].AlignedAddress == u32_AlignedAddress )
-      {
-        alloc_address = dynamic_mem[i].BaseAllocated; // 'success' status
-	pci_free_consistent(pdev,dynamic_mem[i].size, 
-				alloc_address, 
-				dynamic_mem[i].dma_handle);
-        dynamic_mem[i].BaseAllocated = 0;   // clear for next use
-        dynamic_mem[i].AlignedAddress = 0;
-        dynamic_mem[i].size = 0;
-        break;                        // quit for loop; done
-      }
-    }
-  }
-  else if( n_alloc )                   // want new memory?
-  {
-    dma_addr_t handle;
-    t_alloc = n_alloc + (ab - allocBoundary); // pad bytes for alignment
+			if (dynamic_mem[i].AlignedAddress == u32_AlignedAddress) {
+				alloc_address = dynamic_mem[i].BaseAllocated;	// 'success' status
+				pci_free_consistent(pdev, dynamic_mem[i].size, alloc_address, dynamic_mem[i].dma_handle);
+				dynamic_mem[i].BaseAllocated = 0;	// clear for next use
+				dynamic_mem[i].AlignedAddress = 0;
+				dynamic_mem[i].size = 0;
+				break;	// quit for loop; done
+			}
+		}
+	} else if (n_alloc)	// want new memory?
+	{
+		dma_addr_t handle;
+		t_alloc = n_alloc + (ab - allocBoundary);	// pad bytes for alignment
 //    printk("pci_alloc_consistent() for Tach alignment: %ld bytes\n", t_alloc);
 
 // (would like to) allow thread block to free pages 
-    alloc_address =                  // total bytes (NumberOfBytes)
-      pci_alloc_consistent(pdev, t_alloc, &handle); 
+		alloc_address =	// total bytes (NumberOfBytes)
+		    pci_alloc_consistent(pdev, t_alloc, &handle);
 
-                                  // now mask off least sig. bits of address
-    if( alloc_address )           // (only if non-NULL)
-    {
-                                  // find place to store ptr, so we
-                                  // can free it later...
-
-      mask = (LONG)(ab - 1);            // mask all low-order bits
-      mask = ~mask;                            // invert bits
-      for( i=0; i<DYNAMIC_ALLOCATIONS; i++) // look for free slot
-      {
-        if( dynamic_mem[i].BaseAllocated == 0) // take 1st available
-        {
-          dynamic_mem[i].BaseAllocated = alloc_address;// address from O/S
-          dynamic_mem[i].dma_handle = handle;
-	  if (dma_handle != NULL) 
-	  {
+		// now mask off least sig. bits of address
+		if (alloc_address)	// (only if non-NULL)
+		{
+			// find place to store ptr, so we
+			// can free it later...
+
+			mask = (s32) (ab - 1);	// mask all low-order bits
+			mask = ~mask;	// invert bits
+			for (i = 0; i < DYNAMIC_ALLOCATIONS; i++)	// look for free slot
+			{
+				if (dynamic_mem[i].BaseAllocated == 0)	// take 1st available
+				{
+					dynamic_mem[i].BaseAllocated = alloc_address;	// address from O/S
+					dynamic_mem[i].dma_handle = handle;
+					if (dma_handle != NULL) {
 //             printk("handle = %p, ab=%d, boundary = %d, mask=0x%08x\n", 
-//			handle, ab, allocBoundary, mask);
-	    *dma_handle = (dma_addr_t) 
-		((((ULONG)handle) + (ab - allocBoundary)) & mask);
-	  }
-          dynamic_mem[i].size = t_alloc;
-          break;
-        }
-      }
-      ulAddress = (unsigned long)alloc_address;
-      
-      ulAddress += (ab - allocBoundary);    // add the alignment bytes-
-                                            // then truncate address...
-      alloc_address = (void*)(ulAddress & mask);
-      
-      dynamic_mem[i].AlignedAddress = 
-	(ULONG)(ulAddress & mask); // 32bit Tach address
-      memset( alloc_address, 0, n_alloc );  // clear new memory
-    }
-    else  // O/S dynamic mem alloc failed!
-      alloc_address = 0;  // (for debugging breakpt)
+//                      handle, ab, allocBoundary, mask);
+						*dma_handle = (dma_addr_t)
+						    ((((u32) handle) + (ab - allocBoundary)) & mask);
+					}
+					dynamic_mem[i].size = t_alloc;
+					break;
+				}
+			}
+			ulAddress = (unsigned long) alloc_address;
+
+			ulAddress += (ab - allocBoundary);	// add the alignment bytes-
+			// then truncate address...
+			alloc_address = (void *) (ulAddress & mask);
+
+			dynamic_mem[i].AlignedAddress = (u32) (ulAddress & mask);	// 32bit Tach address
+			memset(alloc_address, 0, n_alloc);	// clear new memory
+		} else		// O/S dynamic mem alloc failed!
+			alloc_address = 0;	// (for debugging breakpt)
 
-  }
+	}
 
-  LEAVE("fcMemManager");
-  return alloc_address;  // good (or NULL) address
+	LEAVE("fcMemManager");
+	return alloc_address;	// good (or NULL) address
 }
 
 
 static Scsi_Host_Template driver_template = CPQFCTS;
 
 #include "scsi_module.c"
-

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