From: Jon Derrick Date: Tue, 12 May 2015 16:09:04 +0000 (-0600) Subject: Added a human-readable format option to id-ctrl and id-ns. This will X-Git-Tag: v0.1~43^2 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=239a39158019ea4637ea98892806cb4e537f5f1e;p=users%2Fsagi%2Fnvme-cli.git Added a human-readable format option to id-ctrl and id-ns. This will partially decode several relevant bitfields in the ID Controller and Namespace commands. Reserved fields are displayed if not 0. Signed-off-by: Jon Derrick --- diff --git a/Documentation/nvme-id-ctrl.1 b/Documentation/nvme-id-ctrl.1 index ac2151ba..1b4ff52e 100644 --- a/Documentation/nvme-id-ctrl.1 +++ b/Documentation/nvme-id-ctrl.1 @@ -1,13 +1,13 @@ '\" t .\" Title: nvme-id-ctrl .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] -.\" Generator: DocBook XSL Stylesheets v1.76.1 -.\" Date: 02/02/2015 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 05/11/2015 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "NVME\-ID\-CTRL" "1" "02/02/2015" "\ \&" "\ \&" +.TH "NVME\-ID\-CTRL" "1" "05/11/2015" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -45,13 +45,18 @@ On success, the structure may be returned in one of several ways depending on th .PP \-b, \-\-raw\-binary .RS 4 -Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific option\&. +Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific and human readable options\&. .RE .PP \-v, \-\-vendor\-specific .RS 4 In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation\&. .RE +.PP +\-H, \-\-human\-readable +.RS 4 +This option will parse and format many of the bitfields into human\-readable formats\&. +.RE .SH "EXAMPLES" .sp .RS 4 diff --git a/Documentation/nvme-id-ctrl.txt b/Documentation/nvme-id-ctrl.txt index ecde3e4f..89b5a768 100644 --- a/Documentation/nvme-id-ctrl.txt +++ b/Documentation/nvme-id-ctrl.txt @@ -27,7 +27,7 @@ OPTIONS -b:: --raw-binary:: Print the raw buffer to stdout. Structure is not parsed by - program. This overrides the vendor specific option. + program. This overrides the vendor specific and human readable options. -v:: --vendor-specific:: @@ -35,6 +35,12 @@ OPTIONS the vendor specific region of the structure in hex with ascii interpretation. +-H:: +--human-readable:: + This option will parse and format many of the bitfields + into human-readable formats. + + EXAMPLES -------- * Has the program interpret the returned buffer and display the known diff --git a/Documentation/nvme-id-ns.1 b/Documentation/nvme-id-ns.1 index f347024b..f9b6a4fb 100644 --- a/Documentation/nvme-id-ns.1 +++ b/Documentation/nvme-id-ns.1 @@ -1,13 +1,13 @@ '\" t .\" Title: nvme-id-ns .\" Author: [FIXME: author] [see http://docbook.sf.net/el/author] -.\" Generator: DocBook XSL Stylesheets v1.76.1 -.\" Date: 02/02/2015 +.\" Generator: DocBook XSL Stylesheets v1.78.1 +.\" Date: 05/11/2015 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "NVME\-ID\-NS" "1" "02/02/2015" "\ \&" "\ \&" +.TH "NVME\-ID\-NS" "1" "05/11/2015" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- @@ -51,13 +51,18 @@ Retrieve the identify namespace structure for the given nsid\&. This is required .PP \-b, \-\-raw\-binary .RS 4 -Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific option\&. +Print the raw buffer to stdout\&. Structure is not parsed by program\&. This overrides the vendor specific and human readable options\&. .RE .PP \-v, \-\-vendor\-specific .RS 4 In addition to parsing known fields, this option will dump the vendor specific region of the structure in hex with ascii interpretation\&. .RE +.PP +\-H, \-\-human\-readable +.RS 4 +This option will parse and format many of the bitfields into human\-readable formats\&. +.RE .SH "EXAMPLES" .sp .RS 4 diff --git a/Documentation/nvme-id-ns.txt b/Documentation/nvme-id-ns.txt index aa65d4c2..6d27ec26 100644 --- a/Documentation/nvme-id-ns.txt +++ b/Documentation/nvme-id-ns.txt @@ -38,7 +38,7 @@ OPTIONS -b:: --raw-binary:: Print the raw buffer to stdout. Structure is not parsed by - program. This overrides the vendor specific option. + program. This overrides the vendor specific and human readable options. -v:: --vendor-specific:: @@ -46,6 +46,12 @@ OPTIONS the vendor specific region of the structure in hex with ascii interpretation. +-H:: +--human-readable:: + This option will parse and format many of the bitfields + into human-readable formats. + + EXAMPLES -------- * Has the program interpret the returned buffer and display the known diff --git a/nvme.c b/nvme.c index cfedcd5c..c4bb3695 100644 --- a/nvme.c +++ b/nvme.c @@ -182,7 +182,7 @@ static void show_nvme_resv_report(struct nvme_reservation_status *status) regctl = status->regctl[0] | (status->regctl[1] << 8); - printf("\nNVME Reservatation status:\n\n"); + printf("\nNVME Reservation status:\n\n"); printf("gen : %d\n", le32toh(status->gen)); printf("regctl : %d\n", regctl); printf("rtype : %d\n", status->rtype); @@ -397,7 +397,244 @@ static void d(unsigned char *buf, int len, int width, int group) fprintf(stdout, "\n"); } -static void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, int vs) +static void show_nvme_id_ctrl_cmic(__u8 cmic) +{ + __u8 rsvd = (cmic & 0xF8) >> 3; + __u8 sriov = (cmic & 0x4) >> 2; + __u8 mctl = (cmic & 0x2) >> 1; + __u8 mp = cmic & 0x1; + if (rsvd) + printf(" [7:3] : %#x\tReserved\n", rsvd); + printf(" [2:2] : %#x\t%s\n", sriov, sriov ? "SR-IOV" : "PCI"); + printf(" [1:1] : %#x\t%s Controller\n", + mctl, mctl ? "Multi" : "Single"); + printf(" [0:0] : %#x\t%s Port\n", mp, mp ? "Multi" : "Single"); + printf("\n"); +} + +static void show_nvme_id_ctrl_oaes(__le32 oaes) +{ + __le32 rsvd0 = (oaes & 0xFFFFFE00) >> 9; + __le32 nace = (oaes & 0x100) >> 8; + __le32 rsvd1 = oaes & 0xFF; + if (rsvd0) + printf(" [31:9] : %#x\tReserved\n", rsvd0); + printf(" [8:8] : %#x\tNamespace Attribute Changed Event %sSupported\n", + nace, nace ? "" : "Not "); + if (rsvd1) + printf(" [7:0] : %#x\tReserved\n", rsvd1); + printf("\n"); +} + +static void show_nvme_id_ctrl_oacs(__le16 oacs) +{ + __le16 rsvd = (oacs & 0xFFF0) >> 4; + __le16 nsm = (oacs & 0x8) >> 3; + __le16 fwc = (oacs & 0x4) >> 2; + __le16 fmt = (oacs & 0x2) >> 1; + __le16 sec = oacs & 0x1; + if (rsvd) + printf(" [15:4] : %#x\tReserved\n", rsvd); + printf(" [3:3] : %#x\tNS Management and Attachment %sSupported\n", + nsm, nsm ? "" : "Not "); + printf(" [2:2] : %#x\tFW Commit and Download %sSupported\n", + fwc, fwc ? "" : "Not "); + printf(" [1:1] : %#x\tFormat NVM %sSupported\n", + fmt, fmt ? "" : "Not "); + printf(" [0:0] : %#x\tSec. Send and Receive %sSupported\n", + sec, sec ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ctrl_frmw(__u8 frmw) +{ + __u8 rsvd = (frmw & 0xE0) >> 5; + __u8 fawr = (frmw & 0x10) >> 4; + __u8 nfws = (frmw & 0xE) >> 1; + __u8 s1ro = frmw & 0x1; + if (rsvd) + printf(" [7:5] : %#x\tReserved\n", rsvd); + printf(" [4:4] : %#x\tFirmware Activate Without Reset %sSupported\n", + fawr, fawr ? "" : "Not "); + printf(" [3:1] : %#x\tNumber of Firmware Slots\n", nfws); + printf(" [0:0] : %#x\tFirmware Slot 1 Read%s\n", + s1ro, s1ro ? "-Only" : "/Write"); + printf("\n"); +} + +static void show_nvme_id_ctrl_lpa(__u8 lpa) +{ + __u8 rsvd = (lpa & 0xFC) >> 2; + __u8 celp = (lpa & 0x2) >> 1; + __u8 smlp = lpa & 0x1; + if (rsvd) + printf(" [7:2] : %#x\tReserved\n", rsvd); + printf(" [1:1] : %#x\tCommand Effects Log Page %sSupported\n", + celp, celp ? "" : "Not "); + printf(" [0:0] : %#x\tSMART/Health Log Page per NS %sSupported\n", + smlp, smlp ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ctrl_avscc(__u8 avscc) +{ + __u8 rsvd = (avscc & 0xFE) >> 1; + __u8 fmt = avscc & 0x1; + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tAdmin Vendor Specific Commands uses %s Format\n", + fmt, fmt ? "NVMe" : "Vendor Specific"); + printf("\n"); +} + +static void show_nvme_id_ctrl_apsta(__u8 apsta) +{ + __u8 rsvd = (apsta & 0xFE) >> 1; + __u8 apst = apsta & 0x1; + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tAutonomous Power State Transitions %sSupported\n", + apst, apst ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ctrl_rpmbs(__le32 rpmbs) +{ + __le32 asz = (rpmbs & 0xFF000000) >> 24; + __le32 tsz = (rpmbs & 0xFF0000) >> 16; + __le32 rsvd = (rpmbs & 0xFFC0) >> 6; + __le32 auth = (rpmbs & 0x38) >> 3; + __le32 rpmb = rpmbs & 0x3; + printf(" [31:24]: %#x\tAccess Size\n", asz); + printf(" [23:16]: %#x\tTotal Size\n", tsz); + if (rsvd) + printf(" [15:6] : %#x\tReserved\n", rsvd); + printf(" [5:3] : %#x\tAuthentication Method\n", auth); + printf(" [2:0] : %#x\tNumber of RPMB Units\n", rpmb); + printf("\n"); +} + +static void show_nvme_id_ctrl_sqes(__u8 sqes) +{ + __u8 msqes = (sqes & 0xF0) >> 4; + __u8 rsqes = sqes & 0xF; + printf(" [7:4] : %#x\tMax SQ Entry Size (%d)\n", msqes, 1 << msqes); + printf(" [3:0] : %#x\tMin SQ Entry Size (%d)\n", rsqes, 1 << rsqes); + printf("\n"); +} + +static void show_nvme_id_ctrl_cqes(__u8 cqes) +{ + __u8 mcqes = (cqes & 0xF0) >> 4; + __u8 rcqes = cqes & 0xF; + printf(" [7:4] : %#x\tMax CQ Entry Size (%d)\n", mcqes, 1 << mcqes); + printf(" [3:0] : %#x\tMin CQ Entry Size (%d)\n", rcqes, 1 << rcqes); + printf("\n"); +} + +static void show_nvme_id_ctrl_oncs(__le16 oncs) +{ + __le16 rsvd = (oncs & 0xFFC0) >> 6; + __le16 resv = (oncs & 0x20) >> 5; + __le16 save = (oncs & 0x10) >> 4; + __le16 wzro = (oncs & 0x8) >> 3; + __le16 dsms = (oncs & 0x4) >> 2; + __le16 wunc = (oncs & 0x2) >> 1; + __le16 cmp = oncs & 0x1; + if (rsvd) + printf(" [15:6] : %#x\tReserved\n", rsvd); + printf(" [5:5] : %#x\tReservations %sSupported\n", + resv, resv ? "" : "Not "); + printf(" [4:4] : %#x\tSave and Select %sSupported\n", + save, save ? "" : "Not "); + printf(" [3:3] : %#x\tWrite Zeroes %sSupported\n", + wzro, wzro ? "" : "Not "); + printf(" [2:2] : %#x\tData Set Management %sSupported\n", + dsms, dsms ? "" : "Not "); + printf(" [1:1] : %#x\tWrite Uncorrectable %sSupported\n", + wunc, wunc ? "" : "Not "); + printf(" [0:0] : %#x\tCompare %sSupported\n", + cmp, cmp ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ctrl_fuses(__le16 fuses) +{ + __le16 rsvd = (fuses & 0xFE) >> 1; + __le16 cmpw = fuses & 0x1; + if (rsvd) + printf(" [15:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tFused Compare and Write %sSupported\n", + cmpw, cmpw ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ctrl_fna(__u8 fna) +{ + __u8 rsvd = (fna & 0xF8) >> 3; + __u8 cese = (fna & 0x4) >> 2; + __u8 cens = (fna & 0x2) >> 1; + __u8 fmns = fna & 0x1; + if (rsvd) + printf(" [7:3] : %#x\tReserved\n", rsvd); + printf(" [2:2] : %#x\tCrypto Erase %sSupported as part of Secure Erase\n", + cese, cese ? "" : "Not "); + printf(" [1:1] : %#x\tCrypto Erase Applies to %s Namespace(s)\n", + cens, cens ? "All" : "Single"); + printf(" [0:0] : %#x\tFormat Applies to %s Namespace(s)\n", + fmns, fmns ? "All" : "Single"); + printf("\n"); +} + +static void show_nvme_id_ctrl_vwc(__u8 vwc) +{ + __u8 rsvd = (vwc & 0xFE) >> 1; + __u8 vwcp = vwc & 0x1; + if (rsvd) + printf(" [7:3] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tVolatile Write Cache %sPresent\n", + vwcp, vwcp ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ctrl_nvscc(__u8 nvscc) +{ + __u8 rsvd = (nvscc & 0xFE) >> 1; + __u8 fmt = nvscc & 0x1; + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tNVM Vendor Specific Commands uses %s Format\n", + fmt, fmt ? "NVMe" : "Vendor Specific"); + printf("\n"); +} + +static void show_nvme_id_ctrl_sgls(__le32 sgls) +{ + __le32 rsvd0 = (sgls & 0xFFF80000) >> 19; + __le32 sglltb = (sgls & 0x40000) >> 18; + __le32 bacmdb = (sgls & 0x20000) >> 17; + __le32 bbs = (sgls & 0x10000) >> 16; + __le32 rsvd1 = (sgls & 0xFFFE) >> 1; + __le32 sglsp = sgls & 0x1; + if (rsvd0) + printf(" [31:19]: %#x\tReserved\n", rsvd0); + if (sglsp || (!sglsp && sglltb)) + printf(" [18:18]: %#x\tSGL Length Larger than Buffer %sSupported\n", + sglltb, sglltb ? "" : "Not "); + if (sglsp || (!sglsp && bacmdb)) + printf(" [17:17]: %#x\tByte-Aligned Contig. MD Buffer %sSupported\n", + bacmdb, bacmdb ? "" : "Not "); + if (sglsp || (!sglsp && bbs)) + printf(" [16:16]: %#x\tSGL Bit-Bucket %sSupported\n", + bbs, bbs ? "" : "Not "); + if (rsvd1) + printf(" [15:1] : %#x\tReserved\n", rsvd1); + printf(" [0:0] : %#x\tScatter-Gather Lists %sSupported\n", + sglsp, sglsp ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, int vs, int human) { int i; char sn[sizeof(ctrl->sn) + 1]; @@ -422,20 +659,35 @@ static void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, int vs) printf("ieee : %02x%02x%02x\n", ctrl->ieee[0], ctrl->ieee[1], ctrl->ieee[2]); printf("cmic : %#x\n", ctrl->cmic); + if (human) + show_nvme_id_ctrl_cmic(ctrl->cmic); printf("mdts : %d\n", ctrl->mdts); printf("cntlid : %x\n", ctrl->cntlid); printf("ver : %x\n", ctrl->ver); printf("rtd3r : %x\n", ctrl->rtd3r); printf("rtd3e : %x\n", ctrl->rtd3e); + printf("oaes : %#x\n", ctrl->oaes); + if (human) + show_nvme_id_ctrl_oaes(ctrl->oaes); printf("oacs : %#x\n", ctrl->oacs); + if (human) + show_nvme_id_ctrl_oacs(ctrl->oacs); printf("acl : %d\n", ctrl->acl); printf("aerl : %d\n", ctrl->aerl); printf("frmw : %#x\n", ctrl->frmw); + if (human) + show_nvme_id_ctrl_frmw(ctrl->frmw); printf("lpa : %#x\n", ctrl->lpa); + if (human) + show_nvme_id_ctrl_lpa(ctrl->lpa); printf("elpe : %d\n", ctrl->elpe); printf("npss : %d\n", ctrl->npss); printf("avscc : %#x\n", ctrl->avscc); + if (human) + show_nvme_id_ctrl_avscc(ctrl->avscc); printf("apsta : %#x\n", ctrl->apsta); + if (human) + show_nvme_id_ctrl_apsta(ctrl->apsta); printf("wctemp : %d\n", ctrl->wctemp); printf("cctemp : %d\n", ctrl->cctemp); printf("mtfa : %d\n", ctrl->mtfa); @@ -443,18 +695,36 @@ static void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, int vs) printf("tnvmcap : %.0Lf\n", int128_to_double(ctrl->tnvmcap)); printf("unvmcap : %.0Lf\n", int128_to_double(ctrl->unvmcap)); printf("rpmbs : %#x\n", ctrl->rpmbs); + if (human) + show_nvme_id_ctrl_rpmbs(ctrl->rpmbs); printf("sqes : %#x\n", ctrl->sqes); + if (human) + show_nvme_id_ctrl_sqes(ctrl->sqes); printf("cqes : %#x\n", ctrl->cqes); + if (human) + show_nvme_id_ctrl_cqes(ctrl->cqes); printf("nn : %d\n", ctrl->nn); printf("oncs : %#x\n", ctrl->oncs); + if (human) + show_nvme_id_ctrl_oncs(ctrl->oncs); printf("fuses : %#x\n", ctrl->fuses); + if (human) + show_nvme_id_ctrl_fuses(ctrl->fuses); printf("fna : %#x\n", ctrl->fna); + if (human) + show_nvme_id_ctrl_fna(ctrl->fna); printf("vwc : %#x\n", ctrl->vwc); + if (human) + show_nvme_id_ctrl_vwc(ctrl->vwc); printf("awun : %d\n", ctrl->awun); printf("awupf : %d\n", ctrl->awupf); printf("nvscc : %d\n", ctrl->nvscc); + if (human) + show_nvme_id_ctrl_nvscc(ctrl->nvscc); printf("acwu : %d\n", ctrl->acwu); printf("sgls : %d\n", ctrl->sgls); + if (human) + show_nvme_id_ctrl_sgls(ctrl->sgls); for (i = 0; i <= ctrl->npss; i++) { printf("ps %4d : mp:%d flags:%x enlat:%d exlat:%d rrt:%d rrl:%d\n" @@ -472,6 +742,7 @@ static void show_nvme_id_ctrl(struct nvme_id_ctrl *ctrl, int vs) } } + static void show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges) { int i, j; @@ -488,7 +759,143 @@ static void show_lba_range(struct nvme_lba_range_type *lbrt, int nr_ranges) } } -static void show_nvme_id_ns(struct nvme_id_ns *ns, int id, int vs) +static void show_nvme_id_ns_nsfeat(__u8 nsfeat) +{ + __u8 rsvd = (nsfeat & 0xF8) >> 3; + __u8 dulbe = (nsfeat & 0x4) >> 2; + __u8 na = (nsfeat & 0x2) >> 1; + __u8 thin = nsfeat & 0x1; + if (rsvd) + printf(" [7:3] : %#x\tReserved\n", rsvd); + printf(" [2:2] : %#x\tDeallocated or Unwritten Logical Block error %sSupported\n", + dulbe, dulbe ? "" : "Not "); + printf(" [1:1] : %#x\tNamespace uses %s\n", + na, na ? "NAWUN, NAWUPF, and NACWU" : "AWUN, AWUPF, and ACWU"); + printf(" [0:0] : %#x\tThin Provisioning %sSupported\n", + thin, thin ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ns_flbas(__u8 flbas) +{ + __u8 rsvd = (flbas & 0xE0) >> 5; + __u8 mdedata = (flbas & 0x10) >> 4; + __u8 lbaf = flbas & 0xF; + if (rsvd) + printf(" [7:5] : %#x\tReserved\n", rsvd); + printf(" [4:4] : %#x\tMetadata Transferred %s\n", + mdedata, mdedata ? "at End of Data LBA" : "in Separate Contiguous Buffer"); + printf(" [3:0] : %#x\tCurrent LBA Format Selected\n", lbaf); + printf("\n"); +} + +static void show_nvme_id_ns_mc(__u8 mc) +{ + __u8 rsvd = (mc & 0xFC) >> 2; + __u8 mdp = (mc & 0x2) >> 1; + __u8 extdlba = mc & 0x1; + if (rsvd) + printf(" [7:2] : %#x\tReserved\n", rsvd); + printf(" [1:1] : %#x\tMetadata Pointer %sSupported\n", + mdp, mdp ? "" : "Not "); + printf(" [0:0] : %#x\tMetadata as Part of Extended Data LBA %sSupported\n", + extdlba, extdlba ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ns_dpc(__u8 dpc) +{ + __u8 rsvd = (dpc & 0xE0) >> 5; + __u8 pil8 = (dpc & 0x10) >> 4; + __u8 pif8 = (dpc & 0x8) >> 3; + __u8 pit3 = (dpc & 0x4) >> 2; + __u8 pit2 = (dpc & 0x2) >> 1; + __u8 pit1 = dpc & 0x1; + if (rsvd) + printf(" [7:5] : %#x\tReserved\n", rsvd); + printf(" [4:4] : %#x\tProtection Information Transferred as Last 8 Bytes of Metadata %sSupported\n", + pil8, pil8 ? "" : "Not "); + printf(" [3:3] : %#x\tProtection Information Transferred as First 8 Bytes of Metadata %sSupported\n", + pif8, pif8 ? "" : "Not "); + printf(" [2:2] : %#x\tProtection Information Type 3 %sSupported\n", + pit3, pit3 ? "" : "Not "); + printf(" [1:1] : %#x\tProtection Information Type 2 %sSupported\n", + pit2, pit2 ? "" : "Not "); + printf(" [0:0] : %#x\tProtection Information Type 1 %sSupported\n", + pit1, pit1 ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ns_dps(__u8 dps) +{ + __u8 rsvd = (dps & 0xF0) >> 4; + __u8 pif8 = (dps & 0x8) >> 3; + __u8 pit = dps & 0x7; + if (rsvd) + printf(" [7:4] : %#x\tReserved\n", rsvd); + printf(" [3:3] : %#x\tProtection Information is Transferred as %s 8 Bytes of Metadata\n", + pif8, pif8 ? "First" : "Last"); + printf(" [2:0] : %#x\tProtection Information %s\n", pit, + pit == 3 ? "Type 3 Enabled" : + pit == 2 ? "Type 2 Enabled" : + pit == 1 ? "Type 1 Enabled" : + pit == 0 ? "Disabled" : "Reserved Enabled"); + printf("\n"); +} + +static void show_nvme_id_ns_nmic(__u8 nmic) +{ + __u8 rsvd = (nmic & 0xFE) >> 1; + __u8 mp = nmic & 0x1; + if (rsvd) + printf(" [7:1] : %#x\tReserved\n", rsvd); + printf(" [0:0] : %#x\tNamespace Multipath %sCapable\n", + mp, mp ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ns_rescap(__u8 rescap) +{ + __u8 rsvd = (rescap & 0x80) >> 7; + __u8 eaar = (rescap & 0x40) >> 6; + __u8 wear = (rescap & 0x20) >> 5; + __u8 earo = (rescap & 0x10) >> 4; + __u8 wero = (rescap & 0x8) >> 3; + __u8 ea = (rescap & 0x4) >> 2; + __u8 we = (rescap & 0x2) >> 1; + __u8 ptpl = rescap & 0x1; + if (rsvd) + printf(" [7:7] : %#x\tReserved\n", rsvd); + printf(" [6:6] : %#x\tExclusive Access - All Registrants %sSupported\n", + eaar, eaar ? "" : "Not "); + printf(" [5:5] : %#x\tWrite Exclusive - All Registrants %sSupported\n", + wear, wear ? "" : "Not "); + printf(" [4:4] : %#x\tExclusive Access - Registrants Only %sSupported\n", + earo, earo ? "" : "Not "); + printf(" [3:3] : %#x\tWrite Exclusive - Registrants Only %sSupported\n", + wero, wero ? "" : "Not "); + printf(" [2:2] : %#x\tExclusive Access %sSupported\n", + ea, ea ? "" : "Not "); + printf(" [1:1] : %#x\tWrite Exclusive %sSupported\n", + we, we ? "" : "Not "); + printf(" [0:0] : %#x\tPersist Through Power Loss %sSupported\n", + ptpl, ptpl ? "" : "Not "); + printf("\n"); +} + +static void show_nvme_id_ns_fpi(__u8 fpi) +{ + __u8 fpis = (fpi & 0x80) >> 7; + __u8 fpii = fpi & 0x7F; + printf(" [7:7] : %#x\tFormat Progress Indicator %sSupported\n", + fpis, fpis ? "" : "Not "); + if (fpis || (!fpis && fpii)) + printf(" [6:0] : %#x\tFormat Progress Indicator (Remaining %d%%)\n", + fpii, 100 - fpii); + printf("\n"); +} + +static void show_nvme_id_ns(struct nvme_id_ns *ns, int id, int vs, int human) { int i; @@ -497,14 +904,30 @@ static void show_nvme_id_ns(struct nvme_id_ns *ns, int id, int vs) printf("ncap : %#llx\n", ns->ncap); printf("nuse : %#llx\n", ns->nuse); printf("nsfeat : %#x\n", ns->nsfeat); + if (human) + show_nvme_id_ns_nsfeat(ns->nsfeat); printf("nlbaf : %d\n", ns->nlbaf); printf("flbas : %#x\n", ns->flbas); + if (human) + show_nvme_id_ns_flbas(ns->flbas); printf("mc : %#x\n", ns->mc); + if (human) + show_nvme_id_ns_mc(ns->mc); printf("dpc : %#x\n", ns->dpc); + if (human) + show_nvme_id_ns_dpc(ns->dpc); printf("dps : %#x\n", ns->dps); + if (human) + show_nvme_id_ns_dps(ns->dps); printf("nmic : %#x\n", ns->nmic); + if (human) + show_nvme_id_ns_nmic(ns->nmic); printf("rescap : %#x\n", ns->rescap); + if (human) + show_nvme_id_ns_rescap(ns->rescap); printf("fpi : %#x\n", ns->fpi); + if (human) + show_nvme_id_ns_fpi(ns->fpi); printf("nawun : %d\n", ns->nawun); printf("nawupf : %d\n", ns->nawupf); printf("nacwu : %d\n", ns->nacwu); @@ -524,9 +947,18 @@ static void show_nvme_id_ns(struct nvme_id_ns *ns, int id, int vs) printf("\n"); for (i = 0; i <= ns->nlbaf; i++) { - printf("lbaf %2d : ms:%-3d ds:%-2d rp:%#x %s\n", i, - ns->lbaf[i].ms, ns->lbaf[i].ds, ns->lbaf[i].rp, - i == (ns->flbas & 0xf) ? "(in use)" : ""); + if (human) + printf("LBA Format %2d : Metadata Size: %-3d bytes - " + "Data Size: %-2d bytes - Relative Performance: %#x %s %s\n", i, + ns->lbaf[i].ms, 1 << ns->lbaf[i].ds, ns->lbaf[i].rp, + ns->lbaf[i].rp == 3 ? "Degraded" : + ns->lbaf[i].rp == 2 ? "Good" : + ns->lbaf[i].rp == 1 ? "Better" : "Best", + i == (ns->flbas & 0xf) ? "(in use)" : ""); + else + printf("lbaf %2d : ms:%-3d ds:%-2d rp:%#x %s\n", i, + ns->lbaf[i].ms, ns->lbaf[i].ds, ns->lbaf[i].rp, + i == (ns->flbas & 0xf) ? "(in use)" : ""); } if (vs) { printf("vs[]:"); @@ -934,6 +1366,7 @@ static int id_ctrl(int argc, char **argv) struct config { __u8 vendor_specific; __u8 raw_binary; + __u8 human_readable; }; struct config cfg; @@ -945,6 +1378,8 @@ static int id_ctrl(int argc, char **argv) {"v", "", CFG_NONE, &defaults.vendor_specific, no_argument, NULL}, {"raw-binary", "", CFG_NONE, &defaults.raw_binary, no_argument, NULL}, {"b", "", CFG_NONE, &defaults.raw_binary, no_argument, NULL}, + {"human-readable", "", CFG_NONE, &defaults.human_readable, no_argument, NULL}, + {"H", "", CFG_NONE, &defaults.human_readable, no_argument, NULL}, {0} }; argconfig_parse(argc, argv, "id_ctrl", command_line_options, @@ -956,7 +1391,7 @@ static int id_ctrl(int argc, char **argv) if (cfg.raw_binary) d_raw((unsigned char *)&ctrl, sizeof(ctrl)); else - show_nvme_id_ctrl(&ctrl, cfg.vendor_specific); + show_nvme_id_ctrl(&ctrl, cfg.vendor_specific, cfg.human_readable); } else if (err > 0) fprintf(stderr, "NVMe Status: %s\n", nvme_status_to_string(err)); @@ -973,6 +1408,7 @@ static int id_ns(int argc, char **argv) __u32 namespace_id; __u8 vendor_specific; __u8 raw_binary; + __u8 human_readable; }; struct config cfg; @@ -987,6 +1423,8 @@ static int id_ns(int argc, char **argv) {"v", "", CFG_NONE, &defaults.vendor_specific, no_argument, NULL}, {"raw-binary", "", CFG_NONE, &defaults.raw_binary, no_argument, NULL}, {"b", "", CFG_NONE, &defaults.raw_binary, no_argument, NULL}, + {"human-readable", "", CFG_NONE, &defaults.human_readable, no_argument, NULL}, + {"H", "", CFG_NONE, &defaults.human_readable, no_argument, NULL}, {0} }; argconfig_parse(argc, argv, "id_ns", command_line_options, @@ -1011,7 +1449,7 @@ static int id_ns(int argc, char **argv) if (cfg.raw_binary) d_raw((unsigned char *)&ns, sizeof(ns)); else - show_nvme_id_ns(&ns, cfg.namespace_id, cfg.vendor_specific); + show_nvme_id_ns(&ns, cfg.namespace_id, cfg.vendor_specific, cfg.human_readable); } else if (err > 0) fprintf(stderr, "NVMe Status: %s NSID:%d\n", nvme_status_to_string(err), @@ -2246,7 +2684,7 @@ static int nvme_passthru(int argc, char **argv, int ioctl_cmd) }; memset(&cmd, 0, sizeof(cmd)); - argconfig_parse(argc, argv, "nvme_passthrou", command_line_options, + argconfig_parse(argc, argv, "nvme_passthru", command_line_options, &defaults, &cfg, sizeof(cfg)); cmd.cdw2 = cfg.cdw2;