#include "precomp.h"
#pragma hdrstop
#define MAX_PACKET_POOL_SIZE 0x0000FFFF//最大64K
#define MIN_PACKET_POOL_SIZE 0x000000FF//最小256字节
//------------------------------------------------------------------------
VOID
PtBindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING DeviceName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2
)
{
NDIS_HANDLE ConfigHandle = NULL;
PNDIS_CONFIGURATION_PARAMETER Param;
NDIS_STRING DeviceStr = NDIS_STRING_CONST("UpperBindings");
PADAPT pAdapt = NULL;
NDIS_STATUS Sts;
UINT MediumIndex;
PNDIS_CONFIGURATION_PARAMETER BundleParam;
NDIS_STRING BundleStr = NDIS_STRING_CONST("BundleId");
NDIS_STATUS BundleStatus;
DBGPRINT("==> Passthru Protocol Initialize/n");
do
{
// Start off by opening the config section and reading our instance which we want
// to export for this binding
//获取中间层驱动程序存储与适配器相关信息的注册表键句柄
NdisOpenProtocolConfiguration(Status,
&ConfigHandle,//获得句柄
SystemSpecific1);
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
//读取获得的句柄下的信息
NdisReadConfiguration(Status,
&Param,
ConfigHandle,
&DeviceStr,
NdisParameterString);
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
//为Adapter structure分配内存,
//当微端口初始化后它表现为协议相关(protocol-context)和adapter structure两个方面。
NdisAllocateMemoryWithTag(&pAdapt, sizeof(ADAPT), TAG);
if (pAdapt == NULL)
{
*Status = NDIS_STATUS_RESOURCES;
break;
}
//零初始化ADAPT结构
NdisZeroMemory(pAdapt, sizeof(ADAPT));
//利用注册来存储字符串,将被用于从注册处读取数据
NdisAllocateMemoryWithTag( &(pAdapt->BundleUniString.Buffer), MAX_BUNDLEID_LENGTH ,TAG);
if (pAdapt->BundleUniString.Buffer == NULL)
{
*Status = NDIS_STATUS_RESOURCES;
break;
}
pAdapt->BundleUniString.MaximumLength = MAX_BUNDLEID_LENGTH ;
//读取键值信息
NdisReadConfiguration(&BundleStatus,
&BundleParam,
ConfigHandle,
&BundleStr,
NdisParameterString);
if (BundleStatus == NDIS_STATUS_SUCCESS)
{
//拷贝包描述符到自己的内存
ASSERT(pAdapt->BundleUniString.MaximumLength >= BundleParam->ParameterData.StringData.Length);
pAdapt->BundleUniString.Length = BundleParam->ParameterData.StringData.Length;
RtlCopyUnicodeString(&pAdapt->BundleUniString, &BundleParam->ParameterData.StringData);
}
else
{ // We do not have a bundle id entry in the registry. To play safe we will enter
// make the escape sequence the Bundle Id, This ensures that no bundle id's are
// spuriously formed
//我们没有一个包标志进入注册,为了显示安全,我们将包标志倒序,这确保了没有包标志被伪造
NDIS_STRING NoBundle = NDIS_STRING_CONST ("<no-bundle>");
RtlCopyUnicodeString(&pAdapt->BundleUniString, &NoBundle);
}
//初始化事件和自旋锁
NdisInitializeEvent(&pAdapt->Event);
KeInitializeSpinLock(&pAdapt->SpinLock);
// Allocate a packet pool for sends. We need this to pass sends down. We cannot use the same
// packet descriptor that came down to our send handler
//为发送分配数据包池。
//我们需要这个来向下传递发送数据。我们不能使用到达我们的发送函数的同样的包描述符。
NdisAllocatePacketPoolEx(Status,
&pAdapt->SendPacketPoolHandle,
MIN_PACKET_POOL_SIZE,
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
sizeof(RSVD));
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
//为接收开辟数据包池,我们需要这样指示接收
NdisAllocatePacketPoolEx(Status,
&pAdapt->RecvPacketPoolHandle,
MIN_PACKET_POOL_SIZE,
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
sizeof(RSVD));
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
//调用NdisOpenAdapter进行绑定
NdisOpenAdapter(Status,
&Sts,
&pAdapt->BindingHandle,
&MediumIndex,
MediumArray,
sizeof(MediumArray)/sizeof(NDIS_MEDIUM),
ProtHandle,
pAdapt,
DeviceName,
0,
NULL);
if(*Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
*Status = pAdapt->Status;
}
if(*Status != NDIS_STATUS_SUCCESS)
{
break;
}
pAdapt->Medium = MediumArray[MediumIndex];
//微端口初始化(可初始化多个)
NdisIMInitializeDeviceInstanceEx(DriverHandle,
&Param->ParameterData.StringData,
pAdapt);
} while(FALSE);
if (ConfigHandle != NULL)
{ //关闭表键
NdisCloseConfiguration(ConfigHandle);
}
//如果分配资源失败,则释放分配的资源
if (*Status != NDIS_STATUS_SUCCESS)
{
if (pAdapt != NULL)
{
if (pAdapt->SendPacketPoolHandle != NULL)
{
NdisFreePacketPool(pAdapt->SendPacketPoolHandle);
}
if (pAdapt->RecvPacketPoolHandle != NULL)
{
NdisFreePacketPool(pAdapt->RecvPacketPoolHandle);
}
NdisFreeMemory(pAdapt, sizeof(ADAPT), 0);
}
}
DBGPRINT("<== Passthru Protocol Initialize/n");
}
//----------------------------------------------------------------------
VOID
PtOpenAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
DBGPRINT("==> Passthru PtOpenAdapterComplete/n");
pAdapt->Status = Status;
NdisSetEvent(&pAdapt->Event);
}
//------------------------------------------------------------------------------
VOID
PtUnbindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE UnbindContext
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
NDIS_HANDLE BindingHandle = pAdapt->BindingHandle;
DBGPRINT("==> Passthru PtUnbindAdapter/n");
if (pAdapt->QueuedRequest == TRUE)
{
pAdapt->QueuedRequest = FALSE;
PtRequestComplete (pAdapt,
&pAdapt->Request,
NDIS_STATUS_FAILURE );
}
//调用NDIS卸载驱动设备实例,我们在HaltHandler中实现大部分功能。
//如果passthru的小端口的Halt Handler被调用,或IM设备从未被初始化,这个句柄将为空。
if(pAdapt->MiniportHandle != NULL)
{
*Status = NdisIMDeInitializeDeviceInstance(pAdapt->MiniportHandle);
if(*Status != NDIS_STATUS_SUCCESS)
{
*Status = NDIS_STATUS_FAILURE;
}
}
else
{
// We need to do some work here.
//关闭对下层绑定并且释放分配的内存
if(pAdapt->BindingHandle != NULL)
{
NdisResetEvent(&pAdapt->Event);
NdisCloseAdapter(Status, pAdapt->BindingHandle);
//等待关闭完成
if(*Status == NDIS_STATUS_PENDING)
{
NdisWaitEvent(&pAdapt->Event, 0);
*Status = pAdapt->Status;
}
}
else
{
//MiniportHandle和Binding Handle均不能为空
*Status = NDIS_STATUS_FAILURE;
ASSERT(0);
}
//此处释放早期调用HaltHandler时未能释放的内存
NdisFreeMemory(pAdapt, sizeof(ADAPT), 0);
}
DBGPRINT("<==Passthru UnbindAdapter/n");
}
//----------------------------------------------------------------------------
VOID
PtUnload(
IN PDRIVER_OBJECT DriverObject
)
{
NDIS_STATUS Status;
//释放注册时分配的空间
NdisDeregisterProtocol(&Status, ProtHandle);
}
//----------------------------------------------------------------------------
VOID
PtCloseAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
pAdapt->Status = Status;
NdisSetEvent(&pAdapt->Event);
}
VOID
PtResetComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
//我们这个程序不产生复位,所以不到达这里
ASSERT(0);
}
VOID
PtRequestComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_REQUEST NdisRequest,
IN NDIS_STATUS Status
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
NDIS_OID Oid = pAdapt->Request.DATA.SET_INFORMATION.Oid ;
//
// Change to the pAdapt for which the request originated
//转换到最初请求的pAdapt
if(MPIsSendOID(Oid))
{
pAdapt = pAdapt->pPrimaryAdapt;
//如果没有捆绑则指向它自己(参看初始化)
}
// Since our request is not outstanding anymore
//以后我们的请求不再突出(传递)
pAdapt->OutstandingRequests = FALSE;
//
// Complete the Set or Query, and fill in the buffer for OID_PNP_CAPABILITIES, if need be.
//完成Set或者Query,如果需要则填充OID_PNP_CAPABILITIES的缓冲区
switch(NdisRequest->RequestType)
{
case NdisRequestQueryInformation:
//这将不会被传递到下面的微端口
ASSERT(Oid != OID_PNP_QUERY_POWER);
// 如果oid == OID_PNP_CAPABILITIES并且查询成功,则用请求的值填充缓冲区。
if(Oid == OID_PNP_CAPABILITIES && Status == NDIS_STATUS_SUCCESS)
{
MPQueryPNPCapbilities(pAdapt,&Status);
}
*pAdapt->BytesReadOrWritten = NdisRequest->DATA.QUERY_INFORMATION.BytesWritten;
*pAdapt->BytesNeeded = NdisRequest->DATA.QUERY_INFORMATION.BytesNeeded;
NdisMQueryInformationComplete(pAdapt->MiniportHandle,
Status);
break;
case NdisRequestSetInformation:
ASSERT( Oid != OID_PNP_SET_POWER);
*pAdapt->BytesReadOrWritten = NdisRequest->DATA.SET_INFORMATION.BytesRead;
*pAdapt->BytesNeeded = NdisRequest->DATA.SET_INFORMATION.BytesNeeded;
NdisMSetInformationComplete(pAdapt->MiniportHandle,
Status);
break;
default:
ASSERT(0);
break;
}
}
//--------------------------------------------------------------------------------
VOID
PtStatus(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS GeneralStatus,
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
//如果我们在微端口被初始化前得到一个状态指示,忽略它
//如果SampleIM没有打开,我们不传递状态指示
if(pAdapt->MiniportHandle != NULL &&
pAdapt->MPDeviceState == NdisDeviceStateD0 &&
pAdapt->PTDeviceState == NdisDeviceStateD0 )
{
NdisMIndicateStatus(pAdapt->MiniportHandle,
GeneralStatus,
StatusBuffer,
StatusBufferSize);
}
}
//----------------------------------------------------------------------------------
VOID
PtStatusComplete(
IN NDIS_HANDLE ProtocolBindingContext
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
//如果我们在微端口被初始化前得到一个状态指示,忽略。
if(pAdapt->MiniportHandle != NULL &&
pAdapt->MPDeviceState == NdisDeviceStateD0 &&
pAdapt->PTDeviceState == NdisDeviceStateD0 )
{
NdisMIndicateStatusComplete(pAdapt->MiniportHandle);
}
}
VOID
PtSendComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET Pkt;
PRSVD Rsvd;
//
// Returning the Send on the Primary, will point to itself if there is no bundle
//返回在主程序中的发送,如果没有绑定则指向它自己
pAdapt = pAdapt->pPrimaryAdapt;
Rsvd =(PRSVD)(Packet->ProtocolReserved);
Pkt = Rsvd->OriginalPkt;
NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);
NdisDprFreePacket(Packet);
NdisMSendComplete(pAdapt->MiniportHandle,
Pkt,
Status);
}
VOID
PtTransferDataComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status,
IN UINT BytesTransferred
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
// Returning the Send on the Primary, will point to itself if there is no LBFO
//返回在主程序中的发送,如果没有LBFO将指向它自己。
pAdapt = pAdapt->pPrimaryAdapt;
if(pAdapt->MiniportHandle)
{
NdisMTransferDataComplete(pAdapt->MiniportHandle,
Packet,
Status,
BytesTransferred);
}
}
//---------------------------------------------------------------------------------
NDIS_STATUS
PtReceive(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookAheadBuffer,
IN UINT LookAheadBufferSize,
IN UINT PacketSize
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
PNDIS_PACKET MyPacket, Packet;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
if(!pAdapt->MiniportHandle)
{
Status = NDIS_STATUS_FAILURE;
}
else do
{
//
// We should not be getting Receives on a Secondary, this is just specific to our LBFO driver
//
if(pAdapt->isSecondary)
{
DBGPRINT("PASSTHRU GETTING RECIEVES ON SECONDARY/n");
ASSERT(0);
}
//
// If this was indicated by the miniport below as a packet, then get that packet pointer and indicate
// it as a packet as well(with appropriate status). This way the OOB stuff is accessible to the
// transport above us.
//
Packet = NdisGetReceivedPacket(pAdapt->BindingHandle, MacReceiveContext);
if(Packet != NULL)
{
//
// Get a packet off the pool and indicate that up
//
NdisDprAllocatePacket(&Status,
&MyPacket,
pAdapt->RecvPacketPoolHandle);
if(Status == NDIS_STATUS_SUCCESS)
{
MyPacket->Private.Head = Packet->Private.Head;
MyPacket->Private.Tail = Packet->Private.Tail;
//
// Get the original packet(it could be the same packet as one received or a different one
// based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible
// correctly at the top.
//
NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, HeaderBufferSize);
//
// Set Packet Flags
//
NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
//
// Make sure the status is set to NDIS_STATUS_RESOURCES.
//
NDIS_SET_PACKET_STATUS(MyPacket, NDIS_STATUS_RESOURCES);
NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);
ASSERT(NDIS_GET_PACKET_STATUS(MyPacket) == NDIS_STATUS_RESOURCES);
NdisDprFreePacket(MyPacket);
break;
}
}
//
// Fall through if the miniport below us has either not indicated a packet or we could not
// allocate one
//
pAdapt->IndicateRcvComplete = TRUE;
switch(pAdapt->Medium)
{
case NdisMedium802_3:
NdisMEthIndicateReceive(pAdapt->MiniportHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
break;
case NdisMedium802_5:
NdisMTrIndicateReceive(pAdapt->MiniportHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
break;
case NdisMediumFddi:
NdisMFddiIndicateReceive(pAdapt->MiniportHandle,
MacReceiveContext,
HeaderBuffer,
HeaderBufferSize,
LookAheadBuffer,
LookAheadBufferSize,
PacketSize);
break;
default:
ASSERT(0);
break;
}
} while(FALSE);
return Status;
}
//----------------------------------------------------------------------------
VOID
PtReceiveComplete(
IN NDIS_HANDLE ProtocolBindingContext
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
//
// We should not be getting Receives on a Secondary, this is just specific to our LBFO driver
//
if(pAdapt->isSecondary)
{
DBGPRINT("PASSTHRU GETTING RECEIVES ON SECONDARY/n");
ASSERT(0);
}
if((pAdapt->MiniportHandle != NULL) && pAdapt->IndicateRcvComplete)
{
switch(pAdapt->Medium)
{
case NdisMedium802_3:
NdisMEthIndicateReceiveComplete(pAdapt->MiniportHandle);
break;
case NdisMedium802_5:
NdisMTrIndicateReceiveComplete(pAdapt->MiniportHandle);
break;
case NdisMediumFddi:
NdisMFddiIndicateReceiveComplete(pAdapt->MiniportHandle);
break;
default:
ASSERT(0);
break;
}
}
pAdapt->IndicateRcvComplete = FALSE;
}
//-------------------------------------------------------------------------------------
INT
PtReceivePacket(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
NDIS_STATUS Status;
PNDIS_PACKET MyPacket;
PRSVD Resvd;
if(!pAdapt->MiniportHandle)
{
return 0;
}
//
// We should not be getting Receives on a Secondary, this is just specific to our LBFO driver
//
if(pAdapt->isSecondary)
{
DBGPRINT("PASSTHRU GETTING RECEIVES ON SECONDARY/n");
ASSERT(0);
}
//
// Get a packet off the pool and indicate that up
//
NdisDprAllocatePacket(&Status,
&MyPacket,
pAdapt->RecvPacketPoolHandle);
if(Status == NDIS_STATUS_SUCCESS)
{
Resvd =(PRSVD)(MyPacket->MiniportReserved);
Resvd->OriginalPkt = Packet;
MyPacket->Private.Head = Packet->Private.Head;
MyPacket->Private.Tail = Packet->Private.Tail;
//
// Get the original packet(it could be the same packet as one received or a different one
// based on # of layered MPs) and set it on the indicated packet so the OOB stuff is visible
// correctly at the top.
//
NDIS_SET_ORIGINAL_PACKET(MyPacket, NDIS_GET_ORIGINAL_PACKET(Packet));
//
// Set Packet Flags
//
NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet);
Status = NDIS_GET_PACKET_STATUS(Packet);
NDIS_SET_PACKET_STATUS(MyPacket, Status);
NDIS_SET_PACKET_HEADER_SIZE(MyPacket, NDIS_GET_PACKET_HEADER_SIZE(Packet));
NdisMIndicateReceivePacket(pAdapt->MiniportHandle, &MyPacket, 1);
if(Status == NDIS_STATUS_RESOURCES)
{
NdisDprFreePacket(MyPacket);
}
return((Status != NDIS_STATUS_RESOURCES) ? 1 : 0);
}
else
{
//
// We are out of packets. Silently drop it. Alternatively we can deal with it:
// - By keeping separate send and receive pools
// - Dynamically allocate more pools as needed and free them when not needed
//
return(0);
}
}
//--------------------------------------------------------------------------------------
NDIS_STATUS
PtPNPHandler(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNET_PNP_EVENT pNetPnPEvent
)
{
PADAPT pAdapt =(PADAPT)ProtocolBindingContext;
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
DBGPRINT ("PtPnPHandler");
//
// This will happen when all entities in the system need to be notified
//
switch(pNetPnPEvent->NetEvent)
{
case NetEventSetPower :
Status = PtPnPNetEventSetPower(pAdapt, pNetPnPEvent);
break;
case NetEventReconfigure :
Status = PtPnPNetEventReconfigure(pAdapt, (PCWSTR)pNetPnPEvent->Buffer);
break;
default :
Status = NDIS_STATUS_SUCCESS;
break;
}
return Status;
}
//----------------------------------------------------------------------------------
NDIS_STATUS
PtPnPNetEventReconfigure(
IN PADAPT pAdapt,
IN PCWSTR pBundleString
)
{
NDIS_STATUS BundleStatus = NDIS_STATUS_SUCCESS;
NDIS_STRING NewBundleUniString;
if(pAdapt == NULL)
{
NdisReEnumerateProtocolBindings (ProtHandle);
return BundleStatus;
}
if (pBundleString == NULL)
{
return BundleStatus;
}
NdisInitUnicodeString( &NewBundleUniString, pBundleString);
do
{
//
// If the bundle Identifier was not changed, do not do anything
//
if(NdisEqualUnicodeString(&NewBundleUniString, &pAdapt->BundleUniString, TRUE))
{
break;
}
//
// We have a new bundle id , copy it and do the necessary bundling work
//
RtlCopyUnicodeString(&pAdapt->BundleUniString , &NewBundleUniString);
//
// If we are part of a bundle and our bundle id was changed, either the primary or the secondary
// will get promoted
// If we are the secondary of a bundle promote ourselves
//
if(pAdapt->isSecondary)
{
PADAPT pPrimaryAdapt = pAdapt->pPrimaryAdapt;
BundleStatus = MPPromoteSecondary(pAdapt);
if(BundleStatus != NDIS_STATUS_SUCCESS)
{
ASSERT(0);
break;
}
//
// resetting all the internal variables of the primary Adapter structure
//
pPrimaryAdapt->pPrimaryAdapt = pPrimaryAdapt;
pPrimaryAdapt->pSecondaryAdapt = pPrimaryAdapt;
pPrimaryAdapt->isSecondary = FALSE;
}
else
{
if(pAdapt->pSecondaryAdapt != pAdapt)
{
BundleStatus = MPPromoteSecondary(pAdapt->pSecondaryAdapt);
if(BundleStatus != NDIS_STATUS_SUCCESS)
{
ASSERT(0);
break;
}
//
// resetting all our internal variables
//
pAdapt->pSecondaryAdapt = pAdapt;
pAdapt->pPrimaryAdapt = pAdapt;
pAdapt->isSecondary = FALSE ;
}
}
BundleStatus = MPBundleSearchAndSetSecondary(pAdapt);
} while(FALSE) ;
DBGPRINT("<==PtPNPNetEventReconfigure/n");
return BundleStatus;
}
//--------------------------------------------------------------------------------------
NDIS_STATUS
PtPnPNetEventSetPower(
IN PADAPT pAdapt,
IN PNET_PNP_EVENT pNetPnPEvent
)
{
PNDIS_DEVICE_POWER_STATE pDeviceState =(PNDIS_DEVICE_POWER_STATE)(pNetPnPEvent->Buffer);
NDIS_DEVICE_POWER_STATE PrevDeviceState = pAdapt->PTDeviceState;
NDIS_STATUS Status ;
//设置内部设备状态,这个支撑所有新的发送或接收。
pAdapt->PTDeviceState = *pDeviceState;
//如果正在被送到standby(if we are being sent to standby),阻塞正在处理的请求和发送
if(*pDeviceState > NdisDeviceStateD0)
{
//如果物理微端口将要备用(standby),所有到来的请求无效。
if (PrevDeviceState == NdisDeviceStateD0)
{
pAdapt->StandingBy = TRUE;
}
while(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) != 0)
{
//等待到正在处理的发送完成。
NdisMSleep(10);
}
while(pAdapt->OutstandingRequests == TRUE)
{
//等待到正在处理的请求完成。
NdisMSleep(10);
}
ASSERT(NdisPacketPoolUsage(pAdapt->SendPacketPoolHandle) == 0);
ASSERT(pAdapt->OutstandingRequests == FALSE);
}
else
{
//协议被打开,一个待处理请求必须结束
if (pAdapt->QueuedRequest == TRUE)
{
pAdapt->QueuedRequest = FALSE;
NdisRequest(&Status,
pAdapt->BindingHandle,
&pAdapt->Request);
//下面的微端口同步地完成同步请求,IM需要完成它早期未决的请求。
if (Status != NDIS_STATUS_PENDING)
{
PtRequestComplete(pAdapt,
&pAdapt->Request,
Status);
}
}
//如果物理微端口功率正在增大(is powering up)(从低功率到D0),清空标志
if (PrevDeviceState > NdisDeviceStateD0)
{
pAdapt->StandingBy = FALSE;
}
}
Status = NDIS_STATUS_SUCCESS;
return Status;
}