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
22 NdisAllocateMemoryWithTag(
23 OUT PVOID
*VirtualAddress
,
27 * FUNCTION: Allocates a block of memory, with a 32-bit tag
29 * VirtualAddress = a pointer to the returned memory block
30 * Length = the number of requested bytes
31 * Tag = 32-bit pool tag
33 * NDIS_STATUS_SUCCESS on success
34 * NDIS_STATUS_FAILURE on failure
39 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
41 Block
= ExAllocatePoolWithTag(NonPagedPool
, Length
, Tag
);
42 *VirtualAddress
= Block
;
45 NDIS_DbgPrint(MIN_TRACE
, ("Failed to allocate memory (%lx)\n", Length
));
46 return NDIS_STATUS_FAILURE
;
49 return NDIS_STATUS_SUCCESS
;
60 OUT PVOID
*VirtualAddress
,
63 IN NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress
)
65 * FUNCTION: Allocates a block of memory
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
73 * NDIS_STATUS_SUCCESS on success
74 * NDIS_STATUS_FAILURE on failure
77 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
79 if (MemoryFlags
& NDIS_MEMORY_CONTIGUOUS
)
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
);
88 else if (MemoryFlags
& NDIS_MEMORY_NONCACHED
)
90 /* Allocate noncached noncontiguous memory */
91 *VirtualAddress
= MmAllocateNonCachedMemory(Length
);
95 /* Allocate plain nonpaged memory */
96 *VirtualAddress
= ExAllocatePool(NonPagedPool
, Length
);
99 if (!*VirtualAddress
) {
100 NDIS_DbgPrint(MIN_TRACE
, ("Allocation failed (%lx, %lx)\n", MemoryFlags
, Length
));
101 return NDIS_STATUS_FAILURE
;
104 return NDIS_STATUS_SUCCESS
;
114 IN PVOID VirtualAddress
,
118 * FUNCTION: Frees a memory block allocated with NdisAllocateMemory
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
125 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
127 if (MemoryFlags
& NDIS_MEMORY_CONTIGUOUS
)
129 /* Free contiguous memory (possibly noncached) */
130 MmFreeContiguousMemorySpecifyCache(VirtualAddress
,
132 (MemoryFlags
& NDIS_MEMORY_NONCACHED
) ? MmNonCached
: MmCached
);
134 else if (MemoryFlags
& NDIS_MEMORY_NONCACHED
)
136 /* Free noncached noncontiguous memory */
137 MmFreeNonCachedMemory(VirtualAddress
, Length
);
141 /* Free nonpaged pool */
142 ExFreePool(VirtualAddress
);
152 NdisMAllocateSharedMemory(
153 IN NDIS_HANDLE MiniportAdapterHandle
,
156 OUT PVOID
*VirtualAddress
,
157 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress
)
159 * FUNCTION: Allocate a common buffer for DMA
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
167 * - Cached is ignored; we always allocate non-cached
170 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
172 NDIS_DbgPrint(MAX_TRACE
,("Called.\n"));
174 if (KeGetCurrentIrql() != PASSIVE_LEVEL
)
176 KeBugCheckEx(BUGCODE_ID_DRIVER
,
177 (ULONG_PTR
)MiniportAdapterHandle
,
183 *VirtualAddress
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
->DmaOperations
->AllocateCommonBuffer(
184 Adapter
->NdisMiniportBlock
.SystemAdapterObject
, Length
, PhysicalAddress
, Cached
);
190 NdisMFreeSharedMemoryPassive(
191 PDEVICE_OBJECT DeviceObject
,
194 * FUNCTION: Free a common buffer
196 * Context: Pointer to a miniport shared memory context
198 * - Called by NdisMFreeSharedMemory to do the actual work
201 PMINIPORT_SHARED_MEMORY Memory
= (PMINIPORT_SHARED_MEMORY
)Context
;
203 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
205 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
207 Memory
->AdapterObject
->DmaOperations
->FreeCommonBuffer(
208 Memory
->AdapterObject
, Memory
->Length
, Memory
->PhysicalAddress
,
209 Memory
->VirtualAddress
, Memory
->Cached
);
211 IoFreeWorkItem(Memory
->WorkItem
);
221 NdisMFreeSharedMemory(
222 IN NDIS_HANDLE MiniportAdapterHandle
,
225 IN PVOID VirtualAddress
,
226 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
)
228 * FUNCTION: Free a shared memory block
230 * MiniportAdapterHandle: Handle passed into MiniportInitialize
231 * Length: Number of bytes in the block to free
232 * Cached: Whether or not the memory was cached
233 * VirtualAddress: Address to free
234 * PhysicalAddress: corresponding physical addres
236 * - This function can be called at dispatch_level or passive_level.
237 * Therefore we have to do this in a worker thread.
240 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
241 PMINIPORT_SHARED_MEMORY Memory
;
242 PDMA_ADAPTER DmaAdapter
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
;
244 NDIS_DbgPrint(MAX_TRACE
,("Called.\n"));
246 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
248 /* Call FreeCommonBuffer synchronously if we are at PASSIVE_LEVEL */
249 if (KeGetCurrentIrql() == PASSIVE_LEVEL
)
251 /* We need this case because we free shared memory asynchronously
252 * and the miniport (and DMA adapter object) could be freed before
253 * our work item executes. Lucky for us, the scenarios where the
254 * freeing needs to be synchronous (failed init, MiniportHalt,
255 * and driver unload) are all at PASSIVE_LEVEL so we can just
256 * call FreeCommonBuffer synchronously and not have to worry
257 * about the miniport falling out from under us */
259 NDIS_DbgPrint(MID_TRACE
,("Freeing shared memory synchronously\n"));
261 DmaAdapter
->DmaOperations
->FreeCommonBuffer(DmaAdapter
,
269 /* Must be NonpagedPool because by definition we're at DISPATCH_LEVEL */
270 Memory
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_SHARED_MEMORY
));
274 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
278 Memory
->AdapterObject
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
;
279 Memory
->Length
= Length
;
280 Memory
->PhysicalAddress
= PhysicalAddress
;
281 Memory
->VirtualAddress
= VirtualAddress
;
282 Memory
->Cached
= Cached
;
283 Memory
->Adapter
= &Adapter
->NdisMiniportBlock
;
285 Memory
->WorkItem
= IoAllocateWorkItem(Adapter
->NdisMiniportBlock
.DeviceObject
);
286 if (!Memory
->WorkItem
)
288 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
293 IoQueueWorkItem(Memory
->WorkItem
,
294 NdisMFreeSharedMemoryPassive
,
301 NdisMAllocateSharedMemoryPassive(
302 PDEVICE_OBJECT DeviceObject
,
305 * FUNCTION: Allocate a common buffer
307 * Context: Pointer to a miniport shared memory context
309 * - Called by NdisMAllocateSharedMemoryAsync to do the actual work
312 PMINIPORT_SHARED_MEMORY Memory
= (PMINIPORT_SHARED_MEMORY
)Context
;
314 NDIS_DbgPrint(MAX_TRACE
, ("Called.\n"));
316 ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL
);
318 Memory
->VirtualAddress
= Memory
->AdapterObject
->DmaOperations
->AllocateCommonBuffer(
319 Memory
->AdapterObject
, Memory
->Length
, &Memory
->PhysicalAddress
, Memory
->Cached
);
321 if (Memory
->Adapter
->DriverHandle
->MiniportCharacteristics
.AllocateCompleteHandler
)
322 Memory
->Adapter
->DriverHandle
->MiniportCharacteristics
.AllocateCompleteHandler(
323 Memory
->Adapter
->MiniportAdapterContext
, Memory
->VirtualAddress
,
324 &Memory
->PhysicalAddress
, Memory
->Length
, Memory
->Context
);
326 IoFreeWorkItem(Memory
->WorkItem
);
336 NdisMAllocateSharedMemoryAsync(
337 IN NDIS_HANDLE MiniportAdapterHandle
,
342 PLOGICAL_ADAPTER Adapter
= (PLOGICAL_ADAPTER
)MiniportAdapterHandle
;
343 PMINIPORT_SHARED_MEMORY Memory
;
345 NDIS_DbgPrint(MAX_TRACE
,("Called.\n"));
347 ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL
);
349 /* Must be NonpagedPool because by definition we're at DISPATCH_LEVEL */
350 Memory
= ExAllocatePool(NonPagedPool
, sizeof(MINIPORT_SHARED_MEMORY
));
354 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
355 return NDIS_STATUS_FAILURE
;
358 Memory
->AdapterObject
= Adapter
->NdisMiniportBlock
.SystemAdapterObject
;
359 Memory
->Length
= Length
;
360 Memory
->Cached
= Cached
;
361 Memory
->Adapter
= &Adapter
->NdisMiniportBlock
;
362 Memory
->Context
= Context
;
364 Memory
->WorkItem
= IoAllocateWorkItem(Adapter
->NdisMiniportBlock
.DeviceObject
);
365 if (!Memory
->WorkItem
)
367 NDIS_DbgPrint(MIN_TRACE
, ("Insufficient resources\n"));
369 return NDIS_STATUS_FAILURE
;
372 IoQueueWorkItem(Memory
->WorkItem
,
373 NdisMAllocateSharedMemoryPassive
,
377 return NDIS_STATUS_PENDING
;
385 NdisAllocateSharedMemory(
386 IN NDIS_HANDLE NdisAdapterHandle
,
389 OUT PVOID
*VirtualAddress
,
390 OUT PNDIS_PHYSICAL_ADDRESS PhysicalAddress
)
392 NdisMAllocateSharedMemory(NdisAdapterHandle
,
405 NdisFreeSharedMemory(
406 IN NDIS_HANDLE NdisAdapterHandle
,
409 IN PVOID VirtualAddress
,
410 IN NDIS_PHYSICAL_ADDRESS PhysicalAddress
)
418 NdisMFreeSharedMemory(NdisAdapterHandle
,