/* Called to start packet transmission. */ int udc_endpoint_write (struct usb_endpoint_instance *endpoint) { unsigned short epnum = endpoint->endpoint_address & USB_ENDPOINT_NUMBER_MASK; debug("Entering for ep %x \n", epnum); if (endpoint->tx_urb) { u32 ep_csr1; debug_urb_buffer("We have an URB, transmitting", endpoint); S3C24X0_write_noniso_tx_fifo(endpoint); S3C24X0_UDC_SETIX(epnum); ep_csr1 = inl(S3C24X0_UDC_IN_CSR1_REG); outl(ep_csr1|S3C24X0_UDC_ICSR1_PKTRDY, S3C24X0_UDC_IN_CSR1_REG); } else debug("\n"); return 0; }
static void S3C24X0_udc_epn(int ep) { struct usb_endpoint_instance *endpoint; struct urb *urb; u32 ep_csr1; if (ep >= S3C24X0_UDC_NUM_ENDPOINTS) return; endpoint = &udc_device->bus->endpoint_array[ep]; S3C24X0_UDC_SETIX(ep); if (endpoint->endpoint_address & USB_DIR_IN) { /* IN transfer (device to host) */ ep_csr1 = inl(S3C24X0_UDC_IN_CSR1_REG); debug("for ep=%u, CSR1=0x%x ", ep, ep_csr1); urb = endpoint->tx_urb; if (ep_csr1 & S3C24X0_UDC_ICSR1_SENTSTL) { /* Stall handshake */ debug("stall\n"); outl(0x00, S3C24X0_UDC_IN_CSR1_REG); return; } if (!(ep_csr1 & S3C24X0_UDC_ICSR1_PKTRDY) && urb && urb->actual_length) { debug("completing previously send data "); usbd_tx_complete(endpoint); /* push pending data into FIFO */ if ((endpoint->last == endpoint->tx_packetSize) && (urb->actual_length - endpoint->sent - endpoint->last == 0)) { endpoint->sent += endpoint->last; /* Write 0 bytes of data (ZLP) */ debug("ZLP "); outl(ep_csr1|S3C24X0_UDC_ICSR1_PKTRDY, S3C24X0_UDC_IN_CSR1_REG); } else { /* write actual data to fifo */ debug_urb_buffer("TX_DATA", endpoint); S3C24X0_write_noniso_tx_fifo(endpoint); outl(ep_csr1|S3C24X0_UDC_ICSR1_PKTRDY, S3C24X0_UDC_IN_CSR1_REG); } } debug("\n"); } else { /* OUT transfer (host to device) */ ep_csr1 = inl(S3C24X0_UDC_OUT_CSR1_REG); debug("for ep=%u, CSR1=0x%x ", ep, ep_csr1); urb = endpoint->rcv_urb; if (ep_csr1 & S3C24X0_UDC_OCSR1_SENTSTL) { /* Stall handshake */ outl(0x00, S3C24X0_UDC_IN_CSR1_REG); return; } if ((ep_csr1 & S3C24X0_UDC_OCSR1_PKTRDY) && urb) { /* Read pending data from fifo */ u32 fifo_count = fifo_count_out(); int is_last = 0; u32 i, urb_avail = urb->buffer_length - urb->actual_length; u8 *cp = urb->buffer + urb->actual_length; if (fifo_count < endpoint->rcv_packetSize) is_last = 1; debug("fifo_count=%u is_last=%, urb_avail=%u)\n", fifo_count, is_last, urb_avail); if (fifo_count < urb_avail) urb_avail = fifo_count; for (i = 0; i < urb_avail; i++) *cp++ = inb(ep_fifo_reg[ep]); if (is_last) outl(ep_csr1 & ~S3C24X0_UDC_OCSR1_PKTRDY, S3C24X0_UDC_OUT_CSR1_REG); usbd_rcv_complete(endpoint, urb_avail, 0); } } urb = endpoint->rcv_urb; }
static void s3c2410_udc_epn(int ep) { struct usb_endpoint_instance *endpoint; struct urb *urb; u32 ep_csr1; if (ep >= S3C2410_UDC_NUM_ENDPOINTS) return; endpoint = &udc_device->bus->endpoint_array[ep]; S3C2410_UDC_SETIX(ep); if (endpoint->endpoint_address & USB_DIR_IN) { /* IN transfer (device to host) */ ep_csr1 = inl(S3C2410_UDC_IN_CSR1_REG); debug("for ep=%u, IN_CSR1=0x%x ", ep, ep_csr1); urb = endpoint->tx_urb; if (ep_csr1 & S3C2410_UDC_ICSR1_SENTSTL) { /* Stall handshake */ debug("stall\n"); outl(0x00, S3C2410_UDC_IN_CSR1_REG); return; } if (!(ep_csr1 & S3C2410_UDC_ICSR1_PKTRDY) && urb && urb->actual_length) { debug("completing previously send data "); usbd_tx_complete(endpoint); /* push pending data into FIFO */ if ((endpoint->last == endpoint->tx_packetSize) && (urb->actual_length - endpoint->sent - endpoint->last == 0)) { endpoint->sent += endpoint->last; /* Write 0 bytes of data (ZLP) */ debug("ZLP "); outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY, S3C2410_UDC_IN_CSR1_REG); } else { /* write actual data to fifo */ debug_urb_buffer("TX_DATA", endpoint); s3c2410_write_noniso_tx_fifo(endpoint); outl(ep_csr1|S3C2410_UDC_ICSR1_PKTRDY, S3C2410_UDC_IN_CSR1_REG); } } debug("\n"); } else { /* OUT transfer (host to device) */ ep_csr1 = inl(S3C2410_UDC_OUT_CSR1_REG); debug("for ep=%u, OUT_CSR1=0x%x ", ep, ep_csr1); urb = endpoint->rcv_urb; if (ep_csr1 & S3C2410_UDC_OCSR1_SENTSTL) { /* Stall handshake */ debugX("SENT STALL\n"); outl(0x00, S3C2410_UDC_IN_CSR1_REG); return; } if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && urb) { /* Read pending data from fifo */ u32 fifo_count = fifo_count_out(); int is_last = 0; u32 i, urb_avail = urb->buffer_length - urb->actual_length; u8 *cp = urb->buffer + urb->actual_length; if (fifo_count < endpoint->rcv_packetSize) is_last = 1; debug("fifo_count=%u is_last=%d, urb_avail=%u\n", fifo_count, is_last, urb_avail); if (fifo_count < urb_avail) urb_avail = fifo_count; for (i = 0; i < urb_avail; i++) *cp++ = inb(ep_fifo_reg[ep]); /* if (is_last) */ /* * Once the MCU reads the packet from FIFO, * this bit should be cleared */ #ifndef AUTO_CLEAR outl(ep_csr1 & ~S3C2410_UDC_OCSR1_PKTRDY, S3C2410_UDC_OUT_CSR1_REG); #endif usbd_rcv_complete(endpoint, urb_avail, 0); /* FIXME is there a better way to notify that, * we have got data */ usbd_device_event_irq(udc_device, DEVICE_FUNCTION_PRIVATE, 0); } } urb = endpoint->rcv_urb; }