Пример #1
0
int
ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize
             , void *data, int datasize)
{
    ASSERT32FLAT();
    if (! CONFIG_USB_EHCI)
        return -1;
    dprintf(5, "ehci_control %p (dir=%d cmd=%d data=%d)\n"
            , p, dir, cmdsize, datasize);
    if (datasize > 4*4096 || cmdsize > 4*4096) {
        // XXX - should support larger sizes.
        warn_noalloc();
        return -1;
    }
    struct ehci_pipe *pipe = container_of(p, struct ehci_pipe, pipe);

    // Setup transfer descriptors
    struct ehci_qtd *tds = memalign_tmphigh(EHCI_QTD_ALIGN, sizeof(*tds) * 3);
    if (!tds) {
        warn_noalloc();
        return -1;
    }
    memset(tds, 0, sizeof(*tds) * 3);
    struct ehci_qtd *td = tds;

    td->qtd_next = (u32)&td[1];
    td->alt_next = EHCI_PTR_TERM;
    td->token = (ehci_explen(cmdsize) | QTD_STS_ACTIVE
                 | QTD_PID_SETUP | ehci_maxerr(3));
    u16 maxpacket = pipe->pipe.maxpacket;
    fillTDbuffer(td, maxpacket, cmd, cmdsize);
    td++;

    if (datasize) {
        td->qtd_next = (u32)&td[1];
        td->alt_next = EHCI_PTR_TERM;
        td->token = (QTD_TOGGLE | ehci_explen(datasize) | QTD_STS_ACTIVE
                     | (dir ? QTD_PID_IN : QTD_PID_OUT) | ehci_maxerr(3));
        fillTDbuffer(td, maxpacket, data, datasize);
        td++;
    }

    td->qtd_next = EHCI_PTR_TERM;
    td->alt_next = EHCI_PTR_TERM;
    td->token = (QTD_TOGGLE | QTD_STS_ACTIVE
                 | (dir ? QTD_PID_OUT : QTD_PID_IN) | ehci_maxerr(3));

    // Transfer data
    barrier();
    pipe->qh.qtd_next = (u32)tds;
    int i, ret=0;
    for (i=0; i<3; i++) {
        struct ehci_qtd *td = &tds[i];
        ret = ehci_wait_td(pipe, td, 500);
        if (ret)
            break;
    }
    free(tds);
    return ret;
}
Пример #2
0
struct usb_pipe *
ehci_alloc_control_pipe(struct usb_pipe *dummy)
{
    if (! CONFIG_USB_EHCI)
        return NULL;
    struct usb_ehci_s *cntl = container_of(
        dummy->cntl, struct usb_ehci_s, usb);
    dprintf(7, "ehci_alloc_control_pipe %p\n", &cntl->usb);

    // Allocate a queue head.
    struct ehci_pipe *pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe));
    if (!pipe) {
        warn_noalloc();
        return NULL;
    }
    memset(pipe, 0, sizeof(*pipe));
    memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe));
    pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM;

    // Add queue head to controller list.
    struct ehci_qh *async_qh = cntl->async_qh;
    pipe->qh.next = async_qh->next;
    barrier();
    async_qh->next = (u32)&pipe->qh | EHCI_PTR_QH;
    return &pipe->pipe;
}
Пример #3
0
void
ramdisk_setup()
{
    if (!CONFIG_COREBOOT_FLASH || !CONFIG_FLASH_FLOPPY)
        return;

    // Find image.
    struct cbfs_file *file = cbfs_findprefix("floppyimg/", NULL);
    if (!file)
        return;
    u32 size = cbfs_datasize(file);
    dprintf(3, "Found floppy file %s of size %d\n", cbfs_filename(file), size);
    int ftype = find_floppy_type(size);
    if (ftype < 0) {
        dprintf(3, "No floppy type found for ramdisk size\n");
        return;
    }

    // Allocate ram for image.
    void *pos = memalign_tmphigh(PAGE_SIZE, size);
    if (!pos) {
        dprintf(3, "Not enough memory for ramdisk\n");
        return;
    }
    add_e820((u32)pos, size, E820_RESERVED);

    // Copy image into ram.
    cbfs_copyfile(file, pos, size);

    // Setup driver.
    dprintf(1, "Mapping CBFS floppy %s to addr %p\n", cbfs_filename(file), pos);
    struct drive_s *drive_g = addFloppy((u32)pos, ftype, DTYPE_RAMDISK);
    if (drive_g)
        strtcpy(drive_g->model, cbfs_filename(file), ARRAY_SIZE(drive_g->model));
}
Пример #4
0
struct usb_pipe *
ehci_alloc_pipe(struct usbdevice_s *usbdev
                , struct usb_endpoint_descriptor *epdesc)
{
    if (! CONFIG_USB_EHCI)
        return NULL;
    u8 eptype = epdesc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
    if (eptype == USB_ENDPOINT_XFER_INT)
        return ehci_alloc_intr_pipe(usbdev, epdesc);
    struct usb_ehci_s *cntl = container_of(
        usbdev->hub->cntl, struct usb_ehci_s, usb);
    dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, eptype);

    struct usb_pipe *usbpipe = usb_getFreePipe(&cntl->usb, eptype);
    if (usbpipe) {
        // Use previously allocated pipe.
        struct ehci_pipe *pipe = container_of(usbpipe, struct ehci_pipe, pipe);
        ehci_desc2pipe(pipe, usbdev, epdesc);
        return usbpipe;
    }

    // Allocate a new queue head.
    struct ehci_pipe *pipe;
    if (eptype == USB_ENDPOINT_XFER_CONTROL)
        pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe));
    else
        pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe));
    if (!pipe) {
        warn_noalloc();
        return NULL;
    }
    memset(pipe, 0, sizeof(*pipe));
    ehci_desc2pipe(pipe, usbdev, epdesc);
    pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM;

    // Add queue head to controller list.
    struct ehci_qh *async_qh = cntl->async_qh;
    pipe->qh.next = async_qh->next;
    barrier();
    async_qh->next = (u32)&pipe->qh | EHCI_PTR_QH;
    return &pipe->pipe;
}