|  | 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 | 
|  | } |