Home | History | Annotate | Line # | Download | only in usb
if_upl.c revision 1.77.8.1
      1  1.77.8.1   thorpej /*	$NetBSD: if_upl.c,v 1.77.8.1 2023/11/16 04:30:21 thorpej Exp $	*/
      2      1.65       mrg 
      3       1.1  augustss /*
      4       1.1  augustss  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      5       1.1  augustss  * All rights reserved.
      6       1.1  augustss  *
      7       1.1  augustss  * This code is derived from software contributed to The NetBSD Foundation
      8       1.3  augustss  * by Lennart Augustsson (lennart (at) augustsson.net) at
      9       1.1  augustss  * Carlstedt Research & Technology.
     10       1.1  augustss  *
     11       1.1  augustss  * Redistribution and use in source and binary forms, with or without
     12       1.1  augustss  * modification, are permitted provided that the following conditions
     13       1.1  augustss  * are met:
     14       1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     15       1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     16       1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     17       1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     18       1.1  augustss  *    documentation and/or other materials provided with the distribution.
     19       1.1  augustss  *
     20       1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21       1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22       1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23       1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24       1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25       1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26       1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27       1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28       1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29       1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30       1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     31       1.1  augustss  */
     32       1.1  augustss 
     33       1.1  augustss /*
     34       1.1  augustss  * Prolific PL2301/PL2302 driver
     35       1.1  augustss  */
     36      1.16     lukem 
     37      1.16     lukem #include <sys/cdefs.h>
     38  1.77.8.1   thorpej __KERNEL_RCSID(0, "$NetBSD: if_upl.c,v 1.77.8.1 2023/11/16 04:30:21 thorpej Exp $");
     39       1.1  augustss 
     40      1.44  christos #ifdef _KERNEL_OPT
     41       1.1  augustss #include "opt_inet.h"
     42      1.57     skrll #include "opt_usb.h"
     43      1.44  christos #endif
     44       1.1  augustss 
     45       1.1  augustss #include <sys/param.h>
     46       1.1  augustss 
     47      1.65       mrg #include <dev/usb/usbnet.h>
     48       1.1  augustss 
     49       1.1  augustss #include <net/if_types.h>
     50       1.1  augustss 
     51       1.1  augustss #ifdef INET
     52      1.19  augustss #include <netinet/in.h>
     53      1.19  augustss #include <netinet/in_var.h>
     54       1.1  augustss #include <netinet/if_inarp.h>
     55       1.1  augustss #endif
     56       1.1  augustss 
     57       1.1  augustss /*
     58       1.1  augustss  * 7  6  5  4  3  2  1  0
     59       1.6  augustss  * tx rx 1  0
     60       1.1  augustss  * 1110 0000 rxdata
     61       1.1  augustss  * 1010 0000 idle
     62       1.1  augustss  * 0010 0000 tx over
     63       1.1  augustss  * 0110      tx over + rxd
     64       1.1  augustss  */
     65       1.1  augustss 
     66       1.1  augustss #define UPL_RXDATA		0x40
     67       1.1  augustss #define UPL_TXOK		0x80
     68       1.1  augustss 
     69       1.1  augustss #define UPL_CONFIG_NO		1
     70       1.1  augustss #define UPL_IFACE_IDX		0
     71       1.1  augustss 
     72       1.1  augustss /***/
     73       1.1  augustss 
     74       1.1  augustss #define UPL_INTR_INTERVAL	20
     75       1.1  augustss 
     76       1.1  augustss #define UPL_BUFSZ		1024
     77       1.1  augustss 
     78       1.1  augustss #define UPL_RX_LIST_CNT		1
     79       1.1  augustss #define UPL_TX_LIST_CNT		1
     80       1.1  augustss 
     81       1.1  augustss #ifdef UPL_DEBUG
     82      1.38    dyoung #define DPRINTF(x)	if (upldebug) printf x
     83      1.38    dyoung #define DPRINTFN(n,x)	if (upldebug >= (n)) printf x
     84       1.1  augustss int	upldebug = 0;
     85       1.1  augustss #else
     86       1.1  augustss #define DPRINTF(x)
     87       1.1  augustss #define DPRINTFN(n,x)
     88       1.1  augustss #endif
     89       1.1  augustss 
     90       1.1  augustss /*
     91       1.1  augustss  * Various supported device vendors/products.
     92       1.1  augustss  */
     93      1.69      maxv static const struct usb_devno sc_devs[] = {
     94       1.1  augustss 	{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301 },
     95       1.1  augustss 	{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302 },
     96      1.65       mrg 	{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL25A1 },
     97      1.65       mrg 	{ USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F5U258 },
     98      1.67      maxv 	{ USB_VENDOR_NI, USB_PRODUCT_NI_HTOH_7825 }
     99       1.1  augustss };
    100       1.1  augustss 
    101      1.69      maxv static int	upl_match(device_t, cfdata_t, void *);
    102      1.69      maxv static void	upl_attach(device_t, device_t, void *);
    103      1.63       mrg 
    104      1.65       mrg CFATTACH_DECL_NEW(upl, sizeof(struct usbnet), upl_match, upl_attach,
    105      1.65       mrg     usbnet_detach, usbnet_activate);
    106       1.1  augustss 
    107      1.65       mrg #if 0
    108      1.71   thorpej static void upl_uno_intr(struct usbnet *, usbd_status);
    109      1.65       mrg #endif
    110      1.71   thorpej static void upl_uno_rx_loop(struct usbnet *, struct usbnet_chain *, uint32_t);
    111      1.71   thorpej static unsigned upl_uno_tx_prepare(struct usbnet *, struct mbuf *,
    112      1.65       mrg 			       struct usbnet_chain *);
    113      1.71   thorpej static int upl_uno_ioctl(struct ifnet *, u_long, void *);
    114      1.65       mrg 
    115      1.69      maxv static const struct usbnet_ops upl_ops = {
    116      1.71   thorpej 	.uno_tx_prepare = upl_uno_tx_prepare,
    117      1.71   thorpej 	.uno_rx_loop = upl_uno_rx_loop,
    118      1.71   thorpej 	.uno_ioctl = upl_uno_ioctl,
    119      1.65       mrg #if 0
    120      1.71   thorpej 	.uno_intr = upl_uno_intr,
    121      1.65       mrg #endif
    122      1.65       mrg };
    123       1.4  augustss 
    124      1.65       mrg static int upl_output(struct ifnet *, struct mbuf *, const struct sockaddr *,
    125      1.52     ozaki 		      const struct rtentry *);
    126      1.65       mrg static void upl_input(struct ifnet *, struct mbuf *);
    127       1.1  augustss 
    128       1.1  augustss /*
    129       1.1  augustss  * Probe for a Prolific chip.
    130       1.1  augustss  */
    131      1.69      maxv static int
    132      1.38    dyoung upl_match(device_t parent, cfdata_t match, void *aux)
    133       1.1  augustss {
    134      1.38    dyoung 	struct usb_attach_arg *uaa = aux;
    135       1.1  augustss 
    136      1.65       mrg 	return usb_lookup(sc_devs, uaa->uaa_vendor, uaa->uaa_product) != NULL ?
    137      1.65       mrg 		UMATCH_VENDOR_PRODUCT : UMATCH_NONE;
    138       1.1  augustss }
    139       1.1  augustss 
    140      1.69      maxv static void
    141      1.38    dyoung upl_attach(device_t parent, device_t self, void *aux)
    142       1.1  augustss {
    143      1.65       mrg 	struct usbnet * const	un = device_private(self);
    144      1.65       mrg 	struct usb_attach_arg	*uaa = aux;
    145      1.22  augustss 	char			*devinfop;
    146      1.51     skrll 	struct usbd_device *	dev = uaa->uaa_device;
    147       1.1  augustss 	usbd_status		err;
    148       1.1  augustss 	usb_interface_descriptor_t	*id;
    149       1.1  augustss 	usb_endpoint_descriptor_t	*ed;
    150       1.1  augustss 	int			i;
    151       1.1  augustss 
    152      1.65       mrg 	DPRINTFN(5,(" : upl_attach: un=%p, dev=%p", un, dev));
    153      1.32      cube 
    154      1.34    plunky 	aprint_naive("\n");
    155      1.34    plunky 	aprint_normal("\n");
    156      1.22  augustss 	devinfop = usbd_devinfo_alloc(dev, 0);
    157      1.32      cube 	aprint_normal_dev(self, "%s\n", devinfop);
    158      1.22  augustss 	usbd_devinfo_free(devinfop);
    159       1.1  augustss 
    160      1.65       mrg 	un->un_dev = self;
    161      1.65       mrg 	un->un_udev = dev;
    162      1.65       mrg 	un->un_sc = un;
    163      1.65       mrg 	un->un_ops = &upl_ops;
    164      1.65       mrg 	un->un_rx_xfer_flags = USBD_SHORT_XFER_OK;
    165      1.65       mrg 	un->un_tx_xfer_flags = USBD_FORCE_SHORT_XFER;
    166      1.65       mrg 	un->un_rx_list_cnt = UPL_RX_LIST_CNT;
    167      1.65       mrg 	un->un_tx_list_cnt = UPL_TX_LIST_CNT;
    168      1.65       mrg 	un->un_rx_bufsz = UPL_BUFSZ;
    169      1.65       mrg 	un->un_tx_bufsz = UPL_BUFSZ;
    170      1.65       mrg 
    171       1.9  augustss 	err = usbd_set_config_no(dev, UPL_CONFIG_NO, 1);
    172       1.1  augustss 	if (err) {
    173      1.43     skrll 		aprint_error_dev(self, "failed to set configuration"
    174      1.43     skrll 		    ", err=%s\n", usbd_errstr(err));
    175      1.38    dyoung 		return;
    176       1.1  augustss 	}
    177       1.1  augustss 
    178      1.65       mrg 	err = usbd_device2interface_handle(dev, UPL_IFACE_IDX, &un->un_iface);
    179       1.1  augustss 	if (err) {
    180      1.32      cube 		aprint_error_dev(self, "getting interface handle failed\n");
    181      1.38    dyoung 		return;
    182       1.1  augustss 	}
    183       1.1  augustss 
    184      1.65       mrg 	id = usbd_get_interface_descriptor(un->un_iface);
    185       1.1  augustss 
    186       1.1  augustss 	/* Find endpoints. */
    187       1.1  augustss 	for (i = 0; i < id->bNumEndpoints; i++) {
    188      1.65       mrg 		ed = usbd_interface2endpoint_descriptor(un->un_iface, i);
    189       1.1  augustss 		if (ed == NULL) {
    190      1.32      cube 			aprint_error_dev(self, "couldn't get ep %d\n", i);
    191      1.38    dyoung 			return;
    192       1.1  augustss 		}
    193       1.1  augustss 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    194       1.1  augustss 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    195      1.65       mrg 			un->un_ed[USBNET_ENDPT_RX] = ed->bEndpointAddress;
    196       1.1  augustss 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
    197       1.1  augustss 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    198      1.65       mrg 			un->un_ed[USBNET_ENDPT_TX] = ed->bEndpointAddress;
    199       1.1  augustss 		}
    200       1.1  augustss 	}
    201       1.1  augustss 
    202      1.65       mrg 	if (un->un_ed[USBNET_ENDPT_RX] == 0 || un->un_ed[USBNET_ENDPT_TX] == 0 /*||
    203      1.65       mrg 	    un->un_ed[USBNET_ENDPT_INTR] == 0*/) {
    204      1.32      cube 		aprint_error_dev(self, "missing endpoint\n");
    205      1.38    dyoung 		return;
    206       1.1  augustss 	}
    207       1.1  augustss 
    208      1.77  riastrad 	usbnet_attach(un);
    209       1.1  augustss 
    210       1.1  augustss 	/* Initialize interface info.*/
    211      1.65       mrg 	struct ifnet *ifp = usbnet_ifp(un);
    212       1.1  augustss 	ifp->if_mtu = UPL_BUFSZ;
    213       1.1  augustss 	ifp->if_type = IFT_OTHER;
    214       1.1  augustss 	ifp->if_addrlen = 0;
    215       1.1  augustss 	ifp->if_hdrlen = 0;
    216       1.1  augustss 	ifp->if_output = upl_output;
    217      1.49     ozaki 	ifp->_if_input = upl_input;
    218       1.1  augustss 	ifp->if_baudrate = 12000000;
    219      1.12  augustss 	ifp->if_dlt = DLT_RAW;
    220       1.1  augustss 
    221      1.66       mrg 	usbnet_attach_ifp(un, IFF_POINTOPOINT | IFF_NOARP | IFF_SIMPLEX,
    222      1.66       mrg 	    0, NULL);
    223       1.1  augustss }
    224       1.1  augustss 
    225      1.65       mrg static void
    226      1.71   thorpej upl_uno_rx_loop(struct usbnet * un, struct usbnet_chain *c, uint32_t total_len)
    227       1.1  augustss {
    228       1.1  augustss 
    229      1.68   msaitoh 	DPRINTFN(9,("%s: %s: enter length=%d\n",
    230      1.68   msaitoh 		    device_xname(un->un_dev), __func__, total_len));
    231       1.1  augustss 
    232      1.65       mrg 	usbnet_input(un, c->unc_buf, total_len);
    233       1.1  augustss }
    234       1.1  augustss 
    235      1.65       mrg static unsigned
    236      1.71   thorpej upl_uno_tx_prepare(struct usbnet *un, struct mbuf *m, struct usbnet_chain *c)
    237       1.1  augustss {
    238      1.65       mrg 	int	total_len;
    239       1.1  augustss 
    240      1.65       mrg 	if ((unsigned)m->m_pkthdr.len > un->un_tx_bufsz)
    241      1.35    dyoung 		return 0;
    242       1.1  augustss 
    243      1.65       mrg 	m_copydata(m, 0, m->m_pkthdr.len, c->unc_buf);
    244       1.1  augustss 	total_len = m->m_pkthdr.len;
    245       1.1  augustss 
    246       1.1  augustss 	DPRINTFN(10,("%s: %s: total_len=%d\n",
    247      1.65       mrg 		     device_xname(un->un_dev), __func__, total_len));
    248       1.1  augustss 
    249      1.65       mrg 	return total_len;
    250       1.1  augustss }
    251       1.1  augustss 
    252      1.65       mrg static int
    253      1.71   thorpej upl_uno_ioctl(struct ifnet *ifp, u_long cmd, void *data)
    254       1.1  augustss {
    255      1.65       mrg 	if (cmd == SIOCSIFMTU) {
    256      1.65       mrg 		struct ifreq *ifr = data;
    257       1.1  augustss 
    258      1.65       mrg 		if (ifr->ifr_mtu > UPL_BUFSZ)
    259      1.65       mrg 			return EINVAL;
    260       1.1  augustss 	}
    261      1.51     skrll 	return 0;
    262       1.1  augustss }
    263       1.1  augustss 
    264      1.65       mrg static int
    265      1.27    dyoung upl_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst,
    266      1.52     ozaki     const struct rtentry *rt0)
    267       1.1  augustss {
    268      1.65       mrg 	struct usbnet * const un __unused = ifp->if_softc;
    269       1.1  augustss 
    270      1.65       mrg 	DPRINTFN(10,("%s: %s: enter\n", device_xname(un->un_dev), __func__));
    271       1.1  augustss 
    272      1.65       mrg 	/* If the queueing discipline needs packet classification, do it now. */
    273  1.77.8.1   thorpej 	ifq_classify_packet(&ifp->if_snd, m, dst->sa_family);
    274      1.17    itojun 
    275       1.1  augustss 	/*
    276       1.1  augustss 	 * Queue message on interface, and start output if interface
    277       1.1  augustss 	 * not yet active.
    278       1.1  augustss 	 */
    279      1.65       mrg 	return if_transmit_lock(ifp, m);
    280       1.1  augustss }
    281       1.1  augustss 
    282      1.65       mrg static void
    283       1.4  augustss upl_input(struct ifnet *ifp, struct mbuf *m)
    284       1.1  augustss {
    285      1.21  christos #ifdef INET
    286      1.46     rmind 	size_t pktlen = m->m_len;
    287       1.1  augustss 	int s;
    288       1.1  augustss 
    289      1.14   thorpej 	s = splnet();
    290      1.46     rmind 	if (__predict_false(!pktq_enqueue(ip_pktq, m, 0))) {
    291      1.70   thorpej 		if_statinc(ifp, if_iqdrops);
    292      1.46     rmind 		m_freem(m);
    293      1.46     rmind 	} else {
    294      1.70   thorpej 		if_statadd2(ifp, if_ipackets, 1, if_ibytes, pktlen);
    295       1.1  augustss 	}
    296       1.1  augustss 	splx(s);
    297      1.21  christos #endif
    298       1.1  augustss }
    299      1.65       mrg 
    300      1.65       mrg #ifdef _MODULE
    301      1.65       mrg #include "ioconf.c"
    302      1.65       mrg #endif
    303      1.65       mrg 
    304      1.65       mrg USBNET_MODULE(upl)
    305