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 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 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 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 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 271 MmIsIoSpaceActive(IN PHYSICAL_ADDRESS StartAddress, 272 IN SIZE_T NumberOfBytes) 273 { 274 UNIMPLEMENTED; 275 return FALSE; 276 } 277 278 /* EOF */ 279