?? ser2440_hw.c
字號(hào):
// 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 (1, (TEXT("SL_ModemIntr - pHWHead->OpenCount %d \r\n"), pHWHead->OpenCount));
if ( !pHWHead->OpenCount )
{
// We want to indicate a cable event.
RETAILMSG(1, (TEXT("!pHWHead->OpenCount : 0x%X\r\n"), pHWHead->OpenCount));
if ( IsAPIReady(SH_WMGR))
{
RETAILMSG(1, (TEXT("IsAPIReady(SH_WMGR) == true\r\n")));
CeEventHasOccurred (NOTIFICATION_EVENT_RS232_DETECTED,NULL);
RETAILMSG(1, (TEXT("Indicating RS232 Cable Event\r\n")));
RETAILMSG(1, (TEXT("Event occurred : NOTIFICATION_EVENT_RS232_DETECTED\r\n")));
}
}
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|USERDBG,
(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) >> 8;
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(0, (TEXT("SL_PowerOff \r\n")));
if ( !pHWHead->UseIrDA )
{
// DeAssert DTR
*(pHWHead->rDTRport) |= (1<<(pHWHead->DtrPortNum));
// DeAssert RTS
#if USE_AFC
*(pHWHead->rRTSport) |= (1<<(pHWHead->RtsPortNum));
#else
CLEARREG(pHWHead, rUMCON, SER2440_RTS);
#endif
}
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")));
if ( !pHWHead->UseIrDA )
{
// Assert DTR
*(pHWHead->rDTRport) &= ~(1<<(pHWHead->DtrPortNum));
// Assert RTS
#if USE_AFC
*(pHWHead->rRTSport) &= ~(1<<(pHWHead->RtsPortNum));
#else
SETREG(pHWHead, rUMCON, SER2440_RTS);
#endif
}
// 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 don't call SL_SetBaud, since it does DebugMsg.
// Call our internal function instead. Can't acquire
// the RegCritSec, but shouldn't really need to since
// we are in power context.
SetBaudRate( pHWHead, pHWHead->dcb.BaudRate );
return;
pHWHead->EventCallback( pHWHead->pMddHead, EV_POWER );
}
//
// @doc OEM
// @func BOOL | SL_SetDCB | Sets new values for DCB. This
// routine gets a DCB from the MDD. It must then compare
// this to the current DCB, and if any fields have changed take
// appropriate action.
//
// @rdesc BOOL
//
BOOL
SL_SetDCB(
PVOID pHead, // @parm PVOID returned by HWInit.
LPDCB lpDCB // @parm Pointer to DCB structure
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
BOOL bRet;
bRet = TRUE;
RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : BaudRate is %d\r\n"), lpDCB->BaudRate));
RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set ByteSize is %d\r\n"), lpDCB->ByteSize));
RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set Parity is %d\r\n"), lpDCB->Parity));
RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set StopBits is %d\r\n"), lpDCB->StopBits));
// If the device is open, scan for changes and do whatever
// is needed for the changed fields. if the device isn't
// open yet, just save the DCB for later use by the open.
if ( pHWHead->OpenCount )
{
// Note, fparity just says whether we should check
// receive parity. And the 16550 won't let us NOT
// check parity if we generate it. So this field
// has no effect on the hardware.
if ( lpDCB->BaudRate != pHWHead->dcb.BaudRate )
{
RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set BaudRate to %d\r\n"), lpDCB->BaudRate));
bRet = SL_SetBaudRate( pHWHead, lpDCB->BaudRate );
}
if ( bRet && (lpDCB->ByteSize != pHWHead->dcb.ByteSize ))
{
RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set ByteSize to %d\r\n"), lpDCB->ByteSize));
bRet = SL_SetByteSize( pHWHead, lpDCB->ByteSize );
}
if ( bRet && (lpDCB->Parity != pHWHead->dcb.Parity ))
{
RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set Parity to %d\r\n"), lpDCB->Parity));
bRet = SL_SetParity( pHWHead, lpDCB->Parity );
}
if ( bRet && (lpDCB->StopBits != pHWHead->dcb.StopBits ))
{
RETAILMSG(DEBUGMODE,(TEXT("SL_SetDCB : Set StopBits to %d\r\n"), lpDCB->StopBits));
bRet = SL_SetStopBits( pHWHead, lpDCB->StopBits );
}
// Don't worry about fOutxCtsFlow. It is a flag which
// will be examined every time we load the TX buffer.
// No special action required here.
}
if (bRet)
{
// Now that we have done the right thing, store this DCB
pHWHead->dcb = *lpDCB;
}
RETAILMSG(DEBUGMODE,(TEXT("-SL_SetDCB 0x%X\r\n"), pHead));
return(bRet);
}
//
// @doc OEM
// @func BOOL | SL_SetCommTimeouts | Sets new values for the
// CommTimeouts structure. routine gets a DCB from the MDD. It
// must then compare this to the current DCB, and if any fields
// have changed take appropriate action.
//
// @rdesc ULONG
//
ULONG
SL_SetCommTimeouts(
PVOID pHead, // @parm PVOID returned by HWInit.
LPCOMMTIMEOUTS lpCommTimeouts // @parm Pointer to CommTimeout structure
)
{
PS2440_UART_INFO pHWHead = (PS2440_UART_INFO)pHead;
ULONG retval = 0;
RETAILMSG(DEBUGMODE,(TEXT("+SL_SetCommTimeout 0x%X\r\n"), pHead));
// ShowSerialRegisters(pHead);
// OK, first check for any changes and act upon them
if ( lpCommTimeouts->WriteTot
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -