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 */
+