//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//
// Use of this sample source code is subject to the terms of the Microsoft
// license agreement under which you licensed this sample source code. If
// you did not accept the terms of the license agreement, you are not
// authorized to use this sample source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the LICENSE.RTF on your install media or the root of your tools installation.
// THE SAMPLE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//
//
/*++
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 2410 UART Common Code.
Notes:
--*/
#include <windows.h>
#include <types.h>
#include <ceddk.h>
#include <ddkreg.h>
#include <serhw.h>
#include <Serdbg.h>
#include <pdds3c2410_ser.h>
#include <s3c2410x_base_regs.h>
CReg2410Uart::CReg2410Uart(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_s3c2410_pclk = DEFAULT_S3C2410X_PCLK;
RETAILMSG(TRUE, (TEXT("WARNING: CReg2410Uart::CReg2410Uart failed to obtain processor frequency - using default value (%d).\r\n"), m_s3c2410_pclk));
}
else
{
m_s3c2410_pclk = procInfo.dwClockSpeed;
RETAILMSG(TRUE, (TEXT("INFO: CReg2410Uart::CReg2410Uart using processor frequency reported by the OAL (%d).\r\n"), m_s3c2410_pclk));
}
}
BOOL CReg2410Uart::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 CReg2410Uart::Backup()
{
m_fIsBackedUp = TRUE;
m_ULCONBackup = Read_ULCON();
m_UCONBackup = Read_UCON();
m_UFCONBackup = Read_UFCON();
m_UMCOMBackup = Read_UMCON();
m_UBRDIVBackup = Read_UBRDIV();
}
void CReg2410Uart::Restore()
{
if (m_fIsBackedUp) {
Write_ULCON(m_ULCONBackup );
Write_UCON( m_UCONBackup );
Write_UFCON( m_UFCONBackup );
Write_UMCON( m_UMCOMBackup );
Write_UBRDIV( m_UBRDIVBackup);
m_fIsBackedUp = FALSE;
}
}
CReg2410Uart::Write_BaudRate(ULONG BaudRate)
{
DEBUGMSG(ZONE_INIT, (TEXT("SetBaudRate -> %d\r\n"), BaudRate));
if ( (Read_UCON() & CS_MASK) == CS_PCLK ) {
Write_UBRDIV( (int)(m_s3c2410_pclk/16.0/BaudRate) -1 );
return TRUE;
}
else {
// TODO: Support external UART clock.
//OUTREG(pHWHead,UBRDIV,( (int)(S2410UCLK/16.0/BaudRate) -1 ));
RETAILMSG(TRUE, (TEXT("ERROR: The s3c2410x serial driver doesn't support an external UART clock.\r\n")));
ASSERT(FALSE);
return(FALSE);
}
}
#ifdef DEBUG
void CReg2410Uart::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
CPdd2410Uart::CPdd2410Uart (LPTSTR lpActivePath, PVOID pMdd, PHWOBJ pHwObj )
: CSerialPDD(lpActivePath,pMdd, pHwObj)
, m_ActiveReg(HKEY_LOCAL_MACHINE,lpActivePath)
, CMiniThread (0, TRUE)
{
m_pReg2410Uart = NULL;
m_pINTregs = NULL;
m_dwIntShift = 0;
m_dwIrq = 0;
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 ;
}
CPdd2410Uart::~CPdd2410Uart()
{
InitModem(FALSE);
if (m_hISTEvent) {
m_bTerminated=TRUE;
ThreadStart();
SetEvent(m_hISTEvent);
ThreadTerminated(1000);
InterruptDisable( m_dwSysIntr );
CloseHandle(m_hISTEvent);
};
if (m_pReg2410Uart)
delete m_pReg2410Uart;
if (m_XmitFlushDone)
CloseHandle(m_XmitFlushDone);
if (m_pRegVirtualAddr != NULL) {
MmUnmapIoSpace((PVOID)m_pRegVirtualAddr,0UL);
}
if (m_pINTregs!=NULL) {
MmUnmapIoSpace((PVOID)m_pINTregs,0UL);
}
}
BOOL CPdd2410Uart::Init()
{
if ( CSerialPDD::Init() && IsKeyOpened() && m_XmitFlushDone!=NULL) {
// IST Setup .
DDKISRINFO ddi;
if (GetIsrInfo(&ddi)!=ERROR_SUCCESS) {
return FALSE;
}
m_dwIrq = ddi.dwIrq;
if (m_dwIrq == 0)
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,sizeof(DWORD))) {
m_dwWaterMark = 8;
}
if (!GetRegValue(PC_REG_2410UART_INTBIT_VAL_NAME,(PBYTE)&m_dwIntShift,sizeof(DWORD))) {
RETAILMSG(1,(TEXT("Registery does not have %s set. Drivers fail!!!\r\n"),PC_REG_2410UART_INTBIT_VAL_NAME));
m_dwIntShift =0;
return FALSE;
}
if (!GetRegValue(PC_REG_2410UART_IST_TIMEOUTS_VAL_NAME,(PBYTE)&m_dwISTTimeout, PC_REG_2410UART_IST_TIMEOUTS_VAL_LEN)) {
m_dwISTTimeout = INFINITE;
}
if (!MapHardware() || !CreateHardwareAccess()) {
return FALSE;
}
return TRUE;
}
return FALSE;
}
BOOL CPdd2410Uart::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 < 0x2c)
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);
}
ioPhysicalBase.LowPart = S3C2410X_BASE_REG_PA_INTR ;
ioPhysicalBase.HighPart = 0;
inIoSpace = 0;
if (TranslateBusAddr(m_hParent,(INTERFACE_TYPE)dwi.dwInterfaceType,dwi.dwBusNumber, ioPhysicalBase,&inIoSpace,&ioPhysicalBase)) {
m_pINTregs = (S3C2410X_INTR_REG *) MmMapIoSpace(ioPhysicalBase,sizeof(S3C2410X_INTR_REG),FALSE);
}
return (m_pRegVirtualAddr!=NULL && m_pINTregs!=NULL);
}
BOOL CPdd2410Uart::CreateHardwareAccess()
{
if (m_pReg2410Uart)
return TRUE;
if (m_pRegVirtualAddr!=NULL) {
m_pReg2410Uart = new CReg2410Uart((PULONG)m_pRegVirtualAddr);
if (m_pReg2410Uart && !m_pReg2410Uart->Init()) { // FALSE.
delete m_pReg2410Uart ;
m_pReg2410Uart = NULL;
}
}
ret