📄 xrser16550.c
字号:
// @func BOOL | XRSL_SetByteSize |
// This routine sets the WordSize of the device.
//
// @rdesc None.
//
BOOL
XRSL_SetByteSize(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG ByteSize // @parm ULONG ByteSize field from DCB.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
UINT8 lcr;
BOOL bRet;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+XRSL_SetByteSize 0x%X, x%X\r\n"), pHead, ByteSize));
bRet = TRUE;
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
lcr = INB(pHWHead, pLCR);
lcr &= ~SERIAL_DATA_MASK;
switch ( ByteSize ) {
case 5:
lcr |= SERIAL_5_DATA;
break;
case 6:
lcr |= SERIAL_6_DATA;
break;
case 7:
lcr |= SERIAL_7_DATA;
break;
case 8:
lcr |= SERIAL_8_DATA;
break;
default:
bRet = FALSE;
break;
}
if (bRet) {
OUTB(pHWHead, pLCR, lcr);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
bRet = FALSE;
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-XRSL_SetByteSize 0x%X\r\n"), pHead));
return(bRet);
}
//
// @doc OEM
// @func BOOL | XRSL_SetParity |
// This routine sets the parity of the device.
//
// @rdesc None.
//
BOOL
XRSL_SetParity(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG Parity // @parm ULONG parity field from DCB.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
UINT8 lcr;
BOOL bRet;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+XRSL_SetParity 0x%X, x%X\r\n"), pHead, Parity));
bRet = TRUE;
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
lcr = INB(pHWHead, pLCR);
lcr &= ~SERIAL_PARITY_MASK;
switch ( Parity ) {
case ODDPARITY:
lcr |= SERIAL_ODD_PARITY;
break;
case EVENPARITY:
lcr |= SERIAL_EVEN_PARITY;
break;
case MARKPARITY:
lcr |= SERIAL_MARK_PARITY;
break;
case SPACEPARITY:
lcr |= SERIAL_SPACE_PARITY;
break;
case NOPARITY:
lcr |= SERIAL_NONE_PARITY;
break;
default:
bRet = FALSE;
break;
}
if (bRet) {
OUTB(pHWHead, pLCR, lcr);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
bRet = FALSE;
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-XRSL_SetParity 0x%X\r\n"), pHead));
return(bRet);
}
//
// @doc OEM
// @func VOID | XRSL_SetStopBits |
// This routine sets the Stop Bits for the device.
//
// @rdesc None.
//
BOOL
XRSL_SetStopBits(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG StopBits // @parm ULONG StopBits field from DCB.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
UINT8 lcr;
BOOL bRet;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+XRSL_SetStopBits 0x%X, x%X\r\n"), pHead, StopBits));
bRet = TRUE;
EnterCriticalSection(&(pHWHead->RegCritSec));
lcr = INB(pHWHead, pLCR);
lcr &= ~SERIAL_STOP_MASK;
try {
// Note that 1.5 stop bits only works if the word size
// is 5 bits. Any other xmit word size will cause the
// 1.5 stop bit setting to generate 2 stop bits.
switch ( StopBits ) {
case ONESTOPBIT :
lcr |= SERIAL_1_STOP ;
break;
case ONE5STOPBITS :
lcr |= SERIAL_1_5_STOP ;
break;
case TWOSTOPBITS :
lcr |= SERIAL_2_STOP ;
break;
default:
bRet = FALSE;
break;
}
if (bRet) {
OUTB(pHWHead, pLCR, lcr);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
bRet = FALSE;
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-XRSL_SetStopBits 0x%X\r\n"), pHead));
return(bRet);
}
//
// @doc OEM
// @func ULONG | XRSL_GetRxBufferSize | This function returns
// the size of the hardware buffer passed to the interrupt
// initialize function. It would be used only for devices
// which share a buffer between the MDD/PDD and an ISR.
//
//
// @rdesc This routine always returns 0 for 16550 UARTS.
//
ULONG
XRSL_GetRxBufferSize(
PVOID pHead
)
{
return(0);
}
//
// @doc OEM
// @func PVOID | SC_GetRxStart | This routine returns the start of the hardware
// receive buffer. See XRSL_GetRxBufferSize.
//
// @rdesc The return value is a pointer to the start of the device receive buffer.
//
PVOID
XRSL_GetRxStart(
PVOID pHead // @parm PVOID returned by SC_init.
)
{
return(NULL);
}
//
// @doc OEM
// @func ULONG | XRSL_GetGetInterruptType | This function is called
// by the MDD whenever an interrupt occurs. The return code
// is then checked by the MDD to determine which of the four
// interrupt handling routines are to be called.
//
// @rdesc This routine returns a bitmask indicating which interrupts
// are currently pending.
//
INTERRUPT_TYPE
XRSL_GetInterruptType(
PVOID pHead // Pointer to hardware head
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
INTERRUPT_TYPE interrupts=INTR_NONE;
BOOL bContinue;
DEBUGMSG (0,
(TEXT("+XRSL_GetInterruptType 0x%X\r\n"), pHead));
do {
bContinue = FALSE;
if (pHWHead->bSuspendResume) {
pHWHead->bSuspendResume = FALSE;
pHWHead->EventCallback( pHWHead->pMddHead, EV_POWER );
}
if (pHWHead->pIsrInfoVirt!=NULL) {
if ( pHWHead->pReceiveBuffer && GetRcvDataSize(pHWHead->pReceiveBuffer)>0) {
pHWHead->IIR=pHWHead->pReceiveBuffer->bBuffer[pHWHead->pReceiveBuffer->dwFIFO_Out].bIntFlag;
}
else
pHWHead->IIR=SERIAL_IIR_INT_INVALID;
}
else
try {
pHWHead->IIR = INB(pHWHead, pIIR_FCR);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
pHWHead->IIR = SERIAL_IIR_INT_INVALID; // simulate no interrupt
}
DEBUGMSG (ZONE_THREAD,
(TEXT("+XRSL_GetInterruptType IIR=%x\r\n"),pHWHead->IIR ));
if ( pHWHead->IIR & SERIAL_IIR_INT_INVALID ) {
// No interrupts pending, vector is useless
interrupts = INTR_NONE;
} else {
// The interrupt value is valid
switch ( pHWHead->IIR & SERIAL_IIR_INT_MASK ) {
case SERIAL_IIR_RLS:
if (pHWHead->pIsrInfoVirt) {
pHWHead->LSR=pHWHead->pReceiveBuffer->bBuffer[pHWHead->pReceiveBuffer->dwFIFO_Out].bIntData;
pHWHead->pReceiveBuffer->dwFIFO_Out=IncRcvIndex(pHWHead->pReceiveBuffer,pHWHead->pReceiveBuffer->dwFIFO_Out);
ProcessLSR (pHWHead);
bContinue=TRUE;
}
else
interrupts |= INTR_LINE;
break;
case SERIAL_IIR_CTI:
case SERIAL_IIR_CTI_2:
case SERIAL_IIR_RDA:
interrupts = INTR_RX;
break;
case SERIAL_IIR_THRE :
interrupts = INTR_TX;
if (pHWHead->pIsrInfoVirt) {
pHWHead->pReceiveBuffer->dwFIFO_Out=IncRcvIndex(pHWHead->pReceiveBuffer,pHWHead->pReceiveBuffer->dwFIFO_Out);
}
break;
case SERIAL_IIR_MS :
if (pHWHead->pIsrInfoVirt) {
pHWHead->MSR=pHWHead->pReceiveBuffer->bBuffer[pHWHead->pReceiveBuffer->dwFIFO_Out].bIntData;
pHWHead->pReceiveBuffer->dwFIFO_Out=IncRcvIndex(pHWHead->pReceiveBuffer,pHWHead->pReceiveBuffer->dwFIFO_Out);
ProcessMSR (pHWHead);
bContinue=TRUE;
}
else
interrupts = INTR_MODEM;
break;
default:
if (pHWHead->pIsrInfoVirt) {
pHWHead->pReceiveBuffer->dwFIFO_Out=IncRcvIndex(pHWHead->pReceiveBuffer,pHWHead->pReceiveBuffer->dwFIFO_Out);
}
interrupts = INTR_NONE;
break;
}
}
if (pHWHead->pIsrInfoVirt) {
if (pHWHead->pReceiveBuffer && GetRcvDataSize(pHWHead->pReceiveBuffer)>0) { //Data available.
interrupts |= INTR_RX;
};
}
if (pHWHead->AddTXIntr) {
interrupts |= INTR_TX;
pHWHead->AddTXIntr = FALSE;
}
}while (bContinue && interrupts == INTR_NONE);
DEBUGMSG (ZONE_THREAD,
(TEXT("-XRSL_GetInterruptType 0x%X, 0x%X\r\n"),
pHead, interrupts));
return(interrupts);
}
// @doc OEM
// @func ULONG | XRSL_RxIntr | This routine gets several characters from the hardware
// receive buffer and puts them in a buffer provided via the second argument.
// It returns the number of bytes lost to overrun.
//
// @rdesc The return value indicates the number of overruns detected.
// The actual number of dropped characters may be higher.
//
ULONG
XRSL_RxIntr(
PVOID pHead, // @parm Pointer to hardware head
PUCHAR pRxBuffer, // @parm Pointer to receive buffer
ULONG *pBufflen // @parm In = max bytes to read, out = bytes read
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
ULONG RetVal = 0;
ULONG TargetRoom = *pBufflen;
BOOL fRXFlag = FALSE;
BOOL fReplaceparityErrors = FALSE;
BOOL fNull;
UCHAR cEvtChar, cRXChar;
ULONG *pRxBuf;
*pBufflen = 0;
pRxBuf = (ULONG*)pRxBuffer;
// LAM - I have local copies of some DCB elements since I don't
// want to keep dereferencing inside my read loop and there are too
// many of them to trust the compiler.
cEvtChar = pHWHead->dcb.EvtChar;
fNull = pHWHead->dcb.fNull;
if ( pHWHead->dcb.fErrorChar && pHWHead->dcb.fParity )
fReplaceparityErrors = TRUE;
try {
while ( TargetRoom ) {
// See if there is another byte to be read
if (pHWHead->pIsrInfoVirt && pHWHead->pReceiveBuffer) { // Soft FIFO
if (GetRcvDataSize(pHWHead->pReceiveBuffer)>0 ) {
UCHAR uIntFlag = pHWHead->pReceiveBuffer->bBuffer[pHWHead->pReceiveBuffer->dwFIFO_Out].bIntFlag & SERIAL_IIR_INT_MASK;
if ( uIntFlag==SERIAL_IIR_CTI || uIntFlag==SERIAL_IIR_CTI_2 || uIntFlag==SERIAL_IIR_RDA ) {
cRXChar = pHWHead->pReceiveBuffer->bBuffer[pHWHead->pReceiveBuffer->dwFIFO_Out].bIntData;
pHWHead->pReceiveBuffer->dwFIFO_Out=IncRcvIndex(pHWHead->pReceiveBuffer,pHWHead->pReceiveBuffer->dwFIFO_Out);
}
else
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -