⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xrser16550.c

📁 wince 5.0下 实现PCI8串口卡驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
                else
                    break;
            }
            else {
                ReadLSR( pHWHead );
                if ( pHWHead->LSR & SERIAL_LSR_DR ) {
                    // Read the byte
#ifdef DO_NOT_USE_EXTENDED_FUNCTIONALITY
                    cRXChar = INB(pHWHead, pData);
#else
					cRXChar = Read1Byte(pHWHead->pData, 0x100);//UART_17158_RX_OFFSET
#endif
                }
                else
                    break;
            }
            // But we may want to discard it
            if ( pHWHead->dcb.fDsrSensitivity &&
                (! (pHWHead->MSR & SERIAL_MSR_DSR)) ) {
                // Do nothing - byte gets discarded
                DEBUGMSG (ZONE_FLOW,
                    (TEXT("Dropping byte because DSR is low\r\n")));
            } else if (!cRXChar && fNull) {
                // Do nothing - byte gets discarded
                DEBUGMSG (ZONE_FLOW| ZONE_WARN,
                    (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, IER_NORMAL_INTS | SERIAL_IER_THR);
    return(RetVal);
}

// @doc OEM
// @func ULONG | XRSL_PutBytes | This routine is called from the MDD
//   in order to write a stream of data to the device. (Obselete)
// 
// @rdesc Always returns 0
//
ULONG
XRSL_PutBytes(
           PVOID   pHead,        // @parm    PVOID returned by HWInit.
           PUCHAR  pSrc,        // @parm    Pointer to bytes to be sent.
           ULONG   NumberOfBytes,  // @parm    Number of bytes to be sent.
           PULONG  pBytesSent        // @parm    Pointer to actual number of bytes put.
           )
{
    PSER16550_INFO   pHWHead    = (PSER16550_INFO)pHead;

    DEBUGMSG (ZONE_WRITE, (TEXT("+PutBytes - Len %d.\r\n"),
                           NumberOfBytes));

    pHWHead->CommErrors &= ~CE_TXFULL;
    *pBytesSent = 0;

    // 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) ) {
            unsigned char byte;
            DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
                      (TEXT("PutBytes, flowed off via CTS\n") ) );
            pHWHead->CTSFlowOff = TRUE;  // Record flowed off state

            EnterCriticalSection(&(pHWHead->RegCritSec));
            if (pHWHead->pIsrInfoVirt ==NULL || pHWHead->pXmitBuffer ==NULL || GetXmitDataSize(pHWHead->pXmitBuffer)==0)  { // no data inbuffer. 
                try {
                    byte = INB(pHWHead, pIER);
                    OUTB(pHWHead, pIER, byte & ~SERIAL_IER_THR); // disable TX interrupts while flowed off
                }
                except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
                        EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
                    // Just ignore it, we'll eventually fall out of here
                }
            }
            LeaveCriticalSection(&(pHWHead->RegCritSec));

            // We could return a positive value here, which would
            // cause the MDD to periodically check the flow control
            // status.  However, we don't need to since we know that
            // the DCTS interrupt will cause the MDD to call us, and we
            // will subsequently fake a TX interrupt to the MDD, causing
            // him to call back into PutBytes.
            return(0);
        }
    }

    // Same thing applies for DSR
    if ( pHWHead->dcb.fOutxDsrFlow ) {
        // 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_DSR) ) {
            DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
                      (TEXT("PutBytes, flowed off via DSR\n") ) );
            pHWHead->DSRFlowOff = TRUE;  // Record flowed off state

            EnterCriticalSection(&(pHWHead->RegCritSec));            
			if (pHWHead->pIsrInfoVirt ==NULL || pHWHead->pXmitBuffer==NULL || GetXmitDataSize(pHWHead->pXmitBuffer)==0) { // no data inbuffer. 
                try {
                    OUTB(pHWHead, pIER, IER_NORMAL_INTS); // disable TX interrupts while flowed off
                }
                except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
                        EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
                    // Just ignore it, we'll eventually fall out of here
                }
            }
            LeaveCriticalSection(&(pHWHead->RegCritSec));

            // See the comment above above positive return codes.
            return(0);
        }
    }

    DEBUGMSG (ZONE_WRITE, (TEXT("PutBytes wait for CritSec %x.\r\n"),
                           &(pHWHead->TransmitCritSec)));
    EnterCriticalSection(&(pHWHead->TransmitCritSec));
    DEBUGMSG (ZONE_WRITE, (TEXT("PutBytes got CritSec %x.\r\n"),
                           &(pHWHead->TransmitCritSec)));
    EnterCriticalSection(&(pHWHead->RegCritSec));
    try {
        if (pHWHead->pIsrInfoVirt ==NULL || pHWHead->pXmitBuffer==NULL || GetXmitDataSize(pHWHead->pXmitBuffer)==0) { // no data inbuffer. 
            ReadLSR( pHWHead );
            if ( pHWHead->LSR & SERIAL_LSR_THRE ) {
                UCHAR       byteCount;
#ifdef DO_NOT_USE_EXTENDED_FUNCTIONALITY
                if ( pHWHead->IIR & SERIAL_IIR_FIFOS_ENABLED )
				{
                    byteCount = SERIAL_FIFO_DEPTH;					
				}
                else
                    byteCount = 1;
#else
				//
				// how much buffer is availabe now to write?
				//
				//byteCount = Read1Byte(pHWHead->pData, XR_17C15X_TXFIFO_CNT); 
				if ( pHWHead->IIR & SERIAL_IIR_FIFOS_ENABLED )
				{
                    byteCount = 64;					
				}
                else
                    byteCount = 1;
#endif

                OUTB(pHWHead, pIER, IER_NORMAL_INTS ); // Mask Xmit Interrupt.
                DEBUGMSG (ZONE_WRITE | ZONE_THREAD,
                    (TEXT("Put Bytes - Write max of %d bytes\r\n"),
                    byteCount));
                if (pHWHead->pIsrInfoVirt !=NULL && pHWHead->pXmitBuffer!=NULL)  { // Software Xmit FIFO
                    if (NumberOfBytes)	{
                        UCHAR bFirstByte=*pSrc;
                        NumberOfBytes--;
                        ++pSrc;
                        (*pBytesSent)++;
                        // Fill up the software ISR buffer.                        
						while (GetXmitAvailableBuffer(pHWHead->pXmitBuffer)>min(pHWHead->pXmitBuffer->dwWaterMark,2) &&
                            NumberOfBytes) {
                            pHWHead->pXmitBuffer->bBuffer[pHWHead->pXmitBuffer->dwFIFO_In]=*pSrc;                            
							pHWHead->pXmitBuffer->dwFIFO_In=IncXmitIndex(pHWHead->pXmitBuffer,pHWHead->pXmitBuffer->dwFIFO_In);
                            ++pSrc;
                            (*pBytesSent)++;
                            NumberOfBytes--;
                        }
                        OUTB(pHWHead, pData, bFirstByte);
                        OUTB(pHWHead, pIER, IER_NORMAL_INTS | SERIAL_IER_THR);
                    }
                    pHWHead->bMoreXmitData=(NumberOfBytes==0?FALSE:TRUE);
                }
                else
                    for ( ; NumberOfBytes && byteCount; NumberOfBytes--, byteCount-- ) {
                        DEBUGLED( ZONE_WRITE, (1, 0x10200000 | *pSrc) );
                        OUTB(pHWHead, pData, *pSrc);
                        ++pSrc;
                        (*pBytesSent)++;
                    }
            }
        }
        // Enable xmit intr. We need to do this no matter what, 
        // since the MDD relies on one final interrupt before
        // returning to the application. 
        OUTB(pHWHead, pIER, IER_NORMAL_INTS | SERIAL_IER_THR);
    }
    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));
    DEBUGMSG (ZONE_WRITE, (TEXT("PutBytes released CritSec %x.\r\n"),
                           &(pHWHead->TransmitCritSec)));

    DEBUGMSG (ZONE_WRITE, (TEXT("-PutBytes - sent %d.\r\n"),
                           *pBytesSent));

    return(0);
}

//
// @doc OEM
// @func ULONG | XRSL_TXIntr | This routine is called from the old MDD
//   whenever INTR_TX is returned by XRSL_GetInterruptType (Obselete)
// 
// @rdesc None
//
VOID
XRSL_TxIntr(
         PVOID pHead                // Hardware Head
         )
{
    PSER16550_INFO   pHWHead    = (PSER16550_INFO)pHead;

    DEBUGMSG (0,
              (TEXT("+XRSL_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));
	if (pHWHead->pIsrInfoVirt ==NULL || pHWHead->pXmitBuffer==NULL || GetXmitDataSize(pHWHead->pXmitBuffer)==0)  {// no data inbuffer.     
        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.
        }
    }
    else 
    if (pHWHead->pIsrInfoVirt  && pHWHead->pXmitBuffer && pHWHead->pXmitBuffer->dwFIFO_Out!=pHWHead->pXmitBuffer->dwFIFO_In) {
        pHWHead->pXmitBuffer->dwFIFO_Out=pHWHead->pXmitBuffer->dwFIFO_In;
        OUTB(pHWHead, pIIR_FCR, pHWHead->FCR | SERIAL_FCR_TXMT_RESET);
        DEBUGMSG (ZONE_ERROR,(TEXT("XRSL_TxIntr:Xmit IST run with SOFT FIFO not empty!!!0x%X\r\n"), pHead));
    }
    LeaveCriticalSection(&(pHWHead->RegCritSec));

    // Let the putbytes routine know he can continue
    PulseEvent(pHWHead->FlushDone);

    DEBUGMSG (0,
              (TEXT("+XRSL_TxIntr 0x%X\r\n"), pHead));
}

//
// @doc OEM
// @func ULONG | XRSL_TXIntrEx | This routine is called from the new MDD
//   whenever INTR_TX is returned by XRSL_GetInterruptType
// 
// @rdesc None
//
VOID
XRSL_TxIntrEx(
           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("+XRSL_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("XRSL_TxIntrEx: Disable INTR_TX.\r\n")));
        if (pHWHead->pIsrInfoVirt && pHWHead->pXmitBuffer) {
// in case of !DO_NOT_USE_EXTENDED_FUNCTIONALITY i.e, while using extended....
// with the new architecture dwFIFO_In != dwFIFO_Out sometimes may be due to trigger levels
// ISR takes care of sending all the data
// so, don't worry about resetting and there won't be any loss of data.
// just return without disabling the transmit interrupt
#ifdef DO_NOT_USE_EXTENDED_FUNCTIONALITY
            pHWHead->bMoreXmitData=FALSE;
            while (pHWHead->pXmitBuffer->dwFIFO_In!= pHWHead->pXmitBuffer->dwFIFO_Out) {
                RETAILMSG(1,(TEXT("!!!XRSL_TxIntrEx: We found lost Xmit FIFO Data \r\n")));
                pHWHead->pXmitBuffer->dwFIFO_In= pHWHead->pXmitBuffer->dwFIFO_Out;
                OUTB(pHWHead, pIIR_FCR, pHWHead->FCR | SERIAL_FCR_TXMT_RESET);
            }
		}
#else
        }
		return;
#endif
        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) ) {
                unsigned char byte;
                DEBUGMSG (ZONE_WRITE|ZONE_FLOW,
                          (TEXT("XRSL_TxIntrEx, flowed off via CTS\n") ) );
                pHWHead->CTSFlowOff = TRUE;  // Record flowed off state
                if (pHWHead->pIsrInfoVirt==NULL || pHWHead->pXmitBuffer==NULL || GetXmitDataSize(pHWHead->pXmitBuffer)==0)  {// no data inbuffer. 				
                    byte = INB(pHWHead, pIER);
                    OUTB(pHWHead, pIER, byte & ~SERIAL_IER_THR); // disable TX interrupts while flowed off
                }
                // We could return a positive va

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -