svn commit: r329824 - in head: sbin/nvmecontrol sys/cam/nvme sys/conf sys/dev/mpr sys/dev/nvme

Wojciech Macek wma at FreeBSD.org
Thu Feb 22 13:32:33 UTC 2018


Author: wma
Date: Thu Feb 22 13:32:31 2018
New Revision: 329824
URL: https://svnweb.freebsd.org/changeset/base/329824

Log:
  NVMe: Add big-endian support
  
  Remove bitfields from defined structures as they are not portable.
  Instead use shift and mask macros in the driver and nvmecontrol application.
  
  NVMe is now working on powerpc64 host.
  
  Submitted by:          Michal Stanek <mst at semihalf.com>
  Obtained from:         Semihalf
  Reviewed by:           imp, wma
  Sponsored by:          IBM, QCM Technologies
  Differential revision: https://reviews.freebsd.org/D13916

Modified:
  head/sbin/nvmecontrol/devlist.c
  head/sbin/nvmecontrol/firmware.c
  head/sbin/nvmecontrol/identify.c
  head/sbin/nvmecontrol/logpage.c
  head/sbin/nvmecontrol/nvmecontrol.c
  head/sbin/nvmecontrol/perftest.c
  head/sbin/nvmecontrol/power.c
  head/sbin/nvmecontrol/wdc.c
  head/sys/cam/nvme/nvme_all.c
  head/sys/cam/nvme/nvme_da.c
  head/sys/conf/files
  head/sys/dev/mpr/mpr_sas.c
  head/sys/dev/nvme/nvme.c
  head/sys/dev/nvme/nvme.h
  head/sys/dev/nvme/nvme_ctrlr.c
  head/sys/dev/nvme/nvme_ctrlr_cmd.c
  head/sys/dev/nvme/nvme_ns.c
  head/sys/dev/nvme/nvme_ns_cmd.c
  head/sys/dev/nvme/nvme_private.h
  head/sys/dev/nvme/nvme_qpair.c

Modified: head/sbin/nvmecontrol/devlist.c
==============================================================================
--- head/sbin/nvmecontrol/devlist.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sbin/nvmecontrol/devlist.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -54,8 +54,14 @@ devlist_usage(void)
 static inline uint32_t
 ns_get_sector_size(struct nvme_namespace_data *nsdata)
 {
+	uint8_t flbas_fmt, lbads;
 
-	return (1 << nsdata->lbaf[nsdata->flbas.format].lbads);
+	flbas_fmt = (nsdata->flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) &
+		NVME_NS_DATA_FLBAS_FORMAT_MASK;
+	lbads = (nsdata->lbaf[flbas_fmt] >> NVME_NS_DATA_LBAF_LBADS_SHIFT) &
+		NVME_NS_DATA_LBAF_LBADS_MASK;
+
+	return (1 << lbads);
 }
 
 void

Modified: head/sbin/nvmecontrol/firmware.c
==============================================================================
--- head/sbin/nvmecontrol/firmware.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sbin/nvmecontrol/firmware.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -125,9 +125,9 @@ update_firmware(int fd, uint8_t *payload, int32_t payl
 		memcpy(chunk, payload + off, size);
 
 		memset(&pt, 0, sizeof(pt));
-		pt.cmd.opc = NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD;
-		pt.cmd.cdw10 = (size / sizeof(uint32_t)) - 1;
-		pt.cmd.cdw11 = (off / sizeof(uint32_t));
+		pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD);
+		pt.cmd.cdw10 = htole32((size / sizeof(uint32_t)) - 1);
+		pt.cmd.cdw11 = htole32(off / sizeof(uint32_t));
 		pt.buf = chunk;
 		pt.len = size;
 		pt.is_read = 0;
@@ -147,17 +147,21 @@ static int
 activate_firmware(int fd, int slot, int activate_action)
 {
 	struct nvme_pt_command	pt;
+	uint16_t sct, sc;
 
 	memset(&pt, 0, sizeof(pt));
-	pt.cmd.opc = NVME_OPC_FIRMWARE_ACTIVATE;
-	pt.cmd.cdw10 = (activate_action << 3) | slot;
+	pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_FIRMWARE_ACTIVATE);
+	pt.cmd.cdw10 = htole32((activate_action << 3) | slot);
 	pt.is_read = 0;
 
 	if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
 		err(1, "firmware activate request failed");
 
-	if (pt.cpl.status.sct == NVME_SCT_COMMAND_SPECIFIC &&
-	    pt.cpl.status.sc == NVME_SC_FIRMWARE_REQUIRES_RESET)
+	sct = NVME_STATUS_GET_SCT(pt.cpl.status);
+	sc = NVME_STATUS_GET_SC(pt.cpl.status);
+
+	if (sct == NVME_SCT_COMMAND_SPECIFIC &&
+	    sc == NVME_SC_FIRMWARE_REQUIRES_RESET)
 		return 1;
 
 	if (nvme_completion_is_error(&pt.cpl))
@@ -180,16 +184,19 @@ firmware(int argc, char *argv[])
 	int				fd = -1, slot = 0;
 	int				a_flag, s_flag, f_flag;
 	int				activate_action, reboot_required;
-	char				ch, *p, *image = NULL;
+	int				opt;
+	char				*p, *image = NULL;
 	char				*controller = NULL, prompt[64];
 	void				*buf = NULL;
 	int32_t				size = 0;
+	uint16_t			oacs_fw;
+	uint8_t				fw_slot1_ro, fw_num_slots;
 	struct nvme_controller_data	cdata;
 
 	a_flag = s_flag = f_flag = false;
 
-	while ((ch = getopt(argc, argv, "af:s:")) != -1) {
-		switch (ch) {
+	while ((opt = getopt(argc, argv, "af:s:")) != -1) {
+		switch (opt) {
 		case 'a':
 			a_flag = true;
 			break;
@@ -243,17 +250,26 @@ firmware(int argc, char *argv[])
 	open_dev(controller, &fd, 1, 1);
 	read_controller_data(fd, &cdata);
 
-	if (cdata.oacs.firmware == 0)
+	oacs_fw = (cdata.oacs >> NVME_CTRLR_DATA_OACS_FIRMWARE_SHIFT) &
+		NVME_CTRLR_DATA_OACS_FIRMWARE_MASK;
+
+	if (oacs_fw == 0)
 		errx(1,
 		    "controller does not support firmware activate/download");
 
-	if (f_flag && slot == 1 && cdata.frmw.slot1_ro)
+	fw_slot1_ro = (cdata.frmw >> NVME_CTRLR_DATA_FRMW_SLOT1_RO_SHIFT) &
+		NVME_CTRLR_DATA_FRMW_SLOT1_RO_MASK;
+
+	if (f_flag && slot == 1 && fw_slot1_ro)
 		errx(1, "slot %d is marked as read only", slot);
 
-	if (slot > cdata.frmw.num_slots)
+	fw_num_slots = (cdata.frmw >> NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT) &
+		NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK;
+
+	if (slot > fw_num_slots)
 		errx(1,
 		    "slot %d specified but controller only supports %d slots",
-		    slot, cdata.frmw.num_slots);
+		    slot, fw_num_slots);
 
 	if (a_flag && !f_flag && !slot_has_valid_firmware(fd, slot))
 		errx(1,

Modified: head/sbin/nvmecontrol/identify.c
==============================================================================
--- head/sbin/nvmecontrol/identify.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sbin/nvmecontrol/identify.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -47,7 +47,52 @@ print_controller(struct nvme_controller_data *cdata)
 {
 	uint8_t str[128];
 	char cbuf[UINT128_DIG + 1];
+	uint16_t oncs, oacs;
+	uint8_t compare, write_unc, dsm, vwc_present;
+	uint8_t security, fmt, fw, nsmgmt;
+	uint8_t	fw_slot1_ro, fw_num_slots;
+	uint8_t ns_smart;
+	uint8_t sqes_max, sqes_min;
+	uint8_t cqes_max, cqes_min;
 
+	oncs = cdata->oncs;
+	compare = (oncs >> NVME_CTRLR_DATA_ONCS_COMPARE_SHIFT) &
+		NVME_CTRLR_DATA_ONCS_COMPARE_MASK;
+	write_unc = (oncs >> NVME_CTRLR_DATA_ONCS_WRITE_UNC_SHIFT) &
+		NVME_CTRLR_DATA_ONCS_WRITE_UNC_MASK;
+	dsm = (oncs >> NVME_CTRLR_DATA_ONCS_DSM_SHIFT) &
+		NVME_CTRLR_DATA_ONCS_DSM_MASK;
+	vwc_present = (cdata->vwc >> NVME_CTRLR_DATA_VWC_PRESENT_SHIFT) &
+		NVME_CTRLR_DATA_VWC_PRESENT_MASK;
+
+	oacs = cdata->oacs;
+	security = (oacs >> NVME_CTRLR_DATA_OACS_SECURITY_SHIFT) &
+		NVME_CTRLR_DATA_OACS_SECURITY_MASK;
+	fmt = (oacs >> NVME_CTRLR_DATA_OACS_FORMAT_SHIFT) &
+		NVME_CTRLR_DATA_OACS_FORMAT_MASK;
+	fw = (oacs >> NVME_CTRLR_DATA_OACS_FIRMWARE_SHIFT) &
+		NVME_CTRLR_DATA_OACS_FIRMWARE_MASK;
+	nsmgmt = (oacs >> NVME_CTRLR_DATA_OACS_NSMGMT_SHIFT) &
+		NVME_CTRLR_DATA_OACS_NSMGMT_MASK;
+
+	fw_num_slots = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT) &
+		NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK;
+	fw_slot1_ro = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_SLOT1_RO_SHIFT) &
+		NVME_CTRLR_DATA_FRMW_SLOT1_RO_MASK;
+
+	ns_smart = (cdata->lpa >> NVME_CTRLR_DATA_LPA_NS_SMART_SHIFT) &
+		NVME_CTRLR_DATA_LPA_NS_SMART_MASK;
+
+	sqes_min = (cdata->sqes >> NVME_CTRLR_DATA_SQES_MIN_SHIFT) &
+		NVME_CTRLR_DATA_SQES_MIN_MASK;
+	sqes_max = (cdata->sqes >> NVME_CTRLR_DATA_SQES_MAX_SHIFT) &
+		NVME_CTRLR_DATA_SQES_MAX_MASK;
+
+	cqes_min = (cdata->cqes >> NVME_CTRLR_DATA_CQES_MIN_SHIFT) &
+		NVME_CTRLR_DATA_CQES_MIN_MASK;
+	cqes_max = (cdata->cqes >> NVME_CTRLR_DATA_CQES_MAX_SHIFT) &
+		NVME_CTRLR_DATA_CQES_MAX_MASK;
+
 	printf("Controller Capabilities/Features\n");
 	printf("================================\n");
 	printf("Vendor ID:                  %04x\n", cdata->vid);
@@ -67,34 +112,34 @@ print_controller(struct nvme_controller_data *cdata)
 	if (cdata->mdts == 0)
 		printf("Unlimited\n");
 	else
-		printf("%d\n", PAGE_SIZE * (1 << cdata->mdts));
+		printf("%ld\n", PAGE_SIZE * (1 << cdata->mdts));
 	printf("Controller ID:              0x%02x\n", cdata->ctrlr_id);
 	printf("\n");
 
 	printf("Admin Command Set Attributes\n");
 	printf("============================\n");
 	printf("Security Send/Receive:       %s\n",
-		cdata->oacs.security ? "Supported" : "Not Supported");
+		security ? "Supported" : "Not Supported");
 	printf("Format NVM:                  %s\n",
-		cdata->oacs.format ? "Supported" : "Not Supported");
+		fmt ? "Supported" : "Not Supported");
 	printf("Firmware Activate/Download:  %s\n",
-		cdata->oacs.firmware ? "Supported" : "Not Supported");
+		fw ? "Supported" : "Not Supported");
 	printf("Namespace Managment:         %s\n",
-		   cdata->oacs.nsmgmt ? "Supported" : "Not Supported");
+		nsmgmt ? "Supported" : "Not Supported");
 	printf("Abort Command Limit:         %d\n", cdata->acl+1);
 	printf("Async Event Request Limit:   %d\n", cdata->aerl+1);
 	printf("Number of Firmware Slots:    ");
-	if (cdata->oacs.firmware != 0)
-		printf("%d\n", cdata->frmw.num_slots);
+	if (fw != 0)
+		printf("%d\n", fw_num_slots);
 	else
 		printf("N/A\n");
 	printf("Firmware Slot 1 Read-Only:   ");
-	if (cdata->oacs.firmware != 0)
-		printf("%s\n", cdata->frmw.slot1_ro ? "Yes" : "No");
+	if (fw != 0)
+		printf("%s\n", fw_slot1_ro ? "Yes" : "No");
 	else
 		printf("N/A\n");
 	printf("Per-Namespace SMART Log:     %s\n",
-		cdata->lpa.ns_smart ? "Yes" : "No");
+		ns_smart ? "Yes" : "No");
 	printf("Error Log Page Entries:      %d\n", cdata->elpe+1);
 	printf("Number of Power States:      %d\n", cdata->npss+1);
 
@@ -102,22 +147,22 @@ print_controller(struct nvme_controller_data *cdata)
 	printf("NVM Command Set Attributes\n");
 	printf("==========================\n");
 	printf("Submission Queue Entry Size\n");
-	printf("  Max:                       %d\n", 1 << cdata->sqes.max);
-	printf("  Min:                       %d\n", 1 << cdata->sqes.min);
+	printf("  Max:                       %d\n", 1 << sqes_max);
+	printf("  Min:                       %d\n", 1 << sqes_min);
 	printf("Completion Queue Entry Size\n");
-	printf("  Max:                       %d\n", 1 << cdata->cqes.max);
-	printf("  Min:                       %d\n", 1 << cdata->cqes.min);
+	printf("  Max:                       %d\n", 1 << cqes_max);
+	printf("  Min:                       %d\n", 1 << cqes_min);
 	printf("Number of Namespaces:        %d\n", cdata->nn);
 	printf("Compare Command:             %s\n",
-		cdata->oncs.compare ? "Supported" : "Not Supported");
+		compare ? "Supported" : "Not Supported");
 	printf("Write Uncorrectable Command: %s\n",
-		cdata->oncs.write_unc ? "Supported" : "Not Supported");
+		write_unc ? "Supported" : "Not Supported");
 	printf("Dataset Management Command:  %s\n",
-		cdata->oncs.dsm ? "Supported" : "Not Supported");
+		dsm ? "Supported" : "Not Supported");
 	printf("Volatile Write Cache:        %s\n",
-		cdata->vwc.present ? "Present" : "Not Present");
+		vwc_present ? "Present" : "Not Present");
 
-	if (cdata->oacs.nsmgmt) {
+	if (nsmgmt) {
 		printf("\n");
 		printf("Namespace Drive Attributes\n");
 		printf("==========================\n");
@@ -132,7 +177,16 @@ static void
 print_namespace(struct nvme_namespace_data *nsdata)
 {
 	uint32_t	i;
+	uint32_t	lbaf, lbads, ms;
+	uint8_t		thin_prov;
+	uint8_t		flbas_fmt;
 
+	thin_prov = (nsdata->nsfeat >> NVME_NS_DATA_NSFEAT_THIN_PROV_SHIFT) &
+		NVME_NS_DATA_NSFEAT_THIN_PROV_MASK;
+
+	flbas_fmt = (nsdata->flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) &
+		NVME_NS_DATA_FLBAS_FORMAT_MASK;
+
 	printf("Size (in LBAs):              %lld (%lldM)\n",
 		(long long)nsdata->nsze,
 		(long long)nsdata->nsze / 1024 / 1024);
@@ -143,13 +197,18 @@ print_namespace(struct nvme_namespace_data *nsdata)
 		(long long)nsdata->nuse,
 		(long long)nsdata->nuse / 1024 / 1024);
 	printf("Thin Provisioning:           %s\n",
-		nsdata->nsfeat.thin_prov ? "Supported" : "Not Supported");
+		thin_prov ? "Supported" : "Not Supported");
 	printf("Number of LBA Formats:       %d\n", nsdata->nlbaf+1);
-	printf("Current LBA Format:          LBA Format #%02d\n",
-		nsdata->flbas.format);
-	for (i = 0; i <= nsdata->nlbaf; i++)
+	printf("Current LBA Format:          LBA Format #%02d\n", flbas_fmt);
+	for (i = 0; i <= nsdata->nlbaf; i++) {
+		lbaf = nsdata->lbaf[i];
+		lbads = (lbaf >> NVME_NS_DATA_LBAF_LBADS_SHIFT) &
+			NVME_NS_DATA_LBAF_LBADS_MASK;
+		ms = (lbaf >> NVME_NS_DATA_LBAF_MS_SHIFT) &
+			NVME_NS_DATA_LBAF_MS_MASK;
 		printf("LBA Format #%02d: Data Size: %5d  Metadata Size: %5d\n",
-		    i, 1 << nsdata->lbaf[i].lbads, nsdata->lbaf[i].ms);
+		    i, 1 << lbads, ms);
+	}
 }
 
 static void

Modified: head/sbin/nvmecontrol/logpage.c
==============================================================================
--- head/sbin/nvmecontrol/logpage.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sbin/nvmecontrol/logpage.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -46,10 +46,6 @@ __FBSDID("$FreeBSD$");
 #include <unistd.h>
 #include <sys/endian.h>
 
-#if _BYTE_ORDER != _LITTLE_ENDIAN
-#error "Code only works on little endian machines"
-#endif
-
 #include "nvmecontrol.h"
 
 #define DEFAULT_SIZE	(4096)
@@ -107,12 +103,15 @@ read_logpage(int fd, uint8_t log_page, int nsid, void 
     uint32_t payload_size)
 {
 	struct nvme_pt_command	pt;
+	struct nvme_error_information_entry	*err_entry;
+	int i, err_pages;
 
 	memset(&pt, 0, sizeof(pt));
-	pt.cmd.opc = NVME_OPC_GET_LOG_PAGE;
-	pt.cmd.nsid = nsid;
+	pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_GET_LOG_PAGE);
+	pt.cmd.nsid = htole32(nsid);
 	pt.cmd.cdw10 = ((payload_size/sizeof(uint32_t)) - 1) << 16;
 	pt.cmd.cdw10 |= log_page;
+	pt.cmd.cdw10 = htole32(pt.cmd.cdw10);
 	pt.buf = payload;
 	pt.len = payload_size;
 	pt.is_read = 1;
@@ -120,6 +119,30 @@ read_logpage(int fd, uint8_t log_page, int nsid, void 
 	if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
 		err(1, "get log page request failed");
 
+	/* Convert data to host endian */
+	switch (log_page) {
+	case NVME_LOG_ERROR:
+		err_entry = (struct nvme_error_information_entry *)payload;
+		err_pages = payload_size / sizeof(struct nvme_error_information_entry);
+		for (i = 0; i < err_pages; i++)
+			nvme_error_information_entry_swapbytes(err_entry++);
+		break;
+	case NVME_LOG_HEALTH_INFORMATION:
+		nvme_health_information_page_swapbytes(
+		    (struct nvme_health_information_page *)payload);
+		break;
+	case NVME_LOG_FIRMWARE_SLOT:
+		nvme_firmware_page_swapbytes(
+		    (struct nvme_firmware_page *)payload);
+		break;
+	case INTEL_LOG_TEMP_STATS:
+		intel_log_temp_stats_swapbytes(
+		    (struct intel_log_temp_stats *)payload);
+		break;
+	default:
+		break;
+	}
+
 	if (nvme_completion_is_error(&pt.cpl))
 		errx(1, "get log page request returned error");
 }
@@ -128,8 +151,9 @@ static void
 print_log_error(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size)
 {
 	int					i, nentries;
+	uint16_t				status;
+	uint8_t					p, sc, sct, m, dnr;
 	struct nvme_error_information_entry	*entry = buf;
-	struct nvme_status			*status;
 
 	printf("Error Information Log\n");
 	printf("=====================\n");
@@ -144,7 +168,14 @@ print_log_error(const struct nvme_controller_data *cda
 		if (entry->error_count == 0)
 			break;
 
-		status = &entry->status;
+		status = entry->status;
+
+		p = NVME_STATUS_GET_P(status);
+		sc = NVME_STATUS_GET_SC(status);
+		sct = NVME_STATUS_GET_SCT(status);
+		m = NVME_STATUS_GET_M(status);
+		dnr = NVME_STATUS_GET_DNR(status);
+
 		printf("Entry %02d\n", i + 1);
 		printf("=========\n");
 		printf(" Error count:          %ju\n", entry->error_count);
@@ -152,11 +183,11 @@ print_log_error(const struct nvme_controller_data *cda
 		printf(" Command ID:           %u\n", entry->cid);
 		/* TODO: Export nvme_status_string structures from kernel? */
 		printf(" Status:\n");
-		printf("  Phase tag:           %d\n", status->p);
-		printf("  Status code:         %d\n", status->sc);
-		printf("  Status code type:    %d\n", status->sct);
-		printf("  More:                %d\n", status->m);
-		printf("  DNR:                 %d\n", status->dnr);
+		printf("  Phase tag:           %d\n", p);
+		printf("  Status code:         %d\n", sc);
+		printf("  Status code type:    %d\n", sct);
+		printf("  More:                %d\n", m);
+		printf("  DNR:                 %d\n", dnr);
 		printf(" Error location:       %u\n", entry->error_location);
 		printf(" LBA:                  %ju\n", entry->lba);
 		printf(" Namespace ID:         %u\n", entry->nsid);
@@ -176,23 +207,25 @@ print_log_health(const struct nvme_controller_data *cd
 {
 	struct nvme_health_information_page *health = buf;
 	char cbuf[UINT128_DIG + 1];
+	uint8_t	warning;
 	int i;
 
+	warning = health->critical_warning;
+
 	printf("SMART/Health Information Log\n");
 	printf("============================\n");
 
-	printf("Critical Warning State:         0x%02x\n",
-	    health->critical_warning.raw);
+	printf("Critical Warning State:         0x%02x\n", warning);
 	printf(" Available spare:               %d\n",
-	    health->critical_warning.bits.available_spare);
+	    !!(warning & NVME_CRIT_WARN_ST_AVAILABLE_SPARE));
 	printf(" Temperature:                   %d\n",
-	    health->critical_warning.bits.temperature);
+	    !!(warning & NVME_CRIT_WARN_ST_TEMPERATURE));
 	printf(" Device reliability:            %d\n",
-	    health->critical_warning.bits.device_reliability);
+	    !!(warning & NVME_CRIT_WARN_ST_DEVICE_RELIABILITY));
 	printf(" Read only:                     %d\n",
-	    health->critical_warning.bits.read_only);
+	    !!(warning & NVME_CRIT_WARN_ST_READ_ONLY));
 	printf(" Volatile memory backup:        %d\n",
-	    health->critical_warning.bits.volatile_memory_backup);
+	    !!(warning & NVME_CRIT_WARN_ST_VOLATILE_MEMORY_BACKUP));
 	printf("Temperature:                    ");
 	print_temp(health->temperature);
 	printf("Available spare:                %u\n",
@@ -225,7 +258,7 @@ print_log_health(const struct nvme_controller_data *cd
 
 	printf("Warning Temp Composite Time:    %d\n", health->warning_temp_time);
 	printf("Error Temp Composite Time:      %d\n", health->error_temp_time);
-	for (i = 0; i < 7; i++) {
+	for (i = 0; i < 8; i++) {
 		if (health->temp_sensor[i] == 0)
 			continue;
 		printf("Temperature Sensor %d:           ", i + 1);
@@ -234,23 +267,34 @@ print_log_health(const struct nvme_controller_data *cd
 }
 
 static void
-print_log_firmware(const struct nvme_controller_data *cdata __unused, void *buf, uint32_t size __unused)
+print_log_firmware(const struct nvme_controller_data *cdata, void *buf, uint32_t size __unused)
 {
 	int				i, slots;
 	const char			*status;
 	struct nvme_firmware_page	*fw = buf;
+	uint8_t				afi_slot;
+	uint16_t			oacs_fw;
+	uint8_t				fw_num_slots;
 
+	afi_slot = fw->afi >> NVME_FIRMWARE_PAGE_AFI_SLOT_SHIFT;
+	afi_slot &= NVME_FIRMWARE_PAGE_AFI_SLOT_MASK;
+
+	oacs_fw = (cdata->oacs >> NVME_CTRLR_DATA_OACS_FIRMWARE_SHIFT) &
+		NVME_CTRLR_DATA_OACS_FIRMWARE_MASK;
+	fw_num_slots = (cdata->frmw >> NVME_CTRLR_DATA_FRMW_NUM_SLOTS_SHIFT) &
+		NVME_CTRLR_DATA_FRMW_NUM_SLOTS_MASK;
+
 	printf("Firmware Slot Log\n");
 	printf("=================\n");
 
-	if (cdata->oacs.firmware == 0)
+	if (oacs_fw == 0)
 		slots = 1;
 	else
-		slots = MIN(cdata->frmw.num_slots, MAX_FW_SLOTS);
+		slots = MIN(fw_num_slots, MAX_FW_SLOTS);
 
 	for (i = 0; i < slots; i++) {
 		printf("Slot %d: ", i + 1);
-		if (fw->afi.slot == i + 1)
+		if (afi_slot == i + 1)
 			status = "  Active";
 		else
 			status = "Inactive";
@@ -868,7 +912,8 @@ logpage(int argc, char *argv[])
 	int				fd, nsid;
 	int				log_page = 0, pageflag = false;
 	int				binflag = false, hexflag = false, ns_specified;
-	char				ch, *p;
+	int				opt;
+	char				*p;
 	char				cname[64];
 	uint32_t			size;
 	void				*buf;
@@ -876,9 +921,10 @@ logpage(int argc, char *argv[])
 	struct logpage_function		*f;
 	struct nvme_controller_data	cdata;
 	print_fn_t			print_fn;
+	uint8_t				ns_smart;
 
-	while ((ch = getopt(argc, argv, "bp:xv:")) != -1) {
-		switch (ch) {
+	while ((opt = getopt(argc, argv, "bp:xv:")) != -1) {
+		switch (opt) {
 		case 'b':
 			binflag = true;
 			break;
@@ -928,6 +974,9 @@ logpage(int argc, char *argv[])
 
 	read_controller_data(fd, &cdata);
 
+	ns_smart = (cdata.lpa >> NVME_CTRLR_DATA_LPA_NS_SMART_SHIFT) &
+		NVME_CTRLR_DATA_LPA_NS_SMART_MASK;
+
 	/*
 	 * The log page attribtues indicate whether or not the controller
 	 * supports the SMART/Health information log page on a per
@@ -937,7 +986,7 @@ logpage(int argc, char *argv[])
 		if (log_page != NVME_LOG_HEALTH_INFORMATION)
 			errx(1, "log page %d valid only at controller level",
 			    log_page);
-		if (cdata.lpa.ns_smart == 0)
+		if (ns_smart == 0)
 			errx(1,
 			    "controller does not support per namespace "
 			    "smart/health information");

Modified: head/sbin/nvmecontrol/nvmecontrol.c
==============================================================================
--- head/sbin/nvmecontrol/nvmecontrol.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sbin/nvmecontrol/nvmecontrol.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -146,8 +146,8 @@ read_controller_data(int fd, struct nvme_controller_da
 	struct nvme_pt_command	pt;
 
 	memset(&pt, 0, sizeof(pt));
-	pt.cmd.opc = NVME_OPC_IDENTIFY;
-	pt.cmd.cdw10 = 1;
+	pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_IDENTIFY);
+	pt.cmd.cdw10 = htole32(1);
 	pt.buf = cdata;
 	pt.len = sizeof(*cdata);
 	pt.is_read = 1;
@@ -155,6 +155,9 @@ read_controller_data(int fd, struct nvme_controller_da
 	if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
 		err(1, "identify request failed");
 
+	/* Convert data to host endian */
+	nvme_controller_data_swapbytes(cdata);
+
 	if (nvme_completion_is_error(&pt.cpl))
 		errx(1, "identify request returned error");
 }
@@ -165,14 +168,17 @@ read_namespace_data(int fd, int nsid, struct nvme_name
 	struct nvme_pt_command	pt;
 
 	memset(&pt, 0, sizeof(pt));
-	pt.cmd.opc = NVME_OPC_IDENTIFY;
-	pt.cmd.nsid = nsid;
+	pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_IDENTIFY);
+	pt.cmd.nsid = htole32(nsid);
 	pt.buf = nsdata;
 	pt.len = sizeof(*nsdata);
 	pt.is_read = 1;
 
 	if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
 		err(1, "identify request failed");
+
+	/* Convert data to host endian */
+	nvme_namespace_data_swapbytes(nsdata);
 
 	if (nvme_completion_is_error(&pt.cpl))
 		errx(1, "identify request returned error");

Modified: head/sbin/nvmecontrol/perftest.c
==============================================================================
--- head/sbin/nvmecontrol/perftest.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sbin/nvmecontrol/perftest.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -81,7 +81,7 @@ perftest(int argc, char *argv[])
 {
 	struct nvme_io_test		io_test;
 	int				fd;
-	char				ch;
+	int				opt;
 	char				*p;
 	u_long				ioctl_cmd = NVME_IO_TEST;
 	bool				nflag, oflag, sflag, tflag;
@@ -91,8 +91,8 @@ perftest(int argc, char *argv[])
 
 	memset(&io_test, 0, sizeof(io_test));
 
-	while ((ch = getopt(argc, argv, "f:i:n:o:ps:t:")) != -1) {
-		switch (ch) {
+	while ((opt = getopt(argc, argv, "f:i:n:o:ps:t:")) != -1) {
+		switch (opt) {
 		case 'f':
 			if (!strcmp(optarg, "refthread"))
 				io_test.flags |= NVME_TEST_FLAG_REFTHREAD;

Modified: head/sbin/nvmecontrol/power.c
==============================================================================
--- head/sbin/nvmecontrol/power.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sbin/nvmecontrol/power.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -56,22 +56,32 @@ static void
 power_list_one(int i, struct nvme_power_state *nps)
 {
 	int mpower, apower, ipower;
+	uint8_t mps, nops, aps, apw;
 
+	mps = (nps->mps_nops >> NVME_PWR_ST_MPS_SHIFT) &
+		NVME_PWR_ST_MPS_MASK;
+	nops = (nps->mps_nops >> NVME_PWR_ST_NOPS_SHIFT) &
+		NVME_PWR_ST_NOPS_MASK;
+	apw = (nps->apw_aps >> NVME_PWR_ST_APW_SHIFT) &
+		NVME_PWR_ST_APW_MASK;
+	aps = (nps->apw_aps >> NVME_PWR_ST_APS_SHIFT) &
+		NVME_PWR_ST_APS_MASK;
+
 	mpower = nps->mp;
-	if (nps->mps == 0)
+	if (mps == 0)
 		mpower *= 100;
 	ipower = nps->idlp;
 	if (nps->ips == 1)
 		ipower *= 100;
 	apower = nps->actp;
-	if (nps->aps == 1)
+	if (aps == 1)
 		apower *= 100;
 	printf("%2d: %2d.%04dW%c %3d.%03dms %3d.%03dms %2d %2d %2d %2d %2d.%04dW %2d.%04dW %d\n",
 	       i, mpower / 10000, mpower % 10000,
-	       nps->nops ? '*' : ' ', nps->enlat / 1000, nps->enlat % 1000,
+	       nops ? '*' : ' ', nps->enlat / 1000, nps->enlat % 1000,
 	       nps->exlat / 1000, nps->exlat % 1000, nps->rrt, nps->rrl,
 	       nps->rwt, nps->rwl, ipower / 10000, ipower % 10000,
-	       apower / 10000, apower % 10000, nps->apw);
+	       apower / 10000, apower % 10000, apw);
 }
 
 static void
@@ -94,9 +104,9 @@ power_set(int fd, int power_val, int workload, int per
 
 	p = perm ? (1u << 31) : 0;
 	memset(&pt, 0, sizeof(pt));
-	pt.cmd.opc = NVME_OPC_SET_FEATURES;
-	pt.cmd.cdw10 = NVME_FEAT_POWER_MANAGEMENT | p;
-	pt.cmd.cdw11 = power_val | (workload << 5);
+	pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_SET_FEATURES);
+	pt.cmd.cdw10 = htole32(NVME_FEAT_POWER_MANAGEMENT | p);
+	pt.cmd.cdw11 = htole32(power_val | (workload << 5));
 
 	if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
 		err(1, "set feature power mgmt request failed");
@@ -111,8 +121,8 @@ power_show(int fd)
 	struct nvme_pt_command	pt;
 
 	memset(&pt, 0, sizeof(pt));
-	pt.cmd.opc = NVME_OPC_GET_FEATURES;
-	pt.cmd.cdw10 = NVME_FEAT_POWER_MANAGEMENT;
+	pt.cmd.opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_GET_FEATURES);
+	pt.cmd.cdw10 = htole32(NVME_FEAT_POWER_MANAGEMENT);
 
 	if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
 		err(1, "set feature power mgmt request failed");

Modified: head/sbin/nvmecontrol/wdc.c
==============================================================================
--- head/sbin/nvmecontrol/wdc.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sbin/nvmecontrol/wdc.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -81,10 +81,10 @@ wdc_get_data(int fd, uint32_t opcode, uint32_t len, ui
 	struct nvme_pt_command	pt;
 
 	memset(&pt, 0, sizeof(pt));
-	pt.cmd.opc = opcode;
-	pt.cmd.cdw10 = len / sizeof(uint32_t);	/* - 1 like all the others ??? */
-	pt.cmd.cdw11 = off / sizeof(uint32_t);
-	pt.cmd.cdw12 = cmd;
+	pt.cmd.opc_fuse = NVME_CMD_SET_OPC(opcode);
+	pt.cmd.cdw10 = htole32(len / sizeof(uint32_t));	/* - 1 like all the others ??? */
+	pt.cmd.cdw11 = htole32(off / sizeof(uint32_t));
+	pt.cmd.cdw12 = htole32(cmd);
 	pt.buf = buffer;
 	pt.len = buflen;
 	pt.is_read = 1;

Modified: head/sys/cam/nvme/nvme_all.c
==============================================================================
--- head/sys/cam/nvme/nvme_all.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sys/cam/nvme/nvme_all.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -70,14 +70,14 @@ nvme_ns_cmd(struct ccb_nvmeio *nvmeio, uint8_t cmd, ui
     uint32_t cdw14, uint32_t cdw15)
 {
 	bzero(&nvmeio->cmd, sizeof(struct nvme_command));
-	nvmeio->cmd.opc = cmd;
-	nvmeio->cmd.nsid = nsid;
-	nvmeio->cmd.cdw10 = cdw10;
-	nvmeio->cmd.cdw11 = cdw11;
-	nvmeio->cmd.cdw12 = cdw12;
-	nvmeio->cmd.cdw13 = cdw13;
-	nvmeio->cmd.cdw14 = cdw14;
-	nvmeio->cmd.cdw15 = cdw15;
+	nvmeio->cmd.opc_fuse = NVME_CMD_SET_OPC(cmd);
+	nvmeio->cmd.nsid = htole32(nsid);
+	nvmeio->cmd.cdw10 = htole32(cdw10);
+	nvmeio->cmd.cdw11 = htole32(cdw11);
+	nvmeio->cmd.cdw12 = htole32(cdw12);
+	nvmeio->cmd.cdw13 = htole32(cdw13);
+	nvmeio->cmd.cdw14 = htole32(cdw14);
+	nvmeio->cmd.cdw15 = htole32(cdw15);
 }
 
 int
@@ -118,24 +118,32 @@ nvme_opc2str[] = {
 const char *
 nvme_op_string(const struct nvme_command *cmd)
 {
-	if (cmd->opc > nitems(nvme_opc2str))
+	uint8_t opc;
+
+	opc = (cmd->opc_fuse >> NVME_CMD_OPC_SHIFT) & NVME_CMD_OPC_MASK;
+	if (opc > nitems(nvme_opc2str))
 		return "UNKNOWN";
 
-	return nvme_opc2str[cmd->opc];
+	return nvme_opc2str[opc];
 }
 
 const char *
 nvme_cmd_string(const struct nvme_command *cmd, char *cmd_string, size_t len)
 {
+	uint8_t opc, fuse;
+
+	opc = (cmd->opc_fuse >> NVME_CMD_OPC_SHIFT) & NVME_CMD_OPC_MASK;
+	fuse = (cmd->opc_fuse >> NVME_CMD_FUSE_SHIFT) & NVME_CMD_FUSE_MASK;
 	/*
 	 * cid, rsvd areas and mptr not printed, since they are used
 	 * only internally by the SIM.
 	 */
 	snprintf(cmd_string, len,
 	    "opc=%x fuse=%x nsid=%x prp1=%llx prp2=%llx cdw=%x %x %x %x %x %x",
-	    cmd->opc, cmd->fuse, cmd->nsid,
+	    opc, fuse, cmd->nsid,
 	    (unsigned long long)cmd->prp1, (unsigned long long)cmd->prp2,
-	    cmd->cdw10, cmd->cdw11, cmd->cdw12, cmd->cdw13, cmd->cdw14, cmd->cdw15);
+	    cmd->cdw10, cmd->cdw11, cmd->cdw12,
+	    cmd->cdw13, cmd->cdw14, cmd->cdw15);
 
 	return cmd_string;
 }

Modified: head/sys/cam/nvme/nvme_da.c
==============================================================================
--- head/sys/cam/nvme/nvme_da.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sys/cam/nvme/nvme_da.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -676,6 +676,7 @@ ndaregister(struct cam_periph *periph, void *arg)
 	const struct nvme_namespace_data *nsd;
 	const struct nvme_controller_data *cd;
 	char   announce_buf[80];
+	uint8_t flbas_fmt, lbads, vwc_present;
 	u_int maxio;
 	int quirks;
 
@@ -744,13 +745,19 @@ ndaregister(struct cam_periph *periph, void *arg)
 	else if (maxio > MAXPHYS)
 		maxio = MAXPHYS;	/* for safety */
 	disk->d_maxsize = maxio;
-	disk->d_sectorsize = 1 << nsd->lbaf[nsd->flbas.format].lbads;
+	flbas_fmt = (nsd->flbas >> NVME_NS_DATA_FLBAS_FORMAT_SHIFT) &
+		NVME_NS_DATA_FLBAS_FORMAT_MASK;
+	lbads = (nsd->lbaf[flbas_fmt] >> NVME_NS_DATA_LBAF_LBADS_SHIFT) &
+		NVME_NS_DATA_LBAF_LBADS_MASK;
+	disk->d_sectorsize = 1 << lbads;
 	disk->d_mediasize = (off_t)(disk->d_sectorsize * nsd->nsze);
 	disk->d_delmaxsize = disk->d_mediasize;
 	disk->d_flags = DISKFLAG_DIRECT_COMPLETION;
 //	if (cd->oncs.dsm) // XXX broken?
 		disk->d_flags |= DISKFLAG_CANDELETE;
-	if (cd->vwc.present)
+	vwc_present = (cd->vwc >> NVME_CTRLR_DATA_VWC_PRESENT_SHIFT) &
+		NVME_CTRLR_DATA_VWC_PRESENT_MASK;
+	if (vwc_present)
 		disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
 	if ((cpi.hba_misc & PIM_UNMAPPED) != 0) {
 		disk->d_flags |= DISKFLAG_UNMAPPED_BIO;
@@ -905,9 +912,9 @@ ndastart(struct cam_periph *periph, union ccb *start_c
 				return;
 			}
 			dsm_range->length =
-			    bp->bio_bcount / softc->disk->d_sectorsize;
+			    htole32(bp->bio_bcount / softc->disk->d_sectorsize);
 			dsm_range->starting_lba =
-			    bp->bio_offset / softc->disk->d_sectorsize;
+			    htole64(bp->bio_offset / softc->disk->d_sectorsize);
 			bp->bio_driver2 = dsm_range;
 			nda_nvme_trim(softc, &start_ccb->nvmeio, dsm_range, 1);
 			start_ccb->ccb_h.ccb_state = NDA_CCB_TRIM;

Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sys/conf/files	Thu Feb 22 13:32:31 2018	(r329824)
@@ -2535,6 +2535,17 @@ dev/nmdm/nmdm.c			optional nmdm
 dev/nsp/nsp.c			optional nsp
 dev/nsp/nsp_pccard.c		optional nsp pccard
 dev/null/null.c			standard
+dev/nvd/nvd.c			optional nvd nvme
+dev/nvme/nvme.c			optional nvme
+dev/nvme/nvme_ctrlr.c		optional nvme
+dev/nvme/nvme_ctrlr_cmd.c	optional nvme
+dev/nvme/nvme_ns.c		optional nvme
+dev/nvme/nvme_ns_cmd.c		optional nvme
+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/oce/oce_hw.c		optional oce pci
 dev/oce/oce_if.c		optional oce pci
 dev/oce/oce_mbox.c		optional oce pci

Modified: head/sys/dev/mpr/mpr_sas.c
==============================================================================
--- head/sys/dev/mpr/mpr_sas.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sys/dev/mpr/mpr_sas.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -1839,7 +1839,7 @@ mprsas_build_nvme_unmap(struct mpr_softc *sc, struct m
 
 	/* Build NVMe DSM command */
 	c = (struct nvme_command *) req->NVMe_Command;
-	c->opc = NVME_OPC_DATASET_MANAGEMENT;
+	c->opc_fuse = NVME_CMD_SET_OPC(NVME_OPC_DATASET_MANAGEMENT);
 	c->nsid = htole32(csio->ccb_h.target_lun + 1);
 	c->cdw10 = htole32(ndesc - 1);
 	c->cdw11 = htole32(NVME_DSM_ATTR_DEALLOCATE);
@@ -2263,22 +2263,26 @@ mpr_sc_failed_io_info(struct mpr_softc *sc, struct ccb
  * Returns appropriate scsi_status
  */
 static u8
-mprsas_nvme_trans_status_code(struct nvme_status nvme_status,
+mprsas_nvme_trans_status_code(uint16_t nvme_status,
     struct mpr_command *cm)
 {
 	u8 status = MPI2_SCSI_STATUS_GOOD;
 	int skey, asc, ascq;
 	union ccb *ccb = cm->cm_complete_data;
 	int returned_sense_len;
+	uint8_t sct, sc;
 
+	sct = NVME_STATUS_GET_SCT(nvme_status);
+	sc = NVME_STATUS_GET_SC(nvme_status);
+
 	status = MPI2_SCSI_STATUS_CHECK_CONDITION;
 	skey = SSD_KEY_ILLEGAL_REQUEST;
 	asc = SCSI_ASC_NO_SENSE;
 	ascq = SCSI_ASCQ_CAUSE_NOT_REPORTABLE;
 
-	switch (nvme_status.sct) {
+	switch (sct) {
 	case NVME_SCT_GENERIC:
-		switch (nvme_status.sc) {
+		switch (sc) {
 		case NVME_SC_SUCCESS:
 			status = MPI2_SCSI_STATUS_GOOD;
 			skey = SSD_KEY_NO_SENSE;
@@ -2351,7 +2355,7 @@ mprsas_nvme_trans_status_code(struct nvme_status nvme_
 		}
 		break;
 	case NVME_SCT_COMMAND_SPECIFIC:
-		switch (nvme_status.sc) {
+		switch (sc) {
 		case NVME_SC_INVALID_FORMAT:
 			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
 			skey = SSD_KEY_ILLEGAL_REQUEST;
@@ -2367,7 +2371,7 @@ mprsas_nvme_trans_status_code(struct nvme_status nvme_
 		}
 		break;
 	case NVME_SCT_MEDIA_ERROR:
-		switch (nvme_status.sc) {
+		switch (sc) {
 		case NVME_SC_WRITE_FAULTS:
 			status = MPI2_SCSI_STATUS_CHECK_CONDITION;
 			skey = SSD_KEY_MEDIUM_ERROR;

Modified: head/sys/dev/nvme/nvme.c
==============================================================================
--- head/sys/dev/nvme/nvme.c	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sys/dev/nvme/nvme.c	Thu Feb 22 13:32:31 2018	(r329824)
@@ -222,23 +222,38 @@ nvme_modevent(module_t mod, int type, void *arg)
 void
 nvme_dump_command(struct nvme_command *cmd)
 {
+	uint8_t opc, fuse;
+
+	opc = (cmd->opc_fuse >> NVME_CMD_OPC_SHIFT) & NVME_CMD_OPC_MASK;
+	fuse = (cmd->opc_fuse >> NVME_CMD_FUSE_SHIFT) & NVME_CMD_FUSE_MASK;
+
 	printf(
-"opc:%x f:%x r1:%x cid:%x nsid:%x r2:%x r3:%x mptr:%jx prp1:%jx prp2:%jx cdw:%x %x %x %x %x %x\n",
-	    cmd->opc, cmd->fuse, cmd->rsvd1, cmd->cid, cmd->nsid,
+"opc:%x f:%x cid:%x nsid:%x r2:%x r3:%x mptr:%jx prp1:%jx prp2:%jx cdw:%x %x %x %x %x %x\n",
+	    opc, fuse, cmd->cid, le32toh(cmd->nsid),
 	    cmd->rsvd2, cmd->rsvd3,
-	    (uintmax_t)cmd->mptr, (uintmax_t)cmd->prp1, (uintmax_t)cmd->prp2,
-	    cmd->cdw10, cmd->cdw11, cmd->cdw12, cmd->cdw13, cmd->cdw14,
-	    cmd->cdw15);
+	    (uintmax_t)le64toh(cmd->mptr), (uintmax_t)le64toh(cmd->prp1), (uintmax_t)le64toh(cmd->prp2),
+	    le32toh(cmd->cdw10), le32toh(cmd->cdw11), le32toh(cmd->cdw12),
+	    le32toh(cmd->cdw13), le32toh(cmd->cdw14), le32toh(cmd->cdw15));
 }
 
 void
 nvme_dump_completion(struct nvme_completion *cpl)
 {
+	uint8_t p, sc, sct, m, dnr;
+	uint16_t status;
+
+	status = le16toh(cpl->status);
+
+	p = NVME_STATUS_GET_P(status);
+	sc = NVME_STATUS_GET_SC(status);
+	sct = NVME_STATUS_GET_SCT(status);
+	m = NVME_STATUS_GET_M(status);
+	dnr = NVME_STATUS_GET_DNR(status);
+
 	printf("cdw0:%08x sqhd:%04x sqid:%04x "
 	    "cid:%04x p:%x sc:%02x sct:%x m:%x dnr:%x\n",
-	    cpl->cdw0, cpl->sqhd, cpl->sqid,
-	    cpl->cid, cpl->status.p, cpl->status.sc, cpl->status.sct,
-	    cpl->status.m, cpl->status.dnr);
+	    le32toh(cpl->cdw0), le16toh(cpl->sqhd), le16toh(cpl->sqid),
+	    cpl->cid, p, sc, sct, m, dnr);
 }
 
 static int

Modified: head/sys/dev/nvme/nvme.h
==============================================================================
--- head/sys/dev/nvme/nvme.h	Thu Feb 22 13:06:27 2018	(r329823)
+++ head/sys/dev/nvme/nvme.h	Thu Feb 22 13:32:31 2018	(r329824)
@@ -36,6 +36,7 @@
 #endif
 
 #include <sys/param.h>
+#include <sys/endian.h>
 
 #define	NVME_PASSTHROUGH_CMD		_IOWR('n', 0, struct nvme_pt_command)
 #define	NVME_RESET_CONTROLLER		_IO('n', 1)
@@ -59,153 +60,264 @@
 /* Cap nvme to 1MB transfers driver explodes with larger sizes */
 #define NVME_MAX_XFER_SIZE		(MAXPHYS < (1<<20) ? MAXPHYS : (1<<20))
 
-union cap_lo_register {
-	uint32_t	raw;
-	struct {
-		/** maximum queue entries supported */
-		uint32_t mqes		: 16;
+/* Register field definitions */
+#define NVME_CAP_LO_REG_MQES_SHIFT			(0)
+#define NVME_CAP_LO_REG_MQES_MASK			(0xFFFF)
+#define NVME_CAP_LO_REG_CQR_SHIFT			(16)
+#define NVME_CAP_LO_REG_CQR_MASK			(0x1)
+#define NVME_CAP_LO_REG_AMS_SHIFT			(17)
+#define NVME_CAP_LO_REG_AMS_MASK			(0x3)
+#define NVME_CAP_LO_REG_TO_SHIFT			(24)
+#define NVME_CAP_LO_REG_TO_MASK				(0xFF)
 
-		/** contiguous queues required */
-		uint32_t cqr		: 1;
+#define NVME_CAP_HI_REG_DSTRD_SHIFT			(0)
+#define NVME_CAP_HI_REG_DSTRD_MASK			(0xF)
+#define NVME_CAP_HI_REG_CSS_NVM_SHIFT			(5)
+#define NVME_CAP_HI_REG_CSS_NVM_MASK			(0x1)
+#define NVME_CAP_HI_REG_MPSMIN_SHIFT			(16)
+#define NVME_CAP_HI_REG_MPSMIN_MASK			(0xF)
+#define NVME_CAP_HI_REG_MPSMAX_SHIFT			(20)
+#define NVME_CAP_HI_REG_MPSMAX_MASK			(0xF)
 
-		/** arbitration mechanism supported */
-		uint32_t ams		: 2;
+#define NVME_CC_REG_EN_SHIFT				(0)
+#define NVME_CC_REG_EN_MASK				(0x1)
+#define NVME_CC_REG_CSS_SHIFT				(4)
+#define NVME_CC_REG_CSS_MASK				(0x7)
+#define NVME_CC_REG_MPS_SHIFT				(7)
+#define NVME_CC_REG_MPS_MASK				(0xF)
+#define NVME_CC_REG_AMS_SHIFT				(11)
+#define NVME_CC_REG_AMS_MASK				(0x7)
+#define NVME_CC_REG_SHN_SHIFT				(14)
+#define NVME_CC_REG_SHN_MASK				(0x3)
+#define NVME_CC_REG_IOSQES_SHIFT			(16)
+#define NVME_CC_REG_IOSQES_MASK				(0xF)
+#define NVME_CC_REG_IOCQES_SHIFT			(20)
+#define NVME_CC_REG_IOCQES_MASK				(0xF)
 
-		uint32_t reserved1	: 5;
+#define NVME_CSTS_REG_RDY_SHIFT				(0)
+#define NVME_CSTS_REG_RDY_MASK				(0x1)
+#define NVME_CSTS_REG_CFS_SHIFT				(1)
+#define NVME_CSTS_REG_CFS_MASK				(0x1)
+#define NVME_CSTS_REG_SHST_SHIFT			(2)
+#define NVME_CSTS_REG_SHST_MASK				(0x3)
 
-		/** timeout */
-		uint32_t to		: 8;
-	} bits __packed;
-} __packed;
+#define NVME_CSTS_GET_SHST(csts)			(((csts) >> NVME_CSTS_REG_SHST_SHIFT) & NVME_CSTS_REG_SHST_MASK)
 
-_Static_assert(sizeof(union cap_lo_register) == 4, "bad size for cap_lo_register");
+#define NVME_AQA_REG_ASQS_SHIFT				(0)
+#define NVME_AQA_REG_ASQS_MASK				(0xFFF)
+#define NVME_AQA_REG_ACQS_SHIFT				(16)
+#define NVME_AQA_REG_ACQS_MASK				(0xFFF)
 
-union cap_hi_register {
-	uint32_t	raw;
-	struct {
-		/** doorbell stride */
-		uint32_t dstrd		: 4;
+/* Command field definitions */
 
-		uint32_t reserved3	: 1;
+#define NVME_CMD_OPC_SHIFT				(0)
+#define NVME_CMD_OPC_MASK				(0xFF)
+#define NVME_CMD_FUSE_SHIFT				(8)
+#define NVME_CMD_FUSE_MASK				(0x3)
 
-		/** command sets supported */
-		uint32_t css_nvm	: 1;
+#define NVME_CMD_SET_OPC(opc)				(htole16(((opc) & NVME_CMD_OPC_MASK) << NVME_CMD_OPC_SHIFT))
 
-		uint32_t css_reserved	: 3;
-		uint32_t reserved2	: 7;
+#define NVME_STATUS_P_SHIFT				(0)
+#define NVME_STATUS_P_MASK				(0x1)
+#define NVME_STATUS_SC_SHIFT				(1)
+#define NVME_STATUS_SC_MASK				(0xFF)
+#define NVME_STATUS_SCT_SHIFT				(9)
+#define NVME_STATUS_SCT_MASK				(0x7)
+#define NVME_STATUS_M_SHIFT				(14)
+#define NVME_STATUS_M_MASK				(0x1)
+#define NVME_STATUS_DNR_SHIFT				(15)
+#define NVME_STATUS_DNR_MASK				(0x1)

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-head mailing list