ohci.c revision 1.182.12.3 1 1.182.12.3 itohy /* $NetBSD: ohci.c,v 1.182.12.3 2008/05/21 05:02:11 itohy Exp $ */
2 1.1 augustss
3 1.182.12.1 itohy /*-
4 1.182.12.1 itohy * Copyright (c) 1998, 2004, 2005, 2007 The NetBSD Foundation, Inc.
5 1.1 augustss * All rights reserved.
6 1.1 augustss *
7 1.11 augustss * This code is derived from software contributed to The NetBSD Foundation
8 1.89 augustss * by Lennart Augustsson (lennart (at) augustsson.net) at
9 1.11 augustss * Carlstedt Research & Technology.
10 1.157 mycroft * This code is derived from software contributed to The NetBSD Foundation
11 1.157 mycroft * by Charles M. Hannum.
12 1.1 augustss *
13 1.1 augustss * Redistribution and use in source and binary forms, with or without
14 1.1 augustss * modification, are permitted provided that the following conditions
15 1.1 augustss * are met:
16 1.1 augustss * 1. Redistributions of source code must retain the above copyright
17 1.1 augustss * notice, this list of conditions and the following disclaimer.
18 1.1 augustss * 2. Redistributions in binary form must reproduce the above copyright
19 1.1 augustss * notice, this list of conditions and the following disclaimer in the
20 1.1 augustss * documentation and/or other materials provided with the distribution.
21 1.1 augustss * 3. All advertising materials mentioning features or use of this software
22 1.1 augustss * must display the following acknowledgement:
23 1.1 augustss * This product includes software developed by the NetBSD
24 1.1 augustss * Foundation, Inc. and its contributors.
25 1.1 augustss * 4. Neither the name of The NetBSD Foundation nor the names of its
26 1.1 augustss * contributors may be used to endorse or promote products derived
27 1.1 augustss * from this software without specific prior written permission.
28 1.1 augustss *
29 1.1 augustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
30 1.1 augustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
31 1.1 augustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
32 1.1 augustss * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
33 1.1 augustss * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 1.1 augustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 1.1 augustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 1.1 augustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 1.1 augustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 1.1 augustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 1.1 augustss * POSSIBILITY OF SUCH DAMAGE.
40 1.1 augustss */
41 1.1 augustss
42 1.1 augustss /*
43 1.1 augustss * USB Open Host Controller driver.
44 1.1 augustss *
45 1.96 augustss * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html
46 1.182.12.1 itohy * USB spec: http://www.usb.org/developers/docs/
47 1.1 augustss */
48 1.108 lukem
49 1.108 lukem #include <sys/cdefs.h>
50 1.182.12.3 itohy __KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.182.12.3 2008/05/21 05:02:11 itohy Exp $");
51 1.182.12.1 itohy /* __FBSDID("$FreeBSD: src/sys/dev/usb/ohci.c,v 1.167 2006/10/19 01:15:58 iedowse Exp $"); */
52 1.1 augustss
53 1.1 augustss #include <sys/param.h>
54 1.1 augustss #include <sys/systm.h>
55 1.1 augustss #include <sys/malloc.h>
56 1.55 augustss #include <sys/kernel.h>
57 1.182.12.1 itohy #if defined(__NetBSD__) || defined(__OpenBSD__)
58 1.1 augustss #include <sys/device.h>
59 1.55 augustss #include <sys/select.h>
60 1.153 fvdl #include <uvm/uvm_extern.h>
61 1.15 augustss #elif defined(__FreeBSD__)
62 1.182.12.1 itohy #include <sys/endian.h>
63 1.15 augustss #include <sys/module.h>
64 1.15 augustss #include <sys/bus.h>
65 1.55 augustss #if defined(DIAGNOSTIC) && defined(__i386__) && defined(__FreeBSD__)
66 1.55 augustss #include <machine/cpu.h>
67 1.55 augustss #endif
68 1.15 augustss #endif
69 1.1 augustss #include <sys/proc.h>
70 1.1 augustss #include <sys/queue.h>
71 1.1 augustss
72 1.4 augustss #include <machine/bus.h>
73 1.16 augustss #include <machine/endian.h>
74 1.4 augustss
75 1.1 augustss #include <dev/usb/usb.h>
76 1.1 augustss #include <dev/usb/usbdi.h>
77 1.1 augustss #include <dev/usb/usbdivar.h>
78 1.38 augustss #include <dev/usb/usb_mem.h>
79 1.1 augustss #include <dev/usb/usb_quirks.h>
80 1.1 augustss
81 1.1 augustss #include <dev/usb/ohcireg.h>
82 1.1 augustss #include <dev/usb/ohcivar.h>
83 1.1 augustss
84 1.15 augustss #if defined(__FreeBSD__)
85 1.182.12.1 itohy #include <sys/sysctl.h>
86 1.55 augustss
87 1.15 augustss #define delay(d) DELAY(d)
88 1.15 augustss #endif
89 1.1 augustss
90 1.36 augustss #if defined(__OpenBSD__)
91 1.36 augustss struct cfdriver ohci_cd = {
92 1.36 augustss NULL, "ohci", DV_DULL
93 1.36 augustss };
94 1.36 augustss #endif
95 1.36 augustss
96 1.182.12.1 itohy #ifdef USB_DEBUG
97 1.52 augustss #define DPRINTF(x) if (ohcidebug) logprintf x
98 1.52 augustss #define DPRINTFN(n,x) if (ohcidebug>(n)) logprintf x
99 1.52 augustss int ohcidebug = 0;
100 1.182.12.1 itohy #ifdef __FreeBSD__
101 1.182.12.1 itohy SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci");
102 1.182.12.1 itohy SYSCTL_INT(_hw_usb_ohci, OID_AUTO, debug, CTLFLAG_RW,
103 1.182.12.1 itohy &ohcidebug, 0, "ohci debug level");
104 1.182.12.1 itohy #endif
105 1.92 tv #ifndef __NetBSD__
106 1.92 tv #define bitmask_snprintf(q,f,b,l) snprintf((b), (l), "%b", (q), (f))
107 1.92 tv #endif
108 1.52 augustss #else
109 1.52 augustss #define DPRINTF(x)
110 1.52 augustss #define DPRINTFN(n,x)
111 1.52 augustss #endif
112 1.52 augustss
113 1.182.12.1 itohy /*
114 1.182.12.1 itohy * The OHCI controller is either little endian or host endian,
115 1.182.12.1 itohy * so on big endian machines with little endian controller
116 1.182.12.1 itohy * the data strored in memory needs to be swapped.
117 1.182.12.1 itohy */
118 1.182.12.1 itohy #define O16TOH(val) (sc->sc_endian ? (val) : le16toh(val))
119 1.182.12.1 itohy #define O32TOH(val) (sc->sc_endian ? (val) : le32toh(val))
120 1.182.12.1 itohy #define HTOO16(val) (sc->sc_endian ? (val) : htole16(val))
121 1.182.12.1 itohy #define HTOO32(val) (sc->sc_endian ? (val) : htole32(val))
122 1.168 augustss
123 1.1 augustss struct ohci_pipe;
124 1.1 augustss
125 1.182.12.1 itohy Static void ohci_free_desc_chunks(ohci_softc_t *,
126 1.182.12.1 itohy struct ohci_mdescs *);
127 1.91 augustss Static ohci_soft_ed_t *ohci_alloc_sed(ohci_softc_t *);
128 1.91 augustss Static void ohci_free_sed(ohci_softc_t *, ohci_soft_ed_t *);
129 1.1 augustss
130 1.182.12.1 itohy Static usbd_status ohci_grow_std(ohci_softc_t *);
131 1.91 augustss Static ohci_soft_td_t *ohci_alloc_std(ohci_softc_t *);
132 1.182.12.1 itohy Static ohci_soft_td_t *ohci_alloc_std_norsv(ohci_softc_t *);
133 1.91 augustss Static void ohci_free_std(ohci_softc_t *, ohci_soft_td_t *);
134 1.182.12.1 itohy Static void ohci_free_std_norsv(ohci_softc_t *, ohci_soft_td_t *);
135 1.1 augustss
136 1.182.12.1 itohy Static usbd_status ohci_grow_sitd(ohci_softc_t *);
137 1.91 augustss Static ohci_soft_itd_t *ohci_alloc_sitd(ohci_softc_t *);
138 1.182.12.1 itohy Static ohci_soft_itd_t *ohci_alloc_sitd_norsv(ohci_softc_t *);
139 1.91 augustss Static void ohci_free_sitd(ohci_softc_t *,ohci_soft_itd_t *);
140 1.182.12.1 itohy Static void ohci_free_sitd_norsv(ohci_softc_t *,ohci_soft_itd_t *);
141 1.60 augustss
142 1.91 augustss Static void ohci_free_std_chain(ohci_softc_t *, ohci_soft_td_t *,
143 1.91 augustss ohci_soft_td_t *);
144 1.91 augustss Static usbd_status ohci_alloc_std_chain(struct ohci_pipe *,
145 1.77 augustss ohci_softc_t *, int, int, usbd_xfer_handle,
146 1.91 augustss ohci_soft_td_t *, ohci_soft_td_t **);
147 1.53 augustss
148 1.91 augustss Static usbd_status ohci_open(usbd_pipe_handle);
149 1.91 augustss Static void ohci_poll(struct usbd_bus *);
150 1.99 augustss Static void ohci_softintr(void *);
151 1.91 augustss Static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle);
152 1.91 augustss Static void ohci_rhsc(ohci_softc_t *, usbd_xfer_handle);
153 1.91 augustss
154 1.91 augustss Static usbd_status ohci_device_request(usbd_xfer_handle xfer);
155 1.168 augustss Static void ohci_add_ed(ohci_softc_t *, ohci_soft_ed_t *,
156 1.168 augustss ohci_soft_ed_t *);
157 1.182.12.3 itohy Static void ohci_rem_ed(ohci_softc_t *, ohci_soft_ed_t *,
158 1.182.12.3 itohy ohci_soft_ed_t *);
159 1.168 augustss
160 1.182.12.1 itohy Static ohci_soft_td_t *ohci_find_td(ohci_softc_t *, ohci_physaddr_t);
161 1.182.12.1 itohy Static ohci_soft_itd_t *ohci_find_itd(ohci_softc_t *, ohci_physaddr_t);
162 1.91 augustss
163 1.91 augustss Static usbd_status ohci_setup_isoc(usbd_pipe_handle pipe);
164 1.91 augustss Static void ohci_device_isoc_enter(usbd_xfer_handle);
165 1.91 augustss
166 1.182.12.1 itohy Static usbd_status ohci_prealloc(struct ohci_softc *,
167 1.182.12.1 itohy struct ohci_xfer *, size_t, int);
168 1.182.12.1 itohy Static usbd_status ohci_allocm(struct usbd_bus *, usbd_xfer_handle,
169 1.182.12.1 itohy void *buf, size_t);
170 1.182.12.1 itohy Static void ohci_freem(struct usbd_bus *, usbd_xfer_handle,
171 1.182.12.1 itohy enum usbd_waitflg);
172 1.182.12.1 itohy
173 1.182.12.1 itohy Static usbd_status ohci_map_alloc(usbd_xfer_handle);
174 1.182.12.1 itohy Static void ohci_map_free(usbd_xfer_handle);
175 1.182.12.1 itohy Static void ohci_mapm(usbd_xfer_handle, void *, size_t);
176 1.182.12.2 itohy Static usbd_status ohci_mapm_mbuf(usbd_xfer_handle, struct mbuf *);
177 1.182.12.1 itohy Static void ohci_unmapm(usbd_xfer_handle);
178 1.91 augustss
179 1.182.12.1 itohy Static usbd_xfer_handle ohci_allocx(struct usbd_bus *, usbd_pipe_handle,
180 1.182.12.1 itohy enum usbd_waitflg);
181 1.91 augustss Static void ohci_freex(struct usbd_bus *, usbd_xfer_handle);
182 1.91 augustss
183 1.182.12.3 itohy Static void ohci_transfer_complete(usbd_xfer_handle, int);
184 1.182.12.3 itohy
185 1.91 augustss Static usbd_status ohci_root_ctrl_transfer(usbd_xfer_handle);
186 1.91 augustss Static usbd_status ohci_root_ctrl_start(usbd_xfer_handle);
187 1.91 augustss Static void ohci_root_ctrl_abort(usbd_xfer_handle);
188 1.91 augustss Static void ohci_root_ctrl_close(usbd_pipe_handle);
189 1.91 augustss Static void ohci_root_ctrl_done(usbd_xfer_handle);
190 1.91 augustss
191 1.91 augustss Static usbd_status ohci_root_intr_transfer(usbd_xfer_handle);
192 1.91 augustss Static usbd_status ohci_root_intr_start(usbd_xfer_handle);
193 1.91 augustss Static void ohci_root_intr_abort(usbd_xfer_handle);
194 1.91 augustss Static void ohci_root_intr_close(usbd_pipe_handle);
195 1.91 augustss Static void ohci_root_intr_done(usbd_xfer_handle);
196 1.91 augustss
197 1.91 augustss Static usbd_status ohci_device_ctrl_transfer(usbd_xfer_handle);
198 1.91 augustss Static usbd_status ohci_device_ctrl_start(usbd_xfer_handle);
199 1.91 augustss Static void ohci_device_ctrl_abort(usbd_xfer_handle);
200 1.91 augustss Static void ohci_device_ctrl_close(usbd_pipe_handle);
201 1.91 augustss Static void ohci_device_ctrl_done(usbd_xfer_handle);
202 1.91 augustss
203 1.91 augustss Static usbd_status ohci_device_bulk_transfer(usbd_xfer_handle);
204 1.91 augustss Static usbd_status ohci_device_bulk_start(usbd_xfer_handle);
205 1.91 augustss Static void ohci_device_bulk_abort(usbd_xfer_handle);
206 1.91 augustss Static void ohci_device_bulk_close(usbd_pipe_handle);
207 1.91 augustss Static void ohci_device_bulk_done(usbd_xfer_handle);
208 1.91 augustss
209 1.91 augustss Static usbd_status ohci_device_intr_transfer(usbd_xfer_handle);
210 1.91 augustss Static usbd_status ohci_device_intr_start(usbd_xfer_handle);
211 1.91 augustss Static void ohci_device_intr_abort(usbd_xfer_handle);
212 1.91 augustss Static void ohci_device_intr_close(usbd_pipe_handle);
213 1.91 augustss Static void ohci_device_intr_done(usbd_xfer_handle);
214 1.91 augustss
215 1.91 augustss Static usbd_status ohci_device_isoc_transfer(usbd_xfer_handle);
216 1.91 augustss Static usbd_status ohci_device_isoc_start(usbd_xfer_handle);
217 1.91 augustss Static void ohci_device_isoc_abort(usbd_xfer_handle);
218 1.91 augustss Static void ohci_device_isoc_close(usbd_pipe_handle);
219 1.91 augustss Static void ohci_device_isoc_done(usbd_xfer_handle);
220 1.91 augustss
221 1.120 augustss Static usbd_status ohci_device_setintr(ohci_softc_t *sc,
222 1.91 augustss struct ohci_pipe *pipe, int ival);
223 1.182.12.1 itohy Static usbd_status ohci_device_intr_insert(ohci_softc_t *sc,
224 1.182.12.1 itohy usbd_xfer_handle xfer);
225 1.91 augustss
226 1.120 augustss Static int ohci_str(usb_string_descriptor_t *, int, const char *);
227 1.91 augustss
228 1.91 augustss Static void ohci_timeout(void *);
229 1.114 augustss Static void ohci_timeout_task(void *);
230 1.104 augustss Static void ohci_rhsc_enable(void *);
231 1.91 augustss
232 1.91 augustss Static void ohci_close_pipe(usbd_pipe_handle, ohci_soft_ed_t *);
233 1.91 augustss Static void ohci_abort_xfer(usbd_xfer_handle, usbd_status);
234 1.53 augustss
235 1.91 augustss Static void ohci_device_clear_toggle(usbd_pipe_handle pipe);
236 1.91 augustss Static void ohci_noop(usbd_pipe_handle pipe);
237 1.37 augustss
238 1.182.12.1 itohy Static usbd_status ohci_controller_init(ohci_softc_t *sc);
239 1.182.12.1 itohy
240 1.182.12.3 itohy Static void ohci_aux_mem_init(struct ohci_aux_mem *);
241 1.182.12.3 itohy Static usbd_status ohci_aux_mem_alloc(ohci_softc_t *,
242 1.182.12.3 itohy struct ohci_aux_mem *,
243 1.182.12.3 itohy int /*naux*/, int /*maxp*/);
244 1.182.12.3 itohy Static void ohci_aux_mem_free(ohci_softc_t *,
245 1.182.12.3 itohy struct ohci_aux_mem *);
246 1.182.12.3 itohy Static bus_addr_t ohci_aux_dma_alloc(struct ohci_aux_mem *,
247 1.182.12.3 itohy const union usb_bufptr *, int,
248 1.182.12.3 itohy struct usb_aux_desc *);
249 1.182.12.3 itohy Static void ohci_aux_dma_complete(struct usb_aux_desc *,
250 1.182.12.3 itohy struct ohci_aux_mem *,
251 1.182.12.3 itohy int /*is_mbuf*/, int /*isread*/);
252 1.182.12.3 itohy Static void ohci_aux_dma_sync(ohci_softc_t *,
253 1.182.12.3 itohy struct ohci_aux_mem *, int /*op*/);
254 1.182.12.3 itohy
255 1.182.12.1 itohy #ifdef USB_DEBUG
256 1.91 augustss Static void ohci_dumpregs(ohci_softc_t *);
257 1.168 augustss Static void ohci_dump_tds(ohci_softc_t *, ohci_soft_td_t *);
258 1.168 augustss Static void ohci_dump_td(ohci_softc_t *, ohci_soft_td_t *);
259 1.168 augustss Static void ohci_dump_ed(ohci_softc_t *, ohci_soft_ed_t *);
260 1.168 augustss Static void ohci_dump_itd(ohci_softc_t *, ohci_soft_itd_t *);
261 1.168 augustss Static void ohci_dump_itds(ohci_softc_t *, ohci_soft_itd_t *);
262 1.1 augustss #endif
263 1.1 augustss
264 1.88 augustss #define OBARR(sc) bus_space_barrier((sc)->iot, (sc)->ioh, 0, (sc)->sc_size, \
265 1.88 augustss BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE)
266 1.88 augustss #define OWRITE1(sc, r, x) \
267 1.88 augustss do { OBARR(sc); bus_space_write_1((sc)->iot, (sc)->ioh, (r), (x)); } while (0)
268 1.88 augustss #define OWRITE2(sc, r, x) \
269 1.88 augustss do { OBARR(sc); bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)); } while (0)
270 1.88 augustss #define OWRITE4(sc, r, x) \
271 1.88 augustss do { OBARR(sc); bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)); } while (0)
272 1.174 mrg static __inline uint8_t
273 1.174 mrg OREAD1(ohci_softc_t *sc, bus_size_t r)
274 1.174 mrg {
275 1.174 mrg
276 1.174 mrg OBARR(sc);
277 1.174 mrg return bus_space_read_1(sc->iot, sc->ioh, r);
278 1.174 mrg }
279 1.174 mrg
280 1.174 mrg static __inline uint16_t
281 1.174 mrg OREAD2(ohci_softc_t *sc, bus_size_t r)
282 1.174 mrg {
283 1.174 mrg
284 1.174 mrg OBARR(sc);
285 1.174 mrg return bus_space_read_2(sc->iot, sc->ioh, r);
286 1.174 mrg }
287 1.174 mrg
288 1.174 mrg static __inline uint32_t
289 1.174 mrg OREAD4(ohci_softc_t *sc, bus_size_t r)
290 1.174 mrg {
291 1.174 mrg
292 1.174 mrg OBARR(sc);
293 1.174 mrg return bus_space_read_4(sc->iot, sc->ioh, r);
294 1.174 mrg }
295 1.1 augustss
296 1.1 augustss /* Reverse the bits in a value 0 .. 31 */
297 1.120 augustss Static u_int8_t revbits[OHCI_NO_INTRS] =
298 1.1 augustss { 0x00, 0x10, 0x08, 0x18, 0x04, 0x14, 0x0c, 0x1c,
299 1.1 augustss 0x02, 0x12, 0x0a, 0x1a, 0x06, 0x16, 0x0e, 0x1e,
300 1.1 augustss 0x01, 0x11, 0x09, 0x19, 0x05, 0x15, 0x0d, 0x1d,
301 1.1 augustss 0x03, 0x13, 0x0b, 0x1b, 0x07, 0x17, 0x0f, 0x1f };
302 1.1 augustss
303 1.1 augustss struct ohci_pipe {
304 1.1 augustss struct usbd_pipe pipe;
305 1.1 augustss ohci_soft_ed_t *sed;
306 1.182.12.1 itohy u_int32_t aborting;
307 1.60 augustss union {
308 1.60 augustss ohci_soft_td_t *td;
309 1.60 augustss ohci_soft_itd_t *itd;
310 1.60 augustss } tail;
311 1.1 augustss /* Info needed for different pipe kinds. */
312 1.1 augustss union {
313 1.1 augustss /* Control pipe */
314 1.1 augustss struct {
315 1.4 augustss usb_dma_t reqdma;
316 1.1 augustss u_int length;
317 1.48 augustss ohci_soft_td_t *setup, *data, *stat;
318 1.1 augustss } ctl;
319 1.1 augustss /* Interrupt pipe */
320 1.1 augustss struct {
321 1.1 augustss int nslots;
322 1.1 augustss int pos;
323 1.1 augustss } intr;
324 1.3 augustss /* Bulk pipe */
325 1.3 augustss struct {
326 1.3 augustss u_int length;
327 1.32 augustss int isread;
328 1.3 augustss } bulk;
329 1.43 augustss /* Iso pipe */
330 1.43 augustss struct iso {
331 1.60 augustss int next, inuse;
332 1.43 augustss } iso;
333 1.1 augustss } u;
334 1.1 augustss };
335 1.1 augustss
336 1.1 augustss #define OHCI_INTR_ENDPT 1
337 1.1 augustss
338 1.182 drochner Static const struct usbd_bus_methods ohci_bus_methods = {
339 1.42 augustss ohci_open,
340 1.73 augustss ohci_softintr,
341 1.42 augustss ohci_poll,
342 1.42 augustss ohci_allocm,
343 1.42 augustss ohci_freem,
344 1.182.12.1 itohy ohci_map_alloc,
345 1.182.12.1 itohy ohci_map_free,
346 1.182.12.1 itohy ohci_mapm,
347 1.182.12.1 itohy ohci_mapm_mbuf,
348 1.182.12.1 itohy ohci_unmapm,
349 1.62 augustss ohci_allocx,
350 1.62 augustss ohci_freex,
351 1.42 augustss };
352 1.42 augustss
353 1.182 drochner Static const struct usbd_pipe_methods ohci_root_ctrl_methods = {
354 1.1 augustss ohci_root_ctrl_transfer,
355 1.17 augustss ohci_root_ctrl_start,
356 1.1 augustss ohci_root_ctrl_abort,
357 1.1 augustss ohci_root_ctrl_close,
358 1.37 augustss ohci_noop,
359 1.65 augustss ohci_root_ctrl_done,
360 1.1 augustss };
361 1.1 augustss
362 1.182 drochner Static const struct usbd_pipe_methods ohci_root_intr_methods = {
363 1.1 augustss ohci_root_intr_transfer,
364 1.17 augustss ohci_root_intr_start,
365 1.1 augustss ohci_root_intr_abort,
366 1.1 augustss ohci_root_intr_close,
367 1.37 augustss ohci_noop,
368 1.38 augustss ohci_root_intr_done,
369 1.1 augustss };
370 1.1 augustss
371 1.182 drochner Static const struct usbd_pipe_methods ohci_device_ctrl_methods = {
372 1.1 augustss ohci_device_ctrl_transfer,
373 1.17 augustss ohci_device_ctrl_start,
374 1.1 augustss ohci_device_ctrl_abort,
375 1.1 augustss ohci_device_ctrl_close,
376 1.37 augustss ohci_noop,
377 1.38 augustss ohci_device_ctrl_done,
378 1.1 augustss };
379 1.1 augustss
380 1.182 drochner Static const struct usbd_pipe_methods ohci_device_intr_methods = {
381 1.1 augustss ohci_device_intr_transfer,
382 1.17 augustss ohci_device_intr_start,
383 1.1 augustss ohci_device_intr_abort,
384 1.1 augustss ohci_device_intr_close,
385 1.37 augustss ohci_device_clear_toggle,
386 1.38 augustss ohci_device_intr_done,
387 1.1 augustss };
388 1.1 augustss
389 1.182 drochner Static const struct usbd_pipe_methods ohci_device_bulk_methods = {
390 1.3 augustss ohci_device_bulk_transfer,
391 1.17 augustss ohci_device_bulk_start,
392 1.3 augustss ohci_device_bulk_abort,
393 1.3 augustss ohci_device_bulk_close,
394 1.37 augustss ohci_device_clear_toggle,
395 1.38 augustss ohci_device_bulk_done,
396 1.3 augustss };
397 1.3 augustss
398 1.182 drochner Static const struct usbd_pipe_methods ohci_device_isoc_methods = {
399 1.43 augustss ohci_device_isoc_transfer,
400 1.43 augustss ohci_device_isoc_start,
401 1.43 augustss ohci_device_isoc_abort,
402 1.43 augustss ohci_device_isoc_close,
403 1.43 augustss ohci_noop,
404 1.43 augustss ohci_device_isoc_done,
405 1.43 augustss };
406 1.43 augustss
407 1.55 augustss #if defined(__NetBSD__) || defined(__OpenBSD__)
408 1.47 augustss int
409 1.182.12.1 itohy ohci_activate(device_t self, enum devact act)
410 1.47 augustss {
411 1.49 augustss struct ohci_softc *sc = (struct ohci_softc *)self;
412 1.47 augustss int rv = 0;
413 1.47 augustss
414 1.47 augustss switch (act) {
415 1.47 augustss case DVACT_ACTIVATE:
416 1.47 augustss return (EOPNOTSUPP);
417 1.47 augustss
418 1.47 augustss case DVACT_DEACTIVATE:
419 1.49 augustss if (sc->sc_child != NULL)
420 1.49 augustss rv = config_deactivate(sc->sc_child);
421 1.83 augustss sc->sc_dying = 1;
422 1.47 augustss break;
423 1.47 augustss }
424 1.47 augustss return (rv);
425 1.47 augustss }
426 1.182.12.1 itohy #endif
427 1.47 augustss
428 1.47 augustss int
429 1.91 augustss ohci_detach(struct ohci_softc *sc, int flags)
430 1.47 augustss {
431 1.47 augustss int rv = 0;
432 1.182.12.1 itohy usbd_xfer_handle xfer;
433 1.47 augustss
434 1.182.12.1 itohy sc->sc_dying = 1;
435 1.182.12.1 itohy
436 1.182.12.1 itohy #if defined(__NetBSD__) || defined(__OpenBSD__)
437 1.47 augustss if (sc->sc_child != NULL)
438 1.47 augustss rv = config_detach(sc->sc_child, flags);
439 1.120 augustss
440 1.47 augustss if (rv != 0)
441 1.47 augustss return (rv);
442 1.182.12.1 itohy #endif
443 1.182.12.1 itohy
444 1.182.12.1 itohy if (sc->sc_bus.methods == NULL)
445 1.182.12.1 itohy return (rv); /* attach has been aborted */
446 1.47 augustss
447 1.104 augustss usb_uncallout(sc->sc_tmo_rhsc, ohci_rhsc_enable, sc);
448 1.104 augustss
449 1.71 augustss #if defined(__NetBSD__) || defined(__OpenBSD__)
450 1.47 augustss powerhook_disestablish(sc->sc_powerhook);
451 1.59 augustss shutdownhook_disestablish(sc->sc_shutdownhook);
452 1.71 augustss #endif
453 1.59 augustss
454 1.182.12.1 itohy #if defined(__NetBSD__) || defined(__OpenBSD__)
455 1.182.12.1 itohy /* Don't touch hardware if it has already been gone. */
456 1.182.12.1 itohy if ((flags & DETACH_FORCE) == 0)
457 1.182.12.1 itohy #endif
458 1.182.12.1 itohy {
459 1.182.12.1 itohy OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
460 1.182.12.1 itohy OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
461 1.182.12.1 itohy }
462 1.182.12.1 itohy
463 1.116 augustss usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */
464 1.116 augustss
465 1.182.12.1 itohy #if 0 /* freed by ohci_free_desc_chunks(sc, &sc->sc_sed_chunks) below */
466 1.182.12.1 itohy for (i = 0; i < OHCI_NO_EDS; i++)
467 1.182.12.1 itohy ohci_free_sed(sc, sc->sc_eds[i]);
468 1.182.12.1 itohy ohci_free_sed(sc, sc->sc_isoc_head);
469 1.182.12.1 itohy ohci_free_sed(sc, sc->sc_bulk_head);
470 1.182.12.1 itohy ohci_free_sed(sc, sc->sc_ctrl_head);
471 1.182.12.1 itohy #endif
472 1.182.12.1 itohy usb_freemem(&sc->sc_dmatag, &sc->sc_hccadma);
473 1.182.12.1 itohy
474 1.182.12.1 itohy while ((xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers)) != NULL) {
475 1.182.12.1 itohy SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
476 1.182.12.1 itohy usb_clean_buffer_dma(&sc->sc_dmatag, &OXFER(xfer)->dmabuf);
477 1.182.12.1 itohy free(xfer, M_USB);
478 1.182.12.1 itohy }
479 1.182.12.1 itohy ohci_free_desc_chunks(sc, &sc->sc_sed_chunks);
480 1.182.12.1 itohy ohci_free_desc_chunks(sc, &sc->sc_std_chunks);
481 1.182.12.1 itohy ohci_free_desc_chunks(sc, &sc->sc_sitd_chunks);
482 1.182.12.1 itohy usb_dma_tag_finish(&sc->sc_dmatag);
483 1.47 augustss
484 1.47 augustss return (rv);
485 1.47 augustss }
486 1.182.12.1 itohy
487 1.182.12.1 itohy Static void
488 1.182.12.1 itohy ohci_free_desc_chunks(ohci_softc_t *sc, struct ohci_mdescs *c)
489 1.182.12.1 itohy {
490 1.182.12.1 itohy struct ohci_mem_desc *om;
491 1.182.12.1 itohy
492 1.182.12.1 itohy while ((om = SIMPLEQ_FIRST(c)) != NULL) {
493 1.182.12.1 itohy SIMPLEQ_REMOVE_HEAD(c, om_next);
494 1.182.12.1 itohy usb_freemem(&sc->sc_dmatag, &om->om_dma);
495 1.182.12.1 itohy }
496 1.182.12.1 itohy }
497 1.47 augustss
498 1.1 augustss ohci_soft_ed_t *
499 1.91 augustss ohci_alloc_sed(ohci_softc_t *sc)
500 1.1 augustss {
501 1.1 augustss ohci_soft_ed_t *sed;
502 1.53 augustss usbd_status err;
503 1.1 augustss int i, offs;
504 1.4 augustss usb_dma_t dma;
505 1.182.12.1 itohy struct ohci_mem_desc *om;
506 1.1 augustss
507 1.53 augustss if (sc->sc_freeeds == NULL) {
508 1.1 augustss DPRINTFN(2, ("ohci_alloc_sed: allocating chunk\n"));
509 1.182.12.1 itohy err = usb_allocmem(&sc->sc_dmatag,
510 1.182.12.1 itohy OHCI_SED_SIZE*OHCI_SED_CHUNK + sizeof(struct ohci_mem_desc),
511 1.182.12.1 itohy OHCI_ED_ALIGN, &dma);
512 1.53 augustss if (err)
513 1.182.12.1 itohy return (NULL);
514 1.182.12.1 itohy om = KERNADDR(&dma, OHCI_SED_SIZE * OHCI_SED_CHUNK);
515 1.182.12.1 itohy om->om_top = KERNADDR(&dma, 0);
516 1.182.12.1 itohy om->om_topdma = DMAADDR(&dma, 0);
517 1.182.12.1 itohy om->om_dma = dma;
518 1.182.12.1 itohy SIMPLEQ_INSERT_HEAD(&sc->sc_sed_chunks, om, om_next);
519 1.39 augustss for(i = 0; i < OHCI_SED_CHUNK; i++) {
520 1.39 augustss offs = i * OHCI_SED_SIZE;
521 1.123 augustss sed = KERNADDR(&dma, offs);
522 1.182.12.1 itohy sed->oe_mdesc = om;
523 1.1 augustss sed->next = sc->sc_freeeds;
524 1.1 augustss sc->sc_freeeds = sed;
525 1.1 augustss }
526 1.1 augustss }
527 1.1 augustss sed = sc->sc_freeeds;
528 1.1 augustss sc->sc_freeeds = sed->next;
529 1.39 augustss memset(&sed->ed, 0, sizeof(ohci_ed_t));
530 1.1 augustss sed->next = 0;
531 1.39 augustss return (sed);
532 1.1 augustss }
533 1.1 augustss
534 1.1 augustss void
535 1.91 augustss ohci_free_sed(ohci_softc_t *sc, ohci_soft_ed_t *sed)
536 1.1 augustss {
537 1.1 augustss sed->next = sc->sc_freeeds;
538 1.1 augustss sc->sc_freeeds = sed;
539 1.1 augustss }
540 1.1 augustss
541 1.182.12.1 itohy Static usbd_status
542 1.182.12.1 itohy ohci_grow_std(ohci_softc_t *sc)
543 1.1 augustss {
544 1.182.12.1 itohy usb_dma_t dma;
545 1.182.12.1 itohy struct ohci_mem_desc *om;
546 1.1 augustss ohci_soft_td_t *std;
547 1.53 augustss usbd_status err;
548 1.182.12.1 itohy int i, s, offs;
549 1.1 augustss
550 1.182.12.1 itohy DPRINTFN(2, ("ohci_grow_std: allocating chunk\n"));
551 1.182.12.1 itohy err = usb_allocmem(&sc->sc_dmatag,
552 1.182.12.1 itohy OHCI_STD_SIZE*OHCI_STD_CHUNK + sizeof(struct ohci_mem_desc),
553 1.182.12.1 itohy OHCI_TD_ALIGN, &dma);
554 1.182.12.1 itohy if (err)
555 1.182.12.1 itohy return (err);
556 1.182.12.1 itohy om = KERNADDR(&dma, OHCI_STD_SIZE * OHCI_STD_CHUNK);
557 1.182.12.1 itohy om->om_top = KERNADDR(&dma, 0);
558 1.182.12.1 itohy om->om_topdma = DMAADDR(&dma, 0);
559 1.182.12.1 itohy om->om_dma = dma;
560 1.182.12.1 itohy s = splusb();
561 1.182.12.1 itohy SIMPLEQ_INSERT_HEAD(&sc->sc_std_chunks, om, om_next);
562 1.182.12.1 itohy for(i = 0; i < OHCI_STD_CHUNK; i++) {
563 1.182.12.1 itohy offs = i * OHCI_STD_SIZE;
564 1.182.12.1 itohy std = KERNADDR(&dma, offs);
565 1.182.12.1 itohy std->ot_mdesc = om;
566 1.182.12.1 itohy std->nexttd = sc->sc_freetds;
567 1.182.12.3 itohy std->ad.aux_len = 0;
568 1.182.12.1 itohy sc->sc_freetds = std;
569 1.182.12.1 itohy sc->sc_nfreetds++;
570 1.1 augustss }
571 1.182.12.1 itohy splx(s);
572 1.182.12.1 itohy
573 1.182.12.1 itohy return (USBD_NORMAL_COMPLETION);
574 1.182.12.1 itohy }
575 1.182.12.1 itohy
576 1.182.12.1 itohy ohci_soft_td_t *
577 1.182.12.1 itohy ohci_alloc_std(ohci_softc_t *sc)
578 1.182.12.1 itohy {
579 1.182.12.1 itohy ohci_soft_td_t *std;
580 1.182.12.1 itohy int s;
581 1.69 augustss
582 1.69 augustss s = splusb();
583 1.182.12.1 itohy
584 1.182.12.1 itohy #ifdef DIAGNOSTIC
585 1.182.12.1 itohy if (sc->sc_freetds == NULL)
586 1.182.12.1 itohy panic("ohci_alloc_std: %d", sc->sc_nfreetds);
587 1.182.12.1 itohy #endif
588 1.1 augustss std = sc->sc_freetds;
589 1.1 augustss sc->sc_freetds = std->nexttd;
590 1.182.12.1 itohy splx(s);
591 1.39 augustss memset(&std->td, 0, sizeof(ohci_td_t));
592 1.83 augustss std->nexttd = NULL;
593 1.83 augustss std->xfer = NULL;
594 1.182.12.1 itohy std->flags = 0;
595 1.69 augustss
596 1.1 augustss return (std);
597 1.1 augustss }
598 1.1 augustss
599 1.182.12.1 itohy Static ohci_soft_td_t *
600 1.182.12.1 itohy ohci_alloc_std_norsv(ohci_softc_t *sc)
601 1.182.12.1 itohy {
602 1.182.12.1 itohy int s;
603 1.182.12.1 itohy
604 1.182.12.1 itohy s = splusb();
605 1.182.12.1 itohy if (sc->sc_nfreetds < 1)
606 1.182.12.1 itohy if (ohci_grow_std(sc))
607 1.182.12.1 itohy return (NULL);
608 1.182.12.1 itohy sc->sc_nfreetds--;
609 1.182.12.1 itohy splx(s);
610 1.182.12.1 itohy return (ohci_alloc_std(sc));
611 1.182.12.1 itohy }
612 1.182.12.1 itohy
613 1.1 augustss void
614 1.91 augustss ohci_free_std(ohci_softc_t *sc, ohci_soft_td_t *std)
615 1.1 augustss {
616 1.69 augustss int s;
617 1.69 augustss
618 1.69 augustss s = splusb();
619 1.182.12.1 itohy std->flags = OHCI_TD_FREE;
620 1.1 augustss std->nexttd = sc->sc_freetds;
621 1.1 augustss sc->sc_freetds = std;
622 1.69 augustss splx(s);
623 1.1 augustss }
624 1.1 augustss
625 1.182.12.1 itohy Static void
626 1.182.12.1 itohy ohci_free_std_norsv(ohci_softc_t *sc, ohci_soft_td_t *std)
627 1.182.12.1 itohy {
628 1.182.12.1 itohy int s;
629 1.182.12.1 itohy
630 1.182.12.1 itohy ohci_free_std(sc, std);
631 1.182.12.1 itohy s = splusb();
632 1.182.12.1 itohy sc->sc_nfreetds++;
633 1.182.12.1 itohy splx(s);
634 1.182.12.1 itohy }
635 1.182.12.1 itohy
636 1.1 augustss usbd_status
637 1.91 augustss ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc,
638 1.91 augustss int alen, int rd, usbd_xfer_handle xfer,
639 1.91 augustss ohci_soft_td_t *sp, ohci_soft_td_t **ep)
640 1.48 augustss {
641 1.182.12.1 itohy ohci_soft_td_t *next, *cur, *end;
642 1.182.12.1 itohy ohci_physaddr_t tddma, segdmaadr, dmaend;
643 1.77 augustss u_int32_t tdflags;
644 1.182.12.3 itohy int len, maxp, curlen, seg, seglen, seglen1;
645 1.182.12.1 itohy struct usb_buffer_dma *ub = &OXFER(xfer)->dmabuf;
646 1.182.12.1 itohy bus_dma_segment_t *segs = USB_BUFFER_SEGS(ub);
647 1.182.12.1 itohy int nsegs = USB_BUFFER_NSEGS(ub);
648 1.77 augustss u_int16_t flags = xfer->flags;
649 1.182.12.3 itohy usb_endpoint_descriptor_t *ed;
650 1.182.12.3 itohy #if 1
651 1.182.12.3 itohy int needaux;
652 1.182.12.3 itohy union usb_bufptr bufptr;
653 1.182.12.3 itohy bus_addr_t auxdma;
654 1.182.12.3 itohy #endif
655 1.48 augustss
656 1.75 augustss DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen));
657 1.75 augustss
658 1.75 augustss len = alen;
659 1.48 augustss cur = sp;
660 1.182.12.1 itohy end = NULL;
661 1.182.12.1 itohy
662 1.182.12.3 itohy ed = opipe->pipe.endpoint->edesc;
663 1.182.12.3 itohy maxp = UE_MAXPKTSZ(ed);
664 1.168 augustss tdflags = HTOO32(
665 1.120 augustss (rd ? OHCI_TD_IN : OHCI_TD_OUT) |
666 1.77 augustss (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) |
667 1.182.12.1 itohy OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_SET_DI(6));
668 1.182.12.3 itohy #if 1
669 1.182.12.3 itohy /*
670 1.182.12.3 itohy * aux memory is possibly required if
671 1.182.12.3 itohy * buffer has more than one segments,
672 1.182.12.3 itohy * the transfer direction is OUT,
673 1.182.12.3 itohy * and
674 1.182.12.3 itohy * buffer is an mbuf chain, or
675 1.182.12.3 itohy * buffer is not maxp aligned
676 1.182.12.3 itohy */
677 1.182.12.3 itohy needaux =
678 1.182.12.3 itohy nsegs > 1 &&
679 1.182.12.3 itohy UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
680 1.182.12.3 itohy ((xfer->rqflags & URQ_DEV_MAP_MBUF) ||
681 1.182.12.3 itohy (maxp & (maxp - 1)) != 0 /* maxp is not a power of 2 */ ||
682 1.182.12.3 itohy (segs[0].ds_addr & (maxp - 1)) != 0 /* buffer is unaligned */);
683 1.182.12.3 itohy
684 1.182.12.3 itohy if (needaux) {
685 1.182.12.3 itohy usb_bufptr_init(&bufptr, xfer);
686 1.182.12.3 itohy }
687 1.182.12.3 itohy #endif
688 1.182.12.1 itohy
689 1.182.12.1 itohy seg = 0;
690 1.182.12.1 itohy seglen = 0;
691 1.182.12.3 itohy segdmaadr = 0; /* XXX -Wuninitialized */
692 1.182.12.1 itohy while (len > 0) {
693 1.182.12.1 itohy /* sync last entry */
694 1.182.12.1 itohy if (end)
695 1.182.12.1 itohy OHCI_STD_SYNC(sc, end,
696 1.182.12.1 itohy BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
697 1.61 augustss
698 1.48 augustss next = ohci_alloc_std(sc);
699 1.75 augustss if (next == NULL)
700 1.61 augustss goto nomem;
701 1.48 augustss
702 1.182.12.1 itohy /*
703 1.182.12.1 itohy * The OHCI hardware can handle at most one 4K crossing.
704 1.182.12.1 itohy * The OHCI spec says: If during the data transfer the buffer
705 1.182.12.1 itohy * address contained in the HC's working copy of
706 1.182.12.1 itohy * CurrentBufferPointer crosses a 4K boundary, the upper 20
707 1.182.12.1 itohy * bits of Buffer End are copied to the working value of
708 1.182.12.1 itohy * CurrentBufferPointer causing the next buffer address to
709 1.182.12.1 itohy * be the 0th byte in the same 4K page that contains the
710 1.182.12.1 itohy * last byte of the buffer (the 4K boundary crossing may
711 1.182.12.1 itohy * occur within a data packet transfer.)
712 1.182.12.1 itohy */
713 1.182.12.1 itohy
714 1.182.12.3 itohy /*
715 1.182.12.3 itohy * 1. skip handled segments
716 1.182.12.3 itohy * 2. gather segments that are continuous in DMA address
717 1.182.12.3 itohy * (Does this make any sense?)
718 1.182.12.3 itohy */
719 1.182.12.3 itohy if (seglen <= 0) {
720 1.182.12.1 itohy USB_KASSERT2(seg < nsegs,
721 1.182.12.1 itohy ("ohci_alloc_std_chain: overrun"));
722 1.182.12.1 itohy do {
723 1.182.12.3 itohy seglen1 = seglen;
724 1.182.12.1 itohy seglen += segs[seg].ds_len;
725 1.182.12.3 itohy if (seglen1 <= 0 && seglen > 0)
726 1.182.12.3 itohy segdmaadr = segs[seg].ds_addr - seglen1;
727 1.182.12.3 itohy } while (++seg < nsegs && (seglen <= 0 ||
728 1.182.12.3 itohy segdmaadr + seglen == segs[seg].ds_addr));
729 1.182.12.1 itohy
730 1.182.12.1 itohy if (seglen > len)
731 1.182.12.1 itohy seglen = len;
732 1.182.12.1 itohy }
733 1.182.12.1 itohy
734 1.182.12.3 itohy #if 1
735 1.182.12.3 itohy if (needaux && seglen < len && seglen < maxp) {
736 1.182.12.3 itohy /* need aux -- a packet is not contiguous */
737 1.182.12.3 itohy curlen = len < maxp ? len : maxp;
738 1.182.12.3 itohy USB_KASSERT(seglen < curlen);
739 1.182.12.3 itohy auxdma = ohci_aux_dma_alloc(&OXFER(xfer)->aux, &bufptr,
740 1.182.12.3 itohy curlen, &cur->ad);
741 1.182.12.3 itohy
742 1.182.12.3 itohy /* prepare aux DMA */
743 1.182.12.3 itohy usb_bufptr_wr(&bufptr, cur->ad.aux_kern,
744 1.182.12.3 itohy curlen, xfer->rqflags & URQ_DEV_MAP_MBUF);
745 1.182.12.3 itohy cur->td.td_cbp = HTOO32(auxdma);
746 1.182.12.3 itohy cur->td.td_be = HTOO32(auxdma + curlen - 1);
747 1.182.12.3 itohy
748 1.182.12.3 itohy /* handled segments will be skipped above */
749 1.182.12.3 itohy } else {
750 1.182.12.3 itohy #ifdef DIAGNOSTIC
751 1.182.12.3 itohy if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)
752 1.182.12.3 itohy USB_KASSERT(seglen >= maxp || seglen >= len);
753 1.182.12.3 itohy #endif
754 1.182.12.3 itohy #endif
755 1.182.12.1 itohy curlen = seglen;
756 1.182.12.1 itohy dmaend = segdmaadr + curlen;
757 1.182.12.1 itohy if ((sc->sc_flags & OHCI_FLAG_QUIRK_2ND_4KB) == 0)
758 1.182.12.1 itohy dmaend--;
759 1.182.12.1 itohy dmaend = OHCI_PAGE(dmaend);
760 1.182.12.1 itohy
761 1.182.12.1 itohy if (OHCI_PAGE(segdmaadr) != dmaend &&
762 1.182.12.1 itohy OHCI_PAGE(segdmaadr) + OHCI_PAGE_SIZE != dmaend) {
763 1.48 augustss /* must use multiple TDs, fill as much as possible. */
764 1.120 augustss curlen = 2 * OHCI_PAGE_SIZE -
765 1.182.12.1 itohy (segdmaadr & (OHCI_PAGE_SIZE-1));
766 1.182.12.1 itohy
767 1.182.12.1 itohy if (sc->sc_flags & OHCI_FLAG_QUIRK_2ND_4KB)
768 1.182.12.1 itohy curlen--;
769 1.182.12.1 itohy }
770 1.182.12.3 itohy
771 1.182.12.3 itohy /* the length must be a multiple of the max size */
772 1.182.12.3 itohy if (curlen < len)
773 1.182.12.3 itohy curlen -= curlen % maxp;
774 1.182.12.3 itohy USB_KASSERT(curlen);
775 1.182.12.3 itohy USB_KASSERT2(curlen <= seglen,
776 1.182.12.3 itohy ("ohci_alloc_std_chain: curlen %d > seglen %d",
777 1.182.12.3 itohy curlen, len));
778 1.182.12.3 itohy
779 1.182.12.1 itohy DPRINTFN(4,("ohci_alloc_std_chain: segdmaadr=0x%08x "
780 1.182.12.1 itohy "dmaend=0x%08x len=%d seglen=%d curlen=%d\n",
781 1.182.12.3 itohy segdmaadr, segdmaadr + curlen - 1,
782 1.182.12.1 itohy len, seglen, curlen));
783 1.182.12.3 itohy cur->td.td_cbp = HTOO32(segdmaadr);
784 1.182.12.3 itohy cur->td.td_be = HTOO32(segdmaadr + curlen - 1);
785 1.182.12.3 itohy }
786 1.48 augustss len -= curlen;
787 1.48 augustss
788 1.77 augustss cur->td.td_flags = tdflags;
789 1.48 augustss cur->nexttd = next;
790 1.182.12.1 itohy tddma = OHCI_STD_DMAADDR(next);
791 1.182.12.1 itohy cur->td.td_nexttd = HTOO32(tddma);
792 1.48 augustss cur->len = curlen;
793 1.48 augustss cur->flags = OHCI_ADD_LEN;
794 1.77 augustss cur->xfer = xfer;
795 1.182.12.3 itohy DPRINTFN(10,("ohci_alloc_std_chain: cbp=0x%08x be=0x%08x",
796 1.182.12.3 itohy O32TOH(cur->td.td_cbp), O32TOH(cur->td.td_be)));
797 1.182.12.1 itohy seglen -= curlen;
798 1.182.12.1 itohy segdmaadr += curlen;
799 1.182.12.3 itohy DPRINTFN(10,("%s\n", seglen < 0 ? " (aux)" : ""));
800 1.182.12.3 itohy
801 1.182.12.3 itohy if (needaux)
802 1.182.12.3 itohy usb_bufptr_advance(&bufptr, curlen,
803 1.182.12.3 itohy xfer->rqflags & URQ_DEV_MAP_MBUF);
804 1.182.12.1 itohy
805 1.182.12.1 itohy end = cur;
806 1.48 augustss cur = next;
807 1.48 augustss }
808 1.182.12.1 itohy if (((flags & USBD_FORCE_SHORT_XFER) || alen == 0) &&
809 1.182.12.1 itohy alen % maxp == 0) {
810 1.182.12.1 itohy if (end)
811 1.182.12.1 itohy OHCI_STD_SYNC(sc, end,
812 1.182.12.1 itohy BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
813 1.75 augustss
814 1.182.12.1 itohy /* Force a 0 length transfer at the end. */
815 1.61 augustss next = ohci_alloc_std(sc);
816 1.75 augustss if (next == NULL)
817 1.61 augustss goto nomem;
818 1.61 augustss
819 1.77 augustss cur->td.td_flags = tdflags;
820 1.61 augustss cur->td.td_cbp = 0; /* indicate 0 length packet */
821 1.61 augustss cur->nexttd = next;
822 1.182.12.1 itohy tddma = OHCI_STD_DMAADDR(next);
823 1.182.12.1 itohy cur->td.td_nexttd = HTOO32(tddma);
824 1.75 augustss cur->td.td_be = ~0;
825 1.61 augustss cur->len = 0;
826 1.61 augustss cur->flags = 0;
827 1.77 augustss cur->xfer = xfer;
828 1.61 augustss DPRINTFN(2,("ohci_alloc_std_chain: add 0 xfer\n"));
829 1.182.12.1 itohy end = cur;
830 1.61 augustss }
831 1.182.12.1 itohy *ep = end;
832 1.48 augustss
833 1.182.12.3 itohy if (needaux)
834 1.182.12.3 itohy ohci_aux_dma_sync(sc, &OXFER(xfer)->aux, BUS_DMASYNC_PREWRITE);
835 1.182.12.3 itohy
836 1.48 augustss return (USBD_NORMAL_COMPLETION);
837 1.61 augustss
838 1.61 augustss nomem:
839 1.182.12.1 itohy /* free chain */
840 1.182.12.1 itohy if (end)
841 1.182.12.1 itohy ohci_free_std_chain(sc, sp->nexttd, end);
842 1.61 augustss return (USBD_NOMEM);
843 1.48 augustss }
844 1.48 augustss
845 1.82 augustss Static void
846 1.120 augustss ohci_free_std_chain(ohci_softc_t *sc, ohci_soft_td_t *std,
847 1.91 augustss ohci_soft_td_t *stdend)
848 1.48 augustss {
849 1.48 augustss ohci_soft_td_t *p;
850 1.48 augustss
851 1.48 augustss for (; std != stdend; std = p) {
852 1.48 augustss p = std->nexttd;
853 1.48 augustss ohci_free_std(sc, std);
854 1.48 augustss }
855 1.182.12.1 itohy ohci_free_std(sc, stdend);
856 1.48 augustss }
857 1.48 augustss
858 1.182.12.1 itohy Static usbd_status
859 1.182.12.1 itohy ohci_grow_sitd(ohci_softc_t *sc)
860 1.60 augustss {
861 1.182.12.1 itohy usb_dma_t dma;
862 1.182.12.1 itohy struct ohci_mem_desc *om;
863 1.60 augustss ohci_soft_itd_t *sitd;
864 1.60 augustss usbd_status err;
865 1.83 augustss int i, s, offs;
866 1.60 augustss
867 1.182.12.1 itohy DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n"));
868 1.182.12.1 itohy err = usb_allocmem(&sc->sc_dmatag,
869 1.182.12.1 itohy OHCI_SITD_SIZE*OHCI_SITD_CHUNK + sizeof(struct ohci_mem_desc),
870 1.182.12.1 itohy OHCI_ITD_ALIGN, &dma);
871 1.182.12.1 itohy if (err)
872 1.182.12.1 itohy return (err);
873 1.182.12.1 itohy om = KERNADDR(&dma, OHCI_SITD_SIZE * OHCI_SITD_CHUNK);
874 1.182.12.1 itohy om->om_top = KERNADDR(&dma, 0);
875 1.182.12.1 itohy om->om_topdma = DMAADDR(&dma, 0);
876 1.182.12.1 itohy om->om_dma = dma;
877 1.182.12.1 itohy s = splusb();
878 1.182.12.1 itohy SIMPLEQ_INSERT_HEAD(&sc->sc_sitd_chunks, om, om_next);
879 1.182.12.1 itohy for(i = 0; i < OHCI_SITD_CHUNK; i++) {
880 1.182.12.1 itohy offs = i * OHCI_SITD_SIZE;
881 1.182.12.1 itohy sitd = KERNADDR(&dma, offs);
882 1.182.12.1 itohy sitd->oit_mdesc = om;
883 1.182.12.1 itohy sitd->nextitd = sc->sc_freeitds;
884 1.182.12.3 itohy sitd->ad.aux_len = 0;
885 1.182.12.1 itohy sc->sc_freeitds = sitd;
886 1.182.12.1 itohy sc->sc_nfreeitds++;
887 1.60 augustss }
888 1.182.12.1 itohy splx(s);
889 1.182.12.1 itohy
890 1.182.12.1 itohy return (USBD_NORMAL_COMPLETION);
891 1.182.12.1 itohy }
892 1.182.12.1 itohy
893 1.182.12.1 itohy ohci_soft_itd_t *
894 1.182.12.1 itohy ohci_alloc_sitd(ohci_softc_t *sc)
895 1.182.12.1 itohy {
896 1.182.12.1 itohy ohci_soft_itd_t *sitd;
897 1.182.12.1 itohy int s;
898 1.182.12.1 itohy
899 1.182.12.1 itohy #ifdef DIAGNOSTIC
900 1.182.12.1 itohy if (sc->sc_freeitds == NULL)
901 1.182.12.1 itohy panic("ohci_alloc_sitd: %d", sc->sc_nfreeitds);
902 1.182.12.1 itohy #endif
903 1.83 augustss
904 1.83 augustss s = splusb();
905 1.60 augustss sitd = sc->sc_freeitds;
906 1.60 augustss sc->sc_freeitds = sitd->nextitd;
907 1.60 augustss memset(&sitd->itd, 0, sizeof(ohci_itd_t));
908 1.83 augustss sitd->nextitd = NULL;
909 1.83 augustss sitd->xfer = NULL;
910 1.182.12.1 itohy sitd->flags = 0;
911 1.83 augustss splx(s);
912 1.83 augustss
913 1.83 augustss #ifdef DIAGNOSTIC
914 1.83 augustss sitd->isdone = 0;
915 1.83 augustss #endif
916 1.83 augustss
917 1.60 augustss return (sitd);
918 1.60 augustss }
919 1.60 augustss
920 1.182.12.1 itohy Static ohci_soft_itd_t *
921 1.182.12.1 itohy ohci_alloc_sitd_norsv(ohci_softc_t *sc)
922 1.182.12.1 itohy {
923 1.182.12.1 itohy int s;
924 1.182.12.1 itohy
925 1.182.12.1 itohy s = splusb();
926 1.182.12.1 itohy if (sc->sc_nfreeitds < 1)
927 1.182.12.1 itohy if (ohci_grow_sitd(sc))
928 1.182.12.1 itohy return (NULL);
929 1.182.12.1 itohy sc->sc_nfreeitds--;
930 1.182.12.1 itohy splx(s);
931 1.182.12.3 itohy return (ohci_alloc_sitd(sc));
932 1.182.12.1 itohy }
933 1.182.12.1 itohy
934 1.60 augustss void
935 1.91 augustss ohci_free_sitd(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
936 1.60 augustss {
937 1.83 augustss int s;
938 1.83 augustss
939 1.83 augustss DPRINTFN(10,("ohci_free_sitd: sitd=%p\n", sitd));
940 1.83 augustss
941 1.83 augustss #ifdef DIAGNOSTIC
942 1.83 augustss if (!sitd->isdone) {
943 1.128 provos panic("ohci_free_sitd: sitd=%p not done", sitd);
944 1.83 augustss return;
945 1.83 augustss }
946 1.134 toshii /* Warn double free */
947 1.134 toshii sitd->isdone = 0;
948 1.83 augustss #endif
949 1.83 augustss
950 1.83 augustss s = splusb();
951 1.182.12.1 itohy sitd->flags = OHCI_ITD_FREE;
952 1.60 augustss sitd->nextitd = sc->sc_freeitds;
953 1.60 augustss sc->sc_freeitds = sitd;
954 1.83 augustss splx(s);
955 1.60 augustss }
956 1.60 augustss
957 1.182.12.1 itohy Static void
958 1.182.12.1 itohy ohci_free_sitd_norsv(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
959 1.182.12.1 itohy {
960 1.182.12.1 itohy int s;
961 1.182.12.1 itohy
962 1.182.12.1 itohy ohci_free_sitd(sc, sitd);
963 1.182.12.1 itohy s = splusb();
964 1.182.12.1 itohy sc->sc_nfreeitds++;
965 1.182.12.1 itohy splx(s);
966 1.182.12.1 itohy }
967 1.182.12.1 itohy
968 1.48 augustss usbd_status
969 1.91 augustss ohci_init(ohci_softc_t *sc)
970 1.1 augustss {
971 1.1 augustss ohci_soft_ed_t *sed, *psed;
972 1.182.12.1 itohy ohci_physaddr_t eddma;
973 1.53 augustss usbd_status err;
974 1.1 augustss int i;
975 1.182.12.1 itohy u_int32_t rev;
976 1.16 augustss
977 1.1 augustss DPRINTF(("ohci_init: start\n"));
978 1.36 augustss #if defined(__OpenBSD__)
979 1.55 augustss printf(",");
980 1.36 augustss #else
981 1.55 augustss printf("%s:", USBDEVNAME(sc->sc_bus.bdev));
982 1.36 augustss #endif
983 1.56 augustss rev = OREAD4(sc, OHCI_REVISION);
984 1.55 augustss printf(" OHCI version %d.%d%s\n", OHCI_REV_HI(rev), OHCI_REV_LO(rev),
985 1.1 augustss OHCI_REV_LEGACY(rev) ? ", legacy support" : "");
986 1.55 augustss
987 1.1 augustss if (OHCI_REV_HI(rev) != 1 || OHCI_REV_LO(rev) != 0) {
988 1.120 augustss printf("%s: unsupported OHCI revision\n",
989 1.15 augustss USBDEVNAME(sc->sc_bus.bdev));
990 1.56 augustss sc->sc_bus.usbrev = USBREV_UNKNOWN;
991 1.1 augustss return (USBD_INVAL);
992 1.1 augustss }
993 1.56 augustss sc->sc_bus.usbrev = USBREV_1_0;
994 1.1 augustss
995 1.62 augustss SIMPLEQ_INIT(&sc->sc_free_xfers);
996 1.182.12.1 itohy SIMPLEQ_INIT(&sc->sc_sed_chunks);
997 1.182.12.1 itohy SIMPLEQ_INIT(&sc->sc_std_chunks);
998 1.182.12.1 itohy SIMPLEQ_INIT(&sc->sc_sitd_chunks);
999 1.62 augustss
1000 1.182.12.1 itohy usb_dma_tag_init(&sc->sc_dmatag);
1001 1.153 fvdl
1002 1.73 augustss /* XXX determine alignment by R/W */
1003 1.1 augustss /* Allocate the HCCA area. */
1004 1.182.12.1 itohy err = usb_allocmem(&sc->sc_dmatag, OHCI_HCCA_SIZE,
1005 1.4 augustss OHCI_HCCA_ALIGN, &sc->sc_hccadma);
1006 1.53 augustss if (err)
1007 1.182.12.1 itohy goto bad1;
1008 1.123 augustss sc->sc_hcca = KERNADDR(&sc->sc_hccadma, 0);
1009 1.1 augustss memset(sc->sc_hcca, 0, OHCI_HCCA_SIZE);
1010 1.1 augustss
1011 1.1 augustss sc->sc_eintrs = OHCI_NORMAL_INTRS;
1012 1.1 augustss
1013 1.60 augustss /* Allocate dummy ED that starts the control list. */
1014 1.1 augustss sc->sc_ctrl_head = ohci_alloc_sed(sc);
1015 1.53 augustss if (sc->sc_ctrl_head == NULL) {
1016 1.53 augustss err = USBD_NOMEM;
1017 1.182.12.1 itohy goto bad2;
1018 1.1 augustss }
1019 1.168 augustss sc->sc_ctrl_head->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
1020 1.34 augustss
1021 1.60 augustss /* Allocate dummy ED that starts the bulk list. */
1022 1.1 augustss sc->sc_bulk_head = ohci_alloc_sed(sc);
1023 1.53 augustss if (sc->sc_bulk_head == NULL) {
1024 1.53 augustss err = USBD_NOMEM;
1025 1.182.12.1 itohy goto bad3;
1026 1.1 augustss }
1027 1.168 augustss sc->sc_bulk_head->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
1028 1.1 augustss
1029 1.60 augustss /* Allocate dummy ED that starts the isochronous list. */
1030 1.60 augustss sc->sc_isoc_head = ohci_alloc_sed(sc);
1031 1.60 augustss if (sc->sc_isoc_head == NULL) {
1032 1.60 augustss err = USBD_NOMEM;
1033 1.60 augustss goto bad3;
1034 1.60 augustss }
1035 1.168 augustss sc->sc_isoc_head->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
1036 1.60 augustss
1037 1.1 augustss /* Allocate all the dummy EDs that make up the interrupt tree. */
1038 1.1 augustss for (i = 0; i < OHCI_NO_EDS; i++) {
1039 1.1 augustss sed = ohci_alloc_sed(sc);
1040 1.53 augustss if (sed == NULL) {
1041 1.1 augustss while (--i >= 0)
1042 1.1 augustss ohci_free_sed(sc, sc->sc_eds[i]);
1043 1.53 augustss err = USBD_NOMEM;
1044 1.182.12.1 itohy goto bad3;
1045 1.1 augustss }
1046 1.1 augustss /* All ED fields are set to 0. */
1047 1.1 augustss sc->sc_eds[i] = sed;
1048 1.168 augustss sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
1049 1.60 augustss if (i != 0)
1050 1.1 augustss psed = sc->sc_eds[(i-1) / 2];
1051 1.60 augustss else
1052 1.182.12.1 itohy psed = sc->sc_isoc_head;
1053 1.60 augustss sed->next = psed;
1054 1.182.12.1 itohy eddma = OHCI_SED_DMAADDR(psed);
1055 1.182.12.1 itohy sed->ed.ed_nexted = HTOO32(eddma);
1056 1.1 augustss }
1057 1.120 augustss /*
1058 1.1 augustss * Fill HCCA interrupt table. The bit reversal is to get
1059 1.1 augustss * the tree set up properly to spread the interrupts.
1060 1.1 augustss */
1061 1.182.12.1 itohy for (i = 0; i < OHCI_NO_INTRS; i++) {
1062 1.182.12.1 itohy eddma = OHCI_SED_DMAADDR(sc->sc_eds[OHCI_NO_EDS-OHCI_NO_INTRS+i]);
1063 1.182.12.1 itohy sc->sc_hcca->hcca_interrupt_table[revbits[i]] = HTOO32(eddma);
1064 1.182.12.1 itohy }
1065 1.182.12.3 itohy USB_MEM_SYNC(&sc->sc_dmatag, &sc->sc_hccadma,
1066 1.182.12.3 itohy BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1067 1.1 augustss
1068 1.182.12.1 itohy #ifdef USB_DEBUG
1069 1.73 augustss if (ohcidebug > 15) {
1070 1.73 augustss for (i = 0; i < OHCI_NO_EDS; i++) {
1071 1.73 augustss printf("ed#%d ", i);
1072 1.168 augustss ohci_dump_ed(sc, sc->sc_eds[i]);
1073 1.73 augustss }
1074 1.73 augustss printf("iso ");
1075 1.168 augustss ohci_dump_ed(sc, sc->sc_isoc_head);
1076 1.73 augustss }
1077 1.73 augustss #endif
1078 1.73 augustss
1079 1.182.12.1 itohy err = ohci_controller_init(sc);
1080 1.182.12.1 itohy if (err != USBD_NORMAL_COMPLETION)
1081 1.182.12.1 itohy goto bad3;
1082 1.182.12.1 itohy
1083 1.182.12.1 itohy /* Set up the bus struct. */
1084 1.182.12.1 itohy sc->sc_bus.methods = &ohci_bus_methods;
1085 1.182.12.1 itohy sc->sc_bus.pipe_size = sizeof(struct ohci_pipe);
1086 1.182.12.1 itohy
1087 1.182.12.1 itohy #if defined(__NetBSD__) || defined(__OpenBSD__)
1088 1.182.12.1 itohy sc->sc_control = sc->sc_intre = 0;
1089 1.182.12.1 itohy sc->sc_powerhook = powerhook_establish(USBDEVNAME(sc->sc_bus.bdev),
1090 1.182.12.1 itohy ohci_power, sc);
1091 1.182.12.1 itohy sc->sc_shutdownhook = shutdownhook_establish(ohci_shutdown, sc);
1092 1.182.12.1 itohy #endif
1093 1.182.12.1 itohy
1094 1.182.12.1 itohy usb_callout_init(sc->sc_tmo_rhsc);
1095 1.182.12.1 itohy
1096 1.182.12.1 itohy /* Finally, turn on interrupts. */
1097 1.182.12.1 itohy DPRINTFN(1,("ohci_init: enabling\n"));
1098 1.182.12.1 itohy OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_eintrs | OHCI_MIE);
1099 1.182.12.1 itohy
1100 1.182.12.1 itohy return (USBD_NORMAL_COMPLETION);
1101 1.182.12.1 itohy
1102 1.182.12.1 itohy bad3:
1103 1.182.12.1 itohy ohci_free_desc_chunks(sc, &sc->sc_sed_chunks);
1104 1.182.12.1 itohy bad2:
1105 1.182.12.1 itohy usb_freemem(&sc->sc_dmatag, &sc->sc_hccadma);
1106 1.182.12.1 itohy bad1:
1107 1.182.12.1 itohy usb_dma_tag_finish(&sc->sc_dmatag);
1108 1.182.12.1 itohy return (err);
1109 1.182.12.1 itohy }
1110 1.182.12.1 itohy
1111 1.182.12.1 itohy Static usbd_status
1112 1.182.12.1 itohy ohci_controller_init(ohci_softc_t *sc)
1113 1.182.12.1 itohy {
1114 1.182.12.1 itohy int i;
1115 1.182.12.1 itohy u_int32_t s, ctl, rwc, ival, hcr, fm, per, desca, descb;
1116 1.182.12.1 itohy
1117 1.161 augustss /* Preserve values programmed by SMM/BIOS but lost over reset. */
1118 1.161 augustss ctl = OREAD4(sc, OHCI_CONTROL);
1119 1.161 augustss rwc = ctl & OHCI_RWC;
1120 1.161 augustss fm = OREAD4(sc, OHCI_FM_INTERVAL);
1121 1.161 augustss desca = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
1122 1.161 augustss descb = OREAD4(sc, OHCI_RH_DESCRIPTOR_B);
1123 1.161 augustss
1124 1.1 augustss /* Determine in what context we are running. */
1125 1.1 augustss if (ctl & OHCI_IR) {
1126 1.1 augustss /* SMM active, request change */
1127 1.1 augustss DPRINTF(("ohci_init: SMM active, request owner change\n"));
1128 1.160 augustss if ((sc->sc_intre & (OHCI_OC | OHCI_MIE)) ==
1129 1.160 augustss (OHCI_OC | OHCI_MIE))
1130 1.160 augustss OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_MIE);
1131 1.1 augustss s = OREAD4(sc, OHCI_COMMAND_STATUS);
1132 1.1 augustss OWRITE4(sc, OHCI_COMMAND_STATUS, s | OHCI_OCR);
1133 1.1 augustss for (i = 0; i < 100 && (ctl & OHCI_IR); i++) {
1134 1.53 augustss usb_delay_ms(&sc->sc_bus, 1);
1135 1.1 augustss ctl = OREAD4(sc, OHCI_CONTROL);
1136 1.1 augustss }
1137 1.160 augustss OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_MIE);
1138 1.1 augustss if ((ctl & OHCI_IR) == 0) {
1139 1.15 augustss printf("%s: SMM does not respond, resetting\n",
1140 1.15 augustss USBDEVNAME(sc->sc_bus.bdev));
1141 1.161 augustss OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET | rwc);
1142 1.1 augustss goto reset;
1143 1.1 augustss }
1144 1.103 augustss #if 0
1145 1.103 augustss /* Don't bother trying to reuse the BIOS init, we'll reset it anyway. */
1146 1.1 augustss } else if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_RESET) {
1147 1.1 augustss /* BIOS started controller. */
1148 1.1 augustss DPRINTF(("ohci_init: BIOS active\n"));
1149 1.1 augustss if ((ctl & OHCI_HCFS_MASK) != OHCI_HCFS_OPERATIONAL) {
1150 1.161 augustss OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_OPERATIONAL | rwc);
1151 1.53 augustss usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
1152 1.1 augustss }
1153 1.103 augustss #endif
1154 1.1 augustss } else {
1155 1.1 augustss DPRINTF(("ohci_init: cold started\n"));
1156 1.1 augustss reset:
1157 1.1 augustss /* Controller was cold started. */
1158 1.53 augustss usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
1159 1.1 augustss }
1160 1.1 augustss
1161 1.16 augustss /*
1162 1.25 augustss * This reset should not be necessary according to the OHCI spec, but
1163 1.25 augustss * without it some controllers do not start.
1164 1.16 augustss */
1165 1.16 augustss DPRINTF(("%s: resetting\n", USBDEVNAME(sc->sc_bus.bdev)));
1166 1.161 augustss OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET | rwc);
1167 1.55 augustss usb_delay_ms(&sc->sc_bus, USB_BUS_RESET_DELAY);
1168 1.16 augustss
1169 1.1 augustss /* We now own the host controller and the bus has been reset. */
1170 1.1 augustss
1171 1.1 augustss OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_HCR); /* Reset HC */
1172 1.1 augustss /* Nominal time for a reset is 10 us. */
1173 1.1 augustss for (i = 0; i < 10; i++) {
1174 1.1 augustss delay(10);
1175 1.1 augustss hcr = OREAD4(sc, OHCI_COMMAND_STATUS) & OHCI_HCR;
1176 1.1 augustss if (!hcr)
1177 1.1 augustss break;
1178 1.1 augustss }
1179 1.1 augustss if (hcr) {
1180 1.15 augustss printf("%s: reset timeout\n", USBDEVNAME(sc->sc_bus.bdev));
1181 1.182.12.1 itohy return (USBD_IOERROR);
1182 1.1 augustss }
1183 1.182.12.1 itohy #ifdef USB_DEBUG
1184 1.1 augustss if (ohcidebug > 15)
1185 1.1 augustss ohci_dumpregs(sc);
1186 1.1 augustss #endif
1187 1.1 augustss
1188 1.60 augustss /* The controller is now in SUSPEND state, we have 2ms to finish. */
1189 1.1 augustss
1190 1.1 augustss /* Set up HC registers. */
1191 1.125 augustss OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0));
1192 1.182.12.1 itohy OWRITE4(sc, OHCI_CONTROL_HEAD_ED, OHCI_SED_DMAADDR(sc->sc_ctrl_head));
1193 1.182.12.1 itohy OWRITE4(sc, OHCI_BULK_HEAD_ED, OHCI_SED_DMAADDR(sc->sc_bulk_head));
1194 1.55 augustss /* disable all interrupts and then switch on all desired interrupts */
1195 1.1 augustss OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTRS);
1196 1.55 augustss /* switch on desired functional features */
1197 1.1 augustss ctl = OREAD4(sc, OHCI_CONTROL);
1198 1.1 augustss ctl &= ~(OHCI_CBSR_MASK | OHCI_LES | OHCI_HCFS_MASK | OHCI_IR);
1199 1.1 augustss ctl |= OHCI_PLE | OHCI_IE | OHCI_CLE | OHCI_BLE |
1200 1.161 augustss OHCI_RATIO_1_4 | OHCI_HCFS_OPERATIONAL | rwc;
1201 1.1 augustss /* And finally start it! */
1202 1.1 augustss OWRITE4(sc, OHCI_CONTROL, ctl);
1203 1.1 augustss
1204 1.1 augustss /*
1205 1.1 augustss * The controller is now OPERATIONAL. Set a some final
1206 1.1 augustss * registers that should be set earlier, but that the
1207 1.1 augustss * controller ignores when in the SUSPEND state.
1208 1.1 augustss */
1209 1.161 augustss ival = OHCI_GET_IVAL(fm);
1210 1.1 augustss fm = (OREAD4(sc, OHCI_FM_INTERVAL) & OHCI_FIT) ^ OHCI_FIT;
1211 1.1 augustss fm |= OHCI_FSMPS(ival) | ival;
1212 1.1 augustss OWRITE4(sc, OHCI_FM_INTERVAL, fm);
1213 1.1 augustss per = OHCI_PERIODIC(ival); /* 90% periodic */
1214 1.1 augustss OWRITE4(sc, OHCI_PERIODIC_START, per);
1215 1.1 augustss
1216 1.68 augustss /* Fiddle the No OverCurrent Protection bit to avoid chip bug. */
1217 1.68 augustss OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca | OHCI_NOCP);
1218 1.68 augustss OWRITE4(sc, OHCI_RH_STATUS, OHCI_LPSC); /* Enable port power */
1219 1.85 augustss usb_delay_ms(&sc->sc_bus, OHCI_ENABLE_POWER_DELAY);
1220 1.68 augustss OWRITE4(sc, OHCI_RH_DESCRIPTOR_A, desca);
1221 1.1 augustss
1222 1.85 augustss /*
1223 1.85 augustss * The AMD756 requires a delay before re-reading the register,
1224 1.85 augustss * otherwise it will occasionally report 0 ports.
1225 1.85 augustss */
1226 1.145 augustss sc->sc_noport = 0;
1227 1.145 augustss for (i = 0; i < 10 && sc->sc_noport == 0; i++) {
1228 1.145 augustss usb_delay_ms(&sc->sc_bus, OHCI_READ_DESC_DELAY);
1229 1.145 augustss sc->sc_noport = OHCI_GET_NDP(OREAD4(sc, OHCI_RH_DESCRIPTOR_A));
1230 1.145 augustss }
1231 1.1 augustss
1232 1.182.12.1 itohy #ifdef USB_DEBUG
1233 1.1 augustss if (ohcidebug > 5)
1234 1.1 augustss ohci_dumpregs(sc);
1235 1.1 augustss #endif
1236 1.182.12.1 itohy return (USBD_NORMAL_COMPLETION);
1237 1.182.12.1 itohy }
1238 1.120 augustss
1239 1.182.12.3 itohy /*
1240 1.182.12.3 itohy * Allocate a physically contiguous buffer to handle cases where OHCI
1241 1.182.12.3 itohy * cannot handle a packet because it is not physically contiguous.
1242 1.182.12.3 itohy */
1243 1.182.12.3 itohy Static void
1244 1.182.12.3 itohy ohci_aux_mem_init(struct ohci_aux_mem *aux)
1245 1.182.12.3 itohy {
1246 1.182.12.3 itohy
1247 1.182.12.3 itohy aux->aux_curchunk = aux->aux_chunkoff = aux->aux_naux = 0;
1248 1.182.12.3 itohy }
1249 1.182.12.3 itohy
1250 1.182.12.3 itohy Static usbd_status
1251 1.182.12.3 itohy ohci_aux_mem_alloc(ohci_softc_t *sc, struct ohci_aux_mem *aux,
1252 1.182.12.3 itohy int naux, int maxp)
1253 1.182.12.3 itohy {
1254 1.182.12.3 itohy int nchunk, i, j;
1255 1.182.12.3 itohy usbd_status err;
1256 1.182.12.3 itohy
1257 1.182.12.3 itohy USB_KASSERT(aux->aux_nchunk == 0);
1258 1.182.12.3 itohy
1259 1.182.12.3 itohy nchunk = OHCI_NCHUNK(naux, maxp);
1260 1.182.12.3 itohy for (i = 0; i < nchunk; i++) {
1261 1.182.12.3 itohy err = usb_allocmem(&sc->sc_dmatag, OHCI_AUX_CHUNK_SIZE,
1262 1.182.12.3 itohy OHCI_AUX_CHUNK_SIZE, &aux->aux_chunk_dma[i]);
1263 1.182.12.3 itohy if (err) {
1264 1.182.12.3 itohy for (j = 0; j < i; j++)
1265 1.182.12.3 itohy usb_freemem(&sc->sc_dmatag,
1266 1.182.12.3 itohy &aux->aux_chunk_dma[j]);
1267 1.182.12.3 itohy return (err);
1268 1.182.12.3 itohy }
1269 1.182.12.3 itohy }
1270 1.182.12.3 itohy
1271 1.182.12.3 itohy aux->aux_nchunk = nchunk;
1272 1.182.12.3 itohy ohci_aux_mem_init(aux);
1273 1.182.12.3 itohy
1274 1.182.12.3 itohy return (USBD_NORMAL_COMPLETION);
1275 1.182.12.3 itohy }
1276 1.182.12.3 itohy
1277 1.182.12.3 itohy Static void
1278 1.182.12.3 itohy ohci_aux_mem_free(ohci_softc_t *sc, struct ohci_aux_mem *aux)
1279 1.182.12.3 itohy {
1280 1.182.12.3 itohy int i;
1281 1.182.12.3 itohy
1282 1.182.12.3 itohy for (i = 0; i < aux->aux_nchunk; i++)
1283 1.182.12.3 itohy usb_freemem(&sc->sc_dmatag, &aux->aux_chunk_dma[i]);
1284 1.182.12.3 itohy
1285 1.182.12.3 itohy aux->aux_nchunk = 0;
1286 1.182.12.3 itohy }
1287 1.182.12.3 itohy
1288 1.182.12.3 itohy Static bus_addr_t
1289 1.182.12.3 itohy ohci_aux_dma_alloc(struct ohci_aux_mem *aux,
1290 1.182.12.3 itohy const union usb_bufptr *bufptr, int len,
1291 1.182.12.3 itohy struct usb_aux_desc *ad)
1292 1.182.12.3 itohy {
1293 1.182.12.3 itohy bus_addr_t auxdma;
1294 1.182.12.3 itohy
1295 1.182.12.3 itohy if (aux->aux_chunkoff + len > OHCI_AUX_CHUNK_SIZE) {
1296 1.182.12.3 itohy aux->aux_curchunk++;
1297 1.182.12.3 itohy aux->aux_chunkoff = 0;
1298 1.182.12.3 itohy }
1299 1.182.12.3 itohy USB_KASSERT(aux->aux_curchunk < aux->aux_nchunk);
1300 1.182.12.3 itohy
1301 1.182.12.3 itohy auxdma =
1302 1.182.12.3 itohy DMAADDR(&aux->aux_chunk_dma[aux->aux_curchunk], aux->aux_chunkoff);
1303 1.182.12.3 itohy ad->aux_kern =
1304 1.182.12.3 itohy KERNADDR(&aux->aux_chunk_dma[aux->aux_curchunk], aux->aux_chunkoff);
1305 1.182.12.3 itohy ad->aux_ptr = *bufptr;
1306 1.182.12.3 itohy ad->aux_len = len;
1307 1.182.12.3 itohy
1308 1.182.12.3 itohy aux->aux_chunkoff += len;
1309 1.182.12.3 itohy aux->aux_naux++;
1310 1.182.12.3 itohy
1311 1.182.12.3 itohy return auxdma;
1312 1.182.12.3 itohy }
1313 1.182.12.3 itohy
1314 1.182.12.3 itohy Static void
1315 1.182.12.3 itohy ohci_aux_dma_complete(struct usb_aux_desc *ad, struct ohci_aux_mem *aux,
1316 1.182.12.3 itohy int is_mbuf, int isread)
1317 1.182.12.3 itohy {
1318 1.182.12.3 itohy
1319 1.182.12.3 itohy if (isread) {
1320 1.182.12.3 itohy usb_bufptr_rd(&ad->aux_ptr, ad->aux_kern, ad->aux_len,
1321 1.182.12.3 itohy is_mbuf);
1322 1.182.12.3 itohy }
1323 1.182.12.3 itohy ad->aux_len = 0;
1324 1.182.12.3 itohy USB_KASSERT(aux->aux_naux > 0);
1325 1.182.12.3 itohy if (--aux->aux_naux == 0)
1326 1.182.12.3 itohy ohci_aux_mem_init(aux);
1327 1.182.12.3 itohy }
1328 1.182.12.3 itohy
1329 1.182.12.3 itohy Static void
1330 1.182.12.3 itohy ohci_aux_dma_sync(ohci_softc_t *sc, struct ohci_aux_mem *aux, int op)
1331 1.182.12.3 itohy {
1332 1.182.12.3 itohy int i;
1333 1.182.12.3 itohy
1334 1.182.12.3 itohy for (i = 0; i < aux->aux_curchunk; i++)
1335 1.182.12.3 itohy USB_MEM_SYNC(&sc->sc_dmatag, &aux->aux_chunk_dma[i], op);
1336 1.182.12.3 itohy if (aux->aux_chunkoff)
1337 1.182.12.3 itohy USB_MEM_SYNC2(&sc->sc_dmatag, &aux->aux_chunk_dma[i],
1338 1.182.12.3 itohy 0, aux->aux_chunkoff, op);
1339 1.182.12.3 itohy }
1340 1.182.12.3 itohy
1341 1.182.12.1 itohy Static usbd_status
1342 1.182.12.1 itohy ohci_prealloc(struct ohci_softc *sc, struct ohci_xfer *oxfer,
1343 1.182.12.1 itohy size_t bufsize, int nseg)
1344 1.182.12.1 itohy {
1345 1.182.12.3 itohy usb_endpoint_descriptor_t *ed;
1346 1.182.12.3 itohy int maxseg, maxp, naux;
1347 1.182.12.1 itohy int seglen, ntd;
1348 1.182.12.1 itohy int s;
1349 1.182.12.1 itohy int err;
1350 1.1 augustss
1351 1.182.12.3 itohy ed = oxfer->xfer.pipe->endpoint->edesc;
1352 1.182.12.3 itohy maxp = UE_MAXPKTSZ(ed);
1353 1.59 augustss
1354 1.182.12.1 itohy if (maxp == 0)
1355 1.182.12.1 itohy return (USBD_INVAL);
1356 1.104 augustss
1357 1.182.12.1 itohy /* (over) estimate needed number of TDs */
1358 1.182.12.1 itohy maxseg = (sc->sc_flags & OHCI_FLAG_QUIRK_2ND_4KB) ? 4096 : 8192;
1359 1.182.12.1 itohy seglen = maxseg - (maxseg % maxp);
1360 1.182.12.1 itohy ntd = bufsize / seglen + nseg;
1361 1.167 augustss
1362 1.182.12.3 itohy #if 1
1363 1.182.12.3 itohy /* allocate aux buffer for non-isoc OUT or isoc transfer */
1364 1.182.12.3 itohy naux = 0;
1365 1.182.12.3 itohy if (nseg > 1 &&
1366 1.182.12.3 itohy ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS ||
1367 1.182.12.3 itohy UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT)) {
1368 1.182.12.3 itohy /* estimate needed aux segments */
1369 1.182.12.3 itohy naux = nseg - 1;
1370 1.182.12.3 itohy
1371 1.182.12.3 itohy /* pre-allocate aux memory */
1372 1.182.12.3 itohy err = ohci_aux_mem_alloc(sc, &oxfer->aux, naux, maxp);
1373 1.182.12.3 itohy if (err)
1374 1.182.12.3 itohy return err;
1375 1.182.12.3 itohy
1376 1.182.12.3 itohy /* an aux segment will consume a TD */
1377 1.182.12.3 itohy ntd += naux;
1378 1.182.12.3 itohy }
1379 1.182.12.3 itohy #endif
1380 1.182.12.3 itohy
1381 1.182.12.1 itohy s = splusb();
1382 1.182.12.3 itohy if ((ed->bmAttributes & UE_XFERTYPE) == UE_ISOCHRONOUS) {
1383 1.182.12.1 itohy /* pre-allocate ITDs */
1384 1.182.12.1 itohy while (sc->sc_nfreeitds < ntd) {
1385 1.182.12.1 itohy DPRINTF(("%s: ohci_prealloc: need %d ITD (%d cur)\n",
1386 1.182.12.1 itohy USBDEVNAME(sc->sc_bus.bdev),
1387 1.182.12.1 itohy ntd, sc->sc_nfreeitds));
1388 1.182.12.1 itohy if ((err = ohci_grow_sitd(sc))
1389 1.182.12.1 itohy != USBD_NORMAL_COMPLETION) {
1390 1.182.12.1 itohy splx(s);
1391 1.182.12.3 itohy ohci_aux_mem_free(sc, &oxfer->aux);
1392 1.182.12.1 itohy return (err);
1393 1.182.12.1 itohy }
1394 1.182.12.1 itohy }
1395 1.182.12.1 itohy sc->sc_nfreeitds -= ntd;
1396 1.182.12.1 itohy } else {
1397 1.182.12.1 itohy /* pre-allocate TDs */
1398 1.182.12.1 itohy while (sc->sc_nfreetds < ntd) {
1399 1.182.12.1 itohy DPRINTF(("%s: ohci_prealloc: need %d TD (%d cur)\n",
1400 1.182.12.1 itohy USBDEVNAME(sc->sc_bus.bdev),
1401 1.182.12.1 itohy ntd, sc->sc_nfreetds));
1402 1.182.12.1 itohy if ((err = ohci_grow_std(sc))
1403 1.182.12.1 itohy != USBD_NORMAL_COMPLETION) {
1404 1.182.12.1 itohy splx(s);
1405 1.182.12.3 itohy ohci_aux_mem_free(sc, &oxfer->aux);
1406 1.182.12.1 itohy return (err);
1407 1.182.12.1 itohy }
1408 1.182.12.1 itohy }
1409 1.182.12.1 itohy sc->sc_nfreetds -= ntd;
1410 1.182.12.1 itohy }
1411 1.182.12.1 itohy splx(s);
1412 1.1 augustss
1413 1.182.12.1 itohy oxfer->rsvd_tds = ntd;
1414 1.182.12.1 itohy
1415 1.182.12.1 itohy return (USBD_NORMAL_COMPLETION);
1416 1.1 augustss }
1417 1.1 augustss
1418 1.42 augustss usbd_status
1419 1.182.12.1 itohy ohci_allocm(struct usbd_bus *bus, usbd_xfer_handle xfer, void *buf, size_t size)
1420 1.42 augustss {
1421 1.42 augustss struct ohci_softc *sc = (struct ohci_softc *)bus;
1422 1.182.12.1 itohy struct ohci_xfer *oxfer = OXFER(xfer);
1423 1.182.12.1 itohy usbd_status err;
1424 1.182.12.1 itohy
1425 1.182.12.1 itohy if ((err = usb_alloc_buffer_dma(&sc->sc_dmatag, &oxfer->dmabuf,
1426 1.182.12.1 itohy buf, size, &xfer->hcbuffer)) == USBD_NORMAL_COMPLETION) {
1427 1.182.12.1 itohy if ((xfer->rqflags & URQ_DEV_MAP_PREPARED) == 0 &&
1428 1.182.12.1 itohy (err = ohci_prealloc(sc, oxfer, size,
1429 1.182.12.1 itohy USB_BUFFER_NSEGS(&oxfer->dmabuf)))
1430 1.182.12.1 itohy != USBD_NORMAL_COMPLETION) {
1431 1.182.12.1 itohy usb_free_buffer_dma(&sc->sc_dmatag, &oxfer->dmabuf,
1432 1.182.12.1 itohy U_WAITOK);
1433 1.182.12.1 itohy }
1434 1.182.12.1 itohy }
1435 1.182.12.1 itohy
1436 1.182.12.1 itohy return err;
1437 1.182.12.1 itohy }
1438 1.182.12.1 itohy
1439 1.182.12.1 itohy void
1440 1.182.12.1 itohy ohci_freem(struct usbd_bus *bus, usbd_xfer_handle xfer,
1441 1.182.12.1 itohy enum usbd_waitflg waitflg)
1442 1.182.12.1 itohy {
1443 1.182.12.1 itohy struct ohci_softc *sc = (struct ohci_softc *)bus;
1444 1.182.12.1 itohy struct ohci_xfer *oxfer = OXFER(xfer);
1445 1.182.12.1 itohy int s;
1446 1.182.12.1 itohy
1447 1.182.12.1 itohy usb_free_buffer_dma(&sc->sc_dmatag, &oxfer->dmabuf, waitflg);
1448 1.182.12.1 itohy
1449 1.182.12.1 itohy if ((xfer->rqflags & URQ_DEV_MAP_PREPARED) == 0) {
1450 1.182.12.1 itohy s = splusb();
1451 1.182.12.1 itohy if ((xfer->pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) ==
1452 1.182.12.1 itohy UE_ISOCHRONOUS) {
1453 1.182.12.1 itohy sc->sc_nfreeitds += oxfer->rsvd_tds;
1454 1.182.12.1 itohy } else {
1455 1.182.12.1 itohy sc->sc_nfreetds += oxfer->rsvd_tds;
1456 1.182.12.1 itohy }
1457 1.182.12.1 itohy splx(s);
1458 1.182.12.3 itohy ohci_aux_mem_free(sc, &oxfer->aux);
1459 1.182.12.1 itohy oxfer->rsvd_tds = 0;
1460 1.182.12.1 itohy }
1461 1.182.12.1 itohy }
1462 1.182.12.1 itohy
1463 1.182.12.1 itohy Static usbd_status
1464 1.182.12.1 itohy ohci_map_alloc(usbd_xfer_handle xfer)
1465 1.182.12.1 itohy {
1466 1.182.12.1 itohy struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
1467 1.182.12.1 itohy struct ohci_xfer *oxfer = OXFER(xfer);
1468 1.182.12.1 itohy usbd_status st;
1469 1.182.12.1 itohy
1470 1.182.12.1 itohy st = usb_alloc_dma_resources(&sc->sc_dmatag, &oxfer->dmabuf);
1471 1.182.12.1 itohy if (st)
1472 1.182.12.1 itohy return st;
1473 1.182.12.1 itohy
1474 1.182.12.1 itohy if ((st = ohci_prealloc(sc, oxfer, MAXPHYS, USB_DMA_NSEG))) {
1475 1.182.12.1 itohy usb_free_dma_resources(&sc->sc_dmatag, &oxfer->dmabuf);
1476 1.182.12.1 itohy }
1477 1.182.12.1 itohy
1478 1.182.12.1 itohy return st;
1479 1.182.12.1 itohy }
1480 1.182.12.1 itohy
1481 1.182.12.1 itohy Static void
1482 1.182.12.1 itohy ohci_map_free(usbd_xfer_handle xfer)
1483 1.182.12.1 itohy {
1484 1.182.12.1 itohy struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
1485 1.182.12.1 itohy struct ohci_xfer *oxfer = OXFER(xfer);
1486 1.182.12.1 itohy int s;
1487 1.182.12.1 itohy
1488 1.182.12.1 itohy USB_KASSERT(xfer->rqflags & URQ_DEV_MAP_PREPARED);
1489 1.182.12.1 itohy
1490 1.182.12.1 itohy usb_free_dma_resources(&sc->sc_dmatag, &oxfer->dmabuf);
1491 1.182.12.1 itohy
1492 1.182.12.1 itohy s = splusb();
1493 1.182.12.1 itohy if ((xfer->pipe->endpoint->edesc->bmAttributes & UE_XFERTYPE) ==
1494 1.182.12.1 itohy UE_ISOCHRONOUS) {
1495 1.182.12.1 itohy sc->sc_nfreeitds += oxfer->rsvd_tds;
1496 1.182.12.1 itohy } else {
1497 1.182.12.1 itohy sc->sc_nfreetds += oxfer->rsvd_tds;
1498 1.182.12.1 itohy }
1499 1.182.12.1 itohy splx(s);
1500 1.182.12.3 itohy ohci_aux_mem_free(sc, &oxfer->aux);
1501 1.182.12.1 itohy oxfer->rsvd_tds = 0;
1502 1.182.12.1 itohy }
1503 1.182.12.1 itohy
1504 1.182.12.1 itohy Static void
1505 1.182.12.1 itohy ohci_mapm(usbd_xfer_handle xfer, void *buf, size_t size)
1506 1.182.12.1 itohy {
1507 1.182.12.1 itohy struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
1508 1.182.12.1 itohy struct ohci_xfer *oxfer = OXFER(xfer);
1509 1.182.12.1 itohy
1510 1.182.12.1 itohy usb_map_dma(&sc->sc_dmatag, &oxfer->dmabuf, buf, size);
1511 1.182.12.1 itohy }
1512 1.182.12.1 itohy
1513 1.182.12.2 itohy Static usbd_status
1514 1.182.12.1 itohy ohci_mapm_mbuf(usbd_xfer_handle xfer, struct mbuf *chain)
1515 1.182.12.1 itohy {
1516 1.182.12.1 itohy struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
1517 1.182.12.1 itohy struct ohci_xfer *oxfer = OXFER(xfer);
1518 1.42 augustss
1519 1.182.12.2 itohy return (usb_map_mbuf_dma(&sc->sc_dmatag, &oxfer->dmabuf, chain));
1520 1.42 augustss }
1521 1.42 augustss
1522 1.182.12.1 itohy Static void
1523 1.182.12.1 itohy ohci_unmapm(usbd_xfer_handle xfer)
1524 1.42 augustss {
1525 1.182.12.1 itohy struct ohci_softc *sc = (struct ohci_softc *)xfer->device->bus;
1526 1.182.12.1 itohy struct ohci_xfer *oxfer = OXFER(xfer);
1527 1.182.12.1 itohy
1528 1.182.12.1 itohy usb_unmap_dma(&sc->sc_dmatag, &oxfer->dmabuf);
1529 1.62 augustss }
1530 1.62 augustss
1531 1.62 augustss usbd_xfer_handle
1532 1.182.12.1 itohy ohci_allocx(struct usbd_bus *bus, usbd_pipe_handle pipe,
1533 1.182.12.1 itohy enum usbd_waitflg waitflg)
1534 1.62 augustss {
1535 1.62 augustss struct ohci_softc *sc = (struct ohci_softc *)bus;
1536 1.62 augustss usbd_xfer_handle xfer;
1537 1.62 augustss
1538 1.62 augustss xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers);
1539 1.118 augustss if (xfer != NULL) {
1540 1.126 lukem SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next);
1541 1.118 augustss #ifdef DIAGNOSTIC
1542 1.118 augustss if (xfer->busy_free != XFER_FREE) {
1543 1.118 augustss printf("ohci_allocx: xfer=%p not free, 0x%08x\n", xfer,
1544 1.118 augustss xfer->busy_free);
1545 1.118 augustss }
1546 1.118 augustss #endif
1547 1.118 augustss } else {
1548 1.182.12.1 itohy xfer = malloc(sizeof(struct ohci_xfer), M_USB,
1549 1.182.12.1 itohy waitflg == U_WAITOK ? M_WAITOK : M_NOWAIT);
1550 1.118 augustss }
1551 1.118 augustss if (xfer != NULL) {
1552 1.114 augustss memset(xfer, 0, sizeof (struct ohci_xfer));
1553 1.182.12.1 itohy usb_init_task(&OXFER(xfer)->abort_task, ohci_timeout_task,
1554 1.182.12.1 itohy xfer);
1555 1.182.12.1 itohy OXFER(xfer)->ohci_xfer_flags = 0;
1556 1.182.12.1 itohy OXFER(xfer)->rsvd_tds = 0;
1557 1.118 augustss #ifdef DIAGNOSTIC
1558 1.118 augustss xfer->busy_free = XFER_BUSY;
1559 1.118 augustss #endif
1560 1.118 augustss }
1561 1.62 augustss return (xfer);
1562 1.62 augustss }
1563 1.62 augustss
1564 1.62 augustss void
1565 1.91 augustss ohci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer)
1566 1.62 augustss {
1567 1.62 augustss struct ohci_softc *sc = (struct ohci_softc *)bus;
1568 1.62 augustss
1569 1.118 augustss #ifdef DIAGNOSTIC
1570 1.118 augustss if (xfer->busy_free != XFER_BUSY) {
1571 1.182.12.3 itohy #if 1
1572 1.182.12.3 itohy panic("ohci_freex: xfer=%p not busy, 0x%08x\n", xfer,
1573 1.182.12.3 itohy xfer->busy_free);
1574 1.182.12.3 itohy #else
1575 1.118 augustss printf("ohci_freex: xfer=%p not busy, 0x%08x\n", xfer,
1576 1.118 augustss xfer->busy_free);
1577 1.182.12.3 itohy #endif
1578 1.118 augustss }
1579 1.118 augustss xfer->busy_free = XFER_FREE;
1580 1.118 augustss #endif
1581 1.62 augustss SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next);
1582 1.42 augustss }
1583 1.42 augustss
1584 1.59 augustss /*
1585 1.182.12.3 itohy * Perform any OHCI-specific transfer completion operations, then
1586 1.182.12.3 itohy * call usb_transfer_complete().
1587 1.182.12.3 itohy */
1588 1.182.12.3 itohy Static void
1589 1.182.12.3 itohy ohci_transfer_complete(usbd_xfer_handle xfer, int clear_halt)
1590 1.182.12.3 itohy {
1591 1.182.12.3 itohy struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
1592 1.182.12.3 itohy ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
1593 1.182.12.3 itohy struct usb_buffer_dma *ub = &OXFER(xfer)->dmabuf;
1594 1.182.12.3 itohy ohci_soft_itd_t *sitd, *sitdnext;
1595 1.182.12.3 itohy ohci_soft_td_t *std, *stdnext;
1596 1.182.12.3 itohy ohci_physaddr_t dmaadr;
1597 1.182.12.3 itohy int isread, is_mbuf;
1598 1.182.12.3 itohy int s;
1599 1.182.12.3 itohy
1600 1.182.12.3 itohy isread = usbd_xfer_isread(xfer);
1601 1.182.12.3 itohy is_mbuf = xfer->rqflags & URQ_DEV_MAP_MBUF;
1602 1.182.12.3 itohy
1603 1.182.12.3 itohy if (ub)
1604 1.182.12.3 itohy usb_sync_buffer_dma(&sc->sc_dmatag, ub,
1605 1.182.12.3 itohy isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1606 1.182.12.3 itohy
1607 1.182.12.3 itohy if (OXFER(xfer)->aux.aux_naux) {
1608 1.182.12.3 itohy /* sync aux */
1609 1.182.12.3 itohy ohci_aux_dma_sync(sc, &OXFER(xfer)->aux,
1610 1.182.12.3 itohy isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1611 1.182.12.3 itohy }
1612 1.182.12.3 itohy
1613 1.182.12.3 itohy /* Copy back from any auxillary buffers after a read operation. */
1614 1.182.12.3 itohy if (xfer->hcpriv == NULL) {
1615 1.182.12.3 itohy DPRINTFN(-1, ("ohci_transfer_complete: hcpriv == NULL\n"));
1616 1.182.12.3 itohy } else if (xfer->nframes == 0) {
1617 1.182.12.3 itohy /* Bulk/Interrupt transfer */
1618 1.182.12.3 itohy /* Remove all TDs belonging to this xfer. */
1619 1.182.12.3 itohy for (std = xfer->hcpriv; std->xfer == xfer; std = stdnext) {
1620 1.182.12.3 itohy stdnext = std->nexttd;
1621 1.182.12.3 itohy if (std->ad.aux_len)
1622 1.182.12.3 itohy ohci_aux_dma_complete(&std->ad,
1623 1.182.12.3 itohy &OXFER(xfer)->aux, is_mbuf, isread);
1624 1.182.12.3 itohy ohci_free_std(sc, std);
1625 1.182.12.3 itohy }
1626 1.182.12.3 itohy if (clear_halt) {
1627 1.182.12.3 itohy /* clear halt */
1628 1.182.12.3 itohy OHCI_SED_SYNC_POST(sc, opipe->sed);
1629 1.182.12.3 itohy dmaadr = OHCI_STD_DMAADDR(std);
1630 1.182.12.3 itohy opipe->sed->ed.ed_headp = HTOO32(dmaadr);
1631 1.182.12.3 itohy OHCI_SED_SYNC2(sc, opipe->sed,
1632 1.182.12.3 itohy offsetof(ohci_ed_t, ed_headp),
1633 1.182.12.3 itohy sizeof(ohci_physaddr_t),
1634 1.182.12.3 itohy BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1635 1.182.12.3 itohy OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
1636 1.182.12.3 itohy }
1637 1.182.12.3 itohy } else {
1638 1.182.12.3 itohy /* Isoc transfer */
1639 1.182.12.3 itohy /* Remove all ITDs belonging to this xfer. */
1640 1.182.12.3 itohy for (sitd = xfer->hcpriv; sitd->xfer == xfer;
1641 1.182.12.3 itohy sitd = sitdnext) {
1642 1.182.12.3 itohy sitdnext = sitd->nextitd;
1643 1.182.12.3 itohy if (sitd->ad.aux_len)
1644 1.182.12.3 itohy ohci_aux_dma_complete(&sitd->ad,
1645 1.182.12.3 itohy &OXFER(xfer)->aux, is_mbuf, isread);
1646 1.182.12.3 itohy ohci_free_sitd(sc, sitd);
1647 1.182.12.3 itohy }
1648 1.182.12.3 itohy }
1649 1.182.12.3 itohy
1650 1.182.12.3 itohy USB_KASSERT(OXFER(xfer)->aux.aux_naux == 0);
1651 1.182.12.3 itohy xfer->hcpriv = NULL;
1652 1.182.12.3 itohy
1653 1.182.12.3 itohy s = splusb();
1654 1.182.12.3 itohy usb_transfer_complete(xfer);
1655 1.182.12.3 itohy splx(s);
1656 1.182.12.3 itohy }
1657 1.182.12.3 itohy
1658 1.182.12.3 itohy /*
1659 1.59 augustss * Shut down the controller when the system is going down.
1660 1.59 augustss */
1661 1.59 augustss void
1662 1.91 augustss ohci_shutdown(void *v)
1663 1.59 augustss {
1664 1.59 augustss ohci_softc_t *sc = v;
1665 1.59 augustss
1666 1.59 augustss DPRINTF(("ohci_shutdown: stopping the HC\n"));
1667 1.59 augustss OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
1668 1.59 augustss }
1669 1.59 augustss
1670 1.59 augustss /*
1671 1.59 augustss * Handle suspend/resume.
1672 1.59 augustss *
1673 1.59 augustss * We need to switch to polling mode here, because this routine is
1674 1.162 augustss * called from an interupt context. This is all right since we
1675 1.59 augustss * are almost suspended anyway.
1676 1.59 augustss */
1677 1.33 augustss void
1678 1.91 augustss ohci_power(int why, void *v)
1679 1.33 augustss {
1680 1.33 augustss ohci_softc_t *sc = v;
1681 1.97 augustss u_int32_t ctl;
1682 1.95 augustss int s;
1683 1.33 augustss
1684 1.182.12.1 itohy #ifdef USB_DEBUG
1685 1.41 augustss DPRINTF(("ohci_power: sc=%p, why=%d\n", sc, why));
1686 1.33 augustss ohci_dumpregs(sc);
1687 1.33 augustss #endif
1688 1.95 augustss
1689 1.98 augustss s = splhardusb();
1690 1.95 augustss switch (why) {
1691 1.182.12.1 itohy USB_PWR_CASE_SUSPEND:
1692 1.97 augustss sc->sc_bus.use_polling++;
1693 1.101 minoura ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK;
1694 1.101 minoura if (sc->sc_control == 0) {
1695 1.101 minoura /*
1696 1.101 minoura * Preserve register values, in case that APM BIOS
1697 1.101 minoura * does not recover them.
1698 1.101 minoura */
1699 1.101 minoura sc->sc_control = ctl;
1700 1.101 minoura sc->sc_intre = OREAD4(sc, OHCI_INTERRUPT_ENABLE);
1701 1.101 minoura }
1702 1.101 minoura ctl |= OHCI_HCFS_SUSPEND;
1703 1.97 augustss OWRITE4(sc, OHCI_CONTROL, ctl);
1704 1.97 augustss usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT);
1705 1.97 augustss sc->sc_bus.use_polling--;
1706 1.95 augustss break;
1707 1.182.12.1 itohy
1708 1.182.12.1 itohy USB_PWR_CASE_RESUME:
1709 1.97 augustss sc->sc_bus.use_polling++;
1710 1.182.12.1 itohy
1711 1.182.12.1 itohy /* Some broken BIOSes never initialize Controller chip */
1712 1.182.12.1 itohy ohci_controller_init(sc);
1713 1.182.12.1 itohy
1714 1.101 minoura if (sc->sc_intre)
1715 1.101 minoura OWRITE4(sc, OHCI_INTERRUPT_ENABLE,
1716 1.101 minoura sc->sc_intre & (OHCI_ALL_INTRS | OHCI_MIE));
1717 1.101 minoura if (sc->sc_control)
1718 1.101 minoura ctl = sc->sc_control;
1719 1.101 minoura else
1720 1.101 minoura ctl = OREAD4(sc, OHCI_CONTROL);
1721 1.101 minoura ctl |= OHCI_HCFS_RESUME;
1722 1.97 augustss OWRITE4(sc, OHCI_CONTROL, ctl);
1723 1.97 augustss usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY);
1724 1.97 augustss ctl = (ctl & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL;
1725 1.97 augustss OWRITE4(sc, OHCI_CONTROL, ctl);
1726 1.97 augustss usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY);
1727 1.101 minoura sc->sc_control = sc->sc_intre = 0;
1728 1.97 augustss sc->sc_bus.use_polling--;
1729 1.95 augustss break;
1730 1.182.12.1 itohy
1731 1.182.12.1 itohy default:
1732 1.95 augustss break;
1733 1.95 augustss }
1734 1.95 augustss splx(s);
1735 1.33 augustss }
1736 1.33 augustss
1737 1.182.12.1 itohy #ifdef USB_DEBUG
1738 1.1 augustss void
1739 1.91 augustss ohci_dumpregs(ohci_softc_t *sc)
1740 1.1 augustss {
1741 1.41 augustss DPRINTF(("ohci_dumpregs: rev=0x%08x control=0x%08x command=0x%08x\n",
1742 1.41 augustss OREAD4(sc, OHCI_REVISION),
1743 1.41 augustss OREAD4(sc, OHCI_CONTROL),
1744 1.41 augustss OREAD4(sc, OHCI_COMMAND_STATUS)));
1745 1.41 augustss DPRINTF((" intrstat=0x%08x intre=0x%08x intrd=0x%08x\n",
1746 1.41 augustss OREAD4(sc, OHCI_INTERRUPT_STATUS),
1747 1.41 augustss OREAD4(sc, OHCI_INTERRUPT_ENABLE),
1748 1.41 augustss OREAD4(sc, OHCI_INTERRUPT_DISABLE)));
1749 1.41 augustss DPRINTF((" hcca=0x%08x percur=0x%08x ctrlhd=0x%08x\n",
1750 1.41 augustss OREAD4(sc, OHCI_HCCA),
1751 1.41 augustss OREAD4(sc, OHCI_PERIOD_CURRENT_ED),
1752 1.41 augustss OREAD4(sc, OHCI_CONTROL_HEAD_ED)));
1753 1.41 augustss DPRINTF((" ctrlcur=0x%08x bulkhd=0x%08x bulkcur=0x%08x\n",
1754 1.41 augustss OREAD4(sc, OHCI_CONTROL_CURRENT_ED),
1755 1.41 augustss OREAD4(sc, OHCI_BULK_HEAD_ED),
1756 1.41 augustss OREAD4(sc, OHCI_BULK_CURRENT_ED)));
1757 1.41 augustss DPRINTF((" done=0x%08x fmival=0x%08x fmrem=0x%08x\n",
1758 1.41 augustss OREAD4(sc, OHCI_DONE_HEAD),
1759 1.41 augustss OREAD4(sc, OHCI_FM_INTERVAL),
1760 1.41 augustss OREAD4(sc, OHCI_FM_REMAINING)));
1761 1.41 augustss DPRINTF((" fmnum=0x%08x perst=0x%08x lsthrs=0x%08x\n",
1762 1.41 augustss OREAD4(sc, OHCI_FM_NUMBER),
1763 1.41 augustss OREAD4(sc, OHCI_PERIODIC_START),
1764 1.41 augustss OREAD4(sc, OHCI_LS_THRESHOLD)));
1765 1.41 augustss DPRINTF((" desca=0x%08x descb=0x%08x stat=0x%08x\n",
1766 1.41 augustss OREAD4(sc, OHCI_RH_DESCRIPTOR_A),
1767 1.41 augustss OREAD4(sc, OHCI_RH_DESCRIPTOR_B),
1768 1.41 augustss OREAD4(sc, OHCI_RH_STATUS)));
1769 1.41 augustss DPRINTF((" port1=0x%08x port2=0x%08x\n",
1770 1.41 augustss OREAD4(sc, OHCI_RH_PORT_STATUS(1)),
1771 1.41 augustss OREAD4(sc, OHCI_RH_PORT_STATUS(2))));
1772 1.41 augustss DPRINTF((" HCCA: frame_number=0x%04x done_head=0x%08x\n",
1773 1.168 augustss O32TOH(sc->sc_hcca->hcca_frame_number),
1774 1.168 augustss O32TOH(sc->sc_hcca->hcca_done_head)));
1775 1.1 augustss }
1776 1.1 augustss #endif
1777 1.1 augustss
1778 1.91 augustss Static int ohci_intr1(ohci_softc_t *);
1779 1.53 augustss
1780 1.182.12.1 itohy #if defined(__NetBSD__) || defined(__OpenBSD__)
1781 1.1 augustss int
1782 1.182.12.1 itohy #elif defined(__FreeBSD__)
1783 1.182.12.1 itohy void
1784 1.182.12.1 itohy #endif
1785 1.91 augustss ohci_intr(void *p)
1786 1.1 augustss {
1787 1.1 augustss ohci_softc_t *sc = p;
1788 1.111 augustss
1789 1.116 augustss if (sc == NULL || sc->sc_dying)
1790 1.182.12.1 itohy #if defined(__NetBSD__) || defined(__OpenBSD__)
1791 1.111 augustss return (0);
1792 1.182.12.1 itohy #elif defined(__FreeBSD__)
1793 1.182.12.1 itohy return;
1794 1.182.12.1 itohy #endif
1795 1.53 augustss
1796 1.53 augustss /* If we get an interrupt while polling, then just ignore it. */
1797 1.57 augustss if (sc->sc_bus.use_polling) {
1798 1.57 augustss #ifdef DIAGNOSTIC
1799 1.149 mycroft DPRINTFN(16, ("ohci_intr: ignored interrupt while polling\n"));
1800 1.57 augustss #endif
1801 1.154 joff /* for level triggered intrs, should do something to ack */
1802 1.155 perry OWRITE4(sc, OHCI_INTERRUPT_STATUS,
1803 1.154 joff OREAD4(sc, OHCI_INTERRUPT_STATUS));
1804 1.155 perry
1805 1.182.12.1 itohy #if defined(__NetBSD__) || defined(__OpenBSD__)
1806 1.53 augustss return (0);
1807 1.182.12.1 itohy #elif defined(__FreeBSD__)
1808 1.182.12.1 itohy return;
1809 1.182.12.1 itohy #endif
1810 1.57 augustss }
1811 1.53 augustss
1812 1.182.12.1 itohy #if defined(__NetBSD__) || defined(__OpenBSD__)
1813 1.182.12.1 itohy return
1814 1.182.12.1 itohy #endif
1815 1.182.12.1 itohy ohci_intr1(sc);
1816 1.53 augustss }
1817 1.53 augustss
1818 1.82 augustss Static int
1819 1.91 augustss ohci_intr1(ohci_softc_t *sc)
1820 1.53 augustss {
1821 1.1 augustss u_int32_t intrs, eintrs;
1822 1.1 augustss
1823 1.105 augustss DPRINTFN(14,("ohci_intr1: enter\n"));
1824 1.105 augustss
1825 1.15 augustss /* In case the interrupt occurs before initialization has completed. */
1826 1.34 augustss if (sc == NULL || sc->sc_hcca == NULL) {
1827 1.15 augustss #ifdef DIAGNOSTIC
1828 1.15 augustss printf("ohci_intr: sc->sc_hcca == NULL\n");
1829 1.15 augustss #endif
1830 1.15 augustss return (0);
1831 1.15 augustss }
1832 1.15 augustss
1833 1.157 mycroft intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS);
1834 1.182.12.1 itohy
1835 1.182.12.1 itohy if (intrs == 0) /* nothing to be done (PCI shared interrupt) */
1836 1.1 augustss return (0);
1837 1.55 augustss
1838 1.182.12.1 itohy /* Acknowledge */
1839 1.182.12.1 itohy OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs & ~(OHCI_MIE|OHCI_WDH));
1840 1.182.12.1 itohy
1841 1.1 augustss eintrs = intrs & sc->sc_eintrs;
1842 1.1 augustss if (!eintrs)
1843 1.1 augustss return (0);
1844 1.1 augustss
1845 1.45 augustss sc->sc_bus.intr_context++;
1846 1.44 augustss sc->sc_bus.no_intrs++;
1847 1.120 augustss DPRINTFN(7, ("ohci_intr: sc=%p intrs=0x%x(0x%x) eintrs=0x%x\n",
1848 1.1 augustss sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS),
1849 1.1 augustss (u_int)eintrs));
1850 1.1 augustss
1851 1.1 augustss if (eintrs & OHCI_SO) {
1852 1.100 augustss sc->sc_overrun_cnt++;
1853 1.100 augustss if (usbd_ratecheck(&sc->sc_overrun_ntc)) {
1854 1.100 augustss printf("%s: %u scheduling overruns\n",
1855 1.100 augustss USBDEVNAME(sc->sc_bus.bdev), sc->sc_overrun_cnt);
1856 1.100 augustss sc->sc_overrun_cnt = 0;
1857 1.100 augustss }
1858 1.1 augustss /* XXX do what */
1859 1.106 augustss eintrs &= ~OHCI_SO;
1860 1.1 augustss }
1861 1.1 augustss if (eintrs & OHCI_WDH) {
1862 1.157 mycroft /*
1863 1.157 mycroft * We block the interrupt below, and reenable it later from
1864 1.157 mycroft * ohci_softintr().
1865 1.157 mycroft */
1866 1.72 augustss usb_schedsoftintr(&sc->sc_bus);
1867 1.1 augustss }
1868 1.1 augustss if (eintrs & OHCI_RD) {
1869 1.33 augustss printf("%s: resume detect\n", USBDEVNAME(sc->sc_bus.bdev));
1870 1.1 augustss /* XXX process resume detect */
1871 1.1 augustss }
1872 1.1 augustss if (eintrs & OHCI_UE) {
1873 1.15 augustss printf("%s: unrecoverable error, controller halted\n",
1874 1.15 augustss USBDEVNAME(sc->sc_bus.bdev));
1875 1.1 augustss OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
1876 1.1 augustss /* XXX what else */
1877 1.1 augustss }
1878 1.1 augustss if (eintrs & OHCI_RHSC) {
1879 1.120 augustss /*
1880 1.157 mycroft * We block the interrupt below, and reenable it later from
1881 1.157 mycroft * a timeout.
1882 1.1 augustss */
1883 1.157 mycroft ohci_rhsc(sc, sc->sc_intrxfer);
1884 1.104 augustss /* Do not allow RHSC interrupts > 1 per second */
1885 1.182.12.1 itohy usb_callout(sc->sc_tmo_rhsc, hz, ohci_rhsc_enable, sc);
1886 1.1 augustss }
1887 1.1 augustss
1888 1.45 augustss sc->sc_bus.intr_context--;
1889 1.44 augustss
1890 1.106 augustss if (eintrs != 0) {
1891 1.157 mycroft /* Block unprocessed interrupts. */
1892 1.106 augustss OWRITE4(sc, OHCI_INTERRUPT_DISABLE, eintrs);
1893 1.106 augustss sc->sc_eintrs &= ~eintrs;
1894 1.157 mycroft DPRINTFN(1, ("%s: blocking intrs 0x%x\n",
1895 1.157 mycroft USBDEVNAME(sc->sc_bus.bdev), eintrs));
1896 1.106 augustss }
1897 1.1 augustss
1898 1.1 augustss return (1);
1899 1.1 augustss }
1900 1.1 augustss
1901 1.1 augustss void
1902 1.104 augustss ohci_rhsc_enable(void *v_sc)
1903 1.104 augustss {
1904 1.104 augustss ohci_softc_t *sc = v_sc;
1905 1.129 augustss int s;
1906 1.104 augustss
1907 1.129 augustss s = splhardusb();
1908 1.157 mycroft sc->sc_eintrs |= OHCI_RHSC;
1909 1.157 mycroft OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_RHSC);
1910 1.129 augustss splx(s);
1911 1.1 augustss }
1912 1.1 augustss
1913 1.182.12.1 itohy #ifdef USB_DEBUG
1914 1.166 drochner const char *ohci_cc_strs[] = {
1915 1.13 augustss "NO_ERROR",
1916 1.13 augustss "CRC",
1917 1.13 augustss "BIT_STUFFING",
1918 1.13 augustss "DATA_TOGGLE_MISMATCH",
1919 1.13 augustss "STALL",
1920 1.13 augustss "DEVICE_NOT_RESPONDING",
1921 1.13 augustss "PID_CHECK_FAILURE",
1922 1.13 augustss "UNEXPECTED_PID",
1923 1.13 augustss "DATA_OVERRUN",
1924 1.13 augustss "DATA_UNDERRUN",
1925 1.13 augustss "BUFFER_OVERRUN",
1926 1.13 augustss "BUFFER_UNDERRUN",
1927 1.67 augustss "reserved",
1928 1.67 augustss "reserved",
1929 1.67 augustss "NOT_ACCESSED",
1930 1.182.12.1 itohy "NOT_ACCESSED"
1931 1.13 augustss };
1932 1.13 augustss #endif
1933 1.13 augustss
1934 1.1 augustss void
1935 1.157 mycroft ohci_softintr(void *v)
1936 1.83 augustss {
1937 1.157 mycroft ohci_softc_t *sc = v;
1938 1.157 mycroft ohci_soft_itd_t *sitd, *sidone, *sitdnext;
1939 1.182.12.3 itohy ohci_soft_td_t *std, *sdone, *stdnext, *p;
1940 1.157 mycroft usbd_xfer_handle xfer;
1941 1.157 mycroft struct ohci_pipe *opipe;
1942 1.157 mycroft int len, cc, s;
1943 1.182.12.1 itohy int i, j, iframes;
1944 1.157 mycroft ohci_physaddr_t done;
1945 1.182.12.3 itohy #if 0
1946 1.182.12.3 itohy int isread, is_mbuf;
1947 1.182.12.3 itohy #endif
1948 1.157 mycroft
1949 1.157 mycroft DPRINTFN(10,("ohci_softintr: enter\n"));
1950 1.157 mycroft
1951 1.157 mycroft sc->sc_bus.intr_context++;
1952 1.157 mycroft
1953 1.157 mycroft s = splhardusb();
1954 1.182.12.3 itohy USB_MEM_SYNC2(&sc->sc_dmatag, &sc->sc_hccadma,
1955 1.182.12.3 itohy offsetof(struct ohci_hcca, hcca_done_head),
1956 1.182.12.3 itohy sizeof(sc->sc_hcca->hcca_done_head),
1957 1.182.12.1 itohy BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1958 1.168 augustss done = O32TOH(sc->sc_hcca->hcca_done_head) & ~OHCI_DONE_INTRS;
1959 1.157 mycroft sc->sc_hcca->hcca_done_head = 0;
1960 1.182.12.3 itohy USB_MEM_SYNC2(&sc->sc_dmatag, &sc->sc_hccadma,
1961 1.182.12.3 itohy offsetof(struct ohci_hcca, hcca_done_head),
1962 1.182.12.3 itohy sizeof(sc->sc_hcca->hcca_done_head),
1963 1.182.12.3 itohy BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1964 1.157 mycroft OWRITE4(sc, OHCI_INTERRUPT_STATUS, OHCI_WDH);
1965 1.157 mycroft sc->sc_eintrs |= OHCI_WDH;
1966 1.157 mycroft OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_WDH);
1967 1.157 mycroft splx(s);
1968 1.83 augustss
1969 1.83 augustss /* Reverse the done list. */
1970 1.83 augustss for (sdone = NULL, sidone = NULL; done != 0; ) {
1971 1.182.12.1 itohy std = ohci_find_td(sc, done);
1972 1.83 augustss if (std != NULL) {
1973 1.182.12.1 itohy OHCI_STD_SYNC(sc, std,
1974 1.182.12.1 itohy BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1975 1.83 augustss std->dnext = sdone;
1976 1.168 augustss done = O32TOH(std->td.td_nexttd);
1977 1.83 augustss sdone = std;
1978 1.83 augustss DPRINTFN(10,("add TD %p\n", std));
1979 1.83 augustss continue;
1980 1.83 augustss }
1981 1.182.12.1 itohy sitd = ohci_find_itd(sc, done);
1982 1.83 augustss if (sitd != NULL) {
1983 1.182.12.1 itohy OHCI_SITD_SYNC(sc, sitd,
1984 1.182.12.1 itohy BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1985 1.83 augustss sitd->dnext = sidone;
1986 1.168 augustss done = O32TOH(sitd->itd.itd_nextitd);
1987 1.83 augustss sidone = sitd;
1988 1.83 augustss DPRINTFN(5,("add ITD %p\n", sitd));
1989 1.83 augustss continue;
1990 1.83 augustss }
1991 1.157 mycroft panic("ohci_softintr: addr 0x%08lx not found", (u_long)done);
1992 1.83 augustss }
1993 1.83 augustss
1994 1.105 augustss DPRINTFN(10,("ohci_softintr: sdone=%p sidone=%p\n", sdone, sidone));
1995 1.1 augustss
1996 1.182.12.1 itohy #ifdef USB_DEBUG
1997 1.1 augustss if (ohcidebug > 10) {
1998 1.41 augustss DPRINTF(("ohci_process_done: TD done:\n"));
1999 1.168 augustss ohci_dump_tds(sc, sdone);
2000 1.1 augustss }
2001 1.1 augustss #endif
2002 1.1 augustss
2003 1.48 augustss for (std = sdone; std; std = stdnext) {
2004 1.53 augustss xfer = std->xfer;
2005 1.48 augustss stdnext = std->dnext;
2006 1.53 augustss DPRINTFN(10, ("ohci_process_done: std=%p xfer=%p hcpriv=%p\n",
2007 1.182.12.1 itohy std, xfer, (xfer ? xfer->hcpriv : NULL)));
2008 1.71 augustss if (xfer == NULL) {
2009 1.117 augustss /*
2010 1.117 augustss * xfer == NULL: There seems to be no xfer associated
2011 1.71 augustss * with this TD. It is tailp that happened to end up on
2012 1.71 augustss * the done queue.
2013 1.71 augustss */
2014 1.71 augustss continue;
2015 1.71 augustss }
2016 1.53 augustss if (xfer->status == USBD_CANCELLED ||
2017 1.53 augustss xfer->status == USBD_TIMEOUT) {
2018 1.34 augustss DPRINTF(("ohci_process_done: cancel/timeout %p\n",
2019 1.53 augustss xfer));
2020 1.38 augustss /* Handled by abort routine. */
2021 1.83 augustss continue;
2022 1.83 augustss }
2023 1.141 mycroft
2024 1.141 mycroft len = std->len;
2025 1.141 mycroft if (std->td.td_cbp != 0)
2026 1.168 augustss len -= O32TOH(std->td.td_be) -
2027 1.168 augustss O32TOH(std->td.td_cbp) + 1;
2028 1.141 mycroft DPRINTFN(10, ("ohci_process_done: len=%d, flags=0x%x\n", len,
2029 1.141 mycroft std->flags));
2030 1.141 mycroft if (std->flags & OHCI_ADD_LEN)
2031 1.141 mycroft xfer->actlen += len;
2032 1.141 mycroft
2033 1.182.12.3 itohy #if 0
2034 1.182.12.3 itohy isread = usbd_xfer_isread(xfer);
2035 1.182.12.3 itohy is_mbuf = xfer->rqflags & URQ_DEV_MAP_MBUF;
2036 1.182.12.3 itohy #endif
2037 1.182.12.3 itohy
2038 1.168 augustss cc = OHCI_TD_GET_CC(O32TOH(std->td.td_flags));
2039 1.182.12.1 itohy if (cc != OHCI_CC_NO_ERROR) {
2040 1.48 augustss /*
2041 1.48 augustss * Endpoint is halted. First unlink all the TDs
2042 1.48 augustss * belonging to the failed transfer, and then restart
2043 1.48 augustss * the endpoint.
2044 1.48 augustss */
2045 1.134 toshii opipe = (struct ohci_pipe *)xfer->pipe;
2046 1.48 augustss
2047 1.71 augustss DPRINTFN(15,("ohci_process_done: error cc=%d (%s)\n",
2048 1.168 augustss OHCI_TD_GET_CC(O32TOH(std->td.td_flags)),
2049 1.168 augustss ohci_cc_strs[OHCI_TD_GET_CC(O32TOH(std->td.td_flags))]));
2050 1.182.12.1 itohy usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
2051 1.182.12.1 itohy usb_rem_task(OXFER(xfer)->xfer.pipe->device,
2052 1.182.12.1 itohy &OXFER(xfer)->abort_task);
2053 1.182.12.1 itohy
2054 1.182.12.1 itohy /* Remove all this xfer's TDs from the done queue. */
2055 1.182.12.1 itohy for (p = std; p->dnext != NULL; p = p->dnext) {
2056 1.182.12.1 itohy if (p->dnext->xfer != xfer)
2057 1.182.12.1 itohy continue;
2058 1.182.12.1 itohy p->dnext = p->dnext->dnext;
2059 1.182.12.1 itohy }
2060 1.182.12.1 itohy /* The next TD may have been removed. */
2061 1.182.12.1 itohy stdnext = std->dnext;
2062 1.48 augustss
2063 1.182.12.3 itohy #if 0
2064 1.182.12.1 itohy /* Remove all TDs belonging to this xfer. */
2065 1.182.12.1 itohy for (p = xfer->hcpriv; p->xfer == xfer; p = n) {
2066 1.1 augustss n = p->nexttd;
2067 1.182.12.3 itohy #if 1
2068 1.182.12.3 itohy if (p->ad.aux_len)
2069 1.182.12.3 itohy ohci_aux_dma_complete(&p->ad,
2070 1.182.12.3 itohy &OXFER(xfer)->aux, is_mbuf, isread);
2071 1.182.12.3 itohy #endif
2072 1.1 augustss ohci_free_std(sc, p);
2073 1.1 augustss }
2074 1.48 augustss
2075 1.16 augustss /* clear halt */
2076 1.182.12.3 itohy OHCI_SED_SYNC_POST(sc, opipe->sed);
2077 1.182.12.1 itohy dmaadr = OHCI_STD_DMAADDR(p);
2078 1.182.12.1 itohy opipe->sed->ed.ed_headp = HTOO32(dmaadr);
2079 1.182.12.3 itohy OHCI_SED_SYNC2(sc, opipe->sed,
2080 1.182.12.3 itohy offsetof(ohci_ed_t, ed_headp),
2081 1.182.12.3 itohy sizeof(ohci_physaddr_t),
2082 1.182.12.1 itohy BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
2083 1.1 augustss OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
2084 1.182.12.3 itohy #endif
2085 1.48 augustss
2086 1.1 augustss if (cc == OHCI_CC_STALL)
2087 1.53 augustss xfer->status = USBD_STALLED;
2088 1.1 augustss else
2089 1.53 augustss xfer->status = USBD_IOERROR;
2090 1.182.12.3 itohy ohci_transfer_complete(xfer, 1);
2091 1.182.12.1 itohy continue;
2092 1.182.12.1 itohy }
2093 1.182.12.1 itohy /*
2094 1.182.12.1 itohy * Skip intermediate TDs. They remain linked from
2095 1.182.12.1 itohy * xfer->hcpriv and we free them when the transfer completes.
2096 1.182.12.1 itohy */
2097 1.182.12.1 itohy if ((std->flags & OHCI_CALL_DONE) == 0)
2098 1.182.12.1 itohy continue;
2099 1.182.12.1 itohy
2100 1.182.12.1 itohy /* Normal transfer completion */
2101 1.182.12.1 itohy usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
2102 1.182.12.1 itohy usb_rem_task(OXFER(xfer)->xfer.pipe->device,
2103 1.182.12.1 itohy &OXFER(xfer)->abort_task);
2104 1.182.12.3 itohy #if 0
2105 1.182.12.1 itohy for (p = xfer->hcpriv; p->xfer == xfer; p = n) {
2106 1.182.12.1 itohy n = p->nexttd;
2107 1.182.12.3 itohy #if 1
2108 1.182.12.3 itohy if (p->ad.aux_len)
2109 1.182.12.3 itohy ohci_aux_dma_complete(&p->ad,
2110 1.182.12.3 itohy &OXFER(xfer)->aux, is_mbuf, isread);
2111 1.182.12.3 itohy #endif
2112 1.182.12.1 itohy ohci_free_std(sc, p);
2113 1.1 augustss }
2114 1.182.12.3 itohy #endif
2115 1.182.12.1 itohy xfer->status = USBD_NORMAL_COMPLETION;
2116 1.182.12.3 itohy #if 0 /* will be done in ohci_transfer_complete() */
2117 1.182.12.1 itohy xfer->hcpriv = NULL;
2118 1.182.12.3 itohy #endif
2119 1.182.12.3 itohy ohci_transfer_complete(xfer, 0);
2120 1.1 augustss }
2121 1.72 augustss
2122 1.182.12.1 itohy #ifdef USB_DEBUG
2123 1.83 augustss if (ohcidebug > 10) {
2124 1.105 augustss DPRINTF(("ohci_softintr: ITD done:\n"));
2125 1.168 augustss ohci_dump_itds(sc, sidone);
2126 1.83 augustss }
2127 1.83 augustss #endif
2128 1.83 augustss
2129 1.83 augustss for (sitd = sidone; sitd != NULL; sitd = sitdnext) {
2130 1.83 augustss xfer = sitd->xfer;
2131 1.83 augustss sitdnext = sitd->dnext;
2132 1.182.12.1 itohy sitd->flags |= OHCI_ITD_INTFIN;
2133 1.83 augustss DPRINTFN(1, ("ohci_process_done: sitd=%p xfer=%p hcpriv=%p\n",
2134 1.83 augustss sitd, xfer, xfer ? xfer->hcpriv : 0));
2135 1.83 augustss if (xfer == NULL)
2136 1.83 augustss continue;
2137 1.83 augustss if (xfer->status == USBD_CANCELLED ||
2138 1.83 augustss xfer->status == USBD_TIMEOUT) {
2139 1.83 augustss DPRINTF(("ohci_process_done: cancel/timeout %p\n",
2140 1.83 augustss xfer));
2141 1.83 augustss /* Handled by abort routine. */
2142 1.83 augustss continue;
2143 1.83 augustss }
2144 1.182.12.1 itohy if (xfer->pipe)
2145 1.182.12.1 itohy if (xfer->pipe->aborting)
2146 1.182.12.1 itohy continue; /*Ignore.*/
2147 1.83 augustss #ifdef DIAGNOSTIC
2148 1.83 augustss if (sitd->isdone)
2149 1.83 augustss printf("ohci_softintr: sitd=%p is done\n", sitd);
2150 1.83 augustss sitd->isdone = 1;
2151 1.83 augustss #endif
2152 1.182.12.1 itohy opipe = (struct ohci_pipe *)xfer->pipe;
2153 1.182.12.1 itohy if (opipe->aborting)
2154 1.182.12.1 itohy continue;
2155 1.182.12.1 itohy
2156 1.134 toshii if (sitd->flags & OHCI_CALL_DONE) {
2157 1.134 toshii ohci_soft_itd_t *next;
2158 1.182.12.3 itohy int isread = opipe->pipe.endpoint->edesc->bEndpointAddress & UE_DIR_IN;
2159 1.134 toshii
2160 1.134 toshii opipe->u.iso.inuse -= xfer->nframes;
2161 1.134 toshii xfer->status = USBD_NORMAL_COMPLETION;
2162 1.182.12.1 itohy for (i = 0, sitd = xfer->hcpriv;;sitd = next) {
2163 1.134 toshii next = sitd->nextitd;
2164 1.182.12.3 itohy cc = OHCI_ITD_GET_CC(O32TOH(sitd->itd.itd_flags));
2165 1.182.12.3 itohy if (cc != OHCI_CC_NO_ERROR) {
2166 1.134 toshii xfer->status = USBD_IOERROR;
2167 1.182.12.3 itohy }
2168 1.182.12.1 itohy
2169 1.182.12.3 itohy {
2170 1.182.12.3 itohy iframes = OHCI_ITD_GET_FC(O32TOH(sitd->itd.itd_flags));
2171 1.134 toshii for (j = 0; j < iframes; i++, j++) {
2172 1.182.12.1 itohy len = O16TOH(sitd->itd.itd_offset[j]);
2173 1.182.12.3 itohy #if 1
2174 1.182.12.3 itohy cc = OHCI_ITD_PSW_GET_CC(len);
2175 1.182.12.3 itohy switch (cc &
2176 1.182.12.3 itohy OHCI_CC_NOT_ACCESSED_MASK) {
2177 1.182.12.3 itohy case OHCI_CC_NOT_ACCESSED:
2178 1.182.12.3 itohy len = 0;
2179 1.182.12.3 itohy break;
2180 1.182.12.3 itohy case OHCI_CC_BUFFER_OVERRUN:
2181 1.182.12.3 itohy /* or BUFFER_UNDERRUN */
2182 1.182.12.3 itohy xfer->status = USBD_IOERROR;
2183 1.182.12.3 itohy /* FALLTHROUGH */
2184 1.182.12.3 itohy default:
2185 1.182.12.3 itohy len = OHCI_ITD_PSW_LENGTH(len);
2186 1.182.12.3 itohy break;
2187 1.182.12.3 itohy }
2188 1.182.12.3 itohy #endif
2189 1.182.12.3 itohy #if 0
2190 1.182.12.1 itohy len =
2191 1.182.12.1 itohy ((OHCI_ITD_PSW_GET_CC(len) &
2192 1.158 toshii OHCI_CC_NOT_ACCESSED_MASK)
2193 1.182.12.1 itohy == OHCI_CC_NOT_ACCESSED) ?
2194 1.182.12.1 itohy 0 :
2195 1.182.12.1 itohy OHCI_ITD_PSW_LENGTH(len);
2196 1.182.12.3 itohy #endif
2197 1.182.12.3 itohy if (isread)
2198 1.182.12.3 itohy xfer->frlengths[i] = len;
2199 1.134 toshii }
2200 1.134 toshii }
2201 1.134 toshii if (sitd->flags & OHCI_CALL_DONE)
2202 1.134 toshii break;
2203 1.182.12.1 itohy }
2204 1.182.12.3 itohy if (xfer->status != USBD_NORMAL_COMPLETION) {
2205 1.182.12.3 itohy /* resync frame */
2206 1.182.12.3 itohy opipe->u.iso.next = -1;
2207 1.83 augustss }
2208 1.182.12.3 itohy #if 1
2209 1.182.12.3 itohy /* XXX? */
2210 1.182.12.3 itohy xfer->status = USBD_NORMAL_COMPLETION;
2211 1.182.12.3 itohy #endif
2212 1.134 toshii
2213 1.182.12.3 itohy ohci_transfer_complete(xfer, 0);
2214 1.83 augustss }
2215 1.83 augustss }
2216 1.83 augustss
2217 1.131 augustss #ifdef USB_USE_SOFTINTR
2218 1.119 augustss if (sc->sc_softwake) {
2219 1.119 augustss sc->sc_softwake = 0;
2220 1.119 augustss wakeup(&sc->sc_softwake);
2221 1.119 augustss }
2222 1.131 augustss #endif /* USB_USE_SOFTINTR */
2223 1.119 augustss
2224 1.72 augustss sc->sc_bus.intr_context--;
2225 1.105 augustss DPRINTFN(10,("ohci_softintr: done:\n"));
2226 1.1 augustss }
2227 1.1 augustss
2228 1.1 augustss void
2229 1.179 christos ohci_device_ctrl_done(usbd_xfer_handle xfer)
2230 1.1 augustss {
2231 1.140 gson DPRINTFN(10,("ohci_device_ctrl_done: xfer=%p\n", xfer));
2232 1.1 augustss
2233 1.38 augustss #ifdef DIAGNOSTIC
2234 1.53 augustss if (!(xfer->rqflags & URQ_REQUEST)) {
2235 1.140 gson panic("ohci_device_ctrl_done: not a request");
2236 1.1 augustss }
2237 1.38 augustss #endif
2238 1.1 augustss }
2239 1.1 augustss
2240 1.1 augustss void
2241 1.91 augustss ohci_device_intr_done(usbd_xfer_handle xfer)
2242 1.1 augustss {
2243 1.53 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
2244 1.38 augustss ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
2245 1.182.12.1 itohy usbd_status err;
2246 1.1 augustss
2247 1.140 gson DPRINTFN(10,("ohci_device_intr_done: xfer=%p, actlen=%d\n",
2248 1.53 augustss xfer, xfer->actlen));
2249 1.1 augustss
2250 1.53 augustss if (xfer->pipe->repeat) {
2251 1.182.12.1 itohy err = ohci_device_intr_insert(sc, xfer);
2252 1.182.12.1 itohy if (err) {
2253 1.182.12.1 itohy xfer->status = err;
2254 1.1 augustss return;
2255 1.1 augustss }
2256 1.1 augustss }
2257 1.1 augustss }
2258 1.1 augustss
2259 1.1 augustss void
2260 1.179 christos ohci_device_bulk_done(usbd_xfer_handle xfer)
2261 1.3 augustss {
2262 1.140 gson DPRINTFN(10,("ohci_device_bulk_done: xfer=%p, actlen=%d\n",
2263 1.53 augustss xfer, xfer->actlen));
2264 1.3 augustss }
2265 1.3 augustss
2266 1.3 augustss void
2267 1.91 augustss ohci_rhsc(ohci_softc_t *sc, usbd_xfer_handle xfer)
2268 1.1 augustss {
2269 1.1 augustss usbd_pipe_handle pipe;
2270 1.1 augustss u_char *p;
2271 1.1 augustss int i, m;
2272 1.1 augustss int hstatus;
2273 1.1 augustss
2274 1.1 augustss hstatus = OREAD4(sc, OHCI_RH_STATUS);
2275 1.120 augustss DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n",
2276 1.53 augustss sc, xfer, hstatus));
2277 1.1 augustss
2278 1.53 augustss if (xfer == NULL) {
2279 1.1 augustss /* Just ignore the change. */
2280 1.1 augustss return;
2281 1.1 augustss }
2282 1.1 augustss
2283 1.53 augustss pipe = xfer->pipe;
2284 1.1 augustss
2285 1.182.12.1 itohy p = xfer->hcbuffer;
2286 1.53 augustss m = min(sc->sc_noport, xfer->length * 8 - 1);
2287 1.53 augustss memset(p, 0, xfer->length);
2288 1.1 augustss for (i = 1; i <= m; i++) {
2289 1.87 augustss /* Pick out CHANGE bits from the status reg. */
2290 1.1 augustss if (OREAD4(sc, OHCI_RH_PORT_STATUS(i)) >> 16)
2291 1.1 augustss p[i/8] |= 1 << (i%8);
2292 1.1 augustss }
2293 1.1 augustss DPRINTF(("ohci_rhsc: change=0x%02x\n", *p));
2294 1.53 augustss xfer->actlen = xfer->length;
2295 1.53 augustss xfer->status = USBD_NORMAL_COMPLETION;
2296 1.1 augustss
2297 1.182.12.3 itohy usb_transfer_complete(xfer);
2298 1.38 augustss }
2299 1.38 augustss
2300 1.38 augustss void
2301 1.179 christos ohci_root_intr_done(usbd_xfer_handle xfer)
2302 1.65 augustss {
2303 1.65 augustss }
2304 1.65 augustss
2305 1.65 augustss void
2306 1.179 christos ohci_root_ctrl_done(usbd_xfer_handle xfer)
2307 1.38 augustss {
2308 1.1 augustss }
2309 1.1 augustss
2310 1.1 augustss /*
2311 1.1 augustss * Wait here until controller claims to have an interrupt.
2312 1.1 augustss * Then call ohci_intr and return. Use timeout to avoid waiting
2313 1.1 augustss * too long.
2314 1.1 augustss */
2315 1.1 augustss void
2316 1.91 augustss ohci_waitintr(ohci_softc_t *sc, usbd_xfer_handle xfer)
2317 1.1 augustss {
2318 1.163 augustss int timo;
2319 1.1 augustss u_int32_t intrs;
2320 1.1 augustss
2321 1.53 augustss xfer->status = USBD_IN_PROGRESS;
2322 1.163 augustss for (timo = xfer->timeout; timo >= 0; timo--) {
2323 1.20 augustss usb_delay_ms(&sc->sc_bus, 1);
2324 1.116 augustss if (sc->sc_dying)
2325 1.116 augustss break;
2326 1.1 augustss intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs;
2327 1.27 augustss DPRINTFN(15,("ohci_waitintr: 0x%04x\n", intrs));
2328 1.182.12.1 itohy #ifdef USB_DEBUG
2329 1.1 augustss if (ohcidebug > 15)
2330 1.1 augustss ohci_dumpregs(sc);
2331 1.1 augustss #endif
2332 1.1 augustss if (intrs) {
2333 1.53 augustss ohci_intr1(sc);
2334 1.53 augustss if (xfer->status != USBD_IN_PROGRESS)
2335 1.1 augustss return;
2336 1.1 augustss }
2337 1.1 augustss }
2338 1.15 augustss
2339 1.15 augustss /* Timeout */
2340 1.1 augustss DPRINTF(("ohci_waitintr: timeout\n"));
2341 1.53 augustss xfer->status = USBD_TIMEOUT;
2342 1.182.12.3 itohy ohci_transfer_complete(xfer, 0);
2343 1.5 augustss }
2344 1.5 augustss
2345 1.5 augustss void
2346 1.91 augustss ohci_poll(struct usbd_bus *bus)
2347 1.5 augustss {
2348 1.5 augustss ohci_softc_t *sc = (ohci_softc_t *)bus;
2349 1.182.12.1 itohy #ifdef USB_DEBUG
2350 1.105 augustss static int last;
2351 1.105 augustss int new;
2352 1.105 augustss new = OREAD4(sc, OHCI_INTERRUPT_STATUS);
2353 1.105 augustss if (new != last) {
2354 1.105 augustss DPRINTFN(10,("ohci_poll: intrs=0x%04x\n", new));
2355 1.105 augustss last = new;
2356 1.105 augustss }
2357 1.105 augustss #endif
2358 1.5 augustss
2359 1.5 augustss if (OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs)
2360 1.53 augustss ohci_intr1(sc);
2361 1.1 augustss }
2362 1.1 augustss
2363 1.1 augustss usbd_status
2364 1.91 augustss ohci_device_request(usbd_xfer_handle xfer)
2365 1.1 augustss {
2366 1.53 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
2367 1.53 augustss usb_device_request_t *req = &xfer->request;
2368 1.1 augustss usbd_device_handle dev = opipe->pipe.device;
2369 1.1 augustss ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
2370 1.77 augustss ohci_soft_td_t *setup, *stat, *next, *tail;
2371 1.1 augustss ohci_soft_ed_t *sed;
2372 1.1 augustss int isread;
2373 1.1 augustss int len;
2374 1.53 augustss usbd_status err;
2375 1.1 augustss int s;
2376 1.182.12.1 itohy ohci_physaddr_t dmaadr;
2377 1.1 augustss
2378 1.1 augustss isread = req->bmRequestType & UT_READ;
2379 1.1 augustss len = UGETW(req->wLength);
2380 1.1 augustss
2381 1.182.12.1 itohy DPRINTFN(3,("ohci_device_request: type=0x%02x, request=0x%02x, "
2382 1.14 augustss "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n",
2383 1.1 augustss req->bmRequestType, req->bRequest, UGETW(req->wValue),
2384 1.182.12.1 itohy UGETW(req->wIndex), len, dev->address,
2385 1.1 augustss opipe->pipe.endpoint->edesc->bEndpointAddress));
2386 1.1 augustss
2387 1.60 augustss setup = opipe->tail.td;
2388 1.1 augustss stat = ohci_alloc_std(sc);
2389 1.53 augustss if (stat == NULL) {
2390 1.53 augustss err = USBD_NOMEM;
2391 1.1 augustss goto bad1;
2392 1.1 augustss }
2393 1.1 augustss tail = ohci_alloc_std(sc);
2394 1.53 augustss if (tail == NULL) {
2395 1.53 augustss err = USBD_NOMEM;
2396 1.1 augustss goto bad2;
2397 1.1 augustss }
2398 1.55 augustss tail->xfer = NULL;
2399 1.1 augustss
2400 1.1 augustss sed = opipe->sed;
2401 1.1 augustss opipe->u.ctl.length = len;
2402 1.77 augustss next = stat;
2403 1.77 augustss
2404 1.1 augustss /* Set up data transaction */
2405 1.1 augustss if (len != 0) {
2406 1.77 augustss ohci_soft_td_t *std = stat;
2407 1.77 augustss
2408 1.77 augustss err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer,
2409 1.77 augustss std, &stat);
2410 1.77 augustss if (err)
2411 1.1 augustss goto bad3;
2412 1.182.12.1 itohy OHCI_STD_SYNC(sc, stat,
2413 1.182.12.1 itohy BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
2414 1.182.12.1 itohy stat = stat->nexttd; /* point at free TD */
2415 1.77 augustss /* Start toggle at 1 and then use the carried toggle. */
2416 1.168 augustss std->td.td_flags &= HTOO32(~OHCI_TD_TOGGLE_MASK);
2417 1.168 augustss std->td.td_flags |= HTOO32(OHCI_TD_TOGGLE_1);
2418 1.34 augustss }
2419 1.1 augustss
2420 1.123 augustss memcpy(KERNADDR(&opipe->u.ctl.reqdma, 0), req, sizeof *req);
2421 1.1 augustss
2422 1.168 augustss setup->td.td_flags = HTOO32(OHCI_TD_SETUP | OHCI_TD_NOCC |
2423 1.182.12.1 itohy OHCI_TD_TOGGLE_0 | OHCI_TD_SET_DI(6));
2424 1.168 augustss setup->td.td_cbp = HTOO32(DMAADDR(&opipe->u.ctl.reqdma, 0));
2425 1.1 augustss setup->nexttd = next;
2426 1.182.12.1 itohy dmaadr = OHCI_STD_DMAADDR(next);
2427 1.182.12.1 itohy setup->td.td_nexttd = HTOO32(dmaadr);
2428 1.168 augustss setup->td.td_be = HTOO32(O32TOH(setup->td.td_cbp) + sizeof *req - 1);
2429 1.77 augustss setup->len = 0;
2430 1.53 augustss setup->xfer = xfer;
2431 1.34 augustss setup->flags = 0;
2432 1.53 augustss xfer->hcpriv = setup;
2433 1.182.12.1 itohy OHCI_STD_SYNC(sc, setup, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
2434 1.1 augustss
2435 1.168 augustss stat->td.td_flags = HTOO32(
2436 1.77 augustss (isread ? OHCI_TD_OUT : OHCI_TD_IN) |
2437 1.77 augustss OHCI_TD_NOCC | OHCI_TD_TOGGLE_1 | OHCI_TD_SET_DI(1));
2438 1.39 augustss stat->td.td_cbp = 0;
2439 1.1 augustss stat->nexttd = tail;
2440 1.182.12.1 itohy dmaadr = OHCI_STD_DMAADDR(tail);
2441 1.182.12.1 itohy stat->td.td_nexttd = HTOO32(dmaadr);
2442 1.39 augustss stat->td.td_be = 0;
2443 1.77 augustss stat->flags = OHCI_CALL_DONE;
2444 1.1 augustss stat->len = 0;
2445 1.53 augustss stat->xfer = xfer;
2446 1.182.12.1 itohy OHCI_STD_SYNC(sc, stat, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
2447 1.1 augustss
2448 1.182.12.1 itohy #ifdef USB_DEBUG
2449 1.1 augustss if (ohcidebug > 5) {
2450 1.41 augustss DPRINTF(("ohci_device_request:\n"));
2451 1.168 augustss ohci_dump_ed(sc, sed);
2452 1.168 augustss ohci_dump_tds(sc, setup);
2453 1.1 augustss }
2454 1.1 augustss #endif
2455 1.1 augustss
2456 1.1 augustss /* Insert ED in schedule */
2457 1.1 augustss s = splusb();
2458 1.182.12.1 itohy dmaadr = OHCI_STD_DMAADDR(tail);
2459 1.182.12.1 itohy sed->ed.ed_tailp = HTOO32(dmaadr);
2460 1.182.12.1 itohy OHCI_SED_SYNC(sc, sed, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
2461 1.60 augustss opipe->tail.td = tail;
2462 1.1 augustss OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF);
2463 1.53 augustss if (xfer->timeout && !sc->sc_bus.use_polling) {
2464 1.182.12.1 itohy usb_callout(xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
2465 1.80 augustss ohci_timeout, xfer);
2466 1.15 augustss }
2467 1.1 augustss splx(s);
2468 1.1 augustss
2469 1.182.12.1 itohy #ifdef USB_DEBUG
2470 1.113 augustss if (ohcidebug > 20) {
2471 1.77 augustss delay(10000);
2472 1.41 augustss DPRINTF(("ohci_device_request: status=%x\n",
2473 1.41 augustss OREAD4(sc, OHCI_COMMAND_STATUS)));
2474 1.113 augustss ohci_dumpregs(sc);
2475 1.113 augustss printf("ctrl head:\n");
2476 1.168 augustss ohci_dump_ed(sc, sc->sc_ctrl_head);
2477 1.113 augustss printf("sed:\n");
2478 1.168 augustss ohci_dump_ed(sc, sed);
2479 1.168 augustss ohci_dump_tds(sc, setup);
2480 1.1 augustss }
2481 1.1 augustss #endif
2482 1.1 augustss
2483 1.1 augustss return (USBD_NORMAL_COMPLETION);
2484 1.1 augustss
2485 1.1 augustss bad3:
2486 1.1 augustss ohci_free_std(sc, tail);
2487 1.1 augustss bad2:
2488 1.1 augustss ohci_free_std(sc, stat);
2489 1.1 augustss bad1:
2490 1.53 augustss return (err);
2491 1.1 augustss }
2492 1.1 augustss
2493 1.1 augustss /*
2494 1.1 augustss * Add an ED to the schedule. Called at splusb().
2495 1.1 augustss */
2496 1.1 augustss void
2497 1.168 augustss ohci_add_ed(ohci_softc_t *sc, ohci_soft_ed_t *sed, ohci_soft_ed_t *head)
2498 1.1 augustss {
2499 1.182.12.1 itohy ohci_physaddr_t dmaadr;
2500 1.182.12.1 itohy
2501 1.113 augustss DPRINTFN(8,("ohci_add_ed: sed=%p head=%p\n", sed, head));
2502 1.113 augustss
2503 1.46 augustss SPLUSBCHECK;
2504 1.1 augustss sed->next = head->next;
2505 1.39 augustss sed->ed.ed_nexted = head->ed.ed_nexted;
2506 1.182.12.3 itohy OHCI_SED_SYNC2(sc, sed,
2507 1.182.12.3 itohy offsetof(ohci_ed_t, ed_nexted), sizeof(ohci_physaddr_t),
2508 1.182.12.3 itohy BUS_DMASYNC_PREWRITE);
2509 1.1 augustss head->next = sed;
2510 1.182.12.1 itohy dmaadr = OHCI_SED_DMAADDR(sed);
2511 1.182.12.1 itohy head->ed.ed_nexted = HTOO32(dmaadr);
2512 1.182.12.3 itohy OHCI_SED_SYNC2(sc, head,
2513 1.182.12.3 itohy offsetof(ohci_ed_t, ed_nexted), sizeof(ohci_physaddr_t),
2514 1.182.12.3 itohy BUS_DMASYNC_PREWRITE);
2515 1.1 augustss }
2516 1.1 augustss
2517 1.1 augustss /*
2518 1.3 augustss * Remove an ED from the schedule. Called at splusb().
2519 1.3 augustss */
2520 1.3 augustss void
2521 1.182.12.3 itohy ohci_rem_ed(ohci_softc_t *sc, ohci_soft_ed_t *sed, ohci_soft_ed_t *head)
2522 1.3 augustss {
2523 1.120 augustss ohci_soft_ed_t *p;
2524 1.3 augustss
2525 1.46 augustss SPLUSBCHECK;
2526 1.46 augustss
2527 1.3 augustss /* XXX */
2528 1.133 toshii for (p = head; p != NULL && p->next != sed; p = p->next)
2529 1.3 augustss ;
2530 1.55 augustss if (p == NULL)
2531 1.128 provos panic("ohci_rem_ed: ED not found");
2532 1.3 augustss p->next = sed->next;
2533 1.39 augustss p->ed.ed_nexted = sed->ed.ed_nexted;
2534 1.182.12.3 itohy OHCI_SED_SYNC2(sc, p,
2535 1.182.12.3 itohy offsetof(ohci_ed_t, ed_nexted), sizeof(ohci_physaddr_t),
2536 1.182.12.3 itohy BUS_DMASYNC_PREWRITE);
2537 1.3 augustss }
2538 1.3 augustss
2539 1.3 augustss /*
2540 1.1 augustss * When a transfer is completed the TD is added to the done queue by
2541 1.1 augustss * the host controller. This queue is the processed by software.
2542 1.1 augustss * Unfortunately the queue contains the physical address of the TD
2543 1.9 augustss * and we have no simple way to translate this back to a kernel address.
2544 1.182.12.1 itohy * To make the translation possible (and fast) we use the chunk of
2545 1.182.12.1 itohy * TDs used for allocation.
2546 1.1 augustss */
2547 1.1 augustss
2548 1.1 augustss ohci_soft_td_t *
2549 1.182.12.1 itohy ohci_find_td(ohci_softc_t *sc, ohci_physaddr_t a)
2550 1.1 augustss {
2551 1.182.12.1 itohy struct ohci_mem_desc *om;
2552 1.1 augustss ohci_soft_td_t *std;
2553 1.182.12.1 itohy size_t off;
2554 1.1 augustss
2555 1.182.12.1 itohy /* if these are present they should be masked out at an earlier
2556 1.182.12.1 itohy * stage.
2557 1.182.12.1 itohy */
2558 1.182.12.1 itohy USB_KASSERT2((a&~OHCI_HEADMASK) == 0, ("%s: 0x%b has lower bits set\n",
2559 1.182.12.1 itohy USBDEVNAME(sc->sc_bus.bdev),
2560 1.182.12.1 itohy (int) a, "\20\1HALT\2TOGGLE"));
2561 1.182.12.1 itohy
2562 1.182.12.1 itohy SIMPLEQ_FOREACH(om, &sc->sc_std_chunks, om_next) {
2563 1.182.12.1 itohy if (a >= om->om_topdma &&
2564 1.182.12.1 itohy a < om->om_topdma + OHCI_STD_SIZE * OHCI_STD_CHUNK) {
2565 1.182.12.1 itohy off = a - om->om_topdma;
2566 1.182.12.1 itohy if (off % OHCI_STD_SIZE) {
2567 1.182.12.1 itohy #ifdef DIAGNOSTIC
2568 1.182.12.1 itohy printf("ohci_find_td: 0x%x bad address\n",
2569 1.182.12.1 itohy (unsigned)a);
2570 1.182.12.1 itohy #endif
2571 1.182.12.1 itohy break;
2572 1.182.12.1 itohy }
2573 1.182.12.1 itohy std = (ohci_soft_td_t *)(om->om_top + off);
2574 1.182.12.1 itohy if (std->flags & OHCI_TD_FREE) {
2575 1.182.12.1 itohy #ifdef DIAGNOSTIC
2576 1.182.12.1 itohy printf("ohci_find_td: 0x%x: free td\n",
2577 1.182.12.1 itohy (unsigned)OHCI_STD_DMAADDR(std));
2578 1.182.12.1 itohy #endif
2579 1.182.12.1 itohy break;
2580 1.182.12.1 itohy }
2581 1.182.12.1 itohy return std;
2582 1.182.12.1 itohy }
2583 1.182.12.1 itohy }
2584 1.83 augustss
2585 1.182.12.1 itohy return (NULL);
2586 1.83 augustss }
2587 1.83 augustss
2588 1.83 augustss ohci_soft_itd_t *
2589 1.182.12.1 itohy ohci_find_itd(ohci_softc_t *sc, ohci_physaddr_t a)
2590 1.83 augustss {
2591 1.182.12.1 itohy struct ohci_mem_desc *om;
2592 1.83 augustss ohci_soft_itd_t *sitd;
2593 1.182.12.1 itohy size_t off;
2594 1.83 augustss
2595 1.182.12.1 itohy SIMPLEQ_FOREACH(om, &sc->sc_sitd_chunks, om_next) {
2596 1.182.12.1 itohy if (a >= om->om_topdma &&
2597 1.182.12.1 itohy a < om->om_topdma + OHCI_SITD_SIZE * OHCI_SITD_CHUNK) {
2598 1.182.12.1 itohy off = a - om->om_topdma;
2599 1.182.12.1 itohy if (off % OHCI_SITD_SIZE) {
2600 1.182.12.1 itohy #ifdef DIAGNOSTIC
2601 1.182.12.1 itohy printf("ohci_find_itd: 0x%x bad address\n",
2602 1.182.12.1 itohy (unsigned)a);
2603 1.182.12.1 itohy #endif
2604 1.182.12.1 itohy break;
2605 1.182.12.1 itohy }
2606 1.182.12.1 itohy sitd = (ohci_soft_itd_t *)(om->om_top + off);
2607 1.182.12.1 itohy if (sitd->flags & OHCI_ITD_FREE) {
2608 1.182.12.1 itohy #ifdef DIAGNOSTIC
2609 1.182.12.1 itohy printf("ohci_find_itd: 0x%x: free itd\n",
2610 1.182.12.1 itohy (unsigned)OHCI_SITD_DMAADDR(sitd));
2611 1.182.12.1 itohy #endif
2612 1.182.12.1 itohy break;
2613 1.182.12.1 itohy }
2614 1.182.12.1 itohy return sitd;
2615 1.182.12.1 itohy }
2616 1.182.12.1 itohy }
2617 1.83 augustss return (NULL);
2618 1.1 augustss }
2619 1.1 augustss
2620 1.1 augustss void
2621 1.91 augustss ohci_timeout(void *addr)
2622 1.1 augustss {
2623 1.114 augustss struct ohci_xfer *oxfer = addr;
2624 1.116 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)oxfer->xfer.pipe;
2625 1.116 augustss ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
2626 1.114 augustss
2627 1.114 augustss DPRINTF(("ohci_timeout: oxfer=%p\n", oxfer));
2628 1.114 augustss
2629 1.116 augustss if (sc->sc_dying) {
2630 1.116 augustss ohci_abort_xfer(&oxfer->xfer, USBD_TIMEOUT);
2631 1.116 augustss return;
2632 1.116 augustss }
2633 1.116 augustss
2634 1.114 augustss /* Execute the abort in a process context. */
2635 1.178 joerg usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task,
2636 1.178 joerg USB_TASKQ_HC);
2637 1.114 augustss }
2638 1.114 augustss
2639 1.114 augustss void
2640 1.114 augustss ohci_timeout_task(void *addr)
2641 1.114 augustss {
2642 1.53 augustss usbd_xfer_handle xfer = addr;
2643 1.48 augustss int s;
2644 1.1 augustss
2645 1.114 augustss DPRINTF(("ohci_timeout_task: xfer=%p\n", xfer));
2646 1.45 augustss
2647 1.48 augustss s = splusb();
2648 1.54 augustss ohci_abort_xfer(xfer, USBD_TIMEOUT);
2649 1.48 augustss splx(s);
2650 1.1 augustss }
2651 1.1 augustss
2652 1.182.12.1 itohy #ifdef USB_DEBUG
2653 1.1 augustss void
2654 1.168 augustss ohci_dump_tds(ohci_softc_t *sc, ohci_soft_td_t *std)
2655 1.1 augustss {
2656 1.1 augustss for (; std; std = std->nexttd)
2657 1.168 augustss ohci_dump_td(sc, std);
2658 1.1 augustss }
2659 1.1 augustss
2660 1.1 augustss void
2661 1.168 augustss ohci_dump_td(ohci_softc_t *sc, ohci_soft_td_t *std)
2662 1.1 augustss {
2663 1.92 tv char sbuf[128];
2664 1.92 tv
2665 1.168 augustss bitmask_snprintf((u_int32_t)O32TOH(std->td.td_flags),
2666 1.92 tv "\20\23R\24OUT\25IN\31TOG1\32SETTOGGLE",
2667 1.92 tv sbuf, sizeof(sbuf));
2668 1.92 tv
2669 1.107 augustss printf("TD(%p) at %08lx: %s delay=%d ec=%d cc=%d\ncbp=0x%08lx "
2670 1.120 augustss "nexttd=0x%08lx be=0x%08lx\n",
2671 1.182.12.1 itohy std, (u_long)OHCI_STD_DMAADDR(std), sbuf,
2672 1.168 augustss OHCI_TD_GET_DI(O32TOH(std->td.td_flags)),
2673 1.168 augustss OHCI_TD_GET_EC(O32TOH(std->td.td_flags)),
2674 1.168 augustss OHCI_TD_GET_CC(O32TOH(std->td.td_flags)),
2675 1.168 augustss (u_long)O32TOH(std->td.td_cbp),
2676 1.168 augustss (u_long)O32TOH(std->td.td_nexttd),
2677 1.168 augustss (u_long)O32TOH(std->td.td_be));
2678 1.1 augustss }
2679 1.1 augustss
2680 1.1 augustss void
2681 1.168 augustss ohci_dump_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
2682 1.83 augustss {
2683 1.83 augustss int i;
2684 1.83 augustss
2685 1.107 augustss printf("ITD(%p) at %08lx: sf=%d di=%d fc=%d cc=%d\n"
2686 1.120 augustss "bp0=0x%08lx next=0x%08lx be=0x%08lx\n",
2687 1.182.12.1 itohy sitd, (u_long)OHCI_SITD_DMAADDR(sitd),
2688 1.168 augustss OHCI_ITD_GET_SF(O32TOH(sitd->itd.itd_flags)),
2689 1.168 augustss OHCI_ITD_GET_DI(O32TOH(sitd->itd.itd_flags)),
2690 1.168 augustss OHCI_ITD_GET_FC(O32TOH(sitd->itd.itd_flags)),
2691 1.168 augustss OHCI_ITD_GET_CC(O32TOH(sitd->itd.itd_flags)),
2692 1.168 augustss (u_long)O32TOH(sitd->itd.itd_bp0),
2693 1.168 augustss (u_long)O32TOH(sitd->itd.itd_nextitd),
2694 1.168 augustss (u_long)O32TOH(sitd->itd.itd_be));
2695 1.83 augustss for (i = 0; i < OHCI_ITD_NOFFSET; i++)
2696 1.107 augustss printf("offs[%d]=0x%04x ", i,
2697 1.168 augustss (u_int)O16TOH(sitd->itd.itd_offset[i]));
2698 1.107 augustss printf("\n");
2699 1.83 augustss }
2700 1.83 augustss
2701 1.83 augustss void
2702 1.168 augustss ohci_dump_itds(ohci_softc_t *sc, ohci_soft_itd_t *sitd)
2703 1.83 augustss {
2704 1.83 augustss for (; sitd; sitd = sitd->nextitd)
2705 1.168 augustss ohci_dump_itd(sc, sitd);
2706 1.83 augustss }
2707 1.83 augustss
2708 1.83 augustss void
2709 1.168 augustss ohci_dump_ed(ohci_softc_t *sc, ohci_soft_ed_t *sed)
2710 1.1 augustss {
2711 1.92 tv char sbuf[128], sbuf2[128];
2712 1.92 tv
2713 1.168 augustss bitmask_snprintf((u_int32_t)O32TOH(sed->ed.ed_flags),
2714 1.92 tv "\20\14OUT\15IN\16LOWSPEED\17SKIP\20ISO",
2715 1.92 tv sbuf, sizeof(sbuf));
2716 1.168 augustss bitmask_snprintf((u_int32_t)O32TOH(sed->ed.ed_headp),
2717 1.92 tv "\20\1HALT\2CARRY", sbuf2, sizeof(sbuf2));
2718 1.92 tv
2719 1.107 augustss printf("ED(%p) at 0x%08lx: addr=%d endpt=%d maxp=%d flags=%s\ntailp=0x%08lx "
2720 1.92 tv "headflags=%s headp=0x%08lx nexted=0x%08lx\n",
2721 1.182.12.1 itohy sed, (u_long)OHCI_SED_DMAADDR(sed),
2722 1.168 augustss OHCI_ED_GET_FA(O32TOH(sed->ed.ed_flags)),
2723 1.168 augustss OHCI_ED_GET_EN(O32TOH(sed->ed.ed_flags)),
2724 1.168 augustss OHCI_ED_GET_MAXP(O32TOH(sed->ed.ed_flags)), sbuf,
2725 1.168 augustss (u_long)O32TOH(sed->ed.ed_tailp), sbuf2,
2726 1.168 augustss (u_long)O32TOH(sed->ed.ed_headp),
2727 1.168 augustss (u_long)O32TOH(sed->ed.ed_nexted));
2728 1.1 augustss }
2729 1.1 augustss #endif
2730 1.1 augustss
2731 1.1 augustss usbd_status
2732 1.91 augustss ohci_open(usbd_pipe_handle pipe)
2733 1.1 augustss {
2734 1.1 augustss usbd_device_handle dev = pipe->device;
2735 1.1 augustss ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
2736 1.1 augustss usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc;
2737 1.1 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
2738 1.1 augustss u_int8_t addr = dev->address;
2739 1.60 augustss u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE;
2740 1.1 augustss ohci_soft_ed_t *sed;
2741 1.1 augustss ohci_soft_td_t *std;
2742 1.60 augustss ohci_soft_itd_t *sitd;
2743 1.60 augustss ohci_physaddr_t tdphys;
2744 1.60 augustss u_int32_t fmt;
2745 1.53 augustss usbd_status err;
2746 1.1 augustss int s;
2747 1.64 augustss int ival;
2748 1.1 augustss
2749 1.1 augustss DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
2750 1.1 augustss pipe, addr, ed->bEndpointAddress, sc->sc_addr));
2751 1.81 augustss
2752 1.116 augustss if (sc->sc_dying)
2753 1.116 augustss return (USBD_IOERROR);
2754 1.116 augustss
2755 1.90 thorpej std = NULL;
2756 1.90 thorpej sed = NULL;
2757 1.90 thorpej
2758 1.1 augustss if (addr == sc->sc_addr) {
2759 1.1 augustss switch (ed->bEndpointAddress) {
2760 1.1 augustss case USB_CONTROL_ENDPOINT:
2761 1.1 augustss pipe->methods = &ohci_root_ctrl_methods;
2762 1.1 augustss break;
2763 1.40 augustss case UE_DIR_IN | OHCI_INTR_ENDPT:
2764 1.1 augustss pipe->methods = &ohci_root_intr_methods;
2765 1.1 augustss break;
2766 1.1 augustss default:
2767 1.1 augustss return (USBD_INVAL);
2768 1.1 augustss }
2769 1.1 augustss } else {
2770 1.1 augustss sed = ohci_alloc_sed(sc);
2771 1.53 augustss if (sed == NULL)
2772 1.1 augustss goto bad0;
2773 1.1 augustss opipe->sed = sed;
2774 1.60 augustss if (xfertype == UE_ISOCHRONOUS) {
2775 1.182.12.1 itohy sitd = ohci_alloc_sitd_norsv(sc);
2776 1.127 augustss if (sitd == NULL)
2777 1.60 augustss goto bad1;
2778 1.60 augustss opipe->tail.itd = sitd;
2779 1.182.12.1 itohy opipe->aborting = 0;
2780 1.182.12.1 itohy tdphys = OHCI_SITD_DMAADDR(sitd);
2781 1.60 augustss fmt = OHCI_ED_FORMAT_ISO;
2782 1.83 augustss if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN)
2783 1.83 augustss fmt |= OHCI_ED_DIR_IN;
2784 1.83 augustss else
2785 1.83 augustss fmt |= OHCI_ED_DIR_OUT;
2786 1.60 augustss } else {
2787 1.182.12.1 itohy std = ohci_alloc_std_norsv(sc);
2788 1.127 augustss if (std == NULL)
2789 1.60 augustss goto bad1;
2790 1.60 augustss opipe->tail.td = std;
2791 1.182.12.1 itohy tdphys = OHCI_STD_DMAADDR(std);
2792 1.83 augustss fmt = OHCI_ED_FORMAT_GEN | OHCI_ED_DIR_TD;
2793 1.60 augustss }
2794 1.168 augustss sed->ed.ed_flags = HTOO32(
2795 1.120 augustss OHCI_ED_SET_FA(addr) |
2796 1.147 mycroft OHCI_ED_SET_EN(UE_GET_ADDR(ed->bEndpointAddress)) |
2797 1.109 augustss (dev->speed == USB_SPEED_LOW ? OHCI_ED_SPEED : 0) |
2798 1.109 augustss fmt |
2799 1.182.12.1 itohy OHCI_ED_SET_MAXP(UE_MAXPKTSZ(ed)));
2800 1.182.12.1 itohy sed->ed.ed_headp = HTOO32(tdphys |
2801 1.182.12.1 itohy (pipe->endpoint->savedtoggle ? OHCI_TOGGLECARRY : 0));
2802 1.182.12.1 itohy sed->ed.ed_tailp = HTOO32(tdphys);
2803 1.1 augustss
2804 1.60 augustss switch (xfertype) {
2805 1.1 augustss case UE_CONTROL:
2806 1.1 augustss pipe->methods = &ohci_device_ctrl_methods;
2807 1.182.12.1 itohy err = usb_allocmem(&sc->sc_dmatag,
2808 1.120 augustss sizeof(usb_device_request_t),
2809 1.53 augustss 0, &opipe->u.ctl.reqdma);
2810 1.53 augustss if (err)
2811 1.1 augustss goto bad;
2812 1.1 augustss s = splusb();
2813 1.168 augustss ohci_add_ed(sc, sed, sc->sc_ctrl_head);
2814 1.1 augustss splx(s);
2815 1.1 augustss break;
2816 1.1 augustss case UE_INTERRUPT:
2817 1.1 augustss pipe->methods = &ohci_device_intr_methods;
2818 1.64 augustss ival = pipe->interval;
2819 1.64 augustss if (ival == USBD_DEFAULT_INTERVAL)
2820 1.64 augustss ival = ed->bInterval;
2821 1.64 augustss return (ohci_device_setintr(sc, opipe, ival));
2822 1.1 augustss case UE_ISOCHRONOUS:
2823 1.60 augustss pipe->methods = &ohci_device_isoc_methods;
2824 1.60 augustss return (ohci_setup_isoc(pipe));
2825 1.1 augustss case UE_BULK:
2826 1.3 augustss pipe->methods = &ohci_device_bulk_methods;
2827 1.3 augustss s = splusb();
2828 1.168 augustss ohci_add_ed(sc, sed, sc->sc_bulk_head);
2829 1.3 augustss splx(s);
2830 1.3 augustss break;
2831 1.1 augustss }
2832 1.1 augustss }
2833 1.1 augustss return (USBD_NORMAL_COMPLETION);
2834 1.1 augustss
2835 1.1 augustss bad:
2836 1.90 thorpej if (std != NULL)
2837 1.90 thorpej ohci_free_std(sc, std);
2838 1.1 augustss bad1:
2839 1.90 thorpej if (sed != NULL)
2840 1.90 thorpej ohci_free_sed(sc, sed);
2841 1.1 augustss bad0:
2842 1.1 augustss return (USBD_NOMEM);
2843 1.120 augustss
2844 1.1 augustss }
2845 1.1 augustss
2846 1.1 augustss /*
2847 1.34 augustss * Close a reqular pipe.
2848 1.34 augustss * Assumes that there are no pending transactions.
2849 1.34 augustss */
2850 1.34 augustss void
2851 1.91 augustss ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head)
2852 1.34 augustss {
2853 1.34 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
2854 1.34 augustss ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
2855 1.34 augustss ohci_soft_ed_t *sed = opipe->sed;
2856 1.34 augustss int s;
2857 1.34 augustss
2858 1.34 augustss s = splusb();
2859 1.34 augustss #ifdef DIAGNOSTIC
2860 1.168 augustss sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
2861 1.168 augustss if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
2862 1.168 augustss (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) {
2863 1.34 augustss ohci_soft_td_t *std;
2864 1.182.12.3 itohy std = ohci_find_td(sc,
2865 1.182.12.3 itohy O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK);
2866 1.34 augustss printf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x "
2867 1.34 augustss "tl=0x%x pipe=%p, std=%p\n", sed,
2868 1.168 augustss (int)O32TOH(sed->ed.ed_headp),
2869 1.168 augustss (int)O32TOH(sed->ed.ed_tailp),
2870 1.34 augustss pipe, std);
2871 1.107 augustss #ifdef USB_DEBUG
2872 1.107 augustss usbd_dump_pipe(&opipe->pipe);
2873 1.107 augustss #endif
2874 1.182.12.1 itohy #ifdef USB_DEBUG
2875 1.168 augustss ohci_dump_ed(sc, sed);
2876 1.106 augustss if (std)
2877 1.168 augustss ohci_dump_td(sc, std);
2878 1.106 augustss #endif
2879 1.34 augustss usb_delay_ms(&sc->sc_bus, 2);
2880 1.168 augustss if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
2881 1.168 augustss (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK))
2882 1.34 augustss printf("ohci_close_pipe: pipe still not empty\n");
2883 1.34 augustss }
2884 1.34 augustss #endif
2885 1.182.12.3 itohy ohci_rem_ed(sc, sed, head);
2886 1.133 toshii /* Make sure the host controller is not touching this ED */
2887 1.133 toshii usb_delay_ms(&sc->sc_bus, 1);
2888 1.34 augustss splx(s);
2889 1.182.12.1 itohy pipe->endpoint->savedtoggle =
2890 1.182.12.1 itohy (O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0;
2891 1.182.12.3 itohy ohci_free_sed(sc, sed);
2892 1.34 augustss }
2893 1.34 augustss
2894 1.120 augustss /*
2895 1.34 augustss * Abort a device request.
2896 1.34 augustss * If this routine is called at splusb() it guarantees that the request
2897 1.34 augustss * will be removed from the hardware scheduling and that the callback
2898 1.34 augustss * for it will be called with USBD_CANCELLED status.
2899 1.34 augustss * It's impossible to guarantee that the requested transfer will not
2900 1.34 augustss * have happened since the hardware runs concurrently.
2901 1.34 augustss * If the transaction has already happened we rely on the ordinary
2902 1.34 augustss * interrupt processing to process it.
2903 1.34 augustss */
2904 1.34 augustss void
2905 1.91 augustss ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
2906 1.34 augustss {
2907 1.182.12.1 itohy struct ohci_xfer *oxfer = OXFER(xfer);
2908 1.53 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
2909 1.106 augustss ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
2910 1.106 augustss ohci_soft_ed_t *sed = opipe->sed;
2911 1.106 augustss ohci_soft_td_t *p, *n;
2912 1.106 augustss ohci_physaddr_t headp;
2913 1.182.12.1 itohy ohci_physaddr_t dmaadr;
2914 1.106 augustss int s, hit;
2915 1.159 augustss int wake;
2916 1.182.12.3 itohy int isread, is_mbuf;
2917 1.34 augustss
2918 1.106 augustss DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,sed));
2919 1.34 augustss
2920 1.116 augustss if (sc->sc_dying) {
2921 1.116 augustss /* If we're dying, just do the software part. */
2922 1.116 augustss s = splusb();
2923 1.116 augustss xfer->status = status; /* make software ignore it */
2924 1.121 tsutsui usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
2925 1.182.12.1 itohy usb_rem_task(xfer->pipe->device, &oxfer->abort_task);
2926 1.182.12.3 itohy ohci_transfer_complete(xfer, 0);
2927 1.116 augustss splx(s);
2928 1.170 christos return;
2929 1.116 augustss }
2930 1.116 augustss
2931 1.106 augustss if (xfer->device->bus->intr_context || !curproc)
2932 1.128 provos panic("ohci_abort_xfer: not in process context");
2933 1.34 augustss
2934 1.106 augustss /*
2935 1.159 augustss * If an abort is already in progress then just wait for it to
2936 1.159 augustss * complete and return.
2937 1.159 augustss */
2938 1.182.12.1 itohy if (oxfer->ohci_xfer_flags & OHCI_XFER_ABORTING) {
2939 1.159 augustss DPRINTFN(2, ("ohci_abort_xfer: already aborting\n"));
2940 1.182.12.1 itohy /* No need to wait if we're aborting from a timeout. */
2941 1.159 augustss if (status == USBD_TIMEOUT)
2942 1.182.12.1 itohy return;
2943 1.159 augustss /* Override the status which might be USBD_TIMEOUT. */
2944 1.159 augustss xfer->status = status;
2945 1.159 augustss DPRINTFN(2, ("ohci_abort_xfer: waiting for abort to finish\n"));
2946 1.182.12.1 itohy oxfer->ohci_xfer_flags |= OHCI_XFER_ABORTWAIT;
2947 1.182.12.1 itohy while (oxfer->ohci_xfer_flags & OHCI_XFER_ABORTING)
2948 1.182.12.1 itohy tsleep(&oxfer->ohci_xfer_flags, PZERO, "ohciaw", 0);
2949 1.159 augustss return;
2950 1.159 augustss }
2951 1.159 augustss
2952 1.159 augustss /*
2953 1.106 augustss * Step 1: Make interrupt routine and hardware ignore xfer.
2954 1.106 augustss */
2955 1.106 augustss s = splusb();
2956 1.182.12.1 itohy oxfer->ohci_xfer_flags |= OHCI_XFER_ABORTING;
2957 1.106 augustss xfer->status = status; /* make software ignore it */
2958 1.81 augustss usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
2959 1.182.12.1 itohy usb_rem_task(xfer->pipe->device, &oxfer->abort_task);
2960 1.106 augustss splx(s);
2961 1.54 augustss DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
2962 1.168 augustss sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); /* force hardware skip */
2963 1.34 augustss
2964 1.120 augustss /*
2965 1.106 augustss * Step 2: Wait until we know hardware has finished any possible
2966 1.106 augustss * use of the xfer. Also make sure the soft interrupt routine
2967 1.106 augustss * has run.
2968 1.106 augustss */
2969 1.119 augustss usb_delay_ms(opipe->pipe.device->bus, 20); /* Hardware finishes in 1ms */
2970 1.119 augustss s = splusb();
2971 1.131 augustss #ifdef USB_USE_SOFTINTR
2972 1.119 augustss sc->sc_softwake = 1;
2973 1.131 augustss #endif /* USB_USE_SOFTINTR */
2974 1.119 augustss usb_schedsoftintr(&sc->sc_bus);
2975 1.131 augustss #ifdef USB_USE_SOFTINTR
2976 1.119 augustss tsleep(&sc->sc_softwake, PZERO, "ohciab", 0);
2977 1.131 augustss #endif /* USB_USE_SOFTINTR */
2978 1.119 augustss splx(s);
2979 1.119 augustss
2980 1.120 augustss /*
2981 1.106 augustss * Step 3: Remove any vestiges of the xfer from the hardware.
2982 1.106 augustss * The complication here is that the hardware may have executed
2983 1.106 augustss * beyond the xfer we're trying to abort. So as we're scanning
2984 1.106 augustss * the TDs of this xfer we check if the hardware points to
2985 1.106 augustss * any of them.
2986 1.106 augustss */
2987 1.106 augustss s = splusb(); /* XXX why? */
2988 1.53 augustss p = xfer->hcpriv;
2989 1.34 augustss #ifdef DIAGNOSTIC
2990 1.55 augustss if (p == NULL) {
2991 1.182.12.1 itohy oxfer->ohci_xfer_flags &= ~OHCI_XFER_ABORTING; /* XXX */
2992 1.102 augustss splx(s);
2993 1.106 augustss printf("ohci_abort_xfer: hcpriv is NULL\n");
2994 1.38 augustss return;
2995 1.38 augustss }
2996 1.34 augustss #endif
2997 1.182.12.1 itohy #ifdef USB_DEBUG
2998 1.106 augustss if (ohcidebug > 1) {
2999 1.106 augustss DPRINTF(("ohci_abort_xfer: sed=\n"));
3000 1.168 augustss ohci_dump_ed(sc, sed);
3001 1.168 augustss ohci_dump_tds(sc, p);
3002 1.106 augustss }
3003 1.106 augustss #endif
3004 1.182.12.3 itohy isread = usbd_xfer_isread(xfer);
3005 1.182.12.3 itohy is_mbuf = xfer->rqflags & URQ_DEV_MAP_MBUF;
3006 1.168 augustss headp = O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK;
3007 1.106 augustss hit = 0;
3008 1.53 augustss for (; p->xfer == xfer; p = n) {
3009 1.182.12.1 itohy hit |= headp == OHCI_STD_DMAADDR(p);
3010 1.38 augustss n = p->nexttd;
3011 1.182.12.3 itohy #if 0
3012 1.182.12.3 itohy #if 1
3013 1.182.12.3 itohy if (p->ad.aux_len)
3014 1.182.12.3 itohy ohci_aux_dma_complete(&p->ad,
3015 1.182.12.3 itohy &OXFER(xfer)->aux, is_mbuf, isread);
3016 1.182.12.3 itohy #endif
3017 1.38 augustss ohci_free_std(sc, p);
3018 1.182.12.3 itohy #endif
3019 1.34 augustss }
3020 1.106 augustss /* Zap headp register if hardware pointed inside the xfer. */
3021 1.106 augustss if (hit) {
3022 1.150 mycroft DPRINTFN(1,("ohci_abort_xfer: set hd=0x%08x, tl=0x%08x\n",
3023 1.182.12.1 itohy (int)OHCI_STD_DMAADDR(p), (int)O32TOH(sed->ed.ed_tailp)));
3024 1.182.12.1 itohy dmaadr = OHCI_STD_DMAADDR(p);
3025 1.182.12.1 itohy sed->ed.ed_headp = HTOO32(dmaadr); /* unlink TDs */
3026 1.106 augustss } else {
3027 1.106 augustss DPRINTFN(1,("ohci_abort_xfer: no hit\n"));
3028 1.106 augustss }
3029 1.34 augustss
3030 1.106 augustss /*
3031 1.106 augustss * Step 4: Turn on hardware again.
3032 1.106 augustss */
3033 1.168 augustss sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */
3034 1.38 augustss
3035 1.106 augustss /*
3036 1.106 augustss * Step 5: Execute callback.
3037 1.106 augustss */
3038 1.182.12.1 itohy /* Do the wakeup first to avoid touching the xfer after the callback. */
3039 1.182.12.1 itohy wake = oxfer->ohci_xfer_flags & OHCI_XFER_ABORTWAIT;
3040 1.182.12.1 itohy oxfer->ohci_xfer_flags &= ~(OHCI_XFER_ABORTING | OHCI_XFER_ABORTWAIT);
3041 1.182.12.3 itohy ohci_transfer_complete(xfer, 0);
3042 1.159 augustss if (wake)
3043 1.182.12.1 itohy wakeup(&oxfer->ohci_xfer_flags);
3044 1.38 augustss
3045 1.34 augustss splx(s);
3046 1.34 augustss }
3047 1.34 augustss
3048 1.34 augustss /*
3049 1.1 augustss * Data structures and routines to emulate the root hub.
3050 1.1 augustss */
3051 1.82 augustss Static usb_device_descriptor_t ohci_devd = {
3052 1.1 augustss USB_DEVICE_DESCRIPTOR_SIZE,
3053 1.1 augustss UDESC_DEVICE, /* type */
3054 1.1 augustss {0x00, 0x01}, /* USB version */
3055 1.74 augustss UDCLASS_HUB, /* class */
3056 1.74 augustss UDSUBCLASS_HUB, /* subclass */
3057 1.182.12.1 itohy UDPROTO_FSHUB, /* protocol */
3058 1.1 augustss 64, /* max packet */
3059 1.1 augustss {0},{0},{0x00,0x01}, /* device id */
3060 1.1 augustss 1,2,0, /* string indicies */
3061 1.1 augustss 1 /* # of configurations */
3062 1.1 augustss };
3063 1.1 augustss
3064 1.182.12.1 itohy Static usb_config_descriptor_t ohci_confd = {
3065 1.1 augustss USB_CONFIG_DESCRIPTOR_SIZE,
3066 1.1 augustss UDESC_CONFIG,
3067 1.1 augustss {USB_CONFIG_DESCRIPTOR_SIZE +
3068 1.1 augustss USB_INTERFACE_DESCRIPTOR_SIZE +
3069 1.1 augustss USB_ENDPOINT_DESCRIPTOR_SIZE},
3070 1.1 augustss 1,
3071 1.1 augustss 1,
3072 1.1 augustss 0,
3073 1.180 drochner UC_ATTR_MBO | UC_SELF_POWERED,
3074 1.1 augustss 0 /* max power */
3075 1.1 augustss };
3076 1.1 augustss
3077 1.182.12.1 itohy Static usb_interface_descriptor_t ohci_ifcd = {
3078 1.1 augustss USB_INTERFACE_DESCRIPTOR_SIZE,
3079 1.1 augustss UDESC_INTERFACE,
3080 1.1 augustss 0,
3081 1.1 augustss 0,
3082 1.1 augustss 1,
3083 1.74 augustss UICLASS_HUB,
3084 1.74 augustss UISUBCLASS_HUB,
3085 1.109 augustss UIPROTO_FSHUB,
3086 1.1 augustss 0
3087 1.1 augustss };
3088 1.1 augustss
3089 1.182.12.1 itohy Static usb_endpoint_descriptor_t ohci_endpd = {
3090 1.175 christos .bLength = USB_ENDPOINT_DESCRIPTOR_SIZE,
3091 1.175 christos .bDescriptorType = UDESC_ENDPOINT,
3092 1.175 christos .bEndpointAddress = UE_DIR_IN | OHCI_INTR_ENDPT,
3093 1.175 christos .bmAttributes = UE_INTERRUPT,
3094 1.175 christos .wMaxPacketSize = {8, 0}, /* max packet */
3095 1.175 christos .bInterval = 255,
3096 1.1 augustss };
3097 1.1 augustss
3098 1.182.12.1 itohy Static usb_hub_descriptor_t ohci_hubd = {
3099 1.175 christos .bDescLength = USB_HUB_DESCRIPTOR_SIZE,
3100 1.175 christos .bDescriptorType = UDESC_HUB,
3101 1.1 augustss };
3102 1.1 augustss
3103 1.82 augustss Static int
3104 1.120 augustss ohci_str(usb_string_descriptor_t *p, int l, const char *s)
3105 1.1 augustss {
3106 1.1 augustss int i;
3107 1.1 augustss
3108 1.1 augustss if (l == 0)
3109 1.1 augustss return (0);
3110 1.1 augustss p->bLength = 2 * strlen(s) + 2;
3111 1.1 augustss if (l == 1)
3112 1.1 augustss return (1);
3113 1.1 augustss p->bDescriptorType = UDESC_STRING;
3114 1.1 augustss l -= 2;
3115 1.1 augustss for (i = 0; s[i] && l > 1; i++, l -= 2)
3116 1.1 augustss USETW2(p->bString[i], 0, s[i]);
3117 1.1 augustss return (2*i+2);
3118 1.1 augustss }
3119 1.1 augustss
3120 1.1 augustss /*
3121 1.1 augustss * Simulate a hardware hub by handling all the necessary requests.
3122 1.1 augustss */
3123 1.82 augustss Static usbd_status
3124 1.91 augustss ohci_root_ctrl_transfer(usbd_xfer_handle xfer)
3125 1.1 augustss {
3126 1.53 augustss usbd_status err;
3127 1.17 augustss
3128 1.46 augustss /* Insert last in queue. */
3129 1.182.12.1 itohy #if 0 /* root ctrl doesn't do DMA */
3130 1.182.12.1 itohy err = usb_insert_transfer_dma(xfer, &sc->sc_dmatag,
3131 1.182.12.1 itohy &OXFER(xfer)->dmabuf);
3132 1.182.12.1 itohy #else
3133 1.53 augustss err = usb_insert_transfer(xfer);
3134 1.182.12.1 itohy #endif
3135 1.53 augustss if (err)
3136 1.53 augustss return (err);
3137 1.46 augustss
3138 1.46 augustss /* Pipe isn't running, start first */
3139 1.53 augustss return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
3140 1.17 augustss }
3141 1.17 augustss
3142 1.82 augustss Static usbd_status
3143 1.91 augustss ohci_root_ctrl_start(usbd_xfer_handle xfer)
3144 1.17 augustss {
3145 1.53 augustss ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
3146 1.1 augustss usb_device_request_t *req;
3147 1.52 augustss void *buf = NULL;
3148 1.1 augustss int port, i;
3149 1.46 augustss int s, len, value, index, l, totlen = 0;
3150 1.1 augustss usb_port_status_t ps;
3151 1.1 augustss usb_hub_descriptor_t hubd;
3152 1.53 augustss usbd_status err;
3153 1.1 augustss u_int32_t v;
3154 1.1 augustss
3155 1.83 augustss if (sc->sc_dying)
3156 1.83 augustss return (USBD_IOERROR);
3157 1.83 augustss
3158 1.42 augustss #ifdef DIAGNOSTIC
3159 1.53 augustss if (!(xfer->rqflags & URQ_REQUEST))
3160 1.1 augustss /* XXX panic */
3161 1.1 augustss return (USBD_INVAL);
3162 1.42 augustss #endif
3163 1.53 augustss req = &xfer->request;
3164 1.1 augustss
3165 1.182.12.1 itohy DPRINTFN(4,("ohci_root_ctrl_start: type=0x%02x request=%02x\n",
3166 1.1 augustss req->bmRequestType, req->bRequest));
3167 1.1 augustss
3168 1.1 augustss len = UGETW(req->wLength);
3169 1.1 augustss value = UGETW(req->wValue);
3170 1.1 augustss index = UGETW(req->wIndex);
3171 1.43 augustss
3172 1.182.12.2 itohy if (len != 0) {
3173 1.182.12.2 itohy /* mbuf transfer is not supported */
3174 1.182.12.2 itohy if (xfer->rqflags & URQ_DEV_MAP_MBUF)
3175 1.182.12.2 itohy return (USBD_INVAL);
3176 1.182.12.1 itohy buf = xfer->hcbuffer;
3177 1.182.12.2 itohy }
3178 1.43 augustss
3179 1.1 augustss #define C(x,y) ((x) | ((y) << 8))
3180 1.1 augustss switch(C(req->bRequest, req->bmRequestType)) {
3181 1.1 augustss case C(UR_CLEAR_FEATURE, UT_WRITE_DEVICE):
3182 1.1 augustss case C(UR_CLEAR_FEATURE, UT_WRITE_INTERFACE):
3183 1.1 augustss case C(UR_CLEAR_FEATURE, UT_WRITE_ENDPOINT):
3184 1.120 augustss /*
3185 1.15 augustss * DEVICE_REMOTE_WAKEUP and ENDPOINT_HALT are no-ops
3186 1.1 augustss * for the integrated root hub.
3187 1.1 augustss */
3188 1.1 augustss break;
3189 1.1 augustss case C(UR_GET_CONFIG, UT_READ_DEVICE):
3190 1.1 augustss if (len > 0) {
3191 1.1 augustss *(u_int8_t *)buf = sc->sc_conf;
3192 1.1 augustss totlen = 1;
3193 1.1 augustss }
3194 1.1 augustss break;
3195 1.1 augustss case C(UR_GET_DESCRIPTOR, UT_READ_DEVICE):
3196 1.1 augustss DPRINTFN(8,("ohci_root_ctrl_control wValue=0x%04x\n", value));
3197 1.171 christos if (len == 0)
3198 1.171 christos break;
3199 1.1 augustss switch(value >> 8) {
3200 1.1 augustss case UDESC_DEVICE:
3201 1.1 augustss if ((value & 0xff) != 0) {
3202 1.53 augustss err = USBD_IOERROR;
3203 1.1 augustss goto ret;
3204 1.1 augustss }
3205 1.1 augustss totlen = l = min(len, USB_DEVICE_DESCRIPTOR_SIZE);
3206 1.29 augustss USETW(ohci_devd.idVendor, sc->sc_id_vendor);
3207 1.1 augustss memcpy(buf, &ohci_devd, l);
3208 1.1 augustss break;
3209 1.1 augustss case UDESC_CONFIG:
3210 1.1 augustss if ((value & 0xff) != 0) {
3211 1.53 augustss err = USBD_IOERROR;
3212 1.1 augustss goto ret;
3213 1.1 augustss }
3214 1.1 augustss totlen = l = min(len, USB_CONFIG_DESCRIPTOR_SIZE);
3215 1.1 augustss memcpy(buf, &ohci_confd, l);
3216 1.1 augustss buf = (char *)buf + l;
3217 1.1 augustss len -= l;
3218 1.1 augustss l = min(len, USB_INTERFACE_DESCRIPTOR_SIZE);
3219 1.1 augustss totlen += l;
3220 1.1 augustss memcpy(buf, &ohci_ifcd, l);
3221 1.1 augustss buf = (char *)buf + l;
3222 1.1 augustss len -= l;
3223 1.1 augustss l = min(len, USB_ENDPOINT_DESCRIPTOR_SIZE);
3224 1.1 augustss totlen += l;
3225 1.1 augustss memcpy(buf, &ohci_endpd, l);
3226 1.1 augustss break;
3227 1.1 augustss case UDESC_STRING:
3228 1.1 augustss *(u_int8_t *)buf = 0;
3229 1.1 augustss totlen = 1;
3230 1.1 augustss switch (value & 0xff) {
3231 1.152 augustss case 0: /* Language table */
3232 1.182 drochner if (len > 0)
3233 1.182 drochner *(u_int8_t *)buf = 4;
3234 1.182 drochner if (len >= 4) {
3235 1.182 drochner USETW(((usb_string_descriptor_t *)buf)->bString[0], 0x0409);
3236 1.182 drochner totlen = 4;
3237 1.182 drochner }
3238 1.152 augustss break;
3239 1.1 augustss case 1: /* Vendor */
3240 1.1 augustss totlen = ohci_str(buf, len, sc->sc_vendor);
3241 1.1 augustss break;
3242 1.1 augustss case 2: /* Product */
3243 1.1 augustss totlen = ohci_str(buf, len, "OHCI root hub");
3244 1.1 augustss break;
3245 1.1 augustss }
3246 1.1 augustss break;
3247 1.1 augustss default:
3248 1.53 augustss err = USBD_IOERROR;
3249 1.1 augustss goto ret;
3250 1.1 augustss }
3251 1.1 augustss break;
3252 1.1 augustss case C(UR_GET_INTERFACE, UT_READ_INTERFACE):
3253 1.1 augustss if (len > 0) {
3254 1.1 augustss *(u_int8_t *)buf = 0;
3255 1.1 augustss totlen = 1;
3256 1.1 augustss }
3257 1.1 augustss break;
3258 1.1 augustss case C(UR_GET_STATUS, UT_READ_DEVICE):
3259 1.1 augustss if (len > 1) {
3260 1.1 augustss USETW(((usb_status_t *)buf)->wStatus,UDS_SELF_POWERED);
3261 1.1 augustss totlen = 2;
3262 1.1 augustss }
3263 1.1 augustss break;
3264 1.1 augustss case C(UR_GET_STATUS, UT_READ_INTERFACE):
3265 1.1 augustss case C(UR_GET_STATUS, UT_READ_ENDPOINT):
3266 1.1 augustss if (len > 1) {
3267 1.1 augustss USETW(((usb_status_t *)buf)->wStatus, 0);
3268 1.1 augustss totlen = 2;
3269 1.1 augustss }
3270 1.1 augustss break;
3271 1.1 augustss case C(UR_SET_ADDRESS, UT_WRITE_DEVICE):
3272 1.1 augustss if (value >= USB_MAX_DEVICES) {
3273 1.53 augustss err = USBD_IOERROR;
3274 1.1 augustss goto ret;
3275 1.1 augustss }
3276 1.1 augustss sc->sc_addr = value;
3277 1.1 augustss break;
3278 1.1 augustss case C(UR_SET_CONFIG, UT_WRITE_DEVICE):
3279 1.1 augustss if (value != 0 && value != 1) {
3280 1.53 augustss err = USBD_IOERROR;
3281 1.1 augustss goto ret;
3282 1.1 augustss }
3283 1.1 augustss sc->sc_conf = value;
3284 1.1 augustss break;
3285 1.1 augustss case C(UR_SET_DESCRIPTOR, UT_WRITE_DEVICE):
3286 1.1 augustss break;
3287 1.1 augustss case C(UR_SET_FEATURE, UT_WRITE_DEVICE):
3288 1.1 augustss case C(UR_SET_FEATURE, UT_WRITE_INTERFACE):
3289 1.1 augustss case C(UR_SET_FEATURE, UT_WRITE_ENDPOINT):
3290 1.53 augustss err = USBD_IOERROR;
3291 1.1 augustss goto ret;
3292 1.1 augustss case C(UR_SET_INTERFACE, UT_WRITE_INTERFACE):
3293 1.1 augustss break;
3294 1.1 augustss case C(UR_SYNCH_FRAME, UT_WRITE_ENDPOINT):
3295 1.1 augustss break;
3296 1.1 augustss /* Hub requests */
3297 1.1 augustss case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_DEVICE):
3298 1.1 augustss break;
3299 1.1 augustss case C(UR_CLEAR_FEATURE, UT_WRITE_CLASS_OTHER):
3300 1.182.12.1 itohy DPRINTFN(8, ("ohci_root_ctrl_start: UR_CLEAR_PORT_FEATURE "
3301 1.14 augustss "port=%d feature=%d\n",
3302 1.1 augustss index, value));
3303 1.1 augustss if (index < 1 || index > sc->sc_noport) {
3304 1.53 augustss err = USBD_IOERROR;
3305 1.1 augustss goto ret;
3306 1.1 augustss }
3307 1.1 augustss port = OHCI_RH_PORT_STATUS(index);
3308 1.1 augustss switch(value) {
3309 1.1 augustss case UHF_PORT_ENABLE:
3310 1.1 augustss OWRITE4(sc, port, UPS_CURRENT_CONNECT_STATUS);
3311 1.1 augustss break;
3312 1.1 augustss case UHF_PORT_SUSPEND:
3313 1.1 augustss OWRITE4(sc, port, UPS_OVERCURRENT_INDICATOR);
3314 1.1 augustss break;
3315 1.1 augustss case UHF_PORT_POWER:
3316 1.86 augustss /* Yes, writing to the LOW_SPEED bit clears power. */
3317 1.1 augustss OWRITE4(sc, port, UPS_LOW_SPEED);
3318 1.1 augustss break;
3319 1.1 augustss case UHF_C_PORT_CONNECTION:
3320 1.1 augustss OWRITE4(sc, port, UPS_C_CONNECT_STATUS << 16);
3321 1.1 augustss break;
3322 1.1 augustss case UHF_C_PORT_ENABLE:
3323 1.1 augustss OWRITE4(sc, port, UPS_C_PORT_ENABLED << 16);
3324 1.1 augustss break;
3325 1.1 augustss case UHF_C_PORT_SUSPEND:
3326 1.1 augustss OWRITE4(sc, port, UPS_C_SUSPEND << 16);
3327 1.1 augustss break;
3328 1.1 augustss case UHF_C_PORT_OVER_CURRENT:
3329 1.1 augustss OWRITE4(sc, port, UPS_C_OVERCURRENT_INDICATOR << 16);
3330 1.1 augustss break;
3331 1.1 augustss case UHF_C_PORT_RESET:
3332 1.1 augustss OWRITE4(sc, port, UPS_C_PORT_RESET << 16);
3333 1.1 augustss break;
3334 1.1 augustss default:
3335 1.53 augustss err = USBD_IOERROR;
3336 1.1 augustss goto ret;
3337 1.1 augustss }
3338 1.1 augustss switch(value) {
3339 1.1 augustss case UHF_C_PORT_CONNECTION:
3340 1.1 augustss case UHF_C_PORT_ENABLE:
3341 1.1 augustss case UHF_C_PORT_SUSPEND:
3342 1.1 augustss case UHF_C_PORT_OVER_CURRENT:
3343 1.1 augustss case UHF_C_PORT_RESET:
3344 1.1 augustss /* Enable RHSC interrupt if condition is cleared. */
3345 1.1 augustss if ((OREAD4(sc, port) >> 16) == 0)
3346 1.157 mycroft ohci_rhsc_enable(sc);
3347 1.1 augustss break;
3348 1.1 augustss default:
3349 1.1 augustss break;
3350 1.1 augustss }
3351 1.1 augustss break;
3352 1.1 augustss case C(UR_GET_DESCRIPTOR, UT_READ_CLASS_DEVICE):
3353 1.171 christos if (len == 0)
3354 1.171 christos break;
3355 1.146 toshii if ((value & 0xff) != 0) {
3356 1.53 augustss err = USBD_IOERROR;
3357 1.1 augustss goto ret;
3358 1.1 augustss }
3359 1.1 augustss v = OREAD4(sc, OHCI_RH_DESCRIPTOR_A);
3360 1.1 augustss hubd = ohci_hubd;
3361 1.1 augustss hubd.bNbrPorts = sc->sc_noport;
3362 1.15 augustss USETW(hubd.wHubCharacteristics,
3363 1.120 augustss (v & OHCI_NPS ? UHD_PWR_NO_SWITCH :
3364 1.1 augustss v & OHCI_PSM ? UHD_PWR_GANGED : UHD_PWR_INDIVIDUAL)
3365 1.1 augustss /* XXX overcurrent */
3366 1.1 augustss );
3367 1.1 augustss hubd.bPwrOn2PwrGood = OHCI_GET_POTPGT(v);
3368 1.1 augustss v = OREAD4(sc, OHCI_RH_DESCRIPTOR_B);
3369 1.120 augustss for (i = 0, l = sc->sc_noport; l > 0; i++, l -= 8, v >>= 8)
3370 1.15 augustss hubd.DeviceRemovable[i++] = (u_int8_t)v;
3371 1.15 augustss hubd.bDescLength = USB_HUB_DESCRIPTOR_SIZE + i;
3372 1.1 augustss l = min(len, hubd.bDescLength);
3373 1.1 augustss totlen = l;
3374 1.1 augustss memcpy(buf, &hubd, l);
3375 1.1 augustss break;
3376 1.1 augustss case C(UR_GET_STATUS, UT_READ_CLASS_DEVICE):
3377 1.1 augustss if (len != 4) {
3378 1.53 augustss err = USBD_IOERROR;
3379 1.1 augustss goto ret;
3380 1.1 augustss }
3381 1.1 augustss memset(buf, 0, len); /* ? XXX */
3382 1.1 augustss totlen = len;
3383 1.1 augustss break;
3384 1.1 augustss case C(UR_GET_STATUS, UT_READ_CLASS_OTHER):
3385 1.1 augustss DPRINTFN(8,("ohci_root_ctrl_transfer: get port status i=%d\n",
3386 1.1 augustss index));
3387 1.1 augustss if (index < 1 || index > sc->sc_noport) {
3388 1.53 augustss err = USBD_IOERROR;
3389 1.1 augustss goto ret;
3390 1.1 augustss }
3391 1.1 augustss if (len != 4) {
3392 1.53 augustss err = USBD_IOERROR;
3393 1.1 augustss goto ret;
3394 1.1 augustss }
3395 1.1 augustss v = OREAD4(sc, OHCI_RH_PORT_STATUS(index));
3396 1.1 augustss DPRINTFN(8,("ohci_root_ctrl_transfer: port status=0x%04x\n",
3397 1.1 augustss v));
3398 1.1 augustss USETW(ps.wPortStatus, v);
3399 1.1 augustss USETW(ps.wPortChange, v >> 16);
3400 1.1 augustss l = min(len, sizeof ps);
3401 1.1 augustss memcpy(buf, &ps, l);
3402 1.1 augustss totlen = l;
3403 1.1 augustss break;
3404 1.1 augustss case C(UR_SET_DESCRIPTOR, UT_WRITE_CLASS_DEVICE):
3405 1.53 augustss err = USBD_IOERROR;
3406 1.1 augustss goto ret;
3407 1.1 augustss case C(UR_SET_FEATURE, UT_WRITE_CLASS_DEVICE):
3408 1.1 augustss break;
3409 1.1 augustss case C(UR_SET_FEATURE, UT_WRITE_CLASS_OTHER):
3410 1.1 augustss if (index < 1 || index > sc->sc_noport) {
3411 1.53 augustss err = USBD_IOERROR;
3412 1.1 augustss goto ret;
3413 1.1 augustss }
3414 1.1 augustss port = OHCI_RH_PORT_STATUS(index);
3415 1.1 augustss switch(value) {
3416 1.1 augustss case UHF_PORT_ENABLE:
3417 1.1 augustss OWRITE4(sc, port, UPS_PORT_ENABLED);
3418 1.1 augustss break;
3419 1.1 augustss case UHF_PORT_SUSPEND:
3420 1.1 augustss OWRITE4(sc, port, UPS_SUSPEND);
3421 1.1 augustss break;
3422 1.1 augustss case UHF_PORT_RESET:
3423 1.14 augustss DPRINTFN(5,("ohci_root_ctrl_transfer: reset port %d\n",
3424 1.14 augustss index));
3425 1.1 augustss OWRITE4(sc, port, UPS_RESET);
3426 1.110 augustss for (i = 0; i < 5; i++) {
3427 1.110 augustss usb_delay_ms(&sc->sc_bus,
3428 1.110 augustss USB_PORT_ROOT_RESET_DELAY);
3429 1.116 augustss if (sc->sc_dying) {
3430 1.116 augustss err = USBD_IOERROR;
3431 1.116 augustss goto ret;
3432 1.116 augustss }
3433 1.1 augustss if ((OREAD4(sc, port) & UPS_RESET) == 0)
3434 1.1 augustss break;
3435 1.1 augustss }
3436 1.1 augustss DPRINTFN(8,("ohci port %d reset, status = 0x%04x\n",
3437 1.1 augustss index, OREAD4(sc, port)));
3438 1.1 augustss break;
3439 1.1 augustss case UHF_PORT_POWER:
3440 1.14 augustss DPRINTFN(2,("ohci_root_ctrl_transfer: set port power "
3441 1.14 augustss "%d\n", index));
3442 1.1 augustss OWRITE4(sc, port, UPS_PORT_POWER);
3443 1.1 augustss break;
3444 1.1 augustss default:
3445 1.53 augustss err = USBD_IOERROR;
3446 1.1 augustss goto ret;
3447 1.1 augustss }
3448 1.1 augustss break;
3449 1.1 augustss default:
3450 1.53 augustss err = USBD_IOERROR;
3451 1.1 augustss goto ret;
3452 1.1 augustss }
3453 1.53 augustss xfer->actlen = totlen;
3454 1.53 augustss err = USBD_NORMAL_COMPLETION;
3455 1.1 augustss ret:
3456 1.53 augustss xfer->status = err;
3457 1.182.12.1 itohy #if 0 /* root ctrl doesn't do DMA */
3458 1.182.12.3 itohy ohci_transfer_complete(xfer, 0);
3459 1.182.12.1 itohy #else
3460 1.182.12.3 itohy s = splusb();
3461 1.53 augustss usb_transfer_complete(xfer);
3462 1.46 augustss splx(s);
3463 1.182.12.3 itohy #endif
3464 1.1 augustss return (USBD_IN_PROGRESS);
3465 1.1 augustss }
3466 1.1 augustss
3467 1.1 augustss /* Abort a root control request. */
3468 1.82 augustss Static void
3469 1.179 christos ohci_root_ctrl_abort(usbd_xfer_handle xfer)
3470 1.1 augustss {
3471 1.9 augustss /* Nothing to do, all transfers are synchronous. */
3472 1.1 augustss }
3473 1.1 augustss
3474 1.1 augustss /* Close the root pipe. */
3475 1.82 augustss Static void
3476 1.179 christos ohci_root_ctrl_close(usbd_pipe_handle pipe)
3477 1.1 augustss {
3478 1.1 augustss DPRINTF(("ohci_root_ctrl_close\n"));
3479 1.34 augustss /* Nothing to do. */
3480 1.1 augustss }
3481 1.1 augustss
3482 1.82 augustss Static usbd_status
3483 1.91 augustss ohci_root_intr_transfer(usbd_xfer_handle xfer)
3484 1.1 augustss {
3485 1.182.12.1 itohy ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
3486 1.53 augustss usbd_status err;
3487 1.17 augustss
3488 1.46 augustss /* Insert last in queue. */
3489 1.182.12.1 itohy err = usb_insert_transfer_dma(xfer, &sc->sc_dmatag,
3490 1.182.12.1 itohy &OXFER(xfer)->dmabuf);
3491 1.53 augustss if (err)
3492 1.53 augustss return (err);
3493 1.46 augustss
3494 1.46 augustss /* Pipe isn't running, start first */
3495 1.53 augustss return (ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
3496 1.17 augustss }
3497 1.17 augustss
3498 1.82 augustss Static usbd_status
3499 1.91 augustss ohci_root_intr_start(usbd_xfer_handle xfer)
3500 1.17 augustss {
3501 1.182.12.1 itohy ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
3502 1.1 augustss
3503 1.83 augustss if (sc->sc_dying)
3504 1.83 augustss return (USBD_IOERROR);
3505 1.182.12.2 itohy if (xfer->rqflags & URQ_DEV_MAP_MBUF)
3506 1.182.12.2 itohy return (USBD_INVAL); /* mbuf transfer is not supported */
3507 1.83 augustss
3508 1.53 augustss sc->sc_intrxfer = xfer;
3509 1.1 augustss
3510 1.1 augustss return (USBD_IN_PROGRESS);
3511 1.1 augustss }
3512 1.1 augustss
3513 1.3 augustss /* Abort a root interrupt request. */
3514 1.82 augustss Static void
3515 1.91 augustss ohci_root_intr_abort(usbd_xfer_handle xfer)
3516 1.1 augustss {
3517 1.182.12.1 itohy usbd_pipe_handle pipe = xfer->pipe;
3518 1.53 augustss
3519 1.182.12.1 itohy if (pipe->intrxfer == xfer) {
3520 1.51 augustss DPRINTF(("ohci_root_intr_abort: remove\n"));
3521 1.182.12.1 itohy pipe->intrxfer = NULL;
3522 1.51 augustss }
3523 1.53 augustss xfer->status = USBD_CANCELLED;
3524 1.182.12.3 itohy ohci_transfer_complete(xfer, 0);
3525 1.1 augustss }
3526 1.1 augustss
3527 1.1 augustss /* Close the root pipe. */
3528 1.82 augustss Static void
3529 1.91 augustss ohci_root_intr_close(usbd_pipe_handle pipe)
3530 1.1 augustss {
3531 1.1 augustss ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
3532 1.120 augustss
3533 1.1 augustss DPRINTF(("ohci_root_intr_close\n"));
3534 1.34 augustss
3535 1.53 augustss sc->sc_intrxfer = NULL;
3536 1.1 augustss }
3537 1.1 augustss
3538 1.1 augustss /************************/
3539 1.1 augustss
3540 1.82 augustss Static usbd_status
3541 1.91 augustss ohci_device_ctrl_transfer(usbd_xfer_handle xfer)
3542 1.1 augustss {
3543 1.182.12.1 itohy ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
3544 1.53 augustss usbd_status err;
3545 1.17 augustss
3546 1.46 augustss /* Insert last in queue. */
3547 1.182.12.1 itohy err = usb_insert_transfer_dma(xfer, &sc->sc_dmatag,
3548 1.182.12.1 itohy &OXFER(xfer)->dmabuf);
3549 1.53 augustss if (err)
3550 1.53 augustss return (err);
3551 1.46 augustss
3552 1.46 augustss /* Pipe isn't running, start first */
3553 1.53 augustss return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
3554 1.17 augustss }
3555 1.17 augustss
3556 1.82 augustss Static usbd_status
3557 1.91 augustss ohci_device_ctrl_start(usbd_xfer_handle xfer)
3558 1.17 augustss {
3559 1.53 augustss ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
3560 1.53 augustss usbd_status err;
3561 1.1 augustss
3562 1.83 augustss if (sc->sc_dying)
3563 1.83 augustss return (USBD_IOERROR);
3564 1.83 augustss
3565 1.42 augustss #ifdef DIAGNOSTIC
3566 1.53 augustss if (!(xfer->rqflags & URQ_REQUEST)) {
3567 1.1 augustss /* XXX panic */
3568 1.1 augustss printf("ohci_device_ctrl_transfer: not a request\n");
3569 1.1 augustss return (USBD_INVAL);
3570 1.1 augustss }
3571 1.42 augustss #endif
3572 1.1 augustss
3573 1.53 augustss err = ohci_device_request(xfer);
3574 1.53 augustss if (err)
3575 1.53 augustss return (err);
3576 1.1 augustss
3577 1.6 augustss if (sc->sc_bus.use_polling)
3578 1.53 augustss ohci_waitintr(sc, xfer);
3579 1.1 augustss return (USBD_IN_PROGRESS);
3580 1.1 augustss }
3581 1.1 augustss
3582 1.1 augustss /* Abort a device control request. */
3583 1.82 augustss Static void
3584 1.91 augustss ohci_device_ctrl_abort(usbd_xfer_handle xfer)
3585 1.1 augustss {
3586 1.53 augustss DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer));
3587 1.54 augustss ohci_abort_xfer(xfer, USBD_CANCELLED);
3588 1.1 augustss }
3589 1.1 augustss
3590 1.1 augustss /* Close a device control pipe. */
3591 1.82 augustss Static void
3592 1.91 augustss ohci_device_ctrl_close(usbd_pipe_handle pipe)
3593 1.1 augustss {
3594 1.60 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
3595 1.1 augustss ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
3596 1.1 augustss
3597 1.34 augustss DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe));
3598 1.34 augustss ohci_close_pipe(pipe, sc->sc_ctrl_head);
3599 1.182.12.1 itohy ohci_free_std_norsv(sc, opipe->tail.td);
3600 1.182.12.1 itohy usb_freemem(&sc->sc_dmatag, &opipe->u.ctl.reqdma);
3601 1.3 augustss }
3602 1.3 augustss
3603 1.3 augustss /************************/
3604 1.37 augustss
3605 1.82 augustss Static void
3606 1.91 augustss ohci_device_clear_toggle(usbd_pipe_handle pipe)
3607 1.37 augustss {
3608 1.37 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
3609 1.168 augustss ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
3610 1.37 augustss
3611 1.168 augustss opipe->sed->ed.ed_headp &= HTOO32(~OHCI_TOGGLECARRY);
3612 1.37 augustss }
3613 1.37 augustss
3614 1.82 augustss Static void
3615 1.179 christos ohci_noop(usbd_pipe_handle pipe)
3616 1.37 augustss {
3617 1.37 augustss }
3618 1.3 augustss
3619 1.82 augustss Static usbd_status
3620 1.91 augustss ohci_device_bulk_transfer(usbd_xfer_handle xfer)
3621 1.3 augustss {
3622 1.182.12.1 itohy ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
3623 1.53 augustss usbd_status err;
3624 1.17 augustss
3625 1.46 augustss /* Insert last in queue. */
3626 1.182.12.1 itohy err = usb_insert_transfer_dma(xfer, &sc->sc_dmatag,
3627 1.182.12.1 itohy &OXFER(xfer)->dmabuf);
3628 1.53 augustss if (err)
3629 1.53 augustss return (err);
3630 1.46 augustss
3631 1.46 augustss /* Pipe isn't running, start first */
3632 1.53 augustss return (ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
3633 1.17 augustss }
3634 1.17 augustss
3635 1.82 augustss Static usbd_status
3636 1.91 augustss ohci_device_bulk_start(usbd_xfer_handle xfer)
3637 1.17 augustss {
3638 1.53 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
3639 1.3 augustss usbd_device_handle dev = opipe->pipe.device;
3640 1.3 augustss ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
3641 1.3 augustss int addr = dev->address;
3642 1.48 augustss ohci_soft_td_t *data, *tail, *tdp;
3643 1.3 augustss ohci_soft_ed_t *sed;
3644 1.182.12.1 itohy ohci_physaddr_t dmaadr;
3645 1.40 augustss int s, len, isread, endpt;
3646 1.53 augustss usbd_status err;
3647 1.3 augustss
3648 1.83 augustss if (sc->sc_dying)
3649 1.83 augustss return (USBD_IOERROR);
3650 1.83 augustss
3651 1.34 augustss #ifdef DIAGNOSTIC
3652 1.53 augustss if (xfer->rqflags & URQ_REQUEST) {
3653 1.3 augustss /* XXX panic */
3654 1.34 augustss printf("ohci_device_bulk_start: a request\n");
3655 1.3 augustss return (USBD_INVAL);
3656 1.3 augustss }
3657 1.34 augustss #endif
3658 1.3 augustss
3659 1.53 augustss len = xfer->length;
3660 1.53 augustss endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
3661 1.40 augustss isread = UE_GET_DIR(endpt) == UE_DIR_IN;
3662 1.3 augustss sed = opipe->sed;
3663 1.3 augustss
3664 1.53 augustss DPRINTFN(4,("ohci_device_bulk_start: xfer=%p len=%d isread=%d "
3665 1.53 augustss "flags=%d endpt=%d\n", xfer, len, isread, xfer->flags,
3666 1.40 augustss endpt));
3667 1.34 augustss
3668 1.32 augustss opipe->u.bulk.isread = isread;
3669 1.3 augustss opipe->u.bulk.length = len;
3670 1.3 augustss
3671 1.3 augustss /* Update device address */
3672 1.168 augustss sed->ed.ed_flags = HTOO32(
3673 1.168 augustss (O32TOH(sed->ed.ed_flags) & ~OHCI_ED_ADDRMASK) |
3674 1.16 augustss OHCI_ED_SET_FA(addr));
3675 1.3 augustss
3676 1.48 augustss /* Allocate a chain of new TDs (including a new tail). */
3677 1.60 augustss data = opipe->tail.td;
3678 1.77 augustss err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer,
3679 1.77 augustss data, &tail);
3680 1.77 augustss /* We want interrupt at the end of the transfer. */
3681 1.168 augustss tail->td.td_flags &= HTOO32(~OHCI_TD_INTR_MASK);
3682 1.168 augustss tail->td.td_flags |= HTOO32(OHCI_TD_SET_DI(1));
3683 1.77 augustss tail->flags |= OHCI_CALL_DONE;
3684 1.182.12.1 itohy OHCI_STD_SYNC(sc, tail, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
3685 1.77 augustss tail = tail->nexttd; /* point at sentinel */
3686 1.53 augustss if (err)
3687 1.53 augustss return (err);
3688 1.48 augustss
3689 1.53 augustss tail->xfer = NULL;
3690 1.53 augustss xfer->hcpriv = data;
3691 1.3 augustss
3692 1.34 augustss DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x "
3693 1.34 augustss "td_cbp=0x%08x td_be=0x%08x\n",
3694 1.168 augustss (int)O32TOH(sed->ed.ed_flags),
3695 1.168 augustss (int)O32TOH(data->td.td_flags),
3696 1.168 augustss (int)O32TOH(data->td.td_cbp),
3697 1.168 augustss (int)O32TOH(data->td.td_be)));
3698 1.34 augustss
3699 1.182.12.1 itohy #ifdef USB_DEBUG
3700 1.75 augustss if (ohcidebug > 5) {
3701 1.168 augustss ohci_dump_ed(sc, sed);
3702 1.168 augustss ohci_dump_tds(sc, data);
3703 1.34 augustss }
3704 1.34 augustss #endif
3705 1.34 augustss
3706 1.3 augustss /* Insert ED in schedule */
3707 1.3 augustss s = splusb();
3708 1.48 augustss for (tdp = data; tdp != tail; tdp = tdp->nexttd) {
3709 1.53 augustss tdp->xfer = xfer;
3710 1.48 augustss }
3711 1.182.12.1 itohy dmaadr = OHCI_STD_DMAADDR(tail);
3712 1.182.12.1 itohy sed->ed.ed_tailp = HTOO32(dmaadr);
3713 1.60 augustss opipe->tail.td = tail;
3714 1.168 augustss sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP);
3715 1.182.12.1 itohy OHCI_SED_SYNC(sc, sed, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
3716 1.3 augustss OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF);
3717 1.53 augustss if (xfer->timeout && !sc->sc_bus.use_polling) {
3718 1.182.12.1 itohy usb_callout(xfer->timeout_handle, MS_TO_TICKS(xfer->timeout),
3719 1.80 augustss ohci_timeout, xfer);
3720 1.15 augustss }
3721 1.34 augustss
3722 1.52 augustss #if 0
3723 1.52 augustss /* This goes wrong if we are too slow. */
3724 1.75 augustss if (ohcidebug > 10) {
3725 1.75 augustss delay(10000);
3726 1.41 augustss DPRINTF(("ohci_device_intr_transfer: status=%x\n",
3727 1.41 augustss OREAD4(sc, OHCI_COMMAND_STATUS)));
3728 1.168 augustss ohci_dump_ed(sc, sed);
3729 1.168 augustss ohci_dump_tds(sc, data);
3730 1.34 augustss }
3731 1.34 augustss #endif
3732 1.34 augustss
3733 1.3 augustss splx(s);
3734 1.3 augustss
3735 1.182.12.1 itohy if (sc->sc_bus.use_polling)
3736 1.182.12.1 itohy ohci_waitintr(sc, xfer);
3737 1.182.12.1 itohy
3738 1.3 augustss return (USBD_IN_PROGRESS);
3739 1.3 augustss }
3740 1.3 augustss
3741 1.82 augustss Static void
3742 1.91 augustss ohci_device_bulk_abort(usbd_xfer_handle xfer)
3743 1.3 augustss {
3744 1.53 augustss DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer));
3745 1.54 augustss ohci_abort_xfer(xfer, USBD_CANCELLED);
3746 1.3 augustss }
3747 1.3 augustss
3748 1.120 augustss /*
3749 1.34 augustss * Close a device bulk pipe.
3750 1.34 augustss */
3751 1.82 augustss Static void
3752 1.91 augustss ohci_device_bulk_close(usbd_pipe_handle pipe)
3753 1.3 augustss {
3754 1.60 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
3755 1.34 augustss ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
3756 1.3 augustss
3757 1.34 augustss DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe));
3758 1.34 augustss ohci_close_pipe(pipe, sc->sc_bulk_head);
3759 1.182.12.1 itohy ohci_free_std_norsv(sc, opipe->tail.td);
3760 1.1 augustss }
3761 1.1 augustss
3762 1.1 augustss /************************/
3763 1.1 augustss
3764 1.82 augustss Static usbd_status
3765 1.91 augustss ohci_device_intr_transfer(usbd_xfer_handle xfer)
3766 1.17 augustss {
3767 1.182.12.1 itohy ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
3768 1.53 augustss usbd_status err;
3769 1.17 augustss
3770 1.46 augustss /* Insert last in queue. */
3771 1.182.12.1 itohy err = usb_insert_transfer_dma(xfer, &sc->sc_dmatag,
3772 1.182.12.1 itohy &OXFER(xfer)->dmabuf);
3773 1.53 augustss if (err)
3774 1.53 augustss return (err);
3775 1.46 augustss
3776 1.46 augustss /* Pipe isn't running, start first */
3777 1.53 augustss return (ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue)));
3778 1.17 augustss }
3779 1.17 augustss
3780 1.82 augustss Static usbd_status
3781 1.91 augustss ohci_device_intr_start(usbd_xfer_handle xfer)
3782 1.1 augustss {
3783 1.53 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
3784 1.182.12.1 itohy ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
3785 1.1 augustss ohci_soft_ed_t *sed = opipe->sed;
3786 1.182.12.1 itohy usbd_status err;
3787 1.1 augustss
3788 1.83 augustss if (sc->sc_dying)
3789 1.83 augustss return (USBD_IOERROR);
3790 1.83 augustss
3791 1.182.12.1 itohy DPRINTFN(3, ("ohci_device_intr_start: xfer=%p len=%d "
3792 1.14 augustss "flags=%d priv=%p\n",
3793 1.53 augustss xfer, xfer->length, xfer->flags, xfer->priv));
3794 1.1 augustss
3795 1.42 augustss #ifdef DIAGNOSTIC
3796 1.53 augustss if (xfer->rqflags & URQ_REQUEST)
3797 1.182.12.1 itohy panic("ohci_device_intr_start: a request");
3798 1.42 augustss #endif
3799 1.1 augustss
3800 1.182.12.1 itohy err = ohci_device_intr_insert(sc, xfer);
3801 1.182.12.1 itohy if (err)
3802 1.182.12.1 itohy return (err);
3803 1.182.12.1 itohy
3804 1.182.12.1 itohy sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP);
3805 1.182.12.1 itohy
3806 1.182.12.1 itohy return (USBD_IN_PROGRESS);
3807 1.182.12.1 itohy }
3808 1.182.12.1 itohy
3809 1.182.12.1 itohy /*
3810 1.182.12.1 itohy * Insert an interrupt transfer into an endpoint descriptor list
3811 1.182.12.1 itohy */
3812 1.182.12.1 itohy Static usbd_status
3813 1.182.12.1 itohy ohci_device_intr_insert(ohci_softc_t *sc, usbd_xfer_handle xfer)
3814 1.182.12.1 itohy {
3815 1.182.12.1 itohy struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
3816 1.182.12.1 itohy ohci_soft_ed_t *sed = opipe->sed;
3817 1.182.12.1 itohy ohci_soft_td_t *data, *tail;
3818 1.182.12.1 itohy ohci_physaddr_t dataphys, physend;
3819 1.182.12.1 itohy ohci_physaddr_t dmaadr;
3820 1.182.12.1 itohy int s, isread, endpt;
3821 1.182.12.1 itohy struct usb_buffer_dma *ub = &OXFER(xfer)->dmabuf;
3822 1.182.12.1 itohy bus_dma_segment_t *segs = USB_BUFFER_SEGS(ub);
3823 1.182.12.1 itohy int nsegs = USB_BUFFER_NSEGS(ub);
3824 1.182.12.1 itohy
3825 1.182.12.1 itohy DPRINTFN(4, ("ohci_device_intr_insert: xfer=%p", xfer));
3826 1.182.12.1 itohy
3827 1.165 skrll endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
3828 1.165 skrll isread = UE_GET_DIR(endpt) == UE_DIR_IN;
3829 1.1 augustss
3830 1.60 augustss data = opipe->tail.td;
3831 1.1 augustss tail = ohci_alloc_std(sc);
3832 1.55 augustss if (tail == NULL)
3833 1.43 augustss return (USBD_NOMEM);
3834 1.53 augustss tail->xfer = NULL;
3835 1.1 augustss
3836 1.168 augustss data->td.td_flags = HTOO32(
3837 1.165 skrll isread ? OHCI_TD_IN : OHCI_TD_OUT |
3838 1.165 skrll OHCI_TD_NOCC |
3839 1.16 augustss OHCI_TD_SET_DI(1) | OHCI_TD_TOGGLE_CARRY);
3840 1.53 augustss if (xfer->flags & USBD_SHORT_XFER_OK)
3841 1.168 augustss data->td.td_flags |= HTOO32(OHCI_TD_R);
3842 1.182.12.1 itohy /*
3843 1.182.12.1 itohy * Assume a short mapping with no complications, which
3844 1.182.12.1 itohy * should always be true for <= 4k buffers in contiguous
3845 1.182.12.1 itohy * virtual memory. The data can take the following forms:
3846 1.182.12.1 itohy * 1 segment in 1 OHCI page
3847 1.182.12.1 itohy * 1 segment in 2 OHCI pages
3848 1.182.12.1 itohy * 2 segments in 2 OHCI pages
3849 1.182.12.1 itohy * (see comment in ohci_alloc_std_chain() for details)
3850 1.182.12.1 itohy */
3851 1.182.12.1 itohy USB_KASSERT2(xfer->length > 0 && xfer->length <= OHCI_PAGE_SIZE,
3852 1.182.12.1 itohy ("ohci_device_intr_insert: bad length %d", xfer->length));
3853 1.182.12.1 itohy dataphys = segs[0].ds_addr;
3854 1.182.12.1 itohy physend = dataphys + xfer->length - 1;
3855 1.182.12.1 itohy if (nsegs == 2) {
3856 1.182.12.1 itohy USB_KASSERT2(OHCI_PAGE_OFFSET(dataphys +
3857 1.182.12.1 itohy segs[0].ds_len) == 0,
3858 1.182.12.1 itohy ("ohci_device_intr_insert: bad seg 0 termination"));
3859 1.182.12.1 itohy physend = segs[1].ds_addr + xfer->length -
3860 1.182.12.1 itohy segs[0].ds_len - 1;
3861 1.182.12.1 itohy } else {
3862 1.182.12.1 itohy USB_KASSERT2(nsegs == 1,
3863 1.182.12.1 itohy ("ohci_device_intr_insert: bad seg count %d",
3864 1.182.12.1 itohy (u_int)nsegs));
3865 1.182.12.1 itohy }
3866 1.182.12.1 itohy data->td.td_cbp = HTOO32(dataphys);
3867 1.48 augustss data->nexttd = tail;
3868 1.182.12.1 itohy dmaadr = OHCI_STD_DMAADDR(tail);
3869 1.182.12.1 itohy data->td.td_nexttd = HTOO32(dmaadr);
3870 1.182.12.1 itohy data->td.td_be = HTOO32(physend);
3871 1.182.12.1 itohy data->len = xfer->length;
3872 1.53 augustss data->xfer = xfer;
3873 1.48 augustss data->flags = OHCI_CALL_DONE | OHCI_ADD_LEN;
3874 1.53 augustss xfer->hcpriv = data;
3875 1.182.12.1 itohy xfer->actlen = 0;
3876 1.182.12.1 itohy OHCI_STD_SYNC(sc, data, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
3877 1.1 augustss
3878 1.182.12.1 itohy #ifdef USB_DEBUG
3879 1.1 augustss if (ohcidebug > 5) {
3880 1.182.12.1 itohy DPRINTF(("ohci_device_intr_insert:\n"));
3881 1.168 augustss ohci_dump_ed(sc, sed);
3882 1.168 augustss ohci_dump_tds(sc, data);
3883 1.1 augustss }
3884 1.1 augustss #endif
3885 1.1 augustss
3886 1.1 augustss /* Insert ED in schedule */
3887 1.1 augustss s = splusb();
3888 1.182.12.1 itohy dmaadr = OHCI_STD_DMAADDR(tail);
3889 1.182.12.1 itohy sed->ed.ed_tailp = HTOO32(dmaadr);
3890 1.182.12.1 itohy OHCI_SED_SYNC(sc, sed, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
3891 1.60 augustss opipe->tail.td = tail;
3892 1.26 augustss splx(s);
3893 1.1 augustss
3894 1.182.12.1 itohy return (USBD_NORMAL_COMPLETION);
3895 1.1 augustss }
3896 1.1 augustss
3897 1.1 augustss /* Abort a device control request. */
3898 1.82 augustss Static void
3899 1.91 augustss ohci_device_intr_abort(usbd_xfer_handle xfer)
3900 1.1 augustss {
3901 1.53 augustss if (xfer->pipe->intrxfer == xfer) {
3902 1.1 augustss DPRINTF(("ohci_device_intr_abort: remove\n"));
3903 1.55 augustss xfer->pipe->intrxfer = NULL;
3904 1.1 augustss }
3905 1.54 augustss ohci_abort_xfer(xfer, USBD_CANCELLED);
3906 1.1 augustss }
3907 1.1 augustss
3908 1.1 augustss /* Close a device interrupt pipe. */
3909 1.82 augustss Static void
3910 1.91 augustss ohci_device_intr_close(usbd_pipe_handle pipe)
3911 1.1 augustss {
3912 1.1 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
3913 1.1 augustss ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
3914 1.1 augustss int nslots = opipe->u.intr.nslots;
3915 1.1 augustss int pos = opipe->u.intr.pos;
3916 1.1 augustss int j;
3917 1.1 augustss ohci_soft_ed_t *p, *sed = opipe->sed;
3918 1.1 augustss int s;
3919 1.1 augustss
3920 1.1 augustss DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n",
3921 1.1 augustss pipe, nslots, pos));
3922 1.1 augustss s = splusb();
3923 1.168 augustss sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
3924 1.168 augustss if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
3925 1.168 augustss (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK))
3926 1.20 augustss usb_delay_ms(&sc->sc_bus, 2);
3927 1.182.12.1 itohy #ifdef DIAGNOSTIC
3928 1.182.12.1 itohy if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) !=
3929 1.182.12.1 itohy (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK))
3930 1.182.12.1 itohy panic("%s: Intr pipe %p still has TDs queued",
3931 1.182.12.1 itohy USBDEVNAME(sc->sc_bus.bdev), pipe);
3932 1.182.12.1 itohy #endif
3933 1.1 augustss
3934 1.1 augustss for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next)
3935 1.182.12.1 itohy ;
3936 1.53 augustss #ifdef DIAGNOSTIC
3937 1.173 christos if (p == NULL)
3938 1.128 provos panic("ohci_device_intr_close: ED not found");
3939 1.53 augustss #endif
3940 1.173 christos p->next = sed->next;
3941 1.173 christos p->ed.ed_nexted = sed->ed.ed_nexted;
3942 1.1 augustss splx(s);
3943 1.1 augustss
3944 1.1 augustss for (j = 0; j < nslots; j++)
3945 1.31 wrstuden --sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS];
3946 1.1 augustss
3947 1.182.12.1 itohy ohci_free_std_norsv(sc, opipe->tail.td);
3948 1.1 augustss ohci_free_sed(sc, opipe->sed);
3949 1.1 augustss }
3950 1.1 augustss
3951 1.82 augustss Static usbd_status
3952 1.91 augustss ohci_device_setintr(ohci_softc_t *sc, struct ohci_pipe *opipe, int ival)
3953 1.1 augustss {
3954 1.1 augustss int i, j, s, best;
3955 1.1 augustss u_int npoll, slow, shigh, nslots;
3956 1.1 augustss u_int bestbw, bw;
3957 1.1 augustss ohci_soft_ed_t *hsed, *sed = opipe->sed;
3958 1.182.12.1 itohy ohci_physaddr_t dmaadr;
3959 1.1 augustss
3960 1.1 augustss DPRINTFN(2, ("ohci_setintr: pipe=%p\n", opipe));
3961 1.1 augustss if (ival == 0) {
3962 1.1 augustss printf("ohci_setintr: 0 interval\n");
3963 1.1 augustss return (USBD_INVAL);
3964 1.1 augustss }
3965 1.1 augustss
3966 1.1 augustss npoll = OHCI_NO_INTRS;
3967 1.1 augustss while (npoll > ival)
3968 1.1 augustss npoll /= 2;
3969 1.1 augustss DPRINTFN(2, ("ohci_setintr: ival=%d npoll=%d\n", ival, npoll));
3970 1.1 augustss
3971 1.1 augustss /*
3972 1.1 augustss * We now know which level in the tree the ED must go into.
3973 1.1 augustss * Figure out which slot has most bandwidth left over.
3974 1.1 augustss * Slots to examine:
3975 1.1 augustss * npoll
3976 1.1 augustss * 1 0
3977 1.1 augustss * 2 1 2
3978 1.1 augustss * 4 3 4 5 6
3979 1.1 augustss * 8 7 8 9 10 11 12 13 14
3980 1.1 augustss * N (N-1) .. (N-1+N-1)
3981 1.1 augustss */
3982 1.1 augustss slow = npoll-1;
3983 1.1 augustss shigh = slow + npoll;
3984 1.1 augustss nslots = OHCI_NO_INTRS / npoll;
3985 1.1 augustss for (best = i = slow, bestbw = ~0; i < shigh; i++) {
3986 1.1 augustss bw = 0;
3987 1.1 augustss for (j = 0; j < nslots; j++)
3988 1.28 augustss bw += sc->sc_bws[(i * nslots + j) % OHCI_NO_INTRS];
3989 1.1 augustss if (bw < bestbw) {
3990 1.1 augustss best = i;
3991 1.1 augustss bestbw = bw;
3992 1.1 augustss }
3993 1.1 augustss }
3994 1.120 augustss DPRINTFN(2, ("ohci_setintr: best=%d(%d..%d) bestbw=%d\n",
3995 1.1 augustss best, slow, shigh, bestbw));
3996 1.1 augustss
3997 1.1 augustss s = splusb();
3998 1.1 augustss hsed = sc->sc_eds[best];
3999 1.1 augustss sed->next = hsed->next;
4000 1.39 augustss sed->ed.ed_nexted = hsed->ed.ed_nexted;
4001 1.1 augustss hsed->next = sed;
4002 1.182.12.1 itohy dmaadr = OHCI_SED_DMAADDR(sed);
4003 1.182.12.1 itohy hsed->ed.ed_nexted = HTOO32(dmaadr);
4004 1.1 augustss splx(s);
4005 1.1 augustss
4006 1.1 augustss for (j = 0; j < nslots; j++)
4007 1.28 augustss ++sc->sc_bws[(best * nslots + j) % OHCI_NO_INTRS];
4008 1.1 augustss opipe->u.intr.nslots = nslots;
4009 1.1 augustss opipe->u.intr.pos = best;
4010 1.1 augustss
4011 1.1 augustss DPRINTFN(5, ("ohci_setintr: returns %p\n", opipe));
4012 1.1 augustss return (USBD_NORMAL_COMPLETION);
4013 1.60 augustss }
4014 1.60 augustss
4015 1.60 augustss /***********************/
4016 1.60 augustss
4017 1.60 augustss usbd_status
4018 1.91 augustss ohci_device_isoc_transfer(usbd_xfer_handle xfer)
4019 1.60 augustss {
4020 1.182.12.1 itohy ohci_softc_t *sc = (ohci_softc_t *)xfer->pipe->device->bus;
4021 1.60 augustss usbd_status err;
4022 1.60 augustss
4023 1.60 augustss DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer));
4024 1.60 augustss
4025 1.60 augustss /* Put it on our queue, */
4026 1.182.12.1 itohy err = usb_insert_transfer_dma(xfer, &sc->sc_dmatag,
4027 1.182.12.1 itohy &OXFER(xfer)->dmabuf);
4028 1.60 augustss
4029 1.60 augustss /* bail out on error, */
4030 1.60 augustss if (err && err != USBD_IN_PROGRESS)
4031 1.60 augustss return (err);
4032 1.60 augustss
4033 1.60 augustss /* XXX should check inuse here */
4034 1.60 augustss
4035 1.60 augustss /* insert into schedule, */
4036 1.60 augustss ohci_device_isoc_enter(xfer);
4037 1.60 augustss
4038 1.83 augustss /* and start if the pipe wasn't running */
4039 1.60 augustss if (!err)
4040 1.60 augustss ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue));
4041 1.60 augustss
4042 1.60 augustss return (err);
4043 1.60 augustss }
4044 1.60 augustss
4045 1.60 augustss void
4046 1.91 augustss ohci_device_isoc_enter(usbd_xfer_handle xfer)
4047 1.60 augustss {
4048 1.61 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
4049 1.61 augustss usbd_device_handle dev = opipe->pipe.device;
4050 1.61 augustss ohci_softc_t *sc = (ohci_softc_t *)dev->bus;
4051 1.61 augustss ohci_soft_ed_t *sed = opipe->sed;
4052 1.61 augustss struct iso *iso = &opipe->u.iso;
4053 1.182.12.1 itohy struct usb_buffer_dma *ub = &OXFER(xfer)->dmabuf;
4054 1.182.12.1 itohy bus_dma_segment_t *segs = USB_BUFFER_SEGS(ub);
4055 1.182.12.1 itohy int nsegs = USB_BUFFER_NSEGS(ub);
4056 1.120 augustss ohci_soft_itd_t *sitd, *nsitd;
4057 1.182.12.3 itohy ohci_physaddr_t dataphys, physend, prevphysend;
4058 1.182.12.3 itohy ohci_physaddr_t segdmaadr;
4059 1.182.12.1 itohy ohci_physaddr_t dmaadr;
4060 1.182.12.3 itohy int i, len, ncur, nframes, seg, seglen, seglen1;
4061 1.182.12.3 itohy int useaux, npagecross;
4062 1.61 augustss int s;
4063 1.182.12.3 itohy #if 1
4064 1.182.12.3 itohy union usb_bufptr bufptr;
4065 1.182.12.3 itohy int endpt, isread, is_mbuf;
4066 1.182.12.3 itohy bus_addr_t auxdma;
4067 1.182.12.3 itohy #endif
4068 1.182.12.3 itohy #if 1
4069 1.182.12.3 itohy uint32_t sitdo, tailo;
4070 1.182.12.3 itohy #endif
4071 1.61 augustss
4072 1.83 augustss DPRINTFN(1,("ohci_device_isoc_enter: used=%d next=%d xfer=%p "
4073 1.83 augustss "nframes=%d\n",
4074 1.83 augustss iso->inuse, iso->next, xfer, xfer->nframes));
4075 1.83 augustss
4076 1.83 augustss if (sc->sc_dying)
4077 1.83 augustss return;
4078 1.83 augustss
4079 1.83 augustss if (iso->next == -1) {
4080 1.83 augustss /* Not in use yet, schedule it a few frames ahead. */
4081 1.182.12.3 itohy USB_MEM_SYNC2(&sc->sc_dmatag, &sc->sc_hccadma,
4082 1.182.12.3 itohy offsetof(struct ohci_hcca, hcca_frame_number),
4083 1.182.12.3 itohy sizeof(sc->sc_hcca->hcca_frame_number),
4084 1.182.12.3 itohy BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
4085 1.182.12.3 itohy iso->next = (uint16_t)(O32TOH(sc->sc_hcca->hcca_frame_number) + 5);
4086 1.120 augustss DPRINTFN(2,("ohci_device_isoc_enter: start next=%d\n",
4087 1.83 augustss iso->next));
4088 1.182.12.3 itohy
4089 1.182.12.3 itohy #if 1
4090 1.182.12.3 itohy OHCI_SED_SYNC_POST(sc, sed);
4091 1.182.12.3 itohy if (sed->ed.ed_headp != sed->ed.ed_tailp) {
4092 1.182.12.3 itohy /* set SKIP first */
4093 1.182.12.3 itohy sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP);
4094 1.182.12.3 itohy OHCI_SED_SYNC2(sc, sed,
4095 1.182.12.3 itohy offsetof(ohci_ed_t, ed_flags), sizeof(u_int32_t),
4096 1.182.12.3 itohy BUS_DMASYNC_PREWRITE);
4097 1.182.12.3 itohy
4098 1.182.12.3 itohy /* wait for SKIP to take effect */
4099 1.182.12.3 itohy delay(2100);
4100 1.182.12.3 itohy
4101 1.182.12.3 itohy OHCI_SED_SYNC_POST(sc, sed);
4102 1.182.12.3 itohy
4103 1.182.12.3 itohy tailo = sed->ed.ed_tailp;
4104 1.182.12.3 itohy for (sitdo = sed->ed.ed_headp; sitdo != tailo;
4105 1.182.12.3 itohy sitdo = sitd->itd.itd_nextitd) {
4106 1.182.12.3 itohy sitd = ohci_find_itd(sc, O32TOH(sitdo));
4107 1.182.12.3 itohy *(uint16_t *)&sitd->itd.itd_flags =
4108 1.182.12.3 itohy HTOO16(iso->next);
4109 1.182.12.3 itohy iso->next = (uint16_t)(iso->next +
4110 1.182.12.3 itohy OHCI_ITD_GET_FC(O32TOH(sitd->itd.itd_flags)));
4111 1.182.12.3 itohy OHCI_SITD_SYNC(sc, sitd,
4112 1.182.12.3 itohy BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
4113 1.182.12.3 itohy }
4114 1.182.12.3 itohy
4115 1.182.12.3 itohy /* clear SKIP */
4116 1.182.12.3 itohy sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP);
4117 1.182.12.3 itohy OHCI_SED_SYNC2(sc, sed,
4118 1.182.12.3 itohy offsetof(ohci_ed_t, ed_flags), sizeof(u_int32_t),
4119 1.182.12.3 itohy BUS_DMASYNC_PREWRITE);
4120 1.182.12.3 itohy }
4121 1.182.12.3 itohy #endif
4122 1.83 augustss }
4123 1.83 augustss
4124 1.182.12.3 itohy usb_bufptr_init(&bufptr, xfer);
4125 1.182.12.3 itohy
4126 1.61 augustss sitd = opipe->tail.itd;
4127 1.61 augustss nframes = xfer->nframes;
4128 1.83 augustss xfer->hcpriv = sitd;
4129 1.182.12.3 itohy endpt = xfer->pipe->endpoint->edesc->bEndpointAddress;
4130 1.182.12.3 itohy isread = UE_GET_DIR(endpt) == UE_DIR_IN;
4131 1.182.12.3 itohy is_mbuf = xfer->rqflags & URQ_DEV_MAP_MBUF;
4132 1.182.12.3 itohy
4133 1.182.12.3 itohy #ifdef DIAGNOSTIC
4134 1.182.12.3 itohy segdmaadr = 0xbbbbbbbb; /* XXX -Wuninitialized */
4135 1.182.12.3 itohy dataphys = 0x77777777; /* XXX -Wuninitialized */
4136 1.182.12.3 itohy physend = 0xeeeeeeee; /* XXX -Wuninitialized */
4137 1.182.12.3 itohy prevphysend = 0x99999999; /* XXX -Wuninitialized */
4138 1.182.12.3 itohy #else
4139 1.182.12.3 itohy segdmaadr = 0; /* XXX -Wuninitialized */
4140 1.182.12.3 itohy dataphys = 0; /* XXX -Wuninitialized */
4141 1.182.12.3 itohy physend = 0; /* XXX -Wuninitialized */
4142 1.182.12.3 itohy prevphysend = 0; /* XXX -Wuninitialized */
4143 1.182.12.3 itohy #endif
4144 1.182.12.3 itohy
4145 1.182.12.1 itohy seg = 0;
4146 1.182.12.3 itohy seglen = 0;
4147 1.182.12.3 itohy useaux = 0;
4148 1.182.12.1 itohy i = 0;
4149 1.182.12.1 itohy while (i < nframes) {
4150 1.182.12.1 itohy ncur = 0;
4151 1.182.12.3 itohy npagecross = 0;
4152 1.182.12.3 itohy do {
4153 1.182.12.3 itohy /*
4154 1.182.12.3 itohy * Fill in as many ITD frames as possible.
4155 1.182.12.3 itohy */
4156 1.182.12.3 itohy
4157 1.182.12.1 itohy /* Find the frame start and end physical addresses. */
4158 1.182.12.1 itohy len = xfer->frlengths[i];
4159 1.182.12.3 itohy
4160 1.182.12.3 itohy if (useaux == 0) {
4161 1.182.12.3 itohy /* skip handled segments */
4162 1.182.12.3 itohy if (seglen <= 0) {
4163 1.182.12.3 itohy USB_KASSERT2(seg < nsegs,
4164 1.182.12.3 itohy ("ohci_device_isoc_enter: overrun"));
4165 1.182.12.3 itohy do {
4166 1.182.12.3 itohy seglen1 = seglen;
4167 1.182.12.3 itohy seglen += segs[seg].ds_len;
4168 1.182.12.3 itohy if (seglen1 <= 0 && seglen > 0)
4169 1.182.12.3 itohy segdmaadr =
4170 1.182.12.3 itohy segs[seg].ds_addr
4171 1.182.12.3 itohy - seglen1;
4172 1.182.12.3 itohy } while (++seg < nsegs &&
4173 1.182.12.3 itohy (seglen <= 0 ||
4174 1.182.12.3 itohy segdmaadr + seglen ==
4175 1.182.12.3 itohy segs[seg].ds_addr));
4176 1.182.12.3 itohy }
4177 1.182.12.3 itohy
4178 1.182.12.3 itohy /* DMA start and end addresses of the frame */
4179 1.182.12.3 itohy if (len <= seglen) {
4180 1.182.12.3 itohy /* the frame fits in the segment */
4181 1.182.12.3 itohy physend = segdmaadr + len - 1;
4182 1.182.12.3 itohy dataphys = segdmaadr;
4183 1.182.12.3 itohy } else if (/* len > seglen */
4184 1.182.12.3 itohy (OHCI_PAGE_OFFSET(segdmaadr + seglen) ||
4185 1.182.12.3 itohy OHCI_PAGE_OFFSET(segs[seg].ds_addr) ||
4186 1.182.12.3 itohy len > seglen + segs[seg].ds_len)) {
4187 1.182.12.3 itohy
4188 1.182.12.3 itohy DPRINTF(("ohci_device_isoc_enter: need aux len %#x dma %#x seglen %#x nextseg %#x\n", len, segdmaadr, seglen, (unsigned)segs[seg].ds_addr));
4189 1.182.12.3 itohy /* need aux memory */
4190 1.182.12.3 itohy useaux = 1;
4191 1.182.12.3 itohy if (ncur > 0) {
4192 1.182.12.3 itohy /* doesn't fit for now */
4193 1.182.12.3 itohy break;
4194 1.182.12.3 itohy } else {
4195 1.182.12.3 itohy goto doaux; /* shortcut */
4196 1.182.12.3 itohy }
4197 1.182.12.3 itohy } else { /* len > seglen */
4198 1.182.12.3 itohy /* the frame ends in the next segment */
4199 1.182.12.3 itohy physend = segs[seg].ds_addr +
4200 1.182.12.3 itohy (len - seglen - 1);
4201 1.182.12.3 itohy dataphys = segdmaadr;
4202 1.182.12.3 itohy }
4203 1.182.12.1 itohy }
4204 1.182.12.3 itohy
4205 1.182.12.3 itohy if (useaux) {
4206 1.182.12.3 itohy doaux:
4207 1.182.12.3 itohy USB_KASSERT(ncur == 0); /* for simplicity */
4208 1.182.12.3 itohy
4209 1.182.12.3 itohy /* need aux memory */
4210 1.182.12.3 itohy auxdma = ohci_aux_dma_alloc(&OXFER(xfer)->aux,
4211 1.182.12.3 itohy &bufptr, len, &sitd->ad);
4212 1.182.12.3 itohy
4213 1.182.12.3 itohy /* prepare aux DMA */
4214 1.182.12.3 itohy if (!isread)
4215 1.182.12.3 itohy usb_bufptr_wr(&bufptr,
4216 1.182.12.3 itohy sitd->ad.aux_kern, len, is_mbuf);
4217 1.182.12.3 itohy dataphys = auxdma;
4218 1.182.12.3 itohy physend = dataphys + len - 1;
4219 1.182.12.3 itohy
4220 1.182.12.3 itohy useaux = 0;
4221 1.61 augustss }
4222 1.182.12.3 itohy
4223 1.182.12.3 itohy if (ncur == 0) {
4224 1.182.12.3 itohy sitd->itd.itd_bp0 = HTOO32(dataphys);
4225 1.182.12.3 itohy } else {
4226 1.182.12.3 itohy /* check start of new page */
4227 1.182.12.3 itohy if (OHCI_PAGE_OFFSET(dataphys) == 0)
4228 1.182.12.3 itohy npagecross++;
4229 1.182.12.1 itohy }
4230 1.182.12.3 itohy
4231 1.182.12.3 itohy sitd->itd.itd_offset[ncur] =
4232 1.182.12.3 itohy HTOO16(OHCI_ITD_MK_OFFS(npagecross, dataphys));
4233 1.182.12.3 itohy
4234 1.182.12.3 itohy if (OHCI_PAGE(dataphys) != OHCI_PAGE(physend))
4235 1.182.12.3 itohy npagecross++;
4236 1.182.12.3 itohy if (npagecross > 1 ||
4237 1.182.12.1 itohy ((sc->sc_flags & OHCI_FLAG_QUIRK_2ND_4KB) &&
4238 1.182.12.3 itohy npagecross == 1 &&
4239 1.182.12.1 itohy OHCI_PAGE_OFFSET(physend) == OHCI_PAGE_SIZE - 1)) {
4240 1.182.12.3 itohy /* the frame doesn't fit in the ITD */
4241 1.182.12.3 itohy physend = prevphysend;
4242 1.182.12.1 itohy break;
4243 1.182.12.1 itohy }
4244 1.182.12.1 itohy
4245 1.182.12.3 itohy /* the frame is handled */
4246 1.182.12.3 itohy seglen -= len;
4247 1.182.12.3 itohy segdmaadr += len;
4248 1.182.12.3 itohy usb_bufptr_advance(&bufptr, len, is_mbuf);
4249 1.182.12.3 itohy prevphysend = physend;
4250 1.182.12.3 itohy
4251 1.182.12.1 itohy i++;
4252 1.182.12.1 itohy ncur++;
4253 1.182.12.3 itohy
4254 1.182.12.3 itohy } while (ncur < OHCI_ITD_NOFFSET && i < nframes);
4255 1.182.12.1 itohy
4256 1.182.12.1 itohy /* Allocate next ITD */
4257 1.182.12.1 itohy nsitd = ohci_alloc_sitd(sc);
4258 1.182.12.1 itohy if (nsitd == NULL) {
4259 1.182.12.1 itohy /* XXX what now? */
4260 1.182.12.1 itohy printf("%s: isoc TD alloc failed\n",
4261 1.182.12.1 itohy USBDEVNAME(sc->sc_bus.bdev));
4262 1.182.12.1 itohy return;
4263 1.182.12.1 itohy }
4264 1.83 augustss
4265 1.182.12.1 itohy /* Fill out remaining fields of current ITD */
4266 1.182.12.3 itohy sitd->itd.itd_be = HTOO32(physend);
4267 1.182.12.1 itohy sitd->nextitd = nsitd;
4268 1.182.12.1 itohy dmaadr = OHCI_SITD_DMAADDR(nsitd);
4269 1.182.12.1 itohy sitd->itd.itd_nextitd = HTOO32(dmaadr);
4270 1.182.12.1 itohy sitd->xfer = xfer;
4271 1.182.12.3 itohy
4272 1.182.12.1 itohy if (i < nframes) {
4273 1.168 augustss sitd->itd.itd_flags = HTOO32(
4274 1.120 augustss OHCI_ITD_NOCC |
4275 1.61 augustss OHCI_ITD_SET_SF(iso->next) |
4276 1.83 augustss OHCI_ITD_SET_DI(6) | /* delay intr a little */
4277 1.83 augustss OHCI_ITD_SET_FC(ncur));
4278 1.182.12.1 itohy sitd->flags = OHCI_ITD_ACTIVE;
4279 1.182.12.1 itohy } else {
4280 1.182.12.1 itohy sitd->itd.itd_flags = HTOO32(
4281 1.182.12.1 itohy OHCI_ITD_NOCC |
4282 1.182.12.1 itohy OHCI_ITD_SET_SF(iso->next) |
4283 1.182.12.1 itohy OHCI_ITD_SET_DI(0) |
4284 1.182.12.1 itohy OHCI_ITD_SET_FC(ncur));
4285 1.182.12.1 itohy sitd->flags = OHCI_CALL_DONE | OHCI_ITD_ACTIVE;
4286 1.182.12.1 itohy }
4287 1.182.12.3 itohy iso->next = (uint16_t)(iso->next + ncur);
4288 1.182.12.1 itohy
4289 1.182.12.1 itohy OHCI_SITD_SYNC(sc, sitd,
4290 1.182.12.1 itohy BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
4291 1.182.12.1 itohy sitd = nsitd;
4292 1.61 augustss }
4293 1.83 augustss
4294 1.83 augustss iso->inuse += nframes;
4295 1.83 augustss
4296 1.182.12.1 itohy /* XXX pretend we did it all */
4297 1.182.12.1 itohy xfer->actlen = 0;
4298 1.182.12.1 itohy for (i = 0; i < nframes; i++)
4299 1.182.12.1 itohy xfer->actlen += xfer->frlengths[i];
4300 1.83 augustss
4301 1.83 augustss xfer->status = USBD_IN_PROGRESS;
4302 1.83 augustss
4303 1.182.12.1 itohy #ifdef USB_DEBUG
4304 1.83 augustss if (ohcidebug > 5) {
4305 1.182.12.3 itohy USB_MEM_SYNC2(&sc->sc_dmatag, &sc->sc_hccadma,
4306 1.182.12.3 itohy offsetof(struct ohci_hcca, hcca_frame_number),
4307 1.182.12.3 itohy sizeof(sc->sc_hcca->hcca_frame_number),
4308 1.182.12.3 itohy BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
4309 1.83 augustss DPRINTF(("ohci_device_isoc_enter: frame=%d\n",
4310 1.168 augustss O32TOH(sc->sc_hcca->hcca_frame_number)));
4311 1.168 augustss ohci_dump_itds(sc, xfer->hcpriv);
4312 1.168 augustss ohci_dump_ed(sc, sed);
4313 1.83 augustss }
4314 1.83 augustss #endif
4315 1.61 augustss
4316 1.182.12.3 itohy /* sync aux */
4317 1.182.12.3 itohy ohci_aux_dma_sync(sc, &OXFER(xfer)->aux,
4318 1.182.12.3 itohy isread ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
4319 1.182.12.3 itohy
4320 1.83 augustss s = splusb();
4321 1.182.12.1 itohy opipe->tail.itd = sitd;
4322 1.168 augustss sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP);
4323 1.182.12.1 itohy dmaadr = OHCI_SITD_DMAADDR(sitd);
4324 1.182.12.1 itohy sed->ed.ed_tailp = HTOO32(dmaadr);
4325 1.182.12.1 itohy OHCI_SED_SYNC(sc, sed, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
4326 1.61 augustss splx(s);
4327 1.83 augustss
4328 1.182.12.1 itohy #ifdef USB_DEBUG
4329 1.83 augustss if (ohcidebug > 5) {
4330 1.83 augustss delay(150000);
4331 1.182.12.3 itohy USB_MEM_SYNC2(&sc->sc_dmatag, &sc->sc_hccadma,
4332 1.182.12.3 itohy offsetof(struct ohci_hcca, hcca_frame_number),
4333 1.182.12.3 itohy sizeof(sc->sc_hcca->hcca_frame_number),
4334 1.182.12.3 itohy BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
4335 1.83 augustss DPRINTF(("ohci_device_isoc_enter: after frame=%d\n",
4336 1.168 augustss O32TOH(sc->sc_hcca->hcca_frame_number)));
4337 1.168 augustss ohci_dump_itds(sc, xfer->hcpriv);
4338 1.168 augustss ohci_dump_ed(sc, sed);
4339 1.83 augustss }
4340 1.83 augustss #endif
4341 1.60 augustss }
4342 1.60 augustss
4343 1.60 augustss usbd_status
4344 1.91 augustss ohci_device_isoc_start(usbd_xfer_handle xfer)
4345 1.60 augustss {
4346 1.83 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
4347 1.83 augustss ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
4348 1.182.12.1 itohy ohci_soft_ed_t *sed;
4349 1.182.12.1 itohy int s;
4350 1.83 augustss
4351 1.83 augustss DPRINTFN(5,("ohci_device_isoc_start: xfer=%p\n", xfer));
4352 1.83 augustss
4353 1.83 augustss if (sc->sc_dying)
4354 1.83 augustss return (USBD_IOERROR);
4355 1.83 augustss
4356 1.83 augustss #ifdef DIAGNOSTIC
4357 1.83 augustss if (xfer->status != USBD_IN_PROGRESS)
4358 1.121 tsutsui printf("ohci_device_isoc_start: not in progress %p\n", xfer);
4359 1.83 augustss #endif
4360 1.83 augustss
4361 1.83 augustss /* XXX anything to do? */
4362 1.83 augustss
4363 1.182.12.1 itohy s = splusb();
4364 1.182.12.1 itohy sed = opipe->sed; /* Turn off ED skip-bit to start processing */
4365 1.182.12.1 itohy sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* ED's ITD list.*/
4366 1.182.12.1 itohy splx(s);
4367 1.182.12.1 itohy
4368 1.83 augustss return (USBD_IN_PROGRESS);
4369 1.60 augustss }
4370 1.60 augustss
4371 1.60 augustss void
4372 1.91 augustss ohci_device_isoc_abort(usbd_xfer_handle xfer)
4373 1.60 augustss {
4374 1.83 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe;
4375 1.83 augustss ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
4376 1.83 augustss ohci_soft_ed_t *sed;
4377 1.182.12.3 itohy ohci_soft_itd_t *sitd, *tmp_sitd;
4378 1.182.12.1 itohy ohci_physaddr_t dmaadr;
4379 1.182.12.1 itohy int s,undone,num_sitds;
4380 1.83 augustss
4381 1.83 augustss s = splusb();
4382 1.182.12.1 itohy opipe->aborting = 1;
4383 1.83 augustss
4384 1.83 augustss DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p\n", xfer));
4385 1.83 augustss
4386 1.83 augustss /* Transfer is already done. */
4387 1.120 augustss if (xfer->status != USBD_NOT_STARTED &&
4388 1.83 augustss xfer->status != USBD_IN_PROGRESS) {
4389 1.83 augustss splx(s);
4390 1.83 augustss printf("ohci_device_isoc_abort: early return\n");
4391 1.83 augustss return;
4392 1.83 augustss }
4393 1.83 augustss
4394 1.83 augustss /* Give xfer the requested abort code. */
4395 1.83 augustss xfer->status = USBD_CANCELLED;
4396 1.83 augustss
4397 1.83 augustss sed = opipe->sed;
4398 1.168 augustss sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); /* force hardware skip */
4399 1.182.12.3 itohy OHCI_SED_SYNC2(sc, sed,
4400 1.182.12.3 itohy offsetof(ohci_ed_t, ed_flags), sizeof(u_int32_t),
4401 1.182.12.3 itohy BUS_DMASYNC_PREWRITE);
4402 1.83 augustss
4403 1.182.12.1 itohy num_sitds = 0;
4404 1.83 augustss sitd = xfer->hcpriv;
4405 1.83 augustss #ifdef DIAGNOSTIC
4406 1.83 augustss if (sitd == NULL) {
4407 1.102 augustss splx(s);
4408 1.83 augustss printf("ohci_device_isoc_abort: hcpriv==0\n");
4409 1.83 augustss return;
4410 1.83 augustss }
4411 1.83 augustss #endif
4412 1.182.12.1 itohy for (; sitd != NULL && sitd->xfer == xfer; sitd = sitd->nextitd) {
4413 1.182.12.1 itohy num_sitds++;
4414 1.83 augustss #ifdef DIAGNOSTIC
4415 1.83 augustss DPRINTFN(1,("abort sets done sitd=%p\n", sitd));
4416 1.83 augustss sitd->isdone = 1;
4417 1.83 augustss #endif
4418 1.83 augustss }
4419 1.83 augustss
4420 1.83 augustss splx(s);
4421 1.83 augustss
4422 1.182.12.1 itohy /*
4423 1.182.12.1 itohy * Each sitd has up to OHCI_ITD_NOFFSET transfers, each can
4424 1.182.12.1 itohy * take a usb 1ms cycle. Conservatively wait for it to drain.
4425 1.182.12.1 itohy * Even with DMA done, it can take awhile for the "batch"
4426 1.182.12.1 itohy * delivery of completion interrupts to occur thru the controller.
4427 1.182.12.1 itohy */
4428 1.182.12.1 itohy
4429 1.182.12.1 itohy do {
4430 1.182.12.1 itohy usb_delay_ms(&sc->sc_bus, 2*(num_sitds*OHCI_ITD_NOFFSET));
4431 1.182.12.1 itohy
4432 1.182.12.1 itohy undone = 0;
4433 1.182.12.1 itohy tmp_sitd = xfer->hcpriv;
4434 1.182.12.1 itohy for (; tmp_sitd != NULL && tmp_sitd->xfer == xfer;
4435 1.182.12.1 itohy tmp_sitd = tmp_sitd->nextitd) {
4436 1.182.12.1 itohy OHCI_SITD_SYNC(sc, tmp_sitd,
4437 1.182.12.1 itohy BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
4438 1.182.12.1 itohy if (OHCI_CC_NO_ERROR ==
4439 1.182.12.1 itohy OHCI_ITD_GET_CC(O32TOH(tmp_sitd->itd.itd_flags)) &&
4440 1.182.12.1 itohy tmp_sitd->flags & OHCI_ITD_ACTIVE &&
4441 1.182.12.1 itohy (tmp_sitd->flags & OHCI_ITD_INTFIN) == 0)
4442 1.182.12.1 itohy undone++;
4443 1.182.12.1 itohy }
4444 1.182.12.3 itohy } while (undone != 0);
4445 1.182.12.1 itohy
4446 1.182.12.3 itohy #if 0
4447 1.182.12.1 itohy /* Free the sitds */
4448 1.182.12.1 itohy for (sitd = xfer->hcpriv; sitd->xfer == xfer;
4449 1.182.12.1 itohy sitd = sitdnext) {
4450 1.182.12.1 itohy sitdnext = sitd->nextitd;
4451 1.182.12.1 itohy ohci_free_sitd(sc, sitd);
4452 1.182.12.1 itohy }
4453 1.83 augustss
4454 1.182.12.3 itohy /* free aux memory if any */
4455 1.182.12.3 itohy ohci_aux_mem_init(&OXFER(xfer)->aux);
4456 1.182.12.3 itohy #endif
4457 1.182.12.3 itohy
4458 1.83 augustss s = splusb();
4459 1.83 augustss
4460 1.83 augustss /* Run callback. */
4461 1.182.12.3 itohy ohci_transfer_complete(xfer, 0);
4462 1.182.12.1 itohy
4463 1.182.12.1 itohy /* There is always a `next' sitd so link it up. */
4464 1.182.12.1 itohy dmaadr = OHCI_SITD_DMAADDR(sitd);
4465 1.182.12.1 itohy sed->ed.ed_headp = HTOO32(dmaadr);
4466 1.83 augustss
4467 1.168 augustss sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */
4468 1.182.12.1 itohy OHCI_SED_SYNC(sc, sed, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
4469 1.182.12.3 itohy #if 0 /* above should be like this? */
4470 1.182.12.3 itohy OHCI_SED_SYNC2(sc, sed,
4471 1.182.12.3 itohy offsetof(ohci_ed_t, ed_flags), sizeof(u_int32_t),
4472 1.182.12.3 itohy BUS_DMASYNC_PREWRITE);
4473 1.182.12.3 itohy #endif
4474 1.83 augustss
4475 1.83 augustss splx(s);
4476 1.60 augustss }
4477 1.60 augustss
4478 1.60 augustss void
4479 1.179 christos ohci_device_isoc_done(usbd_xfer_handle xfer)
4480 1.60 augustss {
4481 1.182.12.1 itohy /* This null routine corresponds to non-isoc "done()" routines
4482 1.182.12.1 itohy * that free the stds associated with an xfer after a completed
4483 1.182.12.1 itohy * xfer interrupt. However, in the case of isoc transfers, the
4484 1.182.12.1 itohy * sitds associated with the transfer have already been processed
4485 1.182.12.1 itohy * and reallocated for the next iteration by
4486 1.182.12.1 itohy * "ohci_device_isoc_transfer()".
4487 1.182.12.1 itohy *
4488 1.182.12.1 itohy * Routine "usb_transfer_complete()" is called at the end of every
4489 1.182.12.1 itohy * relevant usb interrupt. "usb_transfer_complete()" indirectly
4490 1.182.12.1 itohy * calls 1) "ohci_device_isoc_transfer()" (which keeps pumping the
4491 1.182.12.1 itohy * pipeline by setting up the next transfer iteration) and 2) then
4492 1.182.12.1 itohy * calls "ohci_device_isoc_done()". Isoc transfers have not been
4493 1.182.12.1 itohy * working for the ohci usb because this routine was trashing the
4494 1.182.12.1 itohy * xfer set up for the next iteration (thus, only the first
4495 1.182.12.1 itohy * UGEN_NISOREQS xfers outstanding on an open would work). Perhaps
4496 1.182.12.1 itohy * this could all be re-factored, but that's another pass...
4497 1.182.12.1 itohy */
4498 1.60 augustss }
4499 1.60 augustss
4500 1.60 augustss usbd_status
4501 1.91 augustss ohci_setup_isoc(usbd_pipe_handle pipe)
4502 1.60 augustss {
4503 1.60 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
4504 1.83 augustss ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
4505 1.60 augustss struct iso *iso = &opipe->u.iso;
4506 1.83 augustss int s;
4507 1.60 augustss
4508 1.60 augustss iso->next = -1;
4509 1.60 augustss iso->inuse = 0;
4510 1.60 augustss
4511 1.83 augustss s = splusb();
4512 1.168 augustss ohci_add_ed(sc, opipe->sed, sc->sc_isoc_head);
4513 1.83 augustss splx(s);
4514 1.83 augustss
4515 1.60 augustss return (USBD_NORMAL_COMPLETION);
4516 1.60 augustss }
4517 1.60 augustss
4518 1.60 augustss void
4519 1.91 augustss ohci_device_isoc_close(usbd_pipe_handle pipe)
4520 1.60 augustss {
4521 1.60 augustss struct ohci_pipe *opipe = (struct ohci_pipe *)pipe;
4522 1.60 augustss ohci_softc_t *sc = (ohci_softc_t *)pipe->device->bus;
4523 1.182.12.1 itohy ohci_soft_ed_t *sed;
4524 1.60 augustss
4525 1.60 augustss DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe));
4526 1.182.12.1 itohy
4527 1.182.12.1 itohy sed = opipe->sed;
4528 1.182.12.1 itohy sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); /* Stop device. */
4529 1.182.12.3 itohy OHCI_SED_SYNC2(sc, sed,
4530 1.182.12.3 itohy offsetof(ohci_ed_t, ed_flags), sizeof(u_int32_t),
4531 1.182.12.3 itohy BUS_DMASYNC_PREWRITE);
4532 1.182.12.1 itohy
4533 1.182.12.1 itohy ohci_close_pipe(pipe, sc->sc_isoc_head); /* Stop isoc list, free ED.*/
4534 1.182.12.1 itohy
4535 1.182.12.1 itohy /* up to NISOREQs xfers still outstanding. */
4536 1.182.12.1 itohy
4537 1.83 augustss #ifdef DIAGNOSTIC
4538 1.83 augustss opipe->tail.itd->isdone = 1;
4539 1.83 augustss #endif
4540 1.182.12.1 itohy ohci_free_sitd_norsv(sc, opipe->tail.itd); /* Next `avail free' sitd.*/
4541 1.1 augustss }
4542