You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3120 lines
83 KiB
3120 lines
83 KiB
/*++
|
|
Copyright (c) 1996-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
adapter.c
|
|
|
|
Abstract:
|
|
|
|
routines for binding/unbinding to/from underlying miniport drivers
|
|
|
|
Author:
|
|
Charlie Wickham (charlwi) 24-Apr-1996.
|
|
Rajesh Sundaram (rajeshsu) 01-Aug-1998.
|
|
|
|
Environment:
|
|
|
|
Kernel Mode
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "psched.h"
|
|
#pragma hdrstop
|
|
|
|
/* Defines */
|
|
|
|
|
|
/* External */
|
|
|
|
/* Static */
|
|
|
|
#define DRIVER_COUNTED_BLOCK \
|
|
{ \
|
|
++DriverRefCount; \
|
|
NdisResetEvent(&DriverUnloadEvent); \
|
|
}
|
|
|
|
#define DRIVER_COUNTED_UNBLOCK \
|
|
{ \
|
|
PS_LOCK(&DriverUnloadLock); \
|
|
if( --DriverRefCount == 0) \
|
|
NdisSetEvent(&DriverUnloadEvent); \
|
|
PS_UNLOCK(&DriverUnloadLock); \
|
|
}
|
|
|
|
/* Forward */
|
|
|
|
NDIS_STATUS
|
|
PsInitializeDeviceInstance(PADAPTER Adapter);
|
|
|
|
NDIS_STATUS
|
|
GetFrameSize(
|
|
PADAPTER Adapter
|
|
);
|
|
|
|
NDIS_STATUS
|
|
InitializeAdapter(
|
|
PADAPTER Adapter,
|
|
NDIS_HANDLE BindContext,
|
|
PNDIS_STRING MpDeviceName,
|
|
PVOID SystemSpecific1);
|
|
|
|
NDIS_STATUS
|
|
UpdateSchedulingPipe(
|
|
PADAPTER Adapter
|
|
);
|
|
|
|
VOID
|
|
DeleteAdapter(PVOID Adapter, BOOLEAN AdapterListLocked);
|
|
|
|
VOID
|
|
ClUnloadProtocol(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
MpHalt(
|
|
IN NDIS_HANDLE MiniportAdapterContext
|
|
);
|
|
|
|
|
|
NDIS_STATUS
|
|
GetSchedulerPipeContext(
|
|
PADAPTER Adapter,
|
|
PPS_PIPE_CONTEXT *AdapterPipeContext,
|
|
PPSI_INFO *AdapterPsComponent,
|
|
PULONG ShutdownMask
|
|
);
|
|
|
|
NDIS_STATUS
|
|
FindProfile(
|
|
IN PNDIS_STRING ProfileName,
|
|
OUT PPS_PROFILE *Profile
|
|
);
|
|
|
|
NDIS_STATUS
|
|
RegisterPsComponent(
|
|
IN PPSI_INFO PsiComponentInfo,
|
|
ULONG Size,
|
|
PPS_DEBUG_INFO DebugInfo
|
|
);
|
|
|
|
NDIS_STATUS
|
|
FindSchedulingComponent(
|
|
IN PNDIS_STRING ComponentName,
|
|
OUT PPSI_INFO *Component
|
|
);
|
|
|
|
NDIS_STATUS
|
|
PsReadMiniportOIDs(
|
|
IN PADAPTER Adapter
|
|
);
|
|
|
|
VOID
|
|
CloseAllGpcVcs(
|
|
IN PADAPTER Adapter);
|
|
|
|
/* End Forward */
|
|
|
|
|
|
NTSTATUS
|
|
PsIoctl(
|
|
IN PDEVICE_OBJECT pdo,
|
|
IN PIRP pirp
|
|
)
|
|
{
|
|
PIO_STACK_LOCATION pirpSp;
|
|
ULONG ioControlCode;
|
|
PLIST_ENTRY NextAdapter;
|
|
PADAPTER Adapter;
|
|
NTSTATUS Status ;
|
|
PGPC_CLIENT_VC Vc;
|
|
PLIST_ENTRY NextVc;
|
|
PPS_WAN_LINK WanLink;
|
|
|
|
PVOID pIoBuf;
|
|
ULONG InputBufferLength;
|
|
ULONG OutputBufferLength;
|
|
|
|
USHORT Port = 0;
|
|
ULONG Ip = 0;
|
|
PTIMESTMP_REQ pTsReq = NULL;
|
|
|
|
|
|
#if DBG
|
|
KIRQL OldIrql;
|
|
KIRQL NewIrql;
|
|
OldIrql = KeGetCurrentIrql();
|
|
#endif
|
|
|
|
pirpSp = IoGetCurrentIrpStackLocation(pirp);
|
|
ioControlCode = pirpSp->Parameters.DeviceIoControl.IoControlCode;
|
|
|
|
pirp->IoStatus.Status = Status = STATUS_SUCCESS;
|
|
pirp->IoStatus.Information = 0;
|
|
|
|
/* Both input and output buffers are mapped to "SystemBuffer" in case of direct-IO */
|
|
pIoBuf = pirp->AssociatedIrp.SystemBuffer;
|
|
|
|
InputBufferLength = pirpSp->Parameters.DeviceIoControl.InputBufferLength;
|
|
OutputBufferLength = pirpSp->Parameters.DeviceIoControl.OutputBufferLength;
|
|
|
|
switch(pirpSp->MajorFunction)
|
|
{
|
|
case IRP_MJ_DEVICE_CONTROL:
|
|
|
|
switch (ioControlCode)
|
|
{
|
|
case IOCTL_PSCHED_ZAW_EVENT:
|
|
|
|
while(InterlockedExchange(&gZAWState, ZAW_STATE_IN_USE) != ZAW_STATE_READY)
|
|
{
|
|
//
|
|
// Some other thread is in this loop. Let's wait
|
|
//
|
|
NdisResetEvent(&gZAWEvent);
|
|
NdisWaitEvent(&gZAWEvent, 0);
|
|
}
|
|
|
|
PsReadDriverRegistryData();
|
|
|
|
//
|
|
// Handle the per adapter settings.
|
|
//
|
|
|
|
PS_LOCK(&AdapterListLock);
|
|
|
|
NextAdapter = AdapterList.Flink;
|
|
|
|
while(NextAdapter != &AdapterList)
|
|
{
|
|
Adapter = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
|
|
|
|
PS_LOCK_DPC(&Adapter->Lock);
|
|
|
|
if(Adapter->PsMpState != AdapterStateRunning)
|
|
{
|
|
PS_UNLOCK_DPC(&Adapter->Lock);
|
|
|
|
NextAdapter = NextAdapter->Flink;
|
|
|
|
continue;
|
|
}
|
|
|
|
REFADD(&Adapter->RefCount, 'IOTL');
|
|
|
|
PS_UNLOCK_DPC(&Adapter->Lock);
|
|
|
|
PS_UNLOCK(&AdapterListLock);
|
|
|
|
PsReadAdapterRegistryData(Adapter,
|
|
&MachineRegistryKey,
|
|
&Adapter->RegistryPath
|
|
);
|
|
//
|
|
// This will apply the effects of the following registry parameters.
|
|
//
|
|
// NonBestEffortLimit
|
|
// TimerResolution (since we update the scheduling pipe)
|
|
//
|
|
|
|
if(Adapter->MediaType != NdisMediumWan)
|
|
{
|
|
UpdateAdapterBandwidthParameters(Adapter);
|
|
|
|
//
|
|
// Set 802.1p/TOS for b/e Vc
|
|
//
|
|
Adapter->BestEffortVc.UserPriorityConforming = Adapter->UserServiceTypeBestEffort;
|
|
Adapter->BestEffortVc.UserPriorityNonConforming = Adapter->UserServiceTypeNonConforming;
|
|
Adapter->BestEffortVc.IPPrecedenceNonConforming = Adapter->IPServiceTypeBestEffortNC;
|
|
}
|
|
else
|
|
{
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
NextVc = Adapter->WanLinkList.Flink;
|
|
|
|
while( NextVc != &Adapter->WanLinkList)
|
|
{
|
|
WanLink = CONTAINING_RECORD(NextVc, PS_WAN_LINK, Linkage);
|
|
|
|
PS_LOCK_DPC(&WanLink->Lock);
|
|
|
|
WanLink->BestEffortVc.UserPriorityConforming = Adapter->UserServiceTypeBestEffort;
|
|
WanLink->BestEffortVc.UserPriorityNonConforming = Adapter->UserServiceTypeNonConforming;
|
|
WanLink->BestEffortVc.IPPrecedenceNonConforming =
|
|
Adapter->IPServiceTypeBestEffortNC;
|
|
|
|
if(WanLink->State == WanStateOpen)
|
|
{
|
|
REFADD(&WanLink->RefCount, 'IOTL');
|
|
|
|
PS_UNLOCK_DPC(&WanLink->Lock);
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
UpdateWanLinkBandwidthParameters(WanLink);
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
NextVc = NextVc->Flink;
|
|
|
|
REFDEL(&WanLink->RefCount, TRUE, 'IOTL');
|
|
|
|
}
|
|
else
|
|
{
|
|
PS_UNLOCK_DPC(&WanLink->Lock);
|
|
|
|
NextVc = NextVc->Flink;
|
|
|
|
}
|
|
}
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
}
|
|
|
|
//
|
|
// Apply the new TOS/802.1p mapping to the VCs.
|
|
//
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
NextVc = Adapter->GpcClientVcList.Flink;
|
|
|
|
while ( NextVc != &Adapter->GpcClientVcList )
|
|
{
|
|
|
|
Vc = CONTAINING_RECORD(NextVc, GPC_CLIENT_VC, Linkage);
|
|
|
|
NextVc = NextVc->Flink;
|
|
|
|
PS_LOCK_DPC(&Vc->Lock);
|
|
|
|
if(Vc->ClVcState == CL_CALL_COMPLETE ||
|
|
Vc->ClVcState == CL_INTERNAL_CALL_COMPLETE )
|
|
{
|
|
SetTOSIEEEValues(Vc);
|
|
}
|
|
|
|
PS_UNLOCK_DPC(&Vc->Lock);
|
|
}
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
PS_LOCK(&AdapterListLock);
|
|
|
|
NextAdapter = NextAdapter->Flink;
|
|
|
|
REFDEL(&Adapter->RefCount, TRUE, 'IOTL');
|
|
|
|
}
|
|
|
|
PS_UNLOCK(&AdapterListLock);
|
|
|
|
InterlockedExchange(&gZAWState, ZAW_STATE_READY);
|
|
NdisSetEvent(&gZAWEvent);
|
|
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IRP_MJ_CREATE:
|
|
break;
|
|
|
|
case IRP_MJ_CLOSE:
|
|
break;
|
|
|
|
case IRP_MJ_CLEANUP:
|
|
break;
|
|
|
|
case IRP_MJ_READ:
|
|
break;
|
|
|
|
case IRP_MJ_SHUTDOWN:
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_NOT_SUPPORTED;
|
|
break;
|
|
}
|
|
|
|
|
|
if( Status == STATUS_SUCCESS)
|
|
{
|
|
pirp->IoStatus.Status = Status;
|
|
IoCompleteRequest(pirp, IO_NETWORK_INCREMENT);
|
|
}
|
|
else
|
|
{
|
|
pirp->IoStatus.Status = Status;
|
|
IoCompleteRequest(pirp, IO_NO_INCREMENT);
|
|
}
|
|
|
|
PsAssert( OldIrql == KeGetCurrentIrql());
|
|
|
|
return Status;
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PsIoctlInit()
|
|
{
|
|
int i;
|
|
NDIS_STATUS Status;
|
|
PDRIVER_DISPATCH DispatchTable[IRP_MJ_MAXIMUM_FUNCTION+1];
|
|
|
|
for(i=0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++)
|
|
{
|
|
DispatchTable[i] = PsIoctl;
|
|
}
|
|
|
|
DispatchTable[IRP_MJ_SYSTEM_CONTROL] = WMIDispatch;
|
|
|
|
Status = NdisMRegisterDevice(MpWrapperHandle,
|
|
&PsDriverName,
|
|
&PsSymbolicName,
|
|
DispatchTable,
|
|
&PsDeviceObject,
|
|
&PsDeviceHandle);
|
|
|
|
if(Status == NDIS_STATUS_SUCCESS)
|
|
{
|
|
InitShutdownMask |= SHUTDOWN_DELETE_DEVICE;
|
|
|
|
PsDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
|
|
|
IoWMIRegistrationControl(PsDeviceObject, WMIREG_ACTION_REGISTER);
|
|
}
|
|
else
|
|
{
|
|
PsDeviceHandle = PsDeviceObject = 0;
|
|
}
|
|
return Status;
|
|
|
|
}
|
|
|
|
VOID
|
|
PsAddDevice()
|
|
{
|
|
//
|
|
// The first Adapter will create the DeviceObject which will enable us to receive
|
|
// irps and become a WMI data provider. The last DeviceObject will unregister from
|
|
// WMI and delete the DeviceObject.
|
|
//
|
|
|
|
MUX_ACQUIRE_MUTEX( &CreateDeviceMutex );
|
|
|
|
++AdapterCount;
|
|
|
|
if(AdapterCount == 1)
|
|
{
|
|
//
|
|
// This is the first adapter, so we create a DeviceObject
|
|
// that allows us to get irps and registers as a WMI data
|
|
// provider.
|
|
|
|
PsIoctlInit();
|
|
}
|
|
|
|
MUX_RELEASE_MUTEX( &CreateDeviceMutex);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
PsInitializeDeviceInstance(PADAPTER Adapter)
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
PsAssert(KeGetCurrentIrql() < DISPATCH_LEVEL);
|
|
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL,
|
|
("[PSInitializeDeviceInstance]: Adapter %08X, InitializeDeviceInstance with %ws \n",
|
|
Adapter,
|
|
Adapter->UpperBinding.Buffer));
|
|
|
|
Status = NdisIMInitializeDeviceInstanceEx(LmDriverHandle,
|
|
&Adapter->UpperBinding,
|
|
Adapter);
|
|
if (Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_PROTOCOL,
|
|
("[PsInitializeDeviceInstance]: Adapter %08X, can't init PS device (%08X)\n",
|
|
Adapter,
|
|
Status));
|
|
|
|
PsAdapterWriteEventLog(
|
|
EVENT_PS_INIT_DEVICE_FAILED,
|
|
0,
|
|
&Adapter->MpDeviceName,
|
|
sizeof(Status),
|
|
&Status);
|
|
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
PsDeleteDevice()
|
|
{
|
|
//
|
|
// The first Adapter will create the DeviceObject which will enable us to receive
|
|
// irps and become a WMI data provider. The last DeviceObject will unregister from
|
|
// WMI and delete the DeviceObject. In order to prevent a race condition we prevent
|
|
// any mpinitialize threads from looking at the AdapterCount. This is achieved by
|
|
// re-setting the WMIAddEvent. It is not sufficient just to do this based on
|
|
// interlocked operations on AdapterCount.
|
|
//
|
|
|
|
MUX_ACQUIRE_MUTEX( &CreateDeviceMutex );
|
|
|
|
--AdapterCount;
|
|
|
|
if(AdapterCount == 0)
|
|
{
|
|
//
|
|
// Delete the DeviceObject, since this is the last Adapter.
|
|
//
|
|
|
|
if(PsDeviceObject)
|
|
{
|
|
IoWMIRegistrationControl(PsDeviceObject, WMIREG_ACTION_DEREGISTER);
|
|
|
|
NdisMDeregisterDevice(PsDeviceHandle);
|
|
|
|
PsDeviceHandle = PsDeviceObject = 0;
|
|
}
|
|
}
|
|
|
|
MUX_RELEASE_MUTEX( &CreateDeviceMutex);
|
|
}
|
|
|
|
|
|
// No of retries to query the frame size
|
|
#define MAX_GET_FRAME_SIZE_RETRY_COUNT 3
|
|
#define WAIT_TIME_FOR_GET_FRAME_SIZE 3
|
|
|
|
|
|
|
|
VOID
|
|
ClBindToLowerMp(
|
|
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:
|
|
|
|
Status : Placeholder for the driver to return a Status to NDIS.
|
|
|
|
BindContext : Handle represents NDIS's context for the bind request.
|
|
This has to be saved and returned when we call
|
|
NdisCompleteBindAdapter
|
|
|
|
SystemSpecific1 : Points to a registy path for the driver to obtain adapter
|
|
specific configuration.
|
|
|
|
MpDeviceName : DeviceName can refer to a NIC managed by an underlying NIC
|
|
driver, or it can be the name of a virtual NIC exported by
|
|
an intermediate NDIS driver that is layered between the
|
|
called intermediate driver and the NIC driver managing the
|
|
adapter to which transmit requests are directed.
|
|
|
|
SystemSpecific2 : Unused, reserved for future use.
|
|
|
|
|
|
Return Values:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PADAPTER Adapter;
|
|
NDIS_STATUS OpenAdapterStatus;
|
|
NDIS_STATUS OpenErrorStatus;
|
|
NDIS_STATUS LocalStatus;
|
|
UINT MediaIndex;
|
|
NDIS_MEDIUM MediumArray[] = {
|
|
NdisMediumFddi,
|
|
NdisMedium802_5,
|
|
NdisMedium802_3,
|
|
NdisMediumWan
|
|
};
|
|
UINT MediumArraySize = sizeof(MediumArray)/sizeof(NDIS_MEDIUM);
|
|
UINT GetFrameSizeRetryCount = 0;
|
|
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL | DBG_INIT,
|
|
("[ClBindToLowerMp]: MpDeviceName %ws\n", MpDeviceName->Buffer));
|
|
|
|
|
|
PS_LOCK(&DriverUnloadLock);
|
|
|
|
//
|
|
// (a) The driver can get unloaded before we complete the bind thread.
|
|
// (b) we can get bound as the driver is getting unloaded.
|
|
//
|
|
// if (a) happens, we block the driver unload and unblock when we finish the bind.
|
|
// if (b) happens, we fail the bind call.
|
|
|
|
if(gDriverState != DriverStateLoaded) {
|
|
|
|
*Status = NDIS_STATUS_FAILURE;
|
|
|
|
PS_UNLOCK(&DriverUnloadLock);
|
|
|
|
PsDbgOut(DBG_FAILURE, DBG_PROTOCOL|DBG_INIT,
|
|
("[ClBindToLowerMp]: Driver is being unloaded \n"));
|
|
|
|
return;
|
|
}
|
|
|
|
DRIVER_COUNTED_BLOCK;
|
|
|
|
PS_UNLOCK(&DriverUnloadLock);
|
|
|
|
//
|
|
// Get a new adapter context struct and initialize it with configuration
|
|
// data from the registry.
|
|
//
|
|
|
|
PsAllocatePool(Adapter, sizeof(ADAPTER), AdapterTag);
|
|
|
|
if(Adapter == NULL) {
|
|
|
|
PsAdapterWriteEventLog(
|
|
(ULONG)EVENT_PS_RESOURCE_POOL,
|
|
0,
|
|
MpDeviceName,
|
|
0,
|
|
NULL);
|
|
|
|
*Status = NDIS_STATUS_RESOURCES;
|
|
|
|
DRIVER_COUNTED_UNBLOCK;
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Initialize the adapter.
|
|
//
|
|
|
|
*Status = InitializeAdapter(Adapter, BindContext, MpDeviceName, SystemSpecific1);
|
|
|
|
Adapter->ShutdownMask |= SHUTDOWN_BIND_CALLED;
|
|
|
|
if(*Status != NDIS_STATUS_SUCCESS) {
|
|
|
|
PsDeleteDevice();
|
|
|
|
REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
|
|
|
|
DRIVER_COUNTED_UNBLOCK;
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
NdisOpenAdapter(&OpenAdapterStatus,
|
|
&OpenErrorStatus,
|
|
&Adapter->LowerMpHandle,
|
|
&MediaIndex,
|
|
MediumArray,
|
|
MediumArraySize,
|
|
ClientProtocolHandle,
|
|
Adapter,
|
|
MpDeviceName,
|
|
0,
|
|
NULL);
|
|
|
|
if(OpenAdapterStatus == NDIS_STATUS_PENDING)
|
|
{
|
|
NdisWaitEvent(&Adapter->BlockingEvent, 0);
|
|
NdisResetEvent(&Adapter->BlockingEvent);
|
|
|
|
}
|
|
else
|
|
{
|
|
Adapter->FinalStatus = OpenAdapterStatus;
|
|
}
|
|
|
|
if(Adapter->FinalStatus == NDIS_STATUS_SUCCESS)
|
|
{
|
|
Adapter->MediaType = MediumArray[MediaIndex];
|
|
|
|
//
|
|
// Take a ref for the open
|
|
//
|
|
REFADD(&Adapter->RefCount, 'NDOP');
|
|
|
|
}
|
|
else
|
|
{
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_PROTOCOL,
|
|
("[ClBindToLowerMp]: Adapter %08X, binding failed (Status = %08X) \n",
|
|
Adapter,
|
|
Status));
|
|
|
|
*Status = Adapter->FinalStatus;
|
|
|
|
PsAdapterWriteEventLog(
|
|
EVENT_PS_BINDING_FAILED,
|
|
0,
|
|
&Adapter->MpDeviceName,
|
|
sizeof(Adapter->FinalStatus),
|
|
&Adapter->FinalStatus);
|
|
|
|
PsDeleteDevice();
|
|
|
|
REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
|
|
|
|
DRIVER_COUNTED_UNBLOCK;
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Get the information pertaining to the miniport below us.
|
|
//
|
|
|
|
|
|
while(1)
|
|
{
|
|
*Status = GetFrameSize(Adapter);
|
|
|
|
if(*Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
if( GetFrameSizeRetryCount == MAX_GET_FRAME_SIZE_RETRY_COUNT)
|
|
{
|
|
goto ErrorCloseOpen;
|
|
}
|
|
else
|
|
{
|
|
GetFrameSizeRetryCount++;
|
|
NdisMSleep( WAIT_TIME_FOR_GET_FRAME_SIZE * 1000 * 1000);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
Adapter->RawLinkSpeed = (ULONG)UNSPECIFIED_RATE;
|
|
|
|
*Status = UpdateAdapterBandwidthParameters(Adapter);
|
|
|
|
if(*Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
if(*Status != NDIS_STATUS_ADAPTER_NOT_READY)
|
|
{
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_PROTOCOL |
|
|
DBG_INIT,
|
|
("[ClBindToLowerMp]: Adapter %08X, couldn't add pipe %08X\n",
|
|
Adapter,
|
|
Status));
|
|
|
|
goto ErrorCloseOpen;
|
|
}
|
|
else
|
|
{
|
|
// The scheduling components have not registered. Let's not call NdisIMInitializeDeviceInstance.
|
|
//
|
|
*Status = NDIS_STATUS_SUCCESS;
|
|
|
|
Adapter->PsMpState = AdapterStateWaiting;
|
|
}
|
|
}
|
|
|
|
// Let's move the creation of IM device here, to see what happens.
|
|
*Status = PsInitializeDeviceInstance(Adapter);
|
|
|
|
if(*Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
goto ErrorCloseOpen;
|
|
}
|
|
|
|
// Ignore the status
|
|
PsReadMiniportOIDs(Adapter);
|
|
|
|
PsUpdateLinkSpeed(Adapter, Adapter->RawLinkSpeed,
|
|
&Adapter->RemainingBandWidth,
|
|
&Adapter->LinkSpeed,
|
|
&Adapter->NonBestEffortLimit,
|
|
&Adapter->Lock);
|
|
|
|
|
|
// This will repro the NetReady bug anywhere, anytime.
|
|
// NdisMSleep( 5 * 1000 * 1000 );
|
|
|
|
REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
|
|
|
|
|
|
DRIVER_COUNTED_UNBLOCK;
|
|
|
|
return;
|
|
|
|
ErrorCloseOpen:
|
|
|
|
|
|
//
|
|
// if we have opened an underlying call manager, close it now.
|
|
//
|
|
|
|
if(Adapter->MediaType == NdisMediumWan) {
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
if(Adapter->ShutdownMask & SHUTDOWN_CLOSE_WAN_ADDR_FAMILY){
|
|
|
|
Adapter->ShutdownMask &= ~SHUTDOWN_CLOSE_WAN_ADDR_FAMILY;
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_WAN | DBG_MINIPORT,
|
|
("[ClBindToLowerMp]: Adapter %08X Closing the WAN address family", Adapter));
|
|
|
|
LocalStatus = NdisClCloseAddressFamily(Adapter->WanCmHandle);
|
|
|
|
}
|
|
else
|
|
{
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close the open since we opened it above
|
|
//
|
|
|
|
if(Adapter->LowerMpHandle)
|
|
{
|
|
NdisCloseAdapter(&LocalStatus, Adapter->LowerMpHandle);
|
|
|
|
if(LocalStatus == NDIS_STATUS_PENDING)
|
|
{
|
|
NdisWaitEvent(&Adapter->BlockingEvent, 0);
|
|
|
|
NdisResetEvent(&Adapter->BlockingEvent);
|
|
}
|
|
|
|
REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
|
|
|
|
}
|
|
|
|
PsDeleteDevice();
|
|
|
|
REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
|
|
|
|
DRIVER_COUNTED_UNBLOCK;
|
|
|
|
return;
|
|
|
|
} // ClBindToLowerMp
|
|
|
|
|
|
VOID
|
|
LinkSpeedQueryComplete(
|
|
PADAPTER Adapter,
|
|
NDIS_STATUS Status
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Completion routine for link speed query during a status indication. Notify
|
|
the scheduling alg. that we have a new adapter
|
|
|
|
Arguments:
|
|
|
|
the usual...
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL,
|
|
("[LinkSpeedQueryComplete]: Adapter %08X, Status %x, Link speed %d\n",
|
|
Adapter, Status,
|
|
Adapter->LinkSpeed*100));
|
|
|
|
if ( !NT_SUCCESS( Status ))
|
|
{
|
|
Adapter->RawLinkSpeed = (ULONG)UNSPECIFIED_RATE;
|
|
|
|
PsAdapterWriteEventLog(
|
|
EVENT_PS_QUERY_OID_GEN_LINK_SPEED,
|
|
0,
|
|
&Adapter->MpDeviceName,
|
|
sizeof(Status),
|
|
&Status);
|
|
|
|
}
|
|
|
|
UpdateAdapterBandwidthParameters(Adapter);
|
|
}
|
|
|
|
VOID
|
|
PsGetLinkSpeed (
|
|
IN PADAPTER Adapter
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
Status = MakeLocalNdisRequest(Adapter,
|
|
NULL,
|
|
NdisRequestLocalQueryInfo,
|
|
OID_GEN_LINK_SPEED,
|
|
&Adapter->RawLinkSpeed,
|
|
sizeof(Adapter->RawLinkSpeed),
|
|
LinkSpeedQueryComplete);
|
|
|
|
if (Status != NDIS_STATUS_PENDING)
|
|
{
|
|
LinkSpeedQueryComplete(Adapter, Status);
|
|
}
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
PsReadMiniportOIDs(
|
|
IN PADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Complete the binding on the lower miniport. Initialize the
|
|
adapter structure, query the MP for certain funtionality and
|
|
initialize the associated PS miniport device
|
|
|
|
Arguments:
|
|
|
|
see the DDK
|
|
|
|
Return Values:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
PWSTR SecondaryName;
|
|
NDIS_HARDWARE_STATUS HwStatus;
|
|
NDIS_MEDIA_STATE MediaState = 0xFFFFFFFF;
|
|
NDIS_STRING PsDevName;
|
|
ULONG MacOptions;
|
|
ULONG LinkSpeed;
|
|
|
|
PsDbgOut(DBG_TRACE,
|
|
DBG_PROTOCOL,
|
|
("[PsReadMiniportOIDs]: Adapter %08X \n", Adapter));
|
|
|
|
|
|
Status = MakeLocalNdisRequest(Adapter,
|
|
NULL,
|
|
NdisRequestLocalQueryInfo,
|
|
OID_GEN_MEDIA_CONNECT_STATUS,
|
|
&MediaState,
|
|
sizeof( MediaState ),
|
|
NULL);
|
|
|
|
PsAssert(Status != NDIS_STATUS_INVALID_OID || Status != NDIS_STATUS_NOT_SUPPORTED);
|
|
|
|
if(Status == NDIS_STATUS_SUCCESS && MediaState == NdisMediaStateConnected){
|
|
|
|
Status = MakeLocalNdisRequest(Adapter,
|
|
NULL,
|
|
NdisRequestLocalQueryInfo,
|
|
OID_GEN_LINK_SPEED,
|
|
&Adapter->RawLinkSpeed,
|
|
sizeof(LinkSpeed),
|
|
NULL);
|
|
if(Status != NDIS_STATUS_SUCCESS){
|
|
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL,
|
|
("[PsReadMiniportOIDs]: Adapter %08X, Can't get link "
|
|
"speed - Status %08X\n", Adapter, Status));
|
|
|
|
Adapter->RawLinkSpeed = (ULONG)UNSPECIFIED_RATE;
|
|
|
|
PsAdapterWriteEventLog(
|
|
EVENT_PS_QUERY_OID_GEN_LINK_SPEED,
|
|
0,
|
|
&Adapter->MpDeviceName,
|
|
sizeof(Status),
|
|
&Status);
|
|
}
|
|
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL,
|
|
("[PsReadMiniportOIDs] Adapter %08X, Link speed %d\n",
|
|
Adapter,
|
|
Adapter->RawLinkSpeed*100));
|
|
}
|
|
else{
|
|
|
|
//
|
|
// We can continue, even though we don't yet have the
|
|
// link speed. We'll update it later.
|
|
//
|
|
|
|
Adapter->RawLinkSpeed = (ULONG)UNSPECIFIED_RATE;
|
|
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL,
|
|
("[PsReadMiniportOIDs]: Adapter %08X, Media not connected\n",
|
|
Adapter));
|
|
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // PsReadMiniportOIDs
|
|
|
|
VOID
|
|
PsUpdateLinkSpeed(
|
|
PADAPTER Adapter,
|
|
ULONG RawLinkSpeed,
|
|
PULONG RemainingBandWidth,
|
|
PULONG LinkSpeed,
|
|
PULONG NonBestEffortLimit,
|
|
PPS_SPIN_LOCK Lock
|
|
)
|
|
{
|
|
ULONG NewNonBestEffortLimit;
|
|
|
|
PS_LOCK(Lock);
|
|
|
|
if(RawLinkSpeed == UNSPECIFIED_RATE)
|
|
{
|
|
|
|
//
|
|
// It is legit to have an unspecified rate - We pend
|
|
// all finite rate flows till we know the link speed.
|
|
// Indefinite rate flows will be admitted.
|
|
//
|
|
|
|
*LinkSpeed = UNSPECIFIED_RATE;
|
|
Adapter->PipeHasResources = FALSE;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// RawLinkSpeed is in 100 bps units. Convert it to 100 Bytes per second
|
|
// and then into Bytes Per Second.
|
|
//
|
|
*LinkSpeed = RawLinkSpeed / 8;
|
|
*LinkSpeed = (ULONG)(*LinkSpeed * 100);
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_PROTOCOL,
|
|
("[PsUpdateLinkSpeed]: Adapter %08X, Link Speed %d \n",
|
|
Adapter, *LinkSpeed));
|
|
|
|
Adapter->PipeHasResources = TRUE;
|
|
|
|
//
|
|
// The NBE is a % of the link speed. If the link speed changes, we need to
|
|
// change this value.
|
|
//
|
|
|
|
NewNonBestEffortLimit = Adapter->ReservationLimitValue * (*LinkSpeed / 100);
|
|
|
|
PsDbgOut(DBG_INFO, DBG_PROTOCOL,
|
|
("[PsUpdateLinkSpeed]: Adapter %08X, LinkSpeed %d, NBE %d, "
|
|
" Remaining b/w = %d, New NBE = %d \n",
|
|
Adapter, *LinkSpeed, *NonBestEffortLimit,
|
|
*RemainingBandWidth, NewNonBestEffortLimit));
|
|
|
|
if(NewNonBestEffortLimit >= *NonBestEffortLimit) {
|
|
|
|
//
|
|
// The bandwidth has increased - we need not do anything with
|
|
// the flows that have already been created. Also, if RemainingBandWidth <
|
|
// NonBestEffortLimit, then some of the resources have been allocated to flows
|
|
// that were already created - We need to subtract this from the new
|
|
// RemainingBandWidth.
|
|
//
|
|
|
|
*RemainingBandWidth = NewNonBestEffortLimit - (*NonBestEffortLimit - *RemainingBandWidth);
|
|
|
|
*NonBestEffortLimit = NewNonBestEffortLimit;
|
|
}
|
|
else {
|
|
|
|
//
|
|
// Sigh. The bandwidth has decreased. We may need to delete some of the flows
|
|
//
|
|
|
|
if(*RemainingBandWidth == *NonBestEffortLimit)
|
|
{
|
|
|
|
//
|
|
// No flows were created as yet - Just update the 2 values
|
|
//
|
|
*NonBestEffortLimit = *RemainingBandWidth = NewNonBestEffortLimit;
|
|
}
|
|
else {
|
|
if((*NonBestEffortLimit - *RemainingBandWidth) <= (NewNonBestEffortLimit)) {
|
|
|
|
//
|
|
// The flows that were created are under the new limit.
|
|
//
|
|
|
|
*RemainingBandWidth = NewNonBestEffortLimit - (*NonBestEffortLimit - *RemainingBandWidth);
|
|
|
|
*NonBestEffortLimit = NewNonBestEffortLimit;
|
|
}
|
|
else
|
|
{
|
|
*RemainingBandWidth = NewNonBestEffortLimit - (*NonBestEffortLimit - *RemainingBandWidth);
|
|
*NonBestEffortLimit = NewNonBestEffortLimit;
|
|
|
|
PsAdapterWriteEventLog(
|
|
EVENT_PS_ADMISSIONCONTROL_OVERFLOW,
|
|
0,
|
|
&Adapter->MpDeviceName,
|
|
0,
|
|
NULL);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PS_UNLOCK(Lock);
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
UpdateAdapterBandwidthParameters(
|
|
PADAPTER Adapter
|
|
)
|
|
|
|
{
|
|
PsUpdateLinkSpeed(Adapter, Adapter->RawLinkSpeed,
|
|
&Adapter->RemainingBandWidth,
|
|
&Adapter->LinkSpeed,
|
|
&Adapter->NonBestEffortLimit,
|
|
&Adapter->Lock);
|
|
|
|
return UpdateSchedulingPipe(Adapter);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
ClLowerMpOpenAdapterComplete(
|
|
IN PADAPTER Adapter,
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_STATUS OpenErrorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Signal that the binding on the lower miniport is complete
|
|
|
|
Arguments:
|
|
|
|
see the DDK
|
|
|
|
Return Values:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_PROTOCOL, ("[ClLowerMpOpenAdapterComplete]: Adapter %08X\n",
|
|
Adapter));
|
|
|
|
//
|
|
// stuff the final status in the Adapter block and signal
|
|
// the bind handler to continue
|
|
//
|
|
|
|
Adapter->FinalStatus = Status;
|
|
NdisSetEvent( &Adapter->BlockingEvent );
|
|
|
|
} // ClLowerMpOpenAdapterComplete
|
|
|
|
|
|
NDIS_STATUS
|
|
GetFrameSize(
|
|
PADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine queries the underlying adapter to derive the total
|
|
frame size and the header size. (Total = Frame + Header)
|
|
|
|
Arguments:
|
|
|
|
Adapter - pointer to adapter context block
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
ULONG i;
|
|
ULONG FrameSize; // doesn't include the header
|
|
|
|
//
|
|
// max amount of data w/o the MAC header
|
|
//
|
|
|
|
Status = MakeLocalNdisRequest(Adapter,
|
|
NULL,
|
|
NdisRequestLocalQueryInfo,
|
|
OID_GEN_MAXIMUM_FRAME_SIZE,
|
|
&FrameSize,
|
|
sizeof(FrameSize),
|
|
NULL);
|
|
|
|
if(Status != NDIS_STATUS_SUCCESS){
|
|
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_PROTOCOL,
|
|
("[GetFrameSize]: Adapter %08X, Can't get frame size - Status %08X\n",
|
|
Adapter,
|
|
Status));
|
|
|
|
PsAdapterWriteEventLog(
|
|
EVENT_PS_QUERY_OID_GEN_MAXIMUM_FRAME_SIZE,
|
|
0,
|
|
&Adapter->MpDeviceName,
|
|
sizeof(Status),
|
|
&Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// this one includes the header
|
|
//
|
|
|
|
Status = MakeLocalNdisRequest(Adapter,
|
|
NULL,
|
|
NdisRequestLocalQueryInfo,
|
|
OID_GEN_MAXIMUM_TOTAL_SIZE,
|
|
&Adapter->TotalSize,
|
|
sizeof(Adapter->TotalSize),
|
|
NULL);
|
|
|
|
if(Status != NDIS_STATUS_SUCCESS){
|
|
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_PROTOCOL,
|
|
("(%08X) GetFrameSize: Can't get total size - Status %08X\n",
|
|
Adapter,
|
|
Status));
|
|
|
|
PsAdapterWriteEventLog(
|
|
EVENT_PS_QUERY_OID_GEN_MAXIMUM_TOTAL_SIZE,
|
|
0,
|
|
&Adapter->MpDeviceName,
|
|
sizeof(Status),
|
|
&Status);
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
//
|
|
// figure the real header size
|
|
//
|
|
|
|
if (Adapter->TotalSize <= FrameSize)
|
|
Status = NDIS_STATUS_FAILURE;
|
|
else
|
|
Adapter->HeaderSize = Adapter->TotalSize - FrameSize;
|
|
|
|
return Status;
|
|
|
|
} // GetFrameSize
|
|
|
|
|
|
NDIS_STATUS
|
|
GetSchedulerPipeContext(
|
|
PADAPTER Adapter,
|
|
PPS_PIPE_CONTEXT *AdapterPipeContext,
|
|
PPSI_INFO *AdapterPsComponent,
|
|
PULONG ShutdownMask
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Allocate the pipe context area for the scheduler.
|
|
|
|
Arguments:
|
|
|
|
Adapter - pointer to adapter context struct
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS, otherwise appropriate error value
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Index = 0;
|
|
PPS_PROFILE ProfileConfig;
|
|
PPSI_INFO PsComponent;
|
|
ULONG ContextLength = 0;
|
|
ULONG FlowContextLength = 0;
|
|
ULONG ClassMapContextLength = 0;
|
|
PPS_PIPE_CONTEXT PipeContext, PrevContext;
|
|
ULONG PacketReservedLength = sizeof(PS_SEND_PACKET_CONTEXT);
|
|
PVOID PipeCxt;
|
|
|
|
ProfileConfig = &DefaultSchedulerConfig;
|
|
|
|
for (Index = 0; Index < ProfileConfig->ComponentCnt; Index++)
|
|
{
|
|
ContextLength +=
|
|
ProfileConfig->ComponentList[Index]->PipeContextLength;
|
|
FlowContextLength +=
|
|
ProfileConfig->ComponentList[Index]->FlowContextLength;
|
|
ClassMapContextLength +=
|
|
ProfileConfig->ComponentList[Index]->ClassMapContextLength;
|
|
|
|
PacketReservedLength += ProfileConfig->ComponentList[Index]->PacketReservedLength;
|
|
}
|
|
|
|
Adapter->FlowContextLength = FlowContextLength;
|
|
Adapter->ClassMapContextLength = ClassMapContextLength;
|
|
Adapter->PacketContextLength = PacketReservedLength;
|
|
|
|
if(AdapterPipeContext)
|
|
{
|
|
PacketReservedLength = sizeof(PS_SEND_PACKET_CONTEXT);
|
|
|
|
PsAllocatePool( PipeContext, ContextLength, PipeContextTag );
|
|
|
|
*AdapterPipeContext = PipeContext;
|
|
|
|
if ( *AdapterPipeContext == NULL ) {
|
|
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
*ShutdownMask |= SHUTDOWN_FREE_PS_CONTEXT;
|
|
|
|
// Set up the context buffer
|
|
|
|
PrevContext = NULL;
|
|
|
|
for (Index = 0; Index < ProfileConfig->ComponentCnt; Index++)
|
|
{
|
|
PsComponent = ProfileConfig->ComponentList[Index];
|
|
|
|
PipeContext->NextComponentContext = (PPS_PIPE_CONTEXT)
|
|
((UINT_PTR)PipeContext + PsComponent->PipeContextLength);
|
|
PipeContext->PrevComponentContext = PrevContext;
|
|
|
|
if(Index+1 == ProfileConfig->ComponentCnt)
|
|
{
|
|
PipeContext->NextComponent = 0;
|
|
}
|
|
else
|
|
{
|
|
PipeContext->NextComponent =
|
|
ProfileConfig->ComponentList[Index + 1];
|
|
}
|
|
|
|
if (PsComponent->PacketReservedLength > 0)
|
|
{
|
|
PipeContext->PacketReservedOffset = PacketReservedLength;
|
|
PacketReservedLength +=
|
|
PsComponent->PacketReservedLength;
|
|
} else
|
|
{
|
|
PipeContext->PacketReservedOffset = 0;
|
|
}
|
|
|
|
PrevContext = PipeContext;
|
|
PipeContext = PipeContext->NextComponentContext;
|
|
}
|
|
|
|
*AdapterPsComponent = ProfileConfig->ComponentList[0];
|
|
}
|
|
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
|
|
|
|
} // GetSchedulerPipeContext
|
|
|
|
NDIS_STATUS
|
|
UpdateWanSchedulingPipe(PPS_WAN_LINK WanLink)
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PS_PIPE_PARAMETERS PipeParameters;
|
|
PADAPTER Adapter = WanLink->Adapter;
|
|
|
|
//
|
|
// Initialize pipe parameters.
|
|
// UNSPECIFIED_RATE indicates that the link speed is currently
|
|
// unknown. This is a legitimate initialization value.
|
|
//
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
PS_LOCK_DPC(&WanLink->Lock);
|
|
|
|
PipeParameters.Bandwidth = WanLink->LinkSpeed;
|
|
PipeParameters.MTUSize = Adapter->TotalSize;
|
|
PipeParameters.HeaderSize = Adapter->HeaderSize;
|
|
PipeParameters.Flags = Adapter->PipeFlags;
|
|
PipeParameters.MaxOutstandingSends = Adapter->MaxOutstandingSends;
|
|
PipeParameters.SDModeControlledLoad = Adapter->SDModeControlledLoad;
|
|
PipeParameters.SDModeGuaranteed = Adapter->SDModeGuaranteed;
|
|
PipeParameters.SDModeNetworkControl = Adapter->SDModeNetworkControl;
|
|
PipeParameters.SDModeQualitative = Adapter->SDModeQualitative;
|
|
PipeParameters.RegistryPath = &Adapter->RegistryPath;
|
|
|
|
PS_UNLOCK_DPC(&WanLink->Lock);
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
//
|
|
// Initialize the pipe for only the first time
|
|
//
|
|
|
|
if ( !(WanLink->ShutdownMask & SHUTDOWN_DELETE_PIPE )) {
|
|
|
|
//
|
|
// Allocate and initialize the context buffer for the scheduler.
|
|
//
|
|
|
|
Status = GetSchedulerPipeContext( Adapter,
|
|
&WanLink->PsPipeContext,
|
|
&WanLink->PsComponent,
|
|
&WanLink->ShutdownMask );
|
|
|
|
if ( !NT_SUCCESS( Status ))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
WanLink->BestEffortVc.PsPipeContext = WanLink->PsPipeContext;
|
|
WanLink->BestEffortVc.PsComponent = WanLink->PsComponent;
|
|
|
|
// Need to set the pipe's media type here.. //
|
|
PipeParameters.MediaType = NdisMediumWan;
|
|
|
|
Status = (*WanLink->PsComponent->InitializePipe)(
|
|
Adapter,
|
|
&PipeParameters,
|
|
WanLink->PsPipeContext,
|
|
&PsProcs,
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(Status))
|
|
{
|
|
WanLink->ShutdownMask |= SHUTDOWN_DELETE_PIPE;
|
|
}
|
|
|
|
}
|
|
else{
|
|
|
|
// Pipe's already been initialized. This is a modify
|
|
|
|
Status = (*WanLink->PsComponent->ModifyPipe)(
|
|
WanLink->PsPipeContext,
|
|
&PipeParameters);
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
UpdateSchedulingPipe(
|
|
PADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize a scheduling pipe on the adapter. Always called with a LOCK
|
|
held.
|
|
|
|
Arguments:
|
|
|
|
Adapter - pointer to adapter context struct
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS, otherwise appropriate error value
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PS_PIPE_PARAMETERS PipeParameters;
|
|
|
|
//
|
|
// Initialize pipe parameters.
|
|
// UNSPECIFIED_RATE indicates that the link speed is currently
|
|
// unknown. This is a legitimate initialization value.
|
|
//
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
PipeParameters.Bandwidth = Adapter->LinkSpeed;
|
|
PipeParameters.MTUSize = Adapter->TotalSize;
|
|
PipeParameters.HeaderSize = Adapter->HeaderSize;
|
|
PipeParameters.Flags = Adapter->PipeFlags;
|
|
PipeParameters.MaxOutstandingSends = Adapter->MaxOutstandingSends;
|
|
PipeParameters.SDModeControlledLoad = Adapter->SDModeControlledLoad;
|
|
PipeParameters.SDModeGuaranteed = Adapter->SDModeGuaranteed;
|
|
PipeParameters.SDModeNetworkControl = Adapter->SDModeNetworkControl;
|
|
PipeParameters.SDModeQualitative = Adapter->SDModeQualitative;
|
|
PipeParameters.RegistryPath = &Adapter->RegistryPath;
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
//
|
|
// Initialize the pipe for only the first time
|
|
//
|
|
|
|
if ( !(Adapter->ShutdownMask & SHUTDOWN_DELETE_PIPE ))
|
|
{
|
|
|
|
//
|
|
// We don't run the scheduling components on the Adapter structure for NDISWAN.
|
|
// Each wanlink has its own set of scheduling components. But, we still need to compute the
|
|
// PacketPool Length and allocate the Packet Pool - Hence we have to call GetSchedulerPipeContext
|
|
//
|
|
|
|
if(Adapter->MediaType == NdisMediumWan)
|
|
{
|
|
//
|
|
// Allocate and initialize the context buffer for the scheduler.
|
|
//
|
|
|
|
Status = GetSchedulerPipeContext( Adapter,
|
|
NULL,
|
|
NULL,
|
|
NULL);
|
|
}
|
|
else
|
|
{
|
|
Status = GetSchedulerPipeContext( Adapter,
|
|
&Adapter->PsPipeContext,
|
|
&Adapter->PsComponent,
|
|
&Adapter->ShutdownMask);
|
|
|
|
}
|
|
|
|
if ( !NT_SUCCESS( Status ))
|
|
{
|
|
return Status;
|
|
}
|
|
|
|
if(Adapter->MediaType == NdisMediumWan)
|
|
{
|
|
|
|
Adapter->ShutdownMask |= SHUTDOWN_DELETE_PIPE;
|
|
|
|
PsAssert(!(Adapter->ShutdownMask & SHUTDOWN_FREE_PS_CONTEXT));
|
|
PsAssert(!Adapter->PsPipeContext);
|
|
PsAssert(!Adapter->PsComponent);
|
|
|
|
}
|
|
else
|
|
{
|
|
// Need to set the pipe's media type here.. //
|
|
PipeParameters.MediaType = Adapter->MediaType;
|
|
|
|
Status = (*Adapter->PsComponent->InitializePipe)(
|
|
Adapter,
|
|
&PipeParameters,
|
|
Adapter->PsPipeContext,
|
|
&PsProcs,
|
|
NULL);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
|
|
Adapter->ShutdownMask |= SHUTDOWN_DELETE_PIPE;
|
|
}
|
|
else
|
|
{
|
|
return Status;
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
else
|
|
{
|
|
// Pipe's already been initialized. This is a modify
|
|
|
|
if(Adapter->MediaType != NdisMediumWan)
|
|
{
|
|
Status = (*Adapter->PsComponent->ModifyPipe)(
|
|
Adapter->PsPipeContext,
|
|
&PipeParameters);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
|
|
} // UpdateSchedulingPipe
|
|
|
|
|
|
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
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Packet scheduler's device initialization routine. The list of media types is
|
|
checked to be sure it is one that we support. If so, match up the name of
|
|
the device being opened with one of the adapters to which we've bound.
|
|
|
|
Arguments:
|
|
|
|
See the DDK...
|
|
|
|
Return Values:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PADAPTER Adapter;
|
|
NDIS_STATUS Status;
|
|
BOOLEAN FakingIt = FALSE;
|
|
NDIS_STRING MpDeviceName;
|
|
|
|
|
|
//
|
|
// We're being called to initialize one of our miniport
|
|
// device instances. We triggered this by calling
|
|
// NdisIMInitializeDeviceInstance when we were asked to
|
|
// bind to the adapter below us. We provided a pointer
|
|
// to the ADAPTER struct corresponding to the actual
|
|
// adapter we opened. We can get that back now, with the
|
|
// following call.
|
|
//
|
|
|
|
Adapter = NdisIMGetDeviceContext(MiniportAdapterHandle);
|
|
|
|
PsStructAssert(Adapter);
|
|
PsDbgOut(DBG_TRACE, DBG_MINIPORT | DBG_INIT, ("[MpInitialize]: Adapter %08X \n", Adapter));
|
|
|
|
Adapter->ShutdownMask |= SHUTDOWN_MPINIT_CALLED;
|
|
|
|
//
|
|
// We assume that the faster packet APIs will be used, and initialize our per-packet pool. If we don't get a packet-stack,
|
|
// we'll initialize the NDIS packet pool and free the per-packet pool (since the NDIS packet pool will have space for a per-packet
|
|
// pool).
|
|
//
|
|
// We cannot know about the old or new packet stack API at bind time (because even if we did know our position in the packet stack, and
|
|
// initialized the old APIs, we could get a newly allocated packet from an IM above us which will have room for a packet stack).
|
|
//
|
|
|
|
Adapter->SendBlockPool = NdisCreateBlockPool((USHORT)Adapter->PacketContextLength,
|
|
FIELD_OFFSET(PS_SEND_PACKET_CONTEXT, FreeList),
|
|
NDIS_PACKET_POOL_TAG_FOR_PSCHED,
|
|
NULL);
|
|
|
|
if(!Adapter->SendBlockPool)
|
|
{
|
|
PsDbgOut(DBG_CRITICAL_ERROR,
|
|
DBG_MINIPORT | DBG_INIT,
|
|
("[MpInitialize]: Adapter %08X, Can't allocate packet pool \n",
|
|
Adapter));
|
|
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
|
|
PsAdapterWriteEventLog(
|
|
EVENT_PS_RESOURCE_POOL,
|
|
0,
|
|
&Adapter->MpDeviceName,
|
|
0,
|
|
NULL);
|
|
|
|
goto MpInitializeError;
|
|
}
|
|
|
|
|
|
//
|
|
// We can also get the instance name for the corresponding
|
|
// adapter. This is the name which WMI will be using to
|
|
// refer to this instance of us.
|
|
//
|
|
|
|
Status = NdisMQueryAdapterInstanceName(&Adapter->WMIInstanceName, MiniportAdapterHandle);
|
|
|
|
if(Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
PsDbgOut(DBG_CRITICAL_ERROR,
|
|
DBG_MINIPORT | DBG_INIT,
|
|
("[MpInitialize]: Adapter %08X, Failed to get WMI instance name.\n",
|
|
Adapter,
|
|
Status));
|
|
|
|
PsAdapterWriteEventLog(
|
|
EVENT_PS_WMI_INSTANCE_NAME_FAILED,
|
|
0,
|
|
&Adapter->MpDeviceName,
|
|
sizeof(Status),
|
|
&Status);
|
|
|
|
goto MpInitializeError;
|
|
}
|
|
|
|
//
|
|
// lookup our media type in the supplied media array
|
|
//
|
|
// if we're NdisMediumWan, then we have to fake out the
|
|
// protocol and pretend that we're NdisMedium802_3, so
|
|
// fake it for now.
|
|
//
|
|
|
|
if(Adapter->MediaType == NdisMediumWan){
|
|
|
|
FakingIt = TRUE;
|
|
Adapter->MediaType = NdisMedium802_3;
|
|
}
|
|
|
|
if (MediumArray != 0) {
|
|
for(--MediumArraySize ; MediumArraySize > 0;) {
|
|
|
|
if(MediumArray[ MediumArraySize ] == Adapter->MediaType){
|
|
break;
|
|
}
|
|
|
|
if(MediumArraySize == 0){
|
|
break;
|
|
}
|
|
|
|
--MediumArraySize;
|
|
}
|
|
}
|
|
|
|
if(MediumArraySize == 0 && MediumArray[ 0 ] != Adapter->MediaType){
|
|
|
|
if(FakingIt)
|
|
{
|
|
FakingIt = FALSE;
|
|
Adapter->MediaType = NdisMediumWan;
|
|
}
|
|
|
|
PsDbgOut(DBG_CRITICAL_ERROR,
|
|
DBG_MINIPORT | DBG_INIT,
|
|
("[MpInitialize]: Adapter %08X, Unsupported Media \n",
|
|
Adapter));
|
|
|
|
Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
|
|
|
|
goto MpInitializeError;
|
|
}
|
|
|
|
if(FakingIt){
|
|
|
|
FakingIt = FALSE;
|
|
Adapter->MediaType = NdisMediumWan;
|
|
}
|
|
|
|
*SelectedMediumIndex = MediumArraySize;
|
|
|
|
//
|
|
// finish the initialization process by set our attributes
|
|
//
|
|
|
|
NdisMSetAttributesEx(MiniportAdapterHandle,
|
|
Adapter,
|
|
0xFFFF,
|
|
NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
|
|
NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT |
|
|
NDIS_ATTRIBUTE_DESERIALIZE |
|
|
NDIS_ATTRIBUTE_INTERMEDIATE_DRIVER |
|
|
NDIS_ATTRIBUTE_NO_HALT_ON_SUSPEND,
|
|
0);
|
|
|
|
//
|
|
// Set the default value for the device state flag as PM capable (for both miniport
|
|
// and protocol). Device is ON by default
|
|
//
|
|
Adapter->MPDeviceState = NdisDeviceStateD0;
|
|
Adapter->PTDeviceState = NdisDeviceStateD0;
|
|
|
|
Adapter->PsNdisHandle = MiniportAdapterHandle;
|
|
|
|
//
|
|
// We create the b/e VC here (rather than the bind handler) because
|
|
// this will be called only after all scheduling components have registered.
|
|
//
|
|
|
|
if(Adapter->MediaType != NdisMediumWan) {
|
|
|
|
Status = CreateBestEffortVc(Adapter,
|
|
&Adapter->BestEffortVc,
|
|
0);
|
|
|
|
if(Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
PsDbgOut(DBG_CRITICAL_ERROR, DBG_MINIPORT | DBG_INIT,
|
|
("[MpInitialize]: Adapter %08X, cannot create b/e VC ! \n",
|
|
Adapter));
|
|
|
|
goto MpInitializeError;
|
|
}
|
|
}
|
|
|
|
Adapter->PsMpState = AdapterStateRunning;
|
|
|
|
//
|
|
// This is for mpinitialize, will be deref'd on mphalt.
|
|
//
|
|
REFADD(&Adapter->RefCount, 'NDHT');
|
|
|
|
PS_LOCK(&AdapterListLock);
|
|
|
|
if(WMIInitialized && !Adapter->IfcNotification)
|
|
{
|
|
//
|
|
// WMI has been initialized correctly. i.e we can post events
|
|
// at this point.
|
|
//
|
|
|
|
Adapter->IfcNotification = TRUE;
|
|
|
|
PS_UNLOCK(&AdapterListLock);
|
|
|
|
TcIndicateInterfaceChange(Adapter, 0, NDIS_STATUS_INTERFACE_UP);
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// WMI has not been initialized. Since this adapter is already on the
|
|
// list, the interface up event will be posted when IRP_MN_REGINFO
|
|
// completes.
|
|
//
|
|
|
|
PS_UNLOCK(&AdapterListLock);
|
|
}
|
|
|
|
NdisSetEvent(&Adapter->MpInitializeEvent);
|
|
|
|
return NDIS_STATUS_SUCCESS;
|
|
|
|
MpInitializeError:
|
|
Adapter->PsNdisHandle = 0;
|
|
NdisSetEvent(&Adapter->MpInitializeEvent);
|
|
return Status;
|
|
|
|
} // MpInitialize
|
|
|
|
|
|
|
|
PADAPTER
|
|
FindAdapterById(
|
|
ULONG InterfaceId,
|
|
ULONG LinkId,
|
|
PPS_WAN_LINK *PsWanLink
|
|
)
|
|
{
|
|
PLIST_ENTRY NextAdapter;
|
|
PLIST_ENTRY NextLink;
|
|
PPS_WAN_LINK WanLink;
|
|
PADAPTER AdapterInList;
|
|
|
|
*PsWanLink = NULL;
|
|
|
|
PS_LOCK(&AdapterListLock);
|
|
|
|
NextAdapter = AdapterList.Flink;
|
|
|
|
while(NextAdapter != &AdapterList){
|
|
|
|
AdapterInList = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
|
|
|
|
PS_LOCK_DPC(&AdapterInList->Lock);
|
|
|
|
//
|
|
// If it's closing, blow right by it.
|
|
//
|
|
|
|
if(AdapterInList->PsMpState != AdapterStateRunning)
|
|
{
|
|
PS_UNLOCK_DPC(&AdapterInList->Lock);
|
|
|
|
NextAdapter = NextAdapter->Flink;
|
|
|
|
continue;
|
|
}
|
|
|
|
if(AdapterInList->MediaType != NdisMediumWan)
|
|
{
|
|
if(AdapterInList->InterfaceID.InterfaceId != InterfaceId)
|
|
{
|
|
PS_UNLOCK_DPC(&AdapterInList->Lock);
|
|
|
|
NextAdapter = NextAdapter->Flink;
|
|
|
|
continue;
|
|
}
|
|
|
|
REFADD(&AdapterInList->RefCount, 'ADVC');
|
|
|
|
PS_UNLOCK_DPC(&AdapterInList->Lock);
|
|
|
|
PS_UNLOCK(&AdapterListLock);
|
|
|
|
return(AdapterInList);
|
|
}
|
|
else
|
|
{
|
|
|
|
if(AdapterInList->WanBindingState & WAN_ADDR_FAMILY_OPEN)
|
|
{
|
|
//
|
|
// Wan adapters are searched by the name stored with
|
|
// their links.
|
|
//
|
|
|
|
NextLink = AdapterInList->WanLinkList.Flink;
|
|
|
|
while(NextLink != &AdapterInList->WanLinkList){
|
|
|
|
WanLink = CONTAINING_RECORD(NextLink, PS_WAN_LINK, Linkage);
|
|
|
|
if((WanLink->State == WanStateOpen) &&
|
|
(LinkId == WanLink->InterfaceID.LinkId) &&
|
|
(InterfaceId == WanLink->InterfaceID.InterfaceId)) {
|
|
REFADD(&AdapterInList->RefCount, 'ADVC');
|
|
REFADD(&WanLink->RefCount, 'WANV');
|
|
|
|
PS_UNLOCK_DPC(&AdapterInList->Lock);
|
|
PS_UNLOCK(&AdapterListLock);
|
|
*PsWanLink = WanLink;
|
|
return(AdapterInList);
|
|
}
|
|
NextLink = NextLink->Flink;
|
|
}
|
|
}
|
|
}
|
|
|
|
PS_UNLOCK_DPC(&AdapterInList->Lock);
|
|
NextAdapter = NextAdapter->Flink;
|
|
|
|
}
|
|
|
|
PS_UNLOCK(&AdapterListLock);
|
|
return NULL;
|
|
|
|
} // FindAdapterByWmiInstanceName
|
|
|
|
|
|
|
|
|
|
PADAPTER
|
|
FindAdapterByWmiInstanceName(
|
|
USHORT StringLength,
|
|
PWSTR StringStart,
|
|
PPS_WAN_LINK *PsWanLink
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Find the miniport instance that matches the instance name passed in.
|
|
|
|
Arguments:
|
|
|
|
StringLength - Number of bytes / 2
|
|
|
|
StringStart - pointer to a buffer containing a wide string
|
|
|
|
PsWanLink - if this is an interface search, then the WAN link
|
|
representing the interface will be returned in this location.
|
|
If it is not an interface search or no matching WanLink is
|
|
found, NULL will be returned.
|
|
|
|
InterfaceSearch - if TRUE, this is a search for an interface. For
|
|
LAN adapters, an interface is equivalent to an adapter. For WAN
|
|
adapters, interfaces are links. Otherwise, it's a search for an
|
|
adapter.
|
|
|
|
Return Value:
|
|
|
|
pointer to ADAPTER struct, otherwise NULL
|
|
|
|
--*/
|
|
|
|
{
|
|
PLIST_ENTRY NextAdapter;
|
|
PLIST_ENTRY NextLink;
|
|
PPS_WAN_LINK WanLink;
|
|
PADAPTER AdapterInList;
|
|
|
|
*PsWanLink = NULL;
|
|
|
|
PS_LOCK(&AdapterListLock);
|
|
|
|
NextAdapter = AdapterList.Flink;
|
|
|
|
while(NextAdapter != &AdapterList){
|
|
|
|
AdapterInList = CONTAINING_RECORD(NextAdapter, ADAPTER, Linkage);
|
|
|
|
PS_LOCK_DPC(&AdapterInList->Lock);
|
|
|
|
//
|
|
// If it's closing, blow right by it.
|
|
//
|
|
|
|
if(AdapterInList->PsMpState != AdapterStateRunning)
|
|
{
|
|
PS_UNLOCK_DPC(&AdapterInList->Lock);
|
|
|
|
NextAdapter = NextAdapter->Flink;
|
|
|
|
continue;
|
|
}
|
|
|
|
if(AdapterInList->MediaType != NdisMediumWan)
|
|
{
|
|
|
|
if(StringLength == AdapterInList->WMIInstanceName.Length){
|
|
|
|
//
|
|
// At least they are of equal length.
|
|
//
|
|
|
|
if(NdisEqualMemory(StringStart,
|
|
AdapterInList->WMIInstanceName.Buffer,
|
|
StringLength)){
|
|
|
|
REFADD(&AdapterInList->RefCount, 'ADVC');
|
|
|
|
PS_UNLOCK_DPC(&AdapterInList->Lock);
|
|
|
|
PS_UNLOCK(&AdapterListLock);
|
|
|
|
return(AdapterInList);
|
|
}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
if(AdapterInList->WanBindingState & WAN_ADDR_FAMILY_OPEN)
|
|
{
|
|
//
|
|
// Wan adapters are searched by the name stored with
|
|
// their links.
|
|
//
|
|
|
|
NextLink = AdapterInList->WanLinkList.Flink;
|
|
|
|
while(NextLink != &AdapterInList->WanLinkList){
|
|
|
|
WanLink = CONTAINING_RECORD(NextLink, PS_WAN_LINK, Linkage);
|
|
|
|
if(WanLink->State == WanStateOpen)
|
|
{
|
|
|
|
if(StringLength == WanLink->InstanceName.Length){
|
|
|
|
//
|
|
// At least they are of equal length.
|
|
//
|
|
|
|
if(NdisEqualMemory(StringStart,
|
|
WanLink->InstanceName.Buffer,
|
|
StringLength)){
|
|
|
|
REFADD(&AdapterInList->RefCount, 'ADVC');
|
|
REFADD(&WanLink->RefCount, 'WANV');
|
|
|
|
PS_UNLOCK_DPC(&AdapterInList->Lock);
|
|
PS_UNLOCK(&AdapterListLock);
|
|
*PsWanLink = WanLink;
|
|
return(AdapterInList);
|
|
}
|
|
}
|
|
}
|
|
|
|
NextLink = NextLink->Flink;
|
|
}
|
|
}
|
|
}
|
|
|
|
PS_UNLOCK_DPC(&AdapterInList->Lock);
|
|
NextAdapter = NextAdapter->Flink;
|
|
|
|
}
|
|
|
|
PS_UNLOCK(&AdapterListLock);
|
|
return NULL;
|
|
|
|
} // FindAdapterByWmiInstanceName
|
|
|
|
VOID
|
|
CleanUpAdapter(
|
|
IN PADAPTER Adapter)
|
|
{
|
|
|
|
NDIS_STATUS Status;
|
|
|
|
PsAssert(KeGetCurrentIrql() < DISPATCH_LEVEL);
|
|
|
|
TcIndicateInterfaceChange(Adapter, 0, NDIS_STATUS_INTERFACE_DOWN);
|
|
|
|
//
|
|
// Close all the VCs
|
|
//
|
|
|
|
CloseAllGpcVcs(Adapter);
|
|
|
|
|
|
//
|
|
// if we have opened an underlying call manager, close it now.
|
|
//
|
|
|
|
if(Adapter->MediaType == NdisMediumWan) {
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
if(Adapter->ShutdownMask & SHUTDOWN_CLOSE_WAN_ADDR_FAMILY){
|
|
|
|
Adapter->ShutdownMask &= ~SHUTDOWN_CLOSE_WAN_ADDR_FAMILY;
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_WAN | DBG_MINIPORT,
|
|
("[CleanupAdapter]: Adapter %08X Closing the WAN address family", Adapter));
|
|
|
|
Status = NdisClCloseAddressFamily(Adapter->WanCmHandle);
|
|
|
|
}
|
|
else
|
|
{
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID
|
|
ClUnbindFromLowerMp(
|
|
OUT PNDIS_STATUS Status,
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_HANDLE UnbindContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Called by NDIS to indicate that an adapter is going away.
|
|
Since this is an integrated call manager/miniport, we will
|
|
have to close the call manager with the adapter. To do so,
|
|
we must first ask the clients of our call manager part to
|
|
close us. We will have to pend until then.
|
|
|
|
Release our reference
|
|
on the adapter and set the closing flag to true to prevent any further
|
|
references from being obtained.
|
|
|
|
Arguments:
|
|
|
|
See the DDK...
|
|
|
|
Return Values:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
|
|
NDIS_STATUS LocalStatus;
|
|
BOOLEAN VirtualMp;
|
|
ULONG ShutdownMask;
|
|
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL | DBG_INIT,
|
|
("[ClUnbindFromLowerMp]: Adapter %08X, %ws, UnbindContext %x \n",
|
|
Adapter,
|
|
Adapter->MpDeviceName.Buffer,
|
|
UnbindContext));
|
|
|
|
PsStructAssert( Adapter );
|
|
PsAssert(!(Adapter->ShutdownMask & SHUTDOWN_UNBIND_CALLED));
|
|
|
|
//
|
|
// If the unbind is not happening from the context of the unload, we need to Make sure that
|
|
// unload waits for this unbind to complete. We do that by setting the DriverUnloadEvent.
|
|
//
|
|
|
|
PS_LOCK(&DriverUnloadLock);
|
|
|
|
DRIVER_COUNTED_BLOCK;
|
|
|
|
PS_UNLOCK(&DriverUnloadLock);
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
if(Adapter->PsMpState == AdapterStateWaiting)
|
|
{
|
|
VirtualMp = FALSE;
|
|
}
|
|
else
|
|
{
|
|
VirtualMp = TRUE;
|
|
}
|
|
|
|
Adapter->PsMpState = AdapterStateClosing;
|
|
|
|
Adapter->ShutdownMask |= SHUTDOWN_UNBIND_CALLED;
|
|
|
|
PsAssert(!(Adapter->ShutdownMask & SHUTDOWN_CLEANUP_ADAPTER));
|
|
|
|
if (Adapter->PendedNdisRequest) {
|
|
PNDIS_REQUEST PendedRequest = (PNDIS_REQUEST)Adapter->PendedNdisRequest;
|
|
|
|
Adapter->PendedNdisRequest = NULL;
|
|
ClRequestComplete(Adapter, PendedRequest, NDIS_STATUS_FAILURE);
|
|
}
|
|
|
|
ShutdownMask = Adapter->ShutdownMask;
|
|
Adapter->ShutdownMask |= SHUTDOWN_CLEANUP_ADAPTER;
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
if ( !(ShutdownMask & SHUTDOWN_CLEANUP_ADAPTER))
|
|
CleanUpAdapter(Adapter);
|
|
|
|
//
|
|
// DeInitialize the device instance if we have been called in the MpInitialize handler.
|
|
//
|
|
if(Adapter->PsNdisHandle)
|
|
{
|
|
//
|
|
// Either the mpinitialize has happened or its in progress. If it is in progress,
|
|
// we need to Wait till it completes.
|
|
//
|
|
|
|
NdisWaitEvent(&Adapter->MpInitializeEvent, 0);
|
|
|
|
//
|
|
// The MpInitialize (that we could have been waiting for in the above step) could have failed :
|
|
// So we need to check this handle again.
|
|
//
|
|
|
|
if(Adapter->PsNdisHandle)
|
|
{
|
|
|
|
*Status = NdisIMDeInitializeDeviceInstance(Adapter->PsNdisHandle);
|
|
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL | DBG_INIT,
|
|
("[ClUnbindFromLowerMp]: Adapter %08X, deiniting device, "
|
|
"status %x\n", Adapter, *Status));
|
|
goto Done;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(VirtualMp)
|
|
{
|
|
//
|
|
// We have never been called in MpInitialize. Try to cancel the NdisIMInitializeDeviceInstance
|
|
// call.
|
|
//
|
|
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL | DBG_INIT,
|
|
("[ClUnbindFromLowerMp]: Adapter %08X, calling NdisIMCancelDeviceInstance with %ws \n",
|
|
Adapter, Adapter->UpperBinding.Buffer));
|
|
|
|
*Status = NdisIMCancelInitializeDeviceInstance(LmDriverHandle, &Adapter->UpperBinding);
|
|
|
|
if(*Status != NDIS_STATUS_SUCCESS)
|
|
{
|
|
//
|
|
// An mpinitialize is in progress or is going to happen soon. Let's wait for it to
|
|
// complete.
|
|
//
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL | DBG_INIT,
|
|
("[ClUnbindFromLowerMp]: Adapter %08X, Waiting for MpInitialize to "
|
|
"finish (NdisIMCancelDeviceInstance failed) \n", Adapter));
|
|
|
|
NdisWaitEvent(&Adapter->MpInitializeEvent, 0);
|
|
|
|
//
|
|
// The MpInitialize (that we could have been waiting for in the above step) could have failed :
|
|
// So we need to check this handle again.
|
|
//
|
|
|
|
if(Adapter->PsNdisHandle)
|
|
{
|
|
*Status = NdisIMDeInitializeDeviceInstance(Adapter->PsNdisHandle);
|
|
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL | DBG_INIT,
|
|
("[ClUnbindFromLowerMp]: Adapter %08X, deiniting device, "
|
|
"status %x\n", Adapter, *Status));
|
|
|
|
goto Done;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Great. We can be assured that we will never get called in the MpInitializeHandler anymore.
|
|
// Proceed to close the binding below.
|
|
//
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Close the open. We have to do this only if we don't call NdisIMDeInitializeDeviceInstance. If
|
|
// we ever call NdisIMDeInitializeDeviceInstance, then we close the open in the MpHalt handler.
|
|
//
|
|
|
|
if(Adapter->LowerMpHandle)
|
|
{
|
|
NdisCloseAdapter(Status, Adapter->LowerMpHandle);
|
|
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL | DBG_INIT,
|
|
("[ClUnbindFromLowerMp]: Adapter %08X, closing adapter, "
|
|
"status %x\n", Adapter, *Status));
|
|
|
|
if (*Status == NDIS_STATUS_PENDING)
|
|
{
|
|
NdisWaitEvent(&Adapter->BlockingEvent, 0);
|
|
NdisResetEvent(&Adapter->BlockingEvent);
|
|
|
|
*Status = Adapter->FinalStatus;
|
|
}
|
|
|
|
REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
PsDbgOut(DBG_CRITICAL_ERROR,
|
|
DBG_PROTOCOL | DBG_INIT,
|
|
("[ClUnbindFromLowerMp]: Adapter %08X, unbind cannot deinit/close adpater \n",
|
|
Adapter));
|
|
|
|
*Status = NDIS_STATUS_FAILURE;
|
|
|
|
PsAssert(0);
|
|
|
|
}
|
|
|
|
Done:
|
|
|
|
PsDbgOut(DBG_INFO,
|
|
DBG_PROTOCOL | DBG_INIT,
|
|
("[ClUnbindFromLowerMp]: Exiting with Status = %08X \n", *Status));
|
|
|
|
DRIVER_COUNTED_UNBLOCK;
|
|
|
|
} // UnbindAdapter
|
|
|
|
|
|
|
|
VOID
|
|
DeleteAdapter(
|
|
PVOID Handle,
|
|
BOOLEAN AdapterListLocked
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Decrement the ref counter associated with this structure. When it goes to
|
|
zero, close the adapter, and delete the memory associated with the struct
|
|
|
|
Arguments:
|
|
|
|
Adapter - pointer to adapter context block
|
|
|
|
Return Value:
|
|
|
|
number of references remaining associated with this structure
|
|
|
|
--*/
|
|
|
|
{
|
|
PADAPTER Adapter = (PADAPTER) Handle;
|
|
|
|
Adapter->PsMpState = AdapterStateClosed;
|
|
|
|
//
|
|
// if we initialized the pipe, tell the scheduler that this pipe is going away
|
|
//
|
|
|
|
if ( Adapter->MediaType != NdisMediumWan && Adapter->ShutdownMask & SHUTDOWN_DELETE_PIPE ) {
|
|
|
|
(*Adapter->PsComponent->DeletePipe)( Adapter->PsPipeContext );
|
|
}
|
|
|
|
if ( Adapter->ShutdownMask & SHUTDOWN_FREE_PS_CONTEXT ) {
|
|
|
|
PsFreePool(Adapter->PsPipeContext);
|
|
}
|
|
|
|
if(Adapter->pDiffServMapping)
|
|
{
|
|
PsFreePool(Adapter->pDiffServMapping);
|
|
}
|
|
|
|
//
|
|
// return packet pool resources
|
|
//
|
|
|
|
if(Adapter->SendPacketPool != 0)
|
|
{
|
|
NdisFreePacketPool(Adapter->SendPacketPool);
|
|
}
|
|
|
|
if(Adapter->RecvPacketPool != 0)
|
|
{
|
|
NdisFreePacketPool(Adapter->RecvPacketPool);
|
|
}
|
|
|
|
if(Adapter->SendBlockPool)
|
|
{
|
|
NdisDestroyBlockPool(Adapter->SendBlockPool);
|
|
}
|
|
|
|
|
|
//
|
|
// free adapter lock from dispatcher DB
|
|
//
|
|
|
|
NdisFreeSpinLock(&Adapter->Lock);
|
|
|
|
//
|
|
// Free various allocations for the adapter, then the adapter
|
|
//
|
|
|
|
if(Adapter->IpNetAddressList){
|
|
PsFreePool(Adapter->IpNetAddressList);
|
|
}
|
|
|
|
if(Adapter->IpxNetAddressList){
|
|
PsFreePool(Adapter->IpxNetAddressList);
|
|
}
|
|
|
|
if(Adapter->MpDeviceName.Buffer) {
|
|
PsFreePool(Adapter->MpDeviceName.Buffer);
|
|
}
|
|
|
|
if(Adapter->UpperBinding.Buffer) {
|
|
PsFreePool(Adapter->UpperBinding.Buffer);
|
|
}
|
|
|
|
if(Adapter->RegistryPath.Buffer) {
|
|
PsFreePool(Adapter->RegistryPath.Buffer);
|
|
}
|
|
|
|
if(Adapter->WMIInstanceName.Buffer) {
|
|
|
|
//
|
|
// We should not call PsFreePool since this memory is allocated by NDIS
|
|
//
|
|
|
|
ExFreePool(Adapter->WMIInstanceName.Buffer);
|
|
}
|
|
|
|
if(Adapter->ProfileName.Buffer) {
|
|
PsFreePool(Adapter->ProfileName.Buffer);
|
|
}
|
|
|
|
if(!AdapterListLocked)
|
|
{
|
|
PS_LOCK(&AdapterListLock);
|
|
|
|
RemoveEntryList(&Adapter->Linkage);
|
|
|
|
PS_UNLOCK(&AdapterListLock);
|
|
}
|
|
else
|
|
{
|
|
RemoveEntryList(&Adapter->Linkage);
|
|
}
|
|
|
|
NdisSetEvent(&Adapter->RefEvent);
|
|
|
|
PsFreePool(Adapter);
|
|
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
ClLowerMpCloseAdapterComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Completion routine for NdisCloseAdapter. All that should be left is to free
|
|
the pool associated with the structure
|
|
|
|
Arguments:
|
|
|
|
See the DDK...
|
|
|
|
Return Values:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PADAPTER Adapter = (PADAPTER)ProtocolBindingContext;
|
|
|
|
PsDbgOut(DBG_TRACE,
|
|
DBG_PROTOCOL,
|
|
("[ClLowerMpCloseAdapterComplete]: Adapter %08X \n", Adapter));
|
|
|
|
PsStructAssert( Adapter );
|
|
|
|
PsAssert(Status == NDIS_STATUS_SUCCESS);
|
|
|
|
Adapter->FinalStatus = Status;
|
|
|
|
Adapter->LowerMpHandle = 0;
|
|
|
|
//
|
|
// Clean up WanLinks. This cannot be done (in CleanUpAdapter) before we call NdisCloseAdapter, because
|
|
// NDIS can unbind us in the middle of an ClStatusIndication, and can cause a race condition. Also, we
|
|
// can all PsDeleteDevice only after this (because we might want to send some status indications.
|
|
//
|
|
|
|
AskWanLinksToClose(Adapter);
|
|
|
|
PsDeleteDevice();
|
|
|
|
NdisSetEvent(&Adapter->BlockingEvent);
|
|
|
|
} // LowerMpCloseAdapterComplete
|
|
|
|
|
|
VOID
|
|
ClUnloadProtocol(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
VOID
|
|
MpHalt(
|
|
IN NDIS_HANDLE MiniportAdapterContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This handler is called on Memphis. It indicates that the PS MP is no more
|
|
and we should avoid calling NdisIMDeInitializeDeviceInstance...
|
|
|
|
Arguments:
|
|
|
|
See the DDK...
|
|
|
|
Return Values:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
|
|
ULONG Status;
|
|
|
|
PsDbgOut(DBG_TRACE, DBG_MINIPORT, ("[MpHalt]: Adapter %08X\n", Adapter));
|
|
|
|
PsStructAssert(Adapter);
|
|
|
|
PsAssert(!(Adapter->ShutdownMask & SHUTDOWN_MPHALT_CALLED));
|
|
PsAssert(!(Adapter->ShutdownMask & SHUTDOWN_PROTOCOL_UNLOAD));
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
//
|
|
// If we ever get called in our unbind handler, we should not call
|
|
// NdisImDeInitializeDeviceInstance.
|
|
//
|
|
|
|
Adapter->ShutdownMask |= SHUTDOWN_MPHALT_CALLED;
|
|
|
|
Adapter->PsMpState = AdapterStateClosing;
|
|
|
|
if(!(Adapter->ShutdownMask & SHUTDOWN_CLEANUP_ADAPTER))
|
|
{
|
|
Adapter->ShutdownMask |= SHUTDOWN_CLEANUP_ADAPTER;
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
CleanUpAdapter(Adapter);
|
|
}
|
|
else
|
|
{
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
}
|
|
|
|
//
|
|
// Close the b/e VC in the mphalt call. This prevents us from taking a lock
|
|
// in the send path. We are assured that we will not get any sends after we
|
|
// get called in the mphalt handler.
|
|
//
|
|
|
|
if(Adapter->MediaType != NdisMediumWan)
|
|
{
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
PS_LOCK_DPC(&Adapter->BestEffortVc.Lock);
|
|
|
|
InternalCloseCall(&Adapter->BestEffortVc);
|
|
}
|
|
|
|
if(Adapter->LowerMpHandle) {
|
|
|
|
NdisCloseAdapter(&Status, Adapter->LowerMpHandle);
|
|
|
|
if(Status == NDIS_STATUS_PENDING) {
|
|
|
|
NdisWaitEvent(&Adapter->BlockingEvent, 0);
|
|
NdisResetEvent(&Adapter->BlockingEvent);
|
|
|
|
Status = Adapter->FinalStatus;
|
|
}
|
|
|
|
REFDEL(&Adapter->RefCount, FALSE, 'NDOP');
|
|
}
|
|
|
|
//
|
|
// Deref for the MpInitialize
|
|
//
|
|
REFDEL(&Adapter->RefCount, FALSE, 'NDHT');
|
|
|
|
}
|
|
|
|
|
|
HANDLE
|
|
GetNdisPipeHandle (
|
|
IN HANDLE PsPipeContext
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Return the NDIS handle for the adapter to the requesting scheduling component.
|
|
|
|
Arguments:
|
|
|
|
PsPipeContext - Pipe context
|
|
|
|
Return Values:
|
|
|
|
Adapter NDIS handle.
|
|
|
|
--*/
|
|
|
|
{
|
|
return ((PADAPTER)PsPipeContext)->PsNdisHandle;
|
|
} // GetNdisPipeHandle
|
|
|
|
|
|
|
|
|
|
STATIC NDIS_STATUS
|
|
FindProfile(
|
|
PNDIS_STRING ProfileName,
|
|
PPS_PROFILE *Profile
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
Find the named profile in the list of profiles
|
|
|
|
Arguments
|
|
|
|
ProfileName - Name of the profile to look for.
|
|
|
|
Return Value:
|
|
NDIS_STATUS_SUCCESS if everything worked ok
|
|
|
|
e--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
PLIST_ENTRY NextComponent;
|
|
PPS_PROFILE PsiInfo;
|
|
|
|
//
|
|
// compare names until we find the right one
|
|
//
|
|
|
|
NextComponent = PsProfileList.Flink;
|
|
while ( NextComponent != &PsProfileList ) {
|
|
|
|
PsiInfo = CONTAINING_RECORD( NextComponent, PS_PROFILE, Links );
|
|
|
|
if ( ProfileName->Length == PsiInfo->ProfileName.Length ) {
|
|
|
|
if ( NdisEqualMemory(
|
|
ProfileName->Buffer,
|
|
PsiInfo->ProfileName.Buffer,
|
|
ProfileName->Length )) {
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
NextComponent = NextComponent->Flink;
|
|
}
|
|
|
|
|
|
if ( NextComponent != &PsProfileList ) {
|
|
|
|
*Profile = PsiInfo;
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
} else {
|
|
|
|
Status = NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
return Status;
|
|
} // FindProfile
|
|
|
|
|
|
|
|
NDIS_STATUS
|
|
InitializeAdapter(
|
|
PADAPTER Adapter,
|
|
PVOID BindContext,
|
|
PNDIS_STRING MpDeviceName,
|
|
PVOID SystemSpecific1)
|
|
{
|
|
NDIS_STATUS LocalStatus;
|
|
PNDIS_STRING PsParamsKey = (PNDIS_STRING) SystemSpecific1;
|
|
|
|
NdisZeroMemory(Adapter, sizeof(ADAPTER));
|
|
|
|
PS_INIT_SPIN_LOCK(&Adapter->Lock);
|
|
REFINIT(&Adapter->RefCount, Adapter, DeleteAdapter);
|
|
REFADD(&Adapter->RefCount, 'NDOP');
|
|
Adapter->PsMpState = AdapterStateInitializing;
|
|
Adapter->BindContext = BindContext;
|
|
Adapter->ShutdownMask = 0;
|
|
|
|
NdisInitializeEvent(&Adapter->BlockingEvent);
|
|
NdisResetEvent(&Adapter->BlockingEvent);
|
|
|
|
NdisInitializeEvent(&Adapter->RefEvent);
|
|
NdisResetEvent(&Adapter->RefEvent);
|
|
|
|
NdisInitializeEvent(&Adapter->LocalRequestEvent);
|
|
NdisResetEvent(&Adapter->LocalRequestEvent);
|
|
|
|
NdisInitializeEvent(&Adapter->MpInitializeEvent);
|
|
NdisResetEvent(&Adapter->MpInitializeEvent);
|
|
|
|
//
|
|
// Initialize the Lists that we are maintaining
|
|
//
|
|
|
|
InitializeListHead(&Adapter->WanLinkList);
|
|
InitializeListHead(&Adapter->GpcClientVcList);
|
|
|
|
|
|
//
|
|
// By default, Adapter comes in RSVP mode
|
|
//
|
|
Adapter->AdapterMode = AdapterModeRsvpFlow;
|
|
|
|
//
|
|
// add adapter on list of known adapters
|
|
//
|
|
|
|
NdisInterlockedInsertTailList(&AdapterList,
|
|
&Adapter->Linkage,
|
|
&AdapterListLock.Lock );
|
|
|
|
PsAddDevice();
|
|
|
|
//
|
|
// We maintain a list of network addresses enabled on
|
|
// each adapter, for IP and for IPX, separately.
|
|
//
|
|
|
|
PsAllocatePool(Adapter->IpNetAddressList,
|
|
sizeof(NETWORK_ADDRESS_LIST),
|
|
PsMiscTag);
|
|
|
|
if(!Adapter->IpNetAddressList)
|
|
{
|
|
goto ERROR_RESOURCES;
|
|
}
|
|
|
|
Adapter->IpNetAddressList->AddressCount = 0;
|
|
|
|
PsAllocatePool(Adapter->IpxNetAddressList,
|
|
sizeof(NETWORK_ADDRESS_LIST),
|
|
PsMiscTag);
|
|
|
|
if(!Adapter->IpxNetAddressList)
|
|
{
|
|
goto ERROR_RESOURCES;
|
|
}
|
|
|
|
Adapter->IpxNetAddressList->AddressCount = 0;
|
|
|
|
|
|
//
|
|
// Allocate a buffer to hold the name of the underlying
|
|
// adpater.
|
|
//
|
|
|
|
Adapter->MpDeviceName.Length = MpDeviceName->Length;
|
|
Adapter->MpDeviceName.MaximumLength = MpDeviceName->MaximumLength;
|
|
|
|
PsAllocatePool(Adapter->MpDeviceName.Buffer,
|
|
MpDeviceName->MaximumLength,
|
|
PsMiscTag);
|
|
|
|
if(Adapter->MpDeviceName.Buffer == NULL)
|
|
{
|
|
goto ERROR_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
|
|
NdisZeroMemory(
|
|
Adapter->MpDeviceName.Buffer,
|
|
Adapter->MpDeviceName.MaximumLength);
|
|
|
|
NdisMoveMemory(
|
|
Adapter->MpDeviceName.Buffer,
|
|
MpDeviceName->Buffer,
|
|
MpDeviceName->Length);
|
|
}
|
|
|
|
//
|
|
// Allocate a buffer to hold PsParams Key. This will be
|
|
// used by the adapter to read external scheduling component
|
|
// specific interface parameters when they register.
|
|
//
|
|
|
|
Adapter->RegistryPath.Length = PsParamsKey->Length;
|
|
Adapter->RegistryPath.MaximumLength = PsParamsKey->MaximumLength;
|
|
|
|
PsAllocatePool(Adapter->RegistryPath.Buffer,
|
|
Adapter->RegistryPath.MaximumLength,
|
|
PsMiscTag);
|
|
|
|
if(Adapter->RegistryPath.Buffer == NULL)
|
|
{
|
|
goto ERROR_RESOURCES;
|
|
}
|
|
else
|
|
{
|
|
NdisMoveMemory(
|
|
Adapter->RegistryPath.Buffer,
|
|
PsParamsKey->Buffer,
|
|
PsParamsKey->MaximumLength);
|
|
}
|
|
|
|
//
|
|
// Read the per adapter registry info
|
|
//
|
|
|
|
LocalStatus = PsReadAdapterRegistryDataInit(Adapter,
|
|
(PNDIS_STRING)SystemSpecific1);
|
|
|
|
if(LocalStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_PROTOCOL | DBG_INIT,
|
|
("[InitializeAdapter]: Couldn't get registry data %ws (Status = %08X) \n",
|
|
MpDeviceName->Buffer, LocalStatus));
|
|
|
|
return LocalStatus;
|
|
}
|
|
|
|
LocalStatus = PsReadAdapterRegistryData(Adapter,
|
|
&MachineRegistryKey,
|
|
(PNDIS_STRING)SystemSpecific1);
|
|
|
|
if(LocalStatus != NDIS_STATUS_SUCCESS)
|
|
{
|
|
PsDbgOut(DBG_FAILURE,
|
|
DBG_PROTOCOL | DBG_INIT,
|
|
("[InitializeAdapter]: Couldn't get registry data %ws (Status = %08X) \n",
|
|
MpDeviceName->Buffer, LocalStatus));
|
|
}
|
|
|
|
return LocalStatus;
|
|
|
|
ERROR_RESOURCES:
|
|
PsAdapterWriteEventLog(
|
|
(ULONG)EVENT_PS_RESOURCE_POOL,
|
|
0,
|
|
MpDeviceName,
|
|
0,
|
|
NULL);
|
|
|
|
return NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
|
|
NDIS_STATUS
|
|
FindSchedulingComponent(
|
|
PNDIS_STRING ComponentName,
|
|
PPSI_INFO *Component
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Find the named component in the list of external scheduling components
|
|
|
|
Arguments:
|
|
|
|
ComponentName - name of component to look for
|
|
|
|
Return Value:
|
|
|
|
NDIS_STATUS_SUCCESS if everything worked ok
|
|
|
|
--*/
|
|
|
|
{
|
|
NDIS_STATUS Status;
|
|
PLIST_ENTRY NextComponent;
|
|
PPSI_INFO PsiInfo;
|
|
|
|
//
|
|
// get the list lock and compare names until we find the right one
|
|
//
|
|
|
|
|
|
NextComponent = PsComponentList.Flink;
|
|
while ( NextComponent != &PsComponentList ) {
|
|
|
|
PsiInfo = CONTAINING_RECORD( NextComponent, PSI_INFO, Links );
|
|
|
|
if ( ComponentName->Length == PsiInfo->ComponentName.Length ) {
|
|
|
|
if ( NdisEqualMemory(
|
|
ComponentName->Buffer,
|
|
PsiInfo->ComponentName.Buffer,
|
|
ComponentName->Length )) {
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
NextComponent = NextComponent->Flink;
|
|
}
|
|
|
|
if ( NextComponent != &PsComponentList ) {
|
|
|
|
*Component = PsiInfo;
|
|
Status = NDIS_STATUS_SUCCESS;
|
|
} else {
|
|
|
|
Status = NDIS_STATUS_FAILURE;
|
|
}
|
|
|
|
return Status;
|
|
} // FindSchedulingComponent
|
|
|
|
VOID
|
|
CloseAllGpcVcs(
|
|
PADAPTER Adapter
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Close all the VCs associated with an adapter
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
PGPC_CLIENT_VC Vc;
|
|
PLIST_ENTRY NextVc;
|
|
|
|
|
|
//
|
|
// Close all the GPC client VCs.
|
|
//
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
NextVc = Adapter->GpcClientVcList.Flink;
|
|
|
|
while(NextVc != &Adapter->GpcClientVcList)
|
|
{
|
|
Vc = CONTAINING_RECORD(NextVc, GPC_CLIENT_VC, Linkage);
|
|
|
|
PsAssert(Vc);
|
|
|
|
PS_LOCK_DPC(&Vc->Lock);
|
|
|
|
if(Vc->ClVcState == CL_INTERNAL_CLOSE_PENDING || Vc->Flags & INTERNAL_CLOSE_REQUESTED)
|
|
{
|
|
PS_UNLOCK_DPC(&Vc->Lock);
|
|
|
|
NextVc = NextVc->Flink;
|
|
}
|
|
else
|
|
{
|
|
InternalCloseCall(Vc);
|
|
|
|
PS_LOCK(&Adapter->Lock);
|
|
|
|
//
|
|
// Sigh. We can't really get hold to the NextVc in a reliable manner. When we call
|
|
// InternalCloseCall on the Vc, it releases the Adapter Lock (since it might have to
|
|
// make calls into NDIS). Now, in this window, the next Vc could go away, and we
|
|
// could point to a stale Vc. So, we start at the head of the list.
|
|
// Note that this can never lead to a infinite loop, since we don't process the
|
|
// internal close'd VCs repeatedly.
|
|
//
|
|
|
|
NextVc = Adapter->GpcClientVcList.Flink;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
PS_UNLOCK(&Adapter->Lock);
|
|
|
|
} // CloseAllGpcVcs
|
|
|
|
VOID
|
|
PsAdapterWriteEventLog(
|
|
IN NDIS_STATUS EventCode,
|
|
IN ULONG UniqueEventValue,
|
|
IN PNDIS_STRING DeviceName,
|
|
IN ULONG DataSize,
|
|
IN PVOID Data OPTIONAL
|
|
)
|
|
|
|
{
|
|
|
|
//
|
|
// The String List is the device name, and it has a \Device against it.
|
|
//
|
|
PWCHAR StringList[1];
|
|
NDIS_STRING Prefix = NDIS_STRING_CONST("\\Device\\");
|
|
|
|
if(DeviceName->Length > Prefix.Length)
|
|
{
|
|
StringList[0] = (PWCHAR) ((PUCHAR) DeviceName->Buffer + Prefix.Length);
|
|
|
|
NdisWriteEventLogEntry(PsDriverObject,
|
|
EventCode,
|
|
UniqueEventValue,
|
|
1,
|
|
&StringList,
|
|
DataSize,
|
|
Data);
|
|
}
|
|
}
|
|
|
|
/* end adapter.c */
|