nvme.h revision 248739
1240616Sjimharris/*-
2240616Sjimharris * Copyright (C) 2012 Intel Corporation
3240616Sjimharris * All rights reserved.
4240616Sjimharris *
5240616Sjimharris * Redistribution and use in source and binary forms, with or without
6240616Sjimharris * modification, are permitted provided that the following conditions
7240616Sjimharris * are met:
8240616Sjimharris * 1. Redistributions of source code must retain the above copyright
9240616Sjimharris *    notice, this list of conditions and the following disclaimer.
10240616Sjimharris * 2. Redistributions in binary form must reproduce the above copyright
11240616Sjimharris *    notice, this list of conditions and the following disclaimer in the
12240616Sjimharris *    documentation and/or other materials provided with the distribution.
13240616Sjimharris *
14240616Sjimharris * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15240616Sjimharris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16240616Sjimharris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17240616Sjimharris * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18240616Sjimharris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19240616Sjimharris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20240616Sjimharris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21240616Sjimharris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22240616Sjimharris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23240616Sjimharris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24240616Sjimharris * SUCH DAMAGE.
25240616Sjimharris *
26240616Sjimharris * $FreeBSD: head/sys/dev/nvme/nvme.h 248739 2013-03-26 18:42:05Z jimharris $
27240616Sjimharris */
28240616Sjimharris
29240616Sjimharris#ifndef __NVME_H__
30240616Sjimharris#define __NVME_H__
31240616Sjimharris
32240616Sjimharris#ifdef _KERNEL
33240616Sjimharris#include <sys/types.h>
34240616Sjimharris#endif
35240616Sjimharris
36240616Sjimharris#define	NVME_IDENTIFY_CONTROLLER	_IOR('n', 0, struct nvme_controller_data)
37240616Sjimharris#define	NVME_IDENTIFY_NAMESPACE		_IOR('n', 1, struct nvme_namespace_data)
38240616Sjimharris#define	NVME_IO_TEST			_IOWR('n', 2, struct nvme_io_test)
39240616Sjimharris#define	NVME_BIO_TEST			_IOWR('n', 4, struct nvme_io_test)
40240616Sjimharris
41240616Sjimharris/*
42240616Sjimharris * Use to mark a command to apply to all namespaces, or to retrieve global
43240616Sjimharris *  log pages.
44240616Sjimharris */
45240616Sjimharris#define NVME_GLOBAL_NAMESPACE_TAG	((uint32_t)0xFFFFFFFF)
46240616Sjimharris
47240616Sjimharrisunion cap_lo_register {
48240616Sjimharris	uint32_t	raw;
49240616Sjimharris	struct {
50240616Sjimharris		/** maximum queue entries supported */
51240616Sjimharris		uint32_t mqes		: 16;
52240616Sjimharris
53240616Sjimharris		/** contiguous queues required */
54240616Sjimharris		uint32_t cqr		: 1;
55240616Sjimharris
56240616Sjimharris		/** arbitration mechanism supported */
57240616Sjimharris		uint32_t ams		: 2;
58240616Sjimharris
59240616Sjimharris		uint32_t reserved1	: 5;
60240616Sjimharris
61240616Sjimharris		/** timeout */
62240616Sjimharris		uint32_t to		: 8;
63240616Sjimharris	} bits __packed;
64240616Sjimharris} __packed;
65240616Sjimharris
66240616Sjimharrisunion cap_hi_register {
67240616Sjimharris	uint32_t	raw;
68240616Sjimharris	struct {
69240616Sjimharris		/** doorbell stride */
70240616Sjimharris		uint32_t dstrd		: 4;
71240616Sjimharris
72240616Sjimharris		uint32_t reserved3	: 1;
73240616Sjimharris
74240616Sjimharris		/** command sets supported */
75240616Sjimharris		uint32_t css_nvm	: 1;
76240616Sjimharris
77240616Sjimharris		uint32_t css_reserved	: 3;
78240616Sjimharris		uint32_t reserved2	: 7;
79240616Sjimharris
80240616Sjimharris		/** memory page size minimum */
81240616Sjimharris		uint32_t mpsmin		: 4;
82240616Sjimharris
83240616Sjimharris		/** memory page size maximum */
84240616Sjimharris		uint32_t mpsmax		: 4;
85240616Sjimharris
86240616Sjimharris		uint32_t reserved1	: 8;
87240616Sjimharris	} bits __packed;
88240616Sjimharris} __packed;
89240616Sjimharris
90240616Sjimharrisunion cc_register {
91240616Sjimharris	uint32_t	raw;
92240616Sjimharris	struct {
93240616Sjimharris		/** enable */
94240616Sjimharris		uint32_t en		: 1;
95240616Sjimharris
96240616Sjimharris		uint32_t reserved1	: 3;
97240616Sjimharris
98240616Sjimharris		/** i/o command set selected */
99240616Sjimharris		uint32_t css		: 3;
100240616Sjimharris
101240616Sjimharris		/** memory page size */
102240616Sjimharris		uint32_t mps		: 4;
103240616Sjimharris
104240616Sjimharris		/** arbitration mechanism selected */
105240616Sjimharris		uint32_t ams		: 3;
106240616Sjimharris
107240616Sjimharris		/** shutdown notification */
108240616Sjimharris		uint32_t shn		: 2;
109240616Sjimharris
110240616Sjimharris		/** i/o submission queue entry size */
111240616Sjimharris		uint32_t iosqes		: 4;
112240616Sjimharris
113240616Sjimharris		/** i/o completion queue entry size */
114240616Sjimharris		uint32_t iocqes		: 4;
115240616Sjimharris
116240616Sjimharris		uint32_t reserved2	: 8;
117240616Sjimharris	} bits __packed;
118240616Sjimharris} __packed;
119240616Sjimharris
120240616Sjimharrisenum shn_value {
121240616Sjimharris	NVME_SHN_NORMAL		= 0x1,
122240616Sjimharris	NVME_SHN_ABRUPT		= 0x2,
123240616Sjimharris};
124240616Sjimharris
125240616Sjimharrisunion csts_register {
126240616Sjimharris	uint32_t	raw;
127240616Sjimharris	struct {
128240616Sjimharris		/** ready */
129240616Sjimharris		uint32_t rdy		: 1;
130240616Sjimharris
131240616Sjimharris		/** controller fatal status */
132240616Sjimharris		uint32_t cfs		: 1;
133240616Sjimharris
134240616Sjimharris		/** shutdown status */
135240616Sjimharris		uint32_t shst		: 2;
136240616Sjimharris
137240616Sjimharris		uint32_t reserved1	: 28;
138240616Sjimharris	} bits __packed;
139240616Sjimharris} __packed;
140240616Sjimharris
141240616Sjimharrisenum shst_value {
142240616Sjimharris	NVME_SHST_NORMAL	= 0x0,
143240616Sjimharris	NVME_SHST_OCCURRING	= 0x1,
144240616Sjimharris	NVME_SHST_COMPLETE	= 0x2,
145240616Sjimharris};
146240616Sjimharris
147240616Sjimharrisunion aqa_register {
148240616Sjimharris	uint32_t	raw;
149240616Sjimharris	struct {
150240616Sjimharris		/** admin submission queue size */
151240616Sjimharris		uint32_t asqs		: 12;
152240616Sjimharris
153240616Sjimharris		uint32_t reserved1	: 4;
154240616Sjimharris
155240616Sjimharris		/** admin completion queue size */
156240616Sjimharris		uint32_t acqs		: 12;
157240616Sjimharris
158240616Sjimharris		uint32_t reserved2	: 4;
159240616Sjimharris	} bits __packed;
160240616Sjimharris} __packed;
161240616Sjimharris
162240616Sjimharrisstruct nvme_registers
163240616Sjimharris{
164240616Sjimharris	/** controller capabilities */
165240616Sjimharris	union cap_lo_register	cap_lo;
166240616Sjimharris	union cap_hi_register	cap_hi;
167240616Sjimharris
168240616Sjimharris	uint32_t	vs;		/* version */
169240616Sjimharris	uint32_t	intms;		/* interrupt mask set */
170240616Sjimharris	uint32_t	intmc;		/* interrupt mask clear */
171240616Sjimharris
172240616Sjimharris	/** controller configuration */
173240616Sjimharris	union cc_register	cc;
174240616Sjimharris
175240616Sjimharris	uint32_t	reserved1;
176240616Sjimharris	uint32_t	csts;		/* controller status */
177240616Sjimharris	uint32_t	reserved2;
178240616Sjimharris
179240616Sjimharris	/** admin queue attributes */
180240616Sjimharris	union aqa_register	aqa;
181240616Sjimharris
182240616Sjimharris	uint64_t	asq;		/* admin submission queue base addr */
183240616Sjimharris	uint64_t	acq;		/* admin completion queue base addr */
184240616Sjimharris	uint32_t	reserved3[0x3f2];
185240616Sjimharris
186240616Sjimharris	struct {
187240616Sjimharris	    uint32_t	sq_tdbl;	/* submission queue tail doorbell */
188240616Sjimharris	    uint32_t	cq_hdbl;	/* completion queue head doorbell */
189240616Sjimharris	} doorbell[1] __packed;
190240616Sjimharris} __packed;
191240616Sjimharris
192240616Sjimharrisstruct nvme_command
193240616Sjimharris{
194240616Sjimharris	/* dword 0 */
195240616Sjimharris	uint16_t opc	:  8;	/* opcode */
196240616Sjimharris	uint16_t fuse	:  2;	/* fused operation */
197240616Sjimharris	uint16_t rsvd1	:  6;
198240616Sjimharris	uint16_t cid;		/* command identifier */
199240616Sjimharris
200240616Sjimharris	/* dword 1 */
201240616Sjimharris	uint32_t nsid;		/* namespace identifier */
202240616Sjimharris
203240616Sjimharris	/* dword 2-3 */
204240616Sjimharris	uint32_t rsvd2;
205240616Sjimharris	uint32_t rsvd3;
206240616Sjimharris
207240616Sjimharris	/* dword 4-5 */
208240616Sjimharris	uint64_t mptr;		/* metadata pointer */
209240616Sjimharris
210240616Sjimharris	/* dword 6-7 */
211240616Sjimharris	uint64_t prp1;		/* prp entry 1 */
212240616Sjimharris
213240616Sjimharris	/* dword 8-9 */
214240616Sjimharris	uint64_t prp2;		/* prp entry 2 */
215240616Sjimharris
216240616Sjimharris	/* dword 10-15 */
217240616Sjimharris	uint32_t cdw10;		/* command-specific */
218240616Sjimharris	uint32_t cdw11;		/* command-specific */
219240616Sjimharris	uint32_t cdw12;		/* command-specific */
220240616Sjimharris	uint32_t cdw13;		/* command-specific */
221240616Sjimharris	uint32_t cdw14;		/* command-specific */
222240616Sjimharris	uint32_t cdw15;		/* command-specific */
223240616Sjimharris} __packed;
224240616Sjimharris
225240616Sjimharrisstruct nvme_completion {
226240616Sjimharris
227240616Sjimharris	/* dword 0 */
228240616Sjimharris	uint32_t cdw0;		/* command-specific */
229240616Sjimharris
230240616Sjimharris	/* dword 1 */
231240616Sjimharris	uint32_t rsvd1;
232240616Sjimharris
233240616Sjimharris	/* dword 2 */
234240616Sjimharris	uint16_t sqhd;		/* submission queue head pointer */
235240616Sjimharris	uint16_t sqid;		/* submission queue identifier */
236240616Sjimharris
237240616Sjimharris	/* dword 3 */
238240616Sjimharris	uint16_t cid;		/* command identifier */
239240616Sjimharris	uint16_t p	:  1;	/* phase tag */
240240616Sjimharris	uint16_t sf_sc	:  8;	/* status field - status code */
241240616Sjimharris	uint16_t sf_sct	:  3;	/* status field - status code type */
242240616Sjimharris	uint16_t rsvd2	:  2;
243240616Sjimharris	uint16_t sf_m	:  1;	/* status field - more */
244240616Sjimharris	uint16_t sf_dnr	:  1;	/* status field - do not retry */
245240616Sjimharris} __packed;
246240616Sjimharris
247240616Sjimharrisstruct nvme_dsm_range {
248240616Sjimharris
249240616Sjimharris	uint32_t attributes;
250240616Sjimharris	uint32_t length;
251240616Sjimharris	uint64_t starting_lba;
252240616Sjimharris} __packed;
253240616Sjimharris
254240616Sjimharris/* status code types */
255240616Sjimharrisenum nvme_status_code_type {
256240616Sjimharris	NVME_SCT_GENERIC		= 0x0,
257240616Sjimharris	NVME_SCT_COMMAND_SPECIFIC	= 0x1,
258240616Sjimharris	NVME_SCT_MEDIA_ERROR		= 0x2,
259240616Sjimharris	/* 0x3-0x6 - reserved */
260240616Sjimharris	NVME_SCT_VENDOR_SPECIFIC	= 0x7,
261240616Sjimharris};
262240616Sjimharris
263240616Sjimharris/* generic command status codes */
264240616Sjimharrisenum nvme_generic_command_status_code {
265240616Sjimharris	NVME_SC_SUCCESS				= 0x00,
266240616Sjimharris	NVME_SC_INVALID_OPCODE			= 0x01,
267240616Sjimharris	NVME_SC_INVALID_FIELD			= 0x02,
268240616Sjimharris	NVME_SC_COMMAND_ID_CONFLICT		= 0x03,
269240616Sjimharris	NVME_SC_DATA_TRANSFER_ERROR		= 0x04,
270240616Sjimharris	NVME_SC_ABORTED_POWER_LOSS		= 0x05,
271240616Sjimharris	NVME_SC_INTERNAL_DEVICE_ERROR		= 0x06,
272240616Sjimharris	NVME_SC_ABORTED_BY_REQUEST		= 0x07,
273240616Sjimharris	NVME_SC_ABORTED_SQ_DELETION		= 0x08,
274240616Sjimharris	NVME_SC_ABORTED_FAILED_FUSED		= 0x09,
275240616Sjimharris	NVME_SC_ABORTED_MISSING_FUSED		= 0x0a,
276240616Sjimharris	NVME_SC_INVALID_NAMESPACE_OR_FORMAT	= 0x0b,
277240616Sjimharris	NVME_SC_COMMAND_SEQUENCE_ERROR		= 0x0c,
278240616Sjimharris
279240616Sjimharris	NVME_SC_LBA_OUT_OF_RANGE		= 0x80,
280240616Sjimharris	NVME_SC_CAPACITY_EXCEEDED		= 0x81,
281240616Sjimharris	NVME_SC_NAMESPACE_NOT_READY		= 0x82,
282240616Sjimharris};
283240616Sjimharris
284240616Sjimharris/* command specific status codes */
285240616Sjimharrisenum nvme_command_specific_status_code {
286240616Sjimharris	NVME_SC_COMPLETION_QUEUE_INVALID	= 0x00,
287240616Sjimharris	NVME_SC_INVALID_QUEUE_IDENTIFIER	= 0x01,
288240616Sjimharris	NVME_SC_MAXIMUM_QUEUE_SIZE_EXCEEDED	= 0x02,
289240616Sjimharris	NVME_SC_ABORT_COMMAND_LIMIT_EXCEEDED	= 0x03,
290240616Sjimharris	/* 0x04 - reserved */
291240616Sjimharris	NVME_SC_ASYNC_EVENT_REQUEST_LIMIT_EXCEEDED = 0x05,
292240616Sjimharris	NVME_SC_INVALID_FIRMWARE_SLOT		= 0x06,
293240616Sjimharris	NVME_SC_INVALID_FIRMWARE_IMAGE		= 0x07,
294240616Sjimharris	NVME_SC_INVALID_INTERRUPT_VECTOR	= 0x08,
295240616Sjimharris	NVME_SC_INVALID_LOG_PAGE		= 0x09,
296240616Sjimharris	NVME_SC_INVALID_FORMAT			= 0x0a,
297240616Sjimharris	NVME_SC_FIRMWARE_REQUIRES_RESET		= 0x0b,
298240616Sjimharris
299240616Sjimharris	NVME_SC_CONFLICTING_ATTRIBUTES		= 0x80,
300240616Sjimharris	NVME_SC_INVALID_PROTECTION_INFO		= 0x81,
301240616Sjimharris	NVME_SC_ATTEMPTED_WRITE_TO_RO_PAGE	= 0x82,
302240616Sjimharris};
303240616Sjimharris
304240616Sjimharris/* media error status codes */
305240616Sjimharrisenum nvme_media_error_status_code {
306240616Sjimharris	NVME_SC_WRITE_FAULTS			= 0x80,
307240616Sjimharris	NVME_SC_UNRECOVERED_READ_ERROR		= 0x81,
308240616Sjimharris	NVME_SC_GUARD_CHECK_ERROR		= 0x82,
309240616Sjimharris	NVME_SC_APPLICATION_TAG_CHECK_ERROR	= 0x83,
310240616Sjimharris	NVME_SC_REFERENCE_TAG_CHECK_ERROR	= 0x84,
311240616Sjimharris	NVME_SC_COMPARE_FAILURE			= 0x85,
312240616Sjimharris	NVME_SC_ACCESS_DENIED			= 0x86,
313240616Sjimharris};
314240616Sjimharris
315240616Sjimharris/* admin opcodes */
316240616Sjimharrisenum nvme_admin_opcode {
317240616Sjimharris	NVME_OPC_DELETE_IO_SQ			= 0x00,
318240616Sjimharris	NVME_OPC_CREATE_IO_SQ			= 0x01,
319240616Sjimharris	NVME_OPC_GET_LOG_PAGE			= 0x02,
320240616Sjimharris	/* 0x03 - reserved */
321240616Sjimharris	NVME_OPC_DELETE_IO_CQ			= 0x04,
322240616Sjimharris	NVME_OPC_CREATE_IO_CQ			= 0x05,
323240616Sjimharris	NVME_OPC_IDENTIFY			= 0x06,
324240616Sjimharris	/* 0x07 - reserved */
325240616Sjimharris	NVME_OPC_ABORT				= 0x08,
326240616Sjimharris	NVME_OPC_SET_FEATURES			= 0x09,
327240616Sjimharris	NVME_OPC_GET_FEATURES			= 0x0a,
328240616Sjimharris	/* 0x0b - reserved */
329240616Sjimharris	NVME_OPC_ASYNC_EVENT_REQUEST		= 0x0c,
330240616Sjimharris	/* 0x0d-0x0f - reserved */
331240616Sjimharris	NVME_OPC_FIRMWARE_ACTIVATE		= 0x10,
332240616Sjimharris	NVME_OPC_FIRMWARE_IMAGE_DOWNLOAD	= 0x11,
333240616Sjimharris
334240616Sjimharris	NVME_OPC_FORMAT_NVM			= 0x80,
335240616Sjimharris	NVME_OPC_SECURITY_SEND			= 0x81,
336240616Sjimharris	NVME_OPC_SECURITY_RECEIVE		= 0x82,
337240616Sjimharris};
338240616Sjimharris
339240616Sjimharris/* nvme nvm opcodes */
340240616Sjimharrisenum nvme_nvm_opcode {
341240616Sjimharris	NVME_OPC_FLUSH				= 0x00,
342240616Sjimharris	NVME_OPC_WRITE				= 0x01,
343240616Sjimharris	NVME_OPC_READ				= 0x02,
344240616Sjimharris	/* 0x03 - reserved */
345240616Sjimharris	NVME_OPC_WRITE_UNCORRECTABLE		= 0x04,
346240616Sjimharris	NVME_OPC_COMPARE			= 0x05,
347240616Sjimharris	/* 0x06-0x07 - reserved */
348240616Sjimharris	NVME_OPC_DATASET_MANAGEMENT		= 0x09,
349240616Sjimharris};
350240616Sjimharris
351240616Sjimharrisenum nvme_feature {
352240616Sjimharris	/* 0x00 - reserved */
353240616Sjimharris	NVME_FEAT_ARBITRATION			= 0x01,
354240616Sjimharris	NVME_FEAT_POWER_MANAGEMENT		= 0x02,
355240616Sjimharris	NVME_FEAT_LBA_RANGE_TYPE		= 0x03,
356240616Sjimharris	NVME_FEAT_TEMPERATURE_THRESHOLD		= 0x04,
357240616Sjimharris	NVME_FEAT_ERROR_RECOVERY		= 0x05,
358240616Sjimharris	NVME_FEAT_VOLATILE_WRITE_CACHE		= 0x06,
359240616Sjimharris	NVME_FEAT_NUMBER_OF_QUEUES		= 0x07,
360240616Sjimharris	NVME_FEAT_INTERRUPT_COALESCING		= 0x08,
361240616Sjimharris	NVME_FEAT_INTERRUPT_VECTOR_CONFIGURATION = 0x09,
362240616Sjimharris	NVME_FEAT_WRITE_ATOMICITY		= 0x0A,
363248737Sjimharris	NVME_FEAT_ASYNC_EVENT_CONFIGURATION	= 0x0B,
364240616Sjimharris	/* 0x0C-0x7F - reserved */
365240616Sjimharris	NVME_FEAT_SOFTWARE_PROGRESS_MARKER	= 0x80,
366240616Sjimharris	/* 0x81-0xBF - command set specific (reserved) */
367240616Sjimharris	/* 0xC0-0xFF - vendor specific */
368240616Sjimharris};
369240616Sjimharris
370240616Sjimharrisenum nvme_dsm_attribute {
371240616Sjimharris	NVME_DSM_ATTR_INTEGRAL_READ		= 0x1,
372240616Sjimharris	NVME_DSM_ATTR_INTEGRAL_WRITE		= 0x2,
373240616Sjimharris	NVME_DSM_ATTR_DEALLOCATE		= 0x4,
374240616Sjimharris};
375240616Sjimharris
376240616Sjimharrisstruct nvme_controller_data {
377240616Sjimharris
378240616Sjimharris	/* bytes 0-255: controller capabilities and features */
379240616Sjimharris
380240616Sjimharris	/** pci vendor id */
381240616Sjimharris	uint16_t		vid;
382240616Sjimharris
383240616Sjimharris	/** pci subsystem vendor id */
384240616Sjimharris	uint16_t		ssvid;
385240616Sjimharris
386240616Sjimharris	/** serial number */
387240616Sjimharris	int8_t			sn[20];
388240616Sjimharris
389240616Sjimharris	/** model number */
390240616Sjimharris	int8_t			mn[40];
391240616Sjimharris
392240616Sjimharris	/** firmware revision */
393240616Sjimharris	uint8_t			fr[8];
394240616Sjimharris
395240616Sjimharris	/** recommended arbitration burst */
396240616Sjimharris	uint8_t			rab;
397240616Sjimharris
398240616Sjimharris	/** ieee oui identifier */
399240616Sjimharris	uint8_t			ieee[3];
400240616Sjimharris
401240616Sjimharris	/** multi-interface capabilities */
402240616Sjimharris	uint8_t			mic;
403240616Sjimharris
404240616Sjimharris	/** maximum data transfer size */
405240616Sjimharris	uint8_t			mdts;
406240616Sjimharris
407240616Sjimharris	uint8_t			reserved1[178];
408240616Sjimharris
409240616Sjimharris	/* bytes 256-511: admin command set attributes */
410240616Sjimharris
411240616Sjimharris	/** optional admin command support */
412240616Sjimharris	struct {
413240616Sjimharris		/* supports security send/receive commands */
414240616Sjimharris		uint16_t	security  : 1;
415240616Sjimharris
416240616Sjimharris		/* supports format nvm command */
417240616Sjimharris		uint16_t	format    : 1;
418240616Sjimharris
419240616Sjimharris		/* supports firmware activate/download commands */
420240616Sjimharris		uint16_t	firmware  : 1;
421240616Sjimharris
422240616Sjimharris		uint16_t	oacs_rsvd : 13;
423240616Sjimharris	} __packed oacs;
424240616Sjimharris
425240616Sjimharris	/** abort command limit */
426240616Sjimharris	uint8_t			acl;
427240616Sjimharris
428240616Sjimharris	/** asynchronous event request limit */
429240616Sjimharris	uint8_t			aerl;
430240616Sjimharris
431240616Sjimharris	/** firmware updates */
432240616Sjimharris	struct {
433240616Sjimharris		/* first slot is read-only */
434240616Sjimharris		uint8_t		slot1_ro  : 1;
435240616Sjimharris
436240616Sjimharris		/* number of firmware slots */
437240616Sjimharris		uint8_t		num_slots : 3;
438240616Sjimharris
439240616Sjimharris		uint8_t		frmw_rsvd : 4;
440240616Sjimharris	} __packed frmw;
441240616Sjimharris
442240616Sjimharris	/** log page attributes */
443240616Sjimharris	struct {
444240616Sjimharris		/* per namespace smart/health log page */
445240616Sjimharris		uint8_t		ns_smart : 1;
446240616Sjimharris
447240616Sjimharris		uint8_t		lpa_rsvd : 7;
448240616Sjimharris	} __packed lpa;
449240616Sjimharris
450240616Sjimharris	/** error log page entries */
451240616Sjimharris	uint8_t			elpe;
452240616Sjimharris
453240616Sjimharris	/** number of power states supported */
454240616Sjimharris	uint8_t			npss;
455240616Sjimharris
456240616Sjimharris	/** admin vendor specific command configuration */
457240616Sjimharris	struct {
458240616Sjimharris		/* admin vendor specific commands use spec format */
459240616Sjimharris		uint8_t		spec_format : 1;
460240616Sjimharris
461240616Sjimharris		uint8_t		avscc_rsvd  : 7;
462240616Sjimharris	} __packed avscc;
463240616Sjimharris
464240616Sjimharris	uint8_t			reserved2[247];
465240616Sjimharris
466240616Sjimharris	/* bytes 512-703: nvm command set attributes */
467240616Sjimharris
468240616Sjimharris	/** submission queue entry size */
469240616Sjimharris	struct {
470240616Sjimharris		uint8_t		min : 4;
471240616Sjimharris		uint8_t		max : 4;
472240616Sjimharris	} __packed sqes;
473240616Sjimharris
474240616Sjimharris	/** completion queue entry size */
475240616Sjimharris	struct {
476240616Sjimharris		uint8_t		min : 4;
477240616Sjimharris		uint8_t		max : 4;
478240616Sjimharris	} __packed cqes;
479240616Sjimharris
480240616Sjimharris	uint8_t			reserved3[2];
481240616Sjimharris
482240616Sjimharris	/** number of namespaces */
483240616Sjimharris	uint32_t		nn;
484240616Sjimharris
485240616Sjimharris	/** optional nvm command support */
486240616Sjimharris	struct {
487240616Sjimharris		uint16_t	compare : 1;
488240616Sjimharris		uint16_t	write_unc : 1;
489240616Sjimharris		uint16_t	dsm: 1;
490240616Sjimharris		uint16_t	reserved: 13;
491240616Sjimharris	} __packed oncs;
492240616Sjimharris
493240616Sjimharris	/** fused operation support */
494240616Sjimharris	uint16_t		fuses;
495240616Sjimharris
496240616Sjimharris	/** format nvm attributes */
497240616Sjimharris	uint8_t			fna;
498240616Sjimharris
499240616Sjimharris	/** volatile write cache */
500240616Sjimharris	struct {
501240616Sjimharris		uint8_t		present : 1;
502240616Sjimharris		uint8_t		reserved : 7;
503240616Sjimharris	} __packed vwc;
504240616Sjimharris
505240616Sjimharris	/* TODO: flesh out remaining nvm command set attributes */
506240616Sjimharris	uint8_t			reserved4[178];
507240616Sjimharris
508240616Sjimharris	/* bytes 704-2047: i/o command set attributes */
509240616Sjimharris	uint8_t			reserved5[1344];
510240616Sjimharris
511240616Sjimharris	/* bytes 2048-3071: power state descriptors */
512240616Sjimharris	uint8_t			reserved6[1024];
513240616Sjimharris
514240616Sjimharris	/* bytes 3072-4095: vendor specific */
515240616Sjimharris	uint8_t			reserved7[1024];
516240671Sjimharris} __packed __aligned(4);
517240616Sjimharris
518240616Sjimharrisstruct nvme_namespace_data {
519240616Sjimharris
520240616Sjimharris	/** namespace size */
521240616Sjimharris	uint64_t		nsze;
522240616Sjimharris
523240616Sjimharris	/** namespace capacity */
524240616Sjimharris	uint64_t		ncap;
525240616Sjimharris
526240616Sjimharris	/** namespace utilization */
527240616Sjimharris	uint64_t		nuse;
528240616Sjimharris
529240616Sjimharris	/** namespace features */
530240616Sjimharris	struct {
531240616Sjimharris		/** thin provisioning */
532240616Sjimharris		uint8_t		thin_prov : 1;
533240616Sjimharris		uint8_t		reserved1 : 7;
534240616Sjimharris	} __packed nsfeat;
535240616Sjimharris
536240616Sjimharris	/** number of lba formats */
537240616Sjimharris	uint8_t			nlbaf;
538240616Sjimharris
539240616Sjimharris	/** formatted lba size */
540240616Sjimharris	struct {
541240616Sjimharris		uint8_t		format    : 4;
542240616Sjimharris		uint8_t		extended  : 1;
543240616Sjimharris		uint8_t		reserved2 : 3;
544240616Sjimharris	} __packed flbas;
545240616Sjimharris
546240616Sjimharris	/** metadata capabilities */
547240616Sjimharris	struct {
548240616Sjimharris		/* metadata can be transferred as part of data prp list */
549240616Sjimharris		uint8_t		extended  : 1;
550240616Sjimharris
551240616Sjimharris		/* metadata can be transferred with separate metadata pointer */
552240616Sjimharris		uint8_t		pointer   : 1;
553240616Sjimharris
554240616Sjimharris		uint8_t		reserved3 : 6;
555240616Sjimharris	} __packed mc;
556240616Sjimharris
557240616Sjimharris	/** end-to-end data protection capabilities */
558240616Sjimharris	struct {
559240616Sjimharris		/* protection information type 1 */
560240616Sjimharris		uint8_t		pit1     : 1;
561240616Sjimharris
562240616Sjimharris		/* protection information type 2 */
563240616Sjimharris		uint8_t		pit2     : 1;
564240616Sjimharris
565240616Sjimharris		/* protection information type 3 */
566240616Sjimharris		uint8_t		pit3     : 1;
567240616Sjimharris
568240616Sjimharris		/* first eight bytes of metadata */
569240616Sjimharris		uint8_t		md_start : 1;
570240616Sjimharris
571240616Sjimharris		/* last eight bytes of metadata */
572240616Sjimharris		uint8_t		md_end   : 1;
573240616Sjimharris	} __packed dpc;
574240616Sjimharris
575240616Sjimharris	/** end-to-end data protection type settings */
576240616Sjimharris	struct {
577240616Sjimharris		/* protection information type */
578240616Sjimharris		uint8_t		pit       : 3;
579240616Sjimharris
580240616Sjimharris		/* 1 == protection info transferred at start of metadata */
581240616Sjimharris		/* 0 == protection info transferred at end of metadata */
582240616Sjimharris		uint8_t		md_start  : 1;
583240616Sjimharris
584240616Sjimharris		uint8_t		reserved4 : 4;
585240616Sjimharris	} __packed dps;
586240616Sjimharris
587240616Sjimharris	uint8_t			reserved5[98];
588240616Sjimharris
589240616Sjimharris	/** lba format support */
590240616Sjimharris	struct {
591240616Sjimharris		/** metadata size */
592240616Sjimharris		uint32_t	ms	  : 16;
593240616Sjimharris
594240616Sjimharris		/** lba data size */
595240616Sjimharris		uint32_t	lbads	  : 8;
596240616Sjimharris
597240616Sjimharris		/** relative performance */
598240616Sjimharris		uint32_t	rp	  : 2;
599240616Sjimharris
600240616Sjimharris		uint32_t	reserved6 : 6;
601240616Sjimharris	} __packed lbaf[16];
602240616Sjimharris
603240616Sjimharris	uint8_t			reserved6[192];
604240616Sjimharris
605240616Sjimharris	uint8_t			vendor_specific[3712];
606240671Sjimharris} __packed __aligned(4);
607240616Sjimharris
608240616Sjimharrisenum nvme_log_page {
609240616Sjimharris
610240616Sjimharris	/* 0x00 - reserved */
611240616Sjimharris	NVME_LOG_ERROR			= 0x01,
612240616Sjimharris	NVME_LOG_HEALTH_INFORMATION	= 0x02,
613240616Sjimharris	NVME_LOG_FIRMWARE_SLOT		= 0x03,
614240616Sjimharris	/* 0x04-0x7F - reserved */
615240616Sjimharris	/* 0x80-0xBF - I/O command set specific */
616240616Sjimharris	/* 0xC0-0xFF - vendor specific */
617240616Sjimharris};
618240616Sjimharris
619240616Sjimharrisunion nvme_critical_warning_state {
620240616Sjimharris
621240616Sjimharris	uint8_t		raw;
622240616Sjimharris
623240616Sjimharris	struct {
624240616Sjimharris		uint8_t	available_spare		: 1;
625240616Sjimharris		uint8_t	temperature		: 1;
626240616Sjimharris		uint8_t	device_reliability	: 1;
627240616Sjimharris		uint8_t	read_only		: 1;
628240616Sjimharris		uint8_t	volatile_memory_backup	: 1;
629240616Sjimharris		uint8_t	reserved		: 3;
630240616Sjimharris	} __packed bits;
631240616Sjimharris} __packed;
632240616Sjimharris
633240616Sjimharrisstruct nvme_health_information_page {
634240616Sjimharris
635240616Sjimharris	union nvme_critical_warning_state	critical_warning;
636240616Sjimharris
637240616Sjimharris	uint16_t		temperature;
638240616Sjimharris	uint8_t			available_spare;
639240616Sjimharris	uint8_t			available_spare_threshold;
640240616Sjimharris	uint8_t			percentage_used;
641240616Sjimharris
642240616Sjimharris	uint8_t			reserved[26];
643240616Sjimharris
644240616Sjimharris	/*
645240616Sjimharris	 * Note that the following are 128-bit values, but are
646240616Sjimharris	 *  defined as an array of 2 64-bit values.
647240616Sjimharris	 */
648240616Sjimharris	/* Data Units Read is always in 512-byte units. */
649240616Sjimharris	uint64_t		data_units_read[2];
650240616Sjimharris	/* Data Units Written is always in 512-byte units. */
651240616Sjimharris	uint64_t		data_units_written[2];
652240616Sjimharris	/* For NVM command set, this includes Compare commands. */
653240616Sjimharris	uint64_t		host_read_commands[2];
654240616Sjimharris	uint64_t		host_write_commands[2];
655240616Sjimharris	/* Controller Busy Time is reported in minutes. */
656240616Sjimharris	uint64_t		controller_busy_time[2];
657240616Sjimharris	uint64_t		power_cycles[2];
658240616Sjimharris	uint64_t		power_on_hours[2];
659240616Sjimharris	uint64_t		unsafe_shutdowns[2];
660240616Sjimharris	uint64_t		media_errors[2];
661240616Sjimharris	uint64_t		num_error_info_log_entries[2];
662240616Sjimharris
663240616Sjimharris	uint8_t			reserved2[320];
664240671Sjimharris} __packed __aligned(4);
665240616Sjimharris
666240616Sjimharris#define NVME_TEST_MAX_THREADS	128
667240616Sjimharris
668240616Sjimharrisstruct nvme_io_test {
669240616Sjimharris
670240616Sjimharris	enum nvme_nvm_opcode	opc;
671240616Sjimharris	uint32_t		size;
672240616Sjimharris	uint32_t		time;	/* in seconds */
673240616Sjimharris	uint32_t		num_threads;
674240616Sjimharris	uint32_t		flags;
675240616Sjimharris	uint32_t		io_completed[NVME_TEST_MAX_THREADS];
676240616Sjimharris};
677240616Sjimharris
678240616Sjimharrisenum nvme_io_test_flags {
679240616Sjimharris
680240616Sjimharris	/*
681240616Sjimharris	 * Specifies whether dev_refthread/dev_relthread should be
682240616Sjimharris	 *  called during NVME_BIO_TEST.  Ignored for other test
683240616Sjimharris	 *  types.
684240616Sjimharris	 */
685240616Sjimharris	NVME_TEST_FLAG_REFTHREAD =	0x1,
686240616Sjimharris};
687240616Sjimharris
688240616Sjimharris#ifdef _KERNEL
689240616Sjimharris
690240616Sjimharrisstruct bio;
691240616Sjimharris
692240616Sjimharrisstruct nvme_namespace;
693248738Sjimharrisstruct nvme_controller;
694240616Sjimharrisstruct nvme_consumer;
695240616Sjimharris
696240616Sjimharristypedef void (*nvme_cb_fn_t)(void *, const struct nvme_completion *);
697240616Sjimharris
698248738Sjimharristypedef void *(*nvme_cons_ns_fn_t)(struct nvme_namespace *, void *);
699248738Sjimharristypedef void *(*nvme_cons_ctrlr_fn_t)(struct nvme_controller *);
700248738Sjimharristypedef void (*nvme_cons_async_fn_t)(void *, const struct nvme_completion *);
701248738Sjimharris
702240616Sjimharrisenum nvme_namespace_flags {
703240616Sjimharris	NVME_NS_DEALLOCATE_SUPPORTED	= 0x1,
704240616Sjimharris	NVME_NS_FLUSH_SUPPORTED		= 0x2,
705240616Sjimharris};
706240616Sjimharris
707248739Sjimharris/* Admin functions */
708248739Sjimharrisvoid	nvme_ctrlr_cmd_set_feature(struct nvme_controller *ctrlr,
709248739Sjimharris				   uint8_t feature, uint32_t cdw11,
710248739Sjimharris				   void *payload, uint32_t payload_size,
711248739Sjimharris				   nvme_cb_fn_t cb_fn, void *cb_arg);
712248739Sjimharrisvoid	nvme_ctrlr_cmd_get_feature(struct nvme_controller *ctrlr,
713248739Sjimharris				   uint8_t feature, uint32_t cdw11,
714248739Sjimharris				   void *payload, uint32_t payload_size,
715248739Sjimharris				   nvme_cb_fn_t cb_fn, void *cb_arg);
716248739Sjimharris
717240616Sjimharris/* NVM I/O functions */
718241657Sjimharrisint	nvme_ns_cmd_write(struct nvme_namespace *ns, void *payload,
719240616Sjimharris			  uint64_t lba, uint32_t lba_count, nvme_cb_fn_t cb_fn,
720240616Sjimharris			  void *cb_arg);
721241657Sjimharrisint	nvme_ns_cmd_read(struct nvme_namespace *ns, void *payload,
722240616Sjimharris			 uint64_t lba, uint32_t lba_count, nvme_cb_fn_t cb_fn,
723240616Sjimharris			 void *cb_arg);
724241657Sjimharrisint	nvme_ns_cmd_deallocate(struct nvme_namespace *ns, void *payload,
725240616Sjimharris			       uint8_t num_ranges, nvme_cb_fn_t cb_fn,
726240616Sjimharris			       void *cb_arg);
727241657Sjimharrisint	nvme_ns_cmd_flush(struct nvme_namespace *ns, nvme_cb_fn_t cb_fn,
728240616Sjimharris			  void *cb_arg);
729240616Sjimharris
730240616Sjimharris/* Registration functions */
731248738Sjimharrisstruct nvme_consumer *	nvme_register_consumer(nvme_cons_ns_fn_t    ns_fn,
732248738Sjimharris					       nvme_cons_ctrlr_fn_t ctrlr_fn,
733248738Sjimharris					       nvme_cons_async_fn_t async_fn);
734240616Sjimharrisvoid		nvme_unregister_consumer(struct nvme_consumer *consumer);
735240616Sjimharris
736248738Sjimharris/* Controller helper functions */
737248738Sjimharrisdevice_t	nvme_ctrlr_get_device(struct nvme_controller *ctrlr);
738248738Sjimharris
739240616Sjimharris/* Namespace helper functions */
740240616Sjimharrisuint32_t	nvme_ns_get_max_io_xfer_size(struct nvme_namespace *ns);
741240616Sjimharrisuint32_t	nvme_ns_get_sector_size(struct nvme_namespace *ns);
742240616Sjimharrisuint64_t	nvme_ns_get_num_sectors(struct nvme_namespace *ns);
743240616Sjimharrisuint64_t	nvme_ns_get_size(struct nvme_namespace *ns);
744240616Sjimharrisuint32_t	nvme_ns_get_flags(struct nvme_namespace *ns);
745240616Sjimharrisconst char *	nvme_ns_get_serial_number(struct nvme_namespace *ns);
746240616Sjimharrisconst char *	nvme_ns_get_model_number(struct nvme_namespace *ns);
747240616Sjimharris
748240616Sjimharrisint	nvme_ns_bio_process(struct nvme_namespace *ns, struct bio *bp,
749240616Sjimharris			    nvme_cb_fn_t cb_fn);
750240616Sjimharris
751240616Sjimharris#endif /* _KERNEL */
752240616Sjimharris
753240616Sjimharris#endif /* __NVME_H__ */
754