Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 24 May 2015 00:53:43 +0000 (UTC)
From:      Ian Lepore <ian@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r283341 - in stable/10/sys: dev/usb/serial kern sys
Message-ID:  <201505240053.t4O0rhpe013434@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201505240053.t4O0rhpe013434>