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