blob: 8f4699544471f89fa66c971cdb40b67f747c2031 [file] [log] [blame] [edit]
package nvme
import (
"bytes"
"encoding/binary"
)
type SelfTestOp uint8
const (
SelfTestNone SelfTestOp = 0x0
SelfTestShort SelfTestOp = 0x1
SelfTestExtended SelfTestOp = 0x2
SelfTestAbort SelfTestOp = 0xF
)
func (d *Device) StartSelfTest(ns uint32, action SelfTestOp) error {
return d.RawCommand(&Command{
Opcode: 0x14,
NamespaceID: ns,
CDW10: uint32(action & 0xF),
})
}
// Figure 99
type selfTestResult struct {
SelfTestStatus uint8
SegmentNumber uint8
ValidDiagnosticInformation uint8
_ byte
PowerOnHours uint64
NamespaceID uint32
FailingLBA uint64
StatusCodeType uint8
StatusCode uint8
VendorSpecific [2]byte
}
// Figure 98
type selfTestLogPage struct {
CurrentSelfTestOp uint8
CurrentSelfTestCompletion uint8
_ [2]byte
SelfTestResults [20]selfTestResult
}
type SelfTestResult struct {
// Op contains the self test type
Op SelfTestOp
Result uint8
SegmentNumber uint8
PowerOnHours uint64
NamespaceID uint32
FailingLBA uint64
Error Error
}
type SelfTestResults struct {
// CurrentOp contains the currently in-progress self test type (or
// SelfTestTypeNone if no self test is in progress).
CurrentOp SelfTestOp
// CurrentCompletion contains the progress from 0 to 1 of the currently
// in-progress self-test. Only valid if CurrentOp is not SelfTestTypeNone.
CurrentSelfTestCompletion float32
// PastResults contains a list of up to 20 previous self test results,
// sorted from the most recent to the oldest.
PastResults []SelfTestResult
}
func (d *Device) GetSelfTestResults(ns uint32) (*SelfTestResults, error) {
var buf [564]byte
if err := d.GetLogPage(ns, 0x06, 0, 0, buf[:]); err != nil {
return nil, err
}
var page selfTestLogPage
binary.Read(bytes.NewReader(buf[:]), binary.LittleEndian, &page)
var res SelfTestResults
res.CurrentOp = SelfTestOp(page.CurrentSelfTestOp & 0xF)
res.CurrentSelfTestCompletion = float32(page.CurrentSelfTestCompletion&0x7F) / 100.
for _, r := range page.SelfTestResults {
var t SelfTestResult
t.Op = SelfTestOp((r.SelfTestStatus >> 4) & 0xF)
t.Result = r.SelfTestStatus & 0xF
if t.Result == 0xF {
continue
}
t.SegmentNumber = r.SegmentNumber
t.PowerOnHours = r.PowerOnHours
t.NamespaceID = r.NamespaceID
t.FailingLBA = r.FailingLBA
t.Error.StatusCode = r.StatusCode
t.Error.StatusCodeType = r.StatusCodeType
res.PastResults = append(res.PastResults, t)
}
return &res, nil
}