📄 ser16552.c
字号:
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
/*
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Abstract:
based serial device.
Functions: UART for serial driver
*/
#include <windows.h>
#include <serhw.h>
#include <serdbg.h>
#include <s2440.h>
#include <ser16550.h>
#include "macros.h"
#include <ser16552.h>
#include "hw16550.h"
#define CHIP_ID_16550 1
#define CHIP_ID_16450 2
#define QYDEBUG 0
#define IER_NORMAL_INTS SERIAL_IER_RDA
volatile IOPreg *v_pIOPRegs1;
PVOID VirtualAllocCopy(unsigned size,char *str,PVOID pVirtualAddress);
#define BAUD_SER_TABLE_SIZE 11
static const PAIRS SER_BaudPairs[BAUD_SER_TABLE_SIZE] = {
{50, 4608},
{1200, 192},
{2400, 96},
{9600, 24},
{14400, 16},
{19200, 12},
{38400, 6},
{57600, 4},
{76800, 3},
{115200, 2},
{230400, 1}
};
const LOOKUP_TBL SER_BaudTable = {BAUD_SER_TABLE_SIZE, (PAIRS *) SER_BaudPairs};
BOOL
SL_SetByteSizeq(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG ByteSize // @parm ULONG ByteSize field from DCB.
);
BOOL
SL_SetStopBitsq(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG StopBits // @parm ULONG StopBits field from DCB.
);
BOOL
SL_SetParityq(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG Parity // @parm ULONG parity field from DCB.
);
__inline
VOID
ReadMSRq(
PSER16550_INFO pHWHead
);
__inline
VOID
ReadLSRq(
// PSER16550_INFO pHWHead
PVOID pHead
);
__inline
VOID
ReadLSRq(
PSER16550_INFO pHWHead
// PVOID pHead
)
{
// PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
ULONG LineEvents = 0;
try {
pHWHead->LSR = INB(pHWHead, pLSR);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
pHWHead->LSR = SERIAL_LSR_THRE;
}
RETAILMSG(QYDEBUG ,(TEXT("SER16550 Register LSR =0x%x\r\n"),pHWHead->LSR));
if ( pHWHead->LSR & (SERIAL_LSR_OE | SERIAL_LSR_PE | SERIAL_LSR_FE)) {//0x02 & 0x04 & 0x08
// 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 ) {
pHWHead->DroppedBytes++;
pHWHead->CommErrors |= CE_OVERRUN;//0x0002
}
if ( pHWHead->LSR & SERIAL_LSR_PE ) {
pHWHead->CommErrors |= CE_RXPARITY;//0x0004
}
if ( pHWHead->LSR & SERIAL_LSR_FE ) {
pHWHead->CommErrors |= CE_FRAME;//0x0008
}
LineEvents |= EV_ERR;//0x0080
}
if ( pHWHead->LSR & SERIAL_LSR_BI )//break interrupt(0x10)
LineEvents |= EV_BREAK;//0x0040
// Let WaitCommEvent know about this error
if ( LineEvents )
pHWHead->EventCallback( pHWHead->pMddHead, LineEvents );
RETAILMSG(QYDEBUG,(TEXT("-ReadLSRq(return LineEvents=%x)\r\n"),LineEvents));
}
__inline
VOID
ReadMSRq(
PSER16550_INFO pHWHead
)
{
ULONG Events = 0;
UCHAR msr;
RETAILMSG(QYDEBUG,(TEXT("+ReadMSRq()\r\n")));
try {
msr = INB(pHWHead, pMSR);
RETAILMSG(QYDEBUG,(TEXT("SER16550 Register MSR=0x%x\r\n"),msr));
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
msr = 0;
}
// Save the MSR value in a shadow
pHWHead->MSR = msr;
// For changes, we use callback to evaluate the event
if (msr & SERIAL_MSR_DCTS)//0x01
Events |= EV_CTS;//0x08
if ( msr & SERIAL_MSR_DDSR )//0x02
Events |= EV_DSR;//0x10
if ( msr & SERIAL_MSR_TERI )//0x04
Events |= EV_RING;//0x100
if ( msr & SERIAL_MSR_DDCD )//0x08
Events |= EV_RLSD;//0x20
if ( Events )
pHWHead->EventCallback( pHWHead->pMddHead, Events );
RETAILMSG(QYDEBUG,(TEXT("EventCallback return Events =0x%x\r\n"),Events));
RETAILMSG(QYDEBUG,(TEXT("-ReadMSRq()\r\n")));
}
VOID
ClearPendingIntsq(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG,(TEXT("+ ClearPendingIntsq() START \r\n")));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
pHWHead->IIR = INB(pHWHead, pIIR_FCR);
while ( !(pHWHead->IIR & 0x01) ) {
RETAILMSG(QYDEBUG, (TEXT("!!IIR %X\r\n"), pHWHead->IIR));
// Reading LSR clears RLS interrupts.
ReadLSRq( pHWHead );
OUTB(pHWHead, pIIR_FCR, pHWHead->FCR | SERIAL_FCR_RCVR_RESET);
// Reading MSR clears Modem Status interrupt
ReadMSRq( pHWHead );
// Simply reading IIR is sufficient to clear THRE
pHWHead->IIR = INB(pHWHead, pIIR_FCR);
RETAILMSG(QYDEBUG, (TEXT("Read IIR = 0X%X\r\n"), pHWHead->IIR));
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
DEBUGMSG (ZONE_ERROR,(TEXT("-SL_PostInit, 0x%X - ERROR\r\n"), pHWHead));
// Just fall through & release CritSec
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
RETAILMSG(QYDEBUG,(TEXT("- ClearPendingIntsq() \r\n")));
}
VOID
DumpSerialRegistersq(
PVOID pHead
)
{
ULONG byte;
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG,(TEXT("+DumpSerialRegistersq\r\n")));
try {
ReadLSRq( 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"));
ReadMSRq( 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.
}
RETAILMSG(QYDEBUG,(TEXT("-DumpSerialRegistersq\r\n")));
}
ULONG
LookUpValueq(
ULONG Key,
PLOOKUP_TBL pTbl,
PULONG pErrorCode
)
{
ULONG index = 0;
*pErrorCode = 0;
RETAILMSG(QYDEBUG,(TEXT("+LookUpValueq()\r\n")));
while ( index < pTbl->Size ) {
if ( Key == pTbl->Table[index].Key ){
RETAILMSG(QYDEBUG,(TEXT("-LookUpValueq(S) return(0x%x)\r\n"),pTbl->Table[index].AssociatedValue));
return(pTbl->Table[index].AssociatedValue);
}
++index;
}
*pErrorCode = (ULONG)-1;
RETAILMSG(QYDEBUG,(TEXT("-LookUpValueq(F)\r\n")));
return(0);
}
//
// Helper function. Pass in a baudrate, and the corresponding divisor
// (from the baudtable) is returned. If no matching baudrate is found
// in baudtable, then return 0.
//
USHORT
DivisorOfRateq(
PVOID pHead, // @parm PVOID returned by HWinit.
ULONG BaudRate // @parm ULONG representing decimal baud rate.
)
{ PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
ULONG errorcode = 0;
USHORT divisor;
divisor = (USHORT)LookUpValueq(BaudRate,
((PSER16550_INFO) pHead)->pBaudTable, &errorcode);
if ( errorcode )
divisor = 0;
return(divisor);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -