/*******************************************************************************
**
*Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved.
*
*Redistribution and use in source and binary forms, with or without modification, are permitted provided
*that the following conditions are met:
*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*2. Redistributions in binary form must reproduce the above copyright notice,
*this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
*
*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
*
*INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
*ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
*SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
*OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
*WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
*THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
**
* $FreeBSD$
**
*******************************************************************************/
#include <dev/pms/freebsd/driver/common/osenv.h>
#include <dev/pms/freebsd/driver/common/ostypes.h>
#include <dev/pms/freebsd/driver/common/osdebug.h>
#include <dev/pms/freebsd/driver/ini/src/agdef.h>
#include <dev/pms/freebsd/driver/common/lxcommon.h>
#ifdef AGTIAPI_ISCSI
#include "cmtypes.h"
#include "bktypes.h"
#endif
#ifdef FDS_DM
#include <dev/pms/RefTisa/discovery/api/dm.h>
#endif
#include <dev/pms/RefTisa/tisa/sassata/sas/ini/itdtypes.h>
#include <dev/pms/RefTisa/tisa/sassata/sas/common/tdtypes.h>
#include <dev/pms/RefTisa/tisa/api/titypes.h>
#include <vm/uma.h>
typedef u_int32_t atomic_t;
#define atomic_set(p,v) (*(p) = (v))
#define atomic_read(p) (*(p))
#define atomic_inc(p) atomic_add_int(p,1)
#define atomic_dec(p) atomic_subtract_int(p,1)
#define atomic_add(n,p) atomic_add_int(p,n)
#define atomic_sub(n,p) atomic_subtract_int(p,n)
#define AGSCSI_INIT_XCHG_LEN sizeof(tiScsiInitiatorRequest_t)
#define AGSMP_INIT_XCHG_LEN sizeof(tiSMPFrame_t)
#define CMND_DMA_UNMAP( pCard, cmnd )
// define PMC lean flags used for bit operations to track dev listing state
#define DPMC_LEANFLAG_NOAGDEVYT 2 // agDev handle not present yet
#define DPMC_LEANFLAG_NOWWNLIST 4 // WWNList entry not present
#define DPMC_LEANFLAG_AGDEVUSED 8 // agDev handle used
#define DPMC_LEANFLAG_PDEVSUSED 16 // pDevice slot used
typedef bus_dmamap_t dma_addr_t; // ##
#define timer_list callout
typedef struct ccb_hdr_s {
void *next;
} ccb_hdr_t;
typedef struct _CCB {
U32 targetId;
U32 lun;
U32 channel;
U16 ccbStatus;
U16 scsiStatus;
U32 dataLen;
U08 senseLen;
U08 addrMode;
U08 retryCount;
U16 numSgElements;
U32 flags;
U32_64 dmaHandle;
caddr_t pSenseData; // auto request sense data
tiSgl_t *sgList; // [AGTIAPI_MAX_DMA_SEGS]
bus_addr_t tisgl_busaddr;
// dma_addr_t sglDmaHandle; // ## dmaHandle for sgList
tiDeviceHandle_t *devHandle;
struct _CCB *pccbNext;
struct _CCB *pccbChainNext; // forward link pointers
struct scsi_cmnd *cmd; // call back owner pointer
struct _CCB *pccbIO; // for TM TARGET_RESET
U32_64 startTime;
tiIORequest_t tiIORequest;
tdIORequestBody_t tdIOReqBody;
tiSuperScsiInitiatorRequest_t tiSuperScsiRequest;
tiSMPFrame_t tiSMPFrame;
#ifdef CCBUILD_TEST_EPL
caddr_t epl_ptr;
dma_addr_t epl_dma_ptr;
#endif
#ifdef CCBUILD_TEST_DPL
caddr_t dplPtr;
dma_addr_t dplDma;
#endif
#if defined (PERF_COUNT)
u64 startCmnd; // temp var to hold cmnd arrival
#endif
#ifdef ENABLE_NONSTANDARD_SECTORS
caddr_t metaPtr;
dma_addr_t dmaHandleMeta;
#endif
#ifdef ENABLE_SATA_DIF
caddr_t holePtr;
dma_addr_t dmaHandleHole;
int scaling_done;
#endif
#ifdef SUPER_FAST_IO_TEST
agsaIORequest_t IoContext;
agsaSASRequestBody_t sasRequestBody;
u32 reqType;
u32 queueId;
agsaSgl_t *sgl; // Used for esgl
#endif
//new
bus_dmamap_t CCB_dmamap;
union ccb *ccb; /* replacement of struct scsi_cmnd */
struct agtiapi_softc *pmcsc;
} ccb_t, *pccb_t;
#define AGTIAPI_CCB_SIZE sizeof(struct _CCB)
/*
typedef struct _ag_portal_data
{
ag_portal_info_t portalInfo;
void *pCard;
} ag_portal_data_t;
*/
typedef enum {
DEK_TABLE_0 = 0,
DEK_TABLE_1 = 1,
DEK_TABLE_INVALID = DEK_MAX_TABLES,
} dek_table_e;
typedef struct ag_encrypt_map_s {
unsigned long long lbaMin;
unsigned long long lbaMax;
dek_table_e dekTable;
bit32 dekIndex;
bit32 kekIndex;
bit32 kekTagCheck;
bit32 kekTag[2];
struct list_head *list;
} ag_encrypt_map_t;
typedef struct ag_kek_table_s {
#define KEK_TABLE_MAX_ENTRY 8
bit32 wrapperIndex;
tiEncryptKekBlob_t kekBlob;
} ag_kek_table_t;
typedef struct ag_dek_kek_map_s {
bit32 kekIndex;
} ag_dek_kek_map_t;
/*
** There is no LUN filed for the device structure.
** The reason is if the device is a single lun device, it
** will be lun 0. If is a multi-lun device such as EMC
** or Galaxi, only one device structure is associated with
** the device since only one device handler is provided.
*/
typedef struct _ag_device {
//#ifdef HOTPLUG_SUPPORT
/* used for hot-plug, temporarily either in new or removed devices list */
LINK_NODE devLink;
//#endif
U32 targetId;
U32 flags;
U16 devType;
U16 resetCount;
U32 portalId;
void *pCard;
U32 sector_size;
U32 CCBCount;
#ifdef HOTPLUG_SUPPORT
struct scsi_device *sdev;
#endif
tiDeviceHandle_t *pDevHandle;
tiDeviceInfo_t devInfo;
ag_portal_info_t *pPortalInfo;
U08 targetName[AGTIAPI_MAX_NAME];
U16 targetLen;
U32 qbusy;
U32 qdepth;
} ag_device_t;
/*
** Use an array of these structures to map from assigned
** device target id (which is the index into the array) to
** the entry in the bd_devlist.
**
** Please note that an extra entry has been added to both
** the bd_devlist array and the bd_WWN_list. This last
** entry is the "no mapping" entry -- used for initialization
** and to indicate an inactive entry.
*/
typedef struct _ag_tgt_map {
U16 devListIndex;
U16 flags;
U08 targetName[AGTIAPI_MAX_NAME];
U16 targetLen;
U08 portId;
int sasLrIdx; // Index into SAS Local/Remote list (part of extend-portID)
uint32_t devRemoved; // when set, ghost target device is timing out
} ag_tgt_map_t;
// use an array of this struct to map local/remote dyads to ag_tgt_map_t
// entries
typedef struct _ag_slr_map {
U08 localeName[AGTIAPI_MIN_NAME];
U08 remoteName[AGTIAPI_MAX_NAME];
int localeNameLen;
int remoteNameLen;
} ag_slr_map_t;
#ifdef LINUX_PERBI_SUPPORT
// Use a list of these structures to hold target-WWN
// mapping assignments on the boot line during driver
// loading.
typedef struct _ag_mapping_s
{
struct _ag_mapping_s *next;
U16 targetId;
U08 cardNo;
U08 targetLen;
U08 targetName[AGTIAPI_MAX_NAME];
} ag_mapping_t;
#endif
typedef struct _ag_portal_data
{
ag_portal_info_t portalInfo;
void *pCard;
} ag_portal_data_t;
// The softc holds our per-instance data
struct agtiapi_softc {
device_t my_dev;
struct cdev *my_cdev;
struct cam_sim *sim;
struct cam_path *path;
struct resource *resirq;
void *intr_cookie;
int rscID[MAX_MSIX_NUM_VECTOR];
struct resource *irq[MAX_MSIX_NUM_VECTOR];
void *intrcookie[MAX_MSIX_NUM_VECTOR];
// timer stuff; mc lean
bus_dma_tag_t buffer_dmat;
struct cam_devq *devq;
struct callout OS_timer;
struct mtx OS_timer_lock;
struct callout IO_timer;
struct mtx IO_timer_lock;
struct callout devRmTimer;
struct mtx devRmTimerLock;
uint16_t rmChkCt;
// for tiSgl_t memory
tiSgl_t *tisgl_mem;
bus_addr_t tisgl_busaddr;
bus_dma_tag_t tisgl_dmat;
bus_dmamap_t tisgl_map;
// for ostiAllocMemory() pre allocation pool
void *osti_mem;
bus_addr_t osti_busaddr;
bus_dma_tag_t osti_dmat;
bus_dmamap_t osti_mapp;
// pre-allocation pool
U32 typhn; // size needed
void *typh_mem;
bus_addr_t typh_busaddr;
bus_dma_tag_t typh_dmat;
bus_dmamap_t typh_mapp;
U32 typhIdx;
U32 tyPhsIx;
// begin ag_card_t references (AKA pCard)
struct Scsi_Host *pHost;
tiRoot_t tiRoot; // tiRoot for the card
U32 VidDid;
U32 SVID_SSID;
U32 flags; // keep track of state
U32 freezeSim;
U32 up_count;
U32 down_count;
U08 hostNo; // host number signed by OS
U08 cardNo; // host no signed by driver
U16 tgtCount; // total target devices
U16 badTgtCount; // total bad target devices
U16 activeCCB; // number of active CCB
U32 ccbTotal; // total # of CCB allocated
U32 devDiscover; // # of device to be discovered
U32 resetCount;
U32 timeoutTicks;
U32 portCount; // portal count
U32 SimQFrozen; // simq frozen state
U32 devq_flag; //device busy flag
U32 dev_scan; //device ready
pccb_t ccbSendHead; // CCB send list head
pccb_t ccbSendTail; // CCB send list tail
pccb_t ccbDoneHead; // CCB done list head
pccb_t ccbDoneTail; // CCB done list tail
pccb_t smpSendHead; // CCB send list head
pccb_t smpSendTail; // CCB send list tail
pccb_t smpDoneHead; // CCB done list head
pccb_t smpDoneTail; // CCB done list tail
caddr_t *ccbChainList; // ccb chain list head
caddr_t *ccbFreeList; // free ccb list head
ccb_hdr_t *ccbAllocList; // ### ccb allocation chain list head
struct pci_pool *sglPool; // for SGL pci_alloc_consistent
struct timer_list osTimerList; // card timer list
#ifdef TD_TIMER
struct timer_list tdTimerList; // tdlayer timer list
#endif
struct timer_list tiTimerList; // tilayer timer list
ag_portal_data_t *pPortalData; // wrapper
ag_card_info_t *pCardInfo;
ag_device_t *pDevList;
#define CIPHER_MODE_INVALID 0xffffffffUL
#define DEK_INDEX_INVALID 0xffffffffUL
#define KEK_INDEX_INVALID 0xffffffffUL
int encrypt; // enable/disable encryption flag
bit32 dek_size; // size of dek
void *ioctl_data; // encryption ioctl data pointer
struct list_head *encrypt_map; // encryption map
ag_kek_table_t kek_table[KEK_TABLE_MAX_ENTRY];
// KEK table
ag_dek_kek_map_t dek_kek_map[DEK_MAX_TABLES][DEK_MAX_TABLE_ITEMS];
// storage for dek index in tables (sysfs)
int dek_index[2];
#define DEK_SIZE_PLAIN 72
#define DEK_SIZE_ENCRYPT 80
#define ENCRYPTION_MAP_MEMPOOL_SIZE 64
char map_cache_name[32]; // name of mapping memory pool
struct kmem_cache *map_cache; // handle to mapping cache
bit32 cipher_mode; // storage of cipher mode
#define ENCRYPTION_IO_ERR_MEMPOOL_SIZE 256
struct mtx ioerr_queue_lock;
char ioerr_cache_name[32];
struct kmem_cache *ioerr_cache; // handle to IO error cache
//#ifdef LINUX_PERBI_SUPPORT
ag_tgt_map_t *pWWNList;
ag_slr_map_t *pSLRList; // SAS Local/Remote map list
U32 numTgtHardMapped; // hard mapped target number
//#endif
struct sema *pIoctlSem; // for ioctl sync.
U32_64 osLockFlag; // flag for oslayer spin lock TBU
#ifdef AGTIAPI_LOCAL_LOCK
struct mtx sendLock; // local queue lock
struct mtx doneLock; // local queue lock
struct mtx sendSMPLock; // local queue lock
struct mtx doneSMPLock; // local queue lock
struct mtx ccbLock; // ccb list lock
struct mtx *STLock; // Low Level & TD locks
unsigned long *STLockFlags; // Low Level & TD locks flags
struct mtx memLock; // dynamic memory allocation lock
struct mtx freezeLock;
#endif
#ifdef AGTIAPI_DPC // card deferred intr process tasklet
struct callout tasklet_dpc[MAX_MSIX_NUM_DPC];
#endif
//#ifdef HOTPLUG_SUPPORT
struct mtx devListLock; // device lists lock
//#endif
};
int agtiapi_getdevlist( struct agtiapi_softc *pCard,
tiIOCTLPayload_t *agIOCTLPayload );
int agtiapi_getCardInfo ( struct agtiapi_softc *pCard,
U32_64 size,
void *buffer );
#ifndef LINUX_PERBI_SUPPORT
#define INDEX(_pCard, _T) (_T)
#else
#define INDEX(_pCard, _T) (((_pCard)->pWWNList + (_T))->devListIndex)
#endif