/* Copyright(c) 2000, Compaq Computer Corporation
 * Fibre Channel Host Bus Adapter 64-bit, 66MHz PCI 
 * Originally developed and tested on:
 * (front): [chip] Tachyon TS HPFC-5166A/1.2  L2C1090 ...
 *          SP# P225CXCBFIEL6T, Rev XC
 *          SP# 161290-001, Rev XD
 * (back): Board No. 010008-001 A/W Rev X5, FAB REV X5
 *  
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 * Written by Don Zimmerman
*/
#ifndef CPQFCTSSTRUCTS_H
#define CPQFCTSSTRUCTS_H

#include <linux/timer.h>  // timer declaration in our host data
#include <linux/tqueue.h> // task queue sched
#include <asm/atomic.h>
#include "cpqfcTSioctl.h"

#define DbgDelay(secs) { int wait_time; printk( " DbgDelay %ds ", secs); \
                         for( wait_time=jiffies + (secs*HZ); \
		         wait_time > jiffies ;) ; }

#define CPQFCTS_DRIVER_VER(maj,min,submin) ((maj<<16)|(min<<8)|(submin))
// don't forget to also change MODULE_DESCRIPTION in cpqfcTSinit.c
#define VER_MAJOR 2
#define VER_MINOR 1
#define VER_SUBMINOR 1

// Macros for kernel (esp. SMP) tracing using a PCI analyzer
// (e.g. x86).
//#define PCI_KERNEL_TRACE
#ifdef PCI_KERNEL_TRACE
#define PCI_TRACE(x) inl( fcChip->Registers.IOBaseL +x);
#define PCI_TRACEO(x,y) outl( x, (fcChip->Registers.IOBaseL +y));
#else

#define PCI_TRACE(x) 
#define PCI_TRACEO(x,y)
#endif

			 
//#define DEBUG_CMND 1   // debug output for Linux Scsi CDBs
//#define DUMMYCMND_DBG 1

//#define DEBUG_CPQFCTS 1
//#undef DEBUG_CPQFCTS 
#ifdef DEBUG_CPQFCTS
#define ENTER(x)	printk("cpqfcts : entering %s()\n", x);
#define LEAVE(x)	printk("cpqfcts : leaving %s()\n", x);
#define DEBUG(x)	x
#else
#define ENTER(x)
#define LEAVE(x)
#define DEBUG(x)
#endif				/* DEBUG_CPQFCTS */

//#define DEBUG_CPQFCTS_PCI 1
//#undef DEBUG_CPQFCTS_PCI
#if DEBUG_CPQFCTS_PCI
#define DEBUG_PCI(x)	x
#else
#define DEBUG_PCI(x)
#endif				/* DEBUG_CPQFCTS_PCI */

#define STACHLITE66_TS12  "Compaq FibreChannel HBA Tachyon TS HPFC-5166A/1.2"
#define STACHLITE66_TS13  "Compaq FibreChannel HBA Tachyon TS HPFC-5166A/1.3"
#define STACHLITE_UNKNOWN "Compaq FibreChannel HBA Tachyon Chip/Board Ver??"
#define SAGILENT_XL2_21   "Agilent FC HBA, Tachyon XL2 HPFC-5200B/2.1"

// PDA is Peripheral Device Address, VSA is Volume Set Addressing
// Linux SCSI parameters
#define CPQFCTS_MAX_TARGET_ID 64

// Note, changing CPQFCTS_MAX_LUN to less than 32 (e.g, 8) will result in
// strange behavior if a box with more than, e.g. 8, is on the loop.
#define CPQFCTS_MAX_LUN 32    // The RA-4x00 supports 32 (Linux SCSI supports 8)
#define CPQFCTS_MAX_CHANNEL 0 // One FC port on cpqfcTS HBA

#define CPQFCTS_CMD_PER_LUN 15 // power of 2 -1, must be >0 
#define CPQFCTS_REQ_QUEUE_LEN (TACH_SEST_LEN/2) // must be < TACH_SEST_LEN

#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s))
#ifndef DECLARE_MUTEX_LOCKED
#define DECLARE_MUTEX_LOCKED(sem) struct semaphore sem = MUTEX_LOCKED
#endif

#define DEV_NAME "cpqfcTS"

#define CPQ_DEVICE_ID     0xA0FC
#define AGILENT_XL2_ID    0x1029

typedef struct
{
  __u16 vendor_id;
  __u16 device_id;
} SupportedPCIcards;
			 
// nn:nn denotes bit field
                            // TachyonHeader struct def.
                            // the fields shared with ODB
                            // need to have same value




#ifndef BYTE
//typedef UCHAR BYTE;
typedef __u8 BYTE;
#endif
#ifndef UCHAR
typedef __u8 UCHAR;
#endif
#ifndef LONG
typedef __s32 LONG;
#endif
#ifndef ULONG
typedef __u32 ULONG;
#endif
#ifndef PVOID
typedef void * PVOID;
#endif
#ifndef USHORT
typedef __u16 USHORT;
#endif
#ifndef BOOLEAN
typedef __u8 BOOLEAN;
#endif


// macro for FC-PH reject codes
// payload format for LS_RJT (FC payloads are big endian):
//     byte  0         1         2         3  (MSB)
// DWORD 0   01        00        00        00
// DWORD 1   resvd     code      expl.     vendor

#define LS_RJT_REASON( code, expl) (( code<<8) | (expl <<16))


#define TachLiteSTATUS 0x12

// Fibre Channel EXCHANGE status codes for Tachyon chips/ driver software
// 32-bit ERROR word defines
#define INVALID_ARGS 0x1
#define LNKDWN_OSLS  0x2
#define LNKDWN_LASER 0x4
#define OUTQUE_FULL  0x8
#define DRIVERQ_FULL 0x10
#define SEST_FULL    0x20
#define BAD_ALPA     0x40
#define OVERFLOW     0x80  // inbound CM
#define COUNT_ERROR     0x100  // inbound CM
#define LINKFAIL_RX     0x200  // inbound CM
#define ABORTSEQ_NOTIFY 0x400  // outbound CM
#define LINKFAIL_TX     0x800  // outbound CM
#define HOSTPROG_ERR     0x1000  // outbound CM
#define FRAME_TO         0x2000  // outbound CM
#define INV_ENTRY        0x4000  // outbound CM
#define SESTPROG_ERR     0x8000  // outbound CM
#define OUTBOUND_TIMEOUT 0x10000L // timeout waiting for Tachyon outbound CM
#define INITIATOR_ABORT  0x20000L // initiator exchange timeout or O/S ABORT
#define MEMPOOL_FAIL     0x40000L // O/S memory pool allocation failed
#define FC2_TIMEOUT      0x80000L // driver timeout for lost frames
#define TARGET_ABORT     0x100000L // ABTS received from FC port
#define EXCHANGE_QUEUED  0x200000L // e.g. Link State was LDn on fcStart
#define PORTID_CHANGED   0x400000L // fc Port address changed
#define DEVICE_REMOVED   0x800000L // fc Port address changed
// Several error scenarios result in SEST Exchange frames 
// unexpectedly arriving in the SFQ
#define SFQ_FRAME        0x1000000L // SFQ frames from open Exchange

// Maximum number of Host Bus Adapters (HBA) / controllers supported
// only important for mem allocation dimensions - increase as necessary

#define MAX_ADAPTERS 8
#define MAX_RX_PAYLOAD 1024  // hardware dependent max frame payload
// Tach header struc defines
#define SOFi3 0x7
#define SOFf  0x8
#define SOFn3 0xB
#define EOFn  0x5
#define EOFt  0x6

// FCP R_CTL defines
#define FCP_CMND 0x6
#define FCP_XFER_RDY 0x5
#define FCP_RSP 0x7
#define FCP_RESPONSE 0x777 // (arbitrary #)
#define NEED_FCP_RSP 0x77  // (arbitrary #)
#define FCP_DATA 0x1

#define RESET_TACH 0x100 // Reset Tachyon/TachLite
#define SCSI_IWE 0x2000  // initiator write entry (for SEST)
#define SCSI_IRE 0x3000  // initiator read entry (for SEST)
#define SCSI_TRE 0x400  // target read entry (for SEST)
#define SCSI_TWE 0x500  // target write entry (for SEST)
#define TOGGLE_LASER 0x800
#define LIP 0x900
#define CLEAR_FCPORTS 99 // (arbitrary #) free mem for Logged in ports
#define FMINIT 0x707     // (arbitrary) for Frame Manager Init command

// BLS == Basic Link Service
// ELS == Extended Link Service
#define BLS_NOP 4
#define BLS_ABTS 0x10   // FC-PH Basic Link Service Abort Sequence
#define BLS_ABTS_ACC 0x100  // FC-PH Basic Link Service Abort Sequence Accept
#define BLS_ABTS_RJT 0x101  // FC-PH Basic Link Service Abort Sequence Reject
#define ELS_PLOGI 0x03  // FC-PH Port Login (arbitrary assign)
#define ELS_SCR   0x70  // (arb assign) State Change Registration (Fabric)
#define FCS_NSR   0x72  // (arb assign) Name Service Request (Fabric)
#define ELS_FLOGI 0x44  // (arb assign) Fabric Login
#define ELS_FDISC 0x41  // (arb assign) Fabric Discovery (Login)
#define ELS_PDISC 0x50  // FC-PH2 Port Discovery
#define ELS_ABTX  0x06  // FC-PH Abort Exchange 
#define ELS_LOGO 0x05   // FC-PH Port Logout
#define ELS_PRLI 0x20   // FCP-SCSI Process Login
#define ELS_PRLO 0x21   // FCP-SCSI Process Logout
#define ELS_LOGO_ACC 0x07   // {FC-PH} Port Logout Accept
#define ELS_PLOGI_ACC 0x08  // {FC-PH} Port Login Accept
#define ELS_ACC 0x18        // {FC-PH} (generic) ACCept
#define ELS_PRLI_ACC 0x22  // {FCP-SCSI} Process Login Accept
#define ELS_RJT 0x1000000
#define SCSI_REPORT_LUNS 0x0A0
#define REPORT_LUNS 0xA0 // SCSI-3 command op-code
#define FCP_TARGET_RESET 0x200

#define ELS_LILP_FRAME 0x00000711 // 1st payload word of LILP frame

#define SFQ_UNASSISTED_FCP  1  // ICM, DWord3, "Type" unassisted FCP
#define SFQ_UNKNOWN         0x31 // (arbitrary) ICM, DWord3, "Type" unknown

// these "LINK" bits refer to loop or non-loop
#define LINKACTIVE 0x2    // fcLinkQ type - LINK UP Tachyon FM 'Lup' bit set
#define LINKDOWN 0xf2     // fcLinkQ type - LINK DOWN Tachyon FM 'Ldn' bit set

//#define VOLUME_SET_ADDRESSING 1 // "channel" or "bus" 1

typedef struct      // 32 bytes hdr ONLY (e.g. FCP_DATA buffer for SEST)
{
  ULONG reserved;   // dword 0 (don't use)
  ULONG sof_eof;
  ULONG d_id;       // dword 2 - 31:24 R_CTL, 23:0 D_ID
  ULONG s_id;       // dword 3 - 31:24 CS_CTL, 23:0 S_ID
  ULONG f_ctl;      // dword 4 - 31:24 Type,  23:0 F_CTL
  ULONG seq_cnt;    // dword 5 - 31:24 SEQ_ID, 23:16 DF_CTL, 15:0 SEQ_CNT
  ULONG ox_rx_id;   // dword 6 - 31:16 OX_ID,  15:0 RX_ID
  ULONG ro;         // dword 7 - relative offset
} TachFCHDR;

                    // NOTE!! the following struct MUST be 64 bytes.
typedef struct      // 32 bytes hdr + 32 bytes payload
{
  ULONG reserved;   // dword 0 (don't use - must clear to 0)
  ULONG sof_eof;    // dword 1 - 31:24 SOF:EOF, UAM,CLS, LCr, TFV, TimeStamp
  ULONG d_id;       // dword 2 - 31:24 R_CTL, 23:0 D_ID
  ULONG s_id;       // dword 3 - 31:24 CS_CTL, 23:0 S_ID
  ULONG f_ctl;      // dword 4 - 31:24 Type,  23:0 F_CTL
  ULONG seq_cnt;    // dword 5 - 31:24 SEQ_ID, 23:16 DF_CTL, 15:0 SEQ_CNT
  ULONG ox_rx_id;   // dword 6 - 31:16 OX_ID,  15:0 RX_ID
  ULONG ro;  // dword 7 - relative offset
//---------
  __u32 pl[8];              // dwords 8-15 frame data payload
} TachFCHDR_CMND;


typedef struct      // 32 bytes hdr + 120 bytes payload
{
  ULONG reserved;   // dword 0 (don't use - must clear to 0)
  ULONG sof_eof;    // dword 1 - 31:24 SOF:EOF, UAM,CLS, LCr, TFV, TimeStamp
  ULONG d_id;       // dword 2 - 31:24 R_CTL, 23:0 D_ID
  ULONG s_id;       // dword 3 - 31:24 CS_CTL, 23:0 S_ID
  ULONG f_ctl;      // dword 4 - 31:24 Type,  23:0 F_CTL
  ULONG seq_cnt;    // dword 5 - 31:24 SEQ_ID, 23:16 DF_CTL, 15:0 SEQ_CNT
  ULONG ox_rx_id;   // dword 6 - 31:16 OX_ID,  15:0 RX_ID
  ULONG ro;  // dword 7 - relative offset
//---------
  __u32 pl[30];              // largest necessary payload (for LOGIN cmnds)
} TachFCHDR_GCMND;

typedef struct      // 32 bytes hdr + 64 bytes payload
{
  ULONG reserved;   // dword 0 (don't use)
  ULONG sof_eof;
  ULONG d_id;       // dword 2 - 31:24 R_CTL, 23:0 D_ID
  ULONG s_id;       // dword 3 - 31:24 CS_CTL, 23:0 S_ID
  ULONG f_ctl;      // dword 4 - 31:24 Type,  23:0 F_CTL
  ULONG seq_cnt;    // dword 5 - 31:24 SEQ_ID, 23:16 DF_CTL, 15:0 SEQ_CNT
  ULONG ox_rx_id;   // dword 6 - 31:16 OX_ID,  15:0 RX_ID
  ULONG ro;  // dword 7 - relative offset
//---------
  __u32 pl[18]; // payload for FCP-RSP (response buffer) RA-4x00 is 72bytes
} TachFCHDR_RSP;






// Inbound Message Queue structures...
typedef struct              // each entry 8 words (32 bytes)
{
  ULONG type;               // IMQ completion message types
  ULONG word[7];            // remainder of structure
                            // interpreted by IMQ type
} TachyonIMQE;


// Queues for TachLite not in original Tachyon
// ERQ       - Exchange Request Queue (for outbound commands)
// SFQ       - Single Frame Queue (for incoming frames)

                            // Define Tachyon Outbound Command Que
                            // (Since many Tachyon registers are Read
                            // only, maintain copies for debugging)
                            // most Tach ques need power-of-2 sizes,
                            // where registers are loaded with po2 -1
#define TACH_SEST_LEN 512   // TachLite SEST

#define ELS_EXCHANGES 64    // e.g. PLOGI, RSCN, ...
// define the total number of outstanding (simultaneous) exchanges
#define TACH_MAX_XID (TACH_SEST_LEN + ELS_EXCHANGES)  // ELS exchanges

#define ERQ_LEN 128         // power of 2, max 4096

// Inbound Message Queue structures...
#define IMQ_LEN 512              // minimum 4 entries [(power of 2) - 1]
typedef struct                   // 8 words - 32 bytes
{
  TachyonIMQE QEntry[IMQ_LEN];
  ULONG producerIndex;   // IMQ Producer Index register
                                 // @32 byte align
  ULONG consumerIndex;   // Consumer Index register (in Tachyon)
  ULONG length;          // Length register
  ULONG base;
} TachyonIMQ;                    // @ 32 * IMQ_LEN align



typedef struct           // inbound completion message
{
  ULONG Type;
  ULONG Index;
  ULONG TransferLength;
} TachyonInbCM;



// arbitrary numeric tags for TL structures
#define TL_FCHS 1  // TachLite Fibre Channel Header Structure
#define TL_IWE 2  // initiator write entry (for SEST)
#define TL_TWE 3  // target write entry (for SEST)
#define TL_IRE 4  // initiator read entry (for SEST)
#define TL_TRE 5  // target read entry (for SEST)
#define TL_IRB 6  // I/O request block

                                // for INCOMING frames
#define SFQ_LEN 32              // minimum 32 entries, max 4096

typedef struct                  // Single Frame Que
{
  TachFCHDR_CMND QEntry[SFQ_LEN]; // must be 64 bytes!!
  ULONG producerIndex;   // IMQ Producer Index register
                                 // @32 byte align
  ULONG consumerIndex;   // Consumer Index register (in Tachyon)
  ULONG length;          // Length register
  ULONG base;
} TachLiteSFQ;


typedef struct                 // I/O Request Block flags
{
  UCHAR  BRD : 1;
  UCHAR      : 1; // reserved
  UCHAR  SFA : 1;
  UCHAR  DNC : 1;
  UCHAR  DIN : 1;
  UCHAR  DCM : 1;
  UCHAR  CTS : 1;
  UCHAR  SBV : 1;  // IRB entry valid - IRB'B' only
} IRBflags;

typedef struct                  // I/O Request Block
{                          // Request 'A'
  ULONG Req_A_SFS_Len;     // total frame len (hdr + payload), min 32
  ULONG Req_A_SFS_Addr;    // 32-bit pointer to FCHS struct (to be sent)
  ULONG Req_A_SFS_D_ID;    // 24-bit FC destination (i.e. 8 bit al_pa)
  ULONG Req_A_Trans_ID;    // X_ID (OX_ID or RX_ID) and/or Index in SEST
                           // Request 'B'
  ULONG Req_B_SFS_Len;     // total frame len (hdr + payload), min 32
  ULONG Req_B_SFS_Addr;    // 32-bit pointer to FCHS struct (to be sent)
  ULONG Req_B_SFS_D_ID;    // 24-bit FC destination (i.e. 8 bit al_pa)
  ULONG Req_B_Trans_ID;    // X_ID (OX_ID or RX_ID) and/or Index in SEST
} TachLiteIRB;


typedef struct           // TachLite placeholder for IRBs
{                        // aligned @sizeof(ERQ) for TachLite
                         // MAX commands is sum of SEST len and ERQ
                         // we know that each SEST entry requires an
                         // IRB (ERQ) entry; in addition, we provide
                         // ERQ_LEN
  TachLiteIRB QEntry[ERQ_LEN]; // Base register; entries 32 bytes ea.
  ULONG consumerIndex;   // Consumer Index register
  ULONG producerIndex;   // ERQ Producer Index register
  ULONG length;          // Length register
  ULONG base;            // copy of base ptr for debug
                         // struct is sized for largest expected cmnd (LOGIN)
} TachLiteERQ;

// for now, just 32 bit DMA, eventually 40something, with code changes
#define CPQFCTS_DMA_MASK ((unsigned long) (0x00000000FFFFFFFF))

#define TL_MAX_SG_ELEM_LEN 0x7ffff  // Max buffer length a single S/G entry
				// may represent (a hardware limitation).  The
				// only reason to ever change this is if you
				// want to exercise very-hard-to-reach code in
				// cpqfcTSworker.c:build_SEST_sglist().

#define TL_DANGER_SGPAGES 7  // arbitrary high water mark for # of S/G pages
				// we must exceed to elicit a warning indicative
				// of EXTREMELY large data transfers or 
				// EXTREME memory fragmentation.
				// (means we just used up 2048 S/G elements,
				// Never seen this is real life, only in 
				// testing with tricked up driver.)

#define TL_EXT_SG_PAGE_COUNT 256  // Number of Extended Scatter/Gather a/l PAIRS
                                  // Tachyon register (IOBaseU 0x68)
                                  // power-of-2 value ONLY!  4 min, 256 max

                          // byte len is #Pairs * 2 ULONG/Pair * 4 bytes/ULONG
#define TL_EXT_SG_PAGE_BYTELEN (TL_EXT_SG_PAGE_COUNT *2 *4)



// SEST entry types: IWE, IRE, TWE, TRE
typedef struct 
{
  ULONG Hdr_Len;
  ULONG Hdr_Addr;
  ULONG RSP_Len;
  ULONG RSP_Addr;
  ULONG Buff_Off;
#define USES_EXTENDED_SGLIST(this_sest, x_ID) \
	(!((this_sest)->u[ x_ID ].IWE.Buff_Off & 0x80000000))
  ULONG Link;
  ULONG RX_ID;
  ULONG Data_Len;
  ULONG Exp_RO;
  ULONG Exp_Byte_Cnt;
   // --- extended/local Gather Len/Address pairs
  ULONG GLen1;
  ULONG GAddr1;
  ULONG GLen2;
  ULONG GAddr2;
  ULONG GLen3;
  ULONG GAddr3;
} TachLiteIWE;


typedef struct 
{
  ULONG Seq_Accum;
  ULONG reserved;       // must clear to 0
  ULONG RSP_Len;
  ULONG RSP_Addr;
  ULONG Buff_Off;
  ULONG Buff_Index;           // ULONG 5
  ULONG Exp_RO;
  ULONG Byte_Count;
  ULONG reserved_;      // ULONG 8
  ULONG Exp_Byte_Cnt;
   // --- extended/local Scatter Len/Address pairs
  ULONG SLen1;
  ULONG SAddr1;
  ULONG SLen2;
  ULONG SAddr2;
  ULONG SLen3;
  ULONG SAddr3;
} TachLiteIRE;


typedef struct          // Target Write Entry
{
  ULONG Seq_Accum;      // dword 0
  ULONG reserved;       // dword 1  must clear to 0
  ULONG Remote_Node_ID;
  ULONG reserved1;      // dword 3  must clear to 0
  ULONG Buff_Off;
  ULONG Buff_Index;     // ULONG 5
  ULONG Exp_RO;
  ULONG Byte_Count;
  ULONG reserved_;      // ULONG 8
  ULONG Exp_Byte_Cnt;
   // --- extended/local Scatter Len/Address pairs
  ULONG SLen1;
  ULONG SAddr1;
  ULONG SLen2;
  ULONG SAddr2;
  ULONG SLen3;
  ULONG SAddr3;
} TachLiteTWE;

typedef struct      
{
  ULONG Hdr_Len;
  ULONG Hdr_Addr;
  ULONG RSP_Len;        // DWord 2
  ULONG RSP_Addr;
  ULONG Buff_Off;
  ULONG Buff_Index;     // DWord 5
  ULONG reserved;
  ULONG Data_Len;
  ULONG reserved_;
  ULONG reserved__;
   // --- extended/local Gather Len/Address pairs
  ULONG GLen1;          // DWord A
  ULONG GAddr1;
  ULONG GLen2;
  ULONG GAddr2;
  ULONG GLen3;
  ULONG GAddr3;
} TachLiteTRE;

typedef struct ext_sg_page_ptr_t *PSGPAGES;
typedef struct ext_sg_page_ptr_t 
{
  unsigned char page[TL_EXT_SG_PAGE_BYTELEN * 2]; // 2x for alignment
  dma_addr_t busaddr; 	// need the bus addresses and
  unsigned int maplen;  // lengths for later pci unmapping.
  PSGPAGES next;
} SGPAGES; // linked list of S/G pairs, by Exchange

typedef struct                  // SCSI Exchange State Table
{
  union                         // Entry can be IWE, IRE, TWE, TRE
  {                             // 64 bytes per entry
    TachLiteIWE IWE;
    TachLiteIRE IRE;
    TachLiteTWE TWE;
    TachLiteTRE TRE;
  } u[TACH_SEST_LEN];

  TachFCHDR DataHDR[TACH_SEST_LEN]; // for SEST FCP_DATA frame hdr (no pl)
  TachFCHDR_RSP RspHDR[TACH_SEST_LEN]; // space for SEST FCP_RSP frame
  PSGPAGES sgPages[TACH_SEST_LEN]; // head of linked list of Pool-allocations
  ULONG length;          // Length register
  ULONG base;            // copy of base ptr for debug
} TachSEST;



typedef struct                  // each register has it's own address
                                // and value (used for write-only regs)
{
  void* address;
  volatile ULONG value;
} FCREGISTER;

typedef struct         // Host copy - TachLite Registers
{
  ULONG IOBaseL, IOBaseU;  // I/O port lower and upper TL register addresses
  ULONG MemBase;           // memory mapped register addresses
  void* ReMapMemBase;      // O/S VM reference for MemBase
  ULONG wwn_hi;            // WWN is set once at startup
  ULONG wwn_lo;
  ULONG my_al_pa;          // al_pa received after LIP()
  ULONG ROMCTR;            // flags for on-board RAM/ROM
  ULONG RAMBase;           // on-board RAM (i.e. some Tachlites)
  ULONG SROMBase;          // on-board EEPROM (some Tachlites)
  ULONG PCIMCTR;           // PCI Master Control Reg (has bus width)

  FCREGISTER INTEN;        // copy of interrupt enable mask
  FCREGISTER INTPEND;      // interrupt pending
  FCREGISTER INTSTAT;      // interrupt status
  FCREGISTER SFQconsumerIndex; 
  FCREGISTER ERQproducerIndex; 
  FCREGISTER TYconfig;   // TachYon (chip level)
  FCREGISTER TYcontrol;
  FCREGISTER TYstatus;
  FCREGISTER FMconfig;   // Frame Manager (FC loop level)
  FCREGISTER FMcontrol;
  FCREGISTER FMstatus;
  FCREGISTER FMLinkStatus1;
  FCREGISTER FMLinkStatus2;
  FCREGISTER FMBB_CreditZero;
  FCREGISTER status;
  FCREGISTER ed_tov;     // error detect time-out value
  FCREGISTER rcv_al_pa;  // received arb. loop physical address
  FCREGISTER primitive;  // e.g. LIP(), OPN(), ...
} TL_REGISTERS;



typedef struct 
{
  ULONG ok;
  ULONG invalidArgs;
  ULONG linkDown;
  ULONG linkUp;
  ULONG outQueFull;
  ULONG SESTFull;
  ULONG hpe;    // host programming err (from Tach)
  ULONG FC4aborted; // aborts from Application or upper driver layer
  ULONG FC2aborted; // aborts from our driver's timeouts
  ULONG timeouts;   // our driver timeout (on individual exchanges)
  ULONG logouts;    // explicit - sent LOGO; implicit - device removed
  ULONG retries;
  ULONG linkFailTX;
  ULONG linkFailRX;
  ULONG CntErrors;  // byte count expected != count received (typ. SEST)
  ULONG e_stores;   // elastic store errs
  ULONG resets;     // hard or soft controller resets
  ULONG FMinits;    // TACH Frame Manager Init (e.g. LIPs)
  ULONG lnkQueFull;  // too many LOGIN, loop commands
  ULONG ScsiQueFull; // too many FCP-SCSI inbound frames
  ULONG LossofSignal;   // FM link status 1 regs
  ULONG BadRXChar;   // FM link status 1 regs
  ULONG LossofSync;   // FM link status 1 regs
  ULONG Rx_EOFa;   // FM link status 2 regs (received EOFa)
  ULONG Dis_Frm;   // FM link status 2 regs (discarded frames)
  ULONG Bad_CRC;   // FM link status 2 regs
  ULONG BB0_Timer; //  FM BB_Credit Zero Timer Reg
  ULONG loopBreaks; // infinite loop exits
  ULONG lastBB0timer;  // static accum. buffer needed by Tachlite
} FCSTATS;


typedef struct               // Config Options
{                            // LS Bit first
  USHORT        : 1;           // bit0:
  USHORT  flogi : 1;           // bit1: We sent FLOGI - wait for Fabric logins
  USHORT  fabric: 1;           // bit2: Tachyon detected Fabric (FM stat LG)
  USHORT  LILPin: 1;           // bit3: We can use an FC-AL LILP frame
  USHORT  target: 1;           // bit4: this Port has SCSI target capability
  USHORT  initiator:    1;     // bit5: this Port has SCSI initiator capability
  USHORT  extLoopback:  1;     // bit6: loopback at GBIC
  USHORT  intLoopback:  1;     // bit7: loopback in HP silicon
  USHORT        : 1;           // bit8:
  USHORT        : 1;           // bit9:
  USHORT        : 1;           // bit10:
  USHORT        : 1;           // bit11:
  USHORT        : 1;           // bit12:
  USHORT        : 1;           // bit13:
  USHORT        : 1;           // bit14:
  USHORT        : 1;           // bit15:
} FC_OPTIONS;



typedef struct dyn_mem_pair
{
  void *BaseAllocated;  // address as allocated from O/S;
  unsigned long AlignedAddress; // aligned address (used by Tachyon DMA)
  dma_addr_t dma_handle;
  size_t size;
} ALIGNED_MEM;




// these structs contain only CRUCIAL (stuff we actually use) parameters
// from FC-PH(n) logins.  (Don't save entire LOGIN payload to save mem.)

// Implicit logout happens when the loop goes down - we require PDISC
// to restore.  Explicit logout is when WE decide never to talk to someone,
// or when a target refuses to talk to us, i.e. sends us a LOGO frame or
// LS_RJT reject in response to our PLOGI request.

#define IMPLICIT_LOGOUT 1
#define EXPLICIT_LOGOUT 2

typedef struct 
{
  UCHAR channel; // SCSI "bus"
  UCHAR target;
  UCHAR InqDeviceType;  // byte 0 from SCSI Inquiry response
  UCHAR VolumeSetAddressing;  // FCP-SCSI LUN coding (40h for VSA)
  UCHAR LunMasking;     // True if selective presentation supported
  UCHAR lun[CPQFCTS_MAX_LUN];
} SCSI_NEXUS;


typedef struct        
{
  union 
  {
    UCHAR ucWWN[8];  // a FC 64-bit World Wide Name/ PortID of target
                     // addressing of single target on single loop...
    u64 liWWN;
  } u;

  ULONG port_id;     // a FC 24-bit address of port (lower 8 bits = al_pa)

  Scsi_Cmnd ScsiCmnd;   // command buffer for Report Luns
#define REPORT_LUNS_PL 256  
  UCHAR ReportLunsPayload[REPORT_LUNS_PL];
  
  SCSI_NEXUS ScsiNexus; // LUNs per FC device

  ULONG LOGO_counter; // might try several times before logging out for good
  ULONG LOGO_timer;   // after LIP, ports expecting PDISC must time-out and
                      // LOGOut if successful PDISC not completed in 2 secs

  ULONG concurrent_seq;  // must be 1 or greater
  ULONG rx_data_size;    // e.g. 128, 256, 1024, 2048 per FC-PH spec
  ULONG BB_credit;
  ULONG EE_credit;

  ULONG fcp_info;        // from PRLI (i.e. INITIATOR/ TARGET flags)
                         // flags for login process
  BOOLEAN Originator;    // Login sequence Originated (if false, we
                         // responded to another port's login sequence)
  BOOLEAN plogi;         // PLOGI frame ACCepted (originated or responded)
  BOOLEAN pdisc;         // PDISC frame was ORIGINATED (self-login logic)
  BOOLEAN prli;          // PRLI frame ACCepted (originated or responded)
  BOOLEAN flogi;         // FLOGI frame ACCepted (originated or responded)
  BOOLEAN logo;          // port permanently logged out (invalid login param)
  BOOLEAN flogiReq;      // Fabric login required (set in LIP process)
  UCHAR highest_ver;
  UCHAR lowest_ver;

  
  // when the "target" (actually FC Port) is waiting for login
  // (e.g. after Link reset), set the device_blocked bit;
  // after Port completes login, un-block target.
  UCHAR device_blocked; // see Scsi_Device struct

                    // define singly-linked list of logged-in ports
                    // once a port_id is identified, it is remembered,
                    // even if the port is removed indefinitely
  PVOID pNextPort;  // actually, type PFC_LOGGEDIN_PORT; void for Compiler

} FC_LOGGEDIN_PORT, *PFC_LOGGEDIN_PORT;



// This serves as the ESB (Exchange Status Block),
// and has timeout counter; used for ABORTs
typedef struct                
{                                  // FC-1 X_IDs
  ULONG type;            // ELS_PLOGI, SCSI_IWE, ... (0 if free)
  PFC_LOGGEDIN_PORT pLoggedInPort; // FC device on other end of Exchange
  Scsi_Cmnd *Cmnd;       // Linux SCSI command packet includes S/G list
  ULONG timeOut;         // units of ??, DEC by driver, Abort when 0
  ULONG reTries;         // need one or more retries?
  ULONG status;          // flags indicating errors (0 if none)
  TachLiteIRB IRB;       // I/O Request Block, gets copied to ERQ
  TachFCHDR_GCMND fchs;  // location of IRB's Req_A_SFS_Addr
} FC_EXCHANGE, *PFC_EXCHANGE;

// Unfortunately, Linux limits our kmalloc() allocations to 128k.
// Because of this and the fact that our ScsiRegister allocation
// is also constrained, we move this large structure out for
// allocation after Scsi Register.
// (In other words, this cumbersome indirection is necessary
// because of kernel memory allocation constraints!)

typedef struct // we will allocate this dynamically
{
  FC_EXCHANGE fcExchange[ TACH_MAX_XID ];
} FC_EXCHANGES;











typedef struct
{
  char Name[64]; // name of controller ("HP Tachlite TL Rev2.0, 33MHz, 64bit bus")
  //PVOID  pAdapterDevExt; // back pointer to device object/extension
  ULONG ChipType;        // local numeric key for Tachyon Type / Rev.
  ULONG status;              // our Driver - logical status
  
  TL_REGISTERS Registers;    // reg addresses & host memory copies
                             // FC-4 mapping of 'transaction' to X_IDs
  UCHAR LILPmap[32*4];       // Loop Position Map of ALPAs (late FC-AL only)
  FC_OPTIONS Options;        // e.g. Target, Initiator, loopback...
  UCHAR highest_FCPH_ver;    // FC-PH version limits
  UCHAR lowest_FCPH_ver;     // FC-PH version limits

  FC_EXCHANGES *Exchanges;  
  ULONG fcLsExchangeLRU;       // Least Recently Used counter (Link Service)
  ULONG fcSestExchangeLRU;       // Least Recently Used counter (FCP-SCSI)
  FC_LOGGEDIN_PORT fcPorts;  // linked list of every FC port ever seen
  FCSTATS fcStats;           // FC comm err counters

                             // Host memory QUEUE pointers
  TachLiteERQ *ERQ;          // Exchange Request Que 
  TachyonIMQ *IMQ;           // Inbound Message Que 
  TachLiteSFQ *SFQ;          // Single Frame Queue
  TachSEST *SEST;            // SCSI Exchange State Table

  dma_addr_t exch_dma_handle;

  // these function pointers are for "generic" functions, which are
  // replaced with Host Bus Adapter types at
  // runtime.
  int (*CreateTachyonQues)( void* , int);
  int (*DestroyTachyonQues)( void* , int);
  int (*LaserControl)(void*, int );   // e.g. On/Off
  int (*ResetTachyon)(void*, int );
  void (*FreezeTachyon)(void*, int );
  void (*UnFreezeTachyon)(void*, int );
  int (*InitializeTachyon)(void*, int, int );
  int (*InitializeFrameManager)(void*, int );
  int (*ProcessIMQEntry)(void*);
  int (*ReadWriteWWN)(void*, int ReadWrite);
  int (*ReadWriteNVRAM)(void*, void*, int ReadWrite);

} TACHYON, *PTACHYON;


void cpqfcTSClearLinkStatusCounters(TACHYON * fcChip);

int CpqTsCreateTachLiteQues( void* pHBA, int opcode);
int CpqTsDestroyTachLiteQues( void* , int);
int CpqTsInitializeTachLite( void *pHBA, int opcode1, int opcode2);

int CpqTsProcessIMQEntry(void* pHBA);
int CpqTsResetTachLite(void *pHBA, int type);
void CpqTsFreezeTachlite(void *pHBA, int type);
void CpqTsUnFreezeTachlite(void *pHBA, int type);
int CpqTsInitializeFrameManager(void *pHBA, int);
int CpqTsLaserControl( void* addrBase, int opcode );
int CpqTsReadWriteWWN(void*, int ReadWrite);
int CpqTsReadWriteNVRAM(void*, void* data, int ReadWrite);

void cpqfcTS_WorkTask( struct Scsi_Host *HostAdapter);
void cpqfcTSWorkerThread( void *host);

int cpqfcTS_GetNVRAM_data( UCHAR *wwnbuf, UCHAR *buf );
ULONG cpqfcTS_ReadNVRAM( void* GPIOin, void* GPIOout , USHORT count,
	UCHAR *buf );

BOOLEAN tl_write_i2c_nvram( void* GPIOin, void* GPIOout,
  USHORT startOffset,  // e.g. 0x2f for WWN start
  USHORT count,
  UCHAR *buf );


// define misc functions 
int cpqfcTSGetLPSM( PTACHYON fcChip, char cErrorString[]);
int cpqfcTSDecodeGBICtype( PTACHYON fcChip, char cErrorString[]);
void* fcMemManager( struct pci_dev *pdev,
		ALIGNED_MEM *dyn_mem_pair, ULONG n_alloc, ULONG ab,
                   ULONG ulAlignedAddress, dma_addr_t *dma_handle);

void BigEndianSwap(  UCHAR *source, UCHAR *dest,  USHORT cnt);

//ULONG virt_to_phys( PVOID virtaddr );
                  

// Linux interrupt handler
void cpqfcTS_intr_handler( int irq,void *dev_id,struct pt_regs *regs);
void cpqfcTSheartbeat( unsigned long ptr );



// The biggest Q element we deal with is Aborts - we
// need 4 bytes for x_ID, and a Scsi_Cmnd (~284 bytes)
//#define LINKQ_ITEM_SIZE ((4+sizeof(Scsi_Cmnd)+3)/4)
#define LINKQ_ITEM_SIZE (3*16)
typedef struct
{
  ULONG Type;              // e.g. LINKUP, SFQENTRY, PDISC, BLS_ABTS, ...
  ULONG ulBuff[ LINKQ_ITEM_SIZE ];
} LINKQ_ITEM;

#define FC_LINKQ_DEPTH TACH_MAX_XID
typedef struct
{
  ULONG producer;
  ULONG consumer;  // when producer equals consumer, Q empty

  LINKQ_ITEM Qitem[ FC_LINKQ_DEPTH ];

} FC_LINK_QUE, *PFC_LINK_QUE;


     // DPC routines post to here on Inbound SCSI frames
     // User thread processes
#define FC_SCSIQ_DEPTH 32

typedef struct
{
  int Type;              // e.g. SCSI
  ULONG ulBuff[ 3*16 ];
} SCSIQ_ITEM;

typedef struct
{
  ULONG producer;
  ULONG consumer;  // when producer equals consumer, Q empty

  SCSIQ_ITEM Qitem[ FC_SCSIQ_DEPTH ];

} FC_SCSI_QUE, *PFC_SCSI_QUE;





#define DYNAMIC_ALLOCATIONS 4  // Tachyon aligned allocations: ERQ,IMQ,SFQ,SEST

// Linux space allocated per HBA (chip state, etc.)
typedef struct 
{
  struct Scsi_Host *HostAdapter; // back pointer to Linux Scsi struct

  TACHYON fcChip;    // All Tachyon registers, Queues, functions
  ALIGNED_MEM dynamic_mem[DYNAMIC_ALLOCATIONS];

  struct pci_dev *PciDev;
  dma_addr_t fcLQ_dma_handle;

  Scsi_Cmnd *LinkDnCmnd[CPQFCTS_REQ_QUEUE_LEN]; // collects Cmnds during LDn
                                                // (for Acceptable targets)
  Scsi_Cmnd *BoardLockCmnd[CPQFCTS_REQ_QUEUE_LEN]; // SEST was full
  
  Scsi_Cmnd *BadTargetCmnd[CPQFCTS_MAX_TARGET_ID]; // missing targets

  u_char HBAnum;     // 0-based host number


  struct timer_list cpqfcTStimer; // FC utility timer for implicit
                                  // logouts, FC protocol timeouts, etc.
  int fcStatsTime;  // Statistics delta reporting time

  struct task_struct *worker_thread; // our kernel thread
  int PortDiscDone;    // set by SendLogins(), cleared by LDn
  
  struct semaphore *TachFrozen;
  struct semaphore *TYOBcomplete;    // handshake for Tach outbound frames
  struct semaphore *fcQueReady;      // FibreChannel work for our kernel thread
  struct semaphore *notify_wt;       // synchronizes kernel thread kill
  struct semaphore *BoardLock;
  
  PFC_LINK_QUE fcLQ;             // the WorkerThread operates on this

  spinlock_t hba_spinlock;           // held/released by WorkerThread

} CPQFCHBA;

#define	CPQ_SPINLOCK_HBA( x )   spin_lock(&x->hba_spinlock);
#define CPQ_SPINUNLOCK_HBA(x)   spin_unlock(&x->hba_spinlock);



void cpqfcTSImplicitLogout( CPQFCHBA* cpqfcHBAdata,
		PFC_LOGGEDIN_PORT pFcPort);


void cpqfcTSTerminateExchange( CPQFCHBA*, SCSI_NEXUS *target, int );

PFC_LOGGEDIN_PORT fcPortLoggedIn( 
   CPQFCHBA *cpqfcHBAdata, 
   TachFCHDR_GCMND* fchs, 
   BOOLEAN, 
   BOOLEAN);
void fcProcessLoggedIn( 
   CPQFCHBA *cpqfcHBAdata, TachFCHDR_GCMND* fchs);


ULONG cpqfcTSBuildExchange( 
  CPQFCHBA *cpqfcHBAdata,
  ULONG type, // e.g. PLOGI
  TachFCHDR_GCMND* InFCHS,  // incoming FCHS
  void *Data,               // the CDB, scatter/gather, etc.  
  LONG *ExchangeID );       // allocated exchange ID

ULONG cpqfcTSStartExchange( 
  CPQFCHBA *cpqfcHBAdata,
  LONG ExchangeID );

void cpqfcTSCompleteExchange( 
       struct pci_dev *pcidev,
       PTACHYON fcChip, 
       ULONG exchange_ID);


PFC_LOGGEDIN_PORT  fcFindLoggedInPort( 
  PTACHYON fcChip, 
  Scsi_Cmnd *Cmnd,  // (We want the channel/target/lun Nexus from Cmnd)
  ULONG port_id,  // search linked list for al_pa, or
  UCHAR wwn[8],    // search linked list for WWN, or...
  PFC_LOGGEDIN_PORT *pLastLoggedInPort
);

void cpqfcTSPutLinkQue( 
  CPQFCHBA *cpqfcHBAdata, 
  int Type, 
  void *QueContent);

void fcPutScsiQue( 
  CPQFCHBA *cpqfcHBAdata, 
  int Type, 
  void *QueContent);

void fcLinkQReset(
   CPQFCHBA *);
void fcScsiQReset(
   CPQFCHBA *);
void fcSestReset(
   CPQFCHBA *);

void cpqfc_pci_unmap(struct pci_dev *pcidev, 
	Scsi_Cmnd *cmd, 
	PTACHYON fcChip, 
	ULONG x_ID);

extern const UCHAR valid_al_pa[];
extern const int number_of_al_pa;

#define FCP_RESID_UNDER   0x80000
#define FCP_RESID_OVER    0x40000
#define FCP_SNS_LEN_VALID 0x20000
#define FCP_RSP_LEN_VALID 0x10000

// RSP_CODE definitions (dpANS Fibre Channel Protocol for SCSI, pg 34)
#define FCP_DATA_LEN_NOT_BURST_LEN 0x1000000
#define FCP_CMND_FIELD_INVALID     0x2000000
#define FCP_DATA_RO_NOT_XRDY_RO    0x3000000
#define FCP_TASKFUNCTION_NS        0x4000000
#define FCP_TASKFUNCTION_FAIL      0x5000000

// FCP-SCSI response status struct
typedef struct  // see "TachFCHDR_RSP" definition - 64 bytes
{
  __u32 reserved;
  __u32 reserved1;
  __u32 fcp_status;    // field validity and SCSI status
  __u32 fcp_resid;
  __u32 fcp_sns_len;   // length of FCP_SNS_INFO field
  __u32 fcp_rsp_len;   // length of FCP_RSP_INFO field (expect 8)
  __u32 fcp_rsp_info;  // 4 bytes of FCP protocol response information
  __u32 fcp_rsp_info2; // (4 more bytes, since most implementations use 8)
  __u8  fcp_sns_info[36]; // bytes for SCSI sense (ASC, ASCQ)

} FCP_STATUS_RESPONSE, *PFCP_STATUS_RESPONSE;


// Fabric State Change Registration
typedef struct scrpl
{
  __u32 command;
  __u32 function;
} SCR_PL;

// Fabric Name Service Request
typedef struct nsrpl
{
  __u32 CT_Rev;  // (& IN_ID)   WORD 0
  __u32 FCS_Type;            // WORD 1
  __u32 Command_code;        // WORD 2
  __u32 reason_code;         // WORD 3
  __u32 FCP;                 // WORD 4 (lower byte)
  
} NSR_PL;



// "FC.H"
#define MAX_RX_SIZE		0x800	// Max Receive Buffer Size is 2048
#define MIN_RX_SIZE		0x100	// Min Size is 256, per FC-PLDA Spec
#define	MAX_TARGET_RXIDS	SEST_DEPTH
#define TARGET_RX_SIZE		SEST_BUFFER_LENGTH

#define CLASS_1			0x01
#define CLASS_2			0x02
#define CLASS_3			0x03

#define FC_PH42			0x08
#define FC_PH43			0x09
#define FC_PH3			0x20

#define RR_TOV			2	// Minimum Time for target to wait for
					// PDISC after a LIP.
#define E_D_TOV			2	// Minimum Time to wait for Sequence
					// Completion.
#define R_A_TOV			0	// Minimum Time for Target to wait 
					// before reclaiming resources.
//
//	R_CTL Field
//
//	Routing Bits (31-28)
//
#define FC4_DEVICE_DATA		0x00000000
#define EXT_LINK_DATA		0x20000000
#define FC4_LINK_DATA		0x30000000
#define VIDEO_DATA		0x40000000
#define BASIC_LINK_DATA		0x80000000
#define LINK_CONTROL		0xC0000000
#define ROUTING_MASK		0xF0000000

//
//	Information Bits (27-24)
//
#define UNCAT_INFORMATION	0x00000000
#define SOLICITED_DATA		0x01000000
#define UNSOLICITED_CONTROL	0x02000000
#define SOLICITED_CONTROL	0x03000000
#define UNSOLICITED_DATA	0x04000000
#define DATA_DESCRIPTOR		0x05000000
#define UNSOLICITED_COMMAND	0x06000000
#define COMMAND_STATUS		0x07000000
#define INFO_MASK		0x0F000000
//
//	(Link Control Codes)
//
#define ACK_1			0x00000000
#define ACK_0_OR_N		0x01000000
#define P_RJT			0x02000000 
#define F_RJT			0x03000000 
#define P_BSY			0x04000000
#define FABRIC_BUSY_TO_DF	0x05000000	// Fabric Busy to Data Frame
#define FABRIC_BUSY_TO_LC	0x06000000	// Fabric Busy to Link Ctl Frame
#define LINK_CREDIT_RESET	0x07000000
//
//	(Link Service Command Codes)
//
//#define LS_RJT			0x01000000	// LS Reject

#define LS_ACC			0x02000000	// LS Accept
#define LS_PLOGI		0x03000000	// N_PORT Login
#define LS_FLOGI		0x04000000	// F_PORT Login
#define LS_LOGO			0x05000000	// Logout
#define LS_ABTX			0x06000000	// Abort Exchange
#define LS_RCS			0x07000000	// Read Connection Status
#define LS_RES			0x08000000	// Read Exchange Status
#define LS_RSS			0x09000000	// Read Sequence Status
#define LS_RSI			0x0A000000	// Request Seq Initiative
#define LS_ESTS			0x0B000000	// Establish Steaming
#define LS_ESTC			0x0C000000	// Estimate Credit
#define LS_ADVC			0x0D000000	// Advice Credit
#define LS_RTV			0x0E000000	// Read Timeout Value
#define LS_RLS			0x0F000000	// Read Link Status
#define LS_ECHO			0x10000000	// Echo
#define LS_TEST			0x11000000	// Test
#define LS_RRQ			0x12000000	// Reinstate Rec. Qual.
#define LS_PRLI			0x20000000	// Process Login
#define LS_PRLO			0x21000000	// Process Logout
#define LS_TPRLO		0x24000000	// 3rd Party Process Logout
#define LS_PDISC		0x50000000	// Process Discovery
#define LS_FDISC		0x51000000	// Fabric Discovery
#define LS_ADISC		0x52000000	// Discover Address
#define LS_RNC			0x53000000	// Report Node Capability
#define LS_SCR                  0x62000000      // State Change Registration
#define LS_MASK			0xFF000000	

//
// 	TYPE Bit Masks
//
#define BASIC_LINK_SERVICE	0x00000000
#define EXT_LINK_SERVICE	0x01000000

#define LLC			0x04000000
#define LLC_SNAP		0x05000000
#define SCSI_FCP		0x08000000
#define SCSI_GPP		0x09000000
#define IPI3_MASTER		0x11000000
#define IPI3_SLAVE		0x12000000
#define IPI3_PEER		0x13000000
#define CP_IPI3_MASTER		0x15000000
#define CP_IPI3_SLAVE		0x16000000
#define CP_IPI3_PEER		0x17000000
#define SBCCS_CHANNEL		0x19000000
#define SBCCS_CONTROL		0x1A000000
#define FIBRE_SERVICES		0x20000000
#define FC_FG			0x21000000
#define FC_XS			0x22000000
#define FC_AL			0x23000000
#define SNMP			0x24000000
#define HIPPI_FP		0x40000000
#define TYPE_MASK		0xFF000000

typedef struct {
	UCHAR seq_id_valid;
	UCHAR seq_id;
	USHORT reserved;  // 2 bytes reserved
	ULONG ox_rx_id;
	USHORT low_seq_cnt;
	USHORT high_seq_cnt;
} BA_ACC_PAYLOAD;

typedef struct {
	UCHAR reserved;
	UCHAR reason_code;
	UCHAR reason_explain;
	UCHAR vendor_unique;
} BA_RJT_PAYLOAD;


typedef struct {
	ULONG 	command_code;
	ULONG 	sid;
	USHORT	ox_id;
	USHORT	rx_id;
} RRQ_MESSAGE;

typedef struct {
	ULONG command_code;
	UCHAR vendor;
	UCHAR explain;
	UCHAR reason;
	UCHAR reserved;
} REJECT_MESSAGE;


#define	N_OR_F_PORT		0x1000
#define RANDOM_RELATIVE_OFFSET	0x4000
#define CONTINUOSLY_INCREASING	0x8000

#define CLASS_VALID		0x8000
#define INTERMIX_MODE		0x4000
#define TRANSPARENT_STACKED	0x2000
#define LOCKDOWN_STACKED	0x1000
#define SEQ_DELIVERY		0x800

#define XID_NOT_SUPPORTED	0x00
#define XID_SUPPORTED		0x4000
#define XID_REQUIRED		0xC000

#define ASSOCIATOR_NOT_SUPPORTED	0x00
#define ASSOCIATOR_SUPPORTED	0x1000
#define ASSOCIATOR_REQUIRED	0x3000

#define	INIT_ACK0_SUPPORT	0x800
#define INIT_ACKN_SUPPORT	0x400

#define	RECIP_ACK0_SUPPORT	0x8000
#define RECIP_ACKN_SUPPORT	0x4000

#define X_ID_INTERLOCK		0x2000

#define ERROR_POLICY		0x1800		// Error Policy Supported
#define ERROR_DISCARD		0x00		// Only Discard Supported
#define ERROR_DISC_PROCESS	0x02		// Discard and process supported

#define NODE_ID			0x01
#define IEEE_EXT		0x20

//
// Categories Supported Per Sequence
//
#define	CATEGORIES_PER_SEQUENCE	0x300
#define ONE_CATEGORY_SEQUENCE	0x00		// 1 Category per Sequence
#define TWO_CATEGORY_SEQUENCE	0x01		// 2 Categories per Sequence
#define MANY_CATEGORY_SEQUENCE	0x03		// > 2 Categories/Sequence

typedef struct {

	USHORT initiator_control;
	USHORT service_options;

	USHORT rx_data_size;
	USHORT recipient_control;

	USHORT ee_credit;
	USHORT concurrent_sequences;

	USHORT reserved;
	USHORT open_sequences;

} CLASS_PARAMETERS;

typedef struct {
	ULONG	login_cmd;
	//
	// Common Service Parameters
	//
	struct {

		USHORT bb_credit;
		UCHAR lowest_ver;
		UCHAR highest_ver;

		USHORT bb_rx_size;
		USHORT common_features;

		USHORT rel_offset;
		USHORT concurrent_seq;


		ULONG e_d_tov;
	} cmn_services;

	//
	// Port Name
	//
	UCHAR port_name[8];

	//
	// Node/Fabric Name
	//
	UCHAR node_name[8];

	//
	// Class 1, 2 and 3 Service Parameters
	//
	CLASS_PARAMETERS	class1;
	CLASS_PARAMETERS	class2;
	CLASS_PARAMETERS	class3;

	ULONG reserved[4];

	//
	// Vendor Version Level
	//
	UCHAR		vendor_id[2];
	UCHAR		vendor_version[6];
	ULONG		buffer_size;
	USHORT		rxid_start;
	USHORT		total_rxids;
} LOGIN_PAYLOAD;


typedef struct
{
  ULONG cmd;  // 4 bytes
  UCHAR n_port_identifier[3];
  UCHAR reserved;
  UCHAR port_name[8];
} LOGOUT_PAYLOAD;


//
//	PRLI Request Service Parameter Defines
//
#define PRLI_ACC			0x01
#define PRLI_REQ			0x02
#define ORIG_PROCESS_ASSOC_VALID	0x8000
#define RESP_PROCESS_ASSOC_VALID	0x4000
#define ESTABLISH_PAIR			0x2000
#define DATA_OVERLAY_ALLOWED		0x40
#define	INITIATOR_FUNCTION		0x20
#define	TARGET_FUNCTION			0x10
#define CMD_DATA_MIXED			0x08
#define DATA_RESP_MIXED			0x04
#define READ_XFER_RDY			0x02
#define WRITE_XFER_RDY			0x01

#define RESPONSE_CODE_MASK	0xF00
#define REQUEST_EXECUTED	0x100
#define NO_RESOURCES		0x200
#define INIT_NOT_COMPLETE	0x300
#define IMAGE_DOES_NOT_EXIST	0x400
#define BAD_PREDEFINED_COND	0x500
#define REQ_EXEC_COND		0x600
#define NO_MULTI_PAGE		0x700

typedef struct {
	USHORT	payload_length;
	UCHAR	page_length;
	UCHAR	cmd;


	ULONG	valid;

	ULONG	orig_process_associator;

	ULONG	resp_process_associator;
	
	ULONG	fcp_info;
} PRLI_REQUEST;

typedef struct {

	USHORT	payload_length;
	UCHAR	page_length;
	UCHAR	cmd;

	ULONG	valid;
	ULONG	orig_process_associator;

	ULONG	resp_process_associator;
	ULONG	reserved;
} PRLO_REQUEST;

typedef struct {
	ULONG	cmd;

	ULONG	hard_address;
	
	UCHAR	port_name[8];

	UCHAR	node_name[8];

	ULONG	s_id;
} ADISC_PAYLOAD;

struct ext_sg_entry_t {
	__u32 len:18;		/* buffer length, bits 0-17 */
	__u32 uba:13;		/* upper bus address bits 18-31 */
	__u32 lba;		/* lower bus address bits 0-31 */
}; 

// J. McCarty's LINK.H
//
//	LS_RJT Reason Codes
//

#define INVALID_COMMAND_CODE	0x01
#define LOGICAL_ERROR		0x03
#define LOGICAL_BUSY		0x05
#define PROTOCOL_ERROR		0x07
#define UNABLE_TO_PERFORM	0x09
#define COMMAND_NOT_SUPPORTED	0x0B
#define LS_VENDOR_UNIQUE	0xFF

//
// 	LS_RJT Reason Codes Explanations
//
#define NO_REASON		0x00
#define OPTIONS_ERROR		0x01
#define INITIATOR_CTL_ERROR	0x03
#define RECIPIENT_CTL_ERROR	0x05
#define DATA_FIELD_SIZE_ERROR	0x07
#define CONCURRENT_SEQ_ERROR	0x09
#define CREDIT_ERROR		0x0B
#define INVALID_PORT_NAME	0x0D
#define INVALID_NODE_NAME	0x0E
#define INVALID_CSP		0x0F	// Invalid Service Parameters
#define INVALID_ASSOC_HDR	0x11	// Invalid Association Header
#define ASSOC_HDR_REQUIRED	0x13	// Association Header Required
#define LS_INVALID_S_ID		0x15
#define INVALID_OX_RX_ID	0x17	// Invalid OX_ID RX_ID Combination
#define CMD_IN_PROCESS		0x19
#define INVALID_IDENTIFIER	0x1F	// Invalid N_PORT Identifier
#define INVALID_SEQ_ID		0x21
#define ABT_INVALID_XCHNG	0x23 	// Attempt to Abort an invalid Exchange
#define ABT_INACTIVE_XCHNG	0x25 	// Attempt to Abort an inactive Exchange
#define NEED_REC_QUAL		0x27	// Recovery Qualifier required
#define NO_LOGIN_RESOURCES	0x29	// No resources to support login
#define NO_DATA			0x2A	// Unable to supply requested data
#define	REQUEST_NOT_SUPPORTED	0x2C	// Request Not Supported

//
//	Link Control Codes
//

//
//	P_BSY Action Codes
//
#define SEQUENCE_TERMINATED	0x01000000
#define SEQUENCE_ACTIVE		0x02000000

//
//	P_BSY Reason Codes
//
#define PHYS_NPORT_BUSY		0x010000
#define NPORT_RESOURCE_BUSY	0x020000

//
// 	P_RJT, F_RJT Action Codes
//

#define RETRYABLE_ERROR		0x01000000
#define NON_RETRYABLE_ERROR	0x02000000

//
// 	P_RJT, F_RJT Reason Codes
//
#define INVALID_D_ID		0x010000
#define INVALID_S_ID		0x020000
#define NPORT_NOT_AVAIL_TMP	0x030000
#define NPORT_NOT_AVAIL_PERM	0x040000
#define CLASS_NOT_SUPPORTED	0x050000
#define USAGE_ERROR		0x060000
#define TYPE_NOT_SUPPORTED	0x070000
#define INVAL_LINK_CONTROL	0x080000
#define INVAL_R_CTL		0x090000
#define INVAL_F_CTL		0x0A0000
#define INVAL_OX_ID		0x0B0000
#define INVAL_RX_ID		0x0C0000
#define INVAL_SEQ_ID		0x0D0000
#define INVAL_DF_CTL		0x0E0000
#define INVAL_SEQ_CNT		0x0F0000
#define INVAL_PARAMS		0x100000
#define EXCHANGE_ERROR		0x110000
#define LS_PROTOCOL_ERROR	0x120000
#define INCORRECT_LENGTH	0x130000
#define UNEXPECTED_ACK		0x140000
#define LOGIN_REQ		0x160000
#define EXCESSIVE_SEQ		0x170000
#define NO_EXCHANGE		0x180000
#define SEC_HDR_NOT_SUPPORTED	0x190000
#define NO_FABRIC		0x1A0000
#define P_VENDOR_UNIQUE		0xFF0000

//
// 	BA_RJT Reason Codes
//
#define BA_INVALID_COMMAND	0x00010000
#define BA_LOGICAL_ERROR	0x00030000
#define BA_LOGICAL_BUSY		0x00050000
#define BA_PROTOCOL_ERROR	0x00070000
#define BA_UNABLE_TO_PERFORM	0x00090000

//
// 	BA_RJT Reason Explanation Codes
//
#define BA_NO_REASON		0x00000000
#define BA_INVALID_OX_RX	0x00000300
#define BA_SEQUENCE_ABORTED	0x00000500



#endif /* CPQFCTSSTRUCTS_H	*/

