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

📄 xrser16550.c

📁 wince 5.0下 实现PCI8串口卡驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
////////////////////////////////////////
//(c) 2005 EXAR Corporation 
//All Rights Reserved.
//
//Exar Corporation ("Exar") hereby grants the User of this Exar 
//product-specific XR17C15x Windows CE.Net Device Driver (hereinafter 
//referred to as "Driver") a non-exclusive, nontransferable license 
//to use the Driver in accordance with the term set forth below.  
//Before using the Driver, the User should read the following use 
//restrictions.  If the User does not accept these terms, the Driver 
//should not be used or downloaded.
//The User is granted this limited license to use this Driver for 
//User's end product that includes the Exar XR17C158/XR17D158 Octal UART PCI 
//device, XR17C154/XR17D154 Quad UART PCI Device, and XR17C152/XR17D152 Dual UART 
//PCI Device and is not granted rights to sell, loan, rent, lease or 
//license the Driver, in whole or in part, or in modified form to anyone 
//other than User.  User may modify the Driver to suit its specific 
//applications but rights to derivative works and such modifications 
//shall belong to Exar.
//
//The Driver is provided on an "AS IS" basis and Exar makes absolutely 
//no warranty with respect to performance or the information contained 
//therein.  EXAR DISCLAIMS AND USER WAIVES ALL WARRANTIES, EXPRESS OR 
//IMPLIED, INCLUDING WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A 
//PARTICULAR PURPOSE.  The entire risk as to Driver quality and 
//performance is with the User.  ACCORDINGLY, IN NO EVENT SHALL EXAR 
//BE LIABLE FOR ANY DAMAGES, WHETHER IN CONTRACT OR TORT, INCLUDING 
//ANY LOST PROFITS OR OTHER INCIDENTAL, CONSEQUENTIAL, EXEMPLARY, OR 
//PUNITIVE DAMAGES ARISING OUT OF THE USE OR APPLICATION OF THE DRIVER.  
//Further, Exar reserves the right to make changes tot eh Driver without 
//notice to improve reliability, function or design.  Exar does not 
//convey any license under patent rights or any other intellectual 
//property rights, including those of third parties.
//
//Exar is not obligated to provide maintenance or support for the Driver. 
//
//////////////////////////////////////////////////////////
/*++
Module Name:  xrser16550.c

Abstract:  

    This file implements the standard device (PDD) specific functions for a 16550
    based serial device.

Functions:

    XRSL_Init()
    XRSL_PostInit()
    XRSL_Deinit()
    XRSL_Open()
    XRSL_Close()
    XRSL_ClearDTR()
    XRSL_SetDTR()
    XRSL_ClearRTS()
    XRSL_SetRTS()
    XRSL_ClearBreak()
    XRSL_SetBreak()
    XRSL_SetBaudRate()
    XRSL_SetByteSize()
    XRSL_SetParity()
    XRSL_SetStopBits()
    XRSL_GetRxBufferSize()
    XRSL_GetRxStart()
    XRSL_GetInterruptType()
    XRSL_RxIntr()
    XRSL_PutBytes()
    XRSL_TxIntr()
    XRSL_LineIntr()
    XRSL_OtherIntr()
    XRSL_GetStatus()
    XRSL_Reset()
    XRSL_GetModemStatus()
    XRSL_PurgeComm()
    XRSL_XmitComChar()
    XRSL_PowerOff()
    XRSL_PowerOn()
    XRSL_SetDCB()
    XRSL_SetCommTimeouts()
    XRSL_Ioctl()
    ReadLSR()
    ReadMSR()
    DumpSerialRegisters()
    LookUpValue()
    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 <nkintr.h>
#include <ceddk.h>
#include <memory.h>
#include <devload.h>
#include <ddkreg.h>
#include <serhw.h>
#include "..\xrisr\xrisr.h"
#include "ser16550.h"
#include "hw16550.h"
#include <serdbg.h>
#include <excpt.h>
#include <pm.h>


#include "xrcom16550.h"
#include "xrser16550.h"


// Macros to read/write serial registers.
#define INB(pInfo, reg) (READ_REGISTER_UCHAR((pInfo)->reg))
#define OUTB(pInfo, reg, value) (WRITE_REGISTER_UCHAR(((pInfo)->reg), (unsigned char)(value)))


#define Read1Byte(pInfo,reg) (READ_REGISTER_UCHAR(pInfo + reg))    
#define Write1Byte(pInfo,reg, value) (WRITE_REGISTER_UCHAR((pInfo+reg), (unsigned char)(value)))


BOOL XRSL_SetByteSize(PVOID pHead, ULONG ByteSize);
BOOL XRSL_SetStopBits(PVOID pHead, ULONG StopBits);
BOOL XRSL_SetParity(PVOID pHead, ULONG Parity);

#define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION 

//
// 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 ProcessLSR (PSER16550_INFO  pHWHead)
{
    ULONG LineEvents = 0;
    if ( 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")));
            pHWHead->DroppedBytes++;
            pHWHead->CommErrors |= CE_OVERRUN;
        }

        if ( pHWHead->LSR & SERIAL_LSR_PE ) {
            // DEBUGMSG (ZONE_WARN, (TEXT("parity\r\n")));
            pHWHead->CommErrors |= CE_RXPARITY;
        }

        if ( pHWHead->LSR & SERIAL_LSR_FE ) {
            // DEBUGMSG (ZONE_WARN, (TEXT("frame\r\n")));
            pHWHead->CommErrors |= CE_FRAME;
        }

        LineEvents |= EV_ERR;
    }

    if ( pHWHead->LSR & SERIAL_LSR_BI )
        LineEvents |= EV_BREAK;

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

}
__inline
VOID
ReadLSR(
       PSER16550_INFO  pHWHead
       )
{

    try {
        pHWHead->LSR = INB(pHWHead, pLSR);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        pHWHead->LSR = SERIAL_LSR_THRE;
    }
	ProcessLSR (pHWHead);
}

//
// 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 ProcessMSR (PSER16550_INFO  pHWHead)
{

    ULONG        Events = 0;
    // For changes, we use callback to evaluate the event
    if (pHWHead->MSR  & SERIAL_MSR_DCTS)
        Events |= EV_CTS;

    if ( pHWHead->MSR  & SERIAL_MSR_DDSR )
        Events |= EV_DSR;

    if ( pHWHead->MSR  & SERIAL_MSR_TERI )
        Events |= EV_RING;

    if ( pHWHead->MSR  & SERIAL_MSR_DDCD )
        Events |= EV_RLSD;

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

}
__inline
VOID
ReadMSR(
       PSER16550_INFO  pHWHead
       )
{
    UCHAR       msr;

    try {
        msr = INB(pHWHead, pMSR);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        msr = 0;
    }

    // Save the MSR value in a shadow
    pHWHead->MSR = msr;
    ProcessMSR (pHWHead);
}

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


    try {
        ReadLSR( pHWHead );
        byte = pHWHead->LSR;

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

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

        byte = INB(pHWHead, pIER);
        NKDbgPrintfW(TEXT("16550 IER: \t%2.2X\t"), byte);
        if ( byte & SERIAL_IER_RDA )
            NKDbgPrintfW(TEXT("RXData "));
        if ( byte & SERIAL_IER_THR )
            NKDbgPrintfW(TEXT("TXData "));
        if ( byte & SERIAL_IER_RLS )
            NKDbgPrintfW(TEXT("RXErr "));
        if ( byte & SERIAL_IER_MS )
            NKDbgPrintfW(TEXT("ModemStatus "));
        NKDbgPrintfW(TEXT("\r\n"));

        byte = INB(pHWHead, pIIR_FCR);
        NKDbgPrintfW(TEXT("16550 iir: \t%2.2X\t"), byte);
        if ( byte & SERIAL_IIR_RDA )
            NKDbgPrintfW(TEXT("RXData "));
        if ( byte & SERIAL_IIR_THRE )
            NKDbgPrintfW(TEXT("TXData "));
        if ( byte & SERIAL_IIR_RLS )
            NKDbgPrintfW(TEXT("RXErr "));
        if ( (byte & SERIAL_IIR_CTI) == SERIAL_IIR_CTI )
            NKDbgPrintfW(TEXT("CTI "));
        if ( byte == SERIAL_IIR_MS )
            NKDbgPrintfW(TEXT("ModemStatus "));
        if ( byte & 0x01 )
            NKDbgPrintfW(TEXT("IntPending "));
        NKDbgPrintfW(TEXT("\r\n"));

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

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

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

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

        ReadMSR( pHWHead );
        byte = pHWHead->MSR;
        NKDbgPrintfW(TEXT("16550 msr: \t%2.2X\t"), byte);
        if ( byte & SERIAL_MSR_DCTS )
            NKDbgPrintfW(TEXT("DCTS "));
        if ( byte & SERIAL_MSR_DDSR )
            NKDbgPrintfW(TEXT("DDSR "));
        if ( byte & SERIAL_MSR_TERI )
            NKDbgPrintfW(TEXT("TERI "));
        if ( byte & SERIAL_MSR_DDCD )
            NKDbgPrintfW(TEXT("DDCD"));
        if ( byte & SERIAL_MSR_CTS )
            NKDbgPrintfW(TEXT(" CTS"));
        if ( byte & SERIAL_MSR_DSR )
            NKDbgPrintfW(TEXT("DSR "));
        if ( byte & SERIAL_MSR_RI )
            NKDbgPrintfW(TEXT("RI "));
        if ( byte & 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
LookUpValue(
           ULONG    Key,
           PLOOKUP_TBL pTbl,
           PULONG    pErrorCode

⌨️ 快捷键说明

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