//
// 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: ser_device_port.cpp 

Abstract:

Serial PDD for SamSung Development Board.

Notes: 
--*/

#include <windows.h>
#include <types.h>
#include <ceddk.h>
#include <ddkreg.h>
#include <serhw.h>
#include <Serdbg.h>
#include <bsp.h>
#include <common_pdd_ser.h>
#include <register_map.h>
#include <sgip_GPIO.h>
#include <sgip_GPIO_register_map.h>
#include <syscon_reg.h>
#include <pm.h>
#include "CSerPdd.h"
#include <PmPlatform.h>

//UART0
class CPddSerial0 : public CPddUart
{
    public:
        CPddSerial0(LPTSTR lpActivePath, PVOID pMdd, PHWOBJ pHwObj)
            : CPddUart(lpActivePath, pMdd, pHwObj)
        {
                m_pIOPregs = NULL;
                m_pSysconRegs = NULL;
                m_fIsDSRSet = FALSE;
        }
        ~CPddSerial0()
        {
                if(m_pSysconRegs)
                {
                                //            m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 &= CLK_UART0_MASK;
                                DWORD dwIPIndex ;
                                DWORD dwBytes;   

                                dwIPIndex = CLK_IP3_UART0;
                                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                                {
                                        ERRMSG((_T("[UART0:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                                }

                        m_pSysconRegs->CLK_SRC.CLK_SRC_MASK0 &= CLK_SRC_MASK0_UART0_DISABLE;            
                        m_pSysconRegs->CLK_SRC.CLK_SRC4      &= (CLK_SCLKMPLL << CLK_UART0_SEL);            						
                        m_pSysconRegs->CLK_DIV.CLK_DIV4      &= ~(0xF << CLK_UART0_SEL);	//DIV set to zero.						
                }
                if (m_pIOPregs != NULL)
                {
                        MmUnmapIoSpace((LPVOID)m_pIOPregs, sizeof(GPIO_REG));
                }
                if (m_pSysconRegs != NULL)
                {
                        MmUnmapIoSpace((LPVOID)m_pSysconRegs, sizeof(CMU_CLK_REG));
                }

                        if (m_hPwrMsgQue != NULL)
                        {
                                CloseMsgQueue(m_hPwrMsgQue);
                        }

        }
        virtual BOOL Init()
        {
                        MSGQUEUEOPTIONS msgOptions;
                PHYSICAL_ADDRESS    ioPhysicalBase = {0,0};

                ioPhysicalBase.LowPart = BASE_REG_PA_CMU_CLK;
                ioPhysicalBase.HighPart = 0;

                        m_hPwrControl = CreateFile( L"PWC0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                        if (INVALID_HANDLE_VALUE == m_hPwrControl )
                        {
                                ERRMSG((_T("[UART0:ERR] ++%s(): PWC0 Open Device Failed!\r\n"), _T(__FUNCTION__)));
                                return FALSE;
                        }

                        memset((void *)&msgOptions, 0x0, sizeof(msgOptions));
                        msgOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
                        msgOptions.dwFlags = 0;
                        msgOptions.dwMaxMessages = 1024;        // Max number of MSG queue entries
                        msgOptions.cbMaxMessage = sizeof(MSG_DEV_STATE);
                        msgOptions.bReadAccess = FALSE;
                        m_hPwrMsgQue = CreateMsgQueue(OEMPM_MSGQ_NAME, &msgOptions);


                m_pSysconRegs = (volatile CMU_CLK_REG *) MmMapIoSpace(ioPhysicalBase,sizeof(CMU_CLK_REG),FALSE);

                if(m_pSysconRegs)
                {
                                //            m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 |= CLK_UART0_PASS;
                                DWORD dwIPIndex ;
                                DWORD dwBytes;   

                                dwIPIndex = CLK_IP3_UART0;
                                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                                {
                                        ERRMSG((_T("[UART:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                                }

                        m_pSysconRegs->CLK_SRC.CLK_SRC4      |= (0x6 << CLK_UART0_SEL);		//SCLKMPLL				
                        m_pSysconRegs->CLK_DIV.CLK_DIV4      &= ~(0xF << CLK_UART0_SEL);	//DIV set to zero.
                        m_pSysconRegs->CLK_DIV.CLK_DIV4      |= (0x4  << CLK_UART0_SEL);	
                        m_pSysconRegs->CLK_SRC.CLK_SRC_MASK0 |= CLK_SRC_MASK0_UART0_ENABLE;
                }
                else
                {
                        return FALSE;
                }

                ioPhysicalBase.LowPart = BASE_REG_PA_GPIO;
                ioPhysicalBase.HighPart = 0;
                m_pIOPregs = (volatile GPIO_REG *) MmMapIoSpace(ioPhysicalBase, sizeof(GPIO_REG),FALSE);

                if (m_pIOPregs)
                {
                        DDKISRINFO ddi;
                        if (GetIsrInfo( &ddi) ==  ERROR_SUCCESS && 
                                KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &ddi.dwIrq, sizeof(UINT32), &ddi.dwSysintr, sizeof(UINT32), NULL))
                        {   
                                        DBGMSG(UART_INFO,(TEXT("[UART0] Serial0 SYSINTR : %d\r\n"), *((PBYTE) &ddi.dwSysintr))); 
                                RegSetValueEx(DEVLOAD_SYSINTR_VALNAME,REG_DWORD,(PBYTE) &ddi.dwSysintr, sizeof(UINT32));
                        }
                        else
                        {
                                return FALSE;
                        }

                        Set_PinFunction(m_pIOPregs, UART0_RXD);
                        Set_PinFunction(m_pIOPregs, UART0_TXD);
                        Set_PinPullUD(m_pIOPregs, UART0_RXD, sgip_PULL_DOWN);
                        Set_PinPullUD(m_pIOPregs, UART0_TXD, sgip_PULL_DISABLE);  
                        Set_PinDrv(m_pIOPregs, UART0_TXD, sgip_DRV_4x);
                        Set_PinDrv(m_pIOPregs, UART0_RXD, sgip_DRV_4x);

                        Set_PinFunction(m_pIOPregs, UART0_CTSn);
                        Set_PinFunction(m_pIOPregs, UART0_RTSn);
                        Set_PinPullUD(m_pIOPregs, UART0_CTSn, sgip_PULL_DISABLE);
                        Set_PinPullUD(m_pIOPregs, UART0_RTSn, sgip_PULL_DISABLE);  
                        Set_PinDrv(m_pIOPregs, UART0_CTSn, sgip_DRV_4x);
                        Set_PinDrv(m_pIOPregs, UART0_RTSn, sgip_DRV_4x);

                        Set_PinFunction(m_pIOPregs, GPD01_Output);
                        Set_PinFunction(m_pIOPregs, GPD02_Input);
                        Set_PinPullUD(m_pIOPregs, GPD01_Output, sgip_PULL_DISABLE);
                        Set_PinPullUD(m_pIOPregs, GPD02_Input, sgip_PULL_DISABLE); 
                        Set_PinDrv(m_pIOPregs, GPD01_Output, sgip_DRV_4x);
                        Set_PinDrv(m_pIOPregs, GPD02_Input, sgip_DRV_4x);

                        return CPddUart::Init();
                }
                return FALSE;
        }

        virtual BOOL    PowerOff()
        {
                        DWORD dwIPIndex ;
                        DWORD dwBytes;   

                SetDTR(FALSE);
                CSerialPDD::PowerOff();

                        dwIPIndex = CLK_IP3_UART0;
                        if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                        {
                                ERRMSG((_T("[UART0:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                        }
#if 0       
                if(m_pSysconRegs)
                {
                        m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 &= CLK_UART0_MASK; 
                }
#endif      
                return TRUE;
        }

        virtual BOOL    PowerOn()
        {
                        DWORD dwIPIndex ;
                        DWORD dwBytes;   

                        dwIPIndex = CLK_IP3_UART0;
                        if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                        {
                                ERRMSG((_T("[UART0:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                        }

#if 0   
                if(m_pSysconRegs)
                {
                        m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 |= CLK_UART0_PASS;
                }
#endif

                CSerialPDD::PowerOn();
                SetDTR(TRUE);
                return TRUE;
        }

#ifdef UART_MODEM
        virtual BOOL    InitModem(BOOL bInit)
        {
                SetDTR(bInit);
                return CPddUart::InitModem(bInit);
        }
#endif 

        virtual ULONG   GetModemStatus()
        {
                ULONG ulReturn = CPddUart::GetModemStatus();
                ULONG ulEvent = 0;
                m_HardwareLock.Lock();
                BOOL fIsDSRSet = (Get_PinData(m_pIOPregs, GPD02_Input) ==  0);

                if (fIsDSRSet != m_fIsDSRSet)
                {
                        ulEvent |= EV_DSR | EV_RLSD;
                }
                ulReturn |= (fIsDSRSet?(MS_DSR_ON |MS_RLSD_ON):0);
                m_fIsDSRSet = fIsDSRSet;
                m_HardwareLock.Unlock();
                if (ulEvent != 0)
                {
                        EventCallback(ulEvent,ulReturn);
                }
                return ulReturn;
        }

        virtual void    SetDTR(BOOL bSet)
        {
                        DBGMSG(UART_INFO, (TEXT("[UART0] [SetDTR] DTRPort Reg 0x%x, DTRSet?(%d).\r\n"), m_pDTRPort, bSet)); 
                if (bSet)
                {
                        Set_PinData(m_pIOPregs, GPD01_Output, FALSE);	
                                DBGMSG(UART_INFO, (TEXT("[UART0] [SetDTR] DTRSet Bit= (%d).\r\n"), (Get_PinData(m_pIOPregs, GPD01_Output) ) )); 
                }
                else
                {
                        Set_PinData(m_pIOPregs, GPD01_Output, TRUE);	
                }
        }

        virtual void    SetDefaultConfiguration()
        {
                // Default Value. Can be altered.
                m_CommPorp.wPacketLength       = 0xffff;
                m_CommPorp.wPacketVersion      = 0xffff;
                m_CommPorp.dwServiceMask       = SP_SERIALCOMM;
                m_CommPorp.dwReserved1         = 0;
                m_CommPorp.dwMaxTxQueue        = 16;
                m_CommPorp.dwMaxRxQueue        = 16;
                m_CommPorp.dwMaxBaud           = BAUD_115200;
                m_CommPorp.dwProvSubType       = PST_RS232;
                m_CommPorp.dwProvCapabilities  =
                    PCF_DTRDSR | PCF_RLSD | PCF_RTSCTS |
                    PCF_SETXCHAR |
                    PCF_INTTIMEOUTS |
                    PCF_PARITY_CHECK |
                    PCF_SPECIALCHARS |
                    PCF_TOTALTIMEOUTS |
                    PCF_XONXOFF;
                m_CommPorp.dwSettableBaud      =
                    BAUD_075 | BAUD_110 | BAUD_150 | BAUD_300 | BAUD_600 |
                    BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
                    BAUD_7200 | BAUD_9600 | BAUD_14400 |
                    BAUD_19200 | BAUD_38400 | BAUD_56K | BAUD_128K |
                    BAUD_115200 | BAUD_57600 | BAUD_USER;
                m_CommPorp.dwSettableParams    =
                    SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
                    SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
                m_CommPorp.wSettableData       =
                    DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
                m_CommPorp.wSettableStopParity =
                    STOPBITS_10 | STOPBITS_20 |
                    PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_SPACE |
                    PARITY_MARK;
                // Setup m_DCB.

                // Set Default Parameter.
                SetOutputMode(FALSE, TRUE );    // No IR.
                // For DCB. The PDD only need to take care BaudRate, ByteSize Parity & StopBit
                m_DCB.DCBlength  = sizeof(DCB);
                SetBaudRate(m_DCB.BaudRate   = 9600,FALSE);
                SetByteSize(m_DCB.ByteSize   = 8);
                SetParity(m_DCB.Parity     = NOPARITY);
                SetStopBits(m_DCB.StopBits   = ONESTOPBIT);            
        }

                //
                //Power Managment Operation

                virtual CEDEVICE_POWER_STATE SetPowerState(    CEDEVICE_POWER_STATE requestState    )
                {
                        BOOL bRtn = TRUE;

                        __try
                        {
                                switch(requestState)
                                {
                                        case D0:
                                        case D1:
                                        case D3:
                                                requestState = D0;
                                                break;
                                        case D2:
                                        case D4:
                                                requestState = D4;
                                                break;
                                        default:
                                                requestState = m_PowerState;
                                                break;
                                }

                                if(m_PowerState != requestState)
                                {
                                        BOOL bSend = FALSE;
                                        //DWORD Profile;
                                        //DWORD dwBytes;  
                                        MSG_DEV_STATE Msg;

                                        Msg.bLPModeSupport = TRUE;
                                        Msg.dwDeviceID = IRQ_UART0;
                                        Msg.dwMsg = DTOP_POWER_SET;
                                        Msg.dwLParam = requestState;

                                        if(requestState == D0)
                                        {
                                                if(m_PowerState == D4 || m_PowerState == D2)
                                                {
                                                        PowerOn();
                                                }

                                                DBGMSG(UART_INFO,(L"[UART0] SEND D0 TO POWERCON\r\n"));
                                                bSend = TRUE;
                                        }
                                        else if(requestState == D2 || requestState == D4)
                                        {
                                                PowerOff();
                                                DBGMSG(UART_INFO,(L"[UART0] SEND D4 TO POWERCON\r\n"));
                                                bSend = TRUE;
                                        }

                                        m_PowerState = requestState;

                                        if(bSend)
                                        {
                                                if(!WriteMsgQueue(m_hPwrMsgQue, &Msg, sizeof(MSG_DEV_STATE), INFINITE, MSGQUEUE_MSGALERT))
                                                {
                                                        ERRMSG((L"[UART0] WriteMsgQueue is failed\r\n"));
                                                }
                                        }
                                } 
                        }
                        __except(EXCEPTION_EXECUTE_HANDLER)
                        {
                                ERRMSG((L"[UART0] SetPowerState EXCEPTION\r\n"));
                        }

                        return requestState;
                }


                virtual CEDEVICE_POWER_STATE GetPowerState(VOID)
                {
                        return m_PowerState;
                }

                virtual BOOL Ioctl(DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
                {
                        BOOL RetVal=FALSE;

                        switch ( dwCode ) 
                        {
                                case IOCTL_POWER_CAPABILITIES: 
                                        DBGMSG(UART_PM, (L"[UART0] +++IOCTL_POWER_CAPABILITIES\r\n"));          
                                        if (!pBufOut || dwLenOut < sizeof(POWER_CAPABILITIES) || !pdwActualOut) 
                                        {
                                                SetLastError(ERROR_INVALID_PARAMETER);
                                                RetVal = FALSE;
                                                ERRMSG((L"[UART0] IOCTL_POWER_CAPABILITIES EXCEPTION\r\n"));                
                                        } 
                                        else
                                        {
                                                m_IsThisPowerManaged = TRUE;
                                                PPOWER_CAPABILITIES ppc = (PPOWER_CAPABILITIES)pBufOut;        
                                                *ppc= GetPowerCapabilities();
                                                if (pdwActualOut)
                                                {
                                                        *pdwActualOut = sizeof(POWER_CAPABILITIES);
                                                }
                                                RetVal = TRUE;
                                        }
                                        DBGMSG(UART_PM, (L"[UART0] ---IOCTL_POWER_CAPABILITIES\r\n"));                      
                                        break;

                                case IOCTL_POWER_SET:
                                        DBGMSG(UART_PM, (L"[UART0] +++IOCTL_POWER_SET\r\n"));

                                        if (pBufOut && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))
                                        {
                                                __try
                                                {
                                                        CEDEVICE_POWER_STATE PowerState = *(PCEDEVICE_POWER_STATE)pBufOut;
                                                        DBGMSG(UART_PM, (L"[UART0] IOCTL_POWER_SET : D%d \r\n", PowerState));

                                                        if (VALID_DX(PowerState))
                                                        {
                                                                *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
                                                                *(PCEDEVICE_POWER_STATE) pBufOut = SetPowerState(PowerState);
                                                                RetVal = TRUE;
                                                        }
                                                }
                                                __except(EXCEPTION_EXECUTE_HANDLER)
                                                {
                                                        ERRMSG((L"[UART0] IOCTL_POWER_SET EXCEPTION\r\n"));
                                                        RetVal = FALSE;
                                                }
                                        }

                                        DBGMSG(UART_PM, (L"[UART0] ---IOCTL_POWER_SET\r\n"));               
                                        break;

                                case IOCTL_POWER_GET:
                                        DBGMSG(UART_PM, (L"[UART0] +++IOCTL_POWER_GET\r\n"));

                                        if (pBufOut != NULL && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))
                                        {
                                                __try
                                                {
                                                        *(PCEDEVICE_POWER_STATE)pBufOut = GetPowerState();
                                                        RetVal = TRUE;
                                                        DBGMSG(UART_PM, (L"[UART0] IOCTL_POWER_GET : D%d \r\n", *pBufOut));
                                                }
                                                __except(EXCEPTION_EXECUTE_HANDLER)
                                                {
                                                        ERRMSG((L"[UART0] IOCTL_POWER_GET EXCEPTION\r\n"));
                                                        RetVal = FALSE;
                                                }
                                        }

                                        DBGMSG(UART_PM, (L"[UART0] ---IOCTL_POWER_GET\r\n"));
                                        break;

                                case IOCTL_REQUEST_UART_SAVE_POWER:
                                        DBGMSG(UART_PM, (L"[UART0] +++IOCTL_REQUEST_UART_SAVE_POWER\r\n"));

                                        __try
                                        {
                                                DevicePowerNotify(UART0_POWER_NAME, D4, POWER_NAME);
                                                RetVal = TRUE;
                                                DBGMSG(UART_PM, (L"[UART0] IOCTL_REQUEST_UART_SAVE_POWER \r\n"));

                                        }
                                        __except(EXCEPTION_EXECUTE_HANDLER)
                                        {
                                                ERRMSG((L"[UART0] IOCTL_REQUEST_UART_SAVE_POWER EXCEPTION\r\n"));
                                                RetVal = FALSE;
                                        }


                                        DBGMSG(UART_PM, (L"[UART0] ---IOCTL_REQUEST_UART_SAVE_POWER\r\n"));
                                        break;

                                case IOCTL_REQUEST_UART_FULL_POWER:
                                        DBGMSG(UART_PM, (L"[UART0] +++IOCTL_REQUEST_UART_FULL_POWER\r\n"));

                                        __try
                                        {
                                                DevicePowerNotify(UART0_POWER_NAME, D0, POWER_NAME);
                                                RetVal = TRUE;
                                                DBGMSG(UART_PM, (L"[UART0] IOCTL_REQUEST_UART_FULL_POWER \r\n"));

                                        }
                                        __except(EXCEPTION_EXECUTE_HANDLER)
                                        {
                                                ERRMSG((L"[UART0] IOCTL_REQUEST_UART_FULL_POWER EXCEPTION\r\n"));
                                                RetVal = FALSE;
                                        }


                                        DBGMSG(UART_PM, (L"[UART0] ---IOCTL_REQUEST_UART_FULL_POWER\r\n"));
                                        break;

                                case IOCTL_REQUEST_ENABLE_AFC:
                                        DBGMSG(UART_PM, (L"[UART0] +++IOCTL_REQUEST_ENABLE_AFC\r\n"));
                                        m_dwAFCEnable = TRUE;
                                        DBGMSG(UART_PM, (L"[UART0] ---IOCTL_REQUEST_ENABLE_AFC\r\n"));
                                        break;

                                case IOCTL_REQUEST_DISABLE_AFC:
                                        DBGMSG(UART_PM, (L"[UART0] +++IOCTL_REQUEST_DISABLE_AFC\r\n"));
                                        m_dwAFCEnable = FALSE;
                                        DBGMSG(UART_PM, (L"[UART0] ---IOCTL_REQUEST_DISABLE_AFC\r\n"));
                                        break;

                                default:
                                        SetLastError(ERROR_INVALID_PARAMETER);
                                        RetVal = FALSE;
                                        break;
                        }
                        return RetVal;
                }

                virtual BOOL InitialPower(BOOL bInit)
                {

                        m_PowerState=D0;
                        m_IsThisPowerManaged=FALSE;
                        m_PowerCapabilities.DeviceDx = DX_MASK(D0) | DX_MASK(D2)| DX_MASK(D3) | DX_MASK(D4);

                        return TRUE;
                }

    private:
                HANDLE              m_hPwrControl;  
                HANDLE              m_hPwrMsgQue;


        volatile GPIO_REG * m_pIOPregs;
        volatile CMU_CLK_REG * m_pSysconRegs;
        volatile ULONG *    m_pDTRPort;
        DWORD               m_dwDTRPortNum;
        volatile ULONG *    m_pDSRPort;
        DWORD               m_dwDSRPortNum;
        BOOL                m_fIsDSRSet;
};

/// CPddSerial1 is used for UART1
/// enabling UART1 is dependent to board's jumper setting.
/// We assume that jumper setting is correct.

class CPddSerial1 : public CPddUart
{
    public:
        CPddSerial1(LPTSTR lpActivePath, PVOID pMdd, PHWOBJ pHwObj)
            : CPddUart(lpActivePath, pMdd, pHwObj)
        {
                m_pIOPregs = NULL;
                m_pSysconRegs = NULL;
        }
        ~CPddSerial1()
        {
                if(m_pSysconRegs)
                {
                                //            m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 &= CLK_UART1_MASK;
                                DWORD dwIPIndex ;
                                DWORD dwBytes;   

                                dwIPIndex = CLK_IP3_UART1;
                                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                                {
                                        ERRMSG((_T("[UART1:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                                }

                        m_pSysconRegs->CLK_SRC.CLK_SRC_MASK0 &= CLK_SRC_MASK0_UART1_DISABLE;            
                        m_pSysconRegs->CLK_SRC.CLK_SRC4      &= (CLK_SCLKMPLL << CLK_UART1_SEL);            						
                        m_pSysconRegs->CLK_DIV.CLK_DIV4      &= ~(0xF << CLK_UART1_SEL);	//DIV set to zero.						
                }
                if (m_pIOPregs != NULL)
                {
                        MmUnmapIoSpace((PVOID)m_pIOPregs, sizeof(GPIO_REG));
                }
                if (m_pSysconRegs != NULL)
                {
                        MmUnmapIoSpace((PVOID)m_pSysconRegs, sizeof(CMU_CLK_REG));
                }
                        if (m_hPwrMsgQue != NULL)
                        {
                                CloseMsgQueue(m_hPwrMsgQue);
                        }

        }
        virtual BOOL Init()
        {
                        MSGQUEUEOPTIONS msgOptions;
                PHYSICAL_ADDRESS    ioPhysicalBase = {0,0};

                ioPhysicalBase.LowPart = BASE_REG_PA_CMU_CLK;
                ioPhysicalBase.HighPart = 0;

                        m_hPwrControl = CreateFile( L"PWC0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                        if (INVALID_HANDLE_VALUE == m_hPwrControl )
                        {
                                ERRMSG((_T("[UART1:ERR] ++%s(): PWC0 Open Device Failed!\r\n"), _T(__FUNCTION__)));
                                return FALSE;
                        }

                        memset((void *)&msgOptions, 0x0, sizeof(msgOptions));
                        msgOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
                        msgOptions.dwFlags = 0;
                        msgOptions.dwMaxMessages = 1024;        // Max number of MSG queue entries
                        msgOptions.cbMaxMessage = sizeof(MSG_DEV_STATE);
                        msgOptions.bReadAccess = FALSE;
                        m_hPwrMsgQue = CreateMsgQueue(OEMPM_MSGQ_NAME, &msgOptions);

                m_pSysconRegs = (volatile CMU_CLK_REG *) MmMapIoSpace(ioPhysicalBase,sizeof(CMU_CLK_REG),FALSE);

                if(m_pSysconRegs)
                {        
                                //            m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 |= CLK_UART1_PASS;
                                DWORD dwIPIndex ;
                                DWORD dwBytes;   

                                dwIPIndex = CLK_IP3_UART1;
                                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                                {
                                        ERRMSG((_T("[UART1:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                                }

                        m_pSysconRegs->CLK_SRC.CLK_SRC4      |= (0x6 << CLK_UART1_SEL);		//SCLKMPLL				
                        m_pSysconRegs->CLK_DIV.CLK_DIV4      &= ~(0xF << CLK_UART1_SEL);	//DIV set to zero.
                        m_pSysconRegs->CLK_DIV.CLK_DIV4      |= (0x4  << CLK_UART1_SEL);	//DIV set to zero.
                        m_pSysconRegs->CLK_SRC.CLK_SRC_MASK0 |= CLK_SRC_MASK0_UART1_ENABLE;
                }
                else
                {
                                DBGMSG( UART_INFO, (TEXT("[UART1] MmMapIoSpace Failed to allocate for m_pIOPregs\r\n"))); 
                        return FALSE;
                }


                ioPhysicalBase.LowPart = BASE_REG_PA_GPIO;
                ioPhysicalBase.HighPart = 0;
                m_pIOPregs = (volatile GPIO_REG *) MmMapIoSpace(ioPhysicalBase, sizeof(GPIO_REG),FALSE);

                if (m_pIOPregs)
                {
                        DDKISRINFO ddi;
                        if (GetIsrInfo( &ddi) ==  ERROR_SUCCESS && 
                                KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &ddi.dwIrq, sizeof(UINT32), &ddi.dwSysintr, sizeof(UINT32), NULL))
                        {   
                                        DBGMSG( UART_INFO, (TEXT("[UART1] SYSINTR : %d\r\n"), *((PBYTE) &ddi.dwSysintr))); 
                                RegSetValueEx(DEVLOAD_SYSINTR_VALNAME,REG_DWORD,(PBYTE) &ddi.dwSysintr, sizeof(UINT32));
                        }
                        else
                        {
                                return FALSE;
                        }

                        Set_PinFunction(m_pIOPregs, UART1_RXD);
                        Set_PinFunction(m_pIOPregs, UART1_TXD);
                        Set_PinPullUD(m_pIOPregs, UART1_RXD, sgip_PULL_DOWN);
                        Set_PinPullUD(m_pIOPregs, UART1_TXD, sgip_PULL_DISABLE);  
                        Set_PinDrv(m_pIOPregs, UART1_TXD, sgip_DRV_4x);
                        Set_PinDrv(m_pIOPregs, UART1_RXD, sgip_DRV_4x);

                        Set_PinFunction(m_pIOPregs, UART1_CTSn);
                        Set_PinFunction(m_pIOPregs, UART1_RTSn);
                        Set_PinPullUD(m_pIOPregs, UART1_CTSn, sgip_PULL_DISABLE);
                        Set_PinPullUD(m_pIOPregs, UART1_RTSn, sgip_PULL_DISABLE);  
                        Set_PinDrv(m_pIOPregs, UART1_CTSn, sgip_DRV_4x);
                        Set_PinDrv(m_pIOPregs, UART1_RTSn, sgip_DRV_4x);

                        return CPddUart::Init();
                }
                return FALSE;
        }

        virtual BOOL    PowerOff()
        {
                        DWORD dwIPIndex ;
                        DWORD dwBytes;   

                CSerialPDD::PowerOff();

                        dwIPIndex = CLK_IP3_UART1;
                        if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                        {
                                ERRMSG((_T("[UART1:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                        }
#if 0       

                if(m_pSysconRegs)
                {
                        m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 &= CLK_UART1_MASK;
                }
#endif      
                return TRUE;
        }

        virtual BOOL    PowerOn()
        {
                        DWORD dwIPIndex ;
                        DWORD dwBytes;   

                        dwIPIndex = CLK_IP3_UART1;
                        if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                        {
                                ERRMSG((_T("[UART1:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                        }

#if 0   
                if(m_pSysconRegs)
                {        
                        m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 |= CLK_UART1_PASS;
                }
#endif
                CSerialPDD::PowerOn();
                return TRUE;
        }

        virtual ULONG   GetModemStatus()
        {
                return (CPddUart::GetModemStatus() | MS_CTS_ON);
        }

        virtual void    SetDefaultConfiguration()
        {
                // Default Value. Can be altered.
                m_CommPorp.wPacketLength       = 0xffff;
                m_CommPorp.wPacketVersion      = 0xffff;
                m_CommPorp.dwServiceMask       = SP_SERIALCOMM;
                m_CommPorp.dwReserved1         = 0;
                m_CommPorp.dwMaxTxQueue        = 16;
                m_CommPorp.dwMaxRxQueue        = 16;
                m_CommPorp.dwMaxBaud           = BAUD_115200;
                m_CommPorp.dwProvSubType       = PST_RS232;
                m_CommPorp.dwProvCapabilities  =
                    PCF_DTRDSR | PCF_RLSD | PCF_RTSCTS |
                    PCF_SETXCHAR |
                    PCF_INTTIMEOUTS |
                    PCF_PARITY_CHECK |
                    PCF_SPECIALCHARS |
                    PCF_TOTALTIMEOUTS |
                    PCF_XONXOFF;
                m_CommPorp.dwSettableBaud      =
                    BAUD_075 | BAUD_110 | BAUD_150 | BAUD_300 | BAUD_600 |
                    BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
                    BAUD_7200 | BAUD_9600 | BAUD_14400 |
                    BAUD_19200 | BAUD_38400 | BAUD_56K | BAUD_128K |
                    BAUD_115200 | BAUD_57600 | BAUD_USER;
                m_CommPorp.dwSettableParams    =
                    SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
                    SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
                m_CommPorp.wSettableData       =
                    DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
                m_CommPorp.wSettableStopParity =
                    STOPBITS_10 | STOPBITS_20 |
                    PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_SPACE |
                    PARITY_MARK;
                // Setup m_DCB.

                // Set Detault Parameter.
                SetOutputMode(FALSE, TRUE );    // No IR.
                // For DCB. The PDD only need to take care BaudRate, ByteSize Parity & StopBit
                m_DCB.DCBlength  = sizeof(DCB);
                SetBaudRate(m_DCB.BaudRate   = 9600,FALSE);
                SetByteSize(m_DCB.ByteSize   = 8);
                SetParity(m_DCB.Parity     = NOPARITY);
                SetStopBits(m_DCB.StopBits   = ONESTOPBIT);        
        }

                //
                //Power Managment Operation

                virtual CEDEVICE_POWER_STATE SetPowerState(    CEDEVICE_POWER_STATE requestState    )
                {
                        BOOL bRtn = TRUE;

                        __try
                        {
                                switch(requestState)
                                {
                                        case D0:
                                        case D1:
                                        case D3:
                                                requestState = D0;
                                                break;
                                        case D2:
                                        case D4:
                                                requestState = D4;
                                                break;
                                        default:
                                                requestState = m_PowerState;
                                                break;
                                }

                                if(m_PowerState != requestState)
                                {
                                        BOOL bSend = FALSE;
                                        //DWORD Profile;
                                        //DWORD dwBytes;  
                                        MSG_DEV_STATE Msg;

                                        Msg.bLPModeSupport = TRUE;
                                        Msg.dwDeviceID = IRQ_UART1;
                                        Msg.dwMsg = DTOP_POWER_SET;
                                        Msg.dwLParam = requestState;

                                        if(requestState == D0)
                                        {
                                                if(m_PowerState == D4 || m_PowerState == D2)
                                                {
                                                        PowerOn();
                                                }

                                                DBGMSG(UART_INFO,(L"[UART1] SEND D0 TO POWERCON\r\n"));
                                                bSend = TRUE;
                                        }
                                        else if(requestState == D2 || requestState == D4)
                                        {
                                                PowerOff();
                                                DBGMSG(UART_INFO,(L"[UART1] SEND D4 TO POWERCON\r\n"));
                                                bSend = TRUE;
                                        }

                                        m_PowerState = requestState;

                                        if(bSend)
                                        {
                                                if(!WriteMsgQueue(m_hPwrMsgQue, &Msg, sizeof(MSG_DEV_STATE), INFINITE, MSGQUEUE_MSGALERT))
                                                {
                                                        ERRMSG((L"[UART1] WriteMsgQueue is failed\r\n"));
                                                }
                                        }
                                } 
                        }
                        __except(EXCEPTION_EXECUTE_HANDLER)
                        {
                                ERRMSG((L"[UART1] SetPowerState EXCEPTION\r\n"));
                        }

                        return requestState;
                }


                virtual CEDEVICE_POWER_STATE GetPowerState(VOID)
                {
                        return m_PowerState;
                }

                virtual BOOL Ioctl(DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
                {
                        BOOL RetVal=FALSE;

                        switch ( dwCode ) 
                        {
                                case IOCTL_POWER_CAPABILITIES: 
                                        DBGMSG(UART_PM, (L"[UART1] +++IOCTL_POWER_CAPABILITIES\r\n"));          
                                        if (!pBufOut || dwLenOut < sizeof(POWER_CAPABILITIES) || !pdwActualOut) 
                                        {
                                                SetLastError(ERROR_INVALID_PARAMETER);
                                                RetVal = FALSE;
                                                ERRMSG((L"[UART1] IOCTL_POWER_CAPABILITIES EXCEPTION\r\n"));                
                                        } 
                                        else
                                        {
                                                m_IsThisPowerManaged = TRUE;
                                                PPOWER_CAPABILITIES ppc = (PPOWER_CAPABILITIES)pBufOut;        
                                                *ppc= GetPowerCapabilities();
                                                if (pdwActualOut)
                                                {
                                                        *pdwActualOut = sizeof(POWER_CAPABILITIES);
                                                }
                                                RetVal = TRUE;
                                        }
                                        DBGMSG(UART_PM, (L"[UART1] ---IOCTL_POWER_CAPABILITIES\r\n"));                      
                                        break;

                                case IOCTL_POWER_SET:
                                        DBGMSG(UART_PM, (L"[UART1] +++IOCTL_POWER_SET\r\n"));

                                        if (pBufOut && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))
                                        {
                                                __try
                                                {
                                                        CEDEVICE_POWER_STATE PowerState = *(PCEDEVICE_POWER_STATE)pBufOut;
                                                        DBGMSG(UART_PM, (L"[UART1] IOCTL_POWER_SET : D%d \r\n", PowerState));

                                                        if (VALID_DX(PowerState))
                                                        {
                                                                *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
                                                                *(PCEDEVICE_POWER_STATE) pBufOut = SetPowerState(PowerState);
                                                                RetVal = TRUE;
                                                        }
                                                }
                                                __except(EXCEPTION_EXECUTE_HANDLER)
                                                {
                                                        ERRMSG((L"[UART1] IOCTL_POWER_SET EXCEPTION\r\n"));
                                                        RetVal = FALSE;
                                                }
                                        }

                                        DBGMSG(UART_PM, (L"[UART11] ---IOCTL_POWER_SET\r\n"));              
                                        break;

                                case IOCTL_POWER_GET:
                                        DBGMSG(UART_PM, (L"[UART1] +++IOCTL_POWER_GET\r\n"));

                                        if (pBufOut != NULL && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))
                                        {
                                                __try
                                                {
                                                        *(PCEDEVICE_POWER_STATE)pBufOut = GetPowerState();
                                                        RetVal = TRUE;
                                                        DBGMSG(UART_PM, (L"[UART1] IOCTL_POWER_GET : D%d \r\n", *pBufOut));
                                                }
                                                __except(EXCEPTION_EXECUTE_HANDLER)
                                                {
                                                        ERRMSG((L"[UART1] IOCTL_POWER_GET EXCEPTION\r\n"));
                                                        RetVal = FALSE;
                                                }
                                        }

                                        DBGMSG(UART_PM, (L"[UART1] ---IOCTL_POWER_GET\r\n"));
                                        break;

                                case IOCTL_REQUEST_UART_SAVE_POWER:
                                        DBGMSG(UART_PM, (L"[UART1] +++IOCTL_REQUEST_UART_SAVE_POWER\r\n"));

                                        __try
                                        {
                                                DevicePowerNotify(UART1_POWER_NAME, D4, POWER_NAME);
                                                RetVal = TRUE;
                                                DBGMSG(UART_PM, (L"[UART1] IOCTL_REQUEST_UART_SAVE_POWER \r\n"));

                                        }
                                        __except(EXCEPTION_EXECUTE_HANDLER)
                                        {
                                                ERRMSG((L"[UART1] IOCTL_REQUEST_UART_SAVE_POWER EXCEPTION\r\n"));
                                                RetVal = FALSE;
                                        }


                                        DBGMSG(UART_PM, (L"[UART1] ---IOCTL_REQUEST_UART_SAVE_POWER\r\n"));
                                        break;

                                case IOCTL_REQUEST_UART_FULL_POWER:
                                        DBGMSG(UART_PM, (L"[UART1] +++IOCTL_REQUEST_UART_FULL_POWER\r\n"));

                                        __try
                                        {
                                                DevicePowerNotify(UART1_POWER_NAME, D0, POWER_NAME);
                                                RetVal = TRUE;
                                                DBGMSG(UART_PM, (L"[UART1] IOCTL_REQUEST_UART_FULL_POWER \r\n"));

                                        }
                                        __except(EXCEPTION_EXECUTE_HANDLER)
                                        {
                                                ERRMSG((L"[UART1] IOCTL_REQUEST_UART_FULL_POWER EXCEPTION\r\n"));
                                                RetVal = FALSE;
                                        }


                                        DBGMSG(UART_PM, (L"[UART1] ---IOCTL_REQUEST_UART_FULL_POWER\r\n"));
                                        break;


                                default:
                                        SetLastError(ERROR_INVALID_PARAMETER);
                                        RetVal = FALSE;
                                        break;
                        }
                        return RetVal;
                }

                virtual BOOL InitialPower(BOOL bInit)
                {

                        m_PowerState=D0;
                        m_IsThisPowerManaged=FALSE;
                        m_PowerCapabilities.DeviceDx = DX_MASK(D0) | DX_MASK(D2)| DX_MASK(D3) | DX_MASK(D4);

                        return TRUE;
                }

        volatile GPIO_REG * m_pIOPregs;
        volatile CMU_CLK_REG * m_pSysconRegs;

        private:
                HANDLE              m_hPwrControl;  
                HANDLE              m_hPwrMsgQue;

};

/// CPddSerial2 is used for UART2

class CPddSerial2 : public CPddUart
{
    public:
        CPddSerial2(LPTSTR lpActivePath, PVOID pMdd, PHWOBJ pHwObj)
            : CPddUart(lpActivePath, pMdd, pHwObj)
        {
                m_pIOPregs = NULL;
                m_pSysconRegs = NULL;
        }
        ~CPddSerial2()
        {
                if(m_pSysconRegs)
                {
                                //          m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 &= CLK_UART2_MASK;        
                                DWORD dwIPIndex ;
                                DWORD dwBytes;   

                                dwIPIndex = CLK_IP3_UART2;
                                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                                {
                                        ERRMSG((_T("[UART2:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                                }

                        m_pSysconRegs->CLK_SRC.CLK_SRC4 &=  (CLK_SCLKMPLL << CLK_UART2_SEL);           
                        m_pSysconRegs->CLK_SRC.CLK_SRC_MASK0 &= CLK_SRC_MASK0_UART2_DISABLE;    
                }
                if (m_pIOPregs != NULL)
                {
                        MmUnmapIoSpace((PVOID)m_pIOPregs, sizeof(GPIO_REG));
                }
                if (m_pSysconRegs != NULL)
                {
                        MmUnmapIoSpace((PVOID)m_pSysconRegs, sizeof(CMU_CLK_REG));
                }
                        if (m_hPwrMsgQue != NULL)
                        {
                                CloseMsgQueue(m_hPwrMsgQue);
                        }

        }
        virtual BOOL Init()
        {
                        MSGQUEUEOPTIONS msgOptions;
                PHYSICAL_ADDRESS    ioPhysicalBase = {0,0};

                ioPhysicalBase.LowPart = BASE_REG_PA_CMU_CLK;
                ioPhysicalBase.HighPart = 0;

                        m_hPwrControl = CreateFile( L"PWC0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                        if (INVALID_HANDLE_VALUE == m_hPwrControl )
                        {
                                ERRMSG((_T("[UART2:ERR] ++%s(): PWC0 Open Device Failed!\r\n"), _T(__FUNCTION__)));
                                return FALSE;
                        }

                        memset((void *)&msgOptions, 0x0, sizeof(msgOptions));
                        msgOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
                        msgOptions.dwFlags = 0;
                        msgOptions.dwMaxMessages = 1024;        // Max number of MSG queue entries
                        msgOptions.cbMaxMessage = sizeof(MSG_DEV_STATE);
                        msgOptions.bReadAccess = FALSE;
                        m_hPwrMsgQue = CreateMsgQueue(OEMPM_MSGQ_NAME, &msgOptions);

                m_pSysconRegs = (volatile CMU_CLK_REG *) MmMapIoSpace(ioPhysicalBase,sizeof(CMU_CLK_REG),FALSE);

                if(m_pSysconRegs)
                {        
                                //            m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 |= CLK_UART2_PASS;
                                DWORD dwIPIndex ;
                                DWORD dwBytes;   

                                dwIPIndex = CLK_IP3_UART2;
                                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                                {
                                        ERRMSG((_T("[UART2:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                                }

                        m_pSysconRegs->CLK_SRC.CLK_SRC4      |= (0x6 << CLK_UART2_SEL);		//SCLKMPLL				
                        m_pSysconRegs->CLK_DIV.CLK_DIV4      &= ~(0xF << CLK_UART2_SEL);	//DIV set to zero.
                        m_pSysconRegs->CLK_DIV.CLK_DIV4      |= (0x4  << CLK_UART2_SEL);	//DIV set to zero.
                        m_pSysconRegs->CLK_SRC.CLK_SRC_MASK0 |= CLK_SRC_MASK0_UART2_ENABLE;
						
                }
                else
                {
                        return FALSE;
                }        

                ioPhysicalBase.LowPart = BASE_REG_PA_GPIO;
                ioPhysicalBase.HighPart = 0;
                m_pIOPregs = (volatile GPIO_REG *) MmMapIoSpace(ioPhysicalBase, sizeof(GPIO_REG),FALSE);

                if (m_pIOPregs)
                {
                        DDKISRINFO ddi;
                        if (GetIsrInfo( &ddi) ==  ERROR_SUCCESS && 
                                KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &ddi.dwIrq, sizeof(UINT32), &ddi.dwSysintr, sizeof(UINT32), NULL))
                        {   
                                        DBGMSG(UART_INFO, (TEXT("[UART2] Serial2 SYSINTR : %d\r\n"), *((PBYTE) &ddi.dwSysintr))); 
                                RegSetValueEx(DEVLOAD_SYSINTR_VALNAME,REG_DWORD,(PBYTE) &ddi.dwSysintr, sizeof(UINT32));
                        }
                        else
                        {
                                return FALSE;
                        }

                        Set_PinFunction(m_pIOPregs, UART2_RXD);
                        Set_PinFunction(m_pIOPregs, UART2_TXD);
                        Set_PinPullUD(m_pIOPregs, UART2_RXD, sgip_PULL_DOWN);
                        Set_PinPullUD(m_pIOPregs, UART2_TXD, sgip_PULL_DISABLE);  
                        Set_PinDrv(m_pIOPregs, UART2_TXD, sgip_DRV_4x);
                        Set_PinDrv(m_pIOPregs, UART2_RXD, sgip_DRV_4x);

#if 0  //if enabled UART3 will not work
                        DBGMSG(UART_INFO, (TEXT("UART2 RTS CTS enabled. UART3 is disabled.\r\n"))); 
                        Set_PinFunction(m_pIOPregs, GPA13_UART_2_RTSn);
                        Set_PinFunction(m_pIOPregs, GPA12_UART_2_CTSn);
                        Set_PinPullUD(m_pIOPregs, GPA13_UART_2_RTSn, sgip_PULL_DISABLE);
                        Set_PinPullUD(m_pIOPregs, GPA12_UART_2_CTSn, sgip_PULL_DISABLE);  
                        Set_PinDrv(m_pIOPregs, GPA13_UART_2_RTSn, sgip_DRV_4x);
                        Set_PinDrv(m_pIOPregs, GPA12_UART_2_CTSn, sgip_DRV_4x);
#endif
                        return CPddUart::Init();
                }
                return FALSE;
        }

        virtual BOOL    PowerOff()
        {
                        DWORD dwIPIndex ;
                        DWORD dwBytes;   

                CSerialPDD::PowerOff();

                        dwIPIndex = CLK_IP3_UART2;
                        if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                        {
                                ERRMSG((_T("[UART2:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                        }
#if 0       

                if(m_pSysconRegs)
                {
                        m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 &= CLK_UART2_MASK;
                }
#endif      
                return TRUE;
        }

        virtual BOOL    PowerOn()
        {
                        DWORD dwIPIndex ;
                        DWORD dwBytes;   

                        dwIPIndex = CLK_IP3_UART2;
                        if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                        {
                                ERRMSG((_T("[UART2:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                        }

#if 0   
                if(m_pSysconRegs)
                {        
                        m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 |= CLK_UART2_PASS;
                }
#endif
                CSerialPDD::PowerOn();
                return TRUE;
        }

        virtual ULONG   GetModemStatus()
        {
                return (CPddUart::GetModemStatus() | MS_CTS_ON);
        }

        virtual void    SetDefaultConfiguration()
        {
                // Default Value. Can be altered.
                m_CommPorp.wPacketLength       = 0xffff;
                m_CommPorp.wPacketVersion      = 0xffff;
                m_CommPorp.dwServiceMask       = SP_SERIALCOMM;
                m_CommPorp.dwReserved1         = 0;
                m_CommPorp.dwMaxTxQueue        = 16;
                m_CommPorp.dwMaxRxQueue        = 16;
                m_CommPorp.dwMaxBaud           = BAUD_115200;
                m_CommPorp.dwProvSubType       = PST_RS232;
                m_CommPorp.dwProvCapabilities  =
                    PCF_DTRDSR | PCF_RLSD | PCF_RTSCTS |
                    PCF_SETXCHAR |
                    PCF_INTTIMEOUTS |
                    PCF_PARITY_CHECK |
                    PCF_SPECIALCHARS |
                    PCF_TOTALTIMEOUTS |
                    PCF_XONXOFF;
                m_CommPorp.dwSettableBaud      =
                    BAUD_075 | BAUD_110 | BAUD_150 | BAUD_300 | BAUD_600 |
                    BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
                    BAUD_7200 | BAUD_9600 | BAUD_14400 |
                    BAUD_19200 | BAUD_38400 | BAUD_56K | BAUD_128K |
                    BAUD_115200 | BAUD_57600 | BAUD_USER;
                m_CommPorp.dwSettableParams    =
                    SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
                    SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
                m_CommPorp.wSettableData       =
                    DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
                m_CommPorp.wSettableStopParity =
                    STOPBITS_10 | STOPBITS_20 |
                    PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_SPACE |
                    PARITY_MARK;
                // Setup m_DCB.

                // Set Default Parameter.
                SetOutputMode(FALSE, TRUE );    // No IR.
                // For DCB. The PDD only need to take care BaudRate, ByteSize Parity & StopBit
                m_DCB.DCBlength  = sizeof(DCB);
                SetBaudRate(m_DCB.BaudRate   = 9600,FALSE);
                SetByteSize(m_DCB.ByteSize   = 8);
                SetParity(m_DCB.Parity     = NOPARITY);
                SetStopBits(m_DCB.StopBits   = ONESTOPBIT);        
        }
        /// change GPIO between RXD2 and Input
                //
                //Power Managment Operation

                virtual CEDEVICE_POWER_STATE SetPowerState(    CEDEVICE_POWER_STATE requestState    )
                {
                        BOOL bRtn = TRUE;

                        __try
                        {
                                switch(requestState)
                                {
                                        case D0:
                                        case D1:
                                        case D3:
                                                requestState = D0;
                                                break;
                                        case D2:
                                        case D4:
                                                requestState = D4;
                                                break;
                                        default:
                                                requestState = m_PowerState;
                                                break;
                                }

                                if(m_PowerState != requestState)
                                {
                                        BOOL bSend = FALSE;
                                        //DWORD Profile;
                                        //DWORD dwBytes;  
                                        MSG_DEV_STATE Msg;

                                        Msg.bLPModeSupport = TRUE;
                                        Msg.dwDeviceID = IRQ_UART2;
                                        Msg.dwMsg = DTOP_POWER_SET;
                                        Msg.dwLParam = requestState;

                                        if(requestState == D0)
                                        {
                                                if(m_PowerState == D4 || m_PowerState == D2)
                                                {
                                                        PowerOn();
                                                }

                                                DBGMSG(UART_INFO,(L"[UART2] SEND D0 TO POWERCON\r\n"));
                                                bSend = TRUE;
                                        }
                                        else if(requestState == D2 || requestState == D4)
                                        {
                                                PowerOff();
                                                DBGMSG(UART_INFO,(L"[UART2] SEND D4 TO POWERCON\r\n"));
                                                bSend = TRUE;
                                        }

                                        m_PowerState = requestState;

                                        if(bSend)
                                        {
                                                if(!WriteMsgQueue(m_hPwrMsgQue, &Msg, sizeof(MSG_DEV_STATE), INFINITE, MSGQUEUE_MSGALERT))
                                                {
                                                        ERRMSG((L"[UART2] WriteMsgQueue is failed\r\n"));
                                                }
                                        }
                                } 
                        }
                        __except(EXCEPTION_EXECUTE_HANDLER)
                        {
                                ERRMSG((L"[UART2] SetPowerState EXCEPTION\r\n"));
                        }

                        return requestState;
                }


                virtual CEDEVICE_POWER_STATE GetPowerState(VOID)
                {
                        return m_PowerState;
                }

                virtual BOOL Ioctl(DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
                {
                        BOOL RetVal=FALSE;

                        switch ( dwCode ) 
                        {
                                case IOCTL_POWER_CAPABILITIES: 
                                        DBGMSG(UART_PM, (L"[UART2] +++IOCTL_POWER_CAPABILITIES\r\n"));          
                                        if (!pBufOut || dwLenOut < sizeof(POWER_CAPABILITIES) || !pdwActualOut) 
                                        {
                                                SetLastError(ERROR_INVALID_PARAMETER);
                                                RetVal = FALSE;
                                                ERRMSG((L"[UART2] IOCTL_POWER_CAPABILITIES EXCEPTION\r\n"));                
                                        } 
                                        else
                                        {
                                                m_IsThisPowerManaged = TRUE;
                                                PPOWER_CAPABILITIES ppc = (PPOWER_CAPABILITIES)pBufOut;        
                                                *ppc= GetPowerCapabilities();
                                                if (pdwActualOut)
                                                {
                                                        *pdwActualOut = sizeof(POWER_CAPABILITIES);
                                                }
                                                RetVal = TRUE;
                                        }
                                        DBGMSG(UART_PM, (L"[UART2] ---IOCTL_POWER_CAPABILITIES\r\n"));                      
                                        break;

                                case IOCTL_POWER_SET:
                                        DBGMSG(UART_PM, (L"[UART2] +++IOCTL_POWER_SET\r\n"));

                                        if (pBufOut && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))
                                        {
                                                __try
                                                {
                                                        CEDEVICE_POWER_STATE PowerState = *(PCEDEVICE_POWER_STATE)pBufOut;
                                                        DBGMSG(UART_PM, (L"[UART2] IOCTL_POWER_SET : D%d \r\n", PowerState));

                                                        if (VALID_DX(PowerState))
                                                        {
                                                                *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
                                                                *(PCEDEVICE_POWER_STATE) pBufOut = SetPowerState(PowerState);
                                                                RetVal = TRUE;
                                                        }
                                                }
                                                __except(EXCEPTION_EXECUTE_HANDLER)
                                                {
                                                        ERRMSG((L"[UART2] IOCTL_POWER_SET EXCEPTION\r\n"));
                                                        RetVal = FALSE;
                                                }
                                        }

                                        DBGMSG(UART_PM, (L"[UART2] ---IOCTL_POWER_SET\r\n"));               
                                        break;

                                case IOCTL_POWER_GET:
                                        DBGMSG(UART_PM, (L"[UART2] +++IOCTL_POWER_GET\r\n"));

                                        if (pBufOut != NULL && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))
                                        {
                                                __try
                                                {
                                                        *(PCEDEVICE_POWER_STATE)pBufOut = GetPowerState();
                                                        RetVal = TRUE;
                                                        DBGMSG(UART_PM, (L"[UART2] IOCTL_POWER_GET : D%d \r\n", *pBufOut));
                                                }
                                                __except(EXCEPTION_EXECUTE_HANDLER)
                                                {
                                                        ERRMSG((L"[UART2] IOCTL_POWER_GET EXCEPTION\r\n"));
                                                        RetVal = FALSE;
                                                }
                                        }

                                        DBGMSG(UART_PM, (L"[UART2] ---IOCTL_POWER_GET\r\n"));
                                        break;

                                case IOCTL_REQUEST_UART_SAVE_POWER:
                                        DBGMSG(UART_PM, (L"[UART2] +++IOCTL_REQUEST_UART_SAVE_POWER\r\n"));

                                        __try
                                        {
                                                DevicePowerNotify(UART2_POWER_NAME, D4, POWER_NAME);
                                                RetVal = TRUE;
                                                DBGMSG(UART_PM, (L"[UART2] IOCTL_REQUEST_UART_SAVE_POWER \r\n"));

                                        }
                                        __except(EXCEPTION_EXECUTE_HANDLER)
                                        {
                                                ERRMSG((L"[UART2] IOCTL_REQUEST_UART_SAVE_POWER EXCEPTION\r\n"));
                                                RetVal = FALSE;
                                        }


                                        DBGMSG(UART_PM, (L"[UART2] ---IOCTL_REQUEST_UART_SAVE_POWER\r\n"));
                                        break;

                                case IOCTL_REQUEST_UART_FULL_POWER:
                                        DBGMSG(UART_PM, (L"[UART2] +++IOCTL_REQUEST_UART_FULL_POWER\r\n"));

                                        __try
                                        {
                                                DevicePowerNotify(UART2_POWER_NAME, D0, POWER_NAME);
                                                RetVal = TRUE;
                                                DBGMSG(UART_PM, (L"[UART2] IOCTL_REQUEST_UART_FULL_POWER \r\n"));

                                        }
                                        __except(EXCEPTION_EXECUTE_HANDLER)
                                        {
                                                ERRMSG((L"[UART2] IOCTL_REQUEST_UART_FULL_POWER EXCEPTION\r\n"));
                                                RetVal = FALSE;
                                        }


                                        DBGMSG(UART_PM, (L"[UART2] ---IOCTL_REQUEST_UART_FULL_POWER\r\n"));
                                        break;


                                default:
                                        SetLastError(ERROR_INVALID_PARAMETER);
                                        RetVal = FALSE;
                                        break;
                        }
                        return RetVal;
                }

                virtual BOOL InitialPower(BOOL bInit)
                {

                        m_PowerState=D0;
                        m_IsThisPowerManaged=FALSE;
                        m_PowerCapabilities.DeviceDx = DX_MASK(D0) | DX_MASK(D2)| DX_MASK(D3) | DX_MASK(D4);

                        return TRUE;
                }

        volatile GPIO_REG * m_pIOPregs;
        volatile CMU_CLK_REG * m_pSysconRegs;

        private:
                HANDLE              m_hPwrControl;  
                HANDLE              m_hPwrMsgQue;
};

/// CPddSerial3 is used for UART3

class CPddSerial3 : public CPddUart
{
    public:
        CPddSerial3(LPTSTR lpActivePath, PVOID pMdd, PHWOBJ pHwObj)
            : CPddUart(lpActivePath, pMdd, pHwObj)
        {
                m_pIOPregs = NULL;
                m_pSysconRegs = NULL;
        }
        ~CPddSerial3()
        {
                if(m_pSysconRegs)
                {
                                //            m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 &= CLK_UART3_MASK;
                                DWORD dwIPIndex;
                                DWORD dwBytes;   

                                dwIPIndex = CLK_IP3_UART3;
                                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                                {
                                        ERRMSG((_T("[UART3:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                                }

                }
                if (m_pIOPregs != NULL)
                {
                        MmUnmapIoSpace((PVOID)m_pIOPregs, sizeof(GPIO_REG));
                }
                if (m_pSysconRegs != NULL)
                {
                        MmUnmapIoSpace((PVOID)m_pSysconRegs, sizeof(CMU_CLK_REG));
                }
                        if (m_hPwrMsgQue != NULL)
                        {
                                CloseMsgQueue(m_hPwrMsgQue);
                        }

        }
        virtual BOOL Init()
        {
                        MSGQUEUEOPTIONS     msgOptions;
                PHYSICAL_ADDRESS    ioPhysicalBase = {0,0};

                ioPhysicalBase.LowPart = BASE_REG_PA_CMU_CLK;
                ioPhysicalBase.HighPart = 0;

                        m_hPwrControl = CreateFile( L"PWC0:", GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0);
                        if (INVALID_HANDLE_VALUE == m_hPwrControl )
                        {
                                ERRMSG((_T("[UART3:ERR] ++%s(): PWC0 Open Device Failed!\r\n"), _T(__FUNCTION__)));
                                return FALSE;
                        }

                        memset((void *)&msgOptions, 0x0, sizeof(msgOptions));
                        msgOptions.dwSize = sizeof(MSGQUEUEOPTIONS);
                        msgOptions.dwFlags = 0;
                        msgOptions.dwMaxMessages = 1024;        // Max number of MSG queue entries
                        msgOptions.cbMaxMessage = sizeof(MSG_DEV_STATE);
                        msgOptions.bReadAccess = FALSE;
                        m_hPwrMsgQue = CreateMsgQueue(OEMPM_MSGQ_NAME, &msgOptions);

                m_pSysconRegs = (volatile CMU_CLK_REG *) MmMapIoSpace(ioPhysicalBase,sizeof(CMU_CLK_REG),FALSE);

                if(m_pSysconRegs)
                {        
                                //            m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 |= CLK_UART3_PASS;
                                DWORD dwIPIndex ;
                                DWORD dwBytes;   

                                dwIPIndex = CLK_IP3_UART3;
                                if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                                {
                                        ERRMSG((_T("[UART3:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                                }

                        m_pSysconRegs->CLK_SRC.CLK_SRC4      |= (0x6 << CLK_UART3_SEL);		//SCLKMPLL				
                        m_pSysconRegs->CLK_DIV.CLK_DIV4      &= ~(0xF << CLK_UART3_SEL);	//DIV set to zero.
                        m_pSysconRegs->CLK_DIV.CLK_DIV4      |= (0x4  << CLK_UART3_SEL);	//DIV set to zero.
                        m_pSysconRegs->CLK_SRC.CLK_SRC_MASK0 |= CLK_SRC_MASK0_UART3_ENABLE;
						
                }
                else
                {
                        return FALSE;
                }

                ioPhysicalBase.LowPart = BASE_REG_PA_GPIO;
                ioPhysicalBase.HighPart = 0;
                m_pIOPregs = (volatile GPIO_REG *) MmMapIoSpace(ioPhysicalBase, sizeof(GPIO_REG),FALSE);

                if (m_pIOPregs)
                {
                        DDKISRINFO ddi;
                        if (GetIsrInfo( &ddi) ==  ERROR_SUCCESS && 
                                KernelIoControl(IOCTL_HAL_REQUEST_SYSINTR, &ddi.dwIrq, sizeof(UINT32), &ddi.dwSysintr, sizeof(UINT32), NULL))
                        {   
                                        DBGMSG( UART_INFO, (TEXT("[UART3] Serial3 SYSINTR : %d\r\n"), *((PBYTE) &ddi.dwSysintr))); 
                                RegSetValueEx(DEVLOAD_SYSINTR_VALNAME,REG_DWORD,(PBYTE) &ddi.dwSysintr, sizeof(UINT32));
                        }
                        else
                        {
                                return FALSE;
                        }

                        Set_PinFunction(m_pIOPregs, UART3_RXD);
                        Set_PinFunction(m_pIOPregs, UART3_TXD);
                        Set_PinPullUD(m_pIOPregs, UART3_RXD, sgip_PULL_DOWN);
                        Set_PinPullUD(m_pIOPregs, UART3_TXD, sgip_PULL_DISABLE);  
                        Set_PinDrv(m_pIOPregs, UART3_TXD, sgip_DRV_4x);
                        Set_PinDrv(m_pIOPregs, UART3_RXD, sgip_DRV_4x);
                        DBGMSG(TRUE, (TEXT("UART3 Rx Tx Configured \r\n")));

                        return CPddUart::Init();
                }
                return FALSE;
        }
        virtual BOOL    PowerOff()
        {
                        DWORD dwIPIndex ;
                        DWORD dwBytes;   

                CSerialPDD::PowerOff();

                        dwIPIndex = CLK_IP3_UART3;
                        if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_OFF, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                        {
                                ERRMSG((_T("[UART1:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_OFF Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                        }
#if 0       

                if(m_pSysconRegs)
                {
                        m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 &= CLK_UART3_MASK; 
                }
#endif      
                return TRUE;
        }

        virtual BOOL    PowerOn()
        {
                        DWORD dwIPIndex ;
                        DWORD dwBytes;   

                        dwIPIndex = CLK_IP3_UART3;
                        if ( !DeviceIoControl(m_hPwrControl, IOCTL_PWRCON_SET_CLOCK_ON, &dwIPIndex, sizeof(DWORD), NULL, 0, &dwBytes, NULL) )
                        {
                                ERRMSG((_T("[UART3:ERR] ++%s:  : IOCTL_PWRCON_SET_POWER_ON Failed on line %d\r\n"),_T(__FUNCTION__), __LINE__));
                        }

#if 0   
                if(m_pSysconRegs)
                {        
                        m_pSysconRegs->CLK_GATE.CLK_GATE_IP3 |= CLK_UART3_PASS;
                }
#endif
                CSerialPDD::PowerOn();
                return TRUE;
        }

        virtual ULONG   GetModemStatus()
        {
                return (CPddUart::GetModemStatus() | MS_CTS_ON);
        }

        virtual void    SetDefaultConfiguration()
        {
                // Default Value. Can be altered.
                m_CommPorp.wPacketLength       = 0xffff;
                m_CommPorp.wPacketVersion      = 0xffff;
                m_CommPorp.dwServiceMask       = SP_SERIALCOMM;
                m_CommPorp.dwReserved1         = 0;
                m_CommPorp.dwMaxTxQueue        = 16;
                m_CommPorp.dwMaxRxQueue        = 16;
                m_CommPorp.dwMaxBaud           = BAUD_115200;
                m_CommPorp.dwProvSubType       = PST_RS232;
                m_CommPorp.dwProvCapabilities  =
                    PCF_DTRDSR | PCF_RLSD | PCF_RTSCTS |
                    PCF_SETXCHAR |
                    PCF_INTTIMEOUTS |
                    PCF_PARITY_CHECK |
                    PCF_SPECIALCHARS |
                    PCF_TOTALTIMEOUTS |
                    PCF_XONXOFF;
                m_CommPorp.dwSettableBaud      =
                    BAUD_075 | BAUD_110 | BAUD_150 | BAUD_300 | BAUD_600 |
                    BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
                    BAUD_7200 | BAUD_9600 | BAUD_14400 |
                    BAUD_19200 | BAUD_38400 | BAUD_56K | BAUD_128K |
                    BAUD_115200 | BAUD_57600 | BAUD_USER;
                m_CommPorp.dwSettableParams    =
                    SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
                    SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
                m_CommPorp.wSettableData       =
                    DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
                m_CommPorp.wSettableStopParity =
                    STOPBITS_10 | STOPBITS_20 |
                    PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_SPACE |
                    PARITY_MARK;
                // Setup m_DCB.

                // Set Default Parameter.
                // To enable IR set IR mode TRUE.
                SetOutputMode(FALSE, TRUE );    // No IR.
                // For DCB. The PDD only need to take care BaudRate, ByteSize Parity & StopBit
                m_DCB.DCBlength  = sizeof(DCB);
                SetBaudRate(m_DCB.BaudRate   = 9600,FALSE);
                SetByteSize(m_DCB.ByteSize   = 8);
                SetParity(m_DCB.Parity     = NOPARITY);
                SetStopBits(m_DCB.StopBits   = ONESTOPBIT);        
        }
        /// change GPIO between RXD3 and Input
#ifndef    BSP_NOIRDA3
        // If use IrDA. When data is transmitted, data cannot be received. 

        virtual void    Rx_Pause(BOOL bSet)
        {

                if(bSet)
                {        // from RXD3 to Input
                        Set_PinFunction(m_pIOPregs, GPA12_Input);
                        DBGMSG( UART_USR4, (TEXT("[UART] [Rx_Pause] %d\r\n"), bSet));                                           
                }
                else
                {        // from Input to RXD3
                        Set_PinFunction(m_pIOPregs, UART3_RXD);
                        DBGMSG( UART_USR4, (TEXT("[UART] [Rx_Pause] %d\r\n"), bSet));                                                                                           
                }
        }
#endif
                //
                //Power Managment Operation

                virtual CEDEVICE_POWER_STATE SetPowerState(    CEDEVICE_POWER_STATE requestState    )
                {
                        BOOL bRtn = TRUE;

                        __try
                        {
                                switch(requestState)
                                {
                                        case D0:
                                        case D1:
                                        case D3:
                                                requestState = D0;
                                                break;
                                        case D2:
                                        case D4:
                                                requestState = D4;
                                                break;
                                        default:
                                                requestState = m_PowerState;
                                                break;
                                }

                                if(m_PowerState != requestState)
                                {
                                        BOOL bSend = FALSE;
                                        //DWORD Profile;
                                        //DWORD dwBytes;  
                                        MSG_DEV_STATE Msg;

                                        Msg.bLPModeSupport = TRUE;
                                        Msg.dwDeviceID = IRQ_UART3;
                                        Msg.dwMsg = DTOP_POWER_SET;
                                        Msg.dwLParam = requestState;

                                        if(requestState == D0)
                                        {
                                                if(m_PowerState == D4 || m_PowerState == D2)
                                                {
                                                        PowerOn();
                                                }

                                                DBGMSG(UART_INFO,(L"[UART3] SEND D0 TO POWERCON\r\n"));
                                                bSend = TRUE;
                                        }
                                        else if(requestState == D2 || requestState == D4)
                                        {
                                                PowerOff();
                                                DBGMSG(UART_INFO,(L"[UART3] SEND D4 TO POWERCON\r\n"));
                                                bSend = TRUE;
                                        }

                                        m_PowerState = requestState;

                                        if(bSend)
                                        {
                                                if(!WriteMsgQueue(m_hPwrMsgQue, &Msg, sizeof(MSG_DEV_STATE), INFINITE, MSGQUEUE_MSGALERT))
                                                {
                                                        ERRMSG((L"[UART3] WriteMsgQueue is failed\r\n"));
                                                }
                                        }
                                } 
                        }
                        __except(EXCEPTION_EXECUTE_HANDLER)
                        {
                                ERRMSG((L"[UART3] SetPowerState EXCEPTION\r\n"));
                        }

                        return requestState;
                }


                virtual CEDEVICE_POWER_STATE GetPowerState(VOID)
                {
                        return m_PowerState;
                }

                virtual BOOL Ioctl(DWORD dwCode,PBYTE pBufIn,DWORD dwLenIn,PBYTE pBufOut,DWORD dwLenOut,PDWORD pdwActualOut)
                {
                        BOOL RetVal=FALSE;

                        switch ( dwCode ) 
                        {
                                case IOCTL_POWER_CAPABILITIES: 
                                        DBGMSG(UART_PM, (L"[UART3] +++IOCTL_POWER_CAPABILITIES\r\n"));          
                                        if (!pBufOut || dwLenOut < sizeof(POWER_CAPABILITIES) || !pdwActualOut) 
                                        {
                                                SetLastError(ERROR_INVALID_PARAMETER);
                                                RetVal = FALSE;
                                                ERRMSG((L"[UART3] IOCTL_POWER_CAPABILITIES EXCEPTION\r\n"));                
                                        } 
                                        else
                                        {
                                                m_IsThisPowerManaged = TRUE;
                                                PPOWER_CAPABILITIES ppc = (PPOWER_CAPABILITIES)pBufOut;        
                                                *ppc= GetPowerCapabilities();
                                                if (pdwActualOut)
                                                {
                                                        *pdwActualOut = sizeof(POWER_CAPABILITIES);
                                                }
                                                RetVal = TRUE;
                                        }
                                        DBGMSG(UART_PM, (L"[UART3] ---IOCTL_POWER_CAPABILITIES\r\n"));                      
                                        break;

                                case IOCTL_POWER_SET:
                                        DBGMSG(UART_PM, (L"[UART3] +++IOCTL_POWER_SET\r\n"));

                                        if (pBufOut && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))
                                        {
                                                __try
                                                {
                                                        CEDEVICE_POWER_STATE PowerState = *(PCEDEVICE_POWER_STATE)pBufOut;
                                                        DBGMSG(UART_PM, (L"[UART3] IOCTL_POWER_SET : D%d \r\n", PowerState));

                                                        if (VALID_DX(PowerState))
                                                        {
                                                                *pdwActualOut = sizeof(CEDEVICE_POWER_STATE);
                                                                *(PCEDEVICE_POWER_STATE) pBufOut = SetPowerState(PowerState);
                                                                RetVal = TRUE;
                                                        }
                                                }
                                                __except(EXCEPTION_EXECUTE_HANDLER)
                                                {
                                                        ERRMSG((L"[UART3] IOCTL_POWER_SET EXCEPTION\r\n"));
                                                        RetVal = FALSE;
                                                }
                                        }

                                        DBGMSG(UART_PM, (L"[UART3] ---IOCTL_POWER_SET\r\n"));               
                                        break;

                                case IOCTL_POWER_GET:
                                        DBGMSG(UART_PM, (L"[UART3] +++IOCTL_POWER_GET\r\n"));

                                        if (pBufOut != NULL && dwLenOut >= sizeof(CEDEVICE_POWER_STATE))
                                        {
                                                __try
                                                {
                                                        *(PCEDEVICE_POWER_STATE)pBufOut = GetPowerState();
                                                        RetVal = TRUE;
                                                        DBGMSG(UART_PM, (L"[UART3] IOCTL_POWER_GET : D%d \r\n", *pBufOut));
                                                }
                                                __except(EXCEPTION_EXECUTE_HANDLER)
                                                {
                                                        ERRMSG((L"[UART3] IOCTL_POWER_GET EXCEPTION\r\n"));
                                                        RetVal = FALSE;
                                                }
                                        }

                                        DBGMSG(UART_PM, (L"[UART3] ---IOCTL_POWER_GET\r\n"));
                                        break;

                                case IOCTL_REQUEST_UART_SAVE_POWER:
                                        DBGMSG(UART_PM, (L"[UART3] +++IOCTL_REQUEST_UART_SAVE_POWER\r\n"));

                                        __try
                                        {
                                                DevicePowerNotify(UART3_POWER_NAME, D4, POWER_NAME);
                                                RetVal = TRUE;
                                                DBGMSG(UART_PM, (L"[UART3] IOCTL_REQUEST_UART_SAVE_POWER \r\n"));

                                        }
                                        __except(EXCEPTION_EXECUTE_HANDLER)
                                        {
                                                ERRMSG((L"[UART3] IOCTL_REQUEST_UART_SAVE_POWER EXCEPTION\r\n"));
                                                RetVal = FALSE;
                                        }


                                        DBGMSG(UART_PM, (L"[UART3] ---IOCTL_REQUEST_UART_SAVE_POWER\r\n"));
                                        break;

                                case IOCTL_REQUEST_UART_FULL_POWER:
                                        DBGMSG(UART_PM, (L"[UART3] +++IOCTL_REQUEST_UART_FULL_POWER\r\n"));

                                        __try
                                        {
                                                DevicePowerNotify(UART3_POWER_NAME, D0, POWER_NAME);
                                                RetVal = TRUE;
                                                DBGMSG(UART_PM, (L"[UART3] IOCTL_REQUEST_UART_FULL_POWER \r\n"));

                                        }
                                        __except(EXCEPTION_EXECUTE_HANDLER)
                                        {
                                                ERRMSG((L"[UART3] IOCTL_REQUEST_UART_FULL_POWER EXCEPTION\r\n"));
                                                RetVal = FALSE;
                                        }


                                        DBGMSG(UART_PM, (L"[UART3] ---IOCTL_REQUEST_UART_FULL_POWER\r\n"));
                                        break;


                                default:
                                        SetLastError(ERROR_INVALID_PARAMETER);
                                        RetVal = FALSE;
                                        break;
                        }
                        return RetVal;
                }

                virtual BOOL InitialPower(BOOL bInit)
                {

                        m_PowerState=D0;
                        m_IsThisPowerManaged=FALSE;
                        m_PowerCapabilities.DeviceDx = DX_MASK(D0) | DX_MASK(D2)| DX_MASK(D3) | DX_MASK(D4);

                        return TRUE;
                }

        volatile GPIO_REG * m_pIOPregs;
        volatile CMU_CLK_REG * m_pSysconRegs;

        private:
                HANDLE              m_hPwrControl;  
                HANDLE              m_hPwrMsgQue;
};

CSerialPDD * CreateSerialObject(LPTSTR lpActivePath, PVOID pMdd,PHWOBJ pHwObj, DWORD DeviceArrayIndex)
{
        CSerialPDD * pSerialPDD = NULL;
        DBGMSG( UART_INFO, (TEXT("[UART] [CreateSerialObject] %d\r\n"), DeviceArrayIndex)); 
        switch (DeviceArrayIndex)
        {
            case 0:        // UART0
                pSerialPDD = new CPddSerial0(lpActivePath,pMdd, pHwObj);
		        break;
            case 1:        // UART1
                pSerialPDD = new CPddSerial1(lpActivePath,pMdd, pHwObj);
                break;
            case 2:        // UART2
                pSerialPDD = new CPddSerial2(lpActivePath, pMdd, pHwObj);
                break;
            case 3:        // UART3
                pSerialPDD = new CPddSerial3(lpActivePath, pMdd, pHwObj);
                break;
        }
        if (pSerialPDD && !pSerialPDD->Init())
        {
                delete pSerialPDD;
                pSerialPDD = NULL;
        }    
        return pSerialPDD;
}
void DeleteSerialObject(CSerialPDD * pSerialPDD)
{
        if (pSerialPDD)
        {
                delete pSerialPDD;
        }
}

