static int uhci_handle_td(UHCIState *s, UHCIQueue *q,

                          UHCI_TD *td, uint32_t td_addr, uint32_t *int_mask)

{

    UHCIAsync *async;

    int len = 0, max_len;

    bool spd;

    bool queuing = (q != NULL);

    uint8_t pid = td->token & 0xff;



    /* Is active ? */

    if (!(td->ctrl & TD_CTRL_ACTIVE)) {

        /*

         * ehci11d spec page 22: "Even if the Active bit in the TD is already

         * cleared when the TD is fetched ... an IOC interrupt is generated"

         */

        if (td->ctrl & TD_CTRL_IOC) {

                *int_mask |= 0x01;

        }

        return TD_RESULT_NEXT_QH;

    }



    async = uhci_async_find_td(s, td_addr, td);

    if (async) {

        /* Already submitted */

        async->queue->valid = 32;



        if (!async->done)

            return TD_RESULT_ASYNC_CONT;

        if (queuing) {

            /* we are busy filling the queue, we are not prepared

               to consume completed packages then, just leave them

               in async state */

            return TD_RESULT_ASYNC_CONT;

        }



        uhci_async_unlink(async);

        goto done;

    }



    /* Allocate new packet */

    if (q == NULL) {

        USBDevice *dev = uhci_find_device(s, (td->token >> 8) & 0x7f);

        USBEndpoint *ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);

        q = uhci_queue_get(s, td, ep);

    }

    async = uhci_async_alloc(q, td_addr);



    /* valid needs to be large enough to handle 10 frame delay

     * for initial isochronous requests

     */

    async->queue->valid = 32;



    max_len = ((td->token >> 21) + 1) & 0x7ff;

    spd = (pid == USB_TOKEN_IN && (td->ctrl & TD_CTRL_SPD) != 0);

    usb_packet_setup(&async->packet, pid, q->ep, td_addr, spd,

                     (td->ctrl & TD_CTRL_IOC) != 0);

    qemu_sglist_add(&async->sgl, td->buffer, max_len);

    usb_packet_map(&async->packet, &async->sgl);



    switch(pid) {

    case USB_TOKEN_OUT:

    case USB_TOKEN_SETUP:

        len = usb_handle_packet(q->ep->dev, &async->packet);

        if (len >= 0)

            len = max_len;

        break;



    case USB_TOKEN_IN:

        len = usb_handle_packet(q->ep->dev, &async->packet);

        break;



    default:

        /* invalid pid : frame interrupted */

        usb_packet_unmap(&async->packet, &async->sgl);

        uhci_async_free(async);

        s->status |= UHCI_STS_HCPERR;

        uhci_update_irq(s);

        return TD_RESULT_STOP_FRAME;

    }

 

    if (len == USB_RET_ASYNC) {

        uhci_async_link(async);

        if (!queuing) {

            uhci_queue_fill(q, td);

        }

        return TD_RESULT_ASYNC_START;

    }



    async->packet.result = len;



done:

    len = uhci_complete_td(s, td, async, int_mask);

    usb_packet_unmap(&async->packet, &async->sgl);

    uhci_async_free(async);

    return len;

}

static int uhci_handle_td(UHCIState *s, UHCIQueue *q,

                          UHCI_TD *td, uint32_t td_addr, uint32_t *int_mask)

{

    UHCIAsync *async;

    int len = 0, max_len;

    bool spd;

    bool queuing = (q != NULL);

    uint8_t pid = td->token & 0xff;



    

    if (!(td->ctrl & TD_CTRL_ACTIVE)) {

        







        if (td->ctrl & TD_CTRL_IOC) {

                *int_mask |= 0x01;

        }

        return TD_RESULT_NEXT_QH;

    }



    async = uhci_async_find_td(s, td_addr, td);

    if (async) {

        

        async->queue->valid = 32;



        if (!async->done)

            return TD_RESULT_ASYNC_CONT;

        if (queuing) {

            





            return TD_RESULT_ASYNC_CONT;

        }



        uhci_async_unlink(async);

        goto done;

    }



    

    if (q == NULL) {

        USBDevice *dev = uhci_find_device(s, (td->token >> 8) & 0x7f);

        USBEndpoint *ep = usb_ep_get(dev, pid, (td->token >> 15) & 0xf);

        q = uhci_queue_get(s, td, ep);

    }

    async = uhci_async_alloc(q, td_addr);



    





    async->queue->valid = 32;



    max_len = ((td->token >> 21) + 1) & 0x7ff;

    spd = (pid == USB_TOKEN_IN && (td->ctrl & TD_CTRL_SPD) != 0);

    usb_packet_setup(&async->packet, pid, q->ep, td_addr, spd,

                     (td->ctrl & TD_CTRL_IOC) != 0);

    qemu_sglist_add(&async->sgl, td->buffer, max_len);

    usb_packet_map(&async->packet, &async->sgl);



    switch(pid) {

    case USB_TOKEN_OUT:

    case USB_TOKEN_SETUP:

        len = usb_handle_packet(q->ep->dev, &async->packet);

        if (len >= 0)

            len = max_len;

        break;



    case USB_TOKEN_IN:

        len = usb_handle_packet(q->ep->dev, &async->packet);

        break;



    default:

        

        usb_packet_unmap(&async->packet, &async->sgl);

        uhci_async_free(async);

        s->status |= UHCI_STS_HCPERR;

        uhci_update_irq(s);

        return TD_RESULT_STOP_FRAME;

    }

 

    if (len == USB_RET_ASYNC) {

        uhci_async_link(async);

        if (!queuing) {

            uhci_queue_fill(q, td);

        }

        return TD_RESULT_ASYNC_START;

    }



    async->packet.result = len;



done:

    len = uhci_complete_td(s, td, async, int_mask);

    usb_packet_unmap(&async->packet, &async->sgl);

    uhci_async_free(async);

    return len;

}

static int uhci_handle_td(UHCIState *s, UHCIQueue *q,         q = uhci_queue_get(s, td, ep);
static int FUNC_0(UHCIState *VAR_0, UHCIQueue *VAR_1,

                          UHCI_TD *VAR_2, uint32_t VAR_3, uint32_t *VAR_4)

{

    UHCIAsync *async;

    int VAR_5 = 0, VAR_6;

    bool spd;

    bool queuing = (VAR_1 != NULL);

    uint8_t pid = VAR_2->token & 0xff;



    

    if (!(VAR_2->ctrl & TD_CTRL_ACTIVE)) {

        







        if (VAR_2->ctrl & TD_CTRL_IOC) {

                *VAR_4 |= 0x01;

        }

        return TD_RESULT_NEXT_QH;

    }



    async = uhci_async_find_td(VAR_0, VAR_3, VAR_2);

    if (async) {

        

        async->queue->valid = 32;



        if (!async->done)

            return TD_RESULT_ASYNC_CONT;

        if (queuing) {

            





            return TD_RESULT_ASYNC_CONT;

        }



        uhci_async_unlink(async);

        goto done;

    }



    

    if (VAR_1 == NULL) {

        USBDevice *dev = uhci_find_device(VAR_0, (VAR_2->token >> 8) & 0x7f);

        USBEndpoint *ep = usb_ep_get(dev, pid, (VAR_2->token >> 15) & 0xf);

        VAR_1 = uhci_queue_get(VAR_0, VAR_2, ep);

    }

    async = uhci_async_alloc(VAR_1, VAR_3);



    





    async->queue->valid = 32;



    VAR_6 = ((VAR_2->token >> 21) + 1) & 0x7ff;

    spd = (pid == USB_TOKEN_IN && (VAR_2->ctrl & TD_CTRL_SPD) != 0);

    usb_packet_setup(&async->packet, pid, VAR_1->ep, VAR_3, spd,

                     (VAR_2->ctrl & TD_CTRL_IOC) != 0);

    qemu_sglist_add(&async->sgl, VAR_2->buffer, VAR_6);

    usb_packet_map(&async->packet, &async->sgl);



    switch(pid) {

    case USB_TOKEN_OUT:

    case USB_TOKEN_SETUP:

        VAR_5 = usb_handle_packet(VAR_1->ep->dev, &async->packet);

        if (VAR_5 >= 0)

            VAR_5 = VAR_6;

        break;



    case USB_TOKEN_IN:

        VAR_5 = usb_handle_packet(VAR_1->ep->dev, &async->packet);

        break;



    default:

        

        usb_packet_unmap(&async->packet, &async->sgl);

        uhci_async_free(async);

        VAR_0->status |= UHCI_STS_HCPERR;

        uhci_update_irq(VAR_0);

        return TD_RESULT_STOP_FRAME;

    }

 

    if (VAR_5 == USB_RET_ASYNC) {

        uhci_async_link(async);

        if (!queuing) {

            uhci_queue_fill(VAR_1, VAR_2);

        }

        return TD_RESULT_ASYNC_START;

    }



    async->packet.result = VAR_5;



done:

    VAR_5 = uhci_complete_td(VAR_0, VAR_2, async, VAR_4);

    usb_packet_unmap(&async->packet, &async->sgl);

    uhci_async_free(async);

    return VAR_5;

}

static int FUNC_0(UHCIState *VAR_0, UHCIQueue *VAR_1,
UHCI_TD *VAR_2, uint32_t VAR_3, uint32_t *VAR_4)
{ UHCIAsync *async; int VAR_5 = 0, VAR_6; bool spd; bool queuing = (VAR_1 != NULL); uint8_t pid = VAR_2->token & 0xff; if (!(VAR_2->ctrl & TD_CTRL_ACTIVE)) { if (VAR_2->ctrl & TD_CTRL_IOC) { *VAR_4 |= 0x01; } return TD_RESULT_NEXT_QH; } async = uhci_async_find_td(VAR_0, VAR_3, VAR_2); if (async) { async->queue->valid = 32; if (!async->done)
return TD_RESULT_ASYNC_CONT; if (queuing) { return TD_RESULT_ASYNC_CONT; } uhci_async_unlink(async); goto done; } if (VAR_1 == NULL) { USBDevice *dev = uhci_find_device(VAR_0, (VAR_2->token >> 8) & 0x7f); USBEndpoint *ep = usb_ep_get(dev, pid, (VAR_2->token >> 15) & 0xf); VAR_1 = uhci_queue_get(VAR_0, VAR_2, ep); } async = uhci_async_alloc(VAR_1, VAR_3); async->queue->valid = 32; VAR_6 = ((VAR_2->token >> 21) + 1) & 0x7ff; spd = (pid == USB_TOKEN_IN && (VAR_2->ctrl & TD_CTRL_SPD) != 0); usb_packet_setup(&async->packet, pid, VAR_1->ep, VAR_3, spd,
(VAR_2->ctrl & TD_CTRL_IOC) != 0); qemu_sglist_add(&async->sgl, VAR_2->buffer, VAR_6); usb_packet_map(&async->packet, &async->sgl); switch(pid) { case USB_TOKEN_OUT:
case USB_TOKEN_SETUP:
VAR_5 = usb_handle_packet(VAR_1->ep->dev, &async->packet); if (VAR_5 >= 0)
VAR_5 = VAR_6; break; case USB_TOKEN_IN:
VAR_5 = usb_handle_packet(VAR_1->ep->dev, &async->packet); break; default:
usb_packet_unmap(&async->packet, &async->sgl); uhci_async_free(async); VAR_0->status |= UHCI_STS_HCPERR; uhci_update_irq(VAR_0); return TD_RESULT_STOP_FRAME; } if (VAR_5 == USB_RET_ASYNC) { uhci_async_link(async); if (!queuing) { uhci_queue_fill(VAR_1, VAR_2); } return TD_RESULT_ASYNC_START; } async->packet.result = VAR_5; done:
VAR_5 = uhci_complete_td(VAR_0, VAR_2, async, VAR_4); usb_packet_unmap(&async->packet, &async->sgl); uhci_async_free(async); return VAR_5; }