[BACK]Return to motg.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / usb

Annotation of src/sys/dev/usb/motg.c, Revision 1.19.2.1

1.19.2.1! pgoyette    1: /*     $NetBSD: motg.c,v 1.21 2018/04/09 16:21:11 jakllsch Exp $       */
1.1       bouyer      2:
                      3: /*
                      4:  * Copyright (c) 1998, 2004, 2011, 2012, 2014 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Lennart Augustsson (lennart@augustsson.net) at
                      9:  * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca),
                     10:  * Matthew R. Green (mrg@eterna.com.au), and Manuel Bouyer (bouyer@netbsd.org).
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     22:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     23:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     24:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     25:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     26:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     27:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     28:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     29:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     30:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     31:  * POSSIBILITY OF SUCH DAMAGE.
                     32:  */
                     33:
                     34:
                     35: /*
                     36:  * This file contains the driver for the Mentor Graphics Inventra USB
                     37:  * 2.0 High Speed Dual-Role controller.
                     38:  *
                     39:  * NOTE: The current implementation only supports Device Side Mode!
                     40:  */
                     41:
1.14      skrll      42: #include <sys/cdefs.h>
1.19.2.1! pgoyette   43: __KERNEL_RCSID(0, "$NetBSD: motg.c,v 1.21 2018/04/09 16:21:11 jakllsch Exp $");
1.14      skrll      44:
                     45: #ifdef _KERNEL_OPT
                     46: #include "opt_usb.h"
                     47: #endif
1.10      jmcneill   48:
1.14      skrll      49: #include <sys/param.h>
1.1       bouyer     50:
1.14      skrll      51: #include <sys/bus.h>
                     52: #include <sys/cpu.h>
                     53: #include <sys/device.h>
1.1       bouyer     54: #include <sys/kernel.h>
                     55: #include <sys/kmem.h>
                     56: #include <sys/proc.h>
                     57: #include <sys/queue.h>
1.14      skrll      58: #include <sys/select.h>
                     59: #include <sys/sysctl.h>
                     60: #include <sys/systm.h>
1.1       bouyer     61:
                     62: #include <machine/endian.h>
                     63:
                     64: #include <dev/usb/usb.h>
                     65: #include <dev/usb/usbdi.h>
                     66: #include <dev/usb/usbdivar.h>
                     67: #include <dev/usb/usb_mem.h>
1.14      skrll      68: #include <dev/usb/usbhist.h>
1.1       bouyer     69:
                     70: #include <dev/usb/motgreg.h>
                     71: #include <dev/usb/motgvar.h>
1.14      skrll      72: #include <dev/usb/usbroothub.h>
                     73:
                     74: #ifdef USB_DEBUG
                     75: #ifndef MOTG_DEBUG
                     76: #define motgdebug 0
                     77: #else
                     78: int motgdebug = 0;
                     79:
                     80: SYSCTL_SETUP(sysctl_hw_motg_setup, "sysctl hw.motg setup")
                     81: {
                     82:        int err;
                     83:        const struct sysctlnode *rnode;
                     84:        const struct sysctlnode *cnode;
                     85:
                     86:        err = sysctl_createv(clog, 0, NULL, &rnode,
                     87:            CTLFLAG_PERMANENT, CTLTYPE_NODE, "motg",
                     88:            SYSCTL_DESCR("motg global controls"),
                     89:            NULL, 0, NULL, 0, CTL_HW, CTL_CREATE, CTL_EOL);
                     90:
                     91:        if (err)
                     92:                goto fail;
                     93:
                     94:        /* control debugging printfs */
                     95:        err = sysctl_createv(clog, 0, &rnode, &cnode,
                     96:            CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_INT,
                     97:            "debug", SYSCTL_DESCR("Enable debugging output"),
                     98:            NULL, 0, &motgdebug, sizeof(motgdebug), CTL_CREATE, CTL_EOL);
                     99:        if (err)
                    100:                goto fail;
                    101:
                    102:        return;
                    103: fail:
                    104:        aprint_error("%s: sysctl_createv failed (err = %d)\n", __func__, err);
                    105: }
                    106:
                    107: #endif /* MOTG_DEBUG */
                    108: #endif /* USB_DEBUG */
1.1       bouyer    109:
                    110: #define MD_ROOT 0x0002
                    111: #define MD_CTRL 0x0004
                    112: #define MD_BULK 0x0008
1.14      skrll     113:
                    114: #define        DPRINTF(FMT,A,B,C,D)    USBHIST_LOGN(motgdebug,1,FMT,A,B,C,D)
                    115: #define        DPRINTFN(N,FMT,A,B,C,D) USBHIST_LOGM(motgdebug,N,FMT,A,B,C,D)
                    116: #define        MOTGHIST_FUNC()         USBHIST_FUNC()
                    117: #define        MOTGHIST_CALLED(name)   USBHIST_CALLED(motgdebug)
                    118:
1.1       bouyer    119:
                    120: /* various timeouts, for various speeds */
                    121: /* control NAK timeouts */
                    122: #define NAK_TO_CTRL    10      /* 1024 frames, about 1s */
                    123: #define NAK_TO_CTRL_HIGH 13    /* 8k microframes, about 0.8s */
                    124:
                    125: /* intr/iso polling intervals */
                    126: #define POLL_TO                100     /* 100 frames, about 0.1s */
                    127: #define POLL_TO_HIGH   10      /* 100 microframes, about 0.12s */
                    128:
                    129: /* bulk NAK timeouts */
1.3       bouyer    130: #define NAK_TO_BULK    0 /* disabled */
                    131: #define NAK_TO_BULK_HIGH 0
1.1       bouyer    132:
                    133: static void            motg_hub_change(struct motg_softc *);
                    134:
1.14      skrll     135: static usbd_status     motg_root_intr_transfer(struct usbd_xfer *);
                    136: static usbd_status     motg_root_intr_start(struct usbd_xfer *);
                    137: static void            motg_root_intr_abort(struct usbd_xfer *);
                    138: static void            motg_root_intr_close(struct usbd_pipe *);
                    139: static void            motg_root_intr_done(struct usbd_xfer *);
                    140:
                    141: static usbd_status     motg_open(struct usbd_pipe *);
1.1       bouyer    142: static void            motg_poll(struct usbd_bus *);
                    143: static void            motg_softintr(void *);
1.14      skrll     144: static struct usbd_xfer *
                    145:                        motg_allocx(struct usbd_bus *, unsigned int);
                    146: static void            motg_freex(struct usbd_bus *, struct usbd_xfer *);
1.1       bouyer    147: static void            motg_get_lock(struct usbd_bus *, kmutex_t **);
1.14      skrll     148: static int             motg_roothub_ctrl(struct usbd_bus *, usb_device_request_t *,
                    149:                            void *, int);
                    150:
                    151: static void            motg_noop(struct usbd_pipe *pipe);
1.1       bouyer    152: static usbd_status     motg_portreset(struct motg_softc*);
                    153:
1.14      skrll     154: static usbd_status     motg_device_ctrl_transfer(struct usbd_xfer *);
                    155: static usbd_status     motg_device_ctrl_start(struct usbd_xfer *);
                    156: static void            motg_device_ctrl_abort(struct usbd_xfer *);
                    157: static void            motg_device_ctrl_close(struct usbd_pipe *);
                    158: static void            motg_device_ctrl_done(struct usbd_xfer *);
1.1       bouyer    159: static usbd_status     motg_device_ctrl_start1(struct motg_softc *);
1.14      skrll     160: static void            motg_device_ctrl_read(struct usbd_xfer *);
1.1       bouyer    161: static void            motg_device_ctrl_intr_rx(struct motg_softc *);
                    162: static void            motg_device_ctrl_intr_tx(struct motg_softc *);
                    163:
1.14      skrll     164: static usbd_status     motg_device_data_transfer(struct usbd_xfer *);
                    165: static usbd_status     motg_device_data_start(struct usbd_xfer *);
1.1       bouyer    166: static usbd_status     motg_device_data_start1(struct motg_softc *,
                    167:                            struct motg_hw_ep *);
1.14      skrll     168: static void            motg_device_data_abort(struct usbd_xfer *);
                    169: static void            motg_device_data_close(struct usbd_pipe *);
                    170: static void            motg_device_data_done(struct usbd_xfer *);
1.1       bouyer    171: static void            motg_device_intr_rx(struct motg_softc *, int);
                    172: static void            motg_device_intr_tx(struct motg_softc *, int);
1.14      skrll     173: static void            motg_device_data_read(struct usbd_xfer *);
                    174: static void            motg_device_data_write(struct usbd_xfer *);
1.1       bouyer    175:
1.14      skrll     176: static void            motg_device_clear_toggle(struct usbd_pipe *);
                    177: static void            motg_device_xfer_abort(struct usbd_xfer *);
1.1       bouyer    178:
                    179: #define UBARR(sc) bus_space_barrier((sc)->sc_iot, (sc)->sc_ioh, 0, (sc)->sc_size, \
                    180:                        BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE)
                    181: #define UWRITE1(sc, r, x) \
                    182:  do { UBARR(sc); bus_space_write_1((sc)->sc_iot, (sc)->sc_ioh, (r), (x)); \
                    183:  } while (/*CONSTCOND*/0)
                    184: #define UWRITE2(sc, r, x) \
                    185:  do { UBARR(sc); bus_space_write_2((sc)->sc_iot, (sc)->sc_ioh, (r), (x)); \
                    186:  } while (/*CONSTCOND*/0)
                    187: #define UWRITE4(sc, r, x) \
                    188:  do { UBARR(sc); bus_space_write_4((sc)->sc_iot, (sc)->sc_ioh, (r), (x)); \
                    189:  } while (/*CONSTCOND*/0)
                    190:
                    191: static __inline uint32_t
                    192: UREAD1(struct motg_softc *sc, bus_size_t r)
                    193: {
                    194:
                    195:        UBARR(sc);
                    196:        return bus_space_read_1(sc->sc_iot, sc->sc_ioh, r);
                    197: }
                    198: static __inline uint32_t
                    199: UREAD2(struct motg_softc *sc, bus_size_t r)
                    200: {
                    201:
                    202:        UBARR(sc);
                    203:        return bus_space_read_2(sc->sc_iot, sc->sc_ioh, r);
                    204: }
1.4       joerg     205:
                    206: #if 0
1.1       bouyer    207: static __inline uint32_t
                    208: UREAD4(struct motg_softc *sc, bus_size_t r)
                    209: {
                    210:
                    211:        UBARR(sc);
                    212:        return bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
                    213: }
1.4       joerg     214: #endif
1.1       bouyer    215:
                    216: static void
1.7       skrll     217: musbotg_pull_common(struct motg_softc *sc, uint8_t on)
1.1       bouyer    218: {
1.14      skrll     219:        uint8_t val;
1.1       bouyer    220:
1.14      skrll     221:        val = UREAD1(sc, MUSB2_REG_POWER);
                    222:        if (on)
                    223:                val |= MUSB2_MASK_SOFTC;
                    224:        else
                    225:                val &= ~MUSB2_MASK_SOFTC;
1.1       bouyer    226:
1.14      skrll     227:        UWRITE1(sc, MUSB2_REG_POWER, val);
1.1       bouyer    228: }
                    229:
                    230: const struct usbd_bus_methods motg_bus_methods = {
1.14      skrll     231:        .ubm_open =     motg_open,
                    232:        .ubm_softint =  motg_softintr,
                    233:        .ubm_dopoll =   motg_poll,
                    234:        .ubm_allocx =   motg_allocx,
                    235:        .ubm_freex =    motg_freex,
                    236:        .ubm_getlock =  motg_get_lock,
                    237:        .ubm_rhctrl =   motg_roothub_ctrl,
1.1       bouyer    238: };
                    239:
                    240: const struct usbd_pipe_methods motg_root_intr_methods = {
1.14      skrll     241:        .upm_transfer = motg_root_intr_transfer,
                    242:        .upm_start =    motg_root_intr_start,
                    243:        .upm_abort =    motg_root_intr_abort,
                    244:        .upm_close =    motg_root_intr_close,
                    245:        .upm_cleartoggle =      motg_noop,
                    246:        .upm_done =     motg_root_intr_done,
1.1       bouyer    247: };
                    248:
                    249: const struct usbd_pipe_methods motg_device_ctrl_methods = {
1.14      skrll     250:        .upm_transfer = motg_device_ctrl_transfer,
                    251:        .upm_start =    motg_device_ctrl_start,
                    252:        .upm_abort =    motg_device_ctrl_abort,
                    253:        .upm_close =    motg_device_ctrl_close,
                    254:        .upm_cleartoggle =      motg_noop,
                    255:        .upm_done =     motg_device_ctrl_done,
1.1       bouyer    256: };
                    257:
                    258: const struct usbd_pipe_methods motg_device_data_methods = {
1.14      skrll     259:        .upm_transfer = motg_device_data_transfer,
                    260:        .upm_start =    motg_device_data_start,
                    261:        .upm_abort =    motg_device_data_abort,
                    262:        .upm_close =    motg_device_data_close,
                    263:        .upm_cleartoggle =      motg_device_clear_toggle,
                    264:        .upm_done =     motg_device_data_done,
1.1       bouyer    265: };
                    266:
1.14      skrll     267: int
1.1       bouyer    268: motg_init(struct motg_softc *sc)
                    269: {
                    270:        uint32_t nrx, ntx, val;
                    271:        int dynfifo;
                    272:        int offset, i;
                    273:
1.14      skrll     274:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                    275:
1.1       bouyer    276:        if (sc->sc_mode == MOTG_MODE_DEVICE)
1.14      skrll     277:                return ENOTSUP; /* not supported */
1.1       bouyer    278:
                    279:        /* disable all interrupts */
                    280:        UWRITE1(sc, MUSB2_REG_INTUSBE, 0);
                    281:        UWRITE2(sc, MUSB2_REG_INTTXE, 0);
                    282:        UWRITE2(sc, MUSB2_REG_INTRXE, 0);
                    283:        /* disable pullup */
                    284:
1.7       skrll     285:        musbotg_pull_common(sc, 0);
1.1       bouyer    286:
1.10      jmcneill  287: #ifdef MUSB2_REG_RXDBDIS
1.1       bouyer    288:        /* disable double packet buffering XXX what's this ? */
                    289:        UWRITE2(sc, MUSB2_REG_RXDBDIS, 0xFFFF);
                    290:        UWRITE2(sc, MUSB2_REG_TXDBDIS, 0xFFFF);
1.10      jmcneill  291: #endif
1.1       bouyer    292:
                    293:        /* enable HighSpeed and ISO Update flags */
                    294:
                    295:        UWRITE1(sc, MUSB2_REG_POWER,
                    296:            MUSB2_MASK_HSENAB | MUSB2_MASK_ISOUPD);
                    297:
                    298:        if (sc->sc_mode == MOTG_MODE_DEVICE) {
                    299:                /* clear Session bit, if set */
                    300:                val = UREAD1(sc, MUSB2_REG_DEVCTL);
                    301:                val &= ~MUSB2_MASK_SESS;
                    302:                UWRITE1(sc, MUSB2_REG_DEVCTL, val);
                    303:        } else {
                    304:                /* Enter session for Host mode */
                    305:                val = UREAD1(sc, MUSB2_REG_DEVCTL);
                    306:                val |= MUSB2_MASK_SESS;
                    307:                UWRITE1(sc, MUSB2_REG_DEVCTL, val);
                    308:        }
                    309:        delay(1000);
1.18      pgoyette  310:        DPRINTF("DEVCTL 0x%jx", UREAD1(sc, MUSB2_REG_DEVCTL), 0, 0, 0);
1.1       bouyer    311:
                    312:        /* disable testmode */
                    313:
                    314:        UWRITE1(sc, MUSB2_REG_TESTMODE, 0);
                    315:
1.10      jmcneill  316: #ifdef MUSB2_REG_MISC
1.7       skrll     317:        /* set default value */
1.1       bouyer    318:
                    319:        UWRITE1(sc, MUSB2_REG_MISC, 0);
1.10      jmcneill  320: #endif
1.1       bouyer    321:
1.7       skrll     322:        /* select endpoint index 0 */
1.1       bouyer    323:
                    324:        UWRITE1(sc, MUSB2_REG_EPINDEX, 0);
                    325:
1.9       jmcneill  326:        if (sc->sc_ep_max == 0) {
                    327:                /* read out number of endpoints */
                    328:                nrx = (UREAD1(sc, MUSB2_REG_EPINFO) / 16);
1.1       bouyer    329:
1.9       jmcneill  330:                ntx = (UREAD1(sc, MUSB2_REG_EPINFO) % 16);
1.1       bouyer    331:
1.9       jmcneill  332:                /* these numbers exclude the control endpoint */
1.1       bouyer    333:
1.18      pgoyette  334:                DPRINTFN(1,"RX/TX endpoints: %ju/%ju", nrx, ntx, 0, 0);
1.1       bouyer    335:
1.9       jmcneill  336:                sc->sc_ep_max = MAX(nrx, ntx);
                    337:        } else {
                    338:                nrx = ntx = sc->sc_ep_max;
                    339:        }
1.1       bouyer    340:        if (sc->sc_ep_max == 0) {
                    341:                aprint_error_dev(sc->sc_dev, " no endpoints\n");
1.14      skrll     342:                return -1;
1.1       bouyer    343:        }
                    344:        KASSERT(sc->sc_ep_max <= MOTG_MAX_HW_EP);
                    345:        /* read out configuration data */
                    346:        val = UREAD1(sc, MUSB2_REG_CONFDATA);
                    347:
1.18      pgoyette  348:        DPRINTF("Config Data: 0x%02jx", val, 0, 0, 0);
1.1       bouyer    349:
                    350:        dynfifo = (val & MUSB2_MASK_CD_DYNFIFOSZ) ? 1 : 0;
                    351:
1.7       skrll     352:        if (dynfifo) {
1.1       bouyer    353:                aprint_normal_dev(sc->sc_dev, "Dynamic FIFO sizing detected, "
                    354:                    "assuming 16Kbytes of FIFO RAM\n");
1.7       skrll     355:        }
                    356:
1.18      pgoyette  357:        DPRINTF("HW version: 0x%04jx\n", UREAD1(sc, MUSB2_REG_HWVERS), 0, 0, 0);
1.1       bouyer    358:
                    359:        /* initialise endpoint profiles */
                    360:        sc->sc_in_ep[0].ep_fifo_size = 64;
                    361:        sc->sc_out_ep[0].ep_fifo_size = 0; /* not used */
                    362:        sc->sc_out_ep[0].ep_number = sc->sc_in_ep[0].ep_number = 0;
                    363:        SIMPLEQ_INIT(&sc->sc_in_ep[0].ep_pipes);
                    364:        offset = 64;
                    365:
                    366:        for (i = 1; i <= sc->sc_ep_max; i++) {
                    367:                int fiforx_size, fifotx_size, fifo_size;
                    368:
1.7       skrll     369:                /* select endpoint */
1.1       bouyer    370:                UWRITE1(sc, MUSB2_REG_EPINDEX, i);
                    371:
1.11      jmcneill  372:                if (sc->sc_ep_fifosize) {
                    373:                        fiforx_size = fifotx_size = sc->sc_ep_fifosize;
                    374:                } else {
                    375:                        val = UREAD1(sc, MUSB2_REG_FSIZE);
                    376:                        fiforx_size = (val & MUSB2_MASK_RX_FSIZE) >> 4;
                    377:                        fifotx_size = (val & MUSB2_MASK_TX_FSIZE);
                    378:                }
1.1       bouyer    379:
1.18      pgoyette  380:                DPRINTF("Endpoint %ju FIFO size: IN=%ju, OUT=%ju, DYN=%jd",
1.14      skrll     381:                    i, fifotx_size, fiforx_size, dynfifo);
1.1       bouyer    382:
                    383:                if (dynfifo) {
1.12      jmcneill  384:                        if (sc->sc_ep_fifosize) {
                    385:                                fifo_size = ffs(sc->sc_ep_fifosize) - 1;
1.1       bouyer    386:                        } else {
1.12      jmcneill  387:                                if (i < 3) {
                    388:                                        fifo_size = 12;       /* 4K */
                    389:                                } else if (i < 10) {
                    390:                                        fifo_size = 10;       /* 1K */
                    391:                                } else {
                    392:                                        fifo_size = 7;        /* 128 bytes */
                    393:                                }
1.7       skrll     394:                        }
1.1       bouyer    395:                        if (fiforx_size && (i <= nrx)) {
                    396:                                fiforx_size = fifo_size;
                    397:                                if (fifo_size > 7) {
1.3       bouyer    398: #if 0
1.7       skrll     399:                                        UWRITE1(sc, MUSB2_REG_RXFIFOSZ,
1.1       bouyer    400:                                            MUSB2_VAL_FIFOSZ(fifo_size) |
                    401:                                            MUSB2_MASK_FIFODB);
1.3       bouyer    402: #else
1.7       skrll     403:                                        UWRITE1(sc, MUSB2_REG_RXFIFOSZ,
1.3       bouyer    404:                                            MUSB2_VAL_FIFOSZ(fifo_size));
                    405: #endif
1.1       bouyer    406:                                } else {
1.7       skrll     407:                                        UWRITE1(sc, MUSB2_REG_RXFIFOSZ,
1.3       bouyer    408:                                            MUSB2_VAL_FIFOSZ(fifo_size));
1.1       bouyer    409:                                }
1.7       skrll     410:                                UWRITE2(sc, MUSB2_REG_RXFIFOADD,
1.1       bouyer    411:                                    offset >> 3);
                    412:                                offset += (1 << fiforx_size);
                    413:                        }
                    414:                        if (fifotx_size && (i <= ntx)) {
                    415:                                fifotx_size = fifo_size;
                    416:                                if (fifo_size > 7) {
1.3       bouyer    417: #if 0
1.7       skrll     418:                                        UWRITE1(sc, MUSB2_REG_TXFIFOSZ,
                    419:                                            MUSB2_VAL_FIFOSZ(fifo_size) |
1.1       bouyer    420:                                            MUSB2_MASK_FIFODB);
1.3       bouyer    421: #else
1.7       skrll     422:                                        UWRITE1(sc, MUSB2_REG_TXFIFOSZ,
                    423:                                            MUSB2_VAL_FIFOSZ(fifo_size));
1.3       bouyer    424: #endif
1.1       bouyer    425:                                } else {
1.7       skrll     426:                                        UWRITE1(sc, MUSB2_REG_TXFIFOSZ,
                    427:                                            MUSB2_VAL_FIFOSZ(fifo_size));
                    428:                                }
                    429:
                    430:                                UWRITE2(sc, MUSB2_REG_TXFIFOADD,
1.1       bouyer    431:                                    offset >> 3);
1.7       skrll     432:
1.1       bouyer    433:                                offset += (1 << fifotx_size);
                    434:                        }
                    435:                }
                    436:                if (fiforx_size && (i <= nrx)) {
                    437:                        sc->sc_in_ep[i].ep_fifo_size = (1 << fiforx_size);
                    438:                        SIMPLEQ_INIT(&sc->sc_in_ep[i].ep_pipes);
                    439:                }
                    440:                if (fifotx_size && (i <= ntx)) {
                    441:                        sc->sc_out_ep[i].ep_fifo_size = (1 << fifotx_size);
                    442:                        SIMPLEQ_INIT(&sc->sc_out_ep[i].ep_pipes);
                    443:                }
                    444:                sc->sc_out_ep[i].ep_number = sc->sc_in_ep[i].ep_number = i;
                    445:        }
                    446:
1.7       skrll     447:
1.18      pgoyette  448:        DPRINTF("Dynamic FIFO size = %jd bytes", offset, 0, 0, 0);
1.1       bouyer    449:
                    450:        /* turn on default interrupts */
                    451:
                    452:        if (sc->sc_mode == MOTG_MODE_HOST) {
                    453:                UWRITE1(sc, MUSB2_REG_INTUSBE, 0xff);
                    454:                UWRITE2(sc, MUSB2_REG_INTTXE, 0xffff);
                    455:                UWRITE2(sc, MUSB2_REG_INTRXE, 0xffff);
                    456:        } else
                    457:                UWRITE1(sc, MUSB2_REG_INTUSBE, MUSB2_MASK_IRESET);
                    458:
                    459:        sc->sc_xferpool = pool_cache_init(sizeof(struct motg_xfer), 0, 0, 0,
                    460:            "motgxfer", NULL, IPL_USB, NULL, NULL, NULL);
                    461:
                    462:        mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB);
1.13      skrll     463:        mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_USB);
1.1       bouyer    464:
                    465:        /* Set up the bus struct. */
1.14      skrll     466:        sc->sc_bus.ub_methods = &motg_bus_methods;
                    467:        sc->sc_bus.ub_pipesize= sizeof(struct motg_pipe);
                    468:        sc->sc_bus.ub_revision = USBREV_2_0;
                    469:        sc->sc_bus.ub_usedma = false;
                    470:        sc->sc_bus.ub_hcpriv = sc;
1.1       bouyer    471:        sc->sc_child = config_found(sc->sc_dev, &sc->sc_bus, usbctlprint);
1.14      skrll     472:        return 0;
1.1       bouyer    473: }
                    474:
                    475: static int
1.14      skrll     476: motg_select_ep(struct motg_softc *sc, struct usbd_pipe *pipe)
1.1       bouyer    477: {
1.14      skrll     478:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(pipe);
                    479:        usb_endpoint_descriptor_t *ed = pipe->up_endpoint->ue_edesc;
1.1       bouyer    480:        struct motg_hw_ep *ep;
                    481:        int i, size;
                    482:
1.14      skrll     483:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                    484:
1.1       bouyer    485:        ep = (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN) ?
                    486:            sc->sc_in_ep : sc->sc_out_ep;
1.14      skrll     487:        size = UE_GET_SIZE(UGETW(pipe->up_endpoint->ue_edesc->wMaxPacketSize));
1.1       bouyer    488:
                    489:        for (i = sc->sc_ep_max; i >= 1; i--) {
1.14      skrll     490:                DPRINTF(UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN ?
1.18      pgoyette  491:                    "in_ep[%jd].ep_fifo_size %jd size %jd ref %jd" :
                    492:                    "out_ep[%jd].ep_fifo_size %jd size %jd ref %jd", i,
1.14      skrll     493:                    ep[i].ep_fifo_size, size, ep[i].refcount);
1.1       bouyer    494:                if (ep[i].ep_fifo_size >= size) {
                    495:                        /* found a suitable endpoint */
                    496:                        otgpipe->hw_ep = &ep[i];
                    497:                        mutex_enter(&sc->sc_lock);
                    498:                        if (otgpipe->hw_ep->refcount > 0) {
                    499:                                /* no luck, try next */
                    500:                                mutex_exit(&sc->sc_lock);
                    501:                                otgpipe->hw_ep = NULL;
                    502:                        } else {
                    503:                                otgpipe->hw_ep->refcount++;
                    504:                                SIMPLEQ_INSERT_TAIL(&otgpipe->hw_ep->ep_pipes,
                    505:                                    otgpipe, ep_pipe_list);
                    506:                                mutex_exit(&sc->sc_lock);
                    507:                                return 0;
                    508:                        }
                    509:                }
                    510:        }
                    511:        return -1;
                    512: }
                    513:
                    514: /* Open a new pipe. */
                    515: usbd_status
1.14      skrll     516: motg_open(struct usbd_pipe *pipe)
1.1       bouyer    517: {
1.14      skrll     518:        struct motg_softc *sc = MOTG_PIPE2SC(pipe);
                    519:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(pipe);
                    520:        usb_endpoint_descriptor_t *ed = pipe->up_endpoint->ue_edesc;
                    521:        uint8_t rhaddr = pipe->up_dev->ud_bus->ub_rhaddr;
                    522:
                    523:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                    524:
1.18      pgoyette  525:        DPRINTF("pipe=%#jx, addr=%jd, endpt=%jd (%jd)", (uintptr_t)pipe,
1.14      skrll     526:            pipe->up_dev->ud_addr, ed->bEndpointAddress, rhaddr);
1.1       bouyer    527:
                    528:        if (sc->sc_dying)
                    529:                return USBD_IOERROR;
                    530:
                    531:        /* toggle state needed for bulk endpoints */
1.14      skrll     532:        otgpipe->nexttoggle = pipe->up_endpoint->ue_toggle;
1.1       bouyer    533:
1.14      skrll     534:        if (pipe->up_dev->ud_addr == rhaddr) {
1.1       bouyer    535:                switch (ed->bEndpointAddress) {
                    536:                case USB_CONTROL_ENDPOINT:
1.14      skrll     537:                        pipe->up_methods = &roothub_ctrl_methods;
1.1       bouyer    538:                        break;
1.14      skrll     539:                case UE_DIR_IN | USBROOTHUB_INTR_ENDPT:
                    540:                        pipe->up_methods = &motg_root_intr_methods;
1.1       bouyer    541:                        break;
                    542:                default:
1.14      skrll     543:                        return USBD_INVAL;
1.1       bouyer    544:                }
                    545:        } else {
                    546:                switch (ed->bmAttributes & UE_XFERTYPE) {
                    547:                case UE_CONTROL:
1.14      skrll     548:                        pipe->up_methods = &motg_device_ctrl_methods;
1.1       bouyer    549:                        /* always use sc_in_ep[0] for in and out */
                    550:                        otgpipe->hw_ep = &sc->sc_in_ep[0];
                    551:                        mutex_enter(&sc->sc_lock);
                    552:                        otgpipe->hw_ep->refcount++;
                    553:                        SIMPLEQ_INSERT_TAIL(&otgpipe->hw_ep->ep_pipes,
                    554:                            otgpipe, ep_pipe_list);
                    555:                        mutex_exit(&sc->sc_lock);
                    556:                        break;
                    557:                case UE_BULK:
                    558:                case UE_INTERRUPT:
1.7       skrll     559:                        DPRINTFN(MD_BULK,
1.18      pgoyette  560:                            "type %jd dir %jd pipe wMaxPacketSize %jd",
1.14      skrll     561:                            UE_GET_XFERTYPE(ed->bmAttributes),
                    562:                            UE_GET_DIR(pipe->up_endpoint->ue_edesc->bEndpointAddress),
                    563:                            UGETW(pipe->up_endpoint->ue_edesc->wMaxPacketSize), 0);
1.1       bouyer    564:                        if (motg_select_ep(sc, pipe) != 0)
                    565:                                goto bad;
                    566:                        KASSERT(otgpipe->hw_ep != NULL);
1.14      skrll     567:                        pipe->up_methods = &motg_device_data_methods;
                    568:                        otgpipe->nexttoggle = pipe->up_endpoint->ue_toggle;
1.1       bouyer    569:                        break;
                    570:                default:
                    571:                        goto bad;
                    572: #ifdef notyet
                    573:                case UE_ISOCHRONOUS:
                    574:                        ...
                    575:                        break;
                    576: #endif /* notyet */
                    577:                }
                    578:        }
1.14      skrll     579:        return USBD_NORMAL_COMPLETION;
1.1       bouyer    580:
                    581:  bad:
1.14      skrll     582:        return USBD_NOMEM;
1.1       bouyer    583: }
                    584:
                    585: void
                    586: motg_softintr(void *v)
                    587: {
                    588:        struct usbd_bus *bus = v;
1.14      skrll     589:        struct motg_softc *sc = MOTG_BUS2SC(bus);
1.1       bouyer    590:        uint16_t rx_status, tx_status;
                    591:        uint8_t ctrl_status;
                    592:        uint32_t val;
                    593:        int i;
                    594:
1.14      skrll     595:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
1.1       bouyer    596:
1.14      skrll     597:        KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock));
                    598:
1.18      pgoyette  599:        DPRINTFN(MD_ROOT | MD_CTRL, "sc %#jx", (uintptr_t)sc, 0 ,0 ,0);
1.1       bouyer    600:
                    601:        mutex_spin_enter(&sc->sc_intr_lock);
                    602:        rx_status = sc->sc_intr_rx_ep;
                    603:        sc->sc_intr_rx_ep = 0;
                    604:        tx_status = sc->sc_intr_tx_ep;
                    605:        sc->sc_intr_tx_ep = 0;
                    606:        ctrl_status = sc->sc_intr_ctrl;
                    607:        sc->sc_intr_ctrl = 0;
                    608:        mutex_spin_exit(&sc->sc_intr_lock);
                    609:
                    610:        ctrl_status |= UREAD1(sc, MUSB2_REG_INTUSB);
                    611:
                    612:        if (ctrl_status & (MUSB2_MASK_IRESET |
                    613:            MUSB2_MASK_IRESUME | MUSB2_MASK_ISUSP |
                    614:            MUSB2_MASK_ICONN | MUSB2_MASK_IDISC)) {
1.18      pgoyette  615:                DPRINTFN(MD_ROOT | MD_CTRL, "bus 0x%jx", ctrl_status, 0, 0, 0);
1.1       bouyer    616:
                    617:                if (ctrl_status & MUSB2_MASK_IRESET) {
                    618:                        sc->sc_isreset = 1;
                    619:                        sc->sc_port_suspended = 0;
                    620:                        sc->sc_port_suspended_change = 1;
                    621:                        sc->sc_connected_changed = 1;
                    622:                        sc->sc_port_enabled = 1;
                    623:
                    624:                        val = UREAD1(sc, MUSB2_REG_POWER);
                    625:                        if (val & MUSB2_MASK_HSMODE)
                    626:                                sc->sc_high_speed = 1;
                    627:                        else
                    628:                                sc->sc_high_speed = 0;
1.18      pgoyette  629:                        DPRINTFN(MD_ROOT | MD_CTRL, "speed %jd", sc->sc_high_speed,
1.14      skrll     630:                            0, 0, 0);
1.1       bouyer    631:
                    632:                        /* turn off interrupts */
                    633:                        val = MUSB2_MASK_IRESET;
                    634:                        val &= ~MUSB2_MASK_IRESUME;
                    635:                        val |= MUSB2_MASK_ISUSP;
                    636:                        UWRITE1(sc, MUSB2_REG_INTUSBE, val);
                    637:                        UWRITE2(sc, MUSB2_REG_INTTXE, 0);
                    638:                        UWRITE2(sc, MUSB2_REG_INTRXE, 0);
                    639:                }
                    640:                if (ctrl_status & MUSB2_MASK_IRESUME) {
                    641:                        if (sc->sc_port_suspended) {
                    642:                                sc->sc_port_suspended = 0;
                    643:                                sc->sc_port_suspended_change = 1;
                    644:                                val = UREAD1(sc, MUSB2_REG_INTUSBE);
                    645:                                /* disable resume interrupt */
                    646:                                val &= ~MUSB2_MASK_IRESUME;
                    647:                                /* enable suspend interrupt */
                    648:                                val |= MUSB2_MASK_ISUSP;
                    649:                                UWRITE1(sc, MUSB2_REG_INTUSBE, val);
                    650:                        }
                    651:                } else if (ctrl_status & MUSB2_MASK_ISUSP) {
                    652:                        if (!sc->sc_port_suspended) {
                    653:                                sc->sc_port_suspended = 1;
                    654:                                sc->sc_port_suspended_change = 1;
                    655:
                    656:                                val = UREAD1(sc, MUSB2_REG_INTUSBE);
                    657:                                /* disable suspend interrupt */
                    658:                                val &= ~MUSB2_MASK_ISUSP;
                    659:                                /* enable resume interrupt */
                    660:                                val |= MUSB2_MASK_IRESUME;
                    661:                                UWRITE1(sc, MUSB2_REG_INTUSBE, val);
                    662:                        }
                    663:                }
                    664:                if (ctrl_status & MUSB2_MASK_ICONN) {
                    665:                        sc->sc_connected = 1;
                    666:                        sc->sc_connected_changed = 1;
                    667:                        sc->sc_isreset = 1;
                    668:                        sc->sc_port_enabled = 1;
                    669:                } else if (ctrl_status & MUSB2_MASK_IDISC) {
                    670:                        sc->sc_connected = 0;
                    671:                        sc->sc_connected_changed = 1;
                    672:                        sc->sc_isreset = 0;
                    673:                        sc->sc_port_enabled = 0;
                    674:                }
                    675:
                    676:                /* complete root HUB interrupt endpoint */
                    677:
                    678:                motg_hub_change(sc);
                    679:        }
                    680:        /*
                    681:         * read in interrupt status and mix with the status we
                    682:         * got from the wrapper
                    683:         */
                    684:        rx_status |= UREAD2(sc, MUSB2_REG_INTRX);
                    685:        tx_status |= UREAD2(sc, MUSB2_REG_INTTX);
                    686:
1.14      skrll     687:        KASSERTMSG((rx_status & 0x01) == 0, "ctrl_rx %08x", rx_status);
1.1       bouyer    688:        if (tx_status & 0x01)
                    689:                motg_device_ctrl_intr_tx(sc);
                    690:        for (i = 1; i <= sc->sc_ep_max; i++) {
                    691:                if (rx_status & (0x01 << i))
                    692:                        motg_device_intr_rx(sc, i);
                    693:                if (tx_status & (0x01 << i))
                    694:                        motg_device_intr_tx(sc, i);
                    695:        }
                    696:        return;
                    697: }
                    698:
                    699: void
                    700: motg_poll(struct usbd_bus *bus)
                    701: {
1.14      skrll     702:        struct motg_softc *sc = MOTG_BUS2SC(bus);
1.1       bouyer    703:
                    704:        sc->sc_intr_poll(sc->sc_intr_poll_arg);
                    705:        mutex_enter(&sc->sc_lock);
                    706:        motg_softintr(bus);
                    707:        mutex_exit(&sc->sc_lock);
                    708: }
                    709:
                    710: int
                    711: motg_intr(struct motg_softc *sc, uint16_t rx_ep, uint16_t tx_ep,
1.2       bouyer    712:     uint8_t ctrl)
1.1       bouyer    713: {
                    714:        KASSERT(mutex_owned(&sc->sc_intr_lock));
                    715:        sc->sc_intr_tx_ep = tx_ep;
                    716:        sc->sc_intr_rx_ep = rx_ep;
                    717:        sc->sc_intr_ctrl = ctrl;
                    718:
1.14      skrll     719:        if (!sc->sc_bus.ub_usepolling) {
1.1       bouyer    720:                usb_schedsoftintr(&sc->sc_bus);
                    721:        }
                    722:        return 1;
                    723: }
                    724:
1.2       bouyer    725: int
                    726: motg_intr_vbus(struct motg_softc *sc, int vbus)
                    727: {
                    728:        uint8_t val;
1.14      skrll     729:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                    730:
1.2       bouyer    731:        if (sc->sc_mode == MOTG_MODE_HOST && vbus == 0) {
1.14      skrll     732:                DPRINTF("vbus down, try to re-enable", 0, 0, 0, 0);
1.2       bouyer    733:                /* try to re-enter session for Host mode */
                    734:                val = UREAD1(sc, MUSB2_REG_DEVCTL);
                    735:                val |= MUSB2_MASK_SESS;
                    736:                UWRITE1(sc, MUSB2_REG_DEVCTL, val);
                    737:        }
                    738:        return 1;
                    739: }
                    740:
1.14      skrll     741: struct usbd_xfer *
                    742: motg_allocx(struct usbd_bus *bus, unsigned int nframes)
1.1       bouyer    743: {
1.14      skrll     744:        struct motg_softc *sc = MOTG_BUS2SC(bus);
                    745:        struct usbd_xfer *xfer;
1.1       bouyer    746:
1.19      skrll     747:        xfer = pool_cache_get(sc->sc_xferpool, PR_WAITOK);
1.1       bouyer    748:        if (xfer != NULL) {
                    749:                memset(xfer, 0, sizeof(struct motg_xfer));
                    750: #ifdef DIAGNOSTIC
1.14      skrll     751:                xfer->ux_state = XFER_BUSY;
1.1       bouyer    752: #endif
                    753:        }
1.14      skrll     754:        return xfer;
1.1       bouyer    755: }
                    756:
                    757: void
1.14      skrll     758: motg_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
1.1       bouyer    759: {
1.14      skrll     760:        struct motg_softc *sc = MOTG_BUS2SC(bus);
1.1       bouyer    761:
                    762: #ifdef DIAGNOSTIC
1.14      skrll     763:        if (xfer->ux_state != XFER_BUSY) {
1.1       bouyer    764:                printf("motg_freex: xfer=%p not busy, 0x%08x\n", xfer,
1.14      skrll     765:                       xfer->ux_state);
1.1       bouyer    766:        }
1.14      skrll     767:        xfer->ux_state = XFER_FREE;
1.1       bouyer    768: #endif
                    769:        pool_cache_put(sc->sc_xferpool, xfer);
                    770: }
                    771:
                    772: static void
                    773: motg_get_lock(struct usbd_bus *bus, kmutex_t **lock)
                    774: {
1.14      skrll     775:        struct motg_softc *sc = MOTG_BUS2SC(bus);
1.1       bouyer    776:
                    777:        *lock = &sc->sc_lock;
                    778: }
                    779:
                    780: /*
1.14      skrll     781:  * Routines to emulate the root hub.
1.1       bouyer    782:  */
1.14      skrll     783: Static int
                    784: motg_roothub_ctrl(struct usbd_bus *bus, usb_device_request_t *req,
                    785:     void *buf, int buflen)
                    786: {
                    787:        struct motg_softc *sc = MOTG_BUS2SC(bus);
                    788:        int status, change, totlen = 0;
                    789:        uint16_t len, value, index;
1.1       bouyer    790:        usb_port_status_t ps;
                    791:        usbd_status err;
                    792:        uint32_t val;
                    793:
1.14      skrll     794:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                    795:
1.1       bouyer    796:        if (sc->sc_dying)
1.14      skrll     797:                return -1;
1.1       bouyer    798:
1.18      pgoyette  799:        DPRINTFN(MD_ROOT, "type=0x%02jx request=%02jx", req->bmRequestType,
1.14      skrll     800:            req->bRequest, 0, 0);
1.1       bouyer    801:
                    802:        len = UGETW(req->wLength);
                    803:        value = UGETW(req->wValue);
                    804:        index = UGETW(req->wIndex);
                    805:
                    806: #define C(x,y) ((x) | ((y) << 8))
1.14      skrll     807:        switch (C(req->bRequest, req->bmRequestType)) {
                    808:        case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
1.18      pgoyette  809:                DPRINTFN(MD_ROOT, "wValue=0x%04jx", value, 0, 0, 0);
1.14      skrll     810:                switch (value) {
                    811: #define sd ((usb_string_descriptor_t *)buf)
                    812:                case C(2, UDESC_STRING):
                    813:                        /* Product */
                    814:                        totlen = usb_makestrdesc(sd, len, "MOTG root hub");
1.1       bouyer    815:                        break;
                    816: #undef sd
                    817:                default:
1.14      skrll     818:                        /* default from usbroothub */
                    819:                        return buflen;
1.1       bouyer    820:                }
                    821:                break;
                    822:        /* Hub requests */
                    823:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
                    824:                break;
                    825:        case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
                    826:                DPRINTFN(MD_ROOT,
1.18      pgoyette  827:                    "UR_CLEAR_PORT_FEATURE port=%jd feature=%jd", index, value,
1.14      skrll     828:                    0, 0);
1.1       bouyer    829:                if (index != 1) {
1.14      skrll     830:                        return -1;
1.1       bouyer    831:                }
1.14      skrll     832:                switch (value) {
1.1       bouyer    833:                case UHF_PORT_ENABLE:
                    834:                        sc->sc_port_enabled = 0;
                    835:                        break;
                    836:                case UHF_PORT_SUSPEND:
                    837:                        if (sc->sc_port_suspended != 0) {
                    838:                                val = UREAD1(sc, MUSB2_REG_POWER);
                    839:                                val &= ~MUSB2_MASK_SUSPMODE;
                    840:                                val |= MUSB2_MASK_RESUME;
                    841:                                UWRITE1(sc, MUSB2_REG_POWER, val);
                    842:                                /* wait 20 milliseconds */
                    843:                                usb_delay_ms(&sc->sc_bus, 20);
                    844:                                val = UREAD1(sc, MUSB2_REG_POWER);
                    845:                                val &= ~MUSB2_MASK_RESUME;
                    846:                                UWRITE1(sc, MUSB2_REG_POWER, val);
                    847:                                sc->sc_port_suspended = 0;
                    848:                                sc->sc_port_suspended_change = 1;
                    849:                        }
                    850:                        break;
                    851:                case UHF_PORT_RESET:
                    852:                        break;
                    853:                case UHF_C_PORT_CONNECTION:
                    854:                        break;
                    855:                case UHF_C_PORT_ENABLE:
                    856:                        break;
                    857:                case UHF_C_PORT_OVER_CURRENT:
                    858:                        break;
                    859:                case UHF_C_PORT_RESET:
                    860:                        sc->sc_isreset = 0;
1.14      skrll     861:                        break;
1.1       bouyer    862:                case UHF_PORT_POWER:
                    863:                        /* XXX todo */
                    864:                        break;
                    865:                case UHF_PORT_CONNECTION:
                    866:                case UHF_PORT_OVER_CURRENT:
                    867:                case UHF_PORT_LOW_SPEED:
                    868:                case UHF_C_PORT_SUSPEND:
                    869:                default:
1.14      skrll     870:                        return -1;
1.1       bouyer    871:                }
                    872:                break;
                    873:        case C(UR_GET_BUS_STATE, UT_READ_CLASS_OTHER):
1.14      skrll     874:                return -1;
1.1       bouyer    875:        case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
                    876:                if (len == 0)
                    877:                        break;
                    878:                if ((value & 0xff) != 0) {
1.14      skrll     879:                        return -1;
1.1       bouyer    880:                }
1.14      skrll     881:                totlen = buflen;
1.1       bouyer    882:                break;
                    883:        case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
                    884:                if (len != 4) {
1.14      skrll     885:                        return -1;
1.1       bouyer    886:                }
                    887:                memset(buf, 0, len);
                    888:                totlen = len;
                    889:                break;
                    890:        case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
                    891:                if (index != 1) {
1.14      skrll     892:                        return -1;
1.1       bouyer    893:                }
                    894:                if (len != 4) {
1.14      skrll     895:                        return -1;
1.1       bouyer    896:                }
                    897:                status = change = 0;
                    898:                if (sc->sc_connected)
                    899:                        status |= UPS_CURRENT_CONNECT_STATUS;
                    900:                if (sc->sc_connected_changed) {
                    901:                        change |= UPS_C_CONNECT_STATUS;
                    902:                        sc->sc_connected_changed = 0;
                    903:                }
                    904:                if (sc->sc_port_enabled)
                    905:                        status |= UPS_PORT_ENABLED;
                    906:                if (sc->sc_port_enabled_changed) {
                    907:                        change |= UPS_C_PORT_ENABLED;
                    908:                        sc->sc_port_enabled_changed = 0;
                    909:                }
                    910:                if (sc->sc_port_suspended)
                    911:                        status |= UPS_SUSPEND;
                    912:                if (sc->sc_high_speed)
                    913:                        status |= UPS_HIGH_SPEED;
                    914:                status |= UPS_PORT_POWER; /* XXX */
                    915:                if (sc->sc_isreset)
                    916:                        change |= UPS_C_PORT_RESET;
                    917:                USETW(ps.wPortStatus, status);
                    918:                USETW(ps.wPortChange, change);
1.14      skrll     919:                totlen = min(len, sizeof(ps));
                    920:                memcpy(buf, &ps, totlen);
1.1       bouyer    921:                break;
                    922:        case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
1.14      skrll     923:                return -1;
1.1       bouyer    924:        case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
                    925:                break;
                    926:        case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
                    927:                if (index != 1) {
1.14      skrll     928:                        return -1;
1.1       bouyer    929:                }
                    930:                switch(value) {
                    931:                case UHF_PORT_ENABLE:
                    932:                        sc->sc_port_enabled = 1;
                    933:                        break;
                    934:                case UHF_PORT_SUSPEND:
                    935:                        if (sc->sc_port_suspended == 0) {
                    936:                                val = UREAD1(sc, MUSB2_REG_POWER);
                    937:                                val |= MUSB2_MASK_SUSPMODE;
                    938:                                UWRITE1(sc, MUSB2_REG_POWER, val);
                    939:                                /* wait 20 milliseconds */
                    940:                                usb_delay_ms(&sc->sc_bus, 20);
                    941:                                sc->sc_port_suspended = 1;
                    942:                                sc->sc_port_suspended_change = 1;
                    943:                        }
                    944:                        break;
                    945:                case UHF_PORT_RESET:
                    946:                        err = motg_portreset(sc);
1.14      skrll     947:                        if (err != USBD_NORMAL_COMPLETION)
                    948:                                return -1;
                    949:                        return 0;
1.1       bouyer    950:                case UHF_PORT_POWER:
                    951:                        /* XXX todo */
1.14      skrll     952:                        return 0;
1.1       bouyer    953:                case UHF_C_PORT_CONNECTION:
                    954:                case UHF_C_PORT_ENABLE:
                    955:                case UHF_C_PORT_OVER_CURRENT:
                    956:                case UHF_PORT_CONNECTION:
                    957:                case UHF_PORT_OVER_CURRENT:
                    958:                case UHF_PORT_LOW_SPEED:
                    959:                case UHF_C_PORT_SUSPEND:
                    960:                case UHF_C_PORT_RESET:
                    961:                default:
1.14      skrll     962:                        return -1;
1.1       bouyer    963:                }
                    964:                break;
                    965:        default:
1.14      skrll     966:                /* default from usbroothub */
                    967:                return buflen;
1.1       bouyer    968:        }
                    969:
1.14      skrll     970:        return totlen;
1.1       bouyer    971: }
                    972:
                    973: /* Abort a root interrupt request. */
                    974: void
1.14      skrll     975: motg_root_intr_abort(struct usbd_xfer *xfer)
1.1       bouyer    976: {
1.14      skrll     977:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
1.1       bouyer    978:
                    979:        KASSERT(mutex_owned(&sc->sc_lock));
1.14      skrll     980:        KASSERT(xfer->ux_pipe->up_intrxfer == xfer);
1.1       bouyer    981:
                    982:        sc->sc_intr_xfer = NULL;
                    983:
1.14      skrll     984:        xfer->ux_status = USBD_CANCELLED;
1.1       bouyer    985:        usb_transfer_complete(xfer);
                    986: }
                    987:
                    988: usbd_status
1.14      skrll     989: motg_root_intr_transfer(struct usbd_xfer *xfer)
1.1       bouyer    990: {
1.14      skrll     991:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
1.1       bouyer    992:        usbd_status err;
                    993:
                    994:        /* Insert last in queue. */
                    995:        mutex_enter(&sc->sc_lock);
                    996:        err = usb_insert_transfer(xfer);
                    997:        mutex_exit(&sc->sc_lock);
                    998:        if (err)
1.14      skrll     999:                return err;
1.1       bouyer   1000:
                   1001:        /*
                   1002:         * Pipe isn't running (otherwise err would be USBD_INPROG),
                   1003:         * start first
                   1004:         */
1.14      skrll    1005:        return motg_root_intr_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1.1       bouyer   1006: }
                   1007:
                   1008: /* Start a transfer on the root interrupt pipe */
                   1009: usbd_status
1.14      skrll    1010: motg_root_intr_start(struct usbd_xfer *xfer)
1.1       bouyer   1011: {
1.14      skrll    1012:        struct usbd_pipe *pipe = xfer->ux_pipe;
                   1013:        struct motg_softc *sc = MOTG_PIPE2SC(pipe);
                   1014:
                   1015:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
1.1       bouyer   1016:
1.18      pgoyette 1017:        DPRINTFN(MD_ROOT, "xfer=%#jx len=%jd flags=%jd", (uintptr_t)xfer,
                   1018:            xfer->ux_length, xfer->ux_flags, 0);
1.1       bouyer   1019:
                   1020:        if (sc->sc_dying)
1.14      skrll    1021:                return USBD_IOERROR;
1.1       bouyer   1022:
                   1023:        sc->sc_intr_xfer = xfer;
1.14      skrll    1024:        return USBD_IN_PROGRESS;
1.1       bouyer   1025: }
                   1026:
                   1027: /* Close the root interrupt pipe. */
                   1028: void
1.14      skrll    1029: motg_root_intr_close(struct usbd_pipe *pipe)
1.1       bouyer   1030: {
1.14      skrll    1031:        struct motg_softc *sc = MOTG_PIPE2SC(pipe);
                   1032:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
1.1       bouyer   1033:
                   1034:        KASSERT(mutex_owned(&sc->sc_lock));
                   1035:
                   1036:        sc->sc_intr_xfer = NULL;
                   1037: }
                   1038:
                   1039: void
1.14      skrll    1040: motg_root_intr_done(struct usbd_xfer *xfer)
1.1       bouyer   1041: {
                   1042: }
                   1043:
                   1044: void
1.14      skrll    1045: motg_noop(struct usbd_pipe *pipe)
1.1       bouyer   1046: {
                   1047: }
                   1048:
                   1049: static usbd_status
                   1050: motg_portreset(struct motg_softc *sc)
                   1051: {
                   1052:        uint32_t val;
1.14      skrll    1053:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
1.1       bouyer   1054:
                   1055:        val = UREAD1(sc, MUSB2_REG_POWER);
                   1056:        val |= MUSB2_MASK_RESET;
                   1057:        UWRITE1(sc, MUSB2_REG_POWER, val);
                   1058:        /* Wait for 20 msec */
                   1059:        usb_delay_ms(&sc->sc_bus, 20);
                   1060:
                   1061:        val = UREAD1(sc, MUSB2_REG_POWER);
                   1062:        val &= ~MUSB2_MASK_RESET;
                   1063:        UWRITE1(sc, MUSB2_REG_POWER, val);
                   1064:
                   1065:        /* determine line speed */
                   1066:        val = UREAD1(sc, MUSB2_REG_POWER);
                   1067:        if (val & MUSB2_MASK_HSMODE)
                   1068:                sc->sc_high_speed = 1;
                   1069:        else
                   1070:                sc->sc_high_speed = 0;
1.18      pgoyette 1071:        DPRINTFN(MD_ROOT | MD_CTRL, "speed %jd", sc->sc_high_speed, 0, 0, 0);
1.1       bouyer   1072:
                   1073:        sc->sc_isreset = 1;
                   1074:        sc->sc_port_enabled = 1;
1.14      skrll    1075:        return USBD_NORMAL_COMPLETION;
1.1       bouyer   1076: }
                   1077:
                   1078: /*
                   1079:  * This routine is executed when an interrupt on the root hub is detected
                   1080:  */
                   1081: static void
                   1082: motg_hub_change(struct motg_softc *sc)
                   1083: {
1.14      skrll    1084:        struct usbd_xfer *xfer = sc->sc_intr_xfer;
                   1085:        struct usbd_pipe *pipe;
1.1       bouyer   1086:        u_char *p;
                   1087:
1.14      skrll    1088:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
1.1       bouyer   1089:
                   1090:        if (xfer == NULL)
                   1091:                return; /* the interrupt pipe is not open */
                   1092:
1.14      skrll    1093:        pipe = xfer->ux_pipe;
                   1094:        if (pipe->up_dev == NULL || pipe->up_dev->ud_bus == NULL)
1.1       bouyer   1095:                return; /* device has detached */
                   1096:
1.14      skrll    1097:        p = xfer->ux_buf;
1.1       bouyer   1098:        p[0] = 1<<1;
1.14      skrll    1099:        xfer->ux_actlen = 1;
                   1100:        xfer->ux_status = USBD_NORMAL_COMPLETION;
1.1       bouyer   1101:        usb_transfer_complete(xfer);
                   1102: }
                   1103:
                   1104: static uint8_t
1.14      skrll    1105: motg_speed(uint8_t speed)
1.1       bouyer   1106: {
                   1107:        switch(speed) {
                   1108:        case USB_SPEED_LOW:
                   1109:                return MUSB2_MASK_TI_SPEED_LO;
                   1110:        case USB_SPEED_FULL:
                   1111:                return MUSB2_MASK_TI_SPEED_FS;
                   1112:        case USB_SPEED_HIGH:
                   1113:                return MUSB2_MASK_TI_SPEED_HS;
                   1114:        default:
                   1115:                panic("motg: unknown speed %d", speed);
                   1116:                /* NOTREACHED */
                   1117:        }
                   1118: }
                   1119:
                   1120: static uint8_t
1.14      skrll    1121: motg_type(uint8_t type)
1.1       bouyer   1122: {
                   1123:        switch(type) {
                   1124:        case UE_CONTROL:
                   1125:                return MUSB2_MASK_TI_PROTO_CTRL;
                   1126:        case UE_ISOCHRONOUS:
                   1127:                return MUSB2_MASK_TI_PROTO_ISOC;
                   1128:        case UE_BULK:
                   1129:                return MUSB2_MASK_TI_PROTO_BULK;
                   1130:        case UE_INTERRUPT:
                   1131:                return MUSB2_MASK_TI_PROTO_INTR;
                   1132:        default:
                   1133:                panic("motg: unknown type %d", type);
                   1134:                /* NOTREACHED */
                   1135:        }
                   1136: }
                   1137:
                   1138: static void
1.14      skrll    1139: motg_setup_endpoint_tx(struct usbd_xfer *xfer)
1.1       bouyer   1140: {
1.14      skrll    1141:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
                   1142:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe);
                   1143:        struct usbd_device *dev = otgpipe->pipe.up_dev;
1.1       bouyer   1144:        int epnumber = otgpipe->hw_ep->ep_number;
                   1145:
1.14      skrll    1146:        UWRITE1(sc, MUSB2_REG_TXFADDR(epnumber), dev->ud_addr);
                   1147:        if (dev->ud_myhsport) {
1.1       bouyer   1148:                UWRITE1(sc, MUSB2_REG_TXHADDR(epnumber),
1.14      skrll    1149:                    dev->ud_myhsport->up_parent->ud_addr);
1.1       bouyer   1150:                UWRITE1(sc, MUSB2_REG_TXHUBPORT(epnumber),
1.14      skrll    1151:                    dev->ud_myhsport->up_portno);
1.1       bouyer   1152:        } else {
                   1153:                UWRITE1(sc, MUSB2_REG_TXHADDR(epnumber), 0);
                   1154:                UWRITE1(sc, MUSB2_REG_TXHUBPORT(epnumber), 0);
                   1155:        }
                   1156:        UWRITE1(sc, MUSB2_REG_TXTI,
1.14      skrll    1157:            motg_speed(dev->ud_speed) |
                   1158:            UE_GET_ADDR(xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress) |
                   1159:            motg_type(UE_GET_XFERTYPE(xfer->ux_pipe->up_endpoint->ue_edesc->bmAttributes))
1.1       bouyer   1160:            );
                   1161:        if (epnumber == 0) {
                   1162:                if (sc->sc_high_speed) {
                   1163:                        UWRITE1(sc, MUSB2_REG_TXNAKLIMIT,
                   1164:                            NAK_TO_CTRL_HIGH);
                   1165:                } else {
                   1166:                        UWRITE1(sc, MUSB2_REG_TXNAKLIMIT, NAK_TO_CTRL);
                   1167:                }
                   1168:        } else {
1.14      skrll    1169:                if ((xfer->ux_pipe->up_endpoint->ue_edesc->bmAttributes & UE_XFERTYPE)
1.1       bouyer   1170:                    == UE_BULK) {
                   1171:                        if (sc->sc_high_speed) {
                   1172:                                UWRITE1(sc, MUSB2_REG_TXNAKLIMIT,
                   1173:                                    NAK_TO_BULK_HIGH);
                   1174:                        } else {
                   1175:                                UWRITE1(sc, MUSB2_REG_TXNAKLIMIT, NAK_TO_BULK);
                   1176:                        }
                   1177:                } else {
                   1178:                        if (sc->sc_high_speed) {
                   1179:                                UWRITE1(sc, MUSB2_REG_TXNAKLIMIT, POLL_TO_HIGH);
                   1180:                        } else {
                   1181:                                UWRITE1(sc, MUSB2_REG_TXNAKLIMIT, POLL_TO);
                   1182:                        }
                   1183:                }
                   1184:        }
                   1185: }
                   1186:
                   1187: static void
1.14      skrll    1188: motg_setup_endpoint_rx(struct usbd_xfer *xfer)
1.1       bouyer   1189: {
1.14      skrll    1190:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
                   1191:        struct usbd_device *dev = xfer->ux_pipe->up_dev;
                   1192:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe);
1.1       bouyer   1193:        int epnumber = otgpipe->hw_ep->ep_number;
                   1194:
1.14      skrll    1195:        UWRITE1(sc, MUSB2_REG_RXFADDR(epnumber), dev->ud_addr);
                   1196:        if (dev->ud_myhsport) {
1.1       bouyer   1197:                UWRITE1(sc, MUSB2_REG_RXHADDR(epnumber),
1.14      skrll    1198:                    dev->ud_myhsport->up_parent->ud_addr);
1.1       bouyer   1199:                UWRITE1(sc, MUSB2_REG_RXHUBPORT(epnumber),
1.14      skrll    1200:                    dev->ud_myhsport->up_portno);
1.1       bouyer   1201:        } else {
                   1202:                UWRITE1(sc, MUSB2_REG_RXHADDR(epnumber), 0);
                   1203:                UWRITE1(sc, MUSB2_REG_RXHUBPORT(epnumber), 0);
                   1204:        }
                   1205:        UWRITE1(sc, MUSB2_REG_RXTI,
1.14      skrll    1206:            motg_speed(dev->ud_speed) |
                   1207:            UE_GET_ADDR(xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress) |
                   1208:            motg_type(UE_GET_XFERTYPE(xfer->ux_pipe->up_endpoint->ue_edesc->bmAttributes))
1.1       bouyer   1209:            );
                   1210:        if (epnumber == 0) {
                   1211:                if (sc->sc_high_speed) {
1.17      jakllsch 1212:                        UWRITE1(sc, MUSB2_REG_RXNAKLIMIT,
1.1       bouyer   1213:                            NAK_TO_CTRL_HIGH);
                   1214:                } else {
1.17      jakllsch 1215:                        UWRITE1(sc, MUSB2_REG_RXNAKLIMIT, NAK_TO_CTRL);
1.1       bouyer   1216:                }
                   1217:        } else {
1.14      skrll    1218:                if ((xfer->ux_pipe->up_endpoint->ue_edesc->bmAttributes & UE_XFERTYPE)
1.1       bouyer   1219:                    == UE_BULK) {
                   1220:                        if (sc->sc_high_speed) {
                   1221:                                UWRITE1(sc, MUSB2_REG_RXNAKLIMIT,
                   1222:                                    NAK_TO_BULK_HIGH);
                   1223:                        } else {
                   1224:                                UWRITE1(sc, MUSB2_REG_RXNAKLIMIT, NAK_TO_BULK);
                   1225:                        }
                   1226:                } else {
                   1227:                        if (sc->sc_high_speed) {
                   1228:                                UWRITE1(sc, MUSB2_REG_RXNAKLIMIT, POLL_TO_HIGH);
                   1229:                        } else {
                   1230:                                UWRITE1(sc, MUSB2_REG_RXNAKLIMIT, POLL_TO);
                   1231:                        }
                   1232:                }
                   1233:        }
                   1234: }
                   1235:
                   1236: static usbd_status
1.14      skrll    1237: motg_device_ctrl_transfer(struct usbd_xfer *xfer)
1.1       bouyer   1238: {
1.14      skrll    1239:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
1.1       bouyer   1240:        usbd_status err;
                   1241:
                   1242:        /* Insert last in queue. */
                   1243:        mutex_enter(&sc->sc_lock);
                   1244:        err = usb_insert_transfer(xfer);
1.14      skrll    1245:        xfer->ux_status = USBD_NOT_STARTED;
1.1       bouyer   1246:        mutex_exit(&sc->sc_lock);
                   1247:        if (err)
1.14      skrll    1248:                return err;
1.1       bouyer   1249:
                   1250:        /*
                   1251:         * Pipe isn't running (otherwise err would be USBD_INPROG),
                   1252:         * so start it first.
                   1253:         */
1.14      skrll    1254:        return motg_device_ctrl_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1.1       bouyer   1255: }
                   1256:
                   1257: static usbd_status
1.14      skrll    1258: motg_device_ctrl_start(struct usbd_xfer *xfer)
1.1       bouyer   1259: {
1.14      skrll    1260:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
1.1       bouyer   1261:        usbd_status err;
                   1262:        mutex_enter(&sc->sc_lock);
                   1263:        err = motg_device_ctrl_start1(sc);
                   1264:        mutex_exit(&sc->sc_lock);
                   1265:        if (err != USBD_IN_PROGRESS)
                   1266:                return err;
                   1267:        return USBD_IN_PROGRESS;
                   1268: }
                   1269:
                   1270: static usbd_status
                   1271: motg_device_ctrl_start1(struct motg_softc *sc)
                   1272: {
                   1273:        struct motg_hw_ep *ep = &sc->sc_in_ep[0];
1.14      skrll    1274:        struct usbd_xfer *xfer = NULL;
1.1       bouyer   1275:        struct motg_pipe *otgpipe;
                   1276:        usbd_status err = 0;
                   1277:
1.14      skrll    1278:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1279:
1.1       bouyer   1280:        KASSERT(mutex_owned(&sc->sc_lock));
                   1281:        if (sc->sc_dying)
1.14      skrll    1282:                return USBD_IOERROR;
1.1       bouyer   1283:
                   1284:        if (!sc->sc_connected)
1.14      skrll    1285:                return USBD_IOERROR;
1.1       bouyer   1286:
                   1287:        if (ep->xfer != NULL) {
                   1288:                err = USBD_IN_PROGRESS;
                   1289:                goto end;
                   1290:        }
                   1291:        /* locate the first pipe with work to do */
                   1292:        SIMPLEQ_FOREACH(otgpipe, &ep->ep_pipes, ep_pipe_list) {
1.14      skrll    1293:                xfer = SIMPLEQ_FIRST(&otgpipe->pipe.up_queue);
1.18      pgoyette 1294:                DPRINTFN(MD_CTRL, "pipe %#jx xfer %#jx status %jd",
                   1295:                    (uintptr_t)otgpipe, (uintptr_t)xfer,
                   1296:                    (xfer != NULL) ? xfer->ux_status : 0, 0);
1.7       skrll    1297:
1.1       bouyer   1298:                if (xfer != NULL) {
                   1299:                        /* move this pipe to the end of the list */
                   1300:                        SIMPLEQ_REMOVE(&ep->ep_pipes, otgpipe,
                   1301:                            motg_pipe, ep_pipe_list);
                   1302:                        SIMPLEQ_INSERT_TAIL(&ep->ep_pipes,
                   1303:                            otgpipe, ep_pipe_list);
                   1304:                        break;
                   1305:                }
                   1306:        }
                   1307:        if (xfer == NULL) {
                   1308:                err = USBD_NOT_STARTED;
                   1309:                goto end;
                   1310:        }
1.14      skrll    1311:        xfer->ux_status = USBD_IN_PROGRESS;
                   1312:        KASSERT(otgpipe == MOTG_PIPE2MPIPE(xfer->ux_pipe));
1.1       bouyer   1313:        KASSERT(otgpipe->hw_ep == ep);
1.14      skrll    1314:        KASSERT(xfer->ux_rqflags & URQ_REQUEST);
                   1315:        // KASSERT(xfer->ux_actlen == 0);
                   1316:        xfer->ux_actlen = 0;
1.1       bouyer   1317:
                   1318:        ep->xfer = xfer;
1.14      skrll    1319:        ep->datalen = xfer->ux_length;
1.1       bouyer   1320:        if (ep->datalen > 0)
1.14      skrll    1321:                ep->data = xfer->ux_buf;
1.1       bouyer   1322:        else
                   1323:                ep->data = NULL;
1.14      skrll    1324:        if ((xfer->ux_flags & USBD_FORCE_SHORT_XFER) &&
1.1       bouyer   1325:            (ep->datalen % 64) == 0)
                   1326:                ep->need_short_xfer = 1;
                   1327:        else
                   1328:                ep->need_short_xfer = 0;
                   1329:        /* now we need send this request */
1.7       skrll    1330:        DPRINTFN(MD_CTRL,
1.18      pgoyette 1331:            "xfer %#jx send data %#jx len %jd short %jd",
                   1332:            (uintptr_t)xfer, (uintptr_t)ep->data, ep->datalen,
                   1333:            ep->need_short_xfer);
1.14      skrll    1334:        DPRINTFN(MD_CTRL,
1.18      pgoyette 1335:            "xfer %#jx ... speed %jd to %jd", (uintptr_t)xfer,
                   1336:            xfer->ux_pipe->up_dev->ud_speed,
                   1337:            xfer->ux_pipe->up_dev->ud_addr, 0);
1.1       bouyer   1338:        KASSERT(ep->phase == IDLE);
                   1339:        ep->phase = SETUP;
                   1340:        /* select endpoint 0 */
                   1341:        UWRITE1(sc, MUSB2_REG_EPINDEX, 0);
                   1342:        /* fifo should be empty at this point */
                   1343:        KASSERT((UREAD1(sc, MUSB2_REG_TXCSRL) & MUSB2_MASK_CSR0L_TXPKTRDY) == 0);
                   1344:        /* send data */
1.14      skrll    1345:        // KASSERT(((vaddr_t)(&xfer->ux_request) & 3) == 0);
                   1346:        KASSERT(sizeof(xfer->ux_request) == 8);
1.1       bouyer   1347:        bus_space_write_multi_1(sc->sc_iot, sc->sc_ioh, MUSB2_REG_EPFIFO(0),
1.14      skrll    1348:            (void *)&xfer->ux_request, sizeof(xfer->ux_request));
1.1       bouyer   1349:
                   1350:        motg_setup_endpoint_tx(xfer);
                   1351:        /* start transaction */
                   1352:        UWRITE1(sc, MUSB2_REG_TXCSRL,
                   1353:            MUSB2_MASK_CSR0L_TXPKTRDY | MUSB2_MASK_CSR0L_SETUPPKT);
                   1354:
                   1355: end:
                   1356:        if (err)
1.14      skrll    1357:                return err;
1.1       bouyer   1358:
1.14      skrll    1359:        return USBD_IN_PROGRESS;
1.1       bouyer   1360: }
                   1361:
                   1362: static void
1.14      skrll    1363: motg_device_ctrl_read(struct usbd_xfer *xfer)
1.1       bouyer   1364: {
1.14      skrll    1365:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
                   1366:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe);
1.1       bouyer   1367:        /* assume endpoint already selected */
                   1368:        motg_setup_endpoint_rx(xfer);
                   1369:        /* start transaction */
                   1370:        UWRITE1(sc, MUSB2_REG_TXCSRL, MUSB2_MASK_CSR0L_REQPKT);
                   1371:        otgpipe->hw_ep->phase = DATA_IN;
                   1372: }
                   1373:
                   1374: static void
                   1375: motg_device_ctrl_intr_rx(struct motg_softc *sc)
                   1376: {
                   1377:        struct motg_hw_ep *ep = &sc->sc_in_ep[0];
1.14      skrll    1378:        struct usbd_xfer *xfer = ep->xfer;
1.1       bouyer   1379:        uint8_t csr;
                   1380:        int datalen, max_datalen;
                   1381:        char *data;
                   1382:        bool got_short;
1.3       bouyer   1383:        usbd_status new_status = USBD_IN_PROGRESS;
1.1       bouyer   1384:
1.14      skrll    1385:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1386:
1.1       bouyer   1387:        KASSERT(mutex_owned(&sc->sc_lock));
                   1388:
1.15      skrll    1389:        KASSERT(ep->phase == DATA_IN || ep->phase == STATUS_IN);
1.14      skrll    1390:        /* select endpoint 0 */
1.1       bouyer   1391:        UWRITE1(sc, MUSB2_REG_EPINDEX, 0);
                   1392:
                   1393:        /* read out FIFO status */
                   1394:        csr = UREAD1(sc, MUSB2_REG_TXCSRL);
1.18      pgoyette 1395:        DPRINTFN(MD_CTRL, "phase %jd csr 0x%jx xfer %#jx status %jd",
                   1396:            ep->phase, csr, (uintptr_t)xfer,
                   1397:            (xfer != NULL) ? xfer->ux_status : 0);
1.1       bouyer   1398:
                   1399:        if (csr & MUSB2_MASK_CSR0L_NAKTIMO) {
                   1400:                csr &= ~MUSB2_MASK_CSR0L_REQPKT;
                   1401:                UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
                   1402:
                   1403:                csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
                   1404:                UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
1.3       bouyer   1405:                new_status = USBD_TIMEOUT; /* XXX */
1.1       bouyer   1406:                goto complete;
                   1407:        }
                   1408:        if (csr & (MUSB2_MASK_CSR0L_RXSTALL | MUSB2_MASK_CSR0L_ERROR)) {
1.3       bouyer   1409:                if (csr & MUSB2_MASK_CSR0L_RXSTALL)
                   1410:                        new_status = USBD_STALLED;
                   1411:                else
                   1412:                        new_status = USBD_IOERROR;
1.1       bouyer   1413:                /* clear status */
                   1414:                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                   1415:                goto complete;
                   1416:        }
                   1417:        if ((csr & MUSB2_MASK_CSR0L_RXPKTRDY) == 0)
                   1418:                return; /* no data yet */
                   1419:
1.14      skrll    1420:        if (xfer == NULL || xfer->ux_status != USBD_IN_PROGRESS)
1.1       bouyer   1421:                goto complete;
                   1422:
                   1423:        if (ep->phase == STATUS_IN) {
1.3       bouyer   1424:                new_status = USBD_NORMAL_COMPLETION;
1.1       bouyer   1425:                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                   1426:                goto complete;
                   1427:        }
                   1428:        datalen = UREAD2(sc, MUSB2_REG_RXCOUNT);
1.18      pgoyette 1429:        DPRINTFN(MD_CTRL, "phase %jd datalen %jd", ep->phase, datalen, 0, 0);
1.14      skrll    1430:        KASSERT(UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize) > 0);
                   1431:        max_datalen = min(UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize),
1.1       bouyer   1432:            ep->datalen);
                   1433:        if (datalen > max_datalen) {
1.3       bouyer   1434:                new_status = USBD_IOERROR;
1.1       bouyer   1435:                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                   1436:                goto complete;
                   1437:        }
                   1438:        got_short = (datalen < max_datalen);
                   1439:        if (datalen > 0) {
                   1440:                KASSERT(ep->phase == DATA_IN);
                   1441:                data = ep->data;
                   1442:                ep->data += datalen;
                   1443:                ep->datalen -= datalen;
1.14      skrll    1444:                xfer->ux_actlen += datalen;
1.1       bouyer   1445:                if (((vaddr_t)data & 0x3) == 0 &&
                   1446:                    (datalen >> 2) > 0) {
1.18      pgoyette 1447:                        DPRINTFN(MD_CTRL, "r4 data %#jx len %jd",
                   1448:                            (uintptr_t)data, datalen, 0, 0);
1.1       bouyer   1449:                        bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh,
                   1450:                            MUSB2_REG_EPFIFO(0), (void *)data, datalen >> 2);
                   1451:                        data += (datalen & ~0x3);
                   1452:                        datalen -= (datalen & ~0x3);
                   1453:                }
1.18      pgoyette 1454:                DPRINTFN(MD_CTRL, "r1 data %#jx len %jd", (uintptr_t)data,
                   1455:                    datalen, 0, 0);
1.1       bouyer   1456:                if (datalen) {
                   1457:                        bus_space_read_multi_1(sc->sc_iot, sc->sc_ioh,
                   1458:                            MUSB2_REG_EPFIFO(0), data, datalen);
                   1459:                }
                   1460:        }
                   1461:        UWRITE1(sc, MUSB2_REG_TXCSRL, csr & ~MUSB2_MASK_CSR0L_RXPKTRDY);
                   1462:        KASSERT(ep->phase == DATA_IN);
                   1463:        if (got_short || (ep->datalen == 0)) {
                   1464:                if (ep->need_short_xfer == 0) {
                   1465:                        ep->phase = STATUS_OUT;
                   1466:                        UWRITE1(sc, MUSB2_REG_TXCSRH,
                   1467:                            UREAD1(sc, MUSB2_REG_TXCSRH) |
                   1468:                            MUSB2_MASK_CSR0H_PING_DIS);
                   1469:                        motg_setup_endpoint_tx(xfer);
                   1470:                        UWRITE1(sc, MUSB2_REG_TXCSRL,
                   1471:                            MUSB2_MASK_CSR0L_STATUSPKT |
                   1472:                            MUSB2_MASK_CSR0L_TXPKTRDY);
                   1473:                        return;
                   1474:                }
                   1475:                ep->need_short_xfer = 0;
                   1476:        }
                   1477:        motg_device_ctrl_read(xfer);
                   1478:        return;
                   1479: complete:
                   1480:        ep->phase = IDLE;
                   1481:        ep->xfer = NULL;
1.14      skrll    1482:        if (xfer && xfer->ux_status == USBD_IN_PROGRESS) {
1.3       bouyer   1483:                KASSERT(new_status != USBD_IN_PROGRESS);
1.14      skrll    1484:                xfer->ux_status = new_status;
1.1       bouyer   1485:                usb_transfer_complete(xfer);
1.3       bouyer   1486:        }
1.1       bouyer   1487:        motg_device_ctrl_start1(sc);
                   1488: }
                   1489:
                   1490: static void
                   1491: motg_device_ctrl_intr_tx(struct motg_softc *sc)
                   1492: {
                   1493:        struct motg_hw_ep *ep = &sc->sc_in_ep[0];
1.14      skrll    1494:        struct usbd_xfer *xfer = ep->xfer;
1.1       bouyer   1495:        uint8_t csr;
                   1496:        int datalen;
                   1497:        char *data;
1.3       bouyer   1498:        usbd_status new_status = USBD_IN_PROGRESS;
1.1       bouyer   1499:
1.14      skrll    1500:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1501:
1.1       bouyer   1502:        KASSERT(mutex_owned(&sc->sc_lock));
                   1503:        if (ep->phase == DATA_IN || ep->phase == STATUS_IN) {
                   1504:                motg_device_ctrl_intr_rx(sc);
                   1505:                return;
                   1506:        }
                   1507:
1.14      skrll    1508:        KASSERT(ep->phase == SETUP || ep->phase == DATA_OUT ||
                   1509:            ep->phase == STATUS_OUT);
                   1510:
                   1511:        /* select endpoint 0 */
1.1       bouyer   1512:        UWRITE1(sc, MUSB2_REG_EPINDEX, 0);
                   1513:
                   1514:        csr = UREAD1(sc, MUSB2_REG_TXCSRL);
1.18      pgoyette 1515:        DPRINTFN(MD_CTRL, "phase %jd csr 0x%jx xfer %#jx status %jd",
                   1516:            ep->phase, csr, (uintptr_t)xfer,
                   1517:            (xfer != NULL) ? xfer->ux_status : 0);
1.1       bouyer   1518:
                   1519:        if (csr & MUSB2_MASK_CSR0L_RXSTALL) {
                   1520:                /* command not accepted */
1.3       bouyer   1521:                new_status = USBD_STALLED;
1.1       bouyer   1522:                /* clear status */
                   1523:                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                   1524:                goto complete;
                   1525:        }
                   1526:        if (csr & MUSB2_MASK_CSR0L_NAKTIMO) {
1.3       bouyer   1527:                new_status = USBD_TIMEOUT; /* XXX */
1.1       bouyer   1528:                /* flush fifo */
                   1529:                while (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY) {
                   1530:                        UWRITE1(sc, MUSB2_REG_TXCSRH,
1.7       skrll    1531:                            UREAD1(sc, MUSB2_REG_TXCSRH) |
1.1       bouyer   1532:                                MUSB2_MASK_CSR0H_FFLUSH);
                   1533:                        csr = UREAD1(sc, MUSB2_REG_TXCSRL);
                   1534:                }
                   1535:                csr &= ~MUSB2_MASK_CSR0L_NAKTIMO;
                   1536:                UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
                   1537:                goto complete;
                   1538:        }
                   1539:        if (csr & MUSB2_MASK_CSR0L_ERROR) {
1.3       bouyer   1540:                new_status = USBD_IOERROR;
1.1       bouyer   1541:                /* clear status */
                   1542:                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                   1543:                goto complete;
                   1544:        }
                   1545:        if (csr & MUSB2_MASK_CSR0L_TXFIFONEMPTY) {
                   1546:                /* data still not sent */
                   1547:                return;
                   1548:        }
                   1549:        if (xfer == NULL)
                   1550:                goto complete;
                   1551:        if (ep->phase == STATUS_OUT) {
                   1552:                /*
                   1553:                 * we have sent status and got no error;
                   1554:                 * declare transfer complete
                   1555:                 */
1.18      pgoyette 1556:                DPRINTFN(MD_CTRL, "xfer %#jx status %jd complete",
                   1557:                    (uintptr_t)xfer, xfer->ux_status, 0, 0);
1.3       bouyer   1558:                new_status = USBD_NORMAL_COMPLETION;
1.1       bouyer   1559:                goto complete;
                   1560:        }
                   1561:        if (ep->datalen == 0) {
                   1562:                if (ep->need_short_xfer) {
                   1563:                        ep->need_short_xfer = 0;
                   1564:                        /* one more data phase */
1.14      skrll    1565:                        if (xfer->ux_request.bmRequestType & UT_READ) {
1.18      pgoyette 1566:                                DPRINTFN(MD_CTRL, "xfer %#jx to DATA_IN",
                   1567:                                    (uintptr_t)xfer, 0, 0, 0);
1.1       bouyer   1568:                                motg_device_ctrl_read(xfer);
                   1569:                                return;
                   1570:                        } /*  else fall back to DATA_OUT */
                   1571:                } else {
1.18      pgoyette 1572:                        DPRINTFN(MD_CTRL, "xfer %#jx to STATUS_IN, csrh 0x%jx",
                   1573:                            (uintptr_t)xfer, UREAD1(sc, MUSB2_REG_TXCSRH),
                   1574:                            0, 0);
1.1       bouyer   1575:                        ep->phase = STATUS_IN;
                   1576:                        UWRITE1(sc, MUSB2_REG_RXCSRH,
                   1577:                            UREAD1(sc, MUSB2_REG_RXCSRH) |
                   1578:                            MUSB2_MASK_CSR0H_PING_DIS);
                   1579:                        motg_setup_endpoint_rx(xfer);
                   1580:                        UWRITE1(sc, MUSB2_REG_TXCSRL,
                   1581:                            MUSB2_MASK_CSR0L_STATUSPKT |
                   1582:                            MUSB2_MASK_CSR0L_REQPKT);
                   1583:                        return;
                   1584:                }
                   1585:        }
1.14      skrll    1586:        if (xfer->ux_request.bmRequestType & UT_READ) {
1.1       bouyer   1587:                motg_device_ctrl_read(xfer);
                   1588:                return;
                   1589:        }
                   1590:        /* setup a dataout phase */
                   1591:        datalen = min(ep->datalen,
1.14      skrll    1592:            UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize));
1.1       bouyer   1593:        ep->phase = DATA_OUT;
1.18      pgoyette 1594:        DPRINTFN(MD_CTRL, "xfer %#jx to DATA_OUT, csrh 0x%jx", (uintptr_t)xfer,
1.14      skrll    1595:            UREAD1(sc, MUSB2_REG_TXCSRH), 0, 0);
1.1       bouyer   1596:        if (datalen) {
                   1597:                data = ep->data;
                   1598:                ep->data += datalen;
                   1599:                ep->datalen -= datalen;
1.14      skrll    1600:                xfer->ux_actlen += datalen;
1.1       bouyer   1601:                if (((vaddr_t)data & 0x3) == 0 &&
                   1602:                    (datalen >> 2) > 0) {
                   1603:                        bus_space_write_multi_4(sc->sc_iot, sc->sc_ioh,
                   1604:                            MUSB2_REG_EPFIFO(0), (void *)data, datalen >> 2);
                   1605:                        data += (datalen & ~0x3);
                   1606:                        datalen -= (datalen & ~0x3);
                   1607:                }
                   1608:                if (datalen) {
                   1609:                        bus_space_write_multi_1(sc->sc_iot, sc->sc_ioh,
                   1610:                            MUSB2_REG_EPFIFO(0), data, datalen);
                   1611:                }
                   1612:        }
                   1613:        /* send data */
                   1614:        motg_setup_endpoint_tx(xfer);
                   1615:        UWRITE1(sc, MUSB2_REG_TXCSRL, MUSB2_MASK_CSR0L_TXPKTRDY);
                   1616:        return;
                   1617:
                   1618: complete:
                   1619:        ep->phase = IDLE;
                   1620:        ep->xfer = NULL;
1.14      skrll    1621:        if (xfer && xfer->ux_status == USBD_IN_PROGRESS) {
1.3       bouyer   1622:                KASSERT(new_status != USBD_IN_PROGRESS);
1.14      skrll    1623:                xfer->ux_status = new_status;
1.1       bouyer   1624:                usb_transfer_complete(xfer);
1.3       bouyer   1625:        }
1.1       bouyer   1626:        motg_device_ctrl_start1(sc);
                   1627: }
                   1628:
                   1629: /* Abort a device control request. */
                   1630: void
1.14      skrll    1631: motg_device_ctrl_abort(struct usbd_xfer *xfer)
1.1       bouyer   1632: {
1.14      skrll    1633:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1634:
1.3       bouyer   1635:        motg_device_xfer_abort(xfer);
1.1       bouyer   1636: }
                   1637:
                   1638: /* Close a device control pipe */
                   1639: void
1.14      skrll    1640: motg_device_ctrl_close(struct usbd_pipe *pipe)
1.1       bouyer   1641: {
1.14      skrll    1642:        struct motg_softc *sc __diagused = MOTG_PIPE2SC(pipe);
                   1643:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(pipe);
1.1       bouyer   1644:        struct motg_pipe *otgpipeiter;
                   1645:
1.14      skrll    1646:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1647:
1.1       bouyer   1648:        KASSERT(mutex_owned(&sc->sc_lock));
                   1649:        KASSERT(otgpipe->hw_ep->xfer == NULL ||
1.14      skrll    1650:            otgpipe->hw_ep->xfer->ux_pipe != pipe);
1.1       bouyer   1651:
                   1652:        SIMPLEQ_FOREACH(otgpipeiter, &otgpipe->hw_ep->ep_pipes, ep_pipe_list) {
                   1653:                if (otgpipeiter == otgpipe) {
                   1654:                        /* remove from list */
                   1655:                        SIMPLEQ_REMOVE(&otgpipe->hw_ep->ep_pipes, otgpipe,
                   1656:                            motg_pipe, ep_pipe_list);
                   1657:                        otgpipe->hw_ep->refcount--;
                   1658:                        /* we're done */
                   1659:                        return;
                   1660:                }
                   1661:        }
                   1662:        panic("motg_device_ctrl_close: not found");
                   1663: }
                   1664:
                   1665: void
1.14      skrll    1666: motg_device_ctrl_done(struct usbd_xfer *xfer)
1.1       bouyer   1667: {
1.14      skrll    1668:        struct motg_pipe *otgpipe __diagused = MOTG_PIPE2MPIPE(xfer->ux_pipe);
                   1669:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1670:
1.1       bouyer   1671:        KASSERT(otgpipe->hw_ep->xfer != xfer);
                   1672: }
                   1673:
                   1674: static usbd_status
1.14      skrll    1675: motg_device_data_transfer(struct usbd_xfer *xfer)
1.1       bouyer   1676: {
1.14      skrll    1677:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
1.1       bouyer   1678:        usbd_status err;
                   1679:
1.14      skrll    1680:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1681:
1.1       bouyer   1682:        /* Insert last in queue. */
                   1683:        mutex_enter(&sc->sc_lock);
1.18      pgoyette 1684:        DPRINTF("xfer %#jx status %jd", (uintptr_t)xfer, xfer->ux_status, 0, 0);
1.1       bouyer   1685:        err = usb_insert_transfer(xfer);
1.14      skrll    1686:        xfer->ux_status = USBD_NOT_STARTED;
1.1       bouyer   1687:        mutex_exit(&sc->sc_lock);
                   1688:        if (err)
1.14      skrll    1689:                return err;
1.1       bouyer   1690:
                   1691:        /*
                   1692:         * Pipe isn't running (otherwise err would be USBD_INPROG),
                   1693:         * so start it first.
                   1694:         */
1.14      skrll    1695:        return motg_device_data_start(SIMPLEQ_FIRST(&xfer->ux_pipe->up_queue));
1.1       bouyer   1696: }
                   1697:
                   1698: static usbd_status
1.14      skrll    1699: motg_device_data_start(struct usbd_xfer *xfer)
1.1       bouyer   1700: {
1.14      skrll    1701:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
                   1702:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe);
1.1       bouyer   1703:        usbd_status err;
1.14      skrll    1704:
                   1705:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1706:
1.1       bouyer   1707:        mutex_enter(&sc->sc_lock);
1.18      pgoyette 1708:        DPRINTF("xfer %#jx status %jd", (uintptr_t)xfer, xfer->ux_status, 0, 0);
1.1       bouyer   1709:        err = motg_device_data_start1(sc, otgpipe->hw_ep);
                   1710:        mutex_exit(&sc->sc_lock);
                   1711:        if (err != USBD_IN_PROGRESS)
                   1712:                return err;
                   1713:        return USBD_IN_PROGRESS;
                   1714: }
                   1715:
                   1716: static usbd_status
                   1717: motg_device_data_start1(struct motg_softc *sc, struct motg_hw_ep *ep)
                   1718: {
1.14      skrll    1719:        struct usbd_xfer *xfer = NULL;
1.1       bouyer   1720:        struct motg_pipe *otgpipe;
                   1721:        usbd_status err = 0;
1.8       skrll    1722:        uint32_t val __diagused;
1.1       bouyer   1723:
1.14      skrll    1724:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1725:
1.1       bouyer   1726:        KASSERT(mutex_owned(&sc->sc_lock));
                   1727:        if (sc->sc_dying)
1.14      skrll    1728:                return USBD_IOERROR;
1.1       bouyer   1729:
                   1730:        if (!sc->sc_connected)
1.14      skrll    1731:                return USBD_IOERROR;
1.1       bouyer   1732:
                   1733:        if (ep->xfer != NULL) {
                   1734:                err = USBD_IN_PROGRESS;
                   1735:                goto end;
                   1736:        }
                   1737:        /* locate the first pipe with work to do */
                   1738:        SIMPLEQ_FOREACH(otgpipe, &ep->ep_pipes, ep_pipe_list) {
1.14      skrll    1739:                xfer = SIMPLEQ_FIRST(&otgpipe->pipe.up_queue);
1.18      pgoyette 1740:                DPRINTFN(MD_BULK, "pipe %#jx xfer %#jx status %jd",
                   1741:                    (uintptr_t)otgpipe, (uintptr_t)xfer,
1.14      skrll    1742:                    (xfer != NULL) ? xfer->ux_status : 0, 0);
1.1       bouyer   1743:                if (xfer != NULL) {
                   1744:                        /* move this pipe to the end of the list */
                   1745:                        SIMPLEQ_REMOVE(&ep->ep_pipes, otgpipe,
                   1746:                            motg_pipe, ep_pipe_list);
                   1747:                        SIMPLEQ_INSERT_TAIL(&ep->ep_pipes,
                   1748:                            otgpipe, ep_pipe_list);
                   1749:                        break;
                   1750:                }
                   1751:        }
                   1752:        if (xfer == NULL) {
                   1753:                err = USBD_NOT_STARTED;
                   1754:                goto end;
                   1755:        }
1.14      skrll    1756:        xfer->ux_status = USBD_IN_PROGRESS;
                   1757:        KASSERT(otgpipe == MOTG_PIPE2MPIPE(xfer->ux_pipe));
1.1       bouyer   1758:        KASSERT(otgpipe->hw_ep == ep);
1.14      skrll    1759:        KASSERT(!(xfer->ux_rqflags & URQ_REQUEST));
                   1760:        // KASSERT(xfer->ux_actlen == 0);
                   1761:        xfer->ux_actlen = 0;
1.1       bouyer   1762:
                   1763:        ep->xfer = xfer;
1.14      skrll    1764:        ep->datalen = xfer->ux_length;
1.1       bouyer   1765:        KASSERT(ep->datalen > 0);
1.14      skrll    1766:        ep->data = xfer->ux_buf;
                   1767:        if ((xfer->ux_flags & USBD_FORCE_SHORT_XFER) &&
1.1       bouyer   1768:            (ep->datalen % 64) == 0)
                   1769:                ep->need_short_xfer = 1;
                   1770:        else
                   1771:                ep->need_short_xfer = 0;
                   1772:        /* now we need send this request */
1.7       skrll    1773:        DPRINTFN(MD_BULK,
1.14      skrll    1774:            UE_GET_DIR(xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress) == UE_DIR_IN ?
1.18      pgoyette 1775:            "xfer %#jx in  data %#jx len %jd short %jd" :
                   1776:            "xfer %#jx out data %#jx len %jd short %jd",
                   1777:            (uintptr_t)xfer, (uintptr_t)ep->data, ep->datalen,
                   1778:            ep->need_short_xfer);
                   1779:        DPRINTFN(MD_BULK, "... speed %jd to %jd",
                   1780:            xfer->ux_pipe->up_dev->ud_speed,
1.14      skrll    1781:            xfer->ux_pipe->up_dev->ud_addr, 0, 0);
1.1       bouyer   1782:        KASSERT(ep->phase == IDLE);
                   1783:        /* select endpoint */
                   1784:        UWRITE1(sc, MUSB2_REG_EPINDEX, ep->ep_number);
1.14      skrll    1785:        if (UE_GET_DIR(xfer->ux_pipe->up_endpoint->ue_edesc->bEndpointAddress)
1.1       bouyer   1786:            == UE_DIR_IN) {
                   1787:                val = UREAD1(sc, MUSB2_REG_RXCSRL);
                   1788:                KASSERT((val & MUSB2_MASK_CSRL_RXPKTRDY) == 0);
                   1789:                motg_device_data_read(xfer);
                   1790:        } else {
                   1791:                ep->phase = DATA_OUT;
                   1792:                val = UREAD1(sc, MUSB2_REG_TXCSRL);
                   1793:                KASSERT((val & MUSB2_MASK_CSRL_TXPKTRDY) == 0);
                   1794:                motg_device_data_write(xfer);
                   1795:        }
                   1796: end:
                   1797:        if (err)
1.14      skrll    1798:                return err;
1.1       bouyer   1799:
1.14      skrll    1800:        return USBD_IN_PROGRESS;
1.1       bouyer   1801: }
                   1802:
                   1803: static void
1.14      skrll    1804: motg_device_data_read(struct usbd_xfer *xfer)
1.1       bouyer   1805: {
1.14      skrll    1806:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
                   1807:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe);
1.1       bouyer   1808:        uint32_t val;
                   1809:
1.14      skrll    1810:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1811:
1.1       bouyer   1812:        KASSERT(mutex_owned(&sc->sc_lock));
                   1813:        /* assume endpoint already selected */
                   1814:        motg_setup_endpoint_rx(xfer);
                   1815:        /* Max packet size */
                   1816:        UWRITE2(sc, MUSB2_REG_RXMAXP,
1.14      skrll    1817:            UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize));
1.1       bouyer   1818:        /* Data Toggle */
                   1819:        val = UREAD1(sc, MUSB2_REG_RXCSRH);
                   1820:        val |= MUSB2_MASK_CSRH_RXDT_WREN;
                   1821:        if (otgpipe->nexttoggle)
                   1822:                val |= MUSB2_MASK_CSRH_RXDT_VAL;
                   1823:        else
                   1824:                val &= ~MUSB2_MASK_CSRH_RXDT_VAL;
                   1825:        UWRITE1(sc, MUSB2_REG_RXCSRH, val);
                   1826:
1.18      pgoyette 1827:        DPRINTFN(MD_BULK, "%#jx to DATA_IN on ep %jd, csrh 0x%jx",
                   1828:            (uintptr_t)xfer, otgpipe->hw_ep->ep_number,
                   1829:            UREAD1(sc, MUSB2_REG_RXCSRH), 0);
1.1       bouyer   1830:        /* start transaction */
                   1831:        UWRITE1(sc, MUSB2_REG_RXCSRL, MUSB2_MASK_CSRL_RXREQPKT);
                   1832:        otgpipe->hw_ep->phase = DATA_IN;
                   1833: }
                   1834:
                   1835: static void
1.14      skrll    1836: motg_device_data_write(struct usbd_xfer *xfer)
1.1       bouyer   1837: {
1.14      skrll    1838:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
                   1839:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe);
1.1       bouyer   1840:        struct motg_hw_ep *ep = otgpipe->hw_ep;
                   1841:        int datalen;
                   1842:        char *data;
                   1843:        uint32_t val;
                   1844:
1.14      skrll    1845:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1846:
1.1       bouyer   1847:        KASSERT(xfer!=NULL);
                   1848:        KASSERT(mutex_owned(&sc->sc_lock));
                   1849:
                   1850:        datalen = min(ep->datalen,
1.14      skrll    1851:            UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize));
1.1       bouyer   1852:        ep->phase = DATA_OUT;
1.18      pgoyette 1853:        DPRINTFN(MD_BULK, "%#jx to DATA_OUT on ep %jd, len %jd csrh 0x%jx",
                   1854:            (uintptr_t)xfer, ep->ep_number, datalen,
                   1855:            UREAD1(sc, MUSB2_REG_TXCSRH));
1.1       bouyer   1856:
                   1857:        /* assume endpoint already selected */
                   1858:        /* write data to fifo */
                   1859:        data = ep->data;
                   1860:        ep->data += datalen;
                   1861:        ep->datalen -= datalen;
1.14      skrll    1862:        xfer->ux_actlen += datalen;
1.1       bouyer   1863:        if (((vaddr_t)data & 0x3) == 0 &&
                   1864:            (datalen >> 2) > 0) {
                   1865:                bus_space_write_multi_4(sc->sc_iot, sc->sc_ioh,
                   1866:                    MUSB2_REG_EPFIFO(ep->ep_number),
                   1867:                    (void *)data, datalen >> 2);
                   1868:                data += (datalen & ~0x3);
                   1869:                datalen -= (datalen & ~0x3);
                   1870:        }
                   1871:        if (datalen) {
                   1872:                bus_space_write_multi_1(sc->sc_iot, sc->sc_ioh,
                   1873:                    MUSB2_REG_EPFIFO(ep->ep_number), data, datalen);
                   1874:        }
                   1875:
                   1876:        motg_setup_endpoint_tx(xfer);
                   1877:        /* Max packet size */
                   1878:        UWRITE2(sc, MUSB2_REG_TXMAXP,
1.14      skrll    1879:            UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize));
1.1       bouyer   1880:        /* Data Toggle */
                   1881:        val = UREAD1(sc, MUSB2_REG_TXCSRH);
                   1882:        val |= MUSB2_MASK_CSRH_TXDT_WREN;
                   1883:        if (otgpipe->nexttoggle)
                   1884:                val |= MUSB2_MASK_CSRH_TXDT_VAL;
                   1885:        else
                   1886:                val &= ~MUSB2_MASK_CSRH_TXDT_VAL;
                   1887:        UWRITE1(sc, MUSB2_REG_TXCSRH, val);
                   1888:
                   1889:        /* start transaction */
                   1890:        UWRITE1(sc, MUSB2_REG_TXCSRL, MUSB2_MASK_CSRL_TXPKTRDY);
                   1891: }
                   1892:
                   1893: static void
                   1894: motg_device_intr_rx(struct motg_softc *sc, int epnumber)
                   1895: {
                   1896:        struct motg_hw_ep *ep = &sc->sc_in_ep[epnumber];
1.14      skrll    1897:        struct usbd_xfer *xfer = ep->xfer;
1.1       bouyer   1898:        uint8_t csr;
                   1899:        int datalen, max_datalen;
                   1900:        char *data;
                   1901:        bool got_short;
1.3       bouyer   1902:        usbd_status new_status = USBD_IN_PROGRESS;
1.1       bouyer   1903:
1.14      skrll    1904:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   1905:
1.1       bouyer   1906:        KASSERT(mutex_owned(&sc->sc_lock));
                   1907:        KASSERT(ep->ep_number == epnumber);
                   1908:
1.18      pgoyette 1909:        DPRINTFN(MD_BULK, "on ep %jd", epnumber, 0, 0, 0);
1.14      skrll    1910:        /* select endpoint */
1.1       bouyer   1911:        UWRITE1(sc, MUSB2_REG_EPINDEX, epnumber);
                   1912:
                   1913:        /* read out FIFO status */
                   1914:        csr = UREAD1(sc, MUSB2_REG_RXCSRL);
1.18      pgoyette 1915:        DPRINTFN(MD_BULK, "phase %jd csr 0x%jx", ep->phase, csr ,0 ,0);
1.1       bouyer   1916:
                   1917:        if ((csr & (MUSB2_MASK_CSRL_RXNAKTO | MUSB2_MASK_CSRL_RXSTALL |
                   1918:            MUSB2_MASK_CSRL_RXERROR | MUSB2_MASK_CSRL_RXPKTRDY)) == 0)
                   1919:                return;
                   1920:
1.14      skrll    1921:        KASSERTMSG(ep->phase == DATA_IN, "phase %d", ep->phase);
1.1       bouyer   1922:        if (csr & MUSB2_MASK_CSRL_RXNAKTO) {
                   1923:                csr &= ~MUSB2_MASK_CSRL_RXREQPKT;
                   1924:                UWRITE1(sc, MUSB2_REG_RXCSRL, csr);
                   1925:
                   1926:                csr &= ~MUSB2_MASK_CSRL_RXNAKTO;
                   1927:                UWRITE1(sc, MUSB2_REG_RXCSRL, csr);
1.3       bouyer   1928:                new_status = USBD_TIMEOUT; /* XXX */
1.1       bouyer   1929:                goto complete;
                   1930:        }
                   1931:        if (csr & (MUSB2_MASK_CSRL_RXSTALL | MUSB2_MASK_CSRL_RXERROR)) {
1.7       skrll    1932:                if (csr & MUSB2_MASK_CSRL_RXSTALL)
1.3       bouyer   1933:                        new_status = USBD_STALLED;
                   1934:                else
                   1935:                        new_status = USBD_IOERROR;
1.1       bouyer   1936:                /* clear status */
                   1937:                UWRITE1(sc, MUSB2_REG_RXCSRL, 0);
                   1938:                goto complete;
                   1939:        }
                   1940:        KASSERT(csr & MUSB2_MASK_CSRL_RXPKTRDY);
                   1941:
1.14      skrll    1942:        if (xfer == NULL || xfer->ux_status != USBD_IN_PROGRESS) {
1.1       bouyer   1943:                UWRITE1(sc, MUSB2_REG_RXCSRL, 0);
                   1944:                goto complete;
                   1945:        }
                   1946:
1.14      skrll    1947:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe);
1.1       bouyer   1948:        otgpipe->nexttoggle = otgpipe->nexttoggle ^ 1;
                   1949:
                   1950:        datalen = UREAD2(sc, MUSB2_REG_RXCOUNT);
1.18      pgoyette 1951:        DPRINTFN(MD_BULK, "phase %jd datalen %jd", ep->phase, datalen ,0 ,0);
1.14      skrll    1952:        KASSERT(UE_GET_SIZE(UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize)) > 0);
1.1       bouyer   1953:        max_datalen = min(
1.14      skrll    1954:            UE_GET_SIZE(UGETW(xfer->ux_pipe->up_endpoint->ue_edesc->wMaxPacketSize)),
1.1       bouyer   1955:            ep->datalen);
                   1956:        if (datalen > max_datalen) {
1.3       bouyer   1957:                new_status = USBD_IOERROR;
1.1       bouyer   1958:                UWRITE1(sc, MUSB2_REG_RXCSRL, 0);
                   1959:                goto complete;
                   1960:        }
                   1961:        got_short = (datalen < max_datalen);
                   1962:        if (datalen > 0) {
                   1963:                KASSERT(ep->phase == DATA_IN);
                   1964:                data = ep->data;
                   1965:                ep->data += datalen;
                   1966:                ep->datalen -= datalen;
1.14      skrll    1967:                xfer->ux_actlen += datalen;
1.1       bouyer   1968:                if (((vaddr_t)data & 0x3) == 0 &&
                   1969:                    (datalen >> 2) > 0) {
1.18      pgoyette 1970:                        DPRINTFN(MD_BULK, "r4 data %#jx len %jd",
                   1971:                            (uintptr_t)data, datalen, 0, 0);
1.1       bouyer   1972:                        bus_space_read_multi_4(sc->sc_iot, sc->sc_ioh,
                   1973:                            MUSB2_REG_EPFIFO(ep->ep_number),
                   1974:                            (void *)data, datalen >> 2);
                   1975:                        data += (datalen & ~0x3);
                   1976:                        datalen -= (datalen & ~0x3);
                   1977:                }
1.18      pgoyette 1978:                DPRINTFN(MD_BULK, "r1 data %#jx len %jd", (uintptr_t)data,
                   1979:                    datalen ,0 ,0);
1.1       bouyer   1980:                if (datalen) {
                   1981:                        bus_space_read_multi_1(sc->sc_iot, sc->sc_ioh,
                   1982:                            MUSB2_REG_EPFIFO(ep->ep_number), data, datalen);
                   1983:                }
                   1984:        }
                   1985:        UWRITE1(sc, MUSB2_REG_RXCSRL, 0);
                   1986:        KASSERT(ep->phase == DATA_IN);
                   1987:        if (got_short || (ep->datalen == 0)) {
                   1988:                if (ep->need_short_xfer == 0) {
1.3       bouyer   1989:                        new_status = USBD_NORMAL_COMPLETION;
1.1       bouyer   1990:                        goto complete;
                   1991:                }
                   1992:                ep->need_short_xfer = 0;
                   1993:        }
                   1994:        motg_device_data_read(xfer);
                   1995:        return;
                   1996: complete:
1.18      pgoyette 1997:        DPRINTFN(MD_BULK, "xfer %#jx complete, status %jd", (uintptr_t)xfer,
1.14      skrll    1998:            (xfer != NULL) ? xfer->ux_status : 0, 0, 0);
1.1       bouyer   1999:        ep->phase = IDLE;
                   2000:        ep->xfer = NULL;
1.14      skrll    2001:        if (xfer && xfer->ux_status == USBD_IN_PROGRESS) {
1.3       bouyer   2002:                KASSERT(new_status != USBD_IN_PROGRESS);
1.14      skrll    2003:                xfer->ux_status = new_status;
1.1       bouyer   2004:                usb_transfer_complete(xfer);
1.3       bouyer   2005:        }
1.1       bouyer   2006:        motg_device_data_start1(sc, ep);
                   2007: }
                   2008:
                   2009: static void
                   2010: motg_device_intr_tx(struct motg_softc *sc, int epnumber)
                   2011: {
                   2012:        struct motg_hw_ep *ep = &sc->sc_out_ep[epnumber];
1.14      skrll    2013:        struct usbd_xfer *xfer = ep->xfer;
1.1       bouyer   2014:        uint8_t csr;
                   2015:        struct motg_pipe *otgpipe;
1.3       bouyer   2016:        usbd_status new_status = USBD_IN_PROGRESS;
1.1       bouyer   2017:
1.14      skrll    2018:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   2019:
1.1       bouyer   2020:        KASSERT(mutex_owned(&sc->sc_lock));
                   2021:        KASSERT(ep->ep_number == epnumber);
                   2022:
1.18      pgoyette 2023:        DPRINTFN(MD_BULK, " on ep %jd", epnumber, 0, 0, 0);
1.14      skrll    2024:        /* select endpoint */
1.1       bouyer   2025:        UWRITE1(sc, MUSB2_REG_EPINDEX, epnumber);
                   2026:
                   2027:        csr = UREAD1(sc, MUSB2_REG_TXCSRL);
1.18      pgoyette 2028:        DPRINTFN(MD_BULK, "phase %jd csr 0x%jx", ep->phase, csr, 0, 0);
1.1       bouyer   2029:
                   2030:        if (csr & (MUSB2_MASK_CSRL_TXSTALLED|MUSB2_MASK_CSRL_TXERROR)) {
                   2031:                /* command not accepted */
1.7       skrll    2032:                if (csr & MUSB2_MASK_CSRL_TXSTALLED)
1.3       bouyer   2033:                        new_status = USBD_STALLED;
                   2034:                else
                   2035:                        new_status = USBD_IOERROR;
1.1       bouyer   2036:                /* clear status */
                   2037:                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                   2038:                goto complete;
                   2039:        }
                   2040:        if (csr & MUSB2_MASK_CSRL_TXNAKTO) {
1.3       bouyer   2041:                new_status = USBD_TIMEOUT; /* XXX */
                   2042:                csr &= ~MUSB2_MASK_CSRL_TXNAKTO;
                   2043:                UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
1.1       bouyer   2044:                /* flush fifo */
                   2045:                while (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY) {
                   2046:                        csr |= MUSB2_MASK_CSRL_TXFFLUSH;
1.3       bouyer   2047:                        csr &= ~MUSB2_MASK_CSRL_TXNAKTO;
1.1       bouyer   2048:                        UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
1.3       bouyer   2049:                        delay(1000);
1.1       bouyer   2050:                        csr = UREAD1(sc, MUSB2_REG_TXCSRL);
1.18      pgoyette 2051:                        DPRINTFN(MD_BULK, "TX fifo flush ep %jd CSR 0x%jx",
1.14      skrll    2052:                            epnumber, csr, 0, 0);
1.1       bouyer   2053:                }
                   2054:                goto complete;
                   2055:        }
                   2056:        if (csr & (MUSB2_MASK_CSRL_TXFIFONEMPTY|MUSB2_MASK_CSRL_TXPKTRDY)) {
                   2057:                /* data still not sent */
                   2058:                return;
                   2059:        }
1.14      skrll    2060:        if (xfer == NULL || xfer->ux_status != USBD_IN_PROGRESS)
1.1       bouyer   2061:                goto complete;
1.14      skrll    2062:        KASSERT(ep->phase == DATA_OUT);
1.7       skrll    2063:
1.14      skrll    2064:        otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe);
1.1       bouyer   2065:        otgpipe->nexttoggle = otgpipe->nexttoggle ^ 1;
                   2066:
                   2067:        if (ep->datalen == 0) {
                   2068:                if (ep->need_short_xfer) {
                   2069:                        ep->need_short_xfer = 0;
                   2070:                        /* one more data phase */
                   2071:                } else {
1.3       bouyer   2072:                        new_status = USBD_NORMAL_COMPLETION;
1.1       bouyer   2073:                        goto complete;
                   2074:                }
                   2075:        }
                   2076:        motg_device_data_write(xfer);
                   2077:        return;
                   2078:
                   2079: complete:
1.18      pgoyette 2080:        DPRINTFN(MD_BULK, "xfer %#jx complete, status %jd", (uintptr_t)xfer,
1.14      skrll    2081:            (xfer != NULL) ? xfer->ux_status : 0, 0, 0);
1.1       bouyer   2082: #ifdef DIAGNOSTIC
1.14      skrll    2083:        if (xfer && xfer->ux_status == USBD_IN_PROGRESS && ep->phase != DATA_OUT)
1.1       bouyer   2084:                panic("motg_device_intr_tx: bad phase %d", ep->phase);
                   2085: #endif
                   2086:        ep->phase = IDLE;
                   2087:        ep->xfer = NULL;
1.14      skrll    2088:        if (xfer && xfer->ux_status == USBD_IN_PROGRESS) {
1.3       bouyer   2089:                KASSERT(new_status != USBD_IN_PROGRESS);
1.14      skrll    2090:                xfer->ux_status = new_status;
1.1       bouyer   2091:                usb_transfer_complete(xfer);
1.3       bouyer   2092:        }
1.1       bouyer   2093:        motg_device_data_start1(sc, ep);
                   2094: }
                   2095:
                   2096: /* Abort a device control request. */
                   2097: void
1.14      skrll    2098: motg_device_data_abort(struct usbd_xfer *xfer)
1.1       bouyer   2099: {
1.14      skrll    2100:        struct motg_softc __diagused *sc = MOTG_XFER2SC(xfer);
1.1       bouyer   2101:        KASSERT(mutex_owned(&sc->sc_lock));
                   2102:
1.14      skrll    2103:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   2104:
1.3       bouyer   2105:        motg_device_xfer_abort(xfer);
1.1       bouyer   2106: }
                   2107:
                   2108: /* Close a device control pipe */
                   2109: void
1.14      skrll    2110: motg_device_data_close(struct usbd_pipe *pipe)
1.1       bouyer   2111: {
1.14      skrll    2112:        struct motg_softc *sc __diagused = MOTG_PIPE2SC(pipe);
                   2113:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(pipe);
1.1       bouyer   2114:        struct motg_pipe *otgpipeiter;
                   2115:
1.14      skrll    2116:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   2117:
1.1       bouyer   2118:        KASSERT(mutex_owned(&sc->sc_lock));
                   2119:        KASSERT(otgpipe->hw_ep->xfer == NULL ||
1.14      skrll    2120:            otgpipe->hw_ep->xfer->ux_pipe != pipe);
1.1       bouyer   2121:
1.14      skrll    2122:        pipe->up_endpoint->ue_toggle = otgpipe->nexttoggle;
1.1       bouyer   2123:        SIMPLEQ_FOREACH(otgpipeiter, &otgpipe->hw_ep->ep_pipes, ep_pipe_list) {
                   2124:                if (otgpipeiter == otgpipe) {
                   2125:                        /* remove from list */
                   2126:                        SIMPLEQ_REMOVE(&otgpipe->hw_ep->ep_pipes, otgpipe,
                   2127:                            motg_pipe, ep_pipe_list);
                   2128:                        otgpipe->hw_ep->refcount--;
                   2129:                        /* we're done */
                   2130:                        return;
                   2131:                }
                   2132:        }
                   2133:        panic("motg_device_data_close: not found");
                   2134: }
                   2135:
                   2136: void
1.14      skrll    2137: motg_device_data_done(struct usbd_xfer *xfer)
1.1       bouyer   2138: {
1.14      skrll    2139:        struct motg_pipe *otgpipe __diagused = MOTG_PIPE2MPIPE(xfer->ux_pipe);
                   2140:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   2141:
1.1       bouyer   2142:        KASSERT(otgpipe->hw_ep->xfer != xfer);
                   2143: }
                   2144:
                   2145: void
1.14      skrll    2146: motg_device_clear_toggle(struct usbd_pipe *pipe)
1.1       bouyer   2147: {
1.14      skrll    2148:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(pipe);
1.1       bouyer   2149:        otgpipe->nexttoggle = 0;
                   2150: }
1.3       bouyer   2151:
                   2152: /* Abort a device control request. */
                   2153: static void
1.14      skrll    2154: motg_device_xfer_abort(struct usbd_xfer *xfer)
1.3       bouyer   2155: {
                   2156:        int wake;
                   2157:        uint8_t csr;
1.14      skrll    2158:        struct motg_softc *sc = MOTG_XFER2SC(xfer);
                   2159:        struct motg_pipe *otgpipe = MOTG_PIPE2MPIPE(xfer->ux_pipe);
1.3       bouyer   2160:        KASSERT(mutex_owned(&sc->sc_lock));
                   2161:
1.14      skrll    2162:        MOTGHIST_FUNC(); MOTGHIST_CALLED();
                   2163:
                   2164:        if (xfer->ux_hcflags & UXFER_ABORTING) {
                   2165:                DPRINTF("already aborting", 0, 0, 0, 0);
                   2166:                xfer->ux_hcflags |= UXFER_ABORTWAIT;
                   2167:                while (xfer->ux_hcflags & UXFER_ABORTING)
                   2168:                        cv_wait(&xfer->ux_hccv, &sc->sc_lock);
1.3       bouyer   2169:                return;
                   2170:        }
1.14      skrll    2171:        xfer->ux_hcflags |= UXFER_ABORTING;
1.3       bouyer   2172:        if (otgpipe->hw_ep->xfer == xfer) {
1.14      skrll    2173:                KASSERT(xfer->ux_status == USBD_IN_PROGRESS);
1.3       bouyer   2174:                otgpipe->hw_ep->xfer = NULL;
                   2175:                if (otgpipe->hw_ep->ep_number > 0) {
1.7       skrll    2176:                        /* select endpoint */
1.3       bouyer   2177:                        UWRITE1(sc, MUSB2_REG_EPINDEX,
                   2178:                            otgpipe->hw_ep->ep_number);
                   2179:                        if (otgpipe->hw_ep->phase == DATA_OUT) {
                   2180:                                csr = UREAD1(sc, MUSB2_REG_TXCSRL);
                   2181:                                while (csr & MUSB2_MASK_CSRL_TXFIFONEMPTY) {
                   2182:                                        csr |= MUSB2_MASK_CSRL_TXFFLUSH;
                   2183:                                        UWRITE1(sc, MUSB2_REG_TXCSRL, csr);
                   2184:                                        csr = UREAD1(sc, MUSB2_REG_TXCSRL);
                   2185:                                }
                   2186:                                UWRITE1(sc, MUSB2_REG_TXCSRL, 0);
                   2187:                        } else if (otgpipe->hw_ep->phase == DATA_IN) {
                   2188:                                csr = UREAD1(sc, MUSB2_REG_RXCSRL);
                   2189:                                while (csr & MUSB2_MASK_CSRL_RXPKTRDY) {
                   2190:                                        csr |= MUSB2_MASK_CSRL_RXFFLUSH;
                   2191:                                        UWRITE1(sc, MUSB2_REG_RXCSRL, csr);
                   2192:                                        csr = UREAD1(sc, MUSB2_REG_RXCSRL);
                   2193:                                }
                   2194:                                UWRITE1(sc, MUSB2_REG_RXCSRL, 0);
                   2195:                        }
                   2196:                        otgpipe->hw_ep->phase = IDLE;
                   2197:                }
                   2198:        }
1.14      skrll    2199:        xfer->ux_status = USBD_CANCELLED; /* make software ignore it */
                   2200:        wake = xfer->ux_hcflags & UXFER_ABORTWAIT;
                   2201:        xfer->ux_hcflags &= ~(UXFER_ABORTING | UXFER_ABORTWAIT);
1.3       bouyer   2202:        usb_transfer_complete(xfer);
                   2203:        if (wake)
1.14      skrll    2204:                cv_broadcast(&xfer->ux_hccv);
1.3       bouyer   2205: }

CVSweb <webmaster@jp.NetBSD.org>