diff options
Diffstat (limited to 'sys/dev/onewire')
-rw-r--r-- | sys/dev/onewire/Makefile | 7 | ||||
-rw-r--r-- | sys/dev/onewire/devlist2h.awk | 55 | ||||
-rw-r--r-- | sys/dev/onewire/files.onewire | 20 | ||||
-rw-r--r-- | sys/dev/onewire/onewire.c | 452 | ||||
-rw-r--r-- | sys/dev/onewire/onewire_bitbang.c | 77 | ||||
-rw-r--r-- | sys/dev/onewire/onewire_subr.c | 112 | ||||
-rw-r--r-- | sys/dev/onewire/onewiredevs | 31 | ||||
-rw-r--r-- | sys/dev/onewire/onewirereg.h | 72 | ||||
-rw-r--r-- | sys/dev/onewire/onewirevar.h | 86 | ||||
-rw-r--r-- | sys/dev/onewire/owid.c | 117 | ||||
-rw-r--r-- | sys/dev/onewire/owtemp.c | 167 |
11 files changed, 1196 insertions, 0 deletions
diff --git a/sys/dev/onewire/Makefile b/sys/dev/onewire/Makefile new file mode 100644 index 00000000000..269c4d22368 --- /dev/null +++ b/sys/dev/onewire/Makefile @@ -0,0 +1,7 @@ +# $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..fdb8357d9bf --- /dev/null +++ b/sys/dev/onewire/devlist2h.awk @@ -0,0 +1,55 @@ +# $OpenBSD: devlist2h.awk,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. +# + +BEGIN { + hfile = "onewiredevs.h" + dfile = "onewiredevs_data.h" +} + +NR == 1 { + VERSION = $0 + gsub("\\$", "", VERSION) + + printf("/*\t$OpenBSD: devlist2h.awk,v 1.1 2006/03/04 16:27:03 grange Exp $\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$OpenBSD: devlist2h.awk,v 1.1 2006/03/04 16:27:03 grange Exp $\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_familytab[] = {\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..682dcc4be73 --- /dev/null +++ b/sys/dev/onewire/files.onewire @@ -0,0 +1,20 @@ +# $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 + +# ID family type device +device owid +attach owid at onewire +file dev/onewire/owid.c owid + +# Temperature family type device +device owtemp +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..27144f5844e --- /dev/null +++ b/sys/dev/onewire/onewire.c @@ -0,0 +1,452 @@ +/* $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. + */ + +/* + * 1-Wire bus driver. + */ + +#include <sys/param.h> +#include <sys/systm.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_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 *, void *, 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 *); + +struct cfattach onewire_ca = { + sizeof(struct onewire_softc), + onewire_match, + onewire_attach, + onewire_detach, + onewire_activate +}; + +struct cfdriver onewire_cd = { + NULL, "onewire", DV_DULL +}; + +int +onewire_match(struct device *parent, void *match, void *aux) +{ + struct cfdata *cf = match; + + return (strcmp(cf->cf_driver->cd_name, "onewire") == 0); +} + +void +onewire_attach(struct device *parent, struct device *self, void *aux) +{ + struct onewire_softc *sc = (struct onewire_softc *)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_deferred(onewire_createthread, sc); +} + +int +onewire_detach(struct device *self, int flags) +{ + struct onewire_softc *sc = (struct onewire_softc *)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); + onewire_unlock(sc); + + return (rv); +} + +int +onewire_activate(struct device *self, enum devact act) +{ + struct onewire_softc *sc = (struct onewire_softc *)self; + + switch (act) { + case DVACT_ACTIVATE: + break; + case DVACT_DEACTIVATE: + sc->sc_dying = 1; + break; + } + + return (config_activate_children(self, act)); +} + +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", 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_create(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; + + 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; i < 64; i++) { + dir = (lastrom >> i) & 0x1; + if (i == i0) + dir = !dir; + rv = onewire_triplet(sc, dir); + switch (rv) { + case 0x0: + if (i != i0) { + 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); + } + 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 != TAILQ_END(&sc->sc_dev); 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..348fb67c4f1 --- /dev/null +++ b/sys/dev/onewire/onewire_bitbang.c @@ -0,0 +1,77 @@ +/* $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. + */ + +/* + * 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, 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, 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..4ff79e5d0b5 --- /dev/null +++ b/sys/dev/onewire/onewiredevs @@ -0,0 +1,31 @@ +$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 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/owid.c b/sys/dev/onewire/owid.c new file mode 100644 index 00000000000..21fdb9e8b3c --- /dev/null +++ b/sys/dev/onewire/owid.c @@ -0,0 +1,117 @@ +/* $OpenBSD: owid.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 ID family type device driver. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/sensors.h> + +#include <dev/onewire/onewiredevs.h> +#include <dev/onewire/onewirereg.h> +#include <dev/onewire/onewirevar.h> + +struct owid_softc { + struct device sc_dev; + + void * sc_onewire; + u_int64_t sc_rom; + + struct sensor sc_sensor; + + int sc_dying; +}; + +int owid_match(struct device *, void *, void *); +void owid_attach(struct device *, struct device *, void *); +int owid_detach(struct device *, int); +int owid_activate(struct device *, enum devact); + +struct cfattach owid_ca = { + sizeof(struct owid_softc), + owid_match, + owid_attach, + owid_detach, + owid_activate +}; + +struct cfdriver owid_cd = { + NULL, "owid", DV_DULL +}; + +static const struct onewire_matchfam owid_fams[] = { + { ONEWIRE_FAMILY_DS1990 } +}; + +int +owid_match(struct device *parent, void *match, void *aux) +{ + return (onewire_matchbyfam(aux, owid_fams, + sizeof(owid_fams) /sizeof(owid_fams[0]))); +} + +void +owid_attach(struct device *parent, struct device *self, void *aux) +{ + struct owid_softc *sc = (struct owid_softc *)self; + struct onewire_attach_args *oa = aux; + + sc->sc_onewire = oa->oa_onewire; + sc->sc_rom = oa->oa_rom; + + /* Initialize sensor */ + strlcpy(sc->sc_sensor.device, sc->sc_dev.dv_xname, + sizeof(sc->sc_sensor.device)); + sc->sc_sensor.type = SENSOR_INTEGER; + strlcpy(sc->sc_sensor.desc, "ID", sizeof(sc->sc_sensor.desc)); + sc->sc_sensor.value = ONEWIRE_ROM_SN(sc->sc_rom); + sensor_add(&sc->sc_sensor); + + printf("\n"); +} + +int +owid_detach(struct device *self, int flags) +{ + struct owid_softc *sc = (struct owid_softc *)self; + + sensor_del(&sc->sc_sensor); + + return (0); +} + +int +owid_activate(struct device *self, enum devact act) +{ + struct owid_softc *sc = (struct owid_softc *)self; + + switch (act) { + case DVACT_ACTIVATE: + return (EOPNOTSUPP); + case DVACT_DEACTIVATE: + sc->sc_dying = 1; + break; + } + + return (0); +} diff --git a/sys/dev/onewire/owtemp.c b/sys/dev/onewire/owtemp.c new file mode 100644 index 00000000000..1fd5b673881 --- /dev/null +++ b/sys/dev/onewire/owtemp.c @@ -0,0 +1,167 @@ +/* $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/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/sensors.h> + +#include <dev/onewire/onewiredevs.h> +#include <dev/onewire/onewirereg.h> +#include <dev/onewire/onewirevar.h> + +#define DS1920_CMD_CONVERT 0x44 +#define DS1920_CMD_READ_SCRATCHPAD 0xbe + +struct owtemp_softc { + struct device sc_dev; + + void * sc_onewire; + u_int64_t sc_rom; + + struct sensor sc_sensor; + + int sc_dying; +}; + +int owtemp_match(struct device *, void *, 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 *); + +struct cfattach owtemp_ca = { + sizeof(struct owtemp_softc), + owtemp_match, + owtemp_attach, + owtemp_detach, + owtemp_activate +}; + +struct cfdriver owtemp_cd = { + NULL, "owtemp", DV_DULL +}; + +static const struct onewire_matchfam owtemp_fams[] = { + { ONEWIRE_FAMILY_DS1920 } +}; + +int +owtemp_match(struct device *parent, void *match, 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 = (struct owtemp_softc *)self; + struct onewire_attach_args *oa = aux; + + sc->sc_onewire = oa->oa_onewire; + sc->sc_rom = oa->oa_rom; + + /* Initialize sensor */ + 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); + + printf("\n"); +} + +int +owtemp_detach(struct device *self, int flags) +{ + struct owtemp_softc *sc = (struct owtemp_softc *)self; + + sensor_del(&sc->sc_sensor); + sensor_task_unregister(sc); + + return (0); +} + +int +owtemp_activate(struct device *self, enum devact act) +{ + struct owtemp_softc *sc = (struct owtemp_softc *)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, DS1920_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, DS1920_CMD_READ_SCRATCHPAD); + onewire_read_block(sc->sc_onewire, data, 9); + if (onewire_crc(data, 8) == data[8]) { + sc->sc_sensor.value = 273150000 + + (int)((u_int16_t)data[1] << 8 | data[0]) * 500000; + } + +done: + onewire_unlock(sc->sc_onewire); +} |