aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/nvme/nvme_ctrlr.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/nvme/nvme_ctrlr.c')
-rw-r--r--sys/dev/nvme/nvme_ctrlr.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/sys/dev/nvme/nvme_ctrlr.c b/sys/dev/nvme/nvme_ctrlr.c
index 3a1894bf754d..f212759a5500 100644
--- a/sys/dev/nvme/nvme_ctrlr.c
+++ b/sys/dev/nvme/nvme_ctrlr.c
@@ -33,6 +33,7 @@
#include <sys/buf.h>
#include <sys/bus.h>
#include <sys/conf.h>
+#include <sys/disk.h>
#include <sys/ioccom.h>
#include <sys/proc.h>
#include <sys/smp.h>
@@ -1254,6 +1255,24 @@ nvme_ctrlr_poll(struct nvme_controller *ctrlr)
}
/*
+ * Copy the NVME device's serial number to the provided buffer, which must be
+ * at least DISK_IDENT_SIZE bytes large.
+ */
+void
+nvme_ctrlr_get_ident(const struct nvme_controller *ctrlr, uint8_t *sn)
+{
+ _Static_assert(NVME_SERIAL_NUMBER_LENGTH < DISK_IDENT_SIZE,
+ "NVME serial number too big for disk ident");
+
+ memmove(sn, ctrlr->cdata.sn, NVME_SERIAL_NUMBER_LENGTH);
+ sn[NVME_SERIAL_NUMBER_LENGTH] = '\0';
+ for (int i = 0; sn[i] != '\0'; i++) {
+ if (sn[i] < 0x20 || sn[i] >= 0x80)
+ sn[i] = ' ';
+ }
+}
+
+/*
* Poll the single-vector interrupt case: num_io_queues will be 1 and
* there's only a single vector. While we're polling, we mask further
* interrupts in the controller.
@@ -1495,6 +1514,11 @@ nvme_ctrlr_ioctl(struct cdev *cdev, u_long cmd, caddr_t arg, int flag,
case NVME_GET_CONTROLLER_DATA:
memcpy(arg, &ctrlr->cdata, sizeof(ctrlr->cdata));
break;
+ case DIOCGIDENT: {
+ uint8_t *sn = arg;
+ nvme_ctrlr_get_ident(ctrlr, sn);
+ break;
+ }
/* Linux Compatible (see nvme_linux.h) */
case NVME_IOCTL_ID:
td->td_retval[0] = 0xfffffffful;