Don't use .Xo/.Xc. Fix date format.
[netbsd-mini2440.git] / sys / dev / onewire / onewire.c
blob2b75e8ded56a3750dcc52fe4f4e9ae5b0357df2b
1 /* $NetBSD: onewire.c,v 1.12 2009/05/12 14:39:51 cegger Exp $ */
2 /* $OpenBSD: onewire.c,v 1.1 2006/03/04 16:27:03 grange Exp $ */
4 /*
5 * Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: onewire.c,v 1.12 2009/05/12 14:39:51 cegger Exp $");
24 * 1-Wire bus driver.
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/conf.h>
30 #include <sys/device.h>
31 #include <sys/kernel.h>
32 #include <sys/kthread.h>
33 #include <sys/rwlock.h>
34 #include <sys/malloc.h>
35 #include <sys/proc.h>
36 #include <sys/queue.h>
38 #include <dev/onewire/onewirereg.h>
39 #include <dev/onewire/onewirevar.h>
41 #ifdef ONEWIRE_DEBUG
42 #define DPRINTF(x) printf x
43 #else
44 #define DPRINTF(x)
45 #endif
47 //#define ONEWIRE_MAXDEVS 256
48 #define ONEWIRE_MAXDEVS 8
49 #define ONEWIRE_SCANTIME 3
51 struct onewire_softc {
52 device_t sc_dev;
54 struct onewire_bus * sc_bus;
55 krwlock_t sc_rwlock;
56 struct lwp * sc_thread;
57 TAILQ_HEAD(, onewire_device) sc_devs;
59 int sc_dying;
62 struct onewire_device {
63 TAILQ_ENTRY(onewire_device) d_list;
64 device_t d_dev;
65 u_int64_t d_rom;
66 int d_present;
69 static int onewire_match(device_t, cfdata_t, void *);
70 static void onewire_attach(device_t, device_t, void *);
71 static int onewire_detach(device_t, int);
72 static int onewire_activate(device_t, enum devact);
73 int onewire_print(void *, const char *);
75 static void onewire_thread(void *);
76 static void onewire_scan(struct onewire_softc *);
78 CFATTACH_DECL_NEW(onewire, sizeof(struct onewire_softc),
79 onewire_match, onewire_attach, onewire_detach, onewire_activate);
81 const struct cdevsw onewire_cdevsw = {
82 noopen, noclose, noread, nowrite, noioctl, nostop, notty,
83 nopoll, nommap, nokqfilter, D_OTHER,
86 extern struct cfdriver onewire_cd;
88 static int
89 onewire_match(device_t parent, cfdata_t cf, void *aux)
91 return 1;
94 static void
95 onewire_attach(device_t parent, device_t self, void *aux)
97 struct onewire_softc *sc = device_private(self);
98 struct onewirebus_attach_args *oba = aux;
100 sc->sc_dev = self;
101 sc->sc_bus = oba->oba_bus;
102 rw_init(&sc->sc_rwlock);
103 TAILQ_INIT(&sc->sc_devs);
105 aprint_naive("\n");
106 aprint_normal("\n");
108 if (kthread_create(PRI_NONE, 0, NULL, onewire_thread, sc,
109 &sc->sc_thread, "%s", device_xname(self)) != 0)
110 aprint_error_dev(self, "can't create kernel thread\n");
113 static int
114 onewire_detach(device_t self, int flags)
116 struct onewire_softc *sc = device_private(self);
117 int rv;
119 sc->sc_dying = 1;
120 if (sc->sc_thread != NULL) {
121 wakeup(sc->sc_thread);
122 tsleep(&sc->sc_dying, PWAIT, "owdt", 0);
125 onewire_lock(sc);
126 //rv = config_detach_children(self, flags);
127 rv = 0; /* XXX riz */
128 onewire_unlock(sc);
129 rw_destroy(&sc->sc_rwlock);
131 return rv;
134 static int
135 onewire_activate(device_t self, enum devact act)
137 struct onewire_softc *sc = device_private(self);
139 switch (act) {
140 case DVACT_DEACTIVATE:
141 sc->sc_dying = 1;
142 return 0;
143 default:
144 return EOPNOTSUPP;
149 onewire_print(void *aux, const char *pnp)
151 struct onewire_attach_args *oa = aux;
152 const char *famname;
154 if (pnp == NULL)
155 aprint_normal(" ");
157 famname = onewire_famname(ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
158 if (famname == NULL)
159 aprint_normal("family 0x%02x",
160 (uint)ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
161 else
162 aprint_normal("\"%s\"", famname);
163 aprint_normal(" sn %012llx", ONEWIRE_ROM_SN(oa->oa_rom));
165 if (pnp != NULL)
166 aprint_normal(" at %s", pnp);
168 return UNCONF;
172 onewirebus_print(void *aux, const char *pnp)
174 if (pnp != NULL)
175 aprint_normal("onewire at %s", pnp);
177 return UNCONF;
180 void
181 onewire_lock(void *arg)
183 struct onewire_softc *sc = arg;
185 rw_enter(&sc->sc_rwlock, RW_WRITER);
188 void
189 onewire_unlock(void *arg)
191 struct onewire_softc *sc = arg;
193 rw_exit(&sc->sc_rwlock);
197 onewire_reset(void *arg)
199 struct onewire_softc *sc = arg;
200 struct onewire_bus *bus = sc->sc_bus;
202 return bus->bus_reset(bus->bus_cookie);
206 onewire_bit(void *arg, int value)
208 struct onewire_softc *sc = arg;
209 struct onewire_bus *bus = sc->sc_bus;
211 return bus->bus_bit(bus->bus_cookie, value);
215 onewire_read_byte(void *arg)
217 struct onewire_softc *sc = arg;
218 struct onewire_bus *bus = sc->sc_bus;
219 uint8_t value = 0;
220 int i;
222 if (bus->bus_read_byte != NULL)
223 return bus->bus_read_byte(bus->bus_cookie);
225 for (i = 0; i < 8; i++)
226 value |= (bus->bus_bit(bus->bus_cookie, 1) << i);
228 return value;
231 void
232 onewire_write_byte(void *arg, int value)
234 struct onewire_softc *sc = arg;
235 struct onewire_bus *bus = sc->sc_bus;
236 int i;
238 if (bus->bus_write_byte != NULL)
239 return bus->bus_write_byte(bus->bus_cookie, value);
241 for (i = 0; i < 8; i++)
242 bus->bus_bit(bus->bus_cookie, (value >> i) & 0x1);
246 onewire_triplet(void *arg, int dir)
248 struct onewire_softc *sc = arg;
249 struct onewire_bus *bus = sc->sc_bus;
250 int rv;
252 if (bus->bus_triplet != NULL)
253 return bus->bus_triplet(bus->bus_cookie, dir);
255 rv = bus->bus_bit(bus->bus_cookie, 1);
256 rv <<= 1;
257 rv |= bus->bus_bit(bus->bus_cookie, 1);
259 switch (rv) {
260 case 0x0:
261 bus->bus_bit(bus->bus_cookie, dir);
262 break;
263 case 0x1:
264 bus->bus_bit(bus->bus_cookie, 0);
265 break;
266 default:
267 bus->bus_bit(bus->bus_cookie, 1);
270 return rv;
273 void
274 onewire_read_block(void *arg, void *buf, int len)
276 uint8_t *p = buf;
278 while (len--)
279 *p++ = onewire_read_byte(arg);
282 void
283 onewire_write_block(void *arg, const void *buf, int len)
285 const uint8_t *p = buf;
287 while (len--)
288 onewire_write_byte(arg, *p++);
291 void
292 onewire_matchrom(void *arg, u_int64_t rom)
294 int i;
296 onewire_write_byte(arg, ONEWIRE_CMD_MATCH_ROM);
297 for (i = 0; i < 8; i++)
298 onewire_write_byte(arg, (rom >> (i * 8)) & 0xff);
301 static void
302 onewire_thread(void *arg)
304 struct onewire_softc *sc = arg;
306 while (!sc->sc_dying) {
307 onewire_scan(sc);
308 tsleep(sc->sc_thread, PWAIT, "owidle", ONEWIRE_SCANTIME * hz);
311 sc->sc_thread = NULL;
312 wakeup(&sc->sc_dying);
313 kthread_exit(0);
316 static void
317 onewire_scan(struct onewire_softc *sc)
319 struct onewire_device *d, *next, *nd;
320 struct onewire_attach_args oa;
321 device_t dev;
322 int search = 1, count = 0, present;
323 int dir, rv;
324 uint64_t mask, rom = 0, lastrom;
325 uint8_t data[8];
326 int i, i0 = -1, lastd = -1;
328 TAILQ_FOREACH(d, &sc->sc_devs, d_list)
329 d->d_present = 0;
331 while (search && count++ < ONEWIRE_MAXDEVS) {
332 /* XXX: yield processor */
333 tsleep(sc, PWAIT, "owscan", hz / 10);
336 * Reset the bus. If there's no presence pulse
337 * don't search for any devices.
339 onewire_lock(sc);
340 if (onewire_reset(sc) != 0) {
341 DPRINTF(("%s: scan: no presence pulse\n",
342 device_xname(sc->sc_dev)));
343 onewire_unlock(sc);
344 break;
348 * Start new search. Go through the previous path to
349 * the point we made a decision last time and make an
350 * opposite decision. If we didn't make any decision
351 * stop searching.
353 search = 0;
354 lastrom = rom;
355 rom = 0;
356 onewire_write_byte(sc, ONEWIRE_CMD_SEARCH_ROM);
357 for (i = 0,i0 = -1; i < 64; i++) {
358 dir = (lastrom >> i) & 0x1;
359 if (i == lastd)
360 dir = 1;
361 else if (i > lastd)
362 dir = 0;
363 rv = onewire_triplet(sc, dir);
364 switch (rv) {
365 case 0x0:
366 if (i != lastd) {
367 if (dir == 0)
368 i0 = i;
369 search = 1;
371 mask = dir;
372 break;
373 case 0x1:
374 mask = 0;
375 break;
376 case 0x2:
377 mask = 1;
378 break;
379 default:
380 DPRINTF(("%s: scan: triplet error 0x%x, "
381 "step %d\n",
382 device_xname(sc->sc_dev), rv, i));
383 onewire_unlock(sc);
384 return;
386 rom |= (mask << i);
388 lastd = i0;
389 onewire_unlock(sc);
391 if (rom == 0)
392 continue;
395 * The last byte of the ROM code contains a CRC calculated
396 * from the first 7 bytes. Re-calculate it to make sure
397 * we found a valid device.
399 for (i = 0; i < 8; i++)
400 data[i] = (rom >> (i * 8)) & 0xff;
401 if (onewire_crc(data, 7) != data[7])
402 continue;
405 * Go through the list of attached devices to see if we
406 * found a new one.
408 present = 0;
409 TAILQ_FOREACH(d, &sc->sc_devs, d_list) {
410 if (d->d_rom == rom) {
411 d->d_present = 1;
412 present = 1;
413 break;
416 if (!present) {
417 memset(&oa, 0, sizeof(oa));
418 oa.oa_onewire = sc;
419 oa.oa_rom = rom;
420 if ((dev = config_found(sc->sc_dev, &oa,
421 onewire_print)) == NULL)
422 continue;
424 nd = malloc(sizeof(struct onewire_device),
425 M_DEVBUF, M_NOWAIT);
426 if (nd == NULL)
427 continue;
428 nd->d_dev = dev;
429 nd->d_rom = rom;
430 nd->d_present = 1;
431 TAILQ_INSERT_TAIL(&sc->sc_devs, nd, d_list);
435 /* Detach disappeared devices */
436 onewire_lock(sc);
437 for (d = TAILQ_FIRST(&sc->sc_devs);
438 d != NULL; d = next) {
439 next = TAILQ_NEXT(d, d_list);
440 if (!d->d_present) {
441 config_detach(d->d_dev, DETACH_FORCE);
442 TAILQ_REMOVE(&sc->sc_devs, d, d_list);
443 free(d, M_DEVBUF);
446 onewire_unlock(sc);