📄 dwc_otg_pcd_intr.c
字号:
iso_packet = _ep->iso_req->iso_packet_desc1; } dma_desc = dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * dwc_ep->proc_buf_num; sts.b.bs = BS_HOST_READY;//0 sts.b.rxsts = 0; sts.b.l = 0; sts.b.sp = 0; sts.b.ioc = 0; sts.b.pid = 0; sts.b.framenum = 0; stsTmp.d32 = readl(&dma_desc->status); _ep->iso_req->start_frame = stsTmp.b.framenum; for(i = 0; i < dwc_ep->desc_cnt - dwc_ep->pkt_per_frm; i+= dwc_ep->pkt_per_frm) { for(j = 0; j < dwc_ep->pkt_per_frm; ++j) { stsTmp.d32 = readl(&dma_desc->status); /* Write status in iso_packet_decsriptor */ iso_packet->status = stsTmp.b.rxsts + (stsTmp.b.bs^BS_DMA_DONE); if(iso_packet->status) { iso_packet->status = -ENODATA; } /* Received data length */ iso_packet->actual_length = dwc_ep->data_per_frame - stsTmp.b.rxbytes; data_per_desc = ( (j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; sts.b.rxbytes = data_per_desc; if(stsTmp.b.bs != BS_DMA_BUSY) { writel((uint32_t)dma_ad, &dma_desc->buf); writel(sts.d32, &dma_desc->status); } dma_desc ++; (uint32_t)dma_ad += data_per_desc; ++iso_packet; } } for(j = 0; j < dwc_ep->pkt_per_frm - 1; ++j) { stsTmp.d32 = readl(&dma_desc->status); /* Write status in iso_packet_decsriptor */ iso_packet->status = stsTmp.b.rxsts + (stsTmp.b.bs^BS_DMA_DONE); if(iso_packet->status) { iso_packet->status = -ENODATA; } /* Received data length */ iso_packet->actual_length = dwc_ep->data_per_frame - stsTmp.b.rxbytes; data_per_desc = ( (j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; sts.b.rxbytes = data_per_desc; if(stsTmp.b.bs != BS_DMA_BUSY) { writel((uint32_t)dma_ad, &dma_desc->buf); writel(sts.d32, &dma_desc->status); } ++iso_packet; dma_desc++; (uint32_t)dma_ad += data_per_desc; } sts.b.ioc = 1; sts.b.l = dwc_ep->proc_buf_num; stsTmp.d32 = readl(&dma_desc->status); while(stsTmp.b.bs == BS_DMA_BUSY) { stsTmp.d32 = readl(&dma_desc->status); } data_per_desc = ( (j + 1) * dwc_ep->maxpacket > dwc_ep->data_per_frame) ? dwc_ep->data_per_frame - j * dwc_ep->maxpacket : dwc_ep->maxpacket; sts.b.rxbytes = data_per_desc; writel((uint32_t)dma_ad, &dma_desc->buf); writel(sts.d32, &dma_desc->status); /* Write status in iso_packet_decsriptor */ iso_packet->status = stsTmp.b.rxsts + (stsTmp.b.bs^BS_DMA_DONE); if(iso_packet->status) { iso_packet->status = -ENODATA; } /* Received data length */ iso_packet->actual_length = dwc_ep->data_per_frame - stsTmp.b.rxbytes; dwc_ep->proc_buf_num ^= 0x1; } else /** ISO IN EP */ { iso_in_sts_data_t sts = { .d32 =0 }; iso_in_sts_data_t stsTmp = {.d32 = 0}; struct usb_gadget_iso_packet_descriptor *iso_packet; if(dwc_ep->proc_buf_num == 0) { /** Buffer 0 descriptors setup */ dma_ad = dwc_ep->dma_addr0; iso_packet = _ep->iso_req->iso_packet_desc0; } else { /** Buffer 1 descriptors setup */ dma_ad = dwc_ep->dma_addr1; iso_packet = _ep->iso_req->iso_packet_desc1; } dma_desc = dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * dwc_ep->proc_buf_num; sts.b.bs = BS_HOST_READY; sts.b.txsts = 0; sts.b.sp = 0;//(dwc_ep->data_per_frame % dwc_ep->maxpacket)? 1 : 0; sts.b.ioc = 0; sts.b.pid = dwc_ep->pkt_per_frm; sts.b.framenum = dwc_ep->next_frame; sts.b.txbytes = dwc_ep->data_per_frame; sts.b.l = 0; for(i = 0; i < dwc_ep->desc_cnt - 1; i++) { stsTmp.d32 = readl(&dma_desc->status); /* Write status in iso packet descriptor */ iso_packet->status = stsTmp.b.txsts + (stsTmp.b.bs^BS_DMA_DONE); if(iso_packet->status != 0) { iso_packet->status = -ENODATA; } /* Bytes has been transfered */ iso_packet->actual_length = dwc_ep->data_per_frame - stsTmp.b.txbytes; if(stsTmp.b.bs != BS_DMA_BUSY){ writel((uint32_t)dma_ad, &dma_desc->buf); writel(sts.d32, &dma_desc->status); } dma_desc ++; (uint32_t)dma_ad += dwc_ep->data_per_frame; sts.b.framenum += dwc_ep->bInterval; ++iso_packet; } sts.b.ioc = 1; sts.b.l = dwc_ep->proc_buf_num; stsTmp.d32 = readl(&dma_desc->status); while(stsTmp.b.bs == BS_DMA_BUSY) { DWC_PRINT("last busy\n"); stsTmp.d32 = readl(&dma_desc->status); } /* Write status in iso packet descriptor ??? do be done with ERROR codes*/ iso_packet->status = stsTmp.b.txsts + (stsTmp.b.bs^BS_DMA_DONE); if(iso_packet->status != 0) { iso_packet->status = -ENODATA; } /* Bytes has been transfered */ iso_packet->actual_length = dwc_ep->data_per_frame - stsTmp.b.txbytes; writel((uint32_t)dma_ad, &dma_desc->buf); writel(sts.d32, &dma_desc->status); dwc_ep->next_frame = sts.b.framenum + dwc_ep->bInterval * 1; dwc_ep->proc_buf_num ^= 1; } /** Call callback function to process data buffer */ _ep->iso_req->status = 0;/* success */ _ep->iso_req->process_buffer(&_ep->ep, _ep->iso_req);}static void dwc_otg_pcd_handle_iso_bna(dwc_otg_pcd_ep_t *_ep){ dwc_ep_t *dwc_ep = &_ep->dwc_ep; volatile uint32_t *addr; depctl_data_t depctl = {.d32 = 0}; dwc_otg_pcd_t *pcd = _ep->pcd; dwc_otg_iso_dma_desc_t *dma_desc; dma_desc = dwc_ep->iso_desc_addr + dwc_ep->desc_cnt * (dwc_ep->proc_buf_num); make_descriptors_host_ready(dma_desc,dwc_ep->desc_cnt,dwc_ep->is_in); if(dwc_ep->is_in == 0){ addr = &GET_CORE_IF(pcd)->dev_if->out_ep_regs[dwc_ep->num]->doepctl; }else{ addr = &GET_CORE_IF(pcd)->dev_if->in_ep_regs[dwc_ep->num]->diepctl; } depctl.b.epena = 1; dwc_modify_reg32(addr,depctl.d32,depctl.d32);}#endif //_EN_ISOC_/** * This function handles EP0 Control transfers. * * The state of the control tranfers are tracked in * <code>ep0state</code>. */static void handle_ep0( dwc_otg_pcd_t *_pcd ){ dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0; desc_sts_data_t desc_sts; deptsiz0_data_t deptsiz; uint32_t byte_count;#ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCDV, "%s()\n", __func__); print_ep0_state(_pcd);#endif// DWC_PRINT("HANDLE EP0\n"); switch (_pcd->ep0state) { case EP0_DISCONNECT: break; case EP0_IDLE: _pcd->request_config = 0; pcd_setup( _pcd ); break; case EP0_IN_DATA_PHASE:#ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCD, "DATA_IN EP%d-%s: type=%d, mps=%d\n", ep0->dwc_ep.num, (ep0->dwc_ep.is_in ?"IN":"OUT"), ep0->dwc_ep.type, ep0->dwc_ep.maxpacket );#endif if (core_if->dma_enable != 0) { if(core_if->dma_desc_enable == 0) { /* * For EP0 we can only program 1 packet at a time so we * need to do the make calculations after each complete. * Call write_packet to make the calculations, as in * slave mode, and use those values to determine if we * can complete. */ dwc_otg_ep_write_packet (core_if, &ep0->dwc_ep, 1); } else { desc_sts.d32 = readl(core_if->dev_if->in_desc_addr); byte_count = ep0->dwc_ep.xfer_len - desc_sts.b.bytes; ep0->dwc_ep.xfer_count += byte_count; ep0->dwc_ep.xfer_buff += byte_count; ep0->dwc_ep.dma_addr += byte_count; } } if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {// DWC_PRINT("IN CONTINUE\n"); dwc_otg_ep0_continue_transfer ( GET_CORE_IF(_pcd), &ep0->dwc_ep ); DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); } else if(ep0->dwc_ep.sent_zlp) {// DWC_PRINT("IN ZLP\n"); dwc_otg_ep0_continue_transfer ( GET_CORE_IF(_pcd), &ep0->dwc_ep ); ep0->dwc_ep.sent_zlp = 0; DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); } else {// DWC_PRINT("IN COMPLETE\n"); ep0_complete_request( ep0 ); DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); } break; case EP0_OUT_DATA_PHASE:#ifdef DEBUG_EP0 DWC_DEBUGPL(DBG_PCD, "DATA_OUT EP%d-%s: type=%d, mps=%d\n", ep0->dwc_ep.num, (ep0->dwc_ep.is_in ?"IN":"OUT"), ep0->dwc_ep.type, ep0->dwc_ep.maxpacket );#endif if (core_if->dma_enable != 0) { byte_count = ep0->dwc_ep.maxpacket; if(core_if->dma_desc_enable == 0) { deptsiz.d32 = dwc_read_reg32(&core_if->dev_if->out_ep_regs[0]->doeptsiz); byte_count -= deptsiz.b.xfersize; } else { desc_sts.d32 = readl(core_if->dev_if->out_desc_addr); byte_count -= desc_sts.b.bytes; } ep0->dwc_ep.xfer_count += byte_count; ep0->dwc_ep.xfer_buff += byte_count; ep0->dwc_ep.dma_addr += byte_count; } if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) {// DWC_PRINT("OUT CONTINUE\n"); dwc_otg_ep0_continue_transfer ( GET_CORE_IF(_pcd), &ep0->dwc_ep ); DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); } else if(ep0->dwc_ep.sent_zlp) {// DWC_PRINT("OUT ZLP\n"); dwc_otg_ep0_continue_transfer ( GET_CORE_IF(_pcd), &ep0->dwc_ep ); ep0->dwc_ep.sent_zlp = 0; DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); } else {// DWC_PRINT("OUT COMPLETE\n"); ep0_complete_request( ep0 ); DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); } break; case EP0_IN_STATUS_PHASE: case EP0_OUT_STATUS_PHASE: DWC_DEBUGPL(DBG_PCD, "CASE: EP0_STATUS\n"); ep0_complete_request( ep0 ); _pcd->ep0state = EP0_IDLE; ep0->stopped = 1; ep0->dwc_ep.is_in = 0; /* OUT for next SETUP */ /* Prepare for more SETUP Packets */ if (core_if->dma_enable) { ep0_out_start( core_if, _pcd ); } else { int i; depctl_data_t diepctl; diepctl.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[0]->diepctl); if (_pcd->ep0.queue_sof) { _pcd->ep0.queue_sof = 0; start_next_request (&_pcd->ep0); } diepctl.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[0]->diepctl); if (_pcd->ep0.queue_sof) { _pcd->ep0.queue_sof = 0; start_next_request (&_pcd->ep0); } for (i=0; i < core_if->dev_if->num_in_eps; i++) { diepctl.d32 = dwc_read_reg32( &core_if->dev_if->in_ep_regs[i+1]->diepctl); if (_pcd->in_ep[i].queue_sof) { _pcd->in_ep[i].queue_sof = 0; start_next_request (&_pcd->in_ep[i]); } } } break; case EP0_STALL: DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n"); break; }#ifdef DEBUG_EP0 print_ep0_state(_pcd);#endif}#if 0/** * This function handles EP0 Control transfers. * * The state of the control tranfers are tracked in * <code>ep0state</code>. */static void handle_ep0_descdma( dwc_otg_pcd_t *_pcd , uint32_t intr_sts){ dwc_otg_core_if_t *core_if = GET_CORE_IF(_pcd); dwc_otg_pcd_ep_t *ep0 = &_pcd->ep0; desc_sts_data_t desc_sts; uint32_t byte_count; depctl_data_t diepctl = { .d32 = 0}; depctl_data_t doepctl = { .d32 = 0}; switch(intr_sts) {//////////////////////// CASE A ///////////////////////////////////////////// case 1: // EP0 OUT IOC is set (case A) switch(_pcd->ep0state) { case EP0_DISCONNECT: break; case EP0_IDLE: case EP0_OUT_STATUS_PHASE: // this tells "IN Token received with Tx FIFO Empty" // Interrupt handler not to STALL EP0 IN _pcd->ep0state = EP0_IDLE; if(desc_sts.b.sr) { pcd_setup(_pcd); if(_pcd->ep0state == EP0_IN_DATA_PHASE || _pcd->ep0state == EP0_IN_STATUS_PHASE) init_setup_desc(core_if, _pcd); } else { init_setup_desc(core_if, _pcd); } break; case EP0_IN_DATA_PHASE: case EP0_IN_STATUS_PHASE: // disable EP0 IN diepctl.d32 = dwc_read_reg32(&dev_if->in_ep_regs[0]->diepctl); diepctl.b.epdis = 1; diepctl.b.snak = 1; dwc_write_reg32( &dev_if->in_ep_regs[0]->diepctl, diepctl.d32 ); // ... should be here ??? ... /// if(desc_sts.b.sr) { pcd_setup(_pcd); if(_pcd->ep0state == EP0_IN_DATA_PHASE || _pcd->ep0state == EP0_IN_STATUS_PHASE) ep0_out_start(core_if, _pcd); } break; case EP0_OUT_DATA_PHASE: if(desc_sts.b.sr) { // ... linking SETUP desc pointer to this ... pcd_setup(_pcd); if(_pcd->ep0state == EP0_IN_DATA_PHASE || _pcd->ep0state == EP0_IN_STATUS_PHASE) ep0_out_start(core_if, _pcd); } else { byte_count = ep0->dwc_ep.maxpacket - desc_sts.b.bytes; ep0->dwc_ep.xfer_count += byte_count; ep0->dwc_ep.xfer_buff += byte_count; ep0->dwc_ep.dma_addr += byte_count; if (ep0->dwc_ep.xfer_count < ep0->dwc_ep.total_len) { dwc_otg_ep0_continue_transfer ( GET_CORE_IF(_pcd), &ep0->dwc_ep ); DWC_DEBUGPL(DBG_PCD, "CONTINUE TRANSFER\n"); } else { // ... EP set STALL ... ep0_complete_request( ep0 ); ep0_out_start(core_if, _pcd); DWC_DEBUGPL(DBG_PCD, "COMPLETE TRANSFER\n"); } } break; case EP0_STALL: DWC_ERROR("EP0 STALLed, should not get here pcd_setup()\n"); break; } break;//////////////////////// CASE B //////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -