Merge trunk head (r43756)
[reactos.git] / reactos / ntoskrnl / mm / ARM3 / iosup.c
1 /*
2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/iosup.c
5 * PURPOSE: ARM Memory Manager I/O Mapping Functionality
6 * PROGRAMMERS: ReactOS Portable Systems Group
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 #line 15 "ARMĀ³::IOSUP"
16 #define MODULE_INVOLVED_IN_ARM3
17 #include "../ARM3/miarm.h"
18
19 /* GLOBALS ********************************************************************/
20
21 //
22 // Each architecture has its own caching attributes for both I/O and Physical
23 // memory mappings.
24 //
25 // This describes the attributes for the x86 architecture. It eventually needs
26 // to go in the appropriate i386 directory.
27 //
28 MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2][MmMaximumCacheType] =
29 {
30 //
31 // RAM
32 //
33 {MiNonCached,MiCached,MiWriteCombined,MiCached,MiNonCached,MiWriteCombined},
34
35 //
36 // Device Memory
37 //
38 {MiNonCached,MiCached,MiWriteCombined,MiCached,MiNonCached,MiWriteCombined},
39 };
40
41 /* PUBLIC FUNCTIONS ***********************************************************/
42
43 /*
44 * @implemented
45 */
46 PVOID
47 NTAPI
48 MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress,
49 IN ULONG NumberOfBytes,
50 IN MEMORY_CACHING_TYPE CacheType)
51 {
52
53 PFN_TYPE Pfn, PageCount;
54 PMMPTE PointerPte;
55 PVOID BaseAddress;
56 MMPTE TempPte;
57 PMMPFN Pfn1 = NULL;
58 MI_PFN_CACHE_ATTRIBUTE CacheAttribute;
59 BOOLEAN IsIoMapping;
60
61 //
62 // Must be called with a non-zero count
63 //
64 ASSERT(NumberOfBytes != 0);
65
66 //
67 // Make sure the upper bits are 0 if this system
68 // can't describe more than 4 GB of physical memory.
69 // FIXME: This doesn't respect PAE, but we currently don't
70 // define a PAE build flag since there is no such build.
71 //
72 #if !defined(_M_AMD64)
73 ASSERT(PhysicalAddress.HighPart == 0);
74 #endif
75
76 //
77 // Normalize and validate the caching attributes
78 //
79 CacheType &= 0xFF;
80 if (CacheType >= MmMaximumCacheType) return NULL;
81
82 //
83 // Calculate page count
84 //
85 PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(PhysicalAddress.LowPart,
86 NumberOfBytes);
87
88 //
89 // Compute the PFN and check if it's a known I/O mapping
90 // Also translate the cache attribute
91 //
92 Pfn = (PFN_NUMBER)(PhysicalAddress.QuadPart >> PAGE_SHIFT);
93 IsIoMapping = (Pfn > MmHighestPhysicalPage) ? TRUE : FALSE;
94 if (!IsIoMapping) Pfn1 = MiGetPfnEntry(Pfn);
95 CacheAttribute = MiPlatformCacheAttributes[IsIoMapping][CacheType];
96
97 //
98 // Now allocate system PTEs for the mapping, and get the VA
99 //
100 PointerPte = MiReserveSystemPtes(PageCount, SystemPteSpace);
101 if (!PointerPte) return NULL;
102 BaseAddress = MiPteToAddress(PointerPte);
103
104 //
105 // Check if this is uncached
106 //
107 if (CacheAttribute != MiCached)
108 {
109 //
110 // Flush all caches
111 //
112 KeFlushEntireTb(TRUE, TRUE);
113 KeInvalidateAllCaches();
114 }
115
116 //
117 // Now compute the VA offset
118 //
119 BaseAddress = (PVOID)((ULONG_PTR)BaseAddress +
120 BYTE_OFFSET(PhysicalAddress.LowPart));
121
122 //
123 // Get the template and configure caching
124 //
125 TempPte = HyperTemplatePte;
126 switch (CacheAttribute)
127 {
128 case MiNonCached:
129
130 //
131 // Disable the cache
132 //
133 MI_PAGE_DISABLE_CACHE(&TempPte);
134 MI_PAGE_WRITE_THROUGH(&TempPte);
135 break;
136
137 case MiCached:
138
139 //
140 // Leave defaults
141 //
142 break;
143
144 case MiWriteCombined:
145
146 //
147 // We don't support write combining yet
148 //
149 ASSERT(FALSE);
150 break;
151
152 default:
153
154 //
155 // Should never happen
156 //
157 ASSERT(FALSE);
158 break;
159 }
160
161 //
162 // Sanity check and re-flush
163 //
164 Pfn = (PFN_NUMBER)(PhysicalAddress.QuadPart >> PAGE_SHIFT);
165 ASSERT((Pfn1 == MiGetPfnEntry(Pfn)) || (Pfn1 == NULL));
166 KeFlushEntireTb(TRUE, TRUE);
167 KeInvalidateAllCaches();
168
169 //
170 // Do the mapping
171 //
172 do
173 {
174 //
175 // Start out with nothing
176 //
177 ASSERT(PointerPte->u.Hard.Valid == 0);
178
179 //
180 // Write the PFN
181 //
182 TempPte.u.Hard.PageFrameNumber = Pfn++;
183 *PointerPte++ = TempPte;
184 } while (--PageCount);
185
186 //
187 // We're done!
188 //
189 return BaseAddress;
190 }
191
192 /*
193 * @implemented
194 */
195 VOID
196 NTAPI
197 MmUnmapIoSpace(IN PVOID BaseAddress,
198 IN SIZE_T NumberOfBytes)
199 {
200 PFN_NUMBER PageCount, Pfn;
201 PMMPTE PointerPte;
202
203 //
204 // Sanity check
205 //
206 ASSERT(NumberOfBytes != 0);
207
208 //
209 // Get the page count
210 //
211 PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, NumberOfBytes);
212
213 //
214 // Get the PTE and PFN
215 //
216 PointerPte = MiAddressToPte(BaseAddress);
217 Pfn = PFN_FROM_PTE(PointerPte);
218
219 //
220 // Is this an I/O mapping?
221 //
222 if (Pfn > MmHighestPhysicalPage)
223 {
224 //
225 // Destroy the PTE
226 //
227 RtlZeroMemory(PointerPte, PageCount * sizeof(MMPTE));
228
229 //
230 // Blow the TLB
231 //
232 KeFlushEntireTb(TRUE, TRUE);
233 }
234
235 //
236 // Release the PTEs
237 //
238 MiReleaseSystemPtes(PointerPte, PageCount, 0);
239 }
240
241 /*
242 * @implemented
243 */
244 PVOID
245 NTAPI
246 MmMapVideoDisplay(IN PHYSICAL_ADDRESS PhysicalAddress,
247 IN SIZE_T NumberOfBytes,
248 IN MEMORY_CACHING_TYPE CacheType)
249 {
250 PAGED_CODE();
251
252 //
253 // Call the real function
254 //
255 return MmMapIoSpace(PhysicalAddress, NumberOfBytes, CacheType);
256 }
257
258 /*
259 * @implemented
260 */
261 VOID
262 NTAPI
263 MmUnmapVideoDisplay(IN PVOID BaseAddress,
264 IN SIZE_T NumberOfBytes)
265 {
266 //
267 // Call the real function
268 //
269 MmUnmapIoSpace(BaseAddress, NumberOfBytes);
270 }
271
272 /* EOF */