windows-nt/Source/XPSP1/NT/net/atm/rawwan/sys/ndisbind.c
2020-09-26 16:20:57 +08:00

1604 lines
29 KiB
C

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
D:\nt\private\ntos\tdi\rawwan\core\ndisbind.c
Abstract:
NDIS entry points and helper routines for binding, unbinding, opening
and closing adapters.
Revision History:
Who When What
-------- -------- ----------------------------------------------
arvindm 05-02-97 Created
Notes:
--*/
#include <precomp.h>
#define _FILENUMBER 'DNIB'
VOID
RWanNdisBindAdapter(
OUT PNDIS_STATUS pStatus,
IN NDIS_HANDLE BindContext,
IN PNDIS_STRING pDeviceName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2
)
/*++
Routine Description:
This is the NDIS protocol entry point for binding to an adapter.
We open the adapter and see if it is one of the supported types.
Action continues when we get notified of a Call Manager that
has registered support for an Address Family.
Arguments:
pStatus - Place to return status of this call
BindContext - Used to complete this call, if we pend it.
pDeviceName - Name of adapter we are asked to bind to.
SystemSpecific1 - Handle to use to access configuration information
SystemSpecific2 - Not used
Return Value:
None directly. But we set *pStatus to NDIS_STATUS_PENDING if we
made the call to open the adapter, NDIS_STATUS_NOT_RECOGNIZED
if this adapter isn't one of the supported media types, NDIS_STATUS_RESOURCES
if we hit any allocation failures.
--*/
{
PRWAN_NDIS_ADAPTER pAdapter;
PNDIS_MEDIUM pMediaArray;
UINT MediaCount; // Number of media-types we support
NDIS_STATUS Status;
NDIS_STATUS OpenStatus;
ULONG TotalLength;
RWANDEBUGP(DL_LOUD, DC_BIND,
("BindAdapter: Context x%x, Device %Z, SS1 x%x, SS2 x%x\n",
BindContext, pDeviceName, SystemSpecific1, SystemSpecific2));
#if DBG
if (RWanSkipAll)
{
RWANDEBUGP(DL_ERROR, DC_WILDCARD,
("BindAdapter: bailing out!\n"));
*pStatus = NDIS_STATUS_NOT_RECOGNIZED;
return;
}
#endif // DBG
//
// Initialize.
//
pAdapter = NULL_PRWAN_NDIS_ADAPTER;
pMediaArray = NULL;
do
{
//
// Allocate an Adapter structure, along with space for the device
// name.
//
TotalLength = sizeof(RWAN_NDIS_ADAPTER) + (pDeviceName->MaximumLength)*sizeof(WCHAR);
RWAN_ALLOC_MEM(pAdapter, RWAN_NDIS_ADAPTER, TotalLength);
if (pAdapter == NULL_PRWAN_NDIS_ADAPTER)
{
RWANDEBUGP(DL_WARN, DC_BIND,
("BindAdapter: Couldnt allocate adapter (%d bytes)\n", TotalLength));
Status = NDIS_STATUS_RESOURCES;
break;
}
//
// Get the list of NDIS media that we support.
//
pMediaArray = RWanGetSupportedMedia(&MediaCount);
if (pMediaArray == NULL)
{
RWANDEBUGP(DL_WARN, DC_BIND,
("BindAdapter: Couldnt get supported media list!\n"));
Status = NDIS_STATUS_NOT_RECOGNIZED;
break;
}
//
// Initialize the Adapter.
//
RWAN_ZERO_MEM(pAdapter, TotalLength);
RWAN_SET_SIGNATURE(pAdapter, nad);
RWAN_INIT_LIST(&(pAdapter->AfList));
RWAN_INIT_LOCK(&(pAdapter->Lock));
pAdapter->pMediaArray = pMediaArray;
pAdapter->BindContext = BindContext;
//
// Copy in the device name.
//
pAdapter->DeviceName.Buffer = (PWCHAR)((PUCHAR)pAdapter + sizeof(RWAN_NDIS_ADAPTER));
pAdapter->DeviceName.MaximumLength = pDeviceName->MaximumLength;
pAdapter->DeviceName.Length = pDeviceName->Length;
RWAN_COPY_MEM(pAdapter->DeviceName.Buffer, pDeviceName->Buffer, pDeviceName->Length);
pAdapter->State = RWANS_AD_OPENING;
//
// Link this adapter to the global list of adapters.
//
RWAN_ACQUIRE_GLOBAL_LOCK();
RWAN_INSERT_HEAD_LIST(&(pRWanGlobal->AdapterList),
&(pAdapter->AdapterLink));
pRWanGlobal->AdapterCount++;
RWAN_RELEASE_GLOBAL_LOCK();
//
// Open the Adapter.
//
NdisOpenAdapter(
&Status,
&OpenStatus,
&(pAdapter->NdisAdapterHandle),
&(pAdapter->MediumIndex), // place to return selected medium index
pMediaArray, // List of media types we support
MediaCount, // Length of above list
pRWanGlobal->ProtocolHandle,
(NDIS_HANDLE)pAdapter, // our context for the adapter binding
pDeviceName,
0, // open options (none)
(PSTRING)NULL // Addressing info (none)
);
if (Status != NDIS_STATUS_PENDING)
{
RWanNdisOpenAdapterComplete(
(NDIS_HANDLE)pAdapter,
Status,
OpenStatus
);
}
Status = NDIS_STATUS_PENDING;
break;
}
while (FALSE);
if (Status != NDIS_STATUS_PENDING)
{
//
// Failed somewhere; clean up.
//
if (pAdapter != NULL_PRWAN_NDIS_ADAPTER)
{
RWAN_FREE_MEM(pAdapter);
}
if (pMediaArray != NULL)
{
RWAN_FREE_MEM(pMediaArray);
}
}
*pStatus = Status;
RWANDEBUGP(DL_LOUD, DC_BIND,
("BindAdapter: pAdapter x%x, returning x%x\n", pAdapter, Status));
return;
}
VOID
RWanNdisUnbindAdapter(
OUT PNDIS_STATUS pStatus,
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE UnbindContext
)
/*++
Routine Description:
This is the NDIS protocol entry point for unbinding from an adapter
that we have opened.
Arguments:
pStatus - Place to return status of this call
ProtocolBindingContext - Our context for the bound adapter
UnbindContext - To be used when we complete the unbind.
Return Value:
None. We set *pStatus to NDIS_STATUS_PENDING.
--*/
{
PRWAN_NDIS_ADAPTER pAdapter;
PLIST_ENTRY pAfEntry;
PLIST_ENTRY pNextAfEntry;
PRWAN_NDIS_AF pAf;
pAdapter = (PRWAN_NDIS_ADAPTER)ProtocolBindingContext;
RWAN_STRUCT_ASSERT(pAdapter, nad);
RWANDEBUGP(DL_WARN, DC_BIND,
("UnbindAdapter: pAdapter x%x, State x%x\n", pAdapter, pAdapter->State));
RWAN_ACQUIRE_ADAPTER_LOCK(pAdapter);
//
// Store away the unbind context for use in completing this
// unbind later.
//
pAdapter->BindContext = UnbindContext;
RWAN_SET_BIT(pAdapter->Flags, RWANF_AD_UNBIND_PENDING);
*pStatus = NDIS_STATUS_PENDING;
if (RWAN_IS_LIST_EMPTY(&(pAdapter->AfList)))
{
RWanCloseAdapter(pAdapter);
//
// Lock is released within the above.
//
}
else
{
//
// Shut down all AFs on this adapter. We release the lock
// early since we are unbinding and don't expect any other
// events now.
//
RWAN_RELEASE_ADAPTER_LOCK(pAdapter);
for (pAfEntry = pAdapter->AfList.Flink;
pAfEntry != &(pAdapter->AfList);
pAfEntry = pNextAfEntry)
{
pNextAfEntry = pAfEntry->Flink;
pAf = CONTAINING_RECORD(pAfEntry, RWAN_NDIS_AF, AfLink);
RWanShutdownAf(pAf);
}
}
return;
}
VOID
RWanNdisOpenAdapterComplete(
IN NDIS_HANDLE ProtocolContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus
)
/*++
Routine Description:
This is the NDIS Entry point called when a previous call we made
to NdisOpenAdapter has completed.
Arguments:
ProtocolContext - our context for the adapter being opened,
which is a pointer to our Adapter structure.
Status - Final status of NdisOpenAdapter
OpenErrorStatus - Error code in case of failure
Return Value:
None
--*/
{
PRWAN_NDIS_ADAPTER pAdapter;
NDIS_HANDLE BindContext;
PNDIS_MEDIUM pMediaArray;
pAdapter = (PRWAN_NDIS_ADAPTER)ProtocolContext;
RWAN_STRUCT_ASSERT(pAdapter, nad);
BindContext = pAdapter->BindContext;
pMediaArray = pAdapter->pMediaArray;
if (Status == NDIS_STATUS_SUCCESS)
{
RWAN_ACQUIRE_ADAPTER_LOCK(pAdapter);
pAdapter->Medium = pMediaArray[pAdapter->MediumIndex];
pAdapter->State = RWANS_AD_OPENED;
RWAN_RELEASE_ADAPTER_LOCK(pAdapter);
}
else
{
//
// Remove this adapter from the global list.
//
//
RWAN_ACQUIRE_GLOBAL_LOCK();
RWAN_DELETE_FROM_LIST(&(pAdapter->AdapterLink));
pRWanGlobal->AdapterCount--;
RWAN_RELEASE_GLOBAL_LOCK();
RWAN_FREE_MEM(pAdapter);
}
RWAN_FREE_MEM(pMediaArray);
RWANDEBUGP(DL_INFO, DC_BIND, ("OpenAdapterComplete: pAdapter x%x, Status x%x\n",
pAdapter, Status));
//
// Now complete the BindAdapter that we had pended.
//
NdisCompleteBindAdapter(
BindContext,
Status,
OpenErrorStatus
);
return;
}
VOID
RWanNdisCloseAdapterComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status
)
/*++
Routine Description:
This is the NDIS entry point signifying completion of a pended call
to NdisCloseAdapter. If we were unbinding from the adapter, complete
the unbind now.
Arguments:
ProtocolBindingContext - our context for an adapter binding,
which is a pointer to our Adapter structure.
Status - Final status of NdisCloseAdapter
Return Value:
None
--*/
{
PRWAN_NDIS_ADAPTER pAdapter;
NDIS_HANDLE UnbindContext;
RWAN_ASSERT(Status == NDIS_STATUS_SUCCESS);
pAdapter = (PRWAN_NDIS_ADAPTER)ProtocolBindingContext;
RWAN_STRUCT_ASSERT(pAdapter, nad);
//
// Unlink this adapter from the global list of adapters.
//
RWAN_ACQUIRE_GLOBAL_LOCK();
RWAN_DELETE_FROM_LIST(&(pAdapter->AdapterLink));
pRWanGlobal->AdapterCount--;
RWAN_RELEASE_GLOBAL_LOCK();
UnbindContext = pAdapter->BindContext;
RWAN_FREE_MEM(pAdapter);
//
// We would have closed the adapter because of one of the following:
// 1. NDIS told us to Unbind from the adapter -> complete the Unbind
// 2. We are unloading -> continue this process
//
if (UnbindContext != NULL)
{
NdisCompleteUnbindAdapter(
UnbindContext,
NDIS_STATUS_SUCCESS
);
}
else
{
//
// We are here because our Unload handler got called.
// Wake up the thread that's waiting for this adapter
// to be closed.
//
RWAN_SIGNAL_EVENT_STRUCT(&pRWanGlobal->Event, Status);
}
return;
}
VOID
RWanNdisAfRegisterNotify(
IN NDIS_HANDLE ProtocolContext,
IN PCO_ADDRESS_FAMILY pAddressFamily
)
/*++
Routine Description:
This is the NDIS entry point to announce the presence of a
Call manager supporting a specified Address Family on an
adapter that we are bound to.
If this address family is one that we support, we create an
AF block, and open the address family.
Arguments:
ProtocolContext - our context for an adapter binding,
which is a pointer to our Adapter structure.
pAddressFamily - pointer to structure describing the Address Family
Return Value:
None
--*/
{
PRWAN_NDIS_ADAPTER pAdapter;
NDIS_STATUS Status;
PLIST_ENTRY pAfInfoEntry;
PRWAN_NDIS_AF_INFO pAfInfo;
PRWAN_NDIS_AF pAf;
BOOLEAN bFound;
pAdapter = (PRWAN_NDIS_ADAPTER)ProtocolContext;
RWAN_STRUCT_ASSERT(pAdapter, nad);
do
{
//
// Create a new NDIS AF block.
//
pAf = RWanAllocateAf();
if (pAf == NULL)
{
break;
}
pAf->pAdapter = pAdapter;
RWanReferenceAf(pAf); // Open AF ref
//
// Search for an AF_INFO structure matching this <NDIS AF, Medium>
// pair.
//
bFound = FALSE;
RWAN_ACQUIRE_GLOBAL_LOCK();
for (pAfInfoEntry = pRWanGlobal->AfInfoList.Flink;
pAfInfoEntry != &(pRWanGlobal->AfInfoList);
pAfInfoEntry = pAfInfoEntry->Flink)
{
pAfInfo = CONTAINING_RECORD(pAfInfoEntry, RWAN_NDIS_AF_INFO, AfInfoLink);
if ((pAfInfo->AfChars.Medium == pAdapter->Medium)
&&
(RWAN_EQUAL_MEM(pAddressFamily,
&(pAfInfo->AfChars.AddressFamily),
sizeof(*pAddressFamily))))
{
bFound = TRUE;
pAf->pAfInfo = pAfInfo;
RWAN_INSERT_TAIL_LIST(&(pAfInfo->NdisAfList),
&(pAf->AfInfoLink));
break;
}
}
RWAN_RELEASE_GLOBAL_LOCK();
if (!bFound)
{
RWAN_FREE_MEM(pAf);
break;
}
//
// Open the Address Family.
//
Status = NdisClOpenAddressFamily(
pAdapter->NdisAdapterHandle,
pAddressFamily,
(NDIS_HANDLE)pAf,
&RWanNdisClientCharacteristics,
sizeof(RWanNdisClientCharacteristics),
&(pAf->NdisAfHandle)
);
if (Status != NDIS_STATUS_PENDING)
{
RWanNdisOpenAddressFamilyComplete(
Status,
(NDIS_HANDLE)pAf,
pAf->NdisAfHandle
);
}
break;
}
while (FALSE);
return;
}
VOID
RWanNdisOpenAddressFamilyComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE ProtocolAfContext,
IN NDIS_HANDLE NdisAfHandle
)
/*++
Routine Description:
This is the NDIS entry point signifying completion of a call
we made to NdisClOpenAddressFamily. If the Address Family open
was successful, we store the returned handle in our AF block.
Otherwise we delete the AF block.
Arguments:
Status - Final status of NdisClOpenAddressFamily
ProtocolAfContext - Our context for an AF open, which is a pointer
to an RWAN_NDIS_AF structure
NdisAfHandle - If successful, this is the handle we should use
to refer to this AF henceforth
Return Value:
None
--*/
{
PRWAN_NDIS_AF pAf;
NDIS_HANDLE NdisAdapterHandle;
PRWAN_NDIS_AF_INFO pAfInfo;
INT rc;
RWAN_STATUS RWanStatus;
ULONG MaxMsgSize;
pAf = (PRWAN_NDIS_AF)ProtocolAfContext;
RWAN_STRUCT_ASSERT(pAf, naf);
RWAN_ACQUIRE_AF_LOCK(pAf);
if (Status == NDIS_STATUS_SUCCESS)
{
pAf->NdisAfHandle = NdisAfHandle;
NdisAdapterHandle = pAf->pAdapter->NdisAdapterHandle;
pAfInfo = pAf->pAfInfo;
RWAN_RELEASE_AF_LOCK(pAf);
//
// Tell the AF-specific module about this successful AF open,
// so that it can initialize and return its context for this open.
//
RWanStatus = (*pAfInfo->AfChars.pAfSpOpenAf)(
pAfInfo->AfSpContext,
(RWAN_HANDLE)pAf,
&pAf->AfSpAFContext,
&MaxMsgSize
);
if (RWanStatus != RWAN_STATUS_PENDING)
{
RWanAfSpOpenAfComplete(
RWanStatus,
(RWAN_HANDLE)pAf,
pAf->AfSpAFContext,
MaxMsgSize
);
}
}
else
{
RWANDEBUGP(DL_WARN, DC_WILDCARD,
("OpenAfComplete: Af x%x, bad status x%x\n", pAf, Status));
rc = RWanDereferenceAf(pAf); // Open AF failure
RWAN_ASSERT(rc == 0);
}
return;
}
VOID
RWanShutdownAf(
IN PRWAN_NDIS_AF pAf
)
/*++
Routine Description:
Shut down an AF open: deregister all SAPs and abort all calls.
Arguments:
pAf - Points to NDIS AF block
Return Value:
None
--*/
{
PRWAN_TDI_ADDRESS pAddrObject;
PRWAN_NDIS_SAP pSap;
PLIST_ENTRY pSapEntry;
PLIST_ENTRY pNextSapEntry;
NDIS_HANDLE NdisSapHandle;
NDIS_STATUS Status;
PRWAN_TDI_CONNECTION pConnObject;
PLIST_ENTRY pVcEntry;
PLIST_ENTRY pNextVcEntry;
PRWAN_NDIS_VC pVc;
INT rc;
RWAN_HANDLE AfSpAFContext;
RWAN_STATUS RWanStatus;
//
// Check if we are already closing this AF.
//
RWAN_ACQUIRE_AF_LOCK(pAf);
RWANDEBUGP(DL_LOUD, DC_BIND,
("ShutdownAf: AF x%x, Flags x%x, AfHandle x%x\n", pAf, pAf->Flags, pAf->NdisAfHandle));
if (RWAN_IS_BIT_SET(pAf->Flags, RWANF_AF_CLOSING))
{
RWAN_RELEASE_AF_LOCK(pAf);
return;
}
RWAN_SET_BIT(pAf->Flags, RWANF_AF_CLOSING);
//
// Make sure the AF doesn't go away while we are here.
//
RWanReferenceAf(pAf); // temp ref: RWanShutdownAf
//
// Deregister all SAPs.
//
for (pSapEntry = pAf->NdisSapList.Flink;
pSapEntry != &(pAf->NdisSapList);
pSapEntry = pNextSapEntry)
{
pNextSapEntry = pSapEntry->Flink;
pSap = CONTAINING_RECORD(pSapEntry, RWAN_NDIS_SAP, AfLink);
pAddrObject = pSap->pAddrObject;
RWAN_RELEASE_AF_LOCK(pAf);
RWAN_ACQUIRE_ADDRESS_LOCK(pAddrObject);
if (!RWAN_IS_BIT_SET(pSap->Flags, RWANF_SAP_CLOSING))
{
RWAN_SET_BIT(pSap->Flags, RWANF_SAP_CLOSING);
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
NdisSapHandle = pSap->NdisSapHandle;
RWAN_ASSERT(NdisSapHandle != NULL);
Status = NdisClDeregisterSap(NdisSapHandle);
if (Status != NDIS_STATUS_PENDING)
{
RWanNdisDeregisterSapComplete(
Status,
(NDIS_HANDLE)pSap
);
}
}
else
{
//
// This SAP is already closing.
//
RWAN_RELEASE_ADDRESS_LOCK(pAddrObject);
}
RWAN_ACQUIRE_AF_LOCK(pAf);
}
//
// Close all connections on this AF.
//
for (pVcEntry = pAf->NdisVcList.Flink;
pVcEntry != &(pAf->NdisVcList);
pVcEntry = pNextVcEntry)
{
pNextVcEntry = pVcEntry->Flink;
pVc = CONTAINING_RECORD(pVcEntry, RWAN_NDIS_VC, VcLink);
RWAN_STRUCT_ASSERT(pVc, nvc);
pConnObject = pVc->pConnObject;
if (pConnObject != NULL)
{
RWAN_ACQUIRE_CONN_LOCK(pConnObject);
RWanReferenceConnObject(pConnObject); // temp - ShutdownAf
RWAN_RELEASE_CONN_LOCK(pConnObject);
RWAN_RELEASE_AF_LOCK(pAf);
RWAN_ACQUIRE_CONN_LOCK(pConnObject);
rc = RWanDereferenceConnObject(pConnObject); // temp - ShutdownAf
if (rc != 0)
{
RWanDoTdiDisconnect(
pConnObject,
NULL, // pTdiRequest,
NULL, // pTimeout
0, // Flags
NULL, // pDisconnInfo
NULL // pReturnInfo
);
//
// Conn Object lock is released within the above.
//
}
RWAN_ACQUIRE_AF_LOCK(pAf);
}
}
//
// Tell the Media-specific module to clean up because this AF
// is being closed.
//
AfSpAFContext = pAf->AfSpAFContext;
RWAN_RELEASE_AF_LOCK(pAf);
if (AfSpAFContext != NULL)
{
RWAN_ASSERT(pAf->pAfInfo->AfChars.pAfSpCloseAf != NULL);
RWanStatus = (*pAf->pAfInfo->AfChars.pAfSpCloseAf)(AfSpAFContext);
if (RWanStatus != RWAN_STATUS_PENDING)
{
RWanAfSpCloseAfComplete((RWAN_HANDLE)pAf);
}
}
else
{
//
// We don't have to inform the media-specific module.
//
RWanAfSpCloseAfComplete((RWAN_HANDLE)pAf);
}
RWAN_ACQUIRE_AF_LOCK(pAf);
rc = RWanDereferenceAf(pAf); // temp ref: RWanShutdownAf
if (rc != 0)
{
RWAN_RELEASE_AF_LOCK(pAf);
}
//
// else the AF is gone.
//
return;
}
VOID
RWanNdisCloseAddressFamilyComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE OurAfContext
)
/*++
Routine Description:
This is the NDIS entry point signifying completion of
a call to NdisClCloseAddressFamily.
Arguments:
Status - Final status of the Close AF
OurAfContext - Pointer to AF block
Return Value:
None
--*/
{
PRWAN_NDIS_AF pAf;
INT rc;
RWAN_ASSERT(Status == NDIS_STATUS_SUCCESS);
pAf = (PRWAN_NDIS_AF)OurAfContext;
RWAN_STRUCT_ASSERT(pAf, naf);
RWAN_ACQUIRE_AF_LOCK(pAf);
rc = RWanDereferenceAf(pAf); // CloseAfComplete
if (rc != 0)
{
RWAN_RELEASE_AF_LOCK(pAf);
}
return;
}
PNDIS_MEDIUM
RWanGetSupportedMedia(
OUT PULONG pMediaCount
)
/*++
Routine Description:
Return a list of NDIS Media types that we support.
Arguments:
pMediaCount - Place to return the number of media types.
Return Value:
An allocated and filled list of media types. The caller is responsible
for freeing this via RWAN_FREE_MEM.
--*/
{
PNDIS_MEDIUM pMediaArray;
UINT NumMedia;
UINT i;
PLIST_ENTRY pAfInfoEntry;
PRWAN_NDIS_AF_INFO pAfInfo;
pMediaArray = NULL;
do
{
RWAN_ACQUIRE_GLOBAL_LOCK();
//
// An upper bound on the total number of media types supported
// is this:
//
NumMedia = pRWanGlobal->AfInfoCount;
if (NumMedia == 0)
{
break;
}
RWAN_ALLOC_MEM(pMediaArray, NDIS_MEDIUM, NumMedia * sizeof(NDIS_MEDIUM));
if (pMediaArray == NULL)
{
break;
}
NumMedia = 0;
for (pAfInfoEntry = pRWanGlobal->AfInfoList.Flink;
pAfInfoEntry != &(pRWanGlobal->AfInfoList);
pAfInfoEntry = pAfInfoEntry->Flink)
{
NDIS_MEDIUM Medium;
pAfInfo = CONTAINING_RECORD(pAfInfoEntry, RWAN_NDIS_AF_INFO, AfInfoLink);
Medium = pAfInfo->AfChars.Medium;
//
// Check if this medium type is already in the output list.
//
for (i = 0; i < NumMedia; i++)
{
if (pMediaArray[i] == Medium)
{
break;
}
}
if (i == NumMedia)
{
//
// This is the first time we've seen this Medium type.
// Create a new entry.
//
pMediaArray[i] = Medium;
NumMedia++;
}
}
RWAN_RELEASE_GLOBAL_LOCK();
if (NumMedia == 0)
{
RWAN_FREE_MEM(pMediaArray);
pMediaArray = NULL;
}
break;
}
while (FALSE);
*pMediaCount = NumMedia;
return (pMediaArray);
}
VOID
RWanCloseAdapter(
IN PRWAN_NDIS_ADAPTER pAdapter
)
/*++
Routine Description:
Initiate closing an adapter. The caller is assumed to hold
the adapter lock, which will be released here.
Arguments:
pAdapter - Points to adapter to be closed
Return Value:
None
--*/
{
NDIS_HANDLE NdisAdapterHandle;
NDIS_STATUS Status;
NdisAdapterHandle = pAdapter->NdisAdapterHandle;
RWAN_ASSERT(NdisAdapterHandle != NULL);
RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&(pAdapter->AfList)));
pAdapter->State = RWANS_AD_CLOSING;
RWAN_RELEASE_ADAPTER_LOCK(pAdapter);
NdisCloseAdapter(
&Status,
NdisAdapterHandle
);
if (Status != NDIS_STATUS_PENDING)
{
RWanNdisCloseAdapterComplete(
(NDIS_HANDLE)pAdapter,
Status
);
}
}
VOID
RWanNdisRequestComplete(
IN NDIS_HANDLE OurBindingContext,
IN PNDIS_REQUEST pNdisRequest,
IN NDIS_STATUS Status
)
/*++
Routine Description:
This is the NDIS entry point called when a previous pended call
to NdisRequest() has completed. We would have called NdisRequest
on behalf of the media-specific module. Complete it now.
Arguments:
OurBindingContext - Points to our adapter structure
pNdisRequest - Points to completed request
Status - Final status of the request
Return Value:
None
--*/
{
PRWAN_NDIS_ADAPTER pAdapter;
PRWAN_NDIS_REQ_CONTEXT pReqContext;
pAdapter = (PRWAN_NDIS_ADAPTER)OurBindingContext;
RWAN_STRUCT_ASSERT(pAdapter, nad);
pReqContext = (PRWAN_NDIS_REQ_CONTEXT)((PUCHAR)pNdisRequest + sizeof(NDIS_REQUEST));
if (pNdisRequest->RequestType == NdisRequestQueryInformation)
{
(*pReqContext->pAf->pAfInfo->AfChars.pAfSpAdapterRequestComplete)(
Status,
pReqContext->pAf->AfSpAFContext,
pReqContext->AfSpReqContext,
pNdisRequest->RequestType,
pNdisRequest->DATA.QUERY_INFORMATION.Oid,
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength
);
}
else
{
(*pReqContext->pAf->pAfInfo->AfChars.pAfSpAdapterRequestComplete)(
Status,
pReqContext->pAf->AfSpAFContext,
pReqContext->AfSpReqContext,
pNdisRequest->RequestType,
pNdisRequest->DATA.SET_INFORMATION.Oid,
pNdisRequest->DATA.SET_INFORMATION.InformationBuffer,
pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength
);
}
RWAN_FREE_MEM(pNdisRequest);
return;
}
VOID
RWanNdisStatus(
IN NDIS_HANDLE OurBindingContext,
IN NDIS_STATUS GeneralStatus,
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
)
/*++
Routine Description:
Arguments:
Return Value:
None
--*/
{
//
// Ignore this.
//
return;
}
VOID
RWanNdisCoStatus(
IN NDIS_HANDLE OurBindingContext,
IN NDIS_HANDLE OurVcContext OPTIONAL,
IN NDIS_STATUS GeneralStatus,
IN PVOID StatusBuffer,
IN UINT StatusBufferSize
)
/*++
Routine Description:
Arguments:
Return Value:
None
--*/
{
//
// Ignore this.
//
return;
}
VOID
RWanNdisStatusComplete(
IN NDIS_HANDLE OurBindingContext
)
/*++
Routine Description:
Arguments:
Return Value:
None
--*/
{
//
// Ignore this.
//
return;
}
NDIS_STATUS
RWanNdisCoRequest(
IN NDIS_HANDLE OurAfContext,
IN NDIS_HANDLE OurVcContext OPTIONAL,
IN NDIS_HANDLE OurPartyContext OPTIONAL,
IN OUT PNDIS_REQUEST pNdisRequest
)
/*++
Routine Description:
Handle events from the Call Manager.
Arguments:
OurAfContext - Points to our AF structure
OurVcContext - If not NULL, points to our VC structure
OurPartyContext - If not NULL, points to our Party structure
pNdisRequest - Points to request
Return Value:
NDIS_STATUS_SUCCESS if the OID is one that we know about, else
NDIS_STATUS_NOT_RECOGNIZED.
--*/
{
NDIS_STATUS Status;
PRWAN_NDIS_AF pAf;
Status = NDIS_STATUS_SUCCESS;
if (pNdisRequest->RequestType == NdisRequestSetInformation)
{
switch (pNdisRequest->DATA.SET_INFORMATION.Oid)
{
case OID_CO_ADDRESS_CHANGE:
break;
case OID_CO_AF_CLOSE:
//
// The Call manager wants us to shutdown this AF open.
//
pAf = (PRWAN_NDIS_AF)OurAfContext;
RWAN_STRUCT_ASSERT(pAf, naf);
RWanShutdownAf(pAf);
break;
default:
Status = NDIS_STATUS_NOT_RECOGNIZED;
break;
}
}
return (Status);
}
VOID
RWanNdisCoRequestComplete(
IN NDIS_STATUS Status,
IN NDIS_HANDLE OurAfContext,
IN NDIS_HANDLE OurVcContext OPTIONAL,
IN NDIS_HANDLE OurPartyContext OPTIONAL,
IN PNDIS_REQUEST pNdisRequest
)
/*++
Routine Description:
Handle completion of a CO-request we had sent to the Call Manager on
behalf of a media-specific module. Inform the media-specific module
of this completion.
Arguments:
Status - Status of request.
OurAfContext - Points to our AF structure
OurVcContext - If not NULL, points to our VC structure
OurPartyContext - If not NULL, points to our Party structure
pNdisRequest - Points to request
Return Value:
None
--*/
{
PRWAN_NDIS_AF pAf;
PRWAN_NDIS_REQ_CONTEXT pReqContext;
pAf = (PRWAN_NDIS_AF)OurAfContext;
RWAN_STRUCT_ASSERT(pAf, naf);
pReqContext = (PRWAN_NDIS_REQ_CONTEXT)((PUCHAR)pNdisRequest + sizeof(NDIS_REQUEST));
if (pNdisRequest->RequestType == NdisRequestQueryInformation)
{
(*pReqContext->pAf->pAfInfo->AfChars.pAfSpAfRequestComplete)(
Status,
pReqContext->pAf->AfSpAFContext,
pReqContext->AfSpReqContext,
pNdisRequest->RequestType,
pNdisRequest->DATA.QUERY_INFORMATION.Oid,
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer,
pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength
);
}
else
{
(*pReqContext->pAf->pAfInfo->AfChars.pAfSpAfRequestComplete)(
Status,
pReqContext->pAf->AfSpAFContext,
pReqContext->AfSpReqContext,
pNdisRequest->RequestType,
pNdisRequest->DATA.SET_INFORMATION.Oid,
pNdisRequest->DATA.SET_INFORMATION.InformationBuffer,
pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength
);
}
RWAN_FREE_MEM(pNdisRequest);
return;
}
NDIS_STATUS
RWanNdisReset(
IN NDIS_HANDLE OurBindingContext
)
/*++
Routine Description:
Arguments:
Return Value:
None
--*/
{
//
// Ignore this.
//
return (NDIS_STATUS_SUCCESS);
}
VOID
RWanNdisResetComplete(
IN NDIS_HANDLE OurBindingContext,
IN NDIS_STATUS Status
)
/*++
Routine Description:
Arguments:
Return Value:
None
--*/
{
//
// Ignore this.
//
return;
}
NDIS_STATUS
RWanNdisPnPEvent(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNET_PNP_EVENT pNetPnPEvent
)
/*++
Routine Description:
Handle a PnP Event from NDIS. The event structure contains the event
code, includes power-management events and reconfigure events.
Arguments:
ProtocolBindingContext - Pointer to our Adapter structure. Could be
NULL for notification of global config changes
pNetPnPEvent - Points to event structure
Return Value:
NDIS_STATUS_SUCCESS if we processed the event successfully.
NDIS_STATUS_NOT_SUPPORTED for unsupported notifications.
--*/
{
NDIS_STATUS Status;
PRWAN_NDIS_ADAPTER pAdapter;
pAdapter = (PRWAN_NDIS_ADAPTER)ProtocolBindingContext;
switch (pNetPnPEvent->NetEvent)
{
case NetEventSetPower:
Status = RWanNdisPnPSetPower(pAdapter, pNetPnPEvent);
break;
case NetEventQueryPower:
Status = RWanNdisPnPQueryPower(pAdapter, pNetPnPEvent);
break;
case NetEventQueryRemoveDevice:
Status = RWanNdisPnPQueryRemove(pAdapter, pNetPnPEvent);
break;
case NetEventCancelRemoveDevice:
Status = RWanNdisPnPCancelRemove(pAdapter, pNetPnPEvent);
break;
case NetEventReconfigure:
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
case NetEventBindList:
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
default:
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
return (Status);
}
NDIS_STATUS
RWanNdisPnPSetPower(
IN PRWAN_NDIS_ADAPTER pAdapter,
IN PNET_PNP_EVENT pNetPnPEvent
)
/*++
Routine Description:
Handle a Set Power event.
Arguments:
pAdapter - Points to our adapter structure
pNetPnPEvent - Points to event to be processed.
Return Value:
NDIS_STATUS_SUCCESS if we successfully processed this event,
NDIS_STATUS_XXX error code otherwise.
--*/
{
PNET_DEVICE_POWER_STATE pPowerState;
NDIS_STATUS Status;
pPowerState = (PNET_DEVICE_POWER_STATE)pNetPnPEvent->Buffer;
switch (*pPowerState)
{
case NetDeviceStateD0:
Status = NDIS_STATUS_SUCCESS;
break;
default:
//
// We can't suspend, so we ask NDIS to unbind us
// by returning this status:
//
Status = NDIS_STATUS_NOT_SUPPORTED;
break;
}
return (Status);
}
NDIS_STATUS
RWanNdisPnPQueryPower(
IN PRWAN_NDIS_ADAPTER pAdapter,
IN PNET_PNP_EVENT pNetPnPEvent
)
/*++
Routine Description:
Called to see if we allow power to be shut off to the adapter.
Arguments:
pAdapter - Points to our adapter structure
pNetPnPEvent - Points to event to be processed.
Return Value:
NDIS_STATUS_SUCCESS always.
--*/
{
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
RWanNdisPnPQueryRemove(
IN PRWAN_NDIS_ADAPTER pAdapter,
IN PNET_PNP_EVENT pNetPnPEvent
)
/*++
Routine Description:
Called to see if we allow the adapter to be removed.
Arguments:
pAdapter - Points to our adapter structure
pNetPnPEvent - Points to event to be processed.
Return Value:
NDIS_STATUS_SUCCESS always.
--*/
{
return (NDIS_STATUS_SUCCESS);
}
NDIS_STATUS
RWanNdisPnPCancelRemove(
IN PRWAN_NDIS_ADAPTER pAdapter,
IN PNET_PNP_EVENT pNetPnPEvent
)
/*++
Routine Description:
Called to cancel the above remove.
Arguments:
pAdapter - Points to our adapter structure
pNetPnPEvent - Points to event to be processed.
Return Value:
NDIS_STATUS_SUCCESS always.
--*/
{
return (NDIS_STATUS_SUCCESS);
}