Bug Summary

File:dev/usb/ohci.c
Warning:line 2759, column 20
Dereference of undefined pointer value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ohci.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -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 -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 -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/lib/clang/13.0.0 -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/swsmu -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/powerplay -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/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 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 -D CONFIG_DRM_AMD_DC_DCN3_0 -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 -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 /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/usb/ohci.c
1/* $OpenBSD: ohci.c,v 1.164 2022/01/09 05:43:00 jsg Exp $ */
2/* $NetBSD: ohci.c,v 1.139 2003/02/22 05:24:16 tsutsui Exp $ */
3/* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */
4
5/*
6 * Copyright (c) 1998 The NetBSD Foundation, Inc.
7 * All rights reserved.
8 *
9 * This code is derived from software contributed to The NetBSD Foundation
10 * by Lennart Augustsson (lennart@augustsson.net) at
11 * Carlstedt Research & Technology.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
25 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
26 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 */
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/malloc.h>
38#include <sys/device.h>
39#include <sys/queue.h>
40#include <sys/timeout.h>
41#include <sys/pool.h>
42#include <sys/endian.h>
43
44#include <machine/bus.h>
45
46#include <dev/usb/usb.h>
47#include <dev/usb/usbdi.h>
48#include <dev/usb/usbdivar.h>
49#include <dev/usb/usb_mem.h>
50
51#include <dev/usb/ohcireg.h>
52#include <dev/usb/ohcivar.h>
53
54struct cfdriver ohci_cd = {
55 NULL((void *)0), "ohci", DV_DULL, CD_SKIPHIBERNATE2
56};
57
58#ifdef OHCI_DEBUG
59#define DPRINTF(x) do { if (ohcidebug) printf x; } while (0)
60#define DPRINTFN(n,x) do { if (ohcidebug>(n)) printf x; } while (0)
61int ohcidebug = 0;
62#define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f))
63#else
64#define DPRINTF(x)
65#define DPRINTFN(n,x)
66#endif
67
68struct pool *ohcixfer;
69
70struct ohci_pipe;
71
72struct ohci_soft_ed *ohci_alloc_sed(struct ohci_softc *);
73void ohci_free_sed(struct ohci_softc *, struct ohci_soft_ed *);
74
75struct ohci_soft_td *ohci_alloc_std(struct ohci_softc *);
76void ohci_free_std(struct ohci_softc *, struct ohci_soft_td *);
77
78struct ohci_soft_itd *ohci_alloc_sitd(struct ohci_softc *);
79void ohci_free_sitd(struct ohci_softc *, struct ohci_soft_itd *);
80
81#if 0
82void ohci_free_std_chain(struct ohci_softc *, struct ohci_soft_td *,
83 struct ohci_soft_td *);
84#endif
85usbd_status ohci_alloc_std_chain(struct ohci_softc *, u_int,
86 struct usbd_xfer *, struct ohci_soft_td *,
87 struct ohci_soft_td **);
88
89usbd_status ohci_open(struct usbd_pipe *);
90int ohci_setaddr(struct usbd_device *, int);
91void ohci_poll(struct usbd_bus *);
92void ohci_softintr(void *);
93void ohci_add_done(struct ohci_softc *, ohci_physaddr_t);
94void ohci_rhsc(struct ohci_softc *, struct usbd_xfer *);
95
96usbd_status ohci_device_request(struct usbd_xfer *xfer);
97void ohci_add_ed(struct ohci_soft_ed *, struct ohci_soft_ed *);
98void ohci_rem_ed(struct ohci_soft_ed *, struct ohci_soft_ed *);
99void ohci_hash_add_td(struct ohci_softc *, struct ohci_soft_td *);
100struct ohci_soft_td *ohci_hash_find_td(struct ohci_softc *, ohci_physaddr_t);
101void ohci_hash_add_itd(struct ohci_softc *, struct ohci_soft_itd *);
102void ohci_hash_rem_itd(struct ohci_softc *, struct ohci_soft_itd *);
103struct ohci_soft_itd *ohci_hash_find_itd(struct ohci_softc *, ohci_physaddr_t);
104
105usbd_status ohci_setup_isoc(struct usbd_pipe *pipe);
106void ohci_device_isoc_enter(struct usbd_xfer *);
107
108struct usbd_xfer *ohci_allocx(struct usbd_bus *);
109void ohci_freex(struct usbd_bus *, struct usbd_xfer *);
110
111usbd_status ohci_root_ctrl_transfer(struct usbd_xfer *);
112usbd_status ohci_root_ctrl_start(struct usbd_xfer *);
113void ohci_root_ctrl_abort(struct usbd_xfer *);
114void ohci_root_ctrl_close(struct usbd_pipe *);
115void ohci_root_ctrl_done(struct usbd_xfer *);
116
117usbd_status ohci_root_intr_transfer(struct usbd_xfer *);
118usbd_status ohci_root_intr_start(struct usbd_xfer *);
119void ohci_root_intr_abort(struct usbd_xfer *);
120void ohci_root_intr_close(struct usbd_pipe *);
121void ohci_root_intr_done(struct usbd_xfer *);
122
123usbd_status ohci_device_ctrl_transfer(struct usbd_xfer *);
124usbd_status ohci_device_ctrl_start(struct usbd_xfer *);
125void ohci_device_ctrl_abort(struct usbd_xfer *);
126void ohci_device_ctrl_close(struct usbd_pipe *);
127void ohci_device_ctrl_done(struct usbd_xfer *);
128
129usbd_status ohci_device_bulk_transfer(struct usbd_xfer *);
130usbd_status ohci_device_bulk_start(struct usbd_xfer *);
131void ohci_device_bulk_abort(struct usbd_xfer *);
132void ohci_device_bulk_close(struct usbd_pipe *);
133void ohci_device_bulk_done(struct usbd_xfer *);
134
135usbd_status ohci_device_intr_transfer(struct usbd_xfer *);
136usbd_status ohci_device_intr_start(struct usbd_xfer *);
137void ohci_device_intr_abort(struct usbd_xfer *);
138void ohci_device_intr_close(struct usbd_pipe *);
139void ohci_device_intr_done(struct usbd_xfer *);
140
141usbd_status ohci_device_isoc_transfer(struct usbd_xfer *);
142usbd_status ohci_device_isoc_start(struct usbd_xfer *);
143void ohci_device_isoc_abort(struct usbd_xfer *);
144void ohci_device_isoc_close(struct usbd_pipe *);
145void ohci_device_isoc_done(struct usbd_xfer *);
146
147usbd_status ohci_device_setintr(struct ohci_softc *sc,
148 struct ohci_pipe *pipe, int ival);
149
150void ohci_timeout(void *);
151void ohci_timeout_task(void *);
152void ohci_rhsc_able(struct ohci_softc *, int);
153void ohci_rhsc_enable(void *);
154
155void ohci_close_pipe(struct usbd_pipe *, struct ohci_soft_ed *);
156void ohci_abort_xfer(struct usbd_xfer *, usbd_status);
157
158void ohci_device_clear_toggle(struct usbd_pipe *pipe);
159
160#ifdef OHCI_DEBUG
161void ohci_dumpregs(struct ohci_softc *);
162void ohci_dump_tds(struct ohci_soft_td *);
163void ohci_dump_td(struct ohci_soft_td *);
164void ohci_dump_ed(struct ohci_soft_ed *);
165void ohci_dump_itd(struct ohci_soft_itd *);
166void ohci_dump_itds(struct ohci_soft_itd *);
167#endif
168
169#define OBARR(sc)bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size
, 0x01|0x02)
bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size, \
170 BUS_SPACE_BARRIER_READ0x01|BUS_SPACE_BARRIER_WRITE0x02)
171#define OWRITE1(sc, r, x)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_1(((sc)->ioh
), ((r)), ((x)))); } while (0)
\
172 do { OBARR(sc)bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size
, 0x01|0x02)
; bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x))(((sc)->iot)->write_1(((sc)->ioh), ((r)), ((x)))); } while (0)
173#define OWRITE2(sc, r, x)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_2(((sc)->ioh
), ((r)), ((x)))); } while (0)
\
174 do { OBARR(sc)bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size
, 0x01|0x02)
; bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x))(((sc)->iot)->write_2(((sc)->ioh), ((r)), ((x)))); } while (0)
175#define OWRITE4(sc, r, x)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((r)), ((x)))); } while (0)
\
176 do { OBARR(sc)bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size
, 0x01|0x02)
; bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x))(((sc)->iot)->write_4(((sc)->ioh), ((r)), ((x)))); } while (0)
177
178__unused__attribute__((__unused__)) static __inline u_int8_t
179OREAD1(struct ohci_softc *sc, bus_size_t r)
180{
181 OBARR(sc)bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size
, 0x01|0x02)
;
182 return bus_space_read_1(sc->iot, sc->ioh, r)((sc->iot)->read_1((sc->ioh), (r)));
183}
184
185__unused__attribute__((__unused__)) static __inline u_int16_t
186OREAD2(struct ohci_softc *sc, bus_size_t r)
187{
188 OBARR(sc)bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size
, 0x01|0x02)
;
189 return bus_space_read_2(sc->iot, sc->ioh, r)((sc->iot)->read_2((sc->ioh), (r)));
190}
191
192__unused__attribute__((__unused__)) static __inline u_int32_t
193OREAD4(struct ohci_softc *sc, bus_size_t r)
194{
195 OBARR(sc)bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size
, 0x01|0x02)
;
196 return bus_space_read_4(sc->iot, sc->ioh, r)((sc->iot)->read_4((sc->ioh), (r)));
197}
198
199/* Reverse the bits in a value 0 .. 31 */
200u_int8_t revbits[OHCI_NO_INTRS32] =
201 { 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c,
202 0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e,
203 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
204 0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f };
205
206struct ohci_pipe {
207 struct usbd_pipe pipe;
208 struct ohci_soft_ed *sed;
209 union {
210 struct ohci_soft_td *td;
211 struct ohci_soft_itd *itd;
212 } tail;
213 union {
214 /* Control pipe */
215 struct {
216 struct usb_dma reqdma;
217 } ctl;
218 /* Interrupt pipe */
219 struct {
220 int nslots;
221 int pos;
222 } intr;
223 /* Iso pipe */
224 struct iso {
225 int next, inuse;
226 } iso;
227 } u;
228};
229
230#define OHCI_INTR_ENDPT1 1
231
232struct usbd_bus_methods ohci_bus_methods = {
233 .open_pipe = ohci_open,
234 .dev_setaddr = ohci_setaddr,
235 .soft_intr = ohci_softintr,
236 .do_poll = ohci_poll,
237 .allocx = ohci_allocx,
238 .freex = ohci_freex,
239};
240
241struct usbd_pipe_methods ohci_root_ctrl_methods = {
242 .transfer = ohci_root_ctrl_transfer,
243 .start = ohci_root_ctrl_start,
244 .abort = ohci_root_ctrl_abort,
245 .close = ohci_root_ctrl_close,
246 .done = ohci_root_ctrl_done,
247};
248
249struct usbd_pipe_methods ohci_root_intr_methods = {
250 .transfer = ohci_root_intr_transfer,
251 .start = ohci_root_intr_start,
252 .abort = ohci_root_intr_abort,
253 .close = ohci_root_intr_close,
254 .done = ohci_root_intr_done,
255};
256
257struct usbd_pipe_methods ohci_device_ctrl_methods = {
258 .transfer = ohci_device_ctrl_transfer,
259 .start = ohci_device_ctrl_start,
260 .abort = ohci_device_ctrl_abort,
261 .close = ohci_device_ctrl_close,
262 .done = ohci_device_ctrl_done,
263};
264
265struct usbd_pipe_methods ohci_device_intr_methods = {
266 .transfer = ohci_device_intr_transfer,
267 .start = ohci_device_intr_start,
268 .abort = ohci_device_intr_abort,
269 .close = ohci_device_intr_close,
270 .cleartoggle = ohci_device_clear_toggle,
271 .done = ohci_device_intr_done,
272};
273
274struct usbd_pipe_methods ohci_device_bulk_methods = {
275 .transfer = ohci_device_bulk_transfer,
276 .start = ohci_device_bulk_start,
277 .abort = ohci_device_bulk_abort,
278 .close = ohci_device_bulk_close,
279 .cleartoggle = ohci_device_clear_toggle,
280 .done = ohci_device_bulk_done,
281};
282
283struct usbd_pipe_methods ohci_device_isoc_methods = {
284 .transfer = ohci_device_isoc_transfer,
285 .start = ohci_device_isoc_start,
286 .abort = ohci_device_isoc_abort,
287 .close = ohci_device_isoc_close,
288 .done = ohci_device_isoc_done,
289};
290
291int
292ohci_activate(struct device *self, int act)
293{
294 struct ohci_softc *sc = (struct ohci_softc *)self;
295 u_int32_t reg;
296 int rv = 0;
297
298 switch (act) {
299 case DVACT_SUSPEND3:
300 rv = config_activate_children(self, act);
301 sc->sc_bus.use_polling++;
302 reg = OREAD4(sc, OHCI_CONTROL0x04) & ~OHCI_HCFS_MASK0x000000c0;
303 if (sc->sc_control == 0) {
304 /*
305 * Preserve register values, in case that APM BIOS
306 * does not recover them.
307 */
308 sc->sc_control = reg;
309 sc->sc_intre = OREAD4(sc, OHCI_INTERRUPT_ENABLE0x10);
310 sc->sc_ival = OHCI_GET_IVAL(OREAD4(sc,((OREAD4(sc, 0x34)) & 0x3fff)
311 OHCI_FM_INTERVAL))((OREAD4(sc, 0x34)) & 0x3fff);
312 }
313 reg |= OHCI_HCFS_SUSPEND0x000000c0;
314 OWRITE4(sc, OHCI_CONTROL, reg)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x04)), ((reg)))); } while (0)
;
315 usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT50);
316 sc->sc_bus.use_polling--;
317 break;
318 case DVACT_RESUME4:
319 sc->sc_bus.use_polling++;
320
321 /* Some broken BIOSes do not recover these values */
322 OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0))do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x18)), ((((&sc->sc_hccadma)->block->map->
dm_segs[0].ds_addr + (&sc->sc_hccadma)->offs + (0))
)))); } while (0)
;
323 OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x20)), ((sc->sc_ctrl_head->physaddr)))); } while (
0)
;
324 OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x28)), ((sc->sc_bulk_head->physaddr)))); } while (
0)
;
325 if (sc->sc_intre)
326 OWRITE4(sc, OHCI_INTERRUPT_ENABLE,do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x10)), ((sc->sc_intre & ((0x00000001 | 0x00000002
| 0x00000004 | 0x00000008 | 0x00000010 | 0x00000020 | 0x00000040
| 0x40000000) | 0x80000000))))); } while (0)
327 sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE))do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x10)), ((sc->sc_intre & ((0x00000001 | 0x00000002
| 0x00000004 | 0x00000008 | 0x00000010 | 0x00000020 | 0x00000040
| 0x40000000) | 0x80000000))))); } while (0)
;
328 if (sc->sc_control)
329 reg = sc->sc_control;
330 else
331 reg = OREAD4(sc, OHCI_CONTROL0x04);
332 reg |= OHCI_HCFS_RESUME0x00000040;
333 OWRITE4(sc, OHCI_CONTROL, reg)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x04)), ((reg)))); } while (0)
;
334 usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY(50*5));
335 reg = (reg & ~OHCI_HCFS_MASK0x000000c0) | OHCI_HCFS_OPERATIONAL0x00000080;
336 OWRITE4(sc, OHCI_CONTROL, reg)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x04)), ((reg)))); } while (0)
;
337
338 reg = (OREAD4(sc, OHCI_FM_REMAINING0x38) & OHCI_FIT0x80000000) ^ OHCI_FIT0x80000000;
339 reg |= OHCI_FSMPS(sc->sc_ival)(((sc->sc_ival-210)*6/7) << 16) | sc->sc_ival;
340 OWRITE4(sc, OHCI_FM_INTERVAL, reg)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x34)), ((reg)))); } while (0)
;
341 OWRITE4(sc, OHCI_PERIODIC_START, OHCI_PERIODIC(sc->sc_ival))do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x40)), ((((sc->sc_ival)*9/10))))); } while (0)
;
342
343 /* Fiddle the No OverCurrent Protection to avoid a chip bug */
344 reg = OREAD4(sc, OHCI_RH_DESCRIPTOR_A0x48);
345 OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, reg | OHCI_NOCP)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x48)), ((reg | 0x1000)))); } while (0)
;
346 OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x50)), ((0x00010000)))); } while (0)
; /* Enable port power */
347 usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY5);
348 OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, reg)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x48)), ((reg)))); } while (0)
;
349
350 usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY50);
351 sc->sc_control = sc->sc_intre = sc->sc_ival = 0;
352 sc->sc_bus.use_polling--;
353 rv = config_activate_children(self, act);
354 break;
355 case DVACT_POWERDOWN6:
356 rv = config_activate_children(self, act);
357 OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x04)), ((0x00000000)))); } while (0)
;
358 break;
359 default:
360 rv = config_activate_children(self, act);
361 break;
362 }
363 return (rv);
364}
365
366int
367ohci_detach(struct device *self, int flags)
368{
369 struct ohci_softc *sc = (struct ohci_softc *)self;
370 int rv;
371
372 rv = config_detach_children(self, flags);
373 if (rv != 0)
374 return (rv);
375
376 timeout_del(&sc->sc_tmo_rhsc);
377
378 usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */
379
380 /* free data structures XXX */
381
382 return (rv);
383}
384
385struct ohci_soft_ed *
386ohci_alloc_sed(struct ohci_softc *sc)
387{
388 struct ohci_soft_ed *sed = NULL((void *)0);
389 usbd_status err;
390 int i, offs;
391 struct usb_dma dma;
392 int s;
393
394 s = splusb()splraise(0x5);
395 if (sc->sc_freeeds == NULL((void *)0)) {
396 DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n"));
397 err = usb_allocmem(&sc->sc_bus, OHCI_SED_SIZE((sizeof (struct ohci_soft_ed) + 16 - 1) / 16 * 16) * OHCI_SED_CHUNK128,
398 OHCI_ED_ALIGN16, USB_DMA_COHERENT(1 << 0), &dma);
399 if (err)
400 goto out;
401 for (i = 0; i < OHCI_SED_CHUNK128; i++) {
402 offs = i * OHCI_SED_SIZE((sizeof (struct ohci_soft_ed) + 16 - 1) / 16 * 16);
403 sed = KERNADDR(&dma, offs)((void *)((char *)((&dma)->block->kaddr + (&dma
)->offs) + (offs)))
;
404 sed->physaddr = DMAADDR(&dma, offs)((&dma)->block->map->dm_segs[0].ds_addr + (&
dma)->offs + (offs))
;
405 sed->next = sc->sc_freeeds;
406 sc->sc_freeeds = sed;
407 }
408 }
409 sed = sc->sc_freeeds;
410 sc->sc_freeeds = sed->next;
411 memset(&sed->ed, 0, sizeof(struct ohci_ed))__builtin_memset((&sed->ed), (0), (sizeof(struct ohci_ed
)))
;
412 sed->next = NULL((void *)0);
413
414out:
415 splx(s)spllower(s);
416 return (sed);
417}
418
419void
420ohci_free_sed(struct ohci_softc *sc, struct ohci_soft_ed *sed)
421{
422 int s;
423
424 s = splusb()splraise(0x5);
425 sed->next = sc->sc_freeeds;
426 sc->sc_freeeds = sed;
427 splx(s)spllower(s);
428}
429
430struct ohci_soft_td *
431ohci_alloc_std(struct ohci_softc *sc)
432{
433 struct ohci_soft_td *std = NULL((void *)0);
434 usbd_status err;
435 int i, offs;
436 struct usb_dma dma;
437 int s;
438
439 s = splusb()splraise(0x5);
440 if (sc->sc_freetds == NULL((void *)0)) {
441 DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n"));
442 err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE((sizeof (struct ohci_soft_td) + 16 - 1) / 16 * 16) * OHCI_STD_CHUNK128,
443 OHCI_TD_ALIGN16, USB_DMA_COHERENT(1 << 0), &dma);
444 if (err)
445 goto out;
446 for (i = 0; i < OHCI_STD_CHUNK128; i++) {
447 offs = i * OHCI_STD_SIZE((sizeof (struct ohci_soft_td) + 16 - 1) / 16 * 16);
448 std = KERNADDR(&dma, offs)((void *)((char *)((&dma)->block->kaddr + (&dma
)->offs) + (offs)))
;
449 std->physaddr = DMAADDR(&dma, offs)((&dma)->block->map->dm_segs[0].ds_addr + (&
dma)->offs + (offs))
;
450 std->nexttd = sc->sc_freetds;
451 sc->sc_freetds = std;
452 }
453 }
454
455 std = sc->sc_freetds;
456 sc->sc_freetds = std->nexttd;
457 memset(&std->td, 0, sizeof(struct ohci_td))__builtin_memset((&std->td), (0), (sizeof(struct ohci_td
)))
;
458 std->nexttd = NULL((void *)0);
459 std->xfer = NULL((void *)0);
460 ohci_hash_add_td(sc, std);
461
462out:
463 splx(s)spllower(s);
464 return (std);
465}
466
467void
468ohci_free_std(struct ohci_softc *sc, struct ohci_soft_td *std)
469{
470 int s;
471
472 s = splusb()splraise(0x5);
473 LIST_REMOVE(std, hnext)do { if ((std)->hnext.le_next != ((void *)0)) (std)->hnext
.le_next->hnext.le_prev = (std)->hnext.le_prev; *(std)->
hnext.le_prev = (std)->hnext.le_next; ((std)->hnext.le_prev
) = ((void *)-1); ((std)->hnext.le_next) = ((void *)-1); }
while (0)
;
474 std->nexttd = sc->sc_freetds;
475 sc->sc_freetds = std;
476 splx(s)spllower(s);
477}
478
479usbd_status
480ohci_alloc_std_chain(struct ohci_softc *sc, u_int alen, struct usbd_xfer *xfer,
481 struct ohci_soft_td *sp, struct ohci_soft_td **ep)
482{
483 struct ohci_soft_td *next, *cur, *end;
484 ohci_physaddr_t dataphys, dataphysend;
485 u_int32_t tdflags;
486 u_int len, curlen;
487 int mps;
488 int rd = usbd_xfer_isread(xfer);
489 struct usb_dma *dma = &xfer->dmabuf;
490 u_int16_t flags = xfer->flags;
491
492 DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%u\n", alen));
493
494 usb_syncmem(&xfer->dmabuf, 0, xfer->length,
495 usbd_xfer_isread(xfer) ?
10
Assuming the condition is false
11
'?' condition is false
496 BUS_DMASYNC_PREREAD0x01 : BUS_DMASYNC_PREWRITE0x04);
497
498 len = alen;
499 cur = sp;
500 end = NULL((void *)0);
501
502 dataphys = DMAADDR(dma, 0)((dma)->block->map->dm_segs[0].ds_addr + (dma)->offs
+ (0))
;
503 dataphysend = OHCI_PAGE(dataphys + len - 1)((dataphys + len - 1) &~ 0xfff);
504 tdflags = htole32(((__uint32_t)((rd ? 0x00100000 : 0x00080000) | (flags & 0x04
? 0x00040000 : 0) | 0xf0000000 | 0x00000000 | 0x00e00000))
12
'?' condition is false
13
Assuming the condition is false
14
'?' condition is false
505 (rd ? OHCI_TD_IN : OHCI_TD_OUT) |((__uint32_t)((rd ? 0x00100000 : 0x00080000) | (flags & 0x04
? 0x00040000 : 0) | 0xf0000000 | 0x00000000 | 0x00e00000))
506 (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |((__uint32_t)((rd ? 0x00100000 : 0x00080000) | (flags & 0x04
? 0x00040000 : 0) | 0xf0000000 | 0x00000000 | 0x00e00000))
507 OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR)((__uint32_t)((rd ? 0x00100000 : 0x00080000) | (flags & 0x04
? 0x00040000 : 0) | 0xf0000000 | 0x00000000 | 0x00e00000))
;
508 mps = UGETW(xfer->pipe->endpoint->edesc->wMaxPacketSize)(*(u_int16_t *)(xfer->pipe->endpoint->edesc->wMaxPacketSize
))
;
509
510 while (len > 0) {
15
Assuming 'len' is > 0
16
Loop condition is true. Entering loop body
511 next = ohci_alloc_std(sc);
512 if (next == NULL((void *)0))
17
Assuming 'next' is equal to NULL
18
Taking true branch
513 goto nomem;
19
Control jumps to line 577
514
515 /* The OHCI hardware can handle at most one page crossing. */
516 if (OHCI_PAGE(dataphys)((dataphys) &~ 0xfff) == dataphysend ||
517 OHCI_PAGE(dataphys)((dataphys) &~ 0xfff) + OHCI_PAGE_SIZE0x1000 == dataphysend) {
518 /* we can handle it in this TD */
519 curlen = len;
520 } else {
521 /* must use multiple TDs, fill as much as possible. */
522 curlen = 2 * OHCI_PAGE_SIZE0x1000 -
523 (dataphys & (OHCI_PAGE_SIZE0x1000-1));
524 /* the length must be a multiple of the max size */
525 curlen -= curlen % mps;
526#ifdef DIAGNOSTIC1
527 if (curlen == 0)
528 panic("ohci_alloc_std: curlen == 0");
529#endif
530 }
531 DPRINTFN(4,("ohci_alloc_std_chain: dataphys=0x%08x "
532 "dataphysend=0x%08x len=%u curlen=%u\n",
533 dataphys, dataphysend,
534 len, curlen));
535 len -= curlen;
536
537 cur->td.td_flags = tdflags;
538 cur->td.td_cbp = htole32(dataphys)((__uint32_t)(dataphys));
539 cur->nexttd = next;
540 cur->td.td_nexttd = htole32(next->physaddr)((__uint32_t)(next->physaddr));
541 cur->td.td_be = htole32(dataphys + curlen - 1)((__uint32_t)(dataphys + curlen - 1));
542 cur->len = curlen;
543 cur->flags = OHCI_ADD_LEN0x0002;
544 cur->xfer = xfer;
545 DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x\n",
546 dataphys, dataphys + curlen - 1));
547 DPRINTFN(10,("ohci_alloc_std_chain: extend chain\n"));
548 dataphys += curlen;
549 end = cur;
550 cur = next;
551 }
552 if (!rd && ((flags & USBD_FORCE_SHORT_XFER0x08) || alen == 0) &&
553 alen % mps == 0) {
554 /* Force a 0 length transfer at the end. */
555
556 next = ohci_alloc_std(sc);
557 if (next == NULL((void *)0))
558 goto nomem;
559
560 cur->td.td_flags = tdflags;
561 cur->td.td_cbp = 0; /* indicate 0 length packet */
562 cur->nexttd = next;
563 cur->td.td_nexttd = htole32(next->physaddr)((__uint32_t)(next->physaddr));
564 cur->td.td_be = ~0;
565 cur->len = 0;
566 cur->flags = 0;
567 cur->xfer = xfer;
568 DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
569 end = cur;
570 }
571 *ep = end;
572
573 return (USBD_NORMAL_COMPLETION);
574
575 nomem:
576 /* XXX free chain */
577 return (USBD_NOMEM);
20
Returning without writing to '*ep'
578}
579
580#if 0
581void
582ohci_free_std_chain(struct ohci_softc *sc, struct ohci_soft_td *std,
583 struct ohci_soft_td *stdend)
584{
585 struct ohci_soft_td *p;
586
587 for (; std != stdend; std = p) {
588 p = std->nexttd;
589 ohci_free_std(sc, std);
590 }
591}
592#endif
593
594struct ohci_soft_itd *
595ohci_alloc_sitd(struct ohci_softc *sc)
596{
597 struct ohci_soft_itd *sitd;
598 usbd_status err;
599 int i, s, offs;
600 struct usb_dma dma;
601
602 if (sc->sc_freeitds == NULL((void *)0)) {
603 DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n"));
604 err = usb_allocmem(&sc->sc_bus, OHCI_SITD_SIZE((sizeof (struct ohci_soft_itd) + 32 - 1) / 32 * 32) * OHCI_SITD_CHUNK64,
605 OHCI_ITD_ALIGN32, USB_DMA_COHERENT(1 << 0), &dma);
606 if (err)
607 return (NULL((void *)0));
608 s = splusb()splraise(0x5);
609 for(i = 0; i < OHCI_SITD_CHUNK64; i++) {
610 offs = i * OHCI_SITD_SIZE((sizeof (struct ohci_soft_itd) + 32 - 1) / 32 * 32);
611 sitd = KERNADDR(&dma, offs)((void *)((char *)((&dma)->block->kaddr + (&dma
)->offs) + (offs)))
;
612 sitd->physaddr = DMAADDR(&dma, offs)((&dma)->block->map->dm_segs[0].ds_addr + (&
dma)->offs + (offs))
;
613 sitd->nextitd = sc->sc_freeitds;
614 sc->sc_freeitds = sitd;
615 }
616 splx(s)spllower(s);
617 }
618
619 s = splusb()splraise(0x5);
620 sitd = sc->sc_freeitds;
621 sc->sc_freeitds = sitd->nextitd;
622 memset(&sitd->itd, 0, sizeof(struct ohci_itd))__builtin_memset((&sitd->itd), (0), (sizeof(struct ohci_itd
)))
;
623 sitd->nextitd = NULL((void *)0);
624 sitd->xfer = NULL((void *)0);
625 ohci_hash_add_itd(sc, sitd);
626 splx(s)spllower(s);
627
628#ifdef DIAGNOSTIC1
629 sitd->isdone = 0;
630#endif
631
632 return (sitd);
633}
634
635void
636ohci_free_sitd(struct ohci_softc *sc, struct ohci_soft_itd *sitd)
637{
638 int s;
639
640 DPRINTFN(10,("ohci_free_sitd: sitd=%p\n", sitd));
641
642#ifdef DIAGNOSTIC1
643 if (!sitd->isdone) {
644 panic("ohci_free_sitd: sitd=%p not done", sitd);
645 return;
646 }
647 /* Warn double free */
648 sitd->isdone = 0;
649#endif
650
651 s = splusb()splraise(0x5);
652 ohci_hash_rem_itd(sc, sitd);
653 sitd->nextitd = sc->sc_freeitds;
654 sc->sc_freeitds = sitd;
655 splx(s)spllower(s);
656}
657
658usbd_status
659ohci_checkrev(struct ohci_softc *sc)
660{
661 u_int32_t rev;
662
663 rev = OREAD4(sc, OHCI_REVISION0x00);
664 printf("version %d.%d%s\n", OHCI_REV_HI(rev)(((rev)>>4)&0xf), OHCI_REV_LO(rev)((rev)&0xf),
665 OHCI_REV_LEGACY(rev)((rev) & 0x100) ? ", legacy support" : "");
666
667 if (OHCI_REV_HI(rev)(((rev)>>4)&0xf) != 1 || OHCI_REV_LO(rev)((rev)&0xf) != 0) {
668 printf("%s: unsupported OHCI revision\n",
669 sc->sc_bus.bdev.dv_xname);
670 sc->sc_bus.usbrev = USBREV_UNKNOWN0;
671 return (USBD_INVAL);
672 }
673 sc->sc_bus.usbrev = USBREV_1_02;
674
675 return (USBD_NORMAL_COMPLETION);
676}
677
678usbd_status
679ohci_handover(struct ohci_softc *sc)
680{
681 u_int32_t s, ctl;
682 int i;
683
684 ctl = OREAD4(sc, OHCI_CONTROL0x04);
685 if (ctl & OHCI_IR0x00000100) {
686 /* SMM active, request change */
687 DPRINTF(("ohci_handover: SMM active, request owner change\n"));
688 if ((sc->sc_intre & (OHCI_OC0x40000000 | OHCI_MIE0x80000000)) ==
689 (OHCI_OC0x40000000 | OHCI_MIE0x80000000))
690 OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_MIE)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x10)), ((0x80000000)))); } while (0)
;
691 s = OREAD4(sc, OHCI_COMMAND_STATUS0x08);
692 OWRITE4(sc, OHCI_COMMAND_STATUS, s | OHCI_OCR)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x08)), ((s | 0x00000008)))); } while (0)
;
693 for (i = 0; i < 100 && (ctl & OHCI_IR0x00000100); i++) {
694 usb_delay_ms(&sc->sc_bus, 1);
695 ctl = OREAD4(sc, OHCI_CONTROL0x04);
696 }
697 OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_MIE)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x14)), ((0x80000000)))); } while (0)
;
698 if (ctl & OHCI_IR0x00000100) {
699 printf("%s: SMM does not respond, will reset\n",
700 sc->sc_bus.bdev.dv_xname);
701 }
702 }
703
704 return (USBD_NORMAL_COMPLETION);
705}
706
707usbd_status
708ohci_init(struct ohci_softc *sc)
709{
710 struct ohci_soft_ed *sed, *psed;
711 usbd_status err;
712 int i;
713 u_int32_t ctl, rwc, ival, hcr, fm, per, desca, descb;
714
715 DPRINTF(("ohci_init: start\n"));
716
717 for (i = 0; i < OHCI_HASH_SIZE128; i++)
718 LIST_INIT(&sc->sc_hash_tds[i])do { ((&sc->sc_hash_tds[i])->lh_first) = ((void *)0
); } while (0)
;
719 for (i = 0; i < OHCI_HASH_SIZE128; i++)
720 LIST_INIT(&sc->sc_hash_itds[i])do { ((&sc->sc_hash_itds[i])->lh_first) = ((void *)
0); } while (0)
;
721
722 if (ohcixfer == NULL((void *)0)) {
723 ohcixfer = malloc(sizeof(struct pool), M_USBHC103, M_NOWAIT0x0002);
724 if (ohcixfer == NULL((void *)0)) {
725 printf("%s: unable to allocate pool descriptor\n",
726 sc->sc_bus.bdev.dv_xname);
727 return (ENOMEM12);
728 }
729 pool_init(ohcixfer, sizeof(struct ohci_xfer), 0, IPL_SOFTUSB0x5,
730 0, "ohcixfer", NULL((void *)0));
731 }
732
733 /* XXX determine alignment by R/W */
734 /* Allocate the HCCA area. */
735 err = usb_allocmem(&sc->sc_bus, OHCI_HCCA_SIZE256, OHCI_HCCA_ALIGN256,
736 USB_DMA_COHERENT(1 << 0), &sc->sc_hccadma);
737 if (err)
738 return (err);
739 sc->sc_hcca = KERNADDR(&sc->sc_hccadma, 0)((void *)((char *)((&sc->sc_hccadma)->block->kaddr
+ (&sc->sc_hccadma)->offs) + (0)))
;
740 memset(sc->sc_hcca, 0, OHCI_HCCA_SIZE)__builtin_memset((sc->sc_hcca), (0), (256));
741
742 sc->sc_eintrs = OHCI_NORMAL_INTRS(0x00000001 | 0x00000002 | 0x00000008 | 0x00000010 | 0x00000040
)
;
743
744 /* Allocate dummy ED that starts the control list. */
745 sc->sc_ctrl_head = ohci_alloc_sed(sc);
746 if (sc->sc_ctrl_head == NULL((void *)0)) {
747 err = USBD_NOMEM;
748 goto bad1;
749 }
750 sc->sc_ctrl_head->ed.ed_flags |= htole32(OHCI_ED_SKIP)((__uint32_t)(0x00004000));
751
752 /* Allocate dummy ED that starts the bulk list. */
753 sc->sc_bulk_head = ohci_alloc_sed(sc);
754 if (sc->sc_bulk_head == NULL((void *)0)) {
755 err = USBD_NOMEM;
756 goto bad2;
757 }
758 sc->sc_bulk_head->ed.ed_flags |= htole32(OHCI_ED_SKIP)((__uint32_t)(0x00004000));
759
760 /* Allocate dummy ED that starts the isochronous list. */
761 sc->sc_isoc_head = ohci_alloc_sed(sc);
762 if (sc->sc_isoc_head == NULL((void *)0)) {
763 err = USBD_NOMEM;
764 goto bad3;
765 }
766 sc->sc_isoc_head->ed.ed_flags |= htole32(OHCI_ED_SKIP)((__uint32_t)(0x00004000));
767
768 /* Allocate all the dummy EDs that make up the interrupt tree. */
769 for (i = 0; i < OHCI_NO_EDS(2*32 -1); i++) {
770 sed = ohci_alloc_sed(sc);
771 if (sed == NULL((void *)0)) {
772 while (--i >= 0)
773 ohci_free_sed(sc, sc->sc_eds[i]);
774 err = USBD_NOMEM;
775 goto bad4;
776 }
777 /* All ED fields are set to 0. */
778 sc->sc_eds[i] = sed;
779 sed->ed.ed_flags |= htole32(OHCI_ED_SKIP)((__uint32_t)(0x00004000));
780 if (i != 0)
781 psed = sc->sc_eds[(i-1) / 2];
782 else
783 psed= sc->sc_isoc_head;
784 sed->next = psed;
785 sed->ed.ed_nexted = htole32(psed->physaddr)((__uint32_t)(psed->physaddr));
786 }
787 /*
788 * Fill HCCA interrupt table. The bit reversal is to get
789 * the tree set up properly to spread the interrupts.
790 */
791 for (i = 0; i < OHCI_NO_INTRS32; i++)
792 sc->sc_hcca->hcca_interrupt_table[revbits[i]] =
793 htole32(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]->physaddr)((__uint32_t)(sc->sc_eds[(2*32 -1)-32 +i]->physaddr));
794
795#ifdef OHCI_DEBUG
796 if (ohcidebug > 15) {
797 for (i = 0; i < OHCI_NO_EDS(2*32 -1); i++) {
798 printf("ed#%d ", i);
799 ohci_dump_ed(sc->sc_eds[i]);
800 }
801 printf("iso ");
802 ohci_dump_ed(sc->sc_isoc_head);
803 }
804#endif
805 /* Preserve values programmed by SMM/BIOS but lost over reset. */
806 ctl = OREAD4(sc, OHCI_CONTROL0x04);
807 rwc = ctl & OHCI_RWC0x00000200;
808 fm = OREAD4(sc, OHCI_FM_INTERVAL0x34);
809 desca = OREAD4(sc, OHCI_RH_DESCRIPTOR_A0x48);
810 descb = OREAD4(sc, OHCI_RH_DESCRIPTOR_B0x4c);
811
812 /* Determine in what context we are running. */
813 if (ctl & OHCI_IR0x00000100) {
814 OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET | rwc)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x04)), ((0x00000000 | rwc)))); } while (0)
;
815 goto reset;
816#if 0
817/* Don't bother trying to reuse the BIOS init, we'll reset it anyway. */
818 } else if ((ctl & OHCI_HCFS_MASK0x000000c0) != OHCI_HCFS_RESET0x00000000) {
819 /* BIOS started controller. */
820 DPRINTF(("ohci_init: BIOS active\n"));
821 if ((ctl & OHCI_HCFS_MASK0x000000c0) != OHCI_HCFS_OPERATIONAL0x00000080) {
822 OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_OPERATIONAL | rwc)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x04)), ((0x00000080 | rwc)))); } while (0)
;
823 usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY(50*5));
824 }
825#endif
826 } else {
827 DPRINTF(("ohci_init: cold started\n"));
828 reset:
829 /* Controller was cold started. */
830 usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY100);
831 }
832
833 /*
834 * This reset should not be necessary according to the OHCI spec, but
835 * without it some controllers do not start.
836 */
837 DPRINTF(("%s: resetting\n", sc->sc_bus.bdev.dv_xname));
838 OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET | rwc)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x04)), ((0x00000000 | rwc)))); } while (0)
;
839 usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY100);
840
841 /* We now own the host controller and the bus has been reset. */
842
843 OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_HCR)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x08)), ((0x00000001)))); } while (0)
; /* Reset HC */
844 /* Nominal time for a reset is 10 us. */
845 for (i = 0; i < 10; i++) {
846 delay(10)(*delay_func)(10);
847 hcr = OREAD4(sc, OHCI_COMMAND_STATUS0x08) & OHCI_HCR0x00000001;
848 if (!hcr)
849 break;
850 }
851 if (hcr) {
852 printf("%s: reset timeout\n", sc->sc_bus.bdev.dv_xname);
853 err = USBD_IOERROR;
854 goto bad5;
855 }
856#ifdef OHCI_DEBUG
857 if (ohcidebug > 15)
858 ohci_dumpregs(sc);
859#endif
860
861 /* The controller is now in SUSPEND state, we have 2ms to finish. */
862
863 /* Set up HC registers. */
864 OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0))do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x18)), ((((&sc->sc_hccadma)->block->map->
dm_segs[0].ds_addr + (&sc->sc_hccadma)->offs + (0))
)))); } while (0)
;
865 OWRITE4(sc, OHCI_CONTROL_HEAD_ED, sc->sc_ctrl_head->physaddr)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x20)), ((sc->sc_ctrl_head->physaddr)))); } while (
0)
;
866 OWRITE4(sc, OHCI_BULK_HEAD_ED, sc->sc_bulk_head->physaddr)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x28)), ((sc->sc_bulk_head->physaddr)))); } while (
0)
;
867 /* disable all interrupts and then switch on all desired interrupts */
868 OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x14)), (((0x00000001 | 0x00000002 | 0x00000004 | 0x00000008
| 0x00000010 | 0x00000020 | 0x00000040 | 0x40000000))))); } while
(0)
;
869 /* switch on desired functional features */
870 ctl = OREAD4(sc, OHCI_CONTROL0x04);
871 ctl &= ~(OHCI_CBSR_MASK0x00000003 | OHCI_LES(0x00000004 | 0x00000008 | 0x00000010 | 0x00000020) | OHCI_HCFS_MASK0x000000c0 | OHCI_IR0x00000100);
872 ctl |= OHCI_PLE0x00000004 | OHCI_IE0x00000008 | OHCI_CLE0x00000010 | OHCI_BLE0x00000020 |
873 OHCI_RATIO_1_40x00000003 | OHCI_HCFS_OPERATIONAL0x00000080 | rwc;
874 /* And finally start it! */
875 OWRITE4(sc, OHCI_CONTROL, ctl)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x04)), ((ctl)))); } while (0)
;
876
877 /*
878 * The controller is now OPERATIONAL. Set a some final
879 * registers that should be set earlier, but that the
880 * controller ignores when in the SUSPEND state.
881 */
882 ival = OHCI_GET_IVAL(fm)((fm) & 0x3fff);
883 fm = (OREAD4(sc, OHCI_FM_REMAINING0x38) & OHCI_FIT0x80000000) ^ OHCI_FIT0x80000000;
884 fm |= OHCI_FSMPS(ival)(((ival-210)*6/7) << 16) | ival;
885 OWRITE4(sc, OHCI_FM_INTERVAL, fm)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x34)), ((fm)))); } while (0)
;
886 per = OHCI_PERIODIC(ival)((ival)*9/10); /* 90% periodic */
887 OWRITE4(sc, OHCI_PERIODIC_START, per)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x40)), ((per)))); } while (0)
;
888
889 /* Fiddle the No OverCurrent Protection bit to avoid chip bug. */
890 OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca | OHCI_NOCP)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x48)), ((desca | 0x1000)))); } while (0)
;
891 OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x50)), ((0x00010000)))); } while (0)
; /* Enable port power */
892 usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY5);
893 OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x48)), ((desca)))); } while (0)
;
894 OWRITE4(sc, OHCI_RH_DESCRIPTOR_B, descb)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x4c)), ((descb)))); } while (0)
;
895 usb_delay_ms(&sc->sc_bus, OHCI_GET_POTPGT(desca)((desca) >> 24) * UHD_PWRON_FACTOR2);
896
897 /*
898 * The AMD756 requires a delay before re-reading the register,
899 * otherwise it will occasionally report 0 ports.
900 */
901 sc->sc_noport = 0;
902 for (i = 0; i < 10 && sc->sc_noport == 0; i++) {
903 usb_delay_ms(&sc->sc_bus, OHCI_READ_DESC_DELAY5);
904 sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A))((OREAD4(sc, 0x48)) & 0xff);
905 }
906
907#ifdef OHCI_DEBUG
908 if (ohcidebug > 5)
909 ohci_dumpregs(sc);
910#endif
911
912 /* Set up the bus struct. */
913 sc->sc_bus.methods = &ohci_bus_methods;
914 sc->sc_bus.pipe_size = sizeof(struct ohci_pipe);
915
916 sc->sc_control = sc->sc_intre = 0;
917
918 timeout_set(&sc->sc_tmo_rhsc, ohci_rhsc_enable, sc);
919
920 /* Finally, turn on interrupts. */
921 DPRINTFN(1,("ohci_init: enabling\n"));
922 OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x10)), ((sc->sc_eintrs | 0x80000000)))); } while (0)
;
923
924 return (USBD_NORMAL_COMPLETION);
925
926 bad5:
927 for (i = 0; i < OHCI_NO_EDS(2*32 -1); i++)
928 ohci_free_sed(sc, sc->sc_eds[i]);
929 bad4:
930 ohci_free_sed(sc, sc->sc_isoc_head);
931 bad3:
932 ohci_free_sed(sc, sc->sc_bulk_head);
933 bad2:
934 ohci_free_sed(sc, sc->sc_ctrl_head);
935 bad1:
936 usb_freemem(&sc->sc_bus, &sc->sc_hccadma);
937 return (err);
938}
939
940struct usbd_xfer *
941ohci_allocx(struct usbd_bus *bus)
942{
943 return (pool_get(ohcixfer, PR_NOWAIT0x0002 | PR_ZERO0x0008));
944}
945
946void
947ohci_freex(struct usbd_bus *bus, struct usbd_xfer *xfer)
948{
949 pool_put(ohcixfer, xfer);
950}
951
952#ifdef OHCI_DEBUG
953void
954ohci_dumpregs(struct ohci_softc *sc)
955{
956 DPRINTF(("ohci_dumpregs: rev=0x%08x control=0x%08x command=0x%08x\n",
957 OREAD4(sc, OHCI_REVISION),
958 OREAD4(sc, OHCI_CONTROL),
959 OREAD4(sc, OHCI_COMMAND_STATUS)));
960 DPRINTF((" intrstat=0x%08x intre=0x%08x intrd=0x%08x\n",
961 OREAD4(sc, OHCI_INTERRUPT_STATUS),
962 OREAD4(sc, OHCI_INTERRUPT_ENABLE),
963 OREAD4(sc, OHCI_INTERRUPT_DISABLE)));
964 DPRINTF((" hcca=0x%08x percur=0x%08x ctrlhd=0x%08x\n",
965 OREAD4(sc, OHCI_HCCA),
966 OREAD4(sc, OHCI_PERIOD_CURRENT_ED),
967 OREAD4(sc, OHCI_CONTROL_HEAD_ED)));
968 DPRINTF((" ctrlcur=0x%08x bulkhd=0x%08x bulkcur=0x%08x\n",
969 OREAD4(sc, OHCI_CONTROL_CURRENT_ED),
970 OREAD4(sc, OHCI_BULK_HEAD_ED),
971 OREAD4(sc, OHCI_BULK_CURRENT_ED)));
972 DPRINTF((" done=0x%08x fmival=0x%08x fmrem=0x%08x\n",
973 OREAD4(sc, OHCI_DONE_HEAD),
974 OREAD4(sc, OHCI_FM_INTERVAL),
975 OREAD4(sc, OHCI_FM_REMAINING)));
976 DPRINTF((" fmnum=0x%08x perst=0x%08x lsthrs=0x%08x\n",
977 OREAD4(sc, OHCI_FM_NUMBER),
978 OREAD4(sc, OHCI_PERIODIC_START),
979 OREAD4(sc, OHCI_LS_THRESHOLD)));
980 DPRINTF((" desca=0x%08x descb=0x%08x stat=0x%08x\n",
981 OREAD4(sc, OHCI_RH_DESCRIPTOR_A),
982 OREAD4(sc, OHCI_RH_DESCRIPTOR_B),
983 OREAD4(sc, OHCI_RH_STATUS)));
984 DPRINTF((" port1=0x%08x port2=0x%08x\n",
985 OREAD4(sc, OHCI_RH_PORT_STATUS(1)),
986 OREAD4(sc, OHCI_RH_PORT_STATUS(2))));
987 DPRINTF((" HCCA: frame_number=0x%04x done_head=0x%08x\n",
988 letoh32(sc->sc_hcca->hcca_frame_number),
989 letoh32(sc->sc_hcca->hcca_done_head)));
990}
991#endif
992
993int ohci_intr1(struct ohci_softc *);
994
995int
996ohci_intr(void *p)
997{
998 struct ohci_softc *sc = p;
999
1000 if (sc == NULL((void *)0) || sc->sc_bus.dying)
1001 return (0);
1002
1003 /* If we get an interrupt while polling, then just ignore it. */
1004 if (sc->sc_bus.use_polling) {
1005#ifdef DIAGNOSTIC1
1006 static struct timeval ohci_intr_tv;
1007 if ((OREAD4(sc, OHCI_INTERRUPT_STATUS0x0c) & sc->sc_eintrs) &&
1008 usbd_ratecheck(&ohci_intr_tv))
1009 DPRINTFN(16,
1010 ("ohci_intr: ignored interrupt while polling\n"));
1011#endif
1012 return (0);
1013 }
1014
1015 return (ohci_intr1(sc));
1016}
1017
1018int
1019ohci_intr1(struct ohci_softc *sc)
1020{
1021 u_int32_t intrs, eintrs;
1022 ohci_physaddr_t done;
1023
1024 DPRINTFN(14,("ohci_intr1: enter\n"));
1025
1026 /* In case the interrupt occurs before initialization has completed. */
1027 if (sc == NULL((void *)0) || sc->sc_hcca == NULL((void *)0)) {
1028#ifdef DIAGNOSTIC1
1029 printf("ohci_intr: sc->sc_hcca == NULL\n");
1030#endif
1031 return (0);
1032 }
1033
1034 intrs = 0;
1035 done = letoh32(sc->sc_hcca->hcca_done_head)((__uint32_t)(sc->sc_hcca->hcca_done_head));
1036 if (done != 0) {
1037 if (done & ~OHCI_DONE_INTRS1)
1038 intrs = OHCI_WDH0x00000002;
1039 if (done & OHCI_DONE_INTRS1)
1040 intrs |= OREAD4(sc, OHCI_INTERRUPT_STATUS0x0c);
1041 sc->sc_hcca->hcca_done_head = 0;
1042 } else {
1043 intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS0x0c);
1044 /* If we've flushed out a WDH then reread */
1045 if (intrs & OHCI_WDH0x00000002) {
1046 done = letoh32(sc->sc_hcca->hcca_done_head)((__uint32_t)(sc->sc_hcca->hcca_done_head));
1047 sc->sc_hcca->hcca_done_head = 0;
1048 }
1049 }
1050
1051 if (intrs == 0xffffffff) {
1052 sc->sc_bus.dying = 1;
1053 return (0);
1054 }
1055
1056 if (!intrs)
1057 return (0);
1058
1059 intrs &= ~OHCI_MIE0x80000000;
1060 OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x0c)), ((intrs)))); } while (0)
; /* Acknowledge */
1061 eintrs = intrs & sc->sc_eintrs;
1062 if (!eintrs)
1063 return (0);
1064
1065 sc->sc_bus.intr_context++;
1066 sc->sc_bus.no_intrs++;
1067 DPRINTFN(7, ("ohci_intr: sc=%p intrs=0x%x(0x%x) eintrs=0x%x\n",
1068 sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS),
1069 (u_int)eintrs));
1070
1071 if (eintrs & OHCI_SO0x00000001) {
1072 sc->sc_overrun_cnt++;
1073 if (usbd_ratecheck(&sc->sc_overrun_ntc)) {
1074 printf("%s: %u scheduling overruns\n",
1075 sc->sc_bus.bdev.dv_xname, sc->sc_overrun_cnt);
1076 sc->sc_overrun_cnt = 0;
1077 }
1078 /* XXX do what */
1079 eintrs &= ~OHCI_SO0x00000001;
1080 }
1081 if (eintrs & OHCI_WDH0x00000002) {
1082 ohci_add_done(sc, done &~ OHCI_DONE_INTRS1);
1083 usb_schedsoftintr(&sc->sc_bus);
1084 eintrs &= ~OHCI_WDH0x00000002;
1085 }
1086 if (eintrs & OHCI_RD0x00000008) {
1087 printf("%s: resume detect\n", sc->sc_bus.bdev.dv_xname);
1088 /* XXX process resume detect */
1089 }
1090 if (eintrs & OHCI_UE0x00000010) {
1091 printf("%s: unrecoverable error, controller halted\n",
1092 sc->sc_bus.bdev.dv_xname);
1093 OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x04)), ((0x00000000)))); } while (0)
;
1094 /* XXX what else */
1095 }
1096 if (eintrs & OHCI_RHSC0x00000040) {
1097 ohci_rhsc(sc, sc->sc_intrxfer);
1098 /*
1099 * Disable RHSC interrupt for now, because it will be
1100 * on until the port has been reset.
1101 */
1102 ohci_rhsc_able(sc, 0);
1103 DPRINTFN(2, ("%s: rhsc interrupt disabled\n",
1104 sc->sc_bus.bdev.dv_xname));
1105
1106 /* Do not allow RHSC interrupts > 1 per second */
1107 timeout_add_sec(&sc->sc_tmo_rhsc, 1);
1108 eintrs &= ~OHCI_RHSC0x00000040;
1109 }
1110
1111 sc->sc_bus.intr_context--;
1112
1113 if (eintrs != 0) {
1114 /* Block unprocessed interrupts. XXX */
1115 OWRITE4(sc, OHCI_INTERRUPT_DISABLE, eintrs)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x14)), ((eintrs)))); } while (0)
;
1116 sc->sc_eintrs &= ~eintrs;
1117 printf("%s: blocking intrs 0x%x\n",
1118 sc->sc_bus.bdev.dv_xname, eintrs);
1119 }
1120
1121 return (1);
1122}
1123
1124void
1125ohci_rhsc_able(struct ohci_softc *sc, int on)
1126{
1127 DPRINTFN(4, ("ohci_rhsc_able: on=%d\n", on));
1128 if (on) {
1129 sc->sc_eintrs |= OHCI_RHSC0x00000040;
1130 OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_RHSC)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x10)), ((0x00000040)))); } while (0)
;
1131 } else {
1132 sc->sc_eintrs &= ~OHCI_RHSC0x00000040;
1133 OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_RHSC)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x14)), ((0x00000040)))); } while (0)
;
1134 }
1135}
1136
1137void
1138ohci_rhsc_enable(void *v_sc)
1139{
1140 struct ohci_softc *sc = v_sc;
1141 int s;
1142
1143 if (sc->sc_bus.dying)
1144 return;
1145
1146 s = splhardusb()splraise(0x6);
1147 ohci_rhsc(sc, sc->sc_intrxfer);
1148 DPRINTFN(2, ("%s: rhsc interrupt enabled\n",
1149 sc->sc_bus.bdev.dv_xname));
1150
1151 ohci_rhsc_able(sc, 1);
1152 splx(s)spllower(s);
1153}
1154
1155#ifdef OHCI_DEBUG
1156char *ohci_cc_strs[] = {
1157 "NO_ERROR",
1158 "CRC",
1159 "BIT_STUFFING",
1160 "DATA_TOGGLE_MISMATCH",
1161 "STALL",
1162 "DEVICE_NOT_RESPONDING",
1163 "PID_CHECK_FAILURE",
1164 "UNEXPECTED_PID",
1165 "DATA_OVERRUN",
1166 "DATA_UNDERRUN",
1167 "BUFFER_OVERRUN",
1168 "BUFFER_UNDERRUN",
1169 "reserved",
1170 "reserved",
1171 "NOT_ACCESSED",
1172 "NOT_ACCESSED",
1173};
1174#endif
1175
1176void
1177ohci_add_done(struct ohci_softc *sc, ohci_physaddr_t done)
1178{
1179 struct ohci_soft_itd *sitd, *sidone, **ip;
1180 struct ohci_soft_td *std, *sdone, **p;
1181
1182 /* Reverse the done list. */
1183 for (sdone = NULL((void *)0), sidone = NULL((void *)0); done != 0; ) {
1184 std = ohci_hash_find_td(sc, done);
1185 if (std != NULL((void *)0)) {
1186 std->dnext = sdone;
1187 done = letoh32(std->td.td_nexttd)((__uint32_t)(std->td.td_nexttd));
1188 sdone = std;
1189 DPRINTFN(10,("add TD %p\n", std));
1190 continue;
1191 }
1192 sitd = ohci_hash_find_itd(sc, done);
1193 if (sitd != NULL((void *)0)) {
1194 sitd->dnext = sidone;
1195 done = letoh32(sitd->itd.itd_nextitd)((__uint32_t)(sitd->itd.itd_nextitd));
1196 sidone = sitd;
1197 DPRINTFN(5,("add ITD %p\n", sitd));
1198 continue;
1199 }
1200 panic("ohci_add_done: addr 0x%08lx not found", (u_long)done);
1201 }
1202
1203 /* sdone & sidone now hold the done lists. */
1204 /* Put them on the already processed lists. */
1205 for (p = &sc->sc_sdone; *p != NULL((void *)0); p = &(*p)->dnext)
1206 ;
1207 *p = sdone;
1208 for (ip = &sc->sc_sidone; *ip != NULL((void *)0); ip = &(*ip)->dnext)
1209 ;
1210 *ip = sidone;
1211}
1212
1213void
1214ohci_softintr(void *v)
1215{
1216 struct ohci_softc *sc = v;
1217 struct ohci_soft_itd *sitd, *sidone, *sitdnext;
1218 struct ohci_soft_td *std, *sdone, *stdnext;
1219 struct usbd_xfer *xfer;
1220 struct ohci_pipe *opipe;
1221 int len, cc, s;
1222 int i, j, actlen, iframes, uedir;
1223
1224 DPRINTFN(10,("ohci_softintr: enter\n"));
1225
1226 if (sc->sc_bus.dying)
1227 return;
1228
1229 sc->sc_bus.intr_context++;
1230
1231 s = splhardusb()splraise(0x6);
1232 sdone = sc->sc_sdone;
1233 sc->sc_sdone = NULL((void *)0);
1234 sidone = sc->sc_sidone;
1235 sc->sc_sidone = NULL((void *)0);
1236 splx(s)spllower(s);
1237
1238 DPRINTFN(10,("ohci_softintr: sdone=%p sidone=%p\n", sdone, sidone));
1239
1240#ifdef OHCI_DEBUG
1241 if (ohcidebug > 10) {
1242 DPRINTF(("ohci_process_done: TD done:\n"));
1243 ohci_dump_tds(sdone);
1244 }
1245#endif
1246
1247 for (std = sdone; std; std = stdnext) {
1248 xfer = std->xfer;
1249 stdnext = std->dnext;
1250 DPRINTFN(10, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n",
1251 std, xfer, xfer ? xfer->hcpriv : 0));
1252 if (xfer == NULL((void *)0)) {
1253 /*
1254 * xfer == NULL: There seems to be no xfer associated
1255 * with this TD. It is tailp that happened to end up on
1256 * the done queue.
1257 * Shouldn't happen, but some chips are broken(?).
1258 */
1259 continue;
1260 }
1261 if (xfer->status == USBD_CANCELLED ||
1262 xfer->status == USBD_TIMEOUT) {
1263 DPRINTF(("ohci_process_done: cancel/timeout %p\n",
1264 xfer));
1265 /* Handled by abort routine. */
1266 continue;
1267 }
1268 timeout_del(&xfer->timeout_handle);
1269 usb_rem_task(xfer->device, &xfer->abort_task);
1270
1271 len = std->len;
1272 if (std->td.td_cbp != 0)
1273 len -= letoh32(std->td.td_be)((__uint32_t)(std->td.td_be)) -
1274 letoh32(std->td.td_cbp)((__uint32_t)(std->td.td_cbp)) + 1;
1275 DPRINTFN(10, ("ohci_process_done: len=%d, flags=0x%x\n", len,
1276 std->flags));
1277 if (std->flags & OHCI_ADD_LEN0x0002)
1278 xfer->actlen += len;
1279
1280 cc = OHCI_TD_GET_CC(letoh32(std->td.td_flags))((((__uint32_t)(std->td.td_flags))) >> 28);
1281 if (cc == OHCI_CC_NO_ERROR0) {
1282 int done = (std->flags & OHCI_CALL_DONE0x0001);
1283
1284 ohci_free_std(sc, std);
1285 if (done) {
1286 if (xfer->actlen)
1287 usb_syncmem(&xfer->dmabuf, 0,
1288 xfer->actlen,
1289 usbd_xfer_isread(xfer) ?
1290 BUS_DMASYNC_POSTREAD0x02 :
1291 BUS_DMASYNC_POSTWRITE0x08);
1292 xfer->status = USBD_NORMAL_COMPLETION;
1293 s = splusb()splraise(0x5);
1294 usb_transfer_complete(xfer);
1295 splx(s)spllower(s);
1296 }
1297 } else {
1298 /*
1299 * Endpoint is halted. First unlink all the TDs
1300 * belonging to the failed transfer, and then restart
1301 * the endpoint.
1302 */
1303 struct ohci_soft_td *p, *n;
1304 opipe = (struct ohci_pipe *)xfer->pipe;
1305
1306 DPRINTFN(15,("ohci_process_done: error cc=%d (%s)\n",
1307 OHCI_TD_GET_CC(letoh32(std->td.td_flags)),
1308 ohci_cc_strs[OHCI_TD_GET_CC(letoh32(std->td.td_flags))]));
1309
1310 /* remove TDs */
1311 for (p = std; p->xfer == xfer; p = n) {
1312 n = p->nexttd;
1313 ohci_free_std(sc, p);
1314 }
1315
1316 /* clear halt */
1317 opipe->sed->ed.ed_headp = htole32(p->physaddr)((__uint32_t)(p->physaddr));
1318 OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x08)), ((0x00000002)))); } while (0)
;
1319
1320 if (cc == OHCI_CC_STALL4)
1321 xfer->status = USBD_STALLED;
1322 else if (cc == OHCI_CC_DATA_UNDERRUN9) {
1323 if (xfer->actlen)
1324 usb_syncmem(&xfer->dmabuf, 0,
1325 xfer->actlen,
1326 usbd_xfer_isread(xfer) ?
1327 BUS_DMASYNC_POSTREAD0x02 :
1328 BUS_DMASYNC_POSTWRITE0x08);
1329 xfer->status = USBD_NORMAL_COMPLETION;
1330 } else
1331 xfer->status = USBD_IOERROR;
1332 s = splusb()splraise(0x5);
1333 usb_transfer_complete(xfer);
1334 splx(s)spllower(s);
1335 }
1336 }
1337
1338#ifdef OHCI_DEBUG
1339 if (ohcidebug > 10) {
1340 DPRINTF(("ohci_softintr: ITD done:\n"));
1341 ohci_dump_itds(sidone);
1342 }
1343#endif
1344
1345 for (sitd = sidone; sitd != NULL((void *)0); sitd = sitdnext) {
1346 xfer = sitd->xfer;
1347 sitdnext = sitd->dnext;
1348 DPRINTFN(1, ("ohci_process_done: sitd=%p xfer=%p hcpriv=%p\n",
1349 sitd, xfer, xfer ? xfer->hcpriv : 0));
1350 if (xfer == NULL((void *)0))
1351 continue;
1352 if (xfer->status == USBD_CANCELLED ||
1353 xfer->status == USBD_TIMEOUT) {
1354 DPRINTF(("ohci_process_done: cancel/timeout %p\n",
1355 xfer));
1356 /* Handled by abort routine. */
1357 continue;
1358 }
1359#ifdef DIAGNOSTIC1
1360 if (sitd->isdone)
1361 printf("ohci_softintr: sitd=%p is done\n", sitd);
1362 sitd->isdone = 1;
1363#endif
1364 if (sitd->flags & OHCI_CALL_DONE0x0001) {
1365 struct ohci_soft_itd *next;
1366
1367 opipe = (struct ohci_pipe *)xfer->pipe;
1368 opipe->u.iso.inuse -= xfer->nframes;
1369 uedir = UE_GET_DIR(xfer->pipe->endpoint->edesc->((xfer->pipe->endpoint->edesc-> bEndpointAddress)
& 0x80)
1370 bEndpointAddress)((xfer->pipe->endpoint->edesc-> bEndpointAddress)
& 0x80)
;
1371 xfer->status = USBD_NORMAL_COMPLETION;
1372 actlen = 0;
1373 for (i = 0, sitd = xfer->hcpriv; ;
1374 sitd = next) {
1375 next = sitd->nextitd;
1376 if (OHCI_ITD_GET_CC(letoh32(sitd->((((__uint32_t)(sitd-> itd.itd_flags))) >> 28)
1377 itd.itd_flags))((((__uint32_t)(sitd-> itd.itd_flags))) >> 28) != OHCI_CC_NO_ERROR0)
1378 xfer->status = USBD_IOERROR;
1379 /* For input, update frlengths with actual */
1380 /* XXX anything necessary for output? */
1381 if (uedir == UE_DIR_IN0x80 &&
1382 xfer->status == USBD_NORMAL_COMPLETION) {
1383 iframes = OHCI_ITD_GET_FC(letoh32(((((((__uint32_t)(sitd->itd.itd_flags))) >> 24) &
7)+1)
1384 sitd->itd.itd_flags))((((((__uint32_t)(sitd->itd.itd_flags))) >> 24) &
7)+1)
;
1385 for (j = 0; j < iframes; i++, j++) {
1386 len = letoh16(sitd->((__uint16_t)(sitd-> itd.itd_offset[j]))
1387 itd.itd_offset[j])((__uint16_t)(sitd-> itd.itd_offset[j]));
1388 if ((OHCI_ITD_PSW_GET_CC(len)((len) >> 12) &
1389 OHCI_CC_NOT_ACCESSED_MASK14)
1390 == OHCI_CC_NOT_ACCESSED14)
1391 len = 0;
1392 else
1393 len = OHCI_ITD_PSW_LENGTH(len)((len) & 0xfff);
1394 xfer->frlengths[i] = len;
1395 actlen += len;
1396 }
1397 }
1398 if (sitd->flags & OHCI_CALL_DONE0x0001)
1399 break;
1400 ohci_free_sitd(sc, sitd);
1401 }
1402 ohci_free_sitd(sc, sitd);
1403 if (uedir == UE_DIR_IN0x80 &&
1404 xfer->status == USBD_NORMAL_COMPLETION)
1405 xfer->actlen = actlen;
1406 xfer->hcpriv = NULL((void *)0);
1407
1408 if (xfer->status == USBD_NORMAL_COMPLETION) {
1409 usb_syncmem(&xfer->dmabuf, 0, xfer->length,
1410 usbd_xfer_isread(xfer) ?
1411 BUS_DMASYNC_POSTREAD0x02 :
1412 BUS_DMASYNC_POSTWRITE0x08);
1413 }
1414
1415 s = splusb()splraise(0x5);
1416 usb_transfer_complete(xfer);
1417 splx(s)spllower(s);
1418 }
1419 }
1420
1421 if (sc->sc_softwake) {
1422 sc->sc_softwake = 0;
1423 wakeup(&sc->sc_softwake);
1424 }
1425
1426 sc->sc_bus.intr_context--;
1427 DPRINTFN(10,("ohci_softintr: done:\n"));
1428}
1429
1430void
1431ohci_device_ctrl_done(struct usbd_xfer *xfer)
1432{
1433 DPRINTFN(10,("ohci_device_ctrl_done: xfer=%p\n", xfer));
1434
1435#ifdef DIAGNOSTIC1
1436 if (!(xfer->rqflags & URQ_REQUEST0x01)) {
1437 panic("ohci_device_ctrl_done: not a request");
1438 }
1439#endif
1440}
1441
1442void
1443ohci_device_intr_done(struct usbd_xfer *xfer)
1444{
1445 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
1446 struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
1447 struct ohci_soft_ed *sed = opipe->sed;
1448 struct ohci_soft_td *data, *tail;
1449
1450
1451 DPRINTFN(10, ("ohci_device_intr_done: xfer=%p, actlen=%d\n", xfer,
1452 xfer->actlen));
1453
1454 if (xfer->pipe->repeat) {
1455 data = opipe->tail.td;
1456 tail = ohci_alloc_std(sc);
1457 if (tail == NULL((void *)0)) {
1458 xfer->status = USBD_NOMEM;
1459 return;
1460 }
1461 tail->xfer = NULL((void *)0);
1462
1463 data->td.td_flags = htole32(((__uint32_t)(0x00100000 | 0xf0000000 | ((1) << 21) | 0x00000000
))
1464 OHCI_TD_IN | OHCI_TD_NOCC |((__uint32_t)(0x00100000 | 0xf0000000 | ((1) << 21) | 0x00000000
))
1465 OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY)((__uint32_t)(0x00100000 | 0xf0000000 | ((1) << 21) | 0x00000000
))
;
1466 if (xfer->flags & USBD_SHORT_XFER_OK0x04)
1467 data->td.td_flags |= htole32(OHCI_TD_R)((__uint32_t)(0x00040000));
1468 data->td.td_cbp = htole32(DMAADDR(&xfer->dmabuf, 0))((__uint32_t)(((&xfer->dmabuf)->block->map->dm_segs
[0].ds_addr + (&xfer->dmabuf)->offs + (0))))
;
1469 data->nexttd = tail;
1470 data->td.td_nexttd = htole32(tail->physaddr)((__uint32_t)(tail->physaddr));
1471 data->td.td_be = htole32(letoh32(data->td.td_cbp) +((__uint32_t)(((__uint32_t)(data->td.td_cbp)) + xfer->length
- 1))
1472 xfer->length - 1)((__uint32_t)(((__uint32_t)(data->td.td_cbp)) + xfer->length
- 1))
;
1473 data->len = xfer->length;
1474 data->xfer = xfer;
1475 data->flags = OHCI_CALL_DONE0x0001 | OHCI_ADD_LEN0x0002;
1476 xfer->hcpriv = data;
1477 xfer->actlen = 0;
1478
1479 sed->ed.ed_tailp = htole32(tail->physaddr)((__uint32_t)(tail->physaddr));
1480 opipe->tail.td = tail;
1481 }
1482}
1483
1484void
1485ohci_device_bulk_done(struct usbd_xfer *xfer)
1486{
1487 DPRINTFN(10, ("ohci_device_bulk_done: xfer=%p, actlen=%d\n", xfer,
1488 xfer->actlen));
1489}
1490
1491void
1492ohci_rhsc(struct ohci_softc *sc, struct usbd_xfer *xfer)
1493{
1494 u_char *p;
1495 int i, m;
1496 int hstatus;
1497
1498 hstatus = OREAD4(sc, OHCI_RH_STATUS0x50);
1499 DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n",
1500 sc, xfer, hstatus));
1501
1502 if (xfer == NULL((void *)0)) {
1503 /* Just ignore the change. */
1504 return;
1505 }
1506
1507 p = KERNADDR(&xfer->dmabuf, 0)((void *)((char *)((&xfer->dmabuf)->block->kaddr
+ (&xfer->dmabuf)->offs) + (0)))
;
1508 m = min(sc->sc_noport, xfer->length * 8 - 1);
1509 memset(p, 0, xfer->length)__builtin_memset((p), (0), (xfer->length));
1510 for (i = 1; i <= m; i++) {
1511 /* Pick out CHANGE bits from the status reg. */
1512 if (OREAD4(sc, OHCI_RH_PORT_STATUS(i)(0x50 + (i)*4)) >> 16)
1513 p[i/8] |= 1 << (i%8);
1514 }
1515 DPRINTF(("ohci_rhsc: change=0x%02x\n", *p));
1516 xfer->actlen = xfer->length;
1517 xfer->status = USBD_NORMAL_COMPLETION;
1518
1519 usb_transfer_complete(xfer);
1520}
1521
1522void
1523ohci_root_intr_done(struct usbd_xfer *xfer)
1524{
1525}
1526
1527void
1528ohci_root_ctrl_done(struct usbd_xfer *xfer)
1529{
1530}
1531
1532void
1533ohci_poll(struct usbd_bus *bus)
1534{
1535 struct ohci_softc *sc = (struct ohci_softc *)bus;
1536#ifdef OHCI_DEBUG
1537 static int last;
1538 int new;
1539 new = OREAD4(sc, OHCI_INTERRUPT_STATUS0x0c);
1540 if (new != last) {
1541 DPRINTFN(10,("ohci_poll: intrs=0x%04x\n", new));
1542 last = new;
1543 }
1544#endif
1545
1546 if (OREAD4(sc, OHCI_INTERRUPT_STATUS0x0c) & sc->sc_eintrs)
1547 ohci_intr1(sc);
1548}
1549
1550usbd_status
1551ohci_device_request(struct usbd_xfer *xfer)
1552{
1553 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
1554 struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
1555 usb_device_request_t *req = &xfer->request;
1556 struct ohci_soft_td *setup, *stat, *next, *tail;
1557 struct ohci_soft_ed *sed;
1558 u_int len;
1559 usbd_status err;
1560 int s;
1561
1562 len = UGETW(req->wLength)(*(u_int16_t *)(req->wLength));
1563
1564 DPRINTFN(3,("ohci_device_control type=0x%02x, request=0x%02x, "
1565 "wValue=0x%04x, wIndex=0x%04x len=%u, addr=%d, endpt=%d\n",
1566 req->bmRequestType, req->bRequest, UGETW(req->wValue),
1567 UGETW(req->wIndex), len, xfer->device->address,
1568 xfer->pipe->endpoint->edesc->bEndpointAddress));
1569
1570 setup = opipe->tail.td;
1571 stat = ohci_alloc_std(sc);
1572 if (stat == NULL((void *)0)) {
1573 err = USBD_NOMEM;
1574 goto bad1;
1575 }
1576 tail = ohci_alloc_std(sc);
1577 if (tail == NULL((void *)0)) {
1578 err = USBD_NOMEM;
1579 goto bad2;
1580 }
1581 tail->xfer = NULL((void *)0);
1582
1583 sed = opipe->sed;
1584
1585 next = stat;
1586
1587 /* Set up data transaction */
1588 if (len != 0) {
1589 struct ohci_soft_td *std = stat;
1590
1591 err = ohci_alloc_std_chain(sc, len, xfer, std, &stat);
1592 stat = stat->nexttd; /* point at free TD */
1593 if (err)
1594 goto bad3;
1595 /* Start toggle at 1 and then use the carried toggle. */
1596 std->td.td_flags &= htole32(~OHCI_TD_TOGGLE_MASK)((__uint32_t)(~0x03000000));
1597 std->td.td_flags |= htole32(OHCI_TD_TOGGLE_1)((__uint32_t)(0x03000000));
1598 }
1599
1600 memcpy(KERNADDR(&opipe->u.ctl.reqdma, 0), req, sizeof *req)__builtin_memcpy((((void *)((char *)((&opipe->u.ctl.reqdma
)->block->kaddr + (&opipe->u.ctl.reqdma)->offs
) + (0)))), (req), (sizeof *req))
;
1601
1602 setup->td.td_flags = htole32(OHCI_TD_SETUP | OHCI_TD_NOCC |((__uint32_t)(0x00000000 | 0xf0000000 | 0x02000000 | 0x00e00000
))
1603 OHCI_TD_TOGGLE_0 | OHCI_TD_NOINTR)((__uint32_t)(0x00000000 | 0xf0000000 | 0x02000000 | 0x00e00000
))
;
1604 setup->td.td_cbp = htole32(DMAADDR(&opipe->u.ctl.reqdma, 0))((__uint32_t)(((&opipe->u.ctl.reqdma)->block->map
->dm_segs[0].ds_addr + (&opipe->u.ctl.reqdma)->offs
+ (0))))
;
1605 setup->nexttd = next;
1606 setup->td.td_nexttd = htole32(next->physaddr)((__uint32_t)(next->physaddr));
1607 setup->td.td_be = htole32(letoh32(setup->td.td_cbp) + sizeof *req - 1)((__uint32_t)(((__uint32_t)(setup->td.td_cbp)) + sizeof *req
- 1))
;
1608 setup->len = 0;
1609 setup->xfer = xfer;
1610 setup->flags = 0;
1611 xfer->hcpriv = setup;
1612
1613 stat->td.td_flags = htole32(((__uint32_t)((usbd_xfer_isread(xfer) ? 0x00080000 : 0x00100000
) | 0xf0000000 | 0x03000000 | ((1) << 21)))
1614 (usbd_xfer_isread(xfer) ? OHCI_TD_OUT : OHCI_TD_IN) |((__uint32_t)((usbd_xfer_isread(xfer) ? 0x00080000 : 0x00100000
) | 0xf0000000 | 0x03000000 | ((1) << 21)))
1615 OHCI_TD_NOCC | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1))((__uint32_t)((usbd_xfer_isread(xfer) ? 0x00080000 : 0x00100000
) | 0xf0000000 | 0x03000000 | ((1) << 21)))
;
1616 stat->td.td_cbp = 0;
1617 stat->nexttd = tail;
1618 stat->td.td_nexttd = htole32(tail->physaddr)((__uint32_t)(tail->physaddr));
1619 stat->td.td_be = 0;
1620 stat->flags = OHCI_CALL_DONE0x0001;
1621 stat->len = 0;
1622 stat->xfer = xfer;
1623
1624#ifdef OHCI_DEBUG
1625 if (ohcidebug > 5) {
1626 DPRINTF(("ohci_device_request:\n"));
1627 ohci_dump_ed(sed);
1628 ohci_dump_tds(setup);
1629 }
1630#endif
1631
1632 /* Insert ED in schedule */
1633 s = splusb()splraise(0x5);
1634 sed->ed.ed_tailp = htole32(tail->physaddr)((__uint32_t)(tail->physaddr));
1635 opipe->tail.td = tail;
1636 OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x08)), ((0x00000002)))); } while (0)
;
1637 if (xfer->timeout && !sc->sc_bus.use_polling) {
1638 timeout_del(&xfer->timeout_handle);
1639 timeout_set(&xfer->timeout_handle, ohci_timeout, xfer);
1640 timeout_add_msec(&xfer->timeout_handle, xfer->timeout);
1641 }
1642 splx(s)spllower(s);
1643
1644#ifdef OHCI_DEBUG
1645 if (ohcidebug > 20) {
1646 delay(10000)(*delay_func)(10000);
1647 DPRINTF(("ohci_device_request: status=%x\n",
1648 OREAD4(sc, OHCI_COMMAND_STATUS)));
1649 ohci_dumpregs(sc);
1650 printf("ctrl head:\n");
1651 ohci_dump_ed(sc->sc_ctrl_head);
1652 printf("sed:\n");
1653 ohci_dump_ed(sed);
1654 ohci_dump_tds(setup);
1655 }
1656#endif
1657
1658 return (USBD_NORMAL_COMPLETION);
1659
1660 bad3:
1661 ohci_free_std(sc, tail);
1662 bad2:
1663 ohci_free_std(sc, stat);
1664 bad1:
1665 return (err);
1666}
1667
1668/*
1669 * Add an ED to the schedule. Called at splusb().
1670 */
1671void
1672ohci_add_ed(struct ohci_soft_ed *sed, struct ohci_soft_ed *head)
1673{
1674 DPRINTFN(8,("ohci_add_ed: sed=%p head=%p\n", sed, head));
1675
1676 splsoftassert(IPL_SOFTUSB)do { if (splassert_ctl > 0) { splassert_check(0x5, __func__
); } } while (0)
;
1677 sed->next = head->next;
1678 sed->ed.ed_nexted = head->ed.ed_nexted;
1679 head->next = sed;
1680 head->ed.ed_nexted = htole32(sed->physaddr)((__uint32_t)(sed->physaddr));
1681}
1682
1683/*
1684 * Remove an ED from the schedule. Called at splusb().
1685 */
1686void
1687ohci_rem_ed(struct ohci_soft_ed *sed, struct ohci_soft_ed *head)
1688{
1689 struct ohci_soft_ed *p;
1690
1691 splsoftassert(IPL_SOFTUSB)do { if (splassert_ctl > 0) { splassert_check(0x5, __func__
); } } while (0)
;
1692
1693 /* XXX */
1694 for (p = head; p != NULL((void *)0) && p->next != sed; p = p->next)
1695 ;
1696 if (p == NULL((void *)0))
1697 panic("ohci_rem_ed: ED not found");
1698 p->next = sed->next;
1699 p->ed.ed_nexted = sed->ed.ed_nexted;
1700}
1701
1702/*
1703 * When a transfer is completed the TD is added to the done queue by
1704 * the host controller. This queue is the processed by software.
1705 * Unfortunately the queue contains the physical address of the TD
1706 * and we have no simple way to translate this back to a kernel address.
1707 * To make the translation possible (and fast) we use a hash table of
1708 * TDs currently in the schedule. The physical address is used as the
1709 * hash value.
1710 */
1711
1712#define HASH(a)(((a) >> 4) % 128) (((a) >> 4) % OHCI_HASH_SIZE128)
1713/* Called at splusb() */
1714void
1715ohci_hash_add_td(struct ohci_softc *sc, struct ohci_soft_td *std)
1716{
1717 int h = HASH(std->physaddr)(((std->physaddr) >> 4) % 128);
1718
1719 splsoftassert(IPL_SOFTUSB)do { if (splassert_ctl > 0) { splassert_check(0x5, __func__
); } } while (0)
;
1720
1721 LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext)do { if (((std)->hnext.le_next = (&sc->sc_hash_tds[
h])->lh_first) != ((void *)0)) (&sc->sc_hash_tds[h]
)->lh_first->hnext.le_prev = &(std)->hnext.le_next
; (&sc->sc_hash_tds[h])->lh_first = (std); (std)->
hnext.le_prev = &(&sc->sc_hash_tds[h])->lh_first
; } while (0)
;
1722}
1723
1724struct ohci_soft_td *
1725ohci_hash_find_td(struct ohci_softc *sc, ohci_physaddr_t a)
1726{
1727 int h = HASH(a)(((a) >> 4) % 128);
1728 struct ohci_soft_td *std;
1729
1730 for (std = LIST_FIRST(&sc->sc_hash_tds[h])((&sc->sc_hash_tds[h])->lh_first);
1731 std != NULL((void *)0);
1732 std = LIST_NEXT(std, hnext)((std)->hnext.le_next))
1733 if (std->physaddr == a)
1734 return (std);
1735 return (NULL((void *)0));
1736}
1737
1738/* Called at splusb() */
1739void
1740ohci_hash_add_itd(struct ohci_softc *sc, struct ohci_soft_itd *sitd)
1741{
1742 int h = HASH(sitd->physaddr)(((sitd->physaddr) >> 4) % 128);
1743
1744 splsoftassert(IPL_SOFTUSB)do { if (splassert_ctl > 0) { splassert_check(0x5, __func__
); } } while (0)
;
1745
1746 DPRINTFN(10,("ohci_hash_add_itd: sitd=%p physaddr=0x%08lx\n",
1747 sitd, (u_long)sitd->physaddr));
1748
1749 LIST_INSERT_HEAD(&sc->sc_hash_itds[h], sitd, hnext)do { if (((sitd)->hnext.le_next = (&sc->sc_hash_itds
[h])->lh_first) != ((void *)0)) (&sc->sc_hash_itds[
h])->lh_first->hnext.le_prev = &(sitd)->hnext.le_next
; (&sc->sc_hash_itds[h])->lh_first = (sitd); (sitd)
->hnext.le_prev = &(&sc->sc_hash_itds[h])->lh_first
; } while (0)
;
1750}
1751
1752/* Called at splusb() */
1753void
1754ohci_hash_rem_itd(struct ohci_softc *sc, struct ohci_soft_itd *sitd)
1755{
1756 splsoftassert(IPL_SOFTUSB)do { if (splassert_ctl > 0) { splassert_check(0x5, __func__
); } } while (0)
;
1757
1758 DPRINTFN(10,("ohci_hash_rem_itd: sitd=%p physaddr=0x%08lx\n",
1759 sitd, (u_long)sitd->physaddr));
1760
1761 LIST_REMOVE(sitd, hnext)do { if ((sitd)->hnext.le_next != ((void *)0)) (sitd)->
hnext.le_next->hnext.le_prev = (sitd)->hnext.le_prev; *
(sitd)->hnext.le_prev = (sitd)->hnext.le_next; ((sitd)->
hnext.le_prev) = ((void *)-1); ((sitd)->hnext.le_next) = (
(void *)-1); } while (0)
;
1762}
1763
1764struct ohci_soft_itd *
1765ohci_hash_find_itd(struct ohci_softc *sc, ohci_physaddr_t a)
1766{
1767 int h = HASH(a)(((a) >> 4) % 128);
1768 struct ohci_soft_itd *sitd;
1769
1770 for (sitd = LIST_FIRST(&sc->sc_hash_itds[h])((&sc->sc_hash_itds[h])->lh_first);
1771 sitd != NULL((void *)0);
1772 sitd = LIST_NEXT(sitd, hnext)((sitd)->hnext.le_next))
1773 if (sitd->physaddr == a)
1774 return (sitd);
1775 return (NULL((void *)0));
1776}
1777
1778void
1779ohci_timeout(void *addr)
1780{
1781 struct usbd_xfer *xfer = addr;
1782 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
1783
1784 if (sc->sc_bus.dying) {
1785 ohci_timeout_task(addr);
1786 return;
1787 }
1788
1789 usb_init_task(&xfer->abort_task, ohci_timeout_task, addr,((&xfer->abort_task)->fun = (ohci_timeout_task), (&
xfer->abort_task)->arg = (addr), (&xfer->abort_task
)->type = (2), (&xfer->abort_task)->state = 0x0)
1790 USB_TASK_TYPE_ABORT)((&xfer->abort_task)->fun = (ohci_timeout_task), (&
xfer->abort_task)->arg = (addr), (&xfer->abort_task
)->type = (2), (&xfer->abort_task)->state = 0x0)
;
1791 usb_add_task(xfer->device, &xfer->abort_task);
1792}
1793
1794void
1795ohci_timeout_task(void *addr)
1796{
1797 struct usbd_xfer *xfer = addr;
1798 int s;
1799
1800 DPRINTF(("%s: xfer=%p\n", __func__, xfer));
1801
1802 s = splusb()splraise(0x5);
1803 ohci_abort_xfer(xfer, USBD_TIMEOUT);
1804 splx(s)spllower(s);
1805}
1806
1807#ifdef OHCI_DEBUG
1808void
1809ohci_dump_tds(struct ohci_soft_td *std)
1810{
1811 for (; std; std = std->nexttd)
1812 ohci_dump_td(std);
1813}
1814
1815void
1816ohci_dump_td(struct ohci_soft_td *std)
1817{
1818 char sbuf[128];
1819
1820 bitmask_snprintf((u_int32_t)letoh32(std->td.td_flags)((__uint32_t)(std->td.td_flags)),
1821 "\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE",
1822 sbuf, sizeof(sbuf));
1823
1824 printf("TD(%p) at %08lx: %s delay=%d ec=%d cc=%d\ncbp=0x%08lx "
1825 "nexttd=0x%08lx be=0x%08lx\n",
1826 std, (u_long)std->physaddr, sbuf,
1827 OHCI_TD_GET_DI(letoh32(std->td.td_flags))(((((__uint32_t)(std->td.td_flags))) >> 21) & 7),
1828 OHCI_TD_GET_EC(letoh32(std->td.td_flags))(((((__uint32_t)(std->td.td_flags))) >> 26) & 3),
1829 OHCI_TD_GET_CC(letoh32(std->td.td_flags))((((__uint32_t)(std->td.td_flags))) >> 28),
1830 (u_long)letoh32(std->td.td_cbp)((__uint32_t)(std->td.td_cbp)),
1831 (u_long)letoh32(std->td.td_nexttd)((__uint32_t)(std->td.td_nexttd)),
1832 (u_long)letoh32(std->td.td_be)((__uint32_t)(std->td.td_be)));
1833}
1834
1835void
1836ohci_dump_itd(struct ohci_soft_itd *sitd)
1837{
1838 int i;
1839
1840 printf("ITD(%p) at %08lx: sf=%d di=%d fc=%d cc=%d\n"
1841 "bp0=0x%08lx next=0x%08lx be=0x%08lx\n",
1842 sitd, (u_long)sitd->physaddr,
1843 OHCI_ITD_GET_SF(letoh32(sitd->itd.itd_flags))((((__uint32_t)(sitd->itd.itd_flags))) & 0x0000ffff),
1844 OHCI_ITD_GET_DI(letoh32(sitd->itd.itd_flags))(((((__uint32_t)(sitd->itd.itd_flags))) >> 21) &
7)
,
1845 OHCI_ITD_GET_FC(letoh32(sitd->itd.itd_flags))((((((__uint32_t)(sitd->itd.itd_flags))) >> 24) &
7)+1)
,
1846 OHCI_ITD_GET_CC(letoh32(sitd->itd.itd_flags))((((__uint32_t)(sitd->itd.itd_flags))) >> 28),
1847 (u_long)letoh32(sitd->itd.itd_bp0)((__uint32_t)(sitd->itd.itd_bp0)),
1848 (u_long)letoh32(sitd->itd.itd_nextitd)((__uint32_t)(sitd->itd.itd_nextitd)),
1849 (u_long)letoh32(sitd->itd.itd_be)((__uint32_t)(sitd->itd.itd_be)));
1850 for (i = 0; i < OHCI_ITD_NOFFSET8; i++)
1851 printf("offs[%d]=0x%04x ", i,
1852 (u_int)letoh16(sitd->itd.itd_offset[i])((__uint16_t)(sitd->itd.itd_offset[i])));
1853 printf("\n");
1854}
1855
1856void
1857ohci_dump_itds(struct ohci_soft_itd *sitd)
1858{
1859 for (; sitd; sitd = sitd->nextitd)
1860 ohci_dump_itd(sitd);
1861}
1862
1863void
1864ohci_dump_ed(struct ohci_soft_ed *sed)
1865{
1866 char sbuf[128], sbuf2[128];
1867
1868 bitmask_snprintf((u_int32_t)letoh32(sed->ed.ed_flags)((__uint32_t)(sed->ed.ed_flags)),
1869 "\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO",
1870 sbuf, sizeof(sbuf));
1871 bitmask_snprintf((u_int32_t)letoh32(sed->ed.ed_headp)((__uint32_t)(sed->ed.ed_headp)),
1872 "\20\1HALT\2CARRY", sbuf2, sizeof(sbuf2));
1873
1874 printf("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d flags=%s\n"
1875 "tailp=0x%08lx headflags=%s headp=0x%08lx nexted=0x%08lx\n",
1876 sed, (u_long)sed->physaddr,
1877 OHCI_ED_GET_FA(letoh32(sed->ed.ed_flags))((((__uint32_t)(sed->ed.ed_flags))) & 0x7f),
1878 OHCI_ED_GET_EN(letoh32(sed->ed.ed_flags))(((((__uint32_t)(sed->ed.ed_flags))) >> 7) & 0xf
)
,
1879 OHCI_ED_GET_MAXP(letoh32(sed->ed.ed_flags))(((((__uint32_t)(sed->ed.ed_flags))) >> 16) & 0x07ff
)
, sbuf,
1880 (u_long)letoh32(sed->ed.ed_tailp)((__uint32_t)(sed->ed.ed_tailp)), sbuf2,
1881 (u_long)letoh32(sed->ed.ed_headp)((__uint32_t)(sed->ed.ed_headp)),
1882 (u_long)letoh32(sed->ed.ed_nexted)((__uint32_t)(sed->ed.ed_nexted)));
1883}
1884#endif
1885
1886usbd_status
1887ohci_open(struct usbd_pipe *pipe)
1888{
1889 struct ohci_softc *sc = (struct ohci_softc *)pipe->device->bus;
1890 usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
1891 struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
1892 u_int8_t xfertype = UE_GET_XFERTYPE(ed->bmAttributes)((ed->bmAttributes) & 0x03);
1893 struct ohci_soft_ed *sed = NULL((void *)0);
1894 struct ohci_soft_td *std = NULL((void *)0);
1895 struct ohci_soft_itd *sitd;
1896 ohci_physaddr_t tdphys;
1897 u_int32_t fmt;
1898 usbd_status err;
1899 int s;
1900 int ival;
1901
1902 DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d\n",
1903 pipe, pipe->device->address, ed->bEndpointAddress));
1904
1905 if (sc->sc_bus.dying)
1906 return (USBD_IOERROR);
1907
1908 /* Root Hub */
1909 if (pipe->device->depth == 0) {
1910 switch (ed->bEndpointAddress) {
1911 case USB_CONTROL_ENDPOINT0:
1912 pipe->methods = &ohci_root_ctrl_methods;
1913 break;
1914 case UE_DIR_IN0x80 | OHCI_INTR_ENDPT1:
1915 pipe->methods = &ohci_root_intr_methods;
1916 break;
1917 default:
1918 return (USBD_INVAL);
1919 }
1920 } else {
1921 sed = ohci_alloc_sed(sc);
1922 if (sed == NULL((void *)0))
1923 goto bad0;
1924 opipe->sed = sed;
1925 if (xfertype == UE_ISOCHRONOUS0x01) {
1926 sitd = ohci_alloc_sitd(sc);
1927 if (sitd == NULL((void *)0))
1928 goto bad1;
1929 opipe->tail.itd = sitd;
1930 tdphys = sitd->physaddr;
1931 fmt = OHCI_ED_FORMAT_ISO0x00008000;
1932 if (UE_GET_DIR(ed->bEndpointAddress)((ed->bEndpointAddress) & 0x80) == UE_DIR_IN0x80)
1933 fmt |= OHCI_ED_DIR_IN0x00001000;
1934 else
1935 fmt |= OHCI_ED_DIR_OUT0x00000800;
1936 } else {
1937 std = ohci_alloc_std(sc);
1938 if (std == NULL((void *)0))
1939 goto bad1;
1940 opipe->tail.td = std;
1941 tdphys = std->physaddr;
1942 fmt = OHCI_ED_FORMAT_GEN0x00000000 | OHCI_ED_DIR_TD0x00000000;
1943 }
1944 sed->ed.ed_flags = htole32(((__uint32_t)((pipe->device->address) | ((((ed->bEndpointAddress
) & 0x0f)) << 7) | (pipe->device->speed == 1 ?
0x00002000 : 0) | fmt | (((*(u_int16_t *)(ed->wMaxPacketSize
))) << 16)))
1945 OHCI_ED_SET_FA(pipe->device->address) |((__uint32_t)((pipe->device->address) | ((((ed->bEndpointAddress
) & 0x0f)) << 7) | (pipe->device->speed == 1 ?
0x00002000 : 0) | fmt | (((*(u_int16_t *)(ed->wMaxPacketSize
))) << 16)))
1946 OHCI_ED_SET_EN(UE_GET_ADDR(ed->bEndpointAddress)) |((__uint32_t)((pipe->device->address) | ((((ed->bEndpointAddress
) & 0x0f)) << 7) | (pipe->device->speed == 1 ?
0x00002000 : 0) | fmt | (((*(u_int16_t *)(ed->wMaxPacketSize
))) << 16)))
1947 (pipe->device->speed == USB_SPEED_LOW ?((__uint32_t)((pipe->device->address) | ((((ed->bEndpointAddress
) & 0x0f)) << 7) | (pipe->device->speed == 1 ?
0x00002000 : 0) | fmt | (((*(u_int16_t *)(ed->wMaxPacketSize
))) << 16)))
1948 OHCI_ED_SPEED : 0) |((__uint32_t)((pipe->device->address) | ((((ed->bEndpointAddress
) & 0x0f)) << 7) | (pipe->device->speed == 1 ?
0x00002000 : 0) | fmt | (((*(u_int16_t *)(ed->wMaxPacketSize
))) << 16)))
1949 fmt | OHCI_ED_SET_MAXP(UGETW(ed->wMaxPacketSize)))((__uint32_t)((pipe->device->address) | ((((ed->bEndpointAddress
) & 0x0f)) << 7) | (pipe->device->speed == 1 ?
0x00002000 : 0) | fmt | (((*(u_int16_t *)(ed->wMaxPacketSize
))) << 16)))
;
1950 sed->ed.ed_headp = htole32(tdphys |((__uint32_t)(tdphys | (pipe->endpoint->savedtoggle ? 0x00000002
: 0)))
1951 (pipe->endpoint->savedtoggle ? OHCI_TOGGLECARRY : 0))((__uint32_t)(tdphys | (pipe->endpoint->savedtoggle ? 0x00000002
: 0)))
;
1952 sed->ed.ed_tailp = htole32(tdphys)((__uint32_t)(tdphys));
1953
1954 switch (xfertype) {
1955 case UE_CONTROL0x00:
1956 pipe->methods = &ohci_device_ctrl_methods;
1957 err = usb_allocmem(&sc->sc_bus,
1958 sizeof(usb_device_request_t),
1959 0, USB_DMA_COHERENT(1 << 0),
1960 &opipe->u.ctl.reqdma);
1961 if (err)
1962 goto bad;
1963 s = splusb()splraise(0x5);
1964 ohci_add_ed(sed, sc->sc_ctrl_head);
1965 splx(s)spllower(s);
1966 break;
1967 case UE_INTERRUPT0x03:
1968 pipe->methods = &ohci_device_intr_methods;
1969 ival = pipe->interval;
1970 if (ival == USBD_DEFAULT_INTERVAL(-1))
1971 ival = ed->bInterval;
1972 return (ohci_device_setintr(sc, opipe, ival));
1973 case UE_ISOCHRONOUS0x01:
1974 pipe->methods = &ohci_device_isoc_methods;
1975 return (ohci_setup_isoc(pipe));
1976 case UE_BULK0x02:
1977 pipe->methods = &ohci_device_bulk_methods;
1978 s = splusb()splraise(0x5);
1979 ohci_add_ed(sed, sc->sc_bulk_head);
1980 splx(s)spllower(s);
1981 break;
1982 }
1983 }
1984 return (USBD_NORMAL_COMPLETION);
1985
1986 bad:
1987 if (std != NULL((void *)0))
1988 ohci_free_std(sc, std);
1989 bad1:
1990 if (sed != NULL((void *)0))
1991 ohci_free_sed(sc, sed);
1992 bad0:
1993 return (USBD_NOMEM);
1994
1995}
1996
1997/*
1998 * Work around the half configured control (default) pipe when setting
1999 * the address of a device.
2000 *
2001 * Because a single ED is setup per endpoint in ohci_open(), and the
2002 * control pipe is configured before we could have set the address
2003 * of the device or read the wMaxPacketSize of the endpoint, we have
2004 * to re-open the pipe twice here.
2005 */
2006int
2007ohci_setaddr(struct usbd_device *dev, int addr)
2008{
2009 /* Root Hub */
2010 if (dev->depth == 0)
2011 return (0);
2012
2013 /* Re-establish the default pipe with the new max packet size. */
2014 ohci_device_ctrl_close(dev->default_pipe);
2015 if (ohci_open(dev->default_pipe))
2016 return (EINVAL22);
2017
2018 if (usbd_set_address(dev, addr))
2019 return (1);
2020
2021 dev->address = addr;
2022
2023 /* Re-establish the default pipe with the new address. */
2024 ohci_device_ctrl_close(dev->default_pipe);
2025 if (ohci_open(dev->default_pipe))
2026 return (EINVAL22);
2027
2028 return (0);
2029}
2030
2031/*
2032 * Close a regular pipe.
2033 * Assumes that there are no pending transactions.
2034 */
2035void
2036ohci_close_pipe(struct usbd_pipe *pipe, struct ohci_soft_ed *head)
2037{
2038 struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
2039 struct ohci_softc *sc = (struct ohci_softc *)pipe->device->bus;
2040 struct ohci_soft_ed *sed = opipe->sed;
2041 int s;
2042
2043 s = splusb()splraise(0x5);
2044#ifdef DIAGNOSTIC1
2045 sed->ed.ed_flags |= htole32(OHCI_ED_SKIP)((__uint32_t)(0x00004000));
2046 if ((letoh32(sed->ed.ed_tailp)((__uint32_t)(sed->ed.ed_tailp)) & OHCI_HEADMASK0xfffffffc) !=
2047 (letoh32(sed->ed.ed_headp)((__uint32_t)(sed->ed.ed_headp)) & OHCI_HEADMASK0xfffffffc)) {
2048 struct ohci_soft_td *std;
2049 std = ohci_hash_find_td(sc, letoh32(sed->ed.ed_headp)((__uint32_t)(sed->ed.ed_headp)));
2050 printf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x "
2051 "tl=0x%x pipe=%p, std=%p\n", sed,
2052 (int)letoh32(sed->ed.ed_headp)((__uint32_t)(sed->ed.ed_headp)),
2053 (int)letoh32(sed->ed.ed_tailp)((__uint32_t)(sed->ed.ed_tailp)),
2054 pipe, std);
2055#ifdef OHCI_DEBUG
2056 ohci_dump_ed(sed);
2057 if (std)
2058 ohci_dump_td(std);
2059#endif
2060 usb_delay_ms(&sc->sc_bus, 2);
2061 if ((letoh32(sed->ed.ed_tailp)((__uint32_t)(sed->ed.ed_tailp)) & OHCI_HEADMASK0xfffffffc) !=
2062 (letoh32(sed->ed.ed_headp)((__uint32_t)(sed->ed.ed_headp)) & OHCI_HEADMASK0xfffffffc))
2063 printf("ohci_close_pipe: pipe still not empty\n");
2064 }
2065#endif
2066 ohci_rem_ed(sed, head);
2067 /* Make sure the host controller is not touching this ED */
2068 usb_delay_ms(&sc->sc_bus, 1);
2069 splx(s)spllower(s);
2070 pipe->endpoint->savedtoggle =
2071 (letoh32(sed->ed.ed_headp)((__uint32_t)(sed->ed.ed_headp)) & OHCI_TOGGLECARRY0x00000002) ? 1 : 0;
2072 ohci_free_sed(sc, opipe->sed);
2073}
2074
2075/*
2076 * Abort a device request.
2077 * If this routine is called at splusb() it guarantees that the request
2078 * will be removed from the hardware scheduling and that the callback
2079 * for it will be called with USBD_CANCELLED status.
2080 * It's impossible to guarantee that the requested transfer will not
2081 * have happened since the hardware runs concurrently.
2082 * If the transaction has already happened we rely on the ordinary
2083 * interrupt processing to process it.
2084 */
2085void
2086ohci_abort_xfer(struct usbd_xfer *xfer, usbd_status status)
2087{
2088 struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
2089 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
2090 struct ohci_soft_ed *sed = opipe->sed;
2091 struct ohci_soft_td *p, *n;
2092 ohci_physaddr_t headp;
2093 int s, hit;
2094
2095 DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,
2096 sed));
2097
2098 if (sc->sc_bus.dying) {
2099 /* If we're dying, just do the software part. */
2100 s = splusb()splraise(0x5);
2101 xfer->status = status; /* make software ignore it */
2102 timeout_del(&xfer->timeout_handle);
2103 usb_rem_task(xfer->device, &xfer->abort_task);
2104 usb_transfer_complete(xfer);
2105 splx(s)spllower(s);
2106 return;
2107 }
2108
2109 if (xfer->device->bus->intr_context || !curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)
2110 panic("ohci_abort_xfer: not in process context");
2111
2112 /*
2113 * Step 1: Make interrupt routine and hardware ignore xfer.
2114 */
2115 s = splusb()splraise(0x5);
2116 xfer->status = status; /* make software ignore it */
2117 timeout_del(&xfer->timeout_handle);
2118 usb_rem_task(xfer->device, &xfer->abort_task);
2119 splx(s)spllower(s);
2120 DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
2121 sed->ed.ed_flags |= htole32(OHCI_ED_SKIP)((__uint32_t)(0x00004000)); /* force hardware skip */
2122
2123 /*
2124 * Step 2: Wait until we know hardware has finished any possible
2125 * use of the xfer. Also make sure the soft interrupt routine
2126 * has run.
2127 */
2128 usb_delay_ms(xfer->device->bus, 20); /* Hardware finishes in 1ms */
2129 s = splusb()splraise(0x5);
2130 sc->sc_softwake = 1;
2131 usb_schedsoftintr(&sc->sc_bus);
2132 tsleep_nsec(&sc->sc_softwake, PZERO22, "ohciab", INFSLP0xffffffffffffffffULL);
2133 splx(s)spllower(s);
2134
2135 /*
2136 * Step 3: Remove any vestiges of the xfer from the hardware.
2137 * The complication here is that the hardware may have executed
2138 * beyond the xfer we're trying to abort. So as we're scanning
2139 * the TDs of this xfer we check if the hardware points to
2140 * any of them.
2141 */
2142 s = splusb()splraise(0x5); /* XXX why? */
2143 p = xfer->hcpriv;
2144#ifdef DIAGNOSTIC1
2145 if (p == NULL((void *)0)) {
2146 splx(s)spllower(s);
2147 printf("ohci_abort_xfer: hcpriv is NULL\n");
2148 return;
2149 }
2150#endif
2151#ifdef OHCI_DEBUG
2152 if (ohcidebug > 1) {
2153 DPRINTF(("ohci_abort_xfer: sed=\n"));
2154 ohci_dump_ed(sed);
2155 ohci_dump_tds(p);
2156 }
2157#endif
2158 headp = letoh32(sed->ed.ed_headp)((__uint32_t)(sed->ed.ed_headp)) & OHCI_HEADMASK0xfffffffc;
2159 hit = 0;
2160 for (; p->xfer == xfer; p = n) {
2161 hit |= headp == p->physaddr;
2162 n = p->nexttd;
2163 if (OHCI_TD_GET_CC(letoh32(p->td.td_flags))((((__uint32_t)(p->td.td_flags))) >> 28) ==
2164 OHCI_CC_NOT_ACCESSED14)
2165 ohci_free_std(sc, p);
2166 }
2167 /* Zap headp register if hardware pointed inside the xfer. */
2168 if (hit) {
2169 DPRINTFN(1,("ohci_abort_xfer: set hd=0x%08x, tl=0x%08x\n",
2170 (int)p->physaddr, (int)letoh32(sed->ed.ed_tailp)));
2171 sed->ed.ed_headp = htole32(p->physaddr)((__uint32_t)(p->physaddr)); /* unlink TDs */
2172 } else {
2173 DPRINTFN(1,("ohci_abort_xfer: no hit\n"));
2174 }
2175
2176 /*
2177 * Step 4: Turn on hardware again.
2178 */
2179 sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP)((__uint32_t)(~0x00004000)); /* remove hardware skip */
2180
2181 /*
2182 * Step 5: Execute callback.
2183 */
2184 usb_transfer_complete(xfer);
2185
2186 splx(s)spllower(s);
2187}
2188
2189/*
2190 * Data structures and routines to emulate the root hub.
2191 */
2192usb_device_descriptor_t ohci_devd = {
2193 USB_DEVICE_DESCRIPTOR_SIZE18,
2194 UDESC_DEVICE0x01, /* type */
2195 {0x00, 0x01}, /* USB version */
2196 UDCLASS_HUB0x09, /* class */
2197 UDSUBCLASS_HUB0x00, /* subclass */
2198 UDPROTO_FSHUB0x00,
2199 64, /* max packet */
2200 {0},{0},{0x00,0x01}, /* device id */
2201 1,2,0, /* string indices */
2202 1 /* # of configurations */
2203};
2204
2205usb_config_descriptor_t ohci_confd = {
2206 USB_CONFIG_DESCRIPTOR_SIZE9,
2207 UDESC_CONFIG0x02,
2208 {USB_CONFIG_DESCRIPTOR_SIZE9 +
2209 USB_INTERFACE_DESCRIPTOR_SIZE9 +
2210 USB_ENDPOINT_DESCRIPTOR_SIZE7},
2211 1,
2212 1,
2213 0,
2214 UC_BUS_POWERED0x80 | UC_SELF_POWERED0x40,
2215 0 /* max power */
2216};
2217
2218usb_interface_descriptor_t ohci_ifcd = {
2219 USB_INTERFACE_DESCRIPTOR_SIZE9,
2220 UDESC_INTERFACE0x04,
2221 0,
2222 0,
2223 1,
2224 UICLASS_HUB0x09,
2225 UISUBCLASS_HUB0,
2226 UIPROTO_FSHUB0,
2227 0
2228};
2229
2230usb_endpoint_descriptor_t ohci_endpd = {
2231 USB_ENDPOINT_DESCRIPTOR_SIZE7,
2232 UDESC_ENDPOINT0x05,
2233 UE_DIR_IN0x80 | OHCI_INTR_ENDPT1,
2234 UE_INTERRUPT0x03,
2235 {8, 0}, /* max packet */
2236 255
2237};
2238
2239usb_hub_descriptor_t ohci_hubd = {
2240 USB_HUB_DESCRIPTOR_SIZE8,
2241 UDESC_HUB0x29,
2242 0,
2243 {0,0},
2244 0,
2245 0,
2246 {0},
2247};
2248
2249/*
2250 * Simulate a hardware hub by handling all the necessary requests.
2251 */
2252usbd_status
2253ohci_root_ctrl_transfer(struct usbd_xfer *xfer)
2254{
2255 usbd_status err;
2256
2257 /* Insert last in queue. */
2258 err = usb_insert_transfer(xfer);
2259 if (err)
2260 return (err);
2261
2262 /* Pipe isn't running, start first */
2263 return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first)));
2264}
2265
2266usbd_status
2267ohci_root_ctrl_start(struct usbd_xfer *xfer)
2268{
2269 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
2270 usb_device_request_t *req;
2271 void *buf = NULL((void *)0);
2272 int port, i;
2273 int s, len, value, index, l, totlen = 0;
2274 usb_port_status_t ps;
2275 usb_hub_descriptor_t hubd;
2276 usbd_status err;
2277 u_int32_t v;
2278
2279 if (sc->sc_bus.dying)
2280 return (USBD_IOERROR);
2281
2282#ifdef DIAGNOSTIC1
2283 if (!(xfer->rqflags & URQ_REQUEST0x01))
2284 /* XXX panic */
2285 return (USBD_INVAL);
2286#endif
2287 req = &xfer->request;
2288
2289 DPRINTFN(4,("ohci_root_ctrl_control type=0x%02x request=%02x\n",
2290 req->bmRequestType, req->bRequest));
2291
2292 len = UGETW(req->wLength)(*(u_int16_t *)(req->wLength));
2293 value = UGETW(req->wValue)(*(u_int16_t *)(req->wValue));
2294 index = UGETW(req->wIndex)(*(u_int16_t *)(req->wIndex));
2295
2296 if (len != 0)
2297 buf = KERNADDR(&xfer->dmabuf, 0)((void *)((char *)((&xfer->dmabuf)->block->kaddr
+ (&xfer->dmabuf)->offs) + (0)))
;
2298
2299#define C(x,y)((x) | ((y) << 8)) ((x) | ((y) << 8))
2300 switch(C(req->bRequest, req->bmRequestType)((req->bRequest) | ((req->bmRequestType) << 8))) {
2301 case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE)((0x01) | (((0x00 | 0x00 | 0x00)) << 8)):
2302 case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE)((0x01) | (((0x00 | 0x00 | 0x01)) << 8)):
2303 case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT)((0x01) | (((0x00 | 0x00 | 0x02)) << 8)):
2304 /*
2305 * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
2306 * for the integrated root hub.
2307 */
2308 break;
2309 case C(UR_GET_CONFIG, UT_READ_DEVICE)((0x08) | (((0x80 | 0x00 | 0x00)) << 8)):
2310 if (len > 0) {
2311 *(u_int8_t *)buf = sc->sc_conf;
2312 totlen = 1;
2313 }
2314 break;
2315 case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE)((0x06) | (((0x80 | 0x00 | 0x00)) << 8)):
2316 DPRINTFN(8,("ohci_root_ctrl_control wValue=0x%04x\n", value));
2317 switch(value >> 8) {
2318 case UDESC_DEVICE0x01:
2319 if ((value & 0xff) != 0) {
2320 err = USBD_IOERROR;
2321 goto ret;
2322 }
2323 totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE18);
2324 USETW(ohci_devd.idVendor, sc->sc_id_vendor)(*(u_int16_t *)(ohci_devd.idVendor) = (sc->sc_id_vendor));
2325 memcpy(buf, &ohci_devd, l)__builtin_memcpy((buf), (&ohci_devd), (l));
2326 break;
2327 case UDESC_CONFIG0x02:
2328 if ((value & 0xff) != 0) {
2329 err = USBD_IOERROR;
2330 goto ret;
2331 }
2332 totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE9);
2333 memcpy(buf, &ohci_confd, l)__builtin_memcpy((buf), (&ohci_confd), (l));
2334 buf = (char *)buf + l;
2335 len -= l;
2336 l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE9);
2337 totlen += l;
2338 memcpy(buf, &ohci_ifcd, l)__builtin_memcpy((buf), (&ohci_ifcd), (l));
2339 buf = (char *)buf + l;
2340 len -= l;
2341 l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE7);
2342 totlen += l;
2343 memcpy(buf, &ohci_endpd, l)__builtin_memcpy((buf), (&ohci_endpd), (l));
2344 break;
2345 case UDESC_STRING0x03:
2346 if (len == 0)
2347 break;
2348 *(u_int8_t *)buf = 0;
2349 totlen = 1;
2350 switch (value & 0xff) {
2351 case 0: /* Language table */
2352 totlen = usbd_str(buf, len, "\001");
2353 break;
2354 case 1: /* Vendor */
2355 totlen = usbd_str(buf, len, sc->sc_vendor);
2356 break;
2357 case 2: /* Product */
2358 totlen = usbd_str(buf, len, "OHCI root hub");
2359 break;
2360 }
2361 break;
2362 default:
2363 err = USBD_IOERROR;
2364 goto ret;
2365 }
2366 break;
2367 case C(UR_GET_INTERFACE, UT_READ_INTERFACE)((0x0a) | (((0x80 | 0x00 | 0x01)) << 8)):
2368 if (len > 0) {
2369 *(u_int8_t *)buf = 0;
2370 totlen = 1;
2371 }
2372 break;
2373 case C(UR_GET_STATUS, UT_READ_DEVICE)((0x00) | (((0x80 | 0x00 | 0x00)) << 8)):
2374 if (len > 1) {
2375 USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED)(*(u_int16_t *)(((usb_status_t *)buf)->wStatus) = (0x0001)
)
;
2376 totlen = 2;
2377 }
2378 break;
2379 case C(UR_GET_STATUS, UT_READ_INTERFACE)((0x00) | (((0x80 | 0x00 | 0x01)) << 8)):
2380 case C(UR_GET_STATUS, UT_READ_ENDPOINT)((0x00) | (((0x80 | 0x00 | 0x02)) << 8)):
2381 if (len > 1) {
2382 USETW(((usb_status_t *)buf)->wStatus, 0)(*(u_int16_t *)(((usb_status_t *)buf)->wStatus) = (0));
2383 totlen = 2;
2384 }
2385 break;
2386 case C(UR_SET_ADDRESS, UT_WRITE_DEVICE)((0x05) | (((0x00 | 0x00 | 0x00)) << 8)):
2387 if (value >= USB_MAX_DEVICES128) {
2388 err = USBD_IOERROR;
2389 goto ret;
2390 }
2391 break;
2392 case C(UR_SET_CONFIG, UT_WRITE_DEVICE)((0x09) | (((0x00 | 0x00 | 0x00)) << 8)):
2393 if (value != 0 && value != 1) {
2394 err = USBD_IOERROR;
2395 goto ret;
2396 }
2397 sc->sc_conf = value;
2398 break;
2399 case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE)((0x07) | (((0x00 | 0x00 | 0x00)) << 8)):
2400 break;
2401 case C(UR_SET_FEATURE, UT_WRITE_DEVICE)((0x03) | (((0x00 | 0x00 | 0x00)) << 8)):
2402 case C(UR_SET_FEATURE, UT_WRITE_INTERFACE)((0x03) | (((0x00 | 0x00 | 0x01)) << 8)):
2403 case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT)((0x03) | (((0x00 | 0x00 | 0x02)) << 8)):
2404 err = USBD_IOERROR;
2405 goto ret;
2406 case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE)((0x0b) | (((0x00 | 0x00 | 0x01)) << 8)):
2407 break;
2408 case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT)((0x0c) | (((0x00 | 0x00 | 0x02)) << 8)):
2409 break;
2410 /* Hub requests */
2411 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE)((0x01) | (((0x00 | 0x20 | 0x00)) << 8)):
2412 break;
2413 case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER)((0x01) | (((0x00 | 0x20 | 0x03)) << 8)):
2414 DPRINTFN(8, ("ohci_root_ctrl_control: UR_CLEAR_PORT_FEATURE "
2415 "port=%d feature=%d\n",
2416 index, value));
2417 if (index < 1 || index > sc->sc_noport) {
2418 err = USBD_IOERROR;
2419 goto ret;
2420 }
2421 port = OHCI_RH_PORT_STATUS(index)(0x50 + (index)*4);
2422 switch(value) {
2423 case UHF_PORT_ENABLE1:
2424 OWRITE4(sc, port, UPS_CURRENT_CONNECT_STATUS)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0001)))); } while (0)
;
2425 break;
2426 case UHF_PORT_SUSPEND2:
2427 OWRITE4(sc, port, UPS_OVERCURRENT_INDICATOR)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0008)))); } while (0)
;
2428 break;
2429 case UHF_PORT_POWER8:
2430 /* Yes, writing to the LOW_SPEED bit clears power. */
2431 OWRITE4(sc, port, UPS_LOW_SPEED)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0200)))); } while (0)
;
2432 break;
2433 case UHF_C_PORT_CONNECTION16:
2434 OWRITE4(sc, port, UPS_C_CONNECT_STATUS << 16)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0001 << 16)))); } while (0)
;
2435 break;
2436 case UHF_C_PORT_ENABLE17:
2437 OWRITE4(sc, port, UPS_C_PORT_ENABLED << 16)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0002 << 16)))); } while (0)
;
2438 break;
2439 case UHF_C_PORT_SUSPEND18:
2440 OWRITE4(sc, port, UPS_C_SUSPEND << 16)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0004 << 16)))); } while (0)
;
2441 break;
2442 case UHF_C_PORT_OVER_CURRENT19:
2443 OWRITE4(sc, port, UPS_C_OVERCURRENT_INDICATOR << 16)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0008 << 16)))); } while (0)
;
2444 break;
2445 case UHF_C_PORT_RESET20:
2446 OWRITE4(sc, port, UPS_C_PORT_RESET << 16)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0010 << 16)))); } while (0)
;
2447 break;
2448 default:
2449 err = USBD_IOERROR;
2450 goto ret;
2451 }
2452 switch(value) {
2453 case UHF_C_PORT_CONNECTION16:
2454 case UHF_C_PORT_ENABLE17:
2455 case UHF_C_PORT_SUSPEND18:
2456 case UHF_C_PORT_OVER_CURRENT19:
2457 case UHF_C_PORT_RESET20:
2458 /* Enable RHSC interrupt if condition is cleared. */
2459 if ((OREAD4(sc, port) >> 16) == 0)
2460 ohci_rhsc_able(sc, 1);
2461 break;
2462 default:
2463 break;
2464 }
2465 break;
2466 case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE)((0x06) | (((0x80 | 0x20 | 0x00)) << 8)):
2467 if ((value & 0xff) != 0) {
2468 err = USBD_IOERROR;
2469 goto ret;
2470 }
2471 v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A0x48);
2472 hubd = ohci_hubd;
2473 hubd.bNbrPorts = sc->sc_noport;
2474 USETW(hubd.wHubCharacteristics,(*(u_int16_t *)(hubd.wHubCharacteristics) = ((v & 0x0200 ?
0x0002 : v & 0x0100 ? 0x0000 : 0x0001)))
2475 (v & OHCI_NPS ? UHD_PWR_NO_SWITCH :(*(u_int16_t *)(hubd.wHubCharacteristics) = ((v & 0x0200 ?
0x0002 : v & 0x0100 ? 0x0000 : 0x0001)))
2476 v & OHCI_PSM ? UHD_PWR_GANGED : UHD_PWR_INDIVIDUAL)(*(u_int16_t *)(hubd.wHubCharacteristics) = ((v & 0x0200 ?
0x0002 : v & 0x0100 ? 0x0000 : 0x0001)))
2477 /* XXX overcurrent */(*(u_int16_t *)(hubd.wHubCharacteristics) = ((v & 0x0200 ?
0x0002 : v & 0x0100 ? 0x0000 : 0x0001)))
2478 )(*(u_int16_t *)(hubd.wHubCharacteristics) = ((v & 0x0200 ?
0x0002 : v & 0x0100 ? 0x0000 : 0x0001)))
;
2479 hubd.bPwrOn2PwrGood = OHCI_GET_POTPGT(v)((v) >> 24);
2480 v = OREAD4(sc, OHCI_RH_DESCRIPTOR_B0x4c);
2481 for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8)
2482 hubd.DeviceRemovable[i++] = (u_int8_t)v;
2483 hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE8 + i;
2484 l = min(len, hubd.bDescLength);
2485 totlen = l;
2486 memcpy(buf, &hubd, l)__builtin_memcpy((buf), (&hubd), (l));
2487 break;
2488 case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE)((0x00) | (((0x80 | 0x20 | 0x00)) << 8)):
2489 if (len != 4) {
2490 err = USBD_IOERROR;
2491 goto ret;
2492 }
2493 memset(buf, 0, len)__builtin_memset((buf), (0), (len)); /* ? XXX */
2494 totlen = len;
2495 break;
2496 case C(UR_GET_STATUS, UT_READ_CLASS_OTHER)((0x00) | (((0x80 | 0x20 | 0x03)) << 8)):
2497 DPRINTFN(8,("ohci_root_ctrl_transfer: get port status i=%d\n",
2498 index));
2499 if (index < 1 || index > sc->sc_noport) {
2500 err = USBD_IOERROR;
2501 goto ret;
2502 }
2503 if (len != 4) {
2504 err = USBD_IOERROR;
2505 goto ret;
2506 }
2507 v = OREAD4(sc, OHCI_RH_PORT_STATUS(index)(0x50 + (index)*4));
2508 DPRINTFN(8,("ohci_root_ctrl_transfer: port status=0x%04x\n",
2509 v));
2510 USETW(ps.wPortStatus, v)(*(u_int16_t *)(ps.wPortStatus) = (v));
2511 USETW(ps.wPortChange, v >> 16)(*(u_int16_t *)(ps.wPortChange) = (v >> 16));
2512 l = min(len, sizeof ps);
2513 memcpy(buf, &ps, l)__builtin_memcpy((buf), (&ps), (l));
2514 totlen = l;
2515 break;
2516 case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE)((0x07) | (((0x00 | 0x20 | 0x00)) << 8)):
2517 err = USBD_IOERROR;
2518 goto ret;
2519 case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE)((0x03) | (((0x00 | 0x20 | 0x00)) << 8)):
2520 break;
2521 case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER)((0x03) | (((0x00 | 0x20 | 0x03)) << 8)):
2522 if (index < 1 || index > sc->sc_noport) {
2523 err = USBD_IOERROR;
2524 goto ret;
2525 }
2526 port = OHCI_RH_PORT_STATUS(index)(0x50 + (index)*4);
2527 switch(value) {
2528 case UHF_PORT_ENABLE1:
2529 OWRITE4(sc, port, UPS_PORT_ENABLED)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0002)))); } while (0)
;
2530 break;
2531 case UHF_PORT_SUSPEND2:
2532 OWRITE4(sc, port, UPS_SUSPEND)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0004)))); } while (0)
;
2533 break;
2534 case UHF_PORT_RESET4:
2535 DPRINTFN(5,("ohci_root_ctrl_transfer: reset port %d\n",
2536 index));
2537 OWRITE4(sc, port, UPS_RESET)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0010)))); } while (0)
;
2538 for (i = 0; i < 5; i++) {
2539 usb_delay_ms(&sc->sc_bus,
2540 USB_PORT_ROOT_RESET_DELAY100);
2541 if (sc->sc_bus.dying) {
2542 err = USBD_IOERROR;
2543 goto ret;
2544 }
2545 if ((OREAD4(sc, port) & UPS_RESET0x0010) == 0)
2546 break;
2547 }
2548 DPRINTFN(8,("ohci port %d reset, status = 0x%04x\n",
2549 index, OREAD4(sc, port)));
2550 break;
2551 case UHF_PORT_POWER8:
2552 DPRINTFN(2,("ohci_root_ctrl_transfer: set port power "
2553 "%d\n", index));
2554 OWRITE4(sc, port, UPS_PORT_POWER)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((port)), ((0x0100)))); } while (0)
;
2555 break;
2556 case UHF_PORT_DISOWN_TO_1_130:
2557 /* accept, but do nothing */
2558 break;
2559 default:
2560 err = USBD_IOERROR;
2561 goto ret;
2562 }
2563 break;
2564 default:
2565 err = USBD_IOERROR;
2566 goto ret;
2567 }
2568 xfer->actlen = totlen;
2569 err = USBD_NORMAL_COMPLETION;
2570 ret:
2571 xfer->status = err;
2572 s = splusb()splraise(0x5);
2573 usb_transfer_complete(xfer);
2574 splx(s)spllower(s);
2575 return (err);
2576}
2577
2578/* Abort a root control request. */
2579void
2580ohci_root_ctrl_abort(struct usbd_xfer *xfer)
2581{
2582 /* Nothing to do, all transfers are synchronous. */
2583}
2584
2585/* Close the root pipe. */
2586void
2587ohci_root_ctrl_close(struct usbd_pipe *pipe)
2588{
2589 DPRINTF(("ohci_root_ctrl_close\n"));
2590 /* Nothing to do. */
2591}
2592
2593usbd_status
2594ohci_root_intr_transfer(struct usbd_xfer *xfer)
2595{
2596 usbd_status err;
2597
2598 /* Insert last in queue. */
2599 err = usb_insert_transfer(xfer);
2600 if (err)
2601 return (err);
2602
2603 /* Pipe isn't running, start first */
2604 return (ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first)));
2605}
2606
2607usbd_status
2608ohci_root_intr_start(struct usbd_xfer *xfer)
2609{
2610 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
2611
2612 if (sc->sc_bus.dying)
2613 return (USBD_IOERROR);
2614
2615 sc->sc_intrxfer = xfer;
2616
2617 return (USBD_IN_PROGRESS);
2618}
2619
2620void
2621ohci_root_intr_abort(struct usbd_xfer *xfer)
2622{
2623 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
2624 int s;
2625
2626 sc->sc_intrxfer = NULL((void *)0);
2627
2628 xfer->status = USBD_CANCELLED;
2629 s = splusb()splraise(0x5);
2630 usb_transfer_complete(xfer);
2631 splx(s)spllower(s);
2632}
2633
2634void
2635ohci_root_intr_close(struct usbd_pipe *pipe)
2636{
2637}
2638
2639usbd_status
2640ohci_device_ctrl_transfer(struct usbd_xfer *xfer)
2641{
2642 usbd_status err;
2643
2644 /* Insert last in queue. */
2645 err = usb_insert_transfer(xfer);
2646 if (err)
2647 return (err);
2648
2649 /* Pipe isn't running, start first */
2650 return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first)));
2651}
2652
2653usbd_status
2654ohci_device_ctrl_start(struct usbd_xfer *xfer)
2655{
2656 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
2657 usbd_status err;
2658
2659 if (sc->sc_bus.dying)
2660 return (USBD_IOERROR);
2661
2662#ifdef DIAGNOSTIC1
2663 if (!(xfer->rqflags & URQ_REQUEST0x01)) {
2664 /* XXX panic */
2665 printf("ohci_device_ctrl_transfer: not a request\n");
2666 return (USBD_INVAL);
2667 }
2668#endif
2669
2670 err = ohci_device_request(xfer);
2671 if (err)
2672 return (err);
2673
2674 return (USBD_IN_PROGRESS);
2675}
2676
2677/* Abort a device control request. */
2678void
2679ohci_device_ctrl_abort(struct usbd_xfer *xfer)
2680{
2681 DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer));
2682 ohci_abort_xfer(xfer, USBD_CANCELLED);
2683}
2684
2685/* Close a device control pipe. */
2686void
2687ohci_device_ctrl_close(struct usbd_pipe *pipe)
2688{
2689 struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
2690 struct ohci_softc *sc = (struct ohci_softc *)pipe->device->bus;
2691
2692 DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe));
2693 ohci_close_pipe(pipe, sc->sc_ctrl_head);
2694 ohci_free_std(sc, opipe->tail.td);
2695}
2696
2697/************************/
2698
2699void
2700ohci_device_clear_toggle(struct usbd_pipe *pipe)
2701{
2702 struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
2703
2704 opipe->sed->ed.ed_headp &= htole32(~OHCI_TOGGLECARRY)((__uint32_t)(~0x00000002));
2705}
2706
2707usbd_status
2708ohci_device_bulk_transfer(struct usbd_xfer *xfer)
2709{
2710 usbd_status err;
2711
2712 /* Insert last in queue. */
2713 err = usb_insert_transfer(xfer);
2714 if (err)
1
Assuming 'err' is 0
2
Taking false branch
2715 return (err);
2716
2717 /* Pipe isn't running, start first */
2718 return (ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first)));
3
Calling 'ohci_device_bulk_start'
2719}
2720
2721usbd_status
2722ohci_device_bulk_start(struct usbd_xfer *xfer)
2723{
2724 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
2725 struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
2726 struct ohci_soft_td *data, *tail, *tdp;
4
'tail' declared without an initial value
2727 struct ohci_soft_ed *sed;
2728 u_int len;
2729 int s, endpt;
2730 usbd_status err;
2731
2732 if (sc->sc_bus.dying)
5
Assuming field 'dying' is 0
6
Taking false branch
2733 return (USBD_IOERROR);
2734
2735#ifdef DIAGNOSTIC1
2736 if (xfer->rqflags & URQ_REQUEST0x01) {
7
Assuming the condition is false
8
Taking false branch
2737 /* XXX panic */
2738 printf("ohci_device_bulk_start: a request\n");
2739 return (USBD_INVAL);
2740 }
2741#endif
2742
2743 len = xfer->length;
2744 endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
2745 sed = opipe->sed;
2746
2747 DPRINTFN(4,("ohci_device_bulk_start: xfer=%p len=%u "
2748 "flags=%d endpt=%d\n", xfer, len, xfer->flags, endpt));
2749
2750 /* Update device address */
2751 sed->ed.ed_flags = htole32(((__uint32_t)((((__uint32_t)(sed->ed.ed_flags)) & ~0x0000007f
) | (xfer->device->address)))
2752 (letoh32(sed->ed.ed_flags) & ~OHCI_ED_ADDRMASK) |((__uint32_t)((((__uint32_t)(sed->ed.ed_flags)) & ~0x0000007f
) | (xfer->device->address)))
2753 OHCI_ED_SET_FA(xfer->device->address))((__uint32_t)((((__uint32_t)(sed->ed.ed_flags)) & ~0x0000007f
) | (xfer->device->address)))
;
2754
2755 /* Allocate a chain of new TDs (including a new tail). */
2756 data = opipe->tail.td;
2757 err = ohci_alloc_std_chain(sc, len, xfer, data, &tail);
9
Calling 'ohci_alloc_std_chain'
21
Returning from 'ohci_alloc_std_chain'
2758 /* We want interrupt at the end of the transfer. */
2759 tail->td.td_flags &= htole32(~OHCI_TD_INTR_MASK)((__uint32_t)(~0x00e00000));
22
Dereference of undefined pointer value
2760 tail->td.td_flags |= htole32(OHCI_TD_SET_DI(1))((__uint32_t)(((1) << 21)));
2761 tail->flags |= OHCI_CALL_DONE0x0001;
2762 tail = tail->nexttd; /* point at sentinel */
2763 if (err)
2764 return (err);
2765
2766 tail->xfer = NULL((void *)0);
2767 xfer->hcpriv = data;
2768
2769 DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x "
2770 "td_cbp=0x%08x td_be=0x%08x\n",
2771 (int)letoh32(sed->ed.ed_flags),
2772 (int)letoh32(data->td.td_flags),
2773 (int)letoh32(data->td.td_cbp),
2774 (int)letoh32(data->td.td_be)));
2775
2776#ifdef OHCI_DEBUG
2777 if (ohcidebug > 5) {
2778 ohci_dump_ed(sed);
2779 ohci_dump_tds(data);
2780 }
2781#endif
2782
2783 /* Insert ED in schedule */
2784 s = splusb()splraise(0x5);
2785 for (tdp = data; tdp != tail; tdp = tdp->nexttd) {
2786 tdp->xfer = xfer;
2787 }
2788 sed->ed.ed_tailp = htole32(tail->physaddr)((__uint32_t)(tail->physaddr));
2789 opipe->tail.td = tail;
2790 sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP)((__uint32_t)(~0x00004000));
2791 OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF)do { bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->
sc_size, 0x01|0x02); (((sc)->iot)->write_4(((sc)->ioh
), ((0x08)), ((0x00000004)))); } while (0)
;
2792 if (xfer->timeout && !sc->sc_bus.use_polling) {
2793 timeout_del(&xfer->timeout_handle);
2794 timeout_set(&xfer->timeout_handle, ohci_timeout, xfer);
2795 timeout_add_msec(&xfer->timeout_handle, xfer->timeout);
2796 }
2797
2798#if 0
2799/* This goes wrong if we are too slow. */
2800 if (ohcidebug > 10) {
2801 delay(10000)(*delay_func)(10000);
2802 DPRINTF(("ohci_device_intr_transfer: status=%x\n",
2803 OREAD4(sc, OHCI_COMMAND_STATUS)));
2804 ohci_dump_ed(sed);
2805 ohci_dump_tds(data);
2806 }
2807#endif
2808
2809 splx(s)spllower(s);
2810
2811 return (USBD_IN_PROGRESS);
2812}
2813
2814void
2815ohci_device_bulk_abort(struct usbd_xfer *xfer)
2816{
2817 DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer));
2818 ohci_abort_xfer(xfer, USBD_CANCELLED);
2819}
2820
2821/*
2822 * Close a device bulk pipe.
2823 */
2824void
2825ohci_device_bulk_close(struct usbd_pipe *pipe)
2826{
2827 struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
2828 struct ohci_softc *sc = (struct ohci_softc *)pipe->device->bus;
2829
2830 DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe));
2831 ohci_close_pipe(pipe, sc->sc_bulk_head);
2832 ohci_free_std(sc, opipe->tail.td);
2833}
2834
2835/************************/
2836
2837usbd_status
2838ohci_device_intr_transfer(struct usbd_xfer *xfer)
2839{
2840 usbd_status err;
2841
2842 /* Insert last in queue. */
2843 err = usb_insert_transfer(xfer);
2844 if (err)
2845 return (err);
2846
2847 /* Pipe isn't running, start first */
2848 return (ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first)));
2849}
2850
2851usbd_status
2852ohci_device_intr_start(struct usbd_xfer *xfer)
2853{
2854 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
2855 struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
2856 struct ohci_soft_ed *sed = opipe->sed;
2857 struct ohci_soft_td *data, *tail;
2858 int s, len, endpt;
2859
2860 if (sc->sc_bus.dying)
2861 return (USBD_IOERROR);
2862
2863 DPRINTFN(3, ("ohci_device_intr_transfer: xfer=%p len=%u "
2864 "flags=%d priv=%p\n",
2865 xfer, xfer->length, xfer->flags, xfer->priv));
2866
2867#ifdef DIAGNOSTIC1
2868 if (xfer->rqflags & URQ_REQUEST0x01)
2869 panic("ohci_device_intr_transfer: a request");
2870#endif
2871
2872 usb_syncmem(&xfer->dmabuf, 0, xfer->length,
2873 usbd_xfer_isread(xfer) ?
2874 BUS_DMASYNC_PREREAD0x01 : BUS_DMASYNC_PREWRITE0x04);
2875
2876 len = xfer->length;
2877 endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
2878
2879 data = opipe->tail.td;
2880 tail = ohci_alloc_std(sc);
2881 if (tail == NULL((void *)0))
2882 return (USBD_NOMEM);
2883 tail->xfer = NULL((void *)0);
2884
2885 data->td.td_flags = htole32(((__uint32_t)((usbd_xfer_isread(xfer) ? 0x00100000 : 0x00080000
) | 0xf0000000 | ((1) << 21) | 0x00000000))
2886 (usbd_xfer_isread(xfer) ? OHCI_TD_IN : OHCI_TD_OUT) |((__uint32_t)((usbd_xfer_isread(xfer) ? 0x00100000 : 0x00080000
) | 0xf0000000 | ((1) << 21) | 0x00000000))
2887 OHCI_TD_NOCC |((__uint32_t)((usbd_xfer_isread(xfer) ? 0x00100000 : 0x00080000
) | 0xf0000000 | ((1) << 21) | 0x00000000))
2888 OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY)((__uint32_t)((usbd_xfer_isread(xfer) ? 0x00100000 : 0x00080000
) | 0xf0000000 | ((1) << 21) | 0x00000000))
;
2889 if (xfer->flags & USBD_SHORT_XFER_OK0x04)
2890 data->td.td_flags |= htole32(OHCI_TD_R)((__uint32_t)(0x00040000));
2891 data->td.td_cbp = htole32(DMAADDR(&xfer->dmabuf, 0))((__uint32_t)(((&xfer->dmabuf)->block->map->dm_segs
[0].ds_addr + (&xfer->dmabuf)->offs + (0))))
;
2892 data->nexttd = tail;
2893 data->td.td_nexttd = htole32(tail->physaddr)((__uint32_t)(tail->physaddr));
2894 data->td.td_be = htole32(letoh32(data->td.td_cbp) + len - 1)((__uint32_t)(((__uint32_t)(data->td.td_cbp)) + len - 1));
2895 data->len = len;
2896 data->xfer = xfer;
2897 data->flags = OHCI_CALL_DONE0x0001 | OHCI_ADD_LEN0x0002;
2898 xfer->hcpriv = data;
2899
2900#ifdef OHCI_DEBUG
2901 if (ohcidebug > 5) {
2902 DPRINTF(("ohci_device_intr_transfer:\n"));
2903 ohci_dump_ed(sed);
2904 ohci_dump_tds(data);
2905 }
2906#endif
2907
2908 /* Insert ED in schedule */
2909 s = splusb()splraise(0x5);
2910 sed->ed.ed_tailp = htole32(tail->physaddr)((__uint32_t)(tail->physaddr));
2911 opipe->tail.td = tail;
2912 sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP)((__uint32_t)(~0x00004000));
2913
2914#if 0
2915/*
2916 * This goes horribly wrong, printing thousands of descriptors,
2917 * because false references are followed due to the fact that the
2918 * TD is gone.
2919 */
2920 if (ohcidebug > 5) {
2921 usb_delay_ms(&sc->sc_bus, 5);
2922 DPRINTF(("ohci_device_intr_transfer: status=%x\n",
2923 OREAD4(sc, OHCI_COMMAND_STATUS)));
2924 ohci_dump_ed(sed);
2925 ohci_dump_tds(data);
2926 }
2927#endif
2928 splx(s)spllower(s);
2929
2930 return (USBD_IN_PROGRESS);
2931}
2932
2933void
2934ohci_device_intr_abort(struct usbd_xfer *xfer)
2935{
2936 KASSERT(!xfer->pipe->repeat || xfer->pipe->intrxfer == xfer)((!xfer->pipe->repeat || xfer->pipe->intrxfer == xfer
) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/dev/usb/ohci.c"
, 2936, "!xfer->pipe->repeat || xfer->pipe->intrxfer == xfer"
))
;
2937
2938 ohci_abort_xfer(xfer, USBD_CANCELLED);
2939}
2940
2941/* Close a device interrupt pipe. */
2942void
2943ohci_device_intr_close(struct usbd_pipe *pipe)
2944{
2945 struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
2946 struct ohci_softc *sc = (struct ohci_softc *)pipe->device->bus;
2947 int nslots = opipe->u.intr.nslots;
2948 int pos = opipe->u.intr.pos;
2949 int j;
2950 struct ohci_soft_ed *p, *sed = opipe->sed;
2951 int s;
2952
2953 DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n",
2954 pipe, nslots, pos));
2955 s = splusb()splraise(0x5);
2956 sed->ed.ed_flags |= htole32(OHCI_ED_SKIP)((__uint32_t)(0x00004000));
2957 if ((letoh32(sed->ed.ed_tailp)((__uint32_t)(sed->ed.ed_tailp)) & OHCI_HEADMASK0xfffffffc) !=
2958 (letoh32(sed->ed.ed_headp)((__uint32_t)(sed->ed.ed_headp)) & OHCI_HEADMASK0xfffffffc))
2959 usb_delay_ms(&sc->sc_bus, 2);
2960
2961 for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next)
2962 ;
2963#ifdef DIAGNOSTIC1
2964 if (p == NULL((void *)0))
2965 panic("ohci_device_intr_close: ED not found");
2966#endif
2967 p->next = sed->next;
2968 p->ed.ed_nexted = sed->ed.ed_nexted;
2969 splx(s)spllower(s);
2970
2971 for (j = 0; j < nslots; j++)
2972 --sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS32];
2973
2974 ohci_free_std(sc, opipe->tail.td);
2975 ohci_free_sed(sc, opipe->sed);
2976}
2977
2978usbd_status
2979ohci_device_setintr(struct ohci_softc *sc, struct ohci_pipe *opipe, int ival)
2980{
2981 int i, j, s, best;
2982 u_int npoll, slow, shigh, nslots;
2983 u_int bestbw, bw;
2984 struct ohci_soft_ed *hsed, *sed = opipe->sed;
2985
2986 DPRINTFN(2, ("ohci_setintr: pipe=%p\n", opipe));
2987 if (ival == 0) {
2988 printf("ohci_setintr: 0 interval\n");
2989 return (USBD_INVAL);
2990 }
2991
2992 npoll = OHCI_NO_INTRS32;
2993 while (npoll > ival)
2994 npoll /= 2;
2995 DPRINTFN(2, ("ohci_setintr: ival=%d npoll=%d\n", ival, npoll));
2996
2997 /*
2998 * We now know which level in the tree the ED must go into.
2999 * Figure out which slot has most bandwidth left over.
3000 * Slots to examine:
3001 * npoll
3002 * 1 0
3003 * 2 1 2
3004 * 4 3 4 5 6
3005 * 8 7 8 9 10 11 12 13 14
3006 * N (N-1) .. (N-1+N-1)
3007 */
3008 slow = npoll-1;
3009 shigh = slow + npoll;
3010 nslots = OHCI_NO_INTRS32 / npoll;
3011 for (best = i = slow, bestbw = ~0; i < shigh; i++) {
3012 bw = 0;
3013 for (j = 0; j < nslots; j++)
3014 bw += sc->sc_bws[(i * nslots + j) % OHCI_NO_INTRS32];
3015 if (bw < bestbw) {
3016 best = i;
3017 bestbw = bw;
3018 }
3019 }
3020 DPRINTFN(2, ("ohci_setintr: best=%d(%d..%d) bestbw=%d\n",
3021 best, slow, shigh, bestbw));
3022
3023 s = splusb()splraise(0x5);
3024 hsed = sc->sc_eds[best];
3025 sed->next = hsed->next;
3026 sed->ed.ed_nexted = hsed->ed.ed_nexted;
3027 hsed->next = sed;
3028 hsed->ed.ed_nexted = htole32(sed->physaddr)((__uint32_t)(sed->physaddr));
3029 splx(s)spllower(s);
3030
3031 for (j = 0; j < nslots; j++)
3032 ++sc->sc_bws[(best * nslots + j) % OHCI_NO_INTRS32];
3033 opipe->u.intr.nslots = nslots;
3034 opipe->u.intr.pos = best;
3035
3036 DPRINTFN(5, ("ohci_setintr: returns %p\n", opipe));
3037 return (USBD_NORMAL_COMPLETION);
3038}
3039
3040/***********************/
3041
3042usbd_status
3043ohci_device_isoc_transfer(struct usbd_xfer *xfer)
3044{
3045 usbd_status err;
3046
3047 DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer));
3048
3049 /* Put it on our queue, */
3050 err = usb_insert_transfer(xfer);
3051
3052 /* bail out on error, */
3053 if (err && err != USBD_IN_PROGRESS)
3054 return (err);
3055
3056 /* XXX should check inuse here */
3057
3058 /* insert into schedule, */
3059 ohci_device_isoc_enter(xfer);
3060
3061 /* and start if the pipe wasn't running */
3062 if (!err)
3063 ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue)((&xfer->pipe->queue)->sqh_first));
3064
3065 return (err);
3066}
3067
3068void
3069ohci_device_isoc_enter(struct usbd_xfer *xfer)
3070{
3071 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
3072 struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
3073 struct ohci_soft_ed *sed = opipe->sed;
3074 struct iso *iso = &opipe->u.iso;
3075 struct ohci_soft_itd *sitd, *nsitd;
3076 ohci_physaddr_t buf, offs, noffs, bp0;
3077 int i, ncur, nframes;
3078 int s;
3079
3080 DPRINTFN(1,("ohci_device_isoc_enter: used=%d next=%d xfer=%p "
3081 "nframes=%d\n",
3082 iso->inuse, iso->next, xfer, xfer->nframes));
3083
3084 if (sc->sc_bus.dying)
3085 return;
3086
3087 usb_syncmem(&xfer->dmabuf, 0, xfer->length,
3088 usbd_xfer_isread(xfer) ?
3089 BUS_DMASYNC_PREREAD0x01 : BUS_DMASYNC_PREWRITE0x04);
3090
3091 if (iso->next == -1) {
3092 /* Not in use yet, schedule it a few frames ahead. */
3093 iso->next = letoh32(sc->sc_hcca->hcca_frame_number)((__uint32_t)(sc->sc_hcca->hcca_frame_number)) + 5;
3094 DPRINTFN(2,("ohci_device_isoc_enter: start next=%d\n",
3095 iso->next));
3096 }
3097
3098 sitd = opipe->tail.itd;
3099 buf = DMAADDR(&xfer->dmabuf, 0)((&xfer->dmabuf)->block->map->dm_segs[0].ds_addr
+ (&xfer->dmabuf)->offs + (0))
;
3100 bp0 = OHCI_PAGE(buf)((buf) &~ 0xfff);
3101 offs = OHCI_PAGE_OFFSET(buf)((buf) & 0xfff);
3102 nframes = xfer->nframes;
3103 xfer->hcpriv = sitd;
3104 for (i = ncur = 0; i < nframes; i++, ncur++) {
3105 noffs = offs + xfer->frlengths[i];
3106 if (ncur == OHCI_ITD_NOFFSET8 || /* all offsets used */
3107 OHCI_PAGE(buf + noffs)((buf + noffs) &~ 0xfff) > bp0 + OHCI_PAGE_SIZE0x1000) { /* too many page crossings */
3108
3109 /* Allocate next ITD */
3110 nsitd = ohci_alloc_sitd(sc);
3111 if (nsitd == NULL((void *)0)) {
3112 /* XXX what now? */
3113 printf("%s: isoc TD alloc failed\n",
3114 sc->sc_bus.bdev.dv_xname);
3115 return;
3116 }
3117
3118 /* Fill current ITD */
3119 sitd->itd.itd_flags = htole32(((__uint32_t)(0xf0000000 | ((iso->next) & 0xffff) | ((
6) << 21) | (((ncur)-1) << 24)))
3120 OHCI_ITD_NOCC |((__uint32_t)(0xf0000000 | ((iso->next) & 0xffff) | ((
6) << 21) | (((ncur)-1) << 24)))
3121 OHCI_ITD_SET_SF(iso->next) |((__uint32_t)(0xf0000000 | ((iso->next) & 0xffff) | ((
6) << 21) | (((ncur)-1) << 24)))
3122 OHCI_ITD_SET_DI(6) | /* delay intr a little */((__uint32_t)(0xf0000000 | ((iso->next) & 0xffff) | ((
6) << 21) | (((ncur)-1) << 24)))
3123 OHCI_ITD_SET_FC(ncur))((__uint32_t)(0xf0000000 | ((iso->next) & 0xffff) | ((
6) << 21) | (((ncur)-1) << 24)))
;
3124 sitd->itd.itd_bp0 = htole32(bp0)((__uint32_t)(bp0));
3125 sitd->nextitd = nsitd;
3126 sitd->itd.itd_nextitd = htole32(nsitd->physaddr)((__uint32_t)(nsitd->physaddr));
3127 sitd->itd.itd_be = htole32(bp0 + offs - 1)((__uint32_t)(bp0 + offs - 1));
3128 sitd->xfer = xfer;
3129 sitd->flags = 0;
3130
3131 sitd = nsitd;
3132 iso->next = iso->next + ncur;
3133 bp0 = OHCI_PAGE(buf + offs)((buf + offs) &~ 0xfff);
3134 ncur = 0;
3135 }
3136 sitd->itd.itd_offset[ncur] = htole16(OHCI_ITD_MK_OFFS(offs))((__uint16_t)((0xe000 | ((offs) & 0x1fff))));
3137 offs = noffs;
3138 }
3139 nsitd = ohci_alloc_sitd(sc);
3140 if (nsitd == NULL((void *)0)) {
3141 /* XXX what now? */
3142 printf("%s: isoc TD alloc failed\n",
3143 sc->sc_bus.bdev.dv_xname);
3144 return;
3145 }
3146 /* Fixup last used ITD */
3147 sitd->itd.itd_flags = htole32(((__uint32_t)(0xf0000000 | ((iso->next) & 0xffff) | ((
0) << 21) | (((ncur)-1) << 24)))
3148 OHCI_ITD_NOCC |((__uint32_t)(0xf0000000 | ((iso->next) & 0xffff) | ((
0) << 21) | (((ncur)-1) << 24)))
3149 OHCI_ITD_SET_SF(iso->next) |((__uint32_t)(0xf0000000 | ((iso->next) & 0xffff) | ((
0) << 21) | (((ncur)-1) << 24)))
3150 OHCI_ITD_SET_DI(0) |((__uint32_t)(0xf0000000 | ((iso->next) & 0xffff) | ((
0) << 21) | (((ncur)-1) << 24)))
3151 OHCI_ITD_SET_FC(ncur))((__uint32_t)(0xf0000000 | ((iso->next) & 0xffff) | ((
0) << 21) | (((ncur)-1) << 24)))
;
3152 sitd->itd.itd_bp0 = htole32(bp0)((__uint32_t)(bp0));
3153 sitd->nextitd = nsitd;
3154 sitd->itd.itd_nextitd = htole32(nsitd->physaddr)((__uint32_t)(nsitd->physaddr));
3155 sitd->itd.itd_be = htole32(bp0 + offs - 1)((__uint32_t)(bp0 + offs - 1));
3156 sitd->xfer = xfer;
3157 sitd->flags = OHCI_CALL_DONE0x0001;
3158
3159 iso->next = iso->next + ncur;
3160 iso->inuse += nframes;
3161
3162 xfer->actlen = offs; /* XXX pretend we did it all */
3163
3164 xfer->status = USBD_IN_PROGRESS;
3165
3166#ifdef OHCI_DEBUG
3167 if (ohcidebug > 5) {
3168 DPRINTF(("ohci_device_isoc_enter: frame=%d\n",
3169 letoh32(sc->sc_hcca->hcca_frame_number)));
3170 ohci_dump_itds(xfer->hcpriv);
3171 ohci_dump_ed(sed);
3172 }
3173#endif
3174
3175 s = splusb()splraise(0x5);
3176 sed->ed.ed_tailp = htole32(nsitd->physaddr)((__uint32_t)(nsitd->physaddr));
3177 opipe->tail.itd = nsitd;
3178 sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP)((__uint32_t)(~0x00004000));
3179 splx(s)spllower(s);
3180
3181#ifdef OHCI_DEBUG
3182 if (ohcidebug > 5) {
3183 delay(150000)(*delay_func)(150000);
3184 DPRINTF(("ohci_device_isoc_enter: after frame=%d\n",
3185 letoh32(sc->sc_hcca->hcca_frame_number)));
3186 ohci_dump_itds(xfer->hcpriv);
3187 ohci_dump_ed(sed);
3188 }
3189#endif
3190}
3191
3192usbd_status
3193ohci_device_isoc_start(struct usbd_xfer *xfer)
3194{
3195 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
3196
3197 DPRINTFN(5,("ohci_device_isoc_start: xfer=%p\n", xfer));
3198
3199 if (sc->sc_bus.dying)
3200 return (USBD_IOERROR);
3201
3202#ifdef DIAGNOSTIC1
3203 if (xfer->status != USBD_IN_PROGRESS)
3204 printf("ohci_device_isoc_start: not in progress %p\n", xfer);
3205#endif
3206
3207 return (USBD_IN_PROGRESS);
3208}
3209
3210void
3211ohci_device_isoc_abort(struct usbd_xfer *xfer)
3212{
3213 struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
3214 struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
3215 struct ohci_soft_ed *sed;
3216 struct ohci_soft_itd *sitd;
3217 int s;
3218
3219 s = splusb()splraise(0x5);
3220
3221 DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p\n", xfer));
3222
3223 /* Transfer is already done. */
3224 if (xfer->status != USBD_NOT_STARTED &&
3225 xfer->status != USBD_IN_PROGRESS) {
3226 splx(s)spllower(s);
3227 printf("ohci_device_isoc_abort: early return\n");
3228 return;
3229 }
3230
3231 /* Give xfer the requested abort code. */
3232 xfer->status = USBD_CANCELLED;
3233
3234 sed = opipe->sed;
3235 sed->ed.ed_flags |= htole32(OHCI_ED_SKIP)((__uint32_t)(0x00004000)); /* force hardware skip */
3236
3237 sitd = xfer->hcpriv;
3238#ifdef DIAGNOSTIC1
3239 if (sitd == NULL((void *)0)) {
3240 splx(s)spllower(s);
3241 printf("ohci_device_isoc_abort: hcpriv==0\n");
3242 return;
3243 }
3244#endif
3245 for (; sitd->xfer == xfer; sitd = sitd->nextitd) {
3246#ifdef DIAGNOSTIC1
3247 DPRINTFN(1,("abort sets done sitd=%p\n", sitd));
3248 sitd->isdone = 1;
3249#endif
3250 }
3251
3252 splx(s)spllower(s);
3253
3254 usb_delay_ms(&sc->sc_bus, OHCI_ITD_NOFFSET8);
3255
3256 s = splusb()splraise(0x5);
3257
3258 /* Run callback. */
3259 usb_transfer_complete(xfer);
3260
3261 sed->ed.ed_headp = htole32(sitd->physaddr)((__uint32_t)(sitd->physaddr)); /* unlink TDs */
3262 sed->ed.ed_flags &= htole32(~OHCI_ED_SKIP)((__uint32_t)(~0x00004000)); /* remove hardware skip */
3263
3264 splx(s)spllower(s);
3265}
3266
3267void
3268ohci_device_isoc_done(struct usbd_xfer *xfer)
3269{
3270 DPRINTFN(1,("ohci_device_isoc_done: xfer=%p\n", xfer));
3271}
3272
3273usbd_status
3274ohci_setup_isoc(struct usbd_pipe *pipe)
3275{
3276 struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
3277 struct ohci_softc *sc = (struct ohci_softc *)pipe->device->bus;
3278 struct iso *iso = &opipe->u.iso;
3279 int s;
3280
3281 iso->next = -1;
3282 iso->inuse = 0;
3283
3284 s = splusb()splraise(0x5);
3285 ohci_add_ed(opipe->sed, sc->sc_isoc_head);
3286 splx(s)spllower(s);
3287
3288 return (USBD_NORMAL_COMPLETION);
3289}
3290
3291void
3292ohci_device_isoc_close(struct usbd_pipe *pipe)
3293{
3294 struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
3295 struct ohci_softc *sc = (struct ohci_softc *)pipe->device->bus;
3296
3297 DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe));
3298 ohci_close_pipe(pipe, sc->sc_isoc_head);
3299#ifdef DIAGNOSTIC1
3300 opipe->tail.itd->isdone = 1;
3301#endif
3302 ohci_free_sitd(sc, opipe->tail.itd);
3303}