/* 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/interrupt.h>
#include <asm/atomic.h>
#include "cpqfcTSioctl.h"
#define DbgDelay(secs) { int wait_time; printk( " DbgDelay %ds ", secs); \
for( wait_time=jiffies + (secs*HZ); \
time_before(jiffies, wait_time) ;) ; }
#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 5
#define VER_SUBMINOR 4
// 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"
struct SupportedPCIcards
{
__u16 vendor_id;
__u16 device_id;
};
// 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 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)
#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
irqreturn_t 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;
typedef struct {
/* This is tacked on to a Scsi_Request in upper_private_data
for pasthrough ioctls, as a place to hold data that can't
be stashed anywhere else in the Scsi_Request. We differentiate
this from _real_ upper_private_data by checking if the virt addr
is within our special pool. */
ushort bus;
ushort pdrive;
} cpqfc_passthru_private_t;
#define CPQFC_MAX_PASSTHRU_CMDS 100
#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
cpqfc_passthru_private_t *private_data_pool;
unsigned long *private_data_bits;
} 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 */