static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)

{

    XHCIState *xhci = epctx->xhci;

    XHCIStreamContext *stctx = NULL;

    XHCITransfer *xfer;

    XHCIRing *ring;

    USBEndpoint *ep = NULL;

    uint64_t mfindex;

    unsigned int count = 0;

    int length;

    int i;



    trace_usb_xhci_ep_kick(epctx->slotid, epctx->epid, streamid);

    assert(!epctx->kick_active);



    /* If the device has been detached, but the guest has not noticed this

       yet the 2 above checks will succeed, but we must NOT continue */

    if (!xhci->slots[epctx->slotid - 1].uport ||

        !xhci->slots[epctx->slotid - 1].uport->dev ||

        !xhci->slots[epctx->slotid - 1].uport->dev->attached) {

        return;

    }



    if (epctx->retry) {

        XHCITransfer *xfer = epctx->retry;



        trace_usb_xhci_xfer_retry(xfer);

        assert(xfer->running_retry);

        if (xfer->timed_xfer) {

            /* time to kick the transfer? */

            mfindex = xhci_mfindex_get(xhci);

            xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex);

            if (xfer->running_retry) {

                return;

            }

            xfer->timed_xfer = 0;

            xfer->running_retry = 1;

        }

        if (xfer->iso_xfer) {

            /* retry iso transfer */

            if (xhci_setup_packet(xfer) < 0) {

                return;

            }

            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);

            assert(xfer->packet.status != USB_RET_NAK);

            xhci_try_complete_packet(xfer);

        } else {

            /* retry nak'ed transfer */

            if (xhci_setup_packet(xfer) < 0) {

                return;

            }

            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);

            if (xfer->packet.status == USB_RET_NAK) {

                return;

            }

            xhci_try_complete_packet(xfer);

        }

        assert(!xfer->running_retry);

        if (xfer->complete) {

            xhci_ep_free_xfer(epctx->retry);

        }

        epctx->retry = NULL;

    }



    if (epctx->state == EP_HALTED) {

        DPRINTF("xhci: ep halted, not running schedule\n");

        return;

    }





    if (epctx->nr_pstreams) {

        uint32_t err;

        stctx = xhci_find_stream(epctx, streamid, &err);

        if (stctx == NULL) {

            return;

        }

        ring = &stctx->ring;

        xhci_set_ep_state(xhci, epctx, stctx, EP_RUNNING);

    } else {

        ring = &epctx->ring;

        streamid = 0;

        xhci_set_ep_state(xhci, epctx, NULL, EP_RUNNING);

    }

    assert(ring->dequeue != 0);



    epctx->kick_active++;

    while (1) {

        length = xhci_ring_chain_length(xhci, ring);

        if (length <= 0) {

            break;

        }

        xfer = xhci_ep_alloc_xfer(epctx, length);

        if (xfer == NULL) {

            break;

        }



        for (i = 0; i < length; i++) {

            TRBType type;

            type = xhci_ring_fetch(xhci, ring, &xfer->trbs[i], NULL);

            assert(type);

        }

        xfer->streamid = streamid;



        if (epctx->epid == 1) {

            xhci_fire_ctl_transfer(xhci, xfer);

        } else {

            xhci_fire_transfer(xhci, xfer, epctx);

        }

        if (xfer->complete) {

            xhci_ep_free_xfer(xfer);

            xfer = NULL;

        }



        if (epctx->state == EP_HALTED) {

            break;

        }

        if (xfer != NULL && xfer->running_retry) {

            DPRINTF("xhci: xfer nacked, stopping schedule\n");

            epctx->retry = xfer;

            break;

        }

        if (count++ > TRANSFER_LIMIT) {

            trace_usb_xhci_enforced_limit("transfers");

            break;

        }

    }

    /* update ring dequeue ptr */

    xhci_set_ep_state(xhci, epctx, stctx, epctx->state);

    epctx->kick_active--;



    ep = xhci_epid_to_usbep(epctx);

    if (ep) {

        usb_device_flush_ep_queue(ep->dev, ep);

    }

}

static void xhci_kick_epctx(XHCIEPContext *epctx, unsigned int streamid)

{

    XHCIState *xhci = epctx->xhci;

    XHCIStreamContext *stctx = NULL;

    XHCITransfer *xfer;

    XHCIRing *ring;

    USBEndpoint *ep = NULL;

    uint64_t mfindex;

    unsigned int count = 0;

    int length;

    int i;



    trace_usb_xhci_ep_kick(epctx->slotid, epctx->epid, streamid);

    assert(!epctx->kick_active);



    



    if (!xhci->slots[epctx->slotid - 1].uport ||

        !xhci->slots[epctx->slotid - 1].uport->dev ||

        !xhci->slots[epctx->slotid - 1].uport->dev->attached) {

        return;

    }



    if (epctx->retry) {

        XHCITransfer *xfer = epctx->retry;



        trace_usb_xhci_xfer_retry(xfer);

        assert(xfer->running_retry);

        if (xfer->timed_xfer) {

            

            mfindex = xhci_mfindex_get(xhci);

            xhci_check_intr_iso_kick(xhci, xfer, epctx, mfindex);

            if (xfer->running_retry) {

                return;

            }

            xfer->timed_xfer = 0;

            xfer->running_retry = 1;

        }

        if (xfer->iso_xfer) {

            

            if (xhci_setup_packet(xfer) < 0) {

                return;

            }

            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);

            assert(xfer->packet.status != USB_RET_NAK);

            xhci_try_complete_packet(xfer);

        } else {

            

            if (xhci_setup_packet(xfer) < 0) {

                return;

            }

            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);

            if (xfer->packet.status == USB_RET_NAK) {

                return;

            }

            xhci_try_complete_packet(xfer);

        }

        assert(!xfer->running_retry);

        if (xfer->complete) {

            xhci_ep_free_xfer(epctx->retry);

        }

        epctx->retry = NULL;

    }



    if (epctx->state == EP_HALTED) {

        DPRINTF("xhci: ep halted, not running schedule\n");

        return;

    }





    if (epctx->nr_pstreams) {

        uint32_t err;

        stctx = xhci_find_stream(epctx, streamid, &err);

        if (stctx == NULL) {

            return;

        }

        ring = &stctx->ring;

        xhci_set_ep_state(xhci, epctx, stctx, EP_RUNNING);

    } else {

        ring = &epctx->ring;

        streamid = 0;

        xhci_set_ep_state(xhci, epctx, NULL, EP_RUNNING);

    }

    assert(ring->dequeue != 0);



    epctx->kick_active++;

    while (1) {

        length = xhci_ring_chain_length(xhci, ring);

        if (length <= 0) {

            break;

        }

        xfer = xhci_ep_alloc_xfer(epctx, length);

        if (xfer == NULL) {

            break;

        }



        for (i = 0; i < length; i++) {

            TRBType type;

            type = xhci_ring_fetch(xhci, ring, &xfer->trbs[i], NULL);

            assert(type);

        }

        xfer->streamid = streamid;



        if (epctx->epid == 1) {

            xhci_fire_ctl_transfer(xhci, xfer);

        } else {

            xhci_fire_transfer(xhci, xfer, epctx);

        }

        if (xfer->complete) {

            xhci_ep_free_xfer(xfer);

            xfer = NULL;

        }



        if (epctx->state == EP_HALTED) {

            break;

        }

        if (xfer != NULL && xfer->running_retry) {

            DPRINTF("xhci: xfer nacked, stopping schedule\n");

            epctx->retry = xfer;

            break;

        }

        if (count++ > TRANSFER_LIMIT) {

            trace_usb_xhci_enforced_limit("transfers");

            break;

        }

    }

    

    xhci_set_ep_state(xhci, epctx, stctx, epctx->state);

    epctx->kick_active--;



    ep = xhci_epid_to_usbep(epctx);

    if (ep) {

        usb_device_flush_ep_queue(ep->dev, ep);

    }

}

    xhci_set_ep_state(xhci, epctx, stctx, epctx->state);
static void FUNC_0(XHCIEPContext *VAR_0, unsigned int VAR_1)

{

    XHCIState *xhci = VAR_0->xhci;

    XHCIStreamContext *stctx = NULL;

    XHCITransfer *xfer;

    XHCIRing *ring;

    USBEndpoint *ep = NULL;

    uint64_t mfindex;

    unsigned int VAR_2 = 0;

    int VAR_3;

    int VAR_4;



    trace_usb_xhci_ep_kick(VAR_0->slotid, VAR_0->epid, VAR_1);

    assert(!VAR_0->kick_active);



    



    if (!xhci->slots[VAR_0->slotid - 1].uport ||

        !xhci->slots[VAR_0->slotid - 1].uport->dev ||

        !xhci->slots[VAR_0->slotid - 1].uport->dev->attached) {

        return;

    }



    if (VAR_0->retry) {

        XHCITransfer *xfer = VAR_0->retry;



        trace_usb_xhci_xfer_retry(xfer);

        assert(xfer->running_retry);

        if (xfer->timed_xfer) {

            

            mfindex = xhci_mfindex_get(xhci);

            xhci_check_intr_iso_kick(xhci, xfer, VAR_0, mfindex);

            if (xfer->running_retry) {

                return;

            }

            xfer->timed_xfer = 0;

            xfer->running_retry = 1;

        }

        if (xfer->iso_xfer) {

            

            if (xhci_setup_packet(xfer) < 0) {

                return;

            }

            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);

            assert(xfer->packet.status != USB_RET_NAK);

            xhci_try_complete_packet(xfer);

        } else {

            

            if (xhci_setup_packet(xfer) < 0) {

                return;

            }

            usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);

            if (xfer->packet.status == USB_RET_NAK) {

                return;

            }

            xhci_try_complete_packet(xfer);

        }

        assert(!xfer->running_retry);

        if (xfer->complete) {

            xhci_ep_free_xfer(VAR_0->retry);

        }

        VAR_0->retry = NULL;

    }



    if (VAR_0->state == EP_HALTED) {

        DPRINTF("xhci: ep halted, not running schedule\n");

        return;

    }





    if (VAR_0->nr_pstreams) {

        uint32_t err;

        stctx = xhci_find_stream(VAR_0, VAR_1, &err);

        if (stctx == NULL) {

            return;

        }

        ring = &stctx->ring;

        xhci_set_ep_state(xhci, VAR_0, stctx, EP_RUNNING);

    } else {

        ring = &VAR_0->ring;

        VAR_1 = 0;

        xhci_set_ep_state(xhci, VAR_0, NULL, EP_RUNNING);

    }

    assert(ring->dequeue != 0);



    VAR_0->kick_active++;

    while (1) {

        VAR_3 = xhci_ring_chain_length(xhci, ring);

        if (VAR_3 <= 0) {

            break;

        }

        xfer = xhci_ep_alloc_xfer(VAR_0, VAR_3);

        if (xfer == NULL) {

            break;

        }



        for (VAR_4 = 0; VAR_4 < VAR_3; VAR_4++) {

            TRBType type;

            type = xhci_ring_fetch(xhci, ring, &xfer->trbs[VAR_4], NULL);

            assert(type);

        }

        xfer->VAR_1 = VAR_1;



        if (VAR_0->epid == 1) {

            xhci_fire_ctl_transfer(xhci, xfer);

        } else {

            xhci_fire_transfer(xhci, xfer, VAR_0);

        }

        if (xfer->complete) {

            xhci_ep_free_xfer(xfer);

            xfer = NULL;

        }



        if (VAR_0->state == EP_HALTED) {

            break;

        }

        if (xfer != NULL && xfer->running_retry) {

            DPRINTF("xhci: xfer nacked, stopping schedule\n");

            VAR_0->retry = xfer;

            break;

        }

        if (VAR_2++ > TRANSFER_LIMIT) {

            trace_usb_xhci_enforced_limit("transfers");

            break;

        }

    }

    

    xhci_set_ep_state(xhci, VAR_0, stctx, VAR_0->state);

    VAR_0->kick_active--;



    ep = xhci_epid_to_usbep(VAR_0);

    if (ep) {

        usb_device_flush_ep_queue(ep->dev, ep);

    }

}

static void FUNC_0(XHCIEPContext *VAR_0, unsigned int VAR_1)
{ XHCIState *xhci = VAR_0->xhci; XHCIStreamContext *stctx = NULL; XHCITransfer *xfer; XHCIRing *ring; USBEndpoint *ep = NULL; uint64_t mfindex; unsigned int VAR_2 = 0; int VAR_3; int VAR_4; trace_usb_xhci_ep_kick(VAR_0->slotid, VAR_0->epid, VAR_1); assert(!VAR_0->kick_active); if (!xhci->slots[VAR_0->slotid - 1].uport ||
!xhci->slots[VAR_0->slotid - 1].uport->dev ||
!xhci->slots[VAR_0->slotid - 1].uport->dev->attached) { return; } if (VAR_0->retry) { XHCITransfer *xfer = VAR_0->retry; trace_usb_xhci_xfer_retry(xfer); assert(xfer->running_retry); if (xfer->timed_xfer) { mfindex = xhci_mfindex_get(xhci); xhci_check_intr_iso_kick(xhci, xfer, VAR_0, mfindex); if (xfer->running_retry) { return; } xfer->timed_xfer = 0; xfer->running_retry = 1; } if (xfer->iso_xfer) { if (xhci_setup_packet(xfer) < 0) { return; } usb_handle_packet(xfer->packet.ep->dev, &xfer->packet); assert(xfer->packet.status != USB_RET_NAK); xhci_try_complete_packet(xfer); } else { if (xhci_setup_packet(xfer) < 0) { return; } usb_handle_packet(xfer->packet.ep->dev, &xfer->packet); if (xfer->packet.status == USB_RET_NAK) { return; } xhci_try_complete_packet(xfer); } assert(!xfer->running_retry); if (xfer->complete) { xhci_ep_free_xfer(VAR_0->retry); } VAR_0->retry = NULL; } if (VAR_0->state == EP_HALTED) { DPRINTF("xhci: ep halted, not running schedule\n"); return; } if (VAR_0->nr_pstreams) { uint32_t err; stctx = xhci_find_stream(VAR_0, VAR_1, &err); if (stctx == NULL) { return; } ring = &stctx->ring; xhci_set_ep_state(xhci, VAR_0, stctx, EP_RUNNING); } else { ring = &VAR_0->ring; VAR_1 = 0; xhci_set_ep_state(xhci, VAR_0, NULL, EP_RUNNING); } assert(ring->dequeue != 0); VAR_0->kick_active++; while (1) { VAR_3 = xhci_ring_chain_length(xhci, ring); if (VAR_3 <= 0) { break; } xfer = xhci_ep_alloc_xfer(VAR_0, VAR_3); if (xfer == NULL) { break; } for (VAR_4 = 0; VAR_4 < VAR_3; VAR_4++) { TRBType type; type = xhci_ring_fetch(xhci, ring, &xfer->trbs[VAR_4], NULL); assert(type); } xfer->VAR_1 = VAR_1; if (VAR_0->epid == 1) { xhci_fire_ctl_transfer(xhci, xfer); } else { xhci_fire_transfer(xhci, xfer, VAR_0); } if (xfer->complete) { xhci_ep_free_xfer(xfer); xfer = NULL; } if (VAR_0->state == EP_HALTED) { break; } if (xfer != NULL && xfer->running_retry) { DPRINTF("xhci: xfer nacked, stopping schedule\n"); VAR_0->retry = xfer; break; } if (VAR_2++ > TRANSFER_LIMIT) { trace_usb_xhci_enforced_limit("transfers"); break; } } xhci_set_ep_state(xhci, VAR_0, stctx, VAR_0->state); VAR_0->kick_active--; ep = xhci_epid_to_usbep(VAR_0); if (ep) { usb_device_flush_ep_queue(ep->dev, ep); } }