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

📄 ser2440_hw.c

📁 2440开发板pb4.2增加两个串口需更改的文件。
💻 C
📖 第 1 页 / 共 5 页
字号:
		}
	}
	except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
		EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
		bRet = FALSE;
	}
	LeaveCriticalSection(&(pHWHead->RegCritSec));

	RETAILMSG(DEBUGMODE, (TEXT("-SL_SetParity 0x%X\r\n"), pHead));

	return(bRet);
}
//
// @doc OEM
// @func VOID | SL_SetStopBits |
//  This routine sets the Stop Bits for the device.
//
// @rdesc None.
//
BOOL
SL_SetStopBits(
              PVOID   pHead,      // @parm     PVOID returned by HWInit
              ULONG   StopBits  // @parm     ULONG StopBits field from DCB.
              )
{
	PS2440_UART_INFO    pHWHead = (PS2440_UART_INFO)pHead;

	UINT32 lcr;
	BOOL bRet;

	RETAILMSG (DEBUGMODE,(TEXT("+SL_SetStopBits 0x%X, 0x%X\r\n"), pHead, StopBits));

	bRet = TRUE;

	EnterCriticalSection(&(pHWHead->RegCritSec));

	try {
		lcr = INREG(pHWHead,rULCON);
		lcr &= ~SER2440_STOPBIT_MASK;

		// 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 |= 0;//SERIAL_1_STOP ;
		break;
		case ONE5STOPBITS :
			//lcr |= SERIAL_1_5_STOP ;
			//break;
		case TWOSTOPBITS :
			lcr |= 4;//SERIAL_2_STOP ;
		break;
		default:
			bRet = FALSE;
		break;
		}

		if (bRet) {
			OUTREG(pHWHead,rULCON,lcr);
		}
	}
	except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
		EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
		bRet = FALSE;
	}

	LeaveCriticalSection(&(pHWHead->RegCritSec));

	RETAILMSG(DEBUGMODE,(TEXT("-SL_SetStopBits 0x%X\r\n"), pHead));

	return(bRet);
}

//
// @doc OEM
// @func ULONG | SL_GetRxBufferSize | This function returns
// the size of the hardware buffer passed to the interrupt
// initialize function.  It would be used only for devices
// which share a buffer between the MDD/PDD and an ISR.
//
// 
// @rdesc This routine always returns 0 for 16550 UARTS.
// 
ULONG
SL_GetRxBufferSize(
                  PVOID pHead
                  )
{
	RETAILMSG(DEBUGMODE, (TEXT("SL_GetRxBufferSize \r\n")));
	return(0);
}

//
// @doc OEM
// @func PVOID | SC_GetRxStart | This routine returns the start of the hardware
// receive buffer.  See SL_GetRxBufferSize.
// 
// @rdesc The return value is a pointer to the start of the device receive buffer.
// 
PVOID
SL_GetRxStart(
             PVOID   pHead // @parm PVOID returned by SC_init.
             )
{
	RETAILMSG(DEBUGMODE, (TEXT("SL_GetRxStart \r\n")));
	return(NULL);
}

//
// @doc OEM
// @func ULONG | SL_GetInterruptType | This function is called
//   by the MDD whenever an interrupt occurs.  The return code
//   is then checked by the MDD to determine which of the four
//   interrupt handling routines are to be called.
// 
// @rdesc This routine returns a bitmask indicating which interrupts
//   are currently pending.
// 
INTERRUPT_TYPE
SL_GetInterruptType(
                   PVOID pHead      // Pointer to hardware head
                   )
{
	PS2440_UART_INFO    pHWHead = (PS2440_UART_INFO)pHead;
	INTERRUPT_TYPE interrupts;
	ULONG IntPndVal=0;
	ULONG IntSubPndVal=0;

	try {
		IntPndVal = *(pHWHead->UART_INTSRCPND);
		IntSubPndVal = *(pHWHead->UART_INTSUBSRCPND);
	}
	except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
		EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
		RETAILMSG(DEBUGMODE, (TEXT("ACCESS VIOLATION ERROR \r\n")));
		IntPndVal = SER2440_INT_INVALID; // simulate no interrupt
	}

	RETAILMSG(DEBUGMODE, (TEXT("SL_GetInterruptType : 0x%X, 0x%X, 0x%X, 0x%X, 0x%X, 0x%X\r\n"),
		*(pHWHead->UART_INTMASK),
		*(pHWHead->UART_INTSUBMASK),
		*(pHWHead->UART_INTSRCPND),
		*(pHWHead->UART_INTSUBSRCPND),
		~(*(pHWHead->UART_INTSUBMASK)) & *(pHWHead->UART_INTSUBSRCPND),
		pHWHead->fSW_EnTxINT));

	if ( IntPndVal & (pHWHead->bINT) )
	{
		if ( IntSubPndVal == SER2440_INT_INVALID ) {      
			RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: SER2440_INT_INVALID\r\n")));
			interrupts = INTR_NONE;
		}
		else if(IntSubPndVal & (pHWHead->bErrINT) )  {
			RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_LINE\r\n")));
			interrupts = INTR_LINE;  // Error status
		}
		else if(IntSubPndVal & (pHWHead->bRxINT) )  {
			RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_RX\r\n")));
			interrupts = INTR_RX;    // Received valid data.
		}
		else if((IntSubPndVal & (pHWHead->bTxINT)) && pHWHead->fSW_EnTxINT )  {
			RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_TX\r\n")));
			interrupts = INTR_TX;
		}
		else 
		{
//			RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_NONE\r\n")));
			interrupts = INTR_NONE;  // No interrupts pending, vector is useless
//			ClearINTPnd(pHWHead, pHWHead->bINT);
		}
	}
	else {
		RETAILMSG (DEBUGMODE, (TEXT("SL_GetInterruptType: INTR_NONE(pHWHead->bINT)\r\n")));
		interrupts = INTR_NONE;  // No interrupts pending, vector is useless
	}

	return(interrupts);
}


// @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
         )
{
	PS2440_UART_INFO   pHWHead    = (PS2440_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 {
		// S2440 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 & COM2440_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.
           )
{
	PS2440_UART_INFO   pHWHead    = (PS2440_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
         )
{
    PS2440_UART_INFO   pHWHead    = (PS2440_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
           )
{
	PS2440_UART_INFO   pHWHead    = (PS2440_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 & SER2440_FIFOCNT_MASK_TX) >> 4);

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

		if (!(rFifoStat & SER2440_FIFOFULL_TX) && (TxFifoCnt < (SER2440_FIFO_DEPTH_TX-1))) {
			byteCount = (unsigned char)(SER2440_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 )

⌨️ 快捷键说明

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