This source file includes following definitions.
- onewire_match
- onewire_attach
- onewire_detach
- onewire_activate
- onewire_print
- onewirebus_print
- onewire_lock
- onewire_unlock
- onewire_reset
- onewire_bit
- onewire_read_byte
- onewire_write_byte
- onewire_read_block
- onewire_write_block
- onewire_triplet
- onewire_matchrom
- onewire_search
- onewire_thread
- onewire_createthread
- onewire_scan
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 #include <sys/param.h>
24 #include <sys/systm.h>
25 #include <sys/device.h>
26 #include <sys/kernel.h>
27 #include <sys/kthread.h>
28 #include <sys/malloc.h>
29 #include <sys/proc.h>
30 #include <sys/queue.h>
31 #include <sys/rwlock.h>
32
33 #include <dev/onewire/onewirereg.h>
34 #include <dev/onewire/onewirevar.h>
35
36 #ifdef ONEWIRE_DEBUG
37 #define DPRINTF(x) printf x
38 #else
39 #define DPRINTF(x)
40 #endif
41
42 #define ONEWIRE_MAXDEVS 16
43 #define ONEWIRE_SCANTIME 3
44
45 struct onewire_softc {
46 struct device sc_dev;
47
48 struct onewire_bus * sc_bus;
49 struct rwlock sc_lock;
50 struct proc * sc_thread;
51 TAILQ_HEAD(, onewire_device) sc_devs;
52
53 int sc_dying;
54 u_int64_t sc_rombuf[ONEWIRE_MAXDEVS];
55 };
56
57 struct onewire_device {
58 TAILQ_ENTRY(onewire_device) d_list;
59 struct device * d_dev;
60 u_int64_t d_rom;
61 int d_present;
62 };
63
64 int onewire_match(struct device *, void *, void *);
65 void onewire_attach(struct device *, struct device *, void *);
66 int onewire_detach(struct device *, int);
67 int onewire_activate(struct device *, enum devact);
68 int onewire_print(void *, const char *);
69
70 void onewire_thread(void *);
71 void onewire_createthread(void *);
72 void onewire_scan(struct onewire_softc *);
73
74 struct cfattach onewire_ca = {
75 sizeof(struct onewire_softc),
76 onewire_match,
77 onewire_attach,
78 onewire_detach,
79 onewire_activate
80 };
81
82 struct cfdriver onewire_cd = {
83 NULL, "onewire", DV_DULL
84 };
85
86 int
87 onewire_match(struct device *parent, void *match, void *aux)
88 {
89 struct cfdata *cf = match;
90
91 return (strcmp(cf->cf_driver->cd_name, "onewire") == 0);
92 }
93
94 void
95 onewire_attach(struct device *parent, struct device *self, void *aux)
96 {
97 struct onewire_softc *sc = (struct onewire_softc *)self;
98 struct onewirebus_attach_args *oba = aux;
99
100 sc->sc_bus = oba->oba_bus;
101 rw_init(&sc->sc_lock, sc->sc_dev.dv_xname);
102 TAILQ_INIT(&sc->sc_devs);
103
104 printf("\n");
105
106 kthread_create_deferred(onewire_createthread, sc);
107 }
108
109 int
110 onewire_detach(struct device *self, int flags)
111 {
112 struct onewire_softc *sc = (struct onewire_softc *)self;
113
114 sc->sc_dying = 1;
115 if (sc->sc_thread != NULL) {
116 wakeup(sc->sc_thread);
117 tsleep(&sc->sc_dying, PWAIT, "owdt", 0);
118 }
119
120 return (config_detach_children(self, flags));
121 }
122
123 int
124 onewire_activate(struct device *self, enum devact act)
125 {
126 struct onewire_softc *sc = (struct onewire_softc *)self;
127
128 switch (act) {
129 case DVACT_ACTIVATE:
130 break;
131 case DVACT_DEACTIVATE:
132 sc->sc_dying = 1;
133 break;
134 }
135
136 return (config_activate_children(self, act));
137 }
138
139 int
140 onewire_print(void *aux, const char *pnp)
141 {
142 struct onewire_attach_args *oa = aux;
143 const char *famname;
144
145 if (pnp == NULL)
146 printf(" ");
147
148 famname = onewire_famname(ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
149 if (famname == NULL)
150 printf("family 0x%02x", ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom));
151 else
152 printf("\"%s\"", famname);
153 printf(" sn %012llx", ONEWIRE_ROM_SN(oa->oa_rom));
154
155 if (pnp != NULL)
156 printf(" at %s", pnp);
157
158 return (UNCONF);
159 }
160
161 int
162 onewirebus_print(void *aux, const char *pnp)
163 {
164 if (pnp != NULL)
165 printf("onewire at %s", pnp);
166
167 return (UNCONF);
168 }
169
170 int
171 onewire_lock(void *arg, int flags)
172 {
173 struct onewire_softc *sc = arg;
174 int lflags = RW_WRITE;
175
176 if (flags & ONEWIRE_NOWAIT)
177 lflags |= RW_NOSLEEP;
178
179 return (rw_enter(&sc->sc_lock, lflags));
180 }
181
182 void
183 onewire_unlock(void *arg)
184 {
185 struct onewire_softc *sc = arg;
186
187 rw_exit(&sc->sc_lock);
188 }
189
190 int
191 onewire_reset(void *arg)
192 {
193 struct onewire_softc *sc = arg;
194 struct onewire_bus *bus = sc->sc_bus;
195
196 return (bus->bus_reset(bus->bus_cookie));
197 }
198
199 int
200 onewire_bit(void *arg, int value)
201 {
202 struct onewire_softc *sc = arg;
203 struct onewire_bus *bus = sc->sc_bus;
204
205 return (bus->bus_bit(bus->bus_cookie, value));
206 }
207
208 int
209 onewire_read_byte(void *arg)
210 {
211 struct onewire_softc *sc = arg;
212 struct onewire_bus *bus = sc->sc_bus;
213 u_int8_t value = 0;
214 int i;
215
216 if (bus->bus_read_byte != NULL)
217 return (bus->bus_read_byte(bus->bus_cookie));
218
219 for (i = 0; i < 8; i++)
220 value |= (bus->bus_bit(bus->bus_cookie, 1) << i);
221
222 return (value);
223 }
224
225 void
226 onewire_write_byte(void *arg, int value)
227 {
228 struct onewire_softc *sc = arg;
229 struct onewire_bus *bus = sc->sc_bus;
230 int i;
231
232 if (bus->bus_write_byte != NULL)
233 return (bus->bus_write_byte(bus->bus_cookie, value));
234
235 for (i = 0; i < 8; i++)
236 bus->bus_bit(bus->bus_cookie, (value >> i) & 0x1);
237 }
238
239 void
240 onewire_read_block(void *arg, void *buf, int len)
241 {
242 struct onewire_softc *sc = arg;
243 struct onewire_bus *bus = sc->sc_bus;
244 u_int8_t *p = buf;
245
246 if (bus->bus_read_block != NULL)
247 return (bus->bus_read_block(bus->bus_cookie, buf, len));
248
249 while (len--)
250 *p++ = onewire_read_byte(arg);
251 }
252
253 void
254 onewire_write_block(void *arg, const void *buf, int len)
255 {
256 struct onewire_softc *sc = arg;
257 struct onewire_bus *bus = sc->sc_bus;
258 const u_int8_t *p = buf;
259
260 if (bus->bus_write_block != NULL)
261 return (bus->bus_write_block(bus->bus_cookie, buf, len));
262
263 while (len--)
264 onewire_write_byte(arg, *p++);
265 }
266
267 int
268 onewire_triplet(void *arg, int dir)
269 {
270 struct onewire_softc *sc = arg;
271 struct onewire_bus *bus = sc->sc_bus;
272 int rv;
273
274 if (bus->bus_triplet != NULL)
275 return (bus->bus_triplet(bus->bus_cookie, dir));
276
277 rv = bus->bus_bit(bus->bus_cookie, 1);
278 rv <<= 1;
279 rv |= bus->bus_bit(bus->bus_cookie, 1);
280
281 switch (rv) {
282 case 0x0:
283 bus->bus_bit(bus->bus_cookie, dir);
284 break;
285 case 0x1:
286 bus->bus_bit(bus->bus_cookie, 0);
287 break;
288 default:
289 bus->bus_bit(bus->bus_cookie, 1);
290 }
291
292 return (rv);
293 }
294
295 void
296 onewire_matchrom(void *arg, u_int64_t rom)
297 {
298 struct onewire_softc *sc = arg;
299 struct onewire_bus *bus = sc->sc_bus;
300 int i;
301
302 if (bus->bus_matchrom != NULL)
303 return (bus->bus_matchrom(bus->bus_cookie, rom));
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 int
311 onewire_search(void *arg, u_int64_t *buf, int size, u_int64_t startrom)
312 {
313 struct onewire_softc *sc = arg;
314 struct onewire_bus *bus = sc->sc_bus;
315 int search = 1, count = 0, lastd = -1, dir, rv, i, i0;
316 u_int64_t mask, rom = startrom, lastrom;
317 u_int8_t data[8];
318
319 if (bus->bus_search != NULL)
320 return (bus->bus_search(bus->bus_cookie, buf, size, rom));
321
322 while (search && count < size) {
323
324 tsleep(sc, PWAIT, "owscan", hz / 10);
325
326
327
328
329
330
331
332 lastrom = rom;
333 rom = 0;
334 onewire_lock(sc, 0);
335 onewire_reset(sc);
336 onewire_write_byte(sc, ONEWIRE_CMD_SEARCH_ROM);
337 for (i = 0, i0 = -1; i < 64; i++) {
338 dir = (lastrom >> i) & 0x1;
339 if (i == lastd)
340 dir = 1;
341 else if (i > lastd)
342 dir = 0;
343 rv = onewire_triplet(sc, dir);
344 switch (rv) {
345 case 0x0:
346 if (i != lastd && dir == 0)
347 i0 = i;
348 mask = dir;
349 break;
350 case 0x1:
351 mask = 0;
352 break;
353 case 0x2:
354 mask = 1;
355 break;
356 default:
357 DPRINTF(("%s: search triplet error 0x%x, "
358 "step %d\n",
359 sc->sc_dev.dv_xname, rv, i));
360 onewire_unlock(sc);
361 return (-1);
362 }
363 rom |= (mask << i);
364 }
365 onewire_unlock(sc);
366
367 if ((lastd = i0) == -1)
368 search = 0;
369
370 if (rom == 0)
371 continue;
372
373
374
375
376
377
378 for (i = 0; i < 8; i++)
379 data[i] = (rom >> (i * 8)) & 0xff;
380 if (onewire_crc(data, 7) != data[7])
381 continue;
382
383 buf[count++] = rom;
384 }
385
386 return (count);
387 }
388
389 void
390 onewire_thread(void *arg)
391 {
392 struct onewire_softc *sc = arg;
393
394 while (!sc->sc_dying) {
395 onewire_scan(sc);
396 tsleep(sc->sc_thread, PWAIT, "owidle", ONEWIRE_SCANTIME * hz);
397 }
398
399 sc->sc_thread = NULL;
400 wakeup(&sc->sc_dying);
401 kthread_exit(0);
402 }
403
404 void
405 onewire_createthread(void *arg)
406 {
407 struct onewire_softc *sc = arg;
408
409 if (kthread_create(onewire_thread, sc, &sc->sc_thread,
410 "%s", sc->sc_dev.dv_xname) != 0)
411 printf("%s: can't create kernel thread\n",
412 sc->sc_dev.dv_xname);
413 }
414
415 void
416 onewire_scan(struct onewire_softc *sc)
417 {
418 struct onewire_device *d, *next, *nd;
419 struct onewire_attach_args oa;
420 struct device *dev;
421 int present;
422 u_int64_t rom;
423 int i, rv;
424
425
426
427
428
429
430 TAILQ_FOREACH(d, &sc->sc_devs, d_list)
431 d->d_present = 0;
432
433
434
435
436
437 onewire_lock(sc, 0);
438 rv = onewire_reset(sc);
439 onewire_unlock(sc);
440 if (rv != 0) {
441 DPRINTF(("%s: no presence pulse\n", sc->sc_dev.dv_xname));
442 goto out;
443 }
444
445
446 if ((rv = onewire_search(sc, sc->sc_rombuf, ONEWIRE_MAXDEVS, 0)) == -1)
447 return;
448
449 for (i = 0; i < rv; i++) {
450 rom = sc->sc_rombuf[i];
451
452
453
454
455
456 present = 0;
457 TAILQ_FOREACH(d, &sc->sc_devs, d_list) {
458 if (d->d_rom == rom) {
459 d->d_present = 1;
460 present = 1;
461 break;
462 }
463 }
464 if (!present) {
465 bzero(&oa, sizeof(oa));
466 oa.oa_onewire = sc;
467 oa.oa_rom = rom;
468 if ((dev = config_found(&sc->sc_dev, &oa,
469 onewire_print)) == NULL)
470 continue;
471
472 MALLOC(nd, struct onewire_device *,
473 sizeof(struct onewire_device), M_DEVBUF, M_NOWAIT);
474 if (nd == NULL)
475 continue;
476 nd->d_dev = dev;
477 nd->d_rom = rom;
478 nd->d_present = 1;
479 TAILQ_INSERT_TAIL(&sc->sc_devs, nd, d_list);
480 }
481 }
482
483 out:
484
485 for (d = TAILQ_FIRST(&sc->sc_devs);
486 d != TAILQ_END(&sc->sc_dev); d = next) {
487 next = TAILQ_NEXT(d, d_list);
488 if (!d->d_present) {
489 config_detach(d->d_dev, DETACH_FORCE);
490 TAILQ_REMOVE(&sc->sc_devs, d, d_list);
491 FREE(d, M_DEVBUF);
492 }
493 }
494 }