urio.c revision 185087
1216829Syongari/*- 2216829Syongari * Copyright (c) 2000 Iwasa Kazmi 3216829Syongari * All rights reserved. 4216829Syongari * 5216829Syongari * Redistribution and use in source and binary forms, with or without 6216829Syongari * modification, are permitted provided that the following conditions 7216829Syongari * are met: 8216829Syongari * 1. Redistributions of source code must retain the above copyright 9216829Syongari * notice, this list of conditions, and the following disclaimer. 10216829Syongari * 2. Redistributions in binary form must reproduce the above copyright 11216829Syongari * notice, this list of conditions and the following disclaimer in the 12216829Syongari * documentation and/or other materials provided with the distribution. 13216829Syongari * 14216829Syongari * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15216829Syongari * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16216829Syongari * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17216829Syongari * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 18216829Syongari * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19216829Syongari * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20216829Syongari * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21216829Syongari * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22216829Syongari * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23216829Syongari * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24216829Syongari * SUCH DAMAGE. 25216829Syongari * 26216829Syongari * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson. 27216829Syongari * This code includes software developed by the NetBSD Foundation, Inc. and 28216829Syongari * its contributors. 29216829Syongari */ 30216829Syongari 31216829Syongari#include <sys/cdefs.h> 32216829Syongari__FBSDID("$FreeBSD: head/sys/dev/usb2/storage/urio2.c 185087 2008-11-19 08:56:35Z alfred $"); 33216829Syongari 34216829Syongari 35216829Syongari/* 36216829Syongari * 2000/3/24 added NetBSD/OpenBSD support (from Alex Nemirovsky) 37216829Syongari * 2000/3/07 use two bulk-pipe handles for read and write (Dirk) 38216829Syongari * 2000/3/06 change major number(143), and copyright header 39216829Syongari * some fix for 4.0 (Dirk) 40216829Syongari * 2000/3/05 codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik) 41216829Syongari * 2000/3/01 remove retry code from urioioctl() 42216829Syongari * change method of bulk transfer (no interrupt) 43216829Syongari * 2000/2/28 small fixes for new rio_usb.h 44216829Syongari * 2000/2/24 first version. 45216829Syongari */ 46216829Syongari 47216829Syongari#include <dev/usb2/include/usb2_devid.h> 48216829Syongari#include <dev/usb2/include/usb2_standard.h> 49216829Syongari#include <dev/usb2/include/usb2_mfunc.h> 50216829Syongari#include <dev/usb2/include/usb2_error.h> 51216829Syongari#include <dev/usb2/include/usb2_ioctl.h> 52216829Syongari#include <dev/usb/rio500_usb.h> 53216829Syongari 54216829Syongari#define USB_DEBUG_VAR urio_debug 55216829Syongari 56216829Syongari#include <dev/usb2/core/usb2_core.h> 57216829Syongari#include <dev/usb2/core/usb2_debug.h> 58216829Syongari#include <dev/usb2/core/usb2_process.h> 59216829Syongari#include <dev/usb2/core/usb2_config_td.h> 60216829Syongari#include <dev/usb2/core/usb2_request.h> 61216829Syongari#include <dev/usb2/core/usb2_lookup.h> 62216829Syongari#include <dev/usb2/core/usb2_util.h> 63216829Syongari#include <dev/usb2/core/usb2_busdma.h> 64216829Syongari#include <dev/usb2/core/usb2_mbuf.h> 65216829Syongari#include <dev/usb2/core/usb2_dev.h> 66216829Syongari#include <dev/usb2/core/usb2_generic.h> 67216829Syongari 68216829Syongari#if USB_DEBUG 69216829Syongaristatic int urio_debug = 0; 70216829Syongari 71216829SyongariSYSCTL_NODE(_hw_usb2, OID_AUTO, urio, CTLFLAG_RW, 0, "USB urio"); 72216829SyongariSYSCTL_INT(_hw_usb2_urio, OID_AUTO, debug, CTLFLAG_RW, 73216829Syongari &urio_debug, 0, "urio debug level"); 74216829Syongari#endif 75216829Syongari 76216829Syongari#define URIO_T_WR 0 77216829Syongari#define URIO_T_RD 1 78216829Syongari#define URIO_T_WR_CS 2 79216829Syongari#define URIO_T_RD_CS 3 80216829Syongari#define URIO_T_MAX 4 81216829Syongari 82216829Syongari#define URIO_BSIZE (1<<12) /* bytes */ 83216829Syongari#define URIO_IFQ_MAXLEN 2 /* units */ 84216829Syongari 85216829Syongaristruct urio_softc { 86216829Syongari struct usb2_fifo_sc sc_fifo; 87216829Syongari struct mtx sc_mtx; 88216829Syongari 89216829Syongari struct usb2_device *sc_udev; 90216829Syongari struct usb2_xfer *sc_xfer[URIO_T_MAX]; 91216829Syongari 92216829Syongari uint8_t sc_flags; 93216829Syongari#define URIO_FLAG_READ_STALL 0x01 /* read transfer stalled */ 94216829Syongari#define URIO_FLAG_WRITE_STALL 0x02 /* write transfer stalled */ 95216829Syongari 96216829Syongari uint8_t sc_name[16]; 97216829Syongari}; 98216829Syongari 99216829Syongari/* prototypes */ 100216829Syongari 101216829Syongaristatic device_probe_t urio_probe; 102216829Syongaristatic device_attach_t urio_attach; 103216829Syongaristatic device_detach_t urio_detach; 104216829Syongari 105216829Syongaristatic usb2_callback_t urio_write_callback; 106216829Syongaristatic usb2_callback_t urio_write_clear_stall_callback; 107216829Syongaristatic usb2_callback_t urio_read_callback; 108216829Syongaristatic usb2_callback_t urio_read_clear_stall_callback; 109216829Syongari 110216829Syongaristatic usb2_fifo_close_t urio_close; 111216829Syongaristatic usb2_fifo_cmd_t urio_start_read; 112216829Syongaristatic usb2_fifo_cmd_t urio_start_write; 113216829Syongaristatic usb2_fifo_cmd_t urio_stop_read; 114216829Syongaristatic usb2_fifo_cmd_t urio_stop_write; 115216829Syongaristatic usb2_fifo_ioctl_t urio_ioctl; 116216829Syongaristatic usb2_fifo_open_t urio_open; 117216829Syongari 118216829Syongaristatic struct usb2_fifo_methods urio_fifo_methods = { 119216829Syongari .f_close = &urio_close, 120216829Syongari .f_ioctl = &urio_ioctl, 121216829Syongari .f_open = &urio_open, 122216829Syongari .f_start_read = &urio_start_read, 123216829Syongari .f_start_write = &urio_start_write, 124216829Syongari .f_stop_read = &urio_stop_read, 125216829Syongari .f_stop_write = &urio_stop_write, 126216829Syongari .basename[0] = "urio", 127216829Syongari}; 128216829Syongari 129216829Syongaristatic const struct usb2_config urio_config[URIO_T_MAX] = { 130216829Syongari [URIO_T_WR] = { 131216829Syongari .type = UE_BULK, 132216829Syongari .endpoint = UE_ADDR_ANY, 133216829Syongari .direction = UE_DIR_OUT, 134216829Syongari .mh.bufsize = URIO_BSIZE, 135216829Syongari .mh.flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,}, 136216829Syongari .mh.callback = &urio_write_callback, 137216829Syongari }, 138216829Syongari 139216829Syongari [URIO_T_RD] = { 140216829Syongari .type = UE_BULK, 141216829Syongari .endpoint = UE_ADDR_ANY, 142216829Syongari .direction = UE_DIR_IN, 143216829Syongari .mh.bufsize = URIO_BSIZE, 144216829Syongari .mh.flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,}, 145216829Syongari .mh.callback = &urio_read_callback, 146216829Syongari }, 147216829Syongari 148216829Syongari [URIO_T_WR_CS] = { 149216829Syongari .type = UE_CONTROL, 150216829Syongari .endpoint = 0x00, /* Control pipe */ 151216829Syongari .direction = UE_DIR_ANY, 152216829Syongari .mh.bufsize = sizeof(struct usb2_device_request), 153216829Syongari .mh.flags = {}, 154216829Syongari .mh.callback = &urio_write_clear_stall_callback, 155216829Syongari .mh.timeout = 1000, /* 1 second */ 156216829Syongari .mh.interval = 50, /* 50ms */ 157216829Syongari }, 158216829Syongari 159216829Syongari [URIO_T_RD_CS] = { 160216829Syongari .type = UE_CONTROL, 161216829Syongari .endpoint = 0x00, /* Control pipe */ 162216829Syongari .direction = UE_DIR_ANY, 163216829Syongari .mh.bufsize = sizeof(struct usb2_device_request), 164216829Syongari .mh.flags = {}, 165216829Syongari .mh.callback = &urio_read_clear_stall_callback, 166216829Syongari .mh.timeout = 1000, /* 1 second */ 167216829Syongari .mh.interval = 50, /* 50ms */ 168216829Syongari }, 169216829Syongari}; 170216829Syongari 171216829Syongaristatic devclass_t urio_devclass; 172216829Syongari 173216829Syongaristatic device_method_t urio_methods[] = { 174216829Syongari /* Device interface */ 175216829Syongari DEVMETHOD(device_probe, urio_probe), 176216829Syongari DEVMETHOD(device_attach, urio_attach), 177216829Syongari DEVMETHOD(device_detach, urio_detach), 178216829Syongari {0, 0} 179216829Syongari}; 180216829Syongari 181216829Syongaristatic driver_t urio_driver = { 182216829Syongari .name = "urio", 183216829Syongari .methods = urio_methods, 184216829Syongari .size = sizeof(struct urio_softc), 185216829Syongari}; 186216829Syongari 187216829SyongariDRIVER_MODULE(urio, ushub, urio_driver, urio_devclass, NULL, 0); 188216829SyongariMODULE_DEPEND(urio, usb2_storage, 1, 1, 1); 189216829SyongariMODULE_DEPEND(urio, usb2_core, 1, 1, 1); 190216829Syongari 191216829Syongaristatic int 192216829Syongariurio_probe(device_t dev) 193216829Syongari{ 194216829Syongari struct usb2_attach_arg *uaa = device_get_ivars(dev); 195216829Syongari 196216829Syongari if (uaa->usb2_mode != USB_MODE_HOST) { 197216829Syongari return (ENXIO); 198216829Syongari } 199216829Syongari if ((((uaa->info.idVendor == USB_VENDOR_DIAMOND) && 200216829Syongari (uaa->info.idProduct == USB_PRODUCT_DIAMOND_RIO500USB)) || 201216829Syongari ((uaa->info.idVendor == USB_VENDOR_DIAMOND2) && 202216829Syongari ((uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO600USB) || 203216829Syongari (uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO800USB))))) 204216829Syongari return (0); 205216829Syongari else 206216829Syongari return (ENXIO); 207216829Syongari} 208216829Syongari 209216829Syongaristatic int 210216829Syongariurio_attach(device_t dev) 211216829Syongari{ 212216829Syongari struct usb2_attach_arg *uaa = device_get_ivars(dev); 213216829Syongari struct urio_softc *sc = device_get_softc(dev); 214216829Syongari int error; 215216829Syongari 216216829Syongari if (sc == NULL) { 217216829Syongari return (ENOMEM); 218216829Syongari } 219216829Syongari device_set_usb2_desc(dev); 220216829Syongari 221216829Syongari sc->sc_udev = uaa->device; 222216829Syongari 223216829Syongari mtx_init(&sc->sc_mtx, "urio lock", NULL, MTX_DEF | MTX_RECURSE); 224216829Syongari 225216829Syongari snprintf(sc->sc_name, sizeof(sc->sc_name), 226216829Syongari "%s", device_get_nameunit(dev)); 227216829Syongari 228216829Syongari error = usb2_transfer_setup(uaa->device, 229216829Syongari &uaa->info.bIfaceIndex, sc->sc_xfer, 230216829Syongari urio_config, URIO_T_MAX, sc, &sc->sc_mtx); 231216829Syongari 232216829Syongari if (error) { 233216829Syongari DPRINTF("error=%s\n", usb2_errstr(error)); 234216829Syongari goto detach; 235216829Syongari } 236216829Syongari /* set interface permissions */ 237216829Syongari usb2_set_iface_perm(uaa->device, uaa->info.bIfaceIndex, 238216829Syongari UID_ROOT, GID_OPERATOR, 0644); 239216829Syongari 240216829Syongari error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, 241216829Syongari &urio_fifo_methods, &sc->sc_fifo, 242216829Syongari device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex); 243216829Syongari if (error) { 244216829Syongari goto detach; 245216829Syongari } 246216829Syongari return (0); /* success */ 247216829Syongari 248216829Syongaridetach: 249216829Syongari urio_detach(dev); 250216829Syongari return (ENOMEM); /* failure */ 251216829Syongari} 252216829Syongari 253216829Syongaristatic void 254216829Syongariurio_write_callback(struct usb2_xfer *xfer) 255216829Syongari{ 256216829Syongari struct urio_softc *sc = xfer->priv_sc; 257216829Syongari struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_TX]; 258216829Syongari uint32_t actlen; 259216829Syongari 260216829Syongari switch (USB_GET_STATE(xfer)) { 261216829Syongari case USB_ST_TRANSFERRED: 262216829Syongari case USB_ST_SETUP: 263216829Syongari if (sc->sc_flags & URIO_FLAG_WRITE_STALL) { 264216829Syongari usb2_transfer_start(sc->sc_xfer[URIO_T_WR_CS]); 265216829Syongari return; 266216829Syongari } 267216829Syongari if (usb2_fifo_get_data(f, xfer->frbuffers, 0, 268216829Syongari xfer->max_data_length, &actlen, 0)) { 269216829Syongari 270216829Syongari xfer->frlengths[0] = actlen; 271216829Syongari usb2_start_hardware(xfer); 272216829Syongari } 273216829Syongari return; 274216829Syongari 275216829Syongari default: /* Error */ 276216829Syongari if (xfer->error != USB_ERR_CANCELLED) { 277216829Syongari /* try to clear stall first */ 278216829Syongari sc->sc_flags |= URIO_FLAG_WRITE_STALL; 279216829Syongari usb2_transfer_start(sc->sc_xfer[URIO_T_WR_CS]); 280216829Syongari } 281216829Syongari return; 282216829Syongari } 283216829Syongari} 284216829Syongari 285216829Syongaristatic void 286216829Syongariurio_write_clear_stall_callback(struct usb2_xfer *xfer) 287216829Syongari{ 288216829Syongari struct urio_softc *sc = xfer->priv_sc; 289216829Syongari struct usb2_xfer *xfer_other = sc->sc_xfer[URIO_T_WR]; 290216829Syongari 291216829Syongari if (usb2_clear_stall_callback(xfer, xfer_other)) { 292216829Syongari DPRINTF("stall cleared\n"); 293216829Syongari sc->sc_flags &= ~URIO_FLAG_WRITE_STALL; 294216829Syongari usb2_transfer_start(xfer_other); 295216829Syongari } 296216829Syongari return; 297216829Syongari} 298216829Syongari 299216829Syongaristatic void 300216829Syongariurio_read_callback(struct usb2_xfer *xfer) 301216829Syongari{ 302216829Syongari struct urio_softc *sc = xfer->priv_sc; 303216829Syongari struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_RX]; 304216829Syongari 305216829Syongari switch (USB_GET_STATE(xfer)) { 306216829Syongari case USB_ST_TRANSFERRED: 307216829Syongari usb2_fifo_put_data(f, xfer->frbuffers, 0, 308216829Syongari xfer->actlen, 1); 309216829Syongari 310216829Syongari case USB_ST_SETUP: 311216829Syongari if (sc->sc_flags & URIO_FLAG_READ_STALL) { 312216829Syongari usb2_transfer_start(sc->sc_xfer[URIO_T_RD_CS]); 313216829Syongari return; 314216829Syongari } 315216829Syongari if (usb2_fifo_put_bytes_max(f) != 0) { 316216829Syongari xfer->frlengths[0] = xfer->max_data_length; 317216829Syongari usb2_start_hardware(xfer); 318216829Syongari } 319216829Syongari return; 320216829Syongari 321216829Syongari default: /* Error */ 322216829Syongari if (xfer->error != USB_ERR_CANCELLED) { 323216829Syongari /* try to clear stall first */ 324216829Syongari sc->sc_flags |= URIO_FLAG_READ_STALL; 325216829Syongari usb2_transfer_start(sc->sc_xfer[URIO_T_RD_CS]); 326216829Syongari } 327216829Syongari return; 328216829Syongari } 329216829Syongari} 330216829Syongari 331216829Syongaristatic void 332216829Syongariurio_read_clear_stall_callback(struct usb2_xfer *xfer) 333216829Syongari{ 334216829Syongari struct urio_softc *sc = xfer->priv_sc; 335216829Syongari struct usb2_xfer *xfer_other = sc->sc_xfer[URIO_T_RD]; 336216829Syongari 337216829Syongari if (usb2_clear_stall_callback(xfer, xfer_other)) { 338216829Syongari DPRINTF("stall cleared\n"); 339216829Syongari sc->sc_flags &= ~URIO_FLAG_READ_STALL; 340216829Syongari usb2_transfer_start(xfer_other); 341216829Syongari } 342216829Syongari return; 343216829Syongari} 344216829Syongari 345216829Syongaristatic void 346216829Syongariurio_start_read(struct usb2_fifo *fifo) 347216829Syongari{ 348216829Syongari struct urio_softc *sc = fifo->priv_sc0; 349216829Syongari 350216829Syongari usb2_transfer_start(sc->sc_xfer[URIO_T_RD]); 351216829Syongari return; 352216829Syongari} 353216829Syongari 354216829Syongaristatic void 355216829Syongariurio_stop_read(struct usb2_fifo *fifo) 356216829Syongari{ 357216829Syongari struct urio_softc *sc = fifo->priv_sc0; 358216829Syongari 359216829Syongari usb2_transfer_stop(sc->sc_xfer[URIO_T_RD_CS]); 360216829Syongari usb2_transfer_stop(sc->sc_xfer[URIO_T_RD]); 361216829Syongari return; 362216829Syongari} 363216829Syongari 364216829Syongaristatic void 365216829Syongariurio_start_write(struct usb2_fifo *fifo) 366216829Syongari{ 367216829Syongari struct urio_softc *sc = fifo->priv_sc0; 368216829Syongari 369216829Syongari usb2_transfer_start(sc->sc_xfer[URIO_T_WR]); 370216829Syongari return; 371216829Syongari} 372216829Syongari 373216829Syongaristatic void 374216829Syongariurio_stop_write(struct usb2_fifo *fifo) 375216829Syongari{ 376216829Syongari struct urio_softc *sc = fifo->priv_sc0; 377216829Syongari 378216829Syongari usb2_transfer_stop(sc->sc_xfer[URIO_T_WR_CS]); 379216829Syongari usb2_transfer_stop(sc->sc_xfer[URIO_T_WR]); 380216829Syongari return; 381216829Syongari} 382216829Syongari 383216829Syongaristatic int 384216829Syongariurio_open(struct usb2_fifo *fifo, int fflags, struct thread *td) 385216829Syongari{ 386216829Syongari struct urio_softc *sc = fifo->priv_sc0; 387216829Syongari 388216829Syongari if ((fflags & (FWRITE | FREAD)) != (FWRITE | FREAD)) { 389216829Syongari return (EACCES); 390216829Syongari } 391216829Syongari if (fflags & FREAD) { 392216829Syongari /* clear stall first */ 393216829Syongari mtx_lock(&sc->sc_mtx); 394216829Syongari sc->sc_flags |= URIO_FLAG_READ_STALL; 395216829Syongari mtx_unlock(&sc->sc_mtx); 396216829Syongari 397216829Syongari if (usb2_fifo_alloc_buffer(fifo, 398216829Syongari sc->sc_xfer[URIO_T_RD]->max_data_length, 399216829Syongari URIO_IFQ_MAXLEN)) { 400216829Syongari return (ENOMEM); 401216829Syongari } 402216829Syongari } 403216829Syongari if (fflags & FWRITE) { 404216829Syongari /* clear stall first */ 405216829Syongari sc->sc_flags |= URIO_FLAG_WRITE_STALL; 406216829Syongari 407216829Syongari if (usb2_fifo_alloc_buffer(fifo, 408216829Syongari sc->sc_xfer[URIO_T_WR]->max_data_length, 409216829Syongari URIO_IFQ_MAXLEN)) { 410216829Syongari return (ENOMEM); 411216829Syongari } 412216829Syongari } 413216829Syongari return (0); /* success */ 414216829Syongari} 415216829Syongari 416216829Syongaristatic void 417216829Syongariurio_close(struct usb2_fifo *fifo, int fflags, struct thread *td) 418216829Syongari{ 419216829Syongari if (fflags & (FREAD | FWRITE)) { 420216829Syongari usb2_fifo_free_buffer(fifo); 421216829Syongari } 422216829Syongari return; 423216829Syongari} 424216829Syongari 425216829Syongaristatic int 426216829Syongariurio_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, 427216829Syongari int fflags, struct thread *td) 428216829Syongari{ 429216829Syongari struct usb2_ctl_request ur; 430216829Syongari struct RioCommand *rio_cmd; 431216829Syongari int error; 432216829Syongari 433216829Syongari switch (cmd) { 434216829Syongari case RIO_RECV_COMMAND: 435216829Syongari if (!(fflags & FWRITE)) { 436216829Syongari error = EPERM; 437216829Syongari goto done; 438216829Syongari } 439216829Syongari bzero(&ur, sizeof(ur)); 440216829Syongari rio_cmd = addr; 441216829Syongari ur.ucr_request.bmRequestType = 442216829Syongari rio_cmd->requesttype | UT_READ_VENDOR_DEVICE; 443216829Syongari break; 444216829Syongari 445216829Syongari case RIO_SEND_COMMAND: 446216829Syongari if (!(fflags & FWRITE)) { 447216829Syongari error = EPERM; 448216829Syongari goto done; 449216829Syongari } 450216829Syongari bzero(&ur, sizeof(ur)); 451216829Syongari rio_cmd = addr; 452216829Syongari ur.ucr_request.bmRequestType = 453216829Syongari rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE; 454216829Syongari break; 455216829Syongari 456216829Syongari default: 457216829Syongari error = EINVAL; 458216829Syongari goto done; 459216829Syongari } 460216829Syongari 461216829Syongari DPRINTFN(2, "Sending command\n"); 462216829Syongari 463216829Syongari /* Send rio control message */ 464216829Syongari ur.ucr_request.bRequest = rio_cmd->request; 465216829Syongari USETW(ur.ucr_request.wValue, rio_cmd->value); 466216829Syongari USETW(ur.ucr_request.wIndex, rio_cmd->index); 467216829Syongari USETW(ur.ucr_request.wLength, rio_cmd->length); 468216829Syongari ur.ucr_data = rio_cmd->buffer; 469216829Syongari 470216829Syongari /* reuse generic USB code */ 471216829Syongari error = ugen_do_request(fifo, &ur); 472216829Syongari 473216829Syongaridone: 474216829Syongari return (error); 475216829Syongari} 476216829Syongari 477216829Syongaristatic int 478216829Syongariurio_detach(device_t dev) 479216829Syongari{ 480216829Syongari struct urio_softc *sc = device_get_softc(dev); 481216829Syongari 482216829Syongari DPRINTF("\n"); 483216829Syongari 484216829Syongari usb2_fifo_detach(&sc->sc_fifo); 485216829Syongari 486216829Syongari usb2_transfer_unsetup(sc->sc_xfer, URIO_T_MAX); 487216829Syongari 488216829Syongari mtx_destroy(&sc->sc_mtx); 489216829Syongari 490216829Syongari return (0); 491216829Syongari} 492216829Syongari