| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: ehci.c,v 1.234.2.46 2015/03/21 16:42:55 skrll Exp $ */ | | 1 | /* $NetBSD: ehci.c,v 1.234.2.47 2015/04/06 07:08:59 skrll Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2004-2012 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2004-2012 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Lennart Augustsson (lennart@augustsson.net), Charles M. Hannum, | | 8 | * by Lennart Augustsson (lennart@augustsson.net), Charles M. Hannum, |
9 | * Jeremy Morse (jeremy.morse@gmail.com), Jared D. McNeill | | 9 | * Jeremy Morse (jeremy.morse@gmail.com), Jared D. McNeill |
10 | * (jmcneill@invisible.ca) and Matthew R. Green (mrg@eterna.com.au). | | 10 | * (jmcneill@invisible.ca) and Matthew R. Green (mrg@eterna.com.au). |
11 | * | | 11 | * |
12 | * Redistribution and use in source and binary forms, with or without | | 12 | * Redistribution and use in source and binary forms, with or without |
13 | * modification, are permitted provided that the following conditions | | 13 | * modification, are permitted provided that the following conditions |
14 | * are met: | | 14 | * are met: |
| @@ -43,27 +43,27 @@ | | | @@ -43,27 +43,27 @@ |
43 | | | 43 | |
44 | /* | | 44 | /* |
45 | * TODO: | | 45 | * TODO: |
46 | * 1) hold off explorations by companion controllers until ehci has started. | | 46 | * 1) hold off explorations by companion controllers until ehci has started. |
47 | * | | 47 | * |
48 | * 2) The hub driver needs to handle and schedule the transaction translator, | | 48 | * 2) The hub driver needs to handle and schedule the transaction translator, |
49 | * to assign place in frame where different devices get to go. See chapter | | 49 | * to assign place in frame where different devices get to go. See chapter |
50 | * on hubs in USB 2.0 for details. | | 50 | * on hubs in USB 2.0 for details. |
51 | * | | 51 | * |
52 | * 3) Command failures are not recovered correctly. | | 52 | * 3) Command failures are not recovered correctly. |
53 | */ | | 53 | */ |
54 | | | 54 | |
55 | #include <sys/cdefs.h> | | 55 | #include <sys/cdefs.h> |
56 | __KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.234.2.46 2015/03/21 16:42:55 skrll Exp $"); | | 56 | __KERNEL_RCSID(0, "$NetBSD: ehci.c,v 1.234.2.47 2015/04/06 07:08:59 skrll Exp $"); |
57 | | | 57 | |
58 | #include "ohci.h" | | 58 | #include "ohci.h" |
59 | #include "uhci.h" | | 59 | #include "uhci.h" |
60 | #include "opt_usb.h" | | 60 | #include "opt_usb.h" |
61 | | | 61 | |
62 | #include <sys/param.h> | | 62 | #include <sys/param.h> |
63 | | | 63 | |
64 | #include <sys/bus.h> | | 64 | #include <sys/bus.h> |
65 | #include <sys/cpu.h> | | 65 | #include <sys/cpu.h> |
66 | #include <sys/device.h> | | 66 | #include <sys/device.h> |
67 | #include <sys/kernel.h> | | 67 | #include <sys/kernel.h> |
68 | #include <sys/kmem.h> | | 68 | #include <sys/kmem.h> |
69 | #include <sys/mutex.h> | | 69 | #include <sys/mutex.h> |
| @@ -127,37 +127,37 @@ struct ehci_pipe { | | | @@ -127,37 +127,37 @@ struct ehci_pipe { |
127 | struct usbd_pipe pipe; | | 127 | struct usbd_pipe pipe; |
128 | int nexttoggle; | | 128 | int nexttoggle; |
129 | | | 129 | |
130 | ehci_soft_qh_t *sqh; | | 130 | ehci_soft_qh_t *sqh; |
131 | union { | | 131 | union { |
132 | ehci_soft_qtd_t *qtd; | | 132 | ehci_soft_qtd_t *qtd; |
133 | /* ehci_soft_itd_t *itd; */ | | 133 | /* ehci_soft_itd_t *itd; */ |
134 | /* ehci_soft_sitd_t *sitd; */ | | 134 | /* ehci_soft_sitd_t *sitd; */ |
135 | } tail; | | 135 | } tail; |
136 | union { | | 136 | union { |
137 | /* Control pipe */ | | 137 | /* Control pipe */ |
138 | struct { | | 138 | struct { |
139 | usb_dma_t reqdma; | | 139 | usb_dma_t reqdma; |
140 | } ctl; | | 140 | } ctrl; |
141 | /* Interrupt pipe */ | | 141 | /* Interrupt pipe */ |
142 | struct { | | 142 | struct { |
143 | u_int length; | | 143 | u_int length; |
144 | } intr; | | 144 | } intr; |
145 | /* Iso pipe */ | | 145 | /* Iso pipe */ |
146 | struct { | | 146 | struct { |
147 | u_int next_frame; | | 147 | u_int next_frame; |
148 | u_int cur_xfers; | | 148 | u_int cur_xfers; |
149 | } isoc; | | 149 | } isoc; |
150 | } u; | | 150 | }; |
151 | }; | | 151 | }; |
152 | | | 152 | |
153 | Static usbd_status ehci_open(struct usbd_pipe *); | | 153 | Static usbd_status ehci_open(struct usbd_pipe *); |
154 | Static void ehci_poll(struct usbd_bus *); | | 154 | Static void ehci_poll(struct usbd_bus *); |
155 | Static void ehci_softintr(void *); | | 155 | Static void ehci_softintr(void *); |
156 | Static int ehci_intr1(ehci_softc_t *); | | 156 | Static int ehci_intr1(ehci_softc_t *); |
157 | Static void ehci_waitintr(ehci_softc_t *, struct usbd_xfer *); | | 157 | Static void ehci_waitintr(ehci_softc_t *, struct usbd_xfer *); |
158 | Static void ehci_check_intr(ehci_softc_t *, struct ehci_xfer *); | | 158 | Static void ehci_check_intr(ehci_softc_t *, struct ehci_xfer *); |
159 | Static void ehci_check_qh_intr(ehci_softc_t *, struct ehci_xfer *); | | 159 | Static void ehci_check_qh_intr(ehci_softc_t *, struct ehci_xfer *); |
160 | Static void ehci_check_itd_intr(ehci_softc_t *, struct ehci_xfer *); | | 160 | Static void ehci_check_itd_intr(ehci_softc_t *, struct ehci_xfer *); |
161 | Static void ehci_check_sitd_intr(ehci_softc_t *, struct ehci_xfer *); | | 161 | Static void ehci_check_sitd_intr(ehci_softc_t *, struct ehci_xfer *); |
162 | Static void ehci_idone(struct ehci_xfer *); | | 162 | Static void ehci_idone(struct ehci_xfer *); |
163 | Static void ehci_timeout(void *); | | 163 | Static void ehci_timeout(void *); |
| @@ -1955,27 +1955,27 @@ ehci_open(struct usbd_pipe *pipe) | | | @@ -1955,27 +1955,27 @@ ehci_open(struct usbd_pipe *pipe) |
1955 | sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL; | | 1955 | sqh->qh.qh_qtd.qtd_altnext = EHCI_NULL; |
1956 | sqh->qh.qh_qtd.qtd_status = htole32(0); | | 1956 | sqh->qh.qh_qtd.qtd_status = htole32(0); |
1957 | | | 1957 | |
1958 | usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), | | 1958 | usb_syncmem(&sqh->dma, sqh->offs, sizeof(sqh->qh), |
1959 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 1959 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
1960 | epipe->sqh = sqh; | | 1960 | epipe->sqh = sqh; |
1961 | } else { | | 1961 | } else { |
1962 | sqh = NULL; | | 1962 | sqh = NULL; |
1963 | } /*xfertype == UE_ISOC*/ | | 1963 | } /*xfertype == UE_ISOC*/ |
1964 | | | 1964 | |
1965 | switch (xfertype) { | | 1965 | switch (xfertype) { |
1966 | case UE_CONTROL: | | 1966 | case UE_CONTROL: |
1967 | err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t), | | 1967 | err = usb_allocmem(&sc->sc_bus, sizeof(usb_device_request_t), |
1968 | 0, &epipe->u.ctl.reqdma); | | 1968 | 0, &epipe->ctrl.reqdma); |
1969 | #ifdef EHCI_DEBUG | | 1969 | #ifdef EHCI_DEBUG |
1970 | if (err) | | 1970 | if (err) |
1971 | printf("ehci_open: usb_allocmem()=%d\n", err); | | 1971 | printf("ehci_open: usb_allocmem()=%d\n", err); |
1972 | #endif | | 1972 | #endif |
1973 | if (err) | | 1973 | if (err) |
1974 | goto bad; | | 1974 | goto bad; |
1975 | pipe->up_methods = &ehci_device_ctrl_methods; | | 1975 | pipe->up_methods = &ehci_device_ctrl_methods; |
1976 | mutex_enter(&sc->sc_lock); | | 1976 | mutex_enter(&sc->sc_lock); |
1977 | ehci_add_qh(sc, sqh, sc->sc_async_head); | | 1977 | ehci_add_qh(sc, sqh, sc->sc_async_head); |
1978 | mutex_exit(&sc->sc_lock); | | 1978 | mutex_exit(&sc->sc_lock); |
1979 | break; | | 1979 | break; |
1980 | case UE_BULK: | | 1980 | case UE_BULK: |
1981 | pipe->up_methods = &ehci_device_bulk_methods; | | 1981 | pipe->up_methods = &ehci_device_bulk_methods; |
| @@ -2009,28 +2009,28 @@ ehci_open(struct usbd_pipe *pipe) | | | @@ -2009,28 +2009,28 @@ ehci_open(struct usbd_pipe *pipe) |
2009 | pipe->up_methods = &ehci_device_isoc_methods; | | 2009 | pipe->up_methods = &ehci_device_isoc_methods; |
2010 | else | | 2010 | else |
2011 | pipe->up_methods = &ehci_device_fs_isoc_methods; | | 2011 | pipe->up_methods = &ehci_device_fs_isoc_methods; |
2012 | if (ed->bInterval == 0 || ed->bInterval > 16) { | | 2012 | if (ed->bInterval == 0 || ed->bInterval > 16) { |
2013 | printf("ehci: opening pipe with invalid bInterval\n"); | | 2013 | printf("ehci: opening pipe with invalid bInterval\n"); |
2014 | err = USBD_INVAL; | | 2014 | err = USBD_INVAL; |
2015 | goto bad; | | 2015 | goto bad; |
2016 | } | | 2016 | } |
2017 | if (UGETW(ed->wMaxPacketSize) == 0) { | | 2017 | if (UGETW(ed->wMaxPacketSize) == 0) { |
2018 | printf("ehci: zero length endpoint open request\n"); | | 2018 | printf("ehci: zero length endpoint open request\n"); |
2019 | err = USBD_INVAL; | | 2019 | err = USBD_INVAL; |
2020 | goto bad; | | 2020 | goto bad; |
2021 | } | | 2021 | } |
2022 | epipe->u.isoc.next_frame = 0; | | 2022 | epipe->isoc.next_frame = 0; |
2023 | epipe->u.isoc.cur_xfers = 0; | | 2023 | epipe->isoc.cur_xfers = 0; |
2024 | break; | | 2024 | break; |
2025 | default: | | 2025 | default: |
2026 | USBHIST_LOG(ehcidebug, "bad xfer type %d", xfertype, 0, 0, 0); | | 2026 | USBHIST_LOG(ehcidebug, "bad xfer type %d", xfertype, 0, 0, 0); |
2027 | err = USBD_INVAL; | | 2027 | err = USBD_INVAL; |
2028 | goto bad; | | 2028 | goto bad; |
2029 | } | | 2029 | } |
2030 | return USBD_NORMAL_COMPLETION; | | 2030 | return USBD_NORMAL_COMPLETION; |
2031 | | | 2031 | |
2032 | bad: | | 2032 | bad: |
2033 | if (sqh != NULL) | | 2033 | if (sqh != NULL) |
2034 | ehci_free_sqh(sc, sqh); | | 2034 | ehci_free_sqh(sc, sqh); |
2035 | return err; | | 2035 | return err; |
2036 | } | | 2036 | } |
| @@ -3460,27 +3460,27 @@ ehci_device_ctrl_done(struct usbd_xfer * | | | @@ -3460,27 +3460,27 @@ ehci_device_ctrl_done(struct usbd_xfer * |
3460 | int len = UGETW(req->wLength); | | 3460 | int len = UGETW(req->wLength); |
3461 | int rd = req->bmRequestType & UT_READ; | | 3461 | int rd = req->bmRequestType & UT_READ; |
3462 | | | 3462 | |
3463 | USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); | | 3463 | USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); |
3464 | | | 3464 | |
3465 | USBHIST_LOG(ehcidebug, "xfer=%p", xfer, 0, 0, 0); | | 3465 | USBHIST_LOG(ehcidebug, "xfer=%p", xfer, 0, 0, 0); |
3466 | | | 3466 | |
3467 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | | 3467 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); |
3468 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); | | 3468 | KASSERT(xfer->ux_rqflags & URQ_REQUEST); |
3469 | | | 3469 | |
3470 | if (xfer->ux_status != USBD_NOMEM && ehci_active_intr_list(ex)) { | | 3470 | if (xfer->ux_status != USBD_NOMEM && ehci_active_intr_list(ex)) { |
3471 | ehci_del_intr_list(sc, ex); /* remove from active list */ | | 3471 | ehci_del_intr_list(sc, ex); /* remove from active list */ |
3472 | ehci_free_sqtd_chain(sc, ex->ex_sqtdstart, NULL); | | 3472 | ehci_free_sqtd_chain(sc, ex->ex_sqtdstart, NULL); |
3473 | usb_syncmem(&epipe->u.ctl.reqdma, 0, sizeof(*req), | | 3473 | usb_syncmem(&epipe->ctrl.reqdma, 0, sizeof(*req), |
3474 | BUS_DMASYNC_POSTWRITE); | | 3474 | BUS_DMASYNC_POSTWRITE); |
3475 | if (len) | | 3475 | if (len) |
3476 | usb_syncmem(&xfer->ux_dmabuf, 0, len, | | 3476 | usb_syncmem(&xfer->ux_dmabuf, 0, len, |
3477 | rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); | | 3477 | rd ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); |
3478 | } | | 3478 | } |
3479 | | | 3479 | |
3480 | USBHIST_LOG(ehcidebug, "length=%d", xfer->ux_actlen, 0, 0, 0); | | 3480 | USBHIST_LOG(ehcidebug, "length=%d", xfer->ux_actlen, 0, 0, 0); |
3481 | } | | 3481 | } |
3482 | | | 3482 | |
3483 | /* Abort a device control request. */ | | 3483 | /* Abort a device control request. */ |
3484 | Static void | | 3484 | Static void |
3485 | ehci_device_ctrl_abort(struct usbd_xfer *xfer) | | 3485 | ehci_device_ctrl_abort(struct usbd_xfer *xfer) |
3486 | { | | 3486 | { |
| @@ -3567,38 +3567,38 @@ ehci_device_request(struct usbd_xfer *xf | | | @@ -3567,38 +3567,38 @@ ehci_device_request(struct usbd_xfer *xf |
3567 | &next, &end); | | 3567 | &next, &end); |
3568 | if (err) | | 3568 | if (err) |
3569 | goto bad3; | | 3569 | goto bad3; |
3570 | end->qtd.qtd_status &= htole32(~EHCI_QTD_IOC); | | 3570 | end->qtd.qtd_status &= htole32(~EHCI_QTD_IOC); |
3571 | end->nextqtd = stat; | | 3571 | end->nextqtd = stat; |
3572 | end->qtd.qtd_next = end->qtd.qtd_altnext = | | 3572 | end->qtd.qtd_next = end->qtd.qtd_altnext = |
3573 | htole32(stat->physaddr); | | 3573 | htole32(stat->physaddr); |
3574 | usb_syncmem(&end->dma, end->offs, sizeof(end->qtd), | | 3574 | usb_syncmem(&end->dma, end->offs, sizeof(end->qtd), |
3575 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3575 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3576 | } else { | | 3576 | } else { |
3577 | next = stat; | | 3577 | next = stat; |
3578 | } | | 3578 | } |
3579 | | | 3579 | |
3580 | memcpy(KERNADDR(&epipe->u.ctl.reqdma, 0), req, sizeof(*req)); | | 3580 | memcpy(KERNADDR(&epipe->ctrl.reqdma, 0), req, sizeof(*req)); |
3581 | usb_syncmem(&epipe->u.ctl.reqdma, 0, sizeof(*req), BUS_DMASYNC_PREWRITE); | | 3581 | usb_syncmem(&epipe->ctrl.reqdma, 0, sizeof(*req), BUS_DMASYNC_PREWRITE); |
3582 | | | 3582 | |
3583 | /* Clear toggle */ | | 3583 | /* Clear toggle */ |
3584 | setup->qtd.qtd_status = htole32( | | 3584 | setup->qtd.qtd_status = htole32( |
3585 | EHCI_QTD_ACTIVE | | | 3585 | EHCI_QTD_ACTIVE | |
3586 | EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) | | | 3586 | EHCI_QTD_SET_PID(EHCI_QTD_PID_SETUP) | |
3587 | EHCI_QTD_SET_CERR(3) | | | 3587 | EHCI_QTD_SET_CERR(3) | |
3588 | EHCI_QTD_SET_TOGGLE(0) | | | 3588 | EHCI_QTD_SET_TOGGLE(0) | |
3589 | EHCI_QTD_SET_BYTES(sizeof(*req)) | | 3589 | EHCI_QTD_SET_BYTES(sizeof(*req)) |
3590 | ); | | 3590 | ); |
3591 | setup->qtd.qtd_buffer[0] = htole32(DMAADDR(&epipe->u.ctl.reqdma, 0)); | | 3591 | setup->qtd.qtd_buffer[0] = htole32(DMAADDR(&epipe->ctrl.reqdma, 0)); |
3592 | setup->qtd.qtd_buffer_hi[0] = 0; | | 3592 | setup->qtd.qtd_buffer_hi[0] = 0; |
3593 | setup->nextqtd = next; | | 3593 | setup->nextqtd = next; |
3594 | setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr); | | 3594 | setup->qtd.qtd_next = setup->qtd.qtd_altnext = htole32(next->physaddr); |
3595 | setup->xfer = xfer; | | 3595 | setup->xfer = xfer; |
3596 | setup->len = sizeof(*req); | | 3596 | setup->len = sizeof(*req); |
3597 | usb_syncmem(&setup->dma, setup->offs, sizeof(setup->qtd), | | 3597 | usb_syncmem(&setup->dma, setup->offs, sizeof(setup->qtd), |
3598 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); | | 3598 | BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD); |
3599 | | | 3599 | |
3600 | stat->qtd.qtd_status = htole32( | | 3600 | stat->qtd.qtd_status = htole32( |
3601 | EHCI_QTD_ACTIVE | | | 3601 | EHCI_QTD_ACTIVE | |
3602 | EHCI_QTD_SET_PID(isread ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN) | | | 3602 | EHCI_QTD_SET_PID(isread ? EHCI_QTD_PID_OUT : EHCI_QTD_PID_IN) | |
3603 | EHCI_QTD_SET_CERR(3) | | | 3603 | EHCI_QTD_SET_CERR(3) | |
3604 | EHCI_QTD_SET_TOGGLE(1) | | | 3604 | EHCI_QTD_SET_TOGGLE(1) | |
| @@ -3904,27 +3904,27 @@ ehci_device_intr_start(struct usbd_xfer | | | @@ -3904,27 +3904,27 @@ ehci_device_intr_start(struct usbd_xfer |
3904 | | | 3904 | |
3905 | if (sc->sc_dying) | | 3905 | if (sc->sc_dying) |
3906 | return USBD_IOERROR; | | 3906 | return USBD_IOERROR; |
3907 | | | 3907 | |
3908 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); | | 3908 | KASSERT(!(xfer->ux_rqflags & URQ_REQUEST)); |
3909 | | | 3909 | |
3910 | mutex_enter(&sc->sc_lock); | | 3910 | mutex_enter(&sc->sc_lock); |
3911 | | | 3911 | |
3912 | len = xfer->ux_length; | | 3912 | len = xfer->ux_length; |
3913 | endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | | 3913 | endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; |
3914 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | | 3914 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; |
3915 | sqh = epipe->sqh; | | 3915 | sqh = epipe->sqh; |
3916 | | | 3916 | |
3917 | epipe->u.intr.length = len; | | 3917 | epipe->intr.length = len; |
3918 | | | 3918 | |
3919 | err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, &data, | | 3919 | err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, &data, |
3920 | &dataend); | | 3920 | &dataend); |
3921 | if (err) { | | 3921 | if (err) { |
3922 | USBHIST_LOG(ehcidebug, "no memory", 0, 0, 0, 0); | | 3922 | USBHIST_LOG(ehcidebug, "no memory", 0, 0, 0, 0); |
3923 | xfer->ux_status = err; | | 3923 | xfer->ux_status = err; |
3924 | usb_transfer_complete(xfer); | | 3924 | usb_transfer_complete(xfer); |
3925 | mutex_exit(&sc->sc_lock); | | 3925 | mutex_exit(&sc->sc_lock); |
3926 | return err; | | 3926 | return err; |
3927 | } | | 3927 | } |
3928 | | | 3928 | |
3929 | #ifdef EHCI_DEBUG | | 3929 | #ifdef EHCI_DEBUG |
3930 | USBHIST_LOGN(ehcidebug, 5, "--- dump start ---", 0, 0, 0, 0); | | 3930 | USBHIST_LOGN(ehcidebug, 5, "--- dump start ---", 0, 0, 0, 0); |
| @@ -4006,27 +4006,27 @@ ehci_device_intr_done(struct usbd_xfer * | | | @@ -4006,27 +4006,27 @@ ehci_device_intr_done(struct usbd_xfer * |
4006 | usbd_status err; | | 4006 | usbd_status err; |
4007 | int len, isread, endpt; | | 4007 | int len, isread, endpt; |
4008 | | | 4008 | |
4009 | USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); | | 4009 | USBHIST_FUNC(); USBHIST_CALLED(ehcidebug); |
4010 | | | 4010 | |
4011 | USBHIST_LOG(ehcidebug, "xfer=%p, actlen=%d", | | 4011 | USBHIST_LOG(ehcidebug, "xfer=%p, actlen=%d", |
4012 | xfer, xfer->ux_actlen, 0, 0); | | 4012 | xfer, xfer->ux_actlen, 0, 0); |
4013 | | | 4013 | |
4014 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); | | 4014 | KASSERT(sc->sc_bus.ub_usepolling || mutex_owned(&sc->sc_lock)); |
4015 | | | 4015 | |
4016 | if (xfer->ux_pipe->up_repeat) { | | 4016 | if (xfer->ux_pipe->up_repeat) { |
4017 | ehci_free_sqtd_chain(sc, exfer->ex_sqtdstart, NULL); | | 4017 | ehci_free_sqtd_chain(sc, exfer->ex_sqtdstart, NULL); |
4018 | | | 4018 | |
4019 | len = epipe->u.intr.length; | | 4019 | len = epipe->intr.length; |
4020 | xfer->ux_length = len; | | 4020 | xfer->ux_length = len; |
4021 | endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; | | 4021 | endpt = epipe->pipe.up_endpoint->ue_edesc->bEndpointAddress; |
4022 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; | | 4022 | isread = UE_GET_DIR(endpt) == UE_DIR_IN; |
4023 | usb_syncmem(&xfer->ux_dmabuf, 0, len, | | 4023 | usb_syncmem(&xfer->ux_dmabuf, 0, len, |
4024 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); | | 4024 | isread ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); |
4025 | sqh = epipe->sqh; | | 4025 | sqh = epipe->sqh; |
4026 | | | 4026 | |
4027 | err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, | | 4027 | err = ehci_alloc_sqtd_chain(epipe, sc, len, isread, xfer, |
4028 | &data, &dataend); | | 4028 | &data, &dataend); |
4029 | if (err) { | | 4029 | if (err) { |
4030 | USBHIST_LOG(ehcidebug, "no memory", 0, 0, 0, 0); | | 4030 | USBHIST_LOG(ehcidebug, "no memory", 0, 0, 0, 0); |
4031 | xfer->ux_status = err; | | 4031 | xfer->ux_status = err; |
4032 | return; | | 4032 | return; |
| @@ -4263,28 +4263,28 @@ ehci_device_fs_isoc_start(struct usbd_xf | | | @@ -4263,28 +4263,28 @@ ehci_device_fs_isoc_start(struct usbd_xf |
4263 | usb_syncmem(&exfer->ex_xfer.ux_dmabuf, 0, total_length, | | 4263 | usb_syncmem(&exfer->ex_xfer.ux_dmabuf, 0, total_length, |
4264 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | | 4264 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
4265 | | | 4265 | |
4266 | /* | | 4266 | /* |
4267 | * Part 2: Transfer descriptors have now been set up, now they must | | 4267 | * Part 2: Transfer descriptors have now been set up, now they must |
4268 | * be scheduled into the periodic frame list. Erk. Not wanting to | | 4268 | * be scheduled into the periodic frame list. Erk. Not wanting to |
4269 | * complicate matters, transfer is denied if the transfer spans | | 4269 | * complicate matters, transfer is denied if the transfer spans |
4270 | * more than the period frame list. | | 4270 | * more than the period frame list. |
4271 | */ | | 4271 | */ |
4272 | | | 4272 | |
4273 | mutex_enter(&sc->sc_lock); | | 4273 | mutex_enter(&sc->sc_lock); |
4274 | | | 4274 | |
4275 | /* Start inserting frames */ | | 4275 | /* Start inserting frames */ |
4276 | if (epipe->u.isoc.cur_xfers > 0) { | | 4276 | if (epipe->isoc.cur_xfers > 0) { |
4277 | frindex = epipe->u.isoc.next_frame; | | 4277 | frindex = epipe->isoc.next_frame; |
4278 | } else { | | 4278 | } else { |
4279 | frindex = EOREAD4(sc, EHCI_FRINDEX); | | 4279 | frindex = EOREAD4(sc, EHCI_FRINDEX); |
4280 | frindex = frindex >> 3; /* Erase microframe index */ | | 4280 | frindex = frindex >> 3; /* Erase microframe index */ |
4281 | frindex += 2; | | 4281 | frindex += 2; |
4282 | } | | 4282 | } |
4283 | | | 4283 | |
4284 | if (frindex >= sc->sc_flsize) | | 4284 | if (frindex >= sc->sc_flsize) |
4285 | frindex &= (sc->sc_flsize - 1); | | 4285 | frindex &= (sc->sc_flsize - 1); |
4286 | | | 4286 | |
4287 | /* Whats the frame interval? */ | | 4287 | /* Whats the frame interval? */ |
4288 | i = epipe->pipe.up_endpoint->ue_edesc->bInterval; | | 4288 | i = epipe->pipe.up_endpoint->ue_edesc->bInterval; |
4289 | | | 4289 | |
4290 | sitd = start; | | 4290 | sitd = start; |
| @@ -4322,28 +4322,28 @@ ehci_device_fs_isoc_start(struct usbd_xf | | | @@ -4322,28 +4322,28 @@ ehci_device_fs_isoc_start(struct usbd_xf |
4322 | sc->sc_softsitds[frindex] = sitd; | | 4322 | sc->sc_softsitds[frindex] = sitd; |
4323 | if (sitd->u.frame_list.next != NULL) | | 4323 | if (sitd->u.frame_list.next != NULL) |
4324 | sitd->u.frame_list.next->u.frame_list.prev = sitd; | | 4324 | sitd->u.frame_list.next->u.frame_list.prev = sitd; |
4325 | sitd->slot = frindex; | | 4325 | sitd->slot = frindex; |
4326 | sitd->u.frame_list.prev = NULL; | | 4326 | sitd->u.frame_list.prev = NULL; |
4327 | | | 4327 | |
4328 | frindex += i; | | 4328 | frindex += i; |
4329 | if (frindex >= sc->sc_flsize) | | 4329 | if (frindex >= sc->sc_flsize) |
4330 | frindex -= sc->sc_flsize; | | 4330 | frindex -= sc->sc_flsize; |
4331 | | | 4331 | |
4332 | sitd = sitd->xfer_next; | | 4332 | sitd = sitd->xfer_next; |
4333 | } | | 4333 | } |
4334 | | | 4334 | |
4335 | epipe->u.isoc.cur_xfers++; | | 4335 | epipe->isoc.cur_xfers++; |
4336 | epipe->u.isoc.next_frame = frindex; | | 4336 | epipe->isoc.next_frame = frindex; |
4337 | | | 4337 | |
4338 | exfer->ex_sitdstart = start; | | 4338 | exfer->ex_sitdstart = start; |
4339 | exfer->ex_sitdend = stop; | | 4339 | exfer->ex_sitdend = stop; |
4340 | | | 4340 | |
4341 | ehci_add_intr_list(sc, exfer); | | 4341 | ehci_add_intr_list(sc, exfer); |
4342 | xfer->ux_status = USBD_IN_PROGRESS; | | 4342 | xfer->ux_status = USBD_IN_PROGRESS; |
4343 | | | 4343 | |
4344 | mutex_exit(&sc->sc_lock); | | 4344 | mutex_exit(&sc->sc_lock); |
4345 | | | 4345 | |
4346 | if (sc->sc_bus.ub_usepolling) { | | 4346 | if (sc->sc_bus.ub_usepolling) { |
4347 | printf("Starting ehci isoc xfer with polling. Bad idea?\n"); | | 4347 | printf("Starting ehci isoc xfer with polling. Bad idea?\n"); |
4348 | ehci_waitintr(sc, xfer); | | 4348 | ehci_waitintr(sc, xfer); |
4349 | } | | 4349 | } |
| @@ -4371,27 +4371,27 @@ ehci_device_fs_isoc_close(struct usbd_pi | | | @@ -4371,27 +4371,27 @@ ehci_device_fs_isoc_close(struct usbd_pi |
4371 | Static void | | 4371 | Static void |
4372 | ehci_device_fs_isoc_done(struct usbd_xfer *xfer) | | 4372 | ehci_device_fs_isoc_done(struct usbd_xfer *xfer) |
4373 | { | | 4373 | { |
4374 | struct ehci_xfer *exfer; | | 4374 | struct ehci_xfer *exfer; |
4375 | ehci_softc_t *sc; | | 4375 | ehci_softc_t *sc; |
4376 | struct ehci_pipe *epipe; | | 4376 | struct ehci_pipe *epipe; |
4377 | | | 4377 | |
4378 | exfer = EXFER(xfer); | | 4378 | exfer = EXFER(xfer); |
4379 | sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; | | 4379 | sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; |
4380 | epipe = (struct ehci_pipe *) xfer->ux_pipe; | | 4380 | epipe = (struct ehci_pipe *) xfer->ux_pipe; |
4381 | | | 4381 | |
4382 | KASSERT(mutex_owned(&sc->sc_lock)); | | 4382 | KASSERT(mutex_owned(&sc->sc_lock)); |
4383 | | | 4383 | |
4384 | epipe->u.isoc.cur_xfers--; | | 4384 | epipe->isoc.cur_xfers--; |
4385 | if (xfer->ux_status != USBD_NOMEM && ehci_active_intr_list(exfer)) { | | 4385 | if (xfer->ux_status != USBD_NOMEM && ehci_active_intr_list(exfer)) { |
4386 | ehci_del_intr_list(sc, exfer); | | 4386 | ehci_del_intr_list(sc, exfer); |
4387 | ehci_rem_free_sitd_chain(sc, exfer); | | 4387 | ehci_rem_free_sitd_chain(sc, exfer); |
4388 | } | | 4388 | } |
4389 | | | 4389 | |
4390 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, BUS_DMASYNC_POSTWRITE | | | 4390 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, BUS_DMASYNC_POSTWRITE | |
4391 | BUS_DMASYNC_POSTREAD); | | 4391 | BUS_DMASYNC_POSTREAD); |
4392 | } | | 4392 | } |
4393 | Static usbd_status | | 4393 | Static usbd_status |
4394 | ehci_device_isoc_transfer(struct usbd_xfer *xfer) | | 4394 | ehci_device_isoc_transfer(struct usbd_xfer *xfer) |
4395 | { | | 4395 | { |
4396 | ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; | | 4396 | ehci_softc_t *sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; |
4397 | usbd_status err; | | 4397 | usbd_status err; |
| @@ -4591,28 +4591,28 @@ ehci_device_isoc_start(struct usbd_xfer | | | @@ -4591,28 +4591,28 @@ ehci_device_isoc_start(struct usbd_xfer |
4591 | usb_syncmem(&exfer->ex_xfer.ux_dmabuf, 0, total_length, | | 4591 | usb_syncmem(&exfer->ex_xfer.ux_dmabuf, 0, total_length, |
4592 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); | | 4592 | BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); |
4593 | | | 4593 | |
4594 | /* | | 4594 | /* |
4595 | * Part 2: Transfer descriptors have now been set up, now they must | | 4595 | * Part 2: Transfer descriptors have now been set up, now they must |
4596 | * be scheduled into the period frame list. Erk. Not wanting to | | 4596 | * be scheduled into the period frame list. Erk. Not wanting to |
4597 | * complicate matters, transfer is denied if the transfer spans | | 4597 | * complicate matters, transfer is denied if the transfer spans |
4598 | * more than the period frame list. | | 4598 | * more than the period frame list. |
4599 | */ | | 4599 | */ |
4600 | | | 4600 | |
4601 | mutex_enter(&sc->sc_lock); | | 4601 | mutex_enter(&sc->sc_lock); |
4602 | | | 4602 | |
4603 | /* Start inserting frames */ | | 4603 | /* Start inserting frames */ |
4604 | if (epipe->u.isoc.cur_xfers > 0) { | | 4604 | if (epipe->isoc.cur_xfers > 0) { |
4605 | frindex = epipe->u.isoc.next_frame; | | 4605 | frindex = epipe->isoc.next_frame; |
4606 | } else { | | 4606 | } else { |
4607 | frindex = EOREAD4(sc, EHCI_FRINDEX); | | 4607 | frindex = EOREAD4(sc, EHCI_FRINDEX); |
4608 | frindex = frindex >> 3; /* Erase microframe index */ | | 4608 | frindex = frindex >> 3; /* Erase microframe index */ |
4609 | frindex += 2; | | 4609 | frindex += 2; |
4610 | } | | 4610 | } |
4611 | | | 4611 | |
4612 | if (frindex >= sc->sc_flsize) | | 4612 | if (frindex >= sc->sc_flsize) |
4613 | frindex &= (sc->sc_flsize - 1); | | 4613 | frindex &= (sc->sc_flsize - 1); |
4614 | | | 4614 | |
4615 | /* What's the frame interval? */ | | 4615 | /* What's the frame interval? */ |
4616 | i = (1 << (epipe->pipe.up_endpoint->ue_edesc->bInterval - 1)); | | 4616 | i = (1 << (epipe->pipe.up_endpoint->ue_edesc->bInterval - 1)); |
4617 | if (i / USB_UFRAMES_PER_FRAME == 0) | | 4617 | if (i / USB_UFRAMES_PER_FRAME == 0) |
4618 | i = 1; | | 4618 | i = 1; |
| @@ -4651,28 +4651,28 @@ ehci_device_isoc_start(struct usbd_xfer | | | @@ -4651,28 +4651,28 @@ ehci_device_isoc_start(struct usbd_xfer |
4651 | sc->sc_softitds[frindex] = itd; | | 4651 | sc->sc_softitds[frindex] = itd; |
4652 | if (itd->u.frame_list.next != NULL) | | 4652 | if (itd->u.frame_list.next != NULL) |
4653 | itd->u.frame_list.next->u.frame_list.prev = itd; | | 4653 | itd->u.frame_list.next->u.frame_list.prev = itd; |
4654 | itd->slot = frindex; | | 4654 | itd->slot = frindex; |
4655 | itd->u.frame_list.prev = NULL; | | 4655 | itd->u.frame_list.prev = NULL; |
4656 | | | 4656 | |
4657 | frindex += i; | | 4657 | frindex += i; |
4658 | if (frindex >= sc->sc_flsize) | | 4658 | if (frindex >= sc->sc_flsize) |
4659 | frindex -= sc->sc_flsize; | | 4659 | frindex -= sc->sc_flsize; |
4660 | | | 4660 | |
4661 | itd = itd->xfer_next; | | 4661 | itd = itd->xfer_next; |
4662 | } | | 4662 | } |
4663 | | | 4663 | |
4664 | epipe->u.isoc.cur_xfers++; | | 4664 | epipe->isoc.cur_xfers++; |
4665 | epipe->u.isoc.next_frame = frindex; | | 4665 | epipe->isoc.next_frame = frindex; |
4666 | | | 4666 | |
4667 | exfer->ex_itdstart = start; | | 4667 | exfer->ex_itdstart = start; |
4668 | exfer->ex_itdend = stop; | | 4668 | exfer->ex_itdend = stop; |
4669 | | | 4669 | |
4670 | ehci_add_intr_list(sc, exfer); | | 4670 | ehci_add_intr_list(sc, exfer); |
4671 | xfer->ux_status = USBD_IN_PROGRESS; | | 4671 | xfer->ux_status = USBD_IN_PROGRESS; |
4672 | mutex_exit(&sc->sc_lock); | | 4672 | mutex_exit(&sc->sc_lock); |
4673 | | | 4673 | |
4674 | if (sc->sc_bus.ub_usepolling) { | | 4674 | if (sc->sc_bus.ub_usepolling) { |
4675 | printf("Starting ehci isoc xfer with polling. Bad idea?\n"); | | 4675 | printf("Starting ehci isoc xfer with polling. Bad idea?\n"); |
4676 | ehci_waitintr(sc, xfer); | | 4676 | ehci_waitintr(sc, xfer); |
4677 | } | | 4677 | } |
4678 | | | 4678 | |
| @@ -4699,23 +4699,23 @@ ehci_device_isoc_close(struct usbd_pipe | | | @@ -4699,23 +4699,23 @@ ehci_device_isoc_close(struct usbd_pipe |
4699 | Static void | | 4699 | Static void |
4700 | ehci_device_isoc_done(struct usbd_xfer *xfer) | | 4700 | ehci_device_isoc_done(struct usbd_xfer *xfer) |
4701 | { | | 4701 | { |
4702 | struct ehci_xfer *exfer; | | 4702 | struct ehci_xfer *exfer; |
4703 | ehci_softc_t *sc; | | 4703 | ehci_softc_t *sc; |
4704 | struct ehci_pipe *epipe; | | 4704 | struct ehci_pipe *epipe; |
4705 | | | 4705 | |
4706 | exfer = EXFER(xfer); | | 4706 | exfer = EXFER(xfer); |
4707 | sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; | | 4707 | sc = xfer->ux_pipe->up_dev->ud_bus->ub_hcpriv; |
4708 | epipe = (struct ehci_pipe *) xfer->ux_pipe; | | 4708 | epipe = (struct ehci_pipe *) xfer->ux_pipe; |
4709 | | | 4709 | |
4710 | KASSERT(mutex_owned(&sc->sc_lock)); | | 4710 | KASSERT(mutex_owned(&sc->sc_lock)); |
4711 | | | 4711 | |
4712 | epipe->u.isoc.cur_xfers--; | | 4712 | epipe->isoc.cur_xfers--; |
4713 | if (xfer->ux_status != USBD_NOMEM && ehci_active_intr_list(exfer)) { | | 4713 | if (xfer->ux_status != USBD_NOMEM && ehci_active_intr_list(exfer)) { |
4714 | ehci_del_intr_list(sc, exfer); | | 4714 | ehci_del_intr_list(sc, exfer); |
4715 | ehci_rem_free_itd_chain(sc, exfer); | | 4715 | ehci_rem_free_itd_chain(sc, exfer); |
4716 | } | | 4716 | } |
4717 | | | 4717 | |
4718 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, BUS_DMASYNC_POSTWRITE | | | 4718 | usb_syncmem(&xfer->ux_dmabuf, 0, xfer->ux_length, BUS_DMASYNC_POSTWRITE | |
4719 | BUS_DMASYNC_POSTREAD); | | 4719 | BUS_DMASYNC_POSTREAD); |
4720 | | | 4720 | |
4721 | } | | 4721 | } |