summaryrefslogtreecommitdiff
path: root/sys/dev/ic/nvmereg.h
blob: 1c73115445258145fc2059a72ccbae20dbeb76b7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
/*	$OpenBSD: nvmereg.h,v 1.11 2016/11/15 12:01:11 mpi Exp $ */

/*
 * Copyright (c) 2014 David Gwynne <dlg@openbsd.org>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#define NVME_CAP	0x0000	/* Controller Capabilities */
#define  NVME_CAP_MPSMAX(_r)	(12 + (((_r) >> 52) & 0xf)) /* shift */
#define  NVME_CAP_MPSMIN(_r)	(12 + (((_r) >> 48) & 0xf)) /* shift */
#define  NVME_CAP_CSS(_r)	(((_r) >> 37) & 0x7f)
#define  NVME_CAP_CSS_NVM	(1 << 0)
#define  NVME_CAP_NSSRS(_r)	ISSET((_r), (1ULL << 36))
#define  NVME_CAP_DSTRD(_r)	(1 << (2 + (((_r) >> 32) & 0xf))) /* bytes */
#define  NVME_CAP_TO(_r)	(500 * (((_r) >> 24) & 0xff)) /* ms */
#define  NVME_CAP_AMS(_r)	(((_r) >> 17) & 0x3)
#define  NVME_CAP_AMS_WRR	(1 << 0)
#define  NVME_CAP_AMS_VENDOR	(1 << 1)
#define  NVME_CAP_CQR(_r)	ISSET((_r), (1 << 16))
#define  NVME_CAP_MQES(_r)	(((_r) & 0xffff) + 1)
#define NVME_CAP_LO	0x0000
#define NVME_CAP_HI	0x0004
#define NVME_VS		0x0008	/* Version */
#define  NVME_VS_MJR(_r)	(((_r) & 0xffff0000) >> 16)
#define  NVME_VS_MNR(_r)	(((_r) & 0x0000ff00) >> 8)
#define NVME_INTMS	0x000c	/* Interrupt Mask Set */
#define NVME_INTMC	0x0010	/* Interrupt Mask Clear */
#define NVME_CC		0x0014	/* Controller Configuration */
#define  NVME_CC_IOCQES(_v)	(((_v) & 0xf) << 20)
#define  NVME_CC_IOCQES_MASK	NVME_CC_IOCQES(0xf)
#define  NVME_CC_IOCQES_R(_v)	(((_v) >> 20) & 0xf)
#define  NVME_CC_IOSQES(_v)	(((_v) & 0xf) << 16)
#define  NVME_CC_IOSQES_MASK	NVME_CC_IOSQES(0xf)
#define  NVME_CC_IOSQES_R(_v)	(((_v) >> 16) & 0xf)
#define  NVME_CC_SHN(_v)	(((_v) & 0x3) << 14)
#define  NVME_CC_SHN_MASK	NVME_CC_SHN(0x3)
#define  NVME_CC_SHN_R(_v)	(((_v) >> 15) & 0x3)
#define  NVME_CC_SHN_NONE	0
#define  NVME_CC_SHN_NORMAL	1
#define  NVME_CC_SHN_ABRUPT	2
#define  NVME_CC_AMS(_v)	(((_v) & 0x7) << 11)
#define  NVME_CC_AMS_MASK	NVME_CC_AMS(0x7)
#define  NVME_CC_AMS_R(_v)	(((_v) >> 11) & 0xf)
#define  NVME_CC_AMS_RR		0 /* round-robin */
#define  NVME_CC_AMS_WRR_U	1 /* weighted round-robin w/ urgent */
#define  NVME_CC_AMS_VENDOR	7 /* vendor */
#define  NVME_CC_MPS(_v)	((((_v) - 12) & 0xf) << 7)
#define  NVME_CC_MPS_MASK	(0xf << 7)
#define  NVME_CC_MPS_R(_v)	(12 + (((_v) >> 7) & 0xf))
#define  NVME_CC_CSS(_v)	(((_v) & 0x7) << 4)
#define  NVME_CC_CSS_MASK	NVME_CC_CSS(0x7)
#define  NVME_CC_CSS_R(_v)	(((_v) >> 4) & 0x7)
#define  NVME_CC_CSS_NVM	0
#define  NVME_CC_EN		(1 << 0)
#define NVME_CSTS	0x001c	/* Controller Status */
#define  NVME_CSTS_SHST_MASK	(0x3 << 2)
#define  NVME_CSTS_SHST_NONE	(0x0 << 2) /* normal operation */
#define  NVME_CSTS_SHST_WAIT	(0x1 << 2) /* shutdown processing occurring */
#define  NVME_CSTS_SHST_DONE	(0x2 << 2) /* shutdown processing complete */
#define  NVME_CSTS_CFS		(1 << 1)
#define  NVME_CSTS_RDY		(1 << 0)
#define NVME_NSSR	0x0020	/* NVM Subsystem Reset (Optional) */
#define NVME_AQA	0x0024	/* Admin Queue Attributes */
				/* Admin Completion Queue Size */
#define  NVME_AQA_ACQS(_v)	(((_v) - 1) << 16)
				/* Admin Submission Queue Size */
#define  NVME_AQA_ASQS(_v)	(((_v) - 1) << 0)
#define NVME_ASQ	0x0028	/* Admin Submission Queue Base Address */
#define NVME_ACQ	0x0030	/* Admin Completion Queue Base Address */

#define NVME_ADMIN_Q		0
/* Submission Queue Tail Doorbell */
#define NVME_SQTDBL(_q, _s)	(0x1000 + (2 * (_q) + 0) * (_s))
/* Completion Queue Head Doorbell */
#define NVME_CQHDBL(_q, _s)	(0x1000 + (2 * (_q) + 1) * (_s))

struct nvme_sge {
	u_int8_t	id;
	u_int8_t	_reserved[15];
} __packed __aligned(8);

struct nvme_sge_data {
	u_int8_t	id;
	u_int8_t	_reserved[3];

	u_int32_t	length;

	u_int64_t	address;
} __packed __aligned(8);

struct nvme_sge_bit_bucket {
	u_int8_t	id;
	u_int8_t	_reserved[3];

	u_int32_t	length;

	u_int64_t	address;
} __packed __aligned(8);

struct nvme_sqe {
	u_int8_t	opcode;
	u_int8_t	flags;
	u_int16_t	cid;

	u_int32_t	nsid;

	u_int8_t	_reserved[8];

	u_int64_t	mptr;

	union {
		u_int64_t	prp[2];
		struct nvme_sge	sge;
	} __packed	entry;

	u_int32_t	cdw10;
	u_int32_t	cdw11;
	u_int32_t	cdw12;
	u_int32_t	cdw13;
	u_int32_t	cdw14;
	u_int32_t	cdw15;
} __packed __aligned(8);

struct nvme_sqe_q {
	u_int8_t	opcode;
	u_int8_t	flags;
	u_int16_t	cid;

	u_int8_t	_reserved1[20];

	u_int64_t	prp1;

	u_int8_t	_reserved2[8];

	u_int16_t	qid;
	u_int16_t	qsize;

	u_int8_t	qflags;
#define NVM_SQE_SQ_QPRIO_URG	(0x0 << 1)
#define NVM_SQE_SQ_QPRIO_HI	(0x1 << 1)
#define NVM_SQE_SQ_QPRIO_MED	(0x2 << 1)
#define NVM_SQE_SQ_QPRIO_LOW	(0x3 << 1)
#define NVM_SQE_CQ_IEN		(1 << 1)
#define NVM_SQE_Q_PC		(1 << 0)
	u_int8_t	_reserved3;
	u_int16_t	cqid; /* XXX interrupt vector for cq */

	u_int8_t	_reserved4[16];
} __packed __aligned(8);

struct nvme_sqe_io {
	u_int8_t	opcode;
	u_int8_t	flags;
	u_int16_t	cid;

	u_int32_t	nsid;

	u_int8_t	_reserved[8];

	u_int64_t	mptr;

	union {
		u_int64_t	prp[2];
		struct nvme_sge	sge;
	} __packed	entry;

	u_int64_t	slba;	/* Starting LBA */

	u_int16_t	nlb;	/* Number of Logical Blocks */
	u_int16_t	ioflags;

	u_int8_t	dsm;	/* Dataset Management */
	u_int8_t	_reserved2[3];

	u_int32_t	eilbrt;	/* Expected Initial Logical Block
				   Reference Tag */

	u_int16_t	elbat;	/* Expected Logical Block
				   Application Tag */
	u_int16_t	elbatm;	/* Expected Logical Block
				   Application Tag Mask */
} __packed __aligned(8);

struct nvme_cqe {
	u_int32_t	cdw0;

	u_int32_t	_reserved;

	u_int16_t	sqhd; /* SQ Head Pointer */
	u_int16_t	sqid; /* SQ Identifier */

	u_int16_t	cid; /* Command Identifier */
	u_int16_t	flags;
#define NVME_CQE_DNR		(1 << 15)
#define NVME_CQE_M		(1 << 14)
#define NVME_CQE_SCT(_f)	((_f) & (0x07 << 8))
#define  NVME_CQE_SCT_GENERIC		(0x00 << 8)
#define  NVME_CQE_SCT_COMMAND		(0x01 << 8)
#define  NVME_CQE_SCT_MEDIAERR		(0x02 << 8)
#define  NVME_CQE_SCT_VENDOR		(0x07 << 8)
#define NVME_CQE_SC(_f)		((_f) & (0x7f << 1))
#define  NVME_CQE_SC_SUCCESS		(0x00 << 1)
#define  NVME_CQE_SC_INVALID_OPCODE	(0x01 << 1)
#define  NVME_CQE_SC_INVALID_FIELD	(0x02 << 1)
#define  NVME_CQE_SC_CID_CONFLICT	(0x03 << 1)
#define  NVME_CQE_SC_DATA_XFER_ERR	(0x04 << 1)
#define  NVME_CQE_SC_ABRT_BY_NO_PWR	(0x05 << 1)
#define  NVME_CQE_SC_INTERNAL_DEV_ERR	(0x06 << 1)
#define  NVME_CQE_SC_CMD_ABRT_REQD	(0x07 << 1)
#define  NVME_CQE_SC_CMD_ABDR_SQ_DEL	(0x08 << 1)
#define  NVME_CQE_SC_CMD_ABDR_FUSE_ERR	(0x09 << 1)
#define  NVME_CQE_SC_CMD_ABDR_FUSE_MISS	(0x0a << 1)
#define  NVME_CQE_SC_INVALID_NS		(0x0b << 1)
#define  NVME_CQE_SC_CMD_SEQ_ERR	(0x0c << 1)
#define  NVME_CQE_SC_INVALID_LAST_SGL	(0x0d << 1)
#define  NVME_CQE_SC_INVALID_NUM_SGL	(0x0e << 1)
#define  NVME_CQE_SC_DATA_SGL_LEN	(0x0f << 1)
#define  NVME_CQE_SC_MDATA_SGL_LEN	(0x10 << 1)
#define  NVME_CQE_SC_SGL_TYPE_INVALID	(0x11 << 1)
#define  NVME_CQE_SC_LBA_RANGE		(0x80 << 1)
#define  NVME_CQE_SC_CAP_EXCEEDED	(0x81 << 1)
#define  NVME_CQE_NS_NOT_RDY		(0x82 << 1)
#define  NVME_CQE_RSV_CONFLICT		(0x83 << 1)
#define NVME_CQE_PHASE		(1 << 0)
} __packed __aligned(8);

#define NVM_ADMIN_DEL_IOSQ	0x00 /* Delete I/O Submission Queue */
#define NVM_ADMIN_ADD_IOSQ	0x01 /* Create I/O Submission Queue */
#define NVM_ADMIN_GET_LOG_PG	0x02 /* Get Log Page */
#define NVM_ADMIN_DEL_IOCQ	0x04 /* Delete I/O Completion Queue */ 
#define NVM_ADMIN_ADD_IOCQ	0x05 /* Create I/O Completion Queue */ 
#define NVM_ADMIN_IDENTIFY	0x06 /* Identify */
#define NVM_ADMIN_ABORT		0x08 /* Abort */
#define NVM_ADMIN_SET_FEATURES	0x09 /* Set Features */
#define NVM_ADMIN_GET_FEATURES	0x0a /* Get Features */
#define NVM_ADMIN_ASYNC_EV_REQ	0x0c /* Asynchronous Event Request */
#define NVM_ADMIN_FW_ACTIVATE	0x10 /* Firmware Activate */
#define NVM_ADMIN_FW_DOWNLOAD	0x11 /* Firmware Image Download */

#define NVM_CMD_FLUSH		0x00 /* Flush */
#define NVM_CMD_WRITE		0x01 /* Write */
#define NVM_CMD_READ		0x02 /* Read */
#define NVM_CMD_WR_UNCOR	0x04 /* Write Uncorrectable */
#define NVM_CMD_COMPARE		0x05 /* Compare */
#define NVM_CMD_DSM		0x09 /* Dataset Management */

/* Power State Descriptor Data */
struct nvm_identify_psd {
	u_int16_t	mp;		/* Max Power */
	u_int16_t	flags;

	u_int32_t	enlat;		/* Entry Latency */

	u_int32_t	exlat;		/* Exit Latency */

	u_int8_t	rrt;		/* Relative Read Throughput */
	u_int8_t	rrl;		/* Relative Read Latency */
	u_int8_t	rwt;		/* Relative Write Throughput */
	u_int8_t	rwl;		/* Relative Write Latency */

	u_int8_t	_reserved[16];
} __packed __aligned(8);

struct nvm_identify_controller {
	/* Controller Capabilities and Features */

	u_int16_t	vid;		/* PCI Vendor ID */
	u_int16_t	ssvid;		/* PCI Subsystem Vendor ID */

	u_int8_t	sn[20];		/* Serial Number */
	u_int8_t	mn[40];		/* Model Number */
	u_int8_t	fr[8];		/* Firmware Revision */

	u_int8_t	rab;		/* Recommended Arbitration Burst */
	u_int8_t	ieee[3];	/* IEEE OUI Identifier */

	u_int8_t	cmic;		/* Controller Multi-Path I/O and
					   Namespace Sharing Capabilities */
	u_int8_t	mdts;		/* Maximum Data Transfer Size */
	u_int16_t	cntlid;		/* Controller ID */

	u_int8_t	_reserved1[176];

	/* Admin Command Set Attributes & Optional Controller Capabilities */

	u_int16_t	oacs;		/* Optional Admin Command Support */
	u_int8_t	acl;		/* Abort Command Limit */
	u_int8_t	aerl;		/* Asynchronous Event Request Limit */

	u_int8_t	frmw;		/* Firmware Updates */
	u_int8_t	lpa;		/* Log Page Attributes */
	u_int8_t	elpe;		/* Error Log Page Entries */
	u_int8_t	npss;		/* Number of Power States Support */

	u_int8_t	avscc;		/* Admin Vendor Specific Command
					   Configuration */
	u_int8_t	apsta;		/* Autonomous Power State Transition
					   Attributes */

	u_int8_t	_reserved2[246];

	/* NVM Command Set Attributes */

	u_int8_t	sqes;		/* Submission Queue Entry Size */
	u_int8_t	cqes;		/* Completion Queue Entry Size */
	u_int8_t	_reserved3[2];

	u_int32_t	nn;		/* Number of Namespaces */

	u_int16_t	oncs;		/* Optional NVM Command Support */
	u_int16_t	fuses;		/* Fused Operation Support */

	u_int8_t	fna;		/* Format NVM Attributes */
	u_int8_t	vwc;		/* Volatile Write Cache */
	u_int16_t	awun;		/* Atomic Write Unit Normal */

	u_int16_t	awupf;		/* Atomic Write Unit Power Fail */
	u_int8_t	nvscc;		/* NVM Vendor Specific Command */
	u_int8_t	_reserved4[1];

	u_int16_t	acwu;		/* Atomic Compare & Write Unit */
	u_int8_t	_reserved5[2];

	u_int32_t	sgls;		/* SGL Support */

	u_int8_t	_reserved6[164];

	/* I/O Command Set Attributes */

	u_int8_t	_reserved7[1344];

	/* Power State Descriptors */

	struct nvm_identify_psd psd[32]; /* Power State Descriptors */

	/* Vendor Specific */

	u_int8_t	_reserved8[1024];
} __packed __aligned(8);

struct nvm_namespace_format {
	u_int16_t	ms;		/* Metadata Size */
	u_int8_t	lbads;		/* LBA Data Size */
	u_int8_t	rp;		/* Relative Performance */
} __packed __aligned(4);

struct nvm_identify_namespace {
	u_int64_t	nsze;		/* Namespace Size */

	u_int64_t	ncap;		/* Namespace Capacity */

	u_int64_t	nuse;		/* Namespace Utilization */

	u_int8_t	nsfeat;		/* Namespace Features */
	u_int8_t	nlbaf;		/* Number of LBA Formats */
	u_int8_t	flbas;		/* Formatted LBA Size */
#define NVME_ID_NS_FLBAS(_f)			((_f) & 0x0f)
#define NVME_ID_NS_FLBAS_MD			0x10
	u_int8_t	mc;		/* Metadata Capabilities */
	u_int8_t	dpc;		/* End-to-end Data Protection
					   Capabilities */
	u_int8_t	dps;		/* End-to-end Data Protection Type Settings */

	u_int8_t	_reserved1[98];

	struct nvm_namespace_format
			lbaf[16];	/* LBA Format Support */

	u_int8_t	_reserved2[192];

	u_int8_t	vs[3712];
} __packed __aligned(8);