summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Yurchenko <grange@cvs.openbsd.org>2006-10-08 21:12:52 +0000
committerAlexander Yurchenko <grange@cvs.openbsd.org>2006-10-08 21:12:52 +0000
commite34e5b0d103acd2a140183ca2bd84aaede787303 (patch)
tree49d49eb338ac8ddc4fc912baa4f990e60293f819
parent6ba975deb33fa023a726a86ada7698e93993a558 (diff)
Rework bus scanning code so that most of work could be offloaded
the hardware. And fix another bug in the search algorithm.
-rw-r--r--sys/dev/onewire/onewire.c157
-rw-r--r--sys/dev/onewire/onewirevar.h4
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 <grange@openbsd.org>
@@ -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 <grange@openbsd.org>
@@ -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