Home | History | Annotate | Line # | Download | only in usb
if_upl.c revision 1.3.2.1
      1  1.3.2.1   minoura /*	$NetBSD: if_upl.c,v 1.3.2.1 2000/06/22 17:08:30 minoura Exp $	*/
      2      1.1  augustss /*
      3      1.1  augustss  * Copyright (c) 2000 The NetBSD Foundation, Inc.
      4      1.1  augustss  * All rights reserved.
      5      1.1  augustss  *
      6      1.1  augustss  * This code is derived from software contributed to The NetBSD Foundation
      7      1.3  augustss  * by Lennart Augustsson (lennart (at) augustsson.net) at
      8      1.1  augustss  * Carlstedt Research & Technology.
      9      1.1  augustss  *
     10      1.1  augustss  * Redistribution and use in source and binary forms, with or without
     11      1.1  augustss  * modification, are permitted provided that the following conditions
     12      1.1  augustss  * are met:
     13      1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     14      1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     15      1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     16      1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     17      1.1  augustss  *    documentation and/or other materials provided with the distribution.
     18      1.1  augustss  * 3. All advertising materials mentioning features or use of this software
     19      1.1  augustss  *    must display the following acknowledgement:
     20      1.1  augustss  *        This product includes software developed by the NetBSD
     21      1.1  augustss  *        Foundation, Inc. and its contributors.
     22      1.1  augustss  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23      1.1  augustss  *    contributors may be used to endorse or promote products derived
     24      1.1  augustss  *    from this software without specific prior written permission.
     25      1.1  augustss  *
     26      1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27      1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28      1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29      1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30      1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31      1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32      1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33      1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34      1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35      1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36      1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     37      1.1  augustss  */
     38      1.1  augustss 
     39      1.1  augustss /*
     40      1.1  augustss  * Prolific PL2301/PL2302 driver
     41      1.1  augustss  */
     42      1.1  augustss 
     43      1.1  augustss #include "opt_inet.h"
     44      1.1  augustss #include "opt_ns.h"
     45      1.1  augustss #include "bpfilter.h"
     46      1.1  augustss #include "rnd.h"
     47      1.1  augustss 
     48      1.1  augustss #include <sys/param.h>
     49      1.1  augustss #include <sys/systm.h>
     50      1.1  augustss #include <sys/callout.h>
     51      1.1  augustss #include <sys/sockio.h>
     52      1.1  augustss #include <sys/mbuf.h>
     53      1.1  augustss #include <sys/malloc.h>
     54      1.1  augustss #include <sys/kernel.h>
     55      1.1  augustss #include <sys/socket.h>
     56      1.1  augustss 
     57      1.1  augustss #include <sys/device.h>
     58      1.1  augustss #if NRND > 0
     59      1.1  augustss #include <sys/rnd.h>
     60      1.1  augustss #endif
     61      1.1  augustss 
     62      1.1  augustss #include <net/if.h>
     63      1.1  augustss #include <net/if_types.h>
     64      1.1  augustss #include <net/if_dl.h>
     65      1.1  augustss #include <net/netisr.h>
     66      1.1  augustss 
     67      1.1  augustss #define BPF_MTAP(ifp, m) bpf_mtap((ifp)->if_bpf, (m))
     68      1.1  augustss 
     69      1.1  augustss #if NBPFILTER > 0
     70      1.1  augustss #include <net/bpf.h>
     71      1.1  augustss #endif
     72      1.1  augustss 
     73      1.1  augustss #ifdef INET
     74      1.1  augustss #include <netinet/in.h>
     75      1.1  augustss #include <netinet/in_var.h>
     76      1.1  augustss #include <netinet/if_inarp.h>
     77      1.1  augustss #endif
     78      1.1  augustss 
     79      1.1  augustss #ifdef NS
     80      1.1  augustss #include <netns/ns.h>
     81      1.1  augustss #include <netns/ns_if.h>
     82      1.1  augustss #endif
     83      1.1  augustss 
     84      1.1  augustss #include <dev/usb/usb.h>
     85      1.1  augustss #include <dev/usb/usbdi.h>
     86      1.1  augustss #include <dev/usb/usbdi_util.h>
     87      1.1  augustss #include <dev/usb/usbdevs.h>
     88      1.1  augustss 
     89      1.1  augustss /*
     90      1.1  augustss  * 7  6  5  4  3  2  1  0
     91      1.1  augustss  *  tx rx 1  0
     92      1.1  augustss  * 1110 0000 rxdata
     93      1.1  augustss  * 1010 0000 idle
     94      1.1  augustss  * 0010 0000 tx over
     95      1.1  augustss  * 0110      tx over + rxd
     96      1.1  augustss  */
     97      1.1  augustss 
     98      1.1  augustss #define UPL_RXDATA		0x40
     99      1.1  augustss #define UPL_TXOK		0x80
    100      1.1  augustss 
    101      1.1  augustss #define UPL_INTR_PKTLEN		1
    102      1.1  augustss 
    103      1.1  augustss #define UPL_CONFIG_NO		1
    104      1.1  augustss #define UPL_IFACE_IDX		0
    105      1.1  augustss 
    106      1.1  augustss /***/
    107      1.1  augustss 
    108      1.1  augustss #define UPL_INTR_INTERVAL	20
    109      1.1  augustss 
    110      1.1  augustss #define UPL_BUFSZ		1024
    111      1.1  augustss 
    112      1.1  augustss #define UPL_RX_FRAMES		1
    113      1.1  augustss #define UPL_TX_FRAMES		1
    114      1.1  augustss 
    115      1.1  augustss #define UPL_RX_LIST_CNT		1
    116      1.1  augustss #define UPL_TX_LIST_CNT		1
    117      1.1  augustss 
    118      1.1  augustss #define UPL_ENDPT_RX		0x0
    119      1.1  augustss #define UPL_ENDPT_TX		0x1
    120      1.1  augustss #define UPL_ENDPT_INTR		0x2
    121      1.1  augustss #define UPL_ENDPT_MAX		0x3
    122      1.1  augustss 
    123      1.1  augustss struct upl_type {
    124      1.1  augustss 	u_int16_t		upl_vid;
    125      1.1  augustss 	u_int16_t		upl_did;
    126      1.1  augustss };
    127      1.1  augustss 
    128      1.1  augustss struct upl_softc;
    129      1.1  augustss 
    130      1.1  augustss struct upl_chain {
    131      1.1  augustss 	struct upl_softc	*upl_sc;
    132      1.1  augustss 	usbd_xfer_handle	upl_xfer;
    133      1.1  augustss 	char			*upl_buf;
    134      1.1  augustss 	struct mbuf		*upl_mbuf;
    135      1.1  augustss 	int			upl_idx;
    136      1.1  augustss };
    137      1.1  augustss 
    138      1.1  augustss struct upl_cdata {
    139      1.1  augustss 	struct upl_chain	upl_tx_chain[UPL_TX_LIST_CNT];
    140      1.1  augustss 	struct upl_chain	upl_rx_chain[UPL_RX_LIST_CNT];
    141      1.1  augustss 	int			upl_tx_prod;
    142      1.1  augustss 	int			upl_tx_cons;
    143      1.1  augustss 	int			upl_tx_cnt;
    144      1.1  augustss 	int			upl_rx_prod;
    145      1.1  augustss };
    146      1.1  augustss 
    147      1.1  augustss struct upl_softc {
    148      1.1  augustss 	USBBASEDEVICE		sc_dev;
    149      1.1  augustss 
    150      1.1  augustss 	struct ifnet		sc_if;
    151      1.1  augustss #if NRND > 0
    152      1.1  augustss 	rndsource_element_t	sc_rnd_source;
    153      1.1  augustss #endif
    154      1.1  augustss 
    155      1.1  augustss 	usb_callout_t		sc_stat_ch;
    156      1.1  augustss 
    157      1.1  augustss 	usbd_device_handle	sc_udev;
    158      1.1  augustss 	usbd_interface_handle	sc_iface;
    159      1.1  augustss 	u_int16_t		sc_vendor;
    160      1.1  augustss 	u_int16_t		sc_product;
    161      1.1  augustss 	int			sc_ed[UPL_ENDPT_MAX];
    162      1.1  augustss 	usbd_pipe_handle	sc_ep[UPL_ENDPT_MAX];
    163      1.1  augustss 	struct upl_cdata	sc_cdata;
    164      1.1  augustss 
    165      1.1  augustss 	uByte			sc_ibuf;
    166      1.1  augustss 
    167      1.1  augustss 	char			sc_dying;
    168      1.1  augustss 	char			sc_attached;
    169      1.1  augustss 	u_int			sc_rx_errs;
    170      1.1  augustss 	struct timeval		sc_rx_notice;
    171      1.1  augustss 	u_int			sc_intr_errs;
    172      1.1  augustss };
    173      1.1  augustss 
    174      1.1  augustss #ifdef UPL_DEBUG
    175      1.1  augustss #define DPRINTF(x)	if (upldebug) logprintf x
    176      1.1  augustss #define DPRINTFN(n,x)	if (upldebug >= (n)) logprintf x
    177      1.1  augustss int	upldebug = 0;
    178      1.1  augustss #else
    179      1.1  augustss #define DPRINTF(x)
    180      1.1  augustss #define DPRINTFN(n,x)
    181      1.1  augustss #endif
    182      1.1  augustss 
    183      1.1  augustss /*
    184      1.1  augustss  * Various supported device vendors/products.
    185      1.1  augustss  */
    186      1.1  augustss Static struct upl_type sc_devs[] = {
    187      1.1  augustss 	{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2301 },
    188      1.1  augustss 	{ USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2302 },
    189      1.1  augustss 	{ 0, 0 }
    190      1.1  augustss };
    191      1.1  augustss 
    192      1.1  augustss USB_DECLARE_DRIVER(upl);
    193      1.1  augustss 
    194  1.3.2.1   minoura Static int upl_openpipes(struct upl_softc *);
    195  1.3.2.1   minoura Static int upl_tx_list_init(struct upl_softc *);
    196  1.3.2.1   minoura Static int upl_rx_list_init(struct upl_softc *);
    197  1.3.2.1   minoura Static int upl_newbuf(struct upl_softc *, struct upl_chain *, struct mbuf *);
    198  1.3.2.1   minoura Static int upl_send(struct upl_softc *, struct mbuf *, int);
    199  1.3.2.1   minoura Static void upl_intr(usbd_xfer_handle, usbd_private_handle, usbd_status);
    200  1.3.2.1   minoura Static void upl_rxeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
    201  1.3.2.1   minoura Static void upl_txeof(usbd_xfer_handle, usbd_private_handle, usbd_status);
    202  1.3.2.1   minoura Static void upl_start(struct ifnet *);
    203  1.3.2.1   minoura Static int upl_ioctl(struct ifnet *, u_long, caddr_t);
    204  1.3.2.1   minoura Static void upl_init(void *);
    205  1.3.2.1   minoura Static void upl_stop(struct upl_softc *);
    206  1.3.2.1   minoura Static void upl_watchdog(struct ifnet *);
    207  1.3.2.1   minoura 
    208  1.3.2.1   minoura Static int upl_output(struct ifnet *, struct mbuf *, struct sockaddr *,
    209  1.3.2.1   minoura 		      struct rtentry *);
    210  1.3.2.1   minoura Static void upl_input(struct ifnet *, struct mbuf *);
    211      1.1  augustss 
    212      1.1  augustss /*
    213      1.1  augustss  * Probe for a Prolific chip.
    214      1.1  augustss  */
    215      1.1  augustss USB_MATCH(upl)
    216      1.1  augustss {
    217      1.1  augustss 	USB_MATCH_START(upl, uaa);
    218      1.1  augustss 	struct upl_type			*t;
    219      1.1  augustss 
    220      1.1  augustss 	if (uaa->iface != NULL)
    221      1.1  augustss 		return (UMATCH_NONE);
    222      1.1  augustss 
    223      1.1  augustss 	for (t = sc_devs; t->upl_vid != 0; t++)
    224      1.1  augustss 		if (uaa->vendor == t->upl_vid && uaa->product == t->upl_did)
    225      1.1  augustss 			return (UMATCH_VENDOR_PRODUCT);
    226      1.1  augustss 
    227      1.1  augustss 	return (UMATCH_NONE);
    228      1.1  augustss }
    229      1.1  augustss 
    230      1.1  augustss USB_ATTACH(upl)
    231      1.1  augustss {
    232      1.1  augustss 	USB_ATTACH_START(upl, sc, uaa);
    233      1.1  augustss 	char			devinfo[1024];
    234      1.1  augustss 	int			s;
    235      1.1  augustss 	usbd_device_handle	dev = uaa->device;
    236      1.1  augustss 	usbd_interface_handle	iface;
    237      1.1  augustss 	usbd_status		err;
    238      1.1  augustss 	struct ifnet		*ifp;
    239      1.1  augustss 	usb_interface_descriptor_t	*id;
    240      1.1  augustss 	usb_endpoint_descriptor_t	*ed;
    241      1.1  augustss 	int			i;
    242      1.1  augustss 
    243      1.1  augustss 	DPRINTFN(5,(" : upl_attach: sc=%p, dev=%p", sc, dev));
    244      1.1  augustss 
    245      1.1  augustss 	usbd_devinfo(dev, 0, devinfo);
    246      1.1  augustss 	USB_ATTACH_SETUP;
    247      1.1  augustss 	printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
    248      1.1  augustss 
    249      1.1  augustss 	err = usbd_set_config_no(dev, UPL_CONFIG_NO, 0);
    250      1.1  augustss 	if (err) {
    251      1.1  augustss 		printf("%s: setting config no failed\n",
    252      1.1  augustss 		    USBDEVNAME(sc->sc_dev));
    253      1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    254      1.1  augustss 	}
    255      1.1  augustss 
    256      1.1  augustss 	sc->sc_udev = dev;
    257      1.1  augustss 	sc->sc_product = uaa->product;
    258      1.1  augustss 	sc->sc_vendor = uaa->vendor;
    259      1.1  augustss 
    260      1.1  augustss 	err = usbd_device2interface_handle(dev, UPL_IFACE_IDX, &iface);
    261      1.1  augustss 	if (err) {
    262      1.1  augustss 		printf("%s: getting interface handle failed\n",
    263      1.1  augustss 		    USBDEVNAME(sc->sc_dev));
    264      1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    265      1.1  augustss 	}
    266      1.1  augustss 
    267      1.1  augustss 	sc->sc_iface = iface;
    268      1.1  augustss 	id = usbd_get_interface_descriptor(iface);
    269      1.1  augustss 
    270      1.1  augustss 	/* Find endpoints. */
    271      1.1  augustss 	for (i = 0; i < id->bNumEndpoints; i++) {
    272      1.1  augustss 		ed = usbd_interface2endpoint_descriptor(iface, i);
    273      1.1  augustss 		if (ed == NULL) {
    274      1.1  augustss 			printf("%s: couldn't get ep %d\n",
    275      1.1  augustss 			    USBDEVNAME(sc->sc_dev), i);
    276      1.1  augustss 			USB_ATTACH_ERROR_RETURN;
    277      1.1  augustss 		}
    278      1.1  augustss 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    279      1.1  augustss 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    280      1.1  augustss 			sc->sc_ed[UPL_ENDPT_RX] = ed->bEndpointAddress;
    281      1.1  augustss 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
    282      1.1  augustss 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
    283      1.1  augustss 			sc->sc_ed[UPL_ENDPT_TX] = ed->bEndpointAddress;
    284      1.1  augustss 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
    285      1.1  augustss 			   UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
    286      1.1  augustss 			sc->sc_ed[UPL_ENDPT_INTR] = ed->bEndpointAddress;
    287      1.1  augustss 		}
    288      1.1  augustss 	}
    289      1.1  augustss 
    290      1.1  augustss 	if (sc->sc_ed[UPL_ENDPT_RX] == 0 || sc->sc_ed[UPL_ENDPT_TX] == 0 ||
    291      1.1  augustss 	    sc->sc_ed[UPL_ENDPT_INTR] == 0) {
    292      1.1  augustss 		printf("%s: missing endpoint\n", USBDEVNAME(sc->sc_dev));
    293      1.1  augustss 		USB_ATTACH_ERROR_RETURN;
    294      1.1  augustss 	}
    295      1.1  augustss 
    296      1.1  augustss 	s = splimp();
    297      1.1  augustss 
    298      1.1  augustss 	/* Initialize interface info.*/
    299      1.1  augustss 	ifp = &sc->sc_if;
    300      1.1  augustss 	ifp->if_softc = sc;
    301      1.1  augustss 	ifp->if_mtu = UPL_BUFSZ;
    302      1.1  augustss 	ifp->if_flags = IFF_POINTOPOINT | IFF_NOARP | IFF_SIMPLEX;
    303      1.1  augustss 	ifp->if_ioctl = upl_ioctl;
    304      1.1  augustss 	ifp->if_start = upl_start;
    305      1.1  augustss 	ifp->if_watchdog = upl_watchdog;
    306      1.1  augustss 	strncpy(ifp->if_xname, USBDEVNAME(sc->sc_dev), IFNAMSIZ);
    307      1.1  augustss 
    308      1.1  augustss 	ifp->if_type = IFT_OTHER;
    309      1.1  augustss 	ifp->if_addrlen = 0;
    310      1.1  augustss 	ifp->if_hdrlen = 0;
    311      1.1  augustss 	ifp->if_output = upl_output;
    312      1.1  augustss 	ifp->if_input = upl_input;
    313      1.1  augustss 	ifp->if_baudrate = 12000000;
    314      1.1  augustss 
    315      1.1  augustss 	/* Attach the interface. */
    316      1.1  augustss 	if_attach(ifp);
    317      1.1  augustss 
    318      1.1  augustss #if NBPFILTER > 0
    319      1.1  augustss 	bpfattach(&ifp->if_bpf, ifp, DLT_EN10MB, 0);
    320      1.1  augustss #endif
    321      1.1  augustss #if NRND > 0
    322      1.1  augustss 	rnd_attach_source(&sc->sc_rnd_source, USBDEVNAME(sc->sc_dev),
    323      1.1  augustss 	    RND_TYPE_NET, 0);
    324      1.1  augustss #endif
    325      1.1  augustss 
    326      1.1  augustss 	sc->sc_attached = 1;
    327      1.1  augustss 	splx(s);
    328      1.1  augustss 
    329      1.1  augustss 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
    330      1.1  augustss 	    USBDEV(sc->sc_dev));
    331      1.1  augustss 
    332      1.1  augustss 	USB_ATTACH_SUCCESS_RETURN;
    333      1.1  augustss }
    334      1.1  augustss 
    335      1.1  augustss USB_DETACH(upl)
    336      1.1  augustss {
    337      1.1  augustss 	USB_DETACH_START(upl, sc);
    338      1.1  augustss 	struct ifnet		*ifp = &sc->sc_if;
    339      1.1  augustss 	int			s;
    340      1.1  augustss 
    341      1.1  augustss 	DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__));
    342      1.1  augustss 
    343      1.1  augustss 	s = splusb();
    344      1.1  augustss 
    345      1.1  augustss 	if (!sc->sc_attached) {
    346      1.1  augustss 		/* Detached before attached finished, so just bail out. */
    347      1.1  augustss 		splx(s);
    348      1.1  augustss 		return (0);
    349      1.1  augustss 	}
    350      1.1  augustss 
    351      1.1  augustss 	if (ifp->if_flags & IFF_RUNNING)
    352      1.1  augustss 		upl_stop(sc);
    353      1.1  augustss 
    354      1.1  augustss #if NRND > 0
    355      1.1  augustss 	rnd_detach_source(&sc->sc_rnd_source);
    356      1.1  augustss #endif
    357      1.1  augustss #if NBPFILTER > 0
    358      1.1  augustss 	bpfdetach(ifp);
    359      1.1  augustss #endif
    360      1.1  augustss 	ether_ifdetach(ifp);
    361      1.1  augustss 
    362      1.1  augustss 	if_detach(ifp);
    363      1.1  augustss 
    364      1.1  augustss #ifdef DIAGNOSTIC
    365      1.1  augustss 	if (sc->sc_ep[UPL_ENDPT_TX] != NULL ||
    366      1.1  augustss 	    sc->sc_ep[UPL_ENDPT_RX] != NULL ||
    367      1.1  augustss 	    sc->sc_ep[UPL_ENDPT_INTR] != NULL)
    368      1.1  augustss 		printf("%s: detach has active endpoints\n",
    369      1.1  augustss 		       USBDEVNAME(sc->sc_dev));
    370      1.1  augustss #endif
    371      1.1  augustss 
    372      1.1  augustss 	sc->sc_attached = 0;
    373      1.1  augustss 	splx(s);
    374      1.1  augustss 
    375      1.1  augustss 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
    376      1.1  augustss 	    USBDEV(sc->sc_dev));
    377      1.1  augustss 
    378      1.1  augustss 	return (0);
    379      1.1  augustss }
    380      1.1  augustss 
    381      1.1  augustss int
    382  1.3.2.1   minoura upl_activate(device_ptr_t self, enum devact act)
    383      1.1  augustss {
    384      1.1  augustss 	struct upl_softc *sc = (struct upl_softc *)self;
    385      1.1  augustss 
    386      1.1  augustss 	DPRINTFN(2,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__));
    387      1.1  augustss 
    388      1.1  augustss 	switch (act) {
    389      1.1  augustss 	case DVACT_ACTIVATE:
    390      1.1  augustss 		return (EOPNOTSUPP);
    391      1.1  augustss 		break;
    392      1.1  augustss 
    393      1.1  augustss 	case DVACT_DEACTIVATE:
    394      1.1  augustss 		/* Deactivate the interface. */
    395      1.1  augustss 		if_deactivate(&sc->sc_if);
    396      1.1  augustss 		sc->sc_dying = 1;
    397      1.1  augustss 		break;
    398      1.1  augustss 	}
    399      1.1  augustss 	return (0);
    400      1.1  augustss }
    401      1.1  augustss 
    402      1.1  augustss /*
    403      1.1  augustss  * Initialize an RX descriptor and attach an MBUF cluster.
    404      1.1  augustss  */
    405      1.1  augustss Static int
    406  1.3.2.1   minoura upl_newbuf(struct upl_softc *sc, struct upl_chain *c, struct mbuf *m)
    407      1.1  augustss {
    408      1.1  augustss 	struct mbuf		*m_new = NULL;
    409      1.1  augustss 
    410      1.1  augustss 	DPRINTFN(8,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__));
    411      1.1  augustss 
    412      1.1  augustss 	if (m == NULL) {
    413      1.1  augustss 		MGETHDR(m_new, M_DONTWAIT, MT_DATA);
    414      1.1  augustss 		if (m_new == NULL) {
    415      1.1  augustss 			printf("%s: no memory for rx list "
    416      1.1  augustss 			    "-- packet dropped!\n", USBDEVNAME(sc->sc_dev));
    417      1.1  augustss 			return (ENOBUFS);
    418      1.1  augustss 		}
    419      1.1  augustss 
    420      1.1  augustss 		MCLGET(m_new, M_DONTWAIT);
    421      1.1  augustss 		if (!(m_new->m_flags & M_EXT)) {
    422      1.1  augustss 			printf("%s: no memory for rx list "
    423      1.1  augustss 			    "-- packet dropped!\n", USBDEVNAME(sc->sc_dev));
    424      1.1  augustss 			m_freem(m_new);
    425      1.1  augustss 			return (ENOBUFS);
    426      1.1  augustss 		}
    427      1.1  augustss 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
    428      1.1  augustss 	} else {
    429      1.1  augustss 		m_new = m;
    430      1.1  augustss 		m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
    431      1.1  augustss 		m_new->m_data = m_new->m_ext.ext_buf;
    432      1.1  augustss 	}
    433      1.1  augustss 
    434      1.1  augustss 	c->upl_mbuf = m_new;
    435      1.1  augustss 
    436      1.1  augustss 	return (0);
    437      1.1  augustss }
    438      1.1  augustss 
    439      1.1  augustss Static int
    440  1.3.2.1   minoura upl_rx_list_init(struct upl_softc *sc)
    441      1.1  augustss {
    442      1.1  augustss 	struct upl_cdata	*cd;
    443      1.1  augustss 	struct upl_chain	*c;
    444      1.1  augustss 	int			i;
    445      1.1  augustss 
    446      1.1  augustss 	DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__));
    447      1.1  augustss 
    448      1.1  augustss 	cd = &sc->sc_cdata;
    449      1.1  augustss 	for (i = 0; i < UPL_RX_LIST_CNT; i++) {
    450      1.1  augustss 		c = &cd->upl_rx_chain[i];
    451      1.1  augustss 		c->upl_sc = sc;
    452      1.1  augustss 		c->upl_idx = i;
    453      1.1  augustss 		if (upl_newbuf(sc, c, NULL) == ENOBUFS)
    454      1.1  augustss 			return (ENOBUFS);
    455      1.1  augustss 		if (c->upl_xfer == NULL) {
    456      1.1  augustss 			c->upl_xfer = usbd_alloc_xfer(sc->sc_udev);
    457      1.1  augustss 			if (c->upl_xfer == NULL)
    458      1.1  augustss 				return (ENOBUFS);
    459      1.1  augustss 			c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ);
    460      1.1  augustss 			if (c->upl_buf == NULL) {
    461      1.1  augustss 				usbd_free_xfer(c->upl_xfer);
    462      1.1  augustss 				return (ENOBUFS);
    463      1.1  augustss 			}
    464      1.1  augustss 		}
    465      1.1  augustss 	}
    466      1.1  augustss 
    467      1.1  augustss 	return (0);
    468      1.1  augustss }
    469      1.1  augustss 
    470      1.1  augustss Static int
    471  1.3.2.1   minoura upl_tx_list_init(struct upl_softc *sc)
    472      1.1  augustss {
    473      1.1  augustss 	struct upl_cdata	*cd;
    474      1.1  augustss 	struct upl_chain	*c;
    475      1.1  augustss 	int			i;
    476      1.1  augustss 
    477      1.1  augustss 	DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev), __FUNCTION__));
    478      1.1  augustss 
    479      1.1  augustss 	cd = &sc->sc_cdata;
    480      1.1  augustss 	for (i = 0; i < UPL_TX_LIST_CNT; i++) {
    481      1.1  augustss 		c = &cd->upl_tx_chain[i];
    482      1.1  augustss 		c->upl_sc = sc;
    483      1.1  augustss 		c->upl_idx = i;
    484      1.1  augustss 		c->upl_mbuf = NULL;
    485      1.1  augustss 		if (c->upl_xfer == NULL) {
    486      1.1  augustss 			c->upl_xfer = usbd_alloc_xfer(sc->sc_udev);
    487      1.1  augustss 			if (c->upl_xfer == NULL)
    488      1.1  augustss 				return (ENOBUFS);
    489      1.1  augustss 			c->upl_buf = usbd_alloc_buffer(c->upl_xfer, UPL_BUFSZ);
    490      1.1  augustss 			if (c->upl_buf == NULL) {
    491      1.1  augustss 				usbd_free_xfer(c->upl_xfer);
    492      1.1  augustss 				return (ENOBUFS);
    493      1.1  augustss 			}
    494      1.1  augustss 		}
    495      1.1  augustss 	}
    496      1.1  augustss 
    497      1.1  augustss 	return (0);
    498      1.1  augustss }
    499      1.1  augustss 
    500      1.1  augustss /*
    501      1.1  augustss  * A frame has been uploaded: pass the resulting mbuf chain up to
    502      1.1  augustss  * the higher level protocols.
    503      1.1  augustss  */
    504      1.1  augustss Static void
    505  1.3.2.1   minoura upl_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
    506      1.1  augustss {
    507      1.1  augustss 	struct upl_chain	*c = priv;
    508      1.1  augustss 	struct upl_softc	*sc = c->upl_sc;
    509      1.1  augustss 	struct ifnet		*ifp = &sc->sc_if;
    510      1.1  augustss 	struct mbuf		*m;
    511      1.1  augustss 	int			total_len = 0;
    512      1.1  augustss 	int			s;
    513      1.1  augustss 
    514      1.1  augustss 	if (sc->sc_dying)
    515      1.1  augustss 		return;
    516      1.1  augustss 
    517      1.1  augustss 	if (!(ifp->if_flags & IFF_RUNNING))
    518      1.1  augustss 		return;
    519      1.1  augustss 
    520      1.1  augustss 	if (status != USBD_NORMAL_COMPLETION) {
    521      1.1  augustss 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
    522      1.1  augustss 			return;
    523      1.1  augustss 		sc->sc_rx_errs++;
    524      1.1  augustss 		if (usbd_ratecheck(&sc->sc_rx_notice)) {
    525      1.1  augustss 			printf("%s: %u usb errors on rx: %s\n",
    526      1.1  augustss 			    USBDEVNAME(sc->sc_dev), sc->sc_rx_errs,
    527      1.1  augustss 			    usbd_errstr(status));
    528      1.1  augustss 			sc->sc_rx_errs = 0;
    529      1.1  augustss 		}
    530      1.1  augustss 		if (status == USBD_STALLED)
    531      1.1  augustss 			usbd_clear_endpoint_stall(sc->sc_ep[UPL_ENDPT_RX]);
    532      1.1  augustss 		goto done;
    533      1.1  augustss 	}
    534      1.1  augustss 
    535      1.1  augustss 	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
    536      1.1  augustss 
    537      1.1  augustss 	DPRINTFN(9,("%s: %s: enter status=%d length=%d\n",
    538      1.1  augustss 		    USBDEVNAME(sc->sc_dev), __FUNCTION__, status, total_len));
    539      1.1  augustss 
    540      1.1  augustss 	m = c->upl_mbuf;
    541      1.1  augustss 	memcpy(mtod(c->upl_mbuf, char *), c->upl_buf, total_len);
    542      1.1  augustss 
    543      1.1  augustss 	ifp->if_ipackets++;
    544      1.1  augustss 	m->m_pkthdr.len = m->m_len = total_len;
    545      1.1  augustss 
    546      1.1  augustss 	m->m_pkthdr.rcvif = ifp;
    547      1.1  augustss 
    548      1.1  augustss 	s = splimp();
    549      1.1  augustss 
    550      1.1  augustss 	/* XXX ugly */
    551      1.1  augustss 	if (upl_newbuf(sc, c, NULL) == ENOBUFS) {
    552      1.1  augustss 		ifp->if_ierrors++;
    553      1.1  augustss 		goto done1;
    554      1.1  augustss 	}
    555      1.1  augustss 
    556      1.1  augustss #if NBPFILTER > 0
    557      1.1  augustss 	/*
    558      1.1  augustss 	 * Handle BPF listeners. Let the BPF user see the packet, but
    559      1.1  augustss 	 * don't pass it up to the ether_input() layer unless it's
    560      1.1  augustss 	 * a broadcast packet, multicast packet, matches our ethernet
    561      1.1  augustss 	 * address or the interface is in promiscuous mode.
    562      1.1  augustss 	 */
    563      1.1  augustss 	if (ifp->if_bpf) {
    564      1.1  augustss 		BPF_MTAP(ifp, m);
    565      1.1  augustss 	}
    566      1.1  augustss #endif
    567      1.1  augustss 
    568      1.1  augustss 	DPRINTFN(10,("%s: %s: deliver %d\n", USBDEVNAME(sc->sc_dev),
    569      1.1  augustss 		    __FUNCTION__, m->m_len));
    570      1.1  augustss 
    571      1.1  augustss 	IF_INPUT(ifp, m);
    572      1.1  augustss 
    573      1.1  augustss  done1:
    574      1.1  augustss 	splx(s);
    575      1.1  augustss 
    576      1.1  augustss  done:
    577      1.1  augustss #if 1
    578      1.1  augustss 	/* Setup new transfer. */
    579      1.1  augustss 	usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX],
    580      1.1  augustss 	    c, c->upl_buf, UPL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
    581      1.1  augustss 	    USBD_NO_TIMEOUT, upl_rxeof);
    582      1.1  augustss 	usbd_transfer(c->upl_xfer);
    583      1.1  augustss 
    584      1.1  augustss 	DPRINTFN(10,("%s: %s: start rx\n", USBDEVNAME(sc->sc_dev),
    585      1.1  augustss 		    __FUNCTION__));
    586      1.1  augustss #endif
    587      1.1  augustss }
    588      1.1  augustss 
    589      1.1  augustss /*
    590      1.1  augustss  * A frame was downloaded to the chip. It's safe for us to clean up
    591      1.1  augustss  * the list buffers.
    592      1.1  augustss  */
    593      1.1  augustss Static void
    594  1.3.2.1   minoura upl_txeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
    595      1.1  augustss {
    596      1.1  augustss 	struct upl_chain	*c = priv;
    597      1.1  augustss 	struct upl_softc	*sc = c->upl_sc;
    598      1.1  augustss 	struct ifnet		*ifp = &sc->sc_if;
    599      1.1  augustss 	int			s;
    600      1.1  augustss 
    601      1.1  augustss 	if (sc->sc_dying)
    602      1.1  augustss 		return;
    603      1.1  augustss 
    604      1.1  augustss 	s = splimp();
    605      1.1  augustss 
    606      1.1  augustss 	DPRINTFN(10,("%s: %s: enter status=%d\n", USBDEVNAME(sc->sc_dev),
    607      1.1  augustss 		    __FUNCTION__, status));
    608      1.1  augustss 
    609      1.1  augustss 	ifp->if_timer = 0;
    610      1.1  augustss 	ifp->if_flags &= ~IFF_OACTIVE;
    611      1.1  augustss 
    612      1.1  augustss 	if (status != USBD_NORMAL_COMPLETION) {
    613      1.1  augustss 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
    614      1.1  augustss 			splx(s);
    615      1.1  augustss 			return;
    616      1.1  augustss 		}
    617      1.1  augustss 		ifp->if_oerrors++;
    618      1.1  augustss 		printf("%s: usb error on tx: %s\n", USBDEVNAME(sc->sc_dev),
    619      1.1  augustss 		    usbd_errstr(status));
    620      1.1  augustss 		if (status == USBD_STALLED)
    621      1.1  augustss 			usbd_clear_endpoint_stall(sc->sc_ep[UPL_ENDPT_TX]);
    622      1.1  augustss 		splx(s);
    623      1.1  augustss 		return;
    624      1.1  augustss 	}
    625      1.1  augustss 
    626      1.1  augustss 	ifp->if_opackets++;
    627      1.1  augustss 
    628      1.1  augustss 	m_freem(c->upl_mbuf);
    629      1.1  augustss 	c->upl_mbuf = NULL;
    630      1.1  augustss 
    631      1.1  augustss 	if (ifp->if_snd.ifq_head != NULL)
    632      1.1  augustss 		upl_start(ifp);
    633      1.1  augustss 
    634      1.1  augustss 	splx(s);
    635      1.1  augustss }
    636      1.1  augustss 
    637      1.1  augustss Static int
    638  1.3.2.1   minoura upl_send(struct upl_softc *sc, struct mbuf *m, int idx)
    639      1.1  augustss {
    640      1.1  augustss 	int			total_len;
    641      1.1  augustss 	struct upl_chain	*c;
    642      1.1  augustss 	usbd_status		err;
    643      1.1  augustss 
    644      1.1  augustss 	c = &sc->sc_cdata.upl_tx_chain[idx];
    645      1.1  augustss 
    646      1.1  augustss 	/*
    647      1.1  augustss 	 * Copy the mbuf data into a contiguous buffer, leaving two
    648      1.1  augustss 	 * bytes at the beginning to hold the frame length.
    649      1.1  augustss 	 */
    650      1.1  augustss 	m_copydata(m, 0, m->m_pkthdr.len, c->upl_buf);
    651      1.1  augustss 	c->upl_mbuf = m;
    652      1.1  augustss 
    653      1.1  augustss 	total_len = m->m_pkthdr.len;
    654      1.1  augustss 
    655      1.1  augustss 	DPRINTFN(10,("%s: %s: total_len=%d\n",
    656      1.1  augustss 		     USBDEVNAME(sc->sc_dev), __FUNCTION__, total_len));
    657      1.1  augustss 
    658      1.1  augustss 	usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_TX],
    659      1.1  augustss 	    c, c->upl_buf, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT,
    660      1.1  augustss 	    upl_txeof);
    661      1.1  augustss 
    662      1.1  augustss 	/* Transmit */
    663      1.1  augustss 	err = usbd_transfer(c->upl_xfer);
    664      1.1  augustss 	if (err != USBD_IN_PROGRESS) {
    665      1.1  augustss 		printf("%s: upl_send error=%s\n", USBDEVNAME(sc->sc_dev),
    666      1.1  augustss 		       usbd_errstr(err));
    667      1.1  augustss 		upl_stop(sc);
    668      1.1  augustss 		return (EIO);
    669      1.1  augustss 	}
    670      1.1  augustss 
    671      1.1  augustss 	sc->sc_cdata.upl_tx_cnt++;
    672      1.1  augustss 
    673      1.1  augustss 	return (0);
    674      1.1  augustss }
    675      1.1  augustss 
    676      1.1  augustss Static void
    677  1.3.2.1   minoura upl_start(struct ifnet *ifp)
    678      1.1  augustss {
    679      1.1  augustss 	struct upl_softc	*sc = ifp->if_softc;
    680      1.1  augustss 	struct mbuf		*m_head = NULL;
    681      1.1  augustss 
    682      1.1  augustss 	if (sc->sc_dying)
    683      1.1  augustss 		return;
    684      1.1  augustss 
    685      1.1  augustss 	DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__FUNCTION__));
    686      1.1  augustss 
    687      1.1  augustss 	if (ifp->if_flags & IFF_OACTIVE)
    688      1.1  augustss 		return;
    689      1.1  augustss 
    690      1.1  augustss 	IF_DEQUEUE(&ifp->if_snd, m_head);
    691      1.1  augustss 	if (m_head == NULL)
    692      1.1  augustss 		return;
    693      1.1  augustss 
    694      1.1  augustss 	if (upl_send(sc, m_head, 0)) {
    695      1.1  augustss 		IF_PREPEND(&ifp->if_snd, m_head);
    696      1.1  augustss 		ifp->if_flags |= IFF_OACTIVE;
    697      1.1  augustss 		return;
    698      1.1  augustss 	}
    699      1.1  augustss 
    700      1.1  augustss #if NBPFILTER > 0
    701      1.1  augustss 	/*
    702      1.1  augustss 	 * If there's a BPF listener, bounce a copy of this frame
    703      1.1  augustss 	 * to him.
    704      1.1  augustss 	 */
    705      1.1  augustss 	if (ifp->if_bpf)
    706      1.1  augustss 		BPF_MTAP(ifp, m_head);
    707      1.1  augustss #endif
    708      1.1  augustss 
    709      1.1  augustss 	ifp->if_flags |= IFF_OACTIVE;
    710      1.1  augustss 
    711      1.1  augustss 	/*
    712      1.1  augustss 	 * Set a timeout in case the chip goes out to lunch.
    713      1.1  augustss 	 */
    714      1.1  augustss 	ifp->if_timer = 5;
    715      1.1  augustss }
    716      1.1  augustss 
    717      1.1  augustss Static void
    718  1.3.2.1   minoura upl_init(void *xsc)
    719      1.1  augustss {
    720      1.1  augustss 	struct upl_softc	*sc = xsc;
    721      1.1  augustss 	struct ifnet		*ifp = &sc->sc_if;
    722      1.1  augustss 	int			s;
    723      1.1  augustss 
    724      1.1  augustss 	if (sc->sc_dying)
    725      1.1  augustss 		return;
    726      1.1  augustss 
    727      1.1  augustss 	DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__FUNCTION__));
    728      1.1  augustss 
    729      1.1  augustss 	if (ifp->if_flags & IFF_RUNNING)
    730      1.1  augustss 		return;
    731      1.1  augustss 
    732      1.1  augustss 	s = splimp();
    733      1.1  augustss 
    734      1.1  augustss 	/* Init TX ring. */
    735      1.1  augustss 	if (upl_tx_list_init(sc) == ENOBUFS) {
    736      1.1  augustss 		printf("%s: tx list init failed\n", USBDEVNAME(sc->sc_dev));
    737      1.1  augustss 		splx(s);
    738      1.1  augustss 		return;
    739      1.1  augustss 	}
    740      1.1  augustss 
    741      1.1  augustss 	/* Init RX ring. */
    742      1.1  augustss 	if (upl_rx_list_init(sc) == ENOBUFS) {
    743      1.1  augustss 		printf("%s: rx list init failed\n", USBDEVNAME(sc->sc_dev));
    744      1.1  augustss 		splx(s);
    745      1.1  augustss 		return;
    746      1.1  augustss 	}
    747      1.1  augustss 
    748      1.1  augustss 	if (sc->sc_ep[UPL_ENDPT_RX] == NULL) {
    749      1.1  augustss 		if (upl_openpipes(sc)) {
    750      1.1  augustss 			splx(s);
    751      1.1  augustss 			return;
    752      1.1  augustss 		}
    753      1.1  augustss 	}
    754      1.1  augustss 
    755      1.1  augustss 	ifp->if_flags |= IFF_RUNNING;
    756      1.1  augustss 	ifp->if_flags &= ~IFF_OACTIVE;
    757      1.1  augustss 
    758      1.1  augustss 	splx(s);
    759      1.1  augustss }
    760      1.1  augustss 
    761      1.1  augustss Static int
    762  1.3.2.1   minoura upl_openpipes(struct upl_softc *sc)
    763      1.1  augustss {
    764      1.1  augustss 	struct upl_chain	*c;
    765      1.1  augustss 	usbd_status		err;
    766      1.1  augustss 	int			i;
    767      1.1  augustss 
    768      1.1  augustss 	/* Open RX and TX pipes. */
    769      1.1  augustss 	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_RX],
    770      1.1  augustss 	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_RX]);
    771      1.1  augustss 	if (err) {
    772      1.1  augustss 		printf("%s: open rx pipe failed: %s\n",
    773      1.1  augustss 		    USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    774      1.1  augustss 		return (EIO);
    775      1.1  augustss 	}
    776      1.1  augustss 	err = usbd_open_pipe(sc->sc_iface, sc->sc_ed[UPL_ENDPT_TX],
    777      1.1  augustss 	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_TX]);
    778      1.1  augustss 	if (err) {
    779      1.1  augustss 		printf("%s: open tx pipe failed: %s\n",
    780      1.1  augustss 		    USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    781      1.1  augustss 		return (EIO);
    782      1.1  augustss 	}
    783      1.1  augustss 	err = usbd_open_pipe_intr(sc->sc_iface, sc->sc_ed[UPL_ENDPT_INTR],
    784      1.1  augustss 	    USBD_EXCLUSIVE_USE, &sc->sc_ep[UPL_ENDPT_INTR], sc,
    785      1.1  augustss 	    &sc->sc_ibuf, UPL_INTR_PKTLEN, upl_intr,
    786      1.1  augustss 	    UPL_INTR_INTERVAL);
    787      1.1  augustss 	if (err) {
    788      1.1  augustss 		printf("%s: open intr pipe failed: %s\n",
    789      1.1  augustss 		    USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    790      1.1  augustss 		return (EIO);
    791      1.1  augustss 	}
    792      1.1  augustss 
    793      1.1  augustss 
    794      1.1  augustss #if 1
    795      1.1  augustss 	/* Start up the receive pipe. */
    796      1.1  augustss 	for (i = 0; i < UPL_RX_LIST_CNT; i++) {
    797      1.1  augustss 		c = &sc->sc_cdata.upl_rx_chain[i];
    798      1.1  augustss 		usbd_setup_xfer(c->upl_xfer, sc->sc_ep[UPL_ENDPT_RX],
    799      1.1  augustss 		    c, c->upl_buf, UPL_BUFSZ,
    800      1.1  augustss 		    USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
    801      1.1  augustss 		    upl_rxeof);
    802      1.1  augustss 		usbd_transfer(c->upl_xfer);
    803      1.1  augustss 	}
    804      1.1  augustss #endif
    805      1.1  augustss 
    806      1.1  augustss 	return (0);
    807      1.1  augustss }
    808      1.1  augustss 
    809      1.1  augustss Static void
    810  1.3.2.1   minoura upl_intr(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
    811      1.1  augustss {
    812      1.1  augustss 	struct upl_softc	*sc = priv;
    813      1.1  augustss 	struct ifnet		*ifp = &sc->sc_if;
    814      1.1  augustss 	uByte			stat;
    815      1.1  augustss 
    816      1.1  augustss 	DPRINTFN(15,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__FUNCTION__));
    817      1.1  augustss 
    818      1.1  augustss 	if (sc->sc_dying)
    819      1.1  augustss 		return;
    820      1.1  augustss 
    821      1.1  augustss 	if (!(ifp->if_flags & IFF_RUNNING))
    822      1.1  augustss 		return;
    823      1.1  augustss 
    824      1.1  augustss 	if (status != USBD_NORMAL_COMPLETION) {
    825      1.1  augustss 		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
    826      1.1  augustss 			return;
    827      1.1  augustss 		}
    828      1.1  augustss 		sc->sc_intr_errs++;
    829      1.1  augustss 		if (usbd_ratecheck(&sc->sc_rx_notice)) {
    830      1.1  augustss 			printf("%s: %u usb errors on intr: %s\n",
    831      1.1  augustss 			    USBDEVNAME(sc->sc_dev), sc->sc_rx_errs,
    832      1.1  augustss 			    usbd_errstr(status));
    833      1.1  augustss 			sc->sc_intr_errs = 0;
    834      1.1  augustss 		}
    835      1.1  augustss 		if (status == USBD_STALLED)
    836      1.1  augustss 			usbd_clear_endpoint_stall(sc->sc_ep[UPL_ENDPT_RX]);
    837      1.1  augustss 		return;
    838      1.1  augustss 	}
    839      1.1  augustss 
    840      1.1  augustss 	stat = sc->sc_ibuf;
    841      1.1  augustss 
    842      1.1  augustss 	if (stat == 0)
    843      1.1  augustss 		return;
    844      1.1  augustss 
    845      1.1  augustss 	DPRINTFN(10,("%s: %s: stat=0x%02x\n", USBDEVNAME(sc->sc_dev),
    846      1.1  augustss 		     __FUNCTION__, stat));
    847      1.1  augustss 
    848      1.1  augustss }
    849      1.1  augustss 
    850      1.1  augustss Static int
    851  1.3.2.1   minoura upl_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
    852      1.1  augustss {
    853      1.1  augustss 	struct upl_softc	*sc = ifp->if_softc;
    854      1.1  augustss 	struct ifaddr 		*ifa = (struct ifaddr *)data;
    855      1.1  augustss 	struct ifreq		*ifr = (struct ifreq *)data;
    856      1.1  augustss 	int			s, error = 0;
    857      1.1  augustss 
    858      1.1  augustss 	if (sc->sc_dying)
    859      1.1  augustss 		return (EIO);
    860      1.1  augustss 
    861      1.1  augustss 	DPRINTFN(5,("%s: %s: cmd=0x%08lx\n",
    862      1.1  augustss 		    USBDEVNAME(sc->sc_dev), __FUNCTION__, command));
    863      1.1  augustss 
    864      1.1  augustss 	s = splimp();
    865      1.1  augustss 
    866      1.1  augustss 	switch(command) {
    867      1.1  augustss 	case SIOCSIFADDR:
    868      1.1  augustss 		ifp->if_flags |= IFF_UP;
    869      1.1  augustss 		upl_init(sc);
    870      1.1  augustss 
    871      1.1  augustss 		switch (ifa->ifa_addr->sa_family) {
    872      1.1  augustss #ifdef INET
    873      1.1  augustss 		case AF_INET:
    874      1.1  augustss 			break;
    875      1.1  augustss #endif /* INET */
    876      1.1  augustss #ifdef NS
    877      1.1  augustss 		case AF_NS:
    878      1.1  augustss 		    {
    879      1.1  augustss 			struct ns_addr *ina = &IA_SNS(ifa)->sns_addr;
    880      1.1  augustss 
    881      1.1  augustss 			if (ns_nullhost(*ina))
    882      1.1  augustss 				ina->x_host = *(union ns_host *)
    883      1.1  augustss 					LLADDR(ifp->if_sadl);
    884      1.1  augustss 			else
    885      1.1  augustss 				memcpy(LLADDR(ifp->if_sadl),
    886      1.1  augustss 				       ina->x_host.c_host,
    887      1.1  augustss 				       ifp->if_addrlen);
    888      1.1  augustss 			break;
    889      1.1  augustss 		    }
    890      1.1  augustss #endif /* NS */
    891      1.1  augustss 		}
    892      1.1  augustss 		break;
    893      1.1  augustss 
    894      1.1  augustss 	case SIOCSIFMTU:
    895      1.1  augustss 		if (ifr->ifr_mtu > UPL_BUFSZ)
    896      1.1  augustss 			error = EINVAL;
    897      1.1  augustss 		else
    898      1.1  augustss 			ifp->if_mtu = ifr->ifr_mtu;
    899      1.1  augustss 		break;
    900      1.1  augustss 
    901      1.1  augustss 	case SIOCSIFFLAGS:
    902      1.1  augustss 		if (ifp->if_flags & IFF_UP) {
    903      1.1  augustss 			if (!(ifp->if_flags & IFF_RUNNING))
    904      1.1  augustss 				upl_init(sc);
    905      1.1  augustss 		} else {
    906      1.1  augustss 			if (ifp->if_flags & IFF_RUNNING)
    907      1.1  augustss 				upl_stop(sc);
    908      1.1  augustss 		}
    909      1.1  augustss 		error = 0;
    910      1.1  augustss 		break;
    911      1.1  augustss 	default:
    912      1.1  augustss 		error = EINVAL;
    913      1.1  augustss 		break;
    914      1.1  augustss 	}
    915      1.1  augustss 
    916      1.1  augustss 	splx(s);
    917      1.1  augustss 
    918      1.1  augustss 	return (error);
    919      1.1  augustss }
    920      1.1  augustss 
    921      1.1  augustss Static void
    922  1.3.2.1   minoura upl_watchdog(struct ifnet *ifp)
    923      1.1  augustss {
    924      1.1  augustss 	struct upl_softc	*sc = ifp->if_softc;
    925      1.1  augustss 
    926      1.1  augustss 	DPRINTFN(5,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__FUNCTION__));
    927      1.1  augustss 
    928      1.1  augustss 	if (sc->sc_dying)
    929      1.1  augustss 		return;
    930      1.1  augustss 
    931      1.1  augustss 	ifp->if_oerrors++;
    932      1.1  augustss 	printf("%s: watchdog timeout\n", USBDEVNAME(sc->sc_dev));
    933      1.1  augustss 
    934      1.1  augustss 	upl_stop(sc);
    935      1.1  augustss 	upl_init(sc);
    936      1.1  augustss 
    937      1.1  augustss 	if (ifp->if_snd.ifq_head != NULL)
    938      1.1  augustss 		upl_start(ifp);
    939      1.1  augustss }
    940      1.1  augustss 
    941      1.1  augustss /*
    942      1.1  augustss  * Stop the adapter and free any mbufs allocated to the
    943      1.1  augustss  * RX and TX lists.
    944      1.1  augustss  */
    945      1.1  augustss Static void
    946  1.3.2.1   minoura upl_stop(struct upl_softc *sc)
    947      1.1  augustss {
    948      1.1  augustss 	usbd_status		err;
    949      1.1  augustss 	struct ifnet		*ifp;
    950      1.1  augustss 	int			i;
    951      1.1  augustss 
    952      1.1  augustss 	DPRINTFN(10,("%s: %s: enter\n", USBDEVNAME(sc->sc_dev),__FUNCTION__));
    953      1.1  augustss 
    954      1.1  augustss 	ifp = &sc->sc_if;
    955      1.1  augustss 	ifp->if_timer = 0;
    956      1.1  augustss 
    957      1.1  augustss 	/* Stop transfers. */
    958      1.1  augustss 	if (sc->sc_ep[UPL_ENDPT_RX] != NULL) {
    959      1.1  augustss 		err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_RX]);
    960      1.1  augustss 		if (err) {
    961      1.1  augustss 			printf("%s: abort rx pipe failed: %s\n",
    962      1.1  augustss 			USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    963      1.1  augustss 		}
    964      1.1  augustss 		err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_RX]);
    965      1.1  augustss 		if (err) {
    966      1.1  augustss 			printf("%s: close rx pipe failed: %s\n",
    967      1.1  augustss 			USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    968      1.1  augustss 		}
    969      1.1  augustss 		sc->sc_ep[UPL_ENDPT_RX] = NULL;
    970      1.1  augustss 	}
    971      1.1  augustss 
    972      1.1  augustss 	if (sc->sc_ep[UPL_ENDPT_TX] != NULL) {
    973      1.1  augustss 		err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_TX]);
    974      1.1  augustss 		if (err) {
    975      1.1  augustss 			printf("%s: abort tx pipe failed: %s\n",
    976      1.1  augustss 			USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    977      1.1  augustss 		}
    978      1.1  augustss 		err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_TX]);
    979      1.1  augustss 		if (err) {
    980      1.1  augustss 			printf("%s: close tx pipe failed: %s\n",
    981      1.1  augustss 			    USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    982      1.1  augustss 		}
    983      1.1  augustss 		sc->sc_ep[UPL_ENDPT_TX] = NULL;
    984      1.1  augustss 	}
    985      1.1  augustss 
    986      1.1  augustss 	if (sc->sc_ep[UPL_ENDPT_INTR] != NULL) {
    987      1.1  augustss 		err = usbd_abort_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
    988      1.1  augustss 		if (err) {
    989      1.1  augustss 			printf("%s: abort intr pipe failed: %s\n",
    990      1.1  augustss 			USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    991      1.1  augustss 		}
    992      1.1  augustss 		err = usbd_close_pipe(sc->sc_ep[UPL_ENDPT_INTR]);
    993      1.1  augustss 		if (err) {
    994      1.1  augustss 			printf("%s: close intr pipe failed: %s\n",
    995      1.1  augustss 			    USBDEVNAME(sc->sc_dev), usbd_errstr(err));
    996      1.1  augustss 		}
    997      1.1  augustss 		sc->sc_ep[UPL_ENDPT_INTR] = NULL;
    998      1.1  augustss 	}
    999      1.1  augustss 
   1000      1.1  augustss 	/* Free RX resources. */
   1001      1.1  augustss 	for (i = 0; i < UPL_RX_LIST_CNT; i++) {
   1002      1.1  augustss 		if (sc->sc_cdata.upl_rx_chain[i].upl_mbuf != NULL) {
   1003      1.1  augustss 			m_freem(sc->sc_cdata.upl_rx_chain[i].upl_mbuf);
   1004      1.1  augustss 			sc->sc_cdata.upl_rx_chain[i].upl_mbuf = NULL;
   1005      1.1  augustss 		}
   1006      1.1  augustss 		if (sc->sc_cdata.upl_rx_chain[i].upl_xfer != NULL) {
   1007      1.1  augustss 			usbd_free_xfer(sc->sc_cdata.upl_rx_chain[i].upl_xfer);
   1008      1.1  augustss 			sc->sc_cdata.upl_rx_chain[i].upl_xfer = NULL;
   1009      1.1  augustss 		}
   1010      1.1  augustss 	}
   1011      1.1  augustss 
   1012      1.1  augustss 	/* Free TX resources. */
   1013      1.1  augustss 	for (i = 0; i < UPL_TX_LIST_CNT; i++) {
   1014      1.1  augustss 		if (sc->sc_cdata.upl_tx_chain[i].upl_mbuf != NULL) {
   1015      1.1  augustss 			m_freem(sc->sc_cdata.upl_tx_chain[i].upl_mbuf);
   1016      1.1  augustss 			sc->sc_cdata.upl_tx_chain[i].upl_mbuf = NULL;
   1017      1.1  augustss 		}
   1018      1.1  augustss 		if (sc->sc_cdata.upl_tx_chain[i].upl_xfer != NULL) {
   1019      1.1  augustss 			usbd_free_xfer(sc->sc_cdata.upl_tx_chain[i].upl_xfer);
   1020      1.1  augustss 			sc->sc_cdata.upl_tx_chain[i].upl_xfer = NULL;
   1021      1.1  augustss 		}
   1022      1.1  augustss 	}
   1023      1.1  augustss 
   1024      1.1  augustss 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
   1025      1.1  augustss }
   1026      1.1  augustss 
   1027      1.1  augustss Static int
   1028  1.3.2.1   minoura upl_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
   1029  1.3.2.1   minoura 	   struct rtentry *rt0)
   1030      1.1  augustss {
   1031      1.1  augustss 	int s;
   1032      1.1  augustss 
   1033      1.1  augustss 	DPRINTFN(10,("%s: %s: enter\n",
   1034      1.1  augustss 		     USBDEVNAME(((struct upl_softc *)ifp->if_softc)->sc_dev),
   1035      1.1  augustss 		     __FUNCTION__));
   1036      1.1  augustss 
   1037      1.1  augustss 	s = splimp();
   1038      1.1  augustss 	/*
   1039      1.1  augustss 	 * Queue message on interface, and start output if interface
   1040      1.1  augustss 	 * not yet active.
   1041      1.1  augustss 	 */
   1042      1.1  augustss 	if (IF_QFULL(&ifp->if_snd)) {
   1043      1.1  augustss 		IF_DROP(&ifp->if_snd);
   1044      1.1  augustss 		splx(s);
   1045      1.1  augustss 		return (ENOBUFS);
   1046      1.1  augustss 	}
   1047      1.1  augustss 	ifp->if_obytes += m->m_pkthdr.len;
   1048      1.1  augustss 	IF_ENQUEUE(&ifp->if_snd, m);
   1049      1.1  augustss 	if ((ifp->if_flags & IFF_OACTIVE) == 0)
   1050      1.1  augustss 		(*ifp->if_start)(ifp);
   1051      1.1  augustss 	splx(s);
   1052      1.1  augustss 
   1053      1.1  augustss 	return (0);
   1054      1.1  augustss }
   1055      1.1  augustss 
   1056      1.1  augustss Static void
   1057  1.3.2.1   minoura upl_input(struct ifnet *ifp, struct mbuf *m)
   1058      1.1  augustss {
   1059      1.1  augustss 	struct ifqueue *inq;
   1060      1.1  augustss 	int s;
   1061      1.1  augustss 
   1062      1.1  augustss 	/* XXX Assume all traffic is IP */
   1063      1.1  augustss 
   1064      1.1  augustss 	schednetisr(NETISR_IP);
   1065      1.1  augustss 	inq = &ipintrq;
   1066      1.1  augustss 
   1067      1.1  augustss 	if (IF_QFULL(inq)) {
   1068      1.1  augustss 		IF_DROP(inq);
   1069      1.1  augustss 		splx(s);
   1070      1.1  augustss 		//if (sc->sc_flags & SC_DEBUG)
   1071      1.1  augustss 		//printf("%s: input queue full\n", ifp->if_xname);
   1072      1.1  augustss 		ifp->if_iqdrops++;
   1073      1.1  augustss 		return;
   1074      1.1  augustss 	}
   1075      1.1  augustss 	IF_ENQUEUE(inq, m);
   1076      1.1  augustss 	splx(s);
   1077      1.1  augustss 	ifp->if_ipackets++;
   1078      1.1  augustss 	ifp->if_ibytes += m->m_len;
   1079      1.1  augustss 	ifp->if_lastchange = time;
   1080      1.1  augustss }
   1081