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

📄 xrisr.c

📁 wince 5.0下 实现PCI8串口卡驱动
💻 C
字号:
////////////////////////////////////////
//(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. 
//
////////////////////////////////////////////////////////
// xrisr.c
//
// Eaxr's PCI UART Installable Interrupt Service Routine.
//
#include <windows.h>
#include <nkintr.h>
#include <ceddk.h>
#include <hw16550.h>

#include "xrisr.h"

static UCHAR ReadByte(PISR16550_INFO pBlockVirt,DWORD dwOffset) {
    if (pBlockVirt->lIoSpace)
        return READ_PORT_UCHAR(pBlockVirt->pIoAddress + (dwOffset*(pBlockVirt->uMultiplier)));
    else
        return READ_REGISTER_UCHAR(pBlockVirt->pIoAddress + (dwOffset*(pBlockVirt->uMultiplier)));
}
static void  WriteByte(PISR16550_INFO pBlockVirt,DWORD dwOffset,UCHAR bData) {
    if (pBlockVirt->lIoSpace)
        WRITE_PORT_UCHAR(pBlockVirt->pIoAddress + (dwOffset*(pBlockVirt->uMultiplier)), bData);
    else
        WRITE_REGISTER_UCHAR(pBlockVirt->pIoAddress + (dwOffset*(pBlockVirt->uMultiplier)), bData);
}

static DWORD DataReceivedIsr(PISR16550_INFO pBlockVirt,BYTE intrFlag,DWORD dwMaxByte)
{
    PRcvDataBuffer pReceiveBuffer= (PRcvDataBuffer)((PBYTE)pBlockVirt + pBlockVirt->InBufferOffset);
    DWORD dwDataBytes=0;
    DWORD dwDataSize;
    DEBUGMSG(0, (TEXT("Isr165550::+DataReceivedIsr \r\n")));
    if (pReceiveBuffer->dwBufferSize) {
#ifndef DO_NOT_USE_EXTENDED_FUNCTIONALITY
	dwMaxByte = ReadByte(pBlockVirt,11); //XR_17C15X_RXFIFO_CNT
#endif
        while (dwMaxByte && GetRcvAvailableBuffer(pReceiveBuffer)>1 && (ReadByte(pBlockVirt,LINE_STATUS_REGISTER) & SERIAL_LSR_DR )) { // Data Ready to read
            pReceiveBuffer->bBuffer[pReceiveBuffer->dwFIFO_In].bIntFlag =intrFlag;
#ifdef DO_NOT_USE_EXTENDED_FUNCTIONALITY
			pReceiveBuffer->bBuffer[pReceiveBuffer->dwFIFO_In].bIntData=ReadByte(pBlockVirt,RECEIVE_BUFFER_REGISTER);
#else
			pReceiveBuffer->bBuffer[pReceiveBuffer->dwFIFO_In].bIntData=ReadByte(pBlockVirt,0x100);//UART_17158_RX_OFFSET
#endif
            pReceiveBuffer->dwFIFO_In=IncRcvIndex(pReceiveBuffer,pReceiveBuffer->dwFIFO_In);
            dwDataBytes++;
            dwMaxByte--;
        };
        dwDataSize=GetRcvDataSize(pReceiveBuffer);
        DEBUGMSG(0, (TEXT("Isr165550::-DataReceivedIsr DataUnloaded %d, BufferSize=%d\r\n"),dwDataBytes,dwDataSize));

        if (dwDataSize<pReceiveBuffer->dwWaterMark && dwDataSize < pReceiveBuffer->dwBufferSize-1 ) { // Not over the mark yet
            return SYSINTR_NOP;// This will trigger OEMISR to clear the interrupt controller.
        }
        else // Over the mark, signal the IST
            return pBlockVirt->SysIntr;
    }
    else 
        return  pBlockVirt->SysIntr; // ISR Input Buffering is not supported, Signal IST.
}
static DWORD DataXmitEmptyIsr(PISR16550_INFO pBlockVirt,BYTE intrFlag)
{
    PXmitDataBuffer pXmitBuffer= (PXmitDataBuffer)((PBYTE)pBlockVirt + pBlockVirt->OutBufferOffset);
    DWORD dwDataBytes=0;
    DWORD dwDataSize;
	WORD wIndex;
    DEBUGMSG(0, (TEXT("Isr165550::+DataXmitIsr \r\n")));
    if (pXmitBuffer->dwBufferSize) {
        if ( ReadByte(pBlockVirt ,LINE_STATUS_REGISTER) & SERIAL_LSR_THRE ) { //FIFO Empty.
#ifdef DO_NOT_USE_EXTENDED_FUNCTIONALITY
            WORD byteCount=( intrFlag & SERIAL_IIR_FIFOS_ENABLED )?SERIAL_FIFO_DEPTH:1;
#else
            //WORD byteCount=( intrFlag & SERIAL_IIR_FIFOS_ENABLED )?64:1; 
			WORD byteCount=ReadByte(pBlockVirt, 10); //XR_17C15X_TXFIFO_CNT-10
			byteCount = 64 - byteCount;
#endif
            for (wIndex=0;wIndex<byteCount && GetXmitDataSize(pXmitBuffer)>0;wIndex++) {                
#ifdef DO_NOT_USE_EXTENDED_FUNCTIONALITY
                WriteByte(pBlockVirt,TRANSMIT_HOLDING_REGISTER,pXmitBuffer->bBuffer[pXmitBuffer->dwFIFO_Out]);
#else
				WriteByte(pBlockVirt, 0x100, pXmitBuffer->bBuffer[pXmitBuffer->dwFIFO_Out]);//UART_17158_TX_OFFSET-0x100
#endif 
                pXmitBuffer->dwFIFO_Out=IncXmitIndex(pXmitBuffer,pXmitBuffer->dwFIFO_Out);
                dwDataBytes++;
            }
        }
        dwDataSize=GetXmitDataSize(pXmitBuffer);
        DEBUGMSG(0, (TEXT("Isr165550::-XmitIsr DataUnloaded %d, BufferSize=%d\r\n"),dwDataBytes,dwDataSize));
        //if (dwDataSize<pXmitBuffer->dwWaterMark && dwDataSize < pXmitBuffer->dwBufferSize-1) { 
        // Water mark for transfer may not work will, Try other.
        if (!dwDataBytes) { // if buffer Empty.
            return pBlockVirt->SysIntr;
        }
        else 
            return SYSINTR_NOP;// This will trigger OEMISR to clear the interrupt controller.
    }
    else 
        return pBlockVirt->SysIntr; // ISR Input Buffering is not supported, Signal IST.
}
static DWORD Isr16550(PISR16550_INFO pBlockVirt)
{
    DWORD dwReturn=SYSINTR_CHAIN;
    DWORD dwTotalReturn=SYSINTR_CHAIN;
    if (pBlockVirt  && pBlockVirt->pIoAddress) {
        BYTE bIntFlag=SERIAL_IIR_INT_INVALID,bIntData=0;
        BOOL  bContinueLoop=TRUE;
        while (bContinueLoop) {
            bIntFlag=ReadByte(pBlockVirt,INTERRUPT_IDENT_REGISTER);
            DEBUGMSG(0, (TEXT("Isr165550::ISRHandler 0x%x \r\n"),bIntFlag));
            if (bIntFlag & SERIAL_IIR_INT_INVALID)
                break;
            else {
                dwReturn=SYSINTR_NOP;
                switch ( bIntFlag & SERIAL_IIR_INT_MASK ) {
                case SERIAL_IIR_RDA:
                    {
                        // Set Maxmum data we can read is
                        DWORD dwDataSize=pBlockVirt->dwReceiveHWWaterMaker;
                        dwDataSize = (dwDataSize>2?dwDataSize-1:1);
                        dwReturn= DataReceivedIsr(pBlockVirt,bIntFlag,dwDataSize);
                        break;
                    }
                case SERIAL_IIR_THRE : {
                    PRcvDataBuffer pReceiveBuffer= (PRcvDataBuffer)((PBYTE)pBlockVirt + pBlockVirt->InBufferOffset);
                    dwReturn=DataXmitEmptyIsr(pBlockVirt ,bIntFlag);
                    if (dwReturn ==pBlockVirt->SysIntr && GetRcvAvailableBuffer(pReceiveBuffer)>1 ) { // Want to notify the IST. So
                        pReceiveBuffer->bBuffer[pReceiveBuffer->dwFIFO_In].bIntFlag =SERIAL_IIR_THRE;
                        pReceiveBuffer->bBuffer[pReceiveBuffer->dwFIFO_In].bIntData=0;
                        pReceiveBuffer->dwFIFO_In=IncRcvIndex(pReceiveBuffer,pReceiveBuffer->dwFIFO_In);
                    }
                    break;
                }
                case SERIAL_IIR_CTI:
                case SERIAL_IIR_CTI_2:
                    DataReceivedIsr(pBlockVirt ,bIntFlag,(DWORD)-1); // Do not return any flag thatindicate IST will trigger.
                    dwReturn= pBlockVirt->SysIntr;
                    break;
                case SERIAL_IIR_RLS: {
                    PRcvDataBuffer pReceiveBuffer= (PRcvDataBuffer)((PBYTE)pBlockVirt + pBlockVirt->InBufferOffset);
                    if (GetRcvAvailableBuffer(pReceiveBuffer)>1) {
                        pReceiveBuffer->bBuffer[pReceiveBuffer->dwFIFO_In].bIntFlag =SERIAL_IIR_RLS;
                        pReceiveBuffer->bBuffer[pReceiveBuffer->dwFIFO_In].bIntData=ReadByte(pBlockVirt,LINE_STATUS_REGISTER);
                        pReceiveBuffer->dwFIFO_In=IncRcvIndex(pReceiveBuffer,pReceiveBuffer->dwFIFO_In);
                    }
                    dwReturn= pBlockVirt->SysIntr;
                    break;
                }
                case SERIAL_IIR_MS: {
                    PRcvDataBuffer pReceiveBuffer= (PRcvDataBuffer)((PBYTE)pBlockVirt + pBlockVirt->InBufferOffset);
                    if (GetRcvAvailableBuffer(pReceiveBuffer)>1) {
                        pReceiveBuffer->bBuffer[pReceiveBuffer->dwFIFO_In].bIntFlag =SERIAL_IIR_MS;
                        pReceiveBuffer->bBuffer[pReceiveBuffer->dwFIFO_In].bIntData=ReadByte(pBlockVirt,MODEM_STATUS_REGISTER);
                        pReceiveBuffer->dwFIFO_In=IncRcvIndex(pReceiveBuffer,pReceiveBuffer->dwFIFO_In);
                    }
                    dwReturn= pBlockVirt->SysIntr;
                    break;
                }
                default:{
                    // Received Wrong Data.
                    PRcvDataBuffer pReceiveBuffer= (PRcvDataBuffer)((PBYTE)pBlockVirt + pBlockVirt->InBufferOffset);
                    if (GetRcvAvailableBuffer(pReceiveBuffer)>1) {
                        pReceiveBuffer->bBuffer[pReceiveBuffer->dwFIFO_In].bIntFlag = SERIAL_IIR_INT_MASK;
                        pReceiveBuffer->bBuffer[pReceiveBuffer->dwFIFO_In].bIntData = bIntFlag ;
                        pReceiveBuffer->dwFIFO_In=IncRcvIndex(pReceiveBuffer,pReceiveBuffer->dwFIFO_In);
                    }
                    dwReturn= pBlockVirt->SysIntr;
                    bContinueLoop=FALSE;
                    break;
                }
                }
                {
                    PRcvDataBuffer pReceiveBuffer= (PRcvDataBuffer)((PBYTE)pBlockVirt + pBlockVirt->InBufferOffset);
                    if (GetRcvAvailableBuffer(pReceiveBuffer) <= 1 ) { // Data Full. So break Interrupt Anyway.
                        dwReturn = pBlockVirt->SysIntr;
                        bContinueLoop = FALSE;
                    }
                }
            }
            if (dwTotalReturn!=dwReturn) {
                if (dwTotalReturn == SYSINTR_CHAIN){
                    dwTotalReturn = dwReturn;
                }
                else 
                if (dwTotalReturn == SYSINTR_NOP && dwReturn == pBlockVirt->SysIntr) {
                    dwTotalReturn = dwReturn;
                }
                    
            }
        };
    }
    return dwTotalReturn ;
}

// Globals
#define MAX_ISR16550_INSTANCES 0x10
static PISR16550_INFO Isr16550Handle[MAX_ISR16550_INSTANCES]= {NULL,};
#define INVALID_ISR16550_HANDLE (PISR16550_INFO)(-1)

static BOOL Init(DWORD dwIndex,PISR16550_INFO pBuffer)
{
    if (dwIndex<MAX_ISR16550_INSTANCES && Isr16550Handle[dwIndex]==INVALID_ISR16550_HANDLE){
        Isr16550Handle[dwIndex]=pBuffer;
        return TRUE;
    }
    else
        return FALSE;
}
/*
 @doc INTERNAL
 @func    BOOL | DllEntry | Process attach/detach api.
 *
 @rdesc The return is a BOOL, representing success (TRUE) or failure (FALSE).
 */
BOOL __stdcall
DllEntry(
    HINSTANCE hinstDll,         // @parm Instance pointer.
    DWORD dwReason,             // @parm Reason routine is called.
    LPVOID lpReserved           // @parm system parameter.
     )
{
    DWORD dwCount;
    if (dwReason == DLL_PROCESS_ATTACH) {
        for (dwCount=0;dwCount<MAX_ISR16550_INSTANCES;dwCount++)
            Isr16550Handle[dwCount]=NULL;
    }
    else
    if (dwReason == DLL_PROCESS_DETACH) { 
        // Current We had nowhere else can call this routine. 
        //It should can another call call DeCreateInstance that invoke when ISR is uninstalled.
        for (dwCount=0;dwCount<MAX_ISR16550_INSTANCES;dwCount++)
            if (Isr16550Handle[dwCount]!=NULL) {
                Isr16550Handle[dwCount]=NULL;
            }

    }
    return TRUE;
}

DWORD CreateInstance(
    void
    )
{
    DWORD dwCount;
    // Search For empty ISR Handle.
    for (dwCount=0;dwCount<MAX_ISR16550_INSTANCES;dwCount++)
        if (Isr16550Handle[dwCount]==NULL)
            break;
    if (dwCount>=MAX_ISR16550_INSTANCES) // FULL.
        return (DWORD)-1;
    else
        Isr16550Handle[dwCount]=INVALID_ISR16550_HANDLE;
    return dwCount;
}


BOOL 
IOControl(
    DWORD   InstanceIndex,
    DWORD   IoControlCode, 
    LPVOID  pInBuf, 
    DWORD   InBufSize,
    LPVOID  pOutBuf, 
    DWORD   OutBufSize, 
    LPDWORD pBytesReturned
    ) 
{
    if (pBytesReturned) {
        *pBytesReturned = 0;
    }
    switch (IoControlCode) {
    case IOCTL_ISR16550_INFO:
        if ((InBufSize < sizeof(ISR16550_INFO)) || !pInBuf || 
            InstanceIndex>=MAX_ISR16550_INSTANCES ) {
            // Invalid IOCTL code or size of input buffer or input buffer pointer
            return FALSE;
        }
        else 
            return Init(InstanceIndex,(PISR16550_INFO)pInBuf);
    case IOCTL_ISR16550_UNLOAD:
        if (InstanceIndex>=MAX_ISR16550_INSTANCES || Isr16550Handle[InstanceIndex]==NULL )
            return FALSE;
        else {
            Isr16550Handle[InstanceIndex]=NULL;
            return TRUE;
        }

    }
    return FALSE;
}
DWORD
ISRHandler(
    DWORD InstanceIndex
    )
{
    if (InstanceIndex<MAX_ISR16550_INSTANCES && 
            Isr16550Handle[InstanceIndex]!=NULL &&
            Isr16550Handle[InstanceIndex]!=INVALID_ISR16550_HANDLE)
        return Isr16550(Isr16550Handle[InstanceIndex]);
    else
        return SYSINTR_CHAIN;
}
void DestroyInstance(
    DWORD InstanceIndex 
    )
{
    if (InstanceIndex<MAX_ISR16550_INSTANCES && Isr16550Handle[InstanceIndex]!=NULL )
        Isr16550Handle[InstanceIndex]=NULL;
}

⌨️ 快捷键说明

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