📄 xrser16550.c
字号:
//
// @doc OEM
// @func PVOID | XRSL_Init | Initializes 16550 device head.
//
VOID
XRSL_Init(
PVOID pHead, // @parm points to device head
PUCHAR pRegBase, // Pointer to 16550 register base
UINT8 RegStride, // Stride amongst the 16550 registers
EVENT_FUNC EventCallback, // This callback exists in MDD
PVOID pMddHead, // This is the first parm to callback
PLOOKUP_TBL pBaudTable // BaudRate Table
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_CLOSE,(TEXT("+XRSL_INIT, 0x%X\r\n"), pHWHead));
// Set up pointers to 16550 registers
pHWHead->pData = pRegBase + (RegStride * RECEIVE_BUFFER_REGISTER);
pHWHead->pIER = pRegBase + (RegStride * INTERRUPT_ENABLE_REGISTER);
pHWHead->pIIR_FCR = pRegBase + (RegStride * INTERRUPT_IDENT_REGISTER);
pHWHead->pLCR = pRegBase + (RegStride * LINE_CONTROL_REGISTER);
pHWHead->pMCR = pRegBase + (RegStride * MODEM_CONTROL_REGISTER);
pHWHead->pLSR = pRegBase + (RegStride * LINE_STATUS_REGISTER);
pHWHead->pMSR = pRegBase + (RegStride * MODEM_STATUS_REGISTER);
pHWHead->pScratch = pRegBase + (RegStride * SCRATCH_REGISTER);
// Store info for callback function
pHWHead->EventCallback = EventCallback;
pHWHead->pMddHead = pMddHead;
// Now set up remaining fields
if ( pBaudTable != NULL )
pHWHead->pBaudTable = (LOOKUP_TBL *) pBaudTable;
else
pHWHead->pBaudTable = (LOOKUP_TBL *) &LS_BaudTable;
pHWHead->FlushDone = CreateEvent(0, FALSE, FALSE, NULL);
pHWHead->OpenCount = 0;
// Don't allow any interrupts till PostInit.
OUTB(pHWHead, pIER, (UCHAR)0);
InitializeCriticalSection(&(pHWHead->TransmitCritSec));
InitializeCriticalSection(&(pHWHead->RegCritSec));
pHWHead->PowerDown = FALSE;
pHWHead->bSuspendResume = FALSE;
InstallSoftwareISR(pHWHead,pHWHead->pVirtualStaticAddr,RegStride);
// Clear any interrupts which may be pending. Normally only
// happens if we were warm reset.
ClearPendingInts( pHWHead );
DEBUGMSG (ZONE_CLOSE,(TEXT("-XRSL_INIT, 0x%X\r\n"), pHWHead));
}
//
// @doc OEM
// @func void | XRSL_PostInit | This routine takes care of final initialization.
//
// @rdesc None.
//
BOOL
XRSL_PostInit(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_INIT,(TEXT("+XRSL_PostInit, 0x%X\r\n"), pHWHead));
// Since we are just a library which might get used for
// builtin ports which init at boot, or by PCMCIA ports
// which init at Open, we can't do anything too fancy.
// Lets just make sure we cancel any pending interrupts so
// that if we are being used with an edge triggered PIC, he
// will see an edge after the MDD hooks the interrupt.
ClearPendingInts( pHWHead );
DEBUGMSG (ZONE_INIT,(TEXT("-XRSL_PostInit, 0x%X\r\n"), pHWHead));
return(TRUE);
}
//
// @doc OEM
// @func PVOID | XRSL_Deinit | De-initializes 16550 device head.
//
VOID
XRSL_Deinit(
PVOID pHead // @parm points to device head
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_CLOSE,(TEXT("+XRSL_DEINIT, 0x%X\r\n"), pHWHead));
UninstallSoftwareISR( pHWHead);
DeleteCriticalSection(&(pHWHead->TransmitCritSec));
DeleteCriticalSection(&(pHWHead->RegCritSec));
// Free the flushdone event
if ( pHWHead->FlushDone )
CloseHandle( pHWHead->FlushDone );
DEBUGMSG (ZONE_CLOSE,(TEXT("-XRSL_DEINIT, 0x%X\r\n"), pHWHead));
}
//
// @doc OEM
// @func void | XRSL_ClearDtr | This routine clears DTR.
//
// @rdesc None.
//
VOID
XRSL_ClearDTR(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_ClearDTR, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
unsigned char byte;
byte = INB((PSER16550_INFO)pHead, pMCR);
OUTB((PSER16550_INFO)pHead, pMCR, byte & ~SERIAL_MCR_DTR);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_ClearDTR, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | XRSL_SetDTR | This routine sets DTR.
//
// @rdesc None.
//
VOID
XRSL_SetDTR(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_SetDTR, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
unsigned char byte;
byte = INB((PSER16550_INFO)pHead, pMCR);
OUTB((PSER16550_INFO)pHead, pMCR, byte | SERIAL_MCR_DTR);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_SetDTR, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | XRSL_ClearRTS | This routine clears RTS.
//
// @rdesc None.
//
VOID
XRSL_ClearRTS(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_ClearRTS, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
unsigned char byte;
byte = INB((PSER16550_INFO)pHead, pMCR);
OUTB((PSER16550_INFO)pHead, pMCR, byte & ~SERIAL_MCR_RTS);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_ClearRTS, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | XRSL_SetRTS | This routine sets RTS.
//
// @rdesc None.
//
VOID
XRSL_SetRTS(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_SetRTS, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
unsigned char byte;
byte = INB((PSER16550_INFO)pHead, pMCR);
OUTB((PSER16550_INFO)pHead, pMCR, byte | SERIAL_MCR_RTS);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_SetRTS, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | XRSL_ClearBreak | This routine clears break.
//
// @rdesc None.
//
VOID
XRSL_ClearBreak(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_ClearBreak, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
unsigned char byte;
byte = INB((PSER16550_INFO)pHead, pLCR);
OUTB((PSER16550_INFO)pHead, pLCR, byte & ~SERIAL_LCR_BREAK);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_ClearBreak, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | XRSL_SetBreak | This routine sets break.
//
// @rdesc None.
//
VOID
XRSL_SetBreak(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+XRSL_SetBreak, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
unsigned char byte;
byte = INB((PSER16550_INFO)pHead, pLCR);
OUTB((PSER16550_INFO)pHead, pLCR, byte | SERIAL_LCR_BREAK);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-XRSL_SetBreak, 0x%X\r\n"), pHead));
}
//
// SetBaudRate
//
// Internal function. The only real reason for splitting this out
// is so that we can call it from PowerOn and still allow XRSL_SetBaud
// to do debug messages, acquire critical sections, etc.
//
BOOL
SetBaudRate(
PVOID pHead,
ULONG BaudRate
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
USHORT divisor;
UCHAR lcr;
// **** Warning ***** Make no system calls, called in power context
divisor = DivisorOfRate(pHead, BaudRate);
if ( divisor ) {
InterruptMask(pHWHead->dwSysIntr,TRUE);
lcr = INB(pHWHead, pLCR);
OUTB(pHWHead, pLCR, lcr | SERIAL_LCR_DLAB);
OUTB(pHWHead, pData, divisor & 0xff); //pData is DivLatch Lo
OUTB(pHWHead, pIER, (divisor >> 8) & 0xff); //pIER is DivLatch Hi
OUTB(pHWHead, pLCR, lcr);
InterruptMask(pHWHead->dwSysIntr,FALSE);
return( TRUE );
} else {
return( FALSE );
}
}
//
// @doc OEM
// @func BOOL | XRSL_SetBaudRate |
// This routine sets the baud rate of the device.
//
// @rdesc None.
//
BOOL
XRSL_SetBaudRate(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG BaudRate // @parm ULONG representing decimal baud rate.
)
{
BOOL fRet;
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+XRSL_SetbaudRate 0x%X, x%X\r\n"), pHead, BaudRate));
try {
// Enter critical section before calling function, since
// we can't make sys calls inside SetBaudRate
EnterCriticalSection(&(pHWHead->RegCritSec));
fRet = SetBaudRate(pHead, BaudRate);
LeaveCriticalSection(&(pHWHead->RegCritSec));
}except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
return( FALSE );
}
if ( fRet ) {
pHWHead->dcb.BaudRate = BaudRate;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-XRSL_SetbaudRate 0x%X (%d Baud)\r\n"),
pHead, BaudRate));
return( TRUE );
} else {
DEBUGMSG (ZONE_FUNCTION | ZONE_ERROR,
(TEXT("-XRSL_SetbaudRate - Error setting %d, failing to %d\r\n"),
BaudRate, pHWHead->dcb.BaudRate) );
return( FALSE );
}
}
//
// @doc OEM
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -