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

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

diff -urN linux-2.4.20/drivers/scsi/cpqfcTSworker.c linux-2.4.21/drivers/scsi/cpqfcTSworker.c
@@ -44,7 +44,7 @@
 
 
 #include "sd.h"
-#include "hosts.h"   // struct Scsi_Host definition for T handler
+#include "hosts.h"		// struct Scsi_Host definition for T handler
 #include "cpqfcTSchip.h"
 #include "cpqfcTSstructs.h"
 #include "cpqfcTStrigger.h"
@@ -116,724 +116,579 @@
 
 // local functions
 
-static void SetLoginFields(
-  PFC_LOGGEDIN_PORT pLoggedInPort,
-  TachFCHDR_GCMND* fchs,
-  BOOLEAN PDisc,
-  BOOLEAN Originator);
+static void SetLoginFields(PFC_LOGGEDIN_PORT pLoggedInPort, TachFCHDR_GCMND * fchs, u8 PDisc, u8 Originator);
 
-static void AnalyzeIncomingFrame( 
-       CPQFCHBA *cpqfcHBAdata,
-       ULONG QNdx );
+static void AnalyzeIncomingFrame(CPQFCHBA * dev, u32 QNdx);
 
-static void SendLogins( CPQFCHBA *cpqfcHBAdata, __u32 *FabricPortIds );
+static void SendLogins(CPQFCHBA * dev, __u32 * FabricPortIds);
 
-static int verify_PLOGI( PTACHYON fcChip,
-      TachFCHDR_GCMND* fchs, ULONG* reject_explain);
-static int verify_PRLI( TachFCHDR_GCMND* fchs, ULONG* reject_explain);
+static int verify_PLOGI(PTACHYON fcChip, TachFCHDR_GCMND * fchs, u32 * reject_explain);
+static int verify_PRLI(TachFCHDR_GCMND * fchs, u32 * reject_explain);
 
-static void LoadWWN( PTACHYON fcChip, UCHAR* dest, UCHAR type);
-static void BuildLinkServicePayload( 
-              PTACHYON fcChip, ULONG type, void* payload);
+static void LoadWWN(PTACHYON fcChip, u8 * dest, u8 type);
+static void BuildLinkServicePayload(PTACHYON fcChip, u32 type, void *payload);
 
-static void UnblockScsiDevice( struct Scsi_Host *HostAdapter, 
-        PFC_LOGGEDIN_PORT pLoggedInPort);
+static void UnblockScsiDevice(struct Scsi_Host *HostAdapter, PFC_LOGGEDIN_PORT pLoggedInPort);
 
-static void cpqfcTSCheckandSnoopFCP( PTACHYON fcChip, ULONG x_ID);
+static void cpqfcTSCheckandSnoopFCP(PTACHYON fcChip, u32 x_ID);
 
-static void CompleteBoardLockCmnd( CPQFCHBA *cpqfcHBAdata);
+static void CompleteBoardLockCmnd(CPQFCHBA * dev);
 
-static void RevalidateSEST( struct Scsi_Host *HostAdapter, 
-		        PFC_LOGGEDIN_PORT pLoggedInPort);
+static void RevalidateSEST(struct Scsi_Host *HostAdapter, PFC_LOGGEDIN_PORT pLoggedInPort);
 
-static void IssueReportLunsCommand( 
-              CPQFCHBA* cpqfcHBAdata, 
-	      TachFCHDR_GCMND* fchs);
+static void IssueReportLunsCommand(CPQFCHBA * dev, TachFCHDR_GCMND * fchs);
 
 // (see scsi_error.c comments on kernel task creation)
 
-void cpqfcTSWorkerThread( void *host)
+void cpqfcTSWorkerThread(void *host)
 {
-  struct Scsi_Host *HostAdapter = (struct Scsi_Host*)host;
-  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata; 
+	struct Scsi_Host *shpnt = (struct Scsi_Host *) host;
+	CPQFCHBA *dev = (CPQFCHBA *) shpnt->hostdata;
 #ifdef PCI_KERNEL_TRACE
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
+	PTACHYON fcChip = &dev->fcChip;
 #endif
-  struct fs_struct *fs;
-  DECLARE_MUTEX_LOCKED(fcQueReady);
-  DECLARE_MUTEX_LOCKED(fcTYOBcomplete); 
-  DECLARE_MUTEX_LOCKED(TachFrozen);  
-  DECLARE_MUTEX_LOCKED(BoardLock);  
+	struct fs_struct *fs;
+	DECLARE_MUTEX_LOCKED(fcQueReady);
+	DECLARE_MUTEX_LOCKED(fcTYOBcomplete);
+	DECLARE_MUTEX_LOCKED(TachFrozen);
+	DECLARE_MUTEX_LOCKED(BoardLock);
 
-  ENTER("WorkerThread");
+	ENTER("WorkerThread");
 
-  lock_kernel();
+	lock_kernel();
 	/*
 	 * If we were started as result of loading a module, close all of the
 	 * user space pages.  We don't need them, and if we didn't close them
 	 * they would be locked into memory.
+	 *
+	 * FIXME: should use daemonize!
 	 */
-  exit_mm(current);
+	exit_mm(current);
 
-  current->session = 1;
-  current->pgrp = 1;
-	
-  /* Become as one with the init task */
-	
-  exit_fs(current);	/* current->fs->count--; */
-  fs = init_task.fs;
-  // Some kernels compiled for SMP, while actually running
-  // on a uniproc machine, will return NULL for this call
-  if( !fs)
-  {
-    printk(" cpqfcTS FATAL: fs is NULL! Is this an SMP kernel on uniproc machine?\n ");
-  }
- 
-  else
-  { 
-    current->fs = fs;
-    atomic_inc(&fs->count);
-  }
+	current->session = 1;
+	current->pgrp = 1;
 
-  siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
+	/* Become as one with the init task */
 
+	exit_fs(current);	/* current->fs->count--; */
+	fs = init_task.fs;
+	current->fs = fs;
+	atomic_inc(&fs->count);
 
-  /*
-   * Set the name of this process.
-   */
-  sprintf(current->comm, "cpqfcTS_wt_%d", HostAdapter->host_no);
+	siginitsetinv(&current->blocked, SHUTDOWN_SIGS);
 
-  cpqfcHBAdata->fcQueReady = &fcQueReady;  // primary wait point
-  cpqfcHBAdata->TYOBcomplete = &fcTYOBcomplete;
-  cpqfcHBAdata->TachFrozen = &TachFrozen;
-    
- 
-  cpqfcHBAdata->worker_thread = current;
-  
-  unlock_kernel();
 
-  if( cpqfcHBAdata->notify_wt != NULL )
-    up( cpqfcHBAdata->notify_wt); // OK to continue
+	/*
+	 * Set the name of this process.
+	 */
+	sprintf(current->comm, "cpqfcTS_wt_%d", shpnt->host_no);
 
-  while(1)
-  {
-    unsigned long flags;
+	dev->fcQueReady = &fcQueReady;	// primary wait point
+	dev->TYOBcomplete = &fcTYOBcomplete;
+	dev->TachFrozen = &TachFrozen;
 
-    down_interruptible( &fcQueReady);  // wait for something to do
 
-    if (signal_pending(current) )
-      break;
-    
-    PCI_TRACE( 0x90)
-    // first, take the IO lock so the SCSI upper layers can't call
-    // into our _quecommand function (this also disables INTs)
-    spin_lock_irqsave( &io_request_lock, flags); // STOP _que function
-    PCI_TRACE( 0x90)
-         
-    CPQ_SPINLOCK_HBA( cpqfcHBAdata)
-    // next, set this pointer to indicate to the _quecommand function
-    // that the board is in use, so it should que the command and 
-    // immediately return (we don't actually require the semaphore function
-    // in this driver rev)
+	dev->worker_thread = current;
 
-    cpqfcHBAdata->BoardLock = &BoardLock;
+	unlock_kernel();
 
-    PCI_TRACE( 0x90)
+	if (dev->notify_wt != NULL)
+		up(dev->notify_wt);	// OK to continue
 
-    // release the IO lock (and re-enable interrupts)
-    spin_unlock_irqrestore( &io_request_lock, flags);
+	while (1) {
+		unsigned long flags;
 
-    // disable OUR HBA interrupt (keep them off as much as possible
-    // during error recovery)
-    disable_irq( cpqfcHBAdata->HostAdapter->irq);
+		down_interruptible(&fcQueReady);	// wait for something to do
 
-    // OK, let's process the Fibre Channel Link Q and do the work
-    cpqfcTS_WorkTask( HostAdapter);
+		if (signal_pending(current))
+			break;
 
-    // hopefully, no more "work" to do;
-    // re-enable our INTs for "normal" completion processing
-    enable_irq( cpqfcHBAdata->HostAdapter->irq);
- 
+		PCI_TRACE(0x90)
+		// first, take the IO lock so the SCSI upper layers can't call
+		// into our _quecommand function (this also disables INTs)
+		spin_lock_irqsave(&io_request_lock, flags);	// STOP _que function
+		PCI_TRACE(0x90)
 
-    cpqfcHBAdata->BoardLock = NULL; // allow commands to be queued
-    CPQ_SPINUNLOCK_HBA( cpqfcHBAdata)
+		CPQ_SPINLOCK_HBA(dev)
+		// next, set this pointer to indicate to the _quecommand function
+		// that the board is in use, so it should que the command and 
+		// immediately return (we don't actually require the semaphore function
+		// in this driver rev)
+		dev->BoardLock = &BoardLock;
 
+		PCI_TRACE(0x90)
+		// release the IO lock (and re-enable interrupts)
+		spin_unlock_irqrestore(&io_request_lock, flags);
 
-    // Now, complete any Cmnd we Q'd up while BoardLock was held
+		// disable OUR HBA interrupt (keep them off as much as possible
+		// during error recovery)
+		disable_irq(dev->HostAdapter->irq);
 
-    CompleteBoardLockCmnd( cpqfcHBAdata);
-  
+		// OK, let's process the Fibre Channel Link Q and do the work
+		cpqfcTS_WorkTask(shpnt);
 
-  }
-  // hopefully, the signal was for our module exit...
-  if( cpqfcHBAdata->notify_wt != NULL )
-    up( cpqfcHBAdata->notify_wt); // yep, we're outta here
+		// hopefully, no more "work" to do;
+		// re-enable our INTs for "normal" completion processing
+		enable_irq(dev->HostAdapter->irq);
+
+
+		dev->BoardLock = NULL;	// allow commands to be queued
+		CPQ_SPINUNLOCK_HBA(dev)
+
+		// Now, complete any Cmnd we Q'd up while BoardLock was held
+		CompleteBoardLockCmnd(dev);
+
+
+	}
+	// hopefully, the signal was for our module exit...
+	if (dev->notify_wt != NULL)
+		up(dev->notify_wt);	// yep, we're outta here
 }
 
 
 // Freeze Tachyon routine.
-// If Tachyon is already frozen, return FALSE
-// If Tachyon is not frozen, call freeze function, return TRUE
+// If Tachyon is already frozen, return 0
+// If Tachyon is not frozen, call freeze function, return 1
 //
-static BOOLEAN FreezeTach( CPQFCHBA *cpqfcHBAdata)
+static u8 FreezeTach(CPQFCHBA * dev)
 {
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  BOOLEAN FrozeTach = FALSE;
-  // It's possible that the chip is already frozen; if so,
-  // "Freezing" again will NOT! generate another Freeze
-  // Completion Message.
-
-  if( (fcChip->Registers.TYstatus.value & 0x70000) != 0x70000)
-  {  // (need to freeze...)
-    fcChip->FreezeTachyon( fcChip, 2);  // both ERQ and FCP assists
-
-    // 2. Get Tach freeze confirmation
-    // (synchronize SEST manipulation with Freeze Completion Message)
-    // we need INTs on so semaphore can be set.	
-    enable_irq( cpqfcHBAdata->HostAdapter->irq); // only way to get Semaphore
-    down_interruptible( cpqfcHBAdata->TachFrozen); // wait for INT handler sem.
-    // can we TIMEOUT semaphore wait?? TBD
-    disable_irq( cpqfcHBAdata->HostAdapter->irq); 
-
-    FrozeTach = TRUE;
-  }  // (else, already frozen)
- 
-  return FrozeTach;
-}  
-
-
-
+	PTACHYON fcChip = &dev->fcChip;
+	u8 FrozeTach = 0;
+	// It's possible that the chip is already frozen; if so,
+	// "Freezing" again will NOT! generate another Freeze
+	// Completion Message.
+
+	if ((fcChip->Registers.TYstatus.value & 0x70000) != 0x70000) {	// (need to freeze...)
+		fcChip->FreezeTachyon(fcChip, 2);	// both ERQ and FCP assists
+		// 2. Get Tach freeze confirmation
+		// (synchronize SEST manipulation with Freeze Completion Message)
+		// we need INTs on so semaphore can be set. 
+		enable_irq(dev->HostAdapter->irq);	// only way to get Semaphore
+		down_interruptible(dev->TachFrozen);	// wait for INT handler sem.
+		// can we TIMEOUT semaphore wait?? TBD
+		disable_irq(dev->HostAdapter->irq);
+		FrozeTach = 1;
+	}			// (else, already frozen)
+	return FrozeTach;
+}
 
 // This is the kernel worker thread task, which processes FC
 // tasks which were queued by the Interrupt handler or by
 // other WorkTask functions.
 
 #define DBG 1
+
 //#undef DBG
-void cpqfcTS_WorkTask( struct Scsi_Host *HostAdapter)
+void cpqfcTS_WorkTask(struct Scsi_Host *shpnt)
 {
-  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  ULONG QconsumerNdx;
-  LONG ExchangeID;
-  ULONG ulStatus=0;
-  TachFCHDR_GCMND fchs;
-  PFC_LINK_QUE fcLQ = cpqfcHBAdata->fcLQ;
-
-  ENTER("WorkTask");
-
-  // copy current index to work on
-  QconsumerNdx = fcLQ->consumer;
-
-  PCI_TRACEO( fcLQ->Qitem[QconsumerNdx].Type, 0x90)
-  
-
-  // NOTE: when this switch completes, we will "consume" the Que item
-//  printk("Que type %Xh\n", fcLQ->Qitem[QconsumerNdx].Type);
-  switch( fcLQ->Qitem[QconsumerNdx].Type )
-  {
-      // incoming frame - link service (ACC, UNSOL REQ, etc.)
-      // or FCP-SCSI command
-    case SFQ_UNKNOWN:  
-      AnalyzeIncomingFrame( cpqfcHBAdata, QconsumerNdx );
+	CPQFCHBA *dev = (CPQFCHBA *) shpnt->hostdata;
+	PTACHYON fcChip = &dev->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	u32 QconsumerNdx;
+	s32 ExchangeID;
+	u32 ulStatus = 0;
+	TachFCHDR_GCMND fchs;
+	PFC_LINK_QUE fcLQ = dev->fcLQ;
+
+	ENTER("WorkTask");
+
+	// copy current index to work on
+	QconsumerNdx = fcLQ->consumer;
+
+	PCI_TRACEO(fcLQ->Qitem[QconsumerNdx].Type, 0x90)
+
+	// NOTE: when this switch completes, we will "consume" the Que item
+	//  printk("Que type %Xh\n", fcLQ->Qitem[QconsumerNdx].Type);
+	switch (fcLQ->Qitem[QconsumerNdx].Type) 
+	{
+		// incoming frame - link service (ACC, UNSOL REQ, etc.)
+		// or FCP-SCSI command
+	case SFQ_UNKNOWN:
+		AnalyzeIncomingFrame(dev, QconsumerNdx);
+		break;
 
-      break;
-  
-    
-    
-    case EXCHANGE_QUEUED:  // an Exchange (i.e. FCP-SCSI) was previously
-                           // Queued because the link was down.  The  
-                           // heartbeat timer detected it and Queued it here.
-                           // We attempt to start it again, and if
-                           // successful we clear the EXCHANGE_Q flag.
-                           // If the link doesn't come up, the Exchange
-                           // will eventually time-out.
-
-      ExchangeID = (LONG)  // x_ID copied from DPC timeout function
-                   fcLQ->Qitem[QconsumerNdx].ulBuff[0];
-
-      // It's possible that a Q'd exchange could have already
-      // been started by other logic (e.g. ABTS process)
-      // Don't start if already started (Q'd flag clear)
-
-      if( Exchanges->fcExchange[ExchangeID].status & EXCHANGE_QUEUED )
-      {
-//        printk(" *Start Q'd x_ID %Xh: type %Xh ", 
-//          ExchangeID, Exchanges->fcExchange[ExchangeID].type);
-      
-        ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID);
-        if( !ulStatus )
-        {
-//          printk("success* ");
-        }	
-        else
-        {
+	case EXCHANGE_QUEUED:	
+		// an Exchange (i.e. FCP-SCSI) was previously
+		// Queued because the link was down.  The  
+		// heartbeat timer detected it and Queued it here.
+		// We attempt to start it again, and if
+		// successful we clear the EXCHANGE_Q flag.
+		// If the link doesn't come up, the Exchange
+		// will eventually time-out.
+
+		ExchangeID = (s32) fcLQ->Qitem[QconsumerNdx].ulBuff[0]; // x_ID copied from DPC timeout function
+
+		// It's possible that a Q'd exchange could have already
+		// been started by other logic (e.g. ABTS process)
+		// Don't start if already started (Q'd flag clear)
+
+		if (Exchanges->fcExchange[ExchangeID].status & EXCHANGE_QUEUED) {
+//      		printk(" *Start Q'd x_ID %Xh: type %Xh ", 
+//				ExchangeID, Exchanges->fcExchange[ExchangeID].type);
+
+			ulStatus = cpqfcTSStartExchange(dev, ExchangeID);
+			if (!ulStatus) {
+//				printk("success* ");
+			} else {
 #ifdef DBG
-      
-          if( ulStatus == EXCHANGE_QUEUED)
-            printk("Queued* ");
-          else
-            printk("failed* ");
-		
+				if (ulStatus == EXCHANGE_QUEUED)
+					printk("Queued* ");
+				else
+					printk("failed* ");
 #endif
-	} 
-      }
-      break;
+			}
+		}
+		break;
 
+	case LINKDOWN:
+		// (lots of things already done in INT handler) future here?
+		break;
 
-    case LINKDOWN:  
-      // (lots of things already done in INT handler) future here?
-      break;
-    
-    
-    case LINKACTIVE:   // Tachyon set the Lup bit in FM status
-                       // NOTE: some misbehaving FC ports (like Tach2.1)
-                       // can re-LIP immediately after a LIP completes.
-      
-      // if "initiator", need to verify LOGs with ports
-//      printk("\n*LNKUP* ");
+	case LINKACTIVE:	// Tachyon set the Lup bit in FM status
+		// NOTE: some misbehaving FC ports (like Tach2.1)
+		// can re-LIP immediately after a LIP completes.
+		// if "initiator", need to verify LOGs with ports
+//		printk("\n*LNKUP* ");
+
+		if (fcChip->Options.initiator)
+			SendLogins(dev, NULL);	// PLOGI or PDISC, based on fcPort data
+		// if SendLogins successfully completes, PortDiscDone
+		// will be set.
+		// If SendLogins was successful, then we expect to get incoming
+		// ACCepts or REJECTs, which are handled below.
+		break;
 
-      if( fcChip->Options.initiator )
-        SendLogins( cpqfcHBAdata, NULL ); // PLOGI or PDISC, based on fcPort data
-                  // if SendLogins successfully completes, PortDiscDone
-                  // will be set.
-      
-      
-      // If SendLogins was successful, then we expect to get incoming
-      // ACCepts or REJECTs, which are handled below.
+		// LinkService and Fabric request/reply processing
+	case ELS_FDISC:	// need to send Fabric Discovery (Login)
+	case ELS_FLOGI:	// need to send Fabric Login
+	case ELS_SCR:		// need to send State Change Registration
+	case FCS_NSR:		// need to send Name Service Request
+	case ELS_PLOGI:	// need to send PLOGI
+	case ELS_ACC:		// send generic ACCept
+	case ELS_PLOGI_ACC:	// need to send ELS ACCept frame to recv'd PLOGI
+	case ELS_PRLI_ACC:	// need to send ELS ACCept frame to recv'd PRLI
+	case ELS_LOGO:		// need to send ELS LOGO (logout)
+	case ELS_LOGO_ACC:	// need to send ELS ACCept frame to recv'd PLOGI
+	case ELS_RJT:		// ReJecT reply
+	case ELS_PRLI:		// need to send ELS PRLI
+
+
+//		printk(" *ELS %Xh* ", fcLQ->Qitem[QconsumerNdx].Type);
+		// if PortDiscDone is not set, it means the SendLogins routine
+		// failed to complete -- assume that LDn occurred, so login frames
+		// are invalid
+		if (!dev->PortDiscDone)	// cleared by LDn
+		{
+			printk("Discard Q'd ELS login frame\n");
+			break;
+		}
 
-      break;
+		ulStatus = cpqfcTSBuildExchange(dev, fcLQ->Qitem[QconsumerNdx].Type,	// e.g. PLOGI
+						(TachFCHDR_GCMND *)
+						fcLQ->Qitem[QconsumerNdx].ulBuff,	// incoming fchs
+						NULL,	// no data (no scatter/gather list)
+						&ExchangeID);	// fcController->fcExchanges index, -1 if failed
+
+		if (!ulStatus)	// Exchange setup?
+		{
+			ulStatus = cpqfcTSStartExchange(dev, ExchangeID);
+			if (!ulStatus) {
+				// 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
+			{
 
-    // LinkService and Fabric request/reply processing
-    case ELS_FDISC:      // need to send Fabric Discovery (Login)
-    case ELS_FLOGI:      // need to send Fabric Login
-    case ELS_SCR:        // need to send State Change Registration
-    case FCS_NSR:        // need to send Name Service Request
-    case ELS_PLOGI:      // need to send PLOGI
-    case ELS_ACC:        // send generic ACCept
-    case ELS_PLOGI_ACC:  // need to send ELS ACCept frame to recv'd PLOGI
-    case ELS_PRLI_ACC:   // need to send ELS ACCept frame to recv'd PRLI
-    case ELS_LOGO:      // need to send ELS LOGO (logout)
-    case ELS_LOGO_ACC:  // need to send ELS ACCept frame to recv'd PLOGI
-    case ELS_RJT:         // ReJecT reply
-    case ELS_PRLI:       // need to send ELS PRLI
- 
-    
-//      printk(" *ELS %Xh* ", fcLQ->Qitem[QconsumerNdx].Type);
-      // if PortDiscDone is not set, it means the SendLogins routine
-      // failed to complete -- assume that LDn occurred, so login frames
-      // are invalid
-      if( !cpqfcHBAdata->PortDiscDone) // cleared by LDn
-      {
-        printk("Discard Q'd ELS login frame\n");
-        break;  
-      }
-
-      ulStatus = cpqfcTSBuildExchange(
-          cpqfcHBAdata,
-          fcLQ->Qitem[QconsumerNdx].Type, // e.g. PLOGI
-          (TachFCHDR_GCMND*)
-            fcLQ->Qitem[QconsumerNdx].ulBuff, // incoming fchs
-          NULL,         // no data (no scatter/gather list)
-          &ExchangeID );// fcController->fcExchanges index, -1 if failed
-
-      if( !ulStatus ) // Exchange setup?
-      {
-        ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );
-        if( !ulStatus )
-        {
-          // 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
-        {
-
-        }
-      }
-
-      else   // Xchange setup failed...
-        printk(" cpqfcTSBuildExchange failed: %Xh\n", ulStatus );
-
-      break;
-
-    case SCSI_REPORT_LUNS:
-      // pass the incoming frame (actually, it's a PRLI frame)
-      // so we can send REPORT_LUNS, in order to determine VSA/PDU
-      // FCP-SCSI Lun address mode
-      IssueReportLunsCommand( cpqfcHBAdata, (TachFCHDR_GCMND*)
-            fcLQ->Qitem[QconsumerNdx].ulBuff); 
+			}
+		}
 
-      break;
-      
+		else		// Xchange setup failed...
+			printk(" cpqfcTSBuildExchange failed: %Xh\n", ulStatus);
 
+		break;
 
+	case SCSI_REPORT_LUNS:
+		// pass the incoming frame (actually, it's a PRLI frame)
+		// so we can send REPORT_LUNS, in order to determine VSA/PDU
+		// FCP-SCSI Lun address mode
+		IssueReportLunsCommand(dev, (TachFCHDR_GCMND *)
+				       fcLQ->Qitem[QconsumerNdx].ulBuff);
 
-    case BLS_ABTS:       // need to ABORT one or more exchanges
-    {
-      LONG x_ID = fcLQ->Qitem[QconsumerNdx].ulBuff[0];
-      BOOLEAN FrozeTach = FALSE;   
-     
-      if( x_ID > TACH_SEST_LEN )  // (in)sanity check
-      {
-//	printk( " cpqfcTS ERROR! BOGUS x_ID %Xh", x_ID);
-	break;
-      }
-
-
-      if( Exchanges->fcExchange[ x_ID].Cmnd == NULL ) // should be RARE
-      {
-//	printk(" ABTS %Xh Scsi Cmnd null! ", x_ID);
-	
-       break;  // nothing to abort!
-      }
+		break;
 
+	case BLS_ABTS:		// need to ABORT one or more exchanges
+		{
+			s32 x_ID = fcLQ->Qitem[QconsumerNdx].ulBuff[0];
+			u8 FrozeTach = 0;
+
+			if (x_ID > TACH_SEST_LEN)	// (in)sanity check
+			{
+//				printk( " cpqfcTS ERROR! BOGUS x_ID %Xh", x_ID);
+				break;
+			}
+			if (Exchanges->fcExchange[x_ID].Cmnd == NULL)	// should be RARE
+			{
+//				printk(" ABTS %Xh Scsi Cmnd null! ", x_ID);
+				break;	// nothing to abort!
+			}
 //#define ABTS_DBG
 #ifdef ABTS_DBG
-      printk("INV SEST[%X] ", x_ID); 
-      if( Exchanges->fcExchange[x_ID].status & FC2_TIMEOUT)
-      {
-        printk("FC2TO");
-      }
-      if( Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT)
-      {
-        printk("IA");
-      }
-      if( Exchanges->fcExchange[x_ID].status & PORTID_CHANGED)
-      {
-        printk("PORTID");
-      }
-      if( Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED)
-      {
-        printk("DEVRM");
-      }
-      if( Exchanges->fcExchange[x_ID].status & LINKFAIL_TX)
-      {
-        printk("LKF");
-      }
-      if( Exchanges->fcExchange[x_ID].status & FRAME_TO)
-      {
-        printk("FRMTO");
-      }
-      if( Exchanges->fcExchange[x_ID].status & ABORTSEQ_NOTIFY)
-      {
-        printk("ABSQ");
-      }
-      if( Exchanges->fcExchange[x_ID].status & SFQ_FRAME)
-      {
-        printk("SFQFR");
-      }
-
-      if( Exchanges->fcExchange[ x_ID].type == 0x2000)
-        printk(" WR");
-      else if( Exchanges->fcExchange[ x_ID].type == 0x3000)
-        printk(" RD");
-      else if( Exchanges->fcExchange[ x_ID].type == 0x10)
-        printk(" ABTS");
-      else
-        printk(" %Xh", Exchanges->fcExchange[ x_ID].type); 
-
-      if( !(Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT))
-      {
-	printk(" Cmd %p, ", 
-          Exchanges->fcExchange[ x_ID].Cmnd);
-
-        printk(" brd/chn/trg/lun %d/%d/%d/%d port_id %06X\n", 
-          cpqfcHBAdata->HBAnum,
-          Exchanges->fcExchange[ x_ID].Cmnd->channel,
-          Exchanges->fcExchange[ x_ID].Cmnd->target,
-          Exchanges->fcExchange[ x_ID].Cmnd->lun,
-          Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF);
-      }
-      else  // assume that Cmnd ptr is invalid on _abort()
-      {
-	printk(" Cmd ptr invalid\n");
-      }
-     
-#endif      
-
-      
-      // Steps to ABORT a SEST exchange:
-      // 1. Freeze TL SCSI assists & ERQ (everything)
-      // 2. Receive FROZEN inbound CM (must succeed!)
-      // 3. Invalidate x_ID SEST entry 
-      // 4. Resume TL SCSI assists & ERQ (everything)
-      // 5. Build/start on exchange - change "type" to BLS_ABTS,
-      //    timeout to X sec (RA_TOV from PLDA is actually 0)
-      // 6. Set Exchange Q'd status if ABTS cannot be started,
-      //    or simply complete Exchange in "Terminate" condition
-
-  PCI_TRACEO( x_ID, 0xB4)
-      
-      // 1 & 2 . Freeze Tach & get confirmation of freeze
-      FrozeTach = FreezeTach( cpqfcHBAdata);
-
-      // 3. OK, Tachyon is frozen, so we can invalidate SEST exchange.
-      // FC2_TIMEOUT means we are originating the abort, while
-      // TARGET_ABORT means we are ACCepting an abort.
-      // LINKFAIL_TX, ABORTSEQ_NOFITY, INV_ENTRY or FRAME_TO are 
-      // all from Tachyon:
-      // Exchange was corrupted by LDn or other FC physical failure
-      // INITIATOR_ABORT means the upper layer driver/application
-      // requested the abort.
-
-
-	  
-      // clear bit 31 (VALid), to invalidate & take control from TL
-      fcChip->SEST->u[ x_ID].IWE.Hdr_Len &= 0x7FFFFFFF;
-
-
-      // examine and Tach's "Linked List" for IWEs that 
-      // received (nearly) simultaneous transfer ready (XRDY) 
-      // repair linked list if necessary (TBD!)
-      // (If we ignore the "Linked List", we will time out
-      // WRITE commands where we received the FCP-SCSI XFRDY
-      // frame (because Tachyon didn't processes it).  Linked List
-      // management should be done as an optimization.
-
-//       readl( fcChip->Registers.ReMapMemBase+TL_MEM_SEST_LINKED_LIST ));
-
-
-      
-
-      // 4. Resume all Tachlite functions (for other open Exchanges)
-      // as quickly as possible to allow other exchanges to other ports
-      // to resume.  Freezing Tachyon may cause cascading errors, because
-      // any received SEST frame cannot be processed by the SEST.
-      // Don't "unfreeze" unless Link is operational
-      if( FrozeTach )  // did we just freeze it (above)?
-        fcChip->UnFreezeTachyon( fcChip, 2);  // both ERQ and FCP assists
-      
-
-  PCI_TRACEO( x_ID, 0xB4)
-
-      // Note there is no confirmation that the chip is "unfrozen".  Also,
-      // if the Link is down when unfreeze is called, it has no effect.
-      // Chip will unfreeze when the Link is back up.
-
-      // 5. Now send out Abort commands if possible
-      // Some Aborts can't be "sent" (Port_id changed or gone);
-      // if the device is gone, there is no port_id to send the ABTS to.
-
-      if( !(Exchanges->fcExchange[ x_ID].status & PORTID_CHANGED)
-			  &&
-          !(Exchanges->fcExchange[ x_ID].status & DEVICE_REMOVED) )
-      {
-        Exchanges->fcExchange[ x_ID].type = BLS_ABTS;
-        fchs.s_id = Exchanges->fcExchange[ x_ID].fchs.d_id;
-        ulStatus = cpqfcTSBuildExchange(
-          cpqfcHBAdata,
-          BLS_ABTS,
-          &fchs,        // (uses only s_id)
-          NULL,         // (no scatter/gather list for ABTS)
-          &x_ID );// ABTS on this Exchange ID
-
-        if( !ulStatus ) // Exchange setup build OK?
-        {
-
-            // ABTS may be needed because an Exchange was corrupted
-            // by a Link disruption.  If the Link is UP, we can
-	    // presume that this ABTS can start immediately; otherwise,
-	    // set Que'd status so the Login functions
-            // can restart it when the FC physical Link is restored
-          if( ((fcChip->Registers.FMstatus.value &0xF0) &0x80)) // loop init?
-          {			    
-//                printk(" *set Q status x_ID %Xh on LDn* ", x_ID);
-                Exchanges->fcExchange[ x_ID].status |= EXCHANGE_QUEUED;
-          }
-
-          else  // what FC device (port_id) does the Cmd belong to?
-          {
-            PFC_LOGGEDIN_PORT pLoggedInPort = 
-              Exchanges->fcExchange[ x_ID].pLoggedInPort;
-            
-            // if Port is logged in, we might start the abort.
-	
-            if( (pLoggedInPort != NULL) 
-			      &&
-                (pLoggedInPort->prli == TRUE) ) 
-            {
-              // it's possible that an Exchange has already been Queued
-              // to start after Login completes.  Check and don't
-	      // start it (again) here if Q'd status set
-//	    printk(" ABTS xchg %Xh ", x_ID);            
- 	      if( Exchanges->fcExchange[x_ID].status & EXCHANGE_QUEUED)
-	      {
-//		    printk("already Q'd ");
-	      }
-	      else
-	      {
-//	            printk("starting ");
-		
-                fcChip->fcStats.FC2aborted++; 
-                ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, x_ID );
-                if( !ulStatus )
-                {
-                    // OK
-                    // submitted to Tach's Outbound Que (ERQ PI incremented)
-                }
-                else
-                {
-/*                   printk("ABTS exchange start failed -status %Xh, x_ID %Xh ",
-                        ulStatus, x_ID);
-*/
-                } 
-	      }
-	    }
-	    else
-	    {
-/*         	  printk(" ABTS NOT starting xchg %Xh, %p ",
-			       x_ID, pLoggedInPort);
-	          if( pLoggedInPort )
-	            printk("prli %d ", pLoggedInPort->prli);
-*/
-	    }		
- 	  }
-        }
-        else  // what the #@!
-        {  // how do we fail to build an Exchange for ABTS??
-              printk("ABTS exchange build failed -status %Xh, x_ID %Xh\n",
-                ulStatus, x_ID);
-        }
-      }
-      else   // abort without ABTS -- just complete exchange/Cmnd to Linux
-      {
-//            printk(" *Terminating x_ID %Xh on %Xh* ", 
-//		    x_ID, Exchanges->fcExchange[x_ID].status);
-        cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, x_ID);
-
-      }
-    } // end of ABTS case
-      break;
-
-
-
-    case BLS_ABTS_ACC:   // need to ACCept one ABTS
-                         // (NOTE! this code not updated for Linux yet..)
-      
-
-      printk(" *ABTS_ACC* ");
-      // 1. Freeze TL
-
-      fcChip->FreezeTachyon( fcChip, 2);  // both ERQ and FCP assists
+			printk("INV SEST[%X] ", x_ID);
+			if (Exchanges->fcExchange[x_ID].status & FC2_TIMEOUT) {
+				printk("FC2TO");
+			}
+			if (Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT) {
+				printk("IA");
+			}
+			if (Exchanges->fcExchange[x_ID].status & PORTID_CHANGED) {
+				printk("PORTID");
+			}
+			if (Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED) {
+				printk("DEVRM");
+			}
+			if (Exchanges->fcExchange[x_ID].status & LINKFAIL_TX) {
+				printk("LKF");
+			}
+			if (Exchanges->fcExchange[x_ID].status & FRAME_TO) {
+				printk("FRMTO");
+			}
+			if (Exchanges->fcExchange[x_ID].status & ABORTSEQ_NOTIFY) {
+				printk("ABSQ");
+			}
+			if (Exchanges->fcExchange[x_ID].status & SFQ_FRAME) {
+				printk("SFQFR");
+			}
 
-      memcpy(  // copy the incoming ABTS frame
-        &fchs,
-        fcLQ->Qitem[QconsumerNdx].ulBuff, // incoming fchs
-        sizeof( fchs));
-
-      // 3. OK, Tachyon is frozen so we can invalidate SEST entry 
-      // (if necessary)
-      // Status FC2_TIMEOUT means we are originating the abort, while
-      // TARGET_ABORT means we are ACCepting an abort
-      
-      ExchangeID = fchs.ox_rx_id & 0x7FFF; // RX_ID for exchange
-//      printk("ABTS ACC for Target ExchangeID %Xh\n", ExchangeID);
+			if (Exchanges->fcExchange[x_ID].type == 0x2000)
+				printk(" WR");
+			else if (Exchanges->fcExchange[x_ID].type == 0x3000)
+				printk(" RD");
+			else if (Exchanges->fcExchange[x_ID].type == 0x10)
+				printk(" ABTS");
+			else
+				printk(" %Xh", Exchanges->fcExchange[x_ID].type);
+
+			if (!(Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT)) {
+				printk(" Cmd %p, ", Exchanges->fcExchange[x_ID].Cmnd);
+
+				printk(" brd/chn/trg/lun %d/%d/%d/%d port_id %06X\n",
+				       dev->HBAnum, Exchanges->fcExchange[x_ID].Cmnd->channel, Exchanges->fcExchange[x_ID].Cmnd->target, Exchanges->fcExchange[x_ID].Cmnd->lun, Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF);
+			} else	// assume that Cmnd ptr is invalid on _abort()
+			{
+				printk(" Cmd ptr invalid\n");
+			}
+#endif
+			// Steps to ABORT a SEST exchange:
+			// 1. Freeze TL SCSI assists & ERQ (everything)
+			// 2. Receive FROZEN inbound CM (must succeed!)
+			// 3. Invalidate x_ID SEST entry 
+			// 4. Resume TL SCSI assists & ERQ (everything)
+			// 5. Build/start on exchange - change "type" to BLS_ABTS,
+			//    timeout to X sec (RA_TOV from PLDA is actually 0)
+			// 6. Set Exchange Q'd status if ABTS cannot be started,
+			//    or simply complete Exchange in "Terminate" condition
+
+			PCI_TRACEO(x_ID, 0xB4)
+			    // 1 & 2 . Freeze Tach & get confirmation of freeze
+			    FrozeTach = FreezeTach(dev);
+
+			// 3. OK, Tachyon is frozen, so we can invalidate SEST exchange.
+			// FC2_TIMEOUT means we are originating the abort, while
+			// TARGET_ABORT means we are ACCepting an abort.
+			// LINKFAIL_TX, ABORTSEQ_NOFITY, INV_ENTRY or FRAME_TO are 
+			// all from Tachyon:
+			// Exchange was corrupted by LDn or other FC physical failure
+			// INITIATOR_ABORT means the upper layer driver/application
+			// requested the abort.
+
+			// clear bit 31 (VALid), to invalidate & take control from TL
+			fcChip->SEST->u[x_ID].IWE.Hdr_Len &= 0x7FFFFFFF;
+
+			// examine and Tach's "Linked List" for IWEs that 
+			// received (nearly) simultaneous transfer ready (XRDY) 
+			// repair linked list if necessary (TBD!)
+			// (If we ignore the "Linked List", we will time out
+			// WRITE commands where we received the FCP-SCSI XFRDY
+			// frame (because Tachyon didn't processes it).  Linked List
+			// management should be done as an optimization.
+
+//			readl( fcChip->Registers.ReMapMemBase+TL_MEM_SEST_LINKED_LIST ));
+
+			// 4. Resume all Tachlite functions (for other open Exchanges)
+			// as quickly as possible to allow other exchanges to other ports
+			// to resume.  Freezing Tachyon may cause cascading errors, because
+			// any received SEST frame cannot be processed by the SEST.
+			// Don't "unfreeze" unless Link is operational
+			if (FrozeTach)	// did we just freeze it (above)?
+				fcChip->UnFreezeTachyon(fcChip, 2);	// both ERQ and FCP assists
+
+			PCI_TRACEO(x_ID, 0xB4)
+			    // Note there is no confirmation that the chip is "unfrozen".  Also,
+			    // if the Link is down when unfreeze is called, it has no effect.
+			    // Chip will unfreeze when the Link is back up.
+			    // 5. Now send out Abort commands if possible
+			    // Some Aborts can't be "sent" (Port_id changed or gone);
+			    // if the device is gone, there is no port_id to send the ABTS to.
+			if (!(Exchanges->fcExchange[x_ID].status & PORTID_CHANGED)
+				&& !(Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED)) {
+				Exchanges->fcExchange[x_ID].type = BLS_ABTS;
+				fchs.s_id = Exchanges->fcExchange[x_ID].fchs.d_id;
+				ulStatus = cpqfcTSBuildExchange(dev, BLS_ABTS, &fchs,	// (uses only s_id)
+								NULL,	// (no scatter/gather list for ABTS)
+								&x_ID);	// ABTS on this Exchange ID
+
+				if (!ulStatus)	// Exchange setup build OK?
+				{
+
+					// ABTS may be needed because an Exchange was corrupted
+					// by a Link disruption.  If the Link is UP, we can
+					// presume that this ABTS can start immediately; otherwise,
+					// set Que'd status so the Login functions
+					// can restart it when the FC physical Link is restored
+					if (((fcChip->Registers.FMstatus.value & 0xF0) & 0x80))	// loop init?
+					{
+//						printk(" *set Q status x_ID %Xh on LDn* ", x_ID);
+						Exchanges->fcExchange[x_ID].status |= EXCHANGE_QUEUED;
+					}
+
+					else	// what FC device (port_id) does the Cmd belong to?
+					{
+						PFC_LOGGEDIN_PORT pLoggedInPort = Exchanges->fcExchange[x_ID].pLoggedInPort;
+
+						// if Port is logged in, we might start the abort.
+
+						if ((pLoggedInPort != NULL)
+						    && (pLoggedInPort->prli == 1)) {
+							// it's possible that an Exchange has already been Queued
+							// to start after Login completes.  Check and don't
+							// start it (again) here if Q'd status set
+//							printk(" ABTS xchg %Xh ", x_ID);            
+							if (Exchanges->fcExchange[x_ID].status & EXCHANGE_QUEUED) {
+//								printk("already Q'd ");
+							} else {
+//								printk("starting ");
+								fcChip->fcStats.FC2aborted++;
+								ulStatus = cpqfcTSStartExchange(dev, x_ID);
+								if (!ulStatus) {
+									// OK
+									// submitted to Tach's Outbound Que (ERQ PI incremented)
+								} else {
+//									printk("ABTS exchange start failed -status %Xh, x_ID %Xh ", ulStatus, x_ID);
+								}
+							}
+						}
+					}
+				} else	// what the #@!
+				{	// how do we fail to build an Exchange for ABTS??
+					printk("ABTS exchange build failed -status %Xh, x_ID %Xh\n", ulStatus, x_ID);
+				}
+			} else	// abort without ABTS -- just complete exchange/Cmnd to Linux
+			{
+//				printk(" *Terminating x_ID %Xh on %Xh* ", 
+//					x_ID, Exchanges->fcExchange[x_ID].status);
+				cpqfcTSCompleteExchange(dev->PciDev, fcChip, x_ID);
 
+			}
+		}		// end of ABTS case
+		break;
 
-      // sanity check on received ExchangeID
-      if( Exchanges->fcExchange[ ExchangeID].status == TARGET_ABORT )
-      {
-          // clear bit 31 (VALid), to invalidate & take control from TL
-//          printk("Invalidating SEST exchange %Xh\n", ExchangeID);
-          fcChip->SEST->u[ ExchangeID].IWE.Hdr_Len &= 0x7FFFFFFF;
-      }
-
-
-      // 4. Resume all Tachlite functions (for other open Exchanges)
-      // as quickly as possible to allow other exchanges to other ports
-      // to resume.  Freezing Tachyon for too long may royally screw
-      // up everything!
-      fcChip->UnFreezeTachyon( fcChip, 2);  // both ERQ and FCP assists
-      
-      // Note there is no confirmation that the chip is "unfrozen".  Also,
-      // if the Link is down when unfreeze is called, it has no effect.
-      // Chip will unfreeze when the Link is back up.
+	case BLS_ABTS_ACC:	// need to ACCept one ABTS
+		// (NOTE! this code not updated for Linux yet..)
+		printk(" *ABTS_ACC* ");
+		// 1. Freeze TL
+
+		fcChip->FreezeTachyon(fcChip, 2);	// both ERQ and FCP assists
+		memcpy(		// copy the incoming ABTS frame
+			      &fchs, fcLQ->Qitem[QconsumerNdx].ulBuff,	// incoming fchs
+			      sizeof(fchs));
+
+		// 3. OK, Tachyon is frozen so we can invalidate SEST entry 
+		// (if necessary)
+		// Status FC2_TIMEOUT means we are originating the abort, while
+		// TARGET_ABORT means we are ACCepting an abort
+
+		ExchangeID = fchs.ox_rx_id & 0x7FFF;	// RX_ID for exchange
+//		printk("ABTS ACC for Target ExchangeID %Xh\n", ExchangeID);
+
+		// sanity check on received ExchangeID
+		if (Exchanges->fcExchange[ExchangeID].status == TARGET_ABORT) {
+			// clear bit 31 (VALid), to invalidate & take control from TL
+//			printk("Invalidating SEST exchange %Xh\n", ExchangeID);
+			fcChip->SEST->u[ExchangeID].IWE.Hdr_Len &= 0x7FFFFFFF;
+		}
 
-      // 5. Now send out Abort ACC reply for this exchange
-      Exchanges->fcExchange[ ExchangeID].type = BLS_ABTS_ACC;
-      
-      fchs.s_id = Exchanges->fcExchange[ ExchangeID].fchs.d_id;
-      ulStatus = cpqfcTSBuildExchange(
-            cpqfcHBAdata,
-            BLS_ABTS_ACC,
-            &fchs,
-            NULL,         // no data (no scatter/gather list)
-            &ExchangeID );// fcController->fcExchanges index, -1 if failed
-
-      if( !ulStatus ) // Exchange setup?
-      {
-        ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );
-        if( !ulStatus )
-        {
-          // 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
-        {
-
-        } 
-      }
-      break;
-
-
-    case BLS_ABTS_RJT:   // need to ReJecT one ABTS; reject implies the
-                         // exchange doesn't exist in the TARGET context.
-                         // ExchangeID has to come from LinkService space.
-
-      printk(" *ABTS_RJT* ");
-      ulStatus = cpqfcTSBuildExchange(
-            cpqfcHBAdata,
-            BLS_ABTS_RJT,
-            (TachFCHDR_GCMND*)
-              fcLQ->Qitem[QconsumerNdx].ulBuff, // incoming fchs
-            NULL,         // no data (no scatter/gather list)
-            &ExchangeID );// fcController->fcExchanges index, -1 if failed
-
-      if( !ulStatus ) // Exchange setup OK?
-      {
-        ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );
-        // If it fails, we aren't required to retry.
-      }
-      if( ulStatus )
-      {
-        printk("Failed to send BLS_RJT for ABTS, X_ID %Xh\n", ExchangeID);
-      }
-      else
-      {
-        printk("Sent BLS_RJT for ABTS, X_ID %Xh\n", ExchangeID);
-      
-      }
+		// 4. Resume all Tachlite functions (for other open Exchanges)
+		// as quickly as possible to allow other exchanges to other ports
+		// to resume.  Freezing Tachyon for too long may royally screw
+		// up everything!
+		fcChip->UnFreezeTachyon(fcChip, 2);	// both ERQ and FCP assists
+
+		// Note there is no confirmation that the chip is "unfrozen".  Also,
+		// if the Link is down when unfreeze is called, it has no effect.
+		// Chip will unfreeze when the Link is back up.
+
+		// 5. Now send out Abort ACC reply for this exchange
+		Exchanges->fcExchange[ExchangeID].type = BLS_ABTS_ACC;
+
+		fchs.s_id = Exchanges->fcExchange[ExchangeID].fchs.d_id;
+		ulStatus = cpqfcTSBuildExchange(dev, BLS_ABTS_ACC, &fchs, NULL,	// no data (no scatter/gather list)
+						&ExchangeID);	// fcController->fcExchanges index, -1 if failed
+
+		if (!ulStatus)	// Exchange setup?
+		{
+			ulStatus = cpqfcTSStartExchange(dev, ExchangeID);
+			if (!ulStatus) {
+				// 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
+			{
 
-      break;
+			}
+		}
+		break;
 
+	case BLS_ABTS_RJT:	// need to ReJecT one ABTS; reject implies the
+		// exchange doesn't exist in the TARGET context.
+		// ExchangeID has to come from LinkService space.
+
+		printk(" *ABTS_RJT* ");
+		ulStatus = cpqfcTSBuildExchange(dev, BLS_ABTS_RJT, (TachFCHDR_GCMND *)
+						fcLQ->Qitem[QconsumerNdx].ulBuff,	// incoming fchs
+						NULL,	// no data (no scatter/gather list)
+						&ExchangeID);	// fcController->fcExchanges index, -1 if failed
+
+		if (!ulStatus)	// Exchange setup OK?
+		{
+			ulStatus = cpqfcTSStartExchange(dev, ExchangeID);
+			// If it fails, we aren't required to retry.
+		}
+		if (ulStatus) {
+			printk("Failed to send BLS_RJT for ABTS, X_ID %Xh\n", ExchangeID);
+		} else {
+			printk("Sent BLS_RJT for ABTS, X_ID %Xh\n", ExchangeID);
 
+		}
+		break;
 
-    default:
-      break;
-  }                   // end switch
-//doNothing:
-    // done with this item - now set the NEXT index
+	default:
+		break;
+	}			// end switch
+	// done with this item - now set the NEXT index
 
-  if( QconsumerNdx+1 >= FC_LINKQ_DEPTH ) // rollover test
-  {
-    fcLQ->consumer = 0;
-  }
-  else
-  { 
-    fcLQ->consumer++;
-  }
+	if (QconsumerNdx + 1 >= FC_LINKQ_DEPTH)	// rollover test
+		fcLQ->consumer = 0;
+	else
+		fcLQ->consumer++;
 
-  PCI_TRACEO( fcLQ->Qitem[QconsumerNdx].Type, 0x94)
+	PCI_TRACEO(fcLQ->Qitem[QconsumerNdx].Type, 0x94)
 
-  LEAVE("WorkTask");
-  return;
+	LEAVE("WorkTask");
+	return;
 }
 
 
@@ -845,115 +700,89 @@
 // This circular Q works like Tachyon's que - the producer points to the next
 // (unused) entry.  Called by Interrupt handler, WorkerThread, Timer
 // sputlinkq
-void cpqfcTSPutLinkQue( CPQFCHBA *cpqfcHBAdata,
-  int Type, 
-  void *QueContent)
-{
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-//  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  PFC_LINK_QUE fcLQ = cpqfcHBAdata->fcLQ;
-  ULONG ndx;
-  
-  ENTER("cpqfcTSPutLinkQ");
-
-  ndx = fcLQ->producer;
-  
-  ndx += 1;  // test for Que full
-
-
-  
-  if( ndx >= FC_LINKQ_DEPTH ) // rollover test
-    ndx = 0;
+void cpqfcTSPutLinkQue(CPQFCHBA * dev, int Type, void *QueContent)
+{
+	PTACHYON fcChip = &dev->fcChip;
+//	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	PFC_LINK_QUE fcLQ = dev->fcLQ;
+	u32 ndx;
 
-  if( ndx == fcLQ->consumer )   // QUE full test
-  {
-                       // QUE was full! lost LK command (fatal to logic)
-    fcChip->fcStats.lnkQueFull++;
+	ENTER("cpqfcTSPutLinkQ");
 
-    printk("*LinkQ Full!*");
-    TriggerHBA( fcChip->Registers.ReMapMemBase, 1);
-/*
-    {
-      int i;
-      printk("LinkQ PI %d, CI %d\n", fcLQ->producer,
-        fcLQ->consumer);
-		      
-      for( i=0; i< FC_LINKQ_DEPTH; )
-      {
-	printk(" [%d]%Xh ", i, fcLQ->Qitem[i].Type);
-	if( (++i %8) == 0) printk("\n");
-      }
-  
-    }
-*/    
-    printk( "cpqfcTS: WARNING!! PutLinkQue - FULL!\n"); // we're hung
-  }
-  else                        // QUE next element
-  {
-    // Prevent certain multiple (back-to-back) requests.
-    // This is important in that we don't want to issue multiple
-    // ABTS for the same Exchange, or do multiple FM inits, etc.
-    // We can never be sure of the timing of events reported to
-    // us by Tach's IMQ, which can depend on system/bus speeds,
-    // FC physical link circumstances, etc.
-     
-    if( (fcLQ->producer != fcLQ->consumer)
-	    && 
-        (Type == FMINIT)  )
-    {
-      LONG lastNdx;  // compute previous producer index
-      if( fcLQ->producer)
-        lastNdx = fcLQ->producer- 1;
-      else
-	lastNdx = FC_LINKQ_DEPTH-1;
+	ndx = fcLQ->producer;
 
+	ndx += 1;		// test for Que full
 
-      if( fcLQ->Qitem[lastNdx].Type == FMINIT)
-      {
-//        printk(" *skip FMINIT Q post* ");
-//        goto DoneWithPutQ;
-      }
 
-    }
 
-    // OK, add the Q'd item...
-    
-    fcLQ->Qitem[fcLQ->producer].Type = Type;
-   
-    memcpy(
-        fcLQ->Qitem[fcLQ->producer].ulBuff,
-        QueContent, 
-        sizeof(fcLQ->Qitem[fcLQ->producer].ulBuff));
+	if (ndx >= FC_LINKQ_DEPTH)	// rollover test
+		ndx = 0;
 
-    fcLQ->producer = ndx;  // increment Que producer
+	if (ndx == fcLQ->consumer)	// QUE full test
+	{
+		// QUE was full! lost LK command (fatal to logic)
+		fcChip->fcStats.lnkQueFull++;
 
-    // set semaphore to wake up Kernel (worker) thread
-    // 
-    up( cpqfcHBAdata->fcQueReady );
-  }
+		printk("*LinkQ Full!*");
+		TriggerHBA(fcChip->Registers.ReMapMemBase, 1);
+/*
+		{
+			int i;
+			printk("LinkQ PI %d, CI %d\n", fcLQ->producer, fcLQ->consumer);
+		      
+			for( i=0; i< FC_LINKQ_DEPTH; )
+			{
+				printk(" [%d]%Xh ", i, fcLQ->Qitem[i].Type);
+				if( (++i %8) == 0)
+					printk("\n");
+			}
+		}
+*/
+		printk("cpqfcTS: WARNING!! PutLinkQue - FULL!\n");	// we're hung
+	}
+	else			// QUE next element
+	{
+		// Prevent certain multiple (back-to-back) requests.
+		// This is important in that we don't want to issue multiple
+		// ABTS for the same Exchange, or do multiple FM inits, etc.
+		// We can never be sure of the timing of events reported to
+		// us by Tach's IMQ, which can depend on system/bus speeds,
+		// FC physical link circumstances, etc.
+
+		if ((fcLQ->producer != fcLQ->consumer)
+		    && (Type == FMINIT)) {
+			s32 lastNdx;	// compute previous producer index
+			if (fcLQ->producer)
+				lastNdx = fcLQ->producer - 1;
+			else
+				lastNdx = FC_LINKQ_DEPTH - 1;
+
+
+			if (fcLQ->Qitem[lastNdx].Type == FMINIT) {
+//      			printk(" *skip FMINIT Q post* ");
+//        			goto DoneWithPutQ;
+			}
 
+		}
+		// OK, add the Q'd item...
+		fcLQ->Qitem[fcLQ->producer].Type = Type;
+		memcpy(fcLQ->Qitem[fcLQ->producer].ulBuff, QueContent, sizeof(fcLQ->Qitem[fcLQ->producer].ulBuff));
+		fcLQ->producer = ndx;	// increment Que producer
+		// set semaphore to wake up Kernel (worker) thread
+		up(dev->fcQueReady);
+	}
 //DoneWithPutQ:
-
-  LEAVE("cpqfcTSPutLinkQ");
+	LEAVE("cpqfcTSPutLinkQ");
 }
 
-
-
-
 // reset device ext FC link Q
-void cpqfcTSLinkQReset( CPQFCHBA *cpqfcHBAdata)
-   
+void cpqfcTSLinkQReset(CPQFCHBA * dev)
 {
-  PFC_LINK_QUE fcLQ = cpqfcHBAdata->fcLQ;
-  fcLQ->producer = 0;
-  fcLQ->consumer = 0;
-
+	PFC_LINK_QUE fcLQ = dev->fcLQ;
+	fcLQ->producer = 0;
+	fcLQ->consumer = 0;
 }
 
-
-
-
-
 // When Tachyon gets an unassisted FCP-SCSI frame, post here so
 // an arbitrary context thread (e.g. IOCTL loopback test function)
 // can process it.
@@ -961,17 +790,15 @@
 // (NOTE: Not revised for Linux)
 // This Q works like Tachyon's que - the producer points to the next
 // (unused) entry.
-void cpqfcTSPutScsiQue( CPQFCHBA *cpqfcHBAdata,
-  int Type, 
-  void *QueContent)
+void cpqfcTSPutScsiQue(CPQFCHBA * dev, int Type, void *QueContent)
 {
-//  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
-//  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
+//  CPQFCHBA *dev = (CPQFCHBA *)shpnt->hostdata;
+//  PTACHYON fcChip = &dev->fcChip;
 
-//  ULONG ndx;
+//  u32 ndx;
 
-//  ULONG *pExchangeID;
-//  LONG ExchangeID;
+//  u32 *pExchangeID;
+//  s32 ExchangeID;
 
 /*
   KeAcquireSpinLockAtDpcLevel( &pDevExt->fcScsiQueLock);
@@ -999,7 +826,7 @@
       // copied an FCP response frame into a buffer pointed to by the SEST
       // entry.  That buffer is allocated in the SEST structure at ->RspHDR.
       // Copy the RspHDR for use by the Que handler.
-      pExchangeID = (ULONG *)QueContent;
+      pExchangeID = (u32 *)QueContent;
       
       memcpy(
 	      pDevExt->fcScsiQue.Qitem[pDevExt->fcScsiQue.producer].ulBuff,
@@ -1020,175 +847,127 @@
 
     KeSetEvent( &pDevExt->TYIBscsi,  // signal any waiting thread
        0,                    // no priority boost
-		   FALSE );              // no waiting later for this event
+		   0 );              // no waiting later for this event
   }
   KeReleaseSpinLockFromDpcLevel( &pDevExt->fcScsiQueLock);
 */
 }
 
+static void ProcessELS_Request(CPQFCHBA *, TachFCHDR_GCMND *);
+static void ProcessELS_Reply(CPQFCHBA *, TachFCHDR_GCMND *);
+static void ProcessFCS_Reply(CPQFCHBA *, TachFCHDR_GCMND *);
 
-
-
-
-
-
-static void ProcessELS_Request( CPQFCHBA*,TachFCHDR_GCMND*);
-
-static void ProcessELS_Reply( CPQFCHBA*,TachFCHDR_GCMND*);
-
-static void ProcessFCS_Reply( CPQFCHBA*,TachFCHDR_GCMND*);
-
-void cpqfcTSImplicitLogout( CPQFCHBA* cpqfcHBAdata,
-		PFC_LOGGEDIN_PORT pFcPort)
+void cpqfcTSImplicitLogout(CPQFCHBA * dev, PFC_LOGGEDIN_PORT pFcPort)
 {
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
+	PTACHYON fcChip = &dev->fcChip;
 
-  if( pFcPort->port_id != 0xFFFC01 ) // don't care about Fabric
-  {
-    fcChip->fcStats.logouts++;
-    printk("cpqfcTS: Implicit logout of WWN %08X%08X, port_id %06X\n", 
-        (ULONG)pFcPort->u.liWWN,
-        (ULONG)(pFcPort->u.liWWN >>32),
-	pFcPort->port_id);
-
-  // Terminate I/O with this (Linux) Scsi target
-    cpqfcTSTerminateExchange( cpqfcHBAdata, 
-                            &pFcPort->ScsiNexus,
-	                    DEVICE_REMOVED);
-  }
-			
-  // Do an "implicit logout" - we can't really Logout the device
-  // (i.e. with LOGOut Request) because of port_id confusion
-  // (i.e. the Other port has no port_id).
-  // A new login for that WWN will have to re-write port_id (0 invalid)
-  pFcPort->port_id = 0;  // invalid!
-  pFcPort->pdisc = FALSE;
-  pFcPort->prli = FALSE;
-  pFcPort->plogi = FALSE;
-  pFcPort->flogi = FALSE;
-  pFcPort->LOGO_timer = 0;
-  pFcPort->device_blocked = TRUE; // block Scsi Requests
-  pFcPort->ScsiNexus.VolumeSetAddressing=0;	
+	if (pFcPort->port_id != 0xFFFC01)	// don't care about Fabric
+	{
+		fcChip->fcStats.logouts++;
+		printk("cpqfcTS: Implicit logout of WWN %08X%08X, port_id %06X\n", (u32) pFcPort->u.liWWN, (u32) (pFcPort->u.liWWN >> 32), pFcPort->port_id);
+
+		// Terminate I/O with this (Linux) Scsi target
+		cpqfcTSTerminateExchange(dev, &pFcPort->ScsiNexus, DEVICE_REMOVED);
+	}
+	// Do an "implicit logout" - we can't really Logout the device
+	// (i.e. with LOGOut Request) because of port_id confusion
+	// (i.e. the Other port has no port_id).
+	// A new login for that WWN will have to re-write port_id (0 invalid)
+	pFcPort->port_id = 0;	// invalid!
+	pFcPort->pdisc = 0;
+	pFcPort->prli = 0;
+	pFcPort->plogi = 0;
+	pFcPort->flogi = 0;
+	pFcPort->LOGO_timer = 0;
+	pFcPort->device_blocked = 1;	// block Scsi Requests
+	pFcPort->ScsiNexus.VolumeSetAddressing = 0;
 }
 
-  
+
 // On FC-AL, there is a chance that a previously known device can
 // be quietly removed (e.g. with non-managed hub), 
 // while a NEW device (with different WWN) took the same alpa or
 // even 24-bit port_id.  This chance is unlikely but we must always
 // check for it.
-static void TestDuplicatePortId( CPQFCHBA* cpqfcHBAdata,
-		PFC_LOGGEDIN_PORT pLoggedInPort)
+
+static void TestDuplicatePortId(CPQFCHBA * dev, PFC_LOGGEDIN_PORT pLoggedInPort)
 {
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  // set "other port" at beginning of fcPorts list
-  PFC_LOGGEDIN_PORT pOtherPortWithPortId = fcChip->fcPorts.pNextPort;
-  while( pOtherPortWithPortId ) 
-  {
-    if( (pOtherPortWithPortId->port_id == 
-         pLoggedInPort->port_id) 
-		    &&
-         (pOtherPortWithPortId != pLoggedInPort) )
-    {
-      // trouble!  (Implicitly) Log the other guy out
-      printk(" *port_id %Xh is duplicated!* ", 
-        pOtherPortWithPortId->port_id);
-      cpqfcTSImplicitLogout( cpqfcHBAdata, pOtherPortWithPortId); 
-   }
-    pOtherPortWithPortId = pOtherPortWithPortId->pNextPort;
-  }
+	PTACHYON fcChip = &dev->fcChip;
+	// set "other port" at beginning of fcPorts list
+	PFC_LOGGEDIN_PORT pOtherPortWithPortId = fcChip->fcPorts.pNextPort;
+	while (pOtherPortWithPortId) {
+		if ((pOtherPortWithPortId->port_id == pLoggedInPort->port_id)
+		    && (pOtherPortWithPortId != pLoggedInPort)) {
+			// trouble!  (Implicitly) Log the other guy out
+			printk(" *port_id %Xh is duplicated!* ", pOtherPortWithPortId->port_id);
+			cpqfcTSImplicitLogout(dev, pOtherPortWithPortId);
+		}
+		pOtherPortWithPortId = pOtherPortWithPortId->pNextPort;
+	}
 }
 
-
-
-
-
-
 // Dynamic Memory Allocation for newly discovered FC Ports.
 // For simplicity, maintain fcPorts structs for ALL
 // for discovered devices, including those we never do I/O with
 // (e.g. Fabric addresses)
 
-static PFC_LOGGEDIN_PORT CreateFcPort( 
-	  CPQFCHBA* cpqfcHBAdata, 
-	  PFC_LOGGEDIN_PORT pLastLoggedInPort, 
-	  TachFCHDR_GCMND* fchs,
-	  LOGIN_PAYLOAD* plogi)
-{
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  PFC_LOGGEDIN_PORT pNextLoggedInPort = NULL;
-  int i;
-
-
-  printk("cpqfcTS: New FC port %06Xh WWN: ", fchs->s_id);
-  for( i=3; i>=0; i--)   // copy the LOGIN port's WWN
-    printk("%02X", plogi->port_name[i]);
-  for( i=7; i>3; i--)   // copy the LOGIN port's WWN
-    printk("%02X", plogi->port_name[i]);
-
-
-  // allocate mem for new port
-  // (these are small and rare allocations...)
-  pNextLoggedInPort = kmalloc( sizeof( FC_LOGGEDIN_PORT), GFP_ATOMIC );
-
-    
-  // allocation succeeded?  Fill out NEW PORT
-  if( pNextLoggedInPort )
-  {    
-                              // clear out any garbage (sometimes exists)
-    memset( pNextLoggedInPort, 0, sizeof( FC_LOGGEDIN_PORT));
-
-
-    // If we login to a Fabric, we don't want to treat it
-    // as a SCSI device...
-    if( (fchs->s_id & 0xFFF000) != 0xFFF000)
-    {
-      int i;
-      
-      // create a unique "virtual" SCSI Nexus (for now, just a
-      // new target ID) -- we will update channel/target on REPORT_LUNS
-      // special case for very first SCSI target...
-      if( cpqfcHBAdata->HostAdapter->max_id == 0)
-      {
-        pNextLoggedInPort->ScsiNexus.target = 0;
-        fcChip->fcPorts.ScsiNexus.target = -1; // don't use "stub"
-      }
-      else
-      {
-        pNextLoggedInPort->ScsiNexus.target =
-          cpqfcHBAdata->HostAdapter->max_id;
-      }
-
-      // initialize the lun[] Nexus struct for lun masking      
-      for( i=0; i< CPQFCTS_MAX_LUN; i++)
-        pNextLoggedInPort->ScsiNexus.lun[i] = 0xFF; // init to NOT USED
-      
-      pNextLoggedInPort->ScsiNexus.channel = 0; // cpqfcTS has 1 FC port
-      
-      printk(" SCSI Chan/Trgt %d/%d", 
-          pNextLoggedInPort->ScsiNexus.channel,
-          pNextLoggedInPort->ScsiNexus.target);
- 
-      // tell Scsi layers about the new target...
-      cpqfcHBAdata->HostAdapter->max_id++; 
-//    printk("HostAdapter->max_id = %d\n",
-//      cpqfcHBAdata->HostAdapter->max_id);		    
-    }                          
-    else
-    {
-      // device is NOT SCSI (in case of Fabric)
-      pNextLoggedInPort->ScsiNexus.target = -1;  // invalid
-    }
+static PFC_LOGGEDIN_PORT CreateFcPort(CPQFCHBA * dev, PFC_LOGGEDIN_PORT pLastLoggedInPort, TachFCHDR_GCMND * fchs, LOGIN_PAYLOAD * plogi)
+{
+	PTACHYON fcChip = &dev->fcChip;
+	PFC_LOGGEDIN_PORT pNextLoggedInPort = NULL;
+	int i;
+
+	printk("cpqfcTS: New FC port %06Xh WWN: ", fchs->s_id);
+	for (i = 3; i >= 0; i--)	// copy the LOGIN port's WWN
+		printk("%02X", plogi->port_name[i]);
+	for (i = 7; i > 3; i--)	// copy the LOGIN port's WWN
+		printk("%02X", plogi->port_name[i]);
+
+	// allocate mem for new port
+	// (these are small and rare allocations...)
+	pNextLoggedInPort = kmalloc(sizeof(FC_LOGGEDIN_PORT), GFP_ATOMIC);
+
+	// allocation succeeded?  Fill out NEW PORT
+	if (pNextLoggedInPort) {
+		// clear out any garbage (sometimes exists)
+		memset(pNextLoggedInPort, 0, sizeof(FC_LOGGEDIN_PORT));
+		// If we login to a Fabric, we don't want to treat it
+		// as a SCSI device...
+		if ((fchs->s_id & 0xFFF000) != 0xFFF000) {
+			int i;
+
+			// create a unique "virtual" SCSI Nexus (for now, just a
+			// new target ID) -- we will update channel/target on REPORT_LUNS
+			// special case for very first SCSI target...
+			if (dev->HostAdapter->max_id == 0) {
+				pNextLoggedInPort->ScsiNexus.target = 0;
+				fcChip->fcPorts.ScsiNexus.target = -1;	// don't use "stub"
+			} else {
+				pNextLoggedInPort->ScsiNexus.target = dev->HostAdapter->max_id;
+			}
 
-	  // create forward link to new port
-    pLastLoggedInPort->pNextPort = pNextLoggedInPort;
-    printk("\n");
-
-  }     
-  return pNextLoggedInPort;  // NULL on allocation failure
-}   // end NEW PORT (WWN) logic
+			// initialize the lun[] Nexus struct for lun masking      
+			for (i = 0; i < CPQFCTS_MAX_LUN; i++)
+				pNextLoggedInPort->ScsiNexus.lun[i] = 0xFF;	// init to NOT USED
+
+			pNextLoggedInPort->ScsiNexus.channel = 0;	// cpqfcTS has 1 FC port
+			printk(" SCSI Chan/Trgt %d/%d", pNextLoggedInPort->ScsiNexus.channel, pNextLoggedInPort->ScsiNexus.target);
+			// tell Scsi layers about the new target...
+			dev->HostAdapter->max_id++;
+//			printk("HostAdapter->max_id = %d\n",
+//				dev->HostAdapter->max_id);                 
+		} else {
+			// device is NOT SCSI (in case of Fabric)
+			pNextLoggedInPort->ScsiNexus.target = -1;	// invalid
+		}
 
+		// create forward link to new port
+		pLastLoggedInPort->pNextPort = pNextLoggedInPort;
+		printk("\n");
 
+	}
+	return pNextLoggedInPort;	// NULL on allocation failure
+}				// end NEW PORT (WWN) logic
 
 // For certain cases, we want to terminate exchanges without
 // sending ABTS to the device.  Examples include when an FC
@@ -1200,870 +979,620 @@
 // Since we must ensure that Tachyon is not operating on the
 // exchange, we have to freeze the chip
 // sterminateex
-void cpqfcTSTerminateExchange( 
-  CPQFCHBA* cpqfcHBAdata, SCSI_NEXUS *ScsiNexus, int TerminateStatus)
+
+void cpqfcTSTerminateExchange(CPQFCHBA * dev, SCSI_NEXUS * ScsiNexus, int TerminateStatus)
 {
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  ULONG x_ID;
+	PTACHYON fcChip = &dev->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	u32 x_ID;
+
+	if (ScsiNexus) {
+//		printk("TerminateExchange: ScsiNexus chan/target %d/%d\n",
+//			ScsiNexus->channel, ScsiNexus->target);
+	}
+	for (x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++) {
+		if (Exchanges->fcExchange[x_ID].type)	// in use?
+		{
+			if (ScsiNexus == NULL)	// our HBA changed - term. all
+			{
+				Exchanges->fcExchange[x_ID].status = TerminateStatus;
+				cpqfcTSPutLinkQue(dev, BLS_ABTS, &x_ID);
+			} else {
+				// If a device, according to WWN, has been removed, it's
+				// port_id may be used by another working device, so we
+				// have to terminate by SCSI target, NOT port_id.
+				if (Exchanges->fcExchange[x_ID].Cmnd)	// Cmnd in progress?
+				{
+					if ((Exchanges->fcExchange[x_ID].Cmnd->target == ScsiNexus->target)
+					    && (Exchanges->fcExchange[x_ID].Cmnd->channel == ScsiNexus->channel)) {
+						Exchanges->fcExchange[x_ID].status = TerminateStatus;
+						cpqfcTSPutLinkQue(dev, BLS_ABTS, &x_ID);	// timed-out
+					}
+				}
+				// (in case we ever need it...)
+				// all SEST structures have a remote node ID at SEST DWORD 2
+				//          if( (fcChip->SEST->u[ x_ID ].TWE.Remote_Node_ID >> 8)
+				//                ==  port_id)
+			}
+		}
+	}
+}
 
-  if( ScsiNexus )
-  {
-//    printk("TerminateExchange: ScsiNexus chan/target %d/%d\n",
-//		    ScsiNexus->channel, ScsiNexus->target);
+static void ProcessELS_Request(CPQFCHBA * dev, TachFCHDR_GCMND * fchs)
+{
+	PTACHYON fcChip = &dev->fcChip;
+//	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+//	u32 ox_id = (fchs->ox_rx_id >>16);
+	PFC_LOGGEDIN_PORT pLoggedInPort = NULL, pLastLoggedInPort;
+	u8 NeedReject = 0;
+	u32 ls_reject_code = 0;	// default don'n know??
 
-  } 
-  
-  for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++)
-  {
-    if( Exchanges->fcExchange[x_ID].type )  // in use?
-    {
-      if( ScsiNexus == NULL ) // our HBA changed - term. all
-      {
-	Exchanges->fcExchange[x_ID].status = TerminateStatus;
-        cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID ); 
-      }
-      else
-      {
-	// If a device, according to WWN, has been removed, it's
-	// port_id may be used by another working device, so we
-	// have to terminate by SCSI target, NOT port_id.
-        if( Exchanges->fcExchange[x_ID].Cmnd) // Cmnd in progress?
-	{	                 
-	  if( (Exchanges->fcExchange[x_ID].Cmnd->target == ScsiNexus->target)
-			&&
-            (Exchanges->fcExchange[x_ID].Cmnd->channel == ScsiNexus->channel)) 
-          {
-            Exchanges->fcExchange[x_ID].status = TerminateStatus;
-            cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &x_ID ); // timed-out
-          }
-	}
-
-	// (in case we ever need it...)
-	// all SEST structures have a remote node ID at SEST DWORD 2
-        //          if( (fcChip->SEST->u[ x_ID ].TWE.Remote_Node_ID >> 8)
-        //                ==  port_id)
-      } 
-    }
-  }
-}
 
+	// Check the incoming frame for a supported ELS type
+	switch (fchs->pl[0] & 0xFFFF) 
+	{
+	case 0x0050:	
+		//  PDISC?
+		// Payload for PLOGI and PDISC is identical (request & reply)
+		if (!verify_PLOGI(fcChip, fchs, &ls_reject_code))	// valid payload?
+		{
+			LOGIN_PAYLOAD logi;	// FC-PH Port Login
+
+			// PDISC payload OK. If critical login fields
+			// (e.g. WWN) matches last login for this port_id,
+			// we may resume any prior exchanges
+			// with the other port
+
+			BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logi, sizeof(logi));
+
+			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
+							   0,	// don't search linked list for port_id
+							   &logi.port_name[0],	// search linked list for WWN
+							   &pLastLoggedInPort);	// must return non-NULL; when a port_id
+			// is not found, this pointer marks the
+			// end of the singly linked list
+
+			if (pLoggedInPort != NULL)	// WWN found (prior login OK)
+			{
+				if ((fchs->s_id & 0xFFFFFF) == pLoggedInPort->port_id) {
+					// Yes.  We were expecting PDISC?
+					if (pLoggedInPort->pdisc) {
+						// Yes; set fields accordingly.     (PDISC, not Originator)
+						SetLoginFields(pLoggedInPort, fchs, 1, 0);
+						// send 'ACC' reply 
+						cpqfcTSPutLinkQue(dev, ELS_PLOGI_ACC,	// (PDISC same as PLOGI ACC)
+								  fchs);
+						// OK to resume I/O...
+					} else {
+						printk("Not expecting PDISC (pdisc=0)\n");
+						NeedReject = 1;
+						// set reject reason code 
+						ls_reject_code = LS_RJT_REASON(PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
+					}
+				} else {
+					if (pLoggedInPort->port_id != 0) {
+						printk("PDISC PortID change: old %Xh, new %Xh\n", pLoggedInPort->port_id, fchs->s_id & 0xFFFFFF);
+					}
+					NeedReject = 1;
+					// set reject reason code 
+					ls_reject_code = LS_RJT_REASON(PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
+				}
+			} else {
+				printk("PDISC Request from unknown WWN\n");
+				NeedReject = 1;
+				// set reject reason code 
+				ls_reject_code = LS_RJT_REASON(LOGICAL_ERROR, INVALID_PORT_NAME);
+			}
 
-static void ProcessELS_Request( 
-              CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs)
-{
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-//  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-//  ULONG ox_id = (fchs->ox_rx_id >>16);
-  PFC_LOGGEDIN_PORT pLoggedInPort=NULL, pLastLoggedInPort;
-  BOOLEAN NeedReject = FALSE;
-  ULONG ls_reject_code = 0; // default don'n know??
+		}
+		else		// Payload unacceptable
+		{
+			printk("payload unacceptable\n");
+			NeedReject = 1;	// reject code already set
 
+		}
+		if (NeedReject) {
+			u32 port_id;
+			// The PDISC failed.  Set login struct flags accordingly,
+			// terminate any I/O to this port, and Q a PLOGI
+			if (pLoggedInPort) {
+				pLoggedInPort->pdisc = 0;
+				pLoggedInPort->prli = 0;
+				pLoggedInPort->plogi = 0;
+
+				cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
+				port_id = pLoggedInPort->port_id;
+			} else {
+				port_id = fchs->s_id & 0xFFFFFF;
+			}
+			fchs->reserved = ls_reject_code;	// borrow this (unused) field
+			cpqfcTSPutLinkQue(dev, ELS_RJT, fchs);
+		}
+		break;
 
-  // Check the incoming frame for a supported ELS type
-  switch( fchs->pl[0] & 0xFFFF)
-  {
-  case 0x0050: //  PDISC?
+	case 0x0003:
+		//  PLOGI?
+		// Payload for PLOGI and PDISC is identical (request & reply)
+		if (!verify_PLOGI(fcChip, fchs, &ls_reject_code))	// valid payload?
+		{
+			LOGIN_PAYLOAD logi;	// FC-PH Port Login
+			u8 NeedReject = 0;
+
+			// PDISC payload OK. If critical login fields
+			// (e.g. WWN) matches last login for this port_id,
+			// we may resume any prior exchanges
+			// with the other port
+
+			BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logi, sizeof(logi));
+			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
+							   0,	// don't search linked list for port_id
+							   &logi.port_name[0],	// search linked list for WWN
+							   &pLastLoggedInPort);	// must return non-NULL; when a port_id
+			// is not found, this pointer marks the
+			// end of the singly linked list
+			if (pLoggedInPort == NULL)	// WWN not found -New Port
+			{
+				pLoggedInPort = CreateFcPort(dev, pLastLoggedInPort, fchs, &logi);
+				if (pLoggedInPort == NULL) {
+					printk(" cpqfcTS: New port allocation failed - lost FC device!\n");
+					// Now Q a LOGOut Request, since we won't be talking to that device
+					NeedReject = 1;
+					// set reject reason code 
+					ls_reject_code = LS_RJT_REASON(LOGICAL_ERROR, NO_LOGIN_RESOURCES);
+				}
+			}
+			if (!NeedReject) {
+				// OK - we have valid fcPort ptr; set fields accordingly.   
+				//                         (not PDISC, not Originator)
+				SetLoginFields(pLoggedInPort, fchs, 0, 0);
+				// send 'ACC' reply 
+				cpqfcTSPutLinkQue(dev, ELS_PLOGI_ACC,	// (PDISC same as PLOGI ACC)
+						  fchs);
+			}
+		}
+		else		// Payload unacceptable
+		{
+			printk("payload unacceptable\n");
+			NeedReject = 1;	// reject code already set
+		}
+		if (NeedReject) {
+			// The PDISC failed.  Set login struct flags accordingly,
+			// terminate any I/O to this port, and Q a PLOGI
+			pLoggedInPort->pdisc = 0;
+			pLoggedInPort->prli = 0;
+			pLoggedInPort->plogi = 0;
 
-    // Payload for PLOGI and PDISC is identical (request & reply)
-    if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) ) // valid payload?
-    {
-      LOGIN_PAYLOAD logi;       // FC-PH Port Login
-      
-      // PDISC payload OK. If critical login fields
-      // (e.g. WWN) matches last login for this port_id,
-      // we may resume any prior exchanges
-      // with the other port
+			fchs->reserved = ls_reject_code;	// borrow this (unused) field
 
-      
-      BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));
-   
-      pLoggedInPort = fcFindLoggedInPort( 
-             fcChip, 
-	     NULL,     // don't search Scsi Nexus
-	     0,        // don't search linked list for port_id
-             &logi.port_name[0],     // search linked list for WWN
-             &pLastLoggedInPort);  // must return non-NULL; when a port_id
-                                   // is not found, this pointer marks the
-                                   // end of the singly linked list
-    
-      if( pLoggedInPort != NULL)   // WWN found (prior login OK)
-      { 
-           
- 	if( (fchs->s_id & 0xFFFFFF) == pLoggedInPort->port_id)
-	{
-          // Yes.  We were expecting PDISC?
-          if( pLoggedInPort->pdisc )
-	  {
-	    // Yes; set fields accordingly.     (PDISC, not Originator)
-            SetLoginFields( pLoggedInPort, fchs, TRUE, FALSE);
-       
-            // send 'ACC' reply 
-            cpqfcTSPutLinkQue( cpqfcHBAdata, 
-                          ELS_PLOGI_ACC, // (PDISC same as PLOGI ACC)
-                          fchs );
-
-	    // OK to resume I/O...
-	  }
-	  else
- 	  {
-	    printk("Not expecting PDISC (pdisc=FALSE)\n");
-	    NeedReject = TRUE;
-	    // set reject reason code 
-            ls_reject_code = 
-              LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
-	  }
-	}
-	else
-	{
-	  if( pLoggedInPort->port_id != 0)
-	  {
-  	    printk("PDISC PortID change: old %Xh, new %Xh\n",
-              pLoggedInPort->port_id, fchs->s_id &0xFFFFFF);
-	  }
-          NeedReject = TRUE;
-          // set reject reason code 
-          ls_reject_code = 
-	    LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
-		  
-	}
-      }
-      else
-      {
-	printk("PDISC Request from unknown WWN\n");
-        NeedReject = TRUE;
-          
-	// set reject reason code 
-        ls_reject_code = 
-          LS_RJT_REASON( LOGICAL_ERROR, INVALID_PORT_NAME);
-      }
+			// send 'RJT' reply 
+			cpqfcTSPutLinkQue(dev, ELS_RJT, fchs);
+		}
+		// terminate any exchanges with this device...
+		if (pLoggedInPort) {
+			cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
+		}
+		break;
 
-    }
-    else // Payload unacceptable
-    {
-      printk("payload unacceptable\n");
-      NeedReject = TRUE;  // reject code already set
-      
-    }
+	case 0x1020:		// PRLI?
+		{
+			u8 NeedReject = 1;
+			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
+							   (fchs->s_id & 0xFFFFFF),	// search linked list for port_id
+							   NULL,	// DON'T search linked list for WWN
+							   NULL);	// don't care
+
+			if (pLoggedInPort == NULL) {
+				// huh?
+				printk(" Unexpected PRLI Request -not logged in!\n");
+				// set reject reason code 
+				ls_reject_code = LS_RJT_REASON(PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
+				// Q a LOGOut here?
+			} else {
+				// verify the PRLI ACC payload
+				if (!verify_PRLI(fchs, &ls_reject_code)) {
+					// PRLI Reply is acceptable; were we expecting it?
+					if (pLoggedInPort->plogi) {
+						// yes, we expected the PRLI ACC  (not PDISC; not Originator)
+						SetLoginFields(pLoggedInPort, fchs, 0, 0);
+						// Q an ACCept Reply
+						cpqfcTSPutLinkQue(dev, ELS_PRLI_ACC, fchs);
+						NeedReject = 0;
+					} else {
+						// huh?
+						printk(" (unexpected) PRLI REQEST with plogi 0\n");
+						// set reject reason code 
+						ls_reject_code = LS_RJT_REASON(PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
+						// Q a LOGOut here?
+					}
+				} else {
+					printk(" PRLI REQUEST payload failed verify\n");
+					// (reject code set by "verify")
+					// Q a LOGOut here?
+				}
+			}
 
-    if( NeedReject)
-    {
-      ULONG port_id;
-      // The PDISC failed.  Set login struct flags accordingly,
-      // terminate any I/O to this port, and Q a PLOGI
-      if( pLoggedInPort )
-      {
-        pLoggedInPort->pdisc = FALSE;
-        pLoggedInPort->prli = FALSE;
-        pLoggedInPort->plogi = FALSE;
-	
-        cpqfcTSTerminateExchange( cpqfcHBAdata, 
-          &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
-	port_id = pLoggedInPort->port_id;
-      }
-      else
-      {
-	port_id = fchs->s_id &0xFFFFFF;
-      }
-      fchs->reserved = ls_reject_code; // borrow this (unused) field
-      cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_RJT, fchs );
-    }
-   
-    break;
+			if (NeedReject) {
+				// Q a ReJecT Reply with reason code
+				fchs->reserved = ls_reject_code;
+				cpqfcTSPutLinkQue(dev, ELS_RJT,	// Q Type
+						  fchs);
+			}
+		}
+		break;
 
+	case 0x0005:		// LOGOut?
+		{
+			// was this LOGOUT because we sent a ELS_PDISC to an FC device
+			// with changed (or new) port_id, or does the port refuse 
+			// to communicate to us?
+			// We maintain a logout counter - if we get 3 consecutive LOGOuts,
+			// give up!
+			LOGOUT_PAYLOAD logo;
+			u8 GiveUpOnDevice = 0;
+			u32 ls_reject_code = 0;
+
+			BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logo, sizeof(logo));
+			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
+							   0,	// don't search linked list for port_id
+							   &logo.port_name[0],	// search linked list for WWN
+							   NULL);	// don't care about end of list
+
+			if (pLoggedInPort)	// found the device?
+			{
+				// Q an ACC reply 
+				cpqfcTSPutLinkQue(dev, ELS_LOGO_ACC,	// Q Type
+						  fchs);	// device to respond to
+				// set login struct fields (LOGO_counter increment)
+				SetLoginFields(pLoggedInPort, fchs, 0, 0);
+				// are we an Initiator?
+				if (fcChip->Options.initiator) {
+					// we're an Initiator, so check if we should 
+					// try (another?) login
+					// Fabrics routinely log out from us after
+					// getting device info - don't try to log them
+					// back in.
+					if ((fchs->s_id & 0xFFF000) == 0xFFF000) {
+						;	// do nothing
+					} else if (pLoggedInPort->LOGO_counter <= 3) {
+						// try (another) login (PLOGI request)
+						cpqfcTSPutLinkQue(dev, ELS_PLOGI,	// Q Type
+								  fchs);
+						// Terminate I/O with "retry" potential
+						cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
+					} else {
+						printk(" Got 3 LOGOuts - terminating comm. with port_id %Xh\n", fchs->s_id && 0xFFFFFF);
+						GiveUpOnDevice = 1;
+					}
+				} else {
+					GiveUpOnDevice = 1;
+				}
+
+				if (GiveUpOnDevice == 1) {
+					cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, DEVICE_REMOVED);
+				}
+			} else	// we don't know this WWN!
+			{
+				// Q a ReJecT Reply with reason code
+				fchs->reserved = ls_reject_code;
+				cpqfcTSPutLinkQue(dev, ELS_RJT,	// Q Type
+						  fchs);
+			}
+		}
+		break;
 
+			// FABRIC only case
+	case 0x0461:	// ELS RSCN (Registered State Change Notification)?
+		{
+			int Ports;
+			int i;
+			__u32 Buff;
+			// Typically, one or more devices have been added to or dropped
+			// from the Fabric.
+			// The format of this frame is defined in FC-FLA (Rev 2.7, Aug 1997)
+			// The first 32-bit word has a 2-byte Payload Length, which
+			// includes the 4 bytes of the first word.  Consequently,
+			// this PL len must never be less than 4, must be a multiple of 4,
+			// and has a specified max value 256.
+			// (Endianess!)
+			Ports = ((fchs->pl[0] >> 24) - 4) / 4;
+			Ports = Ports > 63 ? 63 : Ports;
+
+			printk(" RSCN ports: %d\n", Ports);
+			if (Ports <= 0)	// huh?
+			{
+				// ReJecT the command
+				fchs->reserved = LS_RJT_REASON(UNABLE_TO_PERFORM, 0);
+
+				cpqfcTSPutLinkQue(dev, ELS_RJT,	// Q Type
+						  fchs);
+
+				break;
+			} else	// Accept the command
+			{
+				cpqfcTSPutLinkQue(dev, ELS_ACC,	// Q Type
+						  fchs);
+			}
 
-  case 0x0003: //  PLOGI?
+			// Check the "address format" to determine action.
+			// We have 3 cases:
+			// 0 = Port Address; 24-bit address of affected device
+			// 1 = Area Address; MS 16 bits valid
+			// 2 = Domain Address; MS 8 bits valid
+			for (i = 0; i < Ports; i++) {
+				BigEndianSwap((u8 *) & fchs->pl[i + 1], (u8 *) & Buff, 4);
+				switch (Buff & 0xFF000000) {
+				case 0:	// Port Address?
+				case 0x01000000:	// Area Domain?
+				case 0x02000000:	// Domain Address
+					// For example, "port_id" 0x201300 
+					// OK, let's try a Name Service Request (Query)
+					fchs->s_id = 0xFFFFFC;	// Name Server Address
+					cpqfcTSPutLinkQue(dev, FCS_NSR, fchs);
+					break;
+				default:	// huh? new value on version change?
+					break;
+				}
+			}
+		}
+		break;
+	default:
+		// don't support this request (yet)
+		// set reject reason code 
+		fchs->reserved = LS_RJT_REASON(UNABLE_TO_PERFORM, REQUEST_NOT_SUPPORTED);
+		cpqfcTSPutLinkQue(dev, ELS_RJT,	fchs);	// Q Type
+		break;
+	}
+}
 
-    // Payload for PLOGI and PDISC is identical (request & reply)
-    if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) ) // valid payload?
-    {
-      LOGIN_PAYLOAD logi;       // FC-PH Port Login
-      BOOLEAN NeedReject = FALSE;
-      
-      // PDISC payload OK. If critical login fields
-      // (e.g. WWN) matches last login for this port_id,
-      // we may resume any prior exchanges
-      // with the other port
 
-      
-      BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));
-   
-      pLoggedInPort = fcFindLoggedInPort( 
-             fcChip, 
-	     NULL,       // don't search Scsi Nexus
-	     0,        // don't search linked list for port_id
-             &logi.port_name[0],     // search linked list for WWN
-             &pLastLoggedInPort);  // must return non-NULL; when a port_id
-                                   // is not found, this pointer marks the
-                                   // end of the singly linked list
-    
-      if( pLoggedInPort == NULL)   // WWN not found -New Port
-      { 
-      	pLoggedInPort = CreateFcPort( 
-			  cpqfcHBAdata, 
-			  pLastLoggedInPort, 
-			  fchs,
-			  &logi);
-        if( pLoggedInPort == NULL )
-        {
-          printk(" cpqfcTS: New port allocation failed - lost FC device!\n");
-          // Now Q a LOGOut Request, since we won't be talking to that device
-	
-          NeedReject = TRUE;  
-	  
-          // set reject reason code 
-          ls_reject_code = 
-            LS_RJT_REASON( LOGICAL_ERROR, NO_LOGIN_RESOURCES);
-	    
+static void ProcessELS_Reply(CPQFCHBA * dev, TachFCHDR_GCMND * fchs)
+{
+	PTACHYON fcChip = &dev->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	u32 ox_id = (fchs->ox_rx_id >> 16);
+	u32 ls_reject_code;
+	PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort;
+
+	// If this is a valid reply, then we MUST have sent a request.
+	// Verify that we can find a valid request OX_ID corresponding to
+	// this reply
+
+	if (Exchanges->fcExchange[(fchs->ox_rx_id >> 16)].type == 0) {
+		printk(" *Discarding ACC/RJT frame, xID %04X/%04X* ", ox_id, fchs->ox_rx_id & 0xffff);
+		goto Quit;	// exit this routine
 	}
-      }
-      if( !NeedReject )
-      {
-      
-        // OK - we have valid fcPort ptr; set fields accordingly.   
-	//                         (not PDISC, not Originator)
-        SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE); 
-
-        // send 'ACC' reply 
-        cpqfcTSPutLinkQue( cpqfcHBAdata, 
-                      ELS_PLOGI_ACC, // (PDISC same as PLOGI ACC)
-                      fchs );
-      }
-    }
-    else // Payload unacceptable
-    {
-      printk("payload unacceptable\n");
-      NeedReject = TRUE;  // reject code already set
-    }
 
-    if( NeedReject)
-    {
-      // The PDISC failed.  Set login struct flags accordingly,
-      // terminate any I/O to this port, and Q a PLOGI
-      pLoggedInPort->pdisc = FALSE;
-      pLoggedInPort->prli = FALSE;
-      pLoggedInPort->plogi = FALSE;
-	
-      fchs->reserved = ls_reject_code; // borrow this (unused) field
+	// Is the reply a RJT (reject)?
+	if ((fchs->pl[0] & 0xFFFFL) == 0x01)	// Reject reply?
+	{
+		//  ******  REJECT REPLY  ********
+		switch (Exchanges->fcExchange[ox_id].type) {
+		case ELS_FDISC:	// we sent out Fabric Discovery
+		case ELS_FLOGI:	// we sent out FLOGI
+			printk("RJT received on Fabric Login from %Xh, reason %Xh\n", fchs->s_id, fchs->pl[1]);
+			break;
+		default:
+			break;
+		}
+		goto Done;
+	}
+	// OK, we have an ACCept...
+	// What's the ACC type? (according to what we sent)
+	switch (Exchanges->fcExchange[ox_id].type) {
+	case ELS_PLOGI:	// we sent out PLOGI
+		if (!verify_PLOGI(fcChip, fchs, &ls_reject_code)) {
+			LOGIN_PAYLOAD logi;	// FC-PH Port Login
+			// login ACC payload acceptable; search for WWN in our list
+			// of fcPorts
+			BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logi, sizeof(logi));
+			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
+						   0,	// don't search linked list for port_id
+						   &logi.port_name[0],	// search linked list for WWN
+						   &pLastLoggedInPort);	// must return non-NULL; when a port_id
+			// is not found, this pointer marks the
+			// end of the singly linked list
+			if (pLoggedInPort == NULL)	// WWN not found - new port
+			{
+				pLoggedInPort = CreateFcPort(dev, pLastLoggedInPort, fchs, &logi);
+				if (pLoggedInPort == NULL) {
+					printk(" cpqfcTS: New port allocation failed - lost FC device!\n");
+					// Now Q a LOGOut Request, since we won't be talking to that device
+					goto Done;	// exit with error! dropped login frame
+				}
+			} else	// WWN was already known.  Ensure that any open
+				// exchanges for this WWN are terminated.
+				// NOTE: It's possible that a device can change its 
+				// 24-bit port_id after a Link init or Fabric change 
+				// (e.g. LIP or Fabric RSCN).  In that case, the old
+				// 24-bit port_id may be duplicated, or no longer exist.
+			{
+				cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
+			}
 
-      // send 'RJT' reply 
-      cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_RJT, fchs );
-    }
-   
-    // terminate any exchanges with this device...
-    if( pLoggedInPort )
-    {
-      cpqfcTSTerminateExchange( cpqfcHBAdata, 
-        &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
-    }
-    break;
+			// We have an fcPort struct - set fields accordingly
+			// not PDISC, originator 
+			SetLoginFields(pLoggedInPort, fchs, 0, 1);
+			// We just set a "port_id"; is it duplicated?
+			TestDuplicatePortId(dev, pLoggedInPort);
+			// For Fabric operation, we issued PLOGI to 0xFFFFFC
+			// so we can send SCR (State Change Registration) 
+			// Check for this special case...
+			if (fchs->s_id == 0xFFFFFC) {
+				// PLOGI ACC was a Fabric response... issue SCR
+				fchs->s_id = 0xFFFFFD;	// address for SCR
+				cpqfcTSPutLinkQue(dev, ELS_SCR, fchs);
+			}
+			else {
+				// Now we need a PRLI to enable FCP-SCSI operation
+				// set flags and Q up a ELS_PRLI
+				cpqfcTSPutLinkQue(dev, ELS_PRLI, fchs);
+			}
+		} else {
+			// login payload unacceptable - reason in ls_reject_code
+			// Q up a Logout Request
+			printk("Login Payload unacceptable\n");
+		}
+		break;
 
+		// PDISC logic very similar to PLOGI, except we never want
+		// to allocate mem for "new" port, and we set flags differently
+		// (might combine later with PLOGI logic for efficiency)  
+	case ELS_PDISC:	// we sent out PDISC
+		if (!verify_PLOGI(fcChip, fchs, &ls_reject_code)) {
+			LOGIN_PAYLOAD logi;	// FC-PH Port Login
+			u8 NeedLogin = 0;
+
+			// login payload acceptable; search for WWN in our list
+			// of (previously seen) fcPorts
+			BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logi, sizeof(logi));
+
+			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
+							   0,	// don't search linked list for port_id
+							   &logi.port_name[0],	// search linked list for WWN
+							   &pLastLoggedInPort);	// must return non-NULL; when a port_id
+			// is not found, this pointer marks the
+			// end of the singly linked list
+			if (pLoggedInPort != NULL)	// WWN found?
+			{
+				// WWN has same port_id as last login?  (Of course, a properly
+				// working FC device should NEVER ACCept a PDISC if it's
+				// port_id changed, but check just in case...)
+				if ((fchs->s_id & 0xFFFFFF) == pLoggedInPort->port_id) {
+					// Yes.  We were expecting PDISC?
+					if (pLoggedInPort->pdisc) {
+						int i;
+
+
+						// PDISC expected -- set fields.  (PDISC, Originator)
+						SetLoginFields(pLoggedInPort, fchs, 1, 1);
+
+						// We are ready to resume FCP-SCSI to this device...
+						// Do we need to start anything that was Queued?
+
+						for (i = 0; i < TACH_SEST_LEN; i++) {
+							// see if any exchange for this PDISC'd port was queued
+							if (((fchs->s_id & 0xFFFFFF) == (Exchanges->fcExchange[i].fchs.d_id & 0xFFFFFF))
+							    && (Exchanges->fcExchange[i].status & EXCHANGE_QUEUED)) {
+								fchs->reserved = i;	// copy ExchangeID
+//						                printk(" *Q x_ID %Xh after PDISC* ",i);
+
+								cpqfcTSPutLinkQue(dev, EXCHANGE_QUEUED, fchs);
+							}
+						}
+						// Complete commands Q'd while we were waiting for Login
+						UnblockScsiDevice(dev->HostAdapter, pLoggedInPort);
+					} else {
+						printk("Not expecting PDISC (pdisc=0)\n");
+						NeedLogin = 1;
+					}
+				} else {
+					printk("PDISC PortID change: old %Xh, new %Xh\n", pLoggedInPort->port_id, fchs->s_id & 0xFFFFFF);
+					NeedLogin = 1;
+				}
+			} else {
+				printk("PDISC ACC from unknown WWN\n");
+				NeedLogin = 1;
+			}
 
+			if (NeedLogin) {
+				// The PDISC failed.  Set login struct flags accordingly,
+				// terminate any I/O to this port, and Q a PLOGI
+				if (pLoggedInPort)	// FC device previously known?
+				{
+					cpqfcTSPutLinkQue(dev, ELS_LOGO, fchs);	// Qtype has port_id to send to 
+					// There are a variety of error scenarios which can result
+					// in PDISC failure, so as a catchall, add the check for
+					// duplicate port_id.
+					TestDuplicatePortId(dev, pLoggedInPort);
+
+					// TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
+					pLoggedInPort->pdisc = 0;
+					pLoggedInPort->prli = 0;
+					pLoggedInPort->plogi = 0;
+
+					cpqfcTSTerminateExchange(dev, &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
+				}
+				cpqfcTSPutLinkQue(dev, ELS_PLOGI, fchs);
+			}
+		} else {
+			// login payload unacceptable - reason in ls_reject_code
+			// Q up a Logout Request
+			printk("ERROR: Login Payload unacceptable!\n");
 
-  case 0x1020:  // PRLI?
-  {
-    BOOLEAN NeedReject = TRUE;
-    pLoggedInPort = fcFindLoggedInPort( 
-           fcChip, 
-           NULL,       // don't search Scsi Nexus
-	   (fchs->s_id & 0xFFFFFF),  // search linked list for port_id
-           NULL,     // DON'T search linked list for WWN
-           NULL);    // don't care
-      
-    if( pLoggedInPort == NULL ) 
-    {
-      // huh?
-      printk(" Unexpected PRLI Request -not logged in!\n");
-
-      // set reject reason code 
-      ls_reject_code = LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
-      
-      // Q a LOGOut here?
-    }
-    else
-    {
-      // verify the PRLI ACC payload
-      if( !verify_PRLI( fchs, &ls_reject_code) )
-      {
-        // PRLI Reply is acceptable; were we expecting it?
-        if( pLoggedInPort->plogi ) 
-        { 
-  	  // yes, we expected the PRLI ACC  (not PDISC; not Originator)
-          SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE);
-
-          // Q an ACCept Reply
-	  cpqfcTSPutLinkQue( cpqfcHBAdata,
-                        ELS_PRLI_ACC, 
-                        fchs );   
-	  
-	  NeedReject = FALSE;
-	}
-        else
-        {
-          // huh?
-          printk(" (unexpected) PRLI REQEST with plogi FALSE\n");
-
-          // set reject reason code 
-          ls_reject_code = LS_RJT_REASON( PROTOCOL_ERROR, INITIATOR_CTL_ERROR);
-    
-    	  // Q a LOGOut here?
-	  
-        }
-      }
-      else
-      {
-        printk(" PRLI REQUEST payload failed verify\n");
-        // (reject code set by "verify")
-
-        // Q a LOGOut here?
-      }
-    }
-
-    if( NeedReject )
-    {
-      // Q a ReJecT Reply with reason code
-      fchs->reserved = ls_reject_code;
-      cpqfcTSPutLinkQue( cpqfcHBAdata,
-                    ELS_RJT, // Q Type
-                    fchs );  
-    }
-  }
-    break;
- 
-
-    
-
-  case  0x0005:  // LOGOut?
-  {
-  // was this LOGOUT because we sent a ELS_PDISC to an FC device
-  // with changed (or new) port_id, or does the port refuse 
-  // to communicate to us?
-  // We maintain a logout counter - if we get 3 consecutive LOGOuts,
-  // give up!
-    LOGOUT_PAYLOAD logo;
-    BOOLEAN GiveUpOnDevice = FALSE;
-    ULONG ls_reject_code = 0;
-    
-    BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logo, sizeof(logo));
-
-    pLoggedInPort = fcFindLoggedInPort( 
-           fcChip, 
-           NULL,     // don't search Scsi Nexus
-	   0,        // don't search linked list for port_id
-           &logo.port_name[0],     // search linked list for WWN
-           NULL);    // don't care about end of list
-    
-    if( pLoggedInPort ) // found the device?
-    {
-      // Q an ACC reply 
-      cpqfcTSPutLinkQue( cpqfcHBAdata,
-                    ELS_LOGO_ACC, // Q Type
-                    fchs );       // device to respond to
-
-      // set login struct fields (LOGO_counter increment)
-      SetLoginFields( pLoggedInPort, fchs, FALSE, FALSE);
-      
-      // are we an Initiator?
-      if( fcChip->Options.initiator)  
-      {
-        // we're an Initiator, so check if we should 
-	// try (another?) login
-
-	// Fabrics routinely log out from us after
-	// getting device info - don't try to log them
-	// back in.
-	if( (fchs->s_id & 0xFFF000) == 0xFFF000 )
-	{
-	  ; // do nothing
-	}
-	else if( pLoggedInPort->LOGO_counter <= 3)
-	{
-	  // try (another) login (PLOGI request)
-	  
-          cpqfcTSPutLinkQue( cpqfcHBAdata,
-                    ELS_PLOGI, // Q Type
-                    fchs );  
-	
-	  // Terminate I/O with "retry" potential
-	  cpqfcTSTerminateExchange( cpqfcHBAdata, 
-			            &pLoggedInPort->ScsiNexus,
-				    PORTID_CHANGED);
-	}
-	else
-	{
-	  printk(" Got 3 LOGOuts - terminating comm. with port_id %Xh\n",
-			  fchs->s_id &&0xFFFFFF);
-	  GiveUpOnDevice = TRUE;
-	}
-      }
-      else
-      {
-	GiveUpOnDevice = TRUE;
-      }
-
-
-      if( GiveUpOnDevice == TRUE )
-      {
-        cpqfcTSTerminateExchange( cpqfcHBAdata, 
-	                          &pLoggedInPort->ScsiNexus,
-		                  DEVICE_REMOVED);
-      }
-    }  
-    else  // we don't know this WWN!
-    {
-      // Q a ReJecT Reply with reason code
-      fchs->reserved = ls_reject_code;
-      cpqfcTSPutLinkQue( cpqfcHBAdata,
-                    ELS_RJT, // Q Type
-                    fchs );  
-    }
-  }
-    break;
-
-
-
-
-  // FABRIC only case
-  case 0x0461:  // ELS RSCN (Registered State Change Notification)?
-  {
-    int Ports;
-    int i;
-    __u32 Buff;
-    // Typically, one or more devices have been added to or dropped
-    // from the Fabric.
-    // The format of this frame is defined in FC-FLA (Rev 2.7, Aug 1997)
-    // The first 32-bit word has a 2-byte Payload Length, which
-    // includes the 4 bytes of the first word.  Consequently,
-    // this PL len must never be less than 4, must be a multiple of 4,
-    // and has a specified max value 256.
-    // (Endianess!)
-    Ports = ((fchs->pl[0] >>24) - 4) / 4;
-    Ports = Ports > 63 ? 63 : Ports;
-    
-    printk(" RSCN ports: %d\n", Ports);
-    if( Ports <= 0 )  // huh?
-    {
-      // ReJecT the command
-      fchs->reserved = LS_RJT_REASON( UNABLE_TO_PERFORM, 0);
-    
-      cpqfcTSPutLinkQue( cpqfcHBAdata,
-                    ELS_RJT, // Q Type
-                    fchs ); 
-      
-      break;
-    }
-    else  // Accept the command
-    {
-       cpqfcTSPutLinkQue( cpqfcHBAdata,
-                    ELS_ACC, // Q Type
-                    fchs ); 
-    }
-    
-      // Check the "address format" to determine action.
-      // We have 3 cases:
-      // 0 = Port Address; 24-bit address of affected device
-      // 1 = Area Address; MS 16 bits valid
-      // 2 = Domain Address; MS 8 bits valid
-    for( i=0; i<Ports; i++)
-    { 
-      BigEndianSwap( (UCHAR*)&fchs->pl[i+1],(UCHAR*)&Buff, 4);
-      switch( Buff & 0xFF000000)
-      {
-
-      case 0:  // Port Address?
-	
-      case 0x01000000: // Area Domain?
-      case 0x02000000: // Domain Address
-        // For example, "port_id" 0x201300 
-	// OK, let's try a Name Service Request (Query)
-      fchs->s_id = 0xFFFFFC;  // Name Server Address
-      cpqfcTSPutLinkQue( cpqfcHBAdata, FCS_NSR, fchs);
-
-      break;
-	
-	
-      default:  // huh? new value on version change?
-      break;
-      }
-    }
-  }    
-  break;    
-
-
-
-    
-  default:  // don't support this request (yet)
-    // set reject reason code 
-    fchs->reserved = LS_RJT_REASON( UNABLE_TO_PERFORM, 
-		                    REQUEST_NOT_SUPPORTED);
-    
-    cpqfcTSPutLinkQue( cpqfcHBAdata,
-                    ELS_RJT, // Q Type
-                    fchs );     
-    break;  
-  }
-}
-
-
-static void ProcessELS_Reply( 
-		CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs)
-{
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  ULONG ox_id = (fchs->ox_rx_id >>16);
-  ULONG ls_reject_code;
-  PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort;
-  
-  // If this is a valid reply, then we MUST have sent a request.
-  // Verify that we can find a valid request OX_ID corresponding to
-  // this reply
-
-  
-  if( Exchanges->fcExchange[(fchs->ox_rx_id >>16)].type == 0)
-  {
-    printk(" *Discarding ACC/RJT frame, xID %04X/%04X* ", 
-		    ox_id, fchs->ox_rx_id & 0xffff);
-    goto Quit;  // exit this routine
-  }
-
-
-  // Is the reply a RJT (reject)?
-  if( (fchs->pl[0] & 0xFFFFL) == 0x01) // Reject reply?
-  {
-//  ******  REJECT REPLY  ********
-    switch( Exchanges->fcExchange[ox_id].type )
-    {
-	  
-    case ELS_FDISC:  // we sent out Fabric Discovery
-    case ELS_FLOGI:  // we sent out FLOGI
-
-      printk("RJT received on Fabric Login from %Xh, reason %Xh\n", 
-        fchs->s_id, fchs->pl[1]);    
-
-    break;
-
-    default:
-    break;
-    }
-      
-    goto Done;
-  }
-
-  // OK, we have an ACCept...
-  // What's the ACC type? (according to what we sent)
-  switch( Exchanges->fcExchange[ox_id].type )
-  {
-	  
-  case ELS_PLOGI:  // we sent out PLOGI
-    if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) )
-    {
-      LOGIN_PAYLOAD logi;       // FC-PH Port Login
-      
-      // login ACC payload acceptable; search for WWN in our list
-      // of fcPorts
-      
-      BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));
-   
-      pLoggedInPort = fcFindLoggedInPort( 
-             fcChip, 
-	     NULL,     // don't search Scsi Nexus
-	     0,        // don't search linked list for port_id
-             &logi.port_name[0],     // search linked list for WWN
-             &pLastLoggedInPort);  // must return non-NULL; when a port_id
-                                   // is not found, this pointer marks the
-                                   // end of the singly linked list
-    
-      if( pLoggedInPort == NULL)         // WWN not found - new port
-      {
+		}
+		break;
 
-	pLoggedInPort = CreateFcPort( 
-			  cpqfcHBAdata, 
-			  pLastLoggedInPort, 
-			  fchs,
-			  &logi);
-
-        if( pLoggedInPort == NULL )
-        {
-          printk(" cpqfcTS: New port allocation failed - lost FC device!\n");
-          // Now Q a LOGOut Request, since we won't be talking to that device
-	
-          goto Done;  // exit with error! dropped login frame
-	}
-      }
-      else      // WWN was already known.  Ensure that any open
-	        // exchanges for this WWN are terminated.
-      	// NOTE: It's possible that a device can change its 
-	// 24-bit port_id after a Link init or Fabric change 
-	// (e.g. LIP or Fabric RSCN).  In that case, the old
-	// 24-bit port_id may be duplicated, or no longer exist.
-      {
-
-        cpqfcTSTerminateExchange( cpqfcHBAdata, 
-          &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
-      }
-
-      // We have an fcPort struct - set fields accordingly
-                                    // not PDISC, originator 
-      SetLoginFields( pLoggedInPort, fchs, FALSE, TRUE);
-			
-      // We just set a "port_id"; is it duplicated?
-      TestDuplicatePortId( cpqfcHBAdata, pLoggedInPort);
-
-      // For Fabric operation, we issued PLOGI to 0xFFFFFC
-      // so we can send SCR (State Change Registration) 
-      // Check for this special case...
-      if( fchs->s_id == 0xFFFFFC ) 
-      {
-        // PLOGI ACC was a Fabric response... issue SCR
-	fchs->s_id = 0xFFFFFD;  // address for SCR
-        cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_SCR, fchs);
-      }
-
-      else
-      {
-      // Now we need a PRLI to enable FCP-SCSI operation
-      // set flags and Q up a ELS_PRLI
-        cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_PRLI, fchs);
-      }
-    }
-    else
-    {
-      // login payload unacceptable - reason in ls_reject_code
-      // Q up a Logout Request
-      printk("Login Payload unacceptable\n");
+	case ELS_PRLI:		// we sent out PRLI
+		pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search Scsi Nexus
+						   (fchs->s_id & 0xFFFFFF),	// search linked list for port_id
+						   NULL,	// DON'T search linked list for WWN
+						   NULL);	// don't care
+
+		if (pLoggedInPort == NULL) {
+			// huh?
+			printk(" Unexpected PRLI ACCept frame!\n");
+			// Q a LOGOut here?
+			goto Done;
+		}
+		// verify the PRLI ACC payload
+		if (!verify_PRLI(fchs, &ls_reject_code)) {
+			// PRLI Reply is acceptable; were we expecting it?
+			if (pLoggedInPort->plogi) {
+				// yes, we expected the PRLI ACC  (not PDISC; Originator)
+				SetLoginFields(pLoggedInPort, fchs, 0, 1);
+				// OK, let's send a REPORT_LUNS command to determine
+				// whether VSA or PDA FCP-LUN addressing is used.
+				cpqfcTSPutLinkQue(dev, SCSI_REPORT_LUNS, fchs);
+				// It's possible that a device we were talking to changed 
+				// port_id, and has logged back in.  This function ensures
+				// that I/O will resume.
+				UnblockScsiDevice(dev->HostAdapter, pLoggedInPort);
+			} else {
+				// huh?
+				printk(" (unexpected) PRLI ACCept with plogi 0\n");
+				// Q a LOGOut here?
+				goto Done;
+			}
+		} else {
+			printk(" PRLI ACCept payload failed verify\n");
+			// Q a LOGOut here?
+		}
+		break;
 
-    }
-    break;
+	case ELS_FLOGI:	// we sent out FLOGI (Fabric Login)
+		// update the upper 16 bits of our port_id in Tachyon
+		// the switch adds those upper 16 bits when responding
+		// to us (i.e. we are the destination_id)
+		fcChip->Registers.my_al_pa = (fchs->d_id & 0xFFFFFF);
+		writel(fcChip->Registers.my_al_pa, fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID);
+
+		// now send out a PLOGI to the well known port_id 0xFFFFFC
+		fchs->s_id = 0xFFFFFC;
+		cpqfcTSPutLinkQue(dev, ELS_PLOGI, fchs);
+		break;
 
 
-  // PDISC logic very similar to PLOGI, except we never want
-  // to allocate mem for "new" port, and we set flags differently
-  // (might combine later with PLOGI logic for efficiency)  
-  case ELS_PDISC:  // we sent out PDISC
-    if( !verify_PLOGI( fcChip, fchs, &ls_reject_code) )
-    {
-      LOGIN_PAYLOAD logi;       // FC-PH Port Login
-      BOOLEAN NeedLogin = FALSE;
-      
-      // login payload acceptable; search for WWN in our list
-      // of (previously seen) fcPorts
-      
-      BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));
-   
-      pLoggedInPort = fcFindLoggedInPort( 
-             fcChip, 
-	     NULL,     // don't search Scsi Nexus
-	     0,        // don't search linked list for port_id
-             &logi.port_name[0],     // search linked list for WWN
-             &pLastLoggedInPort);  // must return non-NULL; when a port_id
-                                   // is not found, this pointer marks the
-                                   // end of the singly linked list
-    
-      if( pLoggedInPort != NULL)   // WWN found?
-      {
-        // WWN has same port_id as last login?  (Of course, a properly
-	// working FC device should NEVER ACCept a PDISC if it's
-	// port_id changed, but check just in case...)
-	if( (fchs->s_id & 0xFFFFFF) == pLoggedInPort->port_id)
-	{
-          // Yes.  We were expecting PDISC?
-          if( pLoggedInPort->pdisc )
-	  {
-            int i;
-	    
-	    
-	    // PDISC expected -- set fields.  (PDISC, Originator)
-            SetLoginFields( pLoggedInPort, fchs, TRUE, TRUE);
+	case ELS_FDISC:	// we sent out FDISC (Fabric Discovery (Login))
+		printk(" ELS_FDISC success ");
+		break;
 
-	    // We are ready to resume FCP-SCSI to this device...
-            // Do we need to start anything that was Queued?
+	case ELS_SCR:		// we sent out State Change Registration
+		// now we can issue Name Service Request to find any
+		// Fabric-connected devices we might want to login to.
+		fchs->s_id = 0xFFFFFC;	// Name Server Address
+		cpqfcTSPutLinkQue(dev, FCS_NSR, fchs);
+		break;
 
-            for( i=0; i< TACH_SEST_LEN; i++)
-            {
-              // see if any exchange for this PDISC'd port was queued
-              if( ((fchs->s_id &0xFFFFFF) == 
-                   (Exchanges->fcExchange[i].fchs.d_id & 0xFFFFFF))
-                      &&
-                  (Exchanges->fcExchange[i].status & EXCHANGE_QUEUED))
-              {
-                fchs->reserved = i; // copy ExchangeID
-//                printk(" *Q x_ID %Xh after PDISC* ",i);
-
-                cpqfcTSPutLinkQue( cpqfcHBAdata, EXCHANGE_QUEUED, fchs );
-              }
-            }
-
-	    // Complete commands Q'd while we were waiting for Login
-
-	    UnblockScsiDevice( cpqfcHBAdata->HostAdapter, pLoggedInPort);
-	  }
-	  else
-	  {
-	    printk("Not expecting PDISC (pdisc=FALSE)\n");
-	    NeedLogin = TRUE;
-	  }
+	default:
+		printk(" *Discarding unknown ACC frame, xID %04X/%04X* ", ox_id, fchs->ox_rx_id & 0xffff);
+		break;
 	}
-	else
-	{
-	  printk("PDISC PortID change: old %Xh, new %Xh\n",
-            pLoggedInPort->port_id, fchs->s_id &0xFFFFFF);
-          NeedLogin = TRUE;
-		  
-	}
-      }
-      else
-      {
-	printk("PDISC ACC from unknown WWN\n");
-        NeedLogin = TRUE;
-      }
-
-      if( NeedLogin)
-      {
-	
-        // The PDISC failed.  Set login struct flags accordingly,
-	// terminate any I/O to this port, and Q a PLOGI
-	if( pLoggedInPort )  // FC device previously known?
-	{
-
-          cpqfcTSPutLinkQue( cpqfcHBAdata,
-                    ELS_LOGO, // Q Type
-                    fchs );   // has port_id to send to 
-
-	  // There are a variety of error scenarios which can result
-  	  // in PDISC failure, so as a catchall, add the check for
-	  // duplicate port_id.
-	  TestDuplicatePortId( cpqfcHBAdata, pLoggedInPort);
-
-//    TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
-          pLoggedInPort->pdisc = FALSE;
-          pLoggedInPort->prli = FALSE;
-          pLoggedInPort->plogi = FALSE;
-	
-          cpqfcTSTerminateExchange( cpqfcHBAdata, 
-	    &pLoggedInPort->ScsiNexus, PORTID_CHANGED);
-        }
-        cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_PLOGI, fchs );
-      }
-    }
-    else
-    {
-      // login payload unacceptable - reason in ls_reject_code
-      // Q up a Logout Request
-      printk("ERROR: Login Payload unacceptable!\n");
-
-    }
-   
-    break;
-    
-
-
-  case ELS_PRLI:  // we sent out PRLI
-
-
-    pLoggedInPort = fcFindLoggedInPort( 
-           fcChip, 
-           NULL,       // don't search Scsi Nexus
-	   (fchs->s_id & 0xFFFFFF),  // search linked list for port_id
-           NULL,     // DON'T search linked list for WWN
-           NULL);    // don't care
-      
-    if( pLoggedInPort == NULL ) 
-    {
-      // huh?
-      printk(" Unexpected PRLI ACCept frame!\n");
-
-      // Q a LOGOut here?
-
-      goto Done;
-    }
-
-    // verify the PRLI ACC payload
-    if( !verify_PRLI( fchs, &ls_reject_code) )
-    {
-      // PRLI Reply is acceptable; were we expecting it?
-      if( pLoggedInPort->plogi ) 
-      { 
-	// yes, we expected the PRLI ACC  (not PDISC; Originator)
-	SetLoginFields( pLoggedInPort, fchs, FALSE, TRUE);
-
-        // OK, let's send a REPORT_LUNS command to determine
-	// whether VSA or PDA FCP-LUN addressing is used.
-	
-        cpqfcTSPutLinkQue( cpqfcHBAdata, SCSI_REPORT_LUNS, fchs );
-	
-	// It's possible that a device we were talking to changed 
-	// port_id, and has logged back in.  This function ensures
-	// that I/O will resume.
-        UnblockScsiDevice( cpqfcHBAdata->HostAdapter, pLoggedInPort);
-
-      }
-      else
-      {
-        // huh?
-        printk(" (unexpected) PRLI ACCept with plogi FALSE\n");
-
-        // Q a LOGOut here?
-        goto Done;
-      }
-    }
-    else
-    {
-      printk(" PRLI ACCept payload failed verify\n");
-
-      // Q a LOGOut here?
-    }
-
-    break;
- 
-  case ELS_FLOGI:  // we sent out FLOGI (Fabric Login)
-
-    // update the upper 16 bits of our port_id in Tachyon
-    // the switch adds those upper 16 bits when responding
-    // to us (i.e. we are the destination_id)
-    fcChip->Registers.my_al_pa = (fchs->d_id & 0xFFFFFF);
-    writel( fcChip->Registers.my_al_pa,  
-      fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID);
-
-    // now send out a PLOGI to the well known port_id 0xFFFFFC
-    fchs->s_id = 0xFFFFFC;
-    cpqfcTSPutLinkQue( cpqfcHBAdata, ELS_PLOGI, fchs);
-  
-   break; 
-
-
-  case ELS_FDISC:  // we sent out FDISC (Fabric Discovery (Login))
-
-   printk( " ELS_FDISC success ");
-   break;
-   
-
-  case ELS_SCR:  // we sent out State Change Registration
-    // now we can issue Name Service Request to find any
-    // Fabric-connected devices we might want to login to.
-   
-	
-    fchs->s_id = 0xFFFFFC;  // Name Server Address
-    cpqfcTSPutLinkQue( cpqfcHBAdata, FCS_NSR, fchs);
-    
-
-    break;
-
-    
-  default:
-    printk(" *Discarding unknown ACC frame, xID %04X/%04X* ", 
-   		    ox_id, fchs->ox_rx_id & 0xffff);
-    break;
-  }
-
-  
 Done:
-  // Regardless of whether the Reply is valid or not, the
-  // the exchange is done - complete
-  cpqfcTSCompleteExchange(cpqfcHBAdata->PciDev, fcChip, (fchs->ox_rx_id >>16)); 
-	  
-Quit:    
-  return;
+	// Regardless of whether the Reply is valid or not, the
+	// the exchange is done - complete
+	cpqfcTSCompleteExchange(dev->PciDev, fcChip, (fchs->ox_rx_id >> 16));
+Quit:
+	return;
 }
 
 
@@ -2075,352 +1604,263 @@
 // This is where we process the Directory (Name) Service Reply
 // to know which devices are on the Fabric
 
-static void ProcessFCS_Reply( 
-	CPQFCHBA* cpqfcHBAdata, TachFCHDR_GCMND* fchs)
+static void ProcessFCS_Reply(CPQFCHBA * dev, TachFCHDR_GCMND * fchs)
 {
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  ULONG ox_id = (fchs->ox_rx_id >>16);
-//  ULONG ls_reject_code;
-//  PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort;
-  
-  // If this is a valid reply, then we MUST have sent a request.
-  // Verify that we can find a valid request OX_ID corresponding to
-  // this reply
-
-  if( Exchanges->fcExchange[(fchs->ox_rx_id >>16)].type == 0)
-  {
-    printk(" *Discarding Reply frame, xID %04X/%04X* ", 
-		    ox_id, fchs->ox_rx_id & 0xffff);
-    goto Quit;  // exit this routine
-  }
-
+	PTACHYON fcChip = &dev->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	u32 ox_id = (fchs->ox_rx_id >> 16);
+//	u32 ls_reject_code;
+//	PFC_LOGGEDIN_PORT pLoggedInPort, pLastLoggedInPort;
+
+	// If this is a valid reply, then we MUST have sent a request.
+	// Verify that we can find a valid request OX_ID corresponding to
+	// this reply
+
+	if (Exchanges->fcExchange[(fchs->ox_rx_id >> 16)].type == 0) {
+		printk(" *Discarding Reply frame, xID %04X/%04X* ", ox_id, fchs->ox_rx_id & 0xffff);
+		goto Quit;	// exit this routine
+	}
 
-  // OK, we were expecting it.  Now check to see if it's a
-  // "Name Service" Reply, and if so force a re-validation of
-  // Fabric device logins (i.e. Start the login timeout and
-  // send PDISC or PLOGI)
-  // (Endianess Byte Swap?)
-  if( fchs->pl[1] == 0x02FC )  // Name Service
-  {
-    // got a new (or NULL) list of Fabric attach devices... 
-    // Invalidate current logins
-    
-    PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts;
-    while( pLoggedInPort ) // for all ports which are expecting
-                           // PDISC after the next LIP, set the
-                           // logoutTimer
-    {
+	// OK, we were expecting it.  Now check to see if it's a
+	// "Name Service" Reply, and if so force a re-validation of
+	// Fabric device logins (i.e. Start the login timeout and
+	// send PDISC or PLOGI)
+	// (Endianess Byte Swap?)
+	if (fchs->pl[1] == 0x02FC)	// Name Service
+	{
+		// got a new (or NULL) list of Fabric attach devices... 
+		// Invalidate current logins
 
-      if( (pLoggedInPort->port_id & 0xFFFF00)  // Fabric device?
-		      &&
-          (pLoggedInPort->port_id != 0xFFFFFC) ) // NOT the F_Port
-      {
-        pLoggedInPort->LOGO_timer = 6;  // what's the Fabric timeout??
-                                // suspend any I/O in progress until
-                                // PDISC received...
-        pLoggedInPort->prli = FALSE;   // block FCP-SCSI commands
-      }
-	    
-      pLoggedInPort = pLoggedInPort->pNextPort;
-    }
-    
-    if( fchs->pl[2] == 0x0280)  // ACCept?
-    {
-      // Send PLOGI or PDISC to these Fabric devices
-      SendLogins( cpqfcHBAdata, &fchs->pl[4] );  
-    }
+		PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts;
+		while (pLoggedInPort)	// for all ports which are expecting
+			// PDISC after the next LIP, set the
+			// logoutTimer
+		{
+
+			if ((pLoggedInPort->port_id & 0xFFFF00)	// Fabric device?
+			    && (pLoggedInPort->port_id != 0xFFFFFC))	// NOT the F_Port
+			{
+				pLoggedInPort->LOGO_timer = 6;	// what's the Fabric timeout??
+				// suspend any I/O in progress until
+				// PDISC received...
+				pLoggedInPort->prli = 0;	// block FCP-SCSI commands
+			}
 
+			pLoggedInPort = pLoggedInPort->pNextPort;
+		}
 
-    // As of this writing, the only reason to reject is because NO
-    // devices are left on the Fabric.  We already started
-    // "logged out" timers; if the device(s) don't come
-    // back, we'll do the implicit logout in the heart beat 
-    // timer routine
-    else  // ReJecT
-    {
-      // this just means no Fabric device is visible at this instant
-    } 
-  }
+		if (fchs->pl[2] == 0x0280)	// ACCept?
+		{
+			// Send PLOGI or PDISC to these Fabric devices
+			SendLogins(dev, &fchs->pl[4]);
+		}
+		// As of this writing, the only reason to reject is because NO
+		// devices are left on the Fabric.  We already started
+		// "logged out" timers; if the device(s) don't come
+		// back, we'll do the implicit logout in the heart beat 
+		// timer routine
+		else		// ReJecT
+		{
+			// this just means no Fabric device is visible at this instant
+		}
+	}
+	// Regardless of whether the Reply is valid or not, the
+	// the exchange is done - complete
+	cpqfcTSCompleteExchange(dev->PciDev, fcChip, (fchs->ox_rx_id >> 16));
 
-  // Regardless of whether the Reply is valid or not, the
-  // the exchange is done - complete
-  cpqfcTSCompleteExchange(cpqfcHBAdata->PciDev, fcChip, (fchs->ox_rx_id >>16));
-	  
-Quit:    
-  return;
+Quit:
+	return;
 }
 
-
-
-
-
-
-
-static void AnalyzeIncomingFrame( 
-        CPQFCHBA *cpqfcHBAdata,
-        ULONG QNdx )
+static void AnalyzeIncomingFrame(CPQFCHBA * dev, u32 QNdx)
 {
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  PFC_LINK_QUE fcLQ = cpqfcHBAdata->fcLQ;
-  TachFCHDR_GCMND* fchs = 
-    (TachFCHDR_GCMND*)fcLQ->Qitem[QNdx].ulBuff;
-//  ULONG ls_reject_code;  // reason for rejecting login
-  LONG ExchangeID;
-//  FC_LOGGEDIN_PORT *pLoggedInPort;
-  BOOLEAN AbortAccept;  
-
-  ENTER("AnalyzeIncomingFrame");
-
-
-
-  switch( fcLQ->Qitem[QNdx].Type) // FCP or Unknown
-  {
+	PTACHYON fcChip = &dev->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	PFC_LINK_QUE fcLQ = dev->fcLQ;
+	TachFCHDR_GCMND *fchs = (TachFCHDR_GCMND *) fcLQ->Qitem[QNdx].ulBuff;
+//	u32 ls_reject_code;  // reason for rejecting login
+	s32 ExchangeID;
+//	FC_LOGGEDIN_PORT *pLoggedInPort;
+	u8 AbortAccept;
 
-  case SFQ_UNKNOWN:  // unknown frame (e.g. LIP position frame, NOP, etc.)
- 
+	ENTER("AnalyzeIncomingFrame");
 
-      // *********  FC-4 Device Data/ Fibre Channel Service *************
-    if( ((fchs->d_id &0xF0000000) == 0)   // R_CTL (upper nibble) 0x0?
-                &&   
-      (fchs->f_ctl & 0x20000000) )  // TYPE 20h is Fibre Channel Service
-    {
-
-      // ************** FCS Reply **********************
-
-      if( (fchs->d_id & 0xff000000L) == 0x03000000L)  // (31:23 R_CTL)
-      {
-	ProcessFCS_Reply( cpqfcHBAdata, fchs );
-
-      }  // end of  FCS logic
-
-    }
-    
-
-      // ***********  Extended Link Service **************
-
-    else if( fchs->d_id & 0x20000000   // R_CTL 0x2?
-                  &&   
-      (fchs->f_ctl & 0x01000000) )  // TYPE = 1
-    {
-
-                           // these frames are either a response to
-                           // something we sent (0x23) or "unsolicited"
-                           // frames (0x22).
-
-
-      // **************Extended Link REPLY **********************
-                           // R_CTL Solicited Control Reply
-
-      if( (fchs->d_id & 0xff000000L) == 0x23000000L)  // (31:23 R_CTL)
-      {
-
-	ProcessELS_Reply( cpqfcHBAdata, fchs );
-
-      }  // end of  "R_CTL Solicited Control Reply"
-
-
-
-
-       // **************Extended Link REQUEST **********************
-       // (unsolicited commands from another port or task...)
-
-                           // R_CTL Ext Link REQUEST
-      else if( (fchs->d_id & 0xff000000L) == 0x22000000L &&
-              (fchs->ox_rx_id != 0xFFFFFFFFL) ) // (ignore LIP frame)
-      {
-
-
-
-	ProcessELS_Request( cpqfcHBAdata, fchs );
-
-      }
-
-
-
-        // ************** LILP **********************
-      else if( (fchs->d_id & 0xff000000L) == 0x22000000L &&
-               (fchs->ox_rx_id == 0xFFFFFFFFL)) // (e.g., LIP frames)
-
-      {
-        // SANMark specifies that when available, we must use
-	// the LILP frame to determine which ALPAs to send Port Discovery
-	// to...
-
-        if( fchs->pl[0] == 0x0711L) //  ELS_PLOGI?
+	switch (fcLQ->Qitem[QNdx].Type)	// FCP or Unknown
 	{
-//	  UCHAR *ptr = (UCHAR*)&fchs->pl[1];
-//	  printk(" %d ALPAs found\n", *ptr);
-	  memcpy( fcChip->LILPmap, &fchs->pl[1], 32*4); // 32 DWORDs
-	  fcChip->Options.LILPin = 1; // our LILPmap is valid!
-	  // now post to make Port Discovery happen...
-          cpqfcTSPutLinkQue( cpqfcHBAdata, LINKACTIVE, fchs);  
-	}
-      }
-    }
-
-     
-    // *****************  BASIC LINK SERVICE *****************
-    
-    else if( fchs->d_id & 0x80000000  // R_CTL:
-                    &&           // Basic Link Service Request
-           !(fchs->f_ctl & 0xFF000000) )  // type=0 for BLS
-    {
+	case SFQ_UNKNOWN:	// unknown frame (e.g. LIP position frame, NOP, etc.)
+		// *********  FC-4 Device Data/ Fibre Channel Service *************
+		if (((fchs->d_id & 0xF0000000) == 0)	// R_CTL (upper nibble) 0x0?
+		    && (fchs->f_ctl & 0x20000000))	// TYPE 20h is Fibre Channel Service
+		{
+			// ************** FCS Reply **********************
+			if ((fchs->d_id & 0xff000000L) == 0x03000000L)	// (31:23 R_CTL)
+			{
+				ProcessFCS_Reply(dev, fchs);
+			}	// end of  FCS logic
+		}
+		// ***********  Extended Link Service **************
+		else if (fchs->d_id & 0x20000000	// R_CTL 0x2?
+			 && (fchs->f_ctl & 0x01000000))	// TYPE = 1
+		{
+			// these frames are either a response to
+			// something we sent (0x23) or "unsolicited"
+			// frames (0x22).
+			// **************Extended Link REPLY **********************
+			// R_CTL Solicited Control Reply
+			if ((fchs->d_id & 0xff000000L) == 0x23000000L)	// (31:23 R_CTL)
+			{
+				ProcessELS_Reply(dev, fchs);
+			}	// end of  "R_CTL Solicited Control Reply"
+			// **************Extended Link REQUEST **********************
+			// (unsolicited commands from another port or task...)
+			// R_CTL Ext Link REQUEST
+			else if ((fchs->d_id & 0xff000000L) == 0x22000000L && (fchs->ox_rx_id != 0xFFFFFFFFL))	// (ignore LIP frame)
+			{
+				ProcessELS_Request(dev, fchs);
+			}
+			// ************** LILP **********************
+			else if ((fchs->d_id & 0xff000000L) == 0x22000000L && (fchs->ox_rx_id == 0xFFFFFFFFL))	// (e.g., LIP frames)
+			{
+				// SANMark specifies that when available, we must use
+				// the LILP frame to determine which ALPAs to send Port Discovery
+				// to...
+				if (fchs->pl[0] == 0x0711L)	//  ELS_PLOGI?
+				{
+//					u8 *ptr = (u8*)&fchs->pl[1];
+//					printk(" %d ALPAs found\n", *ptr);
+					memcpy(fcChip->LILPmap, &fchs->pl[1], 32 * 4);	// 32 DWORDs
+					fcChip->Options.LILPin = 1;	// our LILPmap is valid!
+					// now post to make Port Discovery happen...
+					cpqfcTSPutLinkQue(dev, LINKACTIVE, fchs);
+				}
+			}
+		}
+		// *****************  BASIC LINK SERVICE *****************
+		else if (fchs->d_id & 0x80000000	// R_CTL:
+			 &&	// Basic Link Service Request
+			 !(fchs->f_ctl & 0xFF000000))	// type=0 for BLS
+		{
+			// Check for ABTS (Abort Sequence)
+			if ((fchs->d_id & 0x8F000000) == 0x81000000) {
+				// look for OX_ID, S_ID pair that matches in our
+				// fcExchanges table; if found, reply with ACCept and complete
+				// the exchange
+
+				// Per PLDA, an ABTS is sent by an initiator; therefore
+				// assume that if we have an exhange open to the port who
+				// sent ABTS, it will be the d_id of what we sent.  
+				for (ExchangeID = 0, AbortAccept = 0; ExchangeID < TACH_SEST_LEN; ExchangeID++) {
+					// Valid "target" exchange 24-bit port_id matches? 
+					// NOTE: For the case of handling Intiator AND Target
+					// functions on the same chip, we can have TWO Exchanges
+					// with the same OX_ID -- OX_ID/FFFF for the CMND, and
+					// OX_ID/RX_ID for the XRDY or DATA frame(s).  Ideally,
+					// we would like to support ABTS from Initiators or Targets,
+					// but it's not clear that can be supported on Tachyon for
+					// all cases (requires more investigation).
+
+					if ((Exchanges->fcExchange[ExchangeID].type == SCSI_TWE || Exchanges->fcExchange[ExchangeID].type == SCSI_TRE)
+					    && ((Exchanges->fcExchange[ExchangeID].fchs.d_id & 0xFFFFFF) == (fchs->s_id & 0xFFFFFF))) {
+
+						// target xchnge port_id matches -- how about OX_ID?
+						if ((Exchanges->fcExchange[ExchangeID].fchs.ox_rx_id & 0xFFFF0000)
+						    == (fchs->ox_rx_id & 0xFFFF0000))
+							// yes! post ACCept response; will be completed by fcStart
+						{
+							Exchanges->fcExchange[ExchangeID].status = TARGET_ABORT;
+
+							// copy (add) rx_id field for simplified ACCept reply
+							fchs->ox_rx_id = Exchanges->fcExchange[ExchangeID].fchs.ox_rx_id;
+
+							cpqfcTSPutLinkQue(dev, BLS_ABTS_ACC,	// Q Type 
+									  fchs);	// void QueContent
+							AbortAccept = 1;
+							printk("ACCepting ABTS for x_ID %8.8Xh, SEST pair %8.8Xh\n", fchs->ox_rx_id, Exchanges->fcExchange[ExchangeID].fchs.ox_rx_id);
+							break;	// ABTS can affect only ONE exchange -exit loop
+						}
+					}
+				}	// end of FOR loop
+				if (!AbortAccept)	// can't ACCept ABTS - send Reject
+				{
+					printk("ReJecTing: can't find ExchangeID %8.8Xh for ABTS command\n", fchs->ox_rx_id);
+					if (Exchanges->fcExchange[ExchangeID].type && !(fcChip->SEST->u[ExchangeID].IWE.Hdr_Len & 0x80000000)) {
+						cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
+					} else {
+						printk("Unexpected ABTS ReJecT! SEST[%X] Dword 0: %Xh\n", ExchangeID, fcChip->SEST->u[ExchangeID].IWE.Hdr_Len);
+					}
+				}
+			}
+			// Check for BLS {ABTS? (Abort Sequence)} ACCept
+			else if ((fchs->d_id & 0x8F000000) == 0x84000000) {
+				// target has responded with ACC for our ABTS;
+				// complete the indicated exchange with ABORTED status 
+				// Make no checks for correct RX_ID, since
+				// all we need to conform ABTS ACC is the OX_ID.
+				// Verify that the d_id matches!
 
-      // Check for ABTS (Abort Sequence)
-      if( (fchs->d_id & 0x8F000000) == 0x81000000)
-      {
-        // look for OX_ID, S_ID pair that matches in our
-        // fcExchanges table; if found, reply with ACCept and complete
-        // the exchange
-
-        // Per PLDA, an ABTS is sent by an initiator; therefore
-        // assume that if we have an exhange open to the port who
-        // sent ABTS, it will be the d_id of what we sent.  
-        for( ExchangeID = 0, AbortAccept=FALSE;
-             ExchangeID < TACH_SEST_LEN; ExchangeID++)
-        {
-            // Valid "target" exchange 24-bit port_id matches? 
-            // NOTE: For the case of handling Intiator AND Target
-            // functions on the same chip, we can have TWO Exchanges
-            // with the same OX_ID -- OX_ID/FFFF for the CMND, and
-            // OX_ID/RX_ID for the XRDY or DATA frame(s).  Ideally,
-            // we would like to support ABTS from Initiators or Targets,
-            // but it's not clear that can be supported on Tachyon for
-            // all cases (requires more investigation).
-            
-          if( (Exchanges->fcExchange[ ExchangeID].type == SCSI_TWE ||
-               Exchanges->fcExchange[ ExchangeID].type == SCSI_TRE)
-                  &&
-             ((Exchanges->fcExchange[ ExchangeID].fchs.d_id & 0xFFFFFF) ==
-             (fchs->s_id & 0xFFFFFF)) )
-          {
-              
-              // target xchnge port_id matches -- how about OX_ID?
-            if( (Exchanges->fcExchange[ ExchangeID].fchs.ox_rx_id &0xFFFF0000)
-                    == (fchs->ox_rx_id & 0xFFFF0000) )
-                    // yes! post ACCept response; will be completed by fcStart
-            {
-              Exchanges->fcExchange[ ExchangeID].status = TARGET_ABORT;
-                
-                // copy (add) rx_id field for simplified ACCept reply
-              fchs->ox_rx_id = 
-                Exchanges->fcExchange[ ExchangeID].fchs.ox_rx_id;
-                
-              cpqfcTSPutLinkQue( cpqfcHBAdata,
-                            BLS_ABTS_ACC, // Q Type 
-                            fchs );    // void QueContent
-              AbortAccept = TRUE;
-      printk("ACCepting ABTS for x_ID %8.8Xh, SEST pair %8.8Xh\n", 
-             fchs->ox_rx_id, Exchanges->fcExchange[ ExchangeID].fchs.ox_rx_id);
-              break;      // ABTS can affect only ONE exchange -exit loop
-            }
-          }
-        }  // end of FOR loop
-        if( !AbortAccept ) // can't ACCept ABTS - send Reject
-        {
-      printk("ReJecTing: can't find ExchangeID %8.8Xh for ABTS command\n", 
-            fchs->ox_rx_id);
-          if( Exchanges->fcExchange[ ExchangeID].type 
-                &&
-              !(fcChip->SEST->u[ ExchangeID].IWE.Hdr_Len
-               & 0x80000000))
-          {
-            cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID);
-          }
-          else
-          {
-            printk("Unexpected ABTS ReJecT! SEST[%X] Dword 0: %Xh\n", 
-              ExchangeID, fcChip->SEST->u[ ExchangeID].IWE.Hdr_Len);
-          }
-        }
-      }
-
-      // Check for BLS {ABTS? (Abort Sequence)} ACCept
-      else if( (fchs->d_id & 0x8F000000) == 0x84000000)
-      {
-        // target has responded with ACC for our ABTS;
-	// complete the indicated exchange with ABORTED status 
-        // Make no checks for correct RX_ID, since
-	// all we need to conform ABTS ACC is the OX_ID.
-        // Verify that the d_id matches!
- 
-        ExchangeID = (fchs->ox_rx_id >> 16) & 0x7FFF; // x_id from ACC
-//	printk("ABTS ACC x_ID 0x%04X 0x%04X, status %Xh\n", 
+				ExchangeID = (fchs->ox_rx_id >> 16) & 0x7FFF;	// x_id from ACC
+//      printk("ABTS ACC x_ID 0x%04X 0x%04X, status %Xh\n", 
 //          fchs->ox_rx_id >> 16, fchs->ox_rx_id & 0xffff,
 //          Exchanges->fcExchange[ExchangeID].status);
+				if (ExchangeID < TACH_SEST_LEN)	// x_ID makes sense
+				{
+					// Does "target" exchange 24-bit port_id match? 
+					// (See "NOTE" above for handling Intiator AND Target in
+					// the same device driver)
+					// First, if this is a target response, then we originated
+					// (initiated) it with BLS_ABTS:
+
+					if ((Exchanges->fcExchange[ExchangeID].type == BLS_ABTS) &&
+					    // Second, does the source of this ACC match the destination
+					    // of who we originally sent it to?
+					    ((Exchanges->fcExchange[ExchangeID].fchs.d_id & 0xFFFFFF) == (fchs->s_id & 0xFFFFFF))) {
+						cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
+					}
+				}
+			}
+			// Check for BLS {ABTS? (Abort Sequence)} ReJecT
+			else if ((fchs->d_id & 0x8F000000) == 0x85000000) {
+				// target has responded with RJT for our ABTS;
+				// complete the indicated exchange with ABORTED status 
+				// Make no checks for correct RX_ID, since
+				// all we need to conform ABTS ACC is the OX_ID.
+				// Verify that the d_id matches!
+
+				ExchangeID = (fchs->ox_rx_id >> 16) & 0x7FFF;	// x_id from ACC
+//				printk("BLS_ABTS RJT on Exchange 0x%04X 0x%04X\n", 
+//					fchs->ox_rx_id >> 16, fchs->ox_rx_id & 0xffff);
+
+				if (ExchangeID < TACH_SEST_LEN)	// x_ID makes sense
+				{
+					// Does "target" exchange 24-bit port_id match? 
+					// (See "NOTE" above for handling Intiator AND Target in
+					// the same device driver)
+					// First, if this is a target response, then we originated
+					// (initiated) it with BLS_ABTS:
+
+					if ((Exchanges->fcExchange[ExchangeID].type == BLS_ABTS)
+
+					    &&
+					    // Second, does the source of this ACC match the destination
+					    // of who we originally sent it to?
+					    ((Exchanges->fcExchange[ExchangeID].fchs.d_id & 0xFFFFFF) == (fchs->s_id & 0xFFFFFF))) {
+						// YES! NOTE: There is a bug in CPQ's RA-4000 box 
+						// where the "reason code" isn't returned in the payload
+						// For now, simply presume the reject is because the target
+						// already completed the exchange...
+
+//						printk("complete x_ID %Xh on ABTS RJT\n", ExchangeID);
+						cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
+					}
+				}
+			}	// end of ABTS check
+		}		// end of Basic Link Service Request
+		break;
 
-
-	
-        if( ExchangeID < TACH_SEST_LEN ) // x_ID makes sense
-        {
-            // Does "target" exchange 24-bit port_id match? 
-            // (See "NOTE" above for handling Intiator AND Target in
-            // the same device driver)
-            // First, if this is a target response, then we originated
-	    // (initiated) it with BLS_ABTS:
-	  
-          if( (Exchanges->fcExchange[ ExchangeID].type == BLS_ABTS)
-
-                  &&
-	    // Second, does the source of this ACC match the destination
-            // of who we originally sent it to?
-             ((Exchanges->fcExchange[ ExchangeID].fchs.d_id & 0xFFFFFF) ==
-             (fchs->s_id & 0xFFFFFF)) )
-          {
-            cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID );
-	  }
-        }              
-      }
-      // Check for BLS {ABTS? (Abort Sequence)} ReJecT
-      else if( (fchs->d_id & 0x8F000000) == 0x85000000)
-      {
-        // target has responded with RJT for our ABTS;
-	// complete the indicated exchange with ABORTED status 
-        // Make no checks for correct RX_ID, since
-	// all we need to conform ABTS ACC is the OX_ID.
-        // Verify that the d_id matches!
- 
-        ExchangeID = (fchs->ox_rx_id >> 16) & 0x7FFF; // x_id from ACC
-//	printk("BLS_ABTS RJT on Exchange 0x%04X 0x%04X\n", 
-//          fchs->ox_rx_id >> 16, fchs->ox_rx_id & 0xffff);
-
-        if( ExchangeID < TACH_SEST_LEN ) // x_ID makes sense
-	{  
-            // Does "target" exchange 24-bit port_id match? 
-            // (See "NOTE" above for handling Intiator AND Target in
-            // the same device driver)
-            // First, if this is a target response, then we originated
-	    // (initiated) it with BLS_ABTS:
-		  
-          if( (Exchanges->fcExchange[ ExchangeID].type == BLS_ABTS)
-
-                  &&
-	    // Second, does the source of this ACC match the destination
-            // of who we originally sent it to?
-             ((Exchanges->fcExchange[ ExchangeID].fchs.d_id & 0xFFFFFF) ==
-             (fchs->s_id & 0xFFFFFF)) )
-          {
-	    // YES! NOTE: There is a bug in CPQ's RA-4000 box 
-	    // where the "reason code" isn't returned in the payload
-	    // For now, simply presume the reject is because the target
-	    // already completed the exchange...
-	    
-//            printk("complete x_ID %Xh on ABTS RJT\n", ExchangeID);
-            cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID );
-	  }
-	} 
-      }  // end of ABTS check
-    }  // end of Basic Link Service Request
-    break;
-  
-    default:
-      printk("AnalyzeIncomingFrame: unknown type: %Xh(%d)\n",
-        fcLQ->Qitem[QNdx].Type,
-        fcLQ->Qitem[QNdx].Type);
-    break;
-  }
+	default:
+		printk("AnalyzeIncomingFrame: unknown type: %Xh(%d)\n", fcLQ->Qitem[QNdx].Type, fcLQ->Qitem[QNdx].Type);
+		break;
+	}
 }
 
 
@@ -2428,506 +1868,433 @@
 // initialization (e.g. LIP).
 // Also may be called if from Fabric Name Service logic.
 
-static void SendLogins( CPQFCHBA *cpqfcHBAdata, __u32 *FabricPortIds )
+static void SendLogins(CPQFCHBA * dev, __u32 * FabricPortIds)
 {
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  ULONG ulStatus=0;
-  TachFCHDR_GCMND fchs;  // copy fields for transmission
-  int i;
-  ULONG loginType;
-  LONG ExchangeID;
-  PFC_LOGGEDIN_PORT pLoggedInPort;
-  __u32 PortIds[ number_of_al_pa];
-  int NumberOfPorts=0;
-
-  // We're going to presume (for now) that our limit of Fabric devices
-  // is the same as the number of alpa on a private loop (126 devices).
-  // (Of course this could be changed to support however many we have
-  // memory for).
-  memset( &PortIds[0], 0, sizeof(PortIds));
-   
-  // First, check if this login is for our own Link Initialization
-  // (e.g. LIP on FC-AL), or if we have knowledge of Fabric devices
-  // from a switch.  If we are logging into Fabric devices, we'll
-  // have a non-NULL FabricPortId pointer
-  
-  if( FabricPortIds != NULL) // may need logins
-  {
-    int LastPort=FALSE;
-    i = 0;
-    while( !LastPort)
-    {
-      // port IDs From NSR payload; byte swap needed?
-      BigEndianSwap( (UCHAR*)FabricPortIds, (UCHAR*)&PortIds[i], 4);
- 
-//      printk("FPortId[%d] %Xh ", i, PortIds[i]);
-      if( PortIds[i] & 0x80000000)
-	LastPort = TRUE;
-      
-      PortIds[i] &= 0xFFFFFF; // get 24-bit port_id
-      // some non-Fabric devices (like the Crossroads Fibre/Scsi bridge)
-      // erroneously use ALPA 0.
-      if( PortIds[i]  ) // need non-zero port_id...
-        i++;
-      
-      if( i >= number_of_al_pa ) // (in)sanity check
-	break;
-      FabricPortIds++;  // next...
-    }
-
-    NumberOfPorts = i;
-//    printk("NumberOf Fabric ports %d", NumberOfPorts);
-  }
-  
-  else  // need to send logins on our "local" link
-  {
-  
-    // are we a loop port?  If so, check for reception of LILP frame,
-    // and if received use it (SANMark requirement)
-    if( fcChip->Options.LILPin )
-    {
-      int j=0;
-      // sanity check on number of ALPAs from LILP frame...
-      // For format of LILP frame, see FC-AL specs or 
-      // "Fibre Channel Bench Reference", J. Stai, 1995 (ISBN 1-879936-17-8)
-      // First byte is number of ALPAs
-      i = fcChip->LILPmap[0] >= (32*4) ? 32*4 : fcChip->LILPmap[0];
-      NumberOfPorts = i;
-//      printk(" LILP alpa count %d ", i);
-      while( i > 0)
-      {
-	PortIds[j] = fcChip->LILPmap[1+ j];
-	j++; i--;
-      }
-    }
-    else  // have to send login to everybody
-    {
-      int j=0;
-      i = number_of_al_pa;
-      NumberOfPorts = i;
-      while( i > 0)
-      {
-        PortIds[j] = valid_al_pa[j]; // all legal ALPAs
-	j++; i--;
-      }
-    }
-  }
-
-
-  // Now we have a copy of the port_ids (and how many)...
-  for( i = 0; i < NumberOfPorts; i++)
-  {
-    // 24-bit FC Port ID
-    fchs.s_id = PortIds[i];  // note: only 8-bits used for ALPA
+	PTACHYON fcChip = &dev->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	u32 ulStatus = 0;
+	TachFCHDR_GCMND fchs;	// copy fields for transmission
+	int i;
+	u32 loginType;
+	s32 ExchangeID;
+	PFC_LOGGEDIN_PORT pLoggedInPort;
+	__u32 PortIds[number_of_al_pa];
+	int NumberOfPorts = 0;
+
+	// We're going to presume (for now) that our limit of Fabric devices
+	// is the same as the number of alpa on a private loop (126 devices).
+	// (Of course this could be changed to support however many we have
+	// memory for).
+	memset(&PortIds[0], 0, sizeof(PortIds));
+
+	// First, check if this login is for our own Link Initialization
+	// (e.g. LIP on FC-AL), or if we have knowledge of Fabric devices
+	// from a switch.  If we are logging into Fabric devices, we'll
+	// have a non-NULL FabricPortId pointer
 
-
-    // don't log into ourselves (Linux Scsi disk scan will stop on
-    // no TARGET support error on us, and quit trying for rest of devices)
-    if( (fchs.s_id & 0xFF ) == (fcChip->Registers.my_al_pa & 0xFF) )
-      continue;
-
-    // fabric login needed?
-    if( (fchs.s_id == 0) || 
-        (fcChip->Options.fabric == 1) )
-    {
-      fcChip->Options.flogi = 1;  // fabric needs longer for login
-      // Do we need FLOGI or FDISC?
-      pLoggedInPort = fcFindLoggedInPort( 
-             fcChip, 
-             NULL,           // don't search SCSI Nexus
-             0xFFFFFC,       // search linked list for Fabric port_id
-             NULL,           // don't search WWN
-             NULL);          // (don't care about end of list)
-
-      if( pLoggedInPort )    // If found, we have prior experience with
-                             // this port -- check whether PDISC is needed
-      {
-        if( pLoggedInPort->flogi )
+	if (FabricPortIds != NULL)	// may need logins
 	{
-	  // does the switch support FDISC?? (FLOGI for now...)
-          loginType = ELS_FLOGI;  // prior FLOGI still valid
-	}
-        else
-          loginType = ELS_FLOGI;  // expired FLOGI
-      }
-      else                      // first FLOGI?
-        loginType = ELS_FLOGI;  
-
-
-      fchs.s_id = 0xFFFFFE;   // well known F_Port address
-
-      // Fabrics are not required to support FDISC, and
-      // it's not clear if that helps us anyway, since
-      // we'll want a Name Service Request to re-verify
-      // visible devices...
-      // Consequently, we always want our upper 16 bit
-      // port_id to be zero (we'll be rejected if we
-      // use our prior port_id if we've been plugged into
-      // a different switch port).
-      // Trick Tachyon to send to ALPA 0 (see TL/TS UG, pg 87)
-      // If our ALPA is 55h for instance, we want the FC frame
-      // s_id to be 0x000055, while Tach's my_al_pa register
-      // must be 0x000155, to force an OPN at ALPA 0 
-      // (the Fabric port)
-      fcChip->Registers.my_al_pa &= 0xFF; // only use ALPA for FLOGI
-      writel( fcChip->Registers.my_al_pa | 0x0100,  
-        fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID);
-    }
+		int LastPort = 0;
+		i = 0;
+		while (!LastPort) {
+			// port IDs From NSR payload; byte swap needed?
+			BigEndianSwap((u8 *) FabricPortIds, (u8 *) & PortIds[i], 4);
+
+//			printk("FPortId[%d] %Xh ", i, PortIds[i]);
+			if (PortIds[i] & 0x80000000)
+				LastPort = 1;
+
+			PortIds[i] &= 0xFFFFFF;	// get 24-bit port_id
+			// some non-Fabric devices (like the Crossroads Fibre/Scsi bridge)
+			// erroneously use ALPA 0.
+			if (PortIds[i])	// need non-zero port_id...
+				i++;
+
+			if (i >= number_of_al_pa)	// (in)sanity check
+				break;
+			FabricPortIds++;	// next...
+		}
 
-    else // not FLOGI...
-    {
-      // should we send PLOGI or PDISC?  Check if any prior port_id
-      // (e.g. alpa) completed a PLOGI/PRLI exchange by checking 
-      // the pdisc flag.
-
-      pLoggedInPort = fcFindLoggedInPort( 
-             fcChip, 
-             NULL,           // don't search SCSI Nexus
-             fchs.s_id,      // search linked list for al_pa
-             NULL,           // don't search WWN
-             NULL);          // (don't care about end of list)
-
-             
-
-      if( pLoggedInPort )      // If found, we have prior experience with
-                             // this port -- check whether PDISC is needed
-      {
-        if( pLoggedInPort->pdisc )
+		NumberOfPorts = i;
+//    printk("NumberOf Fabric ports %d", NumberOfPorts);
+	}
+	else			// need to send logins on our "local" link
 	{
-          loginType = ELS_PDISC;  // prior PLOGI and PRLI maybe still valid
-           
+		// are we a loop port?  If so, check for reception of LILP frame,
+		// and if received use it (SANMark requirement)
+		if (fcChip->Options.LILPin) {
+			int j = 0;
+			// sanity check on number of ALPAs from LILP frame...
+			// For format of LILP frame, see FC-AL specs or 
+			// "Fibre Channel Bench Reference", J. Stai, 1995 (ISBN 1-879936-17-8)
+			// First byte is number of ALPAs
+			i = fcChip->LILPmap[0] >= (32 * 4) ? 32 * 4 : fcChip->LILPmap[0];
+			NumberOfPorts = i;
+//			printk(" LILP alpa count %d ", i);
+			while (i > 0) {
+				PortIds[j] = fcChip->LILPmap[1 + j];
+				j++;
+				i--;
+			}
+		}
+		else		// have to send login to everybody
+		{
+			int j = 0;
+			i = number_of_al_pa;
+			NumberOfPorts = i;
+			while (i > 0) {
+				PortIds[j] = valid_al_pa[j];	// all legal ALPAs
+				j++;
+				i--;
+			}
+		}
 	}
-        else
-          loginType = ELS_PLOGI;  // prior knowledge, but can't use PDISC
-      }
-      else                      // never talked to this port_id before
-        loginType = ELS_PLOGI;  // prior knowledge, but can't use PDISC
-    }
-
-
-    
-    ulStatus = cpqfcTSBuildExchange(
-          cpqfcHBAdata,
-          loginType,            // e.g. PLOGI
-          &fchs,        // no incoming frame (we are originator)
-          NULL,         // no data (no scatter/gather list)
-          &ExchangeID );// fcController->fcExchanges index, -1 if failed
 
-    if( !ulStatus ) // Exchange setup OK?
-    {
-      ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, ExchangeID );
-      if( !ulStatus )
-      {
-          // submitted to Tach's Outbound Que (ERQ PI incremented)
-          // waited for completion for ELS type (Login frames issued
-          // synchronously)
+	// Now we have a copy of the port_ids (and how many)...
+	for (i = 0; i < NumberOfPorts; i++) {
+		// 24-bit FC Port ID
+		fchs.s_id = PortIds[i];	// note: only 8-bits used for ALPA
+		// don't log into ourselves (Linux Scsi disk scan will stop on
+		// no TARGET support error on us, and quit trying for rest of devices)
+		if ((fchs.s_id & 0xFF) == (fcChip->Registers.my_al_pa & 0xFF))
+			continue;
+		// fabric login needed?
+		if ((fchs.s_id == 0) || (fcChip->Options.fabric == 1)) {
+			fcChip->Options.flogi = 1;	// fabric needs longer for login
+			// Do we need FLOGI or FDISC?
+			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search SCSI Nexus
+							   0xFFFFFC,	// search linked list for Fabric port_id
+							   NULL,	// don't search WWN
+							   NULL);	// (don't care about end of list)
+
+			if (pLoggedInPort)	// If found, we have prior experience with
+				// this port -- check whether PDISC is needed
+			{
+				if (pLoggedInPort->flogi) {
+					// does the switch support FDISC?? (FLOGI for now...)
+					loginType = ELS_FLOGI;	// prior FLOGI still valid
+				} else
+					loginType = ELS_FLOGI;	// expired FLOGI
+			} else	// first FLOGI?
+				loginType = ELS_FLOGI;
+
+			fchs.s_id = 0xFFFFFE;	// well known F_Port address
+
+			// Fabrics are not required to support FDISC, and
+			// it's not clear if that helps us anyway, since
+			// we'll want a Name Service Request to re-verify
+			// visible devices...
+			// Consequently, we always want our upper 16 bit
+			// port_id to be zero (we'll be rejected if we
+			// use our prior port_id if we've been plugged into
+			// a different switch port).
+			// Trick Tachyon to send to ALPA 0 (see TL/TS UG, pg 87)
+			// If our ALPA is 55h for instance, we want the FC frame
+			// s_id to be 0x000055, while Tach's my_al_pa register
+			// must be 0x000155, to force an OPN at ALPA 0 
+			// (the Fabric port)
+			fcChip->Registers.my_al_pa &= 0xFF;	// only use ALPA for FLOGI
+			writel(fcChip->Registers.my_al_pa | 0x0100, fcChip->Registers.ReMapMemBase + TL_MEM_TACH_My_ID);
+		}
+		else		// not FLOGI...
+		{
+			// should we send PLOGI or PDISC?  Check if any prior port_id
+			// (e.g. alpa) completed a PLOGI/PRLI exchange by checking 
+			// the pdisc flag.
+
+			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// don't search SCSI Nexus
+							   fchs.s_id,	// search linked list for al_pa
+							   NULL,	// don't search WWN
+							   NULL);	// (don't care about end of list)
+
+			if (pLoggedInPort)	// If found, we have prior experience with
+				// this port -- check whether PDISC is needed
+			{
+				if (pLoggedInPort->pdisc) {
+					loginType = ELS_PDISC;	// prior PLOGI and PRLI maybe still valid
+				} else
+					loginType = ELS_PLOGI;	// prior knowledge, but can't use PDISC
+			} else	// never talked to this port_id before
+				loginType = ELS_PLOGI;	// prior knowledge, but can't use PDISC
+		}
 
-	if( loginType == ELS_PDISC )
-	{
-	  // now, we really shouldn't Revalidate SEST exchanges until
-	  // we get an ACC reply from our target and verify that
-	  // the target address/WWN is unchanged.  However, when a fast
-	  // target gets the PDISC, they can send SEST Exchange data
-	  // before we even get around to processing the PDISC ACC.
-	  // Consequently, we lose the I/O.
-	  // To avoid this, go ahead and Revalidate when the PDISC goes
-	  // out, anticipating that the ACC will be truly acceptable
-	  // (this happens 99.9999....% of the time).
-	  // If we revalidate a SEST write, and write data goes to a
-	  // target that is NOT the one we originated the WRITE to,
-	  // that target is required (FCP-SCSI specs, etc) to discard 
-	  // our WRITE data.
-
-          // Re-validate SEST entries (Tachyon hardware assists)
-          RevalidateSEST( cpqfcHBAdata->HostAdapter, pLoggedInPort); 
-    //TriggerHBA( fcChip->Registers.ReMapMemBase, 1);
-	}
-      }
-      else  // give up immediately on error
-      {
+		ulStatus = cpqfcTSBuildExchange(dev, loginType,	// e.g. PLOGI
+						&fchs,	// no incoming frame (we are originator)
+						NULL,	// no data (no scatter/gather list)
+						&ExchangeID);	// fcController->fcExchanges index, -1 if failed
+
+		if (!ulStatus)	// Exchange setup OK?
+		{
+			ulStatus = cpqfcTSStartExchange(dev, ExchangeID);
+			if (!ulStatus) {
+				// submitted to Tach's Outbound Que (ERQ PI incremented)
+				// waited for completion for ELS type (Login frames issued
+				// synchronously)
+
+				if (loginType == ELS_PDISC) {
+					// now, we really shouldn't Revalidate SEST exchanges until
+					// we get an ACC reply from our target and verify that
+					// the target address/WWN is unchanged.  However, when a fast
+					// target gets the PDISC, they can send SEST Exchange data
+					// before we even get around to processing the PDISC ACC.
+					// Consequently, we lose the I/O.
+					// To avoid this, go ahead and Revalidate when the PDISC goes
+					// out, anticipating that the ACC will be truly acceptable
+					// (this happens 99.9999....% of the time).
+					// If we revalidate a SEST write, and write data goes to a
+					// target that is NOT the one we originated the WRITE to,
+					// that target is required (FCP-SCSI specs, etc) to discard 
+					// our WRITE data.
+
+					// Re-validate SEST entries (Tachyon hardware assists)
+					RevalidateSEST(dev->HostAdapter, pLoggedInPort);
+					//TriggerHBA( fcChip->Registers.ReMapMemBase, 1);
+				}
+			} else	// give up immediately on error
+			{
 #ifdef LOGIN_DBG
-        printk("SendLogins: fcStartExchange failed: %Xh\n", ulStatus );
+				printk("SendLogins: fcStartExchange failed: %Xh\n", ulStatus);
 #endif
-        break;
-      }
+				break;
+			}
+
 
-              
-      if( fcChip->Registers.FMstatus.value & 0x080 ) // LDn during Port Disc.
-      {
-        ulStatus = LNKDWN_OSLS;
+			if (fcChip->Registers.FMstatus.value & 0x080)	// LDn during Port Disc.
+			{
+				ulStatus = LNKDWN_OSLS;
 #ifdef LOGIN_DBG
-        printk("SendLogins: PortDisc aborted (LDn) @alpa %Xh\n", fchs.s_id);
+				printk("SendLogins: PortDisc aborted (LDn) @alpa %Xh\n", fchs.s_id);
 #endif
-        break;
-      }
-        // Check the exchange for bad status (i.e. FrameTimeOut),
-        // and complete on bad status (most likely due to BAD_ALPA)
-        // on LDn, DPC function may already complete (ABORT) a started
-        // exchange, so check type first (type = 0 on complete).
-      if( Exchanges->fcExchange[ExchangeID].status )
-      {
-#ifdef LOGIN_DBG 
- 	printk("completing x_ID %X on status %Xh\n", 
-          ExchangeID, Exchanges->fcExchange[ExchangeID].status);
+				break;
+			}
+			// Check the exchange for bad status (i.e. FrameTimeOut),
+			// and complete on bad status (most likely due to BAD_ALPA)
+			// on LDn, DPC function may already complete (ABORT) a started
+			// exchange, so check type first (type = 0 on complete).
+			if (Exchanges->fcExchange[ExchangeID].status) {
+#ifdef LOGIN_DBG
+				printk("completing x_ID %X on status %Xh\n", ExchangeID, Exchanges->fcExchange[ExchangeID].status);
 #endif
-        cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID);
-      }
-    }
-    else   // Xchange setup failed...
-    {
+				cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
+			}
+		} else		// Xchange setup failed...
+		{
 #ifdef LOGIN_DBG
-      printk("FC: cpqfcTSBuildExchange failed: %Xh\n", ulStatus );
+			printk("FC: cpqfcTSBuildExchange failed: %Xh\n", ulStatus);
 #endif
-      break;
-    }
-  }
-  if( !ulStatus )
-  {
-    // set the event signifying that all ALPAs were sent out.
+			break;
+		}
+	}
+	if (!ulStatus) {
+		// set the event signifying that all ALPAs were sent out.
 #ifdef LOGIN_DBG
-    printk("SendLogins: PortDiscDone\n");
+		printk("SendLogins: PortDiscDone\n");
 #endif
-    cpqfcHBAdata->PortDiscDone = 1;
-
-
-    // TL/TS UG, pg. 184
-    // 0x0065 = 100ms for RT_TOV
-    // 0x01f5 = 500ms for ED_TOV
-    fcChip->Registers.ed_tov.value = 0x006501f5L; 
-    writel( fcChip->Registers.ed_tov.value,
-      (fcChip->Registers.ed_tov.address));
-
-    // set the LP_TOV back to ED_TOV (i.e. 500 ms)
-    writel( 0x00000010, fcChip->Registers.ReMapMemBase +TL_MEM_FM_TIMEOUT2);
-  }
-  else
-  {
-    printk("SendLogins: failed at xchng %Xh, alpa %Xh, status %Xh\n", 
-      ExchangeID, fchs.s_id, ulStatus);
-  }
-  LEAVE("SendLogins");
+		dev->PortDiscDone = 1;
+		// TL/TS UG, pg. 184
+		// 0x0065 = 100ms for RT_TOV
+		// 0x01f5 = 500ms for ED_TOV
+		fcChip->Registers.ed_tov.value = 0x006501f5L;
+		writel(fcChip->Registers.ed_tov.value, (fcChip->Registers.ed_tov.address));
+
+		// set the LP_TOV back to ED_TOV (i.e. 500 ms)
+		writel(0x00000010, fcChip->Registers.ReMapMemBase + TL_MEM_FM_TIMEOUT2);
+	} else {
+		printk("SendLogins: failed at xchng %Xh, alpa %Xh, status %Xh\n", ExchangeID, fchs.s_id, ulStatus);
+	}
+	LEAVE("SendLogins");
 
 }
 
-
 // for REPORT_LUNS documentation, see "In-Depth Exploration of Scsi",
 // D. Deming, 1994, pg 7-19 (ISBN 1-879936-08-9)
-static void ScsiReportLunsDone(Scsi_Cmnd *Cmnd)
+static void ScsiReportLunsDone(Scsi_Cmnd * Cmnd)
 {
-  struct Scsi_Host *HostAdapter = Cmnd->host;
-  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  PFC_LOGGEDIN_PORT pLoggedInPort; 
-  int LunListLen=0;
-  int i;
-  ULONG x_ID = 0xFFFFFFFF;
-  UCHAR *ucBuff = Cmnd->request_buffer;
-
-//  printk("cpqfcTS: ReportLunsDone \n");
-  // first, we need to find the Exchange for this command,
-  // so we can find the fcPort struct to make the indicated
-  // changes.
-  for( i=0; i< TACH_SEST_LEN; i++)
-  {
-    if( Exchanges->fcExchange[i].type   // exchange defined?
-                   &&
-       (Exchanges->fcExchange[i].Cmnd == Cmnd) ) // matches?
-	      
-    {
-      x_ID = i;  // found exchange!
-      break;
-    }
-  }
-  if( x_ID == 0xFFFFFFFF)
-  {
-//    printk("cpqfcTS: ReportLuns failed - no FC Exchange\n");
-    goto Done;  // Report Luns FC Exchange gone; 
-                // exchange probably Terminated by Implicit logout
-  }
+	struct Scsi_Host *shpnt = Cmnd->host;
+	CPQFCHBA *dev = (CPQFCHBA *) shpnt->hostdata;
+	PTACHYON fcChip = &dev->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	PFC_LOGGEDIN_PORT pLoggedInPort;
+	int LunListLen = 0;
+	int i;
+	u32 x_ID = 0xFFFFFFFF;
+	u8 *ucBuff = Cmnd->request_buffer;
+
+	//  printk("cpqfcTS: ReportLunsDone \n");
+	// first, we need to find the Exchange for this command,
+	// so we can find the fcPort struct to make the indicated
+	// changes.
+	for (i = 0; i < TACH_SEST_LEN; i++) {
+		if (Exchanges->fcExchange[i].type	// exchange defined?
+		    && (Exchanges->fcExchange[i].Cmnd == Cmnd))	// matches?
+
+		{
+			x_ID = i;	// found exchange!
+			break;
+		}
+	}
+	if (x_ID == 0xFFFFFFFF) {
+//		printk("cpqfcTS: ReportLuns failed - no FC Exchange\n");
+		goto Done;	// Report Luns FC Exchange gone; 
+		// exchange probably Terminated by Implicit logout
+	}
 
+	// search linked list for the port_id we sent INQUIRY to
+	pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// DON'T search Scsi Nexus (we will set it)
+					   Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF, NULL,	// DON'T search linked list for FC WWN
+					   NULL);	// DON'T care about end of list
+
+	if (!pLoggedInPort) {
+//		printk("cpqfcTS: ReportLuns failed - device gone\n");
+		goto Done;	// error! can't find logged in Port
+	}
+	LunListLen = ucBuff[3];
+	LunListLen += ucBuff[2] >> 8;
 
-  // search linked list for the port_id we sent INQUIRY to
-  pLoggedInPort = fcFindLoggedInPort( fcChip,
-    NULL,     // DON'T search Scsi Nexus (we will set it)
-    Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF,        
-    NULL,     // DON'T search linked list for FC WWN
-    NULL);    // DON'T care about end of list
- 
-  if( !pLoggedInPort )
-  {
-//    printk("cpqfcTS: ReportLuns failed - device gone\n");
-    goto Done; // error! can't find logged in Port
-  }    
-  LunListLen = ucBuff[3];
-  LunListLen += ucBuff[2]>>8;
+	if (!LunListLen)	// failed
+	{
+		// generically speaking, a soft error means we should retry...
+		if ((Cmnd->result >> 16) == DID_SOFT_ERROR) {
+			if (((Cmnd->sense_buffer[2] & 0xF) == 0x6) && (Cmnd->sense_buffer[12] == 0x29))	// Sense Code "reset"
+			{
+				TachFCHDR_GCMND *fchs = &Exchanges->fcExchange[x_ID].fchs;
+				// did we fail because of "check condition, device reset?"
+				// e.g. the device was reset (i.e., at every power up)
+				// retry the Report Luns
+
+				// who are we sending it to?
+				// we know this because we have a copy of the command
+				// frame from the original Report Lun command -
+				// switch the d_id/s_id fields, because the Exchange Build
+				// context is "reply to source".
 
-  if( !LunListLen )  // failed
-  {
-    // generically speaking, a soft error means we should retry...
-    if( (Cmnd->result >> 16) == DID_SOFT_ERROR )
-    {
-      if( ((Cmnd->sense_buffer[2] & 0xF) == 0x6) &&
-	        (Cmnd->sense_buffer[12] == 0x29) ) // Sense Code "reset"
-      {
-        TachFCHDR_GCMND *fchs = &Exchanges->fcExchange[ x_ID].fchs;
-      // did we fail because of "check condition, device reset?"
-      // e.g. the device was reset (i.e., at every power up)
-      // retry the Report Luns
-      
-      // who are we sending it to?
-      // we know this because we have a copy of the command
-      // frame from the original Report Lun command -
-      // switch the d_id/s_id fields, because the Exchange Build
-      // context is "reply to source".
-      
-        fchs->s_id = fchs->d_id; // (temporarily re-use the struct)
-        cpqfcTSPutLinkQue( cpqfcHBAdata, SCSI_REPORT_LUNS, fchs );
-      }
-    }
-    else  // probably, the device doesn't support Report Luns
-      pLoggedInPort->ScsiNexus.VolumeSetAddressing = 0;  
-  }
-  else  // we have LUN info - check VSA mode
-  {
-    // for now, assume all LUNs will have same addr mode
-    // for VSA, payload byte 8 will be 0x40; otherwise, 0
-    pLoggedInPort->ScsiNexus.VolumeSetAddressing = ucBuff[8];  
-      
-    // Since we got a Report Luns answer, set lun masking flag
-    pLoggedInPort->ScsiNexus.LunMasking = 1;
+				fchs->s_id = fchs->d_id;	// (temporarily re-use the struct)
+				cpqfcTSPutLinkQue(dev, SCSI_REPORT_LUNS, fchs);
+			}
+		} else		// probably, the device doesn't support Report Luns
+			pLoggedInPort->ScsiNexus.VolumeSetAddressing = 0;
+	} else			// we have LUN info - check VSA mode
+	{
+		// for now, assume all LUNs will have same addr mode
+		// for VSA, payload byte 8 will be 0x40; otherwise, 0
+		pLoggedInPort->ScsiNexus.VolumeSetAddressing = ucBuff[8];
 
-    if( LunListLen > 8*CPQFCTS_MAX_LUN)   // We expect CPQFCTS_MAX_LUN max
-      LunListLen = 8*CPQFCTS_MAX_LUN;
+		// Since we got a Report Luns answer, set lun masking flag
+		pLoggedInPort->ScsiNexus.LunMasking = 1;
+
+		if (LunListLen > 8 * CPQFCTS_MAX_LUN)	// We expect CPQFCTS_MAX_LUN max
+			LunListLen = 8 * CPQFCTS_MAX_LUN;
 
 /*   
-    printk("Device WWN %08X%08X Reports Luns @: ", 
-          (ULONG)(pLoggedInPort->u.liWWN &0xFFFFFFFF), 
-          (ULONG)(pLoggedInPort->u.liWWN>>32));
+		printk("Device WWN %08X%08X Reports Luns @: ", 
+			(u32)(pLoggedInPort->u.liWWN &0xFFFFFFFF), 
+			(u32)(pLoggedInPort->u.liWWN>>32));
 	    
-    for( i=8; i<LunListLen+8; i+=8)
-    {  
-      printk("%02X%02X ", ucBuff[i], ucBuff[i+1] );
-    }
-    printk("\n");
+		for( i=8; i<LunListLen+8; i+=8)
+		{  
+			printk("%02X%02X ", ucBuff[i], ucBuff[i+1] );
+		}
+		printk("\n");
 */
-    
-    // Since the device was kind enough to tell us where the
-    // LUNs are, lets ensure they are contiguous for Linux's
-    // SCSI driver scan, which expects them to start at 0.
-    // Since Linux only supports 8 LUNs, only copy the first
-    // eight from the report luns command
-
-    // e.g., the Compaq RA4x00 f/w Rev 2.54 and above may report
-    // LUNs 4001, 4004, etc., because other LUNs are masked from
-    // this HBA (owned by someone else).  We'll make those appear as
-    // LUN 0, 1... to Linux
-    {
-      int j;
-      int AppendLunList = 0;
-      // Walk through the LUN list.  The 'j' array number is
-      // Linux's lun #, while the value of .lun[j] is the target's
-      // lun #.
-      // Once we build a LUN list, it's possible for a known device 
-      // to go offline while volumes (LUNs) are added.  Later,
-      // the device will do another PLOGI ... Report Luns command,
-      // and we must not alter the existing Linux Lun map.
-      // (This will be very rare).
-      for( j=0; j < CPQFCTS_MAX_LUN; j++)
-      {
-        if( pLoggedInPort->ScsiNexus.lun[j] != 0xFF )
-	{
-	  AppendLunList = 1;
-	  break;
-	}
-      }
-      if( AppendLunList )
-      {
-	int k;
-        int FreeLunIndex;
-//        printk("cpqfcTS: AppendLunList\n");
-
-	// If we get a new Report Luns, we cannot change
-	// any existing LUN mapping! (Only additive entry)
-	// For all LUNs in ReportLun list
-	// if RL lun != ScsiNexus lun
-	//   if RL lun present in ScsiNexus lun[], continue
-	//   else find ScsiNexus lun[]==FF and add, continue
-	
-        for( i=8, j=0; i<LunListLen+8 && j< CPQFCTS_MAX_LUN; i+=8, j++)
-	{
-          if( pLoggedInPort->ScsiNexus.lun[j] != ucBuff[i+1] )
-	  {
-	    // something changed from the last Report Luns
-	    printk(" cpqfcTS: Report Lun change!\n");
-	    for( k=0, FreeLunIndex=CPQFCTS_MAX_LUN; 
-                 k < CPQFCTS_MAX_LUN; k++)
-            {
-	      if( pLoggedInPort->ScsiNexus.lun[k] == 0xFF)
-	      {
-		FreeLunIndex = k;
-		break;
-	      }
-              if( pLoggedInPort->ScsiNexus.lun[k] == ucBuff[i+1] )
-		break; // we already masked this lun
-	    }
-	    if( k >= CPQFCTS_MAX_LUN )
-	    {
-	      printk(" no room for new LUN %d\n", ucBuff[i+1]);
-	    }
-	    else if( k == FreeLunIndex )  // need to add LUN
-	    {
-	      pLoggedInPort->ScsiNexus.lun[k] = ucBuff[i+1];
-//	      printk("add [%d]->%02d\n", k, pLoggedInPort->ScsiNexus.lun[k]);
-	      
-	    }
-	    else
-	    {
-	      // lun already known
-	    }
-	    break;
-	  }
-	}
-	// print out the new list...
-	for( j=0; j< CPQFCTS_MAX_LUN; j++)
-	{
-	  if( pLoggedInPort->ScsiNexus.lun[j] == 0xFF)
-	    break; // done
-//	  printk("[%d]->%02d ", j, pLoggedInPort->ScsiNexus.lun[j]);
-	}
-      }
-      else
-      {
-//	  printk("Linux SCSI LUNs[] -> Device LUNs: ");
-	// first time - this is easy
-        for( i=8, j=0; i<LunListLen+8 && j< CPQFCTS_MAX_LUN; i+=8, j++)
-	{
-          pLoggedInPort->ScsiNexus.lun[j] = ucBuff[i+1];
-//	  printk("[%d]->%02d ", j, pLoggedInPort->ScsiNexus.lun[j]);
+
+		// Since the device was kind enough to tell us where the
+		// LUNs are, lets ensure they are contiguous for Linux's
+		// SCSI driver scan, which expects them to start at 0.
+		// Since Linux only supports 8 LUNs, only copy the first
+		// eight from the report luns command
+
+		// e.g., the Compaq RA4x00 f/w Rev 2.54 and above may report
+		// LUNs 4001, 4004, etc., because other LUNs are masked from
+		// this HBA (owned by someone else).  We'll make those appear as
+		// LUN 0, 1... to Linux
+		{
+			int j;
+			int AppendLunList = 0;
+			// Walk through the LUN list.  The 'j' array number is
+			// Linux's lun #, while the value of .lun[j] is the target's
+			// lun #.
+			// Once we build a LUN list, it's possible for a known device 
+			// to go offline while volumes (LUNs) are added.  Later,
+			// the device will do another PLOGI ... Report Luns command,
+			// and we must not alter the existing Linux Lun map.
+			// (This will be very rare).
+			for (j = 0; j < CPQFCTS_MAX_LUN; j++) {
+				if (pLoggedInPort->ScsiNexus.lun[j] != 0xFF) {
+					AppendLunList = 1;
+					break;
+				}
+			}
+			if (AppendLunList) {
+				int k;
+				int FreeLunIndex;
+//				printk("cpqfcTS: AppendLunList\n");
+
+				// If we get a new Report Luns, we cannot change
+				// any existing LUN mapping! (Only additive entry)
+				// For all LUNs in ReportLun list
+				// if RL lun != ScsiNexus lun
+				//   if RL lun present in ScsiNexus lun[], continue
+				//   else find ScsiNexus lun[]==FF and add, continue
+
+				for (i = 8, j = 0; i < LunListLen + 8 && j < CPQFCTS_MAX_LUN; i += 8, j++) {
+					if (pLoggedInPort->ScsiNexus.lun[j] != ucBuff[i + 1]) {
+						// something changed from the last Report Luns
+						printk(" cpqfcTS: Report Lun change!\n");
+						for (k = 0, FreeLunIndex = CPQFCTS_MAX_LUN; k < CPQFCTS_MAX_LUN; k++) {
+							if (pLoggedInPort->ScsiNexus.lun[k] == 0xFF) {
+								FreeLunIndex = k;
+								break;
+							}
+							if (pLoggedInPort->ScsiNexus.lun[k] == ucBuff[i + 1])
+								break;	// we already masked this lun
+						}
+						if (k >= CPQFCTS_MAX_LUN) {
+							printk(" no room for new LUN %d\n", ucBuff[i + 1]);
+						} else if (k == FreeLunIndex)	// need to add LUN
+						{
+							pLoggedInPort->ScsiNexus.lun[k] = ucBuff[i + 1];
+//							printk("add [%d]->%02d\n", k, pLoggedInPort->ScsiNexus.lun[k]);
+
+						} else {
+							// lun already known
+						}
+						break;
+					}
+				}
+				// print out the new list...
+				for (j = 0; j < CPQFCTS_MAX_LUN; j++) {
+					if (pLoggedInPort->ScsiNexus.lun[j] == 0xFF)
+						break;	// done
+//					printk("[%d]->%02d ", j, pLoggedInPort->ScsiNexus.lun[j]);
+				}
+			} else {
+//				printk("Linux SCSI LUNs[] -> Device LUNs: ");
+				// first time - this is easy
+				for (i = 8, j = 0; i < LunListLen + 8 && j < CPQFCTS_MAX_LUN; i += 8, j++) {
+					pLoggedInPort->ScsiNexus.lun[j] = ucBuff[i + 1];
+//					printk("[%d]->%02d ", j, pLoggedInPort->ScsiNexus.lun[j]);
+				}
+//				printk("\n");
+			}
+		}
 	}
-//	printk("\n");
-      }
-    }
-  }
 
-Done:  ;
+      Done:;
 }
 
-static void 
-call_scsi_done(Scsi_Cmnd *Cmnd)
+static void call_scsi_done(Scsi_Cmnd * Cmnd)
 {
 	// We have to reinitialize sent_command here, so the scsi-mid
 	// layer won't re-use the scsi command leaving it set incorrectly.
 	// (incorrectly for our purposes...it's normally unused.)
 
-        if (Cmnd->SCp.sent_command != 0) {	// was it a passthru?
+	if (Cmnd->SCp.sent_command != 0) {	// was it a passthru?
 		Cmnd->SCp.sent_command = 0;
 		Cmnd->result &= 0xff00ffff;
-		Cmnd->result |= (DID_PASSTHROUGH << 16);  // prevents retry
+		Cmnd->result |= (DID_PASSTHROUGH << 16);	// prevents retry
 	}
 	if (Cmnd->scsi_done != NULL)
-		(*Cmnd->scsi_done)(Cmnd);
+		(*Cmnd->scsi_done) (Cmnd);
 }
 
 // After successfully getting a "Process Login" (PRLI) from an
@@ -2939,361 +2306,301 @@
 // driver model, which expects a contiguous LUNs starting at 0,
 // will use the ReportLuns info to map from "device" to "Linux" 
 // LUNs.
-static void IssueReportLunsCommand( 
-              CPQFCHBA* cpqfcHBAdata, 
-	      TachFCHDR_GCMND* fchs)
-{
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  PFC_LOGGEDIN_PORT pLoggedInPort; 
-  Scsi_Cmnd *Cmnd;
-  LONG x_ID;
-  ULONG ulStatus;
-  UCHAR *ucBuff;
-
-  if( !cpqfcHBAdata->PortDiscDone) // cleared by LDn
-  {
-    printk("Discard Q'd ReportLun command\n");
-    goto Done;
-  }
-
-  // find the device (from port_id) we're talking to
-  pLoggedInPort = fcFindLoggedInPort( fcChip,
-        NULL,     // DON'T search Scsi Nexus 
-  	fchs->s_id & 0xFFFFFF,        
-	NULL,     // DON'T search linked list for FC WWN
-        NULL);    // DON'T care about end of list
-  if( pLoggedInPort ) // we'd BETTER find it!
-  {
-
-
-    if( !(pLoggedInPort->fcp_info & TARGET_FUNCTION) )
-      goto Done;  // forget it - FC device not a "target"
-
-    // now use the port's Scsi Command buffer for the 
-    // Report Luns Command
- 
-    Cmnd = &pLoggedInPort->ScsiCmnd; 
-    ucBuff = pLoggedInPort->ReportLunsPayload;
-    
-    memset( Cmnd, 0, sizeof(Scsi_Cmnd));
-    memset( ucBuff, 0, REPORT_LUNS_PL);
-    
-    Cmnd->scsi_done = ScsiReportLunsDone;
-    Cmnd->host = cpqfcHBAdata->HostAdapter;
-
-    Cmnd->request_buffer = pLoggedInPort->ReportLunsPayload; 
-    Cmnd->request_bufflen = REPORT_LUNS_PL; 
-	    
-    Cmnd->cmnd[0] = 0xA0;
-    Cmnd->cmnd[8] = REPORT_LUNS_PL >> 8;
-    Cmnd->cmnd[9] = (UCHAR)REPORT_LUNS_PL;
-    Cmnd->cmd_len = 12;
-
-    Cmnd->channel = pLoggedInPort->ScsiNexus.channel;
-    Cmnd->target = pLoggedInPort->ScsiNexus.target;
+static void IssueReportLunsCommand(CPQFCHBA * dev, TachFCHDR_GCMND * fchs)
+{
+	PTACHYON fcChip = &dev->fcChip;
+	PFC_LOGGEDIN_PORT pLoggedInPort;
+	Scsi_Cmnd *Cmnd;
+	s32 x_ID;
+	u32 ulStatus;
+	u8 *ucBuff;
 
-	    
-    ulStatus = cpqfcTSBuildExchange(
-      cpqfcHBAdata,
-      SCSI_IRE, 
-      fchs,
-      Cmnd,         // buffer for Report Lun data
-      &x_ID );// fcController->fcExchanges index, -1 if failed
+	if (!dev->PortDiscDone)	// cleared by LDn
+	{
+		printk("Discard Q'd ReportLun command\n");
+		goto Done;
+	}
+	// find the device (from port_id) we're talking to
+	pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// DON'T search Scsi Nexus 
+					   fchs->s_id & 0xFFFFFF, NULL,	// DON'T search linked list for FC WWN
+					   NULL);	// DON'T care about end of list
+	if (pLoggedInPort)	// we'd BETTER find it!
+	{
 
-    if( !ulStatus ) // Exchange setup?
-    {
-      ulStatus = cpqfcTSStartExchange( cpqfcHBAdata, x_ID );
-      if( !ulStatus )
-      {
-        // 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
-      {
-  
-      }
-    }
 
-    else   // Xchange setup failed...
-      printk(" cpqfcTSBuildExchange failed: %Xh\n", ulStatus );
-  }
-  else     // like, we just got a PRLI ACC, and now the port is gone?
-  {
-    printk(" can't send ReportLuns - no login for port_id %Xh\n",
-	    fchs->s_id & 0xFFFFFF);
-  }
+		if (!(pLoggedInPort->fcp_info & TARGET_FUNCTION))
+			goto Done;	// forget it - FC device not a "target"
 
+		// now use the port's Scsi Command buffer for the 
+		// Report Luns Command
 
+		Cmnd = &pLoggedInPort->ScsiCmnd;
+		ucBuff = pLoggedInPort->ReportLunsPayload;
 
-Done: ;
+		memset(Cmnd, 0, sizeof(Scsi_Cmnd));
+		memset(ucBuff, 0, REPORT_LUNS_PL);
+
+		Cmnd->scsi_done = ScsiReportLunsDone;
+		Cmnd->host = dev->HostAdapter;
+
+		Cmnd->request_buffer = pLoggedInPort->ReportLunsPayload;
+		Cmnd->request_bufflen = REPORT_LUNS_PL;
+
+		Cmnd->cmnd[0] = 0xA0;
+		Cmnd->cmnd[8] = REPORT_LUNS_PL >> 8;
+		Cmnd->cmnd[9] = (u8) REPORT_LUNS_PL;
+		Cmnd->cmd_len = 12;
+
+		Cmnd->channel = pLoggedInPort->ScsiNexus.channel;
+		Cmnd->target = pLoggedInPort->ScsiNexus.target;
+
+
+		ulStatus = cpqfcTSBuildExchange(dev, SCSI_IRE, fchs, Cmnd,	// buffer for Report Lun data
+						&x_ID);	// fcController->fcExchanges index, -1 if failed
+
+		if (!ulStatus)	// Exchange setup?
+		{
+			ulStatus = cpqfcTSStartExchange(dev, x_ID);
+			if (!ulStatus) {
+				// 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
+			{
+			}
+		}
 
+		else		// Xchange setup failed...
+			printk(" cpqfcTSBuildExchange failed: %Xh\n", ulStatus);
+	} else			// like, we just got a PRLI ACC, and now the port is gone?
+	{
+		printk(" can't send ReportLuns - no login for port_id %Xh\n", fchs->s_id & 0xFFFFFF);
+	}
+Done:;
 }
 
-
-
-
-
-
-
-static void CompleteBoardLockCmnd( CPQFCHBA *cpqfcHBAdata)
+static void CompleteBoardLockCmnd(CPQFCHBA * dev)
 {
-  int i;
-  for( i = CPQFCTS_REQ_QUEUE_LEN-1; i>= 0; i--)
-  {
-    if( cpqfcHBAdata->BoardLockCmnd[i] != NULL )
-    {
-      Scsi_Cmnd *Cmnd = cpqfcHBAdata->BoardLockCmnd[i];
-      cpqfcHBAdata->BoardLockCmnd[i] = NULL;
-      Cmnd->result = (DID_SOFT_ERROR << 16);  // ask for retry
-//      printk(" BoardLockCmnd[%d] %p Complete, chnl/target/lun %d/%d/%d\n",
-//        i,Cmnd, Cmnd->channel, Cmnd->target, Cmnd->lun);
-      call_scsi_done(Cmnd);
-    }
-  }
+	int i;
+	for (i = CPQFCTS_REQ_QUEUE_LEN - 1; i >= 0; i--) {
+		if (dev->BoardLockCmnd[i] != NULL) {
+			Scsi_Cmnd *Cmnd = dev->BoardLockCmnd[i];
+			dev->BoardLockCmnd[i] = NULL;
+			Cmnd->result = (DID_SOFT_ERROR << 16);	// ask for retry
+//			printk(" BoardLockCmnd[%d] %p Complete, chnl/target/lun %d/%d/%d\n",
+//				i,Cmnd, Cmnd->channel, Cmnd->target, Cmnd->lun);
+			call_scsi_done(Cmnd);
+		}
+	}
 }
 
+// runs every 1 second for FC exchange timeouts and implicit FC device logouts
 
+void cpqfcTSheartbeat(unsigned long ptr)
+{
+	CPQFCHBA *dev = (CPQFCHBA *) ptr;
+	PTACHYON fcChip = &dev->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts;
+	u32 i;
+	unsigned long flags;
+	DECLARE_MUTEX_LOCKED(BoardLock);
 
+	PCI_TRACE(0xA8)
 
+	if (dev->BoardLock)	// Worker Task Running?
+		goto Skip;
 
+	spin_lock_irqsave(&io_request_lock, flags);	// STOP _que function
 
-// runs every 1 second for FC exchange timeouts and implicit FC device logouts
-
-void cpqfcTSheartbeat( unsigned long ptr )
-{
-  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)ptr;
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts; 
-  ULONG i;
-  unsigned long flags;
-  DECLARE_MUTEX_LOCKED(BoardLock);
-  
-  PCI_TRACE( 0xA8)
-
-  if( cpqfcHBAdata->BoardLock) // Worker Task Running?
-    goto Skip;
-
-  spin_lock_irqsave( &io_request_lock, flags); // STOP _que function
-
-  PCI_TRACE( 0xA8)
-
-
-  cpqfcHBAdata->BoardLock = &BoardLock; // stop Linux SCSI command queuing
-  
-  // release the IO lock (and re-enable interrupts)
-  spin_unlock_irqrestore( &io_request_lock, flags);
-  
-  // Ensure no contention from  _quecommand or Worker process 
-  CPQ_SPINLOCK_HBA( cpqfcHBAdata)
-  
-  PCI_TRACE( 0xA8)
-  
-
-  disable_irq( cpqfcHBAdata->HostAdapter->irq);  // our IRQ
-
-  // Complete the "bad target" commands (normally only used during
-  // initialization, since we aren't supposed to call "scsi_done"
-  // inside the queuecommand() function).  (this is overly contorted,
-  // scsi_done can be safely called from queuecommand for
-  // this bad target case.  May want to simplify this later)
+	PCI_TRACE(0xA8)
 
-  for( i=0; i< CPQFCTS_MAX_TARGET_ID; i++)
-  {
-    if( cpqfcHBAdata->BadTargetCmnd[i] )
-    {
-      Scsi_Cmnd *Cmnd = cpqfcHBAdata->BadTargetCmnd[i];
-      cpqfcHBAdata->BadTargetCmnd[i] = NULL;
-      Cmnd->result = (DID_BAD_TARGET << 16);
-      call_scsi_done(Cmnd);
-    }
-    else
-      break;
-  }
+	dev->BoardLock = &BoardLock;	// stop Linux SCSI command queuing
 
-  
-  // logged in ports -- re-login check (ports required to verify login with
-  // PDISC after LIP within 2 secs)
-
-  // prevent contention
-  while( pLoggedInPort ) // for all ports which are expecting
-                         // PDISC after the next LIP, check to see if
-                         // time is up!
-  {
-      // Important: we only detect "timeout" condition on TRANSITION
-      // from non-zero to zero
-    if( pLoggedInPort->LOGO_timer )  // time-out "armed"?
-    {
-      if( !(--pLoggedInPort->LOGO_timer) ) // DEC from 1 to 0?
-      {
-          // LOGOUT time!  Per PLDA, PDISC hasn't complete in 2 secs, so
-          // issue LOGO request and destroy all I/O with other FC port(s).
-        
-/*          
-        printk(" ~cpqfcTS heartbeat: LOGOut!~ ");
-        printk("Linux SCSI Chanl/Target %d/%d (port_id %06Xh) WWN %08X%08X\n", 
-        pLoggedInPort->ScsiNexus.channel, 
-        pLoggedInPort->ScsiNexus.target, 
-	pLoggedInPort->port_id,
-          (ULONG)(pLoggedInPort->u.liWWN &0xFFFFFFFF), 
-          (ULONG)(pLoggedInPort->u.liWWN>>32));
+	// release the IO lock (and re-enable interrupts)
+	spin_unlock_irqrestore(&io_request_lock, flags);
 
-*/
-        cpqfcTSImplicitLogout( cpqfcHBAdata, pLoggedInPort);
+	// Ensure no contention from  _quecommand or Worker process 
+	CPQ_SPINLOCK_HBA(dev)
 
-      }
-      // else simply decremented - maybe next time...
-    }
-    pLoggedInPort = pLoggedInPort->pNextPort;
-  }
+	PCI_TRACE(0xA8)
 
+	disable_irq(dev->HostAdapter->irq);	// our IRQ
 
+	// Complete the "bad target" commands (normally only used during
+	// initialization, since we aren't supposed to call "scsi_done"
+	// inside the queuecommand() function).  (this is overly contorted,
+	// scsi_done can be safely called from queuecommand for
+	// this bad target case.  May want to simplify this later)
 
-  
-  
-  // ************  FC EXCHANGE TIMEOUT CHECK **************
-  
-  for( i=0; i< TACH_MAX_XID; i++)
-  {
-    if( Exchanges->fcExchange[i].type )  // exchange defined?
-    {
+	for (i = 0; i < CPQFCTS_MAX_TARGET_ID; i++) {
+		if (dev->BadTargetCmnd[i]) {
+			Scsi_Cmnd *Cmnd = dev->BadTargetCmnd[i];
+			dev->BadTargetCmnd[i] = NULL;
+			Cmnd->result = (DID_BAD_TARGET << 16);
+			call_scsi_done(Cmnd);
+		} else
+			break;
+	}
 
-      if( !Exchanges->fcExchange[i].timeOut ) // time expired
-      {
-        // Set Exchange timeout status
-        Exchanges->fcExchange[i].status |= FC2_TIMEOUT;
-
-        if( i >= TACH_SEST_LEN ) // Link Service Exchange
-        {
-          cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, i);  // Don't "abort" LinkService
-        }
-        
-        else  // SEST Exchange TO -- may post ABTS to Worker Thread Que
-        {
-	  // (Make sure we don't keep timing it out; let other functions
-	  // complete it or set the timeOut as needed)
-	  Exchanges->fcExchange[i].timeOut = 30000; // seconds default
-
-          if( Exchanges->fcExchange[i].type 
-                  & 
-              (BLS_ABTS | BLS_ABTS_ACC )  )
-          {
-	    // For BLS_ABTS*, an upper level might still have
-	    // an outstanding command waiting for low-level completion.
-	    // Also, in the case of a WRITE, we MUST get confirmation
-	    // of either ABTS ACC or RJT before re-using the Exchange.
-	    // It's possible that the RAID cache algorithm can hang
-	    // if we fail to complete a WRITE to a LBA, when a READ
-	    // comes later to that same LBA.  Therefore, we must
-	    // ensure that the target verifies receipt of ABTS for
-	    // the exchange
-	   
-	    printk("~TO Q'd ABTS (x_ID %Xh)~ ", i); 
-//            TriggerHBA( fcChip->Registers.ReMapMemBase);
-
-	    // On timeout of a ABTS exchange, check to
-	    // see if the FC device has a current valid login.
-	    // If so, restart it.
-	    pLoggedInPort = fcFindLoggedInPort( fcChip,
-              Exchanges->fcExchange[i].Cmnd, // find 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
-
-	    // device exists?
-	    if( pLoggedInPort ) // device exists?
-	    {
-	      if( pLoggedInPort->prli ) // logged in for FCP-SCSI?
-	      {
-		// attempt to restart the ABTS
-		printk(" ~restarting ABTS~ ");
-                cpqfcTSStartExchange( cpqfcHBAdata, i );
-
-	      }
-	    }
-          }
-	  else  // not an ABTS
-	  { 
-           
-            // We expect the WorkerThread to change the xchng type to
-            // abort and set appropriate timeout.
-            cpqfcTSPutLinkQue( cpqfcHBAdata, BLS_ABTS, &i ); // timed-out
-	  }
-        }
-      }
-      else  // time not expired...
-      {
-        // decrement timeout: 1 or more seconds left
-        --Exchanges->fcExchange[i].timeOut;
-      }
-    }
-  }
 
+	// logged in ports -- re-login check (ports required to verify login with
+	// PDISC after LIP within 2 secs)
 
-  enable_irq( cpqfcHBAdata->HostAdapter->irq);
- 
+	// prevent contention
+	while (pLoggedInPort)	// for all ports which are expecting
+				// PDISC after the next LIP, check to see if
+				// time is up!
+	{
+		// Important: we only detect "timeout" condition on TRANSITION
+		// from non-zero to zero
+		if (pLoggedInPort->LOGO_timer)	// time-out "armed"?
+		{
+			if (!(--pLoggedInPort->LOGO_timer))	// DEC from 1 to 0?
+			{
+				// LOGOUT time!  Per PLDA, PDISC hasn't complete in 2 secs, so
+				// issue LOGO request and destroy all I/O with other FC port(s).
 
-  CPQ_SPINUNLOCK_HBA( cpqfcHBAdata)
+/*          
+			        printk(" ~cpqfcTS heartbeat: LOGOut!~ ");
+        			printk("Linux SCSI Chanl/Target %d/%d (port_id %06Xh) WWN %08X%08X\n", 
+				        pLoggedInPort->ScsiNexus.channel, 
+				        pLoggedInPort->ScsiNexus.target, 
+					pLoggedInPort->port_id,
+				        (u32)(pLoggedInPort->u.liWWN &0xFFFFFFFF), 
+				        (u32)(pLoggedInPort->u.liWWN>>32));
+*/
+				cpqfcTSImplicitLogout(dev, pLoggedInPort);
 
-  cpqfcHBAdata->BoardLock = NULL; // Linux SCSI commands may be queued
+			}
+			// else simply decremented - maybe next time...
+		}
+		pLoggedInPort = pLoggedInPort->pNextPort;
+	}
 
-  // Now, complete any Cmnd we Q'd up while BoardLock was held
+	// ************  FC EXCHANGE TIMEOUT CHECK **************
 
-  CompleteBoardLockCmnd( cpqfcHBAdata);
- 
+	for (i = 0; i < TACH_MAX_XID; i++) {
+		if (Exchanges->fcExchange[i].type)	// exchange defined?
+		{
+
+			if (!Exchanges->fcExchange[i].timeOut)	// time expired
+			{
+				// Set Exchange timeout status
+				Exchanges->fcExchange[i].status |= FC2_TIMEOUT;
+
+				if (i >= TACH_SEST_LEN)	// Link Service Exchange
+				{
+					cpqfcTSCompleteExchange(dev->PciDev, fcChip, i);	// Don't "abort" LinkService
+				}
+				else	// SEST Exchange TO -- may post ABTS to Worker Thread Que
+				{
+					// (Make sure we don't keep timing it out; let other functions
+					// complete it or set the timeOut as needed)
+					Exchanges->fcExchange[i].timeOut = 30000;	// seconds default
+
+					if (Exchanges->fcExchange[i].type & (BLS_ABTS | BLS_ABTS_ACC)) {
+						// For BLS_ABTS*, an upper level might still have
+						// an outstanding command waiting for low-level completion.
+						// Also, in the case of a WRITE, we MUST get confirmation
+						// of either ABTS ACC or RJT before re-using the Exchange.
+						// It's possible that the RAID cache algorithm can hang
+						// if we fail to complete a WRITE to a LBA, when a READ
+						// comes later to that same LBA.  Therefore, we must
+						// ensure that the target verifies receipt of ABTS for
+						// the exchange
+
+						printk("~TO Q'd ABTS (x_ID %Xh)~ ", i);
+//						TriggerHBA( fcChip->Registers.ReMapMemBase);
+
+						// On timeout of a ABTS exchange, check to
+						// see if the FC device has a current valid login.
+						// If so, restart it.
+						pLoggedInPort = fcFindLoggedInPort(fcChip, Exchanges->fcExchange[i].Cmnd,	// find 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
+						// device exists?
+						if (pLoggedInPort)	// device exists?
+						{
+							if (pLoggedInPort->prli)	// logged in for FCP-SCSI?
+							{
+								// attempt to restart the ABTS
+								printk(" ~restarting ABTS~ ");
+								cpqfcTSStartExchange(dev, i);
+
+							}
+						}
+					} else	// not an ABTS
+					{
+
+						// We expect the WorkerThread to change the xchng type to
+						// abort and set appropriate timeout.
+						cpqfcTSPutLinkQue(dev, BLS_ABTS, &i);	// timed-out
+					}
+				}
+			} else	// time not expired...
+			{
+				// decrement timeout: 1 or more seconds left
+				--Exchanges->fcExchange[i].timeOut;
+			}
+		}
+	}
 
-  // restart the timer to run again (1 sec later)
+	enable_irq(dev->HostAdapter->irq);
+	CPQ_SPINUNLOCK_HBA(dev)
+	dev->BoardLock = NULL;	// Linux SCSI commands may be queued
+	// Now, complete any Cmnd we Q'd up while BoardLock was held
+	CompleteBoardLockCmnd(dev);
+	// restart the timer to run again (1 sec later)
 Skip:
-  mod_timer( &cpqfcHBAdata->cpqfcTStimer, jiffies + HZ);
-  
-  PCI_TRACEO( i, 0xA8)
-  return;
+	mod_timer(&dev->cpqfcTStimer, jiffies + HZ);
+	PCI_TRACEO(i, 0xA8)
+	return;
 }
 
 
 // put valid FC-AL physical address in spec order
-static const UCHAR valid_al_pa[]={
-    0xef, 0xe8, 0xe4, 0xe2, 
-    0xe1, 0xE0, 0xDC, 0xDA, 
-    0xD9, 0xD6, 0xD5, 0xD4, 
-    0xD3, 0xD2, 0xD1, 0xCe, 
-    0xCd, 0xCc, 0xCb, 0xCa, 
-    0xC9, 0xC7, 0xC6, 0xC5, 
-    0xC3, 0xBc, 0xBa, 0xB9,
-    0xB6, 0xB5, 0xB4, 0xB3, 
-    0xB2, 0xB1, 0xae, 0xad,
-    0xAc, 0xAb, 0xAa, 0xA9, 
-
-    0xA7, 0xA6, 0xA5, 0xA3, 
-    0x9f, 0x9e, 0x9d, 0x9b, 
-    0x98, 0x97, 0x90, 0x8f, 
-    0x88, 0x84, 0x82, 0x81, 
-    0x80, 0x7c, 0x7a, 0x79, 
-    0x76, 0x75, 0x74, 0x73, 
-    0x72, 0x71, 0x6e, 0x6d, 
-    0x6c, 0x6b, 0x6a, 0x69, 
-    0x67, 0x66, 0x65, 0x63, 
-    0x5c, 0x5a, 0x59, 0x56, 
-    
-    0x55, 0x54, 0x53, 0x52, 
-    0x51, 0x4e, 0x4d, 0x4c, 
-    0x4b, 0x4a, 0x49, 0x47, 
-    0x46, 0x45, 0x43, 0x3c,
-    0x3a, 0x39, 0x36, 0x35, 
-    0x34, 0x33, 0x32, 0x31, 
-    0x2e, 0x2d, 0x2c, 0x2b, 
-    0x2a, 0x29, 0x27, 0x26, 
-    0x25, 0x23, 0x1f, 0x1E,
-    0x1d, 0x1b, 0x18, 0x17, 
-
-    0x10, 0x0f, 8, 4, 2, 1 }; // ALPA 0 (Fabric) is special case
-
-const int number_of_al_pa = (sizeof(valid_al_pa) );
+static const u8 valid_al_pa[] = {
+	0xef, 0xe8, 0xe4, 0xe2,
+	0xe1, 0xE0, 0xDC, 0xDA,
+	0xD9, 0xD6, 0xD5, 0xD4,
+	0xD3, 0xD2, 0xD1, 0xCe,
+	0xCd, 0xCc, 0xCb, 0xCa,
+	0xC9, 0xC7, 0xC6, 0xC5,
+	0xC3, 0xBc, 0xBa, 0xB9,
+	0xB6, 0xB5, 0xB4, 0xB3,
+	0xB2, 0xB1, 0xae, 0xad,
+	0xAc, 0xAb, 0xAa, 0xA9,
+
+	0xA7, 0xA6, 0xA5, 0xA3,
+	0x9f, 0x9e, 0x9d, 0x9b,
+	0x98, 0x97, 0x90, 0x8f,
+	0x88, 0x84, 0x82, 0x81,
+	0x80, 0x7c, 0x7a, 0x79,
+	0x76, 0x75, 0x74, 0x73,
+	0x72, 0x71, 0x6e, 0x6d,
+	0x6c, 0x6b, 0x6a, 0x69,
+	0x67, 0x66, 0x65, 0x63,
+	0x5c, 0x5a, 0x59, 0x56,
+
+	0x55, 0x54, 0x53, 0x52,
+	0x51, 0x4e, 0x4d, 0x4c,
+	0x4b, 0x4a, 0x49, 0x47,
+	0x46, 0x45, 0x43, 0x3c,
+	0x3a, 0x39, 0x36, 0x35,
+	0x34, 0x33, 0x32, 0x31,
+	0x2e, 0x2d, 0x2c, 0x2b,
+	0x2a, 0x29, 0x27, 0x26,
+	0x25, 0x23, 0x1f, 0x1E,
+	0x1d, 0x1b, 0x18, 0x17,
 
+	0x10, 0x0f, 8, 4, 2, 1
+};				// ALPA 0 (Fabric) is special case
 
+const int number_of_al_pa = (sizeof(valid_al_pa));
 
 // this function looks up an al_pa from the table of valid al_pa's
 // we decrement from the last decimal loop ID, because soft al_pa
@@ -3306,16 +2613,16 @@
 //  -1      - invalid al_pa (not all 8 bit values are legal)
 
 #if (0)
-static int GetLoopID( ULONG al_pa )
+static int GetLoopID(u32 al_pa)
 {
-  int i;
+	int i;
 
-  for( i = number_of_al_pa -1; i >= 0; i--)  // dec.
-  {
-    if( valid_al_pa[i] == (UCHAR)al_pa )  // take lowest 8 bits
-      return i;  // success - found valid al_pa; return decimal LoopID
-  }
-  return -1; // failed - not found
+	for (i = number_of_al_pa - 1; i >= 0; i--)	// dec.
+	{
+		if (valid_al_pa[i] == (u8) al_pa)	// take lowest 8 bits
+			return i;	// success - found valid al_pa; return decimal LoopID
+	}
+	return -1;		// failed - not found
 }
 #endif
 
@@ -3330,739 +2637,620 @@
 //     (NULL if not found)
 //   pLastLoggedInPort - ptr to last struct (for adding new ones)
 // 
-PFC_LOGGEDIN_PORT  fcFindLoggedInPort( 
-  PTACHYON fcChip, 
-  Scsi_Cmnd *Cmnd, // search linked list for Scsi Nexus (channel/target/lun)
-  ULONG port_id,   // search linked list for al_pa, or
-  UCHAR wwn[8],    // search linked list for WWN, or...
-  PFC_LOGGEDIN_PORT *pLastLoggedInPort )
-             
-{
-  PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts; 
-  BOOLEAN target_id_valid=FALSE;
-  BOOLEAN port_id_valid=FALSE;
-  BOOLEAN wwn_valid=FALSE;
-  int i;
-
-
-  if( Cmnd != NULL )
-    target_id_valid = TRUE;
-  
-  else if( port_id ) // note! 24-bit NULL address is illegal
-    port_id_valid = TRUE;
+PFC_LOGGEDIN_PORT fcFindLoggedInPort(PTACHYON fcChip, Scsi_Cmnd * Cmnd,	// search linked list for Scsi Nexus (channel/target/lun)
+				     u32 port_id,	// search linked list for al_pa, or
+				     u8 wwn[8],	// search linked list for WWN, or...
+				     PFC_LOGGEDIN_PORT * pLastLoggedInPort)
+{
+	PFC_LOGGEDIN_PORT pLoggedInPort = &fcChip->fcPorts;
+	u8 target_id_valid = 0;
+	u8 port_id_valid = 0;
+	u8 wwn_valid = 0;
+	int i;
+
+
+	if (Cmnd != NULL)
+		target_id_valid = 1;
+
+	else if (port_id)	// note! 24-bit NULL address is illegal
+		port_id_valid = 1;
+
+	else {
+		if (wwn)	// non-null arg? (OK to pass NULL when not searching WWN)
+		{
+			for (i = 0; i < 8; i++)	// valid WWN passed?  NULL WWN invalid
+			{
+				if (wwn[i] != 0)
+					wwn_valid = 1;	// any non-zero byte makes (presumably) valid
+			}
+		}
+	}
+	// check other options ...
 
-  else
-  {
-    if( wwn ) // non-null arg? (OK to pass NULL when not searching WWN)
-    {
-      for( i=0; i<8; i++)  // valid WWN passed?  NULL WWN invalid
-      {
-        if( wwn[i] != 0 )
-          wwn_valid = TRUE;  // any non-zero byte makes (presumably) valid
-      }
-    }
-  }
-                // check other options ...
 
+	// In case multiple search options are given, we use a priority
+	// scheme:
+	// While valid pLoggedIn Ptr
+	//   If port_id is valid
+	//     if port_id matches, return Ptr
+	//   If wwn is valid
+	//     if wwn matches, return Ptr
+	//   Next Ptr in list
+	//
+	// Return NULL (not found)
 
-  // In case multiple search options are given, we use a priority
-  // scheme:
-  // While valid pLoggedIn Ptr
-  //   If port_id is valid
-  //     if port_id matches, return Ptr
-  //   If wwn is valid
-  //     if wwn matches, return Ptr
-  //   Next Ptr in list
-  //
-  // Return NULL (not found)
- 
-      
-  while( pLoggedInPort ) // NULL marks end of list (1st ptr always valid)
-  {
-    if( pLastLoggedInPort ) // caller's pointer valid?
-      *pLastLoggedInPort = pLoggedInPort;  // end of linked list
-    
-    if( target_id_valid )
-    {
-      // check Linux Scsi Cmnd for channel/target Nexus match
-      // (all luns are accessed through matching "pLoggedInPort")
-      if( (pLoggedInPort->ScsiNexus.target == Cmnd->target)
-                &&
-          (pLoggedInPort->ScsiNexus.channel == Cmnd->channel))
-      {
-        // For "passthru" modes, the IOCTL caller is responsible
-	// for setting the FCP-LUN addressing
-	if( !Cmnd->SCp.sent_command ) // NOT passthru?
+
+	while (pLoggedInPort)	// NULL marks end of list (1st ptr always valid)
 	{
-	
-          // set the FCP-LUN addressing type
-          Cmnd->SCp.phase = pLoggedInPort->ScsiNexus.VolumeSetAddressing;	
-
-          // set the Device Type we got from the snooped INQUIRY string
-	  Cmnd->SCp.Message = pLoggedInPort->ScsiNexus.InqDeviceType;
-
-	  // handle LUN masking; if not "default" (illegal) lun value,
-	  // the use it.  These lun values are set by a successful
-	  // Report Luns command
-          if( pLoggedInPort->ScsiNexus.LunMasking == 1) 
-	  {
-            // we KNOW all the valid LUNs... 0xFF is invalid!
-            Cmnd->SCp.have_data_in = pLoggedInPort->ScsiNexus.lun[Cmnd->lun];
-	    if (pLoggedInPort->ScsiNexus.lun[Cmnd->lun] == 0xFF)
-		return NULL;
-	    // printk("xlating lun %d to 0x%02x\n", Cmnd->lun, 
-            //	pLoggedInPort->ScsiNexus.lun[Cmnd->lun]);
-	  }
-	  else
-	    Cmnd->SCp.have_data_in = Cmnd->lun; // Linux & target luns match
-	}
-	break; // found it!
-      }
-    }
-    
-    if( port_id_valid ) // look for alpa first
-    {
-      if( pLoggedInPort->port_id == port_id )
-          break;  // found it!
-    }
-    if( wwn_valid ) // look for wwn second
-    {
+		if (pLastLoggedInPort)	// caller's pointer valid?
+			*pLastLoggedInPort = pLoggedInPort;	// end of linked list
 
-      if( !memcmp( &pLoggedInPort->u.ucWWN[0], &wwn[0], 8))
-      {  
-                 // all 8 bytes of WWN match
-        break;   // found it!
-      }
-    }
-                
-    pLoggedInPort = pLoggedInPort->pNextPort; // try next port
-  }
+		if (target_id_valid) {
+			// check Linux Scsi Cmnd for channel/target Nexus match
+			// (all luns are accessed through matching "pLoggedInPort")
+			if ((pLoggedInPort->ScsiNexus.target == Cmnd->target)
+			    && (pLoggedInPort->ScsiNexus.channel == Cmnd->channel)) {
+				// For "passthru" modes, the IOCTL caller is responsible
+				// for setting the FCP-LUN addressing
+				if (!Cmnd->SCp.sent_command)	// NOT passthru?
+				{
+
+					// set the FCP-LUN addressing type
+					Cmnd->SCp.phase = pLoggedInPort->ScsiNexus.VolumeSetAddressing;
+
+					// set the Device Type we got from the snooped INQUIRY string
+					Cmnd->SCp.Message = pLoggedInPort->ScsiNexus.InqDeviceType;
+
+					// handle LUN masking; if not "default" (illegal) lun value,
+					// the use it.  These lun values are set by a successful
+					// Report Luns command
+					if (pLoggedInPort->ScsiNexus.LunMasking == 1) {
+						// we KNOW all the valid LUNs... 0xFF is invalid!
+						if (Cmnd->lun > sizeof(pLoggedInPort->ScsiNexus.lun)){
+							// printk("cpqfcTS FATAL: Invalid LUN index !!!!\n ");
+							return NULL;
+						}
+						Cmnd->SCp.have_data_in = pLoggedInPort->ScsiNexus.lun[Cmnd->lun];
+						if (pLoggedInPort->ScsiNexus.lun[Cmnd->lun] == 0xFF)
+							return NULL;
+						// printk("xlating lun %d to 0x%02x\n", Cmnd->lun, 
+						//  pLoggedInPort->ScsiNexus.lun[Cmnd->lun]);
+					} else
+						Cmnd->SCp.have_data_in = Cmnd->lun;	// Linux & target luns match
+				}
+				break;	// found it!
+			}
+		}
 
-  return pLoggedInPort;
-}
+		if (port_id_valid)	// look for alpa first
+		{
+			if (pLoggedInPort->port_id == port_id)
+				break;	// found it!
+		}
+		if (wwn_valid)	// look for wwn second
+		{
 
+			if (!memcmp(&pLoggedInPort->u.ucWWN[0], &wwn[0], 8)) {
+				// all 8 bytes of WWN match
+				break;	// found it!
+			}
+		}
 
+		pLoggedInPort = pLoggedInPort->pNextPort;	// try next port
+	}
 
+	return pLoggedInPort;
+}
 
 // 
 // We need to examine the SEST table and re-validate
 // any open Exchanges for this LoggedInPort
 // To make Tachyon pay attention, Freeze FCP assists,
 // set VAL bits, Unfreeze FCP assists
-static void RevalidateSEST( struct Scsi_Host *HostAdapter, 
-		        PFC_LOGGEDIN_PORT pLoggedInPort)
+static void RevalidateSEST(struct Scsi_Host *shpnt, PFC_LOGGEDIN_PORT pLoggedInPort)
 {
-  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  ULONG x_ID;
-  BOOLEAN TachFroze = FALSE;
-  
-  
-  // re-validate any SEST exchanges that are permitted
-  // to survive the link down (e.g., good PDISC performed)
-  for( x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++)
-  {
-
-    // If the SEST entry port_id matches the pLoggedInPort,
-    // we need to re-validate
-    if( (Exchanges->fcExchange[ x_ID].type == SCSI_IRE)
-         || 
-	(Exchanges->fcExchange[ x_ID].type == SCSI_IWE))
-    {
-		     
-      if( (Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF)  // (24-bit port ID)
-            == pLoggedInPort->port_id) 
-      {
-//	printk(" re-val xID %Xh ", x_ID);
-        if( !TachFroze )  // freeze if not already frozen
-          TachFroze |= FreezeTach( cpqfcHBAdata);
-        fcChip->SEST->u[ x_ID].IWE.Hdr_Len |= 0x80000000; // set VAL bit
-      }
-    } 
-  }
-
-  if( TachFroze) 
-  { 
-    fcChip->UnFreezeTachyon( fcChip, 2);  // both ERQ and FCP assists
-  }
-} 
+	CPQFCHBA *dev = (CPQFCHBA *) shpnt->hostdata;
+	PTACHYON fcChip = &dev->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	u32 x_ID;
+	u8 TachFroze = 0;
+
+
+	// re-validate any SEST exchanges that are permitted
+	// to survive the link down (e.g., good PDISC performed)
+	for (x_ID = 0; x_ID < TACH_SEST_LEN; x_ID++) {
+
+		// If the SEST entry port_id matches the pLoggedInPort,
+		// we need to re-validate
+		if ((Exchanges->fcExchange[x_ID].type == SCSI_IRE)
+		    || (Exchanges->fcExchange[x_ID].type == SCSI_IWE)) {
+			if ((Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF) == pLoggedInPort->port_id) 	// (24-bit port ID)
+			{
+//				printk(" re-val xID %Xh ", x_ID);
+				if (!TachFroze)	// freeze if not already frozen
+					TachFroze |= FreezeTach(dev);
+				fcChip->SEST->u[x_ID].IWE.Hdr_Len |= 0x80000000;	// set VAL bit
+			}
+		}
+	}
+	if (TachFroze) {
+		fcChip->UnFreezeTachyon(fcChip, 2);	// both ERQ and FCP assists
+	}
+}
 
 
 // Complete an Linux Cmnds that we Queued because
 // our FC link was down (cause immediate retry)
 
-static void UnblockScsiDevice( struct Scsi_Host *HostAdapter, 
-		        PFC_LOGGEDIN_PORT pLoggedInPort)
+static void UnblockScsiDevice(struct Scsi_Host *shpnt, PFC_LOGGEDIN_PORT pLoggedInPort)
 {
-//  Scsi_Device *sdev = HostAdapter->host_queue;
-  CPQFCHBA *cpqfcHBAdata = (CPQFCHBA *)HostAdapter->hostdata;
-  Scsi_Cmnd* *SCptr = &cpqfcHBAdata->LinkDnCmnd[0];
-  Scsi_Cmnd *Cmnd;
-  int indx;
-
- 
-  
-  // if the device was previously "blocked", make sure
-  // we unblock it so Linux SCSI will resume
-
-  pLoggedInPort->device_blocked = FALSE; // clear our flag
-
-  // check the Link Down command ptr buffer;
-  // we can complete now causing immediate retry
-  for( indx=0; indx < CPQFCTS_REQ_QUEUE_LEN; indx++, SCptr++)
-  {
-    if( *SCptr != NULL ) // scsi command to complete?
-    {
+//  Scsi_Device *sdev = shpnt->host_queue;
+	CPQFCHBA *dev = (CPQFCHBA *) shpnt->hostdata;
+	Scsi_Cmnd **SCptr = &dev->LinkDnCmnd[0];
+	Scsi_Cmnd *Cmnd;
+	int indx;
+
+	// if the device was previously "blocked", make sure
+	// we unblock it so Linux SCSI will resume
+
+	pLoggedInPort->device_blocked = 0;	// clear our flag
+
+	// check the Link Down command ptr buffer;
+	// we can complete now causing immediate retry
+	for (indx = 0; indx < CPQFCTS_REQ_QUEUE_LEN; indx++, SCptr++) {
+		if (*SCptr != NULL)	// scsi command to complete?
+		{
 #ifdef DUMMYCMND_DBG
-      printk("complete Cmnd %p in LinkDnCmnd[%d]\n", *SCptr,indx);
+			printk("complete Cmnd %p in LinkDnCmnd[%d]\n", *SCptr, indx);
 #endif
-      Cmnd = *SCptr;
-
+			Cmnd = *SCptr;
 
-      // Are there any Q'd commands for this target?
-      if( (Cmnd->target == pLoggedInPort->ScsiNexus.target)
-	       &&
-          (Cmnd->channel == pLoggedInPort->ScsiNexus.channel) )
-      {
-        Cmnd->result = (DID_SOFT_ERROR <<16); // force retry
-        if( Cmnd->scsi_done == NULL) 
-	{
-          printk("LinkDnCmnd scsi_done ptr null, port_id %Xh\n",
-		  pLoggedInPort->port_id);
-	  Cmnd->SCp.sent_command = 0;
+			// Are there any Q'd commands for this target?
+			if ((Cmnd->target == pLoggedInPort->ScsiNexus.target)
+			    && (Cmnd->channel == pLoggedInPort->ScsiNexus.channel)) {
+				Cmnd->result = (DID_SOFT_ERROR << 16);	// force retry
+				if (Cmnd->scsi_done == NULL) {
+					printk("LinkDnCmnd scsi_done ptr null, port_id %Xh\n", pLoggedInPort->port_id);
+					Cmnd->SCp.sent_command = 0;
+				} else
+					call_scsi_done(Cmnd);
+				*SCptr = NULL;	// free this slot for next use
+			}
+		}
 	}
-	else
-	  call_scsi_done(Cmnd);
-        *SCptr = NULL;  // free this slot for next use
-      }
-    }
-  }
 }
 
-  
+
 //#define WWN_DBG 1
 
-static void SetLoginFields(
-  PFC_LOGGEDIN_PORT pLoggedInPort,
-  TachFCHDR_GCMND* fchs,
-  BOOLEAN PDisc,
-  BOOLEAN Originator)
-{
-  LOGIN_PAYLOAD logi;       // FC-PH Port Login
-  PRLI_REQUEST prli;  // copy for BIG ENDIAN switch
-  int i;
+static void SetLoginFields(PFC_LOGGEDIN_PORT pLoggedInPort, TachFCHDR_GCMND * fchs, u8 PDisc, u8 Originator)
+{
+	LOGIN_PAYLOAD logi;	// FC-PH Port Login
+	PRLI_REQUEST prli;	// copy for BIG ENDIAN switch
+	int i;
 #ifdef WWN_DBG
-  ULONG ulBuff;
+	u32 ulBuff;
 #endif
 
-  BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&logi, sizeof(logi));
+	BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & logi, sizeof(logi));
 
-  pLoggedInPort->Originator = Originator;
-  pLoggedInPort->port_id = fchs->s_id & 0xFFFFFF;
-  
-  switch( fchs->pl[0] & 0xffff )
-  {
-  case 0x00000002:  //  PLOGI or PDISC ACCept?
-    if( PDisc )     // PDISC accept
-      goto PDISC_case;
-
-  case 0x00000003:  //  ELS_PLOGI or ELS_PLOGI_ACC
-
-  // Login BB_credit typically 0 for Tachyons
-    pLoggedInPort->BB_credit = logi.cmn_services.bb_credit;
-
-    // e.g. 128, 256, 1024, 2048 per FC-PH spec
-    // We have to use this when setting up SEST Writes,
-    // since that determines frame size we send.
-    pLoggedInPort->rx_data_size = logi.class3.rx_data_size;
-    pLoggedInPort->plogi = TRUE;
-    pLoggedInPort->pdisc = FALSE;
-    pLoggedInPort->prli = FALSE;    // ELS_PLOGI resets
-    pLoggedInPort->flogi = FALSE;   // ELS_PLOGI resets
-    pLoggedInPort->logo = FALSE;    // ELS_PLOGI resets
-    pLoggedInPort->LOGO_counter = 0;// ELS_PLOGI resets
-    pLoggedInPort->LOGO_timer = 0;// ELS_PLOGI resets
-
-    // was this PLOGI to a Fabric?
-    if( pLoggedInPort->port_id == 0xFFFFFC ) // well know address
-      pLoggedInPort->flogi = TRUE;
+	pLoggedInPort->Originator = Originator;
+	pLoggedInPort->port_id = fchs->s_id & 0xFFFFFF;
+
+	switch (fchs->pl[0] & 0xffff) {
+	case 0x00000002:	//  PLOGI or PDISC ACCept?
+		if (PDisc)	// PDISC accept
+			goto PDISC_case;
+
+	case 0x00000003:	//  ELS_PLOGI or ELS_PLOGI_ACC
+
+		// Login BB_credit typically 0 for Tachyons
+		pLoggedInPort->BB_credit = logi.cmn_services.bb_credit;
+
+		// e.g. 128, 256, 1024, 2048 per FC-PH spec
+		// We have to use this when setting up SEST Writes,
+		// since that determines frame size we send.
+		pLoggedInPort->rx_data_size = logi.class3.rx_data_size;
+		pLoggedInPort->plogi = 1;
+		pLoggedInPort->pdisc = 0;
+		pLoggedInPort->prli = 0;	// ELS_PLOGI resets
+		pLoggedInPort->flogi = 0;	// ELS_PLOGI resets
+		pLoggedInPort->logo = 0;	// ELS_PLOGI resets
+		pLoggedInPort->LOGO_counter = 0;	// ELS_PLOGI resets
+		pLoggedInPort->LOGO_timer = 0;	// ELS_PLOGI resets
+
+		// was this PLOGI to a Fabric?
+		if (pLoggedInPort->port_id == 0xFFFFFC)	// well know address
+			pLoggedInPort->flogi = 1;
 
 
-    for( i=0; i<8; i++)   // copy the LOGIN port's WWN
-      pLoggedInPort->u.ucWWN[i] = logi.port_name[i];  
+		for (i = 0; i < 8; i++)	// copy the LOGIN port's WWN
+			pLoggedInPort->u.ucWWN[i] = logi.port_name[i];
 
 #ifdef WWN_DBG
-    ulBuff = (ULONG)pLoggedInPort->u.liWWN;
-    if( pLoggedInPort->Originator)
-      printk("o");
-    else
-      printk("r");
-    printk("PLOGI port_id %Xh, WWN %08X",
-      pLoggedInPort->port_id, ulBuff);
+		ulBuff = (u32) pLoggedInPort->u.liWWN;
+		if (pLoggedInPort->Originator)
+			printk("o");
+		else
+			printk("r");
+		printk("PLOGI port_id %Xh, WWN %08X", pLoggedInPort->port_id, ulBuff);
 
-    ulBuff = (ULONG)(pLoggedInPort->u.liWWN >> 32);
-    printk("%08Xh fcPort %p\n", ulBuff, pLoggedInPort);
+		ulBuff = (u32) (pLoggedInPort->u.liWWN >> 32);
+		printk("%08Xh fcPort %p\n", ulBuff, pLoggedInPort);
 #endif
-    break;
-
-
-
-  
-  case 0x00000005:  //  ELS_LOGO (logout)
-
+		break;
 
-    pLoggedInPort->plogi = FALSE;
-    pLoggedInPort->pdisc = FALSE;
-    pLoggedInPort->prli = FALSE;   // ELS_PLOGI resets
-    pLoggedInPort->flogi = FALSE;  // ELS_PLOGI resets
-    pLoggedInPort->logo = TRUE;    // ELS_PLOGI resets
-    pLoggedInPort->LOGO_counter++; // ELS_PLOGI resets
-    pLoggedInPort->LOGO_timer = 0;
+	case 0x00000005:	//  ELS_LOGO (logout)
+		pLoggedInPort->plogi = 0;
+		pLoggedInPort->pdisc = 0;
+		pLoggedInPort->prli = 0;	// ELS_PLOGI resets
+		pLoggedInPort->flogi = 0;	// ELS_PLOGI resets
+		pLoggedInPort->logo = 1;	// ELS_PLOGI resets
+		pLoggedInPort->LOGO_counter++;	// ELS_PLOGI resets
+		pLoggedInPort->LOGO_timer = 0;
 #ifdef WWN_DBG
-    ulBuff = (ULONG)pLoggedInPort->u.liWWN;
-    if( pLoggedInPort->Originator)
-      printk("o");
-    else
-      printk("r");
-    printk("LOGO port_id %Xh, WWN %08X",
-      pLoggedInPort->port_id, ulBuff);
+		ulBuff = (u32) pLoggedInPort->u.liWWN;
+		if (pLoggedInPort->Originator)
+			printk("o");
+		else
+			printk("r");
+		printk("LOGO port_id %Xh, WWN %08X", pLoggedInPort->port_id, ulBuff);
 
-    ulBuff = (ULONG)(pLoggedInPort->u.liWWN >> 32);
-    printk("%08Xh\n", ulBuff);
+		ulBuff = (u32) (pLoggedInPort->u.liWWN >> 32);
+		printk("%08Xh\n", ulBuff);
 #endif
-    break;
-
-
+		break;
 
-PDISC_case:
-  case 0x00000050: //  ELS_PDISC or ELS_PDISC_ACC
-    pLoggedInPort->LOGO_timer = 0;  // stop the time-out
-      
-    pLoggedInPort->prli = TRUE;     // ready to accept FCP-SCSI I/O
-    
+	PDISC_case:
+	case 0x00000050:	//  ELS_PDISC or ELS_PDISC_ACC
+		pLoggedInPort->LOGO_timer = 0;	// stop the time-out
 
-      
+		pLoggedInPort->prli = 1;	// ready to accept FCP-SCSI I/O
 #ifdef WWN_DBG
-    ulBuff = (ULONG)pLoggedInPort->u.liWWN;
-    if( pLoggedInPort->Originator)
-      printk("o");
-    else
-      printk("r");
-    printk("PDISC port_id %Xh, WWN %08X",
-      pLoggedInPort->port_id, ulBuff);
+		ulBuff = (u32) pLoggedInPort->u.liWWN;
+		if (pLoggedInPort->Originator)
+			printk("o");
+		else
+			printk("r");
+		printk("PDISC port_id %Xh, WWN %08X", pLoggedInPort->port_id, ulBuff);
 
-    ulBuff = (ULONG)(pLoggedInPort->u.liWWN >> 32);
-    printk("%08Xh\n", ulBuff);
+		ulBuff = (u32) (pLoggedInPort->u.liWWN >> 32);
+		printk("%08Xh\n", ulBuff);
 #endif
+		break;
 
-
-    
-    break;
-
-
-    
-  case  0x1020L: //  PRLI?
-  case  0x1002L: //  PRLI ACCept?
-    BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&prli, sizeof(prli));
-
-    pLoggedInPort->fcp_info = prli.fcp_info; // target/initiator flags
-    pLoggedInPort->prli = TRUE;  // PLOGI resets, PDISC doesn't
-
-    pLoggedInPort->pdisc = TRUE;  // expect to send (or receive) PDISC
-                                  // next time
-    pLoggedInPort->LOGO_timer = 0;  // will be set next LinkDown
+	case 0x1020L:		//  PRLI?
+	case 0x1002L:		//  PRLI ACCept?
+		BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & prli, sizeof(prli));
+
+		pLoggedInPort->fcp_info = prli.fcp_info;	// target/initiator flags
+		pLoggedInPort->prli = 1;	// PLOGI resets, PDISC doesn't
+
+		pLoggedInPort->pdisc = 1;	// expect to send (or receive) PDISC
+		// next time
+		pLoggedInPort->LOGO_timer = 0;	// will be set next LinkDown
 #ifdef WWN_DBG
-    ulBuff = (ULONG)pLoggedInPort->u.liWWN;
-    if( pLoggedInPort->Originator)
-      printk("o");
-    else
-      printk("r");
-    printk("PRLI port_id %Xh, WWN %08X",
-      pLoggedInPort->port_id, ulBuff);
+		ulBuff = (u32) pLoggedInPort->u.liWWN;
+		if (pLoggedInPort->Originator)
+			printk("o");
+		else
+			printk("r");
+		printk("PRLI port_id %Xh, WWN %08X", pLoggedInPort->port_id, ulBuff);
 
-    ulBuff = (ULONG)(pLoggedInPort->u.liWWN >> 32);
-      printk("%08Xh\n", ulBuff);
+		ulBuff = (u32) (pLoggedInPort->u.liWWN >> 32);
+		printk("%08Xh\n", ulBuff);
 #endif
-
-    break;
-
-  }
-
-  return;
+		break;
+	}
+	return;
 }
 
-
-
-
-
-
-static void BuildLinkServicePayload( PTACHYON fcChip, ULONG type, void* payload)
+static void BuildLinkServicePayload(PTACHYON fcChip, u32 type, void *payload)
 {
-  LOGIN_PAYLOAD *plogi;  // FC-PH Port Login
-  LOGIN_PAYLOAD PlogiPayload;   // copy for BIG ENDIAN switch
-  PRLI_REQUEST  *prli;          // FCP-SCSI Process Login
-  PRLI_REQUEST  PrliPayload;    // copy for BIG ENDIAN switch
-  LOGOUT_PAYLOAD  *logo;
-  LOGOUT_PAYLOAD  LogoutPayload;
-//  PRLO_REQUEST  *prlo;
-//  PRLO_REQUEST  PrloPayload;
-  REJECT_MESSAGE rjt, *prjt;
-
-  memset( &PlogiPayload, 0, sizeof( PlogiPayload));
-  plogi = &PlogiPayload;    // load into stack buffer,
-                                // then BIG-ENDIAN switch a copy to caller
-
-
-  switch( type )  // payload type can be ELS_PLOGI, ELS_PRLI, ADISC, ...
-  {
-    case ELS_FDISC:
-    case ELS_FLOGI:
-    case ELS_PLOGI_ACC:   // FC-PH PORT Login Accept
-    case ELS_PLOGI:   // FC-PH PORT Login
-    case ELS_PDISC:   // FC-PH2 Port Discovery - same payload as ELS_PLOGI
-      plogi->login_cmd = LS_PLOGI;
-      if( type == ELS_PDISC)
-        plogi->login_cmd = LS_PDISC;
-      else if( type == ELS_PLOGI_ACC )
-        plogi->login_cmd = LS_ACC;
-
-      plogi->cmn_services.bb_credit = 0x00;
-      plogi->cmn_services.lowest_ver = fcChip->lowest_FCPH_ver;
-      plogi->cmn_services.highest_ver = fcChip->highest_FCPH_ver;
-      plogi->cmn_services.bb_rx_size = TACHLITE_TS_RX_SIZE;
-      plogi->cmn_services.common_features = CONTINUOSLY_INCREASING |
-              RANDOM_RELATIVE_OFFSET;
-
-             // fill in with World Wide Name based Port Name - 8 UCHARs
-             // get from Tach registers WWN hi & lo
-      LoadWWN( fcChip, plogi->port_name, 0);
-             // fill in with World Wide Name based Node/Fabric Name - 8 UCHARs
-             // get from Tach registers WWN hi & lo
-      LoadWWN( fcChip, plogi->node_name, 1);
-
-	// For Seagate Drives.
-	//
-      plogi->cmn_services.common_features |= 0x800;
-      plogi->cmn_services.rel_offset = 0xFE;
-      plogi->cmn_services.concurrent_seq = 1;
-      plogi->class1.service_options = 0x00;
-      plogi->class2.service_options = 0x00;
-      plogi->class3.service_options = CLASS_VALID;
-      plogi->class3.initiator_control = 0x00;
-      plogi->class3.rx_data_size = MAX_RX_PAYLOAD;
-      plogi->class3.recipient_control =
-             ERROR_DISCARD | ONE_CATEGORY_SEQUENCE;
-      plogi->class3.concurrent_sequences = 1;
-      plogi->class3.open_sequences = 1;
-      plogi->vendor_id[0] = 'C'; plogi->vendor_id[1] = 'Q';
-      plogi->vendor_version[0] = 'C'; plogi->vendor_version[1] = 'Q';
-      plogi->vendor_version[2] = ' '; plogi->vendor_version[3] = '0';
-      plogi->vendor_version[4] = '0'; plogi->vendor_version[5] = '0';
-
-
-      // FLOGI specific fields... (see FC-FLA, Rev 2.7, Aug 1999, sec 5.1)
-      if( (type == ELS_FLOGI) || (type == ELS_FDISC) )
-      {
-        if( type == ELS_FLOGI )
-  	  plogi->login_cmd = LS_FLOGI;  
-	else
-  	  plogi->login_cmd = LS_FDISC;  
-
-        plogi->cmn_services.lowest_ver = 0x20;
-        plogi->cmn_services.common_features = 0x0800;
-        plogi->cmn_services.rel_offset = 0;
-        plogi->cmn_services.concurrent_seq = 0;
-
-        plogi->class3.service_options = 0x8800;
-        plogi->class3.rx_data_size = 0;
-        plogi->class3.recipient_control = 0;
-        plogi->class3.concurrent_sequences = 0;
-        plogi->class3.open_sequences = 0;
-      }
-      
-              // copy back to caller's buff, w/ BIG ENDIAN swap
-      BigEndianSwap( (UCHAR*)&PlogiPayload, payload,  sizeof(PlogiPayload));
-      break;
-
-    
-    case ELS_ACC:       // generic Extended Link Service ACCept	    
-      plogi->login_cmd = LS_ACC;
-              // copy back to caller's buff, w/ BIG ENDIAN swap
-      BigEndianSwap( (UCHAR*)&PlogiPayload, payload,  4);
-      break;
-
-
-      
-    case ELS_SCR:    // Fabric State Change Registration
-    {
-      SCR_PL scr;     // state change registration
-
-      memset( &scr, 0, sizeof(scr));
-
-      scr.command = LS_SCR;  // 0x62000000
-                             // see FC-FLA, Rev 2.7, Table A.22 (pg 82)
-      scr.function = 3;      // 1 = Events detected by Fabric
-                             // 2 = N_Port detected registration
-                             // 3 = Full registration
-      
-      // copy back to caller's buff, w/ BIG ENDIAN swap
-      BigEndianSwap( (UCHAR*)&scr, payload,  sizeof(SCR_PL));
-    }
-    
-    break;
-
-    
-    case FCS_NSR:    // Fabric Name Service Request
-    {
-      NSR_PL nsr;    // Name Server Req. payload
-
-      memset( &nsr, 0, sizeof(NSR_PL));
-
-                             // see Brocade Fabric Programming Guide,
-                             // Rev 1.3, pg 4-44
-      nsr.CT_Rev = 0x01000000;
-      nsr.FCS_Type = 0xFC020000;
-      nsr.Command_code = 0x01710000;
-      nsr.FCP = 8;
-     
-      // copy back to caller's buff, w/ BIG ENDIAN swap
-      BigEndianSwap( (UCHAR*)&nsr, payload,  sizeof(NSR_PL));
-    }
-    
-    break;
-
-
-
-    
-    case ELS_LOGO:   // FC-PH PORT LogOut
-      logo = &LogoutPayload;    // load into stack buffer,
-                                // then BIG-ENDIAN switch a copy to caller
-      logo->cmd = LS_LOGO;
-                                // load the 3 UCHARs of the node name
-                                // (if private loop, upper two UCHARs 0)
-      logo->reserved = 0;
-
-      logo->n_port_identifier[0] = (UCHAR)(fcChip->Registers.my_al_pa);
-      logo->n_port_identifier[1] =
-                     (UCHAR)(fcChip->Registers.my_al_pa>>8);
-      logo->n_port_identifier[2] =
-                     (UCHAR)(fcChip->Registers.my_al_pa>>16);
-             // fill in with World Wide Name based Port Name - 8 UCHARs
-             // get from Tach registers WWN hi & lo
-      LoadWWN( fcChip, logo->port_name, 0);
-
-      BigEndianSwap( (UCHAR*)&LogoutPayload,
-                     payload,  sizeof(LogoutPayload) );  // 16 UCHAR struct
-      break;
-
-
-    case ELS_LOGO_ACC:     // Logout Accept (FH-PH pg 149, table 74)
-      logo = &LogoutPayload;    // load into stack buffer,
-                                // then BIG-ENDIAN switch a copy to caller
-      logo->cmd = LS_ACC;
-      BigEndianSwap( (UCHAR*)&LogoutPayload, payload, 4 );  // 4 UCHAR cmnd
-      break;
-      
-
-    case ELS_RJT:          // ELS_RJT link service reject (FH-PH pg 155)
-
-      prjt = (REJECT_MESSAGE*)payload;  // pick up passed data
-      rjt.command_code = ELS_RJT;
-                       // reverse fields, because of Swap that follows...
-      rjt.vendor = prjt->reserved; // vendor specific
-      rjt.explain = prjt->reason; //
-      rjt.reason = prjt->explain; //
-      rjt.reserved = prjt->vendor; //
-                       // BIG-ENDIAN switch a copy to caller
-      BigEndianSwap( (UCHAR*)&rjt, payload, 8 );  // 8 UCHAR cmnd
-      break;
+	LOGIN_PAYLOAD *plogi;	// FC-PH Port Login
+	LOGIN_PAYLOAD PlogiPayload;	// copy for BIG ENDIAN switch
+	PRLI_REQUEST *prli;	// FCP-SCSI Process Login
+	PRLI_REQUEST PrliPayload;	// copy for BIG ENDIAN switch
+	LOGOUT_PAYLOAD *logo;
+	LOGOUT_PAYLOAD LogoutPayload;
+//	PRLO_REQUEST  *prlo;
+//	PRLO_REQUEST  PrloPayload;
+	REJECT_MESSAGE rjt, *prjt;
+
+	memset(&PlogiPayload, 0, sizeof(PlogiPayload));
+	plogi = &PlogiPayload;	// load into stack buffer,
+	// then BIG-ENDIAN switch a copy to caller
 
+	switch (type)		// payload type can be ELS_PLOGI, ELS_PRLI, ADISC, ...
+	{
+	case ELS_FDISC:
+	case ELS_FLOGI:
+	case ELS_PLOGI_ACC:	// FC-PH PORT Login Accept
+	case ELS_PLOGI:	// FC-PH PORT Login
+	case ELS_PDISC:	// FC-PH2 Port Discovery - same payload as ELS_PLOGI
+		plogi->login_cmd = LS_PLOGI;
+		if (type == ELS_PDISC)
+			plogi->login_cmd = LS_PDISC;
+		else if (type == ELS_PLOGI_ACC)
+			plogi->login_cmd = LS_ACC;
+
+		plogi->cmn_services.bb_credit = 0x00;
+		plogi->cmn_services.lowest_ver = fcChip->lowest_FCPH_ver;
+		plogi->cmn_services.highest_ver = fcChip->highest_FCPH_ver;
+		plogi->cmn_services.bb_rx_size = TACHLITE_TS_RX_SIZE;
+		plogi->cmn_services.common_features = CONTINUOSLY_INCREASING | RANDOM_RELATIVE_OFFSET;
+
+		// fill in with World Wide Name based Port Name - 8 u8s
+		// get from Tach registers WWN hi & lo
+		LoadWWN(fcChip, plogi->port_name, 0);
+		// fill in with World Wide Name based Node/Fabric Name - 8 u8s
+		// get from Tach registers WWN hi & lo
+		LoadWWN(fcChip, plogi->node_name, 1);
+
+		// For Seagate Drives.
+		//
+		plogi->cmn_services.common_features |= 0x800;
+		plogi->cmn_services.rel_offset = 0xFE;
+		plogi->cmn_services.concurrent_seq = 1;
+		plogi->class1.service_options = 0x00;
+		plogi->class2.service_options = 0x00;
+		plogi->class3.service_options = CLASS_VALID;
+		plogi->class3.initiator_control = 0x00;
+		plogi->class3.rx_data_size = MAX_RX_PAYLOAD;
+		plogi->class3.recipient_control = ERROR_DISCARD | ONE_CATEGORY_SEQUENCE;
+		plogi->class3.concurrent_sequences = 1;
+		plogi->class3.open_sequences = 1;
+		plogi->vendor_id[0] = 'C';
+		plogi->vendor_id[1] = 'Q';
+		plogi->vendor_version[0] = 'C';
+		plogi->vendor_version[1] = 'Q';
+		plogi->vendor_version[2] = ' ';
+		plogi->vendor_version[3] = '0';
+		plogi->vendor_version[4] = '0';
+		plogi->vendor_version[5] = '0';
+
+		// FLOGI specific fields... (see FC-FLA, Rev 2.7, Aug 1999, sec 5.1)
+		if ((type == ELS_FLOGI) || (type == ELS_FDISC)) {
+			if (type == ELS_FLOGI)
+				plogi->login_cmd = LS_FLOGI;
+			else
+				plogi->login_cmd = LS_FDISC;
+
+			plogi->cmn_services.lowest_ver = 0x20;
+			plogi->cmn_services.common_features = 0x0800;
+			plogi->cmn_services.rel_offset = 0;
+			plogi->cmn_services.concurrent_seq = 0;
+
+			plogi->class3.service_options = 0x8800;
+			plogi->class3.rx_data_size = 0;
+			plogi->class3.recipient_control = 0;
+			plogi->class3.concurrent_sequences = 0;
+			plogi->class3.open_sequences = 0;
+		}
+		// copy back to caller's buff, w/ BIG ENDIAN swap
+		BigEndianSwap((u8 *) & PlogiPayload, payload, sizeof(PlogiPayload));
+		break;
 
+	case ELS_ACC:		// generic Extended Link Service ACCept     
+		plogi->login_cmd = LS_ACC;
+		// copy back to caller's buff, w/ BIG ENDIAN swap
+		BigEndianSwap((u8 *) & PlogiPayload, payload, 4);
+		break;
 
+	case ELS_SCR:		// Fabric State Change Registration
+		{
+			SCR_PL scr;	// state change registration
+
+			memset(&scr, 0, sizeof(scr));
+
+			scr.command = LS_SCR;	// 0x62000000
+			// see FC-FLA, Rev 2.7, Table A.22 (pg 82)
+			scr.function = 3;	// 1 = Events detected by Fabric
+			// 2 = N_Port detected registration
+			// 3 = Full registration
 
+			// copy back to caller's buff, w/ BIG ENDIAN swap
+			BigEndianSwap((u8 *) & scr, payload, sizeof(SCR_PL));
+		}
+		break;
 
-    case ELS_PRLI_ACC:  // Process Login ACCept
-    case ELS_PRLI:  // Process Login
-    case ELS_PRLO:  // Process Logout
-      memset( &PrliPayload, 0, sizeof( PrliPayload));
-      prli = &PrliPayload;      // load into stack buffer,
+	case FCS_NSR:		// Fabric Name Service Request
+		{
+			NSR_PL nsr;	// Name Server Req. payload
+
+			memset(&nsr, 0, sizeof(NSR_PL));
+
+			// see Brocade Fabric Programming Guide,
+			// Rev 1.3, pg 4-44
+			nsr.CT_Rev = 0x01000000;
+			nsr.FCS_Type = 0xFC020000;
+			nsr.Command_code = 0x01710000;
+			nsr.FCP = 8;
 
-      if( type == ELS_PRLI )
-        prli->cmd = 0x20;  // Login
-      else if( type == ELS_PRLO )
-        prli->cmd = 0x21;  // Logout
-      else if( type == ELS_PRLI_ACC )
-      {
-        prli->cmd = 0x02;  // Login ACCept
-        prli->valid = REQUEST_EXECUTED;
-      }
+			// copy back to caller's buff, w/ BIG ENDIAN swap
+			BigEndianSwap((u8 *) & nsr, payload, sizeof(NSR_PL));
+		}
+		break;
 
+	case ELS_LOGO:		// FC-PH PORT LogOut
+		logo = &LogoutPayload;	// load into stack buffer,
+		// then BIG-ENDIAN switch a copy to caller
+		logo->cmd = LS_LOGO;
+		// load the 3 u8s of the node name
+		// (if private loop, upper two u8s 0)
+		logo->reserved = 0;
+
+		logo->n_port_identifier[0] = (u8) (fcChip->Registers.my_al_pa);
+		logo->n_port_identifier[1] = (u8) (fcChip->Registers.my_al_pa >> 8);
+		logo->n_port_identifier[2] = (u8) (fcChip->Registers.my_al_pa >> 16);
+		// fill in with World Wide Name based Port Name - 8 u8s
+		// get from Tach registers WWN hi & lo
+		LoadWWN(fcChip, logo->port_name, 0);
 
-      prli->valid |= SCSI_FCP | ESTABLISH_PAIR;
-      prli->fcp_info = READ_XFER_RDY;
-      prli->page_length = 0x10;
-      prli->payload_length = 20;
-                                // Can be initiator AND target
+		BigEndianSwap((u8 *) & LogoutPayload, payload, sizeof(LogoutPayload));	// 16 u8 struct
+		break;
 
-      if( fcChip->Options.initiator )
-        prli->fcp_info |= INITIATOR_FUNCTION;
-      if( fcChip->Options.target )
-        prli->fcp_info |= TARGET_FUNCTION;
+	case ELS_LOGO_ACC:	// Logout Accept (FH-PH pg 149, table 74)
+		logo = &LogoutPayload;	// load into stack buffer,
+		// then BIG-ENDIAN switch a copy to caller
+		logo->cmd = LS_ACC;
+		BigEndianSwap((u8 *) & LogoutPayload, payload, 4);	// 4 u8 cmnd
+		break;
 
-      BigEndianSwap( (UCHAR*)&PrliPayload, payload,  prli->payload_length);
-      break;
+	case ELS_RJT:		// ELS_RJT link service reject (FH-PH pg 155)
+		prjt = (REJECT_MESSAGE *) payload;	// pick up passed data
+		rjt.command_code = ELS_RJT;
+		// reverse fields, because of Swap that follows...
+		rjt.vendor = prjt->reserved;	// vendor specific
+		rjt.explain = prjt->reason;	//
+		rjt.reason = prjt->explain;	//
+		rjt.reserved = prjt->vendor;	//
+		// BIG-ENDIAN switch a copy to caller
+		BigEndianSwap((u8 *) & rjt, payload, 8);	// 8 u8 cmnd
+		break;
 
+	case ELS_PRLI_ACC:	// Process Login ACCept
+	case ELS_PRLI:		// Process Login
+	case ELS_PRLO:		// Process Logout
+		memset(&PrliPayload, 0, sizeof(PrliPayload));
+		prli = &PrliPayload;	// load into stack buffer,
+
+		if (type == ELS_PRLI)
+			prli->cmd = 0x20;	// Login
+		else if (type == ELS_PRLO)
+			prli->cmd = 0x21;	// Logout
+		else if (type == ELS_PRLI_ACC) {
+			prli->cmd = 0x02;	// Login ACCept
+			prli->valid = REQUEST_EXECUTED;
+		}
+		prli->valid |= SCSI_FCP | ESTABLISH_PAIR;
+		prli->fcp_info = READ_XFER_RDY;
+		prli->page_length = 0x10;
+		prli->payload_length = 20;
+		// Can be initiator AND target
+
+		if (fcChip->Options.initiator)
+			prli->fcp_info |= INITIATOR_FUNCTION;
+		if (fcChip->Options.target)
+			prli->fcp_info |= TARGET_FUNCTION;
 
+		BigEndianSwap((u8 *) & PrliPayload, payload, prli->payload_length);
+		break;
 
-    default:  // no can do - programming error
-      printk(" BuildLinkServicePayload unknown!\n");
-      break;
-  }
+	default:		// no can do - programming error
+		printk(" BuildLinkServicePayload unknown!\n");
+		break;
+	}
 }
 
-// loads 8 UCHARs for PORT name or NODE name base on
+// loads 8 u8s for PORT name or NODE name base on
 // controller's WWN.
-void LoadWWN( PTACHYON fcChip, UCHAR* dest, UCHAR type)
+void LoadWWN(PTACHYON fcChip, u8 * dest, u8 type)
 {
-  UCHAR* bPtr, i;
-
-  switch( type )
-  {
-    case 0:  // Port_Name
-      bPtr = (UCHAR*)&fcChip->Registers.wwn_hi;
-      for( i =0; i<4; i++)
-        dest[i] = *bPtr++;
-      bPtr = (UCHAR*)&fcChip->Registers.wwn_lo;
-      for( i =4; i<8; i++)
-        dest[i] = *bPtr++;
-      break;
-    case 1:  // Node/Fabric _Name
-      bPtr = (UCHAR*)&fcChip->Registers.wwn_hi;
-      for( i =0; i<4; i++)
-        dest[i] = *bPtr++;
-      bPtr = (UCHAR*)&fcChip->Registers.wwn_lo;
-      for( i =4; i<8; i++)
-        dest[i] = *bPtr++;
-      break;
-  }
-  
-}
+	u8 *bPtr, i;
 
+	switch (type) {
+	case 0:		// Port_Name
+		bPtr = (u8 *) & fcChip->Registers.wwn_hi;
+		for (i = 0; i < 4; i++)
+			dest[i] = *bPtr++;
+		bPtr = (u8 *) & fcChip->Registers.wwn_lo;
+		for (i = 4; i < 8; i++)
+			dest[i] = *bPtr++;
+		break;
+	case 1:		// Node/Fabric _Name
+		bPtr = (u8 *) & fcChip->Registers.wwn_hi;
+		for (i = 0; i < 4; i++)
+			dest[i] = *bPtr++;
+		bPtr = (u8 *) & fcChip->Registers.wwn_lo;
+		for (i = 4; i < 8; i++)
+			dest[i] = *bPtr++;
+		break;
+	}
 
+}
 
 // We check the Port Login payload for required values.  Note that
 // ELS_PLOGI and ELS_PDISC (Port DISCover) use the same payload.
 
+int verify_PLOGI(PTACHYON fcChip, TachFCHDR_GCMND * fchs, u32 * reject_explain)
+{
+	LOGIN_PAYLOAD login;
 
-int verify_PLOGI( PTACHYON fcChip,
-                  TachFCHDR_GCMND* fchs, 
-                  ULONG* reject_explain)
-{
-  LOGIN_PAYLOAD	login;
-
-                  // source, dest, len (should be mult. of 4)
-  BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&login,  sizeof(login));
-
-                            // check FC version
-                            // if other port's highest supported version
-                            // is less than our lowest, and 
-                            // if other port's lowest
-  if( login.cmn_services.highest_ver < fcChip->lowest_FCPH_ver ||
-      login.cmn_services.lowest_ver > fcChip->highest_FCPH_ver )
-  {
-    *reject_explain = LS_RJT_REASON( LOGICAL_ERROR, OPTIONS_ERROR);
-    return LOGICAL_ERROR;
-  }
-
-                            // Receive Data Field Size must be >=128
-                            // per FC-PH
-  if (login.cmn_services.bb_rx_size < 128)
-  {
-    *reject_explain = LS_RJT_REASON( LOGICAL_ERROR, DATA_FIELD_SIZE_ERROR);
-    return LOGICAL_ERROR;
-  }
+	// source, dest, len (should be mult. of 4)
+	BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & login, sizeof(login));
 
-                            // Only check Class 3 params
-  if( login.class3.service_options & CLASS_VALID)
-  {
-    if (login.class3.rx_data_size < 128)
-    {
-      *reject_explain = LS_RJT_REASON( LOGICAL_ERROR, INVALID_CSP);
-      return LOGICAL_ERROR;
-    }
-    if( login.class3.initiator_control & XID_REQUIRED)
-    {
-      *reject_explain = LS_RJT_REASON( LOGICAL_ERROR, INITIATOR_CTL_ERROR);
-      return LOGICAL_ERROR;
-    }
-  }
-  return 0;   // success
+	// check FC version
+	// if other port's highest supported version
+	// is less than our lowest, and 
+	// if other port's lowest
+	if (login.cmn_services.highest_ver < fcChip->lowest_FCPH_ver || login.cmn_services.lowest_ver > fcChip->highest_FCPH_ver) {
+		*reject_explain = LS_RJT_REASON(LOGICAL_ERROR, OPTIONS_ERROR);
+		return LOGICAL_ERROR;
+	}
+	// Receive Data Field Size must be >=128
+	// per FC-PH
+	if (login.cmn_services.bb_rx_size < 128) {
+		*reject_explain = LS_RJT_REASON(LOGICAL_ERROR, DATA_FIELD_SIZE_ERROR);
+		return LOGICAL_ERROR;
+	}
+	// Only check Class 3 params
+	if (login.class3.service_options & CLASS_VALID) {
+		if (login.class3.rx_data_size < 128) {
+			*reject_explain = LS_RJT_REASON(LOGICAL_ERROR, INVALID_CSP);
+			return LOGICAL_ERROR;
+		}
+		if (login.class3.initiator_control & XID_REQUIRED) {
+			*reject_explain = LS_RJT_REASON(LOGICAL_ERROR, INITIATOR_CTL_ERROR);
+			return LOGICAL_ERROR;
+		}
+	}
+	return 0;		// success
 }
 
-
-
-
-int verify_PRLI( TachFCHDR_GCMND* fchs, ULONG* reject_explain)
+int verify_PRLI(TachFCHDR_GCMND * fchs, u32 * reject_explain)
 {
-  PRLI_REQUEST prli;  // buffer for BIG ENDIAN
+	PRLI_REQUEST prli;	// buffer for BIG ENDIAN
 
-                  // source, dest, len (should be mult. of 4)
-  BigEndianSwap( (UCHAR*)&fchs->pl[0], (UCHAR*)&prli,  sizeof(prli));
+	// source, dest, len (should be mult. of 4)
+	BigEndianSwap((u8 *) & fchs->pl[0], (u8 *) & prli, sizeof(prli));
 
-  if( prli.fcp_info == 0 )  // i.e., not target or initiator?
-  {
-    *reject_explain = LS_RJT_REASON( LOGICAL_ERROR, OPTIONS_ERROR);
-    return LOGICAL_ERROR;
-  }
+	if (prli.fcp_info == 0)	// i.e., not target or initiator?
+	{
+		*reject_explain = LS_RJT_REASON(LOGICAL_ERROR, OPTIONS_ERROR);
+		return LOGICAL_ERROR;
+	}
 
-  return 0;  // success
+	return 0;		// success
 }
 
-
-// SWAP UCHARs as required by Fibre Channel (i.e. BIG ENDIAN)
+// SWAP u8s as required by Fibre Channel (i.e. BIG ENDIAN)
 // INPUTS:
-//   source   - ptr to LITTLE ENDIAN ULONGS
-//   cnt      - number of UCHARs to switch (should be mult. of ULONG)
+//   source   - ptr to LITTLE ENDIAN u32S
+//   cnt      - number of u8s to switch (should be mult. of u32)
 // OUTPUTS:
 //   dest     - ptr to BIG ENDIAN copy
 // RETURN:
 //   none
 //
-void BigEndianSwap( UCHAR *source, UCHAR *dest,  USHORT cnt)
+void BigEndianSwap(u8 * source, u8 * dest, u16 cnt)
 {
-  int i,j;
+	int i, j;
 
-  source+=3;   // start at MSB of 1st ULONG
-  for( j=0; j < cnt; j+=4, source+=4, dest+=4)  // every ULONG
-  {
-    for( i=0; i<4; i++)  // every UCHAR in ULONG
-          *(dest+i) = *(source-i);
-  }
+	source += 3;		// start at MSB of 1st u32
+	for (j = 0; j < cnt; j += 4, source += 4, dest += 4)	// every u32
+	{
+		for (i = 0; i < 4; i++)	// every u8 in u32
+			*(dest + i) = *(source - i);
+	}
 }
 
-
-
-
 // Build FC Exchanges............
 
-static void  buildFCPstatus( 
-  PTACHYON fcChip, 
-  ULONG ExchangeID);
-
-static LONG FindFreeExchange( PTACHYON fcChip, ULONG type );
-
-static ULONG build_SEST_sgList( 
-  struct pci_dev *pcidev,
-  ULONG *SESTalPairStart,
-  Scsi_Cmnd *Cmnd,
-  ULONG *sgPairs,
-  PSGPAGES *sgPages_head  // link list of TL Ext. S/G pages from O/S Pool
-);
-
-static int build_FCP_payload( Scsi_Cmnd *Cmnd, 
-  UCHAR* payload, ULONG type, ULONG fcp_dl );
-
+static void buildFCPstatus(PTACHYON fcChip, u32 ExchangeID);
+static s32 FindFreeExchange(PTACHYON fcChip, u32 type);
+static u32 build_SEST_sgList(struct pci_dev *pcidev, u32 * SESTalPairStart, Scsi_Cmnd * Cmnd, u32 * sgPairs, PSGPAGES * sgPages_head);	// link list of TL Ext. S/G pages from O/S Pool
+static int build_FCP_payload(Scsi_Cmnd * Cmnd, u8 * payload, u32 type, u32 fcp_dl);
 
 /*
                              IRB
@@ -4118,7 +3306,7 @@
 // SEST entry, and several frame headers and data buffers all
 // logically linked together.
 // Inputs:
-//   cpqfcHBAdata  - controller struct
+//   dev  - controller struct
 //   type          - PLOGI, SCSI_IWE, etc.
 //   InFCHS        - Incoming Tachlite FCHS which prompted this exchange
 //                   (only s_id set if we are originating)
@@ -4143,990 +3331,807 @@
 // return success
 
 //sbuildex
-ULONG cpqfcTSBuildExchange(
-  CPQFCHBA *cpqfcHBAdata,
-  ULONG type, // e.g. PLOGI
-  TachFCHDR_GCMND* InFCHS,  // incoming FCHS
-  void *Data,               // the CDB, scatter/gather, etc.  
-  LONG *fcExchangeIndex )   // points to allocated exchange, 
-{
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  ULONG ulStatus = 0;  // assume OK
-  USHORT ox_ID, rx_ID=0xFFFF;
-  ULONG SfsLen=0L;
-  TachLiteIRB* pIRB;
-  IRBflags IRB_flags;
-  UCHAR *pIRB_flags = (UCHAR*)&IRB_flags;
-  TachFCHDR_GCMND* CMDfchs;
-  TachFCHDR* dataHDR;     // 32 byte HEADER ONLY FCP-DATA buffer
-  TachFCHDR_RSP* rspHDR;     // 32 byte header + RSP payload
-  Scsi_Cmnd *Cmnd = (Scsi_Cmnd*)Data;   // Linux Scsi CDB, S/G, ...
-  TachLiteIWE* pIWE;
-  TachLiteIRE* pIRE;
-  TachLiteTWE* pTWE;
-  TachLiteTRE* pTRE;
-  ULONG fcp_dl;           // total byte length of DATA transferred
-  ULONG fl;               // frame length (FC frame size, 128, 256, 512, 1024)
-  ULONG sgPairs;          // number of valid scatter/gather pairs
-  int FCP_SCSI_command;
-  BA_ACC_PAYLOAD *ba_acc;
-  BA_RJT_PAYLOAD *ba_rjt;
-
-                          // check passed ARGS
-  if( !fcChip->ERQ )      // NULL ptr means uninitialized Tachlite chip
-    return INVALID_ARGS;
-
-
-  if( type == SCSI_IRE ||
-      type == SCSI_TRE ||
-      type == SCSI_IWE ||
-      type == SCSI_TWE)
-    FCP_SCSI_command = 1;
-
-  else
-    FCP_SCSI_command = 0;
-
-
-                     // for commands that pass payload data (e.g. SCSI write)
-                     // examine command struct - verify that the
-                     // length of s/g buffers is adequate for total payload
-                     // length (end of list is NULL address)
-
-  if( FCP_SCSI_command )
-  {
-    if( Data )     // must have data descriptor (S/G list -- at least
-                   // one address with at least 1 byte of data)
-    {
-      // something to do (later)?
-    }
-
-    else
-      return INVALID_ARGS;  // invalid DATA ptr
-  }
-
-    
-
-         // we can build an Exchange for later Queuing (on the TL chip)
-         // if an empty slot is available in the DevExt for this controller
-         // look for available Exchange slot...
-
-  if( type != FCP_RESPONSE &&
-      type != BLS_ABTS &&
-      type != BLS_ABTS_ACC )  // already have Exchange slot!
-    *fcExchangeIndex = FindFreeExchange( fcChip, type );
-
-  if( *fcExchangeIndex != -1 )   // Exchange is available?
-  {
-                     // assign tmp ptr (shorthand)
-    CMDfchs = &Exchanges->fcExchange[ *fcExchangeIndex].fchs; 
-
-    if( Cmnd != NULL ) // (necessary for ABTS cases)
-    {
-      Exchanges->fcExchange[ *fcExchangeIndex].Cmnd = Cmnd; // Linux Scsi
-      Exchanges->fcExchange[ *fcExchangeIndex].pLoggedInPort = 
-	fcFindLoggedInPort( fcChip,
-          Exchanges->fcExchange[ *fcExchangeIndex].Cmnd, // find 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
-
-    }
-
-
-                     // Build the command frame header (& data) according
-                     // to command type
-
-                     // fields common for all SFS frame types
-    CMDfchs->reserved = 0L; // must clear
-    CMDfchs->sof_eof = 0x75000000L;  // SOFi3:EOFn  no UAM; LCr=0, no TS
-    
-             // get the destination port_id from incoming FCHS
-             // (initialized before calling if we're Originator)
-             // Frame goes to port it was from - the source_id
-    
-    CMDfchs->d_id = InFCHS->s_id &0xFFFFFF; // destination (add R_CTL later)
-    CMDfchs->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0
+u32 cpqfcTSBuildExchange(CPQFCHBA * dev, u32 type,	// e.g. PLOGI
+			   TachFCHDR_GCMND * InFCHS,	// incoming FCHS
+			   void *Data,	// the CDB, scatter/gather, etc.  
+			   s32 * fcExchangeIndex)	// points to allocated exchange, 
+{
+	PTACHYON fcChip = &dev->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	u32 ulStatus = 0;	// assume OK
+	u16 ox_ID, rx_ID = 0xFFFF;
+	u32 SfsLen = 0L;
+	TachLiteIRB *pIRB;
+	IRBflags IRB_flags;
+	u8 *pIRB_flags = (u8 *) & IRB_flags;
+	TachFCHDR_GCMND *CMDfchs;
+	TachFCHDR *dataHDR;	// 32 byte HEADER ONLY FCP-DATA buffer
+	TachFCHDR_RSP *rspHDR;	// 32 byte header + RSP payload
+	Scsi_Cmnd *Cmnd = (Scsi_Cmnd *) Data;	// Linux Scsi CDB, S/G, ...
+	TachLiteIWE *pIWE;
+	TachLiteIRE *pIRE;
+	TachLiteTWE *pTWE;
+	TachLiteTRE *pTRE;
+	u32 fcp_dl;		// total byte length of DATA transferred
+	u32 fl;		// frame length (FC frame size, 128, 256, 512, 1024)
+	u32 sgPairs;		// number of valid scatter/gather pairs
+	int FCP_SCSI_command;
+	BA_ACC_PAYLOAD *ba_acc;
+	BA_RJT_PAYLOAD *ba_rjt;
+
+	// check passed ARGS
+	if (!fcChip->ERQ)	// NULL ptr means uninitialized Tachlite chip
+		return INVALID_ARGS;
 
-
-    // now enter command-specific fields
-    switch( type )
-    {
-
-    case BLS_NOP:   // FC defined basic link service command NO-OP
-                // ensure unique X_IDs! (use tracking function)
-
-      *pIRB_flags = 0;      // clear IRB flags
-      IRB_flags.SFA = 1;    // send SFS (not SEST index)
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      SfsLen += 32L;        // add len to LSB (header only - no payload)
-
-                   // TYPE[31-24] 00 Basic Link Service
-                   // f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
-      CMDfchs->d_id |= 0x80000000L;  // R_CTL = 80 for NOP (Basic Link Ser.)
-      CMDfchs->f_ctl = 0x00310000L;  // xchng originator, 1st seq,....
-      CMDfchs->seq_cnt = 0x0L;
-      CMDfchs->ox_rx_id = 0xFFFF;        // RX_ID for now; OX_ID on start
-      CMDfchs->ro = 0x0L;    // relative offset (n/a)
-      CMDfchs->pl[0] = 0xaabbccddL;   // words 8-15 frame data payload (n/a)
-      Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 1; // seconds
-                                      // (NOP should complete ~instantly)
-      break;
-
-
-    
-    
-    case BLS_ABTS_ACC:  // Abort Sequence ACCept
-      *pIRB_flags = 0;      // clear IRB flags
-      IRB_flags.SFA = 1;    // send SFS (not SEST index)
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      SfsLen += 32 + 12;    // add len to LSB (header + 3 DWORD payload)
-
-      CMDfchs->d_id |= 0x84000000L;  // R_CTL = 84 for BASIC ACCept
-                   // TYPE[31-24] 00 Basic Link Service
-                   // f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
-      CMDfchs->f_ctl = 0x00910000L;  // xchnge responder, last seq, xfer SI
-                   // CMDfchs->seq_id & count might be set from DataHdr?
-      CMDfchs->ro = 0x0L;    // relative offset (n/a)
-      Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 5; // seconds
-                        // (Timeout in case of weird error)
-      
-      // now set the ACCept payload...
-      ba_acc = (BA_ACC_PAYLOAD*)&CMDfchs->pl[0];
-      memset( ba_acc, 0, sizeof( BA_ACC_PAYLOAD));
-      // Since PLDA requires (only) entire Exchange aborts, we don't need
-      // to worry about what the last sequence was.
-
-      // We expect that a "target" task is accepting the abort, so we
-      // can use the OX/RX ID pair 
-      ba_acc->ox_rx_id = CMDfchs->ox_rx_id;
- 
-      // source, dest, #bytes
-      BigEndianSwap((UCHAR *)&CMDfchs->ox_rx_id, (UCHAR *)&ba_acc->ox_rx_id, 4);
-
-      ba_acc->low_seq_cnt = 0;
-      ba_acc->high_seq_cnt = 0xFFFF;
-
-
-      break;
-    
-
-    case BLS_ABTS_RJT:  // Abort Sequence ACCept
-      *pIRB_flags = 0;      // clear IRB flags
-      IRB_flags.SFA = 1;    // send SFS (not SEST index)
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      SfsLen += 32 + 12;    // add len to LSB (header + 3 DWORD payload)
-
-      CMDfchs->d_id |= 0x85000000L;  // R_CTL = 85 for BASIC ReJecT
-                   // f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
-                   // TYPE[31-24] 00 Basic Link Service
-      CMDfchs->f_ctl = 0x00910000L;  // xchnge responder, last seq, xfer SI
-                   // CMDfchs->seq_id & count might be set from DataHdr?
-      CMDfchs->ro = 0x0L;    // relative offset (n/a)
-      Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 5; // seconds
-                        // (Timeout in case of weird error)
-      
-      CMDfchs->ox_rx_id = InFCHS->ox_rx_id; // copy from sender!
-      
-      // now set the ReJecT payload...
-      ba_rjt = (BA_RJT_PAYLOAD*)&CMDfchs->pl[0];
-      memset( ba_rjt, 0, sizeof( BA_RJT_PAYLOAD));
-
-      // We expect that a "target" task couldn't find the Exhange in the
-      // array of active exchanges, so we use a new LinkService X_ID.
-      // See Reject payload description in FC-PH (Rev 4.3), pg. 140
-      ba_rjt->reason_code = 0x09; // "unable to perform command request"
-      ba_rjt->reason_explain = 0x03; // invalid OX/RX ID pair
-
-
-      break;
-    
-    
-    case BLS_ABTS:   // FC defined basic link service command ABTS 
-                     // Abort Sequence
-                     
-
-      *pIRB_flags = 0;      // clear IRB flags
-      IRB_flags.SFA = 1;    // send SFS (not SEST index)
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      SfsLen += 32L;        // add len to LSB (header only - no payload)
-
-                   // TYPE[31-24] 00 Basic Link Service
-                   // f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
-      CMDfchs->d_id |= 0x81000000L;  // R_CTL = 81 for ABTS
-      CMDfchs->f_ctl = 0x00110000L;  // xchnge originator, last seq, xfer SI
-                   // CMDfchs->seq_id & count might be set from DataHdr?
-      CMDfchs->ro = 0x0L;    // relative offset (n/a)
-      Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 2; // seconds
-                        // (ABTS must timeout when responder is gone)
-      break;
-
-    
-    
-    case FCS_NSR:    // Fabric Name Service Request
-       Exchanges->fcExchange[ *fcExchangeIndex].reTries = 2;
-
-
-      Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 2; // seconds
-                         // OX_ID, linked to Driver Transaction ID
-                         // (fix-up at Queing time)
-      CMDfchs->ox_rx_id = 0xFFFF; // RX_ID - Responder (target) to modify
-                                    // OX_ID set at ERQueing time
-      *pIRB_flags = 0;      // clear IRB flags
-      IRB_flags.SFA = 1;    // send SFS (not SEST index)
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      SfsLen += (32L + sizeof(NSR_PL)); // add len (header & NSR payload)
-
-      CMDfchs->d_id |= 0x02000000L;  // R_CTL = 02 for -
-                                   // Name Service Request: Unsolicited 
-                   // TYPE[31-24] 01 Extended Link Service
-                   // f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
-      CMDfchs->f_ctl = 0x20210000L;
-                   // OX_ID will be fixed-up at Tachyon enqueing time
-      CMDfchs->seq_cnt = 0; // seq ID, DF_ctl, seq cnt
-      CMDfchs->ro = 0x0L;    // relative offset (n/a)
-
-      BuildLinkServicePayload( fcChip, type, &CMDfchs->pl[0]);
-
-   
-    
-    
-    
-    
-      break;
-    
-    
-    
-    
-    case ELS_PLOGI:  // FC-PH extended link service command Port Login
-      // (May, 2000)
-      // NOTE! This special case facilitates SANMark testing.  The SANMark
-      // test script for initialization-timeout.fcal.SANMark-1.fc
-      // "eats" the OPN() primitive without issuing an R_RDY, causing
-      // Tachyon to report LST (loop state timeout), which causes a
-      // LIP.  To avoid this, simply send out the frame (i.e. assuming a
-      // buffer credit of 1) without waiting for R_RDY.  Many FC devices
-      // (other than Tachyon) have been doing this for years.  We don't
-      // ever want to do this for non-Link Service frames unless the
-      // other device really did report non-zero login BB credit (i.e.
-      // in the PLOGI ACCept frame).
-//      CMDfchs->sof_eof |= 0x00000400L;  // LCr=1
-    
-    case ELS_FDISC:  // Fabric Discovery (Login)
-    case ELS_FLOGI:  // Fabric Login
-    case ELS_SCR:    // Fabric State Change Registration
-    case ELS_LOGO:   // FC-PH extended link service command Port Logout
-    case ELS_PDISC:  // FC-PH extended link service cmnd Port Discovery
-    case ELS_PRLI:   // FC-PH extended link service cmnd Process Login
-
-      Exchanges->fcExchange[ *fcExchangeIndex].reTries = 2;
-
-
-      Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 2; // seconds
-                         // OX_ID, linked to Driver Transaction ID
-                         // (fix-up at Queing time)
-      CMDfchs->ox_rx_id = 0xFFFF; // RX_ID - Responder (target) to modify
-                                    // OX_ID set at ERQueing time
-      *pIRB_flags = 0;      // clear IRB flags
-      IRB_flags.SFA = 1;    // send SFS (not SEST index)
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      if( type == ELS_LOGO )
-        SfsLen += (32L + 16L); //  add len (header & PLOGI payload)
-      else if( type == ELS_PRLI )
-        SfsLen += (32L + 20L); //  add len (header & PRLI payload)
-      else if( type == ELS_SCR )
-        SfsLen += (32L + sizeof(SCR_PL)); //  add len (header & SCR payload)
-      else
-        SfsLen += (32L + 116L); //  add len (header & PLOGI payload)
-
-      CMDfchs->d_id |= 0x22000000L;  // R_CTL = 22 for -
-                                   // Extended Link_Data: Unsolicited Control
-                   // TYPE[31-24] 01 Extended Link Service
-                   // f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
-      CMDfchs->f_ctl = 0x01210000L;
-                   // OX_ID will be fixed-up at Tachyon enqueing time
-      CMDfchs->seq_cnt = 0; // seq ID, DF_ctl, seq cnt
-      CMDfchs->ro = 0x0L;    // relative offset (n/a)
-
-      BuildLinkServicePayload( fcChip, type, &CMDfchs->pl[0]);
-
-      break;
-
-
-
-    case ELS_LOGO_ACC: // FC-PH extended link service logout accept
-    case ELS_RJT:          // extended link service reject (add reason)
-    case ELS_ACC:      // ext. link service generic accept
-    case ELS_PLOGI_ACC:// ext. link service login accept (PLOGI or PDISC)
-    case ELS_PRLI_ACC: // ext. link service process login accept
-
-
-      Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 1; // assume done
-                // ensure unique X_IDs! (use tracking function)
-                // OX_ID from initiator cmd
-      ox_ID = (USHORT)(InFCHS->ox_rx_id >> 16); 
-      rx_ID = 0xFFFF; // RX_ID, linked to Driver Exchange ID
-
-      *pIRB_flags = 0;      // clear IRB flags
-      IRB_flags.SFA = 1;    // send SFS (not SEST index)
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      if( type == ELS_RJT )
-      {
-        SfsLen += (32L + 8L); //  add len (header + payload)
-
-        // ELS_RJT reason codes (utilize unused "reserved" field)
-        CMDfchs->pl[0] = 1;
-        CMDfchs->pl[1] = InFCHS->reserved;  
-          
-      }
-      else if( (type == ELS_LOGO_ACC) || (type == ELS_ACC)  )
-        SfsLen += (32L + 4L); //  add len (header + payload)
-      else if( type == ELS_PLOGI_ACC )
-        SfsLen += (32L + 116L); //  add len (header + payload)
-      else if( type == ELS_PRLI_ACC )
-        SfsLen += (32L + 20L); //  add len (header + payload)
-
-      CMDfchs->d_id |= 0x23000000L;  // R_CTL = 23 for -
-                                   // Extended Link_Data: Control Reply
-                   // TYPE[31-24] 01 Extended Link Service
-                   // f_ctl[23:0] exchg responder, last seq, e_s, tsi
-      CMDfchs->f_ctl = 0x01990000L;
-      CMDfchs->seq_cnt = 0x0L;
-      CMDfchs->ox_rx_id = 0L;        // clear
-      CMDfchs->ox_rx_id = ox_ID; // load upper 16 bits
-      CMDfchs->ox_rx_id <<= 16;      // shift them
-
-      CMDfchs->ro = 0x0L;    // relative offset (n/a)
-
-      BuildLinkServicePayload( fcChip, type, &CMDfchs->pl[0]);
-
-      break;
-
-
-                         // Fibre Channel SCSI 'originator' sequences...
-                         // (originator means 'initiator' in FCP-SCSI)
-
-    case SCSI_IWE: // TachLite Initiator Write Entry
-    {
-      PFC_LOGGEDIN_PORT pLoggedInPort = 
-        Exchanges->fcExchange[ *fcExchangeIndex].pLoggedInPort;
-
-      Exchanges->fcExchange[ *fcExchangeIndex].reTries = 1;
-      Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 7; // FC2 timeout
-                       
-      // first, build FCP_CMND
-      // unique X_ID fix-ups in StartExchange 
-
-      *pIRB_flags = 0;      // clear IRB flags
-      IRB_flags.SFA = 1;    // send SFS FCP-CMND (not SEST index)
-
-      // NOTE: unlike FC LinkService login frames, normal
-      // SCSI commands are sent without outgoing verification
-      IRB_flags.DCM = 1;    // Disable completion message for Cmnd frame
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      SfsLen += 64L;        // add len to LSB (header & CMND payload)
-
-      CMDfchs->d_id |= (0x06000000L);  // R_CTL = 6 for command
-
-                   // TYPE[31-24] 8 for FCP SCSI
-                   // f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
-                   //             valid RO
-      CMDfchs->f_ctl = 0x08210008L;
-      CMDfchs->seq_cnt = 0x0L;
-      CMDfchs->ox_rx_id = 0L;        // clear for now (-or- in later)
-      CMDfchs->ro = 0x0L;    // relative offset (n/a)
-
-                   // now, fill out FCP-DATA header
-                   // (use buffer inside SEST object)
-      dataHDR = &fcChip->SEST->DataHDR[ *fcExchangeIndex ];
-      dataHDR->reserved = 0L; // must clear
-      dataHDR->sof_eof = 0x75002000L;  // SOFi3:EOFn  no UAM; no CLS, noLCr, no TS
-      dataHDR->d_id = (InFCHS->s_id | 0x01000000L); // R_CTL= FCP_DATA
-      dataHDR->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0
-                   // TYPE[31-24] 8 for FCP SCSI
-                   // f_ctl[23:0] xfer S.I.| valid RO
-      dataHDR->f_ctl = 0x08010008L;
-      dataHDR->seq_cnt = 0x02000000L;  // sequence ID: df_ctl : seqence count
-      dataHDR->ox_rx_id = 0L;        // clear; fix-up dataHDR fields later
-      dataHDR->ro = 0x0L;    // relative offset (n/a)
-
-                   // Now setup the SEST entry
-      pIWE = &fcChip->SEST->u[ *fcExchangeIndex ].IWE;
-      
-                   // fill out the IWE:
-
-                // VALid entry:Dir outbound:DCM:enable CM:enal INT: FC frame len
-      pIWE->Hdr_Len = 0x8e000020L; // data frame Len always 32 bytes
-      
-      
-      // from login parameters with other port, what's the largest frame
-      // we can send? 
-      if( pLoggedInPort == NULL) 
-      {
-	ulStatus = INVALID_ARGS;  // failed! give up
-	break;
-      }
-      if( pLoggedInPort->rx_data_size  >= 2048)
-        fl = 0x00020000;  // 2048 code (only support 1024!)
-      else if( pLoggedInPort->rx_data_size  >= 1024)
-        fl = 0x00020000;  // 1024 code
-      else if( pLoggedInPort->rx_data_size  >= 512)
-        fl = 0x00010000;  // 512 code
-      else
-	fl = 0;  // 128 bytes -- should never happen
-      
-      
-      pIWE->Hdr_Len |= fl; // add xmit FC frame len for data phase
-      pIWE->Hdr_Addr = fcChip->SEST->base + 
-		((unsigned long)&fcChip->SEST->DataHDR[*fcExchangeIndex] - 
-			(unsigned long)fcChip->SEST);
-
-      pIWE->RSP_Len = sizeof(TachFCHDR_RSP) ; // hdr+data (recv'd RSP frame)
-      pIWE->RSP_Len |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID
-      
-      memset( &fcChip->SEST->RspHDR[ *fcExchangeIndex].pl, 0, 
-        sizeof( FCP_STATUS_RESPONSE) );  // clear out previous status
- 
-      pIWE->RSP_Addr = fcChip->SEST->base + 
-		((unsigned long)&fcChip->SEST->RspHDR[*fcExchangeIndex] - 
-			(unsigned long)fcChip->SEST);
-
-                   // Do we need local or extended gather list?
-                   // depends on size - we can handle 3 len/addr pairs
-                   // locally.
-
-      fcp_dl = build_SEST_sgList( 
-	cpqfcHBAdata->PciDev,
-        &pIWE->GLen1, 
-        Cmnd,       // S/G list
-        &sgPairs,   // return # of pairs in S/G list (from "Data" descriptor)
-        &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later)
-
-      if( !fcp_dl ) // error building S/G list?
-      {
-        ulStatus = MEMPOOL_FAIL;
-        break;      // give up
-      }
-
-                             // Now that we know total data length in
-                             // the passed S/G buffer, set FCP CMND frame
-      build_FCP_payload( Cmnd, (UCHAR*)&CMDfchs->pl[0], type, fcp_dl );
-
-
-      
-      if( sgPairs > 3 )  // need extended s/g list
-        pIWE->Buff_Off = 0x78000000L; // extended data | (no offset)
-      else               // local data pointers (in SEST)
-        pIWE->Buff_Off = 0xf8000000L; // local data | (no offset)
-
-                              // ULONG 5
-      pIWE->Link = 0x0000ffffL;   // Buff_Index | Link
-
-      pIWE->RX_ID = 0x0L;     // DWord 6: RX_ID set by target XFER_RDY
-
-                                      // DWord 7
-      pIWE->Data_Len = 0L;    // TL enters rcv'd XFER_RDY BURST_LEN
-      pIWE->Exp_RO = 0L;      // DWord 8
-                              // DWord 9
-      pIWE->Exp_Byte_Cnt = fcp_dl;  // sum of gather buffers
-    }
-    break;
-
-
-
-
-
-    case SCSI_IRE: // TachLite Initiator Read Entry
-
-      if( Cmnd->timeout != 0)
-      {
-//	printk("Cmnd->timeout %d\n", Cmnd->timeout);
-	// per Linux Scsi
-        Exchanges->fcExchange[ *fcExchangeIndex].timeOut = Cmnd->timeout;
-      }
-      else  // use our best guess, based on FC & device
-      {
-
-        if( Cmnd->SCp.Message == 1 ) // Tape device? (from INQUIRY)	
-	{
-	  // turn off our timeouts (for now...)
-          Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 0xFFFFFFFF; 
-	}
+	if (type == SCSI_IRE || type == SCSI_TRE || type == SCSI_IWE || type == SCSI_TWE)
+		FCP_SCSI_command = 1;
 	else
-	{
-          Exchanges->fcExchange[ *fcExchangeIndex].reTries = 1;
-          Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 7; // per SCSI req.
-	}
-      }
-
-  
-      // first, build FCP_CMND
-
-
-      *pIRB_flags = 0;      // clear IRB flags
-      IRB_flags.SFA = 1;    // send SFS FCP-CMND (not SEST index)
-                            // NOTE: unlike FC LinkService login frames,
-                            // normal SCSI commands are sent "open loop"
-      IRB_flags.DCM = 1;    // Disable completion message for Cmnd frame
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      SfsLen += 64L;        // add len to LSB (header & CMND payload)
-
-      CMDfchs->d_id |= (0x06000000L);  // R_CTL = 6 for command
-
-             // TYPE[31-24] 8 for FCP SCSI
-             // f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
-             //             valid RO
-      CMDfchs->f_ctl = 0x08210008L;
-      CMDfchs->seq_cnt = 0x0L;
-      // x_ID & data direction bit set later
-      CMDfchs->ox_rx_id = 0xFFFF;        // clear
-      CMDfchs->ro = 0x0L;    // relative offset (n/a)
-
-
-
-                   // Now setup the SEST entry
-      pIRE = &fcChip->SEST->u[ *fcExchangeIndex ].IRE;
-
-      // fill out the IRE:
-      // VALid entry:Dir outbound:enable CM:enal INT:
-      pIRE->Seq_Accum = 0xCE000000L; // VAL,DIR inbound,DCM| INI,DAT,RSP
-
-      pIRE->reserved = 0L;
-      pIRE->RSP_Len = sizeof(TachFCHDR_RSP) ; // hdr+data (recv'd RSP frame)
-      pIRE->RSP_Len |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID
-
-      pIRE->RSP_Addr = fcChip->SEST->base + 
-		((unsigned long)&fcChip->SEST->RspHDR[*fcExchangeIndex] - 
-			(unsigned long)fcChip->SEST);
-      
-                   // Do we need local or extended gather list?
-                   // depends on size - we can handle 3 len/addr pairs
-                   // locally.
-
-      fcp_dl = build_SEST_sgList( 
-	cpqfcHBAdata->PciDev,
-        &pIRE->SLen1, 
-        Cmnd,       // SCSI command Data desc. with S/G list
-        &sgPairs,   // return # of pairs in S/G list (from "Data" descriptor)
-        &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later)
-      
-      
-      if( !fcp_dl ) // error building S/G list?
-      {
-	// It is permissible to have a ZERO LENGTH Read command.
-	// If there is the case, simply set fcp_dl (and Exp_Byte_Cnt)
-	// to 0 and continue.
-	if( Cmnd->request_bufflen == 0 )
-	{
-	  fcp_dl = 0; // no FC DATA frames expected
+		FCP_SCSI_command = 0;
 
+	// for commands that pass payload data (e.g. SCSI write)
+	// examine command struct - verify that the
+	// length of s/g buffers is adequate for total payload
+	// length (end of list is NULL address)
+
+	if (FCP_SCSI_command) {
+		if (Data)	// must have data descriptor (S/G list -- at least
+			// one address with at least 1 byte of data)
+		{
+			// something to do (later)?
+		}
+		else
+			return INVALID_ARGS;	// invalid DATA ptr
 	}
-	else
-	{
-          ulStatus = MEMPOOL_FAIL;
-          break;      // give up
-	}
-      }
-
-      // now that we know the S/G length, build CMND payload
-      build_FCP_payload( Cmnd, (UCHAR*)&CMDfchs->pl[0], type, fcp_dl );
-
-      
-      if( sgPairs > 3 )  // need extended s/g list
-        pIRE->Buff_Off = 0x00000000; // DWord 4: extended s/g list, no offset
-      else
-        pIRE->Buff_Off = 0x80000000; // local data, no offset
-      
-      pIRE->Buff_Index = 0x0L;    // DWord 5: Buff_Index | Reserved
-
-      pIRE->Exp_RO  = 0x0L;       // DWord 6: Expected Rel. Offset
-
-      pIRE->Byte_Count = 0;  // DWord 7: filled in by TL on err
-      pIRE->reserved_ = 0;   // DWord 8: reserved
-                             // NOTE: 0 length READ is OK.
-      pIRE->Exp_Byte_Cnt = fcp_dl;// DWord 9: sum of scatter buffers
-      
-      break;
-
-
-
-
-                         // Fibre Channel SCSI 'responder' sequences...
-                         // (originator means 'target' in FCP-SCSI)
-    case SCSI_TWE: // TachLite Target Write Entry
-
-      Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 10; // per SCSI req.
-
-                       // first, build FCP_CMND
-
-      *pIRB_flags = 0;      // clear IRB flags
-      IRB_flags.SFA = 1;    // send SFS (XFER_RDY)
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      SfsLen += (32L + 12L);// add SFS len (header & XFER_RDY payload)
-
-      CMDfchs->d_id |= (0x05000000L);  // R_CTL = 5 for XFER_RDY
-
-                   // TYPE[31-24] 8 for FCP SCSI
-                   // f_ctl[23:0] exchg responder, 1st seq, xfer S.I.
-                //             valid RO
-      CMDfchs->f_ctl = 0x08810008L;
-      CMDfchs->seq_cnt = 0x01000000; // sequence ID: df_ctl: sequence count
-                       // use originator (other port's) OX_ID
-      CMDfchs->ox_rx_id = InFCHS->ox_rx_id;     // we want upper 16 bits
-      CMDfchs->ro = 0x0L;    // relative offset (n/a)
-
-                   // now, fill out FCP-RSP header
-                   // (use buffer inside SEST object)
-
-      rspHDR = &fcChip->SEST->RspHDR[ *fcExchangeIndex ];
-      rspHDR->reserved = 0L; // must clear
-      rspHDR->sof_eof = 0x75000000L;  // SOFi3:EOFn  no UAM; no CLS, noLCr, no TS
-      rspHDR->d_id = (InFCHS->s_id | 0x07000000L); // R_CTL= FCP_RSP
-      rspHDR->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0
-                   // TYPE[31-24] 8 for FCP SCSI
-                   // f_ctl[23:0] responder|last seq| xfer S.I.
-      rspHDR->f_ctl = 0x08910000L;
-      rspHDR->seq_cnt = 0x03000000;  // sequence ID
-      rspHDR->ox_rx_id = InFCHS->ox_rx_id; // gives us OX_ID
-      rspHDR->ro = 0x0L;    // relative offset (n/a)
-
-
-                   // Now setup the SEST entry
-                   
-      pTWE = &fcChip->SEST->u[ *fcExchangeIndex ].TWE;
-
-      // fill out the TWE:
-
-      // VALid entry:Dir outbound:enable CM:enal INT:
-      pTWE->Seq_Accum = 0xC4000000L;  // upper word flags
-      pTWE->reserved = 0L;
-      pTWE->Remote_Node_ID = 0L; // no more auto RSP frame! (TL/TS change)
-      pTWE->Remote_Node_ID |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID
-      
-
-                   // Do we need local or extended gather list?
-                   // depends on size - we can handle 3 len/addr pairs
-                   // locally.
-
-      fcp_dl = build_SEST_sgList( 
-	cpqfcHBAdata->PciDev,
-        &pTWE->SLen1, 
-        Cmnd,       // S/G list
-        &sgPairs,   // return # of pairs in S/G list (from "Data" descriptor)
-        &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later)
-      
-      
-      if( !fcp_dl ) // error building S/G list?
-      {
-        ulStatus = MEMPOOL_FAIL;
-        break;      // give up
-      }
-
-      // now that we know the S/G length, build CMND payload
-      build_FCP_payload( Cmnd, (UCHAR*)&CMDfchs->pl[0], type, fcp_dl );
-
-      
-      if( sgPairs > 3 )  // need extended s/g list
-        pTWE->Buff_Off = 0x00000000; // extended s/g list, no offset
-      else
-        pTWE->Buff_Off = 0x80000000; // local data, no offset
-      
-      pTWE->Buff_Index = 0;     // Buff_Index | Link
-      pTWE->Exp_RO = 0;
-      pTWE->Byte_Count = 0;  // filled in by TL on err
-      pTWE->reserved_ = 0;
-      pTWE->Exp_Byte_Cnt = fcp_dl;// sum of scatter buffers
-      
-      break;
-
-
-
-
-
-
-    case SCSI_TRE: // TachLite Target Read Entry
-
-      // It doesn't make much sense for us to "time-out" a READ,
-      // but we'll use it for design consistency and internal error recovery.
-      Exchanges->fcExchange[ *fcExchangeIndex].timeOut = 10; // per SCSI req.
-
-      // I/O request block settings...
-      *pIRB_flags = 0;      // clear IRB flags
-                                  // check PRLI (process login) info
-                                  // to see if Initiator Requires XFER_RDY
-                                  // if not, don't send one!
-                                  // { PRLI check...}
-      IRB_flags.SFA = 0;    // don't send XFER_RDY - start data
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      SfsLen += (32L + 12L);// add SFS len (header & XFER_RDY payload)
-
 
-      
-      // now, fill out FCP-DATA header
-                   // (use buffer inside SEST object)
-      dataHDR = &fcChip->SEST->DataHDR[ *fcExchangeIndex ];
-
-      dataHDR->reserved = 0L; // must clear
-      dataHDR->sof_eof = 0x75000000L;  // SOFi3:EOFn no UAM; no CLS,noLCr,no TS
-      dataHDR->d_id = (InFCHS->s_id | 0x01000000L); // R_CTL= FCP_DATA
-      dataHDR->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0
-
-
-                   // TYPE[31-24] 8 for FCP SCSI
-                   // f_ctl[23:0] exchg responder, not 1st seq, xfer S.I.
-                   //             valid RO
-      dataHDR->f_ctl = 0x08810008L;
-      dataHDR->seq_cnt = 0x01000000;  // sequence ID (no XRDY)
-      dataHDR->ox_rx_id = InFCHS->ox_rx_id & 0xFFFF0000; // we want upper 16 bits
-      dataHDR->ro = 0x0L;    // relative offset (n/a)
-
-                   // now, fill out FCP-RSP header
-                   // (use buffer inside SEST object)
-      rspHDR = &fcChip->SEST->RspHDR[ *fcExchangeIndex ];
-
-      rspHDR->reserved = 0L; // must clear
-      rspHDR->sof_eof = 0x75000000L;  // SOFi3:EOFn  no UAM; no CLS, noLCr, no TS
-      rspHDR->d_id = (InFCHS->s_id | 0x07000000L); // R_CTL= FCP_RSP
-      rspHDR->s_id = fcChip->Registers.my_al_pa; // CS_CTL = 0
-                   // TYPE[31-24] 8 for FCP SCSI
-                   // f_ctl[23:0] responder|last seq| xfer S.I.
-      rspHDR->f_ctl = 0x08910000L;
-      rspHDR->seq_cnt = 0x02000000;  // sequence ID: df_ctl: sequence count
-
-      rspHDR->ro = 0x0L;    // relative offset (n/a)
-
-
-      // Now setup the SEST entry
-      pTRE = &fcChip->SEST->u[ *fcExchangeIndex ].TRE;
-
-
-      // VALid entry:Dir outbound:enable CM:enal INT:
-      pTRE->Hdr_Len = 0x86010020L; // data frame Len always 32 bytes
-      pTRE->Hdr_Addr =  // bus address of dataHDR;
-            fcChip->SEST->base + 
-		((unsigned long)&fcChip->SEST->DataHDR[ *fcExchangeIndex ] -
-			(unsigned long)fcChip->SEST);
-	
-      pTRE->RSP_Len = 64L; // hdr+data (TL assisted RSP frame)
-      pTRE->RSP_Len |= (InFCHS->s_id << 8); // MS 24 bits Remote_ID
-      pTRE->RSP_Addr = // bus address of rspHDR
-		fcChip->SEST->base + 
-			((unsigned long)&fcChip->SEST->RspHDR[ *fcExchangeIndex ] -
-				(unsigned long)fcChip->SEST);
-
-                   // Do we need local or extended gather list?
-                   // depends on size - we can handle 3 len/addr pairs
-                   // locally.
-
-      fcp_dl = build_SEST_sgList( 
-	cpqfcHBAdata->PciDev,
-        &pTRE->GLen1, 
-        Cmnd,       // S/G list
-        &sgPairs,   // return # of pairs in S/G list (from "Data" descriptor)
-        &fcChip->SEST->sgPages[ *fcExchangeIndex ]);// (for Freeing later)
-      
-      
-      if( !fcp_dl ) // error building S/G list?
-      {
-        ulStatus = MEMPOOL_FAIL;
-        break;      // give up
-      }
-
-      // no payload or command to build -- READ doesn't need XRDY
-
-      
-      if( sgPairs > 3 )  // need extended s/g list
-        pTRE->Buff_Off = 0x78000000L; // extended data | (no offset)
-      else               // local data pointers (in SEST)
-        pTRE->Buff_Off = 0xf8000000L; // local data | (no offset)
-
-                                            // ULONG 5
-      pTRE->Buff_Index = 0L;   // Buff_Index | reserved
-      pTRE->reserved = 0x0L;   // DWord 6
-
-                                     // DWord 7: NOTE: zero length will
-                                     // hang TachLite!
-      pTRE->Data_Len = fcp_dl; // e.g. sum of scatter buffers
-
-      pTRE->reserved_ = 0L;     // DWord 8
-      pTRE->reserved__ = 0L;    // DWord 9
-
-      break;
+	// we can build an Exchange for later Queuing (on the TL chip)
+	// if an empty slot is available in the DevExt for this controller
+	// look for available Exchange slot...
 
+	if (type != FCP_RESPONSE && type != BLS_ABTS && type != BLS_ABTS_ACC)	// already have Exchange slot!
+		*fcExchangeIndex = FindFreeExchange(fcChip, type);
 
+	if (*fcExchangeIndex != -1)	// Exchange is available?
+	{
+		// assign tmp ptr (shorthand)
+		CMDfchs = &Exchanges->fcExchange[*fcExchangeIndex].fchs;
 
+		if (Cmnd != NULL)	// (necessary for ABTS cases)
+		{
+			Exchanges->fcExchange[*fcExchangeIndex].Cmnd = Cmnd;	// Linux Scsi
+			Exchanges->fcExchange[*fcExchangeIndex].pLoggedInPort = fcFindLoggedInPort(fcChip, Exchanges->fcExchange[*fcExchangeIndex].Cmnd,	// find 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
+		}
 
+		// Build the command frame header (& data) according
+		// to command type
 
-    
-
-    case FCP_RESPONSE: 
-                  // Target response frame: this sequence uses an OX/RX ID
-                  // pair from a completed SEST exchange.  We built most
-                  // of the response frame when we created the TWE/TRE.
-
-      *pIRB_flags = 0;      // clear IRB flags
-      IRB_flags.SFA = 1;    // send SFS (RSP)
-      SfsLen = *pIRB_flags;
-
-      SfsLen <<= 24;        // shift flags to MSB
-      SfsLen += sizeof(TachFCHDR_RSP);// add SFS len (header & RSP payload)
-      
-
-      Exchanges->fcExchange[ *fcExchangeIndex].type = 
-        FCP_RESPONSE; // change Exchange type to "response" phase
-
-      // take advantage of prior knowledge of OX/RX_ID pair from
-      // previous XFER outbound frame (still in fchs of exchange)
-      fcChip->SEST->RspHDR[ *fcExchangeIndex ].ox_rx_id = 
-        CMDfchs->ox_rx_id;
-
-      // Check the status of the DATA phase of the exchange so we can report
-      // status to the initiator
-      buildFCPstatus( fcChip, *fcExchangeIndex); // set RSP payload fields
-
-      memcpy(
-        CMDfchs,  // re-use same XFER fchs for Response frame
-        &fcChip->SEST->RspHDR[ *fcExchangeIndex ],
-        sizeof( TachFCHDR_RSP ));
-      
-        
-      break;
+		// fields common for all SFS frame types
+		CMDfchs->reserved = 0L;	// must clear
+		CMDfchs->sof_eof = 0x75000000L;	// SOFi3:EOFn  no UAM; LCr=0, no TS
+
+		// get the destination port_id from incoming FCHS
+		// (initialized before calling if we're Originator)
+		// Frame goes to port it was from - the source_id
+
+		CMDfchs->d_id = InFCHS->s_id & 0xFFFFFF;	// destination (add R_CTL later)
+		CMDfchs->s_id = fcChip->Registers.my_al_pa;	// CS_CTL = 0
+
+		// now enter command-specific fields
+		switch (type) {
+		case BLS_NOP:	// FC defined basic link service command NO-OP
+			// ensure unique X_IDs! (use tracking function)
+			*pIRB_flags = 0;	// clear IRB flags
+			IRB_flags.SFA = 1;	// send SFS (not SEST index)
+			SfsLen = *pIRB_flags;
+
+			SfsLen <<= 24;	// shift flags to MSB
+			SfsLen += 32L;	// add len to LSB (header only - no payload)
+
+			// TYPE[31-24] 00 Basic Link Service
+			// f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
+			CMDfchs->d_id |= 0x80000000L;	// R_CTL = 80 for NOP (Basic Link Ser.)
+			CMDfchs->f_ctl = 0x00310000L;	// xchng originator, 1st seq,....
+			CMDfchs->seq_cnt = 0x0L;
+			CMDfchs->ox_rx_id = 0xFFFF;	// RX_ID for now; OX_ID on start
+			CMDfchs->ro = 0x0L;	// relative offset (n/a)
+			CMDfchs->pl[0] = 0xaabbccddL;	// words 8-15 frame data payload (n/a)
+			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 1;	// seconds
+			// (NOP should complete ~instantly)
+			break;
+
+		case BLS_ABTS_ACC:	// Abort Sequence ACCept
+			*pIRB_flags = 0;	// clear IRB flags
+			IRB_flags.SFA = 1;	// send SFS (not SEST index)
+			SfsLen = *pIRB_flags;
+
+			SfsLen <<= 24;	// shift flags to MSB
+			SfsLen += 32 + 12;	// add len to LSB (header + 3 DWORD payload)
+
+			CMDfchs->d_id |= 0x84000000L;	// R_CTL = 84 for BASIC ACCept
+			// TYPE[31-24] 00 Basic Link Service
+			// f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
+			CMDfchs->f_ctl = 0x00910000L;	// xchnge responder, last seq, xfer SI
+			// CMDfchs->seq_id & count might be set from DataHdr?
+			CMDfchs->ro = 0x0L;	// relative offset (n/a)
+			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 5;	// seconds
+			// (Timeout in case of weird error)
+
+			// now set the ACCept payload...
+			ba_acc = (BA_ACC_PAYLOAD *) & CMDfchs->pl[0];
+			memset(ba_acc, 0, sizeof(BA_ACC_PAYLOAD));
+			// Since PLDA requires (only) entire Exchange aborts, we don't need
+			// to worry about what the last sequence was.
+
+			// We expect that a "target" task is accepting the abort, so we
+			// can use the OX/RX ID pair 
+			ba_acc->ox_rx_id = CMDfchs->ox_rx_id;
+
+			// source, dest, #bytes
+			BigEndianSwap((u8 *) & CMDfchs->ox_rx_id, (u8 *) & ba_acc->ox_rx_id, 4);
+
+			ba_acc->low_seq_cnt = 0;
+			ba_acc->high_seq_cnt = 0xFFFF;
+			break;
+
+		case BLS_ABTS_RJT:	// Abort Sequence ACCept
+			*pIRB_flags = 0;	// clear IRB flags
+			IRB_flags.SFA = 1;	// send SFS (not SEST index)
+			SfsLen = *pIRB_flags;
+
+			SfsLen <<= 24;	// shift flags to MSB
+			SfsLen += 32 + 12;	// add len to LSB (header + 3 DWORD payload)
+
+			CMDfchs->d_id |= 0x85000000L;	// R_CTL = 85 for BASIC ReJecT
+			// f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
+			// TYPE[31-24] 00 Basic Link Service
+			CMDfchs->f_ctl = 0x00910000L;	// xchnge responder, last seq, xfer SI
+			// CMDfchs->seq_id & count might be set from DataHdr?
+			CMDfchs->ro = 0x0L;	// relative offset (n/a)
+			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 5;	// seconds
+			// (Timeout in case of weird error)
+
+			CMDfchs->ox_rx_id = InFCHS->ox_rx_id;	// copy from sender!
+
+			// now set the ReJecT payload...
+			ba_rjt = (BA_RJT_PAYLOAD *) & CMDfchs->pl[0];
+			memset(ba_rjt, 0, sizeof(BA_RJT_PAYLOAD));
+
+			// We expect that a "target" task couldn't find the Exhange in the
+			// array of active exchanges, so we use a new LinkService X_ID.
+			// See Reject payload description in FC-PH (Rev 4.3), pg. 140
+			ba_rjt->reason_code = 0x09;	// "unable to perform command request"
+			ba_rjt->reason_explain = 0x03;	// invalid OX/RX ID pair
+			break;
+
+		case BLS_ABTS:	// FC defined basic link service command ABTS 
+			// Abort Sequence
+			*pIRB_flags = 0;	// clear IRB flags
+			IRB_flags.SFA = 1;	// send SFS (not SEST index)
+			SfsLen = *pIRB_flags;
+
+			SfsLen <<= 24;	// shift flags to MSB
+			SfsLen += 32L;	// add len to LSB (header only - no payload)
+
+			// TYPE[31-24] 00 Basic Link Service
+			// f_ctl[23:0] exchg originator, not 1st seq, xfer S.I.
+			CMDfchs->d_id |= 0x81000000L;	// R_CTL = 81 for ABTS
+			CMDfchs->f_ctl = 0x00110000L;	// xchnge originator, last seq, xfer SI
+			// CMDfchs->seq_id & count might be set from DataHdr?
+			CMDfchs->ro = 0x0L;	// relative offset (n/a)
+			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 2;	// seconds
+			// (ABTS must timeout when responder is gone)
+			break;
+
+		case FCS_NSR:	// Fabric Name Service Request
+			Exchanges->fcExchange[*fcExchangeIndex].reTries = 2;
+			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 2;	// seconds
+			// OX_ID, linked to Driver Transaction ID
+			// (fix-up at Queing time)
+			CMDfchs->ox_rx_id = 0xFFFF;	// RX_ID - Responder (target) to modify
+			// OX_ID set at ERQueing time
+			*pIRB_flags = 0;	// clear IRB flags
+			IRB_flags.SFA = 1;	// send SFS (not SEST index)
+			SfsLen = *pIRB_flags;
+			SfsLen <<= 24;	// shift flags to MSB
+			SfsLen += (32L + sizeof(NSR_PL));	// add len (header & NSR payload)
+			CMDfchs->d_id |= 0x02000000L;	// R_CTL = 02 for -
+			// Name Service Request: Unsolicited 
+			// TYPE[31-24] 01 Extended Link Service
+			// f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
+			CMDfchs->f_ctl = 0x20210000L;
+			// OX_ID will be fixed-up at Tachyon enqueing time
+			CMDfchs->seq_cnt = 0;	// seq ID, DF_ctl, seq cnt
+			CMDfchs->ro = 0x0L;	// relative offset (n/a)
+			BuildLinkServicePayload(fcChip, type, &CMDfchs->pl[0]);
+			break;
+
+		case ELS_PLOGI:	// FC-PH extended link service command Port Login
+			// (May, 2000)
+			// NOTE! This special case facilitates SANMark testing.  The SANMark
+			// test script for initialization-timeout.fcal.SANMark-1.fc
+			// "eats" the OPN() primitive without issuing an R_RDY, causing
+			// Tachyon to report LST (loop state timeout), which causes a
+			// LIP.  To avoid this, simply send out the frame (i.e. assuming a
+			// buffer credit of 1) without waiting for R_RDY.  Many FC devices
+			// (other than Tachyon) have been doing this for years.  We don't
+			// ever want to do this for non-Link Service frames unless the
+			// other device really did report non-zero login BB credit (i.e.
+			// in the PLOGI ACCept frame).
+//			CMDfchs->sof_eof |= 0x00000400L;  // LCr=1
+
+		case ELS_FDISC:	// Fabric Discovery (Login)
+		case ELS_FLOGI:	// Fabric Login
+		case ELS_SCR:	// Fabric State Change Registration
+		case ELS_LOGO:	// FC-PH extended link service command Port Logout
+		case ELS_PDISC:	// FC-PH extended link service cmnd Port Discovery
+		case ELS_PRLI:	// FC-PH extended link service cmnd Process Login
+			Exchanges->fcExchange[*fcExchangeIndex].reTries = 2;
+			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 2;	// seconds
+			// OX_ID, linked to Driver Transaction ID
+			// (fix-up at Queing time)
+			CMDfchs->ox_rx_id = 0xFFFF;	// RX_ID - Responder (target) to modify
+			// OX_ID set at ERQueing time
+			*pIRB_flags = 0;	// clear IRB flags
+			IRB_flags.SFA = 1;	// send SFS (not SEST index)
+			SfsLen = *pIRB_flags;
+			SfsLen <<= 24;	// shift flags to MSB
+			if (type == ELS_LOGO)
+				SfsLen += (32L + 16L);	//  add len (header & PLOGI payload)
+			else if (type == ELS_PRLI)
+				SfsLen += (32L + 20L);	//  add len (header & PRLI payload)
+			else if (type == ELS_SCR)
+				SfsLen += (32L + sizeof(SCR_PL));	//  add len (header & SCR payload)
+			else
+				SfsLen += (32L + 116L);	//  add len (header & PLOGI payload)
+
+			CMDfchs->d_id |= 0x22000000L;	// R_CTL = 22 for -
+			// Extended Link_Data: Unsolicited Control
+			// TYPE[31-24] 01 Extended Link Service
+			// f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
+			CMDfchs->f_ctl = 0x01210000L;
+			// OX_ID will be fixed-up at Tachyon enqueing time
+			CMDfchs->seq_cnt = 0;	// seq ID, DF_ctl, seq cnt
+			CMDfchs->ro = 0x0L;	// relative offset (n/a)
+
+			BuildLinkServicePayload(fcChip, type, &CMDfchs->pl[0]);
+			break;
+
+		case ELS_LOGO_ACC:	// FC-PH extended link service logout accept
+		case ELS_RJT:	// extended link service reject (add reason)
+		case ELS_ACC:	// ext. link service generic accept
+		case ELS_PLOGI_ACC:	// ext. link service login accept (PLOGI or PDISC)
+		case ELS_PRLI_ACC:	// ext. link service process login accept
+			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 1;	// assume done
+			// ensure unique X_IDs! (use tracking function)
+			// OX_ID from initiator cmd
+			ox_ID = (u16) (InFCHS->ox_rx_id >> 16);
+			rx_ID = 0xFFFF;	// RX_ID, linked to Driver Exchange ID
+
+			*pIRB_flags = 0;	// clear IRB flags
+			IRB_flags.SFA = 1;	// send SFS (not SEST index)
+			SfsLen = *pIRB_flags;
+
+			SfsLen <<= 24;	// shift flags to MSB
+			if (type == ELS_RJT) {
+				SfsLen += (32L + 8L);	//  add len (header + payload)
+
+				// ELS_RJT reason codes (utilize unused "reserved" field)
+				CMDfchs->pl[0] = 1;
+				CMDfchs->pl[1] = InFCHS->reserved;
+
+			} else if ((type == ELS_LOGO_ACC) || (type == ELS_ACC))
+				SfsLen += (32L + 4L);	//  add len (header + payload)
+			else if (type == ELS_PLOGI_ACC)
+				SfsLen += (32L + 116L);	//  add len (header + payload)
+			else if (type == ELS_PRLI_ACC)
+				SfsLen += (32L + 20L);	//  add len (header + payload)
+
+			CMDfchs->d_id |= 0x23000000L;	// R_CTL = 23 for -
+			// Extended Link_Data: Control Reply
+			// TYPE[31-24] 01 Extended Link Service
+			// f_ctl[23:0] exchg responder, last seq, e_s, tsi
+			CMDfchs->f_ctl = 0x01990000L;
+			CMDfchs->seq_cnt = 0x0L;
+			CMDfchs->ox_rx_id = 0L;	// clear
+			CMDfchs->ox_rx_id = ox_ID;	// load upper 16 bits
+			CMDfchs->ox_rx_id <<= 16;	// shift them
+
+			CMDfchs->ro = 0x0L;	// relative offset (n/a)
+
+			BuildLinkServicePayload(fcChip, type, &CMDfchs->pl[0]);
+			break;
+
+			// Fibre Channel SCSI 'originator' sequences...
+			// (originator means 'initiator' in FCP-SCSI)
+		case SCSI_IWE:	// TachLite Initiator Write Entry
+			{
+				PFC_LOGGEDIN_PORT pLoggedInPort = Exchanges->fcExchange[*fcExchangeIndex].pLoggedInPort;
+
+				Exchanges->fcExchange[*fcExchangeIndex].reTries = 1;
+				Exchanges->fcExchange[*fcExchangeIndex].timeOut = 7;	// FC2 timeout
+
+				// first, build FCP_CMND
+				// unique X_ID fix-ups in StartExchange 
+
+				*pIRB_flags = 0;	// clear IRB flags
+				IRB_flags.SFA = 1;	// send SFS FCP-CMND (not SEST index)
+
+				// NOTE: unlike FC LinkService login frames, normal
+				// SCSI commands are sent without outgoing verification
+				IRB_flags.DCM = 1;	// Disable completion message for Cmnd frame
+				SfsLen = *pIRB_flags;
+
+				SfsLen <<= 24;	// shift flags to MSB
+				SfsLen += 64L;	// add len to LSB (header & CMND payload)
+
+				CMDfchs->d_id |= (0x06000000L);	// R_CTL = 6 for command
+
+				// TYPE[31-24] 8 for FCP SCSI
+				// f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
+				//             valid RO
+				CMDfchs->f_ctl = 0x08210008L;
+				CMDfchs->seq_cnt = 0x0L;
+				CMDfchs->ox_rx_id = 0L;	// clear for now (-or- in later)
+				CMDfchs->ro = 0x0L;	// relative offset (n/a)
+
+				// now, fill out FCP-DATA header
+				// (use buffer inside SEST object)
+				dataHDR = &fcChip->SEST->DataHDR[*fcExchangeIndex];
+				dataHDR->reserved = 0L;	// must clear
+				dataHDR->sof_eof = 0x75002000L;	// SOFi3:EOFn  no UAM; no CLS, noLCr, no TS
+				dataHDR->d_id = (InFCHS->s_id | 0x01000000L);	// R_CTL= FCP_DATA
+				dataHDR->s_id = fcChip->Registers.my_al_pa;	// CS_CTL = 0
+				// TYPE[31-24] 8 for FCP SCSI
+				// f_ctl[23:0] xfer S.I.| valid RO
+				dataHDR->f_ctl = 0x08010008L;
+				dataHDR->seq_cnt = 0x02000000L;	// sequence ID: df_ctl : seqence count
+				dataHDR->ox_rx_id = 0L;	// clear; fix-up dataHDR fields later
+				dataHDR->ro = 0x0L;	// relative offset (n/a)
+
+				// Now setup the SEST entry
+				pIWE = &fcChip->SEST->u[*fcExchangeIndex].IWE;
+
+				// fill out the IWE:
+
+				// VALid entry:Dir outbound:DCM:enable CM:enal INT: FC frame len
+				pIWE->Hdr_Len = 0x8e000020L;	// data frame Len always 32 bytes
+
+
+				// from login parameters with other port, what's the largest frame
+				// we can send? 
+				if (pLoggedInPort == NULL) {
+					ulStatus = INVALID_ARGS;	// failed! give up
+					break;
+				}
+				if (pLoggedInPort->rx_data_size >= 2048)
+					fl = 0x00020000;	// 2048 code (only support 1024!)
+				else if (pLoggedInPort->rx_data_size >= 1024)
+					fl = 0x00020000;	// 1024 code
+				else if (pLoggedInPort->rx_data_size >= 512)
+					fl = 0x00010000;	// 512 code
+				else
+					fl = 0;	// 128 bytes -- should never happen
+
+
+				pIWE->Hdr_Len |= fl;	// add xmit FC frame len for data phase
+				pIWE->Hdr_Addr = fcChip->SEST->base + ((unsigned long) &fcChip->SEST->DataHDR[*fcExchangeIndex] - (unsigned long) fcChip->SEST);
+
+				pIWE->RSP_Len = sizeof(TachFCHDR_RSP);	// hdr+data (recv'd RSP frame)
+				pIWE->RSP_Len |= (InFCHS->s_id << 8);	// MS 24 bits Remote_ID
+
+				memset(&fcChip->SEST->RspHDR[*fcExchangeIndex].pl, 0, sizeof(FCP_STATUS_RESPONSE));	// clear out previous status
+
+				pIWE->RSP_Addr = fcChip->SEST->base + ((unsigned long) &fcChip->SEST->RspHDR[*fcExchangeIndex] - (unsigned long) fcChip->SEST);
+
+				// Do we need local or extended gather list?
+				// depends on size - we can handle 3 len/addr pairs
+				// locally.
+
+				fcp_dl = build_SEST_sgList(dev->PciDev, &pIWE->GLen1, Cmnd,	// S/G list
+							   &sgPairs,	// return # of pairs in S/G list (from "Data" descriptor)
+							   &fcChip->SEST->sgPages[*fcExchangeIndex]);	// (for Freeing later)
+
+				if (!fcp_dl)	// error building S/G list?
+				{
+					ulStatus = MEMPOOL_FAIL;
+					break;	// give up
+				}
+				// Now that we know total data length in
+				// the passed S/G buffer, set FCP CMND frame
+				build_FCP_payload(Cmnd, (u8 *) & CMDfchs->pl[0], type, fcp_dl);
+
+
+
+				if (sgPairs > 3)	// need extended s/g list
+					pIWE->Buff_Off = 0x78000000L;	// extended data | (no offset)
+				else	// local data pointers (in SEST)
+					pIWE->Buff_Off = 0xf8000000L;	// local data | (no offset)
+
+				// u32 5
+				pIWE->Link = 0x0000ffffL;	// Buff_Index | Link
+
+				pIWE->RX_ID = 0x0L;	// DWord 6: RX_ID set by target XFER_RDY
+
+				// DWord 7
+				pIWE->Data_Len = 0L;	// TL enters rcv'd XFER_RDY BURST_LEN
+				pIWE->Exp_RO = 0L;	// DWord 8
+				// DWord 9
+				pIWE->Exp_Byte_Cnt = fcp_dl;	// sum of gather buffers
+			}
+			break;
 
-    default:
-      printk("cpqfcTS: don't know how to build FC type: %Xh(%d)\n", type,type);
-      break;
+		case SCSI_IRE:	// TachLite Initiator Read Entry
+			if (Cmnd->timeout != 0) {
+//      printk("Cmnd->timeout %d\n", Cmnd->timeout);
+				// per Linux Scsi
+				Exchanges->fcExchange[*fcExchangeIndex].timeOut = Cmnd->timeout;
+			} else	// use our best guess, based on FC & device
+			{
+
+				if (Cmnd->SCp.Message == 1)	// Tape device? (from INQUIRY)     
+				{
+					// turn off our timeouts (for now...)
+					Exchanges->fcExchange[*fcExchangeIndex].timeOut = 0xFFFFFFFF;
+				} else {
+					Exchanges->fcExchange[*fcExchangeIndex].reTries = 1;
+					Exchanges->fcExchange[*fcExchangeIndex].timeOut = 7;	// per SCSI req.
+				}
+			}
+			// first, build FCP_CMND
+			*pIRB_flags = 0;	// clear IRB flags
+			IRB_flags.SFA = 1;	// send SFS FCP-CMND (not SEST index)
+			// NOTE: unlike FC LinkService login frames,
+			// normal SCSI commands are sent "open loop"
+			IRB_flags.DCM = 1;	// Disable completion message for Cmnd frame
+			SfsLen = *pIRB_flags;
+
+			SfsLen <<= 24;	// shift flags to MSB
+			SfsLen += 64L;	// add len to LSB (header & CMND payload)
+
+			CMDfchs->d_id |= (0x06000000L);	// R_CTL = 6 for command
+
+			// TYPE[31-24] 8 for FCP SCSI
+			// f_ctl[23:0] exchg originator, 1st seq, xfer S.I.
+			//             valid RO
+			CMDfchs->f_ctl = 0x08210008L;
+			CMDfchs->seq_cnt = 0x0L;
+			// x_ID & data direction bit set later
+			CMDfchs->ox_rx_id = 0xFFFF;	// clear
+			CMDfchs->ro = 0x0L;	// relative offset (n/a)
+			// Now setup the SEST entry
+			pIRE = &fcChip->SEST->u[*fcExchangeIndex].IRE;
+			// fill out the IRE:
+			// VALid entry:Dir outbound:enable CM:enal INT:
+			pIRE->Seq_Accum = 0xCE000000L;	// VAL,DIR inbound,DCM| INI,DAT,RSP
+
+			pIRE->reserved = 0L;
+			pIRE->RSP_Len = sizeof(TachFCHDR_RSP);	// hdr+data (recv'd RSP frame)
+			pIRE->RSP_Len |= (InFCHS->s_id << 8);	// MS 24 bits Remote_ID
+
+			pIRE->RSP_Addr = fcChip->SEST->base + ((unsigned long) &fcChip->SEST->RspHDR[*fcExchangeIndex] - (unsigned long) fcChip->SEST);
+
+			// Do we need local or extended gather list?
+			// depends on size - we can handle 3 len/addr pairs
+			// locally.
+
+			fcp_dl = build_SEST_sgList(dev->PciDev, &pIRE->SLen1, Cmnd,	// SCSI command Data desc. with S/G list
+						   &sgPairs,	// return # of pairs in S/G list (from "Data" descriptor)
+						   &fcChip->SEST->sgPages[*fcExchangeIndex]);	// (for Freeing later)
+
+
+			if (!fcp_dl)	// error building S/G list?
+			{
+				// It is permissible to have a ZERO LENGTH Read command.
+				// If there is the case, simply set fcp_dl (and Exp_Byte_Cnt)
+				// to 0 and continue.
+				if (Cmnd->request_bufflen == 0) {
+					fcp_dl = 0;	// no FC DATA frames expected
+
+				} else {
+					ulStatus = MEMPOOL_FAIL;
+					break;	// give up
+				}
+			}
+			// now that we know the S/G length, build CMND payload
+			build_FCP_payload(Cmnd, (u8 *) & CMDfchs->pl[0], type, fcp_dl);
 
-    }
 
-    
-    
-    if( !ulStatus)  // no errors above?
-    {
-      // FCHS is built; now build IRB
+			if (sgPairs > 3)	// need extended s/g list
+				pIRE->Buff_Off = 0x00000000;	// DWord 4: extended s/g list, no offset
+			else
+				pIRE->Buff_Off = 0x80000000;	// local data, no offset
+
+			pIRE->Buff_Index = 0x0L;	// DWord 5: Buff_Index | Reserved
+
+			pIRE->Exp_RO = 0x0L;	// DWord 6: Expected Rel. Offset
+
+			pIRE->Byte_Count = 0;	// DWord 7: filled in by TL on err
+			pIRE->reserved_ = 0;	// DWord 8: reserved
+			// NOTE: 0 length READ is OK.
+			pIRE->Exp_Byte_Cnt = fcp_dl;	// DWord 9: sum of scatter buffers
+			break;
+
+			// Fibre Channel SCSI 'responder' sequences...
+			// (originator means 'target' in FCP-SCSI)
+		case SCSI_TWE:	// TachLite Target Write Entry
+			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 10;	// per SCSI req.
+			// first, build FCP_CMND
+			*pIRB_flags = 0;	// clear IRB flags
+			IRB_flags.SFA = 1;	// send SFS (XFER_RDY)
+			SfsLen = *pIRB_flags;
+			SfsLen <<= 24;	// shift flags to MSB
+			SfsLen += (32L + 12L);	// add SFS len (header & XFER_RDY payload)
+
+			CMDfchs->d_id |= (0x05000000L);	// R_CTL = 5 for XFER_RDY
+
+			// TYPE[31-24] 8 for FCP SCSI
+			// f_ctl[23:0] exchg responder, 1st seq, xfer S.I.
+			//             valid RO
+			CMDfchs->f_ctl = 0x08810008L;
+			CMDfchs->seq_cnt = 0x01000000;	// sequence ID: df_ctl: sequence count
+			// use originator (other port's) OX_ID
+			CMDfchs->ox_rx_id = InFCHS->ox_rx_id;	// we want upper 16 bits
+			CMDfchs->ro = 0x0L;	// relative offset (n/a)
+
+			// now, fill out FCP-RSP header
+			// (use buffer inside SEST object)
+
+			rspHDR = &fcChip->SEST->RspHDR[*fcExchangeIndex];
+			rspHDR->reserved = 0L;	// must clear
+			rspHDR->sof_eof = 0x75000000L;	// SOFi3:EOFn  no UAM; no CLS, noLCr, no TS
+			rspHDR->d_id = (InFCHS->s_id | 0x07000000L);	// R_CTL= FCP_RSP
+			rspHDR->s_id = fcChip->Registers.my_al_pa;	// CS_CTL = 0
+			// TYPE[31-24] 8 for FCP SCSI
+			// f_ctl[23:0] responder|last seq| xfer S.I.
+			rspHDR->f_ctl = 0x08910000L;
+			rspHDR->seq_cnt = 0x03000000;	// sequence ID
+			rspHDR->ox_rx_id = InFCHS->ox_rx_id;	// gives us OX_ID
+			rspHDR->ro = 0x0L;	// relative offset (n/a)
+			// Now setup the SEST entry
+
+			pTWE = &fcChip->SEST->u[*fcExchangeIndex].TWE;
+			// fill out the TWE:
+
+			// VALid entry:Dir outbound:enable CM:enal INT:
+			pTWE->Seq_Accum = 0xC4000000L;	// upper word flags
+			pTWE->reserved = 0L;
+			pTWE->Remote_Node_ID = 0L;	// no more auto RSP frame! (TL/TS change)
+			pTWE->Remote_Node_ID |= (InFCHS->s_id << 8);	// MS 24 bits Remote_ID
+
+			// Do we need local or extended gather list?
+			// depends on size - we can handle 3 len/addr pairs
+			// locally.
+
+			fcp_dl = build_SEST_sgList(dev->PciDev, &pTWE->SLen1, Cmnd,	// S/G list
+						   &sgPairs,	// return # of pairs in S/G list (from "Data" descriptor)
+						   &fcChip->SEST->sgPages[*fcExchangeIndex]);	// (for Freeing later)
+
+			if (!fcp_dl)	// error building S/G list?
+			{
+				ulStatus = MEMPOOL_FAIL;
+				break;	// give up
+			}
+			// now that we know the S/G length, build CMND payload
+			build_FCP_payload(Cmnd, (u8 *) & CMDfchs->pl[0], type, fcp_dl);
 
-      // link the just built FCHS (the "command") to the IRB entry 
-      // for this Exchange.
-      pIRB = &Exchanges->fcExchange[ *fcExchangeIndex].IRB; 
-    
-                          // len & flags according to command type above
-      pIRB->Req_A_SFS_Len = SfsLen;  // includes IRB flags & len
-      pIRB->Req_A_SFS_Addr = // TL needs physical addr of frame to send
-		fcChip->exch_dma_handle + (unsigned long)CMDfchs - 
-			(unsigned long)Exchanges;
-
-      pIRB->Req_A_SFS_D_ID = CMDfchs->d_id << 8; // Dest_ID must be consistent!
-
-    // Exchange is complete except for "fix-up" fields to be set
-    // at Tachyon Queuing time:
-    //    IRB->Req_A_Trans_ID (OX_ID/ RX_ID):  
-    //        for SEST entry, lower bits correspond to actual FC Exchange ID
-    //    fchs->OX_ID or RX_ID
-    }
-    else
-    {
-#ifdef DBG     
-      printk( "FC Error: SEST build Pool Allocation failed\n");
+			if (sgPairs > 3)	// need extended s/g list
+				pTWE->Buff_Off = 0x00000000;	// extended s/g list, no offset
+			else
+				pTWE->Buff_Off = 0x80000000;	// local data, no offset
+
+			pTWE->Buff_Index = 0;	// Buff_Index | Link
+			pTWE->Exp_RO = 0;
+			pTWE->Byte_Count = 0;	// filled in by TL on err
+			pTWE->reserved_ = 0;
+			pTWE->Exp_Byte_Cnt = fcp_dl;	// sum of scatter buffers
+			break;
+
+		case SCSI_TRE:	// TachLite Target Read Entry
+			// It doesn't make much sense for us to "time-out" a READ,
+			// but we'll use it for design consistency and internal error recovery.
+			Exchanges->fcExchange[*fcExchangeIndex].timeOut = 10;	// per SCSI req.
+			// I/O request block settings...
+			*pIRB_flags = 0;	// clear IRB flags
+			// check PRLI (process login) info
+			// to see if Initiator Requires XFER_RDY
+			// if not, don't send one!
+			// { PRLI check...}
+			IRB_flags.SFA = 0;	// don't send XFER_RDY - start data
+			SfsLen = *pIRB_flags;
+			SfsLen <<= 24;	// shift flags to MSB
+			SfsLen += (32L + 12L);	// add SFS len (header & XFER_RDY payload)
+
+			// now, fill out FCP-DATA header
+			// (use buffer inside SEST object)
+			dataHDR = &fcChip->SEST->DataHDR[*fcExchangeIndex];
+
+			dataHDR->reserved = 0L;	// must clear
+			dataHDR->sof_eof = 0x75000000L;	// SOFi3:EOFn no UAM; no CLS,noLCr,no TS
+			dataHDR->d_id = (InFCHS->s_id | 0x01000000L);	// R_CTL= FCP_DATA
+			dataHDR->s_id = fcChip->Registers.my_al_pa;	// CS_CTL = 0
+
+			// TYPE[31-24] 8 for FCP SCSI
+			// f_ctl[23:0] exchg responder, not 1st seq, xfer S.I.
+			//             valid RO
+			dataHDR->f_ctl = 0x08810008L;
+			dataHDR->seq_cnt = 0x01000000;	// sequence ID (no XRDY)
+			dataHDR->ox_rx_id = InFCHS->ox_rx_id & 0xFFFF0000;	// we want upper 16 bits
+			dataHDR->ro = 0x0L;	// relative offset (n/a)
+
+			// now, fill out FCP-RSP header
+			// (use buffer inside SEST object)
+			rspHDR = &fcChip->SEST->RspHDR[*fcExchangeIndex];
+
+			rspHDR->reserved = 0L;	// must clear
+			rspHDR->sof_eof = 0x75000000L;	// SOFi3:EOFn  no UAM; no CLS, noLCr, no TS
+			rspHDR->d_id = (InFCHS->s_id | 0x07000000L);	// R_CTL= FCP_RSP
+			rspHDR->s_id = fcChip->Registers.my_al_pa;	// CS_CTL = 0
+			// TYPE[31-24] 8 for FCP SCSI
+			// f_ctl[23:0] responder|last seq| xfer S.I.
+			rspHDR->f_ctl = 0x08910000L;
+			rspHDR->seq_cnt = 0x02000000;	// sequence ID: df_ctl: sequence count
+			rspHDR->ro = 0x0L;	// relative offset (n/a)
+
+			// Now setup the SEST entry
+			pTRE = &fcChip->SEST->u[*fcExchangeIndex].TRE;
+
+			// VALid entry:Dir outbound:enable CM:enal INT:
+			pTRE->Hdr_Len = 0x86010020L;	// data frame Len always 32 bytes
+			pTRE->Hdr_Addr =	// bus address of dataHDR;
+			    fcChip->SEST->base + ((unsigned long) &fcChip->SEST->DataHDR[*fcExchangeIndex] - (unsigned long) fcChip->SEST);
+
+			pTRE->RSP_Len = 64L;	// hdr+data (TL assisted RSP frame)
+			pTRE->RSP_Len |= (InFCHS->s_id << 8);	// MS 24 bits Remote_ID
+			pTRE->RSP_Addr =	// bus address of rspHDR
+			    fcChip->SEST->base + ((unsigned long) &fcChip->SEST->RspHDR[*fcExchangeIndex] - (unsigned long) fcChip->SEST);
+
+			// Do we need local or extended gather list?
+			// depends on size - we can handle 3 len/addr pairs
+			// locally.
+
+			fcp_dl = build_SEST_sgList(dev->PciDev, &pTRE->GLen1, Cmnd,	// S/G list
+						   &sgPairs,	// return # of pairs in S/G list (from "Data" descriptor)
+						   &fcChip->SEST->sgPages[*fcExchangeIndex]);	// (for Freeing later)
+
+			if (!fcp_dl)	// error building S/G list?
+			{
+				ulStatus = MEMPOOL_FAIL;
+				break;	// give up
+			}
+			// no payload or command to build -- READ doesn't need XRDY
+			if (sgPairs > 3)	// need extended s/g list
+				pTRE->Buff_Off = 0x78000000L;	// extended data | (no offset)
+			else	// local data pointers (in SEST)
+				pTRE->Buff_Off = 0xf8000000L;	// local data | (no offset)
+
+			// u32 5
+			pTRE->Buff_Index = 0L;	// Buff_Index | reserved
+			pTRE->reserved = 0x0L;	// DWord 6
+
+			// DWord 7: NOTE: zero length will
+			// hang TachLite!
+			pTRE->Data_Len = fcp_dl;	// e.g. sum of scatter buffers
+
+			pTRE->reserved_ = 0L;	// DWord 8
+			pTRE->reserved__ = 0L;	// DWord 9
+
+			break;
+
+		case FCP_RESPONSE:
+			// Target response frame: this sequence uses an OX/RX ID
+			// pair from a completed SEST exchange.  We built most
+			// of the response frame when we created the TWE/TRE.
+
+			*pIRB_flags = 0;	// clear IRB flags
+			IRB_flags.SFA = 1;	// send SFS (RSP)
+			SfsLen = *pIRB_flags;
+
+			SfsLen <<= 24;	// shift flags to MSB
+			SfsLen += sizeof(TachFCHDR_RSP);	// add SFS len (header & RSP payload)
+			Exchanges->fcExchange[*fcExchangeIndex].type = FCP_RESPONSE;	// change Exchange type to "response" phase
+
+			// take advantage of prior knowledge of OX/RX_ID pair from
+			// previous XFER outbound frame (still in fchs of exchange)
+			fcChip->SEST->RspHDR[*fcExchangeIndex].ox_rx_id = CMDfchs->ox_rx_id;
+
+			// Check the status of the DATA phase of the exchange so we can report
+			// status to the initiator
+			buildFCPstatus(fcChip, *fcExchangeIndex);	// set RSP payload fields
+
+			memcpy(CMDfchs,	// re-use same XFER fchs for Response frame
+			       &fcChip->SEST->RspHDR[*fcExchangeIndex], sizeof(TachFCHDR_RSP));
+			break;
+
+		default:
+			printk("cpqfcTS: don't know how to build FC type: %Xh(%d)\n", type, type);
+			break;
+		}
+		if (!ulStatus)	// no errors above?
+		{
+			// FCHS is built; now build IRB
+
+			// link the just built FCHS (the "command") to the IRB entry 
+			// for this Exchange.
+			pIRB = &Exchanges->fcExchange[*fcExchangeIndex].IRB;
+
+			// len & flags according to command type above
+			pIRB->Req_A_SFS_Len = SfsLen;	// includes IRB flags & len
+			pIRB->Req_A_SFS_Addr =	// TL needs physical addr of frame to send
+			    fcChip->exch_dma_handle + (unsigned long) CMDfchs - (unsigned long) Exchanges;
+
+			pIRB->Req_A_SFS_D_ID = CMDfchs->d_id << 8;	// Dest_ID must be consistent!
+
+			// Exchange is complete except for "fix-up" fields to be set
+			// at Tachyon Queuing time:
+			//    IRB->Req_A_Trans_ID (OX_ID/ RX_ID):  
+			//        for SEST entry, lower bits correspond to actual FC Exchange ID
+			//    fchs->OX_ID or RX_ID
+		} else {
+#ifdef DBG
+			printk("FC Error: SEST build Pool Allocation failed\n");
 #endif
-      // return resources...
-      cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, *fcExchangeIndex);  // SEST build failed
-    }
-  }
-  else  // no Exchanges available
-  {
-    ulStatus = SEST_FULL;
-    printk( "FC Error: no fcExchanges available\n");
-  }
-  return ulStatus;
+			// return resources...
+			cpqfcTSCompleteExchange(dev->PciDev, fcChip, *fcExchangeIndex);	// SEST build failed
+		}
+	} else			// no Exchanges available
+	{
+		ulStatus = SEST_FULL;
+		printk("FC Error: no fcExchanges available\n");
+	}
+	return ulStatus;
 }
 
-
-
-
-
-
 // set RSP payload fields
-static void  buildFCPstatus( PTACHYON fcChip, ULONG ExchangeID) 
+static void buildFCPstatus(PTACHYON fcChip, u32 ExchangeID)
 {
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  FC_EXCHANGE *pExchange = &Exchanges->fcExchange[ExchangeID];  // shorthand
-  PFCP_STATUS_RESPONSE pFcpStatus;
-  
-  memset( &fcChip->SEST->RspHDR[ ExchangeID ].pl, 0,
-    sizeof( FCP_STATUS_RESPONSE) );
-  if( pExchange->status ) // something wrong?
-  {
-    pFcpStatus = (PFCP_STATUS_RESPONSE)  // cast RSP buffer for this xchng
-      &fcChip->SEST->RspHDR[ ExchangeID ].pl;
-    if( pExchange->status & COUNT_ERROR )
-    {
-      
-      // set FCP response len valid (so we can report count error)
-      pFcpStatus->fcp_status |= FCP_RSP_LEN_VALID;
-      pFcpStatus->fcp_rsp_len = 0x04000000;  // 4 byte len (BIG Endian)
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	FC_EXCHANGE *pExchange = &Exchanges->fcExchange[ExchangeID];	// shorthand
+	PFCP_STATUS_RESPONSE pFcpStatus;
 
-      pFcpStatus->fcp_rsp_info = FCP_DATA_LEN_NOT_BURST_LEN; // RSP_CODE
-    }
-  }
+	memset(&fcChip->SEST->RspHDR[ExchangeID].pl, 0, sizeof(FCP_STATUS_RESPONSE));
+	if (pExchange->status)	// something wrong?
+	{
+		pFcpStatus = (PFCP_STATUS_RESPONSE)	// cast RSP buffer for this xchng
+		    & fcChip->SEST->RspHDR[ExchangeID].pl;
+		if (pExchange->status & COUNT_ERROR) {
+
+			// set FCP response len valid (so we can report count error)
+			pFcpStatus->fcp_status |= FCP_RSP_LEN_VALID;
+			pFcpStatus->fcp_rsp_len = 0x04000000;	// 4 byte len (BIG Endian)
+
+			pFcpStatus->fcp_rsp_info = FCP_DATA_LEN_NOT_BURST_LEN;	// RSP_CODE
+		}
+	}
 }
 
 
-static dma_addr_t 
-cpqfc_pci_map_sg_page(
-    		struct pci_dev *pcidev,
-		ULONG *hw_paddr, 	// where to put phys addr for HW use
-		void *sgp_vaddr,	// the virtual address of the sg page 
-	 	dma_addr_t *umap_paddr,	// where to put phys addr for unmap
-		unsigned int *maplen,	// where to store sg entry length
-		int PairCount)		// number of sg pairs used in the page.	
+static dma_addr_t cpqfc_pci_map_sg_page(struct pci_dev *pcidev, u32 * hw_paddr,	// where to put phys addr for HW use
+					void *sgp_vaddr,	// the virtual address of the sg page 
+					dma_addr_t * umap_paddr,	// where to put phys addr for unmap
+					unsigned int *maplen,	// where to store sg entry length
+					int PairCount)	// number of sg pairs used in the page. 
 {
 	unsigned long aligned_addr = (unsigned long) sgp_vaddr;
 
 	*maplen = PairCount * 8;
-        aligned_addr += TL_EXT_SG_PAGE_BYTELEN;
-        aligned_addr &= ~(TL_EXT_SG_PAGE_BYTELEN -1);
-	
-	*umap_paddr = pci_map_single(pcidev, (void *) aligned_addr, 
-				*maplen, PCI_DMA_TODEVICE);
-	*hw_paddr = (ULONG) *umap_paddr;
+	aligned_addr += TL_EXT_SG_PAGE_BYTELEN;
+	aligned_addr &= ~(TL_EXT_SG_PAGE_BYTELEN - 1);
+
+	*umap_paddr = pci_map_single(pcidev, (void *) aligned_addr, *maplen, PCI_DMA_TODEVICE);
+	*hw_paddr = (u32) * umap_paddr;
 
 #       if BITS_PER_LONG > 32
-       		if( *umap_paddr >>32 ) {
-       	  		printk("cqpfcTS:Tach SG DMA addr %p>32 bits\n", 
-	  			(void*)umap_paddr);
-       			return 0;
-       		}
+	if (*umap_paddr >> 32) {
+		printk("cqpfcTS:Tach SG DMA addr %p>32 bits\n", (void *) umap_paddr);
+		return 0;
+	}
 #       endif
 	return *umap_paddr;
 }
 
-static void
-cpqfc_undo_SEST_mappings(struct pci_dev *pcidev,
-			unsigned long contigaddr, int len, int dir,
-  			struct scatterlist *sgl, int use_sg,
-    			PSGPAGES *sgPages_head,
-			int allocated_pages)
+static void cpqfc_undo_SEST_mappings(struct pci_dev *pcidev, unsigned long contigaddr, int len, int dir, struct scatterlist *sgl, int use_sg, PSGPAGES * sgPages_head, int allocated_pages)
 {
 	PSGPAGES i, next;
 
@@ -5136,14 +4141,12 @@
 	if (sgl != NULL)
 		pci_unmap_sg(pcidev, sgl, use_sg, dir);
 
-	for (i=*sgPages_head; i != NULL ;i = next)
-	{
-		pci_unmap_single(pcidev, i->busaddr, i->maplen, 
-			scsi_to_pci_dma_dir(PCI_DMA_TODEVICE));
-		i->busaddr = (dma_addr_t) NULL; 
-		i->maplen = 0L; 
+	for (i = *sgPages_head; i != NULL; i = next) {
+		pci_unmap_single(pcidev, i->busaddr, i->maplen, scsi_to_pci_dma_dir(PCI_DMA_TODEVICE));
+		i->busaddr = (dma_addr_t) NULL;
+		i->maplen = 0L;
 		next = i->next;
-		kfree(i); 
+		kfree(i);
 	}
 	*sgPages_head = NULL;
 }
@@ -5166,380 +4169,331 @@
 
 static int ap_hi_water = TL_DANGER_SGPAGES;
 
-static ULONG build_SEST_sgList( 
-    struct pci_dev *pcidev,
-    ULONG *SESTalPairStart,  // the 3 len/address buffers in SEST
-    Scsi_Cmnd *Cmnd,
-    ULONG *sgPairs, 
-    PSGPAGES *sgPages_head)  // link list of TL Ext. S/G pages from O/S Pool
-    
+static u32 build_SEST_sgList(struct pci_dev *pcidev, u32 * SESTalPairStart,	// the 3 len/address buffers in SEST
+			       Scsi_Cmnd * Cmnd, u32 * sgPairs, PSGPAGES * sgPages_head)	// link list of TL Ext. S/G pages from O/S Pool
 {
-  ULONG i, AllocatedPages=0; // Tach Ext. S/G page allocations
-  ULONG* alPair = SESTalPairStart;
-  ULONG* ext_sg_page_phys_addr_place = NULL;
-  int PairCount;
-  unsigned long ulBuff, contigaddr;
-  ULONG total_data_len=0; // (in bytes)
-  ULONG bytes_to_go = Cmnd->request_bufflen; // total xfer (S/G sum)
-  ULONG thisMappingLen;
-  struct scatterlist *sgl = NULL;  // S/G list (Linux format)
-  int sg_count, totalsgs; 
-  dma_addr_t busaddr;
-  unsigned long thislen, offset;
-  PSGPAGES *sgpage = sgPages_head;
-  PSGPAGES prev_page = NULL;
-
-# define WE_HAVE_SG_LIST (sgl != (unsigned long) NULL)
-  contigaddr = (unsigned long) NULL;
-
-  if( !Cmnd->use_sg )  // no S/G list?
-  {
-	if (bytes_to_go <= TL_MAX_SG_ELEM_LEN)
-	{
-    		*sgPairs = 1;	// use "local" S/G pair in SEST entry
-				// (for now, ignore address bits above #31)
+	u32 i, AllocatedPages = 0;	// Tach Ext. S/G page allocations
+	u32 *alPair = SESTalPairStart;
+	u32 *ext_sg_page_phys_addr_place = NULL;
+	int PairCount;
+	unsigned long ulBuff, contigaddr;
+	u32 total_data_len = 0;	// (in bytes)
+	u32 bytes_to_go = Cmnd->request_bufflen;	// total xfer (S/G sum)
+	u32 thisMappingLen;
+	struct scatterlist *sgl = NULL;	// S/G list (Linux format)
+	int sg_count, totalsgs;
+	dma_addr_t busaddr;
+	unsigned long thislen, offset;
+	PSGPAGES *sgpage = sgPages_head;
+	PSGPAGES prev_page = NULL;
 
-		*alPair++ = bytes_to_go; // bits 18-0, length
+# define WE_HAVE_SG_LIST (sgl != (unsigned long) NULL)
+	contigaddr = (unsigned long) NULL;
 
-		if (bytes_to_go != 0) {
-			contigaddr = ulBuff = pci_map_single(pcidev, 
-				Cmnd->request_buffer, 
-				Cmnd->request_bufflen,
-				scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
-			// printk("ms %p ", ulBuff);
-		}
-		else {
-			// No data transfer, (e.g.: Test Unit Ready)
-			// printk("btg=0 ");
-			*sgPairs = 0;
-			memset(alPair, 0, sizeof(*alPair));
-			return 0;
-		}
+	if (!Cmnd->use_sg)	// no S/G list?
+	{
+		if (bytes_to_go <= TL_MAX_SG_ELEM_LEN) {
+			*sgPairs = 1;	// use "local" S/G pair in SEST entry
+			// (for now, ignore address bits above #31)
+
+			*alPair++ = bytes_to_go;	// bits 18-0, length
+
+			if (bytes_to_go != 0) {
+				contigaddr = ulBuff = pci_map_single(pcidev, Cmnd->request_buffer, Cmnd->request_bufflen, scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
+				// printk("ms %p ", ulBuff);
+			} else {
+				// No data transfer, (e.g.: Test Unit Ready)
+				// printk("btg=0 ");
+				*sgPairs = 0;
+				memset(alPair, 0, sizeof(*alPair));
+				return 0;
+			}
 
 #		if BITS_PER_LONG > 32
-    			if( ulBuff >>32 ) {
-      				printk("FATAL! Tachyon DMA address %p "
-					"exceeds 32 bits\n", (void*)ulBuff );
-      				return 0;
-    			}
+			if (ulBuff >> 32) {
+				printk("FATAL! Tachyon DMA address %p " "exceeds 32 bits\n", (void *) ulBuff);
+				return 0;
+			}
 #		endif
-    		*alPair = (ULONG)ulBuff;      
-    		return bytes_to_go;
-	} 
-	else	// We have a single large (too big) contiguous buffer.
-	{	// We will have to break it up.  We'll use the scatter
-		// gather code way below, but use contigaddr instead
-		// of sg_dma_addr(). (this is a very rare case).
-
-		unsigned long btg;
-		contigaddr = pci_map_single(pcidev, Cmnd->request_buffer, 
-				Cmnd->request_bufflen,
-				scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
-
-		// printk("contigaddr = %p, len = %d\n", 
-		//	(void *) contigaddr, bytes_to_go);
-		totalsgs = 0;
-		for (btg = bytes_to_go; btg > 0; ) {
-			btg -= ( btg > TL_MAX_SG_ELEM_LEN ? 
-				TL_MAX_SG_ELEM_LEN : btg );
-			totalsgs++;
-		}
-		sgl = NULL;
-		*sgPairs = totalsgs;
-	}
-  }
-  else  // we do have a scatter gather list
-  {
-	// [TBD - update for Linux to support > 32 bits addressing]
-	// since the format for local & extended S/G lists is different,
-	// check if S/G pairs exceeds 3.
-	// *sgPairs = Cmnd->use_sg; Nope, that's wrong.
- 
-	sgl = (struct scatterlist*)Cmnd->request_buffer;  
-	sg_count = pci_map_sg(pcidev, sgl, Cmnd->use_sg, 
-		scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
-        // printk("sgl = %p, sg_count = %d\n", (void *) sgl, sg_count);
-  	if( sg_count <= 3 ) {
-
-	// we need to be careful here that no individual mapping
-	// is too large, and if any is, that breaking it up
-	// doesn't push us over 3 sgs, or, if it does, that we
-	// handle that case.  Tachyon can take 0x7FFFF bits for length,
-	// but sg structure uses "unsigned int", on the face of it, 
-	// up to 0xFFFFFFFF or even more.
-
-		int i;
-		unsigned long thislen;
-
-		totalsgs = 0;
-		for (i=0;i<sg_count;i++) {
-      			thislen = sg_dma_len(&sgl[i]);
-			while (thislen >= TL_MAX_SG_ELEM_LEN) {
+			*alPair = (u32) ulBuff;
+			return bytes_to_go;
+		} else		// We have a single large (too big) contiguous buffer.
+		{		// We will have to break it up.  We'll use the scatter
+			// gather code way below, but use contigaddr instead
+			// of sg_dma_addr(). (this is a very rare case).
+
+			unsigned long btg;
+			contigaddr = pci_map_single(pcidev, Cmnd->request_buffer, Cmnd->request_bufflen, scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
+
+			// printk("contigaddr = %p, len = %d\n", 
+			//      (void *) contigaddr, bytes_to_go);
+			totalsgs = 0;
+			for (btg = bytes_to_go; btg > 0;) {
+				btg -= (btg > TL_MAX_SG_ELEM_LEN ? TL_MAX_SG_ELEM_LEN : btg);
 				totalsgs++;
-				thislen -= TL_MAX_SG_ELEM_LEN;
 			}
-			if (thislen > 0) totalsgs++;
+			sgl = NULL;
+			*sgPairs = totalsgs;
 		}
-		*sgPairs = totalsgs;
-  	} else totalsgs = 999; // as a first estimate, definitely >3, 
-			      
-	// if (totalsgs != sg_count) 
-	//	printk("totalsgs = %d, sgcount=%d\n",totalsgs,sg_count);
-  }
+	} else			// we do have a scatter gather list
+	{
+		// [TBD - update for Linux to support > 32 bits addressing]
+		// since the format for local & extended S/G lists is different,
+		// check if S/G pairs exceeds 3.
+		// *sgPairs = Cmnd->use_sg; Nope, that's wrong.
+
+		sgl = (struct scatterlist *) Cmnd->request_buffer;
+		sg_count = pci_map_sg(pcidev, sgl, Cmnd->use_sg, scsi_to_pci_dma_dir(Cmnd->sc_data_direction));
+		// printk("sgl = %p, sg_count = %d\n", (void *) sgl, sg_count);
+		if (sg_count <= 3) {
+
+			// we need to be careful here that no individual mapping
+			// is too large, and if any is, that breaking it up
+			// doesn't push us over 3 sgs, or, if it does, that we
+			// handle that case.  Tachyon can take 0x7FFFF bits for length,
+			// but sg structure uses "unsigned int", on the face of it, 
+			// up to 0xFFFFFFFF or even more.
+
+			int i;
+			unsigned long thislen;
+
+			totalsgs = 0;
+			for (i = 0; i < sg_count; i++) {
+				thislen = sg_dma_len(&sgl[i]);
+				while (thislen >= TL_MAX_SG_ELEM_LEN) {
+					totalsgs++;
+					thislen -= TL_MAX_SG_ELEM_LEN;
+				}
+				if (thislen > 0)
+					totalsgs++;
+			}
+			*sgPairs = totalsgs;
+		} else
+			totalsgs = 999;	// as a first estimate, definitely >3, 
 
-  // printk("totalsgs = %d, sgcount=%d\n", totalsgs, sg_count);
-  if( totalsgs <= 3 ) // can (must) use "local" SEST list
-  {
-    while( bytes_to_go)
-    {
-      offset = 0L;
+		// if (totalsgs != sg_count) 
+		//      printk("totalsgs = %d, sgcount=%d\n",totalsgs,sg_count);
+	}
 
-      if ( WE_HAVE_SG_LIST ) 
-	thisMappingLen = sg_dma_len(sgl);
-      else					// or contiguous buffer?
-	thisMappingLen = bytes_to_go;
+	// printk("totalsgs = %d, sgcount=%d\n", totalsgs, sg_count);
+	if (totalsgs <= 3)	// can (must) use "local" SEST list
+	{
+		while (bytes_to_go) {
+			offset = 0L;
 
-      while (thisMappingLen > 0)
-      {  
-	thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? 
-		TL_MAX_SG_ELEM_LEN : thisMappingLen;
-	bytes_to_go = bytes_to_go - thislen;
+			if (WE_HAVE_SG_LIST)
+				thisMappingLen = sg_dma_len(sgl);
+			else	// or contiguous buffer?
+				thisMappingLen = bytes_to_go;
 
-	// we have L/A pair; L = thislen, A = physicalAddress
-	// load into SEST...
+			while (thisMappingLen > 0) {
+				thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? TL_MAX_SG_ELEM_LEN : thisMappingLen;
+				bytes_to_go = bytes_to_go - thislen;
 
-	total_data_len += thislen;
-	*alPair = thislen; // bits 18-0, length
+				// we have L/A pair; L = thislen, A = physicalAddress
+				// load into SEST...
 
-	alPair++;
+				total_data_len += thislen;
+				*alPair = thislen;	// bits 18-0, length
 
-	if ( WE_HAVE_SG_LIST ) 
-		ulBuff = sg_dma_address(sgl) + offset;
-	else
-		ulBuff = contigaddr + offset;
+				alPair++;
 
-	offset += thislen;
+				if (WE_HAVE_SG_LIST)
+					ulBuff = sg_dma_address(sgl) + offset;
+				else
+					ulBuff = contigaddr + offset;
+
+				offset += thislen;
 
 #	if BITS_PER_LONG > 32
-		if( ulBuff >>32 ) {
-        		printk("cqpfcTS: 2Tach DMA address %p > 32 bits\n", 
-				(void*)ulBuff );
-		    printk("%s = %p, offset = %ld\n", 
-			WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr",
-			WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr,
-				offset);
-        		return 0;
-      		}
+				if (ulBuff >> 32) {
+					printk("cqpfcTS: 2Tach DMA address %p > 32 bits\n", (void *) ulBuff);
+					printk("%s = %p, offset = %ld\n", WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr", WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr, offset);
+					return 0;
+				}
 #	endif
-        *alPair++ = (ULONG)ulBuff; // lower 32 bits (31-0)
-	thisMappingLen -= thislen;
-      }
+				*alPair++ = (u32) ulBuff;	// lower 32 bits (31-0)
+				thisMappingLen -= thislen;
+			}
 
-      if ( WE_HAVE_SG_LIST ) ++sgl;  // next S/G pair
-	else if (bytes_to_go != 0) printk("BTG not zero!\n");
+			if (WE_HAVE_SG_LIST)
+				++sgl;	// next S/G pair
+			else if (bytes_to_go != 0)
+				printk("BTG not zero!\n");
 
 #     ifdef DBG_SEST_SGLIST
-	printk("L=%d ", thisMappingLen);
-	printk("btg=%d ", bytes_to_go);
+			printk("L=%d ", thisMappingLen);
+			printk("btg=%d ", bytes_to_go);
 #     endif
 
-    }
-    // printk("i:%d\n", *sgPairs);
-  }
-  else    // more than 3 pairs requires Extended S/G page (Pool Allocation)
-  {
-    // clear out SEST DWORDs (local S/G addr) C-F (A-B set in following logic)
-    for( i=2; i<6; i++)
-      alPair[i] = 0;
-
-    PairCount = TL_EXT_SG_PAGE_COUNT;    // forces initial page allocation
-    totalsgs = 0;
-    while( bytes_to_go )
-    {
-      // Per SEST format, we can support 524287 byte lengths per
-      // S/G pair.  Typical user buffers are 4k, and very rarely
-      // exceed 12k due to fragmentation of physical memory pages.
-      // However, on certain O/S system (not "user") buffers (on platforms 
-      // with huge memories), it's possible to exceed this
-      // length in a single S/G address/len mapping, so we have to handle
-      // that.
-
-      offset = 0L;
-      if ( WE_HAVE_SG_LIST ) 
-	thisMappingLen = sg_dma_len(sgl);
-      else
-	thisMappingLen = bytes_to_go;
-
-      while (thisMappingLen > 0)
-      {
-	thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? 
-		TL_MAX_SG_ELEM_LEN : thisMappingLen;
-	// printk("%d/%d/%d\n", thislen, thisMappingLen, bytes_to_go);
-      
-  	// should we load into "this" extended S/G page, or allocate
-	// new page?
-
-	if( PairCount >= TL_EXT_SG_PAGE_COUNT )
+		}
+		// printk("i:%d\n", *sgPairs);
+	} else			// more than 3 pairs requires Extended S/G page (Pool Allocation)
 	{
-	  // Now, we have to map the previous page, (triggering buffer bounce)
-	  // The first time thru the loop, there won't be a previous page.
-	  if (prev_page != NULL) // is there a prev page? 
-	  {
-		// this code is normally kind of hard to trigger, 
-		// you have to use up more than 256 scatter gather 
-		// elements to get here.  Cranking down TL_MAX_SG_ELEM_LEN
-		// to an absurdly low value (128 bytes or so) to artificially
-		// break i/o's into a zillion pieces is how I tested it. 
-		busaddr = cpqfc_pci_map_sg_page(pcidev,
-				ext_sg_page_phys_addr_place,
-				prev_page->page,
-        			&prev_page->busaddr,
-        			&prev_page->maplen,
-				PairCount);
-          } 
-          // Allocate the TL Extended S/G list page.  We have
-          // to allocate twice what we want to ensure required TL alignment
-          // (Tachlite TL/TS User Man. Rev 6.0, p 168)
-          // We store the original allocated PVOID so we can free later
-	  *sgpage = kmalloc( sizeof(SGPAGES), GFP_ATOMIC);
-	  if ( ! *sgpage )
-          {
-		printk("cpqfc: Allocation failed @ %d S/G page allocations\n",
-			AllocatedPages);
-		total_data_len = 0;  // failure!! Ext. S/G is All-or-none affair
-
-	        // unmap the previous mappings, if any.
-
-	        cpqfc_undo_SEST_mappings(pcidev, contigaddr, 
-			Cmnd->request_bufflen,
-			scsi_to_pci_dma_dir(Cmnd->sc_data_direction),
-  			sgl, Cmnd->use_sg, sgPages_head, AllocatedPages+1);
-
-		// FIXME: testing shows that if we get here, 
-		// it's bad news.  (this has been this way for a long 
-		// time though, AFAIK.  Not that that excuses it.)
-
-		return 0; // give up (and probably hang the system)
-          }
-                               // clear out memory we just allocated
-	  memset( (*sgpage)->page,0,TL_EXT_SG_PAGE_BYTELEN*2);
-	  (*sgpage)->next = NULL;
-	  (*sgpage)->busaddr = (dma_addr_t) NULL;
-	  (*sgpage)->maplen = 0L;
-      
-	  // align the memory - TL requires sizeof() Ext. S/G page alignment.
-	  // We doubled the actual required size so we could mask off LSBs 
-	  // to get desired offset 
-
-	  ulBuff = (unsigned long) (*sgpage)->page;
-	  ulBuff += TL_EXT_SG_PAGE_BYTELEN;
-	  ulBuff &= ~(TL_EXT_SG_PAGE_BYTELEN -1);
-
-	  // set pointer, in SEST if first Ext. S/G page, or in last pair
-	  // of linked Ext. S/G pages... (Only 32-bit PVOIDs, so just 
-	  // load lower 32 bits)
-	  // NOTE: the Len field must be '0' if this is the first Ext. S/G
-	  // pointer in SEST, and not 0 otherwise (we know thislen != 0).
+		// clear out SEST DWORDs (local S/G addr) C-F (A-B set in following logic)
+		for (i = 2; i < 6; i++)
+			alPair[i] = 0;
 
-	  *alPair = (alPair != SESTalPairStart) ? thislen : 0;
+		PairCount = TL_EXT_SG_PAGE_COUNT;	// forces initial page allocation
+		totalsgs = 0;
+		while (bytes_to_go) {
+			// Per SEST format, we can support 524287 byte lengths per
+			// S/G pair.  Typical user buffers are 4k, and very rarely
+			// exceed 12k due to fragmentation of physical memory pages.
+			// However, on certain O/S system (not "user") buffers (on platforms 
+			// with huge memories), it's possible to exceed this
+			// length in a single S/G address/len mapping, so we have to handle
+			// that.
+
+			offset = 0L;
+			if (WE_HAVE_SG_LIST)
+				thisMappingLen = sg_dma_len(sgl);
+			else
+				thisMappingLen = bytes_to_go;
+
+			while (thisMappingLen > 0) {
+				thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? TL_MAX_SG_ELEM_LEN : thisMappingLen;
+				// printk("%d/%d/%d\n", thislen, thisMappingLen, bytes_to_go);
+
+				// should we load into "this" extended S/G page, or allocate
+				// new page?
+
+				if (PairCount >= TL_EXT_SG_PAGE_COUNT) {
+					// Now, we have to map the previous page, (triggering buffer bounce)
+					// The first time thru the loop, there won't be a previous page.
+					if (prev_page != NULL)	// is there a prev page? 
+					{
+						// this code is normally kind of hard to trigger, 
+						// you have to use up more than 256 scatter gather 
+						// elements to get here.  Cranking down TL_MAX_SG_ELEM_LEN
+						// to an absurdly low value (128 bytes or so) to artificially
+						// break i/o's into a zillion pieces is how I tested it. 
+						busaddr = cpqfc_pci_map_sg_page(pcidev, ext_sg_page_phys_addr_place, prev_page->page, &prev_page->busaddr, &prev_page->maplen, PairCount);
+					}
+					// Allocate the TL Extended S/G list page.  We have
+					// to allocate twice what we want to ensure required TL alignment
+					// (Tachlite TL/TS User Man. Rev 6.0, p 168)
+					// We store the original allocated PVOID so we can free later
+					*sgpage = kmalloc(sizeof(SGPAGES), GFP_ATOMIC);
+					if (!*sgpage) {
+						printk("cpqfc: Allocation failed @ %d S/G page allocations\n", AllocatedPages);
+						total_data_len = 0;	// failure!! Ext. S/G is All-or-none affair
+
+						// unmap the previous mappings, if any.
+
+						cpqfc_undo_SEST_mappings(pcidev, contigaddr, Cmnd->request_bufflen, scsi_to_pci_dma_dir(Cmnd->sc_data_direction), sgl, Cmnd->use_sg, sgPages_head, AllocatedPages + 1);
+
+						// FIXME: testing shows that if we get here, 
+						// it's bad news.  (this has been this way for a long 
+						// time though, AFAIK.  Not that that excuses it.)
+
+						return 0;	// give up (and probably hang the system)
+					}
+					// clear out memory we just allocated
+					memset((*sgpage)->page, 0, TL_EXT_SG_PAGE_BYTELEN * 2);
+					(*sgpage)->next = NULL;
+					(*sgpage)->busaddr = (dma_addr_t) NULL;
+					(*sgpage)->maplen = 0L;
+
+					// align the memory - TL requires sizeof() Ext. S/G page alignment.
+					// We doubled the actual required size so we could mask off LSBs 
+					// to get desired offset 
+
+					ulBuff = (unsigned long) (*sgpage)->page;
+					ulBuff += TL_EXT_SG_PAGE_BYTELEN;
+					ulBuff &= ~(TL_EXT_SG_PAGE_BYTELEN - 1);
+
+					// set pointer, in SEST if first Ext. S/G page, or in last pair
+					// of linked Ext. S/G pages... (Only 32-bit PVOIDs, so just 
+					// load lower 32 bits)
+					// NOTE: the Len field must be '0' if this is the first Ext. S/G
+					// pointer in SEST, and not 0 otherwise (we know thislen != 0).
+
+					*alPair = (alPair != SESTalPairStart) ? thislen : 0;
 
 #	  ifdef DBG_SEST_SGLIST
-        	printk("PairCount %d @%p even %Xh, ", 
-			PairCount, alPair, *alPair);
+					printk("PairCount %d @%p even %Xh, ", PairCount, alPair, *alPair);
 #	  endif
 
-	  // Save the place where we need to store the physical
-	  // address of this scatter gather page which we get when we map it
-	  // (and mapping we can do only after we fill it in.)
-	  alPair++;  // next DWORD, will contain phys addr of the ext page
-	  ext_sg_page_phys_addr_place = alPair;
-
-	  // Now, set alPair = the virtual addr of the (Extended) S/G page
-	  // which will accept the Len/ PhysicalAddress pairs
-	  alPair = (ULONG *) ulBuff;
-
-	  AllocatedPages++;
-	  if (AllocatedPages >= ap_hi_water)
-	  {
-		// This message should rarely, if ever, come out.
-		// Previously (cpqfc version <= 2.0.5) the driver would
-		// just puke if more than 4 SG pages were used, and nobody
-		// ever complained about that.  This only comes out if 
-		// more than 8 pages are used.
-
-		printk(KERN_WARNING
-		"cpqfc: Possible danger.  %d scatter gather pages used.\n"
-			"cpqfc: detected seemingly extreme memory "
-			"fragmentation or huge data transfers.\n", 
-			AllocatedPages);
-		ap_hi_water = AllocatedPages+1;
-	  }
-		
-	  PairCount = 1;  // starting new Ext. S/G page
-	  prev_page = (*sgpage);  // remember this page, for next time thru
-	  sgpage = &((*sgpage)->next);
-	}  // end of new TL Ext. S/G page allocation
+					// Save the place where we need to store the physical
+					// address of this scatter gather page which we get when we map it
+					// (and mapping we can do only after we fill it in.)
+					alPair++;	// next DWORD, will contain phys addr of the ext page
+					ext_sg_page_phys_addr_place = alPair;
+
+					// Now, set alPair = the virtual addr of the (Extended) S/G page
+					// which will accept the Len/ PhysicalAddress pairs
+					alPair = (u32 *) ulBuff;
+
+					AllocatedPages++;
+					if (AllocatedPages >= ap_hi_water) {
+						// This message should rarely, if ever, come out.
+						// Previously (cpqfc version <= 2.0.5) the driver would
+						// just puke if more than 4 SG pages were used, and nobody
+						// ever complained about that.  This only comes out if 
+						// more than 8 pages are used.
+
+						printk(KERN_WARNING "cpqfc: Possible danger.  %d scatter gather pages used.\n" "cpqfc: detected seemingly extreme memory " "fragmentation or huge data transfers.\n", AllocatedPages);
+						ap_hi_water = AllocatedPages + 1;
+					}
+
+					PairCount = 1;	// starting new Ext. S/G page
+					prev_page = (*sgpage);	// remember this page, for next time thru
+					sgpage = &((*sgpage)->next);
+				}	// end of new TL Ext. S/G page allocation
+
+				*alPair = thislen;	// bits 18-0, length (range check above)
 
-	*alPair = thislen; // bits 18-0, length (range check above)
-      
 #	ifdef DBG_SEST_SGLIST
-	  printk("PairCount %d @%p, even %Xh, ", PairCount, alPair, *alPair);
+				printk("PairCount %d @%p, even %Xh, ", PairCount, alPair, *alPair);
 #	endif
 
-	alPair++;    // next DWORD, physical address 
+				alPair++;	// next DWORD, physical address 
 
-	if ( WE_HAVE_SG_LIST ) 
-		ulBuff = sg_dma_address(sgl) + offset;
-	else
-		ulBuff = contigaddr + offset;
-	offset += thislen;
+				if (WE_HAVE_SG_LIST)
+					ulBuff = sg_dma_address(sgl) + offset;
+				else
+					ulBuff = contigaddr + offset;
+				offset += thislen;
 
 #	if BITS_PER_LONG > 32
-          if( ulBuff >>32 )
-	  {
-	    printk("cqpfcTS: 1Tach DMA address %p > 32 bits\n", (void*)ulBuff );
-	    printk("%s = %p, offset = %ld\n", 
-		WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr",
-		WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr,
-			offset);
-	    return 0;
-	  }
+				if (ulBuff >> 32) {
+					printk("cqpfcTS: 1Tach DMA address %p > 32 bits\n", (void *) ulBuff);
+					printk("%s = %p, offset = %ld\n", WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr", WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr, offset);
+					return 0;
+				}
 #	endif
 
-	*alPair = (ULONG) ulBuff; // lower 32 bits (31-0)
+				*alPair = (u32) ulBuff;	// lower 32 bits (31-0)
 
 #       ifdef DBG_SEST_SGLIST
-        printk("odd %Xh\n", *alPair);
+				printk("odd %Xh\n", *alPair);
 #       endif
-	alPair++;    // next DWORD, next address/length pair
-                                           
-	PairCount++; // next Length/Address pair
-
-	// if (PairCount > pc_hi_water)
-	// {
-		// printk("pc hi = %d ", PairCount);
-		// pc_hi_water = PairCount;
-	// }
-	bytes_to_go -= thislen;
-	total_data_len += thislen;  
-	thisMappingLen -= thislen;
-	totalsgs++;
-      } // while (thisMappingLen > 0)
-      if ( WE_HAVE_SG_LIST ) sgl++;  // next S/G pair
-    } // while (bytes_to_go)
-
-    // printk("Totalsgs=%d\n", totalsgs);
-    *sgPairs = totalsgs;
-
-    // PCI map (and bounce) the last (and usually only) extended SG page
-    busaddr = cpqfc_pci_map_sg_page(pcidev,
-		ext_sg_page_phys_addr_place,
-		prev_page->page, 
-		&prev_page->busaddr, 
-		&prev_page->maplen,
-		PairCount);
-  }
-  return total_data_len;
+				alPair++;	// next DWORD, next address/length pair
+
+				PairCount++;	// next Length/Address pair
+
+				// if (PairCount > pc_hi_water)
+				// {
+				// printk("pc hi = %d ", PairCount);
+				// pc_hi_water = PairCount;
+				// }
+				bytes_to_go -= thislen;
+				total_data_len += thislen;
+				thisMappingLen -= thislen;
+				totalsgs++;
+			}	// while (thisMappingLen > 0)
+			if (WE_HAVE_SG_LIST)
+				sgl++;	// next S/G pair
+		}		// while (bytes_to_go)
+
+		// printk("Totalsgs=%d\n", totalsgs);
+		*sgPairs = totalsgs;
+
+		// PCI map (and bounce) the last (and usually only) extended SG page
+		busaddr = cpqfc_pci_map_sg_page(pcidev, ext_sg_page_phys_addr_place, prev_page->page, &prev_page->busaddr, &prev_page->maplen, PairCount);
+	}
+	return total_data_len;
 }
 
 
@@ -5554,268 +4508,249 @@
 // 0 if successful
 // non-zero on error
 //sstartex
-ULONG cpqfcTSStartExchange( 
-  CPQFCHBA *cpqfcHBAdata,                      
-  LONG ExchangeID )
-{
-  PTACHYON fcChip = &cpqfcHBAdata->fcChip;
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  FC_EXCHANGE *pExchange = &Exchanges->fcExchange[ ExchangeID ]; // shorthand
-  USHORT producer, consumer;
-  ULONG ulStatus=0;
-  short int ErqIndex;
-  BOOLEAN CompleteExchange = FALSE;  // e.g. ACC replies are complete
-  BOOLEAN SestType=FALSE;
-  ULONG InboundData=0;
 
-  // We will manipulate Tachlite chip registers here to successfully
-  // start exchanges. 
+u32 cpqfcTSStartExchange(CPQFCHBA * dev, s32 ExchangeID)
+{
+	PTACHYON fcChip = &dev->fcChip;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	FC_EXCHANGE *pExchange = &Exchanges->fcExchange[ExchangeID];	// shorthand
+	u16 producer, consumer;
+	u32 ulStatus = 0;
+	short int ErqIndex;
+	u8 CompleteExchange = 0;	// e.g. ACC replies are complete
+	u8 SestType = 0;
+	u32 InboundData = 0;
 
-  // Check that link is not down -- we can't start an exchange on a
-  // down link!
+	// We will manipulate Tachlite chip registers here to successfully
+	// start exchanges. 
 
-  if( fcChip->Registers.FMstatus.value & 0x80) // LPSM offline?
-  {
-printk("fcStartExchange: PSM offline (%Xh), x_ID %Xh, type %Xh, port_id %Xh\n",
-         fcChip->Registers.FMstatus.value & 0xFF,
-         ExchangeID,
-         pExchange->type,
-         pExchange->fchs.d_id);
+	// Check that link is not down -- we can't start an exchange on a
+	// down link!
 
-    if( ExchangeID >= TACH_SEST_LEN )  // Link Service Outbound frame?
-    {
-      // Our most popular LinkService commands are port discovery types
-      // (PLOGI/ PDISC...), which are implicitly nullified by Link Down
-      // events, so it makes no sense to Que them.  However, ABTS should
-      // be queued, since exchange sequences are likely destroyed by
-      // Link Down events, and we want to notify other ports of broken
-      // sequences by aborting the corresponding exchanges.
-      if( pExchange->type != BLS_ABTS )
-      {
-	ulStatus = LNKDWN_OSLS;
-	goto Done;
-        // don't Que most LinkServ exchanges on LINK DOWN
-      }
-    }
+	if (fcChip->Registers.FMstatus.value & 0x80)	// LPSM offline?
+	{
+		printk("fcStartExchange: PSM offline (%Xh), x_ID %Xh, type %Xh, port_id %Xh\n", fcChip->Registers.FMstatus.value & 0xFF, ExchangeID, pExchange->type, pExchange->fchs.d_id);
 
-    printk("fcStartExchange: Que x_ID %Xh, type %Xh\n", 
-      ExchangeID, pExchange->type);
-    pExchange->status |= EXCHANGE_QUEUED;
-    ulStatus = EXCHANGE_QUEUED;
-    goto Done;
-  }
+		if (ExchangeID >= TACH_SEST_LEN)	// Link Service Outbound frame?
+		{
+			// Our most popular LinkService commands are port discovery types
+			// (PLOGI/ PDISC...), which are implicitly nullified by Link Down
+			// events, so it makes no sense to Que them.  However, ABTS should
+			// be queued, since exchange sequences are likely destroyed by
+			// Link Down events, and we want to notify other ports of broken
+			// sequences by aborting the corresponding exchanges.
+			if (pExchange->type != BLS_ABTS) {
+				ulStatus = LNKDWN_OSLS;
+				goto Done;
+				// don't Que most LinkServ exchanges on LINK DOWN
+			}
+		}
 
-  // Make sure ERQ has available space.
-  
-  producer = (USHORT)fcChip->ERQ->producerIndex; // copies for logical arith.
-  consumer = (USHORT)fcChip->ERQ->consumerIndex;
-  producer++;  // We are testing for full que by incrementing
-  
-  if( producer >= ERQ_LEN )  // rollover condition?
-    producer = 0;
-  if( consumer != producer ) // ERQ not full?
-  {
-    // ****************** Need Atomic access to chip registers!!********
-    
-    // remember ERQ PI for copying IRB
-    ErqIndex = (USHORT)fcChip->ERQ->producerIndex; 
-    fcChip->ERQ->producerIndex = producer; // this is written to Tachyon
-               // we have an ERQ slot! If SCSI command, need SEST slot
-               // otherwise we are done.
-
-    // Note that Tachyon requires that bit 15 of the OX_ID or RX_ID be
-    // set according to direction of data to/from Tachyon for SEST assists.
-    // For consistency, enforce this rule for Link Service (non-SEST)
-    // exchanges as well.
-
-    // fix-up the X_ID field in IRB
-    pExchange->IRB.Req_A_Trans_ID = ExchangeID & 0x7FFF; // 15-bit field
-
-    // fix-up the X_ID field in fchs -- depends on Originator or Responder,
-    // outgoing or incoming data?
-    switch( pExchange->type )
-    {
-               // ORIGINATOR types...  we're setting our OX_ID and
-               // defaulting the responder's RX_ID to 0xFFFF
-    
-    case SCSI_IRE:
-      // Requirement: set MSB of x_ID for Incoming TL data
-      // (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
-      InboundData = 0x8000;
-
-    case SCSI_IWE:   
-      SestType = TRUE;
-      pExchange->fchs.ox_rx_id = (ExchangeID | InboundData);
-      pExchange->fchs.ox_rx_id <<= 16;     // MSW shift
-      pExchange->fchs.ox_rx_id |= 0xffff;  // add default RX_ID
-      
-      // now fix-up the Data HDR OX_ID (TL automatically does rx_id)
-      // (not necessary for IRE -- data buffer unused)
-      if( pExchange->type == SCSI_IWE)
-      {
-        fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id = 
-          pExchange->fchs.ox_rx_id;
-
-      }
-
-      break;
-
-
-    case FCS_NSR:  // ext. link service Name Service Request
-    case ELS_SCR:  // ext. link service State Change Registration
-    case ELS_FDISC:// ext. link service login
-    case ELS_FLOGI:// ext. link service login
-    case ELS_LOGO: // FC-PH extended link service logout
-    case BLS_NOP:  // Basic link service No OPeration
-    case ELS_PLOGI:// ext. link service login (PLOGI)
-    case ELS_PDISC:// ext. link service login (PDISC)
-    case ELS_PRLI: // ext. link service process login
-
-      pExchange->fchs.ox_rx_id = ExchangeID;
-      pExchange->fchs.ox_rx_id <<= 16;  // MSW shift
-      pExchange->fchs.ox_rx_id |= 0xffff;  // and RX_ID
+		printk("fcStartExchange: Que x_ID %Xh, type %Xh\n", ExchangeID, pExchange->type);
+		pExchange->status |= EXCHANGE_QUEUED;
+		ulStatus = EXCHANGE_QUEUED;
+		goto Done;
+	}
+	// Make sure ERQ has available space.
 
-      break;
-      
+	producer = (u16) fcChip->ERQ->producerIndex;	// copies for logical arith.
+	consumer = (u16) fcChip->ERQ->consumerIndex;
+	producer++;		// We are testing for full que by incrementing
+
+	if (producer >= ERQ_LEN)	// rollover condition?
+		producer = 0;
+	if (consumer != producer)	// ERQ not full?
+	{
+		// ****************** Need Atomic access to chip registers!!********
 
+		// remember ERQ PI for copying IRB
+		ErqIndex = (u16) fcChip->ERQ->producerIndex;
+		fcChip->ERQ->producerIndex = producer;	// this is written to Tachyon
+		// we have an ERQ slot! If SCSI command, need SEST slot
+		// otherwise we are done.
+
+		// Note that Tachyon requires that bit 15 of the OX_ID or RX_ID be
+		// set according to direction of data to/from Tachyon for SEST assists.
+		// For consistency, enforce this rule for Link Service (non-SEST)
+		// exchanges as well.
+
+		// fix-up the X_ID field in IRB
+		pExchange->IRB.Req_A_Trans_ID = ExchangeID & 0x7FFF;	// 15-bit field
+
+		// fix-up the X_ID field in fchs -- depends on Originator or Responder,
+		// outgoing or incoming data?
+		switch (pExchange->type) {
+			// ORIGINATOR types...  we're setting our OX_ID and
+			// defaulting the responder's RX_ID to 0xFFFF
+
+		case SCSI_IRE:
+			// Requirement: set MSB of x_ID for Incoming TL data
+			// (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
+			InboundData = 0x8000;
+
+		case SCSI_IWE:
+			SestType = 1;
+			pExchange->fchs.ox_rx_id = (ExchangeID | InboundData);
+			pExchange->fchs.ox_rx_id <<= 16;	// MSW shift
+			pExchange->fchs.ox_rx_id |= 0xffff;	// add default RX_ID
+
+			// now fix-up the Data HDR OX_ID (TL automatically does rx_id)
+			// (not necessary for IRE -- data buffer unused)
+			if (pExchange->type == SCSI_IWE) {
+				fcChip->SEST->DataHDR[ExchangeID].ox_rx_id = pExchange->fchs.ox_rx_id;
 
+			}
 
-               // RESPONDER types... we must set our RX_ID while preserving
-               // sender's OX_ID
-               // outgoing (or no) data
-    case ELS_RJT:       // extended link service reject 
-    case ELS_LOGO_ACC: // FC-PH extended link service logout accept
-    case ELS_ACC:      // ext. generic link service accept
-    case ELS_PLOGI_ACC:// ext. link service login accept (PLOGI or PDISC)
-    case ELS_PRLI_ACC: // ext. link service process login accept
-
-      CompleteExchange = TRUE;   // Reply (ACC or RJT) is end of exchange
-      pExchange->fchs.ox_rx_id |= (ExchangeID & 0xFFFF);
-
-      break;
-
-
-      // since we are a Responder, OX_ID should already be set by
-      // cpqfcTSBuildExchange().  We need to -OR- in RX_ID
-    case SCSI_TWE:
-      SestType = TRUE;
-      // Requirement: set MSB of x_ID for Incoming TL data
-      // (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
-
-      pExchange->fchs.ox_rx_id &= 0xFFFF0000;  // clear RX_ID
-      // Requirement: set MSB of RX_ID for Incoming TL data
-      // (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
-      pExchange->fchs.ox_rx_id |= (ExchangeID | 0x8000);
-      break;
-          
-    
-    case SCSI_TRE:
-      SestType = TRUE;
-      
-      // there is no XRDY for SEST target read; the data
-      // header needs to be updated. Also update the RSP
-      // exchange IDs for the status frame, in case it is sent automatically
-      fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id |= ExchangeID;
-      fcChip->SEST->RspHDR[ ExchangeID ].ox_rx_id = 
-        fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id;
-      
-      // for easier FCP response logic (works for TWE and TRE), 
-      // copy exchange IDs.  (Not needed if TRE 'RSP' bit set)
-      pExchange->fchs.ox_rx_id =
-        fcChip->SEST->DataHDR[ ExchangeID ].ox_rx_id;
-
-      break;
+			break;
 
 
-    case FCP_RESPONSE:  // using existing OX_ID/ RX_ID pair,
-                        // start SFS FCP-RESPONSE frame
-      // OX/RX_ID should already be set! (See "fcBuild" above)
-      CompleteExchange = TRUE;   // RSP is end of FCP-SCSI exchange
+		case FCS_NSR:	// ext. link service Name Service Request
+		case ELS_SCR:	// ext. link service State Change Registration
+		case ELS_FDISC:	// ext. link service login
+		case ELS_FLOGI:	// ext. link service login
+		case ELS_LOGO:	// FC-PH extended link service logout
+		case BLS_NOP:	// Basic link service No OPeration
+		case ELS_PLOGI:	// ext. link service login (PLOGI)
+		case ELS_PDISC:	// ext. link service login (PDISC)
+		case ELS_PRLI:	// ext. link service process login
 
-      
-      break;
+			pExchange->fchs.ox_rx_id = ExchangeID;
+			pExchange->fchs.ox_rx_id <<= 16;	// MSW shift
+			pExchange->fchs.ox_rx_id |= 0xffff;	// and RX_ID
 
+			break;
 
-    case BLS_ABTS_RJT:  // uses new RX_ID, since SEST x_ID non-existent
-    case BLS_ABTS_ACC:  // using existing OX_ID/ RX_ID pair from SEST entry
-      CompleteExchange = TRUE;   // ACC or RJT marks end of FCP-SCSI exchange
-    case BLS_ABTS:  // using existing OX_ID/ RX_ID pair from SEST entry
 
 
-      break;
 
+			// RESPONDER types... we must set our RX_ID while preserving
+			// sender's OX_ID
+			// outgoing (or no) data
+		case ELS_RJT:	// extended link service reject 
+		case ELS_LOGO_ACC:	// FC-PH extended link service logout accept
+		case ELS_ACC:	// ext. generic link service accept
+		case ELS_PLOGI_ACC:	// ext. link service login accept (PLOGI or PDISC)
+		case ELS_PRLI_ACC:	// ext. link service process login accept
 
-    default:
-      printk("Error on fcStartExchange: undefined type %Xh(%d)\n",
-        pExchange->type, pExchange->type);
-      return INVALID_ARGS;
-    }
-    
-    
-      // X_ID fields are entered -- copy IRB to Tachyon's ERQ
-    
+			CompleteExchange = 1;	// Reply (ACC or RJT) is end of exchange
+			pExchange->fchs.ox_rx_id |= (ExchangeID & 0xFFFF);
 
-    memcpy(
-        &fcChip->ERQ->QEntry[ ErqIndex ],  // dest.
-        &pExchange->IRB,
-        32);  // fixed (hardware) length!
-
-    PCI_TRACEO( ExchangeID, 0xA0)
-
-    // ACTION!  May generate INT and IMQ entry
-    writel( fcChip->ERQ->producerIndex,
-          fcChip->Registers.ERQproducerIndex.address);
+			break;
 
-  
-    if( ExchangeID >= TACH_SEST_LEN )  // Link Service Outbound frame?
-    {
-    
-      // wait for completion! (TDB -- timeout and chip reset)
-      
 
-  PCI_TRACEO( ExchangeID, 0xA4)
-  
-      enable_irq( cpqfcHBAdata->HostAdapter->irq); // only way to get Sem.
-      
-      down_interruptible( cpqfcHBAdata->TYOBcomplete); 
-  
-      disable_irq( cpqfcHBAdata->HostAdapter->irq);
-  PCI_TRACE( 0xA4)
-
-      // On login exchanges, BAD_ALPA (non-existent port_id) results in 
-      // FTO (Frame Time Out) on the Outbound Completion message.
-      // If we got an FTO status, complete the exchange (free up slot)
-      if( CompleteExchange ||   // flag from Reply frames
-          pExchange->status )   // typically, can get FRAME_TO
-      {
-    	cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID);  
-      }
-    }
+			// since we are a Responder, OX_ID should already be set by
+			// cpqfcTSBuildExchange().  We need to -OR- in RX_ID
+		case SCSI_TWE:
+			SestType = 1;
+			// Requirement: set MSB of x_ID for Incoming TL data
+			// (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
 
-    else                         // SEST Exchange
-    {
-      ulStatus = 0;   // ship & pray success (e.g. FCP-SCSI)
-      
-      if( CompleteExchange )   // by Type of exchange (e.g. end-of-xchng)
-      {
-    	cpqfcTSCompleteExchange( cpqfcHBAdata->PciDev, fcChip, ExchangeID);  
-      }
-       
-      else
-        pExchange->status &= ~EXCHANGE_QUEUED;  // clear ExchangeQueued flag 
+			pExchange->fchs.ox_rx_id &= 0xFFFF0000;	// clear RX_ID
+			// Requirement: set MSB of RX_ID for Incoming TL data
+			// (see "Tachyon TL/TS User's Manual", Rev 6.0, Sept.'98, pg. 50)
+			pExchange->fchs.ox_rx_id |= (ExchangeID | 0x8000);
+			break;
 
-    }
-  }
 
-  
-  else                // ERQ 'producer' = 'consumer' and QUE is full
-  {
-    ulStatus = OUTQUE_FULL; // Outbound (ERQ) Que full
-  }
- 
-Done: 
-  PCI_TRACE( 0xA0)
-  return ulStatus; 
+		case SCSI_TRE:
+			SestType = 1;
+
+			// there is no XRDY for SEST target read; the data
+			// header needs to be updated. Also update the RSP
+			// exchange IDs for the status frame, in case it is sent automatically
+			fcChip->SEST->DataHDR[ExchangeID].ox_rx_id |= ExchangeID;
+			fcChip->SEST->RspHDR[ExchangeID].ox_rx_id = fcChip->SEST->DataHDR[ExchangeID].ox_rx_id;
+
+			// for easier FCP response logic (works for TWE and TRE), 
+			// copy exchange IDs.  (Not needed if TRE 'RSP' bit set)
+			pExchange->fchs.ox_rx_id = fcChip->SEST->DataHDR[ExchangeID].ox_rx_id;
+
+			break;
+
+
+		case FCP_RESPONSE:	// using existing OX_ID/ RX_ID pair,
+			// start SFS FCP-RESPONSE frame
+			// OX/RX_ID should already be set! (See "fcBuild" above)
+			CompleteExchange = 1;	// RSP is end of FCP-SCSI exchange
+
+
+			break;
+
+
+		case BLS_ABTS_RJT:	// uses new RX_ID, since SEST x_ID non-existent
+		case BLS_ABTS_ACC:	// using existing OX_ID/ RX_ID pair from SEST entry
+			CompleteExchange = 1;	// ACC or RJT marks end of FCP-SCSI exchange
+		case BLS_ABTS:	// using existing OX_ID/ RX_ID pair from SEST entry
+
+
+			break;
+
+
+		default:
+			printk("Error on fcStartExchange: undefined type %Xh(%d)\n", pExchange->type, pExchange->type);
+			return INVALID_ARGS;
+		}
+
+
+		// X_ID fields are entered -- copy IRB to Tachyon's ERQ
+
+
+		memcpy(&fcChip->ERQ->QEntry[ErqIndex],	// dest.
+		       &pExchange->IRB, 32);	// fixed (hardware) length!
+
+		PCI_TRACEO(ExchangeID, 0xA0)
+		    // ACTION!  May generate INT and IMQ entry
+		    writel(fcChip->ERQ->producerIndex, fcChip->Registers.ERQproducerIndex.address);
+
+
+		if (ExchangeID >= TACH_SEST_LEN)	// Link Service Outbound frame?
+		{
+
+			// wait for completion! (TDB -- timeout and chip reset)
+
+
+			PCI_TRACEO(ExchangeID, 0xA4)
+
+			    enable_irq(dev->HostAdapter->irq);	// only way to get Sem.
+
+			down_interruptible(dev->TYOBcomplete);
+
+			disable_irq(dev->HostAdapter->irq);
+			PCI_TRACE(0xA4)
+			    // On login exchanges, BAD_ALPA (non-existent port_id) results in 
+			    // FTO (Frame Time Out) on the Outbound Completion message.
+			    // If we got an FTO status, complete the exchange (free up slot)
+			    if (CompleteExchange ||	// flag from Reply frames
+				pExchange->status)	// typically, can get FRAME_TO
+			{
+				cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
+			}
+		}
+
+		else		// SEST Exchange
+		{
+			ulStatus = 0;	// ship & pray success (e.g. FCP-SCSI)
+
+			if (CompleteExchange)	// by Type of exchange (e.g. end-of-xchng)
+			{
+				cpqfcTSCompleteExchange(dev->PciDev, fcChip, ExchangeID);
+			}
+
+			else
+				pExchange->status &= ~EXCHANGE_QUEUED;	// clear ExchangeQueued flag 
+
+		}
+	}
+
+
+	else			// ERQ 'producer' = 'consumer' and QUE is full
+	{
+		ulStatus = OUTQUE_FULL;	// Outbound (ERQ) Que full
+	}
+
+      Done:
+	PCI_TRACE(0xA0)
+	    return ulStatus;
 }
 
 
@@ -5839,408 +4774,364 @@
 // (Least Recently Used) scheme.
 
 
-static LONG FindFreeExchange( PTACHYON fcChip, ULONG type )
+static s32 FindFreeExchange(PTACHYON fcChip, u32 type)
 {
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  ULONG i;
-  ULONG ulStatus=-1;  // assume failure
-
-
-  if( type == SCSI_IRE ||
-      type == SCSI_TRE ||
-      type == SCSI_IWE ||
-      type == SCSI_TWE)
-  {
-        // SCSI type - X_IDs should be from 0 to TACH_SEST_LEN-1
-    if( fcChip->fcSestExchangeLRU >= TACH_SEST_LEN) // rollover?
-      fcChip->fcSestExchangeLRU = 0;
-    i = fcChip->fcSestExchangeLRU; // typically it's already free!
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	u32 i;
+	u32 ulStatus = -1;	// assume failure
+
+
+	if (type == SCSI_IRE || type == SCSI_TRE || type == SCSI_IWE || type == SCSI_TWE) {
+		// SCSI type - X_IDs should be from 0 to TACH_SEST_LEN-1
+		if (fcChip->fcSestExchangeLRU >= TACH_SEST_LEN)	// rollover?
+			fcChip->fcSestExchangeLRU = 0;
+		i = fcChip->fcSestExchangeLRU;	// typically it's already free!
+
+		if (Exchanges->fcExchange[i].type == 0)	// check for "free" element
+		{
+			ulStatus = 0;	// success!
+		}
 
-    if( Exchanges->fcExchange[i].type == 0 ) // check for "free" element
-    {
-      ulStatus = 0; // success!
-    }
-    
-    else
-    {         // YUK! we need to do a linear search for free element.
-              // Fragmentation of the fcExchange array is due to excessively
-              // long completions or timeouts.
-      
-      while( TRUE )
-      {
-        if( ++i >= TACH_SEST_LEN ) // rollover check
-          i = 0;  // beginning of SEST X_IDs
-
-//        printk( "looping for SCSI xchng ID: i=%d, type=%Xh\n", 
-//         i, Exchanges->fcExchange[i].type);
-
-        if( Exchanges->fcExchange[i].type == 0 ) // "free"?
-        {
-          ulStatus = 0; // success!
-          break;
-        }
-        if( i == fcChip->fcSestExchangeLRU ) // wrapped-around array?
-        {
-          printk( "SEST X_ID space full\n");
-          break;       // failed - prevent inf. loop
-        }
-      }
-    }
-    fcChip->fcSestExchangeLRU = i + 1; // next! (rollover check next pass)
-  }
+		else {		// YUK! we need to do a linear search for free element.
+			// Fragmentation of the fcExchange array is due to excessively
+			// long completions or timeouts.
+
+			while (1) {
+				if (++i >= TACH_SEST_LEN)	// rollover check
+					i = 0;	// beginning of SEST X_IDs
+
+//					printk( "looping for SCSI xchng ID: i=%d, type=%Xh\n", 
+//						i, Exchanges->fcExchange[i].type);
+
+				if (Exchanges->fcExchange[i].type == 0)	// "free"?
+				{
+					ulStatus = 0;	// success!
+					break;
+				}
+				if (i == fcChip->fcSestExchangeLRU)	// wrapped-around array?
+				{
+					printk("SEST X_ID space full\n");
+					break;	// failed - prevent inf. loop
+				}
+			}
+		}
+		fcChip->fcSestExchangeLRU = i + 1;	// next! (rollover check next pass)
+	}
+	else			// Link Service type - X_IDs should be from TACH_SEST_LEN 
+				// to TACH_MAX_XID
+	{
+		if (fcChip->fcLsExchangeLRU >= TACH_MAX_XID ||	// range check
+		    fcChip->fcLsExchangeLRU < TACH_SEST_LEN)	// (e.g. startup)
+			fcChip->fcLsExchangeLRU = TACH_SEST_LEN;
+
+		i = fcChip->fcLsExchangeLRU;	// typically it's already free!
+		if (Exchanges->fcExchange[i].type == 0)	// check for "free" element
+		{
+			ulStatus = 0;	// success!
+		}
 
-  
-  
-  else  // Link Service type - X_IDs should be from TACH_SEST_LEN 
-        // to TACH_MAX_XID
-  {
-    if( fcChip->fcLsExchangeLRU >= TACH_MAX_XID || // range check
-        fcChip->fcLsExchangeLRU < TACH_SEST_LEN ) // (e.g. startup)
-      fcChip->fcLsExchangeLRU = TACH_SEST_LEN;
+		else {		// YUK! we need to do a linear search for free element
+			// Fragmentation of the fcExchange array is due to excessively
+			// long completions or timeouts.
+
+			while (1) {
+				if (++i >= TACH_MAX_XID)	// rollover check
+					i = TACH_SEST_LEN;	// beginning of Link Service X_IDs
+
+//				printk( "looping for xchng ID: i=%d, type=%Xh\n", 
+//					i, Exchanges->fcExchange[i].type);
+
+				if (Exchanges->fcExchange[i].type == 0)	// "free"?
+				{
+					ulStatus = 0;	// success!
+					break;
+				}
+				if (i == fcChip->fcLsExchangeLRU)	// wrapped-around array?
+				{
+					printk("LinkService X_ID space full\n");
+					break;	// failed - prevent inf. loop
+				}
+			}
+		}
+		fcChip->fcLsExchangeLRU = i + 1;	// next! (rollover check next pass)
 
-    i = fcChip->fcLsExchangeLRU; // typically it's already free!
-    if( Exchanges->fcExchange[i].type == 0 ) // check for "free" element
-    {
-      ulStatus = 0; // success!
-    }
-    
-    else
-    {         // YUK! we need to do a linear search for free element
-              // Fragmentation of the fcExchange array is due to excessively
-              // long completions or timeouts.
-      
-      while( TRUE )
-      {
-        if( ++i >= TACH_MAX_XID ) // rollover check
-          i = TACH_SEST_LEN;// beginning of Link Service X_IDs
-
-//        printk( "looping for xchng ID: i=%d, type=%Xh\n", 
-//         i, Exchanges->fcExchange[i].type);
-
-        if( Exchanges->fcExchange[i].type == 0 ) // "free"?
-        {
-          ulStatus = 0; // success!
-          break;
-        }
-        if( i == fcChip->fcLsExchangeLRU ) // wrapped-around array?
-        {
-          printk( "LinkService X_ID space full\n");
-          break;       // failed - prevent inf. loop
-        }
-      }
-    }
-    fcChip->fcLsExchangeLRU = i + 1; // next! (rollover check next pass)
+	}
 
-  }
+	if (!ulStatus)		// success?
+		Exchanges->fcExchange[i].type = type;	// allocate it.
 
-  if( !ulStatus )  // success?
-    Exchanges->fcExchange[i].type = type; // allocate it.
-  
-  else
-    i = -1;  // error - all exchanges "open"
+	else
+		i = -1;		// error - all exchanges "open"
 
-  return i;  
+	return i;
 }
 
-static void
-cpqfc_pci_unmap_extended_sg(struct pci_dev *pcidev,
-	PTACHYON fcChip,
-	ULONG x_ID)
+static void cpqfc_pci_unmap_extended_sg(struct pci_dev *pcidev, PTACHYON fcChip, u32 x_ID)
 {
 	// Unmaps the memory regions used to hold the scatter gather lists
 
 	PSGPAGES i;
 
 	// Were there any such regions needing unmapping?
-	if (! USES_EXTENDED_SGLIST(fcChip->SEST, x_ID))
-		return;	// No such regions, we're outta here.
+	if (!USES_EXTENDED_SGLIST(fcChip->SEST, x_ID))
+		return;		// No such regions, we're outta here.
 
 	// for each extended scatter gather region needing unmapping... 
-	for (i=fcChip->SEST->sgPages[x_ID] ; i != NULL ; i = i->next)
-		pci_unmap_single(pcidev, i->busaddr, i->maplen,
-			scsi_to_pci_dma_dir(PCI_DMA_TODEVICE));
+	for (i = fcChip->SEST->sgPages[x_ID]; i != NULL; i = i->next)
+		pci_unmap_single(pcidev, i->busaddr, i->maplen, scsi_to_pci_dma_dir(PCI_DMA_TODEVICE));
 }
 
 // Called also from cpqfcTScontrol.o, so can't be static
-void
-cpqfc_pci_unmap(struct pci_dev *pcidev, 
-	Scsi_Cmnd *cmd, 
-	PTACHYON fcChip, 
-	ULONG x_ID)
+void cpqfc_pci_unmap(struct pci_dev *pcidev, Scsi_Cmnd * cmd, PTACHYON fcChip, u32 x_ID)
 {
 	// Undo the DMA mappings
 	if (cmd->use_sg) {	// Used scatter gather list for data buffer?
 		cpqfc_pci_unmap_extended_sg(pcidev, fcChip, x_ID);
-		pci_unmap_sg(pcidev, cmd->buffer, cmd->use_sg,
-			scsi_to_pci_dma_dir(cmd->sc_data_direction));
+		pci_unmap_sg(pcidev, cmd->buffer, cmd->use_sg, scsi_to_pci_dma_dir(cmd->sc_data_direction));
 		// printk("umsg %d\n", cmd->use_sg);
-	}
-	else if (cmd->request_bufflen) {
+	} else if (cmd->request_bufflen) {
 		// printk("ums %p ", fcChip->SEST->u[ x_ID ].IWE.GAddr1);
-		pci_unmap_single(pcidev, fcChip->SEST->u[ x_ID ].IWE.GAddr1,
-			cmd->request_bufflen,
-			scsi_to_pci_dma_dir(cmd->sc_data_direction));
-	}	 
+		pci_unmap_single(pcidev, fcChip->SEST->u[x_ID].IWE.GAddr1, cmd->request_bufflen, scsi_to_pci_dma_dir(cmd->sc_data_direction));
+	}
 }
 
 // We call this routine to free an Exchange for any reason:
 // completed successfully, completed with error, aborted, etc.
 
-// returns FALSE if Exchange failed and "retry" is acceptable
-// returns TRUE if Exchange was successful, or retry is impossible
+// returns 0 if Exchange failed and "retry" is acceptable
+// returns 1 if Exchange was successful, or retry is impossible
 // (e.g. port/device gone).
 //scompleteexchange
 
-void cpqfcTSCompleteExchange( 
-       struct pci_dev *pcidev,
-       PTACHYON fcChip, 
-       ULONG x_ID)
-{
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  int already_unmapped = 0;
-  
-  if( x_ID < TACH_SEST_LEN ) // SEST-based (or LinkServ for FCP exchange)
-  {
-    if( Exchanges->fcExchange[ x_ID ].Cmnd == NULL ) // what#@!
-    {
-//      TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
-      printk(" x_ID %Xh, type %Xh, NULL ptr!\n", x_ID,
-			Exchanges->fcExchange[ x_ID ].type);
+void cpqfcTSCompleteExchange(struct pci_dev *pcidev, PTACHYON fcChip, u32 x_ID)
+{
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	int already_unmapped = 0;
 
-      goto CleanUpSestResources;  // this path should be very rare.
-    }
+	if (x_ID < TACH_SEST_LEN)	// SEST-based (or LinkServ for FCP exchange)
+	{
+		if (Exchanges->fcExchange[x_ID].Cmnd == NULL)	// what#@!
+		{
+//			TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
+			printk(" x_ID %Xh, type %Xh, NULL ptr!\n", x_ID, Exchanges->fcExchange[x_ID].type);
 
-    // we have Linux Scsi Cmnd ptr..., now check our Exchange status
-    // to decide how to complete this SEST FCP exchange
+			goto CleanUpSestResources;	// this path should be very rare.
+		}
+		// we have Linux Scsi Cmnd ptr..., now check our Exchange status
+		// to decide how to complete this SEST FCP exchange
 
-    if( Exchanges->fcExchange[ x_ID ].status ) // perhaps a Tach indicated problem,
-                                             // or abnormal exchange completion
-    {
-      // set FCP Link statistics
-     
-      if( Exchanges->fcExchange[ x_ID ].status & FC2_TIMEOUT)
-        fcChip->fcStats.timeouts++;
-      if( Exchanges->fcExchange[ x_ID ].status & INITIATOR_ABORT)
-        fcChip->fcStats.FC4aborted++;
-      if( Exchanges->fcExchange[ x_ID ].status & COUNT_ERROR)
-        fcChip->fcStats.CntErrors++;
-      if( Exchanges->fcExchange[ x_ID ].status & LINKFAIL_TX)
-        fcChip->fcStats.linkFailTX++;
-      if( Exchanges->fcExchange[ x_ID ].status & LINKFAIL_RX)
-        fcChip->fcStats.linkFailRX++;
-      if( Exchanges->fcExchange[ x_ID ].status & OVERFLOW)
-        fcChip->fcStats.CntErrors++;
-
-      // First, see if the Scsi upper level initiated an ABORT on this
-      // exchange...
-      if( Exchanges->fcExchange[ x_ID ].status == INITIATOR_ABORT )
-      {
-        printk(" DID_ABORT, x_ID %Xh, Cmnd %p ", 
-            x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
-        goto CleanUpSestResources;  // (we don't expect Linux _aborts)
-      }
-
-      // Did our driver timeout the Exchange, or did Tachyon indicate
-      // a failure during transmission?  Ask for retry with "SOFT_ERROR"
-      else if( Exchanges->fcExchange[ x_ID ].status & FC2_TIMEOUT) 
-      {
-//        printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", 
-//            x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
-        Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16);
-      }
-      
-      // Did frame(s) for an open exchange arrive in the SFQ,
-      // meaning the SEST was unable to process them?
-      else if( Exchanges->fcExchange[ x_ID ].status & SFQ_FRAME) 
-      {
-//        printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", 
-//            x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
-        Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16);
-      }
-      
-      // Did our driver timeout the Exchange, or did Tachyon indicate
-      // a failure during transmission?  Ask for retry with "SOFT_ERROR"
-      else if( 
-               (Exchanges->fcExchange[ x_ID ].status & LINKFAIL_TX) ||
-               (Exchanges->fcExchange[ x_ID ].status & PORTID_CHANGED) ||
-	       (Exchanges->fcExchange[ x_ID ].status & FRAME_TO)    ||
-	       (Exchanges->fcExchange[ x_ID ].status & INV_ENTRY)    ||
-	       (Exchanges->fcExchange[ x_ID ].status & ABORTSEQ_NOTIFY)    )
-
-
-      {
-//        printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", 
-//            x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
-        Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16);
-
-
-      }
-
-      // e.g., a LOGOut happened, or device never logged back in.
-      else if( Exchanges->fcExchange[ x_ID ].status & DEVICE_REMOVED) 
-      {
-//	printk(" *LOGOut or timeout on login!* ");
-	// trigger?
-//        TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
-
-        Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_BAD_TARGET <<16);
-      }      
-		
-		      
-      // Did Tachyon indicate a CNT error?  We need further analysis
-      // to determine if the exchange is acceptable
-      else if( Exchanges->fcExchange[ x_ID ].status == COUNT_ERROR)
-      {
-        UCHAR ScsiStatus;
-        FCP_STATUS_RESPONSE *pFcpStatus = 
-	  (PFCP_STATUS_RESPONSE)&fcChip->SEST->RspHDR[ x_ID ].pl;
-
-      	ScsiStatus = pFcpStatus->fcp_status >>24;
-  
-	// If the command is a SCSI Read/Write type, we don't tolerate
-	// count errors of any kind; assume the count error is due to
-	// a dropped frame and ask for retry...
-	
-	if(( (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0x8) ||
-	    (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0x28) ||		
-            (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0xA) ||
-            (Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0] == 0x2A) )
-	                   &&
-                     ScsiStatus == 0 )
-	{
-          // ask for retry
-/*          printk("COUNT_ERROR retry, x_ID %Xh, status %Xh, Cmnd %p\n", 
-            x_ID, Exchanges->fcExchange[ x_ID ].status,
-            Exchanges->fcExchange[ x_ID ].Cmnd);*/
-          Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_SOFT_ERROR <<16);
-	}
-	
-	else  // need more analysis
-	{
-	  cpqfcTSCheckandSnoopFCP(fcChip, x_ID);  // (will set ->result)
-	}
-      }
-      
-      // default: NOTE! We don't ever want to get here.  Getting here
-      // implies something new is happening that we've never had a test
-      // case for.  Need code maintenance!  Return "ERROR"
-      else
-      {
-	unsigned int stat = Exchanges->fcExchange[ x_ID ].status;
-        printk("DEFAULT result %Xh, x_ID %Xh, Cmnd %p", 
-          Exchanges->fcExchange[ x_ID ].status, x_ID, 
-	  Exchanges->fcExchange[ x_ID ].Cmnd);
-
-	if (stat & INVALID_ARGS)	printk(" INVALID_ARGS ");
-	if (stat & LNKDWN_OSLS)		printk(" LNKDWN_OSLS ");
-	if (stat & LNKDWN_LASER)	printk(" LNKDWN_LASER ");
-	if (stat & OUTQUE_FULL)		printk(" OUTQUE_FULL ");
-	if (stat & DRIVERQ_FULL)	printk(" DRIVERQ_FULL ");
-	if (stat & SEST_FULL)		printk(" SEST_FULL ");
-	if (stat & BAD_ALPA)		printk(" BAD_ALPA ");
-	if (stat & OVERFLOW)		printk(" OVERFLOW ");
-	if (stat & COUNT_ERROR)		printk(" COUNT_ERROR ");
-	if (stat & LINKFAIL_RX)		printk(" LINKFAIL_RX ");
-	if (stat & ABORTSEQ_NOTIFY)	printk(" ABORTSEQ_NOTIFY ");
-	if (stat & LINKFAIL_TX)		printk(" LINKFAIL_TX ");
-	if (stat & HOSTPROG_ERR)	printk(" HOSTPROG_ERR ");
-	if (stat & FRAME_TO)		printk(" FRAME_TO ");
-	if (stat & INV_ENTRY)		printk(" INV_ENTRY ");
-	if (stat & SESTPROG_ERR)	printk(" SESTPROG_ERR ");
-	if (stat & OUTBOUND_TIMEOUT)	printk(" OUTBOUND_TIMEOUT ");
-	if (stat & INITIATOR_ABORT)	printk(" INITIATOR_ABORT ");
-	if (stat & MEMPOOL_FAIL)	printk(" MEMPOOL_FAIL ");
-	if (stat & FC2_TIMEOUT)		printk(" FC2_TIMEOUT ");
-	if (stat & TARGET_ABORT)	printk(" TARGET_ABORT ");
-	if (stat & EXCHANGE_QUEUED)	printk(" EXCHANGE_QUEUED ");
-	if (stat & PORTID_CHANGED)	printk(" PORTID_CHANGED ");
-	if (stat & DEVICE_REMOVED)	printk(" DEVICE_REMOVED ");
-	if (stat & SFQ_FRAME)		printk(" SFQ_FRAME ");
-	printk("\n");
+		if (Exchanges->fcExchange[x_ID].status)	// perhaps a Tach indicated problem,
+			// or abnormal exchange completion
+		{
+			// set FCP Link statistics
+
+			if (Exchanges->fcExchange[x_ID].status & FC2_TIMEOUT)
+				fcChip->fcStats.timeouts++;
+			if (Exchanges->fcExchange[x_ID].status & INITIATOR_ABORT)
+				fcChip->fcStats.FC4aborted++;
+			if (Exchanges->fcExchange[x_ID].status & COUNT_ERROR)
+				fcChip->fcStats.CntErrors++;
+			if (Exchanges->fcExchange[x_ID].status & LINKFAIL_TX)
+				fcChip->fcStats.linkFailTX++;
+			if (Exchanges->fcExchange[x_ID].status & LINKFAIL_RX)
+				fcChip->fcStats.linkFailRX++;
+			if (Exchanges->fcExchange[x_ID].status & OVERFLOW)
+				fcChip->fcStats.CntErrors++;
+
+			// First, see if the Scsi upper level initiated an ABORT on this
+			// exchange...
+			if (Exchanges->fcExchange[x_ID].status == INITIATOR_ABORT) {
+				printk(" DID_ABORT, x_ID %Xh, Cmnd %p ", x_ID, Exchanges->fcExchange[x_ID].Cmnd);
+				goto CleanUpSestResources;	// (we don't expect Linux _aborts)
+			}
+			// Did our driver timeout the Exchange, or did Tachyon indicate
+			// a failure during transmission?  Ask for retry with "SOFT_ERROR"
+			else if (Exchanges->fcExchange[x_ID].status & FC2_TIMEOUT) {
+//				printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", 
+//					x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
+				Exchanges->fcExchange[x_ID].Cmnd->result = (DID_SOFT_ERROR << 16);
+			}
+			// Did frame(s) for an open exchange arrive in the SFQ,
+			// meaning the SEST was unable to process them?
+			else if (Exchanges->fcExchange[x_ID].status & SFQ_FRAME) {
+//				printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", 
+//					x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
+				Exchanges->fcExchange[x_ID].Cmnd->result = (DID_SOFT_ERROR << 16);
+			}
+			// Did our driver timeout the Exchange, or did Tachyon indicate
+			// a failure during transmission?  Ask for retry with "SOFT_ERROR"
+			else if ((Exchanges->fcExchange[x_ID].status & LINKFAIL_TX) ||
+				 (Exchanges->fcExchange[x_ID].status & PORTID_CHANGED) || (Exchanges->fcExchange[x_ID].status & FRAME_TO) || (Exchanges->fcExchange[x_ID].status & INV_ENTRY) || (Exchanges->fcExchange[x_ID].status & ABORTSEQ_NOTIFY))
+
+			{
+//				printk("result DID_SOFT_ERROR, x_ID %Xh, Cmnd %p\n", 
+//					x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
+				Exchanges->fcExchange[x_ID].Cmnd->result = (DID_SOFT_ERROR << 16);
 
-        Exchanges->fcExchange[ x_ID ].Cmnd->result = (DID_ERROR <<16);
-      }
-    }
-    else    // definitely no Tach problem, but perhaps an FCP problem
-    {
-      // set FCP Link statistic
-      fcChip->fcStats.ok++;
-      cpqfcTSCheckandSnoopFCP( fcChip, x_ID);  // (will set ->result)    
-    }
 
-    cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd, 
-			fcChip, x_ID); // undo DMA mappings.
-    already_unmapped = 1;
-
-    // OK, we've set the Scsi "->result" field, so proceed with calling
-    // Linux Scsi "done" (if not NULL), and free any kernel memory we
-    // may have allocated for the exchange.
-
-  PCI_TRACEO( (ULONG)Exchanges->fcExchange[x_ID].Cmnd, 0xAC);
-    // complete the command back to upper Scsi drivers
-    if( Exchanges->fcExchange[ x_ID ].Cmnd->scsi_done != NULL)
-    {
-      // Calling "done" on an Linux _abort() aborted
-      // Cmnd causes a kernel panic trying to re-free mem.
-      // Actually, we shouldn't do anything with an _abort CMND
-      if( Exchanges->fcExchange[ x_ID ].Cmnd->result != (DID_ABORT<<16) )
-      {
-        PCI_TRACE(0xAC)
-	call_scsi_done(Exchanges->fcExchange[ x_ID ].Cmnd);
-      }
-      else
-      {
-	Exchanges->fcExchange[ x_ID ].Cmnd->SCp.sent_command = 0;
-//	printk(" not calling scsi_done on x_ID %Xh, Cmnd %p\n",
-//			x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
-      }
-    }
-    else{
-	Exchanges->fcExchange[ x_ID ].Cmnd->SCp.sent_command = 0;
-      printk(" x_ID %Xh, type %Xh, Cdb0 %Xh\n", x_ID,
-	Exchanges->fcExchange[ x_ID ].type, 
-	Exchanges->fcExchange[ x_ID ].Cmnd->cmnd[0]);	      
-      printk(" cpqfcTS: Null scsi_done function pointer!\n");
-    }
+			}
+			// e.g., a LOGOut happened, or device never logged back in.
+			else if (Exchanges->fcExchange[x_ID].status & DEVICE_REMOVED) {
+//				printk(" *LOGOut or timeout on login!* ");
+//				trigger?
+//				TriggerHBA( fcChip->Registers.ReMapMemBase, 0);
+				Exchanges->fcExchange[x_ID].Cmnd->result = (DID_BAD_TARGET << 16);
+			}
+
+			// Did Tachyon indicate a CNT error?  We need further analysis
+			// to determine if the exchange is acceptable
+			else if (Exchanges->fcExchange[x_ID].status == COUNT_ERROR) {
+				u8 ScsiStatus;
+				FCP_STATUS_RESPONSE *pFcpStatus = (PFCP_STATUS_RESPONSE) & fcChip->SEST->RspHDR[x_ID].pl;
+
+				ScsiStatus = pFcpStatus->fcp_status >> 24;
+
+				// If the command is a SCSI Read/Write type, we don't tolerate
+				// count errors of any kind; assume the count error is due to
+				// a dropped frame and ask for retry...
+
+				if (((Exchanges->fcExchange[x_ID].Cmnd->cmnd[0] == 0x8) || (Exchanges->fcExchange[x_ID].Cmnd->cmnd[0] == 0x28) || (Exchanges->fcExchange[x_ID].Cmnd->cmnd[0] == 0xA) || (Exchanges->fcExchange[x_ID].Cmnd->cmnd[0] == 0x2A))
+				    && ScsiStatus == 0) {
+					// ask for retry
+//					printk("COUNT_ERROR retry, x_ID %Xh, status %Xh, Cmnd %p\n", 
+//						x_ID, Exchanges->fcExchange[ x_ID ].status,
+//						Exchanges->fcExchange[ x_ID ].Cmnd);
+					Exchanges->fcExchange[x_ID].Cmnd->result = (DID_SOFT_ERROR << 16);
+				}
+
+				else	// need more analysis
+				{
+					cpqfcTSCheckandSnoopFCP(fcChip, x_ID);	// (will set ->result)
+				}
+			}
+			// default: NOTE! We don't ever want to get here.  Getting here
+			// implies something new is happening that we've never had a test
+			// case for.  Need code maintenance!  Return "ERROR"
+			else {
+				unsigned int stat = Exchanges->fcExchange[x_ID].status;
+				printk("DEFAULT result %Xh, x_ID %Xh, Cmnd %p", Exchanges->fcExchange[x_ID].status, x_ID, Exchanges->fcExchange[x_ID].Cmnd);
+
+				if (stat & INVALID_ARGS)
+					printk(" INVALID_ARGS ");
+				if (stat & LNKDWN_OSLS)
+					printk(" LNKDWN_OSLS ");
+				if (stat & LNKDWN_LASER)
+					printk(" LNKDWN_LASER ");
+				if (stat & OUTQUE_FULL)
+					printk(" OUTQUE_FULL ");
+				if (stat & DRIVERQ_FULL)
+					printk(" DRIVERQ_FULL ");
+				if (stat & SEST_FULL)
+					printk(" SEST_FULL ");
+				if (stat & BAD_ALPA)
+					printk(" BAD_ALPA ");
+				if (stat & OVERFLOW)
+					printk(" OVERFLOW ");
+				if (stat & COUNT_ERROR)
+					printk(" COUNT_ERROR ");
+				if (stat & LINKFAIL_RX)
+					printk(" LINKFAIL_RX ");
+				if (stat & ABORTSEQ_NOTIFY)
+					printk(" ABORTSEQ_NOTIFY ");
+				if (stat & LINKFAIL_TX)
+					printk(" LINKFAIL_TX ");
+				if (stat & HOSTPROG_ERR)
+					printk(" HOSTPROG_ERR ");
+				if (stat & FRAME_TO)
+					printk(" FRAME_TO ");
+				if (stat & INV_ENTRY)
+					printk(" INV_ENTRY ");
+				if (stat & SESTPROG_ERR)
+					printk(" SESTPROG_ERR ");
+				if (stat & OUTBOUND_TIMEOUT)
+					printk(" OUTBOUND_TIMEOUT ");
+				if (stat & INITIATOR_ABORT)
+					printk(" INITIATOR_ABORT ");
+				if (stat & MEMPOOL_FAIL)
+					printk(" MEMPOOL_FAIL ");
+				if (stat & FC2_TIMEOUT)
+					printk(" FC2_TIMEOUT ");
+				if (stat & TARGET_ABORT)
+					printk(" TARGET_ABORT ");
+				if (stat & EXCHANGE_QUEUED)
+					printk(" EXCHANGE_QUEUED ");
+				if (stat & PORTID_CHANGED)
+					printk(" PORTID_CHANGED ");
+				if (stat & DEVICE_REMOVED)
+					printk(" DEVICE_REMOVED ");
+				if (stat & SFQ_FRAME)
+					printk(" SFQ_FRAME ");
+				printk("\n");
+
+				Exchanges->fcExchange[x_ID].Cmnd->result = (DID_ERROR << 16);
+			}
+		} else		// definitely no Tach problem, but perhaps an FCP problem
+		{
+			// set FCP Link statistic
+			fcChip->fcStats.ok++;
+			cpqfcTSCheckandSnoopFCP(fcChip, x_ID);	// (will set ->result)    
+		}
+
+		cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd, fcChip, x_ID);	// undo DMA mappings.
+		already_unmapped = 1;
+
+		// OK, we've set the Scsi "->result" field, so proceed with calling
+		// Linux Scsi "done" (if not NULL), and free any kernel memory we
+		// may have allocated for the exchange.
+
+		PCI_TRACEO((u32) Exchanges->fcExchange[x_ID].Cmnd, 0xAC);
+		// complete the command back to upper Scsi drivers
+		if (Exchanges->fcExchange[x_ID].Cmnd->scsi_done != NULL) {
+			// Calling "done" on an Linux _abort() aborted
+			// Cmnd causes a kernel panic trying to re-free mem.
+			// Actually, we shouldn't do anything with an _abort CMND
+			if (Exchanges->fcExchange[x_ID].Cmnd->result != (DID_ABORT << 16)) {
+				PCI_TRACE(0xAC)
+				    call_scsi_done(Exchanges->fcExchange[x_ID].Cmnd);
+			} else {
+				Exchanges->fcExchange[x_ID].Cmnd->SCp.sent_command = 0;
+//				printk(" not calling scsi_done on x_ID %Xh, Cmnd %p\n",
+//					x_ID, Exchanges->fcExchange[ x_ID ].Cmnd);
+			}
+		} else {
+			Exchanges->fcExchange[x_ID].Cmnd->SCp.sent_command = 0;
+			printk(" x_ID %Xh, type %Xh, Cdb0 %Xh\n", x_ID, Exchanges->fcExchange[x_ID].type, Exchanges->fcExchange[x_ID].Cmnd->cmnd[0]);
+			printk(" cpqfcTS: Null scsi_done function pointer!\n");
+		}
 
 
-    // Now, clean up non-Scsi_Cmnd items...
+		// Now, clean up non-Scsi_Cmnd items...
 CleanUpSestResources:
-   
-    if (!already_unmapped) 
-	cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd, 
-			fcChip, x_ID); // undo DMA mappings.
-
-    // Was an Extended Scatter/Gather page allocated?  We know
-    // this by checking DWORD 4, bit 31 ("LOC") of SEST entry
-    if( !(fcChip->SEST->u[ x_ID ].IWE.Buff_Off & 0x80000000))
-    {
-      PSGPAGES p, next;
 
-      // extended S/G list was used -- Free the allocated ext. S/G pages
-      for (p = fcChip->SEST->sgPages[x_ID]; p != NULL; p = next) {
-	 next = p->next;
-	 kfree(p);
-      }
-      fcChip->SEST->sgPages[x_ID] = NULL;
-    }
-  
-    Exchanges->fcExchange[ x_ID ].Cmnd = NULL; 
-  }  // Done with FCP (SEST) exchanges
-
-
-  // the remaining logic is common to ALL Exchanges: 
-  // FCP(SEST) and LinkServ.
-
-  Exchanges->fcExchange[ x_ID ].type = 0; // there -- FREE!  
-  Exchanges->fcExchange[ x_ID ].status = 0; 
-
-  PCI_TRACEO( x_ID, 0xAC)
-     
-  
-  return;
-}   // (END of CompleteExchange function)
- 
+		if (!already_unmapped)
+			cpqfc_pci_unmap(pcidev, Exchanges->fcExchange[x_ID].Cmnd, fcChip, x_ID);	// undo DMA mappings.
+
+		// Was an Extended Scatter/Gather page allocated?  We know
+		// this by checking DWORD 4, bit 31 ("LOC") of SEST entry
+		if (!(fcChip->SEST->u[x_ID].IWE.Buff_Off & 0x80000000)) {
+			PSGPAGES p, next;
+
+			// extended S/G list was used -- Free the allocated ext. S/G pages
+			for (p = fcChip->SEST->sgPages[x_ID]; p != NULL; p = next) {
+				next = p->next;
+				kfree(p);
+			}
+			fcChip->SEST->sgPages[x_ID] = NULL;
+		}
+
+		Exchanges->fcExchange[x_ID].Cmnd = NULL;
+	}			// Done with FCP (SEST) exchanges
+
+
+	// the remaining logic is common to ALL Exchanges: 
+	// FCP(SEST) and LinkServ.
+
+	Exchanges->fcExchange[x_ID].type = 0;	// there -- FREE!  
+	Exchanges->fcExchange[x_ID].status = 0;
+
+	PCI_TRACEO(x_ID, 0xAC)
+}				// (END of CompleteExchange function)
+
 
 
 
@@ -6249,161 +5140,137 @@
 // device types, etc., to facilitate the Fibre-Channel to SCSI
 // "mapping".  
 // (Watch for BIG Endian confusion on some payload fields)
-void cpqfcTSCheckandSnoopFCP( PTACHYON fcChip, ULONG x_ID)
+void cpqfcTSCheckandSnoopFCP(PTACHYON fcChip, u32 x_ID)
 {
-  FC_EXCHANGES *Exchanges = fcChip->Exchanges;
-  Scsi_Cmnd *Cmnd = Exchanges->fcExchange[ x_ID].Cmnd;
-  FCP_STATUS_RESPONSE *pFcpStatus = 
-    (PFCP_STATUS_RESPONSE)&fcChip->SEST->RspHDR[ x_ID ].pl;
-  UCHAR ScsiStatus;
+	FC_EXCHANGES *Exchanges = fcChip->Exchanges;
+	Scsi_Cmnd *Cmnd = Exchanges->fcExchange[x_ID].Cmnd;
+	FCP_STATUS_RESPONSE *pFcpStatus = (PFCP_STATUS_RESPONSE) & fcChip->SEST->RspHDR[x_ID].pl;
+	u8 ScsiStatus;
 
-  ScsiStatus = pFcpStatus->fcp_status >>24;
+	ScsiStatus = pFcpStatus->fcp_status >> 24;
 
 #ifdef FCP_COMPLETION_DBG
-  printk("ScsiStatus = 0x%X\n", ScsiStatus);
-#endif	
+	printk("ScsiStatus = 0x%X\n", ScsiStatus);
+#endif
 
-  // First, check FCP status
-  if( pFcpStatus->fcp_status & FCP_RSP_LEN_VALID )
-  {
-    // check response code (RSP_CODE) -- most popular is bad len
-    // 1st 4 bytes of rsp info -- only byte 3 interesting
-    if( pFcpStatus->fcp_rsp_info & FCP_DATA_LEN_NOT_BURST_LEN )
-    { 
+	// First, check FCP status
+	if (pFcpStatus->fcp_status & FCP_RSP_LEN_VALID) {
+		// check response code (RSP_CODE) -- most popular is bad len
+		// 1st 4 bytes of rsp info -- only byte 3 interesting
+		if (pFcpStatus->fcp_rsp_info & FCP_DATA_LEN_NOT_BURST_LEN) {
 
-      // do we EVER get here?
-      printk("cpqfcTS: FCP data len not burst len, x_ID %Xh\n", x_ID);
-    }
-  }
+			// do we EVER get here?
+			printk("cpqfcTS: FCP data len not burst len, x_ID %Xh\n", x_ID);
+		}
+	}
+	// for now, go by the ScsiStatus, and manipulate certain
+	// commands when necessary...
+	if (ScsiStatus == 0)	// SCSI status byte "good"?
+	{
+		Cmnd->result = 0;	// everything's OK
 
-  // for now, go by the ScsiStatus, and manipulate certain
-  // commands when necessary...
-  if( ScsiStatus == 0) // SCSI status byte "good"?
-  {
-    Cmnd->result = 0; // everything's OK
+		if ((Cmnd->cmnd[0] == INQUIRY)) {
+			u8 *InquiryData = Cmnd->request_buffer;
+			PFC_LOGGEDIN_PORT pLoggedInPort;
+
+			// We need to manipulate INQUIRY
+			// strings for COMPAQ RAID controllers to force
+			// Linux to scan additional LUNs.  Namely, set
+			// the Inquiry string byte 2 (ANSI-approved version)
+			// to 2.
+
+			if (!memcmp(&InquiryData[8], "COMPAQ", 6)) {
+				InquiryData[2] = 0x2;	// claim SCSI-2 compliance,
+				// so multiple LUNs may be scanned.
+				// (no SCSI-2 problems known in CPQ)
+			}
+			// snoop the Inquiry to detect Disk, Tape, etc. type
+			// (search linked list for the port_id we sent INQUIRY to)
+			pLoggedInPort = fcFindLoggedInPort(fcChip, NULL,	// DON'T search Scsi Nexus (we will set it)
+							   Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF, NULL,	// DON'T search linked list for FC WWN
+							   NULL);	// DON'T care about end of list
+
+			if (pLoggedInPort) {
+				pLoggedInPort->ScsiNexus.InqDeviceType = InquiryData[0];
+			} else {
+				printk("cpqfcTS: can't find LoggedIn FC port %06X for INQUIRY\n", Exchanges->fcExchange[x_ID].fchs.d_id & 0xFFFFFF);
+			}
+		}
+	}
 
-    if( (Cmnd->cmnd[0] == INQUIRY)) 
-    {
-      UCHAR *InquiryData = Cmnd->request_buffer;
-      PFC_LOGGEDIN_PORT pLoggedInPort;
+	// Scsi Status not good -- pass it back to caller 
 
-      // We need to manipulate INQUIRY
-      // strings for COMPAQ RAID controllers to force
-      // Linux to scan additional LUNs.  Namely, set
-      // the Inquiry string byte 2 (ANSI-approved version)
-      // to 2.
-
-      if( !memcmp( &InquiryData[8], "COMPAQ", 6 ))
-      {
-        InquiryData[2] = 0x2;  // claim SCSI-2 compliance,
-                               // so multiple LUNs may be scanned.
-                               // (no SCSI-2 problems known in CPQ)
-      }
-        
-      // snoop the Inquiry to detect Disk, Tape, etc. type
-      // (search linked list for the port_id we sent INQUIRY to)
-      pLoggedInPort = fcFindLoggedInPort( fcChip,
-        NULL,     // DON'T search Scsi Nexus (we will set it)
-        Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF,        
-        NULL,     // DON'T search linked list for FC WWN
-        NULL);    // DON'T care about end of list
- 
-      if( pLoggedInPort )
-      {
-        pLoggedInPort->ScsiNexus.InqDeviceType = InquiryData[0];
-      }
-      else
-      {
-	printk("cpqfcTS: can't find LoggedIn FC port %06X for INQUIRY\n",
-          Exchanges->fcExchange[ x_ID].fchs.d_id & 0xFFFFFF);
-      }
-    }
-  }
+	else {
+		Cmnd->result = ScsiStatus;	// SCSI status byte is 1st
 
+		// check for valid "sense" data
 
-  // Scsi Status not good -- pass it back to caller 
+		if (pFcpStatus->fcp_status & FCP_SNS_LEN_VALID) {	// limit Scsi Sense field length!
+			int SenseLen = pFcpStatus->fcp_sns_len >> 24;	// (BigEndian) lower byte
 
-  else
-  {
-    Cmnd->result = ScsiStatus; // SCSI status byte is 1st
-    
-    // check for valid "sense" data
+			SenseLen = SenseLen > sizeof(Cmnd->sense_buffer) ? sizeof(Cmnd->sense_buffer) : SenseLen;
 
-    if( pFcpStatus->fcp_status & FCP_SNS_LEN_VALID ) 
-    {            // limit Scsi Sense field length!
-      int SenseLen = pFcpStatus->fcp_sns_len >>24; // (BigEndian) lower byte
-      
-      SenseLen = SenseLen > sizeof( Cmnd->sense_buffer) ? 
-        sizeof( Cmnd->sense_buffer) : SenseLen;
-	   
-
-#ifdef FCP_COMPLETION_DBG	    
-      printk("copy sense_buffer %p, len %d, result %Xh\n",
-        Cmnd->sense_buffer, SenseLen, Cmnd->result);
-#endif	  
-
-      // NOTE: There is some dispute over the FCP response
-      // format.  Most FC devices assume that FCP_RSP_INFO
-      // is 8 bytes long, in spite of the fact that FCP_RSP_LEN
-      // is (virtually) always 0 and the field is "invalid".  
-      // Some other devices assume that
-      // the FCP_SNS_INFO begins after FCP_RSP_LEN bytes (i.e. 0)
-      // when the FCP_RSP is invalid (this almost appears to be
-      // one of those "religious" issues).
-      // Consequently, we test the usual position of FCP_SNS_INFO
-      // for 7Xh, since the SCSI sense format says the first
-      // byte ("error code") should be 0x70 or 0x71.  In practice,
-      // we find that every device does in fact have 0x70 or 0x71
-      // in the first byte position, so this test works for all
-      // FC devices.  
-      // (This logic is especially effective for the CPQ/DEC HSG80
-      // & HSG60 controllers).
-
-      if( (pFcpStatus->fcp_sns_info[0] & 0x70) == 0x70 )
-        memcpy( Cmnd->sense_buffer, 
-          &pFcpStatus->fcp_sns_info[0], SenseLen);
-      else
-      {
-        unsigned char *sbPtr = 
-		(unsigned char *)&pFcpStatus->fcp_sns_info[0];
-        sbPtr -= 8;  // back up 8 bytes hoping to find the
-	             // start of the sense buffer
-        memcpy( Cmnd->sense_buffer, sbPtr, SenseLen);
-      }
-
-      // in the special case of Device Reset, tell upper layer
-      // to immediately retry (with SOFT_ERROR status)
-      // look for Sense Key Unit Attention (0x6) with ASC Device
-      // Reset (0x29)
-      //	    printk("SenseLen %d, Key = 0x%X, ASC = 0x%X\n",
-      //		    SenseLen, Cmnd->sense_buffer[2], 
-      //                   Cmnd->sense_buffer[12]);
-      if( ((Cmnd->sense_buffer[2] & 0xF) == 0x6) &&
-	        (Cmnd->sense_buffer[12] == 0x29) ) // Sense Code "reset"
-      {
-        Cmnd->result |= (DID_SOFT_ERROR << 16); // "Host" status byte 3rd
-      }
- 
-      // check for SenseKey "HARDWARE ERROR", ASC InternalTargetFailure
-      else if(  ((Cmnd->sense_buffer[2] & 0xF) == 0x4) &&  // "hardware error"
-      	        (Cmnd->sense_buffer[12] == 0x44) ) // Addtl. Sense Code 
-      {
+
+#ifdef FCP_COMPLETION_DBG
+			printk("copy sense_buffer %p, len %d, result %Xh\n", Cmnd->sense_buffer, SenseLen, Cmnd->result);
+#endif
+
+			// NOTE: There is some dispute over the FCP response
+			// format.  Most FC devices assume that FCP_RSP_INFO
+			// is 8 bytes long, in spite of the fact that FCP_RSP_LEN
+			// is (virtually) always 0 and the field is "invalid".  
+			// Some other devices assume that
+			// the FCP_SNS_INFO begins after FCP_RSP_LEN bytes (i.e. 0)
+			// when the FCP_RSP is invalid (this almost appears to be
+			// one of those "religious" issues).
+			// Consequently, we test the usual position of FCP_SNS_INFO
+			// for 7Xh, since the SCSI sense format says the first
+			// byte ("error code") should be 0x70 or 0x71.  In practice,
+			// we find that every device does in fact have 0x70 or 0x71
+			// in the first byte position, so this test works for all
+			// FC devices.  
+			// (This logic is especially effective for the CPQ/DEC HSG80
+			// & HSG60 controllers).
+
+			if ((pFcpStatus->fcp_sns_info[0] & 0x70) == 0x70)
+				memcpy(Cmnd->sense_buffer, &pFcpStatus->fcp_sns_info[0], SenseLen);
+			else {
+				unsigned char *sbPtr = (unsigned char *) &pFcpStatus->fcp_sns_info[0];
+				sbPtr -= 8;	// back up 8 bytes hoping to find the
+				// start of the sense buffer
+				memcpy(Cmnd->sense_buffer, sbPtr, SenseLen);
+			}
+
+			// in the special case of Device Reset, tell upper layer
+			// to immediately retry (with SOFT_ERROR status)
+			// look for Sense Key Unit Attention (0x6) with ASC Device
+			// Reset (0x29)
+			//            printk("SenseLen %d, Key = 0x%X, ASC = 0x%X\n",
+			//                    SenseLen, Cmnd->sense_buffer[2], 
+			//                   Cmnd->sense_buffer[12]);
+			if (((Cmnd->sense_buffer[2] & 0xF) == 0x6) && (Cmnd->sense_buffer[12] == 0x29))	// Sense Code "reset"
+			{
+				Cmnd->result |= (DID_SOFT_ERROR << 16);	// "Host" status byte 3rd
+			}
+			// check for SenseKey "HARDWARE ERROR", ASC InternalTargetFailure
+			else if (((Cmnd->sense_buffer[2] & 0xF) == 0x4) &&	// "hardware error"
+				 (Cmnd->sense_buffer[12] == 0x44))	// Addtl. Sense Code 
+			{
 //        printk("HARDWARE_ERROR, Channel/Target/Lun %d/%d/%d\n",
-//		Cmnd->channel, Cmnd->target, Cmnd->lun);
-      	Cmnd->result |= (DID_ERROR << 16); // "Host" status byte 3rd
-      }
-      
-    }  // (end of sense len valid)
+//              Cmnd->channel, Cmnd->target, Cmnd->lun);
+				Cmnd->result |= (DID_ERROR << 16);	// "Host" status byte 3rd
+			}
 
-    // there is no sense data to help out Linux's Scsi layers...
-    // We'll just return the Scsi status and hope he will "do the 
-    // right thing"
-    else
-    {
-      // as far as we know, the Scsi status is sufficient
-      Cmnd->result |= (DID_OK << 16); // "Host" status byte 3rd
-    }
-  }
+		}		// (end of sense len valid)
+
+		// there is no sense data to help out Linux's Scsi layers...
+		// We'll just return the Scsi status and hope he will "do the 
+		// right thing"
+		else {
+			// as far as we know, the Scsi status is sufficient
+			Cmnd->result |= (DID_OK << 16);	// "Host" status byte 3rd
+		}
+	}
 }
 
 
@@ -6413,118 +5280,108 @@
 // remember BIG ENDIAN payload - DWord values must be byte-reversed
 // (hence the affinity for byte pointer building).
 
-static int build_FCP_payload( Scsi_Cmnd *Cmnd, 
-      UCHAR* payload, ULONG type, ULONG fcp_dl )
+static int build_FCP_payload(Scsi_Cmnd * Cmnd, u8 * payload, u32 type, u32 fcp_dl)
 {
-  int i;
+	int i;
 
-  
-  switch( type)
-  {
-		  
-    case SCSI_IWE: 
-    case SCSI_IRE:        
-      // 8 bytes FCP_LUN
-      // Peripheral Device or Volume Set addressing, and LUN mapping
-      // When the FC port was looked up, we copied address mode
-      // and any LUN mask to the scratch pad SCp.phase & .mode
-
-      *payload++ = (UCHAR)Cmnd->SCp.phase;
-
-      // Now, because of "lun masking" 
-      // (aka selective storage presentation),
-      // the contiguous Linux Scsi lun number may not match the
-      // device's lun number, so we may have to "map".  
-      
-      *payload++ = (UCHAR)Cmnd->SCp.have_data_in;
-      
-      // We don't know of anyone in the FC business using these 
-      // extra "levels" of addressing.  In fact, confusion still exists
-      // just using the FIRST level... ;-)
-      
-      *payload++ = 0;  // 2nd level addressing
-      *payload++ = 0;
-      *payload++ = 0;  // 3rd level addressing
-      *payload++ = 0;
-      *payload++ = 0;  // 4th level addressing
-      *payload++ = 0;
-
-      // 4 bytes Control Field FCP_CNTL
-      *payload++ = 0;    // byte 0: (MSB) reserved
-      *payload++ = 0;    // byte 1: task codes
-
-                         // byte 2: task management flags
-      // another "use" of the spare field to accomplish TDR
-      // note combination needed
-      if( (Cmnd->cmnd[0] == RELEASE) &&
-          (Cmnd->SCp.buffers_residual == FCP_TARGET_RESET) )
-      {
-        Cmnd->cmnd[0] = 0;    // issue "Test Unit Ready" for TDR
-        *payload++ = 0x20;    // target device reset bit
-      }
-      else
-        *payload++ = 0;    // no TDR
-		      // byte 3: (LSB) execution management codes
-		      // bit 0 write, bit 1 read (don't set together)
-      
-      if( fcp_dl != 0 )
-      {
-        if( type == SCSI_IWE )         // WRITE
-          *payload++ = 1;
-        else                           // READ
-          *payload++ = 2;
-      }
-      else
-      {
-	// On some devices, if RD or WR bits are set,
-	// and fcp_dl is 0, they will generate an error on the command.
-	// (i.e., if direction is specified, they insist on a length).
-	*payload++ = 0;                // no data (necessary for CPQ)
-      }
-
-
-      // NOTE: clean this up if/when MAX_COMMAND_SIZE is increased to 16
-      // FCP_CDB allows 16 byte SCSI command descriptor blk;
-      // Linux SCSI CDB array is MAX_COMMAND_SIZE (12 at this time...)
-      for( i=0; (i < Cmnd->cmd_len) && i < MAX_COMMAND_SIZE; i++)
-	*payload++ = Cmnd->cmnd[i];
-
-      if( Cmnd->cmd_len == 16 )
-      {
-        memcpy( payload, &Cmnd->SCp.buffers_residual, 4);
-      }
-      payload+= (16 - i);  
-
-		      // FCP_DL is largest number of expected data bytes
-		      // per CDB (i.e. read/write command)
-      *payload++ = (UCHAR)(fcp_dl >>24);  // (MSB) 8 bytes data len FCP_DL
-      *payload++ = (UCHAR)(fcp_dl >>16);
-      *payload++ = (UCHAR)(fcp_dl >>8);
-      *payload++ = (UCHAR)fcp_dl;    // (LSB)
-      break;
-
-    case SCSI_TWE:          // need FCP_XFER_RDY
-      *payload++ = 0;     // (4 bytes) DATA_RO (MSB byte 0)
-      *payload++ = 0;
-      *payload++ = 0;
-      *payload++ = 0;     // LSB (byte 3)
-			     // (4 bytes) BURST_LEN
-			     // size of following FCP_DATA payload
-      *payload++ = (UCHAR)(fcp_dl >>24);  // (MSB) 8 bytes data len FCP_DL
-      *payload++ = (UCHAR)(fcp_dl >>16);
-      *payload++ = (UCHAR)(fcp_dl >>8);
-      *payload++ = (UCHAR)fcp_dl;    // (LSB)
-		       // 4 bytes RESERVED
-      *payload++ = 0;
-      *payload++ = 0;
-      *payload++ = 0;
-      *payload++ = 0;
-      break;
 
-    default:
-      break;
-  }
+	switch (type) {
 
-  return 0;
-}
+	case SCSI_IWE:
+	case SCSI_IRE:
+		// 8 bytes FCP_LUN
+		// Peripheral Device or Volume Set addressing, and LUN mapping
+		// When the FC port was looked up, we copied address mode
+		// and any LUN mask to the scratch pad SCp.phase & .mode
+
+		*payload++ = (u8) Cmnd->SCp.phase;
+
+		// Now, because of "lun masking" 
+		// (aka selective storage presentation),
+		// the contiguous Linux Scsi lun number may not match the
+		// device's lun number, so we may have to "map".  
+
+		*payload++ = (u8) Cmnd->SCp.have_data_in;
+
+		// We don't know of anyone in the FC business using these 
+		// extra "levels" of addressing.  In fact, confusion still exists
+		// just using the FIRST level... ;-)
+
+		*payload++ = 0;	// 2nd level addressing
+		*payload++ = 0;
+		*payload++ = 0;	// 3rd level addressing
+		*payload++ = 0;
+		*payload++ = 0;	// 4th level addressing
+		*payload++ = 0;
+
+		// 4 bytes Control Field FCP_CNTL
+		*payload++ = 0;	// byte 0: (MSB) reserved
+		*payload++ = 0;	// byte 1: task codes
+
+		// byte 2: task management flags
+		// another "use" of the spare field to accomplish TDR
+		// note combination needed
+		if ((Cmnd->cmnd[0] == RELEASE) && (Cmnd->SCp.buffers_residual == FCP_TARGET_RESET)) {
+			Cmnd->cmnd[0] = 0;	// issue "Test Unit Ready" for TDR
+			*payload++ = 0x20;	// target device reset bit
+		} else
+			*payload++ = 0;	// no TDR
+		// byte 3: (LSB) execution management codes
+		// bit 0 write, bit 1 read (don't set together)
+
+		if (fcp_dl != 0) {
+			if (type == SCSI_IWE)	// WRITE
+				*payload++ = 1;
+			else	// READ
+				*payload++ = 2;
+		} else {
+			// On some devices, if RD or WR bits are set,
+			// and fcp_dl is 0, they will generate an error on the command.
+			// (i.e., if direction is specified, they insist on a length).
+			*payload++ = 0;	// no data (necessary for CPQ)
+		}
+
+
+		// NOTE: clean this up if/when MAX_COMMAND_SIZE is increased to 16
+		// FCP_CDB allows 16 byte SCSI command descriptor blk;
+		// Linux SCSI CDB array is MAX_COMMAND_SIZE (12 at this time...)
+		for (i = 0; (i < Cmnd->cmd_len) && i < MAX_COMMAND_SIZE; i++)
+			*payload++ = Cmnd->cmnd[i];
+
+		if (Cmnd->cmd_len == 16) {
+			memcpy(payload, &Cmnd->SCp.buffers_residual, 4);
+		}
+		payload += (16 - i);
 
+		// FCP_DL is largest number of expected data bytes
+		// per CDB (i.e. read/write command)
+		*payload++ = (u8) (fcp_dl >> 24);	// (MSB) 8 bytes data len FCP_DL
+		*payload++ = (u8) (fcp_dl >> 16);
+		*payload++ = (u8) (fcp_dl >> 8);
+		*payload++ = (u8) fcp_dl;	// (LSB)
+		break;
+
+	case SCSI_TWE:		// need FCP_XFER_RDY
+		*payload++ = 0;	// (4 bytes) DATA_RO (MSB byte 0)
+		*payload++ = 0;
+		*payload++ = 0;
+		*payload++ = 0;	// LSB (byte 3)
+		// (4 bytes) BURST_LEN
+		// size of following FCP_DATA payload
+		*payload++ = (u8) (fcp_dl >> 24);	// (MSB) 8 bytes data len FCP_DL
+		*payload++ = (u8) (fcp_dl >> 16);
+		*payload++ = (u8) (fcp_dl >> 8);
+		*payload++ = (u8) fcp_dl;	// (LSB)
+		// 4 bytes RESERVED
+		*payload++ = 0;
+		*payload++ = 0;
+		*payload++ = 0;
+		*payload++ = 0;
+		break;
+
+	default:
+		break;
+	}
+
+	return 0;
+}

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