📄 pdds3c6410_ser.cpp
字号:
//
// 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 + -