📄 ser2440_hw.c
字号:
{
RETAILMSG (1, (TEXT("SL_TxInt : Error : i = %d \r\n"), i));
}
}
++pTxBuffer;
(*pBufflen)++;
}
if (FifoModeReg&0x1) // FIFO Mode enabled.
{
unsigned int cnt = 0;
for ( ;; )
{
unsigned int tmpreg;
tmpreg = INREG(pHWHead, rUFSTAT);
// RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt : Waiting till tx buffer empty : tmpreg = %x \r\n"), tmpreg));
if ( (tmpreg & 0xf0) == 0) break; // waitint to empty the tx buffer empty...
if ( cnt++ > 600000 )
{
RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt : Reset TX FIFO : tmpreg = %x \r\n"), tmpreg));
//SETREG(pHWHead,rUFCON,0x6); // tx, rx fifo reset
SETREG(pHWHead,rUFCON,0x4); // tx, rx fifo reset
break;
}
}
RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt : Exit for loop \r\n")));
}
}
else
{
RETAILMSG (1, (TEXT("SL_TxIntrEx: Not Send - rFifoStat[0x%x] TxFifoCnt[0x%x]\r\n"),
rFifoStat, TxFifoCnt));
}
if (pHWHead->UseIrDA )
{
// IR is half-duplex.
ClearPendingInts( pHWHead );
EnSubINT(pHWHead, pHWHead->bRxINT);
pHWHead->RxDiscard = FALSE;
}
// Enable xmit intr. We need to do this no matter what,
// since the MDD relies on one final interrupt before
// returning to the application.
ClearPendingInts( pHWHead );
EnINT(pHWHead, pHWHead->bINT);
EnSubINT(pHWHead, pHWHead->bTxINT);
pHWHead->fSW_EnTxINT = TRUE; // FALSE;
}
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(&(pHWHead->RegCritSec));
LeaveCriticalSection(&(pHWHead->TransmitCritSec));
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
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("INTR_LINE \r\n")));
ReadLSR( pHWHead );
ClearINTPnd(pHWHead, pHWHead->bINT);
ClearSubINTPnd(pHWHead, pHWHead->bErrINT);
EnINT(pHWHead, pHWHead->bINT);
EnSubINT(pHWHead, pHWHead->bErrINT);
}
//
// @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
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
// S2440 does not have modem interrupt.
RETAILMSG(DEBUGMODE,(TEXT("+SL_OtherIntr \r\n")));
ReadMSR( pHWHead );
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
// 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 ( pHWHead->DSRFlowOff && (pHWHead->vUMSTAT & COM2440_MSR_DSR) ) {
RETAILMSG (DEBUGMODE, (TEXT("**********************PutBytes, flowed on via DSR\n") ) );
pHWHead->DSRFlowOff = FALSE;
// DSR is set, so go ahead and resume sending
EnINT(pHWHead, pHWHead->bINT);
EnSubINT(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
pHWHead->fSW_EnTxINT = TRUE;
// Then simulate a TX intr to get things moving
pHWHead->AddTXIntr = TRUE;
}
if ( pHWHead->CTSFlowOff && (pHWHead->vUMSTAT & COM2440_MSR_CTS) ) {
RETAILMSG(DEBUGMODE, (TEXT("***********************PutBytes, flowed on via CTS\n") ) );
pHWHead->CTSFlowOff = FALSE;
// CTS is set, so go ahead and resume sending
EnINT(pHWHead, pHWHead->bINT);
EnSubINT(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
pHWHead->fSW_EnTxINT = TRUE;
// Then simulate a TX intr to get things moving
pHWHead->AddTXIntr = TRUE;
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
RETAILMSG(DEBUGMODE,(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
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
INTERRUPT_TYPE it = INTR_NONE;
ULONG win32status = 0;
RETAILMSG (DEBUGMODE, (TEXT("SL_ModemIntr - pHWHead->OpenCount %d \r\n"), pHWHead->OpenCount));
if ( !pHWHead->OpenCount ) {
// We want to indicate a cable event.
RETAILMSG (DEBUGMODE, (TEXT("Indicating RS232 Cable Event\r\n")));
if ( IsAPIReady(SH_WMGR) ) {
CeEventHasOccurred (NOTIFICATION_EVENT_RS232_DETECTED,NULL);
}
}
else
{
RETAILMSG(1,(TEXT("+SL_ModemIntr 0x%X\r\n"), pHead));
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.
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
ULONG RetVal = pHWHead->CommErrors;
RETAILMSG(1, (TEXT("+SL_GetStatus 0x%X\r\n"), pHead));
pHWHead->CommErrors = 0; // Clear old errors each time
if ( lpStat ) {
try {
if (pHWHead->CTSFlowOff)
pHWHead->Status.fCtsHold = 1;
else
pHWHead->Status.fCtsHold = 0;
if (pHWHead->DSRFlowOff)
pHWHead->Status.fDsrHold = 1;
else
pHWHead->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.
pHWHead->Status.cbInQue = 0;
pHWHead->Status.cbOutQue = 0;
memcpy(lpStat, &(pHWHead->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.
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("+SL_Reset 0x%X\r\n"), pHead));
memset(&pHWHead->Status, 0, sizeof(COMSTAT));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
DisEnINT(pHWHead, pHWHead->bINT);
DisEnSubINT(pHWHead, pHWHead->bTxINT);
// if ( GetSubINTStatus(pHWHead) )
pHWHead->fSW_EnTxINT = FALSE;
pHWHead->RxDiscard = FALSE;
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Do nothing
}
LeaveCriticalSection(&(pHWHead->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.
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
UINT8 ubModemStatus;
RETAILMSG(DEBUGMODE, (TEXT("SL_GetModemStatus:\r\n")));
ReadMSR( pHWHead );
ubModemStatus = (unsigned char)pHWHead->vUMSTAT;
RETAILMSG(DEBUGMODE, (TEXT("SL_GetModemStatus: ubModemStatus = 0x%x\r\n"), ubModemStatus));
if ( ubModemStatus & COM2440_MSR_CTS )
*pModemStatus |= MS_CTS_ON;
if ( ubModemStatus & COM2440_MSR_DSR ) {
*pModemStatus |= MS_DSR_ON;
*pModemStatus |= MS_RLSD_ON;
}
RETAILMSG(DEBUGMODE,(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.
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
RETAILMSG(DEBUGMODE,(TEXT("+SL_PurgeComm 0x%X\r\n"), fdwAction));
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.
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
ULONG rFifoStat, TxFifoCnt;
RETAILMSG (DEBUGMODE,(TEXT("+SL_XmitComChar 0x%X\r\n"), pHead));
// Get critical section, then transmit when buffer empties
RETAILMSG(DEBUGMODE, (TEXT("XmitComChar wait for CritSec %x.\r\n"),&(pHWHead->TransmitCritSec)));
EnterCriticalSection(&(pHWHead->TransmitCritSec));
RETAILMSG(DEBUGMODE, (TEXT("XmitComChar got CritSec %x.\r\n"),&(pHWHead->TransmitCritSec)));
try {
while ( TRUE ) { // We know THR will eventually empty
EnterCriticalSection(&(pHWHead->RegCritSec));
// Write the character if we can
rFifoStat = INREG(pHWHead,rUFSTAT);
TxFifoCnt = (rFifoStat & SER2440_FIFOCNT_MASK_TX) >> 4;
if (!(rFifoStat & SER2440_FIFOFULL_TX) && (TxFifoCnt < (SER2440_FIFO_DEPTH_TX-1))) {
// FIFO is empty, send this character
//OUTB(pHWHead, pData, ComChar);
OUTREG(pHWHead,rUTXH,ComChar);
// Make sure we release the register critical section
LeaveCriticalSection(&(pHWHead->RegCritSec));
RETAILMSG(DEBUGMODE, (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.
EnINT(pHWHead, pHWHead->bINT);
EnSubINT(pHWHead, pHWHead->bTxINT | pHWHead->bRxINT | pHWHead->bErrINT);
pHWHead->fSW_EnTxINT = TRUE;
LeaveCriticalSection(&(pHWHead->RegCritSec));
// Wait until the txintr has signalled.
DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar WaitIntr x%X\r\n"),
pHWHead->FlushDone));
WaitForSingleObject(pHWHead->FlushDone, (ULONG)1000);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Make sure we release the register critical section
LeaveCriticalSection(&(pHWHead->RegCritSec));
}
LeaveCriticalSection(&(pHWHead->TransmitCritSec));
DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar released CritSec %x.\r\n"),
&(pHWHead->TransmitCritSec)));
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SL_XmitComChar 0x%X\r\n"), pHead));
return(TRUE);
}
//
// @doc OEM
// @func BOOL | SL_PowerOff | Perform powerdown sequence.
//
// @rdesc TRUE if succesful
//
VOID
SL_PowerOff(
PVOID pHead // @parm PVOID returned by HWInit.
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
RETAILMSG(DEBUGMODE, (TEXT("SL_PowerOff \r\n")));
pHWHead->sULCON = INREG(pHWHead, rULCON);
pHWHead->sUCON = INREG(pHWHead, rUCON);
pHWHead->sUMCON = INREG(pHWHead, rUMCON);
pHWHead->sUFCON = INREG(pHWHead, rUFCON);
pHWHead->sINTstat = (*(pHWHead->UART_INTSUBMASK) & (pHWHead->bTxINT | pHWHead->bRxINT));
}
//
// @doc OEM
// @func BOOL | SL_PowerOn | Perform poweron sequence.
//
// @rdesc TRUE if succesful
//
VOID
SL_PowerOn(
PVOID pHead // @parm PVOID returned by HWInit.
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
// Restore any registers that we need
RETAILMSG(DEBUGMODE, (TEXT("SL_PowerOn \r\n")));
// In power handler context, so don't try to do a critical section
OUTREG(pHWHead, rULCON, pHWHead->sULCON);
OUTREG(pHWHead, rUCON, pHWHead->sUCON);
OUTREG(pHWHead, rUMCON, pHWHead->sUMCON);
OUTREG(pHWHead, rUFCON, pHWHead->sUFCON);
if((pHWHead->sINTstat) & (pHWHead->bTxINT)) {
EnINT(pHWHead, pHWHead->bINT);
EnSubINT(pHWHead, pHWHead->bTxINT);
pHWHead->fSW_EnTxINT = TRUE;
pHWHead->RxDiscard = FALSE;
}
if((pHWHead->sINTstat) & (pHWHead->bRxINT))
{
EnINT(pHWHead, pHWHead->bINT);
EnSubINT(pHWHead, pHWHead->bRxINT);
}
// And we didn't save the Divisor Reg, so set baud rate
// But d
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -