LCOV - code coverage report
Current view: top level - dev/usb - if_kue.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 516 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*      $OpenBSD: if_kue.c,v 1.88 2017/04/08 02:57:25 deraadt Exp $ */
       2             : /*      $NetBSD: if_kue.c,v 1.50 2002/07/16 22:00:31 augustss Exp $     */
       3             : /*
       4             :  * Copyright (c) 1997, 1998, 1999, 2000
       5             :  *      Bill Paul <wpaul@ee.columbia.edu>.  All rights reserved.
       6             :  *
       7             :  * Redistribution and use in source and binary forms, with or without
       8             :  * modification, are permitted provided that the following conditions
       9             :  * are met:
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  * 2. Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in the
      14             :  *    documentation and/or other materials provided with the distribution.
      15             :  * 3. All advertising materials mentioning features or use of this software
      16             :  *    must display the following acknowledgement:
      17             :  *      This product includes software developed by Bill Paul.
      18             :  * 4. Neither the name of the author nor the names of any co-contributors
      19             :  *    may be used to endorse or promote products derived from this software
      20             :  *    without specific prior written permission.
      21             :  *
      22             :  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
      23             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      24             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      25             :  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
      26             :  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
      27             :  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
      28             :  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
      29             :  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
      30             :  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
      31             :  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
      32             :  * THE POSSIBILITY OF SUCH DAMAGE.
      33             :  *
      34             :  * $FreeBSD: src/sys/dev/usb/if_kue.c,v 1.14 2000/01/14 01:36:15 wpaul Exp $
      35             :  */
      36             : 
      37             : /*
      38             :  * Kawasaki LSI KL5KUSB101B USB to ethernet adapter driver.
      39             :  *
      40             :  * Written by Bill Paul <wpaul@ee.columbia.edu>
      41             :  * Electrical Engineering Department
      42             :  * Columbia University, New York City
      43             :  */
      44             : 
      45             : /*
      46             :  * The KLSI USB to ethernet adapter chip contains an USB serial interface,
      47             :  * ethernet MAC and embedded microcontroller (called the QT Engine).
      48             :  * The chip must have firmware loaded into it before it will operate.
      49             :  * Packets are passed between the chip and host via bulk transfers.
      50             :  * There is an interrupt endpoint mentioned in the software spec, however
      51             :  * it's currently unused. This device is 10Mbps half-duplex only, hence
      52             :  * there is no media selection logic. The MAC supports a 128 entry
      53             :  * multicast filter, though the exact size of the filter can depend
      54             :  * on the firmware. Curiously, while the software spec describes various
      55             :  * ethernet statistics counters, my sample adapter and firmware combination
      56             :  * claims not to support any statistics counters at all.
      57             :  *
      58             :  * Note that once we load the firmware in the device, we have to be
      59             :  * careful not to load it again: if you restart your computer but
      60             :  * leave the adapter attached to the USB controller, it may remain
      61             :  * powered on and retain its firmware. In this case, we don't need
      62             :  * to load the firmware a second time.
      63             :  *
      64             :  * Special thanks to Rob Furr for providing an ADS Technologies
      65             :  * adapter for development and testing. No monkeys were harmed during
      66             :  * the development of this driver.
      67             :  */
      68             : 
      69             : /*
      70             :  * Ported to NetBSD and somewhat rewritten by Lennart Augustsson.
      71             :  */
      72             : 
      73             : #include "bpfilter.h"
      74             : 
      75             : #include <sys/param.h>
      76             : #include <sys/systm.h>
      77             : #include <sys/sockio.h>
      78             : #include <sys/mbuf.h>
      79             : #include <sys/malloc.h>
      80             : #include <sys/kernel.h>
      81             : #include <sys/socket.h>
      82             : #include <sys/device.h>
      83             : 
      84             : #include <net/if.h>
      85             : 
      86             : #if NBPFILTER > 0
      87             : #include <net/bpf.h>
      88             : #endif
      89             : 
      90             : #include <netinet/in.h>
      91             : #include <netinet/if_ether.h>
      92             : 
      93             : #include <dev/usb/usb.h>
      94             : #include <dev/usb/usbdi.h>
      95             : #include <dev/usb/usbdi_util.h>
      96             : #include <dev/usb/usbdevs.h>
      97             : 
      98             : #include <dev/usb/if_kuereg.h>
      99             : #include <dev/usb/if_kuevar.h>
     100             : 
     101             : #ifdef KUE_DEBUG
     102             : #define DPRINTF(x)      do { if (kuedebug) printf x; } while (0)
     103             : #define DPRINTFN(n,x)   do { if (kuedebug >= (n)) printf x; } while (0)
     104             : int     kuedebug = 0;
     105             : #else
     106             : #define DPRINTF(x)
     107             : #define DPRINTFN(n,x)
     108             : #endif
     109             : 
     110             : /*
     111             :  * Various supported device vendors/products.
     112             :  */
     113             : const struct usb_devno kue_devs[] = {
     114             :         { USB_VENDOR_3COM, USB_PRODUCT_3COM_3C19250 },
     115             :         { USB_VENDOR_3COM, USB_PRODUCT_3COM_3C460 },
     116             :         { USB_VENDOR_ABOCOM, USB_PRODUCT_ABOCOM_URE450 },
     117             :         { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BT },
     118             :         { USB_VENDOR_ADS, USB_PRODUCT_ADS_UBS10BTX },
     119             :         { USB_VENDOR_AOX, USB_PRODUCT_AOX_USB101 },
     120             :         { USB_VENDOR_ASANTE, USB_PRODUCT_ASANTE_EA },
     121             :         { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_UC10T },
     122             :         { USB_VENDOR_ATEN, USB_PRODUCT_ATEN_DSB650C },
     123             :         { USB_VENDOR_COREGA, USB_PRODUCT_COREGA_ETHER_USB_T },
     124             :         { USB_VENDOR_DLINK, USB_PRODUCT_DLINK_DSB650C },
     125             :         { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_E45 },
     126             :         { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_XX1 },
     127             :         { USB_VENDOR_ENTREGA, USB_PRODUCT_ENTREGA_XX2 },
     128             :         { USB_VENDOR_IODATA, USB_PRODUCT_IODATA_USBETT },
     129             :         { USB_VENDOR_JATON, USB_PRODUCT_JATON_EDA },
     130             :         { USB_VENDOR_KINGSTON, USB_PRODUCT_KINGSTON_XX1 },
     131             :         { USB_VENDOR_KLSI, USB_PRODUCT_KLSI_DUH3E10BT },
     132             :         { USB_VENDOR_KLSI, USB_PRODUCT_KLSI_DUH3E10BTN },
     133             :         { USB_VENDOR_LINKSYS, USB_PRODUCT_LINKSYS_USB10T },
     134             :         { USB_VENDOR_MOBILITY, USB_PRODUCT_MOBILITY_EA },
     135             :         { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101 },
     136             :         { USB_VENDOR_NETGEAR, USB_PRODUCT_NETGEAR_EA101X },
     137             :         { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET },
     138             :         { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET2 },
     139             :         { USB_VENDOR_PERACOM, USB_PRODUCT_PERACOM_ENET3 },
     140             :         { USB_VENDOR_PORTGEAR, USB_PRODUCT_PORTGEAR_EA8 },
     141             :         { USB_VENDOR_PORTGEAR, USB_PRODUCT_PORTGEAR_EA9 },
     142             :         { USB_VENDOR_PORTSMITH, USB_PRODUCT_PORTSMITH_EEA },
     143             :         { USB_VENDOR_SHARK, USB_PRODUCT_SHARK_PA },
     144             :         { USB_VENDOR_SILICOM, USB_PRODUCT_SILICOM_U2E },
     145             :         { USB_VENDOR_SILICOM, USB_PRODUCT_SILICOM_GPE },
     146             :         { USB_VENDOR_SMC, USB_PRODUCT_SMC_2102USB },
     147             : };
     148             : 
     149             : int kue_match(struct device *, void *, void *);
     150             : void kue_attach(struct device *, struct device *, void *);
     151             : int kue_detach(struct device *, int);
     152             : 
     153             : struct cfdriver kue_cd = {
     154             :         NULL, "kue", DV_IFNET
     155             : };
     156             : 
     157             : const struct cfattach kue_ca = {
     158             :         sizeof(struct kue_softc), kue_match, kue_attach, kue_detach
     159             : };
     160             : 
     161             : int kue_tx_list_init(struct kue_softc *);
     162             : int kue_rx_list_init(struct kue_softc *);
     163             : int kue_newbuf(struct kue_softc *, struct kue_chain *,struct mbuf *);
     164             : int kue_send(struct kue_softc *, struct mbuf *, int);
     165             : int kue_open_pipes(struct kue_softc *);
     166             : void kue_rxeof(struct usbd_xfer *, void *, usbd_status);
     167             : void kue_txeof(struct usbd_xfer *, void *, usbd_status);
     168             : void kue_start(struct ifnet *);
     169             : int kue_ioctl(struct ifnet *, u_long, caddr_t);
     170             : void kue_init(void *);
     171             : void kue_stop(struct kue_softc *);
     172             : void kue_watchdog(struct ifnet *);
     173             : 
     174             : void kue_setmulti(struct kue_softc *);
     175             : void kue_reset(struct kue_softc *);
     176             : 
     177             : usbd_status kue_ctl(struct kue_softc *, int, u_int8_t,
     178             :                            u_int16_t, void *, u_int32_t);
     179             : usbd_status kue_setword(struct kue_softc *, u_int8_t, u_int16_t);
     180             : int kue_load_fw(struct kue_softc *);
     181             : void kue_attachhook(struct device *);
     182             : 
     183             : usbd_status
     184           0 : kue_setword(struct kue_softc *sc, u_int8_t breq, u_int16_t word)
     185             : {
     186           0 :         usb_device_request_t    req;
     187             : 
     188             :         DPRINTFN(10,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
     189             : 
     190           0 :         req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
     191           0 :         req.bRequest = breq;
     192           0 :         USETW(req.wValue, word);
     193           0 :         USETW(req.wIndex, 0);
     194           0 :         USETW(req.wLength, 0);
     195             : 
     196           0 :         return (usbd_do_request(sc->kue_udev, &req, NULL));
     197           0 : }
     198             : 
     199             : usbd_status
     200           0 : kue_ctl(struct kue_softc *sc, int rw, u_int8_t breq, u_int16_t val,
     201             :         void *data, u_int32_t len)
     202             : {
     203           0 :         usb_device_request_t    req;
     204             : 
     205             :         DPRINTFN(10,("%s: %s: enter, len=%d\n", sc->kue_dev.dv_xname,
     206             :                      __func__, len));
     207             : 
     208           0 :         if (rw == KUE_CTL_WRITE)
     209           0 :                 req.bmRequestType = UT_WRITE_VENDOR_DEVICE;
     210             :         else
     211           0 :                 req.bmRequestType = UT_READ_VENDOR_DEVICE;
     212             : 
     213           0 :         req.bRequest = breq;
     214           0 :         USETW(req.wValue, val);
     215           0 :         USETW(req.wIndex, 0);
     216           0 :         USETW(req.wLength, len);
     217             : 
     218           0 :         return (usbd_do_request(sc->kue_udev, &req, data));
     219           0 : }
     220             : 
     221             : int
     222           0 : kue_load_fw(struct kue_softc *sc)
     223             : {
     224             :         usb_device_descriptor_t *dd;
     225             :         usbd_status             err;
     226             :         struct kue_firmware     *fw;
     227           0 :         u_char                  *buf;
     228           0 :         size_t                  buflen;
     229             : 
     230             :         DPRINTFN(1,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));
     231             : 
     232             :         /*
     233             :          * First, check if we even need to load the firmware.
     234             :          * If the device was still attached when the system was
     235             :          * rebooted, it may already have firmware loaded in it.
     236             :          * If this is the case, we don't need to do it again.
     237             :          * And in fact, if we try to load it again, we'll hang,
     238             :          * so we have to avoid this condition if we don't want
     239             :          * to look stupid.
     240             :          *
     241             :          * We can test this quickly by checking the bcdRevision
     242             :          * code. The NIC will return a different revision code if
     243             :          * it's probed while the firmware is still loaded and
     244             :          * running.
     245             :          */
     246           0 :         if ((dd = usbd_get_device_descriptor(sc->kue_udev)) == NULL)
     247           0 :                 return (EIO);
     248           0 :         if (UGETW(dd->bcdDevice) >= KUE_WARM_REV) {
     249           0 :                 printf("%s: warm boot, no firmware download\n",
     250           0 :                        sc->kue_dev.dv_xname);
     251           0 :                 return (0);
     252             :         }
     253             : 
     254           0 :         err = loadfirmware("kue", &buf, &buflen);
     255           0 :         if (err) {
     256           0 :                 printf("%s: failed loadfirmware of file %s: errno %d\n",
     257           0 :                     sc->kue_dev.dv_xname, "kue", err);
     258           0 :                 return (err);
     259             :         }
     260           0 :         fw = (struct kue_firmware *)buf;
     261             : 
     262           0 :         printf("%s: cold boot, downloading firmware\n",
     263           0 :                sc->kue_dev.dv_xname);
     264             : 
     265             :         /* Load code segment */
     266             :         DPRINTFN(1,("%s: kue_load_fw: download code_seg\n",
     267             :                     sc->kue_dev.dv_xname));
     268           0 :         err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
     269           0 :             0, (void *)&fw->data[0], ntohl(fw->codeseglen));
     270           0 :         if (err) {
     271           0 :                 printf("%s: failed to load code segment: %s\n",
     272           0 :                     sc->kue_dev.dv_xname, usbd_errstr(err));
     273           0 :                 free(buf, M_DEVBUF, buflen);
     274           0 :                 return (EIO);
     275             :         }
     276             : 
     277             :         /* Load fixup segment */
     278             :         DPRINTFN(1,("%s: kue_load_fw: download fix_seg\n",
     279             :                     sc->kue_dev.dv_xname));
     280           0 :         err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
     281           0 :             0, (void *)&fw->data[ntohl(fw->codeseglen)], ntohl(fw->fixseglen));
     282           0 :         if (err) {
     283           0 :                 printf("%s: failed to load fixup segment: %s\n",
     284           0 :                     sc->kue_dev.dv_xname, usbd_errstr(err));
     285           0 :                 free(buf, M_DEVBUF, buflen);
     286           0 :                 return (EIO);
     287             :         }
     288             : 
     289             :         /* Send trigger command. */
     290             :         DPRINTFN(1,("%s: kue_load_fw: download trig_seg\n",
     291             :                     sc->kue_dev.dv_xname));
     292           0 :         err = kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SEND_SCAN,
     293           0 :             0, (void *)&fw->data[ntohl(fw->codeseglen) + ntohl(fw->fixseglen)],
     294           0 :             ntohl(fw->trigseglen));
     295           0 :         if (err) {
     296           0 :                 printf("%s: failed to load trigger segment: %s\n",
     297           0 :                     sc->kue_dev.dv_xname, usbd_errstr(err));
     298           0 :                 free(buf, M_DEVBUF, buflen);
     299           0 :                 return (EIO);
     300             :         }
     301           0 :         free(buf, M_DEVBUF, buflen);
     302             : 
     303           0 :         usbd_delay_ms(sc->kue_udev, 10);
     304             : 
     305             :         /*
     306             :          * Reload device descriptor.
     307             :          * Why? The chip without the firmware loaded returns
     308             :          * one revision code. The chip with the firmware
     309             :          * loaded and running returns a *different* revision
     310             :          * code. This confuses the quirk mechanism, which is
     311             :          * dependent on the revision data.
     312             :          */
     313           0 :         (void)usbd_reload_device_desc(sc->kue_udev);
     314             : 
     315             :         DPRINTFN(1,("%s: %s: done\n", sc->kue_dev.dv_xname, __func__));
     316             : 
     317             :         /* Reset the adapter. */
     318           0 :         kue_reset(sc);
     319             : 
     320           0 :         return (0);
     321           0 : }
     322             : 
     323             : void
     324           0 : kue_setmulti(struct kue_softc *sc)
     325             : {
     326           0 :         struct arpcom           *ac = &sc->arpcom;
     327           0 :         struct ifnet            *ifp = GET_IFP(sc);
     328             :         struct ether_multi      *enm;
     329             :         struct ether_multistep  step;
     330             :         int                     i;
     331             : 
     332             :         DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));
     333             : 
     334           0 :         if (ifp->if_flags & IFF_PROMISC || ac->ac_multirangecnt > 0) {
     335             : allmulti:
     336           0 :                 ifp->if_flags |= IFF_ALLMULTI;
     337           0 :                 sc->kue_rxfilt |= KUE_RXFILT_ALLMULTI;
     338           0 :                 sc->kue_rxfilt &= ~KUE_RXFILT_MULTICAST;
     339           0 :                 kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt);
     340           0 :                 return;
     341             :         }
     342             : 
     343           0 :         sc->kue_rxfilt &= ~KUE_RXFILT_ALLMULTI;
     344             : 
     345             :         i = 0;
     346           0 :         ETHER_FIRST_MULTI(step, ac, enm);
     347           0 :         while (enm != NULL) {
     348           0 :                 if (i == KUE_MCFILTCNT(sc))
     349             :                         goto allmulti;
     350             : 
     351           0 :                 memcpy(KUE_MCFILT(sc, i), enm->enm_addrlo, ETHER_ADDR_LEN);
     352           0 :                 ETHER_NEXT_MULTI(step, enm);
     353           0 :                 i++;
     354             :         }
     355             : 
     356           0 :         ifp->if_flags &= ~IFF_ALLMULTI;
     357             : 
     358           0 :         sc->kue_rxfilt |= KUE_RXFILT_MULTICAST;
     359           0 :         kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MCAST_FILTERS,
     360           0 :             i, sc->kue_mcfilters, i * ETHER_ADDR_LEN);
     361             : 
     362           0 :         kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt);
     363           0 : }
     364             : 
     365             : /*
     366             :  * Issue a SET_CONFIGURATION command to reset the MAC. This should be
     367             :  * done after the firmware is loaded into the adapter in order to
     368             :  * bring it into proper operation.
     369             :  */
     370             : void
     371           0 : kue_reset(struct kue_softc *sc)
     372             : {
     373             :         DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));
     374             : 
     375           0 :         if (usbd_set_config_no(sc->kue_udev, KUE_CONFIG_NO, 1) ||
     376           0 :             usbd_device2interface_handle(sc->kue_udev, KUE_IFACE_IDX,
     377           0 :                                          &sc->kue_iface))
     378           0 :                 printf("%s: reset failed\n", sc->kue_dev.dv_xname);
     379             : 
     380             :         /* Wait a little while for the chip to get its brains in order. */
     381           0 :         usbd_delay_ms(sc->kue_udev, 10);
     382           0 : }
     383             : 
     384             : /*
     385             :  * Probe for a KLSI chip.
     386             :  */
     387             : int
     388           0 : kue_match(struct device *parent, void *match, void *aux)
     389             : {
     390           0 :         struct usb_attach_arg   *uaa = aux;
     391             : 
     392             :         DPRINTFN(25,("kue_match: enter\n"));
     393             : 
     394           0 :         if (uaa->iface != NULL)
     395           0 :                 return (UMATCH_NONE);
     396             : 
     397           0 :         return (usb_lookup(kue_devs, uaa->vendor, uaa->product) != NULL ?
     398             :             UMATCH_VENDOR_PRODUCT : UMATCH_NONE);
     399           0 : }
     400             : 
     401             : void
     402           0 : kue_attachhook(struct device *self)
     403             : {
     404           0 :         struct kue_softc        *sc = (struct kue_softc *)self;
     405             :         int                     s;
     406             :         struct ifnet            *ifp;
     407           0 :         struct usbd_device      *dev = sc->kue_udev;
     408           0 :         struct usbd_interface   *iface;
     409             :         usbd_status             err;
     410             :         usb_interface_descriptor_t      *id;
     411             :         usb_endpoint_descriptor_t       *ed;
     412             :         int                     i;
     413             : 
     414             :         /* Load the firmware into the NIC. */
     415           0 :         if (kue_load_fw(sc)) {
     416           0 :                 printf("%s: loading firmware failed\n",
     417           0 :                     sc->kue_dev.dv_xname);
     418           0 :                 return;
     419             :         }
     420             : 
     421           0 :         err = usbd_device2interface_handle(dev, KUE_IFACE_IDX, &iface);
     422           0 :         if (err) {
     423           0 :                 printf("%s: getting interface handle failed\n",
     424           0 :                     sc->kue_dev.dv_xname);
     425           0 :                 return;
     426             :         }
     427             : 
     428           0 :         sc->kue_iface = iface;
     429           0 :         id = usbd_get_interface_descriptor(iface);
     430             : 
     431             :         /* Find endpoints. */
     432           0 :         for (i = 0; i < id->bNumEndpoints; i++) {
     433           0 :                 ed = usbd_interface2endpoint_descriptor(iface, i);
     434           0 :                 if (ed == NULL) {
     435           0 :                         printf("%s: couldn't get ep %d\n",
     436           0 :                             sc->kue_dev.dv_xname, i);
     437           0 :                         return;
     438             :                 }
     439           0 :                 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
     440           0 :                     UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
     441           0 :                         sc->kue_ed[KUE_ENDPT_RX] = ed->bEndpointAddress;
     442           0 :                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
     443           0 :                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
     444           0 :                         sc->kue_ed[KUE_ENDPT_TX] = ed->bEndpointAddress;
     445           0 :                 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
     446           0 :                            UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT) {
     447           0 :                         sc->kue_ed[KUE_ENDPT_INTR] = ed->bEndpointAddress;
     448           0 :                 }
     449             :         }
     450             : 
     451           0 :         if (sc->kue_ed[KUE_ENDPT_RX] == 0 || sc->kue_ed[KUE_ENDPT_TX] == 0) {
     452           0 :                 printf("%s: missing endpoint\n", sc->kue_dev.dv_xname);
     453           0 :                 return;
     454             :         }
     455             : 
     456             :         /* Read ethernet descriptor */
     457           0 :         err = kue_ctl(sc, KUE_CTL_READ, KUE_CMD_GET_ETHER_DESCRIPTOR,
     458           0 :             0, &sc->kue_desc, sizeof(sc->kue_desc));
     459           0 :         if (err) {
     460           0 :                 printf("%s: could not read Ethernet descriptor\n",
     461           0 :                     sc->kue_dev.dv_xname);
     462           0 :                 return;
     463             :         }
     464             : 
     465           0 :         sc->kue_mcfilters = mallocarray(KUE_MCFILTCNT(sc), ETHER_ADDR_LEN,
     466             :             M_USBDEV, M_NOWAIT);
     467           0 :         if (sc->kue_mcfilters == NULL) {
     468           0 :                 printf("%s: no memory for multicast filter buffer\n",
     469           0 :                     sc->kue_dev.dv_xname);
     470           0 :                 return;
     471             :         }
     472           0 :         sc->kue_mcfilterslen = KUE_MCFILTCNT(sc);
     473             : 
     474           0 :         s = splnet();
     475             : 
     476             :         /*
     477             :          * A KLSI chip was detected. Inform the world.
     478             :          */
     479           0 :         printf("%s: address %s\n", sc->kue_dev.dv_xname,
     480           0 :             ether_sprintf(sc->kue_desc.kue_macaddr));
     481             : 
     482           0 :         bcopy(sc->kue_desc.kue_macaddr,
     483           0 :             (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
     484             : 
     485             :         /* Initialize interface info.*/
     486           0 :         ifp = GET_IFP(sc);
     487           0 :         ifp->if_softc = sc;
     488           0 :         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     489           0 :         ifp->if_ioctl = kue_ioctl;
     490           0 :         ifp->if_start = kue_start;
     491           0 :         ifp->if_watchdog = kue_watchdog;
     492           0 :         strlcpy(ifp->if_xname, sc->kue_dev.dv_xname, IFNAMSIZ);
     493             : 
     494             :         /* Attach the interface. */
     495           0 :         if_attach(ifp);
     496           0 :         ether_ifattach(ifp);
     497             : 
     498           0 :         sc->kue_attached = 1;
     499           0 :         splx(s);
     500             : 
     501           0 : }
     502             : 
     503             : /*
     504             :  * Attach the interface. Allocate softc structures, do
     505             :  * setup and ethernet/BPF attach.
     506             :  */
     507             : void
     508           0 : kue_attach(struct device *parent, struct device *self, void *aux)
     509             : {
     510           0 :         struct kue_softc        *sc = (struct kue_softc *)self;
     511           0 :         struct usb_attach_arg   *uaa = aux;
     512           0 :         struct usbd_device      *dev = uaa->device;
     513             :         usbd_status             err;
     514             : 
     515             :         DPRINTFN(5,(" : kue_attach: sc=%p, dev=%p", sc, dev));
     516             : 
     517           0 :         err = usbd_set_config_no(dev, KUE_CONFIG_NO, 1);
     518           0 :         if (err) {
     519           0 :                 printf("%s: setting config no failed\n",
     520           0 :                     sc->kue_dev.dv_xname);
     521           0 :                 return;
     522             :         }
     523             : 
     524           0 :         sc->kue_udev = dev;
     525           0 :         sc->kue_product = uaa->product;
     526           0 :         sc->kue_vendor = uaa->vendor;
     527             : 
     528           0 :         config_mountroot(self, kue_attachhook);
     529           0 : }
     530             : 
     531             : int
     532           0 : kue_detach(struct device *self, int flags)
     533             : {
     534           0 :         struct kue_softc        *sc = (struct kue_softc *)self;
     535           0 :         struct ifnet            *ifp = GET_IFP(sc);
     536             :         int                     s;
     537             : 
     538             :         /* Detached before attached finished, so just bail out. */
     539           0 :         if (!sc->kue_attached)
     540           0 :                 return (0);
     541             : 
     542           0 :         s = splusb();           /* XXX why? */
     543             : 
     544           0 :         if (sc->kue_mcfilters != NULL) {
     545           0 :                 free(sc->kue_mcfilters, M_USBDEV, sc->kue_mcfilterslen);
     546           0 :                 sc->kue_mcfilters = NULL;
     547           0 :         }
     548             : 
     549           0 :         if (ifp->if_flags & IFF_RUNNING)
     550           0 :                 kue_stop(sc);
     551             : 
     552           0 :         if (ifp->if_softc != NULL) {
     553           0 :                 ether_ifdetach(ifp);
     554           0 :                 if_detach(ifp);
     555           0 :         }
     556             : 
     557             : #ifdef DIAGNOSTIC
     558           0 :         if (sc->kue_ep[KUE_ENDPT_TX] != NULL ||
     559           0 :             sc->kue_ep[KUE_ENDPT_RX] != NULL ||
     560           0 :             sc->kue_ep[KUE_ENDPT_INTR] != NULL)
     561           0 :                 printf("%s: detach has active endpoints\n",
     562           0 :                        sc->kue_dev.dv_xname);
     563             : #endif
     564             : 
     565           0 :         sc->kue_attached = 0;
     566           0 :         splx(s);
     567             : 
     568           0 :         return (0);
     569           0 : }
     570             : 
     571             : /*
     572             :  * Initialize an RX descriptor and attach an MBUF cluster.
     573             :  */
     574             : int
     575           0 : kue_newbuf(struct kue_softc *sc, struct kue_chain *c, struct mbuf *m)
     576             : {
     577             :         struct mbuf             *m_new = NULL;
     578             : 
     579             :         DPRINTFN(10,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
     580             : 
     581           0 :         if (m == NULL) {
     582           0 :                 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
     583           0 :                 if (m_new == NULL) {
     584           0 :                         printf("%s: no memory for rx list "
     585           0 :                             "-- packet dropped!\n", sc->kue_dev.dv_xname);
     586           0 :                         return (ENOBUFS);
     587             :                 }
     588             : 
     589           0 :                 MCLGET(m_new, M_DONTWAIT);
     590           0 :                 if (!(m_new->m_flags & M_EXT)) {
     591           0 :                         printf("%s: no memory for rx list "
     592           0 :                             "-- packet dropped!\n", sc->kue_dev.dv_xname);
     593           0 :                         m_freem(m_new);
     594           0 :                         return (ENOBUFS);
     595             :                 }
     596           0 :                 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
     597           0 :         } else {
     598             :                 m_new = m;
     599           0 :                 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
     600           0 :                 m_new->m_data = m_new->m_ext.ext_buf;
     601             :         }
     602             : 
     603           0 :         c->kue_mbuf = m_new;
     604             : 
     605           0 :         return (0);
     606           0 : }
     607             : 
     608             : int
     609           0 : kue_rx_list_init(struct kue_softc *sc)
     610             : {
     611             :         struct kue_cdata        *cd;
     612             :         struct kue_chain        *c;
     613             :         int                     i;
     614             : 
     615             :         DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));
     616             : 
     617           0 :         cd = &sc->kue_cdata;
     618           0 :         for (i = 0; i < KUE_RX_LIST_CNT; i++) {
     619           0 :                 c = &cd->kue_rx_chain[i];
     620           0 :                 c->kue_sc = sc;
     621           0 :                 c->kue_idx = i;
     622           0 :                 if (kue_newbuf(sc, c, NULL) == ENOBUFS)
     623           0 :                         return (ENOBUFS);
     624           0 :                 if (c->kue_xfer == NULL) {
     625           0 :                         c->kue_xfer = usbd_alloc_xfer(sc->kue_udev);
     626           0 :                         if (c->kue_xfer == NULL)
     627           0 :                                 return (ENOBUFS);
     628           0 :                         c->kue_buf = usbd_alloc_buffer(c->kue_xfer, KUE_BUFSZ);
     629           0 :                         if (c->kue_buf == NULL)
     630           0 :                                 return (ENOBUFS); /* XXX free xfer */
     631             :                 }
     632             :         }
     633             : 
     634           0 :         return (0);
     635           0 : }
     636             : 
     637             : int
     638           0 : kue_tx_list_init(struct kue_softc *sc)
     639             : {
     640             :         struct kue_cdata        *cd;
     641             :         struct kue_chain        *c;
     642             :         int                     i;
     643             : 
     644             :         DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname, __func__));
     645             : 
     646           0 :         cd = &sc->kue_cdata;
     647           0 :         for (i = 0; i < KUE_TX_LIST_CNT; i++) {
     648           0 :                 c = &cd->kue_tx_chain[i];
     649           0 :                 c->kue_sc = sc;
     650           0 :                 c->kue_idx = i;
     651           0 :                 c->kue_mbuf = NULL;
     652           0 :                 if (c->kue_xfer == NULL) {
     653           0 :                         c->kue_xfer = usbd_alloc_xfer(sc->kue_udev);
     654           0 :                         if (c->kue_xfer == NULL)
     655           0 :                                 return (ENOBUFS);
     656           0 :                         c->kue_buf = usbd_alloc_buffer(c->kue_xfer, KUE_BUFSZ);
     657           0 :                         if (c->kue_buf == NULL)
     658           0 :                                 return (ENOBUFS);
     659             :                 }
     660             :         }
     661             : 
     662           0 :         return (0);
     663           0 : }
     664             : 
     665             : /*
     666             :  * A frame has been uploaded: pass the resulting mbuf chain up to
     667             :  * the higher level protocols.
     668             :  */
     669             : void
     670           0 : kue_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
     671             : {
     672           0 :         struct kue_chain        *c = priv;
     673           0 :         struct kue_softc        *sc = c->kue_sc;
     674           0 :         struct ifnet            *ifp = GET_IFP(sc);
     675           0 :         struct mbuf_list        ml = MBUF_LIST_INITIALIZER();
     676             :         struct mbuf             *m;
     677           0 :         int                     total_len = 0;
     678             :         int                     s;
     679             : 
     680             :         DPRINTFN(10,("%s: %s: enter status=%d\n", sc->kue_dev.dv_xname,
     681             :                      __func__, status));
     682             : 
     683           0 :         if (usbd_is_dying(sc->kue_udev))
     684           0 :                 return;
     685             : 
     686           0 :         if (!(ifp->if_flags & IFF_RUNNING))
     687           0 :                 return;
     688             : 
     689           0 :         if (status != USBD_NORMAL_COMPLETION) {
     690           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
     691           0 :                         return;
     692           0 :                 sc->kue_rx_errs++;
     693           0 :                 if (usbd_ratecheck(&sc->kue_rx_notice)) {
     694           0 :                         printf("%s: %u usb errors on rx: %s\n",
     695           0 :                             sc->kue_dev.dv_xname, sc->kue_rx_errs,
     696           0 :                             usbd_errstr(status));
     697           0 :                         sc->kue_rx_errs = 0;
     698           0 :                 }
     699           0 :                 if (status == USBD_STALLED)
     700           0 :                         usbd_clear_endpoint_stall_async(sc->kue_ep[KUE_ENDPT_RX]);
     701             :                 goto done;
     702             :         }
     703             : 
     704           0 :         usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);
     705             : 
     706             :         DPRINTFN(10,("%s: %s: total_len=%d len=%d\n", sc->kue_dev.dv_xname,
     707             :                      __func__, total_len,
     708             :                      UGETW(mtod(c->kue_mbuf, u_int8_t *))));
     709             : 
     710           0 :         if (total_len <= 1)
     711             :                 goto done;
     712             : 
     713           0 :         m = c->kue_mbuf;
     714             :         /* copy data to mbuf */
     715           0 :         memcpy(mtod(m, char *), c->kue_buf, total_len);
     716             : 
     717             :         /* No errors; receive the packet. */
     718           0 :         total_len = UGETW(mtod(m, u_int8_t *));
     719           0 :         m_adj(m, sizeof(u_int16_t));
     720             : 
     721           0 :         if (total_len < sizeof(struct ether_header)) {
     722           0 :                 ifp->if_ierrors++;
     723           0 :                 goto done;
     724             :         }
     725             : 
     726           0 :         m->m_pkthdr.len = m->m_len = total_len;
     727           0 :         ml_enqueue(&ml, m);
     728             : 
     729           0 :         if (kue_newbuf(sc, c, NULL) == ENOBUFS) {
     730           0 :                 ifp->if_ierrors++;
     731           0 :                 goto done;
     732             :         }
     733             : 
     734           0 :         s = splnet();
     735           0 :         if_input(ifp, &ml);
     736           0 :         splx(s);
     737             : 
     738             :  done:
     739             : 
     740             :         /* Setup new transfer. */
     741           0 :         usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX],
     742           0 :             c, c->kue_buf, KUE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
     743             :             USBD_NO_TIMEOUT, kue_rxeof);
     744           0 :         usbd_transfer(c->kue_xfer);
     745             : 
     746             :         DPRINTFN(10,("%s: %s: start rx\n", sc->kue_dev.dv_xname,
     747             :                     __func__));
     748           0 : }
     749             : 
     750             : /*
     751             :  * A frame was downloaded to the chip. It's safe for us to clean up
     752             :  * the list buffers.
     753             :  */
     754             : 
     755             : void
     756           0 : kue_txeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
     757             : {
     758           0 :         struct kue_chain        *c = priv;
     759           0 :         struct kue_softc        *sc = c->kue_sc;
     760           0 :         struct ifnet            *ifp = GET_IFP(sc);
     761             :         int                     s;
     762             : 
     763           0 :         if (usbd_is_dying(sc->kue_udev))
     764           0 :                 return;
     765             : 
     766           0 :         s = splnet();
     767             : 
     768             :         DPRINTFN(10,("%s: %s: enter status=%d\n", sc->kue_dev.dv_xname,
     769             :                     __func__, status));
     770             : 
     771           0 :         ifp->if_timer = 0;
     772           0 :         ifq_clr_oactive(&ifp->if_snd);
     773             : 
     774           0 :         if (status != USBD_NORMAL_COMPLETION) {
     775           0 :                 if (status == USBD_NOT_STARTED || status == USBD_CANCELLED) {
     776           0 :                         splx(s);
     777           0 :                         return;
     778             :                 }
     779           0 :                 ifp->if_oerrors++;
     780           0 :                 printf("%s: usb error on tx: %s\n", sc->kue_dev.dv_xname,
     781           0 :                     usbd_errstr(status));
     782           0 :                 if (status == USBD_STALLED)
     783           0 :                         usbd_clear_endpoint_stall_async(sc->kue_ep[KUE_ENDPT_TX]);
     784           0 :                 splx(s);
     785           0 :                 return;
     786             :         }
     787             : 
     788           0 :         m_freem(c->kue_mbuf);
     789           0 :         c->kue_mbuf = NULL;
     790             : 
     791           0 :         if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
     792           0 :                 kue_start(ifp);
     793             : 
     794           0 :         splx(s);
     795           0 : }
     796             : 
     797             : int
     798           0 : kue_send(struct kue_softc *sc, struct mbuf *m, int idx)
     799             : {
     800             :         int                     total_len;
     801             :         struct kue_chain        *c;
     802             :         usbd_status             err;
     803             : 
     804             :         DPRINTFN(10,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
     805             : 
     806           0 :         c = &sc->kue_cdata.kue_tx_chain[idx];
     807             : 
     808             :         /*
     809             :          * Copy the mbuf data into a contiguous buffer, leaving two
     810             :          * bytes at the beginning to hold the frame length.
     811             :          */
     812           0 :         m_copydata(m, 0, m->m_pkthdr.len, c->kue_buf + 2);
     813           0 :         c->kue_mbuf = m;
     814             : 
     815           0 :         total_len = m->m_pkthdr.len + 2;
     816             :         /* XXX what's this? */
     817           0 :         total_len += 64 - (total_len % 64);
     818             : 
     819             :         /* Frame length is specified in the first 2 bytes of the buffer. */
     820           0 :         c->kue_buf[0] = (u_int8_t)m->m_pkthdr.len;
     821           0 :         c->kue_buf[1] = (u_int8_t)(m->m_pkthdr.len >> 8);
     822             : 
     823           0 :         usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_TX],
     824           0 :             c, c->kue_buf, total_len, USBD_NO_COPY, USBD_DEFAULT_TIMEOUT,
     825             :             kue_txeof);
     826             : 
     827             :         /* Transmit */
     828           0 :         err = usbd_transfer(c->kue_xfer);
     829           0 :         if (err != USBD_IN_PROGRESS) {
     830           0 :                 printf("%s: kue_send error=%s\n", sc->kue_dev.dv_xname,
     831           0 :                        usbd_errstr(err));
     832           0 :                 kue_stop(sc);
     833           0 :                 return (EIO);
     834             :         }
     835             : 
     836           0 :         sc->kue_cdata.kue_tx_cnt++;
     837             : 
     838           0 :         return (0);
     839           0 : }
     840             : 
     841             : void
     842           0 : kue_start(struct ifnet *ifp)
     843             : {
     844           0 :         struct kue_softc        *sc = ifp->if_softc;
     845             :         struct mbuf             *m_head = NULL;
     846             : 
     847             :         DPRINTFN(10,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
     848             : 
     849           0 :         if (usbd_is_dying(sc->kue_udev))
     850           0 :                 return;
     851             : 
     852           0 :         if (ifq_is_oactive(&ifp->if_snd))
     853           0 :                 return;
     854             : 
     855           0 :         m_head = ifq_deq_begin(&ifp->if_snd);
     856           0 :         if (m_head == NULL)
     857           0 :                 return;
     858             : 
     859           0 :         if (kue_send(sc, m_head, 0)) {
     860           0 :                 ifq_deq_rollback(&ifp->if_snd, m_head);
     861           0 :                 ifq_set_oactive(&ifp->if_snd);
     862           0 :                 return;
     863             :         }
     864             : 
     865           0 :         ifq_deq_commit(&ifp->if_snd, m_head);
     866             : 
     867             : #if NBPFILTER > 0
     868             :         /*
     869             :          * If there's a BPF listener, bounce a copy of this frame
     870             :          * to him.
     871             :          */
     872           0 :         if (ifp->if_bpf)
     873           0 :                 bpf_mtap(ifp->if_bpf, m_head, BPF_DIRECTION_OUT);
     874             : #endif
     875             : 
     876           0 :         ifq_set_oactive(&ifp->if_snd);
     877             : 
     878             :         /*
     879             :          * Set a timeout in case the chip goes out to lunch.
     880             :          */
     881           0 :         ifp->if_timer = 6;
     882           0 : }
     883             : 
     884             : void
     885           0 : kue_init(void *xsc)
     886             : {
     887           0 :         struct kue_softc        *sc = xsc;
     888           0 :         struct ifnet            *ifp = GET_IFP(sc);
     889             :         int                     s;
     890             :         u_char                  *eaddr;
     891             : 
     892             :         DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
     893             : 
     894           0 :         if (ifp->if_flags & IFF_RUNNING)
     895           0 :                 return;
     896             : 
     897           0 :         s = splnet();
     898             : 
     899           0 :         eaddr = sc->arpcom.ac_enaddr;
     900             :         /* Set MAC address */
     901           0 :         kue_ctl(sc, KUE_CTL_WRITE, KUE_CMD_SET_MAC, 0, eaddr, ETHER_ADDR_LEN);
     902             : 
     903           0 :         sc->kue_rxfilt = KUE_RXFILT_UNICAST | KUE_RXFILT_BROADCAST;
     904             : 
     905             :          /* If we want promiscuous mode, set the allframes bit. */
     906           0 :         if (ifp->if_flags & IFF_PROMISC)
     907           0 :                 sc->kue_rxfilt |= KUE_RXFILT_PROMISC;
     908             : 
     909           0 :         kue_setword(sc, KUE_CMD_SET_PKT_FILTER, sc->kue_rxfilt);
     910             : 
     911             :         /* I'm not sure how to tune these. */
     912             : #if 0
     913             :         /*
     914             :          * Leave this one alone for now; setting it
     915             :          * wrong causes lockups on some machines/controllers.
     916             :          */
     917             :         kue_setword(sc, KUE_CMD_SET_SOFS, 1);
     918             : #endif
     919           0 :         kue_setword(sc, KUE_CMD_SET_URB_SIZE, 64);
     920             : 
     921             :         /* Init TX ring. */
     922           0 :         if (kue_tx_list_init(sc) == ENOBUFS) {
     923           0 :                 printf("%s: tx list init failed\n", sc->kue_dev.dv_xname);
     924           0 :                 splx(s);
     925           0 :                 return;
     926             :         }
     927             : 
     928             :         /* Init RX ring. */
     929           0 :         if (kue_rx_list_init(sc) == ENOBUFS) {
     930           0 :                 printf("%s: rx list init failed\n", sc->kue_dev.dv_xname);
     931           0 :                 splx(s);
     932           0 :                 return;
     933             :         }
     934             : 
     935             :         /* Load the multicast filter. */
     936           0 :         kue_setmulti(sc);
     937             : 
     938           0 :         if (sc->kue_ep[KUE_ENDPT_RX] == NULL) {
     939           0 :                 if (kue_open_pipes(sc)) {
     940           0 :                         splx(s);
     941           0 :                         return;
     942             :                 }
     943             :         }
     944             : 
     945           0 :         ifp->if_flags |= IFF_RUNNING;
     946           0 :         ifq_clr_oactive(&ifp->if_snd);
     947             : 
     948           0 :         splx(s);
     949           0 : }
     950             : 
     951             : int
     952           0 : kue_open_pipes(struct kue_softc *sc)
     953             : {
     954             :         usbd_status             err;
     955             :         struct kue_chain        *c;
     956             :         int                     i;
     957             : 
     958             :         DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
     959             : 
     960             :         /* Open RX and TX pipes. */
     961           0 :         err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_RX],
     962           0 :             USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_RX]);
     963           0 :         if (err) {
     964           0 :                 printf("%s: open rx pipe failed: %s\n",
     965           0 :                     sc->kue_dev.dv_xname, usbd_errstr(err));
     966           0 :                 return (EIO);
     967             :         }
     968             : 
     969           0 :         err = usbd_open_pipe(sc->kue_iface, sc->kue_ed[KUE_ENDPT_TX],
     970           0 :             USBD_EXCLUSIVE_USE, &sc->kue_ep[KUE_ENDPT_TX]);
     971           0 :         if (err) {
     972           0 :                 printf("%s: open tx pipe failed: %s\n",
     973           0 :                     sc->kue_dev.dv_xname, usbd_errstr(err));
     974           0 :                 return (EIO);
     975             :         }
     976             : 
     977             :         /* Start up the receive pipe. */
     978           0 :         for (i = 0; i < KUE_RX_LIST_CNT; i++) {
     979           0 :                 c = &sc->kue_cdata.kue_rx_chain[i];
     980           0 :                 usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX],
     981           0 :                     c, c->kue_buf, KUE_BUFSZ,
     982             :                     USBD_SHORT_XFER_OK | USBD_NO_COPY, USBD_NO_TIMEOUT,
     983             :                     kue_rxeof);
     984             :                 DPRINTFN(5,("%s: %s: start read\n", sc->kue_dev.dv_xname,
     985             :                             __func__));
     986           0 :                 usbd_transfer(c->kue_xfer);
     987             :         }
     988             : 
     989           0 :         return (0);
     990           0 : }
     991             : 
     992             : int
     993           0 : kue_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
     994             : {
     995           0 :         struct kue_softc        *sc = ifp->if_softc;
     996             :         int                     s, error = 0;
     997             : 
     998             :         DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
     999             : 
    1000           0 :         if (usbd_is_dying(sc->kue_udev))
    1001           0 :                 return (EIO);
    1002             : 
    1003             : #ifdef DIAGNOSTIC
    1004           0 :         if (!curproc) {
    1005           0 :                 printf("%s: no proc!!\n", sc->kue_dev.dv_xname);
    1006           0 :                 return EIO;
    1007             :         }
    1008             : #endif
    1009             : 
    1010           0 :         s = splnet();
    1011             : 
    1012           0 :         switch(command) {
    1013             :         case SIOCSIFADDR:
    1014           0 :                 ifp->if_flags |= IFF_UP;
    1015           0 :                 kue_init(sc);
    1016           0 :                 break;
    1017             : 
    1018             :         case SIOCSIFFLAGS:
    1019           0 :                 if (ifp->if_flags & IFF_UP) {
    1020           0 :                         if (ifp->if_flags & IFF_RUNNING &&
    1021           0 :                             ifp->if_flags & IFF_PROMISC &&
    1022           0 :                             !(sc->kue_if_flags & IFF_PROMISC)) {
    1023           0 :                                 sc->kue_rxfilt |= KUE_RXFILT_PROMISC;
    1024           0 :                                 kue_setword(sc, KUE_CMD_SET_PKT_FILTER,
    1025             :                                     sc->kue_rxfilt);
    1026           0 :                         } else if (ifp->if_flags & IFF_RUNNING &&
    1027           0 :                             !(ifp->if_flags & IFF_PROMISC) &&
    1028           0 :                             sc->kue_if_flags & IFF_PROMISC) {
    1029           0 :                                 sc->kue_rxfilt &= ~KUE_RXFILT_PROMISC;
    1030           0 :                                 kue_setword(sc, KUE_CMD_SET_PKT_FILTER,
    1031             :                                     sc->kue_rxfilt);
    1032           0 :                         } else if (!(ifp->if_flags & IFF_RUNNING))
    1033           0 :                                 kue_init(sc);
    1034             :                 } else {
    1035           0 :                         if (ifp->if_flags & IFF_RUNNING)
    1036           0 :                                 kue_stop(sc);
    1037             :                 }
    1038           0 :                 sc->kue_if_flags = ifp->if_flags;
    1039             :                 error = 0;
    1040           0 :                 break;
    1041             : 
    1042             :         default:
    1043           0 :                 error = ether_ioctl(ifp, &sc->arpcom, command, data);
    1044           0 :         }
    1045             : 
    1046           0 :         if (error == ENETRESET) {
    1047           0 :                 if (ifp->if_flags & IFF_RUNNING)
    1048           0 :                         kue_setmulti(sc);
    1049             :                 error = 0;
    1050           0 :         }
    1051             : 
    1052           0 :         splx(s);
    1053           0 :         return (error);
    1054           0 : }
    1055             : 
    1056             : void
    1057           0 : kue_watchdog(struct ifnet *ifp)
    1058             : {
    1059           0 :         struct kue_softc        *sc = ifp->if_softc;
    1060             :         struct kue_chain        *c;
    1061           0 :         usbd_status             stat;
    1062             :         int                     s;
    1063             : 
    1064             :         DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
    1065             : 
    1066           0 :         if (usbd_is_dying(sc->kue_udev))
    1067           0 :                 return;
    1068             : 
    1069           0 :         ifp->if_oerrors++;
    1070           0 :         printf("%s: watchdog timeout\n", sc->kue_dev.dv_xname);
    1071             : 
    1072           0 :         s = splusb();
    1073           0 :         c = &sc->kue_cdata.kue_tx_chain[0];
    1074           0 :         usbd_get_xfer_status(c->kue_xfer, NULL, NULL, NULL, &stat);
    1075           0 :         kue_txeof(c->kue_xfer, c, stat);
    1076             : 
    1077           0 :         if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    1078           0 :                 kue_start(ifp);
    1079           0 :         splx(s);
    1080           0 : }
    1081             : 
    1082             : /*
    1083             :  * Stop the adapter and free any mbufs allocated to the
    1084             :  * RX and TX lists.
    1085             :  */
    1086             : void
    1087           0 : kue_stop(struct kue_softc *sc)
    1088             : {
    1089             :         usbd_status             err;
    1090             :         struct ifnet            *ifp;
    1091             :         int                     i;
    1092             : 
    1093             :         DPRINTFN(5,("%s: %s: enter\n", sc->kue_dev.dv_xname,__func__));
    1094             : 
    1095           0 :         ifp = GET_IFP(sc);
    1096           0 :         ifp->if_timer = 0;
    1097           0 :         ifp->if_flags &= ~IFF_RUNNING;
    1098           0 :         ifq_clr_oactive(&ifp->if_snd);
    1099             : 
    1100             :         /* Stop transfers. */
    1101           0 :         if (sc->kue_ep[KUE_ENDPT_RX] != NULL) {
    1102           0 :                 usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_RX]);
    1103           0 :                 err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_RX]);
    1104           0 :                 if (err) {
    1105           0 :                         printf("%s: close rx pipe failed: %s\n",
    1106           0 :                             sc->kue_dev.dv_xname, usbd_errstr(err));
    1107           0 :                 }
    1108           0 :                 sc->kue_ep[KUE_ENDPT_RX] = NULL;
    1109           0 :         }
    1110             : 
    1111           0 :         if (sc->kue_ep[KUE_ENDPT_TX] != NULL) {
    1112           0 :                 usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_TX]);
    1113           0 :                 err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_TX]);
    1114           0 :                 if (err) {
    1115           0 :                         printf("%s: close tx pipe failed: %s\n",
    1116           0 :                             sc->kue_dev.dv_xname, usbd_errstr(err));
    1117           0 :                 }
    1118           0 :                 sc->kue_ep[KUE_ENDPT_TX] = NULL;
    1119           0 :         }
    1120             : 
    1121           0 :         if (sc->kue_ep[KUE_ENDPT_INTR] != NULL) {
    1122           0 :                 usbd_abort_pipe(sc->kue_ep[KUE_ENDPT_INTR]);
    1123           0 :                 err = usbd_close_pipe(sc->kue_ep[KUE_ENDPT_INTR]);
    1124           0 :                 if (err) {
    1125           0 :                         printf("%s: close intr pipe failed: %s\n",
    1126           0 :                             sc->kue_dev.dv_xname, usbd_errstr(err));
    1127           0 :                 }
    1128           0 :                 sc->kue_ep[KUE_ENDPT_INTR] = NULL;
    1129           0 :         }
    1130             : 
    1131             :         /* Free RX resources. */
    1132           0 :         for (i = 0; i < KUE_RX_LIST_CNT; i++) {
    1133           0 :                 if (sc->kue_cdata.kue_rx_chain[i].kue_mbuf != NULL) {
    1134           0 :                         m_freem(sc->kue_cdata.kue_rx_chain[i].kue_mbuf);
    1135           0 :                         sc->kue_cdata.kue_rx_chain[i].kue_mbuf = NULL;
    1136           0 :                 }
    1137           0 :                 if (sc->kue_cdata.kue_rx_chain[i].kue_xfer != NULL) {
    1138           0 :                         usbd_free_xfer(sc->kue_cdata.kue_rx_chain[i].kue_xfer);
    1139           0 :                         sc->kue_cdata.kue_rx_chain[i].kue_xfer = NULL;
    1140           0 :                 }
    1141             :         }
    1142             : 
    1143             :         /* Free TX resources. */
    1144           0 :         for (i = 0; i < KUE_TX_LIST_CNT; i++) {
    1145           0 :                 if (sc->kue_cdata.kue_tx_chain[i].kue_mbuf != NULL) {
    1146           0 :                         m_freem(sc->kue_cdata.kue_tx_chain[i].kue_mbuf);
    1147           0 :                         sc->kue_cdata.kue_tx_chain[i].kue_mbuf = NULL;
    1148           0 :                 }
    1149           0 :                 if (sc->kue_cdata.kue_tx_chain[i].kue_xfer != NULL) {
    1150           0 :                         usbd_free_xfer(sc->kue_cdata.kue_tx_chain[i].kue_xfer);
    1151           0 :                         sc->kue_cdata.kue_tx_chain[i].kue_xfer = NULL;
    1152           0 :                 }
    1153             :         }
    1154           0 : }

Generated by: LCOV version 1.13