1 /* $NetBSD: onewire.c,v 1.10 2008/12/17 20:51:34 cegger 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@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.10 2008/12/17 20:51:34 cegger 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 int rv = 0; 139 140 switch (act) { 141 case DVACT_ACTIVATE: 142 rv = EOPNOTSUPP; 143 break; 144 case DVACT_DEACTIVATE: 145 sc->sc_dying = 1; 146 break; 147 } 148 149 //return (config_activate_children(self, act)); 150 return rv; 151 } 152 153 int 154 onewire_print(void *aux, const char *pnp) 155 { 156 struct onewire_attach_args *oa = aux; 157 const char *famname; 158 159 if (pnp == NULL) 160 aprint_normal(" "); 161 162 famname = onewire_famname(ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom)); 163 if (famname == NULL) 164 aprint_normal("family 0x%02x", 165 (uint)ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom)); 166 else 167 aprint_normal("\"%s\"", famname); 168 aprint_normal(" sn %012llx", ONEWIRE_ROM_SN(oa->oa_rom)); 169 170 if (pnp != NULL) 171 aprint_normal(" at %s", pnp); 172 173 return UNCONF; 174 } 175 176 int 177 onewirebus_print(void *aux, const char *pnp) 178 { 179 if (pnp != NULL) 180 aprint_normal("onewire at %s", pnp); 181 182 return UNCONF; 183 } 184 185 void 186 onewire_lock(void *arg) 187 { 188 struct onewire_softc *sc = arg; 189 190 rw_enter(&sc->sc_rwlock, RW_WRITER); 191 } 192 193 void 194 onewire_unlock(void *arg) 195 { 196 struct onewire_softc *sc = arg; 197 198 rw_exit(&sc->sc_rwlock); 199 } 200 201 int 202 onewire_reset(void *arg) 203 { 204 struct onewire_softc *sc = arg; 205 struct onewire_bus *bus = sc->sc_bus; 206 207 return bus->bus_reset(bus->bus_cookie); 208 } 209 210 int 211 onewire_bit(void *arg, int value) 212 { 213 struct onewire_softc *sc = arg; 214 struct onewire_bus *bus = sc->sc_bus; 215 216 return bus->bus_bit(bus->bus_cookie, value); 217 } 218 219 int 220 onewire_read_byte(void *arg) 221 { 222 struct onewire_softc *sc = arg; 223 struct onewire_bus *bus = sc->sc_bus; 224 uint8_t value = 0; 225 int i; 226 227 if (bus->bus_read_byte != NULL) 228 return bus->bus_read_byte(bus->bus_cookie); 229 230 for (i = 0; i < 8; i++) 231 value |= (bus->bus_bit(bus->bus_cookie, 1) << i); 232 233 return value; 234 } 235 236 void 237 onewire_write_byte(void *arg, int value) 238 { 239 struct onewire_softc *sc = arg; 240 struct onewire_bus *bus = sc->sc_bus; 241 int i; 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 if (bus->bus_triplet != NULL) 258 return bus->bus_triplet(bus->bus_cookie, dir); 259 260 rv = bus->bus_bit(bus->bus_cookie, 1); 261 rv <<= 1; 262 rv |= bus->bus_bit(bus->bus_cookie, 1); 263 264 switch (rv) { 265 case 0x0: 266 bus->bus_bit(bus->bus_cookie, dir); 267 break; 268 case 0x1: 269 bus->bus_bit(bus->bus_cookie, 0); 270 break; 271 default: 272 bus->bus_bit(bus->bus_cookie, 1); 273 } 274 275 return rv; 276 } 277 278 void 279 onewire_read_block(void *arg, void *buf, int len) 280 { 281 uint8_t *p = buf; 282 283 while (len--) 284 *p++ = onewire_read_byte(arg); 285 } 286 287 void 288 onewire_write_block(void *arg, const void *buf, int len) 289 { 290 const uint8_t *p = buf; 291 292 while (len--) 293 onewire_write_byte(arg, *p++); 294 } 295 296 void 297 onewire_matchrom(void *arg, u_int64_t rom) 298 { 299 int i; 300 301 onewire_write_byte(arg, ONEWIRE_CMD_MATCH_ROM); 302 for (i = 0; i < 8; i++) 303 onewire_write_byte(arg, (rom >> (i * 8)) & 0xff); 304 } 305 306 static void 307 onewire_thread(void *arg) 308 { 309 struct onewire_softc *sc = arg; 310 311 while (!sc->sc_dying) { 312 onewire_scan(sc); 313 tsleep(sc->sc_thread, PWAIT, "owidle", ONEWIRE_SCANTIME * hz); 314 } 315 316 sc->sc_thread = NULL; 317 wakeup(&sc->sc_dying); 318 kthread_exit(0); 319 } 320 321 static void 322 onewire_scan(struct onewire_softc *sc) 323 { 324 struct onewire_device *d, *next, *nd; 325 struct onewire_attach_args oa; 326 struct device *dev; 327 int search = 1, count = 0, present; 328 int dir, rv; 329 uint64_t mask, rom = 0, lastrom; 330 uint8_t data[8]; 331 int i, i0 = -1, lastd = -1; 332 333 TAILQ_FOREACH(d, &sc->sc_devs, d_list) 334 d->d_present = 0; 335 336 while (search && count++ < ONEWIRE_MAXDEVS) { 337 /* XXX: yield processor */ 338 tsleep(sc, PWAIT, "owscan", hz / 10); 339 340 /* 341 * Reset the bus. If there's no presence pulse 342 * don't search for any devices. 343 */ 344 onewire_lock(sc); 345 if (onewire_reset(sc) != 0) { 346 DPRINTF(("%s: scan: no presence pulse\n", 347 device_xname(sc->sc_dev))); 348 onewire_unlock(sc); 349 break; 350 } 351 352 /* 353 * Start new search. Go through the previous path to 354 * the point we made a decision last time and make an 355 * opposite decision. If we didn't make any decision 356 * stop searching. 357 */ 358 search = 0; 359 lastrom = rom; 360 rom = 0; 361 onewire_write_byte(sc, ONEWIRE_CMD_SEARCH_ROM); 362 for (i = 0,i0 = -1; i < 64; i++) { 363 dir = (lastrom >> i) & 0x1; 364 if (i == lastd) 365 dir = 1; 366 else if (i > lastd) 367 dir = 0; 368 rv = onewire_triplet(sc, dir); 369 switch (rv) { 370 case 0x0: 371 if (i != lastd) { 372 if (dir == 0) 373 i0 = i; 374 search = 1; 375 } 376 mask = dir; 377 break; 378 case 0x1: 379 mask = 0; 380 break; 381 case 0x2: 382 mask = 1; 383 break; 384 default: 385 DPRINTF(("%s: scan: triplet error 0x%x, " 386 "step %d\n", 387 device_xname(sc->sc_dev), rv, i)); 388 onewire_unlock(sc); 389 return; 390 } 391 rom |= (mask << i); 392 } 393 lastd = i0; 394 onewire_unlock(sc); 395 396 if (rom == 0) 397 continue; 398 399 /* 400 * The last byte of the ROM code contains a CRC calculated 401 * from the first 7 bytes. Re-calculate it to make sure 402 * we found a valid device. 403 */ 404 for (i = 0; i < 8; i++) 405 data[i] = (rom >> (i * 8)) & 0xff; 406 if (onewire_crc(data, 7) != data[7]) 407 continue; 408 409 /* 410 * Go through the list of attached devices to see if we 411 * found a new one. 412 */ 413 present = 0; 414 TAILQ_FOREACH(d, &sc->sc_devs, d_list) { 415 if (d->d_rom == rom) { 416 d->d_present = 1; 417 present = 1; 418 break; 419 } 420 } 421 if (!present) { 422 bzero(&oa, sizeof(oa)); 423 oa.oa_onewire = sc; 424 oa.oa_rom = rom; 425 if ((dev = config_found(sc->sc_dev, &oa, 426 onewire_print)) == NULL) 427 continue; 428 429 nd = malloc(sizeof(struct onewire_device), 430 M_DEVBUF, M_NOWAIT); 431 if (nd == NULL) 432 continue; 433 nd->d_dev = dev; 434 nd->d_rom = rom; 435 nd->d_present = 1; 436 TAILQ_INSERT_TAIL(&sc->sc_devs, nd, d_list); 437 } 438 } 439 440 /* Detach disappeared devices */ 441 onewire_lock(sc); 442 for (d = TAILQ_FIRST(&sc->sc_devs); 443 d != NULL; d = next) { 444 next = TAILQ_NEXT(d, d_list); 445 if (!d->d_present) { 446 config_detach(d->d_dev, DETACH_FORCE); 447 TAILQ_REMOVE(&sc->sc_devs, d, d_list); 448 free(d, M_DEVBUF); 449 } 450 } 451 onewire_unlock(sc); 452 } 453