Merge from amd64-branch:
[reactos.git] / reactos / drivers / network / ndis / ndis / memory.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
4 * FILE: ndis/memory.c
5 * PURPOSE: Memory management routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
8 * REVISIONS:
9 * CSH 01/08-2000 Created
10 * 15 Aug 2003 Vizzini - DMA support
11 * 3 Oct 2003 Vizzini - formatting and minor bugfixing
12 */
13
14 #include "ndissys.h"
15
16 \f
17 /*
18 * @implemented
19 */
20 NDIS_STATUS
21 EXPORT
22 NdisAllocateMemoryWithTag(
23 OUT PVOID *VirtualAddress,
24 IN UINT Length,
25 IN ULONG Tag)
26 /*
27 * FUNCTION: Allocates a block of memory, with a 32-bit tag
28 * ARGUMENTS:
29 * VirtualAddress = a pointer to the returned memory block
30 * Length = the number of requested bytes
31 * Tag = 32-bit pool tag
32 * RETURNS:
33 * NDIS_STATUS_SUCCESS on success
34 * NDIS_STATUS_FAILURE on failure
35 */
36 {
37 PVOID Block;
38
39 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
40
41 Block = ExAllocatePoolWithTag(NonPagedPool, Length, Tag);
42 *VirtualAddress = Block;
43
44 if (!Block) {
45 NDIS_DbgPrint(MIN_TRACE, ("Failed to allocate memory (%lx)\n", Length));
46 return NDIS_STATUS_FAILURE;
47 }
48
49 return NDIS_STATUS_SUCCESS;
50 }
51
52
53 \f
54 /*
55 * @implemented
56 */
57 NDIS_STATUS
58 EXPORT
59 NdisAllocateMemory(
60 OUT PVOID *VirtualAddress,
61 IN UINT Length,
62 IN UINT MemoryFlags,
63 IN NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress)
64 /*
65 * FUNCTION: Allocates a block of memory
66 * ARGUMENTS:
67 * VirtualAddress = Address of buffer to place virtual
68 * address of the allocated memory
69 * Length = Size of the memory block to allocate
70 * MemoryFlags = Flags to specify special restrictions
71 * HighestAcceptableAddress = Specifies -1
72 * RETURNS:
73 * NDIS_STATUS_SUCCESS on success
74 * NDIS_STATUS_FAILURE on failure
75 */
76 {
77 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
78
79 if (MemoryFlags & NDIS_MEMORY_CONTIGUOUS)
80 {
81 /* Allocate contiguous memory (possibly noncached) */
82 *VirtualAddress = MmAllocateContiguousMemorySpecifyCache(Length,
83 RtlConvertUlongToLargeInteger(0),
84 HighestAcceptableAddress,
85 RtlConvertUlongToLargeInteger(0),
86 (MemoryFlags & NDIS_MEMORY_NONCACHED) ? MmNonCached : MmCached);
87 }
88 else if (MemoryFlags & NDIS_MEMORY_NONCACHED)
89 {
90 /* Allocate noncached noncontiguous memory */
91 *VirtualAddress = MmAllocateNonCachedMemory(Length);
92 }
93 else
94 {
95 /* Allocate plain nonpaged memory */
96 *VirtualAddress = ExAllocatePool(NonPagedPool, Length);
97 }
98
99 if (!*VirtualAddress) {
100 NDIS_DbgPrint(MIN_TRACE, ("Allocation failed (%lx, %lx)\n", MemoryFlags, Length));
101 return NDIS_STATUS_FAILURE;
102 }
103
104 return NDIS_STATUS_SUCCESS;
105 }
106
107 \f
108 /*
109 * @implemented
110 */
111 VOID
112 EXPORT
113 NdisFreeMemory(
114 IN PVOID VirtualAddress,
115 IN UINT Length,
116 IN UINT MemoryFlags)
117 /*
118 * FUNCTION: Frees a memory block allocated with NdisAllocateMemory
119 * ARGUMENTS:
120 * VirtualAddress = Pointer to the base virtual address of the allocated memory
121 * Length = Size of the allocated memory block as passed to NdisAllocateMemory
122 * MemoryFlags = Memory flags passed to NdisAllocateMemory
123 */
124 {
125 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
126
127 if (MemoryFlags & NDIS_MEMORY_CONTIGUOUS)
128 {
129 /* Free contiguous memory (possibly noncached) */
130 MmFreeContiguousMemorySpecifyCache(VirtualAddress,
131 Length,
132 (MemoryFlags & NDIS_MEMORY_NONCACHED) ? MmNonCached : MmCached);
133 }
134 else if (MemoryFlags & NDIS_MEMORY_NONCACHED)
135 {
136 /* Free noncached noncontiguous memory */
137 MmFreeNonCachedMemory(VirtualAddress, Length);
138 }
139 else
140 {
141 /* Free nonpaged pool */
142 ExFreePool(VirtualAddress);
143 }
144 }
145
146 \f
147 /*
148 * @implemented
149 */
150 VOID
151 EXPORT
152 NdisMAllocateSharedMemory(
153 IN NDIS_HANDLE MiniportAdapterHandle,
154 IN ULONG Length,
155 IN BOOLEAN Cached,
156 OUT PVOID *VirtualAddress,
157 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
158 /*
159 * FUNCTION: Allocate a common buffer for DMA
160 * ARGUMENTS:
161 * MiniportAdapterHandle: Handle passed into MiniportInitialize
162 * Length: Number of bytes to allocate
163 * Cached: Whether or not the memory can be cached
164 * VirtualAddress: Pointer to memory is returned here
165 * PhysicalAddress: Physical address corresponding to virtual address
166 * NOTES:
167 * - Cached is ignored; we always allocate non-cached
168 */
169 {
170 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
171
172 NDIS_DbgPrint(MAX_TRACE,("Called.\n"));
173
174 *VirtualAddress = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->AllocateCommonBuffer(
175 Adapter->NdisMiniportBlock.SystemAdapterObject, Length, PhysicalAddress, Cached);
176 }
177
178 \f
179 VOID
180 NTAPI
181 NdisMFreeSharedMemoryPassive(
182 PVOID Context)
183 /*
184 * FUNCTION: Free a common buffer
185 * ARGUMENTS:
186 * Context: Pointer to a miniport shared memory context
187 * NOTES:
188 * - Called by NdisMFreeSharedMemory to do the actual work
189 */
190 {
191 PMINIPORT_SHARED_MEMORY Memory = (PMINIPORT_SHARED_MEMORY)Context;
192 PRKEVENT Event = Memory->Event;
193
194 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
195
196 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
197
198 Memory->AdapterObject->DmaOperations->FreeCommonBuffer(
199 Memory->AdapterObject, Memory->Length, Memory->PhysicalAddress,
200 Memory->VirtualAddress, Memory->Cached);
201
202 ExFreePool(Memory);
203
204 KeSetEvent(Event,
205 IO_NO_INCREMENT,
206 FALSE);
207 }
208
209 \f
210 /*
211 * @implemented
212 */
213 VOID
214 EXPORT
215 NdisMFreeSharedMemory(
216 IN NDIS_HANDLE MiniportAdapterHandle,
217 IN ULONG Length,
218 IN BOOLEAN Cached,
219 IN PVOID VirtualAddress,
220 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress)
221 /*
222 * FUNCTION: Free a shared memory block
223 * ARGUMENTS:
224 * MiniportAdapterHandle: Handle passed into MiniportInitialize
225 * Length: Number of bytes in the block to free
226 * Cached: Whether or not the memory was cached
227 * VirtualAddress: Address to free
228 * PhysicalAddress: corresponding physical addres
229 * NOTES:
230 * - This function can be called at dispatch_level or passive_level.
231 * Therefore we have to do this in a worker thread.
232 */
233 {
234 HANDLE ThreadHandle;
235 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
236 PMINIPORT_SHARED_MEMORY Memory;
237 KEVENT Event;
238
239 NDIS_DbgPrint(MAX_TRACE,("Called.\n"));
240
241 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
242
243 /* Must be NonpagedPool because by definition we're at DISPATCH_LEVEL */
244 Memory = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_SHARED_MEMORY));
245
246 if(!Memory)
247 {
248 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
249 return;
250 }
251
252 KeInitializeEvent(&Event, NotificationEvent, FALSE);
253
254 Memory->AdapterObject = Adapter->NdisMiniportBlock.SystemAdapterObject;
255 Memory->Length = Length;
256 Memory->PhysicalAddress = PhysicalAddress;
257 Memory->VirtualAddress = VirtualAddress;
258 Memory->Cached = Cached;
259 Memory->Adapter = &Adapter->NdisMiniportBlock;
260 Memory->Event = &Event;
261
262 PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, NdisMFreeSharedMemoryPassive, Memory);
263 ZwClose(ThreadHandle);
264
265 KeWaitForSingleObject(&Event,
266 Executive,
267 KernelMode,
268 FALSE,
269 NULL);
270 }
271
272 VOID
273 NTAPI
274 NdisMAllocateSharedMemoryPassive(
275 PVOID Context)
276 /*
277 * FUNCTION: Allocate a common buffer
278 * ARGUMENTS:
279 * Context: Pointer to a miniport shared memory context
280 * NOTES:
281 * - Called by NdisMAllocateSharedMemoryAsync to do the actual work
282 */
283 {
284 PMINIPORT_SHARED_MEMORY Memory = (PMINIPORT_SHARED_MEMORY)Context;
285
286 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
287
288 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
289
290 Memory->VirtualAddress = Memory->AdapterObject->DmaOperations->AllocateCommonBuffer(
291 Memory->AdapterObject, Memory->Length, &Memory->PhysicalAddress, Memory->Cached);
292
293 if (Memory->Adapter->DriverHandle->MiniportCharacteristics.AllocateCompleteHandler)
294 Memory->Adapter->DriverHandle->MiniportCharacteristics.AllocateCompleteHandler(
295 Memory->Adapter->MiniportAdapterContext, Memory->VirtualAddress,
296 &Memory->PhysicalAddress, Memory->Length, Memory->Context);
297
298 ExFreePool(Memory);
299 }
300
301
302 /*
303 * @implemented
304 */
305 NDIS_STATUS
306 EXPORT
307 NdisMAllocateSharedMemoryAsync(
308 IN NDIS_HANDLE MiniportAdapterHandle,
309 IN ULONG Length,
310 IN BOOLEAN Cached,
311 IN PVOID Context)
312 {
313 HANDLE ThreadHandle;
314 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
315 PMINIPORT_SHARED_MEMORY Memory;
316
317 NDIS_DbgPrint(MAX_TRACE,("Called.\n"));
318
319 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
320
321 /* Must be NonpagedPool because by definition we're at DISPATCH_LEVEL */
322 Memory = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_SHARED_MEMORY));
323
324 if(!Memory)
325 {
326 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
327 return NDIS_STATUS_FAILURE;
328 }
329
330 Memory->AdapterObject = Adapter->NdisMiniportBlock.SystemAdapterObject;
331 Memory->Length = Length;
332 Memory->Cached = Cached;
333 Memory->Adapter = &Adapter->NdisMiniportBlock;
334 Memory->Context = Context;
335
336 PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, NdisMAllocateSharedMemoryPassive, Memory);
337 ZwClose(ThreadHandle);
338
339 return NDIS_STATUS_PENDING;
340 }
341
342 /*
343 * @implemented
344 */
345 VOID
346 EXPORT
347 NdisAllocateSharedMemory(
348 IN NDIS_HANDLE NdisAdapterHandle,
349 IN ULONG Length,
350 IN BOOLEAN Cached,
351 OUT PVOID *VirtualAddress,
352 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
353 {
354 NdisMAllocateSharedMemory(NdisAdapterHandle,
355 Length,
356 Cached,
357 VirtualAddress,
358 PhysicalAddress);
359 }
360
361
362 /*
363 * @implemented
364 */
365 VOID
366 EXPORT
367 NdisFreeSharedMemory(
368 IN NDIS_HANDLE NdisAdapterHandle,
369 IN ULONG Length,
370 IN BOOLEAN Cached,
371 IN PVOID VirtualAddress,
372 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress)
373 /*
374 * FUNCTION:
375 * ARGUMENTS:
376 * NOTES:
377 * NDIS 4.0
378 */
379 {
380 NdisMFreeSharedMemory(NdisAdapterHandle,
381 Length,
382 Cached,
383 VirtualAddress,
384 PhysicalAddress);
385 }
386
387
388 /* EOF */
389