/*++ Copyright (c) 1999-2000 Microsoft Corporation Module Name: mdlpool9x.c Abstract: This file contains the implementation of an NDIS_BUFFER pool. Author: Shaun Cox (shaunco) 11-Nov-1999 --*/ #include "ndis.h" #include "mdlpool.h" // The pool structure itself is just a look aside list allocated out of // non-paged pool. // // Each entry in the look aside list is an NDIS_BUFFER structure followed // by the buffer itself. We initialize the NDIS_BUFFER structure each // time we allocate from the look aside list. We need to do this in order // to properly associate the NDIS_BUFFER with its owning pool. This is not // possible to do with a custom allocate routine for the look aside list // because their is no provision for an extra context parameter to the // look aside allocate function. // // ---- Temporary Definitions until ndis.h is updated for Millennium ----- // typedef struct _XNDIS_BUFFER { struct _NDIS_BUFFER *Next; PVOID VirtualAddress; PVOID Pool; UINT Length; UINT Signature; } XNDIS_BUFFER, *PXNDIS_BUFFER; __inline SIZE_T NDIS_SIZEOF_NDIS_BUFFER( VOID ) { return sizeof(XNDIS_BUFFER); } __inline VOID NdisInitializeNdisBuffer( OUT PNDIS_BUFFER Buffer, IN PVOID Pool, IN PVOID VirtualAddress, IN UINT Length ) { PXNDIS_BUFFER Internal = (PXNDIS_BUFFER)Buffer; Internal->Next = 0; Internal->Pool = Pool; Internal->VirtualAddress = VirtualAddress; Internal->Length = Length; Internal->Signature = 0; } __inline PVOID NdisGetPoolFromNdisBuffer( IN PNDIS_BUFFER Buffer ) { PXNDIS_BUFFER Internal = (PXNDIS_BUFFER)Buffer; return Internal->Pool; } // ---- End temporary Definitions until ndis.h is updated for Millennium ----- UINT SizeOfNdisBufferStructure; // Creates a pool of NDIS_BUFFERs built over non-paged pool. Each // NDIS_BUFFER describes a buffer that is BufferSize bytes long. // If NULL is not returned, MdpDestroyPool should be called at a later time // to reclaim the resources used by the pool. // // Arguments: // BufferSize - The size, in bytes, of the buffer that each MDL // should describe. // Tag - The pool tag to be used internally for calls to // ExAllocatePoolWithTag. This allows callers to track // memory consumption for different pools. // // Returns the handle used to identify the pool. // // Caller IRQL: [PASSIVE_LEVEL, DISPATCH_LEVEL] // HANDLE MdpCreatePool( IN USHORT BufferSize, IN ULONG Tag ) { PNPAGED_LOOKASIDE_LIST Lookaside; ASSERT(BufferSize); // Cache the constant value of an NDIS_BUFFER structure size to // avoid calling back into NDIS everytime we want a buffer. // if (0 == SizeOfNdisBufferStructure) { SizeOfNdisBufferStructure = NDIS_SIZEOF_NDIS_BUFFER(); } ASSERT(SizeOfNdisBufferStructure); // Allocate the pool header. This is a look aside list on Millenium. // Lookaside = ExAllocatePoolWithTag( NonPagedPool, sizeof(NPAGED_LOOKASIDE_LIST), ' pdM'); if (Lookaside) { // The size of the entries allocated by the look aside list are // the NDIS_BUFFER structure size plus the buffer size requested by // the caller. // ExInitializeNPagedLookasideList( Lookaside, NULL, NULL, 0, SizeOfNdisBufferStructure + BufferSize, Tag, 0); } return Lookaside; } // Destroys a pool of NDIS_BUFFERs previously created by a call to // MdpCreatePool. // // Arguments: // PoolHandle - Handle which identifies the pool being destroyed. // // Caller IRQL: [PASSIVE_LEVEL, DISPATCH_LEVEL] // VOID MdpDestroyPool( IN HANDLE PoolHandle ) { ExDeleteNPagedLookasideList(PoolHandle); } // Returns an NDIS_BUFFER allocated from a pool. NULL is returned if the // request could not be granted. // // Arguments: // PoolHandle - Handle which identifies the pool being allocated from. // Buffer - Address to receive the pointer to the underlying mapped buffer // described by the MDL. // // Caller IRQL: [PASSIVE_LEVEL, DISPATCH_LEVEL] // PNDIS_BUFFER MdpAllocate( IN HANDLE PoolHandle, OUT PVOID* Buffer ) { PNPAGED_LOOKASIDE_LIST Lookaside; PNDIS_BUFFER NdisBuffer; PUCHAR VirtualAddress; ASSERT(PoolHandle); Lookaside = (PNPAGED_LOOKASIDE_LIST)PoolHandle; // Get an item from the look aside list. // NdisBuffer = ExAllocateFromNPagedLookasideList(Lookaside); if (NdisBuffer) { // (Re)Initialize it to associate it with the pool handle so that // we know which look aside list to return it to when it is freed. // VirtualAddress = (PUCHAR)NdisBuffer + SizeOfNdisBufferStructure; NdisInitializeNdisBuffer( NdisBuffer, PoolHandle, VirtualAddress, Lookaside->L.Size - SizeOfNdisBufferStructure); *Buffer = VirtualAddress; } return NdisBuffer; } // Free an NDIS_BUFFER to the pool from which it was allocated. // // Arguments: // NdisBuffer - An NDIS_BUFFER returned from a prior call to MdpAllocate. // // Caller IRQL: [PASSIVE_LEVEL, DISPATCH_LEVEL] // VOID MdpFree( IN PNDIS_BUFFER NdisBuffer ) { PNPAGED_LOOKASIDE_LIST Lookaside; // Locate the owning look aside list for this buffer and return it. // Lookaside = NdisGetPoolFromNdisBuffer(NdisBuffer); ASSERT(Lookaside); ExFreeToNPagedLookasideList(Lookaside, NdisBuffer); }