Sat Apr 29 00:06:40 2017 UTC ()
nvmectl(8): sync with FreeBSD HEAD r316105.

 - Expand the SMART / Health Information Log Page (Page 02) printout based on
   NVM Express 1.2.1 Standard.
 - Implement Intel-specific log pages.
 - Implement HGST-specific log pages.
 - Implement wdc-specific nvme control options.
 - Add the ability to dump log pages directly in binary to stdout.


(nonaka)
diff -r1.2 -r1.3 src/sbin/nvmectl/Makefile
diff -r1.2 -r1.3 src/sbin/nvmectl/nvmectl.8
diff -r1.2 -r1.3 src/sbin/nvmectl/nvmectl.c
diff -r1.2 -r1.3 src/sbin/nvmectl/nvmectl.h
diff -r1.1 -r1.2 src/sbin/nvmectl/firmware.c
diff -r1.1 -r1.2 src/sbin/nvmectl/nvme.h
diff -r1.3 -r1.4 src/sbin/nvmectl/logpage.c

cvs diff -r1.2 -r1.3 src/sbin/nvmectl/Makefile (expand / switch to unified diff)

--- src/sbin/nvmectl/Makefile 2017/02/13 11:16:46 1.2
+++ src/sbin/nvmectl/Makefile 2017/04/29 00:06:40 1.3
@@ -1,21 +1,22 @@ @@ -1,21 +1,22 @@
1# $NetBSD: Makefile,v 1.2 2017/02/13 11:16:46 nonaka Exp $ 1# $NetBSD: Makefile,v 1.3 2017/04/29 00:06:40 nonaka Exp $
2 2
3.include <bsd.own.mk> 3.include <bsd.own.mk>
4 4
5PROG= nvmectl 5PROG= nvmectl
6SRCS= nvmectl.c 6SRCS= nvmectl.c
7SRCS+= devlist.c 7SRCS+= devlist.c
8SRCS+= firmware.c 8SRCS+= firmware.c
9SRCS+= identify.c 9SRCS+= identify.c
10SRCS+= logpage.c 10SRCS+= logpage.c
11SRCS+= perftest.c 11SRCS+= perftest.c
12SRCS+= power.c 12SRCS+= power.c
13SRCS+= reset.c 13SRCS+= reset.c
 14SRCS+= wdc.c
14SRCS+= bignum.c 15SRCS+= bignum.c
15SRCS+= humanize_bignum.c 16SRCS+= humanize_bignum.c
16MAN= nvmectl.8 17MAN= nvmectl.8
17 18
18DPADD+= ${LIBUTIL} 19DPADD+= ${LIBUTIL}
19LDADD+= -lutil 20LDADD+= -lutil
20 21
21.include <bsd.prog.mk> 22.include <bsd.prog.mk>

cvs diff -r1.2 -r1.3 src/sbin/nvmectl/nvmectl.8 (expand / switch to unified diff)

--- src/sbin/nvmectl/nvmectl.8 2016/06/05 09:13:08 1.2
+++ src/sbin/nvmectl/nvmectl.8 2017/04/29 00:06:40 1.3
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1.\" $NetBSD: nvmectl.8,v 1.2 2016/06/05 09:13:08 wiz Exp $ 1.\" $NetBSD: nvmectl.8,v 1.3 2017/04/29 00:06:40 nonaka Exp $
2.\" 2.\"
3.\" Copyright (c) 2012 Intel Corporation 3.\" Copyright (c) 2012 Intel Corporation
4.\" All rights reserved. 4.\" All rights reserved.
5.\" 5.\"
6.\" Redistribution and use in source and binary forms, with or without 6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions 7.\" modification, are permitted provided that the following conditions
8.\" are met: 8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright 9.\" 1. Redistributions of source code must retain the above copyright
10.\" notice, this list of conditions, and the following disclaimer, 10.\" notice, this list of conditions, and the following disclaimer,
11.\" without modification. 11.\" without modification.
12.\" 2. Redistributions in binary form must reproduce at minimum a disclaimer 12.\" 2. Redistributions in binary form must reproduce at minimum a disclaimer
13.\" substantially similar to the "NO WARRANTY" disclaimer below 13.\" substantially similar to the "NO WARRANTY" disclaimer below
14.\" ("Disclaimer") and any redistribution must be conditioned upon 14.\" ("Disclaimer") and any redistribution must be conditioned upon
@@ -22,27 +22,27 @@ @@ -22,27 +22,27 @@
22.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22.\" A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23.\" HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23.\" HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 26.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 27.\" STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
28.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28.\" IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29.\" POSSIBILITY OF SUCH DAMAGES. 29.\" POSSIBILITY OF SUCH DAMAGES.
30.\" 30.\"
31.\" nvmecontrol man page. 31.\" nvmecontrol man page.
32.\" 32.\"
33.\" Author: Jim Harris <jimharris@FreeBSD.org> 33.\" Author: Jim Harris <jimharris@FreeBSD.org>
34.\" 34.\"
35.\" $FreeBSD: head/sbin/nvmecontrol/nvmecontrol.8 299151 2016-05-06 03:11:34Z pfg $ 35.\" $FreeBSD: head/sbin/nvmecontrol/nvmecontrol.8 314230 2017-02-25 00:09:16Z imp $
36.\" 36.\"
37.Dd May 19, 2016 37.Dd May 19, 2016
38.Dt NVMECTL 8 38.Dt NVMECTL 8
39.Os 39.Os
40.Sh NAME 40.Sh NAME
41.Nm nvmectl 41.Nm nvmectl
42.Nd NVM Express control utility 42.Nd NVM Express control utility
43.Sh SYNOPSIS 43.Sh SYNOPSIS
44.Nm 44.Nm
45.Ic devlist 45.Ic devlist
46.Nm 46.Nm
47.Ic identify 47.Ic identify
48.Op Fl x Op Fl v 48.Op Fl x Op Fl v
@@ -52,96 +52,159 @@ @@ -52,96 +52,159 @@
52.\".Op Fl p 52.\".Op Fl p
53.\".Aq Fl n Ar num_threads 53.\".Aq Fl n Ar num_threads
54.\".Aq Fl o Ar read|write 54.\".Aq Fl o Ar read|write
55.\".Aq Fl s Ar size_in_bytes 55.\".Aq Fl s Ar size_in_bytes
56.\".Aq Fl t Ar time_in_sec 56.\".Aq Fl t Ar time_in_sec
57.\".Aq namespace id 57.\".Aq namespace id
58.\".Nm 58.\".Nm
59.\".Ic reset 59.\".Ic reset
60.\".Aq controller id 60.\".Aq controller id
61.Nm 61.Nm
62.Ic logpage 62.Ic logpage
63.Op Fl x 63.Op Fl x
64.Op Fl p Ar page_id 64.Op Fl p Ar page_id
 65.Op Fl v Ar vendor-string
 66.Op Fl b
65.Ar device_id Ns | Ns Ar namespace_id 67.Ar device_id Ns | Ns Ar namespace_id
66.\".Nm 68.\".Nm
67.\".Ic firmware 69.\".Ic firmware
68.\".Op Fl a 70.\".Op Fl a
69.\".Op Fl s Ar slot 71.\".Op Fl s Ar slot
70.\".Op Fl f Ar path_to_firmware 72.\".Op Fl f Ar path_to_firmware
71.\".Aq device id 73.\".Aq device id
72.Nm 74.Nm
73.Ic power 75.Ic power
74.Op Fl l 76.Op Fl l
75.Op Fl p Ar power_state 77.Op Fl p Ar power_state
76.Op Fl w Ar workload_hint 78.Op Fl w Ar workload_hint
77.Ar device_id 79.Ar device_id
 80.Nm
 81.Ic wdc cap-diag
 82.Op Fl o path_template
 83.Ar device id
 84.Nm
 85.Ic wdc drive-log
 86.Op Fl o path_template
 87.Ar device id
 88.Nm
 89.Ic wdc get-crash-dump
 90.Op Fl o path_template
 91.Ar device id
 92.\" .Nm
 93.\" .Ic wdc purge
 94.\" .Aq device id
 95.\" .Nm
 96.\" .Ic wdc purge-monitor
 97.\" .Aq device id
78.Sh DESCRIPTION 98.Sh DESCRIPTION
79NVM Express (NVMe) is a storage protocol standard, for SSDs and other 99NVM Express (NVMe) is a storage protocol standard, for SSDs and other
80high-speed storage devices over PCI Express. 100high-speed storage devices over PCI Express.
 101.Pp
 102.Ss logpage
 103The logpage command knows how to print log pages of various types.
 104It also knows about vendor specific log pages from hgst/wdc and intel.
 105Page 0xc1 for hgst/wdc contains the advanced smart information about
 106the drive.
 107Page 0xc1 is read latency stats for intel.
 108Page 0xc2 is write latency stats for intel.
 109Page 0xc5 is temperature stats for intel.
 110Page 0xca is advanced smart information for intel.
 111.Pp
 112Specifying
 113.Fl p
 114.Ic help
 115will list all valid vendors and pages.
 116.Fl x
 117will print the page as hex.
 118.Fl b
 119will print the binary data for the page.
 120.Ss wdc
 121The various wdc command retrieve log data from the wdc/hgst drives.
 122The
 123.Fl o
 124flag specifies a path template to use to output the files.
 125Each file takes the path template (which defaults to nothing), appends
 126the drive's serial number and the type of dump it is followed
 127by .bin.
 128These logs must be sent to the vendor for analysis.
 129This tool only provides a way to extract them.
81.Sh EXAMPLES 130.Sh EXAMPLES
82.Dl nvmectl devlist 131.Dl nvmectl devlist
83.Pp 132.Pp
84Display a list of NVMe controllers and namespaces along with their device nodes. 133Display a list of NVMe controllers and namespaces along with their device nodes.
85.Pp 134.Pp
86.Dl nvmectl identify nvme0 135.Dl nvmectl identify nvme0
87.Pp 136.Pp
88Display a human-readable summary of the nvme0 IDENTIFY_CONTROLLER data. 137Display a human-readable summary of the nvme0 IDENTIFY_CONTROLLER data.
89.Pp 138.Pp
90.Dl nvmectl identify -x -v nvme0ns1 139.Dl nvmectl identify -x -v nvme0ns1
91.Pp 140.Pp
92Display an hexadecimal dump of the nvme0 141Display an hexadecimal dump of the nvme0
93.Dv IDENTIFY_NAMESPACE 142.Dv IDENTIFY_NAMESPACE
94data for namespace 1. 143data for namespace 1.
95.\".Pp 144.\".Pp
96.\".Dl nvmectl perftest -n 32 -o read -s 512 -t 30 nvme0ns1 145.\".Dl nvmectl perftest -n 32 -o read -s 512 -t 30 nvme0ns1
97.\".Pp 146.\".Pp
98.\"Run a performance test on nvme0ns1 using 32 kernel threads for 30 seconds. Each 147.\"Run a performance test on nvme0ns1 using 32 kernel threads for 30 seconds.
99.\"thread will issue a single 512 byte read command. Results are printed to 148.\"Each thread will issue a single 512 byte read command.
100.\"stdout when 30 seconds expires. 149.\"Results are printed to stdout when 30 seconds expires.
101.\".Pp 150.\".Pp
102.\".Dl nvmectl reset nvme0 151.\".Dl nvmectl reset nvme0
103.\".Pp 152.\".Pp
104.\"Perform a controller-level reset of the nvme0 controller. 153.\"Perform a controller-level reset of the nvme0 controller.
105.Pp 154.Pp
106.Dl nvmectl logpage -p 1 nvme0 155.Dl nvmectl logpage -p 1 nvme0
107.Pp 156.Pp
108Display a human-readable summary of the nvme0 controller's Error Information Log. 157Display a human-readable summary of the nvme0 controller's Error Information Log.
109Log pages defined by the NVMe specification include Error Information Log (ID=1), 158Log pages defined by the NVMe specification include Error Information Log (ID=1),
110SMART/Health Information Log (ID=2), and Firmware Slot Log (ID=3). 159SMART/Health Information Log (ID=2), and Firmware Slot Log (ID=3).
111.Pp 160.Pp
 161.Dl nvmectl logpage -p 0xc1 -v wdc nvme0
 162.Pp
 163Display a human-readable summary of the nvme0's wdc-specific advanced
 164SMART data.
 165.Pp
112.Dl nvmectl logpage -p 1 -x nvme0 166.Dl nvmectl logpage -p 1 -x nvme0
113.Pp 167.Pp
114Display a hexadecimal dump of the nvme0 controller's Error Information Log. 168Display a hexadecimal dump of the nvme0 controller's Error Information Log.
 169.Pp
 170.Dl nvmectl logpage -p 0xcb -b nvme0 > /tmp/page-cb.bin
 171.Pp
 172Print the contents of vendor specific page 0xcb as binary data on
 173standard out.
 174Redirect it to a temporary file.
115.\".Pp 175.\".Pp
116.\".Dl nvmectl firmware -s 2 -f /tmp/nvme_firmware nvme0 176.\".Dl nvmectl firmware -s 2 -f /tmp/nvme_firmware nvme0
117.\".Pp 177.\".Pp
118.\"Download the firmware image contained in "/tmp/nvme_firmware" to slot 2 of the 178.\"Download the firmware image contained in "/tmp/nvme_firmware" to slot 2 of the
119.\"nvme0 controller, but do not activate the image. 179.\"nvme0 controller, but do not activate the image.
120.\".Pp 180.\".Pp
121.\".Dl nvmectl firmware -s 4 -a nvme0 181.\".Dl nvmectl firmware -s 4 -a nvme0
122.\".Pp 182.\".Pp
123.\"Activate the firmware in slot 4 of the nvme0 controller on the next reset. 183.\"Activate the firmware in slot 4 of the nvme0 controller on the next reset.
124.\".Pp 184.\".Pp
125.\".Dl nvmectl firmware -s 7 -f /tmp/nvme_firmware -a nvme0 185.\".Dl nvmectl firmware -s 7 -f /tmp/nvme_firmware -a nvme0
126.\".Pp 186.\".Pp
127.\"Download the firmware image contained in "/tmp/nvme_firmware" to slot 7 of the 187.\"Download the firmware image contained in "/tmp/nvme_firmware" to slot 7 of the
128.\"nvme0 controller and activate it on the next reset. 188.\"nvme0 controller and activate it on the next reset.
129.Pp 189.Pp
130.Dl nvmectl power -l nvme0 190.Dl nvmectl power -l nvme0
131.Pp 191.Pp
132List all the current power modes. 192List all the current power modes.
133.Pp 193.Pp
134.Dl nvmectl power -p 3 nvme0 194.Dl nvmectl power -p 3 nvme0
135.Pp 195.Pp
136Set the current power mode. 196Set the current power mode.
137.Pp 197.Pp
138.Dl nvmectl power nvme0 198.Dl nvmectl power nvme0
139.Pp 199.Pp
140Get the current power mode. 200Get the current power mode.
 201.Sh HISTORY
 202The nvmecontrol utility appeared in
 203.Fx 9.2 .
141.Sh AUTHORS 204.Sh AUTHORS
142.An -nosplit 205.An -nosplit
143nvmecontrol was developed by Intel and originally written by 206nvmecontrol was developed by Intel and originally written by
144.An Jim Harris Aq Mt jimharris@FreeBSD.org . 207.An Jim Harris Aq Mt jimharris@FreeBSD.org .
145.Pp 208.Pp
146This man page was written by 209This man page was written by
147.An Jim Harris Aq Mt jimharris@FreeBSD.org . 210.An Jim Harris Aq Mt jimharris@FreeBSD.org .

cvs diff -r1.2 -r1.3 src/sbin/nvmectl/nvmectl.c (expand / switch to unified diff)

--- src/sbin/nvmectl/nvmectl.c 2016/06/04 20:59:49 1.2
+++ src/sbin/nvmectl/nvmectl.c 2017/04/29 00:06:40 1.3
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: nvmectl.c,v 1.2 2016/06/04 20:59:49 joerg Exp $ */ 1/* $NetBSD: nvmectl.c,v 1.3 2017/04/29 00:06:40 nonaka Exp $ */
2 2
3/*- 3/*-
4 * Copyright (C) 2012-2013 Intel Corporation 4 * Copyright (C) 2012-2013 Intel Corporation
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
@@ -18,87 +18,100 @@ @@ -18,87 +18,100 @@
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29#include <sys/cdefs.h> 29#include <sys/cdefs.h>
30#ifndef lint 30#ifndef lint
31__RCSID("$NetBSD: nvmectl.c,v 1.2 2016/06/04 20:59:49 joerg Exp $"); 31__RCSID("$NetBSD: nvmectl.c,v 1.3 2017/04/29 00:06:40 nonaka Exp $");
32#if 0 32#if 0
33__FBSDID("$FreeBSD: head/sbin/nvmecontrol/nvmecontrol.c 295087 2016-01-30 22:48:06Z imp $"); 33__FBSDID("$FreeBSD: head/sbin/nvmecontrol/nvmecontrol.c 314229 2017-02-25 00:09:12Z imp $");
34#endif 34#endif
35#endif 35#endif
36 36
37#include <sys/param.h> 37#include <sys/param.h>
38#include <sys/ioccom.h> 38#include <sys/ioccom.h>
39#include <sys/stat.h> 39#include <sys/stat.h>
40 40
41#include <ctype.h> 41#include <ctype.h>
42#include <err.h> 42#include <err.h>
43#include <errno.h> 43#include <errno.h>
44#include <fcntl.h> 44#include <fcntl.h>
45#include <paths.h> 45#include <paths.h>
46#include <stdbool.h> 46#include <stdbool.h>
47#include <stddef.h> 47#include <stddef.h>
48#include <stdio.h> 48#include <stdio.h>
49#include <stdlib.h> 49#include <stdlib.h>
50#include <string.h> 50#include <string.h>
51#include <unistd.h> 51#include <unistd.h>
52 52
53#include "nvmectl.h" 53#include "nvmectl.h"
54 54
55typedef void (*nvme_fn_t)(int argc, char *argv[]); 55static struct nvme_function funcs[] = {
56 
57static struct nvme_function { 
58 const char *name; 
59 nvme_fn_t fn; 
60 const char *usage; 
61} funcs[] = { 
62 {"devlist", devlist, DEVLIST_USAGE}, 56 {"devlist", devlist, DEVLIST_USAGE},
63 {"identify", identify, IDENTIFY_USAGE}, 57 {"identify", identify, IDENTIFY_USAGE},
64#ifdef PERFTEST_USAGE 58#ifdef PERFTEST_USAGE
65 {"perftest", perftest, PERFTEST_USAGE}, 59 {"perftest", perftest, PERFTEST_USAGE},
66#endif 60#endif
67#ifdef RESET_USAGE 61#ifdef RESET_USAGE
68 {"reset", reset, RESET_USAGE}, 62 {"reset", reset, RESET_USAGE},
69#endif 63#endif
70 {"logpage", logpage, LOGPAGE_USAGE}, 64 {"logpage", logpage, LOGPAGE_USAGE},
71#ifdef FIRMWARE_USAGE 65#ifdef FIRMWARE_USAGE
72 {"firmware", firmware, FIRMWARE_USAGE}, 66 {"firmware", firmware, FIRMWARE_USAGE},
73#endif 67#endif
74 {"power", power, POWER_USAGE}, 68 {"power", power, POWER_USAGE},
 69 {"wdc", wdc, WDC_USAGE},
75 {NULL, NULL, NULL}, 70 {NULL, NULL, NULL},
76}; 71};
77 72
78__dead static void 73void
79usage(void) 74gen_usage(struct nvme_function *f)
80{ 75{
81 struct nvme_function *f; 
82 76
83 f = funcs; 
84 fprintf(stderr, "usage:\n"); 77 fprintf(stderr, "usage:\n");
85 while (f->name != NULL) { 78 while (f->name != NULL) {
86 fprintf(stderr, "%s", f->usage); 79 fprintf(stderr, "%s", f->usage);
87 f++; 80 f++;
88 } 81 }
89 exit(1); 82 exit(1);
90} 83}
91 84
 85void
 86dispatch(int argc, char *argv[], struct nvme_function *tbl)
 87{
 88 struct nvme_function *f = tbl;
 89
 90 if (argv[1] == NULL) {
 91 gen_usage(tbl);
 92 return;
 93 }
 94
 95 while (f->name != NULL) {
 96 if (strcmp(argv[1], f->name) == 0)
 97 f->fn(argc-1, &argv[1]);
 98 f++;
 99 }
 100
 101 fprintf(stderr, "Unknown command: %s\n", argv[1]);
 102 gen_usage(tbl);
 103}
 104
92static void 105static void
93print_bytes(void *data, uint32_t length) 106print_bytes(void *data, uint32_t length)
94{ 107{
95 uint32_t i, j; 108 uint32_t i, j;
96 uint8_t *p, *end; 109 uint8_t *p, *end;
97 110
98 end = (uint8_t *)data + length; 111 end = (uint8_t *)data + length;
99 112
100 for (i = 0; i < length; i++) { 113 for (i = 0; i < length; i++) {
101 p = (uint8_t *)data + (i*16); 114 p = (uint8_t *)data + (i*16);
102 printf("%03x: ", i*16); 115 printf("%03x: ", i*16);
103 for (j = 0; j < 16 && p < end; j++) 116 for (j = 0; j < 16 && p < end; j++)
104 printf("%02x ", *p++); 117 printf("%02x ", *p++);
@@ -259,29 +272,21 @@ nvme_strvis(u_char *dst, int dlen, const @@ -259,29 +272,21 @@ nvme_strvis(u_char *dst, int dlen, const
259 if (--dlen < 1) 272 if (--dlen < 1)
260 break; 273 break;
261 *dst++ = *src; 274 *dst++ = *src;
262 } 275 }
263 ++src, --slen; 276 ++src, --slen;
264 } 277 }
265 278
266 *dst++ = 0; 279 *dst++ = 0;
267} 280}
268 281
269int 282int
270main(int argc, char *argv[]) 283main(int argc, char *argv[])
271{ 284{
272 struct nvme_function *f; 
273 285
274 if (argc < 2) 286 if (argc < 2)
275 usage(); 287 gen_usage(funcs);
276 
277 f = funcs; 
278 while (f->name != NULL) { 
279 if (strcmp(argv[1], f->name) == 0) 
280 f->fn(argc-1, &argv[1]); 
281 f++; 
282 } 
283 288
284 usage(); 289 dispatch(argc, argv, funcs);
285 290
286 return (0); 291 return (0);
287} 292}

cvs diff -r1.2 -r1.3 src/sbin/nvmectl/nvmectl.h (expand / switch to unified diff)

--- src/sbin/nvmectl/nvmectl.h 2016/06/04 20:59:49 1.2
+++ src/sbin/nvmectl/nvmectl.h 2017/04/29 00:06:40 1.3
@@ -1,94 +1,109 @@ @@ -1,94 +1,109 @@
1/* $NetBSD: nvmectl.h,v 1.2 2016/06/04 20:59:49 joerg Exp $ */ 1/* $NetBSD: nvmectl.h,v 1.3 2017/04/29 00:06:40 nonaka Exp $ */
2 2
3/*- 3/*-
4 * Copyright (C) 2012-2013 Intel Corporation 4 * Copyright (C) 2012-2013 Intel Corporation
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 * 27 *
28 * $FreeBSD: head/sbin/nvmecontrol/nvmecontrol.h 295087 2016-01-30 22:48:06Z imp $ 28 * $FreeBSD: head/sbin/nvmecontrol/nvmecontrol.h 314230 2017-02-25 00:09:16Z imp $
29 */ 29 */
30 30
31#ifndef __NVMECTL_H__ 31#ifndef __NVMECTL_H__
32#define __NVMECTL_H__ 32#define __NVMECTL_H__
33 33
34#include <sys/ioctl.h> 34#include <sys/ioctl.h>
35 35
36#include <dev/ic/nvmeio.h> 36#include <dev/ic/nvmeio.h>
37#include "nvme.h" 37#include "nvme.h"
38 38
 39typedef void (*nvme_fn_t)(int argc, char *argv[]);
 40
 41struct nvme_function {
 42 const char *name;
 43 nvme_fn_t fn;
 44 const char *usage;
 45};
 46
39#define NVME_CTRLR_PREFIX "nvme" 47#define NVME_CTRLR_PREFIX "nvme"
40#define NVME_NS_PREFIX "ns" 48#define NVME_NS_PREFIX "ns"
41 49
42#define DEVLIST_USAGE \ 50#define DEVLIST_USAGE \
43" nvmectl devlist\n" 51" nvmectl devlist\n"
44 52
45#define IDENTIFY_USAGE \ 53#define IDENTIFY_USAGE \
46" nvmectl identify [-x [-v]] <controller id|namespace id>\n" 54" nvmectl identify [-x [-v]] <controller id|namespace id>\n"
47 55
48#if 0 56#if 0
49#define PERFTEST_USAGE \ 57#define PERFTEST_USAGE \
50" nvmectl perftest <-n num_threads> <-o read|write>\n" \ 58" nvmectl perftest <-n num_threads> <-o read|write>\n" \
51" <-s size_in_bytes> <-t time_in_seconds>\n" \ 59" <-s size_in_bytes> <-t time_in_seconds>\n" \
52" <-i intr|wait> [-f refthread] [-p]\n" \ 60" <-i intr|wait> [-f refthread] [-p]\n" \
53" <namespace id>\n" 61" <namespace id>\n"
54#endif 62#endif
55 63
56#if 0 64#if 0
57#define RESET_USAGE \ 65#define RESET_USAGE \
58" nvmectl reset <controller id>\n" 66" nvmectl reset <controller id>\n"
59#endif 67#endif
60 68
61#define LOGPAGE_USAGE \ 69#define LOGPAGE_USAGE \
62" nvmectl logpage <-p page_id> [-x] <controller id|namespace id>\n" \ 70" nvmectl logpage <-p page_id> [-b] [-v vendor] [-x] " \
 71 "<controller id|namespace id>\n"
63 72
64#if 0 73#if 0
65#define FIRMWARE_USAGE \ 74#define FIRMWARE_USAGE \
66" nvmectl firmware [-s slot] [-f path_to_firmware] [-a] <controller id>\n" 75" nvmectl firmware [-s slot] [-f path_to_firmware] [-a] <controller id>\n"
67#endif 76#endif
68 77
69#define POWER_USAGE \ 78#define POWER_USAGE \
70" nvmectl power [-l] [-p new-state [-w workload-hint]] <controller id>\n" 79" nvmectl power [-l] [-p new-state [-w workload-hint]] <controller id>\n"
71 80
 81#define WDC_USAGE \
 82" nvmecontrol wdc (cap-diag|drive-log|get-crash-dump|purge|purge-montior)\n"
 83
72void devlist(int, char *[]) __dead; 84void devlist(int, char *[]) __dead;
73void identify(int, char *[]) __dead; 85void identify(int, char *[]) __dead;
74#ifdef PERFTEST_USAGE 86#ifdef PERFTEST_USAGE
75void perftest(int, char *[]); 87void perftest(int, char *[]) __dead;
76#endif 88#endif
77#ifdef RESET_USAGE 89#ifdef RESET_USAGE
78void reset(int, char *[]); 90void reset(int, char *[]) __dead;
79#endif 91#endif
80void logpage(int, char *[]) __dead; 92void logpage(int, char *[]) __dead;
81#ifdef FIRMWARE_USAGE 93#ifdef FIRMWARE_USAGE
82void firmware(int, char *[]); 94void firmware(int, char *[]) __dead;
83#endif 95#endif
84void power(int, char *[]) __dead; 96void power(int, char *[]) __dead;
 97void wdc(int, char *[]) __dead;
85 98
86int open_dev(const char *, int *, int, int); 99int open_dev(const char *, int *, int, int);
87void parse_ns_str(const char *, char *, int *); 100void parse_ns_str(const char *, char *, int *);
88void read_controller_data(int, struct nvm_identify_controller *); 101void read_controller_data(int, struct nvm_identify_controller *);
89void read_namespace_data(int, int, struct nvm_identify_namespace *); 102void read_namespace_data(int, int, struct nvm_identify_namespace *);
90void print_hex(void *, uint32_t); 103void print_hex(void *, uint32_t);
91void read_logpage(int, uint8_t, int, void *, uint32_t); 104void read_logpage(int, uint8_t, int, void *, uint32_t);
 105void gen_usage(struct nvme_function *) __dead;
 106void dispatch(int argc, char *argv[], struct nvme_function *f);
92void nvme_strvis(uint8_t *, int, const uint8_t *, int); 107void nvme_strvis(uint8_t *, int, const uint8_t *, int);
93 108
94#endif /* __NVMECTL_H__ */ 109#endif /* __NVMECTL_H__ */

cvs diff -r1.1 -r1.2 src/sbin/nvmectl/firmware.c (expand / switch to unified diff)

--- src/sbin/nvmectl/firmware.c 2016/06/04 16:29:35 1.1
+++ src/sbin/nvmectl/firmware.c 2017/04/29 00:06:40 1.2
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: firmware.c,v 1.1 2016/06/04 16:29:35 nonaka Exp $ */ 1/* $NetBSD: firmware.c,v 1.2 2017/04/29 00:06:40 nonaka Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2013 EMC Corp. 4 * Copyright (c) 2013 EMC Corp.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Copyright (C) 2012-2013 Intel Corporation 7 * Copyright (C) 2012-2013 Intel Corporation
8 * All rights reserved. 8 * All rights reserved.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -21,29 +21,29 @@ @@ -21,29 +21,29 @@
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#ifndef lint 33#ifndef lint
34__RCSID("$NetBSD: firmware.c,v 1.1 2016/06/04 16:29:35 nonaka Exp $"); 34__RCSID("$NetBSD: firmware.c,v 1.2 2017/04/29 00:06:40 nonaka Exp $");
35#if 0 35#if 0
36__FBSDID("$FreeBSD: head/sbin/nvmecontrol/firmware.c 258071 2013-11-12 21:14:19Z jimharris $"); 36__FBSDID("$FreeBSD: head/sbin/nvmecontrol/firmware.c 313188 2017-02-04 05:52:50Z imp $");
37#endif 37#endif
38#endif 38#endif
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/ioccom.h> 41#include <sys/ioccom.h>
42#include <sys/stat.h> 42#include <sys/stat.h>
43#include <sys/types.h> 43#include <sys/types.h>
44 44
45#include <ctype.h> 45#include <ctype.h>
46#include <err.h> 46#include <err.h>
47#include <fcntl.h> 47#include <fcntl.h>
48#include <inttypes.h> 48#include <inttypes.h>
49#include <stdbool.h> 49#include <stdbool.h>
@@ -111,27 +111,27 @@ read_image_file(char *path, void **buf,  @@ -111,27 +111,27 @@ read_image_file(char *path, void **buf,
111 path, *size, filesize); 111 path, *size, filesize);
112} 112}
113 113
114static void 114static void
115update_firmware(int fd, uint8_t *payload, int32_t payload_size) 115update_firmware(int fd, uint8_t *payload, int32_t payload_size)
116{ 116{
117 struct nvme_pt_command pt; 117 struct nvme_pt_command pt;
118 int32_t off, resid, size; 118 int32_t off, resid, size;
119 void *chunk; 119 void *chunk;
120 120
121 off = 0; 121 off = 0;
122 resid = payload_size; 122 resid = payload_size;
123 123
124 if ((chunk = malloc(NVME_MAX_XFER_SIZE)) == NULL) 124 if ((chunk = aligned_alloc(PAGE_SIZE, NVME_MAX_XFER_SIZE)) == NULL)
125 errx(1, "unable to malloc %d bytes", NVME_MAX_XFER_SIZE); 125 errx(1, "unable to malloc %d bytes", NVME_MAX_XFER_SIZE);
126 126
127 while (resid > 0) { 127 while (resid > 0) {
128 size = (resid >= NVME_MAX_XFER_SIZE) ? 128 size = (resid >= NVME_MAX_XFER_SIZE) ?
129 NVME_MAX_XFER_SIZE : resid; 129 NVME_MAX_XFER_SIZE : resid;
130 memcpy(chunk, payload + off, size); 130 memcpy(chunk, payload + off, size);
131 131
132 memset(&pt, 0, sizeof(pt)); 132 memset(&pt, 0, sizeof(pt));
133 pt.cmd.opcode = NVM_ADMIN_FW_DOWNLOAD; 133 pt.cmd.opcode = NVM_ADMIN_FW_DOWNLOAD;
134 pt.cmd.cdw10 = (size / sizeof(uint32_t)) - 1; 134 pt.cmd.cdw10 = (size / sizeof(uint32_t)) - 1;
135 pt.cmd.cdw11 = (off / sizeof(uint32_t)); 135 pt.cmd.cdw11 = (off / sizeof(uint32_t));
136 pt.buf = chunk; 136 pt.buf = chunk;
137 pt.len = size; 137 pt.len = size;

cvs diff -r1.1 -r1.2 src/sbin/nvmectl/nvme.h (expand / switch to unified diff)

--- src/sbin/nvmectl/nvme.h 2016/06/04 16:29:35 1.1
+++ src/sbin/nvmectl/nvme.h 2017/04/29 00:06:40 1.2
@@ -1,47 +1,48 @@ @@ -1,47 +1,48 @@
1/* $NetBSD: nvme.h,v 1.1 2016/06/04 16:29:35 nonaka Exp $ */ 1/* $NetBSD: nvme.h,v 1.2 2017/04/29 00:06:40 nonaka Exp $ */
2 2
3/*- 3/*-
4 * Copyright (C) 2012-2013 Intel Corporation 4 * Copyright (C) 2012-2013 Intel Corporation
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 * 27 *
28 * $FreeBSD: head/sys/dev/nvme/nvme.h 296617 2016-03-10 17:13:10Z mav $ 28 * $FreeBSD: head/sys/dev/nvme/nvme.h 314888 2017-03-07 23:02:59Z imp $
29 */ 29 */
30 30
31#ifndef __NVME_H__ 31#ifndef __NVME_H__
32#define __NVME_H__ 32#define __NVME_H__
33 33
34#define NVME_MAX_XFER_SIZE MAXPHYS 34/* Cap nvme to 1MB transfers driver explodes with larger sizes */
 35#define NVME_MAX_XFER_SIZE (MAXPHYS < (1<<20) ? MAXPHYS : (1<<20))
35 36
36/* Get/Set Features */ 37/* Get/Set Features */
37#define NVME_FEAT_ARBITRATION 0x01 38#define NVME_FEAT_ARBITRATION 0x01
38#define NVME_FEAT_POWER_MANAGEMENT 0x02 39#define NVME_FEAT_POWER_MANAGEMENT 0x02
39#define NVME_FEAT_LBA_RANGE_TYPE 0x03 40#define NVME_FEAT_LBA_RANGE_TYPE 0x03
40#define NVME_FEAT_TEMPERATURE_THRESHOLD 0x04 41#define NVME_FEAT_TEMPERATURE_THRESHOLD 0x04
41#define NVME_FEAT_ERROR_RECOVERY 0x05 42#define NVME_FEAT_ERROR_RECOVERY 0x05
42#define NVME_FEAT_VOLATILE_WRITE_CACHE 0x06 43#define NVME_FEAT_VOLATILE_WRITE_CACHE 0x06
43#define NVME_FEAT_NUMBER_OF_QUEUES 0x07 44#define NVME_FEAT_NUMBER_OF_QUEUES 0x07
44#define NVME_FEAT_INTERRUPT_COALESCING 0x08 45#define NVME_FEAT_INTERRUPT_COALESCING 0x08
45#define NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION 0x09 46#define NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION 0x09
46#define NVME_FEAT_WRITE_ATOMICITY_NORMAL 0x0a 47#define NVME_FEAT_WRITE_ATOMICITY_NORMAL 0x0a
47#define NVME_FEAT_ASYNC_EVENT_CONFIGURATION 0x0b 48#define NVME_FEAT_ASYNC_EVENT_CONFIGURATION 0x0b
@@ -50,26 +51,39 @@ @@ -50,26 +51,39 @@
50/* NVM Command Set specific */ 51/* NVM Command Set specific */
51#define NVME_FEAT_SOFTWARE_PROGRESS_MARKER 0x80 52#define NVME_FEAT_SOFTWARE_PROGRESS_MARKER 0x80
52#define NVME_FEAT_HOST_IDENTIFIER 0x81 53#define NVME_FEAT_HOST_IDENTIFIER 0x81
53#define NVME_FEAT_RESERVATION_NOTIFICATION_MASK 0x82 54#define NVME_FEAT_RESERVATION_NOTIFICATION_MASK 0x82
54#define NVME_FEAT_RESERVATION_PERSISTANCE 0x83 55#define NVME_FEAT_RESERVATION_PERSISTANCE 0x83
55 56
56/* Get Log Page */ 57/* Get Log Page */
57#define NVME_LOG_ERROR 0x01 58#define NVME_LOG_ERROR 0x01
58#define NVME_LOG_HEALTH_INFORMATION 0x02 59#define NVME_LOG_HEALTH_INFORMATION 0x02
59#define NVME_LOG_FIRMWARE_SLOT 0x03 60#define NVME_LOG_FIRMWARE_SLOT 0x03
60#define NVME_LOG_CHANGED_NAMESPACE_LIST 0x04 61#define NVME_LOG_CHANGED_NAMESPACE_LIST 0x04
61#define NVME_LOG_COMMAND_EFFECTS_LOG 0x05 62#define NVME_LOG_COMMAND_EFFECTS_LOG 0x05
62#define NVME_LOG_RESERVATION_NOTIFICATION 0x80 63#define NVME_LOG_RESERVATION_NOTIFICATION 0x80
 64/*
 65 * The following are Intel Specific log pages, but they seem
 66 * to be widely implemented.
 67 */
 68#define INTEL_LOG_READ_LAT_LOG 0xc1
 69#define INTEL_LOG_WRITE_LAT_LOG 0xc2
 70#define INTEL_LOG_TEMP_STATS 0xc5
 71#define INTEL_LOG_ADD_SMART 0xca
 72#define INTEL_LOG_DRIVE_MKT_NAME 0xdd
 73/*
 74 * HGST log page, with lots ofs sub pages.
 75 */
 76#define HGST_INFO_LOG 0xc1
63 77
64/* Error Information Log (Log Identifier 01h) */ 78/* Error Information Log (Log Identifier 01h) */
65struct nvme_error_information_entry { 79struct nvme_error_information_entry {
66 uint64_t error_count; 80 uint64_t error_count;
67 uint16_t sqid; 81 uint16_t sqid;
68 uint16_t cid; 82 uint16_t cid;
69 uint16_t status; 83 uint16_t status;
70 uint16_t error_location; 84 uint16_t error_location;
71 uint64_t lba; 85 uint64_t lba;
72 uint32_t nsid; 86 uint32_t nsid;
73 uint8_t vendor_specific; 87 uint8_t vendor_specific;
74 uint8_t _reserved1[3]; 88 uint8_t _reserved1[3];
75 uint64_t command_specific; 89 uint64_t command_specific;
@@ -91,51 +105,63 @@ struct nvme_health_information_page { @@ -91,51 +105,63 @@ struct nvme_health_information_page {
91 105
92 uint8_t _reserved1[26]; 106 uint8_t _reserved1[26];
93 107
94 uint64_t data_units_read[2]; 108 uint64_t data_units_read[2];
95 uint64_t data_units_written[2]; 109 uint64_t data_units_written[2];
96 uint64_t host_read_commands[2]; 110 uint64_t host_read_commands[2];
97 uint64_t host_write_commands[2]; 111 uint64_t host_write_commands[2];
98 uint64_t controller_busy_time[2]; 112 uint64_t controller_busy_time[2];
99 uint64_t power_cycles[2]; 113 uint64_t power_cycles[2];
100 uint64_t power_on_hours[2]; 114 uint64_t power_on_hours[2];
101 uint64_t unsafe_shutdowns[2]; 115 uint64_t unsafe_shutdowns[2];
102 uint64_t media_errors[2]; 116 uint64_t media_errors[2];
103 uint64_t num_error_info_log_entries[2]; 117 uint64_t num_error_info_log_entries[2];
104 uint32_t warning_composite_temperature_time; 118 uint32_t warning_temp_time;
105 uint32_t critical_composite_temperature_time; 119 uint32_t error_temp_time;
106 uint16_t temperature_sensor[8]; 120 uint16_t temp_sensor[8];
107 121
108 uint8_t reserved[296]; 122 uint8_t reserved[296];
109} __packed __aligned(4); 123} __packed __aligned(4);
110 124
111/* Firmware Commit */ 125/* Firmware Commit */
112#define NVME_COMMIT_ACTION_REPLACE_NO_ACTIVATE 0 126#define NVME_COMMIT_ACTION_REPLACE_NO_ACTIVATE 0
113#define NVME_COMMIT_ACTION_REPLACE_ACTIVATE 1 127#define NVME_COMMIT_ACTION_REPLACE_ACTIVATE 1
114#define NVME_COMMIT_ACTION_ACTIVATE_RESET 2 128#define NVME_COMMIT_ACTION_ACTIVATE_RESET 2
115#define NVME_COMMIT_ACTION_ACTIVATE_NO_RESET 3 129#define NVME_COMMIT_ACTION_ACTIVATE_NO_RESET 3
116 130
117/* Firmware Slot Information (Log Identifier 03h) */ 131/* Firmware Slot Information (Log Identifier 03h) */
118struct nvme_firmware_page { 132struct nvme_firmware_page {
119 uint8_t afi; 133 uint8_t afi;
120#define NVME_FW_PAGE_AFI_SLOT_RST __BITS(4, 6) 134#define NVME_FW_PAGE_AFI_SLOT_RST __BITS(4, 6)
121#define NVME_FW_PAGE_AFI_SLOT __BITS(0, 2) 135#define NVME_FW_PAGE_AFI_SLOT __BITS(0, 2)
122 uint8_t _reserved1[7]; 136 uint8_t _reserved1[7];
123 137
124 uint64_t revision[7]; /* revisions for 7 slots */ 138 uint64_t revision[7]; /* revisions for 7 slots */
125 139
126 uint8_t reserved[448]; 140 uint8_t reserved[448];
127} __packed __aligned(4); 141} __packed __aligned(4);
128 142
 143struct intel_log_temp_stats {
 144 uint64_t current;
 145 uint64_t overtemp_flag_last;
 146 uint64_t overtemp_flag_life;
 147 uint64_t max_temp;
 148 uint64_t min_temp;
 149 uint64_t _rsvd[5];
 150 uint64_t max_oper_temp;
 151 uint64_t min_oper_temp;
 152 uint64_t est_offset;
 153} __packed __aligned(4);
 154
129/* Commands Supported and Effects (Log Identifier 05h) */ 155/* Commands Supported and Effects (Log Identifier 05h) */
130struct nvme_command_effeects_page { 156struct nvme_command_effeects_page {
131 uint32_t acs[256]; 157 uint32_t acs[256];
132#define NVME_CE_PAGE_CS_CSE __BITS(16, 18) 158#define NVME_CE_PAGE_CS_CSE __BITS(16, 18)
133#define NVME_CE_PAGE_CS_CCC __BIT(4) 159#define NVME_CE_PAGE_CS_CCC __BIT(4)
134#define NVME_CE_PAGE_CS_NIC __BIT(3) 160#define NVME_CE_PAGE_CS_NIC __BIT(3)
135#define NVME_CE_PAGE_CS_NCC __BIT(2) 161#define NVME_CE_PAGE_CS_NCC __BIT(2)
136#define NVME_CE_PAGE_CS_LBCC __BIT(1) 162#define NVME_CE_PAGE_CS_LBCC __BIT(1)
137#define NVME_CE_PAGE_CS_CSUPP __BIT(0) 163#define NVME_CE_PAGE_CS_CSUPP __BIT(0)
138 uint32_t iocs[256]; 164 uint32_t iocs[256];
139 165
140 uint8_t reserved[2048]; 166 uint8_t reserved[2048];
141} __packed __aligned(4); 167} __packed __aligned(4);

cvs diff -r1.3 -r1.4 src/sbin/nvmectl/logpage.c (expand / switch to unified diff)

--- src/sbin/nvmectl/logpage.c 2017/02/13 11:16:46 1.3
+++ src/sbin/nvmectl/logpage.c 2017/04/29 00:06:40 1.4
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: logpage.c,v 1.3 2017/02/13 11:16:46 nonaka Exp $ */ 1/* $NetBSD: logpage.c,v 1.4 2017/04/29 00:06:40 nonaka Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2013 EMC Corp. 4 * Copyright (c) 2013 EMC Corp.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Copyright (C) 2012-2013 Intel Corporation 7 * Copyright (C) 2012-2013 Intel Corporation
8 * All rights reserved. 8 * All rights reserved.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -21,53 +21,87 @@ @@ -21,53 +21,87 @@
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE. 29 * SUCH DAMAGE.
30 */ 30 */
31 31
32#include <sys/cdefs.h> 32#include <sys/cdefs.h>
33#ifndef lint 33#ifndef lint
34__RCSID("$NetBSD: logpage.c,v 1.3 2017/02/13 11:16:46 nonaka Exp $"); 34__RCSID("$NetBSD: logpage.c,v 1.4 2017/04/29 00:06:40 nonaka Exp $");
35#if 0 35#if 0
36__FBSDID("$FreeBSD: head/sbin/nvmecontrol/logpage.c 285796 2015-07-22 16:10:29Z jimharris $"); 36__FBSDID("$FreeBSD: head/sbin/nvmecontrol/logpage.c 314230 2017-02-25 00:09:16Z imp $");
37#endif 37#endif
38#endif 38#endif
39 39
40#include <sys/param.h> 40#include <sys/param.h>
41#include <sys/ioccom.h> 41#include <sys/ioccom.h>
 42#include <sys/endian.h>
42 43
43#include <ctype.h> 44#include <ctype.h>
44#include <err.h> 45#include <err.h>
45#include <fcntl.h> 46#include <fcntl.h>
46#include <stdbool.h> 47#include <stdbool.h>
47#include <stddef.h> 48#include <stddef.h>
48#include <stdio.h> 49#include <stdio.h>
49#include <stdlib.h> 50#include <stdlib.h>
50#include <string.h> 51#include <string.h>
51#include <unistd.h> 52#include <unistd.h>
52 53
53#include "nvmectl.h" 54#include "nvmectl.h"
54#include "bn.h" 55#include "bn.h"
55 56
56#define DEFAULT_SIZE (4096) 57#define DEFAULT_SIZE (4096)
57#define MAX_FW_SLOTS (7) 58#define MAX_FW_SLOTS (7)
58 59
59typedef void (*print_fn_t)(void *buf, uint32_t size); 60typedef void (*print_fn_t)(void *buf, uint32_t size);
60 61
 62struct kv_name {
 63 uint32_t key;
 64 const char *name;
 65};
 66
 67static const char *
 68kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key)
 69{
 70 static char bad[32];
 71 size_t i;
 72
 73 for (i = 0; i < kv_count; i++, kv++)
 74 if (kv->key == key)
 75 return kv->name;
 76 snprintf(bad, sizeof(bad), "Attribute %#x", key);
 77 return bad;
 78}
 79
 80static void
 81print_bin(void *data, uint32_t length)
 82{
 83 write(STDOUT_FILENO, data, length);
 84}
 85
 86/* "Missing" from endian.h */
 87static __inline uint64_t
 88le48dec(const void *pp)
 89{
 90 uint8_t const *p = (uint8_t const *)pp;
 91
 92 return (((uint64_t)le16dec(p + 4) << 32) | le32dec(p));
 93}
 94
61static void * 95static void *
62get_log_buffer(uint32_t size) 96get_log_buffer(uint32_t size)
63{ 97{
64 void *buf; 98 void *buf;
65 99
66 if ((buf = malloc(size)) == NULL) 100 if ((buf = malloc(size)) == NULL)
67 errx(1, "unable to malloc %u bytes", size); 101 errx(1, "unable to malloc %u bytes", size);
68 102
69 memset(buf, 0, size); 103 memset(buf, 0, size);
70 return (buf); 104 return (buf);
71} 105}
72 106
73void 107void
@@ -168,82 +202,89 @@ print_bignum(const char *title, uint64_t @@ -168,82 +202,89 @@ print_bignum(const char *title, uint64_t
168 buf[0] = '\0'; 202 buf[0] = '\0';
169 BIGNUM *bn = BN_bin2bn(tmp, __arraycount(tmp), NULL); 203 BIGNUM *bn = BN_bin2bn(tmp, __arraycount(tmp), NULL);
170 if (bn != NULL) { 204 if (bn != NULL) {
171 humanize_bignum(buf, METRIX_PREFIX_BUFSIZ + strlen(suffix), 205 humanize_bignum(buf, METRIX_PREFIX_BUFSIZ + strlen(suffix),
172 bn, suffix, HN_AUTOSCALE, HN_DECIMAL); 206 bn, suffix, HN_AUTOSCALE, HN_DECIMAL);
173 BN_free(bn); 207 BN_free(bn);
174 } 208 }
175 if (buf[0] == '\0') 209 if (buf[0] == '\0')
176 snprintf(buf, sizeof(buf), "0x%016jx%016jx", h, l); 210 snprintf(buf, sizeof(buf), "0x%016jx%016jx", h, l);
177 printf("%-31s %s\n", title, buf); 211 printf("%-31s %s\n", title, buf);
178} 212}
179 213
180static void 214static void
 215print_temp(uint16_t t)
 216{
 217 printf("%u K, %2.2f C, %3.2f F\n", t, (float)t - 273.15,
 218 (float)t * 9 / 5 - 459.67);
 219}
 220
 221static void
181print_log_health(void *buf, uint32_t size __unused) 222print_log_health(void *buf, uint32_t size __unused)
182{ 223{
183 struct nvme_health_information_page *health = buf; 224 struct nvme_health_information_page *health = buf;
184 float composite_temperature = health->composite_temperature; 225 int i;
185 226
186 printf("SMART/Health Information Log\n"); 227 printf("SMART/Health Information Log\n");
187 printf("============================\n"); 228 printf("============================\n");
188 229
189 printf("Critical Warning State: 0x%02x\n", 230 printf("Critical Warning State: 0x%02x\n",
190 health->critical_warning); 231 health->critical_warning);
191 printf(" Available spare: %d\n", 232 printf(" Available spare: %d\n",
192 (uint8_t)__SHIFTOUT(health->critical_warning, 233 (uint8_t)__SHIFTOUT(health->critical_warning,
193 NVME_HEALTH_PAGE_CW_AVAIL_SPARE)); 234 NVME_HEALTH_PAGE_CW_AVAIL_SPARE));
194 printf(" Temperature: %d\n", 235 printf(" Temperature: %d\n",
195 (uint8_t)__SHIFTOUT(health->critical_warning, 236 (uint8_t)__SHIFTOUT(health->critical_warning,
196 NVME_HEALTH_PAGE_CW_TEMPERTURE)); 237 NVME_HEALTH_PAGE_CW_TEMPERTURE));
197 printf(" Device reliability: %d\n", 238 printf(" Device reliability: %d\n",
198 (uint8_t)__SHIFTOUT(health->critical_warning, 239 (uint8_t)__SHIFTOUT(health->critical_warning,
199 NVME_HEALTH_PAGE_CW_DEVICE_RELIABLITY)); 240 NVME_HEALTH_PAGE_CW_DEVICE_RELIABLITY));
200 printf(" Read only: %d\n", 241 printf(" Read only: %d\n",
201 (uint8_t)__SHIFTOUT(health->critical_warning, 242 (uint8_t)__SHIFTOUT(health->critical_warning,
202 NVME_HEALTH_PAGE_CW_READ_ONLY)); 243 NVME_HEALTH_PAGE_CW_READ_ONLY));
203 printf(" Volatile memory backup: %d\n", 244 printf(" Volatile memory backup: %d\n",
204 (uint8_t)__SHIFTOUT(health->critical_warning, 245 (uint8_t)__SHIFTOUT(health->critical_warning,
205 NVME_HEALTH_PAGE_CW_VOLATILE_MEMORY_BACKUP)); 246 NVME_HEALTH_PAGE_CW_VOLATILE_MEMORY_BACKUP));
206 printf("Temperature: %u K, %2.2f C, %3.2f F\n", 247 printf("Temperature: ");
207 health->composite_temperature, 248 print_temp(health->composite_temperature);
208 composite_temperature - (float)273.15, 
209 (composite_temperature * (float)9/5) - (float)459.67); 
210 printf("Available spare: %u\n", 249 printf("Available spare: %u\n",
211 health->available_spare); 250 health->available_spare);
212 printf("Available spare threshold: %u\n", 251 printf("Available spare threshold: %u\n",
213 health->available_spare_threshold); 252 health->available_spare_threshold);
214 printf("Percentage used: %u\n", 253 printf("Percentage used: %u\n",
215 health->percentage_used); 254 health->percentage_used);
216 255
217 print_bignum("Data units (512 byte) read:", 256 print_bignum("Data units (512 byte) read:", health->data_units_read, "");
218 health->data_units_read, ""); 257 print_bignum("Data units (512 byte) written:", health->data_units_written,
219 print_bignum("Data units (512 byte) written:", 258 "");
220 health->data_units_written, ""); 259 print_bignum("Host read commands:", health->host_read_commands, "");
221 print_bignum("Host read commands:", 260 print_bignum("Host write commands:", health->host_write_commands, "");
222 health->host_read_commands, ""); 261 print_bignum("Controller busy time (minutes):", health->controller_busy_time,
223 print_bignum("Host write commands:", 262 "");
224 health->host_write_commands, ""); 263 print_bignum("Power cycles:", health->power_cycles, "");
225 print_bignum("Controller busy time (minutes):", 264 print_bignum("Power on hours:", health->power_on_hours, "");
226 health->controller_busy_time, ""); 265 print_bignum("Unsafe shutdowns:", health->unsafe_shutdowns, "");
227 print_bignum("Power cycles:", 266 print_bignum("Media errors:", health->media_errors, "");
228 health->power_cycles, ""); 
229 print_bignum("Power on hours:", 
230 health->power_on_hours, ""); 
231 print_bignum("Unsafe shutdowns:", 
232 health->unsafe_shutdowns, ""); 
233 print_bignum("Media errors:", 
234 health->media_errors, ""); 
235 print_bignum("No. error info log entries:", 267 print_bignum("No. error info log entries:",
236 health->num_error_info_log_entries, ""); 268 health->num_error_info_log_entries, "");
 269
 270 printf("Warning Temp Composite Time: %d\n", health->warning_temp_time);
 271 printf("Error Temp Composite Time: %d\n", health->error_temp_time);
 272 for (i = 0; i < 7; i++) {
 273 if (health->temp_sensor[i] == 0)
 274 continue;
 275 printf("Temperature Sensor %d: ", i + 1);
 276 print_temp(health->temp_sensor[i]);
 277 }
237} 278}
238 279
239static void 280static void
240print_log_firmware(void *buf, uint32_t size __unused) 281print_log_firmware(void *buf, uint32_t size __unused)
241{ 282{
242 u_int i; 283 u_int i;
243 const char *status; 284 const char *status;
244 struct nvme_firmware_page *fw = buf; 285 struct nvme_firmware_page *fw = buf;
245 286
246 printf("Firmware Slot Log\n"); 287 printf("Firmware Slot Log\n");
247 printf("=================\n"); 288 printf("=================\n");
248 289
249 for (i = 0; i < MAX_FW_SLOTS; i++) { 290 for (i = 0; i < MAX_FW_SLOTS; i++) {
@@ -255,83 +296,683 @@ print_log_firmware(void *buf, uint32_t s @@ -255,83 +296,683 @@ print_log_firmware(void *buf, uint32_t s
255 296
256 if (fw->revision[i] == 0LLU) 297 if (fw->revision[i] == 0LLU)
257 printf("Empty\n"); 298 printf("Empty\n");
258 else 299 else
259 if (isprint(*(uint8_t *)&fw->revision[i])) 300 if (isprint(*(uint8_t *)&fw->revision[i]))
260 printf("[%s] %.8s\n", status, 301 printf("[%s] %.8s\n", status,
261 (char *)&fw->revision[i]); 302 (char *)&fw->revision[i]);
262 else 303 else
263 printf("[%s] %016jx\n", status, 304 printf("[%s] %016jx\n", status,
264 fw->revision[i]); 305 fw->revision[i]);
265 } 306 }
266} 307}
267 308
 309/*
 310 * Intel specific log pages from
 311 * http://www.intel.com/content/dam/www/public/us/en/documents/product-specifications/ssd-dc-p3700-spec.pdf
 312 *
 313 * Though the version as of this date has a typo for the size of log page 0xca,
 314 * offset 147: it is only 1 byte, not 6.
 315 */
 316static void
 317print_intel_temp_stats(void *buf, uint32_t size __unused)
 318{
 319 struct intel_log_temp_stats *temp = buf;
 320
 321 printf("Intel Temperature Log\n");
 322 printf("=====================\n");
 323
 324 printf("Current: ");
 325 print_temp(temp->current);
 326 printf("Overtemp Last Flags %#jx\n",
 327 (uintmax_t)temp->overtemp_flag_last);
 328 printf("Overtemp Lifetime Flags %#jx\n",
 329 (uintmax_t)temp->overtemp_flag_life);
 330 printf("Max Temperature ");
 331 print_temp(temp->max_temp);
 332 printf("Min Temperature ");
 333 print_temp(temp->min_temp);
 334 printf("Max Operating Temperature ");
 335 print_temp(temp->max_oper_temp);
 336 printf("Min Operating Temperature ");
 337 print_temp(temp->min_oper_temp);
 338 printf("Estimated Temperature Offset: %ju C/K\n",
 339 (uintmax_t)temp->est_offset);
 340}
 341
 342/*
 343 * Format from Table 22, section 5.7 IO Command Latency Statistics.
 344 * Read and write stats pages have identical encoding.
 345 */
 346static void
 347print_intel_read_write_lat_log(void *buf, uint32_t size __unused)
 348{
 349 const char *walker = buf;
 350 int i;
 351
 352 printf("Major: %d\n", le16dec(walker + 0));
 353 printf("Minor: %d\n", le16dec(walker + 2));
 354 for (i = 0; i < 32; i++)
 355 printf("%4dus-%4dus: %ju\n", i * 32, (i + 1) * 32,
 356 (uintmax_t)le32dec(walker + 4 + i * 4));
 357 for (i = 1; i < 32; i++)
 358 printf("%4dms-%4dms: %ju\n", i, i + 1,
 359 (uintmax_t)le32dec(walker + 132 + i * 4));
 360 for (i = 1; i < 32; i++)
 361 printf("%4dms-%4dms: %ju\n", i * 32, (i + 1) * 32,
 362 (uintmax_t)le32dec(walker + 256 + i * 4));
 363}
 364
 365static void
 366print_intel_read_lat_log(void *buf, uint32_t size)
 367{
 368
 369 printf("Intel Read Latency Log\n");
 370 printf("======================\n");
 371 print_intel_read_write_lat_log(buf, size);
 372}
 373
 374static void
 375print_intel_write_lat_log(void *buf, uint32_t size)
 376{
 377
 378 printf("Intel Write Latency Log\n");
 379 printf("=======================\n");
 380 print_intel_read_write_lat_log(buf, size);
 381}
 382
 383/*
 384 * Table 19. 5.4 SMART Attributes.
 385 * Samsung also implements this and some extra data not documented.
 386 */
 387static void
 388print_intel_add_smart(void *buf, uint32_t size __unused)
 389{
 390 uint8_t *walker = buf;
 391 uint8_t *end = walker + 150;
 392 const char *name;
 393 uint64_t raw;
 394 uint8_t normalized;
 395
 396 static struct kv_name kv[] = {
 397 { 0xab, "Program Fail Count" },
 398 { 0xac, "Erase Fail Count" },
 399 { 0xad, "Wear Leveling Count" },
 400 { 0xb8, "End to End Error Count" },
 401 { 0xc7, "CRC Error Count" },
 402 { 0xe2, "Timed: Media Wear" },
 403 { 0xe3, "Timed: Host Read %" },
 404 { 0xe4, "Timed: Elapsed Time" },
 405 { 0xea, "Thermal Throttle Status" },
 406 { 0xf0, "Retry Buffer Overflows" },
 407 { 0xf3, "PLL Lock Loss Count" },
 408 { 0xf4, "NAND Bytes Written" },
 409 { 0xf5, "Host Bytes Written" },
 410 };
 411
 412 printf("Additional SMART Data Log\n");
 413 printf("=========================\n");
 414 /*
 415 * walker[0] = Key
 416 * walker[1,2] = reserved
 417 * walker[3] = Normalized Value
 418 * walker[4] = reserved
 419 * walker[5..10] = Little Endian Raw value
 420 * (or other represenations)
 421 * walker[11] = reserved
 422 */
 423 while (walker < end) {
 424 name = kv_lookup(kv, __arraycount(kv), *walker);
 425 normalized = walker[3];
 426 raw = le48dec(walker + 5);
 427 switch (*walker){
 428 case 0:
 429 break;
 430 case 0xad:
 431 printf("%-32s: %3d min: %u max: %u ave: %u\n", name,
 432 normalized, le16dec(walker + 5), le16dec(walker + 7),
 433 le16dec(walker + 9));
 434 break;
 435 case 0xe2:
 436 printf("%-32s: %3d %.3f%%\n", name, normalized, raw / 1024.0);
 437 break;
 438 case 0xea:
 439 printf("%-32s: %3d %d%% %d times\n", name, normalized,
 440 walker[5], le32dec(walker+6));
 441 break;
 442 default:
 443 printf("%-32s: %3d %ju\n", name, normalized, (uintmax_t)raw);
 444 break;
 445 }
 446 walker += 12;
 447 }
 448}
 449
 450/*
 451 * HGST's 0xc1 page. This is a grab bag of additional data. Please see
 452 * https://www.hgst.com/sites/default/files/resources/US_SN150_ProdManual.pdf
 453 * https://www.hgst.com/sites/default/files/resources/US_SN100_ProdManual.pdf
 454 * Appendix A for details
 455 */
 456
 457typedef void (*subprint_fn_t)(void *buf, uint16_t subtype, uint8_t res, uint32_t size);
 458
 459struct subpage_print {
 460 uint16_t key;
 461 subprint_fn_t fn;
 462};
 463
 464static void print_hgst_info_write_errors(void *, uint16_t, uint8_t, uint32_t);
 465static void print_hgst_info_read_errors(void *, uint16_t, uint8_t, uint32_t);
 466static void print_hgst_info_verify_errors(void *, uint16_t, uint8_t, uint32_t);
 467static void print_hgst_info_self_test(void *, uint16_t, uint8_t, uint32_t);
 468static void print_hgst_info_background_scan(void *, uint16_t, uint8_t, uint32_t);
 469static void print_hgst_info_erase_errors(void *, uint16_t, uint8_t, uint32_t);
 470static void print_hgst_info_erase_counts(void *, uint16_t, uint8_t, uint32_t);
 471static void print_hgst_info_temp_history(void *, uint16_t, uint8_t, uint32_t);
 472static void print_hgst_info_ssd_perf(void *, uint16_t, uint8_t, uint32_t);
 473static void print_hgst_info_firmware_load(void *, uint16_t, uint8_t, uint32_t);
 474
 475static struct subpage_print hgst_subpage[] = {
 476 { 0x02, print_hgst_info_write_errors },
 477 { 0x03, print_hgst_info_read_errors },
 478 { 0x05, print_hgst_info_verify_errors },
 479 { 0x10, print_hgst_info_self_test },
 480 { 0x15, print_hgst_info_background_scan },
 481 { 0x30, print_hgst_info_erase_errors },
 482 { 0x31, print_hgst_info_erase_counts },
 483 { 0x32, print_hgst_info_temp_history },
 484 { 0x37, print_hgst_info_ssd_perf },
 485 { 0x38, print_hgst_info_firmware_load },
 486};
 487
 488/* Print a subpage that is basically just key value pairs */
 489static void
 490print_hgst_info_subpage_gen(void *buf, uint16_t subtype __unused, uint32_t size,
 491 const struct kv_name *kv, size_t kv_count)
 492{
 493 uint8_t *wsp, *esp;
 494 uint16_t ptype;
 495 uint8_t plen;
 496 uint64_t param;
 497 int i;
 498
 499 wsp = buf;
 500 esp = wsp + size;
 501 while (wsp < esp) {
 502 ptype = le16dec(wsp);
 503 wsp += 2;
 504 wsp++; /* Flags, just ignore */
 505 plen = *wsp++;
 506 param = 0;
 507 for (i = 0; i < plen; i++)
 508 param |= (uint64_t)*wsp++ << (i * 8);
 509 printf(" %-30s: %jd\n", kv_lookup(kv, kv_count, ptype),
 510 (uintmax_t)param);
 511 }
 512}
 513
 514static void
 515print_hgst_info_write_errors(void *buf, uint16_t subtype, uint8_t res __unused,
 516 uint32_t size)
 517{
 518 static const struct kv_name kv[] = {
 519 { 0x0000, "Corrected Without Delay" },
 520 { 0x0001, "Corrected Maybe Delayed" },
 521 { 0x0002, "Re-Writes" },
 522 { 0x0003, "Errors Corrected" },
 523 { 0x0004, "Correct Algorithm Used" },
 524 { 0x0005, "Bytes Processed" },
 525 { 0x0006, "Uncorrected Errors" },
 526 { 0x8000, "Flash Write Commands" },
 527 { 0x8001, "HGST Special" },
 528 };
 529
 530 printf("Write Errors Subpage:\n");
 531 print_hgst_info_subpage_gen(buf, subtype, size, kv, __arraycount(kv));
 532}
 533
 534static void
 535print_hgst_info_read_errors(void *buf, uint16_t subtype, uint8_t res __unused,
 536 uint32_t size)
 537{
 538 static const struct kv_name kv[] = {
 539 { 0x0000, "Corrected Without Delay" },
 540 { 0x0001, "Corrected Maybe Delayed" },
 541 { 0x0002, "Re-Reads" },
 542 { 0x0003, "Errors Corrected" },
 543 { 0x0004, "Correct Algorithm Used" },
 544 { 0x0005, "Bytes Processed" },
 545 { 0x0006, "Uncorrected Errors" },
 546 { 0x8000, "Flash Read Commands" },
 547 { 0x8001, "XOR Recovered" },
 548 { 0x8002, "Total Corrected Bits" },
 549 };
 550
 551 printf("Read Errors Subpage:\n");
 552 print_hgst_info_subpage_gen(buf, subtype, size, kv, __arraycount(kv));
 553}
 554
 555static void
 556print_hgst_info_verify_errors(void *buf, uint16_t subtype, uint8_t res __unused,
 557 uint32_t size)
 558{
 559 static const struct kv_name kv[] = {
 560 { 0x0000, "Corrected Without Delay" },
 561 { 0x0001, "Corrected Maybe Delayed" },
 562 { 0x0002, "Re-Reads" },
 563 { 0x0003, "Errors Corrected" },
 564 { 0x0004, "Correct Algorithm Used" },
 565 { 0x0005, "Bytes Processed" },
 566 { 0x0006, "Uncorrected Errors" },
 567 { 0x8000, "Commands Processed" },
 568 };
 569
 570 printf("Verify Errors Subpage:\n");
 571 print_hgst_info_subpage_gen(buf, subtype, size, kv, __arraycount(kv));
 572}
 573
 574static void
 575print_hgst_info_self_test(void *buf, uint16_t subtype __unused, uint8_t res __unused,
 576 uint32_t size)
 577{
 578 size_t i;
 579 uint8_t *walker = buf;
 580 uint16_t code, hrs;
 581 uint32_t lba;
 582
 583 printf("Self Test Subpage:\n");
 584 for (i = 0; i < size / 20; i++) { /* Each entry is 20 bytes */
 585 code = le16dec(walker);
 586 walker += 2;
 587 walker++; /* Ignore fixed flags */
 588 if (*walker == 0) /* Last entry is zero length */
 589 break;
 590 if (*walker++ != 0x10) {
 591 printf("Bad length for self test report\n");
 592 return;
 593 }
 594 printf(" %-30s: %d\n", "Recent Test", code);
 595 printf(" %-28s: %#x\n", "Self-Test Results", *walker & 0xf);
 596 printf(" %-28s: %#x\n", "Self-Test Code", (*walker >> 5) & 0x7);
 597 walker++;
 598 printf(" %-28s: %#x\n", "Self-Test Number", *walker++);
 599 hrs = le16dec(walker);
 600 walker += 2;
 601 lba = le32dec(walker);
 602 walker += 4;
 603 printf(" %-28s: %u\n", "Total Power On Hrs", hrs);
 604 printf(" %-28s: %#jx (%jd)\n", "LBA", (uintmax_t)lba,
 605 (uintmax_t)lba);
 606 printf(" %-28s: %#x\n", "Sense Key", *walker++ & 0xf);
 607 printf(" %-28s: %#x\n", "Additional Sense Code", *walker++);
 608 printf(" %-28s: %#x\n", "Additional Sense Qualifier", *walker++);
 609 printf(" %-28s: %#x\n", "Vendor Specific Detail", *walker++);
 610 }
 611}
 612
 613static void
 614print_hgst_info_background_scan(void *buf, uint16_t subtype __unused,
 615 uint8_t res __unused, uint32_t size)
 616{
 617 uint8_t *walker = buf;
 618 uint8_t status;
 619 uint16_t code, nscan, progress;
 620 uint32_t pom, nand;
 621
 622 printf("Background Media Scan Subpage:\n");
 623 /* Decode the header */
 624 code = le16dec(walker);
 625 walker += 2;
 626 walker++; /* Ignore fixed flags */
 627 if (*walker++ != 0x10) {
 628 printf("Bad length for background scan header\n");
 629 return;
 630 }
 631 if (code != 0) {
 632 printf("Expceted code 0, found code %#x\n", code);
 633 return;
 634 }
 635 pom = le32dec(walker);
 636 walker += 4;
 637 walker++; /* Reserved */
 638 status = *walker++;
 639 nscan = le16dec(walker);
 640 walker += 2;
 641 progress = le16dec(walker);
 642 walker += 2;
 643 walker += 6; /* Reserved */
 644 printf(" %-30s: %d\n", "Power On Minutes", pom);
 645 printf(" %-30s: %x (%s)\n", "BMS Status", status,
 646 status == 0 ? "idle" : (status == 1 ? "active" :
 647 (status == 8 ? "suspended" : "unknown")));
 648 printf(" %-30s: %d\n", "Number of BMS", nscan);
 649 printf(" %-30s: %d\n", "Progress Current BMS", progress);
 650 /* Report retirements */
 651 if (walker - (uint8_t *)buf != 20) {
 652 printf("Coding error, offset not 20\n");
 653 return;
 654 }
 655 size -= 20;
 656 printf(" %-30s: %d\n", "BMS retirements", size / 0x18);
 657 while (size > 0) {
 658 code = le16dec(walker);
 659 walker += 2;
 660 walker++;
 661 if (*walker++ != 0x14) {
 662 printf("Bad length parameter\n");
 663 return;
 664 }
 665 pom = le32dec(walker);
 666 walker += 4;
 667 /*
 668 * Spec sheet says the following are hard coded, if true, just
 669 * print the NAND retirement.
 670 */
 671 if (walker[0] == 0x41 &&
 672 walker[1] == 0x0b &&
 673 walker[2] == 0x01 &&
 674 walker[3] == 0x00 &&
 675 walker[4] == 0x00 &&
 676 walker[5] == 0x00 &&
 677 walker[6] == 0x00 &&
 678 walker[7] == 0x00) {
 679 walker += 8;
 680 walker += 4; /* Skip reserved */
 681 nand = le32dec(walker);
 682 walker += 4;
 683 printf(" %-30s: %d\n", "Retirement number", code);
 684 printf(" %-28s: %#x\n", "NAND (C/T)BBBPPP", nand);
 685 } else {
 686 printf("Parameter %#x entry corrupt\n", code);
 687 walker += 16;
 688 }
 689 }
 690}
 691
 692static void
 693print_hgst_info_erase_errors(void *buf, uint16_t subtype __unused,
 694 uint8_t res __unused, uint32_t size)
 695{
 696 static const struct kv_name kv[] = {
 697 { 0x0000, "Corrected Without Delay" },
 698 { 0x0001, "Corrected Maybe Delayed" },
 699 { 0x0002, "Re-Erase" },
 700 { 0x0003, "Errors Corrected" },
 701 { 0x0004, "Correct Algorithm Used" },
 702 { 0x0005, "Bytes Processed" },
 703 { 0x0006, "Uncorrected Errors" },
 704 { 0x8000, "Flash Erase Commands" },
 705 { 0x8001, "Mfg Defect Count" },
 706 { 0x8002, "Grown Defect Count" },
 707 { 0x8003, "Erase Count -- User" },
 708 { 0x8004, "Erase Count -- System" },
 709 };
 710
 711 printf("Erase Errors Subpage:\n");
 712 print_hgst_info_subpage_gen(buf, subtype, size, kv, __arraycount(kv));
 713}
 714
 715static void
 716print_hgst_info_erase_counts(void *buf, uint16_t subtype, uint8_t res __unused,
 717 uint32_t size)
 718{
 719 /* My drive doesn't export this -- so not coding up */
 720 printf("XXX: Erase counts subpage: %p, %#x %d\n", buf, subtype, size);
 721}
 722
 723static void
 724print_hgst_info_temp_history(void *buf, uint16_t subtype __unused,
 725 uint8_t res __unused, uint32_t size __unused)
 726{
 727 uint8_t *walker = buf;
 728 uint32_t min;
 729
 730 printf("Temperature History:\n");
 731 printf(" %-30s: %d C\n", "Current Temperature", *walker++);
 732 printf(" %-30s: %d C\n", "Reference Temperature", *walker++);
 733 printf(" %-30s: %d C\n", "Maximum Temperature", *walker++);
 734 printf(" %-30s: %d C\n", "Minimum Temperature", *walker++);
 735 min = le32dec(walker);
 736 walker += 4;
 737 printf(" %-30s: %d:%02d:00\n", "Max Temperature Time", min / 60, min % 60);
 738 min = le32dec(walker);
 739 walker += 4;
 740 printf(" %-30s: %d:%02d:00\n", "Over Temperature Duration", min / 60,
 741 min % 60);
 742 min = le32dec(walker);
 743 walker += 4;
 744 printf(" %-30s: %d:%02d:00\n", "Min Temperature Time", min / 60, min % 60);
 745}
 746
 747static void
 748print_hgst_info_ssd_perf(void *buf, uint16_t subtype __unused, uint8_t res,
 749 uint32_t size __unused)
 750{
 751 uint8_t *walker = buf;
 752 uint64_t val;
 753
 754 printf("SSD Performance Subpage Type %d:\n", res);
 755 val = le64dec(walker);
 756 walker += 8;
 757 printf(" %-30s: %ju\n", "Host Read Commands", val);
 758 val = le64dec(walker);
 759 walker += 8;
 760 printf(" %-30s: %ju\n", "Host Read Blocks", val);
 761 val = le64dec(walker);
 762 walker += 8;
 763 printf(" %-30s: %ju\n", "Host Cache Read Hits Commands", val);
 764 val = le64dec(walker);
 765 walker += 8;
 766 printf(" %-30s: %ju\n", "Host Cache Read Hits Blocks", val);
 767 val = le64dec(walker);
 768 walker += 8;
 769 printf(" %-30s: %ju\n", "Host Read Commands Stalled", val);
 770 val = le64dec(walker);
 771 walker += 8;
 772 printf(" %-30s: %ju\n", "Host Write Commands", val);
 773 val = le64dec(walker);
 774 walker += 8;
 775 printf(" %-30s: %ju\n", "Host Write Blocks", val);
 776 val = le64dec(walker);
 777 walker += 8;
 778 printf(" %-30s: %ju\n", "Host Write Odd Start Commands", val);
 779 val = le64dec(walker);
 780 walker += 8;
 781 printf(" %-30s: %ju\n", "Host Write Odd End Commands", val);
 782 val = le64dec(walker);
 783 walker += 8;
 784 printf(" %-30s: %ju\n", "Host Write Commands Stalled", val);
 785 val = le64dec(walker);
 786 walker += 8;
 787 printf(" %-30s: %ju\n", "NAND Read Commands", val);
 788 val = le64dec(walker);
 789 walker += 8;
 790 printf(" %-30s: %ju\n", "NAND Read Blocks", val);
 791 val = le64dec(walker);
 792 walker += 8;
 793 printf(" %-30s: %ju\n", "NAND Write Commands", val);
 794 val = le64dec(walker);
 795 walker += 8;
 796 printf(" %-30s: %ju\n", "NAND Write Blocks", val);
 797 val = le64dec(walker);
 798 walker += 8;
 799 printf(" %-30s: %ju\n", "NAND Read Before Writes", val);
 800}
 801
 802static void
 803print_hgst_info_firmware_load(void *buf, uint16_t subtype __unused,
 804 uint8_t res __unused, uint32_t size __unused)
 805{
 806 uint8_t *walker = buf;
 807
 808 printf("Firmware Load Subpage:\n");
 809 printf(" %-30s: %d\n", "Firmware Downloads", le32dec(walker));
 810}
 811
 812static void
 813kv_indirect(void *buf, uint32_t subtype, uint8_t res, uint32_t size,
 814 struct subpage_print *sp, size_t nsp)
 815{
 816 size_t i;
 817
 818 for (i = 0; i < nsp; i++, sp++) {
 819 if (sp->key == subtype) {
 820 sp->fn(buf, subtype, res, size);
 821 return;
 822 }
 823 }
 824 printf("No handler for page type %x\n", subtype);
 825}
 826
 827static void
 828print_hgst_info_log(void *buf, uint32_t size __unused)
 829{
 830 uint8_t *walker, *end, *subpage;
 831 int pages __unused;
 832 uint16_t len;
 833 uint8_t subtype, res;
 834
 835 printf("HGST Extra Info Log\n");
 836 printf("===================\n");
 837
 838 walker = buf;
 839 pages = *walker++;
 840 walker++;
 841 len = le16dec(walker);
 842 walker += 2;
 843 end = walker + len; /* Length is exclusive of this header */
 844
 845 while (walker < end) {
 846 subpage = walker + 4;
 847 subtype = *walker++ & 0x3f; /* subtype */
 848 res = *walker++; /* Reserved */
 849 len = le16dec(walker);
 850 walker += len + 2; /* Length, not incl header */
 851 if (walker > end) {
 852 printf("Ooops! Off the end of the list\n");
 853 break;
 854 }
 855 kv_indirect(subpage, subtype, res, len, hgst_subpage,
 856 __arraycount(hgst_subpage));
 857 }
 858}
 859
 860/*
 861 * Table of log page printer / sizing.
 862 *
 863 * This includes Intel specific pages that are widely implemented.
 864 * Make sure you keep all the pages of one vendor together so -v help
 865 * lists all the vendors pages.
 866 */
268static struct logpage_function { 867static struct logpage_function {
269 uint8_t log_page; 868 uint8_t log_page;
270 print_fn_t fn; 869 const char *vendor;
 870 const char *name;
 871 print_fn_t print_fn;
 872 size_t size;
271} logfuncs[] = { 873} logfuncs[] = {
272 {NVME_LOG_ERROR, print_log_error }, 874 {NVME_LOG_ERROR, NULL, "Drive Error Log",
273 {NVME_LOG_HEALTH_INFORMATION, print_log_health }, 875 print_log_error, 0},
274 {NVME_LOG_FIRMWARE_SLOT, print_log_firmware }, 876 {NVME_LOG_HEALTH_INFORMATION, NULL, "Health/SMART Data",
275 {0, NULL }, 877 print_log_health, sizeof(struct nvme_health_information_page)},
 878 {NVME_LOG_FIRMWARE_SLOT, NULL, "Firmware Information",
 879 print_log_firmware, sizeof(struct nvme_firmware_page)},
 880 {HGST_INFO_LOG, "hgst", "Detailed Health/SMART",
 881 print_hgst_info_log, DEFAULT_SIZE},
 882 {HGST_INFO_LOG, "wds", "Detailed Health/SMART",
 883 print_hgst_info_log, DEFAULT_SIZE},
 884 {INTEL_LOG_TEMP_STATS, "intel", "Temperature Stats",
 885 print_intel_temp_stats, sizeof(struct intel_log_temp_stats)},
 886 {INTEL_LOG_READ_LAT_LOG, "intel", "Read Latencies",
 887 print_intel_read_lat_log, DEFAULT_SIZE},
 888 {INTEL_LOG_WRITE_LAT_LOG, "intel", "Write Latencies",
 889 print_intel_write_lat_log, DEFAULT_SIZE},
 890 {INTEL_LOG_ADD_SMART, "intel", "Extra Health/SMART Data",
 891 print_intel_add_smart, DEFAULT_SIZE},
 892 {INTEL_LOG_ADD_SMART, "samsung", "Extra Health/SMART Data",
 893 print_intel_add_smart, DEFAULT_SIZE},
 894
 895 {0, NULL, NULL, NULL, 0},
276}; 896};
277 897
278__dead static void 898__dead static void
279logpage_usage(void) 899logpage_usage(void)
280{ 900{
281 fprintf(stderr, "usage:\n"); 901 fprintf(stderr, "usage:\n");
282 fprintf(stderr, LOGPAGE_USAGE); 902 fprintf(stderr, LOGPAGE_USAGE);
283 exit(1); 903 exit(1);
284} 904}
285 905
 906__dead static void
 907logpage_help(void)
 908{
 909 struct logpage_function *f;
 910 const char *v;
 911
 912 fprintf(stderr, "\n");
 913 fprintf(stderr, "%-8s %-10s %s\n", "Page", "Vendor","Page Name");
 914 fprintf(stderr, "-------- ---------- ----------\n");
 915 for (f = logfuncs; f->log_page > 0; f++) {
 916 v = f->vendor == NULL ? "-" : f->vendor;
 917 fprintf(stderr, "0x%02x %-10s %s\n", f->log_page, v, f->name);
 918 }
 919
 920 exit(1);
 921}
 922
286void 923void
287logpage(int argc, char *argv[]) 924logpage(int argc, char *argv[])
288{ 925{
289 int fd, nsid; 926 int fd, nsid;
290 int log_page = 0, pageflag = false; 927 int log_page = 0, pageflag = false;
291 int hexflag = false, ns_specified; 928 int binflag = false, hexflag = false, ns_specified;
292 int ch; 929 int ch;
293 char *p; 930 char *p;
294 char cname[64]; 931 char cname[64];
295 uint32_t size; 932 uint32_t size;
296 void *buf; 933 void *buf;
 934 const char *vendor = NULL;
297 struct logpage_function *f; 935 struct logpage_function *f;
298 struct nvm_identify_controller cdata; 936 struct nvm_identify_controller cdata;
299 print_fn_t print_fn; 937 print_fn_t print_fn;
300 938
301 while ((ch = getopt(argc, argv, "p:x")) != -1) { 939 while ((ch = getopt(argc, argv, "bp:xv:")) != -1) {
302 switch (ch) { 940 switch (ch) {
 941 case 'b':
 942 binflag = true;
 943 break;
303 case 'p': 944 case 'p':
 945 if (strcmp(optarg, "help") == 0)
 946 logpage_help();
 947
304 /* TODO: Add human-readable ASCII page IDs */ 948 /* TODO: Add human-readable ASCII page IDs */
305 log_page = strtol(optarg, &p, 0); 949 log_page = strtol(optarg, &p, 0);
306 if (p != NULL && *p != '\0') { 950 if (p != NULL && *p != '\0') {
307 fprintf(stderr, 951 fprintf(stderr,
308 "\"%s\" not valid log page id.\n", 952 "\"%s\" not valid log page id.\n",
309 optarg); 953 optarg);
310 logpage_usage(); 954 logpage_usage();
311 /* TODO: Define valid log page id ranges in nvme.h? */ 
312 } else if (log_page == 0 || 
313 (log_page >= 0x04 && log_page <= 0x7F) || 
314 (log_page >= 0x80 && log_page <= 0xBF)) { 
315 fprintf(stderr, 
316 "\"%s\" not valid log page id.\n", 
317 optarg); 
318 logpage_usage(); 
319 } 955 }
320 pageflag = true; 956 pageflag = true;
321 break; 957 break;
322 case 'x': 958 case 'x':
323 hexflag = true; 959 hexflag = true;
324 break; 960 break;
 961 case 'v':
 962 if (strcmp(optarg, "help") == 0)
 963 logpage_help();
 964 vendor = optarg;
 965 break;
325 } 966 }
326 } 967 }
327 968
328 if (!pageflag) { 969 if (!pageflag) {
329 printf("Missing page_id (-p).\n"); 970 printf("Missing page_id (-p).\n");
330 logpage_usage(); 971 logpage_usage();
331 } 972 }
332 973
333 /* Check that a controller and/or namespace was specified. */ 974 /* Check that a controller and/or namespace was specified. */
334 if (optind >= argc) 975 if (optind >= argc)
335 logpage_usage(); 976 logpage_usage();
336 977
337 if (strstr(argv[optind], NVME_NS_PREFIX) != NULL) { 978 if (strstr(argv[optind], NVME_NS_PREFIX) != NULL) {
@@ -352,53 +993,49 @@ logpage(int argc, char *argv[]) @@ -352,53 +993,49 @@ logpage(int argc, char *argv[])
352 * namespace basis. 993 * namespace basis.
353 */ 994 */
354 if (ns_specified) { 995 if (ns_specified) {
355 if (log_page != NVME_LOG_HEALTH_INFORMATION) 996 if (log_page != NVME_LOG_HEALTH_INFORMATION)
356 errx(1, "log page %d valid only at controller level", 997 errx(1, "log page %d valid only at controller level",
357 log_page); 998 log_page);
358 if (!(cdata.lpa & NVME_ID_CTRLR_LPA_NS_SMART)) 999 if (!(cdata.lpa & NVME_ID_CTRLR_LPA_NS_SMART))
359 errx(1, 1000 errx(1,
360 "controller does not support per namespace " 1001 "controller does not support per namespace "
361 "smart/health information"); 1002 "smart/health information");
362 } 1003 }
363 1004
364 print_fn = print_hex; 1005 print_fn = print_hex;
365 if (!hexflag) { 1006 size = DEFAULT_SIZE;
 1007 if (binflag)
 1008 print_fn = print_bin;
 1009 if (!binflag && !hexflag) {
366 /* 1010 /*
367 * See if there is a pretty print function for the 1011 * See if there is a pretty print function for the specified log
368 * specified log page. If one isn't found, we 1012 * page. If one isn't found, we just revert to the default
369 * just revert to the default (print_hex). 1013 * (print_hex). If there was a vendor specified bt the user, and
 1014 * the page is vendor specific, don't match the print function
 1015 * unless the vendors match.
370 */ 1016 */
371 f = logfuncs; 1017 for (f = logfuncs; f->log_page > 0; f++) {
372 while (f->log_page > 0) { 1018 if (f->vendor != NULL && vendor != NULL &&
373 if (log_page == f->log_page) { 1019 strcmp(f->vendor, vendor) != 0)
374 print_fn = f->fn; 1020 continue;
375 break; 1021 if (log_page != f->log_page)
376 } 1022 continue;
377 f++; 1023 print_fn = f->print_fn;
 1024 size = f->size;
 1025 break;
378 } 1026 }
379 } 1027 }
380 1028
381 /* Read the log page */ 1029 if (log_page == NVME_LOG_ERROR) {
382 switch (log_page) { 
383 case NVME_LOG_ERROR: 
384 size = sizeof(struct nvme_error_information_entry); 1030 size = sizeof(struct nvme_error_information_entry);
385 size *= (cdata.elpe + 1); 1031 size *= (cdata.elpe + 1);
386 break; 
387 case NVME_LOG_HEALTH_INFORMATION: 
388 size = sizeof(struct nvme_health_information_page); 
389 break; 
390 case NVME_LOG_FIRMWARE_SLOT: 
391 size = sizeof(struct nvme_firmware_page); 
392 break; 
393 default: 
394 size = DEFAULT_SIZE; 
395 break; 
396 } 1032 }
397 1033
 1034 /* Read the log page */
398 buf = get_log_buffer(size); 1035 buf = get_log_buffer(size);
399 read_logpage(fd, log_page, nsid, buf, size); 1036 read_logpage(fd, log_page, nsid, buf, size);
400 print_fn(buf, size); 1037 print_fn(buf, size);
401 1038
402 close(fd); 1039 close(fd);
403 exit(0); 1040 exit(0);
404} 1041}