|  | /** | 
|  | * @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); | 
|  | } | 
|  | } |