xref: /reactos/ntoskrnl/mm/ARM3/iosup.c (revision c2c66aff)
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