1 /* $NetBSD: onewire.c,v 1.3 2006/10/12 01:31:27 christos 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.3 2006/10/12 01:31:27 christos 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/lock.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 struct device sc_dev; 53 54 struct onewire_bus * sc_bus; 55 struct lock sc_lock; 56 struct proc * 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 struct device * d_dev; 65 u_int64_t d_rom; 66 int d_present; 67 }; 68 69 int onewire_match(struct device *, struct cfdata *, void *); 70 void onewire_attach(struct device *, struct device *, void *); 71 int onewire_detach(struct device *, int); 72 int onewire_activate(struct device *, enum devact); 73 int onewire_print(void *, const char *); 74 75 void onewire_thread(void *); 76 void onewire_createthread(void *); 77 void onewire_scan(struct onewire_softc *); 78 79 CFATTACH_DECL(onewire, sizeof(struct onewire_softc), 80 onewire_match, onewire_attach, onewire_detach, onewire_activate); 81 82 const struct cdevsw onewire_cdevsw = { 83 noopen, noclose, noread, nowrite, noioctl, nostop, notty, 84 nopoll, nommap, nokqfilter, D_OTHER, 85 }; 86 87 extern struct cfdriver onewire_cd; 88 89 int 90 onewire_match(struct device *parent __unused, struct cfdata *cf __unused, 91 void *aux __unused) 92 { 93 return 1; 94 } 95 96 void 97 onewire_attach(struct device *parent __unused, struct device *self, void *aux) 98 { 99 struct onewire_softc *sc = device_private(self); 100 struct onewirebus_attach_args *oba = aux; 101 102 sc->sc_bus = oba->oba_bus; 103 lockinit(&sc->sc_lock, PRIBIO, "owlock", 0, 0); 104 TAILQ_INIT(&sc->sc_devs); 105 106 printf("\n"); 107 108 kthread_create(onewire_createthread, sc); 109 } 110 111 int 112 onewire_detach(struct device *self, int flags __unused) 113 { 114 struct onewire_softc *sc = device_private(self); 115 int rv; 116 117 sc->sc_dying = 1; 118 if (sc->sc_thread != NULL) { 119 wakeup(sc->sc_thread); 120 tsleep(&sc->sc_dying, PWAIT, "owdt", 0); 121 } 122 123 onewire_lock(sc, 0); 124 //rv = config_detach_children(self, flags); 125 rv = 0; /* XXX riz */ 126 onewire_unlock(sc); 127 128 return (rv); 129 } 130 131 int 132 onewire_activate(struct device *self, enum devact act) 133 { 134 struct onewire_softc *sc = device_private(self); 135 int rv = 0; 136 137 switch (act) { 138 case DVACT_ACTIVATE: 139 rv = EOPNOTSUPP; 140 break; 141 case DVACT_DEACTIVATE: 142 sc->sc_dying = 1; 143 break; 144 } 145 146 //return (config_activate_children(self, act)); 147 return rv; 148 } 149 150 int 151 onewire_print(void *aux, const char *pnp) 152 { 153 struct onewire_attach_args *oa = aux; 154 const char *famname; 155 156 if (pnp == NULL) 157 printf(" "); 158 159 famname = onewire_famname(ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom)); 160 if (famname == NULL) 161 printf("family 0x%02x", (uint)ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom)); 162 else 163 printf("\"%s\"", famname); 164 printf(" sn %012llx", ONEWIRE_ROM_SN(oa->oa_rom)); 165 166 if (pnp != NULL) 167 printf(" at %s", pnp); 168 169 return (UNCONF); 170 } 171 172 int 173 onewirebus_print(void *aux __unused, const char *pnp) 174 { 175 if (pnp != NULL) 176 printf("onewire at %s", pnp); 177 178 return (UNCONF); 179 } 180 181 int 182 onewire_lock(void *arg, int flags) 183 { 184 struct onewire_softc *sc = arg; 185 int lflags = LK_EXCLUSIVE; 186 187 if (flags & ONEWIRE_NOWAIT) 188 lflags |= LK_NOWAIT; 189 190 return (lockmgr(&sc->sc_lock, lflags, NULL)); 191 } 192 193 void 194 onewire_unlock(void *arg) 195 { 196 struct onewire_softc *sc = arg; 197 198 lockmgr(&sc->sc_lock, LK_RELEASE, NULL); 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 u_int8_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 u_int8_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 u_int8_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 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 void 322 onewire_createthread(void *arg) 323 { 324 struct onewire_softc *sc = arg; 325 326 if (kthread_create1(onewire_thread, sc, &sc->sc_thread, 327 "%s", sc->sc_dev.dv_xname) != 0) 328 printf("%s: can't create kernel thread\n", 329 sc->sc_dev.dv_xname); 330 } 331 332 void 333 onewire_scan(struct onewire_softc *sc) 334 { 335 struct onewire_device *d, *next, *nd; 336 struct onewire_attach_args oa; 337 struct device *dev; 338 int search = 1, count = 0, present; 339 int dir, rv; 340 u_int64_t mask, rom = 0, lastrom; 341 u_int8_t data[8]; 342 int i, i0 = -1, lastd = -1; 343 344 TAILQ_FOREACH(d, &sc->sc_devs, d_list) 345 d->d_present = 0; 346 347 while (search && count++ < ONEWIRE_MAXDEVS) { 348 /* XXX: yield processor */ 349 tsleep(sc, PWAIT, "owscan", hz / 10); 350 351 /* 352 * Reset the bus. If there's no presence pulse 353 * don't search for any devices. 354 */ 355 onewire_lock(sc, 0); 356 if (onewire_reset(sc) != 0) { 357 DPRINTF(("%s: scan: no presence pulse\n", 358 sc->sc_dev.dv_xname)); 359 onewire_unlock(sc); 360 break; 361 } 362 363 /* 364 * Start new search. Go through the previous path to 365 * the point we made a decision last time and make an 366 * opposite decision. If we didn't make any decision 367 * stop searching. 368 */ 369 search = 0; 370 lastrom = rom; 371 rom = 0; 372 onewire_write_byte(sc, ONEWIRE_CMD_SEARCH_ROM); 373 for (i = 0,i0 = -1; i < 64; i++) { 374 dir = (lastrom >> i) & 0x1; 375 if (i == lastd) 376 dir = 1; 377 else if (i > lastd) 378 dir = 0; 379 rv = onewire_triplet(sc, dir); 380 switch (rv) { 381 case 0x0: 382 if (i != lastd) { 383 if (dir == 0) 384 i0 = i; 385 search = 1; 386 } 387 mask = dir; 388 break; 389 case 0x1: 390 mask = 0; 391 break; 392 case 0x2: 393 mask = 1; 394 break; 395 default: 396 DPRINTF(("%s: scan: triplet error 0x%x, " 397 "step %d\n", 398 sc->sc_dev.dv_xname, rv, i)); 399 onewire_unlock(sc); 400 return; 401 } 402 rom |= (mask << i); 403 } 404 lastd = i0; 405 onewire_unlock(sc); 406 407 if (rom == 0) 408 continue; 409 410 /* 411 * The last byte of the ROM code contains a CRC calculated 412 * from the first 7 bytes. Re-calculate it to make sure 413 * we found a valid device. 414 */ 415 for (i = 0; i < 8; i++) 416 data[i] = (rom >> (i * 8)) & 0xff; 417 if (onewire_crc(data, 7) != data[7]) 418 continue; 419 420 /* 421 * Go through the list of attached devices to see if we 422 * found a new one. 423 */ 424 present = 0; 425 TAILQ_FOREACH(d, &sc->sc_devs, d_list) { 426 if (d->d_rom == rom) { 427 d->d_present = 1; 428 present = 1; 429 break; 430 } 431 } 432 if (!present) { 433 bzero(&oa, sizeof(oa)); 434 oa.oa_onewire = sc; 435 oa.oa_rom = rom; 436 if ((dev = config_found(&sc->sc_dev, &oa, 437 onewire_print)) == NULL) 438 continue; 439 440 MALLOC(nd, struct onewire_device *, 441 sizeof(struct onewire_device), M_DEVBUF, M_NOWAIT); 442 if (nd == NULL) 443 continue; 444 nd->d_dev = dev; 445 nd->d_rom = rom; 446 nd->d_present = 1; 447 TAILQ_INSERT_TAIL(&sc->sc_devs, nd, d_list); 448 } 449 } 450 451 /* Detach disappeared devices */ 452 onewire_lock(sc, 0); 453 for (d = TAILQ_FIRST(&sc->sc_devs); 454 d != NULL; d = next) { 455 next = TAILQ_NEXT(d, d_list); 456 if (!d->d_present) { 457 config_detach(d->d_dev, DETACH_FORCE); 458 TAILQ_REMOVE(&sc->sc_devs, d, d_list); 459 FREE(d, M_DEVBUF); 460 } 461 } 462 onewire_unlock(sc); 463 } 464