📄 xrisr.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 + -