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 /* 17 * Implements logic to map a device to a vendor-specific entity. 18 */ 19 20 #include <libdevinfo.h> 21 #include <sys/sysmacros.h> 22 #include <string.h> 23 24 #include "libnvme_impl.h" 25 26 const nvme_vsd_t *const nvme_vsd_devices[] = { 27 &wdc_sn840, 28 &wdc_sn65x, 29 &wdc_sn861, 30 µn_7300, 31 µn_74x0, 32 µn_x500, 33 µn_9550, 34 &intel_p5510, 35 &solidigm_p5x20, 36 &solidigm_ps10x0, 37 &kioxia_cd8, 38 &phison_x200, 39 &samsung_pm9d3a 40 }; 41 42 /* 43 * Our job is to attempt to map a given device to vendor specific information, 44 * if it exists. It may not. 45 */ 46 void 47 nvme_vendor_map_ctrl(nvme_ctrl_t *ctrl) 48 { 49 int *vid, *did, *svidp, *sdidp; 50 uint16_t svid = UINT16_MAX, sdid = UINT16_MAX; 51 52 if (di_prop_lookup_ints(DDI_DEV_T_ANY, ctrl->nc_devi, "vendor-id", 53 &vid) != 1 || di_prop_lookup_ints(DDI_DEV_T_ANY, ctrl->nc_devi, 54 "device-id", &did) != 1) { 55 return; 56 } 57 58 if (di_prop_lookup_ints(DDI_DEV_T_ANY, ctrl->nc_devi, 59 "subsystem-vendor-id", &svidp) == 1) { 60 svid = (uint16_t)*svidp; 61 } 62 63 if (di_prop_lookup_ints(DDI_DEV_T_ANY, ctrl->nc_devi, "subsystem-id", 64 &sdidp) == 1) { 65 sdid = (uint16_t)*sdidp; 66 } 67 68 for (size_t dev = 0; dev < ARRAY_SIZE(nvme_vsd_devices); dev++) { 69 const nvme_vsd_t *vsd = nvme_vsd_devices[dev]; 70 71 for (size_t i = 0; i < vsd->nvd_nident; i++) { 72 const nvme_vsd_ident_t *ident = &vsd->nvd_ident[i]; 73 if (ident->nvdi_vid != (uint16_t)vid[0] || 74 ident->nvdi_did != (uint16_t)did[0]) { 75 continue; 76 } 77 78 if (ident->nvdi_subsys && (ident->nvdi_svid != svid || 79 ident->nvdi_sdid != sdid)) { 80 continue; 81 } 82 83 ctrl->nc_vsd = nvme_vsd_devices[dev]; 84 return; 85 } 86 } 87 } 88 89 bool 90 nvme_vendor_vuc_supported(nvme_ctrl_t *ctrl, const char *name) 91 { 92 if (ctrl->nc_vsd != NULL) { 93 for (size_t i = 0; i < ctrl->nc_vsd->nvd_nvuc; i++) { 94 if (strcmp(name, ctrl->nc_vsd->nvd_vuc[i].nvd_short) == 95 0) { 96 return (true); 97 } 98 } 99 } 100 101 return (nvme_ctrl_error(ctrl, NVME_ERR_VU_FUNC_UNSUP_BY_DEV, 0, 102 "device missing support for vendor unique command %s", name)); 103 } 104