|
root / base / usr / src / uts / common / sys / nvme / wdc.h
wdc.h C 148 lines 4.5 KB
  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
/*
 * This file and its contents are supplied under the terms of the
 * Common Development and Distribution License ("CDDL"), version 1.0.
 * You may only use this file in accordance with the terms of version
 * 1.0 of the CDDL.
 *
 * A full copy of the text of the CDDL should have accompanied this
 * source.  A copy of the CDDL is also available via the Internet at
 * http://www.illumos.org/license/CDDL.
 */

/*
 * Copyright 2025 Oxide Computer Company
 */

#ifndef _SYS_NVME_WDC_H
#define	_SYS_NVME_WDC_H

/*
 * This header defines vendor-specific NVMe interfaces and is not a committed
 * interface. Its contents and existence are subject to change.
 *
 * This header contains all of the current vendor-specific entries for known WDC
 * devices as well as common structures and definitions that are shared across
 * multiple device families.
 */

#include <sys/nvme/wdc_sn840.h>
#include <sys/nvme/wdc_sn65x.h>
#include <sys/nvme/wdc_sn861.h>

#ifdef __cplusplus
extern "C" {
#endif

#define	WDC_PCI_VID	0x1b96

/*
 * All data structures must be packed to account for the layout from the various
 * programmer's manuals.
 */
#pragma pack(1)

/*
 * WDC common device power samples log page data structure. All power samples
 * are in mW.
 */
typedef struct {
	uint32_t	pow_nsamples;
	uint32_t	pow_samples[];
} wdc_vul_power_t;

/*
 * This is a device generation agnostic structure that defines temperature
 * samples log page. The temperature is in degrees Celsius, but we do not
 * currently know the exact format of the data. Each device has a specific
 * enumeration that describes what each array entry is supposed to mean.
 */
typedef struct {
	uint32_t	temp_nsamples;
	uint32_t	temp_samples[];
} wdc_vul_temp_t;

/*
 * The device manageability log page consists of a series of variable length
 * entries which are guaranteed to always be 4-byte aligned. The length includes
 * the length of the header itself. This header is used to start the log itself
 * and in that case the id is the version.
 */
typedef struct {
	uint32_t	vsd_len;
	uint32_t	vsd_id;
	uint8_t		vsd_data[];
} wdc_vsd_t;

/*
 * This is the WDC 'Counted ByteString'. This is not a null-terminated string!
 * The length of data in bytes is stored in cbs_len (defined as little endian).
 * There may be additional padding following csd_data to make up the fact that
 * the device manageability log is units of four bytes.
 */
typedef struct {
	uint32_t	cbs_len;
	uint8_t		csd_data[];
} wdc_cbs_t;

/*
 * Vendor Unique Commands that span multiple devices.
 */

/*
 * The e6 command is a diagnostic dump that can be initiated that traces its
 * lineage back to the HDD world. The dump is variable sized and starts with an
 * 8 byte header (the wdc_e6_header_t) which indicates the total size of the
 * dump.
 *
 * The command accepts a number of dwords to read and uses cdw12 to indicate the
 * dword offset to start to read out.
 */
#define	WDC_VUC_E6_DUMP_OPC	0xe6

/*
 * The following is the WDC e6 dump diagnostic header. This is used to determine
 * the size of the full payload. The first member is a uint32_t. The second
 * member determines the size of the log. e6_size[0] is the upper 24 bits,
 * e6_size[1], bits 16-23, etc. This is a size in bytes, it cannot be passed to
 * commands directly which are in units of uint32_t's.
 */
typedef struct {
	uint32_t	e6_head;
	uint32_t	e6_size_be;
} wdc_e6_header_t;

CTASSERT((sizeof (wdc_e6_header_t) % 4) == 0);
CTASSERT(sizeof (wdc_e6_header_t) == 8);

/*
 * The drive diagnostic resize command allows certain devices to resize their
 * capacity. This is a fully destructive operation. It is known to be supported
 * by the SN840 and SN65x families. It utilizes a mode argument in cdw12 which
 * indicates whether to get, set, or query progress. That argument is in
 * bits[15:8]. To indicate that we are doing the resize operation of the opcode
 * we must set bits[7:0] to 3. The target size is specified in cdw13.
 */
#define	WDC_VUC_RESIZE_OPC	0xcc
#define	WDC_VUC_RESIZE_CMD	0x3
#define	WDC_VUC_RESIZE_SUB_GET		0x0
#define	WDC_VUC_RESIZE_SUB_SET		0x1
#define	WDC_VUC_RESIZE_SUB_PHASE	0x2

/*
 * Several WDC devices have a notion of an assert that is visible in the device
 * manageability log. As part of recovering devices, that assert must be cleared
 * through a vendor-specific command.
 */
#define	WDC_VUC_ASSERT_OPC	0xd8
#define	WDC_VUC_ASSERT_CMD	0x3
#define	WDC_VUC_ASSERT_SUB_CLEAR	0x5
#define	WDC_VUC_ASSERT_SUB_INJECT	0x6

#pragma	pack()	/* pack(1) */

#ifdef __cplusplus
}
#endif

#endif /* _SYS_NVME_WDC_H */