diff -urP --exclude-from=/home/raceme/diff_exclude /usr/src/sys/conf/files sys/conf/files
--- /usr/src/sys/conf/files	Fri Nov 17 01:01:33 2000
+++ sys/conf/files	Tue Jul  3 13:17:29 2001
@@ -1061,6 +1061,7 @@
 dev/usb/if_aue.c	optional aue
 dev/usb/if_cue.c	optional cue
 dev/usb/if_kue.c	optional kue
+dev/usb/urio.c		optional urio
 isa_if.o		optional isa					\
 	dependency	"isa_if.c isa_if.h"				\
 	compile-with	"${NORMAL_C}"					\
diff -urP --exclude-from=/home/raceme/diff_exclude /usr/src/sys/conf/options sys/conf/options
--- /usr/src/sys/conf/options	Fri Nov 17 01:01:33 2000
+++ sys/conf/options	Tue Jul  3 13:32:52 2001
@@ -435,6 +435,7 @@
 ULPT_DEBUG		opt_usb.h
 UMASS_DEBUG		opt_usb.h
 UMS_DEBUG		opt_usb.h
+URIO_DEBUG		opt_usb.h
 
 # Vinum options
 VINUMDEBUG		opt_vinum.h
diff -urP --exclude-from=/home/raceme/diff_exclude /usr/src/sys/dev/usb/rio500_usb.h sys/dev/usb/rio500_usb.h
--- /usr/src/sys/dev/usb/rio500_usb.h	Thu Jan  1 01:00:00 1970
+++ sys/dev/usb/rio500_usb.h	Mon Jul  2 17:28:36 2001
@@ -0,0 +1,58 @@
+/*  ----------------------------------------------------------------------
+
+    Copyright (C) 2000  Cesar Miquel  (miquel@df.uba.ar)
+
+    Redistribution and use in source and binary forms, with or without
+    modification, are permitted under any licence of your choise which
+    meets the open source licence definiton
+    http://www.opensource.org/opd.html such as the GNU licence or the
+    BSD licence.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License or the BSD license for more details.
+
+    ----------------------------------------------------------------------
+
+    Modified for FreeBSD by Iwasa Kazmi <kzmi@ca2.so-net.ne.jp>
+
+    ---------------------------------------------------------------------- */
+
+/*  $FreeBSD: src/sys/dev/usb/rio500_usb.h,v 1.1 2000/04/08 17:02:13 n_hibma Exp $ */
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#include <sys/ioccom.h>
+#ifndef USB_VENDOR_DIAMOND
+#define USB_VENDOR_DIAMOND 0x841
+#endif
+#ifndef USB_PRODUCT_DIAMOND_RIO500USB
+#define USB_PRODUCT_DIAMOND_RIO500USB 0x1
+#endif
+#endif
+
+struct RioCommand
+{
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+  u_int16_t  length;
+#else
+  short length;
+#endif
+  int   request;
+  int   requesttype;
+  int   value;
+  int   index;
+  void *buffer;
+  int  timeout;
+};
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
+#define RIO_SEND_COMMAND	_IOWR('U', 200, struct RioCommand)
+#define RIO_RECV_COMMAND	_IOWR('U', 201, struct RioCommand)
+#else
+#define RIO_SEND_COMMAND			0x1
+#define RIO_RECV_COMMAND			0x2
+#endif
+
+#define RIO_DIR_OUT               	        0x0
+#define RIO_DIR_IN				0x1
diff -urP --exclude-from=/home/raceme/diff_exclude /usr/src/sys/dev/usb/urio.c sys/dev/usb/urio.c
--- /usr/src/sys/dev/usb/urio.c	Thu Jan  1 01:00:00 1970
+++ sys/dev/usb/urio.c	Thu Jul  5 11:51:13 2001
@@ -0,0 +1,729 @@
+/*
+ * Copyright (c) 2000 Iwasa Kazmi
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson.
+ * This code includes software developed by the NetBSD Foundation, Inc. and
+ * its contributors.
+ */
+
+/* $FreeBSD: src/sys/dev/usb/urio.c,v 1.8 2001/06/15 00:26:41 peter Exp $ */
+
+/*
+ * 2000/3/24  added NetBSD/OpenBSD support (from Alex Nemirovsky)
+ * 2000/3/07  use two bulk-pipe handles for read and write (Dirk)
+ * 2000/3/06  change major number(143), and copyright header
+ *            some fix for 4.0 (Dirk)
+ * 2000/3/05  codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik)
+ * 2000/3/01  remove retry code from urioioctl()
+ *            change method of bulk transfer (no interrupt)
+ * 2000/2/28  small fixes for new rio_usb.h
+ * 2000/2/24  first version.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#if defined(__NetBSD__)
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#elif defined(__FreeBSD__)
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/ioccom.h>
+#endif
+#include <sys/fcntl.h>
+#include <sys/filio.h>
+#include <sys/conf.h>
+#include <sys/uio.h>
+#include <sys/tty.h>
+#include <sys/file.h>
+#if __FreeBSD_version >= 500014
+#include <sys/selinfo.h>
+#else
+#include <sys/select.h>
+#endif
+#include <sys/vnode.h>
+#include <sys/poll.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+
+#include <dev/usb/usbdevs.h>
+#include <dev/usb/rio500_usb.h>
+
+#ifdef URIO_DEBUG
+#define DPRINTF(x)	if (uriodebug) logprintf x
+#define DPRINTFN(n,x)	if (uriodebug>(n)) logprintf x
+int	uriodebug = 100;
+#else
+#define DPRINTF(x)
+#define DPRINTFN(n,x)
+#endif
+
+/* difference of usbd interface */
+#if defined(__FreeBSD__)
+#if (__FreeBSD__ >= 4)
+  #define USBDI 1
+#else
+  #define USBDI 0
+#endif
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+  #define USBDI 1
+#endif
+
+#define RIO_OUT 0
+#define RIO_IN  1
+#define RIO_NODIR  2
+
+#if defined(__NetBSD__)
+int urioopen(dev_t, int, int, struct proc *);
+int urioclose(dev_t, int, int, struct proc *p);
+int urioread(dev_t, struct uio *uio, int);
+int uriowrite(dev_t, struct uio *uio, int);
+int urioioctl(dev_t, u_long, caddr_t, int, struct proc *);
+
+cdev_decl(urio);
+#define RIO_UE_GET_DIR(p) ((UE_GET_DIR(p) == UE_DIR_IN) ? RIO_IN :\
+			  ((UE_GET_DIR(p) == UE_DIR_OUT) ? RIO_OUT :\
+							   RIO_NODIR))
+#elif defined(__FreeBSD__)
+d_open_t  urioopen;
+d_close_t urioclose;
+d_read_t  urioread;
+d_write_t uriowrite;
+d_ioctl_t urioioctl;
+
+#define URIO_CDEV_MAJOR	143
+
+#if (__FreeBSD__ >= 4)
+Static struct cdevsw urio_cdevsw = {
+	urioopen,	urioclose,	urioread,	uriowrite,
+ 	urioioctl,	nopoll,		nommap,		nostrategy,
+ 	"urio",		URIO_CDEV_MAJOR,nodump,		nopsize,
+ 	0,
+#if (__FreeBSD__ < 5)
+ 	-1
+#endif
+};
+#define RIO_UE_GET_DIR(p) ((UE_GET_DIR(p) == UE_DIR_IN) ? RIO_IN :\
+		 	  ((UE_GET_DIR(p) == UE_DIR_OUT) ? RIO_OUT :\
+			    				   RIO_NODIR))
+#else
+Static struct cdevsw urio_cdevsw = {
+	urioopen,	urioclose,	urioread,	uriowrite,
+	urioioctl,	nostop,		nullreset,	nodevtotty,
+	seltrue,	nommap,		nostrat,
+	"urio",		NULL,		-1
+};
+#define USBBASEDEVICE bdevice
+#define RIO_UE_GET_DIR(p) UE_GET_IN(p)
+#endif
+
+#endif  /*defined(__FreeBSD__)*/
+
+#define	URIO_BBSIZE	1024
+
+struct urio_softc {
+ 	USBBASEDEVICE sc_dev;
+	usbd_device_handle sc_udev;
+	usbd_interface_handle sc_iface;
+
+	int sc_opened;
+	usbd_pipe_handle sc_pipeh_in;
+	usbd_pipe_handle sc_pipeh_out;
+	int sc_epaddr[2];
+
+	int sc_refcnt;
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+	u_char sc_dying;
+#endif
+};
+
+#define URIOUNIT(n) (minor(n))
+
+#define RIO_RW_TIMEOUT 4000	/* ms */
+
+USB_DECLARE_DRIVER(urio);
+
+USB_MATCH(urio)
+{
+	USB_MATCH_START(urio, uaa);
+	usb_device_descriptor_t *dd;
+
+	DPRINTFN(10,("urio_match\n"));
+	if (!uaa->iface)
+		return UMATCH_NONE;
+
+	dd = usbd_get_device_descriptor(uaa->device);
+
+	if (dd &&
+	    UGETW(dd->idVendor) == USB_VENDOR_DIAMOND &&
+	    UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND_RIO500USB)
+             {
+	        DPRINTFN(10,("urio_match ok (rio500)\n"));
+		return UMATCH_VENDOR_PRODUCT;
+             }
+	else if (dd &&
+	    UGETW(dd->idVendor) == USB_VENDOR_DIAMOND2 &&
+             UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND2_RIO600USB)
+             {
+	        DPRINTFN(10,("urio_match ok (rio600)\n"));
+		return UMATCH_VENDOR_PRODUCT;
+             }
+	else
+		return UMATCH_NONE;
+}
+
+USB_ATTACH(urio)
+{
+	USB_ATTACH_START(urio, sc, uaa);
+	char devinfo[1024];
+	usbd_device_handle udev;
+	usbd_interface_handle iface;
+	u_int8_t epcount;
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+	u_int8_t niface;
+#endif
+	usbd_status r;
+	char * ermsg = "<none>";
+	int i;
+
+	DPRINTFN(10,("urio_attach: sc=%p\n", sc));	
+	usbd_devinfo(uaa->device, 0, devinfo);
+	USB_ATTACH_SETUP;
+	printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
+
+	sc->sc_udev = udev = uaa->device;
+
+#if defined(__FreeBSD__)
+ 	if ((!uaa->device) || (!uaa->iface)) {
+		ermsg = "device or iface";
+ 		goto nobulk;
+	}
+	sc->sc_iface = iface = uaa->iface;
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+ 	if (!udev) {
+		ermsg = "device";
+ 		goto nobulk;
+	}
+	r = usbd_interface_count(udev, &niface);
+	if (r) {
+		ermsg = "iface";
+		goto nobulk;  
+	}
+	r = usbd_device2interface_handle(udev, 0, &iface);
+	if (r) {
+		ermsg = "iface";
+		goto nobulk;  
+	}
+	sc->sc_iface = iface;
+#endif
+	sc->sc_opened = 0;
+	sc->sc_pipeh_in = 0;
+	sc->sc_pipeh_out = 0;
+	sc->sc_refcnt = 0;
+
+	r = usbd_endpoint_count(iface, &epcount);
+	if (r != USBD_NORMAL_COMPLETION) { 
+		ermsg = "endpoints";
+		goto nobulk;
+	}
+
+	sc->sc_epaddr[RIO_OUT] = 0xff;
+	sc->sc_epaddr[RIO_IN] = 0x00;
+
+	for (i = 0; i < epcount; i++) {
+		usb_endpoint_descriptor_t *edesc = 
+			usbd_interface2endpoint_descriptor(iface, i);
+		int d;
+
+		if (!edesc) {
+			ermsg = "interface endpoint";
+			goto nobulk;
+		}
+	
+		d = RIO_UE_GET_DIR(edesc->bEndpointAddress);
+		if (d != RIO_NODIR)
+			sc->sc_epaddr[d] = edesc->bEndpointAddress;
+	}
+	if ( sc->sc_epaddr[RIO_OUT] == 0xff ||
+	     sc->sc_epaddr[RIO_IN] == 0x00) {
+		ermsg = "Rio I&O";
+		goto nobulk;
+	}
+
+#if defined(__FreeBSD__)
+ #if (__FreeBSD__ >= 4)
+	/* XXX no error trapping, no storing of dev_t */
+	(void) make_dev(&urio_cdevsw, device_get_unit(self),
+			UID_ROOT, GID_OPERATOR,
+			0644, "urio%d", device_get_unit(self));
+ #endif
+#elif defined(__NetBSD__) || defined(__OpenBSD__)
+	usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
+			   USBDEV(sc->sc_dev));
+#endif
+
+	DPRINTFN(10, ("urio_attach: %p\n", sc->sc_udev));
+
+	USB_ATTACH_SUCCESS_RETURN;
+
+ nobulk:
+	printf("%s: could not find %s\n", USBDEVNAME(sc->sc_dev),ermsg);
+	USB_ATTACH_ERROR_RETURN;
+}
+
+
+int
+urioopen(dev, flag, mode, p)
+	dev_t dev;
+	int flag;
+	int mode;
+	struct proc *p;
+{
+#if (USBDI >= 1)
+	struct urio_softc * sc;
+#endif
+	int unit = URIOUNIT(dev);
+	USB_GET_SC_OPEN(urio, unit, sc);
+
+	DPRINTFN(5, ("urioopen: flag=%d, mode=%d, unit=%d\n", 
+		     flag, mode, unit));
+
+	if (sc->sc_opened)
+		return EBUSY;
+
+	if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD))
+		return EACCES;
+
+	sc->sc_opened = 1;
+	sc->sc_pipeh_in = 0;
+	sc->sc_pipeh_out = 0;
+	if (usbd_open_pipe(sc->sc_iface, 
+		sc->sc_epaddr[RIO_IN], 0, &sc->sc_pipeh_in) 
+	   		!= USBD_NORMAL_COMPLETION)
+	{
+			sc->sc_pipeh_in = 0;
+			return EIO;
+	};
+	if (usbd_open_pipe(sc->sc_iface, 
+		sc->sc_epaddr[RIO_OUT], 0, &sc->sc_pipeh_out) 
+	   		!= USBD_NORMAL_COMPLETION)
+	{
+			usbd_close_pipe(sc->sc_pipeh_in);	
+			sc->sc_pipeh_in = 0;
+			sc->sc_pipeh_out = 0;
+			return EIO;
+	};
+	return 0;
+}
+
+int
+urioclose(dev, flag, mode, p)
+	dev_t dev;
+	int flag;
+	int mode;
+	struct proc *p;
+{
+#if (USBDI >= 1)
+	struct urio_softc * sc;
+#endif
+	int unit = URIOUNIT(dev);
+	USB_GET_SC(urio, unit, sc);
+
+	DPRINTFN(5, ("urioclose: flag=%d, mode=%d, unit=%d\n", flag, mode, unit));
+	if (sc->sc_pipeh_in) 
+		usbd_close_pipe(sc->sc_pipeh_in);	
+
+	if (sc->sc_pipeh_out) 
+		usbd_close_pipe(sc->sc_pipeh_out);	
+
+	sc->sc_pipeh_in = 0;
+	sc->sc_pipeh_out = 0;
+	sc->sc_opened = 0;
+	sc->sc_refcnt = 0;
+	return 0;	
+}
+
+int
+urioread(dev, uio, flag)
+	dev_t dev;
+	struct uio *uio;
+	int flag;
+{
+#if (USBDI >= 1)
+	struct urio_softc * sc;
+	usbd_xfer_handle reqh;
+#else
+	usbd_request_handle reqh;
+	usbd_private_handle r_priv;
+        void *r_buff;
+        usbd_status r_status;
+#endif
+	int unit = URIOUNIT(dev);
+	usbd_status r;
+	char buf[URIO_BBSIZE];
+	u_int32_t n, tn;
+	int error = 0;
+
+	USB_GET_SC(urio, unit, sc);
+
+	DPRINTFN(5, ("urioread: %d\n", unit));
+	if (!sc->sc_opened)
+		return EIO;
+
+#if (USBDI >= 1)
+	sc->sc_refcnt++;
+	reqh = usbd_alloc_xfer(sc->sc_udev);
+#else
+	reqh = usbd_alloc_request();
+#endif
+	if (reqh == 0)
+		return ENOMEM;
+	while ((n = min(URIO_BBSIZE, uio->uio_resid)) != 0) {
+		DPRINTFN(1, ("urioread: start transfer %d bytes\n", n));
+		tn = n;
+#if (USBDI >= 1)
+ 		usbd_setup_xfer(reqh, sc->sc_pipeh_in, 0, buf, tn,
+				       0, RIO_RW_TIMEOUT, 0);
+#else
+		r = usbd_setup_request(reqh, sc->sc_pipeh_in, 0, buf, tn,
+				       0, RIO_RW_TIMEOUT, 0);
+		if (r != USBD_NORMAL_COMPLETION) {
+			error = EIO;
+			break;
+		}
+#endif
+		r = usbd_sync_transfer(reqh);
+		if (r != USBD_NORMAL_COMPLETION) {
+			DPRINTFN(1, ("urioread: error=%d\n", r));
+			usbd_clear_endpoint_stall(sc->sc_pipeh_in);
+			tn = 0;
+			error = EIO;
+			break;
+		}
+#if (USBDI >= 1)
+		usbd_get_xfer_status(reqh, 0, 0, &tn, 0);
+#else
+		usbd_get_request_status(reqh, &r_priv, &r_buff, &tn, &r_status);
+#endif
+
+		DPRINTFN(1, ("urioread: got %d bytes\n", tn));
+		error = uiomove(buf, tn, uio);
+		if (error || tn < n)
+			break;
+	}
+#if (USBDI >= 1)
+	usbd_free_xfer(reqh);
+#else
+	usbd_free_request(reqh);
+#endif
+
+	return error;
+}
+
+int
+uriowrite(dev, uio, flag)
+	dev_t dev;
+	struct uio *uio;
+	int flag;
+{
+#if (USBDI >= 1)
+	struct urio_softc * sc;
+	usbd_xfer_handle reqh;
+#else
+	usbd_request_handle reqh;
+#endif
+	int unit = URIOUNIT(dev);
+	usbd_status r;
+	char buf[URIO_BBSIZE];
+	u_int32_t n;
+	int error = 0;
+
+	USB_GET_SC(urio, unit, sc);
+
+	DPRINTFN(5, ("uriowrite: %d\n", unit));
+	if (!sc->sc_opened)
+		return EIO;
+
+#if (USBDI >= 1)
+	sc->sc_refcnt++;
+	reqh = usbd_alloc_xfer(sc->sc_udev);
+#else
+	reqh = usbd_alloc_request();
+#endif
+	if (reqh == 0)
+		return EIO;
+	while ((n = min(URIO_BBSIZE, uio->uio_resid)) != 0) {
+		error = uiomove(buf, n, uio);
+		if (error)
+			break;
+		DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n));
+#if (USBDI >= 1)
+ 		usbd_setup_xfer(reqh, sc->sc_pipeh_out, 0, buf, n,
+				       0, RIO_RW_TIMEOUT, 0);
+#else
+		r = usbd_setup_request(reqh, sc->sc_pipeh_out, 0, buf, n,
+				       0, RIO_RW_TIMEOUT, 0);
+		if (r != USBD_NORMAL_COMPLETION) {
+			error = EIO;
+			break;
+		}
+#endif
+		r = usbd_sync_transfer(reqh);
+		if (r != USBD_NORMAL_COMPLETION) {
+			DPRINTFN(1, ("uriowrite: error=%d\n", r));
+			usbd_clear_endpoint_stall(sc->sc_pipeh_out);
+			error = EIO;
+			break;
+		}
+#if (USBDI >= 1)
+		usbd_get_xfer_status(reqh, 0, 0, 0, 0);
+#endif
+	}
+
+#if (USBDI >= 1)
+	usbd_free_xfer(reqh);
+#else
+	usbd_free_request(reqh);
+#endif
+
+	return error;
+}
+
+
+int
+urioioctl(dev, cmd, addr, flag, p)
+	dev_t dev;
+	u_long cmd;
+	caddr_t addr; 
+	int flag;
+	struct proc *p;
+{
+#if (USBDI >= 1)
+	struct urio_softc * sc;
+#endif
+	int unit = URIOUNIT(dev);
+	struct RioCommand *rio_cmd;
+	int requesttype, len;
+	struct iovec iov;
+	struct uio uio;
+	usb_device_request_t req;
+	int req_flags = 0, req_actlen = 0;
+	void *ptr = 0;
+	int error = 0;
+	usbd_status r;
+
+	USB_GET_SC(urio, unit, sc);
+
+	switch (cmd) {
+	case RIO_RECV_COMMAND:
+		if (!(flag & FWRITE))
+			return EPERM;
+		rio_cmd = (struct RioCommand *)addr;
+		if (rio_cmd == NULL)
+			return EINVAL;
+		len = rio_cmd->length;
+
+		requesttype = rio_cmd->requesttype | UT_READ_VENDOR_DEVICE;
+		DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", 
+			requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len));
+		break;
+
+	case RIO_SEND_COMMAND:
+		if (!(flag & FWRITE))
+			return EPERM;
+		rio_cmd = (struct RioCommand *)addr;
+		if (rio_cmd == NULL)
+			return EINVAL;
+		len = rio_cmd->length;
+
+		requesttype = rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE;
+		DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n", 
+			requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len));
+		break;
+
+	default:
+		return EINVAL;
+		break;
+	}
+
+	/* Send rio control message */
+	req.bmRequestType = requesttype;
+	req.bRequest = rio_cmd->request;
+	USETW(req.wValue, rio_cmd->value);
+	USETW(req.wIndex, rio_cmd->index);
+	USETW(req.wLength, len);
+
+	if (len < 0 || len > 32767)
+		return EINVAL;
+	if (len != 0) {
+		iov.iov_base = (caddr_t)rio_cmd->buffer;
+		iov.iov_len = len;
+		uio.uio_iov = &iov;
+		uio.uio_iovcnt = 1;
+		uio.uio_resid = len;
+		uio.uio_offset = 0;
+		uio.uio_segflg = UIO_USERSPACE;
+		uio.uio_rw =
+			req.bmRequestType & UT_READ ? 
+			UIO_READ : UIO_WRITE;
+		uio.uio_procp = p;
+		ptr = malloc(len, M_TEMP, M_WAITOK);
+		if (uio.uio_rw == UIO_WRITE) {
+			error = uiomove(ptr, len, &uio);
+			if (error)
+				goto ret;
+		}
+	}
+
+	r = usbd_do_request_flags(sc->sc_udev, &req, 
+				  ptr, req_flags, &req_actlen);
+	if (r == USBD_NORMAL_COMPLETION) {
+		error = 0;
+		if (len != 0) {
+			if (uio.uio_rw == UIO_READ) {
+				error = uiomove(ptr, len, &uio);
+			}
+		}
+	} else {
+		error = EIO;
+	}
+
+ret:
+	if (ptr)
+		free(ptr, M_TEMP);
+	return error;
+}
+
+
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+int
+urio_activate(self, act)
+	device_ptr_t self;
+	enum devact act;
+{
+	struct urio_softc *sc = (struct urio_softc *)self;
+
+	switch (act) {
+	case DVACT_ACTIVATE:
+		return (EOPNOTSUPP);
+		break;
+
+	case DVACT_DEACTIVATE:
+		sc->sc_dying = 1;
+		break;
+	}
+	return (0);
+}
+
+USB_DETACH(urio)
+{
+	USB_DETACH_START(urio, sc);
+	struct urio_endpoint *sce;
+	int i, dir;
+	int s;
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+	int maj, mn;
+
+	DPRINTF(("urio_detach: sc=%p flags=%d\n", sc, flags));
+#elif defined(__FreeBSD__)
+	DPRINTF(("urio_detach: sc=%p\n", sc));
+#endif
+
+	sc->sc_dying = 1;
+	/* Abort all pipes.  Causes processes waiting for transfer to wake. */
+#if 0
+	for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
+		for (dir = OUT; dir <= IN; dir++) {
+			sce = &sc->sc_endpoints[i][dir];
+			if (sce && sce->pipeh)
+				usbd_abort_pipe(sce->pipeh);
+		}
+	}
+
+	s = splusb();
+	if (--sc->sc_refcnt >= 0) {
+		/* Wake everyone */
+		for (i = 0; i < USB_MAX_ENDPOINTS; i++)
+			wakeup(&sc->sc_endpoints[i][IN]);
+		/* Wait for processes to go away. */
+		usb_detach_wait(USBDEV(sc->sc_dev));
+	}
+	splx(s);
+#else
+	if (sc->sc_pipeh_in) 
+		usbd_abort_pipe(sc->sc_pipeh_in);	
+
+	if (sc->sc_pipeh_out) 
+		usbd_abort_pipe(sc->sc_pipeh_out);	
+
+	s = splusb();
+	if (--sc->sc_refcnt >= 0) {
+		/* Wait for processes to go away. */
+		usb_detach_wait(USBDEV(sc->sc_dev));
+	}
+	splx(s);
+#endif
+
+#if defined(__NetBSD__) || defined(__OpenBSD__)
+	/* locate the major number */
+	for (maj = 0; maj < nchrdev; maj++)
+		if (cdevsw[maj].d_open == urioopen)
+			break;
+
+	/* Nuke the vnodes for any open instances (calls close). */
+	mn = self->dv_unit * USB_MAX_ENDPOINTS;
+	vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR);
+#elif defined(__FreeBSD__)
+	/* XXX not implemented yet */
+#endif
+
+	usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
+			   USBDEV(sc->sc_dev));
+
+	return (0);
+}
+#endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
+
+#if defined(__FreeBSD__)
+Static int
+urio_detach(device_t self)
+{       
+	DPRINTF(("%s: disconnected\n", USBDEVNAME(self)));
+	device_set_desc(self, NULL);
+	return 0;
+}
+
+#if (__FreeBSD__ >= 4)
+DRIVER_MODULE(urio, uhub, urio_driver, urio_devclass, usbd_driver_load, 0);
+#else
+CDEV_DRIVER_MODULE(urio, uhub, urio_driver, urio_devclass,
+			URIO_CDEV_MAJOR, urio_cdevsw, usbd_driver_load, 0);
+#endif
+
+#endif
diff -urP --exclude-from=/home/raceme/diff_exclude /usr/src/sys/modules/Makefile sys/modules/Makefile
--- /usr/src/sys/modules/Makefile	Wed Nov  8 15:41:04 2000
+++ sys/modules/Makefile	Mon Jul  2 17:59:34 2001
@@ -8,7 +8,7 @@
 	linux md mfs mii mlx msdos ncp pcn netgraph nfs ntfs nullfs \
 	nwfs portal procfs rl sf sis sk ste syscons ti tl twe \
 	ugen uhid ukbd ulpt umapfs umass umodem ums union usb uscanner \
-	vinum vn vpo vr wb wx xl
+	vinum vn vpo vr wb wx xl urio
 
 # XXX some of these can move to the general case when de-i386'ed
 .if ${MACHINE_ARCH} == "i386"
diff -urP --exclude-from=/home/raceme/diff_exclude /usr/src/sys/modules/urio/Makefile sys/modules/urio/Makefile
--- /usr/src/sys/modules/urio/Makefile	Thu Jan  1 01:00:00 1970
+++ sys/modules/urio/Makefile	Tue Jul  3 15:42:20 2001
@@ -0,0 +1,12 @@
+# $FreeBSD: src/sys/modules/urio/Makefile,v 1.4 2001/01/06 14:00:38 obrien Exp $ 
+
+MAINTAINER=	Iwasa Kazmi <kzmi@ca2.so-net.ne.jp>
+
+.PATH: ${.CURDIR}/../../dev/usb
+
+KMOD=	urio
+SRCS=	bus_if.h device_if.h vnode_if.h opt_usb.h urio.c
+NOMAN=
+#CFLAGS+=-DURIO_DEBUG
+
+.include <bsd.kmod.mk>
