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"

Reply via email to