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 #ifndef _SYS_NVME_DISCOVERY_H 17 #define _SYS_NVME_DISCOVERY_H 18 19 /* 20 * This defines common types that are used for discovering features of NVMe 21 * devices. The primary way for users to consume these types is through the 22 * libnvme discovery APIs. 23 */ 24 25 #ifdef __cplusplus 26 extern "C" { 27 #endif 28 29 typedef enum { 30 NVME_LOG_ID_MANDATORY, 31 NVME_LOG_ID_OPTIONAL, 32 NVME_LOG_ID_VENDOR_SPECIFIC 33 } nvme_log_disc_kind_t; 34 35 /* 36 * Different logs cover different aspects of a device. These are listed below 37 * referring to the NVMe controller, the NVM subsystem itself, and then 38 * particular namespaces. NVMe 2.x adds the notion of a domain. From a 39 * specification perspective, the NVM subsystem is instead sometimes referred to 40 * as a domain. A controller can only access a single domain so while the 2.x 41 * specifications suggest the scope is slightly different for the NVM subsystem 42 * below, they're basically the same for our purposes. 43 */ 44 typedef enum { 45 NVME_LOG_SCOPE_CTRL = 1 << 0, 46 NVME_LOG_SCOPE_NVM = 1 << 1, 47 NVME_LOG_SCOPE_NS = 1 << 2 48 } nvme_log_disc_scope_t; 49 50 typedef enum { 51 /* 52 * This indicates that the implementation information is based on 53 * knowledge from a base spec. 54 */ 55 NVME_LOG_DISC_S_SPEC = 1 << 0, 56 /* 57 * This indicates that the knowledge is from the identify controller 58 * data structure. 59 */ 60 NVME_LOG_DISC_S_ID_CTRL = 1 << 1, 61 /* 62 * This indicates that we have used our internal information database 63 * about devices from a vendor's datasheets to determine that something 64 * is supported. 65 */ 66 NVME_LOG_DISC_S_DB = 1 << 2, 67 /* 68 * This indicates that we have used a command (whether vendor-specific 69 * or the NVMe 2.x Supported Log Pages) to get additional information 70 * about this. 71 */ 72 NVME_LOG_DISC_S_CMD = 1 << 3 73 } nvme_log_disc_source_t; 74 75 typedef enum { 76 /* 77 * These next three flags indicate that the log page requires additional 78 * information for it to complete successfully. These are specifically 79 * the log specific parameter or a log specific indicator (e.g. an 80 * endurance group, NVM set, domain, etc.). RAE was introduced in NVMe 81 * 1.3 and applied to logs that already existed. It will not be possible 82 * to set RAE on a log request that operates on a controller prior to 83 * NVMe 1.3. 84 */ 85 NVME_LOG_DISC_F_NEED_LSP = 1 << 0, 86 NVME_LOG_DISC_F_NEED_LSI = 1 << 1, 87 NVME_LOG_DISC_F_NEED_RAE = 1 << 2, 88 /* 89 * Log pages whose only scope is a namespace are required to specify a 90 * namespace. Otherwise, when the scope includes a controller or NVM 91 * subsystem then it is assumed that the default is to target the 92 * controller (e.g. the health log page). 93 */ 94 NVME_LOG_DISC_F_NEED_NSID = 1 << 3 95 } nvme_log_disc_fields_t; 96 97 98 typedef enum { 99 NVME_FEAT_SCOPE_CTRL = 1 << 0, 100 NVME_FEAT_SCOPE_NS = 1 << 1 101 } nvme_feat_scope_t; 102 103 typedef enum { 104 /* 105 * Indicates that this feature requires an argument to select some part 106 * of the feature in cdw11. 107 */ 108 NVME_GET_FEAT_F_CDW11 = 1 << 0, 109 /* 110 * Indicates that this feature will output data to a specific buffer and 111 * therefore a data argument is required for this feature. 112 */ 113 NVME_GET_FEAT_F_DATA = 1 << 1, 114 /* 115 * Indicates that this feature requires a namespace ID to be specified 116 * when getting this feature. In general, while one can usually set a 117 * feature to target the broadcast namespace, the same is not true of 118 * getting a feature. 119 */ 120 NVME_GET_FEAT_F_NSID = 1 << 2, 121 } nvme_get_feat_fields_t; 122 123 typedef enum { 124 /* 125 * These indicate that the feature requires fields set in the various 126 * control words to set the feature. 127 */ 128 NVME_SET_FEAT_F_CDW11 = 1 << 0, 129 NVME_SET_FEAT_F_CDW12 = 1 << 1, 130 NVME_SET_FEAT_F_CDW13 = 1 << 2, 131 NVME_SET_FEAT_F_CDW14 = 1 << 3, 132 NVME_SET_FEAT_F_CDW15 = 1 << 4, 133 /* 134 * Indicates that there is a data payload component to this feature that 135 * must be set. 136 */ 137 NVME_SET_FEAT_F_DATA = 1 << 5, 138 /* 139 * Indicates that this feature requires a namespace ID. Broadcast IDs 140 * are more often allowed than with getting a feature, but it still 141 * depends. 142 */ 143 NVME_SET_FEAT_F_NSID = 1 << 6 144 } nvme_set_feat_fields_t; 145 146 typedef enum { 147 /* 148 * Indicates that getting the feature outputs data in cdw0 for 149 * consumption. This is the most common form of data output for getting 150 * features. Setting features usually doesn't output data in cdw0; 151 * however, a few are defined to. 152 */ 153 NVME_FEAT_OUTPUT_CDW0 = 1 << 0, 154 /* 155 * Indicates that data is output in the data buffer that was passed in. 156 * This is only ever used for get features. 157 */ 158 NVME_FEAT_OUTPUT_DATA = 1 << 1 159 } nvme_feat_output_t; 160 161 typedef enum { 162 /* 163 * Indicates that when getting or setting this feature that requires a 164 * namespace ID, the broadcast namespace is allowed. 165 */ 166 NVME_FEAT_F_GET_BCAST_NSID = 1 << 0, 167 NVME_FEAT_F_SET_BCAST_NSID = 1 << 1 168 } nvme_feat_flags_t; 169 170 typedef enum { 171 NVME_FEAT_MANDATORY = 0, 172 NVME_FEAT_OPTIONAL, 173 NVME_FEAT_VENDOR_SPECIFIC 174 } nvme_feat_kind_t; 175 176 /* 177 * This enumeration indicates whether or not a given feature is specific to a 178 * command set, and if so what one. The default is that most features are 179 * present for all command sets, which uses the NVME_FEAT_CSI_NONE value. 180 * Otherwise, it uses a bit-field to indicate what it is present in. 181 */ 182 typedef enum { 183 NVME_FEAT_CSI_NONE = 0, 184 NVME_FEAT_CSI_NVM = 1 << 0, 185 } nvme_feat_csi_t; 186 187 /* 188 * Prior to NVMe 2.x, there was no standard way to determine if a given log page 189 * was actually implemented or not. While several features had bits in the 190 * identify controller namespace, some (e.g. LBA Range Type) are optional, 191 * command-set specific, and have no such way of knowing if they're supported 192 * short of saying so. If we cannot determine this from the controller's 193 * version, type, and identify controller information, then we will indicate 194 * that we don't know. When we have full support for leveraging the NVMe 2.x 195 * Feature Identifiers Supported and Effects log pages and someone is 196 * interrogating an NVMe 2.x controller, then ideally one should not see 197 * unknown. 198 */ 199 typedef enum { 200 NVME_FEAT_IMPL_UNKNOWN = 0, 201 NVME_FEAT_IMPL_UNSUPPORTED, 202 NVME_FEAT_IMPL_SUPPORTED 203 } nvme_feat_impl_t; 204 205 #ifdef __cplusplus 206 } 207 #endif 208 209 #endif /* _SYS_NVME_DISCOVERY_H */ 210