Home | History | Annotate | Line # | Download | only in i2c
sht3x.c revision 1.1
      1  1.1  brad /*	$NetBSD: sht3x.c,v 1.1 2021/11/06 13:34:40 brad Exp $	*/
      2  1.1  brad 
      3  1.1  brad /*
      4  1.1  brad  * Copyright (c) 2021 Brad Spencer <brad (at) anduin.eldar.org>
      5  1.1  brad  *
      6  1.1  brad  * Permission to use, copy, modify, and distribute this software for any
      7  1.1  brad  * purpose with or without fee is hereby granted, provided that the above
      8  1.1  brad  * copyright notice and this permission notice appear in all copies.
      9  1.1  brad  *
     10  1.1  brad  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  1.1  brad  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  1.1  brad  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  1.1  brad  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  1.1  brad  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15  1.1  brad  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16  1.1  brad  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  1.1  brad  */
     18  1.1  brad 
     19  1.1  brad #include <sys/cdefs.h>
     20  1.1  brad __KERNEL_RCSID(0, "$NetBSD: sht3x.c,v 1.1 2021/11/06 13:34:40 brad Exp $");
     21  1.1  brad 
     22  1.1  brad /*
     23  1.1  brad   Driver for the Sensirion SHT30/SHT31/SHT35
     24  1.1  brad */
     25  1.1  brad 
     26  1.1  brad #include <sys/param.h>
     27  1.1  brad #include <sys/systm.h>
     28  1.1  brad #include <sys/kernel.h>
     29  1.1  brad #include <sys/device.h>
     30  1.1  brad #include <sys/module.h>
     31  1.1  brad #include <sys/conf.h>
     32  1.1  brad #include <sys/sysctl.h>
     33  1.1  brad #include <sys/mutex.h>
     34  1.1  brad #include <sys/condvar.h>
     35  1.1  brad #include <sys/kthread.h>
     36  1.1  brad #include <sys/pool.h>
     37  1.1  brad #include <sys/kmem.h>
     38  1.1  brad 
     39  1.1  brad #include <dev/sysmon/sysmonvar.h>
     40  1.1  brad #include <dev/i2c/i2cvar.h>
     41  1.1  brad #include <dev/i2c/sht3xreg.h>
     42  1.1  brad #include <dev/i2c/sht3xvar.h>
     43  1.1  brad 
     44  1.1  brad 
     45  1.1  brad static int	sht3x_take_break(void *, bool);
     46  1.1  brad static int	sht3x_get_status_register(void *, uint16_t *, bool);
     47  1.1  brad static int	sht3x_clear_status_register(void *, bool);
     48  1.1  brad static uint8_t 	sht3x_crc(uint8_t *, size_t);
     49  1.1  brad static int	sht3x_cmdr(struct sht3x_sc *, uint16_t, uint8_t *, size_t);
     50  1.1  brad static int 	sht3x_poke(i2c_tag_t, i2c_addr_t, bool);
     51  1.1  brad static int 	sht3x_match(device_t, cfdata_t, void *);
     52  1.1  brad static void 	sht3x_attach(device_t, device_t, void *);
     53  1.1  brad static int 	sht3x_detach(device_t, int);
     54  1.1  brad static void 	sht3x_refresh(struct sysmon_envsys *, envsys_data_t *);
     55  1.1  brad /* The chip that I had would not allow the limits to actually be set
     56  1.1  brad  * for reasons which are not obvious.  The chip took the command just
     57  1.1  brad  * fine, but a read back of the limit registers showed that no change
     58  1.1  brad  * was made, so disable limits for now.
     59  1.1  brad  */
     60  1.1  brad #ifdef __did_not_work
     61  1.1  brad static void	sht3x_get_limits(struct sysmon_envsys *, envsys_data_t *,
     62  1.1  brad     				 sysmon_envsys_lim_t *, uint32_t *);
     63  1.1  brad static void	sht3x_set_limits(struct sysmon_envsys *, envsys_data_t *,
     64  1.1  brad     				 sysmon_envsys_lim_t *, uint32_t *);
     65  1.1  brad #endif
     66  1.1  brad static int 	sht3x_verify_sysctl(SYSCTLFN_ARGS);
     67  1.1  brad static int 	sht3x_verify_sysctl_heateron(SYSCTLFN_ARGS);
     68  1.1  brad static int 	sht3x_verify_sysctl_modes(SYSCTLFN_ARGS);
     69  1.1  brad static int 	sht3x_verify_sysctl_repeatability(SYSCTLFN_ARGS);
     70  1.1  brad static int 	sht3x_verify_sysctl_rate(SYSCTLFN_ARGS);
     71  1.1  brad static int	sht3x_set_heater(struct sht3x_sc *);
     72  1.1  brad static void     sht3x_thread(void *);
     73  1.1  brad static int	sht3x_init_periodic_measurement(void *, int *);
     74  1.1  brad static void     sht3x_take_periodic_measurement(void *);
     75  1.1  brad static void     sht3x_start_thread(void *);
     76  1.1  brad static void     sht3x_stop_thread(void *);
     77  1.1  brad static int	sht3x_activate(device_t, enum devact);
     78  1.1  brad 
     79  1.1  brad #define SHT3X_DEBUG
     80  1.1  brad #ifdef SHT3X_DEBUG
     81  1.1  brad #define DPRINTF(s, l, x) \
     82  1.1  brad     do { \
     83  1.1  brad 	if (l <= s->sc_sht3xdebug) \
     84  1.1  brad 	    printf x; \
     85  1.1  brad     } while (/*CONSTCOND*/0)
     86  1.1  brad #else
     87  1.1  brad #define DPRINTF(s, l, x)
     88  1.1  brad #endif
     89  1.1  brad 
     90  1.1  brad CFATTACH_DECL_NEW(sht3xtemp, sizeof(struct sht3x_sc),
     91  1.1  brad     sht3x_match, sht3x_attach, sht3x_detach, sht3x_activate);
     92  1.1  brad 
     93  1.1  brad extern struct cfdriver sht3xtemp_cd;
     94  1.1  brad 
     95  1.1  brad static dev_type_open(sht3xopen);
     96  1.1  brad static dev_type_read(sht3xread);
     97  1.1  brad static dev_type_close(sht3xclose);
     98  1.1  brad const struct cdevsw sht3x_cdevsw = {
     99  1.1  brad 	.d_open = sht3xopen,
    100  1.1  brad 	.d_close = sht3xclose,
    101  1.1  brad 	.d_read = sht3xread,
    102  1.1  brad 	.d_write = nowrite,
    103  1.1  brad 	.d_ioctl = noioctl,
    104  1.1  brad 	.d_stop = nostop,
    105  1.1  brad 	.d_tty = notty,
    106  1.1  brad 	.d_poll = nopoll,
    107  1.1  brad 	.d_mmap = nommap,
    108  1.1  brad 	.d_kqfilter = nokqfilter,
    109  1.1  brad 	.d_discard = nodiscard,
    110  1.1  brad 	.d_flag = D_OTHER
    111  1.1  brad };
    112  1.1  brad 
    113  1.1  brad static struct sht3x_sensor sht3x_sensors[] = {
    114  1.1  brad 	{
    115  1.1  brad 		.desc = "humidity",
    116  1.1  brad 		.type = ENVSYS_SRELHUMIDITY,
    117  1.1  brad 	},
    118  1.1  brad 	{
    119  1.1  brad 		.desc = "temperature",
    120  1.1  brad 		.type = ENVSYS_STEMP,
    121  1.1  brad 	}
    122  1.1  brad };
    123  1.1  brad 
    124  1.1  brad /* The typical delays are MOSTLY documented in the datasheet for the chip.
    125  1.1  brad    There is no need to be very accurate with these, just rough estimates
    126  1.1  brad    will work fine.
    127  1.1  brad */
    128  1.1  brad 
    129  1.1  brad static struct sht3x_timing sht3x_timings[] = {
    130  1.1  brad 	{
    131  1.1  brad 		.cmd = SHT3X_SOFT_RESET,
    132  1.1  brad 		.typicaldelay = 3000,
    133  1.1  brad 	},
    134  1.1  brad 	{
    135  1.1  brad 		.cmd = SHT3X_GET_STATUS_REGISTER,
    136  1.1  brad 		.typicaldelay = 100,
    137  1.1  brad 	},
    138  1.1  brad 	{
    139  1.1  brad 		.cmd = SHT3X_BREAK,
    140  1.1  brad 		.typicaldelay = 100,
    141  1.1  brad 	},
    142  1.1  brad 	{
    143  1.1  brad 		.cmd = SHT3X_CLEAR_STATUS_REGISTER,
    144  1.1  brad 		.typicaldelay = 100,
    145  1.1  brad 	},
    146  1.1  brad 	{
    147  1.1  brad 		.cmd = SHT3X_MEASURE_REPEATABILITY_CS_HIGH,
    148  1.1  brad 		.typicaldelay = 15000,
    149  1.1  brad 	},
    150  1.1  brad 	{
    151  1.1  brad 		.cmd = SHT3X_MEASURE_REPEATABILITY_CS_MEDIUM,
    152  1.1  brad 		.typicaldelay = 6000,
    153  1.1  brad 	},
    154  1.1  brad 	{
    155  1.1  brad 		.cmd = SHT3X_MEASURE_REPEATABILITY_CS_LOW,
    156  1.1  brad 		.typicaldelay = 4000,
    157  1.1  brad 	},
    158  1.1  brad 	{
    159  1.1  brad 		.cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_HIGH,
    160  1.1  brad 		.typicaldelay = 15000,
    161  1.1  brad 	},
    162  1.1  brad 	{
    163  1.1  brad 		.cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_MEDIUM,
    164  1.1  brad 		.typicaldelay = 6000,
    165  1.1  brad 	},
    166  1.1  brad 	{
    167  1.1  brad 		.cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_LOW,
    168  1.1  brad 		.typicaldelay = 4000,
    169  1.1  brad 	},
    170  1.1  brad 	{
    171  1.1  brad 		.cmd = SHT3X_WRITE_HIGH_ALERT_SET,
    172  1.1  brad 		.typicaldelay = 5000,
    173  1.1  brad 	},
    174  1.1  brad 	{
    175  1.1  brad 		.cmd = SHT3X_WRITE_HIGH_ALERT_CLEAR,
    176  1.1  brad 		.typicaldelay = 5000,
    177  1.1  brad 	},
    178  1.1  brad 	{
    179  1.1  brad 		.cmd = SHT3X_WRITE_LOW_ALERT_SET,
    180  1.1  brad 		.typicaldelay = 5000,
    181  1.1  brad 	},
    182  1.1  brad 	{
    183  1.1  brad 		.cmd = SHT3X_WRITE_LOW_ALERT_CLEAR,
    184  1.1  brad 		.typicaldelay = 5000,
    185  1.1  brad 	}
    186  1.1  brad };
    187  1.1  brad 
    188  1.1  brad /* In single shot mode, find the command */
    189  1.1  brad 
    190  1.1  brad static struct sht3x_repeatability sht3x_repeatability_ss[] = {
    191  1.1  brad 	{
    192  1.1  brad 		.text = "high",
    193  1.1  brad 		.cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_HIGH,
    194  1.1  brad 	},
    195  1.1  brad 	{
    196  1.1  brad 		.text = "medium",
    197  1.1  brad 		.cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_MEDIUM,
    198  1.1  brad 	},
    199  1.1  brad 	{
    200  1.1  brad 		.text = "low",
    201  1.1  brad 		.cmd = SHT3X_MEASURE_REPEATABILITY_NOCS_LOW,
    202  1.1  brad 	}
    203  1.1  brad };
    204  1.1  brad 
    205  1.1  brad 
    206  1.1  brad /* For periodic, look at the repeatability and the rate.
    207  1.1  brad  * ART is a bit fake here, as the repeatability is not really
    208  1.1  brad  * used.
    209  1.1  brad  */
    210  1.1  brad 
    211  1.1  brad static struct sht3x_periodic sht3x_periodic_rate[] = {
    212  1.1  brad 	{
    213  1.1  brad 		.repeatability = "high",
    214  1.1  brad 		.rate = "0.5mps",
    215  1.1  brad 		.sdelay = 1000,
    216  1.1  brad 		.cmd = SHT3X_HALF_MPS_HIGH,
    217  1.1  brad 	},
    218  1.1  brad 	{
    219  1.1  brad 		.repeatability = "medium",
    220  1.1  brad 		.rate = "0.5mps",
    221  1.1  brad 		.sdelay = 1000,
    222  1.1  brad 		.cmd = SHT3X_HALF_MPS_MEDIUM,
    223  1.1  brad 	},
    224  1.1  brad 	{
    225  1.1  brad 		.repeatability = "low",
    226  1.1  brad 		.rate = "0.5mps",
    227  1.1  brad 		.sdelay = 1000,
    228  1.1  brad 		.cmd = SHT3X_HALF_MPS_LOW,
    229  1.1  brad 	},
    230  1.1  brad 	{
    231  1.1  brad 		.repeatability = "high",
    232  1.1  brad 		.rate = "1.0mps",
    233  1.1  brad 		.sdelay = 500,
    234  1.1  brad 		.cmd = SHT3X_ONE_MPS_HIGH,
    235  1.1  brad 	},
    236  1.1  brad 	{
    237  1.1  brad 		.repeatability = "medium",
    238  1.1  brad 		.rate = "1.0mps",
    239  1.1  brad 		.sdelay = 500,
    240  1.1  brad 		.cmd = SHT3X_ONE_MPS_MEDIUM,
    241  1.1  brad 	},
    242  1.1  brad 	{
    243  1.1  brad 		.repeatability = "low",
    244  1.1  brad 		.rate = "1.0mps",
    245  1.1  brad 		.sdelay = 500,
    246  1.1  brad 		.cmd = SHT3X_ONE_MPS_LOW,
    247  1.1  brad 	},
    248  1.1  brad 	{
    249  1.1  brad 		.repeatability = "high",
    250  1.1  brad 		.rate = "2.0mps",
    251  1.1  brad 		.sdelay = 250,
    252  1.1  brad 		.cmd = SHT3X_TWO_MPS_HIGH,
    253  1.1  brad 	},
    254  1.1  brad 	{
    255  1.1  brad 		.repeatability = "medium",
    256  1.1  brad 		.rate = "2.0mps",
    257  1.1  brad 		.sdelay = 250,
    258  1.1  brad 		.cmd = SHT3X_TWO_MPS_MEDIUM,
    259  1.1  brad 	},
    260  1.1  brad 	{
    261  1.1  brad 		.repeatability = "low",
    262  1.1  brad 		.rate = "2.0mps",
    263  1.1  brad 		.sdelay = 250,
    264  1.1  brad 		.cmd = SHT3X_TWO_MPS_LOW,
    265  1.1  brad 	},
    266  1.1  brad 	{
    267  1.1  brad 		.repeatability = "high",
    268  1.1  brad 		.rate = "4.0mps",
    269  1.1  brad 		.sdelay = 100,
    270  1.1  brad 		.cmd = SHT3X_FOUR_MPS_HIGH,
    271  1.1  brad 	},
    272  1.1  brad 	{
    273  1.1  brad 		.repeatability = "medium",
    274  1.1  brad 		.rate = "4.0mps",
    275  1.1  brad 		.sdelay = 100,
    276  1.1  brad 		.cmd = SHT3X_FOUR_MPS_MEDIUM,
    277  1.1  brad 	},
    278  1.1  brad 	{
    279  1.1  brad 		.repeatability = "low",
    280  1.1  brad 		.rate = "4.0mps",
    281  1.1  brad 		.sdelay = 100,
    282  1.1  brad 		.cmd = SHT3X_FOUR_MPS_LOW,
    283  1.1  brad 	},
    284  1.1  brad 	{
    285  1.1  brad 		.repeatability = "high",
    286  1.1  brad 		.rate = "10.0mps",
    287  1.1  brad 		.sdelay = 50,
    288  1.1  brad 		.cmd = SHT3X_TEN_MPS_HIGH,
    289  1.1  brad 	},
    290  1.1  brad 	{
    291  1.1  brad 		.repeatability = "medium",
    292  1.1  brad 		.rate = "10.0mps",
    293  1.1  brad 		.sdelay = 50,
    294  1.1  brad 		.cmd = SHT3X_FOUR_MPS_MEDIUM,
    295  1.1  brad 	},
    296  1.1  brad 	{
    297  1.1  brad 		.repeatability = "low",
    298  1.1  brad 		.rate = "10.0mps",
    299  1.1  brad 		.sdelay = 50,
    300  1.1  brad 		.cmd = SHT3X_FOUR_MPS_LOW,
    301  1.1  brad 	},
    302  1.1  brad 	{
    303  1.1  brad 		.repeatability = "high",
    304  1.1  brad 		.rate = "ART",
    305  1.1  brad 		.sdelay = 100,
    306  1.1  brad 		.cmd = SHT3X_ART_ENABLE,
    307  1.1  brad 	},
    308  1.1  brad 	{
    309  1.1  brad 		.repeatability = "medium",
    310  1.1  brad 		.rate = "ART",
    311  1.1  brad 		.sdelay = 100,
    312  1.1  brad 		.cmd = SHT3X_ART_ENABLE,
    313  1.1  brad 	},
    314  1.1  brad 	{
    315  1.1  brad 		.repeatability = "low",
    316  1.1  brad 		.rate = "ART",
    317  1.1  brad 		.sdelay = 100,
    318  1.1  brad 		.cmd = SHT3X_ART_ENABLE,
    319  1.1  brad 	}
    320  1.1  brad };
    321  1.1  brad 
    322  1.1  brad static const char sht3x_rate_names[] =
    323  1.1  brad     "0.5mps, 1.0mps, 2.0mps, 4.0mps, 10.0mps, ART";
    324  1.1  brad 
    325  1.1  brad static const char sht3x_mode_names[] =
    326  1.1  brad     "single-shot, periodic";
    327  1.1  brad 
    328  1.1  brad static const char sht3x_repeatability_names[] =
    329  1.1  brad     "high, medium, low";
    330  1.1  brad 
    331  1.1  brad static int
    332  1.1  brad sht3x_take_break(void *aux, bool have_bus)
    333  1.1  brad {
    334  1.1  brad 	struct sht3x_sc *sc;
    335  1.1  brad 	sc = aux;
    336  1.1  brad 	int error = 0;
    337  1.1  brad 
    338  1.1  brad 	if (! have_bus) {
    339  1.1  brad 		error = iic_acquire_bus(sc->sc_tag, 0);
    340  1.1  brad 		if (error) {
    341  1.1  brad 			DPRINTF(sc, 2, ("%s: Could not acquire iic bus for breaking %d\n",
    342  1.1  brad 			    device_xname(sc->sc_dev), error));
    343  1.1  brad 			goto out;
    344  1.1  brad 		}
    345  1.1  brad 	}
    346  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_BREAK, NULL, 0);
    347  1.1  brad 	if (error) {
    348  1.1  brad 		DPRINTF(sc, 2, ("%s: Error breaking: %d\n",
    349  1.1  brad 		    device_xname(sc->sc_dev), error));
    350  1.1  brad 	}
    351  1.1  brad  out:
    352  1.1  brad 	if (! have_bus) {
    353  1.1  brad 		iic_release_bus(sc->sc_tag, 0);
    354  1.1  brad 	}
    355  1.1  brad 
    356  1.1  brad 	sc->sc_isperiodic = false;
    357  1.1  brad 	strlcpy(sc->sc_mode,"single-shot",SHT3X_MODE_NAME);
    358  1.1  brad 
    359  1.1  brad 	return error;
    360  1.1  brad }
    361  1.1  brad 
    362  1.1  brad static int
    363  1.1  brad sht3x_get_status_register(void *aux, uint16_t *reg, bool have_bus)
    364  1.1  brad {
    365  1.1  brad 	struct sht3x_sc *sc;
    366  1.1  brad 	sc = aux;
    367  1.1  brad 	uint8_t buf[3];
    368  1.1  brad 	int error = 0;
    369  1.1  brad 
    370  1.1  brad 	if (! have_bus) {
    371  1.1  brad 		error = iic_acquire_bus(sc->sc_tag, 0);
    372  1.1  brad 		if (error) {
    373  1.1  brad 			DPRINTF(sc, 2, ("%s: Could not acquire iic bus for getting status %d\n",
    374  1.1  brad 			    device_xname(sc->sc_dev), error));
    375  1.1  brad 			goto out;
    376  1.1  brad 		}
    377  1.1  brad 	}
    378  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_GET_STATUS_REGISTER, buf, 3);
    379  1.1  brad 	if (error) {
    380  1.1  brad 		DPRINTF(sc, 2, ("%s: Error getting status: %d\n",
    381  1.1  brad 		    device_xname(sc->sc_dev), error));
    382  1.1  brad 	}
    383  1.1  brad  out:
    384  1.1  brad 	if (! have_bus) {
    385  1.1  brad 		iic_release_bus(sc->sc_tag, 0);
    386  1.1  brad 	}
    387  1.1  brad 
    388  1.1  brad 	if (!error) {
    389  1.1  brad 		uint8_t c;
    390  1.1  brad 
    391  1.1  brad 		c = sht3x_crc(&buf[0],2);
    392  1.1  brad 		if (c == buf[2]) {
    393  1.1  brad 			*reg = buf[0] << 8 | buf[1];
    394  1.1  brad 		} else {
    395  1.1  brad 			error = EINVAL;
    396  1.1  brad 		}
    397  1.1  brad 	}
    398  1.1  brad 
    399  1.1  brad 	return error;
    400  1.1  brad }
    401  1.1  brad 
    402  1.1  brad static int
    403  1.1  brad sht3x_clear_status_register(void *aux, bool have_bus)
    404  1.1  brad {
    405  1.1  brad 	struct sht3x_sc *sc;
    406  1.1  brad 	sc = aux;
    407  1.1  brad 	int error = 0;
    408  1.1  brad 
    409  1.1  brad 	if (! have_bus) {
    410  1.1  brad 		error = iic_acquire_bus(sc->sc_tag, 0);
    411  1.1  brad 		if (error) {
    412  1.1  brad 			DPRINTF(sc, 2, ("%s: Could not acquire iic bus for clearing status %d\n",
    413  1.1  brad 			    device_xname(sc->sc_dev), error));
    414  1.1  brad 			goto out;
    415  1.1  brad 		}
    416  1.1  brad 	}
    417  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_CLEAR_STATUS_REGISTER, NULL, 0);
    418  1.1  brad 	if (error) {
    419  1.1  brad 		DPRINTF(sc, 2, ("%s: Error clear status register: %d\n",
    420  1.1  brad 		    device_xname(sc->sc_dev), error));
    421  1.1  brad 	}
    422  1.1  brad  out:
    423  1.1  brad 	if (! have_bus) {
    424  1.1  brad 		iic_release_bus(sc->sc_tag, 0);
    425  1.1  brad 	}
    426  1.1  brad 
    427  1.1  brad 	return error;
    428  1.1  brad }
    429  1.1  brad 
    430  1.1  brad void
    431  1.1  brad sht3x_thread(void *aux)
    432  1.1  brad {
    433  1.1  brad 	struct sht3x_sc *sc = aux;
    434  1.1  brad 	int error, rv;
    435  1.1  brad 	int sdelay = 100;
    436  1.1  brad 
    437  1.1  brad 	mutex_enter(&sc->sc_threadmutex);
    438  1.1  brad 
    439  1.1  brad 	while (!sc->sc_stopping && !sc->sc_dying) {
    440  1.1  brad 		if (sc->sc_initperiodic) {
    441  1.1  brad 			error = sht3x_init_periodic_measurement(sc,&sdelay);
    442  1.1  brad 			if (error) {
    443  1.1  brad 				DPRINTF(sc, 2, ("%s: Error initing periodic measurement "
    444  1.1  brad 				    "in thread: %d\n", device_xname(sc->sc_dev), error));
    445  1.1  brad 			}
    446  1.1  brad 			sc->sc_initperiodic = false;
    447  1.1  brad 		}
    448  1.1  brad 		rv = cv_timedwait(&sc->sc_condvar, &sc->sc_threadmutex,
    449  1.1  brad 		    mstohz(sdelay));
    450  1.1  brad 		if (rv == EWOULDBLOCK && !sc->sc_stopping && !sc->sc_initperiodic && !sc->sc_dying) {
    451  1.1  brad 			sht3x_take_periodic_measurement(sc);
    452  1.1  brad 		}
    453  1.1  brad 	}
    454  1.1  brad 	mutex_exit(&sc->sc_threadmutex);
    455  1.1  brad 	kthread_exit(0);
    456  1.1  brad }
    457  1.1  brad 
    458  1.1  brad int
    459  1.1  brad sht3x_init_periodic_measurement(void *aux, int *sdelay)
    460  1.1  brad {
    461  1.1  brad 	struct sht3x_sc *sc;
    462  1.1  brad 	sc = aux;
    463  1.1  brad 	int i,error = 0;
    464  1.1  brad 	uint16_t r = 0;
    465  1.1  brad 
    466  1.1  brad 	for (i = 0; i < __arraycount(sht3x_periodic_rate); i++) {
    467  1.1  brad 		if (strncmp(sc->sc_repeatability,sht3x_periodic_rate[i].repeatability,SHT3X_REP_NAME) == 0 &&
    468  1.1  brad 		    strncmp(sc->sc_periodic_rate, sht3x_periodic_rate[i].rate,SHT3X_RATE_NAME) == 0) {
    469  1.1  brad 			r = sht3x_periodic_rate[i].cmd;
    470  1.1  brad 			*sdelay = sht3x_periodic_rate[i].sdelay;
    471  1.1  brad 			break;
    472  1.1  brad 		}
    473  1.1  brad 	}
    474  1.1  brad 
    475  1.1  brad 	if (i == __arraycount(sht3x_periodic_rate)) {
    476  1.1  brad 		error = 1;
    477  1.1  brad 		*sdelay = 100;
    478  1.1  brad 	}
    479  1.1  brad 
    480  1.1  brad 	DPRINTF(sc, 2, ("%s: Would init with: %x\n",
    481  1.1  brad 	    device_xname(sc->sc_dev), r));
    482  1.1  brad 
    483  1.1  brad 	if (error == 0) {
    484  1.1  brad 		mutex_enter(&sc->sc_mutex);
    485  1.1  brad 
    486  1.1  brad 		error = iic_acquire_bus(sc->sc_tag, 0);
    487  1.1  brad 		if (error) {
    488  1.1  brad 			DPRINTF(sc, 2, ("%s: Could not acquire iic bus for initing: "
    489  1.1  brad 			    " %d\n", device_xname(sc->sc_dev), error));
    490  1.1  brad 		} else {
    491  1.1  brad 			error = sht3x_take_break(sc,true);
    492  1.1  brad 			if (error) {
    493  1.1  brad 				DPRINTF(sc, 2, ("%s: Could not acquire iic bus for initing: "
    494  1.1  brad 				    " %d\n", device_xname(sc->sc_dev), error));
    495  1.1  brad 			}
    496  1.1  brad 
    497  1.1  brad 			error = sht3x_cmdr(sc, r, NULL, 0);
    498  1.1  brad 			if (error) {
    499  1.1  brad 				DPRINTF(sc, 2, ("%s: Error sending periodic measurement command: %d\n",
    500  1.1  brad 				    device_xname(sc->sc_dev), error));
    501  1.1  brad 			}
    502  1.1  brad 			iic_release_bus(sc->sc_tag, 0);
    503  1.1  brad 			sc->sc_isperiodic = true;
    504  1.1  brad 			strlcpy(sc->sc_mode,"periodic",SHT3X_MODE_NAME);
    505  1.1  brad 		}
    506  1.1  brad 		mutex_exit(&sc->sc_mutex);
    507  1.1  brad 	}
    508  1.1  brad 
    509  1.1  brad 	return error;
    510  1.1  brad }
    511  1.1  brad 
    512  1.1  brad static void
    513  1.1  brad sht3x_take_periodic_measurement(void *aux)
    514  1.1  brad {
    515  1.1  brad 	struct sht3x_sc *sc;
    516  1.1  brad 	sc = aux;
    517  1.1  brad 	int error = 0, data_error = 0;
    518  1.1  brad 	uint8_t rawbuf[6];
    519  1.1  brad 	struct sht3x_read_q *pp;
    520  1.1  brad 
    521  1.1  brad 	mutex_enter(&sc->sc_mutex);
    522  1.1  brad 	error = iic_acquire_bus(sc->sc_tag, 0);
    523  1.1  brad 	if (error) {
    524  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not acquire iic bus for getting "
    525  1.1  brad 		    "periodic data: %d\n", device_xname(sc->sc_dev), error));
    526  1.1  brad 	} else {
    527  1.1  brad 		uint16_t status_reg;
    528  1.1  brad 
    529  1.1  brad 		error = sht3x_get_status_register(sc, &status_reg, true);
    530  1.1  brad 		if (error) {
    531  1.1  brad 			DPRINTF(sc, 2, ("%s: Error getting status register periodic: %d\n",
    532  1.1  brad 			    device_xname(sc->sc_dev), error));
    533  1.1  brad 		} else {
    534  1.1  brad 			if (status_reg & SHT3X_RESET_DETECTED) {
    535  1.1  brad 				aprint_error_dev(sc->sc_dev, "Reset detected in periodic mode.  Heater may have been reset.\n");
    536  1.1  brad 				delay(3000);
    537  1.1  brad 				sht3x_take_break(sc,true);
    538  1.1  brad 				sht3x_clear_status_register(sc, true);
    539  1.1  brad 				sc->sc_heateron = status_reg & SHT3X_HEATER_STATUS;
    540  1.1  brad 				sc->sc_initperiodic = true;
    541  1.1  brad 			} else {
    542  1.1  brad 				data_error = sht3x_cmdr(sc, SHT3X_PERIODIC_FETCH_DATA, rawbuf, 6);
    543  1.1  brad 				/* EIO is actually expected if the poll interval is faster
    544  1.1  brad 				 * than the rate that the sensor is set to.  Unfortunally,
    545  1.1  brad 				 * this will also mess with the ability to detect an actual problem
    546  1.1  brad 				 * with the sensor in periodic mode, so we do the best we can here.
    547  1.1  brad 				 */
    548  1.1  brad 				if (data_error && data_error != EIO) {
    549  1.1  brad 					DPRINTF(sc, 2, ("%s: Error sending periodic fetch command: %d\n",
    550  1.1  brad 					    device_xname(sc->sc_dev), data_error));
    551  1.1  brad 				}
    552  1.1  brad 			}
    553  1.1  brad 		}
    554  1.1  brad 		iic_release_bus(sc->sc_tag, 0);
    555  1.1  brad 		/* If there was no errors from anything then the data should be
    556  1.1  brad 		 * valid.
    557  1.1  brad 		 */
    558  1.1  brad 		if (!data_error && !error) {
    559  1.1  brad 			DPRINTF(sc, 2, ("%s: Raw periodic: %x%x - %x -- %x%x - %x\n",
    560  1.1  brad 			    device_xname(sc->sc_dev), rawbuf[0], rawbuf[1], rawbuf[2],
    561  1.1  brad 			    rawbuf[3], rawbuf[4], rawbuf[5]));
    562  1.1  brad 			memcpy(sc->sc_pbuffer,rawbuf,6);
    563  1.1  brad 
    564  1.1  brad 			if (sc->sc_opened) {
    565  1.1  brad 				mutex_enter(&sc->sc_read_mutex);
    566  1.1  brad 				pp = pool_cache_get(sc->sc_readpool,PR_NOWAIT);
    567  1.1  brad 				if (pp != NULL) {
    568  1.1  brad 					memcpy(pp->measurement,rawbuf,6);
    569  1.1  brad 					DPRINTF(sc, 4, ("%s: Queue insert\n",device_xname(sc->sc_dev)));
    570  1.1  brad 					SIMPLEQ_INSERT_HEAD(&sc->sc_read_queue,pp,read_q);
    571  1.1  brad 				} else {
    572  1.1  brad 					aprint_error("Could not allocate memory for pool read\n");
    573  1.1  brad 				}
    574  1.1  brad 				cv_signal(&sc->sc_condreadready);
    575  1.1  brad 				mutex_exit(&sc->sc_read_mutex);
    576  1.1  brad 			}
    577  1.1  brad 
    578  1.1  brad 		} else {
    579  1.1  brad 			/* We are only going to worry about errors when it was not related
    580  1.1  brad 			 * to actually getting data.  That is a likely indicator of a problem
    581  1.1  brad 			 * with the sensor.
    582  1.1  brad 			 */
    583  1.1  brad 			if (error) {
    584  1.1  brad 				DPRINTF(sc, 2, ("%s: Raw periodic with error: %x%x - %x -- %x%x - %x -- %d\n",
    585  1.1  brad 				    device_xname(sc->sc_dev), rawbuf[0], rawbuf[1], rawbuf[2],
    586  1.1  brad 				    rawbuf[3], rawbuf[4], rawbuf[5], error));
    587  1.1  brad 				uint8_t bad[6] = "dedbef";
    588  1.1  brad 				memcpy(sc->sc_pbuffer, bad, 6);
    589  1.1  brad 			}
    590  1.1  brad 		}
    591  1.1  brad 
    592  1.1  brad 	}
    593  1.1  brad 	mutex_exit(&sc->sc_mutex);
    594  1.1  brad }
    595  1.1  brad 
    596  1.1  brad static void
    597  1.1  brad sht3x_stop_thread(void *aux)
    598  1.1  brad {
    599  1.1  brad 	struct sht3x_sc *sc;
    600  1.1  brad 	sc = aux;
    601  1.1  brad 
    602  1.1  brad 	if (!sc->sc_isperiodic) {
    603  1.1  brad 		return;
    604  1.1  brad 	}
    605  1.1  brad 
    606  1.1  brad 	mutex_enter(&sc->sc_threadmutex);
    607  1.1  brad 	sc->sc_stopping = true;
    608  1.1  brad 	cv_signal(&sc->sc_condvar);
    609  1.1  brad 	mutex_exit(&sc->sc_threadmutex);
    610  1.1  brad 
    611  1.1  brad 	/* wait for the thread to exit */
    612  1.1  brad 	kthread_join(sc->sc_thread);
    613  1.1  brad 
    614  1.1  brad 	mutex_enter(&sc->sc_mutex);
    615  1.1  brad 	sht3x_take_break(sc,false);
    616  1.1  brad 	mutex_exit(&sc->sc_mutex);
    617  1.1  brad }
    618  1.1  brad 
    619  1.1  brad static void
    620  1.1  brad sht3x_start_thread(void *aux)
    621  1.1  brad {
    622  1.1  brad 	struct sht3x_sc *sc;
    623  1.1  brad 	sc = aux;
    624  1.1  brad 	int error;
    625  1.1  brad 
    626  1.1  brad 	error = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL,
    627  1.1  brad 	    sht3x_thread, sc, &sc->sc_thread, "%s", device_xname(sc->sc_dev));
    628  1.1  brad 	if (error) {
    629  1.1  brad 		DPRINTF(sc, 2, ("%s: Unable to create measurement thread: %d\n",
    630  1.1  brad 		    device_xname(sc->sc_dev), error));
    631  1.1  brad 	}
    632  1.1  brad }
    633  1.1  brad 
    634  1.1  brad int
    635  1.1  brad sht3x_verify_sysctl(SYSCTLFN_ARGS)
    636  1.1  brad {
    637  1.1  brad 	int error, t;
    638  1.1  brad 	struct sysctlnode node;
    639  1.1  brad 
    640  1.1  brad 	node = *rnode;
    641  1.1  brad 	t = *(int *)rnode->sysctl_data;
    642  1.1  brad 	node.sysctl_data = &t;
    643  1.1  brad 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    644  1.1  brad 	if (error || newp == NULL)
    645  1.1  brad 		return error;
    646  1.1  brad 
    647  1.1  brad 	if (t < 0)
    648  1.1  brad 		return EINVAL;
    649  1.1  brad 
    650  1.1  brad 	*(int *)rnode->sysctl_data = t;
    651  1.1  brad 
    652  1.1  brad 	return 0;
    653  1.1  brad }
    654  1.1  brad 
    655  1.1  brad int
    656  1.1  brad sht3x_verify_sysctl_heateron(SYSCTLFN_ARGS)
    657  1.1  brad {
    658  1.1  brad 	int 		error;
    659  1.1  brad 	bool 		t;
    660  1.1  brad 	struct sht3x_sc *sc;
    661  1.1  brad 	struct sysctlnode node;
    662  1.1  brad 
    663  1.1  brad 	node = *rnode;
    664  1.1  brad 	sc = node.sysctl_data;
    665  1.1  brad 	t = sc->sc_heateron;
    666  1.1  brad 	node.sysctl_data = &t;
    667  1.1  brad 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    668  1.1  brad 	if (error || newp == NULL)
    669  1.1  brad 		return error;
    670  1.1  brad 
    671  1.1  brad 	sc->sc_heateron = t;
    672  1.1  brad 	error = sht3x_set_heater(sc);
    673  1.1  brad 
    674  1.1  brad 	return error;
    675  1.1  brad }
    676  1.1  brad 
    677  1.1  brad static int
    678  1.1  brad sht3x_set_heater(struct sht3x_sc *sc)
    679  1.1  brad {
    680  1.1  brad 	int error = 0;
    681  1.1  brad 	uint16_t cmd;
    682  1.1  brad 
    683  1.1  brad 	mutex_enter(&sc->sc_mutex);
    684  1.1  brad 	error = iic_acquire_bus(sc->sc_tag, 0);
    685  1.1  brad 	if (error) {
    686  1.1  brad 		DPRINTF(sc, 2, ("%s:%s: Failed to acquire bus: %d\n",
    687  1.1  brad 		    device_xname(sc->sc_dev), __func__, error));
    688  1.1  brad 		return error;
    689  1.1  brad 	}
    690  1.1  brad 
    691  1.1  brad 	if (sc->sc_heateron) {
    692  1.1  brad 		cmd = SHT3X_HEATER_ENABLE;
    693  1.1  brad 	} else {
    694  1.1  brad 		cmd = SHT3X_HEATER_DISABLE;
    695  1.1  brad 	}
    696  1.1  brad 
    697  1.1  brad 	error = sht3x_cmdr(sc, cmd, NULL, 0);
    698  1.1  brad 
    699  1.1  brad 	iic_release_bus(sc->sc_tag,0);
    700  1.1  brad 	mutex_exit(&sc->sc_mutex);
    701  1.1  brad 
    702  1.1  brad 	return error;
    703  1.1  brad }
    704  1.1  brad 
    705  1.1  brad int
    706  1.1  brad sht3x_verify_sysctl_modes(SYSCTLFN_ARGS)
    707  1.1  brad {
    708  1.1  brad 	char buf[SHT3X_MODE_NAME];
    709  1.1  brad 	struct sht3x_sc *sc;
    710  1.1  brad 	struct sysctlnode node;
    711  1.1  brad 	int error = 0;
    712  1.1  brad 	bool is_ss = false;
    713  1.1  brad 	bool is_periodic = false;
    714  1.1  brad 
    715  1.1  brad 	node = *rnode;
    716  1.1  brad 	sc = node.sysctl_data;
    717  1.1  brad 	(void) memcpy(buf, sc->sc_mode, SHT3X_MODE_NAME);
    718  1.1  brad 	node.sysctl_data = buf;
    719  1.1  brad 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    720  1.1  brad 	if (error || newp == NULL)
    721  1.1  brad 		return error;
    722  1.1  brad 
    723  1.1  brad 	if (sc->sc_opened) {
    724  1.1  brad 		return EINVAL;
    725  1.1  brad 	}
    726  1.1  brad 
    727  1.1  brad 	is_ss = (strncmp(node.sysctl_data, "single-shot", SHT3X_MODE_NAME) == 0);
    728  1.1  brad 	is_periodic = (strncmp(node.sysctl_data, "periodic", SHT3X_MODE_NAME) == 0);
    729  1.1  brad 
    730  1.1  brad 	if (is_ss || is_periodic) {
    731  1.1  brad 		(void) memcpy(sc->sc_mode, node.sysctl_data, SHT3X_MODE_NAME);
    732  1.1  brad 	} else {
    733  1.1  brad 		error = EINVAL;
    734  1.1  brad 	}
    735  1.1  brad 
    736  1.1  brad 	if (error == 0) {
    737  1.1  brad 		if (is_ss) {
    738  1.1  brad 			sht3x_stop_thread(sc);
    739  1.1  brad 			sc->sc_stopping = false;
    740  1.1  brad 			sc->sc_initperiodic = false;
    741  1.1  brad 			sc->sc_isperiodic = false;
    742  1.1  brad 		}
    743  1.1  brad 		if (is_periodic) {
    744  1.1  brad 			sc->sc_stopping = false;
    745  1.1  brad 			sc->sc_initperiodic = true;
    746  1.1  brad 			sc->sc_isperiodic = true;
    747  1.1  brad 			sht3x_start_thread(sc);
    748  1.1  brad 		}
    749  1.1  brad 	}
    750  1.1  brad 
    751  1.1  brad 	return error;
    752  1.1  brad }
    753  1.1  brad 
    754  1.1  brad int
    755  1.1  brad sht3x_verify_sysctl_repeatability(SYSCTLFN_ARGS)
    756  1.1  brad {
    757  1.1  brad 	char buf[SHT3X_REP_NAME];
    758  1.1  brad 	struct sht3x_sc *sc;
    759  1.1  brad 	struct sysctlnode node;
    760  1.1  brad 	int error = 0;
    761  1.1  brad 	size_t i;
    762  1.1  brad 
    763  1.1  brad 	node = *rnode;
    764  1.1  brad 	sc = node.sysctl_data;
    765  1.1  brad 	(void) memcpy(buf, sc->sc_repeatability, SHT3X_REP_NAME);
    766  1.1  brad 	node.sysctl_data = buf;
    767  1.1  brad 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    768  1.1  brad 	if (error || newp == NULL)
    769  1.1  brad 		return error;
    770  1.1  brad 
    771  1.1  brad 	for (i = 0; i < __arraycount(sht3x_repeatability_ss); i++) {
    772  1.1  brad 		if (strncmp(node.sysctl_data, sht3x_repeatability_ss[i].text,
    773  1.1  brad 		    SHT3X_REP_NAME) == 0) {
    774  1.1  brad 			break;
    775  1.1  brad 		}
    776  1.1  brad 	}
    777  1.1  brad 
    778  1.1  brad 	if (i == __arraycount(sht3x_repeatability_ss))
    779  1.1  brad 		return EINVAL;
    780  1.1  brad 	(void) memcpy(sc->sc_repeatability, node.sysctl_data, SHT3X_REP_NAME);
    781  1.1  brad 
    782  1.1  brad 	if (sc->sc_isperiodic) {
    783  1.1  brad 		sc->sc_initperiodic = true;
    784  1.1  brad 	}
    785  1.1  brad 
    786  1.1  brad 	return error;
    787  1.1  brad }
    788  1.1  brad 
    789  1.1  brad int
    790  1.1  brad sht3x_verify_sysctl_rate(SYSCTLFN_ARGS)
    791  1.1  brad {
    792  1.1  brad 	char buf[SHT3X_RATE_NAME];
    793  1.1  brad 	struct sht3x_sc *sc;
    794  1.1  brad 	struct sysctlnode node;
    795  1.1  brad 	int error = 0;
    796  1.1  brad 	size_t i;
    797  1.1  brad 
    798  1.1  brad 	node = *rnode;
    799  1.1  brad 	sc = node.sysctl_data;
    800  1.1  brad 	(void) memcpy(buf, sc->sc_periodic_rate, SHT3X_RATE_NAME);
    801  1.1  brad 	node.sysctl_data = buf;
    802  1.1  brad 	error = sysctl_lookup(SYSCTLFN_CALL(&node));
    803  1.1  brad 	if (error || newp == NULL)
    804  1.1  brad 		return error;
    805  1.1  brad 
    806  1.1  brad 	for (i = 0; i < __arraycount(sht3x_periodic_rate); i++) {
    807  1.1  brad 		if (strncmp(node.sysctl_data, sht3x_periodic_rate[i].rate,
    808  1.1  brad 		    SHT3X_RATE_NAME) == 0) {
    809  1.1  brad 			break;
    810  1.1  brad 		}
    811  1.1  brad 	}
    812  1.1  brad 
    813  1.1  brad 	if (i == __arraycount(sht3x_periodic_rate))
    814  1.1  brad 		return EINVAL;
    815  1.1  brad 	(void) memcpy(sc->sc_periodic_rate, node.sysctl_data, SHT3X_RATE_NAME);
    816  1.1  brad 
    817  1.1  brad 	if (sc->sc_isperiodic) {
    818  1.1  brad 		sc->sc_initperiodic = true;
    819  1.1  brad 	}
    820  1.1  brad 
    821  1.1  brad 	return error;
    822  1.1  brad }
    823  1.1  brad 
    824  1.1  brad static int
    825  1.1  brad sht3x_cmddelay(uint16_t cmd)
    826  1.1  brad {
    827  1.1  brad 	int r = -2;
    828  1.1  brad 
    829  1.1  brad 	for(int i = 0;i < __arraycount(sht3x_timings);i++) {
    830  1.1  brad 		if (cmd == sht3x_timings[i].cmd) {
    831  1.1  brad 			r = sht3x_timings[i].typicaldelay;
    832  1.1  brad 			break;
    833  1.1  brad 		}
    834  1.1  brad 	}
    835  1.1  brad 
    836  1.1  brad 	if (r == -2) {
    837  1.1  brad 		r = -1;
    838  1.1  brad 	}
    839  1.1  brad 
    840  1.1  brad 	return r;
    841  1.1  brad }
    842  1.1  brad 
    843  1.1  brad static int
    844  1.1  brad sht3x_cmd(i2c_tag_t tag, i2c_addr_t addr, uint16_t *cmd,
    845  1.1  brad     uint8_t clen, uint8_t *buf, size_t blen, int readattempts)
    846  1.1  brad {
    847  1.1  brad 	int error;
    848  1.1  brad 	int cmddelay;
    849  1.1  brad 	uint8_t cmd8[2];
    850  1.1  brad 
    851  1.1  brad 	/* All commands are two bytes and must be in a proper order */
    852  1.1  brad 	KASSERT(clen == 2);
    853  1.1  brad 
    854  1.1  brad 	cmd8[0] = cmd[0] >> 8;
    855  1.1  brad 	cmd8[1] = cmd[0] & 0x00ff;
    856  1.1  brad 
    857  1.1  brad 	error = iic_exec(tag,I2C_OP_WRITE_WITH_STOP,addr,&cmd8[0],clen,NULL,0,0);
    858  1.1  brad 
    859  1.1  brad 	if (error == 0) {
    860  1.1  brad 		cmddelay = sht3x_cmddelay(cmd[0]);
    861  1.1  brad 		if (cmddelay != -1) {
    862  1.1  brad 			delay(cmddelay);
    863  1.1  brad 		}
    864  1.1  brad 
    865  1.1  brad 		/* Not all commands return anything  */
    866  1.1  brad 		if (blen > 0) {
    867  1.1  brad 			for (int aint = 0; aint < readattempts; aint++) {
    868  1.1  brad 				error = iic_exec(tag,I2C_OP_READ_WITH_STOP,addr,NULL,0,buf,blen,0);
    869  1.1  brad 				if (error == 0)
    870  1.1  brad 					break;
    871  1.1  brad 				delay(1000);
    872  1.1  brad 			}
    873  1.1  brad 		}
    874  1.1  brad 	}
    875  1.1  brad 
    876  1.1  brad 	return error;
    877  1.1  brad }
    878  1.1  brad 
    879  1.1  brad static int
    880  1.1  brad sht3x_cmdr(struct sht3x_sc *sc, uint16_t cmd, uint8_t *buf, size_t blen)
    881  1.1  brad {
    882  1.1  brad 	return sht3x_cmd(sc->sc_tag, sc->sc_addr, &cmd, 2, buf, blen, sc->sc_readattempts);
    883  1.1  brad }
    884  1.1  brad 
    885  1.1  brad static	uint8_t
    886  1.1  brad sht3x_crc(uint8_t * data, size_t size)
    887  1.1  brad {
    888  1.1  brad 	uint8_t crc = 0xFF;
    889  1.1  brad 
    890  1.1  brad 	for (size_t i = 0; i < size; i++) {
    891  1.1  brad 		crc ^= data[i];
    892  1.1  brad 		for (size_t j = 8; j > 0; j--) {
    893  1.1  brad 			if (crc & 0x80)
    894  1.1  brad 				crc = (crc << 1) ^ 0x31;
    895  1.1  brad 			else
    896  1.1  brad 				crc <<= 1;
    897  1.1  brad 		}
    898  1.1  brad 	}
    899  1.1  brad 	return crc;
    900  1.1  brad }
    901  1.1  brad 
    902  1.1  brad static int
    903  1.1  brad sht3x_poke(i2c_tag_t tag, i2c_addr_t addr, bool matchdebug)
    904  1.1  brad {
    905  1.1  brad 	uint16_t reg = SHT3X_GET_STATUS_REGISTER;
    906  1.1  brad 	uint8_t buf[3];
    907  1.1  brad 	int error;
    908  1.1  brad 
    909  1.1  brad 	error = sht3x_cmd(tag, addr, &reg, 2, buf, 3, 10);
    910  1.1  brad 	if (matchdebug) {
    911  1.1  brad 		printf("poke X 1: %d\n", error);
    912  1.1  brad 	}
    913  1.1  brad 	return error;
    914  1.1  brad }
    915  1.1  brad 
    916  1.1  brad static int
    917  1.1  brad sht3x_sysctl_init(struct sht3x_sc *sc)
    918  1.1  brad {
    919  1.1  brad 	int error;
    920  1.1  brad 	const struct sysctlnode *cnode;
    921  1.1  brad 	int sysctlroot_num;
    922  1.1  brad 
    923  1.1  brad 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
    924  1.1  brad 	    0, CTLTYPE_NODE, device_xname(sc->sc_dev),
    925  1.1  brad 	    SYSCTL_DESCR("sht3x controls"), NULL, 0, NULL, 0, CTL_HW,
    926  1.1  brad 	    CTL_CREATE, CTL_EOL)) != 0)
    927  1.1  brad 		return error;
    928  1.1  brad 
    929  1.1  brad 	sysctlroot_num = cnode->sysctl_num;
    930  1.1  brad 
    931  1.1  brad #ifdef SHT3X_DEBUG
    932  1.1  brad 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
    933  1.1  brad 	    CTLFLAG_READWRITE, CTLTYPE_INT, "debug",
    934  1.1  brad 	    SYSCTL_DESCR("Debug level"), sht3x_verify_sysctl, 0,
    935  1.1  brad 	    &sc->sc_sht3xdebug, 0, CTL_HW, sysctlroot_num, CTL_CREATE,
    936  1.1  brad 	    CTL_EOL)) != 0)
    937  1.1  brad 		return error;
    938  1.1  brad 
    939  1.1  brad #endif
    940  1.1  brad 
    941  1.1  brad 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
    942  1.1  brad 	    CTLFLAG_READWRITE, CTLTYPE_INT, "readattempts",
    943  1.1  brad 	    SYSCTL_DESCR("The number of times to attempt to read the values"),
    944  1.1  brad 	    sht3x_verify_sysctl, 0, &sc->sc_readattempts, 0, CTL_HW,
    945  1.1  brad 	    sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
    946  1.1  brad 		return error;
    947  1.1  brad 
    948  1.1  brad 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
    949  1.1  brad 	    CTLFLAG_READONLY, CTLTYPE_STRING, "modes",
    950  1.1  brad 	    SYSCTL_DESCR("Valid modes"), 0, 0,
    951  1.1  brad 	    __UNCONST(sht3x_mode_names),
    952  1.1  brad 	    sizeof(sht3x_mode_names) + 1,
    953  1.1  brad 	    CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
    954  1.1  brad 		return error;
    955  1.1  brad 
    956  1.1  brad 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
    957  1.1  brad 	    CTLFLAG_READWRITE, CTLTYPE_STRING, "mode",
    958  1.1  brad 	    SYSCTL_DESCR("Mode for measurement collection"),
    959  1.1  brad 	    sht3x_verify_sysctl_modes, 0, (void *) sc,
    960  1.1  brad 	    SHT3X_MODE_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
    961  1.1  brad 		return error;
    962  1.1  brad 
    963  1.1  brad 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
    964  1.1  brad 	    CTLFLAG_READONLY, CTLTYPE_STRING, "repeatabilities",
    965  1.1  brad 	    SYSCTL_DESCR("Valid repeatability values"), 0, 0,
    966  1.1  brad 	    __UNCONST(sht3x_repeatability_names),
    967  1.1  brad 	    sizeof(sht3x_repeatability_names) + 1,
    968  1.1  brad 	    CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
    969  1.1  brad 		return error;
    970  1.1  brad 
    971  1.1  brad 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
    972  1.1  brad 	    CTLFLAG_READWRITE, CTLTYPE_STRING, "repeatability",
    973  1.1  brad 	    SYSCTL_DESCR("Repeatability of RH and Temp"),
    974  1.1  brad 	    sht3x_verify_sysctl_repeatability, 0, (void *) sc,
    975  1.1  brad 	    SHT3X_REP_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
    976  1.1  brad 		return error;
    977  1.1  brad 
    978  1.1  brad 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
    979  1.1  brad 	    CTLFLAG_READONLY, CTLTYPE_STRING, "rates",
    980  1.1  brad 	    SYSCTL_DESCR("Valid peridoic rates"), 0, 0,
    981  1.1  brad 	    __UNCONST(sht3x_rate_names),
    982  1.1  brad 	    sizeof(sht3x_rate_names) + 1,
    983  1.1  brad 	    CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
    984  1.1  brad 		return error;
    985  1.1  brad 
    986  1.1  brad 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
    987  1.1  brad 	    CTLFLAG_READWRITE, CTLTYPE_STRING, "rate",
    988  1.1  brad 	    SYSCTL_DESCR("Rate for periodic measurements"),
    989  1.1  brad 	    sht3x_verify_sysctl_rate, 0, (void *) sc,
    990  1.1  brad 	    SHT3X_RATE_NAME, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
    991  1.1  brad 		return error;
    992  1.1  brad 
    993  1.1  brad 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
    994  1.1  brad 	    CTLFLAG_READWRITE, CTLTYPE_BOOL, "ignorecrc",
    995  1.1  brad 	    SYSCTL_DESCR("Ignore the CRC byte"), NULL, 0, &sc->sc_ignorecrc,
    996  1.1  brad 	    0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
    997  1.1  brad 		return error;
    998  1.1  brad 
    999  1.1  brad 	if ((error = sysctl_createv(&sc->sc_sht3xlog, 0, NULL, &cnode,
   1000  1.1  brad 	    CTLFLAG_READWRITE, CTLTYPE_BOOL, "heateron",
   1001  1.1  brad 	    SYSCTL_DESCR("Heater on"), sht3x_verify_sysctl_heateron, 0,
   1002  1.1  brad 	    (void *)sc, 0, CTL_HW, sysctlroot_num, CTL_CREATE, CTL_EOL)) != 0)
   1003  1.1  brad 		return error;
   1004  1.1  brad 
   1005  1.1  brad 	return 0;
   1006  1.1  brad }
   1007  1.1  brad 
   1008  1.1  brad static int
   1009  1.1  brad sht3x_match(device_t parent, cfdata_t match, void *aux)
   1010  1.1  brad {
   1011  1.1  brad 	struct i2c_attach_args *ia = aux;
   1012  1.1  brad 	int error, match_result;
   1013  1.1  brad 	const bool matchdebug = false;
   1014  1.1  brad 
   1015  1.1  brad 	if (iic_use_direct_match(ia, match, NULL, &match_result))
   1016  1.1  brad 		return match_result;
   1017  1.1  brad 
   1018  1.1  brad 	if (matchdebug) {
   1019  1.1  brad 		printf("Looking at ia_addr: %x\n",ia->ia_addr);
   1020  1.1  brad 	}
   1021  1.1  brad 
   1022  1.1  brad 	/* indirect config - check for configured address */
   1023  1.1  brad 	if (ia->ia_addr == SHT3X_TYPICAL_ADDR_1 ||
   1024  1.1  brad 	    ia->ia_addr == SHT3X_TYPICAL_ADDR_2) {
   1025  1.1  brad 		/*
   1026  1.1  brad 		 * Check to see if something is really at this i2c address. This will
   1027  1.1  brad 		 * keep phantom devices from appearing
   1028  1.1  brad 		 */
   1029  1.1  brad 		if (iic_acquire_bus(ia->ia_tag, 0) != 0) {
   1030  1.1  brad 			if (matchdebug)
   1031  1.1  brad 				printf("in match acquire bus failed\n");
   1032  1.1  brad 			return 0;
   1033  1.1  brad 		}
   1034  1.1  brad 
   1035  1.1  brad 		error = sht3x_poke(ia->ia_tag, ia->ia_addr, matchdebug);
   1036  1.1  brad 		iic_release_bus(ia->ia_tag, 0);
   1037  1.1  brad 
   1038  1.1  brad 		return error == 0 ? I2C_MATCH_ADDRESS_AND_PROBE : 0;
   1039  1.1  brad 	} else {
   1040  1.1  brad 		return 0;
   1041  1.1  brad 	}
   1042  1.1  brad }
   1043  1.1  brad 
   1044  1.1  brad static void
   1045  1.1  brad sht3x_attach(device_t parent, device_t self, void *aux)
   1046  1.1  brad {
   1047  1.1  brad 	struct sht3x_sc *sc;
   1048  1.1  brad 	struct i2c_attach_args *ia;
   1049  1.1  brad 	int error, i;
   1050  1.1  brad 	int ecount = 0;
   1051  1.1  brad 	uint8_t buf[6];
   1052  1.1  brad 	uint32_t serialnumber;
   1053  1.1  brad 	uint8_t sncrcpt1, sncrcpt2;
   1054  1.1  brad 
   1055  1.1  brad 	ia = aux;
   1056  1.1  brad 	sc = device_private(self);
   1057  1.1  brad 
   1058  1.1  brad 	sc->sc_dev = self;
   1059  1.1  brad 	sc->sc_tag = ia->ia_tag;
   1060  1.1  brad 	sc->sc_addr = ia->ia_addr;
   1061  1.1  brad 	sc->sc_sht3xdebug = 0;
   1062  1.1  brad 	strlcpy(sc->sc_mode,"single-shot",SHT3X_MODE_NAME);
   1063  1.1  brad 	sc->sc_isperiodic = false;
   1064  1.1  brad 	strlcpy(sc->sc_repeatability,"high",SHT3X_REP_NAME);
   1065  1.1  brad 	strlcpy(sc->sc_periodic_rate,"1.0mps",SHT3X_RATE_NAME);
   1066  1.1  brad 	sc->sc_readattempts = 10;
   1067  1.1  brad 	sc->sc_ignorecrc = false;
   1068  1.1  brad 	sc->sc_heateron = false;
   1069  1.1  brad 	sc->sc_sme = NULL;
   1070  1.1  brad 	sc->sc_stopping = false;
   1071  1.1  brad 	sc->sc_initperiodic = false;
   1072  1.1  brad 	sc->sc_opened = false;
   1073  1.1  brad 	sc->sc_dying = false;
   1074  1.1  brad 	sc->sc_readpoolname = NULL;
   1075  1.1  brad 
   1076  1.1  brad 	aprint_normal("\n");
   1077  1.1  brad 
   1078  1.1  brad 	mutex_init(&sc->sc_dying_mutex, MUTEX_DEFAULT, IPL_NONE);
   1079  1.1  brad 	mutex_init(&sc->sc_read_mutex, MUTEX_DEFAULT, IPL_NONE);
   1080  1.1  brad 	mutex_init(&sc->sc_threadmutex, MUTEX_DEFAULT, IPL_NONE);
   1081  1.1  brad 	mutex_init(&sc->sc_mutex, MUTEX_DEFAULT, IPL_NONE);
   1082  1.1  brad 	cv_init(&sc->sc_condvar, "sht3xcv");
   1083  1.1  brad 	cv_init(&sc->sc_condreadready, "sht3xread");
   1084  1.1  brad 	cv_init(&sc->sc_cond_dying, "sht3xdie");
   1085  1.1  brad 	sc->sc_numsensors = __arraycount(sht3x_sensors);
   1086  1.1  brad 
   1087  1.1  brad 	if ((sc->sc_sme = sysmon_envsys_create()) == NULL) {
   1088  1.1  brad 		aprint_error_dev(self,
   1089  1.1  brad 		    "Unable to create sysmon structure\n");
   1090  1.1  brad 		sc->sc_sme = NULL;
   1091  1.1  brad 		return;
   1092  1.1  brad 	}
   1093  1.1  brad 	if ((error = sht3x_sysctl_init(sc)) != 0) {
   1094  1.1  brad 		aprint_error_dev(self, "Can't setup sysctl tree (%d)\n", error);
   1095  1.1  brad 		goto out;
   1096  1.1  brad 	}
   1097  1.1  brad 
   1098  1.1  brad 	sc->sc_readpoolname = kmem_asprintf("sht3xrp%d",device_unit(self));
   1099  1.1  brad 	sc->sc_readpool = pool_cache_init(sizeof(struct sht3x_read_q),0,0,0,sc->sc_readpoolname,NULL,IPL_VM,NULL,NULL,NULL);
   1100  1.1  brad 	pool_cache_sethiwat(sc->sc_readpool,100);
   1101  1.1  brad 
   1102  1.1  brad 	SIMPLEQ_INIT(&sc->sc_read_queue);
   1103  1.1  brad 
   1104  1.1  brad 	error = iic_acquire_bus(sc->sc_tag, 0);
   1105  1.1  brad 	if (error) {
   1106  1.1  brad 		aprint_error_dev(self, "Could not acquire iic bus: %d\n",
   1107  1.1  brad 		    error);
   1108  1.1  brad 		goto out;
   1109  1.1  brad 	}
   1110  1.1  brad 
   1111  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_SOFT_RESET, NULL, 0);
   1112  1.1  brad 	if (error != 0)
   1113  1.1  brad 		aprint_error_dev(self, "Reset failed: %d\n", error);
   1114  1.1  brad 
   1115  1.1  brad 	error = sht3x_clear_status_register(sc, true);
   1116  1.1  brad 	if (error) {
   1117  1.1  brad 		aprint_error_dev(self, "Failed to clear status register: %d\n",
   1118  1.1  brad 		    error);
   1119  1.1  brad 		ecount++;
   1120  1.1  brad 	}
   1121  1.1  brad 
   1122  1.1  brad 	uint16_t status_reg;
   1123  1.1  brad 	error = sht3x_get_status_register(sc, &status_reg, true);
   1124  1.1  brad 	if (error) {
   1125  1.1  brad 		aprint_error_dev(self, "Failed to read status register: %d\n",
   1126  1.1  brad 		    error);
   1127  1.1  brad 		ecount++;
   1128  1.1  brad 	}
   1129  1.1  brad 
   1130  1.1  brad 	DPRINTF(sc, 2, ("%s: read status register values: %04x\n",
   1131  1.1  brad 	    device_xname(sc->sc_dev), status_reg));
   1132  1.1  brad 
   1133  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_READ_SERIAL_NUMBER, buf, 6);
   1134  1.1  brad 	if (error) {
   1135  1.1  brad 		aprint_error_dev(self, "Failed to read serial number: %d\n",
   1136  1.1  brad 		    error);
   1137  1.1  brad 		ecount++;
   1138  1.1  brad 	}
   1139  1.1  brad 
   1140  1.1  brad 	sncrcpt1 = sht3x_crc(&buf[0],2);
   1141  1.1  brad 	sncrcpt2 = sht3x_crc(&buf[3],2);
   1142  1.1  brad 	serialnumber = (buf[0] << 24) | (buf[1] << 16) | (buf[3] << 8) | buf[4];
   1143  1.1  brad 
   1144  1.1  brad 	DPRINTF(sc, 2, ("%s: read serial number values: %02x%02x - %02x - %02x%02x - %02x -- %02x %02x\n",
   1145  1.1  brad 	    device_xname(sc->sc_dev), buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], sncrcpt1, sncrcpt2));
   1146  1.1  brad 
   1147  1.1  brad 	iic_release_bus(sc->sc_tag, 0);
   1148  1.1  brad 	if (error != 0) {
   1149  1.1  brad 		aprint_error_dev(self, "Unable to setup device\n");
   1150  1.1  brad 		goto out;
   1151  1.1  brad 	}
   1152  1.1  brad 
   1153  1.1  brad 	for (i = 0; i < sc->sc_numsensors; i++) {
   1154  1.1  brad 		strlcpy(sc->sc_sensors[i].desc, sht3x_sensors[i].desc,
   1155  1.1  brad 		    sizeof(sc->sc_sensors[i].desc));
   1156  1.1  brad 
   1157  1.1  brad 		sc->sc_sensors[i].units = sht3x_sensors[i].type;
   1158  1.1  brad 		sc->sc_sensors[i].state = ENVSYS_SINVALID;
   1159  1.1  brad #ifdef __did_not_work
   1160  1.1  brad 		sc->sc_sensors[i].flags |= ENVSYS_FMONLIMITS;
   1161  1.1  brad #endif
   1162  1.1  brad 
   1163  1.1  brad 		DPRINTF(sc, 2, ("%s: registering sensor %d (%s)\n", __func__, i,
   1164  1.1  brad 		    sc->sc_sensors[i].desc));
   1165  1.1  brad 
   1166  1.1  brad 		error = sysmon_envsys_sensor_attach(sc->sc_sme,
   1167  1.1  brad 		    &sc->sc_sensors[i]);
   1168  1.1  brad 		if (error) {
   1169  1.1  brad 			aprint_error_dev(self,
   1170  1.1  brad 			    "Unable to attach sensor %d: %d\n", i, error);
   1171  1.1  brad 			goto out;
   1172  1.1  brad 		}
   1173  1.1  brad 	}
   1174  1.1  brad 
   1175  1.1  brad 	sc->sc_sme->sme_name = device_xname(sc->sc_dev);
   1176  1.1  brad 	sc->sc_sme->sme_cookie = sc;
   1177  1.1  brad 	sc->sc_sme->sme_refresh = sht3x_refresh;
   1178  1.1  brad #ifdef __did_not_work
   1179  1.1  brad 	sc->sc_sme->sme_get_limits = sht3x_get_limits;
   1180  1.1  brad 	sc->sc_sme->sme_set_limits = sht3x_set_limits;
   1181  1.1  brad #endif
   1182  1.1  brad 
   1183  1.1  brad 	DPRINTF(sc, 2, ("sht3x_attach: registering with envsys\n"));
   1184  1.1  brad 
   1185  1.1  brad 	if (sysmon_envsys_register(sc->sc_sme)) {
   1186  1.1  brad 		aprint_error_dev(self,
   1187  1.1  brad 			"unable to register with sysmon\n");
   1188  1.1  brad 		sysmon_envsys_destroy(sc->sc_sme);
   1189  1.1  brad 		sc->sc_sme = NULL;
   1190  1.1  brad 		return;
   1191  1.1  brad 	}
   1192  1.1  brad 
   1193  1.1  brad 	/* There is no documented way to ask the chip what version it is.  This
   1194  1.1  brad 	   is likely fine as the only apparent difference is in how precise the
   1195  1.1  brad 	   measurements will be.  The actual conversation with the chip is
   1196  1.1  brad 	   identical no matter which one you are talking to.
   1197  1.1  brad 	*/
   1198  1.1  brad 
   1199  1.1  brad 	aprint_normal_dev(self, "Sensirion SHT30/SHT31/SHT35, "
   1200  1.1  brad 	    "Serial number: %x%s",
   1201  1.1  brad 	    serialnumber,
   1202  1.1  brad 	    (sncrcpt1 == buf[2] && sncrcpt2 == buf[5]) ? "\n" : " (bad crc)\n");
   1203  1.1  brad 	return;
   1204  1.1  brad out:
   1205  1.1  brad 	sysmon_envsys_destroy(sc->sc_sme);
   1206  1.1  brad 	sc->sc_sme = NULL;
   1207  1.1  brad }
   1208  1.1  brad 
   1209  1.1  brad static uint16_t
   1210  1.1  brad sht3x_compute_measure_command_ss(char *repeatability)
   1211  1.1  brad {
   1212  1.1  brad 	int i;
   1213  1.1  brad 	uint16_t r;
   1214  1.1  brad 
   1215  1.1  brad 	for (i = 0; i < __arraycount(sht3x_repeatability_ss); i++) {
   1216  1.1  brad 		if (strncmp(repeatability, sht3x_repeatability_ss[i].text,
   1217  1.1  brad 		    SHT3X_REP_NAME) == 0) {
   1218  1.1  brad 			r = sht3x_repeatability_ss[i].cmd;
   1219  1.1  brad 			break;
   1220  1.1  brad 		}
   1221  1.1  brad 	}
   1222  1.1  brad 
   1223  1.1  brad 	if (i == __arraycount(sht3x_repeatability_ss))
   1224  1.1  brad 		panic("Single-shot could not find command for repeatability: %s\n", repeatability);
   1225  1.1  brad 
   1226  1.1  brad 	return r;
   1227  1.1  brad }
   1228  1.1  brad 
   1229  1.1  brad /*
   1230  1.1  brad   The documented conversion calculations for the raw values are as follows:
   1231  1.1  brad 
   1232  1.1  brad   %RH = (-6 + 125 * rawvalue / 65535)
   1233  1.1  brad 
   1234  1.1  brad   T in Celsius = (-45 + 175 * rawvalue / 65535)
   1235  1.1  brad 
   1236  1.1  brad   It follows then:
   1237  1.1  brad 
   1238  1.1  brad   T in Kelvin = (228.15 + 175 * rawvalue / 65535)
   1239  1.1  brad 
   1240  1.1  brad   given the relationship between Celsius and Kelvin
   1241  1.1  brad 
   1242  1.1  brad   What follows reorders the calculation a bit and scales it up to avoid
   1243  1.1  brad   the use of any floating point.  All that would really have to happen
   1244  1.1  brad   is a scale up to 10^6 for the sysenv framework, which wants
   1245  1.1  brad   temperature in micro-kelvin and percent relative humidity scaled up
   1246  1.1  brad   10^6, but since this conversion uses 64 bits due to intermediate
   1247  1.1  brad   values that are bigger than 32 bits the conversion first scales up to
   1248  1.1  brad   10^9 and the scales back down by 10^3 at the end.  This preserves some
   1249  1.1  brad   precision in the conversion that would otherwise be lost.
   1250  1.1  brad */
   1251  1.1  brad 
   1252  1.1  brad static uint64_t
   1253  1.1  brad sht3x_compute_temp_from_raw(uint8_t msb, uint8_t lsb) {
   1254  1.1  brad 	uint64_t svalue;
   1255  1.1  brad 	int64_t v1;
   1256  1.1  brad 	uint64_t v2;
   1257  1.1  brad 	uint64_t d1 = 65535;
   1258  1.1  brad 	uint64_t mul1;
   1259  1.1  brad 	uint64_t mul2;
   1260  1.1  brad 	uint64_t div1 = 10000;
   1261  1.1  brad 	uint64_t q;
   1262  1.1  brad 
   1263  1.1  brad 	svalue = msb << 8 | lsb;
   1264  1.1  brad 
   1265  1.1  brad 	v1 = 22815; /* this is scaled up already from 228.15 */
   1266  1.1  brad 	v2 = 175;
   1267  1.1  brad 	mul1 = 10000000000;
   1268  1.1  brad 	mul2 = 100000000;
   1269  1.1  brad 
   1270  1.1  brad 	svalue = svalue * mul1;
   1271  1.1  brad 	v1 = v1 * mul2;
   1272  1.1  brad 	/* Perform the conversion */
   1273  1.1  brad 	q = ((v2 * (svalue / d1)) + v1) / div1;
   1274  1.1  brad 
   1275  1.1  brad 	return q;
   1276  1.1  brad }
   1277  1.1  brad 
   1278  1.1  brad static uint64_t
   1279  1.1  brad sht3x_compute_rh_from_raw(uint8_t msb, uint8_t lsb) {
   1280  1.1  brad 	uint64_t svalue;
   1281  1.1  brad 	int64_t v1;
   1282  1.1  brad 	uint64_t v2;
   1283  1.1  brad 	uint64_t d1 = 65535;
   1284  1.1  brad 	uint64_t mul1;
   1285  1.1  brad 	uint64_t mul2;
   1286  1.1  brad 	uint64_t div1 = 10000;
   1287  1.1  brad 	uint64_t q;
   1288  1.1  brad 
   1289  1.1  brad 	svalue = msb << 8 | lsb;
   1290  1.1  brad 
   1291  1.1  brad 	v1 = 0;
   1292  1.1  brad 	v2 = 100;
   1293  1.1  brad 	mul1 = 10000000000;
   1294  1.1  brad 	mul2 = 10000000000;
   1295  1.1  brad 
   1296  1.1  brad 	svalue = svalue * mul1;
   1297  1.1  brad 	v1 = v1 * mul2;
   1298  1.1  brad 	/* Perform the conversion */
   1299  1.1  brad 	q = ((v2 * (svalue / d1)) + v1) / div1;
   1300  1.1  brad 
   1301  1.1  brad 	return q;
   1302  1.1  brad }
   1303  1.1  brad 
   1304  1.1  brad /* These are the the same as above except solved for the raw tick rather than
   1305  1.1  brad  * temperature or humidity.  These are needed for setting the alert limits, but
   1306  1.1  brad  * since that did not work, disable these too for now.
   1307  1.1  brad  */
   1308  1.1  brad #ifdef __did_not_work
   1309  1.1  brad static uint16_t
   1310  1.1  brad sht3x_compute_raw_from_temp(uint32_t temp)
   1311  1.1  brad {
   1312  1.1  brad 	uint64_t i1;
   1313  1.1  brad 	uint32_t tempc;
   1314  1.1  brad 
   1315  1.1  brad 	tempc = temp - 272150000;
   1316  1.1  brad 	tempc = tempc / 1000000;
   1317  1.1  brad 
   1318  1.1  brad 	i1 = (13107 * tempc) + 589815;
   1319  1.1  brad 	return (uint16_t)(i1 / 35);
   1320  1.1  brad }
   1321  1.1  brad 
   1322  1.1  brad static uint16_t
   1323  1.1  brad sht3x_compute_raw_from_rh(uint32_t mrh)
   1324  1.1  brad {
   1325  1.1  brad 	uint64_t i1;
   1326  1.1  brad 	uint32_t rh;
   1327  1.1  brad 
   1328  1.1  brad 	rh = mrh / 1000000;
   1329  1.1  brad 
   1330  1.1  brad 	i1 = 13107 * rh;
   1331  1.1  brad 	return (uint16_t)(i1 / 20);
   1332  1.1  brad }
   1333  1.1  brad #endif
   1334  1.1  brad 
   1335  1.1  brad static void
   1336  1.1  brad sht3x_refresh(struct sysmon_envsys * sme, envsys_data_t * edata)
   1337  1.1  brad {
   1338  1.1  brad 	struct sht3x_sc *sc;
   1339  1.1  brad 	sc = sme->sme_cookie;
   1340  1.1  brad 	int error;
   1341  1.1  brad 	uint8_t rawdata[6];
   1342  1.1  brad 	uint16_t measurement_command_ss;
   1343  1.1  brad 	uint64_t current_value;
   1344  1.1  brad 	uint8_t *svalptr;
   1345  1.1  brad 
   1346  1.1  brad 	edata->state = ENVSYS_SINVALID;
   1347  1.1  brad 
   1348  1.1  brad 	mutex_enter(&sc->sc_mutex);
   1349  1.1  brad 
   1350  1.1  brad 	if (!sc->sc_isperiodic) {
   1351  1.1  brad 		error = iic_acquire_bus(sc->sc_tag, 0);
   1352  1.1  brad 		if (error) {
   1353  1.1  brad 			DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n",
   1354  1.1  brad 			    device_xname(sc->sc_dev), error));
   1355  1.1  brad 			goto out;
   1356  1.1  brad 		}
   1357  1.1  brad 
   1358  1.1  brad 		measurement_command_ss = sht3x_compute_measure_command_ss(sc->sc_repeatability);
   1359  1.1  brad 		DPRINTF(sc, 2, ("%s: Measurement command: %04x\n",
   1360  1.1  brad 		    device_xname(sc->sc_dev), measurement_command_ss));
   1361  1.1  brad 		error = sht3x_cmdr(sc,measurement_command_ss,rawdata,6);
   1362  1.1  brad 		if (error == 0) {
   1363  1.1  brad 			DPRINTF(sc, 2, ("%s: Raw data ss: %02x%02x %02x - %02x%02x %02x\n",
   1364  1.1  brad 			    device_xname(sc->sc_dev), rawdata[0], rawdata[1], rawdata[2],
   1365  1.1  brad 			    rawdata[3], rawdata[4], rawdata[5]));
   1366  1.1  brad 			switch (edata->sensor) {
   1367  1.1  brad 			case SHT3X_TEMP_SENSOR:
   1368  1.1  brad 				svalptr = &rawdata[0];
   1369  1.1  brad 				current_value = sht3x_compute_temp_from_raw(rawdata[0],rawdata[1]);
   1370  1.1  brad 				break;
   1371  1.1  brad 			case SHT3X_HUMIDITY_SENSOR:
   1372  1.1  brad 				svalptr = &rawdata[3];
   1373  1.1  brad 				current_value = sht3x_compute_rh_from_raw(rawdata[3],rawdata[4]);
   1374  1.1  brad 				break;
   1375  1.1  brad 			default:
   1376  1.1  brad 				error = EINTR;
   1377  1.1  brad 				break;
   1378  1.1  brad 			}
   1379  1.1  brad 
   1380  1.1  brad 			if (error == 0) {
   1381  1.1  brad 				uint8_t testcrc;
   1382  1.1  brad 
   1383  1.1  brad 				/* Fake out the CRC check if being asked to ignore CRC */
   1384  1.1  brad 				if (sc->sc_ignorecrc) {
   1385  1.1  brad 					testcrc = *(svalptr + 2);
   1386  1.1  brad 				} else {
   1387  1.1  brad 					testcrc = sht3x_crc(svalptr,2);
   1388  1.1  brad 				}
   1389  1.1  brad 
   1390  1.1  brad 				if (*(svalptr + 2) == testcrc) {
   1391  1.1  brad 					edata->value_cur = (uint32_t) current_value;
   1392  1.1  brad 					edata->state = ENVSYS_SVALID;
   1393  1.1  brad 				} else {
   1394  1.1  brad 					error = EINVAL;
   1395  1.1  brad 				}
   1396  1.1  brad 			}
   1397  1.1  brad 		}
   1398  1.1  brad 
   1399  1.1  brad 		if (error) {
   1400  1.1  brad 			DPRINTF(sc, 2, ("%s: Failed to get new status in refresh for single-shot %d\n",
   1401  1.1  brad 			    device_xname(sc->sc_dev), error));
   1402  1.1  brad 		}
   1403  1.1  brad 
   1404  1.1  brad 		uint16_t sbuf;
   1405  1.1  brad 		int status_error;
   1406  1.1  brad 
   1407  1.1  brad 		status_error = sht3x_get_status_register(sc, &sbuf, true);
   1408  1.1  brad 
   1409  1.1  brad 		if (!status_error) {
   1410  1.1  brad 			DPRINTF(sc, 2, ("%s: read status register single-shot: %04x\n",
   1411  1.1  brad 			    device_xname(sc->sc_dev), sbuf));
   1412  1.1  brad 
   1413  1.1  brad 			if (sbuf & SHT3X_RESET_DETECTED) {
   1414  1.1  brad 				aprint_error_dev(sc->sc_dev, "Reset detected in single shot mode.  Heater may have been reset\n");
   1415  1.1  brad 				sht3x_clear_status_register(sc, true);
   1416  1.1  brad 			}
   1417  1.1  brad 
   1418  1.1  brad 			sc->sc_heateron = sbuf & SHT3X_HEATER_STATUS;
   1419  1.1  brad 		}
   1420  1.1  brad 
   1421  1.1  brad 		iic_release_bus(sc->sc_tag, 0);
   1422  1.1  brad 	} else {
   1423  1.1  brad 		error = 0;
   1424  1.1  brad 		memcpy(rawdata,sc->sc_pbuffer,6);
   1425  1.1  brad 
   1426  1.1  brad 		DPRINTF(sc, 2, ("%s: Raw data periodic: %02x%02x %02x - %02x%02x %02x\n",
   1427  1.1  brad 		    device_xname(sc->sc_dev), rawdata[0], rawdata[1], rawdata[2],
   1428  1.1  brad 		    rawdata[3], rawdata[4], rawdata[5]));
   1429  1.1  brad 
   1430  1.1  brad 		switch (edata->sensor) {
   1431  1.1  brad 		case SHT3X_TEMP_SENSOR:
   1432  1.1  brad 			svalptr = &rawdata[0];
   1433  1.1  brad 			current_value = sht3x_compute_temp_from_raw(rawdata[0],rawdata[1]);
   1434  1.1  brad 			break;
   1435  1.1  brad 		case SHT3X_HUMIDITY_SENSOR:
   1436  1.1  brad 			svalptr = &rawdata[3];
   1437  1.1  brad 			current_value = sht3x_compute_rh_from_raw(rawdata[3],rawdata[4]);
   1438  1.1  brad 			break;
   1439  1.1  brad 		default:
   1440  1.1  brad 			error = EINTR;
   1441  1.1  brad 			break;
   1442  1.1  brad 		}
   1443  1.1  brad 
   1444  1.1  brad 		if (error == 0) {
   1445  1.1  brad 			uint8_t testcrc;
   1446  1.1  brad 
   1447  1.1  brad 			/* Fake out the CRC check if being asked to ignore CRC */
   1448  1.1  brad 			if (sc->sc_ignorecrc) {
   1449  1.1  brad 				testcrc = *(svalptr + 2);
   1450  1.1  brad 			} else {
   1451  1.1  brad 				testcrc = sht3x_crc(svalptr,2);
   1452  1.1  brad 			}
   1453  1.1  brad 
   1454  1.1  brad 			if (*(svalptr + 2) == testcrc) {
   1455  1.1  brad 				edata->value_cur = (uint32_t) current_value;
   1456  1.1  brad 				edata->state = ENVSYS_SVALID;
   1457  1.1  brad 			} else {
   1458  1.1  brad 				error = EINVAL;
   1459  1.1  brad 			}
   1460  1.1  brad 		}
   1461  1.1  brad 
   1462  1.1  brad 		if (error) {
   1463  1.1  brad 			DPRINTF(sc, 2, ("%s: Failed to get new status in refresh for periodic %d\n",
   1464  1.1  brad 			    device_xname(sc->sc_dev), error));
   1465  1.1  brad 		}
   1466  1.1  brad 	}
   1467  1.1  brad out:
   1468  1.1  brad 	mutex_exit(&sc->sc_mutex);
   1469  1.1  brad }
   1470  1.1  brad 
   1471  1.1  brad #ifdef __did_not_work
   1472  1.1  brad static void
   1473  1.1  brad sht3x_get_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
   1474  1.1  brad 		 sysmon_envsys_lim_t *limits, uint32_t *props)
   1475  1.1  brad {
   1476  1.1  brad 	struct sht3x_sc *sc = sme->sme_cookie;
   1477  1.1  brad 	uint16_t rawlimitshigh, rawlimitslow;
   1478  1.1  brad 	uint16_t templimithigh, rhlimithigh,
   1479  1.1  brad 	    templimitlow, rhlimitlow;
   1480  1.1  brad 	uint8_t templimithighmsb, templimithighlsb,
   1481  1.1  brad 	    templimitlowmsb, templimitlowlsb;
   1482  1.1  brad 	uint8_t rhlimithighmsb, rhlimithighlsb,
   1483  1.1  brad 	    rhlimitlowmsb, rhlimitlowlsb;
   1484  1.1  brad 	int error;
   1485  1.1  brad 	uint8_t lbuf[3];
   1486  1.1  brad 	uint8_t limitscrchigh, limitskcrchigh,
   1487  1.1  brad 	    limitscrclow, limitskcrclow;
   1488  1.1  brad 
   1489  1.1  brad 	*props = 0;
   1490  1.1  brad 
   1491  1.1  brad 	mutex_enter(&sc->sc_mutex);
   1492  1.1  brad 	error = iic_acquire_bus(sc->sc_tag, 0);
   1493  1.1  brad 	if (error) {
   1494  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n",
   1495  1.1  brad 		    device_xname(sc->sc_dev), error));
   1496  1.1  brad 		goto out;
   1497  1.1  brad 	}
   1498  1.1  brad 
   1499  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_SET, lbuf, 3);
   1500  1.1  brad 	if (error) {
   1501  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n",
   1502  1.1  brad 		    device_xname(sc->sc_dev), error));
   1503  1.1  brad 		goto out;
   1504  1.1  brad 	}
   1505  1.1  brad 
   1506  1.1  brad 	rawlimitshigh = (lbuf[0] << 8) | lbuf[1];
   1507  1.1  brad 	limitskcrchigh = lbuf[2];
   1508  1.1  brad 	limitscrchigh = sht3x_crc(&lbuf[0],2);
   1509  1.1  brad 
   1510  1.1  brad 	templimithigh = ((rawlimitshigh & 0x1FF) << 7);
   1511  1.1  brad 	templimithighmsb = (uint8_t)(templimithigh >> 8);
   1512  1.1  brad 	templimithighlsb = (uint8_t)(templimithigh & 0x00FF);
   1513  1.1  brad 	DPRINTF(sc, 2, ("%s: Limits high intermediate temp: %04x %04x %02x %02x\n",
   1514  1.1  brad 	    device_xname(sc->sc_dev), rawlimitshigh, templimithigh, templimithighmsb,
   1515  1.1  brad 	    templimithighlsb));
   1516  1.1  brad 
   1517  1.1  brad 	rhlimithigh = (rawlimitshigh & 0xFE00);
   1518  1.1  brad 	rhlimithighmsb = (uint8_t)(rhlimithigh >> 8);
   1519  1.1  brad 	rhlimithighlsb = (uint8_t)(rhlimithigh & 0x00FF);
   1520  1.1  brad 	DPRINTF(sc, 2, ("%s: Limits high intermediate rh: %04x %04x %02x %02x\n",
   1521  1.1  brad 	    device_xname(sc->sc_dev), rawlimitshigh, rhlimithigh, rhlimithighmsb,
   1522  1.1  brad 	    rhlimithighlsb));
   1523  1.1  brad 
   1524  1.1  brad 	DPRINTF(sc, 2, ("%s: Limit high raw: %02x%02x %02x %02x %02x\n",
   1525  1.1  brad 	    device_xname(sc->sc_dev), lbuf[0], lbuf[1], lbuf[2],
   1526  1.1  brad 	    limitscrchigh, limitskcrchigh));
   1527  1.1  brad 
   1528  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_READ_LOW_ALERT_SET, lbuf, 3);
   1529  1.1  brad 	if (error) {
   1530  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n",
   1531  1.1  brad 		    device_xname(sc->sc_dev), error));
   1532  1.1  brad 		goto out;
   1533  1.1  brad 	}
   1534  1.1  brad 
   1535  1.1  brad 	rawlimitslow = (lbuf[0] << 8) | lbuf[1];
   1536  1.1  brad 	limitskcrclow = lbuf[2];
   1537  1.1  brad 	limitscrclow = sht3x_crc(&lbuf[0],2);
   1538  1.1  brad 
   1539  1.1  brad 	templimitlow = ((rawlimitslow & 0x1FF) << 7);
   1540  1.1  brad 	templimitlowmsb = (uint8_t)(templimitlow >> 8);
   1541  1.1  brad 	templimitlowlsb = (uint8_t)(templimitlow & 0x00FF);
   1542  1.1  brad 	DPRINTF(sc, 2, ("%s: Limits low intermediate temp: %04x %04x %02x %02x\n",
   1543  1.1  brad 	    device_xname(sc->sc_dev), rawlimitslow, templimitlow, templimitlowmsb,
   1544  1.1  brad 	    templimitlowlsb));
   1545  1.1  brad 
   1546  1.1  brad 	rhlimitlow = (rawlimitslow & 0xFE00);
   1547  1.1  brad 	rhlimitlowmsb = (uint8_t)(rhlimitlow >> 8);
   1548  1.1  brad 	rhlimitlowlsb = (uint8_t)(rhlimitlow & 0x00FF);
   1549  1.1  brad 	DPRINTF(sc, 2, ("%s: Limits low intermediate rh: %04x %04x %02x %02x\n",
   1550  1.1  brad 	    device_xname(sc->sc_dev), rawlimitslow, rhlimitlow, rhlimitlowmsb,
   1551  1.1  brad 	    rhlimitlowlsb));
   1552  1.1  brad 
   1553  1.1  brad 	DPRINTF(sc, 2, ("%s: Limit low raw: %02x%02x %02x %02x %02x\n",
   1554  1.1  brad 	    device_xname(sc->sc_dev), lbuf[0], lbuf[1], lbuf[2],
   1555  1.1  brad 	    limitscrclow, limitskcrclow));
   1556  1.1  brad 
   1557  1.1  brad 
   1558  1.1  brad 	switch (edata->sensor) {
   1559  1.1  brad 	case SHT3X_TEMP_SENSOR:
   1560  1.1  brad 		if (limitscrchigh == limitskcrchigh) {
   1561  1.1  brad 			limits->sel_critmax = sht3x_compute_temp_from_raw(templimithighmsb, templimithighlsb);
   1562  1.1  brad 			*props |= PROP_CRITMAX;
   1563  1.1  brad 		}
   1564  1.1  brad 		if (limitscrclow == limitskcrclow) {
   1565  1.1  brad 			limits->sel_critmin = sht3x_compute_temp_from_raw(templimitlowmsb, templimitlowlsb);
   1566  1.1  brad 			*props |= PROP_CRITMIN;
   1567  1.1  brad 		}
   1568  1.1  brad 		break;
   1569  1.1  brad 	case SHT3X_HUMIDITY_SENSOR:
   1570  1.1  brad 		if (limitscrchigh == limitskcrchigh) {
   1571  1.1  brad 			limits->sel_critmax = sht3x_compute_rh_from_raw(rhlimithighmsb, rhlimithighlsb);
   1572  1.1  brad 			*props |= PROP_CRITMAX;
   1573  1.1  brad 		}
   1574  1.1  brad 		if (limitscrclow == limitskcrclow) {
   1575  1.1  brad 			limits->sel_critmin = sht3x_compute_rh_from_raw(rhlimitlowmsb, rhlimitlowlsb);
   1576  1.1  brad 			*props |= PROP_CRITMIN;
   1577  1.1  brad 		}
   1578  1.1  brad 		break;
   1579  1.1  brad 	default:
   1580  1.1  brad 		break;
   1581  1.1  brad 	}
   1582  1.1  brad 
   1583  1.1  brad 	if (*props != 0)
   1584  1.1  brad 		*props |= PROP_DRIVER_LIMITS;
   1585  1.1  brad 
   1586  1.1  brad 	iic_release_bus(sc->sc_tag, 0);
   1587  1.1  brad  out:
   1588  1.1  brad 	mutex_exit(&sc->sc_mutex);
   1589  1.1  brad }
   1590  1.1  brad 
   1591  1.1  brad static void
   1592  1.1  brad sht3x_set_alert_limits(void *aux, uint16_t high, uint16_t low, bool have_bus)
   1593  1.1  brad {
   1594  1.1  brad 	struct sht3x_sc *sc;
   1595  1.1  brad 	sc = aux;
   1596  1.1  brad 
   1597  1.1  brad 	int error = 0;
   1598  1.1  brad 	uint8_t hbuf[3];
   1599  1.1  brad 	uint8_t lbuf[3];
   1600  1.1  brad 
   1601  1.1  brad 	if (! have_bus) {
   1602  1.1  brad 		error = iic_acquire_bus(sc->sc_tag, 0);
   1603  1.1  brad 		if (error) {
   1604  1.1  brad 			DPRINTF(sc, 2, ("%s: Could not acquire iic bus for setting alerts %d\n",
   1605  1.1  brad 			    device_xname(sc->sc_dev), error));
   1606  1.1  brad 			goto out;
   1607  1.1  brad 		}
   1608  1.1  brad 	}
   1609  1.1  brad 
   1610  1.1  brad 	hbuf[0] = high >> 8;
   1611  1.1  brad 	hbuf[1] = high & 0x00FF;
   1612  1.1  brad 	hbuf[2] = sht3x_crc(&hbuf[0],2);
   1613  1.1  brad 
   1614  1.1  brad 	lbuf[0] = low >> 8;
   1615  1.1  brad 	lbuf[1] = low & 0x00FF;
   1616  1.1  brad 	lbuf[2] = sht3x_crc(&lbuf[0],2);
   1617  1.1  brad 
   1618  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_SET, hbuf, 3);
   1619  1.1  brad 	if (error) {
   1620  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not set high alert for SET %d\n",
   1621  1.1  brad 		    device_xname(sc->sc_dev), error));
   1622  1.1  brad 		goto out;
   1623  1.1  brad 	}
   1624  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_CLEAR, hbuf, 3);
   1625  1.1  brad 	if (error) {
   1626  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n",
   1627  1.1  brad 		    device_xname(sc->sc_dev), error));
   1628  1.1  brad 		goto out;
   1629  1.1  brad 	}
   1630  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_SET, lbuf, 3);
   1631  1.1  brad 	if (error) {
   1632  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not set low alert for SET %d\n",
   1633  1.1  brad 		    device_xname(sc->sc_dev), error));
   1634  1.1  brad 		goto out;
   1635  1.1  brad 	}
   1636  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_CLEAR, lbuf, 3);
   1637  1.1  brad 	if (error) {
   1638  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n",
   1639  1.1  brad 		    device_xname(sc->sc_dev), error));
   1640  1.1  brad 	}
   1641  1.1  brad 
   1642  1.1  brad  out:
   1643  1.1  brad 	if (! have_bus) {
   1644  1.1  brad 		iic_release_bus(sc->sc_tag, 0);
   1645  1.1  brad 	}
   1646  1.1  brad }
   1647  1.1  brad 
   1648  1.1  brad static void
   1649  1.1  brad sht3x_set_alert_limits2(void *aux, uint16_t high, uint16_t low,
   1650  1.1  brad     uint16_t highminusone, uint16_t lowplusone, bool have_bus)
   1651  1.1  brad {
   1652  1.1  brad 	struct sht3x_sc *sc;
   1653  1.1  brad 	sc = aux;
   1654  1.1  brad 
   1655  1.1  brad 	int error = 0;
   1656  1.1  brad 	uint8_t hbuf[3];
   1657  1.1  brad 	uint8_t lbuf[3];
   1658  1.1  brad 	uint8_t hbufminusone[3];
   1659  1.1  brad 	uint8_t lbufplusone[3];
   1660  1.1  brad 
   1661  1.1  brad 	if (! have_bus) {
   1662  1.1  brad 		error = iic_acquire_bus(sc->sc_tag, 0);
   1663  1.1  brad 		if (error) {
   1664  1.1  brad 			DPRINTF(sc, 2, ("%s: Could not acquire iic bus for setting alerts %d\n",
   1665  1.1  brad 			    device_xname(sc->sc_dev), error));
   1666  1.1  brad 			goto out;
   1667  1.1  brad 		}
   1668  1.1  brad 	}
   1669  1.1  brad 
   1670  1.1  brad 	hbuf[0] = high >> 8;
   1671  1.1  brad 	hbuf[1] = high & 0x00FF;
   1672  1.1  brad 	hbuf[2] = sht3x_crc(&hbuf[0],2);
   1673  1.1  brad 
   1674  1.1  brad 	lbuf[0] = low >> 8;
   1675  1.1  brad 	lbuf[1] = low & 0x00FF;
   1676  1.1  brad 	lbuf[2] = sht3x_crc(&lbuf[0],2);
   1677  1.1  brad 
   1678  1.1  brad 	hbufminusone[0] = highminusone >> 8;
   1679  1.1  brad 	hbufminusone[1] = highminusone & 0x00FF;
   1680  1.1  brad 	hbufminusone[2] = sht3x_crc(&hbufminusone[0],2);
   1681  1.1  brad 
   1682  1.1  brad 	lbufplusone[0] = lowplusone >> 8;
   1683  1.1  brad 	lbufplusone[1] = lowplusone & 0x00FF;
   1684  1.1  brad 	lbufplusone[2] = sht3x_crc(&lbufplusone[0],2);
   1685  1.1  brad 
   1686  1.1  brad 	DPRINTF(sc, 2, ("%s: Physical SET HIGH %02x %02x %02x\n",
   1687  1.1  brad 	    device_xname(sc->sc_dev), hbuf[0], hbuf[1], hbuf[2]));
   1688  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_SET, hbuf, 3);
   1689  1.1  brad 	if (error) {
   1690  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not set high alert for SET %d\n",
   1691  1.1  brad 		    device_xname(sc->sc_dev), error));
   1692  1.1  brad 		goto out;
   1693  1.1  brad 	}
   1694  1.1  brad 
   1695  1.1  brad 	uint16_t sbuf;
   1696  1.1  brad 	int status_error;
   1697  1.1  brad 	status_error = sht3x_get_status_register(sc, &sbuf, true);
   1698  1.1  brad 	DPRINTF(sc, 2, ("%s: In SETTING, status register %04x -- %d\n",
   1699  1.1  brad 	    device_xname(sc->sc_dev), sbuf, status_error));
   1700  1.1  brad 
   1701  1.1  brad 	hbuf[0] = 0;
   1702  1.1  brad 	hbuf[1] = 0;
   1703  1.1  brad 	hbuf[2] = 0;
   1704  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_SET, hbuf, 3);
   1705  1.1  brad 	if (error) {
   1706  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not read high alert for SET %d\n",
   1707  1.1  brad 		    device_xname(sc->sc_dev), error));
   1708  1.1  brad 		goto out;
   1709  1.1  brad 	}
   1710  1.1  brad 	DPRINTF(sc, 2, ("%s: Physical READBACK SET HIGH %02x %02x %02x\n",
   1711  1.1  brad 	    device_xname(sc->sc_dev), hbuf[0], hbuf[1], hbuf[2]));
   1712  1.1  brad 
   1713  1.1  brad 	DPRINTF(sc, 2, ("%s: Physical CLEAR HIGH %02x %02x %02x\n",
   1714  1.1  brad 	    device_xname(sc->sc_dev), hbufminusone[0], hbufminusone[1], hbufminusone[2]));
   1715  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_WRITE_HIGH_ALERT_CLEAR, hbufminusone, 3);
   1716  1.1  brad 	if (error) {
   1717  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n",
   1718  1.1  brad 		    device_xname(sc->sc_dev), error));
   1719  1.1  brad 		goto out;
   1720  1.1  brad 	}
   1721  1.1  brad 	hbufminusone[0] = 0;
   1722  1.1  brad 	hbufminusone[1] = 0;
   1723  1.1  brad 	hbufminusone[2] = 0;
   1724  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_CLEAR, hbufminusone, 3);
   1725  1.1  brad 	if (error) {
   1726  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not read high alert for CLEAR %d\n",
   1727  1.1  brad 		    device_xname(sc->sc_dev), error));
   1728  1.1  brad 		goto out;
   1729  1.1  brad 	}
   1730  1.1  brad 	DPRINTF(sc, 2, ("%s: Physical READBACK CLEAR HIGH %02x %02x %02x\n",
   1731  1.1  brad 	    device_xname(sc->sc_dev), hbufminusone[0], hbufminusone[1], hbufminusone[2]));
   1732  1.1  brad 
   1733  1.1  brad 	DPRINTF(sc, 2, ("%s: Physical SET LOW %02x %02x %02x\n",
   1734  1.1  brad 	    device_xname(sc->sc_dev), lbuf[0], lbuf[1], lbuf[2]));
   1735  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_SET, lbuf, 3);
   1736  1.1  brad 	if (error) {
   1737  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not set low alert for SET %d\n",
   1738  1.1  brad 		    device_xname(sc->sc_dev), error));
   1739  1.1  brad 		goto out;
   1740  1.1  brad 	}
   1741  1.1  brad 	DPRINTF(sc, 2, ("%s: Physical CLEAR LOW %02x %02x %02x\n",
   1742  1.1  brad 	    device_xname(sc->sc_dev), lbufplusone[0], lbufplusone[1], lbufplusone[2]));
   1743  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_WRITE_LOW_ALERT_CLEAR, lbufplusone, 3);
   1744  1.1  brad 	if (error) {
   1745  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not set high alert for CLEAR %d\n",
   1746  1.1  brad 		    device_xname(sc->sc_dev), error));
   1747  1.1  brad 	}
   1748  1.1  brad 
   1749  1.1  brad  out:
   1750  1.1  brad 	if (! have_bus) {
   1751  1.1  brad 		iic_release_bus(sc->sc_tag, 0);
   1752  1.1  brad 	}
   1753  1.1  brad }
   1754  1.1  brad 
   1755  1.1  brad static void
   1756  1.1  brad sht3x_set_limits(struct sysmon_envsys *sme, envsys_data_t *edata,
   1757  1.1  brad 		 sysmon_envsys_lim_t *limits, uint32_t *props)
   1758  1.1  brad {
   1759  1.1  brad 	struct sht3x_sc *sc = sme->sme_cookie;
   1760  1.1  brad 	uint16_t rawlimitshigh, rawlimitslow;
   1761  1.1  brad 	uint16_t rawlimitshighclear, rawlimitslowclear;
   1762  1.1  brad 	uint16_t rawlimitshighminusone, rawlimitslowplusone;
   1763  1.1  brad 	int error;
   1764  1.1  brad 	uint8_t lbuf[3];
   1765  1.1  brad 	uint8_t limitscrchigh, limitskcrchigh,
   1766  1.1  brad 	    limitscrclow, limitskcrclow;
   1767  1.1  brad 	uint16_t limithigh, limitlow;
   1768  1.1  brad 	uint16_t limithighminusone, limitlowplusone;
   1769  1.1  brad 
   1770  1.1  brad 	if (limits == NULL) {
   1771  1.1  brad 		printf("XXX - Need to set back to default... limits is NULL\n");
   1772  1.1  brad 		return;
   1773  1.1  brad 	}
   1774  1.1  brad 
   1775  1.1  brad 	DPRINTF(sc, 2, ("%s: In set_limits - %d -- %d %d\n",
   1776  1.1  brad 	    device_xname(sc->sc_dev), edata->sensor,
   1777  1.1  brad 	    limits->sel_critmin, limits->sel_critmax));
   1778  1.1  brad 
   1779  1.1  brad 	mutex_enter(&sc->sc_mutex);
   1780  1.1  brad 	error = iic_acquire_bus(sc->sc_tag, 0);
   1781  1.1  brad 	if (error) {
   1782  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not acquire i2c bus: %x\n",
   1783  1.1  brad 		    device_xname(sc->sc_dev), error));
   1784  1.1  brad 		goto out;
   1785  1.1  brad 	}
   1786  1.1  brad 
   1787  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_SET, lbuf, 3);
   1788  1.1  brad 	if (error) {
   1789  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n",
   1790  1.1  brad 		    device_xname(sc->sc_dev), error));
   1791  1.1  brad 		goto out;
   1792  1.1  brad 	}
   1793  1.1  brad 
   1794  1.1  brad 	rawlimitshigh = (lbuf[0] << 8) | lbuf[1];
   1795  1.1  brad 	limitskcrchigh = lbuf[2];
   1796  1.1  brad 	limitscrchigh = sht3x_crc(&lbuf[0],2);
   1797  1.1  brad 
   1798  1.1  brad 
   1799  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_READ_LOW_ALERT_SET, lbuf, 3);
   1800  1.1  brad 	if (error) {
   1801  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not get high alert: %x\n",
   1802  1.1  brad 		    device_xname(sc->sc_dev), error));
   1803  1.1  brad 		goto out;
   1804  1.1  brad 	}
   1805  1.1  brad 
   1806  1.1  brad 	rawlimitslow = (lbuf[0] << 8) | lbuf[1];
   1807  1.1  brad 	limitskcrclow = lbuf[2];
   1808  1.1  brad 	limitscrclow = sht3x_crc(&lbuf[0],2);
   1809  1.1  brad 
   1810  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_READ_HIGH_ALERT_CLEAR, lbuf, 3);
   1811  1.1  brad 	if (error) {
   1812  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not get high alert clear: %x\n",
   1813  1.1  brad 		    device_xname(sc->sc_dev), error));
   1814  1.1  brad 		goto out;
   1815  1.1  brad 	}
   1816  1.1  brad 
   1817  1.1  brad 	rawlimitshighclear = (lbuf[0] << 8) | lbuf[1];
   1818  1.1  brad 
   1819  1.1  brad 	error = sht3x_cmdr(sc, SHT3X_READ_LOW_ALERT_CLEAR, lbuf, 3);
   1820  1.1  brad 	if (error) {
   1821  1.1  brad 		DPRINTF(sc, 2, ("%s: Could not get high alert clear: %x\n",
   1822  1.1  brad 		    device_xname(sc->sc_dev), error));
   1823  1.1  brad 		goto out;
   1824  1.1  brad 	}
   1825  1.1  brad 
   1826  1.1  brad 	rawlimitslowclear = (lbuf[0] << 8) | lbuf[1];
   1827  1.1  brad 
   1828  1.1  brad 	DPRINTF(sc, 2, ("%s: Set limits current raw limits %04x - %02x %02x ; %04x - %02x %02x ;; %04x %04x\n",
   1829  1.1  brad 	    device_xname(sc->sc_dev), rawlimitshigh, limitskcrchigh, limitscrchigh,
   1830  1.1  brad 	    rawlimitslow, limitskcrclow, limitscrclow, rawlimitshighclear, rawlimitslowclear));
   1831  1.1  brad 
   1832  1.1  brad 	switch (edata->sensor) {
   1833  1.1  brad 	case SHT3X_TEMP_SENSOR:
   1834  1.1  brad 		limithigh = sht3x_compute_raw_from_temp(limits->sel_critmax);
   1835  1.1  brad 		limitlow = sht3x_compute_raw_from_temp(limits->sel_critmin);
   1836  1.1  brad 		limithigh = limithigh >> 7;
   1837  1.1  brad 		limithighminusone = limithigh - 1;
   1838  1.1  brad 		limitlow = limitlow >> 7;
   1839  1.1  brad 		limitlowplusone = limitlow + 1;
   1840  1.1  brad 		rawlimitshigh = (rawlimitshigh & 0xFE00) | limithigh;
   1841  1.1  brad 		rawlimitshighminusone = (rawlimitshigh & 0xFE00) | limithighminusone;
   1842  1.1  brad 		rawlimitslow = (rawlimitslow & 0xFE00) | limitlow;
   1843  1.1  brad 		rawlimitslowplusone = (rawlimitslow & 0xFE00) | limitlowplusone;
   1844  1.1  brad 		DPRINTF(sc, 2, ("%s: Temp new raw limits high/low %04x %04x %04x %04x\n",
   1845  1.1  brad 		    device_xname(sc->sc_dev), rawlimitshigh, rawlimitslow,
   1846  1.1  brad 		    rawlimitshighminusone, rawlimitslowplusone));
   1847  1.1  brad 		sht3x_set_alert_limits2(sc, rawlimitshigh, rawlimitslow,
   1848  1.1  brad 		    rawlimitshighminusone, rawlimitslowplusone, true);
   1849  1.1  brad 		break;
   1850  1.1  brad 	case SHT3X_HUMIDITY_SENSOR:
   1851  1.1  brad 		limithigh = sht3x_compute_raw_from_rh(limits->sel_critmax);
   1852  1.1  brad 		limitlow = sht3x_compute_raw_from_rh(limits->sel_critmin);
   1853  1.1  brad 		limithigh = limithigh & 0xFE00;
   1854  1.1  brad 		limitlow = limitlow & 0xFE00;
   1855  1.1  brad 		rawlimitshigh = (rawlimitshigh & 0x1FF) | limithigh;
   1856  1.1  brad 		rawlimitslow = (rawlimitslow & 0x1FF) | limitlow;
   1857  1.1  brad 		DPRINTF(sc, 2, ("%s: RH new raw limits high/low %04x %04x from %x %x\n",
   1858  1.1  brad 		    device_xname(sc->sc_dev), rawlimitshigh, rawlimitslow, limithigh, limitlow));
   1859  1.1  brad 		sht3x_set_alert_limits(sc, rawlimitshigh, rawlimitslow, true);
   1860  1.1  brad 		break;
   1861  1.1  brad 	default:
   1862  1.1  brad 		break;
   1863  1.1  brad 	}
   1864  1.1  brad 
   1865  1.1  brad 	iic_release_bus(sc->sc_tag, 0);
   1866  1.1  brad  out:
   1867  1.1  brad 	mutex_exit(&sc->sc_mutex);
   1868  1.1  brad }
   1869  1.1  brad #endif
   1870  1.1  brad 
   1871  1.1  brad static int
   1872  1.1  brad sht3xopen(dev_t dev, int flags, int fmt, struct lwp *l)
   1873  1.1  brad {
   1874  1.1  brad 	struct sht3x_sc *sc;
   1875  1.1  brad 
   1876  1.1  brad 	sc = device_lookup_private(&sht3xtemp_cd, minor(dev));
   1877  1.1  brad 	if (!sc)
   1878  1.1  brad 		return (ENXIO);
   1879  1.1  brad 
   1880  1.1  brad 	if (sc->sc_opened)
   1881  1.1  brad 		return (EBUSY);
   1882  1.1  brad 
   1883  1.1  brad 	mutex_enter(&sc->sc_mutex);
   1884  1.1  brad 	sc->sc_opened = true;
   1885  1.1  brad 
   1886  1.1  brad 	sc->sc_wassingleshot = false;
   1887  1.1  brad 	if (!sc->sc_isperiodic) {
   1888  1.1  brad 		sc->sc_stopping = false;
   1889  1.1  brad 		sc->sc_initperiodic = true;
   1890  1.1  brad 		sc->sc_isperiodic = true;
   1891  1.1  brad 		sc->sc_wassingleshot = true;
   1892  1.1  brad 		sht3x_start_thread(sc);
   1893  1.1  brad 	}
   1894  1.1  brad 	mutex_exit(&sc->sc_mutex);
   1895  1.1  brad 
   1896  1.1  brad 	return (0);
   1897  1.1  brad }
   1898  1.1  brad 
   1899  1.1  brad static int
   1900  1.1  brad sht3xread(dev_t dev, struct uio *uio, int flags)
   1901  1.1  brad {
   1902  1.1  brad 	struct sht3x_sc *sc;
   1903  1.1  brad 	struct sht3x_read_q *pp;
   1904  1.1  brad 	int error,any;
   1905  1.1  brad 
   1906  1.1  brad 	sc = device_lookup_private(&sht3xtemp_cd, minor(dev));
   1907  1.1  brad 	if (!sc)
   1908  1.1  brad 		return (ENXIO);
   1909  1.1  brad 
   1910  1.1  brad 	while (uio->uio_resid) {
   1911  1.1  brad 		any = 0;
   1912  1.1  brad 		error = 0;
   1913  1.1  brad 		mutex_enter(&sc->sc_read_mutex);
   1914  1.1  brad 
   1915  1.1  brad 		while (any == 0) {
   1916  1.1  brad 			pp = SIMPLEQ_FIRST(&sc->sc_read_queue);
   1917  1.1  brad 			if (pp != NULL) {
   1918  1.1  brad 				SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q);
   1919  1.1  brad 				any = 1;
   1920  1.1  brad 				break;
   1921  1.1  brad 			} else {
   1922  1.1  brad 				error = cv_wait_sig(&sc->sc_condreadready,&sc->sc_read_mutex);
   1923  1.1  brad 				if (sc->sc_dying)
   1924  1.1  brad 					error = EIO;
   1925  1.1  brad 				if (error == 0)
   1926  1.1  brad 					continue;
   1927  1.1  brad 				break;
   1928  1.1  brad 			}
   1929  1.1  brad 		}
   1930  1.1  brad 
   1931  1.1  brad 		if (any == 1 && error == 0) {
   1932  1.1  brad 			mutex_exit(&sc->sc_read_mutex);
   1933  1.1  brad 			pool_cache_put(sc->sc_readpool,pp);
   1934  1.1  brad 
   1935  1.1  brad 			DPRINTF(sc,2, ("%s: sending %02x%02x %02x -- %02x%02x %02x -- %x\n",device_xname(sc->sc_dev),pp->measurement[0],pp->measurement[1],pp->measurement[2],pp->measurement[3],pp->measurement[4],pp->measurement[5],mutex_owned(&sc->sc_read_mutex)));
   1936  1.1  brad 			if ((error = uiomove(&pp->measurement[0], 6, uio)) != 0) {
   1937  1.1  brad 				DPRINTF(sc,2, ("%s: send error %d\n",device_xname(sc->sc_dev),error));
   1938  1.1  brad 				break;
   1939  1.1  brad 			}
   1940  1.1  brad 		} else {
   1941  1.1  brad 			mutex_exit(&sc->sc_read_mutex);
   1942  1.1  brad 			if (error) {
   1943  1.1  brad 				break;
   1944  1.1  brad 			}
   1945  1.1  brad 		}
   1946  1.1  brad 	}
   1947  1.1  brad 
   1948  1.1  brad 	DPRINTF(sc,2, ("%s: loop done: %d\n",device_xname(sc->sc_dev),error));
   1949  1.1  brad 	if (sc->sc_dying) {
   1950  1.1  brad 		DPRINTF(sc, 2, ("%s: Telling all we are almost dead\n",
   1951  1.1  brad 		    device_xname(sc->sc_dev)));
   1952  1.1  brad 		mutex_enter(&sc->sc_dying_mutex);
   1953  1.1  brad 		cv_signal(&sc->sc_cond_dying);
   1954  1.1  brad 		mutex_exit(&sc->sc_dying_mutex);
   1955  1.1  brad 	}
   1956  1.1  brad 	return error;
   1957  1.1  brad }
   1958  1.1  brad 
   1959  1.1  brad static int
   1960  1.1  brad sht3xclose(dev_t dev, int flags, int fmt, struct lwp *l)
   1961  1.1  brad {
   1962  1.1  brad 	struct sht3x_sc *sc;
   1963  1.1  brad 	struct sht3x_read_q *pp;
   1964  1.1  brad 
   1965  1.1  brad 	sc = device_lookup_private(&sht3xtemp_cd, minor(dev));
   1966  1.1  brad 
   1967  1.1  brad 	if (sc->sc_wassingleshot) {
   1968  1.1  brad 		sht3x_stop_thread(sc);
   1969  1.1  brad 		sc->sc_stopping = false;
   1970  1.1  brad 		sc->sc_initperiodic = false;
   1971  1.1  brad 		sc->sc_isperiodic = false;
   1972  1.1  brad 	}
   1973  1.1  brad 
   1974  1.1  brad 	mutex_enter(&sc->sc_mutex);
   1975  1.1  brad 	/* Drain any read pools */
   1976  1.1  brad 	while ((pp = SIMPLEQ_FIRST(&sc->sc_read_queue)) != NULL) {
   1977  1.1  brad 		SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q);
   1978  1.1  brad 		pool_cache_put(sc->sc_readpool,pp);
   1979  1.1  brad 	}
   1980  1.1  brad 
   1981  1.1  brad 	/* Say that the device is now free */
   1982  1.1  brad 	sc->sc_opened = false;
   1983  1.1  brad 	mutex_exit(&sc->sc_mutex);
   1984  1.1  brad 
   1985  1.1  brad 	return(0);
   1986  1.1  brad }
   1987  1.1  brad 
   1988  1.1  brad static int
   1989  1.1  brad sht3x_detach(device_t self, int flags)
   1990  1.1  brad {
   1991  1.1  brad 	struct sht3x_sc *sc;
   1992  1.1  brad 	struct sht3x_read_q *pp;
   1993  1.1  brad 
   1994  1.1  brad 	sc = device_private(self);
   1995  1.1  brad 
   1996  1.1  brad 	if (sc->sc_isperiodic) {
   1997  1.1  brad 		sht3x_stop_thread(sc);
   1998  1.1  brad 	}
   1999  1.1  brad 
   2000  1.1  brad 	mutex_enter(&sc->sc_mutex);
   2001  1.1  brad 
   2002  1.1  brad 	sc->sc_dying = true;
   2003  1.1  brad 
   2004  1.1  brad 	/* If this is true we are still open, destroy the condvar */
   2005  1.1  brad 	if (sc->sc_opened) {
   2006  1.1  brad 		mutex_enter(&sc->sc_dying_mutex);
   2007  1.1  brad 		mutex_enter(&sc->sc_read_mutex);
   2008  1.1  brad 		cv_signal(&sc->sc_condreadready);
   2009  1.1  brad 		mutex_exit(&sc->sc_read_mutex);
   2010  1.1  brad 		DPRINTF(sc, 2, ("%s: Will wait for anything to exit\n",
   2011  1.1  brad 		    device_xname(sc->sc_dev)));
   2012  1.1  brad 		cv_timedwait_sig(&sc->sc_cond_dying,&sc->sc_dying_mutex,mstohz(5000));
   2013  1.1  brad 		mutex_exit(&sc->sc_dying_mutex);
   2014  1.1  brad 		cv_destroy(&sc->sc_condreadready);
   2015  1.1  brad 		cv_destroy(&sc->sc_cond_dying);
   2016  1.1  brad 	}
   2017  1.1  brad 
   2018  1.1  brad 	/* Drain any read pools */
   2019  1.1  brad 	while ((pp = SIMPLEQ_FIRST(&sc->sc_read_queue)) != NULL) {
   2020  1.1  brad 		SIMPLEQ_REMOVE_HEAD(&sc->sc_read_queue, read_q);
   2021  1.1  brad 		pool_cache_put(sc->sc_readpool,pp);
   2022  1.1  brad 	}
   2023  1.1  brad 
   2024  1.1  brad 	/* Destroy the pool cache now that nothing is using it */
   2025  1.1  brad 	pool_cache_destroy(sc->sc_readpool);
   2026  1.1  brad 
   2027  1.1  brad 	/* Remove the sensors */
   2028  1.1  brad 	if (sc->sc_sme != NULL) {
   2029  1.1  brad 		sysmon_envsys_unregister(sc->sc_sme);
   2030  1.1  brad 		sc->sc_sme = NULL;
   2031  1.1  brad 	}
   2032  1.1  brad 	mutex_exit(&sc->sc_mutex);
   2033  1.1  brad 
   2034  1.1  brad 	/* Remove the sysctl tree */
   2035  1.1  brad 	sysctl_teardown(&sc->sc_sht3xlog);
   2036  1.1  brad 
   2037  1.1  brad 	/* Remove the mutex */
   2038  1.1  brad 	mutex_destroy(&sc->sc_mutex);
   2039  1.1  brad 	mutex_destroy(&sc->sc_threadmutex);
   2040  1.1  brad 	mutex_destroy(&sc->sc_read_mutex);
   2041  1.1  brad 	mutex_destroy(&sc->sc_dying_mutex);
   2042  1.1  brad 
   2043  1.1  brad 	/* Free the poolname string */
   2044  1.1  brad         if (sc->sc_readpoolname != NULL) {
   2045  1.1  brad                 kmem_free(sc->sc_readpoolname,strlen(sc->sc_readpoolname) + 1);
   2046  1.1  brad         }
   2047  1.1  brad 
   2048  1.1  brad 	return 0;
   2049  1.1  brad }
   2050  1.1  brad 
   2051  1.1  brad int
   2052  1.1  brad sht3x_activate(device_t self, enum devact act)
   2053  1.1  brad {
   2054  1.1  brad 	struct sht3x_sc *sc = device_private(self);
   2055  1.1  brad 
   2056  1.1  brad 	switch (act) {
   2057  1.1  brad 	case DVACT_DEACTIVATE:
   2058  1.1  brad 		sc->sc_dying = true;
   2059  1.1  brad 		return 0;
   2060  1.1  brad 	default:
   2061  1.1  brad 		return EOPNOTSUPP;
   2062  1.1  brad 	}
   2063  1.1  brad }
   2064  1.1  brad 
   2065  1.1  brad MODULE(MODULE_CLASS_DRIVER, sht3xtemp, "i2cexec,sysmon_envsys");
   2066  1.1  brad 
   2067  1.1  brad #ifdef _MODULE
   2068  1.1  brad #include "ioconf.c"
   2069  1.1  brad #endif
   2070  1.1  brad 
   2071  1.1  brad static int
   2072  1.1  brad sht3xtemp_modcmd(modcmd_t cmd, void *opaque)
   2073  1.1  brad {
   2074  1.1  brad 	int error;
   2075  1.1  brad #ifdef _MODULE
   2076  1.1  brad 	int bmaj = -1, cmaj = -1;
   2077  1.1  brad #endif
   2078  1.1  brad 
   2079  1.1  brad 	switch (cmd) {
   2080  1.1  brad 	case MODULE_CMD_INIT:
   2081  1.1  brad #ifdef _MODULE
   2082  1.1  brad 		error = config_init_component(cfdriver_ioconf_sht3xtemp,
   2083  1.1  brad 		    cfattach_ioconf_sht3xtemp, cfdata_ioconf_sht3xtemp);
   2084  1.1  brad 		if (error)
   2085  1.1  brad 			aprint_error("%s: unable to init component\n",
   2086  1.1  brad 			    sht3xtemp_cd.cd_name);
   2087  1.1  brad 
   2088  1.1  brad 		error = devsw_attach("sht3xtemp", NULL, &bmaj,
   2089  1.1  brad 		    &sht3x_cdevsw, &cmaj);
   2090  1.1  brad 		if (error) {
   2091  1.1  brad 			aprint_error("%s: unable to attach devsw\n",
   2092  1.1  brad 			    sht3xtemp_cd.cd_name);
   2093  1.1  brad 			config_fini_component(cfdriver_ioconf_sht3xtemp,
   2094  1.1  brad 			    cfattach_ioconf_sht3xtemp, cfdata_ioconf_sht3xtemp);
   2095  1.1  brad 		}
   2096  1.1  brad 		return error;
   2097  1.1  brad #else
   2098  1.1  brad 		return 0;
   2099  1.1  brad #endif
   2100  1.1  brad 	case MODULE_CMD_FINI:
   2101  1.1  brad #ifdef _MODULE
   2102  1.1  brad 		devsw_detach(NULL, &sht3x_cdevsw);
   2103  1.1  brad 		return config_fini_component(cfdriver_ioconf_sht3xtemp,
   2104  1.1  brad 		      cfattach_ioconf_sht3xtemp, cfdata_ioconf_sht3xtemp);
   2105  1.1  brad #else
   2106  1.1  brad 		return 0;
   2107  1.1  brad #endif
   2108  1.1  brad 	default:
   2109  1.1  brad 		return ENOTTY;
   2110  1.1  brad 	}
   2111  1.1  brad }
   2112