/* * 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 #include #include #include #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 */