onewire.c revision 1.13 1 /* $NetBSD: onewire.c,v 1.13 2009/12/06 22:49:48 dyoung Exp $ */
2 /* $OpenBSD: onewire.c,v 1.1 2006/03/04 16:27:03 grange Exp $ */
3
4 /*
5 * Copyright (c) 2006 Alexander Yurchenko <grange (at) openbsd.org>
6 *
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.
10 *
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.
18 */
19
20 #include <sys/cdefs.h>
21 __KERNEL_RCSID(0, "$NetBSD: onewire.c,v 1.13 2009/12/06 22:49:48 dyoung Exp $");
22
23 /*
24 * 1-Wire bus driver.
25 */
26
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>
37
38 #include <dev/onewire/onewirereg.h>
39 #include <dev/onewire/onewirevar.h>
40
41 #ifdef ONEWIRE_DEBUG
42 #define DPRINTF(x) printf x
43 #else
44 #define DPRINTF(x)
45 #endif
46
47 //#define ONEWIRE_MAXDEVS 256
48 #define ONEWIRE_MAXDEVS 8
49 #define ONEWIRE_SCANTIME 3
50
51 struct onewire_softc {
52 device_t sc_dev;
53
54 struct onewire_bus * sc_bus;
55 krwlock_t sc_rwlock;
56 struct lwp * sc_thread;
57 TAILQ_HEAD(, onewire_device) sc_devs;
58
59 int sc_dying;
60 };
61
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;
67 };
68
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 *);
74
75 static void onewire_thread(void *);
76 static void onewire_scan(struct onewire_softc *);
77
78 CFATTACH_DECL_NEW(onewire, sizeof(struct onewire_softc),
79 onewire_match, onewire_attach, onewire_detach, onewire_activate);
80
81 const struct cdevsw onewire_cdevsw = {
82 noopen, noclose, noread, nowrite, noioctl, nostop, notty,
83 nopoll, nommap, nokqfilter, D_OTHER,
84 };
85
86 extern struct cfdriver onewire_cd;
87
88 static int
89 onewire_match(device_t parent, cfdata_t cf, void *aux)
90 {
91 return 1;
92 }
93
94 static void
95 onewire_attach(device_t parent, device_t self, void *aux)
96 {
97 struct onewire_softc *sc = device_private(self);
98 struct onewirebus_attach_args *oba = aux;
99
100 sc->sc_dev = self;
101 sc->sc_bus = oba->oba_bus;
102 rw_init(&sc->sc_rwlock);
103 TAILQ_INIT(&sc->sc_devs);
104
105 aprint_naive("\n");
106 aprint_normal("\n");
107
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");
111 }
112
113 static int
114 onewire_detach(device_t self, int flags)
115 {
116 struct onewire_softc *sc = device_private(self);
117 int rv;
118
119 sc->sc_dying = 1;
120 if (sc->sc_thread != NULL) {
121 wakeup(sc->sc_thread);
122 tsleep(&sc->sc_dying, PWAIT, "owdt", 0);
123 }
124
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);
130
131 return rv;
132 }
133
134 static int
135 onewire_activate(device_t self, enum devact act)
136 {
137 struct onewire_softc *sc = device_private(self);
138
139 switch (act) {
140 case DVACT_DEACTIVATE:
141 sc->sc_dying = 1;
142 return 0;
143 default:
144 return EOPNOTSUPP;
145 }
146 }
147
148 int
149 onewire_print(void *aux, const char *pnp)
150 {
151 struct onewire_attach_args *oa = aux;
152 const char *famname;
153
154 if (pnp == NULL)
155 aprint_normal(" ");
156
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));
164
165 if (pnp != NULL)
166 aprint_normal(" at %s", pnp);
167
168 return UNCONF;
169 }
170
171 int
172 onewirebus_print(void *aux, const char *pnp)
173 {
174 if (pnp != NULL)
175 aprint_normal("onewire at %s", pnp);
176
177 return UNCONF;
178 }
179
180 void
181 onewire_lock(void *arg)
182 {
183 struct onewire_softc *sc = arg;
184
185 rw_enter(&sc->sc_rwlock, RW_WRITER);
186 }
187
188 void
189 onewire_unlock(void *arg)
190 {
191 struct onewire_softc *sc = arg;
192
193 rw_exit(&sc->sc_rwlock);
194 }
195
196 int
197 onewire_reset(void *arg)
198 {
199 struct onewire_softc *sc = arg;
200 struct onewire_bus *bus = sc->sc_bus;
201
202 return bus->bus_reset(bus->bus_cookie);
203 }
204
205 int
206 onewire_bit(void *arg, int value)
207 {
208 struct onewire_softc *sc = arg;
209 struct onewire_bus *bus = sc->sc_bus;
210
211 return bus->bus_bit(bus->bus_cookie, value);
212 }
213
214 int
215 onewire_read_byte(void *arg)
216 {
217 struct onewire_softc *sc = arg;
218 struct onewire_bus *bus = sc->sc_bus;
219 uint8_t value = 0;
220 int i;
221
222 if (bus->bus_read_byte != NULL)
223 return bus->bus_read_byte(bus->bus_cookie);
224
225 for (i = 0; i < 8; i++)
226 value |= (bus->bus_bit(bus->bus_cookie, 1) << i);
227
228 return value;
229 }
230
231 void
232 onewire_write_byte(void *arg, int value)
233 {
234 struct onewire_softc *sc = arg;
235 struct onewire_bus *bus = sc->sc_bus;
236 int i;
237
238 if (bus->bus_write_byte != NULL)
239 return bus->bus_write_byte(bus->bus_cookie, value);
240
241 for (i = 0; i < 8; i++)
242 bus->bus_bit(bus->bus_cookie, (value >> i) & 0x1);
243 }
244
245 int
246 onewire_triplet(void *arg, int dir)
247 {
248 struct onewire_softc *sc = arg;
249 struct onewire_bus *bus = sc->sc_bus;
250 int rv;
251
252 if (bus->bus_triplet != NULL)
253 return bus->bus_triplet(bus->bus_cookie, dir);
254
255 rv = bus->bus_bit(bus->bus_cookie, 1);
256 rv <<= 1;
257 rv |= bus->bus_bit(bus->bus_cookie, 1);
258
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);
268 }
269
270 return rv;
271 }
272
273 void
274 onewire_read_block(void *arg, void *buf, int len)
275 {
276 uint8_t *p = buf;
277
278 while (len--)
279 *p++ = onewire_read_byte(arg);
280 }
281
282 void
283 onewire_write_block(void *arg, const void *buf, int len)
284 {
285 const uint8_t *p = buf;
286
287 while (len--)
288 onewire_write_byte(arg, *p++);
289 }
290
291 void
292 onewire_matchrom(void *arg, u_int64_t rom)
293 {
294 int i;
295
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);
299 }
300
301 static void
302 onewire_thread(void *arg)
303 {
304 struct onewire_softc *sc = arg;
305
306 while (!sc->sc_dying) {
307 onewire_scan(sc);
308 tsleep(sc->sc_thread, PWAIT, "owidle", ONEWIRE_SCANTIME * hz);
309 }
310
311 sc->sc_thread = NULL;
312 wakeup(&sc->sc_dying);
313 kthread_exit(0);
314 }
315
316 static void
317 onewire_scan(struct onewire_softc *sc)
318 {
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;
327
328 TAILQ_FOREACH(d, &sc->sc_devs, d_list)
329 d->d_present = 0;
330
331 while (search && count++ < ONEWIRE_MAXDEVS) {
332 /* XXX: yield processor */
333 tsleep(sc, PWAIT, "owscan", hz / 10);
334
335 /*
336 * Reset the bus. If there's no presence pulse
337 * don't search for any devices.
338 */
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;
345 }
346
347 /*
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.
352 */
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;
370 }
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;
385 }
386 rom |= (mask << i);
387 }
388 lastd = i0;
389 onewire_unlock(sc);
390
391 if (rom == 0)
392 continue;
393
394 /*
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.
398 */
399 for (i = 0; i < 8; i++)
400 data[i] = (rom >> (i * 8)) & 0xff;
401 if (onewire_crc(data, 7) != data[7])
402 continue;
403
404 /*
405 * Go through the list of attached devices to see if we
406 * found a new one.
407 */
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;
414 }
415 }
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;
423
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);
432 }
433 }
434
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);
444 }
445 }
446 onewire_unlock(sc);
447 }
448