1 /* $NetBSD: onewire.c,v 1.1 2006/04/07 18:55:22 riz 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.1 2006/04/07 18:55:22 riz 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, 85 }; 86 87 extern struct cfdriver onewire_cd; 88 89 int 90 onewire_match(struct device *parent, struct cfdata *cf, void *aux) 91 { 92 return 1; 93 } 94 95 void 96 onewire_attach(struct device *parent, struct device *self, void *aux) 97 { 98 struct onewire_softc *sc = device_private(self); 99 struct onewirebus_attach_args *oba = aux; 100 101 sc->sc_bus = oba->oba_bus; 102 lockinit(&sc->sc_lock, PRIBIO, "owlock", 0, 0); 103 TAILQ_INIT(&sc->sc_devs); 104 105 printf("\n"); 106 107 kthread_create(onewire_createthread, sc); 108 } 109 110 int 111 onewire_detach(struct device *self, int flags) 112 { 113 struct onewire_softc *sc = device_private(self); 114 int rv; 115 116 sc->sc_dying = 1; 117 if (sc->sc_thread != NULL) { 118 wakeup(sc->sc_thread); 119 tsleep(&sc->sc_dying, PWAIT, "owdt", 0); 120 } 121 122 onewire_lock(sc, 0); 123 //rv = config_detach_children(self, flags); 124 rv = 0; /* XXX riz */ 125 onewire_unlock(sc); 126 127 return (rv); 128 } 129 130 int 131 onewire_activate(struct device *self, enum devact act) 132 { 133 struct onewire_softc *sc = device_private(self); 134 int rv = 0; 135 136 switch (act) { 137 case DVACT_ACTIVATE: 138 rv = EOPNOTSUPP; 139 break; 140 case DVACT_DEACTIVATE: 141 sc->sc_dying = 1; 142 break; 143 } 144 145 //return (config_activate_children(self, act)); 146 return rv; 147 } 148 149 int 150 onewire_print(void *aux, const char *pnp) 151 { 152 struct onewire_attach_args *oa = aux; 153 const char *famname; 154 155 if (pnp == NULL) 156 printf(" "); 157 158 famname = onewire_famname(ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom)); 159 if (famname == NULL) 160 printf("family 0x%02x", (uint)ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom)); 161 else 162 printf("\"%s\"", famname); 163 printf(" sn %012llx", ONEWIRE_ROM_SN(oa->oa_rom)); 164 165 if (pnp != NULL) 166 printf(" at %s", pnp); 167 168 return (UNCONF); 169 } 170 171 int 172 onewirebus_print(void *aux, const char *pnp) 173 { 174 if (pnp != NULL) 175 printf("onewire at %s", pnp); 176 177 return (UNCONF); 178 } 179 180 int 181 onewire_lock(void *arg, int flags) 182 { 183 struct onewire_softc *sc = arg; 184 int lflags = LK_EXCLUSIVE; 185 186 if (flags & ONEWIRE_NOWAIT) 187 lflags |= LK_NOWAIT; 188 189 return (lockmgr(&sc->sc_lock, lflags, NULL)); 190 } 191 192 void 193 onewire_unlock(void *arg) 194 { 195 struct onewire_softc *sc = arg; 196 197 lockmgr(&sc->sc_lock, LK_RELEASE, NULL); 198 } 199 200 int 201 onewire_reset(void *arg) 202 { 203 struct onewire_softc *sc = arg; 204 struct onewire_bus *bus = sc->sc_bus; 205 206 return (bus->bus_reset(bus->bus_cookie)); 207 } 208 209 int 210 onewire_bit(void *arg, int value) 211 { 212 struct onewire_softc *sc = arg; 213 struct onewire_bus *bus = sc->sc_bus; 214 215 return (bus->bus_bit(bus->bus_cookie, value)); 216 } 217 218 int 219 onewire_read_byte(void *arg) 220 { 221 struct onewire_softc *sc = arg; 222 struct onewire_bus *bus = sc->sc_bus; 223 u_int8_t value = 0; 224 int i; 225 226 if (bus->bus_read_byte != NULL) 227 return (bus->bus_read_byte(bus->bus_cookie)); 228 229 for (i = 0; i < 8; i++) 230 value |= (bus->bus_bit(bus->bus_cookie, 1) << i); 231 232 return (value); 233 } 234 235 void 236 onewire_write_byte(void *arg, int value) 237 { 238 struct onewire_softc *sc = arg; 239 struct onewire_bus *bus = sc->sc_bus; 240 int i; 241 242 if (bus->bus_write_byte != NULL) 243 return (bus->bus_write_byte(bus->bus_cookie, value)); 244 245 for (i = 0; i < 8; i++) 246 bus->bus_bit(bus->bus_cookie, (value >> i) & 0x1); 247 } 248 249 int 250 onewire_triplet(void *arg, int dir) 251 { 252 struct onewire_softc *sc = arg; 253 struct onewire_bus *bus = sc->sc_bus; 254 int rv; 255 256 if (bus->bus_triplet != NULL) 257 return (bus->bus_triplet(bus->bus_cookie, dir)); 258 259 rv = bus->bus_bit(bus->bus_cookie, 1); 260 rv <<= 1; 261 rv |= bus->bus_bit(bus->bus_cookie, 1); 262 263 switch (rv) { 264 case 0x0: 265 bus->bus_bit(bus->bus_cookie, dir); 266 break; 267 case 0x1: 268 bus->bus_bit(bus->bus_cookie, 0); 269 break; 270 default: 271 bus->bus_bit(bus->bus_cookie, 1); 272 } 273 274 return (rv); 275 } 276 277 void 278 onewire_read_block(void *arg, void *buf, int len) 279 { 280 u_int8_t *p = buf; 281 282 while (len--) 283 *p++ = onewire_read_byte(arg); 284 } 285 286 void 287 onewire_write_block(void *arg, const void *buf, int len) 288 { 289 const u_int8_t *p = buf; 290 291 while (len--) 292 onewire_write_byte(arg, *p++); 293 } 294 295 void 296 onewire_matchrom(void *arg, u_int64_t rom) 297 { 298 int i; 299 300 onewire_write_byte(arg, ONEWIRE_CMD_MATCH_ROM); 301 for (i = 0; i < 8; i++) 302 onewire_write_byte(arg, (rom >> (i * 8)) & 0xff); 303 } 304 305 void 306 onewire_thread(void *arg) 307 { 308 struct onewire_softc *sc = arg; 309 310 while (!sc->sc_dying) { 311 onewire_scan(sc); 312 tsleep(sc->sc_thread, PWAIT, "owidle", ONEWIRE_SCANTIME * hz); 313 } 314 315 sc->sc_thread = NULL; 316 wakeup(&sc->sc_dying); 317 kthread_exit(0); 318 } 319 320 void 321 onewire_createthread(void *arg) 322 { 323 struct onewire_softc *sc = arg; 324 325 if (kthread_create1(onewire_thread, sc, &sc->sc_thread, 326 "%s", sc->sc_dev.dv_xname) != 0) 327 printf("%s: can't create kernel thread\n", 328 sc->sc_dev.dv_xname); 329 } 330 331 void 332 onewire_scan(struct onewire_softc *sc) 333 { 334 struct onewire_device *d, *next, *nd; 335 struct onewire_attach_args oa; 336 struct device *dev; 337 int search = 1, count = 0, present; 338 int dir, rv; 339 u_int64_t mask, rom = 0, lastrom; 340 u_int8_t data[8]; 341 int i, i0 = -1, lastd = -1; 342 343 TAILQ_FOREACH(d, &sc->sc_devs, d_list) 344 d->d_present = 0; 345 346 while (search && count++ < ONEWIRE_MAXDEVS) { 347 /* XXX: yield processor */ 348 tsleep(sc, PWAIT, "owscan", hz / 10); 349 350 /* 351 * Reset the bus. If there's no presence pulse 352 * don't search for any devices. 353 */ 354 onewire_lock(sc, 0); 355 if (onewire_reset(sc) != 0) { 356 DPRINTF(("%s: scan: no presence pulse\n", 357 sc->sc_dev.dv_xname)); 358 onewire_unlock(sc); 359 break; 360 } 361 362 /* 363 * Start new search. Go through the previous path to 364 * the point we made a decision last time and make an 365 * opposite decision. If we didn't make any decision 366 * stop searching. 367 */ 368 search = 0; 369 lastrom = rom; 370 rom = 0; 371 onewire_write_byte(sc, ONEWIRE_CMD_SEARCH_ROM); 372 for (i = 0,i0 = -1; i < 64; i++) { 373 dir = (lastrom >> i) & 0x1; 374 if (i == lastd) 375 dir = 1; 376 else if (i > lastd) 377 dir = 0; 378 rv = onewire_triplet(sc, dir); 379 switch (rv) { 380 case 0x0: 381 if (i != lastd) { 382 if (dir == 0) 383 i0 = i; 384 search = 1; 385 } 386 mask = dir; 387 break; 388 case 0x1: 389 mask = 0; 390 break; 391 case 0x2: 392 mask = 1; 393 break; 394 default: 395 DPRINTF(("%s: scan: triplet error 0x%x, " 396 "step %d\n", 397 sc->sc_dev.dv_xname, rv, i)); 398 onewire_unlock(sc); 399 return; 400 } 401 rom |= (mask << i); 402 } 403 lastd = i0; 404 onewire_unlock(sc); 405 406 if (rom == 0) 407 continue; 408 409 /* 410 * The last byte of the ROM code contains a CRC calculated 411 * from the first 7 bytes. Re-calculate it to make sure 412 * we found a valid device. 413 */ 414 for (i = 0; i < 8; i++) 415 data[i] = (rom >> (i * 8)) & 0xff; 416 if (onewire_crc(data, 7) != data[7]) 417 continue; 418 419 /* 420 * Go through the list of attached devices to see if we 421 * found a new one. 422 */ 423 present = 0; 424 TAILQ_FOREACH(d, &sc->sc_devs, d_list) { 425 if (d->d_rom == rom) { 426 d->d_present = 1; 427 present = 1; 428 break; 429 } 430 } 431 if (!present) { 432 bzero(&oa, sizeof(oa)); 433 oa.oa_onewire = sc; 434 oa.oa_rom = rom; 435 if ((dev = config_found(&sc->sc_dev, &oa, 436 onewire_print)) == NULL) 437 continue; 438 439 MALLOC(nd, struct onewire_device *, 440 sizeof(struct onewire_device), M_DEVBUF, M_NOWAIT); 441 if (nd == NULL) 442 continue; 443 nd->d_dev = dev; 444 nd->d_rom = rom; 445 nd->d_present = 1; 446 TAILQ_INSERT_TAIL(&sc->sc_devs, nd, d_list); 447 } 448 } 449 450 /* Detach disappeared devices */ 451 onewire_lock(sc, 0); 452 for (d = TAILQ_FIRST(&sc->sc_devs); 453 d != NULL; d = next) { 454 next = TAILQ_NEXT(d, d_list); 455 if (!d->d_present) { 456 config_detach(d->d_dev, DETACH_FORCE); 457 TAILQ_REMOVE(&sc->sc_devs, d, d_list); 458 FREE(d, M_DEVBUF); 459 } 460 } 461 onewire_unlock(sc); 462 } 463