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

📄 scif_cmn.c

📁 WinCE5.0BSP for Renesas SH7770
💻 C
📖 第 1 页 / 共 3 页
字号:
//
//  Copyright(C) Renesas Technology Corp. 1999-2004. All rights reserved.
//
//  Serial driver for ITS-DS7
//
//  FILE      : scif_cmn.c
//  CREATED   : 2002.06.26
//  MODIFIED  : 2004.09.01
//  AUTHOR    : Renesas Technology Corp.
//  HARDWARE  : RENESAS ITS-DS7
//  HISTORY   : 
//              2003.06.20
//              - Created release code.
//                (based on Serial driver for ITS-DS4 Source Kit Ver.1.2.0 for WCE 4.2)
//              2004.01.23
//              - Modified specification changed DDASR for 2nd cut. use DTCSR.
//              2004.02.02
//              - Changed for corresponding to COM_MDD2.
//              - Bug fixed. (fail,etc in CETK)
//              2004.03.02
//              - Revised Check and clear Receive Error Bit of Serial Status Register.
//              2004.09.01
//              - Created release code for WCE5.0.
//

#include <windows.h>
#include <types.h>
#include <memory.h>
#include <serhw.h>
#include <excpt.h>
#include <serdbg.h>

#include "platform.h"
#include "sh7770.h"
#include "..\inc\scif.h"
#include "oalintr.h"

#include "drv_glob.h"

extern const HW_VTBL SCIF0IoVTbl;
extern const HW_VTBL SCIF3IoVTbl;

#define EXCEPTION_ACCESS_VIOLATION STATUS_ACCESS_VIOLATION 

#define BAUD_TABLE_SIZE	19

static const
PAIRS	SCIF_BaudPairs[BAUD_TABLE_SIZE] = {
    {110,    2095},
    {300,    768},
    {600,    384},
    {1200,   192},
    {2400,   96},
    {4800,   48},
    {9600,   24},
    {14400,  16},
    {19200,  12},
    {38400,  6},
    {57600,  4},
    {115200, 2}};
static const
LOOKUP_TBL  SCIF_BaudTable = {BAUD_TABLE_SIZE, (PAIRS *) SCIF_BaudPairs};
// Miscellaneous internal routines.
PUCHAR

Ser_InternalMapRegisterAddresses(
    ULONG   HWAddress,
    ULONG   Size
    )
{
	PUCHAR	ioPortBase; 

    DEBUGMSG(ZONE_FUNCTION, 
             (TEXT("+Ser_InternalMapRegisterAddresses: adr=0x%x len=0x%x\r\n"),
			 HWAddress, Size));

	ioPortBase = VirtualAlloc(0, Size, MEM_RESERVE, PAGE_NOACCESS);
	if ( ioPortBase == NULL )
	{
		ERRORMSG(1, (TEXT("Ser_InternalMapRegisterAddresses: VirtualAlloc failed!\r\n")));
	}
	else if ( !VirtualCopy((PVOID)ioPortBase, (PVOID)HWAddress, Size, PAGE_READWRITE|PAGE_NOCACHE) )
	{
		ERRORMSG(1, (TEXT("Ser_InternalMapRegisterAddresses: VirtualCopy failed!\r\n")));
		VirtualFree( (PVOID)ioPortBase, 0, MEM_RELEASE );
		ioPortBase = 0;
	}

    DEBUGMSG(ZONE_FUNCTION, 
             (TEXT("-Ser_InternalMapRegisterAddresses: mapped at 0x%x\r\n"),
              ioPortBase ));

    return ioPortBase;
}


static
BOOL
SerSetIRBaudRate(
                PSCIF_INFO   pHWHead,
                ULONG baud     // @parm     UINT16 what is the baud rate
                )
{
    DEBUGMSG (ZONE_INIT, (TEXT("Serial set IR Baud %d\r\n"),
                          baud));

    // We don't support IR
    return (FALSE);
}


//
// Helper routine to search through a lookup table for a designated
// key.
//
ULONG
SCIF_LookUpValue(
    ULONG	Key,
    PLOOKUP_TBL pTbl,
    PULONG	pErrorCode
    )
{
    ULONG   index = 0;

    *pErrorCode = 0;

    while ( index < pTbl->Size )
	{
        if ( Key == pTbl->Table[index].Key )
            return pTbl->Table[index].AssociatedValue;

        ++index;
	}

    *pErrorCode = (ULONG)-1;

    return 0;
}

//
// Helper function.  Pass in a baudrate, and the corresponding divisor
// (from the baudtable) is returned.  If no matching baudrate is found
// in baudtable, then return 0.
//
USHORT
SCIF_DivisorOfRate(
    PVOID   pHead,      // @parm PVOID returned by HWinit.
    ULONG   BaudRate	// @parm     ULONG representing decimal baud rate.    
    )
{
    ULONG   errorcode = 0;
    USHORT  divisor;

//    divisor = (USHORT)LookUpValue(BaudRate, ((PSCIF_INFO) pHead)->pBaudTable, &errorcode);
    divisor = (USHORT)SCIF_LookUpValue(BaudRate, (PLOOKUP_TBL)&SCIF_BaudTable, &errorcode);

    if ( errorcode )
        divisor = 0;

    return divisor;
}

//
// This function is a derivative of the ReadLSR function
// from the 16550 driver. Everytime that we need to
// check the status of the connection (errors, etc) we
// do it by calling this function. It reads the register
// and reports any errors to the MDD. That is convenient.
//
USHORT
ReadStatus(
    PVOID  pHead
    )
{
    PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;
    ULONG LineEvents = 0;
    USHORT	FSR;
    USHORT	LSR;
    int		i,j;
    USHORT	SCFDR;
    
    try
    {
        FSR = READ_REGISTER_USHORT(pHWHead -> pFSR);
        LSR = READ_REGISTER_USHORT(pHWHead -> pLSR);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        FSR = 0;
    }
    if ( (FSR & (SCIF_SSR_PER | SCIF_SSR_FER | SCIF_SSR_BRK)) ||
         (LSR & SCIF_LSR_ORER) || (FSR & SCIF_SSR_ER) ){

		if ( FSR & SCIF_SSR_ER )
			pHWHead -> CommErrors |= CE_FRAME|CE_RXPARITY;

        if ( FSR & SCIF_SSR_PER )
            pHWHead -> CommErrors |= CE_RXPARITY;

        if ( FSR & SCIF_SSR_FER )
            pHWHead -> CommErrors |= CE_FRAME;

        if ( LSR & SCIF_LSR_ORER ){
            pHWHead -> CommErrors |= CE_OVERRUN;
            pHWHead -> DroppedBytes ++;
        }

        if ( LSR & SCIF_SSR_BRK )
            LineEvents |= EV_BREAK;

        LineEvents |= EV_ERR;

	    try
	    {
	        if ( FSR & SCIF_SSR_BRK ){
	            WRITE_REGISTER_USHORT(pHWHead -> pFSR, FSR & ~SCIF_SSR_BRK);
	        }
			if ( LSR & SCIF_LSR_ORER ){
				// receive FIFO clear
				SCFDR = READ_REGISTER_USHORT(pHWHead -> pFDR);
				j  = (SCFDR & 0x001f);
				//pHWHead -> DroppedBytes += j;
				DEBUGMSG (ZONE_THREAD,(TEXT("find overrun : receive FIFO clear %d\r\n"), j));
				for( i = 0; i < j; i++ )
					READ_REGISTER_UCHAR(pHWHead -> pFRDR);
				WRITE_REGISTER_USHORT(pHWHead -> pLSR, LSR & ~SCIF_LSR_ORER);
			}
			if ( FSR & SCIF_SSR_ER ){
				WRITE_REGISTER_USHORT(pHWHead -> pFSR, FSR & ~SCIF_SSR_ER);
			}

			// Check Error
	        if ( FSR & (SCIF_SSR_ER | SCIF_SSR_PER | SCIF_SSR_FER | SCIF_SSR_BRK) ){
				// Error Process
	        	if( FSR ){
	        		j  = ((FSR & 0xf000) >> 12);
	        		j |= ((FSR & 0x0f00) >>  8);
	        	}
	        	else{
	        		j = 16;
	        	}
				for( i = 0; i < j; i++ )
	                READ_REGISTER_UCHAR(pHWHead -> pFRDR);

	            WRITE_REGISTER_USHORT(pHWHead->pFSR, FSR & ~(SCIF_SSR_ER | SCIF_SSR_PER | SCIF_SSR_FER | SCIF_SSR_BRK));
	        }
		}
		except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
				    EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
		}
	}
	// Let WaitCommEvent know about this error
	if ( LineEvents )
		EvaluateEventFlag( pHWHead -> pMddHead, LineEvents );
//        pHWHead -> EventCallback( pHWHead -> pMddHead, LineEvents );
    return FSR;
}

//
// This function checks the status of all of the modem
// signals : CTS, RTS.
//
USHORT
ReadModemStatus(
    PVOID  pHead
    )
{
    PSCIF_INFO  pHWHead = (PSCIF_INFO)pHead;
    ULONG       Events = 0;
    USHORT      MSR;
    
    try
    {
        MSR = READ_REGISTER_USHORT(pHWHead -> pSPTR);
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        MSR = 0;
    }

    if( (pHWHead->SPTR & SCIF_SPTR_CTS) != (MSR & SCIF_SPTR_CTS) ){

        // For changes, we use callback to evaluate the event
        if ( !(MSR & SCIF_SPTR_CTS) ){
            Events |= EV_CTS;
            pHWHead->ModemStatus &= ~MS_CTS_ON;
            pHWHead->ModemStatus &= ~MS_RLSD_ON;
        }
        else{
            pHWHead->ModemStatus |= MS_CTS_ON;
            pHWHead->ModemStatus |= MS_RLSD_ON;
            Events |= EV_RLSD;
        }
    }

    if( Events )
        EvaluateEventFlag( pHWHead -> pMddHead, Events );

//        pHWHead->EventCallback( pHWHead->pMddHead, Events );
	pHWHead->SPTR = MSR;

    return MSR;
}


#define IER_NORMAL_INTS (SCIF_SCR_RIE | SCIF_SCR_REIE)

//
/////////////////// Start of exported entrypoints ////////////////
//


//
// @doc OEM 
// @func ULONG | SCIF_Close | Does nothing except keep track of the
// open count so that other routines know what to do.
//
ULONG
SCIF_Close(
    PVOID   pHead // @parm PVOID returned by HWinit.
    )
{
    PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;

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

    if( pHWHead->OpenCount )
        pHWHead->OpenCount--;
    if ( !pHWHead -> OpenCount ){
        try
        {
			while( !(READ_REGISTER_USHORT(pHWHead -> pFSR) & SCIF_SSR_TEND) );
			while(  (READ_REGISTER_USHORT(pHWHead -> pFSR) & SCIF_SSR_RDF) );

			// Disable all interrupts and clear MCR.
            WRITE_REGISTER_USHORT(pHWHead -> pSCR, READ_REGISTER_USHORT(pHWHead -> pSCR) &
                ~(SCIF_SCR_TIE|SCIF_SCR_RIE|SCIF_SCR_REIE|SCIF_SCR_TE|SCIF_SCR_RE) );
            WRITE_REGISTER_USHORT(pHWHead -> pFCR, SCIF_FCR_TFRST | SCIF_FCR_RFRST);
        }
        except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
                EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
            // Just get out of here.
        }
    }
	dma_InterruptDisable(pHWHead -> pRxDma);
	dma_InterruptDisable(pHWHead -> pTxDma);
    dma_Stop(pHWHead -> pRxDma);
    dma_Stop(pHWHead -> pTxDma);

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


/*
 @doc OEM 
 @func PVOID | SerPostInit | Performs final hardware initialization.
 *
 */
BOOL
SCIF_PostInit(
         PVOID   pHead   // @parm PVOID returned by SerInit.
         )
{
    PSCIF_INFO   pHWHead = (PSCIF_INFO)pHead;

    DEBUGMSG (ZONE_INIT,(TEXT("+SerPostInit, 0x%X\r\n"), pHWHead));
    
    // Since we are just a library which might get used for 
    // builtin ports which init at boot, or by PCMCIA ports
    // which init at Open, we can't do anything too fancy.
    // Lets just make sure we cancel any pending interrupts so
    // that if we are being used with an edge triggered PIC, he
    // will see an edge after the MDD hooks the interrupt.
//    ClearPendingInts( pHWHead );
    ReadModemStatus( pHWHead );

    DEBUGMSG (ZONE_INIT,(TEXT("-SerPostInit, 0x%X\r\n"), pHWHead));

    return TRUE;
}


// Routine to clear any pending interrupts.  Called from Init and PostInit
// to make sure we atart out in a known state.
/*
VOID
ClearPendingInts(
       PSCIF_INFO   pHead // @parm PVOID returned by HWinit.
       )
{
    PSCIF_INFO pHWHead = (PSCIF_INFO)pHead;


    EnterCriticalSection(&(pHWHead->RegCritSec));

    try {
    	// Clear Interrupt
    }
    except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
            EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
        DEBUGMSG (ZONE_ERROR,(TEXT("-SerPostInit, 0x%X - ERROR\r\n"), pHWHead));
        // Just fall through & release CritSec
    }

    LeaveCriticalSection(&(pHWHead->RegCritSec));
}
*/


/*
 *  NOTE : The caller should have set pHWHead->fIRMode.  It is not
 * set here, since power on/off may need to temporarily disable
 * the intefaces without actually overwriting the current recorded
 * mode.
 */
static
void
SerSetOutputMode(
                PSCIF_INFO   pHWHead,
                BOOL UseIR,     // @parm     BOOL Should we use IR interface
                BOOL Use9Pin    // @parm     BOOL Should we use Wire interface
                )
{
    // If you support IR, here you need to set the interface to either IR mode
    // or normal serial. Note that it is possible for both BOOls to
    // be false (i.e. power down), but never for both to be TRUE.
}


/*++
*******************************************************************************
Routine:

    Ser_GetRegistryData

Description:

    Take the registry path provided to COM_Init and use it to find this 
    requested comm port's DeviceArrayIndex, the IOPort Base Address, and the
    Interrupt number.
   
Arguments:

    LPCTSTR regKeyPath	the registry path passed in to COM_Init.

Return Value:

    -1 if there is an error.

*******************************************************************************
--*/
BOOL
Ser_GetRegistryData(PSCIF_INFO pHWHead, LPCTSTR regKeyPath)
{
#define GCI_BUFFER_SIZE 256   

    LONG    regError;
    HKEY    hKey;

    DEBUGMSG(ZONE_INIT, (TEXT("Try to open %s\r\n"), regKeyPath));

    // We've been handed the name of a key in the registry that was generated
    // on the fly by device.exe.  We're going to open that key and pull from it
    // a value that is the name of this serial port's real key.  That key
    // will have the DeviceArrayIndex that we're trying to find.  

    regError = RegOpenKeyEx(
                           HKEY_LOCAL_MACHINE, 
                           regKeyPath,
                           0, 
                           KEY_ALL_ACCESS, 
                           &hKey);
    if ( regError != ERROR_SUCCESS ) {
        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
                 (TEXT("Failed to open %s, Error 0x%X\r\n"), regKeyPath, regError));
        return ( FALSE );                

⌨️ 快捷键说明

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