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