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 } ksensor_test_t; 36 37 static int 38 ksensor_test_temperature(void *arg, sensor_ioctl_temperature_t *temp) 39 { 40 temp->sit_unit = SENSOR_UNIT_CELSIUS; 41 temp->sit_gran = 4; 42 temp->sit_prec = -2; 43 temp->sit_temp = 23; 44 return (0); 45 } 46 47 static const ksensor_ops_t ksensor_test_temp_ops = { 48 ksensor_kind_temperature, 49 ksensor_test_temperature 50 }; 51 52 static int 53 ksensor_test_kind_eio(void *arg, sensor_ioctl_kind_t *kindp) 54 { 55 return (EIO); 56 } 57 58 static int 59 ksensor_test_temp_eio(void *arg, sensor_ioctl_temperature_t *tempp) 60 { 61 return (EIO); 62 } 63 64 static const ksensor_ops_t ksensor_test_eio_ops = { 65 ksensor_test_kind_eio, 66 ksensor_test_temp_eio 67 }; 68 69 static int 70 ksensor_test_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 71 { 72 int ret; 73 char buf[128]; 74 ksensor_test_t *kt; 75 76 switch (cmd) { 77 case DDI_RESUME: 78 return (DDI_SUCCESS); 79 case DDI_ATTACH: 80 break; 81 default: 82 return (DDI_FAILURE); 83 } 84 85 kt = kmem_zalloc(sizeof (ksensor_test_t), KM_SLEEP); 86 kt->kt_dip = dip; 87 88 (void) snprintf(buf, sizeof (buf), "test.temp.%d.1", 89 ddi_get_instance(dip)); 90 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf, 91 "ddi_sensor:test", &kt->kt_sensor1)) != 0) { 92 dev_err(dip, CE_WARN, "failed to attatch sensor %s: %d", buf, 93 ret); 94 goto err; 95 } 96 97 (void) snprintf(buf, sizeof (buf), "test.temp.%d.2", 98 ddi_get_instance(dip)); 99 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf, 100 "ddi_sensor:test", &kt->kt_sensor2)) != 0) { 101 dev_err(dip, CE_WARN, "failed to attatch sensor %s: %d", buf, 102 ret); 103 goto err; 104 } 105 106 (void) snprintf(buf, sizeof (buf), "test.temp.%d.3", 107 ddi_get_instance(dip)); 108 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf, 109 "ddi_sensor:test", &kt->kt_sensor3)) != 0) { 110 dev_err(dip, CE_WARN, "failed to attatch sensor %s: %d", buf, 111 ret); 112 goto err; 113 } 114 115 (void) snprintf(buf, sizeof (buf), "test.temp.%d.4", 116 ddi_get_instance(dip)); 117 if ((ret = ksensor_create(dip, &ksensor_test_temp_ops, NULL, buf, 118 "ddi_sensor:test", &kt->kt_sensor4)) != 0) { 119 dev_err(dip, CE_WARN, "failed to attatch sensor %s: %d", buf, 120 ret); 121 goto err; 122 } 123 124 (void) snprintf(buf, sizeof (buf), "test.eio.%d", 125 ddi_get_instance(dip)); 126 if ((ret = ksensor_create(dip, &ksensor_test_eio_ops, NULL, buf, 127 "ddi_sensor:test", &kt->kt_sensor5)) != 0) { 128 dev_err(dip, CE_WARN, "failed to attatch sensor %s: %d", buf, 129 ret); 130 goto err; 131 } 132 133 ddi_set_driver_private(dip, kt); 134 135 return (DDI_SUCCESS); 136 err: 137 (void) ksensor_remove(dip, KSENSOR_ALL_IDS); 138 kmem_free(kt, sizeof (ksensor_test_t)); 139 return (DDI_FAILURE); 140 } 141 142 static int 143 ksensor_test_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 144 { 145 ksensor_test_t *kt; 146 147 switch (cmd) { 148 case DDI_DETACH: 149 break; 150 case DDI_SUSPEND: 151 return (DDI_SUCCESS); 152 default: 153 return (DDI_FAILURE); 154 } 155 156 kt = ddi_get_driver_private(dip); 157 if (kt == NULL) { 158 dev_err(dip, CE_WARN, "failed to find ksensor_test_t"); 159 return (DDI_FAILURE); 160 } 161 162 if (kt->kt_sensor3 != 0 && 163 ksensor_remove(dip, kt->kt_sensor3) != 0) { 164 dev_err(dip, CE_WARN, "failed to remove sensor 3"); 165 return (DDI_FAILURE); 166 } 167 kt->kt_sensor3 = 0; 168 if (ksensor_remove(dip, KSENSOR_ALL_IDS) != 0) { 169 dev_err(dip, CE_WARN, "failed to remove sensors"); 170 return (DDI_FAILURE); 171 } 172 kmem_free(kt, sizeof (*kt)); 173 ddi_set_driver_private(dip, NULL); 174 return (DDI_SUCCESS); 175 } 176 177 static struct dev_ops ksensor_test_dev_ops = { 178 .devo_rev = DEVO_REV, 179 .devo_refcnt = 0, 180 .devo_getinfo = nodev, 181 .devo_identify = nulldev, 182 .devo_probe = nulldev, 183 .devo_attach = ksensor_test_attach, 184 .devo_detach = ksensor_test_detach, 185 .devo_reset = nodev, 186 .devo_power = ddi_power, 187 .devo_quiesce = ddi_quiesce_not_needed, 188 }; 189 190 static struct modldrv ksensor_test_modldrv = { 191 .drv_modops = &mod_driverops, 192 .drv_linkinfo = "Kernel Sensor test driver", 193 .drv_dev_ops = &ksensor_test_dev_ops 194 }; 195 196 static struct modlinkage ksensor_test_modlinkage = { 197 .ml_rev = MODREV_1, 198 .ml_linkage = { &ksensor_test_modldrv, NULL } 199 }; 200 201 int 202 _init(void) 203 { 204 return (mod_install(&ksensor_test_modlinkage)); 205 } 206 207 int 208 _info(struct modinfo *modinfop) 209 { 210 return (mod_info(&ksensor_test_modlinkage, modinfop)); 211 } 212 213 int 214 _fini(void) 215 { 216 return (mod_remove(&ksensor_test_modlinkage)); 217 } 218