root/usr/src/uts/common/io/fibre-channel/fca/fcoei/fcoei.h
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (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 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */
#ifndef _FCOEI_H
#define _FCOEI_H

#ifdef  __cplusplus
extern "C" {
#endif

#ifdef  _KERNEL

/*
 * FCOEI logging
 */
extern int fcoei_use_ext_log;
extern void *fcoei_state;

#define FCOEI_EXT_LOG(log_ident, ...)                           \
        {                                                       \
                if (fcoei_use_ext_log) {                        \
                        fcoe_trace(log_ident, __VA_ARGS__);     \
                }                                               \
        }

#define FCOEI_LOG(log_ident, ...)               \
        fcoe_trace(log_ident, __VA_ARGS__)

/*
 * IOCTL supporting stuff
 */
#define FCOEI_IOCTL_FLAG_MASK           0xFF
#define FCOEI_IOCTL_FLAG_IDLE           0x00
#define FCOEI_IOCTL_FLAG_OPEN           0x01
#define FCOEI_IOCTL_FLAG_EXCL           0x02

/*
 * define common constants
 */
#define FCOEI_MAX_OPEN_XCHS     2048
#define FCOEI_SOL_HASH_SIZE     2048
#define FCOEI_UNSOL_HASH_SIZE   128
#define FCOEI_VERSION           "20090729-1.00"
#define FCOEI_NAME_VERSION      "SunFC FCoEI v" FCOEI_VERSION

/*
 * define RNID Management Info
 */
#define FCOEI_RNID_HBA  0x7
#define FCOEI_RNID_IPV4 0x1
#define FCOEI_RNID_IPV6 0x2

typedef enum event_type {
        AE_EVENT_NONE = 0,
        AE_EVENT_EXCHANGE,
        AE_EVENT_SOL_FRAME,
        AE_EVENT_UNSOL_FRAME,
        AE_EVENT_PORT,
        AE_EVENT_ABORT,
        AE_EVENT_RESET,
} event_type_e;

typedef struct fcoei_event {
        list_node_t      ae_node;
        event_type_e     ae_type;

        /*
         * event specific
         */
        uint64_t         ae_specific;

        /*
         * event related object
         */
        void            *ae_obj;
} fcoei_event_t;

typedef struct fcoei_soft_state {
        dev_info_t              *ss_dip;
        uint32_t                 ss_flags;
        uint32_t                 ss_fcp_data_payload_size;
        list_t                   ss_comp_xch_list;

        /*
         * common data structure (fc_local_port_t) between leadville and fcoei
         */
        void                    *ss_port;

        /*
         * common data structure between fcoei and fcoe module
         */
        fcoe_port_t             *ss_eport;

        mod_hash_t              *ss_sol_oxid_hash;
        mod_hash_t              *ss_unsol_rxid_hash;
        uint16_t                 ss_next_sol_oxid;
        uint16_t                 ss_next_unsol_rxid;

        /*
         * We will use ss_taskq to dispatch watchdog and other tasks
         */
        ddi_taskq_t             *ss_taskq;

        kcondvar_t               ss_watchdog_cv;
        kmutex_t                 ss_watchdog_mutex;

        /*
         * current port state, speed. see fctl.h
         */
        uint16_t                 ss_link_state;
        uint16_t                 ss_link_speed;

        /*
         * # of unprocessed port/link change
         */
        uint32_t                 ss_port_event_counter;
        list_t                   ss_event_list;

        /*
         * solicited and unsolicited exchanges timing checking
         */
        uint32_t                 ss_sol_cnt1;
        uint32_t                 ss_sol_cnt2;
        uint32_t                *ss_sol_cnt;
        uint32_t                 ss_unsol_cnt1;
        uint32_t                 ss_unsol_cnt2;
        uint32_t                *ss_unsol_cnt;

        /*
         * ioctl related stuff
         */
        uint32_t                 ss_ioctl_flags;
        kmutex_t                 ss_ioctl_mutex;

        /*
         * fp-defined routines that fcoei will call
         */
        fc_fca_bind_info_t       ss_bind_info;

        /*
         * fcoei-defined plogi response that fp will use
         */
        la_els_logi_t            ss_els_logi;

        /*
         * fcoei-defined routines that fp will call
         */
        fc_fca_tran_t            ss_fca_tran;

        /*
         * Direct p2p information, and ss's fcid will be stored here
         */
        fc_fca_p2p_info_t       ss_p2p_info;

        /*
         * RNID Management Information
         */
        fc_rnid_t                       ss_rnid;
} fcoei_soft_state_t;

#define SS_FLAG_LV_NONE                 0x0000
#define SS_FLAG_LV_BOUND                0x0001
#define SS_FLAG_PORT_DISABLED           0x0002
#define SS_FLAG_TERMINATE_WATCHDOG      0x0004
#define SS_FLAG_WATCHDOG_RUNNING        0x0008
#define SS_FLAG_WATCHDOG_IDLE           0x0010
#define SS_FLAG_TRIGGER_FP_ATTACH       0x0020
#define SS_FLAG_FLOGI_FAILED            0x0040

/*
 * fcoei_frame - corresponding data structure to fcoe_frame/fc_frame
 */
typedef struct fcoei_frame {
        fcoei_event_t            ifm_ae;
        fcoe_frame_t            *ifm_frm;
        uint32_t                 ifm_flags;
        struct fcoei_exchange   *ifm_xch;

        /*
         * will be used after the relevant frame mblk was released by ETH layer
         */
        uint8_t                  ifm_rctl;
} fcoei_frame_t;

#define IFM_FLAG_NONE           0x0000
#define IFM_FLAG_FREE_NETB      0x0001

/*
 * fcoei_exchange - corresponding data structure to leadville fc_packet
 */
typedef struct fcoei_exchange {
        list_node_t              xch_comp_node;
        fcoei_event_t            xch_ae;
        uint32_t                 xch_flags;
        fcoei_soft_state_t      *xch_ss;
        clock_t                  xch_start_tick;
        clock_t                  xch_end_tick;
        int                      xch_resid;
        ksema_t                  xch_sema;

        /*
         * current cnt for timing check, when the exchange is created
         */
        uint32_t                *xch_cnt;

        /*
         * leadville fc_packet will not maintain oxid/rxid,
         * so fcoei exchange  need do it
         */
        uint16_t                 xch_oxid;
        uint16_t                 xch_rxid;

        /*
         * to link leadville's stuff
         */
        fc_packet_t             *xch_fpkt;
        fc_unsol_buf_t          *xch_ub;
} fcoei_exchange_t;

#define XCH_FLAG_NONE           0x00000000
#define XCH_FLAG_TMOUT          0x00000001
#define XCH_FLAG_ABORT          0x00000002
#define XCH_FLAG_IN_SOL_HASH    0x00000004
#define XCH_FLAG_IN_UNSOL_HASH  0x00000008

typedef struct fcoei_walk_arg
{
        fcoei_exchange_t        *wa_xch;
        uint16_t                 wa_oxid;
} fcoei_walk_arg_t;

/*
 * Define conversion and calculation macros
 */
#define FRM2IFM(x_frm)  ((fcoei_frame_t *)(x_frm)->frm_client_private)
#define FRM2SS(x_frm)                                                   \
        ((fcoei_soft_state_t *)(x_frm)->frm_eport->eport_client_private)

#define PORT2SS(x_port) ((fcoei_soft_state_t *)(x_port)->port_fca_private)
#define EPORT2SS(x_eport)                                       \
        ((fcoei_soft_state_t *)(x_eport)->eport_client_private)

#define FPKT2XCH(x_fpkt)        ((fcoei_exchange_t *)x_fpkt->pkt_fca_private)
#define FRM2FPKT(x_fpkt)        (FRM2IFM(frm)->ifm_xch->xch_fpkt)

#define HANDLE2SS(x_handle)     ((fcoei_soft_state_t *)fca_handle)

#define FPLD                    frm->frm_payload

#define FCOEI_FRM2FHDR(x_frm, x_fhdr)                           \
        {                                                       \
                (x_fhdr)->r_ctl = FRM_R_CTL(x_frm);             \
                (x_fhdr)->d_id = FRM_D_ID(x_frm);               \
                (x_fhdr)->s_id = FRM_S_ID(x_frm);               \
                (x_fhdr)->type = FRM_TYPE(x_frm);               \
                (x_fhdr)->f_ctl = FRM_F_CTL(x_frm);             \
                (x_fhdr)->seq_id = FRM_SEQ_ID(x_frm);           \
                (x_fhdr)->df_ctl = FRM_DF_CTL(x_frm);           \
                (x_fhdr)->seq_cnt = FRM_SEQ_CNT(x_frm);         \
                (x_fhdr)->ox_id = FRM_OXID(x_frm);              \
                (x_fhdr)->rx_id = FRM_RXID(x_frm);              \
                (x_fhdr)->ro = FRM_PARAM(x_frm);                \
        }

#define FCOEI_PARTIAL_FHDR2FRM(x_fhdr, x_frm)           \
        {                                               \
                FFM_R_CTL((x_fhdr)->r_ctl, x_frm);      \
                FFM_D_ID((x_fhdr)->d_id, x_frm);        \
                FFM_S_ID((x_fhdr)->s_id, x_frm);        \
                FFM_TYPE((x_fhdr)->type, x_frm);        \
                FFM_F_CTL((x_fhdr)->f_ctl, x_frm);      \
        }

#define PRT_FRM_HDR(x_p, x_f)                                           \
        {                                                               \
                FCOEI_LOG(x_p, "rctl/%x, fctl/%x, type/%x, oxid/%x",    \
                        FCOE_B2V_1((x_f)->frm_hdr->hdr_r_ctl),          \
                        FCOE_B2V_3((x_f)->frm_hdr->hdr_f_ctl),          \
                        FCOE_B2V_1((x_f)->frm_hdr->hdr_type),           \
                        FCOE_B2V_2((x_f)->frm_hdr->hdr_oxid));          \
        }

#define FCOEI_INIT_SOL_ID_HASH(xch, xch_tmp)                            \
        {                                                               \
                do {                                                    \
                        if (++xch->xch_ss->ss_next_sol_oxid == 0xFFFF) { \
                                ++xch->xch_ss->ss_next_sol_oxid;        \
                        }                                               \
                } while (mod_hash_find(xch->xch_ss->ss_sol_oxid_hash,   \
                    (mod_hash_key_t)(intptr_t)xch->xch_ss->ss_next_sol_oxid, \
                    (mod_hash_val_t)&xch_tmp) == 0);    \
                xch->xch_oxid = xch->xch_ss->ss_next_sol_oxid;          \
                xch->xch_rxid = 0xFFFF;                                 \
                (void) mod_hash_insert(xch->xch_ss->ss_sol_oxid_hash,   \
                    FMHK(xch->xch_oxid), (mod_hash_val_t)xch); \
                xch->xch_flags |= XCH_FLAG_IN_SOL_HASH;                 \
        }

#define FCOEI_SET_UNSOL_FRM_RXID(frm, xch_tmp)                          \
        {                                                               \
                do {                                                    \
                        if (++FRM2SS(frm)->ss_next_unsol_rxid == 0xFFFF) { \
                                ++FRM2SS(frm)->ss_next_unsol_rxid;      \
                        }                                               \
                } while (mod_hash_find(FRM2SS(frm)->ss_unsol_rxid_hash, \
                    (mod_hash_key_t)(intptr_t)FRM2SS(frm)->ss_next_unsol_rxid, \
                    (mod_hash_val_t)&xch_tmp) == 0);    \
                FFM_RXID(FRM2SS(frm)->ss_next_unsol_rxid, frm); \
        }

#define FCOEI_INIT_UNSOL_ID_HASH(xch)                                   \
        {                                                               \
                xch->xch_oxid = fpkt->pkt_cmd_fhdr.ox_id;               \
                xch->xch_rxid = fpkt->pkt_cmd_fhdr.rx_id;               \
                (void) mod_hash_insert(xch->xch_ss->ss_unsol_rxid_hash, \
                    FMHK(xch->xch_rxid), (mod_hash_val_t)xch);          \
                xch->xch_flags |= XCH_FLAG_IN_UNSOL_HASH;               \
        }

/*
 * Common functions defined in fcoei.c
 */
void fcoei_complete_xch(fcoei_exchange_t *xch, fcoe_frame_t *frm,
    uint8_t pkt_state, uint8_t pkt_reason);
void fcoei_init_ifm(fcoe_frame_t *frm, fcoei_exchange_t *xch);
void fcoei_handle_comp_xch_list(fcoei_soft_state_t *ss);

/*
 * Common functions defined in fcoei_lv.c
 */
void fcoei_init_fcatran_vectors(fc_fca_tran_t *fcatran);
void fcoei_process_event_exchange(fcoei_event_t *ae);
void fcoei_process_event_reset(fcoei_event_t *ae);

/*
 * Common functions defined in fcoei_eth.c
 */
void fcoei_init_ect_vectors(fcoe_client_t *ect);
void fcoei_process_unsol_frame(fcoe_frame_t *frm);
void fcoei_handle_sol_frame_done(fcoe_frame_t *frm);
void fcoei_process_event_port(fcoei_event_t *ae);
void fcoei_port_event(fcoe_port_t *eport, uint32_t event);

#endif /* _KERNEL */

#ifdef  __cplusplus
}
#endif

#endif /* _FCOEI_H */