if_cue.c revision 190734
11592Srgrimes/*- 21592Srgrimes * Copyright (c) 1997, 1998, 1999, 2000 31592Srgrimes * Bill Paul <wpaul@ee.columbia.edu>. All rights reserved. 496195Sdes * 596195Sdes * Redistribution and use in source and binary forms, with or without 61592Srgrimes * modification, are permitted provided that the following conditions 796195Sdes * are met: 896195Sdes * 1. Redistributions of source code must retain the above copyright 996195Sdes * notice, this list of conditions and the following disclaimer. 1096195Sdes * 2. Redistributions in binary form must reproduce the above copyright 1196195Sdes * notice, this list of conditions and the following disclaimer in the 121592Srgrimes * documentation and/or other materials provided with the distribution. 131592Srgrimes * 3. All advertising materials mentioning features or use of this software 141592Srgrimes * must display the following acknowledgement: 151592Srgrimes * This product includes software developed by Bill Paul. 161592Srgrimes * 4. Neither the name of the author nor the names of any co-contributors 171592Srgrimes * may be used to endorse or promote products derived from this software 181592Srgrimes * without specific prior written permission. 191592Srgrimes * 201592Srgrimes * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 211592Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221592Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231592Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD 241592Srgrimes * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 251592Srgrimes * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 261592Srgrimes * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 271592Srgrimes * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 281592Srgrimes * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 291592Srgrimes * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 301592Srgrimes * THE POSSIBILITY OF SUCH DAMAGE. 311592Srgrimes */ 321592Srgrimes 331592Srgrimes#include <sys/cdefs.h> 341592Srgrimes__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_cue.c 190734 2009-04-05 18:20:38Z thompsa $"); 351592Srgrimes 361592Srgrimes/* 371592Srgrimes * CATC USB-EL1210A USB to ethernet driver. Used in the CATC Netmate 381592Srgrimes * adapters and others. 391592Srgrimes * 401592Srgrimes * Written by Bill Paul <wpaul@ee.columbia.edu> 411592Srgrimes * Electrical Engineering Department 4229917Smarkm * Columbia University, New York City 431592Srgrimes */ 441592Srgrimes 451592Srgrimes/* 461592Srgrimes * The CATC USB-EL1210A provides USB ethernet support at 10Mbps. The 471592Srgrimes * RX filter uses a 512-bit multicast hash table, single perfect entry 4831490Scharnier * for the station address, and promiscuous mode. Unlike the ADMtek 4929917Smarkm * and KLSI chips, the CATC ASIC supports read and write combining 5031490Scharnier * mode where multiple packets can be transfered using a single bulk 511592Srgrimes * transaction, which helps performance a great deal. 521592Srgrimes */ 5398885Smarkm 5498885Smarkm#include "usbdevs.h" 5598885Smarkm#include <dev/usb/usb.h> 561592Srgrimes#include <dev/usb/usb_mfunc.h> 571592Srgrimes#include <dev/usb/usb_error.h> 581592Srgrimes 5996195Sdes#define USB_DEBUG_VAR cue_debug 6096195Sdes 611592Srgrimes#include <dev/usb/usb_core.h> 621592Srgrimes#include <dev/usb/usb_lookup.h> 631592Srgrimes#include <dev/usb/usb_process.h> 641592Srgrimes#include <dev/usb/usb_debug.h> 651592Srgrimes#include <dev/usb/usb_request.h> 661592Srgrimes#include <dev/usb/usb_busdma.h> 671592Srgrimes#include <dev/usb/usb_util.h> 681592Srgrimes 6922454Simp#include <dev/usb/net/usb_ethernet.h> 701592Srgrimes#include <dev/usb/net/if_cuereg.h> 7122454Simp 7241445Sdg/* 731592Srgrimes * Various supported device vendors/products. 741592Srgrimes */ 751592Srgrimes 7676094Smarkm/* Belkin F5U111 adapter covered by NETMATE entry */ 771592Srgrimes 781592Srgrimesstatic const struct usb2_device_id cue_devs[] = { 7945393Sbrian {USB_VPI(USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE, 0)}, 801592Srgrimes {USB_VPI(USB_VENDOR_CATC, USB_PRODUCT_CATC_NETMATE2, 0)}, 811592Srgrimes {USB_VPI(USB_VENDOR_SMARTBRIDGES, USB_PRODUCT_SMARTBRIDGES_SMARTLINK, 0)}, 821592Srgrimes}; 8376134Smarkm 841592Srgrimes/* prototypes */ 851592Srgrimes 861592Srgrimesstatic device_probe_t cue_probe; 871592Srgrimesstatic device_attach_t cue_attach; 881592Srgrimesstatic device_detach_t cue_detach; 8925099Sdavidnstatic device_shutdown_t cue_shutdown; 901592Srgrimes 9174874Smarkmstatic usb2_callback_t cue_bulk_read_callback; 9296195Sdesstatic usb2_callback_t cue_bulk_write_callback; 9374874Smarkm 9474874Smarkmstatic usb2_ether_fn_t cue_attach_post; 9596195Sdesstatic usb2_ether_fn_t cue_init; 9674874Smarkmstatic usb2_ether_fn_t cue_stop; 9796195Sdesstatic usb2_ether_fn_t cue_start; 9874874Smarkmstatic usb2_ether_fn_t cue_tick; 9974874Smarkmstatic usb2_ether_fn_t cue_setmulti; 10096195Sdesstatic usb2_ether_fn_t cue_setpromisc; 10196195Sdes 10296195Sdesstatic uint8_t cue_csr_read_1(struct cue_softc *, uint16_t); 10396195Sdesstatic uint16_t cue_csr_read_2(struct cue_softc *, uint8_t); 10496195Sdesstatic int cue_csr_write_1(struct cue_softc *, uint16_t, uint16_t); 10596195Sdesstatic int cue_mem(struct cue_softc *, uint8_t, uint16_t, void *, int); 10674874Smarkmstatic int cue_getmac(struct cue_softc *, void *); 10774874Smarkmstatic uint32_t cue_mchash(const uint8_t *); 1081592Srgrimesstatic void cue_reset(struct cue_softc *); 1091592Srgrimes 1101592Srgrimes#if USB_DEBUG 11141445Sdgstatic int cue_debug = 0; 1121592Srgrimes 11396195SdesSYSCTL_NODE(_hw_usb2, OID_AUTO, cue, CTLFLAG_RW, 0, "USB cue"); 11490334SimpSYSCTL_INT(_hw_usb2_cue, OID_AUTO, debug, CTLFLAG_RW, &cue_debug, 0, 11590335Simp "Debug level"); 11690334Simp#endif 11790334Simp 11890334Simpstatic const struct usb2_config cue_config[CUE_N_TRANSFER] = { 1191592Srgrimes 12098885Smarkm [CUE_BULK_DT_WR] = { 12198885Smarkm .type = UE_BULK, 12298885Smarkm .endpoint = UE_ADDR_ANY, 123141589Sru .direction = UE_DIR_OUT, 12451433Smarkm .bufsize = (MCLBYTES + 2), 1251592Srgrimes .flags = {.pipe_bof = 1,}, 12690334Simp .callback = cue_bulk_write_callback, 1271592Srgrimes .timeout = 10000, /* 10 seconds */ 1281592Srgrimes }, 1291592Srgrimes 130141918Sstefanf [CUE_BULK_DT_RD] = { 131141918Sstefanf .type = UE_BULK, 13256590Sshin .endpoint = UE_ADDR_ANY, 1331592Srgrimes .direction = UE_DIR_IN, 1341592Srgrimes .bufsize = (MCLBYTES + 2), 1351592Srgrimes .flags = {.pipe_bof = 1,.short_xfer_ok = 1,}, 1361592Srgrimes .callback = cue_bulk_read_callback, 13724349Simp }, 1381592Srgrimes}; 1391592Srgrimes 14072093Sasmodaistatic device_method_t cue_methods[] = { 1411592Srgrimes /* Device interface */ 1421592Srgrimes DEVMETHOD(device_probe, cue_probe), 1431592Srgrimes DEVMETHOD(device_attach, cue_attach), 1441592Srgrimes DEVMETHOD(device_detach, cue_detach), 1451592Srgrimes DEVMETHOD(device_shutdown, cue_shutdown), 1461592Srgrimes 1471592Srgrimes {0, 0} 14841445Sdg}; 14941445Sdg 15041445Sdgstatic driver_t cue_driver = { 1511592Srgrimes .name = "cue", 1521592Srgrimes .methods = cue_methods, 1531592Srgrimes .size = sizeof(struct cue_softc), 1541592Srgrimes}; 1551592Srgrimes 1561592Srgrimesstatic devclass_t cue_devclass; 1571592Srgrimes 1581592SrgrimesDRIVER_MODULE(cue, uhub, cue_driver, cue_devclass, NULL, 0); 1591592SrgrimesMODULE_DEPEND(cue, uether, 1, 1, 1); 1601592SrgrimesMODULE_DEPEND(cue, usb, 1, 1, 1); 1611592SrgrimesMODULE_DEPEND(cue, ether, 1, 1, 1); 1621592Srgrimes 1631592Srgrimesstatic const struct usb2_ether_methods cue_ue_methods = { 1641592Srgrimes .ue_attach_post = cue_attach_post, 1651592Srgrimes .ue_start = cue_start, 16635728Srnordier .ue_init = cue_init, 1671592Srgrimes .ue_stop = cue_stop, 1681592Srgrimes .ue_tick = cue_tick, 1691592Srgrimes .ue_setmulti = cue_setmulti, 1701592Srgrimes .ue_setpromisc = cue_setpromisc, 1711592Srgrimes}; 1721592Srgrimes 1731592Srgrimes#define CUE_SETBIT(sc, reg, x) \ 1741592Srgrimes cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) | (x)) 1751592Srgrimes 1761592Srgrimes#define CUE_CLRBIT(sc, reg, x) \ 17741445Sdg cue_csr_write_1(sc, reg, cue_csr_read_1(sc, reg) & ~(x)) 17841445Sdg 17941445Sdgstatic uint8_t 18096195Sdescue_csr_read_1(struct cue_softc *sc, uint16_t reg) 1811592Srgrimes{ 18229917Smarkm struct usb2_device_request req; 1831592Srgrimes uint8_t val; 1841592Srgrimes 18596195Sdes req.bmRequestType = UT_READ_VENDOR_DEVICE; 18674874Smarkm req.bRequest = CUE_CMD_READREG; 1871592Srgrimes USETW(req.wValue, 0); 18896195Sdes USETW(req.wIndex, reg); 1891592Srgrimes USETW(req.wLength, 1); 1901592Srgrimes 1911592Srgrimes if (usb2_ether_do_request(&sc->sc_ue, &req, &val, 1000)) { 1921592Srgrimes /* ignore any errors */ 1931592Srgrimes } 19496195Sdes return (val); 1951592Srgrimes} 19696195Sdes 19796195Sdesstatic uint16_t 198143907Sdascue_csr_read_2(struct cue_softc *sc, uint8_t reg) 19996195Sdes{ 20056590Sshin struct usb2_device_request req; 20198885Smarkm uint16_t val; 202143907Sdas 20325099Sdavidn req.bmRequestType = UT_READ_VENDOR_DEVICE; 2041592Srgrimes req.bRequest = CUE_CMD_READREG; 205143907Sdas USETW(req.wValue, 0); 206143907Sdas USETW(req.wIndex, reg); 207143907Sdas USETW(req.wLength, 2); 208143907Sdas 2091592Srgrimes (void)usb2_ether_do_request(&sc->sc_ue, &req, &val, 1000); 2101592Srgrimes return (le16toh(val)); 2111592Srgrimes} 21296195Sdes 21396195Sdesstatic int 21496195Sdescue_csr_write_1(struct cue_softc *sc, uint16_t reg, uint16_t val) 21596195Sdes{ 21696195Sdes struct usb2_device_request req; 21796195Sdes 21896195Sdes req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 21996195Sdes req.bRequest = CUE_CMD_WRITEREG; 22096195Sdes USETW(req.wValue, val); 22174874Smarkm USETW(req.wIndex, reg); 2221592Srgrimes USETW(req.wLength, 0); 2231592Srgrimes 2241592Srgrimes return (usb2_ether_do_request(&sc->sc_ue, &req, NULL, 1000)); 22596195Sdes} 22696195Sdes 227141918Sstefanfstatic int 22896195Sdescue_mem(struct cue_softc *sc, uint8_t cmd, uint16_t addr, void *buf, int len) 2291592Srgrimes{ 23096195Sdes struct usb2_device_request req; 23196195Sdes 23296195Sdes if (cmd == CUE_CMD_READSRAM) 23396195Sdes req.bmRequestType = UT_READ_VENDOR_DEVICE; 23496195Sdes else 23596195Sdes req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 23696195Sdes req.bRequest = cmd; 23796195Sdes USETW(req.wValue, 0); 23896195Sdes USETW(req.wIndex, addr); 23996195Sdes USETW(req.wLength, len); 24096195Sdes 24196195Sdes return (usb2_ether_do_request(&sc->sc_ue, &req, buf, 1000)); 24296195Sdes} 24396195Sdes 24496195Sdesstatic int 24596195Sdescue_getmac(struct cue_softc *sc, void *buf) 24696195Sdes{ 24796195Sdes struct usb2_device_request req; 24822454Simp 2491592Srgrimes req.bmRequestType = UT_READ_VENDOR_DEVICE; 2501592Srgrimes req.bRequest = CUE_CMD_GET_MACADDR; 2511592Srgrimes USETW(req.wValue, 0); 2521592Srgrimes USETW(req.wIndex, 0); 25396195Sdes USETW(req.wLength, ETHER_ADDR_LEN); 25496195Sdes 25551433Smarkm return (usb2_ether_do_request(&sc->sc_ue, &req, buf, 1000)); 25651433Smarkm} 25756590Sshin 25896195Sdes#define CUE_BITS 9 25951433Smarkm 26051433Smarkmstatic uint32_t 2611592Srgrimescue_mchash(const uint8_t *addr) 2621592Srgrimes{ 2631592Srgrimes uint32_t crc; 26441860Speter 2651592Srgrimes /* Compute CRC for the address value. */ 2661592Srgrimes crc = ether_crc32_le(addr, ETHER_ADDR_LEN); 2671592Srgrimes 2681592Srgrimes return (crc & ((1 << CUE_BITS) - 1)); 2691592Srgrimes} 270146074Sjmallett 2711592Srgrimesstatic void 2721592Srgrimescue_setpromisc(struct usb2_ether *ue) 27341860Speter{ 2741592Srgrimes struct cue_softc *sc = usb2_ether_getsc(ue); 2751592Srgrimes struct ifnet *ifp = usb2_ether_getifp(ue); 2761592Srgrimes 2771592Srgrimes CUE_LOCK_ASSERT(sc, MA_OWNED); 2781592Srgrimes 2791592Srgrimes /* if we want promiscuous mode, set the allframes bit */ 2801592Srgrimes if (ifp->if_flags & IFF_PROMISC) 28156590Sshin CUE_SETBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC); 2821592Srgrimes else 2831592Srgrimes CUE_CLRBIT(sc, CUE_ETHCTL, CUE_ETHCTL_PROMISC); 2841592Srgrimes 2851592Srgrimes /* write multicast hash-bits */ 28651433Smarkm cue_setmulti(ue); 28751433Smarkm} 28851433Smarkm 28951433Smarkmstatic void 29056590Sshincue_setmulti(struct usb2_ether *ue) 29151433Smarkm{ 29251433Smarkm struct cue_softc *sc = usb2_ether_getsc(ue); 29351433Smarkm struct ifnet *ifp = usb2_ether_getifp(ue); 29496195Sdes struct ifmultiaddr *ifma; 29596195Sdes uint32_t h = 0, i; 2961592Srgrimes uint8_t hashtbl[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; 2971592Srgrimes 2981592Srgrimes CUE_LOCK_ASSERT(sc, MA_OWNED); 2991592Srgrimes 3001592Srgrimes if (ifp->if_flags & IFF_ALLMULTI || ifp->if_flags & IFF_PROMISC) { 3011592Srgrimes for (i = 0; i < 8; i++) 30296195Sdes hashtbl[i] = 0xff; 30396195Sdes cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR, 30496195Sdes &hashtbl, 8); 3051592Srgrimes return; 30696195Sdes } 30796195Sdes 30896195Sdes /* now program new ones */ 309143907Sdas IF_ADDR_LOCK(ifp); 31096195Sdes TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) 31174874Smarkm { 31296195Sdes if (ifma->ifma_addr->sa_family != AF_LINK) 31396195Sdes continue; 31496195Sdes h = cue_mchash(LLADDR((struct sockaddr_dl *)ifma->ifma_addr)); 31596195Sdes hashtbl[h >> 3] |= 1 << (h & 0x7); 31676134Smarkm } 31774874Smarkm IF_ADDR_UNLOCK(ifp); 31874874Smarkm 31996195Sdes /* 320227208Sbrueffer * Also include the broadcast address in the filter 32196195Sdes * so we can receive broadcast frames. 32296195Sdes */ 32376134Smarkm if (ifp->if_flags & IFF_BROADCAST) { 32474874Smarkm h = cue_mchash(ifp->if_broadcastaddr); 32574874Smarkm hashtbl[h >> 3] |= 1 << (h & 0x7); 32696195Sdes } 32796195Sdes 32896195Sdes cue_mem(sc, CUE_CMD_WRITESRAM, CUE_MCAST_TABLE_ADDR, &hashtbl, 8); 32996195Sdes} 33096195Sdes 33196195Sdesstatic void 33296195Sdescue_reset(struct cue_softc *sc) 33396195Sdes{ 33474874Smarkm struct usb2_device_request req; 33596195Sdes 33696195Sdes req.bmRequestType = UT_WRITE_VENDOR_DEVICE; 33796195Sdes req.bRequest = CUE_CMD_RESET; 33896195Sdes USETW(req.wValue, 0); 33976134Smarkm USETW(req.wIndex, 0); 34074874Smarkm USETW(req.wLength, 0); 34174874Smarkm 3421592Srgrimes if (usb2_ether_do_request(&sc->sc_ue, &req, NULL, 1000)) { 34396195Sdes /* ignore any errors */ 3441592Srgrimes } 3451592Srgrimes 3461592Srgrimes /* 34796195Sdes * wait a little while for the chip to get its brains in order: 3481592Srgrimes */ 34976094Smarkm usb2_ether_pause(&sc->sc_ue, hz / 100); 35096195Sdes} 3511592Srgrimes 35274874Smarkmstatic void 35325674Sdavidncue_attach_post(struct usb2_ether *ue) 35474874Smarkm{ 35574874Smarkm struct cue_softc *sc = usb2_ether_getsc(ue); 35674874Smarkm 3571592Srgrimes cue_getmac(sc, ue->ue_eaddr); 35825099Sdavidn} 35925099Sdavidn 36025099Sdavidnstatic int 36125099Sdavidncue_probe(device_t dev) 36296195Sdes{ 36376134Smarkm struct usb2_attach_arg *uaa = device_get_ivars(dev); 36425099Sdavidn 36598885Smarkm if (uaa->usb2_mode != USB_MODE_HOST) 3661592Srgrimes return (ENXIO); 3671592Srgrimes if (uaa->info.bConfigIndex != CUE_CONFIG_IDX) 36896195Sdes return (ENXIO); 36925099Sdavidn if (uaa->info.bIfaceIndex != CUE_IFACE_IDX) 37025099Sdavidn return (ENXIO); 37156590Sshin 37225099Sdavidn return (usb2_lookup_id_by_uaa(cue_devs, sizeof(cue_devs), uaa)); 37325099Sdavidn} 37496195Sdes 37596195Sdes/* 37625099Sdavidn * Attach the interface. Allocate softc structures, do ifmedia 37725099Sdavidn * setup and ethernet/BPF attach. 37896195Sdes */ 37925099Sdavidnstatic int 38076134Smarkmcue_attach(device_t dev) 38125099Sdavidn{ 38276094Smarkm struct usb2_attach_arg *uaa = device_get_ivars(dev); 38376134Smarkm struct cue_softc *sc = device_get_softc(dev); 38425099Sdavidn struct usb2_ether *ue = &sc->sc_ue; 3851592Srgrimes uint8_t iface_index; 38674874Smarkm int error; 38774874Smarkm 38874874Smarkm device_set_usb2_desc(dev); 38974874Smarkm mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 39074874Smarkm 39174874Smarkm iface_index = CUE_IFACE_IDX; 39296195Sdes error = usb2_transfer_setup(uaa->device, &iface_index, 39374874Smarkm sc->sc_xfer, cue_config, CUE_N_TRANSFER, sc, &sc->sc_mtx); 39474874Smarkm if (error) { 39574874Smarkm device_printf(dev, "allocating USB transfers failed!\n"); 39696195Sdes goto detach; 39796195Sdes } 39896195Sdes 39996195Sdes ue->ue_sc = sc; 40074874Smarkm ue->ue_dev = dev; 40174874Smarkm ue->ue_udev = uaa->device; 4021592Srgrimes ue->ue_mtx = &sc->sc_mtx; 4031592Srgrimes ue->ue_methods = &cue_ue_methods; 4041592Srgrimes 4051592Srgrimes error = usb2_ether_ifattach(ue); 40676094Smarkm if (error) { 40776134Smarkm device_printf(dev, "could not attach interface\n"); 4081592Srgrimes goto detach; 40976094Smarkm } 41076134Smarkm return (0); /* success */ 4111592Srgrimes 41298885Smarkmdetach: 41398885Smarkm cue_detach(dev); 4141592Srgrimes return (ENXIO); /* failure */ 4151592Srgrimes} 4161592Srgrimes 4171592Srgrimesstatic int 4181592Srgrimescue_detach(device_t dev) 4191592Srgrimes{ 4201592Srgrimes struct cue_softc *sc = device_get_softc(dev); 4211592Srgrimes struct usb2_ether *ue = &sc->sc_ue; 4221592Srgrimes 4231592Srgrimes usb2_transfer_unsetup(sc->sc_xfer, CUE_N_TRANSFER); 4241592Srgrimes usb2_ether_ifdetach(ue); 4251592Srgrimes mtx_destroy(&sc->sc_mtx); 4261592Srgrimes 4271592Srgrimes return (0); 4281592Srgrimes} 4291592Srgrimes 43098885Smarkmstatic void 43198885Smarkmcue_bulk_read_callback(struct usb2_xfer *xfer) 43298885Smarkm{ 4331592Srgrimes struct cue_softc *sc = xfer->priv_sc; 4341592Srgrimes struct usb2_ether *ue = &sc->sc_ue; 4351592Srgrimes struct ifnet *ifp = usb2_ether_getifp(ue); 43698885Smarkm uint8_t buf[2]; 43798885Smarkm int len; 43898885Smarkm 43998885Smarkm switch (USB_GET_STATE(xfer)) { 4401592Srgrimes case USB_ST_TRANSFERRED: 4411592Srgrimes 4421592Srgrimes if (xfer->actlen <= (2 + sizeof(struct ether_header))) { 4431592Srgrimes ifp->if_ierrors++; 4441592Srgrimes goto tr_setup; 445146074Sjmallett } 4461592Srgrimes usb2_copy_out(xfer->frbuffers, 0, buf, 2); 4471592Srgrimes xfer->actlen -= 2; 44898885Smarkm len = buf[0] | (buf[1] << 8); 4491592Srgrimes len = min(xfer->actlen, len); 4501592Srgrimes 4511592Srgrimes usb2_ether_rxbuf(ue, xfer->frbuffers, 2, len); 4521592Srgrimes /* FALLTHROUGH */ 4531592Srgrimes case USB_ST_SETUP: 45474874Smarkmtr_setup: 4551592Srgrimes xfer->frlengths[0] = xfer->max_data_length; 4561592Srgrimes usb2_start_hardware(xfer); 4571592Srgrimes usb2_ether_rxflush(ue); 4581592Srgrimes return; 4591592Srgrimes 4601592Srgrimes default: /* Error */ 4611592Srgrimes DPRINTF("bulk read error, %s\n", 46274874Smarkm usb2_errstr(xfer->error)); 46374874Smarkm 46476094Smarkm if (xfer->error != USB_ERR_CANCELLED) { 46576134Smarkm /* try to clear stall first */ 46674874Smarkm xfer->flags.stall_pipe = 1; 46774874Smarkm goto tr_setup; 46896195Sdes } 46996195Sdes return; 47074874Smarkm 47174874Smarkm } 47274874Smarkm} 47374874Smarkm 47474874Smarkmstatic void 47596195Sdescue_bulk_write_callback(struct usb2_xfer *xfer) 47696195Sdes{ 47796195Sdes struct cue_softc *sc = xfer->priv_sc; 47896195Sdes struct ifnet *ifp = usb2_ether_getifp(&sc->sc_ue); 47996195Sdes struct mbuf *m; 48096195Sdes uint8_t buf[2]; 48196195Sdes 4821592Srgrimes switch (USB_GET_STATE(xfer)) { 48398885Smarkm case USB_ST_TRANSFERRED: 48496195Sdes DPRINTFN(11, "transfer complete\n"); 48596195Sdes ifp->if_opackets++; 48696195Sdes 48796195Sdes /* FALLTHROUGH */ 48896195Sdes case USB_ST_SETUP: 48996195Sdestr_setup: 4901592Srgrimes IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 4911592Srgrimes 4921592Srgrimes if (m == NULL) 4931592Srgrimes return; 4941592Srgrimes if (m->m_pkthdr.len > MCLBYTES) 49574874Smarkm m->m_pkthdr.len = MCLBYTES; 49696195Sdes xfer->frlengths[0] = (m->m_pkthdr.len + 2); 49796195Sdes 49896195Sdes /* the first two bytes are the frame length */ 49925099Sdavidn 50025099Sdavidn buf[0] = (uint8_t)(m->m_pkthdr.len); 50125099Sdavidn buf[1] = (uint8_t)(m->m_pkthdr.len >> 8); 5021592Srgrimes 5031592Srgrimes usb2_copy_in(xfer->frbuffers, 0, buf, 2); 5041592Srgrimes 50596195Sdes usb2_m_copy_in(xfer->frbuffers, 2, 5061592Srgrimes m, 0, m->m_pkthdr.len); 507127864Smux 50896195Sdes /* 5091592Srgrimes * If there's a BPF listener, bounce a copy of this frame 5101592Srgrimes * to him. 5111592Srgrimes */ 51276134Smarkm BPF_MTAP(ifp, m); 51376134Smarkm 51476134Smarkm m_freem(m); 51576134Smarkm 51676134Smarkm usb2_start_hardware(xfer); 51776134Smarkm 51876134Smarkm return; 51976134Smarkm 52076134Smarkm default: /* Error */ 52176134Smarkm DPRINTFN(11, "transfer error, %s\n", 52276134Smarkm usb2_errstr(xfer->error)); 52376134Smarkm 52476134Smarkm ifp->if_oerrors++; 52576134Smarkm 52676134Smarkm if (xfer->error != USB_ERR_CANCELLED) { 52776134Smarkm /* try to clear stall first */ 52876134Smarkm xfer->flags.stall_pipe = 1; 52976134Smarkm goto tr_setup; 53076134Smarkm } 53176134Smarkm return; 5321592Srgrimes } 53390335Simp} 5341592Srgrimes 5351592Srgrimesstatic void 5361592Srgrimescue_tick(struct usb2_ether *ue) 5371592Srgrimes{ 5381592Srgrimes struct cue_softc *sc = usb2_ether_getsc(ue); 5391592Srgrimes struct ifnet *ifp = usb2_ether_getifp(ue); 5401592Srgrimes 54176125Smarkm CUE_LOCK_ASSERT(sc, MA_OWNED); 54290335Simp 5431592Srgrimes ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_SINGLECOLL); 5441592Srgrimes ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_MULTICOLL); 5451592Srgrimes ifp->if_collisions += cue_csr_read_2(sc, CUE_TX_EXCESSCOLL); 5461592Srgrimes 5471592Srgrimes if (cue_csr_read_2(sc, CUE_RX_FRAMEERR)) 5481592Srgrimes ifp->if_ierrors++; 5491592Srgrimes} 5501592Srgrimes 5511592Srgrimesstatic void 5521592Srgrimescue_start(struct usb2_ether *ue) 5531592Srgrimes{ 5541592Srgrimes struct cue_softc *sc = usb2_ether_getsc(ue); 55590334Simp 5561592Srgrimes /* 5571592Srgrimes * start the USB transfers, if not already started: 5581592Srgrimes */ 5591592Srgrimes usb2_transfer_start(sc->sc_xfer[CUE_BULK_DT_RD]); 5601592Srgrimes usb2_transfer_start(sc->sc_xfer[CUE_BULK_DT_WR]); 56145422Sbrian} 56245422Sbrian 56396195Sdesstatic void 5641592Srgrimescue_init(struct usb2_ether *ue) 5651592Srgrimes{ 5661592Srgrimes struct cue_softc *sc = usb2_ether_getsc(ue); 5671592Srgrimes struct ifnet *ifp = usb2_ether_getifp(ue); 5681592Srgrimes int i; 5691592Srgrimes 5701592Srgrimes CUE_LOCK_ASSERT(sc, MA_OWNED); 5711592Srgrimes 57290334Simp /* 5731592Srgrimes * Cancel pending I/O and free all RX/TX buffers. 5741592Srgrimes */ 5751592Srgrimes cue_stop(ue); 5761592Srgrimes#if 0 5771592Srgrimes cue_reset(sc); 5781592Srgrimes#endif 5791592Srgrimes /* Set MAC address */ 5801592Srgrimes for (i = 0; i < ETHER_ADDR_LEN; i++) 5811592Srgrimes cue_csr_write_1(sc, CUE_PAR0 - i, IF_LLADDR(ifp)[i]); 5821592Srgrimes 5831592Srgrimes /* Enable RX logic. */ 5841592Srgrimes cue_csr_write_1(sc, CUE_ETHCTL, CUE_ETHCTL_RX_ON | CUE_ETHCTL_MCAST_ON); 5851592Srgrimes 5861592Srgrimes /* Load the multicast filter */ 5871592Srgrimes cue_setpromisc(ue); 58890334Simp 5891592Srgrimes /* 5901592Srgrimes * Set the number of RX and TX buffers that we want 5911592Srgrimes * to reserve inside the ASIC. 5921592Srgrimes */ 5931592Srgrimes cue_csr_write_1(sc, CUE_RX_BUFPKTS, CUE_RX_FRAMES); 594 cue_csr_write_1(sc, CUE_TX_BUFPKTS, CUE_TX_FRAMES); 595 596 /* Set advanced operation modes. */ 597 cue_csr_write_1(sc, CUE_ADVANCED_OPMODES, 598 CUE_AOP_EMBED_RXLEN | 0x01);/* 1 wait state */ 599 600 /* Program the LED operation. */ 601 cue_csr_write_1(sc, CUE_LEDCTL, CUE_LEDCTL_FOLLOW_LINK); 602 603 usb2_transfer_set_stall(sc->sc_xfer[CUE_BULK_DT_WR]); 604 605 ifp->if_drv_flags |= IFF_DRV_RUNNING; 606 cue_start(ue); 607} 608 609/* 610 * Stop the adapter and free any mbufs allocated to the 611 * RX and TX lists. 612 */ 613static void 614cue_stop(struct usb2_ether *ue) 615{ 616 struct cue_softc *sc = usb2_ether_getsc(ue); 617 struct ifnet *ifp = usb2_ether_getifp(ue); 618 619 CUE_LOCK_ASSERT(sc, MA_OWNED); 620 621 ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 622 623 /* 624 * stop all the transfers, if not already stopped: 625 */ 626 usb2_transfer_stop(sc->sc_xfer[CUE_BULK_DT_WR]); 627 usb2_transfer_stop(sc->sc_xfer[CUE_BULK_DT_RD]); 628 629 cue_csr_write_1(sc, CUE_ETHCTL, 0); 630 cue_reset(sc); 631} 632 633/* 634 * Stop all chip I/O so that the kernel's probe routines don't 635 * get confused by errant DMAs when rebooting. 636 */ 637static int 638cue_shutdown(device_t dev) 639{ 640 struct cue_softc *sc = device_get_softc(dev); 641 642 usb2_ether_ifshutdown(&sc->sc_ue); 643 644 return (0); 645} 646