urio.c revision 192502
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/usb/storage/urio.c 192502 2009-05-21 01:48:42Z thompsa $"); 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 47188746Sthompsa#include "usbdevs.h" 48188942Sthompsa#include <dev/usb/usb.h> 49188942Sthompsa#include <dev/usb/usb_mfunc.h> 50188942Sthompsa#include <dev/usb/usb_error.h> 51188942Sthompsa#include <dev/usb/usb_ioctl.h> 52188942Sthompsa#include <dev/usb/storage/rio500_usb.h> 53184610Salfred 54184610Salfred#define USB_DEBUG_VAR urio_debug 55184610Salfred 56188942Sthompsa#include <dev/usb/usb_core.h> 57188942Sthompsa#include <dev/usb/usb_debug.h> 58188942Sthompsa#include <dev/usb/usb_process.h> 59188942Sthompsa#include <dev/usb/usb_request.h> 60188942Sthompsa#include <dev/usb/usb_lookup.h> 61188942Sthompsa#include <dev/usb/usb_util.h> 62188942Sthompsa#include <dev/usb/usb_busdma.h> 63188942Sthompsa#include <dev/usb/usb_mbuf.h> 64188942Sthompsa#include <dev/usb/usb_dev.h> 65188942Sthompsa#include <dev/usb/usb_generic.h> 66184610Salfred 67184610Salfred#if USB_DEBUG 68184610Salfredstatic int urio_debug = 0; 69184610Salfred 70192502SthompsaSYSCTL_NODE(_hw_usb, OID_AUTO, urio, CTLFLAG_RW, 0, "USB urio"); 71192502SthompsaSYSCTL_INT(_hw_usb_urio, OID_AUTO, debug, CTLFLAG_RW, 72184610Salfred &urio_debug, 0, "urio debug level"); 73184610Salfred#endif 74184610Salfred 75184610Salfred#define URIO_T_WR 0 76184610Salfred#define URIO_T_RD 1 77184610Salfred#define URIO_T_WR_CS 2 78184610Salfred#define URIO_T_RD_CS 3 79184610Salfred#define URIO_T_MAX 4 80184610Salfred 81184610Salfred#define URIO_BSIZE (1<<12) /* bytes */ 82184610Salfred#define URIO_IFQ_MAXLEN 2 /* units */ 83184610Salfred 84184610Salfredstruct urio_softc { 85184610Salfred struct usb2_fifo_sc sc_fifo; 86184610Salfred struct mtx sc_mtx; 87184610Salfred 88184610Salfred struct usb2_device *sc_udev; 89184610Salfred struct usb2_xfer *sc_xfer[URIO_T_MAX]; 90184610Salfred 91184610Salfred uint8_t sc_flags; 92184610Salfred#define URIO_FLAG_READ_STALL 0x01 /* read transfer stalled */ 93184610Salfred#define URIO_FLAG_WRITE_STALL 0x02 /* write transfer stalled */ 94184610Salfred 95184610Salfred uint8_t sc_name[16]; 96184610Salfred}; 97184610Salfred 98184610Salfred/* prototypes */ 99184610Salfred 100184610Salfredstatic device_probe_t urio_probe; 101184610Salfredstatic device_attach_t urio_attach; 102184610Salfredstatic device_detach_t urio_detach; 103184610Salfred 104184610Salfredstatic usb2_callback_t urio_write_callback; 105184610Salfredstatic usb2_callback_t urio_write_clear_stall_callback; 106184610Salfredstatic usb2_callback_t urio_read_callback; 107184610Salfredstatic usb2_callback_t urio_read_clear_stall_callback; 108184610Salfred 109184610Salfredstatic usb2_fifo_close_t urio_close; 110184610Salfredstatic usb2_fifo_cmd_t urio_start_read; 111184610Salfredstatic usb2_fifo_cmd_t urio_start_write; 112184610Salfredstatic usb2_fifo_cmd_t urio_stop_read; 113184610Salfredstatic usb2_fifo_cmd_t urio_stop_write; 114184610Salfredstatic usb2_fifo_ioctl_t urio_ioctl; 115184610Salfredstatic usb2_fifo_open_t urio_open; 116184610Salfred 117184610Salfredstatic struct usb2_fifo_methods urio_fifo_methods = { 118184610Salfred .f_close = &urio_close, 119184610Salfred .f_ioctl = &urio_ioctl, 120184610Salfred .f_open = &urio_open, 121184610Salfred .f_start_read = &urio_start_read, 122184610Salfred .f_start_write = &urio_start_write, 123184610Salfred .f_stop_read = &urio_stop_read, 124184610Salfred .f_stop_write = &urio_stop_write, 125184610Salfred .basename[0] = "urio", 126184610Salfred}; 127184610Salfred 128184610Salfredstatic const struct usb2_config urio_config[URIO_T_MAX] = { 129184610Salfred [URIO_T_WR] = { 130184610Salfred .type = UE_BULK, 131184610Salfred .endpoint = UE_ADDR_ANY, 132184610Salfred .direction = UE_DIR_OUT, 133190734Sthompsa .bufsize = URIO_BSIZE, 134190734Sthompsa .flags = {.pipe_bof = 1,.force_short_xfer = 1,.proxy_buffer = 1,}, 135190734Sthompsa .callback = &urio_write_callback, 136184610Salfred }, 137184610Salfred 138184610Salfred [URIO_T_RD] = { 139184610Salfred .type = UE_BULK, 140184610Salfred .endpoint = UE_ADDR_ANY, 141184610Salfred .direction = UE_DIR_IN, 142190734Sthompsa .bufsize = URIO_BSIZE, 143190734Sthompsa .flags = {.pipe_bof = 1,.short_xfer_ok = 1,.proxy_buffer = 1,}, 144190734Sthompsa .callback = &urio_read_callback, 145184610Salfred }, 146184610Salfred 147184610Salfred [URIO_T_WR_CS] = { 148184610Salfred .type = UE_CONTROL, 149184610Salfred .endpoint = 0x00, /* Control pipe */ 150184610Salfred .direction = UE_DIR_ANY, 151190734Sthompsa .bufsize = sizeof(struct usb2_device_request), 152190734Sthompsa .callback = &urio_write_clear_stall_callback, 153190734Sthompsa .timeout = 1000, /* 1 second */ 154190734Sthompsa .interval = 50, /* 50ms */ 155184610Salfred }, 156184610Salfred 157184610Salfred [URIO_T_RD_CS] = { 158184610Salfred .type = UE_CONTROL, 159184610Salfred .endpoint = 0x00, /* Control pipe */ 160184610Salfred .direction = UE_DIR_ANY, 161190734Sthompsa .bufsize = sizeof(struct usb2_device_request), 162190734Sthompsa .callback = &urio_read_clear_stall_callback, 163190734Sthompsa .timeout = 1000, /* 1 second */ 164190734Sthompsa .interval = 50, /* 50ms */ 165184610Salfred }, 166184610Salfred}; 167184610Salfred 168184610Salfredstatic devclass_t urio_devclass; 169184610Salfred 170184610Salfredstatic device_method_t urio_methods[] = { 171184610Salfred /* Device interface */ 172184610Salfred DEVMETHOD(device_probe, urio_probe), 173184610Salfred DEVMETHOD(device_attach, urio_attach), 174184610Salfred DEVMETHOD(device_detach, urio_detach), 175184610Salfred {0, 0} 176184610Salfred}; 177184610Salfred 178184610Salfredstatic driver_t urio_driver = { 179184610Salfred .name = "urio", 180184610Salfred .methods = urio_methods, 181184610Salfred .size = sizeof(struct urio_softc), 182184610Salfred}; 183184610Salfred 184189275SthompsaDRIVER_MODULE(urio, uhub, urio_driver, urio_devclass, NULL, 0); 185188942SthompsaMODULE_DEPEND(urio, usb, 1, 1, 1); 186184610Salfred 187184610Salfredstatic int 188184610Salfredurio_probe(device_t dev) 189184610Salfred{ 190184610Salfred struct usb2_attach_arg *uaa = device_get_ivars(dev); 191184610Salfred 192192499Sthompsa if (uaa->usb_mode != USB_MODE_HOST) { 193184610Salfred return (ENXIO); 194184610Salfred } 195184610Salfred if ((((uaa->info.idVendor == USB_VENDOR_DIAMOND) && 196184610Salfred (uaa->info.idProduct == USB_PRODUCT_DIAMOND_RIO500USB)) || 197184610Salfred ((uaa->info.idVendor == USB_VENDOR_DIAMOND2) && 198184610Salfred ((uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO600USB) || 199184610Salfred (uaa->info.idProduct == USB_PRODUCT_DIAMOND2_RIO800USB))))) 200184610Salfred return (0); 201184610Salfred else 202184610Salfred return (ENXIO); 203184610Salfred} 204184610Salfred 205184610Salfredstatic int 206184610Salfredurio_attach(device_t dev) 207184610Salfred{ 208184610Salfred struct usb2_attach_arg *uaa = device_get_ivars(dev); 209184610Salfred struct urio_softc *sc = device_get_softc(dev); 210184610Salfred int error; 211184610Salfred 212184610Salfred device_set_usb2_desc(dev); 213184610Salfred 214184610Salfred sc->sc_udev = uaa->device; 215184610Salfred 216184610Salfred mtx_init(&sc->sc_mtx, "urio lock", NULL, MTX_DEF | MTX_RECURSE); 217184610Salfred 218184610Salfred snprintf(sc->sc_name, sizeof(sc->sc_name), 219184610Salfred "%s", device_get_nameunit(dev)); 220184610Salfred 221184610Salfred error = usb2_transfer_setup(uaa->device, 222184610Salfred &uaa->info.bIfaceIndex, sc->sc_xfer, 223184610Salfred urio_config, URIO_T_MAX, sc, &sc->sc_mtx); 224184610Salfred 225184610Salfred if (error) { 226184610Salfred DPRINTF("error=%s\n", usb2_errstr(error)); 227184610Salfred goto detach; 228184610Salfred } 229184610Salfred 230184610Salfred error = usb2_fifo_attach(uaa->device, sc, &sc->sc_mtx, 231184610Salfred &urio_fifo_methods, &sc->sc_fifo, 232189110Sthompsa device_get_unit(dev), 0 - 1, uaa->info.bIfaceIndex, 233189110Sthompsa UID_ROOT, GID_OPERATOR, 0644); 234184610Salfred if (error) { 235184610Salfred goto detach; 236184610Salfred } 237184610Salfred return (0); /* success */ 238184610Salfred 239184610Salfreddetach: 240184610Salfred urio_detach(dev); 241184610Salfred return (ENOMEM); /* failure */ 242184610Salfred} 243184610Salfred 244184610Salfredstatic void 245184610Salfredurio_write_callback(struct usb2_xfer *xfer) 246184610Salfred{ 247184610Salfred struct urio_softc *sc = xfer->priv_sc; 248184610Salfred struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_TX]; 249184610Salfred uint32_t actlen; 250184610Salfred 251184610Salfred switch (USB_GET_STATE(xfer)) { 252184610Salfred case USB_ST_TRANSFERRED: 253184610Salfred case USB_ST_SETUP: 254184610Salfred if (sc->sc_flags & URIO_FLAG_WRITE_STALL) { 255184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_WR_CS]); 256184610Salfred return; 257184610Salfred } 258184610Salfred if (usb2_fifo_get_data(f, xfer->frbuffers, 0, 259184610Salfred xfer->max_data_length, &actlen, 0)) { 260184610Salfred 261184610Salfred xfer->frlengths[0] = actlen; 262184610Salfred usb2_start_hardware(xfer); 263184610Salfred } 264184610Salfred return; 265184610Salfred 266184610Salfred default: /* Error */ 267184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 268184610Salfred /* try to clear stall first */ 269184610Salfred sc->sc_flags |= URIO_FLAG_WRITE_STALL; 270184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_WR_CS]); 271184610Salfred } 272184610Salfred return; 273184610Salfred } 274184610Salfred} 275184610Salfred 276184610Salfredstatic void 277184610Salfredurio_write_clear_stall_callback(struct usb2_xfer *xfer) 278184610Salfred{ 279184610Salfred struct urio_softc *sc = xfer->priv_sc; 280184610Salfred struct usb2_xfer *xfer_other = sc->sc_xfer[URIO_T_WR]; 281184610Salfred 282184610Salfred if (usb2_clear_stall_callback(xfer, xfer_other)) { 283184610Salfred DPRINTF("stall cleared\n"); 284184610Salfred sc->sc_flags &= ~URIO_FLAG_WRITE_STALL; 285184610Salfred usb2_transfer_start(xfer_other); 286184610Salfred } 287184610Salfred} 288184610Salfred 289184610Salfredstatic void 290184610Salfredurio_read_callback(struct usb2_xfer *xfer) 291184610Salfred{ 292184610Salfred struct urio_softc *sc = xfer->priv_sc; 293184610Salfred struct usb2_fifo *f = sc->sc_fifo.fp[USB_FIFO_RX]; 294184610Salfred 295184610Salfred switch (USB_GET_STATE(xfer)) { 296184610Salfred case USB_ST_TRANSFERRED: 297184610Salfred usb2_fifo_put_data(f, xfer->frbuffers, 0, 298184610Salfred xfer->actlen, 1); 299184610Salfred 300184610Salfred case USB_ST_SETUP: 301184610Salfred if (sc->sc_flags & URIO_FLAG_READ_STALL) { 302184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_RD_CS]); 303184610Salfred return; 304184610Salfred } 305184610Salfred if (usb2_fifo_put_bytes_max(f) != 0) { 306184610Salfred xfer->frlengths[0] = xfer->max_data_length; 307184610Salfred usb2_start_hardware(xfer); 308184610Salfred } 309184610Salfred return; 310184610Salfred 311184610Salfred default: /* Error */ 312184610Salfred if (xfer->error != USB_ERR_CANCELLED) { 313184610Salfred /* try to clear stall first */ 314184610Salfred sc->sc_flags |= URIO_FLAG_READ_STALL; 315184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_RD_CS]); 316184610Salfred } 317184610Salfred return; 318184610Salfred } 319184610Salfred} 320184610Salfred 321184610Salfredstatic void 322184610Salfredurio_read_clear_stall_callback(struct usb2_xfer *xfer) 323184610Salfred{ 324184610Salfred struct urio_softc *sc = xfer->priv_sc; 325184610Salfred struct usb2_xfer *xfer_other = sc->sc_xfer[URIO_T_RD]; 326184610Salfred 327184610Salfred if (usb2_clear_stall_callback(xfer, xfer_other)) { 328184610Salfred DPRINTF("stall cleared\n"); 329184610Salfred sc->sc_flags &= ~URIO_FLAG_READ_STALL; 330184610Salfred usb2_transfer_start(xfer_other); 331184610Salfred } 332184610Salfred} 333184610Salfred 334184610Salfredstatic void 335184610Salfredurio_start_read(struct usb2_fifo *fifo) 336184610Salfred{ 337184610Salfred struct urio_softc *sc = fifo->priv_sc0; 338184610Salfred 339184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_RD]); 340184610Salfred} 341184610Salfred 342184610Salfredstatic void 343184610Salfredurio_stop_read(struct usb2_fifo *fifo) 344184610Salfred{ 345184610Salfred struct urio_softc *sc = fifo->priv_sc0; 346184610Salfred 347184610Salfred usb2_transfer_stop(sc->sc_xfer[URIO_T_RD_CS]); 348184610Salfred usb2_transfer_stop(sc->sc_xfer[URIO_T_RD]); 349184610Salfred} 350184610Salfred 351184610Salfredstatic void 352184610Salfredurio_start_write(struct usb2_fifo *fifo) 353184610Salfred{ 354184610Salfred struct urio_softc *sc = fifo->priv_sc0; 355184610Salfred 356184610Salfred usb2_transfer_start(sc->sc_xfer[URIO_T_WR]); 357184610Salfred} 358184610Salfred 359184610Salfredstatic void 360184610Salfredurio_stop_write(struct usb2_fifo *fifo) 361184610Salfred{ 362184610Salfred struct urio_softc *sc = fifo->priv_sc0; 363184610Salfred 364184610Salfred usb2_transfer_stop(sc->sc_xfer[URIO_T_WR_CS]); 365184610Salfred usb2_transfer_stop(sc->sc_xfer[URIO_T_WR]); 366184610Salfred} 367184610Salfred 368184610Salfredstatic int 369189110Sthompsaurio_open(struct usb2_fifo *fifo, int fflags) 370184610Salfred{ 371184610Salfred struct urio_softc *sc = fifo->priv_sc0; 372184610Salfred 373184610Salfred if ((fflags & (FWRITE | FREAD)) != (FWRITE | FREAD)) { 374184610Salfred return (EACCES); 375184610Salfred } 376184610Salfred if (fflags & FREAD) { 377184610Salfred /* clear stall first */ 378184610Salfred mtx_lock(&sc->sc_mtx); 379184610Salfred sc->sc_flags |= URIO_FLAG_READ_STALL; 380184610Salfred mtx_unlock(&sc->sc_mtx); 381184610Salfred 382184610Salfred if (usb2_fifo_alloc_buffer(fifo, 383184610Salfred sc->sc_xfer[URIO_T_RD]->max_data_length, 384184610Salfred URIO_IFQ_MAXLEN)) { 385184610Salfred return (ENOMEM); 386184610Salfred } 387184610Salfred } 388184610Salfred if (fflags & FWRITE) { 389184610Salfred /* clear stall first */ 390184610Salfred sc->sc_flags |= URIO_FLAG_WRITE_STALL; 391184610Salfred 392184610Salfred if (usb2_fifo_alloc_buffer(fifo, 393184610Salfred sc->sc_xfer[URIO_T_WR]->max_data_length, 394184610Salfred URIO_IFQ_MAXLEN)) { 395184610Salfred return (ENOMEM); 396184610Salfred } 397184610Salfred } 398184610Salfred return (0); /* success */ 399184610Salfred} 400184610Salfred 401184610Salfredstatic void 402189110Sthompsaurio_close(struct usb2_fifo *fifo, int fflags) 403184610Salfred{ 404184610Salfred if (fflags & (FREAD | FWRITE)) { 405184610Salfred usb2_fifo_free_buffer(fifo); 406184610Salfred } 407184610Salfred} 408184610Salfred 409184610Salfredstatic int 410184610Salfredurio_ioctl(struct usb2_fifo *fifo, u_long cmd, void *addr, 411189110Sthompsa int fflags) 412184610Salfred{ 413184610Salfred struct usb2_ctl_request ur; 414184610Salfred struct RioCommand *rio_cmd; 415184610Salfred int error; 416184610Salfred 417184610Salfred switch (cmd) { 418184610Salfred case RIO_RECV_COMMAND: 419184610Salfred if (!(fflags & FWRITE)) { 420184610Salfred error = EPERM; 421184610Salfred goto done; 422184610Salfred } 423184610Salfred bzero(&ur, sizeof(ur)); 424184610Salfred rio_cmd = addr; 425184610Salfred ur.ucr_request.bmRequestType = 426184610Salfred rio_cmd->requesttype | UT_READ_VENDOR_DEVICE; 427184610Salfred break; 428184610Salfred 429184610Salfred case RIO_SEND_COMMAND: 430184610Salfred if (!(fflags & FWRITE)) { 431184610Salfred error = EPERM; 432184610Salfred goto done; 433184610Salfred } 434184610Salfred bzero(&ur, sizeof(ur)); 435184610Salfred rio_cmd = addr; 436184610Salfred ur.ucr_request.bmRequestType = 437184610Salfred rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE; 438184610Salfred break; 439184610Salfred 440184610Salfred default: 441184610Salfred error = EINVAL; 442184610Salfred goto done; 443184610Salfred } 444184610Salfred 445184610Salfred DPRINTFN(2, "Sending command\n"); 446184610Salfred 447184610Salfred /* Send rio control message */ 448184610Salfred ur.ucr_request.bRequest = rio_cmd->request; 449184610Salfred USETW(ur.ucr_request.wValue, rio_cmd->value); 450184610Salfred USETW(ur.ucr_request.wIndex, rio_cmd->index); 451184610Salfred USETW(ur.ucr_request.wLength, rio_cmd->length); 452184610Salfred ur.ucr_data = rio_cmd->buffer; 453184610Salfred 454184610Salfred /* reuse generic USB code */ 455184610Salfred error = ugen_do_request(fifo, &ur); 456184610Salfred 457184610Salfreddone: 458184610Salfred return (error); 459184610Salfred} 460184610Salfred 461184610Salfredstatic int 462184610Salfredurio_detach(device_t dev) 463184610Salfred{ 464184610Salfred struct urio_softc *sc = device_get_softc(dev); 465184610Salfred 466184610Salfred DPRINTF("\n"); 467184610Salfred 468184610Salfred usb2_fifo_detach(&sc->sc_fifo); 469184610Salfred 470184610Salfred usb2_transfer_unsetup(sc->sc_xfer, URIO_T_MAX); 471184610Salfred 472184610Salfred mtx_destroy(&sc->sc_mtx); 473184610Salfred 474184610Salfred return (0); 475184610Salfred} 476