1 /* $NetBSD: onewire.c,v 1.17 2019/10/25 16:25:14 martin 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.17 2019/10/25 16:25:14 martin 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/kmem.h> 34 #include <sys/proc.h> 35 #include <sys/queue.h> 36 #include <sys/module.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 int onewire_maxdevs = 8; 48 int onewire_scantime = 10; /* was 3 seconds - too often */ 49 50 struct onewire_softc { 51 device_t sc_dev; 52 struct onewire_bus * sc_bus; 53 kmutex_t sc_lock; 54 kcondvar_t sc_scancv; 55 struct lwp * sc_thread; 56 TAILQ_HEAD(, onewire_device) sc_devs; 57 int sc_dying; 58 }; 59 60 struct onewire_device { 61 TAILQ_ENTRY(onewire_device) d_list; 62 device_t d_dev; 63 u_int64_t d_rom; 64 bool d_present; 65 }; 66 67 static int onewire_match(device_t, cfdata_t, void *); 68 static void onewire_attach(device_t, device_t, void *); 69 static int onewire_detach(device_t, int); 70 static int onewire_activate(device_t, enum devact); 71 int onewire_print(void *, const char *); 72 73 static void onewire_thread(void *); 74 static void onewire_scan(struct onewire_softc *); 75 76 CFATTACH_DECL_NEW(onewire, sizeof(struct onewire_softc), 77 onewire_match, onewire_attach, onewire_detach, onewire_activate); 78 79 extern struct cfdriver onewire_cd; 80 81 static int 82 onewire_match(device_t parent, cfdata_t cf, void *aux) 83 { 84 return 1; 85 } 86 87 static void 88 onewire_attach(device_t parent, device_t self, void *aux) 89 { 90 struct onewire_softc *sc = device_private(self); 91 struct onewirebus_attach_args *oba = aux; 92 93 sc->sc_dev = self; 94 sc->sc_bus = oba->oba_bus; 95 mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE); 96 cv_init(&sc->sc_scancv, "owscan"); 97 TAILQ_INIT(&sc->sc_devs); 98 99 aprint_normal("\n"); 100 101 if (kthread_create(PRI_NONE, KTHREAD_MUSTJOIN | KTHREAD_MPSAFE, NULL, 102 onewire_thread, sc, &sc->sc_thread, "%s", device_xname(self)) != 0) { 103 aprint_error_dev(self, "can't create kernel thread\n"); 104 /* Normally the kthread destroys these. */ 105 mutex_destroy(&sc->sc_lock); 106 cv_destroy(&sc->sc_scancv); 107 } 108 } 109 110 static int 111 onewire_detach(device_t self, int flags) 112 { 113 struct onewire_softc *sc = device_private(self); 114 int rv; 115 116 if (sc->sc_thread != NULL) { 117 mutex_enter(&sc->sc_lock); 118 sc->sc_dying = 1; 119 cv_broadcast(&sc->sc_scancv); 120 mutex_exit(&sc->sc_lock); 121 /* Must no longer touch sc_lock nor sc_scancv. */ 122 kthread_join(sc->sc_thread); 123 } 124 125 //rv = config_detach_children(self, flags); 126 rv = 0; /* XXX riz */ 127 128 return rv; 129 } 130 131 static int 132 onewire_activate(device_t self, enum devact act) 133 { 134 struct onewire_softc *sc = device_private(self); 135 136 switch (act) { 137 case DVACT_DEACTIVATE: 138 sc->sc_dying = 1; 139 return 0; 140 default: 141 return EOPNOTSUPP; 142 } 143 } 144 145 int 146 onewire_print(void *aux, const char *pnp) 147 { 148 struct onewire_attach_args *oa = aux; 149 const char *famname; 150 151 if (pnp == NULL) 152 aprint_normal(" "); 153 154 famname = onewire_famname(ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom)); 155 if (famname == NULL) 156 aprint_normal("family 0x%02x", 157 (uint)ONEWIRE_ROM_FAMILY_TYPE(oa->oa_rom)); 158 else 159 aprint_normal("\"%s\"", famname); 160 aprint_normal(" sn %012" PRIx64, ONEWIRE_ROM_SN(oa->oa_rom)); 161 162 if (pnp != NULL) 163 aprint_normal(" at %s", pnp); 164 165 return UNCONF; 166 } 167 168 int 169 onewirebus_print(void *aux, const char *pnp) 170 { 171 if (pnp != NULL) 172 aprint_normal("onewire at %s", pnp); 173 174 return UNCONF; 175 } 176 177 void 178 onewire_lock(void *arg) 179 { 180 struct onewire_softc *sc = arg; 181 182 mutex_enter(&sc->sc_lock); 183 } 184 185 void 186 onewire_unlock(void *arg) 187 { 188 struct onewire_softc *sc = arg; 189 190 mutex_exit(&sc->sc_lock); 191 } 192 193 int 194 onewire_reset(void *arg) 195 { 196 struct onewire_softc *sc = arg; 197 struct onewire_bus *bus = sc->sc_bus; 198 199 KASSERT(mutex_owned(&sc->sc_lock)); 200 201 return bus->bus_reset(bus->bus_cookie); 202 } 203 204 int 205 onewire_bit(void *arg, int value) 206 { 207 struct onewire_softc *sc = arg; 208 struct onewire_bus *bus = sc->sc_bus; 209 210 KASSERT(mutex_owned(&sc->sc_lock)); 211 212 return bus->bus_bit(bus->bus_cookie, value); 213 } 214 215 int 216 onewire_read_byte(void *arg) 217 { 218 struct onewire_softc *sc = arg; 219 struct onewire_bus *bus = sc->sc_bus; 220 uint8_t value = 0; 221 int i; 222 223 KASSERT(mutex_owned(&sc->sc_lock)); 224 225 if (bus->bus_read_byte != NULL) 226 return bus->bus_read_byte(bus->bus_cookie); 227 228 for (i = 0; i < 8; i++) 229 value |= (bus->bus_bit(bus->bus_cookie, 1) << i); 230 231 return value; 232 } 233 234 void 235 onewire_write_byte(void *arg, int value) 236 { 237 struct onewire_softc *sc = arg; 238 struct onewire_bus *bus = sc->sc_bus; 239 int i; 240 241 KASSERT(mutex_owned(&sc->sc_lock)); 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 KASSERT(mutex_owned(&sc->sc_lock)); 258 259 if (bus->bus_triplet != NULL) 260 return bus->bus_triplet(bus->bus_cookie, dir); 261 262 rv = bus->bus_bit(bus->bus_cookie, 1); 263 rv <<= 1; 264 rv |= bus->bus_bit(bus->bus_cookie, 1); 265 266 switch (rv) { 267 case 0x0: 268 bus->bus_bit(bus->bus_cookie, dir); 269 break; 270 case 0x1: 271 bus->bus_bit(bus->bus_cookie, 0); 272 break; 273 default: 274 bus->bus_bit(bus->bus_cookie, 1); 275 } 276 277 return rv; 278 } 279 280 void 281 onewire_read_block(void *arg, void *buf, int len) 282 { 283 struct onewire_softc *sc = arg; 284 uint8_t *p = buf; 285 286 KASSERT(mutex_owned(&sc->sc_lock)); 287 288 while (len--) 289 *p++ = onewire_read_byte(sc); 290 } 291 292 void 293 onewire_write_block(void *arg, const void *buf, int len) 294 { 295 struct onewire_softc *sc = arg; 296 const uint8_t *p = buf; 297 298 KASSERT(mutex_owned(&sc->sc_lock)); 299 300 while (len--) 301 onewire_write_byte(sc, *p++); 302 } 303 304 void 305 onewire_matchrom(void *arg, u_int64_t rom) 306 { 307 struct onewire_softc *sc = arg; 308 int i; 309 310 KASSERT(mutex_owned(&sc->sc_lock)); 311 312 onewire_write_byte(sc, ONEWIRE_CMD_MATCH_ROM); 313 for (i = 0; i < 8; i++) 314 onewire_write_byte(sc, (rom >> (i * 8)) & 0xff); 315 } 316 317 static void 318 onewire_thread(void *arg) 319 { 320 struct onewire_softc *sc = arg; 321 322 mutex_enter(&sc->sc_lock); 323 while (!sc->sc_dying) { 324 onewire_scan(sc); 325 (void)cv_timedwait(&sc->sc_scancv, &sc->sc_lock, 326 onewire_scantime * hz); 327 } 328 mutex_exit(&sc->sc_lock); 329 330 /* Caller has set sc_dying and will no longer touch these. */ 331 cv_destroy(&sc->sc_scancv); 332 mutex_destroy(&sc->sc_lock); 333 kthread_exit(0); 334 } 335 336 static void 337 onewire_scan(struct onewire_softc *sc) 338 { 339 struct onewire_device *d, *next, *nd; 340 struct onewire_attach_args oa; 341 int search = 1, count = 0, present; 342 int dir, rv; 343 uint64_t mask, rom = 0, lastrom; 344 uint8_t data[8]; 345 int i, i0 = -1, lastd = -1; 346 347 TAILQ_FOREACH(d, &sc->sc_devs, d_list) { 348 d->d_present = false; 349 KASSERT(d->d_dev != NULL); 350 } 351 352 KASSERT(mutex_owned(&sc->sc_lock)); 353 KASSERT(curlwp == sc->sc_thread); 354 355 while (search && count++ < onewire_maxdevs) { 356 /* 357 * Reset the bus. If there's no presence pulse 358 * don't search for any devices. 359 */ 360 if (onewire_reset(sc) != 0) { 361 DPRINTF(("%s: scan: no presence pulse\n", 362 device_xname(sc->sc_dev))); 363 break; 364 } 365 366 /* 367 * Start new search. Go through the previous path to 368 * the point we made a decision last time and make an 369 * opposite decision. If we didn't make any decision 370 * stop searching. 371 */ 372 search = 0; 373 lastrom = rom; 374 rom = 0; 375 onewire_write_byte(sc, ONEWIRE_CMD_SEARCH_ROM); 376 for (i = 0,i0 = -1; i < 64; i++) { 377 dir = (lastrom >> i) & 0x1; 378 if (i == lastd) 379 dir = 1; 380 else if (i > lastd) 381 dir = 0; 382 rv = onewire_triplet(sc, dir); 383 switch (rv) { 384 case 0x0: 385 if (i != lastd) { 386 if (dir == 0) 387 i0 = i; 388 search = 1; 389 } 390 mask = dir; 391 break; 392 case 0x1: 393 mask = 0; 394 break; 395 case 0x2: 396 mask = 1; 397 break; 398 default: 399 DPRINTF(("%s: scan: triplet error 0x%x, " 400 "step %d\n", 401 device_xname(sc->sc_dev), rv, i)); 402 return; 403 } 404 rom |= (mask << i); 405 } 406 lastd = i0; 407 408 if (rom == 0) 409 continue; 410 411 /* 412 * The last byte of the ROM code contains a CRC calculated 413 * from the first 7 bytes. Re-calculate it to make sure 414 * we found a valid device. 415 */ 416 for (i = 0; i < 8; i++) 417 data[i] = (rom >> (i * 8)) & 0xff; 418 if (onewire_crc(data, 7) != data[7]) 419 continue; 420 421 /* 422 * Go through the list of attached devices to see if we 423 * found a new one. 424 */ 425 present = 0; 426 TAILQ_FOREACH(d, &sc->sc_devs, d_list) { 427 if (d->d_rom == rom) { 428 d->d_present = true; 429 present = 1; 430 break; 431 } 432 } 433 if (!present) { 434 nd = kmem_alloc(sizeof(*nd), KM_SLEEP); 435 nd->d_dev = NULL; 436 nd->d_rom = rom; 437 nd->d_present = true; 438 TAILQ_INSERT_TAIL(&sc->sc_devs, nd, d_list); 439 } 440 441 /* 442 * Yield processor, but continue to hold the lock 443 * so that scan is not interrupted. 444 */ 445 kpause("owscan", false, 1, NULL); 446 } 447 448 /* 449 * Detach disappeared devices, and attach new devices. Drop the 450 * lock when doing this in order to prevent lock order reversal 451 * against sysmon. This is safe because nothing other than this 452 * kthread modifies our device list. 453 */ 454 for (d = TAILQ_FIRST(&sc->sc_devs); d != NULL; d = next) { 455 next = TAILQ_NEXT(d, d_list); 456 if (!d->d_present) { 457 mutex_exit(&sc->sc_lock); 458 459 KERNEL_LOCK(1, NULL); /* XXXSMP */ 460 config_detach(d->d_dev, DETACH_FORCE); 461 d->d_dev = NULL; 462 KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */ 463 464 mutex_enter(&sc->sc_lock); 465 } else if (d->d_dev == NULL) { 466 memset(&oa, 0, sizeof(oa)); 467 oa.oa_onewire = sc; 468 oa.oa_rom = d->d_rom; 469 mutex_exit(&sc->sc_lock); 470 471 KERNEL_LOCK(1, NULL); /* XXXSMP */ 472 d->d_dev = config_found(sc->sc_dev, &oa, onewire_print); 473 KERNEL_UNLOCK_ONE(NULL); /* XXXSMP */ 474 475 mutex_enter(&sc->sc_lock); 476 } 477 if (d->d_dev == NULL) { 478 TAILQ_REMOVE(&sc->sc_devs, d, d_list); 479 kmem_free(d, sizeof(*d)); 480 } 481 } 482 } 483 484 MODULE(MODULE_CLASS_DRIVER, onewire, NULL); 485 486 #ifdef _MODULE 487 #include "ioconf.c" 488 #endif 489 490 static int 491 onewire_modcmd(modcmd_t cmd, void *opaque) 492 { 493 int error; 494 495 error = 0; 496 switch (cmd) { 497 case MODULE_CMD_INIT: 498 #ifdef _MODULE 499 error = config_init_component(cfdriver_ioconf_onewire, 500 cfattach_ioconf_onewire, cfdata_ioconf_onewire); 501 if (error) 502 aprint_error("%s: unable to init component\n", 503 onewire_cd.cd_name); 504 #endif 505 break; 506 case MODULE_CMD_FINI: 507 #ifdef _MODULE 508 config_fini_component(cfdriver_ioconf_onewire, 509 cfattach_ioconf_onewire, cfdata_ioconf_onewire); 510 #endif 511 break; 512 default: 513 error = ENOTTY; 514 } 515 return error; 516 } 517