Module Name:    src
Committed By:   bouyer
Date:           Mon Apr 17 20:32:27 UTC 2017

Modified Files:
        src/sys/netcan [bouyer-socketcan]: Makefile can.c can.h can_var.h
Added Files:
        src/sys/netcan [bouyer-socketcan]: can_link.h

Log Message:
Add infranstructure to configure timings from userland on a can interface.
This uses the SIOCGDRVSPEC/SIOCSDRVSPEC ioctls.
Compile-tested only.


To generate a diff of this commit:
cvs rdiff -u -r1.1.2.1 -r1.1.2.2 src/sys/netcan/Makefile
cvs rdiff -u -r1.1.2.6 -r1.1.2.7 src/sys/netcan/can.c
cvs rdiff -u -r1.1.2.3 -r1.1.2.4 src/sys/netcan/can.h
cvs rdiff -u -r0 -r1.1.2.1 src/sys/netcan/can_link.h
cvs rdiff -u -r1.1.2.4 -r1.1.2.5 src/sys/netcan/can_var.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/netcan/Makefile
diff -u src/sys/netcan/Makefile:1.1.2.1 src/sys/netcan/Makefile:1.1.2.2
--- src/sys/netcan/Makefile:1.1.2.1	Sun Jan 15 20:27:33 2017
+++ src/sys/netcan/Makefile	Mon Apr 17 20:32:27 2017
@@ -1,8 +1,8 @@
-#	$NetBSD: Makefile,v 1.1.2.1 2017/01/15 20:27:33 bouyer Exp $
+#	$NetBSD: Makefile,v 1.1.2.2 2017/04/17 20:32:27 bouyer Exp $
 
 KDIR=	/sys/netcan
 INCSDIR= /usr/include/netcan
 
-INCS=	can.h
+INCS=	can.h can_link.h
 
 .include <bsd.kinc.mk>

Index: src/sys/netcan/can.c
diff -u src/sys/netcan/can.c:1.1.2.6 src/sys/netcan/can.c:1.1.2.7
--- src/sys/netcan/can.c:1.1.2.6	Sun Feb  5 19:44:53 2017
+++ src/sys/netcan/can.c	Mon Apr 17 20:32:27 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: can.c,v 1.1.2.6 2017/02/05 19:44:53 bouyer Exp $	*/
+/*	$NetBSD: can.c,v 1.1.2.7 2017/04/17 20:32:27 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: can.c,v 1.1.2.6 2017/02/05 19:44:53 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: can.c,v 1.1.2.7 2017/04/17 20:32:27 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -90,6 +90,77 @@ can_init(void)
 /*
  * Generic control operations (ioctl's).
  */
+static int
+can_get_netlink(struct ifnet *ifp, struct ifdrv *ifd)
+{
+	struct canif_softc *csc = ifp->if_softc;
+
+	if (ifp->if_dlt != DLT_CAN_SOCKETCAN || csc == NULL)
+		return EOPNOTSUPP;
+
+	switch(ifd->ifd_cmd) {
+	case CANGLINKTIMECAP:
+		if (ifd->ifd_len != sizeof(struct can_link_timecaps))
+			return EINVAL;
+		return copyout(&csc->csc_timecaps, ifd->ifd_data, ifd->ifd_len);
+	case CANGLINKTIMINGS:
+		if (ifd->ifd_len != sizeof(struct can_link_timings))
+			return EINVAL;
+		return copyout(&csc->csc_timings, ifd->ifd_data, ifd->ifd_len);
+	case CANGLINKMODE:
+		if (ifd->ifd_len != sizeof(uint32_t))
+			return EINVAL;
+		return copyout(&csc->csc_linkmodes, ifd->ifd_data, ifd->ifd_len);
+	}
+	return EOPNOTSUPP;
+}
+
+static int
+can_set_netlink(struct ifnet *ifp, struct ifdrv *ifd)
+{
+	struct canif_softc *csc = ifp->if_softc;
+	uint32_t mode;
+	int error;
+
+	if (ifp->if_dlt != DLT_CAN_SOCKETCAN || csc == NULL)
+		return EOPNOTSUPP;
+
+	error = kauth_authorize_network(curlwp->l_cred,
+		    KAUTH_NETWORK_INTERFACE,
+		    KAUTH_REQ_NETWORK_INTERFACE_SETPRIV, ifp,
+	            (void *)SIOCSDRVSPEC, NULL);
+	if (error != 0)
+		return error;
+
+	if ((ifp->if_flags & IFF_UP) != 0) {
+		return EBUSY;
+	}
+
+	switch(ifd->ifd_cmd) {
+	case CANSLINKTIMINGS:
+		if (ifd->ifd_len != sizeof(struct can_link_timings))
+			return EINVAL;
+		return copyin(ifd->ifd_data, &csc->csc_timings, ifd->ifd_len);
+
+	case CANSLINKMODE:
+	case CANCLINKMODE:
+		if (ifd->ifd_len != sizeof(uint32_t))
+			return EINVAL;
+		error = copyout(ifd->ifd_data, &mode, ifd->ifd_len);
+		if (error)
+			return error;
+		if ((mode & csc->csc_timecaps.cltc_linkmode_caps) != mode)
+			return EINVAL;
+		/* XXX locking */
+		if (ifd->ifd_cmd == CANSLINKMODE)
+			csc->csc_linkmodes |= mode;
+		else
+			csc->csc_linkmodes &= ~mode;
+		return 0;
+	}
+	return EOPNOTSUPP;
+}
+
 /* ARGSUSED */
 static int
 can_control(struct socket *so, u_long cmd, void *data, struct ifnet *ifp)
@@ -98,12 +169,16 @@ can_control(struct socket *so, u_long cm
 	struct can_ifreq *cfr = (struct can_ifreq *)data;
 	int error = 0;
 #endif
-
+	if (ifp == NULL)
+		return (EOPNOTSUPP);
 
 	switch (cmd) {
-
+	case SIOCGDRVSPEC:
+		return can_get_netlink(ifp, (struct ifdrv *) data);
+	case SIOCSDRVSPEC:
+		return can_set_netlink(ifp, (struct ifdrv *) data);
 	default:
-		if (ifp == 0 || ifp->if_ioctl == 0)
+		if (ifp->if_ioctl == 0)
 			return (EOPNOTSUPP);
 		return ((*ifp->if_ioctl)(ifp, cmd, data));
 	}

Index: src/sys/netcan/can.h
diff -u src/sys/netcan/can.h:1.1.2.3 src/sys/netcan/can.h:1.1.2.4
--- src/sys/netcan/can.h:1.1.2.3	Mon Jan 16 18:03:38 2017
+++ src/sys/netcan/can.h	Mon Apr 17 20:32:27 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: can.h,v 1.1.2.3 2017/01/16 18:03:38 bouyer Exp $	*/
+/*	$NetBSD: can.h,v 1.1.2.4 2017/04/17 20:32:27 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -118,12 +118,6 @@ struct can_filter {
 #define CAN_INV_FILTER 0x20000000U
 
 #ifdef _NETBSD_SOURCE
-
-/* CAN sockets ioctl */
-
-#define SIOCSCANBAUD	_IOW('i', 134, int) /* set interface speed */
-#define SIOCGCANBAUD	_IOR('i', 135, int) /* get interface speed */
-
 #ifdef _KERNEL
 
 #define	satoscan(sa)	((struct sockaddr_can *)(sa))

Index: src/sys/netcan/can_var.h
diff -u src/sys/netcan/can_var.h:1.1.2.4 src/sys/netcan/can_var.h:1.1.2.5
--- src/sys/netcan/can_var.h:1.1.2.4	Sun Feb  5 17:37:10 2017
+++ src/sys/netcan/can_var.h	Mon Apr 17 20:32:27 2017
@@ -1,4 +1,4 @@
-/*	$NetBSD: can_var.h,v 1.1.2.4 2017/02/05 17:37:10 bouyer Exp $	*/
+/*	$NetBSD: can_var.h,v 1.1.2.5 2017/04/17 20:32:27 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2003, 2017 The NetBSD Foundation, Inc.
@@ -33,6 +33,8 @@
 #define _NETCAN_CAN_VAR_H_
 
 #include <sys/queue.h>
+#include <sys/device.h>
+#include <netcan/can_link.h>
 
 struct can_ifreq {
 	char            cfr_name[IFNAMSIZ];	/* if name, e.g. "sja0" */
@@ -40,6 +42,17 @@ struct can_ifreq {
 
 #ifdef _KERNEL
 
+/*
+ * common structure for CAN interface drivers. Should be at the start of
+ * each driver's softc.
+ */
+struct canif_softc {
+	device_t csc_dev;
+	struct can_link_timecaps csc_timecaps; /* timing capabilities */
+	struct can_link_timings csc_timings; /* operating timing values */
+	uint32_t csc_linkmodes;
+};
+
 extern struct ifqueue canintrq;
 extern struct domain candomain;
 

Added files:

Index: src/sys/netcan/can_link.h
diff -u /dev/null src/sys/netcan/can_link.h:1.1.2.1
--- /dev/null	Mon Apr 17 20:32:27 2017
+++ src/sys/netcan/can_link.h	Mon Apr 17 20:32:27 2017
@@ -0,0 +1,81 @@
+/*	$NetBSD: can_link.h,v 1.1.2.1 2017/04/17 20:32:27 bouyer Exp $	*/
+
+/*-
+ * Copyright (c) 2017 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Manuel Bouyer
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _NETCAN_CAN_LINK_H
+#define _NETCAN_CAN_LINK_H
+
+/*
+ * CAN bus link-layer related commands, from the SIOCSDRVSPEC
+ */
+
+/* get timing capabilities from HW */
+struct can_link_timecaps {
+	uint32_t cltc_prop_min; /* prop seg, in tq */
+	uint32_t cltc_prop_max;
+	uint32_t cltc_ps1_min; /* phase1 seg, in tq */
+	uint32_t cltc_ps1_max;
+	uint32_t cltc_ps2_min; /* phase 2 seg, in tq */
+	uint32_t cltc_ps2_max;
+	uint32_t cltc_sjw_max;	/* Synchronisation Jump Width */
+	uint32_t cltc_brp_min;	/* bit-rate prescaler */
+	uint32_t cltc_brp_max;
+	uint32_t cltc_brp_inc;
+	uint32_t cltc_clock_freq; /* prescaler input clock, in hz */
+	uint32_t cltc_linkmode_caps; /* link mode, see below */
+};
+#define CANGLINKTIMECAP	0 /* get struct can_link_timecaps */
+
+/* get/set timing parameters */
+struct can_link_timings {
+	uint32_t clt_clock_freq; /* prescaler input clock, in hz */
+	uint32_t clt_brp;	/* prescaler value */
+	uint32_t clt_prop;	/* Propagation segment in tq */
+	uint32_t clt_ps1;	/* Phase segment 1 in tq */
+	uint32_t clt_ps2;	/* Phase segment 2 in tq */
+	uint32_t clt_sjw;	/* Synchronisation jump width in tq */
+};
+#define CANGLINKTIMINGS	1 /* get struct can_link_timings */
+#define CANSLINKTIMINGS	2 /* set struct can_link_timings */
+
+/* link-level modes */
+#define CAN_LINKMODE_LOOPBACK		0x01    /* Loopback mode */
+#define CAN_LINKMODE_LISTENONLY		0x02    /* Listen-only mode */
+#define CAN_LINKMODE_3SAMPLES		0x04    /* Triple sampling mode */
+#define CAN_LINKMODE_PRESUME_ACK	0x08    /* Ignore missing CAN ACKs */
+#define CAN_IFFBITS \
+    "\020\1LOOPBACK\2LISTENONLY\3TRIPLESAMPLE\4PRESUMEACK"
+
+#define CANGLINKMODE	3 /* (uint32_t) get bits */
+#define CANSLINKMODE	4 /* (uint32_t) set bits */
+#define CANCLINKMODE	5 /* (uint32_t) clear bits */
+
+#endif /* _NETCAN_CAN_LINK_H */
+

Reply via email to