Home | History | Annotate | Line # | Download | only in onewire
onewire.c revision 1.17
      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 (at) 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