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>