mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-01 00:49:43 +00:00
84ad688473
Signed-off-by: Peter Tyser <ptyser@xes-inc.com>
332 lines
11 KiB
C
332 lines
11 KiB
C
/**
|
|
* @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);
|
|
}
|
|
}
|