Bug Summary

File:dev/usb/ehci.c
Warning:line 1123, column 3
3rd function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.4 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name ehci.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -ffp-contract=on -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -target-feature +retpoline-external-thunk -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/llvm16/lib/clang/16 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/legacy-dpm -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu13 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/inc -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/inc/pmfw_if -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D SUSPEND -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fcf-protection=branch -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /home/ben/Projects/scan/2024-01-11-110808-61670-1 -x c /usr/src/sys/dev/usb/ehci.c
1/* $OpenBSD: ehci.c,v 1.219 2022/04/12 19:41:11 naddy Exp $ */
2/* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */
3
4/*
5 * Copyright (c) 2014-2015 Martin Pieuchot
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19/*
20 * Copyright (c) 2004-2008 The NetBSD Foundation, Inc.
21 * All rights reserved.
22 *
23 * This code is derived from software contributed to The NetBSD Foundation
24 * by Lennart Augustsson (lennart@augustsson.net), Charles M. Hannum and
25 * Jeremy Morse (jeremy.morse@gmail.com).
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 *
36 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
37 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
38 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
40 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
41 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
42 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
43 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
44 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
46 * POSSIBILITY OF SUCH DAMAGE.
47 */
48
49/*
50 * TODO:
51 * 1) The hub driver needs to handle and schedule the transaction translator,
52 * to assign place in frame where different devices get to go. See chapter
53 * on hubs in USB 2.0 for details.
54 *
55 * 2) Command failures are not recovered correctly.
56 */
57
58#include <sys/param.h>
59#include <sys/systm.h>
60#include <sys/kernel.h>
61#include <sys/rwlock.h>
62#include <sys/malloc.h>
63#include <sys/device.h>
64#include <sys/queue.h>
65#include <sys/timeout.h>
66#include <sys/pool.h>
67#include <sys/endian.h>
68#include <sys/atomic.h>
69
70#include <machine/bus.h>
71
72#include <dev/usb/usb.h>
73#include <dev/usb/usbdi.h>
74#include <dev/usb/usbdivar.h>
75#include <dev/usb/usb_mem.h>
76
77#include <dev/usb/ehcireg.h>
78#include <dev/usb/ehcivar.h>
79
80struct cfdriver ehci_cd = {
81 NULL((void *)0), "ehci", DV_DULL, CD_SKIPHIBERNATE2
82};
83
84#ifdef EHCI_DEBUG
85#define DPRINTF(x) do { if (ehcidebug) printf x; } while(0)
86#define DPRINTFN(n,x) do { if (ehcidebug>(n)) printf x; } while (0)
87int ehcidebug = 0;
88#define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f))
89#else
90#define DPRINTF(x)
91#define DPRINTFN(n,x)
92#endif
93
94struct pool *ehcixfer;
95
96struct ehci_pipe {
97 struct usbd_pipe pipe;
98
99 struct ehci_soft_qh *sqh;
100 union {
101 /* Control pipe */
102 struct {
103 struct usb_dma reqdma;
104 } ctl;
105 /* Iso pipe */
106 struct {
107 u_int next_frame;
108 u_int cur_xfers;
109 } isoc;
110 } u;
111};
112
113u_int8_t ehci_reverse_bits(u_int8_t, int);
114
115usbd_status ehci_open(struct usbd_pipe *);
116int ehci_setaddr(struct usbd_device *, int);
117void ehci_poll(struct usbd_bus *);
118void ehci_softintr(void *);
119int ehci_intr1(struct ehci_softc *);
120void ehci_check_intr(struct ehci_softc *, struct usbd_xfer *);
121void ehci_check_qh_intr(struct ehci_softc *, struct usbd_xfer *);
122void ehci_check_itd_intr(struct ehci_softc *, struct usbd_xfer *);
123void ehci_idone(struct usbd_xfer *);
124void ehci_isoc_idone(struct usbd_xfer *);
125void ehci_timeout(void *);
126void ehci_timeout_task(void *);
127void ehci_intrlist_timeout(void *);
128
129struct usbd_xfer *ehci_allocx(struct usbd_bus *);
130void ehci_freex(struct usbd_bus *, struct usbd_xfer *);
131
132usbd_status ehci_root_ctrl_transfer(struct usbd_xfer *);
133usbd_status ehci_root_ctrl_start(struct usbd_xfer *);
134void ehci_root_ctrl_abort(struct usbd_xfer *);
135void ehci_root_ctrl_close(struct usbd_pipe *);
136void ehci_root_ctrl_done(struct usbd_xfer *);
137
138usbd_status ehci_root_intr_transfer(struct usbd_xfer *);
139usbd_status ehci_root_intr_start(struct usbd_xfer *);
140void ehci_root_intr_abort(struct usbd_xfer *);
141void ehci_root_intr_close(struct usbd_pipe *);
142void ehci_root_intr_done(struct usbd_xfer *);
143
144usbd_status ehci_device_ctrl_transfer(struct usbd_xfer *);
145usbd_status ehci_device_ctrl_start(struct usbd_xfer *);
146void ehci_device_ctrl_abort(struct usbd_xfer *);
147void ehci_device_ctrl_close(struct usbd_pipe *);
148void ehci_device_ctrl_done(struct usbd_xfer *);
149
150usbd_status ehci_device_bulk_transfer(struct usbd_xfer *);
151usbd_status ehci_device_bulk_start(struct usbd_xfer *);
152void ehci_device_bulk_abort(struct usbd_xfer *);
153void ehci_device_bulk_close(struct usbd_pipe *);
154void ehci_device_bulk_done(struct usbd_xfer *);
155
156usbd_status ehci_device_intr_transfer(struct usbd_xfer *);
157usbd_status ehci_device_intr_start(struct usbd_xfer *);
158void ehci_device_intr_abort(struct usbd_xfer *);
159void ehci_device_intr_close(struct usbd_pipe *);
160void ehci_device_intr_done(struct usbd_xfer *);
161
162usbd_status ehci_device_isoc_transfer(struct usbd_xfer *);
163usbd_status ehci_device_isoc_start(struct usbd_xfer *);
164void ehci_device_isoc_abort(struct usbd_xfer *);
165void ehci_device_isoc_close(struct usbd_pipe *);
166void ehci_device_isoc_done(struct usbd_xfer *);
167
168void ehci_device_clear_toggle(struct usbd_pipe *pipe);
169
170void ehci_pcd(struct ehci_softc *, struct usbd_xfer *);
171void ehci_disown(struct ehci_softc *, int, int);
172
173struct ehci_soft_qh *ehci_alloc_sqh(struct ehci_softc *);
174void ehci_free_sqh(struct ehci_softc *, struct ehci_soft_qh *);
175
176struct ehci_soft_qtd *ehci_alloc_sqtd(struct ehci_softc *);
177void ehci_free_sqtd(struct ehci_softc *, struct ehci_soft_qtd *);
178usbd_status ehci_alloc_sqtd_chain(struct ehci_softc *, u_int,
179 struct usbd_xfer *, struct ehci_soft_qtd **, struct ehci_soft_qtd **);
180void ehci_free_sqtd_chain(struct ehci_softc *, struct ehci_xfer *);
181
182struct ehci_soft_itd *ehci_alloc_itd(struct ehci_softc *);
183void ehci_free_itd(struct ehci_softc *, struct ehci_soft_itd *);
184void ehci_rem_itd_chain(struct ehci_softc *, struct ehci_xfer *);
185void ehci_free_itd_chain(struct ehci_softc *, struct ehci_xfer *);
186int ehci_alloc_itd_chain(struct ehci_softc *, struct usbd_xfer *);
187int ehci_alloc_sitd_chain(struct ehci_softc *, struct usbd_xfer *);
188void ehci_abort_isoc_xfer(struct usbd_xfer *xfer,
189 usbd_status status);
190
191usbd_status ehci_device_setintr(struct ehci_softc *, struct ehci_soft_qh *,
192 int ival);
193
194void ehci_add_qh(struct ehci_soft_qh *, struct ehci_soft_qh *);
195void ehci_rem_qh(struct ehci_softc *, struct ehci_soft_qh *);
196void ehci_set_qh_qtd(struct ehci_soft_qh *, struct ehci_soft_qtd *);
197void ehci_sync_hc(struct ehci_softc *);
198
199void ehci_close_pipe(struct usbd_pipe *);
200void ehci_abort_xfer(struct usbd_xfer *, usbd_status);
201
202#ifdef EHCI_DEBUG
203void ehci_dump_regs(struct ehci_softc *);
204void ehci_dump(void);
205struct ehci_softc *theehci;
206void ehci_dump_link(ehci_link_t, int);
207void ehci_dump_sqtds(struct ehci_soft_qtd *);
208void ehci_dump_sqtd(struct ehci_soft_qtd *);
209void ehci_dump_qtd(struct ehci_qtd *);
210void ehci_dump_sqh(struct ehci_soft_qh *);
211#if notyet
212void ehci_dump_itd(struct ehci_soft_itd *);
213#endif
214#ifdef DIAGNOSTIC1
215void ehci_dump_exfer(struct ehci_xfer *);
216#endif
217#endif
218
219#define EHCI_INTR_ENDPT1 1
220
221const struct usbd_bus_methods ehci_bus_methods = {
222 .open_pipe = ehci_open,
223 .dev_setaddr = ehci_setaddr,
224 .soft_intr = ehci_softintr,
225 .do_poll = ehci_poll,
226 .allocx = ehci_allocx,
227 .freex = ehci_freex,
228};
229
230const struct usbd_pipe_methods ehci_root_ctrl_methods = {
231 .transfer = ehci_root_ctrl_transfer,
232 .start = ehci_root_ctrl_start,
233 .abort = ehci_root_ctrl_abort,
234 .close = ehci_root_ctrl_close,
235 .done = ehci_root_ctrl_done,
236};
237
238const struct usbd_pipe_methods ehci_root_intr_methods = {
239 .transfer = ehci_root_intr_transfer,
240 .start = ehci_root_intr_start,
241 .abort = ehci_root_intr_abort,
242 .close = ehci_root_intr_close,
243 .done = ehci_root_intr_done,
244};
245
246const struct usbd_pipe_methods ehci_device_ctrl_methods = {
247 .transfer = ehci_device_ctrl_transfer,
248 .start = ehci_device_ctrl_start,
249 .abort = ehci_device_ctrl_abort,
250 .close = ehci_device_ctrl_close,
251 .done = ehci_device_ctrl_done,
252};
253
254const struct usbd_pipe_methods ehci_device_intr_methods = {
255 .transfer = ehci_device_intr_transfer,
256 .start = ehci_device_intr_start,
257 .abort = ehci_device_intr_abort,
258 .close = ehci_device_intr_close,
259 .cleartoggle = ehci_device_clear_toggle,
260 .done = ehci_device_intr_done,
261};
262
263const struct usbd_pipe_methods ehci_device_bulk_methods = {
264 .transfer = ehci_device_bulk_transfer,
265 .start = ehci_device_bulk_start,
266 .abort = ehci_device_bulk_abort,
267 .close = ehci_device_bulk_close,
268 .cleartoggle = ehci_device_clear_toggle,
269 .done = ehci_device_bulk_done,
270};
271
272const struct usbd_pipe_methods ehci_device_isoc_methods = {
273 .transfer = ehci_device_isoc_transfer,
274 .start = ehci_device_isoc_start,
275 .abort = ehci_device_isoc_abort,
276 .close = ehci_device_isoc_close,
277 .done = ehci_device_isoc_done,
278};
279
280/*
281 * Reverse a number with nbits bits. Used to evenly distribute lower-level
282 * interrupt heads in the periodic schedule.
283 * Suitable for use with EHCI_IPOLLRATES <= 9.
284 */
285u_int8_t
286ehci_reverse_bits(u_int8_t c, int nbits)
287{
288 c = ((c >> 1) & 0x55) | ((c << 1) & 0xaa);
289 c = ((c >> 2) & 0x33) | ((c << 2) & 0xcc);
290 c = ((c >> 4) & 0x0f) | ((c << 4) & 0xf0);
291
292 return c >> (8 - nbits);
293}
294
295usbd_status
296ehci_init(struct ehci_softc *sc)
297{
298 u_int32_t sparams, cparams, hcr;
299 u_int i, j;
300 usbd_status err;
301 struct ehci_soft_qh *sqh;
302
303#ifdef EHCI_DEBUG
304 u_int32_t vers;
305 theehci = sc;
306
307 DPRINTF(("ehci_init: start\n"));
308
309 vers = EREAD2(sc, EHCI_HCIVERSION)(((sc)->iot)->read_2(((sc)->ioh), ((0x02))));
310 DPRINTF(("%s: EHCI version %x.%x\n", sc->sc_bus.bdev.dv_xname,
311 vers >> 8, vers & 0xff));
312#endif
313
314 sc->sc_offs = EREAD1(sc, EHCI_CAPLENGTH)(((sc)->iot)->read_1(((sc)->ioh), ((0x00))));
315
316 sparams = EREAD4(sc, EHCI_HCSPARAMS)(((sc)->iot)->read_4(((sc)->ioh), ((0x04))));
317 DPRINTF(("ehci_init: sparams=0x%x\n", sparams));
318 sc->sc_noport = EHCI_HCS_N_PORTS(sparams)((sparams) & 0xf);
319 cparams = EREAD4(sc, EHCI_HCCPARAMS)(((sc)->iot)->read_4(((sc)->ioh), ((0x08))));
320 DPRINTF(("ehci_init: cparams=0x%x\n", cparams));
321
322 /* MUST clear segment register if 64 bit capable. */
323 if (EHCI_HCC_64BIT(cparams)((cparams) & 0x1))
324 EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0)(((sc)->iot)->write_4(((sc)->ioh), ((0x10)), ((0))));
325
326 sc->sc_bus.usbrev = USBREV_2_04;
327
328 DPRINTF(("%s: resetting\n", sc->sc_bus.bdev.dv_xname));
329 err = ehci_reset(sc);
330 if (err)
331 return (err);
332
333 if (ehcixfer == NULL((void *)0)) {
334 ehcixfer = malloc(sizeof(struct pool), M_USBHC103, M_NOWAIT0x0002);
335 if (ehcixfer == NULL((void *)0)) {
336 printf("%s: unable to allocate pool descriptor\n",
337 sc->sc_bus.bdev.dv_xname);
338 return (ENOMEM12);
339 }
340 pool_init(ehcixfer, sizeof(struct ehci_xfer), 0, IPL_SOFTUSB0x2,
341 0, "ehcixfer", NULL((void *)0));
342 }
343
344 /* frame list size at default, read back what we got and use that */
345 switch (EHCI_CMD_FLS(EOREAD4(sc, EHCI_USBCMD))((((((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs
+(0x00))))) >> 2) & 3)
) {
346 case 0:
347 sc->sc_flsize = 1024;
348 break;
349 case 1:
350 sc->sc_flsize = 512;
351 break;
352 case 2:
353 sc->sc_flsize = 256;
354 break;
355 case 3:
356 return (USBD_IOERROR);
357 }
358 err = usb_allocmem(&sc->sc_bus, sc->sc_flsize * sizeof(ehci_link_t),
359 EHCI_FLALIGN_ALIGN0x1000, USB_DMA_COHERENT(1 << 0), &sc->sc_fldma);
360 if (err)
361 return (err);
362 DPRINTF(("%s: flsize=%d\n", sc->sc_bus.bdev.dv_xname,sc->sc_flsize));
363 sc->sc_flist = KERNADDR(&sc->sc_fldma, 0)((void *)((char *)((&sc->sc_fldma)->block->kaddr
+ (&sc->sc_fldma)->offs) + (0)))
;
364
365 for (i = 0; i < sc->sc_flsize; i++)
366 sc->sc_flist[i] = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
367
368 EOWRITE4(sc, EHCI_PERIODICLISTBASE, DMAADDR(&sc->sc_fldma, 0))(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x14)), ((((&sc->sc_fldma)->block->map->dm_segs
[0].ds_addr + (&sc->sc_fldma)->offs + (0))))))
;
369
370 sc->sc_softitds = mallocarray(sc->sc_flsize,
371 sizeof(struct ehci_soft_itd *), M_USBHC103, M_NOWAIT0x0002 | M_ZERO0x0008);
372 if (sc->sc_softitds == NULL((void *)0)) {
373 usb_freemem(&sc->sc_bus, &sc->sc_fldma);
374 return (ENOMEM12);
375 }
376 LIST_INIT(&sc->sc_freeitds)do { ((&sc->sc_freeitds)->lh_first) = ((void *)0); }
while (0)
;
377 TAILQ_INIT(&sc->sc_intrhead)do { (&sc->sc_intrhead)->tqh_first = ((void *)0); (
&sc->sc_intrhead)->tqh_last = &(&sc->sc_intrhead
)->tqh_first; } while (0)
;
378
379 /* Set up the bus struct. */
380 sc->sc_bus.methods = &ehci_bus_methods;
381 sc->sc_bus.pipe_size = sizeof(struct ehci_pipe);
382
383 sc->sc_eintrs = EHCI_NORMAL_INTRS(0x00000020 | 0x00000010 | 0x00000004 | 0x00000002 | 0x00000001
)
;
384
385 /*
386 * Allocate the interrupt dummy QHs. These are arranged to give poll
387 * intervals that are powers of 2 times 1ms.
388 */
389 for (i = 0; i < EHCI_INTRQHS((1 << 8) - 1); i++) {
390 sqh = ehci_alloc_sqh(sc);
391 if (sqh == NULL((void *)0)) {
392 err = USBD_NOMEM;
393 goto bad1;
394 }
395 sc->sc_islots[i].sqh = sqh;
396 }
397 for (i = 0; i < EHCI_INTRQHS((1 << 8) - 1); i++) {
398 sqh = sc->sc_islots[i].sqh;
399 if (i == 0) {
400 /* The last (1ms) QH terminates. */
401 sqh->qh.qh_link = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
402 sqh->next = NULL((void *)0);
403 } else {
404 /* Otherwise the next QH has half the poll interval */
405 sqh->next = sc->sc_islots[(i + 1) / 2 - 1].sqh;
406 sqh->qh.qh_link = htole32(sqh->next->physaddr |((__uint32_t)(sqh->next->physaddr | 0x2))
407 EHCI_LINK_QH)((__uint32_t)(sqh->next->physaddr | 0x2));
408 }
409 sqh->qh.qh_endp = htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH))((__uint32_t)(((0x2) << 12)));
410 sqh->qh.qh_endphub = htole32(EHCI_QH_SET_MULT(1))((__uint32_t)(((1) << 30)));
411 sqh->qh.qh_curqtd = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
412 sqh->qh.qh_qtd.qtd_next = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
413 sqh->qh.qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
414 sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED)((__uint32_t)(0x40));
415 sqh->sqtd = NULL((void *)0);
416 usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
417 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
418 }
419 /* Point the frame list at the last level (128ms). */
420 for (i = 0; i < (1 << (EHCI_IPOLLRATES8 - 1)); i++)
421 for (j = i; j < sc->sc_flsize; j += 1 << (EHCI_IPOLLRATES8 - 1))
422 sc->sc_flist[j] = htole32(EHCI_LINK_QH | sc->sc_islots[((__uint32_t)(0x2 | sc->sc_islots[ ((((ehci_reverse_bits( i
, 8 - 1)) & ((1 << (8 - 1)) - 1)) | (1 << (8 -
1))) - 1)].sqh->physaddr))
423 EHCI_IQHIDX(EHCI_IPOLLRATES - 1, ehci_reverse_bits(((__uint32_t)(0x2 | sc->sc_islots[ ((((ehci_reverse_bits( i
, 8 - 1)) & ((1 << (8 - 1)) - 1)) | (1 << (8 -
1))) - 1)].sqh->physaddr))
424 i, EHCI_IPOLLRATES - 1))].sqh->physaddr)((__uint32_t)(0x2 | sc->sc_islots[ ((((ehci_reverse_bits( i
, 8 - 1)) & ((1 << (8 - 1)) - 1)) | (1 << (8 -
1))) - 1)].sqh->physaddr))
;
425 usb_syncmem(&sc->sc_fldma, 0, sc->sc_flsize * sizeof(ehci_link_t),
426 BUS_DMASYNC_PREWRITE0x04);
427
428 /* Allocate dummy QH that starts the async list. */
429 sqh = ehci_alloc_sqh(sc);
430 if (sqh == NULL((void *)0)) {
431 err = USBD_NOMEM;
432 goto bad1;
433 }
434 /* Fill the QH */
435 sqh->qh.qh_endp =
436 htole32(EHCI_QH_SET_EPS(EHCI_QH_SPEED_HIGH) | EHCI_QH_HRECL)((__uint32_t)(((0x2) << 12) | 0x00008000));
437 sqh->qh.qh_link =
438 htole32(sqh->physaddr | EHCI_LINK_QH)((__uint32_t)(sqh->physaddr | 0x2));
439 sqh->qh.qh_curqtd = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
440 sqh->prev = sqh; /*It's a circular list.. */
441 sqh->next = sqh;
442 /* Fill the overlay qTD */
443 sqh->qh.qh_qtd.qtd_next = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
444 sqh->qh.qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
445 sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED)((__uint32_t)(0x40));
446 sqh->sqtd = NULL((void *)0);
447 usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
448 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
449
450 /* Point to async list */
451 sc->sc_async_head = sqh;
452 EOWRITE4(sc, EHCI_ASYNCLISTADDR, sqh->physaddr | EHCI_LINK_QH)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x18)), ((sqh->physaddr | 0x2))))
;
453
454 timeout_set(&sc->sc_tmo_intrlist, ehci_intrlist_timeout, sc);
455
456 rw_init(&sc->sc_doorbell_lock, "ehcidb")_rw_init_flags(&sc->sc_doorbell_lock, "ehcidb", 0, ((void
*)0))
;
457
458 /* Turn on controller */
459 EOWRITE4(sc, EHCI_USBCMD,(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
460 EHCI_CMD_ITC_2 | /* 2 microframes interrupt delay */(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
461 (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_FLS_M) |(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
462 EHCI_CMD_ASE |(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
463 EHCI_CMD_PSE |(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
464 EHCI_CMD_RS)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
;
465
466 /* Take over port ownership */
467 EOWRITE4(sc, EHCI_CONFIGFLAG, EHCI_CONF_CF)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x40)), ((0x00000001))))
;
468
469 for (i = 0; i < 100; i++) {
470 usb_delay_ms(&sc->sc_bus, 1);
471 hcr = EOREAD4(sc, EHCI_USBSTS)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x04))))
& EHCI_STS_HCH0x00001000;
472 if (!hcr)
473 break;
474 }
475 if (hcr) {
476 printf("%s: run timeout\n", sc->sc_bus.bdev.dv_xname);
477 return (USBD_IOERROR);
478 }
479
480 /* Enable interrupts */
481 EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x08)), ((sc->sc_eintrs))))
;
482
483 return (USBD_NORMAL_COMPLETION);
484
485#if 0
486 bad2:
487 ehci_free_sqh(sc, sc->sc_async_head);
488#endif
489 bad1:
490 free(sc->sc_softitds, M_USBHC103,
491 sc->sc_flsize * sizeof(struct ehci_soft_itd *));
492 usb_freemem(&sc->sc_bus, &sc->sc_fldma);
493 return (err);
494}
495
496int
497ehci_intr(void *v)
498{
499 struct ehci_softc *sc = v;
500
501 if (sc == NULL((void *)0) || sc->sc_bus.dying)
502 return (0);
503
504 /* If we get an interrupt while polling, then just ignore it. */
505 if (sc->sc_bus.use_polling) {
506 u_int32_t intrs = EHCI_STS_INTRS(EOREAD4(sc, EHCI_USBSTS))(((((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs
+(0x04))))) & 0x3f)
;
507
508 if (intrs)
509 EOWRITE4(sc, EHCI_USBSTS, intrs)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x04)), ((intrs))))
; /* Acknowledge */
510 return (0);
511 }
512
513 return (ehci_intr1(sc));
514}
515
516int
517ehci_intr1(struct ehci_softc *sc)
518{
519 u_int32_t intrs, eintrs;
520
521 /* In case the interrupt occurs before initialization has completed. */
522 if (sc == NULL((void *)0)) {
523#ifdef DIAGNOSTIC1
524 printf("ehci_intr1: sc == NULL\n");
525#endif
526 return (0);
527 }
528
529 intrs = EOREAD4(sc, EHCI_USBSTS)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x04))))
;
530 if (intrs == 0xffffffff) {
531 sc->sc_bus.dying = 1;
532 return (0);
533 }
534 intrs = EHCI_STS_INTRS(intrs)((intrs) & 0x3f);
535 if (!intrs)
536 return (0);
537
538 eintrs = intrs & sc->sc_eintrs;
539 if (!eintrs)
540 return (0);
541
542 EOWRITE4(sc, EHCI_USBSTS, intrs)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x04)), ((intrs))))
; /* Acknowledge */
543 sc->sc_bus.no_intrs++;
544
545 if (eintrs & EHCI_STS_HSE0x00000010) {
546 printf("%s: unrecoverable error, controller halted\n",
547 sc->sc_bus.bdev.dv_xname);
548 sc->sc_bus.dying = 1;
549 return (1);
550 }
551 if (eintrs & EHCI_STS_IAA0x00000020) {
552 wakeup(&sc->sc_async_head);
553 eintrs &= ~EHCI_STS_IAA0x00000020;
554 }
555 if (eintrs & (EHCI_STS_INT0x00000001 | EHCI_STS_ERRINT0x00000002)) {
556 usb_schedsoftintr(&sc->sc_bus);
557 eintrs &= ~(EHCI_STS_INT0x00000001 | EHCI_STS_ERRINT0x00000002);
558 }
559 if (eintrs & EHCI_STS_PCD0x00000004) {
560 atomic_setbits_intx86_atomic_setbits_u32(&sc->sc_flags, EHCIF_PCB_INTR0x02);
561 usb_schedsoftintr(&sc->sc_bus);
562 eintrs &= ~EHCI_STS_PCD0x00000004;
563 }
564
565 if (eintrs != 0) {
566 /* Block unprocessed interrupts. */
567 sc->sc_eintrs &= ~eintrs;
568 EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x08)), ((sc->sc_eintrs))))
;
569 printf("%s: blocking intrs 0x%x\n",
570 sc->sc_bus.bdev.dv_xname, eintrs);
571 }
572
573 return (1);
574}
575
576void
577ehci_pcd(struct ehci_softc *sc, struct usbd_xfer *xfer)
578{
579 u_char *p;
580 int i, m;
581
582 if (xfer == NULL((void *)0)) {
583 /* Just ignore the change. */
584 return;
585 }
586
587 p = KERNADDR(&xfer->dmabuf, 0)((void *)((char *)((&xfer->dmabuf)->block->kaddr
+ (&xfer->dmabuf)->offs) + (0)))
;
588 m = min(sc->sc_noport, xfer->length * 8 - 1);
589 memset(p, 0, xfer->length)__builtin_memset((p), (0), (xfer->length));
590 for (i = 1; i <= m; i++) {
591 /* Pick out CHANGE bits from the status reg. */
592 if (EOREAD4(sc, EHCI_PORTSC(i))(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
((0x40+4*(i))))))
& EHCI_PS_CLEAR(0x00000020|0x00000008|0x00000002))
593 p[i / 8] |= 1 << (i % 8);
594 }
595 xfer->actlen = xfer->length;
596 xfer->status = USBD_NORMAL_COMPLETION;
597
598 usb_transfer_complete(xfer);
599}
600
601/*
602 * Work around the half configured control (default) pipe when setting
603 * the address of a device.
604 *
605 * Because a single QH is setup per endpoint in ehci_open(), and the
606 * control pipe is configured before we could have set the address
607 * of the device or read the wMaxPacketSize of the endpoint, we have
608 * to re-open the pipe twice here.
609 */
610int
611ehci_setaddr(struct usbd_device *dev, int addr)
612{
613 /* Root Hub */
614 if (dev->depth == 0)
615 return (0);
616
617 /* Re-establish the default pipe with the new max packet size. */
618 ehci_close_pipe(dev->default_pipe);
619 if (ehci_open(dev->default_pipe))
620 return (EINVAL22);
621
622 if (usbd_set_address(dev, addr))
623 return (1);
624
625 dev->address = addr;
626
627 /* Re-establish the default pipe with the new address. */
628 ehci_close_pipe(dev->default_pipe);
629 if (ehci_open(dev->default_pipe))
630 return (EINVAL22);
631
632 return (0);
633}
634
635void
636ehci_softintr(void *v)
637{
638 struct ehci_softc *sc = v;
639 struct ehci_xfer *ex, *nextex;
640
641 if (sc->sc_bus.dying)
642 return;
643
644 sc->sc_bus.intr_context++;
645
646 if (sc->sc_flags & EHCIF_PCB_INTR0x02) {
647 atomic_clearbits_intx86_atomic_clearbits_u32(&sc->sc_flags, EHCIF_PCB_INTR0x02);
648 ehci_pcd(sc, sc->sc_intrxfer);
649 }
650
651 /*
652 * The only explanation I can think of for why EHCI is as brain dead
653 * as UHCI interrupt-wise is that Intel was involved in both.
654 * An interrupt just tells us that something is done, we have no
655 * clue what, so we need to scan through all active transfers. :-(
656 */
657 for (ex = TAILQ_FIRST(&sc->sc_intrhead)((&sc->sc_intrhead)->tqh_first); ex; ex = nextex) {
658 nextex = TAILQ_NEXT(ex, inext)((ex)->inext.tqe_next);
659 ehci_check_intr(sc, &ex->xfer);
660 }
661
662 /* Schedule a callout to catch any dropped transactions. */
663 if ((sc->sc_flags & EHCIF_DROPPED_INTR_WORKAROUND0x01) &&
664 !TAILQ_EMPTY(&sc->sc_intrhead)(((&sc->sc_intrhead)->tqh_first) == ((void *)0))) {
665 timeout_add_sec(&sc->sc_tmo_intrlist, 1);
666 }
667
668 if (sc->sc_softwake) {
669 sc->sc_softwake = 0;
670 wakeup(&sc->sc_softwake);
671 }
672
673 sc->sc_bus.intr_context--;
674}
675
676void
677ehci_check_intr(struct ehci_softc *sc, struct usbd_xfer *xfer)
678{
679 int attr = xfer->pipe->endpoint->edesc->bmAttributes;
680
681 if (UE_GET_XFERTYPE(attr)((attr) & 0x03) == UE_ISOCHRONOUS0x01)
682 ehci_check_itd_intr(sc, xfer);
683 else
684 ehci_check_qh_intr(sc, xfer);
685}
686
687void
688ehci_check_qh_intr(struct ehci_softc *sc, struct usbd_xfer *xfer)
689{
690 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
691 struct ehci_soft_qtd *sqtd, *lsqtd = ex->sqtdend_TD.sqtd.end;
692 uint32_t status;
693
694 KASSERT(ex->sqtdstart != NULL && ex->sqtdend != NULL)((ex->_TD.sqtd.start != ((void *)0) && ex->_TD.
sqtd.end != ((void *)0)) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/usb/ehci.c"
, 694, "ex->sqtdstart != NULL && ex->sqtdend != NULL"
))
;
695
696 usb_syncmem(&lsqtd->dma,
697 lsqtd->offs + offsetof(struct ehci_qtd, qtd_status)__builtin_offsetof(struct ehci_qtd, qtd_status),
698 sizeof(lsqtd->qtd.qtd_status),
699 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
700
701 /*
702 * If the last TD is still active we need to check whether there
703 * is a an error somewhere in the middle, or whether there was a
704 * short packet (SPD and not ACTIVE).
705 */
706 if (letoh32(lsqtd->qtd.qtd_status)((__uint32_t)(lsqtd->qtd.qtd_status)) & EHCI_QTD_ACTIVE0x80) {
707 DPRINTFN(12, ("ehci_check_intr: active ex=%p\n", ex));
708 for (sqtd = ex->sqtdstart_TD.sqtd.start; sqtd != lsqtd; sqtd=sqtd->nextqtd) {
709 usb_syncmem(&sqtd->dma,
710 sqtd->offs + offsetof(struct ehci_qtd, qtd_status)__builtin_offsetof(struct ehci_qtd, qtd_status),
711 sizeof(sqtd->qtd.qtd_status),
712 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
713 status = letoh32(sqtd->qtd.qtd_status)((__uint32_t)(sqtd->qtd.qtd_status));
714 usb_syncmem(&sqtd->dma,
715 sqtd->offs + offsetof(struct ehci_qtd, qtd_status)__builtin_offsetof(struct ehci_qtd, qtd_status),
716 sizeof(sqtd->qtd.qtd_status), BUS_DMASYNC_PREREAD0x01);
717 /* If there's an active QTD the xfer isn't done. */
718 if (status & EHCI_QTD_ACTIVE0x80)
719 break;
720 /* Any kind of error makes the xfer done. */
721 if (status & EHCI_QTD_HALTED0x40)
722 goto done;
723 /* We want short packets, and it is short: it's done */
724 if (EHCI_QTD_GET_BYTES(status)(((status) >> 16) & 0x7fff) != 0)
725 goto done;
726 }
727 DPRINTFN(12, ("ehci_check_intr: ex=%p std=%p still active\n",
728 ex, ex->sqtdstart));
729 usb_syncmem(&lsqtd->dma,
730 lsqtd->offs + offsetof(struct ehci_qtd, qtd_status)__builtin_offsetof(struct ehci_qtd, qtd_status),
731 sizeof(lsqtd->qtd.qtd_status), BUS_DMASYNC_PREREAD0x01);
732 return;
733 }
734 done:
735 TAILQ_REMOVE(&sc->sc_intrhead, ex, inext)do { if (((ex)->inext.tqe_next) != ((void *)0)) (ex)->inext
.tqe_next->inext.tqe_prev = (ex)->inext.tqe_prev; else (
&sc->sc_intrhead)->tqh_last = (ex)->inext.tqe_prev
; *(ex)->inext.tqe_prev = (ex)->inext.tqe_next; ((ex)->
inext.tqe_prev) = ((void *)-1); ((ex)->inext.tqe_next) = (
(void *)-1); } while (0)
;
736 timeout_del(&xfer->timeout_handle);
737 usb_rem_task(xfer->pipe->device, &xfer->abort_task);
738 ehci_idone(xfer);
739}
740
741void
742ehci_check_itd_intr(struct ehci_softc *sc, struct usbd_xfer *xfer)
743{
744 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
745 struct ehci_soft_itd *itd = ex->itdend_TD.itd.end;
746 int i;
747
748 if (xfer != SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first))
749 return;
750
751 KASSERT(ex->itdstart != NULL && ex->itdend != NULL)((ex->_TD.itd.start != ((void *)0) && ex->_TD.itd
.end != ((void *)0)) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/usb/ehci.c"
, 751, "ex->itdstart != NULL && ex->itdend != NULL"
))
;
752
753 /* Check no active transfers in last itd, meaning we're finished */
754 if (xfer->device->speed == USB_SPEED_HIGH3) {
755 usb_syncmem(&itd->dma,
756 itd->offs + offsetof(struct ehci_itd, itd_ctl)__builtin_offsetof(struct ehci_itd, itd_ctl),
757 sizeof(itd->itd.itd_ctl),
758 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
759
760 for (i = 0; i < 8; i++) {
761 if (letoh32(itd->itd.itd_ctl[i])((__uint32_t)(itd->itd.itd_ctl[i])) & EHCI_ITD_ACTIVE0x80000000)
762 return;
763 }
764 } else {
765 usb_syncmem(&itd->dma,
766 itd->offs + offsetof(struct ehci_sitd, sitd_trans)__builtin_offsetof(struct ehci_sitd, sitd_trans),
767 sizeof(itd->sitd.sitd_trans),
768 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
769
770 if (le32toh(itd->sitd.sitd_trans)((__uint32_t)(itd->sitd.sitd_trans)) & EHCI_SITD_ACTIVE0x80)
771 return;
772 }
773
774 /* All descriptor(s) inactive, it's done */
775 TAILQ_REMOVE(&sc->sc_intrhead, ex, inext)do { if (((ex)->inext.tqe_next) != ((void *)0)) (ex)->inext
.tqe_next->inext.tqe_prev = (ex)->inext.tqe_prev; else (
&sc->sc_intrhead)->tqh_last = (ex)->inext.tqe_prev
; *(ex)->inext.tqe_prev = (ex)->inext.tqe_next; ((ex)->
inext.tqe_prev) = ((void *)-1); ((ex)->inext.tqe_next) = (
(void *)-1); } while (0)
;
776 timeout_del(&xfer->timeout_handle);
777 usb_rem_task(xfer->pipe->device, &xfer->abort_task);
778 ehci_isoc_idone(xfer);
779}
780
781void
782ehci_isoc_idone(struct usbd_xfer *xfer)
783{
784 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
785 struct ehci_soft_itd *itd;
786 int i, len, uframes, nframes = 0, actlen = 0;
787 uint32_t status = 0;
788
789 if (xfer->status == USBD_CANCELLED || xfer->status == USBD_TIMEOUT)
790 return;
791
792 if (xfer->device->speed == USB_SPEED_HIGH3) {
793 switch (xfer->pipe->endpoint->edesc->bInterval) {
794 case 0:
795 panic("isoc xfer suddenly has 0 bInterval, invalid");
796 case 1:
797 uframes = 1;
798 break;
799 case 2:
800 uframes = 2;
801 break;
802 case 3:
803 uframes = 4;
804 break;
805 default:
806 uframes = 8;
807 break;
808 }
809
810 for (itd = ex->itdstart_TD.itd.start; itd != NULL((void *)0); itd = itd->xfer_next) {
811 usb_syncmem(&itd->dma,
812 itd->offs + offsetof(struct ehci_itd, itd_ctl)__builtin_offsetof(struct ehci_itd, itd_ctl),
813 sizeof(itd->itd.itd_ctl), BUS_DMASYNC_POSTWRITE0x08 |
814 BUS_DMASYNC_POSTREAD0x02);
815
816 for (i = 0; i < 8; i += uframes) {
817 /* XXX - driver didn't fill in the frame full
818 * of uframes. This leads to scheduling
819 * inefficiencies, but working around
820 * this doubles complexity of tracking
821 * an xfer.
822 */
823 if (nframes >= xfer->nframes)
824 break;
825
826 status = letoh32(itd->itd.itd_ctl[i])((__uint32_t)(itd->itd.itd_ctl[i]));
827 len = EHCI_ITD_GET_LEN(status)(((status) >> 16) & 0xfff);
828 if (EHCI_ITD_GET_STATUS(status)(((status) >> 28) & 0xf) != 0)
829 len = 0; /*No valid data on error*/
830
831 xfer->frlengths[nframes++] = len;
832 actlen += len;
833 }
834 }
835 } else {
836 for (itd = ex->itdstart_TD.itd.start; itd != NULL((void *)0); itd = itd->xfer_next) {
837 usb_syncmem(&itd->dma,
838 itd->offs + offsetof(struct ehci_sitd, sitd_trans)__builtin_offsetof(struct ehci_sitd, sitd_trans),
839 sizeof(itd->sitd.sitd_trans),
840 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
841
842 status = le32toh(itd->sitd.sitd_trans)((__uint32_t)(itd->sitd.sitd_trans));
843 len = EHCI_SITD_GET_LEN(status)(((status) >> 16) & 0x3ff);
844 if (xfer->frlengths[nframes] >= len)
845 len = xfer->frlengths[nframes] - len;
846 else
847 len = 0;
848
849 xfer->frlengths[nframes++] = len;
850 actlen += len;
851 }
852 }
853
854#ifdef DIAGNOSTIC1
855 ex->isdone = 1;
856#endif
857 xfer->actlen = actlen;
858 xfer->status = USBD_NORMAL_COMPLETION;
859
860 usb_syncmem(&xfer->dmabuf, 0, xfer->length,
861 usbd_xfer_isread(xfer) ?
862 BUS_DMASYNC_POSTREAD0x02 : BUS_DMASYNC_POSTWRITE0x08);
863 usb_transfer_complete(xfer);
864}
865
866void
867ehci_idone(struct usbd_xfer *xfer)
868{
869 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
870 struct ehci_soft_qtd *sqtd;
871 u_int32_t status = 0, nstatus = 0;
872 int actlen, cerr;
873
874#ifdef DIAGNOSTIC1
875 {
876 int s = splhigh()splraise(0xd);
877 if (ex->isdone) {
878 splx(s)spllower(s);
879 printf("ehci_idone: ex=%p is done!\n", ex);
880 return;
881 }
882 ex->isdone = 1;
883 splx(s)spllower(s);
884 }
885#endif
886 if (xfer->status == USBD_CANCELLED || xfer->status == USBD_TIMEOUT)
887 return;
888
889 actlen = 0;
890 for (sqtd = ex->sqtdstart_TD.sqtd.start; sqtd != NULL((void *)0); sqtd = sqtd->nextqtd) {
891 usb_syncmem(&sqtd->dma, sqtd->offs, sizeof(sqtd->qtd),
892 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
893 nstatus = letoh32(sqtd->qtd.qtd_status)((__uint32_t)(sqtd->qtd.qtd_status));
894 if (nstatus & EHCI_QTD_ACTIVE0x80)
895 break;
896
897 status = nstatus;
898 /* halt is ok if descriptor is last, and complete */
899 if (sqtd->qtd.qtd_next == htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001)) &&
900 EHCI_QTD_GET_BYTES(status)(((status) >> 16) & 0x7fff) == 0)
901 status &= ~EHCI_QTD_HALTED0x40;
902 if (EHCI_QTD_GET_PID(status)(((status) >> 8) & 0x3) != EHCI_QTD_PID_SETUP0x2)
903 actlen += sqtd->len - EHCI_QTD_GET_BYTES(status)(((status) >> 16) & 0x7fff);
904 }
905
906 cerr = EHCI_QTD_GET_CERR(status)(((status) >> 10) & 0x3);
907 DPRINTFN(/*10*/2, ("ehci_idone: len=%d, actlen=%d, cerr=%d, "
908 "status=0x%x\n", xfer->length, actlen, cerr, status));
909 xfer->actlen = actlen;
910 if ((status & EHCI_QTD_HALTED0x40) != 0) {
911 if ((status & EHCI_QTD_BABBLE0x10) == 0 && cerr > 0)
912 xfer->status = USBD_STALLED;
913 else
914 xfer->status = USBD_IOERROR; /* more info XXX */
915 } else
916 xfer->status = USBD_NORMAL_COMPLETION;
917
918 if (xfer->actlen)
919 usb_syncmem(&xfer->dmabuf, 0, xfer->actlen,
920 usbd_xfer_isread(xfer) ?
921 BUS_DMASYNC_POSTREAD0x02 : BUS_DMASYNC_POSTWRITE0x08);
922 usb_transfer_complete(xfer);
923 DPRINTFN(/*12*/2, ("ehci_idone: ex=%p done\n", ex));
924}
925
926void
927ehci_poll(struct usbd_bus *bus)
928{
929 struct ehci_softc *sc = (struct ehci_softc *)bus;
930
931 if (EOREAD4(sc, EHCI_USBSTS)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x04))))
& sc->sc_eintrs)
932 ehci_intr1(sc);
933}
934
935int
936ehci_detach(struct device *self, int flags)
937{
938 struct ehci_softc *sc = (struct ehci_softc *)self;
939 int rv;
940
941 rv = config_detach_children(self, flags);
942 if (rv != 0)
943 return (rv);
944
945 timeout_del(&sc->sc_tmo_intrlist);
946
947 ehci_reset(sc);
948
949 usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */
950
951 free(sc->sc_softitds, M_USBHC103,
952 sc->sc_flsize * sizeof(struct ehci_soft_itd *));
953 usb_freemem(&sc->sc_bus, &sc->sc_fldma);
954 /* XXX free other data structures XXX */
955
956 return (rv);
957}
958
959
960int
961ehci_activate(struct device *self, int act)
962{
963 struct ehci_softc *sc = (struct ehci_softc *)self;
964 u_int32_t cmd, hcr, cparams;
965 int i, rv = 0;
966
967 switch (act) {
1
Control jumps to 'case 4:' at line 1015
968 case DVACT_SUSPEND3:
969 rv = config_activate_children(self, act);
970
971#ifdef DIAGNOSTIC1
972 if (!TAILQ_EMPTY(&sc->sc_intrhead)(((&sc->sc_intrhead)->tqh_first) == ((void *)0))) {
973 printf("%s: interrupt list not empty\n",
974 sc->sc_bus.bdev.dv_xname);
975 return (-1);
976 }
977#endif
978
979 sc->sc_bus.use_polling++;
980
981 for (i = 1; i <= sc->sc_noport; i++) {
982 cmd = EOREAD4(sc, EHCI_PORTSC(i))(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
((0x40+4*(i))))))
;
983 if ((cmd & (EHCI_PS_PO0x00002000|EHCI_PS_PE0x00000004)) == EHCI_PS_PE0x00000004)
984 EOWRITE4(sc, EHCI_PORTSC(i),(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+((0x40+4*(i)))), ((cmd | 0x00000080))))
985 cmd | EHCI_PS_SUSP)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+((0x40+4*(i)))), ((cmd | 0x00000080))))
;
986 }
987
988 /*
989 * First tell the host to stop processing Asynchronous
990 * and Periodic schedules.
991 */
992 cmd = EOREAD4(sc, EHCI_USBCMD)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x00))))
& ~(EHCI_CMD_ASE0x00000020 | EHCI_CMD_PSE0x00000010);
993 EOWRITE4(sc, EHCI_USBCMD, cmd)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((cmd))))
;
994 for (i = 0; i < 100; i++) {
995 usb_delay_ms(&sc->sc_bus, 1);
996 hcr = EOREAD4(sc, EHCI_USBSTS)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x04))))
&
997 (EHCI_STS_ASS0x00008000 | EHCI_STS_PSS0x00004000);
998 if (hcr == 0)
999 break;
1000 }
1001 if (hcr != 0)
1002 printf("%s: disable schedules timeout\n",
1003 sc->sc_bus.bdev.dv_xname);
1004
1005 /*
1006 * Then reset the host as if it was a shutdown.
1007 *
1008 * All USB devices are disconnected/reconnected during
1009 * a suspend/resume cycle so keep it simple.
1010 */
1011 ehci_reset(sc);
1012
1013 sc->sc_bus.use_polling--;
1014 break;
1015 case DVACT_RESUME4:
1016 sc->sc_bus.use_polling++;
1017
1018 ehci_reset(sc);
2
Calling 'ehci_reset'
1019
1020 cparams = EREAD4(sc, EHCI_HCCPARAMS)(((sc)->iot)->read_4(((sc)->ioh), ((0x08))));
1021 /* MUST clear segment register if 64 bit capable. */
1022 if (EHCI_HCC_64BIT(cparams)((cparams) & 0x1))
1023 EWRITE4(sc, EHCI_CTRLDSSEGMENT, 0)(((sc)->iot)->write_4(((sc)->ioh), ((0x10)), ((0))));
1024
1025 EOWRITE4(sc, EHCI_PERIODICLISTBASE, DMAADDR(&sc->sc_fldma, 0))(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x14)), ((((&sc->sc_fldma)->block->map->dm_segs
[0].ds_addr + (&sc->sc_fldma)->offs + (0))))))
;
1026 EOWRITE4(sc, EHCI_ASYNCLISTADDR,(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x18)), ((sc->sc_async_head->physaddr | 0x2))))
1027 sc->sc_async_head->physaddr | EHCI_LINK_QH)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x18)), ((sc->sc_async_head->physaddr | 0x2))))
;
1028
1029 hcr = 0;
1030 for (i = 1; i <= sc->sc_noport; i++) {
1031 cmd = EOREAD4(sc, EHCI_PORTSC(i))(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
((0x40+4*(i))))))
;
1032 if ((cmd & (EHCI_PS_PO0x00002000|EHCI_PS_SUSP0x00000080)) == EHCI_PS_SUSP0x00000080) {
1033 EOWRITE4(sc, EHCI_PORTSC(i), cmd | EHCI_PS_FPR)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+((0x40+4*(i)))), ((cmd | 0x00000040))))
;
1034 hcr = 1;
1035 }
1036 }
1037
1038 if (hcr) {
1039 usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT50);
1040 for (i = 1; i <= sc->sc_noport; i++) {
1041 cmd = EOREAD4(sc, EHCI_PORTSC(i))(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
((0x40+4*(i))))))
;
1042 if ((cmd & (EHCI_PS_PO0x00002000|EHCI_PS_SUSP0x00000080)) ==
1043 EHCI_PS_SUSP0x00000080)
1044 EOWRITE4(sc, EHCI_PORTSC(i),(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+((0x40+4*(i)))), ((cmd & ~0x00000040))))
1045 cmd & ~EHCI_PS_FPR)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+((0x40+4*(i)))), ((cmd & ~0x00000040))))
;
1046 }
1047 }
1048
1049 /* Turn on controller */
1050 EOWRITE4(sc, EHCI_USBCMD,(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
1051 EHCI_CMD_ITC_2 | /* 2 microframes interrupt delay */(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
1052 (EOREAD4(sc, EHCI_USBCMD) & EHCI_CMD_FLS_M) |(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
1053 EHCI_CMD_ASE |(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
1054 EHCI_CMD_PSE |(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
1055 EHCI_CMD_RS)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00020000 | ((((sc)->iot)->read_4(((sc)->
ioh), ((sc)->sc_offs+(0x00)))) & 0x0000000c) | 0x00000020
| 0x00000010 | 0x00000001))))
;
1056
1057 /* Take over port ownership */
1058 EOWRITE4(sc, EHCI_CONFIGFLAG, EHCI_CONF_CF)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x40)), ((0x00000001))))
;
1059 for (i = 0; i < 100; i++) {
1060 usb_delay_ms(&sc->sc_bus, 1);
1061 hcr = EOREAD4(sc, EHCI_USBSTS)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x04))))
& EHCI_STS_HCH0x00001000;
1062 if (!hcr)
1063 break;
1064 }
1065
1066 if (hcr) {
1067 printf("%s: run timeout\n", sc->sc_bus.bdev.dv_xname);
1068 /* XXX should we bail here? */
1069 }
1070
1071 EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x08)), ((sc->sc_eintrs))))
;
1072
1073 usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT50);
1074
1075 sc->sc_bus.use_polling--;
1076 rv = config_activate_children(self, act);
1077 break;
1078 case DVACT_POWERDOWN6:
1079 rv = config_activate_children(self, act);
1080 ehci_reset(sc);
1081 break;
1082 default:
1083 rv = config_activate_children(self, act);
1084 break;
1085 }
1086 return (rv);
1087}
1088
1089usbd_status
1090ehci_reset(struct ehci_softc *sc)
1091{
1092 u_int32_t hcr, usbmode;
3
'usbmode' declared without an initial value
1093 int i;
1094
1095 EOWRITE4(sc, EHCI_USBCMD, 0)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0))))
; /* Halt controller */
1096 for (i = 0; i < 100; i++) {
4
Loop condition is true. Entering loop body
1097 usb_delay_ms(&sc->sc_bus, 1);
1098 hcr = EOREAD4(sc, EHCI_USBSTS)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x04))))
& EHCI_STS_HCH0x00001000;
1099 if (hcr)
5
Assuming 'hcr' is not equal to 0
6
Taking true branch
1100 break;
1101 }
1102
1103 if (!hcr
7.1
'hcr' is not equal to 0
)
7
Execution continues on line 1103
8
Taking false branch
1104 printf("%s: halt timeout\n", sc->sc_bus.bdev.dv_xname);
1105
1106 if (sc->sc_flags & EHCIF_USBMODE0x04)
9
Assuming the condition is false
10
Taking false branch
1107 usbmode = EOREAD4(sc, EHCI_USBMODE)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x68))))
;
1108
1109 EOWRITE4(sc, EHCI_USBCMD, EHCI_CMD_HCRESET)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), ((0x00000002))))
;
1110 for (i = 0; i < 100; i++) {
11
Loop condition is true. Entering loop body
1111 usb_delay_ms(&sc->sc_bus, 1);
1112 hcr = EOREAD4(sc, EHCI_USBCMD)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x00))))
& EHCI_CMD_HCRESET0x00000002;
1113 if (!hcr)
12
Assuming 'hcr' is 0
13
Taking true branch
1114 break;
1115 }
1116
1117 if (hcr
14.1
'hcr' is 0
) {
14
Execution continues on line 1117
15
Taking false branch
1118 printf("%s: reset timeout\n", sc->sc_bus.bdev.dv_xname);
1119 return (USBD_IOERROR);
1120 }
1121
1122 if (sc->sc_flags & EHCIF_USBMODE0x04)
16
Assuming the condition is true
17
Taking true branch
1123 EOWRITE4(sc, EHCI_USBMODE, usbmode)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x68)), ((usbmode))))
;
18
3rd function call argument is an uninitialized value
1124
1125 return (USBD_NORMAL_COMPLETION);
1126}
1127
1128struct usbd_xfer *
1129ehci_allocx(struct usbd_bus *bus)
1130{
1131 struct ehci_xfer *ex;
1132
1133 ex = pool_get(ehcixfer, PR_NOWAIT0x0002 | PR_ZERO0x0008);
1134#ifdef DIAGNOSTIC1
1135 if (ex != NULL((void *)0))
1136 ex->isdone = 1;
1137#endif
1138 return ((struct usbd_xfer *)ex);
1139}
1140
1141void
1142ehci_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
1143{
1144 struct ehci_xfer *ex = (struct ehci_xfer*)xfer;
1145
1146#ifdef DIAGNOSTIC1
1147 if (!ex->isdone) {
1148 printf("%s: !isdone\n", __func__);
1149 return;
1150 }
1151#endif
1152 pool_put(ehcixfer, ex);
1153}
1154
1155void
1156ehci_device_clear_toggle(struct usbd_pipe *pipe)
1157{
1158 struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
1159
1160#ifdef DIAGNOSTIC1
1161 if ((epipe->sqh->qh.qh_qtd.qtd_status & htole32(EHCI_QTD_ACTIVE)((__uint32_t)(0x80))) != 0)
1162 printf("%s: queue active\n", __func__);
1163#endif
1164 epipe->sqh->qh.qh_qtd.qtd_status &= htole32(~EHCI_QTD_TOGGLE_MASK)((__uint32_t)(~0x80000000));
1165}
1166
1167#ifdef EHCI_DEBUG
1168void
1169ehci_dump_regs(struct ehci_softc *sc)
1170{
1171 int i;
1172
1173 printf("cmd=0x%08x, sts=0x%08x, ien=0x%08x\n",
1174 EOREAD4(sc, EHCI_USBCMD)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x00))))
,
1175 EOREAD4(sc, EHCI_USBSTS)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x04))))
,
1176 EOREAD4(sc, EHCI_USBINTR)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x08))))
);
1177 printf("frindex=0x%08x ctrdsegm=0x%08x periodic=0x%08x async=0x%08x\n",
1178 EOREAD4(sc, EHCI_FRINDEX)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x0c))))
,
1179 EOREAD4(sc, EHCI_CTRLDSSEGMENT)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x10))))
,
1180 EOREAD4(sc, EHCI_PERIODICLISTBASE)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x14))))
,
1181 EOREAD4(sc, EHCI_ASYNCLISTADDR)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x18))))
);
1182 for (i = 1; i <= sc->sc_noport; i++)
1183 printf("port %d status=0x%08x\n", i,
1184 EOREAD4(sc, EHCI_PORTSC(i))(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
((0x40+4*(i))))))
);
1185}
1186
1187/*
1188 * Unused function - this is meant to be called from a kernel
1189 * debugger.
1190 */
1191void
1192ehci_dump(void)
1193{
1194 ehci_dump_regs(theehci);
1195}
1196
1197void
1198ehci_dump_link(ehci_link_t link, int type)
1199{
1200 link = letoh32(link)((__uint32_t)(link));
1201 printf("0x%08x", link);
1202 if (link & EHCI_LINK_TERMINATE0x00000001)
1203 printf("<T>");
1204 else {
1205 printf("<");
1206 if (type) {
1207 switch (EHCI_LINK_TYPE(link)((link) & 0x00000006)) {
1208 case EHCI_LINK_ITD0x0:
1209 printf("ITD");
1210 break;
1211 case EHCI_LINK_QH0x2:
1212 printf("QH");
1213 break;
1214 case EHCI_LINK_SITD0x4:
1215 printf("SITD");
1216 break;
1217 case EHCI_LINK_FSTN0x6:
1218 printf("FSTN");
1219 break;
1220 }
1221 }
1222 printf(">");
1223 }
1224}
1225
1226void
1227ehci_dump_sqtds(struct ehci_soft_qtd *sqtd)
1228{
1229 int i;
1230 u_int32_t stop;
1231
1232 stop = 0;
1233 for (i = 0; sqtd && i < 20 && !stop; sqtd = sqtd->nextqtd, i++) {
1234 ehci_dump_sqtd(sqtd);
1235 usb_syncmem(&sqtd->dma,
1236 sqtd->offs + offsetof(struct ehci_qtd, qtd_next)__builtin_offsetof(struct ehci_qtd, qtd_next),
1237 sizeof(sqtd->qtd),
1238 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
1239 stop = sqtd->qtd.qtd_next & htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
1240 usb_syncmem(&sqtd->dma,
1241 sqtd->offs + offsetof(struct ehci_qtd, qtd_next)__builtin_offsetof(struct ehci_qtd, qtd_next),
1242 sizeof(sqtd->qtd), BUS_DMASYNC_PREREAD0x01);
1243 }
1244 if (!stop)
1245 printf("dump aborted, too many TDs\n");
1246}
1247
1248void
1249ehci_dump_sqtd(struct ehci_soft_qtd *sqtd)
1250{
1251 usb_syncmem(&sqtd->dma, sqtd->offs,
1252 sizeof(sqtd->qtd), BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
1253 printf("QTD(%p) at 0x%08x:\n", sqtd, sqtd->physaddr);
1254 ehci_dump_qtd(&sqtd->qtd);
1255 usb_syncmem(&sqtd->dma, sqtd->offs,
1256 sizeof(sqtd->qtd), BUS_DMASYNC_PREREAD0x01);
1257}
1258
1259void
1260ehci_dump_qtd(struct ehci_qtd *qtd)
1261{
1262 u_int32_t s;
1263 char sbuf[128];
1264
1265 printf(" next="); ehci_dump_link(qtd->qtd_next, 0);
1266 printf(" altnext="); ehci_dump_link(qtd->qtd_altnext, 0);
1267 printf("\n");
1268 s = letoh32(qtd->qtd_status)((__uint32_t)(qtd->qtd_status));
1269 bitmask_snprintf(EHCI_QTD_GET_STATUS(s)(((s) >> 0) & 0xff), "\20\10ACTIVE\7HALTED"
1270 "\6BUFERR\5BABBLE\4XACTERR\3MISSED\2SPLIT\1PING",
1271 sbuf, sizeof(sbuf));
1272 printf(" status=0x%08x: toggle=%d bytes=0x%x ioc=%d c_page=0x%x\n",
1273 s, EHCI_QTD_GET_TOGGLE(s)(((s) >> 31) & 0x1), EHCI_QTD_GET_BYTES(s)(((s) >> 16) & 0x7fff),
1274 EHCI_QTD_GET_IOC(s)(((s) >> 15) & 0x1), EHCI_QTD_GET_C_PAGE(s)(((s) >> 12) & 0x7));
1275 printf(" cerr=%d pid=%d stat=0x%s\n", EHCI_QTD_GET_CERR(s)(((s) >> 10) & 0x3),
1276 EHCI_QTD_GET_PID(s)(((s) >> 8) & 0x3), sbuf);
1277 for (s = 0; s < 5; s++)
1278 printf(" buffer[%d]=0x%08x\n", s, letoh32(qtd->qtd_buffer[s])((__uint32_t)(qtd->qtd_buffer[s])));
1279}
1280
1281void
1282ehci_dump_sqh(struct ehci_soft_qh *sqh)
1283{
1284 struct ehci_qh *qh = &sqh->qh;
1285 u_int32_t endp, endphub;
1286
1287 usb_syncmem(&sqh->dma, sqh->offs,
1288 sizeof(sqh->qh), BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
1289 printf("QH(%p) at 0x%08x:\n", sqh, sqh->physaddr);
1290 printf(" link="); ehci_dump_link(qh->qh_link, 1); printf("\n");
1291 endp = letoh32(qh->qh_endp)((__uint32_t)(qh->qh_endp));
1292 printf(" endp=0x%08x\n", endp);
1293 printf(" addr=0x%02x inact=%d endpt=%d eps=%d dtc=%d hrecl=%d\n",
1294 EHCI_QH_GET_ADDR(endp)(((endp) >> 0) & 0x7f), EHCI_QH_GET_INACT(endp)(((endp) >> 7) & 0x01),
1295 EHCI_QH_GET_ENDPT(endp)(((endp) >> 8) & 0x0f), EHCI_QH_GET_EPS(endp)(((endp) >> 12) & 0x03),
1296 EHCI_QH_GET_DTC(endp)(((endp) >> 14) & 0x01), EHCI_QH_GET_HRECL(endp)(((endp) >> 15) & 0x01));
1297 printf(" mpl=0x%x ctl=%d nrl=%d\n",
1298 EHCI_QH_GET_MPL(endp)(((endp) >> 16) & 0x7ff), EHCI_QH_GET_CTL(endp)(((endp) >> 27) & 0x01),
1299 EHCI_QH_GET_NRL(endp)(((endp) >> 28) & 0x0f));
1300 endphub = letoh32(qh->qh_endphub)((__uint32_t)(qh->qh_endphub));
1301 printf(" endphub=0x%08x\n", endphub);
1302 printf(" smask=0x%02x cmask=0x%02x huba=0x%02x port=%d mult=%d\n",
1303 EHCI_QH_GET_SMASK(endphub)(((endphub) >> 0) & 0xff), EHCI_QH_GET_CMASK(endphub)(((endphub) >> 8) & 0xff),
1304 EHCI_QH_GET_HUBA(endphub)(((endphub) >> 16) & 0x7f), EHCI_QH_GET_PORT(endphub)(((endphub) >> 23) & 0x7f),
1305 EHCI_QH_GET_MULT(endphub)(((endphub) >> 30) & 0x03));
1306 printf(" curqtd="); ehci_dump_link(qh->qh_curqtd, 0); printf("\n");
1307 printf("Overlay qTD:\n");
1308 ehci_dump_qtd(&qh->qh_qtd);
1309 usb_syncmem(&sqh->dma, sqh->offs,
1310 sizeof(sqh->qh), BUS_DMASYNC_PREREAD0x01);
1311}
1312
1313#if notyet
1314void
1315ehci_dump_itd(struct ehci_soft_itd *itd)
1316{
1317 ehci_isoc_trans_t t;
1318 ehci_isoc_bufr_ptr_t b, b2, b3;
1319 int i;
1320
1321 printf("ITD: next phys=%X\n", itd->itd.itd_next);
1322
1323 for (i = 0; i < 8; i++) {
1324 t = letoh32(itd->itd.itd_ctl[i])((__uint32_t)(itd->itd.itd_ctl[i]));
1325 printf("ITDctl %d: stat=%X len=%X ioc=%X pg=%X offs=%X\n", i,
1326 EHCI_ITD_GET_STATUS(t)(((t) >> 28) & 0xf), EHCI_ITD_GET_LEN(t)(((t) >> 16) & 0xfff),
1327 EHCI_ITD_GET_IOC(t)(((t) >> 15) & 1), EHCI_ITD_GET_PG(t)(((t) >> 12) & 0x7),
1328 EHCI_ITD_GET_OFFS(t)(((t) >> 0) & 0xfff));
1329 }
1330 printf("ITDbufr: ");
1331 for (i = 0; i < 7; i++)
1332 printf("%X,", EHCI_ITD_GET_BPTR(letoh32(itd->itd.itd_bufr[i])((__uint32_t)(itd->itd.itd_bufr[i]))));
1333
1334 b = letoh32(itd->itd.itd_bufr[0])((__uint32_t)(itd->itd.itd_bufr[0]));
1335 b2 = letoh32(itd->itd.itd_bufr[1])((__uint32_t)(itd->itd.itd_bufr[1]));
1336 b3 = letoh32(itd->itd.itd_bufr[2])((__uint32_t)(itd->itd.itd_bufr[2]));
1337 printf("\nep=%X daddr=%X dir=%d maxpkt=%X multi=%X\n",
1338 EHCI_ITD_GET_EP(b), EHCI_ITD_GET_DADDR(b)((b) & 0x7f), EHCI_ITD_GET_DIR(b2)(((b2) >> 11) & 1),
1339 EHCI_ITD_GET_MAXPKT(b2)((b2) & 0x7ff), EHCI_ITD_GET_MULTI(b3)((b3) & 0x3));
1340}
1341#endif
1342
1343#ifdef DIAGNOSTIC1
1344void
1345ehci_dump_exfer(struct ehci_xfer *ex)
1346{
1347 printf("ehci_dump_exfer: ex=%p sqtdstart=%p end=%p itdstart=%p end=%p "
1348 "isdone=%d\n", ex, ex->sqtdstart_TD.sqtd.start, ex->sqtdend_TD.sqtd.end, ex->itdstart_TD.itd.start,
1349 ex->itdend_TD.itd.end, ex->isdone);
1350}
1351#endif
1352
1353#endif /* EHCI_DEBUG */
1354
1355usbd_status
1356ehci_open(struct usbd_pipe *pipe)
1357{
1358 struct usbd_device *dev = pipe->device;
1359 struct ehci_softc *sc = (struct ehci_softc *)dev->bus;
1360 usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
1361 u_int8_t addr = dev->address;
1362 u_int8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03);
1363 struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
1364 struct ehci_soft_qh *sqh;
1365 usbd_status err;
1366 int s;
1367 int ival, speed, naks;
1368 int hshubaddr, hshubport;
1369
1370 DPRINTFN(1, ("ehci_open: pipe=%p, addr=%d, endpt=%d\n",
1371 pipe, addr, ed->bEndpointAddress));
1372
1373 if (sc->sc_bus.dying)
1374 return (USBD_IOERROR);
1375
1376 if (dev->myhsport) {
1377 hshubaddr = dev->myhsport->parent->address;
1378 hshubport = dev->myhsport->portno;
1379 } else {
1380 hshubaddr = 0;
1381 hshubport = 0;
1382 }
1383
1384 /* Root Hub */
1385 if (pipe->device->depth == 0) {
1386 switch (ed->bEndpointAddress) {
1387 case USB_CONTROL_ENDPOINT0:
1388 pipe->methods = &ehci_root_ctrl_methods;
1389 break;
1390 case UE_DIR_IN0x80 | EHCI_INTR_ENDPT1:
1391 pipe->methods = &ehci_root_intr_methods;
1392 break;
1393 default:
1394 return (USBD_INVAL);
1395 }
1396 return (USBD_NORMAL_COMPLETION);
1397 }
1398
1399 /* XXX All this stuff is only valid for async. */
1400 switch (dev->speed) {
1401 case USB_SPEED_LOW1:
1402 speed = EHCI_QH_SPEED_LOW0x1;
1403 break;
1404 case USB_SPEED_FULL2:
1405 speed = EHCI_QH_SPEED_FULL0x0;
1406 break;
1407 case USB_SPEED_HIGH3:
1408 speed = EHCI_QH_SPEED_HIGH0x2;
1409 break;
1410 default:
1411 panic("ehci_open: bad device speed %d", dev->speed);
1412 }
1413
1414 /*
1415 * NAK reload count:
1416 * must be zero with using periodic transfer.
1417 * Linux 4.20's driver (ehci-q.c) sets 4, we use same value.
1418 */
1419 naks = ((xfertype == UE_CONTROL0x00) || (xfertype == UE_BULK0x02)) ? 4 : 0;
1420
1421 /* Allocate sqh for everything, save isoc xfers */
1422 if (xfertype != UE_ISOCHRONOUS0x01) {
1423 sqh = ehci_alloc_sqh(sc);
1424 if (sqh == NULL((void *)0))
1425 return (USBD_NOMEM);
1426 /* qh_link filled when the QH is added */
1427 sqh->qh.qh_endp = htole32(((__uint32_t)((addr) | ((((ed->bEndpointAddress) & 0x0f
)) << 8) | ((speed) << 12) | (xfertype == 0x00 ? 0x00004000
: 0) | (((*(u_int16_t *)(ed->wMaxPacketSize))) << 16
) | (speed != 0x2 && xfertype == 0x00 ? 0x08000000 : 0
) | ((naks) << 28)))
1428 EHCI_QH_SET_ADDR(addr) |((__uint32_t)((addr) | ((((ed->bEndpointAddress) & 0x0f
)) << 8) | ((speed) << 12) | (xfertype == 0x00 ? 0x00004000
: 0) | (((*(u_int16_t *)(ed->wMaxPacketSize))) << 16
) | (speed != 0x2 && xfertype == 0x00 ? 0x08000000 : 0
) | ((naks) << 28)))
1429 EHCI_QH_SET_ENDPT(UE_GET_ADDR(ed->bEndpointAddress)) |((__uint32_t)((addr) | ((((ed->bEndpointAddress) & 0x0f
)) << 8) | ((speed) << 12) | (xfertype == 0x00 ? 0x00004000
: 0) | (((*(u_int16_t *)(ed->wMaxPacketSize))) << 16
) | (speed != 0x2 && xfertype == 0x00 ? 0x08000000 : 0
) | ((naks) << 28)))
1430 EHCI_QH_SET_EPS(speed) |((__uint32_t)((addr) | ((((ed->bEndpointAddress) & 0x0f
)) << 8) | ((speed) << 12) | (xfertype == 0x00 ? 0x00004000
: 0) | (((*(u_int16_t *)(ed->wMaxPacketSize))) << 16
) | (speed != 0x2 && xfertype == 0x00 ? 0x08000000 : 0
) | ((naks) << 28)))
1431 (xfertype == UE_CONTROL ? EHCI_QH_DTC : 0) |((__uint32_t)((addr) | ((((ed->bEndpointAddress) & 0x0f
)) << 8) | ((speed) << 12) | (xfertype == 0x00 ? 0x00004000
: 0) | (((*(u_int16_t *)(ed->wMaxPacketSize))) << 16
) | (speed != 0x2 && xfertype == 0x00 ? 0x08000000 : 0
) | ((naks) << 28)))
1432 EHCI_QH_SET_MPL(UGETW(ed->wMaxPacketSize)) |((__uint32_t)((addr) | ((((ed->bEndpointAddress) & 0x0f
)) << 8) | ((speed) << 12) | (xfertype == 0x00 ? 0x00004000
: 0) | (((*(u_int16_t *)(ed->wMaxPacketSize))) << 16
) | (speed != 0x2 && xfertype == 0x00 ? 0x08000000 : 0
) | ((naks) << 28)))
1433 (speed != EHCI_QH_SPEED_HIGH && xfertype == UE_CONTROL ?((__uint32_t)((addr) | ((((ed->bEndpointAddress) & 0x0f
)) << 8) | ((speed) << 12) | (xfertype == 0x00 ? 0x00004000
: 0) | (((*(u_int16_t *)(ed->wMaxPacketSize))) << 16
) | (speed != 0x2 && xfertype == 0x00 ? 0x08000000 : 0
) | ((naks) << 28)))
1434 EHCI_QH_CTL : 0) |((__uint32_t)((addr) | ((((ed->bEndpointAddress) & 0x0f
)) << 8) | ((speed) << 12) | (xfertype == 0x00 ? 0x00004000
: 0) | (((*(u_int16_t *)(ed->wMaxPacketSize))) << 16
) | (speed != 0x2 && xfertype == 0x00 ? 0x08000000 : 0
) | ((naks) << 28)))
1435 EHCI_QH_SET_NRL(naks)((__uint32_t)((addr) | ((((ed->bEndpointAddress) & 0x0f
)) << 8) | ((speed) << 12) | (xfertype == 0x00 ? 0x00004000
: 0) | (((*(u_int16_t *)(ed->wMaxPacketSize))) << 16
) | (speed != 0x2 && xfertype == 0x00 ? 0x08000000 : 0
) | ((naks) << 28)))
1436 )((__uint32_t)((addr) | ((((ed->bEndpointAddress) & 0x0f
)) << 8) | ((speed) << 12) | (xfertype == 0x00 ? 0x00004000
: 0) | (((*(u_int16_t *)(ed->wMaxPacketSize))) << 16
) | (speed != 0x2 && xfertype == 0x00 ? 0x08000000 : 0
) | ((naks) << 28)))
;
1437 /*
1438 * To reduce conflict with split isochronous transfer,
1439 * schedule (split) interrupt transfer at latter half of
1440 * 1ms frame:
1441 *
1442 * |<-------------- H-Frame -------------->|
1443 * .H0 :H1 H2 H3 H4 H5 H6 H7 .H0" :H1"
1444 * . : . :
1445 * [HS] . : SS CS CS' CS" . :
1446 * [FS/LS] . : |<== >>>> >>>| . :
1447 * . : . :
1448 * .B7' :B0 B1 B2 B3 B4 B5 B6 .B7 :B0"
1449 * |<-------------- B-Frame -------------->|
1450 *
1451 */
1452 sqh->qh.qh_endphub = htole32(((__uint32_t)(((1) << 30) | ((xfertype == 0x03 ? 0x08 :
0) << 0)))
1453 EHCI_QH_SET_MULT(1) |((__uint32_t)(((1) << 30) | ((xfertype == 0x03 ? 0x08 :
0) << 0)))
1454 EHCI_QH_SET_SMASK(xfertype == UE_INTERRUPT ? 0x08 : 0)((__uint32_t)(((1) << 30) | ((xfertype == 0x03 ? 0x08 :
0) << 0)))
1455 )((__uint32_t)(((1) << 30) | ((xfertype == 0x03 ? 0x08 :
0) << 0)))
;
1456 if (speed != EHCI_QH_SPEED_HIGH0x2) {
1457 sqh->qh.qh_endphub |= htole32(((__uint32_t)(((hshubaddr) << 16) | ((hshubport) <<
23) | ((0xe0) << 8)))
1458 EHCI_QH_SET_HUBA(hshubaddr) |((__uint32_t)(((hshubaddr) << 16) | ((hshubport) <<
23) | ((0xe0) << 8)))
1459 EHCI_QH_SET_PORT(hshubport) |((__uint32_t)(((hshubaddr) << 16) | ((hshubport) <<
23) | ((0xe0) << 8)))
1460 EHCI_QH_SET_CMASK(0xe0)((__uint32_t)(((hshubaddr) << 16) | ((hshubport) <<
23) | ((0xe0) << 8)))
1461 )((__uint32_t)(((hshubaddr) << 16) | ((hshubport) <<
23) | ((0xe0) << 8)))
;
1462 }
1463 sqh->qh.qh_curqtd = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
1464 /* Fill the overlay qTD */
1465 sqh->qh.qh_qtd.qtd_next = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
1466 sqh->qh.qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
1467 sqh->qh.qh_qtd.qtd_status =
1468 htole32(EHCI_QTD_SET_TOGGLE(pipe->endpoint->savedtoggle))((__uint32_t)(((pipe->endpoint->savedtoggle) << 31
)))
;
1469
1470 usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
1471 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
1472 epipe->sqh = sqh;
1473 } /*xfertype == UE_ISOC*/
1474
1475 switch (xfertype) {
1476 case UE_CONTROL0x00:
1477 err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t),
1478 0, USB_DMA_COHERENT(1 << 0), &epipe->u.ctl.reqdma);
1479 if (err) {
1480 ehci_free_sqh(sc, sqh);
1481 return (err);
1482 }
1483 pipe->methods = &ehci_device_ctrl_methods;
1484 s = splusb()splraise(0x2);
1485 ehci_add_qh(sqh, sc->sc_async_head);
1486 splx(s)spllower(s);
1487 break;
1488 case UE_BULK0x02:
1489 pipe->methods = &ehci_device_bulk_methods;
1490 s = splusb()splraise(0x2);
1491 ehci_add_qh(sqh, sc->sc_async_head);
1492 splx(s)spllower(s);
1493 break;
1494 case UE_INTERRUPT0x03:
1495 pipe->methods = &ehci_device_intr_methods;
1496 ival = pipe->interval;
1497 if (ival == USBD_DEFAULT_INTERVAL(-1))
1498 ival = ed->bInterval;
1499 s = splusb()splraise(0x2);
1500 err = ehci_device_setintr(sc, sqh, ival);
1501 splx(s)spllower(s);
1502 return (err);
1503 case UE_ISOCHRONOUS0x01:
1504 switch (speed) {
1505 case EHCI_QH_SPEED_HIGH0x2:
1506 case EHCI_QH_SPEED_FULL0x0:
1507 pipe->methods = &ehci_device_isoc_methods;
1508 break;
1509 case EHCI_QH_SPEED_LOW0x1:
1510 default:
1511 return (USBD_INVAL);
1512 }
1513 /* Spec page 271 says intervals > 16 are invalid */
1514 if (ed->bInterval == 0 || ed->bInterval > 16) {
1515 printf("ehci: opening pipe with invalid bInterval\n");
1516 return (USBD_INVAL);
1517 }
1518 if (UGETW(ed->wMaxPacketSize)(*(u_int16_t *)(ed->wMaxPacketSize)) == 0) {
1519 printf("ehci: zero length endpoint open request\n");
1520 return (USBD_INVAL);
1521 }
1522 epipe->u.isoc.next_frame = 0;
1523 epipe->u.isoc.cur_xfers = 0;
1524 break;
1525 default:
1526 DPRINTF(("ehci: bad xfer type %d\n", xfertype));
1527 return (USBD_INVAL);
1528 }
1529 return (USBD_NORMAL_COMPLETION);
1530}
1531
1532/*
1533 * Add an ED to the schedule. Called at splusb().
1534 * If in the async schedule, it will always have a next.
1535 * If in the intr schedule it may not.
1536 */
1537void
1538ehci_add_qh(struct ehci_soft_qh *sqh, struct ehci_soft_qh *head)
1539{
1540 splsoftassert(IPL_SOFTUSB)do { if (splassert_ctl > 0) { splassert_check(0x2, __func__
); } } while (0)
;
1541
1542 usb_syncmem(&head->dma, head->offs + offsetof(struct ehci_qh, qh_link)__builtin_offsetof(struct ehci_qh, qh_link),
1543 sizeof(head->qh.qh_link), BUS_DMASYNC_POSTWRITE0x08);
1544 sqh->next = head->next;
1545 sqh->prev = head;
1546 sqh->qh.qh_link = head->qh.qh_link;
1547 usb_syncmem(&sqh->dma, sqh->offs + offsetof(struct ehci_qh, qh_link)__builtin_offsetof(struct ehci_qh, qh_link),
1548 sizeof(sqh->qh.qh_link), BUS_DMASYNC_PREWRITE0x04);
1549 head->next = sqh;
1550 if (sqh->next)
1551 sqh->next->prev = sqh;
1552 head->qh.qh_link = htole32(sqh->physaddr | EHCI_LINK_QH)((__uint32_t)(sqh->physaddr | 0x2));
1553 usb_syncmem(&head->dma, head->offs + offsetof(struct ehci_qh, qh_link)__builtin_offsetof(struct ehci_qh, qh_link),
1554 sizeof(head->qh.qh_link), BUS_DMASYNC_PREWRITE0x04);
1555}
1556
1557/*
1558 * Remove an ED from the schedule. Called at splusb().
1559 * Will always have a 'next' if it's in the async list as it's circular.
1560 */
1561void
1562ehci_rem_qh(struct ehci_softc *sc, struct ehci_soft_qh *sqh)
1563{
1564 splsoftassert(IPL_SOFTUSB)do { if (splassert_ctl > 0) { splassert_check(0x2, __func__
); } } while (0)
;
1565 /* XXX */
1566 usb_syncmem(&sqh->dma, sqh->offs + offsetof(struct ehci_qh, qh_link)__builtin_offsetof(struct ehci_qh, qh_link),
1567 sizeof(sqh->qh.qh_link), BUS_DMASYNC_POSTWRITE0x08);
1568 sqh->prev->qh.qh_link = sqh->qh.qh_link;
1569 sqh->prev->next = sqh->next;
1570 if (sqh->next)
1571 sqh->next->prev = sqh->prev;
1572 usb_syncmem(&sqh->prev->dma,
1573 sqh->prev->offs + offsetof(struct ehci_qh, qh_link)__builtin_offsetof(struct ehci_qh, qh_link),
1574 sizeof(sqh->prev->qh.qh_link), BUS_DMASYNC_PREWRITE0x04);
1575
1576 ehci_sync_hc(sc);
1577}
1578
1579void
1580ehci_set_qh_qtd(struct ehci_soft_qh *sqh, struct ehci_soft_qtd *sqtd)
1581{
1582 int i;
1583 u_int32_t status;
1584
1585 /* Save toggle bit and ping status. */
1586 usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
1587 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
1588 status = sqh->qh.qh_qtd.qtd_status &
1589 htole32(EHCI_QTD_TOGGLE_MASK |((__uint32_t)(0x80000000 | ((0x01) << 0)))
1590 EHCI_QTD_SET_STATUS(EHCI_QTD_PINGSTATE))((__uint32_t)(0x80000000 | ((0x01) << 0)));
1591 /* Set HALTED to make hw leave it alone. */
1592 sqh->qh.qh_qtd.qtd_status =
1593 htole32(EHCI_QTD_SET_STATUS(EHCI_QTD_HALTED))((__uint32_t)(((0x40) << 0)));
1594 usb_syncmem(&sqh->dma,
1595 sqh->offs + offsetof(struct ehci_qh, qh_qtd.qtd_status)__builtin_offsetof(struct ehci_qh, qh_qtd.qtd_status),
1596 sizeof(sqh->qh.qh_qtd.qtd_status),
1597 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
1598 sqh->qh.qh_curqtd = 0;
1599 sqh->qh.qh_qtd.qtd_next = htole32(sqtd->physaddr)((__uint32_t)(sqtd->physaddr));
1600 sqh->qh.qh_qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
1601 for (i = 0; i < EHCI_QTD_NBUFFERS5; i++)
1602 sqh->qh.qh_qtd.qtd_buffer[i] = 0;
1603 sqh->sqtd = sqtd;
1604 usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh),
1605 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
1606 /* Set !HALTED && !ACTIVE to start execution, preserve some fields */
1607 sqh->qh.qh_qtd.qtd_status = status;
1608 usb_syncmem(&sqh->dma,
1609 sqh->offs + offsetof(struct ehci_qh, qh_qtd.qtd_status)__builtin_offsetof(struct ehci_qh, qh_qtd.qtd_status),
1610 sizeof(sqh->qh.qh_qtd.qtd_status),
1611 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
1612}
1613
1614/*
1615 * Ensure that the HC has released all references to the QH. We do this
1616 * by asking for a Async Advance Doorbell interrupt and then we wait for
1617 * the interrupt.
1618 * To make this easier we first obtain exclusive use of the doorbell.
1619 */
1620void
1621ehci_sync_hc(struct ehci_softc *sc)
1622{
1623 int s, error;
1624 int tries = 0;
1625
1626 if (sc->sc_bus.dying) {
1627 return;
1628 }
1629
1630 /* get doorbell */
1631 rw_enter_write(&sc->sc_doorbell_lock);
1632 s = splhardusb()splraise(0x3);
1633 do {
1634 EOWRITE4(sc, EHCI_USBCMD, EOREAD4(sc, EHCI_USBCMD) |(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), (((((sc)->iot)->read_4(((sc)->ioh), ((sc)->
sc_offs+(0x00)))) | 0x00000040))))
1635 EHCI_CMD_IAAD)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(0x00)), (((((sc)->iot)->read_4(((sc)->ioh), ((sc)->
sc_offs+(0x00)))) | 0x00000040))))
;
1636 error = tsleep_nsec(&sc->sc_async_head, PZERO22, "ehcidi",
1637 MSEC_TO_NSEC(500));
1638 } while (error && ++tries < 10);
1639 splx(s)spllower(s);
1640 /* release doorbell */
1641 rw_exit_write(&sc->sc_doorbell_lock);
1642#ifdef DIAGNOSTIC1
1643 if (error)
1644 printf("ehci_sync_hc: tsleep() = %d\n", error);
1645#endif
1646}
1647
1648void
1649ehci_rem_itd_chain(struct ehci_softc *sc, struct ehci_xfer *ex)
1650{
1651 struct ehci_soft_itd *itd, *prev = NULL((void *)0);
1652
1653 splsoftassert(IPL_SOFTUSB)do { if (splassert_ctl > 0) { splassert_check(0x2, __func__
); } } while (0)
;
1654
1655 KASSERT(ex->itdstart != NULL && ex->itdend != NULL)((ex->_TD.itd.start != ((void *)0) && ex->_TD.itd
.end != ((void *)0)) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/usb/ehci.c"
, 1655, "ex->itdstart != NULL && ex->itdend != NULL"
))
;
1656
1657 for (itd = ex->itdstart_TD.itd.start; itd != NULL((void *)0); itd = itd->xfer_next) {
1658 prev = itd->u.frame_list.prev;
1659 /* Unlink itd from hardware chain, or frame array */
1660 if (prev == NULL((void *)0)) { /* We're at the table head */
1661 sc->sc_softitds[itd->slot] = itd->u.frame_list.next;
1662 sc->sc_flist[itd->slot] = itd->itd.itd_next;
1663 usb_syncmem(&sc->sc_fldma,
1664 sizeof(uint32_t) * itd->slot, sizeof(uint32_t),
1665 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
1666
1667 if (itd->u.frame_list.next != NULL((void *)0))
1668 itd->u.frame_list.next->u.frame_list.prev =
1669 NULL((void *)0);
1670 } else {
1671 /* XXX this part is untested... */
1672 prev->itd.itd_next = itd->itd.itd_next;
1673 usb_syncmem(&itd->dma,
1674 itd->offs + offsetof(struct ehci_itd, itd_next)__builtin_offsetof(struct ehci_itd, itd_next),
1675 sizeof(itd->itd.itd_next), BUS_DMASYNC_PREWRITE0x04);
1676
1677 prev->u.frame_list.next = itd->u.frame_list.next;
1678 if (itd->u.frame_list.next != NULL((void *)0))
1679 itd->u.frame_list.next->u.frame_list.prev =
1680 prev;
1681 }
1682 }
1683}
1684
1685void
1686ehci_free_itd_chain(struct ehci_softc *sc, struct ehci_xfer *ex)
1687{
1688 struct ehci_soft_itd *itd, *prev = NULL((void *)0);
1689
1690 splsoftassert(IPL_SOFTUSB)do { if (splassert_ctl > 0) { splassert_check(0x2, __func__
); } } while (0)
;
1691
1692 KASSERT(ex->itdstart != NULL && ex->itdend != NULL)((ex->_TD.itd.start != ((void *)0) && ex->_TD.itd
.end != ((void *)0)) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/usb/ehci.c"
, 1692, "ex->itdstart != NULL && ex->itdend != NULL"
))
;
1693
1694 for (itd = ex->itdstart_TD.itd.start; itd != NULL((void *)0); itd = itd->xfer_next) {
1695 if (prev != NULL((void *)0))
1696 ehci_free_itd(sc, prev);
1697 prev = itd;
1698 }
1699 if (prev)
1700 ehci_free_itd(sc, prev);
1701 ex->itdstart_TD.itd.start = NULL((void *)0);
1702 ex->itdend_TD.itd.end = NULL((void *)0);
1703}
1704
1705/*
1706 * Data structures and routines to emulate the root hub.
1707 */
1708const usb_device_descriptor_t ehci_devd = {
1709 USB_DEVICE_DESCRIPTOR_SIZE18,
1710 UDESC_DEVICE0x01, /* type */
1711 {0x00, 0x02}, /* USB version */
1712 UDCLASS_HUB0x09, /* class */
1713 UDSUBCLASS_HUB0x00, /* subclass */
1714 UDPROTO_HSHUBSTT0x01, /* protocol */
1715 64, /* max packet */
1716 {0},{0},{0x00,0x01}, /* device id */
1717 1,2,0, /* string indices */
1718 1 /* # of configurations */
1719};
1720
1721const usb_device_qualifier_t ehci_odevd = {
1722 USB_DEVICE_DESCRIPTOR_SIZE18,
1723 UDESC_DEVICE_QUALIFIER0x06, /* type */
1724 {0x00, 0x02}, /* USB version */
1725 UDCLASS_HUB0x09, /* class */
1726 UDSUBCLASS_HUB0x00, /* subclass */
1727 UDPROTO_FSHUB0x00, /* protocol */
1728 64, /* max packet */
1729 1, /* # of configurations */
1730 0
1731};
1732
1733const usb_config_descriptor_t ehci_confd = {
1734 USB_CONFIG_DESCRIPTOR_SIZE9,
1735 UDESC_CONFIG0x02,
1736 {USB_CONFIG_DESCRIPTOR_SIZE9 +
1737 USB_INTERFACE_DESCRIPTOR_SIZE9 +
1738 USB_ENDPOINT_DESCRIPTOR_SIZE7},
1739 1,
1740 1,
1741 0,
1742 UC_BUS_POWERED0x80 | UC_SELF_POWERED0x40,
1743 0 /* max power */
1744};
1745
1746const usb_interface_descriptor_t ehci_ifcd = {
1747 USB_INTERFACE_DESCRIPTOR_SIZE9,
1748 UDESC_INTERFACE0x04,
1749 0,
1750 0,
1751 1,
1752 UICLASS_HUB0x09,
1753 UISUBCLASS_HUB0,
1754 UIPROTO_HSHUBSTT0,
1755 0
1756};
1757
1758const usb_endpoint_descriptor_t ehci_endpd = {
1759 USB_ENDPOINT_DESCRIPTOR_SIZE7,
1760 UDESC_ENDPOINT0x05,
1761 UE_DIR_IN0x80 | EHCI_INTR_ENDPT1,
1762 UE_INTERRUPT0x03,
1763 {8, 0}, /* max packet */
1764 12
1765};
1766
1767const usb_hub_descriptor_t ehci_hubd = {
1768 USB_HUB_DESCRIPTOR_SIZE8,
1769 UDESC_HUB0x29,
1770 0,
1771 {0,0},
1772 0,
1773 0,
1774 {0},
1775};
1776
1777/*
1778 * Simulate a hardware hub by handling all the necessary requests.
1779 */
1780usbd_status
1781ehci_root_ctrl_transfer(struct usbd_xfer *xfer)
1782{
1783 usbd_status err;
1784
1785 /* Insert last in queue. */
1786 err = usb_insert_transfer(xfer);
1787 if (err)
1788 return (err);
1789
1790 /* Pipe isn't running, start first */
1791 return (ehci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first)));
1792}
1793
1794usbd_status
1795ehci_root_ctrl_start(struct usbd_xfer *xfer)
1796{
1797 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
1798 usb_device_request_t *req;
1799 void *buf = NULL((void *)0);
1800 int port, i;
1801 int s, len, value, index, l, totlen = 0;
1802 usb_port_status_t ps;
1803 usb_device_descriptor_t devd;
1804 usb_hub_descriptor_t hubd;
1805 usbd_status err;
1806 u_int32_t v;
1807
1808 if (sc->sc_bus.dying)
1809 return (USBD_IOERROR);
1810
1811#ifdef DIAGNOSTIC1
1812 if (!(xfer->rqflags & URQ_REQUEST0x01))
1813 /* XXX panic */
1814 return (USBD_INVAL);
1815#endif
1816 req = &xfer->request;
1817
1818 DPRINTFN(4,("ehci_root_ctrl_start: type=0x%02x request=%02x\n",
1819 req->bmRequestType, req->bRequest));
1820
1821 len = UGETW(req->wLength)(*(u_int16_t *)(req->wLength));
1822 value = UGETW(req->wValue)(*(u_int16_t *)(req->wValue));
1823 index = UGETW(req->wIndex)(*(u_int16_t *)(req->wIndex));
1824
1825 if (len != 0)
1826 buf = KERNADDR(&xfer->dmabuf, 0)((void *)((char *)((&xfer->dmabuf)->block->kaddr
+ (&xfer->dmabuf)->offs) + (0)))
;
1827
1828#define C(x,y)((x) | ((y) << 8)) ((x) | ((y) << 8))
1829 switch(C(req->bRequest, req->bmRequestType)((req->bRequest) | ((req->bmRequestType) << 8))) {
1830 case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE)((0x01) | (((0x00 | 0x00 | 0x00)) << 8)):
1831 case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE)((0x01) | (((0x00 | 0x00 | 0x01)) << 8)):
1832 case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT)((0x01) | (((0x00 | 0x00 | 0x02)) << 8)):
1833 /*
1834 * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
1835 * for the integrated root hub.
1836 */
1837 break;
1838 case C(UR_GET_CONFIG, UT_READ_DEVICE)((0x08) | (((0x80 | 0x00 | 0x00)) << 8)):
1839 if (len > 0) {
1840 *(u_int8_t *)buf = sc->sc_conf;
1841 totlen = 1;
1842 }
1843 break;
1844 case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE)((0x06) | (((0x80 | 0x00 | 0x00)) << 8)):
1845 DPRINTFN(8,("ehci_root_ctrl_start: wValue=0x%04x\n", value));
1846 switch(value >> 8) {
1847 case UDESC_DEVICE0x01:
1848 if ((value & 0xff) != 0) {
1849 err = USBD_IOERROR;
1850 goto ret;
1851 }
1852 devd = ehci_devd;
1853 USETW(devd.idVendor, sc->sc_id_vendor)(*(u_int16_t *)(devd.idVendor) = (sc->sc_id_vendor));
1854 totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE18);
1855 memcpy(buf, &devd, l)__builtin_memcpy((buf), (&devd), (l));
1856 break;
1857 case UDESC_DEVICE_QUALIFIER0x06:
1858 if ((value & 0xff) != 0) {
1859 err = USBD_IOERROR;
1860 goto ret;
1861 }
1862 totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE18);
1863 memcpy(buf, &ehci_odevd, l)__builtin_memcpy((buf), (&ehci_odevd), (l));
1864 break;
1865 /*
1866 * We can't really operate at another speed, but the spec says
1867 * we need this descriptor.
1868 */
1869 case UDESC_OTHER_SPEED_CONFIGURATION0x07:
1870 case UDESC_CONFIG0x02:
1871 if ((value & 0xff) != 0) {
1872 err = USBD_IOERROR;
1873 goto ret;
1874 }
1875 totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE9);
1876 memcpy(buf, &ehci_confd, l)__builtin_memcpy((buf), (&ehci_confd), (l));
1877 ((usb_config_descriptor_t *)buf)->bDescriptorType =
1878 value >> 8;
1879 buf = (char *)buf + l;
1880 len -= l;
1881 l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE9);
1882 totlen += l;
1883 memcpy(buf, &ehci_ifcd, l)__builtin_memcpy((buf), (&ehci_ifcd), (l));
1884 buf = (char *)buf + l;
1885 len -= l;
1886 l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE7);
1887 totlen += l;
1888 memcpy(buf, &ehci_endpd, l)__builtin_memcpy((buf), (&ehci_endpd), (l));
1889 break;
1890 case UDESC_STRING0x03:
1891 if (len == 0)
1892 break;
1893 *(u_int8_t *)buf = 0;
1894 totlen = 1;
1895 switch (value & 0xff) {
1896 case 0: /* Language table */
1897 totlen = usbd_str(buf, len, "\001");
1898 break;
1899 case 1: /* Vendor */
1900 totlen = usbd_str(buf, len, sc->sc_vendor);
1901 break;
1902 case 2: /* Product */
1903 totlen = usbd_str(buf, len, "EHCI root hub");
1904 break;
1905 }
1906 break;
1907 default:
1908 err = USBD_IOERROR;
1909 goto ret;
1910 }
1911 break;
1912 case C(UR_GET_INTERFACE, UT_READ_INTERFACE)((0x0a) | (((0x80 | 0x00 | 0x01)) << 8)):
1913 if (len > 0) {
1914 *(u_int8_t *)buf = 0;
1915 totlen = 1;
1916 }
1917 break;
1918 case C(UR_GET_STATUS, UT_READ_DEVICE)((0x00) | (((0x80 | 0x00 | 0x00)) << 8)):
1919 if (len > 1) {
1920 USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED)(*(u_int16_t *)(((usb_status_t *)buf)->wStatus) = (0x0001)
)
;
1921 totlen = 2;
1922 }
1923 break;
1924 case C(UR_GET_STATUS, UT_READ_INTERFACE)((0x00) | (((0x80 | 0x00 | 0x01)) << 8)):
1925 case C(UR_GET_STATUS, UT_READ_ENDPOINT)((0x00) | (((0x80 | 0x00 | 0x02)) << 8)):
1926 if (len > 1) {
1927 USETW(((usb_status_t *)buf)->wStatus, 0)(*(u_int16_t *)(((usb_status_t *)buf)->wStatus) = (0));
1928 totlen = 2;
1929 }
1930 break;
1931 case C(UR_SET_ADDRESS, UT_WRITE_DEVICE)((0x05) | (((0x00 | 0x00 | 0x00)) << 8)):
1932 if (value >= USB_MAX_DEVICES128) {
1933 err = USBD_IOERROR;
1934 goto ret;
1935 }
1936 break;
1937 case C(UR_SET_CONFIG, UT_WRITE_DEVICE)((0x09) | (((0x00 | 0x00 | 0x00)) << 8)):
1938 if (value != 0 && value != 1) {
1939 err = USBD_IOERROR;
1940 goto ret;
1941 }
1942 sc->sc_conf = value;
1943 break;
1944 case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE)((0x07) | (((0x00 | 0x00 | 0x00)) << 8)):
1945 break;
1946 case C(UR_SET_FEATURE, UT_WRITE_DEVICE)((0x03) | (((0x00 | 0x00 | 0x00)) << 8)):
1947 case C(UR_SET_FEATURE, UT_WRITE_INTERFACE)((0x03) | (((0x00 | 0x00 | 0x01)) << 8)):
1948 case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT)((0x03) | (((0x00 | 0x00 | 0x02)) << 8)):
1949 err = USBD_IOERROR;
1950 goto ret;
1951 case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE)((0x0b) | (((0x00 | 0x00 | 0x01)) << 8)):
1952 break;
1953 case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT)((0x0c) | (((0x00 | 0x00 | 0x02)) << 8)):
1954 break;
1955 /* Hub requests */
1956 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE)((0x01) | (((0x00 | 0x20 | 0x00)) << 8)):
1957 break;
1958 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER)((0x01) | (((0x00 | 0x20 | 0x03)) << 8)):
1959 DPRINTFN(8, ("ehci_root_ctrl_start: UR_CLEAR_PORT_FEATURE "
1960 "port=%d feature=%d\n", index, value));
1961 if (index < 1 || index > sc->sc_noport) {
1962 err = USBD_IOERROR;
1963 goto ret;
1964 }
1965 port = EHCI_PORTSC(index)(0x40+4*(index));
1966 v = EOREAD4(sc, port)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(port))))
&~ EHCI_PS_CLEAR(0x00000020|0x00000008|0x00000002);
1967 switch(value) {
1968 case UHF_PORT_ENABLE1:
1969 EOWRITE4(sc, port, v &~ EHCI_PS_PE)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v &~ 0x00000004))))
;
1970 break;
1971 case UHF_PORT_SUSPEND2:
1972 EOWRITE4(sc, port, v &~ EHCI_PS_SUSP)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v &~ 0x00000080))))
;
1973 break;
1974 case UHF_PORT_POWER8:
1975 EOWRITE4(sc, port, v &~ EHCI_PS_PP)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v &~ 0x00001000))))
;
1976 break;
1977 case UHF_PORT_TEST21:
1978 DPRINTFN(2,("ehci_root_ctrl_start: "
1979 "clear port test %d\n", index));
1980 break;
1981 case UHF_PORT_INDICATOR22:
1982 DPRINTFN(2,("ehci_root_ctrl_start: "
1983 "clear port index %d\n", index));
1984 EOWRITE4(sc, port, v &~ EHCI_PS_PIC)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v &~ 0x0000c000))))
;
1985 break;
1986 case UHF_C_PORT_CONNECTION16:
1987 EOWRITE4(sc, port, v | EHCI_PS_CSC)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v | 0x00000002))))
;
1988 break;
1989 case UHF_C_PORT_ENABLE17:
1990 EOWRITE4(sc, port, v | EHCI_PS_PEC)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v | 0x00000008))))
;
1991 break;
1992 case UHF_C_PORT_SUSPEND18:
1993 /* how? */
1994 break;
1995 case UHF_C_PORT_OVER_CURRENT19:
1996 EOWRITE4(sc, port, v | EHCI_PS_OCC)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v | 0x00000020))))
;
1997 break;
1998 case UHF_C_PORT_RESET20:
1999 sc->sc_isreset = 0;
2000 break;
2001 default:
2002 err = USBD_IOERROR;
2003 goto ret;
2004 }
2005 break;
2006 case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE)((0x06) | (((0x80 | 0x20 | 0x00)) << 8)):
2007 if ((value & 0xff) != 0) {
2008 err = USBD_IOERROR;
2009 goto ret;
2010 }
2011 hubd = ehci_hubd;
2012 hubd.bNbrPorts = sc->sc_noport;
2013 v = EREAD4(sc, EHCI_HCSPARAMS)(((sc)->iot)->read_4(((sc)->ioh), ((0x04))));
2014 USETW(hubd.wHubCharacteristics,(*(u_int16_t *)(hubd.wHubCharacteristics) = ((((v) & 0x10
) ? 0x0001 : 0x0002) | (((v) & 0x10000) ? 0x0080 : 0)))
2015 (EHCI_HCS_PPC(v) ? UHD_PWR_INDIVIDUAL : UHD_PWR_NO_SWITCH) |(*(u_int16_t *)(hubd.wHubCharacteristics) = ((((v) & 0x10
) ? 0x0001 : 0x0002) | (((v) & 0x10000) ? 0x0080 : 0)))
2016 (EHCI_HCS_P_INDICATOR(v) ? UHD_PORT_IND : 0))(*(u_int16_t *)(hubd.wHubCharacteristics) = ((((v) & 0x10
) ? 0x0001 : 0x0002) | (((v) & 0x10000) ? 0x0080 : 0)))
;
2017 hubd.bPwrOn2PwrGood = 200; /* XXX can't find out? */
2018 for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8)
2019 hubd.DeviceRemovable[i++] = 0; /* XXX can't find out? */
2020 hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE8 + i;
2021 l = min(len, hubd.bDescLength);
2022 totlen = l;
2023 memcpy(buf, &hubd, l)__builtin_memcpy((buf), (&hubd), (l));
2024 break;
2025 case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE)((0x00) | (((0x80 | 0x20 | 0x00)) << 8)):
2026 if (len != 4) {
2027 err = USBD_IOERROR;
2028 goto ret;
2029 }
2030 memset(buf, 0, len)__builtin_memset((buf), (0), (len)); /* ? XXX */
2031 totlen = len;
2032 break;
2033 case C(UR_GET_STATUS, UT_READ_CLASS_OTHER)((0x00) | (((0x80 | 0x20 | 0x03)) << 8)):
2034 DPRINTFN(8,("ehci_root_ctrl_start: get port status i=%d\n",
2035 index));
2036 if (index < 1 || index > sc->sc_noport) {
2037 err = USBD_IOERROR;
2038 goto ret;
2039 }
2040 if (len != 4) {
2041 err = USBD_IOERROR;
2042 goto ret;
2043 }
2044 v = EOREAD4(sc, EHCI_PORTSC(index))(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
((0x40+4*(index))))))
;
2045 DPRINTFN(8,("ehci_root_ctrl_start: port status=0x%04x\n", v));
2046 i = UPS_HIGH_SPEED0x0400;
2047 if (v & EHCI_PS_CS0x00000001) i |= UPS_CURRENT_CONNECT_STATUS0x0001;
2048 if (v & EHCI_PS_PE0x00000004) i |= UPS_PORT_ENABLED0x0002;
2049 if (v & EHCI_PS_SUSP0x00000080) i |= UPS_SUSPEND0x0004;
2050 if (v & EHCI_PS_OCA0x00000010) i |= UPS_OVERCURRENT_INDICATOR0x0008;
2051 if (v & EHCI_PS_PR0x00000100) i |= UPS_RESET0x0010;
2052 if (v & EHCI_PS_PP0x00001000) i |= UPS_PORT_POWER0x0100;
2053 USETW(ps.wPortStatus, i)(*(u_int16_t *)(ps.wPortStatus) = (i));
2054 i = 0;
2055 if (v & EHCI_PS_CSC0x00000002) i |= UPS_C_CONNECT_STATUS0x0001;
2056 if (v & EHCI_PS_PEC0x00000008) i |= UPS_C_PORT_ENABLED0x0002;
2057 if (v & EHCI_PS_OCC0x00000020) i |= UPS_C_OVERCURRENT_INDICATOR0x0008;
2058 if (sc->sc_isreset) i |= UPS_C_PORT_RESET0x0010;
2059 USETW(ps.wPortChange, i)(*(u_int16_t *)(ps.wPortChange) = (i));
2060 l = min(len, sizeof(ps));
2061 memcpy(buf, &ps, l)__builtin_memcpy((buf), (&ps), (l));
2062 totlen = l;
2063 break;
2064 case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE)((0x07) | (((0x00 | 0x20 | 0x00)) << 8)):
2065 err = USBD_IOERROR;
2066 goto ret;
2067 case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE)((0x03) | (((0x00 | 0x20 | 0x00)) << 8)):
2068 break;
2069 case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER)((0x03) | (((0x00 | 0x20 | 0x03)) << 8)):
2070 if (index < 1 || index > sc->sc_noport) {
2071 err = USBD_IOERROR;
2072 goto ret;
2073 }
2074 port = EHCI_PORTSC(index)(0x40+4*(index));
2075 v = EOREAD4(sc, port)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(port))))
&~ EHCI_PS_CLEAR(0x00000020|0x00000008|0x00000002);
2076 switch(value) {
2077 case UHF_PORT_ENABLE1:
2078 EOWRITE4(sc, port, v | EHCI_PS_PE)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v | 0x00000004))))
;
2079 break;
2080 case UHF_PORT_SUSPEND2:
2081 EOWRITE4(sc, port, v | EHCI_PS_SUSP)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v | 0x00000080))))
;
2082 break;
2083 case UHF_PORT_DISOWN_TO_1_130:
2084 /* enter to Port Reset State */
2085 v &= ~EHCI_PS_PE0x00000004;
2086 EOWRITE4(sc, port, v | EHCI_PS_PR)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v | 0x00000100))))
;
2087 ehci_disown(sc, index, 0);
2088 break;
2089 case UHF_PORT_RESET4:
2090 DPRINTFN(5,("ehci_root_ctrl_start: reset port %d\n",
2091 index));
2092 if (EHCI_PS_IS_LOWSPEED(v)(((v) & 0x00000c00) == 0x00000400)) {
2093 /* Low speed device, give up ownership. */
2094 ehci_disown(sc, index, 1);
2095 break;
2096 }
2097 /* Start reset sequence. */
2098 v &= ~ (EHCI_PS_PE0x00000004 | EHCI_PS_PR0x00000100);
2099 EOWRITE4(sc, port, v | EHCI_PS_PR)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v | 0x00000100))))
;
2100 /* Wait for reset to complete. */
2101 usb_delay_ms(&sc->sc_bus, USB_PORT_ROOT_RESET_DELAY100);
2102 if (sc->sc_bus.dying) {
2103 err = USBD_IOERROR;
2104 goto ret;
2105 }
2106 /* Terminate reset sequence. */
2107 v = EOREAD4(sc, port)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(port))))
;
2108 EOWRITE4(sc, port, v & ~EHCI_PS_PR)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v & ~0x00000100))))
;
2109 /* Wait for HC to complete reset. */
2110 usb_delay_ms(&sc->sc_bus, EHCI_PORT_RESET_COMPLETE2);
2111 if (sc->sc_bus.dying) {
2112 err = USBD_IOERROR;
2113 goto ret;
2114 }
2115 v = EOREAD4(sc, port)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(port))))
;
2116 DPRINTF(("ehci after reset, status=0x%08x\n", v));
2117 if (v & EHCI_PS_PR0x00000100) {
2118 printf("%s: port reset timeout\n",
2119 sc->sc_bus.bdev.dv_xname);
2120 err = USBD_IOERROR;
2121 goto ret;
2122 }
2123 if (!(v & EHCI_PS_PE0x00000004)) {
2124 /* Not a high speed device, give up ownership.*/
2125 ehci_disown(sc, index, 0);
2126 break;
2127 }
2128 sc->sc_isreset = 1;
2129 DPRINTF(("ehci port %d reset, status = 0x%08x\n",
2130 index, v));
2131 break;
2132 case UHF_PORT_POWER8:
2133 DPRINTFN(2,("ehci_root_ctrl_start: "
2134 "set port power %d\n", index));
2135 EOWRITE4(sc, port, v | EHCI_PS_PP)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v | 0x00001000))))
;
2136 break;
2137 case UHF_PORT_TEST21:
2138 DPRINTFN(2,("ehci_root_ctrl_start: "
2139 "set port test %d\n", index));
2140 break;
2141 case UHF_PORT_INDICATOR22:
2142 DPRINTFN(2,("ehci_root_ctrl_start: "
2143 "set port ind %d\n", index));
2144 EOWRITE4(sc, port, v | EHCI_PS_PIC)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v | 0x0000c000))))
;
2145 break;
2146 default:
2147 err = USBD_IOERROR;
2148 goto ret;
2149 }
2150 break;
2151 case C(UR_CLEAR_TT_BUFFER, UT_WRITE_CLASS_OTHER)((0x08) | (((0x00 | 0x20 | 0x03)) << 8)):
2152 case C(UR_RESET_TT, UT_WRITE_CLASS_OTHER)((0x09) | (((0x00 | 0x20 | 0x03)) << 8)):
2153 case C(UR_GET_TT_STATE, UT_READ_CLASS_OTHER)((0x0a) | (((0x80 | 0x20 | 0x03)) << 8)):
2154 case C(UR_STOP_TT, UT_WRITE_CLASS_OTHER)((0x0b) | (((0x00 | 0x20 | 0x03)) << 8)):
2155 break;
2156 default:
2157 err = USBD_IOERROR;
2158 goto ret;
2159 }
2160 xfer->actlen = totlen;
2161 err = USBD_NORMAL_COMPLETION;
2162 ret:
2163 xfer->status = err;
2164 s = splusb()splraise(0x2);
2165 usb_transfer_complete(xfer);
2166 splx(s)spllower(s);
2167 return (err);
2168}
2169
2170void
2171ehci_disown(struct ehci_softc *sc, int index, int lowspeed)
2172{
2173 int port;
2174 u_int32_t v;
2175
2176 port = EHCI_PORTSC(index)(0x40+4*(index));
2177 v = EOREAD4(sc, port)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(port))))
&~ EHCI_PS_CLEAR(0x00000020|0x00000008|0x00000002);
2178 EOWRITE4(sc, port, v | EHCI_PS_PO)(((sc)->iot)->write_4(((sc)->ioh), ((sc)->sc_offs
+(port)), ((v | 0x00002000))))
;
2179}
2180
2181/* Abort a root control request. */
2182void
2183ehci_root_ctrl_abort(struct usbd_xfer *xfer)
2184{
2185 /* Nothing to do, all transfers are synchronous. */
2186}
2187
2188/* Close the root pipe. */
2189void
2190ehci_root_ctrl_close(struct usbd_pipe *pipe)
2191{
2192 /* Nothing to do. */
2193}
2194
2195void
2196ehci_root_intr_done(struct usbd_xfer *xfer)
2197{
2198}
2199
2200usbd_status
2201ehci_root_intr_transfer(struct usbd_xfer *xfer)
2202{
2203 usbd_status err;
2204
2205 /* Insert last in queue. */
2206 err = usb_insert_transfer(xfer);
2207 if (err)
2208 return (err);
2209
2210 /* Pipe isn't running, start first */
2211 return (ehci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first)));
2212}
2213
2214usbd_status
2215ehci_root_intr_start(struct usbd_xfer *xfer)
2216{
2217 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
2218
2219 if (sc->sc_bus.dying)
2220 return (USBD_IOERROR);
2221
2222 sc->sc_intrxfer = xfer;
2223
2224 return (USBD_IN_PROGRESS);
2225}
2226
2227void
2228ehci_root_intr_abort(struct usbd_xfer *xfer)
2229{
2230 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
2231 int s;
2232
2233 sc->sc_intrxfer = NULL((void *)0);
2234
2235 xfer->status = USBD_CANCELLED;
2236 s = splusb()splraise(0x2);
2237 usb_transfer_complete(xfer);
2238 splx(s)spllower(s);
2239}
2240
2241void
2242ehci_root_intr_close(struct usbd_pipe *pipe)
2243{
2244}
2245
2246void
2247ehci_root_ctrl_done(struct usbd_xfer *xfer)
2248{
2249}
2250
2251struct ehci_soft_qh *
2252ehci_alloc_sqh(struct ehci_softc *sc)
2253{
2254 struct ehci_soft_qh *sqh = NULL((void *)0);
2255 usbd_status err;
2256 int i, offs;
2257 struct usb_dma dma;
2258 int s;
2259
2260 s = splusb()splraise(0x2);
2261 if (sc->sc_freeqhs == NULL((void *)0)) {
2262 DPRINTFN(2, ("ehci_alloc_sqh: allocating chunk\n"));
2263 err = usb_allocmem(&sc->sc_bus, EHCI_SQH_SIZE((sizeof (struct ehci_soft_qh) + 32 - 1) / 32 * 32) * EHCI_SQH_CHUNK(0x1000 / ((sizeof (struct ehci_soft_qh) + 32 - 1) / 32 * 32)
)
,
2264 EHCI_PAGE_SIZE0x1000, USB_DMA_COHERENT(1 << 0), &dma);
2265 if (err)
2266 goto out;
2267 for (i = 0; i < EHCI_SQH_CHUNK(0x1000 / ((sizeof (struct ehci_soft_qh) + 32 - 1) / 32 * 32)
)
; i++) {
2268 offs = i * EHCI_SQH_SIZE((sizeof (struct ehci_soft_qh) + 32 - 1) / 32 * 32);
2269 sqh = KERNADDR(&dma, offs)((void *)((char *)((&dma)->block->kaddr + (&dma
)->offs) + (offs)))
;
2270 sqh->physaddr = DMAADDR(&dma, offs)((&dma)->block->map->dm_segs[0].ds_addr + (&
dma)->offs + (offs))
;
2271 sqh->dma = dma;
2272 sqh->offs = offs;
2273 sqh->next = sc->sc_freeqhs;
2274 sc->sc_freeqhs = sqh;
2275 }
2276 }
2277 sqh = sc->sc_freeqhs;
2278 sc->sc_freeqhs = sqh->next;
2279 memset(&sqh->qh, 0, sizeof(struct ehci_qh))__builtin_memset((&sqh->qh), (0), (sizeof(struct ehci_qh
)))
;
2280 sqh->next = NULL((void *)0);
2281 sqh->prev = NULL((void *)0);
2282
2283out:
2284 splx(s)spllower(s);
2285 return (sqh);
2286}
2287
2288void
2289ehci_free_sqh(struct ehci_softc *sc, struct ehci_soft_qh *sqh)
2290{
2291 int s;
2292
2293 s = splusb()splraise(0x2);
2294 sqh->next = sc->sc_freeqhs;
2295 sc->sc_freeqhs = sqh;
2296 splx(s)spllower(s);
2297}
2298
2299struct ehci_soft_qtd *
2300ehci_alloc_sqtd(struct ehci_softc *sc)
2301{
2302 struct ehci_soft_qtd *sqtd = NULL((void *)0);
2303 usbd_status err;
2304 int i, offs;
2305 struct usb_dma dma;
2306 int s;
2307
2308 s = splusb()splraise(0x2);
2309 if (sc->sc_freeqtds == NULL((void *)0)) {
2310 DPRINTFN(2, ("ehci_alloc_sqtd: allocating chunk\n"));
2311 err = usb_allocmem(&sc->sc_bus, EHCI_SQTD_SIZE((sizeof (struct ehci_soft_qtd) + 32 - 1) / 32 * 32)*EHCI_SQTD_CHUNK(0x1000 / ((sizeof (struct ehci_soft_qtd) + 32 - 1) / 32 * 32
))
,
2312 EHCI_PAGE_SIZE0x1000, USB_DMA_COHERENT(1 << 0), &dma);
2313 if (err)
2314 goto out;
2315 for(i = 0; i < EHCI_SQTD_CHUNK(0x1000 / ((sizeof (struct ehci_soft_qtd) + 32 - 1) / 32 * 32
))
; i++) {
2316 offs = i * EHCI_SQTD_SIZE((sizeof (struct ehci_soft_qtd) + 32 - 1) / 32 * 32);
2317 sqtd = KERNADDR(&dma, offs)((void *)((char *)((&dma)->block->kaddr + (&dma
)->offs) + (offs)))
;
2318 sqtd->physaddr = DMAADDR(&dma, offs)((&dma)->block->map->dm_segs[0].ds_addr + (&
dma)->offs + (offs))
;
2319 sqtd->dma = dma;
2320 sqtd->offs = offs;
2321 sqtd->nextqtd = sc->sc_freeqtds;
2322 sc->sc_freeqtds = sqtd;
2323 }
2324 }
2325
2326 sqtd = sc->sc_freeqtds;
2327 sc->sc_freeqtds = sqtd->nextqtd;
2328 memset(&sqtd->qtd, 0, sizeof(struct ehci_qtd))__builtin_memset((&sqtd->qtd), (0), (sizeof(struct ehci_qtd
)))
;
2329 sqtd->nextqtd = NULL((void *)0);
2330
2331out:
2332 splx(s)spllower(s);
2333 return (sqtd);
2334}
2335
2336void
2337ehci_free_sqtd(struct ehci_softc *sc, struct ehci_soft_qtd *sqtd)
2338{
2339 int s;
2340
2341 s = splusb()splraise(0x2);
2342 sqtd->nextqtd = sc->sc_freeqtds;
2343 sc->sc_freeqtds = sqtd;
2344 splx(s)spllower(s);
2345}
2346
2347usbd_status
2348ehci_alloc_sqtd_chain(struct ehci_softc *sc, u_int alen, struct usbd_xfer *xfer,
2349 struct ehci_soft_qtd **sp, struct ehci_soft_qtd **ep)
2350{
2351 struct ehci_soft_qtd *next, *cur;
2352 ehci_physaddr_t dataphys, dataphyspage, dataphyslastpage, nextphys;
2353 u_int32_t qtdstatus;
2354 u_int len, curlen;
2355 int mps, i, iscontrol, forceshort;
2356 int rd = usbd_xfer_isread(xfer);
2357 struct usb_dma *dma = &xfer->dmabuf;
2358
2359 DPRINTFN(alen<4*4096,("ehci_alloc_sqtd_chain: start len=%d\n", alen));
2360
2361 len = alen;
2362 iscontrol = UE_GET_XFERTYPE(xfer->pipe->endpoint->edesc->bmAttributes)((xfer->pipe->endpoint->edesc->bmAttributes) &
0x03)
==
2363 UE_CONTROL0x00;
2364
2365 dataphys = DMAADDR(dma, 0)((dma)->block->map->dm_segs[0].ds_addr + (dma)->offs
+ (0))
;
2366 dataphyslastpage = EHCI_PAGE(dataphys + len - 1)((dataphys + len - 1) &~ 0xfff);
2367 qtdstatus = EHCI_QTD_ACTIVE0x80 |
2368 EHCI_QTD_SET_PID(rd ? EHCI_QTD_PID_IN : EHCI_QTD_PID_OUT)((rd ? 0x1 : 0x0) << 8) |
2369 EHCI_QTD_SET_CERR(3)((3) << 10); /* IOC and BYTES set below */
2370 mps = UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize)(*(u_int16_t *)(xfer->pipe->endpoint->edesc->wMaxPacketSize
))
;
2371 forceshort = ((xfer->flags & USBD_FORCE_SHORT_XFER0x08) || len == 0) &&
2372 len % mps == 0;
2373 /*
2374 * The control transfer data stage always starts with a toggle of 1.
2375 * For other transfers we let the hardware track the toggle state.
2376 */
2377 if (iscontrol)
2378 qtdstatus |= EHCI_QTD_SET_TOGGLE(1)((1) << 31);
2379
2380 cur = ehci_alloc_sqtd(sc);
2381 *sp = cur;
2382 if (cur == NULL((void *)0))
2383 goto nomem;
2384
2385 usb_syncmem(dma, 0, alen,
2386 rd ? BUS_DMASYNC_PREREAD0x01 : BUS_DMASYNC_PREWRITE0x04);
2387 for (;;) {
2388 dataphyspage = EHCI_PAGE(dataphys)((dataphys) &~ 0xfff);
2389 /* The EHCI hardware can handle at most 5 pages. */
2390 if (dataphyslastpage - dataphyspage <
2391 EHCI_QTD_NBUFFERS5 * EHCI_PAGE_SIZE0x1000) {
2392 /* we can handle it in this QTD */
2393 curlen = len;
2394 } else {
2395 /* must use multiple TDs, fill as much as possible. */
2396 curlen = EHCI_QTD_NBUFFERS5 * EHCI_PAGE_SIZE0x1000 -
2397 EHCI_PAGE_OFFSET(dataphys)((dataphys) & 0xfff);
2398
2399 if (curlen > len) {
2400 DPRINTFN(1,("ehci_alloc_sqtd_chain: curlen=%u "
2401 "len=%u offs=0x%x\n", curlen, len,
2402 EHCI_PAGE_OFFSET(dataphys)));
2403 DPRINTFN(1,("lastpage=0x%x page=0x%x phys=0x%x\n",
2404 dataphyslastpage, dataphyspage, dataphys));
2405 curlen = len;
2406 }
2407
2408 /* the length must be a multiple of the max size */
2409 curlen -= curlen % mps;
2410 DPRINTFN(1,("ehci_alloc_sqtd_chain: multiple QTDs, "
2411 "curlen=%u\n", curlen));
2412 }
2413
2414 DPRINTFN(4,("ehci_alloc_sqtd_chain: dataphys=0x%08x "
2415 "dataphyslastpage=0x%08x len=%u curlen=%u\n",
2416 dataphys, dataphyslastpage, len, curlen));
2417 len -= curlen;
2418
2419 /*
2420 * Allocate another transfer if there's more data left,
2421 * or if force last short transfer flag is set and we're
2422 * allocating a multiple of the max packet size.
2423 */
2424 if (len != 0 || forceshort) {
2425 next = ehci_alloc_sqtd(sc);
2426 if (next == NULL((void *)0))
2427 goto nomem;
2428 nextphys = htole32(next->physaddr)((__uint32_t)(next->physaddr));
2429 } else {
2430 next = NULL((void *)0);
2431 nextphys = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
2432 }
2433
2434 for (i = 0; i * EHCI_PAGE_SIZE0x1000 <
2435 curlen + EHCI_PAGE_OFFSET(dataphys)((dataphys) & 0xfff); i++) {
2436 ehci_physaddr_t a = dataphys + i * EHCI_PAGE_SIZE0x1000;
2437 if (i != 0) /* use offset only in first buffer */
2438 a = EHCI_PAGE(a)((a) &~ 0xfff);
2439#ifdef DIAGNOSTIC1
2440 if (i >= EHCI_QTD_NBUFFERS5) {
2441 printf("ehci_alloc_sqtd_chain: i=%d\n", i);
2442 goto nomem;
2443 }
2444#endif
2445 cur->qtd.qtd_buffer[i] = htole32(a)((__uint32_t)(a));
2446 cur->qtd.qtd_buffer_hi[i] = 0;
2447 }
2448 cur->nextqtd = next;
2449 cur->qtd.qtd_next = cur->qtd.qtd_altnext = nextphys;
2450 cur->qtd.qtd_status = htole32(qtdstatus |((__uint32_t)(qtdstatus | ((curlen) << 16)))
2451 EHCI_QTD_SET_BYTES(curlen))((__uint32_t)(qtdstatus | ((curlen) << 16)));
2452 cur->len = curlen;
2453 DPRINTFN(10,("ehci_alloc_sqtd_chain: cbp=0x%08x end=0x%08x\n",
2454 dataphys, dataphys + curlen));
2455 DPRINTFN(10,("ehci_alloc_sqtd_chain: curlen=%u\n", curlen));
2456 if (iscontrol) {
2457 /*
2458 * adjust the toggle based on the number of packets
2459 * in this qtd
2460 */
2461 if ((((curlen + mps - 1) / mps) & 1) || curlen == 0)
2462 qtdstatus ^= EHCI_QTD_TOGGLE_MASK0x80000000;
2463 }
2464 if (len == 0) {
2465 if (! forceshort)
2466 break;
2467 forceshort = 0;
2468 }
2469 usb_syncmem(&cur->dma, cur->offs, sizeof(cur->qtd),
2470 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
2471 DPRINTFN(10,("ehci_alloc_sqtd_chain: extend chain\n"));
2472 dataphys += curlen;
2473 cur = next;
2474 }
2475 cur->qtd.qtd_status |= htole32(EHCI_QTD_IOC)((__uint32_t)(0x00008000));
2476 usb_syncmem(&cur->dma, cur->offs, sizeof(cur->qtd),
2477 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
2478 *ep = cur;
2479
2480 DPRINTFN(10,("ehci_alloc_sqtd_chain: return sqtd=%p sqtdend=%p\n",
2481 *sp, *ep));
2482
2483 return (USBD_NORMAL_COMPLETION);
2484
2485 nomem:
2486 /* XXX free chain */
2487 DPRINTFN(-1,("ehci_alloc_sqtd_chain: no memory\n"));
2488 return (USBD_NOMEM);
2489}
2490
2491void
2492ehci_free_sqtd_chain(struct ehci_softc *sc, struct ehci_xfer *ex)
2493{
2494 struct ehci_pipe *epipe = (struct ehci_pipe *)ex->xfer.pipe;
2495 struct ehci_soft_qtd *sqtd, *next;
2496
2497 DPRINTFN(10,("ehci_free_sqtd_chain: sqtd=%p\n", ex->sqtdstart));
2498
2499 for (sqtd = ex->sqtdstart_TD.sqtd.start; sqtd != NULL((void *)0); sqtd = next) {
2500 next = sqtd->nextqtd;
2501 ehci_free_sqtd(sc, sqtd);
2502 }
2503 ex->sqtdstart_TD.sqtd.start = ex->sqtdend_TD.sqtd.end = NULL((void *)0);
2504 epipe->sqh->sqtd = NULL((void *)0);
2505}
2506
2507struct ehci_soft_itd *
2508ehci_alloc_itd(struct ehci_softc *sc)
2509{
2510 struct ehci_soft_itd *itd, *freeitd;
2511 usbd_status err;
2512 int i, s, offs, frindex, previndex;
2513 struct usb_dma dma;
2514
2515 s = splusb()splraise(0x2);
2516
2517 /* Find an itd that wasn't freed this frame or last frame. This can
2518 * discard itds that were freed before frindex wrapped around
2519 * XXX - can this lead to thrashing? Could fix by enabling wrap-around
2520 * interrupt and fiddling with list when that happens */
2521 frindex = (EOREAD4(sc, EHCI_FRINDEX)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x0c))))
+ 1) >> 3;
2522 previndex = (frindex != 0) ? frindex - 1 : sc->sc_flsize;
2523
2524 freeitd = NULL((void *)0);
2525 LIST_FOREACH(itd, &sc->sc_freeitds, u.free_list)for((itd) = ((&sc->sc_freeitds)->lh_first); (itd)!=
((void *)0); (itd) = ((itd)->u.free_list.le_next))
{
2526 if (itd->slot != frindex && itd->slot != previndex) {
2527 freeitd = itd;
2528 break;
2529 }
2530 }
2531
2532 if (freeitd == NULL((void *)0)) {
2533 err = usb_allocmem(&sc->sc_bus, EHCI_ITD_SIZE((sizeof(struct ehci_soft_itd) + 32 - 1) / 32 * 32) * EHCI_ITD_CHUNK(0x1000 / ((sizeof(struct ehci_soft_itd) + 32 - 1) / 32 * 32)
)
,
2534 EHCI_PAGE_SIZE0x1000, USB_DMA_COHERENT(1 << 0), &dma);
2535 if (err) {
2536 splx(s)spllower(s);
2537 return (NULL((void *)0));
2538 }
2539
2540 for (i = 0; i < EHCI_ITD_CHUNK(0x1000 / ((sizeof(struct ehci_soft_itd) + 32 - 1) / 32 * 32)
)
; i++) {
2541 offs = i * EHCI_ITD_SIZE((sizeof(struct ehci_soft_itd) + 32 - 1) / 32 * 32);
2542 itd = KERNADDR(&dma, offs)((void *)((char *)((&dma)->block->kaddr + (&dma
)->offs) + (offs)))
;
2543 itd->physaddr = DMAADDR(&dma, offs)((&dma)->block->map->dm_segs[0].ds_addr + (&
dma)->offs + (offs))
;
2544 itd->dma = dma;
2545 itd->offs = offs;
2546 LIST_INSERT_HEAD(&sc->sc_freeitds, itd, u.free_list)do { if (((itd)->u.free_list.le_next = (&sc->sc_freeitds
)->lh_first) != ((void *)0)) (&sc->sc_freeitds)->
lh_first->u.free_list.le_prev = &(itd)->u.free_list
.le_next; (&sc->sc_freeitds)->lh_first = (itd); (itd
)->u.free_list.le_prev = &(&sc->sc_freeitds)->
lh_first; } while (0)
;
2547 }
2548 freeitd = LIST_FIRST(&sc->sc_freeitds)((&sc->sc_freeitds)->lh_first);
2549 }
2550
2551 itd = freeitd;
2552 LIST_REMOVE(itd, u.free_list)do { if ((itd)->u.free_list.le_next != ((void *)0)) (itd)->
u.free_list.le_next->u.free_list.le_prev = (itd)->u.free_list
.le_prev; *(itd)->u.free_list.le_prev = (itd)->u.free_list
.le_next; ((itd)->u.free_list.le_prev) = ((void *)-1); ((itd
)->u.free_list.le_next) = ((void *)-1); } while (0)
;
2553 memset(&itd->itd, 0, sizeof(struct ehci_itd))__builtin_memset((&itd->itd), (0), (sizeof(struct ehci_itd
)))
;
2554 usb_syncmem(&itd->dma, itd->offs + offsetof(struct ehci_itd, itd_next)__builtin_offsetof(struct ehci_itd, itd_next),
2555 sizeof(itd->itd.itd_next), BUS_DMASYNC_PREWRITE0x04 |
2556 BUS_DMASYNC_PREREAD0x01);
2557
2558 itd->u.frame_list.next = NULL((void *)0);
2559 itd->u.frame_list.prev = NULL((void *)0);
2560 itd->xfer_next = NULL((void *)0);
2561 itd->slot = 0;
2562 splx(s)spllower(s);
2563
2564 return (itd);
2565}
2566
2567void
2568ehci_free_itd(struct ehci_softc *sc, struct ehci_soft_itd *itd)
2569{
2570 int s;
2571
2572 s = splusb()splraise(0x2);
2573 LIST_INSERT_HEAD(&sc->sc_freeitds, itd, u.free_list)do { if (((itd)->u.free_list.le_next = (&sc->sc_freeitds
)->lh_first) != ((void *)0)) (&sc->sc_freeitds)->
lh_first->u.free_list.le_prev = &(itd)->u.free_list
.le_next; (&sc->sc_freeitds)->lh_first = (itd); (itd
)->u.free_list.le_prev = &(&sc->sc_freeitds)->
lh_first; } while (0)
;
2574 splx(s)spllower(s);
2575}
2576
2577/*
2578 * Close a regular pipe.
2579 * Assumes that there are no pending transactions.
2580 */
2581void
2582ehci_close_pipe(struct usbd_pipe *pipe)
2583{
2584 struct ehci_pipe *epipe = (struct ehci_pipe *)pipe;
2585 struct ehci_softc *sc = (struct ehci_softc *)pipe->device->bus;
2586 struct ehci_soft_qh *sqh = epipe->sqh;
2587 int s;
2588
2589 s = splusb()splraise(0x2);
2590 ehci_rem_qh(sc, sqh);
2591 splx(s)spllower(s);
2592 pipe->endpoint->savedtoggle =
2593 EHCI_QTD_GET_TOGGLE(letoh32(sqh->qh.qh_qtd.qtd_status))(((((__uint32_t)(sqh->qh.qh_qtd.qtd_status))) >> 31)
& 0x1)
;
2594 ehci_free_sqh(sc, epipe->sqh);
2595}
2596
2597/*
2598 * Abort a device request.
2599 * If this routine is called at splusb() it guarantees that the request
2600 * will be removed from the hardware scheduling and that the callback
2601 * for it will be called with USBD_CANCELLED status.
2602 * It's impossible to guarantee that the requested transfer will not
2603 * have happened since the hardware runs concurrently.
2604 * If the transaction has already happened we rely on the ordinary
2605 * interrupt processing to process it.
2606 */
2607void
2608ehci_abort_xfer(struct usbd_xfer *xfer, usbd_status status)
2609{
2610 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
2611 struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
2612 struct ehci_xfer *ex = (struct ehci_xfer*)xfer;
2613 struct ehci_soft_qh *sqh = epipe->sqh;
2614 struct ehci_soft_qtd *sqtd;
2615 int s;
2616
2617 if (sc->sc_bus.dying || xfer->status == USBD_NOT_STARTED) {
2618 s = splusb()splraise(0x2);
2619 if (xfer->status != USBD_NOT_STARTED)
2620 TAILQ_REMOVE(&sc->sc_intrhead, ex, inext)do { if (((ex)->inext.tqe_next) != ((void *)0)) (ex)->inext
.tqe_next->inext.tqe_prev = (ex)->inext.tqe_prev; else (
&sc->sc_intrhead)->tqh_last = (ex)->inext.tqe_prev
; *(ex)->inext.tqe_prev = (ex)->inext.tqe_next; ((ex)->
inext.tqe_prev) = ((void *)-1); ((ex)->inext.tqe_next) = (
(void *)-1); } while (0)
;
2621 xfer->status = status; /* make software ignore it */
2622 timeout_del(&xfer->timeout_handle);
2623 usb_rem_task(xfer->device, &xfer->abort_task);
2624#ifdef DIAGNOSTIC1
2625 ex->isdone = 1;
2626#endif
2627 usb_transfer_complete(xfer);
2628 splx(s)spllower(s);
2629 return;
2630 }
2631
2632 if (xfer->device->bus->intr_context)
2633 panic("ehci_abort_xfer: not in process context");
2634
2635 /*
2636 * If an abort is already in progress then just wait for it to
2637 * complete and return.
2638 */
2639 if (ex->ehci_xfer_flags & EHCI_XFER_ABORTING0x0001) {
2640 DPRINTFN(2, ("ehci_abort_xfer: already aborting\n"));
2641 /* No need to wait if we're aborting from a timeout. */
2642 if (status == USBD_TIMEOUT)
2643 return;
2644 /* Override the status which might be USBD_TIMEOUT. */
2645 xfer->status = status;
2646 DPRINTFN(2, ("ehci_abort_xfer: waiting for abort to finish\n"));
2647 ex->ehci_xfer_flags |= EHCI_XFER_ABORTWAIT0x0002;
2648 while (ex->ehci_xfer_flags & EHCI_XFER_ABORTING0x0001)
2649 tsleep_nsec(&ex->ehci_xfer_flags, PZERO22, "ehciaw", INFSLP0xffffffffffffffffULL);
2650 return;
2651 }
2652
2653 /*
2654 * Step 1: Make interrupt routine and timeouts ignore xfer.
2655 */
2656 s = splusb()splraise(0x2);
2657 ex->ehci_xfer_flags |= EHCI_XFER_ABORTING0x0001;
2658 xfer->status = status; /* make software ignore it */
2659 TAILQ_REMOVE(&sc->sc_intrhead, ex, inext)do { if (((ex)->inext.tqe_next) != ((void *)0)) (ex)->inext
.tqe_next->inext.tqe_prev = (ex)->inext.tqe_prev; else (
&sc->sc_intrhead)->tqh_last = (ex)->inext.tqe_prev
; *(ex)->inext.tqe_prev = (ex)->inext.tqe_next; ((ex)->
inext.tqe_prev) = ((void *)-1); ((ex)->inext.tqe_next) = (
(void *)-1); } while (0)
;
2660 timeout_del(&xfer->timeout_handle);
2661 usb_rem_task(xfer->device, &xfer->abort_task);
2662 splx(s)spllower(s);
2663
2664 /*
2665 * Step 2: Deactivate all of the qTDs that we will be removing,
2666 * otherwise the queue head may go active again.
2667 */
2668 usb_syncmem(&sqh->dma,
2669 sqh->offs + offsetof(struct ehci_qh, qh_qtd.qtd_status)__builtin_offsetof(struct ehci_qh, qh_qtd.qtd_status),
2670 sizeof(sqh->qh.qh_qtd.qtd_status),
2671 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
2672 sqh->qh.qh_qtd.qtd_status = htole32(EHCI_QTD_HALTED)((__uint32_t)(0x40));
2673 usb_syncmem(&sqh->dma,
2674 sqh->offs + offsetof(struct ehci_qh, qh_qtd.qtd_status)__builtin_offsetof(struct ehci_qh, qh_qtd.qtd_status),
2675 sizeof(sqh->qh.qh_qtd.qtd_status),
2676 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
2677
2678 for (sqtd = ex->sqtdstart_TD.sqtd.start; sqtd != NULL((void *)0); sqtd = sqtd->nextqtd) {
2679 usb_syncmem(&sqtd->dma,
2680 sqtd->offs + offsetof(struct ehci_qtd, qtd_status)__builtin_offsetof(struct ehci_qtd, qtd_status),
2681 sizeof(sqtd->qtd.qtd_status),
2682 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
2683 sqtd->qtd.qtd_status = htole32(EHCI_QTD_HALTED)((__uint32_t)(0x40));
2684 usb_syncmem(&sqtd->dma,
2685 sqtd->offs + offsetof(struct ehci_qtd, qtd_status)__builtin_offsetof(struct ehci_qtd, qtd_status),
2686 sizeof(sqtd->qtd.qtd_status),
2687 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
2688 }
2689 ehci_sync_hc(sc);
2690
2691 /*
2692 * Step 3: Make sure the soft interrupt routine has run. This
2693 * should remove any completed items off the queue.
2694 * The hardware has no reference to completed items (TDs).
2695 * It's safe to remove them at any time.
2696 */
2697 s = splusb()splraise(0x2);
2698 sc->sc_softwake = 1;
2699 usb_schedsoftintr(&sc->sc_bus);
2700 tsleep_nsec(&sc->sc_softwake, PZERO22, "ehciab", INFSLP0xffffffffffffffffULL);
2701
2702#ifdef DIAGNOSTIC1
2703 ex->isdone = 1;
2704#endif
2705 /* Do the wakeup first to avoid touching the xfer after the callback. */
2706 ex->ehci_xfer_flags &= ~EHCI_XFER_ABORTING0x0001;
2707 if (ex->ehci_xfer_flags & EHCI_XFER_ABORTWAIT0x0002) {
2708 ex->ehci_xfer_flags &= ~EHCI_XFER_ABORTWAIT0x0002;
2709 wakeup(&ex->ehci_xfer_flags);
2710 }
2711 usb_transfer_complete(xfer);
2712
2713 splx(s)spllower(s);
2714}
2715
2716void
2717ehci_abort_isoc_xfer(struct usbd_xfer *xfer, usbd_status status)
2718{
2719 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
2720 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
2721 ehci_isoc_trans_t trans_status;
2722 struct ehci_soft_itd *itd;
2723 int i;
2724
2725 splsoftassert(IPL_SOFTUSB)do { if (splassert_ctl > 0) { splassert_check(0x2, __func__
); } } while (0)
;
2726
2727 if (sc->sc_bus.dying || xfer->status == USBD_NOT_STARTED) {
2728 if (xfer->status != USBD_NOT_STARTED)
2729 TAILQ_REMOVE(&sc->sc_intrhead, ex, inext)do { if (((ex)->inext.tqe_next) != ((void *)0)) (ex)->inext
.tqe_next->inext.tqe_prev = (ex)->inext.tqe_prev; else (
&sc->sc_intrhead)->tqh_last = (ex)->inext.tqe_prev
; *(ex)->inext.tqe_prev = (ex)->inext.tqe_next; ((ex)->
inext.tqe_prev) = ((void *)-1); ((ex)->inext.tqe_next) = (
(void *)-1); } while (0)
;
2730 xfer->status = status;
2731 timeout_del(&xfer->timeout_handle);
2732 usb_rem_task(xfer->device, &xfer->abort_task);
2733 usb_transfer_complete(xfer);
2734 return;
2735 }
2736
2737 /* Transfer is already done. */
2738 if (xfer->status != USBD_IN_PROGRESS) {
2739 DPRINTF(("%s: already done \n", __func__));
2740 return;
2741 }
2742
2743
2744#ifdef DIAGNOSTIC1
2745 ex->isdone = 1;
2746#endif
2747 xfer->status = status;
2748 TAILQ_REMOVE(&sc->sc_intrhead, ex, inext)do { if (((ex)->inext.tqe_next) != ((void *)0)) (ex)->inext
.tqe_next->inext.tqe_prev = (ex)->inext.tqe_prev; else (
&sc->sc_intrhead)->tqh_last = (ex)->inext.tqe_prev
; *(ex)->inext.tqe_prev = (ex)->inext.tqe_next; ((ex)->
inext.tqe_prev) = ((void *)-1); ((ex)->inext.tqe_next) = (
(void *)-1); } while (0)
;
2749 timeout_del(&xfer->timeout_handle);
2750 usb_rem_task(xfer->device, &xfer->abort_task);
2751
2752 if (xfer->device->speed == USB_SPEED_HIGH3) {
2753 for (itd = ex->itdstart_TD.itd.start; itd != NULL((void *)0); itd = itd->xfer_next) {
2754 usb_syncmem(&itd->dma,
2755 itd->offs + offsetof(struct ehci_itd, itd_ctl)__builtin_offsetof(struct ehci_itd, itd_ctl),
2756 sizeof(itd->itd.itd_ctl),
2757 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
2758
2759 for (i = 0; i < 8; i++) {
2760 trans_status = le32toh(itd->itd.itd_ctl[i])((__uint32_t)(itd->itd.itd_ctl[i]));
2761 trans_status &= ~EHCI_ITD_ACTIVE0x80000000;
2762 itd->itd.itd_ctl[i] = htole32(trans_status)((__uint32_t)(trans_status));
2763 }
2764
2765 usb_syncmem(&itd->dma,
2766 itd->offs + offsetof(struct ehci_itd, itd_ctl)__builtin_offsetof(struct ehci_itd, itd_ctl),
2767 sizeof(itd->itd.itd_ctl),
2768 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
2769 }
2770 } else {
2771 for (itd = ex->itdstart_TD.itd.start; itd != NULL((void *)0); itd = itd->xfer_next) {
2772 usb_syncmem(&itd->dma,
2773 itd->offs + offsetof(struct ehci_sitd, sitd_trans)__builtin_offsetof(struct ehci_sitd, sitd_trans),
2774 sizeof(itd->sitd.sitd_trans),
2775 BUS_DMASYNC_POSTWRITE0x08 | BUS_DMASYNC_POSTREAD0x02);
2776
2777 trans_status = le32toh(itd->sitd.sitd_trans)((__uint32_t)(itd->sitd.sitd_trans));
2778 trans_status &= ~EHCI_SITD_ACTIVE0x80;
2779 itd->sitd.sitd_trans = htole32(trans_status)((__uint32_t)(trans_status));
2780
2781 usb_syncmem(&itd->dma,
2782 itd->offs + offsetof(struct ehci_sitd, sitd_trans)__builtin_offsetof(struct ehci_sitd, sitd_trans),
2783 sizeof(itd->sitd.sitd_trans),
2784 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
2785 }
2786 }
2787
2788 sc->sc_softwake = 1;
2789 usb_schedsoftintr(&sc->sc_bus);
2790 tsleep_nsec(&sc->sc_softwake, PZERO22, "ehciab", INFSLP0xffffffffffffffffULL);
2791
2792 usb_transfer_complete(xfer);
2793}
2794
2795void
2796ehci_timeout(void *addr)
2797{
2798 struct usbd_xfer *xfer = addr;
2799 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
2800
2801 if (sc->sc_bus.dying) {
2802 ehci_timeout_task(addr);
2803 return;
2804 }
2805
2806 usb_init_task(&xfer->abort_task, ehci_timeout_task, addr,((&xfer->abort_task)->fun = (ehci_timeout_task), (&
xfer->abort_task)->arg = (addr), (&xfer->abort_task
)->type = (2), (&xfer->abort_task)->state = 0x0)
2807 USB_TASK_TYPE_ABORT)((&xfer->abort_task)->fun = (ehci_timeout_task), (&
xfer->abort_task)->arg = (addr), (&xfer->abort_task
)->type = (2), (&xfer->abort_task)->state = 0x0)
;
2808 usb_add_task(xfer->device, &xfer->abort_task);
2809}
2810
2811void
2812ehci_timeout_task(void *addr)
2813{
2814 struct usbd_xfer *xfer = addr;
2815 int s;
2816
2817 s = splusb()splraise(0x2);
2818 ehci_abort_xfer(xfer, USBD_TIMEOUT);
2819 splx(s)spllower(s);
2820}
2821
2822/*
2823 * Some EHCI chips from VIA / ATI seem to trigger interrupts before writing
2824 * back the qTD status, or miss signalling occasionally under heavy load.
2825 * If the host machine is too fast, we can miss transaction completion - when
2826 * we scan the active list the transaction still seems to be active. This
2827 * generally exhibits itself as a umass stall that never recovers.
2828 *
2829 * We work around this behaviour by setting up this callback after any softintr
2830 * that completes with transactions still pending, giving us another chance to
2831 * check for completion after the writeback has taken place.
2832 */
2833void
2834ehci_intrlist_timeout(void *arg)
2835{
2836 struct ehci_softc *sc = arg;
2837 int s;
2838
2839 if (sc->sc_bus.dying)
2840 return;
2841
2842 s = splusb()splraise(0x2);
2843 DPRINTFN(1, ("ehci_intrlist_timeout\n"));
2844 usb_schedsoftintr(&sc->sc_bus);
2845 splx(s)spllower(s);
2846}
2847
2848usbd_status
2849ehci_device_ctrl_transfer(struct usbd_xfer *xfer)
2850{
2851 usbd_status err;
2852
2853 /* Insert last in queue. */
2854 err = usb_insert_transfer(xfer);
2855 if (err)
2856 return (err);
2857
2858 /* Pipe isn't running, start first */
2859 return (ehci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first)));
2860}
2861
2862usbd_status
2863ehci_device_ctrl_start(struct usbd_xfer *xfer)
2864{
2865 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
2866 struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
2867 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
2868 usb_device_request_t *req = &xfer->request;
2869 struct ehci_soft_qtd *setup, *stat, *next;
2870 struct ehci_soft_qh *sqh;
2871 u_int len = UGETW(req->wLength)(*(u_int16_t *)(req->wLength));
2872 usbd_status err;
2873 int s;
2874
2875 KASSERT(xfer->rqflags & URQ_REQUEST)((xfer->rqflags & 0x01) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/usb/ehci.c", 2875, "xfer->rqflags & URQ_REQUEST"
))
;
2876
2877 if (sc->sc_bus.dying)
2878 return (USBD_IOERROR);
2879
2880 setup = ehci_alloc_sqtd(sc);
2881 if (setup == NULL((void *)0)) {
2882 err = USBD_NOMEM;
2883 goto bad1;
2884 }
2885 stat = ehci_alloc_sqtd(sc);
2886 if (stat == NULL((void *)0)) {
2887 err = USBD_NOMEM;
2888 goto bad2;
2889 }
2890
2891 sqh = epipe->sqh;
2892
2893 /* Set up data transaction */
2894 if (len != 0) {
2895 struct ehci_soft_qtd *end;
2896
2897 err = ehci_alloc_sqtd_chain(sc, len, xfer, &next, &end);
2898 if (err)
2899 goto bad3;
2900 end->qtd.qtd_status &= htole32(~EHCI_QTD_IOC)((__uint32_t)(~0x00008000));
2901 end->nextqtd = stat;
2902 end->qtd.qtd_next =
2903 end->qtd.qtd_altnext = htole32(stat->physaddr)((__uint32_t)(stat->physaddr));
2904 usb_syncmem(&end->dma, end->offs, sizeof(end->qtd),
2905 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
2906 } else {
2907 next = stat;
2908 }
2909
2910 memcpy(KERNADDR(&epipe->u.ctl.reqdma, 0), req, sizeof(*req))__builtin_memcpy((((void *)((char *)((&epipe->u.ctl.reqdma
)->block->kaddr + (&epipe->u.ctl.reqdma)->offs
) + (0)))), (req), (sizeof(*req)))
;
2911 usb_syncmem(&epipe->u.ctl.reqdma, 0, sizeof *req, BUS_DMASYNC_PREWRITE0x04);
2912
2913 /* Clear toggle */
2914 setup->qtd.qtd_status = htole32(((__uint32_t)(0x80 | ((0x2) << 8) | ((3) << 10) |
((0) << 31) | ((sizeof(*req)) << 16)))
2915 EHCI_QTD_ACTIVE |((__uint32_t)(0x80 | ((0x2) << 8) | ((3) << 10) |
((0) << 31) | ((sizeof(*req)) << 16)))
2916 EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) |((__uint32_t)(0x80 | ((0x2) << 8) | ((3) << 10) |
((0) << 31) | ((sizeof(*req)) << 16)))
2917 EHCI_QTD_SET_CERR(3) |((__uint32_t)(0x80 | ((0x2) << 8) | ((3) << 10) |
((0) << 31) | ((sizeof(*req)) << 16)))
2918 EHCI_QTD_SET_TOGGLE(0) |((__uint32_t)(0x80 | ((0x2) << 8) | ((3) << 10) |
((0) << 31) | ((sizeof(*req)) << 16)))
2919 EHCI_QTD_SET_BYTES(sizeof(*req)))((__uint32_t)(0x80 | ((0x2) << 8) | ((3) << 10) |
((0) << 31) | ((sizeof(*req)) << 16)))
;
2920 setup->qtd.qtd_buffer[0] = htole32(DMAADDR(&epipe->u.ctl.reqdma, 0))((__uint32_t)(((&epipe->u.ctl.reqdma)->block->map
->dm_segs[0].ds_addr + (&epipe->u.ctl.reqdma)->offs
+ (0))))
;
2921 setup->qtd.qtd_buffer_hi[0] = 0;
2922 setup->nextqtd = next;
2923 setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr)((__uint32_t)(next->physaddr));
2924 setup->len = sizeof(*req);
2925 usb_syncmem(&setup->dma, setup->offs, sizeof(setup->qtd),
2926 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
2927
2928 stat->qtd.qtd_status = htole32(((__uint32_t)(0x80 | ((usbd_xfer_isread(xfer) ? 0x0 : 0x1) <<
8) | ((3) << 10) | ((1) << 31) | 0x00008000))
2929 EHCI_QTD_ACTIVE |((__uint32_t)(0x80 | ((usbd_xfer_isread(xfer) ? 0x0 : 0x1) <<
8) | ((3) << 10) | ((1) << 31) | 0x00008000))
2930 EHCI_QTD_SET_PID(usbd_xfer_isread(xfer) ?((__uint32_t)(0x80 | ((usbd_xfer_isread(xfer) ? 0x0 : 0x1) <<
8) | ((3) << 10) | ((1) << 31) | 0x00008000))
2931 EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN) |((__uint32_t)(0x80 | ((usbd_xfer_isread(xfer) ? 0x0 : 0x1) <<
8) | ((3) << 10) | ((1) << 31) | 0x00008000))
2932 EHCI_QTD_SET_CERR(3) |((__uint32_t)(0x80 | ((usbd_xfer_isread(xfer) ? 0x0 : 0x1) <<
8) | ((3) << 10) | ((1) << 31) | 0x00008000))
2933 EHCI_QTD_SET_TOGGLE(1) |((__uint32_t)(0x80 | ((usbd_xfer_isread(xfer) ? 0x0 : 0x1) <<
8) | ((3) << 10) | ((1) << 31) | 0x00008000))
2934 EHCI_QTD_IOC)((__uint32_t)(0x80 | ((usbd_xfer_isread(xfer) ? 0x0 : 0x1) <<
8) | ((3) << 10) | ((1) << 31) | 0x00008000))
;
2935 stat->qtd.qtd_buffer[0] = 0; /* XXX not needed? */
2936 stat->qtd.qtd_buffer_hi[0] = 0; /* XXX not needed? */
2937 stat->nextqtd = NULL((void *)0);
2938 stat->qtd.qtd_next = stat->qtd.qtd_altnext = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
2939 stat->len = 0;
2940 usb_syncmem(&stat->dma, stat->offs, sizeof(stat->qtd),
2941 BUS_DMASYNC_PREWRITE0x04 | BUS_DMASYNC_PREREAD0x01);
2942
2943 ex->sqtdstart_TD.sqtd.start = setup;
2944 ex->sqtdend_TD.sqtd.end = stat;
2945#ifdef DIAGNOSTIC1
2946 if (!ex->isdone) {
2947 printf("%s: not done, ex=%p\n", __func__, ex);
2948 }
2949 ex->isdone = 0;
2950#endif
2951
2952 /* Insert qTD in QH list. */
2953 s = splusb()splraise(0x2);
2954 ehci_set_qh_qtd(sqh, setup);
2955 if (xfer->timeout && !sc->sc_bus.use_polling) {
2956 timeout_del(&xfer->timeout_handle);
2957 timeout_set(&xfer->timeout_handle, ehci_timeout, xfer);
2958 timeout_add_msec(&xfer->timeout_handle, xfer->timeout);
2959 }
2960 TAILQ_INSERT_TAIL(&sc->sc_intrhead, ex, inext)do { (ex)->inext.tqe_next = ((void *)0); (ex)->inext.tqe_prev
= (&sc->sc_intrhead)->tqh_last; *(&sc->sc_intrhead
)->tqh_last = (ex); (&sc->sc_intrhead)->tqh_last
= &(ex)->inext.tqe_next; } while (0)
;
2961 xfer->status = USBD_IN_PROGRESS;
2962 splx(s)spllower(s);
2963
2964 return (USBD_IN_PROGRESS);
2965
2966 bad3:
2967 ehci_free_sqtd(sc, stat);
2968 bad2:
2969 ehci_free_sqtd(sc, setup);
2970 bad1:
2971 xfer->status = err;
2972 usb_transfer_complete(xfer);
2973 return (err);
2974}
2975
2976void
2977ehci_device_ctrl_done(struct usbd_xfer *xfer)
2978{
2979 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
2980 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
2981
2982 KASSERT(xfer->rqflags & URQ_REQUEST)((xfer->rqflags & 0x01) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/usb/ehci.c", 2982, "xfer->rqflags & URQ_REQUEST"
))
;
2983
2984 if (xfer->status != USBD_NOMEM) {
2985 ehci_free_sqtd_chain(sc, ex);
2986 }
2987}
2988
2989void
2990ehci_device_ctrl_abort(struct usbd_xfer *xfer)
2991{
2992 ehci_abort_xfer(xfer, USBD_CANCELLED);
2993}
2994
2995void
2996ehci_device_ctrl_close(struct usbd_pipe *pipe)
2997{
2998 ehci_close_pipe(pipe);
2999}
3000
3001usbd_status
3002ehci_device_bulk_transfer(struct usbd_xfer *xfer)
3003{
3004 usbd_status err;
3005
3006 /* Insert last in queue. */
3007 err = usb_insert_transfer(xfer);
3008 if (err)
3009 return (err);
3010
3011 /* Pipe isn't running, start first */
3012 return (ehci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first)));
3013}
3014
3015usbd_status
3016ehci_device_bulk_start(struct usbd_xfer *xfer)
3017{
3018 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
3019 struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
3020 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
3021 struct ehci_soft_qtd *data, *dataend;
3022 struct ehci_soft_qh *sqh;
3023 usbd_status err;
3024 int s;
3025
3026 KASSERT(!(xfer->rqflags & URQ_REQUEST))((!(xfer->rqflags & 0x01)) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/usb/ehci.c", 3026, "!(xfer->rqflags & URQ_REQUEST)"
))
;
3027
3028 if (sc->sc_bus.dying)
3029 return (USBD_IOERROR);
3030
3031 sqh = epipe->sqh;
3032
3033 err = ehci_alloc_sqtd_chain(sc, xfer->length, xfer, &data, &dataend);
3034 if (err) {
3035 xfer->status = err;
3036 usb_transfer_complete(xfer);
3037 return (err);
3038 }
3039
3040 /* Set up interrupt info. */
3041 ex->sqtdstart_TD.sqtd.start = data;
3042 ex->sqtdend_TD.sqtd.end = dataend;
3043#ifdef DIAGNOSTIC1
3044 if (!ex->isdone) {
3045 printf("ehci_device_bulk_start: not done, ex=%p\n", ex);
3046 }
3047 ex->isdone = 0;
3048#endif
3049
3050 s = splusb()splraise(0x2);
3051 ehci_set_qh_qtd(sqh, data);
3052 if (xfer->timeout && !sc->sc_bus.use_polling) {
3053 timeout_del(&xfer->timeout_handle);
3054 timeout_set(&xfer->timeout_handle, ehci_timeout, xfer);
3055 timeout_add_msec(&xfer->timeout_handle, xfer->timeout);
3056 }
3057 TAILQ_INSERT_TAIL(&sc->sc_intrhead, ex, inext)do { (ex)->inext.tqe_next = ((void *)0); (ex)->inext.tqe_prev
= (&sc->sc_intrhead)->tqh_last; *(&sc->sc_intrhead
)->tqh_last = (ex); (&sc->sc_intrhead)->tqh_last
= &(ex)->inext.tqe_next; } while (0)
;
3058 xfer->status = USBD_IN_PROGRESS;
3059 splx(s)spllower(s);
3060
3061 return (USBD_IN_PROGRESS);
3062}
3063
3064void
3065ehci_device_bulk_abort(struct usbd_xfer *xfer)
3066{
3067 ehci_abort_xfer(xfer, USBD_CANCELLED);
3068}
3069
3070/*
3071 * Close a device bulk pipe.
3072 */
3073void
3074ehci_device_bulk_close(struct usbd_pipe *pipe)
3075{
3076 ehci_close_pipe(pipe);
3077}
3078
3079void
3080ehci_device_bulk_done(struct usbd_xfer *xfer)
3081{
3082 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
3083 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
3084
3085 if (xfer->status != USBD_NOMEM) {
3086 ehci_free_sqtd_chain(sc, ex);
3087 }
3088}
3089
3090usbd_status
3091ehci_device_setintr(struct ehci_softc *sc, struct ehci_soft_qh *sqh, int ival)
3092{
3093 struct ehci_soft_islot *isp;
3094 int islot, lev;
3095
3096 /* Find a poll rate that is large enough. */
3097 for (lev = EHCI_IPOLLRATES8 - 1; lev > 0; lev--)
3098 if (EHCI_ILEV_IVAL(lev)(1 << (lev)) <= ival)
3099 break;
3100
3101 /* Pick an interrupt slot at the right level. */
3102 /* XXX could do better than picking at random */
3103 islot = EHCI_IQHIDX(lev, arc4random())((((arc4random()) & ((1 << (lev)) - 1)) | (1 <<
(lev))) - 1)
;
3104
3105 sqh->islot = islot;
3106 isp = &sc->sc_islots[islot];
3107 ehci_add_qh(sqh, isp->sqh);
3108
3109 return (USBD_NORMAL_COMPLETION);
3110}
3111
3112usbd_status
3113ehci_device_intr_transfer(struct usbd_xfer *xfer)
3114{
3115 usbd_status err;
3116
3117 /* Insert last in queue. */
3118 err = usb_insert_transfer(xfer);
3119 if (err)
3120 return (err);
3121
3122 /*
3123 * Pipe isn't running (otherwise err would be USBD_INPROG),
3124 * so start it first.
3125 */
3126 return (ehci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first)));
3127}
3128
3129usbd_status
3130ehci_device_intr_start(struct usbd_xfer *xfer)
3131{
3132 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
3133 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
3134 struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
3135 struct ehci_soft_qtd *data, *dataend;
3136 struct ehci_soft_qh *sqh;
3137 usbd_status err;
3138 int s;
3139
3140 KASSERT(!(xfer->rqflags & URQ_REQUEST))((!(xfer->rqflags & 0x01)) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/usb/ehci.c", 3140, "!(xfer->rqflags & URQ_REQUEST)"
))
;
3141
3142 if (sc->sc_bus.dying)
3143 return (USBD_IOERROR);
3144
3145 sqh = epipe->sqh;
3146
3147 err = ehci_alloc_sqtd_chain(sc, xfer->length, xfer, &data, &dataend);
3148 if (err) {
3149 xfer->status = err;
3150 usb_transfer_complete(xfer);
3151 return (err);
3152 }
3153
3154 /* Set up interrupt info. */
3155 ex->sqtdstart_TD.sqtd.start = data;
3156 ex->sqtdend_TD.sqtd.end = dataend;
3157#ifdef DIAGNOSTIC1
3158 if (!ex->isdone)
3159 printf("ehci_device_intr_start: not done, ex=%p\n", ex);
3160 ex->isdone = 0;
3161#endif
3162
3163 s = splusb()splraise(0x2);
3164 ehci_set_qh_qtd(sqh, data);
3165 if (xfer->timeout && !sc->sc_bus.use_polling) {
3166 timeout_del(&xfer->timeout_handle);
3167 timeout_set(&xfer->timeout_handle, ehci_timeout, xfer);
3168 timeout_add_msec(&xfer->timeout_handle, xfer->timeout);
3169 }
3170 TAILQ_INSERT_TAIL(&sc->sc_intrhead, ex, inext)do { (ex)->inext.tqe_next = ((void *)0); (ex)->inext.tqe_prev
= (&sc->sc_intrhead)->tqh_last; *(&sc->sc_intrhead
)->tqh_last = (ex); (&sc->sc_intrhead)->tqh_last
= &(ex)->inext.tqe_next; } while (0)
;
3171 xfer->status = USBD_IN_PROGRESS;
3172 splx(s)spllower(s);
3173
3174 return (USBD_IN_PROGRESS);
3175}
3176
3177void
3178ehci_device_intr_abort(struct usbd_xfer *xfer)
3179{
3180 KASSERT(!xfer->pipe->repeat || xfer->pipe->intrxfer == xfer)((!xfer->pipe->repeat || xfer->pipe->intrxfer == xfer
) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/usb/ehci.c"
, 3180, "!xfer->pipe->repeat || xfer->pipe->intrxfer == xfer"
))
;
3181
3182 /*
3183 * XXX - abort_xfer uses ehci_sync_hc, which syncs via the advance
3184 * async doorbell. That's dependant on the async list, whereas
3185 * intr xfers are periodic, should not use this?
3186 */
3187 ehci_abort_xfer(xfer, USBD_CANCELLED);
3188}
3189
3190void
3191ehci_device_intr_close(struct usbd_pipe *pipe)
3192{
3193 ehci_close_pipe(pipe);
3194}
3195
3196void
3197ehci_device_intr_done(struct usbd_xfer *xfer)
3198{
3199 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
3200 struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
3201 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
3202 struct ehci_soft_qtd *data, *dataend;
3203 struct ehci_soft_qh *sqh;
3204 usbd_status err;
3205 int s;
3206
3207 if (xfer->pipe->repeat) {
3208 ehci_free_sqtd_chain(sc, ex);
3209
3210 sqh = epipe->sqh;
3211
3212 err = ehci_alloc_sqtd_chain(sc, xfer->length, xfer, &data, &dataend);
3213 if (err) {
3214 xfer->status = err;
3215 return;
3216 }
3217
3218 /* Set up interrupt info. */
3219 ex->sqtdstart_TD.sqtd.start = data;
3220 ex->sqtdend_TD.sqtd.end = dataend;
3221#ifdef DIAGNOSTIC1
3222 if (!ex->isdone) {
3223 printf("ehci_device_intr_done: not done, ex=%p\n",
3224 ex);
3225 }
3226 ex->isdone = 0;
3227#endif
3228
3229 s = splusb()splraise(0x2);
3230 ehci_set_qh_qtd(sqh, data);
3231 if (xfer->timeout && !sc->sc_bus.use_polling) {
3232 timeout_del(&xfer->timeout_handle);
3233 timeout_set(&xfer->timeout_handle, ehci_timeout, xfer);
3234 timeout_add_msec(&xfer->timeout_handle, xfer->timeout);
3235 }
3236 TAILQ_INSERT_TAIL(&sc->sc_intrhead, ex, inext)do { (ex)->inext.tqe_next = ((void *)0); (ex)->inext.tqe_prev
= (&sc->sc_intrhead)->tqh_last; *(&sc->sc_intrhead
)->tqh_last = (ex); (&sc->sc_intrhead)->tqh_last
= &(ex)->inext.tqe_next; } while (0)
;
3237 xfer->status = USBD_IN_PROGRESS;
3238 splx(s)spllower(s);
3239 } else if (xfer->status != USBD_NOMEM) {
3240 ehci_free_sqtd_chain(sc, ex);
3241 }
3242}
3243
3244usbd_status
3245ehci_device_isoc_transfer(struct usbd_xfer *xfer)
3246{
3247 usbd_status err;
3248
3249 err = usb_insert_transfer(xfer);
3250 if (err && err != USBD_IN_PROGRESS)
3251 return (err);
3252
3253 return (ehci_device_isoc_start(xfer));
3254}
3255
3256usbd_status
3257ehci_device_isoc_start(struct usbd_xfer *xfer)
3258{
3259 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
3260 struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
3261 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
3262 usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc;
3263 uint8_t ival = ed->bInterval;
3264 struct ehci_soft_itd *itd;
3265 int s, frindex;
3266 uint32_t link;
3267
3268 KASSERT(!(xfer->rqflags & URQ_REQUEST))((!(xfer->rqflags & 0x01)) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/dev/usb/ehci.c", 3268, "!(xfer->rqflags & URQ_REQUEST)"
))
;
3269 KASSERT(ival > 0 && ival <= 16)((ival > 0 && ival <= 16) ? (void)0 : __assert(
"diagnostic ", "/usr/src/sys/dev/usb/ehci.c", 3269, "ival > 0 && ival <= 16"
))
;
3270
3271 /*
3272 * To allow continuous transfers, above we start all transfers
3273 * immediately. However, we're still going to get usbd_start_next call
3274 * this when another xfer completes. So, check if this is already
3275 * in progress or not
3276 */
3277 if (ex->itdstart_TD.itd.start != NULL((void *)0))
3278 return (USBD_IN_PROGRESS);
3279
3280 if (sc->sc_bus.dying)
3281 return (USBD_IOERROR);
3282
3283 /* Why would you do that anyway? */
3284 if (sc->sc_bus.use_polling)
3285 return (USBD_INVAL);
3286
3287 /*
3288 * To avoid complication, don't allow a request right now that'll span
3289 * the entire frame table. To within 4 frames, to allow some leeway
3290 * on either side of where the hc currently is.
3291 */
3292 if ((1 << (ival - 1)) * xfer->nframes >= (sc->sc_flsize - 4) * 8)
3293 return (USBD_INVAL);
3294
3295 /*
3296 * Step 1: Allocate and initialize itds.
3297 */
3298 if (xfer->device->speed == USB_SPEED_HIGH3) {
3299 if (ehci_alloc_itd_chain(sc, xfer))
3300 return (USBD_INVAL);
3301
3302 link = EHCI_LINK_ITD0x0;
3303 } else {
3304 if (ehci_alloc_sitd_chain(sc, xfer))
3305 return (USBD_INVAL);
3306
3307 link = EHCI_LINK_SITD0x4;
3308 }
3309
3310#ifdef DIAGNOSTIC1
3311 if (!ex->isdone) {
3312 printf("%s: not done, ex=%p\n", __func__, ex);
3313 }
3314 ex->isdone = 0;
3315#endif
3316
3317 /*
3318 * Part 2: Transfer descriptors have now been set up, now they must
3319 * be scheduled into the period frame list. Erk. Not wanting to
3320 * complicate matters, transfer is denied if the transfer spans
3321 * more than the period frame list.
3322 */
3323 s = splusb()splraise(0x2);
3324
3325 /* Start inserting frames */
3326 if (epipe->u.isoc.cur_xfers > 0) {
3327 frindex = epipe->u.isoc.next_frame;
3328 } else {
3329 frindex = EOREAD4(sc, EHCI_FRINDEX)(((sc)->iot)->read_4(((sc)->ioh), ((sc)->sc_offs+
(0x0c))))
;
3330 frindex = frindex >> 3; /* Erase microframe index */
3331 frindex += 2;
3332 }
3333
3334 if (frindex >= sc->sc_flsize)
3335 frindex &= (sc->sc_flsize - 1);
3336
3337 /* What's the frame interval? */
3338 ival = (1 << (ival - 1));
3339 if (ival / 8 == 0)
3340 ival = 1;
3341 else
3342 ival /= 8;
3343
3344 /* Abuse the fact that itd_next == sitd_next. */
3345 for (itd = ex->itdstart_TD.itd.start; itd != NULL((void *)0); itd = itd->xfer_next) {
3346 itd->itd.itd_next = sc->sc_flist[frindex];
3347 if (itd->itd.itd_next == 0)
3348 itd->itd.itd_next = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
3349
3350 sc->sc_flist[frindex] = htole32(link | itd->physaddr)((__uint32_t)(link | itd->physaddr));
3351 itd->u.frame_list.next = sc->sc_softitds[frindex];
3352 sc->sc_softitds[frindex] = itd;
3353 if (itd->u.frame_list.next != NULL((void *)0))
3354 itd->u.frame_list.next->u.frame_list.prev = itd;
3355 itd->slot = frindex;
3356 itd->u.frame_list.prev = NULL((void *)0);
3357
3358 frindex += ival;
3359 if (frindex >= sc->sc_flsize)
3360 frindex -= sc->sc_flsize;
3361 }
3362
3363 epipe->u.isoc.cur_xfers++;
3364 epipe->u.isoc.next_frame = frindex;
3365
3366 TAILQ_INSERT_TAIL(&sc->sc_intrhead, ex, inext)do { (ex)->inext.tqe_next = ((void *)0); (ex)->inext.tqe_prev
= (&sc->sc_intrhead)->tqh_last; *(&sc->sc_intrhead
)->tqh_last = (ex); (&sc->sc_intrhead)->tqh_last
= &(ex)->inext.tqe_next; } while (0)
;
3367 xfer->status = USBD_IN_PROGRESS;
3368 xfer->done = 0;
3369 splx(s)spllower(s);
3370
3371 return (USBD_IN_PROGRESS);
3372}
3373
3374int
3375ehci_alloc_itd_chain(struct ehci_softc *sc, struct usbd_xfer *xfer)
3376{
3377 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
3378 usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc;
3379 const uint32_t mps = UGETW(ed->wMaxPacketSize)(*(u_int16_t *)(ed->wMaxPacketSize));
3380 struct ehci_soft_itd *itd = NULL((void *)0), *pitd = NULL((void *)0);
3381 int i, j, nframes, uframes, ufrperframe;
3382 int offs = 0, trans_count = 0;
3383
3384 /*
3385 * How many itds do we need? One per transfer if interval >= 8
3386 * microframes, fewer if we use multiple microframes per frame.
3387 */
3388 switch (ed->bInterval) {
3389 case 1:
3390 ufrperframe = 8;
3391 break;
3392 case 2:
3393 ufrperframe = 4;
3394 break;
3395 case 3:
3396 ufrperframe = 2;
3397 break;
3398 default:
3399 ufrperframe = 1;
3400 break;
3401 }
3402 nframes = (xfer->nframes + (ufrperframe - 1)) / ufrperframe;
3403 uframes = 8 / ufrperframe;
3404 if (nframes == 0)
3405 return (1);
3406
3407 usb_syncmem(&xfer->dmabuf, 0, xfer->length,
3408 usbd_xfer_isread(xfer) ?
3409 BUS_DMASYNC_PREREAD0x01 : BUS_DMASYNC_PREWRITE0x04);
3410 for (i = 0; i < nframes; i++) {
3411 uint32_t froffs = offs;
3412
3413 itd = ehci_alloc_itd(sc);
3414 if (itd == NULL((void *)0)) {
3415 ehci_free_itd_chain(sc, ex);
3416 return (1);
3417 }
3418
3419 if (pitd != NULL((void *)0))
3420 pitd->xfer_next = itd;
3421 else
3422 ex->itdstart_TD.itd.start = itd;
3423
3424 /*
3425 * Step 1.5, initialize uframes
3426 */
3427 for (j = 0; j < 8; j += uframes) {
3428 /* Calculate which page in the list this starts in */
3429 int addr = DMAADDR(&xfer->dmabuf, froffs)((&xfer->dmabuf)->block->map->dm_segs[0].ds_addr
+ (&xfer->dmabuf)->offs + (froffs))
;
3430 addr = EHCI_PAGE_OFFSET(addr)((addr) & 0xfff) + (offs - froffs);
3431 addr = EHCI_PAGE(addr)((addr) &~ 0xfff) / EHCI_PAGE_SIZE0x1000;
3432
3433 /* This gets the initial offset into the first page,
3434 * looks how far further along the current uframe
3435 * offset is. Works out how many pages that is.
3436 */
3437 itd->itd.itd_ctl[j] = htole32(((__uint32_t)(0x80000000 | (((xfer->frlengths[trans_count]
) & 0xfff) << 16) | (((addr) & 0x7) << 12
) | (((((&xfer->dmabuf)->block->map->dm_segs[
0].ds_addr + (&xfer->dmabuf)->offs + (offs))) &
0xfff) << 0)))
3438 EHCI_ITD_ACTIVE |((__uint32_t)(0x80000000 | (((xfer->frlengths[trans_count]
) & 0xfff) << 16) | (((addr) & 0x7) << 12
) | (((((&xfer->dmabuf)->block->map->dm_segs[
0].ds_addr + (&xfer->dmabuf)->offs + (offs))) &
0xfff) << 0)))
3439 EHCI_ITD_SET_LEN(xfer->frlengths[trans_count]) |((__uint32_t)(0x80000000 | (((xfer->frlengths[trans_count]
) & 0xfff) << 16) | (((addr) & 0x7) << 12
) | (((((&xfer->dmabuf)->block->map->dm_segs[
0].ds_addr + (&xfer->dmabuf)->offs + (offs))) &
0xfff) << 0)))
3440 EHCI_ITD_SET_PG(addr) |((__uint32_t)(0x80000000 | (((xfer->frlengths[trans_count]
) & 0xfff) << 16) | (((addr) & 0x7) << 12
) | (((((&xfer->dmabuf)->block->map->dm_segs[
0].ds_addr + (&xfer->dmabuf)->offs + (offs))) &
0xfff) << 0)))
3441 EHCI_ITD_SET_OFFS(DMAADDR(&xfer->dmabuf, offs))((__uint32_t)(0x80000000 | (((xfer->frlengths[trans_count]
) & 0xfff) << 16) | (((addr) & 0x7) << 12
) | (((((&xfer->dmabuf)->block->map->dm_segs[
0].ds_addr + (&xfer->dmabuf)->offs + (offs))) &
0xfff) << 0)))
3442 )((__uint32_t)(0x80000000 | (((xfer->frlengths[trans_count]
) & 0xfff) << 16) | (((addr) & 0x7) << 12
) | (((((&xfer->dmabuf)->block->map->dm_segs[
0].ds_addr + (&xfer->dmabuf)->offs + (offs))) &
0xfff) << 0)))
;
3443
3444 offs += xfer->frlengths[trans_count];
3445 trans_count++;
3446
3447 if (trans_count >= xfer->nframes) { /*Set IOC*/
3448 itd->itd.itd_ctl[j] |= htole32(EHCI_ITD_IOC)((__uint32_t)(0x8000));
3449 break;
3450 }
3451 }
3452
3453 /* Step 1.75, set buffer pointers. To simplify matters, all
3454 * pointers are filled out for the next 7 hardware pages in
3455 * the dma block, so no need to worry what pages to cover
3456 * and what to not.
3457 */
3458
3459 for (j = 0; j < 7; j++) {
3460 /*
3461 * Don't try to lookup a page that's past the end
3462 * of buffer
3463 */
3464 int page_offs = EHCI_PAGE(froffs +((froffs + (0x1000 * j)) &~ 0xfff)
3465 (EHCI_PAGE_SIZE * j))((froffs + (0x1000 * j)) &~ 0xfff);
3466
3467 if (page_offs >= xfer->dmabuf.block->size)
3468 break;
3469
3470 long long page = DMAADDR(&xfer->dmabuf, page_offs)((&xfer->dmabuf)->block->map->dm_segs[0].ds_addr
+ (&xfer->dmabuf)->offs + (page_offs))
;
3471 page = EHCI_PAGE(page)((page) &~ 0xfff);
3472 itd->itd.itd_bufr[j] = htole32(page)((__uint32_t)(page));
3473 itd->itd.itd_bufr_hi[j] = htole32(page >> 32)((__uint32_t)(page >> 32));
3474 }
3475
3476 /*
3477 * Other special values
3478 */
3479 itd->itd.itd_bufr[0] |= htole32(((__uint32_t)((((((ed->bEndpointAddress) & 0x0f)) &
0xf) << 8) | ((xfer->pipe->device->address) &
0x7f)))
3480 EHCI_ITD_SET_ENDPT(UE_GET_ADDR(ed->bEndpointAddress)) |((__uint32_t)((((((ed->bEndpointAddress) & 0x0f)) &
0xf) << 8) | ((xfer->pipe->device->address) &
0x7f)))
3481 EHCI_ITD_SET_DADDR(xfer->pipe->device->address)((__uint32_t)((((((ed->bEndpointAddress) & 0x0f)) &
0xf) << 8) | ((xfer->pipe->device->address) &
0x7f)))
3482 )((__uint32_t)((((((ed->bEndpointAddress) & 0x0f)) &
0xf) << 8) | ((xfer->pipe->device->address) &
0x7f)))
;
3483
3484 itd->itd.itd_bufr[1] |= htole32(((__uint32_t)((usbd_xfer_isread(xfer) ? (((1) & 1) <<
11) : 0) | ((((mps) & 0x7ff)) & 0x7ff)))
3485 (usbd_xfer_isread(xfer) ? EHCI_ITD_SET_DIR(1) : 0) |((__uint32_t)((usbd_xfer_isread(xfer) ? (((1) & 1) <<
11) : 0) | ((((mps) & 0x7ff)) & 0x7ff)))
3486 EHCI_ITD_SET_MAXPKT(UE_GET_SIZE(mps))((__uint32_t)((usbd_xfer_isread(xfer) ? (((1) & 1) <<
11) : 0) | ((((mps) & 0x7ff)) & 0x7ff)))
3487 )((__uint32_t)((usbd_xfer_isread(xfer) ? (((1) & 1) <<
11) : 0) | ((((mps) & 0x7ff)) & 0x7ff)))
;
3488 /* FIXME: handle invalid trans */
3489 itd->itd.itd_bufr[2] |= htole32(((__uint32_t)((((((mps) >> 11) & 0x3)+1) & 0x3)
))
3490 EHCI_ITD_SET_MULTI(UE_GET_TRANS(mps)+1)((__uint32_t)((((((mps) >> 11) & 0x3)+1) & 0x3)
))
3491 )((__uint32_t)((((((mps) >> 11) & 0x3)+1) & 0x3)
))
;
3492
3493 pitd = itd;
3494 }
3495
3496 ex->itdend_TD.itd.end = itd;
3497
3498 return (0);
3499}
3500
3501int
3502ehci_alloc_sitd_chain(struct ehci_softc *sc, struct usbd_xfer *xfer)
3503{
3504 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
3505 struct usbd_device *hshub = xfer->device->myhsport->parent;
3506 usb_endpoint_descriptor_t *ed = xfer->pipe->endpoint->edesc;
3507 struct ehci_soft_itd *itd = NULL((void *)0), *pitd = NULL((void *)0);
3508 uint8_t smask, cmask, tp, uf;
3509 int i, nframes, offs = 0;
3510 uint32_t endp;
3511
3512 nframes = xfer->nframes;
3513 if (nframes == 0)
3514 return (1);
3515
3516 endp = EHCI_SITD_SET_ENDPT(UE_GET_ADDR(ed->bEndpointAddress))((((ed->bEndpointAddress) & 0x0f)) << 8) |
3517 EHCI_SITD_SET_ADDR(xfer->device->address)(xfer->device->address) |
3518 EHCI_SITD_SET_PORT(xfer->device->myhsport->portno)((xfer->device->myhsport->portno) << 23) |
3519 EHCI_SITD_SET_HUBA(hshub->address)((hshub->address) << 16);
3520
3521 if (usbd_xfer_isread(xfer))
3522 endp |= EHCI_SITD_SET_DIR(1)((1) << 31);
3523
3524 usb_syncmem(&xfer->dmabuf, 0, xfer->length,
3525 usbd_xfer_isread(xfer) ?
3526 BUS_DMASYNC_PREREAD0x01 : BUS_DMASYNC_PREWRITE0x04);
3527 for (i = 0; i < nframes; i++) {
3528 uint32_t addr = DMAADDR(&xfer->dmabuf, offs)((&xfer->dmabuf)->block->map->dm_segs[0].ds_addr
+ (&xfer->dmabuf)->offs + (offs))
;
3529 uint32_t page = EHCI_PAGE(addr + xfer->frlengths[i] - 1)((addr + xfer->frlengths[i] - 1) &~ 0xfff);
3530
3531 itd = ehci_alloc_itd(sc);
3532 if (itd == NULL((void *)0)) {
3533 ehci_free_itd_chain(sc, ex);
3534 return (1);
3535 }
3536 if (pitd)
3537 pitd->xfer_next = itd;
3538 else
3539 ex->itdstart_TD.itd.start = itd;
3540
3541 itd->sitd.sitd_endp = htole32(endp)((__uint32_t)(endp));
3542 itd->sitd.sitd_back = htole32(EHCI_LINK_TERMINATE)((__uint32_t)(0x00000001));
3543 itd->sitd.sitd_trans = htole32(((__uint32_t)(0x80 | (((xfer->frlengths[i]) & 0x3ff) <<
16) | ((i == nframes - 1) ? 0x80000000 : 0)))
3544 EHCI_SITD_ACTIVE |((__uint32_t)(0x80 | (((xfer->frlengths[i]) & 0x3ff) <<
16) | ((i == nframes - 1) ? 0x80000000 : 0)))
3545 EHCI_SITD_SET_LEN(xfer->frlengths[i]) |((__uint32_t)(0x80 | (((xfer->frlengths[i]) & 0x3ff) <<
16) | ((i == nframes - 1) ? 0x80000000 : 0)))
3546 ((i == nframes - 1) ? EHCI_SITD_IOC : 0)((__uint32_t)(0x80 | (((xfer->frlengths[i]) & 0x3ff) <<
16) | ((i == nframes - 1) ? 0x80000000 : 0)))
3547 )((__uint32_t)(0x80 | (((xfer->frlengths[i]) & 0x3ff) <<
16) | ((i == nframes - 1) ? 0x80000000 : 0)))
;
3548
3549 uf = max(1, ((xfer->frlengths[i] + 187) / 188));
3550
3551 /*
3552 * Since we do not yet budget and schedule micro-frames
3553 * we assume there is no other transfer using the same
3554 * TT.
3555 */
3556 if (usbd_xfer_isread(xfer)) {
3557 smask = 0x01;
3558 cmask = ((1 << (uf + 2)) - 1) << 2;
3559 } else {
3560 /* Is the payload is greater than 188 bytes? */
3561 if (uf == 1)
3562 tp = EHCI_SITD_TP_ALL0x0;
3563 else
3564 tp = EHCI_SITD_TP_BEGIN0x1;
3565
3566 page |= EHCI_SITD_SET_TCOUNT(uf)((uf) << 0) | EHCI_SITD_SET_TP(tp)((tp) << 3);
3567 smask = (1 << uf) - 1;
3568 cmask = 0x00;
3569 }
3570
3571 itd->sitd.sitd_sched = htole32(((__uint32_t)(((smask) << 0) | ((cmask) << 8)))
3572 EHCI_SITD_SET_SMASK(smask) | EHCI_SITD_SET_CMASK(cmask)((__uint32_t)(((smask) << 0) | ((cmask) << 8)))
3573 )((__uint32_t)(((smask) << 0) | ((cmask) << 8)));
3574 itd->sitd.sitd_bufr[0] = htole32(addr)((__uint32_t)(addr));
3575 itd->sitd.sitd_bufr[1] = htole32(page)((__uint32_t)(page));
3576
3577 offs += xfer->frlengths[i];
3578 pitd = itd;
3579 }
3580
3581 ex->itdend_TD.itd.end = itd;
3582
3583 return (0);
3584}
3585
3586void
3587ehci_device_isoc_abort(struct usbd_xfer *xfer)
3588{
3589 int s;
3590
3591 s = splusb()splraise(0x2);
3592 ehci_abort_isoc_xfer(xfer, USBD_CANCELLED);
3593 splx(s)spllower(s);
3594}
3595
3596void
3597ehci_device_isoc_close(struct usbd_pipe *pipe)
3598{
3599}
3600
3601void
3602ehci_device_isoc_done(struct usbd_xfer *xfer)
3603{
3604 struct ehci_softc *sc = (struct ehci_softc *)xfer->device->bus;
3605 struct ehci_pipe *epipe = (struct ehci_pipe *)xfer->pipe;
3606 struct ehci_xfer *ex = (struct ehci_xfer *)xfer;
3607 int s;
3608
3609 s = splusb()splraise(0x2);
3610 epipe->u.isoc.cur_xfers--;
3611 if (xfer->status != USBD_NOMEM) {
3612 ehci_rem_itd_chain(sc, ex);
3613 ehci_free_itd_chain(sc, ex);
3614 }
3615 splx(s)spllower(s);
3616}