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