static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask)

{

    int len = 0, max_len, err, ret;

    uint8_t pid;



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

    pid = td->token & 0xff;



    ret = async->packet.len;



    if (td->ctrl & TD_CTRL_IOS)

        td->ctrl &= ~TD_CTRL_ACTIVE;



    if (ret < 0)

        goto out;



    len = async->packet.len;

    td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);



    /* The NAK bit may have been set by a previous frame, so clear it

       here.  The docs are somewhat unclear, but win2k relies on this

       behavior.  */

    td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);

    if (td->ctrl & TD_CTRL_IOC)

        *int_mask |= 0x01;



    if (pid == USB_TOKEN_IN) {

        if (len > max_len) {

            ret = USB_RET_BABBLE;

            goto out;

        }



        if (len > 0) {

            /* write the data back */

            cpu_physical_memory_write(td->buffer, async->buffer, len);

        }



        if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {

            *int_mask |= 0x02;

            /* short packet: do not update QH */

            DPRINTF("uhci: short packet. td 0x%x token 0x%x\n", async->td, async->token);

            return 1;

        }

    }



    /* success */

    return 0;



out:

    switch(ret) {

    case USB_RET_STALL:

        td->ctrl |= TD_CTRL_STALL;

        td->ctrl &= ~TD_CTRL_ACTIVE;

        s->status |= UHCI_STS_USBERR;

        if (td->ctrl & TD_CTRL_IOC) {

            *int_mask |= 0x01;

        }

        uhci_update_irq(s);

        return 1;



    case USB_RET_BABBLE:

        td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;

        td->ctrl &= ~TD_CTRL_ACTIVE;

        s->status |= UHCI_STS_USBERR;

        if (td->ctrl & TD_CTRL_IOC) {

            *int_mask |= 0x01;

        }

        uhci_update_irq(s);

        /* frame interrupted */

        return -1;



    case USB_RET_NAK:

        td->ctrl |= TD_CTRL_NAK;

        if (pid == USB_TOKEN_SETUP)

            break;

	return 1;



    case USB_RET_NODEV:

    default:

	break;

    }



    /* Retry the TD if error count is not zero */



    td->ctrl |= TD_CTRL_TIMEOUT;

    err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;

    if (err != 0) {

        err--;

        if (err == 0) {

            td->ctrl &= ~TD_CTRL_ACTIVE;

            s->status |= UHCI_STS_USBERR;

            if (td->ctrl & TD_CTRL_IOC)

                *int_mask |= 0x01;

            uhci_update_irq(s);

        }

    }

    td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |

        (err << TD_CTRL_ERROR_SHIFT);

    return 1;

}

static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_t *int_mask)

{

    int len = 0, max_len, err, ret;

    uint8_t pid;



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

    pid = td->token & 0xff;



    ret = async->packet.len;



    if (td->ctrl & TD_CTRL_IOS)

        td->ctrl &= ~TD_CTRL_ACTIVE;



    if (ret < 0)

        goto out;



    len = async->packet.len;

    td->ctrl = (td->ctrl & ~0x7ff) | ((len - 1) & 0x7ff);



    





    td->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);

    if (td->ctrl & TD_CTRL_IOC)

        *int_mask |= 0x01;



    if (pid == USB_TOKEN_IN) {

        if (len > max_len) {

            ret = USB_RET_BABBLE;

            goto out;

        }



        if (len > 0) {

            

            cpu_physical_memory_write(td->buffer, async->buffer, len);

        }



        if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {

            *int_mask |= 0x02;

            

            DPRINTF("uhci: short packet. td 0x%x token 0x%x\n", async->td, async->token);

            return 1;

        }

    }



    

    return 0;



out:

    switch(ret) {

    case USB_RET_STALL:

        td->ctrl |= TD_CTRL_STALL;

        td->ctrl &= ~TD_CTRL_ACTIVE;

        s->status |= UHCI_STS_USBERR;

        if (td->ctrl & TD_CTRL_IOC) {

            *int_mask |= 0x01;

        }

        uhci_update_irq(s);

        return 1;



    case USB_RET_BABBLE:

        td->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;

        td->ctrl &= ~TD_CTRL_ACTIVE;

        s->status |= UHCI_STS_USBERR;

        if (td->ctrl & TD_CTRL_IOC) {

            *int_mask |= 0x01;

        }

        uhci_update_irq(s);

        

        return -1;



    case USB_RET_NAK:

        td->ctrl |= TD_CTRL_NAK;

        if (pid == USB_TOKEN_SETUP)

            break;

	return 1;



    case USB_RET_NODEV:

    default:

	break;

    }



    



    td->ctrl |= TD_CTRL_TIMEOUT;

    err = (td->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;

    if (err != 0) {

        err--;

        if (err == 0) {

            td->ctrl &= ~TD_CTRL_ACTIVE;

            s->status |= UHCI_STS_USBERR;

            if (td->ctrl & TD_CTRL_IOC)

                *int_mask |= 0x01;

            uhci_update_irq(s);

        }

    }

    td->ctrl = (td->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |

        (err << TD_CTRL_ERROR_SHIFT);

    return 1;

}

    ret = async->packet.len;     len = async->packet.len;
static int FUNC_0(UHCIState *VAR_0, UHCI_TD *VAR_1, UHCIAsync *VAR_2, uint32_t *VAR_3)

{

    int VAR_4 = 0, VAR_5, VAR_6, VAR_7;

    uint8_t pid;



    VAR_5 = ((VAR_1->token >> 21) + 1) & 0x7ff;

    pid = VAR_1->token & 0xff;



    VAR_7 = VAR_2->packet.VAR_4;



    if (VAR_1->ctrl & TD_CTRL_IOS)

        VAR_1->ctrl &= ~TD_CTRL_ACTIVE;



    if (VAR_7 < 0)

        goto out;



    VAR_4 = VAR_2->packet.VAR_4;

    VAR_1->ctrl = (VAR_1->ctrl & ~0x7ff) | ((VAR_4 - 1) & 0x7ff);



    





    VAR_1->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK);

    if (VAR_1->ctrl & TD_CTRL_IOC)

        *VAR_3 |= 0x01;



    if (pid == USB_TOKEN_IN) {

        if (VAR_4 > VAR_5) {

            VAR_7 = USB_RET_BABBLE;

            goto out;

        }



        if (VAR_4 > 0) {

            

            cpu_physical_memory_write(VAR_1->buffer, VAR_2->buffer, VAR_4);

        }



        if ((VAR_1->ctrl & TD_CTRL_SPD) && VAR_4 < VAR_5) {

            *VAR_3 |= 0x02;

            

            DPRINTF("uhci: short packet. VAR_1 0x%x token 0x%x\n", VAR_2->VAR_1, VAR_2->token);

            return 1;

        }

    }



    

    return 0;



out:

    switch(VAR_7) {

    case USB_RET_STALL:

        VAR_1->ctrl |= TD_CTRL_STALL;

        VAR_1->ctrl &= ~TD_CTRL_ACTIVE;

        VAR_0->status |= UHCI_STS_USBERR;

        if (VAR_1->ctrl & TD_CTRL_IOC) {

            *VAR_3 |= 0x01;

        }

        uhci_update_irq(VAR_0);

        return 1;



    case USB_RET_BABBLE:

        VAR_1->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL;

        VAR_1->ctrl &= ~TD_CTRL_ACTIVE;

        VAR_0->status |= UHCI_STS_USBERR;

        if (VAR_1->ctrl & TD_CTRL_IOC) {

            *VAR_3 |= 0x01;

        }

        uhci_update_irq(VAR_0);

        

        return -1;



    case USB_RET_NAK:

        VAR_1->ctrl |= TD_CTRL_NAK;

        if (pid == USB_TOKEN_SETUP)

            break;

	return 1;



    case USB_RET_NODEV:

    default:

	break;

    }



    



    VAR_1->ctrl |= TD_CTRL_TIMEOUT;

    VAR_6 = (VAR_1->ctrl >> TD_CTRL_ERROR_SHIFT) & 3;

    if (VAR_6 != 0) {

        VAR_6--;

        if (VAR_6 == 0) {

            VAR_1->ctrl &= ~TD_CTRL_ACTIVE;

            VAR_0->status |= UHCI_STS_USBERR;

            if (VAR_1->ctrl & TD_CTRL_IOC)

                *VAR_3 |= 0x01;

            uhci_update_irq(VAR_0);

        }

    }

    VAR_1->ctrl = (VAR_1->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |

        (VAR_6 << TD_CTRL_ERROR_SHIFT);

    return 1;

}

static int FUNC_0(UHCIState *VAR_0, UHCI_TD *VAR_1, UHCIAsync *VAR_2, uint32_t *VAR_3)
{ int VAR_4 = 0, VAR_5, VAR_6, VAR_7; uint8_t pid; VAR_5 = ((VAR_1->token >> 21) + 1) & 0x7ff; pid = VAR_1->token & 0xff; VAR_7 = VAR_2->packet.VAR_4; if (VAR_1->ctrl & TD_CTRL_IOS)
VAR_1->ctrl &= ~TD_CTRL_ACTIVE; if (VAR_7 < 0)
goto out; VAR_4 = VAR_2->packet.VAR_4; VAR_1->ctrl = (VAR_1->ctrl & ~0x7ff) | ((VAR_4 - 1) & 0x7ff); VAR_1->ctrl &= ~(TD_CTRL_ACTIVE | TD_CTRL_NAK); if (VAR_1->ctrl & TD_CTRL_IOC)
*VAR_3 |= 0x01; if (pid == USB_TOKEN_IN) { if (VAR_4 > VAR_5) { VAR_7 = USB_RET_BABBLE; goto out; } if (VAR_4 > 0) { cpu_physical_memory_write(VAR_1->buffer, VAR_2->buffer, VAR_4); } if ((VAR_1->ctrl & TD_CTRL_SPD) && VAR_4 < VAR_5) { *VAR_3 |= 0x02; DPRINTF("uhci: short packet. VAR_1 0x%x token 0x%x\n", VAR_2->VAR_1, VAR_2->token); return 1; } } return 0; out:
switch(VAR_7) { case USB_RET_STALL:
VAR_1->ctrl |= TD_CTRL_STALL; VAR_1->ctrl &= ~TD_CTRL_ACTIVE; VAR_0->status |= UHCI_STS_USBERR; if (VAR_1->ctrl & TD_CTRL_IOC) { *VAR_3 |= 0x01; } uhci_update_irq(VAR_0); return 1; case USB_RET_BABBLE:
VAR_1->ctrl |= TD_CTRL_BABBLE | TD_CTRL_STALL; VAR_1->ctrl &= ~TD_CTRL_ACTIVE; VAR_0->status |= UHCI_STS_USBERR; if (VAR_1->ctrl & TD_CTRL_IOC) { *VAR_3 |= 0x01; } uhci_update_irq(VAR_0); return -1; case USB_RET_NAK:
VAR_1->ctrl |= TD_CTRL_NAK; if (pid == USB_TOKEN_SETUP)
break; return 1; case USB_RET_NODEV:
default:
break; } VAR_1->ctrl |= TD_CTRL_TIMEOUT; VAR_6 = (VAR_1->ctrl >> TD_CTRL_ERROR_SHIFT) & 3; if (VAR_6 != 0) { VAR_6--; if (VAR_6 == 0) { VAR_1->ctrl &= ~TD_CTRL_ACTIVE; VAR_0->status |= UHCI_STS_USBERR; if (VAR_1->ctrl & TD_CTRL_IOC)
*VAR_3 |= 0x01; uhci_update_irq(VAR_0); } } VAR_1->ctrl = (VAR_1->ctrl & ~(3 << TD_CTRL_ERROR_SHIFT)) |
(VAR_6 << TD_CTRL_ERROR_SHIFT); return 1; }