|
|
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Module Name:
util.c
Abstract:
This module contains the routines some helper routines.
- Workitems: These routines manage the scheduled work items. - Handle table: There routines manage a handle table that creates unique handles and stores context pointers into the table that are only accessible by the unique handle generated.
Author:
Hakan Berk - Microsoft, Inc. (hakanb@microsoft.com) Feb-2000
Environment:
Windows 2000 kernel mode Miniport driver or equivalent.
Revision History:
---------------------------------------------------------------------------*/ #include <ntddk.h>
#include <ntddndis.h>
#include <ndis.h>
#include <ndiswan.h>
#include <ndistapi.h>
#include <ntverp.h>
#include "debug.h"
#include "timer.h"
#include "bpool.h"
#include "ppool.h"
#include "util.h"
#include "packet.h"
#include "protocol.h"
#include "miniport.h"
#include "tapi.h"
VOID InitializeWorkItemLookasideList( IN PNPAGED_LOOKASIDE_LIST pLookaside, IN ULONG tagLookaside ) { NdisInitializeNPagedLookasideList( pLookaside, NULL, NULL, 0, sizeof( WORKITEM ), tagLookaside, 0 ); } WORKITEM* AllocWorkItem( IN PNPAGED_LOOKASIDE_LIST pLookaside, IN WORKITEM_EXEC_ROUTINE pExecRoutine, IN WORKITEM_FREE_ROUTINE pFreeRoutine, IN PVOID Args[4], IN UINT workType ) { WORKITEM* pWorkItem = NULL;
//
// Allocate a binding work item from our pool
//
pWorkItem = NdisAllocateFromNPagedLookasideList( pLookaside );
if ( pWorkItem == NULL ) return NULL;
//
// Clear the memory
//
NdisZeroMemory( pWorkItem, sizeof( WORKITEM ) );
//
// Initialize the state of the work item
//
pWorkItem->workState = WS_NotScheduled;
//
// Initialize the type of work
//
pWorkItem->workType = workType;
//
// Set the lookaside list member
//
pWorkItem->pLookaside = pLookaside;
//
// Initialize the context for the work item
//
NdisMoveMemory( pWorkItem->Args, Args, 4 * sizeof( PVOID ) );
pWorkItem->pExecRoutine = pExecRoutine; pWorkItem->pFreeRoutine = pFreeRoutine; //
// As our NDIS_WORK_ITEM structure is embedded into our own work item
// we can initialize it here.
//
NdisInitializeWorkItem( &pWorkItem->ndisWorkItem, &WorkItemExec, pWorkItem );
return pWorkItem; }
VOID ScheduleWorkItem( IN WORKITEM *pWorkItem ) { //
// Initialize the state of the work item
//
pWorkItem->workState = WS_Scheduled;
//
// Schedule the item
//
NdisScheduleWorkItem( &pWorkItem->ndisWorkItem ); }
VOID FreeWorkItem( IN WORKITEM *pWorkItem ) { WORKITEM_FREE_ROUTINE pFreeRoutine = NULL;
ASSERT( pWorkItem != NULL );
//
// Free the associated context information
//
if ( pWorkItem->pFreeRoutine != NULL ) pWorkItem->pFreeRoutine( pWorkItem->Args, pWorkItem->workType );
//
// Free the actual work item
//
NdisFreeToNPagedLookasideList( pWorkItem->pLookaside, (PVOID) pWorkItem ); }
//
// This is the NDIS_WORK_ITEM handler that we schedule for our BINDING_WORKITEMs.
//
VOID WorkItemExec( IN NDIS_WORK_ITEM* pNdisWorkItem, IN PVOID pvContext ) { WORKITEM* pWorkItem = NULL; ASSERT( pNdisWorkItem != NULL );
pWorkItem = (WORKITEM*) pvContext;
ASSERT( pWorkItem->workState == WS_Scheduled ); pWorkItem->workState = WS_Executing;
if ( pWorkItem->pExecRoutine != NULL ) pWorkItem->pExecRoutine( pWorkItem->Args, pWorkItem->workType );
pWorkItem->workState = WS_Executed;
FreeWorkItem( pWorkItem ); }
HANDLE_TABLE InitializeHandleTable( IN UINT nHandleTableSize ) { NDIS_STATUS status = NDIS_STATUS_RESOURCES; HANDLE_TABLE Table = NULL;
do { //
// Allocate the table context
//
status = NdisAllocateMemoryWithTag( &Table, sizeof( HANDLE_TABLE_CB ), MTAG_HANDLETABLE ); if ( status != NDIS_STATUS_SUCCESS ) break; NdisZeroMemory( Table, sizeof( HANDLE_TABLE_CB ) ); //
// Allocate the array that holds the handle contexts
//
status = NdisAllocateMemoryWithTag( &Table->HandleTable, sizeof( HANDLE_CB ) * nHandleTableSize, MTAG_HANDLECB ); if ( status != NDIS_STATUS_SUCCESS ) break; NdisZeroMemory( Table->HandleTable, sizeof( HANDLE_CB ) * nHandleTableSize ); Table->nTableSize = nHandleTableSize; Table->nActiveHandles = 0; Table->usKeys = 0;
status = NDIS_STATUS_SUCCESS;
} while ( FALSE );
if ( status != NDIS_STATUS_SUCCESS ) FreeHandleTable( Table ); return Table; }
VOID FreeHandleTable( IN OUT HANDLE_TABLE Table ) { if ( Table == NULL ) return;
if ( Table->HandleTable ) { NdisFreeMemory( Table->HandleTable, Table->nTableSize * sizeof( HANDLE_CB ), 0 ); }
NdisFreeMemory( Table, sizeof( HANDLE_TABLE_CB ), 0 ); }
NDIS_HANDLE InsertToHandleTable( IN HANDLE_TABLE Table, IN USHORT usPreferedIndex, IN PVOID pContext ) { ULONG ulHandle; USHORT usKey;
HANDLE_CB* pHandleCB = NULL;
if ( Table == NULL ) return (NDIS_HANDLE) NULL;
if ( usPreferedIndex == NO_PREFERED_INDEX ) { UINT i; for (i = 0 ; i < Table->nTableSize ; i++ ) if ( !Table->HandleTable[i].fActive ) break;
usPreferedIndex = (USHORT) i; } else { if ( Table->HandleTable[ usPreferedIndex ].fActive ) return NULL; }
if ( usPreferedIndex >= Table->nTableSize ) return NULL;
//
// Generate Handle
//
ulHandle = (ULONG) usPreferedIndex;
usKey = ++Table->usKeys;
ulHandle = ulHandle << 16;
ulHandle |= (ULONG) usKey;
//
// Update the handle control block
//
pHandleCB = &Table->HandleTable[ usPreferedIndex ];
pHandleCB->fActive = TRUE;
pHandleCB->pContext = pContext;
pHandleCB->Handle = (NDIS_HANDLE) ULongToPtr( ulHandle );
//
// Increment the active handle counter
//
Table->nActiveHandles++;
return pHandleCB->Handle; } USHORT RetrieveIndexFromHandle( IN NDIS_HANDLE Handle ) { ULONG_PTR ulHandle = (ULONG_PTR) Handle; USHORT usIndex; usIndex = (USHORT) ( ulHandle >> 16 );
return usIndex; }
PVOID RetrieveFromHandleTable( IN HANDLE_TABLE Table, IN NDIS_HANDLE Handle ) { USHORT usIndex; HANDLE_CB* pHandleCB = NULL;
if ( Table == NULL ) return NULL;
usIndex = RetrieveIndexFromHandle( Handle );
if ( usIndex >= Table->nTableSize ) return NULL;
pHandleCB = &Table->HandleTable[ usIndex ];
if ( !pHandleCB->fActive ) return NULL;
if ( pHandleCB->Handle != Handle ) return NULL;
return pHandleCB->pContext;
}
PVOID RetrieveFromHandleTableByIndex( IN HANDLE_TABLE Table, IN USHORT usIndex ) { HANDLE_CB* pHandleCB = NULL;
if ( Table == NULL ) return NULL; if ( usIndex >= Table->nTableSize ) return NULL;
pHandleCB = &Table->HandleTable[ usIndex ];
if ( !pHandleCB->fActive ) return NULL;
return pHandleCB->pContext; }
PVOID RetrieveFromHandleTableBySessionId( IN HANDLE_TABLE Table, IN USHORT usSessionId ) { USHORT usIndex = usSessionId - 1;
return RetrieveFromHandleTableByIndex( Table, usIndex ); }
VOID RemoveFromHandleTable( IN HANDLE_TABLE Table, IN NDIS_HANDLE Handle ) { USHORT usIndex;
HANDLE_CB* pHandleCB = NULL;
if ( Table == NULL ) return; usIndex = RetrieveIndexFromHandle( Handle );
if ( usIndex >= Table->nTableSize ) return;
pHandleCB = &Table->HandleTable[ usIndex ];
if ( !pHandleCB->fActive ) return;
if ( pHandleCB->Handle != Handle ) return;
NdisZeroMemory( pHandleCB, sizeof( HANDLE_CB ) );
Table->nActiveHandles--; }
USHORT RetrieveSessionIdFromHandle( IN NDIS_HANDLE Handle ) { return ( RetrieveIndexFromHandle( Handle ) + 1 ); }
|