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