BOOL PXA271_USB_Driver::StartOutput( USB_CONTROLLER_STATE* State, int endpoint ) { ASSERT( State ); ASSERT(endpoint < c_Used_Endpoints); GLOBAL_LOCK(irq); // If endpoint is not an output if( State->Queues[endpoint] == NULL || !State->IsTxQueue[endpoint] ) return FALSE; /* if the halt feature for this endpoint is set, then just clear all the characters */ if(State->EndpointStatus[endpoint] & USB_STATUS_ENDPOINT_HALT) { ClearTxQueue( State, endpoint ); return TRUE; } //If TxRunning, interrupts will drain the queue if(!g_PXA271_USB_Driver.TxRunning[endpoint]) { g_PXA271_USB_Driver.TxRunning[endpoint] = TRUE; // Calling both TxPacket & EP_TxISR in this routine could cause a TX FIFO overflow TxPacket( State, endpoint ); } else if(irq.WasDisabled()) { PXA271_USB& USB = PXA271::USB(); // This could be called during Flush with all interrupts off. Just taking care of the endpoint // in question may cause a logjam if the host is expecting a response from another endpoint. // All endpoints must be examined for activity. if( USB.UDCISR0 & USB.UDCICR0 & USB.UDCICR__BOTH ) // If endpoint 0 needs attention EP0_ISR( 0 ); for( int ep = 1; ep < c_Used_Endpoints; ep++ ) { // If no interrupt for this endpoint if( (((USB.UDCISR0 & USB.UDCICR0) >> (ep * 2)) & USB.UDCICR__BOTH) == 0 ) continue; if(State->Queues[ep]) { if( State->IsTxQueue[endpoint] ) EP_TxISR( endpoint ); else EP_RxISR( endpoint ); } } }
BOOL AT91_USBHS_Driver::StartOutput( USB_CONTROLLER_STATE* State, int endpoint ) { ASSERT(State); ASSERT(endpoint < c_Used_Endpoints); GLOBAL_LOCK(irq); struct AT91_UDPHS *pUdp = (struct AT91_UDPHS *) AT91C_BASE_UDP; // If endpoint is not an output if( State->Queues[endpoint] == NULL || !State->IsTxQueue[endpoint] ) return FALSE; pUdp->UDPHS_IEN |= 1 << SHIFT_INTERUPT << endpoint; pUdp->UDPHS_EPT[endpoint].UDPHS_EPTCTLENB = AT91C_UDPHS_TX_PK_RDY; /* if the halt feature for this endpoint is set, then just clear all the characters */ if(g_AT91_USBHS_Driver.EndpointStatus[endpoint] & USB_STATUS_ENDPOINT_HALT) { ClearTxQueue( State, endpoint ); return TRUE; } //If TxRunning, interrupts will drain the queue if(!(BOOL)((UINT8)g_AT91_USBHS_Driver.TxRunning[endpoint])) { num_ep_int1++; g_AT91_USBHS_Driver.TxRunning[endpoint] = TRUE; TxPacket( State, endpoint ); } else if(irq.WasDisabled()) // We should not call EP_TxISR after calling TxPacket becuase it can cause a TX FIFO overflow error. { Endpoint_ISR(endpoint); } return TRUE; }