📄 ser16950.c
字号:
(TEXT("+SL_TxIntr 0x%X\r\n"), pHead));
}
//
// @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
)
{
PSER16950_INFO pHWHead = (PSER16950_INFO)pHead;
DEBUGMSG (0,
(TEXT("+SL_LineIntr 0x%X\r\n"), pHead));
ReadLSR( pHWHead );
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
)
{
PSER16950_INFO pHWHead = (PSER16950_INFO)pHead;
DEBUGMSG (0,
(TEXT("+SL_OtherIntr 0x%X\r\n"), pHead));
ReadMSR( pHWHead );
try
{
// If we are currently flowed off by and end of packet wait
// for RI toggle, then we better signal the TX thread when
// one of them changes so that TX can resume sending.
if (pHWHead->MSR & SERIAL_MSR_TERI)
{
pHWHead->RIToggleCount += 1;
if( pHWHead->RINGFlowOff )
{
pHWHead->RINGFlowOff = FALSE;
pHWHead->IER |= SERIAL_IER_THR;// Enable xmit intr.
OUTB(pHWHead, pIER, pHWHead->IER);
// Then simulate a TX intr to get things moving
pHWHead->AddTXIntr = TRUE;
}
}
// 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->MSR & SERIAL_MSR_DSR) )
{
DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
(TEXT("PutBytes, flowed on via DSR\n") ) );
pHWHead->DSRFlowOff = FALSE;
// DSR is set, so go ahead and resume sending
pHWHead->IER |= SERIAL_IER_THR;// Enable xmit intr.
OUTB(pHWHead, pIER, pHWHead->IER);
// Then simulate a TX intr to get things moving
pHWHead->AddTXIntr = TRUE;
}
if ( pHWHead->CTSFlowOff && (pHWHead->MSR & SERIAL_MSR_CTS) )
{
DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
(TEXT("PutBytes, flowed on via CTS\n") ) );
pHWHead->CTSFlowOff = FALSE;
// CTS is set, so go ahead and resume sending
pHWHead->IER |= SERIAL_IER_THR;// Enable xmit intr.
OUTB(pHWHead, pIER, pHWHead->IER);
// 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
}
DEBUGMSG (0,
(TEXT("-SL_OtherIntr 0x%X\r\n"), 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.
)
{
PSER16950_INFO pHWHead = (PSER16950_INFO)pHead;
ULONG RetVal = pHWHead->CommErrors;
DEBUGMSG (ZONE_FUNCTION,
(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;
if (pHWHead->RINGFlowOff) // added 2002-04-28 ** cea for Wendy flow control
pHWHead->Status.fRlsdHold = 1;
else
pHWHead->Status.fRlsdHold = 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.
)
{
PSER16950_INFO pHWHead = (PSER16950_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SL_Reset 0x%X\r\n"), pHead));
memset(&pHWHead->Status, 0, sizeof(COMSTAT));
try
{
pHWHead->IER &= ~SERIAL_IER_THR;
OUTB(pHWHead, pIER, pHWHead->IER);// disable xmit intr.
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Do nothing
}
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.
)
{
PSER16950_INFO pHWHead = (PSER16950_INFO)pHead;
UINT8 ubModemStatus;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SL_GetModemStatus 0x%X\r\n"), pHead));
ReadMSR( pHWHead );
ubModemStatus = pHWHead->MSR;
if ( ubModemStatus & SERIAL_MSR_CTS )
*pModemStatus |= MS_CTS_ON;
if ( ubModemStatus & SERIAL_MSR_DSR )
*pModemStatus |= MS_DSR_ON;
if ( ubModemStatus & SERIAL_MSR_RI )
*pModemStatus |= MS_RING_ON;
if ( ubModemStatus & SERIAL_MSR_DCD )
*pModemStatus |= MS_RLSD_ON;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SL_GetModemStatus 0x%X\r\n"), pHead));
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.
)
{
PSER16950_INFO pHWHead = (PSER16950_INFO)pHead;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SL_PurgeComm 0x%X\r\n"), pHead));
try
{
#ifdef TODO
// REVIEW THIS - I don't see how this could have terminated a pending read,
// nor how RX interrupts would ever get turned back on. I suspect that
// RXABORT and TXABORT would both be better implemented in the MDD.
if ( fdwAction & PURGE_RXABORT )
{
pHWHead->IER &= ~SERIAL_IER_RDA;
OUTB(pHWHead, pIER, pHWHead->IER);// disable rx intr.
}
#endif
if ( fdwAction & PURGE_TXCLEAR )
{
// Write the TX reset bit. It is self clearing
OUTB(pHWHead, pIIR_FCR, pHWHead->FCR | SERIAL_FCR_TXMT_RESET);
}
if ( fdwAction & PURGE_RXCLEAR )
{
// Write the RX reset bit. It is self clearing
OUTB(pHWHead, pIIR_FCR, pHWHead->FCR | SERIAL_FCR_RCVR_RESET);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Just exit
}
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.
)
{
PSER16950_INFO pHWHead = (PSER16950_INFO)pHead;
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"),
&(pHWHead->TransmitCritSec)));
EnterCriticalSection(&(pHWHead->TransmitCritSec));
DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar got CritSec %x.\r\n"),
&(pHWHead->TransmitCritSec)));
try
{
while( TRUE ) // We know THR will eventually empty
{
// Write the character if we can
if( ReadLSR( pHWHead ) & SERIAL_LSR_THRE )
{
OUTB(pHWHead, pData, ComChar);
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.
pHWHead->IER |= SERIAL_IER_THR;
OUTB(pHWHead, pIER, pHWHead->IER);
// 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) {
// Just exit
}
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.
)
{
#if 0
// These are useless on PC Cards!
PSER16950_INFO pHWHead = (PSER16950_INFO)pHead;
// Current FCR is already saved in a shadow
// Current IER is not normally shadowed, save it
// pHWHead->IER = INB(pHWHead, pIER);
// Current LCR is not normally shadowed, save it
//pHWHead->LCR = INB(pHWHead, pLCR);
// Current MCR is not normally shadowed, save it
//pHWHead->MCR = INB(pHWHead, pMCR);
// Current Scratch is not normally shadowed, save it
pHWHead->Scratch = INB(pHWHead, pScratch);
#endif
}
//
// @doc OEM
// @func BOOL | SL_PowerOn | Perform poweron sequence.
//
// @rdesc TRUE if succesful
//
VOID
SL_PowerOn(
PVOID pHead // @parm PVOID returned by HWInit.
)
{
}
//
// @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 ULONG
//
ULONG
SL_SetDCB(
PVOID pHead, // @parm PVOID returned by HWInit.
LPDCB lpDCB // @parm Pointer to DCB structure
)
{
return 0;
}
//
// @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
)
{
PSER16950_INFO pHWHead = (PSER16950_INFO)pHead;
ULONG retval = 0;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("+SL_SetCommTimeout 0x%X\r\n"), pHead));
// OK, first check for any changes and act upon them
if( lpCommTimeouts->WriteTotalTimeoutMultiplier !=
pHWHead->CommTimeouts.WriteTotalTimeoutMultiplier )
{
}
// Now that we have done the right thing, store this DCB
pHWHead->CommTimeouts = *lpCommTimeouts;
DEBUGMSG (ZONE_FUNCTION,
(TEXT("-SL_SetCommTimeout 0x%X\r\n"), pHead));
return retval;
}
//
// @doc OEM
// @func BOOL | SL_Ioctl | Device IO control routine.
// @parm DWORD | dwOpenData | value returned from COM_Open call
// @parm DWORD | dwCode | io control code to be performed
// @parm PBYTE | pBufIn | input data to the device
// @parm DWORD | dwLenIn | number of bytes being passed in
// @parm PBYTE | pBufOut | output data from the device
// @parm DWORD | dwLenOut |maximum number of bytes to receive from device
// @parm PDWORD | pdwActualOut | actual number of bytes received from device
//
// @rdesc Returns TRUE for success, FALSE for failure
//
// @remark The MDD will pass any unrecognized IOCTLs through to this function.
//
BOOL
SL_Ioctl(PVOID pHead, DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,
PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
{
BOOL RetVal = TRUE;
DEBUGMSG (ZONE_FUNCTION, (TEXT("+SL_Ioctl 0x%X\r\n"), pHead));
switch (dwCode) {
// Currently, no defined IOCTLs
default:
RetVal = FALSE;
DEBUGMSG (ZONE_FUNCTION, (TEXT(" Unsupported ioctl 0x%X\r\n"), dwCode));
break;
}
DEBUGMSG (ZONE_FUNCTION, (TEXT("-SL_Ioctl 0x%X\r\n"), pHead));
return RetVal;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -