diff options
Diffstat (limited to 'nvmecmds.h')
-rw-r--r-- | nvmecmds.h | 301 |
1 files changed, 301 insertions, 0 deletions
diff --git a/nvmecmds.h b/nvmecmds.h new file mode 100644 index 0000000..452c297 --- /dev/null +++ b/nvmecmds.h @@ -0,0 +1,301 @@ +/* + * nvmecmds.h + * + * Home page of code is: https://www.smartmontools.org + * + * Copyright (C) 2016-23 Christian Franke + * + * Original code from <linux/nvme.h>: + * Copyright (C) 2011-2014 Intel Corporation + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef NVMECMDS_H +#define NVMECMDS_H + +#define NVMECMDS_H_CVSID "$Id: nvmecmds.h 5471 2023-05-29 12:22:41Z chrfranke $" + +#include "static_assert.h" + +#include <errno.h> +#include <stddef.h> +#include <stdint.h> + +// The code below was originally imported from <linux/nvme.h> include file from +// Linux kernel sources. Types from <linux/types.h> were replaced. +// Symbol names are unchanged but placed in a namespace to allow inclusion +// of the original <linux/nvme.h>. +namespace smartmontools { + +//////////////////////////////////////////////////////////////////////////// +// BEGIN: From <linux/nvme.h> + +struct nvme_error_log_page { + uint64_t error_count; + unsigned short sqid; + unsigned short cmdid; + unsigned short status_field; + unsigned short parm_error_location; + uint64_t lba; + unsigned int nsid; + unsigned char vs; + unsigned char resv[35]; +}; +STATIC_ASSERT(sizeof(nvme_error_log_page) == 64); + +struct nvme_id_power_state { + unsigned short max_power; // centiwatts + unsigned char rsvd2; + unsigned char flags; + unsigned int entry_lat; // microseconds + unsigned int exit_lat; // microseconds + unsigned char read_tput; + unsigned char read_lat; + unsigned char write_tput; + unsigned char write_lat; + unsigned short idle_power; + unsigned char idle_scale; + unsigned char rsvd19; + unsigned short active_power; + unsigned char active_work_scale; + unsigned char rsvd23[9]; +}; +STATIC_ASSERT(sizeof(nvme_id_power_state) == 32); + +struct nvme_id_ctrl { + unsigned short vid; + unsigned short ssvid; + char sn[20]; + char mn[40]; + char fr[8]; + unsigned char rab; + unsigned char ieee[3]; + unsigned char cmic; + unsigned char mdts; + unsigned short cntlid; + unsigned int ver; + unsigned int rtd3r; + unsigned int rtd3e; + unsigned int oaes; + unsigned int ctratt; + unsigned char rsvd100[156]; + unsigned short oacs; + unsigned char acl; + unsigned char aerl; + unsigned char frmw; + unsigned char lpa; + unsigned char elpe; + unsigned char npss; + unsigned char avscc; + unsigned char apsta; + unsigned short wctemp; + unsigned short cctemp; + unsigned short mtfa; + unsigned int hmpre; + unsigned int hmmin; + unsigned char tnvmcap[16]; + unsigned char unvmcap[16]; + unsigned int rpmbs; + unsigned short edstt; + unsigned char dsto; + unsigned char fwug; + unsigned short kas; + unsigned short hctma; + unsigned short mntmt; + unsigned short mxtmt; + unsigned int sanicap; + unsigned char rsvd332[180]; + unsigned char sqes; + unsigned char cqes; + unsigned short maxcmd; + unsigned int nn; + unsigned short oncs; + unsigned short fuses; + unsigned char fna; + unsigned char vwc; + unsigned short awun; + unsigned short awupf; + unsigned char nvscc; + unsigned char rsvd531; + unsigned short acwu; + unsigned char rsvd534[2]; + unsigned int sgls; + unsigned char rsvd540[228]; + char subnqn[256]; + unsigned char rsvd1024[768]; + unsigned int ioccsz; + unsigned int iorcsz; + unsigned short icdoff; + unsigned char ctrattr; + unsigned char msdbd; + unsigned char rsvd1804[244]; + struct nvme_id_power_state psd[32]; + unsigned char vs[1024]; +}; +STATIC_ASSERT(sizeof(nvme_id_ctrl) == 4096); + +struct nvme_lbaf { + unsigned short ms; + unsigned char ds; + unsigned char rp; +}; +STATIC_ASSERT(sizeof(nvme_lbaf) == 4); + +struct nvme_id_ns { + uint64_t nsze; + uint64_t ncap; + uint64_t nuse; + unsigned char nsfeat; + unsigned char nlbaf; + unsigned char flbas; + unsigned char mc; + unsigned char dpc; + unsigned char dps; + unsigned char nmic; + unsigned char rescap; + unsigned char fpi; + unsigned char rsvd33; + unsigned short nawun; + unsigned short nawupf; + unsigned short nacwu; + unsigned short nabsn; + unsigned short nabo; + unsigned short nabspf; + unsigned char rsvd46[2]; + unsigned char nvmcap[16]; + unsigned char rsvd64[40]; + unsigned char nguid[16]; + unsigned char eui64[8]; + struct nvme_lbaf lbaf[16]; + unsigned char rsvd192[192]; + unsigned char vs[3712]; +}; +STATIC_ASSERT(sizeof(nvme_id_ns) == 4096); + +struct nvme_smart_log { + unsigned char critical_warning; + unsigned char temperature[2]; + unsigned char avail_spare; + unsigned char spare_thresh; + unsigned char percent_used; + unsigned char rsvd6[26]; + unsigned char data_units_read[16]; + unsigned char data_units_written[16]; + unsigned char host_reads[16]; + unsigned char host_writes[16]; + unsigned char ctrl_busy_time[16]; + unsigned char power_cycles[16]; + unsigned char power_on_hours[16]; + unsigned char unsafe_shutdowns[16]; + unsigned char media_errors[16]; + unsigned char num_err_log_entries[16]; + unsigned int warning_temp_time; + unsigned int critical_comp_time; + unsigned short temp_sensor[8]; + unsigned int thm_temp1_trans_count; + unsigned int thm_temp2_trans_count; + unsigned int thm_temp1_total_time; + unsigned int thm_temp2_total_time; + unsigned char rsvd232[280]; +}; +STATIC_ASSERT(sizeof(nvme_smart_log) == 512); + +enum nvme_admin_opcode { +//nvme_admin_delete_sq = 0x00, +//nvme_admin_create_sq = 0x01, + nvme_admin_get_log_page = 0x02, +//nvme_admin_delete_cq = 0x04, +//nvme_admin_create_cq = 0x05, + nvme_admin_identify = 0x06, +//nvme_admin_abort_cmd = 0x08, +//nvme_admin_set_features = 0x09, +//nvme_admin_get_features = 0x0a, +//nvme_admin_async_event = 0x0c, +//nvme_admin_ns_mgmt = 0x0d, +//nvme_admin_activate_fw = 0x10, +//nvme_admin_download_fw = 0x11, + nvme_admin_dev_self_test = 0x14, // NVMe 1.3 +//nvme_admin_ns_attach = 0x15, +//nvme_admin_format_nvm = 0x80, +//nvme_admin_security_send = 0x81, +//nvme_admin_security_recv = 0x82, +}; + +// END: From <linux/nvme.h> +//////////////////////////////////////////////////////////////////////////// + +// Figure 213 of NVM Express(TM) Base Specification, revision 2.0a, July 2021 +struct nvme_self_test_result { + uint8_t self_test_status; + uint8_t segment; + uint8_t valid; + uint8_t rsvd3; + uint8_t power_on_hours[8]; // unaligned LE 64 + uint32_t nsid; + uint8_t lba[8]; // unaligned LE 64 + uint8_t status_code_type; + uint8_t status_code; + uint8_t vendor_specific[2]; +}; +STATIC_ASSERT(sizeof(nvme_self_test_result) == 28); + +// Figure 212 of NVM Express(TM) Base Specification, revision 2.0a, July 2021 +struct nvme_self_test_log { + uint8_t current_operation; + uint8_t current_completion; + uint8_t rsvd2[2]; + nvme_self_test_result results[20]; // [0] = newest +}; +STATIC_ASSERT(sizeof(nvme_self_test_log) == 564); + +} // namespace smartmontools + +class nvme_device; + +// Print NVMe debug messages? +extern unsigned char nvme_debugmode; + +// Read NVMe Identify Controller data structure. +bool nvme_read_id_ctrl(nvme_device * device, smartmontools::nvme_id_ctrl & id_ctrl); + +// Read NVMe Identify Namespace data structure for namespace NSID. +bool nvme_read_id_ns(nvme_device * device, unsigned nsid, smartmontools::nvme_id_ns & id_ns); + +// Read NVMe log page with identifier LID. +unsigned nvme_read_log_page(nvme_device * device, unsigned nsid, unsigned char lid, + void * data, unsigned size, bool lpo_sup, unsigned offset = 0); + +// Read NVMe Error Information Log. +unsigned nvme_read_error_log(nvme_device * device, smartmontools::nvme_error_log_page * error_log, + unsigned num_entries, bool lpo_sup); + +// Read NVMe SMART/Health Information log. +bool nvme_read_smart_log(nvme_device * device, smartmontools::nvme_smart_log & smart_log); + +// Read NVMe Self-test Log. +bool nvme_read_self_test_log(nvme_device * device, uint32_t nsid, + smartmontools::nvme_self_test_log & self_test_log); + +// Start Self-test +bool nvme_self_test(nvme_device * device, uint8_t stc, uint32_t nsid); + +// Return true if NVMe status indicates an error. +constexpr bool nvme_status_is_error(uint16_t status) + { return !!(status & 0x07ff); } + +// Return errno for NVMe status SCT/SC fields: 0, EINVAL or EIO. +int nvme_status_to_errno(uint16_t status); + +// Return error message for NVMe status SCT/SC fields or nullptr if unknown. +const char * nvme_status_to_str(uint16_t status); + +// Return error message for NVMe status SCT/SC fields or explanatory message if unknown. +const char * nvme_status_to_info_str(char * buf, size_t bufsize, uint16_t status); + +// Version of above for fixed size buffers. +template <size_t SIZE> +inline const char * nvme_status_to_info_str(char (& buf)[SIZE], unsigned status) + { return nvme_status_to_info_str(buf, SIZE, status); } + +#endif // NVMECMDS_H |