Source-Changes-HG archive

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

[src/trunk]: src/sys/rump/dev/lib/libugenhc * support isochronous transfers (...



details:   https://anonhg.NetBSD.org/src/rev/7cb88c600cfc
branches:  trunk
changeset: 753284:7cb88c600cfc
user:      pooka <pooka%NetBSD.org@localhost>
date:      Mon Mar 22 12:05:45 2010 +0000

description:
* support isochronous transfers (for as much as they can be supported
  considering our ugen driver doesn't support isochronous write.
  kern/25960 seems to contain a patch and could be investigated for that)
* add a dirty rotten hack which makes interrupt transfers of >16
  work for me

diffstat:

 sys/rump/dev/lib/libugenhc/ugenhc.c |  69 +++++++++++++++++++++++++++---------
 1 files changed, 51 insertions(+), 18 deletions(-)

diffs (160 lines):

diff -r 5734faf3d11b -r 7cb88c600cfc sys/rump/dev/lib/libugenhc/ugenhc.c
--- a/sys/rump/dev/lib/libugenhc/ugenhc.c       Mon Mar 22 12:03:04 2010 +0000
+++ b/sys/rump/dev/lib/libugenhc/ugenhc.c       Mon Mar 22 12:05:45 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ugenhc.c,v 1.8 2010/02/23 14:05:04 pooka Exp $ */
+/*     $NetBSD: ugenhc.c,v 1.9 2010/03/22 12:05:45 pooka Exp $ */
 
 /*
  * Copyright (c) 2009, 2010 Antti Kantee.  All Rights Reserved.
@@ -61,7 +61,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.8 2010/02/23 14:05:04 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.9 2010/03/22 12:05:45 pooka Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -506,6 +506,7 @@
        case C(0x22, UT_WRITE_CLASS_INTERFACE):
        case C(0x0a, UT_WRITE_CLASS_INTERFACE):
        case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
+       case C(0x00, UT_WRITE_CLASS_DEVICE):
        case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
        case C(UR_SET_REPORT, UT_WRITE_CLASS_INTERFACE):
@@ -718,40 +719,46 @@
 rumpusb_device_bulk_start(usbd_xfer_handle xfer)
 {
        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
+       usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc;
        ssize_t n;
        ssize_t done;
        bool isread;
        int len, error, endpt;
        uint8_t *buf;
        int xfererr = USBD_NORMAL_COMPLETION;
-       int val;
+       int shortval, i;
 
-       endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
+       ed = xfer->pipe->endpoint->edesc;
+       endpt = ed->bEndpointAddress;
        isread = UE_GET_DIR(endpt) == UE_DIR_IN;
        endpt = UE_GET_ADDR(endpt);
        KASSERT(endpt < UGEN_NEPTS);
 
-       KASSERT(xfer->length);
-       len = xfer->length;
        buf = KERNADDR(&xfer->dmabuf, 0);
        done = 0;
+       if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) {
+               for (i = 0, len = 0; i < xfer->nframes; i++)
+                       len += xfer->frlengths[i];
+       } else {
+               KASSERT(xfer->length);
+               len = xfer->length;
+       }
+       shortval = (xfer->flags & USBD_SHORT_XFER_OK) != 0;
 
        while (RUSB(xfer)->rusb_status == 0) {
                if (isread) {
-                       if (xfer->flags & USBD_SHORT_XFER_OK)
-                               val = 1;
-                       else
-                               val = 0;
                        rumpuser_ioctl(sc->sc_ugenfd[endpt],
-                           USB_SET_SHORT_XFER, &val, &error);
+                           USB_SET_SHORT_XFER, &shortval, &error);
                        n = rumpuser_read(sc->sc_ugenfd[endpt],
                            buf+done, len-done, &error);
                        if (n == -1) {
-                               if (error == ETIMEDOUT)
-                                       continue;
                                n = 0;
-                               xfererr = USBD_IOERROR;
-                               goto out;
+                               if (done == 0) {
+                                       if (error == ETIMEDOUT)
+                                               continue;
+                                       xfererr = USBD_IOERROR;
+                                       goto out;
+                               }
                        }
                        done += n;
                        if (done == len)
@@ -769,8 +776,23 @@
                        goto out;
                }
 
-               if (xfer->flags & USBD_SHORT_XFER_OK)
-                       break;
+               if (shortval) {
+                       /*
+                        * Holy XXX, bitman.  I get >16byte interrupt
+                        * transfers from ugen in 16 byte chunks.
+                        * Don't know how to better fix this for now.
+                        * Of course this hack will fail e.g. if someone
+                        * sports other magic values or if the transfer
+                        * happens to be an integral multiple of 16
+                        * in size ....
+                        */
+                       if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT
+                           && n == 16) {
+                               continue;
+                       } else {
+                               break;
+                       }
+               }
        }
 
        if (RUSB(xfer)->rusb_status == 0) {
@@ -780,6 +802,9 @@
                RUSB(xfer)->rusb_status = 2;
        }
  out:
+       if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS)
+               if (done != len)
+                       panic("lazy bum");
        xfer->status = xfererr;
        usb_transfer_complete(xfer);
        return (USBD_IN_PROGRESS);
@@ -918,6 +943,7 @@
                        break;
                case UE_INTERRUPT:
                case UE_BULK:
+               case UE_ISOCHRONOUS:
                        pipe->methods = &rumpusb_device_bulk_methods;
                        endpt = pipe->endpoint->edesc->bEndpointAddress;
                        if (UE_GET_DIR(endpt) == UE_DIR_IN) {
@@ -927,6 +953,11 @@
                        }
                        endpt = UE_GET_ADDR(endpt);
 
+                       if (oflags != O_RDONLY && xfertype == UE_ISOCHRONOUS) {
+                               printf("WARNING: faking isoc write open\n");
+                               oflags = O_RDONLY;
+                       }
+
                        if (sc->sc_fdmodes[endpt] == oflags
                            || sc->sc_fdmodes[endpt] == O_RDWR)
                                break;
@@ -939,14 +970,16 @@
 
                        makeugendevstr(sc->sc_devnum, endpt, buf);
                        fd = rumpuser_open(buf, oflags, &error);
-                       if (fd == -1)
+                       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;
                default:
                        panic("%d not supported", xfertype);



Home | Main Index | Thread Index | Old Index