Module Name: src Committed By: gdt Date: Fri Jul 25 16:13:21 UTC 2014
Modified Files: src/share/man/man4: ucom.4 src/sys/dev/usb: ucom.c Log Message: Add PPS support to ucom(4). This is basically cribbed from regular serial ports, and just adds hooks to call the pps support routines. Also, note in the ucom(4) man page that there is about 1 ms of latency. Discussed on tech-kern in October of 2013, with the only concern being that someone who didn't know what they were doing might set up a stratum 1 server, and that somehow might have worse timekeeping than whatever else that person might have done; the man page comment is a mitigation for this. This patch has been live-tested in netbsd-5/i386 and netbsd-6/i386, and has been running on machines without a USB-serial GPS device for most of a year with no adverse consequences (very little happens if the PPS ioctls are not invoked). To generate a diff of this commit: cvs rdiff -u -r1.23 -r1.24 src/share/man/man4/ucom.4 cvs rdiff -u -r1.105 -r1.106 src/sys/dev/usb/ucom.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/share/man/man4/ucom.4 diff -u src/share/man/man4/ucom.4:1.23 src/share/man/man4/ucom.4:1.24 --- src/share/man/man4/ucom.4:1.23 Thu Apr 17 17:50:21 2014 +++ src/share/man/man4/ucom.4 Fri Jul 25 16:13:21 2014 @@ -1,4 +1,4 @@ -.\" $NetBSD: ucom.4,v 1.23 2014/04/17 17:50:21 martin Exp $ +.\" $NetBSD: ucom.4,v 1.24 2014/07/25 16:13:21 gdt Exp $ .\" .\" Copyright (c) 1999 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -69,6 +69,12 @@ The .Va portno locator can be used to decide which port to use for device that have multiple external ports. +.Pp +Note that while +.Nm +supports the (undocumented) pulse-per-second API normally used on +conventional serial ports, USB serial devices typically have a varying +latency around 1 ms due to the USB frame structure. .Sh FILES .Bl -tag -width Pa .It Pa /dev/dtyU? Index: src/sys/dev/usb/ucom.c diff -u src/sys/dev/usb/ucom.c:1.105 src/sys/dev/usb/ucom.c:1.106 --- src/sys/dev/usb/ucom.c:1.105 Fri Jul 25 08:10:39 2014 +++ src/sys/dev/usb/ucom.c Fri Jul 25 16:13:21 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: ucom.c,v 1.105 2014/07/25 08:10:39 dholland Exp $ */ +/* $NetBSD: ucom.c,v 1.106 2014/07/25 16:13:21 gdt Exp $ */ /* * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.105 2014/07/25 08:10:39 dholland Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.106 2014/07/25 16:13:21 gdt Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.1 #include <sys/poll.h> #include <sys/queue.h> #include <sys/kauth.h> +#include <sys/timepps.h> #include <sys/rnd.h> #include <dev/usb/usb.h> @@ -141,6 +142,8 @@ struct ucom_softc { int sc_refcnt; u_char sc_dying; /* disconnecting */ + struct pps_state sc_pps_state; /* pps state */ + krndsource_t sc_rndsource; /* random source */ }; @@ -418,6 +421,13 @@ ucomopen(dev_t dev, int flag, int mode, ucom_status_change(sc); + /* Clear PPS capture state on first open. */ + mutex_spin_enter(&timecounter_lock); + memset(&sc->sc_pps_state, 0, sizeof(sc->sc_pps_state)); + sc->sc_pps_state.ppscap = PPS_CAPTUREASSERT | PPS_CAPTURECLEAR; + pps_init(&sc->sc_pps_state); + mutex_spin_exit(&timecounter_lock); + /* * Initialize the termios status to the defaults. Add in the * sticky bits from TIOCSFLAGS. @@ -775,6 +785,20 @@ ucom_do_ioctl(struct ucom_softc *sc, u_l *(int *)data = ucom_to_tiocm(sc); break; + case PPS_IOC_CREATE: + case PPS_IOC_DESTROY: + case PPS_IOC_GETPARAMS: + case PPS_IOC_SETPARAMS: + case PPS_IOC_GETCAP: + case PPS_IOC_FETCH: +#ifdef PPS_SYNC + case PPS_IOC_KCBIND: +#endif + mutex_spin_enter(&timecounter_lock); + error = pps_ioctl(cmd, data, &sc->sc_pps_state); + mutex_spin_exit(&timecounter_lock); + break; + default: error = EPASSTHROUGH; break; @@ -888,9 +912,18 @@ ucom_status_change(struct ucom_softc *sc old_msr = sc->sc_msr; sc->sc_methods->ucom_get_status(sc->sc_parent, sc->sc_portno, &sc->sc_lsr, &sc->sc_msr); - if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) + if (ISSET((sc->sc_msr ^ old_msr), UMSR_DCD)) { + mutex_spin_enter(&timecounter_lock); + pps_capture(&sc->sc_pps_state); + pps_event(&sc->sc_pps_state, + (sc->sc_msr & UMSR_DCD) ? + PPS_CAPTUREASSERT : + PPS_CAPTURECLEAR); + mutex_spin_exit(&timecounter_lock); + (*tp->t_linesw->l_modem)(tp, ISSET(sc->sc_msr, UMSR_DCD)); + } } else { sc->sc_lsr = 0; /* Assume DCD is present, if we have no chance to check it. */