840 lines
18 KiB
C
840 lines
18 KiB
C
/*++
|
|
|
|
Copyright (c) 1998-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
util.c
|
|
|
|
Abstract:
|
|
|
|
ATMEPVC - utilities
|
|
|
|
Author:
|
|
|
|
|
|
Revision History:
|
|
|
|
Who When What
|
|
-------- -------- ----
|
|
ADube 03-23-00 created, .
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
#if DO_TIMESTAMPS
|
|
|
|
void
|
|
epvcTimeStamp(
|
|
char *szFormatString,
|
|
UINT Val
|
|
)
|
|
{
|
|
UINT Minutes;
|
|
UINT Seconds;
|
|
UINT Milliseconds;
|
|
LARGE_INTEGER Time;
|
|
NdisGetCurrentSystemTime(&Time);
|
|
Time.QuadPart /= 10000; //10-nanoseconds to milliseconds.
|
|
Milliseconds = Time.LowPart; // don't care about highpart.
|
|
Seconds = Milliseconds/1000;
|
|
Milliseconds %= 1000;
|
|
Minutes = Seconds/60;
|
|
Seconds %= 60;
|
|
|
|
|
|
DbgPrint( szFormatString, Minutes, Seconds, Milliseconds, Val);
|
|
}
|
|
|
|
#endif // DO_TIMESTAMPS
|
|
|
|
//------------------------------------------------------------------------
|
|
// //
|
|
// Task Data structures and functions begin here //
|
|
// //
|
|
//----------------------------------------------------------------------//
|
|
|
|
|
|
//
|
|
// EpvcTasks_StaticInfo contains static information about
|
|
// objects of type EPVC_TASK;
|
|
//
|
|
RM_STATIC_OBJECT_INFO
|
|
EpvcTasks_StaticInfo =
|
|
{
|
|
0, // TypeUID
|
|
0, // TypeFlags
|
|
"ATM Epvc Task", // TypeName
|
|
0, // Timeout
|
|
|
|
NULL, // pfnCreate
|
|
epvcTaskDelete, // pfnDelete
|
|
NULL, // LockVerifier
|
|
|
|
0, // length of resource table
|
|
NULL // Resource Table
|
|
};
|
|
|
|
|
|
VOID
|
|
epvcTaskDelete (
|
|
PRM_OBJECT_HEADER pObj,
|
|
PRM_STACK_RECORD psr
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Free an object of type EPVC_TASK.
|
|
|
|
Arguments:
|
|
|
|
pHdr - Actually a pointer to the EPVC_TASK to be deleted.
|
|
|
|
--*/
|
|
{
|
|
EPVC_FREE(pObj);
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
epvcAllocateTask(
|
|
IN PRM_OBJECT_HEADER pParentObject,
|
|
IN PFN_RM_TASK_HANDLER pfnHandler,
|
|
IN UINT Timeout,
|
|
IN const char * szDescription, OPTIONAL
|
|
OUT PRM_TASK *ppTask,
|
|
IN PRM_STACK_RECORD pSR
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocates and initializes a task of subtype ARP1394_TASK.
|
|
|
|
Arguments:
|
|
|
|
pParentObject - Object that is to be the parent of the allocated task.
|
|
pfnHandler - The task handler for the task.
|
|
Timeout - Unused.
|
|
szDescription - Text describing this task.
|
|
ppTask - Place to store pointer to the new task.
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS if we could allocate and initialize the task.
|
|
NDIS_STATUS_RESOURCES otherwise
|
|
--*/
|
|
{
|
|
EPVC_TASK *pATask;
|
|
NDIS_STATUS Status;
|
|
|
|
Status = EPVC_ALLOCSTRUCT(pATask, TAG_TASK); // TODO use lookaside lists.
|
|
|
|
*ppTask = NULL;
|
|
|
|
if (pATask != NULL && (FAIL(Status)== FALSE))
|
|
{
|
|
EPVC_ZEROSTRUCT(pATask);
|
|
|
|
RmInitializeTask(
|
|
&(pATask->TskHdr),
|
|
pParentObject,
|
|
pfnHandler,
|
|
&EpvcTasks_StaticInfo,
|
|
szDescription,
|
|
Timeout,
|
|
pSR
|
|
);
|
|
*ppTask = &(pATask->TskHdr);
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
epvcAllocateTaskUsingLookasideList(
|
|
IN PRM_OBJECT_HEADER pParentObject,
|
|
IN PEPVC_NPAGED_LOOKASIDE_LIST pList,
|
|
IN PFN_RM_TASK_HANDLER pfnHandler,
|
|
IN UINT Timeout,
|
|
IN const char * szDescription, OPTIONAL
|
|
OUT PRM_TASK *ppTask,
|
|
IN PRM_STACK_RECORD pSR
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocates and initializes a task of subtype ARP1394_TASK.
|
|
|
|
Arguments:
|
|
|
|
pParentObject - Object that is to be the parent of the allocated task.
|
|
pfnHandler - The task handler for the task.
|
|
Timeout - Unused.
|
|
szDescription - Text describing this task.
|
|
ppTask - Place to store pointer to the new task.
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS if we could allocate and initialize the task.
|
|
NDIS_STATUS_RESOURCES otherwise
|
|
--*/
|
|
{
|
|
EPVC_TASK *pATask;
|
|
NDIS_STATUS Status;
|
|
|
|
pATask = epvcGetLookasideBuffer (pList);
|
|
|
|
|
|
Status = EPVC_ALLOCSTRUCT(pATask, TAG_TASK); // TODO use lookaside lists.
|
|
|
|
*ppTask = NULL;
|
|
|
|
if (pATask != NULL && (FAIL(Status)== FALSE))
|
|
{
|
|
EPVC_ZEROSTRUCT(pATask);
|
|
|
|
RmInitializeTask(
|
|
&(pATask->TskHdr),
|
|
pParentObject,
|
|
pfnHandler,
|
|
&EpvcTasks_StaticInfo,
|
|
szDescription,
|
|
Timeout,
|
|
pSR
|
|
);
|
|
*ppTask = &(pATask->TskHdr);
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID
|
|
epvcSetPrimaryAdapterTask(
|
|
PEPVC_ADAPTER pAdapter, // LOCKIN LOCKOUT
|
|
PRM_TASK pTask,
|
|
ULONG PrimaryState,
|
|
PRM_STACK_RECORD pSR
|
|
)
|
|
{
|
|
ENTER("epvcSetPrimaryAdapterTask", 0x49c9e2d5)
|
|
RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR);
|
|
|
|
ASSERT(pAdapter->bind.pPrimaryTask==NULL);
|
|
|
|
#if DBG
|
|
// Veriy that this is a valid primary task. Also verify that PrimaryState
|
|
// is a valid primary state.
|
|
//
|
|
{
|
|
PFN_RM_TASK_HANDLER pfn = pTask->pfnHandler;
|
|
ASSERT(
|
|
((pfn == epvcTaskInitializeAdapter) && (PrimaryState == EPVC_AD_PS_INITING))
|
|
|| ((pfn == epvcTaskShutdownAdapter) && (PrimaryState == EPVC_AD_PS_DEINITING))
|
|
);
|
|
}
|
|
#endif // DBG
|
|
|
|
//
|
|
// Although it's tempting to put pTask as entity1 and pRask->Hdr.szDescption as
|
|
// entity2 below, we specify NULL for both so that we can be sure that ONLY one
|
|
// primary task can be active at any one time.
|
|
//
|
|
DBG_ADDASSOC(
|
|
&pAdapter->Hdr,
|
|
NULL, // Entity1
|
|
NULL, // Entity2
|
|
EPVC_ASSOC_AD_PRIMARY_TASK,
|
|
" Primary task\n",
|
|
pSR
|
|
);
|
|
|
|
pAdapter->bind.pPrimaryTask = pTask;
|
|
SET_AD_PRIMARY_STATE(pAdapter, PrimaryState);
|
|
|
|
EXIT()
|
|
}
|
|
|
|
|
|
VOID
|
|
epvcClearPrimaryAdapterTask(
|
|
PEPVC_ADAPTER pAdapter, // LOCKIN LOCKOUT
|
|
PRM_TASK pTask,
|
|
ULONG PrimaryState,
|
|
PRM_STACK_RECORD pSR
|
|
)
|
|
{
|
|
ENTER("epvcClearPrimaryAdapterTask", 0x593087b1)
|
|
|
|
RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR);
|
|
ASSERT(pAdapter->bind.pPrimaryTask==pTask);
|
|
|
|
// Veriy that PrimaryState is a valid primary state.
|
|
//
|
|
ASSERT(
|
|
(PrimaryState == EPVC_AD_PS_INITED)
|
|
|| (PrimaryState == EPVC_AD_PS_FAILEDINIT)
|
|
|| (PrimaryState == EPVC_AD_PS_DEINITED)
|
|
);
|
|
|
|
// Delete the association added when setting the primary IF task
|
|
//
|
|
DBG_DELASSOC(
|
|
&pAdapter->Hdr,
|
|
NULL,
|
|
NULL,
|
|
EPVC_ASSOC_AD_PRIMARY_TASK,
|
|
pSR
|
|
);
|
|
|
|
pAdapter->bind.pPrimaryTask = NULL;
|
|
SET_AD_PRIMARY_STATE(pAdapter, PrimaryState);
|
|
|
|
EXIT()
|
|
}
|
|
|
|
|
|
VOID
|
|
epvcSetSecondaryAdapterTask(
|
|
PEPVC_ADAPTER pAdapter, // LOCKIN LOCKOUT
|
|
PRM_TASK pTask,
|
|
ULONG SecondaryState,
|
|
PRM_STACK_RECORD pSR
|
|
)
|
|
{
|
|
ENTER("epvcSetSecondaryAdapterTask", 0x56bbb567)
|
|
RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR);
|
|
|
|
if (pAdapter->bind.pSecondaryTask != NULL)
|
|
{
|
|
ASSERT(FALSE);
|
|
return; // EARLY RETURN
|
|
}
|
|
|
|
#if DBG
|
|
// Veriy that this is a valid act/deact task. Also verify that SecondaryState
|
|
// is a valid state.
|
|
//
|
|
{
|
|
PFN_RM_TASK_HANDLER pfn = pTask->pfnHandler;
|
|
ASSERT(
|
|
((pfn == epvcTaskActivateAdapter) && (SecondaryState == EPVC_AD_AS_ACTIVATING))
|
|
|| ((pfn == epvcTaskDeactivateAdapter) && (SecondaryState == EPVC_AD_AS_DEACTIVATING))
|
|
);
|
|
}
|
|
#endif // DBG
|
|
|
|
//
|
|
// Although it's tempting to put pTask as entity1 and pRask->Hdr.szDescption as
|
|
// entity2 below, we specify NULL for both so that we can be sure that ONLY one
|
|
// primary task can be active at any one time.
|
|
//
|
|
DBG_ADDASSOC(
|
|
&pAdapter->Hdr,
|
|
NULL, // Entity1
|
|
NULL, // Entity2
|
|
EPVC_ASSOC_ACTDEACT_AD_TASK,
|
|
" Secondary task\n",
|
|
pSR
|
|
);
|
|
|
|
pAdapter->bind.pSecondaryTask = pTask;
|
|
SET_AD_ACTIVE_STATE(pAdapter, SecondaryState);
|
|
|
|
EXIT()
|
|
}
|
|
|
|
|
|
VOID
|
|
epvcClearSecondaryAdapterTask(
|
|
PEPVC_ADAPTER pAdapter, // LOCKIN LOCKOUT
|
|
PRM_TASK pTask,
|
|
ULONG SecondaryState,
|
|
PRM_STACK_RECORD pSR
|
|
)
|
|
{
|
|
ENTER("epvcClearSecondaryAdapterTask", 0x698552bd)
|
|
RM_ASSERT_OBJLOCKED(&pAdapter->Hdr, pSR);
|
|
|
|
if (pAdapter->bind.pSecondaryTask != pTask)
|
|
{
|
|
ASSERT(FALSE);
|
|
return; // EARLY RETURN
|
|
}
|
|
|
|
// Veriy that SecondaryState is a valid primary state.
|
|
//
|
|
ASSERT(
|
|
(SecondaryState == EPVC_AD_AS_ACTIVATED)
|
|
|| (SecondaryState == EPVC_AD_AS_FAILEDACTIVATE)
|
|
|| (SecondaryState == EPVC_AD_AS_DEACTIVATED)
|
|
);
|
|
|
|
// Delete the association added when setting the primary IF task
|
|
//
|
|
DBG_DELASSOC(
|
|
&pAdapter->Hdr,
|
|
NULL,
|
|
NULL,
|
|
EPVC_ASSOC_ACTDEACT_AD_TASK,
|
|
pSR
|
|
);
|
|
|
|
pAdapter->bind.pSecondaryTask = NULL;
|
|
SET_AD_ACTIVE_STATE(pAdapter, SecondaryState);
|
|
|
|
EXIT()
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
epvcCopyUnicodeString(
|
|
OUT PNDIS_STRING pDest,
|
|
IN PNDIS_STRING pSrc,
|
|
BOOLEAN fUpCase
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Copy the contents of unicode string pSrc into pDest.
|
|
pDest->Buffer is allocated using NdisAllocateMemoryWithTag; Caller is
|
|
responsible for freeing it.
|
|
|
|
EXTRA EXTRA EXTRA:
|
|
This make sure the destination is NULL terminated.
|
|
IPAddInterface expects the Unicode string passed in to be
|
|
NULL terminated.
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS on success;
|
|
NDIS failure status on failure.
|
|
--*/
|
|
{
|
|
USHORT Length = pSrc->Length;
|
|
PWCHAR pwStr;
|
|
epvcAllocateMemoryWithTag(&pwStr, Length+sizeof(WCHAR), MTAG_STRING);
|
|
EPVC_ZEROSTRUCT(pDest);
|
|
|
|
if (pwStr == NULL)
|
|
{
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
pDest->Length = Length;
|
|
pDest->MaximumLength = Length+sizeof(WCHAR);
|
|
|
|
pDest->Buffer = pwStr;
|
|
|
|
{
|
|
NdisMoveMemory(pwStr, pSrc->Buffer, Length);
|
|
if (Length & 0x1)
|
|
{
|
|
((PUCHAR)pwStr)[Length] = 0;
|
|
}
|
|
else
|
|
{
|
|
pwStr[Length/sizeof(*pwStr)] = 0;
|
|
}
|
|
}
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
epvcSetFlags(
|
|
IN OUT ULONG* pulFlags,
|
|
IN ULONG ulMask )
|
|
|
|
// Set 'ulMask' bits in '*pulFlags' flags as an interlocked operation.
|
|
//
|
|
{
|
|
ULONG ulFlags;
|
|
ULONG ulNewFlags;
|
|
|
|
do
|
|
{
|
|
ulFlags = *pulFlags;
|
|
ulNewFlags = ulFlags | ulMask;
|
|
}
|
|
while (InterlockedCompareExchange(
|
|
pulFlags, ulNewFlags, ulFlags ) != (LONG )ulFlags);
|
|
}
|
|
|
|
VOID
|
|
epvcClearFlags(
|
|
IN OUT ULONG* pulFlags,
|
|
IN ULONG ulMask )
|
|
|
|
// Set 'ulMask' bits in '*pulFlags' flags as an interlocked operation.
|
|
//
|
|
{
|
|
ULONG ulFlags;
|
|
ULONG ulNewFlags;
|
|
|
|
do
|
|
{
|
|
ulFlags = *pulFlags;
|
|
ulNewFlags = ulFlags & ~(ulMask);
|
|
}
|
|
while (InterlockedCompareExchange(
|
|
pulFlags, ulNewFlags, ulFlags ) != (LONG )ulFlags);
|
|
}
|
|
|
|
ULONG
|
|
epvcReadFlags(
|
|
IN ULONG* pulFlags )
|
|
|
|
// Read the value of '*pulFlags' as an interlocked operation.
|
|
//
|
|
{
|
|
return *pulFlags;
|
|
}
|
|
|
|
|
|
|
|
BOOLEAN
|
|
epvcIsThisTaskPrimary (
|
|
PRM_TASK pTask,
|
|
PRM_TASK* ppLocation
|
|
)
|
|
{
|
|
BOOLEAN fIsThisTaskPrimary = FALSE;
|
|
|
|
ASSERT (*ppLocation != pTask);
|
|
|
|
if (*ppLocation == NULL)
|
|
{
|
|
*ppLocation = pTask;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
|
|
}
|
|
}
|
|
|
|
VOID
|
|
epvcClearPrimaryTask (
|
|
PRM_TASK* ppLocation
|
|
)
|
|
{
|
|
|
|
*ppLocation = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if DBG
|
|
VOID
|
|
CheckList(
|
|
IN LIST_ENTRY* pList,
|
|
IN BOOLEAN fShowLinks )
|
|
|
|
// Tries to detect corruption in list 'pList', printing verbose linkage
|
|
// output if 'fShowLinks' is set.
|
|
//
|
|
{
|
|
LIST_ENTRY* pLink;
|
|
ULONG ul;
|
|
|
|
ul = 0;
|
|
for (pLink = pList->Flink;
|
|
pLink != pList;
|
|
pLink = pLink->Flink)
|
|
{
|
|
if (fShowLinks)
|
|
{
|
|
DbgPrint( "EPVC: CheckList($%p) Flink(%d)=$%p\n",
|
|
pList, ul, pLink );
|
|
}
|
|
++ul;
|
|
}
|
|
|
|
for (pLink = pList->Blink;
|
|
pLink != pList;
|
|
pLink = pLink->Blink)
|
|
{
|
|
if (fShowLinks)
|
|
{
|
|
DbgPrint( "EPVC: CheckList($%p) Blink(%d)=$%p\n",
|
|
pList, ul, pLink );
|
|
}
|
|
--ul;
|
|
}
|
|
|
|
if (ul)
|
|
{
|
|
DbgBreakPoint();
|
|
}
|
|
}
|
|
#endif
|
|
|
|
|
|
#if DBG
|
|
VOID
|
|
Dump(
|
|
IN CHAR* p,
|
|
IN ULONG cb,
|
|
IN BOOLEAN fAddress,
|
|
IN ULONG ulGroup )
|
|
|
|
// Hex dump 'cb' bytes starting at 'p' grouping 'ulGroup' bytes together.
|
|
// For example, with 'ulGroup' of 1, 2, and 4:
|
|
//
|
|
// 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
|
// 0000 0000 0000 0000 0000 0000 0000 0000 |................|
|
|
// 00000000 00000000 00000000 00000000 |................|
|
|
//
|
|
// If 'fAddress' is true, the memory address dumped is prepended to each
|
|
// line.
|
|
//
|
|
{
|
|
while (cb)
|
|
{
|
|
INT cbLine;
|
|
|
|
cbLine = (cb < DUMP_BytesPerLine) ? cb : DUMP_BytesPerLine;
|
|
DumpLine( p, cbLine, fAddress, ulGroup );
|
|
cb -= cbLine;
|
|
p += cbLine;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if DBG
|
|
VOID
|
|
DumpLine(
|
|
IN CHAR* p,
|
|
IN ULONG cb,
|
|
IN BOOLEAN fAddress,
|
|
IN ULONG ulGroup )
|
|
{
|
|
CHAR* pszDigits = "0123456789ABCDEF";
|
|
CHAR szHex[ ((2 + 1) * DUMP_BytesPerLine) + 1 ];
|
|
CHAR* pszHex = szHex;
|
|
CHAR szAscii[ DUMP_BytesPerLine + 1 ];
|
|
CHAR* pszAscii = szAscii;
|
|
ULONG ulGrouped = 0;
|
|
|
|
if (fAddress)
|
|
DbgPrint( "EPVC: %p: ", p );
|
|
else
|
|
DbgPrint( "EPVC: " );
|
|
|
|
while (cb)
|
|
{
|
|
*pszHex++ = pszDigits[ ((UCHAR )*p) / 16 ];
|
|
*pszHex++ = pszDigits[ ((UCHAR )*p) % 16 ];
|
|
|
|
if (++ulGrouped >= ulGroup)
|
|
{
|
|
*pszHex++ = ' ';
|
|
ulGrouped = 0;
|
|
}
|
|
|
|
*pszAscii++ = (*p >= 32 && *p < 128) ? *p : '.';
|
|
|
|
++p;
|
|
--cb;
|
|
}
|
|
|
|
*pszHex = '\0';
|
|
*pszAscii = '\0';
|
|
|
|
DbgPrint(
|
|
"%-*s|%-*s|\n",
|
|
(2 * DUMP_BytesPerLine) + (DUMP_BytesPerLine / ulGroup), szHex,
|
|
DUMP_BytesPerLine, szAscii );
|
|
}
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
VOID
|
|
epvcInitializeLookasideList(
|
|
IN OUT PEPVC_NPAGED_LOOKASIDE_LIST pLookasideList,
|
|
ULONG Size,
|
|
ULONG Tag,
|
|
USHORT Depth
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
Allocates and initializes a epvc Lookaside list
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
TRACE( TL_T, TM_Mp, ( "==> epvcInitializeLookasideList pLookaside List %x, size %x, Tag %x, Depth %x, ",
|
|
pLookasideList, Size, Tag, Depth) );
|
|
|
|
NdisInitializeNPagedLookasideList( &pLookasideList->List,
|
|
NULL, //Allocate
|
|
NULL, // Free
|
|
0, // Flags
|
|
Size,
|
|
Tag,
|
|
Depth ); // Depth
|
|
|
|
pLookasideList->Size = Size;
|
|
pLookasideList->bIsAllocated = TRUE;
|
|
|
|
TRACE( TL_T, TM_Mp, ( "<== epvcInitializeLookasideList " ) );
|
|
}
|
|
|
|
|
|
VOID
|
|
epvcDeleteLookasideList (
|
|
IN OUT PEPVC_NPAGED_LOOKASIDE_LIST pLookasideList
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
Deletes a lookaside list, only if it has been allocated
|
|
|
|
Arguments:
|
|
|
|
|
|
Return Value:
|
|
|
|
|
|
--*/
|
|
{
|
|
TRACE( TL_T, TM_Mp, ( "==> epvcDeleteLookasideList pLookaside List %x",pLookasideList ) );
|
|
|
|
if (pLookasideList && pLookasideList->bIsAllocated == TRUE)
|
|
{
|
|
while (pLookasideList->OutstandingPackets != 0)
|
|
{
|
|
NdisMSleep( 10000);
|
|
|
|
}
|
|
|
|
NdisDeleteNPagedLookasideList (&pLookasideList->List);
|
|
}
|
|
|
|
TRACE( TL_T, TM_Mp, ( "<== epvcDeleteLookasideList pLookaside List %x", pLookasideList) );
|
|
|
|
}
|
|
|
|
|
|
PVOID
|
|
epvcGetLookasideBuffer(
|
|
IN PEPVC_NPAGED_LOOKASIDE_LIST pLookasideList
|
|
)
|
|
// Function Description:
|
|
// Allocate an buffer from the lookaside list.
|
|
// will be changed to a macro
|
|
//
|
|
//
|
|
//
|
|
// Arguments
|
|
// Lookaside list - from which the buffer is allocated
|
|
//
|
|
//
|
|
// Return Value:
|
|
// Return buffer can be NULL
|
|
//
|
|
{
|
|
|
|
PVOID pLocalBuffer = NULL;
|
|
|
|
TRACE( TL_T, TM_Send, ( "==>epvcGetLookasideBuffer pList %x",pLookasideList) );
|
|
|
|
ASSERT (pLookasideList != NULL);
|
|
|
|
//
|
|
// Optimize the lookaside list code path
|
|
//
|
|
pLocalBuffer = NdisAllocateFromNPagedLookasideList (&pLookasideList->List);
|
|
|
|
if (pLocalBuffer != NULL)
|
|
{
|
|
NdisZeroMemory (pLocalBuffer, pLookasideList->Size);
|
|
NdisInterlockedIncrement (&pLookasideList->OutstandingPackets);
|
|
}
|
|
else
|
|
{
|
|
epvcIncrementMallocFailure();
|
|
}
|
|
|
|
|
|
|
|
TRACE( TL_T, TM_Send, ( "<==epvcGetLookasideBuffer, %x", pLocalBuffer ) );
|
|
|
|
return pLocalBuffer ;
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
epvcFreeToNPagedLookasideList (
|
|
IN PEPVC_NPAGED_LOOKASIDE_LIST pLookasideList,
|
|
IN PVOID pBuffer
|
|
)
|
|
|
|
// Function Description:
|
|
// Return the local buffer to the lookaside list
|
|
//
|
|
// Atguments
|
|
// Lookaside list and its buffer
|
|
// Return Value:
|
|
// None
|
|
{
|
|
|
|
|
|
TRACE( TL_T, TM_Send, ( "==> epvcFreeToNPagedLookasideList , Lookaside list %x, plocalbuffer %x",pLookasideList, pBuffer ) );
|
|
|
|
NdisFreeToNPagedLookasideList (&pLookasideList->List, pBuffer);
|
|
NdisInterlockedDecrement (&pLookasideList->OutstandingPackets);
|
|
|
|
TRACE( TL_T, TM_Send, ( "<== epvcFreeToNPagedLookasideList ") );
|
|
|
|
|
|
}
|
|
|
|
|
|
|