urio.c revision 188942
1127664Sbms/*- 2127664Sbms * Copyright (c) 2000 Iwasa Kazmi 3127664Sbms * All rights reserved. 4127664Sbms * 5127664Sbms * Redistribution and use in source and binary forms, with or without 6127664Sbms * modification, are permitted provided that the following conditions 7127664Sbms * are met: 8127664Sbms * 1. Redistributions of source code must retain the above copyright 9127664Sbms * notice, this list of conditions, and the following disclaimer. 10127664Sbms * 2. Redistributions in binary form must reproduce the above copyright 11127664Sbms * notice, this list of conditions and the following disclaimer in the 12146768Ssam * documentation and/or other materials provided with the distribution. 13162012Ssam * 14162012Ssam * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15162012Ssam * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16127664Sbms * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17127664Sbms * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 18127664Sbms * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19127664Sbms * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20214518Srpaulo * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21127664Sbms * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22127664Sbms * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23127664Sbms * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24127664Sbms * SUCH DAMAGE. 25127664Sbms * 26127664Sbms * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson. 27127664Sbms * This code includes software developed by the NetBSD Foundation, Inc. and 28127664Sbms * its contributors. 29127664Sbms */ 30127664Sbms 31127664Sbms#include <sys/cdefs.h> 32127664Sbms__FBSDID("$FreeBSD: head/sys/dev/usb/storage/urio.c 188942 2009-02-23 18:31:00Z thompsa $"); 33127664Sbms 34127664Sbms 35127664Sbms/* 36127664Sbms * 2000/3/24 added NetBSD/OpenBSD support (from Alex Nemirovsky) 37127664Sbms * 2000/3/07 use two bulk-pipe handles for read and write (Dirk) 38127664Sbms * 2000/3/06 change major number(143), and copyright header 39127664Sbms * some fix for 4.0 (Dirk) 40127664Sbms * 2000/3/05 codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik) 41127664Sbms * 2000/3/01 remove retry code from urioioctl() 42127664Sbms * change method of bulk transfer (no interrupt) 43127664Sbms * 2000/2/28 small fixes for new rio_usb.h 44127664Sbms * 2000/2/24 first version. 45127664Sbms */ 46146768Ssam 47146768Ssam#include "usbdevs.h" 48127664Sbms#include <dev/usb/usb.h> 49190225Srpaulo#include <dev/usb/usb_mfunc.h> 50190225Srpaulo#include <dev/usb/usb_error.h> 51252281Sdelphij#include <dev/usb/usb_ioctl.h> 52252281Sdelphij#include <dev/usb/storage/rio500_usb.h> 53252281Sdelphij 54252281Sdelphij#define USB_DEBUG_VAR urio_debug 55252281Sdelphij 56252281Sdelphij#include <dev/usb/usb_core.h> 57146768Ssam#include <dev/usb/usb_debug.h> 58146768Ssam#include <dev/usb/usb_process.h> 59127664Sbms#include <dev/usb/usb_request.h> 60172677Smlaier#include <dev/usb/usb_lookup.h> 61172677Smlaier#include <dev/usb/usb_util.h> 62172677Smlaier#include <dev/usb/usb_busdma.h> 63172677Smlaier#include <dev/usb/usb_mbuf.h> 64172677Smlaier#include <dev/usb/usb_dev.h> 65172677Smlaier#include <dev/usb/usb_generic.h> 66172677Smlaier 67172677Smlaier#if USB_DEBUG 68172677Smlaierstatic int urio_debug = 0; 69172677Smlaier 70172677SmlaierSYSCTL_NODE(_hw_usb2, OID_AUTO, urio, CTLFLAG_RW, 0, "USB urio"); 71172677SmlaierSYSCTL_INT(_hw_usb2_urio, OID_AUTO, debug, CTLFLAG_RW, 72146768Ssam &urio_debug, 0, "urio debug level"); 73146768Ssam#endif 74146768Ssam 75146768Ssam#define URIO_T_WR 0 76146768Ssam#define URIO_T_RD 1 77146768Ssam#define URIO_T_WR_CS 2 78146768Ssam#define URIO_T_RD_CS 3 79127664Sbms#define URIO_T_MAX 4 80146768Ssam 81146768Ssam#define URIO_BSIZE (1<<12) /* bytes */ 82146768Ssam#define URIO_IFQ_MAXLEN 2 /* units */ 83127664Sbms 84127664Sbmsstruct urio_softc { 85127664Sbms struct usb2_fifo_sc sc_fifo; 86127664Sbms struct mtx sc_mtx; 87127664Sbms 88127664Sbms struct usb2_device *sc_udev; 89127664Sbms struct usb2_xfer *sc_xfer[URIO_T_MAX]; 90127664Sbms 91172677Smlaier uint8_t sc_flags; 92172677Smlaier#define URIO_FLAG_READ_STALL 0x01 /* read transfer stalled */ 93172677Smlaier#define URIO_FLAG_WRITE_STALL 0x02 /* write transfer stalled */ 94172677Smlaier 95127664Sbms uint8_t sc_name[16]; 96127664Sbms}; 97127664Sbms 98127664Sbms/* prototypes */ 99127664Sbms 100127664Sbmsstatic device_probe_t urio_probe; 101146768Ssamstatic device_attach_t urio_attach; 102146768Ssamstatic device_detach_t urio_detach; 103146768Ssam 104146768Ssamstatic usb2_callback_t urio_write_callback; 105127664Sbmsstatic usb2_callback_t urio_write_clear_stall_callback; 106146768Ssamstatic usb2_callback_t urio_read_callback; 107146768Ssamstatic usb2_callback_t urio_read_clear_stall_callback; 108146768Ssam 109127664Sbmsstatic usb2_fifo_close_t urio_close; 110146768Ssamstatic usb2_fifo_cmd_t urio_start_read; 111146768Ssamstatic usb2_fifo_cmd_t urio_start_write; 112146768Ssamstatic usb2_fifo_cmd_t urio_stop_read; 113146768Ssamstatic usb2_fifo_cmd_t urio_stop_write; 114146768Ssamstatic usb2_fifo_ioctl_t urio_ioctl; 115146768Ssamstatic usb2_fifo_open_t urio_open; 116146768Ssam 117127664Sbmsstatic struct usb2_fifo_methods urio_fifo_methods = { 118127664Sbms .f_close = &urio_close, 119127664Sbms .f_ioctl = &urio_ioctl, 120127664Sbms .f_open = &urio_open, 121127664Sbms .f_start_read = &urio_start_read, 122127664Sbms .f_start_write = &urio_start_write, 123127664Sbms .f_stop_read = &urio_stop_read, 124146768Ssam .f_stop_write = &urio_stop_write, 125190225Srpaulo .basename[0] = "urio", 126146768Ssam}; 127162012Ssam 128162012Ssamstatic const struct usb2_config urio_config[URIO_T_MAX] = { 129162012Ssam [URIO_T_WR] = { 130162012Ssam .type = UE_BULK, 131162012Ssam .endpoint = UE_ADDR_ANY, 132146768Ssam .direction = UE_DIR_OUT, 133162012Ssam .mh.bufsize = URIO_BSIZE, 134162012Ssam .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,}, 135127664Sbms .mh.callback = &urio_write_callback, 136146768Ssam }, 137146768Ssam 138162012Ssam [URIO_T_RD] = { 139190225Srpaulo .type = UE_BULK, 140190225Srpaulo .endpoint = UE_ADDR_ANY, 141190225Srpaulo .direction = UE_DIR_IN, 142190225Srpaulo .mh.bufsize = URIO_BSIZE, 143190225Srpaulo .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,}, 144190225Srpaulo .mh.callback = &urio_read_callback, 145190225Srpaulo }, 146146768Ssam 147146768Ssam [URIO_T_WR_CS] = { 148127664Sbms .type = UE_CONTROL, 149127664Sbms .endpoint = 0x00, /* Control pipe */ 150146768Ssam .direction = UE_DIR_ANY, 151146768Ssam .mh.bufsize = sizeof(struct usb2_device_request), 152146768Ssam .mh.flags = {}, 153146768Ssam .mh.callback = &urio_write_clear_stall_callback, 154146768Ssam .mh.timeout = 1000, /* 1 second */ 155190225Srpaulo .mh.interval = 50, /* 50ms */ 156146768Ssam }, 157146768Ssam 158146768Ssam [URIO_T_RD_CS] = { 159146768Ssam .type = UE_CONTROL, 160127664Sbms .endpoint = 0x00, /* Control pipe */ 161127664Sbms .direction = UE_DIR_ANY, 162146768Ssam .mh.bufsize = sizeof(struct usb2_device_request), 163146768Ssam .mh.flags = {}, 164146768Ssam .mh.callback = &urio_read_clear_stall_callback, 165146768Ssam .mh.timeout = 1000, /* 1 second */ 166127664Sbms .mh.interval = 50, /* 50ms */ 167146768Ssam }, 168146768Ssam}; 169146768Ssam 170127664Sbmsstatic devclass_t urio_devclass; 171146768Ssam 172146768Ssamstatic device_method_t urio_methods[] = { 173146768Ssam /* Device interface */ 174146768Ssam DEVMETHOD(device_probe, urio_probe), 175127664Sbms DEVMETHOD(device_attach, urio_attach), 176146768Ssam DEVMETHOD(device_detach, urio_detach), 177146768Ssam {0, 0} 178146768Ssam}; 179127664Sbms 180146768Ssamstatic driver_t urio_driver = { 181127664Sbms .name = "urio", 182146768Ssam .methods = urio_methods, 183127664Sbms .size = sizeof(struct urio_softc), 184127664Sbms}; 185190225Srpaulo 186190225SrpauloDRIVER_MODULE(urio, ushub, urio_driver, urio_devclass, NULL, 0); 187190225SrpauloMODULE_DEPEND(urio, usb, 1, 1, 1); 188190225Srpaulo 189190225Srpaulostatic int 190190225Srpaulourio_probe(device_t dev) 191190225Srpaulo{ 192190225Srpaulo struct usb2_attach_arg *uaa = device_get_ivars(dev); 193190225Srpaulo 194190225Srpaulo if (uaa->usb2_mode != USB_MODE_HOST) { 195190225Srpaulo return (ENXIO); 196190225Srpaulo } 197190225Srpaulo if ((((uaa->info.idVendor == USB_VENDOR_DIAMOND) && 198190225Srpaulo (uaa->info.idProduct == USB_PRODUCT_DIAMOND_RIO500USB)) || 199190225Srpaulo ((uaa->info.idVendor == USB_VENDOR_DIAMOND2) && 200190225Srpaulo ((uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO600USB) || 201190225Srpaulo (uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO800USB))))) 202190225Srpaulo return (0); 203190225Srpaulo else 204190225Srpaulo return (ENXIO); 205190225Srpaulo} 206190225Srpaulo 207190225Srpaulostatic int 208190225Srpaulourio_attach(device_t dev) 209190225Srpaulo{ 210190225Srpaulo struct usb2_attach_arg *uaa = device_get_ivars(dev); 211190225Srpaulo struct urio_softc *sc = device_get_softc(dev); 212190225Srpaulo int error; 213190225Srpaulo 214190225Srpaulo device_set_usb2_desc(dev); 215190225Srpaulo 216190225Srpaulo sc->sc_udev = uaa->device; 217127664Sbms 218127664Sbms mtx_init(&sc->sc_mtx, "urio lock", NULL, MTX_DEF | MTX_RECURSE); 219127664Sbms 220127664Sbms snprintf(sc->sc_name, sizeof(sc->sc_name), 221127664Sbms "%s", device_get_nameunit(dev)); 222146768Ssam 223146768Ssam error = usb2_transfer_setup(uaa->device, 224146768Ssam &uaa->info.bIfaceIndex, sc->sc_xfer, 225127664Sbms urio_config, URIO_T_MAX, sc, &sc->sc_mtx); 226127664Sbms 227127664Sbms if (error) { 228190225Srpaulo DPRINTF("error=%s\n", usb2_errstr(error)); 229127664Sbms goto detach; 230162012Ssam } 231162012Ssam /* set interface permissions */ 232127664Sbms usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, 233162012Ssam UID_ROOT, GID_OPERATOR, 0644); 234162012Ssam 235162012Ssam error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, 236162012Ssam &urio_fifo_methods, &sc->sc_fifo, 237127664Sbms device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex); 238162012Ssam if (error) { 239162012Ssam goto detach; 240162012Ssam } 241127664Sbms return (0); /* success */ 242162012Ssam 243162012Ssamdetach: 244162012Ssam urio_detach(dev); 245127664Sbms return (ENOMEM); /* failure */ 246162012Ssam} 247162012Ssam 248162012Ssamstatic void 249162012Ssamurio_write_callback(struct usb2_xfer *xfer) 250162012Ssam{ 251162012Ssam struct urio_softc *sc = xfer->priv_sc; 252162012Ssam struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_TX]; 253162012Ssam uint32_t actlen; 254162012Ssam 255162012Ssam switch (USB_GET_STATE(xfer)) { 256162012Ssam case USB_ST_TRANSFERRED: 257162012Ssam case USB_ST_SETUP: 258190225Srpaulo if (sc->sc_flags & URIO_FLAG_WRITE_STALL) { 259190225Srpaulo usb2_transfer_start(sc->sc_xfer[URIO_T_WR_CS]); 260190225Srpaulo return; 261162012Ssam } 262162012Ssam if (usb2_fifo_get_data(f, xfer->frbuffers, 0, 263162012Ssam xfer->max_data_length, &actlen, 0)) { 264162012Ssam 265162012Ssam xfer->frlengths[0] = actlen; 266162012Ssam usb2_start_hardware(xfer); 267162012Ssam } 268162012Ssam return; 269162012Ssam 270127664Sbms default: /* Error */ 271162012Ssam if (xfer->error != USB_ERR_CANCELLED) { 272162012Ssam /* try to clear stall first */ 273162012Ssam sc->sc_flags |= URIO_FLAG_WRITE_STALL; 274162012Ssam usb2_transfer_start(sc->sc_xfer[URIO_T_WR_CS]); 275162012Ssam } 276162012Ssam return; 277162012Ssam } 278162012Ssam} 279162012Ssam 280162012Ssamstatic void 281146768Ssamurio_write_clear_stall_callback(struct usb2_xfer *xfer) 282162012Ssam{ 283162012Ssam struct urio_softc *sc = xfer->priv_sc; 284190225Srpaulo struct usb2_xfer *xfer_other = sc->sc_xfer[URIO_T_WR]; 285162012Ssam 286162012Ssam if (usb2_clear_stall_callback(xfer, xfer_other)) { 287162012Ssam DPRINTF("stall cleared\n"); 288190225Srpaulo sc->sc_flags &= ~URIO_FLAG_WRITE_STALL; 289162012Ssam usb2_transfer_start(xfer_other); 290162012Ssam } 291162012Ssam} 292162012Ssam 293162012Ssamstatic void 294162012Ssamurio_read_callback(struct usb2_xfer *xfer) 295190225Srpaulo{ 296162012Ssam struct urio_softc *sc = xfer->priv_sc; 297127664Sbms struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_RX]; 298162012Ssam 299162012Ssam switch (USB_GET_STATE(xfer)) { 300162012Ssam case USB_ST_TRANSFERRED: 301162012Ssam usb2_fifo_put_data(f, xfer->frbuffers, 0, 302127664Sbms xfer->actlen, 1); 303162012Ssam 304162012Ssam case USB_ST_SETUP: 305162012Ssam if (sc->sc_flags & URIO_FLAG_READ_STALL) { 306127664Sbms usb2_transfer_start(sc->sc_xfer[URIO_T_RD_CS]); 307162012Ssam return; 308162012Ssam } 309162012Ssam if (usb2_fifo_put_bytes_max(f) != 0) { 310127664Sbms xfer->frlengths[0] = xfer->max_data_length; 311162012Ssam usb2_start_hardware(xfer); 312162012Ssam } 313162012Ssam return; 314162012Ssam 315162012Ssam default: /* Error */ 316162012Ssam if (xfer->error != USB_ERR_CANCELLED) { 317162012Ssam /* try to clear stall first */ 318162012Ssam sc->sc_flags |= URIO_FLAG_READ_STALL; 319162012Ssam usb2_transfer_start(sc->sc_xfer[URIO_T_RD_CS]); 320190225Srpaulo } 321190225Srpaulo return; 322162012Ssam } 323162012Ssam} 324172677Smlaier 325172677Smlaierstatic void 326172677Smlaierurio_read_clear_stall_callback(struct usb2_xfer *xfer) 327190225Srpaulo{ 328190225Srpaulo struct urio_softc *sc = xfer->priv_sc; 329172677Smlaier struct usb2_xfer *xfer_other = sc->sc_xfer[URIO_T_RD]; 330172677Smlaier 331162012Ssam if (usb2_clear_stall_callback(xfer, xfer_other)) { 332127664Sbms DPRINTF("stall cleared\n"); 333146768Ssam sc->sc_flags &= ~URIO_FLAG_READ_STALL; 334127664Sbms usb2_transfer_start(xfer_other); 335127664Sbms } 336146768Ssam} 337127664Sbms 338127664Sbmsstatic void 339162012Ssamurio_start_read(struct usb2_fifo *fifo) 340190225Srpaulo{ 341190225Srpaulo struct urio_softc *sc = fifo->priv_sc0; 342190225Srpaulo 343190225Srpaulo usb2_transfer_start(sc->sc_xfer[URIO_T_RD]); 344127664Sbms} 345190225Srpaulo 346190225Srpaulostatic void 347190225Srpaulourio_stop_read(struct usb2_fifo *fifo) 348190225Srpaulo{ 349190225Srpaulo struct urio_softc *sc = fifo->priv_sc0; 350190225Srpaulo 351190225Srpaulo usb2_transfer_stop(sc->sc_xfer[URIO_T_RD_CS]); 352190225Srpaulo usb2_transfer_stop(sc->sc_xfer[URIO_T_RD]); 353190225Srpaulo} 354190225Srpaulo 355190225Srpaulostatic void 356190225Srpaulourio_start_write(struct usb2_fifo *fifo) 357190225Srpaulo{ 358190225Srpaulo struct urio_softc *sc = fifo->priv_sc0; 359190225Srpaulo 360190225Srpaulo usb2_transfer_start(sc->sc_xfer[URIO_T_WR]); 361190225Srpaulo} 362190225Srpaulo 363190225Srpaulostatic void 364190225Srpaulourio_stop_write(struct usb2_fifo *fifo) 365190225Srpaulo{ 366190225Srpaulo struct urio_softc *sc = fifo->priv_sc0; 367190225Srpaulo 368214518Srpaulo usb2_transfer_stop(sc->sc_xfer[URIO_T_WR_CS]); 369214518Srpaulo usb2_transfer_stop(sc->sc_xfer[URIO_T_WR]); 370214518Srpaulo} 371214518Srpaulo 372190225Srpaulostatic int 373190225Srpaulourio_open(struct usb2_fifo *fifo, int fflags, struct thread *td) 374190225Srpaulo{ 375190225Srpaulo struct urio_softc *sc = fifo->priv_sc0; 376190225Srpaulo 377190225Srpaulo if ((fflags & (FWRITE | FREAD)) != (FWRITE | FREAD)) { 378190225Srpaulo return (EACCES); 379190225Srpaulo } 380190225Srpaulo if (fflags & FREAD) { 381190225Srpaulo /* clear stall first */ 382190225Srpaulo mtx_lock(&sc->sc_mtx); 383190225Srpaulo sc->sc_flags |= URIO_FLAG_READ_STALL; 384190225Srpaulo mtx_unlock(&sc->sc_mtx); 385190225Srpaulo 386190225Srpaulo if (usb2_fifo_alloc_buffer(fifo, 387190225Srpaulo sc->sc_xfer[URIO_T_RD]->max_data_length, 388190225Srpaulo URIO_IFQ_MAXLEN)) { 389190225Srpaulo return (ENOMEM); 390190225Srpaulo } 391190225Srpaulo } 392190225Srpaulo if (fflags & FWRITE) { 393190225Srpaulo /* clear stall first */ 394190225Srpaulo sc->sc_flags |= URIO_FLAG_WRITE_STALL; 395190225Srpaulo 396190225Srpaulo if (usb2_fifo_alloc_buffer(fifo, 397190225Srpaulo sc->sc_xfer[URIO_T_WR]->max_data_length, 398190225Srpaulo URIO_IFQ_MAXLEN)) { 399190225Srpaulo return (ENOMEM); 400190225Srpaulo } 401190225Srpaulo } 402190225Srpaulo return (0); /* success */ 403190225Srpaulo} 404190225Srpaulo 405190225Srpaulostatic void 406190225Srpaulourio_close(struct usb2_fifo *fifo, int fflags, struct thread *td) 407190225Srpaulo{ 408190225Srpaulo if (fflags & (FREAD | FWRITE)) { 409190225Srpaulo usb2_fifo_free_buffer(fifo); 410190225Srpaulo } 411190225Srpaulo} 412190225Srpaulo 413190225Srpaulostatic int 414190225Srpaulourio_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, 415190225Srpaulo int fflags, struct thread *td) 416190225Srpaulo{ 417190225Srpaulo struct usb2_ctl_request ur; 418190225Srpaulo struct RioCommand *rio_cmd; 419190225Srpaulo int error; 420190225Srpaulo 421190225Srpaulo switch (cmd) { 422190225Srpaulo case RIO_RECV_COMMAND: 423190225Srpaulo if (!(fflags & FWRITE)) { 424190225Srpaulo error = EPERM; 425190225Srpaulo goto done; 426190225Srpaulo } 427190225Srpaulo bzero(&ur, sizeof(ur)); 428190225Srpaulo rio_cmd = addr; 429190225Srpaulo ur.ucr_request.bmRequestType = 430190225Srpaulo rio_cmd->requesttype | UT_READ_VENDOR_DEVICE; 431190225Srpaulo break; 432190225Srpaulo 433190225Srpaulo case RIO_SEND_COMMAND: 434190225Srpaulo if (!(fflags & FWRITE)) { 435190225Srpaulo error = EPERM; 436190225Srpaulo goto done; 437190225Srpaulo } 438190225Srpaulo bzero(&ur, sizeof(ur)); 439190225Srpaulo rio_cmd = addr; 440190225Srpaulo ur.ucr_request.bmRequestType = 441190225Srpaulo rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE; 442190225Srpaulo break; 443190225Srpaulo 444190225Srpaulo default: 445190225Srpaulo error = EINVAL; 446190225Srpaulo goto done; 447190225Srpaulo } 448190225Srpaulo 449190225Srpaulo DPRINTFN(2, "Sending command\n"); 450190225Srpaulo 451190225Srpaulo /* Send rio control message */ 452190225Srpaulo ur.ucr_request.bRequest = rio_cmd->request; 453190225Srpaulo USETW(ur.ucr_request.wValue, rio_cmd->value); 454190225Srpaulo USETW(ur.ucr_request.wIndex, rio_cmd->index); 455190225Srpaulo USETW(ur.ucr_request.wLength, rio_cmd->length); 456190225Srpaulo ur.ucr_data = rio_cmd->buffer; 457190225Srpaulo 458190225Srpaulo /* reuse generic USB code */ 459190225Srpaulo error = ugen_do_request(fifo, &ur); 460190225Srpaulo 461190225Srpaulodone: 462190225Srpaulo return (error); 463190225Srpaulo} 464190225Srpaulo 465190225Srpaulostatic int 466190225Srpaulourio_detach(device_t dev) 467190225Srpaulo{ 468190225Srpaulo struct urio_softc *sc = device_get_softc(dev); 469190225Srpaulo 470190225Srpaulo DPRINTF("\n"); 471190225Srpaulo 472190225Srpaulo usb2_fifo_detach(&sc->sc_fifo); 473190225Srpaulo 474190225Srpaulo usb2_transfer_unsetup(sc->sc_xfer, URIO_T_MAX); 475190225Srpaulo 476190225Srpaulo mtx_destroy(&sc->sc_mtx); 477190225Srpaulo 478190225Srpaulo return (0); 479190225Srpaulo} 480190225Srpaulo