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