|
root / base / usr / src / uts / common / sys / nvme / ocp.h
ocp.h C 790 lines 19.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
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
/*
 * 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 2026 Oxide Computer Company
 */

#ifndef _SYS_NVME_OCP_H
#define	_SYS_NVME_OCP_H

/*
 * This header defines vendor-specific NVMe interfaces and is not a committed
 * interface. Its contents and existence are subject to change.
 *
 * This covers the OCP Datacenter NVMe SSD Specification versions 2.0 and 2.5.
 * Version 1.0 of this specification was previously called the OCP NVMe Cloud
 * SSD Specification.
 */

#include <sys/isa_defs.h>
#include <sys/debug.h>
#include <sys/stdint.h>
#include <sys/stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef enum {
	/*
	 * This is the OCP variant of SMART information. Present since v1.0.
	 * Scoped to the NVM subsystem. Tracked by the ocp_vul_smart_t.
	 */
	OCP_LOG_DSSD_SMART	= 0xc0,
	/*
	 * Error recovery information. Present since v1.0. Scoped to the NVM
	 * subsystem.
	 */
	OCP_LOG_DSSD_ERROR_REC	= 0xc1,
	/*
	 * This log page covers firmware activation history. It was added in
	 * v1.0 of the specification, but v2.5 removed this as obsolete. Scoped
	 * to the NVM subsystem.
	 */
	OCP_LOG_DSSD_FWACT	= 0xc2,
	/*
	 * This is the latency monitor log page that has information in tandem
	 * with the Latency monitor feature (0xc5). Added in v2.0. Scoped to the
	 * controller.
	 */
	OCP_LOG_DSSD_LATENCY	= 0xc3,
	/*
	 * This log page indicates various device capabilities. Added in v2.0.
	 * Scoped to the NVM subsystem.
	 */
	OCP_LOG_DSSD_DEV_CAP	= 0xc4,
	/*
	 * This log page indicates which requirements aren't actually
	 * implemented by a device. Added in v2.0. Scoped to the NVM subsystem.
	 */
	OCP_LOG_DSSD_UNSUP_REQ	= 0xc5,
	/*
	 * This log page covers various trusted computing group configuration.
	 * Added in v2.5. Scoped to the NVM subsystem.
	 */
	OCP_LOG_DSSD_TCG	= 0xc7,
	/*
	 * This is the telemetry string log. Added in v2.5. Scoped to the NVM
	 * subsystem. See the ocp_vul_telstr_t.
	 */
	OCP_LOG_DSSD_TELEMETRY	= 0xc9
} ocp_vul_t;

typedef enum {
	/*
	 * Error injection feature. Added in v1.0. Scoped to the NVM subsystem.
	 */
	OCP_FEAT_DSSD_ERR_INJ		= 0xc0,
	/*
	 * Clear the firmware activation and update history log. Added in v1.0,
	 * but marked obsolete in v2.5. Scoped to the NVM subsystem.
	 */
	OCP_FEAT_DSSD_CLEAR_FWACT	= 0xc1,
	/*
	 * Controls the failure mode on device EOL or power loss protection
	 * (PLP) failure. Added in v1.0. Scoped to the NVM subsystem.
	 */
	OCP_FEAT_DSSD_EOLPLP		= 0xc2,
	/*
	 * Clears the PCIe correctable error counters. Added in v1.0. Scoped to
	 * the controller.
	 */
	OCP_FEAT_DSSD_CLEAR_PCIE_ERRCOR	= 0xc3,
	/*
	 * Manipulates the IEEE1667 silo which ties into the OPAL security
	 * feature set. Added in v1.0. Scoped to the NVM subsystem.
	 */
	OCP_FEAT_DSSD_IEEE1667		= 0xc4,
	/*
	 * Controls the latency monitor feature. Added in v2.0. Scoped to the
	 * controller.
	 */
	OCP_FEAT_DSSD_LATENCY		= 0xc5,
	/*
	 * Controls the PLP health check interval. Added in v2.0. Scoped to the
	 * NVM subsystem.
	 */
	OCP_FEAT_DSSD_PLP_HEALTH	= 0xc6,
	/*
	 * Controls the power state that the device is in. Added in v2.0. Scoped
	 * to the NVM subsystem.
	 */
	OCP_FEAT_DSSD_POWER_STATE	= 0xc7,
	/*
	 * Controls the OCP DSSD telemetry profile that should be active. Added
	 * in v2.5. Scoped to the NVM subsystem.
	 */
	OCP_FEAT_DSSD_TEL_PROFILE	= 0xc8,
	/*
	 * Controls whether additional spec-specific events should be sent with
	 * the asynchronous event commands.
	 */
	OCP_FEAT_DSSD_ASYNC_EVENT	= 0xc9
} ocp_vuf_t;

/*
 * All data structures must be packed to account for the layout from the various
 * specifications. All fields are required to be in little endian.
 */
#pragma pack(1)

/*
 * OCP SMART / Health log page. A number in parentheses like (2.0) indicates the
 * version something was added in if it was not v1.0.
 */
typedef struct {
	/*
	 * Physical media units read and written.
	 */
	uint8_t	osh_pmed_write[16];
	uint8_t osh_pmed_read[16];
	/*
	 * Bad user and system NAND blocks. Both a raw count and normalized
	 * value (percentage remaining).
	 */
	struct {
		uint8_t bunb_raw[6];
		uint16_t bunb_norm;
	} osh_bunb;
	struct {
		uint8_t bsnb_raw[6];
		uint16_t bsnb_norm;
	} osh_bsnb;
	/*
	 * Various error and recovery metrics:
	 * - XOR
	 * - Uncorrectable reads
	 * - Soft ECC errors
	 * - End to end errors detected and corrected
	 */
	uint64_t osh_xor_rec;
	uint64_t osh_read_unrec;
	uint64_t osh_soft_ecc_err;
	struct {
		uint32_t e2e_det;
		uint32_t e2e_corr;
	} osh_e2e;
	/*
	 * Tracks the normalized percent used of the device by estimated erase
	 * cycles per block.
	 */
	uint8_t osh_sys_used;
	/*
	 * This is the count of blocks that have been refreshed.
	 */
	uint8_t osh_refresh[7];
	/*
	 * Tracks the maximum and minimum erase count across NAND reserved for
	 * the user.
	 */
	struct {
		uint32_t udec_max;
		uint32_t udec_min;
	} osh_udec;
	/*
	 * The number of events and the current level of throttling.
	 */
	struct {
		uint8_t therm_event;
		uint8_t throt_level;
	} osh_therm;
	/*
	 * DSSD versioning for the device. (2.0).
	 */
	struct {
		uint8_t dssd_errata;
		uint16_t dssd_point;
		uint16_t dssd_minor;
		uint8_t dssd_major;
	} osh_dssd;
	/*
	 * PCIe Correctable error count.
	 */
	uint64_t osh_pcie_errcor;
	/*
	 * Incomplete shutdowns.
	 */
	uint32_t osh_inc_shut;
	uint8_t osh_rsvd116[4];
	/*
	 * Normalized free percentage.
	 */
	uint8_t osh_free;
	uint8_t osh_rsvd121[7];
	/*
	 * Capacitor health as a percentage.
	 */
	uint16_t osh_cap_health;
	/*
	 * NVMe base spec errata version (2.0).
	 * NVMe cmd spec errata version (2.5).
	 */
	uint8_t osh_nvme_base_errata;
	uint8_t osh_nvme_cmd_errata;
	uint8_t osh_rsvd132[4];
	/*
	 * Quantity of unaligned I/O
	 */
	uint64_t osh_unaligned;
	/*
	 * An incrementing integer representing a security version that
	 * shouldn't be rolled back across.
	 */
	uint64_t osh_sec_vers;
	/*
	 * Namespace utilization.
	 */
	uint64_t osh_nuse;
	/*
	 * Count of events where PLP kicked in.
	 */
	uint8_t osh_plp_start[16];
	/*
	 * Estimation of total data that can be written to the device in bytes.
	 */
	uint8_t osh_endurance[16];
	/*
	 * Count of PCIe retraining events (2.0).
	 */
	uint64_t osh_pcie_retrain;
	/*
	 * Count of power state changes, regardless of initiator. (2.0).
	 */
	uint64_t osh_ps_change;
	/*
	 * Minimum permitted firmware version for rollback purposes.
	 */
	uint64_t osh_min_fwrev;
	uint8_t osh_rsvd216[278];
	/*
	 * v1.0: 2, v2.0: 3, v2.5: 4
	 */
	uint16_t osh_vers;
	/*
	 * Log page GUID: AFD514C97C6F4F9CA4f2BFEA2810AFC5h.
	 */
	uint8_t osh_guid[16];
} ocp_vul_smart_t;

/*
 * OCP Error Recovery log.
 */
typedef struct {
	/*
	 * Time in ms to wait for a reset to complete.
	 */
	uint16_t oer_prwt;
	/*
	 * List of reset actions we should consider taking. See ocp_errrec_pra_t
	 * for bit meanings.
	 */
	uint8_t oer_pra;
	/*
	 * List of steps to take to handle the device's recovery from a given
	 * situation. See ocp_errrec_dra_t for bit meanings.
	 */
	uint8_t oer_dra;
	uint64_t oer_panic_id;
	/*
	 * See ocp_errrec_devcap_t for more information.
	 */
	uint32_t oer_devcap;
	/*
	 * Information for how to send the vendor specific recovery command. The
	 * timout was added in 2.0.
	 */
	uint8_t oer_vsr_opcode;
	uint8_t oer_rsvd17[3];
	uint32_t oer_vsr_cdw12;
	uint32_t oer_vsr_cdw13;
	uint8_t oer_vsr_to;
	/*
	 * Secondary recovery actions post-reset (2.5). Uses the same bits as
	 * ocp_errrec_dra_t.
	 */
	uint8_t oer_dra2;
	uint8_t oer_dra2_to;
	uint8_t oer_npanic;
	uint64_t oer_old_panics[4];
	uint8_t oer_rsvd54[430];
	/*
	 * V1.0: 1, V2.0: 2, V2.5: 3
	 */
	uint16_t oer_vers;
	/*
	 * Log page GUID: 5A1983BA3DFD4DABAE3430FE2131D944h.
	 */
	uint8_t oer_guid[16];
} ocp_vul_errrec_t;

/*
 * List of panic reset actions that should be taken to recover.
 */
typedef enum {
	/* NVMe Controller Reset */
	OCP_LOG_ERRREC_F_PRA_CTRL	= 1 << 0,
	/* NVM Subsystem Reset */
	OCP_LOG_ERRREC_F_PRA_SUBSYS	= 1 << 1,
	/* PCIe Function Level Reset */
	OCP_LOG_ERRREC_F_PRA_FLR	= 1 << 2,
	/* ASSERT #PERST (PCIe Fundamental Reset) */
	OCP_LOG_ERRREC_F_PRA_PERST	= 1 << 3,
	/* Power cycle the device */
	OCP_LOG_ERRREC_F_PRA_POWER	= 1 << 4,
	/* PCIe conventional hot reset */
	OCP_LOG_ERRREC_F_PRA_HOT	= 1 << 5
} ocp_errrec_pra_t;

typedef enum {
	/* Do nothing */
	OCP_LOG_ERRREC_F_DRA_NONE	= 1 << 0,
	/* Format required */
	OCP_LOG_ERRREC_F_DRA_FMT	= 1 << 1,
	/* Vendor specific commad */
	OCP_LOG_ERRREC_F_DRA_VSC	= 1 << 2,
	/* Vendor analysis required */
	OCP_LOG_ERRREC_F_DRA_VAR	= 1 << 3,
	/* Replace the device */
	OCP_LOG_ERRREC_F_DRA_REPLACE	= 1 << 4,
	/* Sanitize required */
	OCP_LOG_ERRREC_F_DRA_SANITIZE	= 1 << 5,
	/*
	 * Indicates that there is permanent data loss in some LBAs. The LBAs
	 * are identified by the LBA Status log 0xe.
	 */
	OCP_LOG_ERRREC_F_DRA_DATALOSS	= 1 << 6,
} ocp_errrec_dra_t;

/*
 * Device capabilities. Used to indicate how a message about a panic can be sent
 * today.
 */
typedef enum {
	OCP_LOG_ERRREC_F_DEVCAP_AEN	= 1 << 0,
	OCP_LOG_ERRREC_F_DEVCAP_CFS	= 1 << 1
} ocp_errrec_devcap_t;

/*
 * OCP Firmware Activation. Present in 1.0 and 2.0. Removed in 2.5.
 */
typedef struct {
	uint8_t ofe_vers;
	uint8_t ofe_len;
	uint8_t ofe_rsvd2[2];
	uint16_t ofe_count;
	uint64_t ofe_ts;
	uint8_t ofe_rsvd14[8];
	uint64_t ofe_pcc;
	uint64_t ofe_prev_fw;
	uint64_t ofe_new_fw;
	uint8_t ofe_slot;
	uint8_t ofe_ctype;
	uint16_t ofe_res;
	uint8_t ofe_rsvd50[14];
} ocp_fwact_entry_t;

typedef struct {
	uint8_t ofw_lid;
	uint8_t ofw_rsvd1[3];
	uint32_t ofw_nents;
	ocp_fwact_entry_t ofw_hist[20];
	uint8_t ofw_rsvd1288[2790];
	/*
	 * V1.0: 1, V2.0: 1
	 */
	uint16_t ofw_vers;
	/*
	 * Log Page GUID: 3AC8AB24DE2A3F6DAB4769A796Dh.
	 */
	uint8_t ofw_guid[16];
} ocp_vul_fwact_t;

/*
 * Latency Monitor log. Added in V2.0.
 */
typedef struct {
	uint32_t obc_read;
	uint32_t obc_write;
	uint32_t obc_dealloc;
	uint32_t obc_rsvd;
} ocp_lat_bkt_ctr_t;

typedef struct {
	uint64_t ola_read;
	uint64_t ola_write;
	uint64_t ola_dealloc;
} ocp_lat_alts_t;

typedef struct {
	uint16_t olm_read;
	uint16_t olm_write;
	uint16_t olm_dealloc;
} ocp_lat_aml_t;

typedef struct {
	/*
	 * Latency monitor features. See ocp_lat_lmfs_t.
	 */
	uint8_t ol_lmfs;
	uint8_t ol_rsvd1[1];
	/*
	 * Active bucket timer, its threshold, and general thresholds.
	 */
	uint16_t ol_abt;
	uint16_t ol_abt_thresh;
	uint8_t ol_thresh_a;
	uint8_t ol_thresh_b;
	uint8_t ol_thresh_c;
	uint8_t ol_thresh_d;
	/*
	 * Active latency configuration. See ocp_lat_alc_t.
	 */
	uint16_t ol_alc;
	uint8_t ol_alw_min;
	uint8_t ol_rsvd13[19];
	/*
	 * Active bucket counters.
	 */
	ocp_lat_bkt_ctr_t ol_ctr0;
	ocp_lat_bkt_ctr_t ol_ctr1;
	ocp_lat_bkt_ctr_t ol_ctr2;
	ocp_lat_bkt_ctr_t ol_ctr3;
	/*
	 * Active Latency Stamps. These contain 64-bit timestamps for when
	 * events occurred. Grouped by bucket.
	 */
	ocp_lat_alts_t ol_ts0;
	ocp_lat_alts_t ol_ts1;
	ocp_lat_alts_t ol_ts2;
	ocp_lat_alts_t ol_ts3;
	/*
	 * Active Measured Latency. Grouped by bucket.
	 */
	ocp_lat_aml_t ol_aml0;
	ocp_lat_aml_t ol_aml1;
	ocp_lat_aml_t ol_aml2;
	ocp_lat_aml_t ol_aml3;
	uint16_t ol_als_units;
	uint8_t ol_rsvd218[22];
	/*
	 * Static versions of everything above.
	 */
	ocp_lat_bkt_ctr_t ol_sb0;
	ocp_lat_bkt_ctr_t ol_sb1;
	ocp_lat_bkt_ctr_t ol_sb2;
	ocp_lat_bkt_ctr_t ol_sb3;
	ocp_lat_alts_t ol_sts0;
	ocp_lat_alts_t ol_sts1;
	ocp_lat_alts_t ol_sts2;
	ocp_lat_alts_t ol_sts3;
	ocp_lat_aml_t ol_saml0;
	ocp_lat_aml_t ol_saml1;
	ocp_lat_aml_t ol_saml2;
	ocp_lat_aml_t ol_saml3;
	uint16_t ol_als_sunits;
	uint8_t ol_rsvd426[10];
	/*
	 * Debug log related fields. The number of dword fields is specific to
	 * v2.5.
	 */
	uint8_t ol_dbg_ndw[12];
	uint16_t ol_dbg_trig;
	uint16_t ol_dbg_ml;
	uint64_t ol_dbg_ts;
	uint16_t ol_dbg_ptr;
	uint16_t ol_dbg_src;
	uint8_t ol_dbg_units;
	uint8_t ol_rsvd465[29];
	/*
	 * V2.0: 1, V2.5: 4
	 */
	uint16_t ol_vers;
	/*
	 * Log page GUID: 85D45E58D4E643709C6C84D08CC07A92h.
	 */
	uint8_t ol_guid[16];
} ocp_vul_lat_t;

typedef enum {
	OPC_LOG_LAT_F_LFMS_EN		= 1 << 0,
	OPC_LOG_LAT_F_LFMS_ALC_SUP	= 1 << 1,
	OPC_LOG_LAT_F_LFMS_AML_SUP	= 1 << 2,
} ocp_lat_lmfs_t;

typedef enum {
	OCP_LOG_LAT_F_ALC_B0_READ	= 1 << 0,
	OCP_LOG_LAT_F_ALC_B0_WRITE	= 1 << 1,
	OCP_LOG_LAT_F_ALC_B0_DEALLOC	= 1 << 2,
	OCP_LOG_LAT_F_ALC_B1_READ	= 1 << 3,
	OCP_LOG_LAT_F_ALC_B1_WRITE	= 1 << 4,
	OCP_LOG_LAT_F_ALC_B1_DEALLOC	= 1 << 5,
	OCP_LOG_LAT_F_ALC_B2_READ	= 1 << 6,
	OCP_LOG_LAT_F_ALC_B2_WRITE	= 1 << 7,
	OCP_LOG_LAT_F_ALC_B2_DEALLOC	= 1 << 8,
	OCP_LOG_LAT_F_ALC_B3_READ	= 1 << 9,
	OCP_LOG_LAT_F_ALC_B3_WRITE	= 1 << 10,
	OCP_LOG_LAT_F_ALC_B3_DEALLOC	= 1 << 11
} ocp_lat_alc_t;

/*
 * Device Capabilities Log. Introduced in v2.0.
 */
typedef struct {
#ifdef	_BIT_FIELDS_LTOH
	uint8_t odp_nps:5;
	uint8_t odp_rsvd5:2;
	uint8_t odp_valid:1;
#else
	uint8_t odp_valid:1;
	uint8_t odp_rsvd5:2;
	uint8_t odp_nps:5;
#endif	/* _BIT_FIELDS_LTOH */
} ocp_dssd_ps_t;

typedef struct {
	uint16_t odc_nports;
	uint16_t odc_oob_sup;
	uint16_t odc_wz_sup;
	uint16_t odc_san_sup;
	uint16_t odc_dsmgmt_sup;
	uint16_t odc_wunc_sup;
	uint16_t odc_fuse_sup;
	uint16_t odc_dssd_min_valid;
	ocp_dssd_ps_t odc_dssd[128];
	uint8_t odc_rsvd144[3934];
	/*
	 * V2.0: 1, V2.5: 1
	 */
	uint16_t odc_vers;
	/*
	 * Log page GUID: B7053C914B58495D98C9E1D10D054297h
	 */
	uint8_t odc_guid[16];
} ocp_vul_devcap_t;

typedef enum {
	/* PCIe VDM Supported */
	OCP_LOG_DEVCAP_F_OOB_VDM	= 1 << 0,
	/* NVMe Basic Management Command supported */
	OCP_LOG_DEVCAP_F_OOB_BMC	= 1 << 1,
	/* Passed compliance testing */
	OCP_LOG_DEVCAP_F_OOB_COMPLY	= 1 << 15,
} ocp_devcap_oob_t;

typedef enum {
	/* Write Zeros command supported */
	OCP_LOG_DEVCAP_F_WZ_SUP		= 1 << 0,
	/* Write Zeros deallocate bit */
	OCP_LOG_DEVCAP_F_WZ_DEAC	= 1 << 1,
	/* Write Zeros force unit access */
	OCP_LOG_DEVCAP_F_WZ_FUA		= 1 << 2,
	/* Adheres to spec req NVME-IO-5 */
	OCP_LOG_DEVCAP_F_WZ_IO5		= 1 << 3,
	/* Adheres to spec req NVME-IO-6 */
	OCP_LOG_DEVCAP_F_WZ_IO6		= 1 << 4,
	/* Passed compliance testing */
	OCP_LOG_DEVCAP_F_WZ_COMPLY	= 1 << 15
} ocp_devcap_wz_t;

typedef enum {
	/* Dataset Management command supported */
	OCP_LOG_DEVCAP_F_DSMGMT_SUP	= 1 << 0,
	/* Attribute deallocate supported */
	OCP_LOG_DEVCAP_F_DSMGMT_AD	= 1 << 1,
	/* Passed compliance testing */
	OCP_LOG_DEVCAP_F_DSMGMT_COMPLY	= 1 << 15
} ocp_devcap_dsmgmt_t;

typedef enum {
	/* Write uncorrectable supported */
	OCP_LOG_DEVCAP_F_WUNC_SUP	= 1 << 0,
	/* Works with a single LBA */
	OCP_LOG_DEVCAP_F_WUNC_ONE	= 1 << 1,
	/* Works with max LBAs per NVMe spec */
	OCP_LOG_DEVCAP_F_WUNC_MAX	= 1 << 2,
	/* Adheres to spec req NVME-IO-14 */
	OCP_LOG_DEVCAP_F_WUNC_IO14	= 1 << 3,
	/* Passed compliance testing */
	OCP_LOG_DEVCAP_F_WUNC_COMPLY	= 1 << 15
} ocp_devcap_wunc_t;

typedef enum {
	/* Fused operation supported */
	OCP_LOG_DEVCAP_F_FUSE_SUP	= 1 << 0,
	/* Passed compliance testing */
	OCP_LOG_DEVCAP_F_FUSE_COMPLY	= 1 << 15
} ocp_devcap_fuse_t;

/*
 * Unsupported Requirements log. This log is structured such that each
 * unimplemented requirement must fit into a single 16 byte array which should
 * be padded with zeros (but nothing in the spec suggests it guarantees
 * termination). We keep the requirements string as a uint8_t as opposed to a
 * char to indicate that this should not be trusted and must be parsed.
 */
typedef struct {
	uint8_t ors_str[16];
} ocp_req_str_t;

typedef struct {
	uint16_t our_nunsup;
	uint8_t our_rsvd2[14];
	ocp_req_str_t our_reqs[253];
	uint8_t our_rsvd4064[14];
	/*
	 * V2.0: 1, V2.5: 1
	 */
	uint16_t our_vers;
	/*
	 * Log page GUID: C7BB98B7D0324863BB2C23990E9C722Fh
	 */
	uint8_t our_guid[16];
} ocp_vul_unsup_req_t;

/*
 * Telemetry String Log. This log, added in OCP v2.5 is structured with a header
 * of fixed tables followed by variable information based upon the header
 * information.
 */
typedef struct {
	/*
	 * v2.5: 1
	 */
	uint8_t ots_vers;
	uint8_t ots_rsvd1[15];
	/*
	 * Log Page GUID: B13A83691A8F408B9EA495940057AA44h
	 */
	uint8_t ots_guid[16];
	/*
	 * These members generally indicate different parts of the table offset
	 * (ends with 's') and size (ends with 'z').
	 * Each of them is a number of uint32_t's long (aka dwords).
	 */
	uint64_t ots_sls;
	uint8_t ots_rsvd40[24];
	uint64_t ots_sits;
	uint64_t ots_sitz;
	uint64_t ots_ests;
	uint64_t ots_estz;
	uint64_t ots_vuests;
	uint64_t ots_vuestz;
	uint64_t ots_ascts;
	uint64_t ots_asctz;
	/*
	 * These are nominally ASCII strings that are supposed to cover various
	 * FIFOs.
	 */
	uint8_t ots_fifo0[16];
	uint8_t ots_fifo1[16];
	uint8_t ots_fifo2[16];
	uint8_t ots_fifo3[16];
	uint8_t ots_fifo4[16];
	uint8_t ots_fifo5[16];
	uint8_t ots_fifo6[16];
	uint8_t ots_fifo7[16];
	uint8_t ots_fifo8[16];
	uint8_t ots_fifo9[16];
	uint8_t ots_fifo10[16];
	uint8_t ots_fifo11[16];
	uint8_t ots_fifo12[16];
	uint8_t ots_fifo13[16];
	uint8_t ots_fifo14[16];
	uint8_t ots_fifo15[16];
	uint8_t ots_rsvd384[48];
	/*
	 * After this we have the various tables. While in theory they are
	 * supposed to be ordered such that its SITS, ESTS, VUEST, ASCTS, in
	 * theory these could be at any offset. The individual structures which
	 * this could be are defined below.
	 */
	uint8_t ots_data[];
} ocp_vul_telstr_t;

/*
 * These three structures all have the same general form. They contain a 0s
 * based length and then an offset from the start of the ASCII string table. The
 * actual string table is spaced in uint32_t increments and padded with spaces.
 * There is no NULL terminator in it.
 */
typedef struct {
	uint16_t ocp_sit_id;
	uint8_t ocp_sit_rsvd2[1];
	/*
	 * Zeros based length, so add one.
	 */
	uint8_t ocp_sit_len;
	/*
	 * Offset from the start of the ASCII table for this entry.
	 */
	uint64_t ocp_sit_off;
	uint8_t ocp_sit_rsvd12[4];
} ocp_vul_telstr_sit_t;

typedef struct {
	uint8_t ocp_est_class;
	uint16_t ocp_est_eid;
	uint8_t ocp_est_len;
	uint64_t ocp_est_off;
	uint8_t ocp_est_rsvd12[4];
} ocp_vul_telstr_est_t;

typedef struct {
	uint8_t ocp_vuest_class;
	uint16_t ocp_vuest_eid;
	uint8_t ocp_vuest_len;
	uint64_t ocp_vuest_off;
	uint8_t ocp_vuest_rsvd12[4];
} ocp_vul_telstr_vuest_t;

/*
 * Our current version of smatch cannot handle packed structures.
 */
#ifndef __CHECKER__
CTASSERT(sizeof (ocp_vul_smart_t) == 512);
CTASSERT(offsetof(ocp_vul_smart_t, osh_therm) == 96);
CTASSERT(offsetof(ocp_vul_smart_t, osh_vers) == 494);
CTASSERT(sizeof (ocp_vul_errrec_t) == 512);
CTASSERT(offsetof(ocp_vul_errrec_t, oer_npanic) == 31);
CTASSERT(offsetof(ocp_vul_errrec_t, oer_npanic) == 31);
CTASSERT(sizeof (ocp_fwact_entry_t) == 64);
CTASSERT(offsetof(ocp_fwact_entry_t, ofe_rsvd50) == 50);
CTASSERT(sizeof (ocp_vul_fwact_t) == 4096);
CTASSERT(offsetof(ocp_vul_fwact_t, ofw_rsvd1288) == 1288);
CTASSERT(offsetof(ocp_vul_fwact_t, ofw_vers) == 4078);
CTASSERT(sizeof (ocp_lat_bkt_ctr_t) == 16);
CTASSERT(sizeof (ocp_lat_alts_t) == 24);
CTASSERT(sizeof (ocp_lat_aml_t) == 6);
CTASSERT(offsetof(ocp_vul_lat_t, ol_aml0) == 192);
CTASSERT(offsetof(ocp_vul_lat_t, ol_rsvd218) == 218);
CTASSERT(offsetof(ocp_vul_lat_t, ol_als_sunits) == 424);
CTASSERT(sizeof (ocp_vul_lat_t) == 512);
CTASSERT(sizeof (ocp_vul_devcap_t) == 4096);
CTASSERT(offsetof(ocp_vul_devcap_t, odc_rsvd144) == 144);
CTASSERT(sizeof (ocp_req_str_t) == 16);
CTASSERT(sizeof (ocp_vul_unsup_req_t) == 4096);
CTASSERT(sizeof (ocp_vul_telstr_t) == 432);
CTASSERT(offsetof(ocp_vul_telstr_t, ots_fifo0) == 128);
CTASSERT(offsetof(ocp_vul_telstr_t, ots_rsvd384) == 384);
CTASSERT(sizeof (ocp_vul_telstr_sit_t) == 16);
CTASSERT(sizeof (ocp_vul_telstr_est_t) == 16);
CTASSERT(sizeof (ocp_vul_telstr_vuest_t) == 16);
#endif

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

#ifdef __cplusplus
}
#endif

#endif /* _SYS_NVME_OCP_H */