1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2024 Oxide Computer Company 14 */ 15 16 /* 17 * Information about supported NVMe identify commands that can be issued. 18 */ 19 20 #include "nvme_common.h" 21 22 #include <sys/sysmacros.h> 23 24 static bool 25 nvme_identify_field_valid_cns(const nvme_field_info_t *field, 26 const nvme_valid_ctrl_data_t *data, uint64_t cns, char *msg, size_t msglen) 27 { 28 uint64_t max; 29 30 if (nvme_field_atleast(data, &nvme_vers_1v2)) { 31 max = NVME_IDENTIFY_MAX_CNS_1v2; 32 } else if (nvme_field_atleast(data, &nvme_vers_1v1)) { 33 max = NVME_IDENTIFY_MAX_CNS_1v1; 34 } else { 35 max = NVME_IDENTIFY_MAX_CNS; 36 } 37 38 return (nvme_field_range_check(field, 0, max, msg, msglen, cns)); 39 } 40 41 static bool 42 nvme_identify_field_valid_buf(const nvme_field_info_t *field, 43 const nvme_valid_ctrl_data_t *data, uint64_t len, char *msg, size_t msglen) 44 { 45 return (nvme_field_range_check(field, NVME_IDENTIFY_BUFSIZE, 46 NVME_IDENTIFY_BUFSIZE, msg, msglen, len)); 47 } 48 49 const nvme_field_info_t nvme_identify_fields[] = { 50 [NVME_ID_REQ_F_CNS] = { 51 .nlfi_vers = &nvme_vers_1v0, 52 .nlfi_valid = nvme_identify_field_valid_cns, 53 .nlfi_spec = "cns", 54 .nlfi_human = "Controller or Namespace Structure", 55 .nlfi_def_req = true, 56 .nlfi_def_allow = true 57 }, 58 [NVME_ID_REQ_F_NSID] = { 59 .nlfi_vers = &nvme_vers_1v0, 60 .nlfi_spec = "nsid", 61 /* 62 * The NSID for an identify command can have several different 63 * forms. 64 */ 65 .nlfi_max_size = NVME_IDENTIFY_MAX_NSID, 66 .nlfi_human = "namespace ID", 67 .nlfi_def_req = false, 68 .nlfi_def_allow = true 69 }, 70 [NVME_ID_REQ_F_CTRLID] = { 71 .nlfi_vers = &nvme_vers_1v2, 72 .nlfi_max_size = NVME_IDENTIFY_MAX_CTRLID, 73 .nlfi_spec = "cntid", 74 .nlfi_human = "Controller ID", 75 .nlfi_def_req = false, 76 .nlfi_def_allow = true 77 }, 78 [NVME_ID_REQ_F_BUF] = { 79 .nlfi_vers = &nvme_vers_1v0, 80 .nlfi_valid = nvme_identify_field_valid_buf, 81 .nlfi_spec = "dptr", 82 .nlfi_human = "output", 83 .nlfi_def_req = true, 84 .nlfi_def_allow = true 85 } 86 }; 87 88 size_t nvme_identify_nfields = ARRAY_SIZE(nvme_identify_fields); 89 90 static bool 91 nvme_identify_support_nsid(const nvme_valid_ctrl_data_t *data) 92 { 93 return (data->vcd_id->id_oacs.oa_nsmgmt != 0); 94 } 95 96 const nvme_identify_info_t nvme_identify_cmds[] = { { 97 .nii_name = "identify namespace", 98 .nii_csi = NVME_CSI_NVM, 99 .nii_cns = NVME_IDENTIFY_NSID, 100 .nii_vers = &nvme_vers_1v0, 101 .nii_fields = 1 << NVME_ID_REQ_F_NSID, 102 .nii_flags = NVME_IDENTIFY_INFO_F_NS_OK | NVME_IDENTIFY_INFO_F_BCAST 103 }, { 104 .nii_name = "identify controller", 105 .nii_csi = NVME_CSI_NVM, 106 .nii_cns = NVME_IDENTIFY_CTRL, 107 .nii_vers = &nvme_vers_1v0, 108 }, { 109 .nii_name = "active namespace ID list", 110 .nii_csi = NVME_CSI_NVM, 111 .nii_cns = NVME_IDENTIFY_NSID_LIST, 112 .nii_vers = &nvme_vers_1v1, 113 .nii_fields = 1 << NVME_ID_REQ_F_NSID, 114 .nii_flags = NVME_IDENTIFY_INFO_F_NSID_LIST 115 }, { 116 .nii_name = "namespace identification descriptor list", 117 .nii_csi = NVME_CSI_NVM, 118 .nii_cns = NVME_IDENTIFY_NSID_DESC, 119 .nii_vers = &nvme_vers_1v3, 120 .nii_fields = (1 << NVME_ID_REQ_F_NSID), 121 .nii_flags = NVME_IDENTIFY_INFO_F_NS_OK 122 }, { 123 .nii_name = "allocated namespace id list", 124 .nii_csi = NVME_CSI_NVM, 125 .nii_cns = NVME_IDENTIFY_NSID_ALLOC_LIST, 126 .nii_vers = &nvme_vers_1v2, 127 .nii_sup_func = nvme_identify_support_nsid, 128 .nii_fields = 1 << NVME_ID_REQ_F_NSID, 129 .nii_flags = NVME_IDENTIFY_INFO_F_NSID_LIST 130 }, { 131 .nii_name = "identify allocated namespace", 132 .nii_csi = NVME_CSI_NVM, 133 .nii_cns = NVME_IDENTIFY_NSID_ALLOC, 134 .nii_vers = &nvme_vers_1v2, 135 .nii_sup_func = nvme_identify_support_nsid, 136 .nii_fields = 1 << NVME_ID_REQ_F_NSID, 137 .nii_flags = NVME_IDENTIFY_INFO_F_NS_OK 138 }, { 139 .nii_name = "namespace attached controller list", 140 .nii_csi = NVME_CSI_NVM, 141 .nii_cns = NVME_IDENTIFY_NSID_CTRL_LIST, 142 .nii_vers = &nvme_vers_1v2, 143 .nii_sup_func = nvme_identify_support_nsid, 144 .nii_fields = (1 << NVME_ID_REQ_F_NSID) | (1 << NVME_ID_REQ_F_CTRLID), 145 .nii_flags = NVME_IDENTIFY_INFO_F_NS_OK 146 }, { 147 .nii_name = "nvm subsystem controller list", 148 .nii_csi = NVME_CSI_NVM, 149 .nii_cns = NVME_IDENTIFY_CTRL_LIST, 150 .nii_vers = &nvme_vers_1v2, 151 .nii_sup_func = nvme_identify_support_nsid, 152 .nii_fields = (1 << NVME_ID_REQ_F_CTRLID) 153 } }; 154 155 size_t nvme_identify_ncmds = ARRAY_SIZE(nvme_identify_cmds); 156 157 bool 158 nvme_identify_info_supported(const nvme_identify_info_t *info, 159 const nvme_valid_ctrl_data_t *data) 160 { 161 if (info->nii_vers != NULL && !nvme_field_atleast(data, 162 info->nii_vers)) { 163 return (false); 164 } 165 166 if (info->nii_sup_func != NULL && !info->nii_sup_func(data)) { 167 return (false); 168 } 169 170 return (true); 171 } 172