| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ohci.c,v 1.218.6.2.2.3 2011/12/08 08:52:25 mrg Exp $ */ | | 1 | /* $NetBSD: ohci.c,v 1.218.6.2.2.4 2011/12/08 09:09:30 mrg 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, 2011 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, Jared D. McNeill (jmcneill@invisible.ca) | | 10 | * Carlstedt Research & Technology, Jared D. McNeill (jmcneill@invisible.ca) |
11 | * and Matthew R. Green. | | 11 | * and Matthew R. Green. |
12 | * This code is derived from software contributed to The NetBSD Foundation | | 12 | * This code is derived from software contributed to The NetBSD Foundation |
13 | * by Charles M. Hannum. | | 13 | * by Charles M. Hannum. |
14 | * | | 14 | * |
| @@ -32,27 +32,27 @@ | | | @@ -32,27 +32,27 @@ |
32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 32 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
33 | * 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 |
34 | * POSSIBILITY OF SUCH DAMAGE. | | 34 | * POSSIBILITY OF SUCH DAMAGE. |
35 | */ | | 35 | */ |
36 | | | 36 | |
37 | /* | | 37 | /* |
38 | * USB Open Host Controller driver. | | 38 | * USB Open Host Controller driver. |
39 | * | | 39 | * |
40 | * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html | | 40 | * OHCI spec: http://www.compaq.com/productinfo/development/openhci.html |
41 | * USB spec: http://www.usb.org/developers/docs/ | | 41 | * USB spec: http://www.usb.org/developers/docs/ |
42 | */ | | 42 | */ |
43 | | | 43 | |
44 | #include <sys/cdefs.h> | | 44 | #include <sys/cdefs.h> |
45 | __KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.218.6.2.2.3 2011/12/08 08:52:25 mrg Exp $"); | | 45 | __KERNEL_RCSID(0, "$NetBSD: ohci.c,v 1.218.6.2.2.4 2011/12/08 09:09:30 mrg Exp $"); |
46 | | | 46 | |
47 | #include "opt_usb.h" | | 47 | #include "opt_usb.h" |
48 | | | 48 | |
49 | #include <sys/param.h> | | 49 | #include <sys/param.h> |
50 | #include <sys/systm.h> | | 50 | #include <sys/systm.h> |
51 | #include <sys/kmem.h> | | 51 | #include <sys/kmem.h> |
52 | #include <sys/kernel.h> | | 52 | #include <sys/kernel.h> |
53 | #include <sys/device.h> | | 53 | #include <sys/device.h> |
54 | #include <sys/select.h> | | 54 | #include <sys/select.h> |
55 | #include <sys/proc.h> | | 55 | #include <sys/proc.h> |
56 | #include <sys/queue.h> | | 56 | #include <sys/queue.h> |
57 | | | 57 | |
58 | #include <sys/bus.h> | | 58 | #include <sys/bus.h> |
| @@ -110,27 +110,28 @@ Static usbd_status ohci_alloc_std_chain( | | | @@ -110,27 +110,28 @@ Static usbd_status ohci_alloc_std_chain( |
110 | ohci_soft_td_t *, ohci_soft_td_t **); | | 110 | ohci_soft_td_t *, ohci_soft_td_t **); |
111 | | | 111 | |
112 | Static usbd_status ohci_open(usbd_pipe_handle); | | 112 | Static usbd_status ohci_open(usbd_pipe_handle); |
113 | Static void ohci_poll(struct usbd_bus *); | | 113 | Static void ohci_poll(struct usbd_bus *); |
114 | Static void ohci_softintr(void *); | | 114 | Static void ohci_softintr(void *); |
115 | Static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle); | | 115 | Static void ohci_waitintr(ohci_softc_t *, usbd_xfer_handle); |
116 | 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); | | 117 | Static void ohci_rhsc_softint(void *arg); |
118 | | | 118 | |
119 | Static usbd_status ohci_device_request(usbd_xfer_handle xfer); | | 119 | Static usbd_status ohci_device_request(usbd_xfer_handle xfer); |
120 | 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 *, |
121 | ohci_soft_ed_t *); | | 121 | ohci_soft_ed_t *); |
122 | | | 122 | |
123 | Static void ohci_rem_ed(ohci_soft_ed_t *, ohci_soft_ed_t *); | | 123 | Static void ohci_rem_ed(ohci_softc_t *, ohci_soft_ed_t *, |
| | | 124 | ohci_soft_ed_t *); |
124 | Static void ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *); | | 125 | Static void ohci_hash_add_td(ohci_softc_t *, ohci_soft_td_t *); |
125 | Static void ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *); | | 126 | Static void ohci_hash_rem_td(ohci_softc_t *, ohci_soft_td_t *); |
126 | Static ohci_soft_td_t *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t); | | 127 | Static ohci_soft_td_t *ohci_hash_find_td(ohci_softc_t *, ohci_physaddr_t); |
127 | Static void ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *); | | 128 | Static void ohci_hash_add_itd(ohci_softc_t *, ohci_soft_itd_t *); |
128 | Static void ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *); | | 129 | Static void ohci_hash_rem_itd(ohci_softc_t *, ohci_soft_itd_t *); |
129 | Static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t); | | 130 | Static ohci_soft_itd_t *ohci_hash_find_itd(ohci_softc_t *, ohci_physaddr_t); |
130 | | | 131 | |
131 | Static usbd_status ohci_setup_isoc(usbd_pipe_handle pipe); | | 132 | Static usbd_status ohci_setup_isoc(usbd_pipe_handle pipe); |
132 | Static void ohci_device_isoc_enter(usbd_xfer_handle); | | 133 | Static void ohci_device_isoc_enter(usbd_xfer_handle); |
133 | | | 134 | |
134 | Static usbd_status ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); | | 135 | Static usbd_status ohci_allocm(struct usbd_bus *, usb_dma_t *, u_int32_t); |
135 | Static void ohci_freem(struct usbd_bus *, usb_dma_t *); | | 136 | Static void ohci_freem(struct usbd_bus *, usb_dma_t *); |
136 | | | 137 | |
| @@ -261,88 +262,88 @@ struct ohci_pipe { | | | @@ -261,88 +262,88 @@ struct ohci_pipe { |
261 | u_int length; | | 262 | u_int length; |
262 | int isread; | | 263 | int isread; |
263 | } bulk; | | 264 | } bulk; |
264 | /* Iso pipe */ | | 265 | /* Iso pipe */ |
265 | struct iso { | | 266 | struct iso { |
266 | int next, inuse; | | 267 | int next, inuse; |
267 | } iso; | | 268 | } iso; |
268 | } u; | | 269 | } u; |
269 | }; | | 270 | }; |
270 | | | 271 | |
271 | #define OHCI_INTR_ENDPT 1 | | 272 | #define OHCI_INTR_ENDPT 1 |
272 | | | 273 | |
273 | Static const struct usbd_bus_methods ohci_bus_methods = { | | 274 | Static const struct usbd_bus_methods ohci_bus_methods = { |
274 | ohci_open, | | 275 | .open_pipe = ohci_open, |
275 | ohci_softintr, | | 276 | .soft_intr = ohci_softintr, |
276 | ohci_poll, | | 277 | .do_poll = ohci_poll, |
277 | ohci_allocm, | | 278 | .allocm = ohci_allocm, |
278 | ohci_freem, | | 279 | .freem = ohci_freem, |
279 | ohci_allocx, | | 280 | .allocx = ohci_allocx, |
280 | ohci_freex, | | 281 | .freex = ohci_freex, |
281 | ohci_get_locks, | | 282 | .get_locks = ohci_get_locks, |
282 | }; | | 283 | }; |
283 | | | 284 | |
284 | Static const struct usbd_pipe_methods ohci_root_ctrl_methods = { | | 285 | Static const struct usbd_pipe_methods ohci_root_ctrl_methods = { |
285 | ohci_root_ctrl_transfer, | | 286 | .transfer = ohci_root_ctrl_transfer, |
286 | ohci_root_ctrl_start, | | 287 | .start = ohci_root_ctrl_start, |
287 | ohci_root_ctrl_abort, | | 288 | .abort = ohci_root_ctrl_abort, |
288 | ohci_root_ctrl_close, | | 289 | .close = ohci_root_ctrl_close, |
289 | ohci_noop, | | 290 | .cleartoggle = ohci_noop, |
290 | ohci_root_ctrl_done, | | 291 | .done = ohci_root_ctrl_done, |
291 | }; | | 292 | }; |
292 | | | 293 | |
293 | Static const struct usbd_pipe_methods ohci_root_intr_methods = { | | 294 | Static const struct usbd_pipe_methods ohci_root_intr_methods = { |
294 | ohci_root_intr_transfer, | | 295 | .transfer = ohci_root_intr_transfer, |
295 | ohci_root_intr_start, | | 296 | .start = ohci_root_intr_start, |
296 | ohci_root_intr_abort, | | 297 | .abort = ohci_root_intr_abort, |
297 | ohci_root_intr_close, | | 298 | .close = ohci_root_intr_close, |
298 | ohci_noop, | | 299 | .cleartoggle = ohci_noop, |
299 | ohci_root_intr_done, | | 300 | .done = ohci_root_intr_done, |
300 | }; | | 301 | }; |
301 | | | 302 | |
302 | Static const struct usbd_pipe_methods ohci_device_ctrl_methods = { | | 303 | Static const struct usbd_pipe_methods ohci_device_ctrl_methods = { |
303 | ohci_device_ctrl_transfer, | | 304 | .transfer = ohci_device_ctrl_transfer, |
304 | ohci_device_ctrl_start, | | 305 | .start = ohci_device_ctrl_start, |
305 | ohci_device_ctrl_abort, | | 306 | .abort = ohci_device_ctrl_abort, |
306 | ohci_device_ctrl_close, | | 307 | .close = ohci_device_ctrl_close, |
307 | ohci_noop, | | 308 | .cleartoggle = ohci_noop, |
308 | ohci_device_ctrl_done, | | 309 | .done = ohci_device_ctrl_done, |
309 | }; | | 310 | }; |
310 | | | 311 | |
311 | Static const struct usbd_pipe_methods ohci_device_intr_methods = { | | 312 | Static const struct usbd_pipe_methods ohci_device_intr_methods = { |
312 | ohci_device_intr_transfer, | | 313 | .transfer = ohci_device_intr_transfer, |
313 | ohci_device_intr_start, | | 314 | .start = ohci_device_intr_start, |
314 | ohci_device_intr_abort, | | 315 | .abort = ohci_device_intr_abort, |
315 | ohci_device_intr_close, | | 316 | .close = ohci_device_intr_close, |
316 | ohci_device_clear_toggle, | | 317 | .cleartoggle = ohci_device_clear_toggle, |
317 | ohci_device_intr_done, | | 318 | .done = ohci_device_intr_done, |
318 | }; | | 319 | }; |
319 | | | 320 | |
320 | Static const struct usbd_pipe_methods ohci_device_bulk_methods = { | | 321 | Static const struct usbd_pipe_methods ohci_device_bulk_methods = { |
321 | ohci_device_bulk_transfer, | | 322 | .transfer = ohci_device_bulk_transfer, |
322 | ohci_device_bulk_start, | | 323 | .start = ohci_device_bulk_start, |
323 | ohci_device_bulk_abort, | | 324 | .abort = ohci_device_bulk_abort, |
324 | ohci_device_bulk_close, | | 325 | .close = ohci_device_bulk_close, |
325 | ohci_device_clear_toggle, | | 326 | .cleartoggle = ohci_device_clear_toggle, |
326 | ohci_device_bulk_done, | | 327 | .done = ohci_device_bulk_done, |
327 | }; | | 328 | }; |
328 | | | 329 | |
329 | Static const struct usbd_pipe_methods ohci_device_isoc_methods = { | | 330 | Static const struct usbd_pipe_methods ohci_device_isoc_methods = { |
330 | ohci_device_isoc_transfer, | | 331 | .transfer = ohci_device_isoc_transfer, |
331 | ohci_device_isoc_start, | | 332 | .start = ohci_device_isoc_start, |
332 | ohci_device_isoc_abort, | | 333 | .abort = ohci_device_isoc_abort, |
333 | ohci_device_isoc_close, | | 334 | .close = ohci_device_isoc_close, |
334 | ohci_noop, | | 335 | .cleartoggle = ohci_noop, |
335 | ohci_device_isoc_done, | | 336 | .done = ohci_device_isoc_done, |
336 | }; | | 337 | }; |
337 | | | 338 | |
338 | int | | 339 | int |
339 | ohci_activate(device_t self, enum devact act) | | 340 | ohci_activate(device_t self, enum devact act) |
340 | { | | 341 | { |
341 | struct ohci_softc *sc = device_private(self); | | 342 | struct ohci_softc *sc = device_private(self); |
342 | | | 343 | |
343 | switch (act) { | | 344 | switch (act) { |
344 | case DVACT_DEACTIVATE: | | 345 | case DVACT_DEACTIVATE: |
345 | sc->sc_dying = 1; | | 346 | sc->sc_dying = 1; |
346 | return 0; | | 347 | return 0; |
347 | default: | | 348 | default: |
348 | return EOPNOTSUPP; | | 349 | return EOPNOTSUPP; |
| @@ -1487,27 +1488,29 @@ ohci_softintr(void *v) | | | @@ -1487,27 +1488,29 @@ ohci_softintr(void *v) |
1487 | cv_broadcast(&sc->sc_softwake_cv); | | 1488 | cv_broadcast(&sc->sc_softwake_cv); |
1488 | } | | 1489 | } |
1489 | | | 1490 | |
1490 | sc->sc_bus.intr_context--; | | 1491 | sc->sc_bus.intr_context--; |
1491 | mutex_exit(&sc->sc_lock); | | 1492 | mutex_exit(&sc->sc_lock); |
1492 | | | 1493 | |
1493 | DPRINTFN(10,("ohci_softintr: done:\n")); | | 1494 | DPRINTFN(10,("ohci_softintr: done:\n")); |
1494 | } | | 1495 | } |
1495 | | | 1496 | |
1496 | void | | 1497 | void |
1497 | ohci_device_ctrl_done(usbd_xfer_handle xfer) | | 1498 | ohci_device_ctrl_done(usbd_xfer_handle xfer) |
1498 | { | | 1499 | { |
1499 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; | | 1500 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; |
| | | 1501 | #ifdef DIAGNOSTIC |
1500 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; | | 1502 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
| | | 1503 | #endif |
1501 | int len = UGETW(xfer->request.wLength); | | 1504 | int len = UGETW(xfer->request.wLength); |
1502 | int isread = (xfer->request.bmRequestType & UT_READ); | | 1505 | int isread = (xfer->request.bmRequestType & UT_READ); |
1503 | | | 1506 | |
1504 | DPRINTFN(10,("ohci_device_ctrl_done: xfer=%p\n", xfer)); | | 1507 | DPRINTFN(10,("ohci_device_ctrl_done: xfer=%p\n", xfer)); |
1505 | | | 1508 | |
1506 | KASSERT(mutex_owned(&sc->sc_lock)); | | 1509 | KASSERT(mutex_owned(&sc->sc_lock)); |
1507 | | | 1510 | |
1508 | #ifdef DIAGNOSTIC | | 1511 | #ifdef DIAGNOSTIC |
1509 | if (!(xfer->rqflags & URQ_REQUEST)) { | | 1512 | if (!(xfer->rqflags & URQ_REQUEST)) { |
1510 | panic("ohci_device_ctrl_done: not a request"); | | 1513 | panic("ohci_device_ctrl_done: not a request"); |
1511 | } | | 1514 | } |
1512 | #endif | | 1515 | #endif |
1513 | if (len) | | 1516 | if (len) |
| @@ -1563,27 +1566,29 @@ ohci_device_intr_done(usbd_xfer_handle x | | | @@ -1563,27 +1566,29 @@ ohci_device_intr_done(usbd_xfer_handle x |
1563 | | | 1566 | |
1564 | sed->ed.ed_tailp = HTOO32(tail->physaddr); | | 1567 | sed->ed.ed_tailp = HTOO32(tail->physaddr); |
1565 | usb_syncmem(&sed->dma, | | 1568 | usb_syncmem(&sed->dma, |
1566 | sed->offs + offsetof(ohci_ed_t, ed_tailp), | | 1569 | sed->offs + offsetof(ohci_ed_t, ed_tailp), |
1567 | sizeof(sed->ed.ed_tailp), | | 1570 | sizeof(sed->ed.ed_tailp), |
1568 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 1571 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
1569 | opipe->tail.td = tail; | | 1572 | opipe->tail.td = tail; |
1570 | } | | 1573 | } |
1571 | } | | 1574 | } |
1572 | | | 1575 | |
1573 | void | | 1576 | void |
1574 | ohci_device_bulk_done(usbd_xfer_handle xfer) | | 1577 | ohci_device_bulk_done(usbd_xfer_handle xfer) |
1575 | { | | 1578 | { |
| | | 1579 | #ifdef DIAGNOSTIC |
1576 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; | | 1580 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
| | | 1581 | #endif |
1577 | int isread = | | 1582 | int isread = |
1578 | (UE_GET_DIR(xfer->pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN); | | 1583 | (UE_GET_DIR(xfer->pipe->endpoint->edesc->bEndpointAddress) == UE_DIR_IN); |
1579 | | | 1584 | |
1580 | KASSERT(mutex_owned(&sc->sc_lock)); | | 1585 | KASSERT(mutex_owned(&sc->sc_lock)); |
1581 | | | 1586 | |
1582 | DPRINTFN(10,("ohci_device_bulk_done: xfer=%p, actlen=%d\n", | | 1587 | DPRINTFN(10,("ohci_device_bulk_done: xfer=%p, actlen=%d\n", |
1583 | xfer, xfer->actlen)); | | 1588 | xfer, xfer->actlen)); |
1584 | usb_syncmem(&xfer->dmabuf, 0, xfer->length, | | 1589 | usb_syncmem(&xfer->dmabuf, 0, xfer->length, |
1585 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); | | 1590 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); |
1586 | } | | 1591 | } |
1587 | | | 1592 | |
1588 | Static void | | 1593 | Static void |
1589 | ohci_rhsc_softint(void *arg) | | 1594 | ohci_rhsc_softint(void *arg) |
| @@ -1855,56 +1860,57 @@ ohci_device_request(usbd_xfer_handle xfe | | | @@ -1855,56 +1860,57 @@ ohci_device_request(usbd_xfer_handle xfe |
1855 | return (USBD_NORMAL_COMPLETION); | | 1860 | return (USBD_NORMAL_COMPLETION); |
1856 | | | 1861 | |
1857 | bad3: | | 1862 | bad3: |
1858 | ohci_free_std(sc, tail); | | 1863 | ohci_free_std(sc, tail); |
1859 | bad2: | | 1864 | bad2: |
1860 | ohci_free_std(sc, stat); | | 1865 | ohci_free_std(sc, stat); |
1861 | bad1: | | 1866 | bad1: |
1862 | return (err); | | 1867 | return (err); |
1863 | } | | 1868 | } |
1864 | | | 1869 | |
1865 | /* | | 1870 | /* |
1866 | * Add an ED to the schedule. Called at splusb(). | | 1871 | * Add an ED to the schedule. Called at splusb(). |
1867 | */ | | 1872 | */ |
1868 | void | | 1873 | Static void |
1869 | ohci_add_ed(ohci_softc_t *sc, ohci_soft_ed_t *sed, ohci_soft_ed_t *head) | | 1874 | ohci_add_ed(ohci_softc_t *sc, ohci_soft_ed_t *sed, ohci_soft_ed_t *head) |
1870 | { | | 1875 | { |
1871 | DPRINTFN(8,("ohci_add_ed: sed=%p head=%p\n", sed, head)); | | 1876 | DPRINTFN(8,("ohci_add_ed: sed=%p head=%p\n", sed, head)); |
1872 | | | 1877 | |
1873 | SPLUSBCHECK; | | 1878 | KASSERT(mutex_owned(&sc->sc_lock)); |
| | | 1879 | |
1874 | usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted), | | 1880 | usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted), |
1875 | sizeof(head->ed.ed_nexted), | | 1881 | sizeof(head->ed.ed_nexted), |
1876 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 1882 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
1877 | sed->next = head->next; | | 1883 | sed->next = head->next; |
1878 | sed->ed.ed_nexted = head->ed.ed_nexted; | | 1884 | sed->ed.ed_nexted = head->ed.ed_nexted; |
1879 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted), | | 1885 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted), |
1880 | sizeof(sed->ed.ed_nexted), | | 1886 | sizeof(sed->ed.ed_nexted), |
1881 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 1887 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
1882 | head->next = sed; | | 1888 | head->next = sed; |
1883 | head->ed.ed_nexted = HTOO32(sed->physaddr); | | 1889 | head->ed.ed_nexted = HTOO32(sed->physaddr); |
1884 | usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted), | | 1890 | usb_syncmem(&head->dma, head->offs + offsetof(ohci_ed_t, ed_nexted), |
1885 | sizeof(head->ed.ed_nexted), | | 1891 | sizeof(head->ed.ed_nexted), |
1886 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 1892 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
1887 | } | | 1893 | } |
1888 | | | 1894 | |
1889 | /* | | 1895 | /* |
1890 | * Remove an ED from the schedule. Called at splusb(). | | 1896 | * Remove an ED from the schedule. Called at splusb(). |
1891 | */ | | 1897 | */ |
1892 | void | | 1898 | Static void |
1893 | ohci_rem_ed(ohci_soft_ed_t *sed, ohci_soft_ed_t *head) | | 1899 | ohci_rem_ed(ohci_softc_t *sc, ohci_soft_ed_t *sed, ohci_soft_ed_t *head) |
1894 | { | | 1900 | { |
1895 | ohci_soft_ed_t *p; | | 1901 | ohci_soft_ed_t *p; |
1896 | | | 1902 | |
1897 | SPLUSBCHECK; | | 1903 | //KASSERT(mutex_owned(&sc->sc_lock)); |
1898 | | | 1904 | |
1899 | /* XXX */ | | 1905 | /* XXX */ |
1900 | for (p = head; p != NULL && p->next != sed; p = p->next) | | 1906 | for (p = head; p != NULL && p->next != sed; p = p->next) |
1901 | ; | | 1907 | ; |
1902 | if (p == NULL) | | 1908 | if (p == NULL) |
1903 | panic("ohci_rem_ed: ED not found"); | | 1909 | panic("ohci_rem_ed: ED not found"); |
1904 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted), | | 1910 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_nexted), |
1905 | sizeof(sed->ed.ed_nexted), | | 1911 | sizeof(sed->ed.ed_nexted), |
1906 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 1912 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
1907 | p->next = sed->next; | | 1913 | p->next = sed->next; |
1908 | p->ed.ed_nexted = sed->ed.ed_nexted; | | 1914 | p->ed.ed_nexted = sed->ed.ed_nexted; |
1909 | usb_syncmem(&p->dma, p->offs + offsetof(ohci_ed_t, ed_nexted), | | 1915 | usb_syncmem(&p->dma, p->offs + offsetof(ohci_ed_t, ed_nexted), |
1910 | sizeof(p->ed.ed_nexted), | | 1916 | sizeof(p->ed.ed_nexted), |
| @@ -1918,73 +1924,74 @@ ohci_rem_ed(ohci_soft_ed_t *sed, ohci_so | | | @@ -1918,73 +1924,74 @@ ohci_rem_ed(ohci_soft_ed_t *sed, ohci_so |
1918 | * and we have no simple way to translate this back to a kernel address. | | 1924 | * and we have no simple way to translate this back to a kernel address. |
1919 | * To make the translation possible (and fast) we use a hash table of | | 1925 | * To make the translation possible (and fast) we use a hash table of |
1920 | * TDs currently in the schedule. The physical address is used as the | | 1926 | * TDs currently in the schedule. The physical address is used as the |
1921 | * hash value. | | 1927 | * hash value. |
1922 | */ | | 1928 | */ |
1923 | | | 1929 | |
1924 | #define HASH(a) (((a) >> 4) % OHCI_HASH_SIZE) | | 1930 | #define HASH(a) (((a) >> 4) % OHCI_HASH_SIZE) |
1925 | /* Called at splusb() */ | | 1931 | /* Called at splusb() */ |
1926 | void | | 1932 | void |
1927 | ohci_hash_add_td(ohci_softc_t *sc, ohci_soft_td_t *std) | | 1933 | ohci_hash_add_td(ohci_softc_t *sc, ohci_soft_td_t *std) |
1928 | { | | 1934 | { |
1929 | int h = HASH(std->physaddr); | | 1935 | int h = HASH(std->physaddr); |
1930 | | | 1936 | |
1931 | SPLUSBCHECK; | | 1937 | //KASSERT(mutex_owned(&sc->sc_lock)); |
1932 | | | 1938 | |
1933 | LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext); | | 1939 | LIST_INSERT_HEAD(&sc->sc_hash_tds[h], std, hnext); |
1934 | } | | 1940 | } |
1935 | | | 1941 | |
1936 | /* Called at splusb() */ | | 1942 | /* Called at splusb() */ |
1937 | void | | 1943 | void |
1938 | ohci_hash_rem_td(ohci_softc_t *sc, ohci_soft_td_t *std) | | 1944 | ohci_hash_rem_td(ohci_softc_t *sc, ohci_soft_td_t *std) |
1939 | { | | 1945 | { |
1940 | SPLUSBCHECK; | | 1946 | |
| | | 1947 | //KASSERT(mutex_owned(&sc->sc_lock)); |
1941 | | | 1948 | |
1942 | LIST_REMOVE(std, hnext); | | 1949 | LIST_REMOVE(std, hnext); |
1943 | } | | 1950 | } |
1944 | | | 1951 | |
1945 | ohci_soft_td_t * | | 1952 | ohci_soft_td_t * |
1946 | ohci_hash_find_td(ohci_softc_t *sc, ohci_physaddr_t a) | | 1953 | ohci_hash_find_td(ohci_softc_t *sc, ohci_physaddr_t a) |
1947 | { | | 1954 | { |
1948 | int h = HASH(a); | | 1955 | int h = HASH(a); |
1949 | ohci_soft_td_t *std; | | 1956 | ohci_soft_td_t *std; |
1950 | | | 1957 | |
1951 | for (std = LIST_FIRST(&sc->sc_hash_tds[h]); | | 1958 | for (std = LIST_FIRST(&sc->sc_hash_tds[h]); |
1952 | std != NULL; | | 1959 | std != NULL; |
1953 | std = LIST_NEXT(std, hnext)) | | 1960 | std = LIST_NEXT(std, hnext)) |
1954 | if (std->physaddr == a) | | 1961 | if (std->physaddr == a) |
1955 | return (std); | | 1962 | return (std); |
1956 | return (NULL); | | 1963 | return (NULL); |
1957 | } | | 1964 | } |
1958 | | | 1965 | |
1959 | /* Called at splusb() */ | | 1966 | /* Called at splusb() */ |
1960 | void | | 1967 | void |
1961 | ohci_hash_add_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) | | 1968 | ohci_hash_add_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) |
1962 | { | | 1969 | { |
1963 | int h = HASH(sitd->physaddr); | | 1970 | int h = HASH(sitd->physaddr); |
1964 | | | 1971 | |
1965 | SPLUSBCHECK; | | 1972 | //KASSERT(mutex_owned(&sc->sc_lock)); |
1966 | | | 1973 | |
1967 | DPRINTFN(10,("ohci_hash_add_itd: sitd=%p physaddr=0x%08lx\n", | | 1974 | DPRINTFN(10,("ohci_hash_add_itd: sitd=%p physaddr=0x%08lx\n", |
1968 | sitd, (u_long)sitd->physaddr)); | | 1975 | sitd, (u_long)sitd->physaddr)); |
1969 | | | 1976 | |
1970 | LIST_INSERT_HEAD(&sc->sc_hash_itds[h], sitd, hnext); | | 1977 | LIST_INSERT_HEAD(&sc->sc_hash_itds[h], sitd, hnext); |
1971 | } | | 1978 | } |
1972 | | | 1979 | |
1973 | /* Called at splusb() */ | | 1980 | /* Called at splusb() */ |
1974 | void | | 1981 | void |
1975 | ohci_hash_rem_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) | | 1982 | ohci_hash_rem_itd(ohci_softc_t *sc, ohci_soft_itd_t *sitd) |
1976 | { | | 1983 | { |
1977 | SPLUSBCHECK; | | 1984 | //KASSERT(mutex_owned(&sc->sc_lock)); |
1978 | | | 1985 | |
1979 | DPRINTFN(10,("ohci_hash_rem_itd: sitd=%p physaddr=0x%08lx\n", | | 1986 | DPRINTFN(10,("ohci_hash_rem_itd: sitd=%p physaddr=0x%08lx\n", |
1980 | sitd, (u_long)sitd->physaddr)); | | 1987 | sitd, (u_long)sitd->physaddr)); |
1981 | | | 1988 | |
1982 | LIST_REMOVE(sitd, hnext); | | 1989 | LIST_REMOVE(sitd, hnext); |
1983 | } | | 1990 | } |
1984 | | | 1991 | |
1985 | ohci_soft_itd_t * | | 1992 | ohci_soft_itd_t * |
1986 | ohci_hash_find_itd(ohci_softc_t *sc, ohci_physaddr_t a) | | 1993 | ohci_hash_find_itd(ohci_softc_t *sc, ohci_physaddr_t a) |
1987 | { | | 1994 | { |
1988 | int h = HASH(a); | | 1995 | int h = HASH(a); |
1989 | ohci_soft_itd_t *sitd; | | 1996 | ohci_soft_itd_t *sitd; |
1990 | | | 1997 | |
| @@ -2215,70 +2222,69 @@ ohci_open(usbd_pipe_handle pipe) | | | @@ -2215,70 +2222,69 @@ ohci_open(usbd_pipe_handle pipe) |
2215 | break; | | 2222 | break; |
2216 | } | | 2223 | } |
2217 | } | | 2224 | } |
2218 | | | 2225 | |
2219 | return USBD_NORMAL_COMPLETION; | | 2226 | return USBD_NORMAL_COMPLETION; |
2220 | | | 2227 | |
2221 | bad: | | 2228 | bad: |
2222 | if (std != NULL) | | 2229 | if (std != NULL) |
2223 | ohci_free_std(sc, std); | | 2230 | ohci_free_std(sc, std); |
2224 | bad1: | | 2231 | bad1: |
2225 | if (sed != NULL) | | 2232 | if (sed != NULL) |
2226 | ohci_free_sed(sc, sed); | | 2233 | ohci_free_sed(sc, sed); |
2227 | bad0: | | 2234 | bad0: |
2228 | mutex_exit(&sc->sc_lock); | | | |
2229 | return err; | | 2235 | return err; |
2230 | | | 2236 | |
2231 | } | | 2237 | } |
2232 | | | 2238 | |
2233 | /* | | 2239 | /* |
2234 | * Close a reqular pipe. | | 2240 | * Close a reqular pipe. |
2235 | * Assumes that there are no pending transactions. | | 2241 | * Assumes that there are no pending transactions. |
2236 | */ | | 2242 | */ |
2237 | void | | 2243 | void |
2238 | ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head) | | 2244 | ohci_close_pipe(usbd_pipe_handle pipe, ohci_soft_ed_t *head) |
2239 | { | | 2245 | { |
2240 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; | | 2246 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; |
2241 | ohci_softc_t *sc = pipe->device->bus->hci_private; | | 2247 | ohci_softc_t *sc = pipe->device->bus->hci_private; |
2242 | ohci_soft_ed_t *sed = opipe->sed; | | 2248 | ohci_soft_ed_t *sed = opipe->sed; |
2243 | | | 2249 | |
2244 | // KASSERT(mutex_owned(&sc->sc_lock)); | | 2250 | KASSERT(mutex_owned(&sc->sc_lock)); |
2245 | | | 2251 | |
2246 | #ifdef DIAGNOSTIC | | 2252 | #ifdef DIAGNOSTIC |
2247 | sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); | | 2253 | sed->ed.ed_flags |= HTOO32(OHCI_ED_SKIP); |
2248 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != | | 2254 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != |
2249 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) { | | 2255 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) { |
2250 | ohci_soft_td_t *std; | | 2256 | ohci_soft_td_t *std; |
2251 | std = ohci_hash_find_td(sc, O32TOH(sed->ed.ed_headp)); | | 2257 | std = ohci_hash_find_td(sc, O32TOH(sed->ed.ed_headp)); |
2252 | printf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x " | | 2258 | printf("ohci_close_pipe: pipe not empty sed=%p hd=0x%x " |
2253 | "tl=0x%x pipe=%p, std=%p\n", sed, | | 2259 | "tl=0x%x pipe=%p, std=%p\n", sed, |
2254 | (int)O32TOH(sed->ed.ed_headp), | | 2260 | (int)O32TOH(sed->ed.ed_headp), |
2255 | (int)O32TOH(sed->ed.ed_tailp), | | 2261 | (int)O32TOH(sed->ed.ed_tailp), |
2256 | pipe, std); | | 2262 | pipe, std); |
2257 | #ifdef USB_DEBUG | | 2263 | #ifdef USB_DEBUG |
2258 | usbd_dump_pipe(&opipe->pipe); | | 2264 | usbd_dump_pipe(&opipe->pipe); |
2259 | #endif | | 2265 | #endif |
2260 | #ifdef OHCI_DEBUG | | 2266 | #ifdef OHCI_DEBUG |
2261 | ohci_dump_ed(sc, sed); | | 2267 | ohci_dump_ed(sc, sed); |
2262 | if (std) | | 2268 | if (std) |
2263 | ohci_dump_td(sc, std); | | 2269 | ohci_dump_td(sc, std); |
2264 | #endif | | 2270 | #endif |
2265 | usb_delay_ms(&sc->sc_bus, 2); | | 2271 | usb_delay_ms(&sc->sc_bus, 2); |
2266 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != | | 2272 | if ((O32TOH(sed->ed.ed_tailp) & OHCI_HEADMASK) != |
2267 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) | | 2273 | (O32TOH(sed->ed.ed_headp) & OHCI_HEADMASK)) |
2268 | printf("ohci_close_pipe: pipe still not empty\n"); | | 2274 | printf("ohci_close_pipe: pipe still not empty\n"); |
2269 | } | | 2275 | } |
2270 | #endif | | 2276 | #endif |
2271 | ohci_rem_ed(sed, head); | | 2277 | ohci_rem_ed(sc, sed, head); |
2272 | /* Make sure the host controller is not touching this ED */ | | 2278 | /* Make sure the host controller is not touching this ED */ |
2273 | usb_delay_ms(&sc->sc_bus, 1); | | 2279 | usb_delay_ms(&sc->sc_bus, 1); |
2274 | pipe->endpoint->datatoggle = | | 2280 | pipe->endpoint->datatoggle = |
2275 | (O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0; | | 2281 | (O32TOH(sed->ed.ed_headp) & OHCI_TOGGLECARRY) ? 1 : 0; |
2276 | ohci_free_sed(sc, opipe->sed); | | 2282 | ohci_free_sed(sc, opipe->sed); |
2277 | } | | 2283 | } |
2278 | | | 2284 | |
2279 | /* | | 2285 | /* |
2280 | * Abort a device request. | | 2286 | * Abort a device request. |
2281 | * If this routine is called at splusb() it guarantees that the request | | 2287 | * If this routine is called at splusb() it guarantees that the request |
2282 | * will be removed from the hardware scheduling and that the callback | | 2288 | * will be removed from the hardware scheduling and that the callback |
2283 | * for it will be called with USBD_CANCELLED status. | | 2289 | * for it will be called with USBD_CANCELLED status. |
2284 | * It's impossible to guarantee that the requested transfer will not | | 2290 | * It's impossible to guarantee that the requested transfer will not |
| @@ -3349,35 +3355,35 @@ ohci_device_setintr(ohci_softc_t *sc, st | | | @@ -3349,35 +3355,35 @@ ohci_device_setintr(ohci_softc_t *sc, st |
3349 | ++sc->sc_bws[(best * nslots + j) % OHCI_NO_INTRS]; | | 3355 | ++sc->sc_bws[(best * nslots + j) % OHCI_NO_INTRS]; |
3350 | opipe->u.intr.nslots = nslots; | | 3356 | opipe->u.intr.nslots = nslots; |
3351 | opipe->u.intr.pos = best; | | 3357 | opipe->u.intr.pos = best; |
3352 | | | 3358 | |
3353 | DPRINTFN(5, ("ohci_setintr: returns %p\n", opipe)); | | 3359 | DPRINTFN(5, ("ohci_setintr: returns %p\n", opipe)); |
3354 | return (USBD_NORMAL_COMPLETION); | | 3360 | return (USBD_NORMAL_COMPLETION); |
3355 | } | | 3361 | } |
3356 | | | 3362 | |
3357 | /***********************/ | | 3363 | /***********************/ |
3358 | | | 3364 | |
3359 | usbd_status | | 3365 | usbd_status |
3360 | ohci_device_isoc_transfer(usbd_xfer_handle xfer) | | 3366 | ohci_device_isoc_transfer(usbd_xfer_handle xfer) |
3361 | { | | 3367 | { |
3362 | //ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; | | 3368 | ohci_softc_t *sc = xfer->pipe->device->bus->hci_private; |
3363 | usbd_status err; | | 3369 | usbd_status err; |
3364 | | | 3370 | |
3365 | DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer)); | | 3371 | DPRINTFN(5,("ohci_device_isoc_transfer: xfer=%p\n", xfer)); |
3366 | | | 3372 | |
3367 | /* Put it on our queue, */ | | 3373 | /* Put it on our queue, */ |
3368 | //mutex_enter(&sc->sc_lock); | | 3374 | mutex_enter(&sc->sc_lock); |
3369 | err = usb_insert_transfer(xfer); | | 3375 | err = usb_insert_transfer(xfer); |
3370 | //mutex_exit(&sc->sc_lock); | | 3376 | mutex_exit(&sc->sc_lock); |
3371 | | | 3377 | |
3372 | /* bail out on error, */ | | 3378 | /* bail out on error, */ |
3373 | if (err && err != USBD_IN_PROGRESS) | | 3379 | if (err && err != USBD_IN_PROGRESS) |
3374 | return (err); | | 3380 | return (err); |
3375 | | | 3381 | |
3376 | /* XXX should check inuse here */ | | 3382 | /* XXX should check inuse here */ |
3377 | | | 3383 | |
3378 | /* insert into schedule, */ | | 3384 | /* insert into schedule, */ |
3379 | ohci_device_isoc_enter(xfer); | | 3385 | ohci_device_isoc_enter(xfer); |
3380 | | | 3386 | |
3381 | /* and start if the pipe wasn't running */ | | 3387 | /* and start if the pipe wasn't running */ |
3382 | if (!err) | | 3388 | if (!err) |
3383 | ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); | | 3389 | ohci_device_isoc_start(SIMPLEQ_FIRST(&xfer->pipe->queue)); |
| @@ -3482,36 +3488,36 @@ ohci_device_isoc_enter(usbd_xfer_handle | | | @@ -3482,36 +3488,36 @@ ohci_device_isoc_enter(usbd_xfer_handle |
3482 | xfer->actlen = offs; /* XXX pretend we did it all */ | | 3488 | xfer->actlen = offs; /* XXX pretend we did it all */ |
3483 | | | 3489 | |
3484 | xfer->status = USBD_IN_PROGRESS; | | 3490 | xfer->status = USBD_IN_PROGRESS; |
3485 | | | 3491 | |
3486 | #ifdef OHCI_DEBUG | | 3492 | #ifdef OHCI_DEBUG |
3487 | if (ohcidebug > 5) { | | 3493 | if (ohcidebug > 5) { |
3488 | DPRINTF(("ohci_device_isoc_enter: frame=%d\n", | | 3494 | DPRINTF(("ohci_device_isoc_enter: frame=%d\n", |
3489 | O32TOH(sc->sc_hcca->hcca_frame_number))); | | 3495 | O32TOH(sc->sc_hcca->hcca_frame_number))); |
3490 | ohci_dump_itds(sc, xfer->hcpriv); | | 3496 | ohci_dump_itds(sc, xfer->hcpriv); |
3491 | ohci_dump_ed(sc, sed); | | 3497 | ohci_dump_ed(sc, sed); |
3492 | } | | 3498 | } |
3493 | #endif | | 3499 | #endif |
3494 | | | 3500 | |
3495 | //mutex_enter(&sc->sc_lock); | | 3501 | mutex_enter(&sc->sc_lock); |
3496 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | | 3502 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), |
3497 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); | | 3503 | BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD); |
3498 | sed->ed.ed_tailp = HTOO32(nsitd->physaddr); | | 3504 | sed->ed.ed_tailp = HTOO32(nsitd->physaddr); |
3499 | opipe->tail.itd = nsitd; | | 3505 | opipe->tail.itd = nsitd; |
3500 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); | | 3506 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); |
3501 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), | | 3507 | usb_syncmem(&sed->dma, sed->offs + offsetof(ohci_ed_t, ed_flags), |
3502 | sizeof(sed->ed.ed_flags), | | 3508 | sizeof(sed->ed.ed_flags), |
3503 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3509 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3504 | //mutex_exit(&sc->sc_lock); | | 3510 | mutex_exit(&sc->sc_lock); |
3505 | | | 3511 | |
3506 | #ifdef OHCI_DEBUG | | 3512 | #ifdef OHCI_DEBUG |
3507 | if (ohcidebug > 5) { | | 3513 | if (ohcidebug > 5) { |
3508 | delay(150000); | | 3514 | delay(150000); |
3509 | DPRINTF(("ohci_device_isoc_enter: after frame=%d\n", | | 3515 | DPRINTF(("ohci_device_isoc_enter: after frame=%d\n", |
3510 | O32TOH(sc->sc_hcca->hcca_frame_number))); | | 3516 | O32TOH(sc->sc_hcca->hcca_frame_number))); |
3511 | ohci_dump_itds(sc, xfer->hcpriv); | | 3517 | ohci_dump_itds(sc, xfer->hcpriv); |
3512 | ohci_dump_ed(sc, sed); | | 3518 | ohci_dump_ed(sc, sed); |
3513 | } | | 3519 | } |
3514 | #endif | | 3520 | #endif |
3515 | } | | 3521 | } |
3516 | | | 3522 | |
3517 | usbd_status | | 3523 | usbd_status |
| @@ -3539,27 +3545,27 @@ ohci_device_isoc_start(usbd_xfer_handle | | | @@ -3539,27 +3545,27 @@ ohci_device_isoc_start(usbd_xfer_handle |
3539 | mutex_exit(&sc->sc_lock); | | 3545 | mutex_exit(&sc->sc_lock); |
3540 | | | 3546 | |
3541 | return (USBD_IN_PROGRESS); | | 3547 | return (USBD_IN_PROGRESS); |
3542 | } | | 3548 | } |
3543 | | | 3549 | |
3544 | void | | 3550 | void |
3545 | ohci_device_isoc_abort(usbd_xfer_handle xfer) | | 3551 | ohci_device_isoc_abort(usbd_xfer_handle xfer) |
3546 | { | | 3552 | { |
3547 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; | | 3553 | struct ohci_pipe *opipe = (struct ohci_pipe *)xfer->pipe; |
3548 | ohci_softc_t *sc = opipe->pipe.device->bus->hci_private; | | 3554 | ohci_softc_t *sc = opipe->pipe.device->bus->hci_private; |
3549 | ohci_soft_ed_t *sed; | | 3555 | ohci_soft_ed_t *sed; |
3550 | ohci_soft_itd_t *sitd; | | 3556 | ohci_soft_itd_t *sitd; |
3551 | | | 3557 | |
3552 | DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p\n", xfer)); | | 3558 | DPRINTFN(1,("ohci_device_isoc_abort: xfer=%p lock=%p\n", xfer, &sc->sc_lock)); |
3553 | | | 3559 | |
3554 | mutex_enter(&sc->sc_lock); | | 3560 | mutex_enter(&sc->sc_lock); |
3555 | | | 3561 | |
3556 | /* Transfer is already done. */ | | 3562 | /* Transfer is already done. */ |
3557 | if (xfer->status != USBD_NOT_STARTED && | | 3563 | if (xfer->status != USBD_NOT_STARTED && |
3558 | xfer->status != USBD_IN_PROGRESS) { | | 3564 | xfer->status != USBD_IN_PROGRESS) { |
3559 | printf("ohci_device_isoc_abort: early return\n"); | | 3565 | printf("ohci_device_isoc_abort: early return\n"); |
3560 | goto done; | | 3566 | goto done; |
3561 | } | | 3567 | } |
3562 | | | 3568 | |
3563 | /* Give xfer the requested abort code. */ | | 3569 | /* Give xfer the requested abort code. */ |
3564 | xfer->status = USBD_CANCELLED; | | 3570 | xfer->status = USBD_CANCELLED; |
3565 | | | 3571 | |
| @@ -3589,27 +3595,27 @@ ohci_device_isoc_abort(usbd_xfer_handle | | | @@ -3589,27 +3595,27 @@ ohci_device_isoc_abort(usbd_xfer_handle |
3589 | | | 3595 | |
3590 | usb_delay_ms(&sc->sc_bus, OHCI_ITD_NOFFSET); | | 3596 | usb_delay_ms(&sc->sc_bus, OHCI_ITD_NOFFSET); |
3591 | | | 3597 | |
3592 | mutex_enter(&sc->sc_lock); | | 3598 | mutex_enter(&sc->sc_lock); |
3593 | | | 3599 | |
3594 | /* Run callback. */ | | 3600 | /* Run callback. */ |
3595 | usb_transfer_complete(xfer); | | 3601 | usb_transfer_complete(xfer); |
3596 | | | 3602 | |
3597 | sed->ed.ed_headp = HTOO32(sitd->physaddr); /* unlink TDs */ | | 3603 | sed->ed.ed_headp = HTOO32(sitd->physaddr); /* unlink TDs */ |
3598 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */ | | 3604 | sed->ed.ed_flags &= HTOO32(~OHCI_ED_SKIP); /* remove hardware skip */ |
3599 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), | | 3605 | usb_syncmem(&sed->dma, sed->offs, sizeof(sed->ed), |
3600 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3606 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3601 | | | 3607 | |
3602 | done: ; | | 3608 | done: |
3603 | mutex_exit(&sc->sc_lock); | | 3609 | mutex_exit(&sc->sc_lock); |
3604 | } | | 3610 | } |
3605 | | | 3611 | |
3606 | void | | 3612 | void |
3607 | ohci_device_isoc_done(usbd_xfer_handle xfer) | | 3613 | ohci_device_isoc_done(usbd_xfer_handle xfer) |
3608 | { | | 3614 | { |
3609 | DPRINTFN(1,("ohci_device_isoc_done: xfer=%p\n", xfer)); | | 3615 | DPRINTFN(1,("ohci_device_isoc_done: xfer=%p\n", xfer)); |
3610 | } | | 3616 | } |
3611 | | | 3617 | |
3612 | usbd_status | | 3618 | usbd_status |
3613 | ohci_setup_isoc(usbd_pipe_handle pipe) | | 3619 | ohci_setup_isoc(usbd_pipe_handle pipe) |
3614 | { | | 3620 | { |
3615 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; | | 3621 | struct ohci_pipe *opipe = (struct ohci_pipe *)pipe; |