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