📄 pl010ser.c
字号:
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.
//
// We have to VirtualCopy the System Controller registers used for
// DTR and RTS signals.
//
//if (!(pSerAMBA->pSC_BASE = VirtualAlloc(NULL, (4 * sizeof(ULONG)), MEM_RESERVE, PAGE_NOACCESS)))
//{
// DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("!SL_Init2: VirtualAlloc Failed\r\n")));
// DEBUGCHK(FALSE);
// return;
//}
//
//if (!VirtualCopy((LPVOID)pSerAMBA->pSC_BASE, (LPVOID)(VA_SC_BASE), (4 * sizeof(ULONG)), PAGE_READWRITE | PAGE_NOCACHE))
//{
// DEBUGMSG(ZONE_INIT | ZONE_ERROR, (TEXT("!SL_Init2: VirtualCopy Failed (%d)\r\n"), GetLastError()));
// DEBUGCHK(FALSE);
// VirtualFree (pSerAMBA->pSC_BASE, 0, MEM_RELEASE);
// return;
//}
if(((PSER_INFO)pHead)->dwDevIndex ==1)
{
pSerAMBA->pSC_MCR = (volatile PULONG)UART1_MCR;
}
else
{
pSerAMBA->pSC_MCR = 0;
}
// Store info for callback function
pSer16550->EventCallback = EventCallback;
pSer16550->pMddHead = pMddHead;
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 );
// Free System Controller memory handle
//
if (pSerAMBA->pSC_BASE)
VirtualFree (pSerAMBA->pSC_BASE, 0, MEM_RELEASE);
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_ClearDTR, 0x%X\r\n"), pHead));
EnterCriticalSection(&(pSer16550->RegCritSec));
try {
if(((PSER_INFO)pHead)->dwDevIndex == 1)
{
*pSerAMBA->pSC_MCR &= ~MCR_DTR;
}
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_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_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 == 1)
{
*pSerAMBA->pSC_MCR |= MCR_DTR;
}
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_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_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 == 1)
{
*pSerAMBA->pSC_MCR &= ~MCR_RTS;
}
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_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_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 == 1)
{
*pSerAMBA->pSC_MCR |= MCR_RTS;
}
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_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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -