nvmectl(8): Sync with FreeBSD nvmecontrol(8) r328763.
This commit is contained in:
parent
cb9f942e0a
commit
1f5086ec4f
@ -1,4 +1,4 @@
|
||||
# $NetBSD: Makefile,v 1.3 2017/04/29 00:06:40 nonaka Exp $
|
||||
# $NetBSD: Makefile,v 1.4 2018/04/17 08:54:35 nonaka Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
@ -11,6 +11,7 @@ SRCS+= logpage.c
|
||||
SRCS+= perftest.c
|
||||
SRCS+= power.c
|
||||
SRCS+= reset.c
|
||||
SRCS+= util.c
|
||||
SRCS+= wdc.c
|
||||
SRCS+= bignum.c
|
||||
SRCS+= humanize_bignum.c
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* $NetBSD: devlist.c,v 1.3 2018/03/17 11:07:26 jdolecek Exp $ */
|
||||
/* $NetBSD: devlist.c,v 1.4 2018/04/17 08:54:35 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (C) 2012-2013 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -28,9 +30,9 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: devlist.c,v 1.3 2018/03/17 11:07:26 jdolecek Exp $");
|
||||
__RCSID("$NetBSD: devlist.c,v 1.4 2018/04/17 08:54:35 nonaka Exp $");
|
||||
#if 0
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/devlist.c 260381 2014-01-06 23:48:47Z jimharris $");
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/devlist.c 326276 2017-11-27 15:37:16Z pfg $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* $NetBSD: firmware.c,v 1.2 2017/04/29 00:06:40 nonaka Exp $ */
|
||||
/* $NetBSD: firmware.c,v 1.3 2018/04/17 08:54:35 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2013 EMC Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -31,9 +33,9 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: firmware.c,v 1.2 2017/04/29 00:06:40 nonaka Exp $");
|
||||
__RCSID("$NetBSD: firmware.c,v 1.3 2018/04/17 08:54:35 nonaka Exp $");
|
||||
#if 0
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/firmware.c 313188 2017-02-04 05:52:50Z imp $");
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/firmware.c 326276 2017-11-27 15:37:16Z pfg $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* $NetBSD: identify.c,v 1.3 2018/03/17 11:07:26 jdolecek Exp $ */
|
||||
/* $NetBSD: identify.c,v 1.4 2018/04/17 08:54:35 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (C) 2012-2013 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -28,9 +30,9 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: identify.c,v 1.3 2018/03/17 11:07:26 jdolecek Exp $");
|
||||
__RCSID("$NetBSD: identify.c,v 1.4 2018/04/17 08:54:35 nonaka Exp $");
|
||||
#if 0
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/identify.c 253476 2013-07-19 21:40:57Z jimharris $");
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/identify.c 326276 2017-11-27 15:37:16Z pfg $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -72,6 +74,7 @@ print_controller(struct nvm_identify_controller *cdata)
|
||||
printf("Unlimited\n");
|
||||
else
|
||||
printf("%ld\n", sysconf(_SC_PAGESIZE) * (1 << cdata->mdts));
|
||||
printf("Controller ID: 0x%02x\n", cdata->cntlid);
|
||||
printf("\n");
|
||||
|
||||
printf("Admin Command Set Attributes\n");
|
||||
@ -85,6 +88,9 @@ print_controller(struct nvm_identify_controller *cdata)
|
||||
printf("Firmware Activate/Download: %s\n",
|
||||
(cdata->oacs & NVME_ID_CTRLR_OACS_FW) ?
|
||||
"Supported" : "Not Supported");
|
||||
printf("Namespace Managment: %s\n",
|
||||
(cdata->oacs & NVME_ID_CTRLR_OACS_NS) ?
|
||||
"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: ");
|
||||
@ -139,6 +145,16 @@ print_controller(struct nvm_identify_controller *cdata)
|
||||
printf("Volatile Write Cache: %s\n",
|
||||
(cdata->vwc & NVME_ID_CTRLR_VWC_PRESENT) ?
|
||||
"Present" : "Not Present");
|
||||
|
||||
if (cdata->oacs & NVME_ID_CTRLR_OACS_NS) {
|
||||
printf("\n");
|
||||
printf("Namespace Drive Attributes\n");
|
||||
printf("==========================\n");
|
||||
print_bignum("NVM total cap: ",
|
||||
cdata->untncap.tnvmcap, "");
|
||||
print_bignum("NVM unallocated cap: ",
|
||||
cdata->untncap.unvmcap, "");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* $NetBSD: logpage.c,v 1.5 2018/03/17 11:07:26 jdolecek Exp $ */
|
||||
/* $NetBSD: logpage.c,v 1.6 2018/04/17 08:54:35 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (c) 2013 EMC Corp.
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -31,9 +33,9 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: logpage.c,v 1.5 2018/03/17 11:07:26 jdolecek Exp $");
|
||||
__RCSID("$NetBSD: logpage.c,v 1.6 2018/04/17 08:54:35 nonaka Exp $");
|
||||
#if 0
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/logpage.c 314230 2017-02-25 00:09:16Z imp $");
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/logpage.c 326276 2017-11-27 15:37:16Z pfg $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -52,12 +54,12 @@ __FBSDID("$FreeBSD: head/sbin/nvmecontrol/logpage.c 314230 2017-02-25 00:09:16Z
|
||||
#include <unistd.h>
|
||||
|
||||
#include "nvmectl.h"
|
||||
#include "bn.h"
|
||||
|
||||
#define DEFAULT_SIZE (4096)
|
||||
#define MAX_FW_SLOTS (7)
|
||||
|
||||
typedef void (*print_fn_t)(void *buf, uint32_t size);
|
||||
typedef void (*print_fn_t)(const struct nvm_identify_controller *cdata, void *buf,
|
||||
uint32_t size);
|
||||
|
||||
struct kv_name {
|
||||
uint32_t key;
|
||||
@ -78,18 +80,17 @@ kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key)
|
||||
}
|
||||
|
||||
static void
|
||||
print_bin(void *data, uint32_t length)
|
||||
print_log_hex(const struct nvm_identify_controller *cdata __unused, void *data,
|
||||
uint32_t length)
|
||||
{
|
||||
write(STDOUT_FILENO, data, length);
|
||||
print_hex(data, length);
|
||||
}
|
||||
|
||||
/* "Missing" from endian.h */
|
||||
static __inline uint64_t
|
||||
le48dec(const void *pp)
|
||||
static void
|
||||
print_bin(const struct nvm_identify_controller *cdata __unused, void *data,
|
||||
uint32_t length)
|
||||
{
|
||||
uint8_t const *p = (uint8_t const *)pp;
|
||||
|
||||
return (((uint64_t)le16dec(p + 4) << 32) | le32dec(p));
|
||||
write(STDOUT_FILENO, data, length);
|
||||
}
|
||||
|
||||
static void *
|
||||
@ -127,7 +128,8 @@ read_logpage(int fd, uint8_t log_page, int nsid, void *payload,
|
||||
}
|
||||
|
||||
static void
|
||||
print_log_error(void *buf, uint32_t size)
|
||||
print_log_error(const struct nvm_identify_controller *cdata __unused, void *buf,
|
||||
uint32_t size)
|
||||
{
|
||||
int i, nentries;
|
||||
struct nvme_error_information_entry *entry = buf;
|
||||
@ -171,46 +173,6 @@ print_log_error(void *buf, uint32_t size)
|
||||
}
|
||||
}
|
||||
|
||||
#define METRIX_PREFIX_BUFSIZ 17
|
||||
#define NO_METRIX_PREFIX_BUFSIZ 42
|
||||
|
||||
static void
|
||||
print_bignum(const char *title, uint64_t v[2], const char *suffix)
|
||||
{
|
||||
char buf[64];
|
||||
uint8_t tmp[16];
|
||||
uint64_t l = le64toh(v[0]);
|
||||
uint64_t h = le64toh(v[1]);
|
||||
|
||||
tmp[ 0] = (h >> 56) & 0xff;
|
||||
tmp[ 1] = (h >> 48) & 0xff;
|
||||
tmp[ 2] = (h >> 40) & 0xff;
|
||||
tmp[ 3] = (h >> 32) & 0xff;
|
||||
tmp[ 4] = (h >> 24) & 0xff;
|
||||
tmp[ 5] = (h >> 16) & 0xff;
|
||||
tmp[ 6] = (h >> 8) & 0xff;
|
||||
tmp[ 7] = h & 0xff;
|
||||
tmp[ 8] = (l >> 56) & 0xff;
|
||||
tmp[ 9] = (l >> 48) & 0xff;
|
||||
tmp[10] = (l >> 40) & 0xff;
|
||||
tmp[11] = (l >> 32) & 0xff;
|
||||
tmp[12] = (l >> 24) & 0xff;
|
||||
tmp[13] = (l >> 16) & 0xff;
|
||||
tmp[14] = (l >> 8) & 0xff;
|
||||
tmp[15] = l & 0xff;
|
||||
|
||||
buf[0] = '\0';
|
||||
BIGNUM *bn = BN_bin2bn(tmp, __arraycount(tmp), NULL);
|
||||
if (bn != NULL) {
|
||||
humanize_bignum(buf, METRIX_PREFIX_BUFSIZ + strlen(suffix),
|
||||
bn, suffix, HN_AUTOSCALE, HN_DECIMAL);
|
||||
BN_free(bn);
|
||||
}
|
||||
if (buf[0] == '\0')
|
||||
snprintf(buf, sizeof(buf), "0x%016jx%016jx", h, l);
|
||||
printf("%-31s %s\n", title, buf);
|
||||
}
|
||||
|
||||
static void
|
||||
print_temp(uint16_t t)
|
||||
{
|
||||
@ -219,7 +181,8 @@ print_temp(uint16_t t)
|
||||
}
|
||||
|
||||
static void
|
||||
print_log_health(void *buf, uint32_t size __unused)
|
||||
print_log_health(const struct nvm_identify_controller *cdata __unused, void *buf,
|
||||
uint32_t size __unused)
|
||||
{
|
||||
struct nvme_health_information_page *health = buf;
|
||||
int i;
|
||||
@ -278,16 +241,23 @@ print_log_health(void *buf, uint32_t size __unused)
|
||||
}
|
||||
|
||||
static void
|
||||
print_log_firmware(void *buf, uint32_t size __unused)
|
||||
print_log_firmware(const struct nvm_identify_controller *cdata, void *buf,
|
||||
uint32_t size __unused)
|
||||
{
|
||||
u_int i;
|
||||
u_int i, slots;
|
||||
const char *status;
|
||||
struct nvme_firmware_page *fw = buf;
|
||||
|
||||
printf("Firmware Slot Log\n");
|
||||
printf("=================\n");
|
||||
|
||||
for (i = 0; i < MAX_FW_SLOTS; i++) {
|
||||
if (!(cdata->oacs & NVME_ID_CTRLR_OACS_FW))
|
||||
slots = 1;
|
||||
else
|
||||
slots = MIN(__SHIFTOUT(cdata->frmw, NVME_ID_CTRLR_FRMW_NSLOT),
|
||||
MAX_FW_SLOTS);
|
||||
|
||||
for (i = 0; i < slots; i++) {
|
||||
printf("Slot %d: ", i + 1);
|
||||
if (__SHIFTOUT(fw->afi, NVME_FW_PAGE_AFI_SLOT) == i + 1)
|
||||
status = " Active";
|
||||
@ -314,7 +284,8 @@ print_log_firmware(void *buf, uint32_t size __unused)
|
||||
* offset 147: it is only 1 byte, not 6.
|
||||
*/
|
||||
static void
|
||||
print_intel_temp_stats(void *buf, uint32_t size __unused)
|
||||
print_intel_temp_stats(const struct nvm_identify_controller *cdata __unused,
|
||||
void *buf, uint32_t size __unused)
|
||||
{
|
||||
struct intel_log_temp_stats *temp = buf;
|
||||
|
||||
@ -344,7 +315,8 @@ print_intel_temp_stats(void *buf, uint32_t size __unused)
|
||||
* Read and write stats pages have identical encoding.
|
||||
*/
|
||||
static void
|
||||
print_intel_read_write_lat_log(void *buf, uint32_t size __unused)
|
||||
print_intel_read_write_lat_log(const struct nvm_identify_controller *cdata __unused,
|
||||
void *buf, uint32_t size __unused)
|
||||
{
|
||||
const char *walker = buf;
|
||||
int i;
|
||||
@ -363,21 +335,23 @@ print_intel_read_write_lat_log(void *buf, uint32_t size __unused)
|
||||
}
|
||||
|
||||
static void
|
||||
print_intel_read_lat_log(void *buf, uint32_t size)
|
||||
print_intel_read_lat_log(const struct nvm_identify_controller *cdata, void *buf,
|
||||
uint32_t size)
|
||||
{
|
||||
|
||||
printf("Intel Read Latency Log\n");
|
||||
printf("======================\n");
|
||||
print_intel_read_write_lat_log(buf, size);
|
||||
print_intel_read_write_lat_log(cdata, buf, size);
|
||||
}
|
||||
|
||||
static void
|
||||
print_intel_write_lat_log(void *buf, uint32_t size)
|
||||
print_intel_write_lat_log(const struct nvm_identify_controller *cdata, void *buf,
|
||||
uint32_t size)
|
||||
{
|
||||
|
||||
printf("Intel Write Latency Log\n");
|
||||
printf("=======================\n");
|
||||
print_intel_read_write_lat_log(buf, size);
|
||||
print_intel_read_write_lat_log(cdata, buf, size);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -385,7 +359,8 @@ print_intel_write_lat_log(void *buf, uint32_t size)
|
||||
* Samsung also implements this and some extra data not documented.
|
||||
*/
|
||||
static void
|
||||
print_intel_add_smart(void *buf, uint32_t size __unused)
|
||||
print_intel_add_smart(const struct nvm_identify_controller *cdata __unused,
|
||||
void *buf, uint32_t size __unused)
|
||||
{
|
||||
uint8_t *walker = buf;
|
||||
uint8_t *end = walker + 150;
|
||||
@ -454,7 +429,8 @@ print_intel_add_smart(void *buf, uint32_t size __unused)
|
||||
* Appendix A for details
|
||||
*/
|
||||
|
||||
typedef void (*subprint_fn_t)(void *buf, uint16_t subtype, uint8_t res, uint32_t size);
|
||||
typedef void (*subprint_fn_t)(void *buf, uint16_t subtype, uint8_t res,
|
||||
uint32_t size);
|
||||
|
||||
struct subpage_print {
|
||||
uint16_t key;
|
||||
@ -825,7 +801,8 @@ kv_indirect(void *buf, uint32_t subtype, uint8_t res, uint32_t size,
|
||||
}
|
||||
|
||||
static void
|
||||
print_hgst_info_log(void *buf, uint32_t size __unused)
|
||||
print_hgst_info_log(const struct nvm_identify_controller *cdata __unused, void *buf,
|
||||
uint32_t size __unused)
|
||||
{
|
||||
uint8_t *walker, *end, *subpage;
|
||||
int pages __unused;
|
||||
@ -1002,7 +979,7 @@ logpage(int argc, char *argv[])
|
||||
"smart/health information");
|
||||
}
|
||||
|
||||
print_fn = print_hex;
|
||||
print_fn = print_log_hex;
|
||||
size = DEFAULT_SIZE;
|
||||
if (binflag)
|
||||
print_fn = print_bin;
|
||||
@ -1034,7 +1011,7 @@ logpage(int argc, char *argv[])
|
||||
/* Read the log page */
|
||||
buf = get_log_buffer(size);
|
||||
read_logpage(fd, log_page, nsid, buf, size);
|
||||
print_fn(buf, size);
|
||||
print_fn(&cdata, buf, size);
|
||||
|
||||
close(fd);
|
||||
exit(0);
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* $NetBSD: nvmectl.c,v 1.5 2018/03/17 11:07:26 jdolecek Exp $ */
|
||||
/* $NetBSD: nvmectl.c,v 1.6 2018/04/17 08:54:35 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (C) 2012-2013 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -28,9 +30,9 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: nvmectl.c,v 1.5 2018/03/17 11:07:26 jdolecek Exp $");
|
||||
__RCSID("$NetBSD: nvmectl.c,v 1.6 2018/04/17 08:54:35 nonaka Exp $");
|
||||
#if 0
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/nvmecontrol.c 314229 2017-02-25 00:09:12Z imp $");
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/nvmecontrol.c 326276 2017-11-27 15:37:16Z pfg $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -238,45 +240,6 @@ parse_ns_str(const char *ns_str, char *ctrlr_str, int *nsid)
|
||||
snprintf(ctrlr_str, nsloc - ns_str + 1, "%s", ns_str);
|
||||
}
|
||||
|
||||
void
|
||||
nvme_strvis(u_char *dst, int dlen, const u_char *src, int slen)
|
||||
{
|
||||
#define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377')
|
||||
/* Trim leading and trailing blanks and NULs. */
|
||||
while (slen > 0 && STRVIS_ISWHITE(src[0]))
|
||||
++src, --slen;
|
||||
while (slen > 0 && STRVIS_ISWHITE(src[slen - 1]))
|
||||
--slen;
|
||||
|
||||
while (slen > 0) {
|
||||
if (*src < 0x20 || *src >= 0x80) {
|
||||
/* non-printable characters */
|
||||
dlen -= 4;
|
||||
if (dlen < 1)
|
||||
break;
|
||||
*dst++ = '\\';
|
||||
*dst++ = ((*src & 0300) >> 6) + '0';
|
||||
*dst++ = ((*src & 0070) >> 3) + '0';
|
||||
*dst++ = ((*src & 0007) >> 0) + '0';
|
||||
} else if (*src == '\\') {
|
||||
/* quote characters */
|
||||
dlen -= 2;
|
||||
if (dlen < 1)
|
||||
break;
|
||||
*dst++ = '\\';
|
||||
*dst++ = '\\';
|
||||
} else {
|
||||
/* normal characters */
|
||||
if (--dlen < 1)
|
||||
break;
|
||||
*dst++ = *src;
|
||||
}
|
||||
++src, --slen;
|
||||
}
|
||||
|
||||
*dst++ = 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* $NetBSD: nvmectl.h,v 1.5 2018/03/17 11:07:26 jdolecek Exp $ */
|
||||
/* $NetBSD: nvmectl.h,v 1.6 2018/04/17 08:54:35 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (C) 2012-2013 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -25,7 +27,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD: head/sbin/nvmecontrol/nvmecontrol.h 314230 2017-02-25 00:09:16Z imp $
|
||||
* $FreeBSD: head/sbin/nvmecontrol/nvmecontrol.h 326276 2017-11-27 15:37:16Z pfg $
|
||||
*/
|
||||
|
||||
#ifndef __NVMECTL_H__
|
||||
@ -53,7 +55,7 @@ struct nvme_function {
|
||||
#define IDENTIFY_USAGE \
|
||||
"identify [-x [-v]] <controller id|namespace id>\n"
|
||||
|
||||
#if 0
|
||||
#ifdef ENABLE_PREFTEST
|
||||
#define PERFTEST_USAGE \
|
||||
"perftest <-n num_threads> <-o read|write>\n" \
|
||||
" <-s size_in_bytes> <-t time_in_seconds>\n" \
|
||||
@ -61,7 +63,7 @@ struct nvme_function {
|
||||
" <namespace id>\n"
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#ifdef ENABLE_RESET
|
||||
#define RESET_USAGE \
|
||||
"reset <controller id>\n"
|
||||
#endif
|
||||
@ -70,7 +72,7 @@ struct nvme_function {
|
||||
"logpage <-p page_id> [-b] [-v vendor] [-x] " \
|
||||
"<controller id|namespace id>\n"
|
||||
|
||||
#if 0
|
||||
#ifdef ENABLE_FIRMWARE
|
||||
#define FIRMWARE_USAGE \
|
||||
"firmware [-s slot] [-f path_to_firmware] [-a] <controller id>\n"
|
||||
#endif
|
||||
@ -103,6 +105,10 @@ void read_namespace_data(int, int, struct nvm_identify_namespace *);
|
||||
void print_hex(void *, uint32_t);
|
||||
void read_logpage(int, uint8_t, int, void *, uint32_t);
|
||||
__dead void dispatch(int argc, char *argv[], const struct nvme_function *f);
|
||||
|
||||
/* Utility Routines */
|
||||
void nvme_strvis(uint8_t *, int, const uint8_t *, int);
|
||||
void print_bignum(const char *, uint64_t v[2], const char *);
|
||||
uint64_t le48dec(const void *);
|
||||
|
||||
#endif /* __NVMECTL_H__ */
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* $NetBSD: perftest.c,v 1.3 2018/03/17 11:07:26 jdolecek Exp $ */
|
||||
/* $NetBSD: perftest.c,v 1.4 2018/04/17 08:54:35 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (C) 2012-2013 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -28,9 +30,9 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: perftest.c,v 1.3 2018/03/17 11:07:26 jdolecek Exp $");
|
||||
__RCSID("$NetBSD: perftest.c,v 1.4 2018/04/17 08:54:35 nonaka Exp $");
|
||||
#if 0
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/perftest.c 257531 2013-11-01 22:05:29Z jimharris $");
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/perftest.c 326276 2017-11-27 15:37:16Z pfg $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* $NetBSD: reset.c,v 1.2 2018/03/17 11:07:26 jdolecek Exp $ */
|
||||
/* $NetBSD: reset.c,v 1.3 2018/04/17 08:54:35 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright (C) 2012-2013 Intel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -28,9 +30,9 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: reset.c,v 1.2 2018/03/17 11:07:26 jdolecek Exp $");
|
||||
__RCSID("$NetBSD: reset.c,v 1.3 2018/04/17 08:54:35 nonaka Exp $");
|
||||
#if 0
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/reset.c 253109 2013-07-09 21:14:15Z jimharris $");
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/reset.c 326276 2017-11-27 15:37:16Z pfg $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
131
sbin/nvmectl/util.c
Normal file
131
sbin/nvmectl/util.c
Normal file
@ -0,0 +1,131 @@
|
||||
/* $NetBSD: util.c,v 1.1 2018/04/17 08:54:35 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Netflix, Inc
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: util.c,v 1.1 2018/04/17 08:54:35 nonaka Exp $");
|
||||
#if 0
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/util.c 320423 2017-06-27 20:24:25Z imp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/endian.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nvmectl.h"
|
||||
#include "bn.h"
|
||||
|
||||
void
|
||||
nvme_strvis(u_char *dst, int dlen, const u_char *src, int slen)
|
||||
{
|
||||
#define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377')
|
||||
/* Trim leading and trailing blanks and NULs. */
|
||||
while (slen > 0 && STRVIS_ISWHITE(src[0]))
|
||||
++src, --slen;
|
||||
while (slen > 0 && STRVIS_ISWHITE(src[slen - 1]))
|
||||
--slen;
|
||||
|
||||
while (slen > 0) {
|
||||
if (*src < 0x20 || *src >= 0x80) {
|
||||
/* non-printable characters */
|
||||
dlen -= 4;
|
||||
if (dlen < 1)
|
||||
break;
|
||||
*dst++ = '\\';
|
||||
*dst++ = ((*src & 0300) >> 6) + '0';
|
||||
*dst++ = ((*src & 0070) >> 3) + '0';
|
||||
*dst++ = ((*src & 0007) >> 0) + '0';
|
||||
} else if (*src == '\\') {
|
||||
/* quote characters */
|
||||
dlen -= 2;
|
||||
if (dlen < 1)
|
||||
break;
|
||||
*dst++ = '\\';
|
||||
*dst++ = '\\';
|
||||
} else {
|
||||
/* normal characters */
|
||||
if (--dlen < 1)
|
||||
break;
|
||||
*dst++ = *src;
|
||||
}
|
||||
++src, --slen;
|
||||
}
|
||||
|
||||
*dst++ = 0;
|
||||
}
|
||||
|
||||
#define METRIX_PREFIX_BUFSIZ 17
|
||||
#define NO_METRIX_PREFIX_BUFSIZ 42
|
||||
|
||||
void
|
||||
print_bignum(const char *title, uint64_t v[2], const char *suffix)
|
||||
{
|
||||
char buf[64];
|
||||
uint8_t tmp[16];
|
||||
uint64_t l = le64toh(v[0]);
|
||||
uint64_t h = le64toh(v[1]);
|
||||
|
||||
tmp[ 0] = (h >> 56) & 0xff;
|
||||
tmp[ 1] = (h >> 48) & 0xff;
|
||||
tmp[ 2] = (h >> 40) & 0xff;
|
||||
tmp[ 3] = (h >> 32) & 0xff;
|
||||
tmp[ 4] = (h >> 24) & 0xff;
|
||||
tmp[ 5] = (h >> 16) & 0xff;
|
||||
tmp[ 6] = (h >> 8) & 0xff;
|
||||
tmp[ 7] = h & 0xff;
|
||||
tmp[ 8] = (l >> 56) & 0xff;
|
||||
tmp[ 9] = (l >> 48) & 0xff;
|
||||
tmp[10] = (l >> 40) & 0xff;
|
||||
tmp[11] = (l >> 32) & 0xff;
|
||||
tmp[12] = (l >> 24) & 0xff;
|
||||
tmp[13] = (l >> 16) & 0xff;
|
||||
tmp[14] = (l >> 8) & 0xff;
|
||||
tmp[15] = l & 0xff;
|
||||
|
||||
buf[0] = '\0';
|
||||
BIGNUM *bn = BN_bin2bn(tmp, __arraycount(tmp), NULL);
|
||||
if (bn != NULL) {
|
||||
humanize_bignum(buf, METRIX_PREFIX_BUFSIZ + strlen(suffix),
|
||||
bn, suffix, HN_AUTOSCALE, HN_DECIMAL);
|
||||
BN_free(bn);
|
||||
}
|
||||
if (buf[0] == '\0')
|
||||
snprintf(buf, sizeof(buf), "0x%016jx%016jx", h, l);
|
||||
printf("%-31s %s\n", title, buf);
|
||||
}
|
||||
|
||||
/* "Missing" from endian.h */
|
||||
uint64_t
|
||||
le48dec(const void *pp)
|
||||
{
|
||||
uint8_t const *p = (uint8_t const *)pp;
|
||||
|
||||
return (((uint64_t)le16dec(p + 4) << 32) | le32dec(p));
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wdc.c,v 1.2 2018/03/17 11:07:26 jdolecek Exp $ */
|
||||
/* $NetBSD: wdc.c,v 1.3 2018/04/17 08:54:35 nonaka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2017 Netflix, Inc
|
||||
@ -28,9 +28,9 @@
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#ifndef lint
|
||||
__RCSID("$NetBSD: wdc.c,v 1.2 2018/03/17 11:07:26 jdolecek Exp $");
|
||||
__RCSID("$NetBSD: wdc.c,v 1.3 2018/04/17 08:54:35 nonaka Exp $");
|
||||
#if 0
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/wdc.c 316105 2017-03-28 20:34:02Z ngie $");
|
||||
__FBSDID("$FreeBSD: head/sbin/nvmecontrol/wdc.c 320522 2017-07-01 02:19:48Z imp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@ -54,36 +54,12 @@ __FBSDID("$FreeBSD: head/sbin/nvmecontrol/wdc.c 316105 2017-03-28 20:34:02Z ngie
|
||||
#define WDC_NVME_CAP_DIAG_OPCODE 0xe6
|
||||
#define WDC_NVME_CAP_DIAG_CMD 0x0000
|
||||
|
||||
#define WDC_NVME_DIAG_OPCODE 0xc6
|
||||
#define WDC_NVME_DRIVE_LOG_SIZE_CMD 0x0120
|
||||
#define WDC_NVME_DRIVE_LOG_CMD 0x0020
|
||||
#define WDC_NVME_CRASH_DUMP_SIZE_CMD 0x0320
|
||||
#define WDC_NVME_CRASH_DUMP_CMD 0x0420
|
||||
#define WDC_NVME_PFAIL_DUMP_SIZE_CMD 0x0520
|
||||
#define WDC_NVME_PFAIL_DUMP_CMD 0x0620
|
||||
|
||||
#define WDC_NVME_CLEAR_DUMP_OPCODE 0xff
|
||||
#define WDC_NVME_CLEAR_CRASH_DUMP_CMD 0x0503
|
||||
#define WDC_NVME_CLEAR_PFAIL_DUMP_CMD 0x0603
|
||||
|
||||
static void wdc_cap_diag(int argc, char *argv[]);
|
||||
static void wdc_drive_log(int argc, char *argv[]);
|
||||
static void wdc_get_crash_dump(int argc, char *argv[]);
|
||||
static void wdc_purge(int argc, char *argv[]);
|
||||
static void wdc_purge_monitor(int argc, char *argv[]);
|
||||
|
||||
#define WDC_CAP_DIAG_USAGE "wdc cap-diag [-o path-template]\n"
|
||||
#define WDC_DRIVE_LOG_USAGE "wdc drive-log [-o path-template]\n"
|
||||
#define WDC_GET_CRASH_DUMP_USAGE "wdc get-crash-dump [-o path-template]\n"
|
||||
#define WDC_PURGE_USAGE "wdc purge [-o path-template]\n"
|
||||
#define WDC_PURGE_MONITOR_USAGE "wdc purge-monitor\n"
|
||||
|
||||
static const struct nvme_function wdc_funcs[] = {
|
||||
{"cap-diag", wdc_cap_diag, WDC_CAP_DIAG_USAGE},
|
||||
{"drive-log", wdc_drive_log, WDC_DRIVE_LOG_USAGE},
|
||||
{"get-crash-dump", wdc_get_crash_dump, WDC_GET_CRASH_DUMP_USAGE},
|
||||
{"purge", wdc_purge, WDC_PURGE_USAGE},
|
||||
{"purge_monitor", wdc_purge_monitor, WDC_PURGE_MONITOR_USAGE},
|
||||
{NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
@ -130,12 +106,13 @@ wdc_get_data(int fd, uint32_t opcode, uint32_t len, uint32_t off, uint32_t cmd,
|
||||
|
||||
static void
|
||||
wdc_do_dump(int fd, char *tmpl, const char *suffix, uint32_t opcode,
|
||||
uint32_t size_cmd, uint32_t cmd, int len_off)
|
||||
uint32_t cmd, int len_off)
|
||||
{
|
||||
int first;
|
||||
int fd2;
|
||||
uint8_t *buf;
|
||||
uint32_t len, offset;
|
||||
ssize_t resid;
|
||||
size_t resid;
|
||||
long page_size;
|
||||
|
||||
page_size = sysconf(_SC_PAGESIZE);
|
||||
@ -144,51 +121,47 @@ wdc_do_dump(int fd, char *tmpl, const char *suffix, uint32_t opcode,
|
||||
|
||||
wdc_append_serial_name(fd, tmpl, MAXPATHLEN, suffix);
|
||||
|
||||
buf = aligned_alloc(page_size, WDC_NVME_TOC_SIZE);
|
||||
if (buf == NULL)
|
||||
errx(1, "Can't get buffer to get size");
|
||||
wdc_get_data(fd, opcode, WDC_NVME_TOC_SIZE,
|
||||
0, size_cmd, buf, WDC_NVME_TOC_SIZE);
|
||||
len = be32dec(buf + len_off);
|
||||
|
||||
if (len == 0)
|
||||
errx(1, "No data for %s", suffix);
|
||||
|
||||
printf("Dumping %d bytes to %s\n", len, tmpl);
|
||||
/* XXX overwrite protection? */
|
||||
fd2 = open(tmpl, O_WRONLY | O_CREAT | O_TRUNC);
|
||||
fd2 = open(tmpl, O_WRONLY | O_CREAT | O_TRUNC, 0644);
|
||||
if (fd2 < 0)
|
||||
err(1, "open %s", tmpl);
|
||||
offset = 0;
|
||||
buf = aligned_alloc(page_size, NVME_MAX_XFER_SIZE);
|
||||
if (buf == NULL)
|
||||
errx(1, "Can't get buffer to read dump");
|
||||
while (len > 0) {
|
||||
offset = 0;
|
||||
len = NVME_MAX_XFER_SIZE;
|
||||
first = 1;
|
||||
|
||||
do {
|
||||
resid = len > NVME_MAX_XFER_SIZE ? NVME_MAX_XFER_SIZE : len;
|
||||
wdc_get_data(fd, opcode, resid, offset, cmd, buf, resid);
|
||||
if (write(fd2, buf, resid) != resid)
|
||||
if (first) {
|
||||
len = be32dec(buf + len_off);
|
||||
if (len == 0)
|
||||
errx(1, "No data for %s", suffix);
|
||||
if (memcmp("E6LG", buf, 4) != 0)
|
||||
printf("Expected header of E6LG, found '%4.4s' instead\n",
|
||||
buf);
|
||||
printf("Dumping %d bytes of version %d.%d log to %s\n", len,
|
||||
buf[8], buf[9], tmpl);
|
||||
/*
|
||||
* Adjust amount to dump if total dump < 1MB,
|
||||
* though it likely doesn't matter to the WDC
|
||||
* analysis tools.
|
||||
*/
|
||||
if (resid > len)
|
||||
resid = len;
|
||||
first = 0;
|
||||
}
|
||||
if (write(fd2, buf, resid) != (ssize_t)resid)
|
||||
err(1, "write");
|
||||
offset += resid;
|
||||
len -= resid;
|
||||
}
|
||||
} while (len > 0);
|
||||
free(buf);
|
||||
close(fd2);
|
||||
}
|
||||
|
||||
static void
|
||||
wdc_do_clear_dump(int fd, uint32_t opcode, uint32_t cmd)
|
||||
{
|
||||
struct nvme_pt_command pt;
|
||||
|
||||
memset(&pt, 0, sizeof(pt));
|
||||
pt.cmd.opcode = opcode;
|
||||
pt.cmd.cdw12 = cmd;
|
||||
if (ioctl(fd, NVME_PASSTHROUGH_CMD, &pt) < 0)
|
||||
err(1, "wdc_do_clear_dump request failed");
|
||||
if (nvme_completion_is_error(&pt.cpl))
|
||||
errx(1, "wdc_do_clear_dump request returned error");
|
||||
}
|
||||
|
||||
__dead static void
|
||||
wdc_cap_diag_usage(void)
|
||||
{
|
||||
@ -219,133 +192,13 @@ wdc_cap_diag(int argc, char *argv[])
|
||||
open_dev(argv[optind], &fd, 1, 1);
|
||||
|
||||
wdc_do_dump(fd, path_tmpl, "cap_diag", WDC_NVME_CAP_DIAG_OPCODE,
|
||||
WDC_NVME_CAP_DIAG_CMD, WDC_NVME_CAP_DIAG_CMD, 4);
|
||||
WDC_NVME_CAP_DIAG_CMD, 4);
|
||||
|
||||
close(fd);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
__dead static void
|
||||
wdc_drive_log_usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage:\n");
|
||||
fprintf(stderr, "\t%s " WDC_DRIVE_LOG_USAGE, getprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
__dead static void
|
||||
wdc_drive_log(int argc, char *argv[])
|
||||
{
|
||||
char path_tmpl[MAXPATHLEN];
|
||||
int ch, fd;
|
||||
|
||||
path_tmpl[0] = '\0';
|
||||
while ((ch = getopt(argc, argv, "o:")) != -1) {
|
||||
switch ((char)ch) {
|
||||
case 'o':
|
||||
strlcpy(path_tmpl, optarg, MAXPATHLEN);
|
||||
break;
|
||||
default:
|
||||
wdc_drive_log_usage();
|
||||
}
|
||||
}
|
||||
/* Check that a controller was specified. */
|
||||
if (optind >= argc)
|
||||
wdc_drive_log_usage();
|
||||
open_dev(argv[optind], &fd, 1, 1);
|
||||
|
||||
wdc_do_dump(fd, path_tmpl, "drive_log", WDC_NVME_DIAG_OPCODE,
|
||||
WDC_NVME_DRIVE_LOG_SIZE_CMD, WDC_NVME_DRIVE_LOG_CMD, 0);
|
||||
|
||||
close(fd);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
__dead static void
|
||||
wdc_get_crash_dump_usage(void)
|
||||
{
|
||||
fprintf(stderr, "usage:\n");
|
||||
fprintf(stderr, "\t%s " WDC_CAP_DIAG_USAGE, getprogname());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
__dead static void
|
||||
wdc_get_crash_dump(int argc, char *argv[])
|
||||
{
|
||||
char path_tmpl[MAXPATHLEN];
|
||||
int ch, fd;
|
||||
|
||||
while ((ch = getopt(argc, argv, "o:")) != -1) {
|
||||
switch ((char)ch) {
|
||||
case 'o':
|
||||
strlcpy(path_tmpl, optarg, MAXPATHLEN);
|
||||
break;
|
||||
default:
|
||||
wdc_get_crash_dump_usage();
|
||||
}
|
||||
}
|
||||
/* Check that a controller was specified. */
|
||||
if (optind >= argc)
|
||||
wdc_get_crash_dump_usage();
|
||||
open_dev(argv[optind], &fd, 1, 1);
|
||||
|
||||
wdc_do_dump(fd, path_tmpl, "crash_dump", WDC_NVME_DIAG_OPCODE,
|
||||
WDC_NVME_CRASH_DUMP_SIZE_CMD, WDC_NVME_CRASH_DUMP_CMD, 0);
|
||||
wdc_do_clear_dump(fd, WDC_NVME_CLEAR_DUMP_OPCODE,
|
||||
WDC_NVME_CLEAR_CRASH_DUMP_CMD);
|
||||
// wdc_led_beacon_disable(fd);
|
||||
wdc_do_dump(fd, path_tmpl, "pfail_dump", WDC_NVME_DIAG_OPCODE,
|
||||
WDC_NVME_PFAIL_DUMP_SIZE_CMD, WDC_NVME_PFAIL_DUMP_CMD, 0);
|
||||
wdc_do_clear_dump(fd, WDC_NVME_CLEAR_DUMP_OPCODE,
|
||||
WDC_NVME_CLEAR_PFAIL_DUMP_CMD);
|
||||
|
||||
close(fd);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
__dead static void
|
||||
wdc_purge(int argc, char *argv[])
|
||||
{
|
||||
char path_tmpl[MAXPATHLEN];
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "o:")) != -1) {
|
||||
switch ((char)ch) {
|
||||
case 'o':
|
||||
strlcpy(path_tmpl, optarg, MAXPATHLEN);
|
||||
break;
|
||||
default:
|
||||
wdc_cap_diag_usage();
|
||||
}
|
||||
}
|
||||
|
||||
printf("purge has not been implemented.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
__dead static void
|
||||
wdc_purge_monitor(int argc, char *argv[])
|
||||
{
|
||||
char path_tmpl[MAXPATHLEN];
|
||||
int ch;
|
||||
|
||||
while ((ch = getopt(argc, argv, "o:")) != -1) {
|
||||
switch ((char)ch) {
|
||||
case 'o':
|
||||
strlcpy(path_tmpl, optarg, MAXPATHLEN);
|
||||
break;
|
||||
default:
|
||||
wdc_cap_diag_usage();
|
||||
}
|
||||
}
|
||||
|
||||
printf("purge has not been implemented.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void
|
||||
wdc(int argc, char *argv[])
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: nvmereg.h,v 1.9 2017/05/29 02:20:34 nonaka Exp $ */
|
||||
/* $NetBSD: nvmereg.h,v 1.10 2018/04/17 08:54:35 nonaka Exp $ */
|
||||
/* $OpenBSD: nvmereg.h,v 1.10 2016/04/14 11:18:32 dlg Exp $ */
|
||||
|
||||
/*
|
||||
@ -20,6 +20,10 @@
|
||||
#ifndef __NVMEREG_H__
|
||||
#define __NVMEREG_H__
|
||||
|
||||
#ifndef NVME_CTASSERT
|
||||
#define NVME_CTASSERT(x, s) __CTASSERT(x)
|
||||
#endif
|
||||
|
||||
#define NVME_CAP 0x0000 /* Controller Capabilities */
|
||||
#define NVME_CAP_MPSMAX(_r) (12 + (((_r) >> 52) & 0xf)) /* shift */
|
||||
#define NVME_CAP_MPSMIN(_r) (12 + (((_r) >> 48) & 0xf)) /* shift */
|
||||
@ -96,6 +100,7 @@ struct nvme_sge {
|
||||
uint8_t id;
|
||||
uint8_t _reserved[15];
|
||||
} __packed __aligned(8);
|
||||
NVME_CTASSERT(sizeof(struct nvme_sge) == 16, "bad size for nvme_sge");
|
||||
|
||||
struct nvme_sge_data {
|
||||
uint8_t id;
|
||||
@ -105,6 +110,7 @@ struct nvme_sge_data {
|
||||
|
||||
uint64_t address;
|
||||
} __packed __aligned(8);
|
||||
NVME_CTASSERT(sizeof(struct nvme_sge_data) == 16, "bad size for nvme_sge_data");
|
||||
|
||||
struct nvme_sge_bit_bucket {
|
||||
uint8_t id;
|
||||
@ -114,6 +120,7 @@ struct nvme_sge_bit_bucket {
|
||||
|
||||
uint64_t address;
|
||||
} __packed __aligned(8);
|
||||
NVME_CTASSERT(sizeof(struct nvme_sge_bit_bucket) == 16, "bad size for nvme_sge_bit_bucket");
|
||||
|
||||
struct nvme_sqe {
|
||||
uint8_t opcode;
|
||||
@ -138,6 +145,7 @@ struct nvme_sqe {
|
||||
uint32_t cdw14;
|
||||
uint32_t cdw15;
|
||||
} __packed __aligned(8);
|
||||
NVME_CTASSERT(sizeof(struct nvme_sqe) == 64, "bad size for nvme_sqe");
|
||||
|
||||
struct nvme_sqe_q {
|
||||
uint8_t opcode;
|
||||
@ -165,6 +173,7 @@ struct nvme_sqe_q {
|
||||
|
||||
uint8_t _reserved4[16];
|
||||
} __packed __aligned(8);
|
||||
NVME_CTASSERT(sizeof(struct nvme_sqe_q) == 64, "bad size for nvme_sqe_q");
|
||||
|
||||
struct nvme_sqe_io {
|
||||
uint8_t opcode;
|
||||
@ -217,6 +226,7 @@ struct nvme_sqe_io {
|
||||
uint16_t elbatm; /* Expected Logical Block
|
||||
Application Tag Mask */
|
||||
} __packed __aligned(8);
|
||||
NVME_CTASSERT(sizeof(struct nvme_sqe_io) == 64, "bad size for nvme_sqe_io");
|
||||
|
||||
struct nvme_cqe {
|
||||
uint32_t cdw0;
|
||||
@ -292,6 +302,7 @@ struct nvme_cqe {
|
||||
#define NVME_CQE_SC_ACCESS_DENIED (0x86 << 1)
|
||||
#define NVME_CQE_PHASE __BIT(0)
|
||||
} __packed __aligned(8);
|
||||
NVME_CTASSERT(sizeof(struct nvme_cqe) == 16, "bad size for nvme_cqe");
|
||||
|
||||
#define NVM_ADMIN_DEL_IOSQ 0x00 /* Delete I/O Submission Queue */
|
||||
#define NVM_ADMIN_ADD_IOSQ 0x01 /* Create I/O Submission Queue */
|
||||
@ -303,8 +314,11 @@ struct nvme_cqe {
|
||||
#define NVM_ADMIN_SET_FEATURES 0x09 /* Set Features */
|
||||
#define NVM_ADMIN_GET_FEATURES 0x0a /* Get Features */
|
||||
#define NVM_ADMIN_ASYNC_EV_REQ 0x0c /* Asynchronous Event Request */
|
||||
#define NVM_ADMIN_NS_MANAGEMENT 0x0d /* Namespace Management */
|
||||
/* 0x0e-0x0f - reserved */
|
||||
#define NVM_ADMIN_FW_COMMIT 0x10 /* Firmware Commit */
|
||||
#define NVM_ADMIN_FW_DOWNLOAD 0x11 /* Firmware Image Download */
|
||||
#define NVM_ADMIN_NS_ATTACHMENT 0x15 /* Namespace Attachment */
|
||||
|
||||
#define NVM_CMD_FLUSH 0x00 /* Flush */
|
||||
#define NVM_CMD_WRITE 0x01 /* Write */
|
||||
@ -314,8 +328,29 @@ struct nvme_cqe {
|
||||
#define NVM_CMD_DSM 0x09 /* Dataset Management */
|
||||
|
||||
/* Features for GET/SET FEATURES */
|
||||
/* 0x00 - reserved */
|
||||
#define NVM_FEAT_ARBITRATION 0x01
|
||||
#define NVM_FEAT_POWER_MANAGEMENT 0x02
|
||||
#define NVM_FEAT_LBA_RANGE_TYPE 0x03
|
||||
#define NVM_FEAT_TEMPERATURE_THRESHOLD 0x04
|
||||
#define NVM_FEAT_ERROR_RECOVERY 0x05
|
||||
#define NVM_FEATURE_VOLATILE_WRITE_CACHE 0x06 /* optional */
|
||||
#define NVM_FEATURE_NUMBER_OF_QUEUES 0x07 /* mandatory */
|
||||
#define NVM_FEAT_INTERRUPT_COALESCING 0x08
|
||||
#define NVM_FEAT_INTERRUPT_VECTOR_CONFIGURATION 0x09
|
||||
#define NVM_FEAT_WRITE_ATOMICITY 0x0a
|
||||
#define NVM_FEAT_ASYNC_EVENT_CONFIGURATION 0x0b
|
||||
#define NVM_FEAT_AUTONOMOUS_POWER_STATE_TRANSITION 0x0c
|
||||
#define NVM_FEAT_HOST_MEMORY_BUFFER 0x0d
|
||||
#define NVM_FEAT_TIMESTAMP 0x0e
|
||||
#define NVM_FEAT_KEEP_ALIVE_TIMER 0x0f
|
||||
#define NVM_FEAT_HOST_CONTROLLED_THERMAL_MGMT 0x10
|
||||
#define NVM_FEAT_NON_OP_POWER_STATE_CONFIG 0x11
|
||||
/* 0x12-0x77 - reserved */
|
||||
/* 0x78-0x7f - NVMe Management Interface */
|
||||
#define NVM_FEAT_SOFTWARE_PROGRESS_MARKER 0x80
|
||||
/* 0x81-0xBF - command set specific (reserved) */
|
||||
/* 0xC0-0xFF - vendor specific */
|
||||
|
||||
/* Power State Descriptor Data */
|
||||
struct nvm_identify_psd {
|
||||
@ -349,6 +384,7 @@ struct nvm_identify_psd {
|
||||
|
||||
uint8_t _reserved[8];
|
||||
} __packed __aligned(8);
|
||||
NVME_CTASSERT(sizeof(struct nvm_identify_psd) == 32, "bad size for nvm_identify_psd");
|
||||
|
||||
struct nvm_identify_controller {
|
||||
/* Controller Capabilities and Features */
|
||||
@ -366,9 +402,21 @@ struct nvm_identify_controller {
|
||||
uint8_t cmic; /* Controller Multi-Path I/O and
|
||||
Namespace Sharing Capabilities */
|
||||
uint8_t mdts; /* Maximum Data Transfer Size */
|
||||
uint16_t cntlid; /* Controller ID */
|
||||
|
||||
uint8_t _reserved1[176];
|
||||
uint16_t cntlid; /* Controller ID */
|
||||
uint32_t ver; /* Version */
|
||||
|
||||
uint32_t rtd3r; /* RTD3 Resume Latency */
|
||||
uint32_t rtd3e; /* RTD3 Enter Latency */
|
||||
|
||||
uint32_t oaes; /* Optional Asynchronous Events Supported */
|
||||
uint32_t ctrattr; /* Controller Attributes */
|
||||
|
||||
uint8_t _reserved1[12];
|
||||
|
||||
uint8_t fguid[16]; /* FRU Globally Unique Identifier */
|
||||
|
||||
uint8_t _reserved2[128];
|
||||
|
||||
/* Admin Command Set Attributes & Optional Controller Capabilities */
|
||||
|
||||
@ -395,7 +443,40 @@ struct nvm_identify_controller {
|
||||
uint8_t apsta; /* Autonomous Power State Transition
|
||||
Attributes */
|
||||
|
||||
uint8_t _reserved2[246];
|
||||
uint16_t wctemp; /* Warning Composite Temperature
|
||||
Threshold */
|
||||
uint16_t cctemp; /* Critical Composite Temperature
|
||||
Threshold */
|
||||
|
||||
uint16_t mtfa; /* Maximum Time for Firmware Activation */
|
||||
|
||||
uint32_t hmpre; /* Host Memory Buffer Preferred Size */
|
||||
uint32_t hmmin; /* Host Memory Buffer Minimum Size */
|
||||
|
||||
struct {
|
||||
uint64_t tnvmcap[2];
|
||||
uint64_t unvmcap[2];
|
||||
} __packed untncap; /* Name space capabilities:
|
||||
if NVME_ID_CTRLR_OACS_NS,
|
||||
report tnvmcap and unvmcap */
|
||||
|
||||
uint32_t rpmbs; /* Replay Protected Memory Block Support */
|
||||
|
||||
uint16_t edstt; /* Extended Device Self-test Time */
|
||||
uint8_t dsto; /* Device Self-test Options */
|
||||
|
||||
uint8_t fwug; /* Firmware Update Granularity */
|
||||
|
||||
uint16_t kas; /* Keep Alive Support */
|
||||
|
||||
uint16_t hctma; /* Host Controlled Thermal Management
|
||||
Attributes */
|
||||
uint16_t mntmt; /* Minimum Thermal Management Temperature */
|
||||
uint16_t mxtmt; /* Maximum Thermal Management Temperature */
|
||||
|
||||
uint32_t sanicap; /* Sanitize Capabilities */
|
||||
|
||||
uint8_t _reserved3[180];
|
||||
|
||||
/* NVM Command Set Attributes */
|
||||
|
||||
@ -405,7 +486,8 @@ struct nvm_identify_controller {
|
||||
uint8_t cqes; /* Completion Queue Entry Size */
|
||||
#define NVME_ID_CTRLR_CQES_MAX __BITS(4, 7)
|
||||
#define NVME_ID_CTRLR_CQES_MIN __BITS(0, 3)
|
||||
uint8_t _reserved3[2];
|
||||
|
||||
uint16_t maxcmd; /* Maximum Outstanding Commands */
|
||||
|
||||
uint32_t nn; /* Number of Namespaces */
|
||||
|
||||
@ -446,12 +528,14 @@ struct nvm_identify_controller {
|
||||
|
||||
uint8_t _reserved8[1024];
|
||||
} __packed __aligned(8);
|
||||
NVME_CTASSERT(sizeof(struct nvm_identify_controller) == 4096, "bad size for nvm_identify_controller");
|
||||
|
||||
struct nvm_namespace_format {
|
||||
uint16_t ms; /* Metadata Size */
|
||||
uint8_t lbads; /* LBA Data Size */
|
||||
uint8_t rp; /* Relative Performance */
|
||||
} __packed __aligned(4);
|
||||
NVME_CTASSERT(sizeof(struct nvm_namespace_format) == 4, "bad size for nvm_namespace_format");
|
||||
|
||||
struct nvm_identify_namespace {
|
||||
uint64_t nsze; /* Namespace Size */
|
||||
@ -482,5 +566,6 @@ struct nvm_identify_namespace {
|
||||
|
||||
uint8_t vs[3712];
|
||||
} __packed __aligned(8);
|
||||
NVME_CTASSERT(sizeof(struct nvm_identify_namespace) == 4096, "bad size for nvm_identify_namespace");
|
||||
|
||||
#endif /* __NVMEREG_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user