/** * This function handles the Rx Status Queue Level Interrupt, which * indicates that there is a least one packet in the Rx FIFO. The * packets are moved from the FIFO to memory, where they will be * processed when the Endpoint Interrupt Register indicates Transfer * Complete or SETUP Phase Done. * * Repeat the following until the Rx Status Queue is empty: * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet * info * -# If Receive FIFO is empty then skip to step Clear the interrupt * and exit * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the * SETUP data to the buffer * -# If OUT Data Packet call dwc_otg_read_packet to copy the data * to the destination buffer */ int32_t dwc_otg_pcd_handle_rx_status_q_level_intr(void) { gintmsk_data_t gintmask = { 0 }; device_grxsts_data_t status; gintsts_data_t gintsts; dwc_ep_t *ep; DBG("dwc_otg_pcd_handle_rx_status_q_level_intr()\n"); /* Disable the Rx Status Queue Level interrupt */ gintmask.b.rxstsqlvl= 1; dwc_modify_reg32( DWC_REG_GINTMSK, gintmask.d32, 0); /* Get the Status from the top of the FIFO */ status.d32 = dwc_read_reg32( DWC_REG_GRXSTSP); //DBG("rx status: ep%d, pktsts: %d\n",status.b.epnum,status.b.pktsts); /* Get pointer to EP structure */ ep = &g_dwc_eps[status.b.epnum]; switch (status.b.pktsts) { case DWC_DSTS_GOUT_NAK: DBG( "Global OUT NAK\n"); break; case DWC_STS_DATA_UPDT: DBG( "OUT Data Packet\n"); { if (status.b.bcnt && ep->xfer_buff) { /** @todo NGS Check for buffer overflow? */ dwc_otg_read_packet( ep->xfer_buff,status.b.bcnt); ep->xfer_count += status.b.bcnt; ep->xfer_buff += status.b.bcnt; if (!status.b.epnum) { /*const char* p = ep->xfer_buff - status.b.bcnt;*/ this_pcd[0].cmdtype.out_complete = 1; /* *if(!strcmp("power", p) || !strcmp("low_power", p)){ * printf("%s, bcnt %d, cnt %d, %d\n", p, status.b.bcnt, ep->xfer_count, this_pcd.cmdtype.in_complete); *} */ } } } break; case DWC_STS_XFER_COMP: DBG("OUT Complete\n"); break; case DWC_DSTS_SETUP_COMP: DBG("SETUP Complete\n"); break; case DWC_DSTS_SETUP_UPDT: DBG("SETUP update\n"); { static int _is_first_setup_out_in_cmd = 1; dwc_otg_read_setup_packet( this_pcd[0].setup_pkt.d32); this_pcd[0].request_enable = 1; ep->xfer_count += status.b.bcnt; DBG("set %d, %d\n", status.b.bcnt, ep->xfer_count); if (_is_first_setup_out_in_cmd) //first tplcmd/bulkcmd that in sequence 'setup + out + in' { struct usb_ctrlrequest request = this_pcd[0].setup_pkt.req; if ( USB_TYPE_VENDOR == (request.bRequestType & USB_TYPE_MASK) ) { unsigned bRequest = request.bRequest; if ((AM_REQ_WR_LARGE_MEM == bRequest) || (AM_REQ_RD_LARGE_MEM == bRequest) ||(AM_REQ_TPL_CMD == bRequest) || (AM_REQ_TPL_STAT == bRequest) || (AM_REQ_DOWNLOAD == bRequest) || (AM_REQ_BULKCMD == bRequest)) { __udelay(20);//delay for first command that consisted of consecutive 'ep0 out', i.e. 'setup + out + in' _is_first_setup_out_in_cmd = 0; } } } } break; default: //DBG( "Invalid Packet Status (0x%0x)\n", status.b.pktsts); break; } /* Enable the Rx Status Queue Level interrupt */ dwc_modify_reg32( DWC_REG_GINTMSK, 0, gintmask.d32); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.rxstsqlvl = 1; dwc_write_reg32 ( DWC_REG_GINTSTS, gintsts.d32); return 1; }
/** * This function handles the Rx Status Queue Level Interrupt, which * indicates that there is a least one packet in the Rx FIFO. The * packets are moved from the FIFO to memory, where they will be * processed when the Endpoint Interrupt Register indicates Transfer * Complete or SETUP Phase Done. * * Repeat the following until the Rx Status Queue is empty: * -# Read the Receive Status Pop Register (GRXSTSP) to get Packet * info * -# If Receive FIFO is empty then skip to step Clear the interrupt * and exit * -# If SETUP Packet call dwc_otg_read_setup_packet to copy the * SETUP data to the buffer * -# If OUT Data Packet call dwc_otg_read_packet to copy the data * to the destination buffer */ int32_t dwc_otg_pcd_handle_rx_status_q_level_intr() { gintmsk_data_t gintmask = { 0 }; device_grxsts_data_t status; gintsts_data_t gintsts; dwc_ep_t *ep; DBG("dwc_otg_pcd_handle_rx_status_q_level_intr()\n"); /* Disable the Rx Status Queue Level interrupt */ gintmask.b.rxstsqlvl= 1; dwc_modify_reg32( DWC_REG_GINTMSK, gintmask.d32, 0); /* Get the Status from the top of the FIFO */ status.d32 = dwc_read_reg32( DWC_REG_GRXSTSP); //DBG("rx status: ep%d, pktsts: %d\n",status.b.epnum,status.b.pktsts); /* Get pointer to EP structure */ if(status.b.epnum == 0) { ep = &g_dwc_eps[0]; } else { ep = &g_dwc_eps[status.b.epnum]; } switch (status.b.pktsts) { case DWC_DSTS_GOUT_NAK: DBG( "Global OUT NAK\n"); break; case DWC_STS_DATA_UPDT: DBG( "OUT Data Packet\n"); if (status.b.bcnt && ep->xfer_buff){ /** @todo NGS Check for buffer overflow? */ dwc_otg_read_packet( ep->xfer_buff,status.b.bcnt); ep->xfer_count += status.b.bcnt; ep->xfer_buff += status.b.bcnt; } break; case DWC_STS_XFER_COMP: DBG("OUT Complete\n"); break; case DWC_DSTS_SETUP_COMP: DBG("SETUP Complete\n"); break; case DWC_DSTS_SETUP_UPDT: DBG("SETUP update\n"); dwc_otg_read_setup_packet( this_pcd.setup_pkt.d32); this_pcd.request_enable = 1; ep->xfer_count += status.b.bcnt; break; default: //DBG( "Invalid Packet Status (0x%0x)\n", status.b.pktsts); break; } /* Enable the Rx Status Queue Level interrupt */ dwc_modify_reg32( DWC_REG_GINTMSK, 0, gintmask.d32); /* Clear interrupt */ gintsts.d32 = 0; gintsts.b.rxstsqlvl = 1; dwc_write_reg32 ( DWC_REG_GINTSTS, gintsts.d32); return 1; }