root/usr/src/uts/sun/sys/scsi/adapters/sfvar.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _SYS_SCSI_ADAPTERS_SFVAR_H
#define _SYS_SCSI_ADAPTERS_SFVAR_H

#pragma ident   "%Z%%M% %I%     %E% SMI"

/*
 * FC-AL FCP driver definitions
 */

#ifdef  __cplusplus
extern "C" {
#endif

/*
 * this is to generate unique minor numbers for each minor
 * node type being created. because of the limitations by SCSA,
 * we have to use minor number values from 32 to 63 for the HBA
 * drivers use
 */
#define SF_BASE_MINOR           32
#define SF_DEVCTL_MINOR         (SF_BASE_MINOR + 1)
#define SF_FC_MINOR             (SF_BASE_MINOR + 2)
#define SF_INST_SHIFT4MINOR     6
#define SF_INST2DEVCTL_MINOR(x) (((x) << SF_INST_SHIFT4MINOR) | SF_DEVCTL_MINOR)
#define SF_INST2FC_MINOR(x)     (((x) << SF_INST_SHIFT4MINOR) | SF_FC_MINOR)
#define SF_MINOR2INST(x)        ((x) >> SF_INST_SHIFT4MINOR)

#define SF_INIT_ITEMS           5
#define SF_MAX_TARGETS          126
#define SF_MAX_LILP_ENTRIES     126

#define SF_NUM_HASH_QUEUES      32
#define SF_HASH(x, y)   ((x[0]+x[1]+x[2]+x[3]+x[4]+x[5]+x[6]+x[7]) &\
(SF_NUM_HASH_QUEUES-1))


/*
 * sf driver needs to be sanitized for exporting some of its
 * macros/variables to userland programs.
 */
#ifdef  _KERNEL

/*
 * sf instance structure
 */

struct sf {
        struct scsi_hba_tran *sf_tran;
        dev_info_t      *sf_dip;
        struct sf       *sf_next;
        struct sf       *sf_sibling;
        kmutex_t        sf_mutex;
        kmutex_t        sf_cr_mutex;
        uint_t          sf_state;
        int64_t         sf_reset_time;  /* reset/lip init time for bus_config */
        struct sf_target *sf_targets[SF_MAX_TARGETS];
        struct sf_target *sf_wwn_lists[SF_NUM_HASH_QUEUES];
        void            *sf_socp;       /* pointer to socal state */
        struct fcal_transport *sf_sochandle;
        kmutex_t        sf_cmd_mutex;
        int             sf_throttle;
        int             sf_ncmds;
        int             sf_ncmds_exp_avg;
        int             sf_device_count;
        uint_t          sf_use_lock;
        uint_t          sf_timer;
        uint_t          sf_online_timer;
        int             sf_take_core;
        struct kmem_cache *sf_pkt_cache;
        struct sf_pkt *sf_pkt_head; /* packet queue */
        struct sf_pkt *sf_pkt_tail;
        struct sf_els_hdr *sf_els_list;
        struct sf_reset_list    *sf_reset_list;
        kcondvar_t      sf_cr_cv;
        uint_t          sf_cr_pool_cnt;
        struct sf_cr_pool *sf_cr_pool; /* list of command/response pools */
        uchar_t         sf_al_pa;
        uchar_t         sf_busy;
        uchar_t         sf_flag;
        uchar_t         sf_cr_flag; /* synchronize creation of new cr pools */
        uint_t          sf_lip_cnt;
        struct scsi_reset_notify_entry  *sf_reset_notify_listf;
        struct fcal_lilp_map    *sf_lilp_map;
        ddi_dma_handle_t        sf_lilp_dmahandle;
        ddi_acc_handle_t        sf_lilp_acchandle;
        ddi_dma_cookie_t        sf_lilp_dmacookie;
        kstat_t         *sf_ksp;
        kmutex_t        sf_hp_daemon_mutex;
        kcondvar_t      sf_hp_daemon_cv;
        struct sf_hp_elem *sf_hp_elem_head;
        struct sf_hp_elem *sf_hp_elem_tail;
        /*
         * Event handling
         */
        ndi_event_definition_t  *sf_event_defs;
        ndi_event_hdl_t         sf_event_hdl;
        ndi_event_set_t         sf_events;
        struct  sf_stats        sf_stats;
        uchar_t         sf_hp_exit;     /* hotplugging thread exit flag */
        uchar_t         sf_check_n_close;
                /* check if unopened sf is being closed */
        kt_did_t        sf_hp_tid;      /* hotplug thread id */
};

#define SF_STATE_INIT           0x01
#define SF_STATE_OFFLINE        0x02
#define SF_STATE_ONLINE         0x04
#define SF_STATE_ONLINING       0x08
#define SF_STATE_SUSPENDED      0x10            /* driver has been suspended */

#define SF_EVENT_TAG_INSERT     0
#define SF_EVENT_TAG_REMOVE     1

/*
 * pool of sf command response blocks
 */

struct  sf_cr_pool {
        struct  sf_cr_pool      *next;
        struct  sf_cr_free_elem *free;
        struct  sf              *sf;
        caddr_t                 cmd_base;       /* start addr of this chunk */
        ddi_dma_handle_t        cmd_dma_handle; /* dma mapping for this chunk */
        ddi_acc_handle_t        cmd_acc_handle;
        caddr_t                 rsp_base;
        ddi_dma_handle_t        rsp_dma_handle;
        ddi_acc_handle_t        rsp_acc_handle;
        uint_t                  nfree;
        uint_t                  ntot;
};

#define SF_CR_POOL_MAX          32      /* allows 4096 outstanding packets */

#define SF_ELEMS_IN_POOL        128
#define SF_LOG2_ELEMS_IN_POOL   7       /* LOG2 SF_ELEMS_IN_POOL */
#define SF_FREE_CR_EPSILON      64      /* SF_ELEMS_IN_POOL /2 */

/*
 * sf command/response free structure which is overlaid on fcp_cmd
 */

struct  sf_cr_free_elem {
        struct          sf_cr_free_elem *next;
        caddr_t         rsp;            /* ptr to corresponding rsp */
        uint_t          cmd_dmac;       /* dmac_address for cmd */
        uint_t          rsp_dmac;       /* dmac_address for rsp */
};

/*
 * list of targets for reset delay handling
 */

struct sf_reset_list {
        struct sf_reset_list    *next;
        struct sf_target        *target;
        clock_t                 timeout;
        uint_t                  lip_cnt;
};

/*
 * structure used to store hotplug event callback info
 */

struct sf_hp_event {
        int (*callback)();
        void *arg;
};


/*
 * sf per target structure
 */

struct sf_target        {
        struct sf_pkt *sft_pkt_head; /* queue of active commands */
        struct sf_pkt *sft_pkt_tail;
        kmutex_t        sft_mutex;
        kcondvar_t      sft_cv;
        kmutex_t        sft_pkt_mutex;
        dev_info_t      *sft_dip;
        uchar_t         sft_node_wwn[FC_WWN_SIZE];
        uchar_t         sft_port_wwn[FC_WWN_SIZE];
        union {
                /* It's easier to shove around an int64 than a byte array */
                uchar_t b[FCP_LUN_SIZE];
                int64_t l;
        }               sft_lun;
        /* XXXX The RAID LUN field is used to implement FCP Annex C */
#ifdef RAID_LUNS
        uint_t          sft_raid_lun;
#define SCSA_LUN(t)     (int64_t)(t)->sft_raid_lun
#else
#define SCSA_LUN(t)     (t)->sft_lun.l
#endif
        uchar_t         sft_hard_address;
        uchar_t         sft_al_pa;
        uchar_t         sft_device_type;
        uchar_t         sft_scan_count;
        uint_t          sft_alive;
        uint_t          sft_state;
        uint_t          sft_lip_cnt;
        struct scsi_hba_tran *sft_tran;
        struct sf_target        *sft_next;
        struct sf_target        *sft_next_lun;
        struct sf_hp_event sft_insert_ev;
        struct sf_hp_event sft_remove_ev;
        struct scsi_inquiry     sft_inq;
};

#define SF_TARGET_INIT_DONE     0x1
#define SF_TARGET_BUSY          0x2
#define SF_TARGET_OFFLINE       0x4
#define SF_TARGET_MARK          0x8

/*
 * sf packet
 */

#define PKT2CMD(pkt)            ((struct sf_pkt *)pkt->pkt_ha_private)
#define CMD2PKT(cmd)            ((cmd)->cmd_pkt)
#ifdef  _LP64
#define PKT_PRIV_SIZE           2
#define PKT_PRIV_LEN            16
#else /* _ILP32 */
#define PKT_PRIV_SIZE           1
#define PKT_PRIV_LEN            8
#endif


struct sf_pkt {
        struct sf_pkt           *cmd_forw;
        struct sf_pkt           *cmd_back;
        struct sf_pkt           *cmd_next;
        struct scsi_pkt         *cmd_pkt;
        fcal_packet_t           *cmd_fp_pkt;
        uint_t          cmd_state;
        uint_t          cmd_timeout;
        char            cmd_scsi_scb[sizeof (struct scsi_arq_status)];
        uint32_t        cmd_dmacount;
        ddi_dma_handle_t        cmd_dmahandle;  /* dma handle */
        ddi_dma_cookie_t        cmd_dmacookie;  /* current dma cookie */
        uint_t          cmd_flags;      /* private flags */
                                                /* needs ZEROING */
        uint_t          cmd_cdblen;     /* length of cdb */
                                        /* needs to be INITialized */
        uint_t          cmd_scblen;     /* length of scb */
                                        /* needs to be INITialized */
        uint_t          cmd_privlen;    /* length of tgt private */
                                        /* needs to be INITialized */
        struct  sf_cr_pool      *cmd_cr_pool; /* pool to which cmd/rsp belong */
        struct fcp_cmd          *cmd_block;
        struct fcp_rsp          *cmd_rsp_block;
        kmutex_t        cmd_abort_mutex;        /* packet abort mutex */
        uint_t          cmd_dmac;
        uint_t          cmd_rsp_dmac;
        uint64_t                cmd_pkt_private[PKT_PRIV_LEN];
                        /* default target private area */
};

#define SF_STATE_IDLE           0x1
#define SF_STATE_ISSUED         0x2
#define SF_STATE_ABORTING       0x4

/*
 * Define size of extended scsi cmd pkt (ie. includes ARQ)
 */
#define EXTCMDS_STATUS_SIZE  (sizeof (struct scsi_arq_status))

/*
 * These are the defined flags for this structure.
 */
#define CFLAG_DMAVALID          0x0010  /* dma mapping valid */
#define CFLAG_DMASEND           0x0020  /* data is going 'out' */
#define CFLAG_CMDIOPB           0x0040  /* this is an 'iopb' packet */
#define CFLAG_CDBEXTERN         0x0100  /* cdb kmem_alloc'd */
#define CFLAG_SCBEXTERN         0x0200  /* scb kmem_alloc'd */
#define CFLAG_FREE              0x0400  /* packet is on free list */
#define CFLAG_PRIVEXTERN        0x1000  /* target private was */
                                        /* kmem_alloc'd */
#define CFLAG_IN_QUEUE          0x2000  /* command in sf queue */

struct sf_els_hdr {
        struct sf       *sf;
        caddr_t         cmd;
        caddr_t         rsp;
        uchar_t         els_code;
        uchar_t         delayed_retry;
        ddi_dma_handle_t        cmd_dma_handle;
        ddi_dma_handle_t        rsp_dma_handle;
        ddi_acc_handle_t        cmd_acc_handle;
        ddi_acc_handle_t        rsp_acc_handle;
        uint_t          dest_nport_id;
        struct  sf_els_hdr      *next;
        struct  sf_els_hdr      *prev;
        uint_t          size;
        uint_t          timeout;
        uint_t          retries;
        struct fcal_packet      *fpkt;
        uint_t          lip_cnt;
        uchar_t         port_wwn[FC_WWN_SIZE];
        uchar_t         node_wwn[FC_WWN_SIZE];
        struct sf_target *target;
        ddi_dma_handle_t        data_dma_handle;
        ddi_acc_handle_t        data_acc_handle;
        caddr_t                 data_buf;
};

union sf_els_cmd {
        struct la_els_logi logi;
        struct la_els_logo logo;
        struct la_els_prli prli;
        struct la_els_adisc adisc;
        struct fcp_cmd cmd;
};

union sf_els_rsp {
        struct la_els_logi logi;
        struct la_els_logo logo;
        struct la_els_prli prli;
        struct la_els_adisc adisc;
        uchar_t rsp[FCP_MAX_RSP_IU_SIZE];
};

struct sf_hp_elem {
        struct sf_hp_elem *next;
        dev_info_t      *dip;
        int             what;
        struct sf_target *target;
        struct sf       *sf;
};
#define SF_ONLINE       0
#define SF_OFFLINE      1


#define ADDR2SF(ap)     (struct sf *)((ap)->a_hba_tran->tran_hba_private)
#define ADDR2TARGET(ap) (struct sf_target *)((ap)->a_hba_tran->\
    tran_tgt_private)
#define SF_ONLINE_TIMEOUT       180
#define SF_OFFLINE_TIMEOUT      45
#define SF_RESET_TIMEOUT        10
#define SF_ELS_TIMEOUT          5
#define SF_INVALID_TIMEOUT      0x7fffffff
#define SF_FCP_TIMEOUT          30
#define SF_BSY_TIMEOUT          10
#define SF_ABORT_TIMEOUT        10000000        /* in usec */
#define SF_POLL_TIMEOUT 60
#define SF_TARGET_RESET_DELAY   250000          /* in usec */

#define SF_DECR_DELTA           5
#define SF_INCR_DELTA           5

#define SF_LO_CMD_DELTA 512
#define SF_HI_CMD_DELTA 256

#define SF_ELS_RETRIES          4
#define SF_BSY_RETRIES          7

#define SF_INIT_WAIT_TIMEOUT    60000000
#define         SF_CORE_CMD_TIMEOUT             0x01
#define         SF_CORE_BAD_ABORT               0x02
#define         SF_CORE_ABORT_TIMEOUT           0x04
#define         SF_CORE_ELS_TIMEOUT             0x08
#define         SF_CORE_ELS_FAILED              0x10
#define         SF_CORE_LILP_FAILED             0x20
#define         SF_CORE_OFFLINE_TIMEOUT         0x40
#define         SF_CORE_LIP_FAILED              0x80
#define         SF_CORE_OFFLINE_TARGET          0x100
#define         SF_CORE_INCOMPLETE_DMA          0x200
#define         SF_CORE_REPORTLUN_TIMEOUT       0x400
#define         SF_CORE_INQUIRY_TIMEOUT         0x800
#define         SF_CORE_BAD_DMA                 0x1000

#define         SF_BAD_DMA_MAGIC        0xdeafbead

#define TRUE            1
#define FALSE           0
#define UNDEFINED       -1


/*
 * The initiator must allocate a minimum of 16 bytes for the response
 * to the REPORT_LUNS command.  Since there is 8 bytes of overhead and
 * each LUN is 4 bytes, this means that the minimum size is 2 LUNs.  We
 * will define the structure that way to prevent any spurious check
 * conditions.
 *
 * There is no maximum size for the response.
 *
 * By default we support 256 LUNs for the moment, which means 256*8+16
 * or 2064 bytes total size.
 */

#define REPORT_LUNS_MIN_LUNS    2
#define REPORT_LUNS_DEFAULT     256
#define REPORT_LUNS_SIZE        ((REPORT_LUNS_DEFAULT)*sizeof (uint32_t) \
                                +2*sizeof (uint32_t))

/*
 * SCSI Report_Luns Data
 *
 * Format of data returned as a result of an REPORT_LUNS command.
 *
 */

struct scsi_report_luns {
        /* Number of bytes of data the target has available to send. */
        uint32_t        lun_list_len;
        uint32_t        reserved;
        uint64_t        lun[REPORT_LUNS_MIN_LUNS];
};

#endif  /* _KERNEL */

#ifdef  __cplusplus
}
#endif

#endif  /* _SYS_SCSI_ADAPTERS_SFVAR_H */