2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: kernel/mm/mdl.cc
5 * PURPOSE: Manipulates MDLs
6 * PROGRAMMER: David Welch (welch@mcmail.com)
11 /* INCLUDES ****************************************************************/
13 #include <ddk/ntddk.h>
14 #include <internal/mm.h>
15 #include <internal/hal/page.h>
16 #include <internal/string.h>
18 #include <internal/debug.h>
20 /* FUNCTIONS ***************************************************************/
23 VOID
MmUnlockPages(PMDL MemoryDescriptorList
)
28 PVOID
MmMapLockedPages(PMDL MemoryDescriptorList
, KPROCESSOR_MODE AccessMode
)
33 VOID
MmUnmapLockedPages(PVOID BaseAddress
, PMDL MemoryDescriptorList
)
38 VOID
MmPrepareMdlForReuse(PMDL Mdl
)
43 VOID
KeFlushIoBuffers(PMDL Mdl
, BOOLEAN ReadOperation
, BOOLEAN DmaOperation
)
46 /* See ntddk.h from Windows 98 DDK */
49 VOID
MmProbeAndLockPages(PMDL Mdl
, KPROCESSOR_MODE AccessMode
,
50 LOCK_OPERATION Operation
)
52 * FUNCTION: Probes the specified pages, makes them resident and locks them
55 * AccessMode = Access at which to probe the buffer
56 * Operation = Operation to probe for
60 * Find the memory area containing the buffer
62 ULONG
* mdl_pages
=NULL
;
64 memory_area
* marea
=find_first_marea(memory_area_list_head
,
69 * Check the area is valid
71 if (marea
==NULL
|| (marea
->base
+marea
->length
) < ((ULONG
)Mdl
->StartVa
))
73 ExRaiseStatus(STATUS_INVALID_PARAMETER
);
77 * Check the permissions
82 if (marea
->access
&PAGE_GUARD
|| marea
->access
&PAGE_NOACCESS
)
84 ExRaiseStatus(STATUS_INVALID_PARAMETER
);
90 if (marea
->access
&PAGE_GUARD
|| marea
->access
&PAGE_READONLY
)
92 ExRaiseStatus(STATUS_INVALID_PARAMETER
);
97 printk("Invalid operation type at %s:%d in %s\n",__FILE__
,__LINE__
,
99 KeBugCheck(UNEXPECTED_KERNEL_MODE_TRAP
);
103 * Lock the memory area
104 * (We can't allow it to be freed while an I/O operation to it is
111 mdl_pages
= (ULONG
*)(Mdl
+ sizeof(MDL
));
113 for (i
=0;i
<(PAGE_ROUND_UP(Mdl
->ByteCount
)/PAGESIZE
);i
++)
115 if (!is_page_present(PAGE_ROUND_DOWN(Mdl
->StartVa
) + (i
*PAGESIZE
)))
117 marea
->load_page(marea
,PAGE_ROUND_DOWN(Mdl
->StartVa
) + (i
*PAGESIZE
)
120 mdl_pages
[i
]=MmGetPhysicalAddress((PVOID
)(PAGE_ROUND_DOWN(Mdl
->StartVa
)
125 ULONG
MmGetMdlByteCount(PMDL Mdl
)
130 return(Mdl
->ByteCount
);
133 ULONG
MmGetMdlByteOffset(PMDL Mdl
)
135 * FUNCTION: Returns the byte offset within its page of the buffer described
138 * Mdl = the mdl to query
139 * RETURNS: The offset in bytes
142 return(Mdl
->ByteOffset
);
145 ULONG
MmSizeOfMdl(PVOID Base
, ULONG Length
)
147 * FUNCTION: Returns the number of bytes to allocate for an MDL describing
148 * the given address range
150 * Base = base virtual address
151 * Length = number of bytes to map
154 unsigned int len
=PAGE_ROUND_UP(Length
)/PAGESIZE
;
156 if (!IS_PAGE_ALIGNED(Base
))
161 return(sizeof(MDL
)+(len
*sizeof(ULONG
)));
164 PVOID
MmGetMdlVirtualAddress(PMDL Mdl
)
166 return(Mdl
->StartVa
+ Mdl
->ByteOffset
);
169 PVOID
MmGetSystemAddressForMdl(PMDL Mdl
)
171 Mdl
->MappedSystemVa
= MmMapLockedPages(Mdl
,KernelMode
);
172 return(Mdl
->MappedSystemVa
);
175 VOID
MmBuildMdlForNonPagedPool(PMDL Mdl
)
178 for (va
=0; va
<Mdl
->Size
; va
++)
180 ((PULONG
)(Mdl
+ 1))[va
] = MmGetPhysicalAddress(
181 Mdl
->StartVa
+ (va
* PAGESIZE
));
185 VOID
MmInitializeMdl(PMDL MemoryDescriptorList
, PVOID Base
, ULONG Length
)
187 memset(MemoryDescriptorList
,0,sizeof(MDL
));
188 MemoryDescriptorList
->StartVa
= PAGE_ROUND_DOWN(Base
);
189 MemoryDescriptorList
->ByteOffset
= Base
- PAGE_ROUND_DOWN(Base
);
190 MemoryDescriptorList
->MdlFlags
= 0;
191 MemoryDescriptorList
->ByteCount
= Length
;
192 MemoryDescriptorList
->Size
= PAGE_ROUND_UP(Length
) / PAGESIZE
;
193 if (!IS_PAGE_ALIGNED(Base
))
195 MemoryDescriptorList
->Size
= MemoryDescriptorList
->Size
198 MemoryDescriptorList
->Process
= PsGetCurrentProcess();
201 PMDL
MmCreateMdl(PMDL MemoryDescriptorList
, PVOID Base
, ULONG Length
)
203 * FUNCTION: Allocates and initalizes an MDL
205 * MemoryDescriptorList = Points to MDL to initalize. If this is
206 * NULL then one is allocated
207 * Base = Base virtual address of the buffer
208 * Length = Length in bytes of the buffer
209 * RETURNS: A pointer to initalized MDL
212 if (MemoryDescriptorList
== NULL
)
214 MemoryDescriptorList
= (PMDL
)ExAllocatePool(NonPagedPool
,sizeof(MDL
));
215 if (MemoryDescriptorList
==NULL
)
221 MmInitializeMdl(MemoryDescriptorList
,Base
,Length
);
223 return(MemoryDescriptorList
);