--- /dev/null
--- /dev/null
++<!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.8" />\r
++<title>nvme-dera-stat(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
++\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; }\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
++/*<+'])');\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="article">\r
++<div id="header">\r
++<h1>nvme-dera-stat(1)</h1>\r
++</div>\r
++<div id="content">\r
++<div class="sect1">\r
++<h2 id="_name">NAME</h2>\r
++<div class="sectionbody">\r
++<div class="paragraph"><p>nvme-dera-stat - Send NVMe Dera Device status and Additional SMART log page request, returns result and log</p></div>\r
++</div>\r
++</div>\r
++<div class="sect1">\r
++<h2 id="_synopsis">SYNOPSIS</h2>\r
++<div class="sectionbody">\r
++<div class="verseblock">\r
++<pre class="content"><em>nvme dera stat</em> <device></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>Retrieves the NVMe Dera Device status and Additional SMART log page from the device and\r
++provides the returned structure.</p></div>\r
++<div class="paragraph"><p>The <device> parameter is mandatory and may be either the NVMe character\r
++device (ex: /dev/nvme0), or a namespace block device (ex: /dev/nvme0n1).</p></div>\r
++<div class="paragraph"><p>On success, the returned status and smart log structure are printed in a readable format.</p></div>\r
++</div>\r
++</div>\r
++<div class="sect1">\r
++<h2 id="_options">OPTIONS</h2>\r
++<div class="sectionbody">\r
++<div class="paragraph"><p>none</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
++Print the Dera Device status and Additional SMART log page in a human readable format:\r
++</p>\r
++<div class="listingblock">\r
++<div class="content">\r
++<pre><code># nvme dera stat /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 2019-11-26 13:57:30 CST\r
++</div>\r
++</div>\r
++</body>\r
++</html>\r
--- /dev/null
- #include <fcntl.h>\r
- #include <errno.h>\r
- #include <stdio.h>\r
- #include <stdlib.h>\r
- #include <unistd.h>\r
- #include <string.h>\r
- #include <dirent.h> \r
- #include <ctype.h> \r
- #include <sys/stat.h>\r
- #include <sys/time.h>\r
- \r
- #include "nvme.h"\r
- #include "nvme-print.h"\r
- #include "nvme-ioctl.h"\r
- #include "plugin.h"\r
- \r
- #include "argconfig.h"\r
- #include "suffix.h"\r
- \r
- #define CREATE_CMD\r
- #include "dera-nvme.h"\r
- \r
- static int char4_to_int(__u8 *data)\r
- {\r
- int i;\r
- int result = 0;\r
- \r
- for (i = 0; i < 4; i++) {\r
- result = result << 8;\r
- result += data[3 - i];\r
- }\r
- return result;\r
- }\r
- \r
- struct nvme_dera_smart_info_log\r
- {\r
- __u8 quick_rebuild_cnt0[4]; \r
- __u8 quick_rebuild_cnt1[4]; \r
- __u8 full_rebuild_cnt0[4];\r
- __u8 full_rebuild_cnt1[4];\r
- __u8 raw_rebuild_cnt0[4];\r
- __u8 raw_rebuild_cnt1[4];\r
- __u8 cap_aged; \r
- __u8 cap_aged_ratio;\r
- __u8 cap_status; \r
- __u8 cap_voltage[4];\r
- __u8 cap_charge_ctrl_en; \r
- __u8 cap_charge_ctrl_val[2];\r
- __u8 cap_charge_max_thr[2]; \r
- __u8 cap_charge_min_thr[2]; \r
- __u8 dev_status; \r
- __u8 dev_status_up;\r
- __u8 nand_erase_err_cnt[4]; \r
- __u8 nand_program_err_cnt[4]; \r
- __u8 ddra_1bit_err[2];\r
- __u8 ddra_2bit_err[2];\r
- __u8 ddrb_1bit_err[2];\r
- __u8 ddrb_2bit_err[2];\r
- __u8 ddr_err_bit;\r
- __u8 pcie_corr_err[2];\r
- __u8 pcie_uncorr_err[2];\r
- __u8 pcie_fatal_err[2];\r
- __u8 pcie_err_bit;\r
- __u8 power_level; \r
- __u8 current_power[2]; \r
- __u8 nand_init_fail[2]; \r
- __u8 fw_loader_version[8]; \r
- __u8 uefi_driver_version[8]; \r
- __u8 gpio0_err[2]; \r
- __u8 gpio5_err[2]; \r
- __u8 gpio_err_bit[2]; \r
- __u8 rebuild_percent; \r
- __u8 pcie_volt_status; \r
- __u8 current_pcie_volt[2]; \r
- __u8 init_pcie_volt_thr[2]; \r
- __u8 rt_pcie_volt_thr[2]; \r
- __u8 init_pcie_volt_low[2]; \r
- __u8 rt_pcie_volt_low[2]; \r
- __u8 temp_sensor_abnormal[2];\r
- __u8 nand_read_retry_fail_cnt[4]; \r
- __u8 fw_slot_version[8]; \r
- __u8 rsved[395];\r
- };\r
- \r
- enum dera_device_status\r
- {\r
- DEVICE_STATUS_READY = 0x00,\r
- DEVICE_STATUS_QUICK_REBUILDING = 0x01,\r
- DEVICE_STATUS_FULL_REBUILDING = 0x02,\r
- DEVICE_STATUS_RAW_REBUILDING = 0x03,\r
- DEVICE_STATUS_CARD_READ_ONLY = 0x04,\r
- DEVICE_STATUS_FATAL_ERROR = 0x05,\r
- DEVICE_STATUS_BUSY = 0x06,\r
- DEVICE_STAUTS_LOW_LEVEL_FORMAT = 0x07,\r
- DEVICE_STAUTS_FW_COMMITING = 0x08,\r
- DEVICE_STAUTS__OVER_TEMPRATURE = 0x09,\r
- };\r
- \r
- static int nvme_dera_get_device_status(int fd, enum dera_device_status *result)\r
- {\r
- int err = 0;\r
- \r
- struct nvme_passthru_cmd cmd = {\r
- .opcode = 0xc0, \r
- .addr = (__u64)(uintptr_t)NULL,\r
- .data_len = 0,\r
- .cdw10 = 0,\r
- .cdw12 = 0x104, \r
- };\r
- \r
- err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &cmd);\r
- if (!err && result) {\r
- *result = cmd.result;\r
- }\r
- \r
- return err;\r
- }\r
- \r
- static int get_status(int argc, char **argv, struct command *cmd, struct plugin *plugin)\r
- {\r
- int fd, err;\r
- struct nvme_dera_smart_info_log log;\r
- enum dera_device_status state = DEVICE_STATUS_FATAL_ERROR;\r
- char *desc = "Get the Dera device status";\r
- const struct argconfig_commandline_options command_line_options[] = {\r
- { 0 }\r
- };\r
- \r
- fd = parse_and_open(argc, argv, desc, command_line_options, NULL, 0); \r
- if (fd < 0)\r
- return fd;\r
- \r
- err = nvme_get_log(fd, 0xffffffff, 0xc0, false, sizeof(log), &log);\r
- if (err) {\r
- goto exit;\r
- }\r
- \r
- const char* dev_status[] = {\r
- "Normal",\r
- "Quick Rebuilding",\r
- "Full Rebuilding",\r
- "Raw Rebuilding",\r
- "Card Read Only",\r
- "Fatal Error",\r
- "Busy",\r
- "Low Level Format",\r
- "Firmware Committing",\r
- "Over Temperature" };\r
- \r
- const char *volt_status[] = {\r
- "Normal",\r
- "Initial Low",\r
- "Runtime Low",\r
- };\r
- \r
- err = nvme_dera_get_device_status(fd, &state);\r
- if (!err){\r
- if (state > 0 && state < 4){\r
- printf("device_status : %s %d%% completed\n", dev_status[state], log.rebuild_percent);\r
- }\r
- else{\r
- printf("device_status : %s\n", dev_status[state]);\r
- }\r
- }\r
- else {\r
- goto exit;\r
- }\r
- \r
- printf("dev_status_up : %s\n", dev_status[log.dev_status_up]);\r
- printf("cap_aged : %s\n", log.cap_aged == 1 ? "True" : "False");\r
- printf("cap_aged_ratio : %d%%\n", log.cap_aged_ratio < 100 ? log.cap_aged_ratio : 100);\r
- printf("cap_status : %s\n", log.cap_status == 0 ? "Normal" : (log.cap_status == 1 ? "Warning" : "Critical"));\r
- printf("cap_voltage : %d mV\n", char4_to_int(log.cap_voltage));\r
- printf("nand_erase_err_cnt : %d\n", char4_to_int(log.nand_erase_err_cnt));\r
- printf("nand_program_err_cnt : %d\n", char4_to_int(log.nand_program_err_cnt));\r
- printf("ddra_1bit_err : %d\n", log.ddra_1bit_err[1] << 8 | log.ddra_1bit_err[0]);\r
- printf("ddra_2bit_err : %d\n", log.ddra_2bit_err[1] << 8 | log.ddra_2bit_err[0]);\r
- printf("ddrb_1bit_err : %d\n", log.ddrb_1bit_err[1] << 8 | log.ddrb_1bit_err[0]);\r
- printf("ddrb_2bit_err : %d\n", log.ddrb_2bit_err[1] << 8 | log.ddrb_2bit_err[0]);\r
- printf("ddr_err_bit : %d\n", log.ddr_err_bit);\r
- printf("pcie_corr_err : %d\n", log.pcie_corr_err[1] << 8 | log.pcie_corr_err[0]);\r
- printf("pcie_uncorr_err : %d\n", log.pcie_uncorr_err[1] << 8 | log.pcie_uncorr_err[0]);\r
- printf("pcie_fatal_err : %d\n", log.pcie_fatal_err[1] << 8 | log.pcie_fatal_err[0]);\r
- printf("power_level : %d W\n", log.power_level);\r
- printf("current_power : %d mW\n", log.current_power[1] << 8 | log.current_power[0]);\r
- printf("nand_init_fail : %d\n", log.nand_init_fail[1] << 8 | log.nand_init_fail[0]);\r
- printf("fw_loader_version : %.*s\n", 8, log.fw_loader_version);\r
- printf("uefi_driver_version : %.*s\n", 8, log.uefi_driver_version);\r
- \r
- if (log.pcie_volt_status >= 0 && log.pcie_volt_status <= sizeof(volt_status) / sizeof(const char *)){\r
- printf("pcie_volt_status : %s\n", volt_status[log.pcie_volt_status]);\r
- }\r
- else{\r
- printf("pcie_volt_status : Unknown\n");\r
- }\r
- \r
- printf("current_pcie_volt : %d mV\n", log.current_pcie_volt[1] << 8 | log.current_pcie_volt[0]);\r
- printf("init_pcie_volt_low_cnt : %d\n", log.init_pcie_volt_low[1] << 8 | log.init_pcie_volt_low[0]);\r
- printf("rt_pcie_volt_low_cnt : %d\n", log.rt_pcie_volt_low[1] << 8 | log.rt_pcie_volt_low[0]);\r
- printf("temp_sensor_abnormal_cnt : %d\n", log.temp_sensor_abnormal[1] << 8 | log.temp_sensor_abnormal[0]);\r
- printf("nand_read_retry_fail_cnt : %d\n", char4_to_int(log.nand_read_retry_fail_cnt));\r
- printf("fw_slot_version : %.*s\n", 8, log.fw_slot_version);\r
- \r
- exit:\r
- if (err > 0)\r
- fprintf(stderr, "\nNVMe status:%s(0x%x)\n", nvme_status_to_string(err), err);\r
- \r
- return err;\r
- }\r
- \r
++#include <fcntl.h>
++#include <errno.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <string.h>
++#include <dirent.h>
++#include <ctype.h>
++#include <sys/stat.h>
++#include <sys/time.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 "dera-nvme.h"
++
++static int char4_to_int(__u8 *data)
++{
++ int i;
++ int result = 0;
++
++ for (i = 0; i < 4; i++) {
++ result = result << 8;
++ result += data[3 - i];
++ }
++ return result;
++}
++
++struct nvme_dera_smart_info_log
++{
++ __u8 quick_rebuild_cnt0[4];
++ __u8 quick_rebuild_cnt1[4];
++ __u8 full_rebuild_cnt0[4];
++ __u8 full_rebuild_cnt1[4];
++ __u8 raw_rebuild_cnt0[4];
++ __u8 raw_rebuild_cnt1[4];
++ __u8 cap_aged;
++ __u8 cap_aged_ratio;
++ __u8 cap_status;
++ __u8 cap_voltage[4];
++ __u8 cap_charge_ctrl_en;
++ __u8 cap_charge_ctrl_val[2];
++ __u8 cap_charge_max_thr[2];
++ __u8 cap_charge_min_thr[2];
++ __u8 dev_status;
++ __u8 dev_status_up;
++ __u8 nand_erase_err_cnt[4];
++ __u8 nand_program_err_cnt[4];
++ __u8 ddra_1bit_err[2];
++ __u8 ddra_2bit_err[2];
++ __u8 ddrb_1bit_err[2];
++ __u8 ddrb_2bit_err[2];
++ __u8 ddr_err_bit;
++ __u8 pcie_corr_err[2];
++ __u8 pcie_uncorr_err[2];
++ __u8 pcie_fatal_err[2];
++ __u8 pcie_err_bit;
++ __u8 power_level;
++ __u8 current_power[2];
++ __u8 nand_init_fail[2];
++ __u8 fw_loader_version[8];
++ __u8 uefi_driver_version[8];
++ __u8 gpio0_err[2];
++ __u8 gpio5_err[2];
++ __u8 gpio_err_bit[2];
++ __u8 rebuild_percent;
++ __u8 pcie_volt_status;
++ __u8 current_pcie_volt[2];
++ __u8 init_pcie_volt_thr[2];
++ __u8 rt_pcie_volt_thr[2];
++ __u8 init_pcie_volt_low[2];
++ __u8 rt_pcie_volt_low[2];
++ __u8 temp_sensor_abnormal[2];
++ __u8 nand_read_retry_fail_cnt[4];
++ __u8 fw_slot_version[8];
++ __u8 rsved[395];
++};
++
++enum dera_device_status
++{
++ DEVICE_STATUS_READY = 0x00,
++ DEVICE_STATUS_QUICK_REBUILDING = 0x01,
++ DEVICE_STATUS_FULL_REBUILDING = 0x02,
++ DEVICE_STATUS_RAW_REBUILDING = 0x03,
++ DEVICE_STATUS_CARD_READ_ONLY = 0x04,
++ DEVICE_STATUS_FATAL_ERROR = 0x05,
++ DEVICE_STATUS_BUSY = 0x06,
++ DEVICE_STAUTS_LOW_LEVEL_FORMAT = 0x07,
++ DEVICE_STAUTS_FW_COMMITING = 0x08,
++ DEVICE_STAUTS__OVER_TEMPRATURE = 0x09,
++};
++
++static int nvme_dera_get_device_status(int fd, enum dera_device_status *result)
++{
++ int err = 0;
++
++ struct nvme_passthru_cmd cmd = {
++ .opcode = 0xc0,
++ .addr = (__u64)(uintptr_t)NULL,
++ .data_len = 0,
++ .cdw10 = 0,
++ .cdw12 = 0x104,
++ };
++
++ err = nvme_submit_passthru(fd, NVME_IOCTL_ADMIN_CMD, &cmd);
++ if (!err && result) {
++ *result = cmd.result;
++ }
++
++ return err;
++}
++
++static int get_status(int argc, char **argv, struct command *cmd, struct plugin *plugin)
++{
++ int fd, err;
++ struct nvme_dera_smart_info_log log;
++ enum dera_device_status state = DEVICE_STATUS_FATAL_ERROR;
++ char *desc = "Get the Dera device status";
++
++ OPT_ARGS(opts) = {
++ OPT_END()
++ };
++
++ fd = parse_and_open(argc, argv, desc, opts);
++ if (fd < 0)
++ return fd;
++
++ err = nvme_get_log(fd, 0xffffffff, 0xc0, false, sizeof(log), &log);
++ if (err) {
++ goto exit;
++ }
++
++ const char* dev_status[] = {
++ "Normal",
++ "Quick Rebuilding",
++ "Full Rebuilding",
++ "Raw Rebuilding",
++ "Card Read Only",
++ "Fatal Error",
++ "Busy",
++ "Low Level Format",
++ "Firmware Committing",
++ "Over Temperature" };
++
++ const char *volt_status[] = {
++ "Normal",
++ "Initial Low",
++ "Runtime Low",
++ };
++
++ err = nvme_dera_get_device_status(fd, &state);
++ if (!err){
++ if (state > 0 && state < 4){
++ printf("device_status : %s %d%% completed\n", dev_status[state], log.rebuild_percent);
++ }
++ else{
++ printf("device_status : %s\n", dev_status[state]);
++ }
++ }
++ else {
++ goto exit;
++ }
++
++ printf("dev_status_up : %s\n", dev_status[log.dev_status_up]);
++ printf("cap_aged : %s\n", log.cap_aged == 1 ? "True" : "False");
++ printf("cap_aged_ratio : %d%%\n", log.cap_aged_ratio < 100 ? log.cap_aged_ratio : 100);
++ printf("cap_status : %s\n", log.cap_status == 0 ? "Normal" : (log.cap_status == 1 ? "Warning" : "Critical"));
++ printf("cap_voltage : %d mV\n", char4_to_int(log.cap_voltage));
++ printf("nand_erase_err_cnt : %d\n", char4_to_int(log.nand_erase_err_cnt));
++ printf("nand_program_err_cnt : %d\n", char4_to_int(log.nand_program_err_cnt));
++ printf("ddra_1bit_err : %d\n", log.ddra_1bit_err[1] << 8 | log.ddra_1bit_err[0]);
++ printf("ddra_2bit_err : %d\n", log.ddra_2bit_err[1] << 8 | log.ddra_2bit_err[0]);
++ printf("ddrb_1bit_err : %d\n", log.ddrb_1bit_err[1] << 8 | log.ddrb_1bit_err[0]);
++ printf("ddrb_2bit_err : %d\n", log.ddrb_2bit_err[1] << 8 | log.ddrb_2bit_err[0]);
++ printf("ddr_err_bit : %d\n", log.ddr_err_bit);
++ printf("pcie_corr_err : %d\n", log.pcie_corr_err[1] << 8 | log.pcie_corr_err[0]);
++ printf("pcie_uncorr_err : %d\n", log.pcie_uncorr_err[1] << 8 | log.pcie_uncorr_err[0]);
++ printf("pcie_fatal_err : %d\n", log.pcie_fatal_err[1] << 8 | log.pcie_fatal_err[0]);
++ printf("power_level : %d W\n", log.power_level);
++ printf("current_power : %d mW\n", log.current_power[1] << 8 | log.current_power[0]);
++ printf("nand_init_fail : %d\n", log.nand_init_fail[1] << 8 | log.nand_init_fail[0]);
++ printf("fw_loader_version : %.*s\n", 8, log.fw_loader_version);
++ printf("uefi_driver_version : %.*s\n", 8, log.uefi_driver_version);
++
++ if (log.pcie_volt_status >= 0 && log.pcie_volt_status <= sizeof(volt_status) / sizeof(const char *)){
++ printf("pcie_volt_status : %s\n", volt_status[log.pcie_volt_status]);
++ }
++ else{
++ printf("pcie_volt_status : Unknown\n");
++ }
++
++ printf("current_pcie_volt : %d mV\n", log.current_pcie_volt[1] << 8 | log.current_pcie_volt[0]);
++ printf("init_pcie_volt_low_cnt : %d\n", log.init_pcie_volt_low[1] << 8 | log.init_pcie_volt_low[0]);
++ printf("rt_pcie_volt_low_cnt : %d\n", log.rt_pcie_volt_low[1] << 8 | log.rt_pcie_volt_low[0]);
++ printf("temp_sensor_abnormal_cnt : %d\n", log.temp_sensor_abnormal[1] << 8 | log.temp_sensor_abnormal[0]);
++ printf("nand_read_retry_fail_cnt : %d\n", char4_to_int(log.nand_read_retry_fail_cnt));
++ printf("fw_slot_version : %.*s\n", 8, log.fw_slot_version);
++
++exit:
++ if (err > 0)
++ fprintf(stderr, "\nNVMe status:%s(0x%x)\n", nvme_status_to_string(err), err);
++
++ return err;
++}
++