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

📄 bvd_udc_hw.c

📁 自制PDA系列之usb驱动(处理器PXA270)
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	ServiceEP0
 *
 *	Services End Point 0.  This has been changed to a state machine in order
 *	to make the handling of the PXA250 UDC easier.  The UDC has an internal
 *	state machine and can get out of sync with the driver.  By implementing
 *	a state machine, this makes the process of keeping in sync with the UDC
 *	much easier.
 *
 *	This routine gets invoked as a result of a line interrupt being report
 *	by the SA_USB_GetInterruptType routine.
 *-----------------------------------------------------------------------------*/
int nResets = 0;	// limits tracebuffer to cover no more than three resets.
void ServiceEP0( PSER_INFO pHWHead, PDWORD pModemStatus )
{
	int nLoopCount = 0;
	DWORD udc_cr; //udc_csrA, udc_csrB;

	UDCTrace( pHWHead, UDCT_EP0,  UDC_STATE( pHWHead ));
	UDCTrace( pHWHead, UDCT_UDCCS0_STATE, UDC_CSR0( pHWHead ));

	// Service EP0 Packet Complete intr
	// This clears the IR0_0 interrupt due to IPR.
	// This does not clear the IR0_0 interrupt due to OPR.
	if (UDC_ISR0(pHWHead) & XLLP_UDC_UDCISR0_IR0_0) 
	{
     UDCTrace( pHWHead, 0xbc04, UDC_ISR0(pHWHead) );
	 UDCTrace( pHWHead, 0xbc04, UDC_CSR0(pHWHead) );
	 UDC_ISR0_CLEAR_ENDPOINT_INTR( UDC_ISR0(pHWHead), XLLP_UDC_UDCISR0_IR0_0);
	}
	// Deal with EP0 FIFO error intr
	if (UDC_ISR0(pHWHead) & XLLP_UDC_UDCISR0_IR0_1) 
	{
	 //NKDbgPrintfW(TEXT("!!! EP0 FIFO error\r\n"));
     UDCTrace( pHWHead, 0xbc05, UDC_ISR0(pHWHead) );
	 UDCTrace( pHWHead, 0xbc05, UDC_CSR0(pHWHead) );
	 UDC_ISR0_CLEAR_ENDPOINT_INTR( UDC_ISR0(pHWHead), XLLP_UDC_UDCISR0_IR0_1);
	}  
	
	if (UDC_ISR1(pHWHead) & XLLP_UDC_UDCISR1_IRCC) 
	{
	  /*
		// bpc stuff: special code to reset the trace buffer after every three resets:
		++nResets;
		if( nResets >= 4 )
		{
			nResets = 0;

			g_pTraceBuffer[0] = 4;	// this resets the trace buffer.

			// now add the trace entries back in that we just lost.
	        UDCTrace( pHWHead, 0xbca6, UDC_ISR1(pHWHead) );
		}
		else
		{
	        UDCTrace( pHWHead, 0xbc06, UDC_ISR1(pHWHead) );
		}
      */

	    CLEAR_CONFIG_CHANGE_INTR(UDC_ISR1(pHWHead));

		UDC_STATE( pHWHead ) = WAIT_FOR_IN_STATUS;

		// Save the configuration index into our state structure.
		udc_cr = UDC_CR(pHWHead);
		pHWHead->dConfIdx = (BYTE) ((udc_cr & 0x1800)>>11);		
		//RETAILMSG( 1, (TEXT("***Set Config: UDC_CR: %X\r\n"), udc_cr   ));
		
		//RETAILMSG( 1, (TEXT("***Setting SMAC\r\n")));
		//Set SMAC
	    UDCCR_SMAC_SET( UDC_CR(pHWHead) ); 

		//udc_csrA = UDC_CSR_A(pHWHead);
        //udc_csrB = UDC_CSR_B(pHWHead);
		//RETAILMSG( 1, (TEXT("UDC_CSR_A: %X\r\n"), udc_csrA));
        //RETAILMSG( 1, (TEXT("UDC_CSR_B: %X\r\n"), udc_csrB));

	    UDC_STATE(pHWHead) = WAIT_FOR_SETUP;

		goto SEP0_10;	// if fall through, will process previous setup command.
	}

	DEBUGMSG( ZONE_USB,(TEXT("ServiceEP0: State=%d\r\n"), UDC_STATE( pHWHead )));
		
	// Check for missing status interrupt
	if( UDC_CSR0( pHWHead ) & XLLP_UDC_UDCCSR0_SA )
		UDC_STATE(pHWHead) = WAIT_FOR_SETUP;

	if( UDC_CSR0( pHWHead ) == 0x81 ) 
	{
      UDCTrace( pHWHead, 0xbc07, UDC_CSR0(pHWHead) );
	  DEBUGMSG( ZONE_ERROR,(TEXT("!!! STATUS = 81\r\n")));
	  //NKDbgPrintfW(TEXT("!!! STATUS = 81\r\n"));
	}
	else if ( UDC_CSR0( pHWHead ) == 0x2 ) 
	{
      UDCTrace( pHWHead, 0xbc18, UDC_CSR0(pHWHead) );	// out of order bcxx number 'cause of typo
	  //RETAILMSG( 1 ,(TEXT("!!! UDC_CSR0 == 2\r\n")));
	  //NKDbgPrintfW(TEXT("!!! !!! UDC_CSR0 == 2\r\n"));
	}

	switch( UDC_STATE(pHWHead)) {
	  case WAIT_FOR_SETUP:
			// This indicates we should be processing a setup packet.
			UDCTrace( pHWHead, 0xbc08, UDC_CSR0(pHWHead) );
			ProcessEP0Setup( pHWHead, pModemStatus );
			UDCTrace( pHWHead, 0xbc88, UDC_CSR0(pHWHead) );
			break;

	  case DATA_STATE_XMIT:
			// Transmit the next data packet for EP0
		    //RETAILMSG( 1 ,(TEXT("!!! Data State xmit!!!")));
			UDCTrace( pHWHead, 0xbc09, UDC_CSR0(pHWHead) );
			XmitEP0Data( pHWHead );
			UDCTrace( pHWHead, 0xbc89, UDC_CSR0(pHWHead) );
			break;

	  case DATA_STATE_RCVR:
			// Receive the next data packet
			UDCTrace( pHWHead, 0xbc0a, UDC_CSR0(pHWHead) );
			ASSERT(0);
			UDCTrace( pHWHead, 0xbc8a, UDC_CSR0(pHWHead) );
			break;

	  case WAIT_FOR_OUT_STATUS:
			// Process the OUT status state
			UDCTrace( pHWHead, 0xbc0b, UDC_CSR0(pHWHead) );
			ProcessEP0OutStatus( pHWHead );
			UDCTrace( pHWHead, 0xbc8b, UDC_CSR0(pHWHead) );
			break;

	  case WAIT_FOR_IN_STATUS:
			// Process in IN status state
			UDCTrace( pHWHead, 0xbc0c, UDC_CSR0(pHWHead) );
			ProcessEP0InStatus( pHWHead );
			UDCTrace( pHWHead, 0xbc8c, UDC_CSR0(pHWHead) );
			//ASSERT(0);
			break;
	  default:
			UDCTrace( pHWHead, 0xbc0d, UDC_CSR0(pHWHead) );
			ASSERT(0);
			UDCTrace( pHWHead, 0xbc8d, UDC_CSR0(pHWHead) );
			break;
		}

	// No need to clear the IR0 interrupt.
	// UDC_ISR0_CLEAR_ENDPOINT_INTR( UDC_ISR0(pHWHead), XLLP_UDC_UDCISR0_IR0_0);


SEP0_10:
	UDCTrace( pHWHead, 0xbc0f, UDC_CSR0(pHWHead) );
	UDCTrace( pHWHead, UDCT_INTR, UDC_ISR0(pHWHead));
}

/*----------------------------------------------------------------------
 * SA_USB_GetInterruptType
 * 
 * Determine the source of an interrupt and return flags to control which
 * function gets called to handle it. EP0 is handled as modem interrupt, EP1
 * as TX, EP2 as RX and reset is handled as line interrupt.
 */
INTERRUPT_TYPE SA_USB_GetInterruptType( PSER_INFO  pHWHead)
{

  unsigned long udc_isr0_copy, udc_isr1_copy;
  INTERRUPT_TYPE interruptFlags = 0;

  udcStats.usbIntCount++;

  udc_isr0_copy = UDC_ISR0( pHWHead ) ; 
  udc_isr1_copy = UDC_ISR1( pHWHead ) ;

  DEBUGMSG( ZONE_INT,
	    (TEXT("+SA_USB_GetInterruptType: udc_isr0=%X udc_isr1=%X\r\n"), udc_isr0_copy, udc_isr1_copy));

  UDCTrace( pHWHead, UDCT_INTR, udc_isr0_copy );
  UDCTrace( pHWHead, UDCT_INTR, ( udc_isr1_copy & 0xffff0000 ) | ( pHWHead->pINTCRegs->ichp & 0x0000ffff ) );

  /*
   * If Reset received...
   */
  if (udc_isr1_copy & XLLP_UDC_UDCISR1_IRRS) 
    interruptFlags |= INTR_LINE;        /* We use INTR_LINE to handle USB Reset */

   /*
   * If Reset received...
   */
  if (udc_isr1_copy & XLLP_UDC_UDCISR1_IRCC) 
  {
    interruptFlags |= INTR_MODEM;        /* We use INTR_MODEM for Config change intr */
	//RETAILMSG( 1 ,(TEXT("!!! Config Change Intr\r\n")));
  }

  /* 
   * Setup command received. Model as modem interrupt.
   */
  if ((udc_isr0_copy & XLLP_UDC_UDCISR0_IR0_0) || (udc_isr0_copy & XLLP_UDC_UDCISR0_IR0_1))
    interruptFlags |= INTR_MODEM;       /* Use INTR_MODEM for EP0 interrupts */

  /* 
   * If Bulk In (transmit) interrupt ...
   */
  if ((udc_isr0_copy & XLLP_UDC_UDCISR0_IRA_0) || (udc_isr0_copy & XLLP_UDC_UDCISR0_IRA_1))
  { interruptFlags |= INTR_TX;
  }
  /* 
   * If Bulk Out (receive) interrupt ...
   */
  if ((udc_isr0_copy & XLLP_UDC_UDCISR0_IRB_0) || (udc_isr0_copy & XLLP_UDC_UDCISR0_IRB_1))
  { interruptFlags |= INTR_RX;
  }
  return (interruptFlags);
}


/*
 * SA_USB_LineIntHandler
 *
 * This handler is called for reset interrupts
 */
void SA_USB_LineIntHandler(PSER_INFO pHWHead)
{
    //NKDbgPrintfW(TEXT("SA_USB_LineIntHandler\r\n"));
   
	if (1 == (pHWHead->UDC_Reset))
    {
      pHWHead->UDC_Reset = 0; 

      //Disable UDC Soft Connect
      //pHWHead->pBCRReg->MISCWR2 |= XLLP_BCR_MISCWR2_NUSBC_SC;

      pHWHead->ModemStatus &= ~MS_RLSD_ON;
      EvaluateEventFlag(pHWHead->pMddHead, EV_RLSD);
        
	  //Timeout
	  WaitForSingleObject(pHWHead->hSerialEvent, pHWHead->UDC_ResetTimeOut);

	  //Enable UDC Soft Connect
      //pHWHead->pBCRReg->MISCWR2 &= ~XLLP_BCR_MISCWR2_NUSBC_SC; 
    
	}
	
  //Clear the interrupt request bit
  CLEAR_RESET_INTR( UDC_ISR1(pHWHead) );
    
}

/*
 * SA_USB_RxIntHandler
 *
 * Read characters up to the max packet length from the IN FIFO. Return the
 * number of characters read in the supplied argument. The function returns
 * a boolean indicating whether event characters are present.
 */
BOOL SA_USB_RxIntHandler(PSER_INFO pHWHead,
						 PUCHAR pRxBuffer,
						 ULONG *pBufflen)
{
	
	
	BOOL fRXFlag = FALSE;
	UCHAR cEvtChar = pHWHead->dcb.EvtChar;
	
	//UCHAR cRxChar;
	//UCHAR *pRxByte;
	ULONG *pRxWord = (unsigned long*) pRxBuffer;
 
	volatile ULONG buflen = *pBufflen;
	
	volatile unsigned int bytes_to_read =0, word_count, byte_count; // temp_byte_count;
	volatile DWORD dw_udc_csr_b; // dw_udc_cr_b;
	
	PBYTE pData;
	//int nIndex;
	unsigned long rx_word1;
	volatile  BYTE  *pEP_B_FIFO; 
    static UCHAR RxPacket[EP1Len];
	static unsigned int RxPacketLen=0, RxPacketIndex=0;

	//ULONG LineEvents = 0;

	DEBUGMSG(ZONE_READ, (TEXT("RX Buff Len = %d \r\n"), buflen));
	//RETAILMSG(1, (TEXT("RX: %X\r\n"), buflen));

	//g_pBLReg->hex_led = 0xFFFFA001;
	
	*pBufflen = 0;
	pEP_B_FIFO = (volatile  BYTE  *) &(UDC_DR_B( pHWHead ));	

	UDCTrace( pHWHead, UDCT_UDC_ISR0, UDC_ISR0(pHWHead) );

	// To do: Deal with EPB FIFO error intr
	// Deal with EPB FIFO error intr
	if (UDC_ISR0(pHWHead) & XLLP_UDC_UDCISR0_IRB_1) 
	{
	 //NKDbgPrintfW(TEXT("****!!! EPB FIFO error\r\n"));
	 UDC_ISR0_CLEAR_ENDPOINT_INTR( UDC_ISR0(pHWHead), XLLP_UDC_UDCISR0_IRB_1);
	}  
	// Clear Interrupt
	UDC_ISR0_CLEAR_ENDPOINT_INTR( UDC_ISR0(pHWHead), XLLP_UDC_UDCISR0_IRB_0);
    
	UDCTrace( pHWHead, UDCT_UDC_ISR0, UDC_ISR0(pHWHead) );

	// Is RPC set.
	dw_udc_csr_b = UDC_CSR_B( pHWHead );
	UDCTrace( pHWHead, UDCT_RX_INT, dw_udc_csr_b );

	//pData  = pRxBuffer; //pTxBuffer;  //lastPacket
    //nIndex=0;

	if (RxPacketLen)
	{
	 //NKDbgPrintfW(TEXT("***RX: Copy %X\r\n"), RxPacketLen);
	 if(buflen >= RxPacketLen)
	 {
	  memcpy(pRxBuffer, RxPacket + RxPacketIndex, RxPacketLen);
	  pRxBuffer += RxPacketLen;
	  (*pBufflen) += RxPacketLen;
	  buflen-= RxPacketLen;

	  RxPacketIndex=0;
	  RxPacketLen -= RxPacketLen;

	  //RETAILMSG(1, (TEXT("***RX: Copied %X\r\n"), buflen));
	 }
	 else
	 {
	  //NKDbgPrintfW(TEXT("***RX: Not copied%d\r\n"), buflen);
	 }
	}

	if((dw_udc_csr_b & XLLP_UDC_UDCCSR_PC) == 0 ) 
	{
		UDCTrace( pHWHead, UDCT_NO_RPC, dw_udc_csr_b );
		udcStats.noRPC++;
		//RETAILMSG( 1, (TEXT("***Rx: PC=0 UDC_CSR_B: %X\r\n"), dw_udc_csr_b));
		
		// Clear Interrupt
        //UDC_ISR0_CLEAR_ENDPOINT_INTR( UDC_ISR0(pHWHead), XLLP_UDC_UDCISR0_IRB_0);    
	    //UDCTrace( pHWHead, UDCT_RX_INTR_DONE, UDC_CSR_B( pHWHead ));
        //UDCTrace( pHWHead, UDCT_RX_DATA, *pBufflen );
		
		//return fRXFlag;

	} 
	else if ((dw_udc_csr_b & XLLP_UDC_UDCCSR_SP) && ((dw_udc_csr_b & XLLP_UDC_UDCCSR_BNE_BNF) == 0)) 
	{
		// Clear the PC bit 
		UDCCSR_MWRITE(UDC_CSR_B( pHWHead), XLLP_UDC_UDCCSR_PC);

	    // Clear Interrupt
        UDC_ISR0_CLEAR_ENDPOINT_INTR( UDC_ISR0(pHWHead), XLLP_UDC_UDCISR0_IRB_0);
		
		//RETAILMSG( 1, (TEXT("********Rx: ZLP received UDC_CSR_B: %X\r\n"), dw_udc_csr_b));

		UDCTrace( pHWHead, UDCT_INTR, UDC_ISR0(pHWHead) );
		UDCTrace( pHWHead, UDCT_RX_INTR_DONE, UDC_CSR_B( pHWHead ));
        UDCTrace( pHWHead, UDCT_RX_DATA, *pBufflen );

		return fRXFlag;
	}
	else
	{
		//
		// Read the bytes from the FIFO and return the actual number read.
		//

		//pData  = pRxBuffer;
		pData = RxPacket;
		
		RxPacketLen=0;
		RxPacketIndex =0;
		
		do
		{
			bytes_to_read = UDC_BCR_B(pHWHead);
			word_count = bytes_to_read/4;
			byte_count = bytes_to_read%4;

			if (buflen >= bytes_to_read)
			{
			  pData  = pRxBuffer;
			}
			else
			{
			  pData = (RxPacket + RxPacketIndex + RxPacketLen); //pData = RxPacket;
			}

			if (UDC_CSR_B( pHWHead ) & XLLP_UDC_UDCCSR_BNE_BNF ) 
			{
				if (word_count)
				{
				 while (word_count)
				 {
					 rx_word1 = UDC_DR_B( pHWHead );
					 //pRxWord[0] = rx_word1;
					 //pRxWord++;

					 pData[0] = (BYTE) (rx_word1 & 0xFF);
					 pData[1] = (BYTE) ((rx_word1>>8)  & 0xFF);
					 pData[2] = (BYTE) ((rx_word1>>16) & 0xFF);
					 pData[3] = (BYTE) ((rx_word1>>24) & 0xFF);
					  
					 //RETAILMSG( 1, (TEXT("Rx: %x %x %x %x\r\n"), pData[0], pData[1], pData[2], pData[3]));
//					 if((pData[0] == cEvtChar) || (pData[1] == cEvtChar) || (pData[2] == cEvtChar) || (pData[3] == cEvtChar))
//					  fRXFlag = TRUE;

					 pData +=4;
					 RxPacketLen +=4;
					 word_count--;
				 }
				}
				  
				if (byte_count)
				{
					//temp_byte_count = byte_count;
					rx_word1 = UDC_DR_B( pHWHead );

					//while (temp_byte_count)
					//{
					//	pData[0] = (BYTE) (rx_word1 & 0xFF);
						//ch1 = (BYTE) (rx_word1 & 0xFF);
						//pData[0] = ch1;

					//	if (pData[0] == cEvtChar)
				   	//	  fRXFlag = TRUE ;

					//	pData++;
					//	rx_word1 = (rx_word1>>8);
					//	temp_byte_count--;
					//}
	                
					if (byte_count == 1)
					{
						pData[0] = (BYTE) (rx_word1 & 0xFF);

//						if (pData[0] == cEvtChar)
//				   		  fRXFlag = TRUE ;
					}
					else if (byte_count == 2)
					{
						pData[0] = (BYTE) (rx_word1 & 0xFF);
						pData[1] = (BYTE) ((rx_word1>>8)  & 0xFF);

//						if ((pData[0] == cEvtChar) || (pData[1] == cEvtChar))
//				   		  fRXFlag = TRUE ;
					}

⌨️ 快捷键说明

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