2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS NDIS library
5 * PURPOSE: Memory management routines
6 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7 * Vizzini (vizzini@plasmic.com)
9 * CSH 01/08-2000 Created
10 * 15 Aug 2003 Vizzini - DMA support
11 * 3 Oct 2003 Vizzini - formatting and minor bugfixing
21 NdisAllocateMemoryWithTag(
22 OUT PVOID
*VirtualAddress
,
26 * FUNCTION: Allocates a block of memory, with a 32-bit tag
28 * VirtualAddress = a pointer to the returned memory block
29 * Length = the number of requested bytes
30 * Tag = 32-bit pool tag
32 * NDIS_STATUS_SUCCESS on success
33 * NDIS_STATUS_FAILURE on failure
38 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
40 Block
= ExAllocatePoolWithTag(NonPagedPool
, Length
, Tag
);
41 *VirtualAddress
= Block
;
44 NDIS_DbgPrint(MIN_TRACE
, ("Failed to allocate memory (%lx)\n", Length
));
45 return NDIS_STATUS_FAILURE
;
48 return NDIS_STATUS_SUCCESS
;
58 OUT PVOID
*VirtualAddress
,
61 IN NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
)
63 * FUNCTION: Allocates a block of memory
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
71 * NDIS_STATUS_SUCCESS on success
72 * NDIS_STATUS_FAILURE on failure
75 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
77 if (MemoryFlags
& NDIS_MEMORY_CONTIGUOUS
)
79 /* Allocate contiguous memory (possibly noncached) */
80 *VirtualAddress
= MmAllocateContiguousMemorySpecifyCache(Length
,
81 RtlConvertUlongToLargeInteger(0),
82 HighestAcceptableAddress
,
83 RtlConvertUlongToLargeInteger(0),
84 (MemoryFlags
& NDIS_MEMORY_NONCACHED
) ? MmNonCached
: MmCached
);
86 else if (MemoryFlags
& NDIS_MEMORY_NONCACHED
)
88 /* Allocate noncached noncontiguous memory */
89 *VirtualAddress
= MmAllocateNonCachedMemory(Length
);
93 /* Allocate plain nonpaged memory */
94 *VirtualAddress
= ExAllocatePool(NonPagedPool
, Length
);
97 if (!*VirtualAddress
) {
98 NDIS_DbgPrint(MIN_TRACE
, ("Allocation failed (%lx, %lx)\n", MemoryFlags
, Length
));
99 return NDIS_STATUS_FAILURE
;
102 return NDIS_STATUS_SUCCESS
;
111 IN PVOID VirtualAddress
,
115 * FUNCTION: Frees a memory block allocated with NdisAllocateMemory
117 * VirtualAddress = Pointer to the base virtual address of the allocated memory
118 * Length = Size of the allocated memory block as passed to NdisAllocateMemory
119 * MemoryFlags = Memory flags passed to NdisAllocateMemory
122 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
124 if (MemoryFlags
& NDIS_MEMORY_CONTIGUOUS
)
126 /* Free contiguous memory (possibly noncached) */
127 MmFreeContiguousMemorySpecifyCache(VirtualAddress
,
129 (MemoryFlags
& NDIS_MEMORY_NONCACHED
) ? MmNonCached
: MmCached
);
131 else if (MemoryFlags
& NDIS_MEMORY_NONCACHED
)
133 /* Free noncached noncontiguous memory */
134 MmFreeNonCachedMemory(VirtualAddress
, Length
);
138 /* Free nonpaged pool */
139 ExFreePool(VirtualAddress
);
148 NdisMAllocateSharedMemory(
149 IN NDIS_HANDLE MiniportAdapterHandle
,
152 OUT PVOID
*VirtualAddress
,
153 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress
)
155 * FUNCTION: Allocate a common buffer for DMA
157 * MiniportAdapterHandle: Handle passed into MiniportInitialize
158 * Length: Number of bytes to allocate
159 * Cached: Whether or not the memory can be cached
160 * VirtualAddress: Pointer to memory is returned here
161 * PhysicalAddress: Physical address corresponding to virtual address
163 * - Cached is ignored; we always allocate non-cached
166 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
168 NDIS_DbgPrint(MAX_TRACE
,("Called.\n"));
170 if (KeGetCurrentIrql() != PASSIVE_LEVEL
)
172 KeBugCheckEx(BUGCODE_ID_DRIVER
,
173 (ULONG_PTR
)MiniportAdapterHandle
,
179 *VirtualAddress
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->AllocateCommonBuffer(
180 Adapter
->NdisMiniportBlock
.SystemAdapterObject
, Length
, PhysicalAddress
, Cached
);
185 NdisMFreeSharedMemoryPassive(
186 PDEVICE_OBJECT DeviceObject
,
189 * FUNCTION: Free a common buffer
191 * Context: Pointer to a miniport shared memory context
193 * - Called by NdisMFreeSharedMemory to do the actual work
196 PMINIPORT_SHARED_MEMORY Memory
= (PMINIPORT_SHARED_MEMORY
)Context
;
198 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
200 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
202 Memory
->AdapterObject
->DmaOperations
->FreeCommonBuffer(
203 Memory
->AdapterObject
, Memory
->Length
, Memory
->PhysicalAddress
,
204 Memory
->VirtualAddress
, Memory
->Cached
);
206 IoFreeWorkItem(Memory
->WorkItem
);
215 NdisMFreeSharedMemory(
216 IN NDIS_HANDLE MiniportAdapterHandle
,
219 IN PVOID VirtualAddress
,
220 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
)
222 * FUNCTION: Free a shared memory block
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
230 * - This function can be called at dispatch_level or passive_level.
231 * Therefore we have to do this in a worker thread.
234 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
235 PMINIPORT_SHARED_MEMORY Memory
;
236 PDMA_ADAPTER DmaAdapter
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
;
238 NDIS_DbgPrint(MAX_TRACE
,("Called.\n"));
240 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
242 /* Call FreeCommonBuffer synchronously if we are at PASSIVE_LEVEL */
243 if (KeGetCurrentIrql() == PASSIVE_LEVEL
)
245 /* We need this case because we free shared memory asynchronously
246 * and the miniport (and DMA adapter object) could be freed before
247 * our work item executes. Lucky for us, the scenarios where the
248 * freeing needs to be synchronous (failed init, MiniportHalt,
249 * and driver unload) are all at PASSIVE_LEVEL so we can just
250 * call FreeCommonBuffer synchronously and not have to worry
251 * about the miniport falling out from under us */
253 NDIS_DbgPrint(MID_TRACE
,("Freeing shared memory synchronously\n"));
255 DmaAdapter
->DmaOperations
->FreeCommonBuffer(DmaAdapter
,
263 /* Must be NonpagedPool because by definition we're at DISPATCH_LEVEL */
264 Memory
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_SHARED_MEMORY
));
268 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
272 Memory
->AdapterObject
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
;
273 Memory
->Length
= Length
;
274 Memory
->PhysicalAddress
= PhysicalAddress
;
275 Memory
->VirtualAddress
= VirtualAddress
;
276 Memory
->Cached
= Cached
;
277 Memory
->Adapter
= &Adapter
->NdisMiniportBlock
;
279 Memory
->WorkItem
= IoAllocateWorkItem(Adapter
->NdisMiniportBlock
.DeviceObject
);
280 if (!Memory
->WorkItem
)
282 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
287 IoQueueWorkItem(Memory
->WorkItem
,
288 NdisMFreeSharedMemoryPassive
,
295 NdisMAllocateSharedMemoryPassive(
296 PDEVICE_OBJECT DeviceObject
,
299 * FUNCTION: Allocate a common buffer
301 * Context: Pointer to a miniport shared memory context
303 * - Called by NdisMAllocateSharedMemoryAsync to do the actual work
306 PMINIPORT_SHARED_MEMORY Memory
= (PMINIPORT_SHARED_MEMORY
)Context
;
308 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
310 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
312 Memory
->VirtualAddress
= Memory
->AdapterObject
->DmaOperations
->AllocateCommonBuffer(
313 Memory
->AdapterObject
, Memory
->Length
, &Memory
->PhysicalAddress
, Memory
->Cached
);
315 if (Memory
->Adapter
->DriverHandle
->MiniportCharacteristics
.AllocateCompleteHandler
)
316 Memory
->Adapter
->DriverHandle
->MiniportCharacteristics
.AllocateCompleteHandler(
317 Memory
->Adapter
->MiniportAdapterContext
, Memory
->VirtualAddress
,
318 &Memory
->PhysicalAddress
, Memory
->Length
, Memory
->Context
);
320 IoFreeWorkItem(Memory
->WorkItem
);
330 NdisMAllocateSharedMemoryAsync(
331 IN NDIS_HANDLE MiniportAdapterHandle
,
336 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
337 PMINIPORT_SHARED_MEMORY Memory
;
339 NDIS_DbgPrint(MAX_TRACE
,("Called.\n"));
341 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
343 /* Must be NonpagedPool because by definition we're at DISPATCH_LEVEL */
344 Memory
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_SHARED_MEMORY
));
348 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
349 return NDIS_STATUS_FAILURE
;
352 Memory
->AdapterObject
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
;
353 Memory
->Length
= Length
;
354 Memory
->Cached
= Cached
;
355 Memory
->Adapter
= &Adapter
->NdisMiniportBlock
;
356 Memory
->Context
= Context
;
358 Memory
->WorkItem
= IoAllocateWorkItem(Adapter
->NdisMiniportBlock
.DeviceObject
);
359 if (!Memory
->WorkItem
)
361 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
363 return NDIS_STATUS_FAILURE
;
366 IoQueueWorkItem(Memory
->WorkItem
,
367 NdisMAllocateSharedMemoryPassive
,
371 return NDIS_STATUS_PENDING
;
379 NdisAllocateSharedMemory(
380 IN NDIS_HANDLE NdisAdapterHandle
,
383 OUT PVOID
*VirtualAddress
,
384 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress
)
386 NdisMAllocateSharedMemory(NdisAdapterHandle
,
399 NdisFreeSharedMemory(
400 IN NDIS_HANDLE NdisAdapterHandle
,
403 IN PVOID VirtualAddress
,
404 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
)
412 NdisMFreeSharedMemory(NdisAdapterHandle
,