diff options
Diffstat (limited to '')
-rw-r--r-- | nvme-ioctl.c | 1157 |
1 files changed, 0 insertions, 1157 deletions
diff --git a/nvme-ioctl.c b/nvme-ioctl.c deleted file mode 100644 index 5a57a25..0000000 --- a/nvme-ioctl.c +++ /dev/null @@ -1,1157 +0,0 @@ -#include <assert.h> -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <errno.h> - -#include <getopt.h> -#include <fcntl.h> -#include <inttypes.h> -#include <locale.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <math.h> - -#include "nvme-ioctl.h" - -static int nvme_verify_chr(int fd) -{ - static struct stat nvme_stat; - int err = fstat(fd, &nvme_stat); - - if (err < 0) { - perror("fstat"); - return errno; - } - if (!S_ISCHR(nvme_stat.st_mode)) { - fprintf(stderr, - "Error: requesting reset on non-controller handle\n"); - return ENOTBLK; - } - return 0; -} - -int nvme_subsystem_reset(int fd) -{ - int ret; - - ret = nvme_verify_chr(fd); - if (ret) - return ret; - return ioctl(fd, NVME_IOCTL_SUBSYS_RESET); -} - -int nvme_reset_controller(int fd) -{ - int ret; - - ret = nvme_verify_chr(fd); - if (ret) - return ret; - return ioctl(fd, NVME_IOCTL_RESET); -} - -int nvme_ns_rescan(int fd) -{ - int ret; - - ret = nvme_verify_chr(fd); - if (ret) - return ret; - return ioctl(fd, NVME_IOCTL_RESCAN); -} - -int nvme_get_nsid(int fd) -{ - static struct stat nvme_stat; - int err = fstat(fd, &nvme_stat); - - if (err < 0) - return err; - - return ioctl(fd, NVME_IOCTL_ID); -} - -int nvme_submit_passthru(int fd, unsigned long ioctl_cmd, - struct nvme_passthru_cmd *cmd) -{ - return ioctl(fd, ioctl_cmd, cmd); -} - -int nvme_submit_admin_passthru(int fd, struct nvme_passthru_cmd *cmd) -{ - return ioctl(fd, NVME_IOCTL_ADMIN_CMD, cmd); -} - -int nvme_submit_io_passthru(int fd, struct nvme_passthru_cmd *cmd) -{ - return ioctl(fd, NVME_IOCTL_IO_CMD, cmd); -} - -int nvme_passthru(int fd, unsigned long ioctl_cmd, __u8 opcode, - __u8 flags, __u16 rsvd, - __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10, __u32 cdw11, - __u32 cdw12, __u32 cdw13, __u32 cdw14, __u32 cdw15, - __u32 data_len, void *data, __u32 metadata_len, - void *metadata, __u32 timeout_ms, __u32 *result) -{ - struct nvme_passthru_cmd cmd = { - .opcode = opcode, - .flags = flags, - .rsvd1 = rsvd, - .nsid = nsid, - .cdw2 = cdw2, - .cdw3 = cdw3, - .metadata = (__u64)(uintptr_t) metadata, - .addr = (__u64)(uintptr_t) data, - .metadata_len = metadata_len, - .data_len = data_len, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw13 = cdw13, - .cdw14 = cdw14, - .cdw15 = cdw15, - .timeout_ms = timeout_ms, - .result = 0, - }; - int err; - - err = nvme_submit_passthru(fd, ioctl_cmd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_io(int fd, __u8 opcode, __u32 nsid, __u64 slba, __u16 nblocks, - __u16 control, __u32 dsmgmt, __u32 reftag, __u16 apptag, - __u16 appmask, __u64 storage_tag, void *data, __u32 buffer_size, - void *metadata, __u32 mbuffer_size) -{ - struct nvme_passthru_cmd cmd = { - .opcode = opcode, - .nsid = nsid, - .metadata = (__u64)(uintptr_t) metadata, - .addr = (__u64)(uintptr_t) data, - .cdw2 = storage_tag & 0xffffffff, - .cdw3 = (storage_tag >> 32) & 0xffff, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = nblocks | (control << 16), - .cdw13 = dsmgmt, - .cdw14 = reftag, - .cdw15 = apptag | (appmask << 16), - .data_len = buffer_size, - .metadata_len = mbuffer_size, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_verify(int fd, __u32 nsid, __u64 slba, __u16 nblocks, - __u16 control, __u32 reftag, __u16 apptag, __u16 appmask, - __u64 storage_tag) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_verify, - .nsid = nsid, - .cdw2 = storage_tag & 0xffffffff, - .cdw3 = (storage_tag >> 32) & 0xffff, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = nblocks | (control << 16), - .cdw14 = reftag, - .cdw15 = apptag | (appmask << 16), - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_passthru_io(int fd, __u8 opcode, __u8 flags, __u16 rsvd, - __u32 nsid, __u32 cdw2, __u32 cdw3, __u32 cdw10, - __u32 cdw11, __u32 cdw12, __u32 cdw13, __u32 cdw14, - __u32 cdw15, __u32 data_len, void *data, - __u32 metadata_len, void *metadata, __u32 timeout_ms) -{ - return nvme_passthru(fd, NVME_IOCTL_IO_CMD, opcode, flags, rsvd, nsid, - cdw2, cdw3, cdw10, cdw11, cdw12, cdw13, cdw14, - cdw15, data_len, data, metadata_len, metadata, - timeout_ms, NULL); -} - -int nvme_write_zeros(int fd, __u32 nsid, __u64 slba, __u16 nlb, - __u16 control, __u32 reftag, __u16 apptag, __u16 appmask, - __u64 storage_tag) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_write_zeroes, - .nsid = nsid, - .cdw2 = storage_tag & 0xffffffff, - .cdw3 = (storage_tag >> 32) & 0xffff, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = nlb | (control << 16), - .cdw14 = reftag, - .cdw15 = apptag | (appmask << 16), - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_write_uncorrectable(int fd, __u32 nsid, __u64 slba, __u16 nlb) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_write_uncor, - .nsid = nsid, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = nlb, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_flush(int fd, __u32 nsid) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_flush, - .nsid = nsid, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_dsm(int fd, __u32 nsid, __u32 cdw11, struct nvme_dsm_range *dsm, - __u16 nr_ranges) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_dsm, - .nsid = nsid, - .addr = (__u64)(uintptr_t) dsm, - .data_len = nr_ranges * sizeof(*dsm), - .cdw10 = nr_ranges - 1, - .cdw11 = cdw11, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -struct nvme_dsm_range *nvme_setup_dsm_range(int *ctx_attrs, int *llbas, - unsigned long long *slbas, - __u16 nr_ranges) -{ - int i; - struct nvme_dsm_range *dsm = malloc(nr_ranges * sizeof(*dsm)); - - if (!dsm) { - fprintf(stderr, "malloc: %s\n", strerror(errno)); - return NULL; - } - for (i = 0; i < nr_ranges; i++) { - dsm[i].cattr = cpu_to_le32(ctx_attrs[i]); - dsm[i].nlb = cpu_to_le32(llbas[i]); - dsm[i].slba = cpu_to_le64(slbas[i]); - } - return dsm; -} - -int nvme_copy(int fd, __u32 nsid, struct nvme_copy_range *copy, __u64 sdlba, - __u16 nr, __u8 prinfor, __u8 prinfow, __u8 dtype, __u16 dspec, - __u8 format, int lr, int fua, __u32 ilbrt, __u16 lbatm, - __u16 lbat) -{ - __u32 cdw12 = ((nr - 1) & 0xff) | ((format & 0xf) << 8) | - ((prinfor & 0xf) << 12) | ((dtype & 0xf) << 20) | - ((prinfow & 0xf) << 26) | ((fua & 0x1) << 30) | - ((lr & 0x1) << 31); - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_copy, - .nsid = nsid, - .addr = (__u64)(uintptr_t)copy, - .data_len = nr * sizeof(*copy), - .cdw10 = sdlba & 0xffffffff, - .cdw11 = sdlba >> 32, - .cdw12 = cdw12, - .cdw13 = (dspec & 0xffff) << 16, - .cdw14 = ilbrt, - .cdw15 = (lbatm << 16) | lbat, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -struct nvme_copy_range *nvme_setup_copy_range(int *nlbs, unsigned long long *slbas, - int *eilbrts, int *elbatms, int *elbats, __u16 nr) -{ - struct nvme_copy_range *copy = malloc(nr * sizeof(*copy)); - if (!copy) { - fprintf(stderr, "malloc: %s\n", strerror(errno)); - return NULL; - } - - for (int i = 0; i < nr; i++) { - copy[i].nlb = cpu_to_le16(nlbs[i]); - copy[i].slba = cpu_to_le64(slbas[i]); - copy[i].eilbrt = cpu_to_le32(eilbrts[i]); - copy[i].elbatm = cpu_to_le16(elbatms[i]); - copy[i].elbat = cpu_to_le16(elbats[i]); - } - - return copy; -} - -int nvme_resv_acquire(int fd, __u32 nsid, __u8 rtype, __u8 racqa, - bool iekey, __u64 crkey, __u64 nrkey) -{ - __le64 payload[2] = { cpu_to_le64(crkey), cpu_to_le64(nrkey) }; - __u32 cdw10 = (racqa & 0x7) | (iekey ? 1 << 3 : 0) | rtype << 8; - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_acquire, - .nsid = nsid, - .cdw10 = cdw10, - .addr = (__u64)(uintptr_t) (payload), - .data_len = sizeof(payload), - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_resv_register(int fd, __u32 nsid, __u8 rrega, __u8 cptpl, - bool iekey, __u64 crkey, __u64 nrkey) -{ - __le64 payload[2] = { cpu_to_le64(crkey), cpu_to_le64(nrkey) }; - __u32 cdw10 = (rrega & 0x7) | (iekey ? 1 << 3 : 0) | cptpl << 30; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_register, - .nsid = nsid, - .cdw10 = cdw10, - .addr = (__u64)(uintptr_t) (payload), - .data_len = sizeof(payload), - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_resv_release(int fd, __u32 nsid, __u8 rtype, __u8 rrela, - bool iekey, __u64 crkey) -{ - __le64 payload[1] = { cpu_to_le64(crkey) }; - __u32 cdw10 = (rrela & 0x7) | (iekey ? 1 << 3 : 0) | rtype << 8; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_release, - .nsid = nsid, - .cdw10 = cdw10, - .addr = (__u64)(uintptr_t) (payload), - .data_len = sizeof(payload), - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_resv_report(int fd, __u32 nsid, __u32 numd, __u32 cdw11, void *data) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_cmd_resv_report, - .nsid = nsid, - .cdw10 = numd, - .cdw11 = cdw11, - .addr = (__u64)(uintptr_t) data, - .data_len = (numd + 1) << 2, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_identify13(int fd, __u32 nsid, __u32 cdw10, __u32 cdw11, void *data) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_identify, - .nsid = nsid, - .addr = (__u64)(uintptr_t) data, - .data_len = NVME_IDENTIFY_DATA_SIZE, - .cdw10 = cdw10, - .cdw11 = cdw11, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_identify(int fd, __u32 nsid, __u32 cdw10, void *data) -{ - return nvme_identify13(fd, nsid, cdw10, 0, data); -} - -int nvme_identify_ctrl(int fd, void *data) -{ - memset(data, 0, sizeof(struct nvme_id_ctrl)); - return nvme_identify(fd, 0, 1, data); -} - -int nvme_identify_ns(int fd, __u32 nsid, bool present, void *data) -{ - int cns = present ? NVME_ID_CNS_NS_PRESENT : NVME_ID_CNS_NS; - - return nvme_identify(fd, nsid, cns, data); -} - -int nvme_identify_ns_list_csi(int fd, __u32 nsid, __u8 csi, bool all, void *data) -{ - int cns; - - if (csi) { - cns = all ? NVME_ID_CNS_CSI_NS_PRESENT_LIST : NVME_ID_CNS_CSI_NS_ACTIVE_LIST; - } else { - cns = all ? NVME_ID_CNS_NS_PRESENT_LIST : NVME_ID_CNS_NS_ACTIVE_LIST; - } - - return nvme_identify13(fd, nsid, cns, csi << 24, data); -} - -int nvme_cmd_set_independent_identify_ns(int fd, __u32 nsid, void *data) -{ - return nvme_identify(fd, nsid, NVME_ID_CNS_CS_INDEPENDENT_ID_NS, data); -} - -int nvme_identify_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data) -{ - int cns = nsid ? NVME_ID_CNS_CTRL_NS_LIST : NVME_ID_CNS_CTRL_LIST; - - return nvme_identify(fd, nsid, (cntid << 16) | cns, data); -} - -int nvme_identify_primary_ctrl_caps(int fd, void *data) -{ - return nvme_identify(fd, 0, NVME_ID_CNS_PRIMARY_CTRL_CAPS, data); -} - -int nvme_identify_secondary_ctrl_list(int fd, __u32 nsid, __u16 cntid, void *data) -{ - return nvme_identify(fd, nsid, (cntid << 16) | NVME_ID_CNS_SCNDRY_CTRL_LIST, data); -} - -int nvme_identify_ns_descs(int fd, __u32 nsid, void *data) -{ - - return nvme_identify(fd, nsid, NVME_ID_CNS_NS_DESC_LIST, data); -} - -int nvme_identify_nvmset(int fd, __u16 nvmset_id, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_NVMSET_LIST, nvmset_id, data); -} - -int nvme_identify_ns_granularity(int fd, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_NS_GRANULARITY, 0, data); -} - -int nvme_identify_uuid(int fd, void *data) -{ - return nvme_identify(fd, 0, NVME_ID_CNS_UUID_LIST, data); -} - -int nvme_identify_ctrl_nvm(int fd, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_CSI_ID_CTRL, 0, data); -} - -int nvme_zns_identify_ns(int fd, __u32 nsid, void *data) -{ - return nvme_identify13(fd, nsid, NVME_ID_CNS_CSI_ID_NS, 2 << 24, data); -} - -int nvme_zns_identify_ctrl(int fd, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_CSI_ID_CTRL, 2 << 24, data); -} - -int nvme_identify_iocs(int fd, __u16 cntid, void *data) -{ - return nvme_identify(fd, 0, (cntid << 16) | NVME_ID_CNS_CSI, data); -} - -int nvme_identify_domain_list(int fd, __u16 dom_id, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_DOMAIN_LIST, dom_id, data); -} - -int nvme_identify_endurance_group_list(int fd, __u16 endgrp_id, void *data) -{ - return nvme_identify13(fd, 0, NVME_ID_CNS_ENDURANCE_GROUP_ID, endgrp_id, data); -} - -int nvme_get_log14(int fd, __u32 nsid, __u8 log_id, __u8 lsp, __u64 lpo, - __u16 lsi, bool rae, __u8 uuid_ix, __u8 csi, bool ot, - __u32 data_len, void *data) -{ - __u32 numd = (data_len >> 2) - 1; - __u16 numdu = numd >> 16, numdl = numd & 0xffff; - __u32 cdw10 = log_id | (numdl << 16) | (rae ? 1 << 15 : 0) | lsp << 8; - __u32 cdw14 = uuid_ix | (ot ? 1 << 23 : 0) | csi << 24; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_get_log_page, - .nsid = nsid, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - .cdw10 = cdw10, - .cdw11 = numdu | (lsi << 16), - .cdw12 = lpo & 0xffffffff, - .cdw13 = lpo >> 32, - .cdw14 = cdw14, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_get_log13(int fd, __u32 nsid, __u8 log_id, __u8 lsp, - __u64 lpo, __u16 lsi, bool rae, __u32 data_len, - void *data) -{ - return nvme_get_log14(fd, nsid, log_id, lsp, lpo, lsi, rae, 0, - 0, false, data_len, data); -} - -int nvme_get_log(int fd, __u32 nsid, __u8 log_id, bool rae, - __u8 lsp, __u32 data_len, void *data) -{ - __u32 offset = 0, xfer_len = data_len; - void *ptr = data; - int ret; - - /* - * 4k is the smallest possible transfer unit, so by - * restricting ourselves for 4k transfers we avoid having - * to check the MDTS value of the controller. - */ - do { - xfer_len = data_len - offset; - if (xfer_len > 4096) - xfer_len = 4096; - - ret = nvme_get_log13(fd, nsid, log_id, lsp, - offset, 0, rae, xfer_len, ptr); - if (ret) - return ret; - - offset += xfer_len; - ptr += xfer_len; - } while (offset < data_len); - - return 0; -} - -int nvme_get_telemetry_log(int fd, void *lp, int generate_report, - int ctrl_init, size_t log_page_size, __u64 offset) -{ - if (ctrl_init) - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_CTRL, - NVME_NO_LOG_LSP, offset, - 0, 1, log_page_size, lp); - if (generate_report) - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_HOST, - NVME_TELEM_LSP_CREATE, offset, - 0, 1, log_page_size, lp); - else - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_TELEMETRY_HOST, - NVME_NO_LOG_LSP, offset, - 0, 1, log_page_size, lp); -} - -int nvme_fw_log(int fd, struct nvme_firmware_log_page *fw_log) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_FW_SLOT, true, - NVME_NO_LOG_LSP, sizeof(*fw_log), fw_log); -} - -int nvme_changed_ns_list_log(int fd, struct nvme_changed_ns_list_log *changed_ns_list_log) -{ - return nvme_get_log(fd, 0, NVME_LOG_CHANGED_NS, true, - NVME_NO_LOG_LSP, sizeof(changed_ns_list_log->log), - changed_ns_list_log->log); -} - -int nvme_error_log(int fd, int entries, struct nvme_error_log_page *err_log) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_ERROR, false, - NVME_NO_LOG_LSP, entries * sizeof(*err_log), err_log); -} - -int nvme_endurance_log(int fd, __u16 group_id, struct nvme_endurance_group_log *endurance_log) -{ - return nvme_get_log13(fd, 0, NVME_LOG_ENDURANCE_GROUP, 0, 0, group_id, 0, - sizeof(*endurance_log), endurance_log); -} - -int nvme_smart_log(int fd, __u32 nsid, struct nvme_smart_log *smart_log) -{ - return nvme_get_log(fd, nsid, NVME_LOG_SMART, false, - NVME_NO_LOG_LSP, sizeof(*smart_log), smart_log); -} - -int nvme_ana_log(int fd, void *ana_log, size_t ana_log_len, int rgo) -{ - return nvme_get_log13(fd, NVME_NSID_ALL, NVME_LOG_ANA, rgo, 0, 0, - true, ana_log_len, ana_log); -} - -int nvme_self_test_log(int fd, __u32 size, struct nvme_self_test_log *self_test_log) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_DEVICE_SELF_TEST, false, - NVME_NO_LOG_LSP, size, self_test_log); -} - -int nvme_effects_log(int fd, struct nvme_effects_log_page *effects_log) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_CMD_EFFECTS, false, - NVME_NO_LOG_LSP, sizeof(*effects_log), effects_log); -} - -int nvme_supported_log(int fd, struct nvme_support_log_pages *supports) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_SUPPORTED_PAGES, false, - NVME_NO_LOG_LSP, sizeof(*supports), supports); -} - -int nvme_discovery_log(int fd, struct nvmf_disc_rsp_page_hdr *log, __u32 size) -{ - return nvme_get_log(fd, 0, NVME_LOG_DISC, false, NVME_NO_LOG_LSP, size, log); -} - -int nvme_sanitize_log(int fd, bool rae, struct nvme_sanitize_log_page *sanitize_log) -{ - return nvme_get_log(fd, 0, NVME_LOG_SANITIZE, rae, - NVME_NO_LOG_LSP, sizeof(*sanitize_log), sanitize_log); -} - -int nvme_predictable_latency_per_nvmset_log(int fd, - __u16 nvmset_id, - struct nvme_predlat_per_nvmset_log_page *plpns_log) -{ - return nvme_get_log13(fd, NVME_NSID_ALL, - NVME_LOG_PRELAT_PER_NVMSET, 0, 0, nvmset_id, - false, sizeof(*plpns_log), plpns_log); -} - -int nvme_predictable_latency_event_agg_log(int fd, - void *pea_log, bool rae, __u32 size) -{ - return nvme_get_log(fd, NVME_NSID_ALL, - NVME_LOG_PRELAT_EVENT_AGG, rae, NVME_NO_LOG_LSP, - size, pea_log); -} - -int nvme_persistent_event_log(int fd, __u8 action, __u32 size, - void *pevent_log_info) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_PERSISTENT_EVENT, - false, action, size, pevent_log_info); -} - -int nvme_endurance_group_event_agg_log(int fd, - void *endurance_log, bool rae, __u32 size) -{ - return nvme_get_log(fd, NVME_NSID_ALL, - NVME_LOG_ENDURANCE_GROUP_EVENT_AGG, rae, NVME_NO_LOG_LSP, - size, endurance_log); -} - -int nvme_lba_status_log(int fd, void *lba_status, bool rae, - __u32 size) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_LBA_STATUS, - rae, NVME_NO_LOG_LSP, size, lba_status); -} - -int nvme_resv_notif_log(int fd, struct nvme_resv_notif_log *resv) -{ - return nvme_get_log(fd, 0, NVME_LOG_RESERVATION, false, - NVME_NO_LOG_LSP, sizeof(*resv), resv); -} - -int nvme_boot_part_log(int fd, __u8 lsp, void *data, __u32 size) -{ - return nvme_get_log(fd, NVME_NSID_ALL, NVME_LOG_BOOT_PARTITION, - false, lsp, size, data); -} - -int nvme_fid_support_effects_log(int fd, struct nvme_fid_support_effects *fid_log) -{ - return nvme_get_log(fd, 0, NVME_LOG_FID_SUPPORT_EFFECTS, false, - NVME_NO_LOG_LSP, sizeof(*fid_log), fid_log); -} - -int nvme_feature(int fd, __u8 opcode, __u32 nsid, __u32 cdw10, __u32 cdw11, - __u32 cdw12, __u32 cdw14, __u32 data_len, void *data, __u32 *result) -{ - struct nvme_admin_cmd cmd = { - .opcode = opcode, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw14 = cdw14, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_set_feature(int fd, __u32 nsid, __u8 fid, __u32 value, __u32 cdw12, - bool save, __u8 uuid_index, __u32 data_len, void *data, __u32 *result) -{ - __u32 cdw10 = fid | (save ? 1 << 31 : 0); - __u32 cdw14 = uuid_index; - - return nvme_feature(fd, nvme_admin_set_features, nsid, cdw10, value, - cdw12, cdw14, data_len, data, result); -} - - -int nvme_get_property(int fd, int offset, uint64_t *value) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_fabrics_command, - .nsid = nvme_fabrics_type_property_get, - .cdw10 = is_64bit_reg(offset), - .cdw11 = offset, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && value) - *value = cmd.result; - return err; -} - -int nvme_get_properties(int fd, void **pbar) -{ - int offset; - uint64_t value; - int err, size = getpagesize(); - - *pbar = malloc(size); - if (!*pbar) { - fprintf(stderr, "malloc: %s\n", strerror(errno)); - return -ENOMEM; - } - - memset(*pbar, 0xff, size); - for (offset = NVME_REG_CAP; offset <= NVME_REG_CMBSZ;) { - err = nvme_get_property(fd, offset, &value); - if (err > 0 && (err & 0xff) == NVME_SC_INVALID_FIELD) { - err = 0; - value = -1; - } else if (err) { - free(*pbar); - break; - } - if (is_64bit_reg(offset)) { - *(uint64_t *)(*pbar + offset) = value; - offset += 8; - } else { - *(uint32_t *)(*pbar + offset) = value; - offset += 4; - } - } - - return err; -} - -int nvme_set_property(int fd, int offset, uint64_t value) -{ - struct nvme_passthru_cmd cmd = { - .opcode = nvme_fabrics_command, - .nsid = nvme_fabrics_type_property_set, - .cdw10 = is_64bit_reg(offset), - .cdw11 = offset, - .cdw12 = value & 0xffffffff, - .cdw13 = value >> 32, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_get_feature(int fd, __u32 nsid, __u8 fid, __u8 sel, __u32 cdw11, - __u8 uuid_index, __u32 data_len, void *data, __u32 *result) -{ - __u32 cdw10 = fid | sel << 8; - __u32 cdw14 = uuid_index; - - return nvme_feature(fd, nvme_admin_get_features, nsid, cdw10, cdw11, - 0, cdw14, data_len, data, result); -} - -int nvme_format(int fd, __u32 nsid, __u8 lbaf, __u8 ses, __u8 pi, - __u8 pil, __u8 ms, __u32 timeout) -{ - __u8 lbafl = lbaf & 0xf; - __u8 lbafu = (lbaf >> 4) & 0x3; - __u32 cdw10 = lbafl | ms << 4 | pi << 5 | pil << 8 | ses << 9 | - lbafu << 12; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_format_nvm, - .nsid = nsid, - .cdw10 = cdw10, - .timeout_ms = timeout, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_ns_create(int fd, __u64 nsze, __u64 ncap, __u8 flbas, __u8 dps, - __u8 nmic, __u32 anagrpid, __u16 nvmsetid, __u8 csi, - __u32 timeout, __u32 *result) -{ - struct nvme_id_ns ns = { - .nsze = cpu_to_le64(nsze), - .ncap = cpu_to_le64(ncap), - .flbas = flbas, - .dps = dps, - .nmic = nmic, - .anagrpid = anagrpid, - .nvmsetid = nvmsetid, - }; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_ns_mgmt, - .addr = (__u64)(uintptr_t) ((void *)&ns), - .cdw10 = 0, - .cdw11 = csi << 24, - .data_len = 0x1000, - .timeout_ms = timeout, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_ns_delete(int fd, __u32 nsid, __u32 timeout) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_ns_mgmt, - .nsid = nsid, - .cdw10 = 1, - .timeout_ms = timeout, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_ns_attachment(int fd, __u32 nsid, __u16 num_ctrls, __u16 *ctrlist, - bool attach) -{ - struct nvme_controller_list cntlist = { - .num = cpu_to_le16(num_ctrls), - }; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_ns_attach, - .nsid = nsid, - .addr = (__u64)(uintptr_t)&cntlist, - .cdw10 = attach ? 0 : 1, - .data_len = 0x1000, - }; - int i; - - for (i = 0; i < num_ctrls; i++) - cntlist.identifier[i] = cpu_to_le16(ctrlist[i]); - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_fw_download(int fd, __u32 offset, __u32 data_len, void *data) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_download_fw, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - .cdw10 = (data_len >> 2) - 1, - .cdw11 = offset >> 2, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_fw_commit(int fd, __u8 slot, __u8 action, __u8 bpid, __u32 *result) -{ - int err; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_activate_fw, - .cdw10 = (bpid << 31) | (action << 3) | slot, - }; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_sec_send(int fd, __u32 nsid, __u8 nssf, __u16 spsp, - __u8 secp, __u32 data_len, void *data) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_security_send, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - .nsid = nsid, - .cdw10 = secp << 24 | spsp << 8 | nssf, - .cdw11 = data_len, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_sec_recv(int fd, __u32 nsid, __u8 nssf, __u16 spsp, - __u8 secp, __u32 al, __u32 data_len, void *data) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_security_recv, - .nsid = nsid, - .cdw10 = secp << 24 | spsp << 8 | nssf, - .cdw11 = al, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_lockdown(int fd, __u8 scp, __u8 prhbt, __u8 ifc, __u8 ofi, - __u8 uuid) -{ - __u32 cdw10 = ofi << 8 | (ifc & 0x3) << 5 | (prhbt & 0x1) << 4 | (scp & 0xF); - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_lockdown_cmd, - .cdw10 = cdw10, - .cdw14 = uuid & 0x3F, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_get_lba_status(int fd, __u32 namespace_id, __u64 slba, __u32 mndw, - __u8 atype, __u16 rl, void *data, __u32 timeout_ms) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_get_lba_status, - .nsid = namespace_id, - .addr = (__u64)(uintptr_t) data, - .data_len = (mndw + 1) * 4, - .cdw10 = slba & 0xffffffff, - .cdw11 = slba >> 32, - .cdw12 = mndw, - .cdw13 = (atype << 24) | rl, - .timeout_ms = timeout_ms, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_dir_send(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper, - __u32 data_len, __u32 dw12, void *data, __u32 *result) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_directive_send, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - .nsid = nsid, - .cdw10 = data_len? (data_len >> 2) - 1 : 0, - .cdw11 = dspec << 16 | dtype << 8 | doper, - .cdw12 = dw12, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_dir_recv(int fd, __u32 nsid, __u16 dspec, __u8 dtype, __u8 doper, - __u32 data_len, __u32 dw12, void *data, __u32 *result) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_directive_recv, - .addr = (__u64)(uintptr_t) data, - .data_len = data_len, - .nsid = nsid, - .cdw10 = data_len? (data_len >> 2) - 1 : 0, - .cdw11 = dspec << 16 | dtype << 8 | doper, - .cdw12 = dw12, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_cap_mgmt(int fd, __u8 op, __u16 element_id, __u32 dw11, - __u32 dw12, __u32 *result) -{ - int err; - __u32 dw10 = op | element_id << 16; - - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_capacity_mgmt, - .cdw10 = dw10, - .cdw11 = dw11, - .cdw12 = dw12, - }; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} - -int nvme_sanitize(int fd, __u8 sanact, __u8 ause, __u8 owpass, __u8 oipbp, - __u8 no_dealloc, __u32 ovrpat) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_sanitize_nvm, - .cdw10 = no_dealloc << 9 | oipbp << 8 | - owpass << NVME_SANITIZE_OWPASS_SHIFT | - ause << 3 | sanact, - .cdw11 = ovrpat, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_self_test_start(int fd, __u32 nsid, __u8 stc) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_dev_self_test, - .nsid = nsid, - .cdw10 = stc, - }; - - return nvme_submit_admin_passthru(fd, &cmd); -} - -int nvme_virtual_mgmt(int fd, __u32 cdw10, __u32 cdw11, __u32 *result) -{ - struct nvme_admin_cmd cmd = { - .opcode = nvme_admin_virtual_mgmt, - .cdw10 = cdw10, - .cdw11 = cdw11, - }; - int err; - - err = nvme_submit_admin_passthru(fd, &cmd); - if (!err && result) - *result = cmd.result; - - return err; -} - -int nvme_zns_mgmt_send(int fd, __u32 nsid, __u64 slba, bool select_all, - __u32 timeout, enum nvme_zns_send_action zsa, __u32 data_len, - void *data) -{ - __u32 cdw10 = slba & 0xffffffff; - __u32 cdw11 = slba >> 32; - __u32 cdw13 = zsa | (!!select_all) << 8; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_zns_cmd_mgmt_send, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw13 = cdw13, - .addr = (__u64)(uintptr_t)data, - .data_len = data_len, - .timeout_ms = timeout, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_zns_mgmt_recv(int fd, __u32 nsid, __u64 slba, - enum nvme_zns_recv_action zra, __u8 zrasf, - bool zras_feat, __u32 data_len, void *data) -{ - __u32 cdw10 = slba & 0xffffffff; - __u32 cdw11 = slba >> 32; - __u32 cdw12 = (data_len >> 2) - 1; - __u32 cdw13 = zra | zrasf << 8 | zras_feat << 16; - - struct nvme_passthru_cmd cmd = { - .opcode = nvme_zns_cmd_mgmt_recv, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw13 = cdw13, - .addr = (__u64)(uintptr_t)data, - .data_len = data_len, - }; - - return nvme_submit_io_passthru(fd, &cmd); -} - -int nvme_zns_report_zones(int fd, __u32 nsid, __u64 slba, bool extended, - enum nvme_zns_report_options opts, bool partial, - __u32 data_len, void *data) -{ - enum nvme_zns_recv_action zra; - - if (extended) - zra = NVME_ZNS_ZRA_EXTENDED_REPORT_ZONES; - else - zra = NVME_ZNS_ZRA_REPORT_ZONES; - - return nvme_zns_mgmt_recv(fd, nsid, slba, zra, opts, partial, - data_len, data); -} - -int nvme_zns_append(int fd, __u32 nsid, __u64 zslba, __u16 nlb, __u16 control, - __u32 ilbrt, __u16 lbat, __u16 lbatm, __u32 data_len, - void *data, __u32 metadata_len, void *metadata, - __u64 *result) -{ - __u32 cdw10 = zslba & 0xffffffff; - __u32 cdw11 = zslba >> 32; - __u32 cdw12 = nlb | (control << 16); - __u32 cdw14 = ilbrt; - __u32 cdw15 = lbat | (lbatm << 16); - - struct nvme_passthru_cmd64 cmd = { - .opcode = nvme_zns_cmd_append, - .nsid = nsid, - .cdw10 = cdw10, - .cdw11 = cdw11, - .cdw12 = cdw12, - .cdw14 = cdw14, - .cdw15 = cdw15, - .metadata = (__u64)(uintptr_t)metadata, - .addr = (__u64)(uintptr_t)data, - .metadata_len = metadata_len, - .data_len = data_len, - }; - - int err; - - err = ioctl(fd, NVME_IOCTL_IO64_CMD, &cmd); - if (!err && result) - *result = cmd.result; - return err; -} |