Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

838 lines
17 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
D:\nt\private\ntos\tdi\rawwan\core\mediasp.c
Abstract:
Media and Address Family Specific routines. These are exported routines
that a media/AF specific module can call.
Revision History:
Who When What
-------- -------- ----------------------------------------------
arvindm 06-02-97 Created
Notes:
--*/
#include <precomp.h>
#define _FILENUMBER ' DEM'
RWAN_STATUS
RWanInitMediaSpecific(
VOID
)
/*++
Routine Description:
Initialize all media/AF specific modules. For now, we just
run through our list of media-specific Init routines and call
each of them.
Arguments:
None
Return Value:
RWAN_STATUS_SUCCESS if initialization completed successfully for
atleast one module, RWAN_STATUS_FAILURE otherwise.
--*/
{
RWAN_STATUS RWanStatus;
PRWAN_AFSP_MODULE_CHARS pModuleChars;
INT SuccessfulInits;
SuccessfulInits = 0;
for (pModuleChars = &RWanMediaSpecificInfo[0];
pModuleChars->pAfSpInitHandler != NULL;
pModuleChars++)
{
RWanStatus = (*pModuleChars->pAfSpInitHandler)();
if (RWanStatus == RWAN_STATUS_SUCCESS)
{
SuccessfulInits++;
}
}
if (SuccessfulInits > 0)
{
return (RWAN_STATUS_SUCCESS);
}
else
{
return (RWAN_STATUS_FAILURE);
}
}
VOID
RWanShutdownMediaSpecific(
VOID
)
/*++
Routine Description:
Tell all media/AF-specific modules to shut down.
Arguments:
None
Return Value:
None
--*/
{
PRWAN_AFSP_MODULE_CHARS pModuleChars;
for (pModuleChars = &RWanMediaSpecificInfo[0];
pModuleChars->pAfSpInitHandler != NULL;
pModuleChars++)
{
(*pModuleChars->pAfSpShutdownHandler)();
}
}
RWAN_STATUS
RWanAfSpRegisterNdisAF(
IN PRWAN_NDIS_AF_CHARS pAfChars,
IN RWAN_HANDLE AfSpContext,
OUT PRWAN_HANDLE pRWanSpHandle
)
/*++
Routine Description:
This is called by a media-specific module to register support
of an NDIS Address family for a particular medium. The characteristics
structure contains the module's entry points for various media-specific
operations.
We create an AF_INFO structure to keep track of this AF+Medium,
and return a pointer to it as the handle.
Arguments:
pAfChars - Entry points for the module
AfSpContext - The media-specific module's context for this AF+medium
pRWanSpHandle - Place to return our handle for this AF+medium
Return Value:
RWAN_STATUS_SUCCESS if the new NDIS AF+medium was successfully registered,
RWAN_STATUS_RESOURCES if we failed due to lack of resources.
XXX: Check for duplicates?
--*/
{
PRWAN_NDIS_AF_INFO pAfInfo;
RWAN_STATUS RWanStatus;
do
{
RWAN_ALLOC_MEM(pAfInfo, RWAN_NDIS_AF_INFO, sizeof(RWAN_NDIS_AF_INFO));
if (pAfInfo == NULL)
{
RWanStatus = RWAN_STATUS_RESOURCES;
break;
}
RWAN_SET_SIGNATURE(pAfInfo, nai);
pAfInfo->Flags = 0;
RWAN_INIT_LIST(&pAfInfo->NdisAfList);
RWAN_INIT_LIST(&pAfInfo->TdiProtocolList);
RWAN_COPY_MEM(&pAfInfo->AfChars, pAfChars, sizeof(RWAN_NDIS_AF_CHARS));
pAfInfo->AfSpContext = AfSpContext;
RWAN_ACQUIRE_GLOBAL_LOCK();
RWAN_INSERT_HEAD_LIST(&pRWanGlobal->AfInfoList,
&pAfInfo->AfInfoLink);
pRWanGlobal->AfInfoCount++;
RWAN_RELEASE_GLOBAL_LOCK();
*pRWanSpHandle = (RWAN_HANDLE)pAfInfo;
RWanStatus = RWAN_STATUS_SUCCESS;
break;
}
while (FALSE);
return (RWanStatus);
}
RWAN_STATUS
RWanAfSpDeregisterNdisAF(
IN RWAN_HANDLE RWanSpAFHandle
)
/*++
Routine Description:
This is called by a media-specific module to deregister support
of an NDIS Address family for a particular medium.
Arguments:
RWanSpAFHandle - Actually a pointer to an NDIS_AF_INFO block.
Return Value:
RWAN_STATUS_SUCCESS if we successfully completed the deregistration
here, RWAN_STATUS_PENDING if there are open AFs or TDI protocols
on this block.
--*/
{
PRWAN_NDIS_AF_INFO pAfInfo;
RWAN_STATUS RWanStatus;
pAfInfo = (PRWAN_NDIS_AF_INFO)RWanSpAFHandle;
RWAN_STRUCT_ASSERT(pAfInfo, nai);
RWAN_ACQUIRE_GLOBAL_LOCK();
//
// See if all AF blocks and TDI protocols are gone.
//
if (RWAN_IS_LIST_EMPTY(&pAfInfo->TdiProtocolList) &&
RWAN_IS_LIST_EMPTY(&pAfInfo->NdisAfList))
{
RWanStatus = RWAN_STATUS_SUCCESS;
//
// Remove this AF INFO block from the global list.
//
RWAN_DELETE_FROM_LIST(&pAfInfo->AfInfoLink);
//
// Free this AF INFO block.
//
RWAN_FREE_MEM(pAfInfo);
}
else
{
//
// There is still some activity on this AF INFO.
// Pend this request till all these go away.
//
RWanStatus = RWAN_STATUS_PENDING;
RWAN_SET_BIT(pAfInfo->Flags, RWANF_AFI_CLOSING);
RWAN_ASSERT(FALSE);
}
RWAN_RELEASE_GLOBAL_LOCK();
return (RWanStatus);
}
RWAN_STATUS
RWanAfSpRegisterTdiProtocol(
IN RWAN_HANDLE RWanSpHandle,
IN PRWAN_TDI_PROTOCOL_CHARS pTdiChars,
OUT PRWAN_HANDLE pRWanProtHandle
)
/*++
Routine Description:
This is the API called by a media-specific module to register
support for a TDI protocol over an NDIS AF. We create a TDI
Protocol block and a device object to represent this protocol.
Arguments:
RWanSpHandle - Actually a pointer to our NDIS_AF_INFO structure
pTdiChars - Characteristics of the protocol being registered
pRWanProtHandle - Place to return our context for this protocol
Return Value:
RWAN_STATUS_SUCCESS if we successfully registered this TDI protocol,
RWAN_STATUS_XXX error code otherwise.
--*/
{
RWAN_STATUS RWanStatus;
PRWAN_NDIS_AF_INFO pAfInfo;
PRWAN_TDI_PROTOCOL pProtocol;
#ifdef NT
PRWAN_DEVICE_OBJECT pRWanDeviceObject;
NTSTATUS Status;
#endif // NT
pAfInfo = (PRWAN_NDIS_AF_INFO)RWanSpHandle;
RWAN_STRUCT_ASSERT(pAfInfo, nai);
pProtocol = NULL;
pRWanDeviceObject = NULL;
do
{
RWAN_ALLOC_MEM(pProtocol, RWAN_TDI_PROTOCOL, sizeof(RWAN_TDI_PROTOCOL));
if (pProtocol == NULL)
{
RWanStatus = RWAN_STATUS_RESOURCES;
break;
}
RWAN_SET_SIGNATURE(pProtocol, ntp);
pProtocol->pAfInfo = pAfInfo;
pProtocol->TdiProtocol = pTdiChars->TdiProtocol;
pProtocol->SockAddressFamily = pTdiChars->SockAddressFamily;
pProtocol->SockProtocol = pTdiChars->SockProtocol;
pProtocol->TdiProtocol = pTdiChars->TdiProtocol;
pProtocol->SockType = pTdiChars->SockType;
pProtocol->bAllowAddressObjects = pTdiChars->bAllowAddressObjects;
pProtocol->bAllowConnObjects = pTdiChars->bAllowConnObjects;
pProtocol->pAfSpDeregTdiProtocolComplete =
pTdiChars->pAfSpDeregTdiProtocolComplete;
pProtocol->ProviderInfo = pTdiChars->ProviderInfo;
RWAN_INIT_LIST(&pProtocol->AddrObjList);
#ifdef NT
//
// Create an I/O Device on which we can receive IRPs for this
// protocol.
//
RWAN_ALLOC_MEM(pRWanDeviceObject, RWAN_DEVICE_OBJECT, sizeof(RWAN_DEVICE_OBJECT));
if (pRWanDeviceObject == NULL)
{
RWanStatus = RWAN_STATUS_RESOURCES;
break;
}
RWAN_SET_SIGNATURE(pRWanDeviceObject, ndo);
pRWanDeviceObject->pProtocol = pProtocol;
pProtocol->pRWanDeviceObject = (PVOID)pRWanDeviceObject;
//
// Create the device now. A pointer's worth of space is requested
// in the device extension.
//
Status = IoCreateDevice(
pRWanGlobal->pDriverObject,
sizeof(PRWAN_DEVICE_OBJECT),
pTdiChars->pDeviceName,
FILE_DEVICE_NETWORK,
0,
FALSE,
&(pRWanDeviceObject->pDeviceObject)
);
if (!NT_SUCCESS(Status))
{
RWanStatus = RWAN_STATUS_FAILURE;
break;
}
//
// Store a pointer to our device context in the
// NT device object extension.
//
*(PRWAN_DEVICE_OBJECT *)(pRWanDeviceObject->pDeviceObject->DeviceExtension) =
pRWanDeviceObject;
RWAN_ACQUIRE_GLOBAL_LOCK();
RWAN_INSERT_HEAD_LIST(&(pRWanGlobal->DeviceObjList),
&(pRWanDeviceObject->DeviceObjectLink));
//
// Add this Protocol to the list of TDI protocols on the
// AF INFO block.
//
RWAN_INSERT_TAIL_LIST(&(pAfInfo->TdiProtocolList),
&(pProtocol->AfInfoLink));
//
// Add this Protocol to the global list of TDI protocols.
//
RWAN_INSERT_TAIL_LIST(&(pRWanGlobal->ProtocolList),
&(pProtocol->TdiProtocolLink));
pRWanGlobal->ProtocolCount++;
RWAN_RELEASE_GLOBAL_LOCK();
#endif // NT
RWanStatus = RWAN_STATUS_SUCCESS;
*pRWanProtHandle = (RWAN_HANDLE)pProtocol;
break;
}
while (FALSE);
if (RWanStatus != RWAN_STATUS_SUCCESS)
{
if (pProtocol != NULL)
{
RWAN_FREE_MEM(pProtocol);
}
#ifdef NT
if (pRWanDeviceObject != NULL)
{
RWAN_FREE_MEM(pRWanDeviceObject);
}
#endif // NT
}
return (RWanStatus);
}
VOID
RWanAfSpDeregisterTdiProtocol(
IN RWAN_HANDLE RWanProtHandle
)
/*++
Routine Description:
This is the API called by a media-specific module to de-register
support for a TDI protocol. We delete the TDI Protocol block
that holds information about this protocol.
Arguments:
RWanProtHandle - Pointer to the TDI Protocol block
Return Value:
None
--*/
{
PRWAN_TDI_PROTOCOL pProtocol;
PRWAN_NDIS_AF_INFO pAfInfo;
#ifdef NT
PRWAN_DEVICE_OBJECT pRWanDeviceObject;
#endif // NT
pProtocol = (PRWAN_TDI_PROTOCOL)RWanProtHandle;
RWAN_STRUCT_ASSERT(pProtocol, ntp);
RWAN_ASSERT(RWAN_IS_LIST_EMPTY(&pProtocol->AddrObjList));
//
// Unlink this TDI protocol.
//
RWAN_ACQUIRE_GLOBAL_LOCK();
RWAN_DELETE_FROM_LIST(&(pProtocol->TdiProtocolLink));
RWAN_DELETE_FROM_LIST(&(pProtocol->AfInfoLink));
pRWanGlobal->ProtocolCount--;
RWAN_RELEASE_GLOBAL_LOCK();
#ifdef NT
//
// Delete the I/O device we'd created for this protocol.
//
pRWanDeviceObject = (PRWAN_DEVICE_OBJECT)pProtocol->pRWanDeviceObject;
RWAN_ASSERT(pRWanDeviceObject != NULL);
IoDeleteDevice(pRWanDeviceObject->pDeviceObject);
RWAN_FREE_MEM(pRWanDeviceObject);
#endif // NT
RWAN_FREE_MEM(pProtocol);
return;
}
VOID
RWanAfSpOpenAfComplete(
IN RWAN_STATUS RWanStatus,
IN RWAN_HANDLE RWanAfHandle,
IN RWAN_HANDLE AfSpAFContext,
IN ULONG MaxMessageSize
)
/*++
Routine Description:
This is called by an AF-specific module to signify completion
of our call to its OpenAfHandler routine. If the AF-specific module
has successfully set up its context for this AF open, we store
its context for this in our NDIS AF structure.
Otherwise, we tear down this AF.
Arguments:
RWanStatus - Final status of our call to AF-specific module's AfOpen handler
RWanAfHandle - Our context for an NDIS AF Open
AfSpAFContext - AF-Specific module's context for this Open
MaxMessageSize - Max message size for this AF
Return Value:
None
--*/
{
PRWAN_NDIS_AF pAf;
PRWAN_NDIS_ADAPTER pAdapter;
PRWAN_NDIS_AF_INFO pAfInfo;
PLIST_ENTRY pEnt;
PRWAN_TDI_PROTOCOL pTdiProtocol;
pAf = (PRWAN_NDIS_AF)RWanAfHandle;
RWAN_STRUCT_ASSERT(pAf, naf);
pAdapter = pAf->pAdapter;
if (RWanStatus == RWAN_STATUS_SUCCESS)
{
RWAN_ACQUIRE_ADAPTER_LOCK(pAdapter);
RWAN_ACQUIRE_AF_LOCK_DPC(pAf);
pAf->AfSpAFContext = AfSpAFContext;
RWAN_SET_BIT(pAf->Flags, RWANF_AF_IN_ADAPTER_LIST);
//
// Add this AF to the adapter's list of open AFs.
//
RWAN_INSERT_HEAD_LIST(&(pAdapter->AfList),
&(pAf->AfLink));
RWAN_RELEASE_AF_LOCK_DPC(pAf);
#if 0
RWanReferenceAdapter(pAdapter); // AF linkage
#endif
RWAN_RELEASE_ADAPTER_LOCK(pAdapter);
RWAN_ACQUIRE_GLOBAL_LOCK();
pAfInfo = pAf->pAfInfo;
for (pEnt = pAfInfo->TdiProtocolList.Flink;
pEnt != &pAfInfo->TdiProtocolList;
pEnt = pEnt->Flink)
{
pTdiProtocol = CONTAINING_RECORD(pEnt, RWAN_TDI_PROTOCOL, AfInfoLink);
pTdiProtocol->ProviderInfo.MaxSendSize =
MIN(pTdiProtocol->ProviderInfo.MaxSendSize, MaxMessageSize);
}
RWAN_RELEASE_GLOBAL_LOCK();
}
else
{
RWanShutdownAf(pAf);
}
}
VOID
RWanAfSpCloseAfComplete(
IN RWAN_HANDLE RWanAfHandle
)
/*++
Routine Description:
This is called by an AF-specific module to signify completion
of our call to its CloseAfHandler routine.
We now call NDIS to close this AF.
Arguments:
RWanAfHandle - Our context for an NDIS AF Open
Return Value:
None
--*/
{
PRWAN_NDIS_AF pAf;
NDIS_HANDLE NdisAfHandle;
NDIS_STATUS Status;
pAf = (PRWAN_NDIS_AF)RWanAfHandle;
RWAN_STRUCT_ASSERT(pAf, naf);
RWAN_ACQUIRE_AF_LOCK(pAf);
pAf->AfSpAFContext = NULL;
NdisAfHandle = pAf->NdisAfHandle;
RWAN_RELEASE_AF_LOCK(pAf);
RWANDEBUGP(DL_LOUD, DC_BIND,
("AfSpCloseAfComplete: pAf x%x, will CloseAF, AfHandle x%x\n",
pAf, NdisAfHandle));
Status = NdisClCloseAddressFamily(NdisAfHandle);
if (Status != NDIS_STATUS_PENDING)
{
RWanNdisCloseAddressFamilyComplete(
Status,
(NDIS_HANDLE)pAf
);
}
}
RWAN_STATUS
RWanAfSpSendAdapterRequest(
IN RWAN_HANDLE RWanAfHandle,
IN RWAN_HANDLE AfSpReqContext,
IN NDIS_REQUEST_TYPE RequestType,
IN NDIS_OID Oid,
IN PVOID pBuffer,
IN ULONG BufferLength
)
/*++
Routine Description:
Send an NDIS Request down to the miniport on behalf of the media
specific module.
Arguments:
RWanAfHandle - Our context for an NDIS AF Open
AfSpReqContext - The caller's context for this request
RequestType - NDIS request type
Oid - The object being set or queried
pBuffer - Points to parameter value
BufferLength - Length of the above
Return Value:
RWAN_STATUS_PENDING if the request was sent to the miniport,
RWAN_STATUS_RESOURCES if we couldn't allocate resources for the
request.
--*/
{
PRWAN_NDIS_AF pAf;
NDIS_HANDLE NdisAdapterHandle;
PNDIS_REQUEST pNdisRequest;
NDIS_STATUS Status;
PRWAN_NDIS_REQ_CONTEXT pContext;
pAf = (PRWAN_NDIS_AF)RWanAfHandle;
RWAN_STRUCT_ASSERT(pAf, naf);
if ((RequestType != NdisRequestQueryInformation) &&
(RequestType != NdisRequestSetInformation))
{
return RWAN_STATUS_BAD_PARAMETER;
}
RWAN_ALLOC_MEM(pNdisRequest, NDIS_REQUEST, sizeof(NDIS_REQUEST) + sizeof(RWAN_NDIS_REQ_CONTEXT));
if (pNdisRequest == NULL)
{
return RWAN_STATUS_RESOURCES;
}
RWAN_ZERO_MEM(pNdisRequest, sizeof(NDIS_REQUEST));
pNdisRequest->RequestType = RequestType;
if (RequestType == NdisRequestQueryInformation)
{
pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = pBuffer;
pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = BufferLength;
pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BufferLength;
}
else
{
pNdisRequest->DATA.SET_INFORMATION.Oid = Oid;
pNdisRequest->DATA.SET_INFORMATION.InformationBuffer = pBuffer;
pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength = BufferLength;
pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
pNdisRequest->DATA.SET_INFORMATION.BytesNeeded = BufferLength;
}
//
// Fill in context about this request, so that we can complete
// it to the media-specific module later.
//
pContext = (PRWAN_NDIS_REQ_CONTEXT)((PUCHAR)pNdisRequest + sizeof(NDIS_REQUEST));
pContext->pAf = pAf;
pContext->AfSpReqContext = AfSpReqContext;
NdisRequest(&Status,
pAf->pAdapter->NdisAdapterHandle,
pNdisRequest);
if (Status != NDIS_STATUS_PENDING)
{
RWanNdisRequestComplete(
pAf->pAdapter,
pNdisRequest,
Status
);
}
return RWAN_STATUS_PENDING;
}
RWAN_STATUS
RWanAfSpSendAfRequest(
IN RWAN_HANDLE RWanAfHandle,
IN RWAN_HANDLE AfSpReqContext,
IN NDIS_REQUEST_TYPE RequestType,
IN NDIS_OID Oid,
IN PVOID pBuffer,
IN ULONG BufferLength
)
/*++
Routine Description:
Send an NDIS Request down to the call manager on behalf of the media
specific module.
Arguments:
RWanAfHandle - Our context for an NDIS AF Open
AfSpReqContext - The caller's context for this request
RequestType - NDIS request type
Oid - The object being set or queried
pBuffer - Points to parameter value
BufferLength - Length of the above
Return Value:
RWAN_STATUS_PENDING if the request was sent to the call manager,
RWAN_STATUS_RESOURCES if we couldn't allocate resources for the
request.
--*/
{
PRWAN_NDIS_AF pAf;
NDIS_HANDLE NdisAfHandle;
PNDIS_REQUEST pNdisRequest;
NDIS_STATUS Status;
PRWAN_NDIS_REQ_CONTEXT pContext;
pAf = (PRWAN_NDIS_AF)RWanAfHandle;
RWAN_STRUCT_ASSERT(pAf, naf);
if ((RequestType != NdisRequestQueryInformation) &&
(RequestType != NdisRequestSetInformation))
{
return RWAN_STATUS_BAD_PARAMETER;
}
RWAN_ALLOC_MEM(pNdisRequest, NDIS_REQUEST, sizeof(NDIS_REQUEST) + sizeof(RWAN_NDIS_REQ_CONTEXT));
if (pNdisRequest == NULL)
{
return RWAN_STATUS_RESOURCES;
}
RWAN_ZERO_MEM(pNdisRequest, sizeof(NDIS_REQUEST));
pNdisRequest->RequestType = RequestType;
if (RequestType == NdisRequestQueryInformation)
{
pNdisRequest->DATA.QUERY_INFORMATION.Oid = Oid;
pNdisRequest->DATA.QUERY_INFORMATION.InformationBuffer = pBuffer;
pNdisRequest->DATA.QUERY_INFORMATION.InformationBufferLength = BufferLength;
pNdisRequest->DATA.QUERY_INFORMATION.BytesWritten = 0;
pNdisRequest->DATA.QUERY_INFORMATION.BytesNeeded = BufferLength;
}
else
{
pNdisRequest->DATA.SET_INFORMATION.Oid = Oid;
pNdisRequest->DATA.SET_INFORMATION.InformationBuffer = pBuffer;
pNdisRequest->DATA.SET_INFORMATION.InformationBufferLength = BufferLength;
pNdisRequest->DATA.SET_INFORMATION.BytesRead = 0;
pNdisRequest->DATA.SET_INFORMATION.BytesNeeded = BufferLength;
}
//
// Fill in context about this request, so that we can complete
// it to the media-specific module later.
//
pContext = (PRWAN_NDIS_REQ_CONTEXT)((PUCHAR)pNdisRequest + sizeof(NDIS_REQUEST));
pContext->pAf = pAf;
pContext->AfSpReqContext = AfSpReqContext;
Status = NdisCoRequest(
pAf->pAdapter->NdisAdapterHandle,
pAf->NdisAfHandle,
NULL, // NdisVcHandle,
NULL, // NdisPartyHandlem
pNdisRequest
);
if (Status != NDIS_STATUS_PENDING)
{
RWanNdisCoRequestComplete(
Status,
(NDIS_HANDLE)pAf,
NULL,
NULL,
pNdisRequest
);
}
return RWAN_STATUS_PENDING;
}