diff --git a/src/add-ons/kernel/busses/usb/xhci.cpp b/src/add-ons/kernel/busses/usb/xhci.cpp index cccb2dcddb..cc49b2f2b5 100644 --- a/src/add-ons/kernel/busses/usb/xhci.cpp +++ b/src/add-ons/kernel/busses/usb/xhci.cpp @@ -968,8 +968,7 @@ XHCI::CancelQueuedTransfers(Pipe *pipe, bool force) // complete, one of the queued transfers posts a completion event, so in // order to avoid a deadlock, we must unlock the endpoint. endpointLocker.Unlock(); - status_t status = StopEndpoint(false, endpoint->id + 1, - endpoint->device->slot); + status_t status = StopEndpoint(false, endpoint); endpointLocker.Lock(); // Detach the head TD from the endpoint. @@ -1776,7 +1775,7 @@ XHCI::_RemoveEndpointForPipe(Pipe *pipe) if (endpoint->id > 0) { xhci_device *device = endpoint->device; uint8 epNumber = endpoint->id + 1; - StopEndpoint(true, epNumber, device->slot); + StopEndpoint(true, endpoint); mutex_lock(&endpoint->lock); @@ -2686,14 +2685,15 @@ XHCI::EvaluateContext(uint64 inputContext, uint8 slot) status_t -XHCI::ResetEndpoint(bool preserve, uint8 endpoint, uint8 slot) +XHCI::ResetEndpoint(bool preserve, xhci_endpoint* endpoint) { TRACE("Reset Endpoint\n"); + xhci_trb trb; trb.address = 0; trb.status = 0; trb.flags = TRB_3_TYPE(TRB_TYPE_RESET_ENDPOINT) - | TRB_3_SLOT(slot) | TRB_3_ENDPOINT(endpoint); + | TRB_3_SLOT(endpoint->device->slot) | TRB_3_ENDPOINT(endpoint->id + 1); if (preserve) trb.flags |= TRB_3_PRSV_BIT; @@ -2702,14 +2702,29 @@ XHCI::ResetEndpoint(bool preserve, uint8 endpoint, uint8 slot) status_t -XHCI::StopEndpoint(bool suspend, uint8 endpoint, uint8 slot) +XHCI::StopEndpoint(bool suspend, xhci_endpoint* endpoint) { TRACE("Stop Endpoint\n"); + struct xhci_device_ctx* device_ctx = endpoint->device->device_ctx; + + // XHCI 1.2, 4.8.3 Endpoint State Diagram + // Only exit from a HALTED state is a reset which will also stop the ep + switch (ENDPOINT_0_STATE_GET(_ReadContext( + &device_ctx->endpoints[endpoint->id].dwendpoint0))) { + case ENDPOINT_STATE_HALTED: + TRACE("Detected XHCI endpoint in halted state. Calling reset."); + return ResetEndpoint(false, endpoint); + case ENDPOINT_STATE_STOPPED: + return B_OK; + default: + break; + } + xhci_trb trb; trb.address = 0; trb.status = 0; trb.flags = TRB_3_TYPE(TRB_TYPE_STOP_ENDPOINT) - | TRB_3_SLOT(slot) | TRB_3_ENDPOINT(endpoint); + | TRB_3_SLOT(endpoint->device->slot) | TRB_3_ENDPOINT(endpoint->id + 1); if (suspend) trb.flags |= TRB_3_SUSPEND_ENDPOINT_BIT; diff --git a/src/add-ons/kernel/busses/usb/xhci.h b/src/add-ons/kernel/busses/usb/xhci.h index 7098d4f272..57d0c14819 100644 --- a/src/add-ons/kernel/busses/usb/xhci.h +++ b/src/add-ons/kernel/busses/usb/xhci.h @@ -185,10 +185,8 @@ private: bool deconfigure, uint8 slot); status_t EvaluateContext(uint64 inputContext, uint8 slot); - status_t ResetEndpoint(bool preserve, uint8 endpoint, - uint8 slot); - status_t StopEndpoint(bool suspend, uint8 endpoint, - uint8 slot); + status_t ResetEndpoint(bool preserve, xhci_endpoint* endpoint); + status_t StopEndpoint(bool suspend, xhci_endpoint* endpoint); status_t SetTRDequeue(uint64 dequeue, uint16 stream, uint8 endpoint, uint8 slot); status_t ResetDevice(uint8 slot); diff --git a/src/add-ons/kernel/busses/usb/xhci_hardware.h b/src/add-ons/kernel/busses/usb/xhci_hardware.h index 24ae8df2d7..673b2af240 100644 --- a/src/add-ons/kernel/busses/usb/xhci_hardware.h +++ b/src/add-ons/kernel/busses/usb/xhci_hardware.h @@ -385,8 +385,8 @@ struct xhci_endpoint_ctx { }; -#define ENDPOINT_0_STATE(x) ((x) & 0x3) -#define ENDPOINT_0_STATE_GET(x) ((x) & 0x3) +#define ENDPOINT_0_STATE(x) ((x) & 0x7) +#define ENDPOINT_0_STATE_GET(x) ((x) & 0x7) #define ENDPOINT_0_MULT(x) (((x) & 0x3) << 8) #define ENDPOINT_0_MULT_GET(x) (((x) >> 8) & 0x3) #define ENDPOINT_0_MAXPSTREAMS(x) (((x) & 0x1F) << 10) @@ -412,6 +412,14 @@ struct xhci_endpoint_ctx { #define ENDPOINT_4_MAXESITPAYLOAD(x) (((x) & 0xFFFF) << 16) #define ENDPOINT_4_MAXESITPAYLOAD_GET(x) (((x) >> 16) & 0xFFFF) +#define ENDPOINT_STATE_DISABLED 0 +#define ENDPOINT_STATE_RUNNING 1 +#define ENDPOINT_STATE_HALTED 2 +#define ENDPOINT_STATE_STOPPED 3 +#define ENDPOINT_STATE_ERROR 4 +#define ENDPOINT_STATE_RESERVED_5 5 +#define ENDPOINT_STATE_RESERVED_6 6 +#define ENDPOINT_STATE_RESERVED_7 7 struct xhci_stream_ctx { uint64 qwstream0;