urio.c revision 184610
1184610Salfred/*- 2184610Salfred * Copyright (c) 2000 Iwasa Kazmi 3184610Salfred * All rights reserved. 4184610Salfred * 5184610Salfred * Redistribution and use in source and binary forms, with or without 6184610Salfred * modification, are permitted provided that the following conditions 7184610Salfred * are met: 8184610Salfred * 1. Redistributions of source code must retain the above copyright 9184610Salfred * notice, this list of conditions, and the following disclaimer. 10184610Salfred * 2. Redistributions in binary form must reproduce the above copyright 11184610Salfred * notice, this list of conditions and the following disclaimer in the 12184610Salfred * documentation and/or other materials provided with the distribution. 13184610Salfred * 14184610Salfred * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15184610Salfred * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16184610Salfred * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17184610Salfred * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 18184610Salfred * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19184610Salfred * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20184610Salfred * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21184610Salfred * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22184610Salfred * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23184610Salfred * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24184610Salfred * SUCH DAMAGE. 25184610Salfred * 26184610Salfred * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson. 27184610Salfred * This code includes software developed by the NetBSD Foundation, Inc. and 28184610Salfred * its contributors. 29184610Salfred */ 30184610Salfred 31184610Salfred#include <sys/cdefs.h> 32184610Salfred__FBSDID("$FreeBSD: head/sys/dev/usb2/storage/urio2.c 184610 2008-11-04 02:31:03Z alfred $"); 33184610Salfred 34184610Salfred 35184610Salfred/* 36184610Salfred * 2000/3/24 added NetBSD/OpenBSD support (from Alex Nemirovsky) 37184610Salfred * 2000/3/07 use two bulk-pipe handles for read and write (Dirk) 38184610Salfred * 2000/3/06 change major number(143), and copyright header 39184610Salfred * some fix for 4.0 (Dirk) 40184610Salfred * 2000/3/05 codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik) 41184610Salfred * 2000/3/01 remove retry code from urioioctl() 42184610Salfred * change method of bulk transfer (no interrupt) 43184610Salfred * 2000/2/28 small fixes for new rio_usb.h 44184610Salfred * 2000/2/24 first version. 45184610Salfred */ 46184610Salfred 47184610Salfred#include <dev/usb2/include/usb2_devid.h> 48184610Salfred#include <dev/usb2/include/usb2_standard.h> 49184610Salfred#include <dev/usb2/include/usb2_mfunc.h> 50184610Salfred#include <dev/usb2/include/usb2_error.h> 51184610Salfred#include <dev/usb2/include/usb2_ioctl.h> 52184610Salfred#include <dev/usb2/include/urio2_ioctl.h> 53184610Salfred 54184610Salfred#define USB_DEBUG_VAR urio_debug 55184610Salfred 56184610Salfred#include <dev/usb2/core/usb2_core.h> 57184610Salfred#include <dev/usb2/core/usb2_debug.h> 58184610Salfred#include <dev/usb2/core/usb2_process.h> 59184610Salfred#include <dev/usb2/core/usb2_config_td.h> 60184610Salfred#include <dev/usb2/core/usb2_request.h> 61184610Salfred#include <dev/usb2/core/usb2_lookup.h> 62184610Salfred#include <dev/usb2/core/usb2_util.h> 63184610Salfred#include <dev/usb2/core/usb2_busdma.h> 64184610Salfred#include <dev/usb2/core/usb2_mbuf.h> 65184610Salfred#include <dev/usb2/core/usb2_dev.h> 66184610Salfred#include <dev/usb2/core/usb2_generic.h> 67184610Salfred 68184610Salfred#if USB_DEBUG 69184610Salfredstatic int urio_debug = 0; 70184610Salfred 71184610SalfredSYSCTL_NODE(_hw_usb2, OID_AUTO, urio, CTLFLAG_RW, 0, "USB urio"); 72184610SalfredSYSCTL_INT(_hw_usb2_urio, OID_AUTO, debug, CTLFLAG_RW, 73184610Salfred &urio_debug, 0, "urio debug level"); 74184610Salfred#endif 75184610Salfred 76184610Salfred#define URIO_T_WR 0 77184610Salfred#define URIO_T_RD 1 78184610Salfred#define URIO_T_WR_CS 2 79184610Salfred#define URIO_T_RD_CS 3 80184610Salfred#define URIO_T_MAX 4 81184610Salfred 82184610Salfred#define URIO_BSIZE (1<<12) /* bytes */ 83184610Salfred#define URIO_IFQ_MAXLEN 2 /* units */ 84184610Salfred 85184610Salfredstruct urio_softc { 86184610Salfred struct usb2_fifo_sc sc_fifo; 87184610Salfred struct mtx sc_mtx; 88184610Salfred 89184610Salfred struct usb2_device *sc_udev; 90184610Salfred struct usb2_xfer *sc_xfer[URIO_T_MAX]; 91184610Salfred 92184610Salfred uint8_t sc_flags; 93184610Salfred#define URIO_FLAG_READ_STALL 0x01 /* read transfer stalled */ 94184610Salfred#define URIO_FLAG_WRITE_STALL 0x02 /* write transfer stalled */ 95184610Salfred 96184610Salfred uint8_t sc_name[16]; 97184610Salfred}; 98184610Salfred 99184610Salfred/* prototypes */ 100184610Salfred 101184610Salfredstatic device_probe_t urio_probe; 102184610Salfredstatic device_attach_t urio_attach; 103184610Salfredstatic device_detach_t urio_detach; 104184610Salfred 105184610Salfredstatic usb2_callback_t urio_write_callback; 106184610Salfredstatic usb2_callback_t urio_write_clear_stall_callback; 107184610Salfredstatic usb2_callback_t urio_read_callback; 108184610Salfredstatic usb2_callback_t urio_read_clear_stall_callback; 109184610Salfred 110184610Salfredstatic usb2_fifo_close_t urio_close; 111184610Salfredstatic usb2_fifo_cmd_t urio_start_read; 112184610Salfredstatic usb2_fifo_cmd_t urio_start_write; 113184610Salfredstatic usb2_fifo_cmd_t urio_stop_read; 114184610Salfredstatic usb2_fifo_cmd_t urio_stop_write; 115184610Salfredstatic usb2_fifo_ioctl_t urio_ioctl; 116184610Salfredstatic usb2_fifo_open_t urio_open; 117184610Salfred 118184610Salfredstatic struct usb2_fifo_methods urio_fifo_methods = { 119184610Salfred .f_close = &urio_close, 120184610Salfred .f_ioctl = &urio_ioctl, 121184610Salfred .f_open = &urio_open, 122184610Salfred .f_start_read = &urio_start_read, 123184610Salfred .f_start_write = &urio_start_write, 124184610Salfred .f_stop_read = &urio_stop_read, 125184610Salfred .f_stop_write = &urio_stop_write, 126184610Salfred .basename[0] = "urio", 127184610Salfred}; 128184610Salfred 129184610Salfredstatic const struct usb2_config urio_config[URIO_T_MAX] = { 130184610Salfred [URIO_T_WR] = { 131184610Salfred .type = UE_BULK, 132184610Salfred .endpoint = UE_ADDR_ANY, 133184610Salfred .direction = UE_DIR_OUT, 134184610Salfred .mh.bufsize = URIO_BSIZE, 135184610Salfred .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,}, 136184610Salfred .mh.callback = &urio_write_callback, 137184610Salfred }, 138184610Salfred 139184610Salfred [URIO_T_RD] = { 140184610Salfred .type = UE_BULK, 141184610Salfred .endpoint = UE_ADDR_ANY, 142184610Salfred .direction = UE_DIR_IN, 143184610Salfred .mh.bufsize = URIO_BSIZE, 144184610Salfred .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,}, 145184610Salfred .mh.callback = &urio_read_callback, 146184610Salfred }, 147184610Salfred 148184610Salfred [URIO_T_WR_CS] = { 149184610Salfred .type = UE_CONTROL, 150184610Salfred .endpoint = 0x00, /* Control pipe */ 151184610Salfred .direction = UE_DIR_ANY, 152184610Salfred .mh.bufsize = sizeof(struct usb2_device_request), 153184610Salfred .mh.flags = {}, 154184610Salfred .mh.callback = &urio_write_clear_stall_callback, 155184610Salfred .mh.timeout = 1000, /* 1 second */ 156184610Salfred .mh.interval = 50, /* 50ms */ 157184610Salfred }, 158184610Salfred 159184610Salfred [URIO_T_RD_CS] = { 160184610Salfred .type = UE_CONTROL, 161184610Salfred .endpoint = 0x00, /* Control pipe */ 162184610Salfred .direction = UE_DIR_ANY, 163184610Salfred .mh.bufsize = sizeof(struct usb2_device_request), 164184610Salfred .mh.flags = {}, 165184610Salfred .mh.callback = &urio_read_clear_stall_callback, 166184610Salfred .mh.timeout = 1000, /* 1 second */ 167184610Salfred .mh.interval = 50, /* 50ms */ 168184610Salfred }, 169184610Salfred}; 170184610Salfred 171184610Salfredstatic devclass_t urio_devclass; 172184610Salfred 173184610Salfredstatic device_method_t urio_methods[] = { 174184610Salfred /* Device interface */ 175184610Salfred DEVMETHOD(device_probe, urio_probe), 176184610Salfred DEVMETHOD(device_attach, urio_attach), 177184610Salfred DEVMETHOD(device_detach, urio_detach), 178184610Salfred {0, 0} 179184610Salfred}; 180184610Salfred 181184610Salfredstatic driver_t urio_driver = { 182184610Salfred .name = "urio", 183184610Salfred .methods = urio_methods, 184184610Salfred .size = sizeof(struct urio_softc), 185184610Salfred}; 186184610Salfred 187184610SalfredDRIVER_MODULE(urio, ushub, urio_driver, urio_devclass, NULL, 0); 188184610SalfredMODULE_DEPEND(urio, usb2_storage, 1, 1, 1); 189184610SalfredMODULE_DEPEND(urio, usb2_core, 1, 1, 1); 190184610Salfred 191184610Salfredstatic int 192184610Salfredurio_probe(device_t dev) 193184610Salfred{ 194184610Salfred struct usb2_attach_arg *uaa = device_get_ivars(dev); 195184610Salfred 196184610Salfred if (uaa->usb2_mode != USB_MODE_HOST) { 197184610Salfred return (ENXIO); 198184610Salfred } 199184610Salfred if ((((uaa->info.idVendor == USB_VENDOR_DIAMOND) && 200184610Salfred (uaa->info.idProduct == USB_PRODUCT_DIAMOND_RIO500USB)) || 201184610Salfred ((uaa->info.idVendor == USB_VENDOR_DIAMOND2) && 202184610Salfred ((uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO600USB) || 203184610Salfred (uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO800USB))))) 204184610Salfred return (0); 205184610Salfred else 206184610Salfred return (ENXIO); 207184610Salfred} 208184610Salfred 209184610Salfredstatic int 210184610Salfredurio_attach(device_t dev) 211184610Salfred{ 212184610Salfred struct usb2_attach_arg *uaa = device_get_ivars(dev); 213184610Salfred struct urio_softc *sc = device_get_softc(dev); 214184610Salfred int error; 215184610Salfred 216184610Salfred if (sc == NULL) { 217184610Salfred return (ENOMEM); 218184610Salfred } 219184610Salfred device_set_usb2_desc(dev); 220184610Salfred 221184610Salfred sc->sc_udev = uaa->device; 222184610Salfred 223184610Salfred mtx_init(&sc->sc_mtx, "urio lock", NULL, MTX_DEF | MTX_RECURSE); 224184610Salfred 225184610Salfred snprintf(sc->sc_name, sizeof(sc->sc_name), 226184610Salfred "%s", device_get_nameunit(dev)); 227184610Salfred 228184610Salfred error = usb2_transfer_setup(uaa->device, 229184610Salfred &uaa->info.bIfaceIndex, sc->sc_xfer, 230184610Salfred urio_config, URIO_T_MAX, sc, &sc->sc_mtx); 231184610Salfred 232184610Salfred if (error) { 233184610Salfred DPRINTF("error=%s\n", usb2_errstr(error)); 234184610Salfred goto detach; 235184610Salfred } 236184610Salfred /* set interface permissions */ 237184610Salfred usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, 238184610Salfred UID_ROOT, GID_OPERATOR, 0644); 239184610Salfred 240184610Salfred error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, 241184610Salfred &urio_fifo_methods, &sc->sc_fifo, 242184610Salfred device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex); 243184610Salfred if (error) { 244184610Salfred goto detach; 245184610Salfred } 246184610Salfred return (0); /* success */ 247184610Salfred 248184610Salfreddetach: 249184610Salfred urio_detach(dev); 250184610Salfred return (ENOMEM); /* failure */ 251184610Salfred} 252184610Salfred 253184610Salfredstatic void 254184610Salfredurio_write_callback(struct usb2_xfer *xfer) 255184610Salfred{ 256184610Salfred struct urio_softc *sc = xfer->priv_sc; 257184610Salfred struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_TX]; 258184610Salfred uint32_t actlen; 259184610Salfred 260184610Salfred switch (USB_GET_STATE(xfer)) { 261184610Salfred case USB_ST_TRANSFERRED: 262184610Salfred case USB_ST_SETUP: 263184610Salfred if (sc->sc_flags & URIO_FLAG_WRITE_STALL) { 264184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_WR_CS]); 265184610Salfred return; 266184610Salfred } 267184610Salfred if (usb2_fifo_get_data(f, xfer->frbuffers, 0, 268184610Salfred xfer->max_data_length, &actlen, 0)) { 269184610Salfred 270184610Salfred xfer->frlengths[0] = actlen; 271184610Salfred usb2_start_hardware(xfer); 272184610Salfred } 273184610Salfred return; 274184610Salfred 275184610Salfred default: /* Error */ 276184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 277184610Salfred /* try to clear stall first */ 278184610Salfred sc->sc_flags |= URIO_FLAG_WRITE_STALL; 279184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_WR_CS]); 280184610Salfred } 281184610Salfred return; 282184610Salfred } 283184610Salfred} 284184610Salfred 285184610Salfredstatic void 286184610Salfredurio_write_clear_stall_callback(struct usb2_xfer *xfer) 287184610Salfred{ 288184610Salfred struct urio_softc *sc = xfer->priv_sc; 289184610Salfred struct usb2_xfer *xfer_other = sc->sc_xfer[URIO_T_WR]; 290184610Salfred 291184610Salfred if (usb2_clear_stall_callback(xfer, xfer_other)) { 292184610Salfred DPRINTF("stall cleared\n"); 293184610Salfred sc->sc_flags &= ~URIO_FLAG_WRITE_STALL; 294184610Salfred usb2_transfer_start(xfer_other); 295184610Salfred } 296184610Salfred return; 297184610Salfred} 298184610Salfred 299184610Salfredstatic void 300184610Salfredurio_read_callback(struct usb2_xfer *xfer) 301184610Salfred{ 302184610Salfred struct urio_softc *sc = xfer->priv_sc; 303184610Salfred struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_RX]; 304184610Salfred 305184610Salfred switch (USB_GET_STATE(xfer)) { 306184610Salfred case USB_ST_TRANSFERRED: 307184610Salfred usb2_fifo_put_data(f, xfer->frbuffers, 0, 308184610Salfred xfer->actlen, 1); 309184610Salfred 310184610Salfred case USB_ST_SETUP: 311184610Salfred if (sc->sc_flags & URIO_FLAG_READ_STALL) { 312184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_RD_CS]); 313184610Salfred return; 314184610Salfred } 315184610Salfred if (usb2_fifo_put_bytes_max(f) != 0) { 316184610Salfred xfer->frlengths[0] = xfer->max_data_length; 317184610Salfred usb2_start_hardware(xfer); 318184610Salfred } 319184610Salfred return; 320184610Salfred 321184610Salfred default: /* Error */ 322184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 323184610Salfred /* try to clear stall first */ 324184610Salfred sc->sc_flags |= URIO_FLAG_READ_STALL; 325184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_RD_CS]); 326184610Salfred } 327184610Salfred return; 328184610Salfred } 329184610Salfred} 330184610Salfred 331184610Salfredstatic void 332184610Salfredurio_read_clear_stall_callback(struct usb2_xfer *xfer) 333184610Salfred{ 334184610Salfred struct urio_softc *sc = xfer->priv_sc; 335184610Salfred struct usb2_xfer *xfer_other = sc->sc_xfer[URIO_T_RD]; 336184610Salfred 337184610Salfred if (usb2_clear_stall_callback(xfer, xfer_other)) { 338184610Salfred DPRINTF("stall cleared\n"); 339184610Salfred sc->sc_flags &= ~URIO_FLAG_READ_STALL; 340184610Salfred usb2_transfer_start(xfer_other); 341184610Salfred } 342184610Salfred return; 343184610Salfred} 344184610Salfred 345184610Salfredstatic void 346184610Salfredurio_start_read(struct usb2_fifo *fifo) 347184610Salfred{ 348184610Salfred struct urio_softc *sc = fifo->priv_sc0; 349184610Salfred 350184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_RD]); 351184610Salfred return; 352184610Salfred} 353184610Salfred 354184610Salfredstatic void 355184610Salfredurio_stop_read(struct usb2_fifo *fifo) 356184610Salfred{ 357184610Salfred struct urio_softc *sc = fifo->priv_sc0; 358184610Salfred 359184610Salfred usb2_transfer_stop(sc->sc_xfer[URIO_T_RD_CS]); 360184610Salfred usb2_transfer_stop(sc->sc_xfer[URIO_T_RD]); 361184610Salfred return; 362184610Salfred} 363184610Salfred 364184610Salfredstatic void 365184610Salfredurio_start_write(struct usb2_fifo *fifo) 366184610Salfred{ 367184610Salfred struct urio_softc *sc = fifo->priv_sc0; 368184610Salfred 369184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_WR]); 370184610Salfred return; 371184610Salfred} 372184610Salfred 373184610Salfredstatic void 374184610Salfredurio_stop_write(struct usb2_fifo *fifo) 375184610Salfred{ 376184610Salfred struct urio_softc *sc = fifo->priv_sc0; 377184610Salfred 378184610Salfred usb2_transfer_stop(sc->sc_xfer[URIO_T_WR_CS]); 379184610Salfred usb2_transfer_stop(sc->sc_xfer[URIO_T_WR]); 380184610Salfred return; 381184610Salfred} 382184610Salfred 383184610Salfredstatic int 384184610Salfredurio_open(struct usb2_fifo *fifo, int fflags, struct thread *td) 385184610Salfred{ 386184610Salfred struct urio_softc *sc = fifo->priv_sc0; 387184610Salfred 388184610Salfred if ((fflags & (FWRITE | FREAD)) != (FWRITE | FREAD)) { 389184610Salfred return (EACCES); 390184610Salfred } 391184610Salfred if (fflags & FREAD) { 392184610Salfred /* clear stall first */ 393184610Salfred mtx_lock(&sc->sc_mtx); 394184610Salfred sc->sc_flags |= URIO_FLAG_READ_STALL; 395184610Salfred mtx_unlock(&sc->sc_mtx); 396184610Salfred 397184610Salfred if (usb2_fifo_alloc_buffer(fifo, 398184610Salfred sc->sc_xfer[URIO_T_RD]->max_data_length, 399184610Salfred URIO_IFQ_MAXLEN)) { 400184610Salfred return (ENOMEM); 401184610Salfred } 402184610Salfred } 403184610Salfred if (fflags & FWRITE) { 404184610Salfred /* clear stall first */ 405184610Salfred sc->sc_flags |= URIO_FLAG_WRITE_STALL; 406184610Salfred 407184610Salfred if (usb2_fifo_alloc_buffer(fifo, 408184610Salfred sc->sc_xfer[URIO_T_WR]->max_data_length, 409184610Salfred URIO_IFQ_MAXLEN)) { 410184610Salfred return (ENOMEM); 411184610Salfred } 412184610Salfred } 413184610Salfred return (0); /* success */ 414184610Salfred} 415184610Salfred 416184610Salfredstatic void 417184610Salfredurio_close(struct usb2_fifo *fifo, int fflags, struct thread *td) 418184610Salfred{ 419184610Salfred if (fflags & (FREAD | FWRITE)) { 420184610Salfred usb2_fifo_free_buffer(fifo); 421184610Salfred } 422184610Salfred return; 423184610Salfred} 424184610Salfred 425184610Salfredstatic int 426184610Salfredurio_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, 427184610Salfred int fflags, struct thread *td) 428184610Salfred{ 429184610Salfred struct usb2_ctl_request ur; 430184610Salfred struct RioCommand *rio_cmd; 431184610Salfred int error; 432184610Salfred 433184610Salfred switch (cmd) { 434184610Salfred case RIO_RECV_COMMAND: 435184610Salfred if (!(fflags & FWRITE)) { 436184610Salfred error = EPERM; 437184610Salfred goto done; 438184610Salfred } 439184610Salfred bzero(&ur, sizeof(ur)); 440184610Salfred rio_cmd = addr; 441184610Salfred ur.ucr_request.bmRequestType = 442184610Salfred rio_cmd->requesttype | UT_READ_VENDOR_DEVICE; 443184610Salfred break; 444184610Salfred 445184610Salfred case RIO_SEND_COMMAND: 446184610Salfred if (!(fflags & FWRITE)) { 447184610Salfred error = EPERM; 448184610Salfred goto done; 449184610Salfred } 450184610Salfred bzero(&ur, sizeof(ur)); 451184610Salfred rio_cmd = addr; 452184610Salfred ur.ucr_request.bmRequestType = 453184610Salfred rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE; 454184610Salfred break; 455184610Salfred 456184610Salfred default: 457184610Salfred error = EINVAL; 458184610Salfred goto done; 459184610Salfred } 460184610Salfred 461184610Salfred DPRINTFN(2, "Sending command\n"); 462184610Salfred 463184610Salfred /* Send rio control message */ 464184610Salfred ur.ucr_request.bRequest = rio_cmd->request; 465184610Salfred USETW(ur.ucr_request.wValue, rio_cmd->value); 466184610Salfred USETW(ur.ucr_request.wIndex, rio_cmd->index); 467184610Salfred USETW(ur.ucr_request.wLength, rio_cmd->length); 468184610Salfred ur.ucr_data = rio_cmd->buffer; 469184610Salfred 470184610Salfred /* reuse generic USB code */ 471184610Salfred error = ugen_do_request(fifo, &ur); 472184610Salfred 473184610Salfreddone: 474184610Salfred return (error); 475184610Salfred} 476184610Salfred 477184610Salfredstatic int 478184610Salfredurio_detach(device_t dev) 479184610Salfred{ 480184610Salfred struct urio_softc *sc = device_get_softc(dev); 481184610Salfred 482184610Salfred DPRINTF("\n"); 483184610Salfred 484184610Salfred usb2_fifo_detach(&sc->sc_fifo); 485184610Salfred 486184610Salfred usb2_transfer_unsetup(sc->sc_xfer, URIO_T_MAX); 487184610Salfred 488184610Salfred mtx_destroy(&sc->sc_mtx); 489184610Salfred 490184610Salfred return (0); 491184610Salfred} 492