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