Initial revision
[reactos.git] / reactos / ntoskrnl / mm / mdl.c
1 /*
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)
7 * UPDATE HISTORY:
8 * 27/05/98: Created
9 */
10
11 /* INCLUDES ****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <internal/mm.h>
15 #include <internal/hal/page.h>
16 #include <internal/string.h>
17
18 #include <internal/debug.h>
19
20 /* FUNCTIONS ***************************************************************/
21
22
23 VOID MmUnlockPages(PMDL MemoryDescriptorList)
24 {
25 UNIMPLEMENTED;
26 }
27
28 PVOID MmMapLockedPages(PMDL MemoryDescriptorList, KPROCESSOR_MODE AccessMode)
29 {
30 UNIMPLEMENTED;
31 }
32
33 VOID MmUnmapLockedPages(PVOID BaseAddress, PMDL MemoryDescriptorList)
34 {
35 UNIMPLEMENTED;
36 }
37
38 VOID MmPrepareMdlForReuse(PMDL Mdl)
39 {
40 UNIMPLEMENTED;
41 }
42
43 VOID KeFlushIoBuffers(PMDL Mdl, BOOLEAN ReadOperation, BOOLEAN DmaOperation)
44 {
45 /* NOP on the x86 */
46 /* See ntddk.h from Windows 98 DDK */
47 }
48
49 VOID MmProbeAndLockPages(PMDL Mdl, KPROCESSOR_MODE AccessMode,
50 LOCK_OPERATION Operation)
51 /*
52 * FUNCTION: Probes the specified pages, makes them resident and locks them
53 * ARGUMENTS:
54 * Mdl = MDL to probe
55 * AccessMode = Access at which to probe the buffer
56 * Operation = Operation to probe for
57 */
58 {
59 /*
60 * Find the memory area containing the buffer
61 */
62 ULONG* mdl_pages=NULL;
63 int i;
64 memory_area* marea=find_first_marea(memory_area_list_head,
65 (ULONG)Mdl->StartVa,
66 Mdl->ByteCount);
67
68 /*
69 * Check the area is valid
70 */
71 if (marea==NULL || (marea->base+marea->length) < ((ULONG)Mdl->StartVa))
72 {
73 ExRaiseStatus(STATUS_INVALID_PARAMETER);
74 }
75
76 /*
77 * Check the permissions
78 */
79 switch(Operation)
80 {
81 case IoReadAccess:
82 if (marea->access&PAGE_GUARD || marea->access&PAGE_NOACCESS)
83 {
84 ExRaiseStatus(STATUS_INVALID_PARAMETER);
85 }
86 break;
87
88 case IoWriteAccess:
89 case IoModifyAccess:
90 if (marea->access&PAGE_GUARD || marea->access&PAGE_READONLY)
91 {
92 ExRaiseStatus(STATUS_INVALID_PARAMETER);
93 }
94 break;
95
96 default:
97 printk("Invalid operation type at %s:%d in %s\n",__FILE__,__LINE__,
98 __FUNCTION__);
99 KeBugCheck(UNEXPECTED_KERNEL_MODE_TRAP);
100 }
101
102 /*
103 * Lock the memory area
104 * (We can't allow it to be freed while an I/O operation to it is
105 * ongoing)
106 */
107
108 /*
109 * Lock the pages
110 */
111 mdl_pages = (ULONG *)(Mdl + sizeof(MDL));
112
113 for (i=0;i<(PAGE_ROUND_UP(Mdl->ByteCount)/PAGESIZE);i++)
114 {
115 if (!is_page_present(PAGE_ROUND_DOWN(Mdl->StartVa) + (i*PAGESIZE)))
116 {
117 marea->load_page(marea,PAGE_ROUND_DOWN(Mdl->StartVa) + (i*PAGESIZE)
118 - marea->base);
119 }
120 mdl_pages[i]=MmGetPhysicalAddress((PVOID)(PAGE_ROUND_DOWN(Mdl->StartVa)
121 +(i*PAGESIZE)));
122 }
123 }
124
125 ULONG MmGetMdlByteCount(PMDL Mdl)
126 /*
127 *
128 */
129 {
130 return(Mdl->ByteCount);
131 }
132
133 ULONG MmGetMdlByteOffset(PMDL Mdl)
134 /*
135 * FUNCTION: Returns the byte offset within its page of the buffer described
136 * by the given MDL
137 * ARGUMENTS:
138 * Mdl = the mdl to query
139 * RETURNS: The offset in bytes
140 */
141 {
142 return(Mdl->ByteOffset);
143 }
144
145 ULONG MmSizeOfMdl(PVOID Base, ULONG Length)
146 /*
147 * FUNCTION: Returns the number of bytes to allocate for an MDL describing
148 * the given address range
149 * ARGUMENTS:
150 * Base = base virtual address
151 * Length = number of bytes to map
152 */
153 {
154 unsigned int len=PAGE_ROUND_UP(Length)/PAGESIZE;
155
156 if (!IS_PAGE_ALIGNED(Base))
157 {
158 len++;
159 }
160
161 return(sizeof(MDL)+(len*sizeof(ULONG)));
162 }
163
164 PVOID MmGetMdlVirtualAddress(PMDL Mdl)
165 {
166 return(Mdl->StartVa + Mdl->ByteOffset);
167 }
168
169 PVOID MmGetSystemAddressForMdl(PMDL Mdl)
170 {
171 Mdl->MappedSystemVa = MmMapLockedPages(Mdl,KernelMode);
172 return(Mdl->MappedSystemVa);
173 }
174
175 VOID MmBuildMdlForNonPagedPool(PMDL Mdl)
176 {
177 int va;
178 for (va=0; va<Mdl->Size; va++)
179 {
180 ((PULONG)(Mdl + 1))[va] = MmGetPhysicalAddress(
181 Mdl->StartVa+ (va * PAGESIZE));
182 }
183 }
184
185 VOID MmInitializeMdl(PMDL MemoryDescriptorList, PVOID Base, ULONG Length)
186 {
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))
194 {
195 MemoryDescriptorList->Size = MemoryDescriptorList->Size
196 + sizeof(ULONG);
197 }
198 MemoryDescriptorList->Process = PsGetCurrentProcess();
199 }
200
201 PMDL MmCreateMdl(PMDL MemoryDescriptorList, PVOID Base, ULONG Length)
202 /*
203 * FUNCTION: Allocates and initalizes an MDL
204 * ARGUMENTS:
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
210 */
211 {
212 if (MemoryDescriptorList == NULL)
213 {
214 MemoryDescriptorList = (PMDL)ExAllocatePool(NonPagedPool,sizeof(MDL));
215 if (MemoryDescriptorList==NULL)
216 {
217 return(NULL);
218 }
219 }
220
221 MmInitializeMdl(MemoryDescriptorList,Base,Length);
222
223 return(MemoryDescriptorList);
224 }