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

📄 scif.c

📁 Wince4.2 BSP for SH4 engineering development board
💻 C
📖 第 1 页 / 共 5 页
字号:
	 */
	WRITE_REGISTER_USHORT(pHWHead->pSSR, READ_REGISTER_USHORT(pHWHead->pSSR) & 
		~(SCIF_SCSSR_RDF | SCIF_SCSSR_DR)); 
    DEBUGMSG (ZONE_FUNCTION, (TEXT("-GetBytes - len %d.\r\n"),
                  *pBufflen));
    return RetVal;
}

/*****************************************************************************
*	FUNCTION :		SCIF_PutBytes
*	DESCRIPTION :	This routine inserts a stream of bytes onto the serial 
*					device (comport)
*	INPUTS :		The HW device info, the src string, number of bytes
*	OUTPUTS :		number of bytes actually sent
*	DESIGN NOTES :	
*	CAUTIONS :		
*****************************************************************************/
ULONG SCIF_PutBytes(
    PVOID   pHead,						/* PVOID returned by SCIF_Init. */
    PUCHAR  pSrc,						/* Pointer to bytes to be sent. */
    ULONG   NumberOfBytes,				/* Number of bytes to be sent. */
    PULONG  pBytesSent)					/* Pointer to actual number of bytes put. */
{
    PSCIF_INFO	pHWHead	= (PSCIF_INFO)pHead;
    BYTE		byteCount;
	USHORT		SSR;

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

    /* clear and txmit buffer full errors */
	pHWHead->CommErrors &= ~CE_TXFULL;

    // CTS flow control
    if(pHWHead->dcb.fOutxCtsFlow) {
        // check CTS just before transmission
        ReadModemStatus(pHWHead);
        
        if(!(pHWHead->ModemStatus & MS_CTS_ON)) {
            DEBUGMSG(ZONE_WRITE|ZONE_FLOW, (TEXT("PutBytes: Flowed OFF via CTS\r\n")));
            
            // start to check CTS periodically
            pHWHead->CTSFlowOff = TRUE;
            SetEvent(pHWHead->hModemLinePollingEvent);
            
            // never let MDD callback here (which uses Sleep API), because it may cause dropping
            // Tx interrupts which come in simultaneously.
            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)));
 
    SSR = ReadStatus( pHWHead );
    
    while (NumberOfBytes && (byteCount = (FIFO_SIZE - GET_SCFDR_TX_BYTES(*pHWHead->pFDR))))
    {
		        
        DEBUGMSG (ZONE_WRITE | ZONE_THREAD,
			(TEXT("Put Bytes - Writing (0x%x), NumberofBytes = %d, byteCount = %d\r\n"),
			*pSrc, NumberOfBytes, byteCount));

		WRITE_REGISTER_UCHAR(pHWHead->pFTDR, *pSrc);
        ++pSrc;
        (*pBytesSent)++;
		NumberOfBytes--;
	}
    /*
	 * Enable xmit intr. We need to do this no matter what, 
     * since the MDD relies on one final interrupt before
     * returning to the application. 
	 */
     WRITE_REGISTER_USHORT(pHWHead->pSCR, READ_REGISTER_USHORT(pHWHead->pSCR) |
		SCIF_SCSCR_TIE); 
    
	 
    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;
}

/*****************************************************************************
*	FUNCTION :		SCIF_TxIntr
*	DESCRIPTION :	This routine is called from the MDD whenever INTR_TX is 
*					returned by SCIF_GetInterruptType.  
*	INPUTS :		pHead
*	OUTPUTS :		none
*	DESIGN NOTES :	This function is referred to as HWTxIntrHandler() by the MDD
*					A transmit interrupt only occurs when someone is waiting to
*					finish a transmit.  So it is effectively a flush.  So
*					all we really do here is set the Flush event
*	CAUTIONS :		
*****************************************************************************/
VOID SCIF_TxIntr(
    PVOID pHead)							/* Hardware Head */
{
    PSCIF_INFO   pHWHead	= (PSCIF_INFO)pHead;

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

    /* Clear and disable the interrupt */
    WRITE_REGISTER_USHORT(pHWHead->pSCR, READ_REGISTER_USHORT(pHWHead->pSCR)
		& ~SCIF_SCSCR_TIE); 
    WRITE_REGISTER_USHORT(pHWHead->pSSR, READ_REGISTER_USHORT(pHWHead->pSSR)
		& ~SCIF_SCSSR_TDFE);
	pHWHead->CommCharInQueue = FALSE;
	DEBUGMSG (ZONE_EVENTS,(TEXT("SCIF_TxIntr : Interrupt Cleared\r\n")));

    
    /* Let the putbytes routine know he can continue */
    PulseEvent(pHWHead->FlushDone);
    
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-SCIF_TxIntr 0x%X\r\n"), pHead));
}

/*****************************************************************************
*	FUNCTION :		SCIF_LineIntr
*	DESCRIPTION :	This routine is called from the MDD whenever INTR_LINE is 
*					returned by SCIF_GetInterruptType.  
*	INPUTS :		pHead
*	OUTPUTS :		none
*	DESIGN NOTES :	This function is referred to as HWClearLineIntr by the MDD.
*					Since we are here because of an interrupt we need to modify 
*					to clear it.
*	CAUTIONS :		
*****************************************************************************/
VOID SCIF_LineIntr(
    PVOID pHead)                /* Hardware Head */
{
    PSCIF_INFO   pHWHead	= (PSCIF_INFO)pHead;

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+SCIF_LineIntr 0x%X\r\n"), pHead));
    ReadStatus( pHWHead );

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-SCIF_LineIntr 0x%X\r\n"), pHead));
}

/*****************************************************************************
*	FUNCTION :		SCIF_OtherIntr
*	DESCRIPTION :	This routine is called from the MDD whenever INTR_MODEM 
*					is returned by SCIF_GetInterruptType.
*	INPUTS :		pHead
*	OUTPUTS :		none
*	DESIGN NOTES :	This function is referred to as HWClearOtherIntr by the MDD.
*					all we do is see what has changed on the line.  Since we 
*					are here because of an interrupt we need to modify 
*					the interrupt so that we will be able to detect the 
*					change in level of the DCD and CTS
*	CAUTIONS :		
*****************************************************************************/
VOID SCIF_OtherIntr(PVOID pHead)
{
    PSCIF_INFO   pHWHead	= (PSCIF_INFO)pHead;

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

    ReadModemStatus( pHWHead );
    
    /*
	* 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->SCPDR & SCPDR_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 */
 
		/* Then simulate a TX intr to get things moving */
//		pHWHead->AddTXIntr = TRUE;
//    }
	
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-SCIF_OtherIntr 0x%X\r\n"), pHead));
}
        

/*****************************************************************************
*	FUNCTION :		SCIF_GetStatus
*	DESCRIPTION :	This structure is called by the MDD to retrieve the 
*					contents of a COMSTAT structure.
*	INPUTS :		pHead
*	OUTPUTS :		none
*	DESIGN NOTES :	The return is a ULONG, representing success (0) or 
*					failure (-1).
*	CAUTIONS :		PDD sets fCtsHold, fDsrHold, fRLSDHold, and fTXim
*****************************************************************************/
ULONG SCIF_GetStatus(
    PVOID	pHead,					/* PVOID returned by SCIF_Init. */
    LPCOMSTAT	lpStat)				/* Pointer to LPCOMMSTAT to hold status. */
{
    PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
    ULONG	  RetVal  = pHWHead->CommErrors;
    
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+SCIF_GetStatus 0x%X\r\n"), pHead));
    pHWHead->CommErrors = 0;		/* Clear old errors each time */
    
    if ( lpStat )
	{
        if (pHWHead->ModemStatus & MS_CTS_MASK)
            pHWHead->Status.fCtsHold = 1;
        else
            pHWHead->Status.fCtsHold = 0;
        if (pHWHead->ModemStatus & MS_RLSD_MASK)
            pHWHead->Status.fRlsdHold = 1;
        else
            pHWHead->Status.fRlsdHold = 0;
        if (pHWHead->DSRFlowOff)
            pHWHead->Status.fDsrHold = 1;
        else
			pHWHead->Status.fDsrHold = 0;

		if (pHWHead->CommCharInQueue)
			pHWHead->Status.fTxim = TRUE;
		else
			pHWHead->Status.fTxim = FALSE;
	    
		DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-SCIF_GetStatus : fCtsHold = %d\r\n"), pHWHead->Status.fCtsHold));
		DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-SCIF_GetStatus : fDsrHold = %d\r\n"), pHWHead->Status.fDsrHold));
		DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-SCIF_GetStatus : fTxim = %d\r\n"), pHWHead->Status.fTxim));
             
        memcpy(lpStat, &(pHWHead->Status), sizeof(COMSTAT));
    }
    else
        RetVal = (ULONG)-1;

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-SCIF_GetStatus 0x%X\r\n"), pHead));
    return RetVal;
}

/*****************************************************************************
*	FUNCTION :		SCIF_Reset
*	DESCRIPTION :	Perform any operations associated with a device reset
*	INPUTS :		pHead
*	OUTPUTS :		none
*	DESIGN NOTES :	The only goal of this function is to reset the COMSTAT 
*					structure in our internal structure.  This function is 
*					NEVER called by the MDD.
*	CAUTIONS :		
*****************************************************************************/
VOID SCIF_Reset(PVOID   pHead)
{
    PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+SCIF_Reset 0x%X\r\n"), pHead)); 
    memset(&pHWHead->Status, 0, sizeof(COMSTAT));
 

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-SCIF_Reset 0x%X\r\n"), pHead));
}

/*****************************************************************************
*	FUNCTION :		SCIF_GetStatus
*	DESCRIPTION :	Retrieves modem status.
*	INPUTS :		pHead
*	OUTPUTS :		none
*	DESIGN NOTES :	The easiest way to do this, but not necessaily the cleanest
*					is to read the Interrupt register. If it is Rising Edge, then
*					we know that the signal is at 0, if it is Falling Edge, then
*					we know that the signal is at 1 (this is for CTS and DTR).
*					Note that 0 is ON and 1 is OFF.
*	CAUTIONS :      But,because of the specification of INTC in SH4, we can't
*                   check the edges or status of IRQ signal.
*                   Now on investigation.
*****************************************************************************/
VOID SCIF_GetModemStatus(
    PVOID   pHead,					/* PVOID returned by SCIF_Init. */
    PULONG  pModemStatus)			/* PULONG passed in by user.*/
{
    PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
    
    
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+SCIF_GetModemStatus 0x%X\r\n"), pHead));
    ReadModemStatus( pHWHead );
    
    *pModemStatus = pHWHead->ModemStatus;

    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("SCIF_GetModemStatus : ModemStatus = 0x%X\r\n"), *pModemStatus));


    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-SCIF_GetModemStatus 0x%X\r\n"), pHead));
    return;
}

/*****************************************************************************
*	FUNCTION :		SCIF_PurgeComm
*	DESCRIPTION :	Purge Rx and/or Tx.  Empty FIFO.
*	INPUTS :		The pointer to the hardware struct and action to take
*	OUTPUTS :		N/A
*	DESIGN NOTES :	
*	CAUTIONS :		
*****************************************************************************/
VOID SCIF_PurgeComm(
    PVOID   pHead,						/* PVOID returned by SCIF_Init. */
    DWORD   fdwAction)					/* @parm Action to take. */
{
    PSCIF_INFO	pHWHead = (PSCIF_INFO)pHead;
	WORD			FCR;				/* Old FCR info */ 
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+SCIF_PurgeComm 0x%X\r\n"), pHead));
    /*
	 * Notes from MS ---
	 * 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 inthe MDD.  for
	 * now, if it is ABORT we will dump all of the data by resetting the FIFO 
	 * no difference between ABORT and CLEAR.  There is not going to be an
	 * easy way to do an abort.  we cannot clear the regs beyond resetting the 
	 * fifo.  So reseting the FIFO is the closest we can come to aborting
	 * a transmission, and unless they de-init, we will keep getting data
     */
		
	FCR = READ_REGISTER_USHORT(pHWHead->pFCR); 

	if ( (fdwAction & PURGE_TXCLEAR) || (fdwAction & PURGE_TXABORT) )
    {
        WRITE_REGISTER_USHORT(pHWHead->pFCR, READ_REGISTER_USHORT(pHWHead->pFCR) 
			| SCIF_SCFCR_TFRST); 
        WRITE_REGISTER_USHORT(pHWHead->pFCR, FCR); 
    }

    if ( (fdwAction & PURGE_RXCLEAR) && (fdwAction & PURGE_RXABORT))
    {
		WRITE_REGISTER_USHORT(pHWHead->pFCR, READ_REGISTER_USHORT(pHWHead->pFCR) 
			| SCIF_SCFCR_RFRST); 
        WRITE_REGISTER_USHORT(pHWHead->pFCR, FCR); 
	}

	    
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("-SCIF_PurgeComm 0x%X\r\n"), pHead));
    return;
}

/*****************************************************************************
*	FUNCTION :		SCIF_XmitComChar
*	DESCRIPTION :	Transmit a char immediately
*	INPUTS :		The pointer to the hardware struct and the char to send
*	OUTPUTS :		N/A
*	DESIGN NOTES :	This code waits for the char to transmitted
*	CAUTIONS :		
*****************************************************************************/
BOOL SCIF_XmitComChar(
    PVOID   pHead,						/* PVOID returned by SCIF_Init.*/
    UCHAR   ComChar)					/* Character to transmit. */
{
    PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
    
    DEBUGMSG (ZONE_FUNCTION,
              (TEXT("+SCIF_XmitComChar 0x%X\r\n"), pHead));

    /* We know Tx FIFO will eventually empty */
    while( TRUE ){
        /* Get critical section, then transmit when buffer empties */
        DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar wait for CritSec %x.\r\n"),
                               &(pHWHead->TransmitCritSec)));
        DEBUGMSG (ZONE_WRITE, (TEXT("XmitComChar got CritSec %x.\r\n"),
                               &(pHWHead->TransmitCritSec)));
        EnterCriticalSection(&(pHWHead->TransmitCritSec));

        // FIFO Full ? 2002.11.28
        if( GET_SCFDR_TX_BYTES(*pHWHead->pFDR)

⌨️ 快捷键说明

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