void usb_stream_reset(struct usb_stream_config const *config) { config->out_desc->flags = DOEPDMA_RXBYTES(config->tx_size) | DOEPDMA_LAST | DOEPDMA_BS_HOST_RDY | DOEPDMA_IOC; config->out_desc->addr = config->rx_ram; GR_USB_DOEPDMA(config->endpoint) = (uint32_t)config->out_desc; config->in_desc->flags = DIEPDMA_LAST | DIEPDMA_BS_HOST_BSY | DIEPDMA_IOC; config->in_desc->addr = config->tx_ram; GR_USB_DIEPDMA(config->endpoint) = (uint32_t)config->in_desc; GR_USB_DOEPCTL(config->endpoint) = DXEPCTL_MPS(64) | DXEPCTL_USBACTEP | DXEPCTL_EPTYPE_BULK | DXEPCTL_CNAK | DXEPCTL_EPENA; GR_USB_DIEPCTL(config->endpoint) = DXEPCTL_MPS(64) | DXEPCTL_USBACTEP | DXEPCTL_EPTYPE_BULK | DXEPCTL_TXFNUM(config->endpoint); GR_USB_DAINTMSK |= DAINT_INEP(config->endpoint) | DAINT_OUTEP(config->endpoint); *config->is_reset = 1; /* Flush any queued data */ hook_call_deferred(config->deferred_tx, 0); hook_call_deferred(config->deferred_rx, 0); }
/* The next packet from the host should be a Setup packet. Get ready for it. */ static void expect_setup_packet(void) { print_later("expect_setup_packet()", 0, 0, 0, 0, 0); what_am_i_doing = WAITING_FOR_SETUP_PACKET; next_out_desc->flags = DOEPDMA_RXBYTES(USB_MAX_PACKET_SIZE) | DOEPDMA_IOC | DOEPDMA_LAST; /* We don't care about IN packets right now, only OUT. */ GR_USB_DAINTMSK |= DAINT_OUTEP(0); GR_USB_DAINTMSK &= ~DAINT_INEP(0); /* Let it run. We might need CNAK if we just got an OUT for status */ GR_USB_DOEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; }
/* We're complaining about something by stalling both IN and OUT packets, * but a SETUP packet will get through anyway, so prepare for it. */ static void stall_both_fifos(void) { print_later("stall_both_fifos()", 0, 0, 0, 0, 0); what_am_i_doing = WAITING_FOR_SETUP_PACKET; next_out_desc->flags = DOEPDMA_RXBYTES(USB_MAX_PACKET_SIZE) | DOEPDMA_IOC | DOEPDMA_LAST; /* We don't care about IN packets right now, only OUT. */ GR_USB_DAINTMSK |= DAINT_OUTEP(0); GR_USB_DAINTMSK &= ~DAINT_INEP(0); /* Stall both IN and OUT. The hardware will reset them when the next * SETUP comes along. */ GR_USB_DOEPCTL(0) = DXEPCTL_STALL | DXEPCTL_EPENA; flush_in_fifo(); GR_USB_DIEPCTL(0) = DXEPCTL_STALL | DXEPCTL_EPENA; }
/* No Data phase, just Status phase (which is IN, since Setup is OUT) */ static void expect_status_phase_in(enum table_case tc) { print_later("expect_status_phase_in(%c)", "0ABCDE67"[tc], 0, 0, 0, 0); what_am_i_doing = NO_DATA_STAGE; /* Expect a zero-length IN for the Status phase */ (void) load_in_fifo(0, 0); /* We apparently have to do this every time we transmit anything */ flush_in_fifo(); /* I don't think we have to do this every time, but the Programmer's * Guide says to, so... */ GR_USB_DIEPDMA(0) = (uint32_t)(cur_in_desc); /* Blindly following instructions here, too. */ if (tc == TABLE_CASE_C) GR_USB_DIEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; else GR_USB_DIEPCTL(0) = DXEPCTL_EPENA; /* The Programmer's Guide instructions for the Normal Two-Stage Control * Transfer leave this next bit out, so we only need it if we intend to * process an Exceptional Two-Stage Control Transfer. Because obviously * we always know in advance what the host is going to do. Idiots. */ /* Be prepared to get a new Setup packet during the Status phase */ next_out_desc->flags = DOEPDMA_RXBYTES(USB_MAX_PACKET_SIZE) | DOEPDMA_IOC | DOEPDMA_LAST; /* We've already set GR_USB_DOEPDMA(0), so just enable it. */ if (tc == TABLE_CASE_C) GR_USB_DOEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; else GR_USB_DOEPCTL(0) = DXEPCTL_EPENA; /* Get an interrupt when either IN or OUT arrives */ GR_USB_DAINTMSK |= (DAINT_OUTEP(0) | DAINT_INEP(0)); }
/* The TX FIFO buffer is loaded. Start the Data phase. */ static void expect_data_phase_in(enum table_case tc) { print_later("expect_data_phase_in(%c)", "0ABCDE67"[tc], 0, 0, 0, 0); what_am_i_doing = DATA_STAGE_IN; /* We apparently have to do this every time we transmit anything */ flush_in_fifo(); /* I don't think we have to do this every time, but the Programmer's * Guide says to, so... */ GR_USB_DIEPDMA(0) = (uint32_t)(cur_in_desc); /* Blindly following instructions here, too. */ if (tc == TABLE_CASE_C) GR_USB_DIEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; else GR_USB_DIEPCTL(0) = DXEPCTL_EPENA; /* * When the IN is done, we expect a zero-length OUT for the status * phase but it could be an early SETUP instead. We'll have to deal * with either one when it arrives. */ next_out_desc->flags = DOEPDMA_RXBYTES(USB_MAX_PACKET_SIZE) | DOEPDMA_IOC | DOEPDMA_LAST; /* And here's this jimmy rustler again... */ if (tc == TABLE_CASE_C) GR_USB_DOEPCTL(0) = DXEPCTL_CNAK | DXEPCTL_EPENA; else GR_USB_DOEPCTL(0) = DXEPCTL_EPENA; /* Get an interrupt when either IN or OUT arrives */ GR_USB_DAINTMSK |= (DAINT_OUTEP(0) | DAINT_INEP(0)); }
static void ep_reset(void) { ep_out_desc.flags = DOEPDMA_RXBYTES(USB_MAX_PACKET_SIZE) | DOEPDMA_LAST | DOEPDMA_BS_HOST_RDY | DOEPDMA_IOC; ep_out_desc.addr = ep_buf_rx; GR_USB_DOEPDMA(USB_EP_BLOB) = (uint32_t)&ep_out_desc; ep_in_desc.flags = DIEPDMA_LAST | DIEPDMA_BS_HOST_BSY | DIEPDMA_IOC; ep_in_desc.addr = ep_buf_tx; GR_USB_DIEPDMA(USB_EP_BLOB) = (uint32_t)&ep_in_desc; GR_USB_DOEPCTL(USB_EP_BLOB) = DXEPCTL_MPS(64) | DXEPCTL_USBACTEP | DXEPCTL_EPTYPE_BULK | DXEPCTL_CNAK | DXEPCTL_EPENA; GR_USB_DIEPCTL(USB_EP_BLOB) = DXEPCTL_MPS(64) | DXEPCTL_USBACTEP | DXEPCTL_EPTYPE_BULK | DXEPCTL_TXFNUM(USB_EP_BLOB); GR_USB_DAINTMSK |= (1<<USB_EP_BLOB) | (1 << (USB_EP_BLOB+16)); is_reset = 1; /* Flush any queued data */ hook_call_deferred(tx_fifo_handler, 0); hook_call_deferred(rx_fifo_handler, 0); }
/* Let the USB HW OUT-from-host FIFO receive some bytes */ static void usb_enable_rx(struct usb_stream_config const *config, int len) { config->out_desc->flags = DOEPDMA_RXBYTES(len) | DOEPDMA_LAST | DOEPDMA_BS_HOST_RDY | DOEPDMA_IOC; GR_USB_DOEPCTL(config->endpoint) |= DXEPCTL_CNAK | DXEPCTL_EPENA; }
/* Let the USB HW OUT-from-host FIFO receive some bytes */ static void usb_enable_rx(int len) { ep_out_desc.flags = DOEPDMA_RXBYTES(len) | DOEPDMA_LAST | DOEPDMA_BS_HOST_RDY | DOEPDMA_IOC; GR_USB_DOEPCTL(USB_EP_BLOB) |= DXEPCTL_CNAK | DXEPCTL_EPENA; }