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

📄 bvd_ser16550.c

📁 cayman提供的PXA270 wince下的bsp源码包
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Copyright ?1999 Intel Corp.  */
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-2000 Microsoft Corporation.  All rights reserved.

Module Name:  

bvd_ser16550.c

Abstract:  

    This file implements the standard device specific functions for a Cotulla's 16550
    compatible UART based serial device.

Functions:

    HW_XSC1_Init()
    HW_XSC1_PostInit()
    HW_XSC1_Deinit()
    HW_XSC1_Open()
    HW_XSC1_Close()
    HW_XSC1_ClearDTR()
    HW_XSC1_SetDTR()
    HW_XSC1_ClearRTS()
    HW_XSC1_SetRTS()
    HW_XSC1_ClearBreak()
    HW_XSC1_SetBreak()
    HW_XSC1_SetBaudRate()
    HW_XSC1_SetByteSize()
    HW_XSC1_SetParity()
    HW_XSC1_SetStopBits()
    HW_XSC1_GetRxBufferSize()
    HW_XSC1_GetRxStart()
    HW_XSC1_GetInterruptType()
    HW_XSC1_RxIntr()
    HW_XSC1_TxIntrEx()
    HW_XSC1_LineIntr()
    HW_XSC1_ModemIntr()
    HW_XSC1_GetStatus()
    HW_XSC1_Reset()
    HW_XSC1_GetModemStatus()
    HW_XSC1_PurgeComm()
    HW_XSC1_XmitComChar()
    HW_XSC1_PowerOff()
    HW_XSC1_PowerOn()
    HW_XSC1_SetDCB()
    HW_XSC1_SetCommTimeouts()
    HW_XSC1_Ioctl()
    HW_XSC1_ReadLSR()
    HW_XSC1_ReadMSR()
    HW_XSC1_DumpSerialRegisters()
    HW_XSC1_LookUpValue()
    HW_XSC1_DivisorOfRate()



Notes:
    The RegCritSec is there to protect against non-atomic access of
    register pairs.  On a 16550, the main such collision comes from 
    the fact that THR and IER are overloaded as the DivLatch registers
    and their mode is controlled via the LCR.  So we need the 
    critical section protection around all access of these 3 registers.
    But we also need to watch out for read/modify/write where we are
    setting/ckearing a bit.  In general, I just go ahead and acquire
    the CS around all register accesses.
--*/

#include <windows.h>
#include <types.h>
#include <ceddk.h>
#include <memory.h>
#include <notify.h>
#include <serhw.h>
#include "bvd1.h"
#include "xllp_gpio.h"
#include "bvd_ser16550.h"   
#include "bvd_hw16550.h"
#include "bvd_serbaud.h"
#include "xllp_defs.h"
#include "xllp_serialization.h"
#include "xllp_clkmgr.h"
#include <serdbg.h>
#include <excpt.h>

/*
#if defined(WAVECOM_DRIVER) || defined(OEM1_DRIVER)
//From gsmradio.h
//Needed for WAVECOM module
//Currently, these two IOCTLs are not supported by the serial driver
#define FILE_DEVICE_GSMRADIO            0x200
#define IOCTL_SPKR_ENABLE               CTL_CODE(FILE_DEVICE_GSMRADIO, 1, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_SPKR_DISABLE              CTL_CODE(FILE_DEVICE_GSMRADIO, 2, METHOD_BUFFERED, FILE_ANY_ACCESS)
#else
#define IOCTL_SPKR_ENABLE   0
#define IOCTL_SPKR_DISABLE  0
#endif
*/

//extern XLLP_UINT32_T XllpLock(XLLP_PROTECTED_REGISTER Xllp_RegisterID);
//extern void XllpUnlock(XLLP_UINT32_T Xllp_LockID);
extern void usWait(unsigned usVal); 

// Macros to read/write serial registers
// Modified macros for ULONGs instead of UCHARs
// In Cotulla's 16550 UART, we always do 32 bit reads/writes,
// even though the actual data is in the least significant byte only. 
#define INB(pInfo, reg)			( (*((pInfo)->reg)) & 0xff) 
#define OUTB(pInfo, reg, value)	( *((pInfo)->reg) = ((value) & 0xff)   )


BOOL    IsAPIReady(DWORD hAPI);
BOOL HW_XSC1_SetByteSize(PVOID pHead, ULONG ByteSize);
BOOL HW_XSC1_SetStopBits(PVOID pHead, ULONG StopBits);
BOOL HW_XSC1_SetParity(PVOID pHead, ULONG Parity);
VOID HW_XSC1_DisableTxRx(PVOID pHead);
VOID HW_XSC1_EnableTxRx(PVOID pHead);
void HW_XSC1_Enable_IR_Rx_Tx(PVOID pHead,BOOL Rxenable, BOOL Txenable);

BOOL StartClock(unsigned int,BOOL);
BOOL StopClock(unsigned int,BOOL);

#define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION 
//#define UART_32_BIT_PERIPHERAL_BUS    1
//#define INITIAL_MSR_STATE (SERIAL_MSR_CTS | SERIAL_MSR_DSR | SERIAL_MSR_DCD)

//Stubs for now
//To do:
__inline XLLP_UINT32_T XllpLock(XLLP_PROTECTED_REGISTER Xllp_RegisterID)
{
	return 0;
}

__inline void XllpUnlock(XLLP_UINT32_T Xllp_LockID)
{

}

//
// Reading the LSR clears most of its bits.  So, we provide this wrapper,
// which reads the register, records any interesting values, and
// stores the current LSR contents in the shadow register.
//
__inline
VOID
HW_XSC1_ReadLSR(
       PSER16550_INFO  pHWHead
       )
{
    ULONG LineEvents = 0;
    UCHAR cRXChar       ;
	unsigned int count = 0;

	DEBUGMSG (ZONE_FUNCTION,(TEXT("+HW_XSC1_ReadLSR\r\n")));
//	DEBUGMSG (1,(TEXT("**************HW_XSC1_ReadLSR\r\n")));

    try {
        pHWHead->LSR = INB(pHWHead, pLSR);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        pHWHead->LSR =  SERIAL_LSR_TDRQ;
    }
    
	//FIFOE bit set (SERIAL_LSR_FIFOERR)
	while (pHWHead->LSR & (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE))
	{ 
      // Note: Its not wise to do debug msgs in here since they will
      // pretty much guarantee that the FIFO gets overrun.
      if ( pHWHead->LSR & SERIAL_LSR_OE ) {
            DEBUGMSG (ZONE_WARN, (TEXT("***Overrun\r\n")));
//          DEBUGMSG (1, (TEXT("**************Overrun\r\n")));
            pHWHead->DroppedBytes++;
            pHWHead->CommErrors |= CE_OVERRUN;
	  }

      if ( pHWHead->LSR & SERIAL_LSR_PE ) {
            DEBUGMSG (ZONE_WARN, (TEXT("***parity\r\n")));
//			DEBUGMSG (1, (TEXT("**************Parity\r\n")));
            pHWHead->CommErrors |= CE_RXPARITY;
	  }
 
      if ( pHWHead->LSR & SERIAL_LSR_FE ) {
            DEBUGMSG (ZONE_WARN, (TEXT("***frame\r\n")));
//			DEBUGMSG (1, (TEXT("**************Frame\r\n")));
            pHWHead->CommErrors |= CE_FRAME;
	  }

      LineEvents |= EV_ERR;
	  
	  // Read chars out of FIFO until no FIFOE
	  cRXChar = (UCHAR) INB(pHWHead, pTHR_RBR_DLL);
      //DEBUGMSG(1,(TEXT("********** Throwing out FIFOE data(0x%x char:%c) count:%d\r\n"),cRXChar, cRXChar, ++count));
      DEBUGMSG(ZONE_WARN,(TEXT("***FIFOE 0x%X 0d%d \r\n"),cRXChar, cRXChar));

	  try
	  {
       pHWHead->LSR = INB(pHWHead, pLSR);
	  }
      except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) 
	  {
       pHWHead->LSR = SERIAL_LSR_TDRQ;
	  }
	}
    
	if ( pHWHead->LSR & SERIAL_LSR_BI ) {
//	    DEBUGMSG (1, (TEXT("**************Break\r\n")));
		DEBUGMSG (ZONE_WARN, (TEXT("***Break\r\n")));
        LineEvents |= EV_BREAK;
	}

    // Let WaitCommEvent know about this error
    if ( LineEvents )
        pHWHead->EventCallback( pHWHead->pMddHead, LineEvents );
}

//
// Reading the MSR clears many of its bits.  So, we provide this wrapper,
// which reads the register, records any interesting values, and
// stores the current MSR contents in the shadow register.
// Note that we always have DDCD and DCTS enabled, so if someone
// wants to keep an eye on these lines, its OK to simply read the
// shadow register, since if the value changes, the interrupt
// will cause the shadow to be updated.
//
__inline
VOID
HW_XSC1_ReadMSR(
       PSER16550_INFO  pHWHead
       )
{
    ULONG        Events = 0;
    ULONG        msr;
	UINT         blr = 0;
   
	DEBUGMSG (ZONE_FUNCTION,(TEXT("+HW_XSC1_ReadMSR\r\n")));
//	DEBUGMSG (1,(TEXT("**************HW_XSC1_ReadMSR\r\n")));

    try {
        msr = INB(pHWHead, pMSR);
		if (pHWHead->IOBase == BTUART_BASE_U_VIRTUAL)
		{

		}
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        msr = 0;
    }

    // Save the MSR value in a shadow
    pHWHead->MSR = msr;

    // For changes, we use callback to evaluate the event
    if (msr & SERIAL_MSR_DCTS)
        Events |= EV_CTS;

	if (pHWHead->IOBase == FFUART_BASE_U_VIRTUAL)
	{
     if ( msr & SERIAL_MSR_DDSR )
        Events |= EV_DSR;

     if ( msr & SERIAL_MSR_TERI )
        Events |= EV_RING;

     if ( msr & SERIAL_MSR_DDCD )
        Events |= EV_RLSD;
	}

    if ( Events )
        pHWHead->EventCallback( pHWHead->pMddHead, Events );

//#ifdef USE_MERLIN
	// If RLSD transitioned to active, we need to generate event.
    //DEBUGMSG(ZONE_EVENTS,(TEXT("************ HW_XSC1_ReadMSR EV_RLSD\r\n")));
    if ((pHWHead->OpenCount==0) && (msr & SERIAL_MSR_DDCD) && (msr & SERIAL_MSR_DCD))
	{
	  //Putting this wait as a workaround to detect whether its a valid DCD event and 
      //the target is still connected to the host and not the cable has been removed.
	  usWait(500);
      msr = INB(pHWHead, pMSR);

     if (pHWHead->IOBase == BTUART_BASE_U_VIRTUAL)
	 {

	 }

	  if (msr & SERIAL_MSR_DCD)
	  {
       // If RLSD transitioned to active, we need to generate event.
       if (IsAPIReady(SH_WMGR))
	   {
        CeEventHasOccurred(NOTIFICATION_EVENT_RS232_DETECTED,NULL);
        DEBUGMSG(1|ZONE_EVENTS,(TEXT("****** HW_XSC1_ReadMSR NOTIFICATION_EVENT_RS232_DETECTED\r\n")));
		//NKDbgPrintfW(TEXT("HW_XSC1_ReadMSR msr:%X MSR:%X MCR:%X\r\n"), msr, pHWHead->MSR, pHWHead->MCR);
	   }
	  }
	}
//#endif

/*
#ifdef USE_TALISKER
	// If RLSD transitioned to active, we need to generate event.
    //DEBUGMSG(ZONE_EVENTS,(TEXT("************ HW_XSC1_ReadMSR EV_RLSD\r\n")));
    if ((pHWHead->OpenCount==0) && (msr & SERIAL_MSR_DDSR))
	{
      // If RLSD transitioned to active, we need to generate event.
      if (IsAPIReady(SH_WMGR))
	  {
        CeEventHasOccurred(NOTIFICATION_EVENT_RS232_DETECTED,NULL);
        DEBUGMSG(1|ZONE_EVENTS,(TEXT("****** HW_XSC1_ReadMSR NOTIFICATION_EVENT_RS232_DETECTED\r\n")));
	  }
	}
#endif
*/

	DEBUGMSG (ZONE_FUNCTION,(TEXT("-HW_XSC1_ReadMSR\r\n")));
}

#ifdef DEBUG
//
// This routine is used only for debugging, and performs a formatted
// ascii dump of the various UART registers.
//
VOID
HW_XSC1_DumpSerialRegisters(
                   PVOID  pHead
                   )
{
    ULONG            value;
    PSER16550_INFO   pHWHead   = (PSER16550_INFO)pHead;

    try {
        HW_XSC1_ReadLSR( pHWHead );
        value = pHWHead->LSR;

        NKDbgPrintfW(TEXT("Cotulla 16550 lsr: \t%2.2X\t"), value);
        if ( value & SERIAL_LSR_DR )
            NKDbgPrintfW(TEXT("DataReady "));
        if ( value & SERIAL_LSR_OE )
            NKDbgPrintfW(TEXT("OverRun "));
        if ( value & SERIAL_LSR_PE )
            NKDbgPrintfW(TEXT("ParityErr "));
        if ( value & SERIAL_LSR_FE )
            NKDbgPrintfW(TEXT("FramingErr "));
        if ( value & SERIAL_LSR_BI )
            NKDbgPrintfW(TEXT("BreakIntpt "));
        if ( value &  SERIAL_LSR_TDRQ )
            NKDbgPrintfW(TEXT("THREmpty "));
        if ( value & SERIAL_LSR_TEMT )
            NKDbgPrintfW(TEXT("TXEmpty "));
        if ( value & SERIAL_LSR_FIFOERR )
            NKDbgPrintfW(TEXT("FIFOErr "));
        NKDbgPrintfW(TEXT("\r\n"));

        value = INB(pHWHead, pTHR_RBR_DLL);
        NKDbgPrintfW(TEXT("Cotulla 16550 rbr/thr:\t%2.2X\r\n"), value);

        value = INB(pHWHead, pIER_DLH);
        NKDbgPrintfW(TEXT("Cotulla 16550 IER: \t%2.2X\t"), value);
        if ( value & SERIAL_IER_RAVIE )
            NKDbgPrintfW(TEXT("RXData "));
        if ( value & SERIAL_IER_TIE )
            NKDbgPrintfW(TEXT("TXData "));
        if ( value & SERIAL_IER_RLSE )
            NKDbgPrintfW(TEXT("RXErr "));
        if ( value & SERIAL_IER_MIE )
            NKDbgPrintfW(TEXT("ModemStatus "));
        if ( value & SERIAL_IER_RTOIE )
            NKDbgPrintfW(TEXT("RxTimeOut "));
        if ( value & SERIAL_IER_NRZE )
            NKDbgPrintfW(TEXT("NRZEncoding "));
        if ( value & SERIAL_IER_UUE )
            NKDbgPrintfW(TEXT("UartEnabled "));
        if ( value & SERIAL_IER_DMAE )
            NKDbgPrintfW(TEXT("DMAEnabled "));
        NKDbgPrintfW(TEXT("\r\n"));

        value = INB(pHWHead, pIIR_FCR);
        NKDbgPrintfW(TEXT("Cotulla 16550 iir: \t%2.2X\t"), value);
        if ( value & SERIAL_IIR_RDA )
            NKDbgPrintfW(TEXT("RXData "));
        if ( value & SERIAL_IIR_THRE )
            NKDbgPrintfW(TEXT("TXData "));
        if ( value & SERIAL_IIR_RLS )
            NKDbgPrintfW(TEXT("RXErr "));
        if ( (value & SERIAL_IIR_CTI) == SERIAL_IIR_CTI )
            NKDbgPrintfW(TEXT("CTI "));
        if ( value & SERIAL_IIR_MS )
            NKDbgPrintfW(TEXT("ModemStatus "));
        if (!( value | SERIAL_IIR_INTERRUPT_PENDING ))

⌨️ 快捷键说明

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