/*++
Copyright(c) 1992-2000 Microsoft Corporation
Module Name:
protocol.c
Abstract:
Ndis Intermediate Miniport driver sample. This is a passthru driver.
Author:
Environment:
Revision History:
--*/
#include "precomp.h"
#pragma hdrstop
#define MAX_PACKET_POOL_SIZE 0x0000FFFF
#define MIN_PACKET_POOL_SIZE 0x000000FF
extern struct node *buffer_head;
VOID
PtBindAdapter(
OUT PNDIS_STATUS Status,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING DeviceName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2
)
/*++
Routine Description:
Called by NDIS to bind to a miniport below.
Arguments:
Status - Return status of bind here.
BindContext - Can be passed to NdisCompleteBindAdapter if this call is pended.
DeviceName - Device name to bind to. This is passed to NdisOpenAdapter.
SystemSpecific1 - Can be passed to NdisOpenProtocolConfiguration to read per-binding information
SystemSpecific2 - Unused
Return Value:
NDIS_STATUS_PENDING if this call is pended. In this case call NdisCompleteBindAdapter
to complete.
Anything else Completes this call synchronously
--*/
{
NDIS_HANDLE ConfigHandle = NULL;
PNDIS_CONFIGURATION_PARAMETER Param;
NDIS_STRING DeviceStr = NDIS_STRING_CONST("UpperBindings");
PADAPT pAdapt = NULL;
NDIS_STATUS Sts;
UINT MediumIndex;
ULONG TotalSize;
BOOLEAN LockAllocated = FALSE;
UNREFERENCED_PARAMETER(BindContext);
UNREFERENCED_PARAMETER(SystemSpecific2);
DBGPRINT(("==> Protocol BindAdapter\n"));
do
{
//
// Access the configuration section for our binding-specific
// parameters.
//
NdisOpenProtocolConfiguration(Status,
&ConfigHandle,
SystemSpecific1);
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Read the "UpperBindings" reserved key that contains a list
// of device names representing our miniport instances corresponding
// to this lower binding. Since this is a 1:1 IM driver, this key
// contains exactly one name.
//
// If we want to implement a N:1 mux driver (N adapter instances
// over a single lower binding), then UpperBindings will be a
// MULTI_SZ containing a list of device names - we would loop through
// this list, calling NdisIMInitializeDeviceInstanceEx once for
// each name in it.
//
NdisReadConfiguration(Status,
&Param,
ConfigHandle,
&DeviceStr,
NdisParameterString);
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Allocate memory for the Adapter structure. This represents both the
// protocol context as well as the adapter structure when the miniport
// is initialized.
//
// In addition to the base structure, allocate space for the device
// instance string.
//
TotalSize = sizeof(ADAPT) + Param->ParameterData.StringData.MaximumLength;
NdisAllocateMemoryWithTag(&pAdapt, TotalSize, TAG);
if (pAdapt == NULL)
{
*Status = NDIS_STATUS_RESOURCES;
break;
}
//
// Initialize the adapter structure. We copy in the IM device
// name as well, because we may need to use it in a call to
// NdisIMCancelInitializeDeviceInstance. The string returned
// by NdisReadConfiguration is active (i.e. available) only
// for the duration of this call to our BindAdapter handler.
//
NdisZeroMemory(pAdapt, TotalSize);
pAdapt->DeviceName.MaximumLength = Param->ParameterData.StringData.MaximumLength;
pAdapt->DeviceName.Length = Param->ParameterData.StringData.Length;
pAdapt->DeviceName.Buffer = (PWCHAR)((ULONG_PTR)pAdapt + sizeof(ADAPT));
NdisMoveMemory(pAdapt->DeviceName.Buffer,
Param->ParameterData.StringData.Buffer,
Param->ParameterData.StringData.MaximumLength);
NdisInitializeEvent(&pAdapt->Event);
NdisAllocateSpinLock(&pAdapt->Lock);
LockAllocated = TRUE;
//
// 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 (see also NDIS 5.1 packet stacking).
//
NdisAllocatePacketPoolEx(Status,
&pAdapt->SendPacketPoolHandle,
MIN_PACKET_POOL_SIZE,
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
sizeof(SEND_RSVD));
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
//
// Allocate a packet pool for receives. We need this to indicate receives.
// Same consideration as sends (see also NDIS 5.1 packet stacking).
//
NdisAllocatePacketPoolEx(Status,
&pAdapt->RecvPacketPoolHandle,
MIN_PACKET_POOL_SIZE,
MAX_PACKET_POOL_SIZE - MIN_PACKET_POOL_SIZE,
PROTOCOL_RESERVED_SIZE_IN_PACKET);
if (*Status != NDIS_STATUS_SUCCESS)
{
break;
}
pAdapt->PTDeviceState = NdisDeviceStateD0;
//
// Now open the adapter below and complete the initialization
//
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];
//
// Now ask NDIS to initialize our miniport (upper) edge.
// Set the flag below to synchronize with a possible call
// to our protocol Unbind handler that may come in before
// our miniport initialization happens.
//
pAdapt->MiniportInitPending = TRUE;
NdisInitializeEvent(&pAdapt->MiniportInitEvent);
*Status = NdisIMInitializeDeviceInstanceEx(DriverHandle,
&pAdapt->DeviceName,
pAdapt);
if (*Status != NDIS_STATUS_SUCCESS)
{
DBGPRINT(("BindAdapter: Adapt %p, IMInitializeDeviceInstance error %x\n",
pAdapt, *Status));
break;
}
} while(FALSE);
//
// Close the configuration handle now - see comments above with
// the call to NdisIMInitializeDeviceInstanceEx.
//
if (ConfigHandle != NULL)
{
NdisCloseConfiguration(ConfigHandle);
}
if (*Status != NDIS_STAT