Author: ian
Date: Sun May 24 00:53:43 2015
New Revision: 283341
URL: https://svnweb.freebsd.org/changeset/base/283341

Log:
  MFC r279728, r279729, r279756, r279773, r282424, r281367:
  
    Add mutex support to the pps_ioctl() API in the kernel.
  
    Add PPS support to USB serial drivers.
  
    Use correct mode variable for PPS support.
  
    Switch polarity of USB serial PPS events.
  
    The ftdi "get latency" and "get bitmode" device commands are read
    operations, not writes.
  
    Implement a mechanism for making changes in the kernel<->driver PPS
    interface without breaking ABI or API compatibility with existing drivers.
  
    Bump version number to indicate the new PPS ABI version changes in the
    pps_state structure.

Modified:
  stable/10/sys/dev/usb/serial/uftdi.c
  stable/10/sys/dev/usb/serial/usb_serial.c
  stable/10/sys/dev/usb/serial/usb_serial.h
  stable/10/sys/kern/kern_tc.c
  stable/10/sys/sys/param.h
  stable/10/sys/sys/timepps.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/dev/usb/serial/uftdi.c
==============================================================================
--- stable/10/sys/dev/usb/serial/uftdi.c        Sat May 23 23:35:19 2015        
(r283340)
+++ stable/10/sys/dev/usb/serial/uftdi.c        Sun May 24 00:53:43 2015        
(r283341)
@@ -1703,7 +1703,7 @@ uftdi_get_bitmode(struct ucom_softc *uco
        struct uftdi_softc *sc = ucom->sc_parent;
        usb_device_request_t req;
 
-       req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+       req.bmRequestType = UT_READ_VENDOR_DEVICE;
        req.bRequest = FTDI_SIO_GET_BITMODE;
 
        USETW(req.wIndex, sc->sc_ucom.sc_portno);
@@ -1740,7 +1740,7 @@ uftdi_get_latency(struct ucom_softc *uco
        usb_error_t err;
        uint8_t buf;
 
-       req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
+       req.bmRequestType = UT_READ_VENDOR_DEVICE;
        req.bRequest = FTDI_SIO_GET_LATENCY;
 
        USETW(req.wIndex, sc->sc_ucom.sc_portno);

Modified: stable/10/sys/dev/usb/serial/usb_serial.c
==============================================================================
--- stable/10/sys/dev/usb/serial/usb_serial.c   Sat May 23 23:35:19 2015        
(r283340)
+++ stable/10/sys/dev/usb/serial/usb_serial.c   Sun May 24 00:53:43 2015        
(r283341)
@@ -96,6 +96,11 @@ __FBSDID("$FreeBSD$");
 
 static SYSCTL_NODE(_hw_usb, OID_AUTO, ucom, CTLFLAG_RW, 0, "USB ucom");
 
+static int ucom_pps_mode;
+
+SYSCTL_INT(_hw_usb_ucom, OID_AUTO, pps_mode, CTLFLAG_RWTUN,
+    &ucom_pps_mode, 0, "pulse capturing mode - 0/1/2 - disabled/CTS/DCD");
+
 #ifdef USB_DEBUG
 static int ucom_debug = 0;
 
@@ -412,6 +417,11 @@ ucom_attach_tty(struct ucom_super_softc 
 
        sc->sc_tty = tp;
 
+       sc->sc_pps.ppscap = PPS_CAPTUREBOTH;
+       sc->sc_pps.driver_abi = PPS_ABI_VERSION;
+       sc->sc_pps.driver_mtx = sc->sc_mtx;
+       pps_init_abi(&sc->sc_pps);
+
        DPRINTF("ttycreate: %s\n", buf);
 
        /* Check if this device should be a console */
@@ -861,6 +871,8 @@ ucom_ioctl(struct tty *tp, u_long cmd, c
                } else {
                        error = ENOIOCTL;
                }
+               if (error == ENOIOCTL)
+                       error = pps_ioctl(cmd, data, &sc->sc_pps);
                break;
        }
        return (error);
@@ -1064,7 +1076,7 @@ ucom_cfg_status_change(struct usb_proc_m
        struct tty *tp;
        uint8_t new_msr;
        uint8_t new_lsr;
-       uint8_t onoff;
+       uint8_t msr_delta;
        uint8_t lsr_delta;
 
        tp = sc->sc_tty;
@@ -1088,15 +1100,42 @@ ucom_cfg_status_change(struct usb_proc_m
                /* TTY device closed */
                return;
        }
-       onoff = ((sc->sc_msr ^ new_msr) & SER_DCD);
+       msr_delta = (sc->sc_msr ^ new_msr);
        lsr_delta = (sc->sc_lsr ^ new_lsr);
 
        sc->sc_msr = new_msr;
        sc->sc_lsr = new_lsr;
 
-       if (onoff) {
+       /*
+        * Time pulse counting support. Note that both CTS and DCD are
+        * active-low signals. The status bit is high to indicate that
+        * the signal on the line is low, which corresponds to a PPS
+        * clear event.
+        */
+       switch(ucom_pps_mode) {
+       case 1:
+               if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) &&
+                   (msr_delta & SER_CTS)) {
+                       pps_capture(&sc->sc_pps);
+                       pps_event(&sc->sc_pps, (sc->sc_msr & SER_CTS) ?
+                           PPS_CAPTURECLEAR : PPS_CAPTUREASSERT);
+               }
+               break;
+       case 2:
+               if ((sc->sc_pps.ppsparam.mode & PPS_CAPTUREBOTH) &&
+                   (msr_delta & SER_DCD)) {
+                       pps_capture(&sc->sc_pps);
+                       pps_event(&sc->sc_pps, (sc->sc_msr & SER_DCD) ?
+                           PPS_CAPTURECLEAR : PPS_CAPTUREASSERT);
+               }
+               break;
+       default:
+               break;
+       }
+
+       if (msr_delta & SER_DCD) {
 
-               onoff = (sc->sc_msr & SER_DCD) ? 1 : 0;
+               int onoff = (sc->sc_msr & SER_DCD) ? 1 : 0;
 
                DPRINTF("DCD changed to %d\n", onoff);
 

Modified: stable/10/sys/dev/usb/serial/usb_serial.h
==============================================================================
--- stable/10/sys/dev/usb/serial/usb_serial.h   Sat May 23 23:35:19 2015        
(r283340)
+++ stable/10/sys/dev/usb/serial/usb_serial.h   Sun May 24 00:53:43 2015        
(r283341)
@@ -64,6 +64,7 @@
 #include <sys/serial.h>
 #include <sys/fcntl.h>
 #include <sys/sysctl.h>
+#include <sys/timepps.h>
 
 /* Module interface related macros */
 #define        UCOM_MODVER     1
@@ -155,6 +156,8 @@ struct ucom_softc {
        struct ucom_cfg_task    sc_line_state_task[2];
        struct ucom_cfg_task    sc_status_task[2];
        struct ucom_param_task  sc_param_task[2];
+       /* pulse capturing support, PPS */
+       struct pps_state        sc_pps;
        /* Used to set "UCOM_FLAG_GP_DATA" flag: */
        struct usb_proc_msg     *sc_last_start_xfer;
        const struct ucom_callback *sc_callback;

Modified: stable/10/sys/kern/kern_tc.c
==============================================================================
--- stable/10/sys/kern/kern_tc.c        Sat May 23 23:35:19 2015        
(r283340)
+++ stable/10/sys/kern/kern_tc.c        Sun May 24 00:53:43 2015        
(r283341)
@@ -23,10 +23,8 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/kernel.h>
 #include <sys/limits.h>
-#ifdef FFCLOCK
 #include <sys/lock.h>
 #include <sys/mutex.h>
-#endif
 #include <sys/sysctl.h>
 #include <sys/syslog.h>
 #include <sys/systm.h>
@@ -1462,6 +1460,17 @@ SYSCTL_PROC(_kern_timecounter, OID_AUTO,
  * RFC 2783 PPS-API implementation.
  */
 
+/*
+ *  Return true if the driver is aware of the abi version extensions in the
+ *  pps_state structure, and it supports at least the given abi version number.
+ */
+static inline int
+abi_aware(struct pps_state *pps, int vers)
+{
+
+       return ((pps->kcmode & KCMODE_ABIFLAG) && pps->driver_abi >= vers);
+}
+
 static int
 pps_fetch(struct pps_fetch_args *fapi, struct pps_state *pps)
 {
@@ -1491,7 +1500,17 @@ pps_fetch(struct pps_fetch_args *fapi, s
                cseq = pps->ppsinfo.clear_sequence;
                while (aseq == pps->ppsinfo.assert_sequence &&
                    cseq == pps->ppsinfo.clear_sequence) {
-                       err = tsleep(pps, PCATCH, "ppsfch", timo);
+                       if (abi_aware(pps, 1) && pps->driver_mtx != NULL) {
+                               if (pps->flags & PPSFLAG_MTX_SPIN) {
+                                       err = msleep_spin(pps, pps->driver_mtx,
+                                           "ppsfch", timo);
+                               } else {
+                                       err = msleep(pps, pps->driver_mtx, 
PCATCH,
+                                           "ppsfch", timo);
+                               }
+                       } else {
+                               err = tsleep(pps, PCATCH, "ppsfch", timo);
+                       }
                        if (err == EWOULDBLOCK && fapi->timeout.tv_sec == -1) {
                                continue;
                        } else if (err != 0) {
@@ -1581,7 +1600,8 @@ pps_ioctl(u_long cmd, caddr_t data, stru
                        return (EINVAL);
                if (kapi->edge & ~pps->ppscap)
                        return (EINVAL);
-               pps->kcmode = kapi->edge;
+               pps->kcmode = (kapi->edge & KCMODE_EDGEMASK) |
+                   (pps->kcmode & KCMODE_ABIFLAG);
                return (0);
 #else
                return (EOPNOTSUPP);
@@ -1602,6 +1622,18 @@ pps_init(struct pps_state *pps)
 #ifdef FFCLOCK
        pps->ppscap |= PPS_TSCLK_MASK;
 #endif
+       pps->kcmode &= ~KCMODE_ABIFLAG;
+}
+
+void
+pps_init_abi(struct pps_state *pps)
+{
+
+       pps_init(pps);
+       if (pps->driver_abi > 0) {
+               pps->kcmode |= KCMODE_ABIFLAG;
+               pps->kernel_abi = PPS_ABI_VERSION;
+       }
 }
 
 void

Modified: stable/10/sys/sys/param.h
==============================================================================
--- stable/10/sys/sys/param.h   Sat May 23 23:35:19 2015        (r283340)
+++ stable/10/sys/sys/param.h   Sun May 24 00:53:43 2015        (r283341)
@@ -58,7 +58,7 @@
  *             in the range 5 to 9.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1001515      /* Master, propagated to newvers */
+#define __FreeBSD_version 1001516      /* Master, propagated to newvers */
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

Modified: stable/10/sys/sys/timepps.h
==============================================================================
--- stable/10/sys/sys/timepps.h Sat May 23 23:35:19 2015        (r283340)
+++ stable/10/sys/sys/timepps.h Sun May 24 00:53:43 2015        (r283341)
@@ -133,6 +133,15 @@ struct pps_kcbind_args {
 
 #ifdef _KERNEL
 
+struct mtx;
+
+#define        KCMODE_EDGEMASK         0x03
+#define        KCMODE_ABIFLAG          0x80000000 /* Internal use: abi-aware 
driver. */
+
+#define        PPS_ABI_VERSION         1
+
+#define        PPSFLAG_MTX_SPIN        0x01    /* Driver mtx is MTX_SPIN type. 
*/
+
 struct pps_state {
        /* Capture information. */
        struct timehands *capth;
@@ -148,11 +157,19 @@ struct pps_state {
        int             ppscap;
        struct timecounter *ppstc;
        unsigned        ppscount[3];
+       /*
+        * The following fields are valid if the driver calls pps_init_abi().
+        */
+       uint16_t        driver_abi;     /* Driver sets before pps_init_abi(). */
+       uint16_t        kernel_abi;     /* Kernel sets during pps_init_abi(). */
+       struct mtx      *driver_mtx;    /* Optional, valid if non-NULL. */
+       uint32_t        flags;
 };
 
 void pps_capture(struct pps_state *pps);
 void pps_event(struct pps_state *pps, int event);
 void pps_init(struct pps_state *pps);
+void pps_init_abi(struct pps_state *pps);
 int pps_ioctl(unsigned long cmd, caddr_t data, struct pps_state *pps);
 void hardpps(struct timespec *tsp, long nsec);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to