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