📄 pl010ser.c
字号:
// OK, now lets actually transmit some data.
DEBUGMSG (ZONE_WRITE, (TEXT("SL_TxIntrEx wait for CritSec %x.\r\n"),
&(pSer16550->TransmitCritSec)));
EnterCriticalSection(&(pSer16550->TransmitCritSec));
DEBUGMSG (ZONE_WRITE, (TEXT("SL_TxIntrEx got CritSec %x.\r\n"),
&(pSer16550->TransmitCritSec)));
EnterCriticalSection(&(pSer16550->RegCritSec));
try
{
if ((INB(pSerAMBA, pUART_FR) & AMBA_UARTFR_TXFE))
{
if (INB(pSerAMBA, pUART_LCR_H) & AMBA_UARTLCR_H_FEN)
byteCount = SERIAL_FIFO_DEPTH;
else
byteCount = 1;
DEBUGMSG (ZONE_WRITE | ZONE_THREAD,
(TEXT("SL_TxIntrEx - Write max of %d bytes\r\n"),
byteCount));
for ( *pBufflen=0; NumberOfBytes && byteCount; NumberOfBytes--, byteCount-- ) {
DEBUGLED( ZONE_WRITE, (1, 0x10200000 | *pTxBuffer) );
OUTB(pSerAMBA, pUART_DR, *pTxBuffer);
++pTxBuffer;
(*pBufflen)++;
}
}
// Enable xmit intr. We need to do this no matter what,
// since the MDD relies on one final interrupt before
// returning to the application.
DEBUGMSG (ZONE_WRITE, (TEXT("SL_TxIntrEx: Enable INTR_TX.\r\n")));
ucCR = CR_NORMAL_INTS | AMBA_UARTCR_TIE;
if(((PSER_INFO)pHead)->fIRMode)
{
ucCR |= CR_SIREN;
}
OUTB(pSerAMBA, pUART_CR, ucCR );
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Hmm, not sure what would cause this. Lets just tell
// the MDD to go away until we get another TX
// interrupt.
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
LeaveCriticalSection(&(pSer16550->TransmitCritSec));
DEBUGMSG (ZONE_WRITE, (TEXT("SL_TxIntrEx released CritSec %x.\r\n"),
&(pSer16550->TransmitCritSec)));
DEBUGMSG (ZONE_WRITE, (TEXT("-SL_TxIntrEx - sent %d.\r\n"),
*pBufflen));
return;
}
//
// @doc OEM
// @func ULONG | SL_LineIntr | This routine is called from the MDD
// whenever INTR_LINE is returned by SL_GetInterruptType.
//
// @rdesc None
//
VOID
SL_LineIntr(
PVOID pHead // Hardware Head
)
{
DEBUGMSG (0,
(TEXT("+SL_LineIntr 0x%X\r\n"), pHead));
ReadRSR((PSER_INFO)pHead);
DEBUGMSG (0,
(TEXT("-SL_LineIntr 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func ULONG | SL_OtherIntr | This routine is called from the MDD
// whenever INTR_MODEM is returned by SL_GetInterruptType.
//
// @rdesc None
//
VOID
SL_OtherIntr(
PVOID pHead // Hardware Head
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
UCHAR ucCR;
DEBUGMSG (0,
(TEXT("+SL_OtherIntr 0x%X\r\n"), pHead));
ReadFR( (PSER_INFO)pHead );
EnterCriticalSection(&(pSer16550->RegCritSec));
try
{
// Clear modem status interrupt.
//
OUTB(pSerAMBA, pUART_ICR, 1);
// If we are currently flowed off via CTS or DSR, then
// we better signal the TX thread when one of them changes
// so that TX can resume sending.
if (pSer16550->DSRFlowOff && (INB(pSerAMBA, pUART_FR) & AMBA_UARTFR_DSR))
{
DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
(TEXT("PutBytes, flowed on via DSR\n") ) );
pSer16550->DSRFlowOff = FALSE;
// DSR is set, so go ahead and resume sending
ucCR = CR_NORMAL_INTS | AMBA_UARTCR_TIE;
if(((PSER_INFO)pHead)->fIRMode)
{
ucCR |= CR_SIREN;
}
OUTB(pSerAMBA, pUART_CR, ucCR ); // Enable xmit intr.
// Then simulate a TX intr to get things moving
pSer16550->AddTXIntr = TRUE;
}
if ( pSer16550->CTSFlowOff && (INB(pSerAMBA, pUART_FR) & AMBA_UARTFR_CTS))
{
DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
(TEXT("PutBytes, flowed on via CTS\n") ) );
pSer16550->CTSFlowOff = FALSE;
// CTS is set, so go ahead and resume sending
ucCR = CR_NORMAL_INTS | AMBA_UARTCR_TIE;
if(((PSER_INFO)pHead)->fIRMode)
{
ucCR |= CR_SIREN;
}
OUTB(pSerAMBA, pUART_CR, ucCR ); // Enable xmit intr.
// Then simulate a TX intr to get things moving
pSer16550->AddTXIntr = TRUE;
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (0,
(TEXT("-SL_OtherIntr 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func ULONG | SL_OtherIntr | This routine is called from the MDD
// whenever INTR_MODEM is returned by SL_GetInterruptType.
//
// @rdesc None
//
VOID
SL_ModemIntr(
PVOID pHead // Hardware Head
)
{
SL_OtherIntr(pHead);
}
//
// @doc OEM
// @func ULONG | SL_GetStatus | This structure is called by the MDD
// to retrieve the contents of a COMSTAT structure.
//
// @rdesc The return is a ULONG, representing success (0) or failure (-1).
//
ULONG
SL_GetStatus(
PVOID pHead, // @parm PVOID returned by HWInit.
LPCOMSTAT lpStat // Pointer to LPCOMMSTAT to hold status.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
ULONG RetVal = pSer16550->CommErrors;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SL_GetStatus 0x%X\r\n"), pHead));
pSer16550->CommErrors = 0; // Clear old errors each time
if ( lpStat )
{
try
{
if (pSer16550->CTSFlowOff)
pSer16550->Status.fCtsHold = 1;
else
pSer16550->Status.fCtsHold = 0;
if (pSer16550->DSRFlowOff)
pSer16550->Status.fDsrHold = 1;
else
pSer16550->Status.fDsrHold = 0;
// NOTE - I think what they really want to know here is
// the amount of data in the MDD buffer, not the amount
// in the UART itself. Just set to 0 for now since the
// MDD doesn't take care of this.
pSer16550->Status.cbInQue = 0;
pSer16550->Status.cbOutQue = 0;
memcpy(lpStat, &(pSer16550->Status), sizeof(COMSTAT));
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
RetVal = (ULONG)-1;
}
} else
RetVal = (ULONG)-1;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SL_GetStatus 0x%X\r\n"), pHead));
return(RetVal);
}
//
// @doc OEM
// @func ULONG | SL_Reset | Perform any operations associated
// with a device reset
//
// @rdesc None.
//
VOID
SL_Reset(
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_Reset 0x%X\r\n"), pHead));
memset(&pSer16550->Status, 0, sizeof(COMSTAT));
EnterCriticalSection(&(pSer16550->RegCritSec));
try
{
OUTB(pSerAMBA, pUART_CR, CR_NORMAL_INTS);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Do nothing
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SL_Reset 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func VOID | SL_GetModemStatus | Retrieves modem status.
//
// @rdesc None.
//
VOID
SL_GetModemStatus(
PVOID pHead, // @parm PVOID returned by HWInit.
PULONG pModemStatus // @parm PULONG passed in by user.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
UINT8 ubModemStatus = 0;
if (pModemStatus)
*pModemStatus = 0;
else
{
DEBUGMSG (ZONE_ERROR, (TEXT("SL_GetModemStatus - bad parameter.\r\n")));
return;
}
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SL_GetModemStatus 0x%X\r\n"), pHead));
ubModemStatus = INB(pSerAMBA, pUART_FR);
if (ubModemStatus & AMBA_UARTFR_CTS)
*pModemStatus |= MS_CTS_ON;
if (ubModemStatus & AMBA_UARTFR_DSR)
*pModemStatus |= MS_DSR_ON;
if (ubModemStatus & AMBA_UARTFR_DCD)
*pModemStatus |= MS_RLSD_ON;
DEBUGMSG (ZONE_FUNCTION | ZONE_EVENTS,
(TEXT("-SL_GetModemStatus 0x%X (stat x%X) \r\n"), pHead, *pModemStatus));
return;
}
//
// @doc OEM
// @func VOID | SL_PurgeComm | Purge RX and/or TX
//
// @rdesc None.
//
VOID
SL_PurgeComm(
PVOID pHead, // @parm PVOID returned by HWInit.
DWORD fdwAction // @parm Action to take.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SL_PurgeComm 0x%X\r\n"), pHead));
EnterCriticalSection(&(pSer16550->RegCritSec));
try
{
// ?.
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SL_PurgeComm 0x%X\r\n"), pHead));
return;
}
//
// @doc OEM
// @func BOOL | SL_XmitComChar | Transmit a char immediately
//
// @rdesc TRUE if succesful
//
BOOL
SL_XmitComChar(
PVOID pHead, // @parm PVOID returned by HWInit.
UCHAR ComChar // @parm Character to transmit.
)
{
PSER16550_INFO pSer16550 = &(((PSER_INFO)pHead)->ser16550);
PAMBA_UART_INFO pSerAMBA = &(((PSER_INFO)pHead)->serAMBA);
UCHAR ucCR;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SL_XmitComChar 0x%X\r\n"), pHead));
// Get critical section, then transmit when buffer empties
DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar wait for CritSec %x.\r\n"),
&(pSer16550->TransmitCritSec)));
EnterCriticalSection(&(pSer16550->TransmitCritSec));
DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar got CritSec %x.\r\n"),
&(pSer16550->TransmitCritSec)));
try
{
while ( TRUE ) { // We know THR will eventually empty
EnterCriticalSection(&(pSer16550->RegCritSec));
// Write the character if we can (if it's not full)...
//
if (!(INB(pSerAMBA, pUART_FR) & AMBA_UARTFR_TXFF))
{
// FIFO is empty, send this character
OUTB(pSerAMBA, pUART_DR, ComChar);
// Make sure we release the register critical section
LeaveCriticalSection(&(pSer16550->RegCritSec));
DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar wrote x%X\r\n"),
ComChar));
break;
}
// If we couldn't write the data yet, then wait for a
// TXINTR to come in and try it again.
// Enable xmit intr.
ucCR = CR_NORMAL_INTS | AMBA_UARTCR_TIE;
if(((PSER_INFO)pHead)->fIRMode)
{
ucCR |= CR_SIREN;
}
OUTB(pSerAMBA, pUART_CR, ucCR );
LeaveCriticalSection(&(pSer16550->RegCritSec));
// Wait until the txintr has signalled.
DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar WaitIntr x%X\r\n"),
pSer16550->FlushDone));
WaitForSingleObject(pSer16550->FlushDone, (ULONG)1000);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Make sure we release the register critical section
LeaveCriticalSection(&(pSer16550->RegCritSec));
}
LeaveCriticalSection(&(pSer16
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -