|
|
/***************************************************************************
Copyright (c) 1999 Microsoft Corporation
Module Name:
UTIL.C
Abstract:
Utility routines for Remote NDIS Miniport driver
Environment:
kernel mode only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
Revision History:
5/17/99 : created
Author:
Tom Green
****************************************************************************/
#include "precomp.h"
ULONG MsgFrameAllocs = 0;
/****************************************************************************/ /* MemAlloc */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Allocate memory */ /* */ /* Arguments: */ /* */ /* Buffer - pointer to buffer pointer */ /* Length - length of buffer to allocate */ /* */ /* Return: */ /* */ /* NDIS_STATUS */ /* */ /****************************************************************************/ NDIS_STATUS MemAlloc(OUT PVOID *Buffer, IN UINT Length) { NDIS_STATUS Status;
TRACE3(("MemAlloc\n")); ASSERT(Length != 0);
Status = NdisAllocateMemoryWithTag(Buffer, Length, RNDISMP_TAG_GEN_ALLOC);
// zero out allocation
if(Status == NDIS_STATUS_SUCCESS) NdisZeroMemory(*Buffer, Length);
return Status; } // MemAlloc
/****************************************************************************/ /* MemFree */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Free memory */ /* */ /* Arguments: */ /* */ /* Buffer - pointer to buffer */ /* Length - length of buffer to allocate */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID MemFree(IN PVOID Buffer, IN UINT Length) { TRACE3(("MemFree\n"));
NdisFreeMemory(Buffer, Length, 0); } // MemFree
/****************************************************************************/ /* AddAdapter */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Add an adapter to the list of adapters associated with this driver */ /* */ /* Arguments: */ /* */ /* pAdapter - Adapter object, contains pointer to associated driver block */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID AddAdapter(IN PRNDISMP_ADAPTER pAdapter) { PDRIVER_BLOCK DriverBlock = pAdapter->DriverBlock;
TRACE3(("AddpAdapter\n"));
CHECK_VALID_ADAPTER(pAdapter);
// grab the global spinlock
NdisAcquireSpinLock(&RndismpGlobalLock);
pAdapter->NextAdapter = DriverBlock->AdapterList; DriverBlock->AdapterList = pAdapter;
// keep track of number of adapters associated with this driver block
DriverBlock->NumberAdapters++;
// release global spinlock
NdisReleaseSpinLock(&RndismpGlobalLock);
} // AddAdapter
/****************************************************************************/ /* RemoveAdapter */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Remove an adapter from the list of adapters associated with this driver */ /* */ /* Arguments: */ /* */ /* pAdapter - Adapter object, contains pointer to associated driver block */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID RemoveAdapter(IN PRNDISMP_ADAPTER pAdapter) { PDRIVER_BLOCK DriverBlock = pAdapter->DriverBlock;
TRACE3(("RemoveAdapter\n"));
CHECK_VALID_ADAPTER(pAdapter);
// remove the adapter from the driver block list of adapters.
// grab the global spinlock
NdisAcquireSpinLock(&RndismpGlobalLock);
// see if it is the first one
if (DriverBlock->AdapterList == pAdapter) { DriverBlock->AdapterList = pAdapter->NextAdapter;
} // not the first one, so walk the list
else { PRNDISMP_ADAPTER * ppAdapter = &DriverBlock->AdapterList;
while (*ppAdapter != pAdapter) { ASSERT(*ppAdapter != NULL); ppAdapter = &((*ppAdapter)->NextAdapter); }
*ppAdapter = pAdapter->NextAdapter; }
// removing this adapter
DriverBlock->NumberAdapters--;
// release global spinlock
NdisReleaseSpinLock(&RndismpGlobalLock);
} // RemoveAdapter
/****************************************************************************/ /* DeviceObjectToAdapter */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Given a pointer to an FDO, return the corresponding Adapter structure, */ /* if it exists, and the driver block. */ /* */ /* Arguments: */ /* */ /* pDeviceObject - pointer to the device object to search for. */ /* ppAdapter - place to return pointer to the adapter structure. */ /* ppDriverBlock - place to return pointer to driver block. */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID DeviceObjectToAdapterAndDriverBlock(IN PDEVICE_OBJECT pDeviceObject, OUT PRNDISMP_ADAPTER * ppAdapter, OUT PDRIVER_BLOCK * ppDriverBlock) { PDRIVER_BLOCK pDriverBlock; PRNDISMP_ADAPTER pAdapter;
pAdapter = NULL; pDriverBlock = DeviceObjectToDriverBlock(&RndismpMiniportBlockListHead, pDeviceObject); if (pDriverBlock != NULL) { NdisAcquireSpinLock(&RndismpGlobalLock);
for (pAdapter = pDriverBlock->AdapterList; pAdapter != NULL; pAdapter = pAdapter->NextAdapter) { if (pAdapter->pDeviceObject == pDeviceObject) { break; } }
NdisReleaseSpinLock(&RndismpGlobalLock); }
*ppAdapter = pAdapter; *ppDriverBlock = pDriverBlock;
} // DeviceObjectToAdapter
/****************************************************************************/ /* AddDriverBlock */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Add driver block to list of drivers (microports) associated with this */ /* driver */ /* */ /* Arguments: */ /* */ /* Head - head of list */ /* Item - driver block to add to list */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID AddDriverBlock(IN PDRIVER_BLOCK Head, IN PDRIVER_BLOCK Item) { TRACE3(("AddDriverBlock\n"));
CHECK_VALID_BLOCK(Item);
// first time through, so allocate global spinlock
if(!RndismpNumMicroports) NdisAllocateSpinLock(&RndismpGlobalLock);
// grab the global spinlock
NdisAcquireSpinLock(&RndismpGlobalLock);
// Link the driver block on the global list of driver blocks
Item->NextDriverBlock = Head->NextDriverBlock; Head->NextDriverBlock = Item;
// keep track of how many microports we support so we can free
// global resources
RndismpNumMicroports++; // release global spinlock
NdisReleaseSpinLock(&RndismpGlobalLock);
} // AddDriverBlock
/****************************************************************************/ /* RemoveDriverBlock */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Remove driver block from list of drivers (microports) associated with */ /* this driver */ /* */ /* Arguments: */ /* */ /* Head - head of list */ /* Item - driver block to remove from list */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID RemoveDriverBlock(IN PDRIVER_BLOCK BlockHead, IN PDRIVER_BLOCK Item) { UINT NumMicroports;
PDRIVER_BLOCK Head = BlockHead;
TRACE1(("RemoveDriverBlock\n"));
CHECK_VALID_BLOCK(Item);
// grab the global spinlock
NdisAcquireSpinLock(&RndismpGlobalLock);
// Remove the driver block from the global list of driver blocks
while(Head->NextDriverBlock != Item) { Head = Head->NextDriverBlock;
// make sure this is valid
if(!Head) break; }
if(Head) Head->NextDriverBlock = Head->NextDriverBlock->NextDriverBlock;
// keep track of how many microports we support so we can free
// global resources
RndismpNumMicroports--;
NumMicroports = RndismpNumMicroports; // release global spinlock
NdisReleaseSpinLock(&RndismpGlobalLock);
// see if we need to free global spinlock
if(!RndismpNumMicroports) NdisFreeSpinLock(&RndismpGlobalLock);
ASSERT(Head);
} // RemoveDriverBlock
/****************************************************************************/ /* DeviceObjectToDriverBlock */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Get driver block pointer associated with the PDO passed in */ /* */ /* Arguments: */ /* */ /* Head - head of driver block list */ /* DeviceObject - device object we want to get associated driver block for */ /* */ /* Return: */ /* */ /* PDRIVER_BLOCK */ /* */ /****************************************************************************/ PDRIVER_BLOCK DeviceObjectToDriverBlock(IN PDRIVER_BLOCK Head, IN PDEVICE_OBJECT DeviceObject) { PDRIVER_OBJECT DriverObject;
TRACE3(("DeviceObjectToDriverBlock\n"));
// grab the global spinlock
NdisAcquireSpinLock(&RndismpGlobalLock);
// get the driver object for this adapter
DriverObject = DeviceObjectToDriverObject(DeviceObject);
Head = Head->NextDriverBlock;
// walk the list of driver blocks to find a match with driver object
while(Head->DriverObject != DriverObject) { Head = Head->NextDriverBlock;
// break out if we are at the end of the list
if(!Head) break; }
// release global spinlock
NdisReleaseSpinLock(&RndismpGlobalLock);
CHECK_VALID_BLOCK(Head);
return Head;
} // DeviceObjectToDriverBlock
/****************************************************************************/ /* DriverObjectToDriverBlock */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Get driver block pointer associated with the Driver Object passed in */ /* */ /* Arguments: */ /* */ /* Head - head of driver block list */ /* DriverObject - Driver object we want to get associated driver block for */ /* */ /* Return: */ /* */ /* PDRIVER_BLOCK */ /* */ /****************************************************************************/ PDRIVER_BLOCK DriverObjectToDriverBlock(IN PDRIVER_BLOCK Head, IN PDRIVER_OBJECT DriverObject) { TRACE3(("DriverObjectToDriverBlock\n"));
// grab the global spinlock
NdisAcquireSpinLock(&RndismpGlobalLock);
Head = Head->NextDriverBlock;
// walk the list of driver blocks to find a match with driver object
while(Head->DriverObject != DriverObject) { Head = Head->NextDriverBlock;
// break out if we are at the end of the list
if(!Head) break; }
// release global spinlock
NdisReleaseSpinLock(&RndismpGlobalLock);
CHECK_VALID_BLOCK(Head);
return Head;
} // DriverObjectToDriverBlock
/****************************************************************************/ /* AllocateMsgFrame */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Allocate a frame that holds context about a message we are about to */ /* send. */ /* */ /* Arguments: */ /* */ /* pAdapter - Adapter object */ /* */ /* Return: */ /* */ /* PRNDISMP_MESSAGE_FRAME */ /* */ /****************************************************************************/ PRNDISMP_MESSAGE_FRAME AllocateMsgFrame(IN PRNDISMP_ADAPTER pAdapter) { PRNDISMP_MESSAGE_FRAME pMsgFrame;
#ifndef DONT_USE_LOOKASIDE_LIST
pMsgFrame = (PRNDISMP_MESSAGE_FRAME) NdisAllocateFromNPagedLookasideList(&pAdapter->MsgFramePool);
#else
{ NDIS_STATUS Status; Status = MemAlloc(&pMsgFrame, sizeof(RNDISMP_MESSAGE_FRAME)); if (Status != NDIS_STATUS_SUCCESS) { pMsgFrame = NULL; } } #endif // DONT_USE_LOOKASIDE_LIST
if (pMsgFrame) { NdisZeroMemory(pMsgFrame, sizeof(*pMsgFrame)); pMsgFrame->pAdapter = pAdapter; pMsgFrame->RequestId = NdisInterlockedIncrement(&pAdapter->RequestId); pMsgFrame->Signature = FRAME_SIGNATURE;
pMsgFrame->RefCount = 1; NdisInterlockedIncrement(&MsgFrameAllocs); } #if DBG
else { TRACE1(("AllocateMsgFrame: pAdapter %x, MsgFramePool at %x, alloc failed, count %d\n", pAdapter, &pAdapter->MsgFramePool, MsgFrameAllocs)); DbgBreakPoint(); } #endif // DBG
return (pMsgFrame); }
/****************************************************************************/ /* DereferenceMsgFrame */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Free a message frame and any associated resources. */ /* */ /* Arguments: */ /* */ /* Frame - pointer to frame */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID DereferenceMsgFrame(IN PRNDISMP_MESSAGE_FRAME pMsgFrame) { PRNDISMP_ADAPTER pAdapter; PMDL pMdl; PUCHAR pMessage;
CHECK_VALID_FRAME(pMsgFrame);
if (NdisInterlockedDecrement(&pMsgFrame->RefCount) == 0) { //
// Mess up the contents slightly to catch bugs resulting from
// improper reuse of this frame after it is freed.
//
pMsgFrame->Signature++;
pMdl = pMsgFrame->pMessageMdl; pMsgFrame->pMessageMdl = NULL; if (pMdl) { pMessage = RNDISMP_GET_MDL_ADDRESS(pMdl); } else { pMessage = NULL; } if (pMessage) { MemFree(pMessage, -1); IoFreeMdl(pMdl); }
pAdapter = pMsgFrame->pAdapter;
#ifndef DONT_USE_LOOKASIDE_LIST
NdisFreeToNPagedLookasideList(&pAdapter->MsgFramePool, pMsgFrame); #else
MemFree(pMsgFrame, sizeof(RNDISMP_MESSAGE_FRAME)); #endif
NdisInterlockedDecrement(&MsgFrameAllocs); }
} // DereferenceMsgFrame
/****************************************************************************/ /* ReferenceMsgFrame */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Add a ref count to a message frame */ /* */ /* Arguments: */ /* */ /* Frame - pointer to frame */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID ReferenceMsgFrame(IN PRNDISMP_MESSAGE_FRAME pMsgFrame) { NdisInterlockedIncrement(&pMsgFrame->RefCount); }
/****************************************************************************/ /* KeepAliveTimerHandler */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Timer that keeps tabs on messages coming up from the device and */ /* sends a "KeepAlive" message if the device has been inactive too long */ /* */ /* Arguments: */ /* */ /* SystemSpecific1 - Don't care */ /* Context - pAdapter object */ /* SystemSpecific2 - Don't care */ /* SystemSpecific3 - Don't care */ /* */ /* Return: */ /* */ /* PNDIS_PACKET */ /* */ /****************************************************************************/ VOID KeepAliveTimerHandler(IN PVOID SystemSpecific1, IN PVOID Context, IN PVOID SystemSpecific2, IN PVOID SystemSpecific3) { PRNDISMP_ADAPTER pAdapter; PRNDISMP_MESSAGE_FRAME pMsgFrame; ULONG CurrentTime;
// get adapter context
pAdapter = PRNDISMP_ADAPTER_FROM_CONTEXT_HANDLE(Context);
TRACE2(("KeepAliveTimerHandler\n"));
do { // get current tick (in milliseconds)
NdisGetSystemUpTime(&CurrentTime);
// check and see if too much time has elapsed since we
// got the last message from the device
RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
if (((CurrentTime - pAdapter->LastMessageFromDevice) > KEEP_ALIVE_TIMER)) { // see if we have a keep alive message pending, so let's bong this
if (pAdapter->KeepAliveMessagePending) { TRACE1(("KeepAliveTimer: Adapter %p, message pending: last msg %d, cur %d\n", pAdapter, pAdapter->LastMessageFromDevice, CurrentTime));
// indicate later from check for hang handler
pAdapter->NeedReset = TRUE;
RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
RNDISMP_INCR_STAT(pAdapter, KeepAliveTimeout);
break; }
RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
// too much time has elapsed, send down a keep alive message
pMsgFrame = BuildRndisMessageCommon(pAdapter, NULL, REMOTE_NDIS_KEEPALIVE_MSG, 0, NULL, 0);
if (pMsgFrame) { RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
pAdapter->KeepAliveMessagePending = TRUE; pAdapter->KeepAliveMessagePendingId = pMsgFrame->RequestId;
RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter);
TRACE2(("Sending Keepalive(%d) on Adapter %p: last rcv %d, cur %d\n", pMsgFrame->RequestId, pAdapter, pAdapter->LastMessageFromDevice, CurrentTime ));
// send the message to the microport
RNDISMP_SEND_TO_MICROPORT(pAdapter, pMsgFrame, FALSE, CompleteSendKeepAlive); } } else { RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter); } } while (FALSE);
// see if the timer was cancelled somewhere
if (!pAdapter->TimerCancelled) { // restart timer
NdisSetTimer(&pAdapter->KeepAliveTimer, KEEP_ALIVE_TIMER / 2); } } // KeepAliveTimerHandler
/****************************************************************************/ /* CompleteSendKeepAlive */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Callback routine to handle completion of send by the microport, for */ /* a keepalive message. */ /* */ /* Arguments: */ /* */ /* pMsgFrame - Pointer to message frame describing the message */ /* SendStatus - Status returned by microport */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID CompleteSendKeepAlive(IN PRNDISMP_MESSAGE_FRAME pMsgFrame, IN NDIS_STATUS SendStatus) { PRNDISMP_ADAPTER pAdapter;
pAdapter = pMsgFrame->pAdapter;
DereferenceMsgFrame(pMsgFrame);
if (SendStatus != NDIS_STATUS_SUCCESS) { TRACE1(("KeepAlive send failure %x on Adapter %x\n", SendStatus, pAdapter));
RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
pAdapter->KeepAliveMessagePending = FALSE; pAdapter->NeedReset = FALSE;
RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter); }
} // CompleteSendKeepAlive
/****************************************************************************/ /* BuildRndisMessageCommon */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Allocate resources for meesage and frame and build RNDIS message */ /* */ /* Arguments: */ /* */ /* pAdapter - adapter object */ /* pVc - optionally, VC on which this message is sent. */ /* NdisMessageType - RNDIS message type */ /* Oid - the NDIS_OID to process. */ /* InformationBuffer - Holds the data to be set. */ /* InformationBufferLength - The length of InformationBuffer. */ /* */ /* Return: */ /* */ /* PRNDISMP_MESSAGE_FRAME */ /* */ /****************************************************************************/ PRNDISMP_MESSAGE_FRAME BuildRndisMessageCommon(IN PRNDISMP_ADAPTER pAdapter, IN PRNDISMP_VC pVc OPTIONAL, IN UINT NdisMessageType, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength) { PRNDIS_MESSAGE pMessage; UINT MessageSize; PRNDISMP_MESSAGE_FRAME pMsgFrame;
TRACE2(("BuildRndisMessageCommon\n"));
pMsgFrame = NULL;
switch(NdisMessageType) { case REMOTE_NDIS_INITIALIZE_MSG: { PRNDIS_INITIALIZE_REQUEST pInitRequest;
MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_INITIALIZE_REQUEST);
// get a message and request frame
pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
if (pMsgFrame == NULL) { break; }
pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame); pMessage->NdisMessageType = NdisMessageType; pMsgFrame->NdisMessageType = NdisMessageType; TRACE1(("RNDISMP: Init Req message %x, Type %d, Length %d, MaxRcv %d\n", pMessage, pMessage->NdisMessageType, pMessage->MessageLength, pAdapter->MaxReceiveSize));
pInitRequest = &pMessage->Message.InitializeRequest; pInitRequest->RequestId = pMsgFrame->RequestId; pInitRequest->MajorVersion = RNDIS_MAJOR_VERSION; pInitRequest->MinorVersion = RNDIS_MINOR_VERSION; pInitRequest->MaxTransferSize = pAdapter->MaxReceiveSize;
break; } case REMOTE_NDIS_HALT_MSG: { PRNDIS_HALT_REQUEST pHaltRequest;
MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_HALT_REQUEST);
// get a message and request frame
pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
if (pMsgFrame == NULL) { break; }
pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame); pMessage->NdisMessageType = NdisMessageType; pMsgFrame->NdisMessageType = NdisMessageType; pHaltRequest = &pMessage->Message.HaltRequest; pHaltRequest->RequestId = pMsgFrame->RequestId;
break; } case REMOTE_NDIS_QUERY_MSG: { PRNDIS_QUERY_REQUEST pQueryRequest;
MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_QUERY_REQUEST) + InformationBufferLength;
// get a message and request frame
pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
if (pMsgFrame == NULL) { break; }
pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame); pMessage->NdisMessageType = NdisMessageType; pMsgFrame->NdisMessageType = NdisMessageType;
pQueryRequest = &pMessage->Message.QueryRequest; pQueryRequest->RequestId = pMsgFrame->RequestId; pQueryRequest->Oid = Oid; pQueryRequest->InformationBufferLength = InformationBufferLength; pQueryRequest->InformationBufferOffset = sizeof(RNDIS_QUERY_REQUEST);
if (pVc == NULL) { pQueryRequest->DeviceVcHandle = NULL_DEVICE_CONTEXT; } else { pQueryRequest->DeviceVcHandle = pVc->DeviceVcContext; }
TRACE2(("Query OID %x, Len %d, RequestId %08X\n", Oid, InformationBufferLength, pQueryRequest->RequestId));
// copy information buffer
RNDISMP_MOVE_MEM(RNDISMP_GET_INFO_BUFFER_FROM_QUERY_MSG(pQueryRequest), InformationBuffer, InformationBufferLength); break; } case REMOTE_NDIS_SET_MSG: { PRNDIS_SET_REQUEST pSetRequest;
MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_SET_REQUEST) + InformationBufferLength;
// get a message and request frame
pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
if (pMsgFrame == NULL) { break; }
pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame); pMessage->NdisMessageType = NdisMessageType; pMsgFrame->NdisMessageType = NdisMessageType;
pSetRequest = &pMessage->Message.SetRequest; pSetRequest->RequestId = pMsgFrame->RequestId; pSetRequest->Oid = Oid; pSetRequest->InformationBufferLength = InformationBufferLength; pSetRequest->InformationBufferOffset = sizeof(RNDIS_SET_REQUEST);
if (pVc == NULL) { pSetRequest->DeviceVcHandle = NULL_DEVICE_CONTEXT; } else { pSetRequest->DeviceVcHandle = pVc->DeviceVcContext; }
// copy information buffer
RNDISMP_MOVE_MEM(RNDISMP_GET_INFO_BUFFER_FROM_QUERY_MSG(pSetRequest), InformationBuffer, InformationBufferLength); break; } case REMOTE_NDIS_RESET_MSG: { PRNDIS_RESET_REQUEST pResetRequest;
MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_RESET_REQUEST);
// get a message and request frame
pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
if (pMsgFrame == NULL) { break; }
pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame); pMessage->NdisMessageType = NdisMessageType; pMsgFrame->NdisMessageType = NdisMessageType;
pResetRequest = &pMessage->Message.ResetRequest; pResetRequest->Reserved = 0; break; } case REMOTE_NDIS_KEEPALIVE_MSG: { PRNDIS_KEEPALIVE_REQUEST pKeepAliveRequest;
MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_KEEPALIVE_REQUEST);
// get a message and request frame
pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
if (pMsgFrame == NULL) { break; }
pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame); pMessage->NdisMessageType = NdisMessageType; pMsgFrame->NdisMessageType = NdisMessageType;
pKeepAliveRequest = &pMessage->Message.KeepaliveRequest; pKeepAliveRequest->RequestId = pMsgFrame->RequestId; break; } case REMOTE_NDIS_KEEPALIVE_CMPLT: { PRNDIS_KEEPALIVE_COMPLETE pKeepAliveComplete;
MessageSize = RNDIS_MESSAGE_SIZE(RNDIS_KEEPALIVE_COMPLETE);
// get a message and request frame
pMsgFrame = AllocateMessageAndFrame(pAdapter, MessageSize);
if (pMsgFrame == NULL) { break; }
pMessage = RNDISMP_GET_MSG_FROM_FRAME(pMsgFrame); pMessage->NdisMessageType = NdisMessageType; pMsgFrame->NdisMessageType = NdisMessageType;
pKeepAliveComplete = &pMessage->Message.KeepaliveComplete; pKeepAliveComplete->RequestId = *(RNDIS_REQUEST_ID *)InformationBuffer; pKeepAliveComplete->Status = NDIS_STATUS_SUCCESS; break; }
default: TRACE2(("Invalid NdisMessageType (%08X)\n", NdisMessageType)); ASSERT(FALSE); break; }
return pMsgFrame; } // BuildRndisMessageCommon
/****************************************************************************/ /* AllocateMessageAndFrame */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Allocate a message and frame for an RNDIS message */ /* */ /* Arguments: */ /* */ /* pAdapter - pAdapter object */ /* MessageSize - size of RNDIS message */ /* */ /* Return: */ /* */ /* PRNDISMP_MESSAGE_FRAME */ /* */ /****************************************************************************/ PRNDISMP_MESSAGE_FRAME AllocateMessageAndFrame(IN PRNDISMP_ADAPTER pAdapter, IN UINT MessageSize) { PRNDIS_MESSAGE pMessage = NULL; PRNDISMP_MESSAGE_FRAME pMsgFrame = NULL; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; PMDL pMdl = NULL;
TRACE3(("AllocateMessageAndFrame\n"));
do { // allocate a buffer for RNDIS message
Status = MemAlloc(&pMessage, MessageSize);
// see if we got our buffer
if (Status != NDIS_STATUS_SUCCESS) { break; }
// allocate an MDL to describe this message.
pMdl = IoAllocateMdl( pMessage, MessageSize, FALSE, FALSE, NULL);
if (pMdl == NULL) { Status = NDIS_STATUS_RESOURCES; break; }
MmBuildMdlForNonPagedPool(pMdl);
// got the message buffer, now allocate a frame
pMsgFrame = AllocateMsgFrame(pAdapter);
if (pMsgFrame == NULL) { Status = NDIS_STATUS_RESOURCES; break; }
// got everything, so fill in some frame things
pMsgFrame->pMessageMdl = pMdl;
pMessage->MessageLength = MessageSize;
} while (FALSE);
if (Status != NDIS_STATUS_SUCCESS) { if (pMdl) { IoFreeMdl(pMdl); }
if (pMessage) { MemFree(pMessage, MessageSize); } }
return pMsgFrame;
} // AllocateMessageAndFrame
/****************************************************************************/ /* FreeAdapter */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Free all memory allocations to do with an Adapter structure */ /* */ /* Arguments: */ /* */ /* pAdapter - pointer to the adapter to be freed. */ /* */ /* Return: */ /* */ /* VOID */ /****************************************************************************/ VOID FreeAdapter(IN PRNDISMP_ADAPTER Adapter) { // free up transport resources
FreeTransportResources(Adapter);
if (Adapter->DriverOIDList) { MemFree(Adapter->DriverOIDList, RndismpSupportedOidsNum*sizeof(NDIS_OID)); }
if (Adapter->FriendlyNameAnsi.Buffer) { MemFree(Adapter->FriendlyNameAnsi.Buffer, Adapter->FriendlyNameAnsi.MaximumLength); }
if (Adapter->FriendlyNameUnicode.Buffer) { MemFree(Adapter->FriendlyNameUnicode.Buffer, Adapter->FriendlyNameUnicode.MaximumLength); }
#if DBG
if (Adapter->pSendLogBuffer) { MemFree(Adapter->pSendLogBuffer, Adapter->LogBufferSize); Adapter->pSendLogBuffer = NULL; } #endif // DBG
MemFree(Adapter, sizeof(RNDISMP_ADAPTER)); }
/****************************************************************************/ /* AllocateVc */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Allocate a VC structure */ /* */ /* Arguments: */ /* */ /* pAdapter - adapter object */ /* */ /* Return: */ /* */ /* PRNDISMP_VC */ /* */ /****************************************************************************/ PRNDISMP_VC AllocateVc(IN PRNDISMP_ADAPTER pAdapter) { PRNDISMP_VC pVc; NDIS_STATUS Status;
Status = MemAlloc(&pVc, sizeof(RNDISMP_VC)); if (Status == NDIS_STATUS_SUCCESS) { pVc->pAdapter = pAdapter; pVc->VcState = RNDISMP_VC_ALLOCATED; pVc->CallState = RNDISMP_CALL_IDLE; pVc->RefCount = 0; RNDISMP_INIT_LOCK(&pVc->Lock);
EnterVcIntoHashTable(pAdapter, pVc); } else { pVc = NULL; }
return pVc; }
/****************************************************************************/ /* DeallocateVc */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Deallocate a VC structure. */ /* */ /* Arguments: */ /* */ /* pVc - Pointer to VC being deallocated. */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID DeallocateVc(IN PRNDISMP_VC pVc) { ASSERT(pVc->RefCount == 0); ASSERT(pVc->VcState == RNDISMP_VC_ALLOCATED);
RemoveVcFromHashTable(pVc->pAdapter, pVc);
MemFree(pVc, sizeof(RNDISMP_VC)); } /****************************************************************************/ /* LookupVcId */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Search for a VC structure that matches a given VC Id. */ /* If we find the VC, we reference it and return it. */ /* */ /* Arguments: */ /* */ /* Adapter - adapter object */ /* VcId - Id to search for */ /* */ /* Notes: */ /* */ /* This routine is called with the adapter lock held! */ /* */ /* Return: */ /* */ /* PRNDISMP_VC - pointer to VC, if one exists */ /* */ /****************************************************************************/ PRNDISMP_VC LookupVcId(IN PRNDISMP_ADAPTER pAdapter, IN UINT32 VcId) { PLIST_ENTRY pVcEnt; PRNDISMP_VC pVc; ULONG VcIdHash; PRNDISMP_VC_HASH_TABLE pVcHashTable; BOOLEAN bFound = FALSE;
VcIdHash = RNDISMP_HASH_VCID(VcId);
pVcHashTable = pAdapter->pVcHashTable;
do { if (pVcHashTable == NULL) { pVc = NULL; break; }
for (pVcEnt = pVcHashTable->HashEntry[VcIdHash].Flink; pVcEnt != &pVcHashTable->HashEntry[VcIdHash]; pVcEnt = pVcEnt->Flink) { pVc = CONTAINING_RECORD(pVcEnt, RNDISMP_VC, VcList); if (pVc->VcId == VcId) { bFound = TRUE;
RNDISMP_REF_VC(pVc);
break; } }
if (!bFound) { pVc = NULL; } } while (FALSE);
return pVc; }
/****************************************************************************/ /* EnterVcIntoHashTable */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Link a VC into the hash table after assigning it a VC Id. */ /* */ /* Arguments: */ /* */ /* pAdapter - adapter object */ /* pVc - VC to link to the above adapter */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID EnterVcIntoHashTable(IN PRNDISMP_ADAPTER pAdapter, IN PRNDISMP_VC pVc) { PRNDISMP_VC pExistingVc; PRNDISMP_VC_HASH_TABLE pVcHashTable; UINT32 VcId; ULONG VcIdHash;
RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
//
// We pick the next sequentially higher Vc Id value for this VC,
// but check to see if it is already in use...
//
do { pAdapter->LastVcId++;
// Never allocate the value 0.
if (pAdapter->LastVcId == 0) { pAdapter->LastVcId++; }
VcId = pAdapter->LastVcId;
pExistingVc = LookupVcId(pAdapter, VcId); } while (pExistingVc != NULL);
pVcHashTable = pAdapter->pVcHashTable; pVc->VcId = VcId; VcIdHash = RNDISMP_HASH_VCID(VcId);
InsertTailList(&pVcHashTable->HashEntry[VcIdHash], &pVc->VcList); pVcHashTable->NumEntries++;
RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter); }
/****************************************************************************/ /* RemoveVcFromHashTable */ /****************************************************************************/ /* */ /* Routine Description: */ /* */ /* Unlink a VC from the adapter hash table. */ /* */ /* Arguments: */ /* */ /* pAdapter - adapter object */ /* pVc - VC to be unlinked. */ /* */ /* Return: */ /* */ /* VOID */ /* */ /****************************************************************************/ VOID RemoveVcFromHashTable(IN PRNDISMP_ADAPTER pAdapter, IN PRNDISMP_VC pVc) { RNDISMP_ACQUIRE_ADAPTER_LOCK(pAdapter);
RemoveEntryList(&pVc->VcList);
pAdapter->pVcHashTable->NumEntries--;
RNDISMP_RELEASE_ADAPTER_LOCK(pAdapter); }
|