Author: hselasky Date: Wed Sep 12 19:15:29 2012 New Revision: 240419 URL: http://svn.freebsd.org/changeset/base/240419
Log: Fix TX FIFO sizes. Correct FIFO handling in Host mode. Modified: head/sys/dev/usb/controller/dwc_otg.c head/sys/dev/usb/controller/dwc_otg.h Modified: head/sys/dev/usb/controller/dwc_otg.c ============================================================================== --- head/sys/dev/usb/controller/dwc_otg.c Wed Sep 12 18:18:14 2012 (r240418) +++ head/sys/dev/usb/controller/dwc_otg.c Wed Sep 12 19:15:29 2012 (r240419) @@ -211,24 +211,34 @@ dwc_otg_init_fifo(struct dwc_otg_softc * return (EINVAL); } - DWC_OTG_WRITE_4(sc, DOTG_GNPTXFSIZ, (0x10 << 16) | (tx_start / 4)); - fifo_size -= 0x40; - tx_start += 0x40; - - /* setup control endpoint profile */ - sc->sc_hw_ep_profile[0].usb = dwc_otg_ep_profile[0]; - if (mode == DWC_MODE_HOST) { /* reset active endpoints */ sc->sc_active_rx_ep = 0; + fifo_size /= 2; + + DWC_OTG_WRITE_4(sc, DOTG_GNPTXFSIZ, + ((fifo_size / 4) << 16) | + (tx_start / 4)); + + tx_start += fifo_size; + DWC_OTG_WRITE_4(sc, DOTG_HPTXFSIZ, ((fifo_size / 4) << 16) | (tx_start / 4)); } + if (mode == DWC_MODE_DEVICE) { + DWC_OTG_WRITE_4(sc, DOTG_GNPTXFSIZ, + (0x10 << 16) | (tx_start / 4)); + fifo_size -= 0x40; + tx_start += 0x40; + + /* setup control endpoint profile */ + sc->sc_hw_ep_profile[0].usb = dwc_otg_ep_profile[0]; + /* reset active endpoints */ sc->sc_active_rx_ep = 1; @@ -521,18 +531,11 @@ dwc_otg_host_channel_alloc(struct dwc_ot /* enable interrupts */ DWC_OTG_WRITE_4(sc, DOTG_HCINTMSK(x), HCINT_STALL | HCINT_BBLERR | - HCINT_AHBERR | HCINT_CHHLTD | - HCINT_XACTERR | HCINT_XFERCOMPL | - HCINT_NAK | HCINT_NYET); + HCINT_AHBERR | HCINT_XACTERR | + HCINT_XFERCOMPL | HCINT_NAK); DWC_OTG_WRITE_4(sc, DOTG_HCSPLT(x), td->hcsplt); DWC_OTG_WRITE_4(sc, DOTG_HCTSIZ(x), 0); - DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(x), 0); - - /* reset TX FIFO */ - DWC_OTG_WRITE_4(sc, DOTG_GRSTCTL, - GRSTCTL_TXFIFO(x) | - GRSTCTL_TXFFLSH); /* set channel */ td->channel = x; @@ -581,8 +584,7 @@ dwc_otg_host_setup_tx(struct dwc_otg_td return (0); /* complete */ } - if (temp & (HCINT_BBLERR | - HCINT_AHBERR | HCINT_CHHLTD | HCINT_XACTERR)) { + if (temp & (HCINT_BBLERR | HCINT_AHBERR | HCINT_XACTERR)) { td->error_any = 1; return (0); /* complete */ } @@ -783,7 +785,6 @@ dwc_otg_host_data_rx(struct dwc_otg_td * struct dwc_otg_softc *sc; uint32_t temp; uint16_t count; - uint8_t got_short; uint8_t ep_type; if (dwc_otg_host_channel_alloc(td)) @@ -800,24 +801,25 @@ dwc_otg_host_data_rx(struct dwc_otg_td * temp, DWC_OTG_READ_4(sc, DOTG_HCCHAR(td->channel)), DWC_OTG_READ_4(sc, DOTG_HCTSIZ(td->channel))); - if (temp & HCINT_NAK) + if (temp & HCINT_NAK) { td->did_nak = 1; + /* disable channel - will generate a halted event */ + DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel), + HCCHAR_CHENA | HCCHAR_CHDIS); + } + if (temp & HCINT_STALL) { td->error_stall = 1; td->error_any = 1; return (0); /* complete */ } - if (temp & (HCINT_BBLERR | - HCINT_AHBERR | HCINT_CHHLTD | HCINT_XACTERR)) { + if (temp & (HCINT_BBLERR | HCINT_AHBERR | HCINT_XACTERR)) { td->error_any = 1; return (0); /* complete */ } - if (temp & HCINT_XFERCOMPL) - td->did_complete = 1; - /* check endpoint status */ if (sc->sc_last_rx_status == 0) goto not_complete; @@ -826,14 +828,22 @@ dwc_otg_host_data_rx(struct dwc_otg_td * goto not_complete; switch (sc->sc_last_rx_status & GRXSTSRD_PKTSTS_MASK) { + case GRXSTSRH_HALTED: + DPRINTF("HALTED\n"); + td->did_complete = 1; + break; + case GRXSTSRH_IN_COMPLETE: + DPRINTF("COMPLETE\n"); + /* disable channel - will generate a halted event */ + DWC_OTG_WRITE_4(sc, DOTG_HCCHAR(td->channel), + HCCHAR_CHENA | HCCHAR_CHDIS); + break; case GRXSTSRH_IN_DATA: DPRINTF("DATA\n"); td->toggle ^= 1; - got_short = 0; - /* get the packet byte count */ count = GRXSTSRD_BCNT_GET(sc->sc_last_rx_status); @@ -842,7 +852,7 @@ dwc_otg_host_data_rx(struct dwc_otg_td * if (count < td->max_packet_size) { /* we have a short packet */ td->short_pkt = 1; - got_short = 1; + td->got_short = 1; } else { /* invalid USB packet */ td->error_any = 1; @@ -863,35 +873,33 @@ dwc_otg_host_data_rx(struct dwc_otg_td * return (0); /* we are complete */ } - usbd_copy_in(td->pc, td->offset, sc->sc_rx_bounce_buffer, count); + usbd_copy_in(td->pc, td->offset, + sc->sc_rx_bounce_buffer, count); + td->remainder -= count; td->offset += count; - - /* release FIFO */ - dwc_otg_common_rx_ack(sc); - - /* check if we are complete */ - if ((td->remainder == 0) || got_short) { - if (td->short_pkt) { - /* we are complete */ - return (0); - } - /* else need to receive a zero length packet */ - } break; default: DPRINTF("OTHER\n"); - - /* release FIFO */ - dwc_otg_common_rx_ack(sc); break; } + /* release FIFO */ + dwc_otg_common_rx_ack(sc); not_complete: - if (td->did_complete == 0 && td->did_nak == 0) + if (td->did_complete == 0) return (1); /* busy */ + /* check if we are complete */ + if ((td->remainder == 0) || (td->got_short != 0)) { + if (td->short_pkt) { + /* we are complete */ + return (0); + } + /* else need to receive a zero length packet */ + } + temp = sc->sc_hcchar[td->channel]; ep_type = ((temp & HCCHAR_EPTYPE_MASK) >> @@ -1077,8 +1085,10 @@ dwc_otg_host_data_tx(struct dwc_otg_td * temp, DWC_OTG_READ_4(sc, DOTG_HCCHAR(td->channel)), DWC_OTG_READ_4(sc, DOTG_HCTSIZ(td->channel))); - if (temp & HCINT_NAK) + if (temp & HCINT_NAK) { td->did_nak = 1; + td->did_complete = 1; + } if (temp & HCINT_STALL) { td->error_stall = 1; @@ -1086,8 +1096,7 @@ dwc_otg_host_data_tx(struct dwc_otg_td * return (0); /* complete */ } - if (temp & (HCINT_BBLERR | - HCINT_AHBERR | HCINT_CHHLTD | HCINT_XACTERR)) { + if (temp & (HCINT_BBLERR | HCINT_AHBERR | HCINT_XACTERR)) { td->error_any = 1; return (0); /* complete */ } @@ -1509,8 +1518,29 @@ repeat: uint8_t ep_no; - temp = GRXSTSRD_BCNT_GET( - sc->sc_last_rx_status); + temp = sc->sc_last_rx_status & + GRXSTSRD_PKTSTS_MASK; + + /* non-data messages we simply skip */ + if (temp != GRXSTSRD_STP_DATA && + temp != GRXSTSRD_OUT_DATA) { + if (sc->sc_flags.status_device_mode) { + dwc_otg_common_rx_ack(sc); + goto repeat; + } else if (temp != GRXSTSRD_OUT_COMPLETE && + temp != GRXSTSRH_HALTED) { + dwc_otg_common_rx_ack(sc); + goto repeat; + } + } + + if (temp == GRXSTSRH_HALTED || + temp == GRXSTSRD_OUT_COMPLETE) { + temp = 0; + } else { + temp = GRXSTSRD_BCNT_GET( + sc->sc_last_rx_status); + } ep_no = GRXSTSRD_CHNUM_GET( sc->sc_last_rx_status); @@ -1522,16 +1552,6 @@ repeat: sc->sc_rx_bounce_buffer, (temp + 3) / 4); } - temp = sc->sc_last_rx_status & - GRXSTSRD_PKTSTS_MASK; - - /* non-data messages we simply skip */ - if (temp != GRXSTSRD_STP_DATA && - temp != GRXSTSRD_OUT_DATA) { - dwc_otg_common_rx_ack(sc); - goto repeat; - } - /* check if we should dump the data */ if (!(sc->sc_active_rx_ep & (1U << ep_no))) { dwc_otg_common_rx_ack(sc); @@ -1575,12 +1595,6 @@ repeat: if (sc->sc_last_rx_status == 0) goto repeat; - /* if no host listener - dump data */ - if (sc->sc_flags.status_device_mode == 0) { - dwc_otg_common_rx_ack(sc); - goto repeat; - } - /* disable RX FIFO level interrupt */ sc->sc_irq_mask &= ~GINTSTS_RXFLVL; DWC_OTG_WRITE_4(sc, DOTG_GINTMSK, sc->sc_irq_mask); @@ -1637,6 +1651,8 @@ dwc_otg_interrupt(struct dwc_otg_softc * /* clear left-over interrupts */ for (x = 0; x != sc->sc_host_ch_max; x++) { + if (!(haint & (1 << x))) + continue; /* check if channel is disabled */ if (sc->sc_hcchar[x] == 0) { uint32_t temp; @@ -1845,6 +1861,7 @@ dwc_otg_setup_standard_chain_sub(struct td->short_pkt = temp->short_pkt; td->alt_next = temp->setup_alt_next; td->set_toggle = 0; + td->got_short = 0; td->channel = DWC_OTG_MAX_CHANNELS; } Modified: head/sys/dev/usb/controller/dwc_otg.h ============================================================================== --- head/sys/dev/usb/controller/dwc_otg.h Wed Sep 12 18:18:14 2012 (r240418) +++ head/sys/dev/usb/controller/dwc_otg.h Wed Sep 12 19:15:29 2012 (r240419) @@ -70,6 +70,7 @@ struct dwc_otg_td { uint8_t set_toggle:1; uint8_t did_nak:1; uint8_t did_complete:1; + uint8_t got_short:1; }; struct dwc_otg_std_temp { _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"