📄 ser16552.c
字号:
// }
}
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.
RETAILMSG(QYDEBUG,(TEXT("SL_TxIntrEx:except.\r\n")));
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
LeaveCriticalSection(&(pHWHead->TransmitCritSec));
DEBUGMSG (ZONE_WRITE, (TEXT("SL_TxIntrEx released CritSec %x.\r\n"),
&(pHWHead->TransmitCritSec)));
DEBUGMSG (ZONE_WRITE, (TEXT("-SL_TxIntrEx - sent %d.\r\n"),
*pBufflen));
return;
}
VOID
SL_LineIntrq(
PVOID pHead // Hardware Head
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG,
(TEXT("+SL_LineIntr 0x%X\r\n"), pHead));
ReadLSRq( pHWHead );
RETAILMSG(QYDEBUG,
(TEXT("-SL_LineIntr 0x%X\r\n"), pHead));
}
ULONG
SL_GetStatusq(
PVOID pHead, // @parm PVOID returned by HWInit.
LPCOMSTAT lpStat // Pointer to LPCOMMSTAT to hold status.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
ULONG RetVal = pHWHead->CommErrors;
RETAILMSG(QYDEBUG,
(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;
RETAILMSG(QYDEBUG,
(TEXT("-SL_GetStatus 0x%X\r\n"), pHead));
return(RetVal);
}
VOID
SL_Resetq(
PVOID pHead // @parm PVOID returned by HWInit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG,
(TEXT("+SL_Reset 0x%X\r\n"), pHead));
memset(&pHWHead->Status, 0, sizeof(COMSTAT));
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
OUTB(pHWHead, pIER, IER_NORMAL_INTS);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Do nothing
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
RETAILMSG(QYDEBUG,
(TEXT("-SL_Reset 0x%X\r\n"), pHead));
}
VOID
SL_PurgeCommq(
PVOID pHead, // @parm PVOID returned by HWInit.
DWORD fdwAction // @parm Action to take.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG,
(TEXT("+SL_PurgeComm 0x%X\r\n"), pHead));
EnterCriticalSection(&(pHWHead->RegCritSec));
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 )
OUTB(pHWHead, pIER, IER_NORMAL_INTS & ~SERIAL_IER_RDA);
#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
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
RETAILMSG(QYDEBUG,(TEXT("LCR :0x%x\r\n"),INB(pHWHead, pLCR)));
RETAILMSG(QYDEBUG,(TEXT("IER :0x%x\r\n"),INB(pHWHead, pIER)));
RETAILMSG(QYDEBUG,(TEXT("IIR_FCR :0x%x\r\n"),INB(pHWHead, pIIR_FCR)));
RETAILMSG(QYDEBUG,(TEXT("MCR :0x%x\r\n"),INB(pHWHead, pMCR)));
RETAILMSG(QYDEBUG,
(TEXT("-SL_PurgeComm 0x%X\r\n"), pHead));
return;
}
BOOL
SL_XmitComCharq(
PVOID pHead, // @parm PVOID returned by HWInit.
UCHAR ComChar // @parm Character to transmit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG,
(TEXT("+SL_XmitComChar 0x%X\r\n"), pHead));
// Get critical section, then transmit when buffer empties
RETAILMSG(QYDEBUG, (TEXT("XmitComChar wait for CritSec %x.\r\n"),
&(pHWHead->TransmitCritSec)));
EnterCriticalSection(&(pHWHead->TransmitCritSec));
RETAILMSG(QYDEBUG, (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
ReadLSRq( pHWHead );
if ( pHWHead->LSR & SERIAL_LSR_THRE ) {
// FIFO is empty, send this character
OUTB(pHWHead, pData, ComChar);
// Make sure we release the register critical section
LeaveCriticalSection(&(pHWHead->RegCritSec));
RETAILMSG(QYDEBUG, (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.
OUTB(pHWHead, pIER, IER_NORMAL_INTS | SERIAL_IER_THR);
LeaveCriticalSection(&(pHWHead->RegCritSec));
// Wait until the txintr has signalled.
RETAILMSG(QYDEBUG, (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));
RETAILMSG(QYDEBUG, (TEXT("XmitComChar released CritSec %x.\r\n"),
&(pHWHead->TransmitCritSec)));
RETAILMSG(QYDEBUG,
(TEXT("-SL_XmitComChar 0x%X\r\n"), pHead));
return(TRUE);
}
VOID
SL_PowerOffq(
PVOID pHead // @parm PVOID returned by HWInit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG,(TEXT("+SL_PowerOffq, 0x%X\r\n"), pHWHead));
// 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);
RETAILMSG(QYDEBUG,(TEXT("-SL_PowerOffq, 0x%X\r\n"), pHWHead));
}
VOID
SL_PowerOnq(
PVOID pHead // @parm PVOID returned by HWInit.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG,(TEXT("+SL_PowerOnq, 0x%X\r\n"), pHWHead));
// Restore any registers that we need
// In power handler context, so don't try to do a critical section
OUTB(pHWHead, pIIR_FCR, pHWHead->FCR);
OUTB(pHWHead, pIER, pHWHead->IER);
OUTB(pHWHead, pLCR, pHWHead->LCR);
OUTB(pHWHead, pMCR, pHWHead->MCR);
OUTB(pHWHead, pScratch, pHWHead->Scratch);
//****
pHWHead->PowerDown = FALSE;
// 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.
SetBaudRateq( pHWHead, pHWHead->dcb.BaudRate );
RETAILMSG(QYDEBUG,(TEXT("-SL_PowerOnq, 0x%X\r\n"), pHWHead));
}
BOOL
SL_SetDCBq(
PVOID pHead, // @parm PVOID returned by HWInit.
LPDCB lpDCB // @parm Pointer to DCB structure
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
BOOL bRet;
RETAILMSG(QYDEBUG,
(TEXT("+SL_SetDCB 0x%X\r\n"), pHead));
bRet = TRUE;
// 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 ) {
bRet = SL_SetBaudRateq( pHWHead, lpDCB->BaudRate );
}
if ( bRet && (lpDCB->ByteSize != pHWHead->dcb.ByteSize )) {
bRet = SL_SetByteSizeq( pHWHead, lpDCB->ByteSize );
}
if ( bRet && (lpDCB->Parity != pHWHead->dcb.Parity )) {
bRet = SL_SetParityq( pHWHead, lpDCB->Parity );
}
if ( bRet && (lpDCB->StopBits != pHWHead->dcb.StopBits )) {
bRet = SL_SetStopBitsq( 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(QYDEBUG,
(TEXT("-SL_SetDCB 0x%X\r\n"), pHead));
return(bRet);
}
ULONG
SL_SetCommTimeoutsq(
PVOID pHead, // @parm PVOID returned by HWInit.
LPCOMMTIMEOUTS lpCommTimeouts // @parm Pointer to CommTimeout structure
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
ULONG retval = 0;
RETAILMSG(QYDEBUG,
(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;
//****
OUTB(pHWHead, pLCR, 0X03);
RETAILMSG(QYDEBUG,
(TEXT("-SL_SetCommTimeout 0x%X\r\n"), pHead));
return(retval);
}
BOOL
SL_Ioctlq(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 + -