| @@ -1,23 +1,24 @@ | | | @@ -1,23 +1,24 @@ |
1 | /* $NetBSD: ohci.c,v 1.218.6.1 2011/12/04 13:23:16 jmcneill Exp $ */ | | 1 | /* $NetBSD: ohci.c,v 1.218.6.2 2011/12/04 21:02:27 jmcneill Exp $ */ |
2 | /* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */ | | 2 | /* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */ |
3 | | | 3 | |
4 | /* | | 4 | /* |
5 | * Copyright (c) 1998, 2004, 2005 The NetBSD Foundation, Inc. | | 5 | * Copyright (c) 1998, 2004, 2005, 2011 The NetBSD Foundation, Inc. |
6 | * All rights reserved. | | 6 | * All rights reserved. |
7 | * | | 7 | * |
8 | * This code is derived from software contributed to The NetBSD Foundation | | 8 | * This code is derived from software contributed to The NetBSD Foundation |
9 | * by Lennart Augustsson (lennart@augustsson.net) at | | 9 | * by Lennart Augustsson (lennart@augustsson.net) at |
10 | * Carlstedt Research & Technology. | | 10 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca) |
| | | 11 | * and Matthew R. Green. |
11 | * This code is derived from software contributed to The NetBSD Foundation | | 12 | * This code is derived from software contributed to The NetBSD Foundation |
12 | * by Charles M. Hannum. | | 13 | * by Charles M. Hannum. |
13 | * | | 14 | * |
14 | * Redistribution and use in source and binary forms, with or without | | 15 | * Redistribution and use in source and binary forms, with or without |
15 | * modification, are permitted provided that the following conditions | | 16 | * modification, are permitted provided that the following conditions |
16 | * are met: | | 17 | * are met: |
17 | * 1. Redistributions of source code must retain the above copyright | | 18 | * 1. Redistributions of source code must retain the above copyright |
18 | * notice, this list of conditions and the following disclaimer. | | 19 | * notice, this list of conditions and the following disclaimer. |
19 | * 2. Redistributions in binary form must reproduce the above copyright | | 20 | * 2. Redistributions in binary form must reproduce the above copyright |
20 | * notice, this list of conditions and the following disclaimer in the | | 21 | * notice, this list of conditions and the following disclaimer in the |
21 | * documentation and/or other materials provided with the distribution. | | 22 | * documentation and/or other materials provided with the distribution. |
22 | * | | 23 | * |
23 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 24 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
| @@ -31,33 +32,33 @@ | | | @@ -31,33 +32,33 @@ |
31 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
32 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 33 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
33 | * POSSIBILITY OF SUCH DAMAGE. | | 34 | * POSSIBILITY OF SUCH DAMAGE. |
34 | */ | | 35 | */ |
35 | | | 36 | |
36 | /* | | 37 | /* |
37 | * USB Open Host Controller driver. | | 38 | * USB Open Host Controller driver. |
38 | * | | 39 | * |
39 | * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html | | 40 | * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html |
40 | * USB spec: http://www.usb.org/developers/docs/ | | 41 | * USB spec: http://www.usb.org/developers/docs/ |
41 | */ | | 42 | */ |
42 | | | 43 | |
43 | #include <sys/cdefs.h> | | 44 | #include <sys/cdefs.h> |
44 | __KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.218.6.1 2011/12/04 13:23:16 jmcneill Exp $"); | | 45 | __KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.218.6.2 2011/12/04 21:02:27 jmcneill Exp $"); |
45 | | | 46 | |
46 | #include "opt_usb.h" | | 47 | #include "opt_usb.h" |
47 | | | 48 | |
48 | #include <sys/param.h> | | 49 | #include <sys/param.h> |
49 | #include <sys/systm.h> | | 50 | #include <sys/systm.h> |
50 | #include <sys/malloc.h> | | 51 | #include <sys/kmem.h> |
51 | #include <sys/kernel.h> | | 52 | #include <sys/kernel.h> |
52 | #include <sys/device.h> | | 53 | #include <sys/device.h> |
53 | #include <sys/select.h> | | 54 | #include <sys/select.h> |
54 | #include <sys/proc.h> | | 55 | #include <sys/proc.h> |
55 | #include <sys/queue.h> | | 56 | #include <sys/queue.h> |
56 | | | 57 | |
57 | #include <sys/bus.h> | | 58 | #include <sys/bus.h> |
58 | #include <machine/endian.h> | | 59 | #include <machine/endian.h> |
59 | | | 60 | |
60 | #include <dev/usb/usb.h> | | 61 | #include <dev/usb/usb.h> |
61 | #include <dev/usb/usbdi.h> | | 62 | #include <dev/usb/usbdi.h> |
62 | #include <dev/usb/usbdivar.h> | | 63 | #include <dev/usb/usbdivar.h> |
63 | #include <dev/usb/usb_mem.h> | | 64 | #include <dev/usb/usb_mem.h> |
| @@ -103,47 +104,50 @@ Static void ohci_free_sitd(ohci_softc_t | | | @@ -103,47 +104,50 @@ Static void ohci_free_sitd(ohci_softc_t |
103 | #if 0 | | 104 | #if 0 |
104 | Static void ohci_free_std_chain(ohci_softc_t *, ohci_soft_td_t *, | | 105 | Static void ohci_free_std_chain(ohci_softc_t *, ohci_soft_td_t *, |
105 | ohci_soft_td_t *); | | 106 | ohci_soft_td_t *); |
106 | #endif | | 107 | #endif |
107 | Static usbd_status ohci_alloc_std_chain(struct ohci_pipe *, | | 108 | Static usbd_status ohci_alloc_std_chain(struct ohci_pipe *, |
108 | ohci_softc_t *, int, int, usbd_xfer_handle, | | 109 | ohci_softc_t *, int, int, usbd_xfer_handle, |
109 | ohci_soft_td_t *, ohci_soft_td_t **); | | 110 | ohci_soft_td_t *, ohci_soft_td_t **); |
110 | | | 111 | |
111 | Static usbd_status ohci_open(usbd_pipe_handle); | | 112 | Static usbd_status ohci_open(usbd_pipe_handle); |
112 | Static void ohci_poll(struct usbd_bus *); | | 113 | Static void ohci_poll(struct usbd_bus *); |
113 | Static void ohci_softintr(void *); | | 114 | Static void ohci_softintr(void *); |
114 | Static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle); | | 115 | Static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle); |
115 | Static void ohci_rhsc(ohci_softc_t *, usbd_xfer_handle); | | 116 | Static void ohci_rhsc(ohci_softc_t *, usbd_xfer_handle); |
| | | 117 | Static void ohci_rhsc_softint(void *arg); |
116 | | | 118 | |
117 | Static usbd_status ohci_device_request(usbd_xfer_handle xfer); | | 119 | Static usbd_status ohci_device_request(usbd_xfer_handle xfer); |
118 | Static void ohci_add_ed(ohci_softc_t *, ohci_soft_ed_t *, | | 120 | Static void ohci_add_ed(ohci_softc_t *, ohci_soft_ed_t *, |
119 | ohci_soft_ed_t *); | | 121 | ohci_soft_ed_t *); |
120 | | | 122 | |
121 | Static void ohci_rem_ed(ohci_soft_ed_t *, ohci_soft_ed_t *); | | 123 | Static void ohci_rem_ed(ohci_soft_ed_t *, ohci_soft_ed_t *); |
122 | Static void ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *); | | 124 | Static void ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *); |
123 | Static void ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *); | | 125 | Static void ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *); |
124 | Static ohci_soft_td_t *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t); | | 126 | Static ohci_soft_td_t *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t); |
125 | Static void ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *); | | 127 | Static void ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *); |
126 | Static void ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *); | | 128 | Static void ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *); |
127 | Static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t); | | 129 | Static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t); |
128 | | | 130 | |
129 | Static usbd_status ohci_setup_isoc(usbd_pipe_handle pipe); | | 131 | Static usbd_status ohci_setup_isoc(usbd_pipe_handle pipe); |
130 | Static void ohci_device_isoc_enter(usbd_xfer_handle); | | 132 | Static void ohci_device_isoc_enter(usbd_xfer_handle); |
131 | | | 133 | |
132 | Static usbd_status ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); | | 134 | Static usbd_status ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); |
133 | Static void ohci_freem(struct usbd_bus *, usb_dma_t *); | | 135 | Static void ohci_freem(struct usbd_bus *, usb_dma_t *); |
134 | | | 136 | |
135 | Static usbd_xfer_handle ohci_allocx(struct usbd_bus *); | | 137 | Static usbd_xfer_handle ohci_allocx(struct usbd_bus *); |
136 | Static void ohci_freex(struct usbd_bus *, usbd_xfer_handle); | | 138 | Static void ohci_freex(struct usbd_bus *, usbd_xfer_handle); |
| | | 139 | Static void ohci_get_locks(struct usbd_bus *, kmutex_t **, |
| | | 140 | kmutex_t **); |
137 | | | 141 | |
138 | Static usbd_status ohci_root_ctrl_transfer(usbd_xfer_handle); | | 142 | Static usbd_status ohci_root_ctrl_transfer(usbd_xfer_handle); |
139 | Static usbd_status ohci_root_ctrl_start(usbd_xfer_handle); | | 143 | Static usbd_status ohci_root_ctrl_start(usbd_xfer_handle); |
140 | Static void ohci_root_ctrl_abort(usbd_xfer_handle); | | 144 | Static void ohci_root_ctrl_abort(usbd_xfer_handle); |
141 | Static void ohci_root_ctrl_close(usbd_pipe_handle); | | 145 | Static void ohci_root_ctrl_close(usbd_pipe_handle); |
142 | Static void ohci_root_ctrl_done(usbd_xfer_handle); | | 146 | Static void ohci_root_ctrl_done(usbd_xfer_handle); |
143 | | | 147 | |
144 | Static usbd_status ohci_root_intr_transfer(usbd_xfer_handle); | | 148 | Static usbd_status ohci_root_intr_transfer(usbd_xfer_handle); |
145 | Static usbd_status ohci_root_intr_start(usbd_xfer_handle); | | 149 | Static usbd_status ohci_root_intr_start(usbd_xfer_handle); |
146 | Static void ohci_root_intr_abort(usbd_xfer_handle); | | 150 | Static void ohci_root_intr_abort(usbd_xfer_handle); |
147 | Static void ohci_root_intr_close(usbd_pipe_handle); | | 151 | Static void ohci_root_intr_close(usbd_pipe_handle); |
148 | Static void ohci_root_intr_done(usbd_xfer_handle); | | 152 | Static void ohci_root_intr_done(usbd_xfer_handle); |
149 | | | 153 | |
| @@ -264,27 +268,27 @@ struct ohci_pipe { | | | @@ -264,27 +268,27 @@ struct ohci_pipe { |
264 | } u; | | 268 | } u; |
265 | }; | | 269 | }; |
266 | | | 270 | |
267 | #define OHCI_INTR_ENDPT 1 | | 271 | #define OHCI_INTR_ENDPT 1 |
268 | | | 272 | |
269 | Static const struct usbd_bus_methods ohci_bus_methods = { | | 273 | Static const struct usbd_bus_methods ohci_bus_methods = { |
270 | ohci_open, | | 274 | ohci_open, |
271 | ohci_softintr, | | 275 | ohci_softintr, |
272 | ohci_poll, | | 276 | ohci_poll, |
273 | ohci_allocm, | | 277 | ohci_allocm, |
274 | ohci_freem, | | 278 | ohci_freem, |
275 | ohci_allocx, | | 279 | ohci_allocx, |
276 | ohci_freex, | | 280 | ohci_freex, |
277 | NULL, /* ohci_get_locks */ | | 281 | ohci_get_locks, |
278 | }; | | 282 | }; |
279 | | | 283 | |
280 | Static const struct usbd_pipe_methods ohci_root_ctrl_methods = { | | 284 | Static const struct usbd_pipe_methods ohci_root_ctrl_methods = { |
281 | ohci_root_ctrl_transfer, | | 285 | ohci_root_ctrl_transfer, |
282 | ohci_root_ctrl_start, | | 286 | ohci_root_ctrl_start, |
283 | ohci_root_ctrl_abort, | | 287 | ohci_root_ctrl_abort, |
284 | ohci_root_ctrl_close, | | 288 | ohci_root_ctrl_close, |
285 | ohci_noop, | | 289 | ohci_noop, |
286 | ohci_root_ctrl_done, | | 290 | ohci_root_ctrl_done, |
287 | }; | | 291 | }; |
288 | | | 292 | |
289 | Static const struct usbd_pipe_methods ohci_root_intr_methods = { | | 293 | Static const struct usbd_pipe_methods ohci_root_intr_methods = { |
290 | ohci_root_intr_transfer, | | 294 | ohci_root_intr_transfer, |
| @@ -361,31 +365,38 @@ ohci_detach(struct ohci_softc *sc, int f | | | @@ -361,31 +365,38 @@ ohci_detach(struct ohci_softc *sc, int f |
361 | usbd_xfer_handle xfer; | | 365 | usbd_xfer_handle xfer; |
362 | | | 366 | |
363 | if (sc->sc_child != NULL) | | 367 | if (sc->sc_child != NULL) |
364 | rv = config_detach(sc->sc_child, flags); | | 368 | rv = config_detach(sc->sc_child, flags); |
365 | | | 369 | |
366 | if (rv != 0) | | 370 | if (rv != 0) |
367 | return (rv); | | 371 | return (rv); |
368 | | | 372 | |
369 | callout_stop(&sc->sc_tmo_rhsc); | | 373 | callout_stop(&sc->sc_tmo_rhsc); |
370 | | | 374 | |
371 | usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */ | | 375 | usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */ |
372 | callout_destroy(&sc->sc_tmo_rhsc); | | 376 | callout_destroy(&sc->sc_tmo_rhsc); |
373 | | | 377 | |
| | | 378 | softint_disestablish(sc->sc_rhsc_si); |
| | | 379 | |
| | | 380 | cv_destroy(&sc->sc_softwake_cv); |
| | | 381 | |
| | | 382 | mutex_destroy(&sc->sc_lock); |
| | | 383 | mutex_destroy(&sc->sc_intr_lock); |
| | | 384 | |
374 | if (sc->sc_hcca != NULL) | | 385 | if (sc->sc_hcca != NULL) |
375 | usb_freemem(&sc->sc_bus, &sc->sc_hccadma); | | 386 | usb_freemem(&sc->sc_bus, &sc->sc_hccadma); |
376 | while((xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers)) != NULL) { | | 387 | while((xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers)) != NULL) { |
377 | SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next); | | 388 | SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next); |
378 | free(xfer, M_USB); | | 389 | kmem_free(xfer, sizeof(struct ohci_xfer)); |
379 | } | | 390 | } |
380 | | | 391 | |
381 | return (rv); | | 392 | return (rv); |
382 | } | | 393 | } |
383 | | | 394 | |
384 | ohci_soft_ed_t * | | 395 | ohci_soft_ed_t * |
385 | ohci_alloc_sed(ohci_softc_t *sc) | | 396 | ohci_alloc_sed(ohci_softc_t *sc) |
386 | { | | 397 | { |
387 | ohci_soft_ed_t *sed; | | 398 | ohci_soft_ed_t *sed; |
388 | usbd_status err; | | 399 | usbd_status err; |
389 | int i, offs; | | 400 | int i, offs; |
390 | usb_dma_t dma; | | 401 | usb_dma_t dma; |
391 | | | 402 | |
| @@ -416,85 +427,79 @@ void | | | @@ -416,85 +427,79 @@ void |
416 | ohci_free_sed(ohci_softc_t *sc, ohci_soft_ed_t *sed) | | 427 | ohci_free_sed(ohci_softc_t *sc, ohci_soft_ed_t *sed) |
417 | { | | 428 | { |
418 | sed->next = sc->sc_freeeds; | | 429 | sed->next = sc->sc_freeeds; |
419 | sc->sc_freeeds = sed; | | 430 | sc->sc_freeeds = sed; |
420 | } | | 431 | } |
421 | | | 432 | |
422 | ohci_soft_td_t * | | 433 | ohci_soft_td_t * |
423 | ohci_alloc_std(ohci_softc_t *sc) | | 434 | ohci_alloc_std(ohci_softc_t *sc) |
424 | { | | 435 | { |
425 | ohci_soft_td_t *std; | | 436 | ohci_soft_td_t *std; |
426 | usbd_status err; | | 437 | usbd_status err; |
427 | int i, offs; | | 438 | int i, offs; |
428 | usb_dma_t dma; | | 439 | usb_dma_t dma; |
429 | int s; | | | |
430 | | | 440 | |
431 | if (sc->sc_freetds == NULL) { | | 441 | if (sc->sc_freetds == NULL) { |
432 | DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n")); | | 442 | DPRINTFN(2, ("ohci_alloc_std: allocating chunk\n")); |
433 | err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK, | | 443 | err = usb_allocmem(&sc->sc_bus, OHCI_STD_SIZE * OHCI_STD_CHUNK, |
434 | OHCI_TD_ALIGN, &dma); | | 444 | OHCI_TD_ALIGN, &dma); |
435 | if (err) | | 445 | if (err) |
436 | return (NULL); | | 446 | return (NULL); |
437 | s = splusb(); | | | |
438 | for(i = 0; i < OHCI_STD_CHUNK; i++) { | | 447 | for(i = 0; i < OHCI_STD_CHUNK; i++) { |
439 | offs = i * OHCI_STD_SIZE; | | 448 | offs = i * OHCI_STD_SIZE; |
440 | std = KERNADDR(&dma, offs); | | 449 | std = KERNADDR(&dma, offs); |
441 | std->physaddr = DMAADDR(&dma, offs); | | 450 | std->physaddr = DMAADDR(&dma, offs); |
442 | std->dma = dma; | | 451 | std->dma = dma; |
443 | std->offs = offs; | | 452 | std->offs = offs; |
444 | std->nexttd = sc->sc_freetds; | | 453 | std->nexttd = sc->sc_freetds; |
445 | sc->sc_freetds = std; | | 454 | sc->sc_freetds = std; |
446 | } | | 455 | } |
447 | splx(s); | | | |
448 | } | | 456 | } |
449 | | | 457 | |
450 | s = splusb(); | | | |
451 | std = sc->sc_freetds; | | 458 | std = sc->sc_freetds; |
452 | sc->sc_freetds = std->nexttd; | | 459 | sc->sc_freetds = std->nexttd; |
453 | memset(&std->td, 0, sizeof(ohci_td_t)); | | 460 | memset(&std->td, 0, sizeof(ohci_td_t)); |
454 | std->nexttd = NULL; | | 461 | std->nexttd = NULL; |
455 | std->xfer = NULL; | | 462 | std->xfer = NULL; |
456 | ohci_hash_add_td(sc, std); | | 463 | ohci_hash_add_td(sc, std); |
457 | splx(s); | | | |
458 | | | 464 | |
459 | return (std); | | 465 | return (std); |
460 | } | | 466 | } |
461 | | | 467 | |
462 | void | | 468 | void |
463 | ohci_free_std(ohci_softc_t *sc, ohci_soft_td_t *std) | | 469 | ohci_free_std(ohci_softc_t *sc, ohci_soft_td_t *std) |
464 | { | | 470 | { |
465 | int s; | | | |
466 | | | 471 | |
467 | s = splusb(); | | | |
468 | ohci_hash_rem_td(sc, std); | | 472 | ohci_hash_rem_td(sc, std); |
469 | std->nexttd = sc->sc_freetds; | | 473 | std->nexttd = sc->sc_freetds; |
470 | sc->sc_freetds = std; | | 474 | sc->sc_freetds = std; |
471 | splx(s); | | | |
472 | } | | 475 | } |
473 | | | 476 | |
474 | usbd_status | | 477 | usbd_status |
475 | ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc, | | 478 | ohci_alloc_std_chain(struct ohci_pipe *opipe, ohci_softc_t *sc, |
476 | int alen, int rd, usbd_xfer_handle xfer, | | 479 | int alen, int rd, usbd_xfer_handle xfer, |
477 | ohci_soft_td_t *sp, ohci_soft_td_t **ep) | | 480 | ohci_soft_td_t *sp, ohci_soft_td_t **ep) |
478 | { | | 481 | { |
479 | ohci_soft_td_t *next, *cur; | | 482 | ohci_soft_td_t *next, *cur; |
480 | ohci_physaddr_t dataphys, dataphysend; | | 483 | ohci_physaddr_t dataphys, dataphysend; |
481 | u_int32_t tdflags; | | 484 | u_int32_t tdflags; |
482 | int len, curlen; | | 485 | int len, curlen; |
483 | usb_dma_t *dma = &xfer->dmabuf; | | 486 | usb_dma_t *dma = &xfer->dmabuf; |
484 | u_int16_t flags = xfer->flags; | | 487 | u_int16_t flags = xfer->flags; |
485 | | | 488 | |
486 | DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen)); | | 489 | DPRINTFN(alen < 4096,("ohci_alloc_std_chain: start len=%d\n", alen)); |
487 | | | 490 | |
| | | 491 | KASSERT(mutex_owned(&sc->sc_lock)); |
| | | 492 | |
488 | len = alen; | | 493 | len = alen; |
489 | cur = sp; | | 494 | cur = sp; |
490 | dataphys = DMAADDR(dma, 0); | | 495 | dataphys = DMAADDR(dma, 0); |
491 | dataphysend = OHCI_PAGE(dataphys + len - 1); | | 496 | dataphysend = OHCI_PAGE(dataphys + len - 1); |
492 | usb_syncmem(dma, 0, len, | | 497 | usb_syncmem(dma, 0, len, |
493 | rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); | | 498 | rd ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); |
494 | tdflags = HTOO32( | | 499 | tdflags = HTOO32( |
495 | (rd ? OHCI_TD_IN : OHCI_TD_OUT) | | | 500 | (rd ? OHCI_TD_IN : OHCI_TD_OUT) | |
496 | (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) | | | 501 | (flags & USBD_SHORT_XFER_OK ? OHCI_TD_R : 0) | |
497 | OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR); | | 502 | OHCI_TD_NOCC | OHCI_TD_TOGGLE_CARRY | OHCI_TD_NOINTR); |
498 | | | 503 | |
499 | for (;;) { | | 504 | for (;;) { |
500 | next = ohci_alloc_std(sc); | | 505 | next = ohci_alloc_std(sc); |
| @@ -580,100 +585,100 @@ ohci_free_std_chain(ohci_softc_t *sc, oh | | | @@ -580,100 +585,100 @@ ohci_free_std_chain(ohci_softc_t *sc, oh |
580 | | | 585 | |
581 | for (; std != stdend; std = p) { | | 586 | for (; std != stdend; std = p) { |
582 | p = std->nexttd; | | 587 | p = std->nexttd; |
583 | ohci_free_std(sc, std); | | 588 | ohci_free_std(sc, std); |
584 | } | | 589 | } |
585 | } | | 590 | } |
586 | #endif | | 591 | #endif |
587 | | | 592 | |
588 | ohci_soft_itd_t * | | 593 | ohci_soft_itd_t * |
589 | ohci_alloc_sitd(ohci_softc_t *sc) | | 594 | ohci_alloc_sitd(ohci_softc_t *sc) |
590 | { | | 595 | { |
591 | ohci_soft_itd_t *sitd; | | 596 | ohci_soft_itd_t *sitd; |
592 | usbd_status err; | | 597 | usbd_status err; |
593 | int i, s, offs; | | 598 | int i, offs; |
594 | usb_dma_t dma; | | 599 | usb_dma_t dma; |
595 | | | 600 | |
596 | if (sc->sc_freeitds == NULL) { | | 601 | if (sc->sc_freeitds == NULL) { |
597 | DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n")); | | 602 | DPRINTFN(2, ("ohci_alloc_sitd: allocating chunk\n")); |
598 | err = usb_allocmem(&sc->sc_bus, OHCI_SITD_SIZE * OHCI_SITD_CHUNK, | | 603 | err = usb_allocmem(&sc->sc_bus, OHCI_SITD_SIZE * OHCI_SITD_CHUNK, |
599 | OHCI_ITD_ALIGN, &dma); | | 604 | OHCI_ITD_ALIGN, &dma); |
600 | if (err) | | 605 | if (err) |
601 | return (NULL); | | 606 | return (NULL); |
602 | s = splusb(); | | | |
603 | for(i = 0; i < OHCI_SITD_CHUNK; i++) { | | 607 | for(i = 0; i < OHCI_SITD_CHUNK; i++) { |
604 | offs = i * OHCI_SITD_SIZE; | | 608 | offs = i * OHCI_SITD_SIZE; |
605 | sitd = KERNADDR(&dma, offs); | | 609 | sitd = KERNADDR(&dma, offs); |
606 | sitd->physaddr = DMAADDR(&dma, offs); | | 610 | sitd->physaddr = DMAADDR(&dma, offs); |
607 | sitd->dma = dma; | | 611 | sitd->dma = dma; |
608 | sitd->offs = offs; | | 612 | sitd->offs = offs; |
609 | sitd->nextitd = sc->sc_freeitds; | | 613 | sitd->nextitd = sc->sc_freeitds; |
610 | sc->sc_freeitds = sitd; | | 614 | sc->sc_freeitds = sitd; |
611 | } | | 615 | } |
612 | splx(s); | | | |
613 | } | | 616 | } |
614 | | | 617 | |
615 | s = splusb(); | | | |
616 | sitd = sc->sc_freeitds; | | 618 | sitd = sc->sc_freeitds; |
617 | sc->sc_freeitds = sitd->nextitd; | | 619 | sc->sc_freeitds = sitd->nextitd; |
618 | memset(&sitd->itd, 0, sizeof(ohci_itd_t)); | | 620 | memset(&sitd->itd, 0, sizeof(ohci_itd_t)); |
619 | sitd->nextitd = NULL; | | 621 | sitd->nextitd = NULL; |
620 | sitd->xfer = NULL; | | 622 | sitd->xfer = NULL; |
621 | ohci_hash_add_itd(sc, sitd); | | 623 | ohci_hash_add_itd(sc, sitd); |
622 | splx(s); | | | |
623 | | | 624 | |
624 | #ifdef DIAGNOSTIC | | 625 | #ifdef DIAGNOSTIC |
625 | sitd->isdone = 0; | | 626 | sitd->isdone = 0; |
626 | #endif | | 627 | #endif |
627 | | | 628 | |
628 | return (sitd); | | 629 | return (sitd); |
629 | } | | 630 | } |
630 | | | 631 | |
631 | void | | 632 | void |
632 | ohci_free_sitd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) | | 633 | ohci_free_sitd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) |
633 | { | | 634 | { |
634 | int s; | | | |
635 | | | 635 | |
636 | DPRINTFN(10,("ohci_free_sitd: sitd=%p\n", sitd)); | | 636 | DPRINTFN(10,("ohci_free_sitd: sitd=%p\n", sitd)); |
637 | | | 637 | |
638 | #ifdef DIAGNOSTIC | | 638 | #ifdef DIAGNOSTIC |
639 | if (!sitd->isdone) { | | 639 | if (!sitd->isdone) { |
640 | panic("ohci_free_sitd: sitd=%p not done", sitd); | | 640 | panic("ohci_free_sitd: sitd=%p not done", sitd); |
641 | return; | | 641 | return; |
642 | } | | 642 | } |
643 | /* Warn double free */ | | 643 | /* Warn double free */ |
644 | sitd->isdone = 0; | | 644 | sitd->isdone = 0; |
645 | #endif | | 645 | #endif |
646 | | | 646 | |
647 | s = splusb(); | | | |
648 | ohci_hash_rem_itd(sc, sitd); | | 647 | ohci_hash_rem_itd(sc, sitd); |
649 | sitd->nextitd = sc->sc_freeitds; | | 648 | sitd->nextitd = sc->sc_freeitds; |
650 | sc->sc_freeitds = sitd; | | 649 | sc->sc_freeitds = sitd; |
651 | splx(s); | | | |
652 | } | | 650 | } |
653 | | | 651 | |
654 | usbd_status | | 652 | usbd_status |
655 | ohci_init(ohci_softc_t *sc) | | 653 | ohci_init(ohci_softc_t *sc) |
656 | { | | 654 | { |
657 | ohci_soft_ed_t *sed, *psed; | | 655 | ohci_soft_ed_t *sed, *psed; |
658 | usbd_status err; | | 656 | usbd_status err; |
659 | int i; | | 657 | int i; |
660 | u_int32_t s, ctl, rwc, ival, hcr, fm, per, rev, desca, descb; | | 658 | u_int32_t s, ctl, rwc, ival, hcr, fm, per, rev, desca, descb; |
661 | | | 659 | |
662 | DPRINTF(("ohci_init: start\n")); | | 660 | DPRINTF(("ohci_init: start\n")); |
663 | aprint_normal_dev(sc->sc_dev, ""); | | 661 | aprint_normal_dev(sc->sc_dev, ""); |
664 | | | 662 | |
665 | sc->sc_hcca = NULL; | | 663 | sc->sc_hcca = NULL; |
666 | callout_init(&sc->sc_tmo_rhsc, 0); | | 664 | callout_init(&sc->sc_tmo_rhsc, CALLOUT_MPSAFE); |
| | | 665 | |
| | | 666 | mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_SOFTUSB); |
| | | 667 | mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_USB); |
| | | 668 | cv_init(&sc->sc_softwake_cv, "ohciab"); |
| | | 669 | |
| | | 670 | sc->sc_rhsc_si = softint_establish(SOFTINT_NET | SOFTINT_MPSAFE, |
| | | 671 | ohci_rhsc_softint, sc); |
667 | | | 672 | |
668 | for (i = 0; i < OHCI_HASH_SIZE; i++) | | 673 | for (i = 0; i < OHCI_HASH_SIZE; i++) |
669 | LIST_INIT(&sc->sc_hash_tds[i]); | | 674 | LIST_INIT(&sc->sc_hash_tds[i]); |
670 | for (i = 0; i < OHCI_HASH_SIZE; i++) | | 675 | for (i = 0; i < OHCI_HASH_SIZE; i++) |
671 | LIST_INIT(&sc->sc_hash_itds[i]); | | 676 | LIST_INIT(&sc->sc_hash_itds[i]); |
672 | | | 677 | |
673 | SIMPLEQ_INIT(&sc->sc_free_xfers); | | 678 | SIMPLEQ_INIT(&sc->sc_free_xfers); |
674 | | | 679 | |
675 | rev = OREAD4(sc, OHCI_REVISION); | | 680 | rev = OREAD4(sc, OHCI_REVISION); |
676 | aprint_normal("OHCI version %d.%d%s\n", | | 681 | aprint_normal("OHCI version %d.%d%s\n", |
677 | OHCI_REV_HI(rev), OHCI_REV_LO(rev), | | 682 | OHCI_REV_HI(rev), OHCI_REV_LO(rev), |
678 | OHCI_REV_LEGACY(rev) ? ", legacy support" : ""); | | 683 | OHCI_REV_LEGACY(rev) ? ", legacy support" : ""); |
679 | | | 684 | |
| @@ -949,124 +954,139 @@ ohci_allocx(struct usbd_bus *bus) | | | @@ -949,124 +954,139 @@ ohci_allocx(struct usbd_bus *bus) |
949 | struct ohci_softc *sc = bus->hci_private; | | 954 | struct ohci_softc *sc = bus->hci_private; |
950 | usbd_xfer_handle xfer; | | 955 | usbd_xfer_handle xfer; |
951 | | | 956 | |
952 | xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); | | 957 | xfer = SIMPLEQ_FIRST(&sc->sc_free_xfers); |
953 | if (xfer != NULL) { | | 958 | if (xfer != NULL) { |
954 | SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next); | | 959 | SIMPLEQ_REMOVE_HEAD(&sc->sc_free_xfers, next); |
955 | #ifdef DIAGNOSTIC | | 960 | #ifdef DIAGNOSTIC |
956 | if (xfer->busy_free != XFER_FREE) { | | 961 | if (xfer->busy_free != XFER_FREE) { |
957 | printf("ohci_allocx: xfer=%p not free, 0x%08x\n", xfer, | | 962 | printf("ohci_allocx: xfer=%p not free, 0x%08x\n", xfer, |
958 | xfer->busy_free); | | 963 | xfer->busy_free); |
959 | } | | 964 | } |
960 | #endif | | 965 | #endif |
961 | } else { | | 966 | } else { |
962 | xfer = malloc(sizeof(struct ohci_xfer), M_USB, M_NOWAIT); | | 967 | xfer = kmem_alloc(sizeof(struct ohci_xfer), KM_SLEEP); |
963 | } | | 968 | } |
964 | if (xfer != NULL) { | | 969 | if (xfer != NULL) { |
965 | memset(xfer, 0, sizeof (struct ohci_xfer)); | | 970 | memset(xfer, 0, sizeof (struct ohci_xfer)); |
966 | #ifdef DIAGNOSTIC | | 971 | #ifdef DIAGNOSTIC |
967 | xfer->busy_free = XFER_BUSY; | | 972 | xfer->busy_free = XFER_BUSY; |
968 | #endif | | 973 | #endif |
969 | } | | 974 | } |
970 | return (xfer); | | 975 | return (xfer); |
971 | } | | 976 | } |
972 | | | 977 | |
973 | void | | 978 | void |
974 | ohci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) | | 979 | ohci_freex(struct usbd_bus *bus, usbd_xfer_handle xfer) |
975 | { | | 980 | { |
976 | struct ohci_softc *sc = bus->hci_private; | | 981 | struct ohci_softc *sc = bus->hci_private; |
977 | | | 982 | |
978 | #ifdef DIAGNOSTIC | | 983 | #ifdef DIAGNOSTIC |
979 | if (xfer->busy_free != XFER_BUSY) { | | 984 | if (xfer->busy_free != XFER_BUSY) { |
980 | printf("ohci_freex: xfer=%p not busy, 0x%08x\n", xfer, | | 985 | printf("ohci_freex: xfer=%p not busy, 0x%08x\n", xfer, |
981 | xfer->busy_free); | | 986 | xfer->busy_free); |
982 | } | | 987 | } |
983 | xfer->busy_free = XFER_FREE; | | 988 | xfer->busy_free = XFER_FREE; |
984 | #endif | | 989 | #endif |
985 | SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); | | 990 | SIMPLEQ_INSERT_HEAD(&sc->sc_free_xfers, xfer, next); |
986 | } | | 991 | } |
987 | | | 992 | |
| | | 993 | Static void |
| | | 994 | ohci_get_locks(struct usbd_bus *bus, kmutex_t **intr, kmutex_t **thread) |
| | | 995 | { |
| | | 996 | struct ohci_softc *sc = bus->hci_private; |
| | | 997 | |
| | | 998 | *intr = &sc->sc_intr_lock; |
| | | 999 | *thread = &sc->sc_lock; |
| | | 1000 | } |
| | | 1001 | |
988 | /* | | 1002 | /* |
989 | * Shut down the controller when the system is going down. | | 1003 | * Shut down the controller when the system is going down. |
990 | */ | | 1004 | */ |
991 | bool | | 1005 | bool |
992 | ohci_shutdown(device_t self, int flags) | | 1006 | ohci_shutdown(device_t self, int flags) |
993 | { | | 1007 | { |
994 | ohci_softc_t *sc = device_private(self); | | 1008 | ohci_softc_t *sc = device_private(self); |
995 | | | 1009 | |
996 | DPRINTF(("ohci_shutdown: stopping the HC\n")); | | 1010 | DPRINTF(("ohci_shutdown: stopping the HC\n")); |
997 | OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); | | 1011 | OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); |
998 | return true; | | 1012 | return true; |
999 | } | | 1013 | } |
1000 | | | 1014 | |
1001 | bool | | 1015 | bool |
1002 | ohci_resume(device_t dv, const pmf_qual_t *qual) | | 1016 | ohci_resume(device_t dv, const pmf_qual_t *qual) |
1003 | { | | 1017 | { |
1004 | ohci_softc_t *sc = device_private(dv); | | 1018 | ohci_softc_t *sc = device_private(dv); |
1005 | uint32_t ctl; | | 1019 | uint32_t ctl; |
1006 | int s; | | | |
1007 | | | 1020 | |
1008 | s = splhardusb(); | | 1021 | mutex_spin_enter(&sc->sc_intr_lock); |
1009 | sc->sc_bus.use_polling++; | | 1022 | sc->sc_bus.use_polling++; |
| | | 1023 | mutex_spin_exit(&sc->sc_intr_lock); |
| | | 1024 | |
1010 | /* Some broken BIOSes do not recover these values */ | | 1025 | /* Some broken BIOSes do not recover these values */ |
1011 | OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0)); | | 1026 | OWRITE4(sc, OHCI_HCCA, DMAADDR(&sc->sc_hccadma, 0)); |
1012 | OWRITE4(sc, OHCI_CONTROL_HEAD_ED, | | 1027 | OWRITE4(sc, OHCI_CONTROL_HEAD_ED, |
1013 | sc->sc_ctrl_head->physaddr); | | 1028 | sc->sc_ctrl_head->physaddr); |
1014 | OWRITE4(sc, OHCI_BULK_HEAD_ED, | | 1029 | OWRITE4(sc, OHCI_BULK_HEAD_ED, |
1015 | sc->sc_bulk_head->physaddr); | | 1030 | sc->sc_bulk_head->physaddr); |
1016 | if (sc->sc_intre) | | 1031 | if (sc->sc_intre) |
1017 | OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_intre & | | 1032 | OWRITE4(sc, OHCI_INTERRUPT_ENABLE, sc->sc_intre & |
1018 | (OHCI_ALL_INTRS | OHCI_MIE)); | | 1033 | (OHCI_ALL_INTRS | OHCI_MIE)); |
1019 | if (sc->sc_control) | | 1034 | if (sc->sc_control) |
1020 | ctl = sc->sc_control; | | 1035 | ctl = sc->sc_control; |
1021 | else | | 1036 | else |
1022 | ctl = OREAD4(sc, OHCI_CONTROL); | | 1037 | ctl = OREAD4(sc, OHCI_CONTROL); |
1023 | ctl |= OHCI_HCFS_RESUME; | | 1038 | ctl |= OHCI_HCFS_RESUME; |
1024 | OWRITE4(sc, OHCI_CONTROL, ctl); | | 1039 | OWRITE4(sc, OHCI_CONTROL, ctl); |
1025 | usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); | | 1040 | usb_delay_ms(&sc->sc_bus, USB_RESUME_DELAY); |
1026 | ctl = (ctl & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL; | | 1041 | ctl = (ctl & ~OHCI_HCFS_MASK) | OHCI_HCFS_OPERATIONAL; |
1027 | OWRITE4(sc, OHCI_CONTROL, ctl); | | 1042 | OWRITE4(sc, OHCI_CONTROL, ctl); |
1028 | usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); | | 1043 | usb_delay_ms(&sc->sc_bus, USB_RESUME_RECOVERY); |
1029 | sc->sc_control = sc->sc_intre = 0; | | 1044 | sc->sc_control = sc->sc_intre = 0; |
| | | 1045 | |
| | | 1046 | mutex_spin_enter(&sc->sc_intr_lock); |
1030 | sc->sc_bus.use_polling--; | | 1047 | sc->sc_bus.use_polling--; |
1031 | splx(s); | | 1048 | mutex_spin_exit(&sc->sc_intr_lock); |
1032 | | | 1049 | |
1033 | return true; | | 1050 | return true; |
1034 | } | | 1051 | } |
1035 | | | 1052 | |
1036 | bool | | 1053 | bool |
1037 | ohci_suspend(device_t dv, const pmf_qual_t *qual) | | 1054 | ohci_suspend(device_t dv, const pmf_qual_t *qual) |
1038 | { | | 1055 | { |
1039 | ohci_softc_t *sc = device_private(dv); | | 1056 | ohci_softc_t *sc = device_private(dv); |
1040 | uint32_t ctl; | | 1057 | uint32_t ctl; |
1041 | int s; | | | |
1042 | | | 1058 | |
1043 | s = splhardusb(); | | 1059 | mutex_spin_enter(&sc->sc_intr_lock); |
1044 | sc->sc_bus.use_polling++; | | 1060 | sc->sc_bus.use_polling++; |
| | | 1061 | mutex_spin_exit(&sc->sc_intr_lock); |
| | | 1062 | |
1045 | ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK; | | 1063 | ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK; |
1046 | if (sc->sc_control == 0) { | | 1064 | if (sc->sc_control == 0) { |
1047 | /* | | 1065 | /* |
1048 | * Preserve register values, in case that BIOS | | 1066 | * Preserve register values, in case that BIOS |
1049 | * does not recover them. | | 1067 | * does not recover them. |
1050 | */ | | 1068 | */ |
1051 | sc->sc_control = ctl; | | 1069 | sc->sc_control = ctl; |
1052 | sc->sc_intre = OREAD4(sc, | | 1070 | sc->sc_intre = OREAD4(sc, |
1053 | OHCI_INTERRUPT_ENABLE); | | 1071 | OHCI_INTERRUPT_ENABLE); |
1054 | } | | 1072 | } |
1055 | ctl |= OHCI_HCFS_SUSPEND; | | 1073 | ctl |= OHCI_HCFS_SUSPEND; |
1056 | OWRITE4(sc, OHCI_CONTROL, ctl); | | 1074 | OWRITE4(sc, OHCI_CONTROL, ctl); |
1057 | usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); | | 1075 | usb_delay_ms(&sc->sc_bus, USB_RESUME_WAIT); |
| | | 1076 | |
| | | 1077 | mutex_spin_enter(&sc->sc_intr_lock); |
1058 | sc->sc_bus.use_polling--; | | 1078 | sc->sc_bus.use_polling--; |
1059 | splx(s); | | 1079 | mutex_spin_exit(&sc->sc_intr_lock); |
1060 | | | 1080 | |
1061 | return true; | | 1081 | return true; |
1062 | } | | 1082 | } |
1063 | | | 1083 | |
1064 | #ifdef OHCI_DEBUG | | 1084 | #ifdef OHCI_DEBUG |
1065 | void | | 1085 | void |
1066 | ohci_dumpregs(ohci_softc_t *sc) | | 1086 | ohci_dumpregs(ohci_softc_t *sc) |
1067 | { | | 1087 | { |
1068 | DPRINTF(("ohci_dumpregs: rev=0x%08x control=0x%08x command=0x%08x\n", | | 1088 | DPRINTF(("ohci_dumpregs: rev=0x%08x control=0x%08x command=0x%08x\n", |
1069 | OREAD4(sc, OHCI_REVISION), | | 1089 | OREAD4(sc, OHCI_REVISION), |
1070 | OREAD4(sc, OHCI_CONTROL), | | 1090 | OREAD4(sc, OHCI_CONTROL), |
1071 | OREAD4(sc, OHCI_COMMAND_STATUS))); | | 1091 | OREAD4(sc, OHCI_COMMAND_STATUS))); |
1072 | DPRINTF((" intrstat=0x%08x intre=0x%08x intrd=0x%08x\n", | | 1092 | DPRINTF((" intrstat=0x%08x intre=0x%08x intrd=0x%08x\n", |
| @@ -1098,60 +1118,72 @@ ohci_dumpregs(ohci_softc_t *sc) | | | @@ -1098,60 +1118,72 @@ ohci_dumpregs(ohci_softc_t *sc) |
1098 | OREAD4(sc, OHCI_RH_PORT_STATUS(2)))); | | 1118 | OREAD4(sc, OHCI_RH_PORT_STATUS(2)))); |
1099 | DPRINTF((" HCCA: frame_number=0x%04x done_head=0x%08x\n", | | 1119 | DPRINTF((" HCCA: frame_number=0x%04x done_head=0x%08x\n", |
1100 | O32TOH(sc->sc_hcca->hcca_frame_number), | | 1120 | O32TOH(sc->sc_hcca->hcca_frame_number), |
1101 | O32TOH(sc->sc_hcca->hcca_done_head))); | | 1121 | O32TOH(sc->sc_hcca->hcca_done_head))); |
1102 | } | | 1122 | } |
1103 | #endif | | 1123 | #endif |
1104 | | | 1124 | |
1105 | Static int ohci_intr1(ohci_softc_t *); | | 1125 | Static int ohci_intr1(ohci_softc_t *); |
1106 | | | 1126 | |
1107 | int | | 1127 | int |
1108 | ohci_intr(void *p) | | 1128 | ohci_intr(void *p) |
1109 | { | | 1129 | { |
1110 | ohci_softc_t *sc = p; | | 1130 | ohci_softc_t *sc = p; |
| | | 1131 | int ret = 0; |
1111 | | | 1132 | |
1112 | if (sc == NULL || sc->sc_dying || !device_has_power(sc->sc_dev)) | | 1133 | if (sc == NULL) |
1113 | return (0); | | 1134 | return (0); |
1114 | | | 1135 | |
| | | 1136 | mutex_spin_enter(&sc->sc_intr_lock); |
| | | 1137 | |
| | | 1138 | if (sc->sc_dying || !device_has_power(sc->sc_dev)) |
| | | 1139 | goto done; |
| | | 1140 | |
1115 | /* If we get an interrupt while polling, then just ignore it. */ | | 1141 | /* If we get an interrupt while polling, then just ignore it. */ |
1116 | if (sc->sc_bus.use_polling) { | | 1142 | if (sc->sc_bus.use_polling) { |
1117 | #ifdef DIAGNOSTIC | | 1143 | #ifdef DIAGNOSTIC |
1118 | DPRINTFN(16, ("ohci_intr: ignored interrupt while polling\n")); | | 1144 | DPRINTFN(16, ("ohci_intr: ignored interrupt while polling\n")); |
1119 | #endif | | 1145 | #endif |
1120 | /* for level triggered intrs, should do something to ack */ | | 1146 | /* for level triggered intrs, should do something to ack */ |
1121 | OWRITE4(sc, OHCI_INTERRUPT_STATUS, | | 1147 | OWRITE4(sc, OHCI_INTERRUPT_STATUS, |
1122 | OREAD4(sc, OHCI_INTERRUPT_STATUS)); | | 1148 | OREAD4(sc, OHCI_INTERRUPT_STATUS)); |
1123 | | | 1149 | |
1124 | return (0); | | 1150 | return (0); |
1125 | } | | 1151 | } |
1126 | | | 1152 | |
1127 | return (ohci_intr1(sc)); | | 1153 | ret = ohci_intr1(sc); |
| | | 1154 | |
| | | 1155 | done: |
| | | 1156 | mutex_spin_exit(&sc->sc_intr_lock); |
| | | 1157 | return ret; |
1128 | } | | 1158 | } |
1129 | | | 1159 | |
1130 | Static int | | 1160 | Static int |
1131 | ohci_intr1(ohci_softc_t *sc) | | 1161 | ohci_intr1(ohci_softc_t *sc) |
1132 | { | | 1162 | { |
1133 | u_int32_t intrs, eintrs; | | 1163 | u_int32_t intrs, eintrs; |
1134 | | | 1164 | |
1135 | DPRINTFN(14,("ohci_intr1: enter\n")); | | 1165 | DPRINTFN(14,("ohci_intr1: enter\n")); |
1136 | | | 1166 | |
1137 | /* In case the interrupt occurs before initialization has completed. */ | | 1167 | /* In case the interrupt occurs before initialization has completed. */ |
1138 | if (sc == NULL || sc->sc_hcca == NULL) { | | 1168 | if (sc == NULL || sc->sc_hcca == NULL) { |
1139 | #ifdef DIAGNOSTIC | | 1169 | #ifdef DIAGNOSTIC |
1140 | printf("ohci_intr: sc->sc_hcca == NULL\n"); | | 1170 | printf("ohci_intr: sc->sc_hcca == NULL\n"); |
1141 | #endif | | 1171 | #endif |
1142 | return (0); | | 1172 | return (0); |
1143 | } | | 1173 | } |
1144 | | | 1174 | |
| | | 1175 | KASSERT(mutex_owned(&sc->sc_intr_lock)); |
| | | 1176 | |
1145 | intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS); | | 1177 | intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS); |
1146 | if (!intrs) | | 1178 | if (!intrs) |
1147 | return (0); | | 1179 | return (0); |
1148 | | | 1180 | |
1149 | OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs & ~(OHCI_MIE|OHCI_WDH)); /* Acknowledge */ | | 1181 | OWRITE4(sc, OHCI_INTERRUPT_STATUS, intrs & ~(OHCI_MIE|OHCI_WDH)); /* Acknowledge */ |
1150 | eintrs = intrs & sc->sc_eintrs; | | 1182 | eintrs = intrs & sc->sc_eintrs; |
1151 | DPRINTFN(7, ("ohci_intr: sc=%p intrs=%#x(%#x) eintrs=%#x(%#x)\n", | | 1183 | DPRINTFN(7, ("ohci_intr: sc=%p intrs=%#x(%#x) eintrs=%#x(%#x)\n", |
1152 | sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS), | | 1184 | sc, (u_int)intrs, OREAD4(sc, OHCI_INTERRUPT_STATUS), |
1153 | (u_int)eintrs, sc->sc_eintrs)); | | 1185 | (u_int)eintrs, sc->sc_eintrs)); |
1154 | | | 1186 | |
1155 | if (!eintrs) { | | 1187 | if (!eintrs) { |
1156 | return (0); | | 1188 | return (0); |
1157 | } | | 1189 | } |
| @@ -1180,54 +1212,52 @@ ohci_intr1(ohci_softc_t *sc) | | | @@ -1180,54 +1212,52 @@ ohci_intr1(ohci_softc_t *sc) |
1180 | /* XXX process resume detect */ | | 1212 | /* XXX process resume detect */ |
1181 | } | | 1213 | } |
1182 | if (eintrs & OHCI_UE) { | | 1214 | if (eintrs & OHCI_UE) { |
1183 | printf("%s: unrecoverable error, controller halted\n", | | 1215 | printf("%s: unrecoverable error, controller halted\n", |
1184 | device_xname(sc->sc_dev)); | | 1216 | device_xname(sc->sc_dev)); |
1185 | OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); | | 1217 | OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET); |
1186 | /* XXX what else */ | | 1218 | /* XXX what else */ |
1187 | } | | 1219 | } |
1188 | if (eintrs & OHCI_RHSC) { | | 1220 | if (eintrs & OHCI_RHSC) { |
1189 | /* | | 1221 | /* |
1190 | * We block the interrupt below, and reenable it later from | | 1222 | * We block the interrupt below, and reenable it later from |
1191 | * a timeout. | | 1223 | * a timeout. |
1192 | */ | | 1224 | */ |
1193 | ohci_rhsc(sc, sc->sc_intrxfer); | | 1225 | softint_schedule(sc->sc_rhsc_si); |
1194 | /* Do not allow RHSC interrupts > 1 per second */ | | | |
1195 | callout_reset(&sc->sc_tmo_rhsc, hz, ohci_rhsc_enable, sc); | | | |
1196 | } | | 1226 | } |
1197 | | | 1227 | |
1198 | sc->sc_bus.intr_context--; | | 1228 | sc->sc_bus.intr_context--; |
1199 | | | 1229 | |
1200 | if (eintrs != 0) { | | 1230 | if (eintrs != 0) { |
1201 | /* Block unprocessed interrupts. */ | | 1231 | /* Block unprocessed interrupts. */ |
1202 | OWRITE4(sc, OHCI_INTERRUPT_DISABLE, eintrs); | | 1232 | OWRITE4(sc, OHCI_INTERRUPT_DISABLE, eintrs); |
1203 | sc->sc_eintrs &= ~eintrs; | | 1233 | sc->sc_eintrs &= ~eintrs; |
1204 | DPRINTFN(1, ("%s: blocking intrs 0x%x\n", | | 1234 | DPRINTFN(1, ("%s: blocking intrs 0x%x\n", |
1205 | device_xname(sc->sc_dev), eintrs)); | | 1235 | device_xname(sc->sc_dev), eintrs)); |
1206 | } | | 1236 | } |
1207 | | | 1237 | |
1208 | return (1); | | 1238 | return (1); |
1209 | } | | 1239 | } |
1210 | | | 1240 | |
1211 | void | | 1241 | void |
1212 | ohci_rhsc_enable(void *v_sc) | | 1242 | ohci_rhsc_enable(void *v_sc) |
1213 | { | | 1243 | { |
1214 | ohci_softc_t *sc = v_sc; | | 1244 | ohci_softc_t *sc = v_sc; |
1215 | int s; | | | |
1216 | | | 1245 | |
1217 | s = splhardusb(); | | 1246 | DPRINTFN(1, ("%s: %s\n", __func__, device_xname(sc->sc_dev))); |
| | | 1247 | mutex_spin_enter(&sc->sc_intr_lock); |
1218 | sc->sc_eintrs |= OHCI_RHSC; | | 1248 | sc->sc_eintrs |= OHCI_RHSC; |
1219 | OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_RHSC); | | 1249 | OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_RHSC); |
1220 | splx(s); | | 1250 | mutex_spin_exit(&sc->sc_intr_lock); |
1221 | } | | 1251 | } |
1222 | | | 1252 | |
1223 | #ifdef OHCI_DEBUG | | 1253 | #ifdef OHCI_DEBUG |
1224 | const char *ohci_cc_strs[] = { | | 1254 | const char *ohci_cc_strs[] = { |
1225 | "NO_ERROR", | | 1255 | "NO_ERROR", |
1226 | "CRC", | | 1256 | "CRC", |
1227 | "BIT_STUFFING", | | 1257 | "BIT_STUFFING", |
1228 | "DATA_TOGGLE_MISMATCH", | | 1258 | "DATA_TOGGLE_MISMATCH", |
1229 | "STALL", | | 1259 | "STALL", |
1230 | "DEVICE_NOT_RESPONDING", | | 1260 | "DEVICE_NOT_RESPONDING", |
1231 | "PID_CHECK_FAILURE", | | 1261 | "PID_CHECK_FAILURE", |
1232 | "UNEXPECTED_PID", | | 1262 | "UNEXPECTED_PID", |
1233 | "DATA_OVERRUN", | | 1263 | "DATA_OVERRUN", |
| @@ -1240,47 +1270,47 @@ const char *ohci_cc_strs[] = { | | | @@ -1240,47 +1270,47 @@ const char *ohci_cc_strs[] = { |
1240 | "NOT_ACCESSED", | | 1270 | "NOT_ACCESSED", |
1241 | }; | | 1271 | }; |
1242 | #endif | | 1272 | #endif |
1243 | | | 1273 | |
1244 | void | | 1274 | void |
1245 | ohci_softintr(void *v) | | 1275 | ohci_softintr(void *v) |
1246 | { | | 1276 | { |
1247 | struct usbd_bus *bus = v; | | 1277 | struct usbd_bus *bus = v; |
1248 | ohci_softc_t *sc = bus->hci_private; | | 1278 | ohci_softc_t *sc = bus->hci_private; |
1249 | ohci_soft_itd_t *sitd, *sidone, *sitdnext; | | 1279 | ohci_soft_itd_t *sitd, *sidone, *sitdnext; |
1250 | ohci_soft_td_t *std, *sdone, *stdnext; | | 1280 | ohci_soft_td_t *std, *sdone, *stdnext; |
1251 | usbd_xfer_handle xfer; | | 1281 | usbd_xfer_handle xfer; |
1252 | struct ohci_pipe *opipe; | | 1282 | struct ohci_pipe *opipe; |
1253 | int len, cc, s; | | 1283 | int len, cc; |
1254 | int i, j, actlen, iframes, uedir; | | 1284 | int i, j, actlen, iframes, uedir; |
1255 | ohci_physaddr_t done; | | 1285 | ohci_physaddr_t done; |
1256 | | | 1286 | |
1257 | DPRINTFN(10,("ohci_softintr: enter\n")); | | 1287 | DPRINTFN(10,("ohci_softintr: enter\n")); |
1258 | | | 1288 | |
| | | 1289 | mutex_enter(&sc->sc_lock); |
| | | 1290 | |
1259 | sc->sc_bus.intr_context++; | | 1291 | sc->sc_bus.intr_context++; |
1260 | | | 1292 | |
1261 | s = splhardusb(); | | | |
1262 | usb_syncmem(&sc->sc_hccadma, offsetof(struct ohci_hcca, hcca_done_head), | | 1293 | usb_syncmem(&sc->sc_hccadma, offsetof(struct ohci_hcca, hcca_done_head), |
1263 | sizeof(sc->sc_hcca->hcca_done_head), | | 1294 | sizeof(sc->sc_hcca->hcca_done_head), |
1264 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 1295 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
1265 | done = O32TOH(sc->sc_hcca->hcca_done_head) & ~OHCI_DONE_INTRS; | | 1296 | done = O32TOH(sc->sc_hcca->hcca_done_head) & ~OHCI_DONE_INTRS; |
1266 | sc->sc_hcca->hcca_done_head = 0; | | 1297 | sc->sc_hcca->hcca_done_head = 0; |
1267 | usb_syncmem(&sc->sc_hccadma, offsetof(struct ohci_hcca, hcca_done_head), | | 1298 | usb_syncmem(&sc->sc_hccadma, offsetof(struct ohci_hcca, hcca_done_head), |
1268 | sizeof(sc->sc_hcca->hcca_done_head), | | 1299 | sizeof(sc->sc_hcca->hcca_done_head), |
1269 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 1300 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
1270 | OWRITE4(sc, OHCI_INTERRUPT_STATUS, OHCI_WDH); | | 1301 | OWRITE4(sc, OHCI_INTERRUPT_STATUS, OHCI_WDH); |
1271 | sc->sc_eintrs |= OHCI_WDH; | | 1302 | sc->sc_eintrs |= OHCI_WDH; |
1272 | OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_WDH); | | 1303 | OWRITE4(sc, OHCI_INTERRUPT_ENABLE, OHCI_WDH); |
1273 | splx(s); | | | |
1274 | | | 1304 | |
1275 | /* Reverse the done list. */ | | 1305 | /* Reverse the done list. */ |
1276 | for (sdone = NULL, sidone = NULL; done != 0; ) { | | 1306 | for (sdone = NULL, sidone = NULL; done != 0; ) { |
1277 | std = ohci_hash_find_td(sc, done); | | 1307 | std = ohci_hash_find_td(sc, done); |
1278 | if (std != NULL) { | | 1308 | if (std != NULL) { |
1279 | usb_syncmem(&std->dma, std->offs, sizeof(std->td), | | 1309 | usb_syncmem(&std->dma, std->offs, sizeof(std->td), |
1280 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 1310 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
1281 | std->dnext = sdone; | | 1311 | std->dnext = sdone; |
1282 | done = O32TOH(std->td.td_nexttd); | | 1312 | done = O32TOH(std->td.td_nexttd); |
1283 | sdone = std; | | 1313 | sdone = std; |
1284 | DPRINTFN(10,("add TD %p\n", std)); | | 1314 | DPRINTFN(10,("add TD %p\n", std)); |
1285 | continue; | | 1315 | continue; |
1286 | } | | 1316 | } |
| @@ -1334,29 +1364,27 @@ ohci_softintr(void *v) | | | @@ -1334,29 +1364,27 @@ ohci_softintr(void *v) |
1334 | len = std->len; | | 1364 | len = std->len; |
1335 | if (std->td.td_cbp != 0) | | 1365 | if (std->td.td_cbp != 0) |
1336 | len -= O32TOH(std->td.td_be) - | | 1366 | len -= O32TOH(std->td.td_be) - |
1337 | O32TOH(std->td.td_cbp) + 1; | | 1367 | O32TOH(std->td.td_cbp) + 1; |
1338 | DPRINTFN(10, ("ohci_process_done: len=%d, flags=0x%x\n", len, | | 1368 | DPRINTFN(10, ("ohci_process_done: len=%d, flags=0x%x\n", len, |
1339 | std->flags)); | | 1369 | std->flags)); |
1340 | if (std->flags & OHCI_ADD_LEN) | | 1370 | if (std->flags & OHCI_ADD_LEN) |
1341 | xfer->actlen += len; | | 1371 | xfer->actlen += len; |
1342 | | | 1372 | |
1343 | cc = OHCI_TD_GET_CC(O32TOH(std->td.td_flags)); | | 1373 | cc = OHCI_TD_GET_CC(O32TOH(std->td.td_flags)); |
1344 | if (cc == OHCI_CC_NO_ERROR) { | | 1374 | if (cc == OHCI_CC_NO_ERROR) { |
1345 | if (std->flags & OHCI_CALL_DONE) { | | 1375 | if (std->flags & OHCI_CALL_DONE) { |
1346 | xfer->status = USBD_NORMAL_COMPLETION; | | 1376 | xfer->status = USBD_NORMAL_COMPLETION; |
1347 | s = splusb(); | | | |
1348 | usb_transfer_complete(xfer); | | 1377 | usb_transfer_complete(xfer); |
1349 | splx(s); | | | |
1350 | } | | 1378 | } |
1351 | ohci_free_std(sc, std); | | 1379 | ohci_free_std(sc, std); |
1352 | } else { | | 1380 | } else { |
1353 | /* | | 1381 | /* |
1354 | * Endpoint is halted. First unlink all the TDs | | 1382 | * Endpoint is halted. First unlink all the TDs |
1355 | * belonging to the failed transfer, and then restart | | 1383 | * belonging to the failed transfer, and then restart |
1356 | * the endpoint. | | 1384 | * the endpoint. |
1357 | */ | | 1385 | */ |
1358 | ohci_soft_td_t *p, *n; | | 1386 | ohci_soft_td_t *p, *n; |
1359 | opipe = (struct ohci_pipe *)xfer->pipe; | | 1387 | opipe = (struct ohci_pipe *)xfer->pipe; |
1360 | | | 1388 | |
1361 | DPRINTFN(15,("ohci_process_done: error cc=%d (%s)\n", | | 1389 | DPRINTFN(15,("ohci_process_done: error cc=%d (%s)\n", |
1362 | OHCI_TD_GET_CC(O32TOH(std->td.td_flags)), | | 1390 | OHCI_TD_GET_CC(O32TOH(std->td.td_flags)), |
| @@ -1366,29 +1394,27 @@ ohci_softintr(void *v) | | | @@ -1366,29 +1394,27 @@ ohci_softintr(void *v) |
1366 | for (p = std; p->xfer == xfer; p = n) { | | 1394 | for (p = std; p->xfer == xfer; p = n) { |
1367 | n = p->nexttd; | | 1395 | n = p->nexttd; |
1368 | ohci_free_std(sc, p); | | 1396 | ohci_free_std(sc, p); |
1369 | } | | 1397 | } |
1370 | | | 1398 | |
1371 | /* clear halt */ | | 1399 | /* clear halt */ |
1372 | opipe->sed->ed.ed_headp = HTOO32(p->physaddr); | | 1400 | opipe->sed->ed.ed_headp = HTOO32(p->physaddr); |
1373 | OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); | | 1401 | OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); |
1374 | | | 1402 | |
1375 | if (cc == OHCI_CC_STALL) | | 1403 | if (cc == OHCI_CC_STALL) |
1376 | xfer->status = USBD_STALLED; | | 1404 | xfer->status = USBD_STALLED; |
1377 | else | | 1405 | else |
1378 | xfer->status = USBD_IOERROR; | | 1406 | xfer->status = USBD_IOERROR; |
1379 | s = splusb(); | | | |
1380 | usb_transfer_complete(xfer); | | 1407 | usb_transfer_complete(xfer); |
1381 | splx(s); | | | |
1382 | } | | 1408 | } |
1383 | } | | 1409 | } |
1384 | | | 1410 | |
1385 | #ifdef OHCI_DEBUG | | 1411 | #ifdef OHCI_DEBUG |
1386 | if (ohcidebug > 10) { | | 1412 | if (ohcidebug > 10) { |
1387 | DPRINTF(("ohci_softintr: ITD done:\n")); | | 1413 | DPRINTF(("ohci_softintr: ITD done:\n")); |
1388 | ohci_dump_itds(sc, sidone); | | 1414 | ohci_dump_itds(sc, sidone); |
1389 | } | | 1415 | } |
1390 | #endif | | 1416 | #endif |
1391 | | | 1417 | |
1392 | for (sitd = sidone; sitd != NULL; sitd = sitdnext) { | | 1418 | for (sitd = sidone; sitd != NULL; sitd = sitdnext) { |
1393 | xfer = sitd->xfer; | | 1419 | xfer = sitd->xfer; |
1394 | sitdnext = sitd->dnext; | | 1420 | sitdnext = sitd->dnext; |
| @@ -1442,78 +1468,80 @@ ohci_softintr(void *v) | | | @@ -1442,78 +1468,80 @@ ohci_softintr(void *v) |
1442 | actlen += len; | | 1468 | actlen += len; |
1443 | } | | 1469 | } |
1444 | } | | 1470 | } |
1445 | if (sitd->flags & OHCI_CALL_DONE) | | 1471 | if (sitd->flags & OHCI_CALL_DONE) |
1446 | break; | | 1472 | break; |
1447 | ohci_free_sitd(sc, sitd); | | 1473 | ohci_free_sitd(sc, sitd); |
1448 | } | | 1474 | } |
1449 | ohci_free_sitd(sc, sitd); | | 1475 | ohci_free_sitd(sc, sitd); |
1450 | if (uedir == UE_DIR_IN && | | 1476 | if (uedir == UE_DIR_IN && |
1451 | xfer->status == USBD_NORMAL_COMPLETION) | | 1477 | xfer->status == USBD_NORMAL_COMPLETION) |
1452 | xfer->actlen = actlen; | | 1478 | xfer->actlen = actlen; |
1453 | xfer->hcpriv = NULL; | | 1479 | xfer->hcpriv = NULL; |
1454 | | | 1480 | |
1455 | s = splusb(); | | | |
1456 | usb_transfer_complete(xfer); | | 1481 | usb_transfer_complete(xfer); |
1457 | splx(s); | | | |
1458 | } | | 1482 | } |
1459 | } | | 1483 | } |
1460 | | | 1484 | |
1461 | #ifdef USB_USE_SOFTINTR | | | |
1462 | if (sc->sc_softwake) { | | 1485 | if (sc->sc_softwake) { |
1463 | sc->sc_softwake = 0; | | 1486 | sc->sc_softwake = 0; |
1464 | wakeup(&sc->sc_softwake); | | 1487 | cv_broadcast(&sc->sc_softwake_cv); |
1465 | } | | 1488 | } |
1466 | #endif /* USB_USE_SOFTINTR */ | | | |
1467 | | | 1489 | |
1468 | sc->sc_bus.intr_context--; | | 1490 | sc->sc_bus.intr_context--; |
| | | 1491 | mutex_exit(&sc->sc_lock); |
| | | 1492 | |
1469 | DPRINTFN(10,("ohci_softintr: done:\n")); | | 1493 | DPRINTFN(10,("ohci_softintr: done:\n")); |
1470 | } | | 1494 | } |
1471 | | | 1495 | |
1472 | void | | 1496 | void |
1473 | ohci_device_ctrl_done(usbd_xfer_handle xfer) | | 1497 | ohci_device_ctrl_done(usbd_xfer_handle xfer) |
1474 | { | | 1498 | { |
1475 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; | | 1499 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; |
| | | 1500 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
1476 | int len = UGETW(xfer->request.wLength); | | 1501 | int len = UGETW(xfer->request.wLength); |
1477 | int isread = (xfer->request.bmRequestType & UT_READ); | | 1502 | int isread = (xfer->request.bmRequestType & UT_READ); |
1478 | | | 1503 | |
1479 | DPRINTFN(10,("ohci_device_ctrl_done: xfer=%p\n", xfer)); | | 1504 | DPRINTFN(10,("ohci_device_ctrl_done: xfer=%p\n", xfer)); |
1480 | | | 1505 | |
| | | 1506 | KASSERT(mutex_owned(&sc->sc_lock)); |
| | | 1507 | |
1481 | #ifdef DIAGNOSTIC | | 1508 | #ifdef DIAGNOSTIC |
1482 | if (!(xfer->rqflags & URQ_REQUEST)) { | | 1509 | if (!(xfer->rqflags & URQ_REQUEST)) { |
1483 | panic("ohci_device_ctrl_done: not a request"); | | 1510 | panic("ohci_device_ctrl_done: not a request"); |
1484 | } | | 1511 | } |
1485 | #endif | | 1512 | #endif |
1486 | if (len) | | 1513 | if (len) |
1487 | usb_syncmem(&xfer->dmabuf, 0, len, | | 1514 | usb_syncmem(&xfer->dmabuf, 0, len, |
1488 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); | | 1515 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); |
1489 | usb_syncmem(&opipe->u.ctl.reqdma, 0, | | 1516 | usb_syncmem(&opipe->u.ctl.reqdma, 0, |
1490 | sizeof(usb_device_request_t), BUS_DMASYNC_POSTWRITE); | | 1517 | sizeof(usb_device_request_t), BUS_DMASYNC_POSTWRITE); |
1491 | } | | 1518 | } |
1492 | | | 1519 | |
1493 | void | | 1520 | void |
1494 | ohci_device_intr_done(usbd_xfer_handle xfer) | | 1521 | ohci_device_intr_done(usbd_xfer_handle xfer) |
1495 | { | | 1522 | { |
1496 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; | | 1523 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; |
1497 | ohci_softc_t *sc = opipe->pipe.device->bus->hci_private; | | 1524 | ohci_softc_t *sc = opipe->pipe.device->bus->hci_private; |
1498 | ohci_soft_ed_t *sed = opipe->sed; | | 1525 | ohci_soft_ed_t *sed = opipe->sed; |
1499 | ohci_soft_td_t *data, *tail; | | 1526 | ohci_soft_td_t *data, *tail; |
1500 | int isread = | | 1527 | int isread = |
1501 | (UE_GET_DIR(xfer->pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN); | | 1528 | (UE_GET_DIR(xfer->pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN); |
1502 | | | 1529 | |
1503 | | | | |
1504 | DPRINTFN(10,("ohci_device_intr_done: xfer=%p, actlen=%d\n", | | 1530 | DPRINTFN(10,("ohci_device_intr_done: xfer=%p, actlen=%d\n", |
1505 | xfer, xfer->actlen)); | | 1531 | xfer, xfer->actlen)); |
1506 | | | 1532 | |
| | | 1533 | KASSERT(mutex_owned(&sc->sc_lock)); |
| | | 1534 | |
1507 | usb_syncmem(&xfer->dmabuf, 0, xfer->length, | | 1535 | usb_syncmem(&xfer->dmabuf, 0, xfer->length, |
1508 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); | | 1536 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); |
1509 | if (xfer->pipe->repeat) { | | 1537 | if (xfer->pipe->repeat) { |
1510 | data = opipe->tail.td; | | 1538 | data = opipe->tail.td; |
1511 | tail = ohci_alloc_std(sc); /* XXX should reuse TD */ | | 1539 | tail = ohci_alloc_std(sc); /* XXX should reuse TD */ |
1512 | if (tail == NULL) { | | 1540 | if (tail == NULL) { |
1513 | xfer->status = USBD_NOMEM; | | 1541 | xfer->status = USBD_NOMEM; |
1514 | return; | | 1542 | return; |
1515 | } | | 1543 | } |
1516 | tail->xfer = NULL; | | 1544 | tail->xfer = NULL; |
1517 | | | 1545 | |
1518 | data->td.td_flags = HTOO32( | | 1546 | data->td.td_flags = HTOO32( |
1519 | OHCI_TD_IN | OHCI_TD_NOCC | | | 1547 | OHCI_TD_IN | OHCI_TD_NOCC | |
| @@ -1535,43 +1563,63 @@ ohci_device_intr_done(usbd_xfer_handle x | | | @@ -1535,43 +1563,63 @@ ohci_device_intr_done(usbd_xfer_handle x |
1535 | | | 1563 | |
1536 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | | 1564 | sed->ed.ed_tailp = HTOO32(tail->physaddr); |
1537 | usb_syncmem(&sed->dma, | | 1565 | usb_syncmem(&sed->dma, |
1538 | sed->offs + offsetof(ohci_ed_t, ed_tailp), | | 1566 | sed->offs + offsetof(ohci_ed_t, ed_tailp), |
1539 | sizeof(sed->ed.ed_tailp), | | 1567 | sizeof(sed->ed.ed_tailp), |
1540 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 1568 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
1541 | opipe->tail.td = tail; | | 1569 | opipe->tail.td = tail; |
1542 | } | | 1570 | } |
1543 | } | | 1571 | } |
1544 | | | 1572 | |
1545 | void | | 1573 | void |
1546 | ohci_device_bulk_done(usbd_xfer_handle xfer) | | 1574 | ohci_device_bulk_done(usbd_xfer_handle xfer) |
1547 | { | | 1575 | { |
| | | 1576 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
1548 | int isread = | | 1577 | int isread = |
1549 | (UE_GET_DIR(xfer->pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN); | | 1578 | (UE_GET_DIR(xfer->pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN); |
1550 | | | 1579 | |
| | | 1580 | KASSERT(mutex_owned(&sc->sc_lock)); |
| | | 1581 | |
1551 | DPRINTFN(10,("ohci_device_bulk_done: xfer=%p, actlen=%d\n", | | 1582 | DPRINTFN(10,("ohci_device_bulk_done: xfer=%p, actlen=%d\n", |
1552 | xfer, xfer->actlen)); | | 1583 | xfer, xfer->actlen)); |
1553 | usb_syncmem(&xfer->dmabuf, 0, xfer->length, | | 1584 | usb_syncmem(&xfer->dmabuf, 0, xfer->length, |
1554 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); | | 1585 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); |
1555 | } | | 1586 | } |
1556 | | | 1587 | |
| | | 1588 | Static void |
| | | 1589 | ohci_rhsc_softint(void *arg) |
| | | 1590 | { |
| | | 1591 | ohci_softc_t *sc = arg; |
| | | 1592 | |
| | | 1593 | mutex_enter(&sc->sc_lock); |
| | | 1594 | |
| | | 1595 | ohci_rhsc(sc, sc->sc_intrxfer); |
| | | 1596 | |
| | | 1597 | /* Do not allow RHSC interrupts > 1 per second */ |
| | | 1598 | callout_reset(&sc->sc_tmo_rhsc, hz, ohci_rhsc_enable, sc); |
| | | 1599 | |
| | | 1600 | mutex_exit(&sc->sc_lock); |
| | | 1601 | } |
| | | 1602 | |
1557 | void | | 1603 | void |
1558 | ohci_rhsc(ohci_softc_t *sc, usbd_xfer_handle xfer) | | 1604 | ohci_rhsc(ohci_softc_t *sc, usbd_xfer_handle xfer) |
1559 | { | | 1605 | { |
1560 | usbd_pipe_handle pipe; | | 1606 | usbd_pipe_handle pipe; |
1561 | u_char *p; | | 1607 | u_char *p; |
1562 | int i, m; | | 1608 | int i, m; |
1563 | int hstatus; | | 1609 | int hstatus; |
1564 | | | 1610 | |
| | | 1611 | KASSERT(mutex_owned(&sc->sc_lock)); |
| | | 1612 | |
1565 | hstatus = OREAD4(sc, OHCI_RH_STATUS); | | 1613 | hstatus = OREAD4(sc, OHCI_RH_STATUS); |
1566 | DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n", | | 1614 | DPRINTF(("ohci_rhsc: sc=%p xfer=%p hstatus=0x%08x\n", |
1567 | sc, xfer, hstatus)); | | 1615 | sc, xfer, hstatus)); |
1568 | | | 1616 | |
1569 | if (xfer == NULL) { | | 1617 | if (xfer == NULL) { |
1570 | /* Just ignore the change. */ | | 1618 | /* Just ignore the change. */ |
1571 | return; | | 1619 | return; |
1572 | } | | 1620 | } |
1573 | | | 1621 | |
1574 | pipe = xfer->pipe; | | 1622 | pipe = xfer->pipe; |
1575 | | | 1623 | |
1576 | p = KERNADDR(&xfer->dmabuf, 0); | | 1624 | p = KERNADDR(&xfer->dmabuf, 0); |
1577 | m = min(sc->sc_noport, xfer->length * 8 - 1); | | 1625 | m = min(sc->sc_noport, xfer->length * 8 - 1); |
| @@ -1599,84 +1647,95 @@ ohci_root_ctrl_done(usbd_xfer_handle xfe | | | @@ -1599,84 +1647,95 @@ ohci_root_ctrl_done(usbd_xfer_handle xfe |
1599 | } | | 1647 | } |
1600 | | | 1648 | |
1601 | /* | | 1649 | /* |
1602 | * Wait here until controller claims to have an interrupt. | | 1650 | * Wait here until controller claims to have an interrupt. |
1603 | * Then call ohci_intr and return. Use timeout to avoid waiting | | 1651 | * Then call ohci_intr and return. Use timeout to avoid waiting |
1604 | * too long. | | 1652 | * too long. |
1605 | */ | | 1653 | */ |
1606 | void | | 1654 | void |
1607 | ohci_waitintr(ohci_softc_t *sc, usbd_xfer_handle xfer) | | 1655 | ohci_waitintr(ohci_softc_t *sc, usbd_xfer_handle xfer) |
1608 | { | | 1656 | { |
1609 | int timo; | | 1657 | int timo; |
1610 | u_int32_t intrs; | | 1658 | u_int32_t intrs; |
1611 | | | 1659 | |
| | | 1660 | mutex_enter(&sc->sc_lock); |
| | | 1661 | |
1612 | xfer->status = USBD_IN_PROGRESS; | | 1662 | xfer->status = USBD_IN_PROGRESS; |
1613 | for (timo = xfer->timeout; timo >= 0; timo--) { | | 1663 | for (timo = xfer->timeout; timo >= 0; timo--) { |
1614 | usb_delay_ms(&sc->sc_bus, 1); | | 1664 | usb_delay_ms(&sc->sc_bus, 1); |
1615 | if (sc->sc_dying) | | 1665 | if (sc->sc_dying) |
1616 | break; | | 1666 | break; |
1617 | intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs; | | 1667 | intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs; |
1618 | DPRINTFN(15,("ohci_waitintr: 0x%04x\n", intrs)); | | 1668 | DPRINTFN(15,("ohci_waitintr: 0x%04x\n", intrs)); |
1619 | #ifdef OHCI_DEBUG | | 1669 | #ifdef OHCI_DEBUG |
1620 | if (ohcidebug > 15) | | 1670 | if (ohcidebug > 15) |
1621 | ohci_dumpregs(sc); | | 1671 | ohci_dumpregs(sc); |
1622 | #endif | | 1672 | #endif |
1623 | if (intrs) { | | 1673 | if (intrs) { |
| | | 1674 | mutex_spin_enter(&sc->sc_intr_lock); |
1624 | ohci_intr1(sc); | | 1675 | ohci_intr1(sc); |
| | | 1676 | mutex_spin_exit(&sc->sc_intr_lock); |
1625 | if (xfer->status != USBD_IN_PROGRESS) | | 1677 | if (xfer->status != USBD_IN_PROGRESS) |
1626 | return; | | 1678 | return; |
1627 | } | | 1679 | } |
1628 | } | | 1680 | } |
1629 | | | 1681 | |
1630 | /* Timeout */ | | 1682 | /* Timeout */ |
1631 | DPRINTF(("ohci_waitintr: timeout\n")); | | 1683 | DPRINTF(("ohci_waitintr: timeout\n")); |
1632 | xfer->status = USBD_TIMEOUT; | | 1684 | xfer->status = USBD_TIMEOUT; |
1633 | usb_transfer_complete(xfer); | | 1685 | usb_transfer_complete(xfer); |
| | | 1686 | |
1634 | /* XXX should free TD */ | | 1687 | /* XXX should free TD */ |
| | | 1688 | |
| | | 1689 | mutex_exit(&sc->sc_lock); |
1635 | } | | 1690 | } |
1636 | | | 1691 | |
1637 | void | | 1692 | void |
1638 | ohci_poll(struct usbd_bus *bus) | | 1693 | ohci_poll(struct usbd_bus *bus) |
1639 | { | | 1694 | { |
1640 | ohci_softc_t *sc = bus->hci_private; | | 1695 | ohci_softc_t *sc = bus->hci_private; |
1641 | #ifdef OHCI_DEBUG | | 1696 | #ifdef OHCI_DEBUG |
1642 | static int last; | | 1697 | static int last; |
1643 | int new; | | 1698 | int new; |
1644 | new = OREAD4(sc, OHCI_INTERRUPT_STATUS); | | 1699 | new = OREAD4(sc, OHCI_INTERRUPT_STATUS); |
1645 | if (new != last) { | | 1700 | if (new != last) { |
1646 | DPRINTFN(10,("ohci_poll: intrs=0x%04x\n", new)); | | 1701 | DPRINTFN(10,("ohci_poll: intrs=0x%04x\n", new)); |
1647 | last = new; | | 1702 | last = new; |
1648 | } | | 1703 | } |
1649 | #endif | | 1704 | #endif |
1650 | | | 1705 | |
1651 | sc->sc_eintrs |= OHCI_WDH; | | 1706 | sc->sc_eintrs |= OHCI_WDH; |
1652 | if (OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs) | | 1707 | if (OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs) { |
| | | 1708 | mutex_spin_enter(&sc->sc_intr_lock); |
1653 | ohci_intr1(sc); | | 1709 | ohci_intr1(sc); |
| | | 1710 | mutex_spin_exit(&sc->sc_intr_lock); |
| | | 1711 | } |
1654 | } | | 1712 | } |
1655 | | | 1713 | |
1656 | usbd_status | | 1714 | usbd_status |
1657 | ohci_device_request(usbd_xfer_handle xfer) | | 1715 | ohci_device_request(usbd_xfer_handle xfer) |
1658 | { | | 1716 | { |
1659 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; | | 1717 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; |
1660 | usb_device_request_t *req = &xfer->request; | | 1718 | usb_device_request_t *req = &xfer->request; |
1661 | usbd_device_handle dev = opipe->pipe.device; | | 1719 | usbd_device_handle dev = opipe->pipe.device; |
1662 | ohci_softc_t *sc = dev->bus->hci_private; | | 1720 | ohci_softc_t *sc = dev->bus->hci_private; |
1663 | int addr = dev->address; | | 1721 | int addr = dev->address; |
1664 | ohci_soft_td_t *setup, *stat, *next, *tail; | | 1722 | ohci_soft_td_t *setup, *stat, *next, *tail; |
1665 | ohci_soft_ed_t *sed; | | 1723 | ohci_soft_ed_t *sed; |
1666 | int isread; | | 1724 | int isread; |
1667 | int len; | | 1725 | int len; |
1668 | usbd_status err; | | 1726 | usbd_status err; |
1669 | int s; | | 1727 | |
| | | 1728 | KASSERT(mutex_owned(&sc->sc_lock)); |
1670 | | | 1729 | |
1671 | isread = req->bmRequestType & UT_READ; | | 1730 | isread = req->bmRequestType & UT_READ; |
1672 | len = UGETW(req->wLength); | | 1731 | len = UGETW(req->wLength); |
1673 | | | 1732 | |
1674 | DPRINTFN(3,("ohci_device_control type=0x%02x, request=0x%02x, " | | 1733 | DPRINTFN(3,("ohci_device_control type=0x%02x, request=0x%02x, " |
1675 | "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n", | | 1734 | "wValue=0x%04x, wIndex=0x%04x len=%d, addr=%d, endpt=%d\n", |
1676 | req->bmRequestType, req->bRequest, UGETW(req->wValue), | | 1735 | req->bmRequestType, req->bRequest, UGETW(req->wValue), |
1677 | UGETW(req->wIndex), len, addr, | | 1736 | UGETW(req->wIndex), len, addr, |
1678 | opipe->pipe.endpoint->edesc->bEndpointAddress)); | | 1737 | opipe->pipe.endpoint->edesc->bEndpointAddress)); |
1679 | | | 1738 | |
1680 | setup = opipe->tail.td; | | 1739 | setup = opipe->tail.td; |
1681 | stat = ohci_alloc_std(sc); | | 1740 | stat = ohci_alloc_std(sc); |
1682 | if (stat == NULL) { | | 1741 | if (stat == NULL) { |
| @@ -1757,39 +1816,37 @@ ohci_device_request(usbd_xfer_handle xfe | | | @@ -1757,39 +1816,37 @@ ohci_device_request(usbd_xfer_handle xfe |
1757 | stat->xfer = xfer; | | 1816 | stat->xfer = xfer; |
1758 | usb_syncmem(&stat->dma, stat->offs, sizeof(stat->td), | | 1817 | usb_syncmem(&stat->dma, stat->offs, sizeof(stat->td), |
1759 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 1818 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
1760 | | | 1819 | |
1761 | #ifdef OHCI_DEBUG | | 1820 | #ifdef OHCI_DEBUG |
1762 | if (ohcidebug > 5) { | | 1821 | if (ohcidebug > 5) { |
1763 | DPRINTF(("ohci_device_request:\n")); | | 1822 | DPRINTF(("ohci_device_request:\n")); |
1764 | ohci_dump_ed(sc, sed); | | 1823 | ohci_dump_ed(sc, sed); |
1765 | ohci_dump_tds(sc, setup); | | 1824 | ohci_dump_tds(sc, setup); |
1766 | } | | 1825 | } |
1767 | #endif | | 1826 | #endif |
1768 | | | 1827 | |
1769 | /* Insert ED in schedule */ | | 1828 | /* Insert ED in schedule */ |
1770 | s = splusb(); | | | |
1771 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | | 1829 | sed->ed.ed_tailp = HTOO32(tail->physaddr); |
1772 | usb_syncmem(&sed->dma, | | 1830 | usb_syncmem(&sed->dma, |
1773 | sed->offs + offsetof(ohci_ed_t, ed_tailp), | | 1831 | sed->offs + offsetof(ohci_ed_t, ed_tailp), |
1774 | sizeof(sed->ed.ed_tailp), | | 1832 | sizeof(sed->ed.ed_tailp), |
1775 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 1833 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
1776 | opipe->tail.td = tail; | | 1834 | opipe->tail.td = tail; |
1777 | OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); | | 1835 | OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_CLF); |
1778 | if (xfer->timeout && !sc->sc_bus.use_polling) { | | 1836 | if (xfer->timeout && !sc->sc_bus.use_polling) { |
1779 | callout_reset(&xfer->timeout_handle, mstohz(xfer->timeout), | | 1837 | callout_reset(&xfer->timeout_handle, mstohz(xfer->timeout), |
1780 | ohci_timeout, xfer); | | 1838 | ohci_timeout, xfer); |
1781 | } | | 1839 | } |
1782 | splx(s); | | | |
1783 | | | 1840 | |
1784 | #ifdef OHCI_DEBUG | | 1841 | #ifdef OHCI_DEBUG |
1785 | if (ohcidebug > 20) { | | 1842 | if (ohcidebug > 20) { |
1786 | delay(10000); | | 1843 | delay(10000); |
1787 | DPRINTF(("ohci_device_request: status=%x\n", | | 1844 | DPRINTF(("ohci_device_request: status=%x\n", |
1788 | OREAD4(sc, OHCI_COMMAND_STATUS))); | | 1845 | OREAD4(sc, OHCI_COMMAND_STATUS))); |
1789 | ohci_dumpregs(sc); | | 1846 | ohci_dumpregs(sc); |
1790 | printf("ctrl head:\n"); | | 1847 | printf("ctrl head:\n"); |
1791 | ohci_dump_ed(sc, sc->sc_ctrl_head); | | 1848 | ohci_dump_ed(sc, sc->sc_ctrl_head); |
1792 | printf("sed:\n"); | | 1849 | printf("sed:\n"); |
1793 | ohci_dump_ed(sc, sed); | | 1850 | ohci_dump_ed(sc, sed); |
1794 | ohci_dump_tds(sc, setup); | | 1851 | ohci_dump_tds(sc, setup); |
1795 | } | | 1852 | } |
| @@ -1953,33 +2010,34 @@ ohci_timeout(void *addr) | | | @@ -1953,33 +2010,34 @@ ohci_timeout(void *addr) |
1953 | return; | | 2010 | return; |
1954 | } | | 2011 | } |
1955 | | | 2012 | |
1956 | /* Execute the abort in a process context. */ | | 2013 | /* Execute the abort in a process context. */ |
1957 | usb_init_task(&oxfer->abort_task, ohci_timeout_task, addr); | | 2014 | usb_init_task(&oxfer->abort_task, ohci_timeout_task, addr); |
1958 | usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task, | | 2015 | usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task, |
1959 | USB_TASKQ_HC); | | 2016 | USB_TASKQ_HC); |
1960 | } | | 2017 | } |
1961 | | | 2018 | |
1962 | void | | 2019 | void |
1963 | ohci_timeout_task(void *addr) | | 2020 | ohci_timeout_task(void *addr) |
1964 | { | | 2021 | { |
1965 | usbd_xfer_handle xfer = addr; | | 2022 | usbd_xfer_handle xfer = addr; |
1966 | int s; | | 2023 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
1967 | | | 2024 | |
1968 | DPRINTF(("ohci_timeout_task: xfer=%p\n", xfer)); | | 2025 | DPRINTF(("ohci_timeout_task: xfer=%p\n", xfer)); |
1969 | | | 2026 | |
1970 | s = splusb(); | | 2027 | KASSERT(mutex_owned(&sc->sc_lock)); |
| | | 2028 | //mutex_enter(&sc->sc_lock); |
1971 | ohci_abort_xfer(xfer, USBD_TIMEOUT); | | 2029 | ohci_abort_xfer(xfer, USBD_TIMEOUT); |
1972 | splx(s); | | 2030 | //mutex_exit(&sc->sc_lock); |
1973 | } | | 2031 | } |
1974 | | | 2032 | |
1975 | #ifdef OHCI_DEBUG | | 2033 | #ifdef OHCI_DEBUG |
1976 | void | | 2034 | void |
1977 | ohci_dump_tds(ohci_softc_t *sc, ohci_soft_td_t *std) | | 2035 | ohci_dump_tds(ohci_softc_t *sc, ohci_soft_td_t *std) |
1978 | { | | 2036 | { |
1979 | for (; std; std = std->nexttd) | | 2037 | for (; std; std = std->nexttd) |
1980 | ohci_dump_td(sc, std); | | 2038 | ohci_dump_td(sc, std); |
1981 | } | | 2039 | } |
1982 | | | 2040 | |
1983 | void | | 2041 | void |
1984 | ohci_dump_td(ohci_softc_t *sc, ohci_soft_td_t *std) | | 2042 | ohci_dump_td(ohci_softc_t *sc, ohci_soft_td_t *std) |
1985 | { | | 2043 | { |
| @@ -2060,49 +2118,51 @@ usbd_status | | | @@ -2060,49 +2118,51 @@ usbd_status |
2060 | ohci_open(usbd_pipe_handle pipe) | | 2118 | ohci_open(usbd_pipe_handle pipe) |
2061 | { | | 2119 | { |
2062 | usbd_device_handle dev = pipe->device; | | 2120 | usbd_device_handle dev = pipe->device; |
2063 | ohci_softc_t *sc = dev->bus->hci_private; | | 2121 | ohci_softc_t *sc = dev->bus->hci_private; |
2064 | usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; | | 2122 | usb_endpoint_descriptor_t *ed = pipe->endpoint->edesc; |
2065 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; | | 2123 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; |
2066 | u_int8_t addr = dev->address; | | 2124 | u_int8_t addr = dev->address; |
2067 | u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE; | | 2125 | u_int8_t xfertype = ed->bmAttributes & UE_XFERTYPE; |
2068 | ohci_soft_ed_t *sed; | | 2126 | ohci_soft_ed_t *sed; |
2069 | ohci_soft_td_t *std; | | 2127 | ohci_soft_td_t *std; |
2070 | ohci_soft_itd_t *sitd; | | 2128 | ohci_soft_itd_t *sitd; |
2071 | ohci_physaddr_t tdphys; | | 2129 | ohci_physaddr_t tdphys; |
2072 | u_int32_t fmt; | | 2130 | u_int32_t fmt; |
2073 | usbd_status err; | | 2131 | usbd_status err = USBD_NOMEM; |
2074 | int s; | | | |
2075 | int ival; | | 2132 | int ival; |
2076 | | | 2133 | |
2077 | DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", | | 2134 | DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n", |
2078 | pipe, addr, ed->bEndpointAddress, sc->sc_addr)); | | 2135 | pipe, addr, ed->bEndpointAddress, sc->sc_addr)); |
2079 | | | 2136 | |
2080 | if (sc->sc_dying) | | 2137 | if (sc->sc_dying) { |
2081 | return (USBD_IOERROR); | | 2138 | err = USBD_IOERROR; |
| | | 2139 | goto bad0; |
| | | 2140 | } |
2082 | | | 2141 | |
2083 | std = NULL; | | 2142 | std = NULL; |
2084 | sed = NULL; | | 2143 | sed = NULL; |
2085 | | | 2144 | |
2086 | if (addr == sc->sc_addr) { | | 2145 | if (addr == sc->sc_addr) { |
2087 | switch (ed->bEndpointAddress) { | | 2146 | switch (ed->bEndpointAddress) { |
2088 | case USB_CONTROL_ENDPOINT: | | 2147 | case USB_CONTROL_ENDPOINT: |
2089 | pipe->methods = &ohci_root_ctrl_methods; | | 2148 | pipe->methods = &ohci_root_ctrl_methods; |
2090 | break; | | 2149 | break; |
2091 | case UE_DIR_IN | OHCI_INTR_ENDPT: | | 2150 | case UE_DIR_IN | OHCI_INTR_ENDPT: |
2092 | pipe->methods = &ohci_root_intr_methods; | | 2151 | pipe->methods = &ohci_root_intr_methods; |
2093 | break; | | 2152 | break; |
2094 | default: | | 2153 | default: |
2095 | return (USBD_INVAL); | | 2154 | err = USBD_INVAL; |
| | | 2155 | goto bad0; |
2096 | } | | 2156 | } |
2097 | } else { | | 2157 | } else { |
2098 | sed = ohci_alloc_sed(sc); | | 2158 | sed = ohci_alloc_sed(sc); |
2099 | if (sed == NULL) | | 2159 | if (sed == NULL) |
2100 | goto bad0; | | 2160 | goto bad0; |
2101 | opipe->sed = sed; | | 2161 | opipe->sed = sed; |
2102 | if (xfertype == UE_ISOCHRONOUS) { | | 2162 | if (xfertype == UE_ISOCHRONOUS) { |
2103 | sitd = ohci_alloc_sitd(sc); | | 2163 | sitd = ohci_alloc_sitd(sc); |
2104 | if (sitd == NULL) | | 2164 | if (sitd == NULL) |
2105 | goto bad1; | | 2165 | goto bad1; |
2106 | opipe->tail.itd = sitd; | | 2166 | opipe->tail.itd = sitd; |
2107 | tdphys = sitd->physaddr; | | 2167 | tdphys = sitd->physaddr; |
2108 | fmt = OHCI_ED_FORMAT_ISO; | | 2168 | fmt = OHCI_ED_FORMAT_ISO; |
| @@ -2128,73 +2188,75 @@ ohci_open(usbd_pipe_handle pipe) | | | @@ -2128,73 +2188,75 @@ ohci_open(usbd_pipe_handle pipe) |
2128 | (pipe->endpoint->datatoggle ? OHCI_TOGGLECARRY : 0)); | | 2188 | (pipe->endpoint->datatoggle ? OHCI_TOGGLECARRY : 0)); |
2129 | sed->ed.ed_tailp = HTOO32(tdphys); | | 2189 | sed->ed.ed_tailp = HTOO32(tdphys); |
2130 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | | 2190 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), |
2131 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 2191 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
2132 | | | 2192 | |
2133 | switch (xfertype) { | | 2193 | switch (xfertype) { |
2134 | case UE_CONTROL: | | 2194 | case UE_CONTROL: |
2135 | pipe->methods = &ohci_device_ctrl_methods; | | 2195 | pipe->methods = &ohci_device_ctrl_methods; |
2136 | err = usb_allocmem(&sc->sc_bus, | | 2196 | err = usb_allocmem(&sc->sc_bus, |
2137 | sizeof(usb_device_request_t), | | 2197 | sizeof(usb_device_request_t), |
2138 | 0, &opipe->u.ctl.reqdma); | | 2198 | 0, &opipe->u.ctl.reqdma); |
2139 | if (err) | | 2199 | if (err) |
2140 | goto bad; | | 2200 | goto bad; |
2141 | s = splusb(); | | 2201 | mutex_enter(&sc->sc_lock); |
2142 | ohci_add_ed(sc, sed, sc->sc_ctrl_head); | | 2202 | ohci_add_ed(sc, sed, sc->sc_ctrl_head); |
2143 | splx(s); | | 2203 | mutex_exit(&sc->sc_lock); |
2144 | break; | | 2204 | break; |
2145 | case UE_INTERRUPT: | | 2205 | case UE_INTERRUPT: |
2146 | pipe->methods = &ohci_device_intr_methods; | | 2206 | pipe->methods = &ohci_device_intr_methods; |
2147 | ival = pipe->interval; | | 2207 | ival = pipe->interval; |
2148 | if (ival == USBD_DEFAULT_INTERVAL) | | 2208 | if (ival == USBD_DEFAULT_INTERVAL) |
2149 | ival = ed->bInterval; | | 2209 | ival = ed->bInterval; |
2150 | return (ohci_device_setintr(sc, opipe, ival)); | | 2210 | return (ohci_device_setintr(sc, opipe, ival)); |
2151 | case UE_ISOCHRONOUS: | | 2211 | case UE_ISOCHRONOUS: |
2152 | pipe->methods = &ohci_device_isoc_methods; | | 2212 | pipe->methods = &ohci_device_isoc_methods; |
2153 | return (ohci_setup_isoc(pipe)); | | 2213 | return (ohci_setup_isoc(pipe)); |
2154 | case UE_BULK: | | 2214 | case UE_BULK: |
2155 | pipe->methods = &ohci_device_bulk_methods; | | 2215 | pipe->methods = &ohci_device_bulk_methods; |
2156 | s = splusb(); | | 2216 | mutex_enter(&sc->sc_lock); |
2157 | ohci_add_ed(sc, sed, sc->sc_bulk_head); | | 2217 | ohci_add_ed(sc, sed, sc->sc_bulk_head); |
2158 | splx(s); | | 2218 | mutex_exit(&sc->sc_lock); |
2159 | break; | | 2219 | break; |
2160 | } | | 2220 | } |
2161 | } | | 2221 | } |
2162 | return (USBD_NORMAL_COMPLETION); | | 2222 | |
| | | 2223 | return USBD_NORMAL_COMPLETION; |
2163 | | | 2224 | |
2164 | bad: | | 2225 | bad: |
2165 | if (std != NULL) | | 2226 | if (std != NULL) |
2166 | ohci_free_std(sc, std); | | 2227 | ohci_free_std(sc, std); |
2167 | bad1: | | 2228 | bad1: |
2168 | if (sed != NULL) | | 2229 | if (sed != NULL) |
2169 | ohci_free_sed(sc, sed); | | 2230 | ohci_free_sed(sc, sed); |
2170 | bad0: | | 2231 | bad0: |
2171 | return (USBD_NOMEM); | | 2232 | mutex_exit(&sc->sc_lock); |
| | | 2233 | return err; |
2172 | | | 2234 | |
2173 | } | | 2235 | } |
2174 | | | 2236 | |
2175 | /* | | 2237 | /* |
2176 | * Close a reqular pipe. | | 2238 | * Close a reqular pipe. |
2177 | * Assumes that there are no pending transactions. | | 2239 | * Assumes that there are no pending transactions. |
2178 | */ | | 2240 | */ |
2179 | void | | 2241 | void |
2180 | ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head) | | 2242 | ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head) |
2181 | { | | 2243 | { |
2182 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; | | 2244 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; |
2183 | ohci_softc_t *sc = pipe->device->bus->hci_private; | | 2245 | ohci_softc_t *sc = pipe->device->bus->hci_private; |
2184 | ohci_soft_ed_t *sed = opipe->sed; | | 2246 | ohci_soft_ed_t *sed = opipe->sed; |
2185 | int s; | | | |
2186 | | | 2247 | |
2187 | s = splusb(); | | 2248 | KASSERT(mutex_owned(&sc->sc_lock)); |
| | | 2249 | |
2188 | #ifdef DIAGNOSTIC | | 2250 | #ifdef DIAGNOSTIC |
2189 | sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); | | 2251 | sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); |
2190 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != | | 2252 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != |
2191 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) { | | 2253 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) { |
2192 | ohci_soft_td_t *std; | | 2254 | ohci_soft_td_t *std; |
2193 | std = ohci_hash_find_td(sc, O32TOH(sed->ed.ed_headp)); | | 2255 | std = ohci_hash_find_td(sc, O32TOH(sed->ed.ed_headp)); |
2194 | printf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x " | | 2256 | printf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x " |
2195 | "tl=0x%x pipe=%p, std=%p\n", sed, | | 2257 | "tl=0x%x pipe=%p, std=%p\n", sed, |
2196 | (int)O32TOH(sed->ed.ed_headp), | | 2258 | (int)O32TOH(sed->ed.ed_headp), |
2197 | (int)O32TOH(sed->ed.ed_tailp), | | 2259 | (int)O32TOH(sed->ed.ed_tailp), |
2198 | pipe, std); | | 2260 | pipe, std); |
2199 | #ifdef USB_DEBUG | | 2261 | #ifdef USB_DEBUG |
2200 | usbd_dump_pipe(&opipe->pipe); | | 2262 | usbd_dump_pipe(&opipe->pipe); |
| @@ -2205,133 +2267,125 @@ ohci_close_pipe(usbd_pipe_handle pipe, o | | | @@ -2205,133 +2267,125 @@ ohci_close_pipe(usbd_pipe_handle pipe, o |
2205 | ohci_dump_td(sc, std); | | 2267 | ohci_dump_td(sc, std); |
2206 | #endif | | 2268 | #endif |
2207 | usb_delay_ms(&sc->sc_bus, 2); | | 2269 | usb_delay_ms(&sc->sc_bus, 2); |
2208 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != | | 2270 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != |
2209 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) | | 2271 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) |
2210 | printf("ohci_close_pipe: pipe still not empty\n"); | | 2272 | printf("ohci_close_pipe: pipe still not empty\n"); |
2211 | } | | 2273 | } |
2212 | #endif | | 2274 | #endif |
2213 | ohci_rem_ed(sed, head); | | 2275 | ohci_rem_ed(sed, head); |
2214 | /* Make sure the host controller is not touching this ED */ | | 2276 | /* Make sure the host controller is not touching this ED */ |
2215 | usb_delay_ms(&sc->sc_bus, 1); | | 2277 | usb_delay_ms(&sc->sc_bus, 1); |
2216 | pipe->endpoint->datatoggle = | | 2278 | pipe->endpoint->datatoggle = |
2217 | (O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0; | | 2279 | (O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0; |
2218 | splx(s); | | | |
2219 | ohci_free_sed(sc, opipe->sed); | | 2280 | ohci_free_sed(sc, opipe->sed); |
2220 | } | | 2281 | } |
2221 | | | 2282 | |
2222 | /* | | 2283 | /* |
2223 | * Abort a device request. | | 2284 | * Abort a device request. |
2224 | * If this routine is called at splusb() it guarantees that the request | | 2285 | * If this routine is called at splusb() it guarantees that the request |
2225 | * will be removed from the hardware scheduling and that the callback | | 2286 | * will be removed from the hardware scheduling and that the callback |
2226 | * for it will be called with USBD_CANCELLED status. | | 2287 | * for it will be called with USBD_CANCELLED status. |
2227 | * It's impossible to guarantee that the requested transfer will not | | 2288 | * It's impossible to guarantee that the requested transfer will not |
2228 | * have happened since the hardware runs concurrently. | | 2289 | * have happened since the hardware runs concurrently. |
2229 | * If the transaction has already happened we rely on the ordinary | | 2290 | * If the transaction has already happened we rely on the ordinary |
2230 | * interrupt processing to process it. | | 2291 | * interrupt processing to process it. |
2231 | */ | | 2292 | */ |
2232 | void | | 2293 | void |
2233 | ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) | | 2294 | ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) |
2234 | { | | 2295 | { |
2235 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; | | 2296 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; |
2236 | ohci_softc_t *sc = opipe->pipe.device->bus->hci_private; | | 2297 | ohci_softc_t *sc = opipe->pipe.device->bus->hci_private; |
2237 | ohci_soft_ed_t *sed = opipe->sed; | | 2298 | ohci_soft_ed_t *sed = opipe->sed; |
2238 | ohci_soft_td_t *p, *n; | | 2299 | ohci_soft_td_t *p, *n; |
2239 | ohci_physaddr_t headp; | | 2300 | ohci_physaddr_t headp; |
2240 | int s, hit; | | 2301 | int hit; |
2241 | int wake; | | 2302 | int wake; |
2242 | | | 2303 | |
2243 | DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,sed)); | | 2304 | DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,sed)); |
2244 | | | 2305 | |
2245 | if (sc->sc_dying) { | | 2306 | if (sc->sc_dying) { |
2246 | /* If we're dying, just do the software part. */ | | 2307 | /* If we're dying, just do the software part. */ |
2247 | s = splusb(); | | 2308 | mutex_enter(&sc->sc_lock); |
2248 | xfer->status = status; /* make software ignore it */ | | 2309 | xfer->status = status; /* make software ignore it */ |
2249 | callout_stop(&xfer->timeout_handle); | | 2310 | callout_halt(&xfer->timeout_handle, &sc->sc_lock); |
2250 | usb_transfer_complete(xfer); | | 2311 | usb_transfer_complete(xfer); |
2251 | splx(s); | | 2312 | mutex_exit(&sc->sc_lock); |
2252 | return; | | 2313 | return; |
2253 | } | | 2314 | } |
2254 | | | 2315 | |
2255 | if (xfer->device->bus->intr_context || !curproc) | | 2316 | if (xfer->device->bus->intr_context || !curproc) |
2256 | panic("ohci_abort_xfer: not in process context"); | | 2317 | panic("ohci_abort_xfer: not in process context"); |
2257 | | | 2318 | |
| | | 2319 | mutex_enter(&sc->sc_lock); |
| | | 2320 | |
2258 | /* | | 2321 | /* |
2259 | * If an abort is already in progress then just wait for it to | | 2322 | * If an abort is already in progress then just wait for it to |
2260 | * complete and return. | | 2323 | * complete and return. |
2261 | */ | | 2324 | */ |
2262 | if (xfer->hcflags & UXFER_ABORTING) { | | 2325 | if (xfer->hcflags & UXFER_ABORTING) { |
2263 | DPRINTFN(2, ("ohci_abort_xfer: already aborting\n")); | | 2326 | DPRINTFN(2, ("ohci_abort_xfer: already aborting\n")); |
2264 | #ifdef DIAGNOSTIC | | 2327 | #ifdef DIAGNOSTIC |
2265 | if (status == USBD_TIMEOUT) | | 2328 | if (status == USBD_TIMEOUT) |
2266 | printf("0hci_abort_xfer: TIMEOUT while aborting\n"); | | 2329 | printf("0hci_abort_xfer: TIMEOUT while aborting\n"); |
2267 | #endif | | 2330 | #endif |
2268 | /* Override the status which might be USBD_TIMEOUT. */ | | 2331 | /* Override the status which might be USBD_TIMEOUT. */ |
2269 | xfer->status = status; | | 2332 | xfer->status = status; |
2270 | DPRINTFN(2, ("ohci_abort_xfer: waiting for abort to finish\n")); | | 2333 | DPRINTFN(2, ("ohci_abort_xfer: waiting for abort to finish\n")); |
2271 | xfer->hcflags |= UXFER_ABORTWAIT; | | 2334 | xfer->hcflags |= UXFER_ABORTWAIT; |
2272 | while (xfer->hcflags & UXFER_ABORTING) | | 2335 | while (xfer->hcflags & UXFER_ABORTING) |
2273 | tsleep(&xfer->hcflags, PZERO, "ohciaw", 0); | | 2336 | cv_wait(&xfer->hccv, &sc->sc_lock); |
| | | 2337 | goto done; |
2274 | return; | | 2338 | return; |
2275 | } | | 2339 | } |
2276 | xfer->hcflags |= UXFER_ABORTING; | | 2340 | xfer->hcflags |= UXFER_ABORTING; |
2277 | | | 2341 | |
2278 | /* | | 2342 | /* |
2279 | * Step 1: Make interrupt routine and hardware ignore xfer. | | 2343 | * Step 1: Make interrupt routine and hardware ignore xfer. |
2280 | */ | | 2344 | */ |
2281 | s = splusb(); | | | |
2282 | xfer->status = status; /* make software ignore it */ | | 2345 | xfer->status = status; /* make software ignore it */ |
2283 | callout_stop(&xfer->timeout_handle); | | 2346 | callout_stop(&xfer->timeout_handle); |
2284 | splx(s); | | | |
2285 | DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed)); | | 2347 | DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed)); |
2286 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), | | 2348 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), |
2287 | sizeof(sed->ed.ed_flags), | | 2349 | sizeof(sed->ed.ed_flags), |
2288 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 2350 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
2289 | sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); /* force hardware skip */ | | 2351 | sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); /* force hardware skip */ |
2290 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), | | 2352 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), |
2291 | sizeof(sed->ed.ed_flags), | | 2353 | sizeof(sed->ed.ed_flags), |
2292 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 2354 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
2293 | | | 2355 | |
2294 | /* | | 2356 | /* |
2295 | * Step 2: Wait until we know hardware has finished any possible | | 2357 | * Step 2: Wait until we know hardware has finished any possible |
2296 | * use of the xfer. Also make sure the soft interrupt routine | | 2358 | * use of the xfer. Also make sure the soft interrupt routine |
2297 | * has run. | | 2359 | * has run. |
2298 | */ | | 2360 | */ |
2299 | usb_delay_ms(opipe->pipe.device->bus, 20); /* Hardware finishes in 1ms */ | | 2361 | usb_delay_ms(opipe->pipe.device->bus, 20); /* Hardware finishes in 1ms */ |
2300 | s = splusb(); | | | |
2301 | #ifdef USB_USE_SOFTINTR | | | |
2302 | sc->sc_softwake = 1; | | 2362 | sc->sc_softwake = 1; |
2303 | #endif /* USB_USE_SOFTINTR */ | | | |
2304 | usb_schedsoftintr(&sc->sc_bus); | | 2363 | usb_schedsoftintr(&sc->sc_bus); |
2305 | #ifdef USB_USE_SOFTINTR | | 2364 | cv_wait(&sc->sc_softwake_cv, &sc->sc_lock); |
2306 | tsleep(&sc->sc_softwake, PZERO, "ohciab", 0); | | | |
2307 | #endif /* USB_USE_SOFTINTR */ | | | |
2308 | splx(s); | | | |
2309 | | | 2365 | |
2310 | /* | | 2366 | /* |
2311 | * Step 3: Remove any vestiges of the xfer from the hardware. | | 2367 | * Step 3: Remove any vestiges of the xfer from the hardware. |
2312 | * The complication here is that the hardware may have executed | | 2368 | * The complication here is that the hardware may have executed |
2313 | * beyond the xfer we're trying to abort. So as we're scanning | | 2369 | * beyond the xfer we're trying to abort. So as we're scanning |
2314 | * the TDs of this xfer we check if the hardware points to | | 2370 | * the TDs of this xfer we check if the hardware points to |
2315 | * any of them. | | 2371 | * any of them. |
2316 | */ | | 2372 | */ |
2317 | s = splusb(); /* XXX why? */ | | | |
2318 | p = xfer->hcpriv; | | 2373 | p = xfer->hcpriv; |
2319 | #ifdef DIAGNOSTIC | | 2374 | #ifdef DIAGNOSTIC |
2320 | if (p == NULL) { | | 2375 | if (p == NULL) { |
2321 | xfer->hcflags &= ~UXFER_ABORTING; /* XXX */ | | 2376 | xfer->hcflags &= ~UXFER_ABORTING; /* XXX */ |
2322 | splx(s); | | | |
2323 | printf("ohci_abort_xfer: hcpriv is NULL\n"); | | 2377 | printf("ohci_abort_xfer: hcpriv is NULL\n"); |
2324 | return; | | 2378 | goto done; |
2325 | } | | 2379 | } |
2326 | #endif | | 2380 | #endif |
2327 | #ifdef OHCI_DEBUG | | 2381 | #ifdef OHCI_DEBUG |
2328 | if (ohcidebug > 1) { | | 2382 | if (ohcidebug > 1) { |
2329 | DPRINTF(("ohci_abort_xfer: sed=\n")); | | 2383 | DPRINTF(("ohci_abort_xfer: sed=\n")); |
2330 | ohci_dump_ed(sc, sed); | | 2384 | ohci_dump_ed(sc, sed); |
2331 | ohci_dump_tds(sc, p); | | 2385 | ohci_dump_tds(sc, p); |
2332 | } | | 2386 | } |
2333 | #endif | | 2387 | #endif |
2334 | headp = O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK; | | 2388 | headp = O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK; |
2335 | hit = 0; | | 2389 | hit = 0; |
2336 | for (; p->xfer == xfer; p = n) { | | 2390 | for (; p->xfer == xfer; p = n) { |
2337 | hit |= headp == p->physaddr; | | 2391 | hit |= headp == p->physaddr; |
| @@ -2359,29 +2413,30 @@ ohci_abort_xfer(usbd_xfer_handle xfer, u | | | @@ -2359,29 +2413,30 @@ ohci_abort_xfer(usbd_xfer_handle xfer, u |
2359 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 2413 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
2360 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */ | | 2414 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */ |
2361 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), | | 2415 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), |
2362 | sizeof(sed->ed.ed_flags), | | 2416 | sizeof(sed->ed.ed_flags), |
2363 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 2417 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
2364 | | | 2418 | |
2365 | /* | | 2419 | /* |
2366 | * Step 5: Execute callback. | | 2420 | * Step 5: Execute callback. |
2367 | */ | | 2421 | */ |
2368 | wake = xfer->hcflags & UXFER_ABORTWAIT; | | 2422 | wake = xfer->hcflags & UXFER_ABORTWAIT; |
2369 | xfer->hcflags &= ~(UXFER_ABORTING | UXFER_ABORTWAIT); | | 2423 | xfer->hcflags &= ~(UXFER_ABORTING | UXFER_ABORTWAIT); |
2370 | usb_transfer_complete(xfer); | | 2424 | usb_transfer_complete(xfer); |
2371 | if (wake) | | 2425 | if (wake) |
2372 | wakeup(&xfer->hcflags); | | 2426 | cv_broadcast(&xfer->hccv); |
2373 | | | 2427 | |
2374 | splx(s); | | 2428 | done: |
| | | 2429 | mutex_exit(&sc->sc_lock); |
2375 | } | | 2430 | } |
2376 | | | 2431 | |
2377 | /* | | 2432 | /* |
2378 | * Data structures and routines to emulate the root hub. | | 2433 | * Data structures and routines to emulate the root hub. |
2379 | */ | | 2434 | */ |
2380 | Static usb_device_descriptor_t ohci_devd = { | | 2435 | Static usb_device_descriptor_t ohci_devd = { |
2381 | USB_DEVICE_DESCRIPTOR_SIZE, | | 2436 | USB_DEVICE_DESCRIPTOR_SIZE, |
2382 | UDESC_DEVICE, /* type */ | | 2437 | UDESC_DEVICE, /* type */ |
2383 | {0x00, 0x01}, /* USB version */ | | 2438 | {0x00, 0x01}, /* USB version */ |
2384 | UDCLASS_HUB, /* class */ | | 2439 | UDCLASS_HUB, /* class */ |
2385 | UDSUBCLASS_HUB, /* subclass */ | | 2440 | UDSUBCLASS_HUB, /* subclass */ |
2386 | UDPROTO_FSHUB, /* protocol */ | | 2441 | UDPROTO_FSHUB, /* protocol */ |
2387 | 64, /* max packet */ | | 2442 | 64, /* max packet */ |
| @@ -2425,45 +2480,48 @@ Static const usb_endpoint_descriptor_t o | | | @@ -2425,45 +2480,48 @@ Static const usb_endpoint_descriptor_t o |
2425 | }; | | 2480 | }; |
2426 | | | 2481 | |
2427 | Static const usb_hub_descriptor_t ohci_hubd = { | | 2482 | Static const usb_hub_descriptor_t ohci_hubd = { |
2428 | .bDescLength = USB_HUB_DESCRIPTOR_SIZE, | | 2483 | .bDescLength = USB_HUB_DESCRIPTOR_SIZE, |
2429 | .bDescriptorType = UDESC_HUB, | | 2484 | .bDescriptorType = UDESC_HUB, |
2430 | }; | | 2485 | }; |
2431 | | | 2486 | |
2432 | /* | | 2487 | /* |
2433 | * Simulate a hardware hub by handling all the necessary requests. | | 2488 | * Simulate a hardware hub by handling all the necessary requests. |
2434 | */ | | 2489 | */ |
2435 | Static usbd_status | | 2490 | Static usbd_status |
2436 | ohci_root_ctrl_transfer(usbd_xfer_handle xfer) | | 2491 | ohci_root_ctrl_transfer(usbd_xfer_handle xfer) |
2437 | { | | 2492 | { |
| | | 2493 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
2438 | usbd_status err; | | 2494 | usbd_status err; |
2439 | | | 2495 | |
2440 | /* Insert last in queue. */ | | 2496 | /* Insert last in queue. */ |
| | | 2497 | mutex_enter(&sc->sc_lock); |
2441 | err = usb_insert_transfer(xfer); | | 2498 | err = usb_insert_transfer(xfer); |
| | | 2499 | mutex_exit(&sc->sc_lock); |
2442 | if (err) | | 2500 | if (err) |
2443 | return (err); | | 2501 | return (err); |
2444 | | | 2502 | |
2445 | /* Pipe isn't running, start first */ | | 2503 | /* Pipe isn't running, start first */ |
2446 | return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); | | 2504 | return (ohci_root_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); |
2447 | } | | 2505 | } |
2448 | | | 2506 | |
2449 | Static usbd_status | | 2507 | Static usbd_status |
2450 | ohci_root_ctrl_start(usbd_xfer_handle xfer) | | 2508 | ohci_root_ctrl_start(usbd_xfer_handle xfer) |
2451 | { | | 2509 | { |
2452 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; | | 2510 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
2453 | usb_device_request_t *req; | | 2511 | usb_device_request_t *req; |
2454 | void *buf = NULL; | | 2512 | void *buf = NULL; |
2455 | int port, i; | | 2513 | int port, i; |
2456 | int s, len, value, index, l, totlen = 0; | | 2514 | int len, value, index, l, totlen = 0; |
2457 | usb_port_status_t ps; | | 2515 | usb_port_status_t ps; |
2458 | usb_hub_descriptor_t hubd; | | 2516 | usb_hub_descriptor_t hubd; |
2459 | usbd_status err; | | 2517 | usbd_status err; |
2460 | u_int32_t v; | | 2518 | u_int32_t v; |
2461 | | | 2519 | |
2462 | if (sc->sc_dying) | | 2520 | if (sc->sc_dying) |
2463 | return (USBD_IOERROR); | | 2521 | return (USBD_IOERROR); |
2464 | | | 2522 | |
2465 | #ifdef DIAGNOSTIC | | 2523 | #ifdef DIAGNOSTIC |
2466 | if (!(xfer->rqflags & URQ_REQUEST)) | | 2524 | if (!(xfer->rqflags & URQ_REQUEST)) |
2467 | /* XXX panic */ | | 2525 | /* XXX panic */ |
2468 | return (USBD_INVAL); | | 2526 | return (USBD_INVAL); |
2469 | #endif | | 2527 | #endif |
| @@ -2744,217 +2802,235 @@ ohci_root_ctrl_start(usbd_xfer_handle xf | | | @@ -2744,217 +2802,235 @@ ohci_root_ctrl_start(usbd_xfer_handle xf |
2744 | default: | | 2802 | default: |
2745 | err = USBD_IOERROR; | | 2803 | err = USBD_IOERROR; |
2746 | goto ret; | | 2804 | goto ret; |
2747 | } | | 2805 | } |
2748 | break; | | 2806 | break; |
2749 | default: | | 2807 | default: |
2750 | err = USBD_IOERROR; | | 2808 | err = USBD_IOERROR; |
2751 | goto ret; | | 2809 | goto ret; |
2752 | } | | 2810 | } |
2753 | xfer->actlen = totlen; | | 2811 | xfer->actlen = totlen; |
2754 | err = USBD_NORMAL_COMPLETION; | | 2812 | err = USBD_NORMAL_COMPLETION; |
2755 | ret: | | 2813 | ret: |
2756 | xfer->status = err; | | 2814 | xfer->status = err; |
2757 | s = splusb(); | | 2815 | mutex_enter(&sc->sc_lock); |
2758 | usb_transfer_complete(xfer); | | 2816 | usb_transfer_complete(xfer); |
2759 | splx(s); | | 2817 | mutex_exit(&sc->sc_lock); |
2760 | return (USBD_IN_PROGRESS); | | 2818 | return (USBD_IN_PROGRESS); |
2761 | } | | 2819 | } |
2762 | | | 2820 | |
2763 | /* Abort a root control request. */ | | 2821 | /* Abort a root control request. */ |
2764 | Static void | | 2822 | Static void |
2765 | ohci_root_ctrl_abort(usbd_xfer_handle xfer) | | 2823 | ohci_root_ctrl_abort(usbd_xfer_handle xfer) |
2766 | { | | 2824 | { |
2767 | /* Nothing to do, all transfers are synchronous. */ | | 2825 | /* Nothing to do, all transfers are synchronous. */ |
2768 | } | | 2826 | } |
2769 | | | 2827 | |
2770 | /* Close the root pipe. */ | | 2828 | /* Close the root pipe. */ |
2771 | Static void | | 2829 | Static void |
2772 | ohci_root_ctrl_close(usbd_pipe_handle pipe) | | 2830 | ohci_root_ctrl_close(usbd_pipe_handle pipe) |
2773 | { | | 2831 | { |
2774 | DPRINTF(("ohci_root_ctrl_close\n")); | | 2832 | DPRINTF(("ohci_root_ctrl_close\n")); |
2775 | /* Nothing to do. */ | | 2833 | /* Nothing to do. */ |
2776 | } | | 2834 | } |
2777 | | | 2835 | |
2778 | Static usbd_status | | 2836 | Static usbd_status |
2779 | ohci_root_intr_transfer(usbd_xfer_handle xfer) | | 2837 | ohci_root_intr_transfer(usbd_xfer_handle xfer) |
2780 | { | | 2838 | { |
| | | 2839 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
2781 | usbd_status err; | | 2840 | usbd_status err; |
2782 | | | 2841 | |
2783 | /* Insert last in queue. */ | | 2842 | /* Insert last in queue. */ |
| | | 2843 | mutex_enter(&sc->sc_lock); |
2784 | err = usb_insert_transfer(xfer); | | 2844 | err = usb_insert_transfer(xfer); |
| | | 2845 | mutex_exit(&sc->sc_lock); |
2785 | if (err) | | 2846 | if (err) |
2786 | return (err); | | 2847 | return (err); |
2787 | | | 2848 | |
2788 | /* Pipe isn't running, start first */ | | 2849 | /* Pipe isn't running, start first */ |
2789 | return (ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); | | 2850 | return (ohci_root_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); |
2790 | } | | 2851 | } |
2791 | | | 2852 | |
2792 | Static usbd_status | | 2853 | Static usbd_status |
2793 | ohci_root_intr_start(usbd_xfer_handle xfer) | | 2854 | ohci_root_intr_start(usbd_xfer_handle xfer) |
2794 | { | | 2855 | { |
2795 | usbd_pipe_handle pipe = xfer->pipe; | | 2856 | usbd_pipe_handle pipe = xfer->pipe; |
2796 | ohci_softc_t *sc = pipe->device->bus->hci_private; | | 2857 | ohci_softc_t *sc = pipe->device->bus->hci_private; |
2797 | | | 2858 | |
2798 | if (sc->sc_dying) | | 2859 | if (sc->sc_dying) |
2799 | return (USBD_IOERROR); | | 2860 | return (USBD_IOERROR); |
2800 | | | 2861 | |
| | | 2862 | mutex_enter(&sc->sc_lock); |
| | | 2863 | KASSERT(sc->sc_intrxfer == NULL); |
2801 | sc->sc_intrxfer = xfer; | | 2864 | sc->sc_intrxfer = xfer; |
| | | 2865 | mutex_exit(&sc->sc_lock); |
2802 | | | 2866 | |
2803 | return (USBD_IN_PROGRESS); | | 2867 | return (USBD_IN_PROGRESS); |
2804 | } | | 2868 | } |
2805 | | | 2869 | |
2806 | /* Abort a root interrupt request. */ | | 2870 | /* Abort a root interrupt request. */ |
2807 | Static void | | 2871 | Static void |
2808 | ohci_root_intr_abort(usbd_xfer_handle xfer) | | 2872 | ohci_root_intr_abort(usbd_xfer_handle xfer) |
2809 | { | | 2873 | { |
2810 | int s; | | 2874 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
2811 | | | 2875 | |
2812 | if (xfer->pipe->intrxfer == xfer) { | | 2876 | if (xfer->pipe->intrxfer == xfer) { |
2813 | DPRINTF(("ohci_root_intr_abort: remove\n")); | | 2877 | DPRINTF(("ohci_root_intr_abort: remove\n")); |
2814 | xfer->pipe->intrxfer = NULL; | | 2878 | xfer->pipe->intrxfer = NULL; |
2815 | } | | 2879 | } |
2816 | xfer->status = USBD_CANCELLED; | | 2880 | xfer->status = USBD_CANCELLED; |
2817 | s = splusb(); | | 2881 | mutex_enter(&sc->sc_lock); |
2818 | usb_transfer_complete(xfer); | | 2882 | usb_transfer_complete(xfer); |
2819 | splx(s); | | 2883 | mutex_exit(&sc->sc_lock); |
2820 | } | | 2884 | } |
2821 | | | 2885 | |
2822 | /* Close the root pipe. */ | | 2886 | /* Close the root pipe. */ |
2823 | Static void | | 2887 | Static void |
2824 | ohci_root_intr_close(usbd_pipe_handle pipe) | | 2888 | ohci_root_intr_close(usbd_pipe_handle pipe) |
2825 | { | | 2889 | { |
2826 | ohci_softc_t *sc = pipe->device->bus->hci_private; | | 2890 | ohci_softc_t *sc = pipe->device->bus->hci_private; |
2827 | | | 2891 | |
2828 | DPRINTF(("ohci_root_intr_close\n")); | | 2892 | DPRINTF(("ohci_root_intr_close\n")); |
2829 | | | 2893 | |
2830 | sc->sc_intrxfer = NULL; | | 2894 | sc->sc_intrxfer = NULL; |
2831 | } | | 2895 | } |
2832 | | | 2896 | |
2833 | /************************/ | | 2897 | /************************/ |
2834 | | | 2898 | |
2835 | Static usbd_status | | 2899 | Static usbd_status |
2836 | ohci_device_ctrl_transfer(usbd_xfer_handle xfer) | | 2900 | ohci_device_ctrl_transfer(usbd_xfer_handle xfer) |
2837 | { | | 2901 | { |
| | | 2902 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
2838 | usbd_status err; | | 2903 | usbd_status err; |
2839 | | | 2904 | |
2840 | /* Insert last in queue. */ | | 2905 | /* Insert last in queue. */ |
| | | 2906 | mutex_enter(&sc->sc_lock); |
2841 | err = usb_insert_transfer(xfer); | | 2907 | err = usb_insert_transfer(xfer); |
| | | 2908 | mutex_exit(&sc->sc_lock); |
2842 | if (err) | | 2909 | if (err) |
2843 | return (err); | | 2910 | return (err); |
2844 | | | 2911 | |
2845 | /* Pipe isn't running, start first */ | | 2912 | /* Pipe isn't running, start first */ |
2846 | return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); | | 2913 | return (ohci_device_ctrl_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); |
2847 | } | | 2914 | } |
2848 | | | 2915 | |
2849 | Static usbd_status | | 2916 | Static usbd_status |
2850 | ohci_device_ctrl_start(usbd_xfer_handle xfer) | | 2917 | ohci_device_ctrl_start(usbd_xfer_handle xfer) |
2851 | { | | 2918 | { |
2852 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; | | 2919 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
2853 | usbd_status err; | | 2920 | usbd_status err; |
2854 | | | 2921 | |
2855 | if (sc->sc_dying) | | 2922 | if (sc->sc_dying) |
2856 | return (USBD_IOERROR); | | 2923 | return (USBD_IOERROR); |
2857 | | | 2924 | |
2858 | #ifdef DIAGNOSTIC | | 2925 | #ifdef DIAGNOSTIC |
2859 | if (!(xfer->rqflags & URQ_REQUEST)) { | | 2926 | if (!(xfer->rqflags & URQ_REQUEST)) { |
2860 | /* XXX panic */ | | 2927 | /* XXX panic */ |
2861 | printf("ohci_device_ctrl_transfer: not a request\n"); | | 2928 | printf("ohci_device_ctrl_transfer: not a request\n"); |
2862 | return (USBD_INVAL); | | 2929 | return (USBD_INVAL); |
2863 | } | | 2930 | } |
2864 | #endif | | 2931 | #endif |
2865 | | | 2932 | |
| | | 2933 | mutex_enter(&sc->sc_lock); |
2866 | err = ohci_device_request(xfer); | | 2934 | err = ohci_device_request(xfer); |
| | | 2935 | mutex_exit(&sc->sc_lock); |
2867 | if (err) | | 2936 | if (err) |
2868 | return (err); | | 2937 | return (err); |
2869 | | | 2938 | |
2870 | if (sc->sc_bus.use_polling) | | 2939 | if (sc->sc_bus.use_polling) |
2871 | ohci_waitintr(sc, xfer); | | 2940 | ohci_waitintr(sc, xfer); |
2872 | return (USBD_IN_PROGRESS); | | 2941 | return (USBD_IN_PROGRESS); |
2873 | } | | 2942 | } |
2874 | | | 2943 | |
2875 | /* Abort a device control request. */ | | 2944 | /* Abort a device control request. */ |
2876 | Static void | | 2945 | Static void |
2877 | ohci_device_ctrl_abort(usbd_xfer_handle xfer) | | 2946 | ohci_device_ctrl_abort(usbd_xfer_handle xfer) |
2878 | { | | 2947 | { |
2879 | DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer)); | | 2948 | DPRINTF(("ohci_device_ctrl_abort: xfer=%p\n", xfer)); |
2880 | ohci_abort_xfer(xfer, USBD_CANCELLED); | | 2949 | ohci_abort_xfer(xfer, USBD_CANCELLED); |
2881 | } | | 2950 | } |
2882 | | | 2951 | |
2883 | /* Close a device control pipe. */ | | 2952 | /* Close a device control pipe. */ |
2884 | Static void | | 2953 | Static void |
2885 | ohci_device_ctrl_close(usbd_pipe_handle pipe) | | 2954 | ohci_device_ctrl_close(usbd_pipe_handle pipe) |
2886 | { | | 2955 | { |
2887 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; | | 2956 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; |
2888 | ohci_softc_t *sc = pipe->device->bus->hci_private; | | 2957 | ohci_softc_t *sc = pipe->device->bus->hci_private; |
2889 | | | 2958 | |
2890 | DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe)); | | 2959 | DPRINTF(("ohci_device_ctrl_close: pipe=%p\n", pipe)); |
| | | 2960 | mutex_enter(&sc->sc_lock); |
2891 | ohci_close_pipe(pipe, sc->sc_ctrl_head); | | 2961 | ohci_close_pipe(pipe, sc->sc_ctrl_head); |
| | | 2962 | mutex_exit(&sc->sc_lock); |
2892 | ohci_free_std(sc, opipe->tail.td); | | 2963 | ohci_free_std(sc, opipe->tail.td); |
2893 | } | | 2964 | } |
2894 | | | 2965 | |
2895 | /************************/ | | 2966 | /************************/ |
2896 | | | 2967 | |
2897 | Static void | | 2968 | Static void |
2898 | ohci_device_clear_toggle(usbd_pipe_handle pipe) | | 2969 | ohci_device_clear_toggle(usbd_pipe_handle pipe) |
2899 | { | | 2970 | { |
2900 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; | | 2971 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; |
2901 | ohci_softc_t *sc = pipe->device->bus->hci_private; | | 2972 | ohci_softc_t *sc = pipe->device->bus->hci_private; |
2902 | | | 2973 | |
2903 | opipe->sed->ed.ed_headp &= HTOO32(~OHCI_TOGGLECARRY); | | 2974 | opipe->sed->ed.ed_headp &= HTOO32(~OHCI_TOGGLECARRY); |
2904 | } | | 2975 | } |
2905 | | | 2976 | |
2906 | Static void | | 2977 | Static void |
2907 | ohci_noop(usbd_pipe_handle pipe) | | 2978 | ohci_noop(usbd_pipe_handle pipe) |
2908 | { | | 2979 | { |
2909 | } | | 2980 | } |
2910 | | | 2981 | |
2911 | Static usbd_status | | 2982 | Static usbd_status |
2912 | ohci_device_bulk_transfer(usbd_xfer_handle xfer) | | 2983 | ohci_device_bulk_transfer(usbd_xfer_handle xfer) |
2913 | { | | 2984 | { |
| | | 2985 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
2914 | usbd_status err; | | 2986 | usbd_status err; |
2915 | | | 2987 | |
2916 | /* Insert last in queue. */ | | 2988 | /* Insert last in queue. */ |
| | | 2989 | mutex_enter(&sc->sc_lock); |
2917 | err = usb_insert_transfer(xfer); | | 2990 | err = usb_insert_transfer(xfer); |
| | | 2991 | mutex_exit(&sc->sc_lock); |
2918 | if (err) | | 2992 | if (err) |
2919 | return (err); | | 2993 | return (err); |
2920 | | | 2994 | |
2921 | /* Pipe isn't running, start first */ | | 2995 | /* Pipe isn't running, start first */ |
2922 | return (ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); | | 2996 | return (ohci_device_bulk_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); |
2923 | } | | 2997 | } |
2924 | | | 2998 | |
2925 | Static usbd_status | | 2999 | Static usbd_status |
2926 | ohci_device_bulk_start(usbd_xfer_handle xfer) | | 3000 | ohci_device_bulk_start(usbd_xfer_handle xfer) |
2927 | { | | 3001 | { |
2928 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; | | 3002 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; |
2929 | usbd_device_handle dev = opipe->pipe.device; | | 3003 | usbd_device_handle dev = opipe->pipe.device; |
2930 | ohci_softc_t *sc = dev->bus->hci_private; | | 3004 | ohci_softc_t *sc = dev->bus->hci_private; |
2931 | int addr = dev->address; | | 3005 | int addr = dev->address; |
2932 | ohci_soft_td_t *data, *tail, *tdp; | | 3006 | ohci_soft_td_t *data, *tail, *tdp; |
2933 | ohci_soft_ed_t *sed; | | 3007 | ohci_soft_ed_t *sed; |
2934 | int s, len, isread, endpt; | | 3008 | int len, isread, endpt; |
2935 | usbd_status err; | | 3009 | usbd_status err; |
2936 | | | 3010 | |
2937 | if (sc->sc_dying) | | 3011 | if (sc->sc_dying) |
2938 | return (USBD_IOERROR); | | 3012 | return (USBD_IOERROR); |
2939 | | | 3013 | |
2940 | #ifdef DIAGNOSTIC | | 3014 | #ifdef DIAGNOSTIC |
2941 | if (xfer->rqflags & URQ_REQUEST) { | | 3015 | if (xfer->rqflags & URQ_REQUEST) { |
2942 | /* XXX panic */ | | 3016 | /* XXX panic */ |
2943 | printf("ohci_device_bulk_start: a request\n"); | | 3017 | printf("ohci_device_bulk_start: a request\n"); |
2944 | return (USBD_INVAL); | | 3018 | return (USBD_INVAL); |
2945 | } | | 3019 | } |
2946 | #endif | | 3020 | #endif |
2947 | | | 3021 | |
| | | 3022 | mutex_enter(&sc->sc_lock); |
| | | 3023 | |
2948 | len = xfer->length; | | 3024 | len = xfer->length; |
2949 | endpt = xfer->pipe->endpoint->edesc->bEndpointAddress; | | 3025 | endpt = xfer->pipe->endpoint->edesc->bEndpointAddress; |
2950 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | | 3026 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; |
2951 | sed = opipe->sed; | | 3027 | sed = opipe->sed; |
2952 | | | 3028 | |
2953 | DPRINTFN(4,("ohci_device_bulk_start: xfer=%p len=%d isread=%d " | | 3029 | DPRINTFN(4,("ohci_device_bulk_start: xfer=%p len=%d isread=%d " |
2954 | "flags=%d endpt=%d\n", xfer, len, isread, xfer->flags, | | 3030 | "flags=%d endpt=%d\n", xfer, len, isread, xfer->flags, |
2955 | endpt)); | | 3031 | endpt)); |
2956 | | | 3032 | |
2957 | opipe->u.bulk.isread = isread; | | 3033 | opipe->u.bulk.isread = isread; |
2958 | opipe->u.bulk.length = len; | | 3034 | opipe->u.bulk.length = len; |
2959 | | | 3035 | |
2960 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | | 3036 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), |
| @@ -2966,124 +3042,129 @@ ohci_device_bulk_start(usbd_xfer_handle | | | @@ -2966,124 +3042,129 @@ ohci_device_bulk_start(usbd_xfer_handle |
2966 | | | 3042 | |
2967 | /* Allocate a chain of new TDs (including a new tail). */ | | 3043 | /* Allocate a chain of new TDs (including a new tail). */ |
2968 | data = opipe->tail.td; | | 3044 | data = opipe->tail.td; |
2969 | err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer, | | 3045 | err = ohci_alloc_std_chain(opipe, sc, len, isread, xfer, |
2970 | data, &tail); | | 3046 | data, &tail); |
2971 | /* We want interrupt at the end of the transfer. */ | | 3047 | /* We want interrupt at the end of the transfer. */ |
2972 | tail->td.td_flags &= HTOO32(~OHCI_TD_INTR_MASK); | | 3048 | tail->td.td_flags &= HTOO32(~OHCI_TD_INTR_MASK); |
2973 | tail->td.td_flags |= HTOO32(OHCI_TD_SET_DI(1)); | | 3049 | tail->td.td_flags |= HTOO32(OHCI_TD_SET_DI(1)); |
2974 | tail->flags |= OHCI_CALL_DONE; | | 3050 | tail->flags |= OHCI_CALL_DONE; |
2975 | tail = tail->nexttd; /* point at sentinel */ | | 3051 | tail = tail->nexttd; /* point at sentinel */ |
2976 | usb_syncmem(&tail->dma, tail->offs + offsetof(ohci_td_t, td_flags), | | 3052 | usb_syncmem(&tail->dma, tail->offs + offsetof(ohci_td_t, td_flags), |
2977 | sizeof(tail->td.td_flags), | | 3053 | sizeof(tail->td.td_flags), |
2978 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3054 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
2979 | if (err) | | 3055 | if (err) { |
| | | 3056 | mutex_exit(&sc->sc_lock); |
2980 | return (err); | | 3057 | return (err); |
| | | 3058 | } |
2981 | | | 3059 | |
2982 | tail->xfer = NULL; | | 3060 | tail->xfer = NULL; |
2983 | xfer->hcpriv = data; | | 3061 | xfer->hcpriv = data; |
2984 | | | 3062 | |
2985 | DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x " | | 3063 | DPRINTFN(4,("ohci_device_bulk_start: ed_flags=0x%08x td_flags=0x%08x " |
2986 | "td_cbp=0x%08x td_be=0x%08x\n", | | 3064 | "td_cbp=0x%08x td_be=0x%08x\n", |
2987 | (int)O32TOH(sed->ed.ed_flags), | | 3065 | (int)O32TOH(sed->ed.ed_flags), |
2988 | (int)O32TOH(data->td.td_flags), | | 3066 | (int)O32TOH(data->td.td_flags), |
2989 | (int)O32TOH(data->td.td_cbp), | | 3067 | (int)O32TOH(data->td.td_cbp), |
2990 | (int)O32TOH(data->td.td_be))); | | 3068 | (int)O32TOH(data->td.td_be))); |
2991 | | | 3069 | |
2992 | #ifdef OHCI_DEBUG | | 3070 | #ifdef OHCI_DEBUG |
2993 | if (ohcidebug > 5) { | | 3071 | if (ohcidebug > 5) { |
2994 | ohci_dump_ed(sc, sed); | | 3072 | ohci_dump_ed(sc, sed); |
2995 | ohci_dump_tds(sc, data); | | 3073 | ohci_dump_tds(sc, data); |
2996 | } | | 3074 | } |
2997 | #endif | | 3075 | #endif |
2998 | | | 3076 | |
2999 | /* Insert ED in schedule */ | | 3077 | /* Insert ED in schedule */ |
3000 | s = splusb(); | | | |
3001 | for (tdp = data; tdp != tail; tdp = tdp->nexttd) { | | 3078 | for (tdp = data; tdp != tail; tdp = tdp->nexttd) { |
3002 | tdp->xfer = xfer; | | 3079 | tdp->xfer = xfer; |
3003 | } | | 3080 | } |
3004 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | | 3081 | sed->ed.ed_tailp = HTOO32(tail->physaddr); |
3005 | opipe->tail.td = tail; | | 3082 | opipe->tail.td = tail; |
3006 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); | | 3083 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); |
3007 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | | 3084 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), |
3008 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3085 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3009 | OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF); | | 3086 | OWRITE4(sc, OHCI_COMMAND_STATUS, OHCI_BLF); |
3010 | if (xfer->timeout && !sc->sc_bus.use_polling) { | | 3087 | if (xfer->timeout && !sc->sc_bus.use_polling) { |
3011 | callout_reset(&xfer->timeout_handle, mstohz(xfer->timeout), | | 3088 | callout_reset(&xfer->timeout_handle, mstohz(xfer->timeout), |
3012 | ohci_timeout, xfer); | | 3089 | ohci_timeout, xfer); |
3013 | } | | 3090 | } |
| | | 3091 | mutex_exit(&sc->sc_lock); |
3014 | | | 3092 | |
3015 | #if 0 | | 3093 | #if 0 |
3016 | /* This goes wrong if we are too slow. */ | | 3094 | /* This goes wrong if we are too slow. */ |
3017 | if (ohcidebug > 10) { | | 3095 | if (ohcidebug > 10) { |
3018 | delay(10000); | | 3096 | delay(10000); |
3019 | DPRINTF(("ohci_device_intr_transfer: status=%x\n", | | 3097 | DPRINTF(("ohci_device_intr_transfer: status=%x\n", |
3020 | OREAD4(sc, OHCI_COMMAND_STATUS))); | | 3098 | OREAD4(sc, OHCI_COMMAND_STATUS))); |
3021 | ohci_dump_ed(sc, sed); | | 3099 | ohci_dump_ed(sc, sed); |
3022 | ohci_dump_tds(sc, data); | | 3100 | ohci_dump_tds(sc, data); |
3023 | } | | 3101 | } |
3024 | #endif | | 3102 | #endif |
3025 | | | 3103 | |
3026 | splx(s); | | | |
3027 | | | | |
3028 | return (USBD_IN_PROGRESS); | | 3104 | return (USBD_IN_PROGRESS); |
3029 | } | | 3105 | } |
3030 | | | 3106 | |
3031 | Static void | | 3107 | Static void |
3032 | ohci_device_bulk_abort(usbd_xfer_handle xfer) | | 3108 | ohci_device_bulk_abort(usbd_xfer_handle xfer) |
3033 | { | | 3109 | { |
3034 | DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer)); | | 3110 | DPRINTF(("ohci_device_bulk_abort: xfer=%p\n", xfer)); |
3035 | ohci_abort_xfer(xfer, USBD_CANCELLED); | | 3111 | ohci_abort_xfer(xfer, USBD_CANCELLED); |
3036 | } | | 3112 | } |
3037 | | | 3113 | |
3038 | /* | | 3114 | /* |
3039 | * Close a device bulk pipe. | | 3115 | * Close a device bulk pipe. |
3040 | */ | | 3116 | */ |
3041 | Static void | | 3117 | Static void |
3042 | ohci_device_bulk_close(usbd_pipe_handle pipe) | | 3118 | ohci_device_bulk_close(usbd_pipe_handle pipe) |
3043 | { | | 3119 | { |
3044 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; | | 3120 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; |
3045 | ohci_softc_t *sc = pipe->device->bus->hci_private; | | 3121 | ohci_softc_t *sc = pipe->device->bus->hci_private; |
3046 | | | 3122 | |
3047 | DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe)); | | 3123 | DPRINTF(("ohci_device_bulk_close: pipe=%p\n", pipe)); |
| | | 3124 | mutex_enter(&sc->sc_lock); |
3048 | ohci_close_pipe(pipe, sc->sc_bulk_head); | | 3125 | ohci_close_pipe(pipe, sc->sc_bulk_head); |
| | | 3126 | mutex_exit(&sc->sc_lock); |
3049 | ohci_free_std(sc, opipe->tail.td); | | 3127 | ohci_free_std(sc, opipe->tail.td); |
3050 | } | | 3128 | } |
3051 | | | 3129 | |
3052 | /************************/ | | 3130 | /************************/ |
3053 | | | 3131 | |
3054 | Static usbd_status | | 3132 | Static usbd_status |
3055 | ohci_device_intr_transfer(usbd_xfer_handle xfer) | | 3133 | ohci_device_intr_transfer(usbd_xfer_handle xfer) |
3056 | { | | 3134 | { |
| | | 3135 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
3057 | usbd_status err; | | 3136 | usbd_status err; |
3058 | | | 3137 | |
3059 | /* Insert last in queue. */ | | 3138 | /* Insert last in queue. */ |
| | | 3139 | mutex_enter(&sc->sc_lock); |
3060 | err = usb_insert_transfer(xfer); | | 3140 | err = usb_insert_transfer(xfer); |
| | | 3141 | mutex_exit(&sc->sc_lock); |
3061 | if (err) | | 3142 | if (err) |
3062 | return (err); | | 3143 | return (err); |
3063 | | | 3144 | |
3064 | /* Pipe isn't running, start first */ | | 3145 | /* Pipe isn't running, start first */ |
3065 | return (ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); | | 3146 | return (ohci_device_intr_start(SIMPLEQ_FIRST(&xfer->pipe->queue))); |
3066 | } | | 3147 | } |
3067 | | | 3148 | |
3068 | Static usbd_status | | 3149 | Static usbd_status |
3069 | ohci_device_intr_start(usbd_xfer_handle xfer) | | 3150 | ohci_device_intr_start(usbd_xfer_handle xfer) |
3070 | { | | 3151 | { |
3071 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; | | 3152 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; |
3072 | usbd_device_handle dev = opipe->pipe.device; | | 3153 | usbd_device_handle dev = opipe->pipe.device; |
3073 | ohci_softc_t *sc = dev->bus->hci_private; | | 3154 | ohci_softc_t *sc = dev->bus->hci_private; |
3074 | ohci_soft_ed_t *sed = opipe->sed; | | 3155 | ohci_soft_ed_t *sed = opipe->sed; |
3075 | ohci_soft_td_t *data, *tail; | | 3156 | ohci_soft_td_t *data, *tail; |
3076 | int s, len, isread, endpt; | | 3157 | int len, isread, endpt; |
3077 | | | 3158 | |
3078 | if (sc->sc_dying) | | 3159 | if (sc->sc_dying) |
3079 | return (USBD_IOERROR); | | 3160 | return (USBD_IOERROR); |
3080 | | | 3161 | |
3081 | DPRINTFN(3, ("ohci_device_intr_transfer: xfer=%p len=%d " | | 3162 | DPRINTFN(3, ("ohci_device_intr_transfer: xfer=%p len=%d " |
3082 | "flags=%d priv=%p\n", | | 3163 | "flags=%d priv=%p\n", |
3083 | xfer, xfer->length, xfer->flags, xfer->priv)); | | 3164 | xfer, xfer->length, xfer->flags, xfer->priv)); |
3084 | | | 3165 | |
3085 | #ifdef DIAGNOSTIC | | 3166 | #ifdef DIAGNOSTIC |
3086 | if (xfer->rqflags & URQ_REQUEST) | | 3167 | if (xfer->rqflags & URQ_REQUEST) |
3087 | panic("ohci_device_intr_transfer: a request"); | | 3168 | panic("ohci_device_intr_transfer: a request"); |
3088 | #endif | | 3169 | #endif |
3089 | | | 3170 | |
| @@ -3113,114 +3194,113 @@ ohci_device_intr_start(usbd_xfer_handle | | | @@ -3113,114 +3194,113 @@ ohci_device_intr_start(usbd_xfer_handle |
3113 | usb_syncmem(&data->dma, data->offs, sizeof(data->td), | | 3194 | usb_syncmem(&data->dma, data->offs, sizeof(data->td), |
3114 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3195 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3115 | xfer->hcpriv = data; | | 3196 | xfer->hcpriv = data; |
3116 | | | 3197 | |
3117 | #ifdef OHCI_DEBUG | | 3198 | #ifdef OHCI_DEBUG |
3118 | if (ohcidebug > 5) { | | 3199 | if (ohcidebug > 5) { |
3119 | DPRINTF(("ohci_device_intr_transfer:\n")); | | 3200 | DPRINTF(("ohci_device_intr_transfer:\n")); |
3120 | ohci_dump_ed(sc, sed); | | 3201 | ohci_dump_ed(sc, sed); |
3121 | ohci_dump_tds(sc, data); | | 3202 | ohci_dump_tds(sc, data); |
3122 | } | | 3203 | } |
3123 | #endif | | 3204 | #endif |
3124 | | | 3205 | |
3125 | /* Insert ED in schedule */ | | 3206 | /* Insert ED in schedule */ |
3126 | s = splusb(); | | 3207 | mutex_enter(&sc->sc_lock); |
3127 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | | 3208 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), |
3128 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 3209 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
3129 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | | 3210 | sed->ed.ed_tailp = HTOO32(tail->physaddr); |
3130 | opipe->tail.td = tail; | | 3211 | opipe->tail.td = tail; |
3131 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); | | 3212 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); |
3132 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | | 3213 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), |
3133 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3214 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3134 | | | 3215 | |
3135 | #if 0 | | 3216 | #if 0 |
3136 | /* | | 3217 | /* |
3137 | * This goes horribly wrong, printing thousands of descriptors, | | 3218 | * This goes horribly wrong, printing thousands of descriptors, |
3138 | * because false references are followed due to the fact that the | | 3219 | * because false references are followed due to the fact that the |
3139 | * TD is gone. | | 3220 | * TD is gone. |
3140 | */ | | 3221 | */ |
3141 | if (ohcidebug > 5) { | | 3222 | if (ohcidebug > 5) { |
3142 | usb_delay_ms(&sc->sc_bus, 5); | | 3223 | usb_delay_ms(&sc->sc_bus, 5); |
3143 | DPRINTF(("ohci_device_intr_transfer: status=%x\n", | | 3224 | DPRINTF(("ohci_device_intr_transfer: status=%x\n", |
3144 | OREAD4(sc, OHCI_COMMAND_STATUS))); | | 3225 | OREAD4(sc, OHCI_COMMAND_STATUS))); |
3145 | ohci_dump_ed(sc, sed); | | 3226 | ohci_dump_ed(sc, sed); |
3146 | ohci_dump_tds(sc, data); | | 3227 | ohci_dump_tds(sc, data); |
3147 | } | | 3228 | } |
3148 | #endif | | 3229 | #endif |
3149 | splx(s); | | 3230 | mutex_exit(&sc->sc_lock); |
3150 | | | 3231 | |
3151 | return (USBD_IN_PROGRESS); | | 3232 | return (USBD_IN_PROGRESS); |
3152 | } | | 3233 | } |
3153 | | | 3234 | |
3154 | /* Abort a device control request. */ | | 3235 | /* Abort a device control request. */ |
3155 | Static void | | 3236 | Static void |
3156 | ohci_device_intr_abort(usbd_xfer_handle xfer) | | 3237 | ohci_device_intr_abort(usbd_xfer_handle xfer) |
3157 | { | | 3238 | { |
3158 | if (xfer->pipe->intrxfer == xfer) { | | 3239 | if (xfer->pipe->intrxfer == xfer) { |
3159 | DPRINTF(("ohci_device_intr_abort: remove\n")); | | 3240 | DPRINTF(("ohci_device_intr_abort: remove\n")); |
3160 | xfer->pipe->intrxfer = NULL; | | 3241 | xfer->pipe->intrxfer = NULL; |
3161 | } | | 3242 | } |
3162 | ohci_abort_xfer(xfer, USBD_CANCELLED); | | 3243 | ohci_abort_xfer(xfer, USBD_CANCELLED); |
3163 | } | | 3244 | } |
3164 | | | 3245 | |
3165 | /* Close a device interrupt pipe. */ | | 3246 | /* Close a device interrupt pipe. */ |
3166 | Static void | | 3247 | Static void |
3167 | ohci_device_intr_close(usbd_pipe_handle pipe) | | 3248 | ohci_device_intr_close(usbd_pipe_handle pipe) |
3168 | { | | 3249 | { |
3169 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; | | 3250 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; |
3170 | ohci_softc_t *sc = pipe->device->bus->hci_private; | | 3251 | ohci_softc_t *sc = pipe->device->bus->hci_private; |
3171 | int nslots = opipe->u.intr.nslots; | | 3252 | int nslots = opipe->u.intr.nslots; |
3172 | int pos = opipe->u.intr.pos; | | 3253 | int pos = opipe->u.intr.pos; |
3173 | int j; | | 3254 | int j; |
3174 | ohci_soft_ed_t *p, *sed = opipe->sed; | | 3255 | ohci_soft_ed_t *p, *sed = opipe->sed; |
3175 | int s; | | | |
3176 | | | 3256 | |
3177 | DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n", | | 3257 | DPRINTFN(1,("ohci_device_intr_close: pipe=%p nslots=%d pos=%d\n", |
3178 | pipe, nslots, pos)); | | 3258 | pipe, nslots, pos)); |
3179 | s = splusb(); | | 3259 | mutex_enter(&sc->sc_lock); |
3180 | usb_syncmem(&sed->dma, sed->offs, | | 3260 | usb_syncmem(&sed->dma, sed->offs, |
3181 | sizeof(sed->ed), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 3261 | sizeof(sed->ed), BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
3182 | sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); | | 3262 | sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); |
3183 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), | | 3263 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), |
3184 | sizeof(sed->ed.ed_flags), | | 3264 | sizeof(sed->ed.ed_flags), |
3185 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3265 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3186 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != | | 3266 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != |
3187 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) | | 3267 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) |
3188 | usb_delay_ms(&sc->sc_bus, 2); | | 3268 | usb_delay_ms(&sc->sc_bus, 2); |
3189 | | | 3269 | |
3190 | for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next) | | 3270 | for (p = sc->sc_eds[pos]; p && p->next != sed; p = p->next) |
3191 | continue; | | 3271 | continue; |
3192 | #ifdef DIAGNOSTIC | | 3272 | #ifdef DIAGNOSTIC |
3193 | if (p == NULL) | | 3273 | if (p == NULL) |
3194 | panic("ohci_device_intr_close: ED not found"); | | 3274 | panic("ohci_device_intr_close: ED not found"); |
3195 | #endif | | 3275 | #endif |
3196 | p->next = sed->next; | | 3276 | p->next = sed->next; |
3197 | p->ed.ed_nexted = sed->ed.ed_nexted; | | 3277 | p->ed.ed_nexted = sed->ed.ed_nexted; |
3198 | usb_syncmem(&p->dma, p->offs + offsetof(ohci_ed_t, ed_nexted), | | 3278 | usb_syncmem(&p->dma, p->offs + offsetof(ohci_ed_t, ed_nexted), |
3199 | sizeof(p->ed.ed_nexted), | | 3279 | sizeof(p->ed.ed_nexted), |
3200 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3280 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3201 | splx(s); | | 3281 | mutex_exit(&sc->sc_lock); |
3202 | | | 3282 | |
3203 | for (j = 0; j < nslots; j++) | | 3283 | for (j = 0; j < nslots; j++) |
3204 | --sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS]; | | 3284 | --sc->sc_bws[(pos * nslots + j) % OHCI_NO_INTRS]; |
3205 | | | 3285 | |
3206 | ohci_free_std(sc, opipe->tail.td); | | 3286 | ohci_free_std(sc, opipe->tail.td); |
3207 | ohci_free_sed(sc, opipe->sed); | | 3287 | ohci_free_sed(sc, opipe->sed); |
3208 | } | | 3288 | } |
3209 | | | 3289 | |
3210 | Static usbd_status | | 3290 | Static usbd_status |
3211 | ohci_device_setintr(ohci_softc_t *sc, struct ohci_pipe *opipe, int ival) | | 3291 | ohci_device_setintr(ohci_softc_t *sc, struct ohci_pipe *opipe, int ival) |
3212 | { | | 3292 | { |
3213 | int i, j, s, best; | | 3293 | int i, j, best; |
3214 | u_int npoll, slow, shigh, nslots; | | 3294 | u_int npoll, slow, shigh, nslots; |
3215 | u_int bestbw, bw; | | 3295 | u_int bestbw, bw; |
3216 | ohci_soft_ed_t *hsed, *sed = opipe->sed; | | 3296 | ohci_soft_ed_t *hsed, *sed = opipe->sed; |
3217 | | | 3297 | |
3218 | DPRINTFN(2, ("ohci_setintr: pipe=%p\n", opipe)); | | 3298 | DPRINTFN(2, ("ohci_setintr: pipe=%p\n", opipe)); |
3219 | if (ival == 0) { | | 3299 | if (ival == 0) { |
3220 | printf("ohci_setintr: 0 interval\n"); | | 3300 | printf("ohci_setintr: 0 interval\n"); |
3221 | return (USBD_INVAL); | | 3301 | return (USBD_INVAL); |
3222 | } | | 3302 | } |
3223 | | | 3303 | |
3224 | npoll = OHCI_NO_INTRS; | | 3304 | npoll = OHCI_NO_INTRS; |
3225 | while (npoll > ival) | | 3305 | while (npoll > ival) |
3226 | npoll /= 2; | | 3306 | npoll /= 2; |
| @@ -3242,63 +3322,66 @@ ohci_device_setintr(ohci_softc_t *sc, st | | | @@ -3242,63 +3322,66 @@ ohci_device_setintr(ohci_softc_t *sc, st |
3242 | nslots = OHCI_NO_INTRS / npoll; | | 3322 | nslots = OHCI_NO_INTRS / npoll; |
3243 | for (best = i = slow, bestbw = ~0; i < shigh; i++) { | | 3323 | for (best = i = slow, bestbw = ~0; i < shigh; i++) { |
3244 | bw = 0; | | 3324 | bw = 0; |
3245 | for (j = 0; j < nslots; j++) | | 3325 | for (j = 0; j < nslots; j++) |
3246 | bw += sc->sc_bws[(i * nslots + j) % OHCI_NO_INTRS]; | | 3326 | bw += sc->sc_bws[(i * nslots + j) % OHCI_NO_INTRS]; |
3247 | if (bw < bestbw) { | | 3327 | if (bw < bestbw) { |
3248 | best = i; | | 3328 | best = i; |
3249 | bestbw = bw; | | 3329 | bestbw = bw; |
3250 | } | | 3330 | } |
3251 | } | | 3331 | } |
3252 | DPRINTFN(2, ("ohci_setintr: best=%d(%d..%d) bestbw=%d\n", | | 3332 | DPRINTFN(2, ("ohci_setintr: best=%d(%d..%d) bestbw=%d\n", |
3253 | best, slow, shigh, bestbw)); | | 3333 | best, slow, shigh, bestbw)); |
3254 | | | 3334 | |
3255 | s = splusb(); | | 3335 | mutex_enter(&sc->sc_lock); |
3256 | hsed = sc->sc_eds[best]; | | 3336 | hsed = sc->sc_eds[best]; |
3257 | sed->next = hsed->next; | | 3337 | sed->next = hsed->next; |
3258 | usb_syncmem(&hsed->dma, hsed->offs + offsetof(ohci_ed_t, ed_flags), | | 3338 | usb_syncmem(&hsed->dma, hsed->offs + offsetof(ohci_ed_t, ed_flags), |
3259 | sizeof(hsed->ed.ed_flags), | | 3339 | sizeof(hsed->ed.ed_flags), |
3260 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 3340 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
3261 | sed->ed.ed_nexted = hsed->ed.ed_nexted; | | 3341 | sed->ed.ed_nexted = hsed->ed.ed_nexted; |
3262 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), | | 3342 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), |
3263 | sizeof(sed->ed.ed_flags), | | 3343 | sizeof(sed->ed.ed_flags), |
3264 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3344 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3265 | hsed->next = sed; | | 3345 | hsed->next = sed; |
3266 | hsed->ed.ed_nexted = HTOO32(sed->physaddr); | | 3346 | hsed->ed.ed_nexted = HTOO32(sed->physaddr); |
3267 | usb_syncmem(&hsed->dma, hsed->offs + offsetof(ohci_ed_t, ed_flags), | | 3347 | usb_syncmem(&hsed->dma, hsed->offs + offsetof(ohci_ed_t, ed_flags), |
3268 | sizeof(hsed->ed.ed_flags), | | 3348 | sizeof(hsed->ed.ed_flags), |
3269 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3349 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3270 | splx(s); | | 3350 | mutex_exit(&sc->sc_lock); |
3271 | | | 3351 | |
3272 | for (j = 0; j < nslots; j++) | | 3352 | for (j = 0; j < nslots; j++) |
3273 | ++sc->sc_bws[(best * nslots + j) % OHCI_NO_INTRS]; | | 3353 | ++sc->sc_bws[(best * nslots + j) % OHCI_NO_INTRS]; |
3274 | opipe->u.intr.nslots = nslots; | | 3354 | opipe->u.intr.nslots = nslots; |
3275 | opipe->u.intr.pos = best; | | 3355 | opipe->u.intr.pos = best; |
3276 | | | 3356 | |
3277 | DPRINTFN(5, ("ohci_setintr: returns %p\n", opipe)); | | 3357 | DPRINTFN(5, ("ohci_setintr: returns %p\n", opipe)); |
3278 | return (USBD_NORMAL_COMPLETION); | | 3358 | return (USBD_NORMAL_COMPLETION); |
3279 | } | | 3359 | } |
3280 | | | 3360 | |
3281 | /***********************/ | | 3361 | /***********************/ |
3282 | | | 3362 | |
3283 | usbd_status | | 3363 | usbd_status |
3284 | ohci_device_isoc_transfer(usbd_xfer_handle xfer) | | 3364 | ohci_device_isoc_transfer(usbd_xfer_handle xfer) |
3285 | { | | 3365 | { |
| | | 3366 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
3286 | usbd_status err; | | 3367 | usbd_status err; |
3287 | | | 3368 | |
3288 | DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer)); | | 3369 | DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer)); |
3289 | | | 3370 | |
3290 | /* Put it on our queue, */ | | 3371 | /* Put it on our queue, */ |
| | | 3372 | mutex_enter(&sc->sc_lock); |
3291 | err = usb_insert_transfer(xfer); | | 3373 | err = usb_insert_transfer(xfer); |
| | | 3374 | mutex_exit(&sc->sc_lock); |
3292 | | | 3375 | |
3293 | /* bail out on error, */ | | 3376 | /* bail out on error, */ |
3294 | if (err && err != USBD_IN_PROGRESS) | | 3377 | if (err && err != USBD_IN_PROGRESS) |
3295 | return (err); | | 3378 | return (err); |
3296 | | | 3379 | |
3297 | /* XXX should check inuse here */ | | 3380 | /* XXX should check inuse here */ |
3298 | | | 3381 | |
3299 | /* insert into schedule, */ | | 3382 | /* insert into schedule, */ |
3300 | ohci_device_isoc_enter(xfer); | | 3383 | ohci_device_isoc_enter(xfer); |
3301 | | | 3384 | |
3302 | /* and start if the pipe wasn't running */ | | 3385 | /* and start if the pipe wasn't running */ |
3303 | if (!err) | | 3386 | if (!err) |
3304 | ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); | | 3387 | ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); |
| @@ -3307,27 +3390,26 @@ ohci_device_isoc_transfer(usbd_xfer_hand | | | @@ -3307,27 +3390,26 @@ ohci_device_isoc_transfer(usbd_xfer_hand |
3307 | } | | 3390 | } |
3308 | | | 3391 | |
3309 | void | | 3392 | void |
3310 | ohci_device_isoc_enter(usbd_xfer_handle xfer) | | 3393 | ohci_device_isoc_enter(usbd_xfer_handle xfer) |
3311 | { | | 3394 | { |
3312 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; | | 3395 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; |
3313 | usbd_device_handle dev = opipe->pipe.device; | | 3396 | usbd_device_handle dev = opipe->pipe.device; |
3314 | ohci_softc_t *sc = dev->bus->hci_private; | | 3397 | ohci_softc_t *sc = dev->bus->hci_private; |
3315 | ohci_soft_ed_t *sed = opipe->sed; | | 3398 | ohci_soft_ed_t *sed = opipe->sed; |
3316 | struct iso *iso = &opipe->u.iso; | | 3399 | struct iso *iso = &opipe->u.iso; |
3317 | ohci_soft_itd_t *sitd, *nsitd; | | 3400 | ohci_soft_itd_t *sitd, *nsitd; |
3318 | ohci_physaddr_t buf, offs, noffs, bp0; | | 3401 | ohci_physaddr_t buf, offs, noffs, bp0; |
3319 | int i, ncur, nframes; | | 3402 | int i, ncur, nframes; |
3320 | int s; | | | |
3321 | | | 3403 | |
3322 | DPRINTFN(1,("ohci_device_isoc_enter: used=%d next=%d xfer=%p " | | 3404 | DPRINTFN(1,("ohci_device_isoc_enter: used=%d next=%d xfer=%p " |
3323 | "nframes=%d\n", | | 3405 | "nframes=%d\n", |
3324 | iso->inuse, iso->next, xfer, xfer->nframes)); | | 3406 | iso->inuse, iso->next, xfer, xfer->nframes)); |
3325 | | | 3407 | |
3326 | if (sc->sc_dying) | | 3408 | if (sc->sc_dying) |
3327 | return; | | 3409 | return; |
3328 | | | 3410 | |
3329 | if (iso->next == -1) { | | 3411 | if (iso->next == -1) { |
3330 | /* Not in use yet, schedule it a few frames ahead. */ | | 3412 | /* Not in use yet, schedule it a few frames ahead. */ |
3331 | iso->next = O32TOH(sc->sc_hcca->hcca_frame_number) + 5; | | 3413 | iso->next = O32TOH(sc->sc_hcca->hcca_frame_number) + 5; |
3332 | DPRINTFN(2,("ohci_device_isoc_enter: start next=%d\n", | | 3414 | DPRINTFN(2,("ohci_device_isoc_enter: start next=%d\n", |
3333 | iso->next)); | | 3415 | iso->next)); |
| @@ -3404,153 +3486,154 @@ ohci_device_isoc_enter(usbd_xfer_handle | | | @@ -3404,153 +3486,154 @@ ohci_device_isoc_enter(usbd_xfer_handle |
3404 | xfer->actlen = offs; /* XXX pretend we did it all */ | | 3486 | xfer->actlen = offs; /* XXX pretend we did it all */ |
3405 | | | 3487 | |
3406 | xfer->status = USBD_IN_PROGRESS; | | 3488 | xfer->status = USBD_IN_PROGRESS; |
3407 | | | 3489 | |
3408 | #ifdef OHCI_DEBUG | | 3490 | #ifdef OHCI_DEBUG |
3409 | if (ohcidebug > 5) { | | 3491 | if (ohcidebug > 5) { |
3410 | DPRINTF(("ohci_device_isoc_enter: frame=%d\n", | | 3492 | DPRINTF(("ohci_device_isoc_enter: frame=%d\n", |
3411 | O32TOH(sc->sc_hcca->hcca_frame_number))); | | 3493 | O32TOH(sc->sc_hcca->hcca_frame_number))); |
3412 | ohci_dump_itds(sc, xfer->hcpriv); | | 3494 | ohci_dump_itds(sc, xfer->hcpriv); |
3413 | ohci_dump_ed(sc, sed); | | 3495 | ohci_dump_ed(sc, sed); |
3414 | } | | 3496 | } |
3415 | #endif | | 3497 | #endif |
3416 | | | 3498 | |
3417 | s = splusb(); | | 3499 | mutex_enter(&sc->sc_lock); |
3418 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | | 3500 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), |
3419 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 3501 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
3420 | sed->ed.ed_tailp = HTOO32(nsitd->physaddr); | | 3502 | sed->ed.ed_tailp = HTOO32(nsitd->physaddr); |
3421 | opipe->tail.itd = nsitd; | | 3503 | opipe->tail.itd = nsitd; |
3422 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); | | 3504 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); |
3423 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), | | 3505 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), |
3424 | sizeof(sed->ed.ed_flags), | | 3506 | sizeof(sed->ed.ed_flags), |
3425 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3507 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3426 | splx(s); | | 3508 | mutex_exit(&sc->sc_lock); |
3427 | | | 3509 | |
3428 | #ifdef OHCI_DEBUG | | 3510 | #ifdef OHCI_DEBUG |
3429 | if (ohcidebug > 5) { | | 3511 | if (ohcidebug > 5) { |
3430 | delay(150000); | | 3512 | delay(150000); |
3431 | DPRINTF(("ohci_device_isoc_enter: after frame=%d\n", | | 3513 | DPRINTF(("ohci_device_isoc_enter: after frame=%d\n", |
3432 | O32TOH(sc->sc_hcca->hcca_frame_number))); | | 3514 | O32TOH(sc->sc_hcca->hcca_frame_number))); |
3433 | ohci_dump_itds(sc, xfer->hcpriv); | | 3515 | ohci_dump_itds(sc, xfer->hcpriv); |
3434 | ohci_dump_ed(sc, sed); | | 3516 | ohci_dump_ed(sc, sed); |
3435 | } | | 3517 | } |
3436 | #endif | | 3518 | #endif |
3437 | } | | 3519 | } |
3438 | | | 3520 | |
3439 | usbd_status | | 3521 | usbd_status |
3440 | ohci_device_isoc_start(usbd_xfer_handle xfer) | | 3522 | ohci_device_isoc_start(usbd_xfer_handle xfer) |
3441 | { | | 3523 | { |
3442 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; | | 3524 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; |
3443 | ohci_softc_t *sc = opipe->pipe.device->bus->hci_private; | | 3525 | ohci_softc_t *sc = opipe->pipe.device->bus->hci_private; |
3444 | | | 3526 | |
3445 | DPRINTFN(5,("ohci_device_isoc_start: xfer=%p\n", xfer)); | | 3527 | DPRINTFN(5,("ohci_device_isoc_start: xfer=%p\n", xfer)); |
3446 | | | 3528 | |
3447 | if (sc->sc_dying) | | 3529 | mutex_enter(&sc->sc_lock); |
| | | 3530 | |
| | | 3531 | if (sc->sc_dying) { |
| | | 3532 | mutex_exit(&sc->sc_lock); |
3448 | return (USBD_IOERROR); | | 3533 | return (USBD_IOERROR); |
| | | 3534 | } |
3449 | | | 3535 | |
3450 | #ifdef DIAGNOSTIC | | 3536 | #ifdef DIAGNOSTIC |
3451 | if (xfer->status != USBD_IN_PROGRESS) | | 3537 | if (xfer->status != USBD_IN_PROGRESS) |
3452 | printf("ohci_device_isoc_start: not in progress %p\n", xfer); | | 3538 | printf("ohci_device_isoc_start: not in progress %p\n", xfer); |
3453 | #endif | | 3539 | #endif |
3454 | | | 3540 | |
3455 | /* XXX anything to do? */ | | 3541 | /* XXX anything to do? */ |
3456 | | | 3542 | |
3457 | return (USBD_IN_PROGRESS); | | 3543 | return (USBD_IN_PROGRESS); |
3458 | } | | 3544 | } |
3459 | | | 3545 | |
3460 | void | | 3546 | void |
3461 | ohci_device_isoc_abort(usbd_xfer_handle xfer) | | 3547 | ohci_device_isoc_abort(usbd_xfer_handle xfer) |
3462 | { | | 3548 | { |
3463 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; | | 3549 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; |
3464 | ohci_softc_t *sc = opipe->pipe.device->bus->hci_private; | | 3550 | ohci_softc_t *sc = opipe->pipe.device->bus->hci_private; |
3465 | ohci_soft_ed_t *sed; | | 3551 | ohci_soft_ed_t *sed; |
3466 | ohci_soft_itd_t *sitd; | | 3552 | ohci_soft_itd_t *sitd; |
3467 | int s; | | | |
3468 | | | | |
3469 | s = splusb(); | | | |
3470 | | | 3553 | |
3471 | DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p\n", xfer)); | | 3554 | DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p\n", xfer)); |
3472 | | | 3555 | |
| | | 3556 | KASSERT(mutex_owned(&sc->sc_lock)); |
| | | 3557 | |
3473 | /* Transfer is already done. */ | | 3558 | /* Transfer is already done. */ |
3474 | if (xfer->status != USBD_NOT_STARTED && | | 3559 | if (xfer->status != USBD_NOT_STARTED && |
3475 | xfer->status != USBD_IN_PROGRESS) { | | 3560 | xfer->status != USBD_IN_PROGRESS) { |
3476 | splx(s); | | | |
3477 | printf("ohci_device_isoc_abort: early return\n"); | | 3561 | printf("ohci_device_isoc_abort: early return\n"); |
3478 | return; | | 3562 | goto done; |
3479 | } | | 3563 | } |
3480 | | | 3564 | |
3481 | /* Give xfer the requested abort code. */ | | 3565 | /* Give xfer the requested abort code. */ |
3482 | xfer->status = USBD_CANCELLED; | | 3566 | xfer->status = USBD_CANCELLED; |
3483 | | | 3567 | |
3484 | sed = opipe->sed; | | 3568 | sed = opipe->sed; |
3485 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | | 3569 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), |
3486 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 3570 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
3487 | sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); /* force hardware skip */ | | 3571 | sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); /* force hardware skip */ |
3488 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), | | 3572 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), |
3489 | sizeof(sed->ed.ed_flags), | | 3573 | sizeof(sed->ed.ed_flags), |
3490 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3574 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3491 | | | 3575 | |
3492 | sitd = xfer->hcpriv; | | 3576 | sitd = xfer->hcpriv; |
3493 | #ifdef DIAGNOSTIC | | 3577 | #ifdef DIAGNOSTIC |
3494 | if (sitd == NULL) { | | 3578 | if (sitd == NULL) { |
3495 | splx(s); | | | |
3496 | printf("ohci_device_isoc_abort: hcpriv==0\n"); | | 3579 | printf("ohci_device_isoc_abort: hcpriv==0\n"); |
3497 | return; | | 3580 | goto done; |
3498 | } | | 3581 | } |
3499 | #endif | | 3582 | #endif |
3500 | for (; sitd->xfer == xfer; sitd = sitd->nextitd) { | | 3583 | for (; sitd->xfer == xfer; sitd = sitd->nextitd) { |
3501 | #ifdef DIAGNOSTIC | | 3584 | #ifdef DIAGNOSTIC |
3502 | DPRINTFN(1,("abort sets done sitd=%p\n", sitd)); | | 3585 | DPRINTFN(1,("abort sets done sitd=%p\n", sitd)); |
3503 | sitd->isdone = 1; | | 3586 | sitd->isdone = 1; |
3504 | #endif | | 3587 | #endif |
3505 | } | | 3588 | } |
3506 | | | 3589 | |
3507 | splx(s); | | 3590 | mutex_exit(&sc->sc_lock); |
3508 | | | 3591 | |
3509 | usb_delay_ms(&sc->sc_bus, OHCI_ITD_NOFFSET); | | 3592 | usb_delay_ms(&sc->sc_bus, OHCI_ITD_NOFFSET); |
3510 | | | 3593 | |
3511 | s = splusb(); | | 3594 | mutex_enter(&sc->sc_lock); |
3512 | | | 3595 | |
3513 | /* Run callback. */ | | 3596 | /* Run callback. */ |
3514 | usb_transfer_complete(xfer); | | 3597 | usb_transfer_complete(xfer); |
3515 | | | 3598 | |
3516 | sed->ed.ed_headp = HTOO32(sitd->physaddr); /* unlink TDs */ | | 3599 | sed->ed.ed_headp = HTOO32(sitd->physaddr); /* unlink TDs */ |
3517 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */ | | 3600 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */ |
3518 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | | 3601 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), |
3519 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3602 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3520 | | | 3603 | |
3521 | splx(s); | | 3604 | done: |
| | | 3605 | mutex_exit(&sc->sc_lock); |
3522 | } | | 3606 | } |
3523 | | | 3607 | |
3524 | void | | 3608 | void |
3525 | ohci_device_isoc_done(usbd_xfer_handle xfer) | | 3609 | ohci_device_isoc_done(usbd_xfer_handle xfer) |
3526 | { | | 3610 | { |
3527 | DPRINTFN(1,("ohci_device_isoc_done: xfer=%p\n", xfer)); | | 3611 | DPRINTFN(1,("ohci_device_isoc_done: xfer=%p\n", xfer)); |
3528 | } | | 3612 | } |
3529 | | | 3613 | |
3530 | usbd_status | | 3614 | usbd_status |
3531 | ohci_setup_isoc(usbd_pipe_handle pipe) | | 3615 | ohci_setup_isoc(usbd_pipe_handle pipe) |
3532 | { | | 3616 | { |
3533 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; | | 3617 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; |
3534 | ohci_softc_t *sc = pipe->device->bus->hci_private; | | 3618 | ohci_softc_t *sc = pipe->device->bus->hci_private; |
3535 | struct iso *iso = &opipe->u.iso; | | 3619 | struct iso *iso = &opipe->u.iso; |
3536 | int s; | | | |
3537 | | | 3620 | |
3538 | iso->next = -1; | | 3621 | iso->next = -1; |
3539 | iso->inuse = 0; | | 3622 | iso->inuse = 0; |
3540 | | | 3623 | |
3541 | s = splusb(); | | 3624 | mutex_enter(&sc->sc_lock); |
3542 | ohci_add_ed(sc, opipe->sed, sc->sc_isoc_head); | | 3625 | ohci_add_ed(sc, opipe->sed, sc->sc_isoc_head); |
3543 | splx(s); | | 3626 | mutex_exit(&sc->sc_lock); |
3544 | | | 3627 | |
3545 | return (USBD_NORMAL_COMPLETION); | | 3628 | return (USBD_NORMAL_COMPLETION); |
3546 | } | | 3629 | } |
3547 | | | 3630 | |
3548 | void | | 3631 | void |
3549 | ohci_device_isoc_close(usbd_pipe_handle pipe) | | 3632 | ohci_device_isoc_close(usbd_pipe_handle pipe) |
3550 | { | | 3633 | { |
3551 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; | | 3634 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; |
3552 | ohci_softc_t *sc = pipe->device->bus->hci_private; | | 3635 | ohci_softc_t *sc = pipe->device->bus->hci_private; |
3553 | | | 3636 | |
3554 | DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe)); | | 3637 | DPRINTF(("ohci_device_isoc_close: pipe=%p\n", pipe)); |
3555 | ohci_close_pipe(pipe, sc->sc_isoc_head); | | 3638 | ohci_close_pipe(pipe, sc->sc_isoc_head); |
3556 | #ifdef DIAGNOSTIC | | 3639 | #ifdef DIAGNOSTIC |