📄 ser16552.c.bak
字号:
RETAILMSG(QYDEBUG,
(TEXT("+SL_GetModemStatus 0x%X\r\n"), pHead));
ReadMSRq( 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 | ZONE_EVENTS,
(TEXT("-SL_GetModemStatus 0x%X (stat x%X) \r\n"), pHead, *pModemStatus));
RETAILMSG(QYDEBUG,(TEXT("SL_GetModemStatusq end\r\n")));
return;
}
VOID
SL_OtherIntrq(
PVOID pHead // Hardware Head
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(QYDEBUG,
(TEXT("+SL_OtherIntr 0x%X\r\n"), pHead));
//RETAILMSG(QYDEBUG,(TEXT("SL_OtherIntrq start\r\n")));
ReadMSRq( 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->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
OUTB(pHWHead, pIER, IER_NORMAL_INTS | SERIAL_IER_THR); // Enable xmit intr.//0x0f
RETAILMSG(QYDEBUG,(TEXT("SER16550 Register IER(0x0f) =0X%x\r\n"),INB(pHWHead,pIER)));
// 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
OUTB(pHWHead, pIER, IER_NORMAL_INTS | SERIAL_IER_THR); // Enable xmit intr.
RETAILMSG(QYDEBUG,(TEXT("SER16550 Register IER(0x0f) =0X%x\r\n"),INB(pHWHead,pIER)));
// 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(QYDEBUG,
(TEXT("-SL_OtherIntr 0x%X\r\n"), pHead));
}
BOOL
SL_SetParityq(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG Parity // @parm ULONG parity field from DCB.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
UINT8 lcr;
BOOL bRet;
RETAILMSG(QYDEBUG,
(TEXT("+SL_SetParity 0x%X, x%X\r\n"), pHead, Parity));
bRet = TRUE;
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
lcr = INB(pHWHead, pLCR);
RETAILMSG(QYDEBUG,(TEXT("SER16550 Register LCR=0x%x\r\n"),lcr));
lcr &= ~SERIAL_PARITY_MASK;
RETAILMSG(QYDEBUG,(TEXT("SERIAL3 PARITY =%d\r\n"),Parity));
switch ( Parity ) {
case ODDPARITY:
lcr |= SERIAL_ODD_PARITY;
break;
case EVENPARITY:
lcr |= SERIAL_EVEN_PARITY;
break;
case MARKPARITY:
lcr |= SERIAL_MARK_PARITY;
break;
case SPACEPARITY:
lcr |= SERIAL_SPACE_PARITY;
break;
case NOPARITY:
lcr |= SERIAL_NONE_PARITY;
break;
default:
bRet = FALSE;
break;
}
if (bRet) {
OUTB(pHWHead, pLCR, lcr);
RETAILMSG(QYDEBUG,(TEXT("SER16550 Register LCR=0x%x\r\n"),INB(pHWHead, pLCR)));
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
bRet = FALSE;
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
RETAILMSG(QYDEBUG,
(TEXT("-SL_SetParity 0x%X\r\n"), pHead));
return(bRet);
}
BOOL
SL_SetStopBitsq(
PVOID pHead, // @parm PVOID returned by HWInit
ULONG StopBits // @parm ULONG StopBits field from DCB.
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
UINT8 lcr;
BOOL bRet;
RETAILMSG(QYDEBUG,
(TEXT("+SL_SetStopBits 0x%X, x%X\r\n"), pHead, StopBits));
bRet = TRUE;
EnterCriticalSection(&(pHWHead->RegCritSec));
lcr = INB(pHWHead, pLCR);
RETAILMSG(QYDEBUG,(TEXT("SERIAL3 Register LCR=0x%x \r\n"),lcr));
lcr &= ~SERIAL_STOP_MASK;
RETAILMSG(QYDEBUG,(TEXT("SERIAL3 STOP BIT =%d\r\n"),StopBits));
try {
// Note that 1.5 stop bits only works if the word size
// is 5 bits. Any other xmit word size will cause the
// 1.5 stop bit setting to generate 2 stop bits.
switch ( StopBits ) {
case ONESTOPBIT :
lcr |= SERIAL_1_STOP ;
break;
case ONE5STOPBITS :
lcr |= SERIAL_1_5_STOP ;
break;
case TWOSTOPBITS :
lcr |= SERIAL_2_STOP ;
break;
default:
bRet = FALSE;
break;
}
if (bRet) {
OUTB(pHWHead, pLCR, lcr);
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
bRet = FALSE;
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
RETAILMSG(QYDEBUG,
(TEXT("-SL_SetStopBits 0x%X\r\n"), pHead));
return(bRet);
}
ULONG
SL_GetRxBufferSizeq(
PVOID pHead
)
{
RETAILMSG(QYDEBUG,(TEXT("SL_GetRufferSizeq() \r\n")));
return(0);
}
PVOID
SL_GetRxStartq(
PVOID pHead // @parm PVOID returned by SC_init.
)
{
RETAILMSG(QYDEBUG,(TEXT("SL_GetRxStartq\r\n")));
return(NULL);
}
INTERRUPT_TYPE
SL_GetInterruptTypeq(
PVOID pHead // Pointer to hardware head
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
INTERRUPT_TYPE interrupts=INTR_NONE;
RETAILMSG(0,
(TEXT("+SL_GetInterruptType 0x%X\r\n"), pHead));
try {
pHWHead->IIR = INB(pHWHead, pIIR_FCR);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
pHWHead->IIR = SERIAL_IIR_INT_INVALID; // simulate no interrupt
}
if ( pHWHead->IIR & SERIAL_IIR_INT_INVALID ) {
// No interrupts pending, vector is useless
interrupts = INTR_NONE;//interrupt ID =0
} else {
// The interrupt value is valid
switch ( pHWHead->IIR & SERIAL_IIR_INT_MASK ) {
case SERIAL_IIR_RLS://Receiver Line Status
interrupts = INTR_LINE;//interrupt ID=1
break;
case SERIAL_IIR_CTI://Receiver Date Time Out
case SERIAL_IIR_CTI_2://(Transmitter Holding Register Empty) &(Receiver Date Time Out)
case SERIAL_IIR_RDA://Receiver Date Ready
interrupts = INTR_RX;//interrupt ID =2
break;
case SERIAL_IIR_THRE ://Transmitter Holding Register Empty
interrupts = INTR_TX;//interrupt ID =4
break;
case SERIAL_IIR_MS ://Modem Status Register
interrupts = INTR_MODEM;//interrupt ID =8
break;
default:
interrupts = INTR_NONE;//interrupt ID =0
break;
}
}
if (pHWHead->AddTXIntr) {
interrupts |= INTR_TX;
pHWHead->AddTXIntr = FALSE;
}
RETAILMSG(0,((TEXT("-SL_GetInterruptTypeq(return(interrupts= 0x%x))\r\n")),interrupts));
return(interrupts);
}
ULONG
SL_RxIntrq(
PVOID pHead, // @parm Pointer to hardware head
PUCHAR pRxBuffer, // @parm Pointer to receive buffer
ULONG *pBufflen // @parm In = max bytes to read, out = bytes read
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
ULONG RetVal = 0;
ULONG TargetRoom = *pBufflen;
BOOL fRXFlag = FALSE;
BOOL fReplaceparityErrors = FALSE;
BOOL fNull;
UCHAR cEvtChar, cRXChar;
RETAILMSG(QYDEBUG, (TEXT("+SL_RxIntrq() %d.\r\n"),
*pBufflen));
*pBufflen = 0;
// LAM - I have local copies of some DCB elements since I don't
// want to keep dereferencing inside my read loop and there are too
// many of them to trust the compiler.
cEvtChar = pHWHead->dcb.EvtChar;
fNull = pHWHead->dcb.fNull;
if ( pHWHead->dcb.fErrorChar && pHWHead->dcb.fParity )
fReplaceparityErrors = TRUE;
try {
// while ( TargetRoom )
//****
while (INB(pHWHead, pIIR_FCR)&0x06)
{
// See if there is another byte to be read
//ReadLSRq( pHWHead );
// pHWHead->LSR = INB(pHWHead, pLSR);
// if ( pHWHead->LSR & SERIAL_LSR_DR ) {//receive data ready (0x01)
// if ( pHWHead->LSR & 0x15 ) {
// Read the byte
cRXChar = INB(pHWHead, pData);
// }else {
// We read all chars, so we're done
// break;
// }
RETAILMSG(0,(TEXT("SERIAL3 Receive Char =%c , 0x%x\r\n"),cRXChar));
// But we may want to discard it
if ( pHWHead->dcb.fDsrSensitivity &&
(! (pHWHead->MSR & SERIAL_MSR_DSR)) ) {
// Do nothing - byte gets discarded
RETAILMSG (QYDEBUG,
(TEXT("Dropping byte because DSR is low\r\n")));
} else if (!cRXChar && fNull) {
// Do nothing - byte gets discarded
RETAILMSG (QYDEBUG,
(TEXT("Dropping NULL byte due to fNull\r\n")));
} else {
// Do character replacement if parity error detected.
if ( fReplaceparityErrors && (pHWHead->LSR & SERIAL_LSR_PE) ) {
cRXChar = pHWHead->dcb.ErrorChar;
} else {
// See if we need to generate an EV_RXFLAG for the received char.
if ( cRXChar == cEvtChar )
fRXFlag = TRUE;
}
// Finally, we can get byte, update status and save.
*pRxBuffer++ = cRXChar;
(*pBufflen)++;
--TargetRoom;
}
}
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// just exit
}
// if we saw one (or more) EVT chars, then generate an event
if ( fRXFlag )
pHWHead->EventCallback( pHWHead->pMddHead, EV_RXFLAG );
if ( pHWHead->DroppedBytes )
DEBUGMSG (ZONE_WARN, (TEXT("Rx drop %d.\r\n"),
pHWHead->DroppedBytes));
RetVal = pHWHead->DroppedBytes;
pHWHead->DroppedBytes = 0;
//****
OUTB(pHWHead, pIER, 0x01);
RETAILMSG(QYDEBUG,(TEXT("-SL_Rxtrq() END\r\n")));
return(RetVal);
}
VOID
SL_TxIntrq(
PVOID pHead // Hardware Head
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
RETAILMSG(0,
(TEXT("+SL_TxIntr 0x%X\r\n"), pHead));
// Disable xmit intr. Most 16550s will keep hammering
// us with xmit interrupts if we don't turn them off
// Whoever gets the FlushDone will then need to turn
// TX Ints back on if needed.
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
OUTB(pHWHead, pIER, IER_NORMAL_INTS);
}
except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
// Do nothing. The worst case is that this was a fluke,
// and a TX Intr will come right back at us and we will
// resume transmission.
}
LeaveCriticalSection(&(pHWHead->RegCritSec));
// Let the putbytes routine know he can continue
PulseEvent(pHWHead->FlushDone);
RETAILMSG(0,
(TEXT("-SL_TxIntr 0x%X\r\n"), pHead));
}
//
// @doc OEM
// @func ULONG | SL_TXIntrEx | This routine is called from the new MDD
// whenever INTR_TX is returned by SL_GetInterruptType
//
// @rdesc None
//
VOID
SL_TxIntrExq(
PVOID pHead, // Hardware Head
PUCHAR pTxBuffer, // @parm Pointer to receive buffer
ULONG *pBufflen // @parm In = max bytes to transmit, out = bytes transmitted
)
{
PSER16550_INFO pHWHead = (PSER16550_INFO)pHead;
ULONG NumberOfBytes = *pBufflen;
DEBUGMSG (ZONE_THREAD, (TEXT("Transmit Event\r\n")));
DEBUGMSG (ZONE_WRITE,
(TEXT("+SL_TxIntrEx 0x%X, Len %d\r\n"), pHead, *pBufflen));
RETAILMSG (QYDEBUG,
(TEXT("+SL_TxIntrEx 0x%X, Len %d\r\n"), pHead, *pBufflen));
// We may be done sending. If so, just disable the TX interrupts
// and return to the MDD.
if( ! *pBufflen ) {
DEBUGMSG (ZONE_WRITE, (TEXT("SL_TxIntrEx: Disable INTR_TX.\r\n")));
RETAILMSG (QYDEBUG, (TEXT("SL_TxIntrEx: Disable INTR_TX.\r\n")));
OUTB(pHWHead, pIER, IER_NORMAL_INTS);
return;
}
*pBufflen = 0; // In case we don't send anything below.
// Disable xmit intr. Most 16550s will keep hammering
// us with xmit interrupts if we don't turn them off
// Whoever gets the FlushDone will then need to turn
// TX Ints back on if needed.
EnterCriticalSection(&(pHWHead->RegCritSec));
try {
// Need to signal FlushDone for XmitComChar
PulseEvent(pHWHead->FlushDone);
pHWHead->CommErrors &= ~CE_TXFULL;
// If CTS flow control is desired, check cts. If clear, don't send,
// but loop. When CTS comes back on, the OtherInt routine will
// detect this and re-enable TX interrupts (causing Flushdone).
// For finest granularity, we would check this in the loop below,
// but for speed, I check it here (up to 8 xmit characters before
// we actually flow off.
if ( pHWHead->dcb.fOutxCtsFlow ) {
// ReadMSR( pHWHead );
// We don't need to explicitly read the MSR, since we always enable
// IER_MS, which ensures that we will get an interrupt and read
// the MSR whenever CTS, DSR, TERI, or DCD change.
if (! (pHWHead->MSR & SERIAL_MSR_CTS) ) {
ULONG value;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -