xref: /illumos-gate/usr/src/uts/common/sys/nvme/wdc.h (revision fbd5b8684156f1cae0891d3e690e5bdf7644c840)
1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2025 Oxide Computer Company
14  */
15 
16 #ifndef _SYS_NVME_WDC_H
17 #define	_SYS_NVME_WDC_H
18 
19 /*
20  * This header defines vendor-specific NVMe interfaces and is not a committed
21  * interface. Its contents and existence are subject to change.
22  *
23  * This header contains all of the current vendor-specific entries for known WDC
24  * devices as well as common structures and definitions that are shared across
25  * multiple device families.
26  */
27 
28 #include <sys/nvme/wdc_sn840.h>
29 #include <sys/nvme/wdc_sn65x.h>
30 #include <sys/nvme/wdc_sn861.h>
31 
32 #ifdef __cplusplus
33 extern "C" {
34 #endif
35 
36 #define	WDC_PCI_VID	0x1b96
37 
38 /*
39  * All data structures must be packed to account for the layout from the various
40  * programmer's manuals.
41  */
42 #pragma pack(1)
43 
44 /*
45  * WDC common device power samples log page data structure. All power samples
46  * are in mW.
47  */
48 typedef struct {
49 	uint32_t	pow_nsamples;
50 	uint32_t	pow_samples[];
51 } wdc_vul_power_t;
52 
53 /*
54  * This is a device generation agnostic structure that defines temperature
55  * samples log page. The temperature is in degrees Celsius, but we do not
56  * currently know the exact format of the data. Each device has a specific
57  * enumeration that describes what each array entry is supposed to mean.
58  */
59 typedef struct {
60 	uint32_t	temp_nsamples;
61 	uint32_t	temp_samples[];
62 } wdc_vul_temp_t;
63 
64 /*
65  * The device manageability log page consists of a series of variable length
66  * entries which are guaranteed to always be 4-byte aligned. The length includes
67  * the length of the header itself. This header is used to start the log itself
68  * and in that case the id is the version.
69  */
70 typedef struct {
71 	uint32_t	vsd_len;
72 	uint32_t	vsd_id;
73 	uint8_t		vsd_data[];
74 } wdc_vsd_t;
75 
76 /*
77  * This is the WDC 'Counted ByteString'. This is not a null-terminated string!
78  * The length of data in bytes is stored in cbs_len (defined as little endian).
79  * There may be additional padding following csd_data to make up the fact that
80  * the device manageability log is units of four bytes.
81  */
82 typedef struct {
83 	uint32_t	cbs_len;
84 	uint8_t		csd_data[];
85 } wdc_cbs_t;
86 
87 /*
88  * Vendor Unique Commands that span multiple devices.
89  */
90 
91 /*
92  * The e6 command is a diagnostic dump that can be initiated that traces its
93  * lineage back to the HDD world. The dump is variable sized and starts with an
94  * 8 byte header (the wdc_e6_header_t) which indicates the total size of the
95  * dump.
96  *
97  * The command accepts a number of dwords to read and uses cdw12 to indicate the
98  * dword offset to start to read out.
99  */
100 #define	WDC_VUC_E6_DUMP_OPC	0xe6
101 
102 /*
103  * The following is the WDC e6 dump diagnostic header. This is used to determine
104  * the size of the full payload. The first member is a uint32_t. The second
105  * member determines the size of the log. e6_size[0] is the upper 24 bits,
106  * e6_size[1], bits 16-23, etc. This is a size in bytes, it cannot be passed to
107  * commands directly which are in units of uint32_t's.
108  */
109 typedef struct {
110 	uint32_t	e6_head;
111 	uint32_t	e6_size_be;
112 } wdc_e6_header_t;
113 
114 CTASSERT((sizeof (wdc_e6_header_t) % 4) == 0);
115 CTASSERT(sizeof (wdc_e6_header_t) == 8);
116 
117 /*
118  * The drive diagnostic resize command allows certain devices to resize their
119  * capacity. This is a fully destructive operation. It is known to be supported
120  * by the SN840 and SN65x families. It utilizes a mode argument in cdw12 which
121  * indicates whether to get, set, or query progress. That argument is in
122  * bits[15:8]. To indicate that we are doing the resize operation of the opcode
123  * we must set bits[7:0] to 3. The target size is specified in cdw13.
124  */
125 #define	WDC_VUC_RESIZE_OPC	0xcc
126 #define	WDC_VUC_RESIZE_CMD	0x3
127 #define	WDC_VUC_RESIZE_SUB_GET		0x0
128 #define	WDC_VUC_RESIZE_SUB_SET		0x1
129 #define	WDC_VUC_RESIZE_SUB_PHASE	0x2
130 
131 /*
132  * Several WDC devices have a notion of an assert that is visible in the device
133  * manageability log. As part of recovering devices, that assert must be cleared
134  * through a vendor-specific command.
135  */
136 #define	WDC_VUC_ASSERT_OPC	0xd8
137 #define	WDC_VUC_ASSERT_CMD	0x3
138 #define	WDC_VUC_ASSERT_SUB_CLEAR	0x5
139 #define	WDC_VUC_ASSERT_SUB_INJECT	0x6
140 
141 #pragma	pack()	/* pack(1) */
142 
143 #ifdef __cplusplus
144 }
145 #endif
146 
147 #endif /* _SYS_NVME_WDC_H */
148