📄 init.c
字号:
/*++
Copyright (c) Microsoft Corporation. All rights reserved.
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.
Module Name:
INIT.C
Abstract:
This module contains initialization helper routines called during
MiniportInitialize.
Author: Eliyas Yakub (Jan 11, 2003)
Revision History:
Notes:
--*/
#include "ndiswdm.h"
#pragma NDIS_PAGEABLE_FUNCTION(NICAllocAdapter)
#pragma NDIS_PAGEABLE_FUNCTION(NICFreeAdapter)
#pragma NDIS_PAGEABLE_FUNCTION(NICAllocSendResources)
#pragma NDIS_PAGEABLE_FUNCTION(NICFreeSendResources)
#pragma NDIS_PAGEABLE_FUNCTION(NICAllocRecvResources)
#pragma NDIS_PAGEABLE_FUNCTION(NICFreeRecvResources)
#pragma NDIS_PAGEABLE_FUNCTION(NICReadRegParameters)
#pragma NDIS_PAGEABLE_FUNCTION(NICInitializeAdapter)
#pragma NDIS_PAGEABLE_FUNCTION(NICInitWorkItemCallback)
#pragma NDIS_PAGEABLE_FUNCTION(NICInitAdapterWorker)
#ifdef INTERFACE_WITH_NDISPROT
#pragma NDIS_PAGEABLE_FUNCTION(NICOpenNdisProtocolInterface)
#endif
ULONG g_ulAddress = 0;
NDIS_STATUS
NICAllocAdapter(
PMP_ADAPTER *pAdapter)
/*++
Routine Description:
Allocates memory of our Adapter Context structure.
Arguments:
Adapter Pointer to our adapter
Should be called at IRQL = PASSIVE_LEVEL.
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_FAILURE
NDIS_STATUS_RESOURCES
--*/
{
PMP_ADAPTER Adapter = NULL;
NDIS_STATUS Status;
PAGED_CODE();
DEBUGP(MP_TRACE, ("--> NICAllocAdapter\n"));
*pAdapter = NULL;
do
{
//
// Allocate memory for adapter context
//
Status = NdisAllocateMemoryWithTag(
&Adapter,
sizeof(MP_ADAPTER),
NIC_TAG);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("Failed to allocate memory for adapter context\n"));
break;
}
//
// Zero the memory block
//
NdisZeroMemory(Adapter, sizeof(MP_ADAPTER));
//
// Lock to synchronize access to misc state variables used to track the
// overall state of the Adapter.
NdisAllocateSpinLock(&Adapter->Lock);
//
//
// List to link other instances of adapter.
//
NdisInitializeListHead(&Adapter->List);
//
// Event used to synchronize execution of NICInitAdapterWorker routine.
// We want to let only one thread execute this routine at any time.
//
KeInitializeEvent((PKEVENT)&Adapter->InitEvent, SynchronizationEvent, TRUE);
//
// This event is used to make sure all the asynchronously running routines
// such as DPCs, workitems, threads have exited before returning from halt
// handler.
//
NdisInitializeEvent(&Adapter->HaltEvent);
//
// Workitem used to post read requests.
//
NdisInitializeWorkItem(&Adapter->ReadWorkItem,
NICPostReadsWorkItemCallBack,
(PVOID)Adapter);
} while(FALSE);
*pAdapter = Adapter;
//
// In the failure case, the caller of this routine will end up
// calling NICFreeAdapter to free all the successfully allocated
// resources.
//
DEBUGP(MP_TRACE, ("<-- NICAllocAdapter\n"));
return(Status);
}
VOID
NICFreeAdapter(
PMP_ADAPTER Adapter)
/*++
Routine Description:
Frees memory of our Adapter Context structure.
Arguments:
Adapter Pointer to our adapter
Should be called at IRQL = PASSIVE_LEVEL.
Return Value:
VOID
--*/
{
DEBUGP(MP_TRACE, ("--> NICFreeAdapter\n"));
PAGED_CODE();
ASSERT(Adapter);
ASSERT(!Adapter->RefCount);
NdisFreeSpinLock(&Adapter->Lock);
//
// Finally free the memory for adapter context.
//
NdisFreeMemory(Adapter, sizeof(MP_ADAPTER), 0);
DEBUGP(MP_TRACE, ("<-- NICFreeAdapter\n"));
}
NDIS_STATUS
NICAllocSendResources(
PMP_ADAPTER Adapter)
/*++
Routine Description:
Allocate resources required to Send packets to the device
Arguments:
Adapter Pointer to our adapter
Should be called at IRQL = PASSIVE_LEVEL.
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_FAILURE
NDIS_STATUS_RESOURCES
--*/
{
NDIS_STATUS Status;
UINT index;
PNDIS_BUFFER Buffer = NULL;
PUCHAR pTCBMem = NULL;
DEBUGP(MP_TRACE, ("--> NICAllocSendResources\n"));
PAGED_CODE();
do
{
//
// Following are the lists to hold packets at different
// stages of processing.
// SendWaitList - Original send packets waiting to be processed
// SendFreeList - Packets available for send operation
// SendBusyList - Packets sent to the lower WDM stack
// SendLock is used to synchronize access to these lists.
//
NdisInitializeListHead(&Adapter->SendWaitList);
NdisInitializeListHead(&Adapter->SendFreeList);
NdisInitializeListHead(&Adapter->SendBusyList);
NdisAllocateSpinLock(&Adapter->SendLock);
//
// Let us set the flag to indicate resources are allocated.
// NICFreeSendResources will check this flag to determine whether there
// is any resource that needs to be freed.
//
MP_SET_FLAG(Adapter, fMP_SEND_SIDE_RESOURCE_ALLOCATED);
//
// Allocate a huge block of memory for all TCB's
//
Status = NdisAllocateMemoryWithTag(
&pTCBMem,
sizeof(TCB) * NIC_MAX_BUSY_SENDS,
NIC_TAG);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("Failed to allocate memory for TCB's\n"));
break;
}
NdisZeroMemory(pTCBMem, sizeof(TCB) * NIC_MAX_BUSY_SENDS);
Adapter->TCBMem = pTCBMem;
//
// Allocate a buffer pool for send buffers.
//
NdisAllocateBufferPool(
&Status,
&Adapter->SendBufferPoolHandle,
NIC_MAX_BUSY_SENDS);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("NdisAllocateBufferPool for send buffer failed\n"));
break;
}
//
// Divide the TCBMem blob into TCBs and create a buffer
// descriptor for the Data portion of the TCBs. The reason for doing
// this instead of using the OriginalSend Packet buffers is because
// the target driver we are talking to is not capable of handling
// chained buffers (MDLs).
//
for(index=0; index < NIC_MAX_BUSY_SENDS; index++)
{
PTCB pTCB = (PTCB) pTCBMem;
//
// Create a buffer descriptor for the Data portion of the TCBs.
// Buffer descriptors are nothing but MDLs on NT systems.
//
NdisAllocateBuffer(
&Status,
&Buffer,
Adapter->SendBufferPoolHandle,
(PVOID)&pTCB->Data[0],
NIC_BUFFER_SIZE);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("NdisAllocateBuffer failed\n"));
break;
}
//
// Initialize the TCB structure.
//
pTCB->Buffer = Buffer;
pTCB->pData = (PUCHAR) &pTCB->Data[0];
pTCB->Adapter = Adapter;
//
// Preallocate all the IRPs required. Do not charge quota
// to the current process for this IRP. If the miniport is
// loaded as a function driver of the WDM stack, say in case
// of USB, the TargetDeviceObject will be the NextDeviceObject.
//
ASSERT(Adapter->TargetDeviceObject);
if(!Adapter->TargetDeviceObject) {
Status = NDIS_STATUS_FAILURE;
break;
}
pTCB->Irp = IoAllocateIrp(Adapter->TargetDeviceObject->StackSize,
FALSE);
if (NULL == pTCB->Irp) {
Status = NDIS_STATUS_RESOURCES;
break;
}
pTCB->IrpLock = IRPLOCK_COMPLETED;
//
// Insert TCB blocks into FreeList.
//
NdisInterlockedInsertTailList(
&Adapter->SendFreeList,
&pTCB->List,
&Adapter->SendLock);
pTCBMem = pTCBMem + sizeof(TCB);
}
}while(FALSE);
DEBUGP(MP_TRACE, ("<-- NICAllocSendResources %x\n", Status));
return Status;
}
VOID
NICFreeSendResources(
PMP_ADAPTER Adapter)
/*++
Routine Description:
Free resources allocated for send operation
Arguments:
Adapter Pointer to our adapter
Should be called at IRQL = PASSIVE_LEVEL.
Return Value:
--*/
{
NDIS_STATUS Status;
PTCB pTCB;
DEBUGP(MP_TRACE, ("--> NICFreeSendResources\n"));
PAGED_CODE();
//
// Did we allocate any resources for send?
//
if(!MP_TEST_FLAG(Adapter, fMP_SEND_SIDE_RESOURCE_ALLOCATED)){
return;
}
while(!IsListEmpty(&Adapter->SendFreeList))
{
pTCB = (PTCB) NdisInterlockedRemoveHeadList(
&Adapter->SendFreeList,
&Adapter->SendLock);
if(!pTCB) {
break;
}
if(pTCB->Buffer) {
NdisFreeBuffer(pTCB->Buffer);
}
if(pTCB->Irp){
IoFreeIrp(pTCB->Irp);
}
}
if(Adapter->SendBufferPoolHandle)
{
NdisFreeBufferPool(Adapter->SendBufferPoolHandle);
Adapter->SendBufferPoolHandle = NULL;
}
if(Adapter->TCBMem) {
NdisFreeMemory(Adapter->TCBMem, sizeof(TCB) * NIC_MAX_BUSY_SENDS, 0);
Adapter->TCBMem = NULL;
}
ASSERT(IsListEmpty(&Adapter->SendFreeList));
ASSERT(IsListEmpty(&Adapter->SendWaitList));
NdisFreeSpinLock(&Adapter->SendLock);
MP_CLEAR_FLAG(Adapter, fMP_SEND_SIDE_RESOURCE_ALLOCATED);
}
NDIS_STATUS
NICAllocRecvResources(
PMP_ADAPTER Adapter)
/*++
Routine Description:
Allocate resources required to receive packets from the WDM driver
Arguments:
Adapter - Pointer to our adapter
Should be called at IRQL = PASSIVE_LEVEL.
Return Value:
NDIS_STATUS_SUCCESS
NDIS_STATUS_FAILURE
NDIS_STATUS_RESOURCES
--*/
{
PUCHAR pRCBMem = NULL;
PNDIS_PACKET Packet = NULL;
PNDIS_BUFFER Buffer = NULL;
UINT index;
NDIS_STATUS Status;
DEBUGP(MP_TRACE, ("--> NICAllocRecvResources\n"));
PAGED_CODE();
do{
//
// Following are the lists to hold packets at different
// stages of processing.
// RecvFreeList - Packets available for received operation
// RecvBusyList - Packets posted to the lower WDM stack
// RecvLock is used to synchronize access to these lists.
//
NdisInitializeListHead(&Adapter->RecvFreeList);
NdisInitializeListHead(&Adapter->RecvBusyList);
NdisAllocateSpinLock(&Adapter->RecvLock);
//
// Let us set the flag to indicate that resources are allocated.
// NICFreeRecvResources will check this flag to determine whether there
// is any resource that needs to be freed.
//
MP_SET_FLAG(Adapter, fMP_RECV_SIDE_RESOURCE_ALLOCATED);
//
// Allocate a huge block of memory for all RCB's
//
Status = NdisAllocateMemoryWithTag(
&pRCBMem,
sizeof(RCB) * NIC_MAX_BUSY_RECVS,
NIC_TAG);
if(Status != NDIS_STATUS_SUCCESS)
{
DEBUGP(MP_ERROR, ("Failed to allocate memory for RCB's\n"));
break;
}
NdisZeroMemory(pRCBMem, sizeof(RCB) * NIC_MAX_BUSY_RECVS);
Adapter->RCBMem = pRCBMem;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -