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