]>
Commit | Line | Data |
---|---|---|
f3c507ad KB |
1 | #ifndef HW_NVME_H |
2 | #define HW_NVME_H | |
3 | ||
4 | typedef struct NvmeBar { | |
5 | uint64_t cap; | |
6 | uint32_t vs; | |
7 | uint32_t intms; | |
8 | uint32_t intmc; | |
9 | uint32_t cc; | |
10 | uint32_t rsvd1; | |
11 | uint32_t csts; | |
12 | uint32_t nssrc; | |
13 | uint32_t aqa; | |
14 | uint64_t asq; | |
15 | uint64_t acq; | |
16 | } NvmeBar; | |
17 | ||
18 | enum NvmeCapShift { | |
19 | CAP_MQES_SHIFT = 0, | |
20 | CAP_CQR_SHIFT = 16, | |
21 | CAP_AMS_SHIFT = 17, | |
22 | CAP_TO_SHIFT = 24, | |
23 | CAP_DSTRD_SHIFT = 32, | |
24 | CAP_NSSRS_SHIFT = 33, | |
25 | CAP_CSS_SHIFT = 37, | |
26 | CAP_MPSMIN_SHIFT = 48, | |
27 | CAP_MPSMAX_SHIFT = 52, | |
28 | }; | |
29 | ||
30 | enum NvmeCapMask { | |
31 | CAP_MQES_MASK = 0xffff, | |
32 | CAP_CQR_MASK = 0x1, | |
33 | CAP_AMS_MASK = 0x3, | |
34 | CAP_TO_MASK = 0xff, | |
35 | CAP_DSTRD_MASK = 0xf, | |
36 | CAP_NSSRS_MASK = 0x1, | |
37 | CAP_CSS_MASK = 0xff, | |
38 | CAP_MPSMIN_MASK = 0xf, | |
39 | CAP_MPSMAX_MASK = 0xf, | |
40 | }; | |
41 | ||
42 | #define NVME_CAP_MQES(cap) (((cap) >> CAP_MQES_SHIFT) & CAP_MQES_MASK) | |
43 | #define NVME_CAP_CQR(cap) (((cap) >> CAP_CQR_SHIFT) & CAP_CQR_MASK) | |
44 | #define NVME_CAP_AMS(cap) (((cap) >> CAP_AMS_SHIFT) & CAP_AMS_MASK) | |
45 | #define NVME_CAP_TO(cap) (((cap) >> CAP_TO_SHIFT) & CAP_TO_MASK) | |
46 | #define NVME_CAP_DSTRD(cap) (((cap) >> CAP_DSTRD_SHIFT) & CAP_DSTRD_MASK) | |
47 | #define NVME_CAP_NSSRS(cap) (((cap) >> CAP_NSSRS_SHIFT) & CAP_NSSRS_MASK) | |
48 | #define NVME_CAP_CSS(cap) (((cap) >> CAP_CSS_SHIFT) & CAP_CSS_MASK) | |
49 | #define NVME_CAP_MPSMIN(cap)(((cap) >> CAP_MPSMIN_SHIFT) & CAP_MPSMIN_MASK) | |
50 | #define NVME_CAP_MPSMAX(cap)(((cap) >> CAP_MPSMAX_SHIFT) & CAP_MPSMAX_MASK) | |
51 | ||
52 | #define NVME_CAP_SET_MQES(cap, val) (cap |= (uint64_t)(val & CAP_MQES_MASK) \ | |
53 | << CAP_MQES_SHIFT) | |
54 | #define NVME_CAP_SET_CQR(cap, val) (cap |= (uint64_t)(val & CAP_CQR_MASK) \ | |
55 | << CAP_CQR_SHIFT) | |
56 | #define NVME_CAP_SET_AMS(cap, val) (cap |= (uint64_t)(val & CAP_AMS_MASK) \ | |
57 | << CAP_AMS_SHIFT) | |
58 | #define NVME_CAP_SET_TO(cap, val) (cap |= (uint64_t)(val & CAP_TO_MASK) \ | |
59 | << CAP_TO_SHIFT) | |
60 | #define NVME_CAP_SET_DSTRD(cap, val) (cap |= (uint64_t)(val & CAP_DSTRD_MASK) \ | |
61 | << CAP_DSTRD_SHIFT) | |
62 | #define NVME_CAP_SET_NSSRS(cap, val) (cap |= (uint64_t)(val & CAP_NSSRS_MASK) \ | |
63 | << CAP_NSSRS_SHIFT) | |
64 | #define NVME_CAP_SET_CSS(cap, val) (cap |= (uint64_t)(val & CAP_CSS_MASK) \ | |
65 | << CAP_CSS_SHIFT) | |
66 | #define NVME_CAP_SET_MPSMIN(cap, val) (cap |= (uint64_t)(val & CAP_MPSMIN_MASK)\ | |
67 | << CAP_MPSMIN_SHIFT) | |
68 | #define NVME_CAP_SET_MPSMAX(cap, val) (cap |= (uint64_t)(val & CAP_MPSMAX_MASK)\ | |
69 | << CAP_MPSMAX_SHIFT) | |
70 | ||
71 | enum NvmeCcShift { | |
72 | CC_EN_SHIFT = 0, | |
73 | CC_CSS_SHIFT = 4, | |
74 | CC_MPS_SHIFT = 7, | |
75 | CC_AMS_SHIFT = 11, | |
76 | CC_SHN_SHIFT = 14, | |
77 | CC_IOSQES_SHIFT = 16, | |
78 | CC_IOCQES_SHIFT = 20, | |
79 | }; | |
80 | ||
81 | enum NvmeCcMask { | |
82 | CC_EN_MASK = 0x1, | |
83 | CC_CSS_MASK = 0x7, | |
84 | CC_MPS_MASK = 0xf, | |
85 | CC_AMS_MASK = 0x7, | |
86 | CC_SHN_MASK = 0x3, | |
87 | CC_IOSQES_MASK = 0xf, | |
88 | CC_IOCQES_MASK = 0xf, | |
89 | }; | |
90 | ||
91 | #define NVME_CC_EN(cc) ((cc >> CC_EN_SHIFT) & CC_EN_MASK) | |
92 | #define NVME_CC_CSS(cc) ((cc >> CC_CSS_SHIFT) & CC_CSS_MASK) | |
93 | #define NVME_CC_MPS(cc) ((cc >> CC_MPS_SHIFT) & CC_MPS_MASK) | |
94 | #define NVME_CC_AMS(cc) ((cc >> CC_AMS_SHIFT) & CC_AMS_MASK) | |
95 | #define NVME_CC_SHN(cc) ((cc >> CC_SHN_SHIFT) & CC_SHN_MASK) | |
96 | #define NVME_CC_IOSQES(cc) ((cc >> CC_IOSQES_SHIFT) & CC_IOSQES_MASK) | |
97 | #define NVME_CC_IOCQES(cc) ((cc >> CC_IOCQES_SHIFT) & CC_IOCQES_MASK) | |
98 | ||
99 | enum NvmeCstsShift { | |
100 | CSTS_RDY_SHIFT = 0, | |
101 | CSTS_CFS_SHIFT = 1, | |
102 | CSTS_SHST_SHIFT = 2, | |
103 | CSTS_NSSRO_SHIFT = 4, | |
104 | }; | |
105 | ||
106 | enum NvmeCstsMask { | |
107 | CSTS_RDY_MASK = 0x1, | |
108 | CSTS_CFS_MASK = 0x1, | |
109 | CSTS_SHST_MASK = 0x3, | |
110 | CSTS_NSSRO_MASK = 0x1, | |
111 | }; | |
112 | ||
113 | enum NvmeCsts { | |
114 | NVME_CSTS_READY = 1 << CSTS_RDY_SHIFT, | |
115 | NVME_CSTS_FAILED = 1 << CSTS_CFS_SHIFT, | |
116 | NVME_CSTS_SHST_NORMAL = 0 << CSTS_SHST_SHIFT, | |
117 | NVME_CSTS_SHST_PROGRESS = 1 << CSTS_SHST_SHIFT, | |
118 | NVME_CSTS_SHST_COMPLETE = 2 << CSTS_SHST_SHIFT, | |
119 | NVME_CSTS_NSSRO = 1 << CSTS_NSSRO_SHIFT, | |
120 | }; | |
121 | ||
122 | #define NVME_CSTS_RDY(csts) ((csts >> CSTS_RDY_SHIFT) & CSTS_RDY_MASK) | |
123 | #define NVME_CSTS_CFS(csts) ((csts >> CSTS_CFS_SHIFT) & CSTS_CFS_MASK) | |
124 | #define NVME_CSTS_SHST(csts) ((csts >> CSTS_SHST_SHIFT) & CSTS_SHST_MASK) | |
125 | #define NVME_CSTS_NSSRO(csts) ((csts >> CSTS_NSSRO_SHIFT) & CSTS_NSSRO_MASK) | |
126 | ||
127 | enum NvmeAqaShift { | |
128 | AQA_ASQS_SHIFT = 0, | |
129 | AQA_ACQS_SHIFT = 16, | |
130 | }; | |
131 | ||
132 | enum NvmeAqaMask { | |
133 | AQA_ASQS_MASK = 0xfff, | |
134 | AQA_ACQS_MASK = 0xfff, | |
135 | }; | |
136 | ||
137 | #define NVME_AQA_ASQS(aqa) ((aqa >> AQA_ASQS_SHIFT) & AQA_ASQS_MASK) | |
138 | #define NVME_AQA_ACQS(aqa) ((aqa >> AQA_ACQS_SHIFT) & AQA_ACQS_MASK) | |
139 | ||
140 | typedef struct NvmeCmd { | |
141 | uint8_t opcode; | |
142 | uint8_t fuse; | |
143 | uint16_t cid; | |
144 | uint32_t nsid; | |
145 | uint64_t res1; | |
146 | uint64_t mptr; | |
147 | uint64_t prp1; | |
148 | uint64_t prp2; | |
149 | uint32_t cdw10; | |
150 | uint32_t cdw11; | |
151 | uint32_t cdw12; | |
152 | uint32_t cdw13; | |
153 | uint32_t cdw14; | |
154 | uint32_t cdw15; | |
155 | } NvmeCmd; | |
156 | ||
157 | enum NvmeAdminCommands { | |
158 | NVME_ADM_CMD_DELETE_SQ = 0x00, | |
159 | NVME_ADM_CMD_CREATE_SQ = 0x01, | |
160 | NVME_ADM_CMD_GET_LOG_PAGE = 0x02, | |
161 | NVME_ADM_CMD_DELETE_CQ = 0x04, | |
162 | NVME_ADM_CMD_CREATE_CQ = 0x05, | |
163 | NVME_ADM_CMD_IDENTIFY = 0x06, | |
164 | NVME_ADM_CMD_ABORT = 0x08, | |
165 | NVME_ADM_CMD_SET_FEATURES = 0x09, | |
166 | NVME_ADM_CMD_GET_FEATURES = 0x0a, | |
167 | NVME_ADM_CMD_ASYNC_EV_REQ = 0x0c, | |
168 | NVME_ADM_CMD_ACTIVATE_FW = 0x10, | |
169 | NVME_ADM_CMD_DOWNLOAD_FW = 0x11, | |
170 | NVME_ADM_CMD_FORMAT_NVM = 0x80, | |
171 | NVME_ADM_CMD_SECURITY_SEND = 0x81, | |
172 | NVME_ADM_CMD_SECURITY_RECV = 0x82, | |
173 | }; | |
174 | ||
175 | enum NvmeIoCommands { | |
176 | NVME_CMD_FLUSH = 0x00, | |
177 | NVME_CMD_WRITE = 0x01, | |
178 | NVME_CMD_READ = 0x02, | |
179 | NVME_CMD_WRITE_UNCOR = 0x04, | |
180 | NVME_CMD_COMPARE = 0x05, | |
181 | NVME_CMD_DSM = 0x09, | |
182 | }; | |
183 | ||
184 | typedef struct NvmeDeleteQ { | |
185 | uint8_t opcode; | |
186 | uint8_t flags; | |
187 | uint16_t cid; | |
188 | uint32_t rsvd1[9]; | |
189 | uint16_t qid; | |
190 | uint16_t rsvd10; | |
191 | uint32_t rsvd11[5]; | |
192 | } NvmeDeleteQ; | |
193 | ||
194 | typedef struct NvmeCreateCq { | |
195 | uint8_t opcode; | |
196 | uint8_t flags; | |
197 | uint16_t cid; | |
198 | uint32_t rsvd1[5]; | |
199 | uint64_t prp1; | |
200 | uint64_t rsvd8; | |
201 | uint16_t cqid; | |
202 | uint16_t qsize; | |
203 | uint16_t cq_flags; | |
204 | uint16_t irq_vector; | |
205 | uint32_t rsvd12[4]; | |
206 | } NvmeCreateCq; | |
207 | ||
208 | #define NVME_CQ_FLAGS_PC(cq_flags) (cq_flags & 0x1) | |
209 | #define NVME_CQ_FLAGS_IEN(cq_flags) ((cq_flags >> 1) & 0x1) | |
210 | ||
211 | typedef struct NvmeCreateSq { | |
212 | uint8_t opcode; | |
213 | uint8_t flags; | |
214 | uint16_t cid; | |
215 | uint32_t rsvd1[5]; | |
216 | uint64_t prp1; | |
217 | uint64_t rsvd8; | |
218 | uint16_t sqid; | |
219 | uint16_t qsize; | |
220 | uint16_t sq_flags; | |
221 | uint16_t cqid; | |
222 | uint32_t rsvd12[4]; | |
223 | } NvmeCreateSq; | |
224 | ||
225 | #define NVME_SQ_FLAGS_PC(sq_flags) (sq_flags & 0x1) | |
226 | #define NVME_SQ_FLAGS_QPRIO(sq_flags) ((sq_flags >> 1) & 0x3) | |
227 | ||
228 | enum NvmeQueueFlags { | |
229 | NVME_Q_PC = 1, | |
230 | NVME_Q_PRIO_URGENT = 0, | |
231 | NVME_Q_PRIO_HIGH = 1, | |
232 | NVME_Q_PRIO_NORMAL = 2, | |
233 | NVME_Q_PRIO_LOW = 3, | |
234 | }; | |
235 | ||
236 | typedef struct NvmeIdentify { | |
237 | uint8_t opcode; | |
238 | uint8_t flags; | |
239 | uint16_t cid; | |
240 | uint32_t nsid; | |
241 | uint64_t rsvd2[2]; | |
242 | uint64_t prp1; | |
243 | uint64_t prp2; | |
244 | uint32_t cns; | |
245 | uint32_t rsvd11[5]; | |
246 | } NvmeIdentify; | |
247 | ||
248 | typedef struct NvmeRwCmd { | |
249 | uint8_t opcode; | |
250 | uint8_t flags; | |
251 | uint16_t cid; | |
252 | uint32_t nsid; | |
253 | uint64_t rsvd2; | |
254 | uint64_t mptr; | |
255 | uint64_t prp1; | |
256 | uint64_t prp2; | |
257 | uint64_t slba; | |
258 | uint16_t nlb; | |
259 | uint16_t control; | |
260 | uint32_t dsmgmt; | |
261 | uint32_t reftag; | |
262 | uint16_t apptag; | |
263 | uint16_t appmask; | |
264 | } NvmeRwCmd; | |
265 | ||
266 | enum { | |
267 | NVME_RW_LR = 1 << 15, | |
268 | NVME_RW_FUA = 1 << 14, | |
269 | NVME_RW_DSM_FREQ_UNSPEC = 0, | |
270 | NVME_RW_DSM_FREQ_TYPICAL = 1, | |
271 | NVME_RW_DSM_FREQ_RARE = 2, | |
272 | NVME_RW_DSM_FREQ_READS = 3, | |
273 | NVME_RW_DSM_FREQ_WRITES = 4, | |
274 | NVME_RW_DSM_FREQ_RW = 5, | |
275 | NVME_RW_DSM_FREQ_ONCE = 6, | |
276 | NVME_RW_DSM_FREQ_PREFETCH = 7, | |
277 | NVME_RW_DSM_FREQ_TEMP = 8, | |
278 | NVME_RW_DSM_LATENCY_NONE = 0 << 4, | |
279 | NVME_RW_DSM_LATENCY_IDLE = 1 << 4, | |
280 | NVME_RW_DSM_LATENCY_NORM = 2 << 4, | |
281 | NVME_RW_DSM_LATENCY_LOW = 3 << 4, | |
282 | NVME_RW_DSM_SEQ_REQ = 1 << 6, | |
283 | NVME_RW_DSM_COMPRESSED = 1 << 7, | |
284 | NVME_RW_PRINFO_PRACT = 1 << 13, | |
285 | NVME_RW_PRINFO_PRCHK_GUARD = 1 << 12, | |
286 | NVME_RW_PRINFO_PRCHK_APP = 1 << 11, | |
287 | NVME_RW_PRINFO_PRCHK_REF = 1 << 10, | |
288 | }; | |
289 | ||
290 | typedef struct NvmeDsmCmd { | |
291 | uint8_t opcode; | |
292 | uint8_t flags; | |
293 | uint16_t cid; | |
294 | uint32_t nsid; | |
295 | uint64_t rsvd2[2]; | |
296 | uint64_t prp1; | |
297 | uint64_t prp2; | |
298 | uint32_t nr; | |
299 | uint32_t attributes; | |
300 | uint32_t rsvd12[4]; | |
301 | } NvmeDsmCmd; | |
302 | ||
303 | enum { | |
304 | NVME_DSMGMT_IDR = 1 << 0, | |
305 | NVME_DSMGMT_IDW = 1 << 1, | |
306 | NVME_DSMGMT_AD = 1 << 2, | |
307 | }; | |
308 | ||
309 | typedef struct NvmeDsmRange { | |
310 | uint32_t cattr; | |
311 | uint32_t nlb; | |
312 | uint64_t slba; | |
313 | } NvmeDsmRange; | |
314 | ||
315 | enum NvmeAsyncEventRequest { | |
316 | NVME_AER_TYPE_ERROR = 0, | |
317 | NVME_AER_TYPE_SMART = 1, | |
318 | NVME_AER_TYPE_IO_SPECIFIC = 6, | |
319 | NVME_AER_TYPE_VENDOR_SPECIFIC = 7, | |
320 | NVME_AER_INFO_ERR_INVALID_SQ = 0, | |
321 | NVME_AER_INFO_ERR_INVALID_DB = 1, | |
322 | NVME_AER_INFO_ERR_DIAG_FAIL = 2, | |
323 | NVME_AER_INFO_ERR_PERS_INTERNAL_ERR = 3, | |
324 | NVME_AER_INFO_ERR_TRANS_INTERNAL_ERR = 4, | |
325 | NVME_AER_INFO_ERR_FW_IMG_LOAD_ERR = 5, | |
326 | NVME_AER_INFO_SMART_RELIABILITY = 0, | |
327 | NVME_AER_INFO_SMART_TEMP_THRESH = 1, | |
328 | NVME_AER_INFO_SMART_SPARE_THRESH = 2, | |
329 | }; | |
330 | ||
331 | typedef struct NvmeAerResult { | |
332 | uint8_t event_type; | |
333 | uint8_t event_info; | |
334 | uint8_t log_page; | |
335 | uint8_t resv; | |
336 | } NvmeAerResult; | |
337 | ||
338 | typedef struct NvmeCqe { | |
339 | uint32_t result; | |
340 | uint32_t rsvd; | |
341 | uint16_t sq_head; | |
342 | uint16_t sq_id; | |
343 | uint16_t cid; | |
344 | uint16_t status; | |
345 | } NvmeCqe; | |
346 | ||
347 | enum NvmeStatusCodes { | |
348 | NVME_SUCCESS = 0x0000, | |
349 | NVME_INVALID_OPCODE = 0x0001, | |
350 | NVME_INVALID_FIELD = 0x0002, | |
351 | NVME_CID_CONFLICT = 0x0003, | |
352 | NVME_DATA_TRAS_ERROR = 0x0004, | |
353 | NVME_POWER_LOSS_ABORT = 0x0005, | |
354 | NVME_INTERNAL_DEV_ERROR = 0x0006, | |
355 | NVME_CMD_ABORT_REQ = 0x0007, | |
356 | NVME_CMD_ABORT_SQ_DEL = 0x0008, | |
357 | NVME_CMD_ABORT_FAILED_FUSE = 0x0009, | |
358 | NVME_CMD_ABORT_MISSING_FUSE = 0x000a, | |
359 | NVME_INVALID_NSID = 0x000b, | |
360 | NVME_CMD_SEQ_ERROR = 0x000c, | |
361 | NVME_LBA_RANGE = 0x0080, | |
362 | NVME_CAP_EXCEEDED = 0x0081, | |
363 | NVME_NS_NOT_READY = 0x0082, | |
364 | NVME_NS_RESV_CONFLICT = 0x0083, | |
365 | NVME_INVALID_CQID = 0x0100, | |
366 | NVME_INVALID_QID = 0x0101, | |
367 | NVME_MAX_QSIZE_EXCEEDED = 0x0102, | |
368 | NVME_ACL_EXCEEDED = 0x0103, | |
369 | NVME_RESERVED = 0x0104, | |
370 | NVME_AER_LIMIT_EXCEEDED = 0x0105, | |
371 | NVME_INVALID_FW_SLOT = 0x0106, | |
372 | NVME_INVALID_FW_IMAGE = 0x0107, | |
373 | NVME_INVALID_IRQ_VECTOR = 0x0108, | |
374 | NVME_INVALID_LOG_ID = 0x0109, | |
375 | NVME_INVALID_FORMAT = 0x010a, | |
376 | NVME_FW_REQ_RESET = 0x010b, | |
377 | NVME_INVALID_QUEUE_DEL = 0x010c, | |
378 | NVME_FID_NOT_SAVEABLE = 0x010d, | |
379 | NVME_FID_NOT_NSID_SPEC = 0x010f, | |
380 | NVME_FW_REQ_SUSYSTEM_RESET = 0x0110, | |
381 | NVME_CONFLICTING_ATTRS = 0x0180, | |
382 | NVME_INVALID_PROT_INFO = 0x0181, | |
383 | NVME_WRITE_TO_RO = 0x0182, | |
384 | NVME_WRITE_FAULT = 0x0280, | |
385 | NVME_UNRECOVERED_READ = 0x0281, | |
386 | NVME_E2E_GUARD_ERROR = 0x0282, | |
387 | NVME_E2E_APP_ERROR = 0x0283, | |
388 | NVME_E2E_REF_ERROR = 0x0284, | |
389 | NVME_CMP_FAILURE = 0x0285, | |
390 | NVME_ACCESS_DENIED = 0x0286, | |
391 | NVME_MORE = 0x2000, | |
392 | NVME_DNR = 0x4000, | |
393 | NVME_NO_COMPLETE = 0xffff, | |
394 | }; | |
395 | ||
396 | typedef struct NvmeFwSlotInfoLog { | |
397 | uint8_t afi; | |
398 | uint8_t reserved1[7]; | |
399 | uint8_t frs1[8]; | |
400 | uint8_t frs2[8]; | |
401 | uint8_t frs3[8]; | |
402 | uint8_t frs4[8]; | |
403 | uint8_t frs5[8]; | |
404 | uint8_t frs6[8]; | |
405 | uint8_t frs7[8]; | |
406 | uint8_t reserved2[448]; | |
407 | } NvmeFwSlotInfoLog; | |
408 | ||
409 | typedef struct NvmeErrorLog { | |
410 | uint64_t error_count; | |
411 | uint16_t sqid; | |
412 | uint16_t cid; | |
413 | uint16_t status_field; | |
414 | uint16_t param_error_location; | |
415 | uint64_t lba; | |
416 | uint32_t nsid; | |
417 | uint8_t vs; | |
418 | uint8_t resv[35]; | |
419 | } NvmeErrorLog; | |
420 | ||
421 | typedef struct NvmeSmartLog { | |
422 | uint8_t critical_warning; | |
423 | uint8_t temperature[2]; | |
424 | uint8_t available_spare; | |
425 | uint8_t available_spare_threshold; | |
426 | uint8_t percentage_used; | |
427 | uint8_t reserved1[26]; | |
428 | uint64_t data_units_read[2]; | |
429 | uint64_t data_units_written[2]; | |
430 | uint64_t host_read_commands[2]; | |
431 | uint64_t host_write_commands[2]; | |
432 | uint64_t controller_busy_time[2]; | |
433 | uint64_t power_cycles[2]; | |
434 | uint64_t power_on_hours[2]; | |
435 | uint64_t unsafe_shutdowns[2]; | |
436 | uint64_t media_errors[2]; | |
437 | uint64_t number_of_error_log_entries[2]; | |
438 | uint8_t reserved2[320]; | |
439 | } NvmeSmartLog; | |
440 | ||
441 | enum NvmeSmartWarn { | |
442 | NVME_SMART_SPARE = 1 << 0, | |
443 | NVME_SMART_TEMPERATURE = 1 << 1, | |
444 | NVME_SMART_RELIABILITY = 1 << 2, | |
445 | NVME_SMART_MEDIA_READ_ONLY = 1 << 3, | |
446 | NVME_SMART_FAILED_VOLATILE_MEDIA = 1 << 4, | |
447 | }; | |
448 | ||
449 | enum LogIdentifier { | |
450 | NVME_LOG_ERROR_INFO = 0x01, | |
451 | NVME_LOG_SMART_INFO = 0x02, | |
452 | NVME_LOG_FW_SLOT_INFO = 0x03, | |
453 | }; | |
454 | ||
455 | typedef struct NvmePSD { | |
456 | uint16_t mp; | |
457 | uint16_t reserved; | |
458 | uint32_t enlat; | |
459 | uint32_t exlat; | |
460 | uint8_t rrt; | |
461 | uint8_t rrl; | |
462 | uint8_t rwt; | |
463 | uint8_t rwl; | |
464 | uint8_t resv[16]; | |
465 | } NvmePSD; | |
466 | ||
467 | typedef struct NvmeIdCtrl { | |
468 | uint16_t vid; | |
469 | uint16_t ssvid; | |
470 | uint8_t sn[20]; | |
471 | uint8_t mn[40]; | |
472 | uint8_t fr[8]; | |
473 | uint8_t rab; | |
474 | uint8_t ieee[3]; | |
475 | uint8_t cmic; | |
476 | uint8_t mdts; | |
477 | uint8_t rsvd255[178]; | |
478 | uint16_t oacs; | |
479 | uint8_t acl; | |
480 | uint8_t aerl; | |
481 | uint8_t frmw; | |
482 | uint8_t lpa; | |
483 | uint8_t elpe; | |
484 | uint8_t npss; | |
485 | uint8_t rsvd511[248]; | |
486 | uint8_t sqes; | |
487 | uint8_t cqes; | |
488 | uint16_t rsvd515; | |
489 | uint32_t nn; | |
490 | uint16_t oncs; | |
491 | uint16_t fuses; | |
492 | uint8_t fna; | |
493 | uint8_t vwc; | |
494 | uint16_t awun; | |
495 | uint16_t awupf; | |
496 | uint8_t rsvd703[174]; | |
497 | uint8_t rsvd2047[1344]; | |
498 | NvmePSD psd[32]; | |
499 | uint8_t vs[1024]; | |
500 | } NvmeIdCtrl; | |
501 | ||
502 | enum NvmeIdCtrlOacs { | |
503 | NVME_OACS_SECURITY = 1 << 0, | |
504 | NVME_OACS_FORMAT = 1 << 1, | |
505 | NVME_OACS_FW = 1 << 2, | |
506 | }; | |
507 | ||
508 | enum NvmeIdCtrlOncs { | |
509 | NVME_ONCS_COMPARE = 1 << 0, | |
510 | NVME_ONCS_WRITE_UNCORR = 1 << 1, | |
511 | NVME_ONCS_DSM = 1 << 2, | |
512 | NVME_ONCS_WRITE_ZEROS = 1 << 3, | |
513 | NVME_ONCS_FEATURES = 1 << 4, | |
514 | NVME_ONCS_RESRVATIONS = 1 << 5, | |
515 | }; | |
516 | ||
517 | #define NVME_CTRL_SQES_MIN(sqes) ((sqes) & 0xf) | |
518 | #define NVME_CTRL_SQES_MAX(sqes) (((sqes) >> 4) & 0xf) | |
519 | #define NVME_CTRL_CQES_MIN(cqes) ((cqes) & 0xf) | |
520 | #define NVME_CTRL_CQES_MAX(cqes) (((cqes) >> 4) & 0xf) | |
521 | ||
522 | typedef struct NvmeFeatureVal { | |
523 | uint32_t arbitration; | |
524 | uint32_t power_mgmt; | |
525 | uint32_t temp_thresh; | |
526 | uint32_t err_rec; | |
527 | uint32_t volatile_wc; | |
528 | uint32_t num_queues; | |
529 | uint32_t int_coalescing; | |
530 | uint32_t *int_vector_config; | |
531 | uint32_t write_atomicity; | |
532 | uint32_t async_config; | |
533 | uint32_t sw_prog_marker; | |
534 | } NvmeFeatureVal; | |
535 | ||
536 | #define NVME_ARB_AB(arb) (arb & 0x7) | |
537 | #define NVME_ARB_LPW(arb) ((arb >> 8) & 0xff) | |
538 | #define NVME_ARB_MPW(arb) ((arb >> 16) & 0xff) | |
539 | #define NVME_ARB_HPW(arb) ((arb >> 24) & 0xff) | |
540 | ||
541 | #define NVME_INTC_THR(intc) (intc & 0xff) | |
542 | #define NVME_INTC_TIME(intc) ((intc >> 8) & 0xff) | |
543 | ||
544 | enum NvmeFeatureIds { | |
545 | NVME_ARBITRATION = 0x1, | |
546 | NVME_POWER_MANAGEMENT = 0x2, | |
547 | NVME_LBA_RANGE_TYPE = 0x3, | |
548 | NVME_TEMPERATURE_THRESHOLD = 0x4, | |
549 | NVME_ERROR_RECOVERY = 0x5, | |
550 | NVME_VOLATILE_WRITE_CACHE = 0x6, | |
551 | NVME_NUMBER_OF_QUEUES = 0x7, | |
552 | NVME_INTERRUPT_COALESCING = 0x8, | |
553 | NVME_INTERRUPT_VECTOR_CONF = 0x9, | |
554 | NVME_WRITE_ATOMICITY = 0xa, | |
555 | NVME_ASYNCHRONOUS_EVENT_CONF = 0xb, | |
556 | NVME_SOFTWARE_PROGRESS_MARKER = 0x80 | |
557 | }; | |
558 | ||
559 | typedef struct NvmeRangeType { | |
560 | uint8_t type; | |
561 | uint8_t attributes; | |
562 | uint8_t rsvd2[14]; | |
563 | uint64_t slba; | |
564 | uint64_t nlb; | |
565 | uint8_t guid[16]; | |
566 | uint8_t rsvd48[16]; | |
567 | } NvmeRangeType; | |
568 | ||
569 | typedef struct NvmeLBAF { | |
570 | uint16_t ms; | |
571 | uint8_t ds; | |
572 | uint8_t rp; | |
573 | } NvmeLBAF; | |
574 | ||
575 | typedef struct NvmeIdNs { | |
576 | uint64_t nsze; | |
577 | uint64_t ncap; | |
578 | uint64_t nuse; | |
579 | uint8_t nsfeat; | |
580 | uint8_t nlbaf; | |
581 | uint8_t flbas; | |
582 | uint8_t mc; | |
583 | uint8_t dpc; | |
584 | uint8_t dps; | |
585 | uint8_t res30[98]; | |
586 | NvmeLBAF lbaf[16]; | |
587 | uint8_t res192[192]; | |
588 | uint8_t vs[3712]; | |
589 | } NvmeIdNs; | |
590 | ||
591 | #define NVME_ID_NS_NSFEAT_THIN(nsfeat) ((nsfeat & 0x1)) | |
592 | #define NVME_ID_NS_FLBAS_EXTENDED(flbas) ((flbas >> 4) & 0x1) | |
593 | #define NVME_ID_NS_FLBAS_INDEX(flbas) ((flbas & 0xf)) | |
594 | #define NVME_ID_NS_MC_SEPARATE(mc) ((mc >> 1) & 0x1) | |
595 | #define NVME_ID_NS_MC_EXTENDED(mc) ((mc & 0x1)) | |
596 | #define NVME_ID_NS_DPC_LAST_EIGHT(dpc) ((dpc >> 4) & 0x1) | |
597 | #define NVME_ID_NS_DPC_FIRST_EIGHT(dpc) ((dpc >> 3) & 0x1) | |
598 | #define NVME_ID_NS_DPC_TYPE_3(dpc) ((dpc >> 2) & 0x1) | |
599 | #define NVME_ID_NS_DPC_TYPE_2(dpc) ((dpc >> 1) & 0x1) | |
600 | #define NVME_ID_NS_DPC_TYPE_1(dpc) ((dpc & 0x1)) | |
601 | #define NVME_ID_NS_DPC_TYPE_MASK 0x7 | |
602 | ||
603 | enum NvmeIdNsDps { | |
604 | DPS_TYPE_NONE = 0, | |
605 | DPS_TYPE_1 = 1, | |
606 | DPS_TYPE_2 = 2, | |
607 | DPS_TYPE_3 = 3, | |
608 | DPS_TYPE_MASK = 0x7, | |
609 | DPS_FIRST_EIGHT = 8, | |
610 | }; | |
611 | ||
612 | static inline void _nvme_check_size(void) | |
613 | { | |
614 | QEMU_BUILD_BUG_ON(sizeof(NvmeAerResult) != 4); | |
615 | QEMU_BUILD_BUG_ON(sizeof(NvmeCqe) != 16); | |
616 | QEMU_BUILD_BUG_ON(sizeof(NvmeDsmRange) != 16); | |
617 | QEMU_BUILD_BUG_ON(sizeof(NvmeCmd) != 64); | |
618 | QEMU_BUILD_BUG_ON(sizeof(NvmeDeleteQ) != 64); | |
619 | QEMU_BUILD_BUG_ON(sizeof(NvmeCreateCq) != 64); | |
620 | QEMU_BUILD_BUG_ON(sizeof(NvmeCreateSq) != 64); | |
621 | QEMU_BUILD_BUG_ON(sizeof(NvmeIdentify) != 64); | |
622 | QEMU_BUILD_BUG_ON(sizeof(NvmeRwCmd) != 64); | |
623 | QEMU_BUILD_BUG_ON(sizeof(NvmeDsmCmd) != 64); | |
624 | QEMU_BUILD_BUG_ON(sizeof(NvmeRangeType) != 64); | |
625 | QEMU_BUILD_BUG_ON(sizeof(NvmeErrorLog) != 64); | |
626 | QEMU_BUILD_BUG_ON(sizeof(NvmeFwSlotInfoLog) != 512); | |
627 | QEMU_BUILD_BUG_ON(sizeof(NvmeSmartLog) != 512); | |
628 | QEMU_BUILD_BUG_ON(sizeof(NvmeIdCtrl) != 4096); | |
629 | QEMU_BUILD_BUG_ON(sizeof(NvmeIdNs) != 4096); | |
630 | } | |
631 | ||
632 | typedef struct NvmeAsyncEvent { | |
633 | QSIMPLEQ_ENTRY(NvmeAsyncEvent) entry; | |
634 | NvmeAerResult result; | |
635 | } NvmeAsyncEvent; | |
636 | ||
637 | typedef struct NvmeRequest { | |
638 | struct NvmeSQueue *sq; | |
639 | BlockDriverAIOCB *aiocb; | |
640 | uint16_t status; | |
641 | NvmeCqe cqe; | |
642 | BlockAcctCookie acct; | |
643 | QEMUSGList qsg; | |
644 | QTAILQ_ENTRY(NvmeRequest)entry; | |
645 | } NvmeRequest; | |
646 | ||
647 | typedef struct NvmeSQueue { | |
648 | struct NvmeCtrl *ctrl; | |
649 | uint16_t sqid; | |
650 | uint16_t cqid; | |
651 | uint32_t head; | |
652 | uint32_t tail; | |
653 | uint32_t size; | |
654 | uint64_t dma_addr; | |
655 | QEMUTimer *timer; | |
656 | NvmeRequest *io_req; | |
657 | QTAILQ_HEAD(sq_req_list, NvmeRequest) req_list; | |
658 | QTAILQ_HEAD(out_req_list, NvmeRequest) out_req_list; | |
659 | QTAILQ_ENTRY(NvmeSQueue) entry; | |
660 | } NvmeSQueue; | |
661 | ||
662 | typedef struct NvmeCQueue { | |
663 | struct NvmeCtrl *ctrl; | |
664 | uint8_t phase; | |
665 | uint16_t cqid; | |
666 | uint16_t irq_enabled; | |
667 | uint32_t head; | |
668 | uint32_t tail; | |
669 | uint32_t vector; | |
670 | uint32_t size; | |
671 | uint64_t dma_addr; | |
672 | QEMUTimer *timer; | |
673 | QTAILQ_HEAD(sq_list, NvmeSQueue) sq_list; | |
674 | QTAILQ_HEAD(cq_req_list, NvmeRequest) req_list; | |
675 | } NvmeCQueue; | |
676 | ||
677 | typedef struct NvmeNamespace { | |
678 | NvmeIdNs id_ns; | |
679 | } NvmeNamespace; | |
680 | ||
681 | #define TYPE_NVME "nvme" | |
682 | #define NVME(obj) \ | |
683 | OBJECT_CHECK(NvmeCtrl, (obj), TYPE_NVME) | |
684 | ||
685 | typedef struct NvmeCtrl { | |
686 | PCIDevice parent_obj; | |
687 | MemoryRegion iomem; | |
688 | NvmeBar bar; | |
689 | BlockConf conf; | |
690 | ||
691 | uint16_t page_size; | |
692 | uint16_t page_bits; | |
693 | uint16_t max_prp_ents; | |
694 | uint16_t cqe_size; | |
695 | uint16_t sqe_size; | |
696 | uint32_t reg_size; | |
697 | uint32_t num_namespaces; | |
698 | uint32_t num_queues; | |
699 | uint32_t max_q_ents; | |
700 | uint64_t ns_size; | |
701 | ||
702 | char *serial; | |
703 | NvmeNamespace *namespaces; | |
704 | NvmeSQueue **sq; | |
705 | NvmeCQueue **cq; | |
706 | NvmeSQueue admin_sq; | |
707 | NvmeCQueue admin_cq; | |
708 | NvmeIdCtrl id_ctrl; | |
709 | } NvmeCtrl; | |
710 | ||
711 | #endif /* HW_NVME_H */ |