File:  [DragonFly] / src / sys / dev / usbmisc / urio / urio.c
Revision 1.9: download - view: text, annotated - select for diffs
Thu May 13 23:49:22 2004 UTC (10 years, 6 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

    1: /*
    2:  * Copyright (c) 2000 Iwasa Kazmi
    3:  * All rights reserved.
    4:  *
    5:  * Redistribution and use in source and binary forms, with or without
    6:  * modification, are permitted provided that the following conditions
    7:  * are met:
    8:  * 1. Redistributions of source code must retain the above copyright
    9:  *    notice, this list of conditions, and the following disclaimer.
   10:  * 2. Redistributions in binary form must reproduce the above copyright
   11:  *    notice, this list of conditions and the following disclaimer in the
   12:  *    documentation and/or other materials provided with the distribution.
   13:  *
   14:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   18:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24:  * SUCH DAMAGE.
   25:  *
   26:  * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson.
   27:  * This code includes software developed by the NetBSD Foundation, Inc. and
   28:  * its contributors.
   29:  */
   30: 
   31: /*
   32:  * $FreeBSD: src/sys/dev/usb/urio.c,v 1.28 2003/08/25 22:01:06 joe Exp $
   33:  * $DragonFly: src/sys/dev/usbmisc/urio/urio.c,v 1.9 2004/05/13 23:49:22 dillon Exp $
   34:  */
   35: 
   36: /*
   37:  * 2000/3/24  added NetBSD/OpenBSD support (from Alex Nemirovsky)
   38:  * 2000/3/07  use two bulk-pipe handles for read and write (Dirk)
   39:  * 2000/3/06  change major number(143), and copyright header
   40:  *            some fix for 4.0 (Dirk)
   41:  * 2000/3/05  codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik)
   42:  * 2000/3/01  remove retry code from urioioctl()
   43:  *            change method of bulk transfer (no interrupt)
   44:  * 2000/2/28  small fixes for new rio_usb.h
   45:  * 2000/2/24  first version.
   46:  */
   47: 
   48: #include <sys/param.h>
   49: #include <sys/systm.h>
   50: #include <sys/kernel.h>
   51: #include <sys/malloc.h>
   52: #if defined(__NetBSD__)
   53: #include <sys/device.h>
   54: #include <sys/ioctl.h>
   55: #elif defined(__FreeBSD__) || defined(__DragonFly__)
   56: #include <sys/module.h>
   57: #include <sys/bus.h>
   58: #include <sys/ioccom.h>
   59: #endif
   60: #include <sys/fcntl.h>
   61: #include <sys/filio.h>
   62: #include <sys/conf.h>
   63: #include <sys/uio.h>
   64: #include <sys/tty.h>
   65: #include <sys/file.h>
   66: #if defined(__FreeBSD__) && __FreeBSD_version >= 500014
   67: #include <sys/selinfo.h>
   68: #else
   69: #include <sys/select.h>
   70: #endif
   71: #include <sys/vnode.h>
   72: #include <sys/poll.h>
   73: #include <sys/sysctl.h>
   74: #include <sys/proc.h>
   75: 
   76: #include <bus/usb/usb.h>
   77: #include <bus/usb/usbdi.h>
   78: #include <bus/usb/usbdi_util.h>
   79: 
   80: #include <bus/usb/usbdevs.h>
   81: #include <bus/usb/rio500_usb.h>
   82: 
   83: #ifdef USB_DEBUG
   84: #define DPRINTF(x)	if (uriodebug) logprintf x
   85: #define DPRINTFN(n,x)	if (uriodebug>(n)) logprintf x
   86: int	uriodebug = 0;
   87: SYSCTL_NODE(_hw_usb, OID_AUTO, urio, CTLFLAG_RW, 0, "USB urio");
   88: SYSCTL_INT(_hw_usb_urio, OID_AUTO, debug, CTLFLAG_RW,
   89: 	   &uriodebug, 0, "urio debug level");
   90: #else
   91: #define DPRINTF(x)
   92: #define DPRINTFN(n,x)
   93: #endif
   94: 
   95: /* difference of usbd interface */
   96: #define USBDI 1
   97: 
   98: #define RIO_OUT 0
   99: #define RIO_IN  1
  100: #define RIO_NODIR  2
  101: 
  102: #if defined(__NetBSD__)
  103: int urioopen(dev_t, int, int, struct proc *);
  104: int urioclose(dev_t, int, int, struct proc *p);
  105: int urioread(dev_t, struct uio *uio, int);
  106: int uriowrite(dev_t, struct uio *uio, int);
  107: int urioioctl(dev_t, u_long, caddr_t, int, struct proc *);
  108: 
  109: cdev_decl(urio);
  110: #define RIO_UE_GET_DIR(p) ((UE_GET_DIR(p) == UE_DIR_IN) ? RIO_IN :\
  111: 			  ((UE_GET_DIR(p) == UE_DIR_OUT) ? RIO_OUT :\
  112: 							   RIO_NODIR))
  113: #elif defined(__FreeBSD__) || defined(__DragonFly__)
  114: d_open_t  urioopen;
  115: d_close_t urioclose;
  116: d_read_t  urioread;
  117: d_write_t uriowrite;
  118: d_ioctl_t urioioctl;
  119: 
  120: #define URIO_CDEV_MAJOR	143
  121: 
  122: Static struct cdevsw urio_cdevsw = {
  123:  	/* name */	"urio",		
  124: 	/* cmaj */	URIO_CDEV_MAJOR,
  125:  	/* flags */	0,
  126: 	/* port */	NULL,
  127: 	/* clone */	NULL,
  128: 	urioopen,	urioclose,	urioread,	uriowrite,
  129:  	urioioctl,	nopoll,		nommap,		nostrategy,
  130: 	nodump,		nopsize
  131: };
  132: #define RIO_UE_GET_DIR(p) ((UE_GET_DIR(p) == UE_DIR_IN) ? RIO_IN :\
  133: 		 	  ((UE_GET_DIR(p) == UE_DIR_OUT) ? RIO_OUT :\
  134: 			    				   RIO_NODIR))
  135: #endif  /*defined(__FreeBSD__)*/
  136: 
  137: #define	URIO_BBSIZE	1024
  138: 
  139: struct urio_softc {
  140:  	USBBASEDEVICE sc_dev;
  141: 	usbd_device_handle sc_udev;
  142: 	usbd_interface_handle sc_iface;
  143: 
  144: 	int sc_opened;
  145: 	usbd_pipe_handle sc_pipeh_in;
  146: 	usbd_pipe_handle sc_pipeh_out;
  147: 	int sc_epaddr[2];
  148: 
  149: 	int sc_refcnt;
  150: #if defined(__FreeBSD__) || defined(__DragonFly__)
  151: 	dev_t sc_dev_t;
  152: #endif	/* defined(__FreeBSD__) */
  153: #if defined(__NetBSD__) || defined(__OpenBSD__)
  154: 	u_char sc_dying;
  155: #endif
  156: };
  157: 
  158: #define URIOUNIT(n) (minor(n))
  159: 
  160: #define RIO_RW_TIMEOUT 4000	/* ms */
  161: 
  162: USB_DECLARE_DRIVER(urio);
  163: 
  164: USB_MATCH(urio)
  165: {
  166: 	USB_MATCH_START(urio, uaa);
  167: 	usb_device_descriptor_t *dd;
  168: 
  169: 	DPRINTFN(10,("urio_match\n"));
  170: 	if (!uaa->iface)
  171: 		return UMATCH_NONE;
  172: 
  173: 	dd = usbd_get_device_descriptor(uaa->device);
  174: 
  175: 	if (dd &&
  176: 	    ((UGETW(dd->idVendor) == USB_VENDOR_DIAMOND &&
  177: 	    UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND_RIO500USB) ||
  178: 	    (UGETW(dd->idVendor) == USB_VENDOR_DIAMOND2 &&
  179: 	      (UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND2_RIO600USB ||
  180: 	      UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND2_RIO800USB))))
  181: 		return UMATCH_VENDOR_PRODUCT;
  182: 	else
  183: 		return UMATCH_NONE;
  184: }
  185: 
  186: USB_ATTACH(urio)
  187: {
  188: 	USB_ATTACH_START(urio, sc, uaa);
  189: 	char devinfo[1024];
  190: 	usbd_device_handle udev;
  191: 	usbd_interface_handle iface;
  192: 	u_int8_t epcount;
  193: #if defined(__NetBSD__) || defined(__OpenBSD__)
  194: 	u_int8_t niface;
  195: #endif
  196: 	usbd_status r;
  197: 	char * ermsg = "<none>";
  198: 	int i;
  199: 
  200: 	DPRINTFN(10,("urio_attach: sc=%p\n", sc));
  201: 	usbd_devinfo(uaa->device, 0, devinfo);
  202: 	USB_ATTACH_SETUP;
  203: 	printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
  204: 
  205: 	sc->sc_udev = udev = uaa->device;
  206: 
  207: #if defined(__FreeBSD__) || defined(__DragonFly__)
  208:  	if ((!uaa->device) || (!uaa->iface)) {
  209: 		ermsg = "device or iface";
  210:  		goto nobulk;
  211: 	}
  212: 	sc->sc_iface = iface = uaa->iface;
  213: #elif defined(__NetBSD__) || defined(__OpenBSD__)
  214:  	if (!udev) {
  215: 		ermsg = "device";
  216:  		goto nobulk;
  217: 	}
  218: 	r = usbd_interface_count(udev, &niface);
  219: 	if (r) {
  220: 		ermsg = "iface";
  221: 		goto nobulk;
  222: 	}
  223: 	r = usbd_device2interface_handle(udev, 0, &iface);
  224: 	if (r) {
  225: 		ermsg = "iface";
  226: 		goto nobulk;
  227: 	}
  228: 	sc->sc_iface = iface;
  229: #endif
  230: 	sc->sc_opened = 0;
  231: 	sc->sc_pipeh_in = 0;
  232: 	sc->sc_pipeh_out = 0;
  233: 	sc->sc_refcnt = 0;
  234: 
  235: 	r = usbd_endpoint_count(iface, &epcount);
  236: 	if (r != USBD_NORMAL_COMPLETION) {
  237: 		ermsg = "endpoints";
  238: 		goto nobulk;
  239: 	}
  240: 
  241: 	sc->sc_epaddr[RIO_OUT] = 0xff;
  242: 	sc->sc_epaddr[RIO_IN] = 0x00;
  243: 
  244: 	for (i = 0; i < epcount; i++) {
  245: 		usb_endpoint_descriptor_t *edesc =
  246: 			usbd_interface2endpoint_descriptor(iface, i);
  247: 		int d;
  248: 
  249: 		if (!edesc) {
  250: 			ermsg = "interface endpoint";
  251: 			goto nobulk;
  252: 		}
  253: 
  254: 		d = RIO_UE_GET_DIR(edesc->bEndpointAddress);
  255: 		if (d != RIO_NODIR)
  256: 			sc->sc_epaddr[d] = edesc->bEndpointAddress;
  257: 	}
  258: 	if ( sc->sc_epaddr[RIO_OUT] == 0xff ||
  259: 	     sc->sc_epaddr[RIO_IN] == 0x00) {
  260: 		ermsg = "Rio I&O";
  261: 		goto nobulk;
  262: 	}
  263: 
  264: #if defined(__FreeBSD__) || defined(__DragonFly__)
  265: 	/* XXX no error trapping, no storing of dev_t */
  266: 	sc->sc_dev_t = make_dev(&urio_cdevsw, device_get_unit(self),
  267: 			UID_ROOT, GID_OPERATOR,
  268: 			0644, "urio%d", device_get_unit(self));
  269: #elif defined(__NetBSD__) || defined(__OpenBSD__)
  270: 	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
  271: 			   USBDEV(sc->sc_dev));
  272: #endif
  273: 
  274: 	DPRINTFN(10, ("urio_attach: %p\n", sc->sc_udev));
  275: 
  276: 	USB_ATTACH_SUCCESS_RETURN;
  277: 
  278:  nobulk:
  279: 	printf("%s: could not find %s\n", USBDEVNAME(sc->sc_dev),ermsg);
  280: 	USB_ATTACH_ERROR_RETURN;
  281: }
  282: 
  283: 
  284: int
  285: urioopen(dev_t dev, int flag, int mode, usb_proc_ptr p)
  286: {
  287: #if (USBDI >= 1)
  288: 	struct urio_softc * sc;
  289: #endif
  290: 	int unit = URIOUNIT(dev);
  291: 	USB_GET_SC_OPEN(urio, unit, sc);
  292: 
  293: 	DPRINTFN(5, ("urioopen: flag=%d, mode=%d, unit=%d\n",
  294: 		     flag, mode, unit));
  295: 
  296: 	if (sc->sc_opened)
  297: 		return EBUSY;
  298: 
  299: 	if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD))
  300: 		return EACCES;
  301: 
  302: 	sc->sc_opened = 1;
  303: 	sc->sc_pipeh_in = 0;
  304: 	sc->sc_pipeh_out = 0;
  305: 	if (usbd_open_pipe(sc->sc_iface,
  306: 		sc->sc_epaddr[RIO_IN], 0, &sc->sc_pipeh_in)
  307: 	   		!= USBD_NORMAL_COMPLETION)
  308: 	{
  309: 			sc->sc_pipeh_in = 0;
  310: 			return EIO;
  311: 	};
  312: 	if (usbd_open_pipe(sc->sc_iface,
  313: 		sc->sc_epaddr[RIO_OUT], 0, &sc->sc_pipeh_out)
  314: 	   		!= USBD_NORMAL_COMPLETION)
  315: 	{
  316: 			usbd_close_pipe(sc->sc_pipeh_in);
  317: 			sc->sc_pipeh_in = 0;
  318: 			sc->sc_pipeh_out = 0;
  319: 			return EIO;
  320: 	};
  321: 	return 0;
  322: }
  323: 
  324: int
  325: urioclose(dev_t dev, int flag, int mode, usb_proc_ptr p)
  326: {
  327: #if (USBDI >= 1)
  328: 	struct urio_softc * sc;
  329: #endif
  330: 	int unit = URIOUNIT(dev);
  331: 	USB_GET_SC(urio, unit, sc);
  332: 
  333: 	DPRINTFN(5, ("urioclose: flag=%d, mode=%d, unit=%d\n", flag, mode, unit));
  334: 	if (sc->sc_pipeh_in)
  335: 		usbd_close_pipe(sc->sc_pipeh_in);
  336: 
  337: 	if (sc->sc_pipeh_out)
  338: 		usbd_close_pipe(sc->sc_pipeh_out);
  339: 
  340: 	sc->sc_pipeh_in = 0;
  341: 	sc->sc_pipeh_out = 0;
  342: 	sc->sc_opened = 0;
  343: 	sc->sc_refcnt = 0;
  344: 	return 0;
  345: }
  346: 
  347: int
  348: urioread(dev_t dev, struct uio *uio, int flag)
  349: {
  350: #if (USBDI >= 1)
  351: 	struct urio_softc * sc;
  352: 	usbd_xfer_handle reqh;
  353: #else
  354: 	usbd_request_handle reqh;
  355: 	usbd_private_handle r_priv;
  356:         void *r_buff;
  357:         usbd_status r_status;
  358: #endif
  359: 	int unit = URIOUNIT(dev);
  360: 	usbd_status r;
  361: 	char buf[URIO_BBSIZE];
  362: 	u_int32_t n, tn;
  363: 	int error = 0;
  364: 
  365: 	USB_GET_SC(urio, unit, sc);
  366: 
  367: 	DPRINTFN(5, ("urioread: %d\n", unit));
  368: 	if (!sc->sc_opened)
  369: 		return EIO;
  370: 
  371: #if (USBDI >= 1)
  372: 	sc->sc_refcnt++;
  373: 	reqh = usbd_alloc_xfer(sc->sc_udev);
  374: #else
  375: 	reqh = usbd_alloc_request();
  376: #endif
  377: 	if (reqh == 0)
  378: 		return ENOMEM;
  379: 	while ((n = min(URIO_BBSIZE, uio->uio_resid)) != 0) {
  380: 		DPRINTFN(1, ("urioread: start transfer %d bytes\n", n));
  381: 		tn = n;
  382: #if (USBDI >= 1)
  383:  		usbd_setup_xfer(reqh, sc->sc_pipeh_in, 0, buf, tn,
  384: 				       0, RIO_RW_TIMEOUT, 0);
  385: #else
  386: 		r = usbd_setup_request(reqh, sc->sc_pipeh_in, 0, buf, tn,
  387: 				       0, RIO_RW_TIMEOUT, 0);
  388: 		if (r != USBD_NORMAL_COMPLETION) {
  389: 			error = EIO;
  390: 			break;
  391: 		}
  392: #endif
  393: 		r = usbd_sync_transfer(reqh);
  394: 		if (r != USBD_NORMAL_COMPLETION) {
  395: 			DPRINTFN(1, ("urioread: error=%d\n", r));
  396: 			usbd_clear_endpoint_stall(sc->sc_pipeh_in);
  397: 			tn = 0;
  398: 			error = EIO;
  399: 			break;
  400: 		}
  401: #if (USBDI >= 1)
  402: 		usbd_get_xfer_status(reqh, 0, 0, &tn, 0);
  403: #else
  404: 		usbd_get_request_status(reqh, &r_priv, &r_buff, &tn, &r_status);
  405: #endif
  406: 
  407: 		DPRINTFN(1, ("urioread: got %d bytes\n", tn));
  408: 		error = uiomove(buf, tn, uio);
  409: 		if (error || tn < n)
  410: 			break;
  411: 	}
  412: #if (USBDI >= 1)
  413: 	usbd_free_xfer(reqh);
  414: #else
  415: 	usbd_free_request(reqh);
  416: #endif
  417: 
  418: 	return error;
  419: }
  420: 
  421: int
  422: uriowrite(dev_t dev, struct uio *uio, int flag)
  423: {
  424: #if (USBDI >= 1)
  425: 	struct urio_softc * sc;
  426: 	usbd_xfer_handle reqh;
  427: #else
  428: 	usbd_request_handle reqh;
  429: #endif
  430: 	int unit = URIOUNIT(dev);
  431: 	usbd_status r;
  432: 	char buf[URIO_BBSIZE];
  433: 	u_int32_t n;
  434: 	int error = 0;
  435: 
  436: 	USB_GET_SC(urio, unit, sc);
  437: 
  438: 	DPRINTFN(5, ("uriowrite: %d\n", unit));
  439: 	if (!sc->sc_opened)
  440: 		return EIO;
  441: 
  442: #if (USBDI >= 1)
  443: 	sc->sc_refcnt++;
  444: 	reqh = usbd_alloc_xfer(sc->sc_udev);
  445: #else
  446: 	reqh = usbd_alloc_request();
  447: #endif
  448: 	if (reqh == 0)
  449: 		return EIO;
  450: 	while ((n = min(URIO_BBSIZE, uio->uio_resid)) != 0) {
  451: 		error = uiomove(buf, n, uio);
  452: 		if (error)
  453: 			break;
  454: 		DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n));
  455: #if (USBDI >= 1)
  456:  		usbd_setup_xfer(reqh, sc->sc_pipeh_out, 0, buf, n,
  457: 				       0, RIO_RW_TIMEOUT, 0);
  458: #else
  459: 		r = usbd_setup_request(reqh, sc->sc_pipeh_out, 0, buf, n,
  460: 				       0, RIO_RW_TIMEOUT, 0);
  461: 		if (r != USBD_NORMAL_COMPLETION) {
  462: 			error = EIO;
  463: 			break;
  464: 		}
  465: #endif
  466: 		r = usbd_sync_transfer(reqh);
  467: 		if (r != USBD_NORMAL_COMPLETION) {
  468: 			DPRINTFN(1, ("uriowrite: error=%d\n", r));
  469: 			usbd_clear_endpoint_stall(sc->sc_pipeh_out);
  470: 			error = EIO;
  471: 			break;
  472: 		}
  473: #if (USBDI >= 1)
  474: 		usbd_get_xfer_status(reqh, 0, 0, 0, 0);
  475: #endif
  476: 	}
  477: 
  478: #if (USBDI >= 1)
  479: 	usbd_free_xfer(reqh);
  480: #else
  481: 	usbd_free_request(reqh);
  482: #endif
  483: 
  484: 	return error;
  485: }
  486: 
  487: 
  488: int
  489: urioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p)
  490: {
  491: #if (USBDI >= 1)
  492: 	struct urio_softc * sc;
  493: #endif
  494: 	int unit = URIOUNIT(dev);
  495: 	struct RioCommand *rio_cmd;
  496: 	int requesttype, len;
  497: 	struct iovec iov;
  498: 	struct uio uio;
  499: 	usb_device_request_t req;
  500: 	int req_flags = 0, req_actlen = 0;
  501: 	void *ptr = 0;
  502: 	int error = 0;
  503: 	usbd_status r;
  504: 
  505: 	USB_GET_SC(urio, unit, sc);
  506: 
  507: 	switch (cmd) {
  508: 	case RIO_RECV_COMMAND:
  509: 		if (!(flag & FWRITE))
  510: 			return EPERM;
  511: 		rio_cmd = (struct RioCommand *)addr;
  512: 		if (rio_cmd == NULL)
  513: 			return EINVAL;
  514: 		len = rio_cmd->length;
  515: 
  516: 		requesttype = rio_cmd->requesttype | UT_READ_VENDOR_DEVICE;
  517: 		DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n",
  518: 			requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len));
  519: 		break;
  520: 
  521: 	case RIO_SEND_COMMAND:
  522: 		if (!(flag & FWRITE))
  523: 			return EPERM;
  524: 		rio_cmd = (struct RioCommand *)addr;
  525: 		if (rio_cmd == NULL)
  526: 			return EINVAL;
  527: 		len = rio_cmd->length;
  528: 
  529: 		requesttype = rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE;
  530: 		DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n",
  531: 			requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len));
  532: 		break;
  533: 
  534: 	default:
  535: 		return EINVAL;
  536: 		break;
  537: 	}
  538: 
  539: 	/* Send rio control message */
  540: 	req.bmRequestType = requesttype;
  541: 	req.bRequest = rio_cmd->request;
  542: 	USETW(req.wValue, rio_cmd->value);
  543: 	USETW(req.wIndex, rio_cmd->index);
  544: 	USETW(req.wLength, len);
  545: 
  546: 	if (len < 0 || len > 32767)
  547: 		return EINVAL;
  548: 	if (len != 0) {
  549: 		iov.iov_base = (caddr_t)rio_cmd->buffer;
  550: 		iov.iov_len = len;
  551: 		uio.uio_iov = &iov;
  552: 		uio.uio_iovcnt = 1;
  553: 		uio.uio_resid = len;
  554: 		uio.uio_offset = 0;
  555: 		uio.uio_segflg = UIO_USERSPACE;
  556: 		uio.uio_rw =
  557: 			req.bmRequestType & UT_READ ?
  558: 			UIO_READ : UIO_WRITE;
  559: 		uio.uio_td = p;
  560: 		ptr = malloc(len, M_TEMP, M_WAITOK);
  561: 		if (uio.uio_rw == UIO_WRITE) {
  562: 			error = uiomove(ptr, len, &uio);
  563: 			if (error)
  564: 				goto ret;
  565: 		}
  566: 	}
  567: 
  568: 	r = usbd_do_request_flags(sc->sc_udev, &req,
  569: 				  ptr, req_flags, &req_actlen,
  570: 				  USBD_DEFAULT_TIMEOUT);
  571: 	if (r == USBD_NORMAL_COMPLETION) {
  572: 		error = 0;
  573: 		if (len != 0) {
  574: 			if (uio.uio_rw == UIO_READ) {
  575: 				error = uiomove(ptr, len, &uio);
  576: 			}
  577: 		}
  578: 	} else {
  579: 		error = EIO;
  580: 	}
  581: 
  582: ret:
  583: 	if (ptr)
  584: 		free(ptr, M_TEMP);
  585: 	return error;
  586: }
  587: 
  588: 
  589: #if defined(__NetBSD__) || defined(__OpenBSD__)
  590: int
  591: urio_activate(device_ptr_t self, enum devact act)
  592: {
  593: 	struct urio_softc *sc = (struct urio_softc *)self;
  594: 
  595: 	switch (act) {
  596: 	case DVACT_ACTIVATE:
  597: 		return (EOPNOTSUPP);
  598: 		break;
  599: 
  600: 	case DVACT_DEACTIVATE:
  601: 		sc->sc_dying = 1;
  602: 		break;
  603: 	}
  604: 	return (0);
  605: }
  606: 
  607: USB_DETACH(urio)
  608: {
  609: 	USB_DETACH_START(urio, sc);
  610: 	struct urio_endpoint *sce;
  611: 	int i, dir;
  612: 	int s;
  613: #if defined(__NetBSD__) || defined(__OpenBSD__)
  614: 	int maj, mn;
  615: 
  616: 	DPRINTF(("urio_detach: sc=%p flags=%d\n", sc, flags));
  617: #elif defined(__FreeBSD__) || defined(__DragonFly__)
  618: 	DPRINTF(("urio_detach: sc=%p\n", sc));
  619: #endif
  620: 
  621: 	sc->sc_dying = 1;
  622: 	/* Abort all pipes.  Causes processes waiting for transfer to wake. */
  623: #if 0
  624: 	for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
  625: 		for (dir = OUT; dir <= IN; dir++) {
  626: 			sce = &sc->sc_endpoints[i][dir];
  627: 			if (sce && sce->pipeh)
  628: 				usbd_abort_pipe(sce->pipeh);
  629: 		}
  630: 	}
  631: 
  632: 	s = splusb();
  633: 	if (--sc->sc_refcnt >= 0) {
  634: 		/* Wake everyone */
  635: 		for (i = 0; i < USB_MAX_ENDPOINTS; i++)
  636: 			wakeup(&sc->sc_endpoints[i][IN]);
  637: 		/* Wait for processes to go away. */
  638: 		usb_detach_wait(USBDEV(sc->sc_dev));
  639: 	}
  640: 	splx(s);
  641: #else
  642: 	if (sc->sc_pipeh_in)
  643: 		usbd_abort_pipe(sc->sc_pipeh_in);
  644: 
  645: 	if (sc->sc_pipeh_out)
  646: 		usbd_abort_pipe(sc->sc_pipeh_out);
  647: 
  648: 	s = splusb();
  649: 	if (--sc->sc_refcnt >= 0) {
  650: 		/* Wait for processes to go away. */
  651: 		usb_detach_wait(USBDEV(sc->sc_dev));
  652: 	}
  653: 	splx(s);
  654: #endif
  655: 
  656: #if defined(__NetBSD__) || defined(__OpenBSD__)
  657: 	/* locate the major number */
  658: 	for (maj = 0; maj < nchrdev; maj++)
  659: 		if (cdevsw[maj].d_open == urioopen)
  660: 			break;
  661: 
  662: 	/* Nuke the vnodes for any open instances (calls close). */
  663: 	mn = self->dv_unit * USB_MAX_ENDPOINTS;
  664: 	vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR);
  665: #endif
  666: 
  667: 	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
  668: 			   USBDEV(sc->sc_dev));
  669: 
  670: 	return (0);
  671: }
  672: #endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
  673: 
  674: #if defined(__FreeBSD__) || defined(__DragonFly__)
  675: Static int
  676: urio_detach(device_t self)
  677: {
  678: 	struct urio_softc *sc = device_get_softc(self);
  679: 
  680: 	DPRINTF(("%s: disconnected\n", USBDEVNAME(self)));
  681: 	destroy_dev(sc->sc_dev_t);
  682: 	/* XXX not implemented yet */
  683: 	device_set_desc(self, NULL);
  684: 	return 0;
  685: }
  686: 
  687: DRIVER_MODULE(urio, uhub, urio_driver, urio_devclass, usbd_driver_load, 0);
  688: #endif