Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 5 Jun 2025 21:06:33 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: 60159a98a837 - main - nvme: Move opcode and status code tables from base CAM to nvme_util.c
Message-ID:  <202506052106.555L6XBV089396@gitrepo.freebsd.org>

next in thread | raw e-mail | index | archive | help
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=60159a98a83747e539eb14c6a0eaaa1875e2cacc

commit 60159a98a83747e539eb14c6a0eaaa1875e2cacc
Author:     John Baldwin <jhb@FreeBSD.org>
AuthorDate: 2025-06-05 21:03:01 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2025-06-05 21:03:01 +0000

    nvme: Move opcode and status code tables from base CAM to nvme_util.c
    
    This makes it possible to share these tables with the nvme(4) driver
    in custom kernels that do not include any CAM support, only nvd(4).
    
    Reviewed by:    imp
    Sponsored by:   Chelsio Communications
    Differential Revision:  https://reviews.freebsd.org/D50685
---
 sys/cam/nvme/nvme_all.c  | 224 ---------------------------------------------
 sys/cam/nvme/nvme_all.h  |   2 -
 sys/conf/files           |   2 +-
 sys/dev/nvme/nvme.h      |   4 +
 sys/dev/nvme/nvme_util.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 236 insertions(+), 227 deletions(-)

diff --git a/sys/cam/nvme/nvme_all.c b/sys/cam/nvme/nvme_all.c
index 4145aa16ed49..2ab8ae5340c6 100644
--- a/sys/cam/nvme/nvme_all.c
+++ b/sys/cam/nvme/nvme_all.c
@@ -60,168 +60,6 @@
 #include <cam/cam_xpt_internal.h>
 #endif
 
-/* XXX: This duplicates lists in nvme_qpair.c. */
-
-#define OPC_ENTRY(x)		[NVME_OPC_ ## x] = #x
-
-static const char *admin_opcode[256] = {
-	OPC_ENTRY(DELETE_IO_SQ),
-	OPC_ENTRY(CREATE_IO_SQ),
-	OPC_ENTRY(GET_LOG_PAGE),
-	OPC_ENTRY(DELETE_IO_CQ),
-	OPC_ENTRY(CREATE_IO_CQ),
-	OPC_ENTRY(IDENTIFY),
-	OPC_ENTRY(ABORT),
-	OPC_ENTRY(SET_FEATURES),
-	OPC_ENTRY(GET_FEATURES),
-	OPC_ENTRY(ASYNC_EVENT_REQUEST),
-	OPC_ENTRY(NAMESPACE_MANAGEMENT),
-	OPC_ENTRY(FIRMWARE_ACTIVATE),
-	OPC_ENTRY(FIRMWARE_IMAGE_DOWNLOAD),
-	OPC_ENTRY(DEVICE_SELF_TEST),
-	OPC_ENTRY(NAMESPACE_ATTACHMENT),
-	OPC_ENTRY(KEEP_ALIVE),
-	OPC_ENTRY(DIRECTIVE_SEND),
-	OPC_ENTRY(DIRECTIVE_RECEIVE),
-	OPC_ENTRY(VIRTUALIZATION_MANAGEMENT),
-	OPC_ENTRY(NVME_MI_SEND),
-	OPC_ENTRY(NVME_MI_RECEIVE),
-	OPC_ENTRY(CAPACITY_MANAGEMENT),
-	OPC_ENTRY(LOCKDOWN),
-	OPC_ENTRY(DOORBELL_BUFFER_CONFIG),
-	OPC_ENTRY(FABRICS_COMMANDS),
-	OPC_ENTRY(FORMAT_NVM),
-	OPC_ENTRY(SECURITY_SEND),
-	OPC_ENTRY(SECURITY_RECEIVE),
-	OPC_ENTRY(SANITIZE),
-	OPC_ENTRY(GET_LBA_STATUS),
-};
-
-static const char *nvm_opcode[256] = {
-	OPC_ENTRY(FLUSH),
-	OPC_ENTRY(WRITE),
-	OPC_ENTRY(READ),
-	OPC_ENTRY(WRITE_UNCORRECTABLE),
-	OPC_ENTRY(COMPARE),
-	OPC_ENTRY(WRITE_ZEROES),
-	OPC_ENTRY(DATASET_MANAGEMENT),
-	OPC_ENTRY(VERIFY),
-	OPC_ENTRY(RESERVATION_REGISTER),
-	OPC_ENTRY(RESERVATION_REPORT),
-	OPC_ENTRY(RESERVATION_ACQUIRE),
-	OPC_ENTRY(RESERVATION_RELEASE),
-	OPC_ENTRY(COPY),
-};
-
-#define SC_ENTRY(x)		[NVME_SC_ ## x] = #x
-
-static const char *generic_status[256] = {
-	SC_ENTRY(SUCCESS),
-	SC_ENTRY(INVALID_OPCODE),
-	SC_ENTRY(INVALID_FIELD),
-	SC_ENTRY(COMMAND_ID_CONFLICT),
-	SC_ENTRY(DATA_TRANSFER_ERROR),
-	SC_ENTRY(ABORTED_POWER_LOSS),
-	SC_ENTRY(INTERNAL_DEVICE_ERROR),
-	SC_ENTRY(ABORTED_BY_REQUEST),
-	SC_ENTRY(ABORTED_SQ_DELETION),
-	SC_ENTRY(ABORTED_FAILED_FUSED),
-	SC_ENTRY(ABORTED_MISSING_FUSED),
-	SC_ENTRY(INVALID_NAMESPACE_OR_FORMAT),
-	SC_ENTRY(COMMAND_SEQUENCE_ERROR),
-	SC_ENTRY(INVALID_SGL_SEGMENT_DESCR),
-	SC_ENTRY(INVALID_NUMBER_OF_SGL_DESCR),
-	SC_ENTRY(DATA_SGL_LENGTH_INVALID),
-	SC_ENTRY(METADATA_SGL_LENGTH_INVALID),
-	SC_ENTRY(SGL_DESCRIPTOR_TYPE_INVALID),
-	SC_ENTRY(INVALID_USE_OF_CMB),
-	SC_ENTRY(PRP_OFFET_INVALID),
-	SC_ENTRY(ATOMIC_WRITE_UNIT_EXCEEDED),
-	SC_ENTRY(OPERATION_DENIED),
-	SC_ENTRY(SGL_OFFSET_INVALID),
-	SC_ENTRY(HOST_ID_INCONSISTENT_FORMAT),
-	SC_ENTRY(KEEP_ALIVE_TIMEOUT_EXPIRED),
-	SC_ENTRY(KEEP_ALIVE_TIMEOUT_INVALID),
-	SC_ENTRY(ABORTED_DUE_TO_PREEMPT),
-	SC_ENTRY(SANITIZE_FAILED),
-	SC_ENTRY(SANITIZE_IN_PROGRESS),
-	SC_ENTRY(SGL_DATA_BLOCK_GRAN_INVALID),
-	SC_ENTRY(NOT_SUPPORTED_IN_CMB),
-	SC_ENTRY(NAMESPACE_IS_WRITE_PROTECTED),
-	SC_ENTRY(COMMAND_INTERRUPTED),
-	SC_ENTRY(TRANSIENT_TRANSPORT_ERROR),
-
-	SC_ENTRY(LBA_OUT_OF_RANGE),
-	SC_ENTRY(CAPACITY_EXCEEDED),
-	SC_ENTRY(NAMESPACE_NOT_READY),
-	SC_ENTRY(RESERVATION_CONFLICT),
-	SC_ENTRY(FORMAT_IN_PROGRESS),
-};
-
-static const char *command_specific_status[256] = {
-	SC_ENTRY(COMPLETION_QUEUE_INVALID),
-	SC_ENTRY(INVALID_QUEUE_IDENTIFIER),
-	SC_ENTRY(MAXIMUM_QUEUE_SIZE_EXCEEDED),
-	SC_ENTRY(ABORT_COMMAND_LIMIT_EXCEEDED),
-	SC_ENTRY(ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED),
-	SC_ENTRY(INVALID_FIRMWARE_SLOT),
-	SC_ENTRY(INVALID_FIRMWARE_IMAGE),
-	SC_ENTRY(INVALID_INTERRUPT_VECTOR),
-	SC_ENTRY(INVALID_LOG_PAGE),
-	SC_ENTRY(INVALID_FORMAT),
-	SC_ENTRY(FIRMWARE_REQUIRES_RESET),
-	SC_ENTRY(INVALID_QUEUE_DELETION),
-	SC_ENTRY(FEATURE_NOT_SAVEABLE),
-	SC_ENTRY(FEATURE_NOT_CHANGEABLE),
-	SC_ENTRY(FEATURE_NOT_NS_SPECIFIC),
-	SC_ENTRY(FW_ACT_REQUIRES_NVMS_RESET),
-	SC_ENTRY(FW_ACT_REQUIRES_RESET),
-	SC_ENTRY(FW_ACT_REQUIRES_TIME),
-	SC_ENTRY(FW_ACT_PROHIBITED),
-	SC_ENTRY(OVERLAPPING_RANGE),
-	SC_ENTRY(NS_INSUFFICIENT_CAPACITY),
-	SC_ENTRY(NS_ID_UNAVAILABLE),
-	SC_ENTRY(NS_ALREADY_ATTACHED),
-	SC_ENTRY(NS_IS_PRIVATE),
-	SC_ENTRY(NS_NOT_ATTACHED),
-	SC_ENTRY(THIN_PROV_NOT_SUPPORTED),
-	SC_ENTRY(CTRLR_LIST_INVALID),
-	SC_ENTRY(SELF_TEST_IN_PROGRESS),
-	SC_ENTRY(BOOT_PART_WRITE_PROHIB),
-	SC_ENTRY(INVALID_CTRLR_ID),
-	SC_ENTRY(INVALID_SEC_CTRLR_STATE),
-	SC_ENTRY(INVALID_NUM_OF_CTRLR_RESRC),
-	SC_ENTRY(INVALID_RESOURCE_ID),
-	SC_ENTRY(SANITIZE_PROHIBITED_WPMRE),
-	SC_ENTRY(ANA_GROUP_ID_INVALID),
-	SC_ENTRY(ANA_ATTACH_FAILED),
-
-	SC_ENTRY(CONFLICTING_ATTRIBUTES),
-	SC_ENTRY(INVALID_PROTECTION_INFO),
-	SC_ENTRY(ATTEMPTED_WRITE_TO_RO_PAGE),
-};
-
-static const char *media_error_status[256] = {
-	SC_ENTRY(WRITE_FAULTS),
-	SC_ENTRY(UNRECOVERED_READ_ERROR),
-	SC_ENTRY(GUARD_CHECK_ERROR),
-	SC_ENTRY(APPLICATION_TAG_CHECK_ERROR),
-	SC_ENTRY(REFERENCE_TAG_CHECK_ERROR),
-	SC_ENTRY(COMPARE_FAILURE),
-	SC_ENTRY(ACCESS_DENIED),
-	SC_ENTRY(DEALLOCATED_OR_UNWRITTEN),
-};
-
-static const char *path_related_status[256] = {
-	SC_ENTRY(INTERNAL_PATH_ERROR),
-	SC_ENTRY(ASYMMETRIC_ACCESS_PERSISTENT_LOSS),
-	SC_ENTRY(ASYMMETRIC_ACCESS_INACCESSIBLE),
-	SC_ENTRY(ASYMMETRIC_ACCESS_TRANSITION),
-	SC_ENTRY(CONTROLLER_PATHING_ERROR),
-	SC_ENTRY(HOST_PATHING_ERROR),
-	SC_ENTRY(COMMAND_ABORTED_BY_HOST),
-};
-
 void
 nvme_ns_cmd(struct ccb_nvmeio *nvmeio, uint8_t cmd, uint32_t nsid,
     uint32_t cdw10, uint32_t cdw11, uint32_t cdw12, uint32_t cdw13,
@@ -292,24 +130,6 @@ nvme_command_string(struct ccb_nvmeio *nvmeio, char *cmd_string, size_t len)
 	return(sbuf_data(&sb));
 }
 
-void
-nvme_opcode_sbuf(bool admin, uint8_t opc, struct sbuf *sb)
-{
-	const char *s, *type;
-
-	if (admin) {
-		s = admin_opcode[opc];
-		type = "ADMIN";
-	} else {
-		s = nvm_opcode[opc];
-		type = "NVM";
-	}
-	if (s == NULL)
-		sbuf_printf(sb, "%s:0x%02x", type, opc);
-	else
-		sbuf_printf(sb, "%s", s);
-}
-
 void
 nvme_cmd_sbuf(const struct nvme_command *cmd, struct sbuf *sb)
 {
@@ -340,50 +160,6 @@ nvme_command_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb)
 	return(0);
 }
 
-void
-nvme_cpl_sbuf(const struct nvme_completion *cpl, struct sbuf *sb)
-{
-	const char *s, *type;
-	uint16_t status;
-
-	status = le16toh(cpl->status);
-	switch (NVME_STATUS_GET_SCT(status)) {
-	case NVME_SCT_GENERIC:
-		s = generic_status[NVME_STATUS_GET_SC(status)];
-		type = "GENERIC";
-		break;
-	case NVME_SCT_COMMAND_SPECIFIC:
-		s = command_specific_status[NVME_STATUS_GET_SC(status)];
-		type = "COMMAND SPECIFIC";
-		break;
-	case NVME_SCT_MEDIA_ERROR:
-		s = media_error_status[NVME_STATUS_GET_SC(status)];
-		type = "MEDIA ERROR";
-		break;
-	case NVME_SCT_PATH_RELATED:
-		s = path_related_status[NVME_STATUS_GET_SC(status)];
-		type = "PATH RELATED";
-		break;
-	case NVME_SCT_VENDOR_SPECIFIC:
-		s = NULL;
-		type = "VENDOR SPECIFIC";
-		break;
-	default:
-		s = "RESERVED";
-		type = NULL;
-		break;
-	}
-
-	if (s == NULL)
-		sbuf_printf(sb, "%s:0x%02x", type, NVME_STATUS_GET_SC(status));
-	else
-		sbuf_printf(sb, "%s", s);
-	if (NVME_STATUS_GET_M(status) != 0)
-		sbuf_printf(sb, " M");
-	if (NVME_STATUS_GET_DNR(status) != 0)
-		sbuf_printf(sb, " DNR");
-}
-
 /*
  * nvme_status_sbuf() returns 0 for success and -1 for failure.
  */
diff --git a/sys/cam/nvme/nvme_all.h b/sys/cam/nvme/nvme_all.h
index 17c068b825be..2bc1953e79be 100644
--- a/sys/cam/nvme/nvme_all.h
+++ b/sys/cam/nvme/nvme_all.h
@@ -42,11 +42,9 @@ struct sbuf;
 void	nvme_print_ident(const struct nvme_controller_data *, const struct nvme_namespace_data *, struct sbuf *);
 void	nvme_print_ident_short(const struct nvme_controller_data *,
     const struct nvme_namespace_data *, struct sbuf *);
-void nvme_opcode_sbuf(bool admin, uint8_t opc, struct sbuf *sb);
 void nvme_cmd_sbuf(const struct nvme_command *, struct sbuf *sb);
 int nvme_command_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb);
 const char *nvme_command_string(struct ccb_nvmeio *nvmeio, char *, size_t);
-void nvme_cpl_sbuf(const struct nvme_completion *cpl, struct sbuf *sbuf);
 int nvme_status_sbuf(struct ccb_nvmeio *nvmeio, struct sbuf *sb);
 const void *nvme_get_identify_cntrl(struct cam_periph *);
 const void *nvme_get_identify_ns(struct cam_periph *);
diff --git a/sys/conf/files b/sys/conf/files
index e54eff8464a7..57f1f7970321 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -2538,7 +2538,7 @@ dev/nvme/nvme_qpair.c		optional nvme
 dev/nvme/nvme_sim.c		optional nvme scbus
 dev/nvme/nvme_sysctl.c		optional nvme
 dev/nvme/nvme_test.c		optional nvme
-dev/nvme/nvme_util.c		optional nvme
+dev/nvme/nvme_util.c		optional nvme | scbus
 dev/nvmem/nvmem.c		optional nvmem fdt
 dev/nvmem/nvmem_if.m		optional nvmem
 dev/nvmf/controller/ctl_frontend_nvmf.c		optional nvmft
diff --git a/sys/dev/nvme/nvme.h b/sys/dev/nvme/nvme.h
index a08abcb4aec6..9ae6d4f3bae6 100644
--- a/sys/dev/nvme/nvme.h
+++ b/sys/dev/nvme/nvme.h
@@ -1906,6 +1906,7 @@ void	nvme_strvis(uint8_t *dst, const uint8_t *src, int dstlen, int srclen);
 #ifdef _KERNEL
 
 struct bio;
+struct sbuf;
 struct thread;
 
 struct nvme_namespace;
@@ -1926,6 +1927,9 @@ enum nvme_namespace_flags {
 	NVME_NS_FLUSH_SUPPORTED		= 0x2,
 };
 
+void	nvme_cpl_sbuf(const struct nvme_completion *cpl, struct sbuf *sbuf);
+void	nvme_opcode_sbuf(bool admin, uint8_t opc, struct sbuf *sb);
+
 int	nvme_ctrlr_passthrough_cmd(struct nvme_controller *ctrlr,
 				   struct nvme_pt_command *pt,
 				   uint32_t nsid, int is_user_buffer,
diff --git a/sys/dev/nvme/nvme_util.c b/sys/dev/nvme/nvme_util.c
index 47d84e5b6957..892ea86c6b22 100644
--- a/sys/dev/nvme/nvme_util.c
+++ b/sys/dev/nvme/nvme_util.c
@@ -5,6 +5,8 @@
  * Copyright (C) 1997 Justin T. Gibbs
  * All rights reserved.
  *
+ * Copyright (c) 2023-2025 Chelsio Communications, Inc.
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
@@ -28,8 +30,237 @@
  */
 
 #include <sys/param.h>
+#ifdef _KERNEL
+#include <sys/sbuf.h>
+#endif
 #include <dev/nvme/nvme.h>
 
+#ifdef _KERNEL
+/* XXX: This duplicates lists in nvme_qpair.c. */
+
+#define OPC_ENTRY(x)		[NVME_OPC_ ## x] = #x
+
+static const char *admin_opcode[256] = {
+	OPC_ENTRY(DELETE_IO_SQ),
+	OPC_ENTRY(CREATE_IO_SQ),
+	OPC_ENTRY(GET_LOG_PAGE),
+	OPC_ENTRY(DELETE_IO_CQ),
+	OPC_ENTRY(CREATE_IO_CQ),
+	OPC_ENTRY(IDENTIFY),
+	OPC_ENTRY(ABORT),
+	OPC_ENTRY(SET_FEATURES),
+	OPC_ENTRY(GET_FEATURES),
+	OPC_ENTRY(ASYNC_EVENT_REQUEST),
+	OPC_ENTRY(NAMESPACE_MANAGEMENT),
+	OPC_ENTRY(FIRMWARE_ACTIVATE),
+	OPC_ENTRY(FIRMWARE_IMAGE_DOWNLOAD),
+	OPC_ENTRY(DEVICE_SELF_TEST),
+	OPC_ENTRY(NAMESPACE_ATTACHMENT),
+	OPC_ENTRY(KEEP_ALIVE),
+	OPC_ENTRY(DIRECTIVE_SEND),
+	OPC_ENTRY(DIRECTIVE_RECEIVE),
+	OPC_ENTRY(VIRTUALIZATION_MANAGEMENT),
+	OPC_ENTRY(NVME_MI_SEND),
+	OPC_ENTRY(NVME_MI_RECEIVE),
+	OPC_ENTRY(CAPACITY_MANAGEMENT),
+	OPC_ENTRY(LOCKDOWN),
+	OPC_ENTRY(DOORBELL_BUFFER_CONFIG),
+	OPC_ENTRY(FABRICS_COMMANDS),
+	OPC_ENTRY(FORMAT_NVM),
+	OPC_ENTRY(SECURITY_SEND),
+	OPC_ENTRY(SECURITY_RECEIVE),
+	OPC_ENTRY(SANITIZE),
+	OPC_ENTRY(GET_LBA_STATUS),
+};
+
+static const char *nvm_opcode[256] = {
+	OPC_ENTRY(FLUSH),
+	OPC_ENTRY(WRITE),
+	OPC_ENTRY(READ),
+	OPC_ENTRY(WRITE_UNCORRECTABLE),
+	OPC_ENTRY(COMPARE),
+	OPC_ENTRY(WRITE_ZEROES),
+	OPC_ENTRY(DATASET_MANAGEMENT),
+	OPC_ENTRY(VERIFY),
+	OPC_ENTRY(RESERVATION_REGISTER),
+	OPC_ENTRY(RESERVATION_REPORT),
+	OPC_ENTRY(RESERVATION_ACQUIRE),
+	OPC_ENTRY(RESERVATION_RELEASE),
+	OPC_ENTRY(COPY),
+};
+
+#define SC_ENTRY(x)		[NVME_SC_ ## x] = #x
+
+static const char *generic_status[256] = {
+	SC_ENTRY(SUCCESS),
+	SC_ENTRY(INVALID_OPCODE),
+	SC_ENTRY(INVALID_FIELD),
+	SC_ENTRY(COMMAND_ID_CONFLICT),
+	SC_ENTRY(DATA_TRANSFER_ERROR),
+	SC_ENTRY(ABORTED_POWER_LOSS),
+	SC_ENTRY(INTERNAL_DEVICE_ERROR),
+	SC_ENTRY(ABORTED_BY_REQUEST),
+	SC_ENTRY(ABORTED_SQ_DELETION),
+	SC_ENTRY(ABORTED_FAILED_FUSED),
+	SC_ENTRY(ABORTED_MISSING_FUSED),
+	SC_ENTRY(INVALID_NAMESPACE_OR_FORMAT),
+	SC_ENTRY(COMMAND_SEQUENCE_ERROR),
+	SC_ENTRY(INVALID_SGL_SEGMENT_DESCR),
+	SC_ENTRY(INVALID_NUMBER_OF_SGL_DESCR),
+	SC_ENTRY(DATA_SGL_LENGTH_INVALID),
+	SC_ENTRY(METADATA_SGL_LENGTH_INVALID),
+	SC_ENTRY(SGL_DESCRIPTOR_TYPE_INVALID),
+	SC_ENTRY(INVALID_USE_OF_CMB),
+	SC_ENTRY(PRP_OFFET_INVALID),
+	SC_ENTRY(ATOMIC_WRITE_UNIT_EXCEEDED),
+	SC_ENTRY(OPERATION_DENIED),
+	SC_ENTRY(SGL_OFFSET_INVALID),
+	SC_ENTRY(HOST_ID_INCONSISTENT_FORMAT),
+	SC_ENTRY(KEEP_ALIVE_TIMEOUT_EXPIRED),
+	SC_ENTRY(KEEP_ALIVE_TIMEOUT_INVALID),
+	SC_ENTRY(ABORTED_DUE_TO_PREEMPT),
+	SC_ENTRY(SANITIZE_FAILED),
+	SC_ENTRY(SANITIZE_IN_PROGRESS),
+	SC_ENTRY(SGL_DATA_BLOCK_GRAN_INVALID),
+	SC_ENTRY(NOT_SUPPORTED_IN_CMB),
+	SC_ENTRY(NAMESPACE_IS_WRITE_PROTECTED),
+	SC_ENTRY(COMMAND_INTERRUPTED),
+	SC_ENTRY(TRANSIENT_TRANSPORT_ERROR),
+
+	SC_ENTRY(LBA_OUT_OF_RANGE),
+	SC_ENTRY(CAPACITY_EXCEEDED),
+	SC_ENTRY(NAMESPACE_NOT_READY),
+	SC_ENTRY(RESERVATION_CONFLICT),
+	SC_ENTRY(FORMAT_IN_PROGRESS),
+};
+
+static const char *command_specific_status[256] = {
+	SC_ENTRY(COMPLETION_QUEUE_INVALID),
+	SC_ENTRY(INVALID_QUEUE_IDENTIFIER),
+	SC_ENTRY(MAXIMUM_QUEUE_SIZE_EXCEEDED),
+	SC_ENTRY(ABORT_COMMAND_LIMIT_EXCEEDED),
+	SC_ENTRY(ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED),
+	SC_ENTRY(INVALID_FIRMWARE_SLOT),
+	SC_ENTRY(INVALID_FIRMWARE_IMAGE),
+	SC_ENTRY(INVALID_INTERRUPT_VECTOR),
+	SC_ENTRY(INVALID_LOG_PAGE),
+	SC_ENTRY(INVALID_FORMAT),
+	SC_ENTRY(FIRMWARE_REQUIRES_RESET),
+	SC_ENTRY(INVALID_QUEUE_DELETION),
+	SC_ENTRY(FEATURE_NOT_SAVEABLE),
+	SC_ENTRY(FEATURE_NOT_CHANGEABLE),
+	SC_ENTRY(FEATURE_NOT_NS_SPECIFIC),
+	SC_ENTRY(FW_ACT_REQUIRES_NVMS_RESET),
+	SC_ENTRY(FW_ACT_REQUIRES_RESET),
+	SC_ENTRY(FW_ACT_REQUIRES_TIME),
+	SC_ENTRY(FW_ACT_PROHIBITED),
+	SC_ENTRY(OVERLAPPING_RANGE),
+	SC_ENTRY(NS_INSUFFICIENT_CAPACITY),
+	SC_ENTRY(NS_ID_UNAVAILABLE),
+	SC_ENTRY(NS_ALREADY_ATTACHED),
+	SC_ENTRY(NS_IS_PRIVATE),
+	SC_ENTRY(NS_NOT_ATTACHED),
+	SC_ENTRY(THIN_PROV_NOT_SUPPORTED),
+	SC_ENTRY(CTRLR_LIST_INVALID),
+	SC_ENTRY(SELF_TEST_IN_PROGRESS),
+	SC_ENTRY(BOOT_PART_WRITE_PROHIB),
+	SC_ENTRY(INVALID_CTRLR_ID),
+	SC_ENTRY(INVALID_SEC_CTRLR_STATE),
+	SC_ENTRY(INVALID_NUM_OF_CTRLR_RESRC),
+	SC_ENTRY(INVALID_RESOURCE_ID),
+	SC_ENTRY(SANITIZE_PROHIBITED_WPMRE),
+	SC_ENTRY(ANA_GROUP_ID_INVALID),
+	SC_ENTRY(ANA_ATTACH_FAILED),
+
+	SC_ENTRY(CONFLICTING_ATTRIBUTES),
+	SC_ENTRY(INVALID_PROTECTION_INFO),
+	SC_ENTRY(ATTEMPTED_WRITE_TO_RO_PAGE),
+};
+
+static const char *media_error_status[256] = {
+	SC_ENTRY(WRITE_FAULTS),
+	SC_ENTRY(UNRECOVERED_READ_ERROR),
+	SC_ENTRY(GUARD_CHECK_ERROR),
+	SC_ENTRY(APPLICATION_TAG_CHECK_ERROR),
+	SC_ENTRY(REFERENCE_TAG_CHECK_ERROR),
+	SC_ENTRY(COMPARE_FAILURE),
+	SC_ENTRY(ACCESS_DENIED),
+	SC_ENTRY(DEALLOCATED_OR_UNWRITTEN),
+};
+
+static const char *path_related_status[256] = {
+	SC_ENTRY(INTERNAL_PATH_ERROR),
+	SC_ENTRY(ASYMMETRIC_ACCESS_PERSISTENT_LOSS),
+	SC_ENTRY(ASYMMETRIC_ACCESS_INACCESSIBLE),
+	SC_ENTRY(ASYMMETRIC_ACCESS_TRANSITION),
+	SC_ENTRY(CONTROLLER_PATHING_ERROR),
+	SC_ENTRY(HOST_PATHING_ERROR),
+	SC_ENTRY(COMMAND_ABORTED_BY_HOST),
+};
+
+void
+nvme_opcode_sbuf(bool admin, uint8_t opc, struct sbuf *sb)
+{
+	const char *s, *type;
+
+	if (admin) {
+		s = admin_opcode[opc];
+		type = "ADMIN";
+	} else {
+		s = nvm_opcode[opc];
+		type = "NVM";
+	}
+	if (s == NULL)
+		sbuf_printf(sb, "%s:0x%02x", type, opc);
+	else
+		sbuf_printf(sb, "%s", s);
+}
+
+void
+nvme_cpl_sbuf(const struct nvme_completion *cpl, struct sbuf *sb)
+{
+	const char *s, *type;
+	uint16_t status;
+
+	status = le16toh(cpl->status);
+	switch (NVME_STATUS_GET_SCT(status)) {
+	case NVME_SCT_GENERIC:
+		s = generic_status[NVME_STATUS_GET_SC(status)];
+		type = "GENERIC";
+		break;
+	case NVME_SCT_COMMAND_SPECIFIC:
+		s = command_specific_status[NVME_STATUS_GET_SC(status)];
+		type = "COMMAND SPECIFIC";
+		break;
+	case NVME_SCT_MEDIA_ERROR:
+		s = media_error_status[NVME_STATUS_GET_SC(status)];
+		type = "MEDIA ERROR";
+		break;
+	case NVME_SCT_PATH_RELATED:
+		s = path_related_status[NVME_STATUS_GET_SC(status)];
+		type = "PATH RELATED";
+		break;
+	case NVME_SCT_VENDOR_SPECIFIC:
+		s = NULL;
+		type = "VENDOR SPECIFIC";
+		break;
+	default:
+		s = "RESERVED";
+		type = NULL;
+		break;
+	}
+
+	if (s == NULL)
+		sbuf_printf(sb, "%s:0x%02x", type, NVME_STATUS_GET_SC(status));
+	else
+		sbuf_printf(sb, "%s", s);
+	if (NVME_STATUS_GET_M(status) != 0)
+		sbuf_printf(sb, " M");
+	if (NVME_STATUS_GET_DNR(status) != 0)
+		sbuf_printf(sb, " DNR");
+}
+#endif
+
 void
 nvme_strvis(uint8_t *dst, const uint8_t *src, int dstlen, int srclen)
 {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202506052106.555L6XBV089396>