blob: a2a60d0bf957db778b2d0df4937930e5c7579597 [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 "fmt"
7
8// Figure 31 in the spec
9var genericStatusCodeDesc = map[uint8]string{
10 0x00: "successful completion",
11 0x01: "invalid command opcode",
12 0x02: "invalid field in command",
13 0x03: "command ID conflict",
14 0x04: "data transfer error",
15 0x05: "command aborted due power loss notification",
16 0x06: "internal error",
17 0x07: "command abort requested",
18 0x08: "command abort due to SQ deletion",
19 0x09: "command abort due to failed fused command",
20 0x0a: "command abort due to missing fused command",
21 0x0b: "invalid namespace or format",
22 0x0c: "command sequence error",
23 0x0d: "invalid SGL segment descriptor",
24 0x0e: "invalid number of SGL descriptors",
25 0x0f: "data SGL length invalid",
26 0x10: "metadata SGL length invalid",
27 0x11: "SGL descriptor type invalid",
28 0x12: "invalid use of controller memory buffer",
29 0x13: "PRP offset invalid",
30 0x14: "atomic write unit exceeded",
31 0x15: "operation denied",
32 0x16: "SGL offset invalid",
33 0x18: "host identifer inconsistent format",
34 0x19: "keep alive timeout expired",
35 0x1a: "keep alive timeout invalid",
36 0x1b: "command aborted due to preempt and abort",
37 0x1c: "sanitize failed",
38 0x1d: "sanitize in progress",
39 0x1e: "SGL data block granularity invalid",
40 0x1f: "command not supported for queue in CMB",
41
42 // Figure 32
43 0x80: "LBA out of range",
44 0x81: "capacity exceeded",
45 0x82: "namespace not ready",
46 0x83: "reservation conflict",
47 0x84: "format in progress",
48}
49
50// Figure 33 in the spec
51var commandSpecificStatusCodeDesc = map[uint8]string{
52 0x00: "completion queue invalid",
53 0x01: "invalid queue identifier",
54 0x02: "invalid queue size",
55 0x03: "abort command limit exceeded",
56 0x05: "asynchronous event request limit exceeded",
57 0x06: "invalid firmware slot",
58 0x07: "invalid firmware image",
59 0x08: "invalid interrupt vector",
60 0x09: "invalid log page",
61 0x0a: "invalid format",
62 0x0b: "firmware activation requires conventional reset",
63 0x0c: "invalid queue deletion",
64 0x0d: "feature identifier not saveable",
65 0x0e: "feature not changeable",
66 0x0f: "feature not namespace-specific",
67 0x10: "firmware activation requires NVM subsystem reset",
68 0x11: "firmware activation requires reset",
69 0x12: "firmware activation requires maximum time violation",
70 0x13: "firmware activation prohibited",
71 0x14: "overlapping range",
72 0x15: "namespace insufficient capacity",
73 0x16: "namespace identifier unavailable",
74 0x18: "namespace already attached",
75 0x19: "namespace is private",
76 0x1a: "namespace is not attached",
77 0x1b: "thin provisioning not supported",
78 0x1c: "controller list invalid",
79 0x1d: "device self-test in progress",
80 0x1e: "boot partition write prohibited",
81 0x1f: "invalid controller identifier",
82 0x20: "invalid secondary controller state",
83 0x21: "invalid number of controller resources",
84 0x22: "invalid resource identifier",
85
86 // Figure 34
87 0x80: "conflicting attributes",
88 0x81: "invalid protection information",
89 0x82: "attempted to write to read-only range",
90}
91
92// Figure 36
93var mediaAndDataIntegrityStatusCodeDesc = map[uint8]string{
94 0x80: "write fault",
95 0x81: "unrecovered read error",
96 0x82: "end-to-end guard check error",
97 0x83: "end-to-end application tag check error",
98 0x84: "end-to-end reference tag check error",
99 0x85: "compare failure",
100 0x86: "access denied",
101 0x87: "deallocated or unwritten logical block",
102}
103
104const (
105 StatusCodeTypeGeneric = 0x0
106 StatusCodeTypeCommandSpecific = 0x1
107 StatusCodeTypeMediaAndDataIntegrity = 0x2
108)
109
110// Error represents an error returned by the NVMe device in the form of a
111// NVMe Status Field (see also Figure 29 in the spec).
112type Error struct {
113 DoNotRetry bool
114 More bool
115 StatusCodeType uint8
116 StatusCode uint8
117}
118
119func (e Error) Error() string {
120 switch e.StatusCodeType {
121 case StatusCodeTypeGeneric:
122 if errStr, ok := genericStatusCodeDesc[e.StatusCode]; ok {
123 return errStr
124 }
125 return fmt.Sprintf("unknown error with generic code 0x%x", e.StatusCode)
126 case StatusCodeTypeCommandSpecific:
127 if errStr, ok := commandSpecificStatusCodeDesc[e.StatusCode]; ok {
128 return errStr
129 }
130 return fmt.Sprintf("unknown error with command-specific code 0x%x", e.StatusCode)
131 case StatusCodeTypeMediaAndDataIntegrity:
132 if errStr, ok := mediaAndDataIntegrityStatusCodeDesc[e.StatusCode]; ok {
133 return errStr
134 }
135 return fmt.Sprintf("unknown error with media and data integrity code 0x%x", e.StatusCode)
136 default:
137 return fmt.Sprintf("unknown error with unknown type 0x%x and code 0x%x", e.StatusCodeType, e.StatusCode)
138 }
139}