onewire.c revision 1.14.16.1 1 /* $NetBSD: onewire.c,v 1.14.16.1 2014/05/18 17:45:39 rmind 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.14.16.1 2014/05/18 17:45:39 rmind 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 #include <sys/module.h>
38
39 #include <dev/onewire/onewirereg.h>
40 #include <dev/onewire/onewirevar.h>
41
42 #ifdef ONEWIRE_DEBUG
43 #define DPRINTF(x) printf x
44 #else
45 #define DPRINTF(x)
46 #endif
47
48 //#define ONEWIRE_MAXDEVS 256
49 #define ONEWIRE_MAXDEVS 8
50 #define ONEWIRE_SCANTIME 3
51
52 struct onewire_softc {
53 device_t sc_dev;
54
55 struct onewire_bus * sc_bus;
56 krwlock_t sc_rwlock;
57 struct lwp * sc_thread;
58 TAILQ_HEAD(, onewire_device) sc_devs;
59
60 int sc_dying;
61 };
62
63 struct onewire_device {
64 TAILQ_ENTRY(onewire_device) d_list;
65 device_t d_dev;
66 u_int64_t d_rom;
67 int d_present;
68 };
69
70 static int onewire_match(device_t, cfdata_t, void *);
71 static void onewire_attach(device_t, device_t, void *);
72 static int onewire_detach(device_t, int);
73 static int onewire_activate(device_t, enum devact);
74 int onewire_print(void *, const char *);
75
76 static void onewire_thread(void *);
77 static void onewire_scan(struct onewire_softc *);
78
79 CFATTACH_DECL_NEW(onewire, sizeof(struct onewire_softc),
80 onewire_match, onewire_attach, onewire_detach, onewire_activate);
81
82 const struct cdevsw onewire_cdevsw = {
83 .d_open = noopen,
84 .d_close = noclose,
85 .d_read = noread,
86 .d_write = nowrite,
87 .d_ioctl = noioctl,
88 .d_stop = nostop,
89 .d_tty = notty,
90 .d_poll = nopoll,
91 .d_mmap = nommap,
92 .d_kqfilter = nokqfilter,
93 .d_flag = D_OTHER
94 };
95
96 extern struct cfdriver onewire_cd;
97
98 static int
99 onewire_match(device_t parent, cfdata_t cf, void *aux)
100 {
101 return 1;
102 }
103
104 static void
105 onewire_attach(device_t parent, device_t self, void *aux)
106 {
107 struct onewire_softc *sc = device_private(self);
108 struct onewirebus_attach_args *oba = aux;
109
110 sc->sc_dev = self;
111 sc->sc_bus = oba->oba_bus;
112 rw_init(&sc->sc_rwlock);
113 TAILQ_INIT(&sc->sc_devs);
114
115 aprint_normal("\n");
116
117 if (kthread_create(PRI_NONE, 0, NULL, onewire_thread, sc,
118 &sc->sc_thread, "%s", device_xname(self)) != 0)
119 aprint_error_dev(self, "can't create kernel thread\n");
120 }
121
122 static int
123 onewire_detach(device_t self, int flags)
124 {
125 struct onewire_softc *sc = device_private(self);
126 int rv;
127
128 sc->sc_dying = 1;
129 if (sc->sc_thread != NULL) {
130 wakeup(sc->sc_thread);
131 tsleep(&sc->sc_dying, PWAIT, "owdt", 0);
132 }
133
134 onewire_lock(sc);
135 //rv = config_detach_children(self, flags);
136 rv = 0; /* XXX riz */
137 onewire_unlock(sc);
138 rw_destroy(&sc->sc_rwlock);
139
140 return rv;
141 }
142
143 static int
144 onewire_activate(device_t self, enum devact act)
145 {
146 struct onewire_softc *sc = device_private(self);
147
148 switch (act) {
149 case DVACT_DEACTIVATE:
150 sc->sc_dying = 1;
151 return 0;
152 default:
153 return EOPNOTSUPP;
154 }
155 }
156
157 int
158 onewire_print(void *aux, const char *pnp)
159 {
160 struct onewire_attach_args *oa = aux;
161 const char *famname;
162
163 if (pnp == NULL)
164 aprint_normal(" ");
165
166 famname = onewire_famname(ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
167 if (famname == NULL)
168 aprint_normal("family 0x%02x",
169 (uint)ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
170 else
171 aprint_normal("\"%s\"", famname);
172 aprint_normal(" sn %012llx", ONEWIRE_ROM_SN(oa->oa_rom));
173
174 if (pnp != NULL)
175 aprint_normal(" at %s", pnp);
176
177 return UNCONF;
178 }
179
180 int
181 onewirebus_print(void *aux, const char *pnp)
182 {
183 if (pnp != NULL)
184 aprint_normal("onewire at %s", pnp);
185
186 return UNCONF;
187 }
188
189 void
190 onewire_lock(void *arg)
191 {
192 struct onewire_softc *sc = arg;
193
194 rw_enter(&sc->sc_rwlock, RW_WRITER);
195 }
196
197 void
198 onewire_unlock(void *arg)
199 {
200 struct onewire_softc *sc = arg;
201
202 rw_exit(&sc->sc_rwlock);
203 }
204
205 int
206 onewire_reset(void *arg)
207 {
208 struct onewire_softc *sc = arg;
209 struct onewire_bus *bus = sc->sc_bus;
210
211 return bus->bus_reset(bus->bus_cookie);
212 }
213
214 int
215 onewire_bit(void *arg, int value)
216 {
217 struct onewire_softc *sc = arg;
218 struct onewire_bus *bus = sc->sc_bus;
219
220 return bus->bus_bit(bus->bus_cookie, value);
221 }
222
223 int
224 onewire_read_byte(void *arg)
225 {
226 struct onewire_softc *sc = arg;
227 struct onewire_bus *bus = sc->sc_bus;
228 uint8_t value = 0;
229 int i;
230
231 if (bus->bus_read_byte != NULL)
232 return bus->bus_read_byte(bus->bus_cookie);
233
234 for (i = 0; i < 8; i++)
235 value |= (bus->bus_bit(bus->bus_cookie, 1) << i);
236
237 return value;
238 }
239
240 void
241 onewire_write_byte(void *arg, int value)
242 {
243 struct onewire_softc *sc = arg;
244 struct onewire_bus *bus = sc->sc_bus;
245 int i;
246
247 if (bus->bus_write_byte != NULL)
248 return bus->bus_write_byte(bus->bus_cookie, value);
249
250 for (i = 0; i < 8; i++)
251 bus->bus_bit(bus->bus_cookie, (value >> i) & 0x1);
252 }
253
254 int
255 onewire_triplet(void *arg, int dir)
256 {
257 struct onewire_softc *sc = arg;
258 struct onewire_bus *bus = sc->sc_bus;
259 int rv;
260
261 if (bus->bus_triplet != NULL)
262 return bus->bus_triplet(bus->bus_cookie, dir);
263
264 rv = bus->bus_bit(bus->bus_cookie, 1);
265 rv <<= 1;
266 rv |= bus->bus_bit(bus->bus_cookie, 1);
267
268 switch (rv) {
269 case 0x0:
270 bus->bus_bit(bus->bus_cookie, dir);
271 break;
272 case 0x1:
273 bus->bus_bit(bus->bus_cookie, 0);
274 break;
275 default:
276 bus->bus_bit(bus->bus_cookie, 1);
277 }
278
279 return rv;
280 }
281
282 void
283 onewire_read_block(void *arg, void *buf, int len)
284 {
285 uint8_t *p = buf;
286
287 while (len--)
288 *p++ = onewire_read_byte(arg);
289 }
290
291 void
292 onewire_write_block(void *arg, const void *buf, int len)
293 {
294 const uint8_t *p = buf;
295
296 while (len--)
297 onewire_write_byte(arg, *p++);
298 }
299
300 void
301 onewire_matchrom(void *arg, u_int64_t rom)
302 {
303 int i;
304
305 onewire_write_byte(arg, ONEWIRE_CMD_MATCH_ROM);
306 for (i = 0; i < 8; i++)
307 onewire_write_byte(arg, (rom >> (i * 8)) & 0xff);
308 }
309
310 static void
311 onewire_thread(void *arg)
312 {
313 struct onewire_softc *sc = arg;
314
315 while (!sc->sc_dying) {
316 onewire_scan(sc);
317 tsleep(sc->sc_thread, PWAIT, "owidle", ONEWIRE_SCANTIME * hz);
318 }
319
320 sc->sc_thread = NULL;
321 wakeup(&sc->sc_dying);
322 kthread_exit(0);
323 }
324
325 static void
326 onewire_scan(struct onewire_softc *sc)
327 {
328 struct onewire_device *d, *next, *nd;
329 struct onewire_attach_args oa;
330 device_t dev;
331 int search = 1, count = 0, present;
332 int dir, rv;
333 uint64_t mask, rom = 0, lastrom;
334 uint8_t data[8];
335 int i, i0 = -1, lastd = -1;
336
337 TAILQ_FOREACH(d, &sc->sc_devs, d_list)
338 d->d_present = 0;
339
340 while (search && count++ < ONEWIRE_MAXDEVS) {
341 /* XXX: yield processor */
342 tsleep(sc, PWAIT, "owscan", hz / 10);
343
344 /*
345 * Reset the bus. If there's no presence pulse
346 * don't search for any devices.
347 */
348 onewire_lock(sc);
349 if (onewire_reset(sc) != 0) {
350 DPRINTF(("%s: scan: no presence pulse\n",
351 device_xname(sc->sc_dev)));
352 onewire_unlock(sc);
353 break;
354 }
355
356 /*
357 * Start new search. Go through the previous path to
358 * the point we made a decision last time and make an
359 * opposite decision. If we didn't make any decision
360 * stop searching.
361 */
362 search = 0;
363 lastrom = rom;
364 rom = 0;
365 onewire_write_byte(sc, ONEWIRE_CMD_SEARCH_ROM);
366 for (i = 0,i0 = -1; i < 64; i++) {
367 dir = (lastrom >> i) & 0x1;
368 if (i == lastd)
369 dir = 1;
370 else if (i > lastd)
371 dir = 0;
372 rv = onewire_triplet(sc, dir);
373 switch (rv) {
374 case 0x0:
375 if (i != lastd) {
376 if (dir == 0)
377 i0 = i;
378 search = 1;
379 }
380 mask = dir;
381 break;
382 case 0x1:
383 mask = 0;
384 break;
385 case 0x2:
386 mask = 1;
387 break;
388 default:
389 DPRINTF(("%s: scan: triplet error 0x%x, "
390 "step %d\n",
391 device_xname(sc->sc_dev), rv, i));
392 onewire_unlock(sc);
393 return;
394 }
395 rom |= (mask << i);
396 }
397 lastd = i0;
398 onewire_unlock(sc);
399
400 if (rom == 0)
401 continue;
402
403 /*
404 * The last byte of the ROM code contains a CRC calculated
405 * from the first 7 bytes. Re-calculate it to make sure
406 * we found a valid device.
407 */
408 for (i = 0; i < 8; i++)
409 data[i] = (rom >> (i * 8)) & 0xff;
410 if (onewire_crc(data, 7) != data[7])
411 continue;
412
413 /*
414 * Go through the list of attached devices to see if we
415 * found a new one.
416 */
417 present = 0;
418 TAILQ_FOREACH(d, &sc->sc_devs, d_list) {
419 if (d->d_rom == rom) {
420 d->d_present = 1;
421 present = 1;
422 break;
423 }
424 }
425 if (!present) {
426 memset(&oa, 0, sizeof(oa));
427 oa.oa_onewire = sc;
428 oa.oa_rom = rom;
429 if ((dev = config_found(sc->sc_dev, &oa,
430 onewire_print)) == NULL)
431 continue;
432
433 nd = malloc(sizeof(struct onewire_device),
434 M_DEVBUF, M_NOWAIT);
435 if (nd == NULL)
436 continue;
437 nd->d_dev = dev;
438 nd->d_rom = rom;
439 nd->d_present = 1;
440 TAILQ_INSERT_TAIL(&sc->sc_devs, nd, d_list);
441 }
442 }
443
444 /* Detach disappeared devices */
445 onewire_lock(sc);
446 for (d = TAILQ_FIRST(&sc->sc_devs);
447 d != NULL; d = next) {
448 next = TAILQ_NEXT(d, d_list);
449 if (!d->d_present) {
450 config_detach(d->d_dev, DETACH_FORCE);
451 TAILQ_REMOVE(&sc->sc_devs, d, d_list);
452 free(d, M_DEVBUF);
453 }
454 }
455 onewire_unlock(sc);
456 }
457
458 MODULE(MODULE_CLASS_DRIVER, onewire, NULL);
459
460 #ifdef _MODULE
461 #include "ioconf.c"
462 #endif
463
464 static int
465 onewire_modcmd(modcmd_t cmd, void *opaque)
466 {
467 int error;
468
469 error = 0;
470 switch (cmd) {
471 case MODULE_CMD_INIT:
472 #ifdef _MODULE
473 error = config_init_component(cfdriver_ioconf_onewire,
474 cfattach_ioconf_onewire, cfdata_ioconf_onewire);
475 if (error)
476 aprint_error("%s: unable to init component\n",
477 onewire_cd.cd_name);
478 #endif
479 break;
480 case MODULE_CMD_FINI:
481 #ifdef _MODULE
482 config_fini_component(cfdriver_ioconf_onewire,
483 cfattach_ioconf_onewire, cfdata_ioconf_onewire);
484 #endif
485 break;
486 default:
487 error = ENOTTY;
488 }
489 return error;
490 }
491