blob: 8f4699544471f89fa66c971cdb40b67f747c2031 [file] [log] [blame]
Lorenz Brunfba5da02022-12-15 11:20:47 +00001package nvme
2
3import (
4 "bytes"
5 "encoding/binary"
6)
7
8type SelfTestOp uint8
9
10const (
11 SelfTestNone SelfTestOp = 0x0
12 SelfTestShort SelfTestOp = 0x1
13 SelfTestExtended SelfTestOp = 0x2
14 SelfTestAbort SelfTestOp = 0xF
15)
16
17func (d *Device) StartSelfTest(ns uint32, action SelfTestOp) error {
18 return d.RawCommand(&Command{
19 Opcode: 0x14,
20 NamespaceID: ns,
21 CDW10: uint32(action & 0xF),
22 })
23}
24
25// Figure 99
26type selfTestResult struct {
27 SelfTestStatus uint8
28 SegmentNumber uint8
29 ValidDiagnosticInformation uint8
30 _ byte
31 PowerOnHours uint64
32 NamespaceID uint32
33 FailingLBA uint64
34 StatusCodeType uint8
35 StatusCode uint8
36 VendorSpecific [2]byte
37}
38
39// Figure 98
40type selfTestLogPage struct {
41 CurrentSelfTestOp uint8
42 CurrentSelfTestCompletion uint8
43 _ [2]byte
44 SelfTestResults [20]selfTestResult
45}
46
47type SelfTestResult struct {
48 // Op contains the self test type
49 Op SelfTestOp
50 Result uint8
51 SegmentNumber uint8
52 PowerOnHours uint64
53 NamespaceID uint32
54 FailingLBA uint64
55 Error Error
56}
57
58type SelfTestResults struct {
59 // CurrentOp contains the currently in-progress self test type (or
60 // SelfTestTypeNone if no self test is in progress).
61 CurrentOp SelfTestOp
62 // CurrentCompletion contains the progress from 0 to 1 of the currently
63 // in-progress self-test. Only valid if CurrentOp is not SelfTestTypeNone.
64 CurrentSelfTestCompletion float32
65 // PastResults contains a list of up to 20 previous self test results,
66 // sorted from the most recent to the oldest.
67 PastResults []SelfTestResult
68}
69
70func (d *Device) GetSelfTestResults(ns uint32) (*SelfTestResults, error) {
71 var buf [564]byte
72 if err := d.GetLogPage(ns, 0x06, 0, 0, buf[:]); err != nil {
73 return nil, err
74 }
75 var page selfTestLogPage
76 binary.Read(bytes.NewReader(buf[:]), binary.LittleEndian, &page)
77 var res SelfTestResults
78 res.CurrentOp = SelfTestOp(page.CurrentSelfTestOp & 0xF)
79 res.CurrentSelfTestCompletion = float32(page.CurrentSelfTestCompletion&0x7F) / 100.
80 for _, r := range page.SelfTestResults {
81 var t SelfTestResult
82 t.Op = SelfTestOp((r.SelfTestStatus >> 4) & 0xF)
83 t.Result = r.SelfTestStatus & 0xF
84 if t.Result == 0xF {
85 continue
86 }
87 t.SegmentNumber = r.SegmentNumber
88 t.PowerOnHours = r.PowerOnHours
89 t.NamespaceID = r.NamespaceID
90 t.FailingLBA = r.FailingLBA
91 t.Error.StatusCode = r.StatusCode
92 t.Error.StatusCodeType = r.StatusCodeType
93 res.PastResults = append(res.PastResults, t)
94 }
95 return &res, nil
96}