/* Memory.c - Memory mappings and remapping functions */

/* Copyright - Galileo technology. */

/* modified by Josh Huber to clean some things up, and
 * fit it into the ppcboot framework */

#include <galileo/core.h>
#include <galileo/memory.h>

/********************************************************************
* memoryGetBankBaseAddress - Gets the base address of a memory bank
*      - If the memory bank size is 0 then this base address has no meaning!!!
*
*
* INPUTS:   MEMORY_BANK bank - The bank we ask for its base Address.
* OUTPUT:   N/A  
* RETURNS: Memory bank base address.
*********************************************************************/
unsigned int memoryGetBankBaseAddress(MEMORY_BANK bank)
{
    unsigned int base;
    unsigned int regOffset;

    switch (bank) 
    {
    case BANK0:
        regOffset = SCS_0_LOW_DECODE_ADDRESS;
        break;
    case BANK1:
        regOffset = SCS_1_LOW_DECODE_ADDRESS;
        break;
    case BANK2:
        regOffset = SCS_2_LOW_DECODE_ADDRESS;
        break;
    case BANK3:
        regOffset = SCS_3_LOW_DECODE_ADDRESS;
        break;
    default:
        regOffset = SCS_0_LOW_DECODE_ADDRESS; /* default value */
        break;
    }
    GT_REG_READ(regOffset,&base); 
    base = base << 20;
    return base;
}

/********************************************************************
* memoryGetDeviceBaseAddress - Gets the base address of a device.
*           - If the device size is 0 then this base address has no meaning!!!
*
*
* INPUT:   DEVICE device - The device we ask for its base address.
* OUTPUT:   N/A  
* RETURNS: Device base address.
*********************************************************************/
unsigned int memoryGetDeviceBaseAddress(DEVICE device)
{
    unsigned int regBase;
    unsigned int regOffset;

    switch (device) 
    {
    case DEVICE0:
        regOffset = CS_0_LOW_DECODE_ADDRESS;
        break;
    case DEVICE1:
        regOffset = CS_1_LOW_DECODE_ADDRESS;
        break;
    case DEVICE2:
        regOffset = CS_2_LOW_DECODE_ADDRESS;
        break;
    case DEVICE3:
        regOffset = CS_3_LOW_DECODE_ADDRESS;
        break;
    case BOOT_DEVICE:
        regOffset = BOOTCS_LOW_DECODE_ADDRESS;
        break;
    default:
        regOffset = CS_0_LOW_DECODE_ADDRESS; /* default value */
        break;
    }
    GT_REG_READ(regOffset, &regBase);
    regBase = regBase << 20;
    return regBase;
}

/********************************************************************
* memoryGetBankSize - Returns the size of a memory bank.
*
*
* INPUT:    MEMORY_BANK bank - The bank we ask for its size.
* OUTPUT:   N/A
* RETURNS: Memory bank size.
*********************************************************************/
unsigned int memoryGetBankSize(MEMORY_BANK bank)
{
    unsigned int size,base;
    unsigned int highAddress;
    unsigned int highValue;
    switch (bank) 
    {
    case BANK0:
        highAddress = SCS_0_HIGH_DECODE_ADDRESS;
        break;
    case BANK1:
        highAddress = SCS_1_HIGH_DECODE_ADDRESS;
        break;
    case BANK2:
        highAddress = SCS_2_HIGH_DECODE_ADDRESS;
        break;
    case BANK3:
        highAddress = SCS_3_HIGH_DECODE_ADDRESS;
        break;
    default:
        highAddress = SCS_0_HIGH_DECODE_ADDRESS;  /* default value */
        break;
    }
    base = memoryGetBankBaseAddress(bank);
    GT_REG_READ(highAddress,&highValue);
    highValue = (highValue + 1) << 20;
    if(base > highValue)
        size=0;
    else
        size = highValue - base;
    return size;
}

/********************************************************************
* memoryGetDeviceSize - Returns the size of a device memory space
*
*
* INPUT:    DEVICE device - The device we ask for its base address.
* OUTPUT:   N/A  
* RETURNS:  Size of a device memory space.
*********************************************************************/
unsigned int memoryGetDeviceSize(DEVICE device)
{
    unsigned int size,base;
    unsigned int highAddress;
    unsigned int highValue;

    switch (device) 
    {
        case DEVICE0:
            highAddress = CS_0_HIGH_DECODE_ADDRESS;
            break;
        case DEVICE1:
            highAddress = CS_1_HIGH_DECODE_ADDRESS;
            break;
        case DEVICE2:
            highAddress = CS_2_HIGH_DECODE_ADDRESS;
            break;
        case DEVICE3:
            highAddress = CS_3_HIGH_DECODE_ADDRESS;
            break;
        case BOOT_DEVICE:
            highAddress = BOOTCS_HIGH_DECODE_ADDRESS;
            break;
        default:
            highAddress = CS_0_HIGH_DECODE_ADDRESS;  /* default value */
            break;
    }
    base = memoryGetDeviceBaseAddress(device);
    GT_REG_READ(highAddress,&highValue);
    if (highValue == 0xfff)
    {
        size = (~base) + 1;
        return size;
    }
    else
        highValue = (highValue + 1) << 20;
    if(base > highValue)
        size=0;
    else
        size = highValue - base;
    return size;
}

/********************************************************************
* memoryGetDeviceWidth - A device can be with: 1,2,4 or 8 Bytes data width.
*                  The width is determine in registers: 'Device Parameters'
*                  registers (0x45c, 0x460, 0x464, 0x468, 0x46c - for each device.
*                  at bits: [21:20].                  
*
* INPUT:    DEVICE device - Device number
* OUTPUT:   N/A  
* RETURNS:  Device width in Bytes (1,2,4 or 8), 0 if error had occurred.
*********************************************************************/
unsigned int memoryGetDeviceWidth(DEVICE device)
{
    unsigned int width;
    unsigned int regValue;

    GT_REG_READ(DEVICE_BANK0PARAMETERS + device*4,&regValue);
    width =  (regValue & 0x00300000) >> 20;
    switch (width)
    {
        case 0:
            return 1;
        case 1:
            return 2;
        case 2:
            return 4;
        case 3:
            return 8;
        default:
            return 0;
    }
}

/********************************************************************
* memoryMapBank0      - Sets new bases and boundaries for memory banks 0
*                     - Pay attention to the PCI mappings and make sure to 
*                       coordinate between the two interfaces!!!
*                     - It is the programmer`s responsibility to make sure 
*                       there are no conflicts with other memory spaces!!!
*                     - If a bank needs to be closed , it gives the LOW max
*                       value (0xffff) and to the HIGH min value (0x0).
*
*
* INPUTS: unsigned int bank0Base - required bank 0 base address.
*         unsigned int bank0Length - required bank 0 size.
* RETURNS: true on success, false on failure or if one of the parameters is 
*          wrong.
*********************************************************************/
bool memoryMapBank0(unsigned int bank0Base,unsigned int bank0Length) 
{
    unsigned int memBank0Base , bank0Top;
    unsigned int mainBank0Top = bank0Base + bank0Length;
    unsigned int currentLow;
    unsigned int baseOld;
    
    GT_REG_READ(SCS_0_LOW_DECODE_ADDRESS,&currentLow);
    baseOld = currentLow << 20;
    memBank0Base = bank0Base >> 20;
    memBank0Base = memBank0Base & 0xffff;
    bank0Top = mainBank0Top >> 20;   
    if ((bank0Base >= baseOld) && (baseOld < mainBank0Top))
    {
        GT_REG_WRITE(SCS_0_LOW_DECODE_ADDRESS,memBank0Base);
        GT_REG_WRITE(SCS_0_HIGH_DECODE_ADDRESS,bank0Top - 1);
        return true;
    }
    else
    {
        GT_REG_WRITE(SCS_0_LOW_DECODE_ADDRESS,0xffff);
        if(bank0Length != 0)
        {
            GT_REG_WRITE(SCS_0_HIGH_DECODE_ADDRESS,bank0Top - 1);
            GT_REG_WRITE(SCS_0_LOW_DECODE_ADDRESS,memBank0Base);
        }
        else
        {
            GT_REG_WRITE(SCS_0_HIGH_DECODE_ADDRESS,0x0);
        }
        return true;
    }
}

/********************************************************************
* memoryMapBank1      - Sets new bases and boundaries for memory banks 1
*                     - Pay attention to the PCI mappings and make sure to 
*                       coordinate between the two interfaces!!!
*                     - It is the programmer`s responsibility to make sure 
*                       there are no conflicts with other memory spaces!!!
*                     - If a bank needs to be closed , it gives the LOW max
*                       value (0xffff) and to the HIGH min value (0x0).
*
*
* INPUTS: unsigned int bank1Base - required bank 0 base address.
*         unsigned int bank1Length - required bank 0 size.
* RETURNS: true on success, false on failure or if one of the parameters is 
*          wrong.
*********************************************************************/
bool memoryMapBank1(unsigned int bank1Base,unsigned int bank1Length) 
{
    unsigned int memBank1Base , bank1Top;
    unsigned int mainBank1Top = bank1Base + bank1Length;
    unsigned int currentLow;
    unsigned int baseOld;
    
    GT_REG_READ(SCS_1_LOW_DECODE_ADDRESS,&currentLow);
    baseOld = currentLow << 20;
    memBank1Base = bank1Base >> 20;
    memBank1Base = memBank1Base & 0xffff;
    bank1Top  = mainBank1Top >> 20;   
    if ((bank1Base >= baseOld) && (baseOld < mainBank1Top))
    {
        GT_REG_WRITE(SCS_1_LOW_DECODE_ADDRESS,memBank1Base);
        GT_REG_WRITE(SCS_1_HIGH_DECODE_ADDRESS,bank1Top - 1);
        return true;
    }
    else
    {
        GT_REG_WRITE(SCS_1_LOW_DECODE_ADDRESS,0xffff);
        if(bank1Length != 0)
        {
            GT_REG_WRITE(SCS_1_HIGH_DECODE_ADDRESS,bank1Top - 1);
            GT_REG_WRITE(SCS_1_LOW_DECODE_ADDRESS,memBank1Base);
        }
        else
        {
            GT_REG_WRITE(SCS_1_HIGH_DECODE_ADDRESS,0x0);
        }
        return true;
    }
}

/********************************************************************
* memoryMapBank2      - Sets new bases and boundaries for memory bank 2.
*                     - Pay attention to the PCI mappings and make sure to  
*                       coordinate between the two interfaces!!!
*                     - It`s the programmer`s responsibility to make sure there
*                       are no conflicts with other memory spaces!!!
*                     - If a bank needs to be closed , it gives the LOW max
*                       value (0xffff) and to the HIGH min value (0x0).
*
*
* INPUTS: unsigned int bank2Base - required bank 2 base address.
*         unsigned int bank2Length - required bank 2 size.
* RETURNS: true on success, false on failure
*********************************************************************/
bool memoryMapBank2(unsigned int bank2Base,unsigned int bank2Length) 
{
    unsigned int memBank2Base , bank2Top;
    unsigned int mainBank2Top = bank2Base + bank2Length;
    unsigned int currentLow;
    unsigned int baseOld;
    
    GT_REG_READ(SCS_2_LOW_DECODE_ADDRESS,&currentLow);
    baseOld = currentLow << 20;
    memBank2Base = bank2Base >> 20;
    memBank2Base = (memBank2Base & 0xffff) | (currentLow & 0xffff0000);
    bank2Top  = mainBank2Top >> 20;   
    if ((bank2Base >= baseOld) && (baseOld < mainBank2Top))
    {
        GT_REG_WRITE(SCS_2_LOW_DECODE_ADDRESS,memBank2Base);
        GT_REG_WRITE(SCS_2_HIGH_DECODE_ADDRESS,bank2Top - 1);
        return true;
    }
    else
    {
        GT_REG_WRITE(SCS_2_LOW_DECODE_ADDRESS,0xffff);
        if(bank2Length != 0)
        {
            GT_REG_WRITE(SCS_2_HIGH_DECODE_ADDRESS,bank2Top - 1);
            GT_REG_WRITE(SCS_2_LOW_DECODE_ADDRESS,memBank2Base);
        }
        else
        {
            GT_REG_WRITE(SCS_2_HIGH_DECODE_ADDRESS,0x0);
        }
        return true;
    }
}

/********************************************************************
* memoryMapBank3      - Sets new bases and boundaries for memory bank 3.
*                     - Pay attention to the PCI mappings and make sure to  
*                       coordinate between the two interfaces!!!
*                     - It`s the programmer`s responsibility to make sure there
*                       are no conflicts with other memory spaces!!!
*                     - If a bank needs to be closed , it gives the LOW max
*                       value (0xffff) and to the HIGH min value (0x0).
*
*
* INPUTS: unsigned int bank3Base - required bank 3 base address.
*         unsigned int bank3Length - required bank 3 size.
* RETURNS: true on success, false on failure
*********************************************************************/
bool memoryMapBank3(unsigned int bank3Base,unsigned int bank3Length) 
{
    
    unsigned int memBank3Base , bank3Top;
    unsigned int mainBank3Top = bank3Base + bank3Length;
    unsigned int currentLow;
    unsigned int baseOld;
    
    GT_REG_READ(SCS_3_LOW_DECODE_ADDRESS,&currentLow);
    baseOld = currentLow << 20;
    memBank3Base = bank3Base >> 20;
    memBank3Base = (memBank3Base & 0xffff) | (currentLow & 0xffff0000);
    bank3Top  = mainBank3Top >> 20;   
    if ((bank3Base >= baseOld) && (baseOld < mainBank3Top))
    {
        GT_REG_WRITE(SCS_3_LOW_DECODE_ADDRESS,memBank3Base);
        GT_REG_WRITE(SCS_3_HIGH_DECODE_ADDRESS,bank3Top - 1);
        return true;
    }
    else
    {
        GT_REG_WRITE(SCS_3_LOW_DECODE_ADDRESS,0xffff);
        if(bank3Length != 0)
        {
            GT_REG_WRITE(SCS_3_HIGH_DECODE_ADDRESS,bank3Top - 1);
            GT_REG_WRITE(SCS_3_LOW_DECODE_ADDRESS,memBank3Base);
        }
        else
        {
            GT_REG_WRITE(SCS_3_HIGH_DECODE_ADDRESS,0x0);
        }
        return true;
    }
}

/********************************************************************
* memoryMapDevice0Space - Sets new bases and boundaries for device 0.
*                       - Pay attention to the PCI mappings and make sure to 
*                         coordinate between the two interfaces!!!
*                       - It`s the programmer`s responsibility to make sure 
*                         there are no conflicts with other memory spaces!!!
*                       - If a device needs to be closed , it gives the LOW max
*                         value (0xffff) and to the HIGH min value (0x0).
*
*
* INPUTS: unsigned int device0Base - required cs_0 base address.
*         unsigned int device0Length - required cs_0 size.
* RETURNS: true on success, false on failure
*********************************************************************/
bool memoryMapDevice0Space(unsigned int device0Base,unsigned int device0Length) 
{
    unsigned int bank0Base,bank0Top;
    unsigned int deviceBank0Top = (unsigned int)(device0Base + device0Length);
    
    bank0Base = device0Base >> 20;
    bank0Top = deviceBank0Top >> 20;
    GT_REG_WRITE(CS_0_LOW_DECODE_ADDRESS,0xffff);
    if(device0Length != 0)
    {
        GT_REG_WRITE(CS_0_HIGH_DECODE_ADDRESS,bank0Top -1);
        GT_REG_WRITE(CS_0_LOW_DECODE_ADDRESS,bank0Base);
    }
    else
    {
        GT_REG_WRITE(CS_0_HIGH_DECODE_ADDRESS,0x0);
    }
    return true;
}

/********************************************************************
* memoryMapDevice1Space - Sets new bases and boundaries for device 1.
*                       - Pay attention to the PCI mappings and make sure to 
*                         coordinate between the two interfaces!!!
*                       - It`s the programmer`s responsibility to make sure there
*                         are no conflicts with other memory spaces!!!
*                       - If a device needs to be closed , it gives the LOW max
*                         value (0xffff) and to the HIGH min value (0x0).
*
*
* INPUTS: unsigned int device1Base - required cs_1 base address.
*         unsigned int device1Length - required cs_1 size.
* RETURNS: true on success, false on failure
*********************************************************************/
bool memoryMapDevice1Space(unsigned int device1Base,unsigned int device1Length) 
{
    unsigned int bank1Base,bank1Top;
    unsigned int deviceBank1Top = (unsigned int)(device1Base + device1Length);

    bank1Base = device1Base >> 20;
    bank1Top = deviceBank1Top >> 20;
    GT_REG_WRITE(CS_1_LOW_DECODE_ADDRESS,0xffff);
    if(device1Length != 0)
    {
        GT_REG_WRITE(CS_1_HIGH_DECODE_ADDRESS,bank1Top -1);
        GT_REG_WRITE(CS_1_LOW_DECODE_ADDRESS,bank1Base);
    }
    else
    {
        GT_REG_WRITE(CS_1_HIGH_DECODE_ADDRESS,0x0);
    }
    return true;
}

/********************************************************************
* memoryMapDevice2Space - Sets new bases and boundaries for device 2.
*                       - Pay attention to the PCI mappings and make sure to 
*                         coordinate between the two interfaces!!!
*                       - It`s the programmer`s responsibility to make sure there
*                         are no conflicts with other memory spaces!!!
*                       - If a device needs to be closed , it gives the LOW max
*                         value (0xffff) and to the HIGH min value (0x0).
*
*
* INPUTS: unsigned int device2Base - required cs_2 base address.
*         unsigned int device2Length - required cs_2 size.
* RETURNS: true on success, false on failure
*********************************************************************/
bool memoryMapDevice2Space(unsigned int device2Base,unsigned int device2Length) 
{
    unsigned int bank2Base,bank2Top;
    unsigned int deviceBank2Top = (unsigned int)(device2Base + device2Length);

    bank2Base = device2Base >> 20;
    bank2Top = deviceBank2Top >> 20;
    GT_REG_WRITE(CS_2_LOW_DECODE_ADDRESS,0xffff);
    if(device2Length != 0)
    {
        GT_REG_WRITE( CS_2_HIGH_DECODE_ADDRESS, bank2Top - 1);
        GT_REG_WRITE(CS_2_LOW_DECODE_ADDRESS,bank2Base);
    }
    else
    {
        GT_REG_WRITE(CS_2_HIGH_DECODE_ADDRESS,0x0);
    }
    return true;
}


/********************************************************************
* memoryMapDevice3Space - Sets new bases and boundaries for device: 3
*                       - Pay attention to the PCI mappings and make sure to 
*                         coordinate between the two interfaces!!!
*                       - It is the programmer`s responsibility to make sure 
*                         there are no conflicts with other memory spaces!!!
*                       - If a device needs to be closed , it gives the LOW max
*                         value (0xffff) and to the HIGH min value (0x0).
*
*
* INPUTS: unsigned int device3Base - required cs_3 base address.
*         unsigned int device3Length - required cs_3 size.
* RETURNS: true on success, false on failure
*********************************************************************/
bool memoryMapDevice3Space(unsigned int device3Base,unsigned int device3Length) 
{
    unsigned int bank3Base,bank3Top;
    unsigned int deviceBank3Top = (unsigned int)(device3Base + device3Length);

    bank3Base = device3Base >> 20;
    bank3Top = deviceBank3Top >> 20;
    GT_REG_WRITE(CS_3_LOW_DECODE_ADDRESS,0xffff);
    if(device3Length != 0)
    {
        GT_REG_WRITE( CS_3_HIGH_DECODE_ADDRESS,bank3Top - 1);
        GT_REG_WRITE(CS_3_LOW_DECODE_ADDRESS,bank3Base);
    }
    else
    {
        GT_REG_WRITE( CS_3_HIGH_DECODE_ADDRESS, 0x0);
    }
    return true;
}

/********************************************************************
* memoryMapDeviceBootSpace - Sets new bases and boundaries for device: boot
*                          - Pay attention to the PCI mappings and make sure  
*                            to coordinate between the two interfaces!!!
*                          - It is the programmer`s responsibility to make sure 
*                            there are no conflicts with other memory spaces!!!
*                          - If a device needs to be closed , it gives the LOW 
*                            max value (0xffff) and to the HIGH min value (0x0).
*
*
* INPUTS: unsigned int bootDeviceBase - required cs_boot base address.
*         unsigned int bootDeviceLength - required cs_boot size.
* RETURNS: true on success, false on failure
*********************************************************************/
bool memoryMapDeviceBootSpace(unsigned int bootDeviceBase,
                              unsigned int bootDeviceLength) 
{
    unsigned int bootBankBase,bootBankTop;
    unsigned int bootDeviceBankTop = 
        (unsigned int)(bootDeviceBase + bootDeviceLength);

    bootBankBase = bootDeviceBase >> 20;
    bootBankTop = bootDeviceBankTop >> 20;
    GT_REG_WRITE(BOOTCS_LOW_DECODE_ADDRESS,0xffff);
    if(bootDeviceLength != 0)
    {
        GT_REG_WRITE(BOOTCS_HIGH_DECODE_ADDRESS,bootBankTop -1);
        GT_REG_WRITE(BOOTCS_LOW_DECODE_ADDRESS,bootBankBase);
    }
    else
    {
        GT_REG_WRITE(BOOTCS_HIGH_DECODE_ADDRESS,0x0);
    }
    return true;
}

/********************************************************************
* memoryMapInternalRegistersSpace - Sets new base address for the internals 
*                                   registers.
*
* INPUTS:  unsigned int internalRegBase - The new base address.
* RETURNS: true on success, false on failure
*********************************************************************/
bool memoryMapInternalRegistersSpace(unsigned int internalRegBase)
{
    unsigned int currentValue;
    unsigned int internalValue = internalRegBase;

    internalRegBase = (internalRegBase >> 20);
    GT_REG_READ(INTERNAL_SPACE_DECODE,&currentValue);
    internalRegBase = (currentValue & 0xffff0000) | internalRegBase;
    GT_REG_WRITE(INTERNAL_SPACE_DECODE,internalRegBase);
    INTERNAL_REG_BASE_ADDR = internalValue;
    return true;
}

/********************************************************************
* memoryGetInternalRegistersSpace - Gets internal registers Base Address.
*
* INPUTS:  unsigned int internalRegBase - The new base address.
* RETURNS: true on success, false on failure
*********************************************************************/
unsigned int memoryGetInternalRegistersSpace(void)
{
    return INTERNAL_REG_BASE_ADDR;
}

/********************************************************************
* memorySetProtectRegion - This function modifys one of the 8 regions with 
*                          one of the three protection mode.
*                        - Be advised to check the spec before modifying them.
*
*
* Inputs: CPU_PROTECT_REGION - one of the eight regions.
*         CPU_ACCESS - general access.
*         CPU_WRITE - read only access.
*         CPU_CACHE_PROTECT - chache access.
*      we defining CPU because there is another protect from the pci SIDE.             
* Returns: false if one of the parameters is wrong and true else
*********************************************************************/
bool memorySetProtectRegion(MEMORY_PROTECT_REGION region,
                            MEMORY_ACCESS memAccess,
                            MEMORY_ACCESS_WRITE memWrite,
                            MEMORY_CACHE_PROTECT cacheProtection,
                            unsigned int baseAddress, 
                            unsigned int regionLength)
{
    unsigned int protectHigh = baseAddress + regionLength;

    if(regionLength == 0) /* closing the region */
    {
        GT_REG_WRITE(CPU_LOW_PROTECT_ADDRESS_0 + 0x10*region,0x0000ffff);
        GT_REG_WRITE(CPU_HIGH_PROTECT_ADDRESS_0 + 0x10*region,0);
        return true;
    }
    baseAddress =  (baseAddress & 0xfff00000) >> 20;
    baseAddress = baseAddress | memAccess << 16 |  memWrite << 17
                     | cacheProtection << 18;
    GT_REG_WRITE(CPU_LOW_PROTECT_ADDRESS_0 + 0x10*region,baseAddress);
    protectHigh = (protectHigh & 0xfff00000) >> 20;
    GT_REG_WRITE(CPU_HIGH_PROTECT_ADDRESS_0 + 0x10*region,protectHigh - 1);
    return true;
}

/********************************************************************
* memorySetRegionSnoopMode - This function modifys one of the 4 regions which   
*                            supports Cache Coherency.
*
*
* Inputs: SNOOP_REGION region - One of the four regions.
*         SNOOP_TYPE snoopType - There is four optional Types:
*                               1. No Snoop.
*                               2. Snoop to WT region.
*                               3. Snoop to WB region.
*                               4. Snoop & Invalidate to WB region.
*         unsigned int baseAddress - Base Address of this region.
*         unsigned int topAddress - Top Address of this region.
* Returns: false if one of the parameters is wrong and true else
*********************************************************************/
bool memorySetRegionSnoopMode(MEMORY_SNOOP_REGION region,
                              MEMORY_SNOOP_TYPE snoopType,
                              unsigned int baseAddress,
                              unsigned int regionLength)
{
    unsigned int snoopXbaseAddress;
    unsigned int snoopXtopAddress;
    unsigned int data;
    unsigned int snoopHigh = baseAddress + regionLength;

    if( (region > MEM_SNOOP_REGION3) || (snoopType > MEM_SNOOP_WB) )
        return false;
    snoopXbaseAddress = SNOOP_BASE_ADDRESS_0 + 0x10 * region;
    snoopXtopAddress = SNOOP_TOP_ADDRESS_0 + 0x10 * region;
    if(regionLength == 0) /* closing the region */
    {
        GT_REG_WRITE(snoopXbaseAddress,0x0000ffff);
        GT_REG_WRITE(snoopXtopAddress,0);
        return true;
    }
    baseAddress = baseAddress & 0xffff0000;
    data = (baseAddress >> 16) | snoopType << 16;
    GT_REG_WRITE(snoopXbaseAddress,data);
    snoopHigh = (snoopHigh & 0xfff00000) >> 20;
    GT_REG_WRITE(snoopXtopAddress,snoopHigh - 1);
    return true;
}

/********************************************************************
* memoryRemapAddress - This fubction used for address remapping.
*
* 
* Inputs: regOffset: remap register 
*         remapValue : 
* Returns: false if one of the parameters is erroneous,true otherwise.
*********************************************************************/
bool memoryRemapAddress(unsigned int remapReg, unsigned int remapValue)
{
    unsigned int valueForReg;
    valueForReg = (remapValue & 0xfff00000) >> 20;
    GT_REG_WRITE(remapReg, valueForReg);
    return true;
}

/********************************************************************
* memoryGetDeviceParam - This function used for getting device parameters from 
*                        DEVICE BANK PARAMETERS REGISTER
*
*
* Inputs:        - deviceParam: STRUCT with paramiters for DEVICE BANK 
*                  PARAMETERS REGISTER  
*                - deviceNum : number of device
* Returns: false if one of the parameters is erroneous,true otherwise.
*********************************************************************/
bool memoryGetDeviceParam(DEVICE_PARAM *deviceParam, DEVICE deviceNum)
{
    unsigned int valueOfReg;
    unsigned int calcData;

    GT_REG_READ(DEVICE_BANK0PARAMETERS + 4 * deviceNum, &valueOfReg);
    calcData = (0x7 & valueOfReg) + ((0x400000 & valueOfReg) >> 19);
    deviceParam -> turnOff = calcData;          /* Turn Off */

    calcData = ((0x78 & valueOfReg) >> 3) + ((0x800000 & valueOfReg) >> 19);
    deviceParam -> acc2First = calcData;        /* Access To First */

    calcData = ((0x780 & valueOfReg) >> 7) + ((0x1000000 & valueOfReg) >> 20);
    deviceParam -> acc2Next = calcData;         /* Access To Next */
                                                
    calcData = ((0x3800 & valueOfReg) >> 11) + ((0x2000000 & valueOfReg) >> 22);
    deviceParam -> ale2Wr = calcData;           /* Ale To Write */
                                                
    calcData = ((0x1c000 & valueOfReg) >> 14) + ((0x4000000 & valueOfReg) >> 23);
    deviceParam -> wrLow = calcData;            /* Write Active */

    calcData = ((0xe0000 & valueOfReg) >> 17) + ((0x8000000 & valueOfReg) >> 24);
    deviceParam -> wrHigh = calcData;           /* Write High */

    calcData = ((0x300000 & valueOfReg) >> 20);
    switch (calcData) 
    {       
    case 0:
        deviceParam -> deviceWidth = 1;         /* one Byte - 8-bit */
        break;
    case 1:
        deviceParam -> deviceWidth = 2;         /* two Bytes - 16-bit */
        break;
    case 2:
        deviceParam -> deviceWidth = 4;         /* four Bytes - 32-bit */
        break;
    case 3:
        deviceParam -> deviceWidth = 8;         /* eight Bytes - 64-bit */
        break;
    default:
        deviceParam -> deviceWidth = 1;
        break;
    }
    return true;
}

/********************************************************************
* memorySetDeviceParam - This function used for setting device parameters to 
*                        DEVICE BANK PARAMETERS REGISTER
*
*
* Inputs:        - deviceParam: STRUCT for store paramiters from DEVICE BANK 
*                  PARAMETERS REGISTER  
*                - deviceNum : number of device
* Returns: false if one of the parameters is erroneous,true otherwise.
*********************************************************************/
bool memorySetDeviceParam(DEVICE_PARAM *deviceParam, DEVICE deviceNum)
{
    unsigned int valueForReg;

    if((deviceParam -> turnOff >= 0xf) || (deviceParam -> acc2First >= 0x1f) || 
       (deviceParam -> acc2Next >= 0x1f) || (deviceParam -> ale2Wr >= 0xf) ||
        (deviceParam -> wrLow >= 0xf) || (deviceParam -> wrHigh >= 0xf))
        return false;
    valueForReg = (((deviceParam -> turnOff) & 0x7) |
                   (((deviceParam -> turnOff) & 0x8) << 19) |
                   (((deviceParam -> acc2First) & 0xf) << 3) |
                   (((deviceParam -> acc2First) & 0x10) << 19) |
                   (((deviceParam -> acc2Next) & 0xf) << 7) |
                   (((deviceParam -> acc2Next) & 0x10) << 20) |
                   (((deviceParam -> ale2Wr) & 0x7) << 11) |
                   (((deviceParam -> ale2Wr) & 0xf) << 22) |
                   (((deviceParam -> wrLow) & 0x7) << 14) |
                   (((deviceParam -> wrLow) & 0xf) << 23) |
                   (((deviceParam -> wrHigh) & 0x7) << 17) |
                   (((deviceParam -> wrHigh) & 0xf) << 24));
    /* insert the device width: */
    switch(deviceParam->deviceWidth)
    {
    case 1:
        valueForReg = valueForReg | _8BIT;
        break;
    case 2:
        valueForReg = valueForReg | _16BIT;
        break;
    case 4:
        valueForReg = valueForReg | _32BIT;
        break;
    case 8:
        valueForReg = valueForReg | _64BIT;
        break;
    default:
        valueForReg = valueForReg | _8BIT;
        break;
    }
    GT_REG_WRITE(DEVICE_BANK0PARAMETERS + 4 * deviceNum, valueForReg);
    return true;
}
