Home | History | Annotate | Line # | Download | only in usb
if_gscan.c revision 1.3.4.2
      1  1.3.4.2  perseant /*	$NetBSD: if_gscan.c,v 1.3.4.2 2025/08/02 05:57:05 perseant Exp $	*/
      2  1.3.4.2  perseant 
      3  1.3.4.2  perseant /*
      4  1.3.4.2  perseant  * Copyright (c) 2025 The NetBSD Foundation, Inc.
      5  1.3.4.2  perseant  * All rights reserved.
      6  1.3.4.2  perseant  *
      7  1.3.4.2  perseant  * This code is derived from software contributed to The NetBSD Foundation
      8  1.3.4.2  perseant  * by Manuel Bouyer.
      9  1.3.4.2  perseant  *
     10  1.3.4.2  perseant  * Redistribution and use in source and binary forms, with or without
     11  1.3.4.2  perseant  * modification, are permitted provided that the following conditions
     12  1.3.4.2  perseant  * are met:
     13  1.3.4.2  perseant  * 1. Redistributions of source code must retain the above copyright
     14  1.3.4.2  perseant  *    notice, this list of conditions and the following disclaimer.
     15  1.3.4.2  perseant  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.3.4.2  perseant  *    notice, this list of conditions and the following disclaimer in the
     17  1.3.4.2  perseant  *    documentation and/or other materials provided with the distribution.
     18  1.3.4.2  perseant  *
     19  1.3.4.2  perseant  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.3.4.2  perseant  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.3.4.2  perseant  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.3.4.2  perseant  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.3.4.2  perseant  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.3.4.2  perseant  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.3.4.2  perseant  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.3.4.2  perseant  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.3.4.2  perseant  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.3.4.2  perseant  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.3.4.2  perseant  * POSSIBILITY OF SUCH DAMAGE.
     30  1.3.4.2  perseant  */
     31  1.3.4.2  perseant 
     32  1.3.4.2  perseant 
     33  1.3.4.2  perseant #include <sys/cdefs.h>
     34  1.3.4.2  perseant __KERNEL_RCSID(0, "$NetBSD: if_gscan.c,v 1.3.4.2 2025/08/02 05:57:05 perseant Exp $");
     35  1.3.4.2  perseant 
     36  1.3.4.2  perseant #ifdef _KERNEL_OPT
     37  1.3.4.2  perseant #include "opt_usb.h"
     38  1.3.4.2  perseant #include "opt_net_mpsafe.h"
     39  1.3.4.2  perseant #include "opt_can.h"
     40  1.3.4.2  perseant #endif
     41  1.3.4.2  perseant 
     42  1.3.4.2  perseant #include <sys/param.h>
     43  1.3.4.2  perseant 
     44  1.3.4.2  perseant #include <sys/device.h>
     45  1.3.4.2  perseant #include <sys/mbuf.h>
     46  1.3.4.2  perseant #include <sys/rndsource.h>
     47  1.3.4.2  perseant #include <sys/mutex.h>
     48  1.3.4.2  perseant #include <sys/module.h>
     49  1.3.4.2  perseant #include <sys/syslog.h>
     50  1.3.4.2  perseant 
     51  1.3.4.2  perseant #include <net/bpf.h>
     52  1.3.4.2  perseant #include <net/if.h>
     53  1.3.4.2  perseant #include <net/if_types.h>
     54  1.3.4.2  perseant 
     55  1.3.4.2  perseant #include <netcan/can.h>
     56  1.3.4.2  perseant #include <netcan/can_var.h>
     57  1.3.4.2  perseant 
     58  1.3.4.2  perseant #include <dev/usb/usb.h>
     59  1.3.4.2  perseant #include <dev/usb/usbdi.h>
     60  1.3.4.2  perseant #include <dev/usb/usbdivar.h>
     61  1.3.4.2  perseant #include <dev/usb/usbdi_util.h>
     62  1.3.4.2  perseant #include <dev/usb/usbdevs.h>
     63  1.3.4.2  perseant 
     64  1.3.4.2  perseant #include <dev/usb/usbhist.h>
     65  1.3.4.2  perseant #include <dev/usb/if_gscanreg.h>
     66  1.3.4.2  perseant 
     67  1.3.4.2  perseant #ifdef USB_DEBUG
     68  1.3.4.2  perseant #ifndef GSCAN_DEBUG
     69  1.3.4.2  perseant #define gscandebug 0
     70  1.3.4.2  perseant #else
     71  1.3.4.2  perseant static int gscandebug = 0;
     72  1.3.4.2  perseant SYSCTL_SETUP(sysctl_hw_gscan_setup, "sysctl hw.gscan setup")
     73  1.3.4.2  perseant {
     74  1.3.4.2  perseant 	int err;
     75  1.3.4.2  perseant 	const struct sysctlnode *rnode;
     76  1.3.4.2  perseant 	const struct sysctlnode *cnode;
     77  1.3.4.2  perseant 
     78  1.3.4.2  perseant 	err = sysctl_createv(clog, 0, NULL, &rnode,
     79  1.3.4.2  perseant 	    CTLFLAG_PERMANENT, CTLTYPE_NODE, "gscan",
     80  1.3.4.2  perseant 	    SYSCTL_DESCR("gscan global controls"),
     81  1.3.4.2  perseant 	    NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
     82  1.3.4.2  perseant 
     83  1.3.4.2  perseant 	if (err)
     84  1.3.4.2  perseant 		goto fail;
     85  1.3.4.2  perseant 	/* control debugging printfs */
     86  1.3.4.2  perseant 	err = sysctl_createv(clog, 0, &rnode, &cnode,
     87  1.3.4.2  perseant 	    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
     88  1.3.4.2  perseant 	    "debug", SYSCTL_DESCR("Enable debugging output"),
     89  1.3.4.2  perseant 	    NULL, 0, &gscandebug, sizeof(gscandebug), CTL_CREATE, CTL_EOL);
     90  1.3.4.2  perseant 	if (err)
     91  1.3.4.2  perseant 		goto fail;
     92  1.3.4.2  perseant 
     93  1.3.4.2  perseant 	return;
     94  1.3.4.2  perseant fail:
     95  1.3.4.2  perseant 	aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err);
     96  1.3.4.2  perseant }
     97  1.3.4.2  perseant 
     98  1.3.4.2  perseant #endif /* GSCAN_DEBUG */
     99  1.3.4.2  perseant #endif /* USB_DEBUG */
    100  1.3.4.2  perseant 
    101  1.3.4.2  perseant #define DPRINTF(FMT,A,B,C,D)	USBHIST_LOGN(gscandebug,1,FMT,A,B,C,D)
    102  1.3.4.2  perseant #define DPRINTFN(N,FMT,A,B,C,D)	USBHIST_LOGN(gscandebug,N,FMT,A,B,C,D)
    103  1.3.4.2  perseant #define GSCANHIST_FUNC()	USBHIST_FUNC()
    104  1.3.4.2  perseant #define GSCANHIST_CALLED(name)	USBHIST_CALLED(gscandebug)
    105  1.3.4.2  perseant #define GSCANHIST_CALLARGS(FMT,A,B,C,D) \
    106  1.3.4.2  perseant 		USBHIST_CALLARGS(gscandebug,FMT,A,B,C,D)
    107  1.3.4.2  perseant 
    108  1.3.4.2  perseant struct gscan_softc {
    109  1.3.4.2  perseant 	struct canif_softc sc_cansc;
    110  1.3.4.2  perseant 	struct usbd_interface *sc_iface;
    111  1.3.4.2  perseant 	struct usbd_device    *sc_udev;
    112  1.3.4.2  perseant 	uByte sc_ed_tx;
    113  1.3.4.2  perseant 	uByte sc_ed_rx;
    114  1.3.4.2  perseant 	struct usbd_pipe *sc_tx_pipe;
    115  1.3.4.2  perseant 	struct usbd_pipe *sc_rx_pipe;
    116  1.3.4.2  perseant 	struct usbd_xfer *sc_tx_xfer;
    117  1.3.4.2  perseant 	struct usbd_xfer *sc_rx_xfer;
    118  1.3.4.2  perseant 	struct gscan_frame *sc_tx_frame;
    119  1.3.4.2  perseant 	struct gscan_frame *sc_rx_frame;
    120  1.3.4.2  perseant 	kmutex_t sc_txlock;
    121  1.3.4.2  perseant 	kmutex_t sc_rxlock;
    122  1.3.4.2  perseant 	bool sc_txstopped;
    123  1.3.4.2  perseant 	bool sc_rxstopped;
    124  1.3.4.2  perseant 	int sc_rx_nerr;
    125  1.3.4.2  perseant 	struct ifnet *sc_ifp;
    126  1.3.4.2  perseant 	struct if_percpuq *sc_ipq;
    127  1.3.4.2  perseant 	volatile bool sc_dying;
    128  1.3.4.2  perseant 	krndsource_t sc_rnd_source;
    129  1.3.4.2  perseant 	struct mbuf *sc_m_transmit; /* mbuf being transmitted */
    130  1.3.4.2  perseant };
    131  1.3.4.2  perseant 
    132  1.3.4.2  perseant #define sc_dev	  sc_cansc.csc_dev
    133  1.3.4.2  perseant #define sc_timecaps     sc_cansc.csc_timecaps
    134  1.3.4.2  perseant #define sc_timings      sc_cansc.csc_timings
    135  1.3.4.2  perseant #define sc_linkmodes    sc_cansc.csc_linkmodes
    136  1.3.4.2  perseant 
    137  1.3.4.2  perseant static bool
    138  1.3.4.2  perseant gscan_isdying(struct gscan_softc *sc)
    139  1.3.4.2  perseant {
    140  1.3.4.2  perseant 	return atomic_load_relaxed(&sc->sc_dying);
    141  1.3.4.2  perseant }
    142  1.3.4.2  perseant 
    143  1.3.4.2  perseant static int
    144  1.3.4.2  perseant gscan_write_device(struct gscan_softc *sc, int breq, void *v, int len)
    145  1.3.4.2  perseant {
    146  1.3.4.2  perseant 	usb_device_request_t req;
    147  1.3.4.2  perseant 	req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
    148  1.3.4.2  perseant 	req.bRequest =  breq;
    149  1.3.4.2  perseant 	USETW(req.wValue, 0);
    150  1.3.4.2  perseant 	USETW(req.wIndex, 0);
    151  1.3.4.2  perseant 	USETW(req.wLength, len);
    152  1.3.4.2  perseant 	return usbd_do_request(sc->sc_udev, &req, v);
    153  1.3.4.2  perseant }
    154  1.3.4.2  perseant 
    155  1.3.4.2  perseant static int
    156  1.3.4.2  perseant gscan_read_device(struct gscan_softc *sc, int breq, void *v, int len)
    157  1.3.4.2  perseant {
    158  1.3.4.2  perseant 	usb_device_request_t req;
    159  1.3.4.2  perseant 	req.bmRequestType = UT_READ_VENDOR_DEVICE;
    160  1.3.4.2  perseant 	req.bRequest =  breq;
    161  1.3.4.2  perseant 	USETW(req.wValue, 0);
    162  1.3.4.2  perseant 	USETW(req.wIndex, 0);
    163  1.3.4.2  perseant 	USETW(req.wLength, len);
    164  1.3.4.2  perseant 	return usbd_do_request(sc->sc_udev, &req, v);
    165  1.3.4.2  perseant }
    166  1.3.4.2  perseant 
    167  1.3.4.2  perseant static int	gscan_match(device_t, cfdata_t, void *);
    168  1.3.4.2  perseant static void	gscan_attach(device_t, device_t, void *);
    169  1.3.4.2  perseant static int      gscan_detach(device_t, int);
    170  1.3.4.2  perseant static int	gscan_activate(device_t, devact_t);
    171  1.3.4.2  perseant 
    172  1.3.4.2  perseant static void	gscan_ifstart(struct ifnet *);
    173  1.3.4.2  perseant static int	gscan_ifioctl(struct ifnet *, u_long, void *);
    174  1.3.4.2  perseant static void	gscan_ifwatchdog(struct ifnet *);
    175  1.3.4.2  perseant 
    176  1.3.4.2  perseant static int 	gscan_ifup(struct gscan_softc * const);
    177  1.3.4.2  perseant static void	gscan_stop(struct gscan_softc * const, struct ifnet *, int);
    178  1.3.4.2  perseant static void	gscan_startrx(struct gscan_softc * const);
    179  1.3.4.2  perseant 
    180  1.3.4.2  perseant CFATTACH_DECL_NEW(gscan, sizeof(struct gscan_softc),
    181  1.3.4.2  perseant 	gscan_match, gscan_attach, gscan_detach, gscan_activate);
    182  1.3.4.2  perseant 
    183  1.3.4.2  perseant static void
    184  1.3.4.2  perseant gscan_rx(struct usbd_xfer *xfer, void *priv, usbd_status status)
    185  1.3.4.2  perseant {
    186  1.3.4.2  perseant 	GSCANHIST_FUNC();
    187  1.3.4.2  perseant 	struct gscan_softc *sc = priv;
    188  1.3.4.2  perseant 	struct gscan_frame *gsframe;
    189  1.3.4.2  perseant 	struct can_frame *cf;
    190  1.3.4.2  perseant 	uint32_t len,  dlc, can_id;
    191  1.3.4.2  perseant 	int32_t echo_id;
    192  1.3.4.2  perseant 	struct ifnet *ifp = sc->sc_ifp;
    193  1.3.4.2  perseant 	struct mbuf *m;
    194  1.3.4.2  perseant 
    195  1.3.4.2  perseant 	GSCANHIST_CALLARGS("status: %d", status, 0, 0, 0);
    196  1.3.4.2  perseant 
    197  1.3.4.2  perseant 	mutex_enter(&sc->sc_rxlock);
    198  1.3.4.2  perseant 	if (sc->sc_rxstopped || gscan_isdying(sc) ||
    199  1.3.4.2  perseant 	    status == USBD_NOT_STARTED || status == USBD_CANCELLED ||
    200  1.3.4.2  perseant 	    status == USBD_INVAL) {
    201  1.3.4.2  perseant 		mutex_exit(&sc->sc_rxlock);
    202  1.3.4.2  perseant 		return;
    203  1.3.4.2  perseant 	}
    204  1.3.4.2  perseant 	if (status != USBD_NORMAL_COMPLETION) {
    205  1.3.4.2  perseant 		DPRINTF("rx error: %jd", status, 0, 0, 0);
    206  1.3.4.2  perseant 		if (status == USBD_STALLED)
    207  1.3.4.2  perseant 			usbd_clear_endpoint_stall_async(sc->sc_rx_pipe);
    208  1.3.4.2  perseant 		if (++sc->sc_rx_nerr > 100) {
    209  1.3.4.2  perseant 			log(LOG_ERR, "%s: too many rx errors, disabling\n",
    210  1.3.4.2  perseant 			    device_xname(sc->sc_dev));
    211  1.3.4.2  perseant 			gscan_activate(sc->sc_dev, DVACT_DEACTIVATE);
    212  1.3.4.2  perseant 		}
    213  1.3.4.2  perseant 		goto out;
    214  1.3.4.2  perseant 	}
    215  1.3.4.2  perseant 	sc->sc_rx_nerr = 0;
    216  1.3.4.2  perseant 	usbd_get_xfer_status(xfer, NULL, (void **)&gsframe, &len, NULL);
    217  1.3.4.2  perseant 	if (len < sizeof(struct gscan_frame) - 8) {
    218  1.3.4.2  perseant 		if_statinc(ifp, if_ierrors);
    219  1.3.4.2  perseant 		goto out;
    220  1.3.4.2  perseant 	}
    221  1.3.4.2  perseant 	if (gsframe->gsframe_flags & GSFRAME_FLAG_OVER) {
    222  1.3.4.2  perseant 		if_statinc(ifp, if_ierrors);
    223  1.3.4.2  perseant 		goto out;
    224  1.3.4.2  perseant 	}
    225  1.3.4.2  perseant 	dlc = le32toh(gsframe->gsframe_can_dlc);
    226  1.3.4.2  perseant 	if (dlc > CAN_MAX_DLC) {
    227  1.3.4.2  perseant 		if_statinc(ifp, if_ierrors);
    228  1.3.4.2  perseant 		goto out;
    229  1.3.4.2  perseant 	}
    230  1.3.4.2  perseant 	echo_id = le32toh(gsframe->gsframe_echo_id);
    231  1.3.4.2  perseant 	if (echo_id != -1) {
    232  1.3.4.2  perseant 		/* echo of a frame we sent */
    233  1.3.4.2  perseant 		goto out;
    234  1.3.4.2  perseant 	}
    235  1.3.4.2  perseant 	can_id = le32toh(gsframe->gsframe_can_id);
    236  1.3.4.2  perseant 	/* for now ignore error frames */
    237  1.3.4.2  perseant 	if (can_id & CAN_ERR_FLAG) {
    238  1.3.4.2  perseant 		goto out;
    239  1.3.4.2  perseant 	}
    240  1.3.4.2  perseant 	m = m_gethdr(M_NOWAIT, MT_HEADER);
    241  1.3.4.2  perseant 	if (m == NULL) {
    242  1.3.4.2  perseant 		if_statinc(ifp, if_ierrors);
    243  1.3.4.2  perseant 		goto out;
    244  1.3.4.2  perseant 	}
    245  1.3.4.2  perseant 	cf = mtod(m, struct can_frame *);
    246  1.3.4.2  perseant 	memset(cf, 0, sizeof(struct can_frame));
    247  1.3.4.2  perseant 	cf->can_id = can_id;
    248  1.3.4.2  perseant 	cf->can_dlc = dlc;
    249  1.3.4.2  perseant 	memcpy(&cf->data[0], &gsframe->gsframe_can_data[0], 8);
    250  1.3.4.2  perseant 	/* done with the buffer, get next frame */
    251  1.3.4.2  perseant 	mutex_exit(&sc->sc_rxlock);
    252  1.3.4.2  perseant 	gscan_startrx(sc);
    253  1.3.4.2  perseant 
    254  1.3.4.2  perseant 	m->m_len = m->m_pkthdr.len = CAN_MTU;
    255  1.3.4.2  perseant 	m_set_rcvif(m, ifp);
    256  1.3.4.2  perseant 	if_statadd(ifp, if_ibytes, m->m_len);
    257  1.3.4.2  perseant 	can_bpf_mtap(ifp, m, 1);
    258  1.3.4.2  perseant 	can_input(ifp, m);
    259  1.3.4.2  perseant 	return;
    260  1.3.4.2  perseant 
    261  1.3.4.2  perseant out:
    262  1.3.4.2  perseant 	mutex_exit(&sc->sc_rxlock);
    263  1.3.4.2  perseant 	gscan_startrx(sc);
    264  1.3.4.2  perseant }
    265  1.3.4.2  perseant 
    266  1.3.4.2  perseant static void
    267  1.3.4.2  perseant gscan_startrx(struct gscan_softc * const sc)
    268  1.3.4.2  perseant {
    269  1.3.4.2  perseant 	usbd_setup_xfer(sc->sc_rx_xfer, sc, sc->sc_rx_frame,
    270  1.3.4.2  perseant 	    sizeof(struct gscan_frame), USBD_SHORT_XFER_OK,
    271  1.3.4.2  perseant 	    USBD_NO_TIMEOUT, gscan_rx);
    272  1.3.4.2  perseant 	usbd_transfer(sc->sc_rx_xfer);
    273  1.3.4.2  perseant }
    274  1.3.4.2  perseant 
    275  1.3.4.2  perseant static void
    276  1.3.4.2  perseant gscan_tx(struct usbd_xfer *xfer, void *priv, usbd_status status)
    277  1.3.4.2  perseant {
    278  1.3.4.2  perseant 	GSCANHIST_FUNC();
    279  1.3.4.2  perseant 	struct gscan_softc *sc = priv;
    280  1.3.4.2  perseant 	struct ifnet *ifp = sc->sc_ifp;
    281  1.3.4.2  perseant 	struct mbuf *m;
    282  1.3.4.2  perseant 
    283  1.3.4.2  perseant 	GSCANHIST_CALLARGS("status: %d", status, 0, 0, 0);
    284  1.3.4.2  perseant 	mutex_enter(&sc->sc_txlock);
    285  1.3.4.2  perseant 	if (sc->sc_txstopped || gscan_isdying(sc)) {
    286  1.3.4.2  perseant 		mutex_exit(&sc->sc_txlock);
    287  1.3.4.2  perseant 		return;
    288  1.3.4.2  perseant 	}
    289  1.3.4.2  perseant 	ifp->if_timer = 0;
    290  1.3.4.2  perseant 	m = sc->sc_m_transmit;
    291  1.3.4.2  perseant 	sc->sc_m_transmit = NULL;
    292  1.3.4.2  perseant 	if (m != NULL) {
    293  1.3.4.2  perseant 		if (status == USBD_NORMAL_COMPLETION)
    294  1.3.4.2  perseant 			if_statadd2(ifp, if_obytes, m->m_len, if_opackets, 1);
    295  1.3.4.2  perseant 		can_mbuf_tag_clean(m);
    296  1.3.4.2  perseant 		m_set_rcvif(m, ifp);
    297  1.3.4.2  perseant 		can_input(ifp, m); /* loopback */
    298  1.3.4.2  perseant 	}
    299  1.3.4.2  perseant 	if (status != USBD_NORMAL_COMPLETION) {
    300  1.3.4.2  perseant 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
    301  1.3.4.2  perseant 			mutex_exit(&sc->sc_txlock);
    302  1.3.4.2  perseant 			return;
    303  1.3.4.2  perseant 		}
    304  1.3.4.2  perseant 		DPRINTF("rx error: %jd", status, 0, 0, 0);
    305  1.3.4.2  perseant 		if (status == USBD_STALLED)
    306  1.3.4.2  perseant 			usbd_clear_endpoint_stall_async(sc->sc_rx_pipe);
    307  1.3.4.2  perseant 	}
    308  1.3.4.2  perseant 	if_schedule_deferred_start(ifp);
    309  1.3.4.2  perseant 	mutex_exit(&sc->sc_txlock);
    310  1.3.4.2  perseant }
    311  1.3.4.2  perseant 
    312  1.3.4.2  perseant static void
    313  1.3.4.2  perseant gscan_ifstart(struct ifnet *ifp)
    314  1.3.4.2  perseant {
    315  1.3.4.2  perseant 	GSCANHIST_FUNC();
    316  1.3.4.2  perseant 	struct gscan_softc * const sc = ifp->if_softc;
    317  1.3.4.2  perseant 	struct mbuf *m;
    318  1.3.4.2  perseant 	struct can_frame *cf;
    319  1.3.4.2  perseant 	int err;
    320  1.3.4.2  perseant 	GSCANHIST_CALLED();
    321  1.3.4.2  perseant 
    322  1.3.4.2  perseant 	mutex_enter(&sc->sc_txlock);
    323  1.3.4.2  perseant 	if (sc->sc_txstopped || gscan_isdying(sc))
    324  1.3.4.2  perseant 		goto out;
    325  1.3.4.2  perseant 
    326  1.3.4.2  perseant 	if (sc->sc_m_transmit != NULL)
    327  1.3.4.2  perseant 		goto out;
    328  1.3.4.2  perseant 	IF_DEQUEUE(&ifp->if_snd, m);
    329  1.3.4.2  perseant 	if (m == NULL)
    330  1.3.4.2  perseant 		goto out;
    331  1.3.4.2  perseant 
    332  1.3.4.2  perseant 	MCLAIM(m, ifp->if_mowner);
    333  1.3.4.2  perseant 
    334  1.3.4.2  perseant 	KASSERT((m->m_flags & M_PKTHDR) != 0);
    335  1.3.4.2  perseant 	KASSERT(m->m_len == m->m_pkthdr.len);
    336  1.3.4.2  perseant 
    337  1.3.4.2  perseant 	cf = mtod(m, struct can_frame *);
    338  1.3.4.2  perseant 	memset(sc->sc_tx_frame, 0, sizeof(struct gscan_frame));
    339  1.3.4.2  perseant 	sc->sc_tx_frame->gsframe_echo_id = 0;
    340  1.3.4.2  perseant 	sc->sc_tx_frame->gsframe_can_id = htole32(cf->can_id);
    341  1.3.4.2  perseant 	sc->sc_tx_frame->gsframe_can_dlc = htole32(cf->can_dlc);
    342  1.3.4.2  perseant 	memcpy(&sc->sc_tx_frame->gsframe_can_data[0], &cf->data[0], 8);
    343  1.3.4.2  perseant 
    344  1.3.4.2  perseant 	usbd_setup_xfer(sc->sc_tx_xfer, sc, sc->sc_tx_frame,
    345  1.3.4.2  perseant 	    sizeof(struct gscan_frame), 0, 10000, gscan_tx);
    346  1.3.4.2  perseant         err = usbd_transfer(sc->sc_tx_xfer);
    347  1.3.4.2  perseant 	if (err != USBD_IN_PROGRESS) {
    348  1.3.4.2  perseant 		DPRINTF("start tx error: %jd", err, 0, 0, 0);
    349  1.3.4.2  perseant 		if_statadd(ifp, if_oerrors, 1);
    350  1.3.4.2  perseant 	} else {
    351  1.3.4.2  perseant 		sc->sc_m_transmit = m;
    352  1.3.4.2  perseant 		ifp->if_timer = 5;
    353  1.3.4.2  perseant 	}
    354  1.3.4.2  perseant 	can_bpf_mtap(ifp, m, 0);
    355  1.3.4.2  perseant out:
    356  1.3.4.2  perseant 	mutex_exit(&sc->sc_txlock);
    357  1.3.4.2  perseant }
    358  1.3.4.2  perseant 
    359  1.3.4.2  perseant static int
    360  1.3.4.2  perseant gscan_ifup(struct gscan_softc * const sc)
    361  1.3.4.2  perseant {
    362  1.3.4.2  perseant 	struct gscan_bt gscan_bt;
    363  1.3.4.2  perseant 	struct gscan_set_mode gscan_set_mode;
    364  1.3.4.2  perseant 	int err;
    365  1.3.4.2  perseant 	struct ifnet * const ifp = sc->sc_ifp;
    366  1.3.4.2  perseant 
    367  1.3.4.2  perseant 	KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname);
    368  1.3.4.2  perseant 
    369  1.3.4.2  perseant 	gscan_set_mode.mode_mode = MODE_START;
    370  1.3.4.2  perseant 	gscan_set_mode.mode_flags = 0;
    371  1.3.4.2  perseant 
    372  1.3.4.2  perseant 	if (sc->sc_linkmodes & CAN_LINKMODE_LISTENONLY) {
    373  1.3.4.2  perseant 		if ((sc->sc_timecaps.cltc_linkmode_caps & CAN_LINKMODE_LISTENONLY) == 0)
    374  1.3.4.2  perseant 			return EINVAL;
    375  1.3.4.2  perseant 		gscan_set_mode.mode_flags |= FLAGS_LISTEN_ONLY;
    376  1.3.4.2  perseant 	}
    377  1.3.4.2  perseant 	if (sc->sc_linkmodes & CAN_LINKMODE_LOOPBACK) {
    378  1.3.4.2  perseant 		if ((sc->sc_timecaps.cltc_linkmode_caps & CAN_LINKMODE_LOOPBACK) == 0)
    379  1.3.4.2  perseant 			return EINVAL;
    380  1.3.4.2  perseant 		gscan_set_mode.mode_flags |= FLAGS_LOOPBACK;
    381  1.3.4.2  perseant 	}
    382  1.3.4.2  perseant 	if (sc->sc_linkmodes & CAN_LINKMODE_3SAMPLES) {
    383  1.3.4.2  perseant 		if ((sc->sc_timecaps.cltc_linkmode_caps & CAN_LINKMODE_3SAMPLES) == 0)
    384  1.3.4.2  perseant 			return EINVAL;
    385  1.3.4.2  perseant 		gscan_set_mode.mode_flags |= FLAGS_TRIPLE_SAMPLE;
    386  1.3.4.2  perseant 	}
    387  1.3.4.2  perseant 	if (sc->sc_timings.clt_prop != 0)
    388  1.3.4.2  perseant 		return EINVAL;
    389  1.3.4.2  perseant 	gscan_bt.bt_prop_seg = 0;
    390  1.3.4.2  perseant 
    391  1.3.4.2  perseant 	if (sc->sc_timings.clt_brp > sc->sc_timecaps.cltc_brp_max ||
    392  1.3.4.2  perseant 	   sc->sc_timings.clt_brp < sc->sc_timecaps.cltc_brp_min)
    393  1.3.4.2  perseant 		return EINVAL;
    394  1.3.4.2  perseant 	gscan_bt.bt_brp = sc->sc_timings.clt_brp;
    395  1.3.4.2  perseant 
    396  1.3.4.2  perseant 	if (sc->sc_timings.clt_ps1 > sc->sc_timecaps.cltc_ps1_max ||
    397  1.3.4.2  perseant 	   sc->sc_timings.clt_ps1 < sc->sc_timecaps.cltc_ps1_min)
    398  1.3.4.2  perseant 		return EINVAL;
    399  1.3.4.2  perseant 	gscan_bt.bt_phase_seg1 = sc->sc_timings.clt_ps1;
    400  1.3.4.2  perseant 	if (sc->sc_timings.clt_ps2 > sc->sc_timecaps.cltc_ps2_max ||
    401  1.3.4.2  perseant 	   sc->sc_timings.clt_ps2 < sc->sc_timecaps.cltc_ps2_min)
    402  1.3.4.2  perseant 		return EINVAL;
    403  1.3.4.2  perseant 	gscan_bt.bt_phase_seg2 = sc->sc_timings.clt_ps2;
    404  1.3.4.2  perseant 	if (sc->sc_timings.clt_sjw > sc->sc_timecaps.cltc_sjw_max ||
    405  1.3.4.2  perseant 	    sc->sc_timings.clt_sjw < 1)
    406  1.3.4.2  perseant 		return EINVAL;
    407  1.3.4.2  perseant 	gscan_bt.bt_swj = sc->sc_timings.clt_sjw;
    408  1.3.4.2  perseant 
    409  1.3.4.2  perseant 	err = gscan_write_device(sc, GSCAN_SET_BITTIMING,
    410  1.3.4.2  perseant 	     &gscan_bt, sizeof(gscan_bt));
    411  1.3.4.2  perseant 	if (err) {
    412  1.3.4.2  perseant 		aprint_error_dev(sc->sc_dev, "SET_BITTIMING: %s\n",
    413  1.3.4.2  perseant 		    usbd_errstr(err));
    414  1.3.4.2  perseant 		return EIO;
    415  1.3.4.2  perseant 	}
    416  1.3.4.2  perseant 	err = gscan_write_device(sc, GSCAN_SET_MODE,
    417  1.3.4.2  perseant 	     &gscan_set_mode, sizeof(gscan_set_mode));
    418  1.3.4.2  perseant 	if (err) {
    419  1.3.4.2  perseant 		aprint_error_dev(sc->sc_dev, "SET_MODE start: %s\n",
    420  1.3.4.2  perseant 		    usbd_errstr(err));
    421  1.3.4.2  perseant 		return EIO;
    422  1.3.4.2  perseant 	}
    423  1.3.4.2  perseant 
    424  1.3.4.2  perseant 	if ((err = usbd_open_pipe(sc->sc_iface, sc->sc_ed_rx,
    425  1.3.4.2  perseant 	    USBD_EXCLUSIVE_USE | USBD_MPSAFE, &sc->sc_rx_pipe)) != 0) {
    426  1.3.4.2  perseant 		aprint_error_dev(sc->sc_dev, "open rx pipe: %s\n",
    427  1.3.4.2  perseant 		    usbd_errstr(err));
    428  1.3.4.2  perseant 		goto fail;
    429  1.3.4.2  perseant 	}
    430  1.3.4.2  perseant 	if ((err = usbd_open_pipe(sc->sc_iface, sc->sc_ed_tx,
    431  1.3.4.2  perseant 	    USBD_EXCLUSIVE_USE | USBD_MPSAFE, &sc->sc_tx_pipe)) != 0) {
    432  1.3.4.2  perseant 		aprint_error_dev(sc->sc_dev, "open tx pipe: %s\n",
    433  1.3.4.2  perseant 		    usbd_errstr(err));
    434  1.3.4.2  perseant 		goto fail;
    435  1.3.4.2  perseant 	}
    436  1.3.4.2  perseant 
    437  1.3.4.2  perseant 	if ((err = usbd_create_xfer(sc->sc_rx_pipe, sizeof(struct gscan_frame),
    438  1.3.4.2  perseant 	    0, 0, &sc->sc_rx_xfer)) != 0) {
    439  1.3.4.2  perseant 		aprint_error_dev(sc->sc_dev, "create rx xfer: %s\n",
    440  1.3.4.2  perseant 		    usbd_errstr(err));
    441  1.3.4.2  perseant 		goto fail;
    442  1.3.4.2  perseant 	}
    443  1.3.4.2  perseant 	if ((err = usbd_create_xfer(sc->sc_tx_pipe, sizeof(struct gscan_frame),
    444  1.3.4.2  perseant 	    0, 0, &sc->sc_tx_xfer)) != 0) {
    445  1.3.4.2  perseant 		aprint_error_dev(sc->sc_dev, "create tx xfer: %s\n",
    446  1.3.4.2  perseant 		    usbd_errstr(err));
    447  1.3.4.2  perseant 		goto fail;
    448  1.3.4.2  perseant 	}
    449  1.3.4.2  perseant 
    450  1.3.4.2  perseant 	sc->sc_rx_frame = usbd_get_buffer(sc->sc_rx_xfer);
    451  1.3.4.2  perseant 	sc->sc_tx_frame = usbd_get_buffer(sc->sc_tx_xfer);
    452  1.3.4.2  perseant 	sc->sc_ifp->if_flags |= IFF_RUNNING;
    453  1.3.4.2  perseant 
    454  1.3.4.2  perseant 	mutex_enter(&sc->sc_rxlock);
    455  1.3.4.2  perseant 	sc->sc_rxstopped = false;
    456  1.3.4.2  perseant 	sc->sc_rx_nerr = 0;
    457  1.3.4.2  perseant 	mutex_exit(&sc->sc_rxlock);
    458  1.3.4.2  perseant 	gscan_startrx(sc);
    459  1.3.4.2  perseant 	mutex_enter(&sc->sc_txlock);
    460  1.3.4.2  perseant 	sc->sc_txstopped = false;
    461  1.3.4.2  perseant 	mutex_exit(&sc->sc_txlock);
    462  1.3.4.2  perseant 	return 0;
    463  1.3.4.2  perseant 
    464  1.3.4.2  perseant fail:
    465  1.3.4.2  perseant 	gscan_stop(sc, ifp, 1);
    466  1.3.4.2  perseant 	return EIO;
    467  1.3.4.2  perseant }
    468  1.3.4.2  perseant 
    469  1.3.4.2  perseant static void
    470  1.3.4.2  perseant gscan_stop(struct gscan_softc * const sc, struct ifnet *ifp, int disable)
    471  1.3.4.2  perseant {
    472  1.3.4.2  perseant 	struct gscan_set_mode gscan_set_mode;
    473  1.3.4.2  perseant 	int err;
    474  1.3.4.2  perseant 
    475  1.3.4.2  perseant 	KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname);
    476  1.3.4.2  perseant 	mutex_enter(&sc->sc_txlock);
    477  1.3.4.2  perseant 	sc->sc_txstopped = true;
    478  1.3.4.2  perseant 	ifp->if_timer = 0;
    479  1.3.4.2  perseant 	if (sc->sc_m_transmit != NULL) {
    480  1.3.4.2  perseant 		m_freem(sc->sc_m_transmit);
    481  1.3.4.2  perseant 		sc->sc_m_transmit = NULL;
    482  1.3.4.2  perseant 	}
    483  1.3.4.2  perseant 	mutex_exit(&sc->sc_txlock);
    484  1.3.4.2  perseant 	mutex_enter(&sc->sc_rxlock);
    485  1.3.4.2  perseant 	sc->sc_rxstopped = true;
    486  1.3.4.2  perseant 	mutex_exit(&sc->sc_rxlock);
    487  1.3.4.2  perseant 	if (ifp->if_flags & IFF_RUNNING) {
    488  1.3.4.2  perseant 		if (sc->sc_tx_pipe)
    489  1.3.4.2  perseant 			usbd_abort_pipe(sc->sc_tx_pipe);
    490  1.3.4.2  perseant 		if (sc->sc_rx_pipe)
    491  1.3.4.2  perseant 			usbd_abort_pipe(sc->sc_rx_pipe);
    492  1.3.4.2  perseant 	}
    493  1.3.4.2  perseant 	if (sc->sc_rx_pipe) {
    494  1.3.4.2  perseant 		usbd_close_pipe(sc->sc_rx_pipe);
    495  1.3.4.2  perseant 		sc->sc_rx_pipe = NULL;
    496  1.3.4.2  perseant 	}
    497  1.3.4.2  perseant 	if (sc->sc_tx_pipe) {
    498  1.3.4.2  perseant 		usbd_close_pipe(sc->sc_tx_pipe);
    499  1.3.4.2  perseant 		sc->sc_tx_pipe = NULL;
    500  1.3.4.2  perseant 	}
    501  1.3.4.2  perseant 	if (sc->sc_rx_xfer != NULL) {
    502  1.3.4.2  perseant 		usbd_destroy_xfer(sc->sc_rx_xfer);
    503  1.3.4.2  perseant 		sc->sc_rx_xfer = NULL;
    504  1.3.4.2  perseant 		sc->sc_rx_pipe = NULL;
    505  1.3.4.2  perseant 	}
    506  1.3.4.2  perseant 	if (sc->sc_tx_xfer != NULL) {
    507  1.3.4.2  perseant 		usbd_destroy_xfer(sc->sc_tx_xfer);
    508  1.3.4.2  perseant 		sc->sc_tx_xfer = NULL;
    509  1.3.4.2  perseant 		sc->sc_tx_pipe = NULL;
    510  1.3.4.2  perseant 	}
    511  1.3.4.2  perseant 
    512  1.3.4.2  perseant 	gscan_set_mode.mode_mode = MODE_RESET;
    513  1.3.4.2  perseant 	gscan_set_mode.mode_flags = 0;
    514  1.3.4.2  perseant 	err = gscan_write_device(sc, GSCAN_SET_MODE,
    515  1.3.4.2  perseant 	     &gscan_set_mode, sizeof(gscan_set_mode));
    516  1.3.4.2  perseant 	if (err != 0 && err  != USBD_CANCELLED) {
    517  1.3.4.2  perseant 		aprint_error_dev(sc->sc_dev, "SET_MODE stop: %s\n",
    518  1.3.4.2  perseant 		    usbd_errstr(err));
    519  1.3.4.2  perseant 	}
    520  1.3.4.2  perseant 	KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname);
    521  1.3.4.2  perseant 	ifp->if_flags &= ~IFF_RUNNING;
    522  1.3.4.2  perseant }
    523  1.3.4.2  perseant 
    524  1.3.4.2  perseant static void
    525  1.3.4.2  perseant gscan_ifstop(struct ifnet *ifp, int disable)
    526  1.3.4.2  perseant {
    527  1.3.4.2  perseant 	struct gscan_softc * const sc = ifp->if_softc;
    528  1.3.4.2  perseant 	KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname);
    529  1.3.4.2  perseant 	gscan_stop(sc, ifp, disable);
    530  1.3.4.2  perseant }
    531  1.3.4.2  perseant 
    532  1.3.4.2  perseant 
    533  1.3.4.2  perseant static int
    534  1.3.4.2  perseant gscan_ifioctl(struct ifnet *ifp, u_long cmd, void *data)
    535  1.3.4.2  perseant {
    536  1.3.4.2  perseant 	struct gscan_softc * const sc = ifp->if_softc;
    537  1.3.4.2  perseant 	struct ifreq *ifr = (struct ifreq *)data;
    538  1.3.4.2  perseant 	int error = 0;
    539  1.3.4.2  perseant 
    540  1.3.4.2  perseant 	KASSERTMSG(IFNET_LOCKED(ifp), "%s", ifp->if_xname);
    541  1.3.4.2  perseant 	if (gscan_isdying(sc))
    542  1.3.4.2  perseant 		return EIO;
    543  1.3.4.2  perseant 
    544  1.3.4.2  perseant 	switch (cmd) {
    545  1.3.4.2  perseant 	case SIOCINITIFADDR:
    546  1.3.4.2  perseant 		error = EAFNOSUPPORT;
    547  1.3.4.2  perseant 		break;
    548  1.3.4.2  perseant 	case SIOCSIFMTU:
    549  1.3.4.2  perseant 		if ((unsigned)ifr->ifr_mtu != sizeof(struct can_frame))
    550  1.3.4.2  perseant 			error = EINVAL;
    551  1.3.4.2  perseant 		break;
    552  1.3.4.2  perseant 	case SIOCADDMULTI:
    553  1.3.4.2  perseant 	case SIOCDELMULTI:
    554  1.3.4.2  perseant 		error = EAFNOSUPPORT;
    555  1.3.4.2  perseant 		break;
    556  1.3.4.2  perseant 	default:
    557  1.3.4.2  perseant 		error = ifioctl_common(ifp, cmd, data);
    558  1.3.4.2  perseant 		if (error == 0) {
    559  1.3.4.2  perseant 			if ((ifp->if_flags & IFF_UP) != 0 &&
    560  1.3.4.2  perseant 			    (ifp->if_flags & IFF_RUNNING) == 0) {
    561  1.3.4.2  perseant 				error = gscan_ifup(sc);
    562  1.3.4.2  perseant 				if (error) {
    563  1.3.4.2  perseant 					ifp->if_flags &= ~IFF_UP;
    564  1.3.4.2  perseant 				}
    565  1.3.4.2  perseant 			} else if ((ifp->if_flags & IFF_UP) == 0 &&
    566  1.3.4.2  perseant 			    (ifp->if_flags & IFF_RUNNING) != 0) {
    567  1.3.4.2  perseant 				gscan_stop(sc, sc->sc_ifp, 1);
    568  1.3.4.2  perseant 			}
    569  1.3.4.2  perseant 		}
    570  1.3.4.2  perseant 		break;
    571  1.3.4.2  perseant 	}
    572  1.3.4.2  perseant 	return error;
    573  1.3.4.2  perseant }
    574  1.3.4.2  perseant 
    575  1.3.4.2  perseant static void
    576  1.3.4.2  perseant gscan_ifwatchdog(struct ifnet *ifp)
    577  1.3.4.2  perseant {
    578  1.3.4.2  perseant 	struct gscan_softc * const sc = ifp->if_softc;
    579  1.3.4.2  perseant 	printf("%s: watchdog timeout\n", device_xname(sc->sc_dev));
    580  1.3.4.2  perseant #if 0
    581  1.3.4.2  perseant 	/* if there is a transmit in progress abort */
    582  1.3.4.2  perseant 	if (gscan_tx_abort(sc)) {
    583  1.3.4.2  perseant 		if_statinc(ifp, if_oerrors);
    584  1.3.4.2  perseant 	}
    585  1.3.4.2  perseant #endif
    586  1.3.4.2  perseant }
    587  1.3.4.2  perseant 
    588  1.3.4.2  perseant static const struct usb_devno gscan_devs[] = {
    589  1.3.4.2  perseant     {USB_VENDOR_FUTUREBITS, USB_PRODUCT_FUTUREBITS_CDL_CAN},
    590  1.3.4.2  perseant     {USB_VENDOR_INTERBIO, USB_PRODUCT_INTERBIO_CDL_CAN},
    591  1.3.4.2  perseant };
    592  1.3.4.2  perseant 
    593  1.3.4.2  perseant static int
    594  1.3.4.2  perseant gscan_match(device_t parent, cfdata_t match, void *aux)
    595  1.3.4.2  perseant {
    596  1.3.4.2  perseant 	struct usb_attach_arg *uaa = aux;
    597  1.3.4.2  perseant 
    598  1.3.4.2  perseant 	return
    599  1.3.4.2  perseant 	    (usb_lookup(gscan_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL ?
    600  1.3.4.2  perseant 	     UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
    601  1.3.4.2  perseant }
    602  1.3.4.2  perseant 
    603  1.3.4.2  perseant static void
    604  1.3.4.2  perseant gscan_attach(device_t parent, device_t self, void *aux)
    605  1.3.4.2  perseant {
    606  1.3.4.2  perseant 	GSCANHIST_FUNC(); GSCANHIST_CALLED();
    607  1.3.4.2  perseant 	struct gscan_softc *sc = device_private(self);
    608  1.3.4.2  perseant 	struct usb_attach_arg *uaa = aux;
    609  1.3.4.2  perseant 	struct usbd_device *dev = uaa->uaa_device;
    610  1.3.4.2  perseant 	usbd_status err;
    611  1.3.4.2  perseant 	usb_interface_descriptor_t *id;
    612  1.3.4.2  perseant 	usb_endpoint_descriptor_t *ed;
    613  1.3.4.2  perseant 	char *devinfop;
    614  1.3.4.2  perseant 	uint32_t val32;
    615  1.3.4.2  perseant 	struct gscan_config gscan_config;
    616  1.3.4.2  perseant 	struct gscan_bt_const gscan_bt_const;
    617  1.3.4.2  perseant 	struct ifnet *ifp;
    618  1.3.4.2  perseant 
    619  1.3.4.2  perseant 	aprint_naive("\n");
    620  1.3.4.2  perseant 	aprint_normal("\n");
    621  1.3.4.2  perseant 	devinfop = usbd_devinfo_alloc(dev, 0);
    622  1.3.4.2  perseant 	aprint_normal_dev(self, "%s\n", devinfop);
    623  1.3.4.2  perseant 	usbd_devinfo_free(devinfop);
    624  1.3.4.2  perseant 
    625  1.3.4.2  perseant 	sc->sc_dev = self;
    626  1.3.4.2  perseant 	sc->sc_udev = dev;
    627  1.3.4.2  perseant 
    628  1.3.4.2  perseant 	err = usbd_set_config_no(dev, 1, 0);
    629  1.3.4.2  perseant 	if (err) {
    630  1.3.4.2  perseant 		aprint_error_dev(self, "failed to set configuration"
    631  1.3.4.2  perseant 		    ", err=%s\n", usbd_errstr(err));
    632  1.3.4.2  perseant 		return;
    633  1.3.4.2  perseant 	}
    634  1.3.4.2  perseant 
    635  1.3.4.2  perseant 	err = usbd_device2interface_handle(dev, 0, &sc->sc_iface);
    636  1.3.4.2  perseant 	if (err) {
    637  1.3.4.2  perseant 		aprint_error_dev(self, "getting interface handle failed\n");
    638  1.3.4.2  perseant 		return;
    639  1.3.4.2  perseant 	}
    640  1.3.4.2  perseant 
    641  1.3.4.2  perseant 	id = usbd_get_interface_descriptor(sc->sc_iface);
    642  1.3.4.2  perseant 	if (id->bNumEndpoints < 2) {
    643  1.3.4.2  perseant 		aprint_error_dev(self, "%d endpoints < 2\n", id->bNumEndpoints);
    644  1.3.4.2  perseant 		return;
    645  1.3.4.2  perseant 	}
    646  1.3.4.2  perseant 
    647  1.3.4.2  perseant 	val32 = htole32(0x0000beef);
    648  1.3.4.2  perseant 	err = gscan_write_device(sc, GSCAN_SET_HOST_FORMAT,
    649  1.3.4.2  perseant 	    &val32, sizeof(val32));
    650  1.3.4.2  perseant 
    651  1.3.4.2  perseant 	if (err) {
    652  1.3.4.2  perseant 		aprint_error_dev(self, "SET_HOST_FORMAT: %s\n",
    653  1.3.4.2  perseant 		    usbd_errstr(err));
    654  1.3.4.2  perseant 		return;
    655  1.3.4.2  perseant 	}
    656  1.3.4.2  perseant 
    657  1.3.4.2  perseant 	err = gscan_read_device(sc, GSCAN_GET_DEVICE_CONFIG,
    658  1.3.4.2  perseant 	    &gscan_config, sizeof(struct gscan_config));
    659  1.3.4.2  perseant 	if (err) {
    660  1.3.4.2  perseant 		aprint_error_dev(self, "GET_DEVICE_CONFIG: %s\n",
    661  1.3.4.2  perseant 		    usbd_errstr(err));
    662  1.3.4.2  perseant 		return;
    663  1.3.4.2  perseant 	}
    664  1.3.4.2  perseant 	aprint_normal_dev(self, "%d port%s, sw version %d, hw version %d\n",
    665  1.3.4.2  perseant 	    gscan_config.conf_count + 1, gscan_config.conf_count ? "s" : "",
    666  1.3.4.2  perseant 	    le32toh(gscan_config.sw_version), le32toh(gscan_config.hw_version));
    667  1.3.4.2  perseant 
    668  1.3.4.2  perseant 	err = gscan_read_device(sc, GSCAN_GET_BT_CONST,
    669  1.3.4.2  perseant 	    &gscan_bt_const, sizeof(struct gscan_bt_const));
    670  1.3.4.2  perseant 	if (err) {
    671  1.3.4.2  perseant 		aprint_error_dev(self, "GET_BT_CONST: %s\n",
    672  1.3.4.2  perseant 		    usbd_errstr(err));
    673  1.3.4.2  perseant 		return;
    674  1.3.4.2  perseant 	}
    675  1.3.4.2  perseant 	aprint_debug_dev(self, "feat 0x%x clk %dHz tseg1 %d -> %d tseg2 %d -> %d max swj %d brp %d -> %d/%d\n",
    676  1.3.4.2  perseant 	    le32toh(gscan_bt_const.btc_features),
    677  1.3.4.2  perseant 	    le32toh(gscan_bt_const.btc_fclk),
    678  1.3.4.2  perseant 	    le32toh(gscan_bt_const.btc_tseg1_min),
    679  1.3.4.2  perseant 	    le32toh(gscan_bt_const.btc_tseg1_max),
    680  1.3.4.2  perseant 	    le32toh(gscan_bt_const.btc_tseg2_min),
    681  1.3.4.2  perseant 	    le32toh(gscan_bt_const.btc_tseg2_max),
    682  1.3.4.2  perseant 	    le32toh(gscan_bt_const.btc_swj_max),
    683  1.3.4.2  perseant 	    le32toh(gscan_bt_const.btc_brp_min),
    684  1.3.4.2  perseant 	    le32toh(gscan_bt_const.btc_brp_max),
    685  1.3.4.2  perseant 	    le32toh(gscan_bt_const.btc_brp_inc));
    686  1.3.4.2  perseant 
    687  1.3.4.2  perseant 	sc->sc_timecaps.cltc_prop_min = 0;
    688  1.3.4.2  perseant 	sc->sc_timecaps.cltc_prop_max = 0;
    689  1.3.4.2  perseant 	sc->sc_timecaps.cltc_ps1_min = le32toh(gscan_bt_const.btc_tseg1_min);
    690  1.3.4.2  perseant 	sc->sc_timecaps.cltc_ps1_max = le32toh(gscan_bt_const.btc_tseg1_max);
    691  1.3.4.2  perseant 	sc->sc_timecaps.cltc_ps2_min = le32toh(gscan_bt_const.btc_tseg2_min);
    692  1.3.4.2  perseant 	sc->sc_timecaps.cltc_ps2_max = le32toh(gscan_bt_const.btc_tseg2_max);
    693  1.3.4.2  perseant 	sc->sc_timecaps.cltc_sjw_max = le32toh(gscan_bt_const.btc_swj_max);
    694  1.3.4.2  perseant 	sc->sc_timecaps.cltc_brp_min = le32toh(gscan_bt_const.btc_brp_min);
    695  1.3.4.2  perseant 	sc->sc_timecaps.cltc_brp_max = le32toh(gscan_bt_const.btc_brp_max);
    696  1.3.4.2  perseant 	sc->sc_timecaps.cltc_brp_inc = le32toh(gscan_bt_const.btc_brp_inc);
    697  1.3.4.2  perseant 	sc->sc_timecaps.cltc_clock_freq = le32toh(gscan_bt_const.btc_fclk);
    698  1.3.4.2  perseant 	sc->sc_timecaps.cltc_linkmode_caps = 0;
    699  1.3.4.2  perseant 	if (le32toh(gscan_bt_const.btc_features) & FEAT_LISTEN_ONLY)
    700  1.3.4.2  perseant 		sc->sc_timecaps.cltc_linkmode_caps |= CAN_LINKMODE_LISTENONLY;
    701  1.3.4.2  perseant 	if (le32toh(gscan_bt_const.btc_features) & FEAT_LOOPBACK)
    702  1.3.4.2  perseant 		sc->sc_timecaps.cltc_linkmode_caps |= CAN_LINKMODE_LOOPBACK;
    703  1.3.4.2  perseant 	if (le32toh(gscan_bt_const.btc_features) & FEAT_TRIPLE_SAMPLE)
    704  1.3.4.2  perseant 		sc->sc_timecaps.cltc_linkmode_caps |= CAN_LINKMODE_3SAMPLES;
    705  1.3.4.2  perseant 
    706  1.3.4.2  perseant 	can_ifinit_timings(&sc->sc_cansc);
    707  1.3.4.2  perseant 	sc->sc_timings.clt_prop = 0;
    708  1.3.4.2  perseant 	sc->sc_timings.clt_sjw = 1;
    709  1.3.4.2  perseant 
    710  1.3.4.2  perseant 	/* Find endpoints. */
    711  1.3.4.2  perseant 	ed = usbd_interface2endpoint_descriptor(sc->sc_iface, 0);
    712  1.3.4.2  perseant 	if (ed == NULL) {
    713  1.3.4.2  perseant 		aprint_error_dev(self, "couldn't get ep 1\n");
    714  1.3.4.2  perseant 		return;
    715  1.3.4.2  perseant 	}
    716  1.3.4.2  perseant 	const uint8_t xt1 = UE_GET_XFERTYPE(ed->bmAttributes);
    717  1.3.4.2  perseant 	const uint8_t dir1 = UE_GET_DIR(ed->bEndpointAddress);
    718  1.3.4.2  perseant 
    719  1.3.4.2  perseant 	if (dir1 != UE_DIR_IN || xt1 != UE_BULK) {
    720  1.3.4.2  perseant 		aprint_error_dev(self,
    721  1.3.4.2  perseant 		    "ep 1 wrong dir %d or xt %d\n", dir1, xt1);
    722  1.3.4.2  perseant 		return;
    723  1.3.4.2  perseant 	}
    724  1.3.4.2  perseant 	sc->sc_ed_rx = ed->bEndpointAddress;
    725  1.3.4.2  perseant 
    726  1.3.4.2  perseant 	ed = usbd_interface2endpoint_descriptor(sc->sc_iface, 1);
    727  1.3.4.2  perseant 	if (ed == NULL) {
    728  1.3.4.2  perseant 		aprint_error_dev(self, "couldn't get ep 2\n");
    729  1.3.4.2  perseant 		return;
    730  1.3.4.2  perseant 	}
    731  1.3.4.2  perseant 	const uint8_t xt2 = UE_GET_XFERTYPE(ed->bmAttributes);
    732  1.3.4.2  perseant 	const uint8_t dir2 = UE_GET_DIR(ed->bEndpointAddress);
    733  1.3.4.2  perseant 
    734  1.3.4.2  perseant 	if (dir2 != UE_DIR_OUT || xt2 != UE_BULK) {
    735  1.3.4.2  perseant 		aprint_error_dev(self,
    736  1.3.4.2  perseant 		    "ep 2 wrong dir %d or xt %d\n", dir2, xt2);
    737  1.3.4.2  perseant 		return;
    738  1.3.4.2  perseant 	}
    739  1.3.4.2  perseant 	sc->sc_ed_tx = ed->bEndpointAddress;
    740  1.3.4.2  perseant 
    741  1.3.4.2  perseant 	mutex_init(&sc->sc_txlock, MUTEX_DEFAULT, IPL_SOFTUSB);
    742  1.3.4.2  perseant 	mutex_init(&sc->sc_rxlock, MUTEX_DEFAULT, IPL_SOFTUSB);
    743  1.3.4.2  perseant 	sc->sc_rxstopped = true;
    744  1.3.4.2  perseant 	sc->sc_txstopped = true;
    745  1.3.4.2  perseant 
    746  1.3.4.2  perseant 
    747  1.3.4.2  perseant 	ifp = if_alloc(IFT_OTHER);
    748  1.3.4.2  perseant 	strlcpy(ifp->if_xname, device_xname(self), IFNAMSIZ);
    749  1.3.4.2  perseant 	ifp->if_softc = sc;
    750  1.3.4.2  perseant 	ifp->if_capabilities = 0;
    751  1.3.4.2  perseant 	ifp->if_flags = 0;
    752  1.3.4.2  perseant 	ifp->if_extflags = IFEF_MPSAFE;
    753  1.3.4.2  perseant 	ifp->if_start = gscan_ifstart;
    754  1.3.4.2  perseant 	ifp->if_ioctl = gscan_ifioctl;
    755  1.3.4.2  perseant 	ifp->if_stop = gscan_ifstop;
    756  1.3.4.2  perseant 	ifp->if_watchdog = gscan_ifwatchdog;
    757  1.3.4.2  perseant 	IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
    758  1.3.4.2  perseant 
    759  1.3.4.2  perseant 	sc->sc_ifp = ifp;
    760  1.3.4.2  perseant 	can_ifattach(ifp);
    761  1.3.4.2  perseant 	if_deferred_start_init(ifp, NULL);
    762  1.3.4.2  perseant 	bpf_mtap_softint_init(ifp);
    763  1.3.4.2  perseant 	rnd_attach_source(&sc->sc_rnd_source, device_xname(self),
    764  1.3.4.2  perseant 	    RND_TYPE_NET, RND_FLAG_DEFAULT);
    765  1.3.4.2  perseant #ifdef MBUFTRACE
    766  1.3.4.2  perseant 	ifp->if_mowner = kmem_zalloc(sizeof(*ifp->if_mowner), KM_SLEEP);
    767  1.3.4.2  perseant 	strlcpy(ifp->if_mowner->mo_name, ifp->if_xname,
    768  1.3.4.2  perseant 		sizeof(ifp->if_mowner->mo_name));
    769  1.3.4.2  perseant 	MOWNER_ATTACH(ifp->if_mowner);
    770  1.3.4.2  perseant #endif
    771  1.3.4.2  perseant 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, sc->sc_dev);
    772  1.3.4.2  perseant };
    773  1.3.4.2  perseant 
    774  1.3.4.2  perseant static int
    775  1.3.4.2  perseant gscan_detach(device_t self, int flags)
    776  1.3.4.2  perseant {
    777  1.3.4.2  perseant 	GSCANHIST_FUNC(); GSCANHIST_CALLED();
    778  1.3.4.2  perseant 	struct gscan_softc * const sc = device_private(self);
    779  1.3.4.2  perseant 
    780  1.3.4.2  perseant 	struct ifnet * const ifp = sc->sc_ifp;
    781  1.3.4.2  perseant 	/*
    782  1.3.4.2  perseant 	 * Prevent new activity.  After we stop the interface, it
    783  1.3.4.2  perseant 	 * cannot be brought back up.
    784  1.3.4.2  perseant 	 */
    785  1.3.4.2  perseant 	atomic_store_relaxed(&sc->sc_dying, true);
    786  1.3.4.2  perseant 
    787  1.3.4.2  perseant 	/*
    788  1.3.4.2  perseant 	 * If we're still running on the network, stop and wait for all
    789  1.3.4.2  perseant 	 * asynchronous activity to finish.
    790  1.3.4.2  perseant 	 *
    791  1.3.4.2  perseant 	 * If _attach_ifp never ran, IFNET_LOCK won't work, but
    792  1.3.4.2  perseant 	 * no activity is possible, so just skip this part.
    793  1.3.4.2  perseant 	 */
    794  1.3.4.2  perseant 	if (ifp != NULL) {
    795  1.3.4.2  perseant 		IFNET_LOCK(ifp);
    796  1.3.4.2  perseant 		if (ifp->if_flags & IFF_RUNNING) {
    797  1.3.4.2  perseant 			gscan_stop(sc, ifp, 1);
    798  1.3.4.2  perseant 		}
    799  1.3.4.2  perseant 		IFNET_UNLOCK(ifp);
    800  1.3.4.2  perseant 		bpf_detach(ifp);
    801  1.3.4.2  perseant 		if_detach(ifp);
    802  1.3.4.2  perseant 	}
    803  1.3.4.2  perseant 	rnd_detach_source(&sc->sc_rnd_source);
    804  1.3.4.2  perseant 	mutex_destroy(&sc->sc_txlock);
    805  1.3.4.2  perseant 	mutex_destroy(&sc->sc_rxlock);
    806  1.3.4.2  perseant 
    807  1.3.4.2  perseant 	pmf_device_deregister(sc->sc_dev);
    808  1.3.4.2  perseant 	if (ifp != NULL) {
    809  1.3.4.2  perseant 		usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
    810  1.3.4.2  perseant 		    sc->sc_dev);
    811  1.3.4.2  perseant 	}
    812  1.3.4.2  perseant 	return 0;
    813  1.3.4.2  perseant }
    814  1.3.4.2  perseant 
    815  1.3.4.2  perseant static int
    816  1.3.4.2  perseant gscan_activate(device_t self, devact_t act)
    817  1.3.4.2  perseant {
    818  1.3.4.2  perseant 	GSCANHIST_FUNC(); GSCANHIST_CALLED();
    819  1.3.4.2  perseant 	struct gscan_softc * const sc = device_private(self);
    820  1.3.4.2  perseant 	struct ifnet * const ifp = sc->sc_ifp;
    821  1.3.4.2  perseant 
    822  1.3.4.2  perseant 	switch (act) {
    823  1.3.4.2  perseant 	case DVACT_DEACTIVATE:
    824  1.3.4.2  perseant 		if_deactivate(ifp);
    825  1.3.4.2  perseant 		atomic_store_relaxed(&sc->sc_dying, true);
    826  1.3.4.2  perseant 		mutex_enter(&sc->sc_txlock);
    827  1.3.4.2  perseant 		sc->sc_txstopped = true;
    828  1.3.4.2  perseant 		if (sc->sc_m_transmit != NULL) {
    829  1.3.4.2  perseant 			m_freem(sc->sc_m_transmit);
    830  1.3.4.2  perseant 			sc->sc_m_transmit = NULL;
    831  1.3.4.2  perseant 		}
    832  1.3.4.2  perseant 		mutex_exit(&sc->sc_txlock);
    833  1.3.4.2  perseant 		mutex_enter(&sc->sc_rxlock);
    834  1.3.4.2  perseant 		sc->sc_rxstopped = true;
    835  1.3.4.2  perseant 		mutex_exit(&sc->sc_rxlock);
    836  1.3.4.2  perseant 		return 0;
    837  1.3.4.2  perseant 	default:
    838  1.3.4.2  perseant 		return EOPNOTSUPP;
    839  1.3.4.2  perseant 	}
    840  1.3.4.2  perseant }
    841  1.3.4.2  perseant 
    842  1.3.4.2  perseant #ifdef _MODULE
    843  1.3.4.2  perseant #include "ioconf.c"
    844  1.3.4.2  perseant #endif
    845  1.3.4.2  perseant 
    846  1.3.4.2  perseant MODULE(MODULE_CLASS_DRIVER, gscan, NULL);
    847  1.3.4.2  perseant 
    848  1.3.4.2  perseant static int
    849  1.3.4.2  perseant gscan_modcmd(modcmd_t cmd, void *aux)
    850  1.3.4.2  perseant {
    851  1.3.4.2  perseant 	int error = 0;
    852  1.3.4.2  perseant 
    853  1.3.4.2  perseant 	switch (cmd) {
    854  1.3.4.2  perseant 	case MODULE_CMD_INIT:
    855  1.3.4.2  perseant #ifdef _MODULE
    856  1.3.4.2  perseant 		error = config_init_component(cfdriver_ioconf_gscan,
    857  1.3.4.2  perseant 		    cfattach_ioconf_gscan, cfdata_ioconf_gscan);
    858  1.3.4.2  perseant #endif
    859  1.3.4.2  perseant 		return error;
    860  1.3.4.2  perseant 	case MODULE_CMD_FINI:
    861  1.3.4.2  perseant #ifdef _MODULE
    862  1.3.4.2  perseant 		error = config_fini_component(cfdriver_ioconf_gscan,
    863  1.3.4.2  perseant 		    cfattach_ioconf_gscan, cfdata_ioconf_gscan);
    864  1.3.4.2  perseant #endif
    865  1.3.4.2  perseant 		return error;
    866  1.3.4.2  perseant 	default:
    867  1.3.4.2  perseant 		return ENOTTY;
    868  1.3.4.2  perseant 	}
    869  1.3.4.2  perseant }
    870