[NDIS]
[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 if (KeGetCurrentIrql() != PASSIVE_LEVEL)
175 {
176 KeBugCheckEx(BUGCODE_ID_DRIVER,
177 (ULONG_PTR)MiniportAdapterHandle,
178 Length,
179 0,
180 1);
181 }
182
183 *VirtualAddress = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->AllocateCommonBuffer(
184 Adapter->NdisMiniportBlock.SystemAdapterObject, Length, PhysicalAddress, Cached);
185 }
186
187 \f
188 VOID
189 NTAPI
190 NdisMFreeSharedMemoryPassive(
191 PVOID Context)
192 /*
193 * FUNCTION: Free a common buffer
194 * ARGUMENTS:
195 * Context: Pointer to a miniport shared memory context
196 * NOTES:
197 * - Called by NdisMFreeSharedMemory to do the actual work
198 */
199 {
200 PMINIPORT_SHARED_MEMORY Memory = (PMINIPORT_SHARED_MEMORY)Context;
201 PRKEVENT Event = Memory->Event;
202
203 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
204
205 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
206
207 Memory->AdapterObject->DmaOperations->FreeCommonBuffer(
208 Memory->AdapterObject, Memory->Length, Memory->PhysicalAddress,
209 Memory->VirtualAddress, Memory->Cached);
210
211 ExFreePool(Memory);
212
213 KeSetEvent(Event,
214 IO_NO_INCREMENT,
215 FALSE);
216 }
217
218 \f
219 /*
220 * @implemented
221 */
222 VOID
223 EXPORT
224 NdisMFreeSharedMemory(
225 IN NDIS_HANDLE MiniportAdapterHandle,
226 IN ULONG Length,
227 IN BOOLEAN Cached,
228 IN PVOID VirtualAddress,
229 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress)
230 /*
231 * FUNCTION: Free a shared memory block
232 * ARGUMENTS:
233 * MiniportAdapterHandle: Handle passed into MiniportInitialize
234 * Length: Number of bytes in the block to free
235 * Cached: Whether or not the memory was cached
236 * VirtualAddress: Address to free
237 * PhysicalAddress: corresponding physical addres
238 * NOTES:
239 * - This function can be called at dispatch_level or passive_level.
240 * Therefore we have to do this in a worker thread.
241 */
242 {
243 HANDLE ThreadHandle;
244 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
245 PMINIPORT_SHARED_MEMORY Memory;
246 KEVENT Event;
247
248 NDIS_DbgPrint(MAX_TRACE,("Called.\n"));
249
250 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
251
252 /* Must be NonpagedPool because by definition we're at DISPATCH_LEVEL */
253 Memory = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_SHARED_MEMORY));
254
255 if(!Memory)
256 {
257 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
258 return;
259 }
260
261 KeInitializeEvent(&Event, NotificationEvent, FALSE);
262
263 Memory->AdapterObject = Adapter->NdisMiniportBlock.SystemAdapterObject;
264 Memory->Length = Length;
265 Memory->PhysicalAddress = PhysicalAddress;
266 Memory->VirtualAddress = VirtualAddress;
267 Memory->Cached = Cached;
268 Memory->Adapter = &Adapter->NdisMiniportBlock;
269 Memory->Event = &Event;
270
271 PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, NdisMFreeSharedMemoryPassive, Memory);
272 ZwClose(ThreadHandle);
273
274 KeWaitForSingleObject(&Event,
275 Executive,
276 KernelMode,
277 FALSE,
278 NULL);
279 }
280
281 VOID
282 NTAPI
283 NdisMAllocateSharedMemoryPassive(
284 PVOID Context)
285 /*
286 * FUNCTION: Allocate a common buffer
287 * ARGUMENTS:
288 * Context: Pointer to a miniport shared memory context
289 * NOTES:
290 * - Called by NdisMAllocateSharedMemoryAsync to do the actual work
291 */
292 {
293 PMINIPORT_SHARED_MEMORY Memory = (PMINIPORT_SHARED_MEMORY)Context;
294
295 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
296
297 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
298
299 Memory->VirtualAddress = Memory->AdapterObject->DmaOperations->AllocateCommonBuffer(
300 Memory->AdapterObject, Memory->Length, &Memory->PhysicalAddress, Memory->Cached);
301
302 if (Memory->Adapter->DriverHandle->MiniportCharacteristics.AllocateCompleteHandler)
303 Memory->Adapter->DriverHandle->MiniportCharacteristics.AllocateCompleteHandler(
304 Memory->Adapter->MiniportAdapterContext, Memory->VirtualAddress,
305 &Memory->PhysicalAddress, Memory->Length, Memory->Context);
306
307 ExFreePool(Memory);
308 }
309
310
311 /*
312 * @implemented
313 */
314 NDIS_STATUS
315 EXPORT
316 NdisMAllocateSharedMemoryAsync(
317 IN NDIS_HANDLE MiniportAdapterHandle,
318 IN ULONG Length,
319 IN BOOLEAN Cached,
320 IN PVOID Context)
321 {
322 HANDLE ThreadHandle;
323 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
324 PMINIPORT_SHARED_MEMORY Memory;
325
326 NDIS_DbgPrint(MAX_TRACE,("Called.\n"));
327
328 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
329
330 /* Must be NonpagedPool because by definition we're at DISPATCH_LEVEL */
331 Memory = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_SHARED_MEMORY));
332
333 if(!Memory)
334 {
335 NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
336 return NDIS_STATUS_FAILURE;
337 }
338
339 Memory->AdapterObject = Adapter->NdisMiniportBlock.SystemAdapterObject;
340 Memory->Length = Length;
341 Memory->Cached = Cached;
342 Memory->Adapter = &Adapter->NdisMiniportBlock;
343 Memory->Context = Context;
344
345 PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, NdisMAllocateSharedMemoryPassive, Memory);
346 ZwClose(ThreadHandle);
347
348 return NDIS_STATUS_PENDING;
349 }
350
351 /*
352 * @implemented
353 */
354 VOID
355 EXPORT
356 NdisAllocateSharedMemory(
357 IN NDIS_HANDLE NdisAdapterHandle,
358 IN ULONG Length,
359 IN BOOLEAN Cached,
360 OUT PVOID *VirtualAddress,
361 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
362 {
363 NdisMAllocateSharedMemory(NdisAdapterHandle,
364 Length,
365 Cached,
366 VirtualAddress,
367 PhysicalAddress);
368 }
369
370
371 /*
372 * @implemented
373 */
374 VOID
375 EXPORT
376 NdisFreeSharedMemory(
377 IN NDIS_HANDLE NdisAdapterHandle,
378 IN ULONG Length,
379 IN BOOLEAN Cached,
380 IN PVOID VirtualAddress,
381 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress)
382 /*
383 * FUNCTION:
384 * ARGUMENTS:
385 * NOTES:
386 * NDIS 4.0
387 */
388 {
389 NdisMFreeSharedMemory(NdisAdapterHandle,
390 Length,
391 Cached,
392 VirtualAddress,
393 PhysicalAddress);
394 }
395
396
397 /* EOF */
398