1533affcbSRobert Mustacchi /* 2533affcbSRobert Mustacchi * This file and its contents are supplied under the terms of the 3533affcbSRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0. 4533affcbSRobert Mustacchi * You may only use this file in accordance with the terms of version 5533affcbSRobert Mustacchi * 1.0 of the CDDL. 6533affcbSRobert Mustacchi * 7533affcbSRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this 8533affcbSRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at 9533affcbSRobert Mustacchi * http://www.illumos.org/license/CDDL. 10533affcbSRobert Mustacchi */ 11533affcbSRobert Mustacchi 12533affcbSRobert Mustacchi /* 13533affcbSRobert Mustacchi * Copyright 2024 Oxide Computer Company 14533affcbSRobert Mustacchi */ 15533affcbSRobert Mustacchi 16533affcbSRobert Mustacchi #ifndef _LIBNVME_H 17533affcbSRobert Mustacchi #define _LIBNVME_H 18533affcbSRobert Mustacchi 19533affcbSRobert Mustacchi /* 20533affcbSRobert Mustacchi * This contains an evolving set of interfaces for more programmatically 21533affcbSRobert Mustacchi * interfacing with NVMe devices. For more information on why the library looks 22533affcbSRobert Mustacchi * this way, please see lib/libnvme/common/libnvme.c. 23533affcbSRobert Mustacchi */ 24533affcbSRobert Mustacchi 25533affcbSRobert Mustacchi #ifdef __cplusplus 26533affcbSRobert Mustacchi extern "C" { 27533affcbSRobert Mustacchi #endif 28533affcbSRobert Mustacchi 29533affcbSRobert Mustacchi #include <stdint.h> 30533affcbSRobert Mustacchi #include <stdbool.h> 31533affcbSRobert Mustacchi #include <libdevinfo.h> 32533affcbSRobert Mustacchi #include <sys/nvme/discovery.h> 33533affcbSRobert Mustacchi 34533affcbSRobert Mustacchi /* 35533affcbSRobert Mustacchi * Right now everything relies on seeing various pieces that are in sys/nvme.h, 36533affcbSRobert Mustacchi * unfortunately. This includes things like the identify, log page, and 37533affcbSRobert Mustacchi * structure data structures, various constants, and other things that have 38533affcbSRobert Mustacchi * accumulated. This must all be rejiggered prior to making this a committed 39533affcbSRobert Mustacchi * interface as we're leaking through many things that software needs. 40533affcbSRobert Mustacchi * Directionally splitting this out into headers that relate to the spec as 41533affcbSRobert Mustacchi * <sys/nvme/identify.h>, etc. would be useful and would address several of the 42533affcbSRobert Mustacchi * places that we're passing in raw uint32_t's for items that come from the spec 43533affcbSRobert Mustacchi * and could be a little more specific to help out consumers. 44533affcbSRobert Mustacchi */ 45533affcbSRobert Mustacchi #include <sys/nvme.h> 46533affcbSRobert Mustacchi 47533affcbSRobert Mustacchi /* 48533affcbSRobert Mustacchi * General error classes that may be returned when operating on non-information 49533affcbSRobert Mustacchi * snapshots. 50533affcbSRobert Mustacchi */ 51533affcbSRobert Mustacchi typedef enum { 52533affcbSRobert Mustacchi NVME_ERR_OK = 0, 53533affcbSRobert Mustacchi /* 54533affcbSRobert Mustacchi * Indicates that a command failed due to a controller-specific error. 55533affcbSRobert Mustacchi * The controller's SCT/SC are valid in the corresponding objects error 56533affcbSRobert Mustacchi * data. 57533affcbSRobert Mustacchi */ 58533affcbSRobert Mustacchi NVME_ERR_CONTROLLER, 59533affcbSRobert Mustacchi /* 60533affcbSRobert Mustacchi * Indicates that there was a memory allocation error. The system error 61533affcbSRobert Mustacchi * contains the specific errno. 62533affcbSRobert Mustacchi */ 63533affcbSRobert Mustacchi NVME_ERR_NO_MEM, 64533affcbSRobert Mustacchi /* 65533affcbSRobert Mustacchi * Indicates that an operation could not complete because the kernel did 66533affcbSRobert Mustacchi * not have DMA resources available for us. 67533affcbSRobert Mustacchi */ 68533affcbSRobert Mustacchi NVME_ERR_NO_DMA_MEM, 69533affcbSRobert Mustacchi /* 70533affcbSRobert Mustacchi * Indicates that an error occurred while trying to use the devinfo 71533affcbSRobert Mustacchi * library. 72533affcbSRobert Mustacchi */ 73533affcbSRobert Mustacchi NVME_ERR_LIBDEVINFO, 74533affcbSRobert Mustacchi /* 75533affcbSRobert Mustacchi * Indicates that an internal error condition occurred. 76533affcbSRobert Mustacchi */ 77533affcbSRobert Mustacchi NVME_ERR_INTERNAL, 78533affcbSRobert Mustacchi /* 79533affcbSRobert Mustacchi * Indicates that the function was given an invalid pointer argument. 80533affcbSRobert Mustacchi */ 81533affcbSRobert Mustacchi NVME_ERR_BAD_PTR, 82533affcbSRobert Mustacchi /* 83533affcbSRobert Mustacchi * Indicates that an unknown flag argument was given to us. 84533affcbSRobert Mustacchi */ 85533affcbSRobert Mustacchi NVME_ERR_BAD_FLAG, 86533affcbSRobert Mustacchi /* 87533affcbSRobert Mustacchi * Indicates that the devinfo node we were given doesn't correspond to 88533affcbSRobert Mustacchi * an NVMe controller. 89533affcbSRobert Mustacchi */ 90533affcbSRobert Mustacchi NVME_ERR_BAD_DEVI, 91533affcbSRobert Mustacchi /* 92533affcbSRobert Mustacchi * Indicates that while we found a devinfo property successfully, 93533affcbSRobert Mustacchi * something about it does not match our expectations. This could be the 94533affcbSRobert Mustacchi * type, number of values, range, etc. 95533affcbSRobert Mustacchi */ 96533affcbSRobert Mustacchi NVME_ERR_BAD_DEVI_PROP, 97533affcbSRobert Mustacchi /* 98533affcbSRobert Mustacchi * Indicates that we were given an illegal instance (i.e. a negative 99533affcbSRobert Mustacchi * instance). 100533affcbSRobert Mustacchi */ 101533affcbSRobert Mustacchi NVME_ERR_ILLEGAL_INSTANCE, 102533affcbSRobert Mustacchi /* 103533affcbSRobert Mustacchi * Indicates that a means of identifying a controller (name, instance, 104533affcbSRobert Mustacchi * etc.) does not match any known NVMe device. 105533affcbSRobert Mustacchi */ 106533affcbSRobert Mustacchi NVME_ERR_BAD_CONTROLLER, 107533affcbSRobert Mustacchi /* 108533affcbSRobert Mustacchi * Indicates that a request could not proceed due to missing privileges. 109533affcbSRobert Mustacchi */ 110533affcbSRobert Mustacchi NVME_ERR_PRIVS, 111533affcbSRobert Mustacchi /* 112533affcbSRobert Mustacchi * Indicates a failure to open a device file. 113533affcbSRobert Mustacchi */ 114533affcbSRobert Mustacchi NVME_ERR_OPEN_DEV, 115533affcbSRobert Mustacchi /* 116533affcbSRobert Mustacchi * Indicates that the given restore data is not valid. 117533affcbSRobert Mustacchi */ 118533affcbSRobert Mustacchi NVME_ERR_BAD_RESTORE, 119533affcbSRobert Mustacchi /* 120533affcbSRobert Mustacchi * Indicates that a namespace (name, ID, etc.) passed in is not valid on 121533affcbSRobert Mustacchi * the controller. This may be because it's outside the valid range or 122533affcbSRobert Mustacchi * there was an attempt to use the broadcast namespace when it's not 123533affcbSRobert Mustacchi * supported. 124533affcbSRobert Mustacchi */ 125533affcbSRobert Mustacchi NVME_ERR_NS_RANGE, 126533affcbSRobert Mustacchi /* 127533affcbSRobert Mustacchi * Indicates that a namespace ID is not usable in this context. For 128533affcbSRobert Mustacchi * example, attempting to specify a namespace to an identify or log page 129533affcbSRobert Mustacchi * that does not support them. 130533affcbSRobert Mustacchi */ 131533affcbSRobert Mustacchi NVME_ERR_NS_UNUSE, 132533affcbSRobert Mustacchi /* 133533affcbSRobert Mustacchi * Indicates that the value for a get log page field is invalid. This 134533affcbSRobert Mustacchi * may happened due to alignment, just being too large, or something 135533affcbSRobert Mustacchi * else. 136533affcbSRobert Mustacchi */ 137533affcbSRobert Mustacchi NVME_ERR_LOG_CSI_RANGE, 138533affcbSRobert Mustacchi NVME_ERR_LOG_LID_RANGE, 139533affcbSRobert Mustacchi NVME_ERR_LOG_LSP_RANGE, 140533affcbSRobert Mustacchi NVME_ERR_LOG_LSI_RANGE, 141533affcbSRobert Mustacchi NVME_ERR_LOG_RAE_RANGE, 142533affcbSRobert Mustacchi NVME_ERR_LOG_SIZE_RANGE, 143533affcbSRobert Mustacchi NVME_ERR_LOG_OFFSET_RANGE, 144533affcbSRobert Mustacchi /* 145533affcbSRobert Mustacchi * Indicates that the log field value given is not supported because the 146533affcbSRobert Mustacchi * controller is not of a sufficient version or does not indicate that 147533affcbSRobert Mustacchi * it is supported in the LPA field. 148533affcbSRobert Mustacchi */ 149533affcbSRobert Mustacchi NVME_ERR_LOG_CSI_UNSUP, 150533affcbSRobert Mustacchi NVME_ERR_LOG_LSP_UNSUP, 151533affcbSRobert Mustacchi NVME_ERR_LOG_LSI_UNSUP, 152533affcbSRobert Mustacchi NVME_ERR_LOG_RAE_UNSUP, 153533affcbSRobert Mustacchi NVME_ERR_LOG_OFFSET_UNSUP, 154533affcbSRobert Mustacchi /* 155533affcbSRobert Mustacchi * Indicates that the log field value is unusable. The specifics of our 156533affcbSRobert Mustacchi * request indicate that this cannot be set. 157533affcbSRobert Mustacchi */ 158533affcbSRobert Mustacchi NVME_ERR_LOG_LSP_UNUSE, 159533affcbSRobert Mustacchi NVME_ERR_LOG_LSI_UNUSE, 160533affcbSRobert Mustacchi NVME_ERR_LOG_RAE_UNUSE, 161533affcbSRobert Mustacchi /* 162533affcbSRobert Mustacchi * Indicates that the log page's scope requires operating on something 163533affcbSRobert Mustacchi * that isn't what was requested. This would happen if manually 164533affcbSRobert Mustacchi * constructing a log page that operates on the controller, but passed a 165533affcbSRobert Mustacchi * namespace (e.g. the firmware log page). 166533affcbSRobert Mustacchi */ 167533affcbSRobert Mustacchi NVME_ERR_LOG_SCOPE_MISMATCH, 168533affcbSRobert Mustacchi /* 169533affcbSRobert Mustacchi * Indicates that a log request can't be executed because required 170533affcbSRobert Mustacchi * fields have not been set. 171533affcbSRobert Mustacchi */ 172533affcbSRobert Mustacchi NVME_ERR_LOG_REQ_MISSING_FIELDS, 173533affcbSRobert Mustacchi /* 174533affcbSRobert Mustacchi * Indicates that the named log is unknown to the library. 175533affcbSRobert Mustacchi */ 176533affcbSRobert Mustacchi NVME_ERR_LOG_NAME_UNKNOWN, 177533affcbSRobert Mustacchi /* 178533affcbSRobert Mustacchi * Indicates that the named log is not supported by the device. 179533affcbSRobert Mustacchi */ 180533affcbSRobert Mustacchi NVME_ERR_LOG_UNSUP_BY_DEV, 181533affcbSRobert Mustacchi /* 182533affcbSRobert Mustacchi * Indicates that the IDENTIFY command requested is unknown. 183533affcbSRobert Mustacchi */ 184533affcbSRobert Mustacchi NVME_ERR_IDENTIFY_UNKNOWN, 185533affcbSRobert Mustacchi /* 186533affcbSRobert Mustacchi * Indicates that the requested identify command is not supported by the 187533affcbSRobert Mustacchi * device. 188533affcbSRobert Mustacchi */ 189533affcbSRobert Mustacchi NVME_ERR_IDENTIFY_UNSUP_BY_DEV, 190533affcbSRobert Mustacchi /* 191533affcbSRobert Mustacchi * Indicates that the identify command parameter is outside of the valid 192533affcbSRobert Mustacchi * range for the field. 193533affcbSRobert Mustacchi */ 194533affcbSRobert Mustacchi NVME_ERR_IDENTIFY_CTRLID_RANGE, 195533affcbSRobert Mustacchi NVME_ERR_IDENTIFY_OUTPUT_RANGE, 196533affcbSRobert Mustacchi /* 197533affcbSRobert Mustacchi * Indicates that the parameter given is not supported because the 198533affcbSRobert Mustacchi * controller is not of a sufficient version or does not indicate that 199533affcbSRobert Mustacchi * it is supported. 200533affcbSRobert Mustacchi */ 201533affcbSRobert Mustacchi NVME_ERR_IDENTIFY_CTRLID_UNSUP, 202533affcbSRobert Mustacchi /* 203533affcbSRobert Mustacchi * Indicates that the parameter given is not supported in the context of 204533affcbSRobert Mustacchi * a given identify command. Namespaces are handled with the 205533affcbSRobert Mustacchi * cross-command error code. 206533affcbSRobert Mustacchi */ 207533affcbSRobert Mustacchi NVME_ERR_IDENTIFY_CTRLID_UNUSE, 208533affcbSRobert Mustacchi /* 209533affcbSRobert Mustacchi * Indicates that an identify request can't be executed because required 210533affcbSRobert Mustacchi * fields have not been set. 211533affcbSRobert Mustacchi */ 212533affcbSRobert Mustacchi NVME_ERR_IDENTIFY_REQ_MISSING_FIELDS, 213533affcbSRobert Mustacchi /* 214533affcbSRobert Mustacchi * Indicates that the controller doesn't support the NVMe standard 215533affcbSRobert Mustacchi * vendor unique command. 216533affcbSRobert Mustacchi */ 217533affcbSRobert Mustacchi NVME_ERR_VUC_UNSUP_BY_DEV, 218533affcbSRobert Mustacchi /* 219533affcbSRobert Mustacchi * Indicates that the vendor unique command parameter is outside of the 220533affcbSRobert Mustacchi * valid range for the field. 221533affcbSRobert Mustacchi */ 222533affcbSRobert Mustacchi NVME_ERR_VUC_TIMEOUT_RANGE, 223533affcbSRobert Mustacchi NVME_ERR_VUC_OPCODE_RANGE, 224533affcbSRobert Mustacchi NVME_ERR_VUC_IMPACT_RANGE, 225533affcbSRobert Mustacchi NVME_ERR_VUC_NDT_RANGE, 226533affcbSRobert Mustacchi /* 227533affcbSRobert Mustacchi * Indicates that a vendor unique command already has an input or output 228533affcbSRobert Mustacchi * buffer set and is being asked to set a separate one. 229533affcbSRobert Mustacchi */ 230533affcbSRobert Mustacchi NVME_ERR_VUC_CANNOT_RW, 231533affcbSRobert Mustacchi /* 232533affcbSRobert Mustacchi * Indicates that the vendor unique request does not have valid 233533affcbSRobert Mustacchi * execution context. This may be because the command was never executed 234533affcbSRobert Mustacchi * or the exec failed in a way such that the controller never exercised 235533affcbSRobert Mustacchi * the command. 236533affcbSRobert Mustacchi */ 237533affcbSRobert Mustacchi NVME_ERR_VUC_NO_RESULTS, 238533affcbSRobert Mustacchi /* 239533affcbSRobert Mustacchi * Indicates that the named vendor unique command is not known to the 240533affcbSRobert Mustacchi * library. 241533affcbSRobert Mustacchi */ 242533affcbSRobert Mustacchi NVME_ERR_VUC_UNKNOWN, 243533affcbSRobert Mustacchi /* 244533affcbSRobert Mustacchi * Indicates that a vendor unique command can't be executed because 245533affcbSRobert Mustacchi * required fields have not been set. 246533affcbSRobert Mustacchi */ 247533affcbSRobert Mustacchi NVME_ERR_VUC_REQ_MISSING_FIELDS, 248533affcbSRobert Mustacchi /* 249533affcbSRobert Mustacchi * Indicates that the vendor-specific library operation could not 250533affcbSRobert Mustacchi * proceed because it is not supported by the given device. 251533affcbSRobert Mustacchi */ 252533affcbSRobert Mustacchi NVME_ERR_VU_FUNC_UNSUP_BY_DEV, 253533affcbSRobert Mustacchi /* 254533affcbSRobert Mustacchi * WDC e6 dump specific invalid values 255533affcbSRobert Mustacchi */ 256533affcbSRobert Mustacchi NVME_ERR_WDC_E6_OFFSET_RANGE, 257533affcbSRobert Mustacchi /* 258533affcbSRobert Mustacchi * Indicates that the controller does not support firmware related 259533affcbSRobert Mustacchi * operations. 260533affcbSRobert Mustacchi */ 261533affcbSRobert Mustacchi NVME_ERR_FW_UNSUP_BY_DEV, 262533affcbSRobert Mustacchi /* 263533affcbSRobert Mustacchi * Indicates that the constraints of the device and what the kernel can 264533affcbSRobert Mustacchi * do make the firmware upgrade non-tenable. 265533affcbSRobert Mustacchi */ 266533affcbSRobert Mustacchi NVME_ERR_KERN_FW_IMPOS, 267533affcbSRobert Mustacchi /* 268533affcbSRobert Mustacchi * Indicates that a firmware download parameter is invalid. 269533affcbSRobert Mustacchi */ 270533affcbSRobert Mustacchi NVME_ERR_FW_LOAD_LEN_RANGE, 271533affcbSRobert Mustacchi NVME_ERR_FW_LOAD_OFFSET_RANGE, 272533affcbSRobert Mustacchi /* 273533affcbSRobert Mustacchi * Indicates that the firmware commit command parameter is outside of 274533affcbSRobert Mustacchi * the valid range for the field. 275533affcbSRobert Mustacchi */ 276533affcbSRobert Mustacchi NVME_ERR_FW_COMMIT_SLOT_RANGE, 277533affcbSRobert Mustacchi NVME_ERR_FW_COMMIT_ACTION_RANGE, 278533affcbSRobert Mustacchi /* 279533affcbSRobert Mustacchi * Indicates that a firmware commit command can't be executed because 280533affcbSRobert Mustacchi * required fields have not been set. 281533affcbSRobert Mustacchi */ 282533affcbSRobert Mustacchi NVME_ERR_FW_COMMIT_REQ_MISSING_FIELDS, 283533affcbSRobert Mustacchi /* 284533affcbSRobert Mustacchi * Indicates that the firmware commit could not occur because the 285533affcbSRobert Mustacchi * requested slot is read-only. 286533affcbSRobert Mustacchi */ 287533affcbSRobert Mustacchi NVME_ERR_FW_SLOT_RO, 288533affcbSRobert Mustacchi /* 289533affcbSRobert Mustacchi * Indicates that the controller does not support NVM format operations. 290533affcbSRobert Mustacchi */ 291533affcbSRobert Mustacchi NVME_ERR_FORMAT_UNSUP_BY_DEV, 292533affcbSRobert Mustacchi /* 293533affcbSRobert Mustacchi * Indicates that the controller does not support cryptographic secure 294533affcbSRobert Mustacchi * erase. 295533affcbSRobert Mustacchi */ 296533affcbSRobert Mustacchi NVME_ERR_CRYPTO_SE_UNSUP_BY_DEV, 297533affcbSRobert Mustacchi /* 298533affcbSRobert Mustacchi * Indicates that the NVM format command cannot be executed because it 299533affcbSRobert Mustacchi * would target a specific namespace; however, the device does not allow 300533affcbSRobert Mustacchi * a secure erase or a format to target an individual namespace. 301533affcbSRobert Mustacchi */ 302533affcbSRobert Mustacchi NVME_ERR_NS_FORMAT_UNSUP_BY_DEV, 303533affcbSRobert Mustacchi /* 304533affcbSRobert Mustacchi * Indicates that the kernel does not support formatting with the 305533affcbSRobert Mustacchi * specified LBA format, generally due to something like the use of 306533affcbSRobert Mustacchi * metadata in the namespace. 307533affcbSRobert Mustacchi */ 308533affcbSRobert Mustacchi NVME_ERR_KERN_FORMAT_UNSUP, 309533affcbSRobert Mustacchi /* 310533affcbSRobert Mustacchi * Indicates that the NVM format command parameter is outside of 311533affcbSRobert Mustacchi * the valid range for the field. 312533affcbSRobert Mustacchi */ 313533affcbSRobert Mustacchi NVME_ERR_FORMAT_LBAF_RANGE, 314533affcbSRobert Mustacchi NVME_ERR_FORMAT_SES_RANGE, 315533affcbSRobert Mustacchi /* 316533affcbSRobert Mustacchi * Indicates that the parameter and/or its value is not supported for a 317533affcbSRobert Mustacchi * NVM format command. 318533affcbSRobert Mustacchi */ 319533affcbSRobert Mustacchi NVME_ERR_FORMAT_PARAM_UNSUP, 320533affcbSRobert Mustacchi /* 321533affcbSRobert Mustacchi * Indicates that a NVM format command can't be executed because 322533affcbSRobert Mustacchi * required fields have not been set. 323533affcbSRobert Mustacchi */ 324533affcbSRobert Mustacchi NVME_ERR_FORMAT_REQ_MISSING_FIELDS, 325533affcbSRobert Mustacchi /* 326533affcbSRobert Mustacchi * Indicates that the WDC e6 log dump request could not be executed due 327533affcbSRobert Mustacchi * to fields not being set. 328533affcbSRobert Mustacchi */ 329533affcbSRobert Mustacchi NVME_ERR_WDC_E6_REQ_MISSING_FIELDS, 330533affcbSRobert Mustacchi /* 331533affcbSRobert Mustacchi * Indicates that the named feature is unknown to the library. 332533affcbSRobert Mustacchi */ 333533affcbSRobert Mustacchi NVME_ERR_FEAT_NAME_UNKNOWN, 334533affcbSRobert Mustacchi /* 335533affcbSRobert Mustacchi * Indicates that the named feature is not supported by the device. 336533affcbSRobert Mustacchi */ 337533affcbSRobert Mustacchi NVME_ERR_FEAT_UNSUP_BY_DEV, 338533affcbSRobert Mustacchi /* 339533affcbSRobert Mustacchi * Indicates that the feature parameter is outside of the valid range 340533affcbSRobert Mustacchi * for the field. 341533affcbSRobert Mustacchi */ 342533affcbSRobert Mustacchi NVME_ERR_FEAT_FID_RANGE, 343533affcbSRobert Mustacchi NVME_ERR_FEAT_SEL_RANGE, 344533affcbSRobert Mustacchi NVME_ERR_FEAT_CDW11_RANGE, 345533affcbSRobert Mustacchi NVME_ERR_FEAT_DATA_RANGE, 346533affcbSRobert Mustacchi /* 347533affcbSRobert Mustacchi * Indicates that the feature parameter given is not supported because 348533affcbSRobert Mustacchi * the controller is not of a sufficient version. 349533affcbSRobert Mustacchi */ 350533affcbSRobert Mustacchi NVME_ERR_FEAT_SEL_UNSUP, 351533affcbSRobert Mustacchi /* 352533affcbSRobert Mustacchi * Indicates that the get feature parameter given is not supported for 353533affcbSRobert Mustacchi * the given feature. For example, passing in a cdw11 argument that is 354533affcbSRobert Mustacchi * not needed. 355533affcbSRobert Mustacchi */ 356533affcbSRobert Mustacchi NVME_ERR_FEAT_CDW11_UNUSE, 357533affcbSRobert Mustacchi NVME_ERR_FEAT_DATA_UNUSE, 358533affcbSRobert Mustacchi /* 359533affcbSRobert Mustacchi * Indicates that a feature request does not have valid output data. 360533affcbSRobert Mustacchi * This may be because the command was never executed or it did not 361533affcbSRobert Mustacchi * execute successfully. 362533affcbSRobert Mustacchi */ 363533affcbSRobert Mustacchi NVME_ERR_FEAT_NO_RESULTS, 364533affcbSRobert Mustacchi /* 365533affcbSRobert Mustacchi * Indicates that a get features request can't be executed because 366533affcbSRobert Mustacchi * required fields have not been set. 367533affcbSRobert Mustacchi */ 368533affcbSRobert Mustacchi NVME_ERR_GET_FEAT_REQ_MISSING_FIELDS, 369533affcbSRobert Mustacchi /* 370533affcbSRobert Mustacchi * These indicate that the operation could not be executed because they 371533affcbSRobert Mustacchi * require holding either a controller or namespace write lock and one 372533affcbSRobert Mustacchi * is not held by the corresponding controller handle. 373533affcbSRobert Mustacchi */ 374533affcbSRobert Mustacchi NVME_ERR_NEED_CTRL_WRLOCK, 375533affcbSRobert Mustacchi NVME_ERR_NEED_NS_WRLOCK, 376533affcbSRobert Mustacchi /* 377533affcbSRobert Mustacchi * These indicate that the operation could not be executed because the 378533affcbSRobert Mustacchi * controller or namespace respectively currently have an exclusive 379533affcbSRobert Mustacchi * write lock (or an equivalent future form) that blocks execution from 380533affcbSRobert Mustacchi * others. 381533affcbSRobert Mustacchi */ 382533affcbSRobert Mustacchi NVME_ERR_CTRL_LOCKED, 383533affcbSRobert Mustacchi NVME_ERR_NS_LOCKED, 384533affcbSRobert Mustacchi /* 385533affcbSRobert Mustacchi * Indicates that a fatal locking operation occurred that will terminate 386533affcbSRobert Mustacchi * the process. This includes cases such as recursive enters on the same 387533affcbSRobert Mustacchi * lock, attempting to unlock a lock that isn't owned, etc. 388533affcbSRobert Mustacchi */ 389533affcbSRobert Mustacchi NVME_ERR_LOCK_PROG, 390533affcbSRobert Mustacchi /* 391533affcbSRobert Mustacchi * Indicates that a lock order violation was attempted. This includes 392533affcbSRobert Mustacchi * things like taking the controller lock while holding the namespace 393533affcbSRobert Mustacchi * lock, attempting to take a second namespace lock, holding a 394533affcbSRobert Mustacchi * controller write lock and trying to get a namespace lock, etc. 395533affcbSRobert Mustacchi */ 396533affcbSRobert Mustacchi NVME_ERR_LOCK_ORDER, 397533affcbSRobert Mustacchi /* 398533affcbSRobert Mustacchi * Indicates that a signal was encountered while attempting to take a 399533affcbSRobert Mustacchi * lock. 400533affcbSRobert Mustacchi */ 401533affcbSRobert Mustacchi NVME_ERR_LOCK_WAIT_INTR, 402533affcbSRobert Mustacchi /* 403533affcbSRobert Mustacchi * Indicates that attempting to take the lock failed because the thread 404533affcbSRobert Mustacchi * would be required to block, but it asked not to. 405533affcbSRobert Mustacchi */ 406533affcbSRobert Mustacchi NVME_ERR_LOCK_WOULD_BLOCK, 407533affcbSRobert Mustacchi /* 408533affcbSRobert Mustacchi * These indicate that the respective attach and detach operations 409533affcbSRobert Mustacchi * failed to complete due to an error in the underlying kernel 410533affcbSRobert Mustacchi * subsystems. For detach this might happen because of a disk being 411533affcbSRobert Mustacchi * open, busy in a zpool, or something else. For attach, it may suggest 412533affcbSRobert Mustacchi * and NDI or other issue. 413533affcbSRobert Mustacchi */ 414533affcbSRobert Mustacchi NVME_ERR_DETACH_KERN, 415533affcbSRobert Mustacchi NVME_ERR_ATTACH_KERN, 416533affcbSRobert Mustacchi /* 417533affcbSRobert Mustacchi * Indicates that the kernel driver does not support some property of 418533affcbSRobert Mustacchi * the requested namespace. 419533affcbSRobert Mustacchi */ 420533affcbSRobert Mustacchi NVME_ERR_ATTACH_UNSUP_KERN, 421533affcbSRobert Mustacchi /* 422533affcbSRobert Mustacchi * Indicates that the operation cannot proceed because a namespace is 423533affcbSRobert Mustacchi * attached to blkdev and it must be detached to proceed. 424533affcbSRobert Mustacchi */ 425533affcbSRobert Mustacchi NVME_ERR_NS_BLKDEV_ATTACH, 426533affcbSRobert Mustacchi /* 427533affcbSRobert Mustacchi * Indicates that non-DMA kernel memory was not available for this 428533affcbSRobert Mustacchi * request. 429533affcbSRobert Mustacchi */ 430533affcbSRobert Mustacchi NVME_ERR_NO_KERN_MEM, 431533affcbSRobert Mustacchi /* 432533affcbSRobert Mustacchi * These two codes represent internal device conditions that indicate 433533affcbSRobert Mustacchi * the device is unusable or that it was physically removed (usually due 434533affcbSRobert Mustacchi * to hotplug). 435533affcbSRobert Mustacchi */ 436533affcbSRobert Mustacchi NVME_ERR_CTRL_DEAD, 437533affcbSRobert Mustacchi NVME_ERR_CTRL_GONE 438533affcbSRobert Mustacchi } nvme_err_t; 439533affcbSRobert Mustacchi 440533affcbSRobert Mustacchi /* 441533affcbSRobert Mustacchi * Errors used for the various information errors. This is shared between both 442533affcbSRobert Mustacchi * controller and namespace information structures. 443533affcbSRobert Mustacchi */ 444533affcbSRobert Mustacchi typedef enum { 445533affcbSRobert Mustacchi NVME_INFO_ERR_OK, 446533affcbSRobert Mustacchi /* 447533affcbSRobert Mustacchi * Indicates that the item is not supported because this is the wrong 448533affcbSRobert Mustacchi * controller transport. For example, asking about a PCI ID for 449533affcbSRobert Mustacchi * something that is not PCI-based. 450533affcbSRobert Mustacchi */ 451533affcbSRobert Mustacchi NVME_INFO_ERR_TRANSPORT, 452533affcbSRobert Mustacchi /* 453533affcbSRobert Mustacchi * Indicates that the item is not supported because the device version 454533affcbSRobert Mustacchi * is too old to get this. 455533affcbSRobert Mustacchi */ 456533affcbSRobert Mustacchi NVME_INFO_ERR_VERSION, 457533affcbSRobert Mustacchi /* 458533affcbSRobert Mustacchi * Indicates that we could not get certain information because the 459533affcbSRobert Mustacchi * device does not support a given capability. 460533affcbSRobert Mustacchi */ 461533affcbSRobert Mustacchi NVME_INFO_ERR_MISSING_CAP, 462533affcbSRobert Mustacchi /* 463533affcbSRobert Mustacchi * Indicates that the specified format value is unknown. 464533affcbSRobert Mustacchi */ 465533affcbSRobert Mustacchi NVME_INFO_ERR_BAD_LBA_FMT, 466533affcbSRobert Mustacchi /* 467533affcbSRobert Mustacchi * These errors only occur during attempts to persist information and 468533affcbSRobert Mustacchi * indicate challenges allocating memory or otherwise challenges with 469533affcbSRobert Mustacchi * libnvpair. 470533affcbSRobert Mustacchi */ 471533affcbSRobert Mustacchi NVME_INFO_ERR_PERSIST_NVL, 472533affcbSRobert Mustacchi /* 473533affcbSRobert Mustacchi * The first indicates that the index is invalid or if it is technically 474533affcbSRobert Mustacchi * within the valid LBA format range, but there is no data size. The 475533affcbSRobert Mustacchi * second indicates that we can't actually fully represent the data 476533affcbSRobert Mustacchi * here. This happens because say the LBA size can't be represented by a 477533affcbSRobert Mustacchi * uint64_t. 478533affcbSRobert Mustacchi */ 479533affcbSRobert Mustacchi NVME_INFO_ERR_BAD_FMT, 480533affcbSRobert Mustacchi NVME_INFO_ERR_BAD_FMT_DATA, 481533affcbSRobert Mustacchi /* 482533affcbSRobert Mustacchi * Indicates that the information cannot be returned because the 483533affcbSRobert Mustacchi * namespace's state does not allow us to answer this question. This may 484533affcbSRobert Mustacchi * be because it's inactive as below or because blkdev is not attached. 485533affcbSRobert Mustacchi */ 486533affcbSRobert Mustacchi NVME_INFO_ERR_NS_INACTIVE, 487533affcbSRobert Mustacchi NVME_INFO_ERR_NS_NO_BLKDEV 488533affcbSRobert Mustacchi } nvme_info_err_t; 489533affcbSRobert Mustacchi 490533affcbSRobert Mustacchi typedef struct nvme nvme_t; 491533affcbSRobert Mustacchi typedef struct nvme_ctrl nvme_ctrl_t; 492533affcbSRobert Mustacchi typedef struct nvme_ctrl_iter nvme_ctrl_iter_t; 493533affcbSRobert Mustacchi typedef struct nvme_ctrl_disc nvme_ctrl_disc_t; 494533affcbSRobert Mustacchi typedef struct nvme_ctrl_info nvme_ctrl_info_t; 495533affcbSRobert Mustacchi typedef struct nvme_ns nvme_ns_t; 496533affcbSRobert Mustacchi typedef struct nvme_ns_iter nvme_ns_iter_t; 497533affcbSRobert Mustacchi typedef struct nvme_ns_disc nvme_ns_disc_t; 498533affcbSRobert Mustacchi typedef struct nvme_ns_info nvme_ns_info_t; 499533affcbSRobert Mustacchi typedef struct nvme_nvm_lba_fmt nvme_nvm_lba_fmt_t; 500533affcbSRobert Mustacchi typedef struct nvme_log_iter nvme_log_iter_t; 501533affcbSRobert Mustacchi typedef struct nvme_log_disc nvme_log_disc_t; 502533affcbSRobert Mustacchi typedef struct nvme_log_req nvme_log_req_t; 503533affcbSRobert Mustacchi typedef struct nvme_id_req nvme_id_req_t; 504533affcbSRobert Mustacchi typedef struct nvme_vuc_iter nvme_vuc_iter_t; 505533affcbSRobert Mustacchi typedef struct nvme_vuc_disc nvme_vuc_disc_t; 506533affcbSRobert Mustacchi typedef struct nvme_vuc_req nvme_vuc_req_t; 507533affcbSRobert Mustacchi typedef struct nvme_fw_commit_req nvme_fw_commit_req_t; 508533affcbSRobert Mustacchi typedef struct nvme_format_req nvme_format_req_t; 509533affcbSRobert Mustacchi typedef struct nvme_feat_disc nvme_feat_disc_t; 510533affcbSRobert Mustacchi typedef struct nvme_feat_iter nvme_feat_iter_t; 511533affcbSRobert Mustacchi typedef struct nvme_get_feat_req nvme_get_feat_req_t; 512533affcbSRobert Mustacchi 513533affcbSRobert Mustacchi /* 514533affcbSRobert Mustacchi * Vendor-specific forwards. 515533affcbSRobert Mustacchi */ 516533affcbSRobert Mustacchi typedef struct nvme_wdc_e6_req nvme_wdc_e6_req_t; 517533affcbSRobert Mustacchi 518533affcbSRobert Mustacchi extern nvme_t *nvme_init(void); 519533affcbSRobert Mustacchi extern void nvme_fini(nvme_t *); 520533affcbSRobert Mustacchi 521533affcbSRobert Mustacchi /* 522533affcbSRobert Mustacchi * Error information. Operations that take an nvme_t, always set error 523533affcbSRobert Mustacchi * information on the nvme_t. Operations that operate on a controller or are 524533affcbSRobert Mustacchi * related to a request object or iterator that starts from the controller 525533affcbSRobert Mustacchi * set error information on the nvme_ctrl_t. 526533affcbSRobert Mustacchi */ 527533affcbSRobert Mustacchi extern nvme_err_t nvme_err(nvme_t *); 528533affcbSRobert Mustacchi extern int32_t nvme_syserr(nvme_t *); 529533affcbSRobert Mustacchi extern const char *nvme_errmsg(nvme_t *); 530533affcbSRobert Mustacchi extern size_t nvme_errlen(nvme_t *); 531533affcbSRobert Mustacchi extern const char *nvme_errtostr(nvme_t *, nvme_err_t); 532533affcbSRobert Mustacchi 533533affcbSRobert Mustacchi extern nvme_err_t nvme_ctrl_err(nvme_ctrl_t *); 534533affcbSRobert Mustacchi extern int32_t nvme_ctrl_syserr(nvme_ctrl_t *); 535533affcbSRobert Mustacchi extern const char *nvme_ctrl_errmsg(nvme_ctrl_t *); 536533affcbSRobert Mustacchi extern size_t nvme_ctrl_errlen(nvme_ctrl_t *); 537533affcbSRobert Mustacchi extern void nvme_ctrl_deverr(nvme_ctrl_t *, uint32_t *, uint32_t *); 538533affcbSRobert Mustacchi extern const char *nvme_ctrl_errtostr(nvme_ctrl_t *, nvme_err_t); 539533affcbSRobert Mustacchi 540533affcbSRobert Mustacchi /* 541533affcbSRobert Mustacchi * Translations for NVMe spec error constants. These end up taking the 542533affcbSRobert Mustacchi * nvme_ctrl_t so that way they can potentially translate vendor-specific errors 543533affcbSRobert Mustacchi * if they are defined. A NULL controller is allowed, which will skip all such 544533affcbSRobert Mustacchi * processing altogether. Both functions will always a return a string so there 545533affcbSRobert Mustacchi * is no need to check for NULL (though it may just be a variant of "unknown 546533affcbSRobert Mustacchi * ..."). 547533affcbSRobert Mustacchi * 548533affcbSRobert Mustacchi * If NULL is passed for the controller in nvme_sctostr(), we will assume that 549533affcbSRobert Mustacchi * the controller's type is a traditional PCI I/O controller and not a fabric 550533affcbSRobert Mustacchi * based controller, which further changes the way that command-specific status 551533affcbSRobert Mustacchi * codes are interpreted. Due to the lack of support in the system for 552533affcbSRobert Mustacchi * different controller types, this function will always assume a PCI I/O 553533affcbSRobert Mustacchi * controller currently. 554533affcbSRobert Mustacchi */ 555533affcbSRobert Mustacchi extern const char *nvme_scttostr(nvme_ctrl_t *, uint32_t); 556533affcbSRobert Mustacchi extern const char *nvme_sctostr(nvme_ctrl_t *, nvme_csi_t, uint32_t, uint32_t); 557533affcbSRobert Mustacchi 558533affcbSRobert Mustacchi typedef enum nvme_iter { 559533affcbSRobert Mustacchi NVME_ITER_VALID, 560533affcbSRobert Mustacchi NVME_ITER_DONE, 561533affcbSRobert Mustacchi NVME_ITER_ERROR 562533affcbSRobert Mustacchi } nvme_iter_t; 563533affcbSRobert Mustacchi 564533affcbSRobert Mustacchi /* 565533affcbSRobert Mustacchi * NVMe Controller discovery. 566533affcbSRobert Mustacchi */ 567533affcbSRobert Mustacchi extern di_node_t nvme_ctrl_disc_devi(const nvme_ctrl_disc_t *); 568533affcbSRobert Mustacchi extern di_minor_t nvme_ctrl_disc_minor(const nvme_ctrl_disc_t *); 569533affcbSRobert Mustacchi 570533affcbSRobert Mustacchi extern bool nvme_ctrl_discover_init(nvme_t *, nvme_ctrl_iter_t **); 571533affcbSRobert Mustacchi extern nvme_iter_t nvme_ctrl_discover_step(nvme_ctrl_iter_t *, 572533affcbSRobert Mustacchi const nvme_ctrl_disc_t **); 573533affcbSRobert Mustacchi extern void nvme_ctrl_discover_fini(nvme_ctrl_iter_t *); 574533affcbSRobert Mustacchi 575533affcbSRobert Mustacchi typedef bool (*nvme_ctrl_disc_f)(nvme_t *, const nvme_ctrl_disc_t *, void *); 576533affcbSRobert Mustacchi extern bool nvme_ctrl_discover(nvme_t *, nvme_ctrl_disc_f, void *); 577533affcbSRobert Mustacchi 578533affcbSRobert Mustacchi extern bool nvme_ctrl_init(nvme_t *, di_node_t, nvme_ctrl_t **); 579533affcbSRobert Mustacchi extern bool nvme_ctrl_init_by_instance(nvme_t *, int32_t, nvme_ctrl_t **); 580533affcbSRobert Mustacchi extern bool nvme_ctrl_devi(nvme_ctrl_t *, di_node_t *); 581533affcbSRobert Mustacchi extern void nvme_ctrl_fini(nvme_ctrl_t *); 582533affcbSRobert Mustacchi 583533affcbSRobert Mustacchi /* 584533affcbSRobert Mustacchi * Get information about a controller. This information about a controller is 585533affcbSRobert Mustacchi * separate from the lifetime of the controller itself. This is done to 586533affcbSRobert Mustacchi * facilitate the ability of saving and using this information on another 587533affcbSRobert Mustacchi * system and make the management a bit easier. Errors appear on this object and 588533affcbSRobert Mustacchi * not the nmve_t. 589533affcbSRobert Mustacchi */ 590533affcbSRobert Mustacchi extern bool nvme_ctrl_info_snap(nvme_ctrl_t *, nvme_ctrl_info_t **); 591533affcbSRobert Mustacchi extern bool nvme_ctrl_info_restore(nvme_t *, nvlist_t *, nvme_ctrl_info_t **); 592533affcbSRobert Mustacchi extern bool nvme_ctrl_info_persist(nvme_ctrl_info_t *, nvlist_t **); 593533affcbSRobert Mustacchi extern void nvme_ctrl_info_free(nvme_ctrl_info_t *); 594533affcbSRobert Mustacchi 595533affcbSRobert Mustacchi extern nvme_info_err_t nvme_ctrl_info_err(nvme_ctrl_info_t *); 596533affcbSRobert Mustacchi extern int32_t nvme_ctrl_info_syserr(nvme_ctrl_info_t *); 597533affcbSRobert Mustacchi extern const char *nvme_ctrl_info_errmsg(nvme_ctrl_info_t *); 598533affcbSRobert Mustacchi extern size_t nvme_ctrl_info_errlen(nvme_ctrl_info_t *); 599533affcbSRobert Mustacchi extern const char *nvme_ctrl_info_errtostr(nvme_ctrl_info_t *, nvme_info_err_t); 600533affcbSRobert Mustacchi 601533affcbSRobert Mustacchi /* 602533affcbSRobert Mustacchi * Information about an NVMe controller. This information is a combination of 603533affcbSRobert Mustacchi * the identify data structure which can be retrieved directly by folks who 604533affcbSRobert Mustacchi * would prefer to use it. Common fields that are used in something like nvmeadm 605533affcbSRobert Mustacchi * or other utilities who would rather not need to know about the specifics of 606533affcbSRobert Mustacchi * the data structure or have to think about the version can use that instead. 607533affcbSRobert Mustacchi * 608533affcbSRobert Mustacchi * NVMe 2.x has kept the identify controller data structure backwards 609533affcbSRobert Mustacchi * compatible. If a future version were to invalidate that, then this could 610533affcbSRobert Mustacchi * possibly return NULL. 611533affcbSRobert Mustacchi */ 612533affcbSRobert Mustacchi extern uint16_t nvme_ctrl_info_vendor(nvme_ctrl_info_t *); 613533affcbSRobert Mustacchi extern const nvme_identify_ctrl_t *nvme_ctrl_info_identify(nvme_ctrl_info_t *); 614533affcbSRobert Mustacchi extern const nvme_version_t *nvme_ctrl_info_version(nvme_ctrl_info_t *); 615533affcbSRobert Mustacchi extern const char *nvme_ctrl_info_model(nvme_ctrl_info_t *); 616533affcbSRobert Mustacchi extern const char *nvme_ctrl_info_serial(nvme_ctrl_info_t *); 6173dd3cd66SAndy Fiddaman extern uint32_t nvme_ctrl_info_fwgran(nvme_ctrl_info_t *); 618533affcbSRobert Mustacchi extern const char *nvme_ctrl_info_fwrev(nvme_ctrl_info_t *); 619533affcbSRobert Mustacchi extern uint32_t nvme_ctrl_info_nns(nvme_ctrl_info_t *); 620533affcbSRobert Mustacchi 621533affcbSRobert Mustacchi typedef enum { 622533affcbSRobert Mustacchi NVME_CTRL_TRANSPORT_PCI, 623533affcbSRobert Mustacchi NVME_CTRL_TRANSPORT_TCP, 624533affcbSRobert Mustacchi NVME_CTRL_TRANSPORT_RDMA, 625533affcbSRobert Mustacchi } nvme_ctrl_transport_t; 626533affcbSRobert Mustacchi 627533affcbSRobert Mustacchi typedef enum { 628533affcbSRobert Mustacchi NVME_CTRL_TYPE_UNKNOWN, 629533affcbSRobert Mustacchi NVME_CTRL_TYPE_IO, 630533affcbSRobert Mustacchi NVME_CTRL_TYPE_ADMIN, 631533affcbSRobert Mustacchi NVME_CTRL_TYPE_DISCOVERY, 632533affcbSRobert Mustacchi } nvme_ctrl_type_t; 633533affcbSRobert Mustacchi 634533affcbSRobert Mustacchi /* 635533affcbSRobert Mustacchi * Controller types were explicitly added in the NVMe 1.4 specification. Prior 636533affcbSRobert Mustacchi * to that all controllers were required to support issuing I/O, hence we return 637533affcbSRobert Mustacchi * them as NVME_CTRL_TYPE_IO, even though this isn't quite by the spec. In 1.4 638533affcbSRobert Mustacchi * this was added to the identify controller information. The 'UNKNOWN' type is 639533affcbSRobert Mustacchi * for cases where we don't recognize the value based upon the standard. 640533affcbSRobert Mustacchi */ 641533affcbSRobert Mustacchi extern nvme_ctrl_type_t nvme_ctrl_info_type(nvme_ctrl_info_t *); 642533affcbSRobert Mustacchi extern nvme_ctrl_transport_t nvme_ctrl_info_transport(nvme_ctrl_info_t *); 643533affcbSRobert Mustacchi 644533affcbSRobert Mustacchi /* 645533affcbSRobert Mustacchi * The following pieces of information are specific to PCI NVMe controllers and 646533affcbSRobert Mustacchi * are not from the common identify controller data structure. As such they are 647533affcbSRobert Mustacchi * fallible. The first group come from configuration space while the others are 648533affcbSRobert Mustacchi * information that comes from the actual controller capability registers. 649533affcbSRobert Mustacchi */ 650533affcbSRobert Mustacchi extern bool nvme_ctrl_info_pci_vid(nvme_ctrl_info_t *, uint16_t *); 651533affcbSRobert Mustacchi extern bool nvme_ctrl_info_pci_did(nvme_ctrl_info_t *, uint16_t *); 652533affcbSRobert Mustacchi extern bool nvme_ctrl_info_pci_rev(nvme_ctrl_info_t *, uint8_t *); 653533affcbSRobert Mustacchi extern bool nvme_ctrl_info_pci_subvid(nvme_ctrl_info_t *, uint16_t *); 654533affcbSRobert Mustacchi extern bool nvme_ctrl_info_pci_subsys(nvme_ctrl_info_t *, uint16_t *); 655533affcbSRobert Mustacchi 656533affcbSRobert Mustacchi extern bool nvme_ctrl_info_pci_mps_min(nvme_ctrl_info_t *, uint32_t *); 657533affcbSRobert Mustacchi extern bool nvme_ctrl_info_pci_mps_max(nvme_ctrl_info_t *, uint32_t *); 658533affcbSRobert Mustacchi 659533affcbSRobert Mustacchi extern bool nvme_ctrl_info_pci_nintrs(nvme_ctrl_info_t *, uint32_t *); 660533affcbSRobert Mustacchi 661533affcbSRobert Mustacchi /* 662533affcbSRobert Mustacchi * These three items are only present if the device supports Namespace 663533affcbSRobert Mustacchi * Management. 664533affcbSRobert Mustacchi */ 665533affcbSRobert Mustacchi extern bool nvme_ctrl_info_cap(nvme_ctrl_info_t *, nvme_uint128_t *); 666533affcbSRobert Mustacchi extern bool nvme_ctrl_info_unalloc_cap(nvme_ctrl_info_t *, nvme_uint128_t *); 667533affcbSRobert Mustacchi extern bool nvme_ctrl_info_common_ns(nvme_ctrl_info_t *, 668533affcbSRobert Mustacchi const nvme_identify_nsid_t **); 669533affcbSRobert Mustacchi 670533affcbSRobert Mustacchi /* 671533affcbSRobert Mustacchi * The following information is specific to the NVM command set for controllers. 672533affcbSRobert Mustacchi */ 673533affcbSRobert Mustacchi extern uint32_t nvme_ctrl_info_nformats(nvme_ctrl_info_t *); 674533affcbSRobert Mustacchi extern bool nvme_ctrl_info_format(nvme_ctrl_info_t *, uint32_t, 675533affcbSRobert Mustacchi const nvme_nvm_lba_fmt_t **); 676533affcbSRobert Mustacchi extern uint32_t nvme_nvm_lba_fmt_id(const nvme_nvm_lba_fmt_t *); 677533affcbSRobert Mustacchi extern uint32_t nvme_nvm_lba_fmt_meta_size(const nvme_nvm_lba_fmt_t *); 678533affcbSRobert Mustacchi extern uint64_t nvme_nvm_lba_fmt_data_size(const nvme_nvm_lba_fmt_t *); 679533affcbSRobert Mustacchi extern uint32_t nvme_nvm_lba_fmt_rel_perf(const nvme_nvm_lba_fmt_t *); 680533affcbSRobert Mustacchi 681533affcbSRobert Mustacchi /* 682533affcbSRobert Mustacchi * Identify Operations 683533affcbSRobert Mustacchi * 684533affcbSRobert Mustacchi * The basic controller and namespace identify operations are a part of the 685533affcbSRobert Mustacchi * controller and namespace snapshot facilities. These functions are designed to 686533affcbSRobert Mustacchi * help enumerate and iterate lists of active and inactive namespaces, 687533affcbSRobert Mustacchi * controllers, and related. The initial interface is a basic form that allows 688533affcbSRobert Mustacchi * folks to create a request based on one that the library knows about as the 689533affcbSRobert Mustacchi * kernel doesn't allow unknown requests. 690533affcbSRobert Mustacchi * 691533affcbSRobert Mustacchi * Eventually, when the kernel allows for arbitrary identify commands to be 692533affcbSRobert Mustacchi * issued we can add an nvme_id_req_init() and the ability to set the CSI and 693533affcbSRobert Mustacchi * CNS. 694533affcbSRobert Mustacchi */ 695533affcbSRobert Mustacchi extern bool nvme_id_req_init_by_cns(nvme_ctrl_t *, nvme_csi_t, uint32_t, 696533affcbSRobert Mustacchi nvme_id_req_t **); 697533affcbSRobert Mustacchi extern void nvme_id_req_fini(nvme_id_req_t *); 698533affcbSRobert Mustacchi 699533affcbSRobert Mustacchi extern bool nvme_id_req_set_nsid(nvme_id_req_t *, uint32_t); 700533affcbSRobert Mustacchi extern bool nvme_id_req_set_ctrlid(nvme_id_req_t *, uint32_t); 701533affcbSRobert Mustacchi extern bool nvme_id_req_set_output(nvme_id_req_t *, void *, size_t); 702*1c02c6c8SRobert Mustacchi extern bool nvme_id_req_clear_output(nvme_id_req_t *); 703533affcbSRobert Mustacchi extern bool nvme_id_req_exec(nvme_id_req_t *); 704533affcbSRobert Mustacchi 705533affcbSRobert Mustacchi /* 706533affcbSRobert Mustacchi * NVMe Namespace Discovery 707533affcbSRobert Mustacchi * 708533affcbSRobert Mustacchi * Namespaces come in various states. While the controller has a list of 709533affcbSRobert Mustacchi * namespace IDs. The following enumeration describes namespace information with 710533affcbSRobert Mustacchi * increasing specificity. 711533affcbSRobert Mustacchi */ 712533affcbSRobert Mustacchi typedef enum { 713533affcbSRobert Mustacchi /* 714533affcbSRobert Mustacchi * This returns all namespaces that are present on the device. This 715533affcbSRobert Mustacchi * includes ones that may be ignored by the kernel or more. 716533affcbSRobert Mustacchi */ 717533affcbSRobert Mustacchi NVME_NS_DISC_F_ALL = 0, 718533affcbSRobert Mustacchi /* 719533affcbSRobert Mustacchi * Only return namespaces that the controller considers to be allocated. 720533affcbSRobert Mustacchi */ 721533affcbSRobert Mustacchi NVME_NS_DISC_F_ALLOCATED, 722533affcbSRobert Mustacchi /* 723533affcbSRobert Mustacchi * Only return namespaces that are active. If the controller does not 724533affcbSRobert Mustacchi * support namespace management then all namespaces are considered 725533affcbSRobert Mustacchi * active. 726533affcbSRobert Mustacchi */ 727533affcbSRobert Mustacchi NVME_NS_DISC_F_ACTIVE, 728533affcbSRobert Mustacchi /* 729533affcbSRobert Mustacchi * The kernel has a notion of a namespace is ignored or not. In general, 730533affcbSRobert Mustacchi * this is a subset of active namespaces that can actually be supported. 731533affcbSRobert Mustacchi * They may or may not have a blkdev instance attached. 732533affcbSRobert Mustacchi */ 733533affcbSRobert Mustacchi NVME_NS_DISC_F_NOT_IGNORED, 734533affcbSRobert Mustacchi /* 735533affcbSRobert Mustacchi * Only return namespaces that have blkdev actively attached. In other 736533affcbSRobert Mustacchi * words these are disks that the OS can use. 737533affcbSRobert Mustacchi */ 738533affcbSRobert Mustacchi NVME_NS_DISC_F_BLKDEV 739533affcbSRobert Mustacchi } nvme_ns_disc_level_t; 740533affcbSRobert Mustacchi 741533affcbSRobert Mustacchi typedef enum nvme_ns_disc_flags { 742533affcbSRobert Mustacchi NVME_NS_DISC_F_EUI64_VALID = 1 << 0, 743533affcbSRobert Mustacchi NVME_NS_DISC_F_NGUID_VALID = 1 << 1 744533affcbSRobert Mustacchi } nvme_ns_disc_flags_t; 745533affcbSRobert Mustacchi 746533affcbSRobert Mustacchi extern uint32_t nvme_ns_disc_nsid(const nvme_ns_disc_t *); 747533affcbSRobert Mustacchi extern nvme_ns_disc_level_t nvme_ns_disc_level(const nvme_ns_disc_t *); 748533affcbSRobert Mustacchi extern nvme_ns_disc_flags_t nvme_ns_disc_flags(const nvme_ns_disc_t *); 749533affcbSRobert Mustacchi extern const uint8_t *nvme_ns_disc_eui64(const nvme_ns_disc_t *); 750533affcbSRobert Mustacchi extern const uint8_t *nvme_ns_disc_nguid(const nvme_ns_disc_t *); 751533affcbSRobert Mustacchi 752533affcbSRobert Mustacchi extern bool nvme_ns_discover_init(nvme_ctrl_t *, nvme_ns_disc_level_t, 753533affcbSRobert Mustacchi nvme_ns_iter_t **); 754533affcbSRobert Mustacchi extern nvme_iter_t nvme_ns_discover_step(nvme_ns_iter_t *, 755533affcbSRobert Mustacchi const nvme_ns_disc_t **); 756533affcbSRobert Mustacchi extern void nvme_ns_discover_fini(nvme_ns_iter_t *); 757533affcbSRobert Mustacchi 758533affcbSRobert Mustacchi typedef bool (*nvme_ns_disc_f)(nvme_ctrl_t *, const nvme_ns_disc_t *, void *); 759533affcbSRobert Mustacchi extern bool nvme_ns_discover(nvme_ctrl_t *, nvme_ns_disc_level_t, 760533affcbSRobert Mustacchi nvme_ns_disc_f, void *); 761533affcbSRobert Mustacchi 762533affcbSRobert Mustacchi extern bool nvme_ns_init(nvme_ctrl_t *, uint32_t, nvme_ns_t **); 763533affcbSRobert Mustacchi extern bool nvme_ns_init_by_name(nvme_ctrl_t *, const char *, nvme_ns_t **); 764533affcbSRobert Mustacchi extern void nvme_ns_fini(nvme_ns_t *); 765533affcbSRobert Mustacchi 766533affcbSRobert Mustacchi /* 767533affcbSRobert Mustacchi * This is a convenience routine for opening up an NVMe controller and/or 768533affcbSRobert Mustacchi * namespace. Many utilities refer to things as <controller>/<namespace>. As 769533affcbSRobert Mustacchi * such, this will parse that apart. If no namespace is specified, it will be 770533affcbSRobert Mustacchi * left as NULL. If the specified controller or namespace cannot be found, then 771533affcbSRobert Mustacchi * the function will fail. 772533affcbSRobert Mustacchi * 773533affcbSRobert Mustacchi * Currently the only supported controller name is nvmeX, though we should 774533affcbSRobert Mustacchi * support GUIDs at some point. The namespace id, EUI64, and NGUID are all 775533affcbSRobert Mustacchi * supported for the namespace. 776533affcbSRobert Mustacchi */ 777533affcbSRobert Mustacchi extern bool nvme_ctrl_ns_init(nvme_t *, const char *, nvme_ctrl_t **, 778533affcbSRobert Mustacchi nvme_ns_t **); 779533affcbSRobert Mustacchi 780533affcbSRobert Mustacchi /* 781533affcbSRobert Mustacchi * NVMe Namespace Information. 782533affcbSRobert Mustacchi * 783533affcbSRobert Mustacchi * Namespace information is broken into a few groups. There is basic information 784533affcbSRobert Mustacchi * about the LBA formats and capacities (which are provided in block sizes). 785533affcbSRobert Mustacchi * There is information about the IDs. Note the NGUID/EUI64 are fallible 786533affcbSRobert Mustacchi * because they are optional. 787533affcbSRobert Mustacchi */ 788533affcbSRobert Mustacchi extern bool nvme_ns_info_snap(nvme_ns_t *, nvme_ns_info_t **); 789533affcbSRobert Mustacchi extern bool nvme_ctrl_ns_info_snap(nvme_ctrl_t *, uint32_t, nvme_ns_info_t **); 790533affcbSRobert Mustacchi extern void nvme_ns_info_free(nvme_ns_info_t *); 791533affcbSRobert Mustacchi 792533affcbSRobert Mustacchi extern nvme_info_err_t nvme_ns_info_err(nvme_ns_info_t *); 793533affcbSRobert Mustacchi extern int32_t nvme_ns_info_syserr(nvme_ns_info_t *); 794533affcbSRobert Mustacchi extern const char *nvme_ns_info_errmsg(nvme_ns_info_t *); 795533affcbSRobert Mustacchi extern size_t nvme_ns_info_errlen(nvme_ns_info_t *); 796533affcbSRobert Mustacchi extern const char *nvme_ns_info_errtostr(nvme_ns_info_t *, nvme_info_err_t); 797533affcbSRobert Mustacchi 798533affcbSRobert Mustacchi extern uint32_t nvme_ns_info_nsid(nvme_ns_info_t *); 799533affcbSRobert Mustacchi extern nvme_ns_disc_level_t nvme_ns_info_level(nvme_ns_info_t *); 800533affcbSRobert Mustacchi extern const nvme_identify_nsid_t *nvme_ns_info_identify(nvme_ns_info_t *); 801533affcbSRobert Mustacchi 802533affcbSRobert Mustacchi extern bool nvme_ns_info_nguid(nvme_ns_info_t *, uint8_t [16]); 803533affcbSRobert Mustacchi extern bool nvme_ns_info_eui64(nvme_ns_info_t *, uint8_t [8]); 804533affcbSRobert Mustacchi 805533affcbSRobert Mustacchi extern bool nvme_ns_info_size(nvme_ns_info_t *, uint64_t *); 806533affcbSRobert Mustacchi extern bool nvme_ns_info_cap(nvme_ns_info_t *, uint64_t *); 807533affcbSRobert Mustacchi extern bool nvme_ns_info_use(nvme_ns_info_t *, uint64_t *); 808533affcbSRobert Mustacchi 809533affcbSRobert Mustacchi extern bool nvme_ns_info_curformat(nvme_ns_info_t *, 810533affcbSRobert Mustacchi const nvme_nvm_lba_fmt_t **); 811533affcbSRobert Mustacchi extern bool nvme_ns_info_nformats(nvme_ns_info_t *, uint32_t *); 812533affcbSRobert Mustacchi extern bool nvme_ns_info_format(nvme_ns_info_t *, uint32_t, 813533affcbSRobert Mustacchi const nvme_nvm_lba_fmt_t **); 814533affcbSRobert Mustacchi 815533affcbSRobert Mustacchi extern bool nvme_ns_info_bd_addr(nvme_ns_info_t *, const char **); 816533affcbSRobert Mustacchi 817533affcbSRobert Mustacchi /* 818533affcbSRobert Mustacchi * Controller and Namespace Locking 819533affcbSRobert Mustacchi * 820533affcbSRobert Mustacchi * A given controller can be active by several different parallel consumers. 821533affcbSRobert Mustacchi */ 822533affcbSRobert Mustacchi extern bool nvme_ctrl_lock(nvme_ctrl_t *, nvme_lock_level_t, nvme_lock_flags_t); 823533affcbSRobert Mustacchi extern void nvme_ctrl_unlock(nvme_ctrl_t *); 824533affcbSRobert Mustacchi extern bool nvme_ns_lock(nvme_ns_t *, nvme_lock_level_t, nvme_lock_flags_t); 825533affcbSRobert Mustacchi extern void nvme_ns_unlock(nvme_ns_t *); 826533affcbSRobert Mustacchi 827533affcbSRobert Mustacchi /* 828533affcbSRobert Mustacchi * Namespace Attach and Detach 829533affcbSRobert Mustacchi * 830533affcbSRobert Mustacchi * These operations are used to attach and detach a blkdev device from a given 831533affcbSRobert Mustacchi * namespace. 832533affcbSRobert Mustacchi */ 833533affcbSRobert Mustacchi extern bool nvme_ns_bd_attach(nvme_ns_t *); 834533affcbSRobert Mustacchi extern bool nvme_ns_bd_detach(nvme_ns_t *); 835533affcbSRobert Mustacchi 836533affcbSRobert Mustacchi /* 837533affcbSRobert Mustacchi * NVMe Log Page Discovery 838533affcbSRobert Mustacchi * 839533affcbSRobert Mustacchi * NVMe Log Pages provide some complications around discovery. There are 840533affcbSRobert Mustacchi * standard log pages, which are either mandatory or optional. There are also 841533affcbSRobert Mustacchi * vendor-specific log pages that we may know about. While NVMe 2.0 introduced a 842533affcbSRobert Mustacchi * way to list all of the supported log pages a device implements, that is not 843533affcbSRobert Mustacchi * true for most devices. Pre 2.x devices sometimes have a vendor-specific way 844533affcbSRobert Mustacchi * to list all the available logs. The NVMe 2.0 based mechanism also does not 845533affcbSRobert Mustacchi * provide a means of getting additional information such as required fields, so 846533affcbSRobert Mustacchi * we'll end up always needing the additional information this interface 847533affcbSRobert Mustacchi * provides. 848533affcbSRobert Mustacchi * 849533affcbSRobert Mustacchi * The log page discovery functions here allow a caller to just ask for all the 850533affcbSRobert Mustacchi * known IDs that exist for something. The discovery callback will fire once for 851533affcbSRobert Mustacchi * each log page that may be implemented. Log pages we know that aren't 852533affcbSRobert Mustacchi * implemented are never called back for. 853533affcbSRobert Mustacchi */ 854533affcbSRobert Mustacchi extern const char *nvme_log_disc_name(const nvme_log_disc_t *); 855533affcbSRobert Mustacchi extern const char *nvme_log_disc_desc(const nvme_log_disc_t *); 856533affcbSRobert Mustacchi extern nvme_csi_t nvme_log_disc_csi(const nvme_log_disc_t *); 857533affcbSRobert Mustacchi extern uint32_t nvme_log_disc_lid(const nvme_log_disc_t *); 858533affcbSRobert Mustacchi extern nvme_log_disc_kind_t nvme_log_disc_kind(const nvme_log_disc_t *); 859533affcbSRobert Mustacchi extern nvme_log_disc_source_t nvme_log_disc_sources(const nvme_log_disc_t *); 860533affcbSRobert Mustacchi extern nvme_log_disc_fields_t nvme_log_disc_fields(const nvme_log_disc_t *); 861533affcbSRobert Mustacchi extern nvme_log_disc_scope_t nvme_log_disc_scopes(const nvme_log_disc_t *); 862533affcbSRobert Mustacchi extern bool nvme_log_disc_impl(const nvme_log_disc_t *); 863533affcbSRobert Mustacchi 864533affcbSRobert Mustacchi typedef enum { 865533affcbSRobert Mustacchi /* 866533affcbSRobert Mustacchi * This indicates that the size of a log page is unknown. Instead, we 867533affcbSRobert Mustacchi * will return a size that is reasonable enough to hopefully cover most 868533affcbSRobert Mustacchi * things. 869533affcbSRobert Mustacchi */ 870533affcbSRobert Mustacchi NVME_LOG_SIZE_K_UNKNOWN = 0, 871533affcbSRobert Mustacchi /* 872533affcbSRobert Mustacchi * This indicates that there is a known fixed size for the log page and 873533affcbSRobert Mustacchi * we have indicated what that is. 874533affcbSRobert Mustacchi */ 875533affcbSRobert Mustacchi NVME_LOG_SIZE_K_FIXED, 876533affcbSRobert Mustacchi /* 877533affcbSRobert Mustacchi * This indicates that the total log size is variable; however, it can 878533affcbSRobert Mustacchi * be determined by reading the specified following number of bytes. 879533affcbSRobert Mustacchi * Once that number of bytes has been read, that can be passed to the 880533affcbSRobert Mustacchi * nvme_log_disc_cal_size() function, which will attempt to determine 881533affcbSRobert Mustacchi * the actual number of bytes based on the returned data. 882533affcbSRobert Mustacchi */ 883533affcbSRobert Mustacchi NVME_LOG_SIZE_K_VAR 884533affcbSRobert Mustacchi } nvme_log_size_kind_t; 885533affcbSRobert Mustacchi extern nvme_log_size_kind_t nvme_log_disc_size(const nvme_log_disc_t *, 886533affcbSRobert Mustacchi uint64_t *); 887533affcbSRobert Mustacchi extern bool nvme_log_disc_calc_size(const nvme_log_disc_t *, uint64_t *, 888533affcbSRobert Mustacchi const void *, size_t); 889533affcbSRobert Mustacchi 890533affcbSRobert Mustacchi /* 891533affcbSRobert Mustacchi * Duplicate and free log discovery information. The free function should only 892533affcbSRobert Mustacchi * be used when it is explicitly duplicated or obtained through something like 893533affcbSRobert Mustacchi * nvme_log_req_init_by_name(). It must not be used on the constant data 894533affcbSRobert Mustacchi * provided as part of the nvme_log_discover family of functions. 895533affcbSRobert Mustacchi */ 896533affcbSRobert Mustacchi extern bool nvme_log_disc_dup(nvme_ctrl_t *, const nvme_log_disc_t *, 897533affcbSRobert Mustacchi nvme_log_disc_t **); 898533affcbSRobert Mustacchi extern void nvme_log_disc_free(nvme_log_disc_t *); 899533affcbSRobert Mustacchi 900533affcbSRobert Mustacchi extern bool nvme_log_discover_init(nvme_ctrl_t *, nvme_log_disc_scope_t, 901533affcbSRobert Mustacchi uint32_t, nvme_log_iter_t **); 902533affcbSRobert Mustacchi extern nvme_iter_t nvme_log_discover_step(nvme_log_iter_t *, 903533affcbSRobert Mustacchi const nvme_log_disc_t **); 904533affcbSRobert Mustacchi extern void nvme_log_discover_fini(nvme_log_iter_t *); 905533affcbSRobert Mustacchi 906533affcbSRobert Mustacchi typedef bool (*nvme_log_disc_f)(nvme_ctrl_t *, const nvme_log_disc_t *, 907533affcbSRobert Mustacchi void *); 908533affcbSRobert Mustacchi extern bool nvme_log_discover(nvme_ctrl_t *, nvme_log_disc_scope_t, 909533affcbSRobert Mustacchi uint32_t, nvme_log_disc_f, void *); 910533affcbSRobert Mustacchi 911533affcbSRobert Mustacchi /* 912533affcbSRobert Mustacchi * One does not simply request a log page. There are a lot of parameters that 913533affcbSRobert Mustacchi * are used to get a log page and these have been evolving over time. For 914533affcbSRobert Mustacchi * example, the size has changed between 1.2 and 1.3, NVMe 1.0 never had UUIDs, 915533affcbSRobert Mustacchi * LSP, LSIs, there are optional features around supporting offsets, etc. 916533affcbSRobert Mustacchi * 917533affcbSRobert Mustacchi * To deal with the fact that this keeps changing and an attempt to create a 918533affcbSRobert Mustacchi * stable ABI, we instead have an opaque structure that allows various fields to 919533affcbSRobert Mustacchi * be set and changed. To speed this up, this can be bootstrapped from the 920533affcbSRobert Mustacchi * discovery information directly or indirectly by the log page short name. 921533affcbSRobert Mustacchi * 922533affcbSRobert Mustacchi * Once all of the appropriate fields are set on a log page request then it can 923533affcbSRobert Mustacchi * be executed. A given request may be executed multiple times. 924533affcbSRobert Mustacchi * 925533affcbSRobert Mustacchi * When creating a raw log request, it will be up to the caller to fill in and 926533affcbSRobert Mustacchi * set up the log ID (lid) and the output information. It is assumed that by 927533affcbSRobert Mustacchi * default a log request should specify the NVM CSI. When using 928533affcbSRobert Mustacchi * nvme_log_req_init_by_disc(), the log ID and command set will be filled in 929533affcbSRobert Mustacchi * automatically. The discovery flags will indicate what other fields are still 930533affcbSRobert Mustacchi * required. 931533affcbSRobert Mustacchi */ 932533affcbSRobert Mustacchi extern bool nvme_log_req_init(nvme_ctrl_t *, nvme_log_req_t **); 933533affcbSRobert Mustacchi extern bool nvme_log_req_init_by_disc(nvme_ctrl_t *, const nvme_log_disc_t *, 934533affcbSRobert Mustacchi nvme_log_req_t **); 935533affcbSRobert Mustacchi extern bool nvme_log_req_init_by_name(nvme_ctrl_t *, const char *, 936533affcbSRobert Mustacchi uint32_t, nvme_log_disc_t **, nvme_log_req_t **); 937533affcbSRobert Mustacchi extern void nvme_log_req_fini(nvme_log_req_t *); 938533affcbSRobert Mustacchi 939533affcbSRobert Mustacchi extern bool nvme_log_req_set_lid(nvme_log_req_t *, uint32_t); 940533affcbSRobert Mustacchi extern bool nvme_log_req_set_lsp(nvme_log_req_t *, uint32_t); 941533affcbSRobert Mustacchi extern bool nvme_log_req_set_lsi(nvme_log_req_t *, uint32_t); 942533affcbSRobert Mustacchi extern bool nvme_log_req_set_uuid(nvme_log_req_t *, uint32_t); 943533affcbSRobert Mustacchi extern bool nvme_log_req_set_nsid(nvme_log_req_t *, uint32_t); 944533affcbSRobert Mustacchi extern bool nvme_log_req_set_output(nvme_log_req_t *, void *, size_t); 945*1c02c6c8SRobert Mustacchi extern bool nvme_log_req_clear_output(nvme_log_req_t *); 946533affcbSRobert Mustacchi extern bool nvme_log_req_set_offset(nvme_log_req_t *, uint64_t); 947533affcbSRobert Mustacchi extern bool nvme_log_req_set_rae(nvme_log_req_t *, bool); 948533affcbSRobert Mustacchi extern bool nvme_log_req_set_csi(nvme_log_req_t *, nvme_csi_t); 949533affcbSRobert Mustacchi extern bool nvme_log_req_exec(nvme_log_req_t *); 950533affcbSRobert Mustacchi 951533affcbSRobert Mustacchi /* 952533affcbSRobert Mustacchi * Feature Discovery and Management 953533affcbSRobert Mustacchi * 954533affcbSRobert Mustacchi * Features are parts of the NVMe specification that can both be retrieved and 955533affcbSRobert Mustacchi * set. Features are often either a uint32_t or a larger data payload. In 956533affcbSRobert Mustacchi * addition, there are additional modifiers that are required to select 957533affcbSRobert Mustacchi * information about features. For example, when getting or setting a 958533affcbSRobert Mustacchi * temperature threshold feature, a temperature sensor ID is required. Much like 959533affcbSRobert Mustacchi * with log pages this has changed and added new arguments to getting and 960533affcbSRobert Mustacchi * setting a feature at the command level and the individual features have grown 961533affcbSRobert Mustacchi * support for more configuration as well. 962533affcbSRobert Mustacchi * 963533affcbSRobert Mustacchi * We currently provide information in discovery to determine what is required 964533affcbSRobert Mustacchi * to get a feature as well as the ability to fast path that. Currently we 965533affcbSRobert Mustacchi * provide the raw feature getting API that works at the low level. There is no 966533affcbSRobert Mustacchi * higher level API for specific features. This works okay for an nvmeadm(8) 967533affcbSRobert Mustacchi * style implementation, but we should consider adding more here based on 968533affcbSRobert Mustacchi * feedback from consumers. 969533affcbSRobert Mustacchi * 970533affcbSRobert Mustacchi * Currently the kernel does not support setting features, which is why there is 971533affcbSRobert Mustacchi * not a set feature API exposed through here. When it is, there will be an 972533affcbSRobert Mustacchi * analogues set feature API to the get feature API that allows for one to 973533affcbSRobert Mustacchi * build this up generically. 974533affcbSRobert Mustacchi */ 975533affcbSRobert Mustacchi extern const char *nvme_feat_disc_short(const nvme_feat_disc_t *); 976533affcbSRobert Mustacchi extern const char *nvme_feat_disc_spec(const nvme_feat_disc_t *); 977533affcbSRobert Mustacchi extern uint32_t nvme_feat_disc_fid(const nvme_feat_disc_t *); 978533affcbSRobert Mustacchi extern nvme_feat_scope_t nvme_feat_disc_scope(const nvme_feat_disc_t *); 979533affcbSRobert Mustacchi extern nvme_feat_kind_t nvme_feat_disc_kind(const nvme_feat_disc_t *); 980533affcbSRobert Mustacchi extern nvme_feat_csi_t nvme_feat_disc_csi(const nvme_feat_disc_t *); 981533affcbSRobert Mustacchi extern nvme_feat_flags_t nvme_feat_disc_flags(const nvme_feat_disc_t *); 982533affcbSRobert Mustacchi extern nvme_get_feat_fields_t nvme_feat_disc_fields_get( 983533affcbSRobert Mustacchi const nvme_feat_disc_t *); 984533affcbSRobert Mustacchi extern nvme_set_feat_fields_t nvme_feat_disc_fields_set( 985533affcbSRobert Mustacchi const nvme_feat_disc_t *); 986533affcbSRobert Mustacchi extern nvme_feat_output_t nvme_feat_disc_output_get(const nvme_feat_disc_t *); 987533affcbSRobert Mustacchi extern nvme_feat_output_t nvme_feat_disc_output_set(const nvme_feat_disc_t *); 988533affcbSRobert Mustacchi extern uint64_t nvme_feat_disc_data_size(const nvme_feat_disc_t *); 989533affcbSRobert Mustacchi extern nvme_feat_impl_t nvme_feat_disc_impl(const nvme_feat_disc_t *); 990533affcbSRobert Mustacchi 991533affcbSRobert Mustacchi extern bool nvme_feat_discover_init(nvme_ctrl_t *, nvme_feat_scope_t, uint32_t, 992533affcbSRobert Mustacchi nvme_feat_iter_t **); 993533affcbSRobert Mustacchi extern nvme_iter_t nvme_feat_discover_step(nvme_feat_iter_t *, 994533affcbSRobert Mustacchi const nvme_feat_disc_t **); 995533affcbSRobert Mustacchi extern void nvme_feat_discover_fini(nvme_feat_iter_t *); 996533affcbSRobert Mustacchi 997533affcbSRobert Mustacchi extern bool nvme_feat_disc_dup(nvme_ctrl_t *, const nvme_feat_disc_t *, 998533affcbSRobert Mustacchi nvme_feat_disc_t **); 999533affcbSRobert Mustacchi extern void nvme_feat_disc_free(nvme_feat_disc_t *); 1000533affcbSRobert Mustacchi 1001533affcbSRobert Mustacchi typedef bool (*nvme_feat_disc_f)(nvme_ctrl_t *, const nvme_feat_disc_t *, 1002533affcbSRobert Mustacchi void *); 1003533affcbSRobert Mustacchi extern bool nvme_feat_discover(nvme_ctrl_t *, nvme_feat_scope_t, uint32_t, 1004533affcbSRobert Mustacchi nvme_feat_disc_f, void *); 1005533affcbSRobert Mustacchi 1006533affcbSRobert Mustacchi /* 1007533affcbSRobert Mustacchi * Get Feature Request 1008533affcbSRobert Mustacchi * 1009533affcbSRobert Mustacchi * The get feature request allows one to build up a get feature command. It is 1010533affcbSRobert Mustacchi * recommended to initiate a request based on discovery information or a 1011533affcbSRobert Mustacchi * feature's name. That will allow the system to perform better validation, know 1012533affcbSRobert Mustacchi * what fields are required or not, and pre-set parameters like the feature id 1013533affcbSRobert Mustacchi * (fid). By default, a get features request will always ask for the current 1014533affcbSRobert Mustacchi * value. Unless you want a saved or default value (and the controller is new 1015533affcbSRobert Mustacchi * enough), then there is no need to set the selector. The only required field 1016533affcbSRobert Mustacchi * when not using discovery information is the fid. 1017533affcbSRobert Mustacchi */ 1018533affcbSRobert Mustacchi extern bool nvme_get_feat_req_init(nvme_ctrl_t *, nvme_get_feat_req_t **); 1019533affcbSRobert Mustacchi extern bool nvme_get_feat_req_init_by_disc(nvme_ctrl_t *, 1020533affcbSRobert Mustacchi const nvme_feat_disc_t *, nvme_get_feat_req_t **); 1021533affcbSRobert Mustacchi extern bool nvme_get_feat_req_init_by_name(nvme_ctrl_t *, const char *, 1022533affcbSRobert Mustacchi uint32_t, nvme_feat_disc_t **, nvme_get_feat_req_t **); 1023533affcbSRobert Mustacchi extern void nvme_get_feat_req_fini(nvme_get_feat_req_t *); 1024533affcbSRobert Mustacchi 1025533affcbSRobert Mustacchi extern bool nvme_get_feat_req_set_fid(nvme_get_feat_req_t *, uint32_t); 1026533affcbSRobert Mustacchi extern bool nvme_get_feat_req_set_sel(nvme_get_feat_req_t *, uint32_t); 1027533affcbSRobert Mustacchi extern bool nvme_get_feat_req_set_nsid(nvme_get_feat_req_t *, uint32_t); 1028533affcbSRobert Mustacchi extern bool nvme_get_feat_req_set_cdw11(nvme_get_feat_req_t *, uint32_t); 1029533affcbSRobert Mustacchi extern bool nvme_get_feat_req_set_output(nvme_get_feat_req_t *, void *, size_t); 1030*1c02c6c8SRobert Mustacchi extern bool nvme_get_feat_req_clear_output(nvme_get_feat_req_t *); 1031533affcbSRobert Mustacchi extern bool nvme_get_feat_req_exec(nvme_get_feat_req_t *); 1032533affcbSRobert Mustacchi extern bool nvme_get_feat_req_get_cdw0(nvme_get_feat_req_t *, uint32_t *); 1033533affcbSRobert Mustacchi 1034533affcbSRobert Mustacchi /* 1035533affcbSRobert Mustacchi * NVMe Vendor Unique Command Discovery and Execution 1036533affcbSRobert Mustacchi * 1037533affcbSRobert Mustacchi * There is a standard form of vendor unique commands which are indicated in the 1038533affcbSRobert Mustacchi * identify controller datasheet. The first set of pieces here allows one to 1039533affcbSRobert Mustacchi * discover which vendor-specific commands are supported by a device that are 1040533affcbSRobert Mustacchi * known to the library. These generally have their own implementation 1041533affcbSRobert Mustacchi * function; however, that isn't really linked to from the discovery function. 1042533affcbSRobert Mustacchi * Tied into this is also asking if a given controller supports a given command 1043533affcbSRobert Mustacchi * and getting information about it. 1044533affcbSRobert Mustacchi * 1045533affcbSRobert Mustacchi * The second set of functions here is all around allocating a vendor unique 1046533affcbSRobert Mustacchi * command then executing it. Currently only admin commands are supported 1047533affcbSRobert Mustacchi * through this interface. 1048533affcbSRobert Mustacchi */ 1049533affcbSRobert Mustacchi extern bool nvme_vuc_discover_init(nvme_ctrl_t *, uint32_t, 1050533affcbSRobert Mustacchi nvme_vuc_iter_t **); 1051533affcbSRobert Mustacchi extern nvme_iter_t nvme_vuc_discover_step(nvme_vuc_iter_t *, 1052533affcbSRobert Mustacchi const nvme_vuc_disc_t **); 1053533affcbSRobert Mustacchi extern void nvme_vuc_discover_fini(nvme_vuc_iter_t *); 1054533affcbSRobert Mustacchi 1055533affcbSRobert Mustacchi typedef bool (*nvme_vuc_disc_f)(nvme_ctrl_t *, const nvme_vuc_disc_t *, void *); 1056533affcbSRobert Mustacchi extern bool nvme_vuc_discover(nvme_ctrl_t *, uint32_t, nvme_vuc_disc_f, void *); 1057533affcbSRobert Mustacchi 1058533affcbSRobert Mustacchi extern bool nvme_vuc_discover_by_name(nvme_ctrl_t *, const char *, uint32_t, 1059533affcbSRobert Mustacchi nvme_vuc_disc_t **); 1060533affcbSRobert Mustacchi extern bool nvme_vuc_disc_dup(nvme_ctrl_t *, const nvme_vuc_disc_t *, 1061533affcbSRobert Mustacchi nvme_vuc_disc_t **); 1062533affcbSRobert Mustacchi extern void nvme_vuc_disc_free(nvme_vuc_disc_t *); 1063533affcbSRobert Mustacchi 1064533affcbSRobert Mustacchi extern const char *nvme_vuc_disc_name(const nvme_vuc_disc_t *); 1065533affcbSRobert Mustacchi extern const char *nvme_vuc_disc_desc(const nvme_vuc_disc_t *); 1066533affcbSRobert Mustacchi extern uint32_t nvme_vuc_disc_opcode(const nvme_vuc_disc_t *); 1067533affcbSRobert Mustacchi 1068533affcbSRobert Mustacchi typedef enum { 1069533affcbSRobert Mustacchi /* 1070533affcbSRobert Mustacchi * Indicates that when this command is run, one should assume that all 1071533affcbSRobert Mustacchi * data is potentially erased. 1072533affcbSRobert Mustacchi */ 1073533affcbSRobert Mustacchi NVME_VUC_DISC_IMPACT_DATA = 1 << 0, 1074533affcbSRobert Mustacchi /* 1075533affcbSRobert Mustacchi * Indicates that when this command is run, one should assume that the 1076533affcbSRobert Mustacchi * list of namespaces and their attributes will change. 1077533affcbSRobert Mustacchi */ 1078533affcbSRobert Mustacchi NVME_VUC_DISC_IMPACT_NS = 1 << 1 1079533affcbSRobert Mustacchi } nvme_vuc_disc_impact_t; 1080533affcbSRobert Mustacchi extern nvme_vuc_disc_impact_t nvme_vuc_disc_impact(const nvme_vuc_disc_t *); 1081533affcbSRobert Mustacchi 1082533affcbSRobert Mustacchi typedef enum { 1083533affcbSRobert Mustacchi NVME_VUC_DISC_IO_NONE = 0, 1084533affcbSRobert Mustacchi /* 1085533affcbSRobert Mustacchi * Indicates that this command needs additional data provided as input 1086533affcbSRobert Mustacchi * to the command. 1087533affcbSRobert Mustacchi */ 1088533affcbSRobert Mustacchi NVME_VUC_DISC_IO_INPUT = 1 << 0, 1089533affcbSRobert Mustacchi /* 1090533affcbSRobert Mustacchi * Indicates that this command writes output back to the host from the 1091533affcbSRobert Mustacchi * controller and a data buffer is required. 1092533affcbSRobert Mustacchi */ 1093533affcbSRobert Mustacchi NVME_VUC_DISC_IO_OUTPUT = 1 << 1 1094533affcbSRobert Mustacchi } nvme_vuc_disc_io_t; 1095533affcbSRobert Mustacchi extern nvme_vuc_disc_io_t nvme_vuc_disc_dt(const nvme_vuc_disc_t *); 1096533affcbSRobert Mustacchi 1097533affcbSRobert Mustacchi typedef enum { 1098533affcbSRobert Mustacchi /* 1099533affcbSRobert Mustacchi * Indicates that the library has no opinion on whether a lock should be 1100533affcbSRobert Mustacchi * taken or not. 1101533affcbSRobert Mustacchi */ 1102533affcbSRobert Mustacchi NVME_VUC_DISC_LOCK_NONE = 0, 1103533affcbSRobert Mustacchi /* 1104533affcbSRobert Mustacchi * Indicates that a controller or namespace level read lock is 1105533affcbSRobert Mustacchi * recommended for this operation. 1106533affcbSRobert Mustacchi */ 1107533affcbSRobert Mustacchi NVME_VUC_DISC_LOCK_READ, 1108533affcbSRobert Mustacchi /* 1109533affcbSRobert Mustacchi * Indicates that a controller or namespace level write lock is 1110533affcbSRobert Mustacchi * recommended for this operation. 1111533affcbSRobert Mustacchi */ 1112533affcbSRobert Mustacchi NVME_VUC_DISC_LOCK_WRITE 1113533affcbSRobert Mustacchi } nvme_vuc_disc_lock_t; 1114533affcbSRobert Mustacchi extern nvme_vuc_disc_lock_t nvme_vuc_disc_lock(const nvme_vuc_disc_t *); 1115533affcbSRobert Mustacchi 1116533affcbSRobert Mustacchi extern bool nvme_vuc_req_init(nvme_ctrl_t *, nvme_vuc_req_t **); 1117533affcbSRobert Mustacchi extern void nvme_vuc_req_fini(nvme_vuc_req_t *); 1118533affcbSRobert Mustacchi 1119533affcbSRobert Mustacchi extern bool nvme_vuc_req_set_opcode(nvme_vuc_req_t *, uint32_t); 1120533affcbSRobert Mustacchi extern bool nvme_vuc_req_set_nsid(nvme_vuc_req_t *, uint32_t); 1121533affcbSRobert Mustacchi extern bool nvme_vuc_req_set_timeout(nvme_vuc_req_t *, uint32_t); 1122533affcbSRobert Mustacchi extern bool nvme_vuc_req_set_cdw12(nvme_vuc_req_t *, uint32_t); 1123533affcbSRobert Mustacchi extern bool nvme_vuc_req_set_cdw13(nvme_vuc_req_t *, uint32_t); 1124533affcbSRobert Mustacchi extern bool nvme_vuc_req_set_cdw14(nvme_vuc_req_t *, uint32_t); 1125533affcbSRobert Mustacchi extern bool nvme_vuc_req_set_cdw15(nvme_vuc_req_t *, uint32_t); 1126533affcbSRobert Mustacchi extern bool nvme_vuc_req_set_impact(nvme_vuc_req_t *, nvme_vuc_disc_impact_t); 1127533affcbSRobert Mustacchi extern bool nvme_vuc_req_set_input(nvme_vuc_req_t *, const void *, size_t); 1128533affcbSRobert Mustacchi extern bool nvme_vuc_req_set_output(nvme_vuc_req_t *, void *, size_t); 1129*1c02c6c8SRobert Mustacchi extern bool nvme_vuc_req_clear_output(nvme_vuc_req_t *); 1130533affcbSRobert Mustacchi 1131533affcbSRobert Mustacchi /* 1132533affcbSRobert Mustacchi * Execute a request. After a request is executed, the status information 1133533affcbSRobert Mustacchi * becomes available. A call to exec will invalidate any prior results. If the 1134533affcbSRobert Mustacchi * request does not make it to the controller for some reason or some other 1135533affcbSRobert Mustacchi * error occurs, then getting the results will fail. If the controller fails the 1136533affcbSRobert Mustacchi * command, that will set the NVME_ERR_CONTROLLER error and the corresponding 1137533affcbSRobert Mustacchi * SCT/SC values can be retrieved from the controller's error information for 1138533affcbSRobert Mustacchi * inspection. 1139533affcbSRobert Mustacchi */ 1140533affcbSRobert Mustacchi extern bool nvme_vuc_req_exec(nvme_vuc_req_t *); 1141533affcbSRobert Mustacchi extern bool nvme_vuc_req_get_cdw0(nvme_vuc_req_t *, uint32_t *); 1142533affcbSRobert Mustacchi 1143533affcbSRobert Mustacchi /* 1144533affcbSRobert Mustacchi * Firmware Download and Commit (Activation) 1145533affcbSRobert Mustacchi * 1146533affcbSRobert Mustacchi * NVMe devices have a buffer that is used to receive a firmware download. This 1147533affcbSRobert Mustacchi * can then be committed into a firmware slot or a boot slot through the commit 1148533affcbSRobert Mustacchi * action. The commit action may also change which firmware slot is activated on 1149533affcbSRobert Mustacchi * the next boot at the same time as installing an image or a commit can be used 1150533affcbSRobert Mustacchi * to just change the active image. The optional bootloader features will have a 1151533affcbSRobert Mustacchi * similar shape as to the firmware commit routines, but ultimately be different 1152533affcbSRobert Mustacchi * ones to make it more obvious what is being done. 1153533affcbSRobert Mustacchi * 1154533affcbSRobert Mustacchi * The firmware download command has to date not really changed through the NVMe 1155533affcbSRobert Mustacchi * 1.x and 2.0 standards, which is why it is not broken into a request and 1156533affcbSRobert Mustacchi * execution format like others at this time. 11573dd3cd66SAndy Fiddaman * 11583dd3cd66SAndy Fiddaman * Firmware must be loaded with a particular granularity and if blocks do not 11593dd3cd66SAndy Fiddaman * conform to that, nvme_fw_load() will return an error. 1160533affcbSRobert Mustacchi */ 1161533affcbSRobert Mustacchi extern bool nvme_fw_load(nvme_ctrl_t *, const void *, size_t, uint64_t); 1162533affcbSRobert Mustacchi 1163533affcbSRobert Mustacchi extern bool nvme_fw_commit_req_init(nvme_ctrl_t *, nvme_fw_commit_req_t **); 1164533affcbSRobert Mustacchi extern void nvme_fw_commit_req_fini(nvme_fw_commit_req_t *); 1165533affcbSRobert Mustacchi extern bool nvme_fw_commit_req_set_slot(nvme_fw_commit_req_t *, uint32_t); 1166533affcbSRobert Mustacchi extern bool nvme_fw_commit_req_set_action(nvme_fw_commit_req_t *, uint32_t); 1167533affcbSRobert Mustacchi extern bool nvme_fw_commit_req_exec(nvme_fw_commit_req_t *); 1168533affcbSRobert Mustacchi 1169533affcbSRobert Mustacchi /* 1170533affcbSRobert Mustacchi * Format NVM 1171533affcbSRobert Mustacchi * 1172533affcbSRobert Mustacchi * This is used to erase and reformat either all namespaces or a specific one. 1173533affcbSRobert Mustacchi * We currently do not support setting metadata or protection information for 1174533affcbSRobert Mustacchi * namespaces in the kernel which is why this is not present in the library. 1175533affcbSRobert Mustacchi */ 1176533affcbSRobert Mustacchi extern bool nvme_format_req_init(nvme_ctrl_t *, nvme_format_req_t **); 1177533affcbSRobert Mustacchi extern void nvme_format_req_fini(nvme_format_req_t *); 1178533affcbSRobert Mustacchi extern bool nvme_format_req_set_lbaf(nvme_format_req_t *, uint32_t); 1179533affcbSRobert Mustacchi extern bool nvme_format_req_set_ses(nvme_format_req_t *, uint32_t); 1180533affcbSRobert Mustacchi extern bool nvme_format_req_set_nsid(nvme_format_req_t *, uint32_t); 1181533affcbSRobert Mustacchi extern bool nvme_format_req_exec(nvme_format_req_t *); 1182533affcbSRobert Mustacchi 1183533affcbSRobert Mustacchi /* 1184533affcbSRobert Mustacchi * Vendor-specific interfaces. 1185533affcbSRobert Mustacchi */ 1186533affcbSRobert Mustacchi 1187533affcbSRobert Mustacchi /* 1188533affcbSRobert Mustacchi * WDC resizing functions. These are interfaces supported in the SN840, SN650, 1189533affcbSRobert Mustacchi * SN655, etc. These end up allowing one to adjust the overprovisioning ratio, 1190533affcbSRobert Mustacchi * though this ends up reformatting the device and all namespaces in the 1191533affcbSRobert Mustacchi * process. The values passed and returned are in GB (not GiB). 1192533affcbSRobert Mustacchi */ 1193533affcbSRobert Mustacchi extern bool nvme_wdc_resize_set(nvme_ctrl_t *, uint32_t); 1194533affcbSRobert Mustacchi extern bool nvme_wdc_resize_get(nvme_ctrl_t *, uint32_t *); 1195533affcbSRobert Mustacchi 1196533affcbSRobert Mustacchi /* 1197533affcbSRobert Mustacchi * WDC e6 diagnostic log. The e6 log is a WDC-specific diagnostic log which 1198533affcbSRobert Mustacchi * contains information about the device itself. 1199533affcbSRobert Mustacchi */ 1200533affcbSRobert Mustacchi extern bool nvme_wdc_e6_req_init(nvme_ctrl_t *, nvme_wdc_e6_req_t **); 1201533affcbSRobert Mustacchi extern void nvme_wdc_e6_req_fini(nvme_wdc_e6_req_t *); 1202533affcbSRobert Mustacchi extern bool nvme_wdc_e6_req_set_offset(nvme_wdc_e6_req_t *, uint64_t); 1203533affcbSRobert Mustacchi extern bool nvme_wdc_e6_req_set_output(nvme_wdc_e6_req_t *, void *, 1204533affcbSRobert Mustacchi size_t); 1205*1c02c6c8SRobert Mustacchi extern bool nvme_wdc_e6_req_clear_output(nvme_wdc_e6_req_t *); 1206533affcbSRobert Mustacchi extern bool nvme_wdc_e6_req_exec(nvme_wdc_e6_req_t *); 1207533affcbSRobert Mustacchi 12087a27a99aSRobert Mustacchi /* 12097a27a99aSRobert Mustacchi * WDC assert injection and removal. 12107a27a99aSRobert Mustacchi */ 12117a27a99aSRobert Mustacchi extern bool nvme_wdc_assert_clear(nvme_ctrl_t *); 12127a27a99aSRobert Mustacchi extern bool nvme_wdc_assert_inject(nvme_ctrl_t *); 12137a27a99aSRobert Mustacchi 1214533affcbSRobert Mustacchi #ifdef __cplusplus 1215533affcbSRobert Mustacchi } 1216533affcbSRobert Mustacchi #endif 1217533affcbSRobert Mustacchi 1218533affcbSRobert Mustacchi #endif /* _LIBNVME_H */ 1219