/* * 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 _FCOE_COMMON_H_ #define _FCOE_COMMON_H_ #ifdef __cplusplus extern "C" { #endif #ifdef _KERNEL /* * Interface return value */ #define FCOE_SUCCESS 0 #define FCOE_FAILURE -1 #define FCOE_BUSY -2 #define FCOE_NOT_SUPPORTED -3 #define FCOE_BAD_FRAME -4 /* * FCOE port speed */ #define FCOE_PORT_SPEED_1G 1000000000 #define FCOE_PORT_SPEED_10G 10000000000 /* * FC Frame header size: 24 bytes */ #define FCFH_SIZE (sizeof (fcoe_fc_frame_header_t)) /* * FLOGI */ #define FLOGI_REQ_PAYLOAD_SIZE 116 #define FLOGI_ACC_PAYLOAD_SIZE 116 #define FCOE_MIN_MTU_SIZE 2500 #define FCOE_MAX_FC_FRAME_SIZE 2136 /* * 24 byte FC frame header * For all data structures that have endian problems, we will use only * one type: uint8_t. We need associate the data structure pointer with * one buffer directly. */ typedef struct fcoe_fc_frame_header { uint8_t hdr_r_ctl[1]; uint8_t hdr_d_id[3]; uint8_t hdr_cs_ctl[1]; uint8_t hdr_s_id[3]; uint8_t hdr_type[1]; uint8_t hdr_f_ctl[3]; uint8_t hdr_seq_id[1]; uint8_t hdr_df_ctl[1]; uint8_t hdr_seq_cnt[2]; uint8_t hdr_oxid[2]; uint8_t hdr_rxid[2]; uint8_t hdr_param[4]; } fcoe_fc_frame_header_t; /* * Solicited frame: allocted by FCOET/FOCEI, free-ed by FCOE * Unsolicited frame: allocated by FCOE, free-ed by FCOET/FCOEI */ struct fcoe_port; typedef struct fcoe_frame { uint32_t frm_flags; void *frm_netb; /* * frm_hdr will be cleared by fcoe explicitly */ fcoe_fc_frame_header_t *frm_hdr; uint8_t *frm_ofh1; uint8_t *frm_ofh2; uint8_t *frm_fc_frame; /* * fcoe client need clear FC payload explicitly, * except for RD/WR data frames */ uint8_t *frm_payload; uint32_t frm_fc_frame_size; uint32_t frm_payload_size; uint32_t frm_alloc_size; struct fcoe_port *frm_eport; void *frm_fcoe_private; void *frm_client_private; clock_t frm_clock; } fcoe_frame_t; /* * FCOE HBA */ typedef struct fcoe_port { uint32_t eport_flags; void *eport_fcoe_private; void *eport_client_private; uint8_t eport_portwwn[8]; uint8_t eport_nodewwn[8]; uint32_t eport_max_fc_frame_size; uint32_t eport_mtu; uint64_t eport_link_speed; uint8_t eport_efh_dst[ETHERADDRL]; void (*eport_tx_frame)(fcoe_frame_t *frame); fcoe_frame_t *(*eport_alloc_frame)(struct fcoe_port *eport, uint32_t this_fc_frame_size, void *netb); void (*eport_release_frame)(fcoe_frame_t *frame); void *(*eport_alloc_netb)(struct fcoe_port *eport, uint32_t this_fc_frame_size, uint8_t **ppfc); void (*eport_free_netb)(void *netb); void (*eport_deregister_client)(struct fcoe_port *eport); int (*eport_ctl)(struct fcoe_port *eport, int cmd, void *arg); int (*eport_set_mac_address)(struct fcoe_port *eport, uint8_t *addr, boolean_t fc_assigned); } fcoe_port_t; /* * FCOE only supports two kinds of topology: direct P2P, fabric P2P. */ #define EPORT_FLAG_IS_DIRECT_P2P 0x01 #define EPORT_FLAG_TGT_MODE 0x02 #define EPORT_FLAG_INI_MODE 0x04 #define EPORT_FLAG_MAC_IN_USE 0x08 #define FCOE_NOTIFY_EPORT_LINK_UP 0x01 #define FCOE_NOTIFY_EPORT_LINK_DOWN 0x02 #define FCOE_NOTIFY_EPORT_ADDR_CHG 0x03 #define FCOE_PORT_CTL_CMDS 0x3000 #define FCOE_CMD_PORT_ONLINE (FCOE_PORT_CTL_CMDS | 0x01) #define FCOE_CMD_PORT_OFFLINE (FCOE_PORT_CTL_CMDS | 0x02) /* * FCoE version control */ typedef enum fcoe_ver { FCOE_VER_1 = 0xAA01, FCOE_VER_2, FCOE_VER_3, FCOE_VER_4, FCOE_VER_5 } fcoe_ver_e; #define FCOE_VER_NOW FCOE_VER_1 extern const fcoe_ver_e fcoe_ver_now; typedef struct fcoe_client { fcoe_ver_e ect_fcoe_ver; uint32_t ect_eport_flags; uint32_t ect_max_fc_frame_size; uint32_t ect_private_frame_struct_size; uint32_t ect_channelid; void *ect_client_port_struct; void (*ect_rx_frame)(fcoe_frame_t *frame); void (*ect_port_event)(fcoe_port_t *eport, uint32_t event); void (*ect_release_sol_frame)(fcoe_frame_t *frame); } fcoe_client_t; /* * Define common-used conversion or calculation macros */ #define FCOE_V2B_1(x_v, x_b) \ { \ ((uint8_t *)(x_b))[0] = 0xFF & (x_v); \ } #define FCOE_V2B_2(x_v, x_b) \ { \ ((uint8_t *)(x_b))[1] = 0xFF & (x_v); \ ((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 8); \ } #define FCOE_V2B_3(x_v, x_b) \ { \ ((uint8_t *)(x_b))[2] = 0xFF & (x_v); \ ((uint8_t *)(x_b))[1] = 0xFF & ((x_v) >> 8); \ ((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 16); \ } #define FCOE_V2B_4(x_v, x_b) \ { \ ((uint8_t *)(x_b))[3] = 0xFF & (x_v); \ ((uint8_t *)(x_b))[2] = 0xFF & ((x_v) >> 8); \ ((uint8_t *)(x_b))[1] = 0xFF & ((x_v) >> 16); \ ((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 24); \ } #define FCOE_V2B_8(x_v, x_b) \ { \ ((uint8_t *)(x_b))[7] = 0xFF & (x_v); \ ((uint8_t *)(x_b))[6] = 0xFF & ((x_v) >> 8); \ ((uint8_t *)(x_b))[5] = 0xFF & ((x_v) >> 16); \ ((uint8_t *)(x_b))[4] = 0xFF & ((x_v) >> 24); \ ((uint8_t *)(x_b))[3] = 0xFF & ((x_v) >> 32); \ ((uint8_t *)(x_b))[2] = 0xFF & ((x_v) >> 40); \ ((uint8_t *)(x_b))[1] = 0xFF & ((x_v) >> 48); \ ((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 56); \ } #define FCOE_B2V_1(x_b) \ ((((uint8_t *)(x_b))[0]) & 0xFF) #define FCOE_B2V_2(x_b) \ ((((uint8_t *)(x_b))[1] | ((uint8_t *)(x_b))[0] << 8) & 0xFFFF) #define FCOE_B2V_3(x_b) \ ((((uint8_t *)(x_b))[2] | ((uint8_t *)(x_b))[1] << 8 | \ ((uint8_t *)(x_b))[0] << 16) & 0xFFFFFF) #define FCOE_B2V_4(x_b) \ ((((uint8_t *)(x_b))[3] | ((uint8_t *)(x_b))[2] << 8 | \ ((uint8_t *)(x_b))[1] << 16 | \ ((uint8_t *)(x_b))[0] << 24) & 0xFFFFFFFF) #define FCOE_B2V_8(x_b) \ ((((uint8_t *)(x_b))[7] | ((uint8_t *)(x_b))[6] << 8 | \ ((uint8_t *)(x_b))[5] << 16 | \ ((uint8_t *)(x_b))[4] << 24 | \ ((uint8_t *)(x_b))[3] << 32 | \ ((uint8_t *)(x_b))[2] << 40 | \ ((uint8_t *)(x_b))[1] << 48 | \ ((uint8_t *)(x_b))[0] << 56) & 0xFFFFFFFFFFFFFFFF) /* * Get FC frame header's element */ #define FRM_R_CTL(x_frm) (FCOE_B2V_1((x_frm)->frm_hdr->hdr_r_ctl)) #define FRM_D_ID(x_frm) (FCOE_B2V_3((x_frm)->frm_hdr->hdr_d_id)) #define FRM_S_ID(x_frm) (FCOE_B2V_3((x_frm)->frm_hdr->hdr_s_id)) #define FRM_TYPE(x_frm) (FCOE_B2V_1((x_frm)->frm_hdr->hdr_type)) #define FRM_F_CTL(x_frm) (FCOE_B2V_3((x_frm)->frm_hdr->hdr_f_ctl)) #define FRM_SEQ_ID(x_frm) (FCOE_B2V_1((x_frm)->frm_hdr->hdr_seq_id)) #define FRM_DF_CTL(x_frm) (FCOE_B2V_1((x_frm)->frm_hdr->hdr_df_ctl)) #define FRM_SEQ_CNT(x_frm) (FCOE_B2V_2((x_frm)->frm_hdr->hdr_seq_cnt)) #define FRM_OXID(x_frm) (FCOE_B2V_2((x_frm)->frm_hdr->hdr_oxid)) #define FRM_RXID(x_frm) (FCOE_B2V_2((x_frm)->frm_hdr->hdr_rxid)) #define FRM_PARAM(x_frm) (FCOE_B2V_4((x_frm)->frm_hdr->hdr_param)) /* * Set FC frame header's element */ #define FFM_R_CTL(x_v, x_frm) FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_r_ctl) #define FFM_D_ID(x_v, x_frm) FCOE_V2B_3((x_v), (x_frm)->frm_hdr->hdr_d_id) #define FFM_S_ID(x_v, x_frm) FCOE_V2B_3((x_v), (x_frm)->frm_hdr->hdr_s_id) #define FFM_TYPE(x_v, x_frm) FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_type) #define FFM_F_CTL(x_v, x_frm) FCOE_V2B_3((x_v), (x_frm)->frm_hdr->hdr_f_ctl) #define FFM_SEQ_ID(x_v, x_frm) FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_seq_id) #define FFM_DF_CTL(x_v, x_frm) FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_df_ctl) #define FFM_SEQ_CNT(x_v, x_frm) FCOE_V2B_2((x_v), (x_frm)->frm_hdr->hdr_seq_cnt) #define FFM_OXID(x_v, x_frm) FCOE_V2B_2((x_v), (x_frm)->frm_hdr->hdr_oxid) #define FFM_RXID(x_v, x_frm) FCOE_V2B_2((x_v), (x_frm)->frm_hdr->hdr_rxid) #define FFM_PARAM(x_v, x_frm) FCOE_V2B_4((x_v), (x_frm)->frm_hdr->hdr_param) /* * frame header checking */ #define FRM_IS_LAST_FRAME(x_frm) (FRM_F_CTL(x_frm) & (1 << 19)) #define FRM_SENDER_IS_XCH_RESPONDER(x_frm) (FRM_F_CTL(x_frm) & (1 << 23)) /* * FCOET/FCOEI will only call this fcoe function explicitly, all others * should be called through vectors in struct fcoe_port. * FCOE client call this to register one port to FCOE, FCOE need initialize * and return the corresponding fcoe_port. */ extern fcoe_port_t *fcoe_register_client(fcoe_client_t *client); #define EPORT_CLT_TYPE(eport) \ (((eport)->eport_flags & EPORT_FLAG_INI_MODE) ? \ FCOE_CLIENT_INITIATOR : FCOE_CLIENT_TARGET) #define FCOE_SET_DEFAULT_OUI(x_oui) \ (x_oui)[0] = 0x0e; (x_oui)[1] = 0xfc; (x_oui)[2] = 0x00; #define FCOE_SET_DEFAULT_FPORT_ADDR(x_addr) \ FCOE_SET_DEFAULT_OUI(x_addr) \ (x_addr)[3] = 0xff; (x_addr)[4] = 0xff; (x_addr)[5] = 0xfe; /* * FC payload size */ #define FCOE_DEFAULT_FCP_DATA_PAYLOAD_SIZE 2048 #define FCOE_MIN_FCP_DATA_PAYLOAD_SIZE 1024 typedef struct fcoe_fcp_cmnd { uint8_t ffc_lun[8]; uint8_t ffc_ref_num[1]; /* * least 3 bits */ uint8_t ffc_attribute[1]; /* * Magnagement flags */ uint8_t ffc_management_flags[1]; /* * additional cdb len and read/write flag */ uint8_t ffc_addlen_rdwr[1]; uint8_t ffc_cdb[16]; uint8_t ffc_fcp_dl[4]; } fcoe_fcp_cmnd_t; typedef struct fcoe_fcp_rsp { uint8_t ffr_rsvd[8]; /* * see SAM-4 */ uint8_t ffr_retry_delay_timer[2]; uint8_t ffr_flags[1]; uint8_t ffr_scsi_status[1]; uint8_t ffr_resid[4]; uint8_t ffr_sns_len[4]; uint8_t ffr_rsp_len[4]; /* * Followed by sense data when available */ } fcoe_fcp_rsp_t; typedef struct fcoe_fcp_xfer_rdy { uint8_t fxr_data_ro[4]; uint8_t fxr_burst_len[4]; uint8_t fxr_rsvd[4]; } fcoe_fcp_xfer_rdy_t; /* * FCOE project global functions */ #if !defined(__FUNCTION__) #define __FUNCTION__ ((caddr_t)__func__) #endif #define FCOE_STR_LEN 32 /* * timestamp (golbal variable in sys/systm.h) */ #define CURRENT_CLOCK lbolt #define FCOE_SEC2TICK(x_sec) (drv_usectohz((x_sec) * 1000000)) /* * Form/convert mod_hash_key from/to xch ID */ #define FMHK(x_xid) (mod_hash_key_t)(uintptr_t)(x_xid) #define CMHK(x_key) (uint16_t)(uintptr_t)(x_key) typedef void (*TQ_FUNC_P)(void *); extern void fcoe_trace(caddr_t ident, const char *fmt, ...); #endif #ifdef __cplusplus } #endif #endif /* _FCOE_COMMON_H_ */