> On 28 Jan 2019, at 22:05, Yuri Benditovich <yuri.benditov...@janustech.com>
> wrote:
>
> Implement underrun/overrun events of isochronous endpoints
> according to XHCI spec (4.10.3.1)
> Guest software restarts data streaming when receives these events.
> The XHCI reports these events using interrupter assigned
> to the slot (as these events do not have TRB), so current
> commit adds the field of assigned interrupter to the
> XHCISlot structure. Guest software assigns interrupter to the
> slot on 'Address Device' and 'Evaluate Context' commands.
>
> Signed-off-by: Yuri Benditovich <yuri.benditov...@janustech.com>
Reviewed-by: Dmitry Fleytman <dmitry.fleyt...@janustech.com>
> ---
> hw/usb/hcd-xhci.c | 17 +++++++++++++++--
> hw/usb/hcd-xhci.h | 1 +
> 2 files changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
> index 1a8fd96..19c64f7 100644
> --- a/hw/usb/hcd-xhci.c
> +++ b/hw/usb/hcd-xhci.c
> @@ -1949,6 +1949,16 @@ static void xhci_kick_epctx(XHCIEPContext *epctx,
> unsigned int streamid)
> while (1) {
> length = xhci_ring_chain_length(xhci, ring);
> if (length <= 0) {
> + if (epctx->type == ET_ISO_OUT || epctx->type == ET_ISO_IN) {
> + /* 4.10.3.1 */
> + XHCIEvent ev = { ER_TRANSFER };
> + ev.ccode = epctx->type == ET_ISO_IN ?
> + CC_RING_OVERRUN : CC_RING_UNDERRUN;
> + ev.slotid = epctx->slotid;
> + ev.epid = epctx->epid;
> + ev.ptr = epctx->ring.dequeue;
> + xhci_event(xhci, &ev, xhci->slots[epctx->slotid-1].intr);
> + }
> break;
> }
> xfer = xhci_ep_alloc_xfer(epctx, length);
> @@ -2028,6 +2038,7 @@ static TRBCCode xhci_disable_slot(XHCIState *xhci,
> unsigned int slotid)
> xhci->slots[slotid-1].enabled = 0;
> xhci->slots[slotid-1].addressed = 0;
> xhci->slots[slotid-1].uport = NULL;
> + xhci->slots[slotid-1].intr = 0;
> return CC_SUCCESS;
> }
>
> @@ -2127,6 +2138,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci,
> unsigned int slotid,
> slot = &xhci->slots[slotid-1];
> slot->uport = uport;
> slot->ctx = octx;
> + slot->intr = get_field(slot_ctx[2], TRB_INTR);
>
> /* Make sure device is in USB_STATE_DEFAULT state */
> usb_device_reset(dev);
> @@ -2300,8 +2312,9 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci,
> unsigned int slotid,
>
> slot_ctx[1] &= ~0xFFFF; /* max exit latency */
> slot_ctx[1] |= islot_ctx[1] & 0xFFFF;
> - slot_ctx[2] &= ~0xFF00000; /* interrupter target */
> - slot_ctx[2] |= islot_ctx[2] & 0xFF000000;
> + /* update interrupter target field */
> + xhci->slots[slotid-1].intr = get_field(islot_ctx[2], TRB_INTR);
> + set_field(&slot_ctx[2], xhci->slots[slotid-1].intr, TRB_INTR);
>
> DPRINTF("xhci: output slot context: %08x %08x %08x %08x\n",
> slot_ctx[0], slot_ctx[1], slot_ctx[2], slot_ctx[3]);
> diff --git a/hw/usb/hcd-xhci.h b/hw/usb/hcd-xhci.h
> index fc36a4c..240caa4 100644
> --- a/hw/usb/hcd-xhci.h
> +++ b/hw/usb/hcd-xhci.h
> @@ -140,6 +140,7 @@ typedef struct XHCIPort {
> typedef struct XHCISlot {
> bool enabled;
> bool addressed;
> + uint16_t intr;
> dma_addr_t ctx;
> USBPort *uport;
> XHCIEPContext *eps[31];
> --
> 2.9.5
>