//#include <ntddk.h> // in here, the use of header file is only on the type define.
#include <linux/kernel.h>

#include <linux/spinlock.h>
//#include <asm/semaphore.h>  // for 2.6.18
#include <linux/semaphore.h>
#include <linux/completion.h>

#include <linux/time.h>

#include "DriverInfo.h"

#include "SPtype.h"
#include "funcresult.h"

#include "DrvDebug.h"
#include "SystemPorting.h"
#include "BusDeviceIO.h"

#include "HwiEUART.h"
#include "HwdEUART.h"

// in Hwc level, we dont check Hwi func.

//HwdEUART    g_sHwdEUART;

FRSTATUS
HwcEUART_Initialize(
    IN      PHwcEUART           hHwcEUART,
    IN      PMappedBusAddress   hMappedRegisters,
    IN      PMappedBusAddress   hMappedRegisters_DMA
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    hHwcEUART->hMappedRegisters = hMappedRegisters;
    hHwcEUART->hMappedRegisters_DMA = hMappedRegisters_DMA;
    
    hHwcEUART->BRDIV = 0;
    SPZeroMemory(&hHwcEUART->sHwcEUARTFIFOConfigure, sizeof(hHwcEUART->sHwcEUARTFIFOConfigure));
    SPZeroMemory(&hHwcEUART->sHwcEUARTPortConfigure, sizeof(hHwcEUART->sHwcEUARTPortConfigure));
    SPZeroMemory(&hHwcEUART->sHwcEUARTInterrupt, sizeof(hHwcEUART->sHwcEUARTInterrupt));
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_InitHW(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    ULONG                       i;
    
    HwiLineControlReg           sHwiLineControlReg;
    HwiDivisorLatchLowReg       sHwiDivisorLatchLowReg;
    HwiDivisorLatchHighReg      sHwiDivisorLatchHighReg;
    HwiInterruptEnableReg       sHwiInterruptEnableReg;
    HwiFIFOControlReg           sHwiFIFOControlReg;
    HwiModemControlReg          sHwiModemControlReg;
    HwiLineStatusReg            sHwiLineStatusReg;
    HwiModemStatusReg           sHwiModemStatusReg;
    HwiReceiverBufferReg        sHwiReceiverBufferReg;
    HwiInterruptIdentificationReg   sHwiInterruptIdentificationReg;
    
    
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    // initialize hardware, off & reset
    
    // reset Modem control
    SPZeroMemory(&sHwiModemControlReg, sizeof(HwiModemControlReg));
    
    _SetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemControlReg
        );
    
    // disable interrupt
    SPZeroMemory(&sHwiInterruptEnableReg, sizeof(HwiInterruptEnableReg));
    
    _SetHwiInterruptEnableReg(
        hHwcEUART->hMappedRegisters,
        &sHwiInterruptEnableReg
        );
    
    // initialize port setting & DivisorLatchAccess = 1
    SPZeroMemory(&sHwiLineControlReg, sizeof(HwiLineControlReg));
    sHwiLineControlReg.DivisorLatchAccess = 1;
    
    _SetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    // set BRDIV = 0x900
    SPZeroMemory(&sHwiDivisorLatchLowReg, sizeof(HwiDivisorLatchLowReg));
    SPZeroMemory(&sHwiDivisorLatchHighReg, sizeof(HwiDivisorLatchHighReg));
    sHwiDivisorLatchHighReg.Data = 0x09;
    sHwiDivisorLatchLowReg.Data = 0x00;
    
    _SetHwiDivisorLatchHighReg(
        hHwcEUART->hMappedRegisters,
        &sHwiDivisorLatchHighReg
        );
        
    _SetHwiDivisorLatchLowReg(
        hHwcEUART->hMappedRegisters,
        &sHwiDivisorLatchLowReg
        );
    
    // DivisorLatchAccess = 0
    sHwiLineControlReg.DivisorLatchAccess = 0;
    
    _SetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    // reset FIFO and disable FIFO
    SPZeroMemory(&sHwiFIFOControlReg, sizeof(HwiFIFOControlReg));
    sHwiFIFOControlReg.RxFIFOReset = 1;
    sHwiFIFOControlReg.TxFIFOReset = 1;
    
    _SetHwiFIFOControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiFIFOControlReg
        );
    
    // clear RxBuffer
    SPZeroMemory(&sHwiReceiverBufferReg, sizeof(HwiReceiverBufferReg));
    
    _GetHwiReceiverBufferReg(
        hHwcEUART->hMappedRegisters,
        &sHwiReceiverBufferReg
        );
    
    // clear Line Status
    SPZeroMemory(&sHwiLineStatusReg, sizeof(HwiLineStatusReg));
    
    _GetHwiLineStatusReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineStatusReg
        );
    
    // clear Modem statue
    SPZeroMemory(&sHwiModemStatusReg, sizeof(HwiModemStatusReg));
    
    _GetHwiModemStatusReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemStatusReg
        );
    
    i = 0;
    // clear pending interrupts
    while(i != 10)
    {
        i += 1;
        SPZeroMemory(&sHwiInterruptIdentificationReg, sizeof(HwiInterruptIdentificationReg));
        
        _GetHwiInterruptIdentificationReg(
            hHwcEUART->hMappedRegisters,
            &sHwiInterruptIdentificationReg
            );
        
        if (sHwiInterruptIdentificationReg.NoPending == 0)
        {
            switch(sHwiInterruptIdentificationReg.ID)
            {
                case EUARTInterruptID_ModemStatus:
                {
                    SPZeroMemory(&sHwiModemStatusReg, sizeof(HwiModemStatusReg));
                    
                    _GetHwiModemStatusReg(
                        hHwcEUART->hMappedRegisters,
                        &sHwiModemStatusReg
                        );
                }
                break;
                
                case EUARTInterruptID_TransmitterHoldingEmpty:
                {
                    
                }
                break;
                
                case EUARTInterruptID_ReceivedDataAvailable:
                {
                    SPZeroMemory(&sHwiReceiverBufferReg, sizeof(HwiReceiverBufferReg));
                    
                    _GetHwiReceiverBufferReg(
                        hHwcEUART->hMappedRegisters,
                        &sHwiReceiverBufferReg
                        );
                }
                break;
                
                case EUARTInterruptID_LineStatus:
                {
                    SPZeroMemory(&sHwiLineStatusReg, sizeof(HwiLineStatusReg));
                    
                    _GetHwiLineStatusReg(
                        hHwcEUART->hMappedRegisters,
                        &sHwiLineStatusReg
                        );
                }
                break;
                
                case EUARTInterruptID_CharacterTimeout:
                {
                    SPZeroMemory(&sHwiReceiverBufferReg, sizeof(HwiReceiverBufferReg));
                    
                    _GetHwiReceiverBufferReg(
                        hHwcEUART->hMappedRegisters,
                        &sHwiReceiverBufferReg
                        );
                }
                break;
            }
        }
        else
        {
            break;
        }
    }
    
    
    
    // wait for the action done.
    //while(1)
    {
        {
            //break;
        }
    }
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_ShowAll(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiLineControlReg           sHwiLineControlReg;
    HwiDivisorLatchLowReg       sHwiDivisorLatchLowReg;
    HwiDivisorLatchHighReg      sHwiDivisorLatchHighReg;
    HwiInterruptEnableReg       sHwiInterruptEnableReg;
    HwiFIFOControlReg           sHwiFIFOControlReg;
    HwiModemControlReg          sHwiModemControlReg;
    HwiLineStatusReg            sHwiLineStatusReg;
    HwiModemStatusReg           sHwiModemStatusReg;
    HwiReceiverBufferReg        sHwiReceiverBufferReg;
    HwiInterruptIdentificationReg   sHwiInterruptIdentificationReg;
    
    
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    // HwiInterruptEnableReg
    _GetHwiInterruptEnableReg(
        hHwcEUART->hMappedRegisters,
        &sHwiInterruptEnableReg
        );

    _ShowHwiInterruptEnableReg(
        &sHwiInterruptEnableReg
        );
    
    // HwiInterruptIdentificationReg
    _GetHwiInterruptIdentificationReg(
        hHwcEUART->hMappedRegisters,
        &sHwiInterruptIdentificationReg
        );
    
    _ShowHwiInterruptIdentificationReg(
        &sHwiInterruptIdentificationReg
        );
    
    // HwiFIFOControlReg
    /*_GetHwiFIFOControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiFIFOControlReg
        );
    
    _ShowHwiFIFOControlReg(
        &sHwiFIFOControlReg
        );*/
    
    // HwiLineControlReg
    _GetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    _ShowHwiLineControlReg(
        &sHwiLineControlReg
        );
        
    sHwiLineControlReg.DivisorLatchAccess = 1;
    
    _SetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    _GetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    _ShowHwiLineControlReg(
        &sHwiLineControlReg
        );
    
    _GetHwiDivisorLatchHighReg(
        hHwcEUART->hMappedRegisters,
        &sHwiDivisorLatchHighReg
        );
        
    _GetHwiDivisorLatchLowReg(
        hHwcEUART->hMappedRegisters,
        &sHwiDivisorLatchLowReg
        );
    
    _ShowHwiDivisorLatchHighReg(
        &sHwiDivisorLatchHighReg
        );
        
    _ShowHwiDivisorLatchLowReg(
        &sHwiDivisorLatchLowReg
        );
    
    sHwiLineControlReg.DivisorLatchAccess = 0;
    
    _SetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    // HwiModemControlReg
    _GetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemControlReg
        );
    
    _ShowHwiModemControlReg(
        &sHwiModemControlReg
        );
    
    // HwiLineStatusReg
    _GetHwiLineStatusReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineStatusReg
        );
    
    _ShowHwiLineStatusReg(
        &sHwiLineStatusReg
        );
    
    // HwiModemStatusReg
    _GetHwiModemStatusReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemStatusReg
        );
    
    _ShowHwiModemStatusReg(
        &sHwiModemStatusReg
        );
        
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetBaudRateDIV(
    IN      PHwcEUART                   hHwcEUART,
    IN      ULONG                       BRDIV
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiLineControlReg           sHwiLineControlReg;
    HwiDivisorLatchLowReg       sHwiDivisorLatchLowReg;
    HwiDivisorLatchHighReg      sHwiDivisorLatchHighReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    hHwcEUART->BRDIV = BRDIV;
    
    // DivisorLatchAccess = 1
    SPZeroMemory(&sHwiLineControlReg, sizeof(HwiLineControlReg));
    _GetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    sHwiLineControlReg.DivisorLatchAccess = 1;
    
    _SetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    // set BRDIV
    SPZeroMemory(&sHwiDivisorLatchLowReg, sizeof(HwiDivisorLatchLowReg));
    SPZeroMemory(&sHwiDivisorLatchHighReg, sizeof(HwiDivisorLatchHighReg));
    sHwiDivisorLatchHighReg.Data = (BRDIV >> 8);
    sHwiDivisorLatchLowReg.Data = (BRDIV & 0x00FF);
    
    _SetHwiDivisorLatchHighReg(
        hHwcEUART->hMappedRegisters,
        &sHwiDivisorLatchHighReg
        );
        
    _SetHwiDivisorLatchLowReg(
        hHwcEUART->hMappedRegisters,
        &sHwiDivisorLatchLowReg
        );
    
    // DivisorLatchAccess = 0
    sHwiLineControlReg.DivisorLatchAccess = 0;
    
    _SetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetFIFOConfigure(
    IN      PHwcEUART                   hHwcEUART,
    IN      PHwcEUARTFIFOConfigure      pHwcEUARTFIFOConfigure
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiFIFOControlReg           sHwiFIFOControlReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    hHwcEUART->sHwcEUARTFIFOConfigure = *pHwcEUARTFIFOConfigure;
    
    // set FIFO
    SPZeroMemory(&sHwiFIFOControlReg, sizeof(HwiFIFOControlReg));
    sHwiFIFOControlReg.FIFOEnable = pHwcEUARTFIFOConfigure->FIFOEnable;
    sHwiFIFOControlReg.RxFIFOReset = 1;
    sHwiFIFOControlReg.TxFIFOReset = 1;
    sHwiFIFOControlReg.RxFIFOTriggerLevel = pHwcEUARTFIFOConfigure->RxFIFOTriggerLevel;
    
    _SetHwiFIFOControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiFIFOControlReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_GetFIFOConfigure(
    IN      PHwcEUART                   hHwcEUART,
        OUT PHwcEUARTFIFOConfigure      pHwcEUARTFIFOConfigure
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    *pHwcEUARTFIFOConfigure = hHwcEUART->sHwcEUARTFIFOConfigure;
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetPortConfigure(
    IN      PHwcEUART                   hHwcEUART,
    IN      PHwcEUARTPortConfigure      pHwcEUARTPortConfigure
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiLineControlReg           sHwiLineControlReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    hHwcEUART->sHwcEUARTPortConfigure = *pHwcEUARTPortConfigure;
    
    // port setting
    SPZeroMemory(&sHwiLineControlReg, sizeof(HwiLineControlReg));
    sHwiLineControlReg.WordLengthSelect = pHwcEUARTPortConfigure->WordLengthSelect;
    sHwiLineControlReg.StopBitsSelect = pHwcEUARTPortConfigure->StopBitsSelect;
    sHwiLineControlReg.ParityEnable = pHwcEUARTPortConfigure->ParityEnable;
    sHwiLineControlReg.ParitySelect = pHwcEUARTPortConfigure->ParitySelect;
    sHwiLineControlReg.TransmitBreak = 0;
    sHwiLineControlReg.DivisorLatchAccess = 0;
    
    _SetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_GetPortConfigure(
    IN      PHwcEUART                   hHwcEUART,
        OUT PHwcEUARTPortConfigure      pHwcEUARTPortConfigure
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    *pHwcEUARTPortConfigure = hHwcEUART->sHwcEUARTPortConfigure;
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}




FRSTATUS
HwcEUART_SetInterruptEnable(
    IN      PHwcEUART                   hHwcEUART,
    IN      PHwcEUARTInterrupt          pHwcEUARTInterrupt
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiInterruptEnableReg       sHwiInterruptEnableReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    hHwcEUART->sHwcEUARTInterrupt = *pHwcEUARTInterrupt;
    
    SPZeroMemory(&sHwiInterruptEnableReg, sizeof(HwiInterruptEnableReg));
    sHwiInterruptEnableReg.ReceivedDataAvailable = pHwcEUARTInterrupt->ReceivedDataAvailable;
    sHwiInterruptEnableReg.TransmitterHoldingEmpty = pHwcEUARTInterrupt->TransmitterHoldingEmpty;
    sHwiInterruptEnableReg.LineStatus = pHwcEUARTInterrupt->LineStatus;
    sHwiInterruptEnableReg.ModemStatus = pHwcEUARTInterrupt->ModemStatus;
    
    _SetHwiInterruptEnableReg(
        hHwcEUART->hMappedRegisters,
        &sHwiInterruptEnableReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}

FRSTATUS
HwcEUART_GetInterruptEnable(
    IN      PHwcEUART                   hHwcEUART,
        OUT PHwcEUARTInterrupt          pHwcEUARTInterrupt
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    *pHwcEUARTInterrupt = hHwcEUART->sHwcEUARTInterrupt;
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_GetInterruptStatus(
    IN      PHwcEUART                   hHwcEUART,
        OUT PHwcEUARTInterruptStatus    pHwcEUARTInterruptStatus
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiInterruptIdentificationReg   sHwiInterruptIdentificationReg;
    
    //HwiLineStatusReg                sHwiLineStatusReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    // for optimization
    //SPZeroMemory(&sHwiInterruptIdentificationReg, sizeof(HwiInterruptIdentificationReg));
    
    _GetHwiInterruptIdentificationReg(
        hHwcEUART->hMappedRegisters,
        &sHwiInterruptIdentificationReg
        );
    
    pHwcEUARTInterruptStatus->ReceivedDataAvailable = 0;
    pHwcEUARTInterruptStatus->TransmitterHoldingEmpty = 0;
    pHwcEUARTInterruptStatus->LineStatus = 0;
    pHwcEUARTInterruptStatus->ModemStatus = 0;
    pHwcEUARTInterruptStatus->CharacterTimeout = 0;
    
    if (sHwiInterruptIdentificationReg.NoPending == 0)
    {
        switch(sHwiInterruptIdentificationReg.ID)
        {
            case EUARTInterruptID_ModemStatus:
            {
                pHwcEUARTInterruptStatus->ModemStatus = 1;
            }
            break;
            
            case EUARTInterruptID_TransmitterHoldingEmpty:
            {
                pHwcEUARTInterruptStatus->TransmitterHoldingEmpty = 1;
            }
            break;
            
            case EUARTInterruptID_ReceivedDataAvailable:
            {
                pHwcEUARTInterruptStatus->ReceivedDataAvailable = 1;
            }
            break;
            
            case EUARTInterruptID_LineStatus:
            {
                pHwcEUARTInterruptStatus->LineStatus = 1;
            }
            break;
            
            case EUARTInterruptID_CharacterTimeout:
            {
                pHwcEUARTInterruptStatus->CharacterTimeout = 1;
            }
            break;
        }
    }
    else
    {
        
    }
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_ClearPendingInterrupts(
    IN      PHwcEUART                   hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    ULONG                       i;
    
    HwiInterruptIdentificationReg   sHwiInterruptIdentificationReg;
    HwiModemStatusReg               sHwiModemStatusReg;
    HwiReceiverBufferReg            sHwiReceiverBufferReg;
    HwiLineStatusReg                sHwiLineStatusReg;
    
    
    
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    i = 0;
    // clear pending interrupts
    while(i != 10)
    {
        i += 1;
        SPZeroMemory(&sHwiInterruptIdentificationReg, sizeof(HwiInterruptIdentificationReg));
        
        _GetHwiInterruptIdentificationReg(
            hHwcEUART->hMappedRegisters,
            &sHwiInterruptIdentificationReg
            );
        
        if (sHwiInterruptIdentificationReg.NoPending == 0)
        {
            switch(sHwiInterruptIdentificationReg.ID)
            {
                case EUARTInterruptID_ModemStatus:
                {
                    SPZeroMemory(&sHwiModemStatusReg, sizeof(HwiModemStatusReg));
                    
                    _GetHwiModemStatusReg(
                        hHwcEUART->hMappedRegisters,
                        &sHwiModemStatusReg
                        );
                }
                break;
                
                case EUARTInterruptID_TransmitterHoldingEmpty:
                {
                    
                }
                break;
                
                case EUARTInterruptID_ReceivedDataAvailable:
                {
                    SPZeroMemory(&sHwiReceiverBufferReg, sizeof(HwiReceiverBufferReg));
                    
                    _GetHwiReceiverBufferReg(
                        hHwcEUART->hMappedRegisters,
                        &sHwiReceiverBufferReg
                        );
                }
                break;
                
                case EUARTInterruptID_LineStatus:
                {
                    SPZeroMemory(&sHwiLineStatusReg, sizeof(HwiLineStatusReg));
                    
                    _GetHwiLineStatusReg(
                        hHwcEUART->hMappedRegisters,
                        &sHwiLineStatusReg
                        );
                }
                break;
                
                case EUARTInterruptID_CharacterTimeout:
                {
                    SPZeroMemory(&sHwiReceiverBufferReg, sizeof(HwiReceiverBufferReg));
                    
                    _GetHwiReceiverBufferReg(
                        hHwcEUART->hMappedRegisters,
                        &sHwiReceiverBufferReg
                        );
                }
                break;
            }
        }
        else
        {
            break;
        }
    }
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_ResetInterrupt(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiInterruptEnableReg       sHwiInterruptEnableReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiInterruptEnableReg, sizeof(HwiInterruptEnableReg));
    
    _SetHwiInterruptEnableReg(
        hHwcEUART->hMappedRegisters,
        &sHwiInterruptEnableReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_ResetFIFOControl(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiFIFOControlReg           sHwiFIFOControlReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiFIFOControlReg, sizeof(HwiFIFOControlReg));
    
    _SetHwiFIFOControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiFIFOControlReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_ResetLineControl(
    IN      PHwcEUART               hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiLineControlReg           sHwiLineControlReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiLineControlReg, sizeof(HwiLineControlReg));
    
    _SetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_ResetModemControl(
    IN      PHwcEUART               hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiModemControlReg          sHwiModemControlReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiModemControlReg, sizeof(HwiModemControlReg));
    
    _SetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemControlReg
        );
    
    SPZeroMemory(&hHwcEUART->sHwiModemControlReg, sizeof(HwiModemControlReg));
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_ReadRxBuffer8(
    IN      PHwcEUART           hHwcEUART,
        OUT PULONG              pData
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiReceiverBufferReg        sHwiReceiverBufferReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    // for optimization
    //SPZeroMemory(&sHwiReceiverBufferReg, sizeof(HwiReceiverBufferReg));
    
    _GetHwiReceiverBufferReg(
        hHwcEUART->hMappedRegisters,
        &sHwiReceiverBufferReg
        );
    
    *pData = sHwiReceiverBufferReg.Data;
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_WriteTxBuffer8(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               Data
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiTransmitterHoldingReg    sHwiTransmitterHoldingReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiTransmitterHoldingReg, sizeof(HwiTransmitterHoldingReg));
    
    sHwiTransmitterHoldingReg.Data = Data;
    
    _SetHwiTransmitterHoldingReg(
        hHwcEUART->hMappedRegisters,
        &sHwiTransmitterHoldingReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_ReadLineStatus(
    IN      PHwcEUART               hHwcEUART,
        OUT PHwcEUARTLineStatus     pHwcEUARTLineStatus
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiLineStatusReg            sHwiLineStatusReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    // for optimization
    //SPZeroMemory(&sHwiLineStatusReg, sizeof(HwiLineStatusReg));
    
    _GetHwiLineStatusReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineStatusReg
        );
    
    pHwcEUARTLineStatus->DataReady = sHwiLineStatusReg.DataReady;
    pHwcEUARTLineStatus->OverrunError = sHwiLineStatusReg.OverrunError;
    pHwcEUARTLineStatus->ParityError = sHwiLineStatusReg.ParityError;
    pHwcEUARTLineStatus->FamingError = sHwiLineStatusReg.FamingError;
    pHwcEUARTLineStatus->BreakSignal = sHwiLineStatusReg.BreakSignal;
    pHwcEUARTLineStatus->TransmitterHodingEmpty = sHwiLineStatusReg.TransmitterHodingEmpty;
    pHwcEUARTLineStatus->TransmitterEmpty = sHwiLineStatusReg.TransmitterEmpty;
    pHwcEUARTLineStatus->ErrorInRxFIFO = sHwiLineStatusReg.ErrorInRxFIFO;
    
    /* for debug
    if (sHwiLineStatusReg.OverrunError)
    {
        sHwiLineStatusReg.OverrunError = sHwiLineStatusReg.OverrunError;
    }
    
    if (sHwiLineStatusReg.ErrorInRxFIFO)
    {
        sHwiLineStatusReg.ErrorInRxFIFO = sHwiLineStatusReg.ErrorInRxFIFO;
    }
    
    if (sHwiLineStatusReg.FamingError)
    {
        sHwiLineStatusReg.FamingError = sHwiLineStatusReg.FamingError;
    }*/
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_ReadModemStatus(
    IN      PHwcEUART               hHwcEUART,
        OUT PHwcEUARTModemStatus    pHwcEUARTModemStatus
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiModemStatusReg           sHwiModemStatusReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    // for optimization
    //SPZeroMemory(&sHwiModemStatusReg, sizeof(HwiModemStatusReg));
    
    _GetHwiModemStatusReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemStatusReg
        );
    
    pHwcEUARTModemStatus->CTSChange = sHwiModemStatusReg.CTSChange;
    pHwcEUARTModemStatus->DSRChange = sHwiModemStatusReg.DSRChange;
    pHwcEUARTModemStatus->RIChange = sHwiModemStatusReg.RIChange;
    pHwcEUARTModemStatus->DCDChange = sHwiModemStatusReg.DCDChange;
    pHwcEUARTModemStatus->CTS = sHwiModemStatusReg.CTS;
    pHwcEUARTModemStatus->DSR = sHwiModemStatusReg.DSR;
    pHwcEUARTModemStatus->RI = sHwiModemStatusReg.RI;
    pHwcEUARTModemStatus->DCD = sHwiModemStatusReg.DCD;
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_StartTransmitBreak(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiLineControlReg           sHwiLineControlReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiLineControlReg, sizeof(HwiLineControlReg));
    
    _GetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    sHwiLineControlReg.TransmitBreak = 1;
    
    _SetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_StopTransmitBreak(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiLineControlReg           sHwiLineControlReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiLineControlReg, sizeof(HwiLineControlReg));
    
    _GetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    sHwiLineControlReg.TransmitBreak = 0;
    
    _SetHwiLineControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiLineControlReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetDTRPin(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               DTRPin      // 0: High, 1: Low
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiModemControlReg          sHwiModemControlReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    hHwcEUART->sHwiModemControlReg.DTRPin = DTRPin;
    
    _SetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &hHwcEUART->sHwiModemControlReg
        );
    
    /*
    SPZeroMemory(&sHwiModemControlReg, sizeof(HwiModemControlReg));
    
    _GetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemControlReg
        );
    
    sHwiModemControlReg.DTRPin = DTRPin;
    
    _SetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemControlReg
        );
    */
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetRTSPin(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               RTSPin      // 0: High, 1: Low
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiModemControlReg          sHwiModemControlReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    hHwcEUART->sHwiModemControlReg.RTSPin = RTSPin;
    
    _SetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &hHwcEUART->sHwiModemControlReg
        );
    
    /*
    SPZeroMemory(&sHwiModemControlReg, sizeof(HwiModemControlReg));
    
    _GetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemControlReg
        );
    
    sHwiModemControlReg.RTSPin = RTSPin;
    
    _SetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemControlReg
        );
    */
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetOut1Pin(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               Out1Pin     // 0: High, 1: Low
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiModemControlReg          sHwiModemControlReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    hHwcEUART->sHwiModemControlReg.Out1Pin = Out1Pin;
    
    _SetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &hHwcEUART->sHwiModemControlReg
        );
    
    /*
    SPZeroMemory(&sHwiModemControlReg, sizeof(HwiModemControlReg));
    
    _GetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemControlReg
        );
    
    sHwiModemControlReg.Out1Pin = Out1Pin;
    
    _SetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemControlReg
        );
    */
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetOut2Pin(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               Out2Pin     // 0: High, 1: Low
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiModemControlReg          sHwiModemControlReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    hHwcEUART->sHwiModemControlReg.Out2Pin = Out2Pin;
    
    _SetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &hHwcEUART->sHwiModemControlReg
        );
    
    /*
    SPZeroMemory(&sHwiModemControlReg, sizeof(HwiModemControlReg));
    
    _GetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemControlReg
        );
    
    sHwiModemControlReg.Out2Pin = Out2Pin;
    
    _SetHwiModemControlReg(
        hHwcEUART->hMappedRegisters,
        &sHwiModemControlReg
        );
    */
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetScratchpad(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               Data
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiScratchpadReg            sHwiScratchpadReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiScratchpadReg, sizeof(HwiScratchpadReg));
    
    sHwiScratchpadReg.Data = Data;
    
    _SetHwiScratchpadReg(
        hHwcEUART->hMappedRegisters,
        &sHwiScratchpadReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_GetScratchpad(
    IN      PHwcEUART           hHwcEUART,
        OUT PULONG              pData
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiScratchpadReg            sHwiScratchpadReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    //if (hHwcEUART == NULL)
    //{
        //funcresult = FR_Error;
        //goto funcexit;
    //}
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiScratchpadReg, sizeof(HwiScratchpadReg));
    
    _GetHwiScratchpadReg(
        hHwcEUART->hMappedRegisters,
        &sHwiScratchpadReg
        );
    
    *pData = sHwiScratchpadReg.Data;
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_HardResetDMA(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl0Reg           sHwiDMAControl0Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl0Reg, sizeof(HwiDMAControl0Reg));
    
    _GetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    sHwiDMAControl0Reg.DebugBit = 0;
    sHwiDMAControl0Reg.HardReset = 1;
    
    _SetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    _GetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    sHwiDMAControl0Reg.HardReset = 0;
    
    _SetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_DMADebugBit(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               DebugBit
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl0Reg           sHwiDMAControl0Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl0Reg, sizeof(HwiDMAControl0Reg));
    
    _GetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    sHwiDMAControl0Reg.DebugBit = DebugBit;
    
    _SetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_EnableDMA(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl0Reg           sHwiDMAControl0Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl0Reg, sizeof(HwiDMAControl0Reg));
    
    _GetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    sHwiDMAControl0Reg.DMAEnable = 1;
    
    _SetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    _GetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    if (sHwiDMAControl0Reg.DMAEnable != 1)
    {
        HwcEUART_DMADebugBit(hHwcEUART, 1);
    }
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_DisableDMA(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl0Reg           sHwiDMAControl0Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl0Reg, sizeof(HwiDMAControl0Reg));
    
    _GetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    sHwiDMAControl0Reg.DMAEnable = 0;
    
    _SetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetRxSegmentTriggerLevel(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               RxSegmentTriggerLevel
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl0Reg           sHwiDMAControl0Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl0Reg, sizeof(HwiDMAControl0Reg));
    
    _GetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    sHwiDMAControl0Reg.RxSegmentTriggerLevel = RxSegmentTriggerLevel;
    
    _SetHwiDMAControl0Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_GetTxSegmentReady(
    IN      PHwcEUART           hHwcEUART,
        OUT PULONG              pTxSegment0Ready,
        OUT PULONG              pTxSegment1Ready
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl1Reg           sHwiDMAControl1Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl1Reg, sizeof(HwiDMAControl1Reg));
    
    _GetHwiDMAControl1Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl1Reg
        );
    
    *pTxSegment0Ready = sHwiDMAControl1Reg.TxSegment0Ready;
    
    *pTxSegment1Ready = sHwiDMAControl1Reg.TxSegment1Ready;
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_GetRxSegmentReady(
    IN      PHwcEUART           hHwcEUART,
        OUT PULONG              pRxSegment0Ready,
        OUT PULONG              pRxSegment1Ready
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl1Reg           sHwiDMAControl1Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl1Reg, sizeof(HwiDMAControl1Reg));
    
    _GetHwiDMAControl1Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl1Reg
        );
    
    *pRxSegment0Ready = sHwiDMAControl1Reg.RxSegment0Ready;
    
    *pRxSegment1Ready = sHwiDMAControl1Reg.RxSegment1Ready;
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_TxSegment0Ready(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl1Reg           sHwiDMAControl1Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl1Reg, sizeof(HwiDMAControl1Reg));
    
    sHwiDMAControl1Reg.TxSegment0Ready = 1;
    
    _SetHwiDMAControl1Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl1Reg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_TxSegment1Ready(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl1Reg           sHwiDMAControl1Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl1Reg, sizeof(HwiDMAControl1Reg));
    
    sHwiDMAControl1Reg.TxSegment1Ready = 1;
    
    _SetHwiDMAControl1Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl1Reg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_RxSegment0Ready(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl1Reg           sHwiDMAControl1Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl1Reg, sizeof(HwiDMAControl1Reg));
    
    sHwiDMAControl1Reg.RxSegment0Ready = 1;
    
    _SetHwiDMAControl1Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl1Reg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_RxSegment1Ready(
    IN      PHwcEUART           hHwcEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl1Reg           sHwiDMAControl1Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl1Reg, sizeof(HwiDMAControl1Reg));
    
    sHwiDMAControl1Reg.RxSegment1Ready = 1;
    
    _SetHwiDMAControl1Reg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl1Reg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_GetDMAStatus(
    IN      PHwcEUART           hHwcEUART,
        OUT PHwcEUARTDMAStatus  pHwcEUARTDMAStatus
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAStatusReg             sHwiDMAStatusReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAStatusReg, sizeof(HwiDMAStatusReg));
    
    _GetHwiDMAStatusReg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAStatusReg
        );
    
    pHwcEUARTDMAStatus->TxSegmentIndication = sHwiDMAStatusReg.TxSegmentIndication;
    pHwcEUARTDMAStatus->RxSegmentIndication = sHwiDMAStatusReg.RxSegmentIndication;
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetDMATxBufferAddress(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               Address32bit
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMATxBufferAddressReg    sHwiDMATxBufferAddressReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMATxBufferAddressReg, sizeof(HwiDMATxBufferAddressReg));
    
    sHwiDMATxBufferAddressReg.Address32bit = Address32bit;
    
    _SetHwiDMATxBufferAddressReg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMATxBufferAddressReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetDMARxBufferAddress(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               Address32bit
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMARxBufferAddressReg    sHwiDMARxBufferAddressReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMARxBufferAddressReg, sizeof(HwiDMARxBufferAddressReg));
    
    sHwiDMARxBufferAddressReg.Address32bit = Address32bit;
    
    _SetHwiDMARxBufferAddressReg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMARxBufferAddressReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetDMAInterruptEnable(
    IN      PHwcEUART               hHwcEUART,
    IN      PHwcEUARTDMAInterrupt   pHwcEUARTDMAInterrupt
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAInterruptEnableReg    sHwiDMAInterruptEnableReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAInterruptEnableReg, sizeof(HwiDMAInterruptEnableReg));
    
    sHwiDMAInterruptEnableReg.TxSegment = pHwcEUARTDMAInterrupt->TxSegment;
    sHwiDMAInterruptEnableReg.RxSegment = pHwcEUARTDMAInterrupt->RxSegment;
    sHwiDMAInterruptEnableReg.ModemStatus = pHwcEUARTDMAInterrupt->ModemStatus;
    sHwiDMAInterruptEnableReg.RxSegmentOverrun = pHwcEUARTDMAInterrupt->RxSegmentOverrun;
    sHwiDMAInterruptEnableReg.UARTOverrun = pHwcEUARTDMAInterrupt->UARTOverrun;
    
    _SetHwiDMAInterruptEnableReg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAInterruptEnableReg
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_GetDMAInterruptEnable(
    IN      PHwcEUART               hHwcEUART,
        OUT PHwcEUARTDMAInterrupt   pHwcEUARTDMAInterrupt
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAInterruptEnableReg    sHwiDMAInterruptEnableReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAInterruptEnableReg, sizeof(HwiDMAInterruptEnableReg));
    
    _GetHwiDMAInterruptEnableReg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAInterruptEnableReg
        );
    
    pHwcEUARTDMAInterrupt->TxSegment = sHwiDMAInterruptEnableReg.TxSegment;
    pHwcEUARTDMAInterrupt->RxSegment = sHwiDMAInterruptEnableReg.RxSegment;
    pHwcEUARTDMAInterrupt->ModemStatus = sHwiDMAInterruptEnableReg.ModemStatus;
    pHwcEUARTDMAInterrupt->RxSegmentOverrun = sHwiDMAInterruptEnableReg.RxSegmentOverrun;
    pHwcEUARTDMAInterrupt->UARTOverrun = sHwiDMAInterruptEnableReg.UARTOverrun;
    
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_GetDMAInterruptStatus(
    IN      PHwcEUART                       hHwcEUART,
        OUT PHwcEUARTDMAInterruptStatus     pHwcEUARTDMAInterruptStatus
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAInterruptStatusReg    sHwiDMAInterruptStatusReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAInterruptStatusReg, sizeof(HwiDMAInterruptStatusReg));
    
    _GetHwiDMAInterruptStatusReg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAInterruptStatusReg
        );
    
    pHwcEUARTDMAInterruptStatus->TxSegment0 = sHwiDMAInterruptStatusReg.TxSegment0;
    pHwcEUARTDMAInterruptStatus->TxSegment1 = sHwiDMAInterruptStatusReg.TxSegment1;
    pHwcEUARTDMAInterruptStatus->RxSegment0 = sHwiDMAInterruptStatusReg.RxSegment0;
    pHwcEUARTDMAInterruptStatus->RxSegment1 = sHwiDMAInterruptStatusReg.RxSegment1;
    pHwcEUARTDMAInterruptStatus->ModemStatus = sHwiDMAInterruptStatusReg.ModemStatus;
    pHwcEUARTDMAInterruptStatus->RxSegmentOverrun = sHwiDMAInterruptStatusReg.RxSegmentOverrun;
    pHwcEUARTDMAInterruptStatus->UARTOverrun = sHwiDMAInterruptStatusReg.UARTOverrun;
    
    pHwcEUARTDMAInterruptStatus->Rx0Ready = sHwiDMAInterruptStatusReg.Rx0Ready;
    pHwcEUARTDMAInterruptStatus->Rx0LineError = sHwiDMAInterruptStatusReg.Rx0LineError;
    pHwcEUARTDMAInterruptStatus->Rx0Timeout = sHwiDMAInterruptStatusReg.Rx0Timeout;
    
    pHwcEUARTDMAInterruptStatus->Rx1Ready = sHwiDMAInterruptStatusReg.Rx1Ready;
    pHwcEUARTDMAInterruptStatus->Rx1LineError = sHwiDMAInterruptStatusReg.Rx1LineError;
    pHwcEUARTDMAInterruptStatus->Rx1Timeout = sHwiDMAInterruptStatusReg.Rx1Timeout;
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetDMAInterruptStatus(
    IN      PHwcEUART                       hHwcEUART,
    IN      PHwcEUARTDMAInterruptStatus     pHwcEUARTDMAInterruptStatus
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAInterruptStatusReg    sHwiDMAInterruptStatusReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAInterruptStatusReg, sizeof(HwiDMAInterruptStatusReg));
    
    sHwiDMAInterruptStatusReg.TxSegment0 = pHwcEUARTDMAInterruptStatus->TxSegment0;
    sHwiDMAInterruptStatusReg.TxSegment1 = pHwcEUARTDMAInterruptStatus->TxSegment1;
    sHwiDMAInterruptStatusReg.RxSegment0 = pHwcEUARTDMAInterruptStatus->RxSegment0;
    sHwiDMAInterruptStatusReg.RxSegment1 = pHwcEUARTDMAInterruptStatus->RxSegment1;
    sHwiDMAInterruptStatusReg.ModemStatus = pHwcEUARTDMAInterruptStatus->ModemStatus;
    sHwiDMAInterruptStatusReg.RxSegmentOverrun = pHwcEUARTDMAInterruptStatus->RxSegmentOverrun;
    sHwiDMAInterruptStatusReg.UARTOverrun = pHwcEUARTDMAInterruptStatus->UARTOverrun;
    
    _SetHwiDMAInterruptStatusReg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAInterruptStatusReg
        );
        
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetTx0DataLength(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               DataLength
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMATx0DataLengthReg      sHwiDMATx0DataLengthReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMATx0DataLengthReg, sizeof(HwiDMATx0DataLengthReg));
    
    sHwiDMATx0DataLengthReg.DataLength = DataLength;
    
    _SetHwiDMATx0DataLengthReg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMATx0DataLengthReg
        );
        
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_SetTx1DataLength(
    IN      PHwcEUART           hHwcEUART,
    IN      ULONG               DataLength
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMATx1DataLengthReg      sHwiDMATx1DataLengthReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMATx1DataLengthReg, sizeof(HwiDMATx1DataLengthReg));
    
    sHwiDMATx1DataLengthReg.DataLength = DataLength;
    
    _SetHwiDMATx1DataLengthReg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMATx1DataLengthReg
        );
        
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_GetRx0DataCount(
    IN      PHwcEUART           hHwcEUART,
        OUT PULONG              pDataCount
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMARx0DataCountReg       sHwiDMARx0DataCountReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMARx0DataCountReg, sizeof(HwiDMARx0DataCountReg));
    
    _GetHwiDMARx0DataCountReg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMARx0DataCountReg
        );
    
    *pDataCount = sHwiDMARx0DataCountReg.DataCount;
        
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwcEUART_GetRx1DataCount(
    IN      PHwcEUART           hHwcEUART,
        OUT PULONG              pDataCount
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMARx1DataCountReg       sHwiDMARx1DataCountReg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMARx1DataCountReg, sizeof(HwiDMARx1DataCountReg));
    
    _GetHwiDMARx1DataCountReg(
        hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMARx1DataCountReg
        );
    
    *pDataCount = sHwiDMARx1DataCountReg.DataCount;
        
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_Initialize(  // initializing struct data
    IN      PHwdEUART             hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    ULONG                       i;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    
    //
    // function body
    //
    
    // System Bus Info
    hHwdEUART->BusNumber = 0;
    hHwdEUART->DeviceNumber = 0;
    hHwdEUART->FunctionNumber = 0;
    
    // Hardware Interface
    hHwdEUART->hMappedRegisters = NULL;
    hHwdEUART->hMappedRegisters_DMA = NULL;
    
    // Hardware Core(Control)
    hHwdEUART->hHwcEUART = &hHwdEUART->sHwcEUART;
    HwcEUART_Initialize(
        hHwdEUART->hHwcEUART,
        NULL,
        NULL
        );
    
    // Driver Core Data
    hHwdEUART->DMAEnable = FALSE;
    
    SPZeroMemory(&hHwdEUART->DMACommonBuffer, sizeof(SPCommonBuffer));
    //SPZeroMemory(&hHwdEUART->DMACommonBufferTx, sizeof(SPCommonBuffer));
    //SPZeroMemory(&hHwdEUART->DMACommonBufferRx, sizeof(SPCommonBuffer));
    
    hHwdEUART->TxSegmentIndication = 0;
    hHwdEUART->RxSegmentIndication = 0;
    
    hHwdEUART->TxSegment0Ready = 0;
    hHwdEUART->TxSegment1Ready = 0;
    
    // Synchronization
    //SPSpinLock_Initialize(&hHwdEUART->sSPSpinLockDPC);
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetMappedRegisters(
    IN      PHwdEUART           hHwdEUART,
    IN      PMappedBusAddress   hMappedRegisters_UART,
    IN      PMappedBusAddress   hMappedRegisters_DMA
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    ULONG                       i;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    
    //
    // function body
    //
    
    // Hardware Interface
    hHwdEUART->hMappedRegisters = hMappedRegisters_UART;
    hHwdEUART->hMappedRegisters_DMA = hMappedRegisters_DMA;
    
    // Hardware Core(Control)
    HwcEUART_Initialize(
        hHwdEUART->hHwcEUART,
        hHwdEUART->hMappedRegisters,
        hHwdEUART->hMappedRegisters_DMA
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_OpenDevice(
    IN      PHwdEUART           hHwdEUART,
    IN      PVOID               pcidev,
    IN      ULONG               BusNumber,
    IN      ULONG               DeviceNumber,
    IN      ULONG               FunctionNumber,
    IN      ULONG               PortID
    )
{
    FRSTATUS                    funcresult;
    ULONG                       result;
    
    ULONG                       BaseAddress0;
    
    PVOID                       VirtualAddress;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    hHwdEUART->pcidev = pcidev;
    hHwdEUART->BusNumber = BusNumber;
    hHwdEUART->DeviceNumber = DeviceNumber;
    hHwdEUART->FunctionNumber = FunctionNumber;
    
    hHwdEUART->PortID = PortID;
    
    hHwdEUART->DMACommonBuffer.pcidev = pcidev;
    
    // Driver Core Data
    if (hHwdEUART->hMappedRegisters_DMA != NULL)
    {
        VirtualAddress = SPAllocateCommonBuffer32(
            &hHwdEUART->DMACommonBuffer,
            4096,
            4096
            );
        if (VirtualAddress == NULL)
        {
            funcresult = FR_Error;
            goto funcexit;
        }
        
        DrvDbgPrint(0, "    DMACommonBuffer.PhysicalAddress:0x%x \n", hHwdEUART->DMACommonBuffer.PhysicalAddress.LowPart);
        DrvDbgPrint(0, "    DMACommonBuffer.VirtualAddress:0x%p \n", hHwdEUART->DMACommonBuffer.VirtualAddress);
        
        /*VirtualAddress = SPAllocateCommonBuffer32(
            &hHwdEUART->DMACommonBufferTx,
            4096,
            4096
            );
        if (VirtualAddress == NULL)
        {
            funcresult = FR_Error;
            goto funcexit;
        }
        
        VirtualAddress = SPAllocateCommonBuffer32(
            &hHwdEUART->DMACommonBufferRx,
            4096,
            4096
            );
        if (VirtualAddress == NULL)
        {
            funcresult = FR_Error;
            goto funcexit;
        }*/
    }
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_CloseDevice(
    IN      PHwdEUART           hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    // Driver Core Data
    SPFreeCommonBuffer32(
        &hHwdEUART->DMACommonBuffer
        );
    
    /*SPFreeCommonBuffer32(
        &hHwdEUART->DMACommonBufferTx
        );
    
    SPFreeCommonBuffer32(
        &hHwdEUART->DMACommonBufferRx
        );*/
    
    hHwdEUART->BusNumber = 0;
    hHwdEUART->DeviceNumber = 0;
    hHwdEUART->FunctionNumber = 0;
    
    result = HwcEUART_Initialize(
        hHwdEUART->hHwcEUART,
        NULL,
        NULL
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_InitHW(
    IN      PHwdEUART           hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    HwcEUART_InitHW(hHwdEUART->hHwcEUART);
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_InitDMA(
    IN      PHwdEUART           hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    if (hHwdEUART->hMappedRegisters_DMA == NULL)
    {
        funcresult = FR_Error;
        goto funcexit;
    }
    
    
    HwcEUART_DisableDMA(
        hHwdEUART->hHwcEUART
        );
    
    HwcEUART_SetRxSegmentTriggerLevel(
        hHwdEUART->hHwcEUART,
        0
        );
    
    hHwdEUART->Tx0Buffer = (PUCHAR)hHwdEUART->DMACommonBuffer.VirtualAddress;
    hHwdEUART->Tx1Buffer = (PUCHAR)hHwdEUART->DMACommonBuffer.VirtualAddress + 128;
    hHwdEUART->Rx0Buffer = (PUCHAR)hHwdEUART->DMACommonBuffer.VirtualAddress + 256;
    hHwdEUART->Rx1Buffer = (PUCHAR)hHwdEUART->DMACommonBuffer.VirtualAddress + 512;
    // TxBufferLength =  128 x 2
    HwcEUART_SetDMATxBufferAddress(
        hHwdEUART->hHwcEUART,
        hHwdEUART->DMACommonBuffer.PhysicalAddress.LowPart
        );
    
    // RxBufferLength =  256 x 2
    HwcEUART_SetDMARxBufferAddress(
        hHwdEUART->hHwcEUART,
        hHwdEUART->DMACommonBuffer.PhysicalAddress.LowPart + 256
        );
    
    //DrvDbgPrint(0, "    Tx0Buffer:0x%p Tx1Buffer:0x%p \n", hHwdEUART->Tx0Buffer, hHwdEUART->Tx1Buffer);
    //DrvDbgPrint(0, "    Rx0Buffer:0x%p Rx1Buffer:0x%p \n", hHwdEUART->Rx0Buffer, hHwdEUART->Rx1Buffer);
    
    /*
    hHwdEUART->Tx0Buffer = (PUCHAR)hHwdEUART->DMACommonBufferTx.VirtualAddress;
    hHwdEUART->Tx1Buffer = (PUCHAR)hHwdEUART->DMACommonBufferTx.VirtualAddress + 128;
    hHwdEUART->Rx0Buffer = (PUCHAR)hHwdEUART->DMACommonBufferRx.VirtualAddress;
    hHwdEUART->Rx1Buffer = (PUCHAR)hHwdEUART->DMACommonBufferRx.VirtualAddress + 256;
    
    
    // TxBufferLength =  128 x 2
    HwcEUART_SetDMATxBufferAddress(
        hHwdEUART->hHwcEUART,
        hHwdEUART->DMACommonBufferTx.PhysicalAddress.LowPart
        );
    
    // RxBufferLength =  256 x 2
    HwcEUART_SetDMARxBufferAddress(
        hHwdEUART->hHwcEUART,
        hHwdEUART->DMACommonBufferRx.PhysicalAddress.LowPart
        );
    */
    
    hHwdEUART->TxSegmentIndication = 0;
    
    hHwdEUART->RxSegmentIndication = 0;
    
    HwcEUART_RxSegment0Ready(hHwdEUART->hHwcEUART);
    
    HwcEUART_RxSegment1Ready(hHwdEUART->hHwcEUART);
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_ISR(
    IN      PHwdEUART               hHwdEUART,
        OUT PULONG                  pbInterrupt,
        OUT PHwdEUARTInterrupt      pHwdEUARTInterrupt,
        OUT PHwdEUARTVolatileInfo   pHwdEUARTVolatileInfo
    )
{
    FRSTATUS                    funcresult;
    ULONG                       result;
    
    ULONG                       i;
    
    ULONG                       ulRxData;
    ULONG                       ulValue;
    
    HwcEUARTInterruptStatus     sHwcEUARTInterruptStatus;
    
    ULONG                       CurrentTxCount;
    ULONG                       CurrentRxCount;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    *pbInterrupt = FALSE;
    
    result = HwcEUART_GetInterruptStatus(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTInterruptStatus
        );
    
    if (sHwcEUARTInterruptStatus.LineStatus == 0 && 
        sHwcEUARTInterruptStatus.ReceivedDataAvailable == 0 &&
        sHwcEUARTInterruptStatus.CharacterTimeout == 0 &&
        sHwcEUARTInterruptStatus.TransmitterHoldingEmpty == 0 &&
        sHwcEUARTInterruptStatus.ModemStatus == 0
        )
    {
        goto funcexit;
    }
    
    //because they are derived form EUARTInterrupt
    *pHwdEUARTInterrupt = sHwcEUARTInterruptStatus;
        
    SPZeroMemory(pHwdEUARTVolatileInfo, sizeof(HwdEUARTVolatileInfo));
    
    result = HwcEUART_ReadModemStatus(  // clear next ModemStatus interrupt if it exists
        hHwdEUART->hHwcEUART,
        &pHwdEUARTVolatileInfo->sEUARTModemStatus
        );
    
    if (pHwdEUARTVolatileInfo->sEUARTModemStatus.CTSChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.DSRChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.RIChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.DCDChange == 1
        )
    {
        sHwcEUARTInterruptStatus.ModemStatus = 1;
        pHwdEUARTInterrupt->ModemStatus = 1;
    }
    
    if (sHwcEUARTInterruptStatus.LineStatus == 1)
    {
        sHwcEUARTInterruptStatus.ReceivedDataAvailable = 1;
        
        *pbInterrupt = TRUE;
    }
    
    if (sHwcEUARTInterruptStatus.ReceivedDataAvailable == 1)
    {
        //else
        {
            //CurrentRxCount = hHwdEUART->hHwcEUART->sHwcEUARTFIFOConfigure.RxFIFOTriggerLevel - 1;
            //CurrentRxCount = hHwdEUART->hHwcEUART->sHwcEUARTFIFOConfigure.RxFIFOTriggerLevel;
            CurrentRxCount = 128;
            
            i = pHwdEUARTVolatileInfo->NumberRxChar;
            while(CurrentRxCount != 0)
            {
                HwdEUART_GetReg(
                    hHwdEUART,
                    EUARTRegID_HwiLineStatusReg,
                    &ulValue
                    );
                //pHwdEUARTVolatileInfo->RxCharStatus[i] = ulValue & 0xFF;
                pHwdEUARTVolatileInfo->CharAndStatus[i].CharStatus = ulValue & 0xFF;
                
                if (ulValue & 0x1E) // any Error
                {
                    pHwdEUARTInterrupt->LineStatus = 1;
                }
                
                if (ulValue & 0x01) // DataReady == 1
                {
                    result = HwcEUART_ReadRxBuffer8(    // clear interrupt
                        hHwdEUART->hHwcEUART,
                        &ulRxData
                        );
                    //pHwdEUARTVolatileInfo->RxChar[i] = (UCHAR)ulRxData;
                    pHwdEUARTVolatileInfo->CharAndStatus[i].Char = (UCHAR)ulRxData;
                    
                    i += 1;
                    CurrentRxCount -= 1;
                }
                else
                {
                    break;
                }
            }
        }
        
        pHwdEUARTVolatileInfo->NumberRxChar += i;
        
        *pbInterrupt = TRUE;
    }
    
    if (sHwcEUARTInterruptStatus.CharacterTimeout == 1)
    {
        //else
        {
            CurrentRxCount = 128;
            
            i = pHwdEUARTVolatileInfo->NumberRxChar;
            while(CurrentRxCount != 0)
            {
                HwdEUART_GetReg(
                    hHwdEUART,
                    EUARTRegID_HwiLineStatusReg,
                    &ulValue
                    );
                //pHwdEUARTVolatileInfo->RxCharStatus[i] = ulValue & 0xFF;
                pHwdEUARTVolatileInfo->CharAndStatus[i].CharStatus = ulValue & 0xFF;
                
                if (ulValue & 0x1E) // any Error
                {
                    pHwdEUARTInterrupt->LineStatus = 1;
                }
                
                if (ulValue & 0x01) // DataReady == 1
                {
                    result = HwcEUART_ReadRxBuffer8(    // clear interrupt
                        hHwdEUART->hHwcEUART,
                        &ulRxData
                        );
                    //pHwdEUARTVolatileInfo->RxChar[i] = (UCHAR)ulRxData;
                    pHwdEUARTVolatileInfo->CharAndStatus[i].Char = (UCHAR)ulRxData;
                    
                    i += 1;
                    CurrentRxCount -= 1;
                }
                else
                {
                    break;
                }
            }
        }
        
        pHwdEUARTVolatileInfo->NumberRxChar += i;
        
        *pbInterrupt = TRUE;
    }
    
    if (sHwcEUARTInterruptStatus.TransmitterHoldingEmpty == 1)
    {
        *pbInterrupt = TRUE;
    }
    
    if (sHwcEUARTInterruptStatus.ModemStatus == 1)
    {
        *pbInterrupt = TRUE;
    }
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_ISREasy(
    IN      PHwdEUART               hHwdEUART,
        OUT PULONG                  pbInterrupt,
        OUT PHwdEUARTInterrupt      pHwdEUARTInterrupt,
        OUT PHwdEUARTVolatileInfo   pHwdEUARTVolatileInfo
    )
{
    FRSTATUS                    funcresult;
    ULONG                       result;
    
    ULONG                       i;
    
    ULONG                       ulRxData;
    ULONG                       ulValue;
    
    HwcEUARTInterruptStatus     sHwcEUARTInterruptStatus;
    
    
    ULONG                       CurrentTxCount;
    ULONG                       CurrentRxCount;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    *pbInterrupt = FALSE;
    
    result = HwcEUART_GetInterruptStatus(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTInterruptStatus
        );
    
    //beacause they are derived form EUARTInterrupt
    *pHwdEUARTInterrupt = sHwcEUARTInterruptStatus;
        
    SPZeroMemory(pHwdEUARTVolatileInfo, sizeof(HwdEUARTVolatileInfo));
    
    result = HwcEUART_ReadModemStatus(  // clear next ModemStatus interrupt if it exists
        hHwdEUART->hHwcEUART,
        &pHwdEUARTVolatileInfo->sEUARTModemStatus
        );
    
    if (pHwdEUARTVolatileInfo->sEUARTModemStatus.CTSChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.DSRChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.RIChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.DCDChange == 1
        )
    {
        sHwcEUARTInterruptStatus.ModemStatus = 1;
        pHwdEUARTInterrupt->ModemStatus = 1;
    }
    
    if (sHwcEUARTInterruptStatus.LineStatus == 1)
    {
        sHwcEUARTInterruptStatus.ReceivedDataAvailable = 1;
        pHwdEUARTInterrupt->ReceivedDataAvailable = 1;
        
        *pbInterrupt = TRUE;
    }
    
    if (sHwcEUARTInterruptStatus.ReceivedDataAvailable == 1)
    {
        //else
        {
            //CurrentRxCount = hHwdEUART->hHwcEUART->sHwcEUARTFIFOConfigure.RxFIFOTriggerLevel - 1;
            //CurrentRxCount = hHwdEUART->hHwcEUART->sHwcEUARTFIFOConfigure.RxFIFOTriggerLevel;
            CurrentRxCount = 128;
            
            i = pHwdEUARTVolatileInfo->NumberRxChar;
            while(CurrentRxCount != 0)
            {
                HwdEUART_GetReg(
                    hHwdEUART,
                    EUARTRegID_HwiLineStatusReg,
                    &ulValue
                    );
                //pHwdEUARTVolatileInfo->RxCharStatus[i] = ulValue & 0xFF;
                pHwdEUARTVolatileInfo->CharAndStatus[i].CharStatus = ulValue & 0xFF;
                
                if (ulValue & 0x01) // DataReady == 1
                {
                    result = HwcEUART_ReadRxBuffer8(    // clear interrupt
                        hHwdEUART->hHwcEUART,
                        &ulRxData
                        );
                    //pHwdEUARTVolatileInfo->RxChar[i] = (UCHAR)ulRxData;
                    pHwdEUARTVolatileInfo->CharAndStatus[i].Char = (UCHAR)ulRxData;
                    
                    i += 1;
                    CurrentRxCount -= 1;
                }
                else
                {
                    break;
                }
            }
        }
        
        pHwdEUARTVolatileInfo->NumberRxChar += i;
        
        *pbInterrupt = TRUE;
    }
    
    if (sHwcEUARTInterruptStatus.CharacterTimeout == 1)
    {
        //else
        {
            CurrentRxCount = 128;
            
            i = pHwdEUARTVolatileInfo->NumberRxChar;
            while(CurrentRxCount != 0)
            {
                HwdEUART_GetReg(
                    hHwdEUART,
                    EUARTRegID_HwiLineStatusReg,
                    &ulValue
                    );
                //pHwdEUARTVolatileInfo->RxCharStatus[i] = ulValue & 0xFF;
                pHwdEUARTVolatileInfo->CharAndStatus[i].CharStatus = ulValue & 0xFF;
                
                if (ulValue & 0x01) // DataReady == 1
                {
                    result = HwcEUART_ReadRxBuffer8(    // clear interrupt
                        hHwdEUART->hHwcEUART,
                        &ulRxData
                        );
                    //pHwdEUARTVolatileInfo->RxChar[i] = (UCHAR)ulRxData;
                    pHwdEUARTVolatileInfo->CharAndStatus[i].Char = (UCHAR)ulRxData;
                    
                    i += 1;
                    CurrentRxCount -= 1;
                }
                else
                {
                    break;
                }
            }
        }
        
        pHwdEUARTVolatileInfo->NumberRxChar += i;
        
        *pbInterrupt = TRUE;
    }
    
    if (sHwcEUARTInterruptStatus.TransmitterHoldingEmpty == 1)
    {
        *pbInterrupt = TRUE;
    }
    
    if (sHwcEUARTInterruptStatus.ModemStatus == 1)
    {
        *pbInterrupt = TRUE;
    }
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_DMAISR(
    IN      PHwdEUART               hHwdEUART,
        OUT PULONG                  pbInterrupt,
        OUT PHwdEUARTInterrupt      pHwdEUARTInterrupt,
        OUT PHwdEUARTVolatileInfo   pHwdEUARTVolatileInfo
    )
{
    FRSTATUS                    funcresult;
    ULONG                       result;
    
    ULONG                       i;
    ULONG                       NumberRxChar;
    
    HwcEUARTDMAInterruptStatus  sHwcEUARTDMAInterruptStatus;
    
    HwcEUARTInterruptStatus     sHwcEUARTInterruptStatus;
    
    ULONG                       Rx0DataCount;
    ULONG                       Rx1DataCount;
    PEUARTCharAndStatus         pCharAndStatus;
    
    ULONG                       RxSegment0;
    ULONG                       RxSegment1;
    
    ULONG                       Data;
    ULONGLONG                   ms;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    *pbInterrupt = FALSE;
    
    result = HwcEUART_GetDMAInterruptStatus(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTDMAInterruptStatus
        );
    
    if (sHwcEUARTDMAInterruptStatus.TxSegment0 == 0 && 
        sHwcEUARTDMAInterruptStatus.TxSegment1 == 0 &&
        sHwcEUARTDMAInterruptStatus.RxSegment0 == 0 &&
        sHwcEUARTDMAInterruptStatus.RxSegment1 == 0 &&
        sHwcEUARTDMAInterruptStatus.ModemStatus == 0 &&
        sHwcEUARTDMAInterruptStatus.RxSegmentOverrun == 0 &&
        sHwcEUARTDMAInterruptStatus.UARTOverrun == 0 
        )
    {
        goto funcexit;
    }
    
    if (sHwcEUARTDMAInterruptStatus.RxSegment0 == 1)
    {
        //SPTime_EndTime(&hHwdEUART->sSPTime_TxRx1);
        HwcEUART_GetRx0DataCount(hHwdEUART->hHwcEUART, &Rx0DataCount);
        hHwdEUART->LastRx0Count = Rx0DataCount;
        //if (Rx0DataCount == 0)
        {
            //HwcEUART_DMADebugBit(hHwdEUART->hHwcEUART, 1);
        }
    }
    
    
    if (sHwcEUARTDMAInterruptStatus.RxSegment1 == 1)
    {
        //SPTime_EndTime(&hHwdEUART->sSPTime_TxRx1);
        HwcEUART_GetRx1DataCount(hHwdEUART->hHwcEUART, &Rx1DataCount);
        hHwdEUART->LastRx1Count = Rx1DataCount;
        //if (Rx1DataCount == 0)
        {
            //HwcEUART_DMADebugBit(hHwdEUART->hHwcEUART, 1);
        }
    }
    
    // clear InterruptStatus
    result = HwcEUART_SetDMAInterruptStatus(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTDMAInterruptStatus
        );
    
    SPZeroMemory(pHwdEUARTInterrupt, sizeof(HwdEUARTInterrupt));
    
    SPZeroMemory(pHwdEUARTVolatileInfo, sizeof(HwdEUARTVolatileInfo));
    
    pHwdEUARTVolatileInfo->sEUARTDMAInterruptStatus = sHwcEUARTDMAInterruptStatus;
    
    if (sHwcEUARTDMAInterruptStatus.TxSegment0 == 1 ||
        sHwcEUARTDMAInterruptStatus.TxSegment1 == 1
        )
    {
        pHwdEUARTInterrupt->TransmitterHoldingEmpty = 1;
        
        *pbInterrupt = TRUE;
    }
    /*
    if (sHwcEUARTDMAInterruptStatus.TxSegment0 == 1)
    {
        hHwdEUART->TxSegment0Ready = 0;
    }
    
    if (sHwcEUARTDMAInterruptStatus.TxSegment1 == 1)
    {
        hHwdEUART->TxSegment1Ready = 0;
    }
    */
    if (sHwcEUARTDMAInterruptStatus.RxSegment0 == 1 ||
        sHwcEUARTDMAInterruptStatus.RxSegment1 == 1
        )
    {
        pHwdEUARTInterrupt->ReceivedDataAvailable = 1;
        
        *pbInterrupt = TRUE;
    }
    
    result = HwcEUART_ReadModemStatus(  // clear next ModemStatus interrupt if it exists
        hHwdEUART->hHwcEUART,
        &pHwdEUARTVolatileInfo->sEUARTModemStatus
        );
    
    if (pHwdEUARTVolatileInfo->sEUARTModemStatus.CTSChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.DSRChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.RIChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.DCDChange == 1
        )
    {
        pHwdEUARTInterrupt->ModemStatus = 1;
        
        *pbInterrupt = TRUE;
    }
    
    if (sHwcEUARTDMAInterruptStatus.RxSegment0 == 1)
    {
        //SPTime_EscapeTime(&hHwdEUART->sSPTime_TxRx1, &ms);
        //if (ms > 500)
        {
            //ms = ms;
        }
        if (sHwcEUARTDMAInterruptStatus.Rx0LineError == 1)
        {
            pHwdEUARTInterrupt->LineStatus = 1;
        }
        if (sHwcEUARTDMAInterruptStatus.Rx0Timeout == 1)
        {
            pHwdEUARTInterrupt->CharacterTimeout = 1;
        }
    }
    
    if (sHwcEUARTDMAInterruptStatus.RxSegment1 == 1)
    {
        //SPTime_EscapeTime(&hHwdEUART->sSPTime_TxRx1, &ms);
        //if (ms > 500)
        {
            //ms = ms;
        }
        if (sHwcEUARTDMAInterruptStatus.Rx1LineError == 1)
        {
            pHwdEUARTInterrupt->LineStatus = 1;
        }
        if (sHwcEUARTDMAInterruptStatus.Rx1Timeout == 1)
        {
            pHwdEUARTInterrupt->CharacterTimeout = 1;
        }
    }
    
    if (sHwcEUARTDMAInterruptStatus.RxSegment0 == 1 ||
        sHwcEUARTDMAInterruptStatus.RxSegment1 == 1
        )
    {
        RxSegment0 = sHwcEUARTDMAInterruptStatus.RxSegment0;
        RxSegment1 = sHwcEUARTDMAInterruptStatus.RxSegment1;
        while(1)
        {
            if (hHwdEUART->RxSegmentIndication == 0 && RxSegment0 == 1)
            {
                pCharAndStatus = (PEUARTCharAndStatus)hHwdEUART->Rx0Buffer;
                
                NumberRxChar = pHwdEUARTVolatileInfo->NumberRxChar;
                SPCopyMemory(&pHwdEUARTVolatileInfo->CharAndStatus[NumberRxChar], hHwdEUART->Rx0Buffer, Rx0DataCount*2);
                //for (i = 0; i < Rx0DataCount; i++, NumberRxChar++)
                {
                    //pHwdEUARTVolatileInfo->RxCharStatus[NumberRxChar] = pCharAndStatus[i].CharStatus;
                    //pHwdEUARTVolatileInfo->RxChar[NumberRxChar] = pCharAndStatus[i].Char;
                    
                    //if (pCharAndStatus[i].CharStatus & 0x1E) // if any Error, set LineStatus = 1
                    {
                        //pHwdEUARTInterrupt->LineStatus = 1;
                    }
                    
                    // for debug
                    /*if (hHwdEUART->PortID == 0)
                    {
                        if (pCharAndStatus[i].Char != hHwdEUART->BytePattern)
                        {
                            HwcEUART_DMADebugBit(hHwdEUART->hHwcEUART, 1);
                        }
                        hHwdEUART->BytePattern += 1;
                        hHwdEUART->BytePattern = (UCHAR)hHwdEUART->BytePattern;
                    }
                    if (hHwdEUART->PortID == 0)
                    {
                        if (pCharAndStatus[i].Char != 0x11)
                        {
                            HwcEUART_DMADebugBit(hHwdEUART->hHwcEUART, 1);
                        }
                    }
                    */
                    
                    /*
                    {   // for all port
                        if (pCharAndStatus[i].Char != hHwdEUART->BytePattern)
                        {
                            HwcEUART_DMADebugBit(hHwdEUART->hHwcEUART, 1);
                        }
                        hHwdEUART->BytePattern += 1;
                        hHwdEUART->BytePattern = (UCHAR)hHwdEUART->BytePattern;
                    }
                    */
                    /*
                    {   // for all port
                        Data = hHwdEUART->PortID + 1;
                        Data <<= 4;
                        Data += hHwdEUART->PortID + 1;
                        if (pCharAndStatus[i].Char != Data)
                        {
                            HwcEUART_DMADebugBit(hHwdEUART->hHwcEUART, 1);
                        }
                    }
                    */
                }
                
                HwcEUART_RxSegment0Ready(hHwdEUART->hHwcEUART);
                
                pHwdEUARTVolatileInfo->NumberRxChar += Rx0DataCount;
                
                hHwdEUART->RxSegmentIndication = 1; // move to next RxSegment
                
                RxSegment0 = 0;
            }
            else if (hHwdEUART->RxSegmentIndication == 1 && RxSegment1 == 1)
            {
                pCharAndStatus = (PEUARTCharAndStatus)hHwdEUART->Rx1Buffer;
                
                NumberRxChar = pHwdEUARTVolatileInfo->NumberRxChar;
                SPCopyMemory(&pHwdEUARTVolatileInfo->CharAndStatus[NumberRxChar], hHwdEUART->Rx1Buffer, Rx1DataCount*2);
                //for (i = 0; i < Rx1DataCount; i++, NumberRxChar++)
                {
                    //pHwdEUARTVolatileInfo->RxCharStatus[NumberRxChar] = pCharAndStatus[i].CharStatus;
                    //pHwdEUARTVolatileInfo->RxChar[NumberRxChar] = pCharAndStatus[i].Char;
                    
                    //if (pCharAndStatus[i].CharStatus & 0x1E) // if any Error, set LineStatus = 1
                    {
                        //pHwdEUARTInterrupt->LineStatus = 1;
                    }
                    
                    // for debug
                    /*if (hHwdEUART->PortID == 0)
                    {
                        if (pCharAndStatus[i].Char != hHwdEUART->BytePattern)
                        {
                            HwcEUART_DMADebugBit(hHwdEUART->hHwcEUART, 1);
                        }
                        hHwdEUART->BytePattern += 1;
                        hHwdEUART->BytePattern = (UCHAR)hHwdEUART->BytePattern;
                    }
                    
                    if (hHwdEUART->PortID == 0)
                    {
                        if (pCharAndStatus[i].Char != 0x11)
                        {
                            HwcEUART_DMADebugBit(hHwdEUART->hHwcEUART, 1);
                        }
                    }*/
                    
                    /*
                    {   // for all port
                        if (pCharAndStatus[i].Char != hHwdEUART->BytePattern)
                        {
                            HwcEUART_DMADebugBit(hHwdEUART->hHwcEUART, 1);
                        }
                        hHwdEUART->BytePattern += 1;
                        hHwdEUART->BytePattern = (UCHAR)hHwdEUART->BytePattern;
                    }
                    */
                    
                    /*
                    {   // for all port
                        Data = hHwdEUART->PortID + 1;
                        Data <<= 4;
                        Data += hHwdEUART->PortID + 1;
                        if (pCharAndStatus[i].Char != Data)
                        {
                            HwcEUART_DMADebugBit(hHwdEUART->hHwcEUART, 1);
                        }
                    }
                    */
                }
                
                HwcEUART_RxSegment1Ready(hHwdEUART->hHwcEUART);
                
                pHwdEUARTVolatileInfo->NumberRxChar += Rx1DataCount;
                
                hHwdEUART->RxSegmentIndication = 0;
                
                RxSegment1 = 0;
            }
            else
            {
                break;
            }
        }
        if (sHwcEUARTDMAInterruptStatus.UARTOverrun == 1)
        {
            // make OverrunError in last RxChar.
            
            if (pHwdEUARTVolatileInfo->NumberRxChar > 0)
            {
                //pHwdEUARTVolatileInfo->RxCharStatus[pHwdEUARTVolatileInfo->NumberRxChar-1] |= 0x02;
                pHwdEUARTVolatileInfo->CharAndStatus[pHwdEUARTVolatileInfo->NumberRxChar-1].CharStatus |= 0x02;
            }
            
            HwcEUART_DMADebugBit(hHwdEUART->hHwcEUART, 1);
            
            pHwdEUARTInterrupt->LineStatus = 1;
        }
    }
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_DMAISREasy(
    IN      PHwdEUART               hHwdEUART,
        OUT PULONG                  pbInterrupt,
        OUT PHwdEUARTInterrupt      pHwdEUARTInterrupt,
        OUT PHwdEUARTVolatileInfo   pHwdEUARTVolatileInfo
    )
{
    FRSTATUS                    funcresult;
    ULONG                       result;
    
    ULONG                       i;
    ULONG                       NumberRxChar;
    
    HwcEUARTDMAInterruptStatus  sHwcEUARTDMAInterruptStatus;
    
    HwcEUARTInterruptStatus     sHwcEUARTInterruptStatus;
    
    ULONG                       Rx0DataCount;
    ULONG                       Rx1DataCount;
    PEUARTCharAndStatus         pCharAndStatus;
    
    ULONG                       RxSegment0;
    ULONG                       RxSegment1;
    
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    *pbInterrupt = FALSE;
    
    result = HwcEUART_GetDMAInterruptStatus(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTDMAInterruptStatus
        );
    
    if (sHwcEUARTDMAInterruptStatus.RxSegment0 == 1)
    {
        HwcEUART_GetRx0DataCount(hHwdEUART->hHwcEUART, &Rx0DataCount);
    }
    
    if (sHwcEUARTDMAInterruptStatus.RxSegment1 == 1)
    {
        HwcEUART_GetRx1DataCount(hHwdEUART->hHwcEUART, &Rx1DataCount);
    }
    
    // clear InterruptStatus
    result = HwcEUART_SetDMAInterruptStatus(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTDMAInterruptStatus
        );
    
    SPZeroMemory(pHwdEUARTInterrupt, sizeof(HwdEUARTInterrupt));
    
    SPZeroMemory(pHwdEUARTVolatileInfo, sizeof(HwdEUARTVolatileInfo));
    
    pHwdEUARTVolatileInfo->sEUARTDMAInterruptStatus = sHwcEUARTDMAInterruptStatus;
    
    if (sHwcEUARTDMAInterruptStatus.TxSegment0 == 1 ||
        sHwcEUARTDMAInterruptStatus.TxSegment1 == 1
        )
    {
        pHwdEUARTInterrupt->TransmitterHoldingEmpty = 1;
        
        *pbInterrupt = TRUE;
    }
    
    if (sHwcEUARTDMAInterruptStatus.RxSegment0 == 1 ||
        sHwcEUARTDMAInterruptStatus.RxSegment1 == 1
        )
    {
        pHwdEUARTInterrupt->ReceivedDataAvailable = 1;
        
        *pbInterrupt = TRUE;
    }
    
    result = HwcEUART_ReadModemStatus(  // clear next ModemStatus interrupt if it exists
        hHwdEUART->hHwcEUART,
        &pHwdEUARTVolatileInfo->sEUARTModemStatus
        );
    
    if (pHwdEUARTVolatileInfo->sEUARTModemStatus.CTSChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.DSRChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.RIChange == 1 ||
        pHwdEUARTVolatileInfo->sEUARTModemStatus.DCDChange == 1
        )
    {
        pHwdEUARTInterrupt->ModemStatus = 1;
        
        *pbInterrupt = TRUE;
    }
    
    if (sHwcEUARTDMAInterruptStatus.RxSegment0 == 1)
    {
        if (sHwcEUARTDMAInterruptStatus.Rx0LineError == 1)
        {
            pHwdEUARTInterrupt->LineStatus = 1;
        }
        if (sHwcEUARTDMAInterruptStatus.Rx0Timeout == 1)
        {
            pHwdEUARTInterrupt->CharacterTimeout = 1;
        }
    }
    
    if (sHwcEUARTDMAInterruptStatus.RxSegment1 == 1)
    {
        if (sHwcEUARTDMAInterruptStatus.Rx1LineError == 1)
        {
            pHwdEUARTInterrupt->LineStatus = 1;
        }
        if (sHwcEUARTDMAInterruptStatus.Rx1Timeout == 1)
        {
            pHwdEUARTInterrupt->CharacterTimeout = 1;
        }
    }
    
    if (sHwcEUARTDMAInterruptStatus.RxSegment0 == 1 ||
        sHwcEUARTDMAInterruptStatus.RxSegment1 == 1
        )
    {
        RxSegment0 = sHwcEUARTDMAInterruptStatus.RxSegment0;
        RxSegment1 = sHwcEUARTDMAInterruptStatus.RxSegment1;
        while(1)
        {
            if (hHwdEUART->RxSegmentIndication == 0 && RxSegment0 == 1)
            {
                pCharAndStatus = (PEUARTCharAndStatus)hHwdEUART->Rx0Buffer;
                
                NumberRxChar = pHwdEUARTVolatileInfo->NumberRxChar;
                SPCopyMemory(&pHwdEUARTVolatileInfo->CharAndStatus[NumberRxChar], hHwdEUART->Rx0Buffer, Rx0DataCount*2);
                //for (i = 0; i < Rx0DataCount; i++, NumberRxChar++)
                {
                    //pHwdEUARTVolatileInfo->RxCharStatus[NumberRxChar] = pCharAndStatus[i].CharStatus;
                    //pHwdEUARTVolatileInfo->RxChar[NumberRxChar] = pCharAndStatus[i].Char;
                    
                    //if (pCharAndStatus[i].CharStatus & 0x1E) // any Error
                    {
                        //pHwdEUARTInterrupt->LineStatus = 1;
                    }
                }
                
                HwcEUART_RxSegment0Ready(hHwdEUART->hHwcEUART);
                
                pHwdEUARTVolatileInfo->NumberRxChar += Rx0DataCount;
                
                hHwdEUART->RxSegmentIndication = 1;
                
                RxSegment0 = 0;
            }
            else if (hHwdEUART->RxSegmentIndication == 1 && RxSegment1 == 1)
            {
                pCharAndStatus = (PEUARTCharAndStatus)hHwdEUART->Rx1Buffer;
                
                NumberRxChar = pHwdEUARTVolatileInfo->NumberRxChar;
                SPCopyMemory(&pHwdEUARTVolatileInfo->CharAndStatus[NumberRxChar], hHwdEUART->Rx1Buffer, Rx1DataCount*2);
                //for (i = 0; i < Rx1DataCount; i++, NumberRxChar++)
                {
                    //pHwdEUARTVolatileInfo->RxCharStatus[NumberRxChar] = pCharAndStatus[i].CharStatus;
                    //pHwdEUARTVolatileInfo->RxChar[NumberRxChar] = pCharAndStatus[i].Char;
                    
                    //if (pCharAndStatus[i].CharStatus & 0x1E) // any Error
                    {
                        //pHwdEUARTInterrupt->LineStatus = 1;
                    }
                }
                
                HwcEUART_RxSegment1Ready(hHwdEUART->hHwcEUART);
                
                pHwdEUARTVolatileInfo->NumberRxChar += Rx1DataCount;
                
                hHwdEUART->RxSegmentIndication = 0;
                
                RxSegment1 = 0;
            }
            else
            {
                break;
            }
        }
        if (sHwcEUARTDMAInterruptStatus.UARTOverrun == 1)
        {
            // make OverrunError in last RxChar.
            if (pHwdEUARTVolatileInfo->NumberRxChar > 0)
            {
                //pHwdEUARTVolatileInfo->RxCharStatus[pHwdEUARTVolatileInfo->NumberRxChar-1] |= 0x02;
                pHwdEUARTVolatileInfo->CharAndStatus[pHwdEUARTVolatileInfo->NumberRxChar-1].CharStatus |= 0x02;
            }
            
            pHwdEUARTInterrupt->LineStatus = 1;
        }
    }
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_DCPForISR(
    IN      PHwdEUART               hHwdEUART,
    IN      PHwdEUARTInterrupt      pHwdEUARTInterrupt,
    IN      PHwdEUARTVolatileInfo   pHwdEUARTVolatileInfo
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    if (pHwdEUARTVolatileInfo->sEUARTDMAInterruptStatus.TxSegment0 == 1)
    {
        hHwdEUART->TxSegment0Ready = 0;
    }
    
    if (pHwdEUARTVolatileInfo->sEUARTDMAInterruptStatus.TxSegment1 == 1)
    {
        hHwdEUART->TxSegment1Ready = 0;
    }
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_EnableInterrupt(
    IN      PHwdEUART               hHwdEUART,
    IN      PHwdEUARTInterrupt      pHwdEUARTInterrupt // TRUE to Enable
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwcEUARTInterrupt           sHwcEUARTInterrupt;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    HwcEUART_GetInterruptEnable(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTInterrupt
        );
    
    if (pHwdEUARTInterrupt->ReceivedDataAvailable == TRUE)
    {
        sHwcEUARTInterrupt.ReceivedDataAvailable = TRUE;
    }
    
    if (pHwdEUARTInterrupt->TransmitterHoldingEmpty == TRUE)
    {
        sHwcEUARTInterrupt.TransmitterHoldingEmpty = TRUE;
    }
    
    if (pHwdEUARTInterrupt->LineStatus == TRUE)
    {
        sHwcEUARTInterrupt.LineStatus = TRUE;
    }
    
    if (pHwdEUARTInterrupt->ModemStatus == TRUE)
    {
        sHwcEUARTInterrupt.ModemStatus = TRUE;
    }
    
    if (pHwdEUARTInterrupt->CharacterTimeout == TRUE)
    {
        sHwcEUARTInterrupt.CharacterTimeout = TRUE;
    }
    
    
    HwcEUART_SetInterruptEnable(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTInterrupt
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_DisableInterrupt(
    IN      PHwdEUART               hHwdEUART,
    IN      PHwdEUARTInterrupt      pHwdEUARTInterrupt // TRUE to Disable
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwcEUARTInterrupt           sHwcEUARTInterrupt;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    HwcEUART_GetInterruptEnable(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTInterrupt
        );
    
    if (pHwdEUARTInterrupt->ReceivedDataAvailable == TRUE)
    {
        sHwcEUARTInterrupt.ReceivedDataAvailable = FALSE;
    }
    
    if (pHwdEUARTInterrupt->TransmitterHoldingEmpty == TRUE)
    {
        sHwcEUARTInterrupt.TransmitterHoldingEmpty = FALSE;
    }
    
    if (pHwdEUARTInterrupt->LineStatus == TRUE)
    {
        sHwcEUARTInterrupt.LineStatus = FALSE;
    }
    
    if (pHwdEUARTInterrupt->ModemStatus == TRUE)
    {
        sHwcEUARTInterrupt.ModemStatus = FALSE;
    }
    
    if (pHwdEUARTInterrupt->CharacterTimeout == TRUE)
    {
        sHwcEUARTInterrupt.CharacterTimeout = FALSE;
    }
    
    HwcEUART_SetInterruptEnable(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTInterrupt
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_EnableDMAInterrupt(
    IN      PHwdEUART               hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwcEUARTDMAInterrupt        sHwcEUARTDMAInterrupt;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    sHwcEUARTDMAInterrupt.TxSegment = TRUE;
    sHwcEUARTDMAInterrupt.RxSegment = TRUE;
    sHwcEUARTDMAInterrupt.ModemStatus = TRUE;
    sHwcEUARTDMAInterrupt.RxSegmentOverrun = TRUE;
    sHwcEUARTDMAInterrupt.UARTOverrun = TRUE;
    
    HwcEUART_SetDMAInterruptEnable(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTDMAInterrupt
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_DisableDMAInterrupt(
    IN      PHwdEUART               hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwcEUARTDMAInterrupt        sHwcEUARTDMAInterrupt;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    sHwcEUARTDMAInterrupt.TxSegment = FALSE;
    sHwcEUARTDMAInterrupt.RxSegment = FALSE;
    sHwcEUARTDMAInterrupt.ModemStatus = FALSE;
    sHwcEUARTDMAInterrupt.RxSegmentOverrun = FALSE;
    sHwcEUARTDMAInterrupt.UARTOverrun = FALSE;
    
    HwcEUART_SetDMAInterruptEnable(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTDMAInterrupt
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetBaudRateDIV(
    IN      PHwdEUART                   hHwdEUART,
    IN      ULONG                       BRDIV
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;

    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    
    HwcEUART_SetBaudRateDIV(
        hHwdEUART->hHwcEUART,
        BRDIV
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetFIFOConfigure(
    IN      PHwdEUART                   hHwdEUART,
    IN      PHwdEUARTFIFOConfigure      pHwdEUARTFIFOConfigure
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwcEUARTFIFOConfigure     sHwcEUARTFIFOConfigure;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    // transfer HwdEUARTFIFOConfigure into HwcEUARTFIFOConfigure
    sHwcEUARTFIFOConfigure = *pHwdEUARTFIFOConfigure;
    
    HwcEUART_SetFIFOConfigure(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTFIFOConfigure
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_GetFIFOConfigure(
    IN      PHwdEUART                   hHwdEUART,
        OUT PHwdEUARTFIFOConfigure      pHwdEUARTFIFOConfigure
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwcEUARTFIFOConfigure     sHwcEUARTFIFOConfigure;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    // transfer HwcEUARTFIFOConfigure into HwdEUARTFIFOConfigure
    HwcEUART_GetFIFOConfigure(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTFIFOConfigure
        );
        
    *pHwdEUARTFIFOConfigure = sHwcEUARTFIFOConfigure;
    
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetPortConfigure(
    IN      PHwdEUART                   hHwdEUART,
    IN      PHwdEUARTPortConfigure      pHwdEUARTPortConfigure
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwcEUARTPortConfigure       sHwcEUARTPortConfigure;

    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    // transfer HwdEUARTPortConfigure into HwcEUARTPortConfigure
    sHwcEUARTPortConfigure = *pHwdEUARTPortConfigure;
    
    HwcEUART_SetPortConfigure(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTPortConfigure
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_GetPortConfigure(
    IN      PHwdEUART                   hHwdEUART,
        OUT PHwdEUARTPortConfigure      pHwdEUARTPortConfigure
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwcEUARTPortConfigure       sHwcEUARTPortConfigure;

    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    // transfer HwcEUARTPortConfigure into HwdEUARTPortConfigure
    HwcEUART_GetPortConfigure(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTPortConfigure
        );
    
    *pHwdEUARTPortConfigure = sHwcEUARTPortConfigure;
    
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_Start(   // empty function
    IN      PHwdEUART           hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_Stop(    // empty function
    IN      PHwdEUART           hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_ReadRxBuffer8(
    IN      PHwdEUART           hHwdEUART,
        OUT PULONG              pData
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    HwcEUART_ReadRxBuffer8(
        hHwdEUART->hHwcEUART,
        pData
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_WriteTxBuffer8(
    IN      PHwdEUART           hHwdEUART,
    IN      ULONG               Data
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    HwcEUART_WriteTxBuffer8(
        hHwdEUART->hHwcEUART,
        Data
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_ReadLineStatus(
    IN      PHwdEUART               hHwdEUART,
        OUT PHwdEUARTLineStatus     pHwdEUARTLineStatus
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwcEUARTLineStatus          sHwcEUARTLineStatus;

    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    // transfer HwcEUARTLineStatus into HwdEUARTLineStatus
    HwcEUART_ReadLineStatus(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTLineStatus
        );
    
    *pHwdEUARTLineStatus = sHwcEUARTLineStatus;
    
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_ReadModemStatus(
    IN      PHwdEUART               hHwdEUART,
        OUT PHwdEUARTModemStatus    pHwdEUARTModemStatus
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwcEUARTModemStatus         sHwcEUARTModemStatus;

    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    // transfer HwcEUARTModemStatus into HwdEUARTModemStatus
    HwcEUART_ReadModemStatus(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTModemStatus
        );
    
    *pHwdEUARTModemStatus = sHwcEUARTModemStatus;
    
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_StartTransmitBreak(
    IN      PHwdEUART           hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    //SPSpinLock_Acquire(&hHwdEUART->sSPSpinLockDPC);
    HwcEUART_StartTransmitBreak(
        hHwdEUART->hHwcEUART
        );
    //SPSpinLock_Release(&hHwdEUART->sSPSpinLockDPC);
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_StopTransmitBreak(
    IN      PHwdEUART           hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    //SPSpinLock_Acquire(&hHwdEUART->sSPSpinLockDPC);
    HwcEUART_StopTransmitBreak(
        hHwdEUART->hHwcEUART
        );
    //SPSpinLock_Release(&hHwdEUART->sSPSpinLockDPC);
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetDTRPin(
    IN      PHwdEUART           hHwdEUART,
    IN      ULONG               DTRPin      // 0: High, 1: Low
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    //SPSpinLock_Acquire(&hHwdEUART->sSPSpinLockDPC);
    HwcEUART_SetDTRPin(
        hHwdEUART->hHwcEUART,
        DTRPin
        );
    //SPSpinLock_Release(&hHwdEUART->sSPSpinLockDPC);
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetRTSPin(
    IN      PHwdEUART           hHwdEUART,
    IN      ULONG               RTSPin      // 0: High, 1: Low
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    //SPSpinLock_Acquire(&hHwdEUART->sSPSpinLockDPC);
    HwcEUART_SetRTSPin(
        hHwdEUART->hHwcEUART,
        RTSPin
        );
    //SPSpinLock_Release(&hHwdEUART->sSPSpinLockDPC);
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetOut1Pin(
    IN      PHwdEUART           hHwdEUART,
    IN      ULONG               Out1Pin     // 0: High, 1: Low
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    //SPSpinLock_Acquire(&hHwdEUART->sSPSpinLockDPC);
    HwcEUART_SetOut1Pin(
        hHwdEUART->hHwcEUART,
        Out1Pin
        );
    //SPSpinLock_Release(&hHwdEUART->sSPSpinLockDPC);
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetOut2Pin(
    IN      PHwdEUART           hHwdEUART,
    IN      ULONG               Out2Pin     // 0: High, 1: Low
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    //SPSpinLock_Acquire(&hHwdEUART->sSPSpinLockDPC);
    HwcEUART_SetOut2Pin(
        hHwdEUART->hHwcEUART,
        Out2Pin
        );
    //SPSpinLock_Release(&hHwdEUART->sSPSpinLockDPC);
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetScratchpad(
    IN      PHwdEUART           hHwdEUART,
    IN      ULONG               Data
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    HwcEUART_SetScratchpad(
        hHwdEUART->hHwcEUART,
        Data
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_GetScratchpad(
    IN      PHwdEUART           hHwdEUART,
        OUT PULONG              pData
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    HwcEUART_GetScratchpad(
        hHwdEUART->hHwcEUART,
        pData
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_HardResetDMA(
    IN      PHwdEUART           hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    hHwdEUART->TxSegmentIndication = 0;
    
    hHwdEUART->RxSegmentIndication = 0;
    
    hHwdEUART->TxSegment0Ready = 0;
    
    hHwdEUART->TxSegment1Ready = 0;
    
    hHwdEUART->DMAEnable = FALSE;
    
    //hHwdEUART->BytePattern = 0;
    
    hHwdEUART->LastRx0Count = 0;
    
    hHwdEUART->LastRx1Count = 0;
    
    HwcEUART_HardResetDMA(
        hHwdEUART->hHwcEUART
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_EnableDMA(
    IN      PHwdEUART           hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    hHwdEUART->TxSegmentIndication = 0;
    
    hHwdEUART->RxSegmentIndication = 0;
    
    hHwdEUART->TxSegment0Ready = 0;
    
    hHwdEUART->TxSegment1Ready = 0;
    
    hHwdEUART->DMAEnable = TRUE;
    
    HwcEUART_EnableDMA(
        hHwdEUART->hHwcEUART
        );
    
    //DrvDbgPrint(0, "    Tx0Buffer:0x%p Tx1Buffer:0x%p \n", hHwdEUART->Tx0Buffer, hHwdEUART->Tx1Buffer);
    //DrvDbgPrint(0, "    Rx0Buffer:0x%p Rx1Buffer:0x%p \n", hHwdEUART->Rx0Buffer, hHwdEUART->Rx1Buffer);
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_DisableDMA(
    IN      PHwdEUART           hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    HwcEUART_DisableDMA(
        hHwdEUART->hHwcEUART
        );
    
    hHwdEUART->DMAEnable = FALSE;
    
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_GetDMAEnable(
    IN      PHwdEUART           hHwdEUART,
        OUT PULONG              pDMAEnable
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    HwiDMAControl0Reg           sHwiDMAControl0Reg;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    // at the Hwc level, we dont validate the input parameter.
    
    //
    // function body
    //
    
    SPZeroMemory(&sHwiDMAControl0Reg, sizeof(HwiDMAControl0Reg));
    
    _GetHwiDMAControl0Reg(
        hHwdEUART->hHwcEUART->hMappedRegisters_DMA,
        &sHwiDMAControl0Reg
        );
    
    *pDMAEnable = sHwiDMAControl0Reg.DMAEnable;
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetRxSegmentTriggerLevel(
    IN      PHwdEUART           hHwdEUART,
    IN      ULONG               RxSegmentTriggerLevel
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    HwcEUART_SetRxSegmentTriggerLevel(
        hHwdEUART->hHwcEUART,
        RxSegmentTriggerLevel
        );
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_DMATxEmpty(
    IN      PHwdEUART           hHwdEUART,
        OUT PULONG              pbTxEmpty
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    ULONG                       TxSegment0Ready;
    ULONG                       TxSegment1Ready;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    *pbTxEmpty = FALSE;
    /*
    if (hHwdEUART->TxSegment0Ready == 0 || hHwdEUART->TxSegment1Ready == 0)
    {
        *pbTxEmpty = TRUE;
    }
    */
    
    HwcEUART_GetTxSegmentReady(
        hHwdEUART->hHwcEUART,
        &TxSegment0Ready,
        &TxSegment1Ready
        );
        
    if (TxSegment0Ready == 0 || TxSegment1Ready == 0)
    {
        *pbTxEmpty = TRUE;
    }
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_DMAWriteTxBuffer(
    IN      PHwdEUART           hHwdEUART,
    IN      PVOID               pDataBuffer,
    IN      ULONG               DataBufferLength    // MaxTxBufferSize 128bytes
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //HwcEUARTDMAStatus           sHwcEUARTDMAStatus;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    /*
    HwcEUART_GetDMAStatus(
        hHwdEUART->hHwcEUART,
        &sHwcEUARTDMAStatus
        );
    */
    
    if (hHwdEUART->TxSegmentIndication == 0)
    //if (sHwcEUARTDMAStatus.TxSegmentIndication == 0)
    {
        SPCopyMemory(hHwdEUART->Tx0Buffer, pDataBuffer, DataBufferLength);
        HwcEUART_SetTx0DataLength(hHwdEUART->hHwcEUART, DataBufferLength);
        
        //SPTime_StartTime(&hHwdEUART->sSPTime_TxRx0);
        HwcEUART_TxSegment0Ready(hHwdEUART->hHwcEUART);
        //hHwdEUART->TxSegment0Ready = 1;
        
        hHwdEUART->TxSegmentIndication = 1;
    }
    else
    {
        SPCopyMemory(hHwdEUART->Tx1Buffer, pDataBuffer, DataBufferLength);
        HwcEUART_SetTx1DataLength(hHwdEUART->hHwcEUART, DataBufferLength);
        
        //SPTime_StartTime(&hHwdEUART->sSPTime_TxRx1);
        HwcEUART_TxSegment1Ready(hHwdEUART->hHwcEUART);
        //hHwdEUART->TxSegment1Ready = 1;
        
        hHwdEUART->TxSegmentIndication = 0;
    }
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_DMAAllEmpty(
    IN      PHwdEUART           hHwdEUART,
        OUT PULONG              pbAllEmpty
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    ULONG                       TxSegment0Ready;
    ULONG                       TxSegment1Ready;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    *pbAllEmpty = FALSE;
    /*
    if (hHwdEUART->TxSegment0Ready == 0 && hHwdEUART->TxSegment1Ready == 0)
    {
        *pbAllEmpty = TRUE;
    }
    */
    
    HwcEUART_GetTxSegmentReady(
        hHwdEUART->hHwcEUART,
        &TxSegment0Ready,
        &TxSegment1Ready
        );
    
    if (TxSegment0Ready == 0 && TxSegment1Ready == 0)
    {
        *pbAllEmpty = TRUE;
    }
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_DMAShowAll(
    IN      PHwdEUART           hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    ULONG                       Value;
    PMappedBusAddress           hMappedRegisters;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    hMappedRegisters = hHwdEUART->hMappedRegisters_DMA;
    
    BusDeviceIO_Read(
        hMappedRegisters,
        EUARTRegOffset_HwiDMAControl0Reg,
        EUARTRegOffset_Size,
        &Value
        );
    DrvDbgPrint(0, "    DMAControl0Reg:0x%x \n", Value);
    
    BusDeviceIO_Read(
        hMappedRegisters,
        EUARTRegOffset_HwiDMAControl1Reg,
        EUARTRegOffset_Size,
        &Value
        );
    DrvDbgPrint(0, "    DMAControl1Reg:0x%x \n", Value);
    
    BusDeviceIO_Read(
        hMappedRegisters,
        EUARTRegOffset_HwiDMAStatusReg,
        EUARTRegOffset_Size,
        &Value
        );
    DrvDbgPrint(0, "    DMAStatusReg:0x%x \n", Value);
    
    BusDeviceIO_Read(
        hMappedRegisters,
        EUARTRegOffset_HwiDMATxBufferAddressReg,
        4,
        &Value
        );
    DrvDbgPrint(0, "    DMATxBufferAddressReg:0x%x \n", Value);
    
    BusDeviceIO_Read(
        hMappedRegisters,
        EUARTRegOffset_HwiDMARxBufferAddressReg,
        4,
        &Value
        );
    DrvDbgPrint(0, "    DMARxBufferAddressReg:0x%x \n", Value);
    
    BusDeviceIO_Read(
        hMappedRegisters,
        EUARTRegOffset_HwiDMAInterruptEnableReg,
        EUARTRegOffset_Size,
        &Value
        );
    DrvDbgPrint(0, "    DMAInterruptEnableReg:0x%x \n", Value);
    
    BusDeviceIO_Read(
        hMappedRegisters,
        EUARTRegOffset_HwiDMAInterruptStatusReg,
        4,
        &Value
        );
    DrvDbgPrint(0, "    DMAInterruptStatusReg:0x%x \n", Value);
    
    BusDeviceIO_Read(
        hMappedRegisters,
        EUARTRegOffset_HwiDMATx0DataLengthReg,
        EUARTRegOffset_Size,
        &Value
        );
    DrvDbgPrint(0, "    DMATx0DataLengthReg:0x%x \n", Value);
    
    BusDeviceIO_Read(
        hMappedRegisters,
        EUARTRegOffset_HwiDMATx1DataLengthReg,
        EUARTRegOffset_Size,
        &Value
        );
    DrvDbgPrint(0, "    DMATx1DataLengthReg:0x%x \n", Value);
    
    BusDeviceIO_Read(
        hMappedRegisters,
        EUARTRegOffset_HwiDMARx0DataCountReg,
        EUARTRegOffset_Size,
        &Value
        );
    DrvDbgPrint(0, "    DMARx0DataCountReg:0x%x \n", Value);
    
    BusDeviceIO_Read(
        hMappedRegisters,
        EUARTRegOffset_HwiDMARx1DataCountReg,
        EUARTRegOffset_Size,
        &Value
        );
    DrvDbgPrint(0, "    DMARx1DataCountReg:0x%x \n", Value);
    
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetHwiReg(
    IN      PHwdEUART           hHwdEUART,
    IN      ULONG               RegID,
    IN      PVOID               pHwiReg,
    IN      ULONG               SizeOfHwiReg
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    PMappedBusAddress           hMappedRegisters;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    hMappedRegisters = hHwdEUART->hMappedRegisters;
    
    switch(RegID)
    {
        
        case EUARTRegID_HwiDivisorLatchLowReg:
        {
            if (SizeOfHwiReg != sizeof(HwiDivisorLatchLowReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _SetHwiDivisorLatchLowReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiDivisorLatchHighReg:
        {
            if (SizeOfHwiReg != sizeof(HwiDivisorLatchHighReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _SetHwiDivisorLatchHighReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiReceiverBufferReg:
        {
            
        }
        break;
        
        case EUARTRegID_HwiTransmitterHoldingReg:
        {
            if (SizeOfHwiReg != sizeof(HwiTransmitterHoldingReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _SetHwiTransmitterHoldingReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiInterruptEnableReg:
        {
            if (SizeOfHwiReg != sizeof(HwiInterruptEnableReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _SetHwiInterruptEnableReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiInterruptIdentificationReg:
        {
            
        }
        break;
        
        case EUARTRegID_HwiFIFOControlReg:
        {
            if (SizeOfHwiReg != sizeof(HwiFIFOControlReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _SetHwiFIFOControlReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiLineControlReg:
        {
            if (SizeOfHwiReg != sizeof(HwiLineControlReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _SetHwiLineControlReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiModemControlReg:
        {
            if (SizeOfHwiReg != sizeof(HwiModemControlReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _SetHwiModemControlReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiLineStatusReg:
        {
            
        }
        break;
        
        case EUARTRegID_HwiModemStatusReg:
        {
            
        }
        break;
        
        case EUARTRegID_HwiScratchpadReg:
        {
            if (SizeOfHwiReg != sizeof(HwiScratchpadReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _SetHwiScratchpadReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        default:
        {
            funcresult = FR_Error;
        }
        break;
    }
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_GetHwiReg(
    IN      PHwdEUART           hHwdEUART,
    IN      ULONG               RegID,
        OUT PVOID               pHwiReg,
    IN      ULONG               SizeOfHwiReg
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    PMappedBusAddress           hMappedRegisters;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    hMappedRegisters = hHwdEUART->hMappedRegisters;
    
    switch(RegID)
    {
        
        case EUARTRegID_HwiDivisorLatchLowReg:
        {
            if (SizeOfHwiReg != sizeof(HwiDivisorLatchLowReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _GetHwiDivisorLatchLowReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiDivisorLatchHighReg:
        {
            if (SizeOfHwiReg != sizeof(HwiDivisorLatchHighReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _GetHwiDivisorLatchHighReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiReceiverBufferReg:
        {
            if (SizeOfHwiReg != sizeof(HwiReceiverBufferReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _GetHwiReceiverBufferReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiTransmitterHoldingReg:
        {
            
        }
        break;
        
        case EUARTRegID_HwiInterruptEnableReg:
        {
            if (SizeOfHwiReg != sizeof(HwiInterruptEnableReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _GetHwiInterruptEnableReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiInterruptIdentificationReg:
        {
            if (SizeOfHwiReg != sizeof(HwiInterruptIdentificationReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _GetHwiInterruptIdentificationReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiFIFOControlReg:
        {
            
        }
        break;
        
        case EUARTRegID_HwiLineControlReg:
        {
            if (SizeOfHwiReg != sizeof(HwiLineControlReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _GetHwiLineControlReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiModemControlReg:
        {
            if (SizeOfHwiReg != sizeof(HwiModemControlReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _GetHwiModemControlReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiLineStatusReg:
        {
            if (SizeOfHwiReg != sizeof(HwiLineStatusReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _GetHwiLineStatusReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiModemStatusReg:
        {
            if (SizeOfHwiReg != sizeof(HwiModemStatusReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _GetHwiModemStatusReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        case EUARTRegID_HwiScratchpadReg:
        {
            if (SizeOfHwiReg != sizeof(HwiScratchpadReg))
            {
                funcresult = FR_Error;
                goto funcexit;
            }
            _GetHwiScratchpadReg(
                hMappedRegisters,
                pHwiReg
                );
        }
        break;
        
        default:
        {
            funcresult = FR_Error;
        }
        break;
    }
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_SetReg(
    IN      PHwdEUART           hHwdEUART,
    IN      ULONG               RegID,
    IN      ULONG               Value
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    PMappedBusAddress           hMappedRegisters;
    ULONG                       RegOffset;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    hMappedRegisters = hHwdEUART->hMappedRegisters;
    
    RegOffset = 0xFFFF;
    
    switch(RegID)
    {
        case EUARTRegID_HwiDivisorLatchLowReg:
        {
            RegOffset = EUARTRegOffset_HwiDivisorLatchLowReg;
        }
        break;
        
        case EUARTRegID_HwiDivisorLatchHighReg:
        {
            RegOffset = EUARTRegOffset_HwiDivisorLatchHighReg;
        }
        break;
        
        case EUARTRegID_HwiReceiverBufferReg:
        {
            RegOffset = EUARTRegOffset_HwiReceiverBufferReg;
        }
        break;
        
        case EUARTRegID_HwiInterruptEnableReg:
        {
            RegOffset = EUARTRegOffset_HwiInterruptEnableReg;
        }
        break;
        
        case EUARTRegID_HwiInterruptIdentificationReg:
        {
            RegOffset = EUARTRegOffset_HwiInterruptIdentificationReg;
        }
        break;
        
        case EUARTRegID_HwiLineControlReg:
        {
            RegOffset = EUARTRegOffset_HwiLineControlReg;
        }
        break;
        
        case EUARTRegID_HwiModemControlReg:
        {
            RegOffset = EUARTRegOffset_HwiModemControlReg;
        }
        break;
        
        case EUARTRegID_HwiLineStatusReg:
        {
            RegOffset = EUARTRegOffset_HwiLineStatusReg;
        }
        break;
        
        case EUARTRegID_HwiModemStatusReg:
        {
            RegOffset = EUARTRegOffset_HwiModemStatusReg;
        }
        break;
        
        case EUARTRegID_HwiScratchpadReg:
        {
            RegOffset = EUARTRegOffset_HwiScratchpadReg;
        }
        break;
        
        case EUARTRegID_HwiTransmitterHoldingReg:
        {
            RegOffset = EUARTRegOffset_HwiTransmitterHoldingReg;
        }
        break;
        
        case EUARTRegID_HwiFIFOControlReg:
        {
            RegOffset = EUARTRegOffset_HwiFIFOControlReg;
        }
        break;
        
        default:
        {
            funcresult = FR_Error;
        }
        break;
    }
    
    if (RegOffset != 0xFFFF)
    {
        BusDeviceIO_Write(
            hMappedRegisters,
            RegOffset,
            EUARTRegOffset_Size,
            Value
            );
    }
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


FRSTATUS
HwdEUART_GetReg(
    IN      PHwdEUART           hHwdEUART,
    IN      ULONG               RegID,
        OUT PULONG              pValue
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    PMappedBusAddress           hMappedRegisters;
    ULONG                       RegOffset;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    hMappedRegisters = hHwdEUART->hMappedRegisters;
    
    RegOffset = 0xFFFF;
    
    switch(RegID)
    {
        case EUARTRegID_HwiDivisorLatchLowReg:
        {
            RegOffset = EUARTRegOffset_HwiDivisorLatchLowReg;
        }
        break;
        
        case EUARTRegID_HwiDivisorLatchHighReg:
        {
            RegOffset = EUARTRegOffset_HwiDivisorLatchHighReg;
        }
        break;
        
        case EUARTRegID_HwiReceiverBufferReg:
        {
            RegOffset = EUARTRegOffset_HwiReceiverBufferReg;
        }
        break;
        
        case EUARTRegID_HwiInterruptEnableReg:
        {
            RegOffset = EUARTRegOffset_HwiInterruptEnableReg;
        }
        break;
        
        case EUARTRegID_HwiInterruptIdentificationReg:
        {
            RegOffset = EUARTRegOffset_HwiInterruptIdentificationReg;
        }
        break;
        
        case EUARTRegID_HwiLineControlReg:
        {
            RegOffset = EUARTRegOffset_HwiLineControlReg;
        }
        break;
        
        case EUARTRegID_HwiModemControlReg:
        {
            RegOffset = EUARTRegOffset_HwiModemControlReg;
        }
        break;
        
        case EUARTRegID_HwiLineStatusReg:
        {
            RegOffset = EUARTRegOffset_HwiLineStatusReg;
        }
        break;
        
        case EUARTRegID_HwiModemStatusReg:
        {
            RegOffset = EUARTRegOffset_HwiModemStatusReg;
        }
        break;
        
        case EUARTRegID_HwiScratchpadReg:
        {
            RegOffset = EUARTRegOffset_HwiScratchpadReg;
        }
        break;
        
        case EUARTRegID_HwiTransmitterHoldingReg:
        {
            RegOffset = EUARTRegOffset_HwiTransmitterHoldingReg;
        }
        break;
        
        case EUARTRegID_HwiFIFOControlReg:
        {
            RegOffset = EUARTRegOffset_HwiFIFOControlReg;
        }
        break;
        
        default:
        {
            funcresult = FR_Error;
        }
        break;
    }
    
    if (RegOffset != 0xFFFF)
    {
        BusDeviceIO_Read(
            hMappedRegisters,
            RegOffset,
            EUARTRegOffset_Size,
            pValue
            );
    }
    
    goto funcexit;
funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    return funcresult;
}


VOID
HwdEUART_ComputeBRDIV(
    IN      ULONG                   SourceClock,
    IN      ULONG                   ClockDIV,
    IN      ULONG                   bAdaptiveBaudRate,
    IN      ULONG                   BaudRate,
        OUT PULONG                  pBRDIV      // 0 if not adaptive BRDIV
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    //PMappedBusAddress           hMappedRegisters;
    
    ULONG                       i;
    ULONG                       bFind;
    ULONG                       BRDIV;
    ULONG                       Remainder;
    
    ULONG                       DIVBaudRate;
    ULONG                       Difference;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    *pBRDIV = 0;
    bFind = FALSE;
    /*
    i = 0;
    while(pEUARTBaudRateTable[i].BaudRate != 0)
    {
        if (pEUARTBaudRateTable[i].BaudRate == BaudRate)
        {
            *pBRDIV = pEUARTBaudRateTable[i].BRDIV;
            bFind = TRUE;
            break;            
        }
        i += 1;
    }
    */
    if (bFind == FALSE)
    {
        BRDIV = (SourceClock / ClockDIV) / BaudRate;
        Remainder = (SourceClock / ClockDIV) % BaudRate;
        
        if (bAdaptiveBaudRate == TRUE)
        {
            if ((Remainder*2) > BaudRate)
            {
                BRDIV += 1;
            }
        }
        else
        {
            
        }
        
        /*
        DIVBaudRate = (SourceClock / ClockDIV) / BRDIV;
        if (BaudRate > DIVBaudRate)
        {
            Difference = BaudRate - DIVBaudRate;
        }
        else
        {
            Difference = DIVBaudRate - BaudRate;
        }
        if (BaudRate >= 9600 && Difference > (BaudRate/10))
        {
            BRDIV = 0;
        }
        */
        
        // i dont sure whether the following rule is right.
        //if (BaudRate >= 9600 && Remainder > (SourceClock/100))
            //BRDIV = 0;
        
        *pBRDIV = BRDIV;
    }
    
    
    //goto funcexit;
//funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    //return funcresult;
}


VOID
HwdEUART_HardReset(
    IN      PHwdEUART               hHwdEUART
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    ULONG                       Data;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    HwcEUART_StopTransmitBreak(
        hHwdEUART->hHwcEUART
        );
    
    HwcEUART_ResetModemControl(
        hHwdEUART->hHwcEUART
        );
    
    HwcEUART_ResetLineControl(
        hHwdEUART->hHwcEUART
        );
    
    HwcEUART_ResetFIFOControl(
        hHwdEUART->hHwcEUART
        );
    
    HwcEUART_ResetInterrupt(
        hHwdEUART->hHwcEUART
        );
    
    HwcEUART_ClearPendingInterrupts(
        hHwdEUART->hHwcEUART
        );
    
    //goto funcexit;
//funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    //return funcresult;
}


VOID
HwdEUART_SoftReset(
    IN      PHwdEUART               hHwdEUART,
    IN      PEUARTFIFOConfigure     pEUARTFIFOConfigure,
    IN      PEUARTPortConfigure     pEUARTPortConfigure
    )
{
    FRSTATUS                    funcresult;
    //ULONG                       result;
    
    ULONG                       Data;
    
    //
    // initialize local variables
    //
    
    funcresult = FR_Success;
    
    //
    // check parameters
    //
    
    //
    // function body
    //
    
    HwcEUART_StopTransmitBreak(
        hHwdEUART->hHwcEUART
        );
    
    HwcEUART_ResetModemControl(
        hHwdEUART->hHwcEUART
        );
    
    HwcEUART_ResetLineControl(
        hHwdEUART->hHwcEUART
        );
    
    HwcEUART_ResetFIFOControl(
        hHwdEUART->hHwcEUART
        );
    
    HwcEUART_SetFIFOConfigure(
        hHwdEUART->hHwcEUART,
        pEUARTFIFOConfigure
        );
    
    HwcEUART_SetPortConfigure(
        hHwdEUART->hHwcEUART,
        pEUARTPortConfigure
        );
    
    HwcEUART_ClearPendingInterrupts(
        hHwdEUART->hHwcEUART
        );
    
    //HwcEUART_ShowAll(hHwdEUART->hHwcEUART);
    
    //goto funcexit;
//funcexit:

    //
    // free local buffers
    //
    
    //
    // unsuccessful handle
    //
    
    //return funcresult;
}