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

📄 bvd_ser16550.c

📁 cayman提供的PXA270 wince下的bsp源码包
💻 C
📖 第 1 页 / 共 5 页
字号:
            NKDbgPrintfW(TEXT("IntPending "));
        NKDbgPrintfW(TEXT("\r\n"));

        value = INB(pHWHead, pLCR);
        NKDbgPrintfW(TEXT("Cotulla 16550 lcr: \t%2.2X\t"), value);

        NKDbgPrintfW(TEXT("%dBPC "), ((value & 0x03)+5) );

        if ( value & SERIAL_LCR_DLAB )
            NKDbgPrintfW(TEXT("DLAB "));
        if ( value & SERIAL_LCR_BREAK )
            NKDbgPrintfW(TEXT("Break "));
        NKDbgPrintfW(TEXT("\r\n"));

        value = INB(pHWHead, pMCR);
        NKDbgPrintfW(TEXT("Cotulla 16550 mcr: \t%2.2X\t"), value);
        if ( value & SERIAL_MCR_DTR )
            NKDbgPrintfW(TEXT("DTR "));
        if ( value & SERIAL_MCR_RTS )
            NKDbgPrintfW(TEXT("RTS "));
        if ( value & SERIAL_MCR_OUT1 )
            NKDbgPrintfW(TEXT("OUT1 "));
        if ( value & SERIAL_MCR_OUT2 )
            NKDbgPrintfW(TEXT("OUT2 "));
        if ( value & SERIAL_MCR_LOOP )
            NKDbgPrintfW(TEXT("LOOP "));
        NKDbgPrintfW(TEXT("\r\n"));

		value = INB(pHWHead, pMSR);
        NKDbgPrintfW(TEXT("Cotulla 16550 msr: \t%2.2X\t"), value);
        if ( value & SERIAL_MSR_DCTS )
            NKDbgPrintfW(TEXT("DCTS "));
        if ( value & SERIAL_MSR_DDSR )
            NKDbgPrintfW(TEXT("DDSR "));
        if ( value & SERIAL_MSR_TERI )
            NKDbgPrintfW(TEXT("TERI "));
        if ( value & SERIAL_MSR_DDCD )
            NKDbgPrintfW(TEXT("DDCD"));
        if ( value & SERIAL_MSR_CTS )
            NKDbgPrintfW(TEXT(" CTS"));
        if ( value & SERIAL_MSR_DSR )
            NKDbgPrintfW(TEXT("DSR "));
        if ( value & SERIAL_MSR_RI )
            NKDbgPrintfW(TEXT("RI "));
        if ( value & SERIAL_MSR_DCD )
            NKDbgPrintfW(TEXT("DCD "));
        NKDbgPrintfW(TEXT("\r\n"));

    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        // Nothing much to clean up here.
    }
}
#endif // DEBUG


//
// Helper routine to search through a lookup table for a designated
// key.
//
ULONG
HW_XSC1_LookUpValue(
           ULONG    Key,
           PLOOKUP_TBL pTbl,
           PULONG    pErrorCode
           )
{
    ULONG   index = 0;

    *pErrorCode = 0;

    while ( index < pTbl->Size ) {
        if ( Key == pTbl->Table[index].Key )
            return(pTbl->Table[index].AssociatedValue);

        ++index;
    }

    *pErrorCode = (ULONG)-1;

    return(0);
}



//
// Helper function.  Pass in a baudrate, and the corresponding divisor
// (from the baudtable) is returned.  If no matching baudrate is found
// in baudtable, then return 0.
//
USHORT
HW_XSC1_DivisorOfRate(
             PVOID   pHead,      // @parm PVOID returned by HWinit.
             ULONG   BaudRate    // @parm     ULONG representing decimal baud rate.    
             )
{
    ULONG   errorcode = 0;
    USHORT  divisor;    

	PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;

    divisor = (USHORT)HW_XSC1_LookUpValue(BaudRate,
                                  ((PSER16550_INFO) pHead)->pBaudTable, &errorcode);

    //if (( errorcode ) || ((pHWHead->IOBase != BTUART_BASE_U_VIRTUAL) && (1 == divisor)))
	if ( errorcode )
        divisor = 0;

    return(divisor);
}

//
// This is a reverse lookup table which can be used to determine
// the FIFO trigger level from the 2 bit value stored in the FCR
//
#define HIGH_WATER_SIZE     4
static const
XSC1_PAIRS    HighWaterPairs[HIGH_WATER_SIZE] = {
    {XSC1_SERIAL_1_BYTE_HIGH_WATER, 1}, //AG why was it 0?
    {XSC1_SERIAL_8_BYTE_HIGH_WATER, 8},
    {XSC1_SERIAL_16_BYTE_HIGH_WATER, 16},
    {XSC1_SERIAL_32_BYTE_HIGH_WATER, 32}
};
static const
LOOKUP_TBL  HighWaterTable = {HIGH_WATER_SIZE, (XSC1_PAIRS *) HighWaterPairs};

#define IER_NORMAL_INTS (SERIAL_IER_RAVIE | SERIAL_IER_RLSE | SERIAL_IER_MIE | SERIAL_IER_RTOIE)

// Routine to clear any pending interrupts.  Called from Init and PostInit
// to make sure we start out in a known state.
VOID
HW_XSC1_ClearPendingInts(
       PVOID   pHead // @parm PVOID returned by HWinit.
       )
{
    PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_CLOSE,(TEXT("+HW_XSC1_ClearPendingInts, 0x%X\r\n"), pHWHead));
//	DEBUGMSG (1,(TEXT("??????????????????+HW_XSC1_ClearPendingInts, 0x%X\r\n"), pHWHead));

    EnterCriticalSection(&(pHWHead->RegCritSec));

    try {
        pHWHead->IIR = INB(pHWHead, pIIR_FCR);
        
        // RX FIFO should be reset once to clear all errors, if any,
        // associated with bytes received other than the bottommost entry byte. 
        do {
            
            DEBUGMSG (ZONE_INIT, (TEXT("!!IIR %X\r\n"), pHWHead->IIR));

            // Reading LSR clears RLS interrupts.
            // Also, any error bits OE, PE, FE or BI that had been set in LSR are also cleared.
            HW_XSC1_ReadLSR( pHWHead );

            // Reset RX FIFO to clear any old data and errors ,if any, remaining in it.
            // Resetting FIFO once is more than enough.
            // Resetting Receiver FIFO does not clear any error bits OE, PE, FE or BI ,if any, that had
            // been set in LSR. But, we have already cleared those error bits by HW_XSC1_ReadLSR.

            OUTB(pHWHead, pIIR_FCR, pHWHead->FCR | SERIAL_FCR_TXRXFIFO_ENABLE | 
				                                   SERIAL_FCR_RESET_RCVR_FIFO | SERIAL_FCR_RESET_TXMT_FIFO);

            // Reading MSR clears Modem Status interrupt
            HW_XSC1_ReadMSR( pHWHead );

            // Simply reading IIR is sufficient to clear THRE
            pHWHead->IIR = INB(pHWHead, pIIR_FCR);
        
        } while (!(pHWHead->IIR & SERIAL_IIR_NO_INTERRUPT_PENDING) );    
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        DEBUGMSG (ZONE_ERROR,(TEXT("-HW_XSC1_ClearPendingInts, 0x%X - ERROR\r\n"), pHWHead));
        // Just fall through & release CritSec
    }

    LeaveCriticalSection(&(pHWHead->RegCritSec));
}

//
/////////////////// Start of exported entrypoints ////////////////
//

//
// @doc OEM 
// @func PVOID | HW_XSC1_Open | Configures Cotulla's 16550 UART for default behaviour.
//
VOID
HW_XSC1_Open(
       PVOID   pHead // @parm PVOID returned by HWinit.
       )
{
    PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_OPEN,
              (TEXT("+HW_XSC1_Open 0x%X\r\n"), pHead));
//	DEBUGMSG (1,(TEXT("???????????????+HW_XSC1_Open 0x%X\r\n"), pHead));

    // If the device is already open, all we do is increment count
    if ( pHWHead->OpenCount++ ) {
        DEBUGMSG (ZONE_OPEN,
                  (TEXT("-HW_XSC1_Open 0x%X (%d opens)\r\n"),
                   pHead, pHWHead->OpenCount));
        return ;
    }

    //Initializing shadow registers.
    pHWHead->FCR = 0;
    pHWHead->IER = 0;
    pHWHead->IIR = 1;  // Cotulla specific
    pHWHead->LSR = 0;
    pHWHead->MSR = 0;  // All modem signals inactive (0 => voltage high)
	pHWHead->LCR = 0;
	pHWHead->MCR = 0;
    pHWHead->SCR = 0;

    //Seting up shadow SLOW_IR_SELECT_REGISTER register also
    //though we don't use it till IR mode is selected.
    pHWHead->IRDASEL = 0;

    pHWHead->DroppedBytes = 0;
    pHWHead->CTSFlowOff = FALSE;  // Not flowed off yet
    pHWHead->DSRFlowOff = FALSE;  // Not flowed off yet
    pHWHead->CommErrors   = 0;
    pHWHead->ModemStatus  = 0;

	EnterCriticalSection(&(pHWHead->RegCritSec));

    try {

         //Disabling all interrupts and the UART Unit
		 //Done in HW_XSC1_Init, but will handle multiple COM_OPEN()s in a single power cycle.
	     //OUTB(pHWHead, pLCR,     (UCHAR)0);   // clearing DLAB 
         //OUTB(pHWHead, pIER_DLH, (UCHAR)0);   // IER_DLH = 0x0

        // Set default framing bits to 8N1 // 8 bits, 1 stop, no parity. Also LCR DLAB bit = 0
		pHWHead->LCR |=  (SERIAL_8_DATA | SERIAL_1_STOP | SERIAL_NONE_PARITY);
        OUTB(pHWHead, pLCR, (pHWHead->LCR) );  //pLCR = 0x3. 

        DEBUGMSG (ZONE_OPEN,
                  (TEXT("HW_XSC1_Open Setting DCB parameters\r\n")));

        // Get defaults from the DCB structure
        HW_XSC1_SetBaudRate( pHead, pHWHead->dcb.BaudRate );
        HW_XSC1_SetByteSize( pHead, pHWHead->dcb.ByteSize );
        HW_XSC1_SetStopBits( pHead, pHWHead->dcb.StopBits );
        HW_XSC1_SetParity(   pHead, pHWHead->dcb.Parity );
        
        //Enabling TxRx FIFOs and choosing the receive interrupt trigger level
		//Both Rx and Tx FIFOs are also reset
        if (pHWHead->ChipID == CHIP_ID_COTULLA) 
		{
         // Set up to use Cotulla fifo for 32 byte interrupt granularity.
         // Shadow the FCR bitmask since reading this location is the IIR.
         pHWHead->FCR = SERIAL_FCR_TXRXFIFO_ENABLE | XSC1_SERIAL_32_BYTE_HIGH_WATER ;
		 //DEBUGMSG (ZONE_OPEN, (TEXT("HW_XSC1_Open Setting Rx FIFO Trigger level: 1 byte\r\n")));
		 //pHWHead->FCR = SERIAL_FCR_TXRXFIFO_ENABLE | XSC1_SERIAL_1_BYTE_HIGH_WATER ;
			
         OUTB(pHWHead, pIIR_FCR,
                 (pHWHead->FCR | SERIAL_FCR_RESET_RCVR_FIFO | SERIAL_FCR_RESET_TXMT_FIFO) );
        }
		else if (pHWHead->ChipID == CHIP_ID_BULVERDE) 
		{
		 //For Bulverde
	     //To Do: Change peripheral bus to be 32 bit
		 #ifdef UART_32_BIT_PERIPHERAL_BUS
		 
		   //Set Tx Interrupt level to FIFO half empty
		   //Trailing bytes are removed by Processor 
		   pHWHead->FCR &=  (  ~SERIAL_FCR_TX_INTR_LEVEL   
	   					    & ~SERIAL_FCR_TRAILING_BYTES);   
		  
		   //Rx FIFO Interrupt Threshold level is 32 bytes and Enable RxTx FIFOs.
		   //Peripheral bus is 32 bit
		   pHWHead->FCR |= (SERIAL_FCR_TXRXFIFO_ENABLE | XSC1_SERIAL_32_BYTE_HIGH_WATER |
		   				    SERIAL_FCR_PERIPHERAL_BUS  ) ; 
		 
         #else
	 	  
		  
		   //Set Tx Interrupt level to FIFO half empty
		   //Trailing bytes are removed by Processor
		   //Peripheral bus is 8 bit
		   pHWHead->FCR &=  (  ~SERIAL_FCR_TX_INTR_LEVEL    
	   	  				     & ~SERIAL_FCR_TRAILING_BYTES  
		 				     & ~SERIAL_FCR_PERIPHERAL_BUS); 
		  
		   //Rx FIFO Interrupt Threshold level is 32 bytes and Enable RxTx FIFOs.
		   pHWHead->FCR |= (SERIAL_FCR_TXRXFIFO_ENABLE | XSC1_SERIAL_32_BYTE_HIGH_WATER) ;
		 
         #endif

         // Set up to use Bulverde fifo for 32 byte interrupt granularity.
         // Shadow the FCR bitmask since reading this location is the IIR.
        
		 //DEBUGMSG (ZONE_OPEN, (TEXT("HW_XSC1_Open Setting Rx FIFO Trigger level: 1 byte\r\n")));
		 //pHWHead->FCR = SERIAL_FCR_TXRXFIFO_ENABLE | XSC1_SERIAL_1_BYTE_HIGH_WATER ;
			
         OUTB(pHWHead, pIIR_FCR,
                 (pHWHead->FCR | SERIAL_FCR_RESET_RCVR_FIFO | SERIAL_FCR_RESET_TXMT_FIFO) );
        } 

        // For CE 3.0, we are still supporting
        // the old style MDDs, and they don't call our PostInit, which
        // needs to happen sometime prior to this.  So for now, we go ahead
        // ahead and clear out interrupts one last time.  In 4.0, we can
        // kill the old serial MDD and assume that everyone uses the new
        // MDD and calls post init.  
        HW_XSC1_PostInit(pHWHead);

        HW_XSC1_ReadMSR(pHWHead);
        HW_XSC1_ReadLSR(pHWHead);

		//Ensuring that loop back mode is off
	    pHWHead->MCR &= (~SERIAL_MCR_LOOP);
/*
		//Detecting chip stepping at run-time
//#ifdef A1_Cotulla
		if( (pHWHead->ProcessorStepping == COTULLA_A1_CP15_VAL) || (pHWHead->ProcessorStepping == SABINAL_A1_CP15_VAL) )
		{
		//Cotulla A1: Set MCR[OUT]=0 to enable UART IRQ
         pHWHead->MCR &= ~SERIAL_MCR_IRQ_ENABLE ;
		}
//#elif B0_Cotulla
		else if( (pHWHead->ProcessorStepping == COTULLA_B0_CP15_VAL) || (pHWHead->ProcessorStepping == SABINAL_B0_CP15_VAL) )
		{
			//Cotulla B0: Set MCR[OUT]=1 to enable UART IRQ
		    pHWHead->MCR |= SERIAL_MCR_IRQ_ENABLE ;
		}
//#else
		else
		{
			//Default stepping: Set MCR[OUT]=1 to enable UART IRQ.
			pHWHead->MCR |= SERIAL_MCR_IRQ_ENABLE ;
		}
//#endif
*/
		//Set MCR[OUT]=1 to enable UART IRQ.
		pHWHead->MCR |= SERIAL_MCR_IRQ_ENABLE ;
	    OUTB(pHWHead, pMCR, (UCHAR) pHWHead->MCR);
	
		//Enabling UART unit, receiver data available, receiver line status and modem interrupts.
        pHWHead->IER |=  (SERIAL_IER_UUE | (UCHAR) (IER_NORMAL_INTS)) ;
        OUTB(pHWHead, pIER_DLH, (UCHAR) pHWHead->IER);
       
		//At this point, serial IRQ is enabled and UART is powered up over here

#ifdef DEBUG
  //      if ( ZONE_INIT )
  //          HW_XSC1_DumpSerialRegisters(pHWHead);
#endif
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        // Just get out of here.
		 DEBUGMSG (ZONE_ERROR,(TEXT("-HW_XSC1_Open, 0x%X - ERROR\r\n"), pHWHead));
    }

    LeaveCriticalSection(&(pHWHead->RegCritSec));

    DEBUGMSG (ZONE_OPEN,
              (TEXT("-HW_XSC1_Open 0x%X, IIR 0x%X\r\n"), pHead, pHWHead->IIR));
}

//
// @doc OEM 
// @func PVOID | HW_XSC1_Close | Does nothing except keep track of the
// open count so that other routines know what to do.
//
VOID
HW_XSC1_Close(
        PVOID   pHead // @parm PVOID returned by HWinit.
        )
{
    PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_CLOSE,
              (TEXT("+HW_XSC1_Close 0x%X\r\n"), pHead));
//	DEBUGMSG (1,(TEXT("???????????????+HW_XSC1_Close 0x%X\r\n"), pHead));

    if ( pHWHead->OpenCount )
        pHWHead->OpenCount--;

    EnterCriticalSection(&(pHWHead->RegCritSec));
    try {
		 //For Merlin Active Sync, we don't disable the interrupts
#ifdef USE_TALISKER
		  HW_XSC1_DisableTxRx(pHead);
#endif
          //NKDbgPrintfW(TEXT("HW_XSC1_Close MSR:%X MCR:%X\r\n\n"), pHWHead->MSR, pHWHead->MCR);

		  // Disable all interrupts and clear MCR.

⌨️ 快捷键说明

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