root/usr/src/uts/common/sys/fct.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 (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
 * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
 * Copyright 2020 RackTop Systems, Inc.
 */
#ifndef _FCT_H
#define _FCT_H

/*
 * Definitions for common FC Target.
 */
#include <sys/note.h>
#include <sys/stmf_defines.h>
#include <sys/fct_defines.h>
#include <sys/portif.h>

#ifdef  __cplusplus
extern "C" {
#endif

typedef enum fct_struct_id {
        FCT_STRUCT_LOCAL_PORT = 1,
        FCT_STRUCT_REMOTE_PORT,
        FCT_STRUCT_CMD_RCVD_ELS,
        FCT_STRUCT_CMD_SOL_ELS,
        FCT_STRUCT_CMD_SOL_CT,
        FCT_STRUCT_CMD_RCVD_ABTS,
        FCT_STRUCT_CMD_FCP_XCHG,
        FCT_STRUCT_DBUF_STORE,

        FCT_MAX_STRUCT_IDS
} fct_struct_id_t;

typedef struct fct_remote_port {
        void            *rp_fct_private;
        void            *rp_fca_private;

        struct fct_local_port *rp_port;
        char            rp_nwwn_str[FC_WWN_BUFLEN];
        char            rp_pwwn_str[FC_WWN_BUFLEN];
        uint8_t         rp_nwwn[FC_WWN_LEN];
        uint8_t         rp_pwwn[FC_WWN_LEN];
        uint32_t        rp_id;          /* 8 or 24 bit */
        uint32_t        rp_hard_address;
        uint16_t        rp_handle;
} fct_remote_port_t;

#define FCT_HANDLE_NONE 0xffff

typedef struct fct_cmd {
        void            *cmd_fct_private;
        void            *cmd_fca_private;
        void            *cmd_specific;

        struct fct_local_port   *cmd_port;

        /* During cmd porting this can be set to NULL */
        struct fct_remote_port  *cmd_rp;

        /* To link cmds together for handling things like ABTS. */
        struct fct_cmd  *cmd_link;
        uint8_t         cmd_type;
        uint8_t         cmd_rsvd1;

        /* During cmd posting this can be set to FCT_HANDLE_NONE */
        uint16_t        cmd_rp_handle;
        uint32_t        cmd_handle;
        uint32_t        cmd_rportid;
        uint32_t        cmd_lportid;
        uint32_t        cmd_rsvd2;
        uint16_t        cmd_oxid;
        uint16_t        cmd_rxid;
        fct_status_t    cmd_comp_status;
} fct_cmd_t;

/*
 * fcmd_cmd_handle: Bit definitions.
 *   31           23           15           7          0
 *  +--------------+------------+------------+------------+
 *  | V |uniq_cntr |fca specific|   cmd slot index        |
 *  +--------------+------------+------------+------------+
 * V = handle valid.
 */
#define CMD_HANDLE_SLOT_INDEX(x)        ((x) & 0xffff)
#define CMD_HANDLE_VALID(x)             ((x) & 0x80000000)

enum fct_cmd_types {
        FCT_CMD_FCP_XCHG =      0x0001,
        FCT_CMD_RCVD_ELS =      0x0002,
        FCT_CMD_SOL_ELS =       0x0004,
        FCT_CMD_RCVD_ABTS =     0x0008,
        FCT_CMD_SOL_CT =        0x0010,

        FCT_CMD_TYPE_ALL =      0xffff
};

typedef struct fct_els {
        uint16_t        els_req_size;
        uint16_t        els_resp_size;
        uint16_t        els_req_alloc_size;
        uint16_t        els_resp_alloc_size;
        uint8_t         *els_req_payload;
        uint8_t         *els_resp_payload;
} fct_els_t;

typedef struct fct_sol_ct {
        uint16_t        ct_req_size;
        uint16_t        ct_resp_size;
        uint16_t        ct_req_alloc_size;
        uint16_t        ct_resp_alloc_size;
        uint8_t         *ct_req_payload;
        uint8_t         *ct_resp_payload;
} fct_sol_ct_t;

typedef struct fct_rcvd_abts {
        uint8_t         abts_resp_rctl; /* Can be BA_ACC or BA_RJT */
        uint8_t         abts_state;
        uint16_t        rsvd;
        uint8_t         abts_resp_payload[12];
} fct_rcvd_abts_t;

/*
 * abts state
 */
#define ABTS_STATE_RECEIVED             0
#define ABTS_STATE_RESPONDED            1
#define ABTS_STATE_COMPLETED            2
#define ABTS_STATE_ABORT_REQUESTED      3
#define ABTS_STATE_ABORT_COMPLETED      4

#define FCHBA_MANUFACTURER_LEN          64
#define FCHBA_SERIAL_NUMBER_LEN         64
#define FCHBA_MODEL_LEN                 256
#define FCHBA_MODEL_DESCRIPTION_LEN     256
#define FCHBA_HARDWARE_VERSION_LEN      256
#define FCHBA_DRIVER_VERSION_LEN        256
#define FCHBA_OPTION_ROM_VERSION_LEN    256
#define FCHBA_FIRMWARE_VERSION_LEN      256
#define FCHBA_DRIVER_NAME_LEN           256
#define FCHBA_SYMB_NAME_LEN             255

#define FCT_INFO_LEN                    160
#define FCT_TASKQ_NAME_LEN              24

#define FC_TGT_PORT_INFO_CMD            (((uint32_t)'I') << 24)
#define FC_TGT_PORT_RLS                 FC_TGT_PORT_INFO_CMD + 0x1

typedef struct fct_port_attrs {
        char            manufacturer[FCHBA_MANUFACTURER_LEN];
        char            serial_number[FCHBA_SERIAL_NUMBER_LEN];
        char            model[FCHBA_MODEL_LEN];
        char            model_description[FCHBA_MODEL_DESCRIPTION_LEN];
        char            hardware_version[FCHBA_HARDWARE_VERSION_LEN];
        char            driver_version[FCHBA_DRIVER_VERSION_LEN];
        char            option_rom_version[FCHBA_OPTION_ROM_VERSION_LEN];
        char            firmware_version[FCHBA_FIRMWARE_VERSION_LEN];
        char            driver_name[FCHBA_DRIVER_NAME_LEN];
        uint32_t        vendor_specific_id;
        uint32_t        supported_cos;
        uint32_t        supported_speed;
        uint32_t        max_frame_size;
} fct_port_attrs_t;

typedef struct fct_port_link_status {
        uint32_t        LinkFailureCount;
        uint32_t        LossOfSyncCount;
        uint32_t        LossOfSignalsCount;
        uint32_t        PrimitiveSeqProtocolErrorCount;
        uint32_t        InvalidTransmissionWordCount;
        uint32_t        InvalidCRCCount;
} fct_port_link_status_t;

typedef struct fct_dbuf_store {
        void                    *fds_fct_private;
        void                    *fds_fca_private;
        struct stmf_dbuf_store  *fds_ds;

        stmf_data_buf_t *(*fds_alloc_data_buf)(struct fct_local_port *port,
                            uint32_t size, uint32_t *pminsize, uint32_t flags);
        void            (*fds_free_data_buf)(struct fct_dbuf_store *fds,
                            stmf_data_buf_t *dbuf);
        stmf_status_t   (*fds_setup_dbuf)(struct fct_local_port *port,
                            stmf_data_buf_t *dbuf, uint32_t flags);
        void            (*fds_teardown_dbuf)(struct fct_dbuf_store *fds,
                            stmf_data_buf_t *dbuf);

        uint32_t                fds_max_sgl_xfer_len;
        uint32_t                fds_copy_threshold;
} fct_dbuf_store_t;

#define FCT_FCA_MODREV_1        1

typedef struct fct_local_port {
        void                    *port_fct_private;
        void                    *port_fca_private;
        stmf_local_port_t       *port_lport;

        char                    port_nwwn_str[FC_WWN_BUFLEN];
        char                    port_pwwn_str[FC_WWN_BUFLEN];
        uint8_t                 port_nwwn[FC_WWN_LEN];
        uint8_t                 port_pwwn[FC_WWN_LEN];
        char                    *port_default_alias;
        char                    *port_sym_node_name;
        char                    *port_sym_port_name;

        stmf_port_provider_t    *port_pp;

        uint32_t                port_hard_address;
        uint16_t                port_max_logins;
        uint16_t                port_max_xchges;
        uint32_t                port_fca_fcp_cmd_size;
        uint32_t                port_fca_rp_private_size;
        uint32_t                port_fca_sol_els_private_size;
        uint32_t                port_fca_sol_ct_private_size;

        /* in milliseconds */
        uint32_t                port_fca_abort_timeout;

        fct_dbuf_store_t        *port_fds;
        fct_status_t            (*port_get_link_info)(
                struct fct_local_port *port, struct fct_link_info *li);
        fct_status_t            (*port_register_remote_port)(
                struct fct_local_port *port, struct fct_remote_port *rp,
                struct fct_cmd *login_els);
        fct_status_t            (*port_deregister_remote_port)(
                struct fct_local_port *port, struct fct_remote_port *rp);
        fct_status_t            (*port_send_cmd)(fct_cmd_t *cmd);
        fct_status_t            (*port_xfer_scsi_data)(fct_cmd_t *cmd,
                        stmf_data_buf_t *dbuf, uint32_t flags);
        fct_status_t            (*port_send_cmd_response)(fct_cmd_t *cmd,
                                        uint32_t ioflags);
        fct_status_t            (*port_abort_cmd)(struct fct_local_port *port,
                        fct_cmd_t *cmd, uint32_t flags);
        void                    (*port_ctl)(struct fct_local_port *port,
                                                int cmd, void *arg);
        fct_status_t            (*port_flogi_xchg)(struct fct_local_port *port,
                        struct fct_flogi_xchg *fx);
        void                    (*port_populate_hba_details)(
                struct fct_local_port *port, struct fct_port_attrs *port_attrs);
        fct_status_t            (*port_info)(uint32_t cmd,
                struct fct_local_port *port, void *arg, uint8_t *buf,
                uint32_t *bufsizep);
        int             port_fca_version;
} fct_local_port_t;

/*
 * Common struct used during FLOGI exchange.
 */
typedef struct fct_flogi_xchg {
        uint8_t         fx_op;          /* ELS_OP_FLOGI or ELS_OP_ACC/RJT */
        uint8_t         fx_rjt_reason;
        uint8_t         fx_rjt_expl;
        uint8_t         fx_sec_timeout; /* Timeout in seconds */
        uint32_t        fx_fport:1,     /* 0=N_port, 1=F_port */
                        rsvd2:31;
        uint32_t        fx_sid;         /* 24 bit SID to use */
        uint32_t        fx_did;         /* 24 bit DID to use */
        uint8_t         fx_pwwn[8];
        uint8_t         fx_nwwn[8];
} fct_flogi_xchg_t;

typedef struct fct_link_info {
        uint32_t                portid;
        uint8_t                 port_topology;
        uint8_t                 port_speed;

        uint8_t                 rsvd:5,

        /*
         * FCA sets this bit to indicate that fct does not need to do FLOGI
         * because either FCA did the FLOGI or it determined that its a private
         * loop. Setting this bit by FCA is optional.
         */
                                port_no_fct_flogi:1,

        /* FCA sets this bit to indicate that it did FLOGI */
                                port_fca_flogi_done:1,

        /* FCT sets this bit to indicate that it did FLOGI */
                                port_fct_flogi_done:1;

        uint8_t                 rsvd1;

        /* The fields below are only valid if someone did a successful flogi */
        uint8_t                 port_rnwwn[8];
        uint8_t                 port_rpwwn[8];
} fct_link_info_t;

typedef struct fct_port_stat {
        kstat_named_t   link_failure_cnt;
        kstat_named_t   loss_of_sync_cnt;
        kstat_named_t   loss_of_signals_cnt;
        kstat_named_t   prim_seq_protocol_err_cnt;
        kstat_named_t   invalid_tx_word_cnt;
        kstat_named_t   invalid_crc_cnt;
} fct_port_stat_t;

/*
 * port topology
 */
#define PORT_TOPOLOGY_UNKNOWN           0
#define PORT_TOPOLOGY_PT_TO_PT          1
#define PORT_TOPOLOGY_PRIVATE_LOOP      2
#define PORT_TOPOLOGY_PUBLIC_LOOP       6
#define PORT_TOPOLOGY_FABRIC_PT_TO_PT   5
#define PORT_TOPOLOGY_FABRIC_BIT        4

#define PORT_FLOGI_DONE(li)     (((li)->port_fca_flogi_done) || \
                                        ((li)->port_fct_flogi_done))

/*
 * port speed
 */
#define PORT_SPEED_UNKNOWN              0
#define PORT_SPEED_1G                   1
#define PORT_SPEED_2G                   2
#define PORT_SPEED_4G                   4
#define PORT_SPEED_8G                   8
#define PORT_SPEED_10G                  16
#define PORT_SPEED_16G                  32
#define PORT_SPEED_32G                  64

/*
 * Abort commands
 */
#define FCT_TERMINATE_CMD               1

/*
 * FCT port states.
 */
#define FCT_STATE_OFFLINE       0
#define FCT_STATE_ONLINING      1
#define FCT_STATE_ONLINE        2
#define FCT_STATE_OFFLINING     3

/*
 * fct ctl commands. These should not conflict with stmf ctl commands
 */
#define FCT_CMD_PORT_ONLINE             (STMF_LPORT_CTL_CMDS | 0x01)
#define FCT_CMD_PORT_ONLINE_COMPLETE    (STMF_LPORT_CTL_CMDS | 0x02)
#define FCT_CMD_PORT_OFFLINE            (STMF_LPORT_CTL_CMDS | 0x03)
#define FCT_CMD_PORT_OFFLINE_COMPLETE   (STMF_LPORT_CTL_CMDS | 0x04)
#define FCT_ACK_PORT_ONLINE_COMPLETE    (STMF_LPORT_CTL_CMDS | 0x05)
#define FCT_ACK_PORT_OFFLINE_COMPLETE   (STMF_LPORT_CTL_CMDS | 0x06)
#define FCT_CMD_FORCE_LIP               (STMF_LPORT_CTL_CMDS | 0x07)

/*
 * IO flags for cmd flow.
 */
#define FCT_IOF_FCA_DONE                0x10000
#define FCT_IOF_FORCE_FCA_DONE          0x20000

/*
 * Fill CTIU preamble
 */
#ifdef  lint
#define FCT_FILL_CTIU_PREAMBLE(x_payload, x_ctop)       _NOTE(EMPTY)
#else
#define FCT_FILL_CTIU_PREAMBLE(x_payload, x_ctop)       \
        do {                                            \
                x_payload[0] = 0x01;                    \
                x_payload[4] = 0xFC;                    \
                x_payload[5] = 0x02;                    \
                x_payload[8] = 0xFF & (x_ctop >> 8);    \
                x_payload[9] = 0xFF & (x_ctop);         \
        } while (0)
#endif

uint64_t fct_netbuf_to_value(uint8_t *buf, uint8_t nbytes);
void fct_value_to_netbuf(uint64_t value, uint8_t *buf, uint8_t nbytes);
void *fct_alloc(fct_struct_id_t struct_id, int additional_size, int flags);
void fct_free(void *ptr);
fct_cmd_t *fct_scsi_task_alloc(struct fct_local_port *port,
    uint16_t rp_handle, uint32_t rportid, uint8_t *lun,
    uint16_t cdb_length, uint16_t task_ext);
fct_status_t fct_register_local_port(fct_local_port_t *port);
fct_status_t fct_deregister_local_port(fct_local_port_t *port);
void fct_handle_event(fct_local_port_t *port, int event_id,
    uint32_t event_flags, caddr_t arg);
void fct_post_rcvd_cmd(fct_cmd_t *cmd, stmf_data_buf_t *dbuf);
void fct_queue_cmd_for_termination(fct_cmd_t *cmd, fct_status_t s);
void fct_queue_scsi_task_for_termination(fct_cmd_t *cmd, fct_status_t s);
fct_cmd_t *fct_handle_to_cmd(fct_local_port_t *port, uint32_t fct_handle);
void fct_ctl(struct stmf_local_port *lport, int cmd, void *arg);
void fct_cmd_fca_aborted(fct_cmd_t *cmd, fct_status_t s, uint32_t ioflags);
uint16_t fct_get_rp_handle(fct_local_port_t *port, uint32_t rportid);
void fct_send_response_done(fct_cmd_t *cmd, fct_status_t s, uint32_t ioflags);
void fct_send_cmd_done(fct_cmd_t *cmd, fct_status_t s, uint32_t ioflags);
void fct_scsi_data_xfer_done(fct_cmd_t *cmd, stmf_data_buf_t *dbuf,
    uint32_t ioflags);
fct_status_t fct_port_initialize(fct_local_port_t *port, uint32_t rflags,
    char *additional_info);
fct_status_t fct_port_shutdown(fct_local_port_t *port, uint32_t rflags,
    char *additional_info);
fct_status_t fct_handle_rcvd_flogi(fct_local_port_t *port,
    fct_flogi_xchg_t *fx);
void fct_log_local_port_event(fct_local_port_t *port, char *subclass);
void fct_log_remote_port_event(fct_local_port_t *port, char *subclass,
    uint8_t *rp_pwwn, uint32_t rp_id);
void fct_wwn_to_str(char *to_ptr, const uint8_t *from_ptr);

#ifdef  __cplusplus
}
#endif

#endif /* _FCT_H */