Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/rump/dev/wip/librumpusbhc * support async transfers



details:   https://anonhg.NetBSD.org/src/rev/23be1a1c8a2c
branches:  trunk
changeset: 747909:23be1a1c8a2c
user:      pooka <pooka%NetBSD.org@localhost>
date:      Mon Oct 05 13:00:37 2009 +0000

description:
* support async transfers
* make it possible to abort transfers
(these are all cheap hacks, but make things work)

diffstat:

 sys/rump/dev/wip/librumpusbhc/Makefile    |    4 +-
 sys/rump/dev/wip/librumpusbhc/rumpusbhc.c |  111 ++++++++++++++++++++++-------
 2 files changed, 87 insertions(+), 28 deletions(-)

diffs (226 lines):

diff -r 1f94b03a8cd1 -r 23be1a1c8a2c sys/rump/dev/wip/librumpusbhc/Makefile
--- a/sys/rump/dev/wip/librumpusbhc/Makefile    Mon Oct 05 12:53:37 2009 +0000
+++ b/sys/rump/dev/wip/librumpusbhc/Makefile    Mon Oct 05 13:00:37 2009 +0000
@@ -1,9 +1,11 @@
-#      $NetBSD: Makefile,v 1.1 2009/10/02 15:35:46 pooka Exp $
+#      $NetBSD: Makefile,v 1.2 2009/10/05 13:00:37 pooka Exp $
 #
 
 LIB=   rumpdev_usbhc
 
 SRCS=  rumpusbhc.c
 
+CPPFLAGS+=     -I${RUMPTOP}/librump/rumpkern
+
 .include <bsd.lib.mk>
 .include <bsd.klinks.mk>
diff -r 1f94b03a8cd1 -r 23be1a1c8a2c sys/rump/dev/wip/librumpusbhc/rumpusbhc.c
--- a/sys/rump/dev/wip/librumpusbhc/rumpusbhc.c Mon Oct 05 12:53:37 2009 +0000
+++ b/sys/rump/dev/wip/librumpusbhc/rumpusbhc.c Mon Oct 05 13:00:37 2009 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: rumpusbhc.c,v 1.5 2009/10/04 17:46:58 pooka Exp $      */
+/*     $NetBSD: rumpusbhc.c,v 1.6 2009/10/05 13:00:37 pooka Exp $      */
 
 /*
  * Copyright (c) 2009 Antti Kantee.  All Rights Reserved.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rumpusbhc.c,v 1.5 2009/10/04 17:46:58 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rumpusbhc.c,v 1.6 2009/10/05 13:00:37 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -69,6 +69,8 @@
 #include <sys/device.h>
 #include <sys/fcntl.h>
 #include <sys/kmem.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -78,6 +80,7 @@
 
 #include <rump/rumpuser.h>
 
+#include "rump_private.h"
 #include "rump_dev_private.h"
 
 #define UGEN_NEPTS 16
@@ -119,12 +122,20 @@
        DVUNIT_ANY
 };
 
+struct rusb_xfer {
+       struct usbd_xfer rusb_xfer;
+       int rusb_status; /* now this is a cheap trick */
+};
+#define RUSB(x) ((struct rusb_xfer *)x)
+
 /* probe ugen0 through ugen3 */
 struct cfdata rumpusbhc_cfdata[] = {
+#if 0
        { "rumpusbhc", "rumpusbhc", 0, FSTATE_NOTFOUND, NULL, 0, &rumpusbhcpar},
        { "rumpusbhc", "rumpusbhc", 1, FSTATE_NOTFOUND, NULL, 0, &rumpusbhcpar},
+       { "rumpusbhc", "rumpusbhc", 3, FSTATE_NOTFOUND, NULL, 0, &rumpusbhcpar},
+#endif
        { "rumpusbhc", "rumpusbhc", 2, FSTATE_NOTFOUND, NULL, 0, &rumpusbhcpar},
-       { "rumpusbhc", "rumpusbhc", 3, FSTATE_NOTFOUND, NULL, 0, &rumpusbhcpar},
 };
 
 #define UGENDEV_BASESTR "/dev/ugen"
@@ -465,10 +476,6 @@
 
        case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
                printf("clear feature UNIMPL\n");
-               break;
-
-       case C(0xfe, UT_READ_CLASS_INTERFACE):
-               /* XXX: what is this? */
                totlen = 0;
                break;
 
@@ -480,6 +487,7 @@
        case C(0x06, UT_WRITE_VENDOR_DEVICE):
        case C(0x07, UT_READ_VENDOR_DEVICE):
        case C(0x09, UT_READ_VENDOR_DEVICE):
+       case C(0xfe, UT_READ_CLASS_INTERFACE):
                {
                struct usb_ctl_request ucr;
 
@@ -631,44 +639,87 @@
        len = xfer->length;
        buf = KERNADDR(&xfer->dmabuf, 0);
 
-       if (isread) {
-               n = rumpuser_read(sc->sc_ugenfd[endpt], buf, len, &error);
-               if (n != len)
-                       n = 0;
-       } else {
-               n = rumpuser_write(sc->sc_ugenfd[endpt], buf, len, &error);
-               if (n != len)
-                       panic("short write");
+       while (RUSB(xfer)->rusb_status == 0) {
+               if (isread) {
+                       n = rumpuser_read(sc->sc_ugenfd[endpt],
+                           buf, len, &error);
+                       if (n == len)
+                               break;
+                       if (error != EAGAIN) {
+                               n = 0;
+                               break;
+                       }
+               } else {
+                       n = rumpuser_write(sc->sc_ugenfd[endpt],
+                           buf, len, &error);
+                       if (n == len)
+                               break;
+                       else
+                               panic("short write");
+               }
        }
 
-       xfer->actlen = n;
-       xfer->status = USBD_NORMAL_COMPLETION;
+       if (RUSB(xfer)->rusb_status == 0) {
+               xfer->actlen = n;
+               xfer->status = USBD_NORMAL_COMPLETION;
+       } else {
+               xfer->status = USBD_CANCELLED;
+               RUSB(xfer)->rusb_status = 2;
+       }
        usb_transfer_complete(xfer);
        return (USBD_IN_PROGRESS);
 }
 
+static void
+doxfer_kth(void *arg)
+{
+       usbd_xfer_handle xfer = arg;
+
+       rumpusb_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
+       kthread_exit(0);
+}
+
 static usbd_status
 rumpusb_device_bulk_transfer(usbd_xfer_handle xfer)
 {
        usbd_status err;
 
-       /* XXX: lie about supporting async transfers */
-       if ((xfer->flags & USBD_SYNCHRONOUS) == 0) {
-               printf("rumpusbhc does not support async transfers. LIAR!\n");
+       if (!rump_threads) {
+               /* XXX: lie about supporting async transfers */
+               if ((xfer->flags & USBD_SYNCHRONOUS) == 0) {
+                       printf("non-threaded rump does not support "
+                           "async transfers.\n");
+                       return USBD_IN_PROGRESS;
+               }
+
+               err = usb_insert_transfer(xfer);
+               if (err)
+                       return err;
+
+               return rumpusb_device_bulk_start(
+                   SIMPLEQ_FIRST(&xfer->pipe->queue));
+       } else {
+               /* biglocked */
+               err = usb_insert_transfer(xfer);
+               if (err)
+                       return err;
+               kthread_create(PRI_NONE, 0, NULL, doxfer_kth, xfer, NULL,
+                   "rusbhcxf");
+
                return USBD_IN_PROGRESS;
        }
-
-       err = usb_insert_transfer(xfer);
-       if (err)
-               return (err);
-
-       return (rumpusb_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
 }
 
+/* wait for transfer to abort.  yea, this is cheesy (from a spray can) */
 static void
 rumpusb_device_bulk_abort(usbd_xfer_handle xfer)
 {
+       struct rusb_xfer *rx = RUSB(xfer);
 
+       rx->rusb_status = 1;
+       while (rx->rusb_status < 2) {
+               kpause("jopo", false, hz/10, NULL);
+       }
 }
 
 static void
@@ -708,7 +759,7 @@
        u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
        char buf[UGENDEV_BUFSIZE];
        int endpt, oflags, error;
-       int fd;
+       int fd, val;
 
        sc->sc_port_status = UPS_CURRENT_CONNECT_STATUS
            | UPS_PORT_ENABLED | UPS_PORT_POWER | UPS_HIGH_SPEED;
@@ -755,6 +806,10 @@
                        fd = rumpuser_open(buf, oflags, &error);
                        if (fd == -1)
                                return USBD_INVAL; /* XXX: no mapping */
+                       val = 100;
+                       if (rumpuser_ioctl(fd, USB_SET_TIMEOUT, &val,
+                           &error) == -1)
+                               panic("timeout set failed");
                        sc->sc_ugenfd[endpt] = fd;
                        sc->sc_fdmodes[endpt] = oflags;
                        break;
@@ -885,4 +940,6 @@
 
        /* whoah, like extreme XXX, bro */
        rhscintr();
+       if (!rump_threads)
+               config_pending_decr();
 }



Home | Main Index | Thread Index | Old Index