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 $ */
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 $");
27 #include <sys/param.h>
28 #include <sys/systm.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>
36 #include <sys/queue.h>
38 #include <dev/onewire/onewirereg.h>
39 #include <dev/onewire/onewirevar.h>
42 #define DPRINTF(x) printf x
47 //#define ONEWIRE_MAXDEVS 256
48 #define ONEWIRE_MAXDEVS 8
49 #define ONEWIRE_SCANTIME 3
51 struct onewire_softc
{
54 struct onewire_bus
* sc_bus
;
56 struct lwp
* sc_thread
;
57 TAILQ_HEAD(, onewire_device
) sc_devs
;
62 struct onewire_device
{
63 TAILQ_ENTRY(onewire_device
) d_list
;
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
;
89 onewire_match(device_t parent
, cfdata_t cf
, void *aux
)
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
;
101 sc
->sc_bus
= oba
->oba_bus
;
102 rw_init(&sc
->sc_rwlock
);
103 TAILQ_INIT(&sc
->sc_devs
);
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");
114 onewire_detach(device_t self
, int flags
)
116 struct onewire_softc
*sc
= device_private(self
);
120 if (sc
->sc_thread
!= NULL
) {
121 wakeup(sc
->sc_thread
);
122 tsleep(&sc
->sc_dying
, PWAIT
, "owdt", 0);
126 //rv = config_detach_children(self, flags);
127 rv
= 0; /* XXX riz */
129 rw_destroy(&sc
->sc_rwlock
);
135 onewire_activate(device_t self
, enum devact act
)
137 struct onewire_softc
*sc
= device_private(self
);
140 case DVACT_DEACTIVATE
:
149 onewire_print(void *aux
, const char *pnp
)
151 struct onewire_attach_args
*oa
= aux
;
157 famname
= onewire_famname(ONEWIRE_ROM_FAMILY_TYPE(oa
->oa_rom
));
159 aprint_normal("family 0x%02x",
160 (uint
)ONEWIRE_ROM_FAMILY_TYPE(oa
->oa_rom
));
162 aprint_normal("\"%s\"", famname
);
163 aprint_normal(" sn %012llx", ONEWIRE_ROM_SN(oa
->oa_rom
));
166 aprint_normal(" at %s", pnp
);
172 onewirebus_print(void *aux
, const char *pnp
)
175 aprint_normal("onewire at %s", pnp
);
181 onewire_lock(void *arg
)
183 struct onewire_softc
*sc
= arg
;
185 rw_enter(&sc
->sc_rwlock
, RW_WRITER
);
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
;
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
);
232 onewire_write_byte(void *arg
, int value
)
234 struct onewire_softc
*sc
= arg
;
235 struct onewire_bus
*bus
= sc
->sc_bus
;
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
;
252 if (bus
->bus_triplet
!= NULL
)
253 return bus
->bus_triplet(bus
->bus_cookie
, dir
);
255 rv
= bus
->bus_bit(bus
->bus_cookie
, 1);
257 rv
|= bus
->bus_bit(bus
->bus_cookie
, 1);
261 bus
->bus_bit(bus
->bus_cookie
, dir
);
264 bus
->bus_bit(bus
->bus_cookie
, 0);
267 bus
->bus_bit(bus
->bus_cookie
, 1);
274 onewire_read_block(void *arg
, void *buf
, int len
)
279 *p
++ = onewire_read_byte(arg
);
283 onewire_write_block(void *arg
, const void *buf
, int len
)
285 const uint8_t *p
= buf
;
288 onewire_write_byte(arg
, *p
++);
292 onewire_matchrom(void *arg
, u_int64_t rom
)
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);
302 onewire_thread(void *arg
)
304 struct onewire_softc
*sc
= arg
;
306 while (!sc
->sc_dying
) {
308 tsleep(sc
->sc_thread
, PWAIT
, "owidle", ONEWIRE_SCANTIME
* hz
);
311 sc
->sc_thread
= NULL
;
312 wakeup(&sc
->sc_dying
);
317 onewire_scan(struct onewire_softc
*sc
)
319 struct onewire_device
*d
, *next
, *nd
;
320 struct onewire_attach_args oa
;
322 int search
= 1, count
= 0, present
;
324 uint64_t mask
, rom
= 0, lastrom
;
326 int i
, i0
= -1, lastd
= -1;
328 TAILQ_FOREACH(d
, &sc
->sc_devs
, d_list
)
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.
340 if (onewire_reset(sc
) != 0) {
341 DPRINTF(("%s: scan: no presence pulse\n",
342 device_xname(sc
->sc_dev
)));
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
356 onewire_write_byte(sc
, ONEWIRE_CMD_SEARCH_ROM
);
357 for (i
= 0,i0
= -1; i
< 64; i
++) {
358 dir
= (lastrom
>> i
) & 0x1;
363 rv
= onewire_triplet(sc
, dir
);
380 DPRINTF(("%s: scan: triplet error 0x%x, "
382 device_xname(sc
->sc_dev
), rv
, i
));
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])
405 * Go through the list of attached devices to see if we
409 TAILQ_FOREACH(d
, &sc
->sc_devs
, d_list
) {
410 if (d
->d_rom
== rom
) {
417 memset(&oa
, 0, sizeof(oa
));
420 if ((dev
= config_found(sc
->sc_dev
, &oa
,
421 onewire_print
)) == NULL
)
424 nd
= malloc(sizeof(struct onewire_device
),
431 TAILQ_INSERT_TAIL(&sc
->sc_devs
, nd
, d_list
);
435 /* Detach disappeared devices */
437 for (d
= TAILQ_FIRST(&sc
->sc_devs
);
438 d
!= NULL
; d
= next
) {
439 next
= TAILQ_NEXT(d
, d_list
);
441 config_detach(d
->d_dev
, DETACH_FORCE
);
442 TAILQ_REMOVE(&sc
->sc_devs
, d
, d_list
);