From e34e5b0d103acd2a140183ca2bd84aaede787303 Mon Sep 17 00:00:00 2001 From: Alexander Yurchenko Date: Sun, 8 Oct 2006 21:12:52 +0000 Subject: Rework bus scanning code so that most of work could be offloaded the hardware. And fix another bug in the search algorithm. --- sys/dev/onewire/onewire.c | 157 +++++++++++++++++++++++++------------------ sys/dev/onewire/onewirevar.h | 4 +- 2 files changed, 93 insertions(+), 68 deletions(-) diff --git a/sys/dev/onewire/onewire.c b/sys/dev/onewire/onewire.c index 9b914bf099e..8a417e36332 100644 --- a/sys/dev/onewire/onewire.c +++ b/sys/dev/onewire/onewire.c @@ -1,4 +1,4 @@ -/* $OpenBSD: onewire.c,v 1.6 2006/09/30 17:45:31 grange Exp $ */ +/* $OpenBSD: onewire.c,v 1.7 2006/10/08 21:12:51 grange Exp $ */ /* * Copyright (c) 2006 Alexander Yurchenko @@ -51,6 +51,7 @@ struct onewire_softc { TAILQ_HEAD(, onewire_device) sc_devs; int sc_dying; + u_int64_t sc_rombuf[ONEWIRE_MAXDEVS]; }; struct onewire_device { @@ -109,7 +110,6 @@ 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) { @@ -117,11 +117,7 @@ onewire_detach(struct device *self, int flags) tsleep(&sc->sc_dying, PWAIT, "owdt", 0); } - onewire_lock(sc, 0); - rv = config_detach_children(self, flags); - onewire_unlock(sc); - - return (rv); + return (config_detach_children(self, flags)); } int @@ -311,72 +307,32 @@ onewire_matchrom(void *arg, u_int64_t rom) 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) +int +onewire_search(void *arg, u_int64_t *buf, int size, u_int64_t startrom) { 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; + struct onewire_bus *bus = sc->sc_bus; + int search = 1, count = 0, lastd = -1, dir, rv, i, i0; + u_int64_t mask, rom = startrom, lastrom; u_int8_t data[8]; - int i, i0, lastd = -1; - TAILQ_FOREACH(d, &sc->sc_devs, d_list) - d->d_present = 0; + if (bus->bus_search != NULL) + return (bus->bus_search(bus->bus_cookie, buf, size, rom)); - while (search && count++ < ONEWIRE_MAXDEVS) { + while (search && count < size) { /* 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_lock(sc, 0); + onewire_reset(sc); onewire_write_byte(sc, ONEWIRE_CMD_SEARCH_ROM); for (i = 0, i0 = -1; i < 64; i++) { dir = (lastrom >> i) & 0x1; @@ -387,11 +343,8 @@ onewire_scan(struct onewire_softc *sc) rv = onewire_triplet(sc, dir); switch (rv) { case 0x0: - if (i != lastd) { - if (dir == 0) - i0 = i; - search = 1; - } + if (i != lastd && dir == 0) + i0 = i; mask = dir; break; case 0x1: @@ -401,17 +354,19 @@ onewire_scan(struct onewire_softc *sc) mask = 1; break; default: - DPRINTF(("%s: scan: triplet error 0x%x, " + DPRINTF(("%s: search triplet error 0x%x, " "step %d\n", sc->sc_dev.dv_xname, rv, i)); onewire_unlock(sc); - return; + return (-1); } rom |= (mask << i); } - lastd = i0; onewire_unlock(sc); + if ((lastd = i0) == -1) + search = 0; + if (rom == 0) continue; @@ -425,6 +380,75 @@ onewire_scan(struct onewire_softc *sc) if (onewire_crc(data, 7) != data[7]) continue; + buf[count++] = rom; + } + + return (count); +} + +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 present; + u_int64_t rom; + int i, rv; + + /* + * Mark all currently present devices as absent before + * scanning. This allows to find out later which devices + * have been disappeared. + */ + TAILQ_FOREACH(d, &sc->sc_devs, d_list) + d->d_present = 0; + + /* + * Reset the bus. If there's no presence pulse don't search + * for any devices. + */ + onewire_lock(sc, 0); + rv = onewire_reset(sc); + onewire_unlock(sc); + if (rv != 0) { + DPRINTF(("%s: no presence pulse\n", sc->sc_dev.dv_xname)); + goto out; + } + + /* Scan the bus */ + if ((rv = onewire_search(sc, sc->sc_rombuf, ONEWIRE_MAXDEVS, 0)) == -1) + return; + + for (i = 0; i < rv; i++) { + rom = sc->sc_rombuf[i]; + /* * Go through the list of attached devices to see if we * found a new one. @@ -456,8 +480,8 @@ onewire_scan(struct onewire_softc *sc) } } +out: /* 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); @@ -467,5 +491,4 @@ onewire_scan(struct onewire_softc *sc) FREE(d, M_DEVBUF); } } - onewire_unlock(sc); } diff --git a/sys/dev/onewire/onewirevar.h b/sys/dev/onewire/onewirevar.h index ad75d929e4d..3aaeb3bffd3 100644 --- a/sys/dev/onewire/onewirevar.h +++ b/sys/dev/onewire/onewirevar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: onewirevar.h,v 1.3 2006/09/30 15:52:21 grange Exp $ */ +/* $OpenBSD: onewirevar.h,v 1.4 2006/10/08 21:12:51 grange Exp $ */ /* * Copyright (c) 2006 Alexander Yurchenko @@ -35,6 +35,7 @@ struct onewire_bus { void (*bus_write_block)(void *, const void *, int); int (*bus_triplet)(void *, int); void (*bus_matchrom)(void *, u_int64_t); + int (*bus_search)(void *, u_int64_t *, int, u_int64_t); }; /* Bus methods */ @@ -49,6 +50,7 @@ void onewire_read_block(void *, void *, int); void onewire_write_block(void *, const void *, int); int onewire_triplet(void *, int); void onewire_matchrom(void *, u_int64_t); +int onewire_search(void *, u_int64_t *, int, u_int64_t); #define ONEWIRE_NOWAIT 0x0001 -- cgit v1.2.3