📄 adapter.c
字号:
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
adapter.c
Abstract:
routines for binding/unbinding to/from underlying miniport drivers
Author:
Jim Mateer 4-1-97
Environment:
Kernel Mode
Revision History:
--*/
#include "ImSamp.h"
#pragma hdrstop
PADAPTER CurrentAdapter;
VOID
BindToLowerMP(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING MPDeviceName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2
);
STATIC NDIS_STATUS
GetAdapterRegistryData(
PNDIS_STRING IMParamsKey,
PADAPTER Adapter
);
STATIC VOID
ProcessLowerMPOpenAdapter(
IN PADAPTER Adapter,
IN NDIS_STATUS Status
);
VOID
LowerMPOpenAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
);
STATIC NDIS_STATUS
AllocatePacketPool(
PADAPTER Adapter
);
STATIC NDIS_STATUS
AllocateReceiveBufferPools(
PADAPTER Adapter
);
//NDIS_STATUS
//AddPipeToPSA(
// PADAPTER Adapter
// );
PADAPTER
FindAdapterByInstanceNumber(
#if BINARY_COMPATIBLE
CHAR InstanceNumber
#else
WCHAR InstanceNumber
#endif
);
PADAPTER
FindAdapterByName(
PWCHAR AdapterName
);
NDIS_STATUS
MPInitialize(
OUT PNDIS_STATUS OpenErrorStatus,
OUT PUINT SelectedMediumIndex,
IN PNDIS_MEDIUM MediumArray,
IN UINT MediumArraySize,
IN NDIS_HANDLE MiniportAdapterHandle,
IN NDIS_HANDLE WrapperConfigurationContext
);
VOID
UnbindFromLowerMP(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE UnbindContext
);
VOID
DerefAdapter(
PADAPTER Adapter
);
VOID
CleanupAdapter(
PADAPTER Adapter
);
VOID
LowerMPCloseAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
);
VOID
CLUnloadProtocol(
VOID
);
VOID
MPHalt(
IN NDIS_HANDLE MiniportAdapterContext
);
NDIS_STATUS
MPReset(
OUT PBOOLEAN AddressingReset,
IN NDIS_HANDLE MiniportAdapterContext
);
#if DBG
VOID
DumpAdapter(
PADAPTER Adapter
);
#endif
#pragma NDIS_PAGEABLE_FUNCTION(BindToLowerMP)
#pragma NDIS_PAGEABLE_FUNCTION(GetAdapterRegistryData)
VOID
BindToLowerMP(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING MPDeviceName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2
)
/*++
Routine Description:
Bind to the underlying MP. Allocate space for an adapter structure,
initializing its fields. Try to open the adapter indicated in MPDeviceName.
Arguments:
See the DDK...
Return Values:
None
--*/
{
PADAPTER Adapter;
NDIS_STATUS OpenAdapterStatus;
NDIS_STATUS OpenErrorStatus;
NDIS_STATUS LocalStatus;
NDIS_MEDIUM MediumArray[] = {
NdisMediumFddi,
NdisMedium802_5,
NdisMedium802_3
};
UINT MediumArraySize = sizeof( MediumArray ) / sizeof( NDIS_MEDIUM );
UINT MediaIndex;
ULONG AdapterStructSize;
PAGED_CODE();
#if BINARY_COMPATIBLE
ImDbgOut( DBG_INFO, DBG_PROTOCOL | DBG_INIT, ("BindToLowerMP: %s\n", MPDeviceName->Buffer ));
#else
ImDbgOut( DBG_INFO, DBG_PROTOCOL | DBG_INIT, ("BindToLowerMP: %ws\n", MPDeviceName->Buffer ));
#endif
//
// allocate enough space for the structure and two unicode buffers to hold
// the IM and underlying MP device names. We add an extra Unicode char to
// to the IM device name to hold the instance char that is be appended later
// on and another unicode char to separate the two strings for reading
//
AdapterStructSize = sizeof( ADAPTER ) + IMMPName.Length + MPDeviceName->Length +
2 * sizeof( UNICODE_NULL );
IMAllocatePool( Adapter, AdapterStructSize, Adapter );
if ( Adapter == NULL ) {
PWCHAR StringData[2];
StringData[0] = IMDriverName.Buffer;
StringData[1] = L"Adapter";
NdisWriteErrorLogEntry(IMDriverObject,
(ULONG)EVENT_TRANSPORT_RESOURCE_POOL,
0,
2,
&StringData,
0,
NULL);
*Status = NDIS_STATUS_RESOURCES;
return;
}
//
// set our state to initializing
//
Adapter->IMMPState = ADAPTER_STATE_INITIALIZING;
//
// make the device name point to the buffer allocated at the back of the
// structure.
//
Adapter->IMDeviceName.MaximumLength = IMMPName.Length + sizeof( UNICODE_NULL );
Adapter->IMDeviceName.Length = Adapter->IMDeviceName.MaximumLength;
Adapter->IMDeviceName.Buffer = (PWSTR)( Adapter + 1 );
Adapter->MPDeviceName.MaximumLength = MPDeviceName->Length;
Adapter->MPDeviceName.Length = Adapter->MPDeviceName.MaximumLength;
Adapter->MPDeviceName.Buffer = (PWSTR)((PCHAR)Adapter->IMDeviceName.Buffer +
Adapter->IMDeviceName.MaximumLength +
sizeof( UNICODE_NULL ));
NdisMoveMemory( Adapter->MPDeviceName.Buffer, MPDeviceName->Buffer, MPDeviceName->Length );
LocalStatus = GetAdapterRegistryData( (PNDIS_STRING)SystemSpecific1, Adapter );
if ( !NT_SUCCESS( LocalStatus )) {
#if BINARY_COMPATIBLE
ImDbgOut(DBG_FAILURE, DBG_PROTOCOL | DBG_INIT,
("(%08X) BindToLowerMP: Couldn't get registry data %08X (%s)\n",
Adapter, LocalStatus, MPDeviceName->Buffer ));
#else
ImDbgOut(DBG_FAILURE, DBG_PROTOCOL | DBG_INIT,
("(%08X) BindToLowerMP: Couldn't get registry data %08X (%ws)\n",
Adapter, LocalStatus, MPDeviceName->Buffer ));
#endif
*Status = NDIS_STATUS_FAILURE;
IMFreePool( Adapter );
return;
}
//
// init the event now since we use it in the completion handler
//
// remember our binding context so we can complete BindAdapter later on
//
NdisInitializeEvent( &Adapter->BlockingEvent );
Adapter->BindContext = BindContext;
// Open the adapter below us.
NdisOpenAdapter(&OpenAdapterStatus,
&OpenErrorStatus,
&Adapter->LowerMPHandle,
&MediaIndex,
MediumArray,
MediumArraySize,
ClientProtocolHandle,
Adapter,
MPDeviceName,
0,
NULL);
//
// Memphis doesn't like you to do NdisRequests from within the OpenAdapterComplete
// handler so wait for OpenAdapterComplete to finish and then do the follow up
// processing.
//
if ( OpenAdapterStatus == NDIS_STATUS_PENDING ) {
NdisWaitEvent( &Adapter->BlockingEvent, 0 );
NdisResetEvent( &Adapter->BlockingEvent );
} else {
Adapter->FinalStatus = OpenAdapterStatus;
}
if ( NT_SUCCESS( Adapter->FinalStatus )) {
Adapter->MediaType = MediumArray[ MediaIndex ];
}
ProcessLowerMPOpenAdapter( Adapter, Adapter->FinalStatus );
*Status = Adapter->FinalStatus;
} // BindToLowerMP
STATIC NDIS_STATUS
GetAdapterRegistryData(
PNDIS_STRING IMParamsKey,
PADAPTER Adapter
)
/*++
Routine Description:
Obtain the IMSamp specific info associated with the underlying MP
Arguments:
IMParamsKey - location in the registry
Adapter - pointer to adapter context struct
Return Value:
NDIS_STATUS_SUCCESS if everything worked ok
--*/
{
NDIS_STATUS Status;
NDIS_HANDLE ConfigHandle;
NDIS_STRING IMInstanceNumberKey = NDIS_STRING_CONST( "InstanceNumber" );
PNDIS_CONFIGURATION_PARAMETER ConfigParam;
ULONG i;
PWCHAR StringData[2];
PVOID DumpData;
PAGED_CODE();
NdisOpenProtocolConfiguration( &Status, &ConfigHandle, IMParamsKey );
if ( !NT_SUCCESS( Status )) {
#if BINARY_COMPATIBLE
ImDbgOut(DBG_FAILURE, DBG_PROTOCOL | DBG_INIT,
( "(%08X) GetAdapterRegistryData: can't open key %s (%08X)\n",
Adapter, IMParamsKey->Buffer, Status ));
#else
ImDbgOut(DBG_FAILURE, DBG_PROTOCOL | DBG_INIT,
( "(%08X) GetAdapterRegistryData: can't open key %ws (%08X)\n",
Adapter, IMParamsKey->Buffer, Status ));
#endif
return Status;
}
//
// get the IM device instance number and build the device instance string
//
NdisReadConfiguration(&Status,
&ConfigParam,
ConfigHandle,
&IMInstanceNumberKey,
NdisParameterInteger);
if ( !NT_SUCCESS( Status )) {
ImDbgOut(DBG_FAILURE, DBG_PROTOCOL | DBG_INIT,
("(%08X) GetAdapterRegistryData: Missing InstanceNumber key\n", Adapter));
Status = NDIS_STATUS_FAILURE;
goto CloseConfig;
}
Adapter->DevInstance = (USHORT)ConfigParam->ParameterData.IntegerData;
NdisMoveMemory( Adapter->IMDeviceName.Buffer, IMMPName.Buffer, IMMPName.Length );
Adapter->IMDeviceName.Buffer[ IMMPName.Length / sizeof( WCHAR ) ] = L'0' + Adapter->DevInstance;
CloseConfig:
NdisCloseConfiguration( ConfigHandle );
return Status;
} // GetAdapterRegistryData
STATIC VOID
ProcessLowerMPOpenAdapter(
IN PADAPTER Adapter,
IN NDIS_STATUS Status
)
/*++
Routine Description:
Complete the binding on the lower miniport. Initialize the adapter structure, query
the MP for certain funtionality and initialize the associated IM miniport device
Arguments:
see the DDK
Return Values:
None
--*/
{
NTSTATUS EventStatus;
PWSTR SecondaryName;
NDIS_HARDWARE_STATUS HWStatus;
NDIS_MEDIA_STATE MediaState = 0xFFFFFFFF;
NDIS_STRING IMDevName;
ULONG MacOptions;
ULONG ErrorLogData[2];
PWCHAR StringData[2];
PVOID DumpData;
ImDbgOut(DBG_TRACE, DBG_PROTOCOL, ("(%08X) ProcessLowerMPOpenAdapter\n", Adapter));
//
// see if it worked; clean up and get out
//
if ( !NT_SUCCESS( Status )) {
ImDbgOut(DBG_FAILURE,
DBG_PROTOCOL,
("(%08X) ProcessLowerMPOpenAdapter: binding failed %08X\n", Adapter, Status));
if ( Status == NDIS_STATUS_ADAPTER_NOT_FOUND ) {
EventStatus = EVENT_TRANSPORT_ADAPTER_NOT_FOUND;
} else {
EventStatus = EVENT_TRANSPORT_BINDING_FAILED;
}
StringData[0] = Adapter->IMDeviceName.Buffer;
StringData[1] = Adapter->MPDeviceName.Buffer;
DumpData = &Status;
NdisWriteErrorLogEntry(IMDriverObject,
EventStatus,
0,
2,
&StringData,
sizeof( Status ),
DumpData);
IMFreePool( Adapter );
return;
}
//
// initialize the variables associated with this structure. From this point on,
// DerefAdapter must be called if any errors are encountered.
//
NdisAllocateSpinLock( &Adapter->Lock );
Adapter->RefCount = 1;
ImDbgOut( DBG_TRACE, DBG_REFCNTS, ("(%08X) =1 Adapter\n", Adapter ));
InitializeListHead( &Adapter->ClientList );
Adapter->ShutdownMask = 0;
//
// add adapter on list of known adapters
//
NdisInterlockedInsertTailList( &AdapterList, &Adapter->Linkage, &AdapterListLock );
//
// determine if adapter is ready for use. All adapters probably support hardware
// status. If they don't, then we'll assume it must be ready for use. If the
// HW status indicates ok, then check for media connect state which is new for 4.0.
// If the media is not connected, then we wait until we get an indication that it
// is connected and then we query the adapter for its link speed. This is important
// for multi-speed adapters, like 10/100 ethernet.
//
//
Status = MakeLocalNdisRequest(Adapter,
OID_GEN_HARDWARE_STATUS,
&HWStatus,
sizeof( HWStatus ),
NULL);
if ( Status == NDIS_STATUS_INVALID_OID || HWStatus == NdisHardwareStatusReady ) {
Status = MakeLocalNdisRequest(Adapter,
OID_GEN_MEDIA_CONNECT_STATUS,
&MediaState,
sizeof( MediaState ),
NULL);
if ( Status == NDIS_STATUS_INVALID_OID || MediaState == NdisMediaStateConnected ) {
Status = MakeLocalNdisRequest(Adapter,
OID_GEN_LINK_SPEED,
&Adapter->LinkSpeed,
sizeof( Adapter->LinkSpeed ),
NULL);
if ( !NT_SUCCESS( Status )) {
ImDbgOut(DBG_INFO, DBG_PROTOCOL,
("(%08X) ProcessLowerMPOpenAdapter: Can't get link speed - Status %08X\n",
Adapter, Status));
ErrorLogData[ 0 ] = IM_ERROR_MISSING_OID;
ErrorLogData[ 1 ] = OID_GEN_LINK_SPEED;
NdisWriteErrorLogEntry(Adapter->LowerMPHandle,
NDIS_ERROR_CODE_MISSING_CONFIGURATION_PARAMETER,
2,
ErrorLogData);
goto ErrorExit;
}
} else {
ImDbgOut(DBG_INFO, DBG_PROTOCOL,
("(%08X) ProcessLowerMPOpenAdapter: Media not connected\n", Adapter ));
}
} else {
ImDbgOut(DBG_INFO, DBG_PROTOCOL,
("(%08X) ProcessLowerMPOpenAdapter: HW Status not ready (%d)\n", HWStatus));
}
//
// determine whether we can copy the lookahead data directly
//
Status = MakeLocalNdisRequest(Adapter,
OID_GEN_MAC_OPTIONS,
&MacOptions,
sizeof( MacOptions ),
NULL);
if ( NT_SUCCESS( Status )) {
Adapter->CopyLookaheadData = (BOOLEAN)(MacOptions & NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA);
}
//
// allocate a packet pool with no buffers. We allocate all the packets and
// stuff them on a lookaside list so we don't take the hit later on
//
Status = AllocatePacketPool( Adapter );
if ( !NT_SUCCESS( Status )) {
goto ErrorExit;
}
//
// now allocate two buffer pools: one to hold header plus lookahead data and the
// other for residual lookahead data that is copied via NdisTransferData.
//
Status = AllocateReceiveBufferPools( Adapter );
if ( !NT_SUCCESS( Status )) {
goto ErrorExit;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -