summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorriz <riz@NetBSD.org>2006-04-07 18:55:21 +0000
committerriz <riz@NetBSD.org>2006-04-07 18:55:21 +0000
commit637bfc29f9b717579ac32fb830009fc467e5f862 (patch)
treed61cab55f51d45c366edc296049c13b38f1f039b /sys/dev
parent5b93dbb4b1a333f52258aad7f780efd30bee936f (diff)
Dallas Semiconductor 1-Wire bus support, from OpenBSD. Currently includes
gpioow(4), attaching a bit-banging driver via a GPIO pin. Also, owtemp(4) which supports some of the 1-Wire temperature sensors, including the DS18b20 and DS1920 - temperatures are returned via the envsys(4) framework. Original drivers by Alexander Yurchenko (grange@openbsd), with envsys(4) support and a fix to the 1-wire search algorithm (for discovering devices on the bus) by me. As discussed on tech-kern earlier this week.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/gpio/files.gpio6
-rw-r--r--sys/dev/gpio/gpioow.c240
-rw-r--r--sys/dev/onewire/Makefile.onewiredevs8
-rw-r--r--sys/dev/onewire/devlist2h.awk56
-rw-r--r--sys/dev/onewire/files.onewire15
-rw-r--r--sys/dev/onewire/onewire.c462
-rw-r--r--sys/dev/onewire/onewire_bitbang.c81
-rw-r--r--sys/dev/onewire/onewire_subr.c112
-rw-r--r--sys/dev/onewire/onewiredevs34
-rw-r--r--sys/dev/onewire/onewiredevs.h20
-rw-r--r--sys/dev/onewire/onewiredevs_data.h23
-rw-r--r--sys/dev/onewire/onewirereg.h72
-rw-r--r--sys/dev/onewire/onewirevar.h86
-rw-r--r--sys/dev/onewire/owtemp.c294
14 files changed, 1508 insertions, 1 deletions
diff --git a/sys/dev/gpio/files.gpio b/sys/dev/gpio/files.gpio
index 0798a5c7e0f..61131a3b531 100644
--- a/sys/dev/gpio/files.gpio
+++ b/sys/dev/gpio/files.gpio
@@ -1,7 +1,11 @@
-# $NetBSD: files.gpio,v 1.3 2006/02/20 03:18:36 riz Exp $
+# $NetBSD: files.gpio,v 1.4 2006/04/07 18:55:21 riz Exp $
define gpio {offset, mask}
device gpio: gpio
attach gpio at gpiobus
file dev/gpio/gpio.c gpio needs-flag
+
+device gpioow: onewirebus, onewire_bitbang
+attach gpioow at gpio
+file dev/gpio/gpioow.c gpioow
diff --git a/sys/dev/gpio/gpioow.c b/sys/dev/gpio/gpioow.c
new file mode 100644
index 00000000000..035ec82b414
--- /dev/null
+++ b/sys/dev/gpio/gpioow.c
@@ -0,0 +1,240 @@
+/* $NetBSD: gpioow.c,v 1.1 2006/04/07 18:55:21 riz Exp $ */
+/* $OpenBSD: gpioow.c,v 1.1 2006/03/04 16:27:03 grange Exp $ */
+
+/*
+ * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: gpioow.c,v 1.1 2006/04/07 18:55:21 riz Exp $");
+
+/*
+ * 1-Wire bus bit-banging through GPIO pin.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/gpio.h>
+
+#include <dev/gpio/gpiovar.h>
+
+#include <dev/onewire/onewirevar.h>
+
+#define GPIOOW_NPINS 1
+#define GPIOOW_PIN_DATA 0
+
+struct gpioow_softc {
+ struct device sc_dev;
+
+ void * sc_gpio;
+ struct gpio_pinmap sc_map;
+ int __map[GPIOOW_NPINS];
+
+ struct onewire_bus sc_ow_bus;
+ struct device * sc_ow_dev;
+
+ int sc_data;
+ int sc_dying;
+};
+
+int gpioow_match(struct device *, struct cfdata *, void *);
+void gpioow_attach(struct device *, struct device *, void *);
+int gpioow_detach(struct device *, int);
+int gpioow_activate(struct device *, enum devact);
+
+int gpioow_ow_reset(void *);
+int gpioow_ow_bit(void *, int);
+
+void gpioow_bb_rx(void *);
+void gpioow_bb_tx(void *);
+int gpioow_bb_get(void *);
+void gpioow_bb_set(void *, int);
+
+CFATTACH_DECL(gpioow, sizeof(struct gpioow_softc),
+ gpioow_match, gpioow_attach, gpioow_detach, gpioow_activate);
+
+extern struct cfdriver gpioow_cd;
+
+static const struct onewire_bbops gpioow_bbops = {
+ gpioow_bb_rx,
+ gpioow_bb_tx,
+ gpioow_bb_get,
+ gpioow_bb_set
+};
+
+int
+gpioow_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+ return 1;
+}
+
+void
+gpioow_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct gpioow_softc *sc = device_private(self);
+ struct gpio_attach_args *ga = aux;
+ struct onewirebus_attach_args oba;
+ int caps;
+
+ /* Check that we have enough pins */
+ if (gpio_npins(ga->ga_mask) != GPIOOW_NPINS) {
+ printf(": invalid pin mask\n");
+ return;
+ }
+
+ /* Map pins */
+ sc->sc_gpio = ga->ga_gpio;
+ sc->sc_map.pm_map = sc->__map;
+ if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask,
+ &sc->sc_map)) {
+ printf(": can't map pins\n");
+ return;
+ }
+
+ /* Configure data pin */
+ caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA);
+ if (!(caps & GPIO_PIN_OUTPUT)) {
+ printf(": data pin is unable to drive output\n");
+ goto fail;
+ }
+ if (!(caps & GPIO_PIN_INPUT)) {
+ printf(": data pin is unable to read input\n");
+ goto fail;
+ }
+ printf(": DATA[%d]", sc->sc_map.pm_map[GPIOOW_PIN_DATA]);
+ sc->sc_data = GPIO_PIN_OUTPUT;
+ if (caps & GPIO_PIN_OPENDRAIN) {
+ printf(" open-drain");
+ sc->sc_data |= GPIO_PIN_OPENDRAIN;
+ } else if ((caps & GPIO_PIN_PUSHPULL) && (caps & GPIO_PIN_TRISTATE)) {
+ printf(" push-pull tri-state");
+ sc->sc_data |= GPIO_PIN_PUSHPULL;
+ }
+ if (caps & GPIO_PIN_PULLUP) {
+ printf(" pull-up");
+ sc->sc_data |= GPIO_PIN_PULLUP;
+ }
+ gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA, sc->sc_data);
+
+ printf("\n");
+
+ /* Attach 1-Wire bus */
+ sc->sc_ow_bus.bus_cookie = sc;
+ sc->sc_ow_bus.bus_reset = gpioow_ow_reset;
+ sc->sc_ow_bus.bus_bit = gpioow_ow_bit;
+
+ bzero(&oba, sizeof(oba));
+ oba.oba_bus = &sc->sc_ow_bus;
+ sc->sc_ow_dev = config_found(self, &oba, onewirebus_print);
+
+ return;
+
+fail:
+ gpio_pin_unmap(sc->sc_gpio, &sc->sc_map);
+}
+
+int
+gpioow_detach(struct device *self, int flags)
+{
+ struct gpioow_softc *sc = device_private(self);
+ int rv = 0;
+
+ if (sc->sc_ow_dev != NULL)
+ rv = config_detach(sc->sc_ow_dev, flags);
+
+ return (rv);
+}
+
+int
+gpioow_activate(struct device *self, enum devact act)
+{
+ struct gpioow_softc *sc = device_private(self);
+ int rv = 0;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return (EOPNOTSUPP);
+ case DVACT_DEACTIVATE:
+ sc->sc_dying = 1;
+ if (sc->sc_ow_dev != NULL)
+ rv = config_deactivate(sc->sc_ow_dev);
+ break;
+ }
+
+ return (rv);
+}
+
+int
+gpioow_ow_reset(void *arg)
+{
+ return (onewire_bb_reset(&gpioow_bbops, arg));
+}
+
+int
+gpioow_ow_bit(void *arg, int value)
+{
+ return (onewire_bb_bit(&gpioow_bbops, arg, value));
+}
+
+void
+gpioow_bb_rx(void *arg)
+{
+ struct gpioow_softc *sc = arg;
+ int data = sc->sc_data;
+
+ data &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
+ data |= GPIO_PIN_INPUT;
+ if (data & GPIO_PIN_PUSHPULL)
+ data |= GPIO_PIN_TRISTATE;
+ if (sc->sc_data != data) {
+ sc->sc_data = data;
+ gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA,
+ sc->sc_data);
+ }
+}
+
+void
+gpioow_bb_tx(void *arg)
+{
+ struct gpioow_softc *sc = arg;
+ int data = sc->sc_data;
+
+ data &= ~(GPIO_PIN_INPUT | GPIO_PIN_OUTPUT | GPIO_PIN_TRISTATE);
+ data |= GPIO_PIN_OUTPUT;
+ if (sc->sc_data != data) {
+ sc->sc_data = data;
+ gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA,
+ sc->sc_data);
+ }
+}
+
+int
+gpioow_bb_get(void *arg)
+{
+ struct gpioow_softc *sc = arg;
+
+ return (gpio_pin_read(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA) ==
+ GPIO_PIN_HIGH ? 1 : 0);
+}
+
+void
+gpioow_bb_set(void *arg, int value)
+{
+ struct gpioow_softc *sc = arg;
+
+ gpio_pin_write(sc->sc_gpio, &sc->sc_map, GPIOOW_PIN_DATA,
+ value ? GPIO_PIN_HIGH : GPIO_PIN_LOW);
+}
diff --git a/sys/dev/onewire/Makefile.onewiredevs b/sys/dev/onewire/Makefile.onewiredevs
new file mode 100644
index 00000000000..e3861bcd546
--- /dev/null
+++ b/sys/dev/onewire/Makefile.onewiredevs
@@ -0,0 +1,8 @@
+# $NetBSD: Makefile.onewiredevs,v 1.1 2006/04/07 18:55:22 riz Exp $
+# $OpenBSD: Makefile,v 1.1 2006/03/04 16:27:03 grange Exp $
+
+AWK?= awk
+
+onewiredevs.h onewiredevs_data.h: onewiredevs devlist2h.awk
+ /bin/rm -f onewiredevs.h onewiredevs_data.h
+ ${AWK} -f devlist2h.awk onewiredevs
diff --git a/sys/dev/onewire/devlist2h.awk b/sys/dev/onewire/devlist2h.awk
new file mode 100644
index 00000000000..149af6e0b23
--- /dev/null
+++ b/sys/dev/onewire/devlist2h.awk
@@ -0,0 +1,56 @@
+# $NetBSD: devlist2h.awk,v 1.1 2006/04/07 18:55:22 riz Exp $
+# $OpenBSD: devlist2h.awk,v 1.3 2006/03/10 14:36:32 grange Exp $
+
+#
+# Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
+#
+# Permission to use, copy, modify, and distribute this software for any
+# purpose with or without fee is hereby granted, provided that the above
+# copyright notice and this permission notice appear in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+#
+
+BEGIN {
+ hfile = "onewiredevs.h"
+ dfile = "onewiredevs_data.h"
+}
+
+NR == 1 {
+ VERSION = $0
+ gsub("\\$", "", VERSION)
+
+ printf("/*\t\$NetBSD\$\t*/\n\n" \
+ "/*\n * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n" \
+ " *\n * Generated from:\n *\t%s\n */\n\n", VERSION) > hfile
+ printf("/*\t\$NetBSD\$\t*/\n\n" \
+ "/*\n * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.\n" \
+ " *\n * Generated from:\n *\t%s\n */\n\n", VERSION) > dfile
+ printf("static const struct onewire_family " \
+ "onewire_famtab[] = {\n") > dfile
+}
+
+$1 == "family" {
+ printf("#define ONEWIRE_FAMILY_%s\t%s\n", toupper($2), $3) > hfile
+ printf("\t{ ONEWIRE_FAMILY_%s, \"", toupper($2)) > dfile
+
+ f = 4
+ while (f <= NF) {
+ if (f > 4)
+ printf(" ") > dfile
+ printf("%s", $f) > dfile
+ f++
+ }
+ printf("\" },\n") > dfile
+ next
+}
+
+END {
+ printf("\t{ 0, NULL }\n};\n") > dfile
+}
diff --git a/sys/dev/onewire/files.onewire b/sys/dev/onewire/files.onewire
new file mode 100644
index 00000000000..6dc17462822
--- /dev/null
+++ b/sys/dev/onewire/files.onewire
@@ -0,0 +1,15 @@
+# $OpenBSD: files.onewire,v 1.1 2006/03/04 16:27:03 grange Exp $
+
+define onewire {}
+
+device onewire: onewire
+attach onewire at onewirebus
+file dev/onewire/onewire.c onewire
+file dev/onewire/onewire_subr.c onewire
+
+file dev/onewire/onewire_bitbang.c onewire_bitbang
+
+# Temperature family type device
+device owtemp: sysmon_envsys
+attach owtemp at onewire
+file dev/onewire/owtemp.c owtemp
diff --git a/sys/dev/onewire/onewire.c b/sys/dev/onewire/onewire.c
new file mode 100644
index 00000000000..b87656790a2
--- /dev/null
+++ b/sys/dev/onewire/onewire.c
@@ -0,0 +1,462 @@
+/* $NetBSD: onewire.c,v 1.1 2006/04/07 18:55:22 riz Exp $ */
+/* $OpenBSD: onewire.c,v 1.1 2006/03/04 16:27:03 grange Exp $ */
+
+/*
+ * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: onewire.c,v 1.1 2006/04/07 18:55:22 riz Exp $");
+
+/*
+ * 1-Wire bus driver.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/conf.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/queue.h>
+
+#include <dev/onewire/onewirereg.h>
+#include <dev/onewire/onewirevar.h>
+
+#ifdef ONEWIRE_DEBUG
+#define DPRINTF(x) printf x
+#else
+#define DPRINTF(x)
+#endif
+
+//#define ONEWIRE_MAXDEVS 256
+#define ONEWIRE_MAXDEVS 8
+#define ONEWIRE_SCANTIME 3
+
+struct onewire_softc {
+ struct device sc_dev;
+
+ struct onewire_bus * sc_bus;
+ struct lock sc_lock;
+ struct proc * sc_thread;
+ TAILQ_HEAD(, onewire_device) sc_devs;
+
+ int sc_dying;
+};
+
+struct onewire_device {
+ TAILQ_ENTRY(onewire_device) d_list;
+ struct device * d_dev;
+ u_int64_t d_rom;
+ int d_present;
+};
+
+int onewire_match(struct device *, struct cfdata *, void *);
+void onewire_attach(struct device *, struct device *, void *);
+int onewire_detach(struct device *, int);
+int onewire_activate(struct device *, enum devact);
+int onewire_print(void *, const char *);
+
+void onewire_thread(void *);
+void onewire_createthread(void *);
+void onewire_scan(struct onewire_softc *);
+
+CFATTACH_DECL(onewire, sizeof(struct onewire_softc),
+ onewire_match, onewire_attach, onewire_detach, onewire_activate);
+
+const struct cdevsw onewire_cdevsw = {
+ noopen, noclose, noread, nowrite, noioctl, nostop, notty,
+ nopoll, nommap, nokqfilter,
+};
+
+extern struct cfdriver onewire_cd;
+
+int
+onewire_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+ return 1;
+}
+
+void
+onewire_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct onewire_softc *sc = device_private(self);
+ struct onewirebus_attach_args *oba = aux;
+
+ sc->sc_bus = oba->oba_bus;
+ lockinit(&sc->sc_lock, PRIBIO, "owlock", 0, 0);
+ TAILQ_INIT(&sc->sc_devs);
+
+ printf("\n");
+
+ kthread_create(onewire_createthread, sc);
+}
+
+int
+onewire_detach(struct device *self, int flags)
+{
+ struct onewire_softc *sc = device_private(self);
+ int rv;
+
+ sc->sc_dying = 1;
+ if (sc->sc_thread != NULL) {
+ wakeup(sc->sc_thread);
+ tsleep(&sc->sc_dying, PWAIT, "owdt", 0);
+ }
+
+ onewire_lock(sc, 0);
+ //rv = config_detach_children(self, flags);
+ rv = 0; /* XXX riz */
+ onewire_unlock(sc);
+
+ return (rv);
+}
+
+int
+onewire_activate(struct device *self, enum devact act)
+{
+ struct onewire_softc *sc = device_private(self);
+ int rv = 0;
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ rv = EOPNOTSUPP;
+ break;
+ case DVACT_DEACTIVATE:
+ sc->sc_dying = 1;
+ break;
+ }
+
+ //return (config_activate_children(self, act));
+ return rv;
+}
+
+int
+onewire_print(void *aux, const char *pnp)
+{
+ struct onewire_attach_args *oa = aux;
+ const char *famname;
+
+ if (pnp == NULL)
+ printf(" ");
+
+ famname = onewire_famname(ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
+ if (famname == NULL)
+ printf("family 0x%02x", (uint)ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
+ else
+ printf("\"%s\"", famname);
+ printf(" sn %012llx", ONEWIRE_ROM_SN(oa->oa_rom));
+
+ if (pnp != NULL)
+ printf(" at %s", pnp);
+
+ return (UNCONF);
+}
+
+int
+onewirebus_print(void *aux, const char *pnp)
+{
+ if (pnp != NULL)
+ printf("onewire at %s", pnp);
+
+ return (UNCONF);
+}
+
+int
+onewire_lock(void *arg, int flags)
+{
+ struct onewire_softc *sc = arg;
+ int lflags = LK_EXCLUSIVE;
+
+ if (flags & ONEWIRE_NOWAIT)
+ lflags |= LK_NOWAIT;
+
+ return (lockmgr(&sc->sc_lock, lflags, NULL));
+}
+
+void
+onewire_unlock(void *arg)
+{
+ struct onewire_softc *sc = arg;
+
+ lockmgr(&sc->sc_lock, LK_RELEASE, NULL);
+}
+
+int
+onewire_reset(void *arg)
+{
+ struct onewire_softc *sc = arg;
+ struct onewire_bus *bus = sc->sc_bus;
+
+ return (bus->bus_reset(bus->bus_cookie));
+}
+
+int
+onewire_bit(void *arg, int value)
+{
+ struct onewire_softc *sc = arg;
+ struct onewire_bus *bus = sc->sc_bus;
+
+ return (bus->bus_bit(bus->bus_cookie, value));
+}
+
+int
+onewire_read_byte(void *arg)
+{
+ struct onewire_softc *sc = arg;
+ struct onewire_bus *bus = sc->sc_bus;
+ u_int8_t value = 0;
+ int i;
+
+ if (bus->bus_read_byte != NULL)
+ return (bus->bus_read_byte(bus->bus_cookie));
+
+ for (i = 0; i < 8; i++)
+ value |= (bus->bus_bit(bus->bus_cookie, 1) << i);
+
+ return (value);
+}
+
+void
+onewire_write_byte(void *arg, int value)
+{
+ struct onewire_softc *sc = arg;
+ struct onewire_bus *bus = sc->sc_bus;
+ int i;
+
+ if (bus->bus_write_byte != NULL)
+ return (bus->bus_write_byte(bus->bus_cookie, value));
+
+ for (i = 0; i < 8; i++)
+ bus->bus_bit(bus->bus_cookie, (value >> i) & 0x1);
+}
+
+int
+onewire_triplet(void *arg, int dir)
+{
+ struct onewire_softc *sc = arg;
+ struct onewire_bus *bus = sc->sc_bus;
+ int rv;
+
+ if (bus->bus_triplet != NULL)
+ return (bus->bus_triplet(bus->bus_cookie, dir));
+
+ rv = bus->bus_bit(bus->bus_cookie, 1);
+ rv <<= 1;
+ rv |= bus->bus_bit(bus->bus_cookie, 1);
+
+ switch (rv) {
+ case 0x0:
+ bus->bus_bit(bus->bus_cookie, dir);
+ break;
+ case 0x1:
+ bus->bus_bit(bus->bus_cookie, 0);
+ break;
+ default:
+ bus->bus_bit(bus->bus_cookie, 1);
+ }
+
+ return (rv);
+}
+
+void
+onewire_read_block(void *arg, void *buf, int len)
+{
+ u_int8_t *p = buf;
+
+ while (len--)
+ *p++ = onewire_read_byte(arg);
+}
+
+void
+onewire_write_block(void *arg, const void *buf, int len)
+{
+ const u_int8_t *p = buf;
+
+ while (len--)
+ onewire_write_byte(arg, *p++);
+}
+
+void
+onewire_matchrom(void *arg, u_int64_t rom)
+{
+ int i;
+
+ onewire_write_byte(arg, ONEWIRE_CMD_MATCH_ROM);
+ for (i = 0; i < 8; i++)
+ onewire_write_byte(arg, (rom >> (i * 8)) & 0xff);
+}
+
+void
+onewire_thread(void *arg)
+{
+ struct onewire_softc *sc = arg;
+
+ while (!sc->sc_dying) {
+ onewire_scan(sc);
+ tsleep(sc->sc_thread, PWAIT, "owidle", ONEWIRE_SCANTIME * hz);
+ }
+
+ sc->sc_thread = NULL;
+ wakeup(&sc->sc_dying);
+ kthread_exit(0);
+}
+
+void
+onewire_createthread(void *arg)
+{
+ struct onewire_softc *sc = arg;
+
+ if (kthread_create1(onewire_thread, sc, &sc->sc_thread,
+ "%s", sc->sc_dev.dv_xname) != 0)
+ printf("%s: can't create kernel thread\n",
+ sc->sc_dev.dv_xname);
+}
+
+void
+onewire_scan(struct onewire_softc *sc)
+{
+ struct onewire_device *d, *next, *nd;
+ struct onewire_attach_args oa;
+ struct device *dev;
+ int search = 1, count = 0, present;
+ int dir, rv;
+ u_int64_t mask, rom = 0, lastrom;
+ u_int8_t data[8];
+ int i, i0 = -1, lastd = -1;
+
+ TAILQ_FOREACH(d, &sc->sc_devs, d_list)
+ d->d_present = 0;
+
+ while (search && count++ < ONEWIRE_MAXDEVS) {
+ /* XXX: yield processor */
+ tsleep(sc, PWAIT, "owscan", hz / 10);
+
+ /*
+ * Reset the bus. If there's no presence pulse
+ * don't search for any devices.
+ */
+ onewire_lock(sc, 0);
+ if (onewire_reset(sc) != 0) {
+ DPRINTF(("%s: scan: no presence pulse\n",
+ sc->sc_dev.dv_xname));
+ onewire_unlock(sc);
+ break;
+ }
+
+ /*
+ * Start new search. Go through the previous path to
+ * the point we made a decision last time and make an
+ * opposite decision. If we didn't make any decision
+ * stop searching.
+ */
+ search = 0;
+ lastrom = rom;
+ rom = 0;
+ onewire_write_byte(sc, ONEWIRE_CMD_SEARCH_ROM);
+ for (i = 0,i0 = -1; i < 64; i++) {
+ dir = (lastrom >> i) & 0x1;
+ if (i == lastd)
+ dir = 1;
+ else if (i > lastd)
+ dir = 0;
+ rv = onewire_triplet(sc, dir);
+ switch (rv) {
+ case 0x0:
+ if (i != lastd) {
+ if (dir == 0)
+ i0 = i;
+ search = 1;
+ }
+ mask = dir;
+ break;
+ case 0x1:
+ mask = 0;
+ break;
+ case 0x2:
+ mask = 1;
+ break;
+ default:
+ DPRINTF(("%s: scan: triplet error 0x%x, "
+ "step %d\n",
+ sc->sc_dev.dv_xname, rv, i));
+ onewire_unlock(sc);
+ return;
+ }
+ rom |= (mask << i);
+ }
+ lastd = i0;
+ onewire_unlock(sc);
+
+ if (rom == 0)
+ continue;
+
+ /*
+ * The last byte of the ROM code contains a CRC calculated
+ * from the first 7 bytes. Re-calculate it to make sure
+ * we found a valid device.
+ */
+ for (i = 0; i < 8; i++)
+ data[i] = (rom >> (i * 8)) & 0xff;
+ if (onewire_crc(data, 7) != data[7])
+ continue;
+
+ /*
+ * Go through the list of attached devices to see if we
+ * found a new one.
+ */
+ present = 0;
+ TAILQ_FOREACH(d, &sc->sc_devs, d_list) {
+ if (d->d_rom == rom) {
+ d->d_present = 1;
+ present = 1;
+ break;
+ }
+ }
+ if (!present) {
+ bzero(&oa, sizeof(oa));
+ oa.oa_onewire = sc;
+ oa.oa_rom = rom;
+ if ((dev = config_found(&sc->sc_dev, &oa,
+ onewire_print)) == NULL)
+ continue;
+
+ MALLOC(nd, struct onewire_device *,
+ sizeof(struct onewire_device), M_DEVBUF, M_NOWAIT);
+ if (nd == NULL)
+ continue;
+ nd->d_dev = dev;
+ nd->d_rom = rom;
+ nd->d_present = 1;
+ TAILQ_INSERT_TAIL(&sc->sc_devs, nd, d_list);
+ }
+ }
+
+ /* Detach disappeared devices */
+ onewire_lock(sc, 0);
+ for (d = TAILQ_FIRST(&sc->sc_devs);
+ d != NULL; d = next) {
+ next = TAILQ_NEXT(d, d_list);
+ if (!d->d_present) {
+ config_detach(d->d_dev, DETACH_FORCE);
+ TAILQ_REMOVE(&sc->sc_devs, d, d_list);
+ FREE(d, M_DEVBUF);
+ }
+ }
+ onewire_unlock(sc);
+}
diff --git a/sys/dev/onewire/onewire_bitbang.c b/sys/dev/onewire/onewire_bitbang.c
new file mode 100644
index 00000000000..5ebc7459566
--- /dev/null
+++ b/sys/dev/onewire/onewire_bitbang.c
@@ -0,0 +1,81 @@
+/* $NetBSD: onewire_bitbang.c,v 1.1 2006/04/07 18:55:22 riz Exp $ */
+/* $OpenBSD: onewire_bitbang.c,v 1.1 2006/03/04 16:27:03 grange Exp $ */
+
+/*
+ * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: onewire_bitbang.c,v 1.1 2006/04/07 18:55:22 riz Exp $");
+
+/*
+ * 1-Wire bus bit-banging routines.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <dev/onewire/onewirevar.h>
+
+int
+onewire_bb_reset(const struct onewire_bbops *ops, void *arg)
+{
+ int s, rv = 0, i;
+
+ s = splhigh();
+ ops->bb_tx(arg);
+ ops->bb_set(arg, 0);
+ DELAY(480);
+ ops->bb_set(arg, 1);
+ ops->bb_rx(arg);
+ DELAY(30);
+ for (i = 0; i < 6; i++) {
+ if ((rv = ops->bb_get(arg)) == 0)
+ break;
+ DELAY(20);
+ }
+ DELAY(450);
+ splx(s);
+
+ return (rv);
+}
+
+int
+onewire_bb_bit(const struct onewire_bbops *ops, void *arg, int value)
+{
+ int s, rv = 0, i;
+
+ s = splhigh();
+ ops->bb_tx(arg);
+ ops->bb_set(arg, 0);
+ DELAY(2);
+ if (value) {
+ ops->bb_set(arg, 1);
+ ops->bb_rx(arg);
+ for (i = 0; i < 15; i++) {
+ if ((rv = ops->bb_get(arg)) == 0)
+ break;
+ DELAY(2);
+ }
+ ops->bb_tx(arg);
+ }
+ DELAY(60);
+ ops->bb_set(arg, 1);
+ DELAY(5);
+ splx(s);
+
+ return (rv);
+}
diff --git a/sys/dev/onewire/onewire_subr.c b/sys/dev/onewire/onewire_subr.c
new file mode 100644
index 00000000000..f20e4913914
--- /dev/null
+++ b/sys/dev/onewire/onewire_subr.c
@@ -0,0 +1,112 @@
+/* $OpenBSD: onewire_subr.c,v 1.1 2006/03/04 16:27:03 grange Exp $ */
+
+/*
+ * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * 1-Wire bus miscellaneous routines.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <dev/onewire/onewiredevs.h>
+#include <dev/onewire/onewirereg.h>
+#include <dev/onewire/onewirevar.h>
+
+#ifdef ONEWIREVERBOSE
+struct onewire_family {
+ int of_type;
+ const char * of_name;
+};
+#include <dev/onewire/onewiredevs_data.h>
+#endif
+
+static const u_int8_t crctable[] = {
+ 0x00, 0x5e, 0xbc, 0xe2, 0x61, 0x3f, 0xdd, 0x83,
+ 0xc2, 0x9c, 0x7e, 0x20, 0xa3, 0xfd, 0x1f, 0x41,
+ 0x9d, 0xc3, 0x21, 0x7f, 0xfc, 0xa2, 0x40, 0x1e,
+ 0x5f, 0x01, 0xe3, 0xbd, 0x3e, 0x60, 0x82, 0xdc,
+ 0x23, 0x7d, 0x9f, 0xc1, 0x42, 0x1c, 0xfe, 0xa0,
+ 0xe1, 0xbf, 0x5d, 0x03, 0x80, 0xde, 0x3c, 0x62,
+ 0xbe, 0xe0, 0x02, 0x5c, 0xdf, 0x81, 0x63, 0x3d,
+ 0x7c, 0x22, 0xc0, 0x9e, 0x1d, 0x43, 0xa1, 0xff,
+ 0x46, 0x18, 0xfa, 0xa4, 0x27, 0x79, 0x9b, 0xc5,
+ 0x84, 0xda, 0x38, 0x66, 0xe5, 0xbb, 0x59, 0x07,
+ 0xdb, 0x85, 0x67, 0x39, 0xba, 0xe4, 0x06, 0x58,
+ 0x19, 0x47, 0xa5, 0xfb, 0x78, 0x26, 0xc4, 0x9a,
+ 0x65, 0x3b, 0xd9, 0x87, 0x04, 0x5a, 0xb8, 0xe6,
+ 0xa7, 0xf9, 0x1b, 0x45, 0xc6, 0x98, 0x7a, 0x24,
+ 0xf8, 0xa6, 0x44, 0x1a, 0x99, 0xc7, 0x25, 0x7b,
+ 0x3a, 0x64, 0x86, 0xd8, 0x5b, 0x05, 0xe7, 0xb9,
+ 0x8c, 0xd2, 0x30, 0x6e, 0xed, 0xb3, 0x51, 0x0f,
+ 0x4e, 0x10, 0xf2, 0xac, 0x2f, 0x71, 0x93, 0xcd,
+ 0x11, 0x4f, 0xad, 0xf3, 0x70, 0x2e, 0xcc, 0x92,
+ 0xd3, 0x8d, 0x6f, 0x31, 0xb2, 0xec, 0x0e, 0x50,
+ 0xaf, 0xf1, 0x13, 0x4d, 0xce, 0x90, 0x72, 0x2c,
+ 0x6d, 0x33, 0xd1, 0x8f, 0x0c, 0x52, 0xb0, 0xee,
+ 0x32, 0x6c, 0x8e, 0xd0, 0x53, 0x0d, 0xef, 0xb1,
+ 0xf0, 0xae, 0x4c, 0x12, 0x91, 0xcf, 0x2d, 0x73,
+ 0xca, 0x94, 0x76, 0x28, 0xab, 0xf5, 0x17, 0x49,
+ 0x08, 0x56, 0xb4, 0xea, 0x69, 0x37, 0xd5, 0x8b,
+ 0x57, 0x09, 0xeb, 0xb5, 0x36, 0x68, 0x8a, 0xd4,
+ 0x95, 0xcb, 0x29, 0x77, 0xf4, 0xaa, 0x48, 0x16,
+ 0xe9, 0xb7, 0x55, 0x0b, 0x88, 0xd6, 0x34, 0x6a,
+ 0x2b, 0x75, 0x97, 0xc9, 0x4a, 0x14, 0xf6, 0xa8,
+ 0x74, 0x2a, 0xc8, 0x96, 0x15, 0x4b, 0xa9, 0xf7,
+ 0xb6, 0xe8, 0x0a, 0x54, 0xd7, 0x89, 0x6b, 0x35
+};
+
+int
+onewire_crc(const void *buf, int len)
+{
+ const u_int8_t *p = buf;
+ u_int8_t crc = 0;
+
+ while (len--)
+ crc = crctable[crc ^ *p++];
+
+ return (crc);
+}
+
+const char *
+onewire_famname(int type)
+{
+#ifdef ONEWIREVERBOSE
+ const struct onewire_family *of;
+
+ for (of = onewire_famtab; of->of_name != NULL; of++)
+ if (of->of_type == type)
+ return (of->of_name);
+#endif
+
+ return (NULL);
+}
+
+int
+onewire_matchbyfam(struct onewire_attach_args *oa,
+ const struct onewire_matchfam *fams, int nent)
+{
+ const struct onewire_matchfam *om;
+ int i;
+
+ for (i = 0, om = fams; i < nent; i++, om++)
+ if (ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom) == om->om_type)
+ return (1);
+
+ return (0);
+}
diff --git a/sys/dev/onewire/onewiredevs b/sys/dev/onewire/onewiredevs
new file mode 100644
index 00000000000..129f8021ba4
--- /dev/null
+++ b/sys/dev/onewire/onewiredevs
@@ -0,0 +1,34 @@
+$NetBSD: onewiredevs,v 1.1 2006/04/07 18:55:22 riz Exp $
+/* $OpenBSD: onewiredevs,v 1.1 2006/03/04 16:27:03 grange Exp $ */
+
+/*
+ * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * List of known 1-Wire family types.
+ */
+
+family DS1990 0x01 ID
+family DS1991 0x02 MultiKey
+family DS1994 0x04 4kb NVRAM + RTC
+family DS1993 0x06 4kb NVRAM
+family DS1992 0x08 1kb NVRAM
+family DS1982 0x09 1kb EPROM
+family DS1995 0x0a 16kb NVRAM
+family DS1996 0x0c 64kb NVRAM
+family DS1920 0x10 Temperature
+family DS1822 0x22 Temperature
+family DS18B20 0x28 Temperature
diff --git a/sys/dev/onewire/onewiredevs.h b/sys/dev/onewire/onewiredevs.h
new file mode 100644
index 00000000000..2e09ce65d0f
--- /dev/null
+++ b/sys/dev/onewire/onewiredevs.h
@@ -0,0 +1,20 @@
+/* $NetBSD: onewiredevs.h,v 1.1 2006/04/07 18:55:22 riz Exp $ */
+
+/*
+ * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
+ *
+ * Generated from:
+ * NetBSD
+ */
+
+#define ONEWIRE_FAMILY_DS1990 0x01
+#define ONEWIRE_FAMILY_DS1991 0x02
+#define ONEWIRE_FAMILY_DS1994 0x04
+#define ONEWIRE_FAMILY_DS1993 0x06
+#define ONEWIRE_FAMILY_DS1992 0x08
+#define ONEWIRE_FAMILY_DS1982 0x09
+#define ONEWIRE_FAMILY_DS1995 0x0a
+#define ONEWIRE_FAMILY_DS1996 0x0c
+#define ONEWIRE_FAMILY_DS1920 0x10
+#define ONEWIRE_FAMILY_DS1822 0x22
+#define ONEWIRE_FAMILY_DS18B20 0x28
diff --git a/sys/dev/onewire/onewiredevs_data.h b/sys/dev/onewire/onewiredevs_data.h
new file mode 100644
index 00000000000..4f1a1d2fe68
--- /dev/null
+++ b/sys/dev/onewire/onewiredevs_data.h
@@ -0,0 +1,23 @@
+/* $NetBSD: onewiredevs_data.h,v 1.1 2006/04/07 18:55:22 riz Exp $ */
+
+/*
+ * THIS FILE AUTOMATICALLY GENERATED. DO NOT EDIT.
+ *
+ * Generated from:
+ * NetBSD
+ */
+
+static const struct onewire_family onewire_famtab[] = {
+ { ONEWIRE_FAMILY_DS1990, "ID" },
+ { ONEWIRE_FAMILY_DS1991, "MultiKey" },
+ { ONEWIRE_FAMILY_DS1994, "4kb NVRAM + RTC" },
+ { ONEWIRE_FAMILY_DS1993, "4kb NVRAM" },
+ { ONEWIRE_FAMILY_DS1992, "1kb NVRAM" },
+ { ONEWIRE_FAMILY_DS1982, "1kb EPROM" },
+ { ONEWIRE_FAMILY_DS1995, "16kb NVRAM" },
+ { ONEWIRE_FAMILY_DS1996, "64kb NVRAM" },
+ { ONEWIRE_FAMILY_DS1920, "Temperature" },
+ { ONEWIRE_FAMILY_DS1822, "Temperature" },
+ { ONEWIRE_FAMILY_DS18B20, "Temperature" },
+ { 0, NULL }
+};
diff --git a/sys/dev/onewire/onewirereg.h b/sys/dev/onewire/onewirereg.h
new file mode 100644
index 00000000000..6462e8db696
--- /dev/null
+++ b/sys/dev/onewire/onewirereg.h
@@ -0,0 +1,72 @@
+/* $OpenBSD: onewirereg.h,v 1.1 2006/03/04 16:27:03 grange Exp $ */
+
+/*
+ * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DEV_ONEWIRE_ONEWIREREG_H_
+#define _DEV_ONEWIRE_ONEWIREREG_H_
+
+/*
+ * 1-Wire bus protocol definitions.
+ */
+
+/*
+ * 64-bit ROM section.
+ */
+
+/* Family code */
+#define ONEWIRE_ROM_FAMILY(x) ((x) & 0xff)
+#define ONEWIRE_ROM_FAMILY_TYPE(x) ((x) & 0x7f)
+#define ONEWIRE_ROM_FAMILY_CUSTOM(x) (((x) >> 7) & 0x1)
+
+/* Serial number */
+#define ONEWIRE_ROM_SN(x) (((x) >> 8) & 0xffffffffffffULL)
+
+/* CRC */
+#define ONEWIRE_ROM_CRC(x) (((x) >> 56) & 0xff)
+
+/*
+ * Command set.
+ */
+
+/* ROM commands */
+#define ONEWIRE_CMD_READ_ROM 0x33
+#define ONEWIRE_CMD_SKIP_ROM 0xcc
+#define ONEWIRE_CMD_MATCH_ROM 0x55
+#define ONEWIRE_CMD_SEARCH_ROM 0xf0
+#define ONEWIRE_CMD_OVERDRIVE_SKIP_ROM 0x3c
+#define ONEWIRE_CMD_OVERDRIVE_MATCH_ROM 0x69
+
+/* Scratchpad commands */
+#define ONEWIRE_CMD_READ_SCRATCHPAD 0xaa
+#define ONEWIRE_CMD_WRITE_SCRATCHPAD 0x0f
+#define ONEWIRE_CMD_COPY_SCRATCHPAD 0x55
+
+/* Memory commands */
+#define ONEWIRE_CMD_READ_MEMORY 0xf0
+#define ONEWIRE_CMD_WRITE_MEMORY 0x0f
+#define ONEWIRE_CMD_EXT_READ_MEMORY 0xa5
+
+/* Password commands */
+#define ONEWIRE_CMD_READ_SUBKEY 0x66
+#define ONEWIRE_CMD_WRITE_SUBKEY 0x99
+#define ONEWIRE_CMD_WRITE_PASSWORD 0x5a
+
+/* Status commands */
+#define ONEWIRE_CMD_READ_STATUS 0xaa
+#define ONEWIRE_CMD_WRITE_STATUS 0x55
+
+#endif /* !_DEV_ONEWIRE_ONEWIREREG_H_ */
diff --git a/sys/dev/onewire/onewirevar.h b/sys/dev/onewire/onewirevar.h
new file mode 100644
index 00000000000..51b7ea4a434
--- /dev/null
+++ b/sys/dev/onewire/onewirevar.h
@@ -0,0 +1,86 @@
+/* $OpenBSD: onewirevar.h,v 1.1 2006/03/04 16:27:03 grange Exp $ */
+
+/*
+ * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _DEV_ONEWIRE_ONEWIREVAR_H_
+#define _DEV_ONEWIRE_ONEWIREVAR_H_
+
+/*
+ * 1-Wire bus interface.
+ */
+
+/* Bus master interface */
+struct onewire_bus {
+ void * bus_cookie;
+
+ int (*bus_reset)(void *);
+ int (*bus_bit)(void *, int);
+ int (*bus_read_byte)(void *);
+ void (*bus_write_byte)(void *, int);
+ int (*bus_triplet)(void *, int);
+};
+
+/* Bus methods */
+int onewire_lock(void *, int);
+void onewire_unlock(void *);
+int onewire_reset(void *);
+int onewire_bit(void *, int);
+int onewire_read_byte(void *);
+void onewire_write_byte(void *, int);
+int onewire_triplet(void *, int);
+void onewire_read_block(void *, void *, int);
+void onewire_write_block(void *, const void *, int);
+void onewire_matchrom(void *, u_int64_t);
+
+#define ONEWIRE_NOWAIT 0x0001
+
+/* Bus attachment */
+struct onewirebus_attach_args {
+ struct onewire_bus * oba_bus;
+};
+
+int onewirebus_print(void *, const char *);
+
+/* Device attachment */
+struct onewire_attach_args {
+ void * oa_onewire;
+ u_int64_t oa_rom;
+};
+
+/* Family matching */
+struct onewire_matchfam {
+ int om_type;
+};
+
+/* Miscellaneous routines */
+int onewire_crc(const void *, int);
+const char * onewire_famname(int);
+int onewire_matchbyfam(struct onewire_attach_args *,
+ const struct onewire_matchfam *, int);
+
+/* Bus bit-banging */
+struct onewire_bbops {
+ void (*bb_rx)(void *);
+ void (*bb_tx)(void *);
+ int (*bb_get)(void *);
+ void (*bb_set)(void *, int);
+};
+
+int onewire_bb_reset(const struct onewire_bbops *, void *);
+int onewire_bb_bit(const struct onewire_bbops *, void *, int);
+
+#endif /* !_DEV_ONEWIRE_ONEWIREVAR_H_ */
diff --git a/sys/dev/onewire/owtemp.c b/sys/dev/onewire/owtemp.c
new file mode 100644
index 00000000000..a00bc6da476
--- /dev/null
+++ b/sys/dev/onewire/owtemp.c
@@ -0,0 +1,294 @@
+/* $NetBSD */
+/* $OpenBSD: owtemp.c,v 1.1 2006/03/04 16:27:03 grange Exp $ */
+
+/*
+ * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * 1-Wire temperature family type device driver.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/proc.h>
+
+#include <dev/sysmon/sysmonvar.h>
+
+#include <dev/onewire/onewiredevs.h>
+#include <dev/onewire/onewirereg.h>
+#include <dev/onewire/onewirevar.h>
+
+#define DS_CMD_CONVERT 0x44
+#define DS_CMD_READ_SCRATCHPAD 0xbe
+
+struct owtemp_softc {
+ struct device sc_dev;
+
+ void * sc_onewire;
+ u_int64_t sc_rom;
+
+ struct envsys_tre_data sc_sensor[1];
+ struct envsys_basic_info sc_info[1];
+
+ struct sysmon_envsys sc_sysmon;
+
+ uint32_t (*sc_owtemp_decode)(const uint8_t *);
+
+ int sc_dying;
+};
+
+int owtemp_match(struct device *, struct cfdata *, void *);
+void owtemp_attach(struct device *, struct device *, void *);
+int owtemp_detach(struct device *, int);
+int owtemp_activate(struct device *, enum devact);
+
+void owtemp_update(void *);
+
+CFATTACH_DECL(owtemp, sizeof(struct owtemp_softc),
+ owtemp_match, owtemp_attach, owtemp_detach, owtemp_activate);
+
+extern struct cfdriver owtemp_cd;
+
+static const struct onewire_matchfam owtemp_fams[] = {
+ { ONEWIRE_FAMILY_DS1920 },
+ { ONEWIRE_FAMILY_DS18B20 },
+ { ONEWIRE_FAMILY_DS1822 },
+};
+
+static const struct envsys_range owtemp_ranges[] = {
+ { 0, 1, ENVSYS_STEMP },
+ { 1, 0, -1 },
+};
+
+static int owtemp_gtredata(struct sysmon_envsys *,
+ struct envsys_tre_data *);
+static int owtemp_streinfo(struct sysmon_envsys *,
+ struct envsys_basic_info *);
+
+static uint32_t owtemp_decode_ds18b20(const uint8_t *);
+static uint32_t owtemp_decode_ds1920(const uint8_t *);
+
+int
+owtemp_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+ return (onewire_matchbyfam(aux, owtemp_fams,
+ sizeof(owtemp_fams) /sizeof(owtemp_fams[0])));
+}
+
+void
+owtemp_attach(struct device *parent, struct device *self, void *aux)
+{
+ struct owtemp_softc *sc = device_private(self);
+ struct onewire_attach_args *oa = aux;
+ int ptype;
+
+ sc->sc_onewire = oa->oa_onewire;
+ sc->sc_rom = oa->oa_rom;
+
+ switch(ONEWIRE_ROM_FAMILY_TYPE(sc->sc_rom)) {
+ case ONEWIRE_FAMILY_DS18B20:
+ case ONEWIRE_FAMILY_DS1822:
+ sc->sc_owtemp_decode = owtemp_decode_ds18b20;
+ break;
+ case ONEWIRE_FAMILY_DS1920:
+ sc->sc_owtemp_decode = owtemp_decode_ds1920;
+ break;
+ }
+
+ /* Initialize sensor */
+ sc->sc_sensor[0].sensor = sc->sc_info[0].sensor = 0;
+ sc->sc_sensor[0].validflags = ENVSYS_FVALID;
+ sc->sc_info[0].validflags = ENVSYS_FVALID;
+ sc->sc_sensor[0].warnflags = ENVSYS_WARN_OK;
+
+ sc->sc_sensor[0].units = sc->sc_info[0].units = ENVSYS_STEMP;
+ if (devprop_get(&sc->sc_dev, "description",
+ sc->sc_info[0].desc, sizeof(sc->sc_info[0].desc),
+ &ptype) < 1 ||
+ ptype != PROP_STRING)
+ strcpy(sc->sc_info[0].desc, sc->sc_dev.dv_xname);
+
+ /* Hook into system monitor. */
+ sc->sc_sysmon.sme_ranges = owtemp_ranges;
+ sc->sc_sysmon.sme_sensor_info = sc->sc_info;
+ sc->sc_sysmon.sme_sensor_data = sc->sc_sensor;
+ sc->sc_sysmon.sme_cookie = sc;
+
+ sc->sc_sysmon.sme_gtredata = owtemp_gtredata;
+ sc->sc_sysmon.sme_streinfo = owtemp_streinfo;
+
+ sc->sc_sysmon.sme_nsensors = 1;
+ sc->sc_sysmon.sme_envsys_version = 1000;
+
+ if (sysmon_envsys_register(&sc->sc_sysmon))
+ aprint_error("%s: unable to register with sysmon\n",
+ sc->sc_dev.dv_xname);
+
+#if 0 /* Old OpenBSD code */
+ strlcpy(sc->sc_sensor.device, sc->sc_dev.dv_xname,
+ sizeof(sc->sc_sensor.device));
+ sc->sc_sensor.type = SENSOR_TEMP;
+ strlcpy(sc->sc_sensor.desc, "Temp", sizeof(sc->sc_sensor.desc));
+
+ if (sensor_task_register(sc, owtemp_update, 5)) {
+ printf(": unable to register update task\n");
+ return;
+ }
+ sensor_add(&sc->sc_sensor);
+#endif
+
+ printf("\n");
+}
+
+int
+owtemp_detach(struct device *self, int flags)
+{
+ struct owtemp_softc *sc = device_private(self);
+
+ sysmon_envsys_unregister(&sc->sc_sysmon);
+
+ return 0;
+}
+
+int
+owtemp_activate(struct device *self, enum devact act)
+{
+ struct owtemp_softc *sc = device_private(self);
+
+ switch (act) {
+ case DVACT_ACTIVATE:
+ return (EOPNOTSUPP);
+ case DVACT_DEACTIVATE:
+ sc->sc_dying = 1;
+ break;
+ }
+
+ return (0);
+}
+
+void
+owtemp_update(void *arg)
+{
+ struct owtemp_softc *sc = arg;
+ u_int8_t data[9];
+
+ onewire_lock(sc->sc_onewire, 0);
+ if (onewire_reset(sc->sc_onewire) != 0)
+ goto done;
+ onewire_matchrom(sc->sc_onewire, sc->sc_rom);
+
+ /*
+ * Start temperature conversion. The conversion takes up to 750ms.
+ * After sending the command, the data line must be held high for
+ * at least 750ms to provide power during the conversion process.
+ * As such, no other activity may take place on the 1-Wire bus for
+ * at least this period.
+ */
+ onewire_write_byte(sc->sc_onewire, DS_CMD_CONVERT);
+ tsleep(sc, PRIBIO, "owtemp", hz);
+
+ if (onewire_reset(sc->sc_onewire) != 0)
+ goto done;
+ onewire_matchrom(sc->sc_onewire, sc->sc_rom);
+
+ /*
+ * The result of the temperature measurement is placed in the
+ * first two bytes of the scratchpad.
+ */
+ onewire_write_byte(sc->sc_onewire, DS_CMD_READ_SCRATCHPAD);
+ onewire_read_block(sc->sc_onewire, data, 9);
+#if 0
+ if (onewire_crc(data, 8) == data[8]) {
+ sc->sc_sensor.value = 273150000 +
+ (int)((u_int16_t)data[1] << 8 | data[0]) * 500000;
+ }
+#endif
+
+ sc->sc_sensor[0].cur.data_us = sc->sc_owtemp_decode(data);
+ sc->sc_sensor[0].validflags |= ENVSYS_FCURVALID;
+
+done:
+ onewire_unlock(sc->sc_onewire);
+}
+
+static int
+owtemp_gtredata(struct sysmon_envsys *sme, struct envsys_tre_data *tred)
+{
+ struct owtemp_softc *sc = sme->sme_cookie;
+
+ owtemp_update(sc);
+ *tred = sc->sc_sensor[tred->sensor];
+
+ return 0;
+}
+
+static int
+owtemp_streinfo(struct sysmon_envsys *sme, struct envsys_basic_info *binfo)
+{
+ struct owtemp_softc *sc = sme->sme_cookie;
+
+ onewire_lock(sc->sc_onewire,0); /* Also locks our instance */
+
+ memcpy(sc->sc_info[binfo->sensor].desc, binfo->desc,
+ sizeof(sc->sc_info[binfo->sensor].desc));
+ sc->sc_info[binfo->sensor].desc[
+ sizeof(sc->sc_info[binfo->sensor].desc) - 1] = '\0';
+
+ onewire_unlock(sc->sc_onewire);
+
+ binfo->validflags = ENVSYS_FVALID;
+
+ return 0;
+}
+
+static uint32_t
+owtemp_decode_ds18b20(const uint8_t *buf)
+{
+ int temp;
+
+ /*
+ * Sign-extend the MSB byte, and add in the fractions of a
+ * degree contained in the LSB (precision 1/16th DegC).
+ */
+ temp = (int8_t)buf[1];
+ temp = (temp << 8) | buf[0];
+
+ /*
+ * Conversion to uK is simple.
+ */
+ return (temp * 62500 + 273150000);
+}
+
+static uint32_t
+owtemp_decode_ds1920(const uint8_t *buf)
+{
+ int temp;
+
+ /*
+ * Sign-extend the MSB byte, and add in the fractions of a
+ * degree contained in the LSB (precision 1/2 DegC).
+ */
+ temp = (int8_t)buf[1];
+ temp = (temp << 8) | buf[0];
+
+ /* Convert to uK */
+ return (temp * 500000 + 273150000);
+}