1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2019 Intel Corporation. 3 * Copyright (c) 2018-2019 Broadcom. All Rights Reserved. 4 * The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. 5 */ 6 7 #ifndef __NVMF_FC_SPEC_H__ 8 #define __NVMF_FC_SPEC_H__ 9 10 #include "spdk/env.h" 11 #include "spdk/nvme.h" 12 13 #ifdef __cplusplus 14 extern "C" { 15 #endif 16 17 /* 18 * FC-NVMe Spec. Definitions 19 */ 20 21 #define FCNVME_R_CTL_CMD_REQ 0x06 22 #define FCNVME_R_CTL_DATA_OUT 0x01 23 #define FCNVME_R_CTL_CONFIRM 0x03 24 #define FCNVME_R_CTL_STATUS 0x07 25 #define FCNVME_R_CTL_ERSP_STATUS 0x08 26 #define FCNVME_R_CTL_LS_REQUEST 0x32 27 #define FCNVME_R_CTL_LS_RESPONSE 0x33 28 #define FCNVME_R_CTL_BA_ABTS 0x81 29 30 #define FCNVME_F_CTL_END_SEQ 0x080000 31 #define FCNVME_F_CTL_SEQ_INIT 0x010000 32 33 /* END_SEQ | LAST_SEQ | Exchange Responder | SEQ init */ 34 #define FCNVME_F_CTL_RSP 0x990000 35 #define FCNVME_F_CTL_PRIORITY_ENABLE 0x020000 36 37 #define FCNVME_D_FCTL_DEVICE_HDR_16_MASK 0x1 38 #define FCNVME_D_FCTL_NETWORK_HDR_MASK 0x20 39 #define FCNVME_D_FCTL_NETWORK_HDR_SIZE 16 40 #define FCNVME_D_FCTL_ESP_HDR_MASK 0x40 41 #define FCNVME_D_FCTL_ESP_HDR_SIZE 8 42 43 #define FCNVME_TYPE_BLS 0x0 44 #define FCNVME_TYPE_FC_EXCHANGE 0x08 45 #define FCNVME_TYPE_NVMF_DATA 0x28 46 47 #define FCNVME_CMND_IU_FC_ID 0x28 48 #define FCNVME_CMND_IU_SCSI_ID 0xFD 49 50 #define FCNVME_CMND_IU_NODATA 0x00 51 #define FCNVME_CMND_IU_READ 0x10 52 #define FCNVME_CMND_IU_WRITE 0x01 53 54 /* BLS reject error codes */ 55 #define FCNVME_BLS_REJECT_UNABLE_TO_PERFORM 0x09 56 #define FCNVME_BLS_REJECT_EXP_NOINFO 0x00 57 #define FCNVME_BLS_REJECT_EXP_INVALID_OXID 0x03 58 59 /* 60 * FC NVMe Link Services (LS) constants 61 */ 62 #define FCNVME_MAX_LS_REQ_SIZE 1536 63 #define FCNVME_MAX_LS_RSP_SIZE 64 64 65 #define FCNVME_LS_CA_CMD_MIN_LEN 592 66 #define FCNVME_LS_CA_DESC_LIST_MIN_LEN 584 67 #define FCNVME_LS_CA_DESC_MIN_LEN 576 68 69 /* this value needs to be in sync with low level driver buffer size */ 70 #define FCNVME_MAX_LS_BUFFER_SIZE 2048 71 72 #define FCNVME_GOOD_RSP_LEN 12 73 #define FCNVME_ASSOC_HOSTID_LEN 16 74 75 76 typedef uint64_t FCNVME_BE64; 77 typedef uint32_t FCNVME_BE32; 78 typedef uint16_t FCNVME_BE16; 79 80 /* 81 * FC-NVME LS Commands 82 */ 83 enum { 84 FCNVME_LS_RSVD = 0, 85 FCNVME_LS_RJT = 1, 86 FCNVME_LS_ACC = 2, 87 FCNVME_LS_CREATE_ASSOCIATION = 3, 88 FCNVME_LS_CREATE_CONNECTION = 4, 89 FCNVME_LS_DISCONNECT = 5, 90 }; 91 92 /* 93 * FC-NVME Link Service Descriptors 94 */ 95 enum { 96 FCNVME_LSDESC_RSVD = 0x0, 97 FCNVME_LSDESC_RQST = 0x1, 98 FCNVME_LSDESC_RJT = 0x2, 99 FCNVME_LSDESC_CREATE_ASSOC_CMD = 0x3, 100 FCNVME_LSDESC_CREATE_CONN_CMD = 0x4, 101 FCNVME_LSDESC_DISCONN_CMD = 0x5, 102 FCNVME_LSDESC_CONN_ID = 0x6, 103 FCNVME_LSDESC_ASSOC_ID = 0x7, 104 }; 105 106 /* 107 * LS Reject reason_codes 108 */ 109 enum fcnvme_ls_rjt_reason { 110 FCNVME_RJT_RC_NONE = 0, /* no reason - not to be sent */ 111 FCNVME_RJT_RC_INVAL = 0x01, /* invalid NVMe_LS command code */ 112 FCNVME_RJT_RC_LOGIC = 0x03, /* logical error */ 113 FCNVME_RJT_RC_UNAB = 0x09, /* unable to perform request */ 114 FCNVME_RJT_RC_UNSUP = 0x0b, /* command not supported */ 115 FCNVME_RJT_RC_INPROG = 0x0e, /* command already in progress */ 116 FCNVME_RJT_RC_INV_ASSOC = 0x40, /* invalid Association ID */ 117 FCNVME_RJT_RC_INV_CONN = 0x41, /* invalid Connection ID */ 118 FCNVME_RJT_RC_INV_PARAM = 0x42, /* invalid parameters */ 119 FCNVME_RJT_RC_INSUFF_RES = 0x43, /* insufficient resources */ 120 FCNVME_RJT_RC_INV_HOST = 0x44, /* invalid or rejected host */ 121 FCNVME_RJT_RC_VENDOR = 0xff, /* vendor specific error */ 122 }; 123 124 /* 125 * LS Reject reason_explanation codes 126 */ 127 enum fcnvme_ls_rjt_explan { 128 FCNVME_RJT_EXP_NONE = 0x00, /* No additional explanation */ 129 FCNVME_RJT_EXP_OXID_RXID = 0x17, /* invalid OX_ID-RX_ID combo */ 130 FCNVME_RJT_EXP_UNAB_DATA = 0x2a, /* unable to supply data */ 131 FCNVME_RJT_EXP_INV_LEN = 0x2d, /* invalid payload length */ 132 FCNVME_RJT_EXP_INV_ESRP = 0x40, /* invalid ESRP ratio */ 133 FCNVME_RJT_EXP_INV_CTL_ID = 0x41, /* invalid controller ID */ 134 FCNVME_RJT_EXP_INV_Q_ID = 0x42, /* invalid queue ID */ 135 FCNVME_RJT_EXP_SQ_SIZE = 0x43, /* invalid submission queue size */ 136 FCNVME_RJT_EXP_INV_HOST_ID = 0x44, /* invalid or rejected host ID */ 137 FCNVME_RJT_EXP_INV_HOSTNQN = 0x45, /* invalid or rejected host NQN */ 138 FCNVME_RJT_EXP_INV_SUBNQN = 0x46, /* invalid or rejected subsys nqn */ 139 }; 140 141 /* 142 * NVMe over FC CMD IU 143 */ 144 struct spdk_nvmf_fc_cmnd_iu { 145 uint32_t scsi_id: 8, 146 fc_id: 8, 147 cmnd_iu_len: 16; 148 uint32_t rsvd0: 24, 149 flags: 8; 150 uint64_t conn_id; 151 uint32_t cmnd_seq_num; 152 uint32_t data_len; 153 struct spdk_nvme_cmd cmd; 154 uint32_t rsvd1[2]; 155 }; 156 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_cmnd_iu) == 96, "size_mismatch"); 157 158 /* 159 * NVMe over Extended Response IU 160 */ 161 struct spdk_nvmf_fc_ersp_iu { 162 uint32_t status_code: 8, 163 rsvd0: 8, 164 ersp_len: 16; 165 uint32_t response_seq_no; 166 uint32_t transferred_data_len; 167 uint32_t rsvd1; 168 struct spdk_nvme_cpl rsp; 169 }; 170 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ersp_iu) == 32, "size_mismatch"); 171 172 /* 173 * Transfer ready IU 174 */ 175 struct spdk_nvmf_fc_xfer_rdy_iu { 176 uint32_t relative_offset; 177 uint32_t burst_len; 178 uint32_t rsvd; 179 }; 180 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_xfer_rdy_iu) == 12, "size_mismatch"); 181 182 /* 183 * FC VM header 184 */ 185 struct spdk_nvmf_fc_vm_header { 186 FCNVME_BE32 dst_vmid; 187 FCNVME_BE32 src_vmid; 188 FCNVME_BE32 rsvd0; 189 FCNVME_BE32 rsvd1; 190 }; 191 192 /* 193 * FC NVME Frame Header 194 */ 195 struct spdk_nvmf_fc_frame_hdr { 196 FCNVME_BE32 r_ctl: 8, 197 d_id: 24; 198 FCNVME_BE32 cs_ctl: 8, 199 s_id: 24; 200 FCNVME_BE32 type: 8, 201 f_ctl: 24; 202 FCNVME_BE32 seq_id: 8, 203 df_ctl: 8, 204 seq_cnt: 16; 205 FCNVME_BE32 ox_id: 16, 206 rx_id: 16; 207 FCNVME_BE32 parameter; 208 }; 209 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_frame_hdr) == 24, "size_mismatch"); 210 211 /* 212 * Request payload word 0 213 */ 214 struct spdk_nvmf_fc_ls_rqst_w0 { 215 uint8_t ls_cmd; /* FCNVME_LS_xxx */ 216 uint8_t zeros[3]; 217 }; 218 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_rqst_w0) == 4, "size_mismatch"); 219 220 /* 221 * LS request information descriptor 222 */ 223 struct spdk_nvmf_fc_lsdesc_rqst { 224 FCNVME_BE32 desc_tag; /* FCNVME_LSDESC_xxx */ 225 FCNVME_BE32 desc_len; 226 struct spdk_nvmf_fc_ls_rqst_w0 w0; 227 FCNVME_BE32 rsvd12; 228 }; 229 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_rqst) == 16, "size_mismatch"); 230 231 /* 232 * LS accept header 233 */ 234 struct spdk_nvmf_fc_ls_acc_hdr { 235 struct spdk_nvmf_fc_ls_rqst_w0 w0; 236 FCNVME_BE32 desc_list_len; 237 struct spdk_nvmf_fc_lsdesc_rqst rqst; 238 /* Followed by cmd-specific ACC descriptors, see next definitions */ 239 }; 240 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_acc_hdr) == 24, "size_mismatch"); 241 242 /* 243 * LS descriptor connection id 244 */ 245 struct spdk_nvmf_fc_lsdesc_conn_id { 246 FCNVME_BE32 desc_tag; 247 FCNVME_BE32 desc_len; 248 FCNVME_BE64 connection_id; 249 }; 250 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_conn_id) == 16, "size_mismatch"); 251 252 /* 253 * LS descriptor association id 254 */ 255 struct spdk_nvmf_fc_lsdesc_assoc_id { 256 FCNVME_BE32 desc_tag; 257 FCNVME_BE32 desc_len; 258 FCNVME_BE64 association_id; 259 }; 260 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_assoc_id) == 16, "size_mismatch"); 261 262 /* 263 * LS Create Association descriptor 264 */ 265 struct spdk_nvmf_fc_lsdesc_cr_assoc_cmd { 266 FCNVME_BE32 desc_tag; 267 FCNVME_BE32 desc_len; 268 FCNVME_BE16 ersp_ratio; 269 FCNVME_BE16 rsvd10; 270 FCNVME_BE32 rsvd12[9]; 271 FCNVME_BE16 cntlid; 272 FCNVME_BE16 sqsize; 273 FCNVME_BE32 rsvd52; 274 uint8_t hostid[FCNVME_ASSOC_HOSTID_LEN]; 275 uint8_t hostnqn[SPDK_NVME_NQN_FIELD_SIZE]; 276 uint8_t subnqn[SPDK_NVME_NQN_FIELD_SIZE]; 277 uint8_t rsvd584[432]; 278 }; 279 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_cr_assoc_cmd) == 1016, "size_mismatch"); 280 281 /* 282 * LS Create Association request payload 283 */ 284 struct spdk_nvmf_fc_ls_cr_assoc_rqst { 285 struct spdk_nvmf_fc_ls_rqst_w0 w0; 286 FCNVME_BE32 desc_list_len; 287 struct spdk_nvmf_fc_lsdesc_cr_assoc_cmd assoc_cmd; 288 }; 289 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_cr_assoc_rqst) == 1024, "size_mismatch"); 290 291 /* 292 * LS Create Association accept payload 293 */ 294 struct spdk_nvmf_fc_ls_cr_assoc_acc { 295 struct spdk_nvmf_fc_ls_acc_hdr hdr; 296 struct spdk_nvmf_fc_lsdesc_assoc_id assoc_id; 297 struct spdk_nvmf_fc_lsdesc_conn_id conn_id; 298 }; 299 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_cr_assoc_acc) == 56, "size_mismatch"); 300 301 /* 302 * LS Create IO Connection descriptor 303 */ 304 struct spdk_nvmf_fc_lsdesc_cr_conn_cmd { 305 FCNVME_BE32 desc_tag; 306 FCNVME_BE32 desc_len; 307 FCNVME_BE16 ersp_ratio; 308 FCNVME_BE16 rsvd10; 309 FCNVME_BE32 rsvd12[9]; 310 FCNVME_BE16 qid; 311 FCNVME_BE16 sqsize; 312 FCNVME_BE32 rsvd52; 313 }; 314 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_cr_assoc_acc) == 56, "size_mismatch"); 315 316 /* 317 * LS Create IO Connection payload 318 */ 319 struct spdk_nvmf_fc_ls_cr_conn_rqst { 320 struct spdk_nvmf_fc_ls_rqst_w0 w0; 321 FCNVME_BE32 desc_list_len; 322 struct spdk_nvmf_fc_lsdesc_assoc_id assoc_id; 323 struct spdk_nvmf_fc_lsdesc_cr_conn_cmd connect_cmd; 324 }; 325 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_cr_conn_rqst) == 80, "size_mismatch"); 326 327 /* 328 * LS Create IO Connection accept payload 329 */ 330 struct spdk_nvmf_fc_ls_cr_conn_acc { 331 struct spdk_nvmf_fc_ls_acc_hdr hdr; 332 struct spdk_nvmf_fc_lsdesc_conn_id conn_id; 333 }; 334 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_cr_conn_acc) == 40, "size_mismatch"); 335 336 /* 337 * LS Disconnect descriptor 338 */ 339 struct spdk_nvmf_fc_lsdesc_disconn_cmd { 340 FCNVME_BE32 desc_tag; 341 FCNVME_BE32 desc_len; 342 FCNVME_BE32 rsvd8; 343 FCNVME_BE32 rsvd12; 344 FCNVME_BE32 rsvd16; 345 FCNVME_BE32 rsvd20; 346 }; 347 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_disconn_cmd) == 24, "size_mismatch"); 348 349 /* 350 * LS Disconnect payload 351 */ 352 struct spdk_nvmf_fc_ls_disconnect_rqst { 353 struct spdk_nvmf_fc_ls_rqst_w0 w0; 354 FCNVME_BE32 desc_list_len; 355 struct spdk_nvmf_fc_lsdesc_assoc_id assoc_id; 356 struct spdk_nvmf_fc_lsdesc_disconn_cmd disconn_cmd; 357 }; 358 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_disconnect_rqst) == 48, "size_mismatch"); 359 360 /* 361 * LS Disconnect accept payload 362 */ 363 struct spdk_nvmf_fc_ls_disconnect_acc { 364 struct spdk_nvmf_fc_ls_acc_hdr hdr; 365 }; 366 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_disconnect_acc) == 24, "size_mismatch"); 367 368 /* 369 * LS Reject descriptor 370 */ 371 struct spdk_nvmf_fc_lsdesc_rjt { 372 FCNVME_BE32 desc_tag; 373 FCNVME_BE32 desc_len; 374 uint8_t rsvd8; 375 376 uint8_t reason_code; 377 uint8_t reason_explanation; 378 379 uint8_t vendor; 380 FCNVME_BE32 rsvd12; 381 }; 382 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_lsdesc_rjt) == 16, "size_mismatch"); 383 384 /* 385 * LS Reject payload 386 */ 387 struct spdk_nvmf_fc_ls_rjt { 388 struct spdk_nvmf_fc_ls_rqst_w0 w0; 389 FCNVME_BE32 desc_list_len; 390 struct spdk_nvmf_fc_lsdesc_rqst rqst; 391 struct spdk_nvmf_fc_lsdesc_rjt rjt; 392 }; 393 SPDK_STATIC_ASSERT(sizeof(struct spdk_nvmf_fc_ls_rjt) == 40, "size_mismatch"); 394 395 /* 396 * FC World Wide Name 397 */ 398 struct spdk_nvmf_fc_wwn { 399 union { 400 uint64_t wwn; /* World Wide Names consist of eight bytes */ 401 uint8_t octets[sizeof(uint64_t)]; 402 } u; 403 }; 404 405 #ifdef __cplusplus 406 } 407 #endif 408 409 #endif 410