Exemplo n.º 1
0
static int
ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout)
{
    u64 end = calc_future_tsc(timeout);
    u32 status;
    for (;;) {
        status = td->token;
        if (!(status & QTD_STS_ACTIVE))
            break;
        if (check_tsc(end)) {
            u32 cur = GET_FLATPTR(pipe->qh.current);
            u32 tok = GET_FLATPTR(pipe->qh.token);
            u32 next = GET_FLATPTR(pipe->qh.qtd_next);
            warn_timeout();
            dprintf(1, "ehci pipe=%p cur=%08x tok=%08x next=%x td=%p status=%x\n"
                    , pipe, cur, tok, next, td, status);
            ehci_reset_pipe(pipe);
            struct usb_ehci_s *cntl = container_of(
                GET_FLATPTR(pipe->pipe.cntl), struct usb_ehci_s, usb);
            ehci_waittick(cntl);
            return -1;
        }
        yield();
    }
    if (status & QTD_STS_HALT) {
        dprintf(1, "ehci_wait_td error - status=%x\n", status);
        ehci_reset_pipe(pipe);
        return -2;
    }
    return 0;
}
Exemplo n.º 2
0
static void
ehci_reset_pipe(struct ehci_pipe *pipe)
{
    SET_FLATPTR(pipe->qh.qtd_next, EHCI_PTR_TERM);
    SET_FLATPTR(pipe->qh.alt_next, EHCI_PTR_TERM);
    barrier();
    SET_FLATPTR(pipe->qh.token, GET_FLATPTR(pipe->qh.token) & QTD_TOGGLE);
}
Exemplo n.º 3
0
int
ehci_poll_intr(struct usb_pipe *p, void *data)
{
    ASSERT16();
    if (! CONFIG_USB_EHCI)
        return -1;
    struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe);
    struct ehci_qtd *td = GET_FLATPTR(pipe->next_td);
    u32 token = GET_FLATPTR(td->token);
    if (token & QTD_STS_ACTIVE)
        // No intrs found.
        return -1;
    // XXX - check for errors.

    // Copy data.
    int maxpacket = GET_FLATPTR(pipe->pipe.maxpacket);
    int pos = td - GET_FLATPTR(pipe->tds);
    void *tddata = GET_FLATPTR(pipe->data) + maxpacket * pos;
    memcpy_far(GET_SEG(SS), data
               , FLATPTR_TO_SEG(tddata), (void*)FLATPTR_TO_OFFSET(tddata)
               , maxpacket);

    // Reenable this td.
    struct ehci_qtd *next = (void*)(GET_FLATPTR(td->qtd_next) & ~EHCI_PTR_BITS);
    SET_FLATPTR(pipe->next_td, next);
    SET_FLATPTR(td->buf[0], (u32)tddata);
    barrier();
    SET_FLATPTR(td->token, (ehci_explen(maxpacket) | QTD_STS_ACTIVE
                            | QTD_PID_IN | ehci_maxerr(3)));

    return 0;
}
Exemplo n.º 4
0
int
ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize)
{
    if (! CONFIG_USB_EHCI)
        return -1;
    struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe);
    dprintf(7, "ehci_send_bulk qh=%p dir=%d data=%p size=%d\n"
            , &pipe->qh, dir, data, datasize);

    // Allocate 4 tds on stack (16byte aligned)
    u8 tdsbuf[sizeof(struct ehci_qtd) * STACKQTDS + EHCI_QTD_ALIGN - 1];
    struct ehci_qtd *tds = (void*)ALIGN((u32)tdsbuf, EHCI_QTD_ALIGN);
    memset(tds, 0, sizeof(*tds) * STACKQTDS);

    // Setup fields in qh
    u16 maxpacket = GET_FLATPTR(pipe->pipe.maxpacket);
    SET_FLATPTR(pipe->qh.info1
                , ((1 << QH_MULT_SHIFT)
                   | (maxpacket << QH_MAXPACKET_SHIFT)
                   | (GET_FLATPTR(pipe->pipe.speed) << QH_SPEED_SHIFT)
                   | (GET_FLATPTR(pipe->pipe.ep) << QH_EP_SHIFT)
                   | (GET_FLATPTR(pipe->pipe.devaddr) << QH_DEVADDR_SHIFT)));
    SET_FLATPTR(pipe->qh.info2
                , ((1 << QH_MULT_SHIFT)
                   | (GET_FLATPTR(pipe->pipe.tt_port) << QH_HUBPORT_SHIFT)
                   | (GET_FLATPTR(pipe->pipe.tt_devaddr) << QH_HUBADDR_SHIFT)));
    barrier();
    SET_FLATPTR(pipe->qh.qtd_next, (u32)MAKE_FLATPTR(GET_SEG(SS), tds));

    int tdpos = 0;
    while (datasize) {
        struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS];
        int ret = ehci_wait_td(pipe, td, 5000);
        if (ret)
            return -1;

        struct ehci_qtd *nexttd_fl = MAKE_FLATPTR(GET_SEG(SS)
                                                 , &tds[tdpos % STACKQTDS]);

        int transfer = fillTDbuffer(td, maxpacket, data, datasize);
        td->qtd_next = (transfer==datasize ? EHCI_PTR_TERM : (u32)nexttd_fl);
        td->alt_next = EHCI_PTR_TERM;
        barrier();
        td->token = (ehci_explen(transfer) | QTD_STS_ACTIVE
                     | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3));

        data += transfer;
        datasize -= transfer;
    }
    int i;
    for (i=0; i<STACKQTDS; i++) {
        struct ehci_qtd *td = &tds[tdpos++ % STACKQTDS];
        int ret = ehci_wait_td(pipe, td, 5000);
        if (ret)
            return -1;
    }

    return 0;
}
Exemplo n.º 5
0
int
ohci_poll_intr(struct usb_pipe *pipe, void *data)
{
    ASSERT16();
    if (! CONFIG_USB_OHCI)
        return -1;

    struct ohci_pipe *p = container_of(pipe, struct ohci_pipe, pipe);
    struct ohci_td *tds = GET_FLATPTR(p->tds);
    struct ohci_td *head = (void*)GET_FLATPTR(p->ed.hwHeadP);
    struct ohci_td *tail = (void*)GET_FLATPTR(p->ed.hwTailP);
    int count = GET_FLATPTR(p->count);
    int pos = (tail - tds + 1) % count;
    struct ohci_td *next = &tds[pos];
    if (head == next)
        // No intrs found.
        return -1;
    // XXX - check for errors.

    // Copy data.
    u32 endp = GET_FLATPTR(p->pipe.endp);
    int maxpacket = endp2maxsize(endp);
    void *pipedata = GET_FLATPTR(p->data);
    void *intrdata = pipedata + maxpacket * pos;
    memcpy_far(GET_SEG(SS), data
               , FLATPTR_TO_SEG(intrdata), (void*)FLATPTR_TO_OFFSET(intrdata)
               , maxpacket);

    // Reenable this td.
    SET_FLATPTR(tail->hwINFO, TD_DP_IN | TD_T_TOGGLE | TD_CC);
    intrdata = pipedata + maxpacket * (tail-tds);
    SET_FLATPTR(tail->hwCBP, (u32)intrdata);
    SET_FLATPTR(tail->hwNextTD, (u32)next);
    SET_FLATPTR(tail->hwBE, (u32)intrdata + maxpacket - 1);

    SET_FLATPTR(p->ed.hwTailP, (u32)next);

    return 0;
}