Index: sbin/nvmecontrol/modules/intel/intel.c =================================================================== --- sbin/nvmecontrol/modules/intel/intel.c +++ sbin/nvmecontrol/modules/intel/intel.c @@ -181,6 +181,97 @@ } } +static void +print_intel_max_lba(uint32_t cdw0, void *buf __unused, uint32_t len __unused) +{ + + printf(" Max LBA: "); + printf("%u\n", cdw0); +} + +static void +print_intel_native_max_lba(uint32_t cdw0, void *buf __unused, uint32_t len __unused) +{ + + printf(" Native Max LBA: "); + printf("%u\n", cdw0); +} + +static void +print_intel_power_governor_setting(uint32_t cdw0, void *buf __unused, uint32_t len __unused) +{ + uint8_t pg = cdw0 & 0xff; /* Power Governor */ + + printf(" Power Governor Setting (PGS): "); + switch (pg) { + case 0x00: + printf("25W(typ)\n"); + break; + case 0x01: + printf("20W(typ)\n"); + break; + case 0x02: + printf("10W(typ)\n"); + break; + default: + printf("%d\n", pg); + break; + } +} + +static void +interpret_intel_max_lba(uint8_t status) +{ + + switch (status) { + case 0xc0: + printf("Requested MAX LBA exceeds Available capacity\n"); + break; + case 0xc1: + printf("Requested MAX LBA smaller than minimum allowable limit\n"); + break; + case 0xc2: + printf("Requested MAX LBA is smaller than allocated Namespace requirements\n"); + break; + default: + printf("Unknown Status Code: %u\n", status); + break; + } +} + +static void +interpret_intel_power_governor_setting(uint8_t status) +{ + + switch (status) { + case 0xc0: + printf("Invalid Setting\n"); + break; + default: + printf("Unknown Status Code: %u\n", status); + break; + } +} + +static void +interpret_intel_reset_timed_workload_counters(uint8_t status) +{ + + switch (status) { + case 0xc0: + printf("Invalid Setting\n"); + break; + default: + printf("Unknown Status Code: %u\n", status); + break; + } +} + +#define INTEL_FEAT_MAX_LBA 0xc1 +#define INTEL_FEAT_NATIVE_MAX_LBA 0xc2 +#define INTEL_FEAT_POWER_GOVERNOR_SETTING 0xc6 +#define INTEL_FEAT_RESET_TIMED_WORKLOAD_COUNTERS 0xd5 + NVME_LOGPAGE(intel_temp, INTEL_LOG_TEMP_STATS, "intel", "Temperature Stats", print_intel_temp_stats, sizeof(struct intel_log_temp_stats)); @@ -193,3 +284,15 @@ NVME_LOGPAGE(intel_smart, INTEL_LOG_ADD_SMART, "intel", "Extra Health/SMART Data", print_intel_add_smart, DEFAULT_SIZE); +NVME_FEATURE(intel_max_lba, + INTEL_FEAT_MAX_LBA, "intel", "Max LBA", + print_intel_max_lba, interpret_intel_max_lba, 0); +NVME_FEATURE(intel_native_max_lba, + INTEL_FEAT_NATIVE_MAX_LBA, "intel", "Native Max LBA", + print_intel_native_max_lba, NULL, 0); +NVME_FEATURE(intel_power_governor_setting, + INTEL_FEAT_POWER_GOVERNOR_SETTING, "intel", "Power Governor Setting", + print_intel_power_governor_setting, interpret_intel_power_governor_setting, 0); +NVME_FEATURE(intel_reset_timed_workload_counters, + INTEL_FEAT_RESET_TIMED_WORKLOAD_COUNTERS, "intel", "Reset Timed Workload Counters", + get_feature_not_support, interpret_intel_reset_timed_workload_counters, 0); Index: sbin/nvmecontrol/nvmecontrol.h =================================================================== --- sbin/nvmecontrol/nvmecontrol.h +++ sbin/nvmecontrol/nvmecontrol.h @@ -35,16 +35,28 @@ #include "comnd.h" typedef void (*print_fn_t)(const struct nvme_controller_data *cdata, void *buf, uint32_t size); +typedef void (*feat_print_fn_t)(uint32_t cdw0, void *buf, uint32_t size); +typedef void (*feat_interpret_fn_t)(uint8_t status); struct logpage_function { - SLIST_ENTRY(logpage_function) link; + SLIST_ENTRY(logpage_function) link; uint8_t log_page; - const char *vendor; - const char *name; + const char *vendor; + const char *name; print_fn_t print_fn; size_t size; }; +struct feature_function { + SLIST_ENTRY(feature_function) link; + uint8_t fid; + const char *vendor; + const char *name; + feat_print_fn_t print_fn; + feat_interpret_fn_t pret_fn; + size_t size; +}; + #define NVME_LOGPAGE(unique, lp, vend, nam, fn, sz) \ static struct logpage_function unique ## _lpf = { \ .log_page = lp, \ @@ -53,8 +65,20 @@ .print_fn = fn, \ .size = sz, \ } ; \ - static void logpage_reg_##unique(void) __attribute__((constructor)); \ - static void logpage_reg_##unique(void) { logpage_register(&unique##_lpf); } + static void logpage_reg_##unique(void) __attribute__((constructor)); \ + static void logpage_reg_##unique(void) { logpage_register(&unique##_lpf); } + +#define NVME_FEATURE(unique, id, vend, nam, fnp, fni, sz) \ + static struct feature_function unique ## _ff = { \ + .fid = id, \ + .vendor = vend, \ + .name = nam, \ + .print_fn = fnp, \ + .pret_fn = fni, \ + .size = sz, \ + } ; \ + static void feature_reg_##unique(void) __attribute__((constructor)); \ + static void feature_reg_##unique(void) { feature_register(&unique##_ff); } #define DEFAULT_SIZE (4096) struct kv_name { @@ -65,6 +89,8 @@ const char *kv_lookup(const struct kv_name *kv, size_t kv_count, uint32_t key); void logpage_register(struct logpage_function *p); +void feature_register(struct feature_function *p); +void get_feature_not_support(uint32_t cdw0, void *buf, uint32_t len); #define NVME_CTRLR_PREFIX "nvme" #define NVME_NS_PREFIX "ns"