pl010ser.c
来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 2,020 行 · 第 1/5 页
C
2,020 行
// ahead and clear out interrupts one last time. In 4.0, we can
// kill the old serial MDD and assume that everyone uses the new
// MDD and calls post init.
SL_PostInit(pHead);
ReadFR((PSER_INFO)pHead);
ReadRSR((PSER_INFO)pHead);
// Enable ints and UART.
pSerAMBA->CR = (CR_NORMAL_INTS | AMBA_UARTCR_TIE);
OUTB(pSerAMBA, pUART_CR, pSerAMBA->CR);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just get out of here.
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (ZONE_OPEN,
(TEXT("-SL_Open 0x%Xr\n"), pHead));
}
//
// @doc OEM
// @func PVOID | SL_Close | Does nothing except keep track of the
// open count so that other routines know what to do.
//
VOID
SL_Close(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_CLOSE,
(TEXT("+SL_Close 0x%X\r\n"), pHead));
if ( pSer16550->OpenCount )
pSer16550->OpenCount--;
EnterCriticalSection(&(pSer16550->RegCritSec));
try {
// Disable all interrupts and clear MCR.
OUTB(pSerAMBA, pUART_CR, (UCHAR)0);
// Clear modem control state.
//
SL_ClearDTR(pHead);
SL_ClearRTS(pHead);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just get out of here.
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (ZONE_CLOSE,
(TEXT("-SL_Close 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func PVOID | SL_Init | Initializes 16550 device head.
//
VOID
SL_Init2(
PVOID pHead, // @parm points to device head
PUCHAR pRegBase, // Pointer to 16550 register base
EVENT_FUNC EventCallback, // This callback exists in MDD
PVOID pMddHead, // This is the first parm to callback
PLOOKUP_TBL pBaudTable // BaudRate Table
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_CLOSE,(TEXT("+SL_INIT, 0x%X\r\n"), pHead));
// Set up pointers to UART registers
pSerAMBA->pUART_DR = pRegBase + AMBA_UARTDR;
pSerAMBA->pUART_RSR = pRegBase + AMBA_UARTRSR;
pSerAMBA->pUART_ECR = pRegBase + AMBA_UARTECR;
pSerAMBA->pUART_LCR_H = pRegBase + AMBA_UARTLCR_H;
pSerAMBA->pUART_LCR_M = pRegBase + AMBA_UARTLCR_M;
pSerAMBA->pUART_LCR_L = pRegBase + AMBA_UARTLCR_L;
pSerAMBA->pUART_CR = pRegBase + AMBA_UARTCR;
pSerAMBA->pUART_FR = pRegBase + AMBA_UARTFR;
pSerAMBA->pUART_IIR = pRegBase + AMBA_UARTIIR;
pSerAMBA->pUART_ICR = pRegBase + AMBA_UARTICR;
pSerAMBA->pUART_ILPR = pRegBase + AMBA_UARTILPR;
// Special registers: the AMBA UART doesn't implement DTR and RTS. Instead,
// these signals are implemented with general-purpose IO lines.
//
pSerAMBA->pSC_CTRLS = (PUCHAR)(VA_SC_BASE + INTEGRATOR_SC_CTRLS_OFFSET);
pSerAMBA->pSC_CTRLC = (PUCHAR)(VA_SC_BASE + INTEGRATOR_SC_CTRLC_OFFSET);
// Store info for callback function
pSer16550->EventCallback = EventCallback;
pSer16550->pMddHead = pMddHead;
// Now set up remaining fields
if ( pBaudTable != NULL )
pSer16550->pBaudTable = (LOOKUP_TBL *) pBaudTable;
else
pSer16550->pBaudTable = (LOOKUP_TBL *) &LS_BaudTable;
pSer16550->FlushDone = CreateEvent(0, FALSE, FALSE, NULL);
pSer16550->OpenCount = 0;
// Don't allow any interrupts till PostInit.
OUTB(pSerAMBA, pUART_CR, (UCHAR)0);
InitializeCriticalSection(&(pSer16550->TransmitCritSec));
InitializeCriticalSection(&(pSer16550->RegCritSec));
// Clear any interrupts which may be pending. Normally only
// happens if we were warm reset.
ClearPendingInts( pHead );
DEBUGMSG (ZONE_CLOSE,(TEXT("-SL_INIT, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func void | SL_PostInit | This routine takes care of final initialization.
//
// @rdesc None.
//
BOOL
SL_PostInit(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_INIT,(TEXT("+SL_PostInit, 0x%X\r\n"), pHead));
// 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( pHead );
DEBUGMSG (ZONE_INIT,(TEXT("-SL_PostInit, 0x%X\r\n"), pHead));
return(TRUE);
}
//
// @doc OEM
// @func PVOID | SL_Deinit | De-initializes 16550 device head.
//
VOID
SL_Deinit(
PVOID pHead // @parm points to device head
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_CLOSE,(TEXT("+SL_DEINIT, 0x%X\r\n"), pHead));
DeleteCriticalSection(&(pSer16550->TransmitCritSec));
DeleteCriticalSection(&(pSer16550->RegCritSec));
// Free the flushdone event
if ( pSer16550->FlushDone )
CloseHandle( pSer16550->FlushDone );
DEBUGMSG (ZONE_CLOSE,(TEXT("-SL_DEINIT, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func void | SL_ClearDtr | This routine clears DTR.
//
// @rdesc None.
//
VOID
SL_ClearDTR(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_FUNCTION, (TEXT("+SL_SetDTR, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pSer16550->RegCritSec));
try {
// Depending on which port we're talking to, assert the DTR signal.
//
if (((PSER_INFO)pHead)->dwDevIndex == 0)
OUTB(pSerAMBA, pSC_CTRLS, INTEGRATOR_SC_CTRL_UDTR0);
else if (((PSER_INFO)pHead)->dwDevIndex == 1)
OUTB(pSerAMBA, pSC_CTRLS, INTEGRATOR_SC_CTRL_UDTR1);
else
{
DEBUGMSG (ZONE_WARN, (TEXT("SL_SetDTR: invalid device index (0x%X)\r\n"), ((PSER_INFO)pHead)->dwDevIndex));
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-SL_SetDTR, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | SL_SetDTR | This routine sets DTR.
//
// @rdesc None.
//
VOID
SL_SetDTR(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_FUNCTION, (TEXT("+SL_ClearDTR, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pSer16550->RegCritSec));
try {
// Depending on which port we're talking to, deassert the DTR signal.
//
if (((PSER_INFO)pHead)->dwDevIndex == 0)
OUTB(pSerAMBA, pSC_CTRLC, INTEGRATOR_SC_CTRL_UDTR0);
else if (((PSER_INFO)pHead)->dwDevIndex == 1)
OUTB(pSerAMBA, pSC_CTRLC, INTEGRATOR_SC_CTRL_UDTR1);
else
{
DEBUGMSG (ZONE_WARN, (TEXT("SL_ClearDTR: invalid device index (0x%X)\r\n"), ((PSER_INFO)pHead)->dwDevIndex));
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-SL_ClearDTR, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | SL_ClearRTS | This routine clears RTS.
//
// @rdesc None.
//
VOID
SL_ClearRTS(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_FUNCTION, (TEXT("+SL_SetRTS, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pSer16550->RegCritSec));
try {
// Depending on which port we're talking to, assert the DTR signal.
//
if (((PSER_INFO)pHead)->dwDevIndex == 0)
OUTB(pSerAMBA, pSC_CTRLS, INTEGRATOR_SC_CTRL_URTS0);
else if (((PSER_INFO)pHead)->dwDevIndex == 1)
OUTB(pSerAMBA, pSC_CTRLS, INTEGRATOR_SC_CTRL_URTS1);
else
{
DEBUGMSG (ZONE_WARN, (TEXT("SL_SetRTS: invalid device index (0x%X)\r\n"), ((PSER_INFO)pHead)->dwDevIndex));
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-SL_SetRTS, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | SL_SetRTS | This routine sets RTS.
//
// @rdesc None.
//
VOID
SL_SetRTS(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_FUNCTION, (TEXT("+SL_ClearRTS, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pSer16550->RegCritSec));
try {
// Depending on which port we're talking to, deassert the RTS signal.
//
if (((PSER_INFO)pHead)->dwDevIndex == 0)
OUTB(pSerAMBA, pSC_CTRLC, INTEGRATOR_SC_CTRL_URTS0);
else if (((PSER_INFO)pHead)->dwDevIndex == 1)
OUTB(pSerAMBA, pSC_CTRLC, INTEGRATOR_SC_CTRL_URTS1);
else
{
DEBUGMSG (ZONE_WARN, (TEXT("SL_ClearRTS: invalid device index (0x%X)\r\n"), ((PSER_INFO)pHead)->dwDevIndex));
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-SL_ClearRTS, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | SL_ClearBreak | This routine clears break.
//
// @rdesc None.
//
VOID
SL_ClearBreak(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_FUNCTION, (TEXT("+SL_ClearBreak, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pSer16550->RegCritSec));
try {
unsigned char byte;
byte = INB(pSerAMBA, pUART_LCR_H);
OUTB(pSerAMBA, pUART_LCR_H, byte & ~AMBA_UARTLCR_H_BRK);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-SL_ClearBreak, 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | SL_SetBreak | This routine sets break.
//
// @rdesc None.
//
VOID
SL_SetBreak(
PVOID pHead // @parm PVOID returned by HWinit.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_FUNCTION, (TEXT("+SL_SetBreak, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pSer16550->RegCritSec));
try {
unsigned char byte;
byte = INB(pSerAMBA, pUART_LCR_H);
OUTB(pSerAMBA, pUART_LCR_H, byte | AMBA_UARTLCR_H_BRK);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (ZONE_FUNCTION, (TEXT("-SL_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 SL_SetBaud
// to do debug messages, acquire critical sections, etc.
//
BOOL
SetBaudRate(
PVOID pHead,
ULONG BaudRate
)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?