| /** |
| * @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 |
| * SPDX-License-Identifier: BSD-3-Clause |
| * @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 = ARRAY_SIZE(ixOsalGlobalMemoryMap); |
| |
| 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); |
| } |
| } |