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

📄 xrmdd.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:  xrmdd.c

Abstract:  

This file contains the serial mdd (model device driver) code.  This is
intended to work with a series of serial pdds to implement serial
devices for the WinCE OS.  

Functions:
COM_Init
COM_Open
COM_Close
COM_Deinit
COM_Read
COM_Write
COM_Seek
COM_PowerUp
COM_PowerDown
COM_IOControl
DllEntry
SerialEventHandler
SerialDispatchThread
ApplyDCB
SerialGetDroppedByteNumber
WaitCommEvent
EvaluateEventFlag
ProcessExiting


Notes: 


--*/
#include <windows.h>
#include <types.h>
#include <memory.h>
#include <linklist.h>
#include <nkintr.h>
#include <serdbg.h>
#include <hwcomapi.h>
#include <pegdser.h>
#include <devload.h>
#include <pm.h>
#include <pkfuncs.h>


#include "xrserpriv.h"

/* Debug Zones.
 */
#ifdef DEBUG

    #define DBG_INIT    0x0001
    #define DBG_OPEN    0x0002
    #define DBG_READ    0x0004
    #define DBG_WRITE   0x0008
    #define DBG_CLOSE   0x0010
    #define DBG_IOCTL   0x0020
    #define DBG_THREAD  0x0040
    #define DBG_EVENTS  0x0080
    #define DBG_CRITSEC 0x0100
    #define DBG_FLOW    0x0200
    #define DBG_IR      0x0400
    #define DBG_NOTHING 0x0800
    #define DBG_ALLOC   0x1000
    #define DBG_FUNCTION 0x2000
    #define DBG_WARNING 0x4000
    #define DBG_ERROR   0x8000

DBGPARAM dpCurSettings = {
    TEXT("Serial"), {
        TEXT("Init"),TEXT("Open"),TEXT("Read"),TEXT("Write"),
        TEXT("Close"),TEXT("Ioctl"),TEXT("Thread"),TEXT("Events"),
        TEXT("CritSec"),TEXT("FlowCtrl"),TEXT("Infrared"),TEXT("User Read"),
        TEXT("Alloc"),TEXT("Function"),TEXT("Warning"),TEXT("Error")},
    0
}; 
#endif

#ifndef MIN
    #define MIN(x,y)		((x) < (y) ? (x) : (y))
#endif

//
// Macros to maintain a usage count for a particular serial structure,
// so that we know when it is safe to deallocate it.
//
#define COM_INC_USAGE_CNT(pOpenHead)  \
    InterlockedIncrement(&pOpenHead->StructUsers)

#define COM_DEC_USAGE_CNT(pOpenHead)  \
    InterlockedDecrement(&pOpenHead->StructUsers)

// Define some internally used functions
BOOL COM_Close(PHW_OPEN_INFO    pOpenHead);
BOOL COM_Deinit(PHW_INDEP_INFO pSerialHead);
VOID EvaluateEventFlag(PVOID pHead, ULONG fdwEventMask);

/*
 @doc INTERNAL
 @func	BOOL | DllEntry | Process attach/detach api.
 *
 @rdesc The return is a BOOL, representing success (TRUE) or failure (FALSE).
 */
BOOL
DllEntry(
              HINSTANCE   hinstDll,             /*@parm Instance pointer. */
              DWORD   dwReason,                 /*@parm Reason routine is called. */
              LPVOID  lpReserved                /*@parm system parameter. */
              )
{
    if ( dwReason == DLL_PROCESS_ATTACH ) {
        DEBUGREGISTER(hinstDll);
        DEBUGMSG (ZONE_INIT, (TEXT("serial port process attach\r\n")));
	DisableThreadLibraryCalls((HMODULE) hinstDll);
    }

    if ( dwReason == DLL_PROCESS_DETACH ) {
        DEBUGMSG (ZONE_INIT, (TEXT("process detach called\r\n")));
    }

    return(TRUE);
}

/*
 @doc INTERNAL
 @func	VOID | DoTxData | Sends next available chunk of TX data.
 *
 */
VOID
DoTxData( PHW_INDEP_INFO pSerialHead )
{
    PHW_VTBL            pFuncTbl = pSerialHead->pHWObj->pFuncTbl;
    PVOID               pHWHead = pSerialHead->pHWHead;
    ULONG               Len;



    DEBUGMSG (ZONE_WRITE, (TEXT("DoPutBytes wait for CritSec %x.\r\n"),
                           &(pSerialHead->TxBufferInfo.CS)));
    TxEnterCS(pSerialHead);
    DEBUGMSG (ZONE_WRITE, (TEXT("DoPutBytes got CritSec %x.\r\n"),
                           &(pSerialHead->TxBufferInfo.CS)));

    // If device was closed from under us, stop transmitting
    if ( !pSerialHead->OpenCnt ) {
        DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("Device closed! Quit transmission!\r\n")));
        DEBUGMSG (ZONE_WRITE,
                  (TEXT("SerialEventHandler: %d sent up-to-now.\n\r"),pSerialHead->TxBytesSent));
        pSerialHead->TxBufferInfo.Permissions = 0;
        pSerialHead->TxBufferInfo.TxCharBuffer = NULL;
        pSerialHead->TxBufferInfo.Length = 0;
        TxRead(pSerialHead) = 0;
    }

    // Check the flow control status, and if not flowed off, call the
    // hw TX routine to actually transmit some data.
    if ( pSerialHead->TxBufferInfo.TxCharBuffer && TxBytesAvail(pSerialHead) ) {
        DWORD oldPerm = SetProcPermissions(pSerialHead->TxBufferInfo.Permissions);

        if ( pSerialHead->DCB.fRtsControl == RTS_CONTROL_TOGGLE ) {
            DEBUGMSG (ZONE_THREAD|ZONE_WRITE , (TEXT("RTS set.\r\n")));
            pFuncTbl->HWSetRTS(pHWHead);
        }

        // Don't transmit anything if we are flowed off.
        if ( pSerialHead->StopXmit ) {
            // But we still need to call TxIntrHandler so that the interrupt
            // gets cleared.
            DEBUGMSG (ZONE_FLOW|ZONE_WRITE , (TEXT("XOFF'ed, send nothing.\r\n")));
            Len = 0;
        } else {
            DEBUGMSG (ZONE_WRITE,
                      (TEXT("TxRead = %d, TxLength = %d, TxBytesAvail = %d.\r\n"),
                       TxRead(pSerialHead), TxLength(pSerialHead),
                       TxBytesAvail(pSerialHead)));
            Len = TxBytesAvail(pSerialHead);
        }
        DEBUGMSG (ZONE_WRITE, (TEXT("About to copy %d bytes\r\n"), Len));
        pFuncTbl->HWTxIntrHandler(pHWHead,
                                  TxBuffRead(pSerialHead),
                                  &Len);
        DEBUGMSG (ZONE_WRITE, (TEXT("%d bytes actually copied.\r\n"), Len));
        // Update Fifo info
        pSerialHead->TxBytes += Len;
        pSerialHead->TxBytesSent += Len;
        TxRead(pSerialHead) += Len;

        // Even if everything was Tx'ed, don't signal TX complete until
        // we get transmit interrupt indicating that the data has
        // actually been sent.  Since few/no UARTS have a way to tell
        // how much data remains, we don't bother trying to adjust the
        // return length to account for partially completed hardware buffer TX
        SetProcPermissions(oldPerm);
    } else {
        // Even if there is nothing left to send, we need to call
        // the interrupt handler so that it can clear the
        // transmit interrupt
        Len = 0;
        pFuncTbl->HWTxIntrHandler(pHWHead,
                                  NULL,
                                  &Len);        
        DEBUGMSG (ZONE_WRITE, (TEXT("Transmission complete, %d bytes sent\r\n"), Len));
        pSerialHead->TxBufferInfo.Permissions = 0;
        pSerialHead->TxBufferInfo.TxCharBuffer = NULL;
        pSerialHead->TxBufferInfo.Length = 0;
        TxRead(pSerialHead) = 0;
        SetEvent(pSerialHead->hTransmitEvent);
    }

    TxLeaveCS(pSerialHead);
    DEBUGMSG (ZONE_WRITE|ZONE_FUNCTION,
              (TEXT("DoPutBytes released CritSec: %x.\r\n"),
               &(pSerialHead->TxBufferInfo.CS)));

}

VOID
SerialEventHandler(PHW_INDEP_INFO       pSerialHead)
{
    PHW_VTBL            pFuncTbl = pSerialHead->pHWObj->pFuncTbl;
    PVOID               pHWHead = pSerialHead->pHWHead;
    ULONG               CharIndex;
    ULONG               RoomLeft = 0;
    ULONG               TotalLeft = 0;
    INTERRUPT_TYPE      it = INTR_NONE;
    BOOL                RxDataAvail = FALSE;

    DEBUGMSG (ZONE_THREAD, (TEXT("+SerialEventHandler, pHead 0x%X\r\n"),
                            pSerialHead));

    if ( pSerialHead->KillRxThread ||
         !pSerialHead->hSerialEvent ) {
        DEBUGMSG (ZONE_THREAD, (TEXT("Exitting thread\r\n")));
        SetEvent(pSerialHead->hKillDispatchThread);
        ExitThread(0);
    }

// NOTE - This one is a little tricky.  If the only owner is a monitoring task
// then I don't have an owner for read/write, yet I might be in this routine
// due to a change in line status.  Lets just do the best we can and increment
// the count for the access owner if available.
    if ( pSerialHead->pAccessOwner )
        COM_INC_USAGE_CNT(pSerialHead->pAccessOwner);

    while ( 1 ) {

        if ( !(it = pFuncTbl->HWGetIntrType(pHWHead)) ) {
            DEBUGMSG (ZONE_THREAD,
                      (TEXT("SerialEventHandler, No Interrupt.\r\n")));
            break;
        }

        DEBUGMSG (ZONE_THREAD,
                  (TEXT("SerialEventHandler, Interrupts 0x%X\r\n"), it));
        if ( it & INTR_RX ) {
            // It's read data event. Optimize the read by reading chunks
            // if the user has not specified using xflow control
            // or event/error/eof characters. Ack the receive,
            // unmask the interrupt, get the current data pointer
            // and see if data is available.
            // Note: We have to copy RxRead and RxWrite index to local in order to make it atomic.
            register DWORD RxWIndex=RxWrite(pSerialHead), RxRIndex=RxRead(pSerialHead);

            DEBUGMSG (ZONE_THREAD|ZONE_READ , (TEXT("Rx Event\r\n")));

            if ( RxRIndex == 0 ) {
                // have to leave one byte free.
                RoomLeft = RxLength(pSerialHead) - RxWIndex - 1;
            } else {
                RoomLeft = RxLength(pSerialHead) - RxWIndex;
            }
            if ( RxRIndex > RxWIndex ) {
                RoomLeft = RxRIndex - RxWIndex - 1;
            }
            if ( RoomLeft ) {
                pSerialHead->DroppedBytesPDD +=
                pFuncTbl->HWRxIntrHandler(pHWHead,
                                          RxBuffWrite(pSerialHead),
                                          &RoomLeft);
            } else {
                BYTE    TempBuf[16];
                RoomLeft = 16;
                pFuncTbl->HWRxIntrHandler(pHWHead,
                                          TempBuf,
                                          &RoomLeft);

                pSerialHead->DroppedBytesMDD += RoomLeft;
                DEBUGMSG (ZONE_WARN|ZONE_READ, (TEXT("Tossed %d bytes\r\n"),
                                                RoomLeft));
                RoomLeft = 0;
            }

            DEBUGMSG (ZONE_READ ,
                      (TEXT("After HWGetBytes, Fifo(R=%d,W=%d,BA=%d,L=%d) ByteRead=%d\r\n"),
                       RxRead(pSerialHead), RxWrite(pSerialHead),

⌨️ 快捷键说明

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