194bfe5ec4bb99ec4500f29d18ea88d7755fc8b3
[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 return NDIS_STATUS_FAILURE;
46
47 return NDIS_STATUS_SUCCESS;
48 }
49
50
51 \f
52 /*
53 * @implemented
54 */
55 NDIS_STATUS
56 EXPORT
57 NdisAllocateMemory(
58 OUT PVOID *VirtualAddress,
59 IN UINT Length,
60 IN UINT MemoryFlags,
61 IN NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress)
62 /*
63 * FUNCTION: Allocates a block of memory
64 * ARGUMENTS:
65 * VirtualAddress = Address of buffer to place virtual
66 * address of the allocated memory
67 * Length = Size of the memory block to allocate
68 * MemoryFlags = Flags to specify special restrictions
69 * HighestAcceptableAddress = Specifies -1
70 * RETURNS:
71 * NDIS_STATUS_SUCCESS on success
72 * NDIS_STATUS_FAILURE on failure
73 */
74 {
75 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
76
77 if (MemoryFlags & NDIS_MEMORY_NONCACHED)
78 {
79 *VirtualAddress = MmAllocateNonCachedMemory(Length);
80 if(!*VirtualAddress)
81 return NDIS_STATUS_FAILURE;
82
83 return NDIS_STATUS_SUCCESS;
84 }
85
86 if (MemoryFlags & NDIS_MEMORY_CONTIGUOUS)
87 {
88 *VirtualAddress = MmAllocateContiguousMemory(Length, HighestAcceptableAddress);
89 if(!*VirtualAddress)
90 return NDIS_STATUS_FAILURE;
91
92 return NDIS_STATUS_SUCCESS;
93 }
94
95 /* Plain nonpaged memory */
96 *VirtualAddress = ExAllocatePool(NonPagedPool, Length);
97 if (!*VirtualAddress)
98 return NDIS_STATUS_FAILURE;
99
100 return NDIS_STATUS_SUCCESS;
101 }
102
103 \f
104 /*
105 * @implemented
106 */
107 VOID
108 EXPORT
109 NdisFreeMemory(
110 IN PVOID VirtualAddress,
111 IN UINT Length,
112 IN UINT MemoryFlags)
113 /*
114 * FUNCTION: Frees a memory block allocated with NdisAllocateMemory
115 * ARGUMENTS:
116 * VirtualAddress = Pointer to the base virtual address of the allocated memory
117 * Length = Size of the allocated memory block as passed to NdisAllocateMemory
118 * MemoryFlags = Memory flags passed to NdisAllocateMemory
119 */
120 {
121 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
122
123 if (MemoryFlags & NDIS_MEMORY_NONCACHED)
124 {
125 MmFreeNonCachedMemory(VirtualAddress, Length);
126 return;
127 }
128
129 if (MemoryFlags & NDIS_MEMORY_CONTIGUOUS)
130 {
131 MmFreeContiguousMemory(VirtualAddress);
132 return;
133 }
134
135 ExFreePool(VirtualAddress);
136 }
137
138 \f
139 /*
140 * @implemented
141 */
142 VOID
143 EXPORT
144 NdisMAllocateSharedMemory(
145 IN NDIS_HANDLE MiniportAdapterHandle,
146 IN ULONG Length,
147 IN BOOLEAN Cached,
148 OUT PVOID *VirtualAddress,
149 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
150 /*
151 * FUNCTION: Allocate a common buffer for DMA
152 * ARGUMENTS:
153 * MiniportAdapterHandle: Handle passed into MiniportInitialize
154 * Length: Number of bytes to allocate
155 * Cached: Whether or not the memory can be cached
156 * VirtualAddress: Pointer to memory is returned here
157 * PhysicalAddress: Physical address corresponding to virtual address
158 * NOTES:
159 * - Cached is ignored; we always allocate non-cached
160 */
161 {
162 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
163
164 NDIS_DbgPrint(MAX_TRACE,("Called.\n"));
165
166 *VirtualAddress = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->AllocateCommonBuffer(
167 Adapter->NdisMiniportBlock.SystemAdapterObject, Length, PhysicalAddress, Cached);
168 }
169
170 \f
171 VOID
172 NTAPI
173 NdisMFreeSharedMemoryPassive(
174 PVOID Context)
175 /*
176 * FUNCTION: Free a common buffer
177 * ARGUMENTS:
178 * Context: Pointer to a miniport shared memory context
179 * NOTES:
180 * - Called by NdisMFreeSharedMemory to do the actual work
181 */
182 {
183 PMINIPORT_SHARED_MEMORY Memory = (PMINIPORT_SHARED_MEMORY)Context;
184 PRKEVENT Event = Memory->Event;
185
186 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
187
188 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
189
190 Memory->AdapterObject->DmaOperations->FreeCommonBuffer(
191 Memory->AdapterObject, Memory->Length, Memory->PhysicalAddress,
192 Memory->VirtualAddress, Memory->Cached);
193
194 ExFreePool(Memory);
195
196 KeSetEvent(Event,
197 IO_NO_INCREMENT,
198 FALSE);
199 }
200
201 \f
202 /*
203 * @implemented
204 */
205 VOID
206 EXPORT
207 NdisMFreeSharedMemory(
208 IN NDIS_HANDLE MiniportAdapterHandle,
209 IN ULONG Length,
210 IN BOOLEAN Cached,
211 IN PVOID VirtualAddress,
212 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress)
213 /*
214 * FUNCTION: Free a shared memory block
215 * ARGUMENTS:
216 * MiniportAdapterHandle: Handle passed into MiniportInitialize
217 * Length: Number of bytes in the block to free
218 * Cached: Whether or not the memory was cached
219 * VirtualAddress: Address to free
220 * PhysicalAddress: corresponding physical addres
221 * NOTES:
222 * - This function can be called at dispatch_level or passive_level.
223 * Therefore we have to do this in a worker thread.
224 */
225 {
226 HANDLE ThreadHandle;
227 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
228 PMINIPORT_SHARED_MEMORY Memory;
229 KEVENT Event;
230
231 NDIS_DbgPrint(MAX_TRACE,("Called.\n"));
232
233 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
234
235 /* Must be NonpagedPool because by definition we're at DISPATCH_LEVEL */
236 Memory = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_SHARED_MEMORY));
237
238 if(!Memory)
239 {
240 NDIS_DbgPrint(MID_TRACE, ("Insufficient resources\n"));
241 return;
242 }
243
244 KeInitializeEvent(&Event, NotificationEvent, FALSE);
245
246 Memory->AdapterObject = Adapter->NdisMiniportBlock.SystemAdapterObject;
247 Memory->Length = Length;
248 Memory->PhysicalAddress = PhysicalAddress;
249 Memory->VirtualAddress = VirtualAddress;
250 Memory->Cached = Cached;
251 Memory->Adapter = &Adapter->NdisMiniportBlock;
252 Memory->Event = &Event;
253
254 PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, NdisMFreeSharedMemoryPassive, Memory);
255 ZwClose(ThreadHandle);
256
257 KeWaitForSingleObject(&Event,
258 Executive,
259 KernelMode,
260 FALSE,
261 NULL);
262 }
263
264 VOID
265 NTAPI
266 NdisMAllocateSharedMemoryPassive(
267 PVOID Context)
268 /*
269 * FUNCTION: Allocate a common buffer
270 * ARGUMENTS:
271 * Context: Pointer to a miniport shared memory context
272 * NOTES:
273 * - Called by NdisMAllocateSharedMemoryAsync to do the actual work
274 */
275 {
276 PMINIPORT_SHARED_MEMORY Memory = (PMINIPORT_SHARED_MEMORY)Context;
277
278 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
279
280 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
281
282 Memory->VirtualAddress = Memory->AdapterObject->DmaOperations->AllocateCommonBuffer(
283 Memory->AdapterObject, Memory->Length, &Memory->PhysicalAddress, Memory->Cached);
284
285 if (Memory->Adapter->DriverHandle->MiniportCharacteristics.AllocateCompleteHandler)
286 Memory->Adapter->DriverHandle->MiniportCharacteristics.AllocateCompleteHandler(
287 Memory->Adapter->MiniportAdapterContext, Memory->VirtualAddress,
288 &Memory->PhysicalAddress, Memory->Length, Memory->Context);
289
290 ExFreePool(Memory);
291 }
292
293
294 /*
295 * @implemented
296 */
297 NDIS_STATUS
298 EXPORT
299 NdisMAllocateSharedMemoryAsync(
300 IN NDIS_HANDLE MiniportAdapterHandle,
301 IN ULONG Length,
302 IN BOOLEAN Cached,
303 IN PVOID Context)
304 {
305 HANDLE ThreadHandle;
306 PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
307 PMINIPORT_SHARED_MEMORY Memory;
308
309 NDIS_DbgPrint(MAX_TRACE,("Called.\n"));
310
311 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
312
313 /* Must be NonpagedPool because by definition we're at DISPATCH_LEVEL */
314 Memory = ExAllocatePool(NonPagedPool, sizeof(MINIPORT_SHARED_MEMORY));
315
316 if(!Memory)
317 {
318 NDIS_DbgPrint(MID_TRACE, ("Insufficient resources\n"));
319 return NDIS_STATUS_FAILURE;
320 }
321
322 Memory->AdapterObject = Adapter->NdisMiniportBlock.SystemAdapterObject;
323 Memory->Length = Length;
324 Memory->Cached = Cached;
325 Memory->Adapter = &Adapter->NdisMiniportBlock;
326 Memory->Context = Context;
327
328 PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, 0, 0, 0, NdisMAllocateSharedMemoryPassive, Memory);
329 ZwClose(ThreadHandle);
330
331 return NDIS_STATUS_PENDING;
332 }
333
334 /*
335 * @implemented
336 */
337 VOID
338 EXPORT
339 NdisAllocateSharedMemory(
340 IN NDIS_HANDLE NdisAdapterHandle,
341 IN ULONG Length,
342 IN BOOLEAN Cached,
343 OUT PVOID *VirtualAddress,
344 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress)
345 {
346 NdisMAllocateSharedMemory(NdisAdapterHandle,
347 Length,
348 Cached,
349 VirtualAddress,
350 PhysicalAddress);
351 }
352
353
354 /*
355 * @implemented
356 */
357 VOID
358 EXPORT
359 NdisFreeSharedMemory(
360 IN NDIS_HANDLE NdisAdapterHandle,
361 IN ULONG Length,
362 IN BOOLEAN Cached,
363 IN PVOID VirtualAddress,
364 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress)
365 /*
366 * FUNCTION:
367 * ARGUMENTS:
368 * NOTES:
369 * NDIS 4.0
370 */
371 {
372 NdisMFreeSharedMemory(NdisAdapterHandle,
373 Length,
374 Cached,
375 VirtualAddress,
376 PhysicalAddress);
377 }
378
379
380 /* EOF */
381