[BACK]Return to ugenhc.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / rump / dev / lib / libugenhc

Annotation of src/sys/rump/dev/lib/libugenhc/ugenhc.c, Revision 1.21

1.21    ! skrll       1: /*     $NetBSD: ugenhc.c,v 1.20 2014/08/02 07:20:08 skrll Exp $        */
1.1       pooka       2:
                      3: /*
1.7       pooka       4:  * Copyright (c) 2009, 2010 Antti Kantee.  All Rights Reserved.
1.1       pooka       5:  *
                      6:  * Redistribution and use in source and binary forms, with or without
                      7:  * modification, are permitted provided that the following conditions
                      8:  * are met:
                      9:  * 1. Redistributions of source code must retain the above copyright
                     10:  *    notice, this list of conditions and the following disclaimer.
                     11:  * 2. Redistributions in binary form must reproduce the above copyright
                     12:  *    notice, this list of conditions and the following disclaimer in the
                     13:  *    documentation and/or other materials provided with the distribution.
                     14:  *
                     15:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
                     16:  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
                     17:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
                     18:  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
                     19:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     20:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
                     21:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     22:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     23:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     24:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     25:  * SUCH DAMAGE.
                     26:  */
                     27:
                     28: /*
                     29:  * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
                     30:  * All rights reserved.
                     31:  *
                     32:  * This code is derived from software contributed to The NetBSD Foundation
                     33:  * by Lennart Augustsson (lennart@augustsson.net) at
                     34:  * Carlstedt Research & Technology.
                     35:  *
                     36:  * Redistribution and use in source and binary forms, with or without
                     37:  * modification, are permitted provided that the following conditions
                     38:  * are met:
                     39:  * 1. Redistributions of source code must retain the above copyright
                     40:  *    notice, this list of conditions and the following disclaimer.
                     41:  * 2. Redistributions in binary form must reproduce the above copyright
                     42:  *    notice, this list of conditions and the following disclaimer in the
                     43:  *    documentation and/or other materials provided with the distribution.
                     44:  *
                     45:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     46:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     47:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     48:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     49:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     50:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     51:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     52:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     53:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     54:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     55:  * POSSIBILITY OF SUCH DAMAGE.
                     56:  */
                     57:
                     58: /*
                     59:  * This rump driver attaches ugen as a kernel usb host controller.
                     60:  * It's still somewhat under the hammer ....
                     61:  */
                     62:
                     63: #include <sys/cdefs.h>
1.21    ! skrll      64: __KERNEL_RCSID(0, "$NetBSD: ugenhc.c,v 1.20 2014/08/02 07:20:08 skrll Exp $");
1.1       pooka      65:
                     66: #include <sys/param.h>
                     67: #include <sys/bus.h>
                     68: #include <sys/conf.h>
                     69: #include <sys/device.h>
                     70: #include <sys/fcntl.h>
                     71: #include <sys/kmem.h>
                     72: #include <sys/kernel.h>
                     73: #include <sys/kthread.h>
1.21    ! skrll      74: #include <sys/mutex.h>
1.1       pooka      75:
                     76: #include <dev/usb/usb.h>
                     77: #include <dev/usb/usbdi.h>
                     78: #include <dev/usb/usbhid.h>
                     79: #include <dev/usb/usbdivar.h>
                     80: #include <dev/usb/usb_mem.h>
                     81: #include <dev/usb/usbroothub_subr.h>
                     82:
                     83: #include <rump/rumpuser.h>
                     84:
1.17      pooka      85: #include "ugenhc_user.h"
1.13      pooka      86:
1.1       pooka      87: #include "rump_private.h"
                     88: #include "rump_dev_private.h"
                     89:
                     90: #define UGEN_NEPTS 16
                     91: #define UGEN_EPT_CTRL 0 /* ugenx.00 is the control endpoint */
                     92:
                     93: struct ugenhc_softc {
                     94:        struct usbd_bus sc_bus;
                     95:        int sc_devnum;
                     96:
                     97:        int sc_ugenfd[UGEN_NEPTS];
                     98:        int sc_fdmodes[UGEN_NEPTS];
                     99:
                    100:        int sc_port_status;
                    101:        int sc_port_change;
                    102:        int sc_addr;
                    103:        int sc_conf;
1.3       pooka     104:
                    105:        struct lwp *sc_rhintr;
                    106:        usbd_xfer_handle sc_intrxfer;
1.21    ! skrll     107:
        !           108:        kmutex_t sc_lock;
1.1       pooka     109: };
                    110:
1.12      chs       111: static int     ugenhc_probe(device_t, cfdata_t, void *);
                    112: static void    ugenhc_attach(device_t, device_t, void *);
1.1       pooka     113:
                    114: CFATTACH_DECL_NEW(ugenhc, sizeof(struct ugenhc_softc),
                    115:        ugenhc_probe, ugenhc_attach, NULL, NULL);
                    116:
                    117: struct rusb_xfer {
                    118:        struct usbd_xfer rusb_xfer;
                    119:        int rusb_status; /* now this is a cheap trick */
                    120: };
                    121: #define RUSB(x) ((struct rusb_xfer *)x)
                    122:
                    123: #define UGENDEV_BASESTR "/dev/ugen"
                    124: #define UGENDEV_BUFSIZE 32
                    125: static void
1.18      christos  126: makeugendevstr(int devnum, int endpoint, char *buf, size_t len)
1.1       pooka     127: {
                    128:
                    129:        CTASSERT(UGENDEV_BUFSIZE > sizeof(UGENDEV_BASESTR)+sizeof("0.00")+1);
1.18      christos  130:        snprintf(buf, len, "%s%d.%02d", UGENDEV_BASESTR, devnum, endpoint);
1.1       pooka     131: }
                    132:
                    133: /*
                    134:  * Our fictional hubbie.
                    135:  */
                    136:
                    137: static const usb_device_descriptor_t rumphub_udd = {
                    138:        .bLength                = USB_DEVICE_DESCRIPTOR_SIZE,
                    139:        .bDescriptorType        = UDESC_DEVICE,
                    140:        .bDeviceClass           = UDCLASS_HUB,
                    141:        .bDeviceSubClass        = UDSUBCLASS_HUB,
                    142:        .bDeviceProtocol        = UDPROTO_FSHUB,
                    143:        .bMaxPacketSize         = 64,
1.8       pooka     144:        .idVendor               = { 0x75, 0x72 },
                    145:        .idProduct              = { 0x70, 0x6d },
1.1       pooka     146:        .bNumConfigurations     = 1,
                    147: };
                    148:
                    149: static const usb_config_descriptor_t rumphub_ucd = {
                    150:        .bLength                = USB_CONFIG_DESCRIPTOR_SIZE,
                    151:        .bDescriptorType        = UDESC_CONFIG,
                    152:        .wTotalLength           = { USB_CONFIG_DESCRIPTOR_SIZE
                    153:                                  + USB_INTERFACE_DESCRIPTOR_SIZE
                    154:                                  + USB_ENDPOINT_DESCRIPTOR_SIZE },
                    155:        .bNumInterface          = 1,
                    156:        .bmAttributes           = UC_SELF_POWERED | UC_ATTR_MBO,
                    157: };
                    158:
                    159: static const usb_interface_descriptor_t rumphub_uid = {
                    160:        .bLength                = USB_INTERFACE_DESCRIPTOR_SIZE,
                    161:        .bDescriptorType        = UDESC_INTERFACE,
                    162:        .bInterfaceNumber       = 0,
                    163:        .bNumEndpoints          = 1,
                    164:        .bInterfaceClass        = UICLASS_HUB,
                    165:        .bInterfaceSubClass     = UISUBCLASS_HUB,
                    166:        .bInterfaceProtocol     = UIPROTO_FSHUB,
                    167: };
                    168:
                    169: static const usb_endpoint_descriptor_t rumphub_epd = {
                    170:        .bLength                = USB_ENDPOINT_DESCRIPTOR_SIZE,
                    171:        .bDescriptorType        = UDESC_ENDPOINT,
                    172:        .bmAttributes           = UE_INTERRUPT,
                    173:        .wMaxPacketSize         = {64, 0},
                    174: };
                    175:
                    176: static const usb_hub_descriptor_t rumphub_hdd = {
                    177:        .bDescLength            = USB_HUB_DESCRIPTOR_SIZE,
                    178:        .bDescriptorType        = UDESC_HUB,
                    179:        .bNbrPorts              = 1,
                    180: };
                    181:
                    182: static usbd_status
                    183: rumpusb_root_ctrl_start(usbd_xfer_handle xfer)
                    184: {
                    185:        usb_device_request_t *req = &xfer->request;
                    186:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
                    187:        int len, totlen, value, curlen, err;
                    188:        uint8_t *buf = NULL;
                    189:
                    190:        len = totlen = UGETW(req->wLength);
                    191:        if (len)
                    192:                buf = KERNADDR(&xfer->dmabuf, 0);
                    193:        value = UGETW(req->wValue);
                    194:
                    195: #define C(x,y) ((x) | ((y) << 8))
                    196:        switch(C(req->bRequest, req->bmRequestType)) {
                    197:
                    198:        case C(UR_GET_CONFIG, UT_READ_DEVICE):
                    199:                if (len > 0) {
                    200:                        *buf = sc->sc_conf;
                    201:                        totlen = 1;
                    202:                }
                    203:                break;
                    204:
                    205:        case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
                    206:                switch (value >> 8) {
                    207:                case UDESC_DEVICE:
                    208:                        totlen = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
                    209:                        memcpy(buf, &rumphub_udd, totlen);
                    210:                        break;
                    211:
                    212:                case UDESC_CONFIG:
                    213:                        totlen = 0;
                    214:                        curlen = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
                    215:                        memcpy(buf, &rumphub_ucd, curlen);
                    216:                        len -= curlen;
                    217:                        buf += curlen;
                    218:                        totlen += curlen;
                    219:
                    220:                        curlen = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
                    221:                        memcpy(buf, &rumphub_uid, curlen);
                    222:                        len -= curlen;
                    223:                        buf += curlen;
                    224:                        totlen += curlen;
                    225:
                    226:                        curlen = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
                    227:                        memcpy(buf, &rumphub_epd, curlen);
                    228:                        len -= curlen;
                    229:                        buf += curlen;
                    230:                        totlen += curlen;
                    231:                        break;
                    232:
                    233:                case UDESC_STRING:
                    234: #define sd ((usb_string_descriptor_t *)buf)
                    235:                        switch (value & 0xff) {
                    236:                        case 0: /* Language table */
                    237:                                totlen = usb_makelangtbl(sd, len);
                    238:                                break;
                    239:                        case 1: /* Vendor */
                    240:                                totlen = usb_makestrdesc(sd, len, "rod nevada");
                    241:                                break;
                    242:                        case 2: /* Product */
                    243:                                totlen = usb_makestrdesc(sd, len,
                    244:                                    "RUMPUSBHC root hub");
                    245:                                break;
                    246:                        }
                    247: #undef sd
                    248:                        break;
                    249:
                    250:                default:
                    251:                        panic("unhandled read device request");
                    252:                        break;
                    253:                }
                    254:                break;
                    255:
                    256:        case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
                    257:                if (value >= USB_MAX_DEVICES) {
                    258:                        err = USBD_IOERROR;
                    259:                        goto ret;
                    260:                }
                    261:                sc->sc_addr = value;
                    262:                break;
                    263:
                    264:        case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
                    265:                if (value != 0 && value != 1) {
                    266:                        err = USBD_IOERROR;
                    267:                        goto ret;
                    268:                }
                    269:                sc->sc_conf = value;
                    270:                break;
                    271:
                    272:        case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
                    273:                switch (value) {
                    274:                case UHF_PORT_RESET:
                    275:                        sc->sc_port_change |= UPS_C_PORT_RESET;
                    276:                        break;
                    277:                case UHF_PORT_POWER:
                    278:                        break;
                    279:                default:
                    280:                        panic("unhandled");
                    281:                }
                    282:                break;
                    283:
                    284:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
                    285:                sc->sc_port_change &= ~value;
                    286:                break;
                    287:
                    288:        case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
                    289:                totlen = min(len, USB_HUB_DESCRIPTOR_SIZE);
                    290:                memcpy(buf, &rumphub_hdd, totlen);
                    291:                break;
                    292:
                    293:        case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
                    294:                /* huh?  other hc's do this */
                    295:                memset(buf, 0, len);
                    296:                totlen = len;
                    297:                break;
                    298:
                    299:        case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
                    300:                {
                    301:                usb_port_status_t ps;
                    302:
                    303:                USETW(ps.wPortStatus, sc->sc_port_status);
                    304:                USETW(ps.wPortChange, sc->sc_port_change);
                    305:                totlen = min(len, sizeof(ps));
                    306:                memcpy(buf, &ps, totlen);
                    307:                break;
                    308:                }
                    309:
                    310:        default:
                    311:                panic("unhandled request");
                    312:                break;
                    313:        }
                    314:        err = USBD_NORMAL_COMPLETION;
                    315:        xfer->actlen = totlen;
                    316:
                    317: ret:
                    318:        xfer->status = err;
1.21    ! skrll     319:        mutex_enter(&sc->sc_lock);
1.1       pooka     320:        usb_transfer_complete(xfer);
1.21    ! skrll     321:        mutex_exit(&sc->sc_lock);
        !           322:
1.1       pooka     323:        return (USBD_IN_PROGRESS);
                    324: }
                    325:
                    326: static usbd_status
                    327: rumpusb_root_ctrl_transfer(usbd_xfer_handle xfer)
                    328: {
1.21    ! skrll     329:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
1.1       pooka     330:        usbd_status err;
                    331:
1.21    ! skrll     332:        mutex_enter(&sc->sc_lock);
1.1       pooka     333:        err = usb_insert_transfer(xfer);
1.21    ! skrll     334:        mutex_exit(&sc->sc_lock);
1.1       pooka     335:        if (err)
                    336:                return (err);
                    337:
                    338:        return (rumpusb_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
                    339: }
                    340:
                    341: static void
                    342: rumpusb_root_ctrl_abort(usbd_xfer_handle xfer)
                    343: {
                    344:
                    345: }
                    346:
                    347: static void
                    348: rumpusb_root_ctrl_close(usbd_pipe_handle pipe)
                    349: {
                    350:
                    351: }
                    352:
                    353: static void
                    354: rumpusb_root_ctrl_cleartoggle(usbd_pipe_handle pipe)
                    355: {
                    356:
                    357: }
                    358:
                    359: static void
                    360: rumpusb_root_ctrl_done(usbd_xfer_handle xfer)
                    361: {
                    362:
                    363: }
                    364:
                    365: static const struct usbd_pipe_methods rumpusb_root_ctrl_methods = {
                    366:        .transfer =     rumpusb_root_ctrl_transfer,
                    367:        .start =        rumpusb_root_ctrl_start,
                    368:        .abort =        rumpusb_root_ctrl_abort,
                    369:        .close =        rumpusb_root_ctrl_close,
                    370:        .cleartoggle =  rumpusb_root_ctrl_cleartoggle,
                    371:        .done =         rumpusb_root_ctrl_done,
                    372: };
                    373:
                    374: static usbd_status
                    375: rumpusb_device_ctrl_start(usbd_xfer_handle xfer)
                    376: {
                    377:        usb_device_request_t *req = &xfer->request;
                    378:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
                    379:        uint8_t *buf = NULL;
                    380:        int len, totlen;
                    381:        int value;
                    382:        int err = 0;
                    383:        int ru_error, mightfail = 0;
                    384:
                    385:        len = totlen = UGETW(req->wLength);
                    386:        if (len)
                    387:                buf = KERNADDR(&xfer->dmabuf, 0);
                    388:        value = UGETW(req->wValue);
                    389:
                    390: #define C(x,y) ((x) | ((y) << 8))
                    391:        switch(C(req->bRequest, req->bmRequestType)) {
                    392:        case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
                    393:                switch (value>>8) {
                    394:                case UDESC_DEVICE:
                    395:                        {
                    396:                        usb_device_descriptor_t uddesc;
                    397:                        totlen = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
                    398:                        memset(buf, 0, totlen);
1.13      pooka     399:                        if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.3       pooka     400:                            USB_GET_DEVICE_DESC, &uddesc, &ru_error) == -1) {
                    401:                                err = EIO;
                    402:                                goto ret;
                    403:                        }
1.1       pooka     404:                        memcpy(buf, &uddesc, totlen);
                    405:                        }
                    406:
                    407:                        break;
                    408:                case UDESC_CONFIG:
                    409:                        {
                    410:                        struct usb_full_desc ufdesc;
1.7       pooka     411:                        ufdesc.ufd_config_index = value & 0xff;
1.1       pooka     412:                        ufdesc.ufd_size = len;
                    413:                        ufdesc.ufd_data = buf;
1.7       pooka     414:                        memset(buf, 0, len);
1.13      pooka     415:                        if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.7       pooka     416:                            USB_GET_FULL_DESC, &ufdesc, &ru_error) == -1) {
                    417:                                err = USBD_IOERROR;
                    418:                                goto ret;
                    419:                        }
                    420:                        totlen = ufdesc.ufd_size;
1.1       pooka     421:                        }
                    422:                        break;
                    423:
                    424:                case UDESC_STRING:
                    425:                        {
                    426:                        struct usb_device_info udi;
                    427:
1.13      pooka     428:                        if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.1       pooka     429:                            USB_GET_DEVICEINFO, &udi, &ru_error) == -1) {
                    430:                                printf("ugenhc: get dev info failed: %d\n",
                    431:                                    ru_error);
                    432:                                err = USBD_IOERROR;
                    433:                                goto ret;
                    434:                        }
                    435:
                    436:                        switch (value & 0xff) {
                    437: #define sd ((usb_string_descriptor_t *)buf)
                    438:                        case 0: /* language table */
                    439:                                break;
                    440:                        case 1: /* vendor */
                    441:                                totlen = usb_makestrdesc(sd, len,
                    442:                                    udi.udi_vendor);
                    443:                                break;
                    444:                        case 2: /* product */
                    445:                                totlen = usb_makestrdesc(sd, len,
                    446:                                    udi.udi_product);
                    447:                                break;
                    448:                        }
                    449: #undef sd
                    450:                        }
                    451:                        break;
                    452:
                    453:                default:
                    454:                        panic("not handled");
                    455:                }
                    456:                break;
                    457:
                    458:        case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
                    459:                /* ignored, ugen won't let us */
                    460:                break;
                    461:
                    462:        case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
1.13      pooka     463:                if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.7       pooka     464:                    USB_SET_CONFIG, &value, &ru_error) == -1) {
                    465:                        printf("ugenhc: set config failed: %d\n",
                    466:                            ru_error);
                    467:                        err = USBD_IOERROR;
                    468:                        goto ret;
                    469:                }
1.1       pooka     470:                break;
                    471:
                    472:        case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
                    473:                {
                    474:                struct usb_alt_interface uai;
                    475:
                    476:                totlen = 0;
                    477:                uai.uai_interface_index = UGETW(req->wIndex);
                    478:                uai.uai_alt_no = value;
1.13      pooka     479:                if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.1       pooka     480:                    USB_SET_ALTINTERFACE, &uai, &ru_error) == -1) {
                    481:                        printf("ugenhc: set alt interface failed: %d\n",
                    482:                            ru_error);
                    483:                        err = USBD_IOERROR;
                    484:                        goto ret;
                    485:                }
                    486:                break;
                    487:                }
                    488:
                    489:        /*
                    490:         * This request might fail unknown reasons.  "EIO" doesn't
                    491:         * give much help, and debugging the host ugen would be
                    492:         * necessary.  However, since it doesn't seem to really
                    493:         * affect anything, just let it fail for now.
                    494:         */
                    495:        case C(0x00, UT_WRITE_CLASS_INTERFACE):
                    496:                mightfail = 1;
                    497:                /*FALLTHROUGH*/
                    498:
                    499:        /*
                    500:         * XXX: don't wildcard these yet.  I want to better figure
                    501:         * out what to trap here.  This is kinda silly, though ...
                    502:         */
                    503:
                    504:        case C(0x01, UT_WRITE_VENDOR_DEVICE):
                    505:        case C(0x06, UT_WRITE_VENDOR_DEVICE):
                    506:        case C(0x07, UT_READ_VENDOR_DEVICE):
                    507:        case C(0x09, UT_READ_VENDOR_DEVICE):
                    508:        case C(0xfe, UT_READ_CLASS_INTERFACE):
                    509:        case C(0x01, UT_READ_CLASS_INTERFACE):
                    510:        case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
                    511:        case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
                    512:        case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
                    513:        case C(UR_GET_DESCRIPTOR, UT_READ_INTERFACE):
                    514:        case C(0xff, UT_WRITE_CLASS_INTERFACE):
                    515:        case C(0x20, UT_WRITE_CLASS_INTERFACE):
                    516:        case C(0x22, UT_WRITE_CLASS_INTERFACE):
                    517:        case C(0x0a, UT_WRITE_CLASS_INTERFACE):
                    518:        case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
1.9       pooka     519:        case C(0x00, UT_WRITE_CLASS_DEVICE):
1.2       pooka     520:        case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
1.1       pooka     521:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
                    522:        case C(UR_SET_REPORT, UT_WRITE_CLASS_INTERFACE):
                    523:        case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
                    524:                {
                    525:                struct usb_ctl_request ucr;
                    526:
                    527:                memcpy(&ucr.ucr_request, req, sizeof(ucr.ucr_request));
                    528:                ucr.ucr_data = buf;
1.13      pooka     529:                if (rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[UGEN_EPT_CTRL],
1.1       pooka     530:                    USB_DO_REQUEST, &ucr, &ru_error) == -1) {
1.2       pooka     531:                        if (!mightfail) {
1.1       pooka     532:                                panic("request failed: %d", ru_error);
1.2       pooka     533:                        } else {
1.1       pooka     534:                                err = ru_error;
1.2       pooka     535:                        }
1.1       pooka     536:                }
                    537:                }
                    538:                break;
                    539:
                    540:        default:
                    541:                panic("unhandled request");
                    542:                break;
                    543:        }
                    544:        xfer->actlen = totlen;
                    545:        err = USBD_NORMAL_COMPLETION;
                    546:
                    547:  ret:
                    548:        xfer->status = err;
1.21    ! skrll     549:        mutex_enter(&sc->sc_lock);
1.1       pooka     550:        usb_transfer_complete(xfer);
1.21    ! skrll     551:        mutex_exit(&sc->sc_lock);
        !           552:
1.1       pooka     553:        return (USBD_IN_PROGRESS);
                    554: }
                    555:
                    556: static usbd_status
                    557: rumpusb_device_ctrl_transfer(usbd_xfer_handle xfer)
                    558: {
1.21    ! skrll     559:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
1.1       pooka     560:        usbd_status err;
                    561:
1.21    ! skrll     562:        mutex_enter(&sc->sc_lock);
1.1       pooka     563:        err = usb_insert_transfer(xfer);
1.21    ! skrll     564:        mutex_exit(&sc->sc_lock);
1.1       pooka     565:        if (err)
                    566:                return (err);
                    567:
                    568:        return (rumpusb_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
                    569: }
                    570:
                    571: static void
                    572: rumpusb_device_ctrl_abort(usbd_xfer_handle xfer)
                    573: {
                    574:
                    575: }
                    576:
                    577: static void
                    578: rumpusb_device_ctrl_close(usbd_pipe_handle pipe)
                    579: {
                    580:
                    581: }
                    582:
                    583: static void
                    584: rumpusb_device_ctrl_cleartoggle(usbd_pipe_handle pipe)
                    585: {
                    586:
                    587: }
                    588:
                    589: static void
                    590: rumpusb_device_ctrl_done(usbd_xfer_handle xfer)
                    591: {
                    592:
                    593: }
                    594:
                    595: static const struct usbd_pipe_methods rumpusb_device_ctrl_methods = {
                    596:        .transfer =     rumpusb_device_ctrl_transfer,
                    597:        .start =        rumpusb_device_ctrl_start,
                    598:        .abort =        rumpusb_device_ctrl_abort,
                    599:        .close =        rumpusb_device_ctrl_close,
                    600:        .cleartoggle =  rumpusb_device_ctrl_cleartoggle,
                    601:        .done =         rumpusb_device_ctrl_done,
                    602: };
                    603:
1.3       pooka     604: static void
                    605: rhscintr(void *arg)
                    606: {
                    607:        char buf[UGENDEV_BUFSIZE];
                    608:        struct ugenhc_softc *sc = arg;
1.1       pooka     609:        usbd_xfer_handle xfer;
1.3       pooka     610:        int fd, error;
                    611:
1.18      christos  612:        makeugendevstr(sc->sc_devnum, 0, buf, sizeof(buf));
1.4       pooka     613:
1.3       pooka     614:        for (;;) {
1.4       pooka     615:                /*
                    616:                 * Detect device attach.
                    617:                 */
                    618:
                    619:                for (;;) {
1.15      pooka     620:                        error = rumpuser_open(buf, RUMPUSER_OPEN_RDWR, &fd);
                    621:                        if (error != 0)
1.4       pooka     622:                                break;
                    623:                        kpause("ugwait", false, hz/4, NULL);
                    624:                }
                    625:
                    626:                sc->sc_ugenfd[UGEN_EPT_CTRL] = fd;
                    627:                sc->sc_port_status = UPS_CURRENT_CONNECT_STATUS
                    628:                    | UPS_PORT_ENABLED | UPS_PORT_POWER;
1.7       pooka     629:                sc->sc_port_change = UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET;
1.4       pooka     630:
                    631:                xfer = sc->sc_intrxfer;
1.7       pooka     632:                memset(xfer->buffer, 0xff, xfer->length);
                    633:                xfer->actlen = xfer->length;
1.4       pooka     634:                xfer->status = USBD_NORMAL_COMPLETION;
1.7       pooka     635:
1.21    ! skrll     636:                mutex_enter(&sc->sc_lock);
1.4       pooka     637:                usb_transfer_complete(xfer);
1.21    ! skrll     638:                mutex_exit(&sc->sc_lock);
1.4       pooka     639:
1.7       pooka     640:                kpause("ugwait2", false, hz, NULL);
                    641:
1.4       pooka     642:                /*
                    643:                 * Detect device detach.
                    644:                 */
                    645:
                    646:                for (;;) {
1.11      pooka     647:                        fd = rumpuser_open(buf, RUMPUSER_OPEN_RDWR, &error);
1.4       pooka     648:                        if (fd == -1)
                    649:                                break;
1.7       pooka     650:
1.15      pooka     651:                        error = rumpuser_close(fd);
1.4       pooka     652:                        kpause("ugwait2", false, hz/4, NULL);
                    653:                }
1.1       pooka     654:
1.4       pooka     655:                sc->sc_port_status = ~(UPS_CURRENT_CONNECT_STATUS
                    656:                    | UPS_PORT_ENABLED | UPS_PORT_POWER);
1.7       pooka     657:                sc->sc_port_change = UPS_C_CONNECT_STATUS | UPS_C_PORT_RESET;
1.5       pooka     658:
1.15      pooka     659:                error = rumpuser_close(sc->sc_ugenfd[UGEN_EPT_CTRL]);
1.4       pooka     660:                sc->sc_ugenfd[UGEN_EPT_CTRL] = -1;
1.1       pooka     661:
1.4       pooka     662:                xfer = sc->sc_intrxfer;
1.7       pooka     663:                memset(xfer->buffer, 0xff, xfer->length);
                    664:                xfer->actlen = xfer->length;
1.4       pooka     665:                xfer->status = USBD_NORMAL_COMPLETION;
1.21    ! skrll     666:                mutex_enter(&sc->sc_lock);
1.4       pooka     667:                usb_transfer_complete(xfer);
1.21    ! skrll     668:                mutex_exit(&sc->sc_lock);
1.7       pooka     669:
                    670:                kpause("ugwait3", false, hz, NULL);
1.4       pooka     671:        }
1.1       pooka     672:
1.3       pooka     673:        kthread_exit(0);
1.1       pooka     674: }
                    675:
                    676: static usbd_status
                    677: rumpusb_root_intr_start(usbd_xfer_handle xfer)
                    678: {
1.3       pooka     679:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
                    680:        int error;
1.1       pooka     681:
1.21    ! skrll     682:        mutex_enter(&sc->sc_lock);
1.3       pooka     683:        sc->sc_intrxfer = xfer;
                    684:        if (!sc->sc_rhintr) {
                    685:                error = kthread_create(PRI_NONE, 0, NULL,
                    686:                    rhscintr, sc, &sc->sc_rhintr, "ugenrhi");
                    687:                if (error)
1.19      skrll     688:                        xfer->status = USBD_IOERROR;
1.3       pooka     689:        }
1.21    ! skrll     690:        mutex_exit(&sc->sc_lock);
1.1       pooka     691:
                    692:        return (USBD_IN_PROGRESS);
                    693: }
                    694:
                    695: static usbd_status
                    696: rumpusb_root_intr_transfer(usbd_xfer_handle xfer)
                    697: {
1.21    ! skrll     698:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
1.1       pooka     699:        usbd_status err;
                    700:
1.21    ! skrll     701:        mutex_enter(&sc->sc_lock);
1.1       pooka     702:        err = usb_insert_transfer(xfer);
1.21    ! skrll     703:        mutex_exit(&sc->sc_lock);
1.1       pooka     704:        if (err)
                    705:                return (err);
                    706:
                    707:        return (rumpusb_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
                    708: }
                    709:
                    710: static void
                    711: rumpusb_root_intr_abort(usbd_xfer_handle xfer)
                    712: {
                    713:
                    714: }
                    715:
                    716: static void
                    717: rumpusb_root_intr_close(usbd_pipe_handle pipe)
                    718: {
                    719:
                    720: }
                    721:
                    722: static void
                    723: rumpusb_root_intr_cleartoggle(usbd_pipe_handle pipe)
                    724: {
                    725:
                    726: }
                    727:
                    728: static void
                    729: rumpusb_root_intr_done(usbd_xfer_handle xfer)
                    730: {
                    731:
                    732: }
                    733:
                    734: static const struct usbd_pipe_methods rumpusb_root_intr_methods = {
                    735:        .transfer =     rumpusb_root_intr_transfer,
                    736:        .start =        rumpusb_root_intr_start,
                    737:        .abort =        rumpusb_root_intr_abort,
                    738:        .close =        rumpusb_root_intr_close,
                    739:        .cleartoggle =  rumpusb_root_intr_cleartoggle,
                    740:        .done =         rumpusb_root_intr_done,
                    741: };
                    742:
                    743: static usbd_status
                    744: rumpusb_device_bulk_start(usbd_xfer_handle xfer)
                    745: {
                    746:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
1.9       pooka     747:        usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc;
1.15      pooka     748:        size_t n, done;
1.1       pooka     749:        bool isread;
                    750:        int len, error, endpt;
                    751:        uint8_t *buf;
1.6       pooka     752:        int xfererr = USBD_NORMAL_COMPLETION;
1.9       pooka     753:        int shortval, i;
1.1       pooka     754:
1.9       pooka     755:        ed = xfer->pipe->endpoint->edesc;
                    756:        endpt = ed->bEndpointAddress;
1.1       pooka     757:        isread = UE_GET_DIR(endpt) == UE_DIR_IN;
                    758:        endpt = UE_GET_ADDR(endpt);
                    759:        KASSERT(endpt < UGEN_NEPTS);
                    760:
                    761:        buf = KERNADDR(&xfer->dmabuf, 0);
                    762:        done = 0;
1.9       pooka     763:        if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) {
                    764:                for (i = 0, len = 0; i < xfer->nframes; i++)
                    765:                        len += xfer->frlengths[i];
                    766:        } else {
                    767:                KASSERT(xfer->length);
                    768:                len = xfer->length;
                    769:        }
                    770:        shortval = (xfer->flags & USBD_SHORT_XFER_OK) != 0;
1.1       pooka     771:
                    772:        while (RUSB(xfer)->rusb_status == 0) {
                    773:                if (isread) {
1.14      pooka     774:                        struct rumpuser_iovec iov;
                    775:
1.13      pooka     776:                        rumpcomp_ugenhc_ioctl(sc->sc_ugenfd[endpt],
1.9       pooka     777:                            USB_SET_SHORT_XFER, &shortval, &error);
1.14      pooka     778:                        iov.iov_base = buf+done;
                    779:                        iov.iov_len = len-done;
1.15      pooka     780:                        error = rumpuser_iovread(sc->sc_ugenfd[endpt], &iov, 1,
                    781:                            RUMPUSER_IOV_NOSEEK, &n);
                    782:                        if (error) {
1.1       pooka     783:                                n = 0;
1.9       pooka     784:                                if (done == 0) {
                    785:                                        if (error == ETIMEDOUT)
                    786:                                                continue;
                    787:                                        xfererr = USBD_IOERROR;
                    788:                                        goto out;
                    789:                                }
1.1       pooka     790:                        }
                    791:                        done += n;
                    792:                        if (done == len)
                    793:                                break;
                    794:                } else {
1.14      pooka     795:                        struct rumpuser_iovec iov;
                    796:
                    797:                        iov.iov_base = buf;
                    798:                        iov.iov_len = len;
1.15      pooka     799:                        error = rumpuser_iovwrite(sc->sc_ugenfd[endpt], &iov, 1,
                    800:                            RUMPUSER_IOV_NOSEEK, &n);
1.1       pooka     801:                        done = n;
                    802:                        if (done == len)
                    803:                                break;
1.15      pooka     804:                        else if (!error)
1.1       pooka     805:                                panic("short write");
1.6       pooka     806:
                    807:                        xfererr = USBD_IOERROR;
                    808:                        goto out;
1.1       pooka     809:                }
                    810:
1.9       pooka     811:                if (shortval) {
                    812:                        /*
                    813:                         * Holy XXX, bitman.  I get >16byte interrupt
                    814:                         * transfers from ugen in 16 byte chunks.
                    815:                         * Don't know how to better fix this for now.
                    816:                         * Of course this hack will fail e.g. if someone
                    817:                         * sports other magic values or if the transfer
                    818:                         * happens to be an integral multiple of 16
                    819:                         * in size ....
                    820:                         */
                    821:                        if ((ed->bmAttributes & UE_XFERTYPE) == UE_INTERRUPT
                    822:                            && n == 16) {
                    823:                                continue;
                    824:                        } else {
                    825:                                break;
                    826:                        }
                    827:                }
1.1       pooka     828:        }
                    829:
                    830:        if (RUSB(xfer)->rusb_status == 0) {
                    831:                xfer->actlen = done;
                    832:        } else {
1.6       pooka     833:                xfererr = USBD_CANCELLED;
1.1       pooka     834:                RUSB(xfer)->rusb_status = 2;
                    835:        }
                    836:  out:
1.9       pooka     837:        if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS)
                    838:                if (done != len)
                    839:                        panic("lazy bum");
1.6       pooka     840:        xfer->status = xfererr;
1.21    ! skrll     841:        mutex_enter(&sc->sc_lock);
1.1       pooka     842:        usb_transfer_complete(xfer);
1.21    ! skrll     843:        mutex_exit(&sc->sc_lock);
1.1       pooka     844:        return (USBD_IN_PROGRESS);
                    845: }
                    846:
                    847: static void
                    848: doxfer_kth(void *arg)
                    849: {
1.21    ! skrll     850:        usbd_pipe_handle pipe = arg;
        !           851:        struct ugenhc_softc *sc = pipe->device->bus->hci_private;
1.1       pooka     852:
1.21    ! skrll     853:        mutex_enter(&sc->sc_lock);
1.1       pooka     854:        do {
1.21    ! skrll     855:                usbd_xfer_handle xfer = SIMPLEQ_FIRST(&pipe->queue);
        !           856:                mutex_exit(&sc->sc_lock);
        !           857:                rumpusb_device_bulk_start(xfer);
        !           858:                mutex_enter(&sc->sc_lock);
        !           859:        } while (!SIMPLEQ_EMPTY(&pipe->queue));
        !           860:        mutex_exit(&sc->sc_lock);
1.1       pooka     861:        kthread_exit(0);
                    862: }
                    863:
                    864: static usbd_status
                    865: rumpusb_device_bulk_transfer(usbd_xfer_handle xfer)
                    866: {
1.21    ! skrll     867:        struct ugenhc_softc *sc = xfer->pipe->device->bus->hci_private;
1.1       pooka     868:        usbd_status err;
                    869:
                    870:        if (!rump_threads) {
                    871:                /* XXX: lie about supporting async transfers */
                    872:                if ((xfer->flags & USBD_SYNCHRONOUS) == 0) {
                    873:                        printf("non-threaded rump does not support "
                    874:                            "async transfers.\n");
                    875:                        return USBD_IN_PROGRESS;
                    876:                }
                    877:
1.21    ! skrll     878:                mutex_enter(&sc->sc_lock);
1.1       pooka     879:                err = usb_insert_transfer(xfer);
1.21    ! skrll     880:                mutex_exit(&sc->sc_lock);
1.1       pooka     881:                if (err)
                    882:                        return err;
                    883:
                    884:                return rumpusb_device_bulk_start(
                    885:                    SIMPLEQ_FIRST(&xfer->pipe->queue));
                    886:        } else {
1.21    ! skrll     887:                mutex_enter(&sc->sc_lock);
1.1       pooka     888:                err = usb_insert_transfer(xfer);
1.21    ! skrll     889:                mutex_exit(&sc->sc_lock);
1.1       pooka     890:                if (err)
                    891:                        return err;
1.21    ! skrll     892:                kthread_create(PRI_NONE, 0, NULL, doxfer_kth, xfer->pipe, NULL,
1.1       pooka     893:                    "rusbhcxf");
                    894:
                    895:                return USBD_IN_PROGRESS;
                    896:        }
                    897: }
                    898:
                    899: /* wait for transfer to abort.  yea, this is cheesy (from a spray can) */
                    900: static void
                    901: rumpusb_device_bulk_abort(usbd_xfer_handle xfer)
                    902: {
                    903:        struct rusb_xfer *rx = RUSB(xfer);
                    904:
                    905:        rx->rusb_status = 1;
                    906:        while (rx->rusb_status < 2) {
                    907:                kpause("jopo", false, hz/10, NULL);
                    908:        }
                    909: }
                    910:
                    911: static void
                    912: rumpusb_device_bulk_close(usbd_pipe_handle pipe)
                    913: {
1.7       pooka     914:        struct ugenhc_softc *sc = pipe->device->bus->hci_private;
                    915:        int endpt = pipe->endpoint->edesc->bEndpointAddress;
                    916:        usbd_xfer_handle xfer;
1.1       pooka     917:
1.21    ! skrll     918:        KASSERT(mutex_owned(&sc->sc_lock));
        !           919:
1.8       pooka     920:        endpt = UE_GET_ADDR(endpt);
                    921:
1.7       pooka     922:        while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL)
                    923:                rumpusb_device_bulk_abort(xfer);
                    924:
1.15      pooka     925:        rumpuser_close(sc->sc_ugenfd[endpt]);
1.7       pooka     926:        sc->sc_ugenfd[endpt] = -1;
                    927:        sc->sc_fdmodes[endpt] = -1;
1.1       pooka     928: }
                    929:
                    930: static void
                    931: rumpusb_device_bulk_cleartoggle(usbd_pipe_handle pipe)
                    932: {
                    933:
                    934: }
                    935:
                    936: static void
                    937: rumpusb_device_bulk_done(usbd_xfer_handle xfer)
                    938: {
                    939:
                    940: }
                    941:
                    942: static const struct usbd_pipe_methods rumpusb_device_bulk_methods = {
                    943:        .transfer =     rumpusb_device_bulk_transfer,
                    944:        .start =        rumpusb_device_bulk_start,
                    945:        .abort =        rumpusb_device_bulk_abort,
                    946:        .close =        rumpusb_device_bulk_close,
                    947:        .cleartoggle =  rumpusb_device_bulk_cleartoggle,
                    948:        .done =         rumpusb_device_bulk_done,
                    949: };
                    950:
                    951: static usbd_status
                    952: ugenhc_open(struct usbd_pipe *pipe)
                    953: {
                    954:        usbd_device_handle dev = pipe->device;
                    955:        struct ugenhc_softc *sc = dev->bus->hci_private;
                    956:        usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
                    957:        u_int8_t addr = dev->address;
                    958:        u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
                    959:        char buf[UGENDEV_BUFSIZE];
                    960:        int endpt, oflags, error;
                    961:        int fd, val;
                    962:
                    963:        if (addr == sc->sc_addr) {
                    964:                switch (xfertype) {
                    965:                case UE_CONTROL:
                    966:                        pipe->methods = &rumpusb_root_ctrl_methods;
                    967:                        break;
                    968:                case UE_INTERRUPT:
                    969:                        pipe->methods = &rumpusb_root_intr_methods;
                    970:                        break;
                    971:                default:
                    972:                        panic("%d not supported", xfertype);
                    973:                        break;
                    974:                }
                    975:        } else {
                    976:                switch (xfertype) {
                    977:                case UE_CONTROL:
                    978:                        pipe->methods = &rumpusb_device_ctrl_methods;
                    979:                        break;
                    980:                case UE_INTERRUPT:
                    981:                case UE_BULK:
1.9       pooka     982:                case UE_ISOCHRONOUS:
1.1       pooka     983:                        pipe->methods = &rumpusb_device_bulk_methods;
                    984:                        endpt = pipe->endpoint->edesc->bEndpointAddress;
                    985:                        if (UE_GET_DIR(endpt) == UE_DIR_IN) {
                    986:                                oflags = O_RDONLY;
                    987:                        } else {
                    988:                                oflags = O_WRONLY;
                    989:                        }
                    990:                        endpt = UE_GET_ADDR(endpt);
                    991:
1.9       pooka     992:                        if (oflags != O_RDONLY && xfertype == UE_ISOCHRONOUS) {
                    993:                                printf("WARNING: faking isoc write open\n");
                    994:                                oflags = O_RDONLY;
                    995:                        }
                    996:
1.1       pooka     997:                        if (sc->sc_fdmodes[endpt] == oflags
                    998:                            || sc->sc_fdmodes[endpt] == O_RDWR)
                    999:                                break;
                   1000:
                   1001:                        if (sc->sc_fdmodes[endpt] != -1) {
                   1002:                                /* XXX: closing from under someone? */
1.15      pooka    1003:                                error = rumpuser_close(sc->sc_ugenfd[endpt]);
1.1       pooka    1004:                                oflags = O_RDWR;
                   1005:                        }
                   1006:
1.18      christos 1007:                        makeugendevstr(sc->sc_devnum, endpt, buf, sizeof(buf));
1.11      pooka    1008:                        /* XXX: theoretically should convert oflags */
1.15      pooka    1009:                        error = rumpuser_open(buf, oflags, &fd);
                   1010:                        if (error != 0) {
1.1       pooka    1011:                                return USBD_INVAL; /* XXX: no mapping */
1.9       pooka    1012:                        }
1.1       pooka    1013:                        val = 100;
1.13      pooka    1014:                        if (rumpcomp_ugenhc_ioctl(fd, USB_SET_TIMEOUT, &val,
1.1       pooka    1015:                            &error) == -1)
                   1016:                                panic("timeout set failed");
                   1017:                        sc->sc_ugenfd[endpt] = fd;
                   1018:                        sc->sc_fdmodes[endpt] = oflags;
1.9       pooka    1019:
1.1       pooka    1020:                        break;
                   1021:                default:
                   1022:                        panic("%d not supported", xfertype);
                   1023:                        break;
                   1024:
                   1025:                }
                   1026:        }
                   1027:        return 0;
                   1028: }
                   1029:
                   1030: static void
                   1031: ugenhc_softint(void *arg)
                   1032: {
                   1033:
                   1034: }
                   1035:
                   1036: static void
                   1037: ugenhc_poll(struct usbd_bus *ubus)
                   1038: {
                   1039:
                   1040: }
                   1041:
                   1042: static usbd_status
                   1043: ugenhc_allocm(struct usbd_bus *bus, usb_dma_t *dma, uint32_t size)
                   1044: {
                   1045:        struct ugenhc_softc *sc = bus->hci_private;
                   1046:
                   1047:        return usb_allocmem(&sc->sc_bus, size, 0, dma);
                   1048: }
                   1049:
                   1050: static void
1.8       pooka    1051: ugenhc_freem(struct usbd_bus *bus, usb_dma_t *dma)
1.1       pooka    1052: {
1.8       pooka    1053:        struct ugenhc_softc *sc = bus->hci_private;
1.1       pooka    1054:
1.8       pooka    1055:        usb_freemem(&sc->sc_bus, dma);
1.1       pooka    1056: }
                   1057:
                   1058: static struct usbd_xfer *
                   1059: ugenhc_allocx(struct usbd_bus *bus)
                   1060: {
                   1061:        usbd_xfer_handle xfer;
                   1062:
                   1063:        xfer = kmem_zalloc(sizeof(struct usbd_xfer), KM_SLEEP);
                   1064:        xfer->busy_free = XFER_BUSY;
                   1065:
                   1066:        return xfer;
                   1067: }
                   1068:
                   1069: static void
                   1070: ugenhc_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
                   1071: {
                   1072:
                   1073:        kmem_free(xfer, sizeof(struct usbd_xfer));
                   1074: }
                   1075:
1.21    ! skrll    1076:
        !          1077: static void
        !          1078: ugenhc_getlock(struct usbd_bus *bus, kmutex_t **lock)
        !          1079: {
        !          1080:        struct ugenhc_softc *sc = bus->hci_private;
        !          1081:
        !          1082:        *lock = &sc->sc_lock;
        !          1083: }
        !          1084:
1.1       pooka    1085: struct ugenhc_pipe {
                   1086:        struct usbd_pipe pipe;
                   1087: };
                   1088:
                   1089: static const struct usbd_bus_methods ugenhc_bus_methods = {
                   1090:        .open_pipe =    ugenhc_open,
                   1091:        .soft_intr =    ugenhc_softint,
                   1092:        .do_poll =      ugenhc_poll,
                   1093:        .allocm =       ugenhc_allocm,
                   1094:        .freem =        ugenhc_freem,
                   1095:        .allocx =       ugenhc_allocx,
                   1096:        .freex =        ugenhc_freex,
1.21    ! skrll    1097:        .get_lock =     ugenhc_getlock
1.1       pooka    1098: };
                   1099:
                   1100: static int
1.12      chs      1101: ugenhc_probe(device_t parent, cfdata_t match, void *aux)
1.1       pooka    1102: {
                   1103:        char buf[UGENDEV_BUFSIZE];
                   1104:
1.18      christos 1105:        makeugendevstr(match->cf_unit, 0, buf, sizeof(buf));
1.15      pooka    1106:        if (rumpuser_getfileinfo(buf, NULL, NULL) != 0)
1.1       pooka    1107:                return 0;
                   1108:
                   1109:        return 1;
                   1110: }
                   1111:
                   1112: static void
1.12      chs      1113: ugenhc_attach(device_t parent, device_t self, void *aux)
1.1       pooka    1114: {
                   1115:        struct mainbus_attach_args *maa = aux;
                   1116:        struct ugenhc_softc *sc = device_private(self);
                   1117:
                   1118:        aprint_normal("\n");
                   1119:
                   1120:        memset(sc, 0, sizeof(*sc));
                   1121:        memset(&sc->sc_ugenfd, -1, sizeof(sc->sc_ugenfd));
                   1122:        memset(&sc->sc_fdmodes, -1, sizeof(sc->sc_fdmodes));
                   1123:
                   1124:        sc->sc_bus.usbrev = USBREV_2_0;
                   1125:        sc->sc_bus.methods = &ugenhc_bus_methods;
                   1126:        sc->sc_bus.hci_private = sc;
                   1127:        sc->sc_bus.pipe_size = sizeof(struct ugenhc_pipe);
                   1128:        sc->sc_devnum = maa->maa_unit;
                   1129:
1.21    ! skrll    1130:        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
        !          1131:
1.1       pooka    1132:        config_found(self, &sc->sc_bus, usbctlprint);
                   1133: }

CVSweb <webmaster@jp.NetBSD.org>