]> www.infradead.org Git - users/hch/nvme-cli.git/commitdiff
Add toshiba plugin code and command documentation.
authorAndrew Meir <andrew.meir@taec.toshiba.com>
Wed, 28 Mar 2018 15:42:53 +0000 (17:42 +0200)
committerAndrew Meir <andrew.meir@taec.toshiba.com>
Wed, 28 Mar 2018 15:42:53 +0000 (17:42 +0200)
Documentation/nvme-toshiba-clear-pcie-correctable-errors.1 [new file with mode: 0644]
Documentation/nvme-toshiba-clear-pcie-correctable-errors.html [new file with mode: 0644]
Documentation/nvme-toshiba-clear-pcie-correctable-errors.txt [new file with mode: 0644]
Documentation/nvme-toshiba-vs-internal-log.1 [new file with mode: 0644]
Documentation/nvme-toshiba-vs-internal-log.html [new file with mode: 0644]
Documentation/nvme-toshiba-vs-internal-log.txt [new file with mode: 0644]
Documentation/nvme-toshiba-vs-smart-add-log.1 [new file with mode: 0644]
Documentation/nvme-toshiba-vs-smart-add-log.html [new file with mode: 0644]
Documentation/nvme-toshiba-vs-smart-add-log.txt [new file with mode: 0644]
toshiba-nvme.c [new file with mode: 0644]
toshiba-nvme.h [new file with mode: 0644]

diff --git a/Documentation/nvme-toshiba-clear-pcie-correctable-errors.1 b/Documentation/nvme-toshiba-clear-pcie-correctable-errors.1
new file mode 100644 (file)
index 0000000..dbe4f4e
--- /dev/null
@@ -0,0 +1,66 @@
+'\" t
+.\"     Title: nvme-toshiba-clear-pcie-correctable-errors
+.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/07/2018
+.\"    Manual: NVMe Manual
+.\"    Source: NVMe
+.\"  Language: English
+.\"
+.TH "NVME\-TOSHIBA\-CLEAR" "1" "03/07/2018" "NVMe" "NVMe Manual"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+nvme-toshiba-clear-pcie-correctable-errors \- Reset the PCIe correctable errors count to zero\&.
+.SH "SYNOPSIS"
+.sp
+.nf
+\*(Aqnvme toshiba clear\-pcie\-correctable\-errors \*(Aq <device>
+.fi
+.SH "DESCRIPTION"
+.sp
+For the NVMe device given, sends the Toshiba clear PCIe correctable errors request\&.
+.sp
+The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&.
+.SH "EXAMPLES"
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Clear the PCIe correctable errors count:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme toshiba clear\-pcie\-correctable\-errors /dev/nvme0
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.SH "NVME"
+.sp
+Part of the nvme\-user suite
diff --git a/Documentation/nvme-toshiba-clear-pcie-correctable-errors.html b/Documentation/nvme-toshiba-clear-pcie-correctable-errors.html
new file mode 100644 (file)
index 0000000..0609f15
--- /dev/null
@@ -0,0 +1,797 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.9" />\r
+<title>nvme-toshiba-clear-pcie-correctable-errors(1)</title>\r
+<style type="text/css">\r
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */\r
+\r
+/* Default font. */\r
+body {\r
+  font-family: Georgia,serif;\r
+}\r
+\r
+/* Title font. */\r
+h1, h2, h3, h4, h5, h6,\r
+div.title, caption.title,\r
+thead, p.table.header,\r
+#toctitle,\r
+#author, #revnumber, #revdate, #revremark,\r
+#footer {\r
+  font-family: Arial,Helvetica,sans-serif;\r
+}\r
+\r
+body {\r
+  margin: 1em 5% 1em 5%;\r
+}\r
+\r
+a {\r
+  color: blue;\r
+  text-decoration: underline;\r
+}\r
+a:visited {\r
+  color: fuchsia;\r
+}\r
+\r
+em {\r
+  font-style: italic;\r
+  color: navy;\r
+}\r
+\r
+strong {\r
+  font-weight: bold;\r
+  color: #083194;\r
+}\r
+\r
+h1, h2, h3, h4, h5, h6 {\r
+  color: #527bbd;\r
+  margin-top: 1.2em;\r
+  margin-bottom: 0.5em;\r
+  line-height: 1.3;\r
+}\r
+\r
+h1, h2, h3 {\r
+  border-bottom: 2px solid silver;\r
+}\r
+h2 {\r
+  padding-top: 0.5em;\r
+}\r
+h3 {\r
+  float: left;\r
+}\r
+h3 + * {\r
+  clear: left;\r
+}\r
+h5 {\r
+  font-size: 1.0em;\r
+}\r
+\r
+div.sectionbody {\r
+  margin-left: 0;\r
+}\r
+\r
+hr {\r
+  border: 1px solid silver;\r
+}\r
+\r
+p {\r
+  margin-top: 0.5em;\r
+  margin-bottom: 0.5em;\r
+}\r
+\r
+ul, ol, li > p {\r
+  margin-top: 0;\r
+}\r
+ul > li     { color: #aaa; }\r
+ul > li > * { color: black; }\r
+\r
+.monospaced, code, pre {\r
+  font-family: "Courier New", Courier, monospace;\r
+  font-size: inherit;\r
+  color: navy;\r
+  padding: 0;\r
+  margin: 0;\r
+}\r
+pre {\r
+  white-space: pre-wrap;\r
+}\r
+\r
+#author {\r
+  color: #527bbd;\r
+  font-weight: bold;\r
+  font-size: 1.1em;\r
+}\r
+#email {\r
+}\r
+#revnumber, #revdate, #revremark {\r
+}\r
+\r
+#footer {\r
+  font-size: small;\r
+  border-top: 2px solid silver;\r
+  padding-top: 0.5em;\r
+  margin-top: 4.0em;\r
+}\r
+#footer-text {\r
+  float: left;\r
+  padding-bottom: 0.5em;\r
+}\r
+#footer-badges {\r
+  float: right;\r
+  padding-bottom: 0.5em;\r
+}\r
+\r
+#preamble {\r
+  margin-top: 1.5em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.imageblock, div.exampleblock, div.verseblock,\r
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,\r
+div.admonitionblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.admonitionblock {\r
+  margin-top: 2.0em;\r
+  margin-bottom: 2.0em;\r
+  margin-right: 10%;\r
+  color: #606060;\r
+}\r
+\r
+div.content { /* Block element content. */\r
+  padding: 0;\r
+}\r
+\r
+/* Block element titles. */\r
+div.title, caption.title {\r
+  color: #527bbd;\r
+  font-weight: bold;\r
+  text-align: left;\r
+  margin-top: 1.0em;\r
+  margin-bottom: 0.5em;\r
+}\r
+div.title + * {\r
+  margin-top: 0;\r
+}\r
+\r
+td div.title:first-child {\r
+  margin-top: 0.0em;\r
+}\r
+div.content div.title:first-child {\r
+  margin-top: 0.0em;\r
+}\r
+div.content + div.title {\r
+  margin-top: 0.0em;\r
+}\r
+\r
+div.sidebarblock > div.content {\r
+  background: #ffffee;\r
+  border: 1px solid #dddddd;\r
+  border-left: 4px solid #f0f0f0;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.listingblock > div.content {\r
+  border: 1px solid #dddddd;\r
+  border-left: 5px solid #f0f0f0;\r
+  background: #f8f8f8;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.quoteblock, div.verseblock {\r
+  padding-left: 1.0em;\r
+  margin-left: 1.0em;\r
+  margin-right: 10%;\r
+  border-left: 5px solid #f0f0f0;\r
+  color: #888;\r
+}\r
+\r
+div.quoteblock > div.attribution {\r
+  padding-top: 0.5em;\r
+  text-align: right;\r
+}\r
+\r
+div.verseblock > pre.content {\r
+  font-family: inherit;\r
+  font-size: inherit;\r
+}\r
+div.verseblock > div.attribution {\r
+  padding-top: 0.75em;\r
+  text-align: left;\r
+}\r
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */\r
+div.verseblock + div.attribution {\r
+  text-align: left;\r
+}\r
+\r
+div.admonitionblock .icon {\r
+  vertical-align: top;\r
+  font-size: 1.1em;\r
+  font-weight: bold;\r
+  text-decoration: underline;\r
+  color: #527bbd;\r
+  padding-right: 0.5em;\r
+}\r
+div.admonitionblock td.content {\r
+  padding-left: 0.5em;\r
+  border-left: 3px solid #dddddd;\r
+}\r
+\r
+div.exampleblock > div.content {\r
+  border-left: 3px solid #dddddd;\r
+  padding-left: 0.5em;\r
+}\r
+\r
+div.imageblock div.content { padding-left: 0; }\r
+span.image img { border-style: none; vertical-align: text-bottom; }\r
+a.image:visited { color: white; }\r
+\r
+dl {\r
+  margin-top: 0.8em;\r
+  margin-bottom: 0.8em;\r
+}\r
+dt {\r
+  margin-top: 0.5em;\r
+  margin-bottom: 0;\r
+  font-style: normal;\r
+  color: navy;\r
+}\r
+dd > *:first-child {\r
+  margin-top: 0.1em;\r
+}\r
+\r
+ul, ol {\r
+    list-style-position: outside;\r
+}\r
+ol.arabic {\r
+  list-style-type: decimal;\r
+}\r
+ol.loweralpha {\r
+  list-style-type: lower-alpha;\r
+}\r
+ol.upperalpha {\r
+  list-style-type: upper-alpha;\r
+}\r
+ol.lowerroman {\r
+  list-style-type: lower-roman;\r
+}\r
+ol.upperroman {\r
+  list-style-type: upper-roman;\r
+}\r
+\r
+div.compact ul, div.compact ol,\r
+div.compact p, div.compact p,\r
+div.compact div, div.compact div {\r
+  margin-top: 0.1em;\r
+  margin-bottom: 0.1em;\r
+}\r
+\r
+tfoot {\r
+  font-weight: bold;\r
+}\r
+td > div.verse {\r
+  white-space: pre;\r
+}\r
+\r
+div.hdlist {\r
+  margin-top: 0.8em;\r
+  margin-bottom: 0.8em;\r
+}\r
+div.hdlist tr {\r
+  padding-bottom: 15px;\r
+}\r
+dt.hdlist1.strong, td.hdlist1.strong {\r
+  font-weight: bold;\r
+}\r
+td.hdlist1 {\r
+  vertical-align: top;\r
+  font-style: normal;\r
+  padding-right: 0.8em;\r
+  color: navy;\r
+}\r
+td.hdlist2 {\r
+  vertical-align: top;\r
+}\r
+div.hdlist.compact tr {\r
+  margin: 0;\r
+  padding-bottom: 0;\r
+}\r
+\r
+.comment {\r
+  background: yellow;\r
+}\r
+\r
+.footnote, .footnoteref {\r
+  font-size: 0.8em;\r
+}\r
+\r
+span.footnote, span.footnoteref {\r
+  vertical-align: super;\r
+}\r
+\r
+#footnotes {\r
+  margin: 20px 0 20px 0;\r
+  padding: 7px 0 0 0;\r
+}\r
+\r
+#footnotes div.footnote {\r
+  margin: 0 0 5px 0;\r
+}\r
+\r
+#footnotes hr {\r
+  border: none;\r
+  border-top: 1px solid silver;\r
+  height: 1px;\r
+  text-align: left;\r
+  margin-left: 0;\r
+  width: 20%;\r
+  min-width: 100px;\r
+}\r
+\r
+div.colist td {\r
+  padding-right: 0.5em;\r
+  padding-bottom: 0.3em;\r
+  vertical-align: top;\r
+}\r
+div.colist td img {\r
+  margin-top: 0.3em;\r
+}\r
+\r
+@media print {\r
+  #footer-badges { display: none; }\r
+}\r
+\r
+#toc {\r
+  margin-bottom: 2.5em;\r
+}\r
+\r
+#toctitle {\r
+  color: #527bbd;\r
+  font-size: 1.1em;\r
+  font-weight: bold;\r
+  margin-top: 1.0em;\r
+  margin-bottom: 0.1em;\r
+}\r
+\r
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {\r
+  margin-top: 0;\r
+  margin-bottom: 0;\r
+}\r
+div.toclevel2 {\r
+  margin-left: 2em;\r
+  font-size: 0.9em;\r
+}\r
+div.toclevel3 {\r
+  margin-left: 4em;\r
+  font-size: 0.9em;\r
+}\r
+div.toclevel4 {\r
+  margin-left: 6em;\r
+  font-size: 0.9em;\r
+}\r
+\r
+span.aqua { color: aqua; }\r
+span.black { color: black; }\r
+span.blue { color: blue; }\r
+span.fuchsia { color: fuchsia; }\r
+span.gray { color: gray; }\r
+span.green { color: green; }\r
+span.lime { color: lime; }\r
+span.maroon { color: maroon; }\r
+span.navy { color: navy; }\r
+span.olive { color: olive; }\r
+span.purple { color: purple; }\r
+span.red { color: red; }\r
+span.silver { color: silver; }\r
+span.teal { color: teal; }\r
+span.white { color: white; }\r
+span.yellow { color: yellow; }\r
+\r
+span.aqua-background { background: aqua; }\r
+span.black-background { background: black; }\r
+span.blue-background { background: blue; }\r
+span.fuchsia-background { background: fuchsia; }\r
+span.gray-background { background: gray; }\r
+span.green-background { background: green; }\r
+span.lime-background { background: lime; }\r
+span.maroon-background { background: maroon; }\r
+span.navy-background { background: navy; }\r
+span.olive-background { background: olive; }\r
+span.purple-background { background: purple; }\r
+span.red-background { background: red; }\r
+span.silver-background { background: silver; }\r
+span.teal-background { background: teal; }\r
+span.white-background { background: white; }\r
+span.yellow-background { background: yellow; }\r
+\r
+span.big { font-size: 2em; }\r
+span.small { font-size: 0.6em; }\r
+\r
+span.underline { text-decoration: underline; }\r
+span.overline { text-decoration: overline; }\r
+span.line-through { text-decoration: line-through; }\r
+\r
+div.unbreakable { page-break-inside: avoid; }\r
+\r
+\r
+/*\r
+ * xhtml11 specific\r
+ *\r
+ * */\r
+\r
+div.tableblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.tableblock > table {\r
+  border: 3px solid #527bbd;\r
+}\r
+thead, p.table.header {\r
+  font-weight: bold;\r
+  color: #527bbd;\r
+}\r
+p.table {\r
+  margin-top: 0;\r
+}\r
+/* Because the table frame attribute is overriden by CSS in most browsers. */\r
+div.tableblock > table[frame="void"] {\r
+  border-style: none;\r
+}\r
+div.tableblock > table[frame="hsides"] {\r
+  border-left-style: none;\r
+  border-right-style: none;\r
+}\r
+div.tableblock > table[frame="vsides"] {\r
+  border-top-style: none;\r
+  border-bottom-style: none;\r
+}\r
+\r
+\r
+/*\r
+ * html5 specific\r
+ *\r
+ * */\r
+\r
+table.tableblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+thead, p.tableblock.header {\r
+  font-weight: bold;\r
+  color: #527bbd;\r
+}\r
+p.tableblock {\r
+  margin-top: 0;\r
+}\r
+table.tableblock {\r
+  border-width: 3px;\r
+  border-spacing: 0px;\r
+  border-style: solid;\r
+  border-color: #527bbd;\r
+  border-collapse: collapse;\r
+}\r
+th.tableblock, td.tableblock {\r
+  border-width: 1px;\r
+  padding: 4px;\r
+  border-style: solid;\r
+  border-color: #527bbd;\r
+}\r
+\r
+table.tableblock.frame-topbot {\r
+  border-left-style: hidden;\r
+  border-right-style: hidden;\r
+}\r
+table.tableblock.frame-sides {\r
+  border-top-style: hidden;\r
+  border-bottom-style: hidden;\r
+}\r
+table.tableblock.frame-none {\r
+  border-style: hidden;\r
+}\r
+\r
+th.tableblock.halign-left, td.tableblock.halign-left {\r
+  text-align: left;\r
+}\r
+th.tableblock.halign-center, td.tableblock.halign-center {\r
+  text-align: center;\r
+}\r
+th.tableblock.halign-right, td.tableblock.halign-right {\r
+  text-align: right;\r
+}\r
+\r
+th.tableblock.valign-top, td.tableblock.valign-top {\r
+  vertical-align: top;\r
+}\r
+th.tableblock.valign-middle, td.tableblock.valign-middle {\r
+  vertical-align: middle;\r
+}\r
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {\r
+  vertical-align: bottom;\r
+}\r
+\r
+\r
+/*\r
+ * manpage specific\r
+ *\r
+ * */\r
+\r
+body.manpage h1 {\r
+  padding-top: 0.5em;\r
+  padding-bottom: 0.5em;\r
+  border-top: 2px solid silver;\r
+  border-bottom: 2px solid silver;\r
+}\r
+body.manpage h2 {\r
+  border-style: none;\r
+}\r
+body.manpage div.sectionbody {\r
+  margin-left: 3em;\r
+}\r
+\r
+@media print {\r
+  body.manpage div#toc { display: none; }\r
+}\r
+\r
+\r
+</style>\r
+<script type="text/javascript">\r
+/*<![CDATA[*/\r
+var asciidoc = {  // Namespace.\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+// Table Of Contents generator\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+/* Author: Mihai Bazon, September 2002\r
+ * http://students.infoiasi.ro/~mishoo\r
+ *\r
+ * Table Of Content generator\r
+ * Version: 0.4\r
+ *\r
+ * Feel free to use this script under the terms of the GNU General Public\r
+ * License, as long as you do not remove or alter this notice.\r
+ */\r
+\r
+ /* modified by Troy D. Hanson, September 2006. License: GPL */\r
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */\r
+\r
+// toclevels = 1..4.\r
+toc: function (toclevels) {\r
+\r
+  function getText(el) {\r
+    var text = "";\r
+    for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.\r
+        text += i.data;\r
+      else if (i.firstChild != null)\r
+        text += getText(i);\r
+    }\r
+    return text;\r
+  }\r
+\r
+  function TocEntry(el, text, toclevel) {\r
+    this.element = el;\r
+    this.text = text;\r
+    this.toclevel = toclevel;\r
+  }\r
+\r
+  function tocEntries(el, toclevels) {\r
+    var result = new Array;\r
+    var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');\r
+    // Function that scans the DOM tree for header elements (the DOM2\r
+    // nodeIterator API would be a better technique but not supported by all\r
+    // browsers).\r
+    var iterate = function (el) {\r
+      for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {\r
+          var mo = re.exec(i.tagName);\r
+          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {\r
+            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);\r
+          }\r
+          iterate(i);\r
+        }\r
+      }\r
+    }\r
+    iterate(el);\r
+    return result;\r
+  }\r
+\r
+  var toc = document.getElementById("toc");\r
+  if (!toc) {\r
+    return;\r
+  }\r
+\r
+  // Delete existing TOC entries in case we're reloading the TOC.\r
+  var tocEntriesToRemove = [];\r
+  var i;\r
+  for (i = 0; i < toc.childNodes.length; i++) {\r
+    var entry = toc.childNodes[i];\r
+    if (entry.nodeName.toLowerCase() == 'div'\r
+     && entry.getAttribute("class")\r
+     && entry.getAttribute("class").match(/^toclevel/))\r
+      tocEntriesToRemove.push(entry);\r
+  }\r
+  for (i = 0; i < tocEntriesToRemove.length; i++) {\r
+    toc.removeChild(tocEntriesToRemove[i]);\r
+  }\r
+\r
+  // Rebuild TOC entries.\r
+  var entries = tocEntries(document.getElementById("content"), toclevels);\r
+  for (var i = 0; i < entries.length; ++i) {\r
+    var entry = entries[i];\r
+    if (entry.element.id == "")\r
+      entry.element.id = "_toc_" + i;\r
+    var a = document.createElement("a");\r
+    a.href = "#" + entry.element.id;\r
+    a.appendChild(document.createTextNode(entry.text));\r
+    var div = document.createElement("div");\r
+    div.appendChild(a);\r
+    div.className = "toclevel" + entry.toclevel;\r
+    toc.appendChild(div);\r
+  }\r
+  if (entries.length == 0)\r
+    toc.parentNode.removeChild(toc);\r
+},\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+// Footnotes generator\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+/* Based on footnote generation code from:\r
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html\r
+ */\r
+\r
+footnotes: function () {\r
+  // Delete existing footnote entries in case we're reloading the footnodes.\r
+  var i;\r
+  var noteholder = document.getElementById("footnotes");\r
+  if (!noteholder) {\r
+    return;\r
+  }\r
+  var entriesToRemove = [];\r
+  for (i = 0; i < noteholder.childNodes.length; i++) {\r
+    var entry = noteholder.childNodes[i];\r
+    if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")\r
+      entriesToRemove.push(entry);\r
+  }\r
+  for (i = 0; i < entriesToRemove.length; i++) {\r
+    noteholder.removeChild(entriesToRemove[i]);\r
+  }\r
+\r
+  // Rebuild footnote entries.\r
+  var cont = document.getElementById("content");\r
+  var spans = cont.getElementsByTagName("span");\r
+  var refs = {};\r
+  var n = 0;\r
+  for (i=0; i<spans.length; i++) {\r
+    if (spans[i].className == "footnote") {\r
+      n++;\r
+      var note = spans[i].getAttribute("data-note");\r
+      if (!note) {\r
+        // Use [\s\S] in place of . so multi-line matches work.\r
+        // Because JavaScript has no s (dotall) regex flag.\r
+        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];\r
+        spans[i].innerHTML =\r
+          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +\r
+          "' title='View footnote' class='footnote'>" + n + "</a>]";\r
+        spans[i].setAttribute("data-note", note);\r
+      }\r
+      noteholder.innerHTML +=\r
+        "<div class='footnote' id='_footnote_" + n + "'>" +\r
+        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +\r
+        n + "</a>. " + note + "</div>";\r
+      var id =spans[i].getAttribute("id");\r
+      if (id != null) refs["#"+id] = n;\r
+    }\r
+  }\r
+  if (n == 0)\r
+    noteholder.parentNode.removeChild(noteholder);\r
+  else {\r
+    // Process footnoterefs.\r
+    for (i=0; i<spans.length; i++) {\r
+      if (spans[i].className == "footnoteref") {\r
+        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");\r
+        href = href.match(/#.*/)[0];  // Because IE return full URL.\r
+        n = refs[href];\r
+        spans[i].innerHTML =\r
+          "[<a href='#_footnote_" + n +\r
+          "' title='View footnote' class='footnote'>" + n + "</a>]";\r
+      }\r
+    }\r
+  }\r
+},\r
+\r
+install: function(toclevels) {\r
+  var timerId;\r
+\r
+  function reinstall() {\r
+    asciidoc.footnotes();\r
+    if (toclevels) {\r
+      asciidoc.toc(toclevels);\r
+    }\r
+  }\r
+\r
+  function reinstallAndRemoveTimer() {\r
+    clearInterval(timerId);\r
+    reinstall();\r
+  }\r
+\r
+  timerId = setInterval(reinstall, 500);\r
+  if (document.addEventListener)\r
+    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);\r
+  else\r
+    window.onload = reinstallAndRemoveTimer;\r
+}\r
+\r
+}\r
+asciidoc.install();\r
+/*]]>*/\r
+</script>\r
+</head>\r
+<body class="manpage">\r
+<div id="header">\r
+<h1>\r
+nvme-toshiba-clear-pcie-correctable-errors(1) Manual Page\r
+</h1>\r
+<h2>NAME</h2>\r
+<div class="sectionbody">\r
+<p>nvme-toshiba-clear-pcie-correctable-errors -\r
+   Reset the PCIe correctable errors count to zero.\r
+</p>\r
+</div>\r
+</div>\r
+<div id="content">\r
+<div class="sect1">\r
+<h2 id="_synopsis">SYNOPSIS</h2>\r
+<div class="sectionbody">\r
+<div class="verseblock">\r
+<pre class="content">'nvme toshiba clear-pcie-correctable-errors ' &lt;device&gt;</pre>\r
+<div class="attribution">\r
+</div></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_description">DESCRIPTION</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>For the NVMe device given, sends the Toshiba clear PCIe correctable errors\r
+request.</p></div>\r
+<div class="paragraph"><p>The &lt;device&gt; parameter is mandatory and may be either the NVMe\r
+character device (ex: /dev/nvme0), or a namespace block device (ex:\r
+/dev/nvme0n1).</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_examples">EXAMPLES</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Clear the PCIe correctable errors count:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme toshiba clear-pcie-correctable-errors /dev/nvme0</code></pre>\r
+</div></div>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_nvme">NVME</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Part of the nvme-user suite</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated\r
+ 2018-01-08 13:19:04 CET\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/Documentation/nvme-toshiba-clear-pcie-correctable-errors.txt b/Documentation/nvme-toshiba-clear-pcie-correctable-errors.txt
new file mode 100644 (file)
index 0000000..5871900
--- /dev/null
@@ -0,0 +1,34 @@
+nvme-toshiba-clear-pcie-correctable-errors(1)
+=============================================
+
+NAME
+----
+nvme-toshiba-clear-pcie-correctable-errors - Reset the PCIe correctable errors count to zero.
+
+SYNOPSIS
+--------
+[verse]
+'nvme toshiba clear-pcie-correctable-errors ' <device>
+
+
+DESCRIPTION
+-----------
+For the NVMe device given, sends the Toshiba clear PCIe correctable errors
+request.
+
+The <device> parameter is mandatory and may be either the NVMe
+character device (ex: /dev/nvme0), or a namespace block device (ex:
+/dev/nvme0n1). 
+
+
+EXAMPLES
+--------
+* Clear the PCIe correctable errors count:
++
+------------
+# nvme toshiba clear-pcie-correctable-errors /dev/nvme0 
+------------
+
+NVME
+----
+Part of the nvme-user suite
diff --git a/Documentation/nvme-toshiba-vs-internal-log.1 b/Documentation/nvme-toshiba-vs-internal-log.1
new file mode 100644 (file)
index 0000000..25e3c11
--- /dev/null
@@ -0,0 +1,108 @@
+'\" t
+.\"     Title: nvme-toshiba-vs-internal-log
+.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/07/2018
+.\"    Manual: NVMe Manual
+.\"    Source: NVMe
+.\"  Language: English
+.\"
+.TH "NVME\-TOSHIBA\-VS\-I" "1" "03/07/2018" "NVMe" "NVMe Manual"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+nvme-toshiba-vs-internal-log \- Retrieve a Toshiba device\*(Aqs vendor specific internal log and either save to file or dump the contents\&.
+.SH "SYNOPSIS"
+.sp
+.nf
+\*(Aqnvme toshiba vs\-internal\-log \*(Aq <device>
+                [\-\-output\-file=<FILE>, \-o <FILE>] (optional)
+                [\-\-saved\-log, \-s] (optional)
+.fi
+.SH "DESCRIPTION"
+.sp
+For the NVMe device given, sends the Toshiba internal device log request and either saves the result to a file or dumps the content to stdout\&.
+.sp
+The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&.
+.sp
+The log is associated with the controller rather than any namespaces\&.
+.sp
+Two logs exist, the current log and the previous log\&.
+.sp
+This will only work on Toshiba devices supporting this feature\&.
+.sp
+Note: The logs are quite large \- typically 100\(cqs of MB\&. This command can take several minutes to complete\&. A progress runner is included when data is written to file and a page count is included in the stdout dump\&.
+.SH "OPTIONS"
+.PP
+\-o <FILE>, \-\-output\-file=<FILE>
+.RS 4
+Output binary file\&. Defaults to text\-formatted dump to stdout
+.RE
+.PP
+\-p, \-\-prev\-log
+.RS 4
+Use previous log contents\&. Defaults to the current log contents\&.
+.RE
+.SH "EXAMPLES"
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Get the current log from the device and dump it to stdout:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme toshiba internal\-log /dev/nvme0
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Get the previous log from the device and save to a binary file:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme toshiba internal\-log /dev/nvme0 \-\-output\-file=log\&.bin \-\-prev\-log
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.SH "NVME"
+.sp
+Part of the nvme\-user suite
diff --git a/Documentation/nvme-toshiba-vs-internal-log.html b/Documentation/nvme-toshiba-vs-internal-log.html
new file mode 100644 (file)
index 0000000..3a19cb5
--- /dev/null
@@ -0,0 +1,843 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.9" />\r
+<title>nvme-toshiba-vs-internal-log(1)</title>\r
+<style type="text/css">\r
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */\r
+\r
+/* Default font. */\r
+body {\r
+  font-family: Georgia,serif;\r
+}\r
+\r
+/* Title font. */\r
+h1, h2, h3, h4, h5, h6,\r
+div.title, caption.title,\r
+thead, p.table.header,\r
+#toctitle,\r
+#author, #revnumber, #revdate, #revremark,\r
+#footer {\r
+  font-family: Arial,Helvetica,sans-serif;\r
+}\r
+\r
+body {\r
+  margin: 1em 5% 1em 5%;\r
+}\r
+\r
+a {\r
+  color: blue;\r
+  text-decoration: underline;\r
+}\r
+a:visited {\r
+  color: fuchsia;\r
+}\r
+\r
+em {\r
+  font-style: italic;\r
+  color: navy;\r
+}\r
+\r
+strong {\r
+  font-weight: bold;\r
+  color: #083194;\r
+}\r
+\r
+h1, h2, h3, h4, h5, h6 {\r
+  color: #527bbd;\r
+  margin-top: 1.2em;\r
+  margin-bottom: 0.5em;\r
+  line-height: 1.3;\r
+}\r
+\r
+h1, h2, h3 {\r
+  border-bottom: 2px solid silver;\r
+}\r
+h2 {\r
+  padding-top: 0.5em;\r
+}\r
+h3 {\r
+  float: left;\r
+}\r
+h3 + * {\r
+  clear: left;\r
+}\r
+h5 {\r
+  font-size: 1.0em;\r
+}\r
+\r
+div.sectionbody {\r
+  margin-left: 0;\r
+}\r
+\r
+hr {\r
+  border: 1px solid silver;\r
+}\r
+\r
+p {\r
+  margin-top: 0.5em;\r
+  margin-bottom: 0.5em;\r
+}\r
+\r
+ul, ol, li > p {\r
+  margin-top: 0;\r
+}\r
+ul > li     { color: #aaa; }\r
+ul > li > * { color: black; }\r
+\r
+.monospaced, code, pre {\r
+  font-family: "Courier New", Courier, monospace;\r
+  font-size: inherit;\r
+  color: navy;\r
+  padding: 0;\r
+  margin: 0;\r
+}\r
+pre {\r
+  white-space: pre-wrap;\r
+}\r
+\r
+#author {\r
+  color: #527bbd;\r
+  font-weight: bold;\r
+  font-size: 1.1em;\r
+}\r
+#email {\r
+}\r
+#revnumber, #revdate, #revremark {\r
+}\r
+\r
+#footer {\r
+  font-size: small;\r
+  border-top: 2px solid silver;\r
+  padding-top: 0.5em;\r
+  margin-top: 4.0em;\r
+}\r
+#footer-text {\r
+  float: left;\r
+  padding-bottom: 0.5em;\r
+}\r
+#footer-badges {\r
+  float: right;\r
+  padding-bottom: 0.5em;\r
+}\r
+\r
+#preamble {\r
+  margin-top: 1.5em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.imageblock, div.exampleblock, div.verseblock,\r
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,\r
+div.admonitionblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.admonitionblock {\r
+  margin-top: 2.0em;\r
+  margin-bottom: 2.0em;\r
+  margin-right: 10%;\r
+  color: #606060;\r
+}\r
+\r
+div.content { /* Block element content. */\r
+  padding: 0;\r
+}\r
+\r
+/* Block element titles. */\r
+div.title, caption.title {\r
+  color: #527bbd;\r
+  font-weight: bold;\r
+  text-align: left;\r
+  margin-top: 1.0em;\r
+  margin-bottom: 0.5em;\r
+}\r
+div.title + * {\r
+  margin-top: 0;\r
+}\r
+\r
+td div.title:first-child {\r
+  margin-top: 0.0em;\r
+}\r
+div.content div.title:first-child {\r
+  margin-top: 0.0em;\r
+}\r
+div.content + div.title {\r
+  margin-top: 0.0em;\r
+}\r
+\r
+div.sidebarblock > div.content {\r
+  background: #ffffee;\r
+  border: 1px solid #dddddd;\r
+  border-left: 4px solid #f0f0f0;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.listingblock > div.content {\r
+  border: 1px solid #dddddd;\r
+  border-left: 5px solid #f0f0f0;\r
+  background: #f8f8f8;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.quoteblock, div.verseblock {\r
+  padding-left: 1.0em;\r
+  margin-left: 1.0em;\r
+  margin-right: 10%;\r
+  border-left: 5px solid #f0f0f0;\r
+  color: #888;\r
+}\r
+\r
+div.quoteblock > div.attribution {\r
+  padding-top: 0.5em;\r
+  text-align: right;\r
+}\r
+\r
+div.verseblock > pre.content {\r
+  font-family: inherit;\r
+  font-size: inherit;\r
+}\r
+div.verseblock > div.attribution {\r
+  padding-top: 0.75em;\r
+  text-align: left;\r
+}\r
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */\r
+div.verseblock + div.attribution {\r
+  text-align: left;\r
+}\r
+\r
+div.admonitionblock .icon {\r
+  vertical-align: top;\r
+  font-size: 1.1em;\r
+  font-weight: bold;\r
+  text-decoration: underline;\r
+  color: #527bbd;\r
+  padding-right: 0.5em;\r
+}\r
+div.admonitionblock td.content {\r
+  padding-left: 0.5em;\r
+  border-left: 3px solid #dddddd;\r
+}\r
+\r
+div.exampleblock > div.content {\r
+  border-left: 3px solid #dddddd;\r
+  padding-left: 0.5em;\r
+}\r
+\r
+div.imageblock div.content { padding-left: 0; }\r
+span.image img { border-style: none; vertical-align: text-bottom; }\r
+a.image:visited { color: white; }\r
+\r
+dl {\r
+  margin-top: 0.8em;\r
+  margin-bottom: 0.8em;\r
+}\r
+dt {\r
+  margin-top: 0.5em;\r
+  margin-bottom: 0;\r
+  font-style: normal;\r
+  color: navy;\r
+}\r
+dd > *:first-child {\r
+  margin-top: 0.1em;\r
+}\r
+\r
+ul, ol {\r
+    list-style-position: outside;\r
+}\r
+ol.arabic {\r
+  list-style-type: decimal;\r
+}\r
+ol.loweralpha {\r
+  list-style-type: lower-alpha;\r
+}\r
+ol.upperalpha {\r
+  list-style-type: upper-alpha;\r
+}\r
+ol.lowerroman {\r
+  list-style-type: lower-roman;\r
+}\r
+ol.upperroman {\r
+  list-style-type: upper-roman;\r
+}\r
+\r
+div.compact ul, div.compact ol,\r
+div.compact p, div.compact p,\r
+div.compact div, div.compact div {\r
+  margin-top: 0.1em;\r
+  margin-bottom: 0.1em;\r
+}\r
+\r
+tfoot {\r
+  font-weight: bold;\r
+}\r
+td > div.verse {\r
+  white-space: pre;\r
+}\r
+\r
+div.hdlist {\r
+  margin-top: 0.8em;\r
+  margin-bottom: 0.8em;\r
+}\r
+div.hdlist tr {\r
+  padding-bottom: 15px;\r
+}\r
+dt.hdlist1.strong, td.hdlist1.strong {\r
+  font-weight: bold;\r
+}\r
+td.hdlist1 {\r
+  vertical-align: top;\r
+  font-style: normal;\r
+  padding-right: 0.8em;\r
+  color: navy;\r
+}\r
+td.hdlist2 {\r
+  vertical-align: top;\r
+}\r
+div.hdlist.compact tr {\r
+  margin: 0;\r
+  padding-bottom: 0;\r
+}\r
+\r
+.comment {\r
+  background: yellow;\r
+}\r
+\r
+.footnote, .footnoteref {\r
+  font-size: 0.8em;\r
+}\r
+\r
+span.footnote, span.footnoteref {\r
+  vertical-align: super;\r
+}\r
+\r
+#footnotes {\r
+  margin: 20px 0 20px 0;\r
+  padding: 7px 0 0 0;\r
+}\r
+\r
+#footnotes div.footnote {\r
+  margin: 0 0 5px 0;\r
+}\r
+\r
+#footnotes hr {\r
+  border: none;\r
+  border-top: 1px solid silver;\r
+  height: 1px;\r
+  text-align: left;\r
+  margin-left: 0;\r
+  width: 20%;\r
+  min-width: 100px;\r
+}\r
+\r
+div.colist td {\r
+  padding-right: 0.5em;\r
+  padding-bottom: 0.3em;\r
+  vertical-align: top;\r
+}\r
+div.colist td img {\r
+  margin-top: 0.3em;\r
+}\r
+\r
+@media print {\r
+  #footer-badges { display: none; }\r
+}\r
+\r
+#toc {\r
+  margin-bottom: 2.5em;\r
+}\r
+\r
+#toctitle {\r
+  color: #527bbd;\r
+  font-size: 1.1em;\r
+  font-weight: bold;\r
+  margin-top: 1.0em;\r
+  margin-bottom: 0.1em;\r
+}\r
+\r
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {\r
+  margin-top: 0;\r
+  margin-bottom: 0;\r
+}\r
+div.toclevel2 {\r
+  margin-left: 2em;\r
+  font-size: 0.9em;\r
+}\r
+div.toclevel3 {\r
+  margin-left: 4em;\r
+  font-size: 0.9em;\r
+}\r
+div.toclevel4 {\r
+  margin-left: 6em;\r
+  font-size: 0.9em;\r
+}\r
+\r
+span.aqua { color: aqua; }\r
+span.black { color: black; }\r
+span.blue { color: blue; }\r
+span.fuchsia { color: fuchsia; }\r
+span.gray { color: gray; }\r
+span.green { color: green; }\r
+span.lime { color: lime; }\r
+span.maroon { color: maroon; }\r
+span.navy { color: navy; }\r
+span.olive { color: olive; }\r
+span.purple { color: purple; }\r
+span.red { color: red; }\r
+span.silver { color: silver; }\r
+span.teal { color: teal; }\r
+span.white { color: white; }\r
+span.yellow { color: yellow; }\r
+\r
+span.aqua-background { background: aqua; }\r
+span.black-background { background: black; }\r
+span.blue-background { background: blue; }\r
+span.fuchsia-background { background: fuchsia; }\r
+span.gray-background { background: gray; }\r
+span.green-background { background: green; }\r
+span.lime-background { background: lime; }\r
+span.maroon-background { background: maroon; }\r
+span.navy-background { background: navy; }\r
+span.olive-background { background: olive; }\r
+span.purple-background { background: purple; }\r
+span.red-background { background: red; }\r
+span.silver-background { background: silver; }\r
+span.teal-background { background: teal; }\r
+span.white-background { background: white; }\r
+span.yellow-background { background: yellow; }\r
+\r
+span.big { font-size: 2em; }\r
+span.small { font-size: 0.6em; }\r
+\r
+span.underline { text-decoration: underline; }\r
+span.overline { text-decoration: overline; }\r
+span.line-through { text-decoration: line-through; }\r
+\r
+div.unbreakable { page-break-inside: avoid; }\r
+\r
+\r
+/*\r
+ * xhtml11 specific\r
+ *\r
+ * */\r
+\r
+div.tableblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.tableblock > table {\r
+  border: 3px solid #527bbd;\r
+}\r
+thead, p.table.header {\r
+  font-weight: bold;\r
+  color: #527bbd;\r
+}\r
+p.table {\r
+  margin-top: 0;\r
+}\r
+/* Because the table frame attribute is overriden by CSS in most browsers. */\r
+div.tableblock > table[frame="void"] {\r
+  border-style: none;\r
+}\r
+div.tableblock > table[frame="hsides"] {\r
+  border-left-style: none;\r
+  border-right-style: none;\r
+}\r
+div.tableblock > table[frame="vsides"] {\r
+  border-top-style: none;\r
+  border-bottom-style: none;\r
+}\r
+\r
+\r
+/*\r
+ * html5 specific\r
+ *\r
+ * */\r
+\r
+table.tableblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+thead, p.tableblock.header {\r
+  font-weight: bold;\r
+  color: #527bbd;\r
+}\r
+p.tableblock {\r
+  margin-top: 0;\r
+}\r
+table.tableblock {\r
+  border-width: 3px;\r
+  border-spacing: 0px;\r
+  border-style: solid;\r
+  border-color: #527bbd;\r
+  border-collapse: collapse;\r
+}\r
+th.tableblock, td.tableblock {\r
+  border-width: 1px;\r
+  padding: 4px;\r
+  border-style: solid;\r
+  border-color: #527bbd;\r
+}\r
+\r
+table.tableblock.frame-topbot {\r
+  border-left-style: hidden;\r
+  border-right-style: hidden;\r
+}\r
+table.tableblock.frame-sides {\r
+  border-top-style: hidden;\r
+  border-bottom-style: hidden;\r
+}\r
+table.tableblock.frame-none {\r
+  border-style: hidden;\r
+}\r
+\r
+th.tableblock.halign-left, td.tableblock.halign-left {\r
+  text-align: left;\r
+}\r
+th.tableblock.halign-center, td.tableblock.halign-center {\r
+  text-align: center;\r
+}\r
+th.tableblock.halign-right, td.tableblock.halign-right {\r
+  text-align: right;\r
+}\r
+\r
+th.tableblock.valign-top, td.tableblock.valign-top {\r
+  vertical-align: top;\r
+}\r
+th.tableblock.valign-middle, td.tableblock.valign-middle {\r
+  vertical-align: middle;\r
+}\r
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {\r
+  vertical-align: bottom;\r
+}\r
+\r
+\r
+/*\r
+ * manpage specific\r
+ *\r
+ * */\r
+\r
+body.manpage h1 {\r
+  padding-top: 0.5em;\r
+  padding-bottom: 0.5em;\r
+  border-top: 2px solid silver;\r
+  border-bottom: 2px solid silver;\r
+}\r
+body.manpage h2 {\r
+  border-style: none;\r
+}\r
+body.manpage div.sectionbody {\r
+  margin-left: 3em;\r
+}\r
+\r
+@media print {\r
+  body.manpage div#toc { display: none; }\r
+}\r
+\r
+\r
+</style>\r
+<script type="text/javascript">\r
+/*<![CDATA[*/\r
+var asciidoc = {  // Namespace.\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+// Table Of Contents generator\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+/* Author: Mihai Bazon, September 2002\r
+ * http://students.infoiasi.ro/~mishoo\r
+ *\r
+ * Table Of Content generator\r
+ * Version: 0.4\r
+ *\r
+ * Feel free to use this script under the terms of the GNU General Public\r
+ * License, as long as you do not remove or alter this notice.\r
+ */\r
+\r
+ /* modified by Troy D. Hanson, September 2006. License: GPL */\r
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */\r
+\r
+// toclevels = 1..4.\r
+toc: function (toclevels) {\r
+\r
+  function getText(el) {\r
+    var text = "";\r
+    for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.\r
+        text += i.data;\r
+      else if (i.firstChild != null)\r
+        text += getText(i);\r
+    }\r
+    return text;\r
+  }\r
+\r
+  function TocEntry(el, text, toclevel) {\r
+    this.element = el;\r
+    this.text = text;\r
+    this.toclevel = toclevel;\r
+  }\r
+\r
+  function tocEntries(el, toclevels) {\r
+    var result = new Array;\r
+    var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');\r
+    // Function that scans the DOM tree for header elements (the DOM2\r
+    // nodeIterator API would be a better technique but not supported by all\r
+    // browsers).\r
+    var iterate = function (el) {\r
+      for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {\r
+          var mo = re.exec(i.tagName);\r
+          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {\r
+            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);\r
+          }\r
+          iterate(i);\r
+        }\r
+      }\r
+    }\r
+    iterate(el);\r
+    return result;\r
+  }\r
+\r
+  var toc = document.getElementById("toc");\r
+  if (!toc) {\r
+    return;\r
+  }\r
+\r
+  // Delete existing TOC entries in case we're reloading the TOC.\r
+  var tocEntriesToRemove = [];\r
+  var i;\r
+  for (i = 0; i < toc.childNodes.length; i++) {\r
+    var entry = toc.childNodes[i];\r
+    if (entry.nodeName.toLowerCase() == 'div'\r
+     && entry.getAttribute("class")\r
+     && entry.getAttribute("class").match(/^toclevel/))\r
+      tocEntriesToRemove.push(entry);\r
+  }\r
+  for (i = 0; i < tocEntriesToRemove.length; i++) {\r
+    toc.removeChild(tocEntriesToRemove[i]);\r
+  }\r
+\r
+  // Rebuild TOC entries.\r
+  var entries = tocEntries(document.getElementById("content"), toclevels);\r
+  for (var i = 0; i < entries.length; ++i) {\r
+    var entry = entries[i];\r
+    if (entry.element.id == "")\r
+      entry.element.id = "_toc_" + i;\r
+    var a = document.createElement("a");\r
+    a.href = "#" + entry.element.id;\r
+    a.appendChild(document.createTextNode(entry.text));\r
+    var div = document.createElement("div");\r
+    div.appendChild(a);\r
+    div.className = "toclevel" + entry.toclevel;\r
+    toc.appendChild(div);\r
+  }\r
+  if (entries.length == 0)\r
+    toc.parentNode.removeChild(toc);\r
+},\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+// Footnotes generator\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+/* Based on footnote generation code from:\r
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html\r
+ */\r
+\r
+footnotes: function () {\r
+  // Delete existing footnote entries in case we're reloading the footnodes.\r
+  var i;\r
+  var noteholder = document.getElementById("footnotes");\r
+  if (!noteholder) {\r
+    return;\r
+  }\r
+  var entriesToRemove = [];\r
+  for (i = 0; i < noteholder.childNodes.length; i++) {\r
+    var entry = noteholder.childNodes[i];\r
+    if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")\r
+      entriesToRemove.push(entry);\r
+  }\r
+  for (i = 0; i < entriesToRemove.length; i++) {\r
+    noteholder.removeChild(entriesToRemove[i]);\r
+  }\r
+\r
+  // Rebuild footnote entries.\r
+  var cont = document.getElementById("content");\r
+  var spans = cont.getElementsByTagName("span");\r
+  var refs = {};\r
+  var n = 0;\r
+  for (i=0; i<spans.length; i++) {\r
+    if (spans[i].className == "footnote") {\r
+      n++;\r
+      var note = spans[i].getAttribute("data-note");\r
+      if (!note) {\r
+        // Use [\s\S] in place of . so multi-line matches work.\r
+        // Because JavaScript has no s (dotall) regex flag.\r
+        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];\r
+        spans[i].innerHTML =\r
+          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +\r
+          "' title='View footnote' class='footnote'>" + n + "</a>]";\r
+        spans[i].setAttribute("data-note", note);\r
+      }\r
+      noteholder.innerHTML +=\r
+        "<div class='footnote' id='_footnote_" + n + "'>" +\r
+        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +\r
+        n + "</a>. " + note + "</div>";\r
+      var id =spans[i].getAttribute("id");\r
+      if (id != null) refs["#"+id] = n;\r
+    }\r
+  }\r
+  if (n == 0)\r
+    noteholder.parentNode.removeChild(noteholder);\r
+  else {\r
+    // Process footnoterefs.\r
+    for (i=0; i<spans.length; i++) {\r
+      if (spans[i].className == "footnoteref") {\r
+        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");\r
+        href = href.match(/#.*/)[0];  // Because IE return full URL.\r
+        n = refs[href];\r
+        spans[i].innerHTML =\r
+          "[<a href='#_footnote_" + n +\r
+          "' title='View footnote' class='footnote'>" + n + "</a>]";\r
+      }\r
+    }\r
+  }\r
+},\r
+\r
+install: function(toclevels) {\r
+  var timerId;\r
+\r
+  function reinstall() {\r
+    asciidoc.footnotes();\r
+    if (toclevels) {\r
+      asciidoc.toc(toclevels);\r
+    }\r
+  }\r
+\r
+  function reinstallAndRemoveTimer() {\r
+    clearInterval(timerId);\r
+    reinstall();\r
+  }\r
+\r
+  timerId = setInterval(reinstall, 500);\r
+  if (document.addEventListener)\r
+    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);\r
+  else\r
+    window.onload = reinstallAndRemoveTimer;\r
+}\r
+\r
+}\r
+asciidoc.install();\r
+/*]]>*/\r
+</script>\r
+</head>\r
+<body class="manpage">\r
+<div id="header">\r
+<h1>\r
+nvme-toshiba-vs-internal-log(1) Manual Page\r
+</h1>\r
+<h2>NAME</h2>\r
+<div class="sectionbody">\r
+<p>nvme-toshiba-vs-internal-log -\r
+   Retrieve a Toshiba device's vendor specific internal log and either save to file or dump the contents.\r
+</p>\r
+</div>\r
+</div>\r
+<div id="content">\r
+<div class="sect1">\r
+<h2 id="_synopsis">SYNOPSIS</h2>\r
+<div class="sectionbody">\r
+<div class="verseblock">\r
+<pre class="content">'nvme toshiba vs-internal-log ' &lt;device&gt;\r
+                [--output-file=&lt;FILE&gt;, -o &lt;FILE&gt;] (optional)\r
+                [--saved-log, -s] (optional)</pre>\r
+<div class="attribution">\r
+</div></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_description">DESCRIPTION</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>For the NVMe device given, sends the Toshiba internal device log\r
+request and either saves the result to a file or dumps the content to stdout.</p></div>\r
+<div class="paragraph"><p>The &lt;device&gt; parameter is mandatory and may be either the NVMe\r
+character device (ex: /dev/nvme0), or a namespace block device (ex:\r
+/dev/nvme0n1).</p></div>\r
+<div class="paragraph"><p>The log is associated with the controller rather than any\r
+namespaces.</p></div>\r
+<div class="paragraph"><p>Two logs exist, the current log and the previous log.</p></div>\r
+<div class="paragraph"><p>This will only work on Toshiba devices supporting this feature.</p></div>\r
+<div class="paragraph"><p>Note: The logs are quite large - typically 100&#8217;s of MB. This command can take several minutes to complete.\r
+A progress runner is included when data is written to file and a page count is included in the stdout dump.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_options">OPTIONS</h2>\r
+<div class="sectionbody">\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+-o &lt;FILE&gt;\r
+</dt>\r
+<dt class="hdlist1">\r
+--output-file=&lt;FILE&gt;\r
+</dt>\r
+<dd>\r
+<p>\r
+        Output binary file. Defaults to text-formatted dump to stdout\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+-p\r
+</dt>\r
+<dt class="hdlist1">\r
+--prev-log\r
+</dt>\r
+<dd>\r
+<p>\r
+        Use previous log contents. Defaults to the current log contents.\r
+</p>\r
+</dd>\r
+</dl></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_examples">EXAMPLES</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Get the current log from the device and dump it to stdout:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme toshiba internal-log /dev/nvme0</code></pre>\r
+</div></div>\r
+</li>\r
+<li>\r
+<p>\r
+Get the previous log from the device and save to a binary file:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme toshiba internal-log /dev/nvme0 --output-file=log.bin --prev-log</code></pre>\r
+</div></div>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_nvme">NVME</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Part of the nvme-user suite</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated\r
+ 2018-03-07 13:57:52 CET\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/Documentation/nvme-toshiba-vs-internal-log.txt b/Documentation/nvme-toshiba-vs-internal-log.txt
new file mode 100644 (file)
index 0000000..d3c0104
--- /dev/null
@@ -0,0 +1,64 @@
+nvme-toshiba-vs-internal-log(1)
+===============================
+
+NAME
+----
+nvme-toshiba-vs-internal-log - Retrieve a Toshiba device's vendor specific internal log and either save to file or dump the contents.
+
+SYNOPSIS
+--------
+[verse]
+'nvme toshiba vs-internal-log ' <device>
+               [--output-file=<FILE>, -o <FILE>] (optional)
+               [--saved-log, -s] (optional)
+
+DESCRIPTION
+-----------
+For the NVMe device given, sends the Toshiba internal device log
+request and either saves the result to a file or dumps the content to stdout.
+
+The <device> parameter is mandatory and may be either the NVMe
+character device (ex: /dev/nvme0), or a namespace block device (ex:
+/dev/nvme0n1). 
+
+The log is associated with the controller rather than any
+namespaces.
+
+Two logs exist, the current log and the previous log.
+
+This will only work on Toshiba devices supporting this feature.
+
+Note: The logs are quite large - typically 100's of MB. This command can take several minutes to complete. 
+A progress runner is included when data is written to file and a page count is included in the stdout dump.
+
+OPTIONS
+-------
+
+
+-o <FILE>::
+--output-file=<FILE>::
+       Output binary file. Defaults to text-formatted dump to stdout
+
+
+-p::
+--prev-log::
+       Use previous log contents. Defaults to the current log contents.
+
+EXAMPLES
+--------
+* Get the current log from the device and dump it to stdout:
++
+------------
+# nvme toshiba internal-log /dev/nvme0 
+------------
++
+
+* Get the previous log from the device and save to a binary file:
++
+------------
+# nvme toshiba internal-log /dev/nvme0 --output-file=log.bin --prev-log
+------------
+
+NVME
+----
+Part of the nvme-user suite
diff --git a/Documentation/nvme-toshiba-vs-smart-add-log.1 b/Documentation/nvme-toshiba-vs-smart-add-log.1
new file mode 100644 (file)
index 0000000..82fe4b2
--- /dev/null
@@ -0,0 +1,106 @@
+'\" t
+.\"     Title: nvme-toshiba-vs-smart-add-log
+.\"    Author: [FIXME: author] [see http://docbook.sf.net/el/author]
+.\" Generator: DocBook XSL Stylesheets v1.79.1 <http://docbook.sf.net/>
+.\"      Date: 03/07/2018
+.\"    Manual: NVMe Manual
+.\"    Source: NVMe
+.\"  Language: English
+.\"
+.TH "NVME\-TOSHIBA\-VS\-S" "1" "03/07/2018" "NVMe" "NVMe Manual"
+.\" -----------------------------------------------------------------
+.\" * Define some portability stuff
+.\" -----------------------------------------------------------------
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.\" http://bugs.debian.org/507673
+.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html
+.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+.ie \n(.g .ds Aq \(aq
+.el       .ds Aq '
+.\" -----------------------------------------------------------------
+.\" * set default formatting
+.\" -----------------------------------------------------------------
+.\" disable hyphenation
+.nh
+.\" disable justification (adjust text to left margin only)
+.ad l
+.\" -----------------------------------------------------------------
+.\" * MAIN CONTENT STARTS HERE *
+.\" -----------------------------------------------------------------
+.SH "NAME"
+nvme-toshiba-vs-smart-add-log \- Retrieve a Toshiba device\*(Aqs vendor specific extended SMART log page contents and either save to file or dump the contents\&.
+.SH "SYNOPSIS"
+.sp
+.nf
+\*(Aqnvme toshiba vs\-smart\-add\-log \*(Aq <device> [\-\-log=<NUM>, \-l <NUM>]
+                [\-\-namespace\-id=<NUM>, \-n <NUM>]
+                [\-\-output\-file=<FILE>, \-o <FILE>]
+.fi
+.SH "DESCRIPTION"
+.sp
+For the NVMe device given, sends the Toshiba vendor log request and either saves the result to a file or dumps the content to stdout\&.
+.sp
+The <device> parameter is mandatory and may be either the NVMe character device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1)\&.
+.sp
+The log contents may be associated with the controller, in which case the namespace parameter is ignored\&.
+.sp
+Two logs exist, page 0xC0 (log page directory) and page 0xCA (vendor log page)
+.sp
+This will only work on Toshiba devices supporting this feature\&.
+.SH "OPTIONS"
+.PP
+\-l <NUM>, \-\-log=<NUM>
+.RS 4
+Log page: 0xC0 or 0xCA (defaults to 0xCA)
+.RE
+.PP
+\-n <NUM>, \-\-namespace\-id=<NUM>, \-o <FILE>, \-\-output\-file=<FILE>
+.RS 4
+Output binary file\&. Defaults to text\-formatted dump to stdout
+.RE
+.SH "EXAMPLES"
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Get the current log from the device and dumps it to stdout:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme toshiba vs\-smart\-add\-log /dev/nvme0
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.sp
+.RS 4
+.ie n \{\
+\h'-04'\(bu\h'+03'\c
+.\}
+.el \{\
+.sp -1
+.IP \(bu 2.3
+.\}
+Get the contents of log page 0xC0 from the device and save to a binary file:
+.sp
+.if n \{\
+.RS 4
+.\}
+.nf
+# nvme toshiba vs\-smart\-add\-log /dev/nvme0 \-\-output\-file=log\&.bin \-\-log=0xC0
+.fi
+.if n \{\
+.RE
+.\}
+.RE
+.SH "NVME"
+.sp
+Part of the nvme\-user suite
diff --git a/Documentation/nvme-toshiba-vs-smart-add-log.html b/Documentation/nvme-toshiba-vs-smart-add-log.html
new file mode 100644 (file)
index 0000000..ebe6e83
--- /dev/null
@@ -0,0 +1,846 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"\r
+    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">\r
+<head>\r
+<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />\r
+<meta name="generator" content="AsciiDoc 8.6.9" />\r
+<title>nvme-toshiba-vs-smart-add-log(1)</title>\r
+<style type="text/css">\r
+/* Shared CSS for AsciiDoc xhtml11 and html5 backends */\r
+\r
+/* Default font. */\r
+body {\r
+  font-family: Georgia,serif;\r
+}\r
+\r
+/* Title font. */\r
+h1, h2, h3, h4, h5, h6,\r
+div.title, caption.title,\r
+thead, p.table.header,\r
+#toctitle,\r
+#author, #revnumber, #revdate, #revremark,\r
+#footer {\r
+  font-family: Arial,Helvetica,sans-serif;\r
+}\r
+\r
+body {\r
+  margin: 1em 5% 1em 5%;\r
+}\r
+\r
+a {\r
+  color: blue;\r
+  text-decoration: underline;\r
+}\r
+a:visited {\r
+  color: fuchsia;\r
+}\r
+\r
+em {\r
+  font-style: italic;\r
+  color: navy;\r
+}\r
+\r
+strong {\r
+  font-weight: bold;\r
+  color: #083194;\r
+}\r
+\r
+h1, h2, h3, h4, h5, h6 {\r
+  color: #527bbd;\r
+  margin-top: 1.2em;\r
+  margin-bottom: 0.5em;\r
+  line-height: 1.3;\r
+}\r
+\r
+h1, h2, h3 {\r
+  border-bottom: 2px solid silver;\r
+}\r
+h2 {\r
+  padding-top: 0.5em;\r
+}\r
+h3 {\r
+  float: left;\r
+}\r
+h3 + * {\r
+  clear: left;\r
+}\r
+h5 {\r
+  font-size: 1.0em;\r
+}\r
+\r
+div.sectionbody {\r
+  margin-left: 0;\r
+}\r
+\r
+hr {\r
+  border: 1px solid silver;\r
+}\r
+\r
+p {\r
+  margin-top: 0.5em;\r
+  margin-bottom: 0.5em;\r
+}\r
+\r
+ul, ol, li > p {\r
+  margin-top: 0;\r
+}\r
+ul > li     { color: #aaa; }\r
+ul > li > * { color: black; }\r
+\r
+.monospaced, code, pre {\r
+  font-family: "Courier New", Courier, monospace;\r
+  font-size: inherit;\r
+  color: navy;\r
+  padding: 0;\r
+  margin: 0;\r
+}\r
+pre {\r
+  white-space: pre-wrap;\r
+}\r
+\r
+#author {\r
+  color: #527bbd;\r
+  font-weight: bold;\r
+  font-size: 1.1em;\r
+}\r
+#email {\r
+}\r
+#revnumber, #revdate, #revremark {\r
+}\r
+\r
+#footer {\r
+  font-size: small;\r
+  border-top: 2px solid silver;\r
+  padding-top: 0.5em;\r
+  margin-top: 4.0em;\r
+}\r
+#footer-text {\r
+  float: left;\r
+  padding-bottom: 0.5em;\r
+}\r
+#footer-badges {\r
+  float: right;\r
+  padding-bottom: 0.5em;\r
+}\r
+\r
+#preamble {\r
+  margin-top: 1.5em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.imageblock, div.exampleblock, div.verseblock,\r
+div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,\r
+div.admonitionblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.admonitionblock {\r
+  margin-top: 2.0em;\r
+  margin-bottom: 2.0em;\r
+  margin-right: 10%;\r
+  color: #606060;\r
+}\r
+\r
+div.content { /* Block element content. */\r
+  padding: 0;\r
+}\r
+\r
+/* Block element titles. */\r
+div.title, caption.title {\r
+  color: #527bbd;\r
+  font-weight: bold;\r
+  text-align: left;\r
+  margin-top: 1.0em;\r
+  margin-bottom: 0.5em;\r
+}\r
+div.title + * {\r
+  margin-top: 0;\r
+}\r
+\r
+td div.title:first-child {\r
+  margin-top: 0.0em;\r
+}\r
+div.content div.title:first-child {\r
+  margin-top: 0.0em;\r
+}\r
+div.content + div.title {\r
+  margin-top: 0.0em;\r
+}\r
+\r
+div.sidebarblock > div.content {\r
+  background: #ffffee;\r
+  border: 1px solid #dddddd;\r
+  border-left: 4px solid #f0f0f0;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.listingblock > div.content {\r
+  border: 1px solid #dddddd;\r
+  border-left: 5px solid #f0f0f0;\r
+  background: #f8f8f8;\r
+  padding: 0.5em;\r
+}\r
+\r
+div.quoteblock, div.verseblock {\r
+  padding-left: 1.0em;\r
+  margin-left: 1.0em;\r
+  margin-right: 10%;\r
+  border-left: 5px solid #f0f0f0;\r
+  color: #888;\r
+}\r
+\r
+div.quoteblock > div.attribution {\r
+  padding-top: 0.5em;\r
+  text-align: right;\r
+}\r
+\r
+div.verseblock > pre.content {\r
+  font-family: inherit;\r
+  font-size: inherit;\r
+}\r
+div.verseblock > div.attribution {\r
+  padding-top: 0.75em;\r
+  text-align: left;\r
+}\r
+/* DEPRECATED: Pre version 8.2.7 verse style literal block. */\r
+div.verseblock + div.attribution {\r
+  text-align: left;\r
+}\r
+\r
+div.admonitionblock .icon {\r
+  vertical-align: top;\r
+  font-size: 1.1em;\r
+  font-weight: bold;\r
+  text-decoration: underline;\r
+  color: #527bbd;\r
+  padding-right: 0.5em;\r
+}\r
+div.admonitionblock td.content {\r
+  padding-left: 0.5em;\r
+  border-left: 3px solid #dddddd;\r
+}\r
+\r
+div.exampleblock > div.content {\r
+  border-left: 3px solid #dddddd;\r
+  padding-left: 0.5em;\r
+}\r
+\r
+div.imageblock div.content { padding-left: 0; }\r
+span.image img { border-style: none; vertical-align: text-bottom; }\r
+a.image:visited { color: white; }\r
+\r
+dl {\r
+  margin-top: 0.8em;\r
+  margin-bottom: 0.8em;\r
+}\r
+dt {\r
+  margin-top: 0.5em;\r
+  margin-bottom: 0;\r
+  font-style: normal;\r
+  color: navy;\r
+}\r
+dd > *:first-child {\r
+  margin-top: 0.1em;\r
+}\r
+\r
+ul, ol {\r
+    list-style-position: outside;\r
+}\r
+ol.arabic {\r
+  list-style-type: decimal;\r
+}\r
+ol.loweralpha {\r
+  list-style-type: lower-alpha;\r
+}\r
+ol.upperalpha {\r
+  list-style-type: upper-alpha;\r
+}\r
+ol.lowerroman {\r
+  list-style-type: lower-roman;\r
+}\r
+ol.upperroman {\r
+  list-style-type: upper-roman;\r
+}\r
+\r
+div.compact ul, div.compact ol,\r
+div.compact p, div.compact p,\r
+div.compact div, div.compact div {\r
+  margin-top: 0.1em;\r
+  margin-bottom: 0.1em;\r
+}\r
+\r
+tfoot {\r
+  font-weight: bold;\r
+}\r
+td > div.verse {\r
+  white-space: pre;\r
+}\r
+\r
+div.hdlist {\r
+  margin-top: 0.8em;\r
+  margin-bottom: 0.8em;\r
+}\r
+div.hdlist tr {\r
+  padding-bottom: 15px;\r
+}\r
+dt.hdlist1.strong, td.hdlist1.strong {\r
+  font-weight: bold;\r
+}\r
+td.hdlist1 {\r
+  vertical-align: top;\r
+  font-style: normal;\r
+  padding-right: 0.8em;\r
+  color: navy;\r
+}\r
+td.hdlist2 {\r
+  vertical-align: top;\r
+}\r
+div.hdlist.compact tr {\r
+  margin: 0;\r
+  padding-bottom: 0;\r
+}\r
+\r
+.comment {\r
+  background: yellow;\r
+}\r
+\r
+.footnote, .footnoteref {\r
+  font-size: 0.8em;\r
+}\r
+\r
+span.footnote, span.footnoteref {\r
+  vertical-align: super;\r
+}\r
+\r
+#footnotes {\r
+  margin: 20px 0 20px 0;\r
+  padding: 7px 0 0 0;\r
+}\r
+\r
+#footnotes div.footnote {\r
+  margin: 0 0 5px 0;\r
+}\r
+\r
+#footnotes hr {\r
+  border: none;\r
+  border-top: 1px solid silver;\r
+  height: 1px;\r
+  text-align: left;\r
+  margin-left: 0;\r
+  width: 20%;\r
+  min-width: 100px;\r
+}\r
+\r
+div.colist td {\r
+  padding-right: 0.5em;\r
+  padding-bottom: 0.3em;\r
+  vertical-align: top;\r
+}\r
+div.colist td img {\r
+  margin-top: 0.3em;\r
+}\r
+\r
+@media print {\r
+  #footer-badges { display: none; }\r
+}\r
+\r
+#toc {\r
+  margin-bottom: 2.5em;\r
+}\r
+\r
+#toctitle {\r
+  color: #527bbd;\r
+  font-size: 1.1em;\r
+  font-weight: bold;\r
+  margin-top: 1.0em;\r
+  margin-bottom: 0.1em;\r
+}\r
+\r
+div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {\r
+  margin-top: 0;\r
+  margin-bottom: 0;\r
+}\r
+div.toclevel2 {\r
+  margin-left: 2em;\r
+  font-size: 0.9em;\r
+}\r
+div.toclevel3 {\r
+  margin-left: 4em;\r
+  font-size: 0.9em;\r
+}\r
+div.toclevel4 {\r
+  margin-left: 6em;\r
+  font-size: 0.9em;\r
+}\r
+\r
+span.aqua { color: aqua; }\r
+span.black { color: black; }\r
+span.blue { color: blue; }\r
+span.fuchsia { color: fuchsia; }\r
+span.gray { color: gray; }\r
+span.green { color: green; }\r
+span.lime { color: lime; }\r
+span.maroon { color: maroon; }\r
+span.navy { color: navy; }\r
+span.olive { color: olive; }\r
+span.purple { color: purple; }\r
+span.red { color: red; }\r
+span.silver { color: silver; }\r
+span.teal { color: teal; }\r
+span.white { color: white; }\r
+span.yellow { color: yellow; }\r
+\r
+span.aqua-background { background: aqua; }\r
+span.black-background { background: black; }\r
+span.blue-background { background: blue; }\r
+span.fuchsia-background { background: fuchsia; }\r
+span.gray-background { background: gray; }\r
+span.green-background { background: green; }\r
+span.lime-background { background: lime; }\r
+span.maroon-background { background: maroon; }\r
+span.navy-background { background: navy; }\r
+span.olive-background { background: olive; }\r
+span.purple-background { background: purple; }\r
+span.red-background { background: red; }\r
+span.silver-background { background: silver; }\r
+span.teal-background { background: teal; }\r
+span.white-background { background: white; }\r
+span.yellow-background { background: yellow; }\r
+\r
+span.big { font-size: 2em; }\r
+span.small { font-size: 0.6em; }\r
+\r
+span.underline { text-decoration: underline; }\r
+span.overline { text-decoration: overline; }\r
+span.line-through { text-decoration: line-through; }\r
+\r
+div.unbreakable { page-break-inside: avoid; }\r
+\r
+\r
+/*\r
+ * xhtml11 specific\r
+ *\r
+ * */\r
+\r
+div.tableblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+div.tableblock > table {\r
+  border: 3px solid #527bbd;\r
+}\r
+thead, p.table.header {\r
+  font-weight: bold;\r
+  color: #527bbd;\r
+}\r
+p.table {\r
+  margin-top: 0;\r
+}\r
+/* Because the table frame attribute is overriden by CSS in most browsers. */\r
+div.tableblock > table[frame="void"] {\r
+  border-style: none;\r
+}\r
+div.tableblock > table[frame="hsides"] {\r
+  border-left-style: none;\r
+  border-right-style: none;\r
+}\r
+div.tableblock > table[frame="vsides"] {\r
+  border-top-style: none;\r
+  border-bottom-style: none;\r
+}\r
+\r
+\r
+/*\r
+ * html5 specific\r
+ *\r
+ * */\r
+\r
+table.tableblock {\r
+  margin-top: 1.0em;\r
+  margin-bottom: 1.5em;\r
+}\r
+thead, p.tableblock.header {\r
+  font-weight: bold;\r
+  color: #527bbd;\r
+}\r
+p.tableblock {\r
+  margin-top: 0;\r
+}\r
+table.tableblock {\r
+  border-width: 3px;\r
+  border-spacing: 0px;\r
+  border-style: solid;\r
+  border-color: #527bbd;\r
+  border-collapse: collapse;\r
+}\r
+th.tableblock, td.tableblock {\r
+  border-width: 1px;\r
+  padding: 4px;\r
+  border-style: solid;\r
+  border-color: #527bbd;\r
+}\r
+\r
+table.tableblock.frame-topbot {\r
+  border-left-style: hidden;\r
+  border-right-style: hidden;\r
+}\r
+table.tableblock.frame-sides {\r
+  border-top-style: hidden;\r
+  border-bottom-style: hidden;\r
+}\r
+table.tableblock.frame-none {\r
+  border-style: hidden;\r
+}\r
+\r
+th.tableblock.halign-left, td.tableblock.halign-left {\r
+  text-align: left;\r
+}\r
+th.tableblock.halign-center, td.tableblock.halign-center {\r
+  text-align: center;\r
+}\r
+th.tableblock.halign-right, td.tableblock.halign-right {\r
+  text-align: right;\r
+}\r
+\r
+th.tableblock.valign-top, td.tableblock.valign-top {\r
+  vertical-align: top;\r
+}\r
+th.tableblock.valign-middle, td.tableblock.valign-middle {\r
+  vertical-align: middle;\r
+}\r
+th.tableblock.valign-bottom, td.tableblock.valign-bottom {\r
+  vertical-align: bottom;\r
+}\r
+\r
+\r
+/*\r
+ * manpage specific\r
+ *\r
+ * */\r
+\r
+body.manpage h1 {\r
+  padding-top: 0.5em;\r
+  padding-bottom: 0.5em;\r
+  border-top: 2px solid silver;\r
+  border-bottom: 2px solid silver;\r
+}\r
+body.manpage h2 {\r
+  border-style: none;\r
+}\r
+body.manpage div.sectionbody {\r
+  margin-left: 3em;\r
+}\r
+\r
+@media print {\r
+  body.manpage div#toc { display: none; }\r
+}\r
+\r
+\r
+</style>\r
+<script type="text/javascript">\r
+/*<![CDATA[*/\r
+var asciidoc = {  // Namespace.\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+// Table Of Contents generator\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+/* Author: Mihai Bazon, September 2002\r
+ * http://students.infoiasi.ro/~mishoo\r
+ *\r
+ * Table Of Content generator\r
+ * Version: 0.4\r
+ *\r
+ * Feel free to use this script under the terms of the GNU General Public\r
+ * License, as long as you do not remove or alter this notice.\r
+ */\r
+\r
+ /* modified by Troy D. Hanson, September 2006. License: GPL */\r
+ /* modified by Stuart Rackham, 2006, 2009. License: GPL */\r
+\r
+// toclevels = 1..4.\r
+toc: function (toclevels) {\r
+\r
+  function getText(el) {\r
+    var text = "";\r
+    for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+      if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.\r
+        text += i.data;\r
+      else if (i.firstChild != null)\r
+        text += getText(i);\r
+    }\r
+    return text;\r
+  }\r
+\r
+  function TocEntry(el, text, toclevel) {\r
+    this.element = el;\r
+    this.text = text;\r
+    this.toclevel = toclevel;\r
+  }\r
+\r
+  function tocEntries(el, toclevels) {\r
+    var result = new Array;\r
+    var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');\r
+    // Function that scans the DOM tree for header elements (the DOM2\r
+    // nodeIterator API would be a better technique but not supported by all\r
+    // browsers).\r
+    var iterate = function (el) {\r
+      for (var i = el.firstChild; i != null; i = i.nextSibling) {\r
+        if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {\r
+          var mo = re.exec(i.tagName);\r
+          if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {\r
+            result[result.length] = new TocEntry(i, getText(i), mo[1]-1);\r
+          }\r
+          iterate(i);\r
+        }\r
+      }\r
+    }\r
+    iterate(el);\r
+    return result;\r
+  }\r
+\r
+  var toc = document.getElementById("toc");\r
+  if (!toc) {\r
+    return;\r
+  }\r
+\r
+  // Delete existing TOC entries in case we're reloading the TOC.\r
+  var tocEntriesToRemove = [];\r
+  var i;\r
+  for (i = 0; i < toc.childNodes.length; i++) {\r
+    var entry = toc.childNodes[i];\r
+    if (entry.nodeName.toLowerCase() == 'div'\r
+     && entry.getAttribute("class")\r
+     && entry.getAttribute("class").match(/^toclevel/))\r
+      tocEntriesToRemove.push(entry);\r
+  }\r
+  for (i = 0; i < tocEntriesToRemove.length; i++) {\r
+    toc.removeChild(tocEntriesToRemove[i]);\r
+  }\r
+\r
+  // Rebuild TOC entries.\r
+  var entries = tocEntries(document.getElementById("content"), toclevels);\r
+  for (var i = 0; i < entries.length; ++i) {\r
+    var entry = entries[i];\r
+    if (entry.element.id == "")\r
+      entry.element.id = "_toc_" + i;\r
+    var a = document.createElement("a");\r
+    a.href = "#" + entry.element.id;\r
+    a.appendChild(document.createTextNode(entry.text));\r
+    var div = document.createElement("div");\r
+    div.appendChild(a);\r
+    div.className = "toclevel" + entry.toclevel;\r
+    toc.appendChild(div);\r
+  }\r
+  if (entries.length == 0)\r
+    toc.parentNode.removeChild(toc);\r
+},\r
+\r
+\r
+/////////////////////////////////////////////////////////////////////\r
+// Footnotes generator\r
+/////////////////////////////////////////////////////////////////////\r
+\r
+/* Based on footnote generation code from:\r
+ * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html\r
+ */\r
+\r
+footnotes: function () {\r
+  // Delete existing footnote entries in case we're reloading the footnodes.\r
+  var i;\r
+  var noteholder = document.getElementById("footnotes");\r
+  if (!noteholder) {\r
+    return;\r
+  }\r
+  var entriesToRemove = [];\r
+  for (i = 0; i < noteholder.childNodes.length; i++) {\r
+    var entry = noteholder.childNodes[i];\r
+    if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")\r
+      entriesToRemove.push(entry);\r
+  }\r
+  for (i = 0; i < entriesToRemove.length; i++) {\r
+    noteholder.removeChild(entriesToRemove[i]);\r
+  }\r
+\r
+  // Rebuild footnote entries.\r
+  var cont = document.getElementById("content");\r
+  var spans = cont.getElementsByTagName("span");\r
+  var refs = {};\r
+  var n = 0;\r
+  for (i=0; i<spans.length; i++) {\r
+    if (spans[i].className == "footnote") {\r
+      n++;\r
+      var note = spans[i].getAttribute("data-note");\r
+      if (!note) {\r
+        // Use [\s\S] in place of . so multi-line matches work.\r
+        // Because JavaScript has no s (dotall) regex flag.\r
+        note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];\r
+        spans[i].innerHTML =\r
+          "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +\r
+          "' title='View footnote' class='footnote'>" + n + "</a>]";\r
+        spans[i].setAttribute("data-note", note);\r
+      }\r
+      noteholder.innerHTML +=\r
+        "<div class='footnote' id='_footnote_" + n + "'>" +\r
+        "<a href='#_footnoteref_" + n + "' title='Return to text'>" +\r
+        n + "</a>. " + note + "</div>";\r
+      var id =spans[i].getAttribute("id");\r
+      if (id != null) refs["#"+id] = n;\r
+    }\r
+  }\r
+  if (n == 0)\r
+    noteholder.parentNode.removeChild(noteholder);\r
+  else {\r
+    // Process footnoterefs.\r
+    for (i=0; i<spans.length; i++) {\r
+      if (spans[i].className == "footnoteref") {\r
+        var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");\r
+        href = href.match(/#.*/)[0];  // Because IE return full URL.\r
+        n = refs[href];\r
+        spans[i].innerHTML =\r
+          "[<a href='#_footnote_" + n +\r
+          "' title='View footnote' class='footnote'>" + n + "</a>]";\r
+      }\r
+    }\r
+  }\r
+},\r
+\r
+install: function(toclevels) {\r
+  var timerId;\r
+\r
+  function reinstall() {\r
+    asciidoc.footnotes();\r
+    if (toclevels) {\r
+      asciidoc.toc(toclevels);\r
+    }\r
+  }\r
+\r
+  function reinstallAndRemoveTimer() {\r
+    clearInterval(timerId);\r
+    reinstall();\r
+  }\r
+\r
+  timerId = setInterval(reinstall, 500);\r
+  if (document.addEventListener)\r
+    document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);\r
+  else\r
+    window.onload = reinstallAndRemoveTimer;\r
+}\r
+\r
+}\r
+asciidoc.install();\r
+/*]]>*/\r
+</script>\r
+</head>\r
+<body class="manpage">\r
+<div id="header">\r
+<h1>\r
+nvme-toshiba-vs-smart-add-log(1) Manual Page\r
+</h1>\r
+<h2>NAME</h2>\r
+<div class="sectionbody">\r
+<p>nvme-toshiba-vs-smart-add-log -\r
+   Retrieve a Toshiba device's vendor specific extended SMART log page contents and either save to file or dump the contents.\r
+</p>\r
+</div>\r
+</div>\r
+<div id="content">\r
+<div class="sect1">\r
+<h2 id="_synopsis">SYNOPSIS</h2>\r
+<div class="sectionbody">\r
+<div class="verseblock">\r
+<pre class="content">'nvme toshiba vs-smart-add-log ' &lt;device&gt; [--log=&lt;NUM&gt;, -l &lt;NUM&gt;]\r
+                [--namespace-id=&lt;NUM&gt;, -n &lt;NUM&gt;]\r
+                [--output-file=&lt;FILE&gt;, -o &lt;FILE&gt;]</pre>\r
+<div class="attribution">\r
+</div></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_description">DESCRIPTION</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>For the NVMe device given, sends the Toshiba vendor log\r
+request and either saves the result to a file or dumps the content to stdout.</p></div>\r
+<div class="paragraph"><p>The &lt;device&gt; parameter is mandatory and may be either the NVMe\r
+character device (ex: /dev/nvme0), or a namespace block device (ex:\r
+/dev/nvme0n1).</p></div>\r
+<div class="paragraph"><p>The log contents may be associated with the controller, in which case the namespace parameter is ignored.</p></div>\r
+<div class="paragraph"><p>Two logs exist, page 0xC0 (log page directory) and page 0xCA (vendor log page)</p></div>\r
+<div class="paragraph"><p>This will only work on Toshiba devices supporting this feature.</p></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_options">OPTIONS</h2>\r
+<div class="sectionbody">\r
+<div class="dlist"><dl>\r
+<dt class="hdlist1">\r
+-l &lt;NUM&gt;\r
+</dt>\r
+<dt class="hdlist1">\r
+--log=&lt;NUM&gt;\r
+</dt>\r
+<dd>\r
+<p>\r
+        Log page: 0xC0 or 0xCA  (defaults to 0xCA)\r
+</p>\r
+</dd>\r
+<dt class="hdlist1">\r
+-n &lt;NUM&gt;\r
+</dt>\r
+<dt class="hdlist1">\r
+--namespace-id=&lt;NUM&gt;\r
+</dt>\r
+<dt class="hdlist1">\r
+-o &lt;FILE&gt;\r
+</dt>\r
+<dt class="hdlist1">\r
+--output-file=&lt;FILE&gt;\r
+</dt>\r
+<dd>\r
+<p>\r
+        Output binary file. Defaults to text-formatted dump to stdout\r
+</p>\r
+</dd>\r
+</dl></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_examples">EXAMPLES</h2>\r
+<div class="sectionbody">\r
+<div class="ulist"><ul>\r
+<li>\r
+<p>\r
+Get the current log from the device and dumps it to stdout:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme toshiba vs-smart-add-log /dev/nvme0</code></pre>\r
+</div></div>\r
+</li>\r
+<li>\r
+<p>\r
+Get the contents of log page 0xC0 from the device and save to a binary file:\r
+</p>\r
+<div class="listingblock">\r
+<div class="content">\r
+<pre><code># nvme toshiba vs-smart-add-log /dev/nvme0 --output-file=log.bin --log=0xC0</code></pre>\r
+</div></div>\r
+</li>\r
+</ul></div>\r
+</div>\r
+</div>\r
+<div class="sect1">\r
+<h2 id="_nvme">NVME</h2>\r
+<div class="sectionbody">\r
+<div class="paragraph"><p>Part of the nvme-user suite</p></div>\r
+</div>\r
+</div>\r
+</div>\r
+<div id="footnotes"><hr /></div>\r
+<div id="footer">\r
+<div id="footer-text">\r
+Last updated\r
+ 2018-03-07 13:58:54 CET\r
+</div>\r
+</div>\r
+</body>\r
+</html>\r
diff --git a/Documentation/nvme-toshiba-vs-smart-add-log.txt b/Documentation/nvme-toshiba-vs-smart-add-log.txt
new file mode 100644 (file)
index 0000000..8ea4d3e
--- /dev/null
@@ -0,0 +1,64 @@
+nvme-toshiba-vs-smart-add-log(1)
+================================
+
+NAME
+----
+nvme-toshiba-vs-smart-add-log - Retrieve a Toshiba device's vendor specific extended SMART log page contents and either save to file or dump the contents.
+
+SYNOPSIS
+--------
+[verse]
+'nvme toshiba vs-smart-add-log ' <device> [--log=<NUM>, -l <NUM>]
+               [--namespace-id=<NUM>, -n <NUM>]
+               [--output-file=<FILE>, -o <FILE>]
+
+
+DESCRIPTION
+-----------
+For the NVMe device given, sends the Toshiba vendor log
+request and either saves the result to a file or dumps the content to stdout.
+
+The <device> parameter is mandatory and may be either the NVMe
+character device (ex: /dev/nvme0), or a namespace block device (ex:
+/dev/nvme0n1). 
+
+The log contents may be associated with the controller, in which case the namespace parameter is ignored.
+
+Two logs exist, page 0xC0 (log page directory) and page 0xCA (vendor log page)
+
+This will only work on Toshiba devices supporting this feature.
+
+OPTIONS
+-------
+
+-l <NUM>::
+--log=<NUM>::
+       Log page: 0xC0 or 0xCA  (defaults to 0xCA)
+
+-n <NUM>::
+--namespace-id=<NUM>::
+
+-o <FILE>::
+--output-file=<FILE>::
+       Output binary file. Defaults to text-formatted dump to stdout
+
+
+
+EXAMPLES
+--------
+* Get the current log from the device and dumps it to stdout:
++
+------------
+# nvme toshiba vs-smart-add-log /dev/nvme0 
+------------
++
+
+* Get the contents of log page 0xC0 from the device and save to a binary file:
++
+------------
+# nvme toshiba vs-smart-add-log /dev/nvme0 --output-file=log.bin --log=0xC0
+------------
+
+NVME
+----
+Part of the nvme-user suite
diff --git a/toshiba-nvme.c b/toshiba-nvme.c
new file mode 100644 (file)
index 0000000..a3b6c13
--- /dev/null
@@ -0,0 +1,639 @@
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/fs.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <stdbool.h>
+
+#include "linux/nvme_ioctl.h"
+#include "nvme.h"
+#include "nvme-print.h"
+#include "nvme-ioctl.h"
+#include "plugin.h"
+#include "argconfig.h"
+#include "suffix.h"
+
+#define CREATE_CMD
+#include "toshiba-nvme.h"
+
+static const __u32 OP_SCT_STATUS = 0xE0;
+static const __u32 OP_SCT_COMMAND_TRANSFER = 0xE0;
+static const __u32 OP_SCT_DATA_TRANSFER = 0xE1;
+
+static const __u32 DW10_SCT_STATUS_COMMAND = 0x0;
+static const __u32 DW10_SCT_COMMAND_TRANSFER = 0x1;
+
+static const __u32 DW11_SCT_STATUS_COMMAND = 0x0;
+static const __u32 DW11_SCT_COMMAND_TRANSFER = 0x0;
+
+static const __u16 INTERNAL_LOG_ACTION_CODE = 0xFFFB;
+static const __u16 CURRENT_LOG_FUNCTION_CODE = 0x0001;
+static const __u16 SAVED_LOG_FUNCTION_CODE = 0x0002;
+
+// A bitmask field for supported devices
+typedef enum {
+       MASK_0    = 1 << 0,
+       MASK_1    = 1 << 1,
+       // Future devices can use the remaining 31 bits from this field
+       // and should use 1 << 2, 1 << 3, etc.
+       MASK_IGNORE = 0
+} DeviceMask;
+
+// Internal device codes
+typedef enum {
+       CODE_0 = 0x0D,
+       CODE_1 = 0x10
+} DeviceCode;
+
+
+static int nvme_sct_op(int fd,  __u32 opcode, __u32 cdw10, __u32 cdw11, void* data, __u32 data_len )
+{
+       void  *metadata = NULL;
+       const __u32 cdw2 = 0;
+       const __u32 cdw3 = 0;
+       const __u32 cdw12 = 0;
+       const __u32 cdw13 = 0;
+       const __u32 cdw14 = 0;
+       const __u32 cdw15 = 0;
+       const __u32 timeout = 0;
+       const __u32 metadata_len = 0;
+       const __u32 namespace_id = 0x0;
+       const __u32 flags = 0;
+       const __u32 rsvd = 0;
+       int err = 0;
+       __u32 result;
+       err = nvme_passthru(fd, NVME_IOCTL_ADMIN_CMD, opcode, flags, rsvd,
+                               namespace_id, cdw2, cdw3, cdw10,
+                               cdw11, cdw12, cdw13, cdw14, cdw15,
+                               data_len, data, metadata_len, metadata,
+                               timeout, &result);
+       return err;
+}
+
+static int nvme_get_sct_status(int fd, __u32 device_mask)
+{
+       int err;
+       void* data = NULL;
+       size_t data_len = 512;
+       if (posix_memalign(&data, getpagesize(), data_len)) {
+               err = ENOMEM;
+               goto end;
+       }
+       memset(data, 0, data_len);
+       err = nvme_sct_op(fd, OP_SCT_STATUS, DW10_SCT_STATUS_COMMAND, DW11_SCT_STATUS_COMMAND, data, data_len);
+       if (err) {
+               fprintf(stderr, "%s: SCT status failed :%d\n", __func__, err);
+               goto end;
+       }
+       const unsigned char* status = data;
+       if (status[0] != 1U) {
+               // Eek, wrong version in status header
+               fprintf(stderr, "%s: unexpected value in SCT status[0]:(%x)\n", __func__, status[0]);
+               err = -1;
+               errno = EINVAL;
+               goto end;
+       }
+
+       // Check if device is supported
+       if (device_mask != MASK_IGNORE) {
+               __u32 supported = 0;
+               switch (status[1]) {
+               case CODE_0:
+                       supported = (device_mask & MASK_0);
+                       break;
+
+               case CODE_1:
+                       supported = (device_mask & MASK_1);
+                       break;
+
+               default:
+                       break;
+               };
+               if (0 == supported) {
+                       fprintf(stderr, "%s: command unsupported on this device: (0x%x)\n",__func__, status[1]);
+                       err = -1;
+                       errno = EINVAL;
+                       goto end;
+               }
+       }
+end:
+       if (data) {
+               free(data);
+       }
+       return err;
+}
+
+static int nvme_sct_command_transfer_log(int fd, bool current)
+{
+       __u16 action_code = INTERNAL_LOG_ACTION_CODE;
+       __u16 function_code;
+       if (current) {
+               function_code = CURRENT_LOG_FUNCTION_CODE;
+       } else {
+               function_code = SAVED_LOG_FUNCTION_CODE;
+       }
+       int err;
+       void* data = NULL;
+       size_t data_len = 512;
+       if (posix_memalign(&data, getpagesize(), data_len)) {
+               err = ENOMEM;
+               goto end;
+       }
+       memset(data, 0, data_len);
+       memcpy(data, &action_code, sizeof(action_code));
+       memcpy(data + 2, &function_code, sizeof(function_code));
+
+       err = nvme_sct_op(fd, OP_SCT_COMMAND_TRANSFER, DW10_SCT_COMMAND_TRANSFER, DW11_SCT_COMMAND_TRANSFER, data, data_len);
+       return err;
+end:
+       if (data) {
+               free(data);
+       }
+       return err;
+}
+
+static int nvme_sct_data_transfer(int fd, void* data, size_t data_len, size_t offset)
+{
+       __u32 lba_count = (data_len) / 512;
+       if (lba_count) {
+               // the count is a 0-based value, which seems to mean
+               // that it's actually last lba
+               --lba_count;
+       }
+
+       __u32 dw10 = (offset << 16) | lba_count;
+       __u32 dw11 = (offset >> 16);
+       return nvme_sct_op(fd, OP_SCT_DATA_TRANSFER, dw10, dw11, data, data_len);
+}
+
+static int d_raw_to_fd(const unsigned char *buf, unsigned len, int fd)
+{
+       int written = 0;
+       int remaining = len;
+       while (remaining) {
+               written = write(fd, buf, remaining);
+               if (written < 0) {
+                       remaining = written;
+                       break;
+               } else if (written <= remaining) {
+                       remaining -= written;
+               } else {
+                       // Unexpected overwrite
+                       break;
+               }
+       }
+       // return 0 on success or remaining/error
+       return remaining;
+}
+
+// Display progress (incoming 0->1.0)
+static void progress_runner(float progress)
+{
+    const size_t barWidth = 70;
+
+    fprintf(stdout, "[");
+    size_t pos = barWidth * progress;
+    for (size_t i = 0; i < barWidth; ++i) {
+        if (i <= pos) {
+               fprintf(stdout, "=");
+        } else {
+               fprintf(stdout, " ");
+        }
+    }
+       fprintf(stdout, "] %d %%\r",(int)(progress * 100.0));
+       fflush(stdout);
+}
+
+static int nvme_get_internal_log(int fd, const char* const filename, bool current)
+{
+       int err;
+       int o_fd = -1;
+       void* page_data = NULL;
+       const size_t page_sector_len = 32;
+       const size_t page_data_len = page_sector_len * 512;// 32 sectors per page
+       // By trial and error it seems that the largest transfer chunk size
+       // is 128 * 32 =  4k sectors = 2MB
+       const __u32 max_pages = 128;
+       err = nvme_sct_command_transfer_log(fd, current);
+       if (err) {
+               fprintf(stderr, "%s: SCT command transfer failed\n", __func__);
+               goto end;
+       }
+       if (posix_memalign(&page_data, getpagesize(), max_pages * page_data_len)) {
+               err = ENOMEM;
+               goto end;
+       }
+       memset(page_data, 0, max_pages * page_data_len);
+       // Read the header to get the last log page - offsets 8->11, 12->15, 16->19
+       err = nvme_sct_data_transfer(fd, page_data, page_data_len, 0);
+       if (err) {
+               fprintf(stderr, "%s: SCT data transfer failed, page 0\n",__func__);
+               goto end;
+       }
+       const uint32_t* area1_last_page = (const uint32_t*) (page_data + 8);
+       const uint32_t* area2_last_page = (const uint32_t*) (page_data + 12);
+       const uint32_t* area3_last_page = (const uint32_t*) (page_data + 16);
+       uint32_t log_sectors = 0;
+       // The number of total log sectors is the maximum + 1;
+       if (*area1_last_page > log_sectors) {
+               log_sectors = *area1_last_page;
+       }
+       if (*area2_last_page > log_sectors) {
+               log_sectors = *area2_last_page;
+       }
+       if (*area3_last_page > log_sectors) {
+               log_sectors = *area3_last_page;
+       }
+       ++log_sectors;
+       const size_t pages = log_sectors / page_sector_len;
+       float progress = 0.0;
+       if (filename == NULL) {
+               fprintf(stdout, "Page: %u of %zu\n", 0u, pages);
+               d(page_data, page_data_len, 16, 1);
+       } else {
+               progress_runner(progress);
+               o_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+               if (o_fd < 0) {
+                       fprintf(stderr, "%s: couldn't output file %s\n", __func__, filename);
+                       err = EINVAL;
+                       goto end;
+               }
+               err = d_raw_to_fd(page_data, page_data_len, o_fd);
+               if (err) {
+                       fprintf(stderr, "%s: couldn't write all data to output file\n", __func__);
+                       goto end;
+               }
+       }
+       // Now read the rest
+       for (size_t i = 1; i < pages;) {
+               __u32 pages_chunk = max_pages;
+               if (pages_chunk + i >= pages) {
+                       pages_chunk = pages - i;
+               }
+               err = nvme_sct_data_transfer(fd, page_data, pages_chunk * page_data_len, i * page_sector_len);
+               if (err) {
+                       fprintf(stderr, "%s: SCT data transfer command failed\n", __func__);
+                       goto end;
+               }
+               progress = (float) (i) / (float) (pages);
+               progress_runner(progress);
+               if (filename == NULL) {
+                       for (unsigned j = 0; j < pages_chunk; ++j) {
+                               fprintf(stdout, "Page: %zu of %zu\n", i + j, pages);
+                               d(page_data + (j * page_data_len), page_data_len, 16, 1);
+                       }
+               } else {
+                       progress_runner(progress);
+                       err = d_raw_to_fd(page_data, pages_chunk * page_data_len, o_fd);
+                       if (err) {
+                               fprintf(stderr, "%s: couldn't write all data to output file\n", __func__);
+                               goto end;
+                       }
+               }
+               i += pages_chunk;
+       }
+       progress = 1.0f;
+       progress_runner(progress);
+       fprintf(stdout,"\n");
+       err = nvme_get_sct_status(fd, MASK_IGNORE);
+       if (err) {
+               fprintf(stderr, "%s: bad SCT status\n", __func__);
+               goto end;
+       }
+end:
+       if (o_fd >= 0) {
+               close(o_fd);
+       }
+       if (page_data) {
+               free(page_data);
+       }
+       return err;
+}
+
+static int nvme_get_internal_log_file(int fd, const char* const filename, bool current)
+{
+       int err;
+       // Check device supported
+       err = nvme_get_sct_status(fd, MASK_0 | MASK_1);
+       if (!err) {
+               err = nvme_get_internal_log(fd, filename, current);
+       }
+       return err;
+}
+
+enum LOG_PAGE_C0 {
+       ERROR_LOG_C0 = 0,
+       SMART_HEALTH_LOG_C0,
+       FIRMWARE_SLOT_INFO_C0,
+       COMMAND_EFFECTS_C0,
+       DEVICE_SELF_TEST_C0,
+       LOG_PAGE_DIRECTORY_C0,
+       SMART_ATTRIBUTES_C0,
+       NR_SMART_ITEMS_C0,
+};
+
+struct nvme_xdn_smart_log_c0 {
+       __u8 items[NR_SMART_ITEMS_C0];
+       __u8 resv[512 - NR_SMART_ITEMS_C0];
+};
+
+enum LOG_PAGE_CA {
+       PHYSICAL_NAND_BYTES_WRITTEN_CA = 0,
+       PHYSICAL_NAND_BYTES_READ_CA = 16,
+       BAD_NAND_BLOCK_COUNT_CA = 32,
+       UNCORRECTABLE_READ_ERROR_COUNT_CA = 40,
+       SOFT_ECC_ERROR_COUNT_CA = 48,
+       SDD_END_TO_END_CORRECTION_COUNTS_CA = 56,
+       SYSTEM_DATA_USED_CA = 64,
+       USER_DATA_ERASE_COUNTS_CA = 65,
+       REFRESH_COUNT_CA = 73,
+       PROGRAM_FAIL_COUNT_CA = 81,
+       USER_ERASE_FAIL_COUNT_CA = 89,
+       SYSTEM_AREA_ERASE_FAIL_COUNT_CA = 97,
+       THERMAL_THROTTLING_STATUS_CA = 105,
+       THERMAL_THROTTLING_COUNT_CA = 106,
+       PCIE_CORRECTABLE_ERROR_COUNT_CA = 107,
+       INCOMPLETE_SHUTDOWNS_CA = 115,
+       FREE_BLOCKS_NORMALISED_CA = 119,
+
+       NR_SMART_ITEMS_CA = 120,
+};
+
+struct nvme_xdn_smart_log_ca {
+       __u8 items[NR_SMART_ITEMS_CA];
+       __u8 resv[512 - NR_SMART_ITEMS_CA];
+};
+
+static unsigned long uint_n_to_ulong(__u8 *data, size_t length)
+{
+       unsigned long result = 0;
+       for (size_t i = 0; i < length; i++) {
+               result *= 256;
+               result += data[(length -1) - i];
+       }
+       return result;
+}
+
+static float uint_n_to_float(__u8 *data, size_t length)
+{
+       float result = 0;
+       for (size_t i = 0; i < length; i++) {
+               result *= 256.0;
+               result += data[(length -1) - i];
+       }
+       return result;
+}
+
+static const char* UNITS_B = "B";
+static const char* UNITS_KB = "KiB";
+static const char* UNITS_MB = "MiB";
+static const char* UNITS_GB = "GiB";
+
+static float to_readable_units(float raw_bytes, const char** units)
+{
+       *units = UNITS_B;
+       float scaled_units = raw_bytes;
+       if (scaled_units > 102400.0) { // Switch to KiB above 100 KiB
+               scaled_units /= 1024.0; // Now in KiB.
+               *units = UNITS_KB;
+       }
+       if (scaled_units > 102400.0) { // Switch to MiB above 100 MiB
+               scaled_units /= 1024.0; // Now in MiB.
+               *units = UNITS_MB;
+       }
+       if (scaled_units > 102400.0) { //Switch to GiB above 100 GiB
+               scaled_units /= 1024.0; // Now in GiB.
+               *units = UNITS_GB;
+       }
+       return scaled_units;
+}
+
+static void default_show_vendor_log_c0(int fd, __u32 nsid, const char *devname,
+               struct nvme_xdn_smart_log_c0 *smart)
+{
+       printf("Vendor Log Page Directory 0xC0 for NVME device:%s namespace-id:%x\n", devname, nsid);
+       printf("Error Log          : %u \n", smart->items[ERROR_LOG_C0]);
+       printf("SMART Health Log   : %u \n", smart->items[SMART_HEALTH_LOG_C0]);
+       printf("Firmware Slot Info : %u \n", smart->items[FIRMWARE_SLOT_INFO_C0]);
+       printf("Command Effects    : %u \n", smart->items[COMMAND_EFFECTS_C0]);
+       printf("Device Self Test   : %u \n", smart->items[DEVICE_SELF_TEST_C0]);
+       printf("Log Page Directory : %u \n", smart->items[LOG_PAGE_DIRECTORY_C0]);
+       printf("SMART Attributes   : %u \n", smart->items[SMART_ATTRIBUTES_C0]);
+}
+
+static void default_show_vendor_log_ca(int fd, __u32 nsid, const char *devname,
+               struct nvme_xdn_smart_log_ca *smart)
+{
+       printf("Vendor Log Page 0xCA for NVME device:%s namespace-id:%x\n", devname, nsid);
+       const char* units;
+       float media_units;
+       media_units = uint_n_to_float(&smart->items[PHYSICAL_NAND_BYTES_WRITTEN_CA], 16); // units are bytes
+       media_units = to_readable_units(media_units, &units);
+       printf("Total data written to NAND               : %.1f %s\n", media_units, units);
+       media_units = uint_n_to_float(&smart->items[PHYSICAL_NAND_BYTES_READ_CA], 16); // units are bytes
+       media_units = to_readable_units(media_units, &units);
+       printf("Total data read from NAND                : %.1f %s\n", media_units, units);
+       printf("Bad NAND Block Count (Normalised)        : %lu\n", uint_n_to_ulong(&smart->items[BAD_NAND_BLOCK_COUNT_CA], 2));
+       printf("Bad NAND Block Count (Raw)               : %lu\n", uint_n_to_ulong(&smart->items[BAD_NAND_BLOCK_COUNT_CA+2], 6));
+       printf("Uncorrectable Read Error Count           : %lu\n", uint_n_to_ulong(&smart->items[UNCORRECTABLE_READ_ERROR_COUNT_CA], 8));
+       printf("Soft ECC Error Count                     : %lu\n", uint_n_to_ulong(&smart->items[SOFT_ECC_ERROR_COUNT_CA], 8));
+       printf("End-to-end Error Count (Detected)        : %lu\n", uint_n_to_ulong(&smart->items[SDD_END_TO_END_CORRECTION_COUNTS_CA], 4));
+       printf("End-to-end Error Count (Corrected)       : %lu\n", uint_n_to_ulong(&smart->items[SDD_END_TO_END_CORRECTION_COUNTS_CA + 4], 4));
+       printf("System Data Used                         : %u %%\n", smart->items[SYSTEM_DATA_USED_CA]);
+       printf("User Data Erase Count (Max)              : %lu\n", uint_n_to_ulong(&smart->items[USER_DATA_ERASE_COUNTS_CA], 4));
+       printf("User Data Erase Count (Min)              : %lu\n", uint_n_to_ulong(&smart->items[USER_DATA_ERASE_COUNTS_CA + 4], 4));
+       printf("Refresh Count                            : %lu\n", uint_n_to_ulong(&smart->items[REFRESH_COUNT_CA], 8));
+       printf("Program Fail Count (Normalised)          : %lu\n", uint_n_to_ulong(&smart->items[PROGRAM_FAIL_COUNT_CA], 2));
+       printf("Program Fail Count (Raw)                 : %lu\n", uint_n_to_ulong(&smart->items[PROGRAM_FAIL_COUNT_CA + 2], 6));
+       printf("User Data Erase Fail Count (Normalised)  : %lu\n", uint_n_to_ulong(&smart->items[USER_ERASE_FAIL_COUNT_CA], 2));
+       printf("User Data Erase Fail Count (Raw)         : %lu\n", uint_n_to_ulong(&smart->items[USER_ERASE_FAIL_COUNT_CA + 2], 6));
+       printf("System Area Erase Fail Count (Normalised): %lu\n", uint_n_to_ulong(&smart->items[SYSTEM_AREA_ERASE_FAIL_COUNT_CA], 2));
+       printf("System Area Erase Fail Count (Raw)       : %lu\n", uint_n_to_ulong(&smart->items[SYSTEM_AREA_ERASE_FAIL_COUNT_CA + 2], 6));
+       printf("Thermal Throttling Status                : %u \n", smart->items[THERMAL_THROTTLING_STATUS_CA]);
+       printf("Thermal Throttling Count                 : %u \n", smart->items[THERMAL_THROTTLING_COUNT_CA]);
+       printf("PCIe Correctable Error Count             : %lu\n", uint_n_to_ulong(&smart->items[PCIE_CORRECTABLE_ERROR_COUNT_CA], 8));
+       printf("Incomplete Shutdowns                     : %lu\n", uint_n_to_ulong(&smart->items[INCOMPLETE_SHUTDOWNS_CA], 4));
+       printf("Free blocks                              : %u %%\n", smart->items[FREE_BLOCKS_NORMALISED_CA]);
+}
+
+static int nvme_get_vendor_log(int fd, __u32 namespace_id, int log_page, const char* const filename)
+{
+       int err;
+       void* log = NULL;
+       size_t log_len = 512;
+       if (posix_memalign(&log, getpagesize(), log_len)) {
+               err = ENOMEM;
+               goto end;
+       }
+       // Check device supported
+       err = nvme_get_sct_status(fd, MASK_0 | MASK_1);
+       if (err) {
+               goto end;
+       }
+       err = nvme_get_log(fd, namespace_id, log_page,
+                   log_len, log);
+       if (err) {
+               fprintf(stderr, "%s: couldn't get log 0x%x\n", __func__, log_page);
+               goto end;
+       }
+       if (filename) {
+               int o_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+
+               if (o_fd < 0) {
+                       fprintf(stderr, "%s: couldn't output file %s\n", __func__, filename);
+                       err = EINVAL;
+                       goto end;
+               }
+               err = d_raw_to_fd(log, log_len, o_fd);
+               if (err) {
+                       fprintf(stderr, "%s: couldn't write all data to output file %s\n", __func__, filename);
+                       // Attempt following close
+               }
+               if (close(o_fd)) {
+                       err = errno;
+                       goto end;
+               }
+       } else {
+               if (log_page == 0xc0) {
+                       default_show_vendor_log_c0(fd, namespace_id, devicename, (struct nvme_xdn_smart_log_c0 *)log);
+               } else if (log_page == 0xca) {
+                       default_show_vendor_log_ca(fd, namespace_id, devicename, (struct nvme_xdn_smart_log_ca *)log);
+               } else {
+                       d(log, sizeof(log),16,1);
+               }
+       }
+end:
+       if (log) {
+               free(log);
+       }
+       return err;
+}
+
+static int vendor_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+       int err;
+       int fd;
+       char *desc = "Get extended SMART information and show it.";
+       const char *namespace = "(optional) desired namespace";
+       const char *output_file = "(optional) binary output filename";
+       const char *log = "(optional) log ID (0xC0, or 0xCA), default 0xCA";
+       struct config {
+               __u32 namespace_id;
+               const char* output_file;
+               int log;
+       };
+       struct config cfg = {
+               .namespace_id = 0xffffffff,
+               .output_file = NULL,
+               .log = 0xca
+       };
+       const struct argconfig_commandline_options command_line_options[] = {
+               {"namespace-id", 'n', "NUM",  CFG_POSITIVE, &cfg.namespace_id, required_argument, namespace},
+               {"output-file",  'o', "FILE", CFG_STRING,   &cfg.output_file,  required_argument, output_file},
+               {"log",          'l', "NUM",  CFG_POSITIVE, &cfg.log,          required_argument, log},
+               {NULL}
+       };
+       fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg));
+       if (fd < 0) {
+               fprintf(stderr,"%s: failed to parse arguments\n", __func__);
+               err = EINVAL;
+               goto end;
+       }
+       if ((cfg.log != 0xC0) && (cfg.log != 0xCA)) {
+               fprintf(stderr, "%s: invalid log page 0x%x - should be 0xC0 or 0xCA\n", __func__, cfg.log);
+               err = EINVAL;
+               goto end;
+       }
+       err = nvme_get_vendor_log(fd, cfg.namespace_id, cfg.log, cfg.output_file);
+       if (err) {
+               fprintf(stderr, "%s: couldn't get vendor log 0x%x\n", __func__, cfg.log);
+               goto end;
+       }
+end:
+       if (err > 0) {
+               fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(err), err);
+       }
+       return err;
+}
+
+static int internal_log(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+       int err;
+       int fd;
+       char *desc = "Get internal status log and show it.";
+       const char *output_file = "(optional) binary output filename";
+       const char *prev_log = "(optional) use previous log. Otherwise uses current log.";
+       struct config {
+               const char* output_file;
+               bool prev_log;
+       };
+       struct config cfg = {
+               .output_file = NULL,
+               .prev_log = false
+       };
+       const struct argconfig_commandline_options command_line_options[] = {
+               {"output-file",  'o', "FILE", CFG_STRING,   &cfg.output_file, required_argument, output_file},
+               {"prev-log", 'p', "", CFG_NONE, &cfg.prev_log, no_argument, prev_log},
+               {NULL}
+       };
+       fd = parse_and_open(argc, argv, desc, command_line_options, &cfg, sizeof(cfg));
+       if (fd < 0) {
+               fprintf(stderr,"%s: failed to parse arguments\n", __func__);
+               err = EINVAL;
+               goto end;
+       }
+       if (cfg.prev_log) {
+               printf("Getting previous log\n");
+       } else {
+               printf("Getting current log\n");
+       }
+       err = nvme_get_internal_log_file(fd, cfg.output_file, !cfg.prev_log);
+       if (err) {
+               fprintf(stderr, "%s: couldn't get fw log \n", __func__);
+       }
+end:
+       if (err > 0) {
+               fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(err), err);
+       }
+       return err;
+}
+
+static int clear_correctable_errors(int argc, char **argv, struct command *cmd, struct plugin *plugin)
+{
+       int err;
+       int fd;
+       char *desc = "Clear PCIe correctable error count.";
+       const struct argconfig_commandline_options command_line_options[] = {
+               {NULL}
+       };
+       fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0);
+       if (fd < 0) {
+               fprintf(stderr,"%s: failed to parse arguments\n", __func__);
+               err = EINVAL;
+               goto end;
+       }
+       // Check device supported
+       err = nvme_get_sct_status(fd, MASK_0 | MASK_1);
+       if (err) {
+               goto end;
+       }
+       const __u32 namespace_id = 0xFFFFFFFF;
+       const __u32 feature_id = 0xCA;
+       const __u32 value = 1; // Bit0 - reset clear PCIe correctable count
+       const __u32 cdw12 = 0;
+       const bool save = false;
+       __u32 result;
+       err = nvme_set_feature(fd, namespace_id, feature_id, value, cdw12, save,
+                               0, NULL, &result);
+       if (err) {
+               fprintf(stderr, "%s: couldn't clear PCIe correctable errors \n", __func__);
+       }
+end:
+       if (err > 0) {
+               fprintf(stderr, "%s: NVMe Status:%s(%x)\n", __func__, nvme_status_to_string(err), err);
+       }
+       return err;
+}
diff --git a/toshiba-nvme.h b/toshiba-nvme.h
new file mode 100644 (file)
index 0000000..cecbbf3
--- /dev/null
@@ -0,0 +1,20 @@
+#undef CMD_INC_FILE
+#define CMD_INC_FILE toshiba-nvme
+
+#if !defined(TOSHIBA_NVME) || defined(CMD_HEADER_MULTI_READ)
+#define TOSHIBA_NVME
+
+#include "cmd.h"
+#include "plugin.h"
+
+PLUGIN(NAME("toshiba", "Toshiba NVME plugin"),
+    COMMAND_LIST(
+                       ENTRY("vs-smart-add-log", "Extended SMART information", vendor_log)
+                       ENTRY("vs-internal-log", "Get Internal Log", internal_log)
+                       ENTRY("clear-pcie-correctable-errors", "Clear PCIe correctable error count", clear_correctable_errors)
+    )
+);
+
+#endif
+
+#include "define_cmd.h"