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