if_ipheth.c revision 213805
1132718Skan/*- 2169689Skan * Copyright (c) 2010 Hans Petter Selasky. All rights reserved. 3132718Skan * Copyright (c) 2009 Diego Giagio. All rights reserved. 4132718Skan * 5132718Skan * Redistribution and use in source and binary forms, with or without 6132718Skan * modification, are permitted provided that the following conditions 7132718Skan * are met: 8132718Skan * 1. Redistributions of source code must retain the above copyright 9132718Skan * notice, this list of conditions and the following disclaimer. 10132718Skan * 2. Redistributions in binary form must reproduce the above copyright 11132718Skan * notice, this list of conditions and the following disclaimer in the 12132718Skan * documentation and/or other materials provided with the distribution. 13132718Skan * 14132718Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15132718Skan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16132718Skan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17132718Skan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18132718Skan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19169689Skan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20169689Skan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21132718Skan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22169689Skan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23169689Skan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24169689Skan * SUCH DAMAGE. 25169689Skan */ 26169689Skan 27169689Skan/* 28169689Skan * Thanks to Diego Giagio for figuring out the programming details for 29169689Skan * the Apple iPhone Ethernet driver. 30169689Skan */ 31169689Skan 32169689Skan#include <sys/cdefs.h> 33169689Skan__FBSDID("$FreeBSD: head/sys/dev/usb/net/if_ipheth.c 213805 2010-10-13 21:36:42Z hselasky $"); 34169689Skan 35169689Skan#include <sys/stdint.h> 36169689Skan#include <sys/stddef.h> 37169689Skan#include <sys/param.h> 38169689Skan#include <sys/queue.h> 39169689Skan#include <sys/types.h> 40169689Skan#include <sys/systm.h> 41169689Skan#include <sys/kernel.h> 42169689Skan#include <sys/bus.h> 43169689Skan#include <sys/linker_set.h> 44169689Skan#include <sys/module.h> 45169689Skan#include <sys/lock.h> 46169689Skan#include <sys/mutex.h> 47169689Skan#include <sys/condvar.h> 48169689Skan#include <sys/sysctl.h> 49169689Skan#include <sys/sx.h> 50169689Skan#include <sys/unistd.h> 51169689Skan#include <sys/callout.h> 52169689Skan#include <sys/malloc.h> 53169689Skan#include <sys/priv.h> 54169689Skan 55169689Skan#include <dev/usb/usb.h> 56169689Skan#include <dev/usb/usbdi.h> 57169689Skan#include <dev/usb/usbdi_util.h> 58169689Skan#include "usbdevs.h" 59169689Skan 60169689Skan#define USB_DEBUG_VAR ipheth_debug 61169689Skan#include <dev/usb/usb_debug.h> 62169689Skan#include <dev/usb/usb_process.h> 63169689Skan 64169689Skan#include <dev/usb/net/usb_ethernet.h> 65169689Skan#include <dev/usb/net/if_iphethvar.h> 66169689Skan 67169689Skanstatic device_probe_t ipheth_probe; 68169689Skanstatic device_attach_t ipheth_attach; 69169689Skanstatic device_detach_t ipheth_detach; 70169689Skan 71169689Skanstatic usb_callback_t ipheth_bulk_write_callback; 72169689Skanstatic usb_callback_t ipheth_bulk_read_callback; 73169689Skan 74169689Skanstatic uether_fn_t ipheth_attach_post; 75169689Skanstatic uether_fn_t ipheth_tick; 76169689Skanstatic uether_fn_t ipheth_init; 77169689Skanstatic uether_fn_t ipheth_stop; 78169689Skanstatic uether_fn_t ipheth_start; 79169689Skanstatic uether_fn_t ipheth_setmulti; 80169689Skanstatic uether_fn_t ipheth_setpromisc; 81169689Skan 82132718Skan#ifdef USB_DEBUG 83132718Skanstatic int ipheth_debug = 0; 84132718Skan 85132718SkanSYSCTL_NODE(_hw_usb, OID_AUTO, ipheth, CTLFLAG_RW, 0, "USB iPhone ethernet"); 86132718SkanSYSCTL_INT(_hw_usb_ipheth, OID_AUTO, debug, CTLFLAG_RW, &ipheth_debug, 0, "Debug level"); 87169689Skan#endif 88132718Skan 89132718Skanstatic const struct usb_config ipheth_config[IPHETH_N_TRANSFER] = { 90132718Skan 91132718Skan [IPHETH_BULK_RX] = { 92132718Skan .type = UE_BULK, 93132718Skan .endpoint = UE_ADDR_ANY, 94132718Skan .direction = UE_DIR_RX, 95169689Skan .frames = IPHETH_RX_FRAMES_MAX, 96132718Skan .bufsize = (IPHETH_RX_FRAMES_MAX * MCLBYTES), 97132718Skan .flags = {.short_frames_ok = 1,.short_xfer_ok = 1,.ext_buffer = 1,}, 98132718Skan .callback = ipheth_bulk_read_callback, 99132718Skan .timeout = 0, /* no timeout */ 100169689Skan }, 101169689Skan 102132718Skan [IPHETH_BULK_TX] = { 103169689Skan .type = UE_BULK, 104169689Skan .endpoint = UE_ADDR_ANY, 105169689Skan .direction = UE_DIR_TX, 106132718Skan .frames = IPHETH_TX_FRAMES_MAX, 107132718Skan .bufsize = (IPHETH_TX_FRAMES_MAX * IPHETH_BUF_SIZE), 108132718Skan .flags = {.force_short_xfer = 1,}, 109132718Skan .callback = ipheth_bulk_write_callback, 110132718Skan .timeout = IPHETH_TX_TIMEOUT, 111132718Skan }, 112132718Skan}; 113132718Skan 114132718Skanstatic device_method_t ipheth_methods[] = { 115132718Skan /* Device interface */ 116169689Skan DEVMETHOD(device_probe, ipheth_probe), 117169689Skan DEVMETHOD(device_attach, ipheth_attach), 118169689Skan DEVMETHOD(device_detach, ipheth_detach), 119169689Skan 120169689Skan {0, 0} 121132718Skan}; 122132718Skan 123132718Skanstatic driver_t ipheth_driver = { 124132718Skan .name = "ipheth", 125132718Skan .methods = ipheth_methods, 126132718Skan .size = sizeof(struct ipheth_softc), 127132718Skan}; 128132718Skan 129132718Skanstatic devclass_t ipheth_devclass; 130169689Skan 131169689SkanDRIVER_MODULE(ipheth, uhub, ipheth_driver, ipheth_devclass, NULL, 0); 132169689SkanMODULE_VERSION(ipheth, 1); 133132718SkanMODULE_DEPEND(ipheth, uether, 1, 1, 1); 134132718SkanMODULE_DEPEND(ipheth, usb, 1, 1, 1); 135132718SkanMODULE_DEPEND(ipheth, ether, 1, 1, 1); 136132718Skan 137169689Skanstatic const struct usb_ether_methods ipheth_ue_methods = { 138132718Skan .ue_attach_post = ipheth_attach_post, 139132718Skan .ue_start = ipheth_start, 140169689Skan .ue_init = ipheth_init, 141132718Skan .ue_tick = ipheth_tick, 142169689Skan .ue_stop = ipheth_stop, 143169689Skan .ue_setmulti = ipheth_setmulti, 144169689Skan .ue_setpromisc = ipheth_setpromisc, 145169689Skan}; 146169689Skan 147169689Skan#define IPHETH_ID(v,p,c,sc,pt) \ 148169689Skan USB_VENDOR(v), USB_PRODUCT(p), \ 149169689Skan USB_IFACE_CLASS(c), USB_IFACE_SUBCLASS(sc), \ 150169689Skan USB_IFACE_PROTOCOL(pt) 151169689Skan 152169689Skanstatic const struct usb_device_id ipheth_devs[] = { 153169689Skan {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE, 154169689Skan IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 155169689Skan IPHETH_USBINTF_PROTO)}, 156132718Skan {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G, 157132718Skan IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 158132718Skan IPHETH_USBINTF_PROTO)}, 159132718Skan {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3GS, 160132718Skan IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 161132718Skan IPHETH_USBINTF_PROTO)}, 162132718Skan {IPHETH_ID(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_4, 163132718Skan IPHETH_USBINTF_CLASS, IPHETH_USBINTF_SUBCLASS, 164169689Skan IPHETH_USBINTF_PROTO)}, 165169689Skan}; 166132718Skan 167132718Skanstatic int 168132718Skanipheth_get_mac_addr(struct ipheth_softc *sc) 169132718Skan{ 170132718Skan struct usb_device_request req; 171132718Skan int error; 172132718Skan 173169689Skan req.bmRequestType = UT_READ_VENDOR_DEVICE; 174169689Skan req.bRequest = IPHETH_CMD_GET_MACADDR; 175169689Skan req.wValue[0] = 0; 176132718Skan req.wValue[1] = 0; 177132718Skan req.wIndex[0] = sc->sc_iface_no; 178169689Skan req.wIndex[1] = 0; 179169689Skan req.wLength[0] = ETHER_ADDR_LEN; 180169689Skan req.wLength[1] = 0; 181169689Skan 182169689Skan error = usbd_do_request(sc->sc_ue.ue_udev, NULL, &req, sc->sc_data); 183169689Skan 184169689Skan if (error) 185169689Skan return (error); 186169689Skan 187169689Skan memcpy(sc->sc_ue.ue_eaddr, sc->sc_data, ETHER_ADDR_LEN); 188169689Skan 189169689Skan return (0); 190169689Skan} 191169689Skan 192169689Skanstatic int 193169689Skanipheth_probe(device_t dev) 194169689Skan{ 195169689Skan struct usb_attach_arg *uaa = device_get_ivars(dev); 196169689Skan 197132718Skan if (uaa->usb_mode != USB_MODE_HOST) 198132718Skan return (ENXIO); 199132718Skan 200132718Skan return (usbd_lookup_id_by_uaa(ipheth_devs, sizeof(ipheth_devs), uaa)); 201169689Skan} 202132718Skan 203169689Skanstatic int 204132718Skanipheth_attach(device_t dev) 205132718Skan{ 206132718Skan struct ipheth_softc *sc = device_get_softc(dev); 207132718Skan struct usb_ether *ue = &sc->sc_ue; 208169689Skan struct usb_attach_arg *uaa = device_get_ivars(dev); 209169689Skan int error; 210169689Skan 211169689Skan sc->sc_iface_no = uaa->info.bIfaceIndex; 212132718Skan 213169689Skan device_set_usb_desc(dev); 214169689Skan 215169689Skan mtx_init(&sc->sc_mtx, device_get_nameunit(dev), NULL, MTX_DEF); 216169689Skan 217169689Skan error = usbd_set_alt_interface_index(uaa->device, 218169689Skan uaa->info.bIfaceIndex, IPHETH_ALT_INTFNUM); 219169689Skan if (error) { 220169689Skan device_printf(dev, "Cannot set alternate setting\n"); 221132718Skan goto detach; 222132718Skan } 223132718Skan error = usbd_transfer_setup(uaa->device, &sc->sc_iface_no, 224132718Skan sc->sc_xfer, ipheth_config, IPHETH_N_TRANSFER, sc, &sc->sc_mtx); 225132718Skan if (error) { 226132718Skan device_printf(dev, "Cannot setup USB transfers\n"); 227132718Skan goto detach; 228169689Skan } 229132718Skan ue->ue_sc = sc; 230132718Skan ue->ue_dev = dev; 231132718Skan ue->ue_udev = uaa->device; 232132718Skan ue->ue_mtx = &sc->sc_mtx; 233169689Skan ue->ue_methods = &ipheth_ue_methods; 234169689Skan 235169689Skan error = ipheth_get_mac_addr(sc); 236169689Skan if (error) { 237132718Skan device_printf(dev, "Cannot get MAC address\n"); 238132718Skan goto detach; 239132718Skan } 240169689Skan 241132718Skan error = uether_ifattach(ue); 242169689Skan if (error) { 243169689Skan device_printf(dev, "could not attach interface\n"); 244169689Skan goto detach; 245132718Skan } 246169689Skan return (0); /* success */ 247169689Skan 248169689Skandetach: 249169689Skan ipheth_detach(dev); 250169689Skan return (ENXIO); /* failure */ 251169689Skan} 252169689Skan 253169689Skanstatic int 254169689Skanipheth_detach(device_t dev) 255169689Skan{ 256169689Skan struct ipheth_softc *sc = device_get_softc(dev); 257169689Skan struct usb_ether *ue = &sc->sc_ue; 258169689Skan 259169689Skan /* stop all USB transfers first */ 260169689Skan usbd_transfer_unsetup(sc->sc_xfer, IPHETH_N_TRANSFER); 261169689Skan 262169689Skan uether_ifdetach(ue); 263169689Skan 264169689Skan mtx_destroy(&sc->sc_mtx); 265169689Skan 266169689Skan return (0); 267169689Skan} 268169689Skan 269169689Skanstatic void 270169689Skanipheth_start(struct usb_ether *ue) 271169689Skan{ 272169689Skan struct ipheth_softc *sc = uether_getsc(ue); 273169689Skan 274169689Skan /* 275169689Skan * Start the USB transfers, if not already started: 276169689Skan */ 277169689Skan usbd_transfer_start(sc->sc_xfer[IPHETH_BULK_TX]); 278132718Skan usbd_transfer_start(sc->sc_xfer[IPHETH_BULK_RX]); 279132718Skan} 280169689Skan 281169689Skanstatic void 282169689Skanipheth_stop(struct usb_ether *ue) 283169689Skan{ 284169689Skan struct ipheth_softc *sc = uether_getsc(ue); 285169689Skan 286169689Skan /* 287169689Skan * Stop the USB transfers, if not already stopped: 288169689Skan */ 289169689Skan usbd_transfer_stop(sc->sc_xfer[IPHETH_BULK_TX]); 290169689Skan usbd_transfer_stop(sc->sc_xfer[IPHETH_BULK_RX]); 291169689Skan} 292169689Skan 293169689Skanstatic void 294169689Skanipheth_tick(struct usb_ether *ue) 295169689Skan{ 296169689Skan struct ipheth_softc *sc = uether_getsc(ue); 297169689Skan struct usb_device_request req; 298169689Skan int error; 299169689Skan 300169689Skan req.bmRequestType = UT_READ_VENDOR_DEVICE; 301169689Skan req.bRequest = IPHETH_CMD_CARRIER_CHECK; 302169689Skan req.wValue[0] = 0; 303169689Skan req.wValue[1] = 0; 304169689Skan req.wIndex[0] = sc->sc_iface_no; 305169689Skan req.wIndex[1] = 0; 306169689Skan req.wLength[0] = IPHETH_CTRL_BUF_SIZE; 307169689Skan req.wLength[1] = 0; 308169689Skan 309169689Skan error = uether_do_request(ue, &req, sc->sc_data, IPHETH_CTRL_TIMEOUT); 310169689Skan 311169689Skan if (error) 312169689Skan return; 313169689Skan 314169689Skan sc->sc_carrier_on = 315169689Skan (sc->sc_data[0] == IPHETH_CARRIER_ON); 316169689Skan} 317169689Skan 318169689Skanstatic void 319169689Skanipheth_attach_post(struct usb_ether *ue) 320169689Skan{ 321169689Skan 322169689Skan} 323169689Skan 324169689Skanstatic void 325169689Skanipheth_init(struct usb_ether *ue) 326169689Skan{ 327169689Skan struct ipheth_softc *sc = uether_getsc(ue); 328169689Skan struct ifnet *ifp = uether_getifp(ue); 329169689Skan 330169689Skan IPHETH_LOCK_ASSERT(sc, MA_OWNED); 331169689Skan 332169689Skan ifp->if_drv_flags |= IFF_DRV_RUNNING; 333169689Skan 334169689Skan /* stall data write direction, which depends on USB mode */ 335169689Skan usbd_xfer_set_stall(sc->sc_xfer[IPHETH_BULK_TX]); 336169689Skan 337169689Skan /* start data transfers */ 338169689Skan ipheth_start(ue); 339169689Skan} 340169689Skan 341169689Skanstatic void 342169689Skanipheth_setmulti(struct usb_ether *ue) 343169689Skan{ 344169689Skan 345169689Skan} 346169689Skan 347169689Skanstatic void 348169689Skanipheth_setpromisc(struct usb_ether *ue) 349169689Skan{ 350169689Skan 351169689Skan} 352169689Skan 353169689Skanstatic void 354169689Skanipheth_free_queue(struct mbuf **ppm, uint8_t n) 355169689Skan{ 356169689Skan uint8_t x; 357169689Skan 358169689Skan for (x = 0; x != n; x++) { 359169689Skan if (ppm[x] != NULL) { 360169689Skan m_freem(ppm[x]); 361169689Skan ppm[x] = NULL; 362169689Skan } 363169689Skan } 364169689Skan} 365169689Skan 366169689Skanstatic void 367169689Skanipheth_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) 368169689Skan{ 369169689Skan struct ipheth_softc *sc = usbd_xfer_softc(xfer); 370169689Skan struct ifnet *ifp = uether_getifp(&sc->sc_ue); 371169689Skan struct usb_page_cache *pc; 372169689Skan struct mbuf *m; 373169689Skan uint8_t x; 374132718Skan int actlen; 375132718Skan int aframes; 376169689Skan 377169689Skan usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 378169689Skan 379132718Skan DPRINTFN(1, "\n"); 380169689Skan 381169689Skan switch (USB_GET_STATE(xfer)) { 382169689Skan case USB_ST_TRANSFERRED: 383132718Skan DPRINTFN(11, "transfer complete: %u bytes in %u frames\n", 384169689Skan actlen, aframes); 385169689Skan 386169689Skan ifp->if_opackets++; 387169689Skan 388169689Skan /* free all previous TX buffers */ 389169689Skan ipheth_free_queue(sc->sc_tx_buf, IPHETH_TX_FRAMES_MAX); 390132718Skan 391132718Skan /* FALLTHROUGH */ 392132718Skan case USB_ST_SETUP: 393132718Skantr_setup: 394132718Skan for (x = 0; x != IPHETH_TX_FRAMES_MAX; x++) { 395132718Skan 396132718Skan IFQ_DRV_DEQUEUE(&ifp->if_snd, m); 397132718Skan 398132718Skan if (m == NULL) 399132718Skan break; 400169689Skan 401132718Skan usbd_xfer_set_frame_offset(xfer, 402132718Skan x * IPHETH_BUF_SIZE, x); 403132718Skan 404169689Skan pc = usbd_xfer_get_frame(xfer, x); 405169689Skan 406132718Skan sc->sc_tx_buf[x] = m; 407169689Skan 408169689Skan if (m->m_pkthdr.len > IPHETH_BUF_SIZE) 409169689Skan m->m_pkthdr.len = IPHETH_BUF_SIZE; 410132718Skan 411169689Skan usbd_m_copy_in(pc, 0, m, 0, m->m_pkthdr.len); 412169689Skan 413132718Skan usbd_xfer_set_frame_len(xfer, x, IPHETH_BUF_SIZE); 414132718Skan 415169689Skan if (IPHETH_BUF_SIZE != m->m_pkthdr.len) { 416169689Skan usbd_frame_zero(pc, m->m_pkthdr.len, 417169689Skan IPHETH_BUF_SIZE - m->m_pkthdr.len); 418169689Skan } 419169689Skan 420169689Skan /* 421169689Skan * If there's a BPF listener, bounce a copy of 422169689Skan * this frame to him: 423169689Skan */ 424169689Skan BPF_MTAP(ifp, m); 425169689Skan } 426169689Skan if (x != 0) { 427169689Skan usbd_xfer_set_frames(xfer, x); 428132718Skan 429132718Skan usbd_transfer_submit(xfer); 430132718Skan } 431169689Skan break; 432132718Skan 433169689Skan default: /* Error */ 434169689Skan DPRINTFN(11, "transfer error, %s\n", 435169689Skan usbd_errstr(error)); 436169689Skan 437169689Skan /* free all previous TX buffers */ 438169689Skan ipheth_free_queue(sc->sc_tx_buf, IPHETH_TX_FRAMES_MAX); 439169689Skan 440169689Skan /* count output errors */ 441169689Skan ifp->if_oerrors++; 442169689Skan 443169689Skan if (error != USB_ERR_CANCELLED) { 444169689Skan /* try to clear stall first */ 445169689Skan usbd_xfer_set_stall(xfer); 446169689Skan goto tr_setup; 447169689Skan } 448169689Skan break; 449169689Skan } 450169689Skan} 451169689Skan 452169689Skanstatic void 453169689Skanipheth_bulk_read_callback(struct usb_xfer *xfer, usb_error_t error) 454169689Skan{ 455169689Skan struct ipheth_softc *sc = usbd_xfer_softc(xfer); 456169689Skan struct mbuf *m; 457169689Skan uint8_t x; 458169689Skan int actlen; 459169689Skan int aframes; 460169689Skan int len; 461169689Skan 462169689Skan usbd_xfer_status(xfer, &actlen, NULL, &aframes, NULL); 463132718Skan 464169689Skan switch (USB_GET_STATE(xfer)) { 465132718Skan case USB_ST_TRANSFERRED: 466169689Skan 467169689Skan DPRINTF("received %u bytes in %u frames\n", actlen, aframes); 468132718Skan 469169689Skan for (x = 0; x != aframes; x++) { 470169689Skan 471132718Skan m = sc->sc_rx_buf[x]; 472132718Skan sc->sc_rx_buf[x] = NULL; 473169689Skan len = usbd_xfer_frame_len(xfer, x); 474169689Skan 475169689Skan if (len < (sizeof(struct ether_header) + 476169689Skan IPHETH_RX_ADJ)) { 477169689Skan m_freem(m); 478169689Skan continue; 479169689Skan } 480169689Skan 481169689Skan m_adj(m, IPHETH_RX_ADJ); 482169689Skan 483169689Skan /* queue up mbuf */ 484169689Skan uether_rxmbuf(&sc->sc_ue, m, len - IPHETH_RX_ADJ); 485169689Skan } 486169689Skan 487169689Skan /* FALLTHROUGH */ 488169689Skan case USB_ST_SETUP: 489169689Skan 490169689Skan for (x = 0; x != IPHETH_RX_FRAMES_MAX; x++) { 491169689Skan if (sc->sc_rx_buf[x] == NULL) { 492169689Skan m = uether_newbuf(); 493169689Skan if (m == NULL) 494169689Skan goto tr_stall; 495169689Skan 496169689Skan /* cancel alignment for ethernet */ 497169689Skan m_adj(m, ETHER_ALIGN); 498169689Skan 499169689Skan sc->sc_rx_buf[x] = m; 500169689Skan } else { 501169689Skan m = sc->sc_rx_buf[x]; 502169689Skan } 503169689Skan 504169689Skan usbd_xfer_set_frame_data(xfer, x, m->m_data, m->m_len); 505169689Skan } 506169689Skan /* set number of frames and start hardware */ 507169689Skan usbd_xfer_set_frames(xfer, x); 508169689Skan usbd_transfer_submit(xfer); 509169689Skan /* flush any received frames */ 510169689Skan uether_rxflush(&sc->sc_ue); 511169689Skan break; 512169689Skan 513169689Skan default: /* Error */ 514169689Skan DPRINTF("error = %s\n", usbd_errstr(error)); 515169689Skan 516169689Skan if (error != USB_ERR_CANCELLED) { 517169689Skan tr_stall: 518169689Skan /* try to clear stall first */ 519169689Skan usbd_xfer_set_stall(xfer); 520169689Skan usbd_xfer_set_frames(xfer, 0); 521169689Skan usbd_transfer_submit(xfer); 522169689Skan break; 523169689Skan } 524169689Skan /* need to free the RX-mbufs when we are cancelled */ 525169689Skan ipheth_free_queue(sc->sc_rx_buf, IPHETH_RX_FRAMES_MAX); 526132718Skan break; 527132718Skan } 528132718Skan} 529132718Skan