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; }
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; }
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)); }
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; }