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 #define MODULE_INVOLVED_IN_ARM3
16 #include <mm/ARM3/miarm.h>
17
18 /* GLOBALS ********************************************************************/
19
20 //
21 // Each architecture has its own caching attributes for both I/O and Physical
22 // memory mappings.
23 //
24 // This describes the attributes for the x86 architecture. It eventually needs
25 // to go in the appropriate i386 directory.
26 //
27 MI_PFN_CACHE_ATTRIBUTE MiPlatformCacheAttributes[2][MmMaximumCacheType] =
28 {
29 //
30 // RAM
31 //
32 {MiNonCached,MiCached,MiWriteCombined,MiCached,MiNonCached,MiWriteCombined},
33
34 //
35 // Device Memory
36 //
37 {MiNonCached,MiCached,MiWriteCombined,MiCached,MiNonCached,MiWriteCombined},
38 };
39
40 /* PUBLIC FUNCTIONS ***********************************************************/
41
42 /*
43 * @implemented
44 */
45 PVOID
46 NTAPI
MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress,IN SIZE_T NumberOfBytes,IN MEMORY_CACHING_TYPE CacheType)47 MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress,
48 IN SIZE_T NumberOfBytes,
49 IN MEMORY_CACHING_TYPE CacheType)
50 {
51
52 PFN_NUMBER Pfn;
53 PFN_COUNT 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 Pfn1 = MiGetPfnEntry(Pfn);
94 IsIoMapping = (Pfn1 == NULL) ? TRUE : FALSE;
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 = ValidKernelPte;
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 // Disable the cache and allow combined writing
148 //
149 MI_PAGE_DISABLE_CACHE(&TempPte);
150 MI_PAGE_WRITE_COMBINED(&TempPte);
151 break;
152
153 default:
154
155 //
156 // Should never happen
157 //
158 ASSERT(FALSE);
159 break;
160 }
161
162 //
163 // Sanity check and re-flush
164 //
165 Pfn = (PFN_NUMBER)(PhysicalAddress.QuadPart >> PAGE_SHIFT);
166 ASSERT((Pfn1 == MiGetPfnEntry(Pfn)) || (Pfn1 == NULL));
167 KeFlushEntireTb(TRUE, TRUE);
168 KeInvalidateAllCaches();
169
170 //
171 // Do the mapping
172 //
173 do
174 {
175 //
176 // Write the PFN
177 //
178 TempPte.u.Hard.PageFrameNumber = Pfn++;
179 MI_WRITE_VALID_PTE(PointerPte++, TempPte);
180 } while (--PageCount);
181
182 //
183 // We're done!
184 //
185 return BaseAddress;
186 }
187
188 /*
189 * @implemented
190 */
191 VOID
192 NTAPI
MmUnmapIoSpace(IN PVOID BaseAddress,IN SIZE_T NumberOfBytes)193 MmUnmapIoSpace(IN PVOID BaseAddress,
194 IN SIZE_T NumberOfBytes)
195 {
196 PFN_NUMBER Pfn;
197 PFN_COUNT PageCount;
198 PMMPTE PointerPte;
199
200 //
201 // Sanity check
202 //
203 ASSERT(NumberOfBytes != 0);
204
205 //
206 // Get the page count
207 //
208 PageCount = ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress, NumberOfBytes);
209
210 //
211 // Get the PTE and PFN
212 //
213 PointerPte = MiAddressToPte(BaseAddress);
214 Pfn = PFN_FROM_PTE(PointerPte);
215
216 //
217 // Is this an I/O mapping?
218 //
219 if (!MiGetPfnEntry(Pfn))
220 {
221 //
222 // Destroy the PTE
223 //
224 RtlZeroMemory(PointerPte, PageCount * sizeof(MMPTE));
225
226 //
227 // Blow the TLB
228 //
229 KeFlushEntireTb(TRUE, TRUE);
230 }
231
232 //
233 // Release the PTEs
234 //
235 MiReleaseSystemPtes(PointerPte, PageCount, 0);
236 }
237
238 /*
239 * @implemented
240 */
241 PVOID
242 NTAPI
MmMapVideoDisplay(IN PHYSICAL_ADDRESS PhysicalAddress,IN SIZE_T NumberOfBytes,IN MEMORY_CACHING_TYPE CacheType)243 MmMapVideoDisplay(IN PHYSICAL_ADDRESS PhysicalAddress,
244 IN SIZE_T NumberOfBytes,
245 IN MEMORY_CACHING_TYPE CacheType)
246 {
247 PAGED_CODE();
248
249 //
250 // Call the real function
251 //
252 return MmMapIoSpace(PhysicalAddress, NumberOfBytes, CacheType);
253 }
254
255 /*
256 * @implemented
257 */
258 VOID
259 NTAPI
MmUnmapVideoDisplay(IN PVOID BaseAddress,IN SIZE_T NumberOfBytes)260 MmUnmapVideoDisplay(IN PVOID BaseAddress,
261 IN SIZE_T NumberOfBytes)
262 {
263 //
264 // Call the real function
265 //
266 MmUnmapIoSpace(BaseAddress, NumberOfBytes);
267 }
268
269 LOGICAL
270 NTAPI
MmIsIoSpaceActive(IN PHYSICAL_ADDRESS StartAddress,IN SIZE_T NumberOfBytes)271 MmIsIoSpaceActive(IN PHYSICAL_ADDRESS StartAddress,
272 IN SIZE_T NumberOfBytes)
273 {
274 UNIMPLEMENTED;
275 return FALSE;
276 }
277
278 /* EOF */
279