mirror of https://github.com/lianthony/NT4.0
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.
723 lines
16 KiB
723 lines
16 KiB
/*++
|
|
|
|
Copyright (c) 1990-1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
Protocol.c
|
|
|
|
Abstract:
|
|
|
|
This file contains the procedures that makeup most of the NDIS 3.1
|
|
Protocol interface. This interface is what NdisWan exposes to the
|
|
WAN Miniports below. NdisWan is not really a protocol and does not
|
|
do TDI, but is a shim that sits between the protocols and the
|
|
WAN Miniport drivers.
|
|
|
|
|
|
Author:
|
|
|
|
Tony Bell (TonyBe) June 06, 1995
|
|
|
|
Environment:
|
|
|
|
Kernel Mode
|
|
|
|
Revision History:
|
|
|
|
TonyBe 06/06/95 Created
|
|
|
|
--*/
|
|
|
|
#include "wan.h"
|
|
|
|
EXPORT
|
|
VOID
|
|
NdisTapiIndicateStatus(
|
|
IN NDIS_HANDLE BindingContext,
|
|
IN PVOID StatusBuffer,
|
|
IN UINT StatusBufferLength
|
|
);
|
|
|
|
NDIS_STATUS
|
|
DoLineUpWork(
|
|
IN PPROTOCOLCB ProtocolCB
|
|
);
|
|
|
|
NDIS_STATUS
|
|
DoLineDownWork(
|
|
PPROTOCOLCB ProtocolCB
|
|
);
|
|
|
|
NDIS_STATUS
|
|
NdisWanOpenWanAdapter(
|
|
IN PWAN_ADAPTERCB pWanAdapterCB
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status, OpenErrorStatus;
|
|
ULONG SelectedMediumIndex;
|
|
NDIS_MEDIUM MediumArray[] = {NdisMediumWan};
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanOpenAdapter: Enter - AdapterName %ls", pWanAdapterCB->MiniportName.Buffer));
|
|
|
|
//
|
|
// This is the only initialization of this event
|
|
//
|
|
NdisWanInitializeNotificationEvent(&pWanAdapterCB->NotificationEvent);
|
|
|
|
NdisOpenAdapter(&Status,
|
|
&OpenErrorStatus,
|
|
&(pWanAdapterCB->hNdisBindingHandle),
|
|
&SelectedMediumIndex,
|
|
MediumArray,
|
|
sizeof(MediumArray) / sizeof(NDIS_MEDIUM),
|
|
NdisWanCB.hProtocolHandle,
|
|
(NDIS_HANDLE)pWanAdapterCB,
|
|
&(pWanAdapterCB->MiniportName),
|
|
0,
|
|
NULL);
|
|
|
|
if (Status == NDIS_STATUS_PENDING) {
|
|
|
|
NdisWanWaitForNotificationEvent(&pWanAdapterCB->NotificationEvent);
|
|
|
|
Status = pWanAdapterCB->NotificationStatus;
|
|
|
|
NdisWanClearNotificationEvent(&pWanAdapterCB->NotificationEvent);
|
|
}
|
|
|
|
//
|
|
// Medium type must be WAN!
|
|
//
|
|
pWanAdapterCB->MediumType = NdisMediumWan;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanOpenAdapter: Exit"));
|
|
|
|
return (Status);
|
|
}
|
|
|
|
VOID
|
|
NdisWanOpenAdapterComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_STATUS Status,
|
|
IN NDIS_STATUS OpenErrorStatus
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
PWAN_ADAPTERCB pWanAdapterCB = (PWAN_ADAPTERCB)ProtocolBindingContext;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanOpenAdapterComplete: Enter - WanAdapterCB 0x%4.4x", pWanAdapterCB));
|
|
|
|
pWanAdapterCB->NotificationStatus = Status;
|
|
|
|
NdisWanSetNotificationEvent(&pWanAdapterCB->NotificationEvent);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanOpenAdapterComplete: Exit"));
|
|
}
|
|
|
|
VOID
|
|
NdisWanCloseAdapterComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
PWAN_ADAPTERCB pWanAdapterCB = (PWAN_ADAPTERCB)ProtocolBindingContext;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanCloseAdapterComplete: Enter"));
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("WanAdapterCB 0x%4.4x", pWanAdapterCB));
|
|
|
|
pWanAdapterCB->NotificationStatus = Status;
|
|
|
|
NdisWanSetNotificationEvent(&pWanAdapterCB->NotificationEvent);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanCloseAdapterComplete: Exit"));
|
|
}
|
|
|
|
VOID
|
|
NdisWanResetComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanResetComplete: Enter"));
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanResetComplete: Exit"));
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
NdisWanTransferDataComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN PNDIS_PACKET pNdisPacket,
|
|
IN NDIS_STATUS Status,
|
|
IN UINT BytesTransferred
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanTransferDataComplete: Enter"));
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanTransferDataComplete: Exit"));
|
|
}
|
|
|
|
VOID
|
|
NdisWanRequestComplete(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN PNDIS_REQUEST NdisRequest,
|
|
IN NDIS_STATUS Status
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
PWAN_ADAPTERCB pWanAdapterCB = (PWAN_ADAPTERCB)ProtocolBindingContext;
|
|
PWAN_REQUEST pWanRequest = GetWanRequest(pWanAdapterCB, NdisRequest);
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanRequestComplete: Enter - pWanRequest: 0x%8.8x", pWanRequest));
|
|
|
|
pWanRequest->NotificationStatus = Status;
|
|
|
|
switch (pWanRequest->Origin) {
|
|
case NDISTAPI:
|
|
NdisWanTapiRequestComplete(pWanAdapterCB, pWanRequest);
|
|
break;
|
|
|
|
default:
|
|
NdisWanSetNotificationEvent(&pWanRequest->NotificationEvent);
|
|
break;
|
|
|
|
}
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanRequestComplete: Exit"));
|
|
}
|
|
|
|
VOID
|
|
NdisWanIndicateStatus(
|
|
IN NDIS_HANDLE ProtocolBindingContext,
|
|
IN NDIS_STATUS GeneralStatus,
|
|
IN PVOID StatusBuffer,
|
|
IN UINT StatusBufferSize
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
PWAN_ADAPTERCB pWanAdapterCB = (PWAN_ADAPTERCB)ProtocolBindingContext;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanIndicateStatus: Enter"));
|
|
|
|
switch (GeneralStatus) {
|
|
case NDIS_STATUS_WAN_LINE_UP:
|
|
NdisWanLineUpIndication(pWanAdapterCB,
|
|
StatusBuffer,
|
|
StatusBufferSize);
|
|
break;
|
|
|
|
case NDIS_STATUS_WAN_LINE_DOWN:
|
|
NdisWanLineDownIndication(pWanAdapterCB,
|
|
StatusBuffer,
|
|
StatusBufferSize);
|
|
break;
|
|
|
|
case NDIS_STATUS_WAN_FRAGMENT:
|
|
NdisWanFragmentIndication(pWanAdapterCB,
|
|
StatusBuffer,
|
|
StatusBufferSize);
|
|
break;
|
|
|
|
case NDIS_STATUS_TAPI_INDICATION:
|
|
NdisWanTapiIndication(pWanAdapterCB,
|
|
StatusBuffer,
|
|
StatusBufferSize);
|
|
|
|
break;
|
|
|
|
default:
|
|
NdisWanDbgOut(DBG_INFO, DBG_PROTOCOL, ("Unknown Status Indication: 0x%8.8x", GeneralStatus));
|
|
break;
|
|
}
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanIndicateStatus: Exit"));
|
|
}
|
|
|
|
VOID
|
|
NdisWanIndicateStatusComplete(
|
|
IN NDIS_HANDLE BindingContext
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanIndicateStatusComplete: Enter"));
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanIndicateStatusComplete: Exit"));
|
|
}
|
|
|
|
NDIS_STATUS
|
|
DoNewLineUpToProtocol(
|
|
PPROTOCOLCB ProtocolCB
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
PADAPTERCB AdapterCB;
|
|
NDIS_STATUS Status = STATUS_SUCCESS;
|
|
PBUNDLECB BundleCB = ProtocolCB->BundleCB;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoNewLineupToProtocol: Enter"));
|
|
|
|
//
|
|
// Find the adapter that this lineup is for
|
|
//
|
|
NdisAcquireSpinLock(&AdapterCBList.Lock);
|
|
|
|
for (AdapterCB = (PADAPTERCB)AdapterCBList.List.Flink;
|
|
(PVOID)AdapterCB != (PVOID)&AdapterCBList.List;
|
|
AdapterCB = (PADAPTERCB)AdapterCB->Linkage.Flink) {
|
|
|
|
if (NdisWanCompareNdisString(&AdapterCB->AdapterName,
|
|
&ProtocolCB->BindingName)) {
|
|
break;
|
|
|
|
}
|
|
}
|
|
|
|
NdisReleaseSpinLock(&AdapterCBList.Lock);
|
|
|
|
if ((PVOID)AdapterCB != (PVOID)&AdapterCBList.List) {
|
|
|
|
ASSERT(AdapterCB->ProtocolType == ProtocolCB->usProtocolType);
|
|
|
|
ETH_COPY_NETWORK_ADDRESS(ProtocolCB->NdisWanAddress, AdapterCB->NetworkAddress);
|
|
|
|
//
|
|
// Put the protocol index in place
|
|
//
|
|
FillNdisWanProtocolIndex(ProtocolCB->NdisWanAddress, ProtocolCB->hProtocolHandle);
|
|
|
|
//
|
|
// Put the bundle index in place
|
|
//
|
|
FillNdisWanBundleIndex(ProtocolCB->NdisWanAddress, BundleCB->hBundleHandle);
|
|
|
|
NdisZeroMemory(ProtocolCB->TransportAddress, 6);
|
|
FillTransportBundleIndex(ProtocolCB->TransportAddress, BundleCB->hBundleHandle);
|
|
|
|
ProtocolCB->AdapterCB = AdapterCB;
|
|
|
|
Status = DoLineUpToProtocol(ProtocolCB);
|
|
|
|
} else {
|
|
Status = NDISWAN_ERROR_NO_ROUTE;
|
|
NdisWanDbgOut(DBG_FAILURE, DBG_PROTOCOL, ("Adapter not found!"));
|
|
}
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoNewLineupToProtocols: Exit"));
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
DoLineUpToProtocol(
|
|
IN PPROTOCOLCB ProtocolCB
|
|
)
|
|
/*++
|
|
|
|
Routine Name:
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Values:
|
|
|
|
--*/
|
|
{
|
|
NDIS_STATUS Status;
|
|
PDEFERRED_DESC DeferredDesc;
|
|
PADAPTERCB AdapterCB = ProtocolCB->AdapterCB;
|
|
|
|
#if TRY_IMMEDIATE_LINEUP
|
|
if (NdisWanAcquireMiniportLock(AdapterCB)) {
|
|
|
|
NdisAcquireSpinLock(&AdapterCB->Lock);
|
|
|
|
if (IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[StatusIndication])) {
|
|
|
|
NdisReleaseSpinLock(&AdapterCB->Lock);
|
|
|
|
Status = DoLineUpWork(ProtocolCB);
|
|
|
|
NdisWanReleaseMiniportLock(AdapterCB);
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NdisReleaseSpinLock(&AdapterCB->Lock);
|
|
|
|
NdisWanReleaseMiniportLock(AdapterCB);
|
|
}
|
|
#endif
|
|
|
|
NdisAcquireSpinLock(&AdapterCB->Lock);
|
|
|
|
//
|
|
// Queue up a deferred work item
|
|
//
|
|
NdisWanGetDeferredDesc(AdapterCB, &DeferredDesc);
|
|
|
|
DeferredDesc->Context = ProtocolCB;
|
|
DeferredDesc->Type = LineUp;
|
|
|
|
InsertTailDeferredQueue(&AdapterCB->DeferredQueue[StatusIndication],
|
|
DeferredDesc);
|
|
|
|
NdisWanSetDeferred(AdapterCB);
|
|
|
|
NdisReleaseSpinLock(&AdapterCB->Lock);
|
|
|
|
Status = NDIS_STATUS_PENDING;
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
DoLineUpWork(
|
|
PPROTOCOLCB ProtocolCB
|
|
)
|
|
{
|
|
ULONG i, AllocationSize;
|
|
NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
|
|
PNDIS_WAN_LINE_UP LineUpInfo;
|
|
PADAPTERCB AdapterCB = ProtocolCB->AdapterCB;
|
|
PBUNDLECB BundleCB = ProtocolCB->BundleCB;
|
|
PBUNDLE_LINE_UP BundleLineUpInfo = &BundleCB->LineUpInfo;
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoLineupToProtocol: Enter"));
|
|
|
|
ASSERT(AdapterCB != NULL);
|
|
|
|
AllocationSize = sizeof(NDIS_WAN_LINE_UP) +
|
|
ProtocolCB->ulLineUpInfoLength +
|
|
(sizeof(WCHAR) * (MAX_NAME_LENGTH + 1) +
|
|
(2 * sizeof(PVOID)));
|
|
|
|
NdisWanAllocateMemory(&LineUpInfo, AllocationSize);
|
|
|
|
if (LineUpInfo != NULL) {
|
|
NDIS_HANDLE LineUpHandle = ProtocolCB->hTransportHandle;
|
|
|
|
//
|
|
// Fill values that are common to all protocols on this bundle
|
|
//
|
|
LineUpInfo->LinkSpeed = BundleLineUpInfo->BundleSpeed;
|
|
LineUpInfo->MaximumTotalSize = BundleLineUpInfo->ulMaximumTotalSize;
|
|
LineUpInfo->Quality = BundleLineUpInfo->Quality;
|
|
LineUpInfo->SendWindow = BundleLineUpInfo->usSendWindow;
|
|
LineUpInfo->ProtocolType = ProtocolCB->usProtocolType;
|
|
LineUpInfo->DeviceName.Length = 0;
|
|
LineUpInfo->DeviceName.MaximumLength = MAX_NAME_LENGTH + 1;
|
|
LineUpInfo->DeviceName.Buffer = (PWCHAR)((PUCHAR)LineUpInfo +
|
|
sizeof(NDIS_WAN_LINE_UP));
|
|
(ULONG)LineUpInfo->DeviceName.Buffer &= (ULONG)~(sizeof(PVOID) - 1);
|
|
|
|
LineUpInfo->ProtocolBuffer = (PUCHAR)LineUpInfo +
|
|
sizeof(NDIS_WAN_LINE_UP) +
|
|
(sizeof(WCHAR) * (MAX_NAME_LENGTH + 1) +
|
|
sizeof(PVOID));
|
|
(ULONG)LineUpInfo->ProtocolBuffer &= (ULONG)~(sizeof(PVOID) - 1);
|
|
|
|
//
|
|
// The Local address(SRC address in a send), is used
|
|
// to figure out what bundle to send across if the
|
|
// DEST address is a multicast. We use the two high
|
|
// order bytes of the address. The transport uses the
|
|
// other four bytes for a context on receive.
|
|
//
|
|
//
|
|
// The Remote address (DEST address in a send) is what we use to
|
|
// mutilplex sends across our single adapter/binding context.
|
|
// The address has the following format:
|
|
//
|
|
// XX XX XX YY YY ZZ
|
|
//
|
|
// XX = Randomly generated OUI
|
|
// YY = Index into the active bundle connection table to get bundlecb
|
|
// ZZ = Index into the protocol table of a bundle to get protocolcb
|
|
//
|
|
ETH_COPY_NETWORK_ADDRESS(LineUpInfo->RemoteAddress,ProtocolCB->NdisWanAddress);
|
|
ETH_COPY_NETWORK_ADDRESS(LineUpInfo->LocalAddress,ProtocolCB->TransportAddress);
|
|
|
|
//
|
|
// Fill in the protocol specific information
|
|
//
|
|
LineUpInfo->ProtocolBufferLength = ProtocolCB->ulLineUpInfoLength;
|
|
NdisMoveMemory(LineUpInfo->ProtocolBuffer,
|
|
ProtocolCB->LineUpInfo,
|
|
ProtocolCB->ulLineUpInfoLength);
|
|
|
|
//
|
|
// Do the line up indication
|
|
//
|
|
NdisMIndicateStatus(AdapterCB->hMiniportHandle,
|
|
NDIS_STATUS_WAN_LINE_UP,
|
|
LineUpInfo,
|
|
AllocationSize);
|
|
|
|
*((ULONG UNALIGNED *)(&LineUpHandle)) = *((ULONG UNALIGNED *)(&LineUpInfo->LocalAddress[2]));
|
|
|
|
//
|
|
// If this was the first line up for this protocolcb and
|
|
// this lineup was answered we need to collect some info
|
|
//
|
|
if (ProtocolCB->hTransportHandle == NULL) {
|
|
|
|
if (LineUpHandle != NULL) {
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
ETH_COPY_NETWORK_ADDRESS(ProtocolCB->TransportAddress, LineUpInfo->LocalAddress);
|
|
|
|
ProtocolCB->hTransportHandle = LineUpHandle;
|
|
|
|
if (LineUpInfo->DeviceName.Length != 0) {
|
|
NdisWanStringToNdisString(&ProtocolCB->DeviceName,
|
|
LineUpInfo->DeviceName.Buffer);
|
|
}
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
|
|
//
|
|
// If this is an nbf adapter
|
|
//
|
|
if (ProtocolCB->usProtocolType == PROTOCOL_NBF) {
|
|
|
|
ASSERT(AdapterCB->ProtocolType == PROTOCOL_NBF);
|
|
|
|
AdapterCB->NbfBundleCB = BundleCB;
|
|
AdapterCB->NbfProtocolHandle = ProtocolCB->hProtocolHandle;
|
|
}
|
|
|
|
} else {
|
|
Status = NDISWAN_ERROR_NO_ROUTE;
|
|
}
|
|
}
|
|
|
|
NdisWanFreeMemory(LineUpInfo);
|
|
|
|
} else {
|
|
|
|
Status = NDIS_STATUS_RESOURCES;
|
|
}
|
|
|
|
NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoLineupToProtocol: Exit"));
|
|
|
|
return (Status);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
DoLineDownToProtocol(
|
|
PPROTOCOLCB ProtocolCB
|
|
)
|
|
{
|
|
PADAPTERCB AdapterCB = ProtocolCB->AdapterCB;
|
|
PDEFERRED_DESC DeferredDesc;
|
|
|
|
//
|
|
// We are always going to defer the line down. This will
|
|
// allow us to complete all sends and process all loopbacks
|
|
// before doing the linedown.
|
|
//
|
|
NdisAcquireSpinLock(&AdapterCB->Lock);
|
|
|
|
//
|
|
// Queue up a deferred work item
|
|
//
|
|
NdisWanGetDeferredDesc(AdapterCB, &DeferredDesc);
|
|
|
|
DeferredDesc->Context = ProtocolCB;
|
|
DeferredDesc->Type = LineDown;
|
|
|
|
InsertTailDeferredQueue(&AdapterCB->DeferredQueue[StatusIndication],
|
|
DeferredDesc);
|
|
|
|
NdisWanSetDeferred(AdapterCB);
|
|
|
|
NdisReleaseSpinLock(&AdapterCB->Lock);
|
|
|
|
return (NDIS_STATUS_PENDING);
|
|
}
|
|
|
|
NDIS_STATUS
|
|
DoLineDownWork(
|
|
PPROTOCOLCB ProtocolCB
|
|
)
|
|
{
|
|
NDIS_WAN_LINE_DOWN WanLineDown;
|
|
PNDIS_WAN_LINE_DOWN LineDownInfo = &WanLineDown;
|
|
PADAPTERCB AdapterCB = ProtocolCB->AdapterCB;
|
|
|
|
//
|
|
// The Remote address (DEST address) is what we use to mutilplex
|
|
// sends across our single adapter/binding context. The address
|
|
// has the following format:
|
|
//
|
|
// XX XX XX YY YY ZZ
|
|
//
|
|
// XX = Randomly generated OUI
|
|
// YY = Index into the active bundle connection table to get bundlecb
|
|
// ZZ = Index into the protocol table of a bundle to get protocolcb
|
|
//
|
|
ETH_COPY_NETWORK_ADDRESS(LineDownInfo->RemoteAddress, ProtocolCB->NdisWanAddress);
|
|
ETH_COPY_NETWORK_ADDRESS(LineDownInfo->LocalAddress, ProtocolCB->TransportAddress);
|
|
|
|
//
|
|
// If this is an nbf adapter
|
|
//
|
|
if (ProtocolCB->usProtocolType == PROTOCOL_NBF) {
|
|
|
|
ASSERT(AdapterCB->ProtocolType == PROTOCOL_NBF);
|
|
|
|
AdapterCB->NbfBundleCB = NULL;
|
|
|
|
(ULONG)AdapterCB->NbfProtocolHandle = MAX_PROTOCOLS + 1;
|
|
}
|
|
|
|
ProtocolCB->hTransportHandle = NULL;
|
|
|
|
NdisMIndicateStatus(AdapterCB->hMiniportHandle,
|
|
NDIS_STATUS_WAN_LINE_DOWN,
|
|
LineDownInfo,
|
|
sizeof(NDIS_WAN_LINE_DOWN));
|
|
|
|
return (NDIS_STATUS_SUCCESS);
|
|
}
|
|
|
|
VOID
|
|
NdisWanProcessStatusIndications(
|
|
PADAPTERCB AdapterCB
|
|
)
|
|
{
|
|
NDIS_STATUS Status;
|
|
|
|
while (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[StatusIndication])) {
|
|
PPROTOCOLCB ProtocolCB;
|
|
PBUNDLECB BundleCB;
|
|
ULONG DescType;
|
|
PDEFERRED_DESC ReturnDesc;
|
|
|
|
ReturnDesc = RemoveHeadDeferredQueue(&AdapterCB->DeferredQueue[StatusIndication]);
|
|
|
|
NdisReleaseSpinLock(&AdapterCB->Lock);
|
|
|
|
ProtocolCB = ReturnDesc->Context;
|
|
BundleCB= ProtocolCB->BundleCB;
|
|
DescType = ReturnDesc->Type;
|
|
|
|
ASSERT((DescType == LineUp) || (DescType == LineDown));
|
|
|
|
if (DescType == LineUp) {
|
|
Status = DoLineUpWork(ProtocolCB);
|
|
}else {
|
|
Status = DoLineDownWork(ProtocolCB);
|
|
}
|
|
|
|
NdisAcquireSpinLock(&AdapterCB->Lock);
|
|
|
|
InsertHeadDeferredQueue(&AdapterCB->FreeDeferredQueue, ReturnDesc);
|
|
|
|
NdisAcquireSpinLock(&BundleCB->Lock);
|
|
|
|
BundleCB->IndicationStatus = Status;
|
|
|
|
NdisWanSetSyncEvent(&BundleCB->IndicationEvent);
|
|
|
|
NdisReleaseSpinLock(&BundleCB->Lock);
|
|
}
|
|
}
|