⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sc2413pdd.cpp-ori

📁 支持三星原产的S3C2413开发板
💻 CPP-ORI
📖 第 1 页 / 共 5 页
字号:
					)
{
	SETFNAME();
	FUNCTION_ENTER_MSG();

	ValidateContext(pContext);
	DEBUGCHK(pContext->fRunning);

	BOOL fNotify = FALSE;
	DWORD dwPendingEvents=0;
	EP_STATUS *peps = GetEpStatus(pContext, dwEndpoint);
	PREFAST_DEBUGCHK(peps);

	LOCK_ENDPOINT(peps);
	DWORD dwEndPoint = peps->dwEndPointNumber;

	if (dwEndpoint == 0){
		BYTE bEP0IrqStatus = ReadIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET);

		// The Setup Token is handled in HandleUSBEvents()
		// Handle End Of Status Packet (Zero Length Data 
		// Packet

		// Note that the SETUP TOKEN is decoded in Ufn_Read to 
		// determine if a GET_ or SET_ command is coming. That decoding 
		// sets the initial State Machine State to   
		// EP0_STATE_OUT_DATA_PHASE or EP0_STATE_IN_DATA_PHASE
		DWORD bWordCount = ReadIndexedReg(pContext, dwEndpoint, OUT_FIFO_CNT1_REG_OFFSET);
		switch(peps->dwEpState) {
		   case EP0_STATE_OUT_DATA_PHASE:
			   // Check For out packet read && receive fifo not empty -> out token event
			   if ( (bEP0IrqStatus & EP0_OUT_PACKET_RDY) && (bWordCount) ){
				   DEBUGMSG(ZONE_RECEIVE, (_T("%s out token packet on endpoint 0 \r\n"), pszFname));				
				   dwPendingEvents |= OUT_TRANSFER;
			   }
			   // status stage of control transfer; zero-length packet received
			   else if ( (bEP0IrqStatus & EP0_OUT_PACKET_RDY) && ( bWordCount == 0) ){					 
				   DEBUGMSG(ZONE_RECEIVE, (_T("%s status stage of control transfer on endpoint 0; UDCCS0 = 0x%x \r\n"), pszFname, bEP0IrqStatus));
				   // clear OPR by writing a 1 to SO bit					   
				   peps->dwEpState = EP_STATE_IDLE; 
				   SetClearIndexedReg(pContext,0,EP0_CSR_REG_OFFSET, DATA_END | SERVICED_OUT_PKY_RDY,SET);   // 050827
//				   SetClearIndexedReg(pContext,0,EP0_CSR_REG_OFFSET, SERVICED_OUT_PKY_RDY,SET);
			   }
			   break;

			   // IN Data Phase and IPR is cleared 
		   case  EP0_STATE_IN_DATA_PHASE: 
			   // Check For status stage - End control transfer; zero-length packet received
			   if ( (bEP0IrqStatus &  EP0_OUT_PACKET_RDY) && ( bWordCount == 0) ) {
				   dwPendingEvents = IN_TRANSFER;
				   DEBUGMSG(ZONE_SEND, (_T("%s In - end xfer; UDCCS0 = 0x%x \r\n"), pszFname, bEP0IrqStatus));
			   }
			   else if ((bEP0IrqStatus &  EP0_IN_PACKET_RDY) == 0) {
				   dwPendingEvents = IN_TRANSFER;
			   }
			   
			   DEBUGMSG(ZONE_SEND, (_T("%s Data Phase In Token\r\n"), pszFname));
			   break;

		   default:	// EP_STATE_IDLE
			   // During Normal ACK/NAK This State should never happen but it will
			   // Force the State Machine into a known State if it does
//			   RETAILMSG(1, (TEXT("<EP_STATE_IDLE(0x%x)>"), peps->dwEpState));
			   peps->dwEpState = EP_STATE_IDLE;  
			   DEBUGMSG(ZONE_FUNCTION, (_T("%s EP0 Status =  %x \r\n"), 
				   pszFname, bEP0IrqStatus ));
			   break;				   
		}

		DEBUGMSG(ZONE_FUNCTION, (_T("%s EP State =  %u \r\n"), pszFname, peps->dwEpState ));
		DEBUGMSG(ZONE_FUNCTION, (_T("%s HE EP0 Status = %x,%u \r\n"), pszFname, bEP0IrqStatus, peps->dwEpState ));
	}
	else { // Any endpoint other than 0
		BYTE bEpIrqStat;

		if (peps->dwDirectionAssigned == USB_IN_TRANSFER){
			bEpIrqStat = ReadIndexedReg(pContext, dwEndPoint,IN_CSR1_REG_OFFSET);
			DEBUGMSG(ZONE_FUNCTION, (_T("%s HE EPIN Status = %x\r\n"), pszFname, bEpIrqStat));

			// Stall "acknowledged" from Host
			if (bEpIrqStat & IN_SENT_STALL) 
			{
				RETAILMSG(1, (TEXT("[ISS]")));
				USB_DEVICE_REQUEST udr;
				udr.bmRequestType = USB_REQUEST_FOR_ENDPOINT;
				udr.bRequest =USB_REQUEST_CLEAR_FEATURE;
				udr.wValue = USB_FEATURE_ENDPOINT_STALL;
				udr.wIndex = USB_ENDPOINT_DIRECTION_MASK | (BYTE) dwEndpoint;
				udr.wLength =0;

				DisableEndpointInterrupt(pContext, dwEndpoint);

				DEBUGMSG(ZONE_PIPE, (_T("%s Got SST EP%u \r\n"), 
					pszFname, dwEndpoint));

				pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);
				// Must Clear both Send and Sent Stall
				SetClearIndexedReg(pContext, dwEndpoint, IN_CSR1_REG_OFFSET, (IN_SEND_STALL), SET);
//				SetClearIndexedReg(pContext, dwEndpoint, IN_CSR1_REG_OFFSET, (IN_SEND_STALL | IN_SENT_STALL), CLEAR);
			}
			
			if (!(bEpIrqStat & IN_PACKET_READY)) {// If Transmit Complete 
				// send another
				DEBUGMSG(ZONE_SEND, (_T("%s transmit packet complete on endpoint %u \r\n"), 
					pszFname, dwEndpoint));
				dwPendingEvents = IN_TRANSFER;
			}

			DEBUGMSG(ZONE_FUNCTION, (_T("%s End EPIn Status =  %x \r\n"),
				pszFname, bEpIrqStat));
		}
		else {
			bEpIrqStat = ReadIndexedReg(pContext, dwEndPoint, OUT_CSR1_REG_OFFSET);
			// Stall "acknowledged" from Host
			if (bEpIrqStat & OUT_SENT_STALL) {
				RETAILMSG(1, (TEXT("[OSS]")));
				USB_DEVICE_REQUEST udr;
				udr.bmRequestType = USB_REQUEST_FOR_ENDPOINT;
				udr.bRequest =USB_REQUEST_CLEAR_FEATURE;
				udr.wValue = USB_FEATURE_ENDPOINT_STALL;
				udr.wIndex = (BYTE) dwEndpoint;
				udr.wLength =0;
				DisableEndpointInterrupt(pContext, dwEndpoint);
				DEBUGMSG(ZONE_FUNCTION, (_T("%s Got SST EP%u \r\n"), pszFname, dwEndpoint));
				pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);
				SetClearIndexedReg(pContext, dwEndpoint, OUT_CSR1_REG_OFFSET, (OUT_SEND_STALL | OUT_SENT_STALL), CLEAR);
			}
			
			// receive packet complete && receive fifo not empty -> out token + data rx event
			if (bEpIrqStat & OUT_PACKET_READY) {
				DEBUGMSG(ZONE_RECEIVE, (_T("%s received packet complete on endpoint %u \r\n"), 
					pszFname, dwEndpoint ));
				// the UDC combines the OUT token event with the Data RX event
				dwPendingEvents = OUT_TRANSFER;
			}

			DEBUGMSG(ZONE_FUNCTION, (_T("%s End EPOut Status =  %x \r\n"),
				pszFname, bEpIrqStat ));
		}   
	}

	if (dwPendingEvents & IN_TRANSFER) {
//		RETAILMSG(1,(TEXT("PI ")));		// 050828
		HandleTx(pContext, peps, 0);
	}
	else if (dwPendingEvents & OUT_TRANSFER) {
//		RETAILMSG(1,(TEXT("PO ")));		// 050828
		HandleRx(pContext, peps);
	}

	FUNCTION_LEAVE_MSG();
	UNLOCK_ENDPOINT(peps);
}



// Process a SC2413 interrupt.
static
VOID
HandleUSBEvent(
			   PCTRLR_PDD_CONTEXT pContext
			   )
{
	SETFNAME();
	FUNCTION_ENTER_MSG();
	ValidateContext(pContext);

	EP_STATUS *peps  = GetEpStatus(pContext, 0);

	BYTE bEpIrqStat = ReadReg(pContext, EP_INT_REG_OFFSET);
	BYTE bUSBBusIrqStat = ReadReg(pContext, USB_INT_REG_OFFSET);
	
#if RNDIS==1
//	static BYTE EP0_OUT_MORE_DATA = FALSE;
	static USHORT EP0_TOTAL_OUT_LEN = 0;
#endif
//	RETAILMSG(1,(TEXT("%x "),bEpIrqStat));			// 050828
#if 0
	RETAILMSG(1, (TEXT("%x,%x\n"),ReadReg(pContext, USB_INT_REG_OFFSET),ReadReg(pContext, USB_INT_EN_REG_OFFSET)));
	RETAILMSG(1, (TEXT("%x,%x\n"),ReadReg(pContext, IDXADDR_REG_OFFSET),ReadReg(pContext, EP0_CSR_REG_OFFSET)));
	RETAILMSG(1, (TEXT("%x,%x\n"),ReadReg(pContext, IN_CSR1_REG_OFFSET),ReadReg(pContext, IN_CSR2_REG_OFFSET)));
	RETAILMSG(1, (TEXT("%x,%x\n"),ReadReg(pContext, OUT_CSR1_REG_OFFSET),ReadReg(pContext, OUT_CSR2_REG_OFFSET)));
	RETAILMSG(1, (TEXT("%x,%x\n\n"),ReadReg(pContext, OUT_FIFO_CNT1_REG_OFFSET),ReadReg(pContext,OUT_FIFO_CNT2_REG_OFFSET)));	
#endif	
	if (bUSBBusIrqStat & USB_SUSPEND_INTR) {
		//RETAILMSG(1, (TEXT("USB_SUSPEND_INTR \r\n")));
		
		WriteReg(pContext, USB_INT_REG_OFFSET, USB_SUSPEND_INTR);
		
		SetClearReg(pContext, PWR_REG_OFFSET, SUSPEND_MODE_ENABLE_CTRL, CLEAR);
		// Disable the interrupt
		SetClearReg(pContext, USB_INT_EN_REG_OFFSET, USB_SUSPEND_INTR, CLEAR);

		// Enable resume interrupt
//		SetClearReg(pContext, USB_INT_EN_REG_OFFSET, USB_RESET_INTR, CLEAR);		// 050827

		if (pContext->attachedState == UFN_ATTACH) {
			RETAILMSG(1, (_T("Suspend\r\n")));
			pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_SUSPEND);
			g_wCurrentState = UFN_SUSPEND;
		}
	}
	else if ( (g_wCurrentState == UFN_SUSPEND && bUSBBusIrqStat & USB_RESET_INTR) || (bUSBBusIrqStat & USB_RESUME_INTR) ) {
		RETAILMSG(1, (TEXT("USB_RESUME_INTR:0x%x,0x%x \r\n"),bUSBBusIrqStat,g_wCurrentState));	// 050827

		if ( bUSBBusIrqStat & USB_RESUME_INTR )
			WriteReg(pContext, USB_INT_REG_OFFSET, USB_RESUME_INTR);
		
//		if ( bUSBBusIrqStat & USB_RESET_INTR )
//			WriteReg(pContext, USB_INT_REG_OFFSET, USB_RESET_INTR);

		// Disable the interrupt
//		SetClearReg(pContext, USB_INT_EN_REG_OFFSET, USB_RESUME_INTR, CLEAR);

		// Enable suspend interrupt
		SetClearReg(pContext, USB_INT_EN_REG_OFFSET, USB_SUSPEND_INTR, SET);

		if (pContext->attachedState == UFN_ATTACH) {
			RETAILMSG(1, (_T("Resume\r\n")));
			pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_RESUME);
			g_wCurrentState = UFN_RESUME;			// 050827
		}
		
	}
	else if (bUSBBusIrqStat & USB_RESET_INTR) {
		RETAILMSG(1, (TEXT("USB_RESET_INTR \r\n")));
		#if RNDIS==1
		EP0_TOTAL_OUT_LEN = 0;
		#endif
//		peps->dwEpState = EP_STATE_IDLE;
//		pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_RESET);
		pContext->fSpeedReported = FALSE;
		WriteReg(pContext, USB_INT_REG_OFFSET, USB_RESET_INTR);
		// If the cable was connected to a host at boot, the attach interrupt
		// will be missed. Generate it here.
		if (pContext->attachedState == UFN_ATTACH) {
			pContext->pfnNotify(pContext->pvMddContext,
				UFN_MSG_BUS_EVENTS, UFN_DETACH);
			pContext->attachedState = UFN_DETACH;
			g_wCurrentState = UFN_DETACH;
		}

		if (pContext->attachedState == UFN_DETACH){
			pContext->pfnNotify(pContext->pvMddContext,
				UFN_MSG_BUS_EVENTS, UFN_ATTACH);
			pContext->attachedState = UFN_ATTACH;
			g_wCurrentState = UFN_ATTACH;
		}

		peps->dwEpState = EP_STATE_IDLE;
		pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_EVENTS, UFN_RESET);

		// Enable the Suspend interrupt...
		SetClearReg(pContext, USB_INT_EN_REG_OFFSET, USB_SUSPEND_INTR, SET);

		SetClearReg(pContext, PWR_REG_OFFSET, SUSPEND_MODE_ENABLE_CTRL, SET);
		DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Reset\r\n"), pszFname));
	}

	// Setup Token Processing

	if (bEpIrqStat & EP0_INT_INTR) {
//		RETAILMSG(1, (TEXT("[EP0]")));
		//Read the Ep0 Interrupt Status Register
		BYTE bEP0IrqStatus = ReadIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET);

		DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Status, %x\r\n"), pszFname, bEP0IrqStatus));

		if (bEP0IrqStatus & SETUP_END) {
//			RETAILMSG(1, (TEXT("[SE]")));
			SetClearIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET, SERVICED_SETUP_END, SET);

			peps->dwEpState = EP_STATE_IDLE;
			PSTransfer pTransfer = peps->pTransfer;

			// Make MDD think everything is ok. Host will retry last packet
			if(pTransfer) {
				CompleteTransfer(pContext, peps, UFN_NO_ERROR);
			}

			// The HW does not seem to work correctly. It takes some time to 
			// clear the setup end before the Setup Toke is correctly acked and
			// The Word Count register is loaded (note that opr is normally set here
			// during the same ISR pass as well. The HW manual says 
			// to unload the packet if opr is set as well. This time was 
			// determined experimentally
			StallExecution(100); // Wait for HW To clear SE

			DEBUGMSG(ZONE_USB_EVENTS, (_T("%s Setup End, %x\r\n"), 
				pszFname, bEP0IrqStatus));

			bEP0IrqStatus &= ~SETUP_END;
		}

		// Set By USB if protocoll violation detected
		if (bEP0IrqStatus & EP0_SENT_STALL) {
			RETAILMSG(1, (TEXT("[SS]")));
			USB_DEVICE_REQUEST udr;
			udr.bmRequestType = USB_REQUEST_FOR_ENDPOINT;
			udr.bRequest =USB_REQUEST_CLEAR_FEATURE;
			udr.wValue = USB_FEATURE_ENDPOINT_STALL; 
			udr.wIndex = 0; // Ep 0
			udr.wLength =0;
			pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);

			// Must Clear both Send and Sent Stall
			SetClearIndexedReg(pContext,0, EP0_CSR_REG_OFFSET, (EP0_SEND_STALL | EP0_SENT_STALL), CLEAR);

			peps->dwEpState = EP_STATE_IDLE;
			bEP0IrqStatus &= ~EP0_SENT_STALL;
		}
		
		const DWORD dwSetupPacketSize = ReadIndexedReg(pContext, 0, OUT_FIFO_CNT1_REG_OFFSET);
		
		// If a new Command receieved
#if RNDIS==1
		if ((bEP0IrqStatus & EP0_OUT_PACKET_RDY) && (EP0_TOTAL_OUT_LEN == 0)) {	
#else
		if (bEP0IrqStatus & EP0_OUT_PACKET_RDY) {
#endif			
			BOOL  fUdrValid = TRUE;  // Indicate whether or not UDR was correctly 
			// decoded

			USB_DEVICE_REQUEST udr;
			udr.wLength = 0;										 
			DWORD dwBytesRead;
			PBYTE pbUdr = (PBYTE) &udr;
			volatile ULONG *pulFifoReg = _GetDataRegister(0);

			for (dwBytesRead = 0; dwBytesRead < dwSetupPacketSize; dwBytesRead++) {
				pbUdr[dwBytesRead] = (UCHAR) *pulFifoReg;
			}

			// Parse the Setup Command this is necessary to Configure the 
			// SW State Machine and to set bits to enable the HW to 
			// ACK/NAK correctly.		
			if (fUdrValid) {
				// Determine if this is a NO Data Packet
				if (udr.wLength > 0) {
					// Determine transfer Direction
					if (udr.bmRequestType & USB_ENDPOINT_DIRECTION_MASK) {
						// Start the SW OUT State Machine
						peps->dwEpState = EP0_STATE_IN_DATA_PHASE;					  
					}
					else {
						// Start the SW OUT State Machine
						peps->dwEpState = EP0_STATE_OUT_DATA_PHASE; 
					}
				}
				else if ( (udr.bmRequestType  != USB_REQUEST_STANDARD) &&
						  (udr.bmRequestType  != USB_REQUEST_FOR_ENDPOINT)  ) { 
					// Is it a Standard, Class, Vendor or Reserved Command
					// The UDC HW needs the IPR bit set accordingly
					// If it is No Data  - Vendor, Class or Reserved Command 

					// ClientDriver will issue a SendControlStatusHandshake to 
					// complete the transaction.

					// Nothing left to do... transition to IDLE.
					peps->dwEpState = EP_STATE_IDLE;			  
				}
				else { // Make sure the IPR Bit is Clear
					// Must be 
					//	(udr->wLength == 0) &&
					//	(udr->bmRequestType  == USB_REQUEST_STANDARD)
					SetClearIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET, EP0_IN_PACKET_RDY, CLEAR);
				}
			}
			else {
				RETAILMSG(1, (_T("%s Udr Invalid\r\n"), 
					pszFname));

				// Udr read from the FIFO was invalid 
				// Ideally this should not hapen. This is a recovery mechanism if 
				// we get out of sync somehow.  

				// Client won't care and will see a reset to clean things up

				SetClearIndexedReg(pContext, 0, OUT_CSR1_REG_OFFSET,
					DATA_END | SERVICED_OUT_PKY_RDY, SET);

				DEBUGCHK(FALSE);
				fUdrValid = FALSE;
			}
#if RNDIS==1
			if(peps->dwEpState == EP0_STATE_OUT_DATA_PHASE)
			{
				if (udr.wLength != 0)
					EP0_TOTAL_OUT_LEN = udr.wLength;
				else
					EP0_TOTAL_OUT_LEN = 0;
			}
#endif
			if (fUdrValid) {
				// Only clear OPR if sending data back - else it will be done in 
				// ControlStatusHandshake
//				RETAILMSG(1, (TEXT("[0x%x]"), udr.wLength));

				if(udr.wLength == 0){
					pContext->sendDataEnd = TRUE;
				}
				else {
					// Clear Out Packet Ready - receive FIFO should be empty
					SetClearIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET, SERVICED_OUT_PKY_RDY, SET);
					pContext->sendDataEnd = FALSE;
				}

				if (pContext->fSpeedReported == FALSE) {
					// After Every Reset Notify MDD of Speed setting.
					// This device can only support FULL Speed.
					pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_BUS_SPEED, BS_FULL_SPEED);
					pContext->fSpeedReported = TRUE;
				}

				pContext->pfnNotify(pContext->pvMddContext, UFN_MSG_SETUP_PACKET, (DWORD) &udr);
			}

			bEP0IrqStatus &= ~EP0_OUT_PACKET_RDY;
		}
#if RNDIS==1   
		else if ((bEP0IrqStatus & EP0_OUT_PACKET_RDY) && (EP0_TOTAL_OUT_LEN != 0) )		// 050827
		{
			HandleEndpointEvent(pContext, 0, bEP0IrqStatus);
			EP0_TOTAL_OUT_LEN -= (USHORT)dwSetupPacketSize;
		}
#endif
		// If Out Packet ready and No Data then must be an End Transfer 
		else if ( (bEP0IrqStatus & EP0_OUT_PACKET_RDY) && (dwSetupPacketSize == 0) ) {
			// Update the register - Clear OPR, Set DE
			SetClearIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET, DATA_END | SERVICED_OUT_PKY_RDY, SET);

			peps->dwEpState = EP_STATE_IDLE;			 
			DEBUGMSG(ZONE_RECEIVE, (_T("%s End Xfer \r\n"), pszFname));
		}
		else {
			HandleEndpointEvent(pContext, 0, bEP0IrqStatus);
		}

#if 1
		bEP0IrqStatus = ReadIndexedReg(pContext, 0, EP0_CSR_REG_OFFSET);
		if ( ((peps->dwDirectionAssigned == USB_OUT_TRANSFER)) && (bEP0IrqStatus & EP0_OUT_PACKET_RDY) )	// 050828
		{
		}
		else
		{
			// Clear End Point 0 Interrupt
			ClearEndpointInterrupt(pContext, 0);
		}
#else
		ClearEndpointInterrupt(pContext, 0);
#endif
	}
	// Process All Other (besides EP0) Endpoints
	BYTE bEpMaskBits = ReadReg(pContext, EP_INT_EN_REG_OFFSET);

	DEBUGMSG(ZONE_FUNCTION, (_T("%s HUSB Status, %x\r\n"), pszFname, bEpIrqStat));
	BYTE bStatusBit = 0;
	for (DWORD dwEndpoint = 1; dwEndpoint < ENDPOINT_COUNT; ++dwEndpoint) {
		// Check the Interrupt Mask 
		// Check the Interrupt Status 
		bStatusBit =  EpToIrqStatBit(dwEndpoint);
		if ( (bEpMaskBits & bStatusBit) &&
			 (bEpIrqStat & bStatusBit) ) {
//			RETAILMSG(1, (TEXT("E%d\n"),dwEndpoint));		// 050828
#if 1
			HandleEndpointEvent(pContext, dwEndpoint, bEpIrqStat);
			BYTE ocsr1 = ReadIndexedReg(pContext, dwEndpoint, OUT_CSR1_REG_OFFSET);
			// receive packet complete && receive fifo not empty -> out token + data rx event
			if ((peps->dwDirectionAssigned == USB_OUT_TRANSFER) && (ocsr1 & OUT_PACKET_READY) ) 	// 050828

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -