if_cdce.c revision 188746
1169695Skan/* $NetBSD: if_cdce.c,v 1.4 2004/10/24 12:50:54 augustss Exp $ */ 2169695Skan 3169695Skan/*- 4169695Skan * Copyright (c) 1997, 1998, 1999, 2000-2003 Bill Paul <wpaul@windriver.com> 5169695Skan * Copyright (c) 2003-2005 Craig Boston 6169695Skan * Copyright (c) 2004 Daniel Hartmeier 7169695Skan * Copyright (c) 2009 Hans Petter Selasky 8169695Skan * All rights reserved. 9169695Skan * 10169695Skan * Redistribution and use in source and binary forms, with or without 11169695Skan * modification, are permitted provided that the following conditions 12169695Skan * are met: 13169695Skan * 1. Redistributions of source code must retain the above copyright 14169695Skan * notice, this list of conditions and the following disclaimer. 15169695Skan * 2. Redistributions in binary form must reproduce the above copyright 16169695Skan * notice, this list of conditions and the following disclaimer in the 17169695Skan * documentation and/or other materials provided with the distribution. 18169695Skan * 3. All advertising materials mentioning features or use of this software 19169695Skan * must display the following acknowledgement: 20169695Skan * This product includes software developed by Bill Paul. 21169695Skan * 4. Neither the name of the author nor the names of any co-contributors 22169695Skan * may be used to endorse or promote products derived from this software 23169695Skan * without specific prior written permission. 24169695Skan * 25169695Skan * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND 26169695Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27169695Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28169695Skan * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul, THE VOICES IN HIS HEAD OR 29169695Skan * THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 30169695Skan * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 31169695Skan * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 32169695Skan * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 33169695Skan * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 34169695Skan * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 35169695Skan * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36169695Skan */ 37169695Skan 38169695Skan/* 39169695Skan * USB Communication Device Class (Ethernet Networking Control Model) 40169695Skan * http://www.usb.org/developers/devclass_docs/usbcdc11.pdf 41169695Skan */ 42169695Skan 43169695Skan#include <sys/cdefs.h> 44169695Skan__FBSDID("$FreeBSD: head/sys/dev/usb2/ethernet/if_cdce2.c 188746 2009-02-18 06:33:10Z thompsa $"); 45169695Skan 46169695Skan#include "usbdevs.h" 47169695Skan#include <dev/usb2/include/usb2_standard.h> 48169695Skan#include <dev/usb2/include/usb2_mfunc.h> 49169695Skan#include <dev/usb2/include/usb2_error.h> 50169695Skan#include <dev/usb2/include/usb2_cdc.h> 51169695Skan#include <dev/usb2/include/usb2_defs.h> 52169695Skan 53169695Skan#define USB_DEBUG_VAR cdce_debug 54169695Skan 55169695Skan#include <dev/usb2/core/usb2_core.h> 56169695Skan#include <dev/usb2/core/usb2_lookup.h> 57169695Skan#include <dev/usb2/core/usb2_process.h> 58169695Skan#include <dev/usb2/core/usb2_debug.h> 59169695Skan#include <dev/usb2/core/usb2_request.h> 60169695Skan#include <dev/usb2/core/usb2_busdma.h> 61169695Skan#include <dev/usb2/core/usb2_util.h> 62169695Skan#include <dev/usb2/core/usb2_parse.h> 63169695Skan#include <dev/usb2/core/usb2_device.h> 64169695Skan 65169695Skan#include <dev/usb2/ethernet/usb2_ethernet.h> 66169695Skan#include <dev/usb2/ethernet/if_cdcereg.h> 67169695Skan 68169695Skanstatic device_probe_t cdce_probe; 69169695Skanstatic device_attach_t cdce_attach; 70169695Skanstatic device_detach_t cdce_detach; 71169695Skanstatic device_shutdown_t cdce_shutdown; 72169695Skanstatic device_suspend_t cdce_suspend; 73169695Skanstatic device_resume_t cdce_resume; 74169695Skanstatic usb2_handle_request_t cdce_handle_request; 75169695Skan 76169695Skanstatic usb2_callback_t cdce_bulk_write_callback; 77169695Skanstatic usb2_callback_t cdce_bulk_read_callback; 78169695Skanstatic usb2_callback_t cdce_intr_read_callback; 79169695Skanstatic usb2_callback_t cdce_intr_write_callback; 80169695Skan 81169695Skanstatic usb2_ether_fn_t cdce_attach_post; 82169695Skanstatic usb2_ether_fn_t cdce_init; 83169695Skanstatic usb2_ether_fn_t cdce_stop; 84169695Skanstatic usb2_ether_fn_t cdce_start; 85169695Skanstatic usb2_ether_fn_t cdce_setmulti; 86169695Skanstatic usb2_ether_fn_t cdce_setpromisc; 87169695Skan 88169695Skanstatic uint32_t cdce_m_crc32(struct mbuf *, uint32_t, uint32_t); 89169695Skan 90169695Skan#if USB_DEBUG 91169695Skanstatic int cdce_debug = 0; 92169695Skan 93169695SkanSYSCTL_NODE(_hw_usb2, OID_AUTO, cdce, CTLFLAG_RW, 0, "USB CDC-Ethernet"); 94169695SkanSYSCTL_INT(_hw_usb2_cdce, OID_AUTO, debug, CTLFLAG_RW, &cdce_debug, 0, 95169695Skan "Debug level"); 96169695Skan#endif 97169695Skan 98169695Skanstatic const struct usb2_config cdce_config[CDCE_N_TRANSFER] = { 99169695Skan 100169695Skan [CDCE_BULK_A] = { 101169695Skan .type = UE_BULK, 102169695Skan .endpoint = UE_ADDR_ANY, 103169695Skan .direction = UE_DIR_OUT, 104169695Skan .if_index = 0, 105169695Skan /* Host Mode */ 106169695Skan .mh.frames = CDCE_FRAMES_MAX, 107169695Skan .mh.bufsize = (CDCE_FRAMES_MAX * MCLBYTES), 108169695Skan .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,}, 109169695Skan .mh.callback = cdce_bulk_write_callback, 110169695Skan .mh.timeout = 10000, /* 10 seconds */ 111169695Skan /* Device Mode */ 112169695Skan .md.frames = CDCE_FRAMES_MAX, 113169695Skan .md.bufsize = (CDCE_FRAMES_MAX * MCLBYTES), 114169695Skan .md.flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,}, 115169695Skan .md.callback = cdce_bulk_read_callback, 116169695Skan .md.timeout = 0, /* no timeout */ 117169695Skan }, 118169695Skan 119169695Skan [CDCE_BULK_B] = { 120169695Skan .type = UE_BULK, 121169695Skan .endpoint = UE_ADDR_ANY, 122169695Skan .direction = UE_DIR_IN, 123169695Skan .if_index = 0, 124169695Skan /* Host Mode */ 125169695Skan .mh.frames = CDCE_FRAMES_MAX, 126169695Skan .mh.bufsize = (CDCE_FRAMES_MAX * MCLBYTES), 127169695Skan .mh.flags = {.pipe_bof = 1,.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,}, 128169695Skan .mh.callback = cdce_bulk_read_callback, 129169695Skan .mh.timeout = 0, /* no timeout */ 130169695Skan /* Device Mode */ 131169695Skan .md.frames = CDCE_FRAMES_MAX, 132169695Skan .md.bufsize = (CDCE_FRAMES_MAX * MCLBYTES), 133169695Skan .md.flags = {.pipe_bof = 1,.force_short_xfer = 1,.ext_buffer = 1,}, 134169695Skan .md.callback = cdce_bulk_write_callback, 135169695Skan .md.timeout = 10000, /* 10 seconds */ 136169695Skan }, 137169695Skan 138169695Skan [CDCE_INTR] = { 139169695Skan .type = UE_INTERRUPT, 140169695Skan .endpoint = UE_ADDR_ANY, 141169695Skan .direction = UE_DIR_IN, 142169695Skan .if_index = 1, 143169695Skan /* Host Mode */ 144169695Skan .mh.bufsize = CDCE_IND_SIZE_MAX, 145169695Skan .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.no_pipe_ok = 1,}, 146169695Skan .mh.callback = cdce_intr_read_callback, 147169695Skan .mh.timeout = 0, 148169695Skan /* Device Mode */ 149169695Skan .md.bufsize = CDCE_IND_SIZE_MAX, 150169695Skan .md.flags = {.pipe_bof = 1,.force_short_xfer = 1,.no_pipe_ok = 1,}, 151169695Skan .md.callback = cdce_intr_write_callback, 152169695Skan .md.timeout = 10000, /* 10 seconds */ 153169695Skan }, 154169695Skan}; 155169695Skan 156169695Skanstatic device_method_t cdce_methods[] = { 157169695Skan /* USB interface */ 158169695Skan DEVMETHOD(usb2_handle_request, cdce_handle_request), 159169695Skan 160169695Skan /* Device interface */ 161169695Skan DEVMETHOD(device_probe, cdce_probe), 162169695Skan DEVMETHOD(device_attach, cdce_attach), 163169695Skan DEVMETHOD(device_detach, cdce_detach), 164169695Skan DEVMETHOD(device_suspend, cdce_suspend), 165169695Skan DEVMETHOD(device_resume, cdce_resume), 166169695Skan DEVMETHOD(device_shutdown, cdce_shutdown), 167169695Skan 168169695Skan {0, 0} 169169695Skan}; 170169695Skan 171169695Skanstatic driver_t cdce_driver = { 172169695Skan .name = "cdce", 173169695Skan .methods = cdce_methods, 174169695Skan .size = sizeof(struct cdce_softc), 175169695Skan}; 176169695Skan 177169695Skanstatic devclass_t cdce_devclass; 178169695Skan 179169695SkanDRIVER_MODULE(cdce, ushub, cdce_driver, cdce_devclass, NULL, 0); 180169695SkanMODULE_VERSION(cdce, 1); 181169695SkanMODULE_DEPEND(cdce, usb2_ethernet, 1, 1, 1); 182169695SkanMODULE_DEPEND(cdce, usb2_core, 1, 1, 1); 183169695SkanMODULE_DEPEND(cdce, ether, 1, 1, 1); 184169695Skan 185169695Skanstatic const struct usb2_ether_methods cdce_ue_methods = { 186169695Skan .ue_attach_post = cdce_attach_post, 187169695Skan .ue_start = cdce_start, 188169695Skan .ue_init = cdce_init, 189169695Skan .ue_stop = cdce_stop, 190169695Skan .ue_setmulti = cdce_setmulti, 191169695Skan .ue_setpromisc = cdce_setpromisc, 192169695Skan}; 193169695Skan 194169695Skanstatic const struct usb2_device_id cdce_devs[] = { 195169695Skan {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_ETHERNET_NETWORKING_CONTROL_MODEL, 0)}, 196169695Skan {USB_IF_CSI(UICLASS_CDC, UISUBCLASS_MOBILE_DIRECT_LINE_MODEL, 0)}, 197169695Skan 198169695Skan {USB_VPI(USB_VENDOR_ACERLABS, USB_PRODUCT_ACERLABS_M5632, CDCE_FLAG_NO_UNION)}, 199169695Skan {USB_VPI(USB_VENDOR_AMBIT, USB_PRODUCT_AMBIT_NTL_250, CDCE_FLAG_NO_UNION)}, 200169695Skan {USB_VPI(USB_VENDOR_COMPAQ, USB_PRODUCT_COMPAQ_IPAQLINUX, CDCE_FLAG_NO_UNION)}, 201169695Skan {USB_VPI(USB_VENDOR_GMATE, USB_PRODUCT_GMATE_YP3X00, CDCE_FLAG_NO_UNION)}, 202169695Skan {USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 203169695Skan {USB_VPI(USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_USBLAN2, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 204169695Skan {USB_VPI(USB_VENDOR_NETCHIP, USB_PRODUCT_NETCHIP_ETHERNETGADGET, CDCE_FLAG_NO_UNION)}, 205169695Skan {USB_VPI(USB_VENDOR_PROLIFIC, USB_PRODUCT_PROLIFIC_PL2501, CDCE_FLAG_NO_UNION)}, 206169695Skan {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5500, CDCE_FLAG_ZAURUS)}, 207169695Skan {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SL5600, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 208169695Skan {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLA300, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 209169695Skan {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC700, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 210169695Skan {USB_VPI(USB_VENDOR_SHARP, USB_PRODUCT_SHARP_SLC750, CDCE_FLAG_ZAURUS | CDCE_FLAG_NO_UNION)}, 211169695Skan}; 212169695Skan 213169695Skanstatic int 214169695Skancdce_probe(device_t dev) 215169695Skan{ 216169695Skan struct usb2_attach_arg *uaa = device_get_ivars(dev); 217169695Skan 218169695Skan return (usb2_lookup_id_by_uaa(cdce_devs, sizeof(cdce_devs), uaa)); 219169695Skan} 220169695Skan 221169695Skanstatic void 222169695Skancdce_attach_post(struct usb2_ether *ue) 223169695Skan{ 224169695Skan /* no-op */ 225169695Skan return; 226169695Skan} 227169695Skan 228169695Skanstatic int 229169695Skancdce_attach(device_t dev) 230169695Skan{ 231169695Skan struct cdce_softc *sc = device_get_softc(dev); 232169695Skan struct usb2_ether *ue = &sc->sc_ue; 233169695Skan struct usb2_attach_arg *uaa = device_get_ivars(dev); 234169695Skan struct usb2_interface *iface; 235169695Skan const struct usb2_cdc_union_descriptor *ud; 236169695Skan const struct usb2_interface_descriptor *id; 237169695Skan const struct usb2_cdc_ethernet_descriptor *ued; 238169695Skan int error; 239169695Skan uint8_t i; 240169695Skan char eaddr_str[5 * ETHER_ADDR_LEN]; /* approx */ 241169695Skan 242169695Skan sc->sc_flags = USB_GET_DRIVER_INFO(uaa); 243169695Skan 244169695Skan device_set_usb2_desc(dev); 245169695Skan 246169695Skan mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 247169695Skan 248169695Skan if (sc->sc_flags & CDCE_FLAG_NO_UNION) { 249169695Skan sc->sc_ifaces_index[0] = uaa->info.bIfaceIndex; 250169695Skan sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 251169695Skan sc->sc_data_iface_no = 0; /* not used */ 252169695Skan goto alloc_transfers; 253169695Skan } 254169695Skan ud = usb2_find_descriptor 255169695Skan (uaa->device, NULL, uaa->info.bIfaceIndex, 256169695Skan UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_UNION, 0 - 1); 257169695Skan 258169695Skan if ((ud == NULL) || (ud->bLength < sizeof(*ud))) { 259169695Skan device_printf(dev, "no union descriptor!\n"); 260169695Skan goto detach; 261169695Skan } 262169695Skan sc->sc_data_iface_no = ud->bSlaveInterface[0]; 263169695Skan 264169695Skan for (i = 0;; i++) { 265169695Skan 266169695Skan iface = usb2_get_iface(uaa->device, i); 267169695Skan 268169695Skan if (iface) { 269169695Skan 270169695Skan id = usb2_get_interface_descriptor(iface); 271169695Skan 272169695Skan if (id && (id->bInterfaceNumber == 273169695Skan sc->sc_data_iface_no)) { 274169695Skan sc->sc_ifaces_index[0] = i; 275169695Skan sc->sc_ifaces_index[1] = uaa->info.bIfaceIndex; 276169695Skan usb2_set_parent_iface(uaa->device, i, uaa->info.bIfaceIndex); 277169695Skan break; 278169695Skan } 279169695Skan } else { 280169695Skan device_printf(dev, "no data interface found!\n"); 281169695Skan goto detach; 282169695Skan } 283169695Skan } 284169695Skan 285169695Skan /* 286169695Skan * <quote> 287169695Skan * 288169695Skan * The Data Class interface of a networking device shall have 289169695Skan * a minimum of two interface settings. The first setting 290169695Skan * (the default interface setting) includes no endpoints and 291169695Skan * therefore no networking traffic is exchanged whenever the 292169695Skan * default interface setting is selected. One or more 293169695Skan * additional interface settings are used for normal 294169695Skan * operation, and therefore each includes a pair of endpoints 295169695Skan * (one IN, and one OUT) to exchange network traffic. Select 296169695Skan * an alternate interface setting to initialize the network 297169695Skan * aspects of the device and to enable the exchange of 298169695Skan * network traffic. 299169695Skan * 300169695Skan * </quote> 301169695Skan * 302169695Skan * Some devices, most notably cable modems, include interface 303169695Skan * settings that have no IN or OUT endpoint, therefore loop 304169695Skan * through the list of all available interface settings 305169695Skan * looking for one with both IN and OUT endpoints. 306169695Skan */ 307169695Skan 308169695Skanalloc_transfers: 309169695Skan 310169695Skan for (i = 0; i != 32; i++) { 311169695Skan 312169695Skan error = usb2_set_alt_interface_index 313169695Skan (uaa->device, sc->sc_ifaces_index[0], i); 314169695Skan 315169695Skan if (error) { 316169695Skan device_printf(dev, "no valid alternate " 317169695Skan "setting found!\n"); 318169695Skan goto detach; 319169695Skan } 320169695Skan error = usb2_transfer_setup 321169695Skan (uaa->device, sc->sc_ifaces_index, 322169695Skan sc->sc_xfer, cdce_config, CDCE_N_TRANSFER, 323169695Skan sc, &sc->sc_mtx); 324169695Skan 325169695Skan if (error == 0) { 326169695Skan break; 327169695Skan } 328169695Skan } 329169695Skan 330169695Skan ued = usb2_find_descriptor 331169695Skan (uaa->device, NULL, uaa->info.bIfaceIndex, 332169695Skan UDESC_CS_INTERFACE, 0 - 1, UDESCSUB_CDC_ENF, 0 - 1); 333169695Skan 334169695Skan if ((ued == NULL) || (ued->bLength < sizeof(*ued))) { 335169695Skan error = USB_ERR_INVAL; 336169695Skan } else { 337169695Skan error = usb2_req_get_string_any(uaa->device, NULL, 338169695Skan eaddr_str, sizeof(eaddr_str), ued->iMacAddress); 339169695Skan } 340169695Skan 341169695Skan if (error) { 342169695Skan 343169695Skan /* fake MAC address */ 344169695Skan 345169695Skan device_printf(dev, "faking MAC address\n"); 346169695Skan sc->sc_ue.ue_eaddr[0] = 0x2a; 347169695Skan memcpy(&sc->sc_ue.ue_eaddr[1], &ticks, sizeof(uint32_t)); 348169695Skan sc->sc_ue.ue_eaddr[5] = device_get_unit(dev); 349169695Skan 350169695Skan } else { 351169695Skan 352169695Skan bzero(sc->sc_ue.ue_eaddr, sizeof(sc->sc_ue.ue_eaddr)); 353169695Skan 354169695Skan for (i = 0; i != (ETHER_ADDR_LEN * 2); i++) { 355169695Skan 356169695Skan char c = eaddr_str[i]; 357169695Skan 358169695Skan if ('0' <= c && c <= '9') 359169695Skan c -= '0'; 360169695Skan else if (c != 0) 361169695Skan c -= 'A' - 10; 362169695Skan else 363169695Skan break; 364169695Skan 365169695Skan c &= 0xf; 366169695Skan 367169695Skan if ((i & 1) == 0) 368169695Skan c <<= 4; 369169695Skan sc->sc_ue.ue_eaddr[i / 2] |= c; 370169695Skan } 371169695Skan 372169695Skan if (uaa->usb2_mode == USB_MODE_DEVICE) { 373169695Skan /* 374169695Skan * Do not use the same MAC address like the peer ! 375169695Skan */ 376169695Skan sc->sc_ue.ue_eaddr[5] ^= 0xFF; 377169695Skan } 378169695Skan } 379169695Skan 380169695Skan ue->ue_sc = sc; 381169695Skan ue->ue_dev = dev; 382169695Skan ue->ue_udev = uaa->device; 383169695Skan ue->ue_mtx = &sc->sc_mtx; 384169695Skan ue->ue_methods = &cdce_ue_methods; 385169695Skan 386169695Skan error = usb2_ether_ifattach(ue); 387169695Skan if (error) { 388169695Skan device_printf(dev, "could not attach interface\n"); 389169695Skan goto detach; 390169695Skan } 391169695Skan return (0); /* success */ 392169695Skan 393169695Skandetach: 394169695Skan cdce_detach(dev); 395169695Skan return (ENXIO); /* failure */ 396169695Skan} 397169695Skan 398169695Skanstatic int 399169695Skancdce_detach(device_t dev) 400169695Skan{ 401169695Skan struct cdce_softc *sc = device_get_softc(dev); 402169695Skan struct usb2_ether *ue = &sc->sc_ue; 403169695Skan 404169695Skan /* stop all USB transfers first */ 405169695Skan usb2_transfer_unsetup(sc->sc_xfer, CDCE_N_TRANSFER); 406169695Skan usb2_ether_ifdetach(ue); 407169695Skan mtx_destroy(&sc->sc_mtx); 408169695Skan 409169695Skan return (0); 410169695Skan} 411169695Skan 412169695Skanstatic void 413169695Skancdce_start(struct usb2_ether *ue) 414169695Skan{ 415169695Skan struct cdce_softc *sc = usb2_ether_getsc(ue); 416169695Skan 417169695Skan /* 418169695Skan * Start the USB transfers, if not already started: 419169695Skan */ 420169695Skan usb2_transfer_start(sc->sc_xfer[CDCE_BULK_B]); 421169695Skan usb2_transfer_start(sc->sc_xfer[CDCE_BULK_A]); 422169695Skan} 423169695Skan 424169695Skanstatic void 425169695Skancdce_free_queue(struct mbuf **ppm, uint8_t n) 426169695Skan{ 427169695Skan uint8_t x; 428169695Skan for (x = 0; x != n; x++) { 429169695Skan if (ppm[x] != NULL) { 430169695Skan m_freem(ppm[x]); 431169695Skan ppm[x] = NULL; 432169695Skan } 433169695Skan } 434169695Skan} 435169695Skan 436169695Skanstatic void 437169695Skancdce_bulk_write_callback(struct usb2_xfer *xfer) 438169695Skan{ 439169695Skan struct cdce_softc *sc = xfer->priv_sc; 440169695Skan struct ifnet *ifp = usb2_ether_getifp(&sc->sc_ue); 441169695Skan struct mbuf *m; 442169695Skan struct mbuf *mt; 443169695Skan uint32_t crc; 444169695Skan uint8_t x; 445169695Skan 446169695Skan DPRINTFN(1, "\n"); 447169695Skan 448169695Skan switch (USB_GET_STATE(xfer)) { 449169695Skan case USB_ST_TRANSFERRED: 450169695Skan DPRINTFN(11, "transfer complete: " 451169695Skan "%u bytes in %u frames\n", xfer->actlen, 452169695Skan xfer->aframes); 453169695Skan 454169695Skan ifp->if_opackets++; 455169695Skan 456169695Skan /* free all previous TX buffers */ 457169695Skan cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX); 458169695Skan 459169695Skan /* FALLTHROUGH */ 460169695Skan case USB_ST_SETUP: 461169695Skantr_setup: 462169695Skan for (x = 0; x != CDCE_FRAMES_MAX; x++) { 463169695Skan 464169695Skan IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 465169695Skan 466169695Skan if (m == NULL) 467169695Skan break; 468169695Skan 469169695Skan if (sc->sc_flags & CDCE_FLAG_ZAURUS) { 470169695Skan /* 471169695Skan * Zaurus wants a 32-bit CRC appended 472169695Skan * to every frame 473169695Skan */ 474169695Skan 475169695Skan crc = cdce_m_crc32(m, 0, m->m_pkthdr.len); 476169695Skan crc = htole32(crc); 477169695Skan 478169695Skan if (!m_append(m, 4, (void *)&crc)) { 479169695Skan m_freem(m); 480169695Skan ifp->if_oerrors++; 481169695Skan continue; 482169695Skan } 483169695Skan } 484169695Skan if (m->m_len != m->m_pkthdr.len) { 485169695Skan mt = m_defrag(m, M_DONTWAIT); 486169695Skan if (mt == NULL) { 487169695Skan m_freem(m); 488169695Skan ifp->if_oerrors++; 489169695Skan continue; 490169695Skan } 491169695Skan m = mt; 492169695Skan } 493169695Skan if (m->m_pkthdr.len > MCLBYTES) { 494169695Skan m->m_pkthdr.len = MCLBYTES; 495169695Skan } 496169695Skan sc->sc_tx_buf[x] = m; 497169695Skan xfer->frlengths[x] = m->m_len; 498169695Skan usb2_set_frame_data(xfer, m->m_data, x); 499169695Skan 500169695Skan /* 501169695Skan * If there's a BPF listener, bounce a copy of 502169695Skan * this frame to him: 503169695Skan */ 504169695Skan BPF_MTAP(ifp, m); 505169695Skan } 506169695Skan if (x != 0) { 507169695Skan xfer->nframes = x; 508169695Skan usb2_start_hardware(xfer); 509169695Skan } 510169695Skan break; 511169695Skan 512169695Skan default: /* Error */ 513169695Skan DPRINTFN(11, "transfer error, %s\n", 514169695Skan usb2_errstr(xfer->error)); 515169695Skan 516169695Skan /* free all previous TX buffers */ 517169695Skan cdce_free_queue(sc->sc_tx_buf, CDCE_FRAMES_MAX); 518169695Skan 519169695Skan /* count output errors */ 520169695Skan ifp->if_oerrors++; 521169695Skan 522169695Skan if (xfer->error != USB_ERR_CANCELLED) { 523169695Skan /* try to clear stall first */ 524169695Skan xfer->flags.stall_pipe = 1; 525169695Skan goto tr_setup; 526169695Skan } 527169695Skan break; 528169695Skan } 529169695Skan} 530169695Skan 531169695Skanstatic int32_t 532169695Skancdce_m_crc32_cb(void *arg, void *src, uint32_t count) 533169695Skan{ 534169695Skan uint32_t *p_crc = arg; 535169695Skan 536169695Skan *p_crc = crc32_raw(src, count, *p_crc); 537169695Skan return (0); 538169695Skan} 539169695Skan 540169695Skanstatic uint32_t 541169695Skancdce_m_crc32(struct mbuf *m, uint32_t src_offset, uint32_t src_len) 542169695Skan{ 543169695Skan uint32_t crc = 0xFFFFFFFF; 544169695Skan int error; 545169695Skan 546169695Skan error = m_apply(m, src_offset, src_len, cdce_m_crc32_cb, &crc); 547169695Skan return (crc ^ 0xFFFFFFFF); 548169695Skan} 549169695Skan 550169695Skanstatic void 551169695Skancdce_init(struct usb2_ether *ue) 552169695Skan{ 553169695Skan struct cdce_softc *sc = usb2_ether_getsc(ue); 554169695Skan struct ifnet *ifp = usb2_ether_getifp(ue); 555169695Skan 556169695Skan CDCE_LOCK_ASSERT(sc, MA_OWNED); 557169695Skan 558169695Skan ifp->if_drv_flags |= IFF_DRV_RUNNING; 559169695Skan 560169695Skan /* start interrupt transfer */ 561169695Skan usb2_transfer_start(sc->sc_xfer[CDCE_INTR]); 562169695Skan 563169695Skan /* stall data write direction, which depends on USB mode */ 564169695Skan if (usb2_get_mode(sc->sc_ue.ue_udev) == USB_MODE_HOST) 565169695Skan usb2_transfer_set_stall(sc->sc_xfer[CDCE_BULK_A]); 566169695Skan else 567169695Skan usb2_transfer_set_stall(sc->sc_xfer[CDCE_BULK_B]); 568169695Skan 569169695Skan /* start data transfers */ 570169695Skan cdce_start(ue); 571169695Skan} 572169695Skan 573169695Skanstatic void 574169695Skancdce_stop(struct usb2_ether *ue) 575169695Skan{ 576169695Skan struct cdce_softc *sc = usb2_ether_getsc(ue); 577169695Skan struct ifnet *ifp = usb2_ether_getifp(ue); 578169695Skan 579169695Skan CDCE_LOCK_ASSERT(sc, MA_OWNED); 580169695Skan 581169695Skan ifp->if_drv_flags &= ~IFF_DRV_RUNNING; 582169695Skan 583169695Skan /* 584169695Skan * stop all the transfers, if not already stopped: 585169695Skan */ 586169695Skan usb2_transfer_stop(sc->sc_xfer[CDCE_BULK_A]); 587169695Skan usb2_transfer_stop(sc->sc_xfer[CDCE_BULK_B]); 588169695Skan usb2_transfer_stop(sc->sc_xfer[CDCE_INTR]); 589169695Skan} 590169695Skan 591169695Skanstatic void 592169695Skancdce_setmulti(struct usb2_ether *ue) 593169695Skan{ 594169695Skan /* no-op */ 595169695Skan return; 596169695Skan} 597169695Skan 598169695Skanstatic void 599169695Skancdce_setpromisc(struct usb2_ether *ue) 600169695Skan{ 601169695Skan /* no-op */ 602169695Skan return; 603169695Skan} 604169695Skan 605169695Skanstatic int 606169695Skancdce_shutdown(device_t dev) 607169695Skan{ 608169695Skan struct cdce_softc *sc = device_get_softc(dev); 609169695Skan 610169695Skan usb2_ether_ifshutdown(&sc->sc_ue); 611169695Skan 612169695Skan return (0); 613169695Skan} 614169695Skan 615169695Skanstatic int 616169695Skancdce_suspend(device_t dev) 617169695Skan{ 618169695Skan device_printf(dev, "Suspending\n"); 619169695Skan return (0); 620169695Skan} 621169695Skan 622169695Skanstatic int 623169695Skancdce_resume(device_t dev) 624169695Skan{ 625169695Skan device_printf(dev, "Resuming\n"); 626169695Skan return (0); 627169695Skan} 628169695Skan 629169695Skanstatic void 630169695Skancdce_bulk_read_callback(struct usb2_xfer *xfer) 631169695Skan{ 632169695Skan struct cdce_softc *sc = xfer->priv_sc; 633169695Skan struct mbuf *m; 634169695Skan uint8_t x; 635169695Skan 636169695Skan switch (USB_GET_STATE(xfer)) { 637169695Skan case USB_ST_TRANSFERRED: 638169695Skan 639169695Skan DPRINTF("received %u bytes in %u frames\n", 640169695Skan xfer->actlen, xfer->aframes); 641169695Skan 642169695Skan for (x = 0; x != xfer->aframes; x++) { 643169695Skan 644169695Skan m = sc->sc_rx_buf[x]; 645169695Skan sc->sc_rx_buf[x] = NULL; 646169695Skan 647169695Skan /* Strip off CRC added by Zaurus, if any */ 648169695Skan if ((sc->sc_flags & CDCE_FLAG_ZAURUS) && 649169695Skan (xfer->frlengths[x] >= 14)) 650169695Skan xfer->frlengths[x] -= 4; 651169695Skan 652169695Skan if (xfer->frlengths[x] < sizeof(struct ether_header)) { 653169695Skan m_freem(m); 654169695Skan continue; 655169695Skan } 656169695Skan /* queue up mbuf */ 657169695Skan usb2_ether_rxmbuf(&sc->sc_ue, m, xfer->frlengths[x]); 658169695Skan } 659169695Skan 660169695Skan /* FALLTHROUGH */ 661169695Skan case USB_ST_SETUP: 662169695Skan /* 663169695Skan * TODO: Implement support for multi frame transfers, 664169695Skan * when the USB hardware supports it. 665169695Skan */ 666169695Skan for (x = 0; x != 1; x++) { 667169695Skan if (sc->sc_rx_buf[x] == NULL) { 668169695Skan m = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); 669169695Skan if (m == NULL) 670169695Skan goto tr_stall; 671169695Skan sc->sc_rx_buf[x] = m; 672169695Skan /* adjust for ethernet */ 673169695Skan m->m_len = m->m_pkthdr.len = MCLBYTES; 674169695Skan m_adj(m, ETHER_ALIGN); 675169695Skan } else { 676169695Skan m = sc->sc_rx_buf[x]; 677169695Skan } 678169695Skan 679169695Skan usb2_set_frame_data(xfer, m->m_data, x); 680169695Skan xfer->frlengths[x] = m->m_len; 681169695Skan } 682169695Skan /* set number of frames and start hardware */ 683169695Skan xfer->nframes = x; 684169695Skan usb2_start_hardware(xfer); 685169695Skan /* flush any received frames */ 686169695Skan usb2_ether_rxflush(&sc->sc_ue); 687169695Skan break; 688169695Skan 689169695Skan default: /* Error */ 690169695Skan DPRINTF("error = %s\n", 691169695Skan usb2_errstr(xfer->error)); 692169695Skan 693169695Skan if (xfer->error != USB_ERR_CANCELLED) { 694169695Skantr_stall: 695169695Skan /* try to clear stall first */ 696169695Skan xfer->flags.stall_pipe = 1; 697169695Skan xfer->nframes = 0; 698169695Skan usb2_start_hardware(xfer); 699169695Skan break; 700169695Skan } 701169695Skan 702169695Skan /* need to free the RX-mbufs when we are cancelled */ 703169695Skan cdce_free_queue(sc->sc_rx_buf, CDCE_FRAMES_MAX); 704169695Skan break; 705169695Skan } 706169695Skan} 707169695Skan 708169695Skanstatic void 709169695Skancdce_intr_read_callback(struct usb2_xfer *xfer) 710169695Skan{ 711169695Skan ; /* style fix */ 712169695Skan switch (USB_GET_STATE(xfer)) { 713169695Skan case USB_ST_TRANSFERRED: 714169695Skan 715169695Skan DPRINTF("Received %d bytes\n", 716169695Skan xfer->actlen); 717169695Skan 718169695Skan /* TODO: decode some indications */ 719169695Skan 720169695Skan /* FALLTHROUGH */ 721169695Skan case USB_ST_SETUP: 722169695Skantr_setup: 723169695Skan xfer->frlengths[0] = xfer->max_data_length; 724169695Skan usb2_start_hardware(xfer); 725169695Skan break; 726169695Skan 727169695Skan default: /* Error */ 728169695Skan if (xfer->error != USB_ERR_CANCELLED) { 729169695Skan /* start clear stall */ 730169695Skan xfer->flags.stall_pipe = 1; 731169695Skan goto tr_setup; 732169695Skan } 733169695Skan break; 734169695Skan } 735169695Skan} 736169695Skan 737169695Skanstatic void 738169695Skancdce_intr_write_callback(struct usb2_xfer *xfer) 739169695Skan{ 740169695Skan ; /* style fix */ 741169695Skan switch (USB_GET_STATE(xfer)) { 742169695Skan case USB_ST_TRANSFERRED: 743169695Skan 744169695Skan DPRINTF("Transferred %d bytes\n", xfer->actlen); 745169695Skan 746169695Skan /* FALLTHROUGH */ 747169695Skan case USB_ST_SETUP: 748169695Skantr_setup: 749169695Skan#if 0 750169695Skan xfer->frlengths[0] = XXX; 751169695Skan usb2_start_hardware(xfer); 752169695Skan#endif 753169695Skan break; 754169695Skan 755169695Skan default: /* Error */ 756169695Skan if (xfer->error != USB_ERR_CANCELLED) { 757169695Skan /* start clear stall */ 758169695Skan xfer->flags.stall_pipe = 1; 759169695Skan goto tr_setup; 760169695Skan } 761169695Skan break; 762169695Skan } 763169695Skan} 764169695Skan 765169695Skanstatic int 766169695Skancdce_handle_request(device_t dev, 767169695Skan const void *req, void **pptr, uint16_t *plen, 768169695Skan uint16_t offset, uint8_t is_complete) 769169695Skan{ 770169695Skan return (ENXIO); /* use builtin handler */ 771169695Skan} 772169695Skan