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

📄 pdds3c6410_ser.cpp

📁 6410BSP3
💻 CPP
📖 第 1 页 / 共 3 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft end-user
// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
// If you did not accept the terms of the EULA, you are not authorized to use
// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
// install media.
//
//
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.

Module Name:  

Abstract:

    Serial PDD for SamSang 6410 UART Common Code.

Notes: 
--*/
#include <windows.h>
#include <types.h>
#include <ceddk.h>

#include <bsp.h>
#include <ddkreg.h>
#include <serhw.h>
#include <pdds3c6410_ser.h>
#include <s3c6410_base_regs.h>
#ifdef USE_DMA
#include <s3c6410_dma_controller.h>
#include "pdds3c6410_ser_dma.h"
#endif 

#define    EPLL_CLK    0

#ifdef USE_DMA
#define UART_DMA_MSG 		0
#define UART_TX_FIFO_LEN	16
#endif 

CReg6410Uart::CReg6410Uart(PULONG pRegAddr)
:   m_pReg(pRegAddr)
{
    m_fIsBackedUp = FALSE;
    m_ULCONBackup = NULL;
    m_UCONBackup = NULL;
    m_UFCONBackup = NULL;
    m_UMCOMBackup = NULL;
    m_UBRDIVBackup = NULL;
    m_UDIVSLOTBackup = NULL;
    m_UINTMBackup = NULL;

    m_BaudRate = NULL;
    m_s3c6410_pclk = S3C6410_PCLK;
}
BOOL   CReg6410Uart::Init() 
{
    BOOL bRet = TRUE;

    if (m_pReg)
    { // Set Value to default.
        Write_ULCON(0);
        Write_UCON(0);
        Write_UFCON(0);
        Write_UMCON(0);
        bRet = TRUE;
    }
    else
    {
        bRet = FALSE;
    }

    return bRet;
}

void CReg6410Uart::Backup()
{
#ifdef USE_DMA
	DmaPowerDown();
#endif	
    m_ULCONBackup = Read_ULCON();
    m_UCONBackup = Read_UCON();
    m_UFCONBackup = Read_UFCON();
    m_UMCOMBackup = Read_UMCON();
    m_UBRDIVBackup = Read_UBRDIV();    
    m_UDIVSLOTBackup = Read_UDIVSLOT();
    m_UINTMBackup = Read_UINTM();
    m_fIsBackedUp = TRUE;
}
void CReg6410Uart::Restore()
{
    if (m_fIsBackedUp) {
        Write_ULCON(m_ULCONBackup );
       //================================[
       // RxD FIFO Reset
        DWORD dwBit =Read_UFCON();
        // Reset RxD Fifo.
        dwBit |= (1<<1);
        dwBit &= ~(1<<0);
        Write_UFCON( dwBit);

        // Enable RxD FIFO.
        dwBit &= ~(1<<1);
        dwBit |= (1<<0);
        Write_UFCON(dwBit); // RxD Fifo Reset Done..
       //================================]
       
        Write_UFCON( m_UFCONBackup );
        Write_UMCON( m_UMCOMBackup );
        Write_UBRDIV( m_UBRDIVBackup);
        Write_UDIVSLOT( m_UDIVSLOTBackup );
	Write_UCON( m_UCONBackup );
        m_fIsBackedUp = FALSE;
#ifdef USE_DMA
	DmaPowerUp();
#endif			
    
    }
}
CReg6410Uart::Write_BaudRate(ULONG BaudRate)
{
    DOUBLE Div_val;
    UINT UDIVSLOTn = 0;
    UINT UBRDIV = 0;
    BOOL bRet = TRUE;

    DEBUGCHK(BaudRate!= NULL);

    DEBUGMSG(ZONE_INIT, (TEXT("SetBaudRate -> %d\r\n"), BaudRate));

    if ( (Read_UCON() & UART_CS_MASK) == UART_CS_PCLK )
    {
        Div_val = (m_s3c6410_pclk/16.0/BaudRate);
        UBRDIV = (int)Div_val - 1;
        Write_UBRDIV( UBRDIV );
        UDIVSLOTn = (int)( (Div_val - (int)Div_val) * 16);
        Write_UDIVSLOT( UDIVSLOT_TABLE[UDIVSLOTn] );
        RETAILMSG( FALSE , (TEXT("CLK:%d, BaudRate:%d, UBRDIV:%d, UDIVSLOTn:%d\r\n"), m_s3c6410_pclk, BaudRate, UBRDIV, UDIVSLOTn));
        bRet = TRUE;
    }
    else if( (Read_UCON() & UART_CS_MASK) == UART_CS_EPLLCLK )
    {
        Div_val = (S3C6410_ECLK/16.0/BaudRate);
        UBRDIV = (int)Div_val - 1;
        Write_UBRDIV( UBRDIV );
        UDIVSLOTn = (int)( (Div_val - (int)Div_val) * 16);
        Write_UDIVSLOT( UDIVSLOT_TABLE[UDIVSLOTn] );
        RETAILMSG( FALSE , (TEXT("CLK:%d, BaudRate:%d, UBRDIV:%d, UDIVSLOTn:%d\r\n"), S3C6410_ECLK, BaudRate, UBRDIV, UDIVSLOTn));
        bRet = TRUE;
    }
    else
    {
        RETAILMSG(TRUE, (TEXT("ERROR: The s3c6410a serial driver doesn't support an external UART clock.\r\n")));
        ASSERT(FALSE);
        bRet =FALSE;
    }

    return bRet;
}
#ifdef DEBUG
void CReg6410Uart::DumpRegister()
{
    NKDbgPrintfW(TEXT("DumpRegister (ULCON=%x, UCON=%x, UFCON=%x, UMCOM = %x, UBDIV =%x)\r\n"),
        Read_ULCON(),Read_UCON(),Read_UFCON(),Read_UMCON(),Read_UBRDIV());
}
#endif

CPdd6410Uart::CPdd6410Uart (LPTSTR lpActivePath, PVOID pMdd, PHWOBJ pHwObj )
:   CSerialPDD(lpActivePath,pMdd, pHwObj)
,   m_ActiveReg(HKEY_LOCAL_MACHINE,lpActivePath)
,   CMiniThread (0, TRUE)   
{
    m_pReg6410Uart = NULL;
    m_dwSysIntr = MAXDWORD;
    m_hISTEvent = NULL;
    m_dwDevIndex = 0;
    m_pRegVirtualAddr = NULL;
    m_XmitFlushDone =  CreateEvent(0, FALSE, FALSE, NULL);
    m_XmitFifoEnable = FALSE;
    m_dwWaterMark = NULL ;
    m_ClockSelectValid = FALSE;
    m_AutoFlowEnabled = FALSE;
    m_UseAutoFlow = FALSE;
}
CPdd6410Uart::~CPdd6410Uart()
{
    InitModem(FALSE);
    if (m_hISTEvent)
    {
        m_bTerminated=TRUE;
        ThreadStart();
        SetEvent(m_hISTEvent);
        ThreadTerminated(1000);
        InterruptDisable( m_dwSysIntr );         
        CloseHandle(m_hISTEvent);
    };
    if (m_pReg6410Uart)
    {
        delete m_pReg6410Uart;
    }
    if (m_XmitFlushDone)
    {
        CloseHandle(m_XmitFlushDone);
    }
    if (m_pRegVirtualAddr != NULL)
    {
        MmUnmapIoSpace((PVOID)m_pRegVirtualAddr,sizeof(S3C6410_UART_REG));
    }        
}
BOOL CPdd6410Uart::Init()
{
    BOOL bRet = TRUE;

    if ( CSerialPDD::Init() && IsKeyOpened() && m_XmitFlushDone!=NULL)
    { 
        // IST Setup .
        DDKISRINFO ddi;
        if (GetIsrInfo(&ddi)!=ERROR_SUCCESS)
        {
            bRet = FALSE;
            goto CleanUp;
        }
        m_dwSysIntr = ddi.dwSysintr;
        if (m_dwSysIntr !=  MAXDWORD && m_dwSysIntr!=0 )
        {
            m_hISTEvent= CreateEvent(0,FALSE,FALSE,NULL);
        }

        if (m_hISTEvent!=NULL)
        {
            InterruptInitialize(m_dwSysIntr,m_hISTEvent,0,0);
        }
        else
        {
            bRet = FALSE;
            goto CleanUp;
        }

        // Get Device Index.
        if (!GetRegValue(PC_REG_DEVINDEX_VAL_NAME, (PBYTE)&m_dwDevIndex, PC_REG_DEVINDEX_VAL_LEN))
        {
            m_dwDevIndex = 0;
        }
        if (!GetRegValue(PC_REG_SERIALWATERMARK_VAL_NAME,(PBYTE)&m_dwWaterMark,PC_REG_SERIALWATERMARKER_VAL_LEN))
        {
            m_dwWaterMark = DEFAULT_VALUE_WATER_MARK;
        }
        if (!GetRegValue(PC_REG_6410UART_IST_TIMEOUTS_VAL_NAME,(PBYTE)&m_dwISTTimeout, PC_REG_6410UART_IST_TIMEOUTS_VAL_LEN))
        {
            m_dwISTTimeout = INFINITE;
        }
        if (!GetRegValue(PC_REG_6410UART_MEM_LENGTH_VAL_NAME, (PBYTE)&m_dwMemLen, PC_REG_6410UART_MEM_LENGTH_VAL_LEN))
        {
            m_dwMemLen = DEFAULT_VALUE_MEM_LENGH;
        }
        if (!MapHardware()  || !CreateHardwareAccess())
        {
            bRet = FALSE;
            goto CleanUp;
        }
#ifdef USE_DMA
        if (!GetRegValue(PC_REG_TX_DMA_EN_NAME,(PBYTE)&m_dwTXDMAEnable, sizeof(DWORD)))
        {
            m_dwTXDMAEnable = FALSE;
        }  
	if(m_dwTXDMAEnable)
	{
      		RETAILMSG(1, (L"[UART] DMA init CH:%d \r\n", m_dwDevIndex));
		InitializeDMA(m_dwDevIndex);
	}    
#endif 
        bRet = TRUE;
        goto CleanUp;
    }
    bRet = FALSE;
CleanUp:
    return bRet;
}
BOOL CPdd6410Uart::MapHardware() 
{
    if (m_pRegVirtualAddr !=NULL)
    {
        return TRUE;
    }

    // Get IO Window From Registry
    DDKWINDOWINFO dwi;
    if ( GetWindowInfo( &dwi)!=ERROR_SUCCESS || 
    dwi.dwNumMemWindows < 1 || 
    dwi.memWindows[0].dwBase == 0 || 
    dwi.memWindows[0].dwLen < m_dwMemLen)
    {
        return FALSE;
    }

    DWORD dwInterfaceType;
    if (m_ActiveReg.IsKeyOpened() && 
    m_ActiveReg.GetRegValue( DEVLOAD_INTERFACETYPE_VALNAME, (PBYTE)&dwInterfaceType,sizeof(DWORD)))
    {
        dwi.dwInterfaceType = dwInterfaceType;
    }

    // Translate to System Address.
    PHYSICAL_ADDRESS    ioPhysicalBase = { dwi.memWindows[0].dwBase, 0};
    ULONG                inIoSpace = 0;
    if (TranslateBusAddr(m_hParent,(INTERFACE_TYPE)dwi.dwInterfaceType,dwi.dwBusNumber, ioPhysicalBase,&inIoSpace,&ioPhysicalBase))
    {
        // Map it if it is Memeory Mapped IO.
        m_pRegVirtualAddr = MmMapIoSpace(ioPhysicalBase, dwi.memWindows[0].dwLen,FALSE);
    }

    return (m_pRegVirtualAddr!=NULL );
}

BOOL CPdd6410Uart::CreateHardwareAccess()
{
    BOOL bRet = TRUE;

    if (m_pReg6410Uart)
    {
        bRet = TRUE;
        goto CleanUp;
    }
    if (m_pRegVirtualAddr!=NULL)
    {
        m_pReg6410Uart = new CReg6410Uart((PULONG)m_pRegVirtualAddr);
        if (m_pReg6410Uart && !m_pReg6410Uart->Init())
        {
            delete m_pReg6410Uart ;
            m_pReg6410Uart = NULL;
        }    
    }
    bRet = (m_pReg6410Uart!=NULL);

CleanUp:
    return bRet;
}
#define MAX_RETRY 0x1000
void CPdd6410Uart::PostInit()
{
    DWORD dwCount=0;
    m_HardwareLock.Lock();
    m_pReg6410Uart->Write_UCON(0); // Set to Default;
    DisableInterrupt(S6410UART_INT_RXD | S6410UART_INT_TXD | S6410UART_INT_ERR | S6410UART_INT_MODEM);
    // Mask all interrupt.
    while ((GetInterruptStatus() & (S6410UART_INT_RXD | S6410UART_INT_TXD | S6410UART_INT_ERR | S6410UART_INT_MODEM))!=0 && dwCount <MAX_RETRY)
    {
        InitReceive(TRUE);
        InitLine(TRUE);
        ClearInterrupt(S6410UART_INT_RXD | S6410UART_INT_TXD | S6410UART_INT_ERR | S6410UART_INT_MODEM);
        dwCount++;
    } 
    ASSERT((GetInterruptStatus() & (S6410UART_INT_RXD | S6410UART_INT_TXD | S6410UART_INT_ERR | S6410UART_INT_MODEM))==0);
    m_HardwareLock.Unlock();
    CSerialPDD::PostInit();
    CeSetPriority(m_dwPriority256);
#ifdef DEBUG
    if ( ZONE_INIT )
    {
        m_pReg6410Uart->DumpRegister();
    }
#endif
    ThreadStart();  // Start IST.
}
DWORD CPdd6410Uart::ThreadRun()
{
    DWORD dwData;
    DWORD interrupts;
    
    while ( m_hISTEvent!=NULL && !IsTerminated() )
    {
        if ( WaitForSingleObject( m_hISTEvent, m_dwISTTimeout) == WAIT_OBJECT_0)
        {
            m_HardwareLock.Lock();    
        
            while ( !IsTerminated() )
            {
                dwData = ( GetInterruptStatus() & (S6410UART_INT_RXD | S6410UART_INT_TXD | S6410UART_INT_ERR | S6410UART_INT_MODEM) );
                if (dwData)
                {
                    DEBUGMSG(ZONE_THREAD, (TEXT(" CPdd6410Uart::ThreadRun Active INT=%x\r\n"), dwData));

                    // Clear the interrupt value to notify to MDD
                    interrupts=NULL;
                    DEBUGCHK(interrupts==NULL);

                    if ((dwData & S6410UART_INT_RXD)!=0)
                    {
                        interrupts |= INTR_RX;
                    }
                    if ((dwData & S6410UART_INT_TXD)!=0)
                    {
                        interrupts |= INTR_TX;

⌨️ 快捷键说明

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