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 2020 Oxide Computer Company 14 */ 15 16 /* 17 * This driver is used to implement parts of the ksensor test suite. 18 */ 19 20 #include <sys/ddi.h> 21 #include <sys/sunddi.h> 22 #include <sys/modctl.h> 23 #include <sys/conf.h> 24 #include <sys/devops.h> 25 #include <sys/zone.h> 26 #include <sys/sensors.h> 27 28 typedef struct ksensor_test { 29 dev_info_t *kt_dip; 30 id_t kt_sensor1; 31 id_t kt_sensor2; 32 id_t kt_sensor3; 33 id_t kt_sensor4; 34 id_t kt_sensor5; 35 id_t kt_volt; 36 id_t kt_current; 37 } ksensor_test_t; 38 39 static int 40 ksensor_test_temp(void *arg, sensor_ioctl_scalar_t *scalar) 41 { 42 scalar->sis_unit = SENSOR_UNIT_CELSIUS; 43 scalar->sis_gran = 4; 44 scalar->sis_prec = -2; 45 scalar->sis_value = 23; 46 return (0); 47 } 48 49 static const ksensor_ops_t ksensor_test_temp_ops = { 50 .kso_kind = ksensor_kind_temperature, 51 .kso_scalar = ksensor_test_temp 52 }; 53 54 static int 55 ksensor_test_volt(void *arg, sensor_ioctl_scalar_t *scalar) 56 { 57 scalar->sis_unit = SENSOR_UNIT_VOLTS; 58 scalar->sis_gran = 1000; 59 scalar->sis_prec = 0; 60 scalar->sis_value = 3300; 61 return (0); 62 } 63 64 static const ksensor_ops_t ksensor_test_volt_ops = { 65 .kso_kind = ksensor_kind_voltage, 66 .kso_scalar = ksensor_test_volt 67 }; 68 69 static int 70 ksensor_test_current(void *arg, sensor_ioctl_scalar_t *scalar) 71 { 72 scalar->sis_unit = SENSOR_UNIT_AMPS; 73 scalar->sis_gran = 10; 74 scalar->sis_prec = 0; 75 scalar->sis_value = 5; 76 return (0); 77 } 78 79 static const ksensor_ops_t ksensor_test_current_ops = { 80 .kso_kind = ksensor_kind_current, 81 .kso_scalar = ksensor_test_current 82 }; 83 84 static int 85 ksensor_test_kind_eio(void *arg, sensor_ioctl_kind_t *kindp) 86 { 87 return (EIO); 88 } 89 90 static int 91 ksensor_test_temp_eio(void *arg, sensor_ioctl_scalar_t *scalar) 92 { 93 return (EIO); 94 } 95 96 static const ksensor_ops_t ksensor_test_eio_ops = { 97 .kso_kind = ksensor_test_kind_eio, 98 .kso_scalar = ksensor_test_temp_eio 99 }; 100 101 static int 102 ksensor_test_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 103 { 104 int ret; 105 char buf[128]; 106 ksensor_test_t *kt; 107 108 switch (cmd) { 109 case DDI_RESUME: 110 return (DDI_SUCCESS); 111 case DDI_ATTACH: 112 break; 113 default: 114 return (DDI_FAILURE); 115 } 116 117 kt = kmem_zalloc(sizeof (ksensor_test_t), KM_SLEEP); 118 kt->kt_dip = dip; 119 120 (void) snprintf(buf, sizeof (buf), "test.temp.%d.1", 121 ddi_get_instance(dip)); 122 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf, 123 "ddi_sensor:test", &kt->kt_sensor1)) != 0) { 124 dev_err(dip, CE_WARN, "failed to attatch sensor %s: %d", buf, 125 ret); 126 goto err; 127 } 128 129 (void) snprintf(buf, sizeof (buf), "test.temp.%d.2", 130 ddi_get_instance(dip)); 131 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf, 132 "ddi_sensor:test", &kt->kt_sensor2)) != 0) { 133 dev_err(dip, CE_WARN, "failed to attatch sensor %s: %d", buf, 134 ret); 135 goto err; 136 } 137 138 (void) snprintf(buf, sizeof (buf), "test.temp.%d.3", 139 ddi_get_instance(dip)); 140 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf, 141 "ddi_sensor:test", &kt->kt_sensor3)) != 0) { 142 dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf, 143 ret); 144 goto err; 145 } 146 147 (void) snprintf(buf, sizeof (buf), "test.temp.%d.4", 148 ddi_get_instance(dip)); 149 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf, 150 "ddi_sensor:test", &kt->kt_sensor4)) != 0) { 151 dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf, 152 ret); 153 goto err; 154 } 155 156 (void) snprintf(buf, sizeof (buf), "test.eio.%d", 157 ddi_get_instance(dip)); 158 if ((ret = ksensor_create(dip, &ksensor_test_eio_ops, NULL, buf, 159 "ddi_sensor:test", &kt->kt_sensor5)) != 0) { 160 dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf, 161 ret); 162 goto err; 163 } 164 165 (void) snprintf(buf, sizeof (buf), "test.volt.%d.1", 166 ddi_get_instance(dip)); 167 if ((ret = ksensor_create(dip, &ksensor_test_volt_ops, NULL, buf, 168 "ddi_sensor:test", &kt->kt_volt)) != 0) { 169 dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf, 170 ret); 171 goto err; 172 } 173 174 (void) snprintf(buf, sizeof (buf), "test.current.%d.1", 175 ddi_get_instance(dip)); 176 if ((ret = ksensor_create(dip, &ksensor_test_current_ops, NULL, buf, 177 "ddi_sensor:test", &kt->kt_current)) != 0) { 178 dev_err(dip, CE_WARN, "failed to attach sensor %s: %d", buf, 179 ret); 180 goto err; 181 } 182 183 ddi_set_driver_private(dip, kt); 184 185 return (DDI_SUCCESS); 186 err: 187 (void) ksensor_remove(dip, KSENSOR_ALL_IDS); 188 kmem_free(kt, sizeof (ksensor_test_t)); 189 return (DDI_FAILURE); 190 } 191 192 static int 193 ksensor_test_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 194 { 195 ksensor_test_t *kt; 196 197 switch (cmd) { 198 case DDI_DETACH: 199 break; 200 case DDI_SUSPEND: 201 return (DDI_SUCCESS); 202 default: 203 return (DDI_FAILURE); 204 } 205 206 kt = ddi_get_driver_private(dip); 207 if (kt == NULL) { 208 dev_err(dip, CE_WARN, "failed to find ksensor_test_t"); 209 return (DDI_FAILURE); 210 } 211 212 if (kt->kt_sensor3 != 0 && 213 ksensor_remove(dip, kt->kt_sensor3) != 0) { 214 dev_err(dip, CE_WARN, "failed to remove sensor 3"); 215 return (DDI_FAILURE); 216 } 217 kt->kt_sensor3 = 0; 218 if (ksensor_remove(dip, KSENSOR_ALL_IDS) != 0) { 219 dev_err(dip, CE_WARN, "failed to remove sensors"); 220 return (DDI_FAILURE); 221 } 222 kmem_free(kt, sizeof (*kt)); 223 ddi_set_driver_private(dip, NULL); 224 return (DDI_SUCCESS); 225 } 226 227 static struct dev_ops ksensor_test_dev_ops = { 228 .devo_rev = DEVO_REV, 229 .devo_refcnt = 0, 230 .devo_getinfo = nodev, 231 .devo_identify = nulldev, 232 .devo_probe = nulldev, 233 .devo_attach = ksensor_test_attach, 234 .devo_detach = ksensor_test_detach, 235 .devo_reset = nodev, 236 .devo_power = ddi_power, 237 .devo_quiesce = ddi_quiesce_not_needed, 238 }; 239 240 static struct modldrv ksensor_test_modldrv = { 241 .drv_modops = &mod_driverops, 242 .drv_linkinfo = "Kernel Sensor test driver", 243 .drv_dev_ops = &ksensor_test_dev_ops 244 }; 245 246 static struct modlinkage ksensor_test_modlinkage = { 247 .ml_rev = MODREV_1, 248 .ml_linkage = { &ksensor_test_modldrv, NULL } 249 }; 250 251 int 252 _init(void) 253 { 254 return (mod_install(&ksensor_test_modlinkage)); 255 } 256 257 int 258 _info(struct modinfo *modinfop) 259 { 260 return (mod_info(&ksensor_test_modlinkage, modinfop)); 261 } 262 263 int 264 _fini(void) 265 { 266 return (mod_remove(&ksensor_test_modlinkage)); 267 } 268