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

📄 ser2410_hw.c

📁 SBC2410 WinCE 5.0 BSP.绝大多数驱动已经调通。
💻 C
📖 第 1 页 / 共 5 页
字号:
}


// @doc OEM
// @func ULONG | SL_RxIntr | This routine gets several characters from the hardware
//   receive buffer and puts them in a buffer provided via the second argument.
//   It returns the number of bytes lost to overrun.
// 
// @rdesc The return value indicates the number of overruns detected.
//   The actual number of dropped characters may be higher.
//
ULONG
SL_RxIntr(
         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
         )
{
	PS2410_UART_INFO   pHWHead    = (PS2410_UART_INFO)pHead;

	ULONG        RetVal    = 0;
	ULONG        TargetRoom    = *pBufflen;
	BOOL        fRXFlag = FALSE;
	BOOL        fReplaceparityErrors = FALSE;
	BOOL        fNull;
	UCHAR       cEvtChar, cRXChar;
	ULONG       rFifoStat, RxFifoCnt, RxDataReady, nRxIntSrc;

	*pBufflen = 0;
	nRxIntSrc = pHWHead->bRxINT;

	RETAILMSG(DEBUGMODE, (TEXT("SL_RxIntr \r\n")));
	// 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 {
		// S2410 UART Rx strategy is different from SER16550..
		rFifoStat = INREG(pHWHead,rUFSTAT);
		RxFifoCnt = rFifoStat & 0x0f;
		if((rFifoStat & 0x100)||(RxFifoCnt > 0))
			RxDataReady = 1;
		else
			RxDataReady = 0;

		while ( TargetRoom && RxDataReady ) {
			// If the line is unstable, we may check the error status...
			// But now, I ignore it....
			// ReadLSR( pHWHead );

			// Read the byte
			cRXChar = *(pHWHead->pUFRXH);
			RETAILMSG(DEBUGMODE, (TEXT("SL_RxIntr : cRXChar = 0x%x \r\n"), cRXChar));

			// But we may want to discard it
			if ( pHWHead->dcb.fDsrSensitivity &&
				(! (pHWHead->vUMSTAT & COM2410_MSR_DSR)) ) {
				// Do nothing - byte gets discarded
				RETAILMSG (1, (TEXT("Dropping byte because DSR is low\r\n")));
			} else if (!cRXChar && fNull) {
				// Do nothing - byte gets discarded
				RETAILMSG (1, (TEXT("Dropping NULL byte due to fNull\r\n")));
			} else {
				// Do character replacement if parity error detected.
				// 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.
				if (!pHWHead->RxDiscard ) {
					*pRxBuffer++ = cRXChar;
					(*pBufflen)++;
				} else {
					RETAILMSG (1,(TEXT("SL_RXIntr : Dropping byte because now Txing\r\n")));
				}

				--TargetRoom;
//				RxFifoCnt--;
//				RxFifoCnt = INREG(pHWHead,rUFSTAT) & 0x0f;
				rFifoStat = INREG(pHWHead,rUFSTAT);
				RxFifoCnt = rFifoStat & 0x0f;
				if((rFifoStat & 0x100)||(RxFifoCnt > 0))
					RxDataReady = 1;
				else
					RxDataReady = 0;

			}
		}

		//Clear interrupt pending bit
		ClearSubINTPnd(pHWHead, nRxIntSrc);
		if ( *(pHWHead->UART_INTSUBSRCPND) & ( pHWHead->bRxINT | pHWHead->bErrINT ) )
		{
			RETAILMSG (DEBUGMODE, (TEXT("*(pHWHead->UART_INTSUBSRCPND) = %x \r\n"), *(pHWHead->UART_INTSUBSRCPND)));
			RETAILMSG (DEBUGMODE, (TEXT("Do Not Clear bINT \r\n")));
		}
		else
		{
			ClearINTPnd(pHWHead, pHWHead->bINT);
		}
		EnINT(pHWHead, pHWHead->bINT);
		EnSubINT(pHWHead, nRxIntSrc);
	}
	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 )
	{
		RETAILMSG (DEBUGMODE, (TEXT("Rx drop %d.\r\n"), pHWHead->DroppedBytes));
	}
    
	RetVal = pHWHead->DroppedBytes;
	pHWHead->DroppedBytes = 0;
	return(RetVal);
}

// @doc OEM
// @func ULONG | SL_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
SL_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.
           )
{
	PS2410_UART_INFO   pHWHead    = (PS2410_UART_INFO)pHead;
	RETAILMSG(1,(TEXT("This routine is called by old MDD\r\n")));
	return(0);
}

//
// @doc OEM
// @func ULONG | SL_TXIntr | This routine is called from the old MDD
//   whenever INTR_TX is returned by SL_GetInterruptType (Obselete)
// 
// @rdesc None
//
VOID
SL_TxIntr(
         PVOID pHead                // Hardware Head
         )
{
    PS2410_UART_INFO   pHWHead    = (PS2410_UART_INFO)pHead;
    RETAILMSG(1, (TEXT("SL_TxIntr(From old MDD)\n")));
}

//
// @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_TxIntrEx(
           PVOID pHead,                // Hardware Head
           PUCHAR pTxBuffer,          // @parm Pointer to receive buffer
           ULONG *pBufflen            // @parm In = max bytes to transmit, out = bytes transmitted
           )
{
	PS2410_UART_INFO   pHWHead    = (PS2410_UART_INFO)pHead;

	UCHAR       byteCount;
	ULONG NumberOfBytes = *pBufflen;
	ULONG       rFifoStat, TxFifoCnt;
	unsigned int FifoModeReg;
   
	RETAILMSG(DEBUGMODE, (TEXT("SL_TxIntrEx \r\n")));
	// We may be done sending.  If so, just disable the TX interrupts and return to the MDD.  
	if( ! *pBufflen ) {
		DisEnINT(pHWHead, pHWHead->bINT);
		DisEnSubINT(pHWHead, pHWHead->bTxINT);
		pHWHead->fSW_EnTxINT = FALSE;

		ClearINTPnd(pHWHead, pHWHead->bINT);
		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;
	}
	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));

	//  OK, now lets actually transmit some data.
	EnterCriticalSection(&(pHWHead->TransmitCritSec));
	EnterCriticalSection(&(pHWHead->RegCritSec));

	FifoModeReg = INREG(pHWHead, rUFCON);

	try {
		rFifoStat = INREG(pHWHead,rUFSTAT);
		TxFifoCnt = ((rFifoStat & SER2410_FIFOCNT_MASK_TX) >> 4);

		if (pHWHead->UseIrDA)
		{
			// IR is half-duplex.
			pHWHead->RxDiscard = TRUE;
			DisEnSubINT(pHWHead, pHWHead->bRxINT);
		}

		if (!(rFifoStat & SER2410_FIFOFULL_TX) && (TxFifoCnt < (SER2410_FIFO_DEPTH_TX-1))) {
			byteCount = (unsigned char)(SER2410_FIFO_DEPTH_TX-TxFifoCnt);
			RETAILMSG(DEBUGMODE, (TEXT("SL_TxIntrEx : %d \r\n"), NumberOfBytes));
			for ( *pBufflen=0; NumberOfBytes && byteCount; NumberOfBytes--, byteCount-- ) {
				unsigned int i, tmpreg;
				*(pHWHead->pUFTXH) = *pTxBuffer;
				RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt - *pTxBuffer = 0x%x \r\n"), *pTxBuffer));
				if (FifoModeReg&0x1) // FIFO Mode enabled.
				{
					for ( i = 0; i < 600000; i++ )
					{
						tmpreg = INREG(pHWHead, rUFSTAT);
						//tmpreg & 0x200 == 1  ->  Fifo full -> waiting...
						//tmpreg & 0xf0 == 0 -> There is no data to send -> break loop.
						if ( (tmpreg & 0x200) == 0x200 )
						{
//							RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt :  fifo full : tmpreg = %x \r\n"), tmpreg));
							continue;
						}
						else break;
					}
					if ( i == 600000 )	// Time Out Error
					{
						RETAILMSG (1, (TEXT("SL_TxInt : Error : i = %d \r\n"), i));
					}
				}
				else		// FIFO Mode disabled.
				{
					for ( i = 0; i < 600000; i++ )
					{
						tmpreg = INREG(pHWHead, rUTRSTAT);
						if ( tmpreg & 0x2 ) break;
					}
					if ( i == 600000 )
					{
						RETAILMSG (1, (TEXT("SL_TxInt : Error : i = %d \r\n"), i));
					}
				}

				++pTxBuffer;
				(*pBufflen)++;
			}

			if (FifoModeReg&0x1) // FIFO Mode enabled.
			{
				unsigned int cnt = 0;
				for ( ;; )
				{
					unsigned int tmpreg;
					tmpreg = INREG(pHWHead, rUFSTAT);
//					RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt : Waiting till tx buffer empty :  tmpreg = %x \r\n"), tmpreg));
					if ( (tmpreg & 0xf0) == 0) break; // waitint to empty the tx buffer empty...
					if ( cnt++ > 600000 )
					{
						RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt : Reset TX FIFO :  tmpreg = %x \r\n"), tmpreg));
						//SETREG(pHWHead,rUFCON,0x6);    // tx, rx fifo reset
						SETREG(pHWHead,rUFCON,0x4);    // tx, rx fifo reset
						break;
					}
				}
				RETAILMSG(DEBUGMODE, (TEXT("SL_TxInt : Exit for loop \r\n")));
			}

		}
		else
		{
			RETAILMSG (1, (TEXT("SL_TxIntrEx: Not Send - rFifoStat[0x%x] TxFifoCnt[0x%x]\r\n"),
							rFifoStat, TxFifoCnt));
		}

		if (pHWHead->UseIrDA )
		{
			// IR is half-duplex.
			ClearPendingInts( pHWHead );
			EnSubINT(pHWHead, pHWHead->bRxINT);
			pHWHead->RxDiscard = FALSE;
		}

		// Enable xmit intr. We need to do this no matter what, 
		// since the MDD relies on one final interrupt before
		// returning to the application. 
		ClearPendingInts( pHWHead );

		EnINT(pHWHead, pHWHead->bINT);
		EnSubINT(pHWHead, pHWHead->bTxINT);
		pHWHead->fSW_EnTxINT = TRUE;  // FALSE;
	}
	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));
	return;
}

//
// @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
           )
{
	PS2410_UART_INFO   pHWHead    = (PS2410_UART_INFO)pHead;

	RETAILMSG(DEBUGMODE,(TEXT("INTR_LINE \r\n")));

	ReadLSR( pHWHead );

	ClearINTPnd(pHWHead, pHWHead->bINT);
	ClearSubINTPnd(pHWHead, pHWHead->bErrINT);
	EnINT(pHWHead, pHWHead->bINT);
	EnSubINT(pHWHead, pHWHead->bErrINT);
}

//
// @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
            )
{
    PS2410_UART_INFO   pHWHead    = (PS2410_UART_INFO)pHead;

    // S2410 does not have modem interrupt.
  
    RETAILMSG(DEBUGMODE,(TEXT("+SL_OtherIntr \r\n")));

    ReadMSR( 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->vUMSTAT & COM2410_MSR_DSR) ) {
            RETAILMSG (DEBUGMODE, (TEXT("**********************PutBytes, flowed on via DSR\n") ) );
            pHWHead->DSRFlowOff = FALSE;
            // DSR 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;
        }
        if ( pHWHead->CTSFlowOff && (pHWHead->vUMSTAT & COM2410_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
            )
{
	PS2410_UART_INFO   pHWHead    = (PS2410_UART_INFO)pHead;
	INTERRUPT_TYPE      it = INTR_NONE;
	ULONG               win32status = 0;

⌨️ 快捷键说明

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