blob: 34df92bf79f63c6a5bab9156f321851e54d5e306 [file] [log] [blame]
Wolfgang Denkba94a1b2006-05-30 15:56:48 +02001/**
2 * @file IxOsalIoMem.c
3 *
4 * @brief OS-independent IO/Mem implementation
5 *
6 *
7 * @par
8 * IXP400 SW Release version 2.0
9 *
10 * -- Copyright Notice --
11 *
12 * @par
13 * Copyright 2001-2005, Intel Corporation.
14 * All rights reserved.
15 *
16 * @par
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 * notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 * 3. Neither the name of the Intel Corporation nor the names of its contributors
26 * may be used to endorse or promote products derived from this software
27 * without specific prior written permission.
28 *
29 * @par
30 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
31 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 *
42 * @par
43 * -- End of Copyright Notice --
44 */
45
46/* Access to the global mem map is only allowed in this file */
47#define IxOsalIoMem_C
48
49#include "IxOsal.h"
50
51#define SEARCH_PHYSICAL_ADDRESS (1)
52#define SEARCH_VIRTUAL_ADDRESS (2)
53
54/*
55 * Searches for map using one of the following criteria:
56 *
57 * - enough room to include a zone starting with the physical "requestedAddress" of size "size" (for mapping)
58 * - includes the virtual "requestedAddress" in its virtual address space (already mapped, for unmapping)
59 * - correct coherency
60 *
61 * Returns a pointer to the map or NULL if a suitable map is not found.
62 */
63PRIVATE IxOsalMemoryMap *
64ixOsalMemMapFind (UINT32 requestedAddress,
65 UINT32 size, UINT32 searchCriteria, UINT32 requestedEndianType)
66{
67 UINT32 mapIndex;
68
69 UINT32 numMapElements =
70 sizeof (ixOsalGlobalMemoryMap) / sizeof (IxOsalMemoryMap);
71
72 for (mapIndex = 0; mapIndex < numMapElements; mapIndex++)
73 {
74 IxOsalMemoryMap *map = &ixOsalGlobalMemoryMap[mapIndex];
75
76 if (searchCriteria == SEARCH_PHYSICAL_ADDRESS
77 && requestedAddress >= map->physicalAddress
78 && (requestedAddress + size) <= (map->physicalAddress + map->size)
79 && (map->mapEndianType & requestedEndianType) != 0)
80 {
81 return map;
82 }
83 else if (searchCriteria == SEARCH_VIRTUAL_ADDRESS
84 && requestedAddress >= map->virtualAddress
85 && requestedAddress <= (map->virtualAddress + map->size)
86 && (map->mapEndianType & requestedEndianType) != 0)
87 {
88 return map;
89 }
90 else if (searchCriteria == SEARCH_PHYSICAL_ADDRESS)
91 {
92 ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
93 IX_OSAL_LOG_DEV_STDOUT,
94 "Osal: Checking [phys addr 0x%x:size 0x%x:endianType %d]\n",
95 map->physicalAddress, map->size, map->mapEndianType, 0, 0, 0);
96 }
97 }
98
99 /*
100 * not found
101 */
102 return NULL;
103}
104
105/*
106 * This function maps an I/O mapped physical memory zone of the given size
107 * into a virtual memory zone accessible by the caller and returns a cookie -
108 * the start address of the virtual memory zone.
109 * IX_OSAL_MMAP_PHYS_TO_VIRT should NOT therefore be used on the returned
110 * virtual address.
111 * The memory zone is to be unmapped using ixOsalMemUnmap once the caller has
112 * finished using this zone (e.g. on driver unload) using the cookie as
113 * parameter.
114 * The IX_OSAL_READ/WRITE_LONG/SHORT macros should be used to read and write
115 * the mapped memory, adding the necessary offsets to the address cookie.
116 *
117 * Note: this function is not to be used directly. Use IX_OSAL_MEM_MAP
118 * instead.
119 */
120PUBLIC void *
121ixOsalIoMemMap (UINT32 requestedAddress,
122 UINT32 size, IxOsalMapEndianessType requestedEndianType)
123{
124 IxOsalMemoryMap *map;
125
126 ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
127 IX_OSAL_LOG_DEV_STDOUT,
128 "OSAL: Mapping [addr 0x%x:size 0x%x:endianType %d]\n",
129 requestedAddress, size, requestedEndianType, 0, 0, 0);
130
131 if (requestedEndianType == IX_OSAL_LE)
132 {
133 ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
134 IX_OSAL_LOG_DEV_STDOUT,
135 "ixOsalIoMemMap: Please specify component coherency mode to use MEM functions \n",
136 0, 0, 0, 0, 0, 0);
137 return (NULL);
138 }
139 map = ixOsalMemMapFind (requestedAddress,
140 size, SEARCH_PHYSICAL_ADDRESS, requestedEndianType);
141 if (map != NULL)
142 {
143 UINT32 offset = requestedAddress - map->physicalAddress;
144
145 ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
146 IX_OSAL_LOG_DEV_STDOUT, "OSAL: Found map [", 0, 0, 0, 0, 0, 0);
147 ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
148 IX_OSAL_LOG_DEV_STDOUT, map->name, 0, 0, 0, 0, 0, 0);
149 ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
150 IX_OSAL_LOG_DEV_STDOUT,
151 ":addr 0x%x: virt 0x%x:size 0x%x:ref %d:endianType %d]\n",
152 map->physicalAddress, map->virtualAddress,
153 map->size, map->refCount, map->mapEndianType, 0);
154
155 if (map->type == IX_OSAL_DYNAMIC_MAP && map->virtualAddress == 0)
156 {
157 if (map->mapFunction != NULL)
158 {
159 map->mapFunction (map);
160
161 if (map->virtualAddress == 0)
162 {
163 /*
164 * failed
165 */
166 ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
167 IX_OSAL_LOG_DEV_STDERR,
168 "OSAL: Remap failed - [addr 0x%x:size 0x%x:endianType %d]\n",
169 requestedAddress, size, requestedEndianType, 0, 0, 0);
170 return NULL;
171 }
172 }
173 else
174 {
175 /*
176 * error, no map function for a dynamic map
177 */
178 ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
179 IX_OSAL_LOG_DEV_STDERR,
180 "OSAL: No map function for a dynamic map - "
181 "[addr 0x%x:size 0x%x:endianType %d]\n",
182 requestedAddress, size, requestedEndianType, 0, 0, 0);
183
184 return NULL;
185 }
186 }
187
188 /*
189 * increment reference count
190 */
191 map->refCount++;
192
193 return (void *) (map->virtualAddress + offset);
194 }
195
196 /*
197 * requested address is not described in the global memory map
198 */
199 ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
200 IX_OSAL_LOG_DEV_STDERR,
201 "OSAL: No mapping found - [addr 0x%x:size 0x%x:endianType %d]\n",
202 requestedAddress, size, requestedEndianType, 0, 0, 0);
203 return NULL;
204}
205
206/*
207 * This function unmaps a previously mapped I/O memory zone using
208 * the cookie obtained in the mapping operation. The memory zone in question
209 * becomes unavailable to the caller once unmapped and the cookie should be
210 * discarded.
211 *
212 * This function cannot fail if the given parameter is correct and does not
213 * return a value.
214 *
215 * Note: this function is not to be used directly. Use IX_OSAL_MEM_UNMAP
216 * instead.
217 */
218PUBLIC void
219ixOsalIoMemUnmap (UINT32 requestedAddress, UINT32 endianType)
220{
221 IxOsalMemoryMap *map;
222
223 if (endianType == IX_OSAL_LE)
224 {
225 ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
226 IX_OSAL_LOG_DEV_STDOUT,
227 "ixOsalIoMemUnmap: Please specify component coherency mode to use MEM functions \n",
228 0, 0, 0, 0, 0, 0);
229 return;
230 }
231
232 if (requestedAddress == 0)
233 {
234 /*
235 * invalid virtual address
236 */
237 return;
238 }
239
240 map =
241 ixOsalMemMapFind (requestedAddress, 0, SEARCH_VIRTUAL_ADDRESS,
242 endianType);
243
244 if (map != NULL)
245 {
246 if (map->refCount > 0)
247 {
248 /*
249 * decrement reference count
250 */
251 map->refCount--;
252
253 if (map->refCount == 0)
254 {
255 /*
256 * no longer used, deallocate
257 */
258 if (map->type == IX_OSAL_DYNAMIC_MAP
259 && map->unmapFunction != NULL)
260 {
261 map->unmapFunction (map);
262 }
263 }
264 }
265 }
266 else
267 {
268 ixOsalLog (IX_OSAL_LOG_LVL_WARNING,
269 IX_OSAL_LOG_DEV_STDERR,
270 "OSAL: ixOsServMemUnmap didn't find the requested map "
271 "[virt addr 0x%x: endianType %d], ignoring call\n",
272 requestedAddress, endianType, 0, 0, 0, 0);
273 }
274}
275
276/*
277 * This function Converts a virtual address into a physical
278 * address, including the dynamically mapped memory.
279 *
280 * Parameters virtAddr - virtual address to convert
281 * Return value: corresponding physical address, or NULL
282 * if there is no physical address addressable
283 * by the given virtual address
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200284 * OS: VxWorks, Linux, WinCE, QNX, eCos
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200285 * Reentrant: Yes
286 * IRQ safe: Yes
287 */
288PUBLIC UINT32
289ixOsalIoMemVirtToPhys (UINT32 virtualAddress, UINT32 requestedCoherency)
290{
291 IxOsalMemoryMap *map =
292 ixOsalMemMapFind (virtualAddress, 0, SEARCH_VIRTUAL_ADDRESS,
293 requestedCoherency);
294
295 if (map != NULL)
296 {
297 return map->physicalAddress + virtualAddress - map->virtualAddress;
298 }
299 else
300 {
301 return (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS (virtualAddress);
302 }
303}
304
305/*
306 * This function Converts a virtual address into a physical
307 * address, including the dynamically mapped memory.
308 *
309 * Parameters virtAddr - virtual address to convert
310 * Return value: corresponding physical address, or NULL
311 * if there is no physical address addressable
312 * by the given virtual address
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200313 * OS: VxWorks, Linux, WinCE, QNX, eCos
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200314 * Reentrant: Yes
315 * IRQ safe: Yes
316 */
317PUBLIC UINT32
318ixOsalIoMemPhysToVirt (UINT32 physicalAddress, UINT32 requestedCoherency)
319{
320 IxOsalMemoryMap *map =
321 ixOsalMemMapFind (physicalAddress, 0, SEARCH_PHYSICAL_ADDRESS,
322 requestedCoherency);
323
324 if (map != NULL)
325 {
326 return map->virtualAddress + physicalAddress - map->physicalAddress;
327 }
328 else
329 {
330 return (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (physicalAddress);
331 }
332}