/**
 * @file IxOsalIoMem.c 
 *
 * @brief OS-independent IO/Mem implementation 
 * 
 * 
 * @par
 * IXP400 SW Release version 2.0
 * 
 * -- Copyright Notice --
 * 
 * @par
 * Copyright 2001-2005, Intel Corporation.
 * All rights reserved.
 * 
 * @par
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Intel Corporation nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 * 
 * @par
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * 
 * @par
 * -- End of Copyright Notice --
 */

/* Access to the global mem map is only allowed in this file */
#define IxOsalIoMem_C

#include "IxOsal.h"

#define SEARCH_PHYSICAL_ADDRESS (1)
#define SEARCH_VIRTUAL_ADDRESS  (2)

/*
 * Searches for map using one of the following criteria:
 * 
 * - enough room to include a zone starting with the physical "requestedAddress" of size "size" (for mapping)
 * - includes the virtual "requestedAddress" in its virtual address space (already mapped, for unmapping)
 * - correct coherency
 *
 * Returns a pointer to the map or NULL if a suitable map is not found.
 */
PRIVATE IxOsalMemoryMap *
ixOsalMemMapFind (UINT32 requestedAddress,
    UINT32 size, UINT32 searchCriteria, UINT32 requestedEndianType)
{
    UINT32 mapIndex;

    UINT32 numMapElements =
        sizeof (ixOsalGlobalMemoryMap) / sizeof (IxOsalMemoryMap);

    for (mapIndex = 0; mapIndex < numMapElements; mapIndex++)
    {
        IxOsalMemoryMap *map = &ixOsalGlobalMemoryMap[mapIndex];

        if (searchCriteria == SEARCH_PHYSICAL_ADDRESS
            && requestedAddress >= map->physicalAddress
            && (requestedAddress + size) <= (map->physicalAddress + map->size)
            && (map->mapEndianType & requestedEndianType) != 0)
        {
            return map;
        }
        else if (searchCriteria == SEARCH_VIRTUAL_ADDRESS
            && requestedAddress >= map->virtualAddress
            && requestedAddress <= (map->virtualAddress + map->size)
            && (map->mapEndianType & requestedEndianType) != 0)
        {
            return map;
        }
        else if (searchCriteria == SEARCH_PHYSICAL_ADDRESS)
        {
            ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
                IX_OSAL_LOG_DEV_STDOUT,
                "Osal: Checking [phys addr 0x%x:size 0x%x:endianType %d]\n",
                map->physicalAddress, map->size, map->mapEndianType, 0, 0, 0);
        }
    }

    /*
     * not found 
     */
    return NULL;
}

/*
 * This function maps an I/O mapped physical memory zone of the given size
 * into a virtual memory zone accessible by the caller and returns a cookie - 
 * the start address of the virtual memory zone. 
 * IX_OSAL_MMAP_PHYS_TO_VIRT should NOT therefore be used on the returned 
 * virtual address.
 * The memory zone is to be unmapped using ixOsalMemUnmap once the caller has
 * finished using this zone (e.g. on driver unload) using the cookie as 
 * parameter.
 * The IX_OSAL_READ/WRITE_LONG/SHORT macros should be used to read and write 
 * the mapped memory, adding the necessary offsets to the address cookie.
 *
 * Note: this function is not to be used directly. Use IX_OSAL_MEM_MAP 
 * instead.
 */
PUBLIC void *
ixOsalIoMemMap (UINT32 requestedAddress,
    UINT32 size, IxOsalMapEndianessType requestedEndianType)
{
    IxOsalMemoryMap *map;

    ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
        IX_OSAL_LOG_DEV_STDOUT,
        "OSAL: Mapping [addr 0x%x:size 0x%x:endianType %d]\n",
        requestedAddress, size, requestedEndianType, 0, 0, 0);

    if (requestedEndianType == IX_OSAL_LE)
    {
        ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
            IX_OSAL_LOG_DEV_STDOUT,
            "ixOsalIoMemMap: Please specify component coherency mode to use MEM functions \n",
            0, 0, 0, 0, 0, 0);
        return (NULL);
    }
    map = ixOsalMemMapFind (requestedAddress,
        size, SEARCH_PHYSICAL_ADDRESS, requestedEndianType);
    if (map != NULL)
    {
        UINT32 offset = requestedAddress - map->physicalAddress;

        ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
            IX_OSAL_LOG_DEV_STDOUT, "OSAL: Found map [", 0, 0, 0, 0, 0, 0);
        ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
            IX_OSAL_LOG_DEV_STDOUT, map->name, 0, 0, 0, 0, 0, 0);
        ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
            IX_OSAL_LOG_DEV_STDOUT,
            ":addr 0x%x: virt 0x%x:size 0x%x:ref %d:endianType %d]\n",
            map->physicalAddress, map->virtualAddress,
            map->size, map->refCount, map->mapEndianType, 0);

        if (map->type == IX_OSAL_DYNAMIC_MAP && map->virtualAddress == 0)
        {
            if (map->mapFunction != NULL)
            {
                map->mapFunction (map);

                if (map->virtualAddress == 0)
                {
                    /*
                     * failed 
                     */
                    ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
                        IX_OSAL_LOG_DEV_STDERR,
                        "OSAL: Remap failed - [addr 0x%x:size 0x%x:endianType %d]\n",
                        requestedAddress, size, requestedEndianType, 0, 0, 0);
                    return NULL;
                }
            }
            else
            {
                /*
                 * error, no map function for a dynamic map 
                 */
                ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
                    IX_OSAL_LOG_DEV_STDERR,
                    "OSAL: No map function for a dynamic map - "
                    "[addr 0x%x:size 0x%x:endianType %d]\n",
                    requestedAddress, size, requestedEndianType, 0, 0, 0);

                return NULL;
            }
        }

        /*
         * increment reference count 
         */
        map->refCount++;

        return (void *) (map->virtualAddress + offset);
    }

    /*
     * requested address is not described in the global memory map 
     */
    ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
        IX_OSAL_LOG_DEV_STDERR,
        "OSAL: No mapping found - [addr 0x%x:size 0x%x:endianType %d]\n",
        requestedAddress, size, requestedEndianType, 0, 0, 0);
    return NULL;
}

/*
 * This function unmaps a previously mapped I/O memory zone using
 * the cookie obtained in the mapping operation. The memory zone in question
 * becomes unavailable to the caller once unmapped and the cookie should be
 * discarded.
 *
 * This function cannot fail if the given parameter is correct and does not
 * return a value.
 *
 * Note: this function is not to be used directly. Use IX_OSAL_MEM_UNMAP
 * instead.
 */
PUBLIC void
ixOsalIoMemUnmap (UINT32 requestedAddress, UINT32 endianType)
{
    IxOsalMemoryMap *map;

    if (endianType == IX_OSAL_LE)
    {
        ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
            IX_OSAL_LOG_DEV_STDOUT,
            "ixOsalIoMemUnmap: Please specify component coherency mode to use MEM functions \n",
            0, 0, 0, 0, 0, 0);
        return;
    }

    if (requestedAddress == 0)
    {
        /*
         * invalid virtual address 
         */
        return;
    }

    map =
        ixOsalMemMapFind (requestedAddress, 0, SEARCH_VIRTUAL_ADDRESS,
        endianType);

    if (map != NULL)
    {
        if (map->refCount > 0)
        {
            /*
             * decrement reference count 
             */
            map->refCount--;

            if (map->refCount == 0)
            {
                /*
                 * no longer used, deallocate 
                 */
                if (map->type == IX_OSAL_DYNAMIC_MAP
                    && map->unmapFunction != NULL)
                {
                    map->unmapFunction (map);
                }
            }
        }
    }
    else
    {
        ixOsalLog (IX_OSAL_LOG_LVL_WARNING,
            IX_OSAL_LOG_DEV_STDERR,
            "OSAL: ixOsServMemUnmap didn't find the requested map "
            "[virt addr 0x%x: endianType %d], ignoring call\n",
            requestedAddress, endianType, 0, 0, 0, 0);
    }
}

/* 
 * This function Converts a virtual address into a physical 
 * address, including the dynamically mapped memory.
 * 
 * Parameters	virtAddr - virtual address to convert
 * Return value: corresponding physical address, or NULL 
 *               if there is no physical address addressable 
 *               by the given virtual address
 * OS: 	VxWorks, Linux, WinCE, QNX, eCos
 * Reentrant: Yes
 * IRQ safe: Yes
 */
PUBLIC UINT32
ixOsalIoMemVirtToPhys (UINT32 virtualAddress, UINT32 requestedCoherency)
{
    IxOsalMemoryMap *map =
        ixOsalMemMapFind (virtualAddress, 0, SEARCH_VIRTUAL_ADDRESS,
        requestedCoherency);

    if (map != NULL)
    {
        return map->physicalAddress + virtualAddress - map->virtualAddress;
    }
    else
    {
        return (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS (virtualAddress);
    }
}

/* 
 * This function Converts a virtual address into a physical 
 * address, including the dynamically mapped memory.
 * 
 * Parameters	virtAddr - virtual address to convert
 * Return value: corresponding physical address, or NULL 
 *               if there is no physical address addressable 
 *               by the given virtual address
 * OS: 	VxWorks, Linux, WinCE, QNX, eCos
 * Reentrant: Yes
 * IRQ safe: Yes
 */
PUBLIC UINT32
ixOsalIoMemPhysToVirt (UINT32 physicalAddress, UINT32 requestedCoherency)
{
    IxOsalMemoryMap *map =
        ixOsalMemMapFind (physicalAddress, 0, SEARCH_PHYSICAL_ADDRESS,
        requestedCoherency);

    if (map != NULL)
    {
        return map->virtualAddress + physicalAddress - map->physicalAddress;
    }
    else
    {
        return (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (physicalAddress);
    }
}
