/*
* 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 (ddi_get_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_ */