blob: bf3acdc10c24b1c6f8b424cdf3585da18f9d9fd7 [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
Wolfgang Denkcb3761e2013-07-28 22:12:47 +020017 * SPDX-License-Identifier: BSD-3-Clause
Wolfgang Denkba94a1b2006-05-30 15:56:48 +020018 * @par
19 * -- End of Copyright Notice --
20 */
21
22/* Access to the global mem map is only allowed in this file */
23#define IxOsalIoMem_C
24
25#include "IxOsal.h"
26
27#define SEARCH_PHYSICAL_ADDRESS (1)
28#define SEARCH_VIRTUAL_ADDRESS (2)
29
30/*
31 * Searches for map using one of the following criteria:
32 *
33 * - enough room to include a zone starting with the physical "requestedAddress" of size "size" (for mapping)
34 * - includes the virtual "requestedAddress" in its virtual address space (already mapped, for unmapping)
35 * - correct coherency
36 *
37 * Returns a pointer to the map or NULL if a suitable map is not found.
38 */
39PRIVATE IxOsalMemoryMap *
40ixOsalMemMapFind (UINT32 requestedAddress,
41 UINT32 size, UINT32 searchCriteria, UINT32 requestedEndianType)
42{
43 UINT32 mapIndex;
44
Axel Lina62cd292013-07-03 11:24:18 +080045 UINT32 numMapElements = ARRAY_SIZE(ixOsalGlobalMemoryMap);
Wolfgang Denkba94a1b2006-05-30 15:56:48 +020046
47 for (mapIndex = 0; mapIndex < numMapElements; mapIndex++)
48 {
49 IxOsalMemoryMap *map = &ixOsalGlobalMemoryMap[mapIndex];
50
51 if (searchCriteria == SEARCH_PHYSICAL_ADDRESS
52 && requestedAddress >= map->physicalAddress
53 && (requestedAddress + size) <= (map->physicalAddress + map->size)
54 && (map->mapEndianType & requestedEndianType) != 0)
55 {
56 return map;
57 }
58 else if (searchCriteria == SEARCH_VIRTUAL_ADDRESS
59 && requestedAddress >= map->virtualAddress
60 && requestedAddress <= (map->virtualAddress + map->size)
61 && (map->mapEndianType & requestedEndianType) != 0)
62 {
63 return map;
64 }
65 else if (searchCriteria == SEARCH_PHYSICAL_ADDRESS)
66 {
67 ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
68 IX_OSAL_LOG_DEV_STDOUT,
69 "Osal: Checking [phys addr 0x%x:size 0x%x:endianType %d]\n",
70 map->physicalAddress, map->size, map->mapEndianType, 0, 0, 0);
71 }
72 }
73
74 /*
75 * not found
76 */
77 return NULL;
78}
79
80/*
81 * This function maps an I/O mapped physical memory zone of the given size
82 * into a virtual memory zone accessible by the caller and returns a cookie -
83 * the start address of the virtual memory zone.
84 * IX_OSAL_MMAP_PHYS_TO_VIRT should NOT therefore be used on the returned
85 * virtual address.
86 * The memory zone is to be unmapped using ixOsalMemUnmap once the caller has
87 * finished using this zone (e.g. on driver unload) using the cookie as
88 * parameter.
89 * The IX_OSAL_READ/WRITE_LONG/SHORT macros should be used to read and write
90 * the mapped memory, adding the necessary offsets to the address cookie.
91 *
92 * Note: this function is not to be used directly. Use IX_OSAL_MEM_MAP
93 * instead.
94 */
95PUBLIC void *
96ixOsalIoMemMap (UINT32 requestedAddress,
97 UINT32 size, IxOsalMapEndianessType requestedEndianType)
98{
99 IxOsalMemoryMap *map;
100
101 ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
102 IX_OSAL_LOG_DEV_STDOUT,
103 "OSAL: Mapping [addr 0x%x:size 0x%x:endianType %d]\n",
104 requestedAddress, size, requestedEndianType, 0, 0, 0);
105
106 if (requestedEndianType == IX_OSAL_LE)
107 {
108 ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
109 IX_OSAL_LOG_DEV_STDOUT,
110 "ixOsalIoMemMap: Please specify component coherency mode to use MEM functions \n",
111 0, 0, 0, 0, 0, 0);
112 return (NULL);
113 }
114 map = ixOsalMemMapFind (requestedAddress,
115 size, SEARCH_PHYSICAL_ADDRESS, requestedEndianType);
116 if (map != NULL)
117 {
118 UINT32 offset = requestedAddress - map->physicalAddress;
119
120 ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
121 IX_OSAL_LOG_DEV_STDOUT, "OSAL: Found map [", 0, 0, 0, 0, 0, 0);
122 ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
123 IX_OSAL_LOG_DEV_STDOUT, map->name, 0, 0, 0, 0, 0, 0);
124 ixOsalLog (IX_OSAL_LOG_LVL_DEBUG3,
125 IX_OSAL_LOG_DEV_STDOUT,
126 ":addr 0x%x: virt 0x%x:size 0x%x:ref %d:endianType %d]\n",
127 map->physicalAddress, map->virtualAddress,
128 map->size, map->refCount, map->mapEndianType, 0);
129
130 if (map->type == IX_OSAL_DYNAMIC_MAP && map->virtualAddress == 0)
131 {
132 if (map->mapFunction != NULL)
133 {
134 map->mapFunction (map);
135
136 if (map->virtualAddress == 0)
137 {
138 /*
139 * failed
140 */
141 ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
142 IX_OSAL_LOG_DEV_STDERR,
143 "OSAL: Remap failed - [addr 0x%x:size 0x%x:endianType %d]\n",
144 requestedAddress, size, requestedEndianType, 0, 0, 0);
145 return NULL;
146 }
147 }
148 else
149 {
150 /*
151 * error, no map function for a dynamic map
152 */
153 ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
154 IX_OSAL_LOG_DEV_STDERR,
155 "OSAL: No map function for a dynamic map - "
156 "[addr 0x%x:size 0x%x:endianType %d]\n",
157 requestedAddress, size, requestedEndianType, 0, 0, 0);
158
159 return NULL;
160 }
161 }
162
163 /*
164 * increment reference count
165 */
166 map->refCount++;
167
168 return (void *) (map->virtualAddress + offset);
169 }
170
171 /*
172 * requested address is not described in the global memory map
173 */
174 ixOsalLog (IX_OSAL_LOG_LVL_FATAL,
175 IX_OSAL_LOG_DEV_STDERR,
176 "OSAL: No mapping found - [addr 0x%x:size 0x%x:endianType %d]\n",
177 requestedAddress, size, requestedEndianType, 0, 0, 0);
178 return NULL;
179}
180
181/*
182 * This function unmaps a previously mapped I/O memory zone using
183 * the cookie obtained in the mapping operation. The memory zone in question
184 * becomes unavailable to the caller once unmapped and the cookie should be
185 * discarded.
186 *
187 * This function cannot fail if the given parameter is correct and does not
188 * return a value.
189 *
190 * Note: this function is not to be used directly. Use IX_OSAL_MEM_UNMAP
191 * instead.
192 */
193PUBLIC void
194ixOsalIoMemUnmap (UINT32 requestedAddress, UINT32 endianType)
195{
196 IxOsalMemoryMap *map;
197
198 if (endianType == IX_OSAL_LE)
199 {
200 ixOsalLog (IX_OSAL_LOG_LVL_ERROR,
201 IX_OSAL_LOG_DEV_STDOUT,
202 "ixOsalIoMemUnmap: Please specify component coherency mode to use MEM functions \n",
203 0, 0, 0, 0, 0, 0);
204 return;
205 }
206
207 if (requestedAddress == 0)
208 {
209 /*
210 * invalid virtual address
211 */
212 return;
213 }
214
215 map =
216 ixOsalMemMapFind (requestedAddress, 0, SEARCH_VIRTUAL_ADDRESS,
217 endianType);
218
219 if (map != NULL)
220 {
221 if (map->refCount > 0)
222 {
223 /*
224 * decrement reference count
225 */
226 map->refCount--;
227
228 if (map->refCount == 0)
229 {
230 /*
231 * no longer used, deallocate
232 */
233 if (map->type == IX_OSAL_DYNAMIC_MAP
234 && map->unmapFunction != NULL)
235 {
236 map->unmapFunction (map);
237 }
238 }
239 }
240 }
241 else
242 {
243 ixOsalLog (IX_OSAL_LOG_LVL_WARNING,
244 IX_OSAL_LOG_DEV_STDERR,
245 "OSAL: ixOsServMemUnmap didn't find the requested map "
246 "[virt addr 0x%x: endianType %d], ignoring call\n",
247 requestedAddress, endianType, 0, 0, 0, 0);
248 }
249}
250
251/*
252 * This function Converts a virtual address into a physical
253 * address, including the dynamically mapped memory.
254 *
255 * Parameters virtAddr - virtual address to convert
256 * Return value: corresponding physical address, or NULL
257 * if there is no physical address addressable
258 * by the given virtual address
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200259 * OS: VxWorks, Linux, WinCE, QNX, eCos
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200260 * Reentrant: Yes
261 * IRQ safe: Yes
262 */
263PUBLIC UINT32
264ixOsalIoMemVirtToPhys (UINT32 virtualAddress, UINT32 requestedCoherency)
265{
266 IxOsalMemoryMap *map =
267 ixOsalMemMapFind (virtualAddress, 0, SEARCH_VIRTUAL_ADDRESS,
268 requestedCoherency);
269
270 if (map != NULL)
271 {
272 return map->physicalAddress + virtualAddress - map->virtualAddress;
273 }
274 else
275 {
276 return (UINT32) IX_OSAL_MMU_VIRT_TO_PHYS (virtualAddress);
277 }
278}
279
280/*
281 * This function Converts a virtual address into a physical
282 * address, including the dynamically mapped memory.
283 *
284 * Parameters virtAddr - virtual address to convert
285 * Return value: corresponding physical address, or NULL
286 * if there is no physical address addressable
287 * by the given virtual address
Wolfgang Denk53677ef2008-05-20 16:00:29 +0200288 * OS: VxWorks, Linux, WinCE, QNX, eCos
Wolfgang Denkba94a1b2006-05-30 15:56:48 +0200289 * Reentrant: Yes
290 * IRQ safe: Yes
291 */
292PUBLIC UINT32
293ixOsalIoMemPhysToVirt (UINT32 physicalAddress, UINT32 requestedCoherency)
294{
295 IxOsalMemoryMap *map =
296 ixOsalMemMapFind (physicalAddress, 0, SEARCH_PHYSICAL_ADDRESS,
297 requestedCoherency);
298
299 if (map != NULL)
300 {
301 return map->virtualAddress + physicalAddress - map->physicalAddress;
302 }
303 else
304 {
305 return (UINT32) IX_OSAL_MMU_PHYS_TO_VIRT (physicalAddress);
306 }
307}