Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src Add PPS support to ucom(4).



details:   https://anonhg.NetBSD.org/src/rev/0b806c6474a3
branches:  trunk
changeset: 797707:0b806c6474a3
user:      gdt <gdt%NetBSD.org@localhost>
date:      Fri Jul 25 16:13:21 2014 +0000

description:
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).

diffstat:

 share/man/man4/ucom.4 |   8 +++++++-
 sys/dev/usb/ucom.c    |  39 ++++++++++++++++++++++++++++++++++++---
 2 files changed, 43 insertions(+), 4 deletions(-)

diffs (112 lines):

diff -r 1fa664dd6bab -r 0b806c6474a3 share/man/man4/ucom.4
--- a/share/man/man4/ucom.4     Fri Jul 25 16:04:27 2014 +0000
+++ b/share/man/man4/ucom.4     Fri Jul 25 16:13:21 2014 +0000
@@ -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 @@
 .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?
diff -r 1fa664dd6bab -r 0b806c6474a3 sys/dev/usb/ucom.c
--- a/sys/dev/usb/ucom.c        Fri Jul 25 16:04:27 2014 +0000
+++ b/sys/dev/usb/ucom.c        Fri Jul 25 16:13:21 2014 +0000
@@ -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 @@
 #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 @@
        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 @@
 
                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 @@
                *(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 @@
                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. */



Home | Main Index | Thread Index | Old Index