// For now, start and len are a number of 512-byte blocks int sd_read(struct sd_card *card, int start, int len, void *dest) { int bl_addr; struct dma_cb ctrl __attribute__ ((__aligned__(32))); if(card->type == 0) start *= 512; dmb(); *BLKSIZECNT = BLKSIZE(512) | BLKCNT(len); sd_send_command(CMD_READ_MULTIPLE_BLOCK, TM_BLKCNT_EN | TM_AUTO_CMD_12 | TM_DAT_CARD_TO_HOST | TM_MULTI_BLOCK | CMD_RSPNS_48 | CMD_ISDATA, start); ctrl.ti = DMA_TI_INTEN | DMA_TI_WAIT_RESP | DMA_TI_DEST_INC | DMA_TI_DEST_WIDTH | DMA_TI_SRC_DREQ | DMA_TI_PERMAP_EMMC; ctrl.source_ad = IO_TO_BUS(DATA); ctrl.dest_ad = virt_to_phy(dest); ctrl.txfr_len = 512 * len; ctrl.stride = 0; ctrl.nextconbk = 0; return dma_initiate(DMA_CHAN_EMMC, &ctrl); }
void process_bulk_out(int ch) { // bulk out the nth block UINT rxvalue = readw( UDC_RXSTAT(ChannelSet[ch].uBulk_OUT) ); DEBUG_OUT('R'); #if 0 if ( (rxvalue & RxVOID ) != 0 ) if ( (rxvalue & RxERR ) != 0 ) if ( (rxvalue & RxURF ) != 0 ) #endif if ( (rxvalue & RxACK ) != 0 ) { // get Bulk Out byte count ChannelSet[ch].sBulkBlockSizeBuffer[ChannelSet[ch].uCurrentBulkOutBlockNum] = rxvalue & RxCNT; // step next DMA block ChannelSet[ch].uCurrentBulkOutBlockNum = ++ChannelSet[ch].uCurrentBulkOutBlockNum % uMaxBlockNumber; writew( virt_to_phy((u32_t)(ChannelSet[ch].pBulkOutBuffer + ChannelSet[ch].uCurrentBulkOutBlockNum * uBulkBlockSize)), UDC_DMALM_OADDR(ChannelSet[ch].uBulk_OUT) ); writew( ENP_DMA_START, UDC_DMACTRLO(ChannelSet[ch].uBulk_OUT) ); // loop back to Bulk Out transfer ChannelSet[ch].uLoopbackCount++; } }
// tx0 handler void process_in0() { readw( UDC_TX0STAT ); //added by Ivan Chiang 040805 if ( uControlStage == DATA_STAGE ) { // data stage //;//printf("tx0 handler uControlDataSize = %x\n",uControlDataSize); if ( uControlDataSize > 0 ) uNeedDoProcCtrlBlockNum++; else { // open OUT gate writew( readw( UDC_RX0CON ) & ~RxNAK, UDC_RX0CON ); writew( virt_to_phy((u32_t)CtrlInBuffer), UDC_DMA0LM_OADDR ); writew( ENP_DMA_START , UDC_DMA0CTLO ); uControlStage = STATUS_STAGE; } } else if ( uControlStage == STATUS_STAGE ) { // status stage, close gates writew( readw( UDC_TX0CON ) | TxNAK, UDC_TX0CON ); writew( readw( UDC_RX0CON ) | RxNAK, UDC_RX0CON ); } //DEBUG_OUT(uControlDataSize); return; }
static s32 dma_FPGAmem2ARMmem_use_acp(void) { s32 ret = ALT_E_SUCCESS; /* for DMAC PC, not cache-able */ ALT_DMA_PROGRAM_t *program = (ALT_DMA_PROGRAM_t *)AMP_SHARE_DMABUF_START; //u32 dma_phy = AMPPHY_START + 0x200000; //physical address: 0x1e200000 u32 src_phy = FPGA_SDRAM_PHYS_BASE; //source physical address for dma : offset: 0 u32 dst_phy = (SH_MEM_START + 0x200000); // destination physical address for dma: offset 0x200000 //source virtual address for mpu, cache-able, WBWA shareable u8 * src_virt = (u8 *)phy_to_virt(src_phy); // desination virtual address for mpu, cache-able, WBWA shareable u8 * dst_virt = (u8 *)phy_to_virt(dst_phy); int i, size = 0x4000; gDMAtestIrqInfoChan0.src_mpu = src_virt; gDMAtestIrqInfoChan0.dst_mpu = dst_virt; gDMAtestIrqInfoChan0.size = size; dma_use_acp_init_fpga(ALT_DMA_CHANNEL_0); memset(program, 0x0, sizeof(ALT_DMA_PROGRAM_t)); ret = alt_dma_channel_alloc(ALT_DMA_CHANNEL_0); if(ret != ALT_E_SUCCESS) { bmlog("ERROR: dma_channel_alloc error!\n"); return ret; } /* init the source memory and the destination memory for dma using ACP */ for(i = 0; i < size; i++) { src_virt[i] = i + 1; dst_virt[i] = 0x0; } dma_init_interrupt_channel0(); /* Init the dma engine's micro code PC */ program->program_phy = virt_to_phy((u32)(program->program)); ret = alt_dma_memory_to_memory(ALT_DMA_CHANNEL_0, program, (void *)(dst_phy|(0x1 << 31)), (const void *)(src_phy&(~(0x1 << 30))), size, true, ALT_DMA_EVENT_0, 1); if(ret != ALT_E_SUCCESS) { bmlog("ERROR: dma memory_to_memory acp failed!\n"); return ret; } return ret; }
static int dma_ARMmem2FPGAmem(void) { s32 ret = ALT_E_SUCCESS; /* for DMAC PC, not cache-able */ ALT_DMA_PROGRAM_t *program = (ALT_DMA_PROGRAM_t *)AMP_SHARE_DMABUF_START; u32 dma_phy = AMPPHY_START + AMPMAP_SIZE - DMABUF_SIZE; u32 src_phy = (dma_phy + 0x100000);//offset: 1MB u32 dst_phy = FPGA_SDRAM_PHYS_BASE + (FPGA_SDRAM_SIZE/2); //non-cacherable, bufferable src u8 * src_virt = (u8 *)phy_to_virt(src_phy); //non-cacherable, bufferable dest u8 * dst_virt = (u8 *)phy_to_virt(dst_phy); int i, size = 0x4000; gDMAtestIrqInfoChan0.src_mpu = src_virt; gDMAtestIrqInfoChan0.dst_mpu = dst_virt; gDMAtestIrqInfoChan0.size = size; memset(program, 0x0, sizeof(ALT_DMA_PROGRAM_t)); ret = alt_dma_channel_alloc(ALT_DMA_CHANNEL_0); if(ret != ALT_E_SUCCESS) { bmlog("ERROR: dma_channel_alloc error!\n"); return ret; } for(i = 0; i < size; i++) { src_virt[i] = i + 1; dst_virt[i] = 0x0; } dma_init_interrupt_channel0(); program->program_phy = virt_to_phy((u32)(program->program)); ret = alt_dma_memory_to_memory(ALT_DMA_CHANNEL_0, program, (void *)dst_phy, (const void *)src_phy, size, true, ALT_DMA_EVENT_0, 0); if(ret != ALT_E_SUCCESS) { bmlog("ERROR: dma memory_to_memory failed!\n"); return ret; } return ret; }
static s32 check_dma_memory_result(u8 *src, u8 *dst, int size) { while(size && size--) { if(*src != *dst) break; src++; dst++; } if(size) { bmlog("src =0x%p, *src=%u; dst = 0x%p, *dst = %u;size=%d\n", src, *src, dst, *dst, size); return ALT_E_ERROR; } else bmlog("DMA test memory(0x%x) to memory(0x%x) is ok!\n", virt_to_phy((u32)src), virt_to_phy((u32)dst)); return ALT_E_SUCCESS; }
u32_t fn_vendor_test_out0() { // ctrl-out via control pipe uControlDataSize = ___swab16 ( SetupRequestData.wLength ); writew( virt_to_phy( (u32_t)CtrlInBuffer ), UDC_DMA0LM_OADDR ); writew( ENP_DMA_START , UDC_DMA0CTLO ); // deassert RX0NAK --- let host data rush into DMA buffer writew( readw( UDC_RX0CON ) & ~RxNAK, UDC_RX0CON ); return 0; }
// rx0 handler void process_out0() { int len; if ( uControlStage == STATUS_STAGE ) { // status stage // read clear RX0ACK interrupt readw( UDC_RX0STAT ); // assert both TX0NAK, RX0NAK at status stage writew( readw( UDC_TX0CON ) | TxNAK, UDC_TX0CON ); writew( readw( UDC_RX0CON ) | RxNAK, UDC_RX0CON ); } else if ( uControlStage == DATA_STAGE ) { // data stage // read length from H/W len = readw( UDC_RX0STAT ) & RxCNT; // record received result uControlDataSize -= len; //DEBUG_OUT(uControlDataSize); // step next dma block uCurrentCtrlBlockNum = ++uCurrentCtrlBlockNum % MAX_CTRL_NUM; writew( virt_to_phy((u32_t)( CtrlInBuffer + uCurrentCtrlBlockNum * uCurrentCtrlPacketSize)), UDC_DMA0LM_OADDR ); writew( ENP_DMA_START , UDC_DMA0CTLO ); /* if ( uControlDataSize <= 0 ) { // open IN gate writew( readw( UDC_TX0CON ) & ~TX0NAK, UDC_TX0CON ); writew( 0, UDC_TX0STAT ); writew( virt_to_phy((u32_t)CtrlInBuffer) , UDC_DMA0LM_IADDR ); writew( DMA0INSTA , UDC_DMA0CTLI ); uControlStage = STATUS_STAGE; } */ } return; }
void process_setup_req() { u32_t* p; u32_t request_type; UINT ch; // channel number int i; // DEBUG_OUT('s'); bRequestError = NO; uCurrentCtrlBlockNum = 0; uNeedDoProcCtrlBlockNum = 0; uControlStage = SETUP_STAGE; if (ResetFlag == 1) { if ( IS_HIGH_SPEED() ) { ;//printf(" USB connect with HIGH Speed!\n"); bIsFullSpeed = 0; uBulkBlockSize = HI_SPEED_BULK_PACKET_SIZE; uCurrentCtrlPacketSize = HI_SPEED_CTRL_PACKET_SIZE; uCurrentBulklPacketSize = HI_SPEED_BULK_PACKET_SIZE; } else { ;//printf(" USB connect with FULL Speed!\n"); bIsFullSpeed = 1; uBulkBlockSize = FULL_SPEED_BULK_PACKET_SIZE; uCurrentCtrlPacketSize = FULL_SPEED_CTRL_PACKET_SIZE; uCurrentBulklPacketSize = FULL_SPEED_BULK_PACKET_SIZE; } uMaxBlockNumber = (BK_BUF_SIZE / uBulkBlockSize); // change device MaxPacketSize of descriptor scusbDscr[7] = uCurrentCtrlPacketSize; ResetFlag = 0; for (ch = 0; ch < NUM_OF_USB_CHANNEL; ch++) { ChannelSet[ch].uLoopbackCount = 0; ChannelSet[ch].uIntrINCount = 0; // start receive from Bulk_OUT pipe writew(virt_to_phy( (u32_t)ChannelSet[ch].pBulkOutBuffer), UDC_DMALM_OADDR(ChannelSet[ch].uBulk_OUT)); writew( ENP_DMA_START, UDC_DMACTRLO(ChannelSet[ch].uBulk_OUT)); } for (i = 0; i < NUM_OF_USB_CHANNEL; i++) ChannelSet[i].uCurrentBulkInBlockNum = ChannelSet[i].uCurrentBulkOutBlockNum = ChannelSet[i].uCurrentIntrInBlockNum = 0; } // clear previous buffer /* writew( readw( UDC_TX0CON ) | TxCLR, UDC_TX0CON ); writew( readw( UDC_TX0CON ) & ~TxCLR, UDC_TX0CON ); writew( readw( UDC_RX0CON ) | RxCLR, UDC_RX0CON ); writew( readw( UDC_RX0CON ) & ~RxCLR, UDC_RX0CON ); */ // read setup data p = (u32_t*)&SetupRequestData; *p++ = *(volatile u32_t *)UDC_SETUP1; *p = *(volatile u32_t *)UDC_SETUP2; // identify standard request request_type = GET_REQ_TYPE(SetupRequestData.bmRequestType); if (request_type == REQ_TYPE_STANDARD) { if (SetupRequestData.bRequest == GET_DESCRIPTOR ) { fn_get_descriptor(); } } else if (request_type == REQ_TYPE_CLASS ) { if (SetupRequestData.bRequest == GET_DEVICE_ID) { ;//printf("process_setup_req() - get device id!\n"); fn_get_device_id(); } } else if (request_type == REQ_TYPE_VENDOR ) { if (SetupRequestData.bRequest == VENDOR_TEST_OUT0 ) { ;//printf("process_setup_req() - vendor test out!\n"); fn_vendor_test_out0(); } else if ( SetupRequestData.bRequest == VENDOR_TEST_IN0 ) { ;//printf("process_setup_req() - vendor test in!\n"); fn_vendor_test_in0(); } } uControlStage = DATA_STAGE ; }
int USBTesting() { UINT ch; // channel number UINT TX_Status; CHAR *dma_src_addr; char Continue_test = 1; //cyli++ 01/17/07 if (IS_16_ENDPT()) { printf("16 end-points\n"); } else if (IS_10_ENDPT()) { printf("10 end-points\n"); } else if (IS_4_ENDPT()) { printf("4 end-points\n"); } else { printf("Error end-point number!\n"); printf("DEV_INFO = 0x%08x", readw(UDC_DEVINFO) & ENDPT_NUM_MASK); } // CY+ to fix program reload Socle phy hang up problem #ifdef UDC_SOCLE_PHY ASSERT_SOFT_POR(); #if 0 isr_time_value = 0; isr_waiting_time = 1; setup_1ms_timer(1); #else MSDELAY(1); #endif while (isr_time_value != isr_waiting_time); DEASSERT_SOFT_POR(); #endif #ifdef UDC_SOCLE_PHY #if 0 isr_time_value = 0; isr_waiting_time = 8; setup_1ms_timer(8); #else MSDELAY(8); #endif while (isr_time_value != isr_waiting_time); // SET_PHY_16_BIT(); #endif ResetFlag = 0; bIsConnected = VBUS_OK(); // if (bIsConnected) // printf(" -> USB VBus connect\n"); // else // printf(" -> USB VBus disconnect"); // enable interrupt INT0_ENABLE(LDK_INTC_UDC); // setup interrupt handler connectInterrupt( LDK_INTC_UDC, UDCIintHandler, NULL); INT0_SET_MASK(LDK_INTC_UDC); while (1) { // ;printf("\n USB cable disconnected!\n"); SOFT_DISCONNECT(); // wait for plugin stable on vbus // printf("\nWait for USB Host connect..."); // while ( !bIsConnected ); //CY++ for checking USB Host connect waiting int wait=0; while ( !bIsConnected ){ MSDELAY(60); printf("%4d", wait); wait++; if(wait > 100) return USB_NO_CONNECT_ERROR; printf("\b\b\b\b"); } #ifdef UDC_SOCLE_PHY ASSERT_SOFT_POR(); #if 0 isr_time_value = 0; isr_waiting_time = 1; setup_1ms_timer(1); #else MSDELAY(1); #endif while (isr_time_value != isr_waiting_time); DEASSERT_SOFT_POR(); #endif #ifdef UDC_SOCLE_PHY #if 0 isr_time_value = 0; isr_waiting_time = 8; setup_1ms_timer(8); #else MSDELAY(8); #endif while (isr_time_value != isr_waiting_time); // SET_PHY_16_BIT(); #endif initUDCController(); // initialize UDC Controller initUDCTestingEnv(); // initialize UDC testing environment SOFT_CONNECT(); ;//printf("\n USB cable connected!\n"); uNeedDoProcCtrlBlockNum = 0; while ( bIsConnected ) { // check ENP 0 transmit request if ( uNeedDoProcCtrlBlockNum > 0 ) { int dma_size; // dma done now, polling for empty data set if (!( readw(UDC_TX0BUF) & TxFULL)) { // critical section DisableInterrupt(); uNeedDoProcCtrlBlockNum--; dma_src_addr = CtrlInBuffer + uCurrentCtrlBlockNum++ * uCurrentCtrlPacketSize; if ( uControlDataSize > uCurrentCtrlPacketSize ) { dma_size = uCurrentCtrlPacketSize; } else { dma_size = uControlDataSize; } // calculate remaining bytes need transfer uControlDataSize -= dma_size; writew( dma_size, UDC_TX0STAT ); writew( virt_to_phy((u32_t)dma_src_addr) , UDC_DMA0LM_IADDR ); writew( ENP_DMA_START , UDC_DMA0CTLI ); EnableInterrupt(); // set ACK--after we have overwritten the previously incorrect data writew( readw( UDC_TX0CON ) & ~TxNAK, UDC_TX0CON ); } } if (Continue_test){ printf("Done\n"); printf("USB initialize...Done\n"); printf("HandShaking...Done\n"); printf("Waiting for Bulk Read/Write test...\n"); printf("Remove Socle USB Bulk device Hardware from Windows and USB cable to Exit !!!\n"); Continue_test = 0; } // check channel group transmit request for (ch = 0; ch < NUM_OF_USB_CHANNEL; ch++) { // check each Bulk_IN End Point transmit request if ( ChannelSet[ch].uLoopbackCount > 0 ) { if (ChannelSet[ch].bBulkDMAOnGoing == false) { // check buffer is available for transmit data TX_Status = readw(UDC_TXBUF(ChannelSet[ch].uBulk_IN)); // get buffer status if ((TX_Status & TxFULL) == 0) { #if 0 if ((TX_Status & TxDS0) == 0) DEBUG_OUT('0'); if ((TX_Status & TxDS1) == 0) DEBUG_OUT('1'); #endif //DEBUG_OUT('i'); // enter critical section, protect share variable DisableInterrupt(); //DEBUG_OUT('+'); ChannelSet[ch].uLoopbackCount--; // get transmit buffer address & move buffer to next position dma_src_addr = ChannelSet[ch].pBulkInBuffer + ChannelSet[ch].uCurrentBulkInBlockNum * uBulkBlockSize; // setup DMA writew( ChannelSet[ch].sBulkBlockSizeBuffer[ChannelSet[ch].uCurrentBulkInBlockNum], UDC_TXSTAT(ChannelSet[ch].uBulk_IN) ); // write transmit count writew( virt_to_phy((u32_t)dma_src_addr), // set transmit buffer pointer UDC_DMALM_IADDR(ChannelSet[ch].uBulk_IN) ); writew( ENP_DMA_START , UDC_DMACTRLI(ChannelSet[ch].uBulk_IN) ); // start transmit DMA // move to next buffer ChannelSet[ch].uCurrentBulkInBlockNum = ++ChannelSet[ch].uCurrentBulkInBlockNum % uMaxBlockNumber; #if 0 WAIT_DMA_DONE(UDC_TXSTAT(ChannelSet[ch].uBulk_IN)); #endif #if 0 for (delay = 0; delay < 1000; delay++) { TX2_DMAOnGoing = true; } #endif ChannelSet[ch].bBulkDMAOnGoing = true; //DEBUG_OUT('-'); EnableInterrupt(); // leave critical section } } } // check each Intr_IN End Point transmit request if ( ChannelSet[ch].uIntrINCount > 0 ) { // if (!( readw(UDC_TXBUF(ChannelSet[ch].uIntr_IN)) & TxFULL)) { if (ChannelSet[ch].bIntrDMAOnGoing == false) { // critical section DisableInterrupt(); ChannelSet[ch].uCurrentIntrInBlockNum--; dma_src_addr = ChannelSet[ch].pIntrInBuffer + ChannelSet[ch].uCurrentIntrInBlockNum * INTR_BLOCK_SIZE; EnableInterrupt(); writew( INTR_BLOCK_SIZE, UDC_TXSTAT(ChannelSet[ch].uIntr_IN) ); writew( virt_to_phy((u32_t)dma_src_addr), UDC_DMALM_IADDR(ChannelSet[ch].uIntr_IN) ); writew( ENP_DMA_START, UDC_DMACTRLI(ChannelSet[ch].uIntr_IN) ); ChannelSet[ch].bIntrDMAOnGoing = true; #if 0 WAIT_DMA_DONE(UDC_DMACTRLI(ChannelSet[ch].uIntr_IN) ); #endif ChannelSet[ch].uCurrentBulkInBlockNum = ++ChannelSet[ch].uCurrentBulkInBlockNum % MAX_INTR_NUM; } } } } // CY+ for disconnect detect and exit testing program printf ("USB Host disconnected !!!\n"); printf ("Press Y to continue and any other Key to exit? "); char i; i=getchar(); if((i!='Y')&&(i!='y')) { printf ("\n"); return UPF_TEST_SUCCESS; } else Continue_test = 1; } // leave usb test now, should never been here return USB_UNKONW_ERROR; }
int USBTesting() { UINT ch; // channel number UINT TX_Status; CHAR *dma_src_addr; #ifdef UDC_SOCLE_PHY ASSERT_SOFT_POR(); #if 0 isr_time_value = 0; isr_waiting_time = 1; setup_1ms_timer(1); #else MSDELAY(1); #endif while (isr_time_value != isr_waiting_time); DEASSERT_SOFT_POR(); #endif #ifdef UDC_SOCLE_PHY #if 0 isr_time_value = 0; isr_waiting_time = 8; setup_1ms_timer(8); #else MSDELAY(8); #endif while (isr_time_value != isr_waiting_time); // SET_PHY_16_BIT(); #endif ResetFlag = 0; bIsConnected = VBUS_OK(); // if (bIsConnected) // printf(" -> USB VBus connect\n"); // else // printf(" -> USB VBus disconnect"); // enable interrupt INT0_ENABLE(LDK_INTC_UDC); // setup interrupt handler connectInterrupt( LDK_INTC_UDC, UDCIintHandler, NULL); INT0_SET_MASK(LDK_INTC_UDC); while (1) { // ;printf("\n USB cable disconnected!\n"); SOFT_DISCONNECT(); // wait for plugin stable on vbus printf("\nWait for USB Host connect..."); // while ( !bIsConnected ); //CY++ for checking USB Host connect waiting int wait=0; while ( !bIsConnected ){ MSDELAY(60); printf("%4d", wait); wait++; if(wait > 100) return USB_NO_CONNECT_ERROR; printf("\b\b\b\b"); } #ifdef UDC_SOCLE_PHY ASSERT_SOFT_POR(); #if 0 isr_time_value = 0; isr_waiting_time = 1; setup_1ms_timer(1); #else MSDELAY(1); #endif while (isr_time_value != isr_waiting_time); DEASSERT_SOFT_POR(); #endif #ifdef UDC_SOCLE_PHY #if 0 isr_time_value = 0; isr_waiting_time = 8; setup_1ms_timer(8); #else MSDELAY(8); #endif while (isr_time_value != isr_waiting_time); // SET_PHY_16_BIT(); #endif initUDCController(); // initialize UDC Controller initUDCTestingEnv(); // initialize UDC testing environment SOFT_CONNECT(); ;//printf("\n USB cable connected!\n"); uNeedDoProcCtrlBlockNum = 0; for (ch = 0; ch < NUM_OF_USB_CHANNEL; ch++) { ChannelSet[ch].uLoopbackCount = 0; ChannelSet[ch].uIntrINCount = 0; // start receive from Bulk_OUT pipe writew(virt_to_phy( (u32_t)ChannelSet[ch].pBulkOutBuffer), UDC_DMALM_OADDR(ChannelSet[ch].uBulk_OUT)); writew( ENP_DMA_START, UDC_DMACTRLO(ChannelSet[ch].uBulk_OUT)); } while ( bIsConnected ) { // check ENP 0 transmit request if ( uNeedDoProcCtrlBlockNum > 0 ) { int dma_size; // dma done now, polling for empty data set if (!( readw(UDC_TX0BUF) & TxFULL)) { // critical section DisableInterrupt(); uNeedDoProcCtrlBlockNum--; dma_src_addr = CtrlInBuffer + uCurrentCtrlBlockNum++ * uCurrentCtrlPacketSize; if ( uControlDataSize > uCurrentCtrlPacketSize ) { dma_size = uCurrentCtrlPacketSize; } else { dma_size = uControlDataSize; } // calculate remaining bytes need transfer uControlDataSize -= dma_size; writew( dma_size, UDC_TX0STAT ); writew( virt_to_phy((u32_t)dma_src_addr) , UDC_DMA0LM_IADDR ); writew( ENP_DMA_START , UDC_DMA0CTLI ); EnableInterrupt(); // set ACK--after we have overwritten the previously incorrect data writew( readw( UDC_TX0CON ) & ~TxNAK, UDC_TX0CON ); } } // check channel group transmit request for (ch = 0; ch < NUM_OF_USB_CHANNEL; ch++) { // check each Bulk_IN End Point transmit request if ( ChannelSet[ch].uLoopbackCount > 0 ) { if (ChannelSet[ch].bBulkDMAOnGoing == false) { // check buffer is available for transmit data TX_Status = readw(UDC_TXBUF(ChannelSet[ch].uBulk_IN)); // get buffer status if ((TX_Status & TxFULL) == 0) { #if 0 if ((TX_Status & TxDS0) == 0) DEBUG_OUT('0'); if ((TX_Status & TxDS1) == 0) DEBUG_OUT('1'); #endif //DEBUG_OUT('i'); // enter critical section, protect share variable DisableInterrupt(); //DEBUG_OUT('+'); ChannelSet[ch].uLoopbackCount--; // get transmit buffer address & move buffer to next position dma_src_addr = ChannelSet[ch].pBulkInBuffer + ChannelSet[ch].uCurrentBulkInBlockNum * uBulkBlockSize; // setup DMA writew( ChannelSet[ch].sBulkBlockSizeBuffer[ChannelSet[ch].uCurrentBulkInBlockNum], UDC_TXSTAT(ChannelSet[ch].uBulk_IN) ); // write transmit count writew( virt_to_phy((u32_t)dma_src_addr), // set transmit buffer pointer UDC_DMALM_IADDR(ChannelSet[ch].uBulk_IN) ); writew( ENP_DMA_START , UDC_DMACTRLI(ChannelSet[ch].uBulk_IN) ); // start transmit DMA // move to next buffer ChannelSet[ch].uCurrentBulkInBlockNum = ++ChannelSet[ch].uCurrentBulkInBlockNum % uMaxBlockNumber; #if 0 WAIT_DMA_DONE(UDC_TXSTAT(ChannelSet[ch].uBulk_IN)); #endif #if 0 for (delay = 0; delay < 1000; delay++) { TX2_DMAOnGoing = true; } #endif ChannelSet[ch].bBulkDMAOnGoing = true; //DEBUG_OUT('-'); EnableInterrupt(); // leave critical section } } } // check each Intr_IN End Point transmit request if ( ChannelSet[ch].uIntrINCount > 0 ) { // if (!( readw(UDC_TXBUF(ChannelSet[ch].uIntr_IN)) & TxFULL)) { if (ChannelSet[ch].bIntrDMAOnGoing == false) { // critical section DisableInterrupt(); ChannelSet[ch].uCurrentIntrInBlockNum--; dma_src_addr = ChannelSet[ch].pIntrInBuffer + ChannelSet[ch].uCurrentIntrInBlockNum * INTR_BLOCK_SIZE; EnableInterrupt(); writew( INTR_BLOCK_SIZE, UDC_TXSTAT(ChannelSet[ch].uIntr_IN) ); writew( virt_to_phy((u32_t)dma_src_addr), UDC_DMALM_IADDR(ChannelSet[ch].uIntr_IN) ); writew( ENP_DMA_START, UDC_DMACTRLI(ChannelSet[ch].uIntr_IN) ); ChannelSet[ch].bIntrDMAOnGoing = true; #if 0 WAIT_DMA_DONE(UDC_DMACTRLI(ChannelSet[ch].uIntr_IN) ); #endif ChannelSet[ch].uCurrentBulkInBlockNum = ++ChannelSet[ch].uCurrentBulkInBlockNum % MAX_INTR_NUM; } } } } } // leave usb test now, should never been here return 0; }