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

📄 pdds3c6410_ser.cpp

📁 SAMSUNG S3C6410 CPU BSP for winmobile6
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// 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 <Serdbg.h>
#include <pdds3c6410_ser.h>
#include <s3c6410_base_regs.h>

#define	EPLL_CLK	0

CReg6410Uart::CReg6410Uart(PULONG pRegAddr)
:   m_pReg(pRegAddr)
{
	m_fIsBackedUp = FALSE;
	//PROCESSOR_INFO procInfo;
	//DWORD dwBytesReturned;
	//if (!KernelIoControl(IOCTL_PROCESSOR_INFORMATION, NULL, 0, &procInfo, sizeof(PROCESSOR_INFO), &dwBytesReturned))
	//{
	m_s3c6410_pclk = S3C6410_PCLK;//DEFAULT_S3C6410_PCLK; 
	//RETAILMSG(TRUE, (TEXT("WARNING: CReg6410Uart::CReg6410Uart failed to obtain processor frequency - using default value (%d).\r\n"), m_s3c6410_pclk)); 
	//}
	//else
	//{
	//m_s3c6410_pclk = procInfo.dwClockSpeed;
	//RETAILMSG(TRUE, (TEXT("INFO: CReg6410Uart::CReg6410Uart using processor frequency reported by the OAL (%d).\r\n"), m_s3c6410_pclk)); 
	//}
}
BOOL   CReg6410Uart::Init() 
{
	if (m_pReg)
	{ // Set Value to default.
		Write_ULCON(0);
		Write_UCON(0);
		Write_UFCON(0);
		Write_UMCON(0);
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

void CReg6410Uart::Backup()
{
	m_fIsBackedUp = TRUE;
	m_ULCONBackup = Read_ULCON();
	m_UCONBackup = Read_UCON();
	m_UFCONBackup = Read_UFCON();
	m_UMCOMBackup = Read_UMCON();
	m_UBRDIVBackup = Read_UBRDIV();    
	m_UDIVSLOTBackup = Read_UDIVSLOT();
}
void CReg6410Uart::Restore()
{
	if (m_fIsBackedUp)
	{
		Write_ULCON(m_ULCONBackup );
		Write_UCON( m_UCONBackup );
		Write_UFCON( m_UFCONBackup );
		Write_UMCON( m_UMCOMBackup );
		Write_UBRDIV( m_UBRDIVBackup);
		Write_UDIVSLOT( m_UDIVSLOTBackup );
		m_fIsBackedUp = FALSE;
	}
}
CReg6410Uart::Write_BaudRate(ULONG BaudRate)
{
	DOUBLE Div_val;
	UINT UDIVSLOTn = 0;
	UINT UBRDIV = 0;
	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( TRUE , (TEXT("CLK:%d, BaudRate:%d, UBRDIV:%d, UDIVSLOTn:%d\r\n"), m_s3c6410_pclk, BaudRate, UBRDIV, UDIVSLOTn));
		return 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( TRUE , (TEXT("CLK:%d, BaudRate:%d, UBRDIV:%d, UDIVSLOTn:%d\r\n"), S3C6410_ECLK, BaudRate, UBRDIV, UDIVSLOTn));
		return TRUE;
	}
	else
	{
		// TODO: Support external UART clock.
		//RETAILMSG(TRUE, (TEXT("ERROR: The s3c6410a serial driver doesn't support an external UART clock.\r\n")));
		ASSERT(FALSE);
		return(FALSE);
	}
}
#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 = 8 ;
}
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,0UL);
	}        
}
BOOL CPdd6410Uart::Init()
{
	if ( CSerialPDD::Init() && IsKeyOpened() && m_XmitFlushDone!=NULL)
	{ 
		// IST Setup .
		DDKISRINFO ddi;
		if (GetIsrInfo(&ddi)!=ERROR_SUCCESS)
		{
			return FALSE;
		}
		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
		{
			return FALSE;
		}

		// 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 = 8;
		}
		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 = 0x40;
		}
		if (!MapHardware()  || !CreateHardwareAccess())
		{
			return FALSE;
		}

		return TRUE;        
	}
	return FALSE;
}
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()
{	
	if (m_pReg6410Uart)
	{
		return TRUE;
	}
	if (m_pRegVirtualAddr!=NULL)
	{
		m_pReg6410Uart = new CReg6410Uart((PULONG)m_pRegVirtualAddr);
		if (m_pReg6410Uart && !m_pReg6410Uart->Init())
		{ // FALSE.
			delete m_pReg6410Uart ;
			m_pReg6410Uart = NULL;
		}    
	}
	return (m_pReg6410Uart!=NULL);
}
#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)
	{ // Interrupt.
		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);
	// IST Start to Run.
	m_HardwareLock.Unlock();
	CSerialPDD::PostInit();
	CeSetPriority(m_dwPriority256);
#ifdef DEBUG
	if ( ZONE_INIT )
	{
		m_pReg6410Uart->DumpRegister();
	}
#endif
	ThreadStart();  // Start IST.
}
DWORD CPdd6410Uart::ThreadRun()
{
	while ( m_hISTEvent!=NULL && !IsTerminated() )
	{
		if ( WaitForSingleObject( m_hISTEvent, m_dwISTTimeout) == WAIT_OBJECT_0)
		{
			m_HardwareLock.Lock();    
		
			while ( !IsTerminated() )
			{
				DWORD 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));

					DWORD interrupts=NULL;

					if ((dwData & S6410UART_INT_RXD)!=0)
					{
						interrupts |= INTR_RX;
					}
					if ((dwData & S6410UART_INT_TXD)!=0)
					{
						interrupts |= INTR_TX;
					}
					if ((dwData & S6410UART_INT_ERR)!=0)
					{
						interrupts |= INTR_LINE | INTR_RX;
					}
					if ((dwData & S6410UART_INT_MODEM)!=0)
					{
						interrupts |=INTR_MODEM;
					}
					
					NotifyPDDInterrupt( (INTERRUPT_TYPE)interrupts );
					
					ClearInterrupt(dwData);
				}
				else
				{
					break;
				}
			}

			m_HardwareLock.Unlock();   

			InterruptDone(m_dwSysIntr);
		}
		else
		{
			DEBUGMSG(ZONE_THREAD,(TEXT(" CPdd6410Uart::ThreadRun timeout INT=%x,MASK=%d\r\n"),m_pReg6410Uart->Read_UINTP()/*m_pReg6410Uart->Read_UINTSP()*/, m_pReg6410Uart->Read_UINTM()) );
			ASSERT(FALSE);
		}
	}

	return 1;
}
BOOL CPdd6410Uart::InitialEnableInterrupt(BOOL bEnable )
{
	m_HardwareLock.Lock();
	if (bEnable)
	{
		EnableInterrupt(S6410UART_INT_RXD | S6410UART_INT_ERR | S6410UART_INT_MODEM);
	}
	else
	{
		DisableInterrupt(S6410UART_INT_RXD | S6410UART_INT_ERR | S6410UART_INT_MODEM);
	}
	m_HardwareLock.Unlock();
	return TRUE;
}

BOOL  CPdd6410Uart::InitXmit(BOOL bInit)
{
	if (bInit)
	{ 
		m_HardwareLock.Lock();    
		DWORD dwBit = m_pReg6410Uart->Read_UCON();
#if EPLL_CLK
		// Set UART CLK.
		dwBit &= ~(UART_CS_MASK);
		dwBit |= (UART_CS_EPLLCLK);
#endif
		// Set Tx Inerrupt Request Type, Tx Interrupt/Polling Mode.
		dwBit &= ~(UART_TX_INT_TYPE_MASK|UART_TX_MODE_MASK);
		dwBit |= (UART_TX_INT_TYPE_LEVEL|UART_TX_INT_POLL);
		m_pReg6410Uart->Write_UCON(dwBit );

		dwBit = m_pReg6410Uart->Read_UFCON();
		// Reset Xmit Fifo.
		dwBit |= (UART_FCR_TX_FIFO_RESET);
		dwBit &= ~(UART_FCR_FIFO_ENABLE);
		m_pReg6410Uart->Write_UFCON( dwBit);
		// Set Trigger level to 16. 
		dwBit &= ~(UART_FCR_TX_FIFO_TRIG_MASK);
		dwBit |= (UART_FCR_TX_FIFO_TRIG_16);//16
		m_pReg6410Uart->Write_UFCON(dwBit); 
		// Enable Xmit FIFO.
		dwBit &= ~(UART_FCR_TX_FIFO_RESET);
		dwBit |= (UART_FCR_FIFO_ENABLE);
		m_pReg6410Uart->Write_UFCON(dwBit); // Xmit Fifo Reset Done..
		m_HardwareLock.Unlock();
	}
	else 
	{ // Make Sure data has been trasmit out.
		// We have to make sure the xmit is complete because MDD will shut donw the device after this return
		DWORD dwTicks = 0;
		DWORD dwUTRState;
		while (dwTicks < 1000 && ((dwUTRState = m_pReg6410Uart->Read_UTRSTAT()) & (UART_TRANSMITTER_STATUS_MASK | UART_TX_BUFFER_STATUS_MASK))
			!= (UART_TRANSMITTER_EMPTY | UART_TX_BUFFER_EMPTY))
		{ // Transmitter empty is not true
			DEBUGMSG(ZONE_THREAD|ZONE_WRITE, (TEXT("CPdd6410Uart::InitXmit! Wait for UTRSTAT=%x clear.\r\n"), dwUTRState));
			Sleep(5);
			dwTicks +=5;
		}
	}
	return TRUE;
}
DWORD   CPdd6410Uart::GetWriteableSize()
{
	DWORD dwWriteSize = 0;
	DWORD dwUfState = m_pReg6410Uart->Read_UFSTAT() ;
	if ((dwUfState & UART_FSR_TX_FIFO_MASK)==UART_FSR_TX_FIFO_NOT_FULL)
	{ // It is not full.
		dwUfState = ((dwUfState & UART_FSR_TX_FIFO_COUNT_MASK) >> UART_FSR_TX_FIFO_COUNT_SHFIT); // It is fifo count.
		if (dwUfState < S3C6410_UART_FIFO_DEPTH-1)
		{
			dwWriteSize = S3C6410_UART_FIFO_DEPTH-1 - dwUfState;
		}
	}
	return dwWriteSize;
}
void    CPdd6410Uart::XmitInterruptHandler(PUCHAR pTxBuffer, ULONG *pBuffLen)
{
	PREFAST_DEBUGCHK(pBuffLen!=NULL);
	m_HardwareLock.Lock();    
	if (*pBuffLen == 0)
	{ 

⌨️ 快捷键说明

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