2 * PROJECT: ReactOS Kernel
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: ntoskrnl/mm/ARM3/ncache.c
5 * PURPOSE: ARM Memory Manager Noncached Memory Allocator
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
15 #line 15 "ARMĀ³::NCACHE"
16 #define MODULE_INVOLVED_IN_ARM3
17 #include "../ARM3/miarm.h"
19 /* GLOBALS ********************************************************************/
26 MmAllocateNonCachedMemory(IN ULONG NumberOfBytes
)
28 PFN_NUMBER PageCount
, MdlPageCount
, PageFrameIndex
;
29 PHYSICAL_ADDRESS LowAddress
, HighAddress
, SkipBytes
;
30 MI_PFN_CACHE_ATTRIBUTE CacheAttribute
;
40 ASSERT(NumberOfBytes
!= 0);
41 PageCount
= BYTES_TO_PAGES(NumberOfBytes
);
44 // Use the MDL allocator for simplicity, so setup the parameters
46 LowAddress
.QuadPart
= 0;
47 HighAddress
.QuadPart
= -1;
48 SkipBytes
.QuadPart
= 0;
49 CacheAttribute
= MiPlatformCacheAttributes
[0][MmNonCached
];
52 // Now call the MDL allocator
54 Mdl
= MiAllocatePagesForMdl(LowAddress
,
60 if (!Mdl
) return NULL
;
63 // Get the MDL VA and check how many pages we got (could be partial)
65 BaseAddress
= (PVOID
)((ULONG_PTR
)Mdl
->StartVa
+ Mdl
->ByteOffset
);
66 MdlPageCount
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(BaseAddress
, Mdl
->ByteCount
);
67 if (PageCount
!= MdlPageCount
)
70 // Unlike MDLs, partial isn't okay for a noncached allocation, so fail
72 ASSERT(PageCount
> MdlPageCount
);
73 MmFreePagesFromMdl(Mdl
);
79 // Allocate system PTEs for the base address
80 // We use an extra page to store the actual MDL pointer for the free later
82 PointerPte
= MiReserveSystemPtes(PageCount
+ 1, SystemPteSpace
);
88 MmFreePagesFromMdl(Mdl
);
94 // Store the MDL pointer
96 *(PMDL
*)PointerPte
++ = Mdl
;
99 // Okay, now see what range we got
101 BaseAddress
= MiPteToAddress(PointerPte
);
104 // This is our array of pages
106 MdlPages
= (PPFN_NUMBER
)(Mdl
+ 1);
109 // Setup the template PTE
111 TempPte
= ValidKernelPte
;
114 // Now check what kind of caching we should use
116 switch (CacheAttribute
)
123 MI_PAGE_DISABLE_CACHE(&TempPte
);
124 MI_PAGE_WRITE_THROUGH(&TempPte
);
127 case MiWriteCombined
:
130 // Enable write combining
132 MI_PAGE_DISABLE_CACHE(&TempPte
);
133 MI_PAGE_WRITE_COMBINED(&TempPte
);
144 // Now loop the MDL pages
151 PageFrameIndex
= *MdlPages
++;
154 // Set the PFN in the page and write it
156 TempPte
.u
.Hard
.PageFrameNumber
= PageFrameIndex
;
157 MI_WRITE_VALID_PTE(PointerPte
++, TempPte
);
158 } while (--PageCount
);
161 // Return the base address
172 MmFreeNonCachedMemory(IN PVOID BaseAddress
,
173 IN ULONG NumberOfBytes
)
177 PFN_NUMBER PageCount
;
182 ASSERT(NumberOfBytes
!= 0);
183 ASSERT(PAGE_ALIGN(BaseAddress
) == BaseAddress
);
186 // Get the page count
188 PageCount
= BYTES_TO_PAGES(NumberOfBytes
);
193 PointerPte
= MiAddressToPte(BaseAddress
);
196 // Remember this is where we store the shadow MDL pointer
198 Mdl
= *(PMDL
*)(--PointerPte
);
201 // Kill the MDL (and underlying pages)
203 MmFreePagesFromMdl(Mdl
);
207 // Now free the system PTEs for the underlying VA
209 MiReleaseSystemPtes(PointerPte
, PageCount
+ 1, SystemPteSpace
);