1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 #ifndef _FCOE_COMMON_H_
  26 #define _FCOE_COMMON_H_
  27 
  28 #ifdef  __cplusplus
  29 extern "C" {
  30 #endif
  31 
  32 #ifdef  _KERNEL
  33 
  34 /*
  35  * Interface return value
  36  */
  37 #define FCOE_SUCCESS             0
  38 #define FCOE_FAILURE            -1
  39 #define FCOE_BUSY               -2
  40 #define FCOE_NOT_SUPPORTED      -3
  41 #define FCOE_BAD_FRAME          -4
  42 
  43 /*
  44  * FCOE port speed
  45  */
  46 #define FCOE_PORT_SPEED_1G      1000000000
  47 #define FCOE_PORT_SPEED_10G     10000000000
  48 
  49 /*
  50  * FC Frame header size: 24 bytes
  51  */
  52 #define FCFH_SIZE               (sizeof (fcoe_fc_frame_header_t))
  53 
  54 /*
  55  * FLOGI
  56  */
  57 #define FLOGI_REQ_PAYLOAD_SIZE  116
  58 #define FLOGI_ACC_PAYLOAD_SIZE  116
  59 
  60 #define FCOE_MIN_MTU_SIZE       2500
  61 #define FCOE_MAX_FC_FRAME_SIZE  2136
  62 
  63 /*
  64  * 24 byte FC frame header
  65  * For all data structures that have endian problems, we will use only
  66  * one type: uint8_t. We need associate the data structure pointer with
  67  * one buffer directly.
  68  */
  69 typedef struct fcoe_fc_frame_header {
  70         uint8_t hdr_r_ctl[1];
  71         uint8_t hdr_d_id[3];
  72 
  73         uint8_t hdr_cs_ctl[1];
  74         uint8_t hdr_s_id[3];
  75 
  76         uint8_t hdr_type[1];
  77         uint8_t hdr_f_ctl[3];
  78 
  79         uint8_t hdr_seq_id[1];
  80         uint8_t hdr_df_ctl[1];
  81         uint8_t hdr_seq_cnt[2];
  82 
  83         uint8_t hdr_oxid[2];
  84         uint8_t hdr_rxid[2];
  85 
  86         uint8_t hdr_param[4];
  87 } fcoe_fc_frame_header_t;
  88 
  89 /*
  90  * Solicited frame:   allocted by FCOET/FOCEI,  free-ed by FCOE
  91  * Unsolicited frame: allocated by FCOE,        free-ed by FCOET/FCOEI
  92  */
  93 struct fcoe_port;
  94 typedef struct fcoe_frame {
  95         uint32_t                 frm_flags;
  96         void                    *frm_netb;
  97 
  98         /*
  99          * frm_hdr will be cleared by fcoe explicitly
 100          */
 101         fcoe_fc_frame_header_t  *frm_hdr;
 102         uint8_t                 *frm_ofh1;
 103         uint8_t                 *frm_ofh2;
 104         uint8_t                 *frm_fc_frame;
 105 
 106         /*
 107          * fcoe client need clear FC payload explicitly,
 108          * except for RD/WR data frames
 109          */
 110         uint8_t                 *frm_payload;
 111         uint32_t                 frm_fc_frame_size;
 112         uint32_t                 frm_payload_size;
 113         uint32_t                 frm_alloc_size;
 114         struct fcoe_port        *frm_eport;
 115         void                    *frm_fcoe_private;
 116         void                    *frm_client_private;
 117         clock_t                  frm_clock;
 118 } fcoe_frame_t;
 119 
 120 /*
 121  * FCOE HBA
 122  */
 123 typedef struct fcoe_port {
 124         uint32_t           eport_flags;
 125         void              *eport_fcoe_private;
 126         void              *eport_client_private;
 127         uint8_t            eport_portwwn[8];
 128         uint8_t            eport_nodewwn[8];
 129         uint32_t           eport_max_fc_frame_size;
 130         uint32_t           eport_mtu;
 131         uint64_t           eport_link_speed;
 132         uint8_t            eport_efh_dst[ETHERADDRL];
 133 
 134         void             (*eport_tx_frame)(fcoe_frame_t *frame);
 135         fcoe_frame_t    *(*eport_alloc_frame)(struct fcoe_port *eport,
 136             uint32_t this_fc_frame_size, void *netb);
 137         void             (*eport_release_frame)(fcoe_frame_t *frame);
 138         void            *(*eport_alloc_netb)(struct fcoe_port *eport,
 139             uint32_t this_fc_frame_size, uint8_t **ppfc);
 140         void             (*eport_free_netb)(void *netb);
 141         void             (*eport_deregister_client)(struct fcoe_port *eport);
 142         int              (*eport_ctl)(struct fcoe_port *eport,
 143             int cmd, void *arg);
 144         int              (*eport_set_mac_address)(struct fcoe_port *eport,
 145             uint8_t *addr, boolean_t fc_assigned);
 146 } fcoe_port_t;
 147 
 148 /*
 149  * FCOE only supports two kinds of topology: direct P2P, fabric P2P.
 150  */
 151 #define EPORT_FLAG_IS_DIRECT_P2P        0x01
 152 #define EPORT_FLAG_TGT_MODE             0x02
 153 #define EPORT_FLAG_INI_MODE             0x04
 154 #define EPORT_FLAG_MAC_IN_USE           0x08
 155 
 156 #define FCOE_NOTIFY_EPORT_LINK_UP       0x01
 157 #define FCOE_NOTIFY_EPORT_LINK_DOWN     0x02
 158 #define FCOE_NOTIFY_EPORT_ADDR_CHG      0x03
 159 
 160 #define FCOE_PORT_CTL_CMDS              0x3000
 161 #define FCOE_CMD_PORT_ONLINE            (FCOE_PORT_CTL_CMDS | 0x01)
 162 #define FCOE_CMD_PORT_OFFLINE           (FCOE_PORT_CTL_CMDS | 0x02)
 163 
 164 /*
 165  * FCoE version control
 166  */
 167 typedef enum fcoe_ver
 168 {
 169         FCOE_VER_1 = 0xAA01,
 170         FCOE_VER_2,
 171         FCOE_VER_3,
 172         FCOE_VER_4,
 173         FCOE_VER_5
 174 } fcoe_ver_e;
 175 
 176 #define FCOE_VER_NOW FCOE_VER_1
 177 extern const fcoe_ver_e fcoe_ver_now;
 178 
 179 typedef struct fcoe_client {
 180         fcoe_ver_e       ect_fcoe_ver;
 181         uint32_t         ect_eport_flags;
 182         uint32_t         ect_max_fc_frame_size;
 183         uint32_t         ect_private_frame_struct_size;
 184         uint32_t         ect_channelid;
 185         void            *ect_client_port_struct;
 186         void             (*ect_rx_frame)(fcoe_frame_t *frame);
 187         void             (*ect_port_event)(fcoe_port_t *eport, uint32_t event);
 188         void             (*ect_release_sol_frame)(fcoe_frame_t *frame);
 189 } fcoe_client_t;
 190 
 191 /*
 192  * Define common-used conversion or calculation macros
 193  */
 194 #define FCOE_V2B_1(x_v, x_b)                            \
 195         {                                               \
 196                 ((uint8_t *)(x_b))[0] = 0xFF & (x_v);       \
 197         }
 198 
 199 #define FCOE_V2B_2(x_v, x_b)                                    \
 200         {                                                       \
 201                 ((uint8_t *)(x_b))[1] = 0xFF & (x_v);               \
 202                 ((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 8);  \
 203         }
 204 
 205 #define FCOE_V2B_3(x_v, x_b)                                    \
 206         {                                                       \
 207                 ((uint8_t *)(x_b))[2] = 0xFF & (x_v);               \
 208                 ((uint8_t *)(x_b))[1] = 0xFF & ((x_v) >> 8);  \
 209                 ((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 16); \
 210         }
 211 
 212 #define FCOE_V2B_4(x_v, x_b)                                    \
 213         {                                                       \
 214                 ((uint8_t *)(x_b))[3] = 0xFF & (x_v);               \
 215                 ((uint8_t *)(x_b))[2] = 0xFF & ((x_v) >> 8);  \
 216                 ((uint8_t *)(x_b))[1] = 0xFF & ((x_v) >> 16); \
 217                 ((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 24); \
 218         }
 219 
 220 #define FCOE_V2B_8(x_v, x_b)                                    \
 221         {                                                       \
 222                 ((uint8_t *)(x_b))[7] = 0xFF & (x_v);               \
 223                 ((uint8_t *)(x_b))[6] = 0xFF & ((x_v) >> 8);  \
 224                 ((uint8_t *)(x_b))[5] = 0xFF & ((x_v) >> 16); \
 225                 ((uint8_t *)(x_b))[4] = 0xFF & ((x_v) >> 24); \
 226                 ((uint8_t *)(x_b))[3] = 0xFF & ((x_v) >> 32); \
 227                 ((uint8_t *)(x_b))[2] = 0xFF & ((x_v) >> 40); \
 228                 ((uint8_t *)(x_b))[1] = 0xFF & ((x_v) >> 48); \
 229                 ((uint8_t *)(x_b))[0] = 0xFF & ((x_v) >> 56); \
 230         }
 231 
 232 #define FCOE_B2V_1(x_b)                         \
 233         ((((uint8_t *)(x_b))[0]) & 0xFF)
 234 
 235 #define FCOE_B2V_2(x_b)                                         \
 236         ((((uint8_t *)(x_b))[1] | ((uint8_t *)(x_b))[0] << 8) & 0xFFFF)
 237 
 238 #define FCOE_B2V_3(x_b)                                         \
 239         ((((uint8_t *)(x_b))[2] | ((uint8_t *)(x_b))[1] << 8 |    \
 240         ((uint8_t *)(x_b))[0] << 16) & 0xFFFFFF)
 241 
 242 #define FCOE_B2V_4(x_b)                                         \
 243         ((((uint8_t *)(x_b))[3] | ((uint8_t *)(x_b))[2] << 8 |    \
 244         ((uint8_t *)(x_b))[1] << 16 |                             \
 245         ((uint8_t *)(x_b))[0] << 24) & 0xFFFFFFFF)
 246 
 247 #define FCOE_B2V_8(x_b)                                         \
 248         ((((uint8_t *)(x_b))[7] | ((uint8_t *)(x_b))[6] << 8 |    \
 249         ((uint8_t *)(x_b))[5] << 16 |                             \
 250         ((uint8_t *)(x_b))[4] << 24 |                             \
 251         ((uint8_t *)(x_b))[3] << 32 |                             \
 252         ((uint8_t *)(x_b))[2] << 40 |                             \
 253         ((uint8_t *)(x_b))[1] << 48 |                             \
 254         ((uint8_t *)(x_b))[0] << 56) & 0xFFFFFFFFFFFFFFFF)
 255 
 256 /*
 257  * Get FC frame header's element
 258  */
 259 #define FRM_R_CTL(x_frm)        (FCOE_B2V_1((x_frm)->frm_hdr->hdr_r_ctl))
 260 #define FRM_D_ID(x_frm)         (FCOE_B2V_3((x_frm)->frm_hdr->hdr_d_id))
 261 #define FRM_S_ID(x_frm)         (FCOE_B2V_3((x_frm)->frm_hdr->hdr_s_id))
 262 #define FRM_TYPE(x_frm)         (FCOE_B2V_1((x_frm)->frm_hdr->hdr_type))
 263 #define FRM_F_CTL(x_frm)        (FCOE_B2V_3((x_frm)->frm_hdr->hdr_f_ctl))
 264 #define FRM_SEQ_ID(x_frm)       (FCOE_B2V_1((x_frm)->frm_hdr->hdr_seq_id))
 265 #define FRM_DF_CTL(x_frm)       (FCOE_B2V_1((x_frm)->frm_hdr->hdr_df_ctl))
 266 #define FRM_SEQ_CNT(x_frm)      (FCOE_B2V_2((x_frm)->frm_hdr->hdr_seq_cnt))
 267 #define FRM_OXID(x_frm)         (FCOE_B2V_2((x_frm)->frm_hdr->hdr_oxid))
 268 #define FRM_RXID(x_frm)         (FCOE_B2V_2((x_frm)->frm_hdr->hdr_rxid))
 269 #define FRM_PARAM(x_frm)        (FCOE_B2V_4((x_frm)->frm_hdr->hdr_param))
 270 
 271 /*
 272  * Set FC frame header's element
 273  */
 274 #define FFM_R_CTL(x_v, x_frm)   FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_r_ctl)
 275 #define FFM_D_ID(x_v, x_frm)    FCOE_V2B_3((x_v), (x_frm)->frm_hdr->hdr_d_id)
 276 #define FFM_S_ID(x_v, x_frm)    FCOE_V2B_3((x_v), (x_frm)->frm_hdr->hdr_s_id)
 277 #define FFM_TYPE(x_v, x_frm)    FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_type)
 278 #define FFM_F_CTL(x_v, x_frm)   FCOE_V2B_3((x_v), (x_frm)->frm_hdr->hdr_f_ctl)
 279 #define FFM_SEQ_ID(x_v, x_frm)  FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_seq_id)
 280 #define FFM_DF_CTL(x_v, x_frm)  FCOE_V2B_1((x_v), (x_frm)->frm_hdr->hdr_df_ctl)
 281 #define FFM_SEQ_CNT(x_v, x_frm) FCOE_V2B_2((x_v), (x_frm)->frm_hdr->hdr_seq_cnt)
 282 #define FFM_OXID(x_v, x_frm)    FCOE_V2B_2((x_v), (x_frm)->frm_hdr->hdr_oxid)
 283 #define FFM_RXID(x_v, x_frm)    FCOE_V2B_2((x_v), (x_frm)->frm_hdr->hdr_rxid)
 284 #define FFM_PARAM(x_v, x_frm)   FCOE_V2B_4((x_v), (x_frm)->frm_hdr->hdr_param)
 285 
 286 /*
 287  * frame header checking
 288  */
 289 #define FRM_IS_LAST_FRAME(x_frm)                (FRM_F_CTL(x_frm) & (1 << 19))
 290 #define FRM_SENDER_IS_XCH_RESPONDER(x_frm)      (FRM_F_CTL(x_frm) & (1 << 23))
 291 
 292 /*
 293  * FCOET/FCOEI will only call this fcoe function explicitly, all others
 294  * should be called through vectors in struct fcoe_port.
 295  * FCOE client call this to register one port to FCOE, FCOE need initialize
 296  * and return the corresponding fcoe_port.
 297  */
 298 extern fcoe_port_t *fcoe_register_client(fcoe_client_t *client);
 299 
 300 #define EPORT_CLT_TYPE(eport)                           \
 301         (((eport)->eport_flags & EPORT_FLAG_INI_MODE) ? \
 302         FCOE_CLIENT_INITIATOR : FCOE_CLIENT_TARGET)
 303 
 304 #define FCOE_SET_DEFAULT_OUI(x_oui)     \
 305         (x_oui)[0] = 0x0e; (x_oui)[1] = 0xfc; (x_oui)[2] = 0x00;
 306 #define FCOE_SET_DEFAULT_FPORT_ADDR(x_addr)     \
 307         FCOE_SET_DEFAULT_OUI(x_addr)            \
 308         (x_addr)[3] = 0xff; (x_addr)[4] = 0xff; (x_addr)[5] = 0xfe;
 309 
 310 /*
 311  * FC payload size
 312  */
 313 #define FCOE_DEFAULT_FCP_DATA_PAYLOAD_SIZE      2048
 314 #define FCOE_MIN_FCP_DATA_PAYLOAD_SIZE          1024
 315 
 316 typedef struct fcoe_fcp_cmnd {
 317         uint8_t ffc_lun[8];
 318         uint8_t ffc_ref_num[1];
 319 
 320         /*
 321          * least 3 bits
 322          */
 323         uint8_t ffc_attribute[1];
 324 
 325         /*
 326          * Magnagement flags
 327          */
 328         uint8_t ffc_management_flags[1];
 329 
 330         /*
 331          * additional cdb len and read/write flag
 332          */
 333         uint8_t ffc_addlen_rdwr[1];
 334 
 335         uint8_t ffc_cdb[16];
 336         uint8_t ffc_fcp_dl[4];
 337 } fcoe_fcp_cmnd_t;
 338 
 339 typedef struct fcoe_fcp_rsp {
 340         uint8_t ffr_rsvd[8];
 341 
 342         /*
 343          * see SAM-4
 344          */
 345         uint8_t ffr_retry_delay_timer[2];
 346         uint8_t ffr_flags[1];
 347         uint8_t ffr_scsi_status[1];
 348         uint8_t ffr_resid[4];
 349         uint8_t ffr_sns_len[4];
 350         uint8_t ffr_rsp_len[4];
 351         /*
 352          * Followed by sense data when available
 353          */
 354 } fcoe_fcp_rsp_t;
 355 
 356 typedef struct fcoe_fcp_xfer_rdy {
 357         uint8_t fxr_data_ro[4];
 358         uint8_t fxr_burst_len[4];
 359         uint8_t fxr_rsvd[4];
 360 } fcoe_fcp_xfer_rdy_t;
 361 
 362 /*
 363  * FCOE project global functions
 364  */
 365 #if !defined(__FUNCTION__)
 366 #define __FUNCTION__ ((caddr_t)__func__)
 367 #endif
 368 
 369 #define FCOE_STR_LEN 32
 370 
 371 /*
 372  * timestamp (golbal variable in sys/systm.h)
 373  */
 374 #define CURRENT_CLOCK           (ddi_get_lbolt())
 375 #define FCOE_SEC2TICK(x_sec)    (drv_usectohz((x_sec) * 1000000))
 376 
 377 /*
 378  * Form/convert mod_hash_key from/to xch ID
 379  */
 380 #define FMHK(x_xid)             (mod_hash_key_t)(uintptr_t)(x_xid)
 381 #define CMHK(x_key)             (uint16_t)(uintptr_t)(x_key)
 382 
 383 typedef void (*TQ_FUNC_P)(void *);
 384 extern void fcoe_trace(caddr_t ident, const char *fmt, ...);
 385 
 386 #endif
 387 
 388 #ifdef  __cplusplus
 389 }
 390 #endif
 391 
 392 #endif  /* _FCOE_COMMON_H_ */